summaryrefslogtreecommitdiff
path: root/src/mscorlib
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib')
-rw-r--r--src/mscorlib/.gitmirrorall1
-rw-r--r--src/mscorlib/Common/PinnableBufferCache.cs666
-rw-r--r--src/mscorlib/Common/Preprocessed/AssemblyRefs.g.cs1082
-rw-r--r--src/mscorlib/GenerateCompilerResponseFile.targets22
-rw-r--r--src/mscorlib/GenerateSplitStringResources.targets42
-rw-r--r--src/mscorlib/System.Private.CoreLib.csproj226
-rw-r--r--src/mscorlib/System.Private.CoreLib.sln52
-rw-r--r--src/mscorlib/Tools/BclRewriter/BclRewriter.targets35
-rw-r--r--src/mscorlib/Tools/PostProcessingTools.targets28
-rw-r--r--src/mscorlib/Tools/Signing/mscorlib.snkbin0 -> 160 bytes
-rw-r--r--src/mscorlib/Tools/Versioning/GenerateVersionInfo.targets114
-rw-r--r--src/mscorlib/Tools/Versioning/NativeVersion.rc45
-rw-r--r--src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs11
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs33
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Casing.cs26
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs79
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs37
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs17
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs31
-rw-r--r--src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Utils.cs52
-rw-r--r--src/mscorlib/corefx/SR.cs247
-rw-r--r--src/mscorlib/corefx/System/Globalization/Calendar.cs854
-rw-r--r--src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs341
-rw-r--r--src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs469
-rw-r--r--src/mscorlib/corefx/System/Globalization/CalendarData.cs381
-rw-r--r--src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs19
-rw-r--r--src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs413
-rw-r--r--src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs339
-rw-r--r--src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs1222
-rw-r--r--src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs399
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs315
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs395
-rw-r--r--src/mscorlib/corefx/System/Globalization/CompareInfo.cs925
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs304
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs561
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureData.cs2174
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs31
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs53
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureInfo.cs1144
-rw-r--r--src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs104
-rw-r--r--src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs2958
-rw-r--r--src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs742
-rw-r--r--src/mscorlib/corefx/System/Globalization/DayLightTime.cs56
-rw-r--r--src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs719
-rw-r--r--src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs662
-rw-r--r--src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs668
-rw-r--r--src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs21
-rw-r--r--src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs1123
-rw-r--r--src/mscorlib/corefx/System/Globalization/HebrewNumber.cs465
-rw-r--r--src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs15
-rw-r--r--src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs16
-rw-r--r--src/mscorlib/corefx/System/Globalization/HijriCalendar.cs675
-rw-r--r--src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs50
-rw-r--r--src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs91
-rw-r--r--src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs62
-rw-r--r--src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs413
-rw-r--r--src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs311
-rw-r--r--src/mscorlib/corefx/System/Globalization/JulianCalendar.cs452
-rw-r--r--src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs264
-rw-r--r--src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs1329
-rw-r--r--src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs819
-rw-r--r--src/mscorlib/corefx/System/Globalization/PersianCalendar.cs613
-rw-r--r--src/mscorlib/corefx/System/Globalization/RegionInfo.cs324
-rw-r--r--src/mscorlib/corefx/System/Globalization/STUBS.cs180
-rw-r--r--src/mscorlib/corefx/System/Globalization/StringInfo.cs322
-rw-r--r--src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs282
-rw-r--r--src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs330
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs154
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs127
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs121
-rw-r--r--src/mscorlib/corefx/System/Globalization/TextInfo.cs457
-rw-r--r--src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs233
-rw-r--r--src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs13
-rw-r--r--src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs862
-rw-r--r--src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs70
-rw-r--r--src/mscorlib/facade/TypeForwards.cs37
-rw-r--r--src/mscorlib/facade/mscorlib.csproj102
-rw-r--r--src/mscorlib/facade/project.json14
-rw-r--r--src/mscorlib/model.xml12084
-rw-r--r--src/mscorlib/mscorlib.shared.sources.props1195
-rw-r--r--src/mscorlib/ref/mscorlib.cs13673
-rw-r--r--src/mscorlib/ref/mscorlib.csproj86
-rw-r--r--src/mscorlib/ref/mscorlib.manual.cs785
-rw-r--r--src/mscorlib/src/GlobalSuppressions.cs105
-rw-r--r--src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs21
-rw-r--r--src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs134
-rw-r--r--src/mscorlib/src/Microsoft/Win32/Registry.cs174
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryKey.cs2166
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs25
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs20
-rw-r--r--src/mscorlib/src/Microsoft/Win32/RegistryView.cs19
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs43
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs43
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs35
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs29
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs29
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs41
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs50
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs47
-rw-r--r--src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs112
-rw-r--r--src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs282
-rw-r--r--src/mscorlib/src/Microsoft/Win32/Win32Native.cs2455
-rw-r--r--src/mscorlib/src/System.Private.CoreLib.txt3495
-rw-r--r--src/mscorlib/src/System/AccessViolationException.cs51
-rw-r--r--src/mscorlib/src/System/Action.cs78
-rw-r--r--src/mscorlib/src/System/Activator.cs688
-rw-r--r--src/mscorlib/src/System/AggregateException.cs497
-rw-r--r--src/mscorlib/src/System/AppContext/AppContext.cs189
-rw-r--r--src/mscorlib/src/System/AppContext/AppContextDefaultValues.CoreClrOverrides.cs21
-rw-r--r--src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.Central.cs33
-rw-r--r--src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs71
-rw-r--r--src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs164
-rw-r--r--src/mscorlib/src/System/AppContext/AppContextSwitches.cs110
-rw-r--r--src/mscorlib/src/System/AppDomain.cs4681
-rw-r--r--src/mscorlib/src/System/AppDomainAttributes.cs48
-rw-r--r--src/mscorlib/src/System/AppDomainManager.cs220
-rw-r--r--src/mscorlib/src/System/AppDomainSetup.cs1444
-rw-r--r--src/mscorlib/src/System/AppDomainUnloadedException.cs43
-rw-r--r--src/mscorlib/src/System/ApplicationException.cs56
-rw-r--r--src/mscorlib/src/System/ApplicationId.cs141
-rw-r--r--src/mscorlib/src/System/ArgIterator.cs148
-rw-r--r--src/mscorlib/src/System/ArgumentException.cs95
-rw-r--r--src/mscorlib/src/System/ArgumentNullException.cs55
-rw-r--r--src/mscorlib/src/System/ArgumentOutOfRangeException.cs106
-rw-r--r--src/mscorlib/src/System/ArithmeticException.cs52
-rw-r--r--src/mscorlib/src/System/Array.cs2858
-rw-r--r--src/mscorlib/src/System/ArraySegment.cs342
-rw-r--r--src/mscorlib/src/System/ArrayTypeMismatchException.cs52
-rw-r--r--src/mscorlib/src/System/AsyncCallback.cs17
-rw-r--r--src/mscorlib/src/System/Attribute.cs975
-rw-r--r--src/mscorlib/src/System/AttributeTargets.cs40
-rw-r--r--src/mscorlib/src/System/AttributeUsageAttribute.cs57
-rw-r--r--src/mscorlib/src/System/BCLDebug.cs442
-rw-r--r--src/mscorlib/src/System/BadImageFormatException.cs158
-rw-r--r--src/mscorlib/src/System/BitConverter.cs451
-rw-r--r--src/mscorlib/src/System/Boolean.cs305
-rw-r--r--src/mscorlib/src/System/Buffer.cs645
-rw-r--r--src/mscorlib/src/System/Byte.cs253
-rw-r--r--src/mscorlib/src/System/CLRConfig.cs36
-rw-r--r--src/mscorlib/src/System/CLSCompliantAttribute.cs34
-rw-r--r--src/mscorlib/src/System/CannotUnloadAppDomainException.cs49
-rw-r--r--src/mscorlib/src/System/CfgParser.cs574
-rw-r--r--src/mscorlib/src/System/Char.cs1001
-rw-r--r--src/mscorlib/src/System/CharEnumerator.cs75
-rw-r--r--src/mscorlib/src/System/Collections/ArrayList.cs2635
-rw-r--r--src/mscorlib/src/System/Collections/BitArray.cs524
-rw-r--r--src/mscorlib/src/System/Collections/CollectionBase.cs215
-rw-r--r--src/mscorlib/src/System/Collections/Comparer.cs98
-rw-r--r--src/mscorlib/src/System/Collections/CompatibleComparer.cs67
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs2095
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs960
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs840
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs116
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs281
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs102
-rw-r--r--src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs1733
-rw-r--r--src/mscorlib/src/System/Collections/DictionaryEntry.cs55
-rw-r--r--src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs194
-rw-r--r--src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs1558
-rw-r--r--src/mscorlib/src/System/Collections/Generic/Comparer.cs325
-rw-r--r--src/mscorlib/src/System/Collections/Generic/DebugView.cs129
-rw-r--r--src/mscorlib/src/System/Collections/Generic/Dictionary.cs1187
-rw-r--r--src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs621
-rw-r--r--src/mscorlib/src/System/Collections/Generic/ICollection.cs52
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IComparer.cs30
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IDictionary.cs58
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IEnumerable.cs38
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IEnumerator.cs35
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IEqualityComparer.cs19
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IList.cs54
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IReadOnlyCollection.cs34
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IReadOnlyDictionary.cs29
-rw-r--r--src/mscorlib/src/System/Collections/Generic/IReadOnlyList.cs34
-rw-r--r--src/mscorlib/src/System/Collections/Generic/KeyNotFoundException.cs45
-rw-r--r--src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs56
-rw-r--r--src/mscorlib/src/System/Collections/Generic/List.cs1120
-rw-r--r--src/mscorlib/src/System/Collections/Hashtable.cs1847
-rw-r--r--src/mscorlib/src/System/Collections/ICollection.cs81
-rw-r--r--src/mscorlib/src/System/Collections/IComparer.cs32
-rw-r--r--src/mscorlib/src/System/Collections/IDictionary.cs69
-rw-r--r--src/mscorlib/src/System/Collections/IDictionaryEnumerator.cs79
-rw-r--r--src/mscorlib/src/System/Collections/IEnumerable.cs34
-rw-r--r--src/mscorlib/src/System/Collections/IEnumerator.cs53
-rw-r--r--src/mscorlib/src/System/Collections/IEqualityComparer.cs27
-rw-r--r--src/mscorlib/src/System/Collections/IHashCodeProvider.cs30
-rw-r--r--src/mscorlib/src/System/Collections/IList.cs71
-rw-r--r--src/mscorlib/src/System/Collections/IStructuralComparable.cs11
-rw-r--r--src/mscorlib/src/System/Collections/IStructuralEquatable.cs10
-rw-r--r--src/mscorlib/src/System/Collections/KeyValuePairs.cs40
-rw-r--r--src/mscorlib/src/System/Collections/ListDictionaryInternal.cs429
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/Collection.cs328
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs245
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs232
-rw-r--r--src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs625
-rw-r--r--src/mscorlib/src/System/Collections/SortedList.cs1011
-rw-r--r--src/mscorlib/src/System/Collections/Stack.cs380
-rw-r--r--src/mscorlib/src/System/Collections/StructuralComparisons.cs89
-rw-r--r--src/mscorlib/src/System/CompatibilitySwitches.cs130
-rw-r--r--src/mscorlib/src/System/Configuration/Assemblies/AssemblyHash.cs74
-rw-r--r--src/mscorlib/src/System/Configuration/Assemblies/AssemblyHashAlgorithm.cs32
-rw-r--r--src/mscorlib/src/System/Configuration/Assemblies/AssemblyVersionCompatibility.cs24
-rw-r--r--src/mscorlib/src/System/ContextBoundObject.cs24
-rw-r--r--src/mscorlib/src/System/ContextMarshalException.cs45
-rw-r--r--src/mscorlib/src/System/ContextStaticAttribute.cs32
-rw-r--r--src/mscorlib/src/System/Convert.cs2718
-rw-r--r--src/mscorlib/src/System/Currency.cs61
-rw-r--r--src/mscorlib/src/System/CurrentTimeZone.cs310
-rw-r--r--src/mscorlib/src/System/DBNull.cs122
-rw-r--r--src/mscorlib/src/System/DataMisalignedException.cs45
-rw-r--r--src/mscorlib/src/System/DateTime.cs1379
-rw-r--r--src/mscorlib/src/System/DateTimeKind.cs19
-rw-r--r--src/mscorlib/src/System/DateTimeOffset.cs831
-rw-r--r--src/mscorlib/src/System/DayOfWeek.cs26
-rw-r--r--src/mscorlib/src/System/Decimal.cs1244
-rw-r--r--src/mscorlib/src/System/DefaultBinder.cs1168
-rw-r--r--src/mscorlib/src/System/Delegate.cs754
-rw-r--r--src/mscorlib/src/System/DelegateSerializationHolder.cs299
-rw-r--r--src/mscorlib/src/System/Diagnostics/Assert.cs114
-rw-r--r--src/mscorlib/src/System/Diagnostics/AssertFilter.cs46
-rw-r--r--src/mscorlib/src/System/Diagnostics/AssertFilters.cs24
-rw-r--r--src/mscorlib/src/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs76
-rw-r--r--src/mscorlib/src/System/Diagnostics/ConditionalAttribute.cs26
-rw-r--r--src/mscorlib/src/System/Diagnostics/Contracts/Contracts.cs1017
-rw-r--r--src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs521
-rw-r--r--src/mscorlib/src/System/Diagnostics/Debugger.cs195
-rw-r--r--src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs378
-rw-r--r--src/mscorlib/src/System/Diagnostics/EditAndContinueHelper.cs27
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs670
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventActivityOptions.cs39
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs436
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventDescriptor.cs193
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs1220
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs6962
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventSourceException.cs53
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs224
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/FrameworkEventSource.cs620
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/StubEnvironment.cs373
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ArrayTypeInfo.cs63
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSet.cs127
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSetItem.cs25
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs319
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EmptyStruct.cs17
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumHelper.cs30
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumerableTypeInfo.cs64
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventDataAttribute.cs146
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldAttribute.cs76
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldFormat.cs130
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventIgnoreAttribute.cs25
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs154
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs321
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceOptions.cs130
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs231
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/InvokeTypeInfo.cs96
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/NameInfo.cs79
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAnalysis.cs39
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs251
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleEventTypes.cs39
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs296
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs727
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs105
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataType.cs349
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs902
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTraits.cs28
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs262
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs370
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs209
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TypeAnalysis.cs103
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/Winmeta.cs196
-rw-r--r--src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs164
-rw-r--r--src/mscorlib/src/System/Diagnostics/ICustomDebuggerNotification.cs21
-rw-r--r--src/mscorlib/src/System/Diagnostics/LogSwitch.cs142
-rw-r--r--src/mscorlib/src/System/Diagnostics/LoggingLevels.cs45
-rw-r--r--src/mscorlib/src/System/Diagnostics/Stackframe.cs348
-rw-r--r--src/mscorlib/src/System/Diagnostics/Stacktrace.cs770
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymBinder.cs42
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocument.cs48
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocumentWriter.cs31
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymMethod.cs86
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymNamespace.cs30
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymReader.cs68
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymScope.cs47
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymVariable.cs41
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs218
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs52
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/SymDocumentType.cs24
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageType.cs42
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageVendor.cs23
-rw-r--r--src/mscorlib/src/System/Diagnostics/SymbolStore/Token.cs51
-rw-r--r--src/mscorlib/src/System/Diagnostics/log.cs251
-rw-r--r--src/mscorlib/src/System/DivideByZeroException.cs39
-rw-r--r--src/mscorlib/src/System/DllNotFoundException.cs40
-rw-r--r--src/mscorlib/src/System/Double.cs367
-rw-r--r--src/mscorlib/src/System/DuplicateWaitObjectException.cs63
-rw-r--r--src/mscorlib/src/System/Empty.cs37
-rw-r--r--src/mscorlib/src/System/EntryPointNotFoundException.cs42
-rw-r--r--src/mscorlib/src/System/Enum.cs1265
-rw-r--r--src/mscorlib/src/System/Environment.cs1768
-rw-r--r--src/mscorlib/src/System/EventArgs.cs18
-rw-r--r--src/mscorlib/src/System/EventHandler.cs13
-rw-r--r--src/mscorlib/src/System/Exception.cs1006
-rw-r--r--src/mscorlib/src/System/ExecutionEngineException.cs44
-rw-r--r--src/mscorlib/src/System/FieldAccessException.cs39
-rw-r--r--src/mscorlib/src/System/FlagsAttribute.cs23
-rw-r--r--src/mscorlib/src/System/FormatException.cs39
-rw-r--r--src/mscorlib/src/System/FormattableString.cs81
-rw-r--r--src/mscorlib/src/System/GC.cs641
-rw-r--r--src/mscorlib/src/System/Globalization/BidiCategory.cs39
-rw-r--r--src/mscorlib/src/System/Globalization/Calendar.cs861
-rw-r--r--src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs20
-rw-r--r--src/mscorlib/src/System/Globalization/CalendarData.cs455
-rw-r--r--src/mscorlib/src/System/Globalization/CalendarWeekRule.cs20
-rw-r--r--src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs413
-rw-r--r--src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs522
-rw-r--r--src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs401
-rw-r--r--src/mscorlib/src/System/Globalization/CompareInfo.cs1359
-rw-r--r--src/mscorlib/src/System/Globalization/CultureData.cs3354
-rw-r--r--src/mscorlib/src/System/Globalization/CultureInfo.cs2023
-rw-r--r--src/mscorlib/src/System/Globalization/CultureNotFoundException.cs131
-rw-r--r--src/mscorlib/src/System/Globalization/CultureTypes.cs31
-rw-r--r--src/mscorlib/src/System/Globalization/DateTimeFormat.cs1054
-rw-r--r--src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs2936
-rw-r--r--src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs750
-rw-r--r--src/mscorlib/src/System/Globalization/DateTimeParse.cs5069
-rw-r--r--src/mscorlib/src/System/Globalization/DateTimeStyles.cs50
-rw-r--r--src/mscorlib/src/System/Globalization/DaylightTime.cs49
-rw-r--r--src/mscorlib/src/System/Globalization/DigitShapes.cs22
-rw-r--r--src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs644
-rw-r--r--src/mscorlib/src/System/Globalization/EncodingDataItem.Unix.cs69
-rw-r--r--src/mscorlib/src/System/Globalization/EncodingDataItem.cs115
-rw-r--r--src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs178
-rw-r--r--src/mscorlib/src/System/Globalization/EncodingTable.cs250
-rw-r--r--src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs63
-rw-r--r--src/mscorlib/src/System/Globalization/GregorianCalendar.cs627
-rw-r--r--src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs633
-rw-r--r--src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs18
-rw-r--r--src/mscorlib/src/System/Globalization/HebrewCalendar.cs1084
-rw-r--r--src/mscorlib/src/System/Globalization/HebrewNumber.cs402
-rw-r--r--src/mscorlib/src/System/Globalization/HijriCalendar.cs723
-rw-r--r--src/mscorlib/src/System/Globalization/IdnMapping.cs1189
-rw-r--r--src/mscorlib/src/System/Globalization/JapaneseCalendar.cs594
-rw-r--r--src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs293
-rw-r--r--src/mscorlib/src/System/Globalization/JulianCalendar.cs441
-rw-r--r--src/mscorlib/src/System/Globalization/KoreanCalendar.cs265
-rw-r--r--src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs1334
-rw-r--r--src/mscorlib/src/System/Globalization/NumberFormatInfo.cs842
-rw-r--r--src/mscorlib/src/System/Globalization/NumberStyles.cs67
-rw-r--r--src/mscorlib/src/System/Globalization/PersianCalendar.cs577
-rw-r--r--src/mscorlib/src/System/Globalization/RegionInfo.cs629
-rw-r--r--src/mscorlib/src/System/Globalization/SortKey.cs208
-rw-r--r--src/mscorlib/src/System/Globalization/SortVersion.cs102
-rw-r--r--src/mscorlib/src/System/Globalization/StringInfo.cs361
-rw-r--r--src/mscorlib/src/System/Globalization/Tables/charinfo.nlpbin0 -> 36992 bytes
-rw-r--r--src/mscorlib/src/System/Globalization/TaiwanCalendar.cs262
-rw-r--r--src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs330
-rw-r--r--src/mscorlib/src/System/Globalization/TextElementEnumerator.cs155
-rw-r--r--src/mscorlib/src/System/Globalization/TextInfo.cs1004
-rw-r--r--src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs225
-rw-r--r--src/mscorlib/src/System/Globalization/TimeSpanFormat.cs474
-rw-r--r--src/mscorlib/src/System/Globalization/TimeSpanParse.cs1557
-rw-r--r--src/mscorlib/src/System/Globalization/TimeSpanStyles.cs12
-rw-r--r--src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs849
-rw-r--r--src/mscorlib/src/System/Globalization/UnicodeCategory.cs79
-rw-r--r--src/mscorlib/src/System/Guid.cs1299
-rw-r--r--src/mscorlib/src/System/IAppDomain.cs268
-rw-r--r--src/mscorlib/src/System/IAppDomainPauseManager.cs100
-rw-r--r--src/mscorlib/src/System/IAppDomainSetup.cs84
-rw-r--r--src/mscorlib/src/System/IAsyncResult.cs32
-rw-r--r--src/mscorlib/src/System/ICloneable.cs29
-rw-r--r--src/mscorlib/src/System/IComparable.cs39
-rw-r--r--src/mscorlib/src/System/IConvertible.cs67
-rw-r--r--src/mscorlib/src/System/ICustomFormatter.cs25
-rw-r--r--src/mscorlib/src/System/IDisposable.cs58
-rw-r--r--src/mscorlib/src/System/IEquatable.cs14
-rw-r--r--src/mscorlib/src/System/IFormatProvider.cs23
-rw-r--r--src/mscorlib/src/System/IFormattable.cs16
-rw-r--r--src/mscorlib/src/System/IO/BinaryReader.cs601
-rw-r--r--src/mscorlib/src/System/IO/BinaryWriter.cs427
-rw-r--r--src/mscorlib/src/System/IO/BufferedStream.cs1320
-rw-r--r--src/mscorlib/src/System/IO/Directory.cs1389
-rw-r--r--src/mscorlib/src/System/IO/DirectoryInfo.cs672
-rw-r--r--src/mscorlib/src/System/IO/DirectoryNotFoundException.cs46
-rw-r--r--src/mscorlib/src/System/IO/DriveInfo.cs281
-rw-r--r--src/mscorlib/src/System/IO/DriveNotFoundException.cs40
-rw-r--r--src/mscorlib/src/System/IO/EndOfStreamException.cs43
-rw-r--r--src/mscorlib/src/System/IO/File.cs1255
-rw-r--r--src/mscorlib/src/System/IO/FileAccess.cs42
-rw-r--r--src/mscorlib/src/System/IO/FileAttributes.cs51
-rw-r--r--src/mscorlib/src/System/IO/FileInfo.cs431
-rw-r--r--src/mscorlib/src/System/IO/FileLoadException.cs191
-rw-r--r--src/mscorlib/src/System/IO/FileMode.cs54
-rw-r--r--src/mscorlib/src/System/IO/FileNotFoundException.cs170
-rw-r--r--src/mscorlib/src/System/IO/FileOptions.cs47
-rw-r--r--src/mscorlib/src/System/IO/FileSecurityState.cs133
-rw-r--r--src/mscorlib/src/System/IO/FileSecurityStateAccess.cs32
-rw-r--r--src/mscorlib/src/System/IO/FileShare.cs60
-rw-r--r--src/mscorlib/src/System/IO/FileStream.cs2695
-rw-r--r--src/mscorlib/src/System/IO/FileSystemEnumerable.cs852
-rw-r--r--src/mscorlib/src/System/IO/FileSystemInfo.cs361
-rw-r--r--src/mscorlib/src/System/IO/IOException.cs68
-rw-r--r--src/mscorlib/src/System/IO/LongPathHelper.cs521
-rw-r--r--src/mscorlib/src/System/IO/MemoryStream.cs646
-rw-r--r--src/mscorlib/src/System/IO/Path.cs1435
-rw-r--r--src/mscorlib/src/System/IO/PathHelper.cs448
-rw-r--r--src/mscorlib/src/System/IO/PathInternal.cs806
-rw-r--r--src/mscorlib/src/System/IO/PathTooLongException.cs44
-rw-r--r--src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs73
-rw-r--r--src/mscorlib/src/System/IO/ReadLinesIterator.cs102
-rw-r--r--src/mscorlib/src/System/IO/SearchOption.cs36
-rw-r--r--src/mscorlib/src/System/IO/SeekOrigin.cs32
-rw-r--r--src/mscorlib/src/System/IO/Stream.cs1304
-rw-r--r--src/mscorlib/src/System/IO/StreamReader.cs1293
-rw-r--r--src/mscorlib/src/System/IO/StreamWriter.cs866
-rw-r--r--src/mscorlib/src/System/IO/StringReader.cs187
-rw-r--r--src/mscorlib/src/System/IO/StringWriter.cs196
-rw-r--r--src/mscorlib/src/System/IO/TextReader.cs413
-rw-r--r--src/mscorlib/src/System/IO/TextWriter.cs915
-rw-r--r--src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs1176
-rw-r--r--src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs712
-rw-r--r--src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs197
-rw-r--r--src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs76
-rw-r--r--src/mscorlib/src/System/IO/__Error.cs232
-rw-r--r--src/mscorlib/src/System/IO/__HResults.cs28
-rw-r--r--src/mscorlib/src/System/IObservable.cs24
-rw-r--r--src/mscorlib/src/System/IObserver.cs27
-rw-r--r--src/mscorlib/src/System/IProgress.cs26
-rw-r--r--src/mscorlib/src/System/IServiceObjectProvider.cs16
-rw-r--r--src/mscorlib/src/System/IndexOutOfRangeException.cs40
-rw-r--r--src/mscorlib/src/System/InsufficientExecutionStackException.cs47
-rw-r--r--src/mscorlib/src/System/InsufficientMemoryException.cs45
-rw-r--r--src/mscorlib/src/System/Int16.cs267
-rw-r--r--src/mscorlib/src/System/Int32.cs239
-rw-r--r--src/mscorlib/src/System/Int64.cs218
-rw-r--r--src/mscorlib/src/System/IntPtr.cs303
-rw-r--r--src/mscorlib/src/System/Internal.cs377
-rw-r--r--src/mscorlib/src/System/InvalidCastException.cs45
-rw-r--r--src/mscorlib/src/System/InvalidOperationException.cs41
-rw-r--r--src/mscorlib/src/System/InvalidProgramException.cs41
-rw-r--r--src/mscorlib/src/System/InvalidTimeZoneException.cs26
-rw-r--r--src/mscorlib/src/System/Lazy.cs517
-rw-r--r--src/mscorlib/src/System/LowLevelConsole.cs50
-rw-r--r--src/mscorlib/src/System/MarshalByRefObject.cs262
-rw-r--r--src/mscorlib/src/System/Math.cs594
-rw-r--r--src/mscorlib/src/System/MemberAccessException.cs48
-rw-r--r--src/mscorlib/src/System/MethodAccessException.cs39
-rw-r--r--src/mscorlib/src/System/MidpointRounding.cs13
-rw-r--r--src/mscorlib/src/System/MissingFieldException.cs73
-rw-r--r--src/mscorlib/src/System/MissingMemberException.cs105
-rw-r--r--src/mscorlib/src/System/MissingMethodException.cs75
-rw-r--r--src/mscorlib/src/System/MulticastDelegate.cs754
-rw-r--r--src/mscorlib/src/System/MulticastNotSupportedException.cs37
-rw-r--r--src/mscorlib/src/System/NonSerializedAttribute.cs36
-rw-r--r--src/mscorlib/src/System/NotFiniteNumberException.cs70
-rw-r--r--src/mscorlib/src/System/NotImplementedException.cs40
-rw-r--r--src/mscorlib/src/System/NotSupportedException.cs41
-rw-r--r--src/mscorlib/src/System/NullReferenceException.cs40
-rw-r--r--src/mscorlib/src/System/Nullable.cs158
-rw-r--r--src/mscorlib/src/System/Number.cs1215
-rw-r--r--src/mscorlib/src/System/Object.cs255
-rw-r--r--src/mscorlib/src/System/ObjectDisposedException.cs74
-rw-r--r--src/mscorlib/src/System/ObsoleteAttribute.cs60
-rw-r--r--src/mscorlib/src/System/OleAutBinder.cs113
-rw-r--r--src/mscorlib/src/System/OperatingSystem.cs157
-rw-r--r--src/mscorlib/src/System/OperationCanceledException.cs70
-rw-r--r--src/mscorlib/src/System/OutOfMemoryException.cs40
-rw-r--r--src/mscorlib/src/System/OverflowException.cs42
-rw-r--r--src/mscorlib/src/System/ParamArrayAttribute.cs22
-rw-r--r--src/mscorlib/src/System/ParamsArray.cs81
-rw-r--r--src/mscorlib/src/System/ParseNumbers.cs74
-rw-r--r--src/mscorlib/src/System/PlatformID.cs28
-rw-r--r--src/mscorlib/src/System/PlatformNotSupportedException.cs42
-rw-r--r--src/mscorlib/src/System/Progress.cs119
-rw-r--r--src/mscorlib/src/System/Random.cs214
-rw-r--r--src/mscorlib/src/System/RankException.cs42
-rw-r--r--src/mscorlib/src/System/Reflection/AmbiguousMatchException.cs42
-rw-r--r--src/mscorlib/src/System/Reflection/Assembly.cs3013
-rw-r--r--src/mscorlib/src/System/Reflection/AssemblyAttributes.cs406
-rw-r--r--src/mscorlib/src/System/Reflection/AssemblyName.cs539
-rw-r--r--src/mscorlib/src/System/Reflection/AssemblyNameFlags.cs56
-rw-r--r--src/mscorlib/src/System/Reflection/AssemblyNameProxy.cs28
-rw-r--r--src/mscorlib/src/System/Reflection/Associates.cs212
-rw-r--r--src/mscorlib/src/System/Reflection/Binder.cs51
-rw-r--r--src/mscorlib/src/System/Reflection/BindingFlags.cs64
-rw-r--r--src/mscorlib/src/System/Reflection/CallingConventions.cs29
-rw-r--r--src/mscorlib/src/System/Reflection/ComInterfaces.cs673
-rw-r--r--src/mscorlib/src/System/Reflection/ConstructorInfo.cs781
-rw-r--r--src/mscorlib/src/System/Reflection/CustomAttribute.cs2527
-rw-r--r--src/mscorlib/src/System/Reflection/CustomAttributeExtensions.cs174
-rw-r--r--src/mscorlib/src/System/Reflection/CustomAttributeFormatException.cs38
-rw-r--r--src/mscorlib/src/System/Reflection/DefaultMemberAttribute.cs40
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs208
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs2245
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs29
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs583
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs288
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs335
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs582
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs1329
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs1039
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs448
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs174
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/EventToken.cs69
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs281
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/FieldToken.cs86
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/FlowControl.cs37
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs248
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs2012
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs828
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/Label.cs74
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs151
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs1610
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs142
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/MethodToken.cs65
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs2422
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs104
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/OpCodes.cs2552
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/Opcode.cs312
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs35
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/OperandType.cs47
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/PEFileKinds.cs17
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs172
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/ParameterToken.cs73
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs306
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/PropertyToken.cs70
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs1019
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/SignatureToken.cs68
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/StackBehaviour.cs54
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/StringToken.cs79
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs184
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/SymbolType.cs606
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs2620
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs276
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/TypeToken.cs74
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs184
-rw-r--r--src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs331
-rw-r--r--src/mscorlib/src/System/Reflection/EventAttributes.cs30
-rw-r--r--src/mscorlib/src/System/Reflection/EventInfo.cs443
-rw-r--r--src/mscorlib/src/System/Reflection/FieldAttributes.cs43
-rw-r--r--src/mscorlib/src/System/Reflection/FieldInfo.cs955
-rw-r--r--src/mscorlib/src/System/Reflection/GenericParameterAttributes.cs22
-rw-r--r--src/mscorlib/src/System/Reflection/ICustomAttributeProvider.cs34
-rw-r--r--src/mscorlib/src/System/Reflection/IReflect.cs117
-rw-r--r--src/mscorlib/src/System/Reflection/IReflectableType.cs20
-rw-r--r--src/mscorlib/src/System/Reflection/InterfaceMapping.cs27
-rw-r--r--src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs35
-rw-r--r--src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs44
-rw-r--r--src/mscorlib/src/System/Reflection/LoaderAllocator.cs86
-rw-r--r--src/mscorlib/src/System/Reflection/ManifestResourceInfo.cs67
-rw-r--r--src/mscorlib/src/System/Reflection/MdConstant.cs169
-rw-r--r--src/mscorlib/src/System/Reflection/MdImport.cs736
-rw-r--r--src/mscorlib/src/System/Reflection/MemberFilter.cs19
-rw-r--r--src/mscorlib/src/System/Reflection/MemberInfo.cs148
-rw-r--r--src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs287
-rw-r--r--src/mscorlib/src/System/Reflection/MemberTypes.cs34
-rw-r--r--src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs47
-rw-r--r--src/mscorlib/src/System/Reflection/MethodAttributes.cs56
-rw-r--r--src/mscorlib/src/System/Reflection/MethodBase.cs402
-rw-r--r--src/mscorlib/src/System/Reflection/MethodBody.cs169
-rw-r--r--src/mscorlib/src/System/Reflection/MethodImplAttributes.cs45
-rw-r--r--src/mscorlib/src/System/Reflection/MethodInfo.cs1061
-rw-r--r--src/mscorlib/src/System/Reflection/Missing.cs38
-rw-r--r--src/mscorlib/src/System/Reflection/Module.cs1230
-rw-r--r--src/mscorlib/src/System/Reflection/ObfuscateAssemblyAttribute.cs46
-rw-r--r--src/mscorlib/src/System/Reflection/ObfuscationAttribute.cs75
-rw-r--r--src/mscorlib/src/System/Reflection/ParameterAttributes.cs36
-rw-r--r--src/mscorlib/src/System/Reflection/ParameterInfo.cs795
-rw-r--r--src/mscorlib/src/System/Reflection/ParameterModifier.cs46
-rw-r--r--src/mscorlib/src/System/Reflection/Pointer.cs82
-rw-r--r--src/mscorlib/src/System/Reflection/PropertyAttributes.cs33
-rw-r--r--src/mscorlib/src/System/Reflection/PropertyInfo.cs657
-rw-r--r--src/mscorlib/src/System/Reflection/ReflectionContext.cs36
-rw-r--r--src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs80
-rw-r--r--src/mscorlib/src/System/Reflection/ResourceAttributes.cs24
-rw-r--r--src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs88
-rw-r--r--src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs194
-rw-r--r--src/mscorlib/src/System/Reflection/TargetException.cs42
-rw-r--r--src/mscorlib/src/System/Reflection/TargetInvocationException.cs51
-rw-r--r--src/mscorlib/src/System/Reflection/TargetParameterCountException.cs45
-rw-r--r--src/mscorlib/src/System/Reflection/TypeAttributes.cs66
-rw-r--r--src/mscorlib/src/System/Reflection/TypeDelegator.cs263
-rw-r--r--src/mscorlib/src/System/Reflection/TypeFilter.cs19
-rw-r--r--src/mscorlib/src/System/Reflection/TypeInfo.cs195
-rw-r--r--src/mscorlib/src/System/Reflection/__Filters.cs67
-rw-r--r--src/mscorlib/src/System/ResId.cs93
-rw-r--r--src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs175
-rw-r--r--src/mscorlib/src/System/Resources/IResourceGroveler.cs32
-rw-r--r--src/mscorlib/src/System/Resources/IResourceReader.cs31
-rw-r--r--src/mscorlib/src/System/Resources/IResourceWriter.cs45
-rw-r--r--src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs86
-rw-r--r--src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs677
-rw-r--r--src/mscorlib/src/System/Resources/MissingManifestResourceException.cs42
-rw-r--r--src/mscorlib/src/System/Resources/MissingSatelliteAssemblyException.cs56
-rw-r--r--src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs65
-rw-r--r--src/mscorlib/src/System/Resources/ResourceFallbackManager.cs278
-rw-r--r--src/mscorlib/src/System/Resources/ResourceManager.cs1679
-rw-r--r--src/mscorlib/src/System/Resources/ResourceReader.cs1424
-rw-r--r--src/mscorlib/src/System/Resources/ResourceSet.cs332
-rw-r--r--src/mscorlib/src/System/Resources/ResourceTypeCode.cs57
-rw-r--r--src/mscorlib/src/System/Resources/RuntimeResourceSet.cs435
-rw-r--r--src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs39
-rw-r--r--src/mscorlib/src/System/Resources/UltimateResourceFallbackLocation.cs29
-rw-r--r--src/mscorlib/src/System/Resources/__FastResourceComparer.cs141
-rw-r--r--src/mscorlib/src/System/Resources/__HResults.cs23
-rw-r--r--src/mscorlib/src/System/RtType.cs5862
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs43
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs94
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs1187
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs16
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs795
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs48
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs98
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs19
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs13
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs14
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs43
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs58
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs14
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs82
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs26
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs58
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs22
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs22
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs12
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs16
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs11
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs13
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs77
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs16
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs26
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs48
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs248
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs14
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs20
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs19
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs531
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs35
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs47
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs14
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs168
-rw-r--r--src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs224
-rw-r--r--src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs135
-rw-r--r--src/mscorlib/src/System/Runtime/GcSettings.cs101
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs76
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs1138
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/COMException.cs90
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs22
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs24
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs202
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs92
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs246
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs286
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs19
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs45
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs26
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs34
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs28
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs34
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs61
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs34
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs79
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs34
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs55
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs49
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs335
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs62
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs68
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs42
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs275
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs44
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs54
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs80
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs219
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs330
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs50
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs17
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs31
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/IException.cs84
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs56
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs146
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs39
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs18
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs2806
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs175
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs28
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs65
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs209
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs24
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs48
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs1087
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs165
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs54
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs42
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs415
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs317
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs115
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs402
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs53
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs773
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs297
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs21
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs141
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs595
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs46
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs27
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs42
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs35
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs60
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs36
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs79
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs57
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs330
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs71
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs37
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/Variant.cs659
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs37
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs123
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs108
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs241
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs66
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs555
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs406
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs288
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs138
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs124
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs118
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs131
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs168
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs53
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs255
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs19
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs57
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs52
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs553
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs54
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs59
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs324
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs171
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs88
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs141
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs26
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs113
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs84
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs210
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs188
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs94
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs255
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs76
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs192
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs183
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs68
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs65
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs64
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs122
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs127
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs170
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs47
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs15
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs1335
-rw-r--r--src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs216
-rw-r--r--src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs481
-rw-r--r--src/mscorlib/src/System/Runtime/MemoryFailPoint.cs488
-rw-r--r--src/mscorlib/src/System/Runtime/ProfileOptimization.cs54
-rw-r--r--src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs44
-rw-r--r--src/mscorlib/src/System/Runtime/Reliability/PrePrepareMethodAttribute.cs32
-rw-r--r--src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs67
-rw-r--r--src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs81
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs167
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs590
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/IDeserializationCallback.cs23
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/IFormatter.cs41
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/IFormatterConverter.cs40
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/IObjectReference.cs30
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/ISerializable.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/ISerializationSurrogate.cs36
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/ISurrogateSelector.cs37
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/MemberHolder.cs51
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationAttributes.cs64
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationBinder.cs29
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationException.cs45
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs166
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs798
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/SerializationInfoEnumerator.cs146
-rw-r--r--src/mscorlib/src/System/Runtime/Serialization/StreamingContext.cs74
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs485
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs61
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs44
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs33
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs237
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs45
-rw-r--r--src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs28
-rw-r--r--src/mscorlib/src/System/RuntimeArgumentHandle.cs24
-rw-r--r--src/mscorlib/src/System/RuntimeHandles.cs2101
-rw-r--r--src/mscorlib/src/System/SByte.cs274
-rw-r--r--src/mscorlib/src/System/Security/AccessControl/Enums.cs81
-rw-r--r--src/mscorlib/src/System/Security/Attributes.cs209
-rw-r--r--src/mscorlib/src/System/Security/BuiltInPermissionSets.cs342
-rw-r--r--src/mscorlib/src/System/Security/CodeAccessPermission.cs284
-rw-r--r--src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs842
-rw-r--r--src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs564
-rw-r--r--src/mscorlib/src/System/Security/HostProtectionException.cs136
-rw-r--r--src/mscorlib/src/System/Security/HostSecurityManager.cs215
-rw-r--r--src/mscorlib/src/System/Security/IEvidenceFactory.cs20
-rw-r--r--src/mscorlib/src/System/Security/IPermission.cs84
-rw-r--r--src/mscorlib/src/System/Security/ISecurityEncodable.cs29
-rw-r--r--src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs28
-rw-r--r--src/mscorlib/src/System/Security/IStackWalk.cs23
-rw-r--r--src/mscorlib/src/System/Security/NamedPermissionSet.cs269
-rw-r--r--src/mscorlib/src/System/Security/PermissionListSet.cs554
-rw-r--r--src/mscorlib/src/System/Security/PermissionSet.cs2641
-rw-r--r--src/mscorlib/src/System/Security/PermissionSetEnumerator.cs103
-rw-r--r--src/mscorlib/src/System/Security/PermissionSetTriple.cs282
-rw-r--r--src/mscorlib/src/System/Security/PermissionToken.cs563
-rw-r--r--src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs405
-rw-r--r--src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs189
-rw-r--r--src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs1478
-rw-r--r--src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs119
-rw-r--r--src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs299
-rw-r--r--src/mscorlib/src/System/Security/Permissions/IBuiltInPermission.cs63
-rw-r--r--src/mscorlib/src/System/Security/Permissions/IUnrestrictedPermission.cs13
-rw-r--r--src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs176
-rw-r--r--src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs274
-rw-r--r--src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs1176
-rw-r--r--src/mscorlib/src/System/Security/Permissions/PermissionState.cs21
-rw-r--r--src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs313
-rw-r--r--src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs494
-rw-r--r--src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs362
-rw-r--r--src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs359
-rw-r--r--src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs487
-rw-r--r--src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs94
-rw-r--r--src/mscorlib/src/System/Security/Permissions/UIPermission.cs371
-rw-r--r--src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs391
-rw-r--r--src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs309
-rw-r--r--src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs688
-rw-r--r--src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs689
-rw-r--r--src/mscorlib/src/System/Security/Policy/Evidence.cs1903
-rw-r--r--src/mscorlib/src/System/Security/Policy/EvidenceBase.cs193
-rw-r--r--src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs160
-rw-r--r--src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs35
-rw-r--r--src/mscorlib/src/System/Security/Policy/IIdentityPermissionFactory.cs20
-rw-r--r--src/mscorlib/src/System/Security/Policy/IRuntimeEvidenceFactory.cs36
-rw-r--r--src/mscorlib/src/System/Security/Policy/PolicyException.cs50
-rw-r--r--src/mscorlib/src/System/Security/Policy/PolicyStatement.cs540
-rw-r--r--src/mscorlib/src/System/Security/Policy/Site.cs128
-rw-r--r--src/mscorlib/src/System/Security/Policy/StrongName.cs222
-rw-r--r--src/mscorlib/src/System/Security/Policy/URL.cs119
-rw-r--r--src/mscorlib/src/System/Security/Policy/Zone.cs151
-rw-r--r--src/mscorlib/src/System/Security/Principal/IIdentity.cs29
-rw-r--r--src/mscorlib/src/System/Security/Principal/IPrincipal.cs26
-rw-r--r--src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs20
-rw-r--r--src/mscorlib/src/System/Security/SafeSecurityHandles.cs164
-rw-r--r--src/mscorlib/src/System/Security/SecurityContext.cs702
-rw-r--r--src/mscorlib/src/System/Security/SecurityElement.cs929
-rw-r--r--src/mscorlib/src/System/Security/SecurityException.cs667
-rw-r--r--src/mscorlib/src/System/Security/SecurityManager.cs671
-rw-r--r--src/mscorlib/src/System/Security/SecurityRuntime.cs299
-rw-r--r--src/mscorlib/src/System/Security/SecurityState.cs34
-rw-r--r--src/mscorlib/src/System/Security/SecurityZone.cs29
-rw-r--r--src/mscorlib/src/System/Security/Util/Config.cs131
-rw-r--r--src/mscorlib/src/System/Security/Util/Hex.cs126
-rw-r--r--src/mscorlib/src/System/Security/Util/StringExpressionSet.cs777
-rw-r--r--src/mscorlib/src/System/Security/Util/TokenBasedSet.cs467
-rw-r--r--src/mscorlib/src/System/Security/Util/TokenBasedSetEnumerator.cs36
-rw-r--r--src/mscorlib/src/System/Security/Util/URLString.cs1366
-rw-r--r--src/mscorlib/src/System/Security/Util/XMLUtil.cs695
-rw-r--r--src/mscorlib/src/System/Security/Util/sitestring.cs289
-rw-r--r--src/mscorlib/src/System/Security/VerificationException.cs33
-rw-r--r--src/mscorlib/src/System/Security/securestring.cs750
-rw-r--r--src/mscorlib/src/System/SerializableAttribute.cs34
-rw-r--r--src/mscorlib/src/System/SharedStatics.cs148
-rw-r--r--src/mscorlib/src/System/Single.cs337
-rw-r--r--src/mscorlib/src/System/StackOverflowException.cs40
-rw-r--r--src/mscorlib/src/System/String.Comparison.cs1160
-rw-r--r--src/mscorlib/src/System/String.Manipulation.cs1596
-rw-r--r--src/mscorlib/src/System/String.Searching.cs358
-rw-r--r--src/mscorlib/src/System/String.cs891
-rw-r--r--src/mscorlib/src/System/StringComparer.cs440
-rw-r--r--src/mscorlib/src/System/StringComparison.cs28
-rw-r--r--src/mscorlib/src/System/StringFreezingAttribute.cs25
-rw-r--r--src/mscorlib/src/System/StringSplitOptions.cs16
-rw-r--r--src/mscorlib/src/System/StubHelpers.cs1957
-rw-r--r--src/mscorlib/src/System/SystemException.cs31
-rw-r--r--src/mscorlib/src/System/Text/ASCIIEncoding.cs773
-rw-r--r--src/mscorlib/src/System/Text/BaseCodePageEncoding.cs350
-rw-r--r--src/mscorlib/src/System/Text/CodePageEncoding.cs139
-rw-r--r--src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs1206
-rw-r--r--src/mscorlib/src/System/Text/Decoder.cs349
-rw-r--r--src/mscorlib/src/System/Text/DecoderBestFitFallback.cs247
-rw-r--r--src/mscorlib/src/System/Text/DecoderExceptionFallback.cs155
-rw-r--r--src/mscorlib/src/System/Text/DecoderFallback.cs284
-rw-r--r--src/mscorlib/src/System/Text/DecoderNLS.cs298
-rw-r--r--src/mscorlib/src/System/Text/DecoderReplacementFallback.cs209
-rw-r--r--src/mscorlib/src/System/Text/EUCJPEncoding.cs186
-rw-r--r--src/mscorlib/src/System/Text/Encoder.cs342
-rw-r--r--src/mscorlib/src/System/Text/EncoderBestFitFallback.cs247
-rw-r--r--src/mscorlib/src/System/Text/EncoderExceptionFallback.cs203
-rw-r--r--src/mscorlib/src/System/Text/EncoderFallback.cs236
-rw-r--r--src/mscorlib/src/System/Text/EncoderNLS.cs296
-rw-r--r--src/mscorlib/src/System/Text/EncoderReplacementFallback.cs233
-rw-r--r--src/mscorlib/src/System/Text/Encoding.cs2152
-rw-r--r--src/mscorlib/src/System/Text/EncodingForwarder.cs339
-rw-r--r--src/mscorlib/src/System/Text/EncodingInfo.cs74
-rw-r--r--src/mscorlib/src/System/Text/EncodingNLS.cs130
-rw-r--r--src/mscorlib/src/System/Text/EncodingProvider.cs137
-rw-r--r--src/mscorlib/src/System/Text/GB18030Encoding.cs1377
-rw-r--r--src/mscorlib/src/System/Text/ISCIIEncoding.cs2625
-rw-r--r--src/mscorlib/src/System/Text/ISO2022Encoding.cs1995
-rw-r--r--src/mscorlib/src/System/Text/Latin1Encoding.cs917
-rw-r--r--src/mscorlib/src/System/Text/MLangCodePageEncoding.cs177
-rw-r--r--src/mscorlib/src/System/Text/Normalization.cs350
-rw-r--r--src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs1020
-rw-r--r--src/mscorlib/src/System/Text/StringBuilder.cs2217
-rw-r--r--src/mscorlib/src/System/Text/StringBuilderCache.cs83
-rw-r--r--src/mscorlib/src/System/Text/SurrogateEncoder.cs58
-rw-r--r--src/mscorlib/src/System/Text/UTF32Encoding.cs1010
-rw-r--r--src/mscorlib/src/System/Text/UTF7Encoding.cs901
-rw-r--r--src/mscorlib/src/System/Text/UTF8Encoding.cs2307
-rw-r--r--src/mscorlib/src/System/Text/UnicodeEncoding.cs1842
-rw-r--r--src/mscorlib/src/System/ThreadAttributes.cs32
-rw-r--r--src/mscorlib/src/System/ThreadStaticAttribute.cs28
-rw-r--r--src/mscorlib/src/System/Threading/AbandonedMutexException.cs85
-rw-r--r--src/mscorlib/src/System/Threading/ApartmentState.cs28
-rw-r--r--src/mscorlib/src/System/Threading/AsyncLocal.cs116
-rw-r--r--src/mscorlib/src/System/Threading/AutoResetEvent.cs27
-rw-r--r--src/mscorlib/src/System/Threading/CancellationToken.cs499
-rw-r--r--src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs161
-rw-r--r--src/mscorlib/src/System/Threading/CancellationTokenSource.cs1269
-rw-r--r--src/mscorlib/src/System/Threading/CountdownEvent.cs592
-rw-r--r--src/mscorlib/src/System/Threading/EventResetMode.cs26
-rw-r--r--src/mscorlib/src/System/Threading/EventWaitHandle.cs297
-rw-r--r--src/mscorlib/src/System/Threading/ExecutionContext.cs1398
-rw-r--r--src/mscorlib/src/System/Threading/IObjectHandle.cs31
-rw-r--r--src/mscorlib/src/System/Threading/Interlocked.cs233
-rw-r--r--src/mscorlib/src/System/Threading/LazyInitializer.cs265
-rw-r--r--src/mscorlib/src/System/Threading/LockCookie.cs57
-rw-r--r--src/mscorlib/src/System/Threading/LockRecursionException.cs34
-rw-r--r--src/mscorlib/src/System/Threading/ManualResetEvent.cs27
-rw-r--r--src/mscorlib/src/System/Threading/ManualResetEventSlim.cs813
-rw-r--r--src/mscorlib/src/System/Threading/Monitor.cs256
-rw-r--r--src/mscorlib/src/System/Threading/Mutex.cs488
-rw-r--r--src/mscorlib/src/System/Threading/Overlapped.cs423
-rw-r--r--src/mscorlib/src/System/Threading/ParameterizedThreadStart.cs24
-rw-r--r--src/mscorlib/src/System/Threading/ReaderWriterLock.cs306
-rw-r--r--src/mscorlib/src/System/Threading/Semaphore.cs201
-rw-r--r--src/mscorlib/src/System/Threading/SemaphoreFullException.cs30
-rw-r--r--src/mscorlib/src/System/Threading/SemaphoreSlim.cs930
-rw-r--r--src/mscorlib/src/System/Threading/SendOrPostCallback.cs16
-rw-r--r--src/mscorlib/src/System/Threading/SpinLock.cs750
-rw-r--r--src/mscorlib/src/System/Threading/SpinWait.cs369
-rw-r--r--src/mscorlib/src/System/Threading/SynchronizationContext.cs320
-rw-r--r--src/mscorlib/src/System/Threading/SynchronizationLockException.cs44
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs295
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs157
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs795
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs2303
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs101
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/Parallel.cs3594
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs642
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs278
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs553
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs763
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/Task.cs7344
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskCanceledException.cs93
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs370
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs867
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs424
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs3206
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs757
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskSchedulerException.cs81
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs189
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs139
-rw-r--r--src/mscorlib/src/System/Threading/Tasks/future.cs1667
-rw-r--r--src/mscorlib/src/System/Threading/Thread.cs1756
-rw-r--r--src/mscorlib/src/System/Threading/ThreadAbortException.cs46
-rw-r--r--src/mscorlib/src/System/Threading/ThreadInterruptedException.cs41
-rw-r--r--src/mscorlib/src/System/Threading/ThreadLocal.cs815
-rw-r--r--src/mscorlib/src/System/Threading/ThreadPool.cs1954
-rw-r--r--src/mscorlib/src/System/Threading/ThreadPriority.cs32
-rw-r--r--src/mscorlib/src/System/Threading/ThreadStart.cs25
-rw-r--r--src/mscorlib/src/System/Threading/ThreadStartException.cs37
-rw-r--r--src/mscorlib/src/System/Threading/ThreadState.cs36
-rw-r--r--src/mscorlib/src/System/Threading/ThreadStateException.cs41
-rw-r--r--src/mscorlib/src/System/Threading/Timeout.cs21
-rw-r--r--src/mscorlib/src/System/Threading/Timer.cs954
-rw-r--r--src/mscorlib/src/System/Threading/Volatile.cs441
-rw-r--r--src/mscorlib/src/System/Threading/WaitHandle.cs617
-rw-r--r--src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs40
-rw-r--r--src/mscorlib/src/System/Threading/WaitHandleExtensions.cs46
-rw-r--r--src/mscorlib/src/System/ThrowHelper.cs347
-rw-r--r--src/mscorlib/src/System/TimeSpan.cs445
-rw-r--r--src/mscorlib/src/System/TimeZone.cs249
-rw-r--r--src/mscorlib/src/System/TimeZoneInfo.cs5761
-rw-r--r--src/mscorlib/src/System/TimeZoneNotFoundException.cs26
-rw-r--r--src/mscorlib/src/System/TimeoutException.cs45
-rw-r--r--src/mscorlib/src/System/Tuple.cs959
-rw-r--r--src/mscorlib/src/System/Type.cs1845
-rw-r--r--src/mscorlib/src/System/TypeAccessException.cs40
-rw-r--r--src/mscorlib/src/System/TypeCode.cs48
-rw-r--r--src/mscorlib/src/System/TypeInitializationException.cs66
-rw-r--r--src/mscorlib/src/System/TypeLoadException.cs143
-rw-r--r--src/mscorlib/src/System/TypeNameParser.cs365
-rw-r--r--src/mscorlib/src/System/TypeUnloadedException.cs43
-rw-r--r--src/mscorlib/src/System/TypedReference.cs133
-rw-r--r--src/mscorlib/src/System/UInt16.cs241
-rw-r--r--src/mscorlib/src/System/UInt32.cs223
-rw-r--r--src/mscorlib/src/System/UInt64.cs218
-rw-r--r--src/mscorlib/src/System/UIntPtr.cs249
-rw-r--r--src/mscorlib/src/System/UnSafeCharBuffer.cs57
-rw-r--r--src/mscorlib/src/System/UnauthorizedAccessException.cs43
-rw-r--r--src/mscorlib/src/System/UnhandledExceptionEventArgs.cs29
-rw-r--r--src/mscorlib/src/System/UnhandledExceptionEventHandler.cs14
-rw-r--r--src/mscorlib/src/System/UnitySerializationHolder.cs359
-rw-r--r--src/mscorlib/src/System/ValueType.cs93
-rw-r--r--src/mscorlib/src/System/Variant.cs681
-rw-r--r--src/mscorlib/src/System/Version.cs504
-rw-r--r--src/mscorlib/src/System/Void.cs18
-rw-r--r--src/mscorlib/src/System/WeakReference.cs125
-rw-r--r--src/mscorlib/src/System/WeakReferenceOfT.cs121
-rw-r--r--src/mscorlib/src/System/XmlIgnoreMemberAttribute.cs21
-rw-r--r--src/mscorlib/src/System/_LocalDataStore.cs244
-rw-r--r--src/mscorlib/src/System/_LocalDataStoreMgr.cs339
-rw-r--r--src/mscorlib/src/System/__ComObject.cs206
-rw-r--r--src/mscorlib/src/System/__Filters.cs155
-rw-r--r--src/mscorlib/src/System/__HResults.cs129
-rw-r--r--src/mscorlib/src/System/cominterfaces.cs68
-rw-r--r--src/mscorlib/src/System/mda.cs88
-rw-r--r--src/mscorlib/src/mscorlib.Friends.cs27
-rw-r--r--src/mscorlib/src/mscorlib.txt3494
1082 files changed, 419502 insertions, 0 deletions
diff --git a/src/mscorlib/.gitmirrorall b/src/mscorlib/.gitmirrorall
new file mode 100644
index 0000000000..9ee5c57b99
--- /dev/null
+++ b/src/mscorlib/.gitmirrorall
@@ -0,0 +1 @@
+This folder will be mirrored by the Git-TFS Mirror recursively. \ No newline at end of file
diff --git a/src/mscorlib/Common/PinnableBufferCache.cs b/src/mscorlib/Common/PinnableBufferCache.cs
new file mode 100644
index 0000000000..fee3e46f46
--- /dev/null
+++ b/src/mscorlib/Common/PinnableBufferCache.cs
@@ -0,0 +1,666 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#define ENABLE
+#define MINBUFFERS
+using System;
+#if !FEATURE_CORECLR
+using System.Diagnostics.Tracing;
+#endif
+using System.Runtime.InteropServices;
+using System.Runtime.ConstrainedExecution;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Diagnostics;
+using System.Security.Permissions;
+
+#if PINNABLEBUFFERCACHE_MSCORLIB
+namespace System.Threading
+#else
+namespace System
+#endif
+{
+ internal sealed class PinnableBufferCache
+ {
+ /// <summary>
+ /// Create a new cache for pinned byte[] buffers
+ /// </summary>
+ /// <param name="cacheName">A name used in diagnostic messages</param>
+ /// <param name="numberOfElements">The size of byte[] buffers in the cache (they are all the same size)</param>
+ public PinnableBufferCache(string cacheName, int numberOfElements) : this(cacheName, () => new byte[numberOfElements]) { }
+
+ /// <summary>
+ /// Get a buffer from the buffer manager. If no buffers exist, allocate a new one.
+ /// </summary>
+ public byte[] AllocateBuffer() { return (byte[])Allocate(); }
+
+ /// <summary>
+ /// Return a buffer back to the buffer manager.
+ /// </summary>
+ public void FreeBuffer(byte[] buffer) { Free(buffer); }
+
+ /// <summary>
+ /// Create a PinnableBufferCache that works on any object (it is intended for OverlappedData)
+ /// This is only used in mscorlib.
+ /// </summary>
+#if (ENABLE || MINBUFFERS)
+#pragma warning disable 618
+ [EnvironmentPermission(SecurityAction.Assert, Unrestricted = true)]
+#pragma warning restore 618
+ [System.Security.SecuritySafeCritical]
+#endif
+ internal PinnableBufferCache(string cacheName, Func<object> factory)
+ {
+ m_NotGen2 = new List<object>(DefaultNumberOfBuffers);
+ m_factory = factory;
+#if ENABLE
+ // Check to see if we should disable the cache.
+ string envVarName = "PinnableBufferCache_" + cacheName + "_Disabled";
+ try
+ {
+ string envVar = Environment.GetEnvironmentVariable(envVarName);
+ if (envVar != null)
+ {
+ PinnableBufferCacheEventSource.Log.DebugMessage("Creating " + cacheName + " PinnableBufferCacheDisabled=" + envVar);
+ int index = envVar.IndexOf(cacheName, StringComparison.OrdinalIgnoreCase);
+ if (0 <= index)
+ {
+ // The cache is disabled because we haven't set the cache name.
+ PinnableBufferCacheEventSource.Log.DebugMessage("Disabling " + cacheName);
+ return;
+ }
+ }
+ }
+ catch
+ {
+ // Ignore failures when reading the environment variable.
+ }
+#endif
+#if MINBUFFERS
+ // Allow the environment to specify a minimum buffer count.
+ string minEnvVarName = "PinnableBufferCache_" + cacheName + "_MinCount";
+ try
+ {
+ string minEnvVar = Environment.GetEnvironmentVariable(minEnvVarName);
+ if (minEnvVar != null)
+ {
+ if (int.TryParse(minEnvVar, out m_minBufferCount))
+ CreateNewBuffers();
+ }
+ }
+ catch
+ {
+ // Ignore failures when reading the environment variable.
+ }
+#endif
+
+ PinnableBufferCacheEventSource.Log.Create(cacheName);
+ m_CacheName = cacheName;
+ }
+
+ /// <summary>
+ /// Get a object from the buffer manager. If no buffers exist, allocate a new one.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ internal object Allocate()
+ {
+#if ENABLE
+ // Check to see whether or not the cache is disabled.
+ if (m_CacheName == null)
+ return m_factory();
+#endif
+ // Fast path, get it from our Gen2 aged m_FreeList.
+ object returnBuffer;
+ if (!m_FreeList.TryPop(out returnBuffer))
+ Restock(out returnBuffer);
+
+ // Computing free count is expensive enough that we don't want to compute it unless logging is on.
+ if (PinnableBufferCacheEventSource.Log.IsEnabled())
+ {
+ int numAllocCalls = Interlocked.Increment(ref m_numAllocCalls);
+ if (numAllocCalls >= 1024)
+ {
+ lock (this)
+ {
+ int previousNumAllocCalls = Interlocked.Exchange(ref m_numAllocCalls, 0);
+ if (previousNumAllocCalls >= 1024)
+ {
+ int nonGen2Count = 0;
+ foreach (object o in m_FreeList)
+ {
+ if (GC.GetGeneration(o) < GC.MaxGeneration)
+ {
+ nonGen2Count++;
+ }
+ }
+
+ PinnableBufferCacheEventSource.Log.WalkFreeListResult(m_CacheName, m_FreeList.Count, nonGen2Count);
+ }
+ }
+ }
+
+ PinnableBufferCacheEventSource.Log.AllocateBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(returnBuffer), returnBuffer.GetHashCode(), GC.GetGeneration(returnBuffer), m_FreeList.Count);
+ }
+ return returnBuffer;
+ }
+
+ /// <summary>
+ /// Return a buffer back to the buffer manager.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ internal void Free(object buffer)
+ {
+#if ENABLE
+ // Check to see whether or not the cache is disabled.
+ if (m_CacheName == null)
+ return;
+#endif
+ if (PinnableBufferCacheEventSource.Log.IsEnabled())
+ PinnableBufferCacheEventSource.Log.FreeBuffer(m_CacheName, PinnableBufferCacheEventSource.AddressOf(buffer), buffer.GetHashCode(), m_FreeList.Count);
+
+
+ // 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))
+ {
+ lock (this)
+ {
+ if (GC.GetGeneration(buffer) < GC.MaxGeneration)
+ {
+ // The buffer is not aged, so put it in the non-aged free list.
+ m_moreThanFreeListNeeded = true;
+ PinnableBufferCacheEventSource.Log.FreeBufferStillTooYoung(m_CacheName, m_NotGen2.Count);
+ m_NotGen2.Add(buffer);
+ m_gen1CountAtLastRestock = GC.CollectionCount(GC.MaxGeneration - 1);
+ return;
+ }
+ }
+ }
+
+ // If we discovered that it is indeed Gen2, great, put it in the Gen2 list.
+ m_FreeList.Push(buffer);
+ }
+
+ #region Private
+
+ /// <summary>
+ /// Called when we don't have any buffers in our free list to give out.
+ /// </summary>
+ /// <returns></returns>
+ [System.Security.SecuritySafeCritical]
+ private void Restock(out object returnBuffer)
+ {
+ lock (this)
+ {
+ // Try again after getting the lock as another thread could have just filled the free list. If we don't check
+ // then we unnecessarily grab a new set of buffers because we think we are out.
+ if (m_FreeList.TryPop(out returnBuffer))
+ return;
+
+ // Lazy init, Ask that TrimFreeListIfNeeded be called on every Gen 2 GC.
+ if (m_restockSize == 0)
+ Gen2GcCallback.Register(Gen2GcCallbackFunc, this);
+
+ // Indicate to the trimming policy that the free list is insufficent.
+ m_moreThanFreeListNeeded = true;
+ PinnableBufferCacheEventSource.Log.AllocateBufferFreeListEmpty(m_CacheName, m_NotGen2.Count);
+
+ // Get more buffers if needed.
+ if (m_NotGen2.Count == 0)
+ CreateNewBuffers();
+
+ // We have no buffers in the aged freelist, so get one from the newer list. Try to pick the best one.
+ // Debug.Assert(m_NotGen2.Count != 0);
+ int idx = m_NotGen2.Count - 1;
+ if (GC.GetGeneration(m_NotGen2[idx]) < GC.MaxGeneration && GC.GetGeneration(m_NotGen2[0]) == GC.MaxGeneration)
+ idx = 0;
+ returnBuffer = m_NotGen2[idx];
+ m_NotGen2.RemoveAt(idx);
+
+ // Remember any sub-optimial buffer so we don't put it on the free list when it gets freed.
+ if (PinnableBufferCacheEventSource.Log.IsEnabled() && GC.GetGeneration(returnBuffer) < GC.MaxGeneration)
+ {
+ PinnableBufferCacheEventSource.Log.AllocateBufferFromNotGen2(m_CacheName, m_NotGen2.Count);
+ }
+
+ // If we have a Gen1 collection, then everything on m_NotGen2 should have aged. Move them to the m_Free list.
+ if (!AgePendingBuffers())
+ {
+ // Before we could age at set of buffers, we have handed out half of them.
+ // This implies we should be proactive about allocating more (since we will trim them if we over-allocate).
+ if (m_NotGen2.Count == m_restockSize / 2)
+ {
+ PinnableBufferCacheEventSource.Log.DebugMessage("Proactively adding more buffers to aging pool");
+ CreateNewBuffers();
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// See if we can promote the buffers to the free list. Returns true if sucessful.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ private bool AgePendingBuffers()
+ {
+ if (m_gen1CountAtLastRestock < GC.CollectionCount(GC.MaxGeneration - 1))
+ {
+ // Allocate a temp list of buffers that are not actually in gen2, and swap it in once
+ // we're done scanning all buffers.
+ int promotedCount = 0;
+ List<object> notInGen2 = new List<object>();
+ PinnableBufferCacheEventSource.Log.AllocateBufferAged(m_CacheName, m_NotGen2.Count);
+ for (int i = 0; i < m_NotGen2.Count; i++)
+ {
+ // We actually check every object to ensure that we aren't putting non-aged buffers into the free list.
+ object currentBuffer = m_NotGen2[i];
+ if (GC.GetGeneration(currentBuffer) >= GC.MaxGeneration)
+ {
+ m_FreeList.Push(currentBuffer);
+ promotedCount++;
+ }
+ else
+ {
+ notInGen2.Add(currentBuffer);
+ }
+ }
+ PinnableBufferCacheEventSource.Log.AgePendingBuffersResults(m_CacheName, promotedCount, notInGen2.Count);
+ m_NotGen2 = notInGen2;
+
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Generates some buffers to age into Gen2.
+ /// </summary>
+ private void CreateNewBuffers()
+ {
+ // We choose a very modest number of buffers initially because for the client case. This is often enough.
+ if (m_restockSize == 0)
+ m_restockSize = 4;
+ else if (m_restockSize < DefaultNumberOfBuffers)
+ m_restockSize = DefaultNumberOfBuffers;
+ else if (m_restockSize < 256)
+ m_restockSize = m_restockSize * 2; // Grow quickly at small sizes
+ else if (m_restockSize < 4096)
+ m_restockSize = m_restockSize * 3 / 2; // Less agressively at large ones
+ else
+ m_restockSize = 4096; // Cap how agressive we are
+
+ // Ensure we hit our minimums
+ if (m_minBufferCount > m_buffersUnderManagement)
+ m_restockSize = Math.Max(m_restockSize, m_minBufferCount - m_buffersUnderManagement);
+
+ PinnableBufferCacheEventSource.Log.AllocateBufferCreatingNewBuffers(m_CacheName, m_buffersUnderManagement, m_restockSize);
+ for (int i = 0; i < m_restockSize; i++)
+ {
+ // Make a new buffer.
+ object newBuffer = m_factory();
+
+ // Create space between the objects. We do this because otherwise it forms a single plug (group of objects)
+ // and the GC pins the entire plug making them NOT move to Gen1 and Gen2. by putting space between them
+ // we ensure that object get a chance to move independently (even if some are pinned).
+ var dummyObject = new object();
+ m_NotGen2.Add(newBuffer);
+ }
+ m_buffersUnderManagement += m_restockSize;
+ m_gen1CountAtLastRestock = GC.CollectionCount(GC.MaxGeneration - 1);
+ }
+
+ /// <summary>
+ /// This is the static function that is called from the gen2 GC callback.
+ /// The input object is the cache itself.
+ /// NOTE: The reason that we make this functionstatic and take the cache as a parameter is that
+ /// otherwise, we root the cache to the Gen2GcCallback object, and leak the cache even when
+ /// the application no longer needs it.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ private static bool Gen2GcCallbackFunc(object targetObj)
+ {
+ return ((PinnableBufferCache)(targetObj)).TrimFreeListIfNeeded();
+ }
+
+ /// <summary>
+ /// This is called on every gen2 GC to see if we need to trim the free list.
+ /// NOTE: DO NOT CALL THIS DIRECTLY FROM THE GEN2GCCALLBACK. INSTEAD CALL IT VIA A STATIC FUNCTION (SEE ABOVE).
+ /// If you register a non-static function as a callback, then this object will be leaked.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ private bool TrimFreeListIfNeeded()
+ {
+ int curMSec = Environment.TickCount;
+ int deltaMSec = curMSec - m_msecNoUseBeyondFreeListSinceThisTime;
+ PinnableBufferCacheEventSource.Log.TrimCheck(m_CacheName, m_buffersUnderManagement, m_moreThanFreeListNeeded, deltaMSec);
+
+ // If we needed more than just the set of aged buffers since the last time we were called,
+ // we obviously should not be trimming any memory, so do nothing except reset the flag
+ if (m_moreThanFreeListNeeded)
+ {
+ m_moreThanFreeListNeeded = false;
+ m_trimmingExperimentInProgress = false;
+ m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
+ return true;
+ }
+
+ // We require a minimum amount of clock time to pass (10 seconds) before we trim. Ideally this time
+ // is larger than the typical buffer hold time.
+ if (0 <= deltaMSec && deltaMSec < 10000)
+ return true;
+
+ // If we got here we have spend the last few second without needing to lengthen the free list. Thus
+ // we have 'enough' buffers, but maybe we have too many.
+ // See if we can trim
+ lock (this)
+ {
+ // Hit a race, try again later.
+ if (m_moreThanFreeListNeeded)
+ {
+ m_moreThanFreeListNeeded = false;
+ m_trimmingExperimentInProgress = false;
+ m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
+ return true;
+ }
+
+ var freeCount = m_FreeList.Count; // This is expensive to fetch, do it once.
+
+ // If there is something in m_NotGen2 it was not used for the last few seconds, it is trimable.
+ if (m_NotGen2.Count > 0)
+ {
+ // If we are not performing an experiment and we have stuff that is waiting to go into the
+ // free list but has not made it there, it could be becasue the 'slow path' of restocking
+ // has not happened, so force this (which should flush the list) and start over.
+ if (!m_trimmingExperimentInProgress)
+ {
+ PinnableBufferCacheEventSource.Log.TrimFlush(m_CacheName, m_buffersUnderManagement, freeCount, m_NotGen2.Count);
+ AgePendingBuffers();
+ m_trimmingExperimentInProgress = true;
+ return true;
+ }
+
+ PinnableBufferCacheEventSource.Log.TrimFree(m_CacheName, m_buffersUnderManagement, freeCount, m_NotGen2.Count);
+ m_buffersUnderManagement -= m_NotGen2.Count;
+
+ // Possibly revise the restocking down. We don't want to grow agressively if we are trimming.
+ var newRestockSize = m_buffersUnderManagement / 4;
+ if (newRestockSize < m_restockSize)
+ m_restockSize = Math.Max(newRestockSize, DefaultNumberOfBuffers);
+
+ m_NotGen2.Clear();
+ m_trimmingExperimentInProgress = false;
+ return true;
+ }
+
+ // Set up an experiment where we use 25% less buffers in our free list. We put them in
+ // m_NotGen2, and if they are needed they will be put back in the free list again.
+ var trimSize = freeCount / 4 + 1;
+
+ // We are OK with a 15% overhead, do nothing in that case.
+ if (freeCount * 15 <= m_buffersUnderManagement || m_buffersUnderManagement - trimSize <= m_minBufferCount)
+ {
+ PinnableBufferCacheEventSource.Log.TrimFreeSizeOK(m_CacheName, m_buffersUnderManagement, freeCount);
+ return true;
+ }
+
+ // Move buffers from the free list back to the non-aged list. If we don't use them by next time, then we'll consider trimming them.
+ PinnableBufferCacheEventSource.Log.TrimExperiment(m_CacheName, m_buffersUnderManagement, freeCount, trimSize);
+ object buffer;
+ for (int i = 0; i < trimSize; i++)
+ {
+ if (m_FreeList.TryPop(out buffer))
+ m_NotGen2.Add(buffer);
+ }
+ m_msecNoUseBeyondFreeListSinceThisTime = curMSec;
+ m_trimmingExperimentInProgress = true;
+ }
+
+ // Indicate that we want to be called back on the next Gen 2 GC.
+ return true;
+ }
+
+ private const int DefaultNumberOfBuffers = 16;
+ private string m_CacheName;
+ private Func<object> m_factory;
+
+ /// <summary>
+ /// Contains 'good' buffers to reuse. They are guarenteed to be Gen 2 ENFORCED!
+ /// </summary>
+ private ConcurrentStack<object> m_FreeList = new ConcurrentStack<object>();
+ /// <summary>
+ /// Contains buffers that are not gen 2 and thus we do not wish to give out unless we have to.
+ /// To implement trimming we sometimes put aged buffers in here as a place to 'park' them
+ /// before true deletion.
+ /// </summary>
+ private List<object> m_NotGen2;
+ /// <summary>
+ /// What whas the gen 1 count the last time re restocked? If it is now greater, then
+ /// we know that all objects are in Gen 2 so we don't have to check. Should be updated
+ /// every time something gets added to the m_NotGen2 list.
+ /// </summary>
+ private int m_gen1CountAtLastRestock;
+
+ /// <summary>
+ /// Used to ensure we have a minimum time between trimmings.
+ /// </summary>
+ private int m_msecNoUseBeyondFreeListSinceThisTime;
+ /// <summary>
+ /// To trim, we remove things from the free list (which is Gen 2) and see if we 'hit bottom'
+ /// This flag indicates that we hit bottom (we really needed a bigger free list).
+ /// </summary>
+ private bool m_moreThanFreeListNeeded;
+ /// <summary>
+ /// The total number of buffers that this cache has ever allocated.
+ /// Used in trimming heuristics.
+ /// </summary>
+ private int m_buffersUnderManagement;
+ /// <summary>
+ /// The number of buffers we added the last time we restocked.
+ /// </summary>
+ private int m_restockSize;
+ /// <summary>
+ /// Did we put some buffers into m_NotGen2 to see if we can trim?
+ /// </summary>
+ private bool m_trimmingExperimentInProgress;
+ /// <summary>
+ /// A forced minimum number of buffers.
+ /// </summary>
+ private int m_minBufferCount;
+ /// <summary>
+ /// The number of calls to Allocate.
+ /// </summary>
+ private int m_numAllocCalls;
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Schedules a callback roughly every gen 2 GC (you may see a Gen 0 an Gen 1 but only once)
+ /// (We can fix this by capturing the Gen 2 count at startup and testing, but I mostly don't care)
+ /// </summary>
+ internal sealed class Gen2GcCallback : CriticalFinalizerObject
+ {
+ [System.Security.SecuritySafeCritical]
+ public Gen2GcCallback()
+ : base()
+ {
+ }
+
+ /// <summary>
+ /// Schedule 'callback' to be called in the next GC. If the callback returns true it is
+ /// rescheduled for the next Gen 2 GC. Otherwise the callbacks stop.
+ ///
+ /// NOTE: This callback will be kept alive until either the callback function returns false,
+ /// or the target object dies.
+ /// </summary>
+ public static void Register(Func<object, bool> callback, object targetObj)
+ {
+ // Create a unreachable object that remembers the callback function and target object.
+ Gen2GcCallback gcCallback = new Gen2GcCallback();
+ gcCallback.Setup(callback, targetObj);
+ }
+
+ #region Private
+
+ private Func<object, bool> m_callback;
+ private GCHandle m_weakTargetObj;
+
+ [System.Security.SecuritySafeCritical]
+ private void Setup(Func<object, bool> callback, object targetObj)
+ {
+ m_callback = callback;
+ m_weakTargetObj = GCHandle.Alloc(targetObj, GCHandleType.Weak);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ ~Gen2GcCallback()
+ {
+ // Check to see if the target object is still alive.
+ object targetObj = m_weakTargetObj.Target;
+ if (targetObj == null)
+ {
+ // The target object is dead, so this callback object is no longer needed.
+ m_weakTargetObj.Free();
+ return;
+ }
+
+ // Execute the callback method.
+ try
+ {
+ if (!m_callback(targetObj))
+ {
+ // If the callback returns false, this callback object is no longer needed.
+ return;
+ }
+ }
+ catch
+ {
+ // Ensure that we still get a chance to resurrect this object, even if the callback throws an exception.
+ }
+
+ // Resurrect ourselves by re-registering for finalization.
+ if (!Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload())
+ {
+ GC.ReRegisterForFinalize(this);
+ }
+ }
+
+ #endregion
+ }
+
+
+#if FEATURE_CORECLR
+ internal sealed class PinnableBufferCacheEventSource
+ {
+ public static readonly PinnableBufferCacheEventSource Log = new PinnableBufferCacheEventSource();
+
+ public bool IsEnabled() { return false; }
+ public void DebugMessage(string message) {}
+ public void DebugMessage1(string message, long value) {}
+ public void DebugMessage2(string message, long value1, long value2) {}
+ public void DebugMessage3(string message, long value1, long value2, long value3) {}
+ public void Create(string cacheName) {}
+ public void AllocateBuffer(string cacheName, ulong objectId, int objectHash, int objectGen, int freeCountAfter) {}
+ public void AllocateBufferFromNotGen2(string cacheName, int notGen2CountAfter) {}
+ public void AllocateBufferCreatingNewBuffers(string cacheName, int totalBuffsBefore, int objectCount) {}
+ 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 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) {}
+ public void TrimExperiment(string cacheName, int totalBuffs, int freeListCount, int numTrimTrial) {}
+ public void TrimFreeSizeOK(string cacheName, int totalBuffs, int freeListCount) {}
+ public void TrimFlush(string cacheName, int totalBuffs, int freeListCount, int notGen2CountBefore) {}
+ public void AgePendingBuffersResults(string cacheName, int promotedToFreeListCount, int heldBackCount) {}
+ public void WalkFreeListResult(string cacheName, int freeListCount, int gen0BuffersInFreeList) {}
+
+ static internal ulong AddressOf(object obj)
+ {
+ return 0;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ static internal unsafe long AddressOfObject(byte[] array)
+ {
+ return 0;
+ }
+ }
+#else
+ /// <summary>
+ /// PinnableBufferCacheEventSource is a private eventSource that we are using to
+ /// debug and monitor the effectiveness of PinnableBufferCache
+ /// </summary>
+#if PINNABLEBUFFERCACHE_MSCORLIB
+ [EventSource(Name = "Microsoft-DotNETRuntime-PinnableBufferCache")]
+#else
+ [EventSource(Name = "Microsoft-DotNETRuntime-PinnableBufferCache-System")]
+#endif
+ internal sealed class PinnableBufferCacheEventSource : EventSource
+ {
+ public static readonly PinnableBufferCacheEventSource Log = new PinnableBufferCacheEventSource();
+
+ [Event(1, Level = EventLevel.Verbose)]
+ public void DebugMessage(string message) { if (IsEnabled()) WriteEvent(1, message); }
+ [Event(2, Level = EventLevel.Verbose)]
+ public void DebugMessage1(string message, long value) { if (IsEnabled()) WriteEvent(2, message, value); }
+ [Event(3, Level = EventLevel.Verbose)]
+ public void DebugMessage2(string message, long value1, long value2) { if (IsEnabled()) WriteEvent(3, message, value1, value2); }
+ [Event(18, Level = EventLevel.Verbose)]
+ public void DebugMessage3(string message, long value1, long value2, long value3) { if (IsEnabled()) WriteEvent(18, message, value1, value2, value3); }
+
+ [Event(4)]
+ public void Create(string cacheName) { if (IsEnabled()) WriteEvent(4, cacheName); }
+
+ [Event(5, Level = EventLevel.Verbose)]
+ public void AllocateBuffer(string cacheName, ulong objectId, int objectHash, int objectGen, int freeCountAfter) { if (IsEnabled()) WriteEvent(5, cacheName, objectId, objectHash, objectGen, freeCountAfter); }
+ [Event(6)]
+ public void AllocateBufferFromNotGen2(string cacheName, int notGen2CountAfter) { if (IsEnabled()) WriteEvent(6, cacheName, notGen2CountAfter); }
+ [Event(7)]
+ public void AllocateBufferCreatingNewBuffers(string cacheName, int totalBuffsBefore, int objectCount) { if (IsEnabled()) WriteEvent(7, cacheName, totalBuffsBefore, objectCount); }
+ [Event(8)]
+ public void AllocateBufferAged(string cacheName, int agedCount) { if (IsEnabled()) WriteEvent(8, cacheName, agedCount); }
+ [Event(9)]
+ public void AllocateBufferFreeListEmpty(string cacheName, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(9, cacheName, notGen2CountBefore); }
+
+ [Event(10, Level = EventLevel.Verbose)]
+ public void FreeBuffer(string cacheName, ulong objectId, int objectHash, int freeCountBefore) { if (IsEnabled()) WriteEvent(10, cacheName, objectId, objectHash, freeCountBefore); }
+ [Event(11)]
+ public void FreeBufferStillTooYoung(string cacheName, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(11, cacheName, notGen2CountBefore); }
+
+ [Event(13)]
+ public void TrimCheck(string cacheName, int totalBuffs, bool neededMoreThanFreeList, int deltaMSec) { if (IsEnabled()) WriteEvent(13, cacheName, totalBuffs, neededMoreThanFreeList, deltaMSec); }
+ [Event(14)]
+ public void TrimFree(string cacheName, int totalBuffs, int freeListCount, int toBeFreed) { if (IsEnabled()) WriteEvent(14, cacheName, totalBuffs, freeListCount, toBeFreed); }
+ [Event(15)]
+ public void TrimExperiment(string cacheName, int totalBuffs, int freeListCount, int numTrimTrial) { if (IsEnabled()) WriteEvent(15, cacheName, totalBuffs, freeListCount, numTrimTrial); }
+ [Event(16)]
+ public void TrimFreeSizeOK(string cacheName, int totalBuffs, int freeListCount) { if (IsEnabled()) WriteEvent(16, cacheName, totalBuffs, freeListCount); }
+ [Event(17)]
+ public void TrimFlush(string cacheName, int totalBuffs, int freeListCount, int notGen2CountBefore) { if (IsEnabled()) WriteEvent(17, cacheName, totalBuffs, freeListCount, notGen2CountBefore); }
+ [Event(20)]
+ 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); }
+
+
+ static internal ulong AddressOf(object obj)
+ {
+ var asByteArray = obj as byte[];
+ if (asByteArray != null)
+ return (ulong)AddressOfByteArray(asByteArray);
+ return 0;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ static internal unsafe long AddressOfByteArray(byte[] array)
+ {
+ if (array == null)
+ return 0;
+ fixed (byte* ptr = array)
+ return (long)(ptr - 2 * sizeof(void*));
+ }
+ }
+#endif
+}
diff --git a/src/mscorlib/Common/Preprocessed/AssemblyRefs.g.cs b/src/mscorlib/Common/Preprocessed/AssemblyRefs.g.cs
new file mode 100644
index 0000000000..24a1866a5d
--- /dev/null
+++ b/src/mscorlib/Common/Preprocessed/AssemblyRefs.g.cs
@@ -0,0 +1,1082 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
+
+/*
+ * Assembly attributes. This file is preprocessed to generate a .cs file
+ * with the correct information. The original lives in VBL\Tools\DevDiv\
+ */
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+/**
+ * Version strings for Frameworks.
+ *
+ */
+
+//
+// Insert just the #defines in winver.h, so that the
+// C# compiler can include this file after macro preprocessing.
+//
+
+
+
+
+
+
+
+
+
+// #line 21 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+//
+// winver.h is bad for rc.exe & csc.exe whereas verrsrc.h does not have an include guard
+// yet defines the same structure twice if RC_INVOKED is not #defined.
+// Temporarily enable RC_INVOKED protection around the #include.
+//
+
+
+
+
+
+
+// #line 1 "c:\\program files (x86)\\windows kits\\8.1\\include\\um\\verrsrc.h"
+// #line 1 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+/*
+
+
+
+Module Name:
+
+ winapifamily.h
+
+Abstract:
+
+ Master include file for API family partitioning.
+
+*/
+
+
+
+
+
+// #pragma once
+// #line 21 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+
+/*
+ * When compiling C and C++ code using SDK header files, the development
+ * environment can specify a target platform by #define-ing the
+ * pre-processor symbol WINAPI_FAMILY to one of the following values.
+ * Each FAMILY value denotes an application family for which a different
+ * subset of the total set of header-file-defined APIs are available.
+ * Setting the WINAPI_FAMILY value will effectively hide from the
+ * editing and compilation environments the existence of APIs that
+ * are not applicable to the family of applications targeting a
+ * specific platform.
+ */
+
+/*
+ * The WINAPI_FAMILY values of 0 and 1 are reserved to ensure that
+ * an error will occur if WINAPI_FAMILY is set to any
+ * WINAPI_PARTITION value (which must be 0 or 1, see below).
+ */
+
+
+
+/* The value of WINAPI_FAMILY_DESKTOP_APP may change in future SDKs. */
+/* Additional WINAPI_FAMILY values may be defined in future SDKs. */
+
+/*
+ * For compatibility with Windows 8 header files, the following
+ * synonym for WINAPI_FAMILY_PC_APP is temporarily #define'd.
+ * Use of this symbol should be considered deprecated.
+ */
+
+
+/*
+ * If no WINAPI_FAMILY value is specified, then all APIs available to
+ * Windows desktop applications are exposed.
+ */
+
+
+// #line 59 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+
+/*
+ * API PARTITONs are part of an indirection mechanism for mapping between
+ * individual APIs and the FAMILYs to which they apply.
+ * Each PARTITION is a category or subset of named APIs. PARTITIONs
+ * are permitted to have overlapping membership -- some single API
+ * might be part of more than one PARTITION. In support of new
+ * FAMILYs that might be added in future SDKs, any single current
+ * PARTITION might in that future SDK be split into two or more new PARTITIONs.
+ * Accordingly, application developers should avoid taking dependencies on
+ * PARTITION names; developers' only dependency upon the symbols defined
+ * in this file should be their reliance on the WINAPI_FAMILY names and values.
+ */
+
+/*
+ * Current PARTITIONS are each #undef'ed below, and then will be #define-ed
+ * to be either 1 or 0 or depending on the active WINAPI_FAMILY.
+ */
+
+
+
+
+
+
+
+/*
+ * The mapping between families and partitions is summarized here.
+ * An X indicates that the given partition is active for the given
+ * platform/family.
+ *
+ * +---------------+
+ * | *Partition* |
+ * +---+---+---+---+
+ * | | | | P |
+ * | | | | H |
+ * | D | | | O |
+ * | E | | P | N |
+ * | S | | C | E |
+ * | K | | _ | _ |
+ * | T | A | A | A |
+ * +-------------------------+-+ O | P | P | P |
+ * | *Platform/Family* \| P | P | P | P |
+ * +---------------------------+---+---+---+---+
+ * | WINAPI_FAMILY_DESKTOP_APP | X | X | X | |
+ * +---------------------------+---+---+---+---+
+ * | WINAPI_FAMILY_PC_APP | | X | X | |
+ * +---------------------------+---+---+---+---+
+ * | WINAPI_FAMILY_PHONE_APP | | X | | X |
+ * +---------------------------+---+---+---+---+
+ *
+ * The table above is encoded in the following expressions,
+ * each of which evaluates to 1 or 0.
+ *
+ * Whenever a new family is added, all of these expressions
+ * need to be reconsidered.
+ */
+
+
+// #line 118 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+
+
+
+
+
+/*
+ * For compatibility with Windows Phone 8 header files, the following
+ * synonym for WINAPI_PARTITION_PHONE_APP is temporarily #define'd.
+ * Use of this symbol should be regarded as deprecated.
+ */
+
+
+/*
+ * Header files use the WINAPI_FAMILY_PARTITION macro to assign one or
+ * more declarations to some group of partitions. The macro chooses
+ * whether the preprocessor will emit or omit a sequence of declarations
+ * bracketed by an #if/#endif pair. All header file references to the
+ * WINAPI_PARTITION_* values should be in the form of occurrences of
+ * WINAPI_FAMILY_PARTITION(...).
+ *
+ * For example, the following usage of WINAPI_FAMILY_PARTITION identifies
+ * a sequence of declarations that are part of both the Windows Desktop
+ * Partition and the Windows-Phone-Specific Store Partition:
+ *
+ * #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
+ * ...
+ * #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_PHONE_APP)
+ *
+ * The comment on the closing #endif allow tools as well as people to find the
+ * matching #ifdef properly.
+ *
+ * Usages of WINAPI_FAMILY_PARTITION may be combined, when the partitition definitions are
+ * related. In particular one might use declarations like
+ *
+ * #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
+ *
+ * or
+ *
+ * #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
+ *
+ * Direct references to WINAPI_PARTITION_ values (eg #if !WINAPI_FAMILY_PARTITION_...)
+ * should not be used.
+ */
+
+
+/*
+ * Macro used to #define or typedef a symbol used for selective deprecation
+ * of individual methods of a COM interfaces that are otherwise available
+ * for a given set of partitions.
+ */
+
+
+/*
+ * For compatibility with Windows 8 header files, the following
+ * symbol is temporarily conditionally #define'd. Additional symbols
+ * like this should be not defined in winapifamily.h, but rather should be
+ * introduced locally to the header files of the component that needs them.
+ */
+
+
+// #line 179 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+
+// #line 181 "c:\\program files (x86)\\windows kits\\8.1\\include\\shared\\winapifamily.h"
+// #line 2 "c:\\program files (x86)\\windows kits\\8.1\\include\\um\\verrsrc.h"
+
+/****************************************************************************
+** *
+* verrsrc.h - Version Resource definitions *
+* *
+* Include file declaring version resources in rc files *
+* *
+* *
+* *
+\*****************************************************************************/
+
+// #pragma region Application Family
+
+
+/* ----- Symbols ----- */
+
+
+
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+
+
+
+
+// #line 27 "c:\\program files (x86)\\windows kits\\8.1\\include\\um\\verrsrc.h"
+
+
+
+/* ----- VS_VERSION.dwFileFlags ----- */
+
+
+
+
+
+
+
+/* ----- VS_VERSION.dwFileOS ----- */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ----- VS_VERSION.dwFileType ----- */
+
+
+
+
+
+
+
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_DRV ----- */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/* ----- VS_VERSION.dwFileSubtype for VFT_WINDOWS_FONT ----- */
+
+
+
+
+// #line 88 "c:\\program files (x86)\\windows kits\\8.1\\include\\um\\verrsrc.h"
+// // #pragma region
+
+// #pragma region Desktop Family
+
+
+/* ----- VerFindFile() flags ----- */
+
+
+
+
+
+
+/* ----- VerInstallFile() flags ----- */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 171 "c:\\program files (x86)\\windows kits\\8.1\\include\\um\\verrsrc.h"
+// #pragma region
+
+// #line 37 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+//
+// Include the definitions for rmj, rmm, rup, rpt
+//
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+
+// #line 6 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\version.h"
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\ndpversion_generated.h"
+
+
+
+
+// #line 6 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\ndpversion_generated.h"
+
+
+
+
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\buildnumber.h"
+
+
+
+
+// #line 6 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\buildnumber.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 12 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\ndpversion_generated.h"
+// #line 2 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\version.h"
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 8 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\asm_version.h"
+
+
+
+
+
+
+
+
+
+
+
+// #line 13 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\asm_version.h"
+
+
+
+
+
+// #line 19 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\asm_version.h"
+
+// #line 12 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+// #line 13 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 161 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+
+
+// #line 167 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+
+
+// #line 173 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+
+
+
+
+
+// #line 180 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\product_version.h"
+
+// #line 48 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+/*
+ * Product version, name and copyright
+ */
+
+// #line 1 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+
+
+
+// #line 6 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+
+
+// #line 10 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+
+
+
+// #line 15 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+// #line 16 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+// The following copyright is intended for display in the Windows Explorer property box for a DLL or EXE
+// See \\lca\pdm\TMGUIDE\Copyright\Crt_Tmk_Notices.xls for copyright guidelines
+//
+
+
+
+
+// #line 25 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+
+
+// #line 29 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+
+
+
+
+
+
+// #line 37 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+// #line 38 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+
+// VSWhidbey #495749
+// Note: The following legal copyright is intended for situations where the copyright symbol doesn't display
+// properly. For example, the following copyright should be displayed as part of the logo for DOS command-line
+// applications. If you change the format or wording of the following copyright, you should apply the same
+// change to fxresstrings.txt (for managed applications).
+
+
+
+// #line 48 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxverstrings.h"
+// #line 54 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+/*
+ * File version, names, description.
+ */
+
+// FX_VER_INTERNALNAME_STR is passed in by the build environment.
+
+
+
+
+
+
+
+// FX_VER_FILEDESCRIPTION_STR is defined in RC files that include fxver.h
+
+
+
+// #line 72 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+// #line 78 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+// #line 85 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+//URT_VFT passed in by the build environment.
+
+
+
+
+
+
+
+/* default is nodebug */
+
+
+
+
+// #line 102 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// DEBUG flag is set for debug build, not set for retail build
+// #if defined(DEBUG) || defined(_DEBUG)
+// #define VER_DEBUG VS_FF_DEBUG
+// #else // DEBUG
+// #define VER_DEBUG 0
+// #endif // DEBUG
+
+
+/* default is prerelease */
+
+
+// #line 115 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// #line 117 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// PRERELEASE flag is always set unless building SHIP version
+// #ifndef _SHIP
+// #define VER_PRERELEASE VS_FF_PRERELEASE
+// #else
+// #define VER_PRERELEASE 0
+// #endif // _SHIP
+
+
+
+// #line 128 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// #line 130 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// PRIVATEBUILD flag is set if not built by build lab
+// #ifndef _VSBUILD
+// #define VER_PRIVATEBUILD VS_FF_PRIVATEBUILD
+// #else // _VSBUILD
+// #define VER_PRIVATEBUILD 0
+// #endif // _VSBUILD
+
+
+
+// #line 141 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// #line 143 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 164 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+
+
+
+// #line 174 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+// #line 180 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+
+
+// #line 189 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+// #line 193 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 248 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// #line 250 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+
+
+// #line 254 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+
+// #line 256 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\include\\fxver.h"
+// #line 24 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
+
+internal static class FXAssembly {
+ internal const string Version = "4.0.0.0";
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// #line 44 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
+
+internal static class ThisAssembly {
+ internal const string Title = "System.Private.CoreLib.dll";
+ internal const string Description = "System.Private.CoreLib.dll";
+ internal const string DefaultAlias = "System.Private.CoreLib.dll";
+ internal const string Copyright = "\u00A9 Microsoft Corporation. All rights reserved.";
+ internal const string Version = "4.0.0.0";
+ internal const string InformationalVersion = "4.0.22306.0";
+ internal const string DailyBuildNumberStr = "22306";
+ internal const string BuildRevisionStr = "0";
+ internal const int DailyBuildNumber = 22306;
+}
+
+
+#pragma warning disable 436
+internal static class AssemblyRef {
+ internal const string EcmaPublicKey = "b77a5c561934e089";
+ internal const string EcmaPublicKeyToken = "b77a5c561934e089";
+ internal const string EcmaPublicKeyFull = "00000000000000000400000000000000";
+
+ internal const string SilverlightPublicKey = "31bf3856ad364e35";
+ internal const string SilverlightPublicKeyToken = "31bf3856ad364e35";
+ internal const string SilverlightPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
+
+ internal const string SilverlightPlatformPublicKey = "7cec85d7bea7798e";
+ internal const string SilverlightPlatformPublicKeyToken = "7cec85d7bea7798e";
+ internal const string SilverlightPlatformPublicKeyFull = "00240000048000009400000006020000002400005253413100040000010001008D56C76F9E8649383049F383C44BE0EC204181822A6C31CF5EB7EF486944D032188EA1D3920763712CCB12D75FB77E9811149E6148E5D32FBAAB37611C1878DDC19E20EF135D0CB2CFF2BFEC3D115810C3D9069638FE4BE215DBF795861920E5AB6F7DB2E2CEEF136AC23D5DD2BF031700AEC232F6C6B1C785B4305C123B37AB";
+
+
+ internal const string PlatformPublicKey = SilverlightPlatformPublicKey;
+ internal const string PlatformPublicKeyToken = SilverlightPlatformPublicKeyToken;
+ internal const string PlatformPublicKeyFull = SilverlightPlatformPublicKeyFull;
+
+
+
+
+// #line 81 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
+
+ internal const string Mscorlib = "mscorlib, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + PlatformPublicKey;
+ internal const string SystemData = "System.Data, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemDataOracleClient = "System.Data.OracleClient, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string System = "System, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + PlatformPublicKey;
+ internal const string SystemCore = "System.Core, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + PlatformPublicKey;
+ internal const string SystemNumerics = "System.Numerics, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + PlatformPublicKey;
+ internal const string SystemRuntimeRemoting = "System.Runtime.Remoting, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemThreadingTasksDataflow = "System.Threading.Tasks.Dataflow, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + PlatformPublicKey;
+ internal const string SystemWindowsForms = "System.Windows.Forms, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemXml = "System.Xml, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+
+ internal const string MicrosoftPublicKey = "b03f5f7f11d50a3a";
+ internal const string MicrosoftPublicKeyToken = "b03f5f7f11d50a3a";
+ internal const string MicrosoftPublicKeyFull = "002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293";
+
+ internal const string SharedLibPublicKey = "31bf3856ad364e35";
+ internal const string SharedLibPublicKeyToken = "31bf3856ad364e35";
+ internal const string SharedLibPublicKeyFull = "0024000004800000940000000602000000240000525341310004000001000100B5FC90E7027F67871E773A8FDE8938C81DD402BA65B9201D60593E96C492651E889CC13F1415EBB53FAC1131AE0BD333C5EE6021672D9718EA31A8AEBD0DA0072F25D87DBA6FC90FFD598ED4DA35E44C398C454307E8E33B8426143DAEC9F596836F97C8F74750E5975C64E2189F45DEF46B2A2B1247ADC3652BF5C308055DA9";
+
+ internal const string SystemComponentModelDataAnnotations = "System.ComponentModel.DataAnnotations, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemConfiguration = "System.Configuration, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemConfigurationInstall = "System.Configuration.Install, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemDeployment = "System.Deployment, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemDesign = "System.Design, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemDirectoryServices = "System.DirectoryServices, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemDrawingDesign = "System.Drawing.Design, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemDrawing = "System.Drawing, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemEnterpriseServices = "System.EnterpriseServices, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemManagement = "System.Management, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemMessaging = "System.Messaging, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemNetHttp = "System.Net.Http, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemNetHttpWebRequest = "System.Net.Http.WebRequest, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemRuntimeSerializationFormattersSoap = "System.Runtime.Serialization.Formatters.Soap, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemRuntimeWindowsRuntime = "System.Runtime.WindowsRuntime, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemRuntimeWindowsRuntimeUIXaml = "System.Runtime.WindowsRuntimeUIXaml, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemSecurity = "System.Security, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemServiceModelWeb = "System.ServiceModel.Web, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemServiceProcess = "System.ServiceProcess, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemWeb = "System.Web, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemWebAbstractions = "System.Web.Abstractions, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebDynamicData = "System.Web.DynamicData, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebDynamicDataDesign = "System.Web.DynamicData.Design, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebEntityDesign = "System.Web.Entity.Design, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + EcmaPublicKey;
+ internal const string SystemWebExtensions = "System.Web.Extensions, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebExtensionsDesign = "System.Web.Extensions.Design, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebMobile = "System.Web.Mobile, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemWebRegularExpressions = "System.Web.RegularExpressions, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string SystemWebRouting = "System.Web.Routing, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+ internal const string SystemWebServices = "System.Web.Services, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+
+ internal const string WindowsBase = "WindowsBase, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + SharedLibPublicKey;
+
+ internal const string MicrosoftVisualStudio = "Microsoft.VisualStudio, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string MicrosoftVisualStudioWindowsForms = "Microsoft.VisualStudio.Windows.Forms, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string VJSharpCodeProvider = "VJSharpCodeProvider, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+
+ internal const string ASPBrowserCapsPublicKey = "b7bd7678b977bd8f";
+ internal const string ASPBrowserCapsFactory = "ASP.BrowserCapsFactory, Version=" + FXAssembly.Version + ", Culture=neutral, PublicKeyToken=" + ASPBrowserCapsPublicKey;
+
+
+ // We do not want these sitting in non-VS specific files. If you need them,
+ // add this line to sources:
+ // C_DEFINES=$(C_DEFINES) /DINCLUDE_VSREFS
+ //
+ // M.VS.dll and M.VSDesigner.dll should also be included here, but it
+ // turns out that everyone, from Data, to XSP to Winforms to diagnostics
+ // has thrown some designer-specific code into M.VS.dll or M.VSDesigner.dll.
+ //
+
+
+
+
+
+
+// #line 157 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
+
+ // VS Provided Assemblies... we can't strong bind to these, they
+ // update their assembly versions too often
+ //
+ internal const string MicrosoftVSDesigner = "Microsoft.VSDesigner, Version=10.0.0.0, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string MicrosoftVisualStudioWeb = "Microsoft.VisualStudio.Web, Version=10.0.0.0, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string MicrosoftWebDesign = "Microsoft.Web.Design.Client, Version=10.0.0.0, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string MicrosoftVSDesignerMobile = "Microsoft.VSDesigner.Mobile, Version=8.0.0.0, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ internal const string MicrosoftJScript = "Microsoft.JScript, Version=8.0.0.0, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+
+ //internal const string MicrosoftVSDesigner = "Microsoft.VSDesigner, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+ //internal const string MicrosoftJScript = "Microsoft.JScript, Culture=neutral, PublicKeyToken=" + MicrosoftPublicKey;
+}
+#pragma warning restore 436
+// #line 172 "d:\\projectk_2\\src\\ndp\\clr\\src\\bcl.oss\\open\\src\\common\\assemblyrefs.cspp"
diff --git a/src/mscorlib/GenerateCompilerResponseFile.targets b/src/mscorlib/GenerateCompilerResponseFile.targets
new file mode 100644
index 0000000000..ed9136ffc6
--- /dev/null
+++ b/src/mscorlib/GenerateCompilerResponseFile.targets
@@ -0,0 +1,22 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+
+ <PropertyGroup>
+ <CompileDependsOn>GenerateCompilerResponseFile;$(CompileDependsOn)</CompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="GenerateCompilerResponseFile">
+ <Message Text="Generating module name response file: $(IntermediateOutputPath)\moduleName.$(AssemblyName).rsp" />
+
+ <!-- We need to set the runtimemetadataversion -->
+ <WriteLinesToFile File="$(IntermediateOutputPath)\moduleName.$(AssemblyName).rsp"
+ Lines="/runtimemetadataversion:v4.0.30319"
+ Overwrite="true" />
+
+ <ItemGroup>
+ <Clean Include="$(IntermediateOutputPath)\moduleName.$(AssemblyName).rsp" />
+ </ItemGroup>
+ <PropertyGroup>
+ <CompilerResponseFile>$(IntermediateOutputPath)\moduleName.$(AssemblyName).rsp;$(CompilerResponseFile)</CompilerResponseFile>
+ </PropertyGroup>
+ </Target>
+</Project> \ No newline at end of file
diff --git a/src/mscorlib/GenerateSplitStringResources.targets b/src/mscorlib/GenerateSplitStringResources.targets
new file mode 100644
index 0000000000..88e01cb612
--- /dev/null
+++ b/src/mscorlib/GenerateSplitStringResources.targets
@@ -0,0 +1,42 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <PrepareResourcesDependsOn>GenerateSplitStringResources;$(PrepareResourcesDependsOn)</PrepareResourcesDependsOn>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <PreprocessFileTaskAsssemblyPath Condition="'$(PreprocessFileTaskAsssemblyPath)' == ''">$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll</PreprocessFileTaskAsssemblyPath>
+ </PropertyGroup>
+
+ <UsingTask TaskName="PreprocessFile" AssemblyFile="$(PreprocessFileTaskAsssemblyPath)" />
+
+ <Target Name="GenerateSplitStringResources"
+ Inputs="@(SplitTextStringResource)"
+ Outputs="@(SplitTextStringResource->'$(IntermediateOutputPath)%(Filename).txt')">
+
+ <ItemGroup>
+ <Internal_ResGenDefines Remove="" />
+ <Internal_ResGenDefines Include="INCLUDE_DEBUG" />
+ <Internal_ResGenDefines Include="INCLUDE_RUNTIME" />
+ <Internal_ResGenDefines Include="%(SplitTextStringResource.ResGenDefines)" />
+ </ItemGroup>
+
+ <PreprocessFile SourceFile="%(SplitTextStringResource.Identity)" OutputFile="$(IntermediateOutputPath)%(SplitTextStringResource.Filename).txt" Defines="@(Internal_ResGenDefines)" />
+
+ <GenerateResource Sources="$(IntermediateOutputPath)%(SplitTextStringResource.Filename).txt"
+ OutputResources="$(IntermediateOutputPath)%(SplitTextStringResource.Filename).resources"
+ ExecuteAsTool="false" />
+
+ <ItemGroup>
+ <EmbeddedResource Include="@(SplitTextStringResource->'$(IntermediateOutputPath)%(Filename).resources')">
+ <WithCulture>false</WithCulture>
+ <ManifestResourceName>%(Filename)</ManifestResourceName>
+ </EmbeddedResource>
+ <Clean Include="$(IntermediateOutputPath)%(SplitTextStringResource.Filename).txt" />
+ <Clean Include="$(IntermediateOutputPath)%(SplitTextStringResource.Filename).resources" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Internal_ResGenDefines Remove="" />
+ </ItemGroup>
+ </Target>
+</Project> \ No newline at end of file
diff --git a/src/mscorlib/System.Private.CoreLib.csproj b/src/mscorlib/System.Private.CoreLib.csproj
new file mode 100644
index 0000000000..c14ce422fb
--- /dev/null
+++ b/src/mscorlib/System.Private.CoreLib.csproj
@@ -0,0 +1,226 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+
+ <!-- Include common build properties -->
+ <Import Project="..\..\dir.props" />
+
+ <!-- Compilation options -->
+ <PropertyGroup>
+ <AvailablePlatforms>amd64,x86,arm,arm-softfp,arm64</AvailablePlatforms>
+ <Configuration Condition=" '$(Configuration)' == '' ">$(BuildType)</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">$(BuildArch)</Platform>
+ <!-- The CLR properties use amd64 as their platform string, we want to keep in sync with those, so set Platform appropriately,
+ though still use the 'x64' output path (see use of BuildArch below) -->
+ <Platform Condition=" '$(Platform)' == 'x64' ">amd64</Platform>
+ <Platform Condition=" '$(Platform)' == 'arm-softfp' ">arm</Platform>
+ <ProjectGuid>{3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}</ProjectGuid>
+
+ <OutputType>Library</OutputType>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+
+ <!-- This prevents the default MsBuild targets from referencing System.Core.dll -->
+ <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
+ <!-- These prevent the default MsBuild targets from referencing System.dll and mscorlib.dll -->
+ <NoStdLib>true</NoStdLib>
+ <NoCompilerStandardLib>true</NoCompilerStandardLib>
+
+ <SubsystemVersion>6.00</SubsystemVersion>
+ <UTF8OutPut>true</UTF8OutPut>
+ <HighEntropyVA>true</HighEntropyVA>
+ <ErrorReport>prompt</ErrorReport>
+ <CLSCompliant>true</CLSCompliant>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <WarningsNotAsErrors>$(WarningsNotAsErrors);618</WarningsNotAsErrors>
+ <NoWarn>649,3019,414,169,3015</NoWarn>
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
+
+ <BclRewriterModelFile>$(MSBuildThisFileDirectory)model.xml</BclRewriterModelFile>
+
+ <SignAssembly>true</SignAssembly>
+ <DelaySign>true</DelaySign>
+
+ <DefineConstants>$(DefineConstants);_USE_NLS_PLUS_TABLE;RESOURCE_SATELLITE_CONFIG;INSIDE_CLR;CODE_ANALYSIS_BASELINE</DefineConstants>
+ </PropertyGroup>
+
+ <!-- Add Serviceable attribute to the project's metadata -->
+ <ItemGroup>
+ <AssemblyMetadata Include="Serviceable">
+ <Value>True</Value>
+ </AssemblyMetadata>
+ </ItemGroup>
+
+ <!-- Platform specific properties -->
+ <PropertyGroup Condition="'$(Platform)' == 'amd64'">
+ <PlatformTarget>x64</PlatformTarget>
+ <Prefer32Bit>false</Prefer32Bit>
+ <BaseAddress>0x180000000</BaseAddress>
+ <DefineConstants>BIT64;AMD64;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Platform)' == 'x86'">
+ <PlatformTarget>x86</PlatformTarget>
+ <BaseAddress>0x10000000</BaseAddress>
+ <DefineConstants>BIT32;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Platform)' == 'arm'">
+ <PlatformTarget>arm</PlatformTarget>
+ <DefineConstants>BIT32;ARM;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Platform)' == 'arm64'">
+ <PlatformTarget>AnyCPU</PlatformTarget>
+ <DefineConstants>BIT64;ARM64;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+
+ <!-- Configuration specific properties -->
+ <PropertyGroup Condition="'$(Configuration)' == 'Debug' or '$(Configuration)' == 'Checked'">
+ <DebugSymbols>true</DebugSymbols>
+ <Optimize Condition="'$(Optimize)' == '' and '$(Configuration)' == 'Debug'">false</Optimize>
+ <Optimize Condition="'$(Optimize)' == '' and '$(Configuration)' == 'Checked'">true</Optimize>
+ <DebugType>full</DebugType>
+ <DefineConstants>DBG;_DEBUG;_LOGGING;DEBUG;TRACE;$(DefineConstants)</DefineConstants>
+ <DefineConstants Condition="'$(Platform)' == 'x86' or '$(Platform)' == 'amd64'">CODE_ANALYSIS;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)' == 'Release'">
+ <DebugSymbols>true</DebugSymbols>
+ <Optimize Condition="'$(Optimize)' == ''">true</Optimize>
+ <DebugType>pdbOnly</DebugType>
+ <DefineConstants>TRACE;$(DefineConstants)</DefineConstants>
+ </PropertyGroup>
+
+ <!-- Roslyn does not support writing PDBs on Unix -->
+ <PropertyGroup Condition="'$(OsEnvironment)' == 'Unix'">
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>none</DebugType>
+ </PropertyGroup>
+
+ <!-- Assembly attributes -->
+ <PropertyGroup>
+ <AssemblyName>System.Private.CoreLib</AssemblyName>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ <MajorVersion>4</MajorVersion>
+ <MinorVersion>6</MinorVersion>
+ </PropertyGroup>
+ <ItemGroup>
+ <AssemblyInfoLines Include="[assembly: System.Resources.SatelliteContractVersion(&quot;$(AssemblyVersion)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly: System.Security.AllowPartiallyTrustedCallers]" />
+ <AssemblyInfoLines Include="[assembly: System.Runtime.InteropServices.ComVisible(false)]" />
+ <AssemblyInfoLines Include="[assembly: System.Resources.NeutralResourcesLanguage(&quot;en-US&quot;)]" />
+ </ItemGroup>
+
+ <!--
+ Helper Paths
+ -->
+ <PropertyGroup>
+ <PostProcessingToolsPath Condition="'$(PostProcessingToolsPath)'==''">$(MSBuildThisFileDirectory)Tools\PostProcessingTools.targets</PostProcessingToolsPath>
+ <CommonPath>$(MSBuildThisFileDirectory)Common</CommonPath>
+ <BclSourcesRoot>$(MSBuildThisFileDirectory)src</BclSourcesRoot>
+ <CoreFxSourcesRoot>$(MSBuildThisFileDirectory)corefx</CoreFxSourcesRoot>
+ <MscorlibDir>$(MSBuildThisFileDirectory)</MscorlibDir>
+ <NlpObjDir>$(BclSourcesRoot)\System\Globalization\Tables</NlpObjDir>
+ </PropertyGroup>
+
+ <!-- Output paths -->
+ <PropertyGroup>
+ <BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)' == ''">$(RootBinDir)obj</BaseIntermediateOutputPath>
+ <IntermediateOutputPath Condition="'$(IntermediateOutputPath)' == ''">$(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)</IntermediateOutputPath>
+ <OutputPath Condition="'$(OutputPath)' == ''">$(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)</OutputPath>
+ <FinalOutputPath Condition="'$(FinalOutputPath)' == ''">$(BinDir)</FinalOutputPath>
+ </PropertyGroup>
+
+ <!-- Msbuild variables needed to get CoreCLR features to be set properly. -->
+ <PropertyGroup>
+ <ClrProduct>core_clr</ClrProduct>
+ <BuildForCoreSystem>true</BuildForCoreSystem>
+
+ <!-- These are needed by BCLRewriter -->
+ <_BuildType Condition="'$(Configuration)' == 'Debug'">chk</_BuildType>
+ <_BuildType Condition="'$(Configuration)' == 'Checked'">chk</_BuildType>
+ <_BuildType Condition="'$(Configuration)' == 'Release'">ret</_BuildType>
+
+ <!-- These are needed to make sure we have the right set of defines -->
+ <TargetArch Condition="'$(Platform)'=='x86'">i386</TargetArch>
+ <TargetArch Condition="'$(Platform)'!='x86'">$(Platform)</TargetArch>
+ </PropertyGroup>
+
+ <!-- CLR Features -->
+ <Import Project="$(MSBuildThisFileDirectory)..\..\clr.coreclr.props" />
+ <Import Project="$(MSBuildThisFileDirectory)..\..\clr.defines.targets" />
+
+ <!-- Sources -->
+ <Import Project="$(MSBuildThisFileDirectory)\mscorlib.shared.sources.props" />
+
+ <!-- Include additional sources shared files in the compilation -->
+ <ItemGroup>
+ <!-- These are files are preprocessed -->
+ <MscorlibSources Include="$(CommonPath)\Preprocessed\AssemblyRefs.g.cs" />
+
+ <!-- These files are shared with other framework components and don't live the same folder as the rest of them-->
+ <MscorlibSources Include="$(CommonPath)\PinnableBufferCache.cs" />
+
+ <!-- Include Internals visible to file in the compilation -->
+ <MscorlibSources Include="$(BclSourcesRoot)\mscorlib.Friends.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <!-- We want the sources to show up nicely in VS-->
+ <Compile Include="@(MscorlibSources)">
+ </Compile>
+ </ItemGroup>
+
+ <!-- Resources -->
+ <ItemGroup>
+ <SplitTextStringResource Include="$(BclSourcesRoot)\System.Private.CoreLib.txt">
+ <ResFile>System.Private.CoreLib</ResFile>
+ <ResGenDefines>$(DefineConstants)</ResGenDefines>
+ </SplitTextStringResource>
+ </ItemGroup>
+
+ <PropertyGroup>
+ <CheckCDefines Condition="'$(CheckCDefines)'==''">true</CheckCDefines>
+ </PropertyGroup>
+
+ <Target Name="CDefineChecker" BeforeTargets="Build" Condition="'$(CheckCDefines)'=='true'">
+ <!-- Compiler Definition Verification -->
+ <Message Importance="High" Text="============" />
+ <PropertyGroup>
+ <IgnoreDefineConstants>FEATURE_IMPLICIT_TLS;FEATURE_HIJACK</IgnoreDefineConstants>
+ <CMakeDefinitionSaveFile>$(IntermediateOutputPath)\cmake.definitions</CMakeDefinitionSaveFile>
+ </PropertyGroup>
+ <Exec Command='python $(MSBuildThisFileDirectory)..\scripts\check-definitions.py "$(CMakeDefinitionSaveFile)" "$(DefineConstants)" "$(IgnoreDefineConstants)" ' />
+ <Message Importance="High" Text="============" />
+ </Target>
+
+ <ItemGroup>
+ <EmbeddedResource Include="$(NlpObjDir)\charinfo.nlp">
+ <LogicalName>charinfo.nlp</LogicalName>
+ </EmbeddedResource>
+ </ItemGroup>
+
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.Targets" />
+
+ <PropertyGroup>
+ <StrongNameSig>Silverlight</StrongNameSig>
+ </PropertyGroup>
+
+ <!-- Import signing tools -->
+ <Import Condition="Exists('$(ToolsDir)\sign.targets')" Project="$(ToolsDir)\sign.targets" />
+
+ <!-- Overwrite the key that we are going to use for signing -->
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)Tools\Signing\mscorlib.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+
+ <Import Project="$(MSBuildThisFileDirectory)Tools\Versioning\GenerateVersionInfo.targets"/>
+ <!-- Override versioning targets -->
+ <Import Condition="Exists('$(ToolsDir)versioning.targets')" Project="$(ToolsDir)versioning.targets" />
+
+ <PropertyGroup>
+ <!-- Use a different nativeresource file to avoid conflicts with mscorlib-->
+ <Win32Resource Condition="'$(GenerateNativeVersionInfo)'=='true'">$(IntermediateOutputPath)\System.Private.CoreLib.res</Win32Resource>
+ </PropertyGroup>
+
+ <Import Project="GenerateSplitStringResources.targets"/>
+ <Import Project="GenerateCompilerResponseFile.targets"/>
+ <Import Project="$(PostProcessingToolsPath)" />
+</Project>
diff --git a/src/mscorlib/System.Private.CoreLib.sln b/src/mscorlib/System.Private.CoreLib.sln
new file mode 100644
index 0000000000..4ab28af2d9
--- /dev/null
+++ b/src/mscorlib/System.Private.CoreLib.sln
@@ -0,0 +1,52 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.Private.CoreLib", "System.Private.CoreLib.csproj", "{3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Checked|amd64 = Checked|amd64
+ Checked|arm = Checked|arm
+ Checked|arm64 = Checked|arm64
+ Checked|x86 = Checked|x86
+ Debug|amd64 = Debug|amd64
+ Debug|arm = Debug|arm
+ Debug|arm64 = Debug|arm64
+ Debug|x86 = Debug|x86
+ Release|amd64 = Release|amd64
+ Release|arm = Release|arm
+ Release|arm64 = Release|arm64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|amd64.ActiveCfg = Checked|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|amd64.Build.0 = Checked|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|arm.ActiveCfg = Checked|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|arm.Build.0 = Checked|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|arm64.ActiveCfg = Checked|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|arm64.Build.0 = Checked|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|x86.ActiveCfg = Checked|x86
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Checked|x86.Build.0 = Checked|x86
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|amd64.ActiveCfg = Debug|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|amd64.Build.0 = Debug|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|arm.ActiveCfg = Debug|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|arm.Build.0 = Debug|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|arm64.ActiveCfg = Debug|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|arm64.Build.0 = Debug|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|x86.ActiveCfg = Debug|x86
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Debug|x86.Build.0 = Debug|x86
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|amd64.ActiveCfg = Release|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|amd64.Build.0 = Release|amd64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|arm.ActiveCfg = Release|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|arm.Build.0 = Release|arm
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|arm64.ActiveCfg = Release|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|arm64.Build.0 = Release|arm64
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|x86.ActiveCfg = Release|x86
+ {3DA06C3A-2E7B-4CB7-80ED-9B12916013F9}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/src/mscorlib/Tools/BclRewriter/BclRewriter.targets b/src/mscorlib/Tools/BclRewriter/BclRewriter.targets
new file mode 100644
index 0000000000..5515b000a7
--- /dev/null
+++ b/src/mscorlib/Tools/BclRewriter/BclRewriter.targets
@@ -0,0 +1,35 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+
+ <!-- ********************************************************************************************* -->
+ <!-- *** Task -->
+ <!-- ********************************************************************************************* -->
+
+ <PropertyGroup>
+ <BclRewriterModelFile Condition="'$(BclRewriterModelFile)'==''">$(MscorlibDir)model.xml</BclRewriterModelFile>
+ <BclRewriterWorkDir>$(IntermediateOutputPath)\BclRewriter</BclRewriterWorkDir>
+ <BclRewriterSymbolOutput>$(IntermediateOutputPath)\BclRewriter\$(TargetName).pdb</BclRewriterSymbolOutput>
+ <BclRewriterOutput>$(IntermediateOutputPath)\BclRewriter\$(TargetName)$(TargetExt)</BclRewriterOutput>
+ <TargetPath>$(BclRewriterOutput)</TargetPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <RewrittenAssembly Include="$(BclRewriterOutput)" />
+ </ItemGroup>
+
+ <Target Name="RewriteWithBclRewriter"
+ Inputs="$(BclRewriterModelFile);@(AnnotatedAssembly)" Outputs="@(RewrittenAssembly)" DependsOnTargets="$(BclRewriterDependencyTargets)">
+
+ <PropertyGroup>
+ <OSPlatform Condition="'$(TargetsWindows)' == 'true'">win</OSPlatform>
+ <OSPlatform Condition="'$(TargetsWindows)' != 'true'">unix</OSPlatform>
+ <BclRewriterCommand Condition="'$(BclRewriterCommand)'==''">"$(ToolRuntimePath)dotnetcli/$(ToolHost)" "$(ToolsDir)BclRewriter.exe"</BclRewriterCommand>
+ </PropertyGroup>
+
+ <Exec Command="$(BclRewriterCommand) -in:&quot;@(AnnotatedAssembly)&quot; -out:&quot;$(BclRewriterOutput)&quot; -include:&quot;$(BclRewriterModelFile)&quot; -platform:$(OSPlatform) -architecture:$(Platform) -flavor:$(_BuildType) -removeSerializable- -define:&quot;$(DefineConstants)&quot; -keepTempFiles+" StandardOutputImportance="Normal" />
+
+ <!-- Update the location of the symbol file-->
+ <PropertyGroup>
+ <CurrentAssemblyPdb>$(BclRewriterSymbolOutput)</CurrentAssemblyPdb>
+ </PropertyGroup>
+ </Target>
+</Project> \ No newline at end of file
diff --git a/src/mscorlib/Tools/PostProcessingTools.targets b/src/mscorlib/Tools/PostProcessingTools.targets
new file mode 100644
index 0000000000..2f48efcecb
--- /dev/null
+++ b/src/mscorlib/Tools/PostProcessingTools.targets
@@ -0,0 +1,28 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+ <Import Project="$(MSBuildThisFileDirectory)\BclRewriter\BclRewriter.targets" />
+
+ <ItemGroup>
+ <AnnotatedAssembly Include="$(IntermediateOutputPath)$(TargetName)$(TargetExt)"/>
+
+ <Clean Include="@(RewrittenAssembly->'$(FinalOutputPath)\%(Filename)%(Extension)')" />
+ <Clean Include="$(FinalOutputPath)\$(TargetName).pdb" />
+ </ItemGroup>
+
+ <Import Project="$(ToolsDir)toolruntime.targets" />
+
+ <PropertyGroup>
+ <CurrentAssemblyPdb>$(IntermediateOutputPath)$(TargetName).pdb</CurrentAssemblyPdb>
+ <PostProcessingTargets>RewriteWithBclRewriter</PostProcessingTargets>
+ <BclRewriterDependencyTargets>EnsureBuildToolsRuntime</BclRewriterDependencyTargets>
+ </PropertyGroup>
+
+ <Target Name="AfterBuild" DependsOnTargets="$(PostProcessingTargets)"
+ Inputs="@(RewrittenAssembly)" Outputs="$(FinalOutputPath)\%(RewrittenAssembly.FileName)%(RewrittenAssembly.Extension)">
+
+ <!-- Copy to the final output location -->
+ <Copy Retries="3" SourceFiles="@(RewrittenAssembly)" DestinationFiles="$(FinalOutputPath)\%(RewrittenAssembly.FileName)%(RewrittenAssembly.Extension)"/>
+ <Message Importance="High" Text="$(MSBuildProjectName) -&gt; $(FinalOutputPath)%(RewrittenAssembly.FileName)%(RewrittenAssembly.Extension)" />
+ <Copy Condition="Exists('$(CurrentAssemblyPdb)')" Retries="3" SourceFiles="$(CurrentAssemblyPdb)" DestinationFiles="$(FinalOutputPath)\$(TargetName).pdb"/>
+ </Target>
+
+</Project> \ No newline at end of file
diff --git a/src/mscorlib/Tools/Signing/mscorlib.snk b/src/mscorlib/Tools/Signing/mscorlib.snk
new file mode 100644
index 0000000000..60146e8891
--- /dev/null
+++ b/src/mscorlib/Tools/Signing/mscorlib.snk
Binary files differ
diff --git a/src/mscorlib/Tools/Versioning/GenerateVersionInfo.targets b/src/mscorlib/Tools/Versioning/GenerateVersionInfo.targets
new file mode 100644
index 0000000000..00f5282c7c
--- /dev/null
+++ b/src/mscorlib/Tools/Versioning/GenerateVersionInfo.targets
@@ -0,0 +1,114 @@
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <!-- Setup the default file version information -->
+ <PropertyGroup>
+ <MajorVersion Condition="'$(MajorVersion)' == ''">1</MajorVersion>
+ <MinorVersion Condition="'$(MinorVersion)' == ''">0</MinorVersion>
+ <BuildNumberMajor Condition="'$(BuildNumberMajor)' == ''">0</BuildNumberMajor>
+ <BuildNumberMinor Condition="'$(BuildNumberMinor)' == ''">0</BuildNumberMinor>
+ </PropertyGroup>
+
+ <!-- #################################### -->
+ <!-- Generate Assembly Info -->
+ <!-- #################################### -->
+ <PropertyGroup>
+ <AssemblyVersion Condition="'$(AssemblyVersion)'==''">999.999.999.0</AssemblyVersion>
+ <CLSCompliant Condition="'$(CLSCompliant)'==''">false</CLSCompliant>
+ <AssemblyFileVersion Condition="'$(AssemblyFileVersionOverride)'==''">$(MajorVersion).$(MinorVersion).$(BuildNumberMajor).$(BuildNumberMinor)</AssemblyFileVersion>
+ </PropertyGroup>
+
+ <PropertyGroup>
+ <GenerateAssemblyInfo Condition="'$(GenerateAssemblyInfo)'==''">true</GenerateAssemblyInfo>
+ </PropertyGroup>
+
+ <PropertyGroup Condition="'$(GenerateAssemblyInfo)'=='true'">
+ <AssemblyInfoFile>$(IntermediateOutputPath)GeneratedAssemblyInfo.cs</AssemblyInfoFile>
+ <CoreCompileDependsOn>$(CoreCompileDependsOn);GenerateAssemblyInfo</CoreCompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="GenerateAssemblyInfo"
+ Inputs="$(MSBuildProjectFile)"
+ Outputs="$(AssemblyInfoFile)"
+ Condition="'$(GenerateAssemblyInfo)'=='true'">
+
+ <Error Condition="!Exists('$(IntermediateOutputPath)')" Text="GenerateAssemblyInfo failed because IntermediateOutputPath isn't set to a valid directory" />
+
+ <ItemGroup>
+ <AssemblyInfoUsings Include="using System%3B" />
+ <AssemblyInfoUsings Include="using System.Reflection%3B" />
+ <AssemblyInfoLines Include="[assembly:AssemblyTitle(&quot;$(AssemblyName)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyDescription(&quot;$(AssemblyName)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyDefaultAlias(&quot;$(AssemblyName)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyCompany(&quot;Microsoft Corporation&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyProduct(&quot;Microsoft\x00ae .NET Framework&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyCopyright(&quot;\x00a9 Microsoft Corporation. All rights reserved.&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyVersion(&quot;$(AssemblyVersion)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyFileVersion(&quot;$(AssemblyFileVersion)&quot;)]" />
+ <AssemblyInfoLines Include="[assembly:AssemblyInformationalVersion(@&quot;$(AssemblyFileVersion)$(BuiltByString)&quot;)]" />
+ <AssemblyInfoLines Condition="'$(CLSCompliant)'=='true'" Include="[assembly:CLSCompliant(true)]" />
+ </ItemGroup>
+
+ <WriteLinesToFile File="$(AssemblyInfoFile)"
+ Lines="@(AssemblyInfoUsings);@(AssemblyInfoLines)"
+ Overwrite="true" />
+
+ <ItemGroup>
+ <Compile Include="$(AssemblyInfoFile)" />
+ <FileWrites Include="$(AssemblyInfoFile)" />
+ </ItemGroup>
+ </Target>
+
+ <!-- #################################### -->
+ <!-- Generate Native Version Info -->
+ <!-- #################################### -->
+ <PropertyGroup Condition="'$(GenerateNativeVersionInfo)'=='true'">
+ <NativeVersionHeaderFile>$(IntermediateOutputPath)GeneratedVersion.h</NativeVersionHeaderFile>
+ <BeforeResourceCompileTargets>$(BeforeResourceCompileTargets);GenerateVersionHeader</BeforeResourceCompileTargets>
+ <Win32Resource>$(IntermediateOutputPath)\NativeVersion.res</Win32Resource>
+ <CoreCompileDependsOn>$(CoreCompileDependsOn);NativeResourceCompile</CoreCompileDependsOn>
+ </PropertyGroup>
+
+ <Target Name="GenerateVersionHeader"
+ Condition="'$(GenerateNativeVersionInfo)'=='true'"
+ Inputs="$(MSBuildProjectFile)"
+ Outputs="$(NativeVersionHeaderFile)">
+
+ <ItemGroup>
+ <NativeVersionLines Include="#define VER_COMPANYNAME_STR &quot;Microsoft Corporation&quot;" />
+ <NativeVersionLines Include="#define VER_FILEDESCRIPTION_STR &quot;$(AssemblyName)&quot;" />
+ <NativeVersionLines Include="#define VER_INTERNALNAME_STR VER_FILEDESCRIPTION_STR" />
+ <NativeVersionLines Include="#define VER_ORIGINALFILENAME_STR VER_FILEDESCRIPTION_STR" />
+ <NativeVersionLines Include="#define VER_PRODUCTNAME_STR &quot;Microsoft\xae .NET Framework&quot;" />
+ <NativeVersionLines Include="#define VER_PRODUCTVERSION $(MajorVersion),$(MinorVersion),$(BuildNumberMajor),$(BuildNumberMinor)" />
+ <NativeVersionLines Include="#define VER_PRODUCTVERSION_STR &quot;$(MajorVersion).$(MinorVersion).$(BuildNumberMajor).$(BuildNumberMinor)&quot;" />
+ <NativeVersionLines Include="#define VER_FILEVERSION $(MajorVersion),$(MinorVersion),$(BuildNumberMajor),$(BuildNumberMinor)" />
+ <NativeVersionLines Include="#define VER_FILEVERSION_STR &quot;$(MajorVersion).$(MinorVersion).$(BuildNumberMajor).$(BuildNumberMinor)&quot;" />
+ <NativeVersionLines Include="#define VER_LEGALCOPYRIGHT_STR &quot;\xa9 Microsoft Corporation. All rights reserved.&quot;" />
+ <NativeVersionLines Condition="'$(Configuration)'=='Debug'" Include="#define VER_DEBUG VS_FF_DEBUG" />
+ <NativeVersionLines Condition="'$(Configuration)'!='Debug'" Include="#define VER_DEBUG 0" />
+ </ItemGroup>
+
+ <WriteLinesToFile File="$(NativeVersionHeaderFile)"
+ Lines="@(NativeVersionLines)"
+ Overwrite="true" />
+
+ <ItemGroup>
+ <FileWrites Include="$(NativeVersionHeaderFile)" />
+ </ItemGroup>
+ </Target>
+
+
+ <PropertyGroup Condition="'$(GenerateNativeVersionInfo)'=='true'">
+ <WindowsSdkDir Condition="'$(WindowsSdkDir)'==''">$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\v8.1@InstallationFolder)</WindowsSdkDir>
+ <RCPath Condition="'$(RCPath)' == ''">$(WindowsSdkDir)bin\x86\rc.exe</RCPath>
+ </PropertyGroup>
+
+ <Target Name="NativeResourceCompile"
+ Condition="'$(GenerateNativeVersionInfo)'=='true'"
+ DependsOnTargets="GenerateVersionHeader"
+ Inputs="$(MsBuildThisFileDirectory)NativeVersion.rc"
+ Outputs="$(Win32Resource)">
+
+ <Exec Command="&quot;$(RCPath)&quot; /nologo /x /i &quot;$(IntermediateOutputPath.TrimEnd('\'))&quot; /i &quot;$(WindowsSdkDir)Include\$(WindowsSDKVersion)um&quot; /i &quot;$(WindowsSdkDir)Include\$(WindowsSDKVersion)\shared&quot; /D _UNICODE /D UNICODE /l&quot;0x0409&quot; /r /fo &quot;$(Win32Resource)&quot; &quot;$(MsBuildThisFileDirectory)NativeVersion.rc&quot;" />
+
+ </Target>
+</Project>
diff --git a/src/mscorlib/Tools/Versioning/NativeVersion.rc b/src/mscorlib/Tools/Versioning/NativeVersion.rc
new file mode 100644
index 0000000000..6a26d16c27
--- /dev/null
+++ b/src/mscorlib/Tools/Versioning/NativeVersion.rc
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include "GeneratedVersion.h"
+
+#include <windows.h>
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEFLAGS VER_DEBUG
+FILEOS VOS__WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "CompanyName", VER_COMPANYNAME_STR
+ VALUE "FileDescription", VER_FILEDESCRIPTION_STR
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "InternalName", VER_INTERNALNAME_STR
+ VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR
+ VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR
+ VALUE "ProductName", VER_PRODUCTNAME_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* The following line should only be modified for localized versions. */
+ /* It consists of any number of WORD,WORD pairs, with each pair */
+ /* describing a language,codepage combination supported by the file. */
+ /* */
+ /* For example, a file might have values "0x409,1252" indicating that it */
+ /* supports English language (0x409) in the Windows ANSI codepage (1252). */
+
+ VALUE "Translation", 0x409, 1252
+
+ END
+END
diff --git a/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs b/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs
new file mode 100644
index 0000000000..f8c5b26e44
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/Interop.Libraries.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+internal static partial class Interop
+{
+ private static partial class Libraries
+ {
+ internal const string GlobalizationInterop = "System.Globalization.Native"; // CoreFX wrappers for ICU
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs
new file mode 100644
index 0000000000..7b3caeabdd
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Calendar.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Text;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ internal delegate void EnumCalendarInfoCallback(
+ [MarshalAs(UnmanagedType.LPWStr)] string calendarString,
+ IntPtr context);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetCalendars")]
+ internal static extern int GetCalendars(string localeName, CalendarId[] calendars, int calendarsCapacity);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetCalendarInfo")]
+ internal static extern ResultCode GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType calendarDataType, [Out] StringBuilder result, int resultCapacity);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_EnumCalendarInfo")]
+ internal static extern bool EnumCalendarInfo(EnumCalendarInfoCallback callback, string localeName, CalendarId calendarId, CalendarDataType calendarDataType, IntPtr context);
+
+ [DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetLatestJapaneseEra")]
+ internal static extern int GetLatestJapaneseEra();
+
+ [DllImport(Libraries.GlobalizationInterop, EntryPoint = "GlobalizationNative_GetJapaneseEraStartDate")]
+ internal static extern bool GetJapaneseEraStartDate(int era, out int startYear, out int startMonth, out int startDay);
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Casing.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Casing.cs
new file mode 100644
index 0000000000..115a8393be
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Casing.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCase")]
+ internal unsafe static extern void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseInvariant")]
+ internal unsafe static extern void ChangeCaseInvariant(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_ChangeCaseTurkish")]
+ internal unsafe static extern void ChangeCaseTurkish(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper);
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
new file mode 100644
index 0000000000..6acf55e17b
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Collation.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetSortHandle")]
+ internal unsafe static extern SafeSortHandle GetSortHandle(byte[] localeName);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CloseSortHandle")]
+ internal unsafe static extern void CloseSortHandle(IntPtr handle);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CompareString")]
+ internal unsafe static extern int CompareString(SafeSortHandle sortHandle, char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOf")]
+ internal unsafe static extern int IndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_LastIndexOf")]
+ internal unsafe static extern int LastIndexOf(SafeSortHandle sortHandle, string target, int cwTargetLength, char* pSource, int cwSourceLength, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_IndexOfOrdinalIgnoreCase")]
+ internal unsafe static extern int IndexOfOrdinalIgnoreCase(string target, int cwTargetLength, char* pSource, int cwSourceLength, bool findLast);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_StartsWith")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool StartsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_EndsWith")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool EndsWith(SafeSortHandle sortHandle, string target, int cwTargetLength, string source, int cwSourceLength, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetSortKey")]
+ internal unsafe static extern int GetSortKey(SafeSortHandle sortHandle, string str, int strLength, byte* sortKey, int sortKeyLength, CompareOptions options);
+
+ [SecurityCritical]
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_CompareStringOrdinalIgnoreCase")]
+ internal unsafe static extern int CompareStringOrdinalIgnoreCase(char* lpStr1, int cwStr1Len, char* lpStr2, int cwStr2Len);
+
+ [SecurityCritical]
+ internal class SafeSortHandle : SafeHandle
+ {
+ private SafeSortHandle() :
+ base(IntPtr.Zero, true)
+ {
+ }
+
+ public override bool IsInvalid
+ {
+ [SecurityCritical]
+ get { return handle == IntPtr.Zero; }
+ }
+
+ [SecurityCritical]
+ protected override bool ReleaseHandle()
+ {
+ CloseSortHandle(handle);
+ SetHandle(IntPtr.Zero);
+ return true;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs
new file mode 100644
index 0000000000..3912581c73
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Locale.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleName")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetLocaleName(string localeName, [Out] StringBuilder value, int valueLength);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoString")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetLocaleInfoString(string localeName, uint localeStringData, [Out] StringBuilder value, int valueLength);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetDefaultLocaleName")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetDefaultLocaleName([Out] StringBuilder value, int valueLength);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleTimeFormat")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetLocaleTimeFormat(string localeName, bool shortFormat, [Out] StringBuilder value, int valueLength);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoInt")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetLocaleInfoInt(string localeName, uint localeNumberData, ref int value);
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetLocaleInfoGroupingSizes")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal unsafe static extern bool GetLocaleInfoGroupingSizes(string localeName, uint localeGroupingData, ref int primaryGroupSize, ref int secondaryGroupSize);
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs
new file mode 100644
index 0000000000..4621580063
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.ResultCode.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ // needs to be kept in sync with ResultCode in System.Globalization.Native
+ internal enum ResultCode
+ {
+ Success = 0,
+ UnknownError = 1,
+ InsufficentBuffer = 2,
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs
new file mode 100644
index 0000000000..26a9fe0579
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.TimeZoneInfo.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Text;
+
+internal static partial class Interop
+{
+ internal static partial class GlobalizationInterop
+ {
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Ansi, EntryPoint = "GlobalizationNative_ReadLink")] // readlink requires char*
+ internal static extern bool ReadLink(string filePath, [Out] StringBuilder result, uint resultCapacity);
+
+ // needs to be kept in sync with TimeZoneDisplayNameType in System.Globalization.Native
+ internal enum TimeZoneDisplayNameType
+ {
+ Generic = 0,
+ Standard = 1,
+ DaylightSavings = 2,
+ }
+
+ [DllImport(Libraries.GlobalizationInterop, CharSet = CharSet.Unicode, EntryPoint = "GlobalizationNative_GetTimeZoneDisplayName")]
+ internal static extern ResultCode GetTimeZoneDisplayName(
+ string localeName,
+ string timeZoneId,
+ TimeZoneDisplayNameType type,
+ [Out] StringBuilder result,
+ int resultLength);
+ }
+}
diff --git a/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Utils.cs b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Utils.cs
new file mode 100644
index 0000000000..33b10c0d74
--- /dev/null
+++ b/src/mscorlib/corefx/Interop/Unix/System.Globalization.Native/Interop.Utils.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+
+internal static partial class Interop
+{
+ /// <summary>
+ /// Helper for making interop calls that return a string, but we don't know
+ /// the correct size of buffer to make. So invoke the interop call with an
+ /// increasing buffer until the size is big enough.
+ /// </summary>
+ internal static bool CallStringMethod<TArg1, TArg2, TArg3>(
+ Func<TArg1, TArg2, TArg3, StringBuilder, GlobalizationInterop.ResultCode> interopCall,
+ TArg1 arg1,
+ TArg2 arg2,
+ TArg3 arg3,
+ out string result)
+ {
+ const int initialStringSize = 80;
+ const int maxDoubleAttempts = 5;
+
+ StringBuilder stringBuilder = StringBuilderCache.Acquire(initialStringSize);
+
+ for (int i = 0; i < maxDoubleAttempts; i++)
+ {
+ GlobalizationInterop.ResultCode resultCode = interopCall(arg1, arg2, arg3, stringBuilder);
+
+ if (resultCode == GlobalizationInterop.ResultCode.Success)
+ {
+ result = StringBuilderCache.GetStringAndRelease(stringBuilder);
+ return true;
+ }
+ else if (resultCode == GlobalizationInterop.ResultCode.InsufficentBuffer)
+ {
+ // increase the string size and loop
+ stringBuilder.EnsureCapacity(stringBuilder.Capacity * 2);
+ }
+ else
+ {
+ // if there is an unknown error, don't proceed
+ break;
+ }
+ }
+
+ StringBuilderCache.Release(stringBuilder);
+ result = null;
+ return false;
+ }
+}
diff --git a/src/mscorlib/corefx/SR.cs b/src/mscorlib/corefx/SR.cs
new file mode 100644
index 0000000000..513bd9d94d
--- /dev/null
+++ b/src/mscorlib/corefx/SR.cs
@@ -0,0 +1,247 @@
+using System;
+
+namespace System.Globalization
+{
+ internal static class SR
+ {
+ public static string Arg_HexStyleNotSupported
+ {
+ get { return Environment.GetResourceString("Arg_HexStyleNotSupported"); }
+ }
+
+ public static string Arg_InvalidHexStyle
+ {
+ get { return Environment.GetResourceString("Arg_InvalidHexStyle"); }
+ }
+
+ public static string ArgumentNull_Array
+ {
+ get { return Environment.GetResourceString("ArgumentNull_Array"); }
+ }
+
+ public static string ArgumentNull_ArrayValue
+ {
+ get { return Environment.GetResourceString("ArgumentNull_ArrayValue"); }
+ }
+
+ public static string ArgumentNull_Obj
+ {
+ get { return Environment.GetResourceString("ArgumentNull_Obj"); }
+ }
+
+ public static string ArgumentNull_String
+ {
+ get { return Environment.GetResourceString("ArgumentNull_String"); }
+ }
+
+ public static string ArgumentOutOfRange_AddValue
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_AddValue"); }
+ }
+
+ public static string ArgumentOutOfRange_BadHourMinuteSecond
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"); }
+ }
+
+ public static string ArgumentOutOfRange_BadYearMonthDay
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"); }
+ }
+
+ public static string ArgumentOutOfRange_Bounds_Lower_Upper
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"); }
+ }
+
+ public static string ArgumentOutOfRange_CalendarRange
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"); }
+ }
+
+ public static string ArgumentOutOfRange_Count
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Count"); }
+ }
+
+ public static string ArgumentOutOfRange_Day
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Day"); }
+ }
+
+ public static string ArgumentOutOfRange_Enum
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Enum"); }
+ }
+
+ public static string ArgumentOutOfRange_Era
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Era"); }
+ }
+
+ public static string ArgumentOutOfRange_Index
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Index"); }
+ }
+
+ public static string ArgumentOutOfRange_InvalidEraValue
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"); }
+ }
+
+ public static string ArgumentOutOfRange_Month
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Month"); }
+ }
+
+ public static string ArgumentOutOfRange_NeedNonNegNum
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"); }
+ }
+
+ public static string ArgumentOutOfRange_NeedPosNum
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"); }
+ }
+
+ public static string ArgumentOutOfRange_OffsetLength
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"); }
+ }
+
+ public static string ArgumentOutOfRange_Range
+ {
+ get { return Environment.GetResourceString("ArgumentOutOfRange_Range"); }
+ }
+
+ public static string Argument_CompareOptionOrdinal
+ {
+ get { return Environment.GetResourceString("Argument_CompareOptionOrdinal"); }
+ }
+
+ public static string Argument_ConflictingDateTimeRoundtripStyles
+ {
+ get { return Environment.GetResourceString("Argument_ConflictingDateTimeRoundtripStyles"); }
+ }
+
+ public static string Argument_ConflictingDateTimeStyles
+ {
+ get { return Environment.GetResourceString("Argument_ConflictingDateTimeStyles"); }
+ }
+
+ public static string Argument_CultureInvalidIdentifier
+ {
+ get { return Environment.GetResourceString("Argument_CultureInvalidIdentifier"); }
+ }
+
+ public static string Argument_CultureNotSupported
+ {
+ get { return Environment.GetResourceString("Argument_CultureNotSupported"); }
+ }
+
+ public static string Argument_EmptyDecString
+ {
+ get { return Environment.GetResourceString("Argument_EmptyDecString"); }
+ }
+
+ public static string Argument_InvalidArrayLength
+ {
+ get { return Environment.GetResourceString("Argument_InvalidArrayLength"); }
+ }
+
+ public static string Argument_InvalidCalendar
+ {
+ get { return Environment.GetResourceString("Argument_InvalidCalendar"); }
+ }
+
+ public static string Argument_InvalidCultureName
+ {
+ get { return Environment.GetResourceString("Argument_InvalidCultureName"); }
+ }
+
+ public static string Argument_InvalidDateTimeStyles
+ {
+ get { return Environment.GetResourceString("Argument_InvalidDateTimeStyles"); }
+ }
+
+ public static string Argument_InvalidFlag
+ {
+ get { return Environment.GetResourceString("Argument_InvalidFlag"); }
+ }
+
+ public static string Argument_InvalidGroupSize
+ {
+ get { return Environment.GetResourceString("Argument_InvalidGroupSize"); }
+ }
+
+ public static string Argument_InvalidNeutralRegionName
+ {
+ get { return Environment.GetResourceString("Argument_InvalidNeutralRegionName"); }
+ }
+
+ public static string Argument_InvalidNumberStyles
+ {
+ get { return Environment.GetResourceString("Argument_InvalidNumberStyles"); }
+ }
+
+ public static string Argument_InvalidResourceCultureName
+ {
+ get { return Environment.GetResourceString("Argument_InvalidResourceCultureName"); }
+ }
+
+ public static string Argument_NoEra
+ {
+ get { return Environment.GetResourceString("Argument_NoEra"); }
+ }
+
+ public static string Argument_NoRegionInvariantCulture
+ {
+ get { return Environment.GetResourceString("Argument_NoRegionInvariantCulture"); }
+ }
+
+ public static string Argument_ResultCalendarRange
+ {
+ get { return Environment.GetResourceString("Argument_ResultCalendarRange"); }
+ }
+
+ public static string Format_BadFormatSpecifier
+ {
+ get { return Environment.GetResourceString("Format_BadFormatSpecifier"); }
+ }
+
+ public static string InvalidOperation_DateTimeParsing
+ {
+ get { return Environment.GetResourceString("InvalidOperation_DateTimeParsing"); }
+ }
+
+ public static string InvalidOperation_EnumEnded
+ {
+ get { return Environment.GetResourceString("InvalidOperation_EnumEnded"); }
+ }
+
+ public static string InvalidOperation_EnumNotStarted
+ {
+ get { return Environment.GetResourceString("InvalidOperation_EnumNotStarted"); }
+ }
+
+ public static string InvalidOperation_ReadOnly
+ {
+ get { return Environment.GetResourceString("InvalidOperation_ReadOnly"); }
+ }
+
+ public static string Overflow_TimeSpanTooLong
+ {
+ get { return Environment.GetResourceString("Overflow_TimeSpanTooLong"); }
+ }
+
+ public static string Serialization_MemberOutOfRange
+ {
+ get { return Environment.GetResourceString("Serialization_MemberOutOfRange"); }
+ }
+
+ public static string Format(string formatString, params object[] args)
+ {
+ return string.Format(CultureInfo.CurrentCulture, formatString, args);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/Calendar.cs b/src/mscorlib/corefx/System/Globalization/Calendar.cs
new file mode 100644
index 0000000000..343682d156
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/Calendar.cs
@@ -0,0 +1,854 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+
+namespace System.Globalization
+{
+ // This abstract class represents a calendar. A calendar reckons time in
+ // divisions such as weeks, months and years. The number, length and start of
+ // the divisions vary in each calendar.
+ //
+ // Any instant in time can be represented as an n-tuple of numeric values using
+ // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0
+ // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An implementation of
+ // Calendar can map any DateTime value to such an n-tuple and vice versa. The
+ // DateTimeFormat class can map between such n-tuples and a textual
+ // representation such as "8:46 AM March 20th 1999 AD".
+ //
+ // Most calendars identify a year which begins the current era. There may be any
+ // number of previous eras. The Calendar class identifies the eras as enumerated
+ // integers where the current era (CurrentEra) has the value zero.
+ //
+ // For consistency, the first unit in each interval, e.g. the first month, is
+ // assigned the value one.
+ // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
+ // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract partial class Calendar : ICloneable
+ {
+ // Number of 100ns (10E-7 second) ticks per time unit
+ internal const long TicksPerMillisecond = 10000;
+ internal const long TicksPerSecond = TicksPerMillisecond * 1000;
+ internal const long TicksPerMinute = TicksPerSecond * 60;
+ internal const long TicksPerHour = TicksPerMinute * 60;
+ internal const long TicksPerDay = TicksPerHour * 24;
+
+ // Number of milliseconds per time unit
+ internal const int MillisPerSecond = 1000;
+ internal const int MillisPerMinute = MillisPerSecond * 60;
+ internal const int MillisPerHour = MillisPerMinute * 60;
+ internal const int MillisPerDay = MillisPerHour * 24;
+
+ // Number of days in a non-leap year
+ internal const int DaysPerYear = 365;
+ // Number of days in 4 years
+ internal const int DaysPer4Years = DaysPerYear * 4 + 1;
+ // Number of days in 100 years
+ internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
+ // Number of days in 400 years
+ internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
+
+ // Number of days from 1/1/0001 to 1/1/10000
+ internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
+
+ internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
+
+
+ private int _currentEraValue = -1;
+
+ [OptionalField(VersionAdded = 2)]
+ private bool _isReadOnly = false;
+
+#if INSIDE_CLR
+ internal const CalendarId CAL_HEBREW = CalendarId.HEBREW;
+ internal const CalendarId CAL_HIJRI = CalendarId.HIJRI;
+ internal const CalendarId CAL_JAPAN = CalendarId.JAPAN;
+ internal const CalendarId CAL_JULIAN = CalendarId.JULIAN;
+ internal const CalendarId CAL_TAIWAN = CalendarId.TAIWAN;
+ internal const CalendarId CAL_UMALQURA = CalendarId.UMALQURA;
+ internal const CalendarId CAL_PERSIAN = CalendarId.PERSIAN;
+#endif
+
+ // The minimum supported DateTime range for the calendar.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ // The maximum supported DateTime range for the calendar.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+
+
+
+ protected Calendar()
+ {
+ //Do-nothing constructor.
+ }
+
+ ///
+ // This can not be abstract, otherwise no one can create a subclass of Calendar.
+ //
+ internal virtual CalendarId ID
+ {
+ get
+ {
+ return CalendarId.UNINITIALIZED_VALUE;
+ }
+ }
+
+ ///
+ // Return the Base calendar ID for calendars that didn't have defined data in calendarData
+ //
+
+ internal virtual CalendarId BaseCalendarID
+ {
+ get { return ID; }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsReadOnly
+ //
+ // Detect if the object is readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsReadOnly
+ {
+ get { return (_isReadOnly); }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Clone
+ //
+ // Is the implementation of ICloneable.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual object Clone()
+ {
+ object o = MemberwiseClone();
+ ((Calendar)o).SetReadOnlyState(false);
+ return (o);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ReadOnly
+ //
+ // Create a cloned readonly instance or return the input one if it is
+ // readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ internal static Calendar ReadOnly(Calendar calendar)
+ {
+ if (calendar == null) { throw new ArgumentNullException("calendar"); }
+ Contract.EndContractBlock();
+ if (calendar.IsReadOnly) { return (calendar); }
+
+ Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
+ clonedCalendar.SetReadOnlyState(true);
+
+ return (clonedCalendar);
+ }
+
+ internal void VerifyWritable()
+ {
+ if (_isReadOnly)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ }
+ }
+
+ internal void SetReadOnlyState(bool readOnly)
+ {
+ _isReadOnly = readOnly;
+ }
+
+
+ /*=================================CurrentEraValue==========================
+ **Action: This is used to convert CurretEra(0) to an appropriate era value.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ **Notes:
+ ** The value is from calendar.nlp.
+ ============================================================================*/
+
+ internal virtual int CurrentEraValue
+ {
+ get
+ {
+ // The following code assumes that the current era value can not be -1.
+ if (_currentEraValue == -1)
+ {
+ Contract.Assert(BaseCalendarID != CalendarId.UNINITIALIZED_VALUE, "[Calendar.CurrentEraValue] Expected a real calendar ID");
+ _currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra;
+ }
+ return (_currentEraValue);
+ }
+ }
+
+ // The current era for a calendar.
+
+ public const int CurrentEra = 0;
+
+ internal int twoDigitYearMax = -1;
+
+ internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue)
+ {
+ if (ticks < minValue.Ticks || ticks > maxValue.Ticks)
+ {
+ throw new ArgumentException(
+ String.Format(CultureInfo.InvariantCulture, SR.Format(SR.Argument_ResultCalendarRange,
+ minValue, maxValue)));
+ }
+ Contract.EndContractBlock();
+ }
+
+ internal DateTime Add(DateTime time, double value, int scale)
+ {
+ // From ECMA CLI spec, Partition III, section 3.27:
+ //
+ // If overflow occurs converting a floating-point type to an integer, or if the floating-point value
+ // being converted to an integer is a NaN, the value returned is unspecified.
+ //
+ // Based upon this, this method should be performing the comparison against the double
+ // before attempting a cast. Otherwise, the result is undefined.
+ double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5));
+ if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis)))
+ {
+ throw new ArgumentOutOfRangeException("value", SR.ArgumentOutOfRange_AddValue);
+ }
+
+ long millis = (long)tempMillis;
+ long ticks = time.Ticks + millis * TicksPerMillisecond;
+ CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // milliseconds to the specified DateTime. The result is computed by rounding
+ // the number of milliseconds given by value to the nearest integer,
+ // and adding that interval to the specified DateTime. The value
+ // argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddMilliseconds(DateTime time, double milliseconds)
+ {
+ return (Add(time, milliseconds, 1));
+ }
+
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // days to the specified DateTime. The result is computed by rounding the
+ // fractional number of days given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddDays(DateTime time, int days)
+ {
+ return (Add(time, days, MillisPerDay));
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // hours to the specified DateTime. The result is computed by rounding the
+ // fractional number of hours given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddHours(DateTime time, int hours)
+ {
+ return (Add(time, hours, MillisPerHour));
+ }
+
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // minutes to the specified DateTime. The result is computed by rounding the
+ // fractional number of minutes given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddMinutes(DateTime time, int minutes)
+ {
+ return (Add(time, minutes, MillisPerMinute));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public abstract DateTime AddMonths(DateTime time, int months);
+
+ // Returns the DateTime resulting from adding a number of
+ // seconds to the specified DateTime. The result is computed by rounding the
+ // fractional number of seconds given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddSeconds(DateTime time, int seconds)
+ {
+ return Add(time, seconds, MillisPerSecond);
+ }
+
+ // Returns the DateTime resulting from adding a number of
+ // weeks to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddWeeks(DateTime time, int weeks)
+ {
+ return (AddDays(time, weeks * 7));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public abstract DateTime AddYears(DateTime time, int years);
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public abstract int GetDayOfMonth(DateTime time);
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public abstract DayOfWeek GetDayOfWeek(DateTime time);
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public abstract int GetDayOfYear(DateTime time);
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public virtual int GetDaysInMonth(int year, int month)
+ {
+ return (GetDaysInMonth(year, month, CurrentEra));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments for the specified era.
+ //
+
+ public abstract int GetDaysInMonth(int year, int month, int era);
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public virtual int GetDaysInYear(int year)
+ {
+ return (GetDaysInYear(year, CurrentEra));
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public abstract int GetDaysInYear(int year, int era);
+
+ // Returns the era for the specified DateTime value.
+
+ public abstract int GetEra(DateTime time);
+
+ /*=================================Eras==========================
+ **Action: Get the list of era values.
+ **Returns: The int array of the era names supported in this calendar.
+ ** null if era is not used.
+ **Arguments: None.
+ **Exceptions: None.
+ ============================================================================*/
+
+
+ public abstract int[] Eras
+ {
+ get;
+ }
+
+
+ // Returns the hour part of the specified DateTime. The returned value is an
+ // integer between 0 and 23.
+ //
+
+ public virtual int GetHour(DateTime time)
+ {
+ return ((int)((time.Ticks / TicksPerHour) % 24));
+ }
+
+ // Returns the millisecond part of the specified DateTime. The returned value
+ // is an integer between 0 and 999.
+ //
+
+ public virtual double GetMilliseconds(DateTime time)
+ {
+ return (double)((time.Ticks / TicksPerMillisecond) % 1000);
+ }
+
+ // Returns the minute part of the specified DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+
+ public virtual int GetMinute(DateTime time)
+ {
+ return ((int)((time.Ticks / TicksPerMinute) % 60));
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public abstract int GetMonth(DateTime time);
+
+ // Returns the number of months in the specified year in the current era.
+
+ public virtual int GetMonthsInYear(int year)
+ {
+ return (GetMonthsInYear(year, CurrentEra));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public abstract int GetMonthsInYear(int year, int era);
+
+ // Returns the second part of the specified DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+
+ public virtual int GetSecond(DateTime time)
+ {
+ return ((int)((time.Ticks / TicksPerSecond) % 60));
+ }
+
+ /*=================================GetFirstDayWeekOfYear==========================
+ **Action: Get the week of year using the FirstDay rule.
+ **Returns: the week of year.
+ **Arguments:
+ ** time
+ ** firstDayOfWeek the first day of week (0=Sunday, 1=Monday, ... 6=Saturday)
+ **Notes:
+ ** The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
+ ** Assume f is the specifed firstDayOfWeek,
+ ** and n is the day of week for January 1 of the specified year.
+ ** Assign offset = n - f;
+ ** Case 1: offset = 0
+ ** E.g.
+ ** f=1
+ ** weekday 0 1 2 3 4 5 6 0 1
+ ** date 1/1
+ ** week# 1 2
+ ** then week of year = (GetDayOfYear(time) - 1) / 7 + 1
+ **
+ ** Case 2: offset < 0
+ ** e.g.
+ ** n=1 f=3
+ ** weekday 0 1 2 3 4 5 6 0
+ ** date 1/1
+ ** week# 1 2
+ ** This means that the first week actually starts 5 days before 1/1.
+ ** So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1
+ ** Case 3: offset > 0
+ ** e.g.
+ ** f=0 n=2
+ ** weekday 0 1 2 3 4 5 6 0 1 2
+ ** date 1/1
+ ** week# 1 2
+ ** This means that the first week actually starts 2 days before 1/1.
+ ** So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
+ ============================================================================*/
+
+ internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek)
+ {
+ int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ // Calculate the day of week for the first day of the year.
+ // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year. Note that
+ // this value can be less than 0. It's fine since we are making it positive again in calculating offset.
+ int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
+ int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
+ Contract.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0");
+ return ((dayOfYear + offset) / 7 + 1);
+ }
+
+ private int GetWeekOfYearFullDays(DateTime time, int firstDayOfWeek, int fullDays)
+ {
+ int dayForJan1;
+ int offset;
+ int day;
+
+ int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ //
+ // Calculate the number of days between the first day of year (1/1) and the first day of the week.
+ // This value will be a positive value from 0 ~ 6. We call this value as "offset".
+ //
+ // If offset is 0, it means that the 1/1 is the start of the first week.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sun Mon Tue Wed Thu Fri Sat
+ // 12/31 1/1 1/2 1/3 1/4 1/5 1/6
+ // +--> First week starts here.
+ //
+ // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sun Mon Tue Wed Thu Fri Sat
+ // 1/1 1/2 1/3 1/4 1/5 1/6 1/7
+ // +--> First week starts here.
+ //
+ // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sat Sun Mon Tue Wed Thu Fri Sat
+ // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8
+ // +--> First week starts here.
+
+
+
+ // Day of week is 0-based.
+ // Get the day of week for 1/1. This can be derived from the day of week of the target day.
+ // Note that we can get a negative value. It's ok since we are going to make it a positive value when calculating the offset.
+ dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
+
+ // Now, calculate the offset. Subtract the first day of week from the dayForJan1. And make it a positive value.
+ offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
+ if (offset != 0 && offset >= fullDays)
+ {
+ //
+ // If the offset is greater than the value of fullDays, it means that
+ // the first week of the year starts on the week where Jan/1 falls on.
+ //
+ offset -= 7;
+ }
+ //
+ // Calculate the day of year for specified time by taking offset into account.
+ //
+ day = dayOfYear - offset;
+ if (day >= 0)
+ {
+ //
+ // If the day of year value is greater than zero, get the week of year.
+ //
+ return (day / 7 + 1);
+ }
+ //
+ // Otherwise, the specified time falls on the week of previous year.
+ // Call this method again by passing the last day of previous year.
+ //
+ // the last day of the previous year may "underflow" to no longer be a valid date time for
+ // this calendar if we just subtract so we need the subclass to provide us with
+ // that information
+ if (time <= MinSupportedDateTime.AddDays(dayOfYear))
+ {
+ return GetWeekOfYearOfMinSupportedDateTime(firstDayOfWeek, fullDays);
+ }
+ return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear + 1)), firstDayOfWeek, fullDays));
+ }
+
+ private int GetWeekOfYearOfMinSupportedDateTime(int firstDayOfWeek, int minimumDaysInFirstWeek)
+ {
+ int dayOfYear = GetDayOfYear(MinSupportedDateTime) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ int dayOfWeekOfFirstOfYear = (int)GetDayOfWeek(MinSupportedDateTime) - dayOfYear % 7;
+
+ // Calculate the offset (how many days from the start of the year to the start of the week)
+ int offset = (firstDayOfWeek + 7 - dayOfWeekOfFirstOfYear) % 7;
+ if (offset == 0 || offset >= minimumDaysInFirstWeek)
+ {
+ // First of year falls in the first week of the year
+ return 1;
+ }
+
+ int daysInYearBeforeMinSupportedYear = DaysInYearBeforeMinSupportedYear - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ int dayOfWeekOfFirstOfPreviousYear = dayOfWeekOfFirstOfYear - 1 - (daysInYearBeforeMinSupportedYear % 7);
+
+ // starting from first day of the year, how many days do you have to go forward
+ // before getting to the first day of the week?
+ int daysInInitialPartialWeek = (firstDayOfWeek - dayOfWeekOfFirstOfPreviousYear + 14) % 7;
+ int day = daysInYearBeforeMinSupportedYear - daysInInitialPartialWeek;
+ if (daysInInitialPartialWeek >= minimumDaysInFirstWeek)
+ {
+ // If the offset is greater than the minimum Days in the first week, it means that
+ // First of year is part of the first week of the year even though it is only a partial week
+ // add another week
+ day += 7;
+ }
+
+ return (day / 7 + 1);
+ }
+
+ // it would be nice to make this abstract but we can't since that would break previous implementations
+ protected virtual int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ return 365;
+ }
+ }
+
+
+ // Returns the week of year for the specified DateTime. The returned value is an
+ // integer between 1 and 53.
+ //
+
+ public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6)
+ {
+ throw new ArgumentOutOfRangeException(
+ "firstDayOfWeek", SR.Format(SR.ArgumentOutOfRange_Range,
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+ switch (rule)
+ {
+ case CalendarWeekRule.FirstDay:
+ return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek));
+ case CalendarWeekRule.FirstFullWeek:
+ return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 7));
+ case CalendarWeekRule.FirstFourDayWeek:
+ return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4));
+ }
+ throw new ArgumentOutOfRangeException(
+ "rule", SR.Format(SR.ArgumentOutOfRange_Range,
+ CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public abstract int GetYear(DateTime time);
+
+ // Checks whether a given day in the current era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public virtual bool IsLeapDay(int year, int month, int day)
+ {
+ return (IsLeapDay(year, month, day, CurrentEra));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public abstract bool IsLeapDay(int year, int month, int day, int era);
+
+ // Checks whether a given month in the current era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public virtual bool IsLeapMonth(int year, int month)
+ {
+ return (IsLeapMonth(year, month, CurrentEra));
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public abstract bool IsLeapMonth(int year, int month, int era);
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int GetLeapMonth(int year, int era)
+ {
+ if (!IsLeapYear(year, era))
+ return 0;
+
+ int monthsCount = GetMonthsInYear(year, era);
+ for (int month = 1; month <= monthsCount; month++)
+ {
+ if (IsLeapMonth(year, month, era))
+ return month;
+ }
+
+ return 0;
+ }
+
+ // Checks whether a given year in the current era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public virtual bool IsLeapYear(int year)
+ {
+ return (IsLeapYear(year, CurrentEra));
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public abstract bool IsLeapYear(int year, int era);
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public virtual DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
+ {
+ return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
+
+ internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ {
+ result = DateTime.MinValue;
+ try
+ {
+ result = ToDateTime(year, month, day, hour, minute, second, millisecond, era);
+ return true;
+ }
+ catch (ArgumentException)
+ {
+ return false;
+ }
+ }
+
+ internal virtual bool IsValidYear(int year, int era)
+ {
+ return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime));
+ }
+
+ internal virtual bool IsValidMonth(int year, int month, int era)
+ {
+ return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era));
+ }
+
+ internal virtual bool IsValidDay(int year, int month, int day, int era)
+ {
+ return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era));
+ }
+
+
+ // Returns and assigns the maximum value to represent a two digit year. This
+ // value is the upper boundary of a 100 year range that allows a two digit year
+ // to be properly translated to a four digit year. For example, if 2029 is the
+ // upper boundary, then a two digit value of 30 should be interpreted as 1930
+ // while a two digit value of 29 should be interpreted as 2029. In this example
+ // , the 100 year range would be from 1930-2029. See ToFourDigitYear().
+
+ public virtual int TwoDigitYearMax
+ {
+ get
+ {
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ twoDigitYearMax = value;
+ }
+ }
+
+ // Converts the year value to the appropriate century by using the
+ // TwoDigitYearMax property. For example, if the TwoDigitYearMax value is 2029,
+ // then a two digit value of 30 will get converted to 1930 while a two digit
+ // value of 29 will get converted to 2029.
+
+ public virtual int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+ if (year < 100)
+ {
+ return ((TwoDigitYearMax / 100 - (year > TwoDigitYearMax % 100 ? 1 : 0)) * 100 + year);
+ }
+ // If the year value is above 100, just return the year value. Don't have to do
+ // the TwoDigitYearMax comparison.
+ return (year);
+ }
+
+ // Return the tick count corresponding to the given hour, minute, second.
+ // Will check the if the parameters are valid.
+ internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
+ {
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
+ {
+ if (millisecond < 0 || millisecond >= MillisPerSecond)
+ {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.Format(SR.ArgumentOutOfRange_Range, 0, MillisPerSecond - 1)));
+ }
+ return InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
+ }
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
+ }
+
+ internal static int GetSystemTwoDigitYearSetting(CalendarId CalID, int defaultYearValue)
+ {
+ // Call nativeGetTwoDigitYearMax
+ int twoDigitYearMax = CalendarData.GetTwoDigitYearMax(CalID);
+ if (twoDigitYearMax < 0)
+ {
+ twoDigitYearMax = defaultYearValue;
+ }
+ return (twoDigitYearMax);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs
new file mode 100644
index 0000000000..6c6a18ec37
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CalendarData.Unix.cs
@@ -0,0 +1,341 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+
+namespace System.Globalization
+{
+ // needs to be kept in sync with CalendarDataType in System.Globalization.Native
+ internal enum CalendarDataType
+ {
+ Uninitialized = 0,
+ NativeName = 1,
+ MonthDay = 2,
+ ShortDates = 3,
+ LongDates = 4,
+ YearMonths = 5,
+ DayNames = 6,
+ AbbrevDayNames = 7,
+ MonthNames = 8,
+ AbbrevMonthNames = 9,
+ SuperShortDayNames = 10,
+ MonthGenitiveNames = 11,
+ AbbrevMonthGenitiveNames = 12,
+ EraNames = 13,
+ AbbrevEraNames = 14,
+ }
+
+ internal partial class CalendarData
+ {
+ private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ {
+ bool result = true;
+ result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.NativeName, out this.sNativeName);
+ result &= GetCalendarInfo(localeName, calendarId, CalendarDataType.MonthDay, out this.sMonthDay);
+ this.sMonthDay = NormalizeDatePattern(this.sMonthDay);
+
+ result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.ShortDates, out this.saShortDates);
+ result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.LongDates, out this.saLongDates);
+ result &= EnumDatePatterns(localeName, calendarId, CalendarDataType.YearMonths, out this.saYearMonths);
+ result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.DayNames, out this.saDayNames);
+ result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.AbbrevDayNames, out this.saAbbrevDayNames);
+ result &= EnumCalendarInfo(localeName, calendarId, CalendarDataType.SuperShortDayNames, out this.saSuperShortDayNames);
+ result &= EnumMonthNames(localeName, calendarId, CalendarDataType.MonthNames, out this.saMonthNames);
+ result &= EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthNames, out this.saAbbrevMonthNames);
+ result &= EnumMonthNames(localeName, calendarId, CalendarDataType.MonthGenitiveNames, out this.saMonthGenitiveNames);
+ result &= EnumMonthNames(localeName, calendarId, CalendarDataType.AbbrevMonthGenitiveNames, out this.saAbbrevMonthGenitiveNames);
+ result &= EnumEraNames(localeName, calendarId, CalendarDataType.EraNames, out this.saEraNames);
+ result &= EnumEraNames(localeName, calendarId, CalendarDataType.AbbrevEraNames, out this.saAbbrevEraNames);
+
+ return result;
+ }
+
+ internal static int GetTwoDigitYearMax(CalendarId calendarId)
+ {
+ // There is no user override for this value on Linux or in ICU.
+ // So just return -1 to use the hard-coded defaults.
+ return -1;
+ }
+
+ // Call native side to figure out which calendars are allowed
+ [SecuritySafeCritical]
+ internal static int GetCalendars(string localeName, bool useUserOverride, CalendarId[] calendars)
+ {
+ // NOTE: there are no 'user overrides' on Linux
+ int count = Interop.GlobalizationInterop.GetCalendars(localeName, calendars, calendars.Length);
+
+ // ensure there is at least 1 calendar returned
+ if (count == 0 && calendars.Length > 0)
+ {
+ calendars[0] = CalendarId.GREGORIAN;
+ count = 1;
+ }
+
+ return count;
+ }
+
+ private static bool SystemSupportsTaiwaneseCalendar()
+ {
+ return true;
+ }
+
+ // PAL Layer ends here
+
+ [SecuritySafeCritical]
+ private static bool GetCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string calendarString)
+ {
+ return Interop.CallStringMethod(
+ (locale, calId, type, stringBuilder) =>
+ Interop.GlobalizationInterop.GetCalendarInfo(
+ locale,
+ calId,
+ type,
+ stringBuilder,
+ stringBuilder.Capacity),
+ localeName,
+ calendarId,
+ dataType,
+ out calendarString);
+ }
+
+ private static bool EnumDatePatterns(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] datePatterns)
+ {
+ datePatterns = null;
+
+ CallbackContext callbackContext = new CallbackContext();
+ callbackContext.DisallowDuplicates = true;
+ bool result = EnumCalendarInfo(localeName, calendarId, dataType, callbackContext);
+ if (result)
+ {
+ List<string> datePatternsList = callbackContext.Results;
+
+ datePatterns = new string[datePatternsList.Count];
+ for (int i = 0; i < datePatternsList.Count; i++)
+ {
+ datePatterns[i] = NormalizeDatePattern(datePatternsList[i]);
+ }
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// The ICU date format characters are not exactly the same as the .NET date format characters.
+ /// NormalizeDatePattern will take in an ICU date pattern and return the equivalent .NET date pattern.
+ /// </summary>
+ /// <remarks>
+ /// see Date Field Symbol Table in http://userguide.icu-project.org/formatparse/datetime
+ /// and https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx
+ /// </remarks>
+ private static string NormalizeDatePattern(string input)
+ {
+ StringBuilder destination = StringBuilderCache.Acquire(input.Length);
+
+ int index = 0;
+ while (index < input.Length)
+ {
+ switch (input[index])
+ {
+ case '\'':
+ // single quotes escape characters, like 'de' in es-SP
+ // so read verbatim until the next single quote
+ destination.Append(input[index++]);
+ while (index < input.Length)
+ {
+ char current = input[index++];
+ destination.Append(current);
+ if (current == '\'')
+ {
+ break;
+ }
+ }
+ break;
+ case 'E':
+ case 'e':
+ case 'c':
+ // 'E' in ICU is the day of the week, which maps to 3 or 4 'd's in .NET
+ // 'e' in ICU is the local day of the week, which has no representation in .NET, but
+ // maps closest to 3 or 4 'd's in .NET
+ // 'c' in ICU is the stand-alone day of the week, which has no representation in .NET, but
+ // maps closest to 3 or 4 'd's in .NET
+ NormalizeDayOfWeek(input, destination, ref index);
+ break;
+ case 'L':
+ case 'M':
+ // 'L' in ICU is the stand-alone name of the month,
+ // which maps closest to 'M' in .NET since it doesn't support stand-alone month names in patterns
+ // 'M' in both ICU and .NET is the month,
+ // but ICU supports 5 'M's, which is the super short month name
+ int occurrences = CountOccurrences(input, input[index], ref index);
+ if (occurrences > 4)
+ {
+ // 5 'L's or 'M's in ICU is the super short name, which maps closest to MMM in .NET
+ occurrences = 3;
+ }
+ destination.Append('M', occurrences);
+ break;
+ case 'G':
+ // 'G' in ICU is the era, which maps to 'g' in .NET
+ occurrences = CountOccurrences(input, 'G', ref index);
+
+ // it doesn't matter how many 'G's, since .NET only supports 'g' or 'gg', and they
+ // have the same meaning
+ destination.Append('g');
+ break;
+ case 'y':
+ // a single 'y' in ICU is the year with no padding or trimming.
+ // a single 'y' in .NET is the year with 1 or 2 digits
+ // so convert any single 'y' to 'yyyy'
+ occurrences = CountOccurrences(input, 'y', ref index);
+ if (occurrences == 1)
+ {
+ occurrences = 4;
+ }
+ destination.Append('y', occurrences);
+ break;
+ default:
+ const string unsupportedDateFieldSymbols = "YuUrQqwWDFg";
+ Contract.Assert(unsupportedDateFieldSymbols.IndexOf(input[index]) == -1,
+ string.Format(CultureInfo.InvariantCulture,
+ "Encountered an unexpected date field symbol '{0}' from ICU which has no known corresponding .NET equivalent.",
+ input[index]));
+
+ destination.Append(input[index++]);
+ break;
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(destination);
+ }
+
+ private static void NormalizeDayOfWeek(string input, StringBuilder destination, ref int index)
+ {
+ char dayChar = input[index];
+ int occurrences = CountOccurrences(input, dayChar, ref index);
+ occurrences = Math.Max(occurrences, 3);
+ if (occurrences > 4)
+ {
+ // 5 and 6 E/e/c characters in ICU is the super short names, which maps closest to ddd in .NET
+ occurrences = 3;
+ }
+
+ destination.Append('d', occurrences);
+ }
+
+ private static int CountOccurrences(string input, char value, ref int index)
+ {
+ int startIndex = index;
+ while (index < input.Length && input[index] == value)
+ {
+ index++;
+ }
+
+ return index - startIndex;
+ }
+
+ [SecuritySafeCritical]
+ private static bool EnumMonthNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] monthNames)
+ {
+ monthNames = null;
+
+ CallbackContext callbackContext = new CallbackContext();
+ bool result = EnumCalendarInfo(localeName, calendarId, dataType, callbackContext);
+ if (result)
+ {
+ // the month-name arrays are expected to have 13 elements. If ICU only returns 12, add an
+ // extra empty string to fill the array.
+ if (callbackContext.Results.Count == 12)
+ {
+ callbackContext.Results.Add(string.Empty);
+ }
+
+ monthNames = callbackContext.Results.ToArray();
+ }
+
+ return result;
+ }
+
+ [SecuritySafeCritical]
+ private static bool EnumEraNames(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] eraNames)
+ {
+ bool result = EnumCalendarInfo(localeName, calendarId, dataType, out eraNames);
+
+ // .NET expects that only the Japanese calendars have more than 1 era.
+ // So for other calendars, only return the latest era.
+ if (calendarId != CalendarId.JAPAN && calendarId != CalendarId.JAPANESELUNISOLAR && eraNames.Length > 0)
+ {
+ string[] latestEraName = new string[] { eraNames[eraNames.Length - 1] };
+ eraNames = latestEraName;
+ }
+
+ return result;
+ }
+
+ [SecuritySafeCritical]
+ internal static bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, out string[] calendarData)
+ {
+ calendarData = null;
+
+ CallbackContext callbackContext = new CallbackContext();
+ bool result = EnumCalendarInfo(localeName, calendarId, dataType, callbackContext);
+ if (result)
+ {
+ calendarData = callbackContext.Results.ToArray();
+ }
+
+ return result;
+ }
+
+ [SecuritySafeCritical]
+ private static bool EnumCalendarInfo(string localeName, CalendarId calendarId, CalendarDataType dataType, CallbackContext callbackContext)
+ {
+ GCHandle context = GCHandle.Alloc(callbackContext);
+ try
+ {
+ return Interop.GlobalizationInterop.EnumCalendarInfo(EnumCalendarInfoCallback, localeName, calendarId, dataType, (IntPtr)context);
+ }
+ finally
+ {
+ context.Free();
+ }
+ }
+
+ [SecuritySafeCritical]
+ private static void EnumCalendarInfoCallback(string calendarString, IntPtr context)
+ {
+ CallbackContext callbackContext = (CallbackContext)((GCHandle)context).Target;
+
+ if (callbackContext.DisallowDuplicates)
+ {
+ foreach (string existingResult in callbackContext.Results)
+ {
+ if (string.Equals(calendarString, existingResult, StringComparison.Ordinal))
+ {
+ // the value is already in the results, so don't add it again
+ return;
+ }
+ }
+ }
+
+ callbackContext.Results.Add(calendarString);
+ }
+
+ private class CallbackContext
+ {
+ private List<string> _results = new List<string>();
+
+ public CallbackContext()
+ {
+ }
+
+ public List<string> Results { get { return _results; } }
+
+ public bool DisallowDuplicates { get; set; }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs
new file mode 100644
index 0000000000..bdf3ff1881
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CalendarData.Windows.cs
@@ -0,0 +1,469 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+
+namespace System.Globalization
+{
+ internal partial class CalendarData
+ {
+ private bool LoadCalendarDataFromSystem(String localeName, CalendarId calendarId)
+ {
+ bool ret = true;
+
+ uint useOverrides = this.bUseUserOverrides ? 0 : CAL_NOUSEROVERRIDE;
+
+ //
+ // Windows doesn't support some calendars right now, so remap those.
+ //
+ switch (calendarId)
+ {
+ case CalendarId.JAPANESELUNISOLAR: // Data looks like Japanese
+ calendarId = CalendarId.JAPAN;
+ break;
+ case CalendarId.JULIAN: // Data looks like gregorian US
+ case CalendarId.CHINESELUNISOLAR: // Algorithmic, so actual data is irrelevent
+ case CalendarId.SAKA: // reserved to match Office but not implemented in our code, so data is irrelevent
+ case CalendarId.LUNAR_ETO_CHN: // reserved to match Office but not implemented in our code, so data is irrelevent
+ case CalendarId.LUNAR_ETO_KOR: // reserved to match Office but not implemented in our code, so data is irrelevent
+ case CalendarId.LUNAR_ETO_ROKUYOU: // reserved to match Office but not implemented in our code, so data is irrelevent
+ case CalendarId.KOREANLUNISOLAR: // Algorithmic, so actual data is irrelevent
+ case CalendarId.TAIWANLUNISOLAR: // Algorithmic, so actual data is irrelevent
+ calendarId = CalendarId.GREGORIAN_US;
+ break;
+ }
+
+ //
+ // Special handling for some special calendar due to OS limitation.
+ // This includes calendar like Taiwan calendar, UmAlQura calendar, etc.
+ //
+ CheckSpecialCalendar(ref calendarId, ref localeName);
+
+ // Numbers
+ ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_ITWODIGITYEARMAX | useOverrides, out this.iTwoDigitYearMax);
+
+ // Strings
+ ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_SCALNAME, out this.sNativeName);
+ ret &= CallGetCalendarInfoEx(localeName, calendarId, CAL_SMONTHDAY | useOverrides, out this.sMonthDay);
+
+ // String Arrays
+ // Formats
+ ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SSHORTDATE, LOCALE_SSHORTDATE | useOverrides, out this.saShortDates);
+ ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SLONGDATE, LOCALE_SLONGDATE | useOverrides, out this.saLongDates);
+
+ // Get the YearMonth pattern.
+ ret &= CallEnumCalendarInfo(localeName, calendarId, CAL_SYEARMONTH, LOCALE_SYEARMONTH, out this.saYearMonths);
+
+ // Day & Month Names
+ // These are all single calType entries, 1 per day, so we have to make 7 or 13 calls to collect all the names
+
+ // Day
+ // Note that we're off-by-one since managed starts on sunday and windows starts on monday
+ ret &= GetCalendarDayInfo(localeName, calendarId, CAL_SDAYNAME7, out this.saDayNames);
+ ret &= GetCalendarDayInfo(localeName, calendarId, CAL_SABBREVDAYNAME7, out this.saAbbrevDayNames);
+
+ // Month names
+ ret &= GetCalendarMonthInfo(localeName, calendarId, CAL_SMONTHNAME1, out this.saMonthNames);
+ ret &= GetCalendarMonthInfo(localeName, calendarId, CAL_SABBREVMONTHNAME1, out this.saAbbrevMonthNames);
+
+ //
+ // The following LCTYPE are not supported in some platforms. If the call fails,
+ // don't return a failure.
+ //
+ GetCalendarDayInfo(localeName, calendarId, CAL_SSHORTESTDAYNAME7, out this.saSuperShortDayNames);
+
+ // Gregorian may have genitive month names
+ if (calendarId == CalendarId.GREGORIAN)
+ {
+ GetCalendarMonthInfo(localeName, calendarId, CAL_SMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, out this.saMonthGenitiveNames);
+ GetCalendarMonthInfo(localeName, calendarId, CAL_SABBREVMONTHNAME1 | CAL_RETURN_GENITIVE_NAMES, out this.saAbbrevMonthGenitiveNames);
+ }
+
+ // Calendar Parts Names
+ // This doesn't get always get localized names for gregorian (not available in windows < 7)
+ // so: eg: coreclr on win < 7 won't get these
+ CallEnumCalendarInfo(localeName, calendarId, CAL_SERASTRING, 0, out this.saEraNames);
+ CallEnumCalendarInfo(localeName, calendarId, CAL_SABBREVERASTRING, 0, out this.saAbbrevEraNames);
+
+ //
+ // Calendar Era Info
+ // Note that calendar era data (offsets, etc) is hard coded for each calendar since this
+ // data is implementation specific and not dynamic (except perhaps Japanese)
+ //
+
+ // Clean up the escaping of the formats
+ this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates);
+ this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates);
+ this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths);
+ this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay);
+
+ return ret;
+ }
+
+ // Get native two digit year max
+ internal static int GetTwoDigitYearMax(CalendarId calendarId)
+ {
+ int twoDigitYearMax = -1;
+
+ if (!CallGetCalendarInfoEx(null, calendarId, (uint)CAL_ITWODIGITYEARMAX, out twoDigitYearMax))
+ {
+ twoDigitYearMax = -1;
+ }
+
+ return twoDigitYearMax;
+ }
+
+ // Call native side to figure out which calendars are allowed
+ internal static int GetCalendars(String localeName, bool useUserOverride, CalendarId[] calendars)
+ {
+ EnumCalendarsData data = new EnumCalendarsData();
+ data.userOverride = 0;
+ data.calendars = new LowLevelList<int>();
+
+ // First call GetLocaleInfo if necessary
+ if (useUserOverride)
+ {
+ // They want user overrides, see if the user calendar matches the input calendar
+ int userCalendar = Interop.mincore.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE);
+
+ // If we got a default, then use it as the first calendar
+ if (userCalendar != 0)
+ {
+ data.userOverride = userCalendar;
+ data.calendars.Add(userCalendar);
+ }
+ }
+
+ GCHandle contextHandle = GCHandle.Alloc(data);
+ try
+ {
+ // Now call the enumeration API. Work is done by our callback function
+ IntPtr callback = AddrofIntrinsics.AddrOf<Func<IntPtr, uint, IntPtr, IntPtr, Interop.BOOL>>(EnumCalendarsCallback);
+ Interop.mincore.EnumCalendarInfoExEx(callback, localeName, ENUM_ALL_CALENDARS, null, CAL_ICALINTVALUE, (IntPtr)contextHandle);
+ }
+ finally
+ {
+ contextHandle.Free();
+ }
+
+ // Copy to the output array
+ for (int i = 0; i < Math.Min(calendars.Length, data.calendars.Count); i++)
+ calendars[i] = (CalendarId)data.calendars[i];
+
+ // Now we have a list of data, return the count
+ return data.calendars.Count;
+ }
+
+ private static bool SystemSupportsTaiwaneseCalendar()
+ {
+ string data;
+ // Taiwanese calendar get listed as one of the optional zh-TW calendars only when having zh-TW UI
+ return CallGetCalendarInfoEx("zh-TW", CalendarId.TAIWAN, CAL_SCALNAME, out data);
+ }
+
+ // PAL Layer ends here
+
+ private const uint CAL_RETURN_NUMBER = 0x20000000;
+ private const uint CAL_RETURN_GENITIVE_NAMES = 0x10000000;
+ private const uint CAL_NOUSEROVERRIDE = 0x80000000;
+ private const uint CAL_SCALNAME = 0x00000002;
+ private const uint CAL_SMONTHDAY = 0x00000038;
+ private const uint CAL_SSHORTDATE = 0x00000005;
+ private const uint CAL_SLONGDATE = 0x00000006;
+ private const uint CAL_SYEARMONTH = 0x0000002f;
+ private const uint CAL_SDAYNAME7 = 0x0000000d;
+ private const uint CAL_SABBREVDAYNAME7 = 0x00000014;
+ private const uint CAL_SMONTHNAME1 = 0x00000015;
+ private const uint CAL_SABBREVMONTHNAME1 = 0x00000022;
+ private const uint CAL_SSHORTESTDAYNAME7 = 0x00000037;
+ private const uint CAL_SERASTRING = 0x00000004;
+ private const uint CAL_SABBREVERASTRING = 0x00000039;
+ private const uint CAL_ICALINTVALUE = 0x00000001;
+ private const uint CAL_ITWODIGITYEARMAX = 0x00000030;
+
+ private const uint ENUM_ALL_CALENDARS = 0xffffffff;
+
+ private const uint LOCALE_SSHORTDATE = 0x0000001F;
+ private const uint LOCALE_SLONGDATE = 0x00000020;
+ private const uint LOCALE_SYEARMONTH = 0x00001006;
+ private const uint LOCALE_ICALENDARTYPE = 0x00001009;
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // For calendars like Gregorain US/Taiwan/UmAlQura, they are not available
+ // in all OS or all localized versions of OS.
+ // If OS does not support these calendars, we will fallback by using the
+ // appropriate fallback calendar and locale combination to retrieve data from OS.
+ //
+ // Parameters:
+ // __deref_inout pCalendarInt:
+ // Pointer to the calendar ID. This will be updated to new fallback calendar ID if needed.
+ // __in_out pLocaleNameStackBuffer
+ // Pointer to the StackSString object which holds the locale name to be checked.
+ // This will be updated to new fallback locale name if needed.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ private static void CheckSpecialCalendar(ref CalendarId calendar, ref string localeName)
+ {
+ string data;
+
+ // Gregorian-US isn't always available in the OS, however it is the same for all locales
+ switch (calendar)
+ {
+ case CalendarId.GREGORIAN_US:
+ // See if this works
+ if (!CallGetCalendarInfoEx(localeName, calendar, CAL_SCALNAME, out data))
+ {
+ // Failed, set it to a locale (fa-IR) that's alway has Gregorian US available in the OS
+ localeName = "fa-IR";
+ }
+ // See if that works
+ if (!CallGetCalendarInfoEx(localeName, calendar, CAL_SCALNAME, out data))
+ {
+ // Failed again, just use en-US with the gregorian calendar
+ localeName = "en-US";
+ calendar = CalendarId.GREGORIAN;
+ }
+ break;
+ case CalendarId.TAIWAN:
+ // Taiwan calendar data is not always in all language version of OS due to Geopolical reasons.
+ // It is only available in zh-TW localized versions of Windows.
+ // Let's check if OS supports it. If not, fallback to Greogrian localized for Taiwan calendar.
+ if (!SystemSupportsTaiwaneseCalendar())
+ {
+ calendar = CalendarId.GREGORIAN;
+ }
+ break;
+ }
+ }
+
+ private static bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out int data)
+ {
+ return (Interop.mincore.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType | CAL_RETURN_NUMBER, IntPtr.Zero, 0, out data) != 0);
+ }
+
+ private static unsafe bool CallGetCalendarInfoEx(string localeName, CalendarId calendar, uint calType, out string data)
+ {
+ const int BUFFER_LENGTH = 80;
+
+ // The maximum size for values returned from GetCalendarInfoEx is 80 characters.
+ char* buffer = stackalloc char[BUFFER_LENGTH];
+
+ int ret = Interop.mincore.GetCalendarInfoEx(localeName, (uint)calendar, IntPtr.Zero, calType, (IntPtr)buffer, BUFFER_LENGTH, IntPtr.Zero);
+ if (ret > 0)
+ {
+ if (buffer[ret - 1] == '\0')
+ {
+ ret--; // don't include the null termination in the string
+ }
+ data = new string(buffer, 0, ret);
+ return true;
+ }
+ data = "";
+ return false;
+ }
+
+ // Context for EnumCalendarInfoExEx callback.
+ private class EnumData
+ {
+ public string userOverride;
+ public LowLevelList<string> strings;
+ }
+
+ // EnumCalendarInfoExEx callback itself.
+ [NativeCallable(CallingConvention = CallingConvention.StdCall)]
+ private static unsafe Interop.BOOL EnumCalendarInfoCallback(IntPtr lpCalendarInfoString, uint calendar, IntPtr pReserved, IntPtr lParam)
+ {
+ EnumData context = (EnumData)((GCHandle)lParam).Target;
+ try
+ {
+ string calendarInfo = new string((char*)lpCalendarInfoString);
+
+ // If we had a user override, check to make sure this differs
+ if (context.userOverride != calendarInfo)
+ context.strings.Add(calendarInfo);
+
+ return Interop.BOOL.TRUE;
+ }
+ catch (Exception)
+ {
+ return Interop.BOOL.FALSE;
+ }
+ }
+
+ private static unsafe bool CallEnumCalendarInfo(string localeName, CalendarId calendar, uint calType, uint lcType, out string[] data)
+ {
+ EnumData context = new EnumData();
+ context.userOverride = null;
+ context.strings = new LowLevelList<string>();
+
+ // First call GetLocaleInfo if necessary
+ if (((lcType != 0) && ((lcType & CAL_NOUSEROVERRIDE) == 0)) &&
+ // Get user locale, see if it matches localeName.
+ // Note that they should match exactly, including letter case
+ GetUserDefaultLocaleName() == localeName)
+ {
+ // They want user overrides, see if the user calendar matches the input calendar
+ CalendarId userCalendar = (CalendarId)Interop.mincore.GetLocaleInfoExInt(localeName, LOCALE_ICALENDARTYPE);
+
+ // If the calendars were the same, see if the locales were the same
+ if (userCalendar == calendar)
+ {
+ // They matched, get the user override since locale & calendar match
+ string res = Interop.mincore.GetLocaleInfoEx(localeName, lcType);
+
+ // if it succeeded remember the override for the later callers
+ if (res != "")
+ {
+ // Remember this was the override (so we can look for duplicates later in the enum function)
+ context.userOverride = res;
+
+ // Add to the result strings.
+ context.strings.Add(res);
+ }
+ }
+ }
+
+ GCHandle contextHandle = GCHandle.Alloc(context);
+ try
+ {
+ // Now call the enumeration API. Work is done by our callback function
+ IntPtr callback = AddrofIntrinsics.AddrOf<Func<IntPtr, uint, IntPtr, IntPtr, Interop.BOOL>>(EnumCalendarInfoCallback);
+ Interop.mincore.EnumCalendarInfoExEx(callback, localeName, (uint)calendar, null, calType, (IntPtr)contextHandle);
+ }
+ finally
+ {
+ contextHandle.Free();
+ }
+
+ // Now we have a list of data, fail if we didn't find anything.
+ if (context.strings.Count == 0)
+ {
+ data = null;
+ return false;
+ }
+
+ string[] output = context.strings.ToArray();
+
+ if (calType == CAL_SABBREVERASTRING || calType == CAL_SERASTRING)
+ {
+ // Eras are enumerated backwards. (oldest era name first, but
+ // Japanese calendar has newest era first in array, and is only
+ // calendar with multiple eras)
+ Array.Reverse(output, 0, output.Length);
+ }
+
+ data = output;
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the native day names
+ //
+ // NOTE: There's a disparity between .Net & windows day orders, the input day should
+ // start with Sunday
+ //
+ // Parameters:
+ // OUT pOutputStrings The output string[] value.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ private static bool GetCalendarDayInfo(string localeName, CalendarId calendar, uint calType, out string[] outputStrings)
+ {
+ bool result = true;
+
+ //
+ // We'll need a new array of 7 items
+ //
+ string[] results = new string[7];
+
+ // Get each one of them
+ for (int i = 0; i < 7; i++, calType++)
+ {
+ result &= CallGetCalendarInfoEx(localeName, calendar, calType, out results[i]);
+
+ // On the first iteration we need to go from CAL_SDAYNAME7 to CAL_SDAYNAME1, so subtract 7 before the ++ happens
+ // This is because the framework starts on sunday and windows starts on monday when counting days
+ if (i == 0)
+ calType -= 7;
+ }
+
+ outputStrings = results;
+
+ return result;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the native month names
+ //
+ // Parameters:
+ // OUT pOutputStrings The output string[] value.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ private static bool GetCalendarMonthInfo(string localeName, CalendarId calendar, uint calType, out string[] outputStrings)
+ {
+ //
+ // We'll need a new array of 13 items
+ //
+ string[] results = new string[13];
+
+ // Get each one of them
+ for (int i = 0; i < 13; i++, calType++)
+ {
+ if (!CallGetCalendarInfoEx(localeName, calendar, calType, out results[i]))
+ results[i] = "";
+ }
+
+ outputStrings = results;
+
+ return true;
+ }
+
+ //
+ // struct to help our calendar data enumaration callback
+ //
+ private class EnumCalendarsData
+ {
+ public int userOverride; // user override value (if found)
+ public LowLevelList<int> calendars; // list of calendars found so far
+ }
+
+ [NativeCallable(CallingConvention = CallingConvention.StdCall)]
+ private static Interop.BOOL EnumCalendarsCallback(IntPtr lpCalendarInfoString, uint calendar, IntPtr reserved, IntPtr lParam)
+ {
+ EnumCalendarsData context = (EnumCalendarsData)((GCHandle)lParam).Target;
+ try
+ {
+ // If we had a user override, check to make sure this differs
+ if (context.userOverride != calendar)
+ context.calendars.Add((int)calendar);
+
+ return Interop.BOOL.TRUE;
+ }
+ catch (Exception)
+ {
+ return Interop.BOOL.FALSE;
+ }
+ }
+
+ private static unsafe String GetUserDefaultLocaleName()
+ {
+ const int LOCALE_NAME_MAX_LENGTH = 85;
+ const uint LOCALE_SNAME = 0x0000005c;
+ const string LOCALE_NAME_USER_DEFAULT = null;
+
+ int result;
+ char* localeName = stackalloc char[LOCALE_NAME_MAX_LENGTH];
+ result = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME, localeName, LOCALE_NAME_MAX_LENGTH);
+
+ return result <= 0 ? "" : new String(localeName, 0, result - 1); // exclude the null termination
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CalendarData.cs b/src/mscorlib/corefx/System/Globalization/CalendarData.cs
new file mode 100644
index 0000000000..2dbd1b8069
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CalendarData.cs
@@ -0,0 +1,381 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+
+namespace System.Globalization
+{
+ // List of calendar data
+ // Note the we cache overrides.
+ // Note that localized names (resource names) aren't available from here.
+ //
+ // NOTE: Calendars depend on the locale name that creates it. Only a few
+ // properties are available without locales using CalendarData.GetCalendar(CalendarData)
+
+ internal partial class CalendarData
+ {
+ // Max calendars
+ internal const int MAX_CALENDARS = 23;
+
+ // Identity
+ internal String sNativeName; // Calendar Name for the locale
+
+ // Formats
+ internal String[] saShortDates; // Short Data format, default first
+ internal String[] saYearMonths; // Year/Month Data format, default first
+ internal String[] saLongDates; // Long Data format, default first
+ internal String sMonthDay; // Month/Day format
+
+ // Calendar Parts Names
+ internal String[] saEraNames; // Names of Eras
+ internal String[] saAbbrevEraNames; // Abbreviated Era Names
+ internal String[] saAbbrevEnglishEraNames; // Abbreviated Era Names in English
+ internal String[] saDayNames; // Day Names, null to use locale data, starts on Sunday
+ internal String[] saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
+ internal String[] saSuperShortDayNames; // Super short Day of week names
+ internal String[] saMonthNames; // Month Names (13)
+ internal String[] saAbbrevMonthNames; // Abbrev Month Names (13)
+ internal String[] saMonthGenitiveNames; // Genitive Month Names (13)
+ internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
+ internal String[] saLeapYearMonthNames; // Multiple strings for the month names in a leap year.
+
+ // Integers at end to make marshaller happier
+ internal int iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
+ internal int iCurrentEra = 0; // current era # (usually 1)
+
+ // Use overrides?
+ internal bool bUseUserOverrides; // True if we want user overrides.
+
+ // Static invariant for the invariant locale
+ internal static CalendarData Invariant;
+
+ // Private constructor
+ private CalendarData() { }
+
+ // Invariant constructor
+ static CalendarData()
+ {
+ // Set our default/gregorian US calendar data
+ // Calendar IDs are 1-based, arrays are 0 based.
+ CalendarData invariant = new CalendarData();
+
+ // Set default data for calendar
+ // Note that we don't load resources since this IS NOT supposed to change (by definition)
+ invariant.sNativeName = "Gregorian Calendar"; // Calendar Name
+
+ // Year
+ invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
+ invariant.iCurrentEra = 1; // Current era #
+
+ // Formats
+ invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
+ invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy" }; // long date format
+ invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format
+ invariant.sMonthDay = "MMMM dd"; // Month day pattern
+
+ // Calendar Parts Names
+ invariant.saEraNames = new String[] { "A.D." }; // Era names
+ invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names
+ invariant.saAbbrevEnglishEraNames = new String[] { "AD" }; // Abbreviated era names in English
+ invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
+ invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
+ invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
+ invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December", String.Empty}; // month names
+ invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names
+ invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant)
+ invariant.saAbbrevMonthGenitiveNames = invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
+ invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant)
+
+ invariant.bUseUserOverrides = false;
+
+ // Calendar was built, go ahead and assign it...
+ Invariant = invariant;
+ }
+
+ //
+ // Get a bunch of data for a calendar
+ //
+ internal CalendarData(String localeName, CalendarId calendarId, bool bUseUserOverrides)
+ {
+ this.bUseUserOverrides = bUseUserOverrides;
+
+ if (!LoadCalendarDataFromSystem(localeName, calendarId))
+ {
+ Contract.Assert(false, "[CalendarData] LoadCalendarDataFromSystem call isn't expected to fail for calendar " + calendarId + " locale " + localeName);
+
+ // Something failed, try invariant for missing parts
+ // This is really not good, but we don't want the callers to crash.
+ if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale.
+
+ // Formats
+ if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first
+ if (this.saYearMonths == null) this.saYearMonths = Invariant.saYearMonths; // Year/Month Data format, default first
+ if (this.saLongDates == null) this.saLongDates = Invariant.saLongDates; // Long Data format, default first
+ if (this.sMonthDay == null) this.sMonthDay = Invariant.sMonthDay; // Month/Day format
+
+ // Calendar Parts Names
+ if (this.saEraNames == null) this.saEraNames = Invariant.saEraNames; // Names of Eras
+ if (this.saAbbrevEraNames == null) this.saAbbrevEraNames = Invariant.saAbbrevEraNames; // Abbreviated Era Names
+ if (this.saAbbrevEnglishEraNames == null) this.saAbbrevEnglishEraNames = Invariant.saAbbrevEnglishEraNames; // Abbreviated Era Names in English
+ if (this.saDayNames == null) this.saDayNames = Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday
+ if (this.saAbbrevDayNames == null) this.saAbbrevDayNames = Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
+ if (this.saSuperShortDayNames == null) this.saSuperShortDayNames = Invariant.saSuperShortDayNames; // Super short Day of week names
+ if (this.saMonthNames == null) this.saMonthNames = Invariant.saMonthNames; // Month Names (13)
+ if (this.saAbbrevMonthNames == null) this.saAbbrevMonthNames = Invariant.saAbbrevMonthNames; // Abbrev Month Names (13)
+ // Genitive and Leap names can follow the fallback below
+ }
+
+ if (calendarId == CalendarId.TAIWAN)
+ {
+ if (SystemSupportsTaiwaneseCalendar())
+ {
+ // We got the month/day names from the OS (same as gregorian), but the native name is wrong
+ this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6";
+ }
+ else
+ {
+ this.sNativeName = String.Empty;
+ }
+ }
+
+ // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc)
+ if (this.saMonthGenitiveNames == null || this.saMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
+ this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant)
+ if (this.saAbbrevMonthGenitiveNames == null || this.saAbbrevMonthGenitiveNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
+ this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
+ if (this.saLeapYearMonthNames == null || this.saLeapYearMonthNames.Length == 0 || String.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
+ this.saLeapYearMonthNames = this.saMonthNames;
+
+ InitializeEraNames(localeName, calendarId);
+
+ InitializeAbbreviatedEraNames(localeName, calendarId);
+
+ // Abbreviated English Era Names are only used for the Japanese calendar.
+ if (calendarId == CalendarId.JAPAN)
+ {
+ this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames();
+ }
+ else
+ {
+ // For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars)
+ this.saAbbrevEnglishEraNames = new String[] { "" };
+ }
+
+ // Japanese is the only thing with > 1 era. Its current era # is how many ever
+ // eras are in the array. (And the others all have 1 string in the array)
+ this.iCurrentEra = this.saEraNames.Length;
+ }
+
+ private void InitializeEraNames(string localeName, CalendarId calendarId)
+ {
+ // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows
+ switch (calendarId)
+ {
+ // For Localized Gregorian we really expect the data from the OS.
+ case CalendarId.GREGORIAN:
+ // Fallback for CoreCLR < Win7 or culture.dll missing
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ {
+ this.saEraNames = new String[] { "A.D." };
+ }
+ break;
+
+ // The rest of the calendars have constant data, so we'll just use that
+ case CalendarId.GREGORIAN_US:
+ case CalendarId.JULIAN:
+ this.saEraNames = new String[] { "A.D." };
+ break;
+ case CalendarId.HEBREW:
+ this.saEraNames = new String[] { "C.E." };
+ break;
+ case CalendarId.HIJRI:
+ case CalendarId.UMALQURA:
+ if (localeName == "dv-MV")
+ {
+ // Special case for Divehi
+ this.saEraNames = new String[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
+ }
+ else
+ {
+ this.saEraNames = new String[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
+ }
+ break;
+ case CalendarId.GREGORIAN_ARABIC:
+ case CalendarId.GREGORIAN_XLIT_ENGLISH:
+ case CalendarId.GREGORIAN_XLIT_FRENCH:
+ // These are all the same:
+ this.saEraNames = new String[] { "\x0645" };
+ break;
+
+ case CalendarId.GREGORIAN_ME_FRENCH:
+ this.saEraNames = new String[] { "ap. J.-C." };
+ break;
+
+ case CalendarId.TAIWAN:
+ if (SystemSupportsTaiwaneseCalendar())
+ {
+ this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" };
+ }
+ else
+ {
+ this.saEraNames = new String[] { String.Empty };
+ }
+ break;
+
+ case CalendarId.KOREA:
+ this.saEraNames = new String[] { "\xb2e8\xae30" };
+ break;
+
+ case CalendarId.THAI:
+ this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" };
+ break;
+
+ case CalendarId.JAPAN:
+ case CalendarId.JAPANESELUNISOLAR:
+ this.saEraNames = JapaneseCalendar.EraNames();
+ break;
+
+ case CalendarId.PERSIAN:
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ {
+ this.saEraNames = new String[] { "\x0647\x002e\x0634" };
+ }
+ break;
+
+ default:
+ // Most calendars are just "A.D."
+ this.saEraNames = Invariant.saEraNames;
+ break;
+ }
+ }
+
+ private void InitializeAbbreviatedEraNames(string localeName, CalendarId calendarId)
+ {
+ // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows
+ switch (calendarId)
+ {
+ // For Localized Gregorian we really expect the data from the OS.
+ case CalendarId.GREGORIAN:
+ // Fallback for CoreCLR < Win7 or culture.dll missing
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ {
+ this.saAbbrevEraNames = new String[] { "AD" };
+ }
+ break;
+
+ // The rest of the calendars have constant data, so we'll just use that
+ case CalendarId.GREGORIAN_US:
+ case CalendarId.JULIAN:
+ this.saAbbrevEraNames = new String[] { "AD" };
+ break;
+ case CalendarId.JAPAN:
+ case CalendarId.JAPANESELUNISOLAR:
+ this.saAbbrevEraNames = JapaneseCalendar.AbbrevEraNames();
+ break;
+ case CalendarId.HIJRI:
+ case CalendarId.UMALQURA:
+ if (localeName == "dv-MV")
+ {
+ // Special case for Divehi
+ this.saAbbrevEraNames = new String[] { "\x0780\x002e" };
+ }
+ else
+ {
+ this.saAbbrevEraNames = new String[] { "\x0647\x0640" };
+ }
+ break;
+ case CalendarId.TAIWAN:
+ // Get era name and abbreviate it
+ this.saAbbrevEraNames = new String[1];
+ if (this.saEraNames[0].Length == 4)
+ {
+ this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2, 2);
+ }
+ else
+ {
+ this.saAbbrevEraNames[0] = this.saEraNames[0];
+ }
+ break;
+
+ case CalendarId.PERSIAN:
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ {
+ this.saAbbrevEraNames = this.saEraNames;
+ }
+ break;
+
+ default:
+ // Most calendars just use the full name
+ this.saAbbrevEraNames = this.saEraNames;
+ break;
+ }
+ }
+
+ internal static CalendarData GetCalendarData(CalendarId calendarId)
+ {
+ //
+ // Get a calendar.
+ // Unfortunately we depend on the locale in the OS, so we need a locale
+ // no matter what. So just get the appropriate calendar from the
+ // appropriate locale here
+ //
+
+ // Get a culture name
+ // TODO: Note that this doesn't handle the new calendars (lunisolar, etc)
+ String culture = CalendarIdToCultureName(calendarId);
+
+ // Return our calendar
+ return CultureInfo.GetCultureInfo(culture).m_cultureData.GetCalendar(calendarId);
+ }
+
+ private static String CalendarIdToCultureName(CalendarId calendarId)
+ {
+ switch (calendarId)
+ {
+ case CalendarId.GREGORIAN_US:
+ return "fa-IR"; // "fa-IR" Iran
+
+ case CalendarId.JAPAN:
+ return "ja-JP"; // "ja-JP" Japan
+
+ case CalendarId.TAIWAN:
+ return "zh-TW"; // zh-TW Taiwan
+
+ case CalendarId.KOREA:
+ return "ko-KR"; // "ko-KR" Korea
+
+ case CalendarId.HIJRI:
+ case CalendarId.GREGORIAN_ARABIC:
+ case CalendarId.UMALQURA:
+ return "ar-SA"; // "ar-SA" Saudi Arabia
+
+ case CalendarId.THAI:
+ return "th-TH"; // "th-TH" Thailand
+
+ case CalendarId.HEBREW:
+ return "he-IL"; // "he-IL" Israel
+
+ case CalendarId.GREGORIAN_ME_FRENCH:
+ return "ar-DZ"; // "ar-DZ" Algeria
+
+ case CalendarId.GREGORIAN_XLIT_ENGLISH:
+ case CalendarId.GREGORIAN_XLIT_FRENCH:
+ return "ar-IQ"; // "ar-IQ"; Iraq
+
+ default:
+ // Default to gregorian en-US
+ break;
+ }
+
+ return "en-US";
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs b/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs
new file mode 100644
index 0000000000..490951e1f0
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CalendarWeekRule.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Globalization
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CalendarWeekRule
+ {
+ FirstDay = 0, // Week 1 begins on the first day of the year
+
+ FirstFullWeek = 1, // Week 1 begins on first FirstDayOfWeek not before the first day of the year
+
+ FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year
+ };
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs
new file mode 100644
index 0000000000..ba7601b420
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CalendricalCalculationsHelper.cs
@@ -0,0 +1,413 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ internal class CalendricalCalculationsHelper
+ {
+ private const double FullCircleOfArc = 360.0; // 360.0;
+ private const int HalfCircleOfArc = 180;
+ private const double TwelveHours = 0.5; // half a day
+ private const double Noon2000Jan01 = 730120.5;
+ internal const double MeanTropicalYearInDays = 365.242189;
+ private const double MeanSpeedOfSun = MeanTropicalYearInDays / FullCircleOfArc;
+ private const double LongitudeSpring = 0.0;
+ private const double TwoDegreesAfterSpring = 2.0;
+ private const int SecondsPerDay = 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds
+
+ private const int DaysInUniformLengthCentury = 36525;
+ private const int SecondsPerMinute = 60;
+ private const int MinutesPerDegree = 60;
+
+ private static readonly long StartOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1));
+ private static readonly long StartOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1));
+
+ private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 };
+ private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 };
+ private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 };
+ private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 };
+ private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 };
+ private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 };
+ private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 };
+ private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) };
+ private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 };
+ private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 };
+
+ private static double RadiansFromDegrees(double degree)
+ {
+ return degree * Math.PI / 180;
+ }
+
+ private static double SinOfDegree(double degree)
+ {
+ return Math.Sin(RadiansFromDegrees(degree));
+ }
+
+ private static double CosOfDegree(double degree)
+ {
+ return Math.Cos(RadiansFromDegrees(degree));
+ }
+ private static double TanOfDegree(double degree)
+ {
+ return Math.Tan(RadiansFromDegrees(degree));
+ }
+
+ public static double Angle(int degrees, int minutes, double seconds)
+ {
+ return ((seconds / SecondsPerMinute + minutes) / MinutesPerDegree) + degrees;
+ }
+
+ private static double Obliquity(double julianCenturies)
+ {
+ return PolynomialSum(s_coefficients, julianCenturies);
+ }
+
+ internal static long GetNumberOfDays(DateTime date)
+ {
+ return date.Ticks / GregorianCalendar.TicksPerDay;
+ }
+
+ private static int GetGregorianYear(double numberOfDays)
+ {
+ return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * GregorianCalendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year;
+ }
+
+ private enum CorrectionAlgorithm
+ {
+ Default,
+ Year1988to2019,
+ Year1900to1987,
+ Year1800to1899,
+ Year1700to1799,
+ Year1620to1699
+ }
+
+ private struct EphemerisCorrectionAlgorithmMap
+ {
+ public EphemerisCorrectionAlgorithmMap(int year, CorrectionAlgorithm algorithm)
+ {
+ _lowestYear = year;
+ _algorithm = algorithm;
+ }
+
+ internal int _lowestYear;
+ internal CorrectionAlgorithm _algorithm;
+ };
+
+ private static readonly EphemerisCorrectionAlgorithmMap[] s_ephemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[]
+ {
+ // lowest year that starts algorithm, algorithm to use
+ new EphemerisCorrectionAlgorithmMap(2020, CorrectionAlgorithm.Default),
+ new EphemerisCorrectionAlgorithmMap(1988, CorrectionAlgorithm.Year1988to2019),
+ new EphemerisCorrectionAlgorithmMap(1900, CorrectionAlgorithm.Year1900to1987),
+ new EphemerisCorrectionAlgorithmMap(1800, CorrectionAlgorithm.Year1800to1899),
+ new EphemerisCorrectionAlgorithmMap(1700, CorrectionAlgorithm.Year1700to1799),
+ new EphemerisCorrectionAlgorithmMap(1620, CorrectionAlgorithm.Year1620to1699),
+ new EphemerisCorrectionAlgorithmMap(int.MinValue, CorrectionAlgorithm.Default) // default must be last
+ };
+
+ private static double Reminder(double divisor, double dividend)
+ {
+ double whole = Math.Floor(divisor / dividend);
+ return divisor - (dividend * whole);
+ }
+
+ private static double NormalizeLongitude(double longitude)
+ {
+ longitude = Reminder(longitude, FullCircleOfArc);
+ if (longitude < 0)
+ {
+ longitude += FullCircleOfArc;
+ }
+ return longitude;
+ }
+
+ static public double AsDayFraction(double longitude)
+ {
+ return longitude / FullCircleOfArc;
+ }
+
+ private static double PolynomialSum(double[] coefficients, double indeterminate)
+ {
+ double sum = coefficients[0];
+ double indeterminateRaised = 1;
+ for (int i = 1; i < coefficients.Length; i++)
+ {
+ indeterminateRaised *= indeterminate;
+ sum += (coefficients[i] * indeterminateRaised);
+ }
+
+ return sum;
+ }
+
+ private static double CenturiesFrom1900(int gregorianYear)
+ {
+ long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1));
+ return (double)(july1stOfYear - StartOf1900Century) / DaysInUniformLengthCentury;
+ }
+
+ // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges
+ private static double DefaultEphemerisCorrection(int gregorianYear)
+ {
+ Contract.Assert(gregorianYear < 1620 || 2020 <= gregorianYear);
+ long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1));
+ double daysSinceStartOf1810 = january1stOfYear - StartOf1810;
+ double x = TwelveHours + daysSinceStartOf1810;
+ return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay;
+ }
+
+ private static double EphemerisCorrection1988to2019(int gregorianYear)
+ {
+ Contract.Assert(1988 <= gregorianYear && gregorianYear <= 2019);
+ return (double)(gregorianYear - 1933) / SecondsPerDay;
+ }
+
+ private static double EphemerisCorrection1900to1987(int gregorianYear)
+ {
+ Contract.Assert(1900 <= gregorianYear && gregorianYear <= 1987);
+ double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
+ return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900);
+ }
+
+ private static double EphemerisCorrection1800to1899(int gregorianYear)
+ {
+ Contract.Assert(1800 <= gregorianYear && gregorianYear <= 1899);
+ double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
+ return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900);
+ }
+
+ private static double EphemerisCorrection1700to1799(int gregorianYear)
+ {
+ Contract.Assert(1700 <= gregorianYear && gregorianYear <= 1799);
+ double yearsSince1700 = gregorianYear - 1700;
+ return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay;
+ }
+
+ private static double EphemerisCorrection1620to1699(int gregorianYear)
+ {
+ Contract.Assert(1620 <= gregorianYear && gregorianYear <= 1699);
+ double yearsSince1600 = gregorianYear - 1600;
+ return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay;
+ }
+
+ // ephemeris-correction: correction to account for the slowing down of the rotation of the earth
+ private static double EphemerisCorrection(double time)
+ {
+ int year = GetGregorianYear(time);
+ foreach (EphemerisCorrectionAlgorithmMap map in s_ephemerisCorrectionTable)
+ {
+ if (map._lowestYear <= year)
+ {
+ switch (map._algorithm)
+ {
+ case CorrectionAlgorithm.Default: return DefaultEphemerisCorrection(year);
+ case CorrectionAlgorithm.Year1988to2019: return EphemerisCorrection1988to2019(year);
+ case CorrectionAlgorithm.Year1900to1987: return EphemerisCorrection1900to1987(year);
+ case CorrectionAlgorithm.Year1800to1899: return EphemerisCorrection1800to1899(year);
+ case CorrectionAlgorithm.Year1700to1799: return EphemerisCorrection1700to1799(year);
+ case CorrectionAlgorithm.Year1620to1699: return EphemerisCorrection1620to1699(year);
+ }
+
+ break; // break the loop and assert eventually
+ }
+ }
+
+ Contract.Assert(false, "Not expected to come here");
+ return DefaultEphemerisCorrection(year);
+ }
+
+ static public double JulianCenturies(double moment)
+ {
+ double dynamicalMoment = moment + EphemerisCorrection(moment);
+ return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury;
+ }
+
+ private static bool IsNegative(double value)
+ {
+ return Math.Sign(value) == -1;
+ }
+
+ private static double CopySign(double value, double sign)
+ {
+ return (IsNegative(value) == IsNegative(sign)) ? value : -value;
+ }
+
+ // equation-of-time; approximate the difference between apparent solar time and mean solar time
+ // formal definition is EOT = GHA - GMHA
+ // GHA is the Greenwich Hour Angle of the apparent (actual) Sun
+ // GMHA is the Greenwich Mean Hour Angle of the mean (fictitious) Sun
+ // http://www.esrl.noaa.gov/gmd/grad/solcalc/
+ // http://en.wikipedia.org/wiki/Equation_of_time
+ private static double EquationOfTime(double time)
+ {
+ double julianCenturies = JulianCenturies(time);
+ double lambda = PolynomialSum(s_lambdaCoefficients, julianCenturies);
+ double anomaly = PolynomialSum(s_anomalyCoefficients, julianCenturies);
+ double eccentricity = PolynomialSum(s_eccentricityCoefficients, julianCenturies);
+
+ double epsilon = Obliquity(julianCenturies);
+ double tanHalfEpsilon = TanOfDegree(epsilon / 2);
+ double y = tanHalfEpsilon * tanHalfEpsilon;
+
+ double dividend = ((y * SinOfDegree(2 * lambda))
+ - (2 * eccentricity * SinOfDegree(anomaly))
+ + (4 * eccentricity * y * SinOfDegree(anomaly) * CosOfDegree(2 * lambda))
+ - (0.5 * Math.Pow(y, 2) * SinOfDegree(4 * lambda))
+ - (1.25 * Math.Pow(eccentricity, 2) * SinOfDegree(2 * anomaly)));
+ double divisor = 2 * Math.PI;
+ double equation = dividend / divisor;
+
+ // approximation of equation of time is not valid for dates that are many millennia in the past or future
+ // thus limited to a half day
+ return CopySign(Math.Min(Math.Abs(equation), TwelveHours), equation);
+ }
+
+ private static double AsLocalTime(double apparentMidday, double longitude)
+ {
+ // slightly inaccurate since equation of time takes mean time not apparent time as its argument, but the difference is negligible
+ double universalTime = apparentMidday - AsDayFraction(longitude);
+ return apparentMidday - EquationOfTime(universalTime);
+ }
+
+ // midday
+ static public double Midday(double date, double longitude)
+ {
+ return AsLocalTime(date + TwelveHours, longitude) - AsDayFraction(longitude);
+ }
+
+ private static double InitLongitude(double longitude)
+ {
+ return NormalizeLongitude(longitude + HalfCircleOfArc) - HalfCircleOfArc;
+ }
+
+ // midday-in-tehran
+ static public double MiddayAtPersianObservationSite(double date)
+ {
+ return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time
+ }
+
+ private static double PeriodicTerm(double julianCenturies, int x, double y, double z)
+ {
+ return x * SinOfDegree(y + z * julianCenturies);
+ }
+
+ private static double SumLongSequenceOfPeriodicTerms(double julianCenturies)
+ {
+ double sum = 0.0;
+ sum += PeriodicTerm(julianCenturies, 403406, 270.54861, 0.9287892);
+ sum += PeriodicTerm(julianCenturies, 195207, 340.19128, 35999.1376958);
+ sum += PeriodicTerm(julianCenturies, 119433, 63.91854, 35999.4089666);
+ sum += PeriodicTerm(julianCenturies, 112392, 331.2622, 35998.7287385);
+ sum += PeriodicTerm(julianCenturies, 3891, 317.843, 71998.20261);
+ sum += PeriodicTerm(julianCenturies, 2819, 86.631, 71998.4403);
+ sum += PeriodicTerm(julianCenturies, 1721, 240.052, 36000.35726);
+ sum += PeriodicTerm(julianCenturies, 660, 310.26, 71997.4812);
+ sum += PeriodicTerm(julianCenturies, 350, 247.23, 32964.4678);
+ sum += PeriodicTerm(julianCenturies, 334, 260.87, -19.441);
+ sum += PeriodicTerm(julianCenturies, 314, 297.82, 445267.1117);
+ sum += PeriodicTerm(julianCenturies, 268, 343.14, 45036.884);
+ sum += PeriodicTerm(julianCenturies, 242, 166.79, 3.1008);
+ sum += PeriodicTerm(julianCenturies, 234, 81.53, 22518.4434);
+ sum += PeriodicTerm(julianCenturies, 158, 3.5, -19.9739);
+ sum += PeriodicTerm(julianCenturies, 132, 132.75, 65928.9345);
+ sum += PeriodicTerm(julianCenturies, 129, 182.95, 9038.0293);
+ sum += PeriodicTerm(julianCenturies, 114, 162.03, 3034.7684);
+ sum += PeriodicTerm(julianCenturies, 99, 29.8, 33718.148);
+ sum += PeriodicTerm(julianCenturies, 93, 266.4, 3034.448);
+ sum += PeriodicTerm(julianCenturies, 86, 249.2, -2280.773);
+ sum += PeriodicTerm(julianCenturies, 78, 157.6, 29929.992);
+ sum += PeriodicTerm(julianCenturies, 72, 257.8, 31556.493);
+ sum += PeriodicTerm(julianCenturies, 68, 185.1, 149.588);
+ sum += PeriodicTerm(julianCenturies, 64, 69.9, 9037.75);
+ sum += PeriodicTerm(julianCenturies, 46, 8.0, 107997.405);
+ sum += PeriodicTerm(julianCenturies, 38, 197.1, -4444.176);
+ sum += PeriodicTerm(julianCenturies, 37, 250.4, 151.771);
+ sum += PeriodicTerm(julianCenturies, 32, 65.3, 67555.316);
+ sum += PeriodicTerm(julianCenturies, 29, 162.7, 31556.08);
+ sum += PeriodicTerm(julianCenturies, 28, 341.5, -4561.54);
+ sum += PeriodicTerm(julianCenturies, 27, 291.6, 107996.706);
+ sum += PeriodicTerm(julianCenturies, 27, 98.5, 1221.655);
+ sum += PeriodicTerm(julianCenturies, 25, 146.7, 62894.167);
+ sum += PeriodicTerm(julianCenturies, 24, 110.0, 31437.369);
+ sum += PeriodicTerm(julianCenturies, 21, 5.2, 14578.298);
+ sum += PeriodicTerm(julianCenturies, 21, 342.6, -31931.757);
+ sum += PeriodicTerm(julianCenturies, 20, 230.9, 34777.243);
+ sum += PeriodicTerm(julianCenturies, 18, 256.1, 1221.999);
+ sum += PeriodicTerm(julianCenturies, 17, 45.3, 62894.511);
+ sum += PeriodicTerm(julianCenturies, 14, 242.9, -4442.039);
+ sum += PeriodicTerm(julianCenturies, 13, 115.2, 107997.909);
+ sum += PeriodicTerm(julianCenturies, 13, 151.8, 119.066);
+ sum += PeriodicTerm(julianCenturies, 13, 285.3, 16859.071);
+ sum += PeriodicTerm(julianCenturies, 12, 53.3, -4.578);
+ sum += PeriodicTerm(julianCenturies, 10, 126.6, 26895.292);
+ sum += PeriodicTerm(julianCenturies, 10, 205.7, -39.127);
+ sum += PeriodicTerm(julianCenturies, 10, 85.9, 12297.536);
+ sum += PeriodicTerm(julianCenturies, 10, 146.1, 90073.778);
+ return sum;
+ }
+
+ private static double Aberration(double julianCenturies)
+ {
+ return (0.0000974 * CosOfDegree(177.63 + (35999.01848 * julianCenturies))) - 0.005575;
+ }
+
+ private static double Nutation(double julianCenturies)
+ {
+ double a = PolynomialSum(s_coefficientsA, julianCenturies);
+ double b = PolynomialSum(s_coefficientsB, julianCenturies);
+ return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b));
+ }
+
+ static public double Compute(double time)
+ {
+ double julianCenturies = JulianCenturies(time);
+ double lambda = 282.7771834
+ + (36000.76953744 * julianCenturies)
+ + (0.000005729577951308232 * SumLongSequenceOfPeriodicTerms(julianCenturies));
+
+ double longitude = lambda + Aberration(julianCenturies) + Nutation(julianCenturies);
+ return InitLongitude(longitude);
+ }
+
+ static public double AsSeason(double longitude)
+ {
+ return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude;
+ }
+
+ private static double EstimatePrior(double longitude, double time)
+ {
+ double timeSunLastAtLongitude = time - (MeanSpeedOfSun * AsSeason(InitLongitude(Compute(time) - longitude)));
+ double longitudeErrorDelta = InitLongitude(Compute(timeSunLastAtLongitude) - longitude);
+ return Math.Min(time, timeSunLastAtLongitude - (MeanSpeedOfSun * longitudeErrorDelta));
+ }
+
+ // persian-new-year-on-or-before
+ // number of days is the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ internal static long PersianNewYearOnOrBefore(long numberOfDays)
+ {
+ double date = (double)numberOfDays;
+
+ double approx = EstimatePrior(LongitudeSpring, MiddayAtPersianObservationSite(date));
+ long lowerBoundNewYearDay = (long)Math.Floor(approx) - 1;
+ long upperBoundNewYearDay = lowerBoundNewYearDay + 3; // estimate is generally within a day of the actual occurrance (at the limits, the error expands, since the calculations rely on the mean tropical year which changes...)
+ long day = lowerBoundNewYearDay;
+ for (; day != upperBoundNewYearDay; ++day)
+ {
+ double midday = MiddayAtPersianObservationSite((double)day);
+ double l = Compute(midday);
+ if ((LongitudeSpring <= l) && (l <= TwoDegreesAfterSpring))
+ {
+ break;
+ }
+ }
+ Contract.Assert(day != upperBoundNewYearDay);
+
+ return day - 1;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs
new file mode 100644
index 0000000000..4cb95fb8f1
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfo.cs
@@ -0,0 +1,339 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class implements a set of methods for retrieving
+// character type information. Character type information is
+// independent of culture and region.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Threading;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Security;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ public static partial class CharUnicodeInfo
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //
+ // Native methods to access the Unicode category data tables in charinfo.nlp.
+ //
+ internal const char HIGH_SURROGATE_START = '\ud800';
+ internal const char HIGH_SURROGATE_END = '\udbff';
+ internal const char LOW_SURROGATE_START = '\udc00';
+ internal const char LOW_SURROGATE_END = '\udfff';
+
+ internal const int UNICODE_CATEGORY_OFFSET = 0;
+ internal const int BIDI_CATEGORY_OFFSET = 1;
+
+
+
+ // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
+ internal const int UNICODE_PLANE01_START = 0x10000;
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Convert the BMP character or surrogate pointed by index to a UTF32 value.
+ // This is similar to Char.ConvertToUTF32, but the difference is that
+ // it does not throw exceptions when invalid surrogate characters are passed in.
+ //
+ // WARNING: since it doesn't throw an exception it CAN return a value
+ // in the surrogate range D800-DFFF, which are not legal unicode values.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int InternalConvertToUtf32(String s, int index)
+ {
+ Contract.Assert(s != null, "s != null");
+ Contract.Assert(index >= 0 && index < s.Length, "index < s.Length");
+ if (index < s.Length - 1)
+ {
+ int temp1 = (int)s[index] - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= 0x3ff)
+ {
+ int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= 0x3ff)
+ {
+ // Convert the surrogate to UTF32 and get the result.
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return ((int)s[index]);
+ }
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Convert a character or a surrogate pair starting at index of string s
+ // to UTF32 value.
+ //
+ // Parameters:
+ // s The string
+ // index The starting index. It can point to a BMP character or
+ // a surrogate pair.
+ // len The length of the string.
+ // charLength [out] If the index points to a BMP char, charLength
+ // will be 1. If the index points to a surrogate pair,
+ // charLength will be 2.
+ //
+ // WARNING: since it doesn't throw an exception it CAN return a value
+ // in the surrogate range D800-DFFF, which are not legal unicode values.
+ //
+ // Returns:
+ // The UTF32 value
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int InternalConvertToUtf32(String s, int index, out int charLength)
+ {
+ Contract.Assert(s != null, "s != null");
+ Contract.Assert(s.Length > 0, "s.Length > 0");
+ Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
+ charLength = 1;
+ if (index < s.Length - 1)
+ {
+ int temp1 = (int)s[index] - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= 0x3ff)
+ {
+ int temp2 = (int)s[index + 1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= 0x3ff)
+ {
+ // Convert the surrogate to UTF32 and get the result.
+ charLength++;
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return ((int)s[index]);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsWhiteSpace
+ //
+ // Determines if the given character is a white space character.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static bool IsWhiteSpace(String s, int index)
+ {
+ Contract.Assert(s != null, "s!=null");
+ Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
+
+ UnicodeCategory uc = GetUnicodeCategory(s, index);
+ // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator".
+ // And U+2029 is th eonly character which is under the category "ParagraphSeparator".
+ switch (uc)
+ {
+ case (UnicodeCategory.SpaceSeparator):
+ case (UnicodeCategory.LineSeparator):
+ case (UnicodeCategory.ParagraphSeparator):
+ return (true);
+ }
+ return (false);
+ }
+
+
+ internal static bool IsWhiteSpace(char c)
+ {
+ UnicodeCategory uc = GetUnicodeCategory(c);
+ // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator".
+ // And U+2029 is th eonly character which is under the category "ParagraphSeparator".
+ switch (uc)
+ {
+ case (UnicodeCategory.SpaceSeparator):
+ case (UnicodeCategory.LineSeparator):
+ case (UnicodeCategory.ParagraphSeparator):
+ return (true);
+ }
+
+ return (false);
+ }
+
+
+ //
+ // This is called by the public char and string, index versions
+ //
+ // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character
+ //
+ internal unsafe static double InternalGetNumericValue(int ch)
+ {
+ Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
+ // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
+ ushort index = s_pNumericLevel1Index[ch >> 8];
+ // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
+ // The offset is referred to an float item in m_pNumericFloatData.
+ // Note that & has the lower precedence than addition, so don't forget the parathesis.
+ index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)];
+
+ fixed (ushort* pUshortPtr = &(s_pNumericLevel1Index[index]))
+ {
+ byte* pBytePtr = (byte*)pUshortPtr;
+ fixed (byte* pByteNum = s_pNumericValues)
+ {
+ double* pDouble = (double*)pByteNum;
+ return pDouble[pBytePtr[(ch & 0x000f)]];
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Returns the numeric value associated with the character c. If the character is a fraction,
+ // the return value will not be an integer. If the character does not have a numeric value, the return value is -1.
+ //
+ //Returns:
+ // the numeric value for the specified Unicode character. If the character does not have a numeric value, the return value is -1.
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // ArgumentNullException
+ // ArgumentOutOfRangeException
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static double GetNumericValue(char ch)
+ {
+ return (InternalGetNumericValue(ch));
+ }
+
+
+ public static double GetNumericValue(String s, int index)
+ {
+ if (s == null)
+ {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length)
+ {
+ throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index);
+ }
+ Contract.EndContractBlock();
+ return (InternalGetNumericValue(InternalConvertToUtf32(s, index)));
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(char ch)
+ {
+ return (InternalGetUnicodeCategory(ch));
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ {
+ if (s == null)
+ throw new ArgumentNullException("s");
+ if (((uint)index) >= ((uint)s.Length))
+ {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return InternalGetUnicodeCategory(s, index);
+ }
+
+ internal unsafe static UnicodeCategory InternalGetUnicodeCategory(int ch)
+ {
+ return ((UnicodeCategory)InternalGetCategoryValue(ch, UNICODE_CATEGORY_OFFSET));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Action: Returns the Unicode Category property for the character c.
+ //Returns:
+ // an value in UnicodeCategory enum
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // None
+ //
+ //Note that this API will return values for D800-DF00 surrogate halves.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal unsafe static byte InternalGetCategoryValue(int ch, int offset)
+ {
+ Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
+ // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
+ ushort index = s_pCategoryLevel1Index[ch >> 8];
+ // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
+ // Note that & has the lower precedence than addition, so don't forget the parathesis.
+ index = s_pCategoryLevel1Index[index + ((ch >> 4) & 0x000f)];
+
+ fixed (ushort* pUshortPtr = &(s_pCategoryLevel1Index[index]))
+ {
+ byte* pBytePtr = (byte*)pUshortPtr;
+ // Get the result from the 0 -3 bit of ch.
+ byte valueIndex = pBytePtr[(ch & 0x000f)];
+ byte uc = s_pCategoriesValue[valueIndex * 2 + offset];
+ //
+ // Make sure that OtherNotAssigned is the last category in UnicodeCategory.
+ // If that changes, change the following assertion as well.
+ //
+ //Contract.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category");
+ return (uc);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Action: Returns the Unicode Category property for the character c.
+ //Returns:
+ // an value in UnicodeCategory enum
+ //Arguments:
+ // value a Unicode String
+ // index Index for the specified string.
+ //Exceptions:
+ // None
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index)
+ {
+ Contract.Assert(value != null, "value can not be null");
+ Contract.Assert(index < value.Length, "index < value.Length");
+
+ return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
+ // If the character is a valid surrogate pair, charLength will return 2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength)
+ {
+ Contract.Assert(str != null, "str can not be null");
+ Contract.Assert(str.Length > 0, "str.Length > 0"); ;
+ Contract.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length");
+
+ return (InternalGetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength)));
+ }
+
+ internal static bool IsCombiningCategory(UnicodeCategory uc)
+ {
+ Contract.Assert(uc >= 0, "uc >= 0");
+ return (
+ uc == UnicodeCategory.NonSpacingMark ||
+ uc == UnicodeCategory.SpacingCombiningMark ||
+ uc == UnicodeCategory.EnclosingMark
+ );
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs
new file mode 100644
index 0000000000..7284cfd3bc
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CharUnicodeInfoData.cs
@@ -0,0 +1,1222 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Globalization
+{
+ public static partial class CharUnicodeInfo
+ {
+ // THE FOLLOWING DATA IS AUTO GENERATED BY GenUnicodeProp.pl SCRIPT UNDER THE TOOLS FOLDER
+ // PLEASE DON'T MODIFY BY HAND
+
+
+ // 12:4:4 index table of the Unicode cateogry data.
+ private static ushort[] s_pCategoryLevel1Index = new ushort[]
+ {
+ 0x1100, 0x1110, 0x1120, 0x1130, 0x1140, 0x1150, 0x1160, 0x1170, 0x1180, 0x1190, 0x11a0, 0x11b0, 0x11c0, 0x11d0, 0x11e0, 0x11f0,
+ 0x1200, 0x1210, 0x1220, 0x1230, 0x1240, 0x1210, 0x1250, 0x1260, 0x1270, 0x1280, 0x1290, 0x12a0, 0x12b0, 0x12c0, 0x12d0, 0x12e0,
+ 0x12f0, 0x1300, 0x1310, 0x1320, 0x1330, 0x1340, 0x1350, 0x1360, 0x1370, 0x1380, 0x1390, 0x13a0, 0x13b0, 0x13c0, 0x13d0, 0x13e0,
+ 0x13f0, 0x1400, 0x1410, 0x1420, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1430, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1440,
+ 0x1450, 0x1210, 0x1210, 0x1210, 0x1460, 0x1210, 0x1470, 0x1480, 0x1490, 0x14a0, 0x14b0, 0x14c0, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x14d0, 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e0, 0x14e0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x1210, 0x1500, 0x1510, 0x1520, 0x1530, 0x1540, 0x1550,
+ 0x1560, 0x1570, 0x1580, 0x1590, 0x15a0, 0x15b0, 0x1210, 0x15c0, 0x15d0, 0x15e0, 0x15f0, 0x1600, 0x1610, 0x1620, 0x1630, 0x1620,
+ 0x1640, 0x1650, 0x1660, 0x1670, 0x1680, 0x1690, 0x16a0, 0x16b0, 0x16c0, 0x1620, 0x16d0, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1210, 0x1210, 0x1210, 0x16e0, 0x16f0, 0x1700, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1710, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1210, 0x1210, 0x1720, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1210, 0x1210, 0x1730, 0x1740, 0x1620, 0x1620, 0x1620, 0x1750,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1760, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1770, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1780, 0x1790, 0x17a0, 0x17b0, 0x17c0, 0x17d0, 0x17e0, 0x17f0, 0x1370, 0x1370, 0x1800, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1810, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1820, 0x1620,
+ 0x1830, 0x1840, 0x1850, 0x1860, 0x1870, 0x1880, 0x1890, 0x18a0, 0x18b0, 0x18c0, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x18d0, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x18e0, 0x18f0, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210,
+ 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1210, 0x1900, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1210, 0x1210, 0x1910, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1920, 0x1930, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620, 0x1620,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x1940,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0,
+ 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x14f0, 0x1940,
+ 0x1950, 0x1958, 0x1960, 0x1968, 0x1970, 0x1978, 0x1980, 0x1988, 0x1990, 0x1998, 0x19a0, 0x19a8, 0x19b0, 0x19b8, 0x19c0, 0x19c8,
+ 0x19d0, 0x19d0, 0x19d0, 0x19d8, 0x19e0, 0x19d0, 0x19d0, 0x19e8, 0x19f0, 0x19f8, 0x1a00, 0x1a08, 0x1a10, 0x1a18, 0x19d0, 0x1a20,
+ 0x19d0, 0x19d0, 0x19d0, 0x1a28, 0x1a30, 0x19c0, 0x19c0, 0x19c0, 0x19c0, 0x1a38, 0x19c0, 0x1a40, 0x1a48, 0x1a50, 0x1a58, 0x1a60,
+ 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a70, 0x1a78, 0x1a80, 0x1a88, 0x19c0, 0x1a90, 0x1a98, 0x19d0, 0x1aa0,
+ 0x19b0, 0x19b0, 0x19b0, 0x19c0, 0x19c0, 0x19c0, 0x19d0, 0x19d0, 0x1aa8, 0x19d0, 0x19d0, 0x19d0, 0x1ab0, 0x19d0, 0x19d0, 0x19d0,
+ 0x19d0, 0x19d0, 0x19d0, 0x1ab8, 0x19b0, 0x1ac0, 0x1ac8, 0x19c0, 0x1ad0, 0x1ad8, 0x1a68, 0x1ae0, 0x1ae8, 0x1af0, 0x1af8, 0x1b00,
+ 0x1b08, 0x1b10, 0x1b18, 0x1b18, 0x1b20, 0x1a68, 0x1b28, 0x1b30, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b38, 0x1b40, 0x1b48,
+ 0x1b50, 0x1b58, 0x1b18, 0x1a68, 0x1b60, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b68, 0x1b70, 0x1b78, 0x1af0, 0x1b80, 0x1b88,
+ 0x1af0, 0x1b90, 0x1b98, 0x1ba0, 0x1af0, 0x1ba8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1b18, 0x1bb8, 0x1bb0, 0x1bb0, 0x1bc0, 0x1a68,
+ 0x1bc8, 0x1bd0, 0x1bd0, 0x1bd8, 0x1be0, 0x1be8, 0x1bf0, 0x1bf8, 0x1c00, 0x1c08, 0x1c10, 0x1c18, 0x1c20, 0x1c28, 0x1c30, 0x1c38,
+ 0x1c40, 0x1c08, 0x1c10, 0x1c48, 0x1c50, 0x1c58, 0x1c60, 0x1c68, 0x1c70, 0x1c78, 0x1c10, 0x1c80, 0x1c88, 0x1c90, 0x1c30, 0x1c98,
+ 0x1ca0, 0x1c08, 0x1c10, 0x1ca8, 0x1cb0, 0x1cb8, 0x1c30, 0x1cc0, 0x1cc8, 0x1cd0, 0x1cd8, 0x1ce0, 0x1ce8, 0x1cf0, 0x1c60, 0x1cf8,
+ 0x1d00, 0x1d08, 0x1c10, 0x1d10, 0x1d18, 0x1d20, 0x1c30, 0x1d28, 0x1d30, 0x1d08, 0x1c10, 0x1d38, 0x1d40, 0x1d48, 0x1c30, 0x1d50,
+ 0x1d30, 0x1d08, 0x1bd0, 0x1d58, 0x1d60, 0x1d68, 0x1c30, 0x1d70, 0x1d78, 0x1d80, 0x1bd0, 0x1d88, 0x1d90, 0x1d98, 0x1c60, 0x1da0,
+ 0x1da8, 0x1bd0, 0x1bd0, 0x1db0, 0x1db8, 0x1dc0, 0x1bb0, 0x1bb0, 0x1dc8, 0x1dd0, 0x1dd8, 0x1de0, 0x1de8, 0x1df0, 0x1bb0, 0x1bb0,
+ 0x1df8, 0x1e00, 0x1e08, 0x1e10, 0x1e18, 0x1bd0, 0x1e20, 0x1e28, 0x1e30, 0x1e38, 0x1a68, 0x1e40, 0x1e48, 0x1e50, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1e58, 0x1e60, 0x1e68, 0x1e70, 0x1e78, 0x1e80, 0x1e88, 0x1e90, 0x19b0, 0x19b0, 0x1e98, 0x1bd0, 0x1bd0, 0x1ea0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1ea8, 0x1eb0, 0x1bd0, 0x1bd0, 0x1ea8, 0x1bd0, 0x1bd0, 0x1eb8, 0x1ec0, 0x1ec8, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1ec0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1ed0, 0x1ed8, 0x1ee0, 0x1bd0, 0x1ee8, 0x19b0, 0x19b0, 0x19b0, 0x19b0, 0x19b0, 0x1ef0,
+ 0x1ef8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f00, 0x1bd0, 0x1f08, 0x1f10, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f18, 0x1f20,
+ 0x1f28, 0x1f30, 0x1bd0, 0x1f38, 0x1bd0, 0x1f40, 0x1f28, 0x1f48, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f50, 0x1f58, 0x1f60, 0x1f68, 0x1f70,
+ 0x1f78, 0x1f68, 0x1bd0, 0x1bd0, 0x1f80, 0x1bd0, 0x1bd0, 0x1f88, 0x1bd0, 0x1bd0, 0x1f90, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f98,
+ 0x1bd0, 0x1fa0, 0x1fa8, 0x1fb0, 0x1fb8, 0x1bd0, 0x1fc0, 0x1fc8, 0x1bd0, 0x1bd0, 0x1fd0, 0x1bd0, 0x1fd8, 0x1fe0, 0x1fe8, 0x1fe8,
+ 0x1bd0, 0x1ff0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1ff8, 0x2000, 0x2008, 0x1f68, 0x1f68, 0x2010, 0x2018, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x2020, 0x1bd0, 0x1bd0, 0x2028, 0x2030, 0x1e68, 0x2038, 0x2040, 0x2048, 0x1bd0, 0x2050, 0x2058, 0x1bd0, 0x1bd0, 0x2060, 0x2068,
+ 0x1bd0, 0x1bd0, 0x2070, 0x2078, 0x2080, 0x2058, 0x1bd0, 0x2088, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x2090, 0x2098, 0x20a0, 0x20a8,
+ 0x19c0, 0x19c0, 0x20b0, 0x20b8, 0x20b8, 0x20b8, 0x20c0, 0x20c8, 0x19c0, 0x20d0, 0x20b8, 0x20b8, 0x1a68, 0x1a68, 0x1a68, 0x20d8,
+ 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x20e0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0,
+ 0x20e8, 0x20f0, 0x20e8, 0x20e8, 0x20f0, 0x20f8, 0x20e8, 0x2100, 0x2108, 0x2108, 0x2108, 0x2110, 0x2118, 0x2120, 0x2128, 0x2130,
+ 0x2138, 0x2140, 0x2148, 0x2150, 0x2158, 0x2160, 0x2168, 0x2170, 0x2178, 0x2180, 0x2188, 0x2190, 0x1bb0, 0x2198, 0x21a0, 0x21a8,
+ 0x21b0, 0x21b8, 0x21c0, 0x21c8, 0x21d0, 0x21d8, 0x21e0, 0x21e0, 0x21e8, 0x21f0, 0x21f8, 0x1fe8, 0x2200, 0x2208, 0x1fe8, 0x2210,
+ 0x2218, 0x2220, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218,
+ 0x2228, 0x1fe8, 0x2230, 0x2238, 0x2240, 0x2240, 0x2240, 0x2248, 0x1fe8, 0x2250, 0x2218, 0x2258, 0x1fe8, 0x2260, 0x2268, 0x2270,
+ 0x1fe8, 0x1fe8, 0x2278, 0x1bb0, 0x2270, 0x1bb0, 0x21d8, 0x21d8, 0x2280, 0x2288, 0x2240, 0x2240, 0x2240, 0x2240, 0x2290, 0x21d8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2298, 0x22a0, 0x1fe8, 0x1fe8, 0x22a8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x22b0, 0x1fe8, 0x1fe8, 0x1fe8, 0x22b8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x22c0, 0x22c8, 0x21d8, 0x22d0, 0x1fe8, 0x1fe8, 0x22d8, 0x2218, 0x22e0, 0x2218,
+ 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240,
+ 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x22e8, 0x22f0, 0x2218, 0x2218, 0x2218, 0x22f8, 0x2218, 0x2300,
+ 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218, 0x2218,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x2218, 0x2308, 0x1fe8, 0x1fe8, 0x2310, 0x1fe8, 0x2318, 0x1fe8, 0x2320, 0x2328, 0x2330, 0x2338, 0x1bb0,
+ 0x19b0, 0x19b0, 0x2340, 0x19c0, 0x19c0, 0x2348, 0x2350, 0x2358, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x19d0, 0x2360, 0x2368,
+ 0x19c0, 0x19c0, 0x2370, 0x1bd0, 0x1bd0, 0x1bd0, 0x2378, 0x2380, 0x1bd0, 0x2388, 0x2390, 0x2390, 0x2390, 0x2390, 0x1a68, 0x1a68,
+ 0x2398, 0x23a0, 0x23a8, 0x23b0, 0x23b8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1fe8, 0x23c0, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x23c8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x23d0, 0x1bb0, 0x23d8,
+ 0x23e0, 0x23e8, 0x23f0, 0x23f8, 0x1da8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2400, 0x1ef8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2408,
+ 0x2410, 0x1bd0, 0x1fc0, 0x1da8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fa0, 0x2418, 0x1bd0, 0x2420, 0x1fe8, 0x1fe8, 0x23c8, 0x1bd0,
+ 0x2240, 0x2428, 0x2430, 0x2240, 0x2438, 0x2440, 0x2240, 0x2448, 0x2430, 0x2240, 0x2240, 0x2450, 0x2458, 0x2240, 0x2240, 0x2460,
+ 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2468, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2470, 0x2240, 0x2478,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f98, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1f98, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x2480, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1e20, 0x1fe8, 0x1fe8, 0x1fe8, 0x2278, 0x1bd0, 0x1bd0, 0x2088,
+ 0x2488, 0x1bd0, 0x2490, 0x1bb0, 0x19d0, 0x19d0, 0x2498, 0x24a0, 0x19d0, 0x24a8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x24b0, 0x24b8,
+ 0x1a60, 0x24c0, 0x24c8, 0x24d0, 0x19d0, 0x19d0, 0x19d0, 0x24d8, 0x24e0, 0x24e8, 0x24f0, 0x24f8, 0x1bb0, 0x1bb0, 0x1bb0, 0x2500,
+ 0x2508, 0x1bd0, 0x2510, 0x2518, 0x1bd0, 0x1bd0, 0x1bd0, 0x2520, 0x2528, 0x1bd0, 0x1bd0, 0x2530, 0x2538, 0x1f68, 0x1a68, 0x2540,
+ 0x2058, 0x1bd0, 0x2548, 0x1bd0, 0x2550, 0x2558, 0x1bd0, 0x1e20, 0x1bc8, 0x1bd0, 0x1bd0, 0x2560, 0x2568, 0x2570, 0x2578, 0x2580,
+ 0x1bd0, 0x1bd0, 0x2588, 0x2590, 0x2598, 0x25a0, 0x1bd0, 0x25a8, 0x1bd0, 0x1bd0, 0x1bd0, 0x25b0, 0x25b8, 0x25c0, 0x25c8, 0x25d0,
+ 0x25d8, 0x25e0, 0x2390, 0x19c0, 0x19c0, 0x25e8, 0x25f0, 0x19c0, 0x19c0, 0x19c0, 0x19c0, 0x19c0, 0x1bd0, 0x1bd0, 0x25f8, 0x1f68,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2600, 0x1bd0, 0x2608, 0x1bd0, 0x1bd0, 0x1fd0,
+ 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610, 0x2610,
+ 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fc0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fd8, 0x1bb0, 0x1bb0,
+ 0x2620, 0x2628, 0x2630, 0x2638, 0x2640, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x2648, 0x2650, 0x2658, 0x1b18, 0x1b18,
+ 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18,
+ 0x1b18, 0x1b18, 0x1b18, 0x2660, 0x1bb0, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x2668, 0x1b18, 0x1b18, 0x2670, 0x1bb0, 0x1bb0, 0x2678,
+ 0x1a68, 0x2680, 0x1a68, 0x2688, 0x2690, 0x2698, 0x26a0, 0x26a8, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x1b18, 0x26b0,
+ 0x26b8, 0x1968, 0x1970, 0x1978, 0x1980, 0x26c0, 0x26c8, 0x26d0, 0x1bd0, 0x26d8, 0x1bd0, 0x1fa0, 0x26e0, 0x26e8, 0x26f0, 0x26f8,
+ 0x2700, 0x1bd0, 0x1ec8, 0x2708, 0x1fc0, 0x1fc0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2420,
+ 0x2710, 0x2718, 0x2718, 0x2720, 0x2728, 0x2728, 0x2728, 0x2730, 0x2738, 0x23d8, 0x2740, 0x1bb0, 0x1bb0, 0x2240, 0x2240, 0x2748,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1e20, 0x1bd0, 0x1bd0, 0x1bd0, 0x1c90, 0x2750, 0x2758,
+ 0x1bd0, 0x1bd0, 0x2760, 0x1bd0, 0x2768, 0x1bd0, 0x1bd0, 0x2770, 0x1bd0, 0x2778, 0x1bd0, 0x1bd0, 0x2780, 0x2788, 0x1bb0, 0x1bb0,
+ 0x19b0, 0x19b0, 0x2790, 0x19c0, 0x19c0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fc0, 0x1f68, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1f88, 0x1bd0, 0x1bd0, 0x1bd0, 0x2798, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x2388, 0x1bd0, 0x1f98, 0x1f88, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x27a0, 0x1af0, 0x1af0, 0x27a8, 0x1af0, 0x27b0, 0x1af0, 0x27b8, 0x1af0, 0x27c0, 0x27c8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1af0, 0x27d0,
+ 0x1af0, 0x27d8, 0x1af0, 0x27e0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1af0, 0x1af0, 0x1af0, 0x27e8, 0x27f0, 0x27f8, 0x27f0, 0x27f0,
+ 0x2800, 0x2808, 0x1af0, 0x2810, 0x2818, 0x2820, 0x1af0, 0x2828, 0x1af0, 0x2830, 0x1bb0, 0x1bb0, 0x2838, 0x1af0, 0x2840, 0x2848,
+ 0x1af0, 0x1af0, 0x1af0, 0x2850, 0x1af0, 0x2858, 0x1af0, 0x2860, 0x1af0, 0x2868, 0x2870, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x2878, 0x1bb0, 0x1bb0, 0x1bb0, 0x2880, 0x2880, 0x2880, 0x2888, 0x2890, 0x2890, 0x2890, 0x2898,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x28a0, 0x28a8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x28b0, 0x1bd0, 0x1bd0, 0x28b8, 0x28c0, 0x28c8, 0x28d0, 0x28d8, 0x2048, 0x1bd0, 0x1bd0, 0x28e0, 0x28e8, 0x1bd0, 0x28f0, 0x1f68,
+ 0x28f8, 0x1bd0, 0x2900, 0x2908, 0x2910, 0x1bd0, 0x1bd0, 0x2918, 0x2048, 0x1bd0, 0x1bd0, 0x2920, 0x2928, 0x2930, 0x2938, 0x2940,
+ 0x1bd0, 0x1c78, 0x2948, 0x2950, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x2958, 0x2960, 0x2968, 0x1bd0, 0x1bd0, 0x2970, 0x2978, 0x1f68,
+ 0x2980, 0x1c08, 0x1c10, 0x1c80, 0x2988, 0x2990, 0x2998, 0x29a0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1bd0, 0x1bd0, 0x29a8, 0x29b0, 0x1f68, 0x1bb0, 0x1bb0,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1bd0, 0x29b8, 0x29c0, 0x29c8, 0x29d0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x29d8, 0x29e0, 0x1f68, 0x1bb0, 0x1bb0, 0x1bd0, 0x1bd0, 0x29e8, 0x29f0, 0x1f68, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x29f8, 0x2a00, 0x2a08, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x19b0, 0x19b0, 0x19c0, 0x19c0, 0x1e08, 0x2a10,
+ 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1bd0, 0x1bd0, 0x28f0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fd8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x21e0, 0x21e0, 0x21e0, 0x21e0, 0x21e0, 0x21e0, 0x2a18, 0x2a20, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2600, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1fa0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2388, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x28f0, 0x1bd0, 0x1fa0, 0x2570, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bd0, 0x1fc0, 0x2a28,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x2a30, 0x2a38, 0x2a40, 0x2a48, 0x2a50, 0x1bd0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1fc8, 0x2a58, 0x2a60, 0x2a68, 0x28d8, 0x2a70, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x2a78, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2420, 0x1e20, 0x28f0, 0x2a80, 0x2a88, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2240, 0x2a90,
+ 0x2240, 0x2240, 0x2a98, 0x2240, 0x2240, 0x2240, 0x2aa0, 0x2aa8, 0x2ab0, 0x2240, 0x2ab8, 0x2240, 0x2240, 0x2240, 0x2ac0, 0x1bb0,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2ac8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2278, 0x2718, 0x2ad0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x19b0, 0x2ad8, 0x19c0, 0x2ae0, 0x2ae8, 0x2af0, 0x20e8, 0x19b0, 0x2af8, 0x2b00, 0x2b08, 0x2b10, 0x2b18, 0x19b0, 0x2ad8, 0x19c0,
+ 0x2b20, 0x2b28, 0x19c0, 0x2b30, 0x2b38, 0x2b40, 0x2b48, 0x19b0, 0x2b50, 0x19c0, 0x19b0, 0x2ad8, 0x19c0, 0x2ae0, 0x2ae8, 0x19c0,
+ 0x20e8, 0x19b0, 0x2af8, 0x2b48, 0x19b0, 0x2b50, 0x19c0, 0x19b0, 0x2ad8, 0x19c0, 0x2b58, 0x19b0, 0x2b60, 0x2b68, 0x2b70, 0x2b78,
+ 0x19c0, 0x2b80, 0x19b0, 0x2b88, 0x2b90, 0x2b98, 0x2ba0, 0x19c0, 0x2ba8, 0x19b0, 0x2bb0, 0x19c0, 0x2bb8, 0x2bc0, 0x2bc0, 0x2bc0,
+ 0x1a68, 0x1a68, 0x1a68, 0x2bc8, 0x1a68, 0x1a68, 0x2bd0, 0x2bd8, 0x2be0, 0x2be8, 0x1ad8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x1af0, 0x2bf0, 0x2bf8, 0x1bb0, 0x1bb0,
+ 0x2c00, 0x1b18, 0x2c08, 0x2c10, 0x2c18, 0x2c20, 0x2c28, 0x2c30, 0x2c38, 0x2c40, 0x2c48, 0x2c40, 0x1bb0, 0x1bb0, 0x1bb0, 0x2c50,
+ 0x1fe8, 0x1fe8, 0x23d8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x23c8, 0x2c58, 0x2c60, 0x2c60, 0x2c60, 0x1fe8, 0x23d0,
+ 0x2c68, 0x2240, 0x2460, 0x2240, 0x2240, 0x2240, 0x2c70, 0x2240, 0x2240, 0x2c78, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x2c80, 0x2240,
+ 0x2c88, 0x2240, 0x2240, 0x2c78, 0x2ac0, 0x2c90, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2c98,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x23c0, 0x1fe8, 0x1fe8, 0x2ca0, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2740, 0x2ca8, 0x23c8,
+ 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x23c8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2cb0, 0x1bb0, 0x1bb0,
+ 0x23d8, 0x1fe8, 0x1fe8, 0x1fe8, 0x2cb8, 0x1ee8, 0x1fe8, 0x1fe8, 0x2cb8, 0x1fe8, 0x2cc0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bb0, 0x2cc8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x2cb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x2740, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2388, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1fc8, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1fc0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0,
+ 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x1bd0, 0x2a78, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1bd0, 0x1fc0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x2cd0, 0x1bb0, 0x2cd8, 0x2cd8, 0x2cd8, 0x2cd8, 0x2cd8, 0x2cd8, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0, 0x1bb0,
+ 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1a68, 0x1bb0,
+ 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2618, 0x2ce0,
+ 0x0101, 0x0101, 0x0101, 0x0101, 0x0201, 0x0203, 0x0304, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0303, 0x0203,
+ 0x0605, 0x0706, 0x0708, 0x0606, 0x0a09, 0x0b06, 0x0d0c, 0x0c0c, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x060c, 0x0f0f, 0x060f,
+ 0x1006, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x0910, 0x0a06, 0x1211,
+ 0x1311, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0913, 0x0a0f, 0x010f,
+ 0x0101, 0x0101, 0x0301, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101, 0x0101,
+ 0x0614, 0x0808, 0x0808, 0x0615, 0x1511, 0x1716, 0x180f, 0x1115, 0x1a19, 0x1b1b, 0x1311, 0x0606, 0x1b11, 0x1c16, 0x1d1d, 0x061d,
+ 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x0f10, 0x1010, 0x1010, 0x1010, 0x1310,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1013, 0x1013, 0x1013, 0x1013,
+ 0x1013, 0x1013, 0x1013, 0x1013, 0x1313, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1010, 0x1013, 0x1013, 0x1313,
+ 0x1013, 0x1310, 0x1310, 0x1010, 0x1013, 0x1010, 0x1313, 0x1010, 0x1010, 0x1013, 0x1310, 0x1010, 0x1310, 0x1313, 0x1010, 0x1013,
+ 0x1310, 0x1310, 0x1310, 0x1010, 0x1013, 0x1313, 0x1310, 0x1010, 0x1013, 0x1010, 0x1013, 0x1013, 0x1310, 0x1613, 0x1310, 0x1313,
+ 0x1616, 0x1616, 0x1e10, 0x1013, 0x131e, 0x1e10, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1313, 0x1310,
+ 0x1013, 0x131e, 0x1310, 0x1010, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1313, 0x1313, 0x1313, 0x1010, 0x1013, 0x1310,
+ 0x1013, 0x1013, 0x1010, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1313, 0x1313, 0x1316, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x201f, 0x1f20, 0x1f1f, 0x1f1f, 0x1f1f, 0x1111, 0x1111, 0x2020, 0x2020, 0x2020, 0x2020, 0x2020,
+ 0x1f1f, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1f1f, 0x1f1f, 0x111f, 0x1111, 0x1111, 0x1111, 0x1120, 0x111f,
+ 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x1111, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121,
+ 0x1310, 0x1310, 0x1120, 0x1310, 0x0000, 0x131f, 0x1313, 0x1006, 0x0000, 0x0000, 0x1111, 0x0610, 0x1010, 0x0010, 0x0010, 0x1010,
+ 0x1013, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1000, 0x1010, 0x1010, 0x1010, 0x1010, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1013, 0x1313, 0x1010, 0x1310, 0x1313, 0x1310, 0x1310, 0x1310, 0x1310,
+ 0x1313, 0x1313, 0x1310, 0x100f, 0x1013, 0x1310, 0x1013, 0x1010, 0x1310, 0x2122, 0x2121, 0x2121, 0x2323, 0x1310, 0x1310, 0x1310,
+ 0x1010, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1013, 0x1313, 0x1000, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
+ 0x1010, 0x1010, 0x1010, 0x0010, 0x1f00, 0x2424, 0x2424, 0x2424, 0x1300, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x2400, 0x0025, 0x1500, 0x0815, 0x2100, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2126, 0x2127, 0x2721, 0x2121, 0x2127, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x0028, 0x0000, 0x0000,
+ 0x2828, 0x2728, 0x0027, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2929, 0x2929, 0x2929, 0x0f0f, 0x072a, 0x2b07, 0x2c0c, 0x1515,
+ 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2c21, 0x002d, 0x2c2c, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2e2f, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x212e, 0x2121, 0x2121, 0x3030, 0x3030, 0x3030, 0x3030, 0x3030, 0x3107, 0x2c31, 0x2e2e,
+ 0x2e21, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2c, 0x2121, 0x2121, 0x2121, 0x2921, 0x2115,
+ 0x2121, 0x2121, 0x2f21, 0x212f, 0x1521, 0x2121, 0x2121, 0x2e2e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x2e2e, 0x322e, 0x2e32,
+ 0x2c2c, 0x2c2c, 0x2c2c, 0x2c2c, 0x2c2c, 0x2c2c, 0x2c2c, 0x2d00, 0x212e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x0021, 0x2e00, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121,
+ 0x2e21, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3333, 0x3333, 0x3333, 0x3333, 0x3333, 0x2828, 0x2828, 0x2828,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2128, 0x2121, 0x2121, 0x2121, 0x2121, 0x3434, 0x0615, 0x0606, 0x0034, 0x0000, 0x0000,
+ 0x2828, 0x2828, 0x2828, 0x2121, 0x2121, 0x2134, 0x2121, 0x2121, 0x2121, 0x2121, 0x2134, 0x2121, 0x2134, 0x2121, 0x2121, 0x0000,
+ 0x2727, 0x2727, 0x2727, 0x2727, 0x2727, 0x2727, 0x2727, 0x0027, 0x2828, 0x2828, 0x2828, 0x2828, 0x2128, 0x2121, 0x0000, 0x0027,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2e2e, 0x2e2e, 0x002e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x2100, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x3521, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3521, 0x1621, 0x3535,
+ 0x2135, 0x2121, 0x2121, 0x2121, 0x3521, 0x3535, 0x2135, 0x3535, 0x2116, 0x2121, 0x2121, 0x2121, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x2121, 0x2424, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x1f24, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x2116, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x0016, 0x1600, 0x0016, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x0016, 0x0016, 0x0000, 0x1616, 0x1616, 0x0000, 0x1621, 0x3535,
+ 0x2135, 0x2121, 0x0021, 0x3500, 0x0035, 0x3500, 0x2135, 0x0016, 0x0000, 0x0000, 0x0000, 0x3500, 0x0000, 0x0000, 0x1616, 0x1600,
+ 0x1616, 0x2121, 0x0000, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x1616, 0x0808, 0x3737, 0x3737, 0x3737, 0x0822, 0x0000, 0x0000,
+ 0x2100, 0x3521, 0x1600, 0x1616, 0x1616, 0x0016, 0x0000, 0x1600, 0x0016, 0x1616, 0x1600, 0x0016, 0x1616, 0x0000, 0x0021, 0x3535,
+ 0x2135, 0x0021, 0x0000, 0x2100, 0x0021, 0x2100, 0x2121, 0x0000, 0x2100, 0x0000, 0x0000, 0x0000, 0x1600, 0x1616, 0x0016, 0x0016,
+ 0x0000, 0x0000, 0x0000, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x2121, 0x1616, 0x2116, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2100, 0x3521, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x0016, 0x1616, 0x1600, 0x1616, 0x1616, 0x0000, 0x1621, 0x3535, 0x2135, 0x2121, 0x2121, 0x2100, 0x3521, 0x3500, 0x2135, 0x0000,
+ 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0824, 0x0000, 0x0000, 0x0000, 0x1600, 0x0000, 0x0000, 0x0000,
+ 0x2100, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x0016, 0x1600, 0x0016, 0x1616, 0x1600, 0x1616, 0x1616, 0x0000, 0x1621, 0x2135,
+ 0x2135, 0x2121, 0x0021, 0x3500, 0x0035, 0x3500, 0x2135, 0x0000, 0x0000, 0x0000, 0x0000, 0x3521, 0x0000, 0x0000, 0x1616, 0x1600,
+ 0x1622, 0x3737, 0x3737, 0x3737, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1621, 0x1600, 0x1616, 0x1616, 0x0016, 0x0000, 0x1616,
+ 0x0016, 0x1616, 0x1616, 0x0000, 0x1600, 0x0016, 0x0016, 0x1616, 0x0000, 0x1600, 0x0016, 0x0000, 0x1616, 0x0016, 0x0000, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x3535, 0x3521, 0x0035, 0x0000, 0x3535, 0x0035, 0x3535, 0x2135, 0x0000,
+ 0x0016, 0x0000, 0x0000, 0x3500, 0x0000, 0x0000, 0x0000, 0x0000, 0x3737, 0x1537, 0x1515, 0x1515, 0x0815, 0x0015, 0x0000, 0x0000,
+ 0x3521, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x1600, 0x2121, 0x3521, 0x3535, 0x0035, 0x2121, 0x0021, 0x2121, 0x2121, 0x0000,
+ 0x0000, 0x0000, 0x2100, 0x0021, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1d1d, 0x1d1d, 0x1d1d, 0x221d,
+ 0x2100, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x0000, 0x1621, 0x3835,
+ 0x3535, 0x3535, 0x0035, 0x3538, 0x0035, 0x3535, 0x2121, 0x0000, 0x0000, 0x0000, 0x3500, 0x0035, 0x0000, 0x0000, 0x0000, 0x0016,
+ 0x1600, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1600, 0x3535,
+ 0x2135, 0x2121, 0x0021, 0x3535, 0x0035, 0x3535, 0x2135, 0x0016, 0x0000, 0x0000, 0x0000, 0x3500, 0x0000, 0x0000, 0x0000, 0x1600,
+ 0x3737, 0x3737, 0x3737, 0x0000, 0x2200, 0x1616, 0x1616, 0x1616, 0x0000, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x0021, 0x0000, 0x3500, 0x3535, 0x2121, 0x0021, 0x0021, 0x3535, 0x3535, 0x3535, 0x3535,
+ 0x0000, 0x3535, 0x0024, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x2116, 0x1616, 0x2121, 0x2121, 0x2121, 0x0021, 0x0000, 0x0800, 0x1616, 0x1616, 0x1616, 0x211f, 0x2121, 0x2121, 0x2121, 0x2421,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x2424, 0x0000, 0x0000, 0x1600, 0x0016, 0x0016, 0x1600, 0x0016, 0x0016, 0x1600, 0x0000,
+ 0x0000, 0x0000, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1600, 0x1600, 0x0000, 0x1616, 0x1600, 0x1616,
+ 0x2116, 0x1616, 0x2121, 0x2121, 0x2121, 0x2100, 0x1621, 0x0000, 0x1616, 0x1616, 0x0016, 0x001f, 0x2121, 0x2121, 0x2121, 0x0000,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x1616, 0x1616, 0x2216, 0x2222, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424,
+ 0x2424, 0x2224, 0x2224, 0x2222, 0x2121, 0x2222, 0x2222, 0x2222, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x3737, 0x3737, 0x3737,
+ 0x3737, 0x3737, 0x2122, 0x2122, 0x2122, 0x0a09, 0x0a09, 0x3535, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x2100, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x3521,
+ 0x2121, 0x2121, 0x2421, 0x2121, 0x1616, 0x1616, 0x2116, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2100, 0x2121, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x0021, 0x2222, 0x2222, 0x2222, 0x2222, 0x2221, 0x2222, 0x2222, 0x0022, 0x2222,
+ 0x2424, 0x2424, 0x2224, 0x2222, 0x2422, 0x0024, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3516, 0x2135, 0x2121,
+ 0x3521, 0x2121, 0x2121, 0x2121, 0x2135, 0x3521, 0x2135, 0x1621, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x2424, 0x2424, 0x2424,
+ 0x1616, 0x1616, 0x1616, 0x3535, 0x2121, 0x1616, 0x1616, 0x2121, 0x1621, 0x3535, 0x1635, 0x3516, 0x3535, 0x3535, 0x3535, 0x1616,
+ 0x2116, 0x2121, 0x1621, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3521, 0x2135, 0x3521, 0x3535, 0x3535, 0x2135, 0x3516,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x3535, 0x2135, 0x2222, 0x1010, 0x1010, 0x1010, 0x1000, 0x0000, 0x0000, 0x1000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2416, 0x161f, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x0016, 0x0016, 0x1616, 0x1616, 0x0000, 0x0016, 0x1616, 0x1616, 0x0000, 0x1616, 0x1616, 0x1616, 0x0016,
+ 0x0016, 0x1616, 0x1616, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x2100, 0x2121, 0x2424, 0x2424, 0x2424, 0x2424, 0x3724, 0x3737, 0x3737, 0x3737,
+ 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x0037, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x0000, 0x0000,
+ 0x1010, 0x1010, 0x1010, 0x0000, 0x1313, 0x1313, 0x1313, 0x0000, 0x1625, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2416, 0x1624, 0x1605, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0916, 0x000a, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2416, 0x2424, 0x3939,
+ 0x1639, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616,
+ 0x1616, 0x2121, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x2121, 0x2421, 0x0024, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x2121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0016, 0x2121, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x2121, 0x2135, 0x2121, 0x2121, 0x2121, 0x3535, 0x3535, 0x3535, 0x3535, 0x3521, 0x2135, 0x2121, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2424, 0x1f24, 0x2424, 0x0824, 0x2116, 0x0000, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x0000, 0x0000,
+ 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x0000, 0x0000, 0x0000, 0x0606, 0x0606, 0x0606, 0x0625, 0x0606, 0x2106, 0x2121, 0x0018,
+ 0x1616, 0x1f16, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x2116, 0x0016, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x2121, 0x3521, 0x3535, 0x2135, 0x3521, 0x3535, 0x0000, 0x0000,
+ 0x3535, 0x3521, 0x3535, 0x3535, 0x2135, 0x2121, 0x0000, 0x0000, 0x0015, 0x0000, 0x0606, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x0000,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0037, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x1616, 0x1616, 0x1616, 0x2116, 0x3521, 0x2135, 0x0000, 0x2424, 0x1616, 0x1616, 0x3516, 0x3521, 0x2121, 0x2121, 0x2121, 0x0021,
+ 0x3521, 0x3521, 0x2135, 0x2121, 0x2121, 0x2121, 0x3521, 0x3535, 0x3535, 0x2135, 0x2121, 0x2121, 0x2121, 0x2121, 0x0021, 0x2100,
+ 0x2424, 0x2424, 0x2424, 0x1f24, 0x2424, 0x2424, 0x2424, 0x0000, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x0023,
+ 0x2121, 0x2121, 0x1635, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3521, 0x2121, 0x2121, 0x3521, 0x3521, 0x3535,
+ 0x3535, 0x3521, 0x1635, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x2224, 0x2222, 0x2222, 0x2222, 0x2222, 0x2122, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2222, 0x2222, 0x2222, 0x2222, 0x0022, 0x0000, 0x2121, 0x1635, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x3516, 0x2121, 0x2121, 0x3535, 0x2121, 0x2135, 0x2121, 0x1616, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x3521, 0x2121, 0x3535, 0x2135, 0x2135, 0x2121, 0x3535, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424, 0x2424,
+ 0x1616, 0x1616, 0x3535, 0x3535, 0x3535, 0x3535, 0x2121, 0x2121, 0x2121, 0x2121, 0x3535, 0x2121, 0x0000, 0x2400, 0x2424, 0x2424,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1f1f, 0x1f1f, 0x1f1f, 0x2424,
+ 0x2424, 0x2424, 0x2424, 0x2424, 0x0000, 0x0000, 0x0000, 0x0000, 0x2121, 0x2421, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121,
+ 0x3521, 0x2121, 0x2121, 0x2121, 0x1621, 0x1616, 0x2116, 0x1616, 0x1616, 0x3535, 0x1621, 0x0016, 0x2121, 0x0000, 0x0000, 0x0000,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f,
+ 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x131f, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x131f, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1f13, 0x1f1f, 0x1f1f, 0x2121, 0x2121, 0x2121, 0x0000, 0x0000, 0x0000, 0x2121, 0x2121,
+ 0x1310, 0x1310, 0x1310, 0x1313, 0x1313, 0x1313, 0x1313, 0x1310, 0x1313, 0x1313, 0x1313, 0x1313, 0x1010, 0x1010, 0x1010, 0x1010,
+ 0x1313, 0x1313, 0x1313, 0x0000, 0x1010, 0x1010, 0x1010, 0x0000, 0x1313, 0x1313, 0x1313, 0x1313, 0x1000, 0x1000, 0x1000, 0x1000,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0000, 0x1313, 0x1313, 0x1313, 0x1313, 0x1e1e, 0x1e1e, 0x1e1e, 0x1e1e,
+ 0x1313, 0x1313, 0x0013, 0x1313, 0x1010, 0x1010, 0x111e, 0x1113, 0x1111, 0x1313, 0x0013, 0x1313, 0x1010, 0x1010, 0x111e, 0x1111,
+ 0x1313, 0x1313, 0x0000, 0x1313, 0x1010, 0x1010, 0x1100, 0x1111, 0x1313, 0x1313, 0x1313, 0x1313, 0x1010, 0x1010, 0x1110, 0x1111,
+ 0x0000, 0x1313, 0x0013, 0x1313, 0x1010, 0x1010, 0x111e, 0x0011, 0x0505, 0x0505, 0x0505, 0x0505, 0x0505, 0x1805, 0x1818, 0x3b3a,
+ 0x2525, 0x2525, 0x2525, 0x0606, 0x1c17, 0x1709, 0x1c17, 0x1709, 0x0606, 0x0606, 0x0606, 0x0606, 0x3d3c, 0x3f3e, 0x4140, 0x1442,
+ 0x0707, 0x0707, 0x0607, 0x0606, 0x1706, 0x061c, 0x0606, 0x1206, 0x0612, 0x0606, 0x0943, 0x060a, 0x0606, 0x0606, 0x0606, 0x0606,
+ 0x0606, 0x060f, 0x0612, 0x0606, 0x0606, 0x0606, 0x0606, 0x0506, 0x1818, 0x1818, 0x0018, 0x4544, 0x4746, 0x1818, 0x1818, 0x1818,
+ 0x1f1b, 0x0000, 0x1b1b, 0x1b1b, 0x1b1b, 0x0b0b, 0x090f, 0x1f0a, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x0b0b, 0x090f, 0x000a,
+ 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x001f, 0x0000, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808,
+ 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0808, 0x0008, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2321, 0x2323,
+ 0x2123, 0x2323, 0x2123, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1515, 0x1510, 0x1515, 0x1015, 0x1515, 0x1013, 0x1010, 0x1313, 0x1010, 0x1310, 0x1015, 0x1515, 0x100f, 0x1010, 0x1010, 0x1515,
+ 0x1515, 0x1515, 0x1510, 0x1510, 0x1510, 0x1010, 0x1010, 0x1319, 0x1010, 0x1010, 0x1613, 0x1616, 0x1316, 0x1515, 0x1313, 0x1010,
+ 0x0f0f, 0x0f0f, 0x100f, 0x1313, 0x1313, 0x0f15, 0x1515, 0x2213, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d,
+ 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x1039, 0x3913, 0x3939, 0x1d39, 0x1515, 0x0000, 0x0000,
+ 0x0f0f, 0x0f0f, 0x150f, 0x1515, 0x1515, 0x0f0f, 0x1515, 0x1515, 0x150f, 0x0f15, 0x1515, 0x150f, 0x1515, 0x1515, 0x1515, 0x150f,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0f0f, 0x1515, 0x150f, 0x150f, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x1515, 0x1515, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
+ 0x0f0f, 0x1a0b, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x1515, 0x1515, 0x1515, 0x1515, 0x0a09, 0x0a09, 0x1515, 0x1515,
+ 0x0f0f, 0x1515, 0x1515, 0x1515, 0x0915, 0x150a, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1522, 0x150f, 0x1515,
+ 0x1515, 0x1515, 0x2215, 0x1515, 0x1515, 0x0f15, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0f0f, 0x0f0f, 0x0f0f, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0015, 0x0000, 0x0000, 0x1515, 0x1515, 0x1515, 0x0015, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x2222, 0x2222,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1d1d, 0x1d1d, 0x1d1d, 0x1515, 0x1515, 0x1515, 0x0f15, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x0f15, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0f15, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1522, 0x1515,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d,
+ 0x1d1d, 0x1d1d, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0f0f, 0x0f0f, 0x090f, 0x0f0a, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
+ 0x0f0f, 0x0f0f, 0x0f0f, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0f0f, 0x090f, 0x090a, 0x090a, 0x090a, 0x090a, 0x090a, 0x090a,
+ 0x090a, 0x090a, 0x090a, 0x090a, 0x0f0a, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0a09, 0x0a09, 0x0f0f, 0x0f0f,
+ 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0a09, 0x0f0f, 0x0f0f, 0x0f0f, 0x150f, 0x0f15, 0x0f0f, 0x0f0f, 0x150f, 0x1515,
+ 0x1515, 0x1515, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x1500, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0015, 0x1515, 0x1515, 0x1515,
+ 0x1515, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1515, 0x1515,
+ 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x0010, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0013,
+ 0x1310, 0x1010, 0x1310, 0x1013, 0x1013, 0x1013, 0x1013, 0x1010, 0x1310, 0x1310, 0x1013, 0x1313, 0x1313, 0x1313, 0x1f1f, 0x1010,
+ 0x1310, 0x1310, 0x1513, 0x1515, 0x1515, 0x1015, 0x1013, 0x2113, 0x2121, 0x1310, 0x0000, 0x0000, 0x0600, 0x0606, 0x1d06, 0x0606,
+ 0x1313, 0x1313, 0x1313, 0x1300, 0x0000, 0x0000, 0x1300, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x0000, 0x1f00,
+ 0x0024, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2100, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x0016, 0x0606, 0x1c17, 0x1c17, 0x0606, 0x1706, 0x061c, 0x1c17, 0x0606,
+ 0x0606, 0x0606, 0x0606, 0x2506, 0x0606, 0x0625, 0x1c17, 0x0606, 0x1c17, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0606, 0x0606, 0x2006,
+ 0x0606, 0x0606, 0x0606, 0x0606, 0x0606, 0x2525, 0x0606, 0x0606, 0x0625, 0x0009, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1500, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1515, 0x1515, 0x1515, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x0000,
+ 0x0605, 0x0606, 0x1f15, 0x3916, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x1515, 0x0a09, 0x0a09, 0x0a09, 0x0a09, 0x0925, 0x0a0a,
+ 0x3915, 0x3939, 0x3939, 0x3939, 0x3939, 0x2121, 0x2121, 0x3535, 0x1f25, 0x1f1f, 0x1f1f, 0x1515, 0x3939, 0x1f39, 0x0616, 0x1515,
+ 0x1616, 0x1616, 0x1616, 0x0016, 0x2100, 0x1121, 0x1f11, 0x161f, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0616, 0x1f1f, 0x161f,
+ 0x0000, 0x0000, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2222, 0x3737, 0x3737, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1522, 0x0015,
+ 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x3737, 0x3737, 0x3737, 0x3737,
+ 0x1d15, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1515, 0x2215,
+ 0x1d22, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1515, 0x1515,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x0022, 0x2222, 0x2222, 0x2222, 0x1522, 0x1515, 0x2215, 0x2222, 0x2222,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1515, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1522,
+ 0x1616, 0x1616, 0x1f16, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x061f, 0x0606,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x1616, 0x0000, 0x0000, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x2116,
+ 0x2323, 0x0623, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2006, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1f1f, 0x2121,
+ 0x1616, 0x1616, 0x1616, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x2121, 0x2424, 0x2424, 0x2424, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1111, 0x1111, 0x1111, 0x2011, 0x2020, 0x2020, 0x2020, 0x2020, 0x1111, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310,
+ 0x1313, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x131f, 0x1313, 0x1313, 0x1313, 0x1013, 0x1013, 0x1013, 0x1310,
+ 0x1310, 0x1310, 0x1310, 0x1310, 0x4820, 0x1048, 0x1013, 0x1613, 0x1310, 0x1310, 0x1313, 0x1310, 0x1310, 0x1310, 0x1310, 0x1310,
+ 0x1310, 0x1310, 0x1310, 0x1310, 0x1310, 0x1010, 0x1010, 0x0000, 0x1010, 0x1010, 0x1310, 0x1310, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1600, 0x1f1f, 0x1613, 0x1616, 0x1616, 0x1616, 0x1621, 0x1616, 0x1621, 0x1616, 0x2116, 0x1616, 0x1616,
+ 0x1616, 0x3516, 0x2135, 0x3521, 0x1515, 0x1515, 0x0000, 0x0000, 0x3737, 0x3737, 0x3737, 0x2222, 0x1908, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x0606, 0x0606, 0x0000, 0x0000, 0x0000, 0x0000, 0x3535, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x2424,
+ 0x2121, 0x1616, 0x1616, 0x1616, 0x2424, 0x1624, 0x1624, 0x0000, 0x1616, 0x1616, 0x1616, 0x2121, 0x2121, 0x2121, 0x2121, 0x2424,
+ 0x1616, 0x1616, 0x1616, 0x2116, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x3535, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2400,
+ 0x1616, 0x2116, 0x3535, 0x2121, 0x2121, 0x3535, 0x3521, 0x3535, 0x2435, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424, 0x1f00,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x0000, 0x2424, 0x1616, 0x1616, 0x2116, 0x161f, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x1616, 0x1616, 0x0016, 0x1616, 0x1616, 0x1616, 0x1616, 0x2116, 0x2121, 0x2121, 0x3521,
+ 0x2135, 0x3521, 0x2135, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x2116, 0x1616, 0x1616, 0x1616, 0x1616, 0x3521, 0x0000,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x2424, 0x2424, 0x161f, 0x1616, 0x1616, 0x2216, 0x2222, 0x3516, 0x3521, 0x1616,
+ 0x1621, 0x2121, 0x1621, 0x2116, 0x1621, 0x1616, 0x1616, 0x2121, 0x2116, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1600, 0x1f16, 0x2424, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3516, 0x2121, 0x3535,
+ 0x2424, 0x1f16, 0x351f, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x1600, 0x1616, 0x1616, 0x0016, 0x1600, 0x1616, 0x1616, 0x0016,
+ 0x1600, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x4813, 0x1f1f, 0x1f1f,
+ 0x1313, 0x1313, 0x1313, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x3516, 0x2135, 0x3535, 0x3521, 0x2435, 0x2135, 0x0000,
+ 0x1616, 0x1616, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x1600, 0x1616, 0x1616,
+ 0x4949, 0x4949, 0x4949, 0x4949, 0x4949, 0x4949, 0x4949, 0x4949, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a,
+ 0x1313, 0x1313, 0x1313, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1300, 0x1313, 0x1313, 0x0000, 0x0000, 0x2800, 0x2821,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x0b28, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x0028, 0x2828, 0x2828, 0x0028, 0x0028,
+ 0x2828, 0x2800, 0x0028, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2e2e, 0x4b4b, 0x4b4b, 0x4b4b, 0x4b4b, 0x4b4b, 0x4b4b, 0x4b4b,
+ 0x4b4b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2e00, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x090a, 0x0000, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x0000, 0x0000, 0x0000, 0x0000, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x152b, 0x0000,
+ 0x0606, 0x0606, 0x0606, 0x0906, 0x060a, 0x0000, 0x0000, 0x0000, 0x2506, 0x1225, 0x0912, 0x090a, 0x090a, 0x090a, 0x090a, 0x090a,
+ 0x090a, 0x090a, 0x060a, 0x0906, 0x060a, 0x0606, 0x1206, 0x1212, 0x060c, 0x000c, 0x0c06, 0x0606, 0x0925, 0x090a, 0x090a, 0x070a,
+ 0x0606, 0x0d0b, 0x0f0f, 0x000f, 0x0806, 0x0607, 0x0000, 0x0000, 0x2e2e, 0x2e2e, 0x002e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x002e, 0x1800, 0x0600, 0x0706, 0x0708, 0x0606, 0x0a09, 0x0b06, 0x0d0c, 0x0c0c,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0913, 0x0a0f, 0x090f, 0x060a, 0x0a09, 0x0606, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x161f, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1f1f,
+ 0x0000, 0x1616, 0x1616, 0x1616, 0x0000, 0x1616, 0x1616, 0x1616, 0x0000, 0x1616, 0x1616, 0x1616, 0x0000, 0x1616, 0x0016, 0x0000,
+ 0x0808, 0x110f, 0x0815, 0x0008, 0x0f15, 0x0f0f, 0x150f, 0x0015, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c00, 0x4c4c, 0x1515, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x1616, 0x1600,
+ 0x0624, 0x0024, 0x0000, 0x3700, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737,
+ 0x3737, 0x3737, 0x0000, 0x2200, 0x2222, 0x2222, 0x2222, 0x2222, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d, 0x4d4d,
+ 0x4d4d, 0x4d4d, 0x1d4d, 0x1d1d, 0x151d, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1d1d, 0x0015, 0x0000,
+ 0x0015, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2122, 0x0000,
+ 0x1b21, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x0000, 0x0000,
+ 0x3737, 0x3737, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3916, 0x1616, 0x1616, 0x1616, 0x1616, 0x0039, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x2121, 0x2121, 0x0021, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2400,
+ 0x1616, 0x1616, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x3924, 0x3939, 0x3939, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1010, 0x1010, 0x1010, 0x1010, 0x1313, 0x1313, 0x1313, 0x1313, 0x1616, 0x1616, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2400,
+ 0x2828, 0x2828, 0x2828, 0x0000, 0x0028, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2800, 0x0028, 0x0000, 0x0028, 0x2800,
+ 0x2828, 0x2828, 0x2828, 0x2700, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x2828, 0x2828, 0x2828, 0x4f28, 0x4e4f, 0x4e4e, 0x4e4e, 0x4e4e,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x0028, 0x0000, 0x0000, 0x0000, 0x4e00, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e,
+ 0x2828, 0x0028, 0x2828, 0x0000, 0x0000, 0x4e00, 0x4e4e, 0x4e4e, 0x2828, 0x2828, 0x2828, 0x4e4e, 0x4e4e, 0x4e4e, 0x0000, 0x0600,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x0000, 0x0000, 0x2700, 0x2828, 0x2828, 0x2828, 0x2828, 0x0000, 0x0000, 0x4e4e, 0x2828,
+ 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x0000, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e,
+ 0x2128, 0x2121, 0x2100, 0x0021, 0x0000, 0x0000, 0x2121, 0x2121, 0x2828, 0x2828, 0x2800, 0x2828, 0x2800, 0x2828, 0x2828, 0x2828,
+ 0x2828, 0x2828, 0x0000, 0x0000, 0x2121, 0x0021, 0x0000, 0x2100, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2727, 0x2727, 0x2727, 0x2727, 0x0027, 0x0000, 0x0000, 0x0000, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x4e28, 0x274e,
+ 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x2828, 0x4e28, 0x4e4e, 0x2828, 0x2828, 0x2828, 0x2828, 0x284f, 0x2828, 0x2828, 0x2828,
+ 0x2828, 0x2828, 0x2128, 0x0021, 0x0000, 0x4e00, 0x4e4e, 0x4e4e, 0x2727, 0x2727, 0x2727, 0x0027, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2828, 0x2828, 0x2828, 0x0000, 0x0600, 0x0606, 0x0606, 0x0606, 0x2828, 0x2828, 0x2828, 0x0000, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e,
+ 0x2828, 0x0028, 0x0000, 0x0000, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x2828, 0x0000, 0x0000, 0x0000, 0x2700, 0x2727, 0x0027, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x4e00, 0x4e4e, 0x4e4e, 0x4e4e, 0x2828, 0x2828, 0x2828, 0x2828, 0x0028, 0x0000, 0x0000, 0x0000,
+ 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x5050, 0x0050, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x5151, 0x5151, 0x5151, 0x5151, 0x5151, 0x5151, 0x5151, 0x5151, 0x5151, 0x0051, 0x0000, 0x0000, 0x0000, 0x4e4e, 0x4e4e, 0x4e4e,
+ 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x5252, 0x0052,
+ 0x2135, 0x1635, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2121, 0x2121, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2121, 0x2421, 0x2424, 0x2424, 0x2424, 0x0000, 0x0000, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d, 0x1d1d,
+ 0x1d1d, 0x1d1d, 0x1d1d, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2100,
+ 0x3535, 0x2135, 0x2121, 0x3521, 0x2135, 0x2421, 0x3a24, 0x2424, 0x2424, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x0016, 0x0000, 0x0000, 0x0000, 0x2121, 0x1621, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x2116, 0x2121, 0x2121, 0x2135, 0x2121, 0x2121, 0x2121, 0x0021, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636,
+ 0x2424, 0x2424, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x2116, 0x2424, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x3516, 0x3535, 0x2121, 0x2121, 0x2121, 0x2121, 0x3521, 0x1635, 0x1616, 0x2416, 0x2424, 0x2424, 0x2121, 0x2421, 0x0000,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x2416, 0x2416, 0x2424, 0x3700, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737, 0x3737,
+ 0x3737, 0x3737, 0x0037, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3535, 0x2135,
+ 0x2121, 0x3535, 0x3521, 0x2121, 0x2424, 0x2424, 0x2424, 0x0000, 0x1616, 0x1616, 0x1616, 0x0016, 0x0016, 0x1616, 0x1616, 0x1600,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x2416, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2116, 0x3535, 0x2135, 0x2121, 0x2121, 0x2121, 0x0021, 0x0000, 0x0000,
+ 0x2121, 0x3535, 0x1600, 0x1616, 0x1616, 0x1616, 0x0016, 0x1600, 0x3521, 0x3535, 0x0035, 0x3500, 0x0035, 0x3500, 0x3535, 0x0000,
+ 0x0016, 0x0000, 0x0000, 0x3500, 0x0000, 0x0000, 0x1600, 0x1616, 0x1616, 0x3535, 0x0000, 0x2121, 0x2121, 0x2121, 0x0021, 0x0000,
+ 0x2121, 0x2121, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3535, 0x2135, 0x2121, 0x2121, 0x3521, 0x3521, 0x3535, 0x2135,
+ 0x3521, 0x2121, 0x1616, 0x1624, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x3516,
+ 0x3535, 0x2121, 0x2121, 0x0000, 0x3535, 0x3535, 0x2121, 0x2135, 0x2421, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424, 0x2424,
+ 0x2424, 0x2424, 0x2424, 0x2424, 0x1616, 0x1616, 0x2121, 0x0000, 0x3535, 0x2135, 0x2121, 0x2121, 0x2121, 0x3521, 0x2135, 0x2135,
+ 0x2421, 0x2424, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x2116, 0x2135, 0x3535,
+ 0x2121, 0x2121, 0x2121, 0x2135, 0x0000, 0x0000, 0x0000, 0x0000, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x2100, 0x2121,
+ 0x3535, 0x2121, 0x2121, 0x2135, 0x2121, 0x2121, 0x0000, 0x0000, 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x3737, 0x2424, 0x2224,
+ 0x3737, 0x0037, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1600, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x3939, 0x0039,
+ 0x2424, 0x2424, 0x0024, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2121, 0x2121, 0x2421, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2121, 0x2121, 0x2121, 0x2421, 0x2424, 0x2424, 0x2222, 0x2222, 0x1f1f, 0x1f1f, 0x2224, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3636, 0x3636, 0x3636, 0x3636, 0x3636, 0x3700, 0x3737, 0x3737, 0x3737, 0x1600, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x1616,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x0000, 0x1600, 0x1616, 0x3516, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535,
+ 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x3535, 0x0035,
+ 0x2121, 0x1f21, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1f1f, 0x1616, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1616, 0x1616, 0x1616, 0x1616, 0x1616, 0x0000, 0x2122, 0x2421, 0x1818, 0x1818, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2222, 0x2222, 0x2222, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2222, 0x2222, 0x2222, 0x0022, 0x2200, 0x2222, 0x2222, 0x2222,
+ 0x2222, 0x2222, 0x3522, 0x2135, 0x2121, 0x2222, 0x3522, 0x3535, 0x3535, 0x1835, 0x1818, 0x1818, 0x1818, 0x2118, 0x2121, 0x2121,
+ 0x2121, 0x2221, 0x2122, 0x2121, 0x2121, 0x2121, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2121, 0x2121, 0x2222,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x0022, 0x0000, 0x0000, 0x0000, 0x1515, 0x2121, 0x1521, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3737, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1313,
+ 0x1313, 0x1313, 0x0013, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1010, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0010, 0x1010, 0x0000, 0x0010, 0x1000, 0x0010, 0x1000, 0x1010, 0x0010, 0x1010,
+ 0x1010, 0x1010, 0x1010, 0x1313, 0x1313, 0x1300, 0x1300, 0x1313, 0x1313, 0x1313, 0x1300, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1010, 0x1000, 0x1010, 0x0010, 0x1000, 0x1010, 0x1010, 0x1010, 0x0010, 0x1010, 0x1010, 0x1010, 0x0010, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1010, 0x1000, 0x1010, 0x0010, 0x1010, 0x1010, 0x0010, 0x0010, 0x0000, 0x1010, 0x1010, 0x1010,
+ 0x0010, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1010, 0x1010,
+ 0x1010, 0x1010, 0x1010, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0000, 0x1010, 0x1010, 0x1010, 0x1010,
+ 0x5310, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313,
+ 0x1313, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x5310, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313, 0x1313, 0x1010, 0x1010, 0x1010, 0x1010, 0x5310, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313,
+ 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313, 0x1313, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
+ 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x5310, 0x1313, 0x1313, 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313, 0x1313,
+ 0x1010, 0x1010, 0x1010, 0x1010, 0x5310, 0x1313, 0x1313, 0x1313, 0x1313, 0x0f13, 0x1313, 0x1313, 0x1313, 0x1310, 0x0000, 0x0e0e,
+ 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x0e0e, 0x2121, 0x2121, 0x2121, 0x2221, 0x2222, 0x2122, 0x2121, 0x2121,
+ 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2121, 0x2221, 0x2222, 0x2222, 0x2222, 0x2122, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222,
+ 0x2222, 0x2222, 0x2221, 0x2422, 0x2424, 0x2424, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2100, 0x2121, 0x2121,
+ 0x2828, 0x2828, 0x0028, 0x4e00, 0x4e4e, 0x4e4e, 0x4e4e, 0x4e4e, 0x2121, 0x2121, 0x2121, 0x0021, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2e2e, 0x2e2e, 0x2e00, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e00, 0x002e, 0x002e, 0x2e00, 0x2e00, 0x2e2e, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x002e, 0x2e2e, 0x2e2e, 0x2e00, 0x2e00, 0x0000, 0x0000, 0x0000, 0x002e, 0x0000, 0x2e00, 0x2e00, 0x2e00, 0x2e00, 0x2e2e,
+ 0x2e00, 0x002e, 0x002e, 0x2e00, 0x2e00, 0x2e00, 0x2e00, 0x2e00, 0x2e00, 0x002e, 0x002e, 0x2e00, 0x2e2e, 0x002e, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x002e, 0x2e2e, 0x2e2e, 0x2e00, 0x2e2e, 0x002e, 0x002e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e00, 0x2e2e, 0x2e2e,
+ 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x2e2e, 0x0000, 0x0000, 0x2e00, 0x2e2e, 0x2e00, 0x2e2e, 0x2e2e, 0x2e00, 0x2e2e, 0x2e2e,
+ 0x0f0f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0015,
+ 0x1500, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1b1b, 0x1d1b, 0x001d, 0x0000,
+ 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x1515, 0x0000, 0x0000, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x0022, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x2222, 0x0022, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x2222, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1115, 0x1111, 0x1111,
+ 0x1515, 0x1515, 0x1500, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0015, 0x0000,
+ 0x1515, 0x1515, 0x0015, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x1515, 0x0000, 0x1515, 0x1515, 0x1515, 0x1515, 0x0015, 0x0000, 0x0000, 0x0000,
+ 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1818, 0x1818, 0x1818, 0x1818, 0x1818, 0x1818, 0x1818, 0x1818,
+ 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x4a4a, 0x0000, 0xeeee, 0xeeee
+ };
+
+ private static byte[] s_pCategoriesValue = new byte[]
+ {
+ 0x1d, 0x00, 0x0e, 0x0e, 0x0e, 0x10, 0x0e, 0x0f, 0x0e, 0x11, 0x0b, 0x11, 0x18, 0x12, 0x18, 0x0a,
+ 0x1a, 0x0a, 0x14, 0x12, 0x15, 0x12, 0x19, 0x09, 0x18, 0x0c, 0x13, 0x09, 0x08, 0x08, 0x19, 0x12,
+ 0x00, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x01, 0x00, 0x0b, 0x0c, 0x1c, 0x12, 0x04, 0x00, 0x16, 0x12,
+ 0x0f, 0x0e, 0x1c, 0x0a, 0x19, 0x0a, 0x0a, 0x08, 0x17, 0x12, 0x0a, 0x12, 0x02, 0x00, 0x03, 0x00,
+ 0x03, 0x12, 0x05, 0x0d, 0x1c, 0x00, 0x07, 0x0d, 0x18, 0x00, 0x13, 0x12, 0x13, 0x03, 0x18, 0x03,
+ 0x04, 0x03, 0x0f, 0x0b, 0x19, 0x04, 0x1a, 0x04, 0x18, 0x04, 0x0f, 0x04, 0x04, 0x04, 0x03, 0x04,
+ 0x08, 0x0b, 0x18, 0x0b, 0x1c, 0x04, 0x08, 0x03, 0x03, 0x03, 0x06, 0x00, 0x08, 0x00, 0x0a, 0x00,
+ 0x05, 0x00, 0x09, 0x00, 0x0f, 0x00, 0x0f, 0x03, 0x0c, 0x11, 0x0d, 0x0f, 0x0f, 0x01, 0x0f, 0x05,
+ 0x0f, 0x07, 0x0f, 0x02, 0x0f, 0x06, 0x19, 0x0c, 0x0f, 0x13, 0x0f, 0x14, 0x0f, 0x15, 0x0f, 0x16,
+ 0x1b, 0x00, 0x10, 0x00, 0x11, 0x00, 0x1b, 0x04, 0x0f, 0x12, 0x09, 0x12, 0x0a, 0x03, 0x1c, 0x03,
+ 0x00, 0x03, 0x01, 0x03, 0x0a, 0x0b, 0x19, 0x00
+ };
+ // 12:4:4 index table of the Unicode numeric data.
+ private static ushort[] s_pNumericLevel1Index = new ushort[]
+ {
+ 0x1100, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1120, 0x1130, 0x1110, 0x1140, 0x1150, 0x1160, 0x1170, 0x1180, 0x1190, 0x11a0,
+ 0x11b0, 0x1110, 0x1110, 0x11c0, 0x1110, 0x1110, 0x11d0, 0x11e0, 0x11f0, 0x1200, 0x1210, 0x1220, 0x1230, 0x1110, 0x1110, 0x1110,
+ 0x1240, 0x1250, 0x1110, 0x1110, 0x1260, 0x1110, 0x1110, 0x1270, 0x1110, 0x1110, 0x1110, 0x1110, 0x1280, 0x1110, 0x1110, 0x1110,
+ 0x1290, 0x12a0, 0x12b0, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x12c0, 0x1110, 0x12d0, 0x12e0, 0x12f0, 0x1300, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1310, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x11f0,
+ 0x1110, 0x1320, 0x1330, 0x1340, 0x1350, 0x1110, 0x1110, 0x1110, 0x1360, 0x1370, 0x1380, 0x1390, 0x13a0, 0x1110, 0x13b0, 0x1110,
+ 0x13c0, 0x13d0, 0x1300, 0x1110, 0x13e0, 0x1110, 0x13f0, 0x1400, 0x1410, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1420, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1430, 0x1440, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1450, 0x1110, 0x1110, 0x1110, 0x1460, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1470, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1480, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1490, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110, 0x1110,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14c0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14c8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14d0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14d8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14e0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14e8, 0x14f0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14f8, 0x1500, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1508, 0x1510,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x1518,
+ 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1520, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1528, 0x1530, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1538, 0x1540, 0x1540, 0x1548, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1550, 0x1558, 0x1560, 0x1568, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1570, 0x1578,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1580, 0x1588, 0x1590, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1598,
+ 0x15a0, 0x14a0, 0x15a8, 0x15b0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x15b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x15c0, 0x14a0, 0x15c8, 0x15d0, 0x14a0, 0x14a0, 0x15c0, 0x14a0, 0x14a0, 0x15d8, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x15e0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x15e8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0,
+ 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a8,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x15f0, 0x15f8, 0x14a0, 0x14a0, 0x14a0, 0x1600, 0x14a0, 0x1608, 0x14a0, 0x1610,
+ 0x1618, 0x1620, 0x1628, 0x1630, 0x1638, 0x1640, 0x1648, 0x1650, 0x1658, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1660, 0x1668,
+ 0x14a0, 0x14a0, 0x1670, 0x14a0, 0x1678, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1680, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1688, 0x14a0, 0x1690, 0x14a0, 0x14a0, 0x1698, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16a0,
+ 0x14a0, 0x16a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16b0, 0x16b8, 0x16c0, 0x16c8, 0x16d0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16d8, 0x14a0, 0x14a0, 0x16e0, 0x14a0, 0x16e8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16f0, 0x14a0, 0x16f0, 0x14a0, 0x14a0, 0x16f8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1700,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1708, 0x1710, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1718, 0x1720, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8,
+ 0x14a0, 0x14a0, 0x14a0, 0x14b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x1660, 0x1728,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x1730, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1738, 0x1740,
+ 0x1748, 0x1750, 0x1758, 0x1760, 0x1768, 0x1770, 0x1778, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1780, 0x1788, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x16b8, 0x1790, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1798, 0x17a0, 0x17a8, 0x17b0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x1618, 0x14a0, 0x14a0, 0x14a0,
+ 0x17b8, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x17c0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0, 0x14a0,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0c0b, 0x0000, 0x0000, 0x0d00, 0x0000, 0x0f0e, 0x0010, 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09,
+ 0x0000, 0x0000, 0x1211, 0x0e13, 0x1410, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0e, 0x1110, 0x1312, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1615, 0x0017, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1918, 0x1b1a, 0x1a19, 0x001b,
+ 0x1615, 0x0e17, 0x100f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x1c0f, 0x1e1d, 0x201f,
+ 0x2221, 0x2423, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0d00, 0x0c0b, 0x2625, 0x2827,
+ 0x2a29, 0x2b15, 0x2d2c, 0x2f2e, 0x3130, 0x1632, 0x0033, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3534,
+ 0x0036, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1918, 0x1b1a, 0x3837, 0x3a39, 0x3c3b, 0x0000, 0x0000, 0x0000,
+ 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x000d, 0x0000, 0x0000, 0x003d, 0x0000, 0x2625, 0x2827, 0x2a29, 0x0000, 0x0000, 0x0000,
+ 0x0d3d, 0x0c0b, 0x2625, 0x2827, 0x2a29, 0x0000, 0x0000, 0x0000, 0x3f3e, 0x4140, 0x4342, 0x4544, 0x4746, 0x1248, 0x4a49, 0x194b,
+ 0x1a19, 0x371b, 0x3938, 0x3b3a, 0x153c, 0x4d4c, 0x162e, 0x174e, 0x4f17, 0x0033, 0x3900, 0x502e, 0x1851, 0x0000, 0x0000, 0x0000,
+ 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x4d4c, 0x5352, 0x1454, 0x3534, 0x2b36, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x4d4c,
+ 0x5352, 0x1454, 0x3534, 0x2b36, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x4d4c, 0x5352, 0x1454, 0x3534, 0x2b36, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c3d, 0x524d, 0x5453, 0x3414, 0x3635, 0x0d2b, 0x0c0b, 0x2625, 0x2827, 0x2a29, 0x3d15,
+ 0x0000, 0x0000, 0x0000, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x0b0d, 0x250c, 0x2726,
+ 0x2928, 0x152a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f00, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x1800, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x1b1a, 0x3837, 0x3a39, 0x3c3b, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2b15, 0x002c, 0x0000, 0x0000, 0x0000, 0x1a19, 0x371b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x1a19, 0x371b, 0x3938, 0x3b3a, 0x153c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2b15, 0x2d2c, 0x2f2e, 0x3130,
+ 0x5500, 0x5756, 0x5958, 0x5b5a, 0x5d5c, 0x5e2c, 0x605f, 0x6261, 0x6300, 0x6564, 0x2d66, 0x6867, 0x6a69, 0x6c6b, 0x6e6d, 0x2e6f,
+ 0x0000, 0x0000, 0x0000, 0x1a19, 0x371b, 0x3938, 0x3b3a, 0x183c, 0x0f0e, 0x1110, 0x1312, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1b00, 0x0000, 0x0000, 0x0000, 0x1500, 0x0000, 0x0000, 0x001a, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0018, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3900, 0x3900, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1500, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x1b1a, 0x3837, 0x3a39, 0x3c3b,
+ 0x2b15, 0x2d2c, 0x2f2e, 0x3130, 0x1632, 0x7170, 0x4e72, 0x7473, 0x7675, 0x7717, 0x7978, 0x7a4f, 0x7c7b, 0x337d, 0x7f7e, 0x5080,
+ 0x8281, 0x8483, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f0e, 0x3819, 0x4e2e, 0x504f, 0x1538, 0x162e, 0x174e, 0x384f,
+ 0x2e15, 0x4e16, 0x3317, 0x1550, 0x1919, 0x1a19, 0x1a1a, 0x381a, 0x1515, 0x1515, 0x2c15, 0x2e2e, 0x2e2e, 0x7116, 0x4e4e, 0x4e4e,
+ 0x174e, 0x384f, 0x0f2e, 0x420f, 0x0010, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e18, 0x0000, 0x0000,
+ 0x1900, 0x1b1a, 0x3837, 0x3a39, 0x3c3b, 0x2b15, 0x2d2c, 0x2f2e, 0x3130, 0x1632, 0x7170, 0x4e72, 0x7473, 0x7675, 0x0000, 0x0000,
+ 0x3819, 0x2e15, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3200, 0x0000, 0x0000, 0x0000, 0x0000, 0x0076, 0x0000, 0x0000,
+ 0x1900, 0x151a, 0x162b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1a19, 0x151b, 0x162b, 0x3317,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x1b1a, 0x3837, 0x2b15, 0x0000, 0x0000, 0x0000, 0x1900, 0x1b1a, 0x3737, 0x1538, 0x162b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x1538, 0x162b, 0x0000, 0x0000, 0x0000, 0x1519, 0x162b, 0x1b1a, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0f85, 0x0000, 0x1a19, 0x371b, 0x3938, 0x3b3a, 0x153c, 0x2c2b, 0x2e2d, 0x302f,
+ 0x0000, 0x7016, 0x7271, 0x734e, 0x7574, 0x1776, 0x7877, 0x4f79, 0x7b7a, 0x7d7c, 0x7e33, 0x807f, 0x8150, 0x8382, 0x5184, 0x8786,
+ 0x8988, 0x8b8a, 0x8d8c, 0x8f8e, 0x9190, 0x9392, 0x9594, 0x9796, 0x0b0d, 0x250c, 0x2b15, 0x1716, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x002e, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x2b15,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x1a19, 0x371b, 0x2b15, 0x1716, 0x0000, 0x0000, 0x0000, 0x0000, 0x1900, 0x1b1a, 0x1537, 0x162b,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3819, 0x2e15, 0x1716, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x2c2b, 0x2e2d, 0x302f,
+ 0x3231, 0x7016, 0x7271, 0x734e, 0x7574, 0x0f76, 0x410e, 0x0042, 0x0000, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x152a, 0x2c2b, 0x2e2d,
+ 0x302f, 0x3231, 0x1716, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x3130, 0x1632, 0x0017, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x2b15, 0x0000, 0x0000, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x2b15, 0x2d2c, 0x2f2e,
+ 0x3130, 0x0032, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1b1a, 0x3837, 0x3a39, 0x3c3b, 0x371b, 0x3938, 0x3b3a, 0x373c,
+ 0x3938, 0x3b3a, 0x193c, 0x1b1a, 0x3837, 0x3a39, 0x3c3b, 0x1a19, 0x371b, 0x1a38, 0x1b1b, 0x3837, 0x3a39, 0x3c3b, 0x1a19, 0x1b1b,
+ 0x3837, 0x9998, 0x1a19, 0x1b1b, 0x3837, 0x1b1b, 0x3737, 0x3737, 0x3a39, 0x3a3a, 0x3b3b, 0x3c3c, 0x3c3c, 0x1b1a, 0x3837, 0x1939,
+ 0x1b1a, 0x3737, 0x3838, 0x1b1a, 0x1a19, 0x4241, 0x4148, 0x1242, 0x470e, 0x0e0e, 0x410f, 0x2d42, 0x372e, 0x3938, 0x3b3a, 0x003c,
+ 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x1500, 0x3316, 0x9b9a, 0x9d9c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x3231, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0201,
+ 0x0403, 0x0605, 0x0807, 0x0a09, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x0201, 0x0403,
+ 0x0605, 0x0807, 0x0a09, 0x0201, 0x0403, 0x0605, 0x0807, 0x0a09, 0x3d3d, 0x0b0d, 0x250c, 0x2726, 0x2928, 0x182a, 0x0018, 0x0000,
+ 0x003c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xeeee, 0xeeee, 0xeeee, 0xeeee
+ };
+ // Every item contains the value for numeric value.
+ private static byte[] s_pNumericValues = new byte[]
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x8f, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x51, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x56, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xc3, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0xc2, 0x3f, 0x1c, 0xc7, 0x71, 0x1c, 0xc7, 0x71, 0xbc, 0x3f,
+ 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xb9, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xe5, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xc9, 0x3f,
+ 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xd9, 0x3f, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xe3, 0x3f,
+ 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xe9, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xc5, 0x3f,
+ 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xb3, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xe8, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0xf8, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x41, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x42, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x43, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x44, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x45, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x46, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x47, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x48, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x72, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x82, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x85, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x8c, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x9f, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xa7, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xaf, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xb7, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xbb, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xbf, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc1, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xd3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xdd, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0xed, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xf1, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf5, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xed, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x08, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, 0x12, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x18, 0x41, 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x1e, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x4f, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x5c, 0x25, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6a, 0x28, 0x41, 0x00, 0x00, 0x00, 0x00, 0x40, 0x77, 0x2b, 0x41,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xb5, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xc5, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0x3f,
+ 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xda, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f,
+ 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xe2, 0x3f, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xe5, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x3f, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xea, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x0a, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x1a, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x84, 0x2e, 0x41, 0x00, 0x00, 0x00, 0x00, 0x84, 0xd7, 0x97, 0x41,
+ 0x00, 0x00, 0x00, 0x20, 0x5f, 0xa0, 0x02, 0x42, 0x00, 0x00, 0x00, 0xa2, 0x94, 0x1a, 0x6d, 0x42
+ };
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs
new file mode 100644
index 0000000000..48f62019d7
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/ChineseLunisolarCalendar.cs
@@ -0,0 +1,399 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about ChineseLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1901/02/19 2101/01/28
+ ** ChineseLunisolar 1901/01/01 2100/12/29
+ */
+ [Serializable]
+ public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar
+ {
+ //
+ // The era value for the current era.
+ //
+
+ public const int ChineseEra = 1;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1901;
+ internal const int MAX_LUNISOLAR_YEAR = 2100;
+
+ internal const int MIN_GREGORIAN_YEAR = 1901;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 19;
+
+ internal const int MAX_GREGORIAN_YEAR = 2101;
+ internal const int MAX_GREGORIAN_MONTH = 1;
+ internal const int MAX_GREGORIAN_DAY = 28;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations
+ return 384;
+ }
+ }
+
+
+ private static readonly int[,] s_yinfo =
+ {
+ /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+ 1901 */
+ { 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
+2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+2051 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+2052 */{ 8 , 2 , 1 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+2053 */{ 0 , 2 , 19 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+2054 */{ 0 , 2 , 8 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+2055 */{ 6 , 1 , 28 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+2056 */{ 0 , 2 , 15 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+2057 */{ 0 , 2 , 4 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
+2058 */{ 4 , 1 , 24 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+2059 */{ 0 , 2 , 12 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
+2060 */{ 0 , 2 , 2 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2061 */{ 3 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+2062 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2063 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2064 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2065 */{ 0 , 2 , 5 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2066 */{ 5 , 1 , 26 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2067 */{ 0 , 2 , 14 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2068 */{ 0 , 2 , 3 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+2069 */{ 4 , 1 , 23 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+2070 */{ 0 , 2 , 11 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
+2071 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+2072 */{ 0 , 2 , 19 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2073 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2074 */{ 6 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2075 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2076 */{ 0 , 2 , 5 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+2077 */{ 4 , 1 , 24 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+2078 */{ 0 , 2 , 12 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2079 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2080 */{ 3 , 1 , 22 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+2081 */{ 0 , 2 , 9 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+2082 */{ 7 , 1 , 29 , 29336 },/* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
+2083 */{ 0 , 2 , 17 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2084 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2085 */{ 5 , 1 , 26 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2086 */{ 0 , 2 , 14 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2087 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2088 */{ 4 , 1 , 24 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+2089 */{ 0 , 2 , 10 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2090 */{ 8 , 1 , 30 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2091 */{ 0 , 2 , 18 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2092 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+2093 */{ 6 , 1 , 27 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2094 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2095 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2096 */{ 4 , 1 , 25 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+2097 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2098 */{ 0 , 2 , 1 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
+2099 */{ 2 , 1 , 21 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+2100 */{ 0 , 2 , 9 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+ */};
+
+
+ internal override int MinCalendarYear
+ {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear
+ {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo
+ {
+ get
+ {
+ return (null);
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index)
+ {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time)
+ {
+ return year;
+ }
+
+ internal override int GetGregorianYear(int year, int era)
+ {
+ if (era != CurrentEra && era != ChineseEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return year;
+ }
+
+ public ChineseLunisolarCalendar()
+ {
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetEra(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return (ChineseEra);
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.CHINESELUNISOLAR);
+ }
+ }
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ //Use CAL_GREGORIAN just to get CurrentEraValue as 1 since we do not have data under the ID CAL_ChineseLunisolar yet
+ return (CalendarId.GREGORIAN);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { ChineseEra });
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
new file mode 100644
index 0000000000..2aaf5a22fa
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Unix.cs
@@ -0,0 +1,315 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Globalization
+{
+ public partial class CompareInfo
+ {
+ [NonSerialized]
+ private Interop.GlobalizationInterop.SafeSortHandle _sortHandle;
+
+ [NonSerialized]
+ private bool _isAsciiEqualityOrdinal;
+
+ [SecuritySafeCritical]
+ internal CompareInfo(CultureInfo culture)
+ {
+ _name = culture.m_name;
+ InitSort(culture);
+ }
+
+ private void InitSort(CultureInfo culture)
+ {
+ _sortName = culture.SortName;
+ _sortHandle = Interop.GlobalizationInterop.GetSortHandle(GetNullTerminatedUtf8String(_sortName));
+ _isAsciiEqualityOrdinal = (_sortName == "en-US" || _sortName == "");
+ }
+
+ internal static unsafe int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert(value != null);
+
+ if (value.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (count < value.Length)
+ {
+ return -1;
+ }
+
+ if (ignoreCase)
+ {
+ fixed (char* pSource = source)
+ {
+ int index = Interop.GlobalizationInterop.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + startIndex, count, findLast: false);
+ return index != -1 ?
+ startIndex + index :
+ -1;
+ }
+ }
+
+ int endIndex = startIndex + (count - value.Length);
+ for (int i = startIndex; i <= endIndex; i++)
+ {
+ int valueIndex, sourceIndex;
+
+ for (valueIndex = 0, sourceIndex = i;
+ valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
+ valueIndex++, sourceIndex++) ;
+
+ if (valueIndex == value.Length)
+ {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ internal static unsafe int LastIndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert(value != null);
+
+ if (value.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (count < value.Length)
+ {
+ return -1;
+ }
+
+ // startIndex is the index into source where we start search backwards from.
+ // leftStartIndex is the index into source of the start of the string that is
+ // count characters away from startIndex.
+ int leftStartIndex = startIndex - count + 1;
+
+ if (ignoreCase)
+ {
+ fixed (char* pSource = source)
+ {
+ int lastIndex = Interop.GlobalizationInterop.IndexOfOrdinalIgnoreCase(value, value.Length, pSource + leftStartIndex, count, findLast: true);
+ return lastIndex != -1 ?
+ leftStartIndex + lastIndex :
+ -1;
+ }
+ }
+
+ for (int i = startIndex - value.Length + 1; i >= leftStartIndex; i--)
+ {
+ int valueIndex, sourceIndex;
+
+ for (valueIndex = 0, sourceIndex = i;
+ valueIndex < value.Length && source[sourceIndex] == value[valueIndex];
+ valueIndex++, sourceIndex++) ;
+
+ if (valueIndex == value.Length) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ private int GetHashCodeOfStringCore(string source, CompareOptions options)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return GetHashCodeOfStringCore(source, options, forceRandomizedHashing: false, additionalEntropy: 0);
+ }
+
+ private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
+ {
+ return Interop.GlobalizationInterop.CompareStringOrdinalIgnoreCase(string1, count1, string2, count2);
+ }
+
+ private unsafe int CompareString(string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options)
+ {
+ Contract.Assert(string1 != null);
+ Contract.Assert(string2 != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ fixed (char* pString1 = string1)
+ {
+ fixed (char* pString2 = string2)
+ {
+ return Interop.GlobalizationInterop.CompareString(_sortHandle, pString1 + offset1, length1, pString2 + offset2, length2, options);
+ }
+ }
+ }
+
+ private unsafe int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(target != null);
+ Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ if (target.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return IndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ }
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
+ {
+ return IndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ }
+
+ fixed (char* pSource = source)
+ {
+ int index = Interop.GlobalizationInterop.IndexOf(_sortHandle, target, target.Length, pSource + startIndex, count, options);
+
+ return index != -1 ? index + startIndex : -1;
+ }
+ }
+
+ private unsafe int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(target != null);
+ Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ if (target.Length == 0)
+ {
+ return startIndex;
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return LastIndexOfOrdinal(source, target, startIndex, count, ignoreCase: false);
+ }
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && target.IsFastSort())
+ {
+ return LastIndexOf(source, target, startIndex, count, GetOrdinalCompareOptions(options));
+ }
+
+ // startIndex is the index into source where we start search backwards from. leftStartIndex is the index into source
+ // of the start of the string that is count characters away from startIndex.
+ int leftStartIndex = (startIndex - count + 1);
+
+ fixed (char* pSource = source)
+ {
+ int lastIndex = Interop.GlobalizationInterop.LastIndexOf(_sortHandle, target, target.Length, pSource + (startIndex - count + 1), count, options);
+
+ return lastIndex != -1 ? lastIndex + leftStartIndex : -1;
+ }
+ }
+
+ [SecuritySafeCritical]
+ private bool StartsWith(string source, string prefix, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(!string.IsNullOrEmpty(prefix));
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && prefix.IsFastSort())
+ {
+ return IsPrefix(source, prefix, GetOrdinalCompareOptions(options));
+ }
+
+ return Interop.GlobalizationInterop.StartsWith(_sortHandle, prefix, prefix.Length, source, source.Length, options);
+ }
+
+ [SecuritySafeCritical]
+ private bool EndsWith(string source, string suffix, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(!string.IsNullOrEmpty(suffix));
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (_isAsciiEqualityOrdinal && CanUseAsciiOrdinalForOptions(options) && source.IsFastSort() && suffix.IsFastSort())
+ {
+ return IsSuffix(source, suffix, GetOrdinalCompareOptions(options));
+ }
+
+ return Interop.GlobalizationInterop.EndsWith(_sortHandle, suffix, suffix.Length, source, source.Length, options);
+ }
+
+ // -----------------------------
+ // ---- PAL layer ends here ----
+ // -----------------------------
+
+ [SecuritySafeCritical]
+ internal unsafe int GetHashCodeOfStringCore(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (source.Length == 0)
+ {
+ return 0;
+ }
+
+ int sortKeyLength = Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, null, 0, options);
+
+ // As an optimization, for small sort keys we allocate the buffer on the stack.
+ if (sortKeyLength <= 256)
+ {
+ byte* pSortKey = stackalloc byte[sortKeyLength];
+ Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
+ return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy);
+ }
+
+ byte[] sortKey = new byte[sortKeyLength];
+
+ fixed(byte* pSortKey = sortKey)
+ {
+ Interop.GlobalizationInterop.GetSortKey(_sortHandle, source, source.Length, pSortKey, sortKeyLength, options);
+ return InternalHashSortKey(pSortKey, sortKeyLength, false, additionalEntropy);
+ }
+ }
+
+ [DllImport(JitHelpers.QCall)]
+ [SuppressUnmanagedCodeSecurity]
+ private static unsafe extern int InternalHashSortKey(byte* sortKey, int sortKeyLength, [MarshalAs(UnmanagedType.Bool)] bool forceRandomizedHashing, long additionalEntropy);
+
+ private static CompareOptions GetOrdinalCompareOptions(CompareOptions options)
+ {
+ if ((options & CompareOptions.IgnoreCase) == CompareOptions.IgnoreCase)
+ {
+ return CompareOptions.OrdinalIgnoreCase;
+ }
+ else
+ {
+ return CompareOptions.Ordinal;
+ }
+ }
+
+ private static bool CanUseAsciiOrdinalForOptions(CompareOptions options)
+ {
+ // Unlike the other Ignore options, IgnoreSymbols impacts ASCII characters (e.g. ').
+ return (options & CompareOptions.IgnoreSymbols) == 0;
+ }
+
+ private static byte[] GetNullTerminatedUtf8String(string s)
+ {
+ int byteLen = System.Text.Encoding.UTF8.GetByteCount(s);
+
+ // Allocate an extra byte (which defaults to 0) as the null terminator.
+ byte[] buffer = new byte[byteLen + 1];
+
+ int bytesWritten = System.Text.Encoding.UTF8.GetBytes(s, 0, s.Length, buffer, 0);
+
+ Contract.Assert(bytesWritten == byteLen);
+
+ return buffer;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs
new file mode 100644
index 0000000000..744a48b107
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.Windows.cs
@@ -0,0 +1,395 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ public partial class CompareInfo
+ {
+ internal unsafe CompareInfo(CultureInfo culture)
+ {
+ _name = culture._name;
+ InitSort(culture);
+ }
+
+ private void InitSort(CultureInfo culture)
+ {
+ _sortName = culture.SortName;
+
+ const uint LCMAP_SORTHANDLE = 0x20000000;
+
+ _name = culture._name;
+ _sortName = culture.SortName;
+
+ IntPtr handle;
+ int ret = Interop.mincore.LCMapStringEx(_sortName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero);
+ _sortHandle = ret > 0 ? handle : IntPtr.Zero;
+ }
+
+ private static unsafe int FindStringOrdinal(
+ uint dwFindStringOrdinalFlags,
+ string stringSource,
+ int offset,
+ int cchSource,
+ string value,
+ int cchValue,
+ bool bIgnoreCase)
+ {
+ fixed (char* pSource = stringSource)
+ fixed (char* pValue = value)
+ {
+ int ret = Interop.mincore.FindStringOrdinal(
+ dwFindStringOrdinalFlags,
+ pSource + offset,
+ cchSource,
+ pValue,
+ cchValue,
+ bIgnoreCase ? 1 : 0);
+ return ret < 0 ? ret : ret + offset;
+ }
+ }
+
+ internal static int IndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert(value != null);
+
+ return FindStringOrdinal(FIND_FROMSTART, source, startIndex, count, value, value.Length, ignoreCase);
+ }
+
+ internal static int LastIndexOfOrdinal(string source, string value, int startIndex, int count, bool ignoreCase)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert(value != null);
+
+ return FindStringOrdinal(FIND_FROMEND, source, startIndex - count + 1, count, value, value.Length, ignoreCase);
+ }
+
+ private unsafe int GetHashCodeOfStringCore(string source, CompareOptions options)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ if (source.Length == 0)
+ {
+ return 0;
+ }
+
+ int tmpHash = 0;
+
+ fixed (char* pSource = source)
+ {
+ if (Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _sortName,
+ LCMAP_HASH | (uint)GetNativeCompareFlags(options),
+ pSource, source.Length,
+ &tmpHash, sizeof(int),
+ null, null, _sortHandle) == 0)
+ {
+ Environment.FailFast("LCMapStringEx failed!");
+ }
+ }
+
+ return tmpHash;
+ }
+
+ private static unsafe int CompareStringOrdinalIgnoreCase(char* string1, int count1, char* string2, int count2)
+ {
+ // Use the OS to compare and then convert the result to expected value by subtracting 2
+ return Interop.mincore.CompareStringOrdinal(string1, count1, string2, count2, true) - 2;
+ }
+
+ private unsafe int CompareString(string string1, int offset1, int length1, string string2, int offset2, int length2, CompareOptions options)
+ {
+ Contract.Assert(string1 != null);
+ Contract.Assert(string2 != null);
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pString1 = string1)
+ fixed (char* pString2 = string2)
+ {
+ int result = Interop.mincore.CompareStringEx(
+ pLocaleName,
+ (uint)GetNativeCompareFlags(options),
+ pString1 + offset1,
+ length1,
+ pString2 + offset2,
+ length2,
+ null,
+ null,
+ _sortHandle);
+
+ if (result == 0)
+ {
+ Environment.FailFast("CompareStringEx failed");
+ }
+
+ // Map CompareStringEx return value to -1, 0, 1.
+ return result - 2;
+ }
+ }
+
+ private unsafe int FindString(
+ uint dwFindNLSStringFlags,
+ string lpStringSource,
+ int startSource,
+ int cchSource,
+ string lpStringValue,
+ int startValue,
+ int cchValue)
+ {
+ string localeName = _sortHandle != IntPtr.Zero ? null : _sortName;
+
+ fixed (char* pLocaleName = localeName)
+ fixed (char* pSource = lpStringSource)
+ fixed (char* pValue = lpStringValue)
+ {
+ char* pS = pSource + startSource;
+ char* pV = pValue + startValue;
+
+ return Interop.mincore.FindNLSStringEx(
+ pLocaleName,
+ dwFindNLSStringFlags,
+ pS,
+ cchSource,
+ pV,
+ cchValue,
+ null,
+ null,
+ null,
+ _sortHandle);
+ }
+ }
+
+ private int IndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(target != null);
+ Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for
+ // and add a precondition that target is not empty.
+ if (target.Length == 0)
+ return startIndex; // keep Whidbey compatibility
+
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ return FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: false);
+ }
+ else
+ {
+ int retValue = FindString(FIND_FROMSTART | (uint)GetNativeCompareFlags(options),
+ source,
+ startIndex,
+ count,
+ target,
+ 0,
+ target.Length);
+ if (retValue >= 0)
+ {
+ return retValue + startIndex;
+ }
+ }
+
+ return -1;
+ }
+
+ private int LastIndexOfCore(string source, string target, int startIndex, int count, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(target != null);
+ Contract.Assert((options & CompareOptions.OrdinalIgnoreCase) == 0);
+
+ // TODO: Consider moving this up to the relevent APIs we need to ensure this behavior for
+ // and add a precondition that target is not empty.
+ if (target.Length == 0)
+ return startIndex; // keep Whidbey compatibility
+
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ return FastIndexOfString(source, target, startIndex, count, target.Length, findLastIndex: true);
+ }
+ else
+ {
+ int retValue = FindString(FIND_FROMEND | (uint)GetNativeCompareFlags(options),
+ source,
+ startIndex - count + 1,
+ count,
+ target,
+ 0,
+ target.Length);
+
+ if (retValue >= 0)
+ {
+ return retValue + startIndex - (count - 1);
+ }
+ }
+
+ return -1;
+ }
+
+ private bool StartsWith(string source, string prefix, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(!string.IsNullOrEmpty(prefix));
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_STARTSWITH | (uint)GetNativeCompareFlags(options),
+ source,
+ 0,
+ source.Length,
+ prefix,
+ 0,
+ prefix.Length) >= 0;
+ }
+
+ private bool EndsWith(string source, string suffix, CompareOptions options)
+ {
+ Contract.Assert(!string.IsNullOrEmpty(source));
+ Contract.Assert(!string.IsNullOrEmpty(suffix));
+ Contract.Assert((options & (CompareOptions.Ordinal | CompareOptions.OrdinalIgnoreCase)) == 0);
+
+ return FindString(FIND_ENDSWITH | (uint)GetNativeCompareFlags(options),
+ source,
+ 0,
+ source.Length,
+ suffix,
+ 0,
+ suffix.Length) >= 0;
+ }
+
+ // PAL ends here
+ [NonSerialized]
+ private readonly IntPtr _sortHandle;
+
+ private const uint LCMAP_HASH = 0x00040000;
+
+ private const int FIND_STARTSWITH = 0x00100000;
+ private const int FIND_ENDSWITH = 0x00200000;
+ private const int FIND_FROMSTART = 0x00400000;
+ private const int FIND_FROMEND = 0x00800000;
+
+ // TODO: Instead of this method could we just have upstack code call IndexOfOrdinal with ignoreCase = false?
+ private static unsafe int FastIndexOfString(string source, string target, int startIndex, int sourceCount, int targetCount, bool findLastIndex)
+ {
+ int retValue = -1;
+
+ int sourceStartIndex = findLastIndex ? startIndex - sourceCount + 1 : startIndex;
+
+#if !TEST_CODEGEN_OPTIMIZATION
+ fixed (char* pSource = source, spTarget = target)
+ {
+ char* spSubSource = pSource + sourceStartIndex;
+#else
+ String.StringPointer spSubSource = source.GetStringPointer(sourceStartIndex);
+ String.StringPointer spTarget = target.GetStringPointer();
+#endif
+ if (findLastIndex)
+ {
+ int startPattern = (sourceCount - 1) - targetCount + 1;
+ if (startPattern < 0)
+ return -1;
+
+ char patternChar0 = spTarget[0];
+ for (int ctrSrc = startPattern; ctrSrc >= 0; ctrSrc--)
+ {
+ if (spSubSource[ctrSrc] != patternChar0)
+ continue;
+
+ int ctrPat;
+ for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
+ {
+ if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
+ break;
+ }
+ if (ctrPat == targetCount)
+ {
+ retValue = ctrSrc;
+ break;
+ }
+ }
+
+ if (retValue >= 0)
+ {
+ retValue += startIndex - sourceCount + 1;
+ }
+ }
+ else
+ {
+ int endPattern = (sourceCount - 1) - targetCount + 1;
+ if (endPattern < 0)
+ return -1;
+
+ char patternChar0 = spTarget[0];
+ for (int ctrSrc = 0; ctrSrc <= endPattern; ctrSrc++)
+ {
+ if (spSubSource[ctrSrc] != patternChar0)
+ continue;
+ int ctrPat;
+ for (ctrPat = 1; ctrPat < targetCount; ctrPat++)
+ {
+ if (spSubSource[ctrSrc + ctrPat] != spTarget[ctrPat])
+ break;
+ }
+ if (ctrPat == targetCount)
+ {
+ retValue = ctrSrc;
+ break;
+ }
+ }
+
+ if (retValue >= 0)
+ {
+ retValue += startIndex;
+ }
+ }
+#if !TEST_CODEGEN_OPTIMIZATION
+ }
+
+ return retValue;
+#endif // TEST_CODEGEN_OPTIMIZATION
+ }
+
+ private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal
+ private const int NORM_IGNORECASE = 0x00000001; // Ignores case. (use LINGUISTIC_IGNORECASE instead)
+ private const int NORM_IGNOREKANATYPE = 0x00010000; // Does not differentiate between Hiragana and Katakana characters. Corresponding Hiragana and Katakana will compare as equal.
+ private const int NORM_IGNORENONSPACE = 0x00000002; // Ignores nonspacing. This flag also removes Japanese accent characters. (use LINGUISTIC_IGNOREDIACRITIC instead)
+ private const int NORM_IGNORESYMBOLS = 0x00000004; // Ignores symbols.
+ private const int NORM_IGNOREWIDTH = 0x00020000; // Does not differentiate between a single-byte character and the same character as a double-byte character.
+ private const int NORM_LINGUISTIC_CASING = 0x08000000; // use linguistic rules for casing
+ private const int SORT_STRINGSORT = 0x00001000; // Treats punctuation the same as symbols.
+
+ private static int GetNativeCompareFlags(CompareOptions options)
+ {
+ // Use "linguistic casing" by default (load the culture's casing exception tables)
+ int nativeCompareFlags = NORM_LINGUISTIC_CASING;
+
+ if ((options & CompareOptions.IgnoreCase) != 0) { nativeCompareFlags |= NORM_IGNORECASE; }
+ if ((options & CompareOptions.IgnoreKanaType) != 0) { nativeCompareFlags |= NORM_IGNOREKANATYPE; }
+ if ((options & CompareOptions.IgnoreNonSpace) != 0) { nativeCompareFlags |= NORM_IGNORENONSPACE; }
+ if ((options & CompareOptions.IgnoreSymbols) != 0) { nativeCompareFlags |= NORM_IGNORESYMBOLS; }
+ if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; }
+ if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; }
+
+ // TODO: Can we try for GetNativeCompareFlags to never
+ // take Ordinal or OrdinalIgnoreCase. This value is not part of Win32, we just handle it special
+ // in some places.
+ // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag
+ if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; }
+
+ Contract.Assert(((options & ~(CompareOptions.IgnoreCase |
+ CompareOptions.IgnoreKanaType |
+ CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreSymbols |
+ CompareOptions.IgnoreWidth |
+ CompareOptions.StringSort)) == 0) ||
+ (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled");
+
+ return nativeCompareFlags;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CompareInfo.cs b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs
new file mode 100644
index 0000000000..77778af23c
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CompareInfo.cs
@@ -0,0 +1,925 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+// Purpose: This class implements a set of methods for comparing
+// strings.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System.Globalization
+{
+ [Flags]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CompareOptions
+ {
+ None = 0x00000000,
+ IgnoreCase = 0x00000001,
+ IgnoreNonSpace = 0x00000002,
+ IgnoreSymbols = 0x00000004,
+ IgnoreKanaType = 0x00000008, // ignore kanatype
+ IgnoreWidth = 0x00000010, // ignore width
+ OrdinalIgnoreCase = 0x10000000, // This flag can not be used with other flags.
+ StringSort = 0x20000000, // use string sort method
+ Ordinal = 0x40000000, // This flag can not be used with other flags.
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class CompareInfo : IDeserializationCallback
+ {
+ // Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags.
+ private const CompareOptions ValidIndexMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
+
+ // Mask used to check if Compare() has the right flags.
+ private const CompareOptions ValidCompareMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort);
+
+ // Mask used to check if GetHashCodeOfString() has the right flags.
+ private const CompareOptions ValidHashCodeOfStringMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
+
+ //
+ // CompareInfos have an interesting identity. They are attached to the locale that created them,
+ // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US.
+ // The interesting part is that since haw-US doesn't have its own sort, it has to point at another
+ // locale, which is what SCOMPAREINFO does.
+
+ [OptionalField(VersionAdded = 2)]
+ private String _name; // The name used to construct this CompareInfo
+ [NonSerialized]
+ private String _sortName; // The name that defines our behavior
+
+ /*=================================GetCompareInfo==========================
+ **Action: Get the CompareInfo for the specified culture.
+ **Returns: The CompareInfo for the specified culture.
+ **Arguments:
+ ** name the name of the culture.
+ **Exceptions:
+ ** ArgumentException if name is invalid.
+ ============================================================================*/
+
+ public static CompareInfo GetCompareInfo(String name)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+ Contract.EndContractBlock();
+
+ return CultureInfo.GetCultureInfo(name).CompareInfo;
+ }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ _name = null;
+ }
+
+ void IDeserializationCallback.OnDeserialization(Object sender)
+ {
+ OnDeserialized();
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserialized();
+ }
+
+ private void OnDeserialized()
+ {
+ if (_name != null)
+ {
+ InitSort(CultureInfo.GetCultureInfo(_name));
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx) { }
+
+ ///////////////////////////----- Name -----/////////////////////////////////
+ //
+ // Returns the name of the culture (well actually, of the sort).
+ // Very important for providing a non-LCID way of identifying
+ // what the sort is.
+ //
+ // Note that this name isn't dereferenced in case the CompareInfo is a different locale
+ // which is consistent with the behaviors of earlier versions. (so if you ask for a sort
+ // and the locale's changed behavior, then you'll get changed behavior, which is like
+ // what happens for a version update)
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String Name
+ {
+ get
+ {
+ Contract.Assert(_name != null, "CompareInfo.Name Expected _name to be set");
+ if (_name == "zh-CHT" || _name == "zh-CHS")
+ {
+ return _name;
+ }
+
+ return _sortName;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Compare
+ //
+ // Compares the two strings with the given options. Returns 0 if the
+ // two strings are equal, a number less than 0 if string1 is less
+ // than string2, and a number greater than 0 if string1 is greater
+ // than string2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public virtual int Compare(String string1, String string2)
+ {
+ return (Compare(string1, string2, CompareOptions.None));
+ }
+
+ public unsafe virtual int Compare(String string1, String string2, CompareOptions options)
+ {
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // Verify the options before we do any real comparison.
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ if (options != CompareOptions.Ordinal)
+ {
+ throw new ArgumentException(SR.Argument_CompareOptionOrdinal, "options");
+ }
+ return String.CompareOrdinal(string1, string2);
+ }
+
+ if ((options & ValidCompareMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+ }
+
+ //Our paradigm is that null sorts less than any other string and
+ //that two nulls sort as equal.
+ if (string1 == null)
+ {
+ if (string2 == null)
+ {
+ return (0); // Equal
+ }
+ return (-1); // null < non-null
+ }
+ if (string2 == null)
+ {
+ return (1); // non-null > null
+ }
+
+ return CompareString(string1, 0, string1.Length, string2, 0, string2.Length, options);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Compare
+ //
+ // Compares the specified regions of the two strings with the given
+ // options.
+ // Returns 0 if the two strings are equal, a number less than 0 if
+ // string1 is less than string2, and a number greater than 0 if
+ // string1 is greater than string2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2)
+ {
+ return Compare(string1, offset1, length1, string2, offset2, length2, 0);
+ }
+
+
+ public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2, CompareOptions options)
+ {
+ return Compare(string1, offset1, string1 == null ? 0 : string1.Length - offset1,
+ string2, offset2, string2 == null ? 0 : string2.Length - offset2, options);
+ }
+
+
+ public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2)
+ {
+ return Compare(string1, offset1, string2, offset2, 0);
+ }
+
+
+ public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2, CompareOptions options)
+ {
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ int result = String.Compare(string1, offset1, string2, offset2, length1 < length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
+ if ((length1 != length2) && result == 0)
+ return (length1 > length2 ? 1 : -1);
+ return (result);
+ }
+
+ // Verify inputs
+ if (length1 < 0 || length2 < 0)
+ {
+ throw new ArgumentOutOfRangeException((length1 < 0) ? "length1" : "length2", SR.ArgumentOutOfRange_NeedPosNum);
+ }
+ if (offset1 < 0 || offset2 < 0)
+ {
+ throw new ArgumentOutOfRangeException((offset1 < 0) ? "offset1" : "offset2", SR.ArgumentOutOfRange_NeedPosNum);
+ }
+ if (offset1 > (string1 == null ? 0 : string1.Length) - length1)
+ {
+ throw new ArgumentOutOfRangeException("string1", SR.ArgumentOutOfRange_OffsetLength);
+ }
+ if (offset2 > (string2 == null ? 0 : string2.Length) - length2)
+ {
+ throw new ArgumentOutOfRangeException("string2", SR.ArgumentOutOfRange_OffsetLength);
+ }
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ if (options != CompareOptions.Ordinal)
+ {
+ throw new ArgumentException(SR.Argument_CompareOptionOrdinal,
+ "options");
+ }
+ }
+ else if ((options & ValidCompareMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+ }
+
+ //
+ // Check for the null case.
+ //
+ if (string1 == null)
+ {
+ if (string2 == null)
+ {
+ return (0);
+ }
+ return (-1);
+ }
+ if (string2 == null)
+ {
+ return (1);
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return CompareOrdinal(string1, offset1, length1,
+ string2, offset2, length2);
+ }
+ return CompareString(string1, offset1, length1,
+ string2, offset2, length2,
+ options);
+ }
+
+ private static int CompareOrdinal(string string1, int offset1, int length1, string string2, int offset2, int length2)
+ {
+ int result = String.CompareOrdinal(string1, offset1, string2, offset2,
+ (length1 < length2 ? length1 : length2));
+ if ((length1 != length2) && result == 0)
+ {
+ return (length1 > length2 ? 1 : -1);
+ }
+ return (result);
+ }
+
+ //
+ // CompareOrdinalIgnoreCase compare two string oridnally with ignoring the case.
+ // it assumes the strings are Ascii string till we hit non Ascii character in strA or strB and then we continue the comparison by
+ // calling the OS.
+ //
+ internal static unsafe int CompareOrdinalIgnoreCase(string strA, int indexA, int lengthA, string strB, int indexB, int lengthB)
+ {
+ Contract.Assert(indexA + lengthA <= strA.Length);
+ Contract.Assert(indexB + lengthB <= strB.Length);
+
+ int length = Math.Min(lengthA, lengthB);
+ int range = length;
+
+ fixed (char* ap = strA) fixed (char* bp = strB)
+ {
+ char* a = ap + indexA;
+ char* b = bp + indexB;
+
+ while (length != 0 && (*a <= 0x80) && (*b <= 0x80))
+ {
+ int charA = *a;
+ int charB = *b;
+
+ if (charA == charB)
+ {
+ a++; b++;
+ length--;
+ continue;
+ }
+
+ // uppercase both chars - notice that we need just one compare per char
+ if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
+ if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
+
+ //Return the (case-insensitive) difference between them.
+ if (charA != charB)
+ return charA - charB;
+
+ // Next char
+ a++; b++;
+ length--;
+ }
+
+ if (length == 0)
+ return lengthA - lengthB;
+
+ range -= length;
+
+ return CompareStringOrdinalIgnoreCase(a, lengthA - range, b, lengthB - range);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsPrefix
+ //
+ // Determines whether prefix is a prefix of string. If prefix equals
+ // String.Empty, true is returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options)
+ {
+ if (source == null || prefix == null)
+ {
+ throw new ArgumentNullException((source == null ? "source" : "prefix"),
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ if (prefix.Length == 0)
+ {
+ return (true);
+ }
+
+ if (source.Length == 0)
+ {
+ return false;
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return source.StartsWith(prefix, StringComparison.Ordinal);
+ }
+
+ if ((options & ValidIndexMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+ }
+
+ return StartsWith(source, prefix, options);
+ }
+
+ public virtual bool IsPrefix(String source, String prefix)
+ {
+ return (IsPrefix(source, prefix, 0));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsSuffix
+ //
+ // Determines whether suffix is a suffix of string. If suffix equals
+ // String.Empty, true is returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public unsafe virtual bool IsSuffix(String source, String suffix, CompareOptions options)
+ {
+ if (source == null || suffix == null)
+ {
+ throw new ArgumentNullException((source == null ? "source" : "suffix"),
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ if (suffix.Length == 0)
+ {
+ return (true);
+ }
+
+ if (source.Length == 0)
+ {
+ return false;
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.EndsWith(suffix, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return source.EndsWith(suffix, StringComparison.Ordinal);
+ }
+
+ if ((options & ValidIndexMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+ }
+
+ return EndsWith(source, suffix, options);
+ }
+
+
+ public virtual bool IsSuffix(String source, String suffix)
+ {
+ return (IsSuffix(source, suffix, 0));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IndexOf
+ //
+ // Returns the first index where value is found in string. The
+ // search starts from startIndex and ends at endIndex. Returns -1 if
+ // the specified value is not found. If value equals String.Empty,
+ // startIndex is returned. Throws IndexOutOfRange if startIndex or
+ // endIndex is less than zero or greater than the length of string.
+ // Throws ArgumentException if value is null.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int IndexOf(String source, char value)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, int count)
+ {
+ return IndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, int count)
+ {
+ return IndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, int count, CompareOptions options)
+ {
+ // Validate inputs
+ if (source == null)
+ throw new ArgumentNullException("source");
+
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index);
+
+ if (count < 0 || startIndex > source.Length - count)
+ throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count);
+ Contract.EndContractBlock();
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.IndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+
+ return IndexOfCore(source, new string(value, 1), startIndex, count, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options)
+ {
+ // Validate inputs
+ if (source == null)
+ throw new ArgumentNullException("source");
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (startIndex > source.Length)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index);
+ }
+ Contract.EndContractBlock();
+
+ // In Everett we used to return -1 for empty string even if startIndex is negative number so we keeping same behavior here.
+ // We return 0 if both source and value are empty strings for Everett compatibility too.
+ if (source.Length == 0)
+ {
+ if (value.Length == 0)
+ {
+ return 0;
+ }
+ return -1;
+ }
+
+ if (startIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index);
+ }
+
+ if (count < 0 || startIndex > source.Length - count)
+ throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count);
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
+ }
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+
+ return IndexOfCore(source, value, startIndex, count, options);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // LastIndexOf
+ //
+ // Returns the last index where value is found in string. The
+ // search starts from startIndex and ends at endIndex. Returns -1 if
+ // the specified value is not found. If value equals String.Empty,
+ // endIndex is returned. Throws IndexOutOfRange if startIndex or
+ // endIndex is less than zero or greater than the length of string.
+ // Throws ArgumentException if value is null.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int LastIndexOf(String source, char value)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, CompareOptions.None);
+ }
+
+
+ public virtual int LastIndexOf(String source, String value)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, CompareOptions.None);
+ }
+
+
+ public virtual int LastIndexOf(String source, char value, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, options);
+ }
+
+ public unsafe virtual int LastIndexOf(String source, String value, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, CompareOptions options)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, CompareOptions options)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count)
+ {
+ return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count)
+ {
+ return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count, CompareOptions options)
+ {
+ // Verify Arguments
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 &&
+ (options != CompareOptions.Ordinal) &&
+ (options != CompareOptions.OrdinalIgnoreCase))
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+
+ // Special case for 0 length input strings
+ if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
+ return -1;
+
+ // Make sure we're not out of range
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index);
+
+ // Make sure that we allow startIndex == source.Length
+ if (startIndex == source.Length)
+ {
+ startIndex--;
+ if (count > 0)
+ count--;
+ }
+
+ // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count);
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.LastIndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ return LastIndexOfCore(source, value.ToString(), startIndex, count, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count, CompareOptions options)
+ {
+ // Verify Arguments
+ if (source == null)
+ throw new ArgumentNullException("source");
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 &&
+ (options != CompareOptions.Ordinal) &&
+ (options != CompareOptions.OrdinalIgnoreCase))
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+
+ // Special case for 0 length input strings
+ if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
+ return (value.Length == 0) ? 0 : -1;
+
+ // Make sure we're not out of range
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", SR.ArgumentOutOfRange_Index);
+
+ // Make sure that we allow startIndex == source.Length
+ if (startIndex == source.Length)
+ {
+ startIndex--;
+ if (count > 0)
+ count--;
+
+ // If we are looking for nothing, just return 0
+ if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0)
+ return startIndex;
+ }
+
+ // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_Count);
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
+ }
+
+ return LastIndexOfCore(source, value, startIndex, count, options);
+ }
+
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CompareInfo as the current
+ // instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Equals(Object value)
+ {
+ CompareInfo that = value as CompareInfo;
+
+ if (that != null)
+ {
+ return this.Name == that.Name;
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CompareInfo. The hash code is guaranteed to be the same for
+ // CompareInfo A and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCodeOfString
+ //
+ // This internal method allows a method that allows the equivalent of creating a Sortkey for a
+ // string from CompareInfo, and generate a hashcode value from it. It is not very convenient
+ // to use this method as is and it creates an unnecessary Sortkey object that will be GC'ed.
+ //
+ // The hash code is guaranteed to be the same for string A and B where A.Equals(B) is true and both
+ // the CompareInfo and the CompareOptions are the same. If two different CompareInfo objects
+ // treat the string the same way, this implementation will treat them differently (the same way that
+ // Sortkey does at the moment).
+ //
+ // This method will never be made public itself, but public consumers of it could be created, e.g.:
+ //
+ // string.GetHashCode(CultureInfo)
+ // string.GetHashCode(CompareInfo)
+ // string.GetHashCode(CultureInfo, CompareOptions)
+ // string.GetHashCode(CompareInfo, CompareOptions)
+ // etc.
+ //
+ // (the methods above that take a CultureInfo would use CultureInfo.CompareInfo)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ internal int GetHashCodeOfString(string source, CompareOptions options)
+ {
+ //
+ // Parameter validation
+ //
+ if (null == source)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if ((options & ValidHashCodeOfStringMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidFlag, "options");
+ }
+ Contract.EndContractBlock();
+
+ return GetHashCodeOfStringCore(source, options);
+ }
+
+ public virtual int GetHashCode(string source, CompareOptions options)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return source.GetHashCode();
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return TextInfo.GetHashCodeOrdinalIgnoreCase(source);
+ }
+
+ //
+ // GetHashCodeOfString does more parameters validation. basically will throw when
+ // having Ordinal, OrdinalIgnoreCase and StringSort
+ //
+
+ return GetHashCodeOfString(source, options);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns a string describing the
+ // CompareInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override String ToString()
+ {
+ return ("CompareInfo - " + this.Name);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs
new file mode 100644
index 0000000000..58aae2f40b
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureData.Unix.cs
@@ -0,0 +1,304 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+
+namespace System.Globalization
+{
+ internal partial class CultureData
+ {
+ // ICU constants
+ const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value
+ const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name
+ const string ICU_COLLATION_KEYWORD = "@collation=";
+
+ /// <summary>
+ /// This method uses the sRealName field (which is initialized by the constructor before this is called) to
+ /// initialize the rest of the state of CultureData based on the underlying OS globalization library.
+ /// </summary>
+ [SecuritySafeCritical]
+ private unsafe bool InitCultureData()
+ {
+ Contract.Assert(_sRealName != null);
+
+ string alternateSortName = string.Empty;
+ string realNameBuffer = _sRealName;
+
+ // Basic validation
+ if (realNameBuffer.Contains("@"))
+ {
+ return false; // don't allow ICU variants to come in directly
+ }
+
+ // Replace _ (alternate sort) with @collation= for ICU
+ int index = realNameBuffer.IndexOf('_');
+ if (index > 0)
+ {
+ if (index >= (realNameBuffer.Length - 1) // must have characters after _
+ || realNameBuffer.Substring(index + 1).Contains("_")) // only one _ allowed
+ {
+ return false; // fail
+ }
+ alternateSortName = realNameBuffer.Substring(index + 1);
+ realNameBuffer = realNameBuffer.Substring(0, index) + ICU_COLLATION_KEYWORD + alternateSortName;
+ }
+
+ // Get the locale name from ICU
+ if (!GetLocaleName(realNameBuffer, out _sWindowsName))
+ {
+ return false; // fail
+ }
+
+ // Replace the ICU collation keyword with an _
+ index = _sWindowsName.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal);
+ if (index >= 0)
+ {
+ _sName = _sWindowsName.Substring(0, index) + "_" + alternateSortName;
+ }
+ else
+ {
+ _sName = _sWindowsName;
+ }
+ _sRealName = _sName;
+ _sSpecificCulture = _sRealName; // we don't attempt to find a non-neutral locale if a neutral is passed in (unlike win32)
+
+ _iLanguage = this.ILANGUAGE;
+ if (_iLanguage == 0)
+ {
+ _iLanguage = LOCALE_CUSTOM_UNSPECIFIED;
+ }
+
+ _bNeutral = (this.SISO3166CTRYNAME.Length == 0);
+
+ // Remove the sort from sName unless custom culture
+ if (!_bNeutral)
+ {
+ if (!IsCustomCultureId(_iLanguage))
+ {
+ _sName = _sWindowsName.Substring(0, index);
+ }
+ }
+ return true;
+ }
+
+ [SecuritySafeCritical]
+ internal static bool GetLocaleName(string localeName, out string windowsName)
+ {
+ // Get the locale name from ICU
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
+ if (!Interop.GlobalizationInterop.GetLocaleName(localeName, sb, sb.Capacity))
+ {
+ StringBuilderCache.Release(sb);
+ windowsName = null;
+ return false; // fail
+ }
+
+ // Success - use the locale name returned which may be different than realNameBuffer (casing)
+ windowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls
+ return true;
+ }
+
+ [SecuritySafeCritical]
+ internal static bool GetDefaultLocaleName(out string windowsName)
+ {
+ // Get the default (system) locale name from ICU
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
+ if (!Interop.GlobalizationInterop.GetDefaultLocaleName(sb, sb.Capacity))
+ {
+ StringBuilderCache.Release(sb);
+ windowsName = null;
+ return false; // fail
+ }
+
+ // Success - use the locale name returned which may be different than realNameBuffer (casing)
+ windowsName = StringBuilderCache.GetStringAndRelease(sb); // the name passed to subsequent ICU calls
+ return true;
+ }
+
+ private string GetLocaleInfo(LocaleStringData type)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo] Expected _sWindowsName to be populated already");
+ return GetLocaleInfo(_sWindowsName, type);
+ }
+
+ // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
+ // "windows" name, which can be specific for downlevel (< windows 7) os's.
+ [SecuritySafeCritical]
+ private string GetLocaleInfo(string localeName, LocaleStringData type)
+ {
+ Contract.Assert(localeName != null, "[CultureData.GetLocaleInfo] Expected localeName to be not be null");
+
+ switch (type)
+ {
+ case LocaleStringData.NegativeInfinitySymbol:
+ // not an equivalent in ICU; prefix the PositiveInfinitySymbol with NegativeSign
+ return GetLocaleInfo(localeName, LocaleStringData.NegativeSign) +
+ GetLocaleInfo(localeName, LocaleStringData.PositiveInfinitySymbol);
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY);
+
+ bool result = Interop.GlobalizationInterop.GetLocaleInfoString(localeName, (uint)type, sb, sb.Capacity);
+ if (!result)
+ {
+ // Failed, just use empty string
+ StringBuilderCache.Release(sb);
+ Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleStringData)] Failed");
+ return String.Empty;
+ }
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ [SecuritySafeCritical]
+ private int GetLocaleInfo(LocaleNumberData type)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleNumberData)] Expected _sWindowsName to be populated already");
+
+ switch (type)
+ {
+ case LocaleNumberData.CalendarType:
+ // returning 0 will cause the first supported calendar to be returned, which is the preferred calendar
+ return 0;
+ }
+
+
+ int value = 0;
+ bool result = Interop.GlobalizationInterop.GetLocaleInfoInt(_sWindowsName, (uint)type, ref value);
+ if (!result)
+ {
+ // Failed, just use 0
+ Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleNumberData)] failed");
+ }
+
+ return value;
+ }
+
+ [SecuritySafeCritical]
+ private int[] GetLocaleInfo(LocaleGroupingData type)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetLocaleInfo(LocaleGroupingData)] Expected _sWindowsName to be populated already");
+
+ int primaryGroupingSize = 0;
+ int secondaryGroupingSize = 0;
+ bool result = Interop.GlobalizationInterop.GetLocaleInfoGroupingSizes(_sWindowsName, (uint)type, ref primaryGroupingSize, ref secondaryGroupingSize);
+ if (!result)
+ {
+ Contract.Assert(false, "[CultureData.GetLocaleInfo(LocaleGroupingData type)] failed");
+ }
+
+ if (secondaryGroupingSize == 0)
+ {
+ return new int[] { primaryGroupingSize };
+ }
+
+ return new int[] { primaryGroupingSize, secondaryGroupingSize };
+ }
+
+ private string GetTimeFormatString()
+ {
+ return GetTimeFormatString(false);
+ }
+
+ [SecuritySafeCritical]
+ private string GetTimeFormatString(bool shortFormat)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetTimeFormatString(bool shortFormat)] Expected _sWindowsName to be populated already");
+
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY);
+
+ bool result = Interop.GlobalizationInterop.GetLocaleTimeFormat(_sWindowsName, shortFormat, sb, sb.Capacity);
+ if (!result)
+ {
+ // Failed, just use empty string
+ StringBuilderCache.Release(sb);
+ Contract.Assert(false, "[CultureData.GetTimeFormatString(bool shortFormat)] Failed");
+ return String.Empty;
+ }
+
+ return ConvertIcuTimeFormatString(StringBuilderCache.GetStringAndRelease(sb));
+ }
+
+ private int GetFirstDayOfWeek()
+ {
+ return this.GetLocaleInfo(LocaleNumberData.FirstDayOfWeek);
+ }
+
+ private String[] GetTimeFormats()
+ {
+ string format = GetTimeFormatString(false);
+ return new string[] { format };
+ }
+
+ private String[] GetShortTimeFormats()
+ {
+ string format = GetTimeFormatString(true);
+ return new string[] { format };
+ }
+
+ private static CultureData GetCultureDataFromRegionName(String regionName)
+ {
+ // no support to lookup by region name, other than the hard-coded list in CultureData
+ return null;
+ }
+
+ private static string GetLanguageDisplayName(string cultureName)
+ {
+ return new CultureInfo(cultureName).m_cultureData.GetLocaleInfo(cultureName, LocaleStringData.LocalizedDisplayName);
+ }
+
+ private static string GetRegionDisplayName(string isoCountryCode)
+ {
+ // use the fallback which is to return NativeName
+ return null;
+ }
+
+ private static CultureInfo GetUserDefaultCulture()
+ {
+ return CultureInfo.GetUserDefaultCulture();
+ }
+
+ private static string ConvertIcuTimeFormatString(string icuFormatString)
+ {
+ StringBuilder sb = StringBuilderCache.Acquire(ICU_ULOC_FULLNAME_CAPACITY);
+ bool amPmAdded = false;
+
+ for (int i = 0; i < icuFormatString.Length; i++)
+ {
+ switch(icuFormatString[i])
+ {
+ case ':':
+ case '.':
+ case 'H':
+ case 'h':
+ case 'm':
+ case 's':
+ sb.Append(icuFormatString[i]);
+ break;
+
+ case ' ':
+ case '\u00A0':
+ // Convert nonbreaking spaces into regular spaces
+ sb.Append(' ');
+ break;
+
+ case 'a': // AM/PM
+ if (!amPmAdded)
+ {
+ amPmAdded = true;
+ sb.Append("tt");
+ }
+ break;
+
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs
new file mode 100644
index 0000000000..9969ecbd81
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureData.Windows.cs
@@ -0,0 +1,561 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Text;
+using Internal.Runtime.Augments;
+
+namespace System.Globalization
+{
+ internal partial class CultureData
+ {
+ private const uint LOCALE_NOUSEROVERRIDE = 0x80000000;
+ private const uint LOCALE_RETURN_NUMBER = 0x20000000;
+ private const uint LOCALE_SISO3166CTRYNAME = 0x0000005A;
+
+ private const uint TIME_NOSECONDS = 0x00000002;
+
+ /// <summary>
+ /// Check with the OS to see if this is a valid culture.
+ /// If so we populate a limited number of fields. If its not valid we return false.
+ ///
+ /// The fields we populate:
+ ///
+ /// sWindowsName -- The name that windows thinks this culture is, ie:
+ /// en-US if you pass in en-US
+ /// de-DE_phoneb if you pass in de-DE_phoneb
+ /// fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine)
+ /// fj if you pass in fj (neutral, post-Windows 7 machine)
+ ///
+ /// sRealName -- The name you used to construct the culture, in pretty form
+ /// en-US if you pass in EN-us
+ /// en if you pass in en
+ /// de-DE_phoneb if you pass in de-DE_phoneb
+ ///
+ /// sSpecificCulture -- The specific culture for this culture
+ /// en-US for en-US
+ /// en-US for en
+ /// de-DE_phoneb for alt sort
+ /// fj-FJ for fj (neutral)
+ ///
+ /// sName -- The IETF name of this culture (ie: no sort info, could be neutral)
+ /// en-US if you pass in en-US
+ /// en if you pass in en
+ /// de-DE if you pass in de-DE_phoneb
+ ///
+ /// bNeutral -- TRUE if it is a neutral locale
+ ///
+ /// For a neutral we just populate the neutral name, but we leave the windows name pointing to the
+ /// windows locale that's going to provide data for us.
+ /// </summary>
+ private unsafe bool InitCultureData()
+ {
+ const int LOCALE_NAME_MAX_LENGTH = 85;
+
+ const uint LOCALE_ILANGUAGE = 0x00000001;
+ const uint LOCALE_INEUTRAL = 0x00000071;
+ const uint LOCALE_SNAME = 0x0000005c;
+
+ int result;
+ string realNameBuffer = _sRealName;
+ char* pBuffer = stackalloc char[LOCALE_NAME_MAX_LENGTH];
+
+ result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_SNAME, pBuffer, LOCALE_NAME_MAX_LENGTH);
+
+ // Did it fail?
+ if (result == 0)
+ {
+ return false;
+ }
+
+ // It worked, note that the name is the locale name, so use that (even for neutrals)
+ // We need to clean up our "real" name, which should look like the windows name right now
+ // so overwrite the input with the cleaned up name
+ _sRealName = new String(pBuffer, 0, result - 1);
+ realNameBuffer = _sRealName;
+
+ // Check for neutrality, don't expect to fail
+ // (buffer has our name in it, so we don't have to do the gc. stuff)
+
+ result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_INEUTRAL | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char));
+ if (result == 0)
+ {
+ return false;
+ }
+
+ // Remember our neutrality
+ _bNeutral = *((uint*)pBuffer) != 0;
+
+ // Note: Parents will be set dynamically
+
+ // Start by assuming the windows name'll be the same as the specific name since windows knows
+ // about specifics on all versions. Only for downlevel Neutral locales does this have to change.
+ _sWindowsName = realNameBuffer;
+
+ // Neutrals and non-neutrals are slightly different
+ if (_bNeutral)
+ {
+ // Neutral Locale
+
+ // IETF name looks like neutral name
+ _sName = realNameBuffer;
+
+ // Specific locale name is whatever ResolveLocaleName (win7+) returns.
+ // (Buffer has our name in it, and we can recycle that because windows resolves it before writing to the buffer)
+ result = Interop.mincore.ResolveLocaleName(realNameBuffer, pBuffer, LOCALE_NAME_MAX_LENGTH);
+
+ // 0 is failure, 1 is invariant (""), which we expect
+ if (result < 1)
+ {
+ return false;
+ }
+ // We found a locale name, so use it.
+ // In vista this should look like a sort name (de-DE_phoneb) or a specific culture (en-US) and be in the "pretty" form
+ _sSpecificCulture = new String(pBuffer, 0, result - 1);
+ }
+ else
+ {
+ // Specific Locale
+
+ // Specific culture's the same as the locale name since we know its not neutral
+ // On mac we'll use this as well, even for neutrals. There's no obvious specific
+ // culture to use and this isn't exposed, but behaviorally this is correct on mac.
+ // Note that specifics include the sort name (de-DE_phoneb)
+ _sSpecificCulture = realNameBuffer;
+
+ _sName = realNameBuffer;
+
+ // We need the IETF name (sname)
+ // If we aren't an alt sort locale then this is the same as the windows name.
+ // If we are an alt sort locale then this is the same as the part before the _ in the windows name
+ // This is for like de-DE_phoneb and es-ES_tradnl that hsouldn't have the _ part
+
+ result = Interop.mincore.GetLocaleInfoEx(realNameBuffer, LOCALE_ILANGUAGE | LOCALE_RETURN_NUMBER, pBuffer, sizeof(int) / sizeof(char));
+ if (result == 0)
+ {
+ return false;
+ }
+
+ _iLanguage = *((int*)pBuffer);
+
+ if (!IsCustomCultureId(_iLanguage))
+ {
+ // not custom locale
+ int index = realNameBuffer.IndexOf('_');
+ if (index > 0 && index < realNameBuffer.Length)
+ {
+ _sName = realNameBuffer.Substring(0, index);
+ }
+ }
+ }
+
+ // It succeeded.
+ return true;
+ }
+
+ private string GetLocaleInfo(LocaleStringData type)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected _sWindowsName to be populated by already");
+ return GetLocaleInfo(_sWindowsName, type);
+ }
+
+ // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
+ // "windows" name, which can be specific for downlevel (< windows 7) os's.
+ private string GetLocaleInfo(string localeName, LocaleStringData type)
+ {
+ uint lctype = (uint)type;
+
+ return GetLocaleInfoFromLCType(localeName, lctype, UseUserOverride);
+ }
+
+ private int GetLocaleInfo(LocaleNumberData type)
+ {
+ uint lctype = (uint)type;
+
+ // Fix lctype if we don't want overrides
+ if (!UseUserOverride)
+ {
+ lctype |= LOCALE_NOUSEROVERRIDE;
+ }
+
+ // Ask OS for data, note that we presume it returns success, so we have to know that
+ // sWindowsName is valid before calling.
+ Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
+ int result = Interop.mincore.GetLocaleInfoExInt(_sWindowsName, lctype);
+
+ return result;
+ }
+
+ private int[] GetLocaleInfo(LocaleGroupingData type)
+ {
+ return ConvertWin32GroupString(GetLocaleInfoFromLCType(_sWindowsName, (uint)type, UseUserOverride));
+ }
+
+ private string GetTimeFormatString()
+ {
+ const uint LOCALE_STIMEFORMAT = 0x00001003;
+
+ return ReescapeWin32String(GetLocaleInfoFromLCType(_sWindowsName, LOCALE_STIMEFORMAT, UseUserOverride));
+ }
+
+ private int GetFirstDayOfWeek()
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected _sWindowsName to be populated by already");
+
+ const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C;
+
+ int result = Interop.mincore.GetLocaleInfoExInt(_sWindowsName, LOCALE_IFIRSTDAYOFWEEK | (!UseUserOverride ? LOCALE_NOUSEROVERRIDE : 0));
+
+ // Win32 and .NET disagree on the numbering for days of the week, so we have to convert.
+ return ConvertFirstDayOfWeekMonToSun(result);
+ }
+
+ private String[] GetTimeFormats()
+ {
+ // Note that this gets overrides for us all the time
+ Contract.Assert(_sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected _sWindowsName to be populated by already");
+ String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, 0, UseUserOverride));
+
+ return result;
+ }
+
+ private String[] GetShortTimeFormats()
+ {
+ // Note that this gets overrides for us all the time
+ Contract.Assert(_sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected _sWindowsName to be populated by already");
+ String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(_sWindowsName, TIME_NOSECONDS, UseUserOverride));
+
+ return result;
+ }
+
+ // Enumerate all system cultures and then try to find out which culture has
+ // region name match the requested region name
+ private static CultureData GetCultureDataFromRegionName(String regionName)
+ {
+ Contract.Assert(regionName != null);
+
+ const uint LOCALE_SUPPLEMENTAL = 0x00000002;
+ const uint LOCALE_SPECIFICDATA = 0x00000020;
+
+ EnumLocaleData context = new EnumLocaleData();
+ context.cultureName = null;
+ context.regionName = regionName;
+
+ GCHandle contextHandle = GCHandle.Alloc(context);
+ try
+ {
+ IntPtr callback = AddrofIntrinsics.AddrOf<Func<IntPtr, uint, IntPtr, Interop.BOOL>>(EnumSystemLocalesProc);
+ Interop.mincore.EnumSystemLocalesEx(callback, LOCALE_SPECIFICDATA | LOCALE_SUPPLEMENTAL, (IntPtr)contextHandle, IntPtr.Zero);
+ }
+ finally
+ {
+ contextHandle.Free();
+ }
+
+ if (context.cultureName != null)
+ {
+ // we got a matched culture
+ return GetCultureData(context.cultureName, true);
+ }
+
+ return null;
+ }
+
+ private static string GetLanguageDisplayName(string cultureName)
+ {
+ return WinRTInterop.Callbacks.GetLanguageDisplayName(cultureName);
+ }
+
+ private static string GetRegionDisplayName(string isoCountryCode)
+ {
+ return WinRTInterop.Callbacks.GetRegionDisplayName(isoCountryCode);
+ }
+
+ private static CultureInfo GetUserDefaultCulture()
+ {
+ return (CultureInfo)WinRTInterop.Callbacks.GetUserDefaultCulture();
+ }
+
+ // PAL methods end here.
+
+ private static string GetLocaleInfoFromLCType(string localeName, uint lctype, bool useUserOveride)
+ {
+ Contract.Assert(localeName != null, "[CultureData.GetLocaleInfoFromLCType] Expected localeName to be not be null");
+
+ // Fix lctype if we don't want overrides
+ if (!useUserOveride)
+ {
+ lctype |= LOCALE_NOUSEROVERRIDE;
+ }
+
+ // Ask OS for data
+ string result = Interop.mincore.GetLocaleInfoEx(localeName, lctype);
+ if (result == null)
+ {
+ // Failed, just use empty string
+ result = String.Empty;
+ }
+
+ return result;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Reescape a Win32 style quote string as a NLS+ style quoted string
+ //
+ // This is also the escaping style used by custom culture data files
+ //
+ // NLS+ uses \ to escape the next character, whether in a quoted string or
+ // not, so we always have to change \ to \\.
+ //
+ // NLS+ uses \' to escape a quote inside a quoted string so we have to change
+ // '' to \' (if inside a quoted string)
+ //
+ // We don't build the stringbuilder unless we find something to change
+ ////////////////////////////////////////////////////////////////////////////
+ internal static String ReescapeWin32String(String str)
+ {
+ // If we don't have data, then don't try anything
+ if (str == null)
+ return null;
+
+ StringBuilder result = null;
+
+ bool inQuote = false;
+ for (int i = 0; i < str.Length; i++)
+ {
+ // Look for quote
+ if (str[i] == '\'')
+ {
+ // Already in quote?
+ if (inQuote)
+ {
+ // See another single quote. Is this '' of 'fred''s' or '''', or is it an ending quote?
+ if (i + 1 < str.Length && str[i + 1] == '\'')
+ {
+ // Found another ', so we have ''. Need to add \' instead.
+ // 1st make sure we have our stringbuilder
+ if (result == null)
+ result = new StringBuilder(str, 0, i, str.Length * 2);
+
+ // Append a \' and keep going (so we don't turn off quote mode)
+ result.Append("\\'");
+ i++;
+ continue;
+ }
+
+ // Turning off quote mode, fall through to add it
+ inQuote = false;
+ }
+ else
+ {
+ // Found beginning quote, fall through to add it
+ inQuote = true;
+ }
+ }
+ // Is there a single \ character?
+ else if (str[i] == '\\')
+ {
+ // Found a \, need to change it to \\
+ // 1st make sure we have our stringbuilder
+ if (result == null)
+ result = new StringBuilder(str, 0, i, str.Length * 2);
+
+ // Append our \\ to the string & continue
+ result.Append("\\\\");
+ continue;
+ }
+
+ // If we have a builder we need to add our character
+ if (result != null)
+ result.Append(str[i]);
+ }
+
+ // Unchanged string? , just return input string
+ if (result == null)
+ return str;
+
+ // String changed, need to use the builder
+ return result.ToString();
+ }
+
+ internal static String[] ReescapeWin32Strings(String[] array)
+ {
+ if (array != null)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = ReescapeWin32String(array[i]);
+ }
+ }
+
+ return array;
+ }
+
+ // If we get a group from windows, then its in 3;0 format with the 0 backwards
+ // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa)
+ // EXCEPT in the case where the list only contains 0 in which NLS and NLS+ have the same meaning.
+ private static int[] ConvertWin32GroupString(String win32Str)
+ {
+ // None of these cases make any sense
+ if (win32Str == null || win32Str.Length == 0)
+ {
+ return (new int[] { 3 });
+ }
+
+ if (win32Str[0] == '0')
+ {
+ return (new int[] { 0 });
+ }
+
+ // Since its in n;n;n;n;n format, we can always get the length quickly
+ int[] values;
+ if (win32Str[win32Str.Length - 1] == '0')
+ {
+ // Trailing 0 gets dropped. 1;0 -> 1
+ values = new int[(win32Str.Length / 2)];
+ }
+ else
+ {
+ // Need extra space for trailing zero 1 -> 1;0
+ values = new int[(win32Str.Length / 2) + 2];
+ values[values.Length - 1] = 0;
+ }
+
+ int i;
+ int j;
+ for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++)
+ {
+ // Note that this # shouldn't ever be zero, 'cause 0 is only at end
+ // But we'll test because its registry that could be anything
+ if (win32Str[i] < '1' || win32Str[i] > '9')
+ return new int[] { 3 };
+
+ values[j] = (int)(win32Str[i] - '0');
+ }
+
+ return (values);
+ }
+
+ private static int ConvertFirstDayOfWeekMonToSun(int iTemp)
+ {
+ // Convert Mon-Sun to Sun-Sat format
+ iTemp++;
+ if (iTemp > 6)
+ {
+ // Wrap Sunday and convert invalid data to Sunday
+ iTemp = 0;
+ }
+ return iTemp;
+ }
+
+
+ // Context for EnumCalendarInfoExEx callback.
+ private class EnumLocaleData
+ {
+ public string regionName;
+ public string cultureName;
+ }
+
+ // EnumSystemLocaleEx callback.
+ [NativeCallable(CallingConvention = CallingConvention.StdCall)]
+ private static unsafe Interop.BOOL EnumSystemLocalesProc(IntPtr lpLocaleString, uint flags, IntPtr contextHandle)
+ {
+ EnumLocaleData context = (EnumLocaleData)((GCHandle)contextHandle).Target;
+ try
+ {
+ string cultureName = new string((char*)lpLocaleString);
+ string regionName = Interop.mincore.GetLocaleInfoEx(cultureName, LOCALE_SISO3166CTRYNAME);
+ if (regionName != null && regionName.Equals(context.regionName, StringComparison.OrdinalIgnoreCase))
+ {
+ context.cultureName = cultureName;
+ return Interop.BOOL.FALSE; // we found a match, then stop the enumeration
+ }
+
+ return Interop.BOOL.TRUE;
+ }
+ catch (Exception)
+ {
+ return Interop.BOOL.FALSE;
+ }
+ }
+
+ // Context for EnumTimeFormatsEx callback.
+ private class EnumData
+ {
+ public LowLevelList<string> strings;
+ }
+
+ // EnumTimeFormatsEx callback itself.
+ [NativeCallable(CallingConvention = CallingConvention.StdCall)]
+ private static unsafe Interop.BOOL EnumTimeCallback(IntPtr lpTimeFormatString, IntPtr lParam)
+ {
+ EnumData context = (EnumData)((GCHandle)lParam).Target;
+
+ try
+ {
+ context.strings.Add(new string((char*)lpTimeFormatString));
+ return Interop.BOOL.TRUE;
+ }
+ catch (Exception)
+ {
+ return Interop.BOOL.FALSE;
+ }
+ }
+
+ private static unsafe String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride)
+ {
+ const uint LOCALE_SSHORTTIME = 0x00000079;
+ const uint LOCALE_STIMEFORMAT = 0x00001003;
+
+ EnumData data = new EnumData();
+ data.strings = new LowLevelList<string>();
+
+ GCHandle dataHandle = GCHandle.Alloc(data);
+ try
+ {
+ // Now call the enumeration API. Work is done by our callback function
+ IntPtr callback = AddrofIntrinsics.AddrOf<Func<IntPtr, IntPtr, Interop.BOOL>>(EnumTimeCallback);
+ Interop.mincore.EnumTimeFormatsEx(callback, localeName, (uint)dwFlags, (IntPtr)dataHandle);
+ }
+ finally
+ {
+ dataHandle.Free();
+ }
+
+ if (data.strings.Count > 0)
+ {
+ // Now we need to allocate our stringarray and populate it
+ string[] results = data.strings.ToArray();
+
+ if (!useUserOverride && data.strings.Count > 1)
+ {
+ // Since there is no "NoUserOverride" aware EnumTimeFormatsEx, we always get an override
+ // The override is the first entry if it is overriden.
+ // We can check if we have overrides by checking the GetLocaleInfo with no override
+ // If we do have an override, we don't know if it is a user defined override or if the
+ // user has just selected one of the predefined formats so we can't just remove it
+ // but we can move it down.
+ uint lcType = (dwFlags == TIME_NOSECONDS) ? LOCALE_SSHORTTIME : LOCALE_STIMEFORMAT;
+ string timeFormatNoUserOverride = GetLocaleInfoFromLCType(localeName, lcType, useUserOverride);
+ if (timeFormatNoUserOverride != "")
+ {
+ string firstTimeFormat = results[0];
+ if (timeFormatNoUserOverride != firstTimeFormat)
+ {
+ results[0] = results[1];
+ results[1] = firstTimeFormat;
+ }
+ }
+ }
+
+ return results;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureData.cs b/src/mscorlib/corefx/System/Globalization/CultureData.cs
new file mode 100644
index 0000000000..eb71318fdb
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureData.cs
@@ -0,0 +1,2174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+
+#if INSIDE_CLR
+ using StringStringDictionary = Dictionary<string, string>;
+ using StringCultureDataDictionary = Dictionary<String, CultureData>;
+ using Lock = Object;
+#else
+ using StringStringDictionary = LowLevelDictionary<string, string>;
+ using StringCultureDataDictionary = LowLevelDictionary<string, CultureData>;
+#endif
+
+ //
+ // List of culture data
+ // Note the we cache overrides.
+ // Note that localized names (resource names) aren't available from here.
+ //
+
+ //
+ // Our names are a tad confusing.
+ //
+ // sWindowsName -- The name that windows thinks this culture is, ie:
+ // en-US if you pass in en-US
+ // de-DE_phoneb if you pass in de-DE_phoneb
+ // fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine)
+ // fj if you pass in fj (neutral, post-Windows 7 machine)
+ //
+ // sRealName -- The name you used to construct the culture, in pretty form
+ // en-US if you pass in EN-us
+ // en if you pass in en
+ // de-DE_phoneb if you pass in de-DE_phoneb
+ //
+ // sSpecificCulture -- The specific culture for this culture
+ // en-US for en-US
+ // en-US for en
+ // de-DE_phoneb for alt sort
+ // fj-FJ for fj (neutral)
+ //
+ // sName -- The IETF name of this culture (ie: no sort info, could be neutral)
+ // en-US if you pass in en-US
+ // en if you pass in en
+ // de-DE if you pass in de-DE_phoneb
+ //
+ internal partial class CultureData
+ {
+ private const int undef = -1;
+ private const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000;
+ private const int LOCALE_CUSTOM_DEFAULT = 0x0c00;
+
+ // Override flag
+ private String _sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+ private String _sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
+
+ // Identity
+ private String _sName; // locale name (ie: en-us, NO sort info, but could be neutral)
+ private String _sParent; // Parent name (which may be a custom locale/culture)
+ private String _sLocalizedDisplayName; // Localized pretty name for this locale
+ private String _sEnglishDisplayName; // English pretty name for this locale
+ private String _sNativeDisplayName; // Native pretty name for this locale
+ private String _sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort
+
+ // Language
+ private String _sISO639Language; // ISO 639 Language Name
+ private String _sLocalizedLanguage; // Localized name for this language
+ private String _sEnglishLanguage; // English name for this language
+ private String _sNativeLanguage; // Native name of this language
+
+ // Region
+ private String _sRegionName; // (RegionInfo)
+ private String _sLocalizedCountry; // localized country name
+ private String _sEnglishCountry; // english country name (RegionInfo)
+ private String _sNativeCountry; // native country name
+ private String _sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US
+
+ // Numbers
+ private String _sPositiveSign; // (user can override) positive sign
+ private String _sNegativeSign; // (user can override) negative sign
+ private String[] _saNativeDigits; // (user can override) native characters for digits 0-9
+ // (nfi populates these 5, don't have to be = undef)
+ private int _iDigits; // (user can override) number of fractional digits
+ private int _iNegativeNumber; // (user can override) negative number format
+ private int[] _waGrouping; // (user can override) grouping of digits
+ private String _sDecimalSeparator; // (user can override) decimal separator
+ private String _sThousandSeparator; // (user can override) thousands separator
+ private String _sNaN; // Not a Number
+ private String _sPositiveInfinity; // + Infinity
+ private String _sNegativeInfinity; // - Infinity
+
+ // Percent
+ private int _iNegativePercent = undef; // Negative Percent (0-3)
+ private int _iPositivePercent = undef; // Positive Percent (0-11)
+ private String _sPercent; // Percent (%) symbol
+ private String _sPerMille; // PerMille symbol
+
+ // Currency
+ private String _sCurrency; // (user can override) local monetary symbol
+ private String _sIntlMonetarySymbol; // international monetary symbol (RegionInfo)
+ // (nfi populates these 4, don't have to be = undef)
+ private int _iCurrencyDigits; // (user can override) # local monetary fractional digits
+ private int _iCurrency; // (user can override) positive currency format
+ private int _iNegativeCurrency; // (user can override) negative currency format
+ private int[] _waMonetaryGrouping; // (user can override) monetary grouping of digits
+ private String _sMonetaryDecimal; // (user can override) monetary decimal separator
+ private String _sMonetaryThousand; // (user can override) monetary thousands separator
+
+ // Misc
+ private int _iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo)
+ private String _sListSeparator; // (user can override) list separator
+
+ // Time
+ private String _sAM1159; // (user can override) AM designator
+ private String _sPM2359; // (user can override) PM designator
+ private String _sTimeSeparator;
+ private volatile String[] _saLongTimes; // (user can override) time format
+ private volatile String[] _saShortTimes; // short time format
+ private volatile String[] _saDurationFormats; // time duration format
+
+ // Calendar specific data
+ private int _iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really)
+ private int _iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really)
+ private volatile CalendarId[] _waCalendars; // all available calendar type(s). The first one is the default calendar
+
+ // Store for specific data about each calendar
+ private CalendarData[] _calendars; // Store for specific calendar data
+
+ // Text information
+ private int _iReadingLayout = undef; // Reading layout data
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+
+ // CoreCLR depends on this even though its not exposed publicly.
+
+ private int _iLanguage; // locale ID (0409) - NO sort information
+ private bool _bUseOverrides; // use user overrides?
+ private bool _bNeutral; // Flags for the culture (ie: neutral or not right now)
+
+
+ // Region Name to Culture Name mapping table
+ // (In future would be nice to be in registry or something)
+
+ //Using a property so we avoid creating the dictionary untill we need it
+ private static StringStringDictionary RegionNames
+ {
+ get
+ {
+ if (s_RegionNames == null)
+ {
+ StringStringDictionary regionNames = new StringStringDictionary(211 /* prime */);
+
+ regionNames.Add("029", "en-029");
+ regionNames.Add("AE", "ar-AE");
+ regionNames.Add("AF", "prs-AF");
+ regionNames.Add("AL", "sq-AL");
+ regionNames.Add("AM", "hy-AM");
+ regionNames.Add("AR", "es-AR");
+ regionNames.Add("AT", "de-AT");
+ regionNames.Add("AU", "en-AU");
+ regionNames.Add("AZ", "az-Cyrl-AZ");
+ regionNames.Add("BA", "bs-Latn-BA");
+ regionNames.Add("BD", "bn-BD");
+ regionNames.Add("BE", "nl-BE");
+ regionNames.Add("BG", "bg-BG");
+ regionNames.Add("BH", "ar-BH");
+ regionNames.Add("BN", "ms-BN");
+ regionNames.Add("BO", "es-BO");
+ regionNames.Add("BR", "pt-BR");
+ regionNames.Add("BY", "be-BY");
+ regionNames.Add("BZ", "en-BZ");
+ regionNames.Add("CA", "en-CA");
+ regionNames.Add("CH", "it-CH");
+ regionNames.Add("CL", "es-CL");
+ regionNames.Add("CN", "zh-CN");
+ regionNames.Add("CO", "es-CO");
+ regionNames.Add("CR", "es-CR");
+ regionNames.Add("CS", "sr-Cyrl-CS");
+ regionNames.Add("CZ", "cs-CZ");
+ regionNames.Add("DE", "de-DE");
+ regionNames.Add("DK", "da-DK");
+ regionNames.Add("DO", "es-DO");
+ regionNames.Add("DZ", "ar-DZ");
+ regionNames.Add("EC", "es-EC");
+ regionNames.Add("EE", "et-EE");
+ regionNames.Add("EG", "ar-EG");
+ regionNames.Add("ES", "es-ES");
+ regionNames.Add("ET", "am-ET");
+ regionNames.Add("FI", "fi-FI");
+ regionNames.Add("FO", "fo-FO");
+ regionNames.Add("FR", "fr-FR");
+ regionNames.Add("GB", "en-GB");
+ regionNames.Add("GE", "ka-GE");
+ regionNames.Add("GL", "kl-GL");
+ regionNames.Add("GR", "el-GR");
+ regionNames.Add("GT", "es-GT");
+ regionNames.Add("HK", "zh-HK");
+ regionNames.Add("HN", "es-HN");
+ regionNames.Add("HR", "hr-HR");
+ regionNames.Add("HU", "hu-HU");
+ regionNames.Add("ID", "id-ID");
+ regionNames.Add("IE", "en-IE");
+ regionNames.Add("IL", "he-IL");
+ regionNames.Add("IN", "hi-IN");
+ regionNames.Add("IQ", "ar-IQ");
+ regionNames.Add("IR", "fa-IR");
+ regionNames.Add("IS", "is-IS");
+ regionNames.Add("IT", "it-IT");
+ regionNames.Add("IV", "");
+ regionNames.Add("JM", "en-JM");
+ regionNames.Add("JO", "ar-JO");
+ regionNames.Add("JP", "ja-JP");
+ regionNames.Add("KE", "sw-KE");
+ regionNames.Add("KG", "ky-KG");
+ regionNames.Add("KH", "km-KH");
+ regionNames.Add("KR", "ko-KR");
+ regionNames.Add("KW", "ar-KW");
+ regionNames.Add("KZ", "kk-KZ");
+ regionNames.Add("LA", "lo-LA");
+ regionNames.Add("LB", "ar-LB");
+ regionNames.Add("LI", "de-LI");
+ regionNames.Add("LK", "si-LK");
+ regionNames.Add("LT", "lt-LT");
+ regionNames.Add("LU", "lb-LU");
+ regionNames.Add("LV", "lv-LV");
+ regionNames.Add("LY", "ar-LY");
+ regionNames.Add("MA", "ar-MA");
+ regionNames.Add("MC", "fr-MC");
+ regionNames.Add("ME", "sr-Latn-ME");
+ regionNames.Add("MK", "mk-MK");
+ regionNames.Add("MN", "mn-MN");
+ regionNames.Add("MO", "zh-MO");
+ regionNames.Add("MT", "mt-MT");
+ regionNames.Add("MV", "dv-MV");
+ regionNames.Add("MX", "es-MX");
+ regionNames.Add("MY", "ms-MY");
+ regionNames.Add("NG", "ig-NG");
+ regionNames.Add("NI", "es-NI");
+ regionNames.Add("NL", "nl-NL");
+ regionNames.Add("NO", "nn-NO");
+ regionNames.Add("NP", "ne-NP");
+ regionNames.Add("NZ", "en-NZ");
+ regionNames.Add("OM", "ar-OM");
+ regionNames.Add("PA", "es-PA");
+ regionNames.Add("PE", "es-PE");
+ regionNames.Add("PH", "en-PH");
+ regionNames.Add("PK", "ur-PK");
+ regionNames.Add("PL", "pl-PL");
+ regionNames.Add("PR", "es-PR");
+ regionNames.Add("PT", "pt-PT");
+ regionNames.Add("PY", "es-PY");
+ regionNames.Add("QA", "ar-QA");
+ regionNames.Add("RO", "ro-RO");
+ regionNames.Add("RS", "sr-Latn-RS");
+ regionNames.Add("RU", "ru-RU");
+ regionNames.Add("RW", "rw-RW");
+ regionNames.Add("SA", "ar-SA");
+ regionNames.Add("SE", "sv-SE");
+ regionNames.Add("SG", "zh-SG");
+ regionNames.Add("SI", "sl-SI");
+ regionNames.Add("SK", "sk-SK");
+ regionNames.Add("SN", "wo-SN");
+ regionNames.Add("SV", "es-SV");
+ regionNames.Add("SY", "ar-SY");
+ regionNames.Add("TH", "th-TH");
+ regionNames.Add("TJ", "tg-Cyrl-TJ");
+ regionNames.Add("TM", "tk-TM");
+ regionNames.Add("TN", "ar-TN");
+ regionNames.Add("TR", "tr-TR");
+ regionNames.Add("TT", "en-TT");
+ regionNames.Add("TW", "zh-TW");
+ regionNames.Add("UA", "uk-UA");
+ regionNames.Add("US", "en-US");
+ regionNames.Add("UY", "es-UY");
+ regionNames.Add("UZ", "uz-Cyrl-UZ");
+ regionNames.Add("VE", "es-VE");
+ regionNames.Add("VN", "vi-VN");
+ regionNames.Add("YE", "ar-YE");
+ regionNames.Add("ZA", "af-ZA");
+ regionNames.Add("ZW", "en-ZW");
+
+ s_RegionNames = regionNames;
+ }
+
+ return s_RegionNames;
+ }
+ }
+
+ // Cache of regions we've already looked up
+ private static volatile StringCultureDataDictionary s_cachedRegions;
+ private static volatile StringStringDictionary s_RegionNames;
+
+ internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride)
+ {
+ // First do a shortcut for Invariant
+ if (String.IsNullOrEmpty(cultureName))
+ {
+ return CultureData.Invariant;
+ }
+
+ //
+ // First check if GetCultureData() can find it (ie: its a real culture)
+ //
+ CultureData retVal = GetCultureData(cultureName, useUserOverride);
+ if (retVal != null && (retVal.IsNeutralCulture == false)) return retVal;
+
+ //
+ // Not a specific culture, perhaps it's region-only name
+ // (Remember this isn't a core clr path where that's not supported)
+ //
+
+ // If it was neutral remember that so that RegionInfo() can throw the right exception
+ CultureData neutral = retVal;
+
+ // Try the hash table next
+ String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
+ StringCultureDataDictionary tempHashTable = s_cachedRegions;
+ if (tempHashTable == null)
+ {
+ // No table yet, make a new one
+ tempHashTable = new StringCultureDataDictionary();
+ }
+ else
+ {
+ // Check the hash table
+ lock (s_lock)
+ {
+ tempHashTable.TryGetValue(hashName, out retVal);
+ }
+ if (retVal != null)
+ {
+ return retVal;
+ }
+ }
+
+ //
+ // Not found in the hash table, look it up the hard way
+ //
+
+ // If not a valid mapping from the registry we'll have to try the hard coded table
+ if (retVal == null || (retVal.IsNeutralCulture == true))
+ {
+ // Not a valid mapping, try the hard coded table
+ string name;
+ if (RegionNames.TryGetValue(cultureName, out name))
+ {
+ // Make sure we can get culture data for it
+ retVal = GetCultureData(name, useUserOverride);
+ }
+ }
+
+ // If not found in the hard coded table we'll have to find a culture that works for us
+ if (retVal == null || (retVal.IsNeutralCulture == true))
+ {
+ retVal = GetCultureDataFromRegionName(cultureName);
+ }
+
+ // If we found one we can use, then cache it for next time
+ if (retVal != null && (retVal.IsNeutralCulture == false))
+ {
+ // first add it to the cache
+ lock (s_lock)
+ {
+ tempHashTable[hashName] = retVal;
+ }
+
+ // Copy the hashtable to the corresponding member variables. This will potentially overwrite
+ // new tables simultaneously created by a new thread, but maximizes thread safety.
+ s_cachedRegions = tempHashTable;
+ }
+ else
+ {
+ // Unable to find a matching culture/region, return null or neutral
+ // (regionInfo throws a more specific exception on neutrals)
+ retVal = neutral;
+ }
+
+ // Return the found culture to use, null, or the neutral culture.
+ return retVal;
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////
+ // Build our invariant information
+ //
+ // We need an invariant instance, which we build hard-coded
+ /////////////////////////////////////////////////////////////////////////
+ internal static CultureData Invariant
+ {
+ get
+ {
+ if (s_Invariant == null)
+ {
+ // Make a new culturedata
+ CultureData invariant = new CultureData();
+
+ // Basics
+ // Note that we override the resources since this IS NOT supposed to change (by definition)
+ invariant._bUseOverrides = false;
+ invariant._sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+ invariant._sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
+
+ // Identity
+ invariant._sName = ""; // locale name (ie: en-us)
+ invariant._sParent = ""; // Parent name (which may be a custom locale/culture)
+ invariant._bNeutral = false; // Flags for the culture (ie: neutral or not right now)
+ invariant._sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale
+ invariant._sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale
+ invariant._sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture()
+
+ // Language
+ invariant._sISO639Language = "iv"; // ISO 639 Language Name
+ invariant._sLocalizedLanguage = "Invariant Language"; // Display name for this Language
+ invariant._sEnglishLanguage = "Invariant Language"; // English name for this language
+ invariant._sNativeLanguage = "Invariant Language"; // Native name of this language
+
+ // Region
+ invariant._sRegionName = "IV"; // (RegionInfo)
+ invariant._sEnglishCountry = "Invariant Country"; // english country name (RegionInfo)
+ invariant._sNativeCountry = "Invariant Country"; // native country name (Windows Only)
+ invariant._sISO3166CountryName = "IV"; // (RegionInfo), ie: US
+
+ // Numbers
+ invariant._sPositiveSign = "+"; // positive sign
+ invariant._sNegativeSign = "-"; // negative sign
+ invariant._saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9
+ invariant._iDigits = 2; // number of fractional digits
+ invariant._iNegativeNumber = 1; // negative number format
+ invariant._waGrouping = new int[] { 3 }; // grouping of digits
+ invariant._sDecimalSeparator = "."; // decimal separator
+ invariant._sThousandSeparator = ","; // thousands separator
+ invariant._sNaN = "NaN"; // Not a Number
+ invariant._sPositiveInfinity = "Infinity"; // + Infinity
+ invariant._sNegativeInfinity = "-Infinity"; // - Infinity
+
+ // Percent
+ invariant._iNegativePercent = 0; // Negative Percent (0-3)
+ invariant._iPositivePercent = 0; // Positive Percent (0-11)
+ invariant._sPercent = "%"; // Percent (%) symbol
+ invariant._sPerMille = "\x2030"; // PerMille symbol
+
+ // Currency
+ invariant._sCurrency = "\x00a4"; // local monetary symbol: for international monetary symbol
+ invariant._sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo)
+ invariant._iCurrencyDigits = 2; // # local monetary fractional digits
+ invariant._iCurrency = 0; // positive currency format
+ invariant._iNegativeCurrency = 0; // negative currency format
+ invariant._waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits
+ invariant._sMonetaryDecimal = "."; // monetary decimal separator
+ invariant._sMonetaryThousand = ","; // monetary thousands separator
+
+ // Misc
+ invariant._iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo)
+ invariant._sListSeparator = ","; // list separator
+
+ // Time
+ invariant._sAM1159 = "AM"; // AM designator
+ invariant._sPM2359 = "PM"; // PM designator
+ invariant._saLongTimes = new String[] { "HH:mm:ss" }; // time format
+ invariant._saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format
+ invariant._saDurationFormats = new String[] { "HH:mm:ss" }; // time duration format
+
+
+ // Calendar specific data
+ invariant._iFirstDayOfWeek = 0; // first day of week
+ invariant._iFirstWeekOfYear = 0; // first week of year
+ invariant._waCalendars = new CalendarId[] { CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar
+
+ // Store for specific data about each calendar
+ invariant._calendars = new CalendarData[CalendarData.MAX_CALENDARS];
+ invariant._calendars[0] = CalendarData.Invariant;
+
+ // Text information
+ invariant._iReadingLayout = 0;
+
+ // These are desktop only, not coreclr
+
+ invariant._iLanguage = 0x007f; // locale ID (0409) - NO sort information
+ // Remember it
+ s_Invariant = invariant;
+ }
+ return s_Invariant;
+ }
+ }
+ private volatile static CultureData s_Invariant;
+
+ ///////////////
+ // Constructors //
+ ///////////////
+ // Cache of cultures we've already looked up
+ private static volatile StringCultureDataDictionary s_cachedCultures;
+ private static readonly Lock s_lock = new Lock();
+
+ internal static CultureData GetCultureData(String cultureName, bool useUserOverride)
+ {
+ // First do a shortcut for Invariant
+ if (String.IsNullOrEmpty(cultureName))
+ {
+ return CultureData.Invariant;
+ }
+
+ // Try the hash table first
+ String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
+ StringCultureDataDictionary tempHashTable = s_cachedCultures;
+ if (tempHashTable == null)
+ {
+ // No table yet, make a new one
+ tempHashTable = new StringCultureDataDictionary();
+ }
+ else
+ {
+ // Check the hash table
+ bool ret;
+ CultureData retVal;
+ lock (s_lock)
+ {
+ ret = tempHashTable.TryGetValue(hashName, out retVal);
+ }
+ if (ret && retVal != null)
+ {
+ return retVal;
+ }
+ }
+
+ // Not found in the hash table, need to see if we can build one that works for us
+ CultureData culture = CreateCultureData(cultureName, useUserOverride);
+ if (culture == null)
+ {
+ return null;
+ }
+
+ // Found one, add it to the cache
+ lock (s_lock)
+ {
+ tempHashTable[hashName] = culture;
+ }
+
+ // Copy the hashtable to the corresponding member variables. This will potentially overwrite
+ // new tables simultaneously created by a new thread, but maximizes thread safety.
+ s_cachedCultures = tempHashTable;
+
+ return culture;
+ }
+
+ private static CultureData CreateCultureData(string cultureName, bool useUserOverride)
+ {
+ CultureData culture = new CultureData();
+ culture._bUseOverrides = useUserOverride;
+ culture._sRealName = cultureName;
+
+ // Ask native code if that one's real
+ if (culture.InitCultureData() == false)
+ {
+ if (culture.InitCompatibilityCultureData() == false)
+ {
+ return null;
+ }
+ }
+
+ return culture;
+ }
+
+ private bool InitCompatibilityCultureData()
+ {
+ // for compatibility handle the deprecated ids: zh-chs, zh-cht
+ string cultureName = _sRealName;
+
+ string fallbackCultureName;
+ string realCultureName;
+ switch (AnsiToLower(cultureName))
+ {
+ case "zh-chs":
+ fallbackCultureName = "zh-Hans";
+ realCultureName = "zh-CHS";
+ break;
+ case "zh-cht":
+ fallbackCultureName = "zh-Hant";
+ realCultureName = "zh-CHT";
+ break;
+ default:
+ return false;
+ }
+
+ _sRealName = fallbackCultureName;
+ if (InitCultureData() == false)
+ {
+ return false;
+ }
+ // fixup our data
+ _sName = realCultureName; // the name that goes back to the user
+ _sParent = fallbackCultureName;
+
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // All the accessors
+ //
+ // Accessors for our data object items
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ ///////////
+ // Identity //
+ ///////////
+
+ // The real name used to construct the locale (ie: de-DE_phoneb)
+ internal String CultureName
+ {
+ get
+ {
+ Contract.Assert(_sRealName != null, "[CultureData.CultureName] Expected _sRealName to be populated by already");
+ // since windows doesn't know about zh-CHS and zh-CHT,
+ // we leave sRealName == zh-Hanx but we still need to
+ // pretend that it was zh-CHX.
+ switch (_sName)
+ {
+ case "zh-CHS":
+ case "zh-CHT":
+ return _sName;
+ }
+ return _sRealName;
+ }
+ }
+
+ // Are overrides enabled?
+ internal bool UseUserOverride
+ {
+ get
+ {
+ return _bUseOverrides;
+ }
+ }
+
+ // locale name (ie: de-DE, NO sort information)
+ internal String SNAME
+ {
+ get
+ {
+ if (_sName == null)
+ {
+ _sName = String.Empty;
+ }
+ return _sName;
+ }
+ }
+
+ // Parent name (which may be a custom locale/culture)
+ internal String SPARENT
+ {
+ get
+ {
+ if (_sParent == null)
+ {
+ // Ask using the real name, so that we get parents of neutrals
+ _sParent = GetLocaleInfo(_sRealName, LocaleStringData.ParentName);
+ }
+ return _sParent;
+ }
+ }
+
+ // Localized pretty name for this locale (ie: Inglis (estados Unitos))
+ internal String SLOCALIZEDDISPLAYNAME
+ {
+ get
+ {
+ if (_sLocalizedDisplayName == null)
+ {
+ if (this.IsSupplementalCustomCulture)
+ {
+ if (this.IsNeutralCulture)
+ {
+ _sLocalizedDisplayName = this.SNATIVELANGUAGE;
+ }
+ else
+ {
+ _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME;
+ }
+ }
+ else
+ {
+ try
+ {
+ const string ZH_CHT = "zh-CHT";
+ const string ZH_CHS = "zh-CHS";
+
+ if (SNAME.Equals(ZH_CHT, StringComparison.OrdinalIgnoreCase))
+ {
+ _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hant");
+ }
+ else if (SNAME.Equals(ZH_CHS, StringComparison.OrdinalIgnoreCase))
+ {
+ _sLocalizedDisplayName = GetLanguageDisplayName("zh-Hans");
+ }
+ else
+ {
+ _sLocalizedDisplayName = GetLanguageDisplayName(SNAME);
+ }
+ }
+ catch (Exception)
+ {
+ // do nothing
+ }
+ }
+ // If it hasn't been found (Windows 8 and up), fallback to the system
+ if (String.IsNullOrEmpty(_sLocalizedDisplayName))
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ _sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE;
+ }
+ else
+ {
+ // Usually the UI culture shouldn't be different than what we got from WinRT except
+ // if DefaultThreadCurrentUICulture was set
+ CultureInfo ci;
+
+ if (CultureInfo.DefaultThreadCurrentUICulture != null &&
+ ((ci = GetUserDefaultCulture()) != null) &&
+ !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name))
+ {
+ _sLocalizedDisplayName = this.SNATIVEDISPLAYNAME;
+ }
+ else
+ {
+ _sLocalizedDisplayName = GetLocaleInfo(LocaleStringData.LocalizedDisplayName);
+ }
+ }
+ }
+ }
+
+ return _sLocalizedDisplayName;
+ }
+ }
+
+ // English pretty name for this locale (ie: English (United States))
+ internal String SENGDISPLAYNAME
+ {
+ get
+ {
+ if (_sEnglishDisplayName == null)
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ _sEnglishDisplayName = this.SENGLISHLANGUAGE;
+ // differentiate the legacy display names
+ switch (_sName)
+ {
+ case "zh-CHS":
+ case "zh-CHT":
+ _sEnglishDisplayName += " Legacy";
+ break;
+ }
+ }
+ else
+ {
+ _sEnglishDisplayName = GetLocaleInfo(LocaleStringData.EnglishDisplayName);
+
+ // if it isn't found build one:
+ if (String.IsNullOrEmpty(_sEnglishDisplayName))
+ {
+ // Our existing names mostly look like:
+ // "English" + "United States" -> "English (United States)"
+ // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
+ if (this.SENGLISHLANGUAGE[this.SENGLISHLANGUAGE.Length - 1] == ')')
+ {
+ // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
+ _sEnglishDisplayName =
+ this.SENGLISHLANGUAGE.Substring(0, _sEnglishLanguage.Length - 1) +
+ ", " + this.SENGCOUNTRY + ")";
+ }
+ else
+ {
+ // "English" + "United States" -> "English (United States)"
+ _sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")";
+ }
+ }
+ }
+ }
+ return _sEnglishDisplayName;
+ }
+ }
+
+ // Native pretty name for this locale (ie: Deutsch (Deutschland))
+ internal String SNATIVEDISPLAYNAME
+ {
+ get
+ {
+ if (_sNativeDisplayName == null)
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ _sNativeDisplayName = this.SNATIVELANGUAGE;
+ // differentiate the legacy display names
+ switch (_sName)
+ {
+ case "zh-CHS":
+ _sNativeDisplayName += " \u65E7\u7248";
+ break;
+ case "zh-CHT":
+ _sNativeDisplayName += " \u820A\u7248";
+ break;
+ }
+ }
+ else
+ {
+ _sNativeDisplayName = GetLocaleInfo(LocaleStringData.NativeDisplayName);
+
+ // if it isn't found build one:
+ if (String.IsNullOrEmpty(_sNativeDisplayName))
+ {
+ // These should primarily be "Deutsch (Deutschland)" type names
+ _sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")";
+ }
+ }
+ }
+ return _sNativeDisplayName;
+ }
+ }
+
+ /////////////
+ // Language //
+ /////////////
+
+ // iso 639 language name, ie: en
+ internal String SISO639LANGNAME
+ {
+ get
+ {
+ if (_sISO639Language == null)
+ {
+ _sISO639Language = GetLocaleInfo(LocaleStringData.Iso639LanguageName);
+ }
+ return _sISO639Language;
+ }
+ }
+
+ // Localized name for this language (Windows Only) ie: Inglis
+ // This is only valid for Windows 8 and higher neutrals:
+ internal String SLOCALIZEDLANGUAGE
+ {
+ get
+ {
+ if (_sLocalizedLanguage == null)
+ {
+ // Usually the UI culture shouldn't be different than what we got from WinRT except
+ // if DefaultThreadCurrentUICulture was set
+ CultureInfo ci;
+
+ if (CultureInfo.DefaultThreadCurrentUICulture != null &&
+ ((ci = GetUserDefaultCulture()) != null) &&
+ !CultureInfo.DefaultThreadCurrentUICulture.Name.Equals(ci.Name))
+ {
+ _sLocalizedLanguage = SNATIVELANGUAGE;
+ }
+ else
+ {
+ _sLocalizedLanguage = GetLocaleInfo(LocaleStringData.LocalizedLanguageName);
+ }
+ }
+
+ return _sLocalizedLanguage;
+ }
+ }
+
+ // English name for this language (Windows Only) ie: German
+ internal String SENGLISHLANGUAGE
+ {
+ get
+ {
+ if (_sEnglishLanguage == null)
+ {
+ _sEnglishLanguage = GetLocaleInfo(LocaleStringData.EnglishLanguageName);
+ }
+ return _sEnglishLanguage;
+ }
+ }
+
+ // Native name of this language (Windows Only) ie: Deutsch
+ internal String SNATIVELANGUAGE
+ {
+ get
+ {
+ if (_sNativeLanguage == null)
+ {
+ _sNativeLanguage = GetLocaleInfo(LocaleStringData.NativeLanguageName);
+ }
+ return _sNativeLanguage;
+ }
+ }
+
+ ///////////
+ // Region //
+ ///////////
+
+ // region name (eg US)
+ internal String SREGIONNAME
+ {
+ get
+ {
+ if (_sRegionName == null)
+ {
+ _sRegionName = GetLocaleInfo(LocaleStringData.Iso3166CountryName);
+ }
+ return _sRegionName;
+ }
+ }
+
+
+ // localized name for the country
+ internal string SLOCALIZEDCOUNTRY
+ {
+ get
+ {
+ if (_sLocalizedCountry == null)
+ {
+ try
+ {
+ _sLocalizedCountry = GetRegionDisplayName(SISO3166CTRYNAME);
+ }
+ catch (Exception)
+ {
+ // do nothing. we'll fallback
+ }
+
+ if (_sLocalizedCountry == null)
+ {
+ _sLocalizedCountry = SNATIVECOUNTRY;
+ }
+ }
+ return _sLocalizedCountry;
+ }
+ }
+
+ // english country name (RegionInfo) ie: Germany
+ internal String SENGCOUNTRY
+ {
+ get
+ {
+ if (_sEnglishCountry == null)
+ {
+ _sEnglishCountry = GetLocaleInfo(LocaleStringData.EnglishCountryName);
+ }
+ return _sEnglishCountry;
+ }
+ }
+
+ // native country name (RegionInfo) ie: Deutschland
+ internal String SNATIVECOUNTRY
+ {
+ get
+ {
+ if (_sNativeCountry == null)
+ {
+ _sNativeCountry = GetLocaleInfo(LocaleStringData.NativeCountryName);
+ }
+ return _sNativeCountry;
+ }
+ }
+
+ // ISO 3166 Country Name
+ internal String SISO3166CTRYNAME
+ {
+ get
+ {
+ if (_sISO3166CountryName == null)
+ {
+ _sISO3166CountryName = GetLocaleInfo(LocaleStringData.Iso3166CountryName);
+ }
+ return _sISO3166CountryName;
+ }
+ }
+
+ /////////////
+ // Numbers //
+ ////////////
+
+ // internal String sPositiveSign ; // (user can override) positive sign
+ // internal String sNegativeSign ; // (user can override) negative sign
+ // internal String[] saNativeDigits ; // (user can override) native characters for digits 0-9
+ // internal int iDigits ; // (user can override) number of fractional digits
+ // internal int iNegativeNumber ; // (user can override) negative number format
+
+
+
+ // (user can override) grouping of digits
+ internal int[] WAGROUPING
+ {
+ get
+ {
+ if (_waGrouping == null)
+ {
+ _waGrouping = GetLocaleInfo(LocaleGroupingData.Digit);
+ }
+ return _waGrouping;
+ }
+ }
+
+
+ // internal String sDecimalSeparator ; // (user can override) decimal separator
+ // internal String sThousandSeparator ; // (user can override) thousands separator
+
+ // Not a Number
+ internal String SNAN
+ {
+ get
+ {
+ if (_sNaN == null)
+ {
+ _sNaN = GetLocaleInfo(LocaleStringData.NaNSymbol);
+ }
+ return _sNaN;
+ }
+ }
+
+ // + Infinity
+ internal String SPOSINFINITY
+ {
+ get
+ {
+ if (_sPositiveInfinity == null)
+ {
+ _sPositiveInfinity = GetLocaleInfo(LocaleStringData.PositiveInfinitySymbol);
+ }
+ return _sPositiveInfinity;
+ }
+ }
+
+ // - Infinity
+ internal String SNEGINFINITY
+ {
+ get
+ {
+ if (_sNegativeInfinity == null)
+ {
+ _sNegativeInfinity = GetLocaleInfo(LocaleStringData.NegativeInfinitySymbol);
+ }
+ return _sNegativeInfinity;
+ }
+ }
+
+
+ ////////////
+ // Percent //
+ ///////////
+
+ // Negative Percent (0-3)
+ internal int INEGATIVEPERCENT
+ {
+ get
+ {
+ if (_iNegativePercent == undef)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ _iNegativePercent = GetLocaleInfo(LocaleNumberData.NegativePercentFormat);
+ }
+ return _iNegativePercent;
+ }
+ }
+
+ // Positive Percent (0-11)
+ internal int IPOSITIVEPERCENT
+ {
+ get
+ {
+ if (_iPositivePercent == undef)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ _iPositivePercent = GetLocaleInfo(LocaleNumberData.PositivePercentFormat);
+ }
+ return _iPositivePercent;
+ }
+ }
+
+ // Percent (%) symbol
+ internal String SPERCENT
+ {
+ get
+ {
+ if (_sPercent == null)
+ {
+ _sPercent = GetLocaleInfo(LocaleStringData.PercentSymbol);
+ }
+ return _sPercent;
+ }
+ }
+
+ // PerMille symbol
+ internal String SPERMILLE
+ {
+ get
+ {
+ if (_sPerMille == null)
+ {
+ _sPerMille = GetLocaleInfo(LocaleStringData.PerMilleSymbol);
+ }
+ return _sPerMille;
+ }
+ }
+
+ /////////////
+ // Currency //
+ /////////////
+
+ // (user can override) local monetary symbol, eg: $
+ internal String SCURRENCY
+ {
+ get
+ {
+ if (_sCurrency == null)
+ {
+ _sCurrency = GetLocaleInfo(LocaleStringData.MonetarySymbol);
+ }
+ return _sCurrency;
+ }
+ }
+
+ // international monetary symbol (RegionInfo), eg: USD
+ internal String SINTLSYMBOL
+ {
+ get
+ {
+ if (_sIntlMonetarySymbol == null)
+ {
+ _sIntlMonetarySymbol = GetLocaleInfo(LocaleStringData.Iso4217MonetarySymbol);
+ }
+ return _sIntlMonetarySymbol;
+ }
+ }
+
+ // internal int iCurrencyDigits ; // (user can override) # local monetary fractional digits
+ // internal int iCurrency ; // (user can override) positive currency format
+ // internal int iNegativeCurrency ; // (user can override) negative currency format
+
+ // (user can override) monetary grouping of digits
+ internal int[] WAMONGROUPING
+ {
+ get
+ {
+ if (_waMonetaryGrouping == null)
+ {
+ _waMonetaryGrouping = GetLocaleInfo(LocaleGroupingData.Monetary);
+ }
+ return _waMonetaryGrouping;
+ }
+ }
+
+ // (user can override) system of measurement 0=metric, 1=US (RegionInfo)
+ internal int IMEASURE
+ {
+ get
+ {
+ if (_iMeasure == undef)
+ {
+ _iMeasure = GetLocaleInfo(LocaleNumberData.MeasurementSystem);
+ }
+ return _iMeasure;
+ }
+ }
+
+ // (user can override) list Separator
+ internal String SLIST
+ {
+ get
+ {
+ if (_sListSeparator == null)
+ {
+ _sListSeparator = GetLocaleInfo(LocaleStringData.ListSeparator);
+ }
+ return _sListSeparator;
+ }
+ }
+
+
+ ////////////////////////////
+ // Calendar/Time (Gregorian) //
+ ////////////////////////////
+
+ // (user can override) AM designator
+ internal String SAM1159
+ {
+ get
+ {
+ if (_sAM1159 == null)
+ {
+ _sAM1159 = GetLocaleInfo(LocaleStringData.AMDesignator);
+ }
+ return _sAM1159;
+ }
+ }
+
+ // (user can override) PM designator
+ internal String SPM2359
+ {
+ get
+ {
+ if (_sPM2359 == null)
+ {
+ _sPM2359 = GetLocaleInfo(LocaleStringData.PMDesignator);
+ }
+ return _sPM2359;
+ }
+ }
+
+ // (user can override) time format
+ internal String[] LongTimes
+ {
+ get
+ {
+ if (_saLongTimes == null)
+ {
+ String[] longTimes = GetTimeFormats();
+ if (longTimes == null || longTimes.Length == 0)
+ {
+ _saLongTimes = Invariant._saLongTimes;
+ }
+ else
+ {
+ _saLongTimes = longTimes;
+ }
+ }
+ return _saLongTimes;
+ }
+ }
+
+ // short time format
+ // Short times (derived from long times format)
+ // TODO: NLS Arrowhead - On Windows 7 we should have short times so this isn't necessary
+ internal String[] ShortTimes
+ {
+ get
+ {
+ if (_saShortTimes == null)
+ {
+ // Try to get the short times from the OS/culture.dll
+ String[] shortTimes = null;
+ shortTimes = GetShortTimeFormats();
+
+ if (shortTimes == null || shortTimes.Length == 0)
+ {
+ //
+ // If we couldn't find short times, then compute them from long times
+ // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll)
+ //
+ shortTimes = DeriveShortTimesFromLong();
+ }
+
+ /* The above logic doesn't make sense on Mac, since the OS can provide us a "short time pattern".
+ * currently this is the 4th element in the array returned by LongTimes. We'll add this to our array
+ * if it doesn't exist.
+ */
+ shortTimes = AdjustShortTimesForMac(shortTimes);
+
+ // Found short times, use them
+ _saShortTimes = shortTimes;
+ }
+ return _saShortTimes;
+ }
+ }
+
+ private string[] AdjustShortTimesForMac(string[] shortTimes)
+ {
+ return shortTimes;
+ }
+
+ private string[] DeriveShortTimesFromLong()
+ {
+ // Our logic is to look for h,H,m,s,t. If we find an s, then we check the string
+ // between it and the previous marker, if any. If its a short, unescaped separator,
+ // then we don't retain that part.
+ // We then check after the ss and remove anything before the next h,H,m,t...
+ string[] shortTimes = new string[LongTimes.Length];
+
+ for (int i = 0; i < LongTimes.Length; i++)
+ {
+ shortTimes[i] = StripSecondsFromPattern(LongTimes[i]);
+ }
+ return shortTimes;
+ }
+
+ private static string StripSecondsFromPattern(string time)
+ {
+ bool bEscape = false;
+ int iLastToken = -1;
+
+ // Find the seconds
+ for (int j = 0; j < time.Length; j++)
+ {
+ // Change escape mode?
+ if (time[j] == '\'')
+ {
+ // Continue
+ bEscape = !bEscape;
+ continue;
+ }
+
+ // See if there was a single \
+ if (time[j] == '\\')
+ {
+ // Skip next char
+ j++;
+ continue;
+ }
+
+ if (bEscape)
+ {
+ continue;
+ }
+
+ switch (time[j])
+ {
+ // Check for seconds
+ case 's':
+ // Found seconds, see if there was something unescaped and short between
+ // the last marker and the seconds. Windows says separator can be a
+ // maximum of three characters (without null)
+ // If 1st or last characters were ', then ignore it
+ if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 &&
+ (time[iLastToken + 1] != '\'') &&
+ (time[j - 1] != '\''))
+ {
+ // There was something there we want to remember
+ if (iLastToken >= 0)
+ {
+ j = iLastToken + 1;
+ }
+ }
+
+ bool containsSpace;
+ int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace);
+
+ string sep;
+
+ if (containsSpace)
+ {
+ sep = " ";
+ }
+ else
+ {
+ sep = "";
+ }
+
+ time = time.Substring(0, j) + sep + time.Substring(endIndex);
+ break;
+ case 'm':
+ case 'H':
+ case 'h':
+ iLastToken = j;
+ break;
+ }
+ }
+ return time;
+ }
+
+ private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace)
+ {
+ bool bEscape = false;
+ containsSpace = false;
+ for (; index < time.Length; index++)
+ {
+ switch (time[index])
+ {
+ case '\'':
+ bEscape = !bEscape;
+ continue;
+ case '\\':
+ index++;
+ if (time[index] == ' ')
+ {
+ containsSpace = true;
+ }
+ continue;
+ case ' ':
+ containsSpace = true;
+ break;
+ case 't':
+ case 'm':
+ case 'H':
+ case 'h':
+ if (bEscape)
+ {
+ continue;
+ }
+ return index;
+ }
+ }
+ containsSpace = false;
+ return index;
+ }
+
+ // (user can override) first day of week
+ internal int IFIRSTDAYOFWEEK
+ {
+ get
+ {
+ if (_iFirstDayOfWeek == undef)
+ {
+ _iFirstDayOfWeek = GetFirstDayOfWeek();
+ }
+ return _iFirstDayOfWeek;
+ }
+ }
+
+ // (user can override) first week of year
+ internal int IFIRSTWEEKOFYEAR
+ {
+ get
+ {
+ if (_iFirstWeekOfYear == undef)
+ {
+ _iFirstWeekOfYear = GetLocaleInfo(LocaleNumberData.FirstWeekOfYear);
+ }
+ return _iFirstWeekOfYear;
+ }
+ }
+
+ // (user can override default only) short date format
+ internal String[] ShortDates(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saShortDates;
+ }
+
+ // (user can override default only) long date format
+ internal String[] LongDates(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saLongDates;
+ }
+
+ // (user can override) date year/month format.
+ internal String[] YearMonths(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saYearMonths;
+ }
+
+ // day names
+ internal string[] DayNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saDayNames;
+ }
+
+ // abbreviated day names
+ internal string[] AbbreviatedDayNames(CalendarId calendarId)
+ {
+ // Get abbreviated day names for this calendar from the OS if necessary
+ return GetCalendar(calendarId).saAbbrevDayNames;
+ }
+
+ // The super short day names
+ internal string[] SuperShortDayNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saSuperShortDayNames;
+ }
+
+ // month names
+ internal string[] MonthNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saMonthNames;
+ }
+
+ // Genitive month names
+ internal string[] GenitiveMonthNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saMonthGenitiveNames;
+ }
+
+ // month names
+ internal string[] AbbreviatedMonthNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saAbbrevMonthNames;
+ }
+
+ // Genitive month names
+ internal string[] AbbreviatedGenitiveMonthNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saAbbrevMonthGenitiveNames;
+ }
+
+ // Leap year month names
+ // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name
+ // the non-leap names skip the 7th name in the normal month name array
+ internal string[] LeapYearMonthNames(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).saLeapYearMonthNames;
+ }
+
+ // month/day format (single string, no override)
+ internal String MonthDay(CalendarId calendarId)
+ {
+ return GetCalendar(calendarId).sMonthDay;
+ }
+
+
+
+ /////////////
+ // Calendars //
+ /////////////
+
+ // all available calendar type(s), The first one is the default calendar.
+ internal CalendarId[] CalendarIds
+ {
+ get
+ {
+ if (_waCalendars == null)
+ {
+ // We pass in an array of ints, and native side fills it up with count calendars.
+ // We then have to copy that list to a new array of the right size.
+ // Default calendar should be first
+ CalendarId[] calendars = new CalendarId[23];
+ Contract.Assert(_sWindowsName != null, "[CultureData.CalendarIds] Expected _sWindowsName to be populated by already");
+ int count = CalendarData.GetCalendars(_sWindowsName, _bUseOverrides, calendars);
+
+ // See if we had a calendar to add.
+ if (count == 0)
+ {
+ // Failed for some reason, just grab Gregorian from Invariant
+ _waCalendars = Invariant._waCalendars;
+ }
+ else
+ {
+ // The OS may not return calendar 4 for zh-TW, but we've always allowed it.
+ // TODO: Is this hack necessary long-term?
+ if (_sWindowsName == "zh-TW")
+ {
+ bool found = false;
+
+ // Do we need to insert calendar 4?
+ for (int i = 0; i < count; i++)
+ {
+ // Stop if we found calendar four
+ if (calendars[i] == CalendarId.TAIWAN)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ // If not found then insert it
+ if (!found)
+ {
+ // Insert it as the 2nd calendar
+ count++;
+ // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added.
+ Array.Copy(calendars, 1, calendars, 2, 23 - 1 - 1);
+ calendars[1] = CalendarId.TAIWAN;
+ }
+ }
+
+ // It worked, remember the list
+ CalendarId[] temp = new CalendarId[count];
+ Array.Copy(calendars, temp, count);
+
+ // Want 1st calendar to be default
+ // Prior to Vista the enumeration didn't have default calendar first
+ if (temp.Length > 1)
+ {
+ CalendarId i = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType);
+ if (temp[1] == i)
+ {
+ temp[1] = temp[0];
+ temp[0] = i;
+ }
+ }
+
+ _waCalendars = temp;
+ }
+ }
+
+ return _waCalendars;
+ }
+ }
+
+ internal CalendarData GetCalendar(CalendarId calendarId)
+ {
+ Contract.Assert(calendarId > 0 && calendarId <= CalendarId.LAST_CALENDAR,
+ "[CultureData.GetCalendar] Expect calendarId to be in a valid range");
+
+ // arrays are 0 based, calendarIds are 1 based
+ int calendarIndex = (int)calendarId - 1;
+
+ // Have to have calendars
+ if (_calendars == null)
+ {
+ _calendars = new CalendarData[CalendarData.MAX_CALENDARS];
+ }
+
+ // we need the following local variable to avoid returning null
+ // when another thread creates a new array of CalendarData (above)
+ // right after we insert the newly created CalendarData (below)
+ CalendarData calendarData = _calendars[calendarIndex];
+ // Make sure that calendar has data
+ if (calendarData == null)
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetCalendar] Expected _sWindowsName to be populated by already");
+ calendarData = new CalendarData(_sWindowsName, calendarId, this.UseUserOverride);
+ _calendars[calendarIndex] = calendarData;
+ }
+
+ return calendarData;
+ }
+
+ ///////////////////
+ // Text Information //
+ ///////////////////
+
+ // IsRightToLeft
+ internal bool IsRightToLeft
+ {
+ get
+ {
+ // Returns one of the following 4 reading layout values:
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+ return (this.IREADINGLAYOUT == 1);
+ }
+ }
+
+ // IREADINGLAYOUT
+ // Returns one of the following 4 reading layout values:
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+ //
+ // If exposed as a public API, we'd have an enum with those 4 values
+ private int IREADINGLAYOUT
+ {
+ get
+ {
+ if (_iReadingLayout == undef)
+ {
+ Contract.Assert(_sRealName != null, "[CultureData.IsRightToLeft] Expected _sRealName to be populated by already");
+ _iReadingLayout = GetLocaleInfo(LocaleNumberData.ReadingLayout);
+ }
+
+ return (_iReadingLayout);
+ }
+ }
+
+ // The TextInfo name never includes that alternate sort and is always specific
+ // For customs, it uses the SortLocale (since the textinfo is not exposed in Win7)
+ // en -> en-US
+ // en-US -> en-US
+ // fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj)
+ // fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ)
+ // es-ES_tradnl -> es-ES
+ internal String STEXTINFO // Text info name to use for text information
+ {
+ get
+ {
+ // Note: Custom cultures might point at another culture's textinfo, however windows knows how
+ // to redirect it to the desired textinfo culture, so this is OK.
+ Contract.Assert(_sWindowsName != null, "[CultureData.STEXTINFO] Expected _sWindowsName to be populated by already");
+ return (_sWindowsName);
+ }
+ }
+
+ // Compare info name (including sorting key) to use if custom
+ internal String SCOMPAREINFO
+ {
+ get
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.SCOMPAREINFO] Expected _sWindowsName to be populated by already");
+ return (_sWindowsName);
+ }
+ }
+
+ internal bool IsSupplementalCustomCulture
+ {
+ get
+ {
+ return IsCustomCultureId(this.ILANGUAGE);
+ }
+ }
+
+ internal int ILANGUAGE
+ {
+ get
+ {
+ return _iLanguage;
+ }
+ }
+
+ internal bool IsNeutralCulture
+ {
+ get
+ {
+ // InitCultureData told us if we're neutral or not
+ return _bNeutral;
+ }
+ }
+
+ internal bool IsInvariantCulture
+ {
+ get
+ {
+ return String.IsNullOrEmpty(this.SNAME);
+ }
+ }
+
+ // Get an instance of our default calendar
+ internal Calendar DefaultCalendar
+ {
+ get
+ {
+ CalendarId defaultCalId = (CalendarId)GetLocaleInfo(LocaleNumberData.CalendarType);
+
+ if (defaultCalId == 0)
+ {
+ defaultCalId = this.CalendarIds[0];
+ }
+
+ return CultureInfo.GetCalendarInstance(defaultCalId);
+ }
+ }
+
+ // All of our era names
+ internal String[] EraNames(CalendarId calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saEraNames;
+ }
+
+ internal String[] AbbrevEraNames(CalendarId calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saAbbrevEraNames;
+ }
+
+ internal String[] AbbreviatedEnglishEraNames(CalendarId calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saAbbrevEnglishEraNames;
+ }
+
+ //// String array DEFAULTS
+ //// Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to.
+
+
+ // Time separator (derived from time format)
+ internal String TimeSeparator
+ {
+ get
+ {
+ if (_sTimeSeparator == null)
+ {
+ string longTimeFormat = GetTimeFormatString();
+ if (String.IsNullOrEmpty(longTimeFormat))
+ {
+ longTimeFormat = LongTimes[0];
+ }
+
+ // Compute STIME from time format
+ _sTimeSeparator = GetTimeSeparator(longTimeFormat);
+ }
+ return _sTimeSeparator;
+ }
+ }
+
+ // Date separator (derived from short date format)
+ internal String DateSeparator(CalendarId calendarId)
+ {
+ return GetDateSeparator(ShortDates(calendarId)[0]);
+ }
+
+ //////////////////////////////////////
+ // Helper Functions to get derived properties //
+ //////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Unescape a NLS style quote string
+ //
+ // This removes single quotes:
+ // 'fred' -> fred
+ // 'fred -> fred
+ // fred' -> fred
+ // fred's -> freds
+ //
+ // This removes the first \ of escaped characters:
+ // fred\'s -> fred's
+ // a\\b -> a\b
+ // a\b -> ab
+ //
+ // We don't build the stringbuilder unless we find a ' or a \. If we find a ' or a \, we
+ // always build a stringbuilder because we need to remove the ' or \.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ private static String UnescapeNlsString(String str, int start, int end)
+ {
+ Contract.Requires(str != null);
+ Contract.Requires(start >= 0);
+ Contract.Requires(end >= 0);
+ StringBuilder result = null;
+
+ for (int i = start; i < str.Length && i <= end; i++)
+ {
+ switch (str[i])
+ {
+ case '\'':
+ if (result == null)
+ {
+ result = new StringBuilder(str, start, i - start, str.Length);
+ }
+ break;
+ case '\\':
+ if (result == null)
+ {
+ result = new StringBuilder(str, start, i - start, str.Length);
+ }
+ ++i;
+ if (i < str.Length)
+ {
+ result.Append(str[i]);
+ }
+ break;
+ default:
+ if (result != null)
+ {
+ result.Append(str[i]);
+ }
+ break;
+ }
+ }
+
+ if (result == null)
+ return (str.Substring(start, end - start + 1));
+
+ return (result.ToString());
+ }
+
+ private static String GetTimeSeparator(String format)
+ {
+ // Time format separator (ie: : in 12:39:00)
+ //
+ // We calculate this from the provided time format
+ //
+
+ //
+ // Find the time separator so that we can pretend we know STIME.
+ //
+ return GetSeparator(format, "Hhms");
+ }
+
+ private static String GetDateSeparator(String format)
+ {
+ // Date format separator (ie: / in 9/1/03)
+ //
+ // We calculate this from the provided short date
+ //
+
+ //
+ // Find the date separator so that we can pretend we know SDATE.
+ //
+ return GetSeparator(format, "dyM");
+ }
+
+ private static string GetSeparator(string format, string timeParts)
+ {
+ int index = IndexOfTimePart(format, 0, timeParts);
+
+ if (index != -1)
+ {
+ // Found a time part, find out when it changes
+ char cTimePart = format[index];
+
+ do
+ {
+ index++;
+ } while (index < format.Length && format[index] == cTimePart);
+
+ int separatorStart = index;
+
+ // Now we need to find the end of the separator
+ if (separatorStart < format.Length)
+ {
+ int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts);
+ if (separatorEnd != -1)
+ {
+ // From [separatorStart, count) is our string, except we need to unescape
+ return UnescapeNlsString(format, separatorStart, separatorEnd - 1);
+ }
+ }
+ }
+
+ return String.Empty;
+ }
+
+ private static int IndexOfTimePart(string format, int startIndex, string timeParts)
+ {
+ Contract.Assert(startIndex >= 0, "startIndex cannot be negative");
+ Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters");
+ bool inQuote = false;
+ for (int i = startIndex; i < format.Length; ++i)
+ {
+ // See if we have a time Part
+ if (!inQuote && timeParts.IndexOf(format[i]) != -1)
+ {
+ return i;
+ }
+ switch (format[i])
+ {
+ case '\\':
+ if (i + 1 < format.Length)
+ {
+ ++i;
+ switch (format[i])
+ {
+ case '\'':
+ case '\\':
+ break;
+ default:
+ --i; //backup since we will move over this next
+ break;
+ }
+ }
+ break;
+ case '\'':
+ inQuote = !inQuote;
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+ private static bool IsCustomCultureId(int cultureId)
+ {
+ return (cultureId == LOCALE_CUSTOM_DEFAULT || cultureId == LOCALE_CUSTOM_UNSPECIFIED);
+ }
+
+ internal void GetNFIValues(NumberFormatInfo nfi)
+ {
+ if (this.IsInvariantCulture)
+ {
+ // FUTURE: NumberFormatInfo already has default values for many of these fields. Can we not do this?
+ // if we do need to do this, then why don't we set nfi.nativeDigits in this case?
+ nfi.positiveSign = _sPositiveSign;
+ nfi.negativeSign = _sNegativeSign;
+
+ nfi.numberGroupSeparator = _sThousandSeparator;
+ nfi.numberDecimalSeparator = _sDecimalSeparator;
+ nfi.numberDecimalDigits = _iDigits;
+ nfi.numberNegativePattern = _iNegativeNumber;
+
+ nfi.currencySymbol = _sCurrency;
+ nfi.currencyGroupSeparator = _sMonetaryThousand;
+ nfi.currencyDecimalSeparator = _sMonetaryDecimal;
+ nfi.currencyDecimalDigits = _iCurrencyDigits;
+ nfi.currencyNegativePattern = _iNegativeCurrency;
+ nfi.currencyPositivePattern = _iCurrency;
+ }
+ else
+ {
+ Contract.Assert(_sWindowsName != null, "[CultureData.GetNFIValues] Expected _sWindowsName to be populated by already");
+ // String values
+ nfi.positiveSign = GetLocaleInfo(LocaleStringData.PositiveSign);
+ nfi.negativeSign = GetLocaleInfo(LocaleStringData.NegativeSign);
+
+ nfi.numberDecimalSeparator = GetLocaleInfo(LocaleStringData.DecimalSeparator);
+ nfi.numberGroupSeparator = GetLocaleInfo(LocaleStringData.ThousandSeparator);
+ nfi.currencyGroupSeparator = GetLocaleInfo(LocaleStringData.MonetaryThousandSeparator);
+ nfi.currencyDecimalSeparator = GetLocaleInfo(LocaleStringData.MonetaryDecimalSeparator);
+ nfi.currencySymbol = GetLocaleInfo(LocaleStringData.MonetarySymbol);
+
+ // Numeric values
+ nfi.numberDecimalDigits = GetLocaleInfo(LocaleNumberData.FractionalDigitsCount);
+ nfi.currencyDecimalDigits = GetLocaleInfo(LocaleNumberData.MonetaryFractionalDigitsCount);
+ nfi.currencyPositivePattern = GetLocaleInfo(LocaleNumberData.PositiveMonetaryNumberFormat);
+ nfi.currencyNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeMonetaryNumberFormat);
+ nfi.numberNegativePattern = GetLocaleInfo(LocaleNumberData.NegativeNumberFormat);
+
+ // LOCALE_SNATIVEDIGITS (array of 10 single character strings).
+ string digits = GetLocaleInfo(LocaleStringData.Digits);
+ nfi.nativeDigits = new string[10];
+ for (int i = 0; i < nfi.nativeDigits.Length; i++)
+ {
+ nfi.nativeDigits[i] = new string(digits[i], 1);
+ }
+ }
+
+ //
+ // Gather additional data
+ //
+ nfi.numberGroupSizes = this.WAGROUPING;
+ nfi.currencyGroupSizes = this.WAMONGROUPING;
+
+ // prefer the cached value since these do not have user overrides
+ nfi.percentNegativePattern = this.INEGATIVEPERCENT;
+ nfi.percentPositivePattern = this.IPOSITIVEPERCENT;
+ nfi.percentSymbol = this.SPERCENT;
+ nfi.perMilleSymbol = this.SPERMILLE;
+
+ nfi.negativeInfinitySymbol = this.SNEGINFINITY;
+ nfi.positiveInfinitySymbol = this.SPOSINFINITY;
+ nfi.nanSymbol = this.SNAN;
+
+ //
+ // We don't have percent values, so use the number values
+ //
+ nfi.percentDecimalDigits = nfi.numberDecimalDigits;
+ nfi.percentDecimalSeparator = nfi.numberDecimalSeparator;
+ nfi.percentGroupSizes = nfi.numberGroupSizes;
+ nfi.percentGroupSeparator = nfi.numberGroupSeparator;
+
+ //
+ // Clean up a few odd values
+ //
+
+ // Windows usually returns an empty positive sign, but we like it to be "+"
+ if (nfi.positiveSign == null || nfi.positiveSign.Length == 0) nfi.positiveSign = "+";
+
+ //Special case for Italian. The currency decimal separator in the control panel is the empty string. When the user
+ //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the
+ //decimal point doesn't show up. We'll just hack this here because our default currency format will never use nfi.
+ if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0)
+ {
+ nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator;
+ }
+ }
+
+ // Helper
+ // This is ONLY used for caching names and shouldn't be used for anything else
+ internal static string AnsiToLower(string testString)
+ {
+ StringBuilder sb = new StringBuilder(testString.Length);
+
+ for (int ich = 0; ich < testString.Length; ich++)
+ {
+ char ch = testString[ich];
+ sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch);
+ }
+
+ return (sb.ToString());
+ }
+
+ /// <remarks>
+ /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
+ /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
+ /// </remarks>
+ private enum LocaleStringData : uint
+ {
+ /// <summary>localized name of locale, eg "German (Germany)" in UI language (coresponds to LOCALE_SLOCALIZEDDISPLAYNAME)</summary>
+ LocalizedDisplayName = 0x00000002,
+ /// <summary>Display name (language + country usually) in English, eg "German (Germany)" (coresponds to LOCALE_SENGLISHDISPLAYNAME)</summary>
+ EnglishDisplayName = 0x00000072,
+ /// <summary>Display name in native locale language, eg "Deutsch (Deutschland) (coresponds to LOCALE_SNATIVEDISPLAYNAME)</summary>
+ NativeDisplayName = 0x00000073,
+ /// <summary>Language Display Name for a language, eg "German" in UI language (coresponds to LOCALE_SLOCALIZEDLANGUAGENAME)</summary>
+ LocalizedLanguageName = 0x0000006f,
+ /// <summary>English name of language, eg "German" (coresponds to LOCALE_SENGLISHLANGUAGENAME)</summary>
+ EnglishLanguageName = 0x00001001,
+ /// <summary>native name of language, eg "Deutsch" (coresponds to LOCALE_SNATIVELANGUAGENAME)</summary>
+ NativeLanguageName = 0x00000004,
+ /// <summary>English name of country, eg "Germany" (coresponds to LOCALE_SENGLISHCOUNTRYNAME)</summary>
+ EnglishCountryName = 0x00001002,
+ /// <summary>native name of country, eg "Deutschland" (coresponds to LOCALE_SNATIVECOUNTRYNAME)</summary>
+ NativeCountryName = 0x00000008,
+ /// <summary>list item separator (coresponds to LOCALE_SLIST)</summary>
+ ListSeparator = 0x0000000C,
+ /// <summary>decimal separator (coresponds to LOCALE_SDECIMAL)</summary>
+ DecimalSeparator = 0x0000000E,
+ /// <summary>thousand separator (coresponds to LOCALE_STHOUSAND)</summary>
+ ThousandSeparator = 0x0000000F,
+ /// <summary>digit grouping (coresponds to LOCALE_SGROUPING)</summary>
+ Digits = 0x00000013,
+ /// <summary>local monetary symbol (coresponds to LOCALE_SCURRENCY)</summary>
+ MonetarySymbol = 0x00000014,
+ /// <summary>uintl monetary symbol (coresponds to LOCALE_SINTLSYMBOL)</summary>
+ Iso4217MonetarySymbol = 0x00000015,
+ /// <summary>monetary decimal separator (coresponds to LOCALE_SMONDECIMALSEP)</summary>
+ MonetaryDecimalSeparator = 0x00000016,
+ /// <summary>monetary thousand separator (coresponds to LOCALE_SMONTHOUSANDSEP)</summary>
+ MonetaryThousandSeparator = 0x00000017,
+ /// <summary>AM designator (coresponds to LOCALE_S1159)</summary>
+ AMDesignator = 0x00000028,
+ /// <summary>PM designator (coresponds to LOCALE_S2359)</summary>
+ PMDesignator = 0x00000029,
+ /// <summary>positive sign (coresponds to LOCALE_SPOSITIVESIGN)</summary>
+ PositiveSign = 0x00000050,
+ /// <summary>negative sign (coresponds to LOCALE_SNEGATIVESIGN)</summary>
+ NegativeSign = 0x00000051,
+ /// <summary>ISO abbreviated language name (coresponds to LOCALE_SISO639LANGNAME)</summary>
+ Iso639LanguageName = 0x00000059,
+ /// <summary>ISO abbreviated country name (coresponds to LOCALE_SISO3166CTRYNAME)</summary>
+ Iso3166CountryName = 0x0000005A,
+ /// <summary>Not a Number (coresponds to LOCALE_SNAN)</summary>
+ NaNSymbol = 0x00000069,
+ /// <summary>+ Infinity (coresponds to LOCALE_SPOSINFINITY)</summary>
+ PositiveInfinitySymbol = 0x0000006a,
+ /// <summary>- Infinity (coresponds to LOCALE_SNEGINFINITY)</summary>
+ NegativeInfinitySymbol = 0x0000006b,
+ /// <summary>Fallback name for resources (coresponds to LOCALE_SPARENT)</summary>
+ ParentName = 0x0000006d,
+ /// <summary>Returns the percent symbol (coresponds to LOCALE_SPERCENT)</summary>
+ PercentSymbol = 0x00000076,
+ /// <summary>Returns the permille (U+2030) symbol (coresponds to LOCALE_SPERMILLE)</summary>
+ PerMilleSymbol = 0x00000077
+ }
+
+ /// <remarks>
+ /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
+ /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
+ /// </remarks>
+ private enum LocaleGroupingData : uint
+ {
+ /// <summary>digit grouping (coresponds to LOCALE_SGROUPING)</summary>
+ Digit = 0x00000010,
+ /// <summary>monetary grouping (coresponds to LOCALE_SMONGROUPING)</summary>
+ Monetary = 0x00000018,
+ }
+
+ /// <remarks>
+ /// The numeric values of the enum members match their Win32 counterparts. The CultureData Win32 PAL implementation
+ /// takes a dependency on this fact, in order to prevent having to construct a mapping from internal values to LCTypes.
+ /// </remarks>
+ private enum LocaleNumberData : uint
+ {
+ /// <summary>language id (coresponds to LOCALE_ILANGUAGE)</summary>
+ LanguageId = 0x00000001,
+ /// <summary>0 = metric, 1 = US (coresponds to LOCALE_IMEASURE)</summary>
+ MeasurementSystem = 0x0000000D,
+ /// <summary>number of fractional digits (coresponds to LOCALE_IDIGITS)</summary>
+ FractionalDigitsCount = 0x00000011,
+ /// <summary>negative number mode (coresponds to LOCALE_INEGNUMBER)</summary>
+ NegativeNumberFormat = 0x00001010,
+ /// <summary># local monetary digits (coresponds to LOCALE_ICURRDIGITS)</summary>
+ MonetaryFractionalDigitsCount = 0x00000019,
+ /// <summary>positive currency mode (coresponds to LOCALE_ICURRENCY)</summary>
+ PositiveMonetaryNumberFormat = 0x0000001B,
+ /// <summary>negative currency mode (coresponds to LOCALE_INEGCURR)</summary>
+ NegativeMonetaryNumberFormat = 0x0000001C,
+ /// <summary>type of calendar specifier (coresponds to LOCALE_ICALENDARTYPE)</summary>
+ CalendarType = 0x00001009,
+ /// <summary>first day of week specifier (coresponds to LOCALE_IFIRSTDAYOFWEEK)</summary>
+ FirstDayOfWeek = 0x0000100C,
+ /// <summary>first week of year specifier (coresponds to LOCALE_IFIRSTWEEKOFYEAR)</summary>
+ FirstWeekOfYear = 0x0000100D,
+ /// <summary>
+ /// Returns one of the following 4 reading layout values:
+ /// 0 - Left to right (eg en-US)
+ /// 1 - Right to left (eg arabic locales)
+ /// 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ /// 3 - Vertical top to bottom with columns proceeding to the right
+ /// (coresponds to LOCALE_IREADINGLAYOUT)
+ /// </summary>
+ ReadingLayout = 0x00000070,
+ /// <summary>Returns 0-11 for the negative percent format (coresponds to LOCALE_INEGATIVEPERCENT)</summary>
+ NegativePercentFormat = 0x00000074,
+ /// <summary>Returns 0-3 for the positive percent format (coresponds to LOCALE_IPOSITIVEPERCENT)</summary>
+ PositivePercentFormat = 0x00000075
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs
new file mode 100644
index 0000000000..6911688b08
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureInfo.Unix.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ public partial class CultureInfo : IFormatProvider
+ {
+ private static CultureInfo GetUserDefaultCultureCacheOverride()
+ {
+ return null; // ICU doesn't provide a user override
+ }
+
+ internal static CultureInfo GetUserDefaultCulture()
+ {
+ CultureInfo cultureInfo = null;
+ string localeName;
+ if (CultureData.GetDefaultLocaleName(out localeName))
+ {
+ cultureInfo = GetCultureByName(localeName, true);
+ cultureInfo.m_isReadOnly = true;
+ }
+ else
+ {
+ cultureInfo = CultureInfo.InvariantCulture;
+ }
+
+ return cultureInfo;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs
new file mode 100644
index 0000000000..16c8a06e08
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureInfo.Windows.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.Augments;
+
+namespace System.Globalization
+{
+ public partial class CultureInfo : IFormatProvider
+ {
+ /// <summary>
+ /// Gets the default user culture from WinRT, if available.
+ /// </summary>
+ /// <remarks>
+ /// This method may return null, if there is no default user culture or if WinRT isn't available.
+ /// </remarks>
+ private static CultureInfo GetUserDefaultCultureCacheOverride()
+ {
+ WinRTInteropCallbacks callbacks = WinRTInterop.UnsafeCallbacks;
+ if (callbacks != null && callbacks.IsAppxModel())
+ {
+ return (CultureInfo)callbacks.GetUserDefaultCulture();
+ }
+
+ return null;
+ }
+
+ private static CultureInfo GetUserDefaultCulture()
+ {
+ const uint LOCALE_SNAME = 0x0000005c;
+ const string LOCALE_NAME_USER_DEFAULT = null;
+ const string LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale";
+
+ string strDefault = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SNAME);
+ if (strDefault == null)
+ {
+ strDefault = Interop.mincore.GetLocaleInfoEx(LOCALE_NAME_SYSTEM_DEFAULT, LOCALE_SNAME);
+
+ if (strDefault == null)
+ {
+ // If system default doesn't work, use invariant
+ return CultureInfo.InvariantCulture;
+ }
+ }
+
+ CultureInfo temp = GetCultureByName(strDefault, true);
+
+ temp._isReadOnly = true;
+
+ return temp;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/CultureInfo.cs b/src/mscorlib/corefx/System/Globalization/CultureInfo.cs
new file mode 100644
index 0000000000..f2b3742ab4
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureInfo.cs
@@ -0,0 +1,1144 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+// Purpose: This class represents the software preferences of a particular
+// culture or community. It includes information such as the
+// language, writing system, and a calendar used by the culture
+// as well as methods for common operations such as printing
+// dates and sorting strings.
+//
+//
+//
+// !!!! NOTE WHEN CHANGING THIS CLASS !!!!
+//
+// If adding or removing members to this class, please update CultureInfoBaseObject
+// in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be
+// different than the order in which members are declared. For instance, all
+// reference types will come first in the class before value types (like ints, bools, etc)
+// regardless of the order in which they are declared. The best way to see the
+// actual order of the class is to do a !dumpobj on an instance of the managed
+// object inside of the debugger.
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Threading;
+
+namespace System.Globalization
+{
+
+#if INSIDE_CLR
+ using StringCultureInfoDictionary = Dictionary<string, CultureInfo>;
+ using Lock = Object;
+#else
+ using StringCultureInfoDictionary = LowLevelDictionary<string, CultureInfo>;
+#endif
+
+ [Serializable]
+ public partial class CultureInfo : IFormatProvider, ICloneable
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //--------------------------------------------------------------------//
+ // Data members to be serialized:
+ //--------------------------------------------------------------------//
+
+ // We use an RFC4646 type string to construct CultureInfo.
+ // This string is stored in m_name and is authoritative.
+ // We use the m_cultureData to get the data for our object
+
+ private bool m_isReadOnly;
+ private CompareInfo compareInfo;
+ private TextInfo textInfo;
+ internal NumberFormatInfo numInfo;
+ internal DateTimeFormatInfo dateTimeInfo;
+ private Calendar calendar;
+ //
+ // The CultureData instance that we are going to read data from.
+ // For supported culture, this will be the CultureData instance that read data from mscorlib assembly.
+ // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
+ //
+ [NonSerialized]
+ internal CultureData m_cultureData;
+
+ [NonSerialized]
+ internal bool m_isInherited;
+
+ // Names are confusing. Here are 3 names we have:
+ //
+ // new CultureInfo() m_name m_nonSortName m_sortName
+ // en-US en-US en-US en-US
+ // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb
+ // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US)
+ // en en
+ //
+ // Note that in Silverlight we ask the OS for the text and sort behavior, so the
+ // textinfo and compareinfo names are the same as the name
+
+ // Note that the name used to be serialized for Everett; it is now serialized
+ // because alernate sorts can have alternate names.
+ // This has a de-DE, de-DE_phoneb or fj-FJ style name
+ internal string m_name;
+
+ // This will hold the non sorting name to be returned from CultureInfo.Name property.
+ // This has a de-DE style name even for de-DE_phoneb type cultures
+ [NonSerialized]
+ private string m_nonSortName;
+
+ // This will hold the sorting name to be returned from CultureInfo.SortName property.
+ // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ.
+ // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
+ [NonSerialized]
+ private string m_sortName;
+
+
+ //--------------------------------------------------------------------//
+ //
+ // Static data members
+ //
+ //--------------------------------------------------------------------//
+
+ //Get the current user default culture. This one is almost always used, so we create it by default.
+ private static volatile CultureInfo s_userDefaultCulture;
+
+ //
+ // All of the following will be created on demand.
+ //
+
+ // WARNING: We allow diagnostic tools to directly inspect these three members (s_InvariantCultureInfo, s_DefaultThreadCurrentUICulture and s_DefaultThreadCurrentCulture)
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // Get in touch with the diagnostics team if you have questions.
+
+ //The Invariant culture;
+ private static volatile CultureInfo s_InvariantCultureInfo;
+
+ //These are defaults that we use if a thread has not opted into having an explicit culture
+ private static volatile CultureInfo s_DefaultThreadCurrentUICulture;
+ private static volatile CultureInfo s_DefaultThreadCurrentCulture;
+
+ [ThreadStatic]
+ private static volatile CultureInfo s_currentThreadCulture;
+ [ThreadStatic]
+ private static volatile CultureInfo s_currentThreadUICulture;
+
+ private static readonly Lock m_lock = new Lock();
+ private static volatile StringCultureInfoDictionary s_NameCachedCultures;
+
+ //The parent culture.
+ [NonSerialized]
+ private CultureInfo m_parent;
+
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentCulture;
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentUICulture;
+
+ static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+ s_currentThreadCulture = args.CurrentValue;
+ }
+
+ static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+ s_currentThreadUICulture = args.CurrentValue;
+ }
+
+ //
+ // The CultureData instance that reads the data provided by our CultureData class.
+ //
+ // Using a field initializer rather than a static constructor so that the whole class can be lazy
+ // init.
+ private static readonly bool init = Init();
+ private static bool Init()
+ {
+ if (s_InvariantCultureInfo == null)
+ {
+ CultureInfo temp = new CultureInfo("", false);
+ temp.m_isReadOnly = true;
+ s_InvariantCultureInfo = temp;
+ }
+
+ s_userDefaultCulture = GetUserDefaultCulture();
+ return true;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CultureInfo Constructors
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public CultureInfo(String name)
+ : this(name, true)
+ {
+ }
+
+
+ internal CultureInfo(String name, bool useUserOverride)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name",
+ SR.ArgumentNull_String);
+ }
+
+ InitializeFromName(name, useUserOverride);
+ }
+
+ private void InitializeFromName(string name, bool useUserOverride)
+ {
+ // Get our data providing record
+ this.m_cultureData = CultureData.GetCultureData(name, useUserOverride);
+
+ if (this.m_cultureData == null)
+ {
+ throw new CultureNotFoundException("name", name, SR.Argument_CultureNotSupported);
+ }
+
+ this.m_name = this.m_cultureData.CultureName;
+ this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
+ }
+
+ // We do this to try to return the system UI language and the default user languages
+ // This method will fallback if this fails (like Invariant)
+ //
+ // TODO: It would appear that this is only ever called with userOveride = true
+ // and this method only has one caller. Can we fold it into the caller?
+ private static CultureInfo GetCultureByName(String name, bool userOverride)
+ {
+ CultureInfo ci = null;
+ // Try to get our culture
+ try
+ {
+ ci = userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (ci == null)
+ {
+ ci = InvariantCulture;
+ }
+
+ return ci;
+ }
+
+ // //
+ // // Return a specific culture. A tad irrelevent now since we always return valid data
+ // // for neutral locales.
+ // //
+ // // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
+ // // if we can't find a bigger name. That doesn't help with things like "zh" though, so
+ // // the approach is of questionable value
+ // //
+
+ internal static bool VerifyCultureName(String cultureName, bool throwException)
+ {
+ // This function is used by ResourceManager.GetResourceFileName().
+ // ResourceManager searches for resource using CultureInfo.Name,
+ // so we should check against CultureInfo.Name.
+
+ for (int i = 0; i < cultureName.Length; i++)
+ {
+ char c = cultureName[i];
+ // TODO: Names can only be RFC4646 names (ie: a-zA-Z0-9) while this allows any unicode letter/digit
+ if (Char.IsLetterOrDigit(c) || c == '-' || c == '_')
+ {
+ continue;
+ }
+ if (throwException)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidResourceCultureName, cultureName));
+ }
+ return false;
+ }
+ return true;
+ }
+
+ internal static bool VerifyCultureName(CultureInfo culture, bool throwException)
+ {
+ //If we have an instance of one of our CultureInfos, the user can't have changed the
+ //name and we know that all names are valid in files.
+ if (!culture.m_isInherited)
+ {
+ return true;
+ }
+
+ return VerifyCultureName(culture.Name, throwException);
+ }
+
+ // We need to store the override from the culture data record.
+ private bool m_useUserOverride;
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ m_name = m_cultureData.CultureName;
+ m_useUserOverride = m_cultureData.UseUserOverride;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null");
+ InitializeFromName(m_name, m_useUserOverride);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrentCulture
+ //
+ // This instance provides methods based on the current user settings.
+ // These settings are volatile and may change over the lifetime of the
+ // thread.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ //
+ // We use the following order to return CurrentCulture and CurrentUICulture
+ // o Use WinRT to return the current user profile language
+ // o use current thread culture if the user already set one using CurrentCulture/CurrentUICulture
+ // o use thread culture if the user already set one using DefaultThreadCurrentCulture
+ // or DefaultThreadCurrentUICulture
+ // o Use NLS default user culture
+ // o Use NLS default system culture
+ // o Use Invariant culture
+ //
+ public static CultureInfo CurrentCulture
+ {
+ get
+ {
+ CultureInfo ci = GetUserDefaultCultureCacheOverride();
+ if (ci != null)
+ {
+ return ci;
+ }
+
+ if (s_currentThreadCulture != null)
+ {
+ return s_currentThreadCulture;
+ }
+
+ ci = s_DefaultThreadCurrentCulture;
+ if (ci != null)
+ {
+ return ci;
+ }
+
+ // if s_userDefaultCulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static
+ // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize
+ if (s_userDefaultCulture == null)
+ {
+ Init();
+ }
+
+ Contract.Assert(s_userDefaultCulture != null);
+ return s_userDefaultCulture;
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ if (s_asyncLocalCurrentCulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentCulture), null);
+ }
+ // this one will set s_currentThreadCulture too
+ s_asyncLocalCurrentCulture.Value = value;
+ }
+ }
+
+ public static CultureInfo CurrentUICulture
+ {
+ get
+ {
+ CultureInfo ci = GetUserDefaultCultureCacheOverride();
+ if (ci != null)
+ {
+ return ci;
+ }
+
+ if (s_currentThreadUICulture != null)
+ {
+ return s_currentThreadUICulture;
+ }
+
+ ci = s_DefaultThreadCurrentUICulture;
+ if (ci != null)
+ {
+ return ci;
+ }
+
+ // if s_userDefaultCulture == null means CultureInfo statics didn't get initialized yet. this can happen if there early static
+ // method get executed which eventually hit the cultureInfo code while CultureInfo statics didn’t get chance to initialize
+ if (s_userDefaultCulture == null)
+ {
+ Init();
+ }
+
+ Contract.Assert(s_userDefaultCulture != null);
+ return s_userDefaultCulture;
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ CultureInfo.VerifyCultureName(value, true);
+
+ if (s_asyncLocalCurrentUICulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentUICulture), null);
+ }
+
+ // this one will set s_currentThreadUICulture too
+ s_asyncLocalCurrentUICulture.Value = value;
+ }
+ }
+
+ public static CultureInfo DefaultThreadCurrentCulture
+ {
+ get { return s_DefaultThreadCurrentCulture; }
+ set
+ {
+ // If you add pre-conditions to this method, check to see if you also need to
+ // add them to Thread.CurrentCulture.set.
+
+ s_DefaultThreadCurrentCulture = value;
+ }
+ }
+
+ public static CultureInfo DefaultThreadCurrentUICulture
+ {
+ get { return s_DefaultThreadCurrentUICulture; }
+ set
+ {
+ //If they're trying to use a Culture with a name that we can't use in resource lookup,
+ //don't even let them set it on the thread.
+
+ // If you add more pre-conditions to this method, check to see if you also need to
+ // add them to Thread.CurrentUICulture.set.
+
+ if (value != null)
+ {
+ CultureInfo.VerifyCultureName(value, true);
+ }
+
+ s_DefaultThreadCurrentUICulture = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // InvariantCulture
+ //
+ // This instance provides methods, for example for casing and sorting,
+ // that are independent of the system and current user settings. It
+ // should be used only by processes such as some system services that
+ // require such invariant results (eg. file systems). In general,
+ // the results are not linguistically correct and do not match any
+ // culture info.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static CultureInfo InvariantCulture
+ {
+ get
+ {
+ return (s_InvariantCultureInfo);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Parent
+ //
+ // Return the parent CultureInfo for the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public virtual CultureInfo Parent
+ {
+ get
+ {
+ if (null == m_parent)
+ {
+ try
+ {
+ string parentName = this.m_cultureData.SPARENT;
+
+ if (String.IsNullOrEmpty(parentName))
+ {
+ m_parent = InvariantCulture;
+ }
+ else
+ {
+ m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
+ }
+ }
+ catch (ArgumentException)
+ {
+ // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
+ // We can't allow ourselves to fail. In case of custom cultures the parent of the
+ // current custom culture isn't installed.
+ m_parent = InvariantCulture;
+ }
+ }
+ return m_parent;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Name
+ //
+ // Returns the full name of the CultureInfo. The name is in format like
+ // "en-US" This version does NOT include sort information in the name.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String Name
+ {
+ get
+ {
+ // We return non sorting name here.
+ if (this.m_nonSortName == null)
+ {
+ this.m_nonSortName = this.m_cultureData.SNAME;
+ if (this.m_nonSortName == null)
+ {
+ this.m_nonSortName = String.Empty;
+ }
+ }
+ return this.m_nonSortName;
+ }
+ }
+
+ // This one has the sort information (ie: de-DE_phoneb)
+ internal String SortName
+ {
+ get
+ {
+ if (this.m_sortName == null)
+ {
+ this.m_sortName = this.m_cultureData.SCOMPAREINFO;
+ }
+
+ return this.m_sortName;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // DisplayName
+ //
+ // Returns the full name of the CultureInfo in the localized language.
+ // For example, if the localized language of the runtime is Spanish and the CultureInfo is
+ // US English, "Ingles (Estados Unidos)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String DisplayName
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Assert(m_name != null, "[CultureInfo.DisplayName] Always expect m_name to be set");
+
+ return m_cultureData.SLOCALIZEDDISPLAYNAME;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetNativeName
+ //
+ // Returns the full name of the CultureInfo in the native language.
+ // For example, if the CultureInfo is US English, "English
+ // (United States)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String NativeName
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SNATIVEDISPLAYNAME);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetEnglishName
+ //
+ // Returns the full name of the CultureInfo in English.
+ // For example, if the CultureInfo is US English, "English
+ // (United States)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String EnglishName
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SENGDISPLAYNAME);
+ }
+ }
+
+ // ie: en
+ public virtual String TwoLetterISOLanguageName
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SISO639LANGNAME);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CompareInfo Read-Only Property
+ //
+ // Gets the CompareInfo for this culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual CompareInfo CompareInfo
+ {
+ get
+ {
+ if (this.compareInfo == null)
+ {
+ // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from
+ // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
+ CompareInfo temp = UseUserOverride
+ ? GetCultureInfo(this.m_name).CompareInfo
+ : new CompareInfo(this);
+ if (OkayToCacheClassWithCompatibilityBehavior)
+ {
+ this.compareInfo = temp;
+ }
+ else
+ {
+ return temp;
+ }
+ }
+ return (compareInfo);
+ }
+ }
+
+ private static bool OkayToCacheClassWithCompatibilityBehavior
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // TextInfo
+ //
+ // Gets the TextInfo for this culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual TextInfo TextInfo
+ {
+ get
+ {
+ if (textInfo == null)
+ {
+ // Make a new textInfo
+ TextInfo tempTextInfo = new TextInfo(this.m_cultureData);
+ tempTextInfo.SetReadOnlyState(m_isReadOnly);
+
+ if (OkayToCacheClassWithCompatibilityBehavior)
+ {
+ textInfo = tempTextInfo;
+ }
+ else
+ {
+ return tempTextInfo;
+ }
+ }
+ return (textInfo);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CultureInfo as the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Equals(Object value)
+ {
+ if (Object.ReferenceEquals(this, value))
+ return true;
+
+ CultureInfo that = value as CultureInfo;
+
+ if (that != null)
+ {
+ // using CompareInfo to verify the data passed through the constructor
+ // CultureInfo(String cultureName, String textAndCompareCultureName)
+
+ return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo));
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A
+ // and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns the name of the CultureInfo,
+ // eg. "de-DE_phoneb", "en-US", or "fj-FJ".
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override String ToString()
+ {
+ return m_name;
+ }
+
+
+ public virtual Object GetFormat(Type formatType)
+ {
+ if (formatType == typeof(NumberFormatInfo))
+ return (NumberFormat);
+ if (formatType == typeof(DateTimeFormatInfo))
+ return (DateTimeFormat);
+ return (null);
+ }
+
+ public virtual bool IsNeutralCulture
+ {
+ get
+ {
+ return this.m_cultureData.IsNeutralCulture;
+ }
+ }
+
+ public virtual NumberFormatInfo NumberFormat
+ {
+ get
+ {
+ if (numInfo == null)
+ {
+ NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData);
+ temp.isReadOnly = m_isReadOnly;
+ numInfo = temp;
+ }
+ return (numInfo);
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value", SR.ArgumentNull_Obj);
+ }
+ VerifyWritable();
+ numInfo = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetDateTimeFormatInfo
+ //
+ // Create a DateTimeFormatInfo, and fill in the properties according to
+ // the CultureID.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual DateTimeFormatInfo DateTimeFormat
+ {
+ get
+ {
+ if (dateTimeInfo == null)
+ {
+ // Change the calendar of DTFI to the specified calendar of this CultureInfo.
+ DateTimeFormatInfo temp = new DateTimeFormatInfo(this.m_cultureData, this.Calendar);
+ temp._isReadOnly = m_isReadOnly;
+ System.Threading.Interlocked.MemoryBarrier();
+ dateTimeInfo = temp;
+ }
+ return (dateTimeInfo);
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value", SR.ArgumentNull_Obj);
+ }
+ VerifyWritable();
+ dateTimeInfo = value;
+ }
+ }
+
+ /*=================================GetCalendarInstance==========================
+ **Action: Map a Win32 CALID to an instance of supported calendar.
+ **Returns: An instance of calendar.
+ **Arguments: calType The Win32 CALID
+ **Exceptions:
+ ** Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
+ ** If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar.
+ ============================================================================*/
+ internal static Calendar GetCalendarInstance(CalendarId calType)
+ {
+ if (calType == CalendarId.GREGORIAN)
+ {
+ return (new GregorianCalendar());
+ }
+ return GetCalendarInstanceRare(calType);
+ }
+
+ //This function exists as a shortcut to prevent us from loading all of the non-gregorian
+ //calendars unless they're required.
+ internal static Calendar GetCalendarInstanceRare(CalendarId calType)
+ {
+ Contract.Assert(calType != CalendarId.GREGORIAN, "calType!=CalendarId.GREGORIAN");
+
+ switch (calType)
+ {
+ case CalendarId.GREGORIAN_US: // Gregorian (U.S.) calendar
+ case CalendarId.GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar
+ case CalendarId.GREGORIAN_ARABIC: // Gregorian Arabic calendar
+ case CalendarId.GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar
+ case CalendarId.GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar
+ return (new GregorianCalendar((GregorianCalendarTypes)calType));
+ case CalendarId.TAIWAN: // Taiwan Era calendar
+ return (new TaiwanCalendar());
+ case CalendarId.JAPAN: // Japanese Emperor Era calendar
+ return (new JapaneseCalendar());
+ case CalendarId.KOREA: // Korean Tangun Era calendar
+ return (new KoreanCalendar());
+ case CalendarId.THAI: // Thai calendar
+ return (new ThaiBuddhistCalendar());
+ case CalendarId.HIJRI: // Hijri (Arabic Lunar) calendar
+ return (new HijriCalendar());
+ case CalendarId.HEBREW: // Hebrew (Lunar) calendar
+ return (new HebrewCalendar());
+ case CalendarId.UMALQURA:
+ return (new UmAlQuraCalendar());
+ case CalendarId.PERSIAN:
+ return (new PersianCalendar());
+ }
+ return (new GregorianCalendar());
+ }
+
+ /*=================================Calendar==========================
+ **Action: Return/set the default calendar used by this culture.
+ ** This value can be overridden by regional option if this is a current culture.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ** ArgumentNull_Obj if the set value is null.
+ ============================================================================*/
+ public virtual Calendar Calendar
+ {
+ get
+ {
+ if (calendar == null)
+ {
+ Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0");
+ // Get the default calendar for this culture. Note that the value can be
+ // from registry if this is a user default culture.
+ Calendar newObj = this.m_cultureData.DefaultCalendar;
+
+ System.Threading.Interlocked.MemoryBarrier();
+ newObj.SetReadOnlyState(m_isReadOnly);
+ calendar = newObj;
+ }
+ return (calendar);
+ }
+ }
+
+ /*=================================OptionCalendars==========================
+ **Action: Return an array of the optional calendar for this culture.
+ **Returns: an array of Calendar.
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+
+ public virtual Calendar[] OptionalCalendars
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<Calendar[]>() != null);
+
+ //
+ // This property always returns a new copy of the calendar array.
+ //
+ CalendarId[] calID = this.m_cultureData.CalendarIds;
+ Calendar[] cals = new Calendar[calID.Length];
+ for (int i = 0; i < cals.Length; i++)
+ {
+ cals[i] = GetCalendarInstance(calID[i]);
+ }
+ return (cals);
+ }
+ }
+
+
+ private bool UseUserOverride
+ {
+ get
+ {
+ return (this.m_cultureData.UseUserOverride);
+ }
+ }
+
+ public virtual Object Clone()
+ {
+ CultureInfo ci = (CultureInfo)MemberwiseClone();
+ ci.m_isReadOnly = false;
+
+ //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
+ //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
+ if (!m_isInherited)
+ {
+ if (this.dateTimeInfo != null)
+ {
+ ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone();
+ }
+ if (this.numInfo != null)
+ {
+ ci.numInfo = (NumberFormatInfo)this.numInfo.Clone();
+ }
+ }
+ else
+ {
+ ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
+ ci.NumberFormat = (NumberFormatInfo)this.NumberFormat.Clone();
+ }
+
+ if (textInfo != null)
+ {
+ ci.textInfo = (TextInfo)textInfo.Clone();
+ }
+
+ if (calendar != null)
+ {
+ ci.calendar = (Calendar)calendar.Clone();
+ }
+
+ return (ci);
+ }
+
+ public static CultureInfo ReadOnly(CultureInfo ci)
+ {
+ if (ci == null)
+ {
+ throw new ArgumentNullException("ci");
+ }
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ Contract.EndContractBlock();
+
+ if (ci.IsReadOnly)
+ {
+ return (ci);
+ }
+ CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
+
+ if (!ci.IsNeutralCulture)
+ {
+ //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
+ //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
+ if (!ci.m_isInherited)
+ {
+ if (ci.dateTimeInfo != null)
+ {
+ newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo);
+ }
+ if (ci.numInfo != null)
+ {
+ newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo);
+ }
+ }
+ else
+ {
+ newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat);
+ newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
+ }
+ }
+
+ if (ci.textInfo != null)
+ {
+ newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo);
+ }
+
+ if (ci.calendar != null)
+ {
+ newInfo.calendar = Calendar.ReadOnly(ci.calendar);
+ }
+
+ // Don't set the read-only flag too early.
+ // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set.
+ newInfo.m_isReadOnly = true;
+
+ return (newInfo);
+ }
+
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return (m_isReadOnly);
+ }
+ }
+
+ private void VerifyWritable()
+ {
+ if (m_isReadOnly)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ }
+ }
+
+ // For resource lookup, we consider a culture the invariant culture by name equality.
+ // We perform this check frequently during resource lookup, so adding a property for
+ // improved readability.
+ internal bool HasInvariantCultureName
+ {
+ get { return Name == CultureInfo.InvariantCulture.Name; }
+ }
+
+ // Helper function both both overloads of GetCachedReadOnlyCulture.
+ internal static CultureInfo GetCultureInfoHelper(string name)
+ {
+ // There is a race condition in this code with the side effect that the second thread's value
+ // clobbers the first in the dictionary. This is an acceptable race since the CultureInfo objects
+ // are content equal (but not reference equal). Since we make no guarantees there, this race is
+ // acceptable.
+
+ // retval is our return value.
+ CultureInfo retval;
+
+ if (name == null)
+ {
+ return null;
+ }
+
+ // Temporary hashtable for the names.
+ StringCultureInfoDictionary tempNameHT = s_NameCachedCultures;
+
+ name = CultureData.AnsiToLower(name);
+
+ // We expect the same result for both hashtables, but will test individually for added safety.
+ if (tempNameHT == null)
+ {
+ tempNameHT = new StringCultureInfoDictionary();
+ }
+ else
+ {
+ bool ret;
+ lock (m_lock)
+ {
+ ret = tempNameHT.TryGetValue(name, out retval);
+ }
+
+ if (ret && retval != null)
+ {
+ return retval;
+ }
+ }
+ try
+ {
+ retval = new CultureInfo(name, false);
+ }
+ catch (ArgumentException)
+ {
+ return null;
+ }
+
+ // Set it to read-only
+ retval.m_isReadOnly = true;
+
+ // Remember our name (as constructed). Do NOT use alternate sort name versions because
+ // we have internal state representing the sort. (So someone would get the wrong cached version)
+ string newName = CultureData.AnsiToLower(retval.m_name);
+
+ // We add this new culture info object to both tables.
+ lock (m_lock)
+ {
+ tempNameHT[newName] = retval;
+ }
+
+ s_NameCachedCultures = tempNameHT;
+
+ // Finally, return our new CultureInfo object.
+ return retval;
+ }
+
+ // Gets a cached copy of the specified culture from an internal hashtable (or creates it
+ // if not found). (Named version)
+ internal static CultureInfo GetCultureInfo(string name)
+ {
+ // Make sure we have a valid, non-zero length string as name
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ CultureInfo retval = GetCultureInfoHelper(name);
+ if (retval == null)
+ {
+ throw new CultureNotFoundException(
+ "name", name, SR.Argument_CultureNotSupported);
+ }
+ return retval;
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs
new file mode 100644
index 0000000000..740063e4d3
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/CultureNotFoundException.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Threading;
+using System.Runtime.Serialization;
+
+namespace System.Globalization
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class CultureNotFoundException : ArgumentException, ISerializable
+ {
+ private string _invalidCultureName; // unrecognized culture name
+
+ public CultureNotFoundException()
+ : base(DefaultMessage)
+ {
+ }
+
+ public CultureNotFoundException(String message)
+ : base(message)
+ {
+ }
+
+ public CultureNotFoundException(String paramName, String message)
+ : base(message, paramName)
+ {
+ }
+
+ public CultureNotFoundException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public CultureNotFoundException(String paramName, string invalidCultureName, String message)
+ : base(message, paramName)
+ {
+ _invalidCultureName = invalidCultureName;
+ }
+
+ public CultureNotFoundException(String message, string invalidCultureName, Exception innerException)
+ : base(message, innerException)
+ {
+ _invalidCultureName = invalidCultureName;
+ }
+
+ protected CultureNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ _invalidCultureName = (string)info.GetValue("InvalidCultureName", typeof(string));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+
+ base.GetObjectData(info, context);
+ info.AddValue("InvalidCultureName", _invalidCultureName, typeof(string));
+ }
+
+ public virtual string InvalidCultureName
+ {
+ get { return _invalidCultureName; }
+ }
+
+ private static String DefaultMessage
+ {
+ get
+ {
+ return SR.Argument_CultureNotSupported;
+ }
+ }
+
+ private String FormatedInvalidCultureId
+ {
+ get
+ {
+ return InvalidCultureName;
+ }
+ }
+
+ public override String Message
+ {
+ get
+ {
+ String s = base.Message;
+ if (
+ _invalidCultureName != null)
+ {
+ String valueMessage = SR.Format(SR.Argument_CultureInvalidIdentifier, FormatedInvalidCultureId);
+ if (s == null)
+ return valueMessage;
+ return s + Environment.NewLine + valueMessage;
+ }
+ return s;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs
new file mode 100644
index 0000000000..da746ada88
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfo.cs
@@ -0,0 +1,2958 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Text;
+using System.Threading;
+
+namespace System.Globalization
+{
+ //
+ // Flags used to indicate different styles of month names.
+ // This is an internal flag used by internalGetMonthName().
+ // Use flag here in case that we need to provide a combination of these styles
+ // (such as month name of a leap year in genitive form. Not likely for now,
+ // but would like to keep the option open).
+ //
+
+ [Flags]
+ internal enum MonthNameStyles
+ {
+ Regular = 0x00000000,
+ Genitive = 0x00000001,
+ LeapYear = 0x00000002,
+ }
+
+ //
+ // Flags used to indicate special rule used in parsing/formatting
+ // for a specific DateTimeFormatInfo instance.
+ // This is an internal flag.
+ //
+ // This flag is different from MonthNameStyles because this flag
+ // can be expanded to accomodate parsing behaviors like CJK month names
+ // or alternative month names, etc.
+
+ [Flags]
+ internal enum DateTimeFormatFlags
+ {
+ None = 0x00000000,
+ UseGenitiveMonth = 0x00000001,
+ UseLeapYearMonth = 0x00000002,
+ UseSpacesInMonthNames = 0x00000004, // Has spaces or non-breaking space in the month names.
+ UseHebrewRule = 0x00000008, // Format/Parse using the Hebrew calendar rule.
+ UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
+ UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
+
+ NotInitialized = -1,
+ }
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed partial class DateTimeFormatInfo : IFormatProvider, ICloneable
+ {
+ // cache for the invariant culture.
+ // invariantInfo is constant irrespective of your current culture.
+ private static volatile DateTimeFormatInfo s_invariantInfo;
+
+ // an index which points to a record in Culture Data Table.
+ [NonSerialized]
+ private CultureData _cultureData;
+
+ // The culture name used to create this DTFI.
+
+ [OptionalField(VersionAdded = 2)]
+ private String _name = null;
+
+ // The language name of the culture used to create this DTFI.
+ [NonSerialized]
+ private String _langName = null;
+
+ // CompareInfo usually used by the parser.
+ [NonSerialized]
+ private CompareInfo _compareInfo = null;
+
+ // Culture matches current DTFI. mainly used for string comparisons during parsing.
+ [NonSerialized]
+ private CultureInfo _cultureInfo = null;
+
+ //
+ // Caches for various properties.
+ //
+
+ private String amDesignator = null;
+ private String pmDesignator = null;
+
+ private String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
+
+ private String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
+
+ private String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
+
+ private String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
+ private String monthDayPattern = null;
+ // added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM}
+ private String dateTimeOffsetPattern = null;
+
+ //
+ // The following are constant values.
+ //
+ private const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
+
+ // The sortable pattern is based on ISO 8601.
+ private const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
+ private const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
+
+ //
+ // The following are affected by calendar settings.
+ //
+ private Calendar calendar = null;
+
+ private int firstDayOfWeek = -1;
+ private int calendarWeekRule = -1;
+
+
+ private String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
+
+ private String[] abbreviatedDayNames = null;
+
+
+ private String[] m_superShortDayNames = null;
+
+ private String[] dayNames = null;
+ private String[] abbreviatedMonthNames = null;
+ private String[] monthNames = null;
+ // Cache the genitive month names that we retrieve from the data table.
+
+ private String[] genitiveMonthNames = null;
+
+ // Cache the abbreviated genitive month names that we retrieve from the data table.
+
+ private String[] m_genitiveAbbreviatedMonthNames = null;
+
+ // Cache the month names of a leap year that we retrieve from the data table.
+
+ private String[] leapYearMonthNames = null;
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+
+ // The "default" Date/time patterns
+ private String longDatePattern = null;
+ private String shortDatePattern = null;
+ private String yearMonthPattern = null;
+ private String longTimePattern = null;
+ private String shortTimePattern = null;
+
+ [OptionalField(VersionAdded = 3)]
+ private String[] allYearMonthPatterns = null;
+
+ private String[] allShortDatePatterns = null;
+ private String[] allLongDatePatterns = null;
+ private String[] allShortTimePatterns = null;
+ private String[] allLongTimePatterns = null;
+
+ // Cache the era names for this DateTimeFormatInfo instance.
+ private String[] m_eraNames = null;
+ private String[] m_abbrevEraNames = null;
+ private String[] m_abbrevEnglishEraNames = null;
+
+ private CalendarId[] optionalCalendars = null;
+
+ private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
+
+ // CultureInfo updates this
+ internal bool _isReadOnly = false;
+
+ // This flag gives hints about if formatting/parsing should perform special code path for things like
+ // genitive form or leap year month names.
+
+ private DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized;
+
+ private String CultureName
+ {
+ get
+ {
+ if (_name == null)
+ {
+ _name = _cultureData.CultureName;
+ }
+ return (_name);
+ }
+ }
+
+ private CultureInfo Culture
+ {
+ get
+ {
+ if (_cultureInfo == null)
+ {
+ _cultureInfo = CultureInfo.GetCultureInfo(this.CultureName);
+ }
+ return _cultureInfo;
+ }
+ }
+
+ // TODO: This ignores other cultures that might want to do something similar
+ private String LanguageName
+ {
+ get
+ {
+ if (_langName == null)
+ {
+ _langName = _cultureData.SISO639LANGNAME;
+ }
+ return (_langName);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the abbreviated day names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetAbbreviatedDayOfWeekNames()
+ {
+ if (this.abbreviatedDayNames == null)
+ {
+ // Get the abbreviated day names for our current calendar
+ this.abbreviatedDayNames = _cultureData.AbbreviatedDayNames(Calendar.ID);
+ Contract.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week");
+ }
+ return (this.abbreviatedDayNames);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Action: Returns the string array of the one-letter day of week names.
+ // Returns:
+ // an array of one-letter day of week names
+ // Arguments:
+ // None
+ // Exceptions:
+ // None
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetSuperShortDayNames()
+ {
+ if (this.m_superShortDayNames == null)
+ {
+ // Get the super short day names for our current calendar
+ this.m_superShortDayNames = _cultureData.SuperShortDayNames(Calendar.ID);
+ Contract.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week");
+ }
+ return (this.m_superShortDayNames);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the day names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetDayOfWeekNames()
+ {
+ if (this.dayNames == null)
+ {
+ // Get the day names for our current calendar
+ this.dayNames = _cultureData.DayNames(Calendar.ID);
+ Contract.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week");
+ }
+ return (this.dayNames);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the abbreviated month names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetAbbreviatedMonthNames()
+ {
+ if (this.abbreviatedMonthNames == null)
+ {
+ // Get the month names for our current calendar
+ this.abbreviatedMonthNames = _cultureData.AbbreviatedMonthNames(Calendar.ID);
+ Contract.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year");
+ }
+ return (this.abbreviatedMonthNames);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the month names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetMonthNames()
+ {
+ if (this.monthNames == null)
+ {
+ // Get the month names for our current calendar
+ this.monthNames = _cultureData.MonthNames(Calendar.ID);
+ Contract.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13,
+ "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year");
+ }
+
+ return (this.monthNames);
+ }
+
+
+ //
+ // Invariant DateTimeFormatInfo doesn't have user-overriden values
+ // Default calendar is gregorian
+ public DateTimeFormatInfo()
+ : this(CultureInfo.InvariantCulture.m_cultureData,
+ GregorianCalendar.GetDefaultInstance())
+ {
+ }
+
+ internal DateTimeFormatInfo(CultureData cultureData, Calendar cal)
+ {
+ Contract.Requires(cultureData != null);
+ Contract.Requires(cal != null);
+
+ // Remember our culture
+ _cultureData = cultureData;
+
+ this.Calendar = cal;
+ }
+
+ private void InitializeOverridableProperties(CultureData cultureData, CalendarId calendarId)
+ {
+ Contract.Requires(cultureData != null);
+ Contract.Assert(calendarId != CalendarId.UNINITIALIZED_VALUE, "[DateTimeFormatInfo.Populate] Expected initalized calendarId");
+
+ if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; }
+ if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; }
+
+ if (this.amDesignator == null) { this.amDesignator = cultureData.SAM1159; }
+ if (this.pmDesignator == null) { this.pmDesignator = cultureData.SPM2359; }
+ if (this.timeSeparator == null) { this.timeSeparator = cultureData.TimeSeparator; }
+ if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarId); }
+
+ this.allLongTimePatterns = _cultureData.LongTimes;
+ Contract.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns");
+
+ this.allShortTimePatterns = _cultureData.ShortTimes;
+ Contract.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns");
+
+ this.allLongDatePatterns = cultureData.LongDates(calendarId);
+ Contract.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns");
+
+ this.allShortDatePatterns = cultureData.ShortDates(calendarId);
+ Contract.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns");
+
+ this.allYearMonthPatterns = cultureData.YearMonths(calendarId);
+ Contract.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns");
+ }
+
+ [OptionalField(VersionAdded = 1)]
+ private bool _useUserOverride;
+
+ // This was synthesized by Whidbey so we knew what words might appear in the middle of a date string
+ // Now we always synthesize so its not helpful
+
+ internal String[] m_dateWords = null;
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ _name = this.CultureName; // make sure the _name is initialized.
+ _useUserOverride = _cultureData.UseUserOverride;
+
+ // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey
+ // because Whidbey try to initialize some of these fields using calendar data which could be null values
+ // and then we get exceptions. So we call the accessors to force the caches to get loaded.
+ Object o;
+ o = this.LongTimePattern;
+ o = this.LongDatePattern;
+ o = this.ShortTimePattern;
+ o = this.ShortDatePattern;
+ o = this.YearMonthPattern;
+ o = this.AllLongTimePatterns;
+ o = this.AllLongDatePatterns;
+ o = this.AllShortTimePatterns;
+ o = this.AllShortDatePatterns;
+ o = this.AllYearMonthPatterns;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (_name != null)
+ {
+ _cultureData = CultureData.GetCultureData(_name, _useUserOverride);
+ if (_cultureData == null)
+ {
+ throw new CultureNotFoundException("_name", _name, SR.Argument_CultureNotSupported);
+ }
+ }
+
+ if (calendar == null)
+ {
+ calendar = (Calendar)GregorianCalendar.GetDefaultInstance().Clone();
+ calendar.SetReadOnlyState(_isReadOnly);
+ }
+
+ InitializeOverridableProperties(_cultureData, calendar.ID);
+
+ //
+ // turn off read only state till we finish initializing all fields and then store read only state after we are done.
+ //
+ bool isReadOnly = _isReadOnly;
+ _isReadOnly = false;
+
+ // If we deserialized defaults ala Whidbey, make sure they're still defaults
+ // Whidbey's arrays could get a bit mixed up.
+ if (longDatePattern != null) this.LongDatePattern = longDatePattern;
+ if (shortDatePattern != null) this.ShortDatePattern = shortDatePattern;
+ if (yearMonthPattern != null) this.YearMonthPattern = yearMonthPattern;
+ if (longTimePattern != null) this.LongTimePattern = longTimePattern;
+ if (shortTimePattern != null) this.ShortTimePattern = shortTimePattern;
+
+ _isReadOnly = isReadOnly;
+ }
+
+ // Returns a default DateTimeFormatInfo that will be universally
+ // supported and constant irrespective of the current culture.
+ // Used by FromString methods.
+ //
+
+ public static DateTimeFormatInfo InvariantInfo
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
+ if (s_invariantInfo == null)
+ {
+ DateTimeFormatInfo info = new DateTimeFormatInfo();
+ info.Calendar.SetReadOnlyState(true);
+ info._isReadOnly = true;
+ s_invariantInfo = info;
+ }
+ return (s_invariantInfo);
+ }
+ }
+
+ // Returns the current culture's DateTimeFormatInfo. Used by Parse methods.
+ //
+
+ public static DateTimeFormatInfo CurrentInfo
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
+ System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
+ if (!culture.m_isInherited)
+ {
+ DateTimeFormatInfo info = culture.dateTimeInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ }
+ return (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo));
+ }
+ }
+
+
+ public static DateTimeFormatInfo GetInstance(IFormatProvider provider)
+ {
+ // Fast case for a regular CultureInfo
+ DateTimeFormatInfo info;
+ CultureInfo cultureProvider = provider as CultureInfo;
+ if (cultureProvider != null && !cultureProvider.m_isInherited)
+ {
+ return cultureProvider.DateTimeFormat;
+ }
+ // Fast case for a DTFI;
+ info = provider as DateTimeFormatInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ // Wasn't cultureInfo or DTFI, do it the slower way
+ if (provider != null)
+ {
+ info = provider.GetFormat(typeof(DateTimeFormatInfo)) as DateTimeFormatInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ }
+ // Couldn't get anything, just use currentInfo as fallback
+ return CurrentInfo;
+ }
+
+
+ public Object GetFormat(Type formatType)
+ {
+ return (formatType == typeof(DateTimeFormatInfo) ? this : null);
+ }
+
+
+ public Object Clone()
+ {
+ DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone();
+ // We can use the data member calendar in the setter, instead of the property Calendar,
+ // since the cloned copy should have the same state as the original copy.
+ n.calendar = (Calendar)this.Calendar.Clone();
+ n._isReadOnly = false;
+ return n;
+ }
+
+
+ public String AMDesignator
+ {
+ // auto-generated
+ get
+ {
+ if (this.amDesignator == null)
+ {
+ this.amDesignator = _cultureData.SAM1159;
+ }
+ Contract.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null");
+ return (this.amDesignator);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+ amDesignator = value;
+ }
+ }
+
+
+ public Calendar Calendar
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<Calendar>() != null);
+
+ Contract.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null");
+ return (this.calendar);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value", SR.ArgumentNull_Obj);
+ }
+ Contract.EndContractBlock();
+ if (value == calendar)
+ {
+ return;
+ }
+
+ for (int i = 0; i < this.OptionalCalendars.Length; i++)
+ {
+ if (this.OptionalCalendars[i] == value.ID)
+ {
+ // We can use this one, so do so.
+
+ // Clean related properties if we already had a calendar set
+ if (calendar != null)
+ {
+ // clean related properties which are affected by the calendar setting,
+ // so that they will be refreshed when they are accessed next time.
+ //
+
+ // These properites are in the order as appearing in calendar.xml.
+ m_eraNames = null;
+ m_abbrevEraNames = null;
+ m_abbrevEnglishEraNames = null;
+
+ monthDayPattern = null;
+
+ dayNames = null;
+ abbreviatedDayNames = null;
+ m_superShortDayNames = null;
+ monthNames = null;
+ abbreviatedMonthNames = null;
+ genitiveMonthNames = null;
+ m_genitiveAbbreviatedMonthNames = null;
+ leapYearMonthNames = null;
+ formatFlags = DateTimeFormatFlags.NotInitialized;
+
+ allShortDatePatterns = null;
+ allLongDatePatterns = null;
+ allYearMonthPatterns = null;
+ dateTimeOffsetPattern = null;
+
+ // The defaults need reset as well:
+ longDatePattern = null;
+ shortDatePattern = null;
+ yearMonthPattern = null;
+
+ // These properies are not in the OS data, but they are dependent on the values like shortDatePattern.
+ fullDateTimePattern = null; // Long date + long time
+ generalShortTimePattern = null; // short date + short time
+ generalLongTimePattern = null; // short date + long time
+
+ // Derived item that changes
+ dateSeparator = null;
+
+ // We don't need to do these because they are not changed by changing calendar
+ // amDesignator
+ // pmDesignator
+ // timeSeparator
+ // longTimePattern
+ // firstDayOfWeek
+ // calendarWeekRule
+
+ // remember to reload tokens
+ ClearTokenHashTable();
+ }
+
+ // Remember the new calendar
+ calendar = value;
+ InitializeOverridableProperties(_cultureData, calendar.ID);
+
+ // We succeeded, return
+ return;
+ }
+ }
+
+ // The assigned calendar is not a valid calendar for this culture, throw
+ throw new ArgumentOutOfRangeException("value", SR.Argument_InvalidCalendar);
+ }
+ }
+
+ private CalendarId[] OptionalCalendars
+ {
+ get
+ {
+ if (this.optionalCalendars == null)
+ {
+ this.optionalCalendars = _cultureData.CalendarIds;
+ }
+ return (this.optionalCalendars);
+ }
+ }
+
+ /*=================================GetEra==========================
+ **Action: Get the era value by parsing the name of the era.
+ **Returns: The era value for the specified era name.
+ ** -1 if the name of the era is not valid or not supported.
+ **Arguments: eraName the name of the era.
+ **Exceptions: None.
+ ============================================================================*/
+
+
+ public int GetEra(String eraName)
+ {
+ if (eraName == null)
+ {
+ throw new ArgumentNullException("eraName",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ // The Era Name and Abbreviated Era Name
+ // for Taiwan Calendar on non-Taiwan SKU returns empty string (which
+ // would be matched below) but we don't want the empty string to give
+ // us an Era number
+ // confer 85900 DTFI.GetEra("") should fail on all cultures
+ if (eraName.Length == 0)
+ {
+ return (-1);
+ }
+
+ // The following is based on the assumption that the era value is starting from 1, and has a
+ // serial values.
+ // If that ever changes, the code has to be changed.
+
+ // The calls to String.Compare should use the current culture for the string comparisons, but the
+ // invariant culture when comparing against the english names.
+ for (int i = 0; i < EraNames.Length; i++)
+ {
+ // Compare the era name in a case-insensitive way for the appropriate culture.
+ if (m_eraNames[i].Length > 0)
+ {
+ if (this.Culture.CompareInfo.Compare(eraName, m_eraNames[i], CompareOptions.IgnoreCase) == 0)
+ {
+ return (i + 1);
+ }
+ }
+ }
+ for (int i = 0; i < AbbreviatedEraNames.Length; i++)
+ {
+ // Compare the abbreviated era name in a case-insensitive way for the appropriate culture.
+ if (this.Culture.CompareInfo.Compare(eraName, m_abbrevEraNames[i], CompareOptions.IgnoreCase) == 0)
+ {
+ return (i + 1);
+ }
+ }
+ for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++)
+ {
+ // this comparison should use the InvariantCulture. The English name could have linguistically
+ // interesting characters.
+ if (CultureInfo.InvariantCulture.CompareInfo.Compare(eraName, m_abbrevEnglishEraNames[i], CompareOptions.IgnoreCase) == 0)
+ {
+ return (i + 1);
+ }
+ }
+ return (-1);
+ }
+
+
+ internal String[] EraNames
+ {
+ get
+ {
+ if (this.m_eraNames == null)
+ {
+ this.m_eraNames = _cultureData.EraNames(Calendar.ID); ;
+ }
+ return (this.m_eraNames);
+ }
+ }
+
+ /*=================================GetEraName==========================
+ **Action: Get the name of the era for the specified era value.
+ **Returns: The name of the specified era.
+ **Arguments:
+ ** era the era value.
+ **Exceptions:
+ ** ArguementException if the era valie is invalid.
+ ============================================================================*/
+
+ // Era names are 1 indexed
+ public String GetEraName(int era)
+ {
+ if (era == Calendar.CurrentEra)
+ {
+ era = Calendar.CurrentEraValue;
+ }
+
+ // The following is based on the assumption that the era value is starting from 1, and has a
+ // serial values.
+ // If that ever changes, the code has to be changed.
+ if ((--era) < EraNames.Length && (era >= 0))
+ {
+ return (m_eraNames[era]);
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal String[] AbbreviatedEraNames
+ {
+ get
+ {
+ if (this.m_abbrevEraNames == null)
+ {
+ this.m_abbrevEraNames = _cultureData.AbbrevEraNames(Calendar.ID);
+ }
+ return (this.m_abbrevEraNames);
+ }
+ }
+
+ // Era names are 1 indexed
+ public String GetAbbreviatedEraName(int era)
+ {
+ if (AbbreviatedEraNames.Length == 0)
+ {
+ // If abbreviation era name is not used in this culture,
+ // return the full era name.
+ return (GetEraName(era));
+ }
+ if (era == Calendar.CurrentEra)
+ {
+ era = Calendar.CurrentEraValue;
+ }
+ if ((--era) < m_abbrevEraNames.Length && (era >= 0))
+ {
+ return (m_abbrevEraNames[era]);
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal String[] AbbreviatedEnglishEraNames
+ {
+ get
+ {
+ if (this.m_abbrevEnglishEraNames == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0");
+ this.m_abbrevEnglishEraNames = _cultureData.AbbreviatedEnglishEraNames(Calendar.ID);
+ }
+ return (this.m_abbrevEnglishEraNames);
+ }
+ }
+
+
+ // Note that cultureData derives this from the short date format (unless someone's set this previously)
+ // Note that this property is quite undesirable.
+ internal String DateSeparator
+ {
+ get
+ {
+ if (this.dateSeparator == null)
+ {
+ this.dateSeparator = _cultureData.DateSeparator(Calendar.ID);
+ }
+ Contract.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null");
+ return (this.dateSeparator);
+ }
+ set
+ {
+ throw null;
+ }
+ }
+
+
+ public DayOfWeek FirstDayOfWeek
+ {
+ get
+ {
+ if (this.firstDayOfWeek == -1)
+ {
+ this.firstDayOfWeek = _cultureData.IFIRSTDAYOFWEEK;
+ }
+ Contract.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1");
+
+ return ((DayOfWeek)this.firstDayOfWeek);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value >= DayOfWeek.Sunday && value <= DayOfWeek.Saturday)
+ {
+ firstDayOfWeek = (int)value;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(
+ "value", SR.Format(SR.ArgumentOutOfRange_Range,
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ }
+ }
+
+ public CalendarWeekRule CalendarWeekRule
+ {
+ get
+ {
+ if (this.calendarWeekRule == -1)
+ {
+ this.calendarWeekRule = _cultureData.IFIRSTWEEKOFYEAR;
+ }
+ Contract.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1");
+ return ((CalendarWeekRule)this.calendarWeekRule);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value >= CalendarWeekRule.FirstDay && value <= CalendarWeekRule.FirstFourDayWeek)
+ {
+ calendarWeekRule = (int)value;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(
+ "value", SR.Format(SR.ArgumentOutOfRange_Range,
+ CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
+ }
+ }
+ }
+
+ public String FullDateTimePattern
+ {
+ get
+ {
+ if (fullDateTimePattern == null)
+ {
+ fullDateTimePattern = LongDatePattern + " " + LongTimePattern;
+ }
+ return (fullDateTimePattern);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ fullDateTimePattern = value;
+ }
+ }
+
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String LongDatePattern
+ {
+ get
+ {
+ // Initialize our long date pattern from the 1st array value if not set
+ if (this.longDatePattern == null)
+ {
+ // Initialize our data
+ this.longDatePattern = this.UnclonedLongDatePatterns[0];
+ }
+
+ return this.longDatePattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.longDatePattern = value;
+
+ // Clear the token hash table
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ this.fullDateTimePattern = null;
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String LongTimePattern
+ {
+ get
+ {
+ // Initialize our long time pattern from the 1st array value if not set
+ if (this.longTimePattern == null)
+ {
+ // Initialize our data
+ this.longTimePattern = this.UnclonedLongTimePatterns[0];
+ }
+
+ return this.longTimePattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.longTimePattern = value;
+
+ // Clear the token hash table
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ this.fullDateTimePattern = null; // Full date = long date + long Time
+ this.generalLongTimePattern = null; // General long date = short date + long Time
+ this.dateTimeOffsetPattern = null;
+ }
+ }
+
+
+ // Note: just to be confusing there's only 1 month day pattern, not a whole list
+ public String MonthDayPattern
+ {
+ get
+ {
+ if (this.monthDayPattern == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0");
+ this.monthDayPattern = _cultureData.MonthDay(Calendar.ID);
+ }
+ Contract.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null");
+ return (this.monthDayPattern);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ this.monthDayPattern = value;
+ }
+ }
+
+
+ public String PMDesignator
+ {
+ // auto-generated
+ get
+ {
+ if (this.pmDesignator == null)
+ {
+ this.pmDesignator = _cultureData.SPM2359;
+ }
+ Contract.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null");
+ return (this.pmDesignator);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+
+ pmDesignator = value;
+ }
+ }
+
+
+ public String RFC1123Pattern
+ {
+ get
+ {
+ return (rfc1123Pattern);
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String ShortDatePattern
+ {
+ get
+ {
+ // Initialize our short date pattern from the 1st array value if not set
+ if (this.shortDatePattern == null)
+ {
+ // Initialize our data
+ this.shortDatePattern = this.UnclonedShortDatePatterns[0];
+ }
+
+ return this.shortDatePattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.shortDatePattern = value;
+
+ // Clear the token hash table, note that even short dates could require this
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ generalLongTimePattern = null; // General long time = short date + long time
+ generalShortTimePattern = null; // General short time = short date + short Time
+ dateTimeOffsetPattern = null;
+ }
+ }
+
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String ShortTimePattern
+ {
+ get
+ {
+ // Initialize our short time pattern from the 1st array value if not set
+ if (this.shortTimePattern == null)
+ {
+ // Initialize our data
+ this.shortTimePattern = this.UnclonedShortTimePatterns[0];
+ }
+ return this.shortTimePattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.shortTimePattern = value;
+
+ // Clear the token hash table, note that even short times could require this
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ generalShortTimePattern = null; // General short date = short date + short time.
+ }
+ }
+
+
+ public String SortableDateTimePattern
+ {
+ get
+ {
+ return (sortableDateTimePattern);
+ }
+ }
+
+ /*=================================GeneralShortTimePattern=====================
+ **Property: Return the pattern for 'g' general format: shortDate + short time
+ **Note: This is used by DateTimeFormat.cs to get the pattern for 'g'
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody asks for the general format.
+ ==============================================================================*/
+
+ internal String GeneralShortTimePattern
+ {
+ get
+ {
+ if (generalShortTimePattern == null)
+ {
+ generalShortTimePattern = ShortDatePattern + " " + ShortTimePattern;
+ }
+ return (generalShortTimePattern);
+ }
+ }
+
+ /*=================================GeneralLongTimePattern=====================
+ **Property: Return the pattern for 'g' general format: shortDate + Long time
+ **Note: This is used by DateTimeFormat.cs to get the pattern for 'g'
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody asks for the general format.
+ ==============================================================================*/
+
+ internal String GeneralLongTimePattern
+ {
+ get
+ {
+ if (generalLongTimePattern == null)
+ {
+ generalLongTimePattern = ShortDatePattern + " " + LongTimePattern;
+ }
+ return (generalLongTimePattern);
+ }
+ }
+
+ /*=================================DateTimeOffsetPattern==========================
+ **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset
+ **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody uses this form
+ ==============================================================================*/
+
+ /*=================================DateTimeOffsetPattern==========================
+ **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset
+ **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody uses this form
+ ==============================================================================*/
+
+ internal String DateTimeOffsetPattern
+ {
+ get
+ {
+ if (dateTimeOffsetPattern == null)
+ {
+ string dateTimePattern = ShortDatePattern + " " + LongTimePattern;
+
+ /* LongTimePattern might contain a "z" as part of the format string in which case we don't want to append a time zone offset */
+
+ bool foundZ = false;
+ bool inQuote = false;
+ char quote = '\'';
+ for (int i = 0; !foundZ && i < LongTimePattern.Length; i++)
+ {
+ switch (LongTimePattern[i])
+ {
+ case 'z':
+ /* if we aren't in a quote, we've found a z */
+ foundZ = !inQuote;
+ /* we'll fall out of the loop now because the test includes !foundZ */
+ break;
+ case '\'':
+ case '\"':
+ if (inQuote && (quote == LongTimePattern[i]))
+ {
+ /* we were in a quote and found a matching exit quote, so we are outside a quote now */
+ inQuote = false;
+ }
+ else if (!inQuote)
+ {
+ quote = LongTimePattern[i];
+ inQuote = true;
+ }
+ else
+ {
+ /* we were in a quote and saw the other type of quote character, so we are still in a quote */
+ }
+ break;
+ case '%':
+ case '\\':
+ i++; /* skip next character that is escaped by this backslash */
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!foundZ)
+ {
+ dateTimePattern = dateTimePattern + " zzz";
+ }
+
+ dateTimeOffsetPattern = dateTimePattern;
+ }
+ return (dateTimeOffsetPattern);
+ }
+ }
+
+ // Note that cultureData derives this from the long time format (unless someone's set this previously)
+ // Note that this property is quite undesirable.
+ internal String TimeSeparator
+ {
+ get
+ {
+ if (timeSeparator == null)
+ {
+ timeSeparator = _cultureData.TimeSeparator;
+ }
+ Contract.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null");
+ return (timeSeparator);
+ }
+
+ set
+ {
+ throw null;
+ }
+ }
+
+
+ public String UniversalSortableDateTimePattern
+ {
+ get
+ {
+ return (universalSortableDateTimePattern);
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String YearMonthPattern
+ {
+ get
+ {
+ // Initialize our year/month pattern from the 1st array value if not set
+ if (this.yearMonthPattern == null)
+ {
+ // Initialize our data
+ this.yearMonthPattern = this.UnclonedYearMonthPatterns[0];
+ }
+ return this.yearMonthPattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.yearMonthPattern = value;
+
+ // Clear the token hash table, note that even short times could require this
+ ClearTokenHashTable();
+ }
+ }
+
+ //
+ // Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value"
+ //
+ private static void CheckNullValue(String[] values, int length)
+ {
+ Contract.Requires(values != null, "value != null");
+ Contract.Requires(values.Length >= length);
+ for (int i = 0; i < length; i++)
+ {
+ if (values[i] == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_ArrayValue);
+ }
+ }
+ }
+
+
+ public String[] AbbreviatedDayNames
+ {
+ get
+ {
+ return ((String[])internalGetAbbreviatedDayOfWeekNames().Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 7)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ ClearTokenHashTable();
+
+ abbreviatedDayNames = value;
+ }
+ }
+
+ // Returns the string array of the one-letter day of week names.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] ShortestDayNames
+ {
+ get
+ {
+ return ((String[])internalGetSuperShortDayNames().Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 7)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ this.m_superShortDayNames = value;
+ }
+ }
+
+
+ public String[] DayNames
+ {
+ get
+ {
+ return ((String[])internalGetDayOfWeekNames().Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 7)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ ClearTokenHashTable();
+
+ dayNames = value;
+ }
+ }
+
+
+ public String[] AbbreviatedMonthNames
+ {
+ get
+ {
+ return ((String[])internalGetAbbreviatedMonthNames().Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ ClearTokenHashTable();
+ abbreviatedMonthNames = value;
+ }
+ }
+
+
+ public String[] MonthNames
+ {
+ get
+ {
+ return ((String[])internalGetMonthNames().Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ monthNames = value;
+ ClearTokenHashTable();
+ }
+ }
+
+ // Whitespaces that we allow in the month names.
+ // U+00a0 is non-breaking space.
+ private static readonly char[] s_monthSpaces = { ' ', '\u00a0' };
+
+ internal bool HasSpacesInMonthNames
+ {
+ get
+ {
+ return (FormatFlags & DateTimeFormatFlags.UseSpacesInMonthNames) != 0;
+ }
+ }
+
+ internal bool HasSpacesInDayNames
+ {
+ get
+ {
+ return (FormatFlags & DateTimeFormatFlags.UseSpacesInDayNames) != 0;
+ }
+ }
+
+
+ //
+ // internalGetMonthName
+ //
+ // Actions: Return the month name using the specified MonthNameStyles in either abbreviated form
+ // or full form.
+ // Arguments:
+ // month
+ // style To indicate a form like regular/genitive/month name in a leap year.
+ // abbreviated When true, return abbreviated form. Otherwise, return a full form.
+ // Exceptions:
+ // ArgumentOutOfRangeException When month name is invalid.
+ //
+ internal String internalGetMonthName(int month, MonthNameStyles style, bool abbreviated)
+ {
+ //
+ // Right now, style is mutual exclusive, but I make the style to be flag so that
+ // maybe we can combine flag if there is such a need.
+ //
+ String[] monthNamesArray = null;
+ switch (style)
+ {
+ case MonthNameStyles.Genitive:
+ monthNamesArray = internalGetGenitiveMonthNames(abbreviated);
+ break;
+ case MonthNameStyles.LeapYear:
+ monthNamesArray = internalGetLeapYearMonthNames(/*abbreviated*/);
+ break;
+ default:
+ monthNamesArray = (abbreviated ? internalGetAbbreviatedMonthNames() : internalGetMonthNames());
+ break;
+ }
+ // The month range is from 1 ~ this.m_monthNames.Length
+ // (actually is 13 right now for all cases)
+ if ((month < 1) || (month > monthNamesArray.Length))
+ {
+ throw new ArgumentOutOfRangeException(
+ "month", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, monthNamesArray.Length));
+ }
+ return (monthNamesArray[month - 1]);
+ }
+
+ //
+ // internalGetGenitiveMonthNames
+ //
+ // Action: Retrieve the array which contains the month names in genitive form.
+ // If this culture does not use the gentive form, the normal month name is returned.
+ // Arguments:
+ // abbreviated When true, return abbreviated form. Otherwise, return a full form.
+ //
+ private String[] internalGetGenitiveMonthNames(bool abbreviated)
+ {
+ if (abbreviated)
+ {
+ if (this.m_genitiveAbbreviatedMonthNames == null)
+ {
+ this.m_genitiveAbbreviatedMonthNames = _cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID);
+ Contract.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year");
+ }
+ return (this.m_genitiveAbbreviatedMonthNames);
+ }
+
+ if (this.genitiveMonthNames == null)
+ {
+ this.genitiveMonthNames = _cultureData.GenitiveMonthNames(this.Calendar.ID);
+ Contract.Assert(this.genitiveMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year");
+ }
+ return (this.genitiveMonthNames);
+ }
+
+ //
+ // internalGetLeapYearMonthNames
+ //
+ // Actions: Retrieve the month names used in a leap year.
+ // If this culture does not have different month names in a leap year, the normal month name is returned.
+ // Agruments: None. (can use abbreviated later if needed)
+ //
+ internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/)
+ {
+ if (this.leapYearMonthNames == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0");
+ this.leapYearMonthNames = _cultureData.LeapYearMonthNames(Calendar.ID);
+ Contract.Assert(this.leapYearMonthNames.Length == 13,
+ "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names");
+ }
+ return (leapYearMonthNames);
+ }
+
+
+ public String GetAbbreviatedDayName(DayOfWeek dayofweek)
+ {
+ if ((int)dayofweek < 0 || (int)dayofweek > 6)
+ {
+ throw new ArgumentOutOfRangeException(
+ "dayofweek", SR.Format(SR.ArgumentOutOfRange_Range,
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+ //
+ // Don't call the public property AbbreviatedDayNames here since a clone is needed in that
+ // property, so it will be slower. Instead, use GetAbbreviatedDayOfWeekNames() directly.
+ //
+ return (internalGetAbbreviatedDayOfWeekNames()[(int)dayofweek]);
+ }
+
+ // Get all possible combination of inputs
+ private static String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString)
+ {
+ Contract.Requires(patterns1 != null);
+ Contract.Requires(patterns2 != null);
+
+ // Get array size
+ String[] result = new String[patterns1.Length * patterns2.Length];
+
+ // Counter of actual results
+ int k = 0;
+ for (int i = 0; i < patterns1.Length; i++)
+ {
+ for (int j = 0; j < patterns2.Length; j++)
+ {
+ // Can't combine if null or empty
+ result[k++] = patterns1[i] + connectString + patterns2[j];
+ }
+ }
+
+ // Return the combinations
+ return (result);
+ }
+
+
+ // auto-generated
+ internal String[] GetAllDateTimePatterns(char format)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ String[] result = null;
+
+ switch (format)
+ {
+ case 'd':
+ result = this.AllShortDatePatterns;
+ break;
+ case 'D':
+ result = this.AllLongDatePatterns;
+ break;
+ case 'f':
+ result = GetCombinedPatterns(AllLongDatePatterns, AllShortTimePatterns, " ");
+ break;
+ case 'F':
+ case 'U':
+ result = GetCombinedPatterns(AllLongDatePatterns, AllLongTimePatterns, " ");
+ break;
+ case 'g':
+ result = GetCombinedPatterns(AllShortDatePatterns, AllShortTimePatterns, " ");
+ break;
+ case 'G':
+ result = GetCombinedPatterns(AllShortDatePatterns, AllLongTimePatterns, " ");
+ break;
+ case 'm':
+ case 'M':
+ result = new String[] { MonthDayPattern };
+ break;
+ case 'o':
+ case 'O':
+ result = new String[] { RoundtripFormat };
+ break;
+ case 'r':
+ case 'R':
+ result = new String[] { rfc1123Pattern };
+ break;
+ case 's':
+ result = new String[] { sortableDateTimePattern };
+ break;
+ case 't':
+ result = this.AllShortTimePatterns;
+ break;
+ case 'T':
+ result = this.AllLongTimePatterns;
+ break;
+ case 'u':
+ result = new String[] { UniversalSortableDateTimePattern };
+ break;
+ case 'y':
+ case 'Y':
+ result = this.AllYearMonthPatterns;
+ break;
+ default:
+ throw new ArgumentException(SR.Format_BadFormatSpecifier, "format");
+ }
+ return (result);
+ }
+
+
+ public String GetDayName(DayOfWeek dayofweek)
+ {
+ if ((int)dayofweek < 0 || (int)dayofweek > 6)
+ {
+ throw new ArgumentOutOfRangeException(
+ "dayofweek", SR.Format(SR.ArgumentOutOfRange_Range,
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+
+ // Use the internal one so that we don't clone the array unnecessarily
+ return (internalGetDayOfWeekNames()[(int)dayofweek]);
+ }
+
+
+
+ public String GetAbbreviatedMonthName(int month)
+ {
+ if (month < 1 || month > 13)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, 13));
+ }
+ Contract.EndContractBlock();
+ // Use the internal one so we don't clone the array unnecessarily
+ return (internalGetAbbreviatedMonthNames()[month - 1]);
+ }
+
+
+ public String GetMonthName(int month)
+ {
+ if (month < 1 || month > 13)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, 13));
+ }
+ Contract.EndContractBlock();
+ // Use the internal one so we don't clone the array unnecessarily
+ return (internalGetMonthNames()[month - 1]);
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ //
+ // The resulting [] can get returned to the calling app, so clone it.
+ private static string[] GetMergedPatterns(string[] patterns, string defaultPattern)
+ {
+ Contract.Assert(patterns != null && patterns.Length > 0,
+ "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern");
+ Contract.Assert(defaultPattern != null,
+ "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string");
+
+ // If the default happens to be the first in the list just return (a cloned) copy
+ if (defaultPattern == patterns[0])
+ {
+ return (string[])patterns.Clone();
+ }
+
+ // We either need a bigger list, or the pattern from the list.
+ int i;
+ for (i = 0; i < patterns.Length; i++)
+ {
+ // Stop if we found it
+ if (defaultPattern == patterns[i])
+ break;
+ }
+
+ // Either way we're going to need a new array
+ string[] newPatterns;
+
+ // Did we find it
+ if (i < patterns.Length)
+ {
+ // Found it, output will be same size
+ newPatterns = (string[])patterns.Clone();
+
+ // Have to move [0] item to [i] so we can re-write default at [0]
+ // (remember defaultPattern == [i] so this is OK)
+ newPatterns[i] = newPatterns[0];
+ }
+ else
+ {
+ // Not found, make room for it
+ newPatterns = new String[patterns.Length + 1];
+
+ // Copy existing array
+ Array.Copy(patterns, 0, newPatterns, 1, patterns.Length);
+ }
+
+ // Remember the default
+ newPatterns[0] = defaultPattern;
+
+ // Return the reconstructed list
+ return newPatterns;
+ }
+
+ // Needed by DateTimeFormatInfo and DateTimeFormat
+ internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+
+ // Default string isn't necessarily in our string array, so get the
+ // merged patterns of both
+ private String[] AllYearMonthPatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedYearMonthPatterns, this.YearMonthPattern);
+ }
+ }
+
+ private String[] AllShortDatePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedShortDatePatterns, this.ShortDatePattern);
+ }
+ }
+
+ private String[] AllShortTimePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedShortTimePatterns, this.ShortTimePattern);
+ }
+ }
+
+ private String[] AllLongDatePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedLongDatePatterns, this.LongDatePattern);
+ }
+ }
+
+ private String[] AllLongTimePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedLongTimePatterns, this.LongTimePattern);
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllYearMonthPatterns
+ private String[] UnclonedYearMonthPatterns
+ {
+ get
+ {
+ if (this.allYearMonthPatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0");
+ this.allYearMonthPatterns = _cultureData.YearMonths(this.Calendar.ID);
+ Contract.Assert(this.allYearMonthPatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns");
+ }
+
+ return this.allYearMonthPatterns;
+ }
+ }
+
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllShortDatePatterns
+ private String[] UnclonedShortDatePatterns
+ {
+ get
+ {
+ if (allShortDatePatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0");
+ this.allShortDatePatterns = _cultureData.ShortDates(this.Calendar.ID);
+ Contract.Assert(this.allShortDatePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns");
+ }
+
+ return this.allShortDatePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllLongDatePatterns
+ private String[] UnclonedLongDatePatterns
+ {
+ get
+ {
+ if (allLongDatePatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0");
+ this.allLongDatePatterns = _cultureData.LongDates(this.Calendar.ID);
+ Contract.Assert(this.allLongDatePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns");
+ }
+
+ return this.allLongDatePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllShortTimePatterns
+ private String[] UnclonedShortTimePatterns
+ {
+ get
+ {
+ if (this.allShortTimePatterns == null)
+ {
+ this.allShortTimePatterns = _cultureData.ShortTimes;
+ Contract.Assert(this.allShortTimePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns");
+ }
+
+ return this.allShortTimePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllLongTimePatterns
+ private String[] UnclonedLongTimePatterns
+ {
+ get
+ {
+ if (this.allLongTimePatterns == null)
+ {
+ this.allLongTimePatterns = _cultureData.LongTimes;
+ Contract.Assert(this.allLongTimePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns");
+ }
+
+ return this.allLongTimePatterns;
+ }
+ }
+
+ public static DateTimeFormatInfo ReadOnly(DateTimeFormatInfo dtfi)
+ {
+ if (dtfi == null)
+ {
+ throw new ArgumentNullException("dtfi",
+ SR.ArgumentNull_Obj);
+ }
+ Contract.EndContractBlock();
+ if (dtfi.IsReadOnly)
+ {
+ return (dtfi);
+ }
+ DateTimeFormatInfo newInfo = (DateTimeFormatInfo)(dtfi.MemberwiseClone());
+ // We can use the data member calendar in the setter, instead of the property Calendar,
+ // since the cloned copy should have the same state as the original copy.
+ newInfo.calendar = Calendar.ReadOnly(dtfi.Calendar);
+ newInfo._isReadOnly = true;
+ return (newInfo);
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return (_isReadOnly);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] AbbreviatedMonthGenitiveNames
+ {
+ get
+ {
+ return ((String[])internalGetGenitiveMonthNames(true).Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ ClearTokenHashTable();
+ this.m_genitiveAbbreviatedMonthNames = value;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] MonthGenitiveNames
+ {
+ get
+ {
+ return ((String[])internalGetGenitiveMonthNames(false).Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ SR.ArgumentNull_Array);
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidArrayLength, 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ genitiveMonthNames = value;
+ ClearTokenHashTable();
+ }
+ }
+
+ //
+ // Positive TimeSpan Pattern
+ //
+
+ private string _fullTimeSpanPositivePattern;
+ internal String FullTimeSpanPositivePattern
+ {
+ get
+ {
+ if (_fullTimeSpanPositivePattern == null)
+ {
+ CultureData cultureDataWithoutUserOverrides;
+ if (_cultureData.UseUserOverride)
+ cultureDataWithoutUserOverrides = CultureData.GetCultureData(_cultureData.CultureName, false);
+ else
+ cultureDataWithoutUserOverrides = _cultureData;
+ String decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
+
+ _fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF";
+ }
+ return _fullTimeSpanPositivePattern;
+ }
+ }
+
+ //
+ // Negative TimeSpan Pattern
+ //
+
+ private string _fullTimeSpanNegativePattern;
+ internal String FullTimeSpanNegativePattern
+ {
+ get
+ {
+ if (_fullTimeSpanNegativePattern == null)
+ _fullTimeSpanNegativePattern = "'-'" + FullTimeSpanPositivePattern;
+ return _fullTimeSpanNegativePattern;
+ }
+ }
+
+ //
+ // Get suitable CompareInfo from current DTFI object.
+ //
+ internal CompareInfo CompareInfo
+ {
+ get
+ {
+ if (_compareInfo == null)
+ {
+ // We use the regular GetCompareInfo here to make sure the created CompareInfo object is stored in the
+ // CompareInfo cache. otherwise we would just create CompareInfo using _cultureData.
+ _compareInfo = CompareInfo.GetCompareInfo(_cultureData.SCOMPAREINFO);
+ }
+
+ return _compareInfo;
+ }
+ }
+
+
+ internal const DateTimeStyles InvalidDateTimeStyles = ~(DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite
+ | DateTimeStyles.AllowInnerWhite | DateTimeStyles.NoCurrentDateDefault
+ | DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal
+ | DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind);
+
+ internal static void ValidateStyles(DateTimeStyles style, String parameterName)
+ {
+ if ((style & InvalidDateTimeStyles) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidDateTimeStyles, parameterName);
+ }
+ if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0))
+ {
+ throw new ArgumentException(SR.Argument_ConflictingDateTimeStyles, parameterName);
+ }
+ Contract.EndContractBlock();
+ if (((style & DateTimeStyles.RoundtripKind) != 0)
+ && ((style & (DateTimeStyles.AssumeLocal | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)) != 0))
+ {
+ throw new ArgumentException(SR.Argument_ConflictingDateTimeRoundtripStyles, parameterName);
+ }
+ }
+
+ //
+ // Actions: Return the internal flag used in formatting and parsing.
+ // The flag can be used to indicate things like if genitive forms is used in this DTFi, or if leap year gets different month names.
+ //
+ internal DateTimeFormatFlags FormatFlags
+ {
+ get
+ {
+ if (formatFlags == DateTimeFormatFlags.NotInitialized)
+ {
+ // Build the format flags from the data in this DTFI
+ formatFlags = DateTimeFormatFlags.None;
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagGenitiveMonth(
+ MonthNames, internalGetGenitiveMonthNames(false), AbbreviatedMonthNames, internalGetGenitiveMonthNames(true));
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInMonthNames(
+ MonthNames, internalGetGenitiveMonthNames(false), AbbreviatedMonthNames, internalGetGenitiveMonthNames(true));
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInDayNames(DayNames, AbbreviatedDayNames);
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseHebrewCalendar((int)Calendar.ID);
+ }
+ return (formatFlags);
+ }
+ }
+
+ internal Boolean HasForceTwoDigitYears
+ {
+ get
+ {
+ switch (calendar.ID)
+ {
+ // Handle Japanese and Taiwan cases.
+ // If is y/yy, do not get (year % 100). "y" will print
+ // year without leading zero. "yy" will print year with two-digit in leading zero.
+ // If pattern is yyy/yyyy/..., print year value with two-digit in leading zero.
+ // So year 5 is "05", and year 125 is "125".
+ // The reason for not doing (year % 100) is for Taiwan calendar.
+ // If year 125, then output 125 and not 25.
+ // Note: OS uses "yyyy" for Taiwan calendar by default.
+ case (CalendarId.JAPAN):
+ case (CalendarId.TAIWAN):
+ return true;
+ }
+ return false;
+ }
+ }
+
+ // Returns whether the YearMonthAdjustment function has any fix-up work to do for this culture/calendar.
+ internal Boolean HasYearMonthAdjustment
+ {
+ get
+ {
+ return ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0);
+ }
+ }
+
+ // This is a callback that the parser can make back into the DTFI to let it fiddle with special
+ // cases associated with that culture or calendar. Currently this only has special cases for
+ // the Hebrew calendar, but this could be extended to other cultures.
+ //
+ // The return value is whether the year and month are actually valid for this calendar.
+ internal Boolean YearMonthAdjustment(ref int year, ref int month, Boolean parsedMonthName)
+ {
+ if ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0)
+ {
+ // Special rules to fix up the Hebrew year/month
+
+ // When formatting, we only format up to the hundred digit of the Hebrew year, although Hebrew year is now over 5000.
+ // E.g. if the year is 5763, we only format as 763.
+ if (year < 1000)
+ {
+ year += 5000;
+ }
+
+ // Because we need to calculate leap year, we should fall out now for an invalid year.
+ if (year < Calendar.GetYear(Calendar.MinSupportedDateTime) || year > Calendar.GetYear(Calendar.MaxSupportedDateTime))
+ {
+ return false;
+ }
+
+ // To handle leap months, the set of month names in the symbol table does not always correspond to the numbers.
+ // For non-leap years, month 7 (Adar Bet) is not present, so we need to make using this month invalid and
+ // shuffle the other months down.
+ if (parsedMonthName)
+ {
+ if (!Calendar.IsLeapYear(year))
+ {
+ if (month >= 8)
+ {
+ month--;
+ }
+ else if (month == 7)
+ {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ //
+ // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens.
+ //
+
+ private TokenHashValue[] _dtfiTokenHash;
+
+ private const int TOKEN_HASH_SIZE = 199;
+ private const int SECOND_PRIME = 197;
+ private const String dateSeparatorOrTimeZoneOffset = "-";
+ private const String invariantDateSeparator = "/";
+ private const String invariantTimeSeparator = ":";
+
+ //
+ // Common Ignorable Symbols
+ //
+ internal const String IgnorablePeriod = ".";
+ internal const String IgnorableComma = ",";
+
+ //
+ // Year/Month/Day suffixes
+ //
+ internal const String CJKYearSuff = "\u5e74";
+ internal const String CJKMonthSuff = "\u6708";
+ internal const String CJKDaySuff = "\u65e5";
+
+ internal const String KoreanYearSuff = "\ub144";
+ internal const String KoreanMonthSuff = "\uc6d4";
+ internal const String KoreanDaySuff = "\uc77c";
+
+ internal const String KoreanHourSuff = "\uc2dc";
+ internal const String KoreanMinuteSuff = "\ubd84";
+ internal const String KoreanSecondSuff = "\ucd08";
+
+ internal const String CJKHourSuff = "\u6642";
+ internal const String ChineseHourSuff = "\u65f6";
+
+ internal const String CJKMinuteSuff = "\u5206";
+ internal const String CJKSecondSuff = "\u79d2";
+
+ internal const String LocalTimeMark = "T";
+
+ internal const String GMTName = "GMT";
+ internal const String ZuluName = "Z";
+
+ internal const String KoreanLangName = "ko";
+ internal const String JapaneseLangName = "ja";
+ internal const String EnglishLangName = "en";
+
+ private static volatile DateTimeFormatInfo s_jajpDTFI;
+ private static volatile DateTimeFormatInfo s_zhtwDTFI;
+
+ //
+ // Create a Japanese DTFI which uses JapaneseCalendar. This is used to parse
+ // date string with Japanese era name correctly even when the supplied DTFI
+ // does not use Japanese calendar.
+ // The created instance is stored in global s_jajpDTFI.
+ //
+ internal static DateTimeFormatInfo GetJapaneseCalendarDTFI()
+ {
+ DateTimeFormatInfo temp = s_jajpDTFI;
+ if (temp == null)
+ {
+ temp = new CultureInfo("ja-JP", false).DateTimeFormat;
+ temp.Calendar = JapaneseCalendar.GetDefaultInstance();
+ s_jajpDTFI = temp;
+ }
+ return (temp);
+ }
+
+ // Create a Taiwan DTFI which uses TaiwanCalendar. This is used to parse
+ // date string with era name correctly even when the supplied DTFI
+ // does not use Taiwan calendar.
+ // The created instance is stored in global s_zhtwDTFI.
+ internal static DateTimeFormatInfo GetTaiwanCalendarDTFI()
+ {
+ DateTimeFormatInfo temp = s_zhtwDTFI;
+ if (temp == null)
+ {
+ temp = new CultureInfo("zh-TW", false).DateTimeFormat;
+ temp.Calendar = TaiwanCalendar.GetDefaultInstance();
+ s_zhtwDTFI = temp;
+ }
+ return (temp);
+ }
+
+
+ // DTFI properties should call this when the setter are called.
+ private void ClearTokenHashTable()
+ {
+ _dtfiTokenHash = null;
+ formatFlags = DateTimeFormatFlags.NotInitialized;
+ }
+
+ internal TokenHashValue[] CreateTokenHashTable()
+ {
+ TokenHashValue[] temp = _dtfiTokenHash;
+ if (temp == null)
+ {
+ temp = new TokenHashValue[TOKEN_HASH_SIZE];
+
+ bool koreanLanguage = LanguageName.Equals(KoreanLangName);
+
+ string sep = this.TimeSeparator.Trim();
+ if (IgnorableComma != sep) InsertHash(temp, IgnorableComma, TokenType.IgnorableSymbol, 0);
+ if (IgnorablePeriod != sep) InsertHash(temp, IgnorablePeriod, TokenType.IgnorableSymbol, 0);
+
+ if (KoreanHourSuff != sep && CJKHourSuff != sep && ChineseHourSuff != sep)
+ {
+ //
+ // On the Macintosh, the default TimeSeparator is identical to the KoreanHourSuff, CJKHourSuff, or ChineseHourSuff for some cultures like
+ // ja-JP and ko-KR. In these cases having the same symbol inserted into the hash table with multiple TokenTypes causes undesirable
+ // DateTime.Parse behavior. For instance, the DateTimeFormatInfo.Tokenize() method might return SEP_DateOrOffset for KoreanHourSuff
+ // instead of SEP_HourSuff.
+ //
+ InsertHash(temp, this.TimeSeparator, TokenType.SEP_Time, 0);
+ }
+
+ InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+
+ // TODO: This ignores similar custom cultures
+ if (LanguageName.Equals("sq"))
+ {
+ // Albanian allows time formats like "12:00.PD"
+ InsertHash(temp, IgnorablePeriod + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, IgnorablePeriod + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+ }
+
+ // CJK suffix
+ InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0);
+ InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0);
+ InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0);
+ InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0);
+ InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0);
+ InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0);
+
+ InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0);
+ InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0);
+
+ // TODO: This ignores other custom cultures that might want to do something similar
+ if (koreanLanguage)
+ {
+ // Korean suffix
+ InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0);
+ InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0);
+ }
+
+ if (LanguageName.Equals("ky"))
+ {
+ // For some cultures, the date separator works more like a comma, being allowed before or after any date part
+ InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.IgnorableSymbol, 0);
+ }
+ else
+ {
+ InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0);
+ }
+
+ String[] dateWords = null;
+ DateTimeFormatInfoScanner scanner = null;
+
+ // We need to rescan the date words since we're always synthetic
+ scanner = new DateTimeFormatInfoScanner();
+ m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this);
+ // Ensure the formatflags is initialized.
+ DateTimeFormatFlags flag = FormatFlags;
+
+ // For some cultures, the date separator works more like a comma, being allowed before or after any date part.
+ // In these cultures, we do not use normal date separator since we disallow date separator after a date terminal state.
+ // This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol.
+ bool useDateSepAsIgnorableSymbol = false;
+
+ String monthPostfix = null;
+ if (dateWords != null)
+ {
+ // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix.
+ // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix.
+ for (int i = 0; i < dateWords.Length; i++)
+ {
+ switch (dateWords[i][0])
+ {
+ // This is a month postfix
+ case DateTimeFormatInfoScanner.MonthPostfixChar:
+ // Get the real month postfix.
+ monthPostfix = dateWords[i].Substring(1);
+ // Add the month name + postfix into the token.
+ AddMonthNames(temp, monthPostfix);
+ break;
+ case DateTimeFormatInfoScanner.IgnorableSymbolChar:
+ String symbol = dateWords[i].Substring(1);
+ InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
+ if (this.DateSeparator.Trim(null).Equals(symbol))
+ {
+ // The date separator is the same as the ignorable symbol.
+ useDateSepAsIgnorableSymbol = true;
+ }
+ break;
+ default:
+ InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0);
+ // TODO: This ignores similar custom cultures
+ if (LanguageName.Equals("eu"))
+ {
+ // Basque has date words with leading dots
+ InsertHash(temp, IgnorablePeriod + dateWords[i], TokenType.DateWordToken, 0);
+ }
+ break;
+ }
+ }
+ }
+
+ if (!useDateSepAsIgnorableSymbol)
+ {
+ // Use the normal date separator.
+ InsertHash(temp, this.DateSeparator, TokenType.SEP_Date, 0);
+ }
+ // Add the regular month names.
+ AddMonthNames(temp, null);
+
+ // Add the abbreviated month names.
+ for (int i = 1; i <= 13; i++)
+ {
+ InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i);
+ }
+
+
+ if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0)
+ {
+ for (int i = 1; i <= 13; i++)
+ {
+ String str;
+ str = internalGetMonthName(i, MonthNameStyles.Genitive, false);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+
+ if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0)
+ {
+ for (int i = 1; i <= 13; i++)
+ {
+ String str;
+ str = internalGetMonthName(i, MonthNameStyles.LeapYear, false);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+
+ for (int i = 0; i < 7; i++)
+ {
+ //String str = GetDayOfWeekNames()[i];
+ // We have to call public methods here to work with inherited DTFI.
+ String str = GetDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ str = GetAbbreviatedDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+ }
+
+ int[] eras = calendar.Eras;
+ for (int i = 1; i <= eras.Length; i++)
+ {
+ InsertHash(temp, GetEraName(i), TokenType.EraToken, i);
+ InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i);
+ }
+
+ // TODO: This ignores other cultures that might want to do something similar
+ if (LanguageName.Equals(JapaneseLangName))
+ {
+ // Japanese allows day of week forms like: "(Tue)"
+ for (int i = 0; i < 7; i++)
+ {
+ String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
+ InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i);
+ }
+ if (this.Calendar.GetType() != typeof(JapaneseCalendar))
+ {
+ // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar,
+ // we will check Japanese Era name as well when the calendar is Gregorian.
+ DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI();
+ for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++)
+ {
+ InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i);
+ InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i);
+ // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
+ InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i - 1], TokenType.JapaneseEraToken, i);
+ }
+ }
+ }
+ // TODO: This prohibits similar custom cultures, but we hard coded the name
+ else if (CultureName.Equals("zh-TW"))
+ {
+ DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI();
+ for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++)
+ {
+ if (twDtfi.GetEraName(i).Length > 0)
+ {
+ InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i);
+ }
+ }
+ }
+
+ InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+
+ // Add invariant month names and day names.
+ for (int i = 1; i <= 12; i++)
+ {
+ String str;
+ // We have to call public methods here to work with inherited DTFI.
+ // Insert the month name first, so that they are at the front of abbrevaited
+ // month names.
+ str = InvariantInfo.GetMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ str = InvariantInfo.GetAbbreviatedMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+
+ for (int i = 0; i < 7; i++)
+ {
+ // We have to call public methods here to work with inherited DTFI.
+ String str = InvariantInfo.GetDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+ }
+
+ for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++)
+ {
+ // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
+ InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1);
+ }
+
+ InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0);
+ InsertHash(temp, GMTName, TokenType.TimeZoneToken, 0);
+ InsertHash(temp, ZuluName, TokenType.TimeZoneToken, 0);
+
+ InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0);
+ InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0);
+
+ _dtfiTokenHash = temp;
+ }
+ return (temp);
+ }
+
+ private void AddMonthNames(TokenHashValue[] temp, String monthPostfix)
+ {
+ for (int i = 1; i <= 13; i++)
+ {
+ String str;
+ //str = internalGetMonthName(i, MonthNameStyles.Regular, false);
+ // We have to call public methods here to work with inherited DTFI.
+ // Insert the month name first, so that they are at the front of abbrevaited
+ // month names.
+ str = GetMonthName(i);
+ if (str.Length > 0)
+ {
+ if (monthPostfix != null)
+ {
+ // Insert the month name with the postfix first, so it can be matched first.
+ InsertHash(temp, str + monthPostfix, TokenType.MonthToken, i);
+ }
+ else
+ {
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+ str = GetAbbreviatedMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Try to parse the current word to see if it is a Hebrew number.
+ // Tokens will be updated accordingly.
+ // This is called by the Lexer of DateTime.Parse().
+ //
+ // Unlike most of the functions in this class, the return value indicates
+ // whether or not it started to parse. The badFormat parameter indicates
+ // if parsing began, but the format was bad.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ private static bool TryParseHebrewNumber(
+#if INSIDE_CLR
+ ref __DTString str,
+#else
+ ref FormatProvider.__DTString str,
+#endif
+ out Boolean badFormat,
+ out int number)
+ {
+ number = -1;
+ badFormat = false;
+
+ int i = str.Index;
+ if (!HebrewNumber.IsDigit(str.Value[i]))
+ {
+ // If the current character is not a Hebrew digit, just return false.
+ // There is no chance that we can parse a valid Hebrew number from here.
+ return (false);
+ }
+ // The current character is a Hebrew digit. Try to parse this word as a Hebrew number.
+ HebrewNumberParsingContext context = new HebrewNumberParsingContext(0);
+ HebrewNumberParsingState state;
+
+ do
+ {
+ state = HebrewNumber.ParseByChar(str.Value[i++], ref context);
+ switch (state)
+ {
+ case HebrewNumberParsingState.InvalidHebrewNumber: // Not a valid Hebrew number.
+ case HebrewNumberParsingState.NotHebrewDigit: // The current character is not a Hebrew digit character.
+ // Break out so that we don't continue to try parse this as a Hebrew number.
+ return (false);
+ }
+ } while (i < str.Value.Length && (state != HebrewNumberParsingState.FoundEndOfHebrewNumber));
+
+ // When we are here, we are either at the end of the string, or we find a valid Hebrew number.
+ Contract.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber,
+ "Invalid returned state from HebrewNumber.ParseByChar()");
+
+ if (state != HebrewNumberParsingState.FoundEndOfHebrewNumber)
+ {
+ // We reach end of the string but we can't find a terminal state in parsing Hebrew number.
+ return (false);
+ }
+
+ // We have found a valid Hebrew number. Update the index.
+ str.Advance(i - str.Index);
+
+ // Get the final Hebrew number value from the HebrewNumberParsingContext.
+ number = context.result;
+
+ return (true);
+ }
+
+ private static bool IsHebrewChar(char ch)
+ {
+ return (ch >= '\x0590' && ch <= '\x05ff');
+ }
+
+ internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue,
+#if INSIDE_CLR
+ ref __DTString str)
+#else
+ ref FormatProvider.__DTString str)
+#endif
+
+ {
+ tokenType = TokenType.UnknownToken;
+ tokenValue = 0;
+
+ TokenHashValue value;
+ Contract.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length");
+
+ char ch = str.m_current;
+ bool isLetter = Char.IsLetter(ch);
+ if (isLetter)
+ {
+ ch = this.Culture.TextInfo.ToLower(ch);
+ if (IsHebrewChar(ch) && TokenMask == TokenType.RegularTokenMask)
+ {
+ bool badFormat;
+ if (TryParseHebrewNumber(ref str, out badFormat, out tokenValue))
+ {
+ if (badFormat)
+ {
+ tokenType = TokenType.UnknownToken;
+ return (false);
+ }
+ // This is a Hebrew number.
+ // Do nothing here. TryParseHebrewNumber() will update token accordingly.
+ tokenType = TokenType.HebrewNumber;
+ return (true);
+ }
+ }
+ }
+
+
+ int hashcode = ch % TOKEN_HASH_SIZE;
+ int hashProbe = 1 + ch % SECOND_PRIME;
+ int remaining = str.len - str.Index;
+ int i = 0;
+
+ TokenHashValue[] hashTable = _dtfiTokenHash;
+ if (hashTable == null)
+ {
+ hashTable = CreateTokenHashTable();
+ }
+ do
+ {
+ value = hashTable[hashcode];
+ if (value == null)
+ {
+ // Not found.
+ break;
+ }
+ // Check this value has the right category (regular token or separator token) that we are looking for.
+ if (((int)value.tokenType & (int)TokenMask) > 0 && value.tokenString.Length <= remaining)
+ {
+ bool compareStrings = true;
+ if (isLetter)
+ {
+ // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately.
+ // Also an optimization to avoid string comparison
+ int nextCharIndex = str.Index + value.tokenString.Length;
+ if (nextCharIndex > str.len)
+ {
+ compareStrings = false;
+ }
+ else if (nextCharIndex < str.len)
+ {
+ // Check word boundary. The next character should NOT be a letter.
+ char nextCh = str.Value[nextCharIndex];
+ compareStrings = !(Char.IsLetter(nextCh));
+ }
+ }
+ if (compareStrings && CompareStringIgnoreCaseOptimized(str.Value, str.Index, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length))
+ {
+ tokenType = value.tokenType & TokenMask;
+ tokenValue = value.tokenValue;
+ str.Advance(value.tokenString.Length);
+ return (true);
+ }
+ else if ((value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) ||
+ (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames))
+ {
+ // For month or day token, we will match the names which have spaces.
+ int matchStrLen = 0;
+ if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen))
+ {
+ tokenType = value.tokenType & TokenMask;
+ tokenValue = value.tokenValue;
+ str.Advance(matchStrLen);
+ return (true);
+ }
+ }
+ }
+ i++;
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ } while (i < TOKEN_HASH_SIZE);
+
+ return (false);
+ }
+
+ private void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe)
+ {
+ // Remember the current slot.
+ TokenHashValue previousNode = hashTable[hashcode];
+
+ //// Console.WriteLine(" Insert Key: {0} in {1}", str, slotToInsert);
+ // Insert the new node into the current slot.
+ hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue); ;
+
+ while (++pos < TOKEN_HASH_SIZE)
+ {
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ // Remember this slot
+ TokenHashValue temp = hashTable[hashcode];
+
+ if (temp != null && this.Culture.TextInfo.ToLower(temp.tokenString[0]) != ch)
+ {
+ continue;
+ }
+ // Put the previous slot into this slot.
+ hashTable[hashcode] = previousNode;
+ //// Console.WriteLine(" Move {0} to slot {1}", previousNode.tokenString, hashcode);
+ if (temp == null)
+ {
+ // Done
+ return;
+ }
+ previousNode = temp;
+ };
+ Contract.Assert(false, "The hashtable is full. This should not happen.");
+ }
+
+ private void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue)
+ {
+ // The month of the 13th month is allowed to be null, so make sure that we ignore null value here.
+ if (str == null || str.Length == 0)
+ {
+ return;
+ }
+ TokenHashValue value;
+ int i = 0;
+ // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
+ // DateTime.Parse().
+ if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1]))
+ {
+ str = str.Trim(null); // Trim white space characters.
+ // Could have space for separators
+ if (str.Length == 0)
+ return;
+ }
+ char ch = this.Culture.TextInfo.ToLower(str[0]);
+ int hashcode = ch % TOKEN_HASH_SIZE;
+ int hashProbe = 1 + ch % SECOND_PRIME;
+ do
+ {
+ value = hashTable[hashcode];
+ if (value == null)
+ {
+ //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode);
+ hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);
+ return;
+ }
+ else
+ {
+ // Collision happens. Find another slot.
+ if (str.Length >= value.tokenString.Length)
+ {
+ // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of
+ // the shorter ones.
+ if (this.CompareStringIgnoreCaseOptimized(str, 0, value.tokenString.Length, value.tokenString, 0, value.tokenString.Length))
+ {
+ if (str.Length > value.tokenString.Length)
+ {
+ // The str to be inserted has the same prefix as the current token, and str is longer.
+ // Insert str into this node, and shift every node behind it.
+ InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe);
+ return;
+ }
+ else
+ {
+ // Same token. If they have different types (regular token vs separator token). Add them.
+ // If we have the same regular token or separator token in the hash already, do NOT update the hash.
+ // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash.
+
+
+ //
+ // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet.
+ // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet.
+ //
+
+ int nTokenType = (int)tokenType;
+ int nCurrentTokenTypeInHash = (int)value.tokenType;
+
+ //
+ // The folowing is the fix for the issue of throwing FormatException when "mar" is passed in string of the short date format dd/MMM/yyyy for es-MX
+ //
+
+ if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) ||
+ ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0))
+ {
+ value.tokenType |= tokenType;
+ if (tokenValue != 0)
+ {
+ value.tokenValue = tokenValue;
+ }
+ }
+ // The token to be inserted is already in the table. Skip it.
+ return;
+ }
+ }
+ }
+ }
+ //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str);
+ i++;
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ } while (i < TOKEN_HASH_SIZE);
+ Contract.Assert(false, "The hashtable is full. This should not happen.");
+ }
+
+ private bool CompareStringIgnoreCaseOptimized(string string1, int offset1, int length1, string string2, int offset2, int length2)
+ {
+ // Optimize for one character cases which are common due to date and time separators (/ and :)
+ if (length1 == 1 && length2 == 1 && string1[offset1] == string2[offset2])
+ {
+ return true;
+ }
+
+ return (this.Culture.CompareInfo.Compare(string1, offset1, length1, string2, offset2, length2, CompareOptions.IgnoreCase) == 0);
+ }
+
+ // class DateTimeFormatInfo
+
+ internal class TokenHashValue
+ {
+ internal String tokenString;
+ internal TokenType tokenType;
+ internal int tokenValue;
+
+ internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue)
+ {
+ this.tokenString = tokenString;
+ this.tokenType = tokenType;
+ this.tokenValue = tokenValue;
+ }
+ }
+ }
+
+#if !INSIDE_CLR
+ //
+ // The type of token that will be returned by DateTimeFormatInfo.Tokenize().
+ //
+ internal enum TokenType
+ {
+ // The valid token should start from 1.
+
+ // Regular tokens. The range is from 0x00 ~ 0xff.
+ NumberToken = 1, // The number. E.g. "12"
+ YearNumberToken = 2, // The number which is considered as year number, which has 3 or more digits. E.g. "2003"
+ Am = 3, // AM timemark. E.g. "AM"
+ Pm = 4, // PM timemark. E.g. "PM"
+ MonthToken = 5, // A word (or words) that represents a month name. E.g. "March"
+ EndOfString = 6, // End of string
+ DayOfWeekToken = 7, // A word (or words) that represents a day of week name. E.g. "Monday" or "Mon"
+ TimeZoneToken = 8, // A word that represents a timezone name. E.g. "GMT"
+ EraToken = 9, // A word that represents a era name. E.g. "A.D."
+ DateWordToken = 10, // A word that can appear in a DateTime string, but serves no parsing semantics. E.g. "de" in Spanish culture.
+ UnknownToken = 11, // An unknown word, which signals an error in parsing.
+ HebrewNumber = 12, // A number that is composed of Hebrew text. Hebrew calendar uses Hebrew digits for year values, month values, and day values.
+ JapaneseEraToken = 13, // Era name for JapaneseCalendar
+ TEraToken = 14, // Era name for TaiwanCalendar
+ IgnorableSymbol = 15, // A separator like "," that is equivalent to whitespace
+
+
+ // Separator tokens.
+ SEP_Unk = 0x100, // Unknown separator.
+ SEP_End = 0x200, // The end of the parsing string.
+ SEP_Space = 0x300, // Whitespace (including comma).
+ SEP_Am = 0x400, // AM timemark. E.g. "AM"
+ SEP_Pm = 0x500, // PM timemark. E.g. "PM"
+ SEP_Date = 0x600, // date separator. E.g. "/"
+ SEP_Time = 0x700, // time separator. E.g. ":"
+ SEP_YearSuff = 0x800, // Chinese/Japanese/Korean year suffix.
+ SEP_MonthSuff = 0x900, // Chinese/Japanese/Korean month suffix.
+ SEP_DaySuff = 0xa00, // Chinese/Japanese/Korean day suffix.
+ SEP_HourSuff = 0xb00, // Chinese/Japanese/Korean hour suffix.
+ SEP_MinuteSuff = 0xc00, // Chinese/Japanese/Korean minute suffix.
+ SEP_SecondSuff = 0xd00, // Chinese/Japanese/Korean second suffix.
+ SEP_LocalTimeMark = 0xe00, // 'T', used in ISO 8601 format.
+ SEP_DateOrOffset = 0xf00, // '-' which could be a date separator or start of a time zone offset
+
+ RegularTokenMask = 0x00ff,
+ SeparatorTokenMask = 0xff00,
+ }
+#endif
+
+}
diff --git a/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs
new file mode 100644
index 0000000000..9cbc19f385
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/DateTimeFormatInfoScanner.cs
@@ -0,0 +1,742 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+// DateTimeFormatInfoScanner
+//
+// Scan a specified DateTimeFormatInfo to search for data used in DateTime.Parse()
+//
+// The data includes:
+//
+// DateWords: such as "de" used in es-ES (Spanish) LongDatePattern.
+// Postfix: such as "ta" used in fi-FI after the month name.
+//
+// This class is shared among mscorlib.dll and sysglobl.dll.
+// Use conditional CULTURE_AND_REGIONINFO_BUILDER_ONLY to differentiate between
+// methods for mscorlib.dll and sysglobl.dll.
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Globalization;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+namespace System.Globalization
+{
+
+#if INSIDE_CLR
+ using StringStringDictionary = Dictionary<string, string>;
+ using StringList = List<string>;
+#else
+ using StringStringDictionary = LowLevelDictionary<string, string>;
+ using StringList = LowLevelList<string>;
+#endif
+
+ //
+ // from LocaleEx.txt header
+ //
+ //; IFORMATFLAGS
+ //; Parsing/formatting flags.
+ internal enum FORMATFLAGS
+ {
+ None = 0x00000000,
+ UseGenitiveMonth = 0x00000001,
+ UseLeapYearMonth = 0x00000002,
+ UseSpacesInMonthNames = 0x00000004,
+ UseHebrewParsing = 0x00000008,
+ UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
+ UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
+ }
+
+ internal enum CalendarId : ushort
+ {
+ UNINITIALIZED_VALUE = 0,
+ GREGORIAN = 1, // Gregorian (localized) calendar
+ GREGORIAN_US = 2, // Gregorian (U.S.) calendar
+ JAPAN = 3, // Japanese Emperor Era calendar
+ /* SSS_WARNINGS_OFF */
+ TAIWAN = 4, // Taiwan Era calendar /* SSS_WARNINGS_ON */
+ KOREA = 5, // Korean Tangun Era calendar
+ HIJRI = 6, // Hijri (Arabic Lunar) calendar
+ THAI = 7, // Thai calendar
+ HEBREW = 8, // Hebrew (Lunar) calendar
+ GREGORIAN_ME_FRENCH = 9, // Gregorian Middle East French calendar
+ GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar
+ GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar
+ GREGORIAN_XLIT_FRENCH = 12,
+ // Note that all calendars after this point are MANAGED ONLY for now.
+ JULIAN = 13,
+ JAPANESELUNISOLAR = 14,
+ CHINESELUNISOLAR = 15,
+ SAKA = 16, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code
+ KOREANLUNISOLAR = 20,
+ TAIWANLUNISOLAR = 21,
+ PERSIAN = 22,
+ UMALQURA = 23,
+ LAST_CALENDAR = 23 // Last calendar ID
+ }
+
+ internal class DateTimeFormatInfoScanner
+ {
+ // Special prefix-like flag char in DateWord array.
+
+ // Use char in PUA area since we won't be using them in real data.
+ // The char used to tell a read date word or a month postfix. A month postfix
+ // is "ta" in the long date pattern like "d. MMMM'ta 'yyyy" for fi-FI.
+ // In this case, it will be stored as "\xfffeta" in the date word array.
+ internal const char MonthPostfixChar = '\xe000';
+
+ // Add ignorable symbol in a DateWord array.
+
+ // hu-HU has:
+ // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
+ // long date pattern: yyyy. MMMM d.
+ // Here, "." is the date separator (derived from short date pattern). However,
+ // "." also appear at the end of long date pattern. In this case, we just
+ // "." as ignorable symbol so that the DateTime.Parse() state machine will not
+ // treat the additional date separator at the end of y,m,d pattern as an error
+ // condition.
+ internal const char IgnorableSymbolChar = '\xe001';
+
+ // Known CJK suffix
+ internal const String CJKYearSuff = "\u5e74";
+ internal const String CJKMonthSuff = "\u6708";
+ internal const String CJKDaySuff = "\u65e5";
+
+ internal const String KoreanYearSuff = "\ub144";
+ internal const String KoreanMonthSuff = "\uc6d4";
+ internal const String KoreanDaySuff = "\uc77c";
+
+ internal const String KoreanHourSuff = "\uc2dc";
+ internal const String KoreanMinuteSuff = "\ubd84";
+ internal const String KoreanSecondSuff = "\ucd08";
+
+ internal const String CJKHourSuff = "\u6642";
+ internal const String ChineseHourSuff = "\u65f6";
+
+ internal const String CJKMinuteSuff = "\u5206";
+ internal const String CJKSecondSuff = "\u79d2";
+
+ // The collection fo date words & postfix.
+ internal StringList m_dateWords = new StringList();
+ // Hashtable for the known words.
+ private static volatile StringStringDictionary s_knownWords;
+
+ static StringStringDictionary KnownWords
+ {
+ get
+ {
+ if (s_knownWords == null)
+ {
+ StringStringDictionary temp = new StringStringDictionary();
+ // Add known words into the hash table.
+
+ // Skip these special symbols.
+ temp.Add("/", String.Empty);
+ temp.Add("-", String.Empty);
+ temp.Add(".", String.Empty);
+ // Skip known CJK suffixes.
+ temp.Add(CJKYearSuff, String.Empty);
+ temp.Add(CJKMonthSuff, String.Empty);
+ temp.Add(CJKDaySuff, String.Empty);
+ temp.Add(KoreanYearSuff, String.Empty);
+ temp.Add(KoreanMonthSuff, String.Empty);
+ temp.Add(KoreanDaySuff, String.Empty);
+ temp.Add(KoreanHourSuff, String.Empty);
+ temp.Add(KoreanMinuteSuff, String.Empty);
+ temp.Add(KoreanSecondSuff, String.Empty);
+ temp.Add(CJKHourSuff, String.Empty);
+ temp.Add(ChineseHourSuff, String.Empty);
+ temp.Add(CJKMinuteSuff, String.Empty);
+ temp.Add(CJKSecondSuff, String.Empty);
+
+ s_knownWords = temp;
+ }
+ return (s_knownWords);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Parameters:
+ // pattern: The pattern to be scanned.
+ // currentIndex: the current index to start the scan.
+ //
+ // Returns:
+ // Return the index with the first character that is a letter, which will
+ // be the start of a date word.
+ // Note that the index can be pattern.Length if we reach the end of the string.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static int SkipWhiteSpacesAndNonLetter(String pattern, int currentIndex)
+ {
+ while (currentIndex < pattern.Length)
+ {
+ char ch = pattern[currentIndex];
+ if (ch == '\\')
+ {
+ // Escaped character. Look ahead one character.
+ currentIndex++;
+ if (currentIndex < pattern.Length)
+ {
+ ch = pattern[currentIndex];
+ if (ch == '\'')
+ {
+ // Skip the leading single quote. We will
+ // stop at the first letter.
+ continue;
+ }
+ // Fall thru to check if this is a letter.
+ }
+ else
+ {
+ // End of string
+ break;
+ }
+ }
+ if (Char.IsLetter(ch) || ch == '\'' || ch == '.')
+ {
+ break;
+ }
+ // Skip the current char since it is not a letter.
+ currentIndex++;
+ }
+ return (currentIndex);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // A helper to add the found date word or month postfix into ArrayList for date words.
+ //
+ // Parameters:
+ // formatPostfix: What kind of postfix this is.
+ // Possible values:
+ // null: This is a regular date word
+ // "MMMM": month postfix
+ // word: The date word or postfix to be added.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal void AddDateWordOrPostfix(String formatPostfix, String str)
+ {
+ if (str.Length > 0)
+ {
+ // Some cultures use . like an abbreviation
+ if (str.Equals("."))
+ {
+ AddIgnorableSymbols(".");
+ return;
+ }
+ String words;
+ if (KnownWords.TryGetValue(str, out words) == false)
+ {
+ if (m_dateWords == null)
+ {
+ m_dateWords = new StringList();
+ }
+ if (formatPostfix == "MMMM")
+ {
+ // Add the word into the ArrayList as "\xfffe" + real month postfix.
+ String temp = MonthPostfixChar + str;
+ if (!m_dateWords.Contains(temp))
+ {
+ m_dateWords.Add(temp);
+ }
+ }
+ else
+ {
+ if (!m_dateWords.Contains(str))
+ {
+ m_dateWords.Add(str);
+ }
+ if (str[str.Length - 1] == '.')
+ {
+ // Old version ignore the trialing dot in the date words. Support this as well.
+ String strWithoutDot = str.Substring(0, str.Length - 1);
+ if (!m_dateWords.Contains(strWithoutDot))
+ {
+ m_dateWords.Add(strWithoutDot);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the pattern from the specified index and add the date word/postfix
+ // when appropriate.
+ //
+ // Parameters:
+ // pattern: The pattern to be scanned.
+ // index: The starting index to be scanned.
+ // formatPostfix: The kind of postfix to be scanned.
+ // Possible values:
+ // null: This is a regular date word
+ // "MMMM": month postfix
+ //
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal int AddDateWords(String pattern, int index, String formatPostfix)
+ {
+ // Skip any whitespaces so we will start from a letter.
+ int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index);
+ if (newIndex != index && formatPostfix != null)
+ {
+ // There are whitespaces. This will not be a postfix.
+ formatPostfix = null;
+ }
+ index = newIndex;
+
+ // This is the first char added into dateWord.
+ // Skip all non-letter character. We will add the first letter into DateWord.
+ StringBuilder dateWord = new StringBuilder();
+ // We assume that date words should start with a letter.
+ // Skip anything until we see a letter.
+
+ while (index < pattern.Length)
+ {
+ char ch = pattern[index];
+ if (ch == '\'')
+ {
+ // We have seen the end of quote. Add the word if we do not see it before,
+ // and break the while loop.
+ AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
+ index++;
+ break;
+ }
+ else if (ch == '\\')
+ {
+ //
+ // Escaped character. Look ahead one character
+ //
+
+ // Skip escaped backslash.
+ index++;
+ if (index < pattern.Length)
+ {
+ dateWord.Append(pattern[index]);
+ index++;
+ }
+ }
+ else if (Char.IsWhiteSpace(ch))
+ {
+ // Found a whitespace. We have to add the current date word/postfix.
+ AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
+ if (formatPostfix != null)
+ {
+ // Done with postfix. The rest will be regular date word.
+ formatPostfix = null;
+ }
+ // Reset the dateWord.
+ dateWord.Length = 0;
+ index++;
+ }
+ else
+ {
+ dateWord.Append(ch);
+ index++;
+ }
+ }
+ return (index);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // A simple helper to find the repeat count for a specified char.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static int ScanRepeatChar(String pattern, char ch, int index, out int count)
+ {
+ count = 1;
+ while (++index < pattern.Length && pattern[index] == ch)
+ {
+ count++;
+ }
+ // Return the updated position.
+ return (index);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Add the text that is a date separator but is treated like ignroable symbol.
+ // E.g.
+ // hu-HU has:
+ // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
+ // long date pattern: yyyy. MMMM d.
+ // Here, "." is the date separator (derived from short date pattern). However,
+ // "." also appear at the end of long date pattern. In this case, we just
+ // "." as ignorable symbol so that the DateTime.Parse() state machine will not
+ // treat the additional date separator at the end of y,m,d pattern as an error
+ // condition.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal void AddIgnorableSymbols(String text)
+ {
+ if (m_dateWords == null)
+ {
+ // Create the date word array.
+ m_dateWords = new StringList();
+ }
+ // Add the ignorable symbol into the ArrayList.
+ String temp = IgnorableSymbolChar + text;
+ if (!m_dateWords.Contains(temp))
+ {
+ m_dateWords.Add(temp);
+ }
+ }
+
+
+ //
+ // Flag used to trace the date patterns (yy/yyyyy/M/MM/MMM/MMM/d/dd) that we have seen.
+ //
+ private enum FoundDatePattern
+ {
+ None = 0x0000,
+ FoundYearPatternFlag = 0x0001,
+ FoundMonthPatternFlag = 0x0002,
+ FoundDayPatternFlag = 0x0004,
+ FoundYMDPatternFlag = 0x0007, // FoundYearPatternFlag | FoundMonthPatternFlag | FoundDayPatternFlag;
+ }
+
+ // Check if we have found all of the year/month/day pattern.
+ private FoundDatePattern _ymdFlags = FoundDatePattern.None;
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Given a date format pattern, scan for date word or postfix.
+ //
+ // A date word should be always put in a single quoted string. And it will
+ // start from a letter, so whitespace and symbols will be ignored before
+ // the first letter.
+ //
+ // Examples of date word:
+ // 'de' in es-SP: dddd, dd' de 'MMMM' de 'yyyy
+ // "\x0443." in bg-BG: dd.M.yyyy '\x0433.'
+ //
+ // Example of postfix:
+ // month postfix:
+ // "ta" in fi-FI: d. MMMM'ta 'yyyy
+ // Currently, only month postfix is supported.
+ //
+ // Usage:
+ // Always call this with Framework-style pattern, instead of Windows style pattern.
+ // Windows style pattern uses '' for single quote, while .NET uses \'
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal void ScanDateWord(String pattern)
+ {
+ // Check if we have found all of the year/month/day pattern.
+ _ymdFlags = FoundDatePattern.None;
+
+ int i = 0;
+ while (i < pattern.Length)
+ {
+ char ch = pattern[i];
+ int chCount;
+
+ switch (ch)
+ {
+ case '\'':
+ // Find a beginning quote. Search until the end quote.
+ i = AddDateWords(pattern, i + 1, null);
+ break;
+ case 'M':
+ i = ScanRepeatChar(pattern, 'M', i, out chCount);
+ if (chCount >= 4)
+ {
+ if (i < pattern.Length && pattern[i] == '\'')
+ {
+ i = AddDateWords(pattern, i + 1, "MMMM");
+ }
+ }
+ _ymdFlags |= FoundDatePattern.FoundMonthPatternFlag;
+ break;
+ case 'y':
+ i = ScanRepeatChar(pattern, 'y', i, out chCount);
+ _ymdFlags |= FoundDatePattern.FoundYearPatternFlag;
+ break;
+ case 'd':
+ i = ScanRepeatChar(pattern, 'd', i, out chCount);
+ if (chCount <= 2)
+ {
+ // Only count "d" & "dd".
+ // ddd, dddd are day names. Do not count them.
+ _ymdFlags |= FoundDatePattern.FoundDayPatternFlag;
+ }
+ break;
+ case '\\':
+ // Found a escaped char not in a quoted string. Skip the current backslash
+ // and its next character.
+ i += 2;
+ break;
+ case '.':
+ if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag)
+ {
+ // If we find a dot immediately after the we have seen all of the y, m, d pattern.
+ // treat it as a ignroable symbol. Check for comments in AddIgnorableSymbols for
+ // more details.
+ AddIgnorableSymbols(".");
+ _ymdFlags = FoundDatePattern.None;
+ }
+ i++;
+ break;
+ default:
+ if (_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch))
+ {
+ // We are not seeing "." after YMD. Clear the flag.
+ _ymdFlags = FoundDatePattern.None;
+ }
+ // We are not in quote. Skip the current character.
+ i++;
+ break;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Given a DTFI, get all of the date words from date patterns and time patterns.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi)
+ {
+ // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
+ String[] datePatterns = dtfi.GetAllDateTimePatterns('D');
+ int i;
+
+ // Scan the long date patterns
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the short date patterns
+ datePatterns = dtfi.GetAllDateTimePatterns('d');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+ // Scan the YearMonth patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('y');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the month/day pattern
+ ScanDateWord(dtfi.MonthDayPattern);
+
+ // Scan the long time patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('T');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the short time patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('t');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ String[] result = null;
+ if (m_dateWords != null && m_dateWords.Count > 0)
+ {
+ result = new String[m_dateWords.Count];
+ for (i = 0; i < m_dateWords.Count; i++)
+ {
+ result[i] = m_dateWords[i];
+ }
+ }
+ return (result);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the month names to see if genitive month names are used, and return
+ // the format flag.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagGenitiveMonth(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ {
+ // If we have different names in regular and genitive month names, use genitive month flag.
+ return ((!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames))
+ ? FORMATFLAGS.UseGenitiveMonth : 0);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the month names to see if spaces are used or start with a digit, and return the format flag
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ {
+ FORMATFLAGS formatFlags = 0;
+ formatFlags |= (ArrayElementsBeginWithDigit(monthNames) ||
+ ArrayElementsBeginWithDigit(genitveMonthNames) ||
+ ArrayElementsBeginWithDigit(abbrevMonthNames) ||
+ ArrayElementsBeginWithDigit(genetiveAbbrevMonthNames)
+ ? FORMATFLAGS.UseDigitPrefixInTokens : 0);
+
+ formatFlags |= (ArrayElementsHaveSpace(monthNames) ||
+ ArrayElementsHaveSpace(genitveMonthNames) ||
+ ArrayElementsHaveSpace(abbrevMonthNames) ||
+ ArrayElementsHaveSpace(genetiveAbbrevMonthNames)
+ ? FORMATFLAGS.UseSpacesInMonthNames : 0);
+ return (formatFlags);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the day names and set the correct format flag.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(String[] dayNames, String[] abbrevDayNames)
+ {
+ return ((ArrayElementsHaveSpace(dayNames) ||
+ ArrayElementsHaveSpace(abbrevDayNames))
+ ? FORMATFLAGS.UseSpacesInDayNames : 0);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Check the calendar to see if it is HebrewCalendar and set the Hebrew format flag if necessary.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseHebrewCalendar(int calID)
+ {
+ return (calID == (int)CalendarId.HEBREW ?
+ FORMATFLAGS.UseHebrewParsing | FORMATFLAGS.UseLeapYearMonth : 0);
+ }
+
+
+ //-----------------------------------------------------------------------------
+ // EqualStringArrays
+ // compares two string arrays and return true if all elements of the first
+ // array equals to all elmentsof the second array.
+ // otherwise it returns false.
+ //-----------------------------------------------------------------------------
+
+ private static bool EqualStringArrays(string[] array1, string[] array2)
+ {
+ // Shortcut if they're the same array
+ if (array1 == array2)
+ {
+ return true;
+ }
+
+ // This is effectively impossible
+ if (array1.Length != array2.Length)
+ {
+ return false;
+ }
+
+ // Check each string
+ for (int i = 0; i < array1.Length; i++)
+ {
+ if (!array1[i].Equals(array2[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //-----------------------------------------------------------------------------
+ // ArrayElementsHaveSpace
+ // It checks all input array elements if any of them has space character
+ // returns true if found space character in one of the array elements.
+ // otherwise returns false.
+ //-----------------------------------------------------------------------------
+
+ private static bool ArrayElementsHaveSpace(string[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ // it is faster to check for space character manually instead of calling IndexOf
+ // so we don't have to go to native code side.
+ for (int j = 0; j < array[i].Length; j++)
+ {
+ if (Char.IsWhiteSpace(array[i][j]))
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Check if any element of the array start with a digit.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ private static bool ArrayElementsBeginWithDigit(string[] array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ // it is faster to check for space character manually instead of calling IndexOf
+ // so we don't have to go to native code side.
+ if (array[i].Length > 0 &&
+ array[i][0] >= '0' && array[i][0] <= '9')
+ {
+ int index = 1;
+ while (index < array[i].Length && array[i][index] >= '0' && array[i][index] <= '9')
+ {
+ // Skip other digits.
+ index++;
+ }
+ if (index == array[i].Length)
+ {
+ return (false);
+ }
+
+ if (index == array[i].Length - 1)
+ {
+ // Skip known CJK month suffix.
+ // CJK uses month name like "1\x6708", since \x6708 is a known month suffix,
+ // we don't need the UseDigitPrefixInTokens since it is slower.
+ switch (array[i][index])
+ {
+ case '\x6708': // CJKMonthSuff
+ case '\xc6d4': // KoreanMonthSuff
+ return (false);
+ }
+ }
+
+ if (index == array[i].Length - 4)
+ {
+ // Skip known CJK month suffix.
+ // Starting with Windows 8, the CJK months for some cultures looks like: "1' \x6708'"
+ // instead of just "1\x6708"
+ if (array[i][index] == '\'' && array[i][index + 1] == ' ' &&
+ array[i][index + 2] == '\x6708' && array[i][index + 3] == '\'')
+ {
+ return (false);
+ }
+ }
+ return (true);
+ }
+ }
+
+ return false;
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/DayLightTime.cs b/src/mscorlib/corefx/System/Globalization/DayLightTime.cs
new file mode 100644
index 0000000000..2345fb5bc2
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/DayLightTime.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Globalization
+{
+ // This class represents a starting/ending time for a period of daylight saving time.
+
+ [Serializable]
+ public partial class DaylightTime
+ {
+ internal DateTime m_start;
+ internal DateTime m_end;
+ internal TimeSpan m_delta;
+
+ private DaylightTime()
+ {
+ }
+
+ public DaylightTime(DateTime start, DateTime end, TimeSpan delta)
+ {
+ m_start = start;
+ m_end = end;
+ m_delta = delta;
+ }
+
+ // The start date of a daylight saving period.
+ public DateTime Start
+ {
+ get
+ {
+ return m_start;
+ }
+ }
+
+ // The end date of a daylight saving period.
+ public DateTime End
+ {
+ get
+ {
+ return m_end;
+ }
+ }
+
+ // Delta to stardard offset in ticks.
+ public TimeSpan Delta
+ {
+ get
+ {
+ return m_delta;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs
new file mode 100644
index 0000000000..8f2bbbc10f
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/EastAsianLunisolarCalendar.cs
@@ -0,0 +1,719 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about EastAsianLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class EastAsianLunisolarCalendar : Calendar
+ {
+ internal const int LeapMonth = 0;
+ internal const int Jan1Month = 1;
+ internal const int Jan1Date = 2;
+ internal const int nDaysPerMonth = 3;
+
+ // # of days so far in the solar year
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
+ };
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ // Return the type of the East Asian Lunisolar calendars.
+ //
+
+ //public override CalendarAlgorithmType AlgorithmType {
+ // get {
+ // return CalendarAlgorithmType.LunisolarCalendar;
+ // }
+ //}
+
+ // Return the year number in the 60-year cycle.
+ //
+
+ public virtual int GetSexagenaryYear(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int year = 0, month = 0, day = 0;
+ TimeToLunar(time, ref year, ref month, ref day);
+
+ return ((year - 4) % 60) + 1;
+ }
+
+ // Return the celestial year from the 60-year cycle.
+ // The returned value is from 1 ~ 10.
+ //
+
+ public int GetCelestialStem(int sexagenaryYear)
+ {
+ if ((sexagenaryYear < 1) || (sexagenaryYear > 60))
+ {
+ throw new ArgumentOutOfRangeException(
+ "sexagenaryYear",
+ SR.Format(SR.ArgumentOutOfRange_Range, 1, 60));
+ }
+ Contract.EndContractBlock();
+
+ return ((sexagenaryYear - 1) % 10) + 1;
+ }
+
+ // Return the Terrestial Branch from the the 60-year cycle.
+ // The returned value is from 1 ~ 12.
+ //
+
+ public int GetTerrestrialBranch(int sexagenaryYear)
+ {
+ if ((sexagenaryYear < 1) || (sexagenaryYear > 60))
+ {
+ throw new ArgumentOutOfRangeException(
+ "sexagenaryYear",
+ SR.Format(SR.ArgumentOutOfRange_Range, 1, 60));
+ }
+ Contract.EndContractBlock();
+
+ return ((sexagenaryYear - 1) % 12) + 1;
+ }
+
+ internal abstract int GetYearInfo(int LunarYear, int Index);
+ internal abstract int GetYear(int year, DateTime time);
+ internal abstract int GetGregorianYear(int year, int era);
+
+ internal abstract int MinCalendarYear { get; }
+ internal abstract int MaxCalendarYear { get; }
+ internal abstract EraInfo[] CalEraInfo { get; }
+ internal abstract DateTime MinDate { get; }
+ internal abstract DateTime MaxDate { get; }
+
+ internal const int MaxCalendarMonth = 13;
+ internal const int MaxCalendarDay = 30;
+
+ internal int MinEraCalendarYear(int era)
+ {
+ EraInfo[] mEraInfo = CalEraInfo;
+ //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null
+ if (mEraInfo == null)
+ {
+ return MinCalendarYear;
+ }
+
+ if (era == Calendar.CurrentEra)
+ {
+ era = CurrentEraValue;
+ }
+ //era has to be in the supported range otherwise we will throw exception in CheckEraRange()
+ if (era == GetEra(MinDate))
+ {
+ return (GetYear(MinCalendarYear, MinDate));
+ }
+
+ for (int i = 0; i < mEraInfo.Length; i++)
+ {
+ if (era == mEraInfo[i].era)
+ {
+ return (mEraInfo[i].minEraYear);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal int MaxEraCalendarYear(int era)
+ {
+ EraInfo[] mEraInfo = CalEraInfo;
+ //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null
+ if (mEraInfo == null)
+ {
+ return MaxCalendarYear;
+ }
+
+ if (era == Calendar.CurrentEra)
+ {
+ era = CurrentEraValue;
+ }
+ //era has to be in the supported range otherwise we will throw exception in CheckEraRange()
+ if (era == GetEra(MaxDate))
+ {
+ return (GetYear(MaxCalendarYear, MaxDate));
+ }
+
+ for (int i = 0; i < mEraInfo.Length; i++)
+ {
+ if (era == mEraInfo[i].era)
+ {
+ return (mEraInfo[i].maxEraYear);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal EastAsianLunisolarCalendar()
+ {
+ }
+
+ internal void CheckTicksRange(long ticks)
+ {
+ if (ticks < MinSupportedDateTime.Ticks || ticks > MaxSupportedDateTime.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(CultureInfo.InvariantCulture, SR.ArgumentOutOfRange_CalendarRange,
+ MinSupportedDateTime, MaxSupportedDateTime));
+ }
+ Contract.EndContractBlock();
+ }
+
+ internal void CheckEraRange(int era)
+ {
+ if (era == Calendar.CurrentEra)
+ {
+ era = CurrentEraValue;
+ }
+
+ if ((era < GetEra(MinDate)) || (era > GetEra(MaxDate)))
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ internal int CheckYearRange(int year, int era)
+ {
+ CheckEraRange(era);
+ year = GetGregorianYear(year, era);
+
+ if ((year < MinCalendarYear) || (year > MaxCalendarYear))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ SR.Format(SR.ArgumentOutOfRange_Range, MinEraCalendarYear(era), MaxEraCalendarYear(era)));
+ }
+ return year;
+ }
+
+ internal int CheckYearMonthRange(int year, int month, int era)
+ {
+ year = CheckYearRange(year, era);
+
+ if (month == 13)
+ {
+ //Reject if there is no leap month this year
+ if (GetYearInfo(year, LeapMonth) == 0)
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+
+ if (month < 1 || month > 13)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ return year;
+ }
+
+ internal int InternalGetDaysInMonth(int year, int month)
+ {
+ int nDays;
+ int mask; // mask for extracting bits
+
+ mask = 0x8000;
+ // convert the lunar day into a lunar month/date
+ mask >>= (month - 1);
+ if ((GetYearInfo(year, nDaysPerMonth) & mask) == 0)
+ nDays = 29;
+ else
+ nDays = 30;
+ return nDays;
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ year = CheckYearMonthRange(year, month, era);
+ return InternalGetDaysInMonth(year, month);
+ }
+
+ private static int GregorianIsLeapYear(int y)
+ {
+ return ((((y) % 4) != 0) ? 0 : ((((y) % 100) != 0) ? 1 : ((((y) % 400) != 0) ? 0 : 1)));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ year = CheckYearMonthRange(year, month, era);
+ int daysInMonth = InternalGetDaysInMonth(year, month);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
+ }
+
+ int gy = 0; int gm = 0; int gd = 0;
+
+ if (LunarToGregorian(year, month, day, ref gy, ref gm, ref gd))
+ {
+ return new DateTime(gy, gm, gd, hour, minute, second, millisecond);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+ }
+
+
+ //
+ // GregorianToLunar calculates lunar calendar info for the given gregorian year, month, date.
+ // The input date should be validated before calling this method.
+ //
+ internal void GregorianToLunar(int nSYear, int nSMonth, int nSDate, ref int nLYear, ref int nLMonth, ref int nLDate)
+ {
+ // unsigned int nLYear, nLMonth, nLDate; // lunar ymd
+ int nSolarDay; // day # in solar year
+ int nLunarDay; // day # in lunar year
+ int fLeap; // is it a solar leap year?
+ int LDpM; // lunar days/month bitfield
+ int mask; // mask for extracting bits
+ int nDays; // # days this lunar month
+ int nJan1Month, nJan1Date;
+
+ // calc the solar day of year
+ fLeap = GregorianIsLeapYear(nSYear);
+ nSolarDay = (fLeap == 1) ? DaysToMonth366[nSMonth - 1] : DaysToMonth365[nSMonth - 1];
+ nSolarDay += nSDate;
+
+ // init lunar year info
+ nLunarDay = nSolarDay;
+ nLYear = nSYear;
+ if (nLYear == (MaxCalendarYear + 1))
+ {
+ nLYear--;
+ nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365);
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear, Jan1Date);
+ }
+ else
+ {
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear, Jan1Date);
+
+ // check if this solar date is actually part of the previous
+ // lunar year
+ if ((nSMonth < nJan1Month) ||
+ (nSMonth == nJan1Month && nSDate < nJan1Date))
+ {
+ // the corresponding lunar day is actually part of the previous
+ // lunar year
+ nLYear--;
+
+ // add a solar year to the lunar day #
+ nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365);
+
+ // update the new start of year
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear, Jan1Date);
+ }
+ }
+
+ // convert solar day into lunar day.
+ // subtract off the beginning part of the solar year which is not
+ // part of the lunar year. since this part is always in Jan or Feb,
+ // we don't need to handle Leap Year (LY only affects March
+ // and later).
+ nLunarDay -= DaysToMonth365[nJan1Month - 1];
+ nLunarDay -= (nJan1Date - 1);
+
+ // convert the lunar day into a lunar month/date
+ mask = 0x8000;
+ LDpM = GetYearInfo(nLYear, nDaysPerMonth);
+ nDays = ((LDpM & mask) != 0) ? 30 : 29;
+ nLMonth = 1;
+ while (nLunarDay > nDays)
+ {
+ nLunarDay -= nDays;
+ nLMonth++;
+ mask >>= 1;
+ nDays = ((LDpM & mask) != 0) ? 30 : 29;
+ }
+ nLDate = nLunarDay;
+ }
+
+ /*
+ //Convert from Lunar to Gregorian
+ //Highly inefficient, but it works based on the forward conversion
+ */
+ internal bool LunarToGregorian(int nLYear, int nLMonth, int nLDate, ref int nSolarYear, ref int nSolarMonth, ref int nSolarDay)
+ {
+ int numLunarDays;
+
+ if (nLDate < 1 || nLDate > 30)
+ return false;
+
+ numLunarDays = nLDate - 1;
+
+ //Add previous months days to form the total num of days from the first of the month.
+ for (int i = 1; i < nLMonth; i++)
+ {
+ numLunarDays += InternalGetDaysInMonth(nLYear, i);
+ }
+
+ //Get Gregorian First of year
+ int nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ int nJan1Date = GetYearInfo(nLYear, Jan1Date);
+
+ // calc the solar day of year of 1 Lunar day
+ int fLeap = GregorianIsLeapYear(nLYear);
+ int[] days = (fLeap == 1) ? DaysToMonth366 : DaysToMonth365;
+
+ nSolarDay = nJan1Date;
+
+ if (nJan1Month > 1)
+ nSolarDay += days[nJan1Month - 1];
+
+ // Add the actual lunar day to get the solar day we want
+ nSolarDay = nSolarDay + numLunarDays;// - 1;
+
+ if (nSolarDay > (fLeap + 365))
+ {
+ nSolarYear = nLYear + 1;
+ nSolarDay -= (fLeap + 365);
+ }
+ else
+ {
+ nSolarYear = nLYear;
+ }
+
+ for (nSolarMonth = 1; nSolarMonth < 12; nSolarMonth++)
+ {
+ if (days[nSolarMonth] >= nSolarDay)
+ break;
+ }
+
+ nSolarDay -= days[nSolarMonth - 1];
+ return true;
+ }
+
+ internal DateTime LunarToTime(DateTime time, int year, int month, int day)
+ {
+ int gy = 0; int gm = 0; int gd = 0;
+ LunarToGregorian(year, month, day, ref gy, ref gm, ref gd);
+ return (GregorianCalendar.GetDefaultInstance().ToDateTime(gy, gm, gd, time.Hour, time.Minute, time.Second, time.Millisecond));
+ }
+
+ internal void TimeToLunar(DateTime time, ref int year, ref int month, ref int day)
+ {
+ int gy = 0; int gm = 0; int gd = 0;
+
+ Calendar Greg = GregorianCalendar.GetDefaultInstance();
+ gy = Greg.GetYear(time);
+ gm = Greg.GetMonth(time);
+ gd = Greg.GetDayOfMonth(time);
+
+ GregorianToLunar(gy, gm, gd, ref year, ref month, ref day);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
+ }
+ Contract.EndContractBlock();
+
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ int i = m + months;
+ if (i > 0)
+ {
+ int monthsInYear = InternalIsLeapYear(y) ? 13 : 12;
+
+ while (i - monthsInYear > 0)
+ {
+ i -= monthsInYear;
+ y++;
+ monthsInYear = InternalIsLeapYear(y) ? 13 : 12;
+ }
+ m = i;
+ }
+ else
+ {
+ int monthsInYear;
+ while (i <= 0)
+ {
+ monthsInYear = InternalIsLeapYear(y - 1) ? 13 : 12;
+ i += monthsInYear;
+ y--;
+ }
+ m = i;
+ }
+
+ int days = InternalGetDaysInMonth(y, m);
+ if (d > days)
+ {
+ d = days;
+ }
+ DateTime dt = LunarToTime(time, y, m, d);
+
+ CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ y += years;
+
+ if (m == 13 && !InternalIsLeapYear(y))
+ {
+ m = 12;
+ d = InternalGetDaysInMonth(y, m);
+ }
+ int DaysInMonths = InternalGetDaysInMonth(y, m);
+ if (d > DaysInMonths)
+ {
+ d = DaysInMonths;
+ }
+
+ DateTime dt = LunarToTime(time, y, m, d);
+ CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and [354|355 |383|384].
+ //
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ for (int i = 1; i < m; i++)
+ {
+ d = d + InternalGetDaysInMonth(y, i);
+ }
+ return d;
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 29 or 30.
+ //
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return d;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ year = CheckYearRange(year, era);
+
+ int Days = 0;
+ int monthsInYear = InternalIsLeapYear(year) ? 13 : 12;
+
+ while (monthsInYear != 0)
+ Days += InternalGetDaysInMonth(year, monthsInYear--);
+
+ return Days;
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 13.
+ //
+
+ public override int GetMonth(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return m;
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+ public override int GetYear(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+
+ int y = 0; int m = 0; int d = 0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return GetYear(y, time);
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return ((DayOfWeek)((int)(time.Ticks / Calendar.TicksPerDay + 1) % 7));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ year = CheckYearRange(year, era);
+ return (InternalIsLeapYear(year) ? 13 : 12);
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ year = CheckYearMonthRange(year, month, era);
+ int daysInMonth = InternalGetDaysInMonth(year, month);
+
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ SR.Format(SR.ArgumentOutOfRange_Day, daysInMonth, month));
+ }
+ int m = GetYearInfo(year, LeapMonth);
+ return ((m != 0) && (month == (m + 1)));
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ year = CheckYearMonthRange(year, month, era);
+ int m = GetYearInfo(year, LeapMonth);
+ return ((m != 0) && (month == (m + 1)));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this this year is not a leap year.
+ //
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ year = CheckYearRange(year, era);
+ int month = GetYearInfo(year, LeapMonth);
+ if (month > 0)
+ {
+ return (month + 1);
+ }
+ return 0;
+ }
+
+ internal bool InternalIsLeapYear(int year)
+ {
+ return (GetYearInfo(year, LeapMonth) != 0);
+ }
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ year = CheckYearRange(year, era);
+ return InternalIsLeapYear(year);
+ }
+
+ private const int DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX = 2029;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(BaseCalendarID, GetYear(new DateTime(DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX, 1, 1)));
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ SR.Format(SR.ArgumentOutOfRange_Range, 99, MaxCalendarYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ year = base.ToFourDigitYear(year);
+ CheckYearRange(year, CurrentEra);
+ return (year);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs
new file mode 100644
index 0000000000..d0933a0fc6
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendar.cs
@@ -0,0 +1,662 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+
+using System;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System.Globalization
+{
+ // This calendar recognizes two era values:
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+
+ public class GregorianCalendar : Calendar
+ {
+ /*
+ A.D. = anno Domini
+ */
+
+ public const int ADEra = 1;
+
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ //
+ // This is the max Gregorian year can be represented by DateTime class. The limitation
+ // is derived from DateTime class.
+ //
+ internal const int MaxYear = 9999;
+
+ internal GregorianCalendarTypes m_type;
+
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ private static volatile Calendar s_defaultInstance;
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (m_type < GregorianCalendarTypes.Localized ||
+ m_type > GregorianCalendarTypes.TransliteratedFrench)
+ {
+ throw new SerializationException(
+ String.Format(CultureInfo.CurrentCulture, SR.Serialization_MemberOutOfRange, "type", "GregorianCalendar"));
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of GregorianCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance()
+ {
+ if (s_defaultInstance == null)
+ {
+ s_defaultInstance = new GregorianCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+ // Construct an instance of gregorian calendar.
+
+ public GregorianCalendar() :
+ this(GregorianCalendarTypes.Localized)
+ {
+ }
+
+
+ public GregorianCalendar(GregorianCalendarTypes type)
+ {
+ if ((int)type < (int)GregorianCalendarTypes.Localized || (int)type > (int)GregorianCalendarTypes.TransliteratedFrench)
+ {
+ throw new ArgumentOutOfRangeException(
+ "type",
+ SR.Format(SR.ArgumentOutOfRange_Range,
+ GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench));
+ }
+ Contract.EndContractBlock();
+ this.m_type = type;
+ }
+
+ public virtual GregorianCalendarTypes CalendarType
+ {
+ get
+ {
+ return (m_type);
+ }
+
+ set
+ {
+ VerifyWritable();
+
+ switch (value)
+ {
+ case GregorianCalendarTypes.Localized:
+ case GregorianCalendarTypes.USEnglish:
+ case GregorianCalendarTypes.MiddleEastFrench:
+ case GregorianCalendarTypes.Arabic:
+ case GregorianCalendarTypes.TransliteratedEnglish:
+ case GregorianCalendarTypes.TransliteratedFrench:
+ m_type = value;
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException("m_type", SR.ArgumentOutOfRange_Enum);
+ }
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ // By returning different ID for different variations of GregorianCalendar,
+ // we can support the Transliterated Gregorian calendar.
+ // DateTimeFormatInfo will use this ID to get formatting information about
+ // the calendar.
+ return ((CalendarId)m_type);
+ }
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ // n = number of days since 1/1/0001
+ int n = (int)(ticks / TicksPerDay);
+ // y400 = number of whole 400-year periods since 1/1/0001
+ int y400 = n / DaysPer400Years;
+ // n = day number within 400-year period
+ n -= y400 * DaysPer400Years;
+ // y100 = number of whole 100-year periods within 400-year period
+ int y100 = n / DaysPer100Years;
+ // Last 100-year period has an extra day, so decrement result if 4
+ if (y100 == 4) y100 = 3;
+ // n = day number within 100-year period
+ n -= y100 * DaysPer100Years;
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / DaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * DaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / DaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * DaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3));
+ int[] days = leapYear ? DaysToMonth366 : DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ /*=================================GetAbsoluteDate==========================
+ **Action: Gets the absolute date for the given Gregorian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns: the absolute date
+ **Arguments:
+ ** year the Gregorian year
+ ** month the Gregorian month
+ ** day the day
+ **Exceptions:
+ ** ArgumentOutOfRangException if year, month, day value is valid.
+ **Note:
+ ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
+ ** Number of Days in Prior Years (both common and leap years) +
+ ** Number of Days in Prior Months of Current Year +
+ ** Number of Days in Current Month
+ **
+ ============================================================================*/
+
+ internal static long GetAbsoluteDate(int year, int month, int day)
+ {
+ if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12)
+ {
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366 : DaysToMonth365;
+ if (day >= 1 && (day <= days[month] - days[month - 1]))
+ {
+ int y = year - 1;
+ int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
+ return (absoluteDate);
+ }
+ }
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ // Will check the if the parameters are valid.
+ internal virtual long DateToTicks(int year, int month, int day)
+ {
+ return (GetAbsoluteDate(year, month, day) * TicksPerDay);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+
+ return (new DateTime(ticks));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ if (year < 1 || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException("year", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, MaxYear));
+ }
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365);
+ return (days[month] - days[month - 1]);
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ if (year >= 1 && year <= MaxYear)
+ {
+ return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365);
+ }
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time)
+ {
+ return (ADEra);
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { ADEra });
+ }
+ }
+
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ if (year >= 1 && year <= MaxYear)
+ {
+ return (12);
+ }
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, 12));
+ }
+ Contract.EndContractBlock();
+
+ if (era != CurrentEra && era != ADEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ if (year < 1 || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ SR.Format(SR.ArgumentOutOfRange_Range, 1, MaxYear));
+ }
+
+ if (day < 1 || day > GetDaysInMonth(year, month))
+ {
+ throw new ArgumentOutOfRangeException("day", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, GetDaysInMonth(year, month)));
+ }
+ if (!IsLeapYear(year))
+ {
+ return (false);
+ }
+ if (month == 2 && day == 29)
+ {
+ return (true);
+ }
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ if (era != CurrentEra && era != ADEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ if (year < 1 || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, 1, MaxYear));
+ }
+ Contract.EndContractBlock();
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ if (era != CurrentEra && era != ADEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ if (year < 1 || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, 1, MaxYear));
+ }
+
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.Format(SR.ArgumentOutOfRange_Range,
+ 1, 12));
+ }
+ Contract.EndContractBlock();
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ if (year >= 1 && year <= MaxYear)
+ {
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+ }
+
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, 1, MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ return new DateTime(year, month, day, hour, minute, second, millisecond);
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result)
+ {
+ if (era == CurrentEra || era == ADEra)
+ {
+ try
+ {
+ result = new DateTime(year, month, day, hour, minute, second, millisecond);
+ return true;
+ }
+ catch (ArgumentOutOfRangeException)
+ {
+ result = DateTime.Now;
+ return false;
+ }
+ catch (ArgumentException)
+ {
+ result = DateTime.Now;
+ return false;
+ }
+ }
+ result = DateTime.MinValue;
+ return false;
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2029;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, 1, MaxYear));
+ }
+ return (base.ToFourDigitYear(year));
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs
new file mode 100644
index 0000000000..f595e72d0d
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendarHelper.cs
@@ -0,0 +1,668 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System.Globalization
+{
+ // Gregorian Calendars use Era Info
+ [Serializable]
+ internal class EraInfo
+ {
+ internal int era; // The value of the era.
+ internal long ticks; // The time in ticks when the era starts
+ internal int yearOffset; // The offset to Gregorian year when the era starts.
+ // Gregorian Year = Era Year + yearOffset
+ // Era Year = Gregorian Year - yearOffset
+ internal int minEraYear; // Min year value in this era. Generally, this value is 1, but this may
+ // be affected by the DateTime.MinValue;
+ internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1)
+
+ [OptionalField(VersionAdded = 4)]
+ internal String eraName; // The era name
+ [OptionalField(VersionAdded = 4)]
+ internal String abbrevEraName; // Abbreviated Era Name
+ [OptionalField(VersionAdded = 4)]
+ internal String englishEraName; // English era name
+
+ internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear)
+ {
+ this.era = era;
+ this.yearOffset = yearOffset;
+ this.minEraYear = minEraYear;
+ this.maxEraYear = maxEraYear;
+ this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
+ }
+
+ internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear,
+ String eraName, String abbrevEraName, String englishEraName)
+ {
+ this.era = era;
+ this.yearOffset = yearOffset;
+ this.minEraYear = minEraYear;
+ this.maxEraYear = maxEraYear;
+ this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
+ this.eraName = eraName;
+ this.abbrevEraName = abbrevEraName;
+ this.englishEraName = englishEraName;
+ }
+ }
+
+ // This calendar recognizes two era values:
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
+ [Serializable]
+ internal class GregorianCalendarHelper
+ {
+ // 1 tick = 100ns = 10E-7 second
+ // Number of ticks per time unit
+ internal const long TicksPerMillisecond = 10000;
+ internal const long TicksPerSecond = TicksPerMillisecond * 1000;
+ internal const long TicksPerMinute = TicksPerSecond * 60;
+ internal const long TicksPerHour = TicksPerMinute * 60;
+ internal const long TicksPerDay = TicksPerHour * 24;
+
+ // Number of milliseconds per time unit
+ internal const int MillisPerSecond = 1000;
+ internal const int MillisPerMinute = MillisPerSecond * 60;
+ internal const int MillisPerHour = MillisPerMinute * 60;
+ internal const int MillisPerDay = MillisPerHour * 24;
+
+ // Number of days in a non-leap year
+ internal const int DaysPerYear = 365;
+ // Number of days in 4 years
+ internal const int DaysPer4Years = DaysPerYear * 4 + 1;
+ // Number of days in 100 years
+ internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
+ // Number of days in 400 years
+ internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
+
+ // Number of days from 1/1/0001 to 1/1/10000
+ internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
+
+ internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ //
+ // This is the max Gregorian year can be represented by DateTime class. The limitation
+ // is derived from DateTime class.
+ //
+ internal int MaxYear
+ {
+ get
+ {
+ return (m_maxYear);
+ }
+ }
+
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ [OptionalField(VersionAdded = 1)]
+ internal int m_maxYear = 9999;
+ [OptionalField(VersionAdded = 1)]
+ internal int m_minYear;
+ internal Calendar m_Cal;
+
+ [OptionalField(VersionAdded = 1)]
+ internal EraInfo[] m_EraInfo;
+ [OptionalField(VersionAdded = 1)]
+ internal int[] m_eras = null;
+
+
+ // Construct an instance of gregorian calendar.
+ internal GregorianCalendarHelper(Calendar cal, EraInfo[] eraInfo)
+ {
+ m_Cal = cal;
+ m_EraInfo = eraInfo;
+ m_maxYear = m_EraInfo[0].maxEraYear;
+ m_minYear = m_EraInfo[0].minEraYear; ;
+ }
+
+ /*=================================GetGregorianYear==========================
+ **Action: Get the Gregorian year value for the specified year in an era.
+ **Returns: The Gregorian year value.
+ **Arguments:
+ ** year the year value in Japanese calendar
+ ** era the Japanese emperor era value.
+ **Exceptions:
+ ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
+ ============================================================================*/
+
+ internal int GetGregorianYear(int year, int era)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (era == Calendar.CurrentEra)
+ {
+ era = m_Cal.CurrentEraValue;
+ }
+
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ if (era == m_EraInfo[i].era)
+ {
+ if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ m_EraInfo[i].minEraYear,
+ m_EraInfo[i].maxEraYear));
+ }
+ return (m_EraInfo[i].yearOffset + year);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+
+ internal bool IsValidYear(int year, int era)
+ {
+ if (year < 0)
+ {
+ return false;
+ }
+
+ if (era == Calendar.CurrentEra)
+ {
+ era = m_Cal.CurrentEraValue;
+ }
+
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ if (era == m_EraInfo[i].era)
+ {
+ if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear)
+ {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ CheckTicksRange(ticks);
+ // n = number of days since 1/1/0001
+ int n = (int)(ticks / TicksPerDay);
+ // y400 = number of whole 400-year periods since 1/1/0001
+ int y400 = n / DaysPer400Years;
+ // n = day number within 400-year period
+ n -= y400 * DaysPer400Years;
+ // y100 = number of whole 100-year periods within 400-year period
+ int y100 = n / DaysPer100Years;
+ // Last 100-year period has an extra day, so decrement result if 4
+ if (y100 == 4) y100 = 3;
+ // n = day number within 100-year period
+ n -= y100 * DaysPer100Years;
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / DaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * DaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / DaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * DaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3));
+ int[] days = leapYear ? DaysToMonth366 : DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ /*=================================GetAbsoluteDate==========================
+ **Action: Gets the absolute date for the given Gregorian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns: the absolute date
+ **Arguments:
+ ** year the Gregorian year
+ ** month the Gregorian month
+ ** day the day
+ **Exceptions:
+ ** ArgumentOutOfRangException if year, month, day value is valid.
+ **Note:
+ ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
+ ** Number of Days in Prior Years (both common and leap years) +
+ ** Number of Days in Prior Months of Current Year +
+ ** Number of Days in Current Month
+ **
+ ============================================================================*/
+
+ internal static long GetAbsoluteDate(int year, int month, int day)
+ {
+ if (year >= 1 && year <= 9999 && month >= 1 && month <= 12)
+ {
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366 : DaysToMonth365;
+ if (day >= 1 && (day <= days[month] - days[month - 1]))
+ {
+ int y = year - 1;
+ int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
+ return (absoluteDate);
+ }
+ }
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ // Will check the if the parameters are valid.
+ internal static long DateToTicks(int year, int month, int day)
+ {
+ return (GetAbsoluteDate(year, month, day) * TicksPerDay);
+ }
+
+ // Return the tick count corresponding to the given hour, minute, second.
+ // Will check the if the parameters are valid.
+ internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
+ {
+ //TimeSpan.TimeToTicks is a family access function which does no error checking, so
+ //we need to put some error checking out here.
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
+ {
+ if (millisecond < 0 || millisecond >= MillisPerSecond)
+ {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ MillisPerSecond - 1));
+ }
+ return (InternalGloablizationHelper.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond); ;
+ }
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
+ }
+
+
+ internal void CheckTicksRange(long ticks)
+ {
+ if (ticks < m_Cal.MinSupportedDateTime.Ticks || ticks > m_Cal.MaxSupportedDateTime.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.ArgumentOutOfRange_CalendarRange,
+ m_Cal.MinSupportedDateTime,
+ m_Cal.MaxSupportedDateTime));
+ }
+ Contract.EndContractBlock();
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+ public DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ CheckTicksRange(time.Ticks);
+
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, m_Cal.MinSupportedDateTime, m_Cal.MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+ public DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+ public int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+ public DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return ((DayOfWeek)((time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+ public int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+ [Pure]
+ public int GetDaysInMonth(int year, int month, int era)
+ {
+ //
+ // Convert year/era value to Gregorain year value.
+ //
+ year = GetGregorianYear(year, era);
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365);
+ return (days[month] - days[month - 1]);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public int GetDaysInYear(int year, int era)
+ {
+ //
+ // Convert year/era value to Gregorain year value.
+ //
+ year = GetGregorianYear(year, era);
+ return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366 : 365);
+ }
+
+ // Returns the era for the specified DateTime value.
+ public int GetEra(DateTime time)
+ {
+ long ticks = time.Ticks;
+ // The assumption here is that m_EraInfo is listed in reverse order.
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ if (ticks >= m_EraInfo[i].ticks)
+ {
+ return (m_EraInfo[i].era);
+ }
+ }
+ throw new ArgumentOutOfRangeException("time", SR.ArgumentOutOfRange_Era);
+ }
+
+
+ public int[] Eras
+ {
+ get
+ {
+ if (m_eras == null)
+ {
+ m_eras = new int[m_EraInfo.Length];
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ m_eras[i] = m_EraInfo[i].era;
+ }
+ }
+ return ((int[])m_eras.Clone());
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+ public int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+ public int GetMonthsInYear(int year, int era)
+ {
+ year = GetGregorianYear(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int GetYear(DateTime time)
+ {
+ long ticks = time.Ticks;
+ int year = GetDatePart(ticks, DatePartYear);
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ if (ticks >= m_EraInfo[i].ticks)
+ {
+ return (year - m_EraInfo[i].yearOffset);
+ }
+ }
+ throw new ArgumentException(SR.Argument_NoEra);
+ }
+
+ // Returns the year that match the specified Gregorian year. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int GetYear(int year, DateTime time)
+ {
+ long ticks = time.Ticks;
+ for (int i = 0; i < m_EraInfo.Length; i++)
+ {
+ // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era
+ // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause
+ // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset
+ // which will end up with zero as calendar year.
+ // We should use the previous era info instead to get the right year number. Example of such date is Feb 2nd 1989
+ if (ticks >= m_EraInfo[i].ticks && year > m_EraInfo[i].yearOffset)
+ {
+ return (year - m_EraInfo[i].yearOffset);
+ }
+ }
+ throw new ArgumentException(SR.Argument_NoEra);
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+ public bool IsLeapDay(int year, int month, int day, int era)
+ {
+ // year/month/era checking is done in GetDaysInMonth()
+ if (day < 1 || day > GetDaysInMonth(year, month, era))
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ GetDaysInMonth(year, month, era)));
+ }
+ Contract.EndContractBlock();
+
+ if (!IsLeapYear(year, era))
+ {
+ return (false);
+ }
+
+ if (month == 2 && day == 29)
+ {
+ return (true);
+ }
+
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+ public int GetLeapMonth(int year, int era)
+ {
+ year = GetGregorianYear(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+ public bool IsLeapMonth(int year, int month, int era)
+ {
+ year = GetGregorianYear(year, era);
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ 12));
+ }
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+ public bool IsLeapYear(int year, int era)
+ {
+ year = GetGregorianYear(year, era);
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+ public DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ year = GetGregorianYear(year, era);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second, millisecond);
+ CheckTicksRange(ticks);
+ return (new DateTime(ticks));
+ }
+
+ public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ CheckTicksRange(time.Ticks);
+ // Use GregorianCalendar to get around the problem that the implmentation in Calendar.GetWeekOfYear()
+ // can call GetYear() that exceeds the supported range of the Gregorian-based calendars.
+ return (GregorianCalendar.GetDefaultInstance().GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public int ToFourDigitYear(int year, int twoDigitYearMax)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedPosNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100)
+ {
+ int y = year % 100;
+ return ((twoDigitYearMax / 100 - (y > twoDigitYearMax % 100 ? 1 : 0)) * 100 + y);
+ }
+
+ if (year < m_minYear || year > m_maxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, m_minYear, m_maxYear));
+ }
+ // If the year value is above 100, just return the year value. Don't have to do
+ // the TwoDigitYearMax comparison.
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs b/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs
new file mode 100644
index 0000000000..a14010fe60
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/GregorianCalendarTypes.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Globalization
+{
+ // Note: The values of the members of this enum must match the coresponding values
+ // in the CalendarId enum (since we cast between GregorianCalendarTypes and CalendarId).
+ [Serializable]
+ public enum GregorianCalendarTypes
+ {
+ Localized = CalendarId.GREGORIAN,
+ USEnglish = CalendarId.GREGORIAN_US,
+ MiddleEastFrench = CalendarId.GREGORIAN_ME_FRENCH,
+ Arabic = CalendarId.GREGORIAN_ARABIC,
+ TransliteratedEnglish = CalendarId.GREGORIAN_XLIT_ENGLISH,
+ TransliteratedFrench = CalendarId.GREGORIAN_XLIT_FRENCH,
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs
new file mode 100644
index 0000000000..5fbf2e0f09
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/HebrewCalendar.cs
@@ -0,0 +1,1123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Rules for the Hebrew calendar:
+ // - The Hebrew calendar is both a Lunar (months) and Solar (years)
+ // calendar, but allows for a week of seven days.
+ // - Days begin at sunset.
+ // - Leap Years occur in the 3, 6, 8, 11, 14, 17, & 19th years of a
+ // 19-year cycle. Year = leap iff ((7y+1) mod 19 < 7).
+ // - There are 12 months in a common year and 13 months in a leap year.
+ // - In a common year, the 6th month, Adar, has 29 days. In a leap
+ // year, the 6th month, Adar I, has 30 days and the leap month,
+ // Adar II, has 29 days.
+ // - Common years have 353-355 days. Leap years have 383-385 days.
+ // - The Hebrew new year (Rosh HaShanah) begins on the 1st of Tishri,
+ // the 7th month in the list below.
+ // - The new year may not begin on Sunday, Wednesday, or Friday.
+ // - If the new year would fall on a Tuesday and the conjunction of
+ // the following year were at midday or later, the new year is
+ // delayed until Thursday.
+ // - If the new year would fall on a Monday after a leap year, the
+ // new year is delayed until Tuesday.
+ // - The length of the 8th and 9th months vary from year to year,
+ // depending on the overall length of the year.
+ // - The length of a year is determined by the dates of the new
+ // years (Tishri 1) preceding and following the year in question.
+ // - The 2th month is long (30 days) if the year has 355 or 385 days.
+ // - The 3th month is short (29 days) if the year has 353 or 383 days.
+ // - The Hebrew months are:
+ // 1. Tishri (30 days)
+ // 2. Heshvan (29 or 30 days)
+ // 3. Kislev (29 or 30 days)
+ // 4. Teveth (29 days)
+ // 5. Shevat (30 days)
+ // 6. Adar I (30 days)
+ // 7. Adar {II} (29 days, this only exists if that year is a leap year)
+ // 8. Nisan (30 days)
+ // 9. Iyyar (29 days)
+ // 10. Sivan (30 days)
+ // 11. Tammuz (29 days)
+ // 12. Av (30 days)
+ // 13. Elul (29 days)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1583/01/01 2239/09/29
+ ** Hebrew 5343/04/07 5999/13/29
+ */
+
+ // Includes CHebrew implemetation;i.e All the code necessary for converting
+ // Gregorian to Hebrew Lunar from 1583 to 2239.
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class HebrewCalendar : Calendar
+ {
+ public static readonly int HebrewEra = 1;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+ internal const int DatePartDayOfWeek = 4;
+
+ //
+ // Hebrew Translation Table.
+ //
+ // This table is used to get the following Hebrew calendar information for a
+ // given Gregorian year:
+ // 1. The day of the Hebrew month corresponding to Gregorian January 1st
+ // for a given Gregorian year.
+ // 2. The month of the Hebrew month corresponding to Gregorian January 1st
+ // for a given Gregorian year.
+ // The information is not directly in the table. Instead, the info is decoded
+ // by special values (numbers above 29 and below 1).
+ // 3. The type of the Hebrew year for a given Gregorian year.
+ //
+
+ /*
+ More notes:
+
+ This table includes 2 numbers for each year.
+ The offset into the table determines the year. (offset 0 is Gregorian year 1500)
+ 1st number determines the day of the Hebrew month coresponeds to January 1st.
+ 2nd number determines the type of the Hebrew year. (the type determines how
+ many days are there in the year.)
+
+ normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ Leap years : 4 = 383 5 384 6 = 385 days.
+
+ A 99 means the year is not supported for translation.
+ for convenience the table was defined for 750 year,
+ but only 640 years are supported. (from 1583 to 2239)
+ the years before 1582 (starting of Georgian calander)
+ and after 2239, are filled with 99.
+
+ Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
+ That's why, there no nead to specify the lunar month in the table.
+ There are exceptions, these are coded by giving numbers above 29 and below 1.
+ Actual decoding is takenig place whenever fetching information from the table.
+ The function for decoding is in GetLunarMonthDay().
+
+ Example:
+ The data for 2000 - 2005 A.D. is:
+
+ 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004
+
+ For year 2000, we know it has a Hebrew year type 6, which means it has 385 days.
+ And 1/1/2000 A.D. is Hebrew year 5760, 23rd day of 4th month.
+ */
+
+ //
+ // Jewish Era in use today is dated from the supposed year of the
+ // Creation with its beginning in 3761 B.C.
+ //
+
+ // The Hebrew year of Gregorian 1st year AD.
+ // 0001/01/01 AD is Hebrew 3760/01/01
+ private const int HebrewYearOf1AD = 3760;
+
+ // The first Gregorian year in HebrewTable.
+ private const int FirstGregorianTableYear = 1583; // == Hebrew Year 5343
+ // The last Gregorian year in HebrewTable.
+ private const int LastGregorianTableYear = 2239; // == Hebrew Year 5999
+ private const int TABLESIZE = (LastGregorianTableYear - FirstGregorianTableYear);
+
+ private const int MinHebrewYear = HebrewYearOf1AD + FirstGregorianTableYear; // == 5343
+ private const int MaxHebrewYear = HebrewYearOf1AD + LastGregorianTableYear; // == 5999
+
+ private static readonly byte[] s_hebrewTable = {
+ 7,3,17,3, // 1583-1584 (Hebrew year: 5343 - 5344)
+ 0,4,11,2,21,6,1,3,13,2, // 1585-1589
+ 25,4,5,3,16,2,27,6,9,1, // 1590-1594
+ 20,2,0,6,11,3,23,4,4,2, // 1595-1599
+ 14,3,27,4,8,2,18,3,28,6, // 1600
+ 11,1,22,5,2,3,12,3,25,4, // 1605
+ 6,2,16,3,26,6,8,2,20,1, // 1610
+ 0,6,11,2,24,4,4,3,15,2, // 1615
+ 25,6,8,1,19,2,29,6,9,3, // 1620
+ 22,4,3,2,13,3,25,4,6,3, // 1625
+ 17,2,27,6,7,3,19,2,31,4, // 1630
+ 11,3,23,4,5,2,15,3,25,6, // 1635
+ 6,2,19,1,29,6,10,2,22,4, // 1640
+ 3,3,14,2,24,6,6,1,17,3, // 1645
+ 28,5,8,3,20,1,32,5,12,3, // 1650
+ 22,6,4,1,16,2,26,6,6,3, // 1655
+ 17,2,0,4,10,3,22,4,3,2, // 1660
+ 14,3,24,6,5,2,17,1,28,6, // 1665
+ 9,2,19,3,31,4,13,2,23,6, // 1670
+ 3,3,15,1,27,5,7,3,17,3, // 1675
+ 29,4,11,2,21,6,3,1,14,2, // 1680
+ 25,6,5,3,16,2,28,4,9,3, // 1685
+ 20,2,0,6,12,1,23,6,4,2, // 1690
+ 14,3,26,4,8,2,18,3,0,4, // 1695
+ 10,3,21,5,1,3,13,1,24,5, // 1700
+ 5,3,15,3,27,4,8,2,19,3, // 1705
+ 29,6,10,2,22,4,3,3,14,2, // 1710
+ 26,4,6,3,18,2,28,6,10,1, // 1715
+ 20,6,2,2,12,3,24,4,5,2, // 1720
+ 16,3,28,4,8,3,19,2,0,6, // 1725
+ 12,1,23,5,3,3,14,3,26,4, // 1730
+ 7,2,17,3,28,6,9,2,21,4, // 1735
+ 1,3,13,2,25,4,5,3,16,2, // 1740
+ 27,6,9,1,19,3,0,5,11,3, // 1745
+ 23,4,4,2,14,3,25,6,7,1, // 1750
+ 18,2,28,6,9,3,21,4,2,2, // 1755
+ 12,3,25,4,6,2,16,3,26,6, // 1760
+ 8,2,20,1,0,6,11,2,22,6, // 1765
+ 4,1,15,2,25,6,6,3,18,1, // 1770
+ 29,5,9,3,22,4,2,3,13,2, // 1775
+ 23,6,4,3,15,2,27,4,7,3, // 1780
+ 19,2,31,4,11,3,21,6,3,2, // 1785
+ 15,1,25,6,6,2,17,3,29,4, // 1790
+ 10,2,20,6,3,1,13,3,24,5, // 1795
+ 4,3,16,1,27,5,7,3,17,3, // 1800
+ 0,4,11,2,21,6,1,3,13,2, // 1805
+ 25,4,5,3,16,2,29,4,9,3, // 1810
+ 19,6,30,2,13,1,23,6,4,2, // 1815
+ 14,3,27,4,8,2,18,3,0,4, // 1820
+ 11,3,22,5,2,3,14,1,26,5, // 1825
+ 6,3,16,3,28,4,10,2,20,6, // 1830
+ 30,3,11,2,24,4,4,3,15,2, // 1835
+ 25,6,8,1,19,2,29,6,9,3, // 1840
+ 22,4,3,2,13,3,25,4,7,2, // 1845
+ 17,3,27,6,9,1,21,5,1,3, // 1850
+ 11,3,23,4,5,2,15,3,25,6, // 1855
+ 6,2,19,1,29,6,10,2,22,4, // 1860
+ 3,3,14,2,24,6,6,1,18,2, // 1865
+ 28,6,8,3,20,4,2,2,12,3, // 1870
+ 24,4,4,3,16,2,26,6,6,3, // 1875
+ 17,2,0,4,10,3,22,4,3,2, // 1880
+ 14,3,24,6,5,2,17,1,28,6, // 1885
+ 9,2,21,4,1,3,13,2,23,6, // 1890
+ 5,1,15,3,27,5,7,3,19,1, // 1895
+ 0,5,10,3,22,4,2,3,13,2, // 1900
+ 24,6,4,3,15,2,27,4,8,3, // 1905
+ 20,4,1,2,11,3,22,6,3,2, // 1910
+ 15,1,25,6,7,2,17,3,29,4, // 1915
+ 10,2,21,6,1,3,13,1,24,5, // 1920
+ 5,3,15,3,27,4,8,2,19,6, // 1925
+ 1,1,12,2,22,6,3,3,14,2, // 1930
+ 26,4,6,3,18,2,28,6,10,1, // 1935
+ 20,6,2,2,12,3,24,4,5,2, // 1940
+ 16,3,28,4,9,2,19,6,30,3, // 1945
+ 12,1,23,5,3,3,14,3,26,4, // 1950
+ 7,2,17,3,28,6,9,2,21,4, // 1955
+ 1,3,13,2,25,4,5,3,16,2, // 1960
+ 27,6,9,1,19,6,30,2,11,3, // 1965
+ 23,4,4,2,14,3,27,4,7,3, // 1970
+ 18,2,28,6,11,1,22,5,2,3, // 1975
+ 12,3,25,4,6,2,16,3,26,6, // 1980
+ 8,2,20,4,30,3,11,2,24,4, // 1985
+ 4,3,15,2,25,6,8,1,18,3, // 1990
+ 29,5,9,3,22,4,3,2,13,3, // 1995
+ 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004
+ 20,4,1,2,11,3,23,4,5,2, // 2005 - 2009
+ 15,3,25,6,6,2,19,1,29,6, // 2010
+ 10,2,20,6,3,1,14,2,24,6, // 2015
+ 4,3,17,1,28,5,8,3,20,4, // 2020
+ 1,3,12,2,22,6,2,3,14,2, // 2025
+ 26,4,6,3,17,2,0,4,10,3, // 2030
+ 20,6,1,2,14,1,24,6,5,2, // 2035
+ 15,3,28,4,9,2,19,6,1,1, // 2040
+ 12,3,23,5,3,3,15,1,27,5, // 2045
+ 7,3,17,3,29,4,11,2,21,6, // 2050
+ 1,3,12,2,25,4,5,3,16,2, // 2055
+ 28,4,9,3,19,6,30,2,12,1, // 2060
+ 23,6,4,2,14,3,26,4,8,2, // 2065
+ 18,3,0,4,10,3,22,5,2,3, // 2070
+ 14,1,25,5,6,3,16,3,28,4, // 2075
+ 9,2,20,6,30,3,11,2,23,4, // 2080
+ 4,3,15,2,27,4,7,3,19,2, // 2085
+ 29,6,11,1,21,6,3,2,13,3, // 2090
+ 25,4,6,2,17,3,27,6,9,1, // 2095
+ 20,5,30,3,10,3,22,4,3,2, // 2100
+ 14,3,24,6,5,2,17,1,28,6, // 2105
+ 9,2,21,4,1,3,13,2,23,6, // 2110
+ 5,1,16,2,27,6,7,3,19,4, // 2115
+ 30,2,11,3,23,4,3,3,14,2, // 2120
+ 25,6,5,3,16,2,28,4,9,3, // 2125
+ 21,4,2,2,12,3,23,6,4,2, // 2130
+ 16,1,26,6,8,2,20,4,30,3, // 2135
+ 11,2,22,6,4,1,14,3,25,5, // 2140
+ 6,3,18,1,29,5,9,3,22,4, // 2145
+ 2,3,13,2,23,6,4,3,15,2, // 2150
+ 27,4,7,3,20,4,1,2,11,3, // 2155
+ 21,6,3,2,15,1,25,6,6,2, // 2160
+ 17,3,29,4,10,2,20,6,3,1, // 2165
+ 13,3,24,5,4,3,17,1,28,5, // 2170
+ 8,3,18,6,1,1,12,2,22,6, // 2175
+ 2,3,14,2,26,4,6,3,17,2, // 2180
+ 28,6,10,1,20,6,1,2,12,3, // 2185
+ 24,4,5,2,15,3,28,4,9,2, // 2190
+ 19,6,33,3,12,1,23,5,3,3, // 2195
+ 13,3,25,4,6,2,16,3,26,6, // 2200
+ 8,2,20,4,30,3,11,2,24,4, // 2205
+ 4,3,15,2,25,6,8,1,18,6, // 2210
+ 33,2,9,3,22,4,3,2,13,3, // 2215
+ 25,4,6,3,17,2,27,6,9,1, // 2220
+ 21,5,1,3,11,3,23,4,5,2, // 2225
+ 15,3,25,6,6,2,19,4,33,3, // 2230
+ 10,2,22,4,3,3,14,2,24,6, // 2235
+ 6,1 // 2240 (Hebrew year: 6000)
+ };
+
+ private const int MaxMonthPlusOne = 14;
+
+ //
+ // The lunar calendar has 6 different variations of month lengths
+ // within a year.
+ //
+ private static readonly byte[] s_lunarMonthLen = {
+ 0,00,00,00,00,00,00,00,00,00,00,00,00,0,
+ 0,30,29,29,29,30,29,30,29,30,29,30,29,0, // 3 common year variations
+ 0,30,29,30,29,30,29,30,29,30,29,30,29,0,
+ 0,30,30,30,29,30,29,30,29,30,29,30,29,0,
+ 0,30,29,29,29,30,30,29,30,29,30,29,30,29, // 3 leap year variations
+ 0,30,29,30,29,30,30,29,30,29,30,29,30,29,
+ 0,30,30,30,29,30,30,29,30,29,30,29,30,29
+ };
+
+ internal static readonly DateTime calendarMinValue = new DateTime(1583, 1, 1);
+ // Gregorian 2239/9/29 = Hebrew 5999/13/29 (last day in Hebrew year 5999).
+ // We can only format/parse Hebrew numbers up to 999, so we limit the max range to Hebrew year 5999.
+ internal static readonly DateTime calendarMaxValue = new DateTime((new DateTime(2239, 9, 29, 23, 59, 59, 999)).Ticks + 9999);
+
+
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (calendarMaxValue);
+ }
+ }
+
+ public HebrewCalendar()
+ {
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.HEBREW);
+ }
+ }
+
+
+ /*=================================CheckHebrewYearValue==========================
+ **Action: Check if the Hebrew year value is supported in this class.
+ **Returns: None.
+ **Arguments: y Hebrew year value
+ ** ear Hebrew era value
+ **Exceptions: ArgumentOutOfRange_Range if the year value is not supported.
+ **Note:
+ ** We use a table for the Hebrew calendar calculation, so the year supported is limited.
+ ============================================================================*/
+
+ private static void CheckHebrewYearValue(int y, int era, String varName)
+ {
+ CheckEraRange(era);
+ if (y > MaxHebrewYear || y < MinHebrewYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ varName,
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MinHebrewYear,
+ MaxHebrewYear));
+ }
+ }
+
+ /*=================================CheckHebrewMonthValue==========================
+ **Action: Check if the Hebrew month value is valid.
+ **Returns: None.
+ **Arguments: year Hebrew year value
+ ** month Hebrew month value
+ **Exceptions: ArgumentOutOfRange_Range if the month value is not valid.
+ **Note:
+ ** Call CheckHebrewYearValue() before calling this to verify the year value is supported.
+ ============================================================================*/
+
+ private void CheckHebrewMonthValue(int year, int month, int era)
+ {
+ int monthsInYear = GetMonthsInYear(year, era);
+ if (month < 1 || month > monthsInYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ monthsInYear));
+ }
+ }
+
+ /*=================================CheckHebrewDayValue==========================
+ **Action: Check if the Hebrew day value is valid.
+ **Returns: None.
+ **Arguments: year Hebrew year value
+ ** month Hebrew month value
+ ** day Hebrew day value.
+ **Exceptions: ArgumentOutOfRange_Range if the day value is not valid.
+ **Note:
+ ** Call CheckHebrewYearValue()/CheckHebrewMonthValue() before calling this to verify the year/month values are valid.
+ ============================================================================*/
+
+ private void CheckHebrewDayValue(int year, int month, int day, int era)
+ {
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ daysInMonth));
+ }
+ }
+
+ internal static void CheckEraRange(int era)
+ {
+ if (era != CurrentEra && era != HebrewEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ private static void CheckTicksRange(long ticks)
+ {
+ if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ // Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar.
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.ArgumentOutOfRange_CalendarRange,
+ calendarMinValue,
+ calendarMaxValue));
+ }
+ }
+
+ internal static int GetResult(__DateBuffer result, int part)
+ {
+ switch (part)
+ {
+ case DatePartYear:
+ return (result.year);
+ case DatePartMonth:
+ return (result.month);
+ case DatePartDay:
+ return (result.day);
+ }
+
+ throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
+ }
+
+ /*=================================GetLunarMonthDay==========================
+ **Action: Using the Hebrew table (HebrewTable) to get the Hebrew month/day value for Gregorian January 1st
+ ** in a given Gregorian year.
+ ** Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
+ ** That's why, there no nead to specify the lunar month in the table. There are exceptions, and these
+ ** are coded by giving numbers above 29 and below 1.
+ ** Actual decoding is takenig place in the switch statement below.
+ **Returns:
+ ** The Hebrew year type. The value is from 1 to 6.
+ ** normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ ** Leap years : 4 = 383 5 384 6 = 385 days.
+ **Arguments:
+ ** gregorianYear The year value in Gregorian calendar. The value should be between 1500 and 2239.
+ ** lunarDate Object to take the result of the Hebrew year/month/day.
+ **Exceptions:
+ ============================================================================*/
+
+ internal static int GetLunarMonthDay(int gregorianYear, __DateBuffer lunarDate)
+ {
+ //
+ // Get the offset into the LunarMonthLen array and the lunar day
+ // for January 1st.
+ //
+ int index = gregorianYear - FirstGregorianTableYear;
+ if (index < 0 || index > TABLESIZE)
+ {
+ throw new ArgumentOutOfRangeException("gregorianYear");
+ }
+
+ index *= 2;
+ lunarDate.day = s_hebrewTable[index];
+
+ // Get the type of the year. The value is from 1 to 6
+ int LunarYearType = s_hebrewTable[index + 1];
+
+ //
+ // Get the Lunar Month.
+ //
+ switch (lunarDate.day)
+ {
+ case (0): // 1/1 is on Shvat 1
+ lunarDate.month = 5;
+ lunarDate.day = 1;
+ break;
+ case (30): // 1/1 is on Kislev 30
+ lunarDate.month = 3;
+ break;
+ case (31): // 1/1 is on Shvat 2
+ lunarDate.month = 5;
+ lunarDate.day = 2;
+ break;
+ case (32): // 1/1 is on Shvat 3
+ lunarDate.month = 5;
+ lunarDate.day = 3;
+ break;
+ case (33): // 1/1 is on Kislev 29
+ lunarDate.month = 3;
+ lunarDate.day = 29;
+ break;
+ default: // 1/1 is on Tevet (This is the general case)
+ lunarDate.month = 4;
+ break;
+ }
+ return (LunarYearType);
+ }
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ // The Gregorian year, month, day value for ticks.
+ int gregorianYear, gregorianMonth, gregorianDay;
+ int hebrewYearType; // lunar year type
+ long AbsoluteDate; // absolute date - absolute date 1/1/1600
+
+ //
+ // Make sure we have a valid Gregorian date that will fit into our
+ // Hebrew conversion limits.
+ //
+ CheckTicksRange(ticks);
+
+ DateTime time = new DateTime(ticks);
+
+ //
+ // Save the Gregorian date values.
+ //
+ gregorianYear = time.Year;
+ gregorianMonth = time.Month;
+ gregorianDay = time.Day;
+
+ __DateBuffer lunarDate = new __DateBuffer(); // lunar month and day for Jan 1
+
+ // From the table looking-up value of HebrewTable[index] (stored in lunarDate.day), we get the the
+ // lunar month and lunar day where the Gregorian date 1/1 falls.
+ lunarDate.year = gregorianYear + HebrewYearOf1AD;
+ hebrewYearType = GetLunarMonthDay(gregorianYear, lunarDate);
+
+ // This is the buffer used to store the result Hebrew date.
+ __DateBuffer result = new __DateBuffer();
+
+ //
+ // Store the values for the start of the new year - 1/1.
+ //
+ result.year = lunarDate.year;
+ result.month = lunarDate.month;
+ result.day = lunarDate.day;
+
+ //
+ // Get the absolute date from 1/1/1600.
+ //
+ AbsoluteDate = GregorianCalendar.GetAbsoluteDate(gregorianYear, gregorianMonth, gregorianDay);
+
+ //
+ // If the requested date was 1/1, then we're done.
+ //
+ if ((gregorianMonth == 1) && (gregorianDay == 1))
+ {
+ return (GetResult(result, part));
+ }
+
+ //
+ // Calculate the number of days between 1/1 and the requested date.
+ //
+ long NumDays; // number of days since 1/1
+ NumDays = AbsoluteDate - GregorianCalendar.GetAbsoluteDate(gregorianYear, 1, 1);
+
+ //
+ // If the requested date is within the current lunar month, then
+ // we're done.
+ //
+ if ((NumDays + (long)lunarDate.day) <= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month]))
+ {
+ result.day += (int)NumDays;
+ return (GetResult(result, part));
+ }
+
+ //
+ // Adjust for the current partial month.
+ //
+ result.month++;
+ result.day = 1;
+
+ //
+ // Adjust the Lunar Month and Year (if necessary) based on the number
+ // of days between 1/1 and the requested date.
+ //
+ // Assumes Jan 1 can never translate to the last Lunar month, which
+ // is true.
+ //
+ NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + lunarDate.month] - lunarDate.day);
+ Contract.Assert(NumDays >= 1, "NumDays >= 1");
+
+ // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month
+ // and day.
+ if (NumDays > 1)
+ {
+ //
+ // See if we're on the correct Lunar month.
+ //
+ while (NumDays > (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month]))
+ {
+ //
+ // Adjust the number of days and move to the next month.
+ //
+ NumDays -= (long)(s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month++]);
+
+ //
+ // See if we need to adjust the Year.
+ // Must handle both 12 and 13 month years.
+ //
+ if ((result.month > 13) || (s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + result.month] == 0))
+ {
+ //
+ // Adjust the Year.
+ //
+ result.year++;
+ hebrewYearType = s_hebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1];
+
+ //
+ // Adjust the Month.
+ //
+ result.month = 1;
+ }
+ }
+ //
+ // Found the right Lunar month.
+ //
+ result.day += (int)(NumDays - 1);
+ }
+ return (GetResult(result, part));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ try
+ {
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+
+
+ int monthsInYear;
+ int i;
+ if (months >= 0)
+ {
+ i = m + months;
+ while (i > (monthsInYear = GetMonthsInYear(y, CurrentEra)))
+ {
+ y++;
+ i -= monthsInYear;
+ }
+ }
+ else
+ {
+ if ((i = m + months) <= 0)
+ {
+ months = -months;
+ months -= m;
+ y--;
+
+ while (months > (monthsInYear = GetMonthsInYear(y, CurrentEra)))
+ {
+ y--;
+ months -= monthsInYear;
+ }
+ monthsInYear = GetMonthsInYear(y, CurrentEra);
+ i = monthsInYear - months;
+ }
+ }
+
+ int days = GetDaysInMonth(y, i);
+ if (d > days)
+ {
+ d = days;
+ }
+ return (new DateTime(ToDateTime(y, i, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay)));
+ }
+ // We expect ArgumentException and ArgumentOutOfRangeException (which is subclass of ArgumentException)
+ // If exception is thrown in the calls above, we are out of the supported range of this calendar.
+ catch (ArgumentException)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_AddValue));
+ }
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+
+ y += years;
+ CheckHebrewYearValue(y, Calendar.CurrentEra, "years");
+
+ int months = GetMonthsInYear(y, CurrentEra);
+ if (m > months)
+ {
+ m = months;
+ }
+
+ int days = GetDaysInMonth(y, m);
+ if (d > days)
+ {
+ d = days;
+ }
+
+ long ticks = ToDateTime(y, m, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ // If we calculate back, the Hebrew day of week for Gregorian 0001/1/1 is Monday (1).
+ // Therfore, the fomula is:
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ internal static int GetHebrewYearType(int year, int era)
+ {
+ CheckHebrewYearValue(year, era, "year");
+ // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear.
+ // So we need to convert year (Hebrew year value) to Gregorian Year below.
+ return (s_hebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]);
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ // Get Hebrew year value of the specified time.
+ int year = GetYear(time);
+ DateTime beginOfYearDate;
+ if (year == 5343)
+ {
+ // Gregorian 1583/01/01 corresponds to Hebrew 5343/04/07 (MinSupportedDateTime)
+ // To figure out the Gregorian date associated with Hebrew 5343/01/01, we need to
+ // count the days from 5343/01/01 to 5343/04/07 and subtract that from Gregorian
+ // 1583/01/01.
+ // 1. Tishri (30 days)
+ // 2. Heshvan (30 days since 5343 has 355 days)
+ // 3. Kislev (30 days since 5343 has 355 days)
+ // 96 days to get from 5343/01/01 to 5343/04/07
+ // Gregorian 1583/01/01 - 96 days = 1582/9/27
+
+ // the beginning of Hebrew year 5343 corresponds to Gregorian September 27, 1582.
+ beginOfYearDate = new DateTime(1582, 9, 27);
+ }
+ else
+ {
+ // following line will fail when year is 5343 (first supported year)
+ beginOfYearDate = ToDateTime(year, 1, 1, 0, 0, 0, 0, CurrentEra);
+ }
+ return ((int)((time.Ticks - beginOfYearDate.Ticks) / TicksPerDay) + 1);
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ CheckEraRange(era);
+ int hebrewYearType = GetHebrewYearType(year, era);
+ CheckHebrewMonthValue(year, month, era);
+
+ Contract.Assert(hebrewYearType >= 1 && hebrewYearType <= 6,
+ "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year);
+ int monthDays = s_lunarMonthLen[hebrewYearType * MaxMonthPlusOne + month];
+ if (monthDays == 0)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ return (monthDays);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ CheckEraRange(era);
+ // normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ // Leap years : 4 = 383 5 384 6 = 385 days.
+
+ // LunarYearType is from 1 to 6
+ int LunarYearType = GetHebrewYearType(year, era);
+ if (LunarYearType < 4)
+ {
+ // common year: LunarYearType = 1, 2, 3
+ return (352 + LunarYearType);
+ }
+ return (382 + (LunarYearType - 3));
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time)
+ {
+ return (HebrewEra);
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { HebrewEra });
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (IsLeapYear(year, era) ? 13 : 12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ if (IsLeapMonth(year, month, era))
+ {
+ // Every day in a leap month is a leap day.
+ CheckHebrewDayValue(year, month, day, era);
+ return (true);
+ }
+ else if (IsLeapYear(year, Calendar.CurrentEra))
+ {
+ // There is an additional day in the 6th month in the leap year (the extra day is the 30th day in the 6th month),
+ // so we should return true for 6/30 if that's in a leap year.
+ if (month == 6 && day == 30)
+ {
+ return (true);
+ }
+ }
+ CheckHebrewDayValue(year, month, day, era);
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ // Year/era values are checked in IsLeapYear().
+ if (IsLeapYear(year, era))
+ {
+ // The 7th month in a leap year is a leap month.
+ return (7);
+ }
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ // Year/era values are checked in IsLeapYear().
+ bool isLeapYear = IsLeapYear(year, era);
+ CheckHebrewMonthValue(year, month, era);
+ // The 7th month in a leap year is a leap month.
+ if (isLeapYear)
+ {
+ if (month == 7)
+ {
+ return (true);
+ }
+ }
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckHebrewYearValue(year, era, "year");
+ return (((7 * (long)year + 1) % 19) < 7);
+ }
+
+ // (month1, day1) - (month2, day2)
+ private static int GetDayDifference(int lunarYearType, int month1, int day1, int month2, int day2)
+ {
+ if (month1 == month2)
+ {
+ return (day1 - day2);
+ }
+
+ // Make sure that (month1, day1) < (month2, day2)
+ bool swap = (month1 > month2);
+ if (swap)
+ {
+ // (month1, day1) < (month2, day2). Swap the values.
+ // The result will be a negative number.
+ int tempMonth, tempDay;
+ tempMonth = month1; tempDay = day1;
+ month1 = month2; day1 = day2;
+ month2 = tempMonth; day2 = tempDay;
+ }
+
+ // Get the number of days from (month1,day1) to (month1, end of month1)
+ int days = s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1] - day1;
+
+ // Move to next month.
+ month1++;
+
+ // Add up the days.
+ while (month1 < month2)
+ {
+ days += s_lunarMonthLen[lunarYearType * MaxMonthPlusOne + month1++];
+ }
+ days += day2;
+
+ return (swap ? days : -days);
+ }
+
+ /*=================================HebrewToGregorian==========================
+ **Action: Convert Hebrew date to Gregorian date.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ** The algorithm is like this:
+ ** The hebrew year has an offset to the Gregorian year, so we can guess the Gregorian year for
+ ** the specified Hebrew year. That is, GreogrianYear = HebrewYear - FirstHebrewYearOf1AD.
+ **
+ ** From the Gregorian year and HebrewTable, we can get the Hebrew month/day value
+ ** of the Gregorian date January 1st. Let's call this month/day value [hebrewDateForJan1]
+ **
+ ** If the requested Hebrew month/day is less than [hebrewDateForJan1], we know the result
+ ** Gregorian date falls in previous year. So we decrease the Gregorian year value, and
+ ** retrieve the Hebrew month/day value of the Gregorian date january 1st again.
+ **
+ ** Now, we get the answer of the Gregorian year.
+ **
+ ** The next step is to get the number of days between the requested Hebrew month/day
+ ** and [hebrewDateForJan1]. When we get that, we can create the DateTime by adding/subtracting
+ ** the ticks value of the number of days.
+ **
+ ============================================================================*/
+
+
+ private static DateTime HebrewToGregorian(int hebrewYear, int hebrewMonth, int hebrewDay, int hour, int minute, int second, int millisecond)
+ {
+ // Get the rough Gregorian year for the specified hebrewYear.
+ //
+ int gregorianYear = hebrewYear - HebrewYearOf1AD;
+
+ __DateBuffer hebrewDateOfJan1 = new __DateBuffer(); // year value is unused.
+ int lunarYearType = GetLunarMonthDay(gregorianYear, hebrewDateOfJan1);
+
+ if ((hebrewMonth == hebrewDateOfJan1.month) && (hebrewDay == hebrewDateOfJan1.day))
+ {
+ return (new DateTime(gregorianYear, 1, 1, hour, minute, second, millisecond));
+ }
+
+ int days = GetDayDifference(lunarYearType, hebrewMonth, hebrewDay, hebrewDateOfJan1.month, hebrewDateOfJan1.day);
+
+ DateTime gregorianNewYear = new DateTime(gregorianYear, 1, 1);
+ return (new DateTime(gregorianNewYear.Ticks + days * TicksPerDay
+ + TimeToTicks(hour, minute, second, millisecond)));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ CheckHebrewYearValue(year, era, "year");
+ CheckHebrewMonthValue(year, month, era);
+ CheckHebrewDayValue(year, month, day, era);
+ DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond);
+ CheckTicksRange(dt.Ticks);
+ return (dt);
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 5790;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value == 99)
+ {
+ // Do nothing here. Year 99 is allowed so that TwoDitYearMax is disabled.
+ }
+ else
+ {
+ CheckHebrewYearValue(value, HebrewEra, "value");
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100)
+ {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxHebrewYear || year < MinHebrewYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MinHebrewYear,
+ MaxHebrewYear));
+ }
+ return (year);
+ }
+
+ internal class __DateBuffer
+ {
+ internal int year;
+ internal int month;
+ internal int day;
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs b/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs
new file mode 100644
index 0000000000..8fc264b788
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/HebrewNumber.cs
@@ -0,0 +1,465 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Text;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+
+#if INSIDE_CLR
+ using Debug = BCLDebug;
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Used in HebrewNumber.ParseByChar to maintain the context information (
+ // the state in the state machine and current Hebrew number values, etc.)
+ // when parsing Hebrew number character by character.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal struct HebrewNumberParsingContext
+ {
+ // The current state of the state machine for parsing Hebrew numbers.
+ internal HebrewNumber.HS state;
+ // The current value of the Hebrew number.
+ // The final value is determined when state is FoundEndOfHebrewNumber.
+ internal int result;
+
+ public HebrewNumberParsingContext(int result)
+ {
+ // Set the start state of the state machine for parsing Hebrew numbers.
+ state = HebrewNumber.HS.Start;
+ this.result = result;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Please see ParseByChar() for comments about different states defined here.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum HebrewNumberParsingState
+ {
+ InvalidHebrewNumber,
+ NotHebrewDigit,
+ FoundEndOfHebrewNumber,
+ ContinueParsing,
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // class HebrewNumber
+ //
+ // Provides static methods for formatting integer values into
+ // Hebrew text and parsing Hebrew number text.
+ //
+ // Limitations:
+ // Parse can only handles value 1 ~ 999.
+ // ToString() can only handles 1 ~ 999. If value is greater than 5000,
+ // 5000 will be subtracted from the value.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal class HebrewNumber
+ {
+ // This class contains only static methods. Add a private ctor so that
+ // compiler won't generate a default one for us.
+ private HebrewNumber()
+ {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Converts the given number to Hebrew letters according to the numeric
+ // value of each Hebrew letter. Basically, this converts the lunar year
+ // and the lunar month to letters.
+ //
+ // The character of a year is described by three letters of the Hebrew
+ // alphabet, the first and third giving, respectively, the days of the
+ // weeks on which the New Year occurs and Passover begins, while the
+ // second is the initial of the Hebrew word for defective, normal, or
+ // complete.
+ //
+ // Defective Year : Both Heshvan and Kislev are defective (353 or 383 days)
+ // Normal Year : Heshvan is defective, Kislev is full (354 or 384 days)
+ // Complete Year : Both Heshvan and Kislev are full (355 or 385 days)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal static String ToString(int Number)
+ {
+ char cTens = '\x0';
+ char cUnits; // tens and units chars
+ int Hundreds, Tens; // hundreds and tens values
+ StringBuilder szHebrew = new StringBuilder();
+
+
+ //
+ // Adjust the number if greater than 5000.
+ //
+ if (Number > 5000)
+ {
+ Number -= 5000;
+ }
+
+ Contract.Assert(Number > 0 && Number <= 999, "Number is out of range."); ;
+
+ //
+ // Get the Hundreds.
+ //
+ Hundreds = Number / 100;
+
+ if (Hundreds > 0)
+ {
+ Number -= Hundreds * 100;
+ // \x05e7 = 100
+ // \x05e8 = 200
+ // \x05e9 = 300
+ // \x05ea = 400
+ // If the number is greater than 400, use the multiples of 400.
+ for (int i = 0; i < (Hundreds / 4); i++)
+ {
+ szHebrew.Append('\x05ea');
+ }
+
+ int remains = Hundreds % 4;
+ if (remains > 0)
+ {
+ szHebrew.Append((char)((int)'\x05e6' + remains));
+ }
+ }
+
+ //
+ // Get the Tens.
+ //
+ Tens = Number / 10;
+ Number %= 10;
+
+ switch (Tens)
+ {
+ case (0):
+ cTens = '\x0';
+ break;
+ case (1):
+ cTens = '\x05d9'; // Hebrew Letter Yod
+ break;
+ case (2):
+ cTens = '\x05db'; // Hebrew Letter Kaf
+ break;
+ case (3):
+ cTens = '\x05dc'; // Hebrew Letter Lamed
+ break;
+ case (4):
+ cTens = '\x05de'; // Hebrew Letter Mem
+ break;
+ case (5):
+ cTens = '\x05e0'; // Hebrew Letter Nun
+ break;
+ case (6):
+ cTens = '\x05e1'; // Hebrew Letter Samekh
+ break;
+ case (7):
+ cTens = '\x05e2'; // Hebrew Letter Ayin
+ break;
+ case (8):
+ cTens = '\x05e4'; // Hebrew Letter Pe
+ break;
+ case (9):
+ cTens = '\x05e6'; // Hebrew Letter Tsadi
+ break;
+ }
+
+ //
+ // Get the Units.
+ //
+ cUnits = (char)(Number > 0 ? ((int)'\x05d0' + Number - 1) : 0);
+
+ if ((cUnits == '\x05d4') && // Hebrew Letter He (5)
+ (cTens == '\x05d9'))
+ { // Hebrew Letter Yod (10)
+ cUnits = '\x05d5'; // Hebrew Letter Vav (6)
+ cTens = '\x05d8'; // Hebrew Letter Tet (9)
+ }
+
+ if ((cUnits == '\x05d5') && // Hebrew Letter Vav (6)
+ (cTens == '\x05d9'))
+ { // Hebrew Letter Yod (10)
+ cUnits = '\x05d6'; // Hebrew Letter Zayin (7)
+ cTens = '\x05d8'; // Hebrew Letter Tet (9)
+ }
+
+ //
+ // Copy the appropriate info to the given buffer.
+ //
+
+ if (cTens != '\x0')
+ {
+ szHebrew.Append(cTens);
+ }
+
+ if (cUnits != '\x0')
+ {
+ szHebrew.Append(cUnits);
+ }
+
+ if (szHebrew.Length > 1)
+ {
+ szHebrew.Insert(szHebrew.Length - 1, '"');
+ }
+ else
+ {
+ szHebrew.Append('\'');
+ }
+
+ //
+ // Return success.
+ //
+ return (szHebrew.ToString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Token used to tokenize a Hebrew word into tokens so that we can use in the
+ // state machine.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private enum HebrewToken : short
+ {
+ Invalid = -1,
+ Digit400 = 0,
+ Digit200_300 = 1,
+ Digit100 = 2,
+ Digit10 = 3, // 10 ~ 90
+ Digit1 = 4, // 1, 2, 3, 4, 5, 8,
+ Digit6_7 = 5,
+ Digit7 = 6,
+ Digit9 = 7,
+ SingleQuote = 8,
+ DoubleQuote = 9,
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // This class is used to map a token into its Hebrew digit value.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private struct HebrewValue
+ {
+ internal HebrewToken token;
+ internal short value;
+ internal HebrewValue(HebrewToken token, short value)
+ {
+ this.token = token;
+ this.value = value;
+ }
+ }
+
+ //
+ // Map a Hebrew character from U+05D0 ~ U+05EA to its digit value.
+ // The value is -1 if the Hebrew character does not have a associated value.
+ //
+ private static readonly HebrewValue[] s_hebrewValues = {
+ new HebrewValue(HebrewToken.Digit1, 1) , // '\x05d0
+ new HebrewValue(HebrewToken.Digit1, 2) , // '\x05d1
+ new HebrewValue(HebrewToken.Digit1, 3) , // '\x05d2
+ new HebrewValue(HebrewToken.Digit1, 4) , // '\x05d3
+ new HebrewValue(HebrewToken.Digit1, 5) , // '\x05d4
+ new HebrewValue(HebrewToken.Digit6_7,6) , // '\x05d5
+ new HebrewValue(HebrewToken.Digit6_7,7) , // '\x05d6
+ new HebrewValue(HebrewToken.Digit1, 8) , // '\x05d7
+ new HebrewValue(HebrewToken.Digit9, 9) , // '\x05d8
+ new HebrewValue(HebrewToken.Digit10, 10) , // '\x05d9; // Hebrew Letter Yod
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05da;
+ new HebrewValue(HebrewToken.Digit10, 20) , // '\x05db; // Hebrew Letter Kaf
+ new HebrewValue(HebrewToken.Digit10, 30) , // '\x05dc; // Hebrew Letter Lamed
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05dd;
+ new HebrewValue(HebrewToken.Digit10, 40) , // '\x05de; // Hebrew Letter Mem
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05df;
+ new HebrewValue(HebrewToken.Digit10, 50) , // '\x05e0; // Hebrew Letter Nun
+ new HebrewValue(HebrewToken.Digit10, 60) , // '\x05e1; // Hebrew Letter Samekh
+ new HebrewValue(HebrewToken.Digit10, 70) , // '\x05e2; // Hebrew Letter Ayin
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e3;
+ new HebrewValue(HebrewToken.Digit10, 80) , // '\x05e4; // Hebrew Letter Pe
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e5;
+ new HebrewValue(HebrewToken.Digit10, 90) , // '\x05e6; // Hebrew Letter Tsadi
+ new HebrewValue(HebrewToken.Digit100, 100) , // '\x05e7;
+ new HebrewValue(HebrewToken.Digit200_300, 200) , // '\x05e8;
+ new HebrewValue(HebrewToken.Digit200_300, 300) , // '\x05e9;
+ new HebrewValue(HebrewToken.Digit400, 400) , // '\x05ea;
+ };
+
+ private const int minHebrewNumberCh = 0x05d0;
+ private static char s_maxHebrewNumberCh = (char)(minHebrewNumberCh + s_hebrewValues.Length - 1);
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Hebrew number parsing State
+ // The current state and the next token will lead to the next state in the state machine.
+ // DQ = Double Quote
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum HS : sbyte
+ {
+ _err = -1, // an error state
+ Start = 0,
+ S400 = 1, // a Hebrew digit 400
+ S400_400 = 2, // Two Hebrew digit 400
+ S400_X00 = 3, // Two Hebrew digit 400 and followed by 100
+ S400_X0 = 4, // Hebrew digit 400 and followed by 10 ~ 90
+ X00_DQ = 5, // A hundred number and followed by a double quote.
+ S400_X00_X0 = 6,
+ X0_DQ = 7, // A two-digit number and followed by a double quote.
+ X = 8, // A single digit Hebrew number.
+ X0 = 9, // A two-digit Hebrew number
+ X00 = 10, // A three-digit Hebrew number
+ S400_DQ = 11, // A Hebrew digit 400 and followed by a double quote.
+ S400_400_DQ = 12,
+ S400_400_100 = 13,
+ S9 = 14, // Hebrew digit 9
+ X00_S9 = 15, // A hundered number and followed by a digit 9
+ S9_DQ = 16, // Hebrew digit 9 and followed by a double quote
+ END = 100, // A terminial state is reached.
+ }
+
+ //
+ // The state machine for Hebrew number pasing.
+ //
+ private readonly static HS[] s_numberPasingState =
+ {
+ // 400 300/200 100 90~10 8~1 6, 7, 9, ' "
+ /* 0 */
+ HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err,
+ /* 1: S400 */
+ HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS.END, HS.S400_DQ,
+ /* 2: S400_400 */
+ HS._err, HS._err, HS.S400_400_100,HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.S400_400_DQ,
+ /* 3: S400_X00 */
+ HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.X00_DQ,
+ /* 4: S400_X0 */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ,
+ /* 5: X00_DQ */
+ HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
+ /* 6: S400_X00_X0 */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ,
+ /* 7: X0_DQ */
+ HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
+ /* 8: X */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err,
+ /* 9: X0 */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ,
+ /* 10: X00 */
+ HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ,
+ /* 11: S400_DQ */
+ HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
+ /* 12: S400_400_DQ*/
+ HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err,
+ /* 13: S400_400_100*/
+ HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ,
+ /* 14: S9 */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.S9_DQ,
+ /* 15: X00_S9 */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ,
+ /* 16: S9_DQ */
+ HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err
+ };
+
+ // Count of valid HebrewToken, column count in the NumberPasingState array
+ private const int HebrewTokenCount = 10;
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Parse the Hebrew number by passing one character at a time.
+ // The state between characters are maintained at HebrewNumberPasingContext.
+ // Returns:
+ // Return a enum of HebrewNumberParsingState.
+ // NotHebrewDigit: The specified ch is not a valid Hebrew digit.
+ // InvalidHebrewNumber: After parsing the specified ch, it will lead into
+ // an invalid Hebrew number text.
+ // FoundEndOfHebrewNumber: A terminal state is reached. This means that
+ // we find a valid Hebrew number text after the specified ch is parsed.
+ // ContinueParsing: The specified ch is a valid Hebrew digit, and
+ // it will lead into a valid state in the state machine, we should
+ // continue to parse incoming characters.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static HebrewNumberParsingState ParseByChar(char ch, ref HebrewNumberParsingContext context)
+ {
+ Debug.Assert(s_numberPasingState.Length == HebrewTokenCount * ((int)HS.S9_DQ + 1));
+
+ HebrewToken token;
+ if (ch == '\'')
+ {
+ token = HebrewToken.SingleQuote;
+ }
+ else if (ch == '\"')
+ {
+ token = HebrewToken.DoubleQuote;
+ }
+ else
+ {
+ int index = (int)ch - minHebrewNumberCh;
+ if (index >= 0 && index < s_hebrewValues.Length)
+ {
+ token = s_hebrewValues[index].token;
+ if (token == HebrewToken.Invalid)
+ {
+ return (HebrewNumberParsingState.NotHebrewDigit);
+ }
+ context.result += s_hebrewValues[index].value;
+ }
+ else
+ {
+ // Not in valid Hebrew digit range.
+ return (HebrewNumberParsingState.NotHebrewDigit);
+ }
+ }
+ context.state = s_numberPasingState[(int)context.state * (int)HebrewTokenCount + (int)token];
+ if (context.state == HS._err)
+ {
+ // Invalid Hebrew state. This indicates an incorrect Hebrew number.
+ return (HebrewNumberParsingState.InvalidHebrewNumber);
+ }
+ if (context.state == HS.END)
+ {
+ // Reach a terminal state.
+ return (HebrewNumberParsingState.FoundEndOfHebrewNumber);
+ }
+ // We should continue to parse.
+ return (HebrewNumberParsingState.ContinueParsing);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Check if the ch is a valid Hebrew number digit.
+ // This function will return true if the specified char is a legal Hebrew
+ // digit character, single quote, or double quote.
+ // Returns:
+ // true if the specified character is a valid Hebrew number character.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static bool IsDigit(char ch)
+ {
+ if (ch >= minHebrewNumberCh && ch <= s_maxHebrewNumberCh)
+ {
+ return (s_hebrewValues[ch - minHebrewNumberCh].value >= 0);
+ }
+ return (ch == '\'' || ch == '\"');
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs
new file mode 100644
index 0000000000..a6e8f73d3e
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Unix.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ public partial class HijriCalendar : Calendar
+ {
+ private static int GetHijriDateAdjustment()
+ {
+ // this setting is not supported on Unix, so always return 0
+ return 0;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs
new file mode 100644
index 0000000000..185c5184be
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.Windows.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Internal.Runtime.Augments;
+
+namespace System.Globalization
+{
+ public partial class HijriCalendar : Calendar
+ {
+ public static int GetHijriDateAdjustment()
+ {
+ return WinRTInterop.Callbacks.GetHijriDateAdjustment();
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs
new file mode 100644
index 0000000000..72d9ab3f52
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/HijriCalendar.cs
@@ -0,0 +1,675 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Rules for the Hijri calendar:
+ // - The Hijri calendar is a strictly Lunar calendar.
+ // - Days begin at sunset.
+ // - Islamic Year 1 (Muharram 1, 1 A.H.) is equivalent to absolute date
+ // 227015 (Friday, July 16, 622 C.E. - Julian).
+ // - Leap Years occur in the 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, & 29th
+ // years of a 30-year cycle. Year = leap iff ((11y+14) mod 30 < 11).
+ // - There are 12 months which contain alternately 30 and 29 days.
+ // - The 12th month, Dhu al-Hijjah, contains 30 days instead of 29 days
+ // in a leap year.
+ // - Common years have 354 days. Leap years have 355 days.
+ // - There are 10,631 days in a 30-year cycle.
+ // - The Islamic months are:
+ // 1. Muharram (30 days) 7. Rajab (30 days)
+ // 2. Safar (29 days) 8. Sha'ban (29 days)
+ // 3. Rabi I (30 days) 9. Ramadan (30 days)
+ // 4. Rabi II (29 days) 10. Shawwal (29 days)
+ // 5. Jumada I (30 days) 11. Dhu al-Qada (30 days)
+ // 6. Jumada II (29 days) 12. Dhu al-Hijjah (29 days) {30}
+ //
+ // NOTENOTE
+ // The calculation of the HijriCalendar is based on the absolute date. And the
+ // absolute date means the number of days from January 1st, 1 A.D.
+ // Therefore, we do not support the days before the January 1st, 1 A.D.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0622/07/18 9999/12/31
+ ** Hijri 0001/01/01 9666/04/03
+ */
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class HijriCalendar : Calendar
+ {
+ internal static readonly int HijriEra = 1;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ internal const int MinAdvancedHijri = -2;
+ internal const int MaxAdvancedHijri = 2;
+
+ internal static readonly int[] HijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 };
+
+ private int _hijriAdvance = Int32.MinValue;
+
+ // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
+ internal const int MaxCalendarYear = 9666;
+ internal const int MaxCalendarMonth = 4;
+ internal const int MaxCalendarDay = 3;
+ // Hijri calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 7, day: 18)
+ // This is the minimal Gregorian date that we support in the HijriCalendar.
+ internal static readonly DateTime calendarMinValue = new DateTime(622, 7, 18);
+ internal static readonly DateTime calendarMaxValue = DateTime.MaxValue;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (calendarMaxValue);
+ }
+ }
+
+ public HijriCalendar()
+ {
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.HIJRI;
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // the year before the 1st year of the cycle would have been the 30th year
+ // of the previous cycle which is not a leap year. Common years have 354 days.
+ return 354;
+ }
+ }
+
+
+
+ /*=================================GetAbsoluteDateHijri==========================
+ **Action: Gets the Absolute date for the given Hijri date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ private long GetAbsoluteDateHijri(int y, int m, int d)
+ {
+ return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m - 1] + d - 1 - HijriAdjustment);
+ }
+
+ /*=================================DaysUpToHijriYear==========================
+ **Action: Gets the total number of days (absolute date) up to the given Hijri Year.
+ ** The absolute date means the number of days from January 1st, 1 A.D.
+ **Returns: Gets the total number of days (absolute date) up to the given Hijri Year.
+ **Arguments: HijriYear year value in Hijri calendar.
+ **Exceptions: None
+ **Notes:
+ ============================================================================*/
+
+ private long DaysUpToHijriYear(int HijriYear)
+ {
+ long NumDays; // number of absolute days
+ int NumYear30; // number of years up to current 30 year cycle
+ int NumYearsLeft; // number of years into 30 year cycle
+
+ //
+ // Compute the number of years up to the current 30 year cycle.
+ //
+ NumYear30 = ((HijriYear - 1) / 30) * 30;
+
+ //
+ // Compute the number of years left. This is the number of years
+ // into the 30 year cycle for the given year.
+ //
+ NumYearsLeft = HijriYear - NumYear30 - 1;
+
+ //
+ // Compute the number of absolute days up to the given year.
+ //
+ NumDays = ((NumYear30 * 10631L) / 30L) + 227013L;
+ while (NumYearsLeft > 0)
+ {
+ // Common year is 354 days, and leap year is 355 days.
+ NumDays += 354 + (IsLeapYear(NumYearsLeft, CurrentEra) ? 1 : 0);
+ NumYearsLeft--;
+ }
+
+ //
+ // Return the number of absolute days.
+ //
+ return (NumDays);
+ }
+
+ public int HijriAdjustment
+ {
+ get
+ {
+ if (_hijriAdvance == Int32.MinValue)
+ {
+ // Never been set before. Use the system value from registry.
+ _hijriAdvance = GetHijriDateAdjustment();
+ }
+ return (_hijriAdvance);
+ }
+
+ set
+ {
+ // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good.
+ if (value < MinAdvancedHijri || value > MaxAdvancedHijri)
+ {
+ throw new ArgumentOutOfRangeException(
+ "HijriAdjustment",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Bounds_Lower_Upper,
+ MinAdvancedHijri,
+ MaxAdvancedHijri));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ _hijriAdvance = value;
+ }
+ }
+
+ internal static void CheckTicksRange(long ticks)
+ {
+ if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.ArgumentOutOfRange_CalendarRange,
+ calendarMinValue,
+ calendarMaxValue));
+ }
+ }
+
+ internal static void CheckEraRange(int era)
+ {
+ if (era != CurrentEra && era != HijriEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ internal static void CheckYearRange(int year, int era)
+ {
+ CheckEraRange(era);
+ if (year < 1 || year > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarYear));
+ }
+ }
+
+ internal static void CheckYearMonthRange(int year, int month, int era)
+ {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear)
+ {
+ if (month > MaxCalendarMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarMonth));
+ }
+ }
+
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ **Notes:
+ ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
+ ** Use the formula (((AbsoluteDate - 227013) * 30) / 10631) + 1, we can a rough value for the Hijri year.
+ ** In order to get the exact Hijri year, we compare the exact absolute date for HijriYear and (HijriYear + 1).
+ ** From here, we can get the correct Hijri year.
+ ============================================================================*/
+
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ int HijriYear; // Hijri year
+ int HijriMonth; // Hijri month
+ int HijriDay; // Hijri day
+ long NumDays; // The calculation buffer in number of days.
+
+ CheckTicksRange(ticks);
+
+ //
+ // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ //
+ NumDays = ticks / GregorianCalendar.TicksPerDay + 1;
+
+ //
+ // See how much we need to backup or advance
+ //
+ NumDays += HijriAdjustment;
+
+ //
+ // Calculate the appromixate Hijri Year from this magic formula.
+ //
+ HijriYear = (int)(((NumDays - 227013) * 30) / 10631) + 1;
+
+ long daysToHijriYear = DaysUpToHijriYear(HijriYear); // The absoulte date for HijriYear
+ long daysOfHijriYear = GetDaysInYear(HijriYear, CurrentEra); // The number of days for (HijriYear+1) year.
+
+ if (NumDays < daysToHijriYear)
+ {
+ daysToHijriYear -= daysOfHijriYear;
+ HijriYear--;
+ }
+ else if (NumDays == daysToHijriYear)
+ {
+ HijriYear--;
+ daysToHijriYear -= GetDaysInYear(HijriYear, CurrentEra);
+ }
+ else
+ {
+ if (NumDays > daysToHijriYear + daysOfHijriYear)
+ {
+ daysToHijriYear += daysOfHijriYear;
+ HijriYear++;
+ }
+ }
+ if (part == DatePartYear)
+ {
+ return (HijriYear);
+ }
+
+ //
+ // Calculate the Hijri Month.
+ //
+
+ HijriMonth = 1;
+ NumDays -= daysToHijriYear;
+
+ if (part == DatePartDayOfYear)
+ {
+ return ((int)NumDays);
+ }
+
+ while ((HijriMonth <= 12) && (NumDays > HijriMonthDays[HijriMonth - 1]))
+ {
+ HijriMonth++;
+ }
+ HijriMonth--;
+
+ if (part == DatePartMonth)
+ {
+ return (HijriMonth);
+ }
+
+ //
+ // Calculate the Hijri Day.
+ //
+ HijriDay = (int)(NumDays - HijriMonthDays[HijriMonth - 1]);
+
+ if (part == DatePartDay)
+ {
+ return (HijriDay);
+ }
+ // Incorrect part value.
+ throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in Hijri calendar.
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int days = GetDaysInMonth(y, m);
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = GetAbsoluteDateHijri(y, m, d) * TicksPerDay + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+ [Pure]
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+ if (month == 12)
+ {
+ // For the 12th month, leap year has 30 days, and common year has 29 days.
+ return (IsLeapYear(year, CurrentEra) ? 30 : 29);
+ }
+ // Other months contain 30 and 29 days alternatively. The 1st month has 30 days.
+ return (((month % 2) == 1) ? 30 : 29);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ // Common years have 354 days. Leap years have 355 days.
+ return (IsLeapYear(year, CurrentEra) ? 355 : 354);
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return (HijriEra);
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { HijriEra });
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+ return (IsLeapYear(year, era) && month == 12 && day == 30);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return ((((year * 11) + 14) % 30) < 11);
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ // The year/month/era checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+
+ long lDate = GetAbsoluteDateHijri(year, month, day);
+
+ if (lDate >= 0)
+ {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ MaxCalendarYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100)
+ {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs b/src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs
new file mode 100644
index 0000000000..0a4e6f0600
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/InternalGlobalizationHelper.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Globalization
+{
+ internal class InternalGloablizationHelper
+ {
+ // Copied from the TimeSpan to be used inside the globalization code and avoid internal dependancy on TimeSpan class
+ internal static long TimeToTicks(int hour, int minute, int second)
+ {
+ // totalSeconds is bounded by 2^31 * 2^12 + 2^31 * 2^8 + 2^31,
+ // which is less than 2^44, meaning we won't overflow totalSeconds.
+ long totalSeconds = (long)hour * 3600 + (long)minute * 60 + (long)second;
+ if (totalSeconds > MaxSeconds || totalSeconds < MinSeconds)
+ throw new ArgumentOutOfRangeException(null, SR.Overflow_TimeSpanTooLong);
+ return totalSeconds * TicksPerSecond;
+ }
+
+
+ //
+ // Define needed constants so globalization code can be independant from any other types
+ //
+
+ internal const long TicksPerMillisecond = 10000;
+ internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
+ internal const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
+ internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+ private const int DaysPerYear = 365;
+ private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
+ private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
+ private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
+ private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059
+ private const long TicksPerMinute = TicksPerSecond * 60;
+ private const long TicksPerHour = TicksPerMinute * 60;
+ private const long TicksPerDay = TicksPerHour * 24;
+ internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
+ internal const long MinTicks = 0;
+ internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+
+ internal const int StringBuilderDefaultCapacity = 16;
+
+ internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const Int64 MinOffset = -MaxOffset;
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs
new file mode 100644
index 0000000000..12f430c71c
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Unix.cs
@@ -0,0 +1,91 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Security;
+
+namespace System.Globalization
+{
+ public partial class JapaneseCalendar : Calendar
+ {
+ [SecuritySafeCritical]
+ private static EraInfo[] GetJapaneseEras()
+ {
+ string[] eraNames;
+ if (!CalendarData.EnumCalendarInfo("ja-JP", CalendarId.JAPAN, CalendarDataType.EraNames, out eraNames))
+ {
+ return null;
+ }
+
+ string[] abbrevEnglishEraNames;
+ if (!CalendarData.EnumCalendarInfo("en", CalendarId.JAPAN, CalendarDataType.AbbrevEraNames, out abbrevEnglishEraNames))
+ {
+ return null;
+ }
+
+ List<EraInfo> eras = new List<EraInfo>();
+ int lastMaxYear = GregorianCalendar.MaxYear;
+
+ int latestEra = Interop.GlobalizationInterop.GetLatestJapaneseEra();
+ for (int i = latestEra; i >= 0; i--)
+ {
+ DateTime dt;
+ if (!GetJapaneseEraStartDate(i, out dt))
+ {
+ return null;
+ }
+
+ if (dt < JapaneseCalendar.calendarMinValue)
+ {
+ // only populate the Eras that are valid JapaneseCalendar date times
+ break;
+ }
+
+ eras.Add(new EraInfo(i, dt.Year, dt.Month, dt.Day, dt.Year - 1, 1, lastMaxYear - dt.Year + 1,
+ eraNames[i], GetAbbreviatedEraName(eraNames, i), abbrevEnglishEraNames[i]));
+
+ lastMaxYear = dt.Year;
+ }
+
+ // remap the Era numbers, now that we know how many there will be
+ for (int i = 0; i < eras.Count; i++)
+ {
+ eras[i].era = eras.Count - i;
+ }
+
+ return eras.ToArray();
+ }
+
+ // PAL Layer ends here
+
+ private static string GetAbbreviatedEraName(string[] eraNames, int eraIndex)
+ {
+ // This matches the behavior on Win32 - only returning the first character of the era name.
+ // See Calendar.EraAsString(Int32) - https://msdn.microsoft.com/en-us/library/windows/apps/br206751.aspx
+ return eraNames[eraIndex].Substring(0, 1);
+ }
+
+ [SecuritySafeCritical]
+ private static bool GetJapaneseEraStartDate(int era, out DateTime dateTime)
+ {
+ dateTime = default(DateTime);
+
+ int startYear;
+ int startMonth;
+ int startDay;
+ bool result = Interop.GlobalizationInterop.GetJapaneseEraStartDate(
+ era,
+ out startYear,
+ out startMonth,
+ out startDay);
+
+ if (result)
+ {
+ dateTime = new DateTime(startYear, startMonth, startDay);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs
new file mode 100644
index 0000000000..6a9df97200
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.Windows.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+using Internal.Runtime.Augments;
+
+namespace System.Globalization
+{
+ public partial class JapaneseCalendar : Calendar
+ {
+ private static EraInfo[] GetJapaneseEras()
+ {
+ int erasCount = WinRTInterop.Callbacks.GetJapaneseEraCount();
+ if (erasCount < 4)
+ {
+ return null;
+ }
+
+ EraInfo[] eras = new EraInfo[erasCount];
+ int lastMaxYear = GregorianCalendar.MaxYear;
+
+ for (int i = erasCount; i > 0; i--)
+ {
+ DateTimeOffset dateOffset;
+
+ string eraName;
+ string abbreviatedEraName;
+
+ if (!GetJapaneseEraInfo(i, out dateOffset, out eraName, out abbreviatedEraName))
+ {
+ return null;
+ }
+
+ DateTime dt = new DateTime(dateOffset.Ticks);
+
+ eras[erasCount - i] = new EraInfo(i, dt.Year, dt.Month, dt.Day, dt.Year - 1, 1, lastMaxYear - dt.Year + 1,
+ eraName, abbreviatedEraName, GetJapaneseEnglishEraName(i)); // era #4 start year/month/day, yearOffset, minEraYear
+
+ lastMaxYear = dt.Year;
+ }
+
+ return eras;
+ }
+
+ // PAL Layer ends here
+
+ private static string[] JapaneseErasEnglishNames = new String[] { "M", "T", "S", "H" };
+
+ private static string GetJapaneseEnglishEraName(int era)
+ {
+ Debug.Assert(era > 0);
+ return era <= JapaneseErasEnglishNames.Length ? JapaneseErasEnglishNames[era - 1] : " ";
+ }
+
+ private static bool GetJapaneseEraInfo(int era, out DateTimeOffset dateOffset, out string eraName, out string abbreviatedEraName)
+ {
+ return WinRTInterop.Callbacks.GetJapaneseEraInfo(era, out dateOffset, out eraName, out abbreviatedEraName);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs
new file mode 100644
index 0000000000..4130801de5
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/JapaneseCalendar.cs
@@ -0,0 +1,413 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+
+#if INSIDE_CLR
+ using Debug = BCLDebug;
+#endif
+
+ /*=================================JapaneseCalendar==========================
+ **
+ ** JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as
+ ** Gregorian calendar. However, the year value is an offset to the Gregorian
+ ** year based on the era.
+ **
+ ** This system is adopted by Emperor Meiji in 1868. The year value is counted based on the reign of an emperor,
+ ** and the era begins on the day an emperor ascends the throne and continues until his death.
+ ** The era changes at 12:00AM.
+ **
+ ** For example, the current era is Heisei. It started on 1989/1/8 A.D. Therefore, Gregorian year 1989 is also Heisei 1st.
+ ** 1989/1/8 A.D. is also Heisei 1st 1/8.
+ **
+ ** Any date in the year during which era is changed can be reckoned in either era. For example,
+ ** 1989/1/1 can be 1/1 Heisei 1st year or 1/1 Showa 64th year.
+ **
+ ** Note:
+ ** The DateTime can be represented by the JapaneseCalendar are limited to two factors:
+ ** 1. The min value and max value of DateTime class.
+ ** 2. The available era information.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1868/09/08 9999/12/31
+ ** Japanese Meiji 01/01 Heisei 8011/12/31
+ ============================================================================*/
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class JapaneseCalendar : Calendar
+ {
+ internal static readonly DateTime calendarMinValue = new DateTime(1868, 9, 8);
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ //
+ // Using a field initializer rather than a static constructor so that the whole class can be lazy
+ // init.
+ internal static volatile EraInfo[] japaneseEraInfo;
+
+ //
+ // Read our era info
+ //
+ // m_EraInfo must be listed in reverse chronological order. The most recent era
+ // should be the first element.
+ // That is, m_EraInfo[0] contains the most recent era.
+ //
+ // We know about 4 built-in eras, however users may add additional era(s) from the
+ // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
+ // we don't read the registry and instead we call WinRT to get the needed informatio
+ //
+ // Registry values look like:
+ // yyyy.mm.dd=era_abbrev_english_englishabbrev
+ //
+ // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
+ // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
+ // era is the Japanese Era name
+ // abbrev is the Abbreviated Japanese Era Name
+ // english is the English name for the Era (unused)
+ // englishabbrev is the Abbreviated English name for the era.
+ // . is a delimiter, but the value of . doesn't matter.
+ // '_' marks the space between the japanese era name, japanese abbreviated era name
+ // english name, and abbreviated english names.
+ //
+ internal static EraInfo[] GetEraInfo()
+ {
+ // See if we need to build it
+ if (japaneseEraInfo == null)
+ {
+ japaneseEraInfo = GetJapaneseEras();
+ // See if we have to use the built-in eras
+ if (japaneseEraInfo == null)
+ {
+ // We know about some built-in ranges
+ EraInfo[] defaultEraRanges = new EraInfo[4];
+ defaultEraRanges[0] = new EraInfo(4, 1989, 1, 8, 1988, 1, GregorianCalendar.MaxYear - 1988,
+ "\x5e73\x6210", "\x5e73", "H"); // era #4 start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[1] = new EraInfo(3, 1926, 12, 25, 1925, 1, 1989 - 1925,
+ "\x662d\x548c", "\x662d", "S"); // era #3,start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[2] = new EraInfo(2, 1912, 7, 30, 1911, 1, 1926 - 1911,
+ "\x5927\x6b63", "\x5927", "T"); // era #2,start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[3] = new EraInfo(1, 1868, 1, 1, 1867, 1, 1912 - 1867,
+ "\x660e\x6cbb", "\x660e", "M"); // era #1,start year/month/day, yearOffset, minEraYear
+
+ // Remember the ranges we built
+ japaneseEraInfo = defaultEraRanges;
+ }
+ }
+
+ // return the era we found/made
+ return japaneseEraInfo;
+ }
+
+ internal static volatile Calendar s_defaultInstance;
+ internal GregorianCalendarHelper helper;
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of JapaneseCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance()
+ {
+ if (s_defaultInstance == null)
+ {
+ s_defaultInstance = new JapaneseCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+
+ public JapaneseCalendar()
+ {
+ try
+ {
+ new CultureInfo("ja-JP");
+ }
+ catch (ArgumentException e)
+ {
+ throw new TypeInitializationException(this.GetType().ToString(), e);
+ }
+ helper = new GregorianCalendarHelper(this, GetEraInfo());
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.JAPAN;
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (helper.AddYears(time, years));
+ }
+
+ /*=================================GetDaysInMonth==========================
+ **Action: Returns the number of days in the month given by the year and month arguments.
+ **Returns: The number of days in the given month.
+ **Arguments:
+ ** year The year in Japanese calendar.
+ ** month The month
+ ** era The Japanese era value.
+ **Exceptions
+ ** ArgumentException If month is less than 1 or greater * than 12.
+ ============================================================================*/
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+ /*=================================GetEra==========================
+ **Action: Get the era value of the specified time.
+ **Returns: The era value for the specified time.
+ **Arguments:
+ ** time the specified date time.
+ **Exceptions: ArgumentOutOfRangeException if time is out of the valid era ranges.
+ ============================================================================*/
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+
+ public override int GetMonth(DateTime time)
+ {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+ // For Japanese calendar, four digit year is not used. Few emperors will live for more than one hundred years.
+ // Therefore, for any two digit number, we just return the original number.
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year <= 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedPosNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ helper.MaxYear));
+ }
+ return (year);
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+
+ //
+ // Return the various era strings
+ // Note: The arrays are backwards of the eras
+ //
+ internal static String[] EraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] eraNames = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ eraNames[i] = eras[eras.Length - i - 1].eraName;
+ }
+
+ return eraNames;
+ }
+
+ internal static String[] AbbrevEraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] erasAbbrev = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ erasAbbrev[i] = eras[eras.Length - i - 1].abbrevEraName;
+ }
+
+ return erasAbbrev;
+ }
+
+ internal static String[] EnglishEraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] erasEnglish = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ erasEnglish[i] = eras[eras.Length - i - 1].englishEraName;
+ }
+
+ return erasEnglish;
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99;
+
+ internal override bool IsValidYear(int year, int era)
+ {
+ return helper.IsValidYear(year, era);
+ }
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ helper.MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs
new file mode 100644
index 0000000000..ecdaced2d7
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/JapaneseLunisolarCalendar.cs
@@ -0,0 +1,311 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about JapaneseLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1960/01/28 2050/01/22
+ ** JapaneseLunisolar 1960/01/01 2049/12/29
+ */
+
+ [Serializable]
+ public class JapaneseLunisolarCalendar : EastAsianLunisolarCalendar
+ {
+ //
+ // The era value for the current era.
+ //
+
+ public const int JapaneseEra = 1;
+
+ internal GregorianCalendarHelper helper;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1960;
+ internal const int MAX_LUNISOLAR_YEAR = 2049;
+
+ internal const int MIN_GREGORIAN_YEAR = 1960;
+ internal const int MIN_GREGORIAN_MONTH = 1;
+ internal const int MIN_GREGORIAN_DAY = 28;
+
+ internal const int MAX_GREGORIAN_YEAR = 2050;
+ internal const int MAX_GREGORIAN_MONTH = 1;
+ internal const int MAX_GREGORIAN_DAY = 22;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1959 from ChineseLunisolarCalendar
+ return 354;
+ }
+ }
+
+ private static readonly int[,] s_yinfo =
+ {
+ /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+ 1960 */
+ { 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+ */ };
+
+ internal override int MinCalendarYear
+ {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear
+ {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo
+ {
+ get
+ {
+ return (JapaneseCalendar.GetEraInfo());
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index)
+ {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time)
+ {
+ return helper.GetYear(year, time);
+ }
+
+ internal override int GetGregorianYear(int year, int era)
+ {
+ return helper.GetGregorianYear(year, era);
+ }
+
+ // Trim off the eras that are before our date range
+ private static EraInfo[] TrimEras(EraInfo[] baseEras)
+ {
+ EraInfo[] newEras = new EraInfo[baseEras.Length];
+ int newIndex = 0;
+
+ // Eras have most recent first, so start with that
+ for (int i = 0; i < baseEras.Length; i++)
+ {
+ // If this one's minimum year is bigger than our maximum year
+ // then we can't use it.
+ if (baseEras[i].yearOffset + baseEras[i].minEraYear >= MAX_LUNISOLAR_YEAR)
+ {
+ // skip this one.
+ continue;
+ }
+
+ // If this one's maximum era is less than our minimum era
+ // then we've gotten too low in the era #s, so we're done
+ if (baseEras[i].yearOffset + baseEras[i].maxEraYear < MIN_LUNISOLAR_YEAR)
+ {
+ break;
+ }
+
+ // Wasn't too large or too small, can use this one
+ newEras[newIndex] = baseEras[i];
+ newIndex++;
+ }
+
+ // If we didn't copy any then something was wrong, just return base
+ if (newIndex == 0) return baseEras;
+
+ // Resize the output array
+ Array.Resize(ref newEras, newIndex);
+ return newEras;
+ }
+
+
+ // Construct an instance of JapaneseLunisolar calendar.
+ public JapaneseLunisolarCalendar()
+ {
+ helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo()));
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ return (CalendarId.JAPAN);
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.JAPANESELUNISOLAR);
+ }
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs
new file mode 100644
index 0000000000..6721899ac9
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/JulianCalendar.cs
@@ -0,0 +1,452 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ //
+ // This class implements the Julian calendar. In 48 B.C. Julius Caesar ordered a calendar reform, and this calendar
+ // is called Julian calendar. It consisted of a solar year of twelve months and of 365 days with an extra day
+ // every fourth year.
+ //*
+ //* Calendar support range:
+ //* Calendar Minimum Maximum
+ //* ========== ========== ==========
+ //* Gregorian 0001/01/01 9999/12/31
+ //* Julia 0001/01/03 9999/10/19
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class JulianCalendar : Calendar
+ {
+ public static readonly int JulianEra = 1;
+
+ private const int DatePartYear = 0;
+ private const int DatePartDayOfYear = 1;
+ private const int DatePartMonth = 2;
+ private const int DatePartDay = 3;
+
+ // Number of days in a non-leap year
+ private const int JulianDaysPerYear = 365;
+ // Number of days in 4 years
+ private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1;
+
+ private static readonly int[] s_daysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ private static readonly int[] s_daysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ // Gregorian Calendar 9999/12/31 = Julian Calendar 9999/10/19
+ // keep it as variable field for serialization compat.
+ internal int MaxYear = 9999;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Julian calendar.
+ //
+
+ //[System.Runtime.InteropServices.ComVisible(false)]
+ //public override CalendarAlgorithmType AlgorithmType
+ //{
+ // get
+ // {
+ // return CalendarAlgorithmType.SolarCalendar;
+ // }
+ //}
+
+ public JulianCalendar()
+ {
+ // There is no system setting of TwoDigitYear max, so set the value here.
+ twoDigitYearMax = 2029;
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.JULIAN;
+ }
+ }
+
+ internal static void CheckEraRange(int era)
+ {
+ if (era != CurrentEra && era != JulianEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ internal void CheckYearEraRange(int year, int era)
+ {
+ CheckEraRange(era);
+ if (year <= 0 || year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxYear));
+ }
+ }
+
+ internal static void CheckMonthRange(int month)
+ {
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ }
+
+ /*===================================CheckDayRange============================
+ **Action: Check for if the day value is valid.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ **Notes:
+ ** Before calling this method, call CheckYearEraRange()/CheckMonthRange() to make
+ ** sure year/month values are correct.
+ ============================================================================*/
+
+ internal static void CheckDayRange(int year, int month, int day)
+ {
+ if (year == 1 && month == 1)
+ {
+ // The mimimum supported Julia date is Julian 0001/01/03.
+ if (day < 3)
+ {
+ throw new ArgumentOutOfRangeException(null,
+ SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+ }
+ bool isLeapYear = (year % 4) == 0;
+ int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365;
+ int monthDays = days[month] - days[month - 1];
+ if (day < 1 || day > monthDays)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ monthDays));
+ }
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ internal static int GetDatePart(long ticks, int part)
+ {
+ // Gregorian 1/1/0001 is Julian 1/3/0001. Remember DateTime(0) is refered to Gregorian 1/1/0001.
+ // The following line convert Gregorian ticks to Julian ticks.
+ long julianTicks = ticks + TicksPerDay * 2;
+ // n = number of days since 1/1/0001
+ int n = (int)(julianTicks / TicksPerDay);
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / JulianDaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * JulianDaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / JulianDaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * JulianDaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3);
+ int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ internal static long DateToTicks(int year, int month, int day)
+ {
+ int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365;
+ int y = year - 1;
+ int n = y * 365 + y / 4 + days[month - 1] + day - 1;
+ // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar.
+ // Therefore, we subtract two days in the following to convert the ticks in JulianCalendar
+ // to ticks in Gregorian calendar.
+ return ((n - 2) * TicksPerDay);
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365;
+ return (days[month] - days[month - 1]);
+ }
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ // Year/Era range is done in IsLeapYear().
+ return (IsLeapYear(year, era) ? 366 : 365);
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (JulianEra);
+ }
+
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { JulianEra });
+ }
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (12);
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ CheckMonthRange(month);
+ // Year/Era range check is done in IsLeapYear().
+ if (IsLeapYear(year, era))
+ {
+ CheckDayRange(year, month, day);
+ return (month == 2 && day == 29);
+ }
+ CheckDayRange(year, month, day);
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (0);
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (year % 4 == 0);
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ CheckDayRange(year, month, day);
+ if (millisecond < 0 || millisecond >= MillisPerSecond)
+ {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ MillisPerSecond - 1));
+ }
+
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >= 0 && second < 60)
+ {
+ return new DateTime(DateToTicks(year, month, day) + (new TimeSpan(0, hour, minute, second, millisecond)).Ticks);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadHourMinuteSecond);
+ }
+ }
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Bounds_Lower_Upper,
+ 1,
+ MaxYear));
+ }
+ return (base.ToFourDigitYear(year));
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs
new file mode 100644
index 0000000000..38a0b41fda
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/KoreanCalendar.cs
@@ -0,0 +1,264 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ /*=================================KoreanCalendar==========================
+ **
+ ** Korean calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
+ ** That is,
+ ** Korean year = Gregorian year + 2333. So 2000/01/01 A.D. is Korean 4333/01/01
+ **
+ ** 0001/1/1 A.D. is Korean year 2334.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0001/01/01 9999/12/31
+ ** Korean 2334/01/01 12332/12/31
+ ============================================================================*/
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class KoreanCalendar : Calendar
+ {
+ //
+ // The era value for the current era.
+ //
+
+ public const int KoreanEra = 1;
+
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // Gregorian Year 1 is Korean year 2334, so that
+ // 1 = 2334 + yearOffset
+ // So yearOffset = -2333
+ // Gregorian year 2001 is Korean year 4334.
+
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1, 1, 1).Ticks, -2333, 2334, GregorianCalendar.MaxYear + 2333);
+
+ // Initialize our era info.
+ internal static EraInfo[] koreanEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1, 1, 1, -2333, 2334, GregorianCalendar.MaxYear + 2333) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal GregorianCalendarHelper helper;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ public KoreanCalendar()
+ {
+ try
+ {
+ new CultureInfo("ko-KR");
+ }
+ catch (ArgumentException e)
+ {
+ throw new TypeInitializationException(this.GetType().ToString(), e);
+ }
+ helper = new GregorianCalendarHelper(this, koreanEraInfo);
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.KOREA;
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (helper.AddYears(time, years));
+ }
+
+ /*=================================GetDaysInMonth==========================
+ **Action: Returns the number of days in the month given by the year and month arguments.
+ **Returns: The number of days in the given month.
+ **Arguments:
+ ** year The year in Korean calendar.
+ ** month The month
+ ** era The Japanese era value.
+ **Exceptions
+ ** ArgumentException If month is less than 1 or greater * than 12.
+ ============================================================================*/
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time)
+ {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 4362;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ helper.MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ return (helper.ToFourDigitYear(year, this.TwoDigitYearMax));
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs
new file mode 100644
index 0000000000..68c4fab58f
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/KoreanLunisolarCalendar.cs
@@ -0,0 +1,1329 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about KoreanLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 918/02/14 2051/02/10
+ ** KoreanLunisolar 918/01/01 2050/13/29
+ */
+
+ [Serializable]
+ public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar
+ {
+ //
+ // The era value for the current era.
+ //
+
+ public const int GregorianEra = 1;
+
+ internal const int MIN_LUNISOLAR_YEAR = 918;
+ internal const int MAX_LUNISOLAR_YEAR = 2050;
+
+ internal const int MIN_GREGORIAN_YEAR = 918;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 14;
+
+ internal const int MAX_GREGORIAN_YEAR = 2051;
+ internal const int MAX_GREGORIAN_MONTH = 2;
+ internal const int MAX_GREGORIAN_DAY = 10;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 917 -- From http://emr.cs.iit.edu/home/reingold/calendar-book/Calendrica.html
+ // using ChineseLunisolar
+ return 384;
+ }
+ }
+
+ private static readonly int[,] s_yinfo =
+ {
+ /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+ 918 */
+ { 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354
+920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+922 */{ 0 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+923 */{ 4 , 1 , 20 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+924 */{ 0 , 2 , 8 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+925 */{ 12 , 1 , 27 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+926 */{ 0 , 2 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+927 */{ 0 , 2 , 5 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+928 */{ 8 , 1 , 26 , 17848 },/* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
+929 */{ 0 , 2 , 13 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+930 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+931 */{ 5 , 1 , 22 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
+932 */{ 0 , 2 , 9 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+933 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+934 */{ 1 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+935 */{ 0 , 2 , 6 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+936 */{ 11 , 1 , 27 , 21344 },/* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
+937 */{ 0 , 2 , 13 , 51904 },/* 30 30 29 29 30 29 30 29 30 30 29 29 0 354
+938 */{ 0 , 2 , 2 , 58720 },/* 30 30 30 29 29 30 29 30 29 30 30 29 0 355
+939 */{ 7 , 1 , 23 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+940 */{ 0 , 2 , 11 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+941 */{ 0 , 1 , 30 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+942 */{ 3 , 1 , 20 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+943 */{ 0 , 2 , 8 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+944 */{ 12 , 1 , 28 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+945 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+946 */{ 0 , 2 , 5 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+947 */{ 7 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+948 */{ 0 , 2 , 13 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+949 */{ 0 , 2 , 1 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
+950 */{ 5 , 1 , 21 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+951 */{ 0 , 2 , 9 , 45936 },/* 30 29 30 30 29 30 29 30 29 30 29 0 0 325
+952 */{ 0 , 12 , 31 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+953 */{ 1 , 1 , 18 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+954 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+955 */{ 9 , 1 , 27 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+956 */{ 0 , 2 , 15 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+957 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+958 */{ 7 , 1 , 23 , 43672 },/* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
+959 */{ 0 , 2 , 11 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+960 */{ 0 , 1 , 31 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+961 */{ 3 , 1 , 20 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+962 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+963 */{ 12 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+964 */{ 0 , 2 , 16 , 41840 },/* 30 29 30 29 29 29 30 30 29 30 30 30 0 355
+965 */{ 0 , 2 , 5 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 0 354
+966 */{ 8 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+967 */{ 0 , 2 , 12 , 54448 },/* 30 30 29 30 29 30 29 29 30 29 30 30 0 355
+968 */{ 0 , 2 , 2 , 23184 },/* 29 30 29 30 30 29 30 29 30 29 29 30 0 354
+969 */{ 5 , 1 , 21 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+970 */{ 0 , 2 , 9 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+971 */{ 0 , 1 , 30 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+972 */{ 2 , 1 , 19 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+973 */{ 0 , 2 , 6 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+974 */{ 10 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+975 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+976 */{ 0 , 2 , 3 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+977 */{ 7 , 1 , 22 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
+978 */{ 0 , 2 , 10 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+979 */{ 0 , 1 , 31 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+980 */{ 3 , 1 , 21 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+981 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+982 */{ 12 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+983 */{ 0 , 2 , 16 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+984 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+985 */{ 9 , 1 , 24 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+986 */{ 0 , 2 , 12 , 44192 },/* 30 29 30 29 30 30 29 29 30 29 30 29 0 354
+987 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+988 */{ 5 , 1 , 22 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+989 */{ 0 , 2 , 9 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+990 */{ 0 , 1 , 30 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+991 */{ 2 , 1 , 19 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+992 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+993 */{ 10 , 1 , 26 , 26968 },/* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
+994 */{ 0 , 2 , 14 , 22864 },/* 29 30 29 30 30 29 29 30 29 30 29 30 0 354
+995 */{ 0 , 2 , 3 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+996 */{ 7 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+997 */{ 0 , 2 , 10 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+998 */{ 0 , 1 , 31 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+999 */{ 3 , 1 , 20 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1000 */{ 0 , 2 , 8 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1001 */{ 12 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1002 */{ 0 , 2 , 15 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1003 */{ 0 , 2 , 4 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1004 */{ 9 , 1 , 25 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1005 */{ 0 , 2 , 12 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1006 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1007 */{ 5 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1008 */{ 0 , 2 , 10 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1009 */{ 0 , 1 , 29 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1010 */{ 2 , 1 , 18 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1011 */{ 0 , 2 , 6 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
+1012 */{ 10 , 1 , 26 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1013 */{ 0 , 2 , 13 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1014 */{ 0 , 2 , 3 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1015 */{ 6 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1016 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1017 */{ 0 , 1 , 31 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1018 */{ 4 , 1 , 20 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1019 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1020 */{ 12 , 1 , 28 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1021 */{ 0 , 2 , 15 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1022 */{ 0 , 2 , 4 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1023 */{ 9 , 1 , 25 , 11688 },/* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
+1024 */{ 0 , 2 , 13 , 11088 },/* 29 29 30 29 30 29 30 30 29 30 29 30 0 354
+1025 */{ 0 , 2 , 1 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1026 */{ 5 , 1 , 22 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1027 */{ 0 , 2 , 9 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
+1028 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1029 */{ 2 , 1 , 18 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1030 */{ 0 , 2 , 5 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1031 */{ 10 , 1 , 26 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1032 */{ 0 , 2 , 14 , 26320 },/* 29 30 30 29 29 30 30 29 30 30 29 30 0 355
+1033 */{ 0 , 2 , 3 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1034 */{ 6 , 1 , 23 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1035 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1036 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1037 */{ 4 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1038 */{ 0 , 2 , 7 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1039 */{ 12 , 1 , 27 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1040 */{ 0 , 2 , 15 , 46464 },/* 30 29 30 30 29 30 29 30 30 29 29 29 0 354
+1041 */{ 0 , 2 , 3 , 54960 },/* 30 30 29 30 29 30 30 29 30 29 30 30 0 356
+1042 */{ 9 , 1 , 25 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1043 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1044 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1045 */{ 5 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1046 */{ 0 , 2 , 9 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1047 */{ 0 , 1 , 29 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1048 */{ 1 , 1 , 18 , 46424 },/* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
+1049 */{ 0 , 2 , 6 , 11600 },/* 29 29 30 29 30 30 29 30 29 30 29 30 0 354
+1050 */{ 11 , 1 , 26 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1051 */{ 0 , 2 , 14 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1052 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1053 */{ 7 , 1 , 23 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1054 */{ 0 , 2 , 11 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1055 */{ 0 , 1 , 31 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1056 */{ 3 , 1 , 20 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1057 */{ 0 , 2 , 7 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1058 */{ 12 , 1 , 27 , 43864 },/* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
+1059 */{ 0 , 2 , 16 , 10064 },/* 29 29 30 29 29 30 30 30 29 30 29 30 0 354
+1060 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1061 */{ 8 , 1 , 24 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1062 */{ 0 , 2 , 12 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1063 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1064 */{ 5 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1065 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1066 */{ 0 , 1 , 29 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1067 */{ 1 , 1 , 18 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1068 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1069 */{ 11 , 1 , 26 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1070 */{ 0 , 2 , 14 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1071 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1072 */{ 7 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1073 */{ 0 , 2 , 10 , 43616 },/* 30 29 30 29 30 29 30 29 29 30 30 29 0 354
+1074 */{ 0 , 1 , 30 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1075 */{ 4 , 1 , 20 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1076 */{ 0 , 2 , 8 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1077 */{ 0 , 1 , 27 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1078 */{ 1 , 1 , 17 , 19352 },/* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
+1079 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1080 */{ 9 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1081 */{ 0 , 2 , 12 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1082 */{ 0 , 2 , 1 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1083 */{ 6 , 1 , 21 , 46408 },/* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
+1084 */{ 0 , 2 , 9 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1085 */{ 0 , 1 , 29 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1086 */{ 2 , 1 , 18 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1087 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1088 */{ 12 , 1 , 27 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1089 */{ 0 , 2 , 13 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
+1090 */{ 0 , 2 , 3 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1091 */{ 8 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1092 */{ 0 , 2 , 10 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1093 */{ 0 , 1 , 30 , 23360 },/* 29 30 29 30 30 29 30 30 29 30 29 29 0 354
+1094 */{ 4 , 1 , 19 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1095 */{ 0 , 2 , 8 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1096 */{ 0 , 1 , 28 , 58896 },/* 30 30 30 29 29 30 30 29 29 29 29 30 0 354
+1097 */{ 2 , 1 , 16 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1098 */{ 0 , 2 , 4 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1099 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1100 */{ 0 , 2 , 12 , 21664 },/* 29 30 29 30 29 30 29 29 30 29 30 29 0 353
+1101 */{ 0 , 1 , 31 , 54864 },/* 30 30 29 30 29 30 30 29 29 30 29 30 0 355
+1102 */{ 6 , 1 , 21 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1103 */{ 0 , 2 , 9 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1104 */{ 0 , 1 , 30 , 9936 },/* 29 29 30 29 29 30 30 29 30 30 29 30 0 354
+1105 */{ 2 , 1 , 18 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1106 */{ 0 , 2 , 6 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1107 */{ 10 , 1 , 26 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1108 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1109 */{ 0 , 2 , 2 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1110 */{ 8 , 1 , 22 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1111 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1112 */{ 0 , 1 , 31 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1113 */{ 4 , 1 , 20 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1114 */{ 0 , 2 , 8 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1115 */{ 0 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1116 */{ 1 , 1 , 17 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1117 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1118 */{ 9 , 1 , 24 , 29352 },/* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
+1119 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1120 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1121 */{ 5 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1122 */{ 0 , 2 , 9 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1123 */{ 0 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1124 */{ 3 , 1 , 19 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1125 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1126 */{ 11 , 1 , 25 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1127 */{ 0 , 2 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1128 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1129 */{ 8 , 1 , 22 , 39824 },/* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
+1130 */{ 0 , 2 , 10 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1131 */{ 0 , 1 , 31 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1132 */{ 4 , 1 , 20 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1133 */{ 0 , 2 , 7 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1134 */{ 0 , 1 , 27 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1135 */{ 2 , 1 , 16 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+1136 */{ 0 , 2 , 4 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1137 */{ 10 , 1 , 23 , 54952 },/* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
+1138 */{ 0 , 2 , 12 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1139 */{ 0 , 2 , 1 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1140 */{ 6 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1141 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1142 */{ 0 , 1 , 29 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1143 */{ 4 , 1 , 18 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1144 */{ 0 , 2 , 6 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1145 */{ 11 , 1 , 25 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1146 */{ 0 , 2 , 13 , 27456 },/* 29 30 30 29 30 29 30 30 29 30 29 29 0 354
+1147 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1148 */{ 8 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1149 */{ 0 , 2 , 10 , 39280 },/* 30 29 29 30 30 29 29 30 29 30 30 30 0 355
+1150 */{ 0 , 1 , 31 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1151 */{ 4 , 1 , 20 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1152 */{ 0 , 2 , 8 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
+1153 */{ 12 , 1 , 27 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1154 */{ 0 , 2 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1155 */{ 0 , 2 , 4 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1156 */{ 10 , 1 , 24 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1157 */{ 0 , 2 , 12 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1158 */{ 0 , 2 , 1 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1159 */{ 6 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1160 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1161 */{ 0 , 1 , 28 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1162 */{ 2 , 1 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1163 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1164 */{ 11 , 1 , 26 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1165 */{ 0 , 2 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1166 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1167 */{ 7 , 1 , 23 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1168 */{ 0 , 2 , 11 , 37488 },/* 30 29 29 30 29 29 30 29 29 30 30 30 0 354
+1169 */{ 0 , 1 , 30 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1170 */{ 5 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1171 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1172 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1173 */{ 1 , 1 , 16 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1174 */{ 0 , 2 , 4 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
+1175 */{ 9 , 1 , 25 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
+1176 */{ 0 , 2 , 12 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1177 */{ 0 , 2 , 1 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1178 */{ 6 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1179 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1180 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1181 */{ 3 , 1 , 17 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1182 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1183 */{ 11 , 1 , 26 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1184 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1185 */{ 0 , 2 , 2 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1186 */{ 7 , 1 , 23 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1187 */{ 0 , 2 , 10 , 53392 },/* 30 30 29 30 29 29 30 29 29 30 30 0 0 325
+1188 */{ 0 , 1 , 1 , 29848 },/* 29 30 30 30 29 30 29 29 30 29 29 30 30 384
+1189 */{ 5 , 1 , 19 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1190 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1191 */{ 0 , 1 , 27 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
+1192 */{ 2 , 1 , 17 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1193 */{ 0 , 2 , 4 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1194 */{ 10 , 1 , 24 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1195 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1196 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1197 */{ 6 , 1 , 20 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1198 */{ 0 , 2 , 8 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1199 */{ 0 , 1 , 28 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1200 */{ 2 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1201 */{ 0 , 2 , 5 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1202 */{ 12 , 1 , 26 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1203 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1204 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1205 */{ 8 , 1 , 22 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1206 */{ 0 , 2 , 10 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1207 */{ 0 , 1 , 30 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1208 */{ 4 , 1 , 19 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
+1209 */{ 0 , 2 , 6 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1210 */{ 0 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1211 */{ 2 , 1 , 17 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1212 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1213 */{ 9 , 1 , 24 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1214 */{ 0 , 2 , 12 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
+1215 */{ 0 , 2 , 1 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1216 */{ 7 , 1 , 21 , 27944 },/* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
+1217 */{ 0 , 2 , 8 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1218 */{ 0 , 1 , 28 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1219 */{ 3 , 1 , 18 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1220 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1221 */{ 12 , 1 , 25 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1222 */{ 0 , 2 , 13 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1223 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1224 */{ 8 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1225 */{ 0 , 2 , 9 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1226 */{ 0 , 1 , 30 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1227 */{ 5 , 1 , 19 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1228 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1229 */{ 0 , 1 , 27 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1230 */{ 2 , 1 , 16 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1231 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1232 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1233 */{ 0 , 2 , 11 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1234 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1235 */{ 7 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1236 */{ 0 , 2 , 9 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1237 */{ 0 , 1 , 28 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1238 */{ 4 , 1 , 18 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1239 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1240 */{ 12 , 1 , 26 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+1241 */{ 0 , 2 , 13 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1242 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1243 */{ 8 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1244 */{ 0 , 2 , 10 , 44624 },/* 30 29 30 29 30 30 30 29 29 30 29 30 0 355
+1245 */{ 0 , 1 , 30 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1246 */{ 4 , 1 , 19 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1247 */{ 0 , 2 , 7 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1248 */{ 0 , 1 , 28 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1249 */{ 2 , 1 , 16 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1250 */{ 0 , 2 , 3 , 58672 },/* 30 30 30 29 29 30 29 30 29 29 30 30 0 355
+1251 */{ 10 , 1 , 24 , 27800 },/* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
+1252 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1253 */{ 0 , 1 , 31 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1254 */{ 6 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1255 */{ 0 , 2 , 9 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1256 */{ 0 , 1 , 29 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1257 */{ 4 , 1 , 17 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1258 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1259 */{ 11 , 1 , 25 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1260 */{ 0 , 2 , 13 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1261 */{ 0 , 2 , 1 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1262 */{ 9 , 1 , 22 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1263 */{ 0 , 2 , 10 , 21872 },/* 29 30 29 30 29 30 29 30 29 30 30 30 0 355
+1264 */{ 0 , 1 , 31 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1265 */{ 5 , 1 , 19 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1266 */{ 0 , 2 , 7 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1267 */{ 0 , 1 , 27 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1268 */{ 1 , 1 , 16 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1269 */{ 0 , 2 , 3 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1270 */{ 11 , 1 , 23 , 46528 },/* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
+1271 */{ 0 , 2 , 11 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1272 */{ 0 , 2 , 1 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1273 */{ 6 , 1 , 21 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1274 */{ 0 , 2 , 9 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1275 */{ 0 , 1 , 29 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1276 */{ 3 , 1 , 18 , 27224 },/* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
+1277 */{ 0 , 2 , 5 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1278 */{ 11 , 1 , 25 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1279 */{ 0 , 2 , 13 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1280 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1281 */{ 8 , 1 , 22 , 10984 },/* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
+1282 */{ 0 , 2 , 10 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
+1283 */{ 0 , 1 , 30 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1284 */{ 5 , 1 , 19 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1285 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+1286 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1287 */{ 2 , 1 , 15 , 62096 },/* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
+1288 */{ 0 , 2 , 3 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1289 */{ 10 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1290 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1291 */{ 0 , 2 , 1 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1292 */{ 6 , 1 , 21 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1293 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1294 */{ 0 , 1 , 28 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1295 */{ 4 , 1 , 17 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1296 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1297 */{ 12 , 1 , 24 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+1298 */{ 0 , 2 , 12 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1299 */{ 0 , 2 , 2 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1300 */{ 8 , 1 , 23 , 2424 },/* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
+1301 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1302 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1303 */{ 5 , 1 , 19 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1304 */{ 0 , 2 , 6 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1305 */{ 0 , 1 , 26 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1306 */{ 1 , 1 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1307 */{ 0 , 2 , 3 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1308 */{ 11 , 1 , 24 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1309 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1310 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1311 */{ 7 , 1 , 20 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1312 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1313 */{ 0 , 1 , 27 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1314 */{ 3 , 1 , 17 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1315 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1316 */{ 0 , 1 , 25 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1317 */{ 1 , 1 , 14 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1318 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1319 */{ 8 , 1 , 22 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1320 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1321 */{ 0 , 1 , 29 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1322 */{ 5 , 1 , 18 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1323 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1324 */{ 0 , 1 , 27 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1325 */{ 1 , 1 , 15 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1326 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1327 */{ 9 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1328 */{ 0 , 2 , 12 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1329 */{ 0 , 1 , 31 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1330 */{ 7 , 1 , 20 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1331 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1332 */{ 0 , 1 , 28 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1333 */{ 3 , 1 , 17 , 19368 },/* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
+1334 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1335 */{ 12 , 1 , 25 , 42608 },/* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
+1336 */{ 0 , 2 , 13 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+1337 */{ 0 , 2 , 1 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1338 */{ 8 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1339 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1340 */{ 0 , 1 , 29 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1341 */{ 5 , 1 , 18 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1342 */{ 0 , 2 , 6 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1343 */{ 0 , 1 , 27 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1344 */{ 2 , 1 , 16 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1345 */{ 0 , 2 , 3 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1346 */{ 10 , 1 , 23 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1347 */{ 0 , 2 , 11 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1348 */{ 0 , 1 , 31 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1349 */{ 7 , 1 , 19 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1350 */{ 0 , 2 , 7 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1351 */{ 0 , 1 , 28 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1352 */{ 3 , 1 , 18 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1353 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1354 */{ 0 , 1 , 25 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1355 */{ 1 , 1 , 14 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1356 */{ 0 , 2 , 2 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1357 */{ 9 , 1 , 21 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1358 */{ 0 , 2 , 9 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
+1359 */{ 0 , 1 , 29 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
+1360 */{ 5 , 1 , 19 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1361 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1362 */{ 0 , 1 , 27 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1363 */{ 3 , 1 , 16 , 41656 },/* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
+1364 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1365 */{ 10 , 1 , 23 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
+1366 */{ 0 , 2 , 10 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1367 */{ 0 , 1 , 31 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1368 */{ 7 , 1 , 20 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1369 */{ 0 , 2 , 7 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1370 */{ 0 , 1 , 28 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
+1371 */{ 3 , 1 , 17 , 50544 },/* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
+1372 */{ 0 , 2 , 5 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1373 */{ 11 , 1 , 24 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1374 */{ 0 , 2 , 12 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1375 */{ 0 , 2 , 1 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1376 */{ 9 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1377 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1378 */{ 0 , 1 , 29 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1379 */{ 5 , 1 , 19 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1380 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1381 */{ 0 , 1 , 26 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
+1382 */{ 2 , 1 , 15 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1383 */{ 0 , 2 , 3 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1384 */{ 10 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1385 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1386 */{ 0 , 1 , 31 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1387 */{ 6 , 1 , 20 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1388 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1389 */{ 0 , 1 , 28 , 20912 },/* 29 30 29 30 29 29 29 30 30 29 30 30 0 354
+1390 */{ 4 , 1 , 17 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1391 */{ 0 , 2 , 5 , 25904 },/* 29 30 30 29 29 30 29 30 29 29 30 30 0 354
+1392 */{ 12 , 1 , 25 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1393 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1394 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1395 */{ 9 , 1 , 22 , 11176 },/* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
+1396 */{ 0 , 2 , 10 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1397 */{ 0 , 1 , 29 , 50032 },/* 30 30 29 29 29 29 30 30 29 30 30 30 0 355
+1398 */{ 5 , 1 , 19 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1399 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1400 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1401 */{ 3 , 1 , 15 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1402 */{ 0 , 2 , 2 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1403 */{ 11 , 1 , 23 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1404 */{ 0 , 2 , 11 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1405 */{ 0 , 1 , 31 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1406 */{ 7 , 1 , 20 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1407 */{ 0 , 2 , 8 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1408 */{ 0 , 1 , 28 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
+1409 */{ 4 , 1 , 16 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1410 */{ 0 , 2 , 4 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1411 */{ 12 , 1 , 24 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
+1412 */{ 0 , 2 , 12 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1413 */{ 0 , 2 , 1 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1414 */{ 9 , 1 , 22 , 9688 },/* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
+1415 */{ 0 , 2 , 10 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1416 */{ 0 , 1 , 30 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1417 */{ 5 , 1 , 18 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1418 */{ 0 , 2 , 6 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1419 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1420 */{ 1 , 1 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1421 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1422 */{ 12 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1423 */{ 0 , 2 , 11 , 19312 },/* 29 30 29 29 30 29 30 30 29 30 30 30 0 355
+1424 */{ 0 , 2 , 1 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1425 */{ 7 , 1 , 20 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1426 */{ 0 , 2 , 8 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1427 */{ 0 , 1 , 28 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1428 */{ 4 , 1 , 17 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1429 */{ 0 , 2 , 4 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1430 */{ 12 , 1 , 24 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
+1431 */{ 0 , 2 , 12 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1432 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1433 */{ 8 , 1 , 21 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1434 */{ 0 , 2 , 9 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1435 */{ 0 , 1 , 29 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1436 */{ 6 , 1 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1437 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1438 */{ 0 , 1 , 26 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1439 */{ 2 , 1 , 15 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1440 */{ 0 , 2 , 3 , 38368 },/* 30 29 29 30 29 30 29 30 30 30 30 29 0 355
+1441 */{ 11 , 1 , 23 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1442 */{ 0 , 2 , 11 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1443 */{ 0 , 1 , 31 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1444 */{ 7 , 1 , 20 , 53872 },/* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
+1445 */{ 0 , 2 , 7 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1446 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1447 */{ 4 , 1 , 17 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1448 */{ 0 , 2 , 5 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1449 */{ 0 , 1 , 24 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1450 */{ 1 , 1 , 14 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1451 */{ 0 , 2 , 2 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1452 */{ 9 , 1 , 22 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1453 */{ 0 , 2 , 9 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1454 */{ 0 , 1 , 29 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1455 */{ 6 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1456 */{ 0 , 2 , 6 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1457 */{ 0 , 1 , 26 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1458 */{ 2 , 1 , 15 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1459 */{ 0 , 2 , 3 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1460 */{ 11 , 1 , 24 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1461 */{ 0 , 2 , 10 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1462 */{ 0 , 1 , 30 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
+1463 */{ 7 , 1 , 20 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1464 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1465 */{ 0 , 1 , 27 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1466 */{ 3 , 1 , 17 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1467 */{ 0 , 2 , 5 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1468 */{ 0 , 1 , 25 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1469 */{ 2 , 1 , 13 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1470 */{ 0 , 2 , 1 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1471 */{ 9 , 1 , 21 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1472 */{ 0 , 2 , 9 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1473 */{ 0 , 1 , 28 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1474 */{ 6 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1475 */{ 0 , 2 , 6 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1476 */{ 0 , 1 , 27 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1477 */{ 2 , 1 , 15 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1478 */{ 0 , 2 , 3 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1479 */{ 10 , 1 , 23 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1480 */{ 0 , 2 , 11 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1481 */{ 0 , 1 , 30 , 29856 },/* 29 30 30 30 29 30 29 29 30 29 30 29 0 354
+1482 */{ 8 , 1 , 19 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1483 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1484 */{ 0 , 1 , 28 , 21424 },/* 29 30 29 30 29 29 30 30 30 29 30 30 0 355
+1485 */{ 4 , 1 , 17 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1486 */{ 0 , 2 , 5 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1487 */{ 0 , 1 , 25 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1488 */{ 1 , 1 , 14 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1489 */{ 0 , 2 , 1 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1490 */{ 9 , 1 , 21 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1491 */{ 0 , 2 , 9 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1492 */{ 0 , 1 , 29 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1493 */{ 5 , 1 , 18 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1494 */{ 0 , 2 , 6 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1495 */{ 0 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1496 */{ 3 , 1 , 16 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1497 */{ 0 , 2 , 2 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1498 */{ 11 , 1 , 22 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
+1499 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1500 */{ 0 , 1 , 31 , 5792 },/* 29 29 29 30 29 30 30 29 30 29 30 29 0 353
+1501 */{ 7 , 1 , 19 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1502 */{ 0 , 2 , 7 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1503 */{ 0 , 1 , 28 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1504 */{ 4 , 1 , 17 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1505 */{ 0 , 2 , 4 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1506 */{ 0 , 1 , 24 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1507 */{ 1 , 1 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
+1508 */{ 0 , 2 , 1 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1509 */{ 9 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1510 */{ 0 , 2 , 9 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1511 */{ 0 , 1 , 29 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1512 */{ 5 , 1 , 19 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1513 */{ 0 , 2 , 6 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1514 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1515 */{ 4 , 1 , 15 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1516 */{ 0 , 2 , 3 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1517 */{ 12 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1518 */{ 0 , 2 , 10 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1519 */{ 0 , 1 , 31 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1520 */{ 8 , 1 , 20 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1521 */{ 0 , 2 , 7 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 0 355
+1522 */{ 0 , 1 , 28 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1523 */{ 4 , 1 , 17 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1524 */{ 0 , 2 , 4 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1525 */{ 12 , 1 , 23 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1526 */{ 0 , 2 , 11 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 0 355
+1527 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1528 */{ 10 , 1 , 22 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1529 */{ 0 , 2 , 9 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1530 */{ 0 , 1 , 29 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
+1531 */{ 6 , 1 , 18 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1532 */{ 0 , 2 , 6 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1533 */{ 0 , 1 , 25 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1534 */{ 2 , 1 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1535 */{ 0 , 2 , 2 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 0 355
+1536 */{ 12 , 1 , 23 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1537 */{ 0 , 2 , 10 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1538 */{ 0 , 1 , 31 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1539 */{ 7 , 1 , 20 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1540 */{ 0 , 2 , 8 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1541 */{ 0 , 1 , 27 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1542 */{ 5 , 1 , 16 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1543 */{ 0 , 2 , 4 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1544 */{ 0 , 1 , 24 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1545 */{ 1 , 1 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1546 */{ 0 , 2 , 1 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1547 */{ 9 , 1 , 22 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1548 */{ 0 , 2 , 10 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1549 */{ 0 , 1 , 29 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1550 */{ 6 , 1 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1551 */{ 0 , 2 , 5 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1552 */{ 0 , 1 , 26 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1553 */{ 3 , 1 , 14 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1554 */{ 0 , 2 , 2 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1555 */{ 11 , 1 , 23 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1556 */{ 0 , 2 , 11 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1557 */{ 0 , 1 , 30 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1558 */{ 7 , 1 , 20 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1559 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1560 */{ 0 , 1 , 27 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1561 */{ 5 , 1 , 16 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1562 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1563 */{ 0 , 1 , 24 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1564 */{ 2 , 1 , 14 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1565 */{ 0 , 2 , 1 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1566 */{ 10 , 1 , 21 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1567 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1568 */{ 0 , 1 , 29 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1569 */{ 6 , 1 , 17 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1570 */{ 0 , 2 , 5 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1571 */{ 0 , 1 , 26 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1572 */{ 2 , 1 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1573 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1574 */{ 12 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1575 */{ 0 , 2 , 11 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1576 */{ 0 , 1 , 31 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1577 */{ 8 , 1 , 19 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1578 */{ 0 , 2 , 7 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1579 */{ 0 , 1 , 27 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1580 */{ 4 , 1 , 16 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1581 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1582 */{ 0 , 1 , 24 , 39024 },/* 30 29 29 30 29 29 30 30 39 30 30 30 0 365
+1583 */{ 2 , 1 , 24 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1584 */{ 0 , 2 , 12 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1585 */{ 9 , 1 , 31 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1586 */{ 0 , 2 , 18 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1587 */{ 0 , 3 , 9 , 53968 },/* 30 30 29 30 29 30 29 29 30 29 30 0 0 325
+1588 */{ 6 , 1 , 28 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1589 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1590 */{ 0 , 2 , 5 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1591 */{ 3 , 1 , 25 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1592 */{ 0 , 2 , 13 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1593 */{ 11 , 2 , 1 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1594 */{ 0 , 2 , 20 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1595 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1596 */{ 8 , 1 , 29 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1597 */{ 0 , 2 , 16 , 46288 },/* 30 29 30 30 29 30 29 29 30 30 29 30 0 355
+1598 */{ 0 , 2 , 6 , 22192 },/* 29 30 29 30 29 30 30 29 30 29 30 30 0 355
+1599 */{ 4 , 1 , 27 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1600 */{ 0 , 2 , 15 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1601 */{ 0 , 2 , 3 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1602 */{ 2 , 1 , 23 , 51608 },/* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
+1603 */{ 0 , 2 , 11 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1604 */{ 9 , 1 , 31 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1605 */{ 0 , 2 , 18 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1606 */{ 0 , 2 , 7 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1607 */{ 6 , 1 , 28 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1608 */{ 0 , 2 , 16 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1609 */{ 0 , 2 , 5 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1610 */{ 3 , 1 , 25 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1611 */{ 0 , 2 , 13 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1612 */{ 11 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1613 */{ 0 , 2 , 19 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1614 */{ 0 , 2 , 9 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1615 */{ 8 , 1 , 29 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1616 */{ 0 , 2 , 17 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
+1617 */{ 0 , 2 , 6 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1618 */{ 4 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1619 */{ 0 , 2 , 14 , 42224 },/* 30 29 30 29 29 30 29 29 30 30 30 30 0 355
+1620 */{ 0 , 2 , 4 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1621 */{ 2 , 1 , 22 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1622 */{ 0 , 2 , 10 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1623 */{ 10 , 1 , 31 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1624 */{ 0 , 2 , 19 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1625 */{ 0 , 2 , 7 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1626 */{ 6 , 1 , 28 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1627 */{ 0 , 2 , 16 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
+1628 */{ 0 , 2 , 5 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1629 */{ 4 , 1 , 24 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1630 */{ 0 , 2 , 12 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1631 */{ 11 , 2 , 1 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1632 */{ 0 , 2 , 20 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1633 */{ 0 , 2 , 8 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1634 */{ 8 , 1 , 29 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1635 */{ 0 , 2 , 17 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1636 */{ 0 , 2 , 7 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1637 */{ 4 , 1 , 26 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1638 */{ 0 , 2 , 14 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1639 */{ 0 , 2 , 3 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1640 */{ 1 , 1 , 23 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1641 */{ 0 , 2 , 10 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1642 */{ 11 , 1 , 30 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1643 */{ 0 , 2 , 19 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1644 */{ 0 , 2 , 8 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1645 */{ 6 , 1 , 28 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1646 */{ 0 , 2 , 16 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1647 */{ 0 , 2 , 5 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1648 */{ 3 , 1 , 24 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1649 */{ 0 , 2 , 11 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1650 */{ 11 , 2 , 1 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1651 */{ 0 , 2 , 20 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1652 */{ 0 , 2 , 10 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
+1653 */{ 7 , 1 , 29 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1654 */{ 0 , 2 , 17 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1655 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1656 */{ 5 , 1 , 26 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1657 */{ 0 , 2 , 13 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1658 */{ 0 , 2 , 2 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1659 */{ 3 , 1 , 23 , 39592 },/* 30 29 29 30 30 29 30 29 30 29 30 29 30 384
+1660 */{ 0 , 2 , 11 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1661 */{ 7 , 1 , 30 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+1662 */{ 0 , 2 , 18 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 0 355
+1663 */{ 0 , 2 , 8 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1664 */{ 6 , 1 , 28 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1665 */{ 0 , 2 , 15 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1666 */{ 0 , 2 , 4 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1667 */{ 4 , 1 , 24 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1668 */{ 0 , 2 , 12 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1669 */{ 0 , 2 , 1 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+1670 */{ 2 , 1 , 21 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1671 */{ 0 , 2 , 9 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1672 */{ 7 , 1 , 30 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1673 */{ 0 , 2 , 17 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1674 */{ 0 , 2 , 6 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1675 */{ 5 , 1 , 26 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+1676 */{ 0 , 2 , 14 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1677 */{ 0 , 2 , 2 , 44432 },/* 30 29 30 29 30 30 29 30 30 29 29 30 0 355
+1678 */{ 3 , 1 , 23 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1679 */{ 0 , 2 , 11 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1680 */{ 8 , 1 , 31 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1681 */{ 0 , 2 , 18 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1682 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1683 */{ 6 , 1 , 27 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1684 */{ 0 , 2 , 15 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+1685 */{ 0 , 2 , 3 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1686 */{ 4 , 1 , 24 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1687 */{ 0 , 2 , 12 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1688 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1689 */{ 3 , 1 , 21 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1690 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1691 */{ 7 , 1 , 29 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1692 */{ 0 , 2 , 17 , 45136 },/* 30 29 29 32 29 29 29 29 29 30 29 30 0 354
+1693 */{ 0 , 2 , 5 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+1694 */{ 5 , 1 , 25 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1695 */{ 0 , 2 , 13 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1696 */{ 0 , 2 , 3 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1697 */{ 3 , 1 , 23 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1698 */{ 0 , 2 , 11 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1699 */{ 7 , 1 , 31 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1700 */{ 0 , 2 , 19 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1701 */{ 0 , 2 , 8 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1702 */{ 6 , 1 , 28 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1703 */{ 0 , 2 , 16 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+1704 */{ 0 , 2 , 5 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1705 */{ 4 , 1 , 25 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1706 */{ 0 , 2 , 13 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1707 */{ 0 , 2 , 3 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1708 */{ 3 , 1 , 23 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1709 */{ 0 , 2 , 10 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1710 */{ 7 , 1 , 30 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1711 */{ 0 , 2 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1712 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1713 */{ 5 , 1 , 26 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1714 */{ 0 , 2 , 14 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
+1715 */{ 0 , 2 , 4 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1716 */{ 3 , 1 , 24 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1717 */{ 0 , 2 , 11 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1718 */{ 8 , 1 , 31 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1719 */{ 0 , 2 , 19 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1720 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1721 */{ 6 , 1 , 28 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1722 */{ 0 , 2 , 16 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1723 */{ 0 , 2 , 5 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1724 */{ 4 , 1 , 26 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1725 */{ 0 , 2 , 13 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
+1726 */{ 0 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1727 */{ 3 , 1 , 22 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+1728 */{ 0 , 2 , 10 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1729 */{ 7 , 1 , 29 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1730 */{ 0 , 2 , 17 , 40272 },/* 30 29 29 30 30 30 29 30 29 30 29 30 0 355
+1731 */{ 0 , 2 , 7 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+1732 */{ 5 , 1 , 27 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1733 */{ 0 , 2 , 14 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1734 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1735 */{ 4 , 1 , 24 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1736 */{ 0 , 2 , 12 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1737 */{ 9 , 1 , 31 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1738 */{ 0 , 2 , 19 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1739 */{ 0 , 2 , 8 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1740 */{ 6 , 1 , 29 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1741 */{ 0 , 2 , 16 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1742 */{ 0 , 2 , 5 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1743 */{ 4 , 1 , 26 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1744 */{ 0 , 2 , 13 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1745 */{ 0 , 2 , 1 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 0 355
+1746 */{ 3 , 1 , 22 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1747 */{ 0 , 2 , 9 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1748 */{ 7 , 1 , 30 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1749 */{ 0 , 2 , 17 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1750 */{ 0 , 2 , 7 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1751 */{ 5 , 1 , 27 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1752 */{ 0 , 2 , 15 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1753 */{ 0 , 2 , 3 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1754 */{ 4 , 2 , 22 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1755 */{ 0 , 2 , 11 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1756 */{ 9 , 1 , 31 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1757 */{ 0 , 2 , 18 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1758 */{ 0 , 2 , 8 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1759 */{ 6 , 1 , 29 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1760 */{ 0 , 2 , 17 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1761 */{ 0 , 2 , 5 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1762 */{ 5 , 1 , 25 , 45400 },/* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
+1763 */{ 0 , 2 , 13 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1764 */{ 0 , 2 , 2 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1765 */{ 2 , 1 , 21 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
+1766 */{ 0 , 2 , 9 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
+1767 */{ 7 , 1 , 30 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1768 */{ 0 , 2 , 18 , 21360 },/* 29 30 29 30 29 29 30 30 29 30 30 30 0 355
+1769 */{ 0 , 2 , 7 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1770 */{ 5 , 1 , 27 , 25272 },/* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
+1771 */{ 0 , 2 , 15 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1772 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1773 */{ 3 , 1 , 23 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1774 */{ 0 , 2 , 11 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1775 */{ 10 , 1 , 31 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1776 */{ 0 , 2 , 19 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1777 */{ 0 , 2 , 8 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1778 */{ 6 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1779 */{ 0 , 2 , 16 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1780 */{ 0 , 2 , 5 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1781 */{ 5 , 1 , 24 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1782 */{ 0 , 2 , 12 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1783 */{ 0 , 2 , 2 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1784 */{ 3 , 1 , 22 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1785 */{ 0 , 2 , 9 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1786 */{ 7 , 1 , 30 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1787 */{ 0 , 2 , 18 , 19120 },/* 29 30 29 29 30 29 30 29 30 29 30 30 0 354
+1788 */{ 0 , 2 , 7 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
+1789 */{ 5 , 1 , 26 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1790 */{ 0 , 2 , 14 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1791 */{ 0 , 2 , 3 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1792 */{ 4 , 1 , 24 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1793 */{ 0 , 2 , 11 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1794 */{ 0 , 1 , 31 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1795 */{ 2 , 1 , 21 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1796 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1797 */{ 6 , 1 , 28 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1798 */{ 0 , 2 , 16 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1799 */{ 0 , 2 , 5 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1800 */{ 4 , 1 , 25 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1801 */{ 0 , 2 , 13 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1802 */{ 0 , 2 , 3 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
+1803 */{ 2 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1804 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1805 */{ 6 , 1 , 31 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1806 */{ 0 , 2 , 18 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1807 */{ 0 , 2 , 7 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
+1808 */{ 5 , 1 , 28 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1809 */{ 0 , 2 , 14 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1810 */{ 0 , 2 , 4 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1811 */{ 3 , 1 , 25 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1812 */{ 0 , 2 , 13 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1813 */{ 0 , 2 , 1 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+1814 */{ 2 , 1 , 21 , 53608 },/* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
+1815 */{ 0 , 2 , 9 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1816 */{ 6 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1817 */{ 0 , 2 , 16 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1818 */{ 0 , 2 , 5 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1819 */{ 4 , 1 , 26 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1820 */{ 0 , 2 , 14 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1821 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1822 */{ 3 , 1 , 23 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+1823 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1824 */{ 7 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1825 */{ 0 , 2 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1826 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1827 */{ 5 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1828 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1829 */{ 0 , 2 , 4 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1830 */{ 4 , 1 , 25 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1831 */{ 0 , 2 , 13 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1832 */{ 9 , 2 , 2 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1833 */{ 0 , 2 , 20 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1834 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1835 */{ 6 , 1 , 29 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1836 */{ 0 , 2 , 17 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1837 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1838 */{ 4 , 1 , 26 , 21352 },/* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
+1839 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1840 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1841 */{ 3 , 1 , 23 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1842 */{ 0 , 2 , 10 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1843 */{ 7 , 1 , 30 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1844 */{ 0 , 2 , 18 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1845 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1846 */{ 5 , 1 , 27 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1847 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1848 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1849 */{ 4 , 1 , 24 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1850 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1851 */{ 8 , 2 , 1 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1852 */{ 0 , 2 , 20 , 45712 },/* 30 29 30 30 29 29 30 29 30 29 29 30 0 354
+1853 */{ 0 , 2 , 8 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1854 */{ 7 , 1 , 29 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1855 */{ 0 , 2 , 17 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1856 */{ 0 , 2 , 6 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1857 */{ 5 , 1 , 26 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1858 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1859 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1860 */{ 3 , 1 , 23 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1861 */{ 0 , 2 , 10 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1862 */{ 8 , 1 , 30 , 44360 },/* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
+1863 */{ 0 , 2 , 18 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1864 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1865 */{ 5 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1866 */{ 0 , 2 , 15 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1867 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1868 */{ 4 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1869 */{ 0 , 2 , 11 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
+1870 */{ 10 , 1 , 31 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1871 */{ 0 , 2 , 19 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1872 */{ 0 , 2 , 9 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1873 */{ 6 , 1 , 29 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1874 */{ 0 , 2 , 17 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1875 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1876 */{ 5 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1877 */{ 0 , 2 , 13 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1878 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1879 */{ 3 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1880 */{ 0 , 2 , 10 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1881 */{ 7 , 1 , 30 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1882 */{ 0 , 2 , 18 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1883 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1884 */{ 5 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1885 */{ 0 , 2 , 15 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1886 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1887 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1888 */{ 0 , 2 , 12 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1889 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1890 */{ 2 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1891 */{ 0 , 2 , 9 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1892 */{ 6 , 1 , 30 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1893 */{ 0 , 2 , 17 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1894 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1895 */{ 5 , 1 , 26 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1896 */{ 0 , 2 , 13 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1897 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1898 */{ 3 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1899 */{ 0 , 2 , 10 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1900 */{ 8 , 1 , 31 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 55624 },/* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
+1915 */{ 0 , 2 , 14 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1916 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1919 */{ 7 , 2 , 1 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1920 */{ 0 , 2 , 20 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1924 */{ 0 , 2 , 5 , 44352 },/* 30 29 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1944 */{ 4 , 1 , 26 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
+1954 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1955 */{ 3 , 1 , 24 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1958 */{ 0 , 2 , 19 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+ */};
+
+
+ internal override int MinCalendarYear
+ {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear
+ {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index)
+ {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+ return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time)
+ {
+ return year;
+ }
+
+ internal override int GetGregorianYear(int year, int era)
+ {
+ if (era != CurrentEra && era != GregorianEra)
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+
+ if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range, MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return year;
+ }
+
+ public KoreanLunisolarCalendar()
+ {
+ }
+
+ public override int GetEra(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return (GregorianEra);
+ }
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ return (CalendarId.KOREA);
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.KOREANLUNISOLAR);
+ }
+ }
+
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { GregorianEra });
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs
new file mode 100644
index 0000000000..6a25eb2c4d
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/NumberFormatInfo.cs
@@ -0,0 +1,819 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace System.Globalization
+{
+ //
+ // Property Default Description
+ // PositiveSign '+' Character used to indicate positive values.
+ // NegativeSign '-' Character used to indicate negative values.
+ // NumberDecimalSeparator '.' The character used as the decimal separator.
+ // NumberGroupSeparator ',' The character used to separate groups of
+ // digits to the left of the decimal point.
+ // NumberDecimalDigits 2 The default number of decimal places.
+ // NumberGroupSizes 3 The number of digits in each group to the
+ // left of the decimal point.
+ // NaNSymbol "NaN" The string used to represent NaN values.
+ // PositiveInfinitySymbol"Infinity" The string used to represent positive
+ // infinities.
+ // NegativeInfinitySymbol"-Infinity" The string used to represent negative
+ // infinities.
+ //
+ //
+ //
+ // Property Default Description
+ // CurrencyDecimalSeparator '.' The character used as the decimal
+ // separator.
+ // CurrencyGroupSeparator ',' The character used to separate groups
+ // of digits to the left of the decimal
+ // point.
+ // CurrencyDecimalDigits 2 The default number of decimal places.
+ // CurrencyGroupSizes 3 The number of digits in each group to
+ // the left of the decimal point.
+ // CurrencyPositivePattern 0 The format of positive values.
+ // CurrencyNegativePattern 0 The format of negative values.
+ // CurrencySymbol "$" String used as local monetary symbol.
+ //
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ sealed public partial class NumberFormatInfo : IFormatProvider, ICloneable
+ {
+ // invariantInfo is constant irrespective of your current culture.
+ private static volatile NumberFormatInfo s_invariantInfo;
+
+ // READTHIS READTHIS READTHIS
+ // This class has an exact mapping onto a native structure defined in COMNumber.cpp
+ // DO NOT UPDATE THIS WITHOUT UPDATING THAT STRUCTURE. IF YOU ADD BOOL, ADD THEM AT THE END.
+ // ALSO MAKE SURE TO UPDATE mscorlib.h in the VM directory to check field offsets.
+ // READTHIS READTHIS READTHIS
+ internal int[] numberGroupSizes = new int[] { 3 };
+ internal int[] currencyGroupSizes = new int[] { 3 };
+ internal int[] percentGroupSizes = new int[] { 3 };
+ internal String positiveSign = "+";
+ internal String negativeSign = "-";
+ internal String numberDecimalSeparator = ".";
+ internal String numberGroupSeparator = ",";
+ internal String currencyGroupSeparator = ",";
+ internal String currencyDecimalSeparator = ".";
+ internal String currencySymbol = "$"; // TODO: CoreFX #846 Restore to the original value "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
+ internal String nanSymbol = "NaN";
+ internal String positiveInfinitySymbol = "Infinity";
+ internal String negativeInfinitySymbol = "-Infinity";
+ internal String percentDecimalSeparator = ".";
+ internal String percentGroupSeparator = ",";
+ internal String percentSymbol = "%";
+ internal String perMilleSymbol = "\u2030";
+
+
+ [OptionalField(VersionAdded = 2)]
+ internal String[] nativeDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+ internal int numberDecimalDigits = 2;
+ internal int currencyDecimalDigits = 2;
+ internal int currencyPositivePattern = 0;
+ internal int currencyNegativePattern = 0;
+ internal int numberNegativePattern = 1;
+ internal int percentPositivePattern = 0;
+ internal int percentNegativePattern = 0;
+ internal int percentDecimalDigits = 2;
+
+
+ internal bool isReadOnly = false;
+
+ // Is this NumberFormatInfo for invariant culture?
+
+ [OptionalField(VersionAdded = 2)]
+ internal bool m_isInvariant = false;
+
+ public NumberFormatInfo() : this(null)
+ {
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx) { }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx) { }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx) { }
+
+ private static void VerifyDecimalSeparator(String decSep, String propertyName)
+ {
+ if (decSep == null)
+ {
+ throw new ArgumentNullException(propertyName,
+ SR.ArgumentNull_String);
+ }
+
+ if (decSep.Length == 0)
+ {
+ throw new ArgumentException(SR.Argument_EmptyDecString);
+ }
+ Contract.EndContractBlock();
+ }
+
+ private static void VerifyGroupSeparator(String groupSep, String propertyName)
+ {
+ if (groupSep == null)
+ {
+ throw new ArgumentNullException(propertyName,
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ }
+
+
+ internal NumberFormatInfo(CultureData cultureData)
+ {
+ if (cultureData != null)
+ {
+ // We directly use fields here since these data is coming from data table or Win32, so we
+ // don't need to verify their values (except for invalid parsing situations).
+ cultureData.GetNFIValues(this);
+
+ if (cultureData.IsInvariantCulture)
+ {
+ // For invariant culture
+ this.m_isInvariant = true;
+ }
+ }
+ }
+
+ [Pure]
+ private void VerifyWritable()
+ {
+ if (isReadOnly)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ }
+ Contract.EndContractBlock();
+ }
+
+ // Returns a default NumberFormatInfo that will be universally
+ // supported and constant irrespective of the current culture.
+ // Used by FromString methods.
+ //
+
+ public static NumberFormatInfo InvariantInfo
+ {
+ get
+ {
+ if (s_invariantInfo == null)
+ {
+ // Lazy create the invariant info. This cannot be done in a .cctor because exceptions can
+ // be thrown out of a .cctor stack that will need this.
+ NumberFormatInfo nfi = new NumberFormatInfo();
+ nfi.m_isInvariant = true;
+ s_invariantInfo = ReadOnly(nfi);
+ }
+ return s_invariantInfo;
+ }
+ }
+
+ public static NumberFormatInfo GetInstance(IFormatProvider formatProvider)
+ {
+ // Fast case for a regular CultureInfo
+ NumberFormatInfo info;
+ CultureInfo cultureProvider = formatProvider as CultureInfo;
+ if (cultureProvider != null && !cultureProvider.m_isInherited)
+ {
+ info = cultureProvider.numInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ else
+ {
+ return cultureProvider.NumberFormat;
+ }
+ }
+ // Fast case for an NFI;
+ info = formatProvider as NumberFormatInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ if (formatProvider != null)
+ {
+ info = formatProvider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ }
+ return CurrentInfo;
+ }
+
+
+
+ public Object Clone()
+ {
+ NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone();
+ n.isReadOnly = false;
+ return n;
+ }
+
+
+ public int CurrencyDecimalDigits
+ {
+ get { return currencyDecimalDigits; }
+ set
+ {
+ if (value < 0 || value > 99)
+ {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyDecimalDigits = value;
+ }
+ }
+
+
+ public String CurrencyDecimalSeparator
+ {
+ get { return currencyDecimalSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "CurrencyDecimalSeparator");
+ currencyDecimalSeparator = value;
+ }
+ }
+
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return isReadOnly;
+ }
+ }
+
+ //
+ // Check the values of the groupSize array.
+ //
+ // Every element in the groupSize array should be between 1 and 9
+ // excpet the last element could be zero.
+ //
+ internal static void CheckGroupSize(String propName, int[] groupSize)
+ {
+ for (int i = 0; i < groupSize.Length; i++)
+ {
+ if (groupSize[i] < 1)
+ {
+ if (i == groupSize.Length - 1 && groupSize[i] == 0)
+ return;
+ throw new ArgumentException(SR.Argument_InvalidGroupSize, propName);
+ }
+ else if (groupSize[i] > 9)
+ {
+ throw new ArgumentException(SR.Argument_InvalidGroupSize, propName);
+ }
+ }
+ }
+
+
+ public int[] CurrencyGroupSizes
+ {
+ get
+ {
+ return ((int[])currencyGroupSizes.Clone());
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("CurrencyGroupSizes",
+ SR.ArgumentNull_Obj);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("CurrencyGroupSizes", inputSizes);
+ currencyGroupSizes = inputSizes;
+ }
+ }
+
+
+
+ public int[] NumberGroupSizes
+ {
+ get
+ {
+ return ((int[])numberGroupSizes.Clone());
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("NumberGroupSizes",
+ SR.ArgumentNull_Obj);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("NumberGroupSizes", inputSizes);
+ numberGroupSizes = inputSizes;
+ }
+ }
+
+
+ public int[] PercentGroupSizes
+ {
+ get
+ {
+ return ((int[])percentGroupSizes.Clone());
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("PercentGroupSizes",
+ SR.ArgumentNull_Obj);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("PercentGroupSizes", inputSizes);
+ percentGroupSizes = inputSizes;
+ }
+ }
+
+
+ public String CurrencyGroupSeparator
+ {
+ get { return currencyGroupSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "CurrencyGroupSeparator");
+ currencyGroupSeparator = value;
+ }
+ }
+
+
+ public String CurrencySymbol
+ {
+ get { return currencySymbol; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("CurrencySymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencySymbol = value;
+ }
+ }
+
+ // Returns the current culture's NumberFormatInfo. Used by Parse methods.
+ //
+
+ public static NumberFormatInfo CurrentInfo
+ {
+ get
+ {
+ System.Globalization.CultureInfo culture = CultureInfo.CurrentCulture;
+ if (!culture.m_isInherited)
+ {
+ NumberFormatInfo info = culture.numInfo;
+ if (info != null)
+ {
+ return info;
+ }
+ }
+ return ((NumberFormatInfo)culture.GetFormat(typeof(NumberFormatInfo)));
+ }
+ }
+
+
+ public String NaNSymbol
+ {
+ get
+ {
+ return nanSymbol;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("NaNSymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ nanSymbol = value;
+ }
+ }
+
+
+
+ public int CurrencyNegativePattern
+ {
+ get { return currencyNegativePattern; }
+ set
+ {
+ if (value < 0 || value > 15)
+ {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 15));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyNegativePattern = value;
+ }
+ }
+
+
+ public int NumberNegativePattern
+ {
+ get { return numberNegativePattern; }
+ set
+ {
+ //
+ // NOTENOTE: the range of value should correspond to negNumberFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 4)
+ {
+ throw new ArgumentOutOfRangeException(
+ "NumberNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 4));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ numberNegativePattern = value;
+ }
+ }
+
+
+ public int PercentPositivePattern
+ {
+ get { return percentPositivePattern; }
+ set
+ {
+ //
+ // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 3)
+ {
+ throw new ArgumentOutOfRangeException(
+ "PercentPositivePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 3));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentPositivePattern = value;
+ }
+ }
+
+
+ public int PercentNegativePattern
+ {
+ get { return percentNegativePattern; }
+ set
+ {
+ //
+ // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 11)
+ {
+ throw new ArgumentOutOfRangeException(
+ "PercentNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 11));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentNegativePattern = value;
+ }
+ }
+
+
+ public String NegativeInfinitySymbol
+ {
+ get
+ {
+ return negativeInfinitySymbol;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("NegativeInfinitySymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ negativeInfinitySymbol = value;
+ }
+ }
+
+
+ public String NegativeSign
+ {
+ get { return negativeSign; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("NegativeSign",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ negativeSign = value;
+ }
+ }
+
+
+ public int NumberDecimalDigits
+ {
+ get { return numberDecimalDigits; }
+ set
+ {
+ if (value < 0 || value > 99)
+ {
+ throw new ArgumentOutOfRangeException(
+ "NumberDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ numberDecimalDigits = value;
+ }
+ }
+
+
+ public String NumberDecimalSeparator
+ {
+ get { return numberDecimalSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "NumberDecimalSeparator");
+ numberDecimalSeparator = value;
+ }
+ }
+
+
+ public String NumberGroupSeparator
+ {
+ get { return numberGroupSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "NumberGroupSeparator");
+ numberGroupSeparator = value;
+ }
+ }
+
+
+ public int CurrencyPositivePattern
+ {
+ get { return currencyPositivePattern; }
+ set
+ {
+ if (value < 0 || value > 3)
+ {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyPositivePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 3));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyPositivePattern = value;
+ }
+ }
+
+
+ public String PositiveInfinitySymbol
+ {
+ get
+ {
+ return positiveInfinitySymbol;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("PositiveInfinitySymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ positiveInfinitySymbol = value;
+ }
+ }
+
+
+ public String PositiveSign
+ {
+ get { return positiveSign; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("PositiveSign",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ positiveSign = value;
+ }
+ }
+
+
+ public int PercentDecimalDigits
+ {
+ get { return percentDecimalDigits; }
+ set
+ {
+ if (value < 0 || value > 99)
+ {
+ throw new ArgumentOutOfRangeException(
+ "PercentDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentDecimalDigits = value;
+ }
+ }
+
+
+ public String PercentDecimalSeparator
+ {
+ get { return percentDecimalSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "PercentDecimalSeparator");
+ percentDecimalSeparator = value;
+ }
+ }
+
+
+ public String PercentGroupSeparator
+ {
+ get { return percentGroupSeparator; }
+ set
+ {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "PercentGroupSeparator");
+ percentGroupSeparator = value;
+ }
+ }
+
+
+ public String PercentSymbol
+ {
+ get
+ {
+ return percentSymbol;
+ }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("PercentSymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentSymbol = value;
+ }
+ }
+
+
+ public String PerMilleSymbol
+ {
+ get { return perMilleSymbol; }
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("PerMilleSymbol",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ perMilleSymbol = value;
+ }
+ }
+
+ public Object GetFormat(Type formatType)
+ {
+ return formatType == typeof(NumberFormatInfo) ? this : null;
+ }
+
+ public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi)
+ {
+ if (nfi == null)
+ {
+ throw new ArgumentNullException("nfi");
+ }
+ Contract.EndContractBlock();
+ if (nfi.IsReadOnly)
+ {
+ return (nfi);
+ }
+ NumberFormatInfo info = (NumberFormatInfo)(nfi.MemberwiseClone());
+ info.isReadOnly = true;
+ return info;
+ }
+
+ // private const NumberStyles InvalidNumberStyles = unchecked((NumberStyles) 0xFFFFFC00);
+ private const NumberStyles InvalidNumberStyles = ~(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite
+ | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign
+ | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint
+ | NumberStyles.AllowThousands | NumberStyles.AllowExponent
+ | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier);
+
+ internal static void ValidateParseStyleInteger(NumberStyles style)
+ {
+ // Check for undefined flags
+ if ((style & InvalidNumberStyles) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidNumberStyles, "style");
+ }
+ Contract.EndContractBlock();
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // Check for hex number
+ if ((style & ~NumberStyles.HexNumber) != 0)
+ {
+ throw new ArgumentException(SR.Arg_InvalidHexStyle);
+ }
+ }
+ }
+
+ internal static void ValidateParseStyleFloatingPoint(NumberStyles style)
+ {
+ // Check for undefined flags
+ if ((style & InvalidNumberStyles) != 0)
+ {
+ throw new ArgumentException(SR.Argument_InvalidNumberStyles, "style");
+ }
+ Contract.EndContractBlock();
+ if ((style & NumberStyles.AllowHexSpecifier) != 0)
+ { // Check for hex number
+ throw new ArgumentException(SR.Arg_HexStyleNotSupported);
+ }
+ }
+ } // NumberFormatInfo
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs b/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs
new file mode 100644
index 0000000000..57bef7eee1
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/PersianCalendar.cs
@@ -0,0 +1,613 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about PersianCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ // Modern Persian calendar is a solar observation based calendar. Each new year begins on the day when the vernal equinox occurs before noon.
+ // The epoch is the date of the vernal equinox prior to the epoch of the Islamic calendar (March 19, 622 Julian or March 22, 622 Gregorian)
+
+ // There is no Persian year 0. Ordinary years have 365 days. Leap years have 366 days with the last month (Esfand) gaining the extra day.
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0622/03/22 9999/12/31
+ ** Persian 0001/01/01 9378/10/13
+ */
+
+ [Serializable]
+ public class PersianCalendar : Calendar
+ {
+ public static readonly int PersianEra = 1;
+
+ internal static long PersianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay;
+ private const int ApproximateHalfYear = 180;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+ internal const int MonthsPerYear = 12;
+
+ internal static int[] DaysToMonth = { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 };
+
+ internal const int MaxCalendarYear = 9378;
+ internal const int MaxCalendarMonth = 10;
+ internal const int MaxCalendarDay = 13;
+
+ // Persian calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 3, day: 22)
+ // This is the minimal Gregorian date that we support in the PersianCalendar.
+ internal static DateTime minDate = new DateTime(622, 3, 22);
+ internal static DateTime maxDate = DateTime.MaxValue;
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ // Return the type of the Persian calendar.
+ //
+
+
+ //public override CalendarAlgorithmType AlgorithmType {
+ // get {
+ // return CalendarAlgorithmType.SolarCalendar;
+ // }
+ //}
+
+ // Construct an instance of Persian calendar.
+
+ public PersianCalendar()
+ {
+ }
+
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ return CalendarId.GREGORIAN;
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.PERSIAN;
+ }
+ }
+
+
+ /*=================================GetAbsoluteDatePersian==========================
+ **Action: Gets the Absolute date for the given Persian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ private long GetAbsoluteDatePersian(int year, int month, int day)
+ {
+ if (year >= 1 && year <= MaxCalendarYear && month >= 1 && month <= 12)
+ {
+ int ordinalDay = DaysInPreviousMonths(month) + day - 1; // day is one based, make 0 based since this will be the number of days we add to beginning of year below
+ int approximateDaysFromEpochForYearStart = (int)(CalendricalCalculationsHelper.MeanTropicalYearInDays * (year - 1));
+ long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(PersianEpoch + approximateDaysFromEpochForYearStart + ApproximateHalfYear);
+ yearStart += ordinalDay;
+ return yearStart;
+ }
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+
+ internal static void CheckTicksRange(long ticks)
+ {
+ if (ticks < minDate.Ticks || ticks > maxDate.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.ArgumentOutOfRange_CalendarRange,
+ minDate,
+ maxDate));
+ }
+ }
+
+ internal static void CheckEraRange(int era)
+ {
+ if (era != CurrentEra && era != PersianEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ internal static void CheckYearRange(int year, int era)
+ {
+ CheckEraRange(era);
+ if (year < 1 || year > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarYear));
+ }
+ }
+
+ internal static void CheckYearMonthRange(int year, int month, int era)
+ {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear)
+ {
+ if (month > MaxCalendarMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarMonth));
+ }
+ }
+
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ }
+
+ private static int MonthFromOrdinalDay(int ordinalDay)
+ {
+ Contract.Assert(ordinalDay <= 366);
+ int index = 0;
+ while (ordinalDay > DaysToMonth[index])
+ index++;
+
+ return index;
+ }
+
+ private static int DaysInPreviousMonths(int month)
+ {
+ Contract.Assert(1 <= month && month <= 12);
+ --month; // months are one based but for calculations use 0 based
+ return DaysToMonth[month];
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ ============================================================================*/
+
+ internal int GetDatePart(long ticks, int part)
+ {
+ long NumDays; // The calculation buffer in number of days.
+
+ CheckTicksRange(ticks);
+
+ //
+ // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ //
+ NumDays = ticks / GregorianCalendar.TicksPerDay + 1;
+
+ //
+ // Calculate the appromixate Persian Year.
+ //
+
+ long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(NumDays);
+ int y = (int)(Math.Floor(((yearStart - PersianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1;
+ Contract.Assert(y >= 1);
+
+ if (part == DatePartYear)
+ {
+ return y;
+ }
+
+ //
+ // Calculate the Persian Month.
+ //
+
+ int ordinalDay = (int)(NumDays - CalendricalCalculationsHelper.GetNumberOfDays(this.ToDateTime(y, 1, 1, 0, 0, 0, 0, 1)));
+
+ if (part == DatePartDayOfYear)
+ {
+ return ordinalDay;
+ }
+
+ int m = MonthFromOrdinalDay(ordinalDay);
+ Contract.Assert(ordinalDay >= 1);
+ Contract.Assert(m >= 1 && m <= 12);
+ if (part == DatePartMonth)
+ {
+ return m;
+ }
+
+ int d = ordinalDay - DaysInPreviousMonths(m);
+ Contract.Assert(1 <= d);
+ Contract.Assert(d <= 31);
+
+ //
+ // Calculate the Persian Day.
+ //
+
+ if (part == DatePartDay)
+ {
+ return (d);
+ }
+
+ // Incorrect part value.
+ throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in Persian calendar.
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int days = GetDaysInMonth(y, m);
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = GetAbsoluteDatePersian(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+
+ if ((month == MaxCalendarMonth) && (year == MaxCalendarYear))
+ {
+ return MaxCalendarDay;
+ }
+
+ int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1];
+ if ((month == MonthsPerYear) && !IsLeapYear(year))
+ {
+ Contract.Assert(daysInMonth == 30);
+ --daysInMonth;
+ }
+ return daysInMonth;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear)
+ {
+ return DaysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay;
+ }
+ // Common years have 365 days. Leap years have 366 days.
+ return (IsLeapYear(year, CurrentEra) ? 366 : 365);
+ }
+
+ // Returns the era for the specified DateTime value.
+
+
+ public override int GetEra(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return (PersianEra);
+ }
+
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { PersianEra });
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear)
+ {
+ return MaxCalendarMonth;
+ }
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+ return (IsLeapYear(year, era) && month == 12 && day == 30);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+
+ if (year == MaxCalendarYear)
+ {
+ return false;
+ }
+
+ return (GetAbsoluteDatePersian(year + 1, 1, 1) - GetAbsoluteDatePersian(year, 1, 1)) == 366;
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ // The year/month/era checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ // BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+
+ long lDate = GetAbsoluteDatePersian(year, month, day);
+
+ if (lDate >= 0)
+ {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1410;
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ MaxCalendarYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100)
+ {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/RegionInfo.cs b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs
new file mode 100644
index 0000000000..0669349040
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/RegionInfo.cs
@@ -0,0 +1,324 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class represents settings specified by de jure or
+// de facto standards for a particular country/region. In
+// contrast to CultureInfo, the RegionInfo does not represent
+// preferences of the user and does not depend on the user's
+// language or culture.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+
+namespace System.Globalization
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class RegionInfo
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //
+ // Variables.
+ //
+
+ //
+ // Name of this region (ie: es-US): serialized, the field used for deserialization
+ //
+ internal String _name;
+
+ //
+ // The CultureData instance that we are going to read data from.
+ //
+ internal CultureData _cultureData;
+
+ //
+ // The RegionInfo for our current region
+ //
+ internal static volatile RegionInfo s_currentRegionInfo;
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // RegionInfo Constructors
+ //
+ // Note: We prefer that a region be created with a full culture name (ie: en-US)
+ // because otherwise the native strings won't be right.
+ //
+ // In Silverlight we enforce that RegionInfos must be created with a full culture name
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public RegionInfo(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0) //The InvariantCulture has no matching region
+ {
+ throw new ArgumentException(SR.Argument_NoRegionInvariantCulture, "name");
+ }
+
+ Contract.EndContractBlock();
+
+ //
+ // For CoreCLR we only want the region names that are full culture names
+ //
+ _cultureData = CultureData.GetCultureDataForRegion(name, true);
+ if (_cultureData == null)
+ throw new ArgumentException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.Argument_InvalidCultureName, name), "name");
+
+
+ // Not supposed to be neutral
+ if (_cultureData.IsNeutralCulture)
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidNeutralRegionName, name), "name");
+
+ SetName(name);
+ }
+
+ internal RegionInfo(CultureData cultureData)
+ {
+ _cultureData = cultureData;
+ _name = _cultureData.SREGIONNAME;
+ }
+
+ private void SetName(string name)
+ {
+ // Use the name of the region we found
+ _name = _cultureData.SREGIONNAME;
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx) { }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ _cultureData = CultureData.GetCultureData(_name, true);
+
+ if (_cultureData == null)
+ {
+ throw new ArgumentException(
+ String.Format(CultureInfo.CurrentCulture, SR.Argument_InvalidCultureName, _name),
+ "_name");
+ }
+
+ _name = _cultureData.SREGIONNAME;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetCurrentRegion
+ //
+ // This instance provides methods based on the current user settings.
+ // These settings are volatile and may change over the lifetime of the
+ // thread.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public static RegionInfo CurrentRegion
+ {
+ get
+ {
+ RegionInfo temp = s_currentRegionInfo;
+ if (temp == null)
+ {
+ temp = new RegionInfo(CultureInfo.CurrentCulture.m_cultureData);
+
+ // Need full name for custom cultures
+ temp._name = temp._cultureData.SREGIONNAME;
+ s_currentRegionInfo = temp;
+ }
+ return temp;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetName
+ //
+ // Returns the name of the region (ie: en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String Name
+ {
+ get
+ {
+ Contract.Assert(_name != null, "Expected RegionInfo._name to be populated already");
+ return (_name);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetEnglishName
+ //
+ // Returns the name of the region in English. (ie: United States)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String EnglishName
+ {
+ get
+ {
+ return (_cultureData.SENGCOUNTRY);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetDisplayName
+ //
+ // Returns the display name (localized) of the region. (ie: United States
+ // if the current UI language is en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String DisplayName
+ {
+ get
+ {
+ return (_cultureData.SLOCALIZEDCOUNTRY);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetNativeName
+ //
+ // Returns the native name of the region. (ie: Deutschland)
+ // WARNING: You need a full locale name for this to make sense.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String NativeName
+ {
+ get
+ {
+ return (_cultureData.SNATIVECOUNTRY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // TwoLetterISORegionName
+ //
+ // Returns the two letter ISO region name (ie: US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String TwoLetterISORegionName
+ {
+ get
+ {
+ return (_cultureData.SISO3166CTRYNAME);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsMetric
+ //
+ // Returns true if this region uses the metric measurement system
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual bool IsMetric
+ {
+ get
+ {
+ int value = _cultureData.IMEASURE;
+ return (value == 0);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrencySymbol
+ //
+ // Currency Symbol for this locale, ie: Fr. or $
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String CurrencySymbol
+ {
+ get
+ {
+ return (_cultureData.SCURRENCY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ISOCurrencySymbol
+ //
+ // ISO Currency Symbol for this locale, ie: CHF
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ISOCurrencySymbol
+ {
+ get
+ {
+ return (_cultureData.SINTLSYMBOL);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same RegionInfo as the current instance.
+ //
+ // RegionInfos are considered equal if and only if they have the same name
+ // (ie: en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override bool Equals(Object value)
+ {
+ RegionInfo that = value as RegionInfo;
+ if (that != null)
+ {
+ return this.Name.Equals(that.Name);
+ }
+
+ return (false);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for RegionInfo
+ // A and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns the name of the Region, ie: es-US
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override String ToString()
+ {
+ return (Name);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/STUBS.cs b/src/mscorlib/corefx/System/Globalization/STUBS.cs
new file mode 100644
index 0000000000..8c85e836d6
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/STUBS.cs
@@ -0,0 +1,180 @@
+namespace System.Globalization
+{
+ public abstract partial class Calendar : System.ICloneable
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GetLeapMonth(int year) { throw new NotImplementedException(); }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CalendarAlgorithmType
+ {
+ Unknown = 0, // This is the default value to return in the Calendar base class.
+ SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc.
+ // Solar calendars are based on the solar year and seasons.
+ LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar.
+ // Lunar calendars are based on the path of the moon. The seasons are not accurately represented.
+ LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars.
+ // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration,
+ // so they align with the seasons as well as lunar events.
+ }
+
+ public static partial class CharUnicodeInfo
+ {
+ public static int GetDecimalDigitValue(char ch) { throw new NotImplementedException(); }
+ public static int GetDecimalDigitValue(string s, int index) { throw new NotImplementedException(); }
+ public static int GetDigitValue(char ch) { throw new NotImplementedException(); }
+ public static int GetDigitValue(string s, int index) { throw new NotImplementedException(); }
+ }
+
+ public partial class CompareInfo : System.Runtime.Serialization.IDeserializationCallback
+ {
+ public int LCID { get { throw new NotImplementedException(); } }
+ public static System.Globalization.CompareInfo GetCompareInfo(int culture) { throw new NotImplementedException(); }
+ public static System.Globalization.CompareInfo GetCompareInfo(int culture, System.Reflection.Assembly assembly) { throw new NotImplementedException(); }
+ public static System.Globalization.CompareInfo GetCompareInfo(string name, System.Reflection.Assembly assembly) { throw new NotImplementedException(); }
+ public virtual System.Globalization.SortKey GetSortKey(string source) { throw new NotImplementedException(); }
+ public virtual System.Globalization.SortKey GetSortKey(string source, System.Globalization.CompareOptions options) { throw new NotImplementedException(); }
+ public virtual int IndexOf(string source, char value, int startIndex) { throw new NotImplementedException(); }
+ public virtual int IndexOf(string source, string value, int startIndex) { throw new NotImplementedException(); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static bool IsSortable(char ch) { throw new NotImplementedException(); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsSortable(string text) { throw new NotImplementedException(); }
+ public virtual int LastIndexOf(string source, char value, int startIndex) { throw new NotImplementedException(); }
+ public virtual int LastIndexOf(string source, string value, int startIndex) { throw new NotImplementedException(); }
+ }
+
+ public partial class CultureInfo : System.ICloneable, System.IFormatProvider
+ {
+ public CultureInfo(int culture) { throw new NotImplementedException(); }
+ public CultureInfo(int culture, bool useUserOverride) { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo InstalledUICulture { get { throw new NotImplementedException(); } }
+ public virtual int LCID { get { throw new NotImplementedException(); } }
+ public virtual string ThreeLetterISOLanguageName { get { throw new NotImplementedException(); } }
+ public virtual string ThreeLetterWindowsLanguageName { get { throw new NotImplementedException(); } }
+ public void ClearCachedData() { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo CreateSpecificCulture(string name) { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo GetCultureInfo(int culture) { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo GetCultureInfo(string name, string altName) { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo GetCultureInfoByIetfLanguageTag(string name) { throw new NotImplementedException(); }
+ public static System.Globalization.CultureInfo[] GetCultures(System.Globalization.CultureTypes types) { throw new NotImplementedException(); }
+ }
+
+ public partial class CultureNotFoundException : System.ArgumentException, System.Runtime.Serialization.ISerializable
+ {
+ public CultureNotFoundException(string message, int invalidCultureId, System.Exception innerException) { throw new NotImplementedException(); }
+ public CultureNotFoundException(string paramName, int invalidCultureId, string message) { throw new NotImplementedException(); }
+ public virtual System.Nullable<int> InvalidCultureId { get { throw new NotImplementedException(); } }
+ }
+
+ public enum CultureTypes
+ {
+ AllCultures = 7,
+ [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")]
+ FrameworkCultures = 64,
+ InstalledWin32Cultures = 4,
+ NeutralCultures = 1,
+ ReplacementCultures = 16,
+ SpecificCultures = 2,
+ UserCustomCulture = 8,
+ [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")]
+ WindowsOnlyCultures = 32,
+ }
+
+ public sealed partial class DateTimeFormatInfo : System.ICloneable, System.IFormatProvider
+ {
+ // Can't do partial properties so add the setter for DateSeparator and TimeSeparator
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string NativeCalendarName { get { throw new NotImplementedException(); } }
+ public string[] GetAllDateTimePatterns() { throw new NotImplementedException(); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string GetShortestDayName(System.DayOfWeek dayOfWeek) { throw new NotImplementedException(); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetAllDateTimePatterns(string[] patterns, char format) { throw new NotImplementedException(); }
+ }
+
+ public enum DigitShapes
+ {
+ Context = 0,
+ NativeNational = 2,
+ None = 1,
+ }
+
+ public sealed partial class IdnMapping
+ {
+ public IdnMapping() { }
+ public bool AllowUnassigned { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
+ public bool UseStd3AsciiRules { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
+ public override bool Equals(object obj) { throw new NotImplementedException(); }
+ public string GetAscii(string unicode) { throw new NotImplementedException(); }
+ public string GetAscii(string unicode, int index) { throw new NotImplementedException(); }
+ public string GetAscii(string unicode, int index, int count) { throw new NotImplementedException(); }
+ public override int GetHashCode() { throw new NotImplementedException(); }
+ public string GetUnicode(string ascii) { throw new NotImplementedException(); }
+ public string GetUnicode(string ascii, int index) { throw new NotImplementedException(); }
+ public string GetUnicode(string ascii, int index, int count) { throw new NotImplementedException(); }
+ }
+
+ public sealed partial class NumberFormatInfo : System.ICloneable, System.IFormatProvider
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Globalization.DigitShapes DigitSubstitution { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] NativeDigits { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
+ }
+
+ public partial class RegionInfo
+ {
+ public RegionInfo(int culture) { throw new NotImplementedException(); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string CurrencyEnglishName { get { throw new NotImplementedException(); } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string CurrencyNativeName { get { throw new NotImplementedException(); } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GeoId { get { throw new NotImplementedException(); } }
+ public virtual string ThreeLetterISORegionName { get { throw new NotImplementedException(); } }
+ public virtual string ThreeLetterWindowsRegionName { get { throw new NotImplementedException(); } }
+ }
+
+ public partial class SortKey
+ {
+ internal SortKey() { throw new NotImplementedException(); }
+ public virtual byte[] KeyData { get { throw new NotImplementedException(); } }
+ public virtual string OriginalString { get { throw new NotImplementedException(); } }
+ public static int Compare(System.Globalization.SortKey sortkey1, System.Globalization.SortKey sortkey2) { throw new NotImplementedException(); }
+ public override bool Equals(object value) { throw new NotImplementedException(); }
+ public override int GetHashCode() { throw new NotImplementedException(); }
+ public override string ToString() { throw new NotImplementedException(); }
+ }
+
+ public sealed partial class SortVersion : System.IEquatable<System.Globalization.SortVersion>
+ {
+ public SortVersion(int fullVersion, System.Guid sortId) { throw new NotImplementedException(); }
+ public int FullVersion { get { throw new NotImplementedException(); } }
+ public System.Guid SortId { get { throw new NotImplementedException(); } }
+ public bool Equals(System.Globalization.SortVersion other) { throw new NotImplementedException(); }
+ public override bool Equals(object obj) { throw new NotImplementedException(); }
+ public override int GetHashCode() { throw new NotImplementedException(); }
+ public static bool operator ==(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw new NotImplementedException(); }
+ public static bool operator !=(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw new NotImplementedException(); }
+ }
+
+ public partial class StringInfo
+ {
+ public string SubstringByTextElements(int startingTextElement) { throw new NotImplementedException(); }
+ public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) { throw new NotImplementedException(); }
+ }
+
+ public partial class TextInfo : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback
+ {
+ public virtual int ANSICodePage { get { throw new NotImplementedException(); } }
+ public virtual int EBCDICCodePage { get { throw new NotImplementedException(); } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public int LCID { get { throw new NotImplementedException(); } }
+ public virtual int MacCodePage { get { throw new NotImplementedException(); } }
+ public virtual int OEMCodePage { get { throw new NotImplementedException(); } }
+ public string ToTitleCase(string str) { throw new NotImplementedException(); }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/corefx/System/Globalization/StringInfo.cs b/src/mscorlib/corefx/System/Globalization/StringInfo.cs
new file mode 100644
index 0000000000..102f703beb
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/StringInfo.cs
@@ -0,0 +1,322 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class defines behaviors specific to a writing system.
+// A writing system is the collection of scripts and
+// orthographic rules required to represent a language as text.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+
+namespace System.Globalization
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class StringInfo
+ {
+ [OptionalField(VersionAdded = 2)]
+ private String _str;
+
+ [NonSerialized]
+ private int[] _indexes;
+
+ // Legacy constructor
+ public StringInfo() : this("") { }
+
+ // Primary, useful constructor
+ public StringInfo(String value)
+ {
+ this.String = value;
+ }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ _str = String.Empty;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (_str.Length == 0)
+ {
+ _indexes = null;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals(Object value)
+ {
+ StringInfo that = value as StringInfo;
+ if (that != null)
+ {
+ return (_str.Equals(that._str));
+ }
+ return (false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ return _str.GetHashCode();
+ }
+
+
+ // Our zero-based array of index values into the string. Initialize if
+ // our private array is not yet, in fact, initialized.
+ private int[] Indexes
+ {
+ get
+ {
+ if ((null == _indexes) && (0 < this.String.Length))
+ {
+ _indexes = StringInfo.ParseCombiningCharacters(this.String);
+ }
+
+ return (_indexes);
+ }
+ }
+
+ public String String
+ {
+ get
+ {
+ return (_str);
+ }
+ set
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException("String",
+ SR.ArgumentNull_String);
+ }
+ Contract.EndContractBlock();
+
+ _str = value;
+ _indexes = null;
+ }
+ }
+
+ public int LengthInTextElements
+ {
+ get
+ {
+ if (null == this.Indexes)
+ {
+ // Indexes not initialized, so assume length zero
+ return (0);
+ }
+
+ return (this.Indexes.Length);
+ }
+ }
+
+ public static String GetNextTextElement(String str)
+ {
+ return (GetNextTextElement(str, 0));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the code point count of the current text element.
+ //
+ // A combining class is defined as:
+ // A character/surrogate that has the following Unicode category:
+ // * NonSpacingMark (e.g. U+0300 COMBINING GRAVE ACCENT)
+ // * SpacingCombiningMark (e.g. U+ 0903 DEVANGARI SIGN VISARGA)
+ // * EnclosingMark (e.g. U+20DD COMBINING ENCLOSING CIRCLE)
+ //
+ // In the context of GetNextTextElement() and ParseCombiningCharacters(), a text element is defined as:
+ //
+ // 1. If a character/surrogate is in the following category, it is a text element.
+ // It can NOT further combine with characters in the combinging class to form a text element.
+ // * one of the Unicode category in the combinging class
+ // * UnicodeCategory.Format
+ // * UnicodeCateogry.Control
+ // * UnicodeCategory.OtherNotAssigned
+ // 2. Otherwise, the character/surrogate can be combined with characters in the combinging class to form a text element.
+ //
+ // Return:
+ // The length of the current text element
+ //
+ // Parameters:
+ // String str
+ // index The starting index
+ // len The total length of str (to define the upper boundary)
+ // ucCurrent The Unicode category pointed by Index. It will be updated to the uc of next character if this is not the last text element.
+ // currentCharCount The char count of an abstract char pointed by Index. It will be updated to the char count of next abstract character if this is not the last text element.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int GetCurrentTextElementLen(String str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount)
+ {
+ Contract.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
+ Contract.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
+ if (index + currentCharCount == len)
+ {
+ // This is the last character/surrogate in the string.
+ return (currentCharCount);
+ }
+
+ // Call an internal GetUnicodeCategory, which will tell us both the unicode category, and also tell us if it is a surrogate pair or not.
+ int nextCharCount;
+ UnicodeCategory ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index + currentCharCount, out nextCharCount);
+ if (CharUnicodeInfo.IsCombiningCategory(ucNext))
+ {
+ // The next element is a combining class.
+ // Check if the current text element to see if it is a valid base category (i.e. it should not be a combining category,
+ // not a format character, and not a control character).
+
+ if (CharUnicodeInfo.IsCombiningCategory(ucCurrent)
+ || (ucCurrent == UnicodeCategory.Format)
+ || (ucCurrent == UnicodeCategory.Control)
+ || (ucCurrent == UnicodeCategory.OtherNotAssigned)
+ || (ucCurrent == UnicodeCategory.Surrogate)) // An unpair high surrogate or low surrogate
+ {
+ // Will fall thru and return the currentCharCount
+ }
+ else
+ {
+ int startIndex = index; // Remember the current index.
+
+ // We have a valid base characters, and we have a character (or surrogate) that is combining.
+ // Check if there are more combining characters to follow.
+ // Check if the next character is a nonspacing character.
+ index += currentCharCount + nextCharCount;
+
+ while (index < len)
+ {
+ ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out nextCharCount);
+ if (!CharUnicodeInfo.IsCombiningCategory(ucNext))
+ {
+ ucCurrent = ucNext;
+ currentCharCount = nextCharCount;
+ break;
+ }
+ index += nextCharCount;
+ }
+ return (index - startIndex);
+ }
+ }
+ // The return value will be the currentCharCount.
+ int ret = currentCharCount;
+ ucCurrent = ucNext;
+ // Update currentCharCount.
+ currentCharCount = nextCharCount;
+ return (ret);
+ }
+
+ // Returns the str containing the next text element in str starting at
+ // index index. If index is not supplied, then it will start at the beginning
+ // of str. It recognizes a base character plus one or more combining
+ // characters or a properly formed surrogate pair as a text element. See also
+ // the ParseCombiningCharacters() and the ParseSurrogates() methods.
+ public static String GetNextTextElement(String str, int index)
+ {
+ //
+ // Validate parameters.
+ //
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ if (index < 0 || index >= len)
+ {
+ if (index == len)
+ {
+ return (String.Empty);
+ }
+ throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index);
+ }
+
+ int charLen;
+ UnicodeCategory uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
+ return (str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen)));
+ }
+
+ public static TextElementEnumerator GetTextElementEnumerator(String str)
+ {
+ return (GetTextElementEnumerator(str, 0));
+ }
+
+ public static TextElementEnumerator GetTextElementEnumerator(String str, int index)
+ {
+ //
+ // Validate parameters.
+ //
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ if (index < 0 || (index > len))
+ {
+ throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index);
+ }
+
+ return (new TextElementEnumerator(str, index, len));
+ }
+
+ /*
+ * Returns the indices of each base character or properly formed surrogate pair
+ * within the str. It recognizes a base character plus one or more combining
+ * characters or a properly formed surrogate pair as a text element and returns
+ * the index of the base character or high surrogate. Each index is the
+ * beginning of a text element within a str. The length of each element is
+ * easily computed as the difference between successive indices. The length of
+ * the array will always be less than or equal to the length of the str. For
+ * example, given the str \u4f00\u302a\ud800\udc00\u4f01, this method would
+ * return the indices: 0, 2, 4.
+ */
+
+ public static int[] ParseCombiningCharacters(String str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ int[] result = new int[len];
+ if (len == 0)
+ {
+ return (result);
+ }
+
+ int resultCount = 0;
+
+ int i = 0;
+ int currentCharLen;
+ UnicodeCategory currentCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, 0, out currentCharLen);
+
+ while (i < len)
+ {
+ result[resultCount++] = i;
+ i += GetCurrentTextElementLen(str, i, len, ref currentCategory, ref currentCharLen);
+ }
+
+ if (resultCount < len)
+ {
+ int[] returnArray = new int[resultCount];
+ Array.Copy(result, returnArray, resultCount);
+ return (returnArray);
+ }
+ return (result);
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs
new file mode 100644
index 0000000000..89b2e4a41d
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TaiwanCalendar.cs
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ /*=================================TaiwanCalendar==========================
+ **
+ ** Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
+ ** That is,
+ ** Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1912/01/01 9999/12/31
+ ** Taiwan 01/01/01 8088/12/31
+ ============================================================================*/
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class TaiwanCalendar : Calendar
+ {
+ //
+ // The era value for the current era.
+ //
+
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // When Gregorian Year 1912 is year 1, so that
+ // 1912 = 1 + yearOffset
+ // So yearOffset = 1911
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911);
+
+ // Initialize our era info.
+ internal static EraInfo[] taiwanEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal static volatile Calendar s_defaultInstance;
+
+ internal GregorianCalendarHelper helper;
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of TaiwanCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance()
+ {
+ if (s_defaultInstance == null)
+ {
+ s_defaultInstance = new TaiwanCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+ internal static readonly DateTime calendarMinValue = new DateTime(1912, 1, 1);
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Taiwan calendar.
+ //
+
+ public TaiwanCalendar()
+ {
+ try
+ {
+ new CultureInfo("zh-TW");
+ }
+ catch (ArgumentException e)
+ {
+ throw new TypeInitializationException(this.GetType().ToString(), e);
+ }
+ helper = new GregorianCalendarHelper(this, taiwanEraInfo);
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return CalendarId.TAIWAN;
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (helper.AddYears(time, years));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time)
+ {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99;
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ helper.MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+ // For Taiwan calendar, four digit year is not used.
+ // Therefore, for any two digit number, we just return the original number.
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year <= 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedPosNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 1,
+ helper.MaxYear));
+ }
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs b/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs
new file mode 100644
index 0000000000..42b7f2473b
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TaiwanLunisolarCalendar.cs
@@ -0,0 +1,330 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about TaiwanLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1912/02/18 2051/02/10
+ ** TaiwanLunisolar 1912/01/01 2050/13/29
+ */
+
+ [Serializable]
+ public class TaiwanLunisolarCalendar : EastAsianLunisolarCalendar
+ {
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // When Gregorian Year 1912 is year 1, so that
+ // 1912 = 1 + yearOffset
+ // So yearOffset = 1911
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911);
+
+ // Initialize our era info.
+ internal static EraInfo[] taiwanLunisolarEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal GregorianCalendarHelper helper;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1912;
+ internal const int MAX_LUNISOLAR_YEAR = 2050;
+
+ internal const int MIN_GREGORIAN_YEAR = 1912;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 18;
+
+ internal const int MAX_GREGORIAN_YEAR = 2051;
+ internal const int MAX_GREGORIAN_MONTH = 2;
+ internal const int MAX_GREGORIAN_DAY = 10;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1911 from ChineseLunisolarCalendar
+ return 384;
+ }
+ }
+
+ private static readonly int[,] s_yinfo =
+ {
+ /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+ 1912 */
+ { 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
+2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+ */};
+
+
+ internal override int MinCalendarYear
+ {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear
+ {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo
+ {
+ get
+ {
+ return (taiwanLunisolarEraInfo);
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index)
+ {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return s_yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time)
+ {
+ return helper.GetYear(year, time);
+ }
+
+ internal override int GetGregorianYear(int year, int era)
+ {
+ return helper.GetGregorianYear(year, era);
+ }
+
+ public TaiwanLunisolarCalendar()
+ {
+ helper = new GregorianCalendarHelper(this, taiwanLunisolarEraInfo);
+ }
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ return (CalendarId.TAIWAN);
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.TAIWANLUNISOLAR);
+ }
+ }
+
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs
new file mode 100644
index 0000000000..487ef11130
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TextElementEnumerator.cs
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose:
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System.Collections;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+
+namespace System.Globalization
+{
+ //
+ // This is public because GetTextElement() is public.
+ //
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class TextElementEnumerator : IEnumerator
+ {
+ private String _str;
+ private int _index;
+ private int _startIndex;
+
+ [NonSerialized]
+ private int _strLen; // This is the length of the total string, counting from the beginning of string.
+
+ [NonSerialized]
+ private int _currTextElementLen; // The current text element lenght after MoveNext() is called.
+
+ [OptionalField(VersionAdded = 2)]
+ private UnicodeCategory _uc;
+
+ [OptionalField(VersionAdded = 2)]
+ private int _charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not.
+
+ internal TextElementEnumerator(String str, int startIndex, int strLen)
+ {
+ Contract.Assert(str != null, "TextElementEnumerator(): str != null");
+ Contract.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
+ Contract.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex");
+ _str = str;
+ _startIndex = startIndex;
+ _strLen = strLen;
+ Reset();
+ }
+
+ // the following fields is defined to keep the compatibility with Everett.
+ // don't change/remove the names/types of these fields.
+ private int _endIndex;
+ private int _nextTextElementLen;
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ _charLen = -1;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ _strLen = _endIndex + 1;
+ _currTextElementLen = _nextTextElementLen;
+
+ if (_charLen == -1)
+ {
+ _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen);
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ _endIndex = _strLen - 1;
+ _nextTextElementLen = _currTextElementLen;
+ }
+
+ public bool MoveNext()
+ {
+ if (_index >= _strLen)
+ {
+ // Make the _index to be greater than _strLen so that we can throw exception if GetTextElement() is called.
+ _index = _strLen + 1;
+ return (false);
+ }
+ _currTextElementLen = StringInfo.GetCurrentTextElementLen(_str, _index, _strLen, ref _uc, ref _charLen);
+ _index += _currTextElementLen;
+ return (true);
+ }
+
+ //
+ // Get the current text element.
+ //
+
+ public Object Current
+ {
+ get
+ {
+ return (GetTextElement());
+ }
+ }
+
+ //
+ // Get the current text element.
+ //
+
+ public String GetTextElement()
+ {
+ if (_index == _startIndex)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ }
+ if (_index > _strLen)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumEnded);
+ }
+
+ return (_str.Substring(_index - _currTextElementLen, _currTextElementLen));
+ }
+
+ //
+ // Get the starting _index of the current text element.
+ //
+
+ public int ElementIndex
+ {
+ get
+ {
+ if (_index == _startIndex)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_EnumNotStarted);
+ }
+ return (_index - _currTextElementLen);
+ }
+ }
+
+
+ public void Reset()
+ {
+ _index = _startIndex;
+ if (_index < _strLen)
+ {
+ // If we have more than 1 character, get the category of the current char.
+ _uc = CharUnicodeInfo.InternalGetUnicodeCategory(_str, _index, out _charLen);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs
new file mode 100644
index 0000000000..8490057306
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Unix.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Security;
+using System.Text;
+
+namespace System.Globalization
+{
+ public partial class TextInfo
+ {
+ [NonSerialized]
+ private Tristate _needsTurkishCasing = Tristate.NotInitialized;
+
+ //////////////////////////////////////////////////////////////////////////
+ ////
+ //// TextInfo Constructors
+ ////
+ //// Implements CultureInfo.TextInfo.
+ ////
+ //////////////////////////////////////////////////////////////////////////
+ internal unsafe TextInfo(CultureData cultureData)
+ {
+ _cultureData = cultureData;
+ _cultureName = _cultureData.CultureName;
+ _textInfoName = _cultureData.STEXTINFO;
+ FinishInitialization(_textInfoName);
+ }
+
+ private void FinishInitialization(string textInfoName)
+ {
+ }
+
+ [SecuritySafeCritical]
+ private unsafe string ChangeCase(string s, bool toUpper)
+ {
+ Contract.Assert(s != null);
+
+ if (s.Length == 0)
+ {
+ return string.Empty;
+ }
+
+ string result = string.FastAllocateString(s.Length);
+
+ fixed (char* pSource = s)
+ {
+ fixed (char* pResult = result)
+ {
+ if (IsAsciiCasingSameAsInvariant && s.IsAscii())
+ {
+ int length = s.Length;
+ char* a = pSource, b = pResult;
+ if (toUpper)
+ {
+ while (length-- != 0)
+ {
+ *b++ = ToUpperAsciiInvariant(*a++);
+ }
+ }
+ else
+ {
+ while (length-- != 0)
+ {
+ *b++ = ToLowerAsciiInvariant(*a++);
+ }
+ }
+ }
+ else
+ {
+ ChangeCase(pSource, s.Length, pResult, result.Length, toUpper);
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [SecuritySafeCritical]
+ private unsafe char ChangeCase(char c, bool toUpper)
+ {
+ char dst = default(char);
+
+ ChangeCase(&c, 1, &dst, 1, toUpper);
+
+ return dst;
+ }
+
+ // -----------------------------
+ // ---- PAL layer ends here ----
+ // -----------------------------
+
+ private bool NeedsTurkishCasing(string localeName)
+ {
+ Contract.Assert(localeName != null);
+
+ return CultureInfo.GetCultureInfo(localeName).CompareInfo.Compare("\u0131", "I", CompareOptions.IgnoreCase) == 0;
+ }
+
+ private bool IsInvariant { get { return _cultureName.Length == 0; } }
+
+ internal unsafe void ChangeCase(char* src, int srcLen, char* dstBuffer, int dstBufferCapacity, bool bToUpper)
+ {
+ if (IsInvariant)
+ {
+ Interop.GlobalizationInterop.ChangeCaseInvariant(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
+ }
+ else
+ {
+ if (_needsTurkishCasing == Tristate.NotInitialized)
+ {
+ _needsTurkishCasing = NeedsTurkishCasing(_textInfoName) ? Tristate.True : Tristate.False;
+ }
+ if (_needsTurkishCasing == Tristate.True)
+ {
+ Interop.GlobalizationInterop.ChangeCaseTurkish(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
+ }
+ else
+ {
+ Interop.GlobalizationInterop.ChangeCase(src, srcLen, dstBuffer, dstBufferCapacity, bToUpper);
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs
new file mode 100644
index 0000000000..238c51217b
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TextInfo.Windows.cs
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ public partial class TextInfo
+ {
+ //////////////////////////////////////////////////////////////////////////
+ ////
+ //// TextInfo Constructors
+ ////
+ //// Implements CultureInfo.TextInfo.
+ ////
+ //////////////////////////////////////////////////////////////////////////
+ internal unsafe TextInfo(CultureData cultureData)
+ {
+ // This is our primary data source, we don't need most of the rest of this
+ _cultureData = cultureData;
+ _cultureName = _cultureData.CultureName;
+ _textInfoName = _cultureData.STEXTINFO;
+ FinishInitialization(_textInfoName);
+ }
+
+ private void FinishInitialization(string textInfoName)
+ {
+ const uint LCMAP_SORTHANDLE = 0x20000000;
+
+ long handle;
+ int ret = Interop.mincore.LCMapStringEx(_textInfoName, LCMAP_SORTHANDLE, null, 0, &handle, IntPtr.Size, null, null, IntPtr.Zero);
+ _sortHandle = ret > 0 ? (IntPtr)handle : IntPtr.Zero;
+ }
+
+ private unsafe string ChangeCase(string s, bool toUpper)
+ {
+ Contract.Assert(s != null);
+
+ //
+ // Get the length of the string.
+ //
+ int nLengthInput = s.Length;
+
+ //
+ // Check if we have the empty string.
+ //
+ if (nLengthInput == 0)
+ {
+ return s;
+ }
+ else
+ {
+ int ret;
+
+ // Check for Invariant to avoid A/V in LCMapStringEx
+ uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
+
+ //
+ // Create the result string.
+ //
+ string result = string.FastAllocateString(nLengthInput);
+
+ fixed (char* pSource = s)
+ fixed (char* pResult = result)
+ {
+ ret = Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
+ toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
+ pSource,
+ nLengthInput,
+ pResult,
+ nLengthInput,
+ null,
+ null,
+ _sortHandle);
+ }
+
+ if (0 == ret)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ }
+
+ Contract.Assert(ret == nLengthInput, "Expected getting the same length of the original string");
+ return result;
+ }
+ }
+
+ private unsafe char ChangeCase(char c, bool toUpper)
+ {
+ char retVal = '\0';
+
+ // Check for Invariant to avoid A/V in LCMapStringEx
+ uint linguisticCasing = IsInvariantLocale(_textInfoName) ? 0 : LCMAP_LINGUISTIC_CASING;
+
+ Interop.mincore.LCMapStringEx(_sortHandle != IntPtr.Zero ? null : _textInfoName,
+ toUpper ? LCMAP_UPPERCASE | linguisticCasing : LCMAP_LOWERCASE | linguisticCasing,
+ &c,
+ 1,
+ &retVal,
+ 1,
+ null,
+ null,
+ _sortHandle);
+
+ return retVal;
+ }
+
+ // PAL Ends here
+
+ private readonly IntPtr _sortHandle;
+
+ private const uint LCMAP_LINGUISTIC_CASING = 0x01000000;
+ private const uint LCMAP_LOWERCASE = 0x00000100;
+ private const uint LCMAP_UPPERCASE = 0x00000200;
+
+ private static bool IsInvariantLocale(string localeName)
+ {
+ return localeName == "";
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/TextInfo.cs b/src/mscorlib/corefx/System/Globalization/TextInfo.cs
new file mode 100644
index 0000000000..6dadb5856a
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TextInfo.cs
@@ -0,0 +1,457 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This Class defines behaviors specific to a writing system.
+// A writing system is the collection of scripts and
+// orthographic rules required to represent a language as text.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Text;
+using System.Threading;
+
+namespace System.Globalization
+{
+ [Serializable]
+ public partial class TextInfo : ICloneable, IDeserializationCallback
+ {
+ ////--------------------------------------------------------------------//
+ //// Internal Information //
+ ////--------------------------------------------------------------------//
+
+ private enum Tristate : byte
+ {
+ NotInitialized,
+ True,
+ False,
+ }
+
+ ////
+ //// Variables.
+ ////
+
+ [OptionalField(VersionAdded = 2)]
+ private String _listSeparator;
+ [OptionalField(VersionAdded = 2)]
+ private bool _isReadOnly = false;
+
+ //// _cultureName is the name of the creating culture. Note that we consider this authoratative,
+ //// if the culture's textinfo changes when deserializing, then behavior may change.
+ //// (ala Whidbey behavior). This is the only string Arrowhead needs to serialize.
+ //// _cultureData is the data that backs this class.
+ //// _textInfoName is the actual name of the textInfo (from cultureData.STEXTINFO)
+ //// this can be the same as _cultureName on Silverlight since the OS knows
+ //// how to do the sorting. However in the desktop, when we call the sorting dll, it doesn't
+ //// know how to resolve custom locle names to sort ids so we have to have alredy resolved this.
+ ////
+
+ [OptionalField(VersionAdded = 3)]
+ private String _cultureName; // Name of the culture that created this text info
+ [NonSerialized]
+ private CultureData _cultureData; // Data record for the culture that made us, not for this textinfo
+ [NonSerialized]
+ private String _textInfoName; // Name of the text info we're using (ie: _cultureData.STEXTINFO)
+ [NonSerialized]
+ private Tristate _isAsciiCasingSameAsInvariant = Tristate.NotInitialized;
+
+ // Invariant text info
+ internal static TextInfo Invariant
+ {
+ get
+ {
+ if (s_Invariant == null)
+ s_Invariant = new TextInfo(CultureData.Invariant);
+ return s_Invariant;
+ }
+ }
+ internal volatile static TextInfo s_Invariant;
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx) { }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ // Clear these so we can check if we've fixed them yet
+ _cultureData = null;
+ _cultureName = null;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserialized();
+ }
+
+ void IDeserializationCallback.OnDeserialization(Object sender)
+ {
+ OnDeserialized();
+ }
+
+ private void OnDeserialized()
+ {
+ // this method will be called twice because of the support of IDeserializationCallback
+ if (_cultureData == null)
+ {
+ // Get the text info name belonging to that culture
+ _cultureData = CultureInfo.GetCultureInfo(_cultureName).m_cultureData;
+ _textInfoName = _cultureData.STEXTINFO;
+ FinishInitialization(_textInfoName);
+ }
+ }
+
+ //
+ // Internal ordinal comparison functions
+ //
+
+ internal static int GetHashCodeOrdinalIgnoreCase(String s)
+ {
+ // This is the same as an case insensitive hash for Invariant
+ // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules)
+ return (Invariant.GetCaseInsensitiveHashCode(s));
+ }
+
+ // Currently we don't have native functions to do this, so we do it the hard way
+ internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
+ {
+ if (count > source.Length || count < 0 || startIndex < 0 || startIndex >= source.Length || startIndex + count > source.Length)
+ {
+ return -1;
+ }
+
+ return CompareInfo.IndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
+ }
+
+ // Currently we don't have native functions to do this, so we do it the hard way
+ internal static int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
+ {
+ if (count > source.Length || count < 0 || startIndex < 0 || startIndex > source.Length - 1 || (startIndex - count + 1 < 0))
+ {
+ return -1;
+ }
+
+ return CompareInfo.LastIndexOfOrdinal(source, value, startIndex, count, ignoreCase: true);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ ////
+ //// CultureName
+ ////
+ //// The name of the culture associated with the current TextInfo.
+ ////
+ //////////////////////////////////////////////////////////////////////////
+ public string CultureName
+ {
+ get
+ {
+ return _textInfoName;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsReadOnly
+ //
+ // Detect if the object is readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsReadOnly
+ {
+ get { return (_isReadOnly); }
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ ////
+ //// Clone
+ ////
+ //// Is the implementation of IColnable.
+ ////
+ //////////////////////////////////////////////////////////////////////////
+ public virtual Object Clone()
+ {
+ object o = MemberwiseClone();
+ ((TextInfo)o).SetReadOnlyState(false);
+ return (o);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ReadOnly
+ //
+ // Create a cloned readonly instance or return the input one if it is
+ // readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ internal static TextInfo ReadOnly(TextInfo textInfo)
+ {
+ if (textInfo == null) { throw new ArgumentNullException("textInfo"); }
+ Contract.EndContractBlock();
+ if (textInfo.IsReadOnly) { return (textInfo); }
+
+ TextInfo clonedTextInfo = (TextInfo)(textInfo.MemberwiseClone());
+ clonedTextInfo.SetReadOnlyState(true);
+
+ return (clonedTextInfo);
+ }
+
+ private void VerifyWritable()
+ {
+ if (_isReadOnly)
+ {
+ throw new InvalidOperationException(SR.InvalidOperation_ReadOnly);
+ }
+ }
+
+ internal void SetReadOnlyState(bool readOnly)
+ {
+ _isReadOnly = readOnly;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ListSeparator
+ //
+ // Returns the string used to separate items in a list.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ListSeparator
+ {
+ get
+ {
+ if (_listSeparator == null)
+ {
+ _listSeparator = _cultureData.SLIST;
+ }
+ return (_listSeparator);
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value", SR.ArgumentNull_String);
+ }
+ VerifyWritable();
+ _listSeparator = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToLower
+ //
+ // Converts the character or string to lower case. Certain locales
+ // have different casing semantics from the file systems in Win32.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public unsafe virtual char ToLower(char c)
+ {
+ if (IsAscii(c) && IsAsciiCasingSameAsInvariant)
+ {
+ return ToLowerAsciiInvariant(c);
+ }
+ return (ChangeCase(c, toUpper: false));
+ }
+
+ public unsafe virtual String ToLower(String str)
+ {
+ if (str == null) { throw new ArgumentNullException("str"); }
+
+ return ChangeCase(str, toUpper: false);
+ }
+
+ private static Char ToLowerAsciiInvariant(Char c)
+ {
+ if ((uint)(c - 'A') <= (uint)('Z' - 'A'))
+ {
+ c = (Char)(c | 0x20);
+ }
+ return c;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToUpper
+ //
+ // Converts the character or string to upper case. Certain locales
+ // have different casing semantics from the file systems in Win32.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public unsafe virtual char ToUpper(char c)
+ {
+ if (IsAscii(c) && IsAsciiCasingSameAsInvariant)
+ {
+ return ToUpperAsciiInvariant(c);
+ }
+ return (ChangeCase(c, toUpper: true));
+ }
+
+ public unsafe virtual String ToUpper(String str)
+ {
+ if (str == null) { throw new ArgumentNullException("str"); }
+
+ return ChangeCase(str, toUpper: true);
+ }
+
+ private static Char ToUpperAsciiInvariant(Char c)
+ {
+ if ((uint)(c - 'a') <= (uint)('z' - 'a'))
+ {
+ c = (Char)(c & ~0x20);
+ }
+ return c;
+ }
+
+ static private bool IsAscii(Char c)
+ {
+ return c < 0x80;
+ }
+
+ private bool IsAsciiCasingSameAsInvariant
+ {
+ get
+ {
+ if (_isAsciiCasingSameAsInvariant == Tristate.NotInitialized)
+ {
+ _isAsciiCasingSameAsInvariant = CultureInfo.GetCultureInfo(_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ CompareOptions.IgnoreCase) == 0 ? Tristate.True : Tristate.False;
+ }
+ return _isAsciiCasingSameAsInvariant == Tristate.True;
+ }
+ }
+
+ // IsRightToLeft
+ //
+ // Returns true if the dominant direction of text and UI such as the relative position of buttons and scroll bars
+ //
+ public bool IsRightToLeft
+ {
+ get
+ {
+ return _cultureData.IsRightToLeft;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CultureInfo as the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override bool Equals(Object obj)
+ {
+ TextInfo that = obj as TextInfo;
+
+ if (that != null)
+ {
+ return this.CultureName.Equals(that.CultureName);
+ }
+
+ return (false);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A
+ // and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override int GetHashCode()
+ {
+ return (this.CultureName.GetHashCode());
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns a string describing the
+ // TextInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override String ToString()
+ {
+ return ("TextInfo - " + _cultureData.CultureName);
+ }
+
+ //
+ // Get case-insensitive hash code for the specified string.
+ //
+ internal unsafe int GetCaseInsensitiveHashCode(String str)
+ {
+ // Validate inputs
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+
+ // This code assumes that ASCII casing is safe for whatever context is passed in.
+ // this is true today, because we only ever call these methods on Invariant. It would be ideal to refactor
+ // these methods so they were correct by construction and we could only ever use Invariant.
+
+ uint hash = 5381;
+ uint c;
+
+ // Note: We assume that str contains only ASCII characters until
+ // we hit a non-ASCII character to optimize the common case.
+ for (int i = 0; i < str.Length; i++)
+ {
+ c = str[i];
+ if (c >= 0x80)
+ {
+ return GetCaseInsensitiveHashCodeSlow(str);
+ }
+
+ // If we have a lowercase character, ANDing off 0x20
+ // will make it an uppercase character.
+ if ((c - 'a') <= ('z' - 'a'))
+ {
+ c = (uint)((int)c & ~0x20);
+ }
+
+ hash = ((hash << 5) + hash) ^ c;
+ }
+
+ return (int)hash;
+ }
+
+ private unsafe int GetCaseInsensitiveHashCodeSlow(String str)
+ {
+ Contract.Assert(str != null);
+
+ string upper = ToUpper(str);
+
+ uint hash = 5381;
+ uint c;
+
+ for (int i = 0; i < upper.Length; i++)
+ {
+ c = upper[i];
+ hash = ((hash << 5) + hash) ^ c;
+ }
+
+ return (int)hash;
+ }
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs
new file mode 100644
index 0000000000..b42af30c04
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/ThaiBuddhistCalendar.cs
@@ -0,0 +1,233 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ /*=================================ThaiBuddhistCalendar==========================
+ **
+ ** ThaiBuddhistCalendar is based on Gregorian calendar. Its year value has
+ ** an offset to the Gregorain calendar.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0001/01/01 9999/12/31
+ ** Thai 0544/01/01 10542/12/31
+ ============================================================================*/
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ThaiBuddhistCalendar : Calendar
+ {
+ // Initialize our era info.
+ internal static EraInfo[] thaiBuddhistEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1, 1, 1, -543, 544, GregorianCalendar.MaxYear + 543) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ //
+ // The era value for the current era.
+ //
+
+ public const int ThaiBuddhistEra = 1;
+
+ internal GregorianCalendarHelper helper;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ public ThaiBuddhistCalendar()
+ {
+ helper = new GregorianCalendarHelper(this, thaiBuddhistEraInfo);
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.THAI);
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (helper.AddYears(time, years));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time)
+ {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2572;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ 99,
+ helper.MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ return (helper.ToFourDigitYear(year, this.TwoDigitYearMax));
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs b/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs
new file mode 100644
index 0000000000..68a47bcbe6
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/TimeSpanStyles.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ [Flags]
+ public enum TimeSpanStyles
+ {
+ None = 0x00000000,
+ AssumeNegative = 0x00000001,
+ }
+}
diff --git a/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs
new file mode 100644
index 0000000000..1116722fe9
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/UmAlQuraCalendar.cs
@@ -0,0 +1,862 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Globalization
+{
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about UmAlQuraCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1900/04/30 2077/05/13
+ ** UmAlQura 1318/01/01 1500/12/30
+ */
+
+ [Serializable]
+ public partial class UmAlQuraCalendar : Calendar
+ {
+ internal const int MinCalendarYear = 1318;
+ internal const int MaxCalendarYear = 1500;
+
+ internal struct DateMapping
+ {
+ internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay)
+ {
+ HijriMonthsLengthFlags = MonthsLengthFlags;
+ GregorianDate = new DateTime(GYear, GMonth, GDay);
+ }
+ internal int HijriMonthsLengthFlags;
+ internal DateTime GregorianDate;
+ }
+
+ private static readonly DateMapping[] s_hijriYearInfo = InitDateMapping();
+
+ private static DateMapping[] InitDateMapping()
+ {
+ short[] rawData = new short[]
+ {
+ //These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync
+ /* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12
+ 1318*/0x02EA, 1900, 4, 30,/* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900
+ 1319*/0x06E9, 1901, 4, 19,/* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901
+ 1320*/0x0ED2, 1902, 4, 9,/* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902
+ 1321*/0x0EA4, 1903, 3, 30,/* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903
+ 1322*/0x0D4A, 1904, 3, 18,/* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904
+ 1323*/0x0A96, 1905, 3, 7,/* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905
+ 1324*/0x0536, 1906, 2, 24,/* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906
+ 1325*/0x0AB5, 1907, 2, 13,/* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907
+ 1326*/0x0DAA, 1908, 2, 3,/* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908
+ 1327*/0x0BA4, 1909, 1, 23,/* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909
+ 1328*/0x0B49, 1910, 1, 12,/* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910
+ 1329*/0x0A93, 1911, 1, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911
+ 1330*/0x052B, 1911, 12, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911
+ 1331*/0x0A57, 1912, 12, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912
+ 1332*/0x04B6, 1913, 11, 29,/* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913
+ 1333*/0x0AB5, 1914, 11, 18,/* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914
+ 1334*/0x05AA, 1915, 11, 8,/* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915
+ 1335*/0x0D55, 1916, 10, 27,/* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916
+ 1336*/0x0D2A, 1917, 10, 17,/* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917
+ 1337*/0x0A56, 1918, 10, 6,/* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918
+ 1338*/0x04AE, 1919, 9, 25,/* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919
+ 1339*/0x095D, 1920, 9, 13,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920
+ 1340*/0x02EC, 1921, 9, 3,/* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921
+ 1341*/0x06D5, 1922, 8, 23,/* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922
+ 1342*/0x06AA, 1923, 8, 13,/* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923
+ 1343*/0x0555, 1924, 8, 1,/* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924
+ 1344*/0x04AB, 1925, 7, 21,/* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925
+ 1345*/0x095B, 1926, 7, 10,/* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926
+ 1346*/0x02BA, 1927, 6, 30,/* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927
+ 1347*/0x0575, 1928, 6, 18,/* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928
+ 1348*/0x0BB2, 1929, 6, 8,/* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929
+ 1349*/0x0764, 1930, 5, 29,/* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930
+ 1350*/0x0749, 1931, 5, 18,/* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931
+ 1351*/0x0655, 1932, 5, 6,/* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932
+ 1352*/0x02AB, 1933, 4, 25,/* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933
+ 1353*/0x055B, 1934, 4, 14,/* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934
+ 1354*/0x0ADA, 1935, 4, 4,/* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935
+ 1355*/0x06D4, 1936, 3, 24,/* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936
+ 1356*/0x0EC9, 1937, 3, 13,/* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937
+ 1357*/0x0D92, 1938, 3, 3,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938
+ 1358*/0x0D25, 1939, 2, 20,/* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939
+ 1359*/0x0A4D, 1940, 2, 9,/* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940
+ 1360*/0x02AD, 1941, 1, 28,/* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941
+ 1361*/0x056D, 1942, 1, 17,/* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942
+ 1362*/0x0B6A, 1943, 1, 7,/* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943
+ 1363*/0x0B52, 1943, 12, 28,/* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943
+ 1364*/0x0AA5, 1944, 12, 16,/* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944
+ 1365*/0x0A4B, 1945, 12, 5,/* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945
+ 1366*/0x0497, 1946, 11, 24,/* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946
+ 1367*/0x0937, 1947, 11, 13,/* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947
+ 1368*/0x02B6, 1948, 11, 2,/* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948
+ 1369*/0x0575, 1949, 10, 22,/* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949
+ 1370*/0x0D6A, 1950, 10, 12,/* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950
+ 1371*/0x0D52, 1951, 10, 2,/* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951
+ 1372*/0x0A96, 1952, 9, 20,/* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952
+ 1373*/0x092D, 1953, 9, 9,/* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953
+ 1374*/0x025D, 1954, 8, 29,/* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954
+ 1375*/0x04DD, 1955, 8, 18,/* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955
+ 1376*/0x0ADA, 1956, 8, 7,/* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956
+ 1377*/0x05D4, 1957, 7, 28,/* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957
+ 1378*/0x0DA9, 1958, 7, 17,/* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958
+ 1379*/0x0D52, 1959, 7, 7,/* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959
+ 1380*/0x0AAA, 1960, 6, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960
+ 1381*/0x04D6, 1961, 6, 14,/* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961
+ 1382*/0x09B6, 1962, 6, 3,/* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962
+ 1383*/0x0374, 1963, 5, 24,/* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963
+ 1384*/0x0769, 1964, 5, 12,/* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964
+ 1385*/0x0752, 1965, 5, 2,/* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965
+ 1386*/0x06A5, 1966, 4, 21,/* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966
+ 1387*/0x054B, 1967, 4, 10,/* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967
+ 1388*/0x0AAB, 1968, 3, 29,/* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968
+ 1389*/0x055A, 1969, 3, 19,/* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969
+ 1390*/0x0AD5, 1970, 3, 8,/* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970
+ 1391*/0x0DD2, 1971, 2, 26,/* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971
+ 1392*/0x0DA4, 1972, 2, 16,/* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972
+ 1393*/0x0D49, 1973, 2, 4,/* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973
+ 1394*/0x0A95, 1974, 1, 24,/* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974
+ 1395*/0x052D, 1975, 1, 13,/* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975
+ 1396*/0x0A5D, 1976, 1, 2,/* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976
+ 1397*/0x055A, 1976, 12, 22,/* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976
+ 1398*/0x0AD5, 1977, 12, 11,/* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977
+ 1399*/0x06AA, 1978, 12, 1,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978
+ 1400*/0x0695, 1979, 11, 20,/* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979
+ 1401*/0x052B, 1980, 11, 8,/* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980
+ 1402*/0x0A57, 1981, 10, 28,/* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981
+ 1403*/0x04AE, 1982, 10, 18,/* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982
+ 1404*/0x0976, 1983, 10, 7,/* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983
+ 1405*/0x056C, 1984, 9, 26,/* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984
+ 1406*/0x0B55, 1985, 9, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985
+ 1407*/0x0AAA, 1986, 9, 5,/* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986
+ 1408*/0x0A55, 1987, 8, 25,/* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987
+ 1409*/0x04AD, 1988, 8, 13,/* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988
+ 1410*/0x095D, 1989, 8, 2,/* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989
+ 1411*/0x02DA, 1990, 7, 23,/* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990
+ 1412*/0x05D9, 1991, 7, 12,/* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991
+ 1413*/0x0DB2, 1992, 7, 1,/* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992
+ 1414*/0x0BA4, 1993, 6, 21,/* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993
+ 1415*/0x0B4A, 1994, 6, 10,/* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994
+ 1416*/0x0A55, 1995, 5, 30,/* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995
+ 1417*/0x02B5, 1996, 5, 18,/* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996
+ 1418*/0x0575, 1997, 5, 7,/* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997
+ 1419*/0x0B6A, 1998, 4, 27,/* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998
+ 1420*/0x0BD2, 1999, 4, 17,/* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999
+ 1421*/0x0BC4, 2000, 4, 6,/* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000
+ 1422*/0x0B89, 2001, 3, 26,/* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001
+ 1423*/0x0A95, 2002, 3, 15,/* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002
+ 1424*/0x052D, 2003, 3, 4,/* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003
+ 1425*/0x05AD, 2004, 2, 21,/* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004
+ 1426*/0x0B6A, 2005, 2, 10,/* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005
+ 1427*/0x06D4, 2006, 1, 31,/* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006
+ 1428*/0x0DC9, 2007, 1, 20,/* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007
+ 1429*/0x0D92, 2008, 1, 10,/* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008
+ 1430*/0x0AA6, 2008, 12, 29,/* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008
+ 1431*/0x0956, 2009, 12, 18,/* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009
+ 1432*/0x02AE, 2010, 12, 7,/* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010
+ 1433*/0x056D, 2011, 11, 26,/* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011
+ 1434*/0x036A, 2012, 11, 15,/* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012
+ 1435*/0x0B55, 2013, 11, 4,/* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013
+ 1436*/0x0AAA, 2014, 10, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014
+ 1437*/0x094D, 2015, 10, 14,/* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015
+ 1438*/0x049D, 2016, 10, 2,/* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016
+ 1439*/0x095D, 2017, 9, 21,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017
+ 1440*/0x02BA, 2018, 9, 11,/* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018
+ 1441*/0x05B5, 2019, 8, 31,/* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019
+ 1442*/0x05AA, 2020, 8, 20,/* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020
+ 1443*/0x0D55, 2021, 8, 9,/* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021
+ 1444*/0x0A9A, 2022, 7, 30,/* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022
+ 1445*/0x092E, 2023, 7, 19,/* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023
+ 1446*/0x026E, 2024, 7, 7,/* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024
+ 1447*/0x055D, 2025, 6, 26,/* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025
+ 1448*/0x0ADA, 2026, 6, 16,/* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026
+ 1449*/0x06D4, 2027, 6, 6,/* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027
+ 1450*/0x06A5, 2028, 5, 25,/* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028
+ 1451*/0x054B, 2029, 5, 14,/* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029
+ 1452*/0x0A97, 2030, 5, 3,/* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030
+ 1453*/0x054E, 2031, 4, 23,/* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031
+ 1454*/0x0AAE, 2032, 4, 11,/* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032
+ 1455*/0x05AC, 2033, 4, 1,/* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033
+ 1456*/0x0BA9, 2034, 3, 21,/* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034
+ 1457*/0x0D92, 2035, 3, 11,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035
+ 1458*/0x0B25, 2036, 2, 28,/* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036
+ 1459*/0x064B, 2037, 2, 16,/* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037
+ 1460*/0x0CAB, 2038, 2, 5,/* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038
+ 1461*/0x055A, 2039, 1, 26,/* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039
+ 1462*/0x0B55, 2040, 1, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040
+ 1463*/0x06D2, 2041, 1, 4,/* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041
+ 1464*/0x0EA5, 2041, 12, 24,/* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041
+ 1465*/0x0E4A, 2042, 12, 14,/* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042
+ 1466*/0x0A95, 2043, 12, 3,/* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043
+ 1467*/0x052D, 2044, 11, 21,/* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044
+ 1468*/0x0AAD, 2045, 11, 10,/* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045
+ 1469*/0x036C, 2046, 10, 31,/* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046
+ 1470*/0x0759, 2047, 10, 20,/* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047
+ 1471*/0x06D2, 2048, 10, 9,/* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048
+ 1472*/0x0695, 2049, 9, 28,/* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049
+ 1473*/0x052D, 2050, 9, 17,/* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050
+ 1474*/0x0A5B, 2051, 9, 6,/* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051
+ 1475*/0x04BA, 2052, 8, 26,/* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052
+ 1476*/0x09BA, 2053, 8, 15,/* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053
+ 1477*/0x03B4, 2054, 8, 5,/* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054
+ 1478*/0x0B69, 2055, 7, 25,/* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055
+ 1479*/0x0B52, 2056, 7, 14,/* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056
+ 1480*/0x0AA6, 2057, 7, 3,/* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057
+ 1481*/0x04B6, 2058, 6, 22,/* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058
+ 1482*/0x096D, 2059, 6, 11,/* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059
+ 1483*/0x02EC, 2060, 5, 31,/* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060
+ 1484*/0x06D9, 2061, 5, 20,/* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061
+ 1485*/0x0EB2, 2062, 5, 10,/* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062
+ 1486*/0x0D54, 2063, 4, 30,/* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063
+ 1487*/0x0D2A, 2064, 4, 18,/* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064
+ 1488*/0x0A56, 2065, 4, 7,/* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065
+ 1489*/0x04AE, 2066, 3, 27,/* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066
+ 1490*/0x096D, 2067, 3, 16,/* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067
+ 1491*/0x0D6A, 2068, 3, 5,/* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068
+ 1492*/0x0B54, 2069, 2, 23,/* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069
+ 1493*/0x0B29, 2070, 2, 12,/* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070
+ 1494*/0x0A93, 2071, 2, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071
+ 1495*/0x052B, 2072, 1, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072
+ 1496*/0x0A57, 2073, 1, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073
+ 1497*/0x0536, 2073, 12, 30,/* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073
+ 1498*/0x0AB5, 2074, 12, 19,/* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074
+ 1499*/0x06AA, 2075, 12, 9,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075
+ 1500*/0x0E93, 2076, 11, 27,/* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076
+ 1501*/ 0, 2077, 11, 17,/* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077
+ */ };
+ // Direct inline initialization of DateMapping array would produce a lot of code bloat.
+
+ // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code.
+ // So we start with raw data stored in primitive type array, and initialize the DateMapping out of it
+
+ DateMapping[] mapping = new DateMapping[rawData.Length / 4];
+ for (int i = 0; i < mapping.Length; i++)
+ mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3]);
+ return mapping;
+ }
+
+ public const int UmAlQuraEra = 1;
+
+ internal const int DateCycle = 30;
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+
+ // This is the minimal Gregorian date that we support in the UmAlQuraCalendar.
+ internal static DateTime minDate = new DateTime(1900, 4, 30);
+ internal static DateTime maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ public UmAlQuraCalendar()
+ {
+ }
+
+ internal override CalendarId BaseCalendarID
+ {
+ get
+ {
+ return (CalendarId.HIJRI);
+ }
+ }
+
+ internal override CalendarId ID
+ {
+ get
+ {
+ return (CalendarId.UMALQURA);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // HijriCalendar has same number of days as UmAlQuraCalendar for any given year
+ // HijriCalendar says year 1317 has 355 days.
+ return 355;
+ }
+ }
+
+ /*==========================ConvertHijriToGregorian==========================
+ ** Purpose: convert Hdate(year,month,day) to Gdate(year,month,day)
+ ** Arguments:
+ ** Input/Ouput: Hijrah date: year:yh, month:mh, day:dh
+ ** Output: Gregorian date: year:yg, month:mg, day:dg , day of week:dayweek
+ ** and returns flag found:1 not found:0
+ =========================ConvertHijriToGregorian============================*/
+ private static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg)
+ {
+ Contract.Assert((HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range.");
+ Contract.Assert(HijriMonth >= 1, "Hijri month is out of range.");
+ Contract.Assert(HijriDay >= 1, "Hijri day is out of range.");
+ int index, b, nDays = HijriDay - 1;
+ DateTime dt;
+
+
+ index = HijriYear - MinCalendarYear;
+ dt = s_hijriYearInfo[index].GregorianDate;
+
+
+ b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
+
+ for (int m = 1; m < HijriMonth; m++)
+ {
+ nDays = nDays + 29 + (b & 1); /* Add the months lengths before mh */
+ b = b >> 1;
+ }
+
+ dt = dt.AddDays(nDays);
+ yg = dt.Year;
+ mg = dt.Month;
+ dg = dt.Day;
+ }
+
+ /*=================================GetAbsoluteDateUmAlQura==========================
+ **Action: Gets the Absolute date for the given UmAlQura date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ private static long GetAbsoluteDateUmAlQura(int year, int month, int day)
+ {
+ //Caller should check the validaty of year, month and day.
+
+ int yg = 0, mg = 0, dg = 0;
+ ConvertHijriToGregorian(year, month, day, ref yg, ref mg, ref dg);
+ return GregorianCalendar.GetAbsoluteDate(yg, mg, dg);
+ }
+
+ internal static void CheckTicksRange(long ticks)
+ {
+ if (ticks < minDate.Ticks || ticks > maxDate.Ticks)
+ {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ SR.ArgumentOutOfRange_CalendarRange,
+ minDate,
+ maxDate));
+ }
+ }
+
+ internal static void CheckEraRange(int era)
+ {
+ if (era != CurrentEra && era != UmAlQuraEra)
+ {
+ throw new ArgumentOutOfRangeException("era", SR.ArgumentOutOfRange_InvalidEraValue);
+ }
+ }
+
+ internal static void CheckYearRange(int year, int era)
+ {
+ CheckEraRange(era);
+ if (year < MinCalendarYear || year > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ }
+
+ internal static void CheckYearMonthRange(int year, int month, int era)
+ {
+ CheckYearRange(year, era);
+ if (month < 1 || month > 12)
+ {
+ throw new ArgumentOutOfRangeException("month", SR.ArgumentOutOfRange_Month);
+ }
+ }
+
+ /*========================ConvertGregorianToHijri============================
+ ** Purpose: convert DateTime to Hdate(year,month,day)
+ ** Arguments:
+ ** Input: DateTime
+ ** Output: Hijrah date: year:yh, month:mh, day:dh
+ ============================================================================*/
+ private static void ConvertGregorianToHijri(DateTime time, ref int HijriYear, ref int HijriMonth, ref int HijriDay)
+ {
+ int index, b, DaysPerThisMonth;
+ double nDays;
+ TimeSpan ts;
+ int yh1 = 0, mh1 = 0, dh1 = 0;
+
+ Contract.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range.");
+
+ // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo.
+ // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index.
+
+ index = (int)((time.Ticks - minDate.Ticks) / Calendar.TicksPerDay) / 355;
+ do
+ {
+ } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); //while greater
+
+ if (time.CompareTo(s_hijriYearInfo[index].GregorianDate) != 0)
+ {
+ index--;
+ }
+
+ ts = time.Subtract(s_hijriYearInfo[index].GregorianDate);
+ yh1 = index + MinCalendarYear;
+
+ mh1 = 1;
+ dh1 = 1;
+ nDays = ts.TotalDays;
+ b = s_hijriYearInfo[index].HijriMonthsLengthFlags;
+ DaysPerThisMonth = 29 + (b & 1);
+
+ while (nDays >= DaysPerThisMonth)
+ {
+ nDays -= DaysPerThisMonth;
+ b = b >> 1;
+ DaysPerThisMonth = 29 + (b & 1);
+ mh1++;
+ }
+ dh1 += (int)nDays;
+
+ HijriDay = dh1;
+ HijriMonth = mh1;
+ HijriYear = yh1;
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ **Notes:
+ ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
+ ** Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura year.
+ ** In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYear + 1).
+ ** From here, we can get the correct UmAlQura year.
+ ============================================================================*/
+
+ internal virtual int GetDatePart(DateTime time, int part)
+ {
+ int UmAlQuraYear = 0; // UmAlQura year
+ int UmAlQuraMonth = 0; // UmAlQura month
+ int UmAlQuraDay = 0; // UmAlQura day
+ long ticks = time.Ticks;
+ CheckTicksRange(ticks);
+
+ ConvertGregorianToHijri(time, ref UmAlQuraYear, ref UmAlQuraMonth, ref UmAlQuraDay);
+
+ if (part == DatePartYear)
+ return (UmAlQuraYear);
+
+ if (part == DatePartMonth)
+ return (UmAlQuraMonth);
+
+ if (part == DatePartDay)
+ return (UmAlQuraDay);
+
+ if (part == DatePartDayOfYear)
+ return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1);
+
+ // Incorrect part value.
+ throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in UmAlQura calendar.
+ int y = GetDatePart(time, DatePartYear);
+ int m = GetDatePart(time, DatePartMonth);
+ int d = GetDatePart(time, DatePartDay);
+ int i = m - 1 + months;
+
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+
+ if (d > 29)
+ {
+ int days = GetDaysInMonth(y, m);
+ if (d > days)
+ {
+ d = days;
+ }
+ }
+ CheckYearRange(y, UmAlQuraEra);
+ DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 354 or 355.
+ //
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time, DatePartDayOfYear));
+ }
+
+ /*
+ internal bool CouldBeLeapYear(int year)
+ {
+ return ((((year * 11) + 14) % 30) < 11);
+ }
+ */
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+
+ public override int GetDaysInMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+
+ if ((s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags & (1 << month - 1)) == 0)
+ return 29;
+ else
+ return 30;
+ }
+
+ internal static int RealGetDaysInYear(int year)
+ {
+ int days = 0, b;
+
+ Contract.Assert((year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range.");
+
+ b = s_hijriYearInfo[year - MinCalendarYear].HijriMonthsLengthFlags;
+
+ for (int m = 1; m <= 12; m++)
+ {
+ days = days + 29 + (b & 1); /* Add the months lengths before mh */
+ b = b >> 1;
+ }
+ Contract.Assert((days == 354) || (days == 355), "Hijri year has to be 354 or 355 days.");
+ return days;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (RealGetDaysInYear(year));
+ }
+
+ // Returns the era for the specified DateTime value.
+
+
+ public override int GetEra(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return (UmAlQuraEra);
+ }
+
+
+
+ public override int[] Eras
+ {
+ get
+ {
+ return (new int[] { UmAlQuraEra });
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between MinCalendarYear and MaxCalendarYear.
+ //
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ if (day >= 1 && day <= 29)
+ {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ if (RealGetDaysInYear(year) == 355)
+ return true;
+ else
+ return false;
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ if (day >= 1 && day <= 29)
+ {
+ CheckYearMonthRange(year, month, era);
+ goto DayInRang;
+ }
+
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+
+ if (day < 1 || day > daysInMonth)
+ {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Day,
+ daysInMonth,
+ month));
+ }
+ DayInRang:
+ long lDate = GetAbsoluteDateUmAlQura(year, month, day);
+
+ if (lDate >= 0)
+ {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451;
+
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1)
+ {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear))
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax to 99.
+ twoDigitYearMax = value;
+ }
+ }
+
+
+
+ public override int ToFourDigitYear(int year)
+ {
+ if (year < 0)
+ {
+ throw new ArgumentOutOfRangeException("year",
+ SR.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100)
+ {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if ((year < MinCalendarYear) || (year > MaxCalendarYear))
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ SR.ArgumentOutOfRange_Range,
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs b/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs
new file mode 100644
index 0000000000..1c5e6bca56
--- /dev/null
+++ b/src/mscorlib/corefx/System/Globalization/UnicodeCategory.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ [Serializable]
+ public enum UnicodeCategory
+ {
+ UppercaseLetter = 0,
+
+ LowercaseLetter = 1,
+
+ TitlecaseLetter = 2,
+
+ ModifierLetter = 3,
+
+ OtherLetter = 4,
+
+ NonSpacingMark = 5,
+
+ SpacingCombiningMark = 6,
+
+ EnclosingMark = 7,
+
+ DecimalDigitNumber = 8,
+
+ LetterNumber = 9,
+
+ OtherNumber = 10,
+
+ SpaceSeparator = 11,
+
+ LineSeparator = 12,
+
+ ParagraphSeparator = 13,
+
+ Control = 14,
+
+ Format = 15,
+
+ Surrogate = 16,
+
+ PrivateUse = 17,
+
+ ConnectorPunctuation = 18,
+
+ DashPunctuation = 19,
+
+ OpenPunctuation = 20,
+
+ ClosePunctuation = 21,
+
+ InitialQuotePunctuation = 22,
+
+ FinalQuotePunctuation = 23,
+
+ OtherPunctuation = 24,
+
+ MathSymbol = 25,
+
+ CurrencySymbol = 26,
+
+ ModifierSymbol = 27,
+
+ OtherSymbol = 28,
+
+ OtherNotAssigned = 29,
+ }
+}
diff --git a/src/mscorlib/facade/TypeForwards.cs b/src/mscorlib/facade/TypeForwards.cs
new file mode 100644
index 0000000000..ba78711eef
--- /dev/null
+++ b/src/mscorlib/facade/TypeForwards.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+#if WINDOWS_TYPEFORWARDS
+[assembly: TypeForwardedTo(typeof(System.Threading.WinRTSynchronizationContextFactoryBase))]
+[assembly: TypeForwardedTo(typeof(System.Resources.WindowsRuntimeResourceManagerBase))]
+[assembly: TypeForwardedTo(typeof(System.Resources.PRIExceptionInfo))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeImportAttribute))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.InteropServices.WindowsRuntime.IRestrictedErrorInfo))]
+[assembly: TypeForwardedTo(typeof(System.StubHelpers.EventArgsMarshaler))]
+[assembly: TypeForwardedTo(typeof(System.StubHelpers.InterfaceMarshaler))]
+#endif
+
+[assembly: TypeForwardedTo(typeof(System.Diagnostics.Tracing.FrameworkEventSource))]
+[assembly: TypeForwardedTo(typeof(System.Globalization.CultureData))]
+[assembly: TypeForwardedTo(typeof(System.Globalization.CalendarData))]
+[assembly: TypeForwardedTo(typeof(System.IO.BufferedStream))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.JitHelpers))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.ObjectHandleOnStack))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.PinningHelper))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.StackCrawlMarkHandle))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.StringHandleOnStack))]
+[assembly: TypeForwardedTo(typeof(System.Runtime.CompilerServices.FriendAccessAllowedAttribute))]
+[assembly: TypeForwardedTo(typeof(System.StubHelpers.StubHelpers))]
+[assembly: TypeForwardedTo(typeof(System.StubHelpers.CleanupWorkList))]
+[assembly: TypeForwardedTo(typeof(System.StubHelpers.CleanupWorkListElement))]
+[assembly: TypeForwardedTo(typeof(System.Threading.StackCrawlMark))]
+[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.AsyncCausalityStatus))]
+[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalityRelation))]
+[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalitySynchronousWork))]
+[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.AsyncCausalityTracer))]
+[assembly: TypeForwardedTo(typeof(System.Threading.Tasks.CausalityTraceLevel))]
+
+
diff --git a/src/mscorlib/facade/mscorlib.csproj b/src/mscorlib/facade/mscorlib.csproj
new file mode 100644
index 0000000000..c3a165d3d5
--- /dev/null
+++ b/src/mscorlib/facade/mscorlib.csproj
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+
+ <PropertyGroup>
+ <AssemblyName>mscorlib</AssemblyName>
+ <ProjectGuid>{263342A6-FC48-4CFC-B16A-2AF964D3536C}</ProjectGuid>
+ <ClsCompliant>true</ClsCompliant>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ <IsPartialFacadeAssembly>true</IsPartialFacadeAssembly>
+ <OutputType>Library</OutputType>
+ <ExcludeMscorlibFacade>true</ExcludeMscorlibFacade>
+
+ <!-- This prevents the default MsBuild targets from referencing System.Core.dll -->
+ <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
+ <!-- These prevent the default MsBuild targets from referencing System.dll and mscorlib.dll -->
+ <NoStdLib>true</NoStdLib>
+ <NoCompilerStandardLib>true</NoCompilerStandardLib>
+
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <AvailablePlatforms>amd64,x86,arm,arm-softfp,arm64</AvailablePlatforms>
+ <Configuration Condition=" '$(Configuration)' == '' ">$(BuildType)</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">$(BuildArch)</Platform>
+ <!-- The CLR properties use amd64 as their platform string, we want to keep in sync with those, so set Platform appropriately,
+ though still use the 'x64' output path (see use of BuildArch below) -->
+ <Platform Condition=" '$(Platform)' == 'x64' ">amd64</Platform>
+ <Platform Condition=" '$(Platform)' == 'arm-softfp' ">arm</Platform>
+
+ <!-- We want to exclude the transitive closure of the packages pulled in via project.json as that introduces ambiguity -->
+ <OmitTransitiveCompileReferences>true</OmitTransitiveCompileReferences>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.3</NuGetTargetMoniker>
+ </PropertyGroup>
+
+ <!-- Default configurations to help VS understand the options -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50aot_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcore50aot_Release|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Debug|AnyCPU'" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'net462_Release|AnyCPU'" />
+
+ <!-- Roslyn does not support writing PDBs on Unix -->
+ <PropertyGroup Condition="'$(OsEnvironment)' == 'Unix'">
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>none</DebugType>
+ </PropertyGroup>
+
+ <!-- Some of the type forwards should only be build when targeting Windows. -->
+ <PropertyGroup>
+ <DefineConstants Condition="'$(TargetsWindows)'=='true'">$(DefineConstants);WINDOWS_TYPEFORWARDS</DefineConstants>
+ </PropertyGroup>
+
+ <!-- Output paths -->
+ <PropertyGroup>
+ <BaseIntermediateOutputPath>$(RootBinDir)\obj</BaseIntermediateOutputPath>
+ <!-- Note the trailing '\\' - they are needed so that genfacade does not fail due to an invalid path
+ In particular, the facadepath is sent in quotes.
+ And the IntermediateOutputPath is required to end in a '\' in the coreclr repo. This means that the
+ facadepath ends up being sent as 'mypath\"' and that trips the Path normalization.
+ Introducing a second '\' tricks the normalization logic to treat this '\\"' as '\"' and not complain. -->
+ <IntermediateOutputPath>$(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)\facade\\</IntermediateOutputPath>
+ <OutputPath>$(BinDir)\facade</OutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\System.Private.CoreLib.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Compile Include="TypeForwards.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <None Include="project.json" />
+ </ItemGroup>
+
+ <PropertyGroup>
+ <StrongNameSig>Silverlight</StrongNameSig>
+ </PropertyGroup>
+
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+
+ <PropertyGroup>
+ <!-- Overwrite the key that we are going to use for signing -->
+ <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)..\Tools\Signing\mscorlib.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+
+ <!-- the signing marker file is incorrectly named mscorlib.dll.requires_signing -->
+ <Target Name="RenameSigningMarker" AfterTargets="WriteSigningRequired" Condition="Exists('$(TargetPath).requires_signing')">
+ <Move SourceFiles="$(TargetPath).requires_signing" DestinationFiles="$(OutputPath)\System.Private.CoreLib.dll.requires_signing" />
+ </Target>
+
+ <ItemGroup>
+ <SeedTypePreference Include="System.Console">
+ <Assembly>System.Console</Assembly>
+ </SeedTypePreference>
+ </ItemGroup>
+
+</Project>
diff --git a/src/mscorlib/facade/project.json b/src/mscorlib/facade/project.json
new file mode 100644
index 0000000000..485086eca5
--- /dev/null
+++ b/src/mscorlib/facade/project.json
@@ -0,0 +1,14 @@
+{
+ "dependencies": {
+ "System.Console": "4.0.0",
+ "System.Security.Cryptography.Primitives": "4.0.0",
+ "System.Security.Claims": "4.0.0",
+ },
+ "frameworks": {
+ "netstandard1.3": {
+ "imports": [
+ "dotnet5.4"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
new file mode 100644
index 0000000000..67db0a0522
--- /dev/null
+++ b/src/mscorlib/model.xml
@@ -0,0 +1,12084 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ThinModel>
+ <Assembly Status="ApiRoot" Name="System.Private.CoreLib">
+ <Type Name="System.AccessViolationException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Field" Name="_accessType" />
+ <Member MemberType="Field" Name="_ip" />
+ <Member MemberType="Field" Name="_target" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke" />
+ </Type>
+ <Type Name="System.Action&lt;T&gt;">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(T,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(T)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3,T4&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3,T4,T5&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3,T4,T5,T6&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3,T4,T5,T6,T7&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,T7,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6,T7)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Action&lt;T1,T2,T3,T4,T5,T6,T7,T8&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,T7,T8,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6,T7,T8)" />
+ </Type>
+ <Type Name="System.Activator">
+ <Member Name="CreateComInstanceFrom(System.String,System.String)" />
+ <Member Name="CreateComInstanceFrom(System.String,System.String,System.Byte[],System.Configuration.Assemblies.AssemblyHashAlgorithm)" />
+ <Member Name="CreateInstance(System.AppDomain,System.String,System.String)" />
+ <Member Name="CreateInstance(System.AppDomain,System.String,System.String,System.Boolean,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateInstance(System.String,System.String)" />
+ <Member Name="CreateInstance(System.String,System.String,System.Boolean,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateInstance(System.String,System.String,System.Object[])" />
+ <Member Name="CreateInstance(System.Type)" />
+ <Member Name="CreateInstance(System.Type,System.Boolean)" />
+ <Member Name="CreateInstance(System.Type,System.Object[])" />
+ <Member Name="CreateInstance(System.Type,System.Object[],System.Object[])" />
+ <Member Name="CreateInstance(System.Type,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="CreateInstance(System.Type,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateInstance&lt;T&gt;" />
+ <Member Name="CreateInstanceFrom(System.AppDomain,System.String,System.String)" />
+ <Member Name="CreateInstanceFrom(System.AppDomain,System.String,System.String,System.Boolean,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateInstanceFrom(System.String,System.String)" />
+ <Member Name="CreateInstanceFrom(System.String,System.String,System.Boolean,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateInstanceFrom(System.String,System.String,System.Object[])" />
+ <Member Status="ImplRoot" Name="System.Runtime.InteropServices._Activator.GetIDsOfNames(System.Guid@,System.IntPtr,System.UInt32,System.UInt32,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="System.Runtime.InteropServices._Activator.GetTypeInfo(System.UInt32,System.UInt32,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="System.Runtime.InteropServices._Activator.GetTypeInfoCount(System.UInt32@)" />
+ <Member Status="ImplRoot" Name="System.Runtime.InteropServices._Activator.Invoke(System.UInt32,System.Guid@,System.UInt32,System.Int16,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ </Type>
+ <Type Name="System.AppDomain">
+ <Member Name="get_CurrentDomain" />
+ <Member Status="ImplRoot" Name="get_MonitoringIsEnabled" />
+ <Member Status="ImplRoot" Name="set_MonitoringIsEnabled(System.Boolean)" />
+ <Member Status="ImplRoot" Name="get_MonitoringTotalProcessorTime" />
+ <Member Status="ImplRoot" Name="get_MonitoringTotalAllocatedMemorySize" />
+ <Member Status="ImplRoot" Name="get_MonitoringSurvivedMemorySize" />
+ <Member Status="ImplRoot" Name="get_MonitoringSurvivedProcessMemorySize" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MonitoringIsEnabled" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MonitoringTotalProcessorTime" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MonitoringTotalAllocatedMemorySize" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MonitoringSurvivedMemorySize" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MonitoringSurvivedProcessMemorySize" />
+ <Member MemberType="Property" Name="IsFullyTrusted" />
+ <Member Name="GetData(System.String)" />
+ <Member Name="ToString" />
+ <Member Status="ImplRoot" Name="SetupDomainSecurity(System.Security.Policy.Evidence,System.IntPtr,System.Boolean)" />
+ <Member Status="ImplRoot" Name="SetupDomainSecurity(System.AppDomainHandle,System.Runtime.CompilerServices.ObjectHandleOnStack,System.IntPtr,System.Boolean)" />
+ <Member Status="ImplRoot" MemberType="Event" Name="AssemblyResolve" />
+ <Member Status="ImplRoot" Name="OnAssemblyResolveEvent(System.Reflection.RuntimeAssembly,System.String)" />
+ <Member Status="ImplRoot" MemberType="Event" Name="AssemblyLoad" />
+ <Member Status="ImplRoot" MemberType="Event" Name="ResourceResolve" />
+ <Member Status="ImplRoot" MemberType="Event" Name="TypeResolve" />
+ <Member Status="ImplRoot" MemberType="Event" Name="DomainUnload" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_applicationTrust" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_FusionStore" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_HasSetPolicy" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_LocalStore" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_processExit" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_SecurityIdentity" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_unhandledException" />
+ <Member Status="ImplRoot" Name="OnAssemblyLoadEvent(System.Reflection.RuntimeAssembly)" />
+ <Member Status="ImplRoot" Name="OnResourceResolveEvent(System.Reflection.RuntimeAssembly,System.String)" />
+ <Member Status="ImplRoot" Name="OnTypeResolveEvent(System.Reflection.RuntimeAssembly,System.String)" />
+ <Member Status="ImplRoot" Name="PrepareDataForSetup(System.String,System.AppDomainSetup,System.Security.Policy.Evidence,System.Security.Policy.Evidence,System.IntPtr,System.String,System.String[],System.String[])" />
+ <Member Status="ImplRoot" Name="Setup(System.Object)" />
+ <Member Status="ImplRoot" Name="SetupDomain(System.Boolean,System.String,System.String,System.String[],System.String[])" />
+ <Member Status="ImplRoot" Name="nCreateContext" />
+ <Member Name="OnDesignerNamespaceResolveEvent(System.String)" Condition="FEATURE_COMINTEROP" />
+ <Member MemberType="Property" Name="BaseDirectory" />
+ <Member Name="get_BaseDirectory" />
+ </Type>
+ <Type Name="System.AppDomainManager">
+ <Member Name="#ctor" />
+ <Member Name="InitializeNewDomain(System.AppDomainSetup)" />
+ <Member Name="CheckSecuritySettings(System.Security.SecurityState)" />
+ </Type>
+ <Type Name="System.AppDomainUnloadedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.AppContext">
+ <Member Name="get_BaseDirectory" />
+ <Member MemberType="Property" Name="BaseDirectory" />
+ <Member Name="get_TargetFrameworkName" />
+ <Member MemberType="Property" Name="TargetFrameworkName" />
+ <Member Name="DefineSwitchDefault(System.String,System.Boolean)" />
+ <Member Name="SetSwitch(System.String,System.Boolean)" />
+ <Member Name="TryGetSwitch(System.String,System.Boolean@)" />
+ <Member Name="GetData(System.String)" />
+ </Type>
+ <Type Name="System.ApplicationException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ApplicationId">
+ <Member Name="#ctor(System.Byte[],System.String,System.Version,System.String,System.String)" />
+ <Member Name="Copy" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Culture" />
+ <Member Name="get_Name" />
+ <Member Name="get_ProcessorArchitecture" />
+ <Member Name="get_PublicKeyToken" />
+ <Member Name="get_Version" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Culture" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ProcessorArchitecture" />
+ <Member MemberType="Property" Name="PublicKeyToken" />
+ <Member MemberType="Property" Name="Version" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.ArrayList">
+ <Member Name="ReadOnly(System.Collections.IList)" />
+ </Type>
+ <Type Name="System.ArgumentException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_ParamName" />
+ <Member MemberType="Property" Name="ParamName" />
+ </Type>
+ <Type Name="System.ArgumentNullException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ArgumentOutOfRangeException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Object,System.String)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_ActualValue" />
+ <Member MemberType="Property" Name="ActualValue" />
+ </Type>
+ <Type Name="System.ArithmeticException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Array">
+ <Member Name="AsReadOnly&lt;T&gt;(T[])" />
+ <Member Name="BinarySearch(System.Array,System.Int32,System.Int32,System.Object)" />
+ <Member Name="BinarySearch(System.Array,System.Int32,System.Int32,System.Object,System.Collections.IComparer)" />
+ <Member Name="BinarySearch(System.Array,System.Object)" />
+ <Member Name="BinarySearch(System.Array,System.Object,System.Collections.IComparer)" />
+ <Member Name="BinarySearch&lt;T&gt;(T[],System.Int32,System.Int32,T)" />
+ <Member Name="BinarySearch&lt;T&gt;(T[],System.Int32,System.Int32,T,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="BinarySearch&lt;T&gt;(T[],T)" />
+ <Member Name="BinarySearch&lt;T&gt;(T[],T,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="Clear(System.Array,System.Int32,System.Int32)" />
+ <Member Name="Clone" />
+ <Member Name="ConstrainedCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)" />
+ <Member Name="ConvertAll&lt;TInput,TOutput&gt;(TInput[],System.Converter&lt;TInput,TOutput&gt;)" />
+ <Member Name="Copy(System.Array,System.Array,System.Int32)" />
+ <Member Name="Copy(System.Array,System.Array,System.Int64)" />
+ <Member Name="Copy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)" />
+ <Member Name="Copy(System.Array,System.Int64,System.Array,System.Int64,System.Int64)" />
+ <Member Name="CopyTo(System.Array,System.Int32)" />
+ <Member Name="CopyTo(System.Array,System.Int64)" />
+ <Member Name="CreateInstance(System.Type,System.Int32)" />
+ <Member Name="CreateInstance(System.Type,System.Int32,System.Int32)" />
+ <Member Name="CreateInstance(System.Type,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="CreateInstance(System.Type,System.Int32[])" />
+ <Member Name="CreateInstance(System.Type,System.Int32[],System.Int32[])" />
+ <Member Name="CreateInstance(System.Type,System.Int64[])" />
+ <Member Name="Empty&lt;T&gt;" />
+ <Member Name="Exists&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="Find&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="FindAll&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex&lt;T&gt;(T[],System.Int32,System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex&lt;T&gt;(T[],System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLast&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex&lt;T&gt;(T[],System.Int32,System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex&lt;T&gt;(T[],System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member Name="ForEach&lt;T&gt;(T[],System.Action&lt;T&gt;)" />
+ <Member Name="get_IsFixedSize" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_IsSynchronized" />
+ <Member Name="get_Length" />
+ <Member Name="get_LongLength" />
+ <Member Name="get_Rank" />
+ <Member Name="get_SyncRoot" />
+ <Member Name="GetEnumerator" />
+ <Member Name="GetLength(System.Int32)" />
+ <Member Name="GetLongLength(System.Int32)" />
+ <Member Name="GetLowerBound(System.Int32)" />
+ <Member Name="GetUpperBound(System.Int32)" />
+ <Member Name="GetValue(System.Int32)" />
+ <Member Name="GetValue(System.Int32,System.Int32)" />
+ <Member Name="GetValue(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetValue(System.Int32[])" />
+ <Member Name="GetValue(System.Int64)" />
+ <Member Name="GetValue(System.Int64,System.Int64)" />
+ <Member Name="GetValue(System.Int64,System.Int64,System.Int64)" />
+ <Member Name="GetValue(System.Int64[])" />
+ <Member Name="IndexOf(System.Array,System.Object)" />
+ <Member Name="IndexOf(System.Array,System.Object,System.Int32)" />
+ <Member Name="IndexOf(System.Array,System.Object,System.Int32,System.Int32)" />
+ <Member Name="IndexOf&lt;T&gt;(T[],T)" />
+ <Member Name="IndexOf&lt;T&gt;(T[],T,System.Int32)" />
+ <Member Name="IndexOf&lt;T&gt;(T[],T,System.Int32,System.Int32)" />
+ <Member Name="Initialize" />
+ <Member Name="LastIndexOf(System.Array,System.Object)" />
+ <Member Name="LastIndexOf(System.Array,System.Object,System.Int32)" />
+ <Member Name="LastIndexOf(System.Array,System.Object,System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf&lt;T&gt;(T[],T)" />
+ <Member Name="LastIndexOf&lt;T&gt;(T[],T,System.Int32)" />
+ <Member Name="LastIndexOf&lt;T&gt;(T[],T,System.Int32,System.Int32)" />
+ <Member Name="Resize&lt;T&gt;(T[]@,System.Int32)" />
+ <Member Name="Reverse(System.Array)" />
+ <Member Name="Reverse(System.Array,System.Int32,System.Int32)" />
+ <Member Name="SetValue(System.Object,System.Int32)" />
+ <Member Name="SetValue(System.Object,System.Int32,System.Int32)" />
+ <Member Name="SetValue(System.Object,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="SetValue(System.Object,System.Int32[])" />
+ <Member Name="SetValue(System.Object,System.Int64)" />
+ <Member Name="SetValue(System.Object,System.Int64,System.Int64)" />
+ <Member Name="SetValue(System.Object,System.Int64,System.Int64,System.Int64)" />
+ <Member Name="SetValue(System.Object,System.Int64[])" />
+ <Member Name="Sort(System.Array)" />
+ <Member Name="Sort(System.Array,System.Array)" />
+ <Member Name="Sort(System.Array,System.Array,System.Collections.IComparer)" />
+ <Member Name="Sort(System.Array,System.Array,System.Int32,System.Int32)" />
+ <Member Name="Sort(System.Array,System.Array,System.Int32,System.Int32,System.Collections.IComparer)" />
+ <Member Name="Sort(System.Array,System.Collections.IComparer)" />
+ <Member Name="Sort(System.Array,System.Int32,System.Int32)" />
+ <Member Name="Sort(System.Array,System.Int32,System.Int32,System.Collections.IComparer)" />
+ <Member Name="Sort&lt;T&gt;(T[])" />
+ <Member Name="Sort&lt;T&gt;(T[],System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="Sort&lt;T&gt;(T[],System.Comparison&lt;T&gt;)" />
+ <Member Name="Sort&lt;T&gt;(T[],System.Int32,System.Int32)" />
+ <Member Name="Sort&lt;T&gt;(T[],System.Int32,System.Int32,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="Sort&lt;TKey,TValue&gt;(TKey[],TValue[])" />
+ <Member Name="Sort&lt;TKey,TValue&gt;(TKey[],TValue[],System.Collections.Generic.IComparer&lt;TKey&gt;)" />
+ <Member Name="Sort&lt;TKey,TValue&gt;(TKey[],TValue[],System.Int32,System.Int32)" />
+ <Member Name="Sort&lt;TKey,TValue&gt;(TKey[],TValue[],System.Int32,System.Int32,System.Collections.Generic.IComparer&lt;TKey&gt;)" />
+ <Member Name="TrueForAll&lt;T&gt;(T[],System.Predicate&lt;T&gt;)" />
+ <Member MemberType="Property" Name="IsFixedSize" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="IsSynchronized" />
+ <Member MemberType="Property" Name="Length" />
+ <Member MemberType="Property" Name="LongLength" />
+ <Member MemberType="Property" Name="Rank" />
+ <Member MemberType="Property" Name="SyncRoot" />
+ <Member Status="ImplRoot" Name="GetDataPtrOffsetInternal" /> <!-- EE -->
+ </Type>
+ <Type Name="System.ArraySegment&lt;T&gt;">
+ <Member Name="#ctor(T[])" />
+ <Member Name="#ctor(T[],System.Int32,System.Int32)" />
+ <Member Name="Equals(System.ArraySegment&lt;T&gt;)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Array" />
+ <Member Name="get_Count" />
+ <Member Name="get_Offset" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.ArraySegment&lt;T&gt;,System.ArraySegment&lt;T&gt;)" />
+ <Member Name="op_Inequality(System.ArraySegment&lt;T&gt;,System.ArraySegment&lt;T&gt;)" />
+ <Member MemberType="Property" Name="Array" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Offset" />
+ </Type>
+ <Type Name="System.ArrayTypeMismatchException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.AssemblyLoadEventHandler">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.AssemblyLoadEventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,System.AssemblyLoadEventArgs)" />
+ </Type>
+ <Type Name="System.AssemblyLoadEventArgs">
+ <Member Name="#ctor(System.Reflection.Assembly)" />
+ <Member Name="get_LoadedAssembly" />
+ <Member MemberType="Property" Name="LoadedAssembly" />
+ </Type>
+ <Type Name="System.AsyncCallback">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.IAsyncResult,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.IAsyncResult)" />
+ </Type>
+ <Type Name="System.Attribute">
+ <Member Name="#ctor" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_TypeId" />
+ <Member Name="GetCustomAttribute(System.Reflection.Assembly,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.Assembly,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttribute(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttribute(System.Reflection.Module,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.Module,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttribute(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ <Member Name="GetHashCode" />
+ <Member Name="IsDefaultAttribute" />
+ <Member Name="IsDefined(System.Reflection.Assembly,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.Assembly,System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Reflection.Module,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.Module,System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ <Member Name="Match(System.Object)" />
+ <Member MemberType="Property" Name="TypeId" />
+ </Type>
+ <Type Name="System.AttributeTargets">
+ <Member MemberType="Field" Name="All" />
+ <Member MemberType="Field" Name="Assembly" />
+ <Member MemberType="Field" Name="Class" />
+ <Member MemberType="Field" Name="Constructor" />
+ <Member MemberType="Field" Name="Delegate" />
+ <Member MemberType="Field" Name="Enum" />
+ <Member MemberType="Field" Name="Event" />
+ <Member MemberType="Field" Name="Field" />
+ <Member MemberType="Field" Name="GenericParameter" />
+ <Member MemberType="Field" Name="Interface" />
+ <Member MemberType="Field" Name="Method" />
+ <Member MemberType="Field" Name="Module" />
+ <Member MemberType="Field" Name="Parameter" />
+ <Member MemberType="Field" Name="Property" />
+ <Member MemberType="Field" Name="ReturnValue" />
+ <Member MemberType="Field" Name="Struct" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.AttributeUsageAttribute">
+ <Member Name="#ctor(System.AttributeTargets)" />
+ <Member Name="get_AllowMultiple" />
+ <Member Name="get_Inherited" />
+ <Member Name="get_ValidOn" />
+ <Member Name="set_AllowMultiple(System.Boolean)" />
+ <Member Name="set_Inherited(System.Boolean)" />
+ <Member MemberType="Property" Name="AllowMultiple" />
+ <Member MemberType="Property" Name="Inherited" />
+ <Member MemberType="Property" Name="ValidOn" />
+ </Type>
+ <Type Name="System.Base64FormattingOptions">
+ <Member MemberType="Field" Name="InsertLineBreaks" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.BitConverter">
+ <Member Name="DoubleToInt64Bits(System.Double)" />
+ <Member Name="Int64BitsToDouble(System.Int64)" />
+ <Member MemberType="Field" Name="IsLittleEndian" />
+ <Member Name="GetBytes(System.Boolean)" />
+ <Member Name="GetBytes(System.Char)" />
+ <Member Name="GetBytes(System.Double)" />
+ <Member Name="GetBytes(System.Single)" />
+ <Member Name="GetBytes(System.Int32)" />
+ <Member Name="GetBytes(System.Int64)" />
+ <Member Name="GetBytes(System.Int16)" />
+ <Member Name="GetBytes(System.UInt32)" />
+ <Member Name="GetBytes(System.UInt64)" />
+ <Member Name="GetBytes(System.UInt16)" />
+ <Member Name="ToBoolean(System.Byte[],System.Int32)" />
+ <Member Name="ToChar(System.Byte[],System.Int32)" />
+ <Member Name="ToDouble(System.Byte[],System.Int32)" />
+ <Member Name="ToInt16(System.Byte[],System.Int32)" />
+ <Member Name="ToInt32(System.Byte[],System.Int32)" />
+ <Member Name="ToInt64(System.Byte[],System.Int32)" />
+ <Member Name="ToSingle(System.Byte[],System.Int32)" />
+ <Member Name="ToString(System.Byte[])" />
+ <Member Name="ToString(System.Byte[],System.Int32)" />
+ <Member Name="ToString(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ToUInt16(System.Byte[],System.Int32)" />
+ <Member Name="ToUInt32(System.Byte[],System.Int32)" />
+ <Member Name="ToUInt64(System.Byte[],System.Int32)" />
+ </Type>
+ <Type Name="System.BadImageFormatException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.String,System.String,System.Int32)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_FileName" />
+ <Member Name="get_FusionLog" />
+ <Member MemberType="Property" Name="FileName" />
+ <Member MemberType="Property" Name="FusionLog" />
+ </Type>
+ <Type Name="System.Boolean">
+ <Member MemberType="Field" Name="FalseString" />
+ <Member MemberType="Field" Name="TrueString" />
+ <Member Name="CompareTo(System.Boolean)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="TryParse(System.String,System.Boolean@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.Buffer">
+ <Member Name="BlockCopy(System.Array,System.Int32,System.Array,System.Int32,System.Int32)" />
+ <Member Name="ByteLength(System.Array)" />
+ <Member Name="GetByte(System.Array,System.Int32)" />
+ <Member Name="SetByte(System.Array,System.Int32,System.Byte)" />
+ <Member Name="MemoryCopy(System.Void*,System.Void*,System.Int64,System.Int64)" />
+ <Member Name="MemoryCopy(System.Void*,System.Void*,System.UInt64,System.UInt64)" />
+ </Type>
+ <Type Name="System.Byte">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Byte)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Byte)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Byte@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Byte@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.CannotUnloadAppDomainException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Char">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Char)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="ConvertFromUtf32(System.Int32)" />
+ <Member Name="ConvertToUtf32(System.Char,System.Char)" />
+ <Member Name="ConvertToUtf32(System.String,System.Int32)" />
+ <Member Name="Equals(System.Char)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetNumericValue(System.Char)" />
+ <Member Name="GetNumericValue(System.String,System.Int32)" />
+ <Member Name="GetTypeCode" />
+ <Member Name="GetUnicodeCategory(System.Char)" />
+ <Member Name="GetUnicodeCategory(System.String,System.Int32)" />
+ <Member Name="IsControl(System.Char)" />
+ <Member Name="IsControl(System.String,System.Int32)" />
+ <Member Name="IsDigit(System.Char)" />
+ <Member Name="IsDigit(System.String,System.Int32)" />
+ <Member Name="IsHighSurrogate(System.Char)" />
+ <Member Name="IsHighSurrogate(System.String,System.Int32)" />
+ <Member Name="IsLetter(System.Char)" />
+ <Member Name="IsLetter(System.String,System.Int32)" />
+ <Member Name="IsLetterOrDigit(System.Char)" />
+ <Member Name="IsLetterOrDigit(System.String,System.Int32)" />
+ <Member Name="IsLower(System.Char)" />
+ <Member Name="IsLower(System.String,System.Int32)" />
+ <Member Name="IsLowSurrogate(System.Char)" />
+ <Member Name="IsLowSurrogate(System.String,System.Int32)" />
+ <Member Name="IsNumber(System.Char)" />
+ <Member Name="IsNumber(System.String,System.Int32)" />
+ <Member Name="IsPunctuation(System.Char)" />
+ <Member Name="IsPunctuation(System.String,System.Int32)" />
+ <Member Name="IsSeparator(System.Char)" />
+ <Member Name="IsSeparator(System.String,System.Int32)" />
+ <Member Name="IsSurrogate(System.Char)" />
+ <Member Name="IsSurrogate(System.String,System.Int32)" />
+ <Member Name="IsSurrogatePair(System.Char,System.Char)" />
+ <Member Name="IsSurrogatePair(System.String,System.Int32)" />
+ <Member Name="IsSymbol(System.Char)" />
+ <Member Name="IsSymbol(System.String,System.Int32)" />
+ <Member Name="IsUpper(System.Char)" />
+ <Member Name="IsUpper(System.String,System.Int32)" />
+ <Member Name="IsWhiteSpace(System.Char)" />
+ <Member Name="IsWhiteSpace(System.String,System.Int32)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="ToLower(System.Char)" />
+ <Member Name="ToLower(System.Char,System.Globalization.CultureInfo)" />
+ <Member Name="ToLowerInvariant(System.Char)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.Char)" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToUpper(System.Char)" />
+ <Member Name="ToUpper(System.Char,System.Globalization.CultureInfo)" />
+ <Member Name="ToUpperInvariant(System.Char)" />
+ <Member Name="TryParse(System.String,System.Char@)" />
+ </Type>
+ <Type Name="System.CharEnumerator">
+ <Member Name="Clone" />
+ <Member Name="Dispose" />
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Current" />
+ <Member Name="System.Collections.IEnumerator.get_Current" />
+ <Member MemberType="Property" Name="System.Collections.IEnumerator.Current" />
+ </Type>
+ <Type Name="System.CLSCompliantAttribute">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_IsCompliant" />
+ <Member MemberType="Property" Name="IsCompliant" />
+ </Type>
+ <Type Name="System.Collections.BitArray">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.Byte[])" />
+ <Member Name="#ctor(System.Boolean[])" />
+ <Member Name="#ctor(System.Int32[])" />
+ <Member Name="#ctor(System.Collections.BitArray)" />
+ <Member Name="Get(System.Int32)" />
+ <Member Name="Set(System.Int32,System.Boolean)" />
+ <Member Name="SetAll(System.Boolean)" />
+ <Member Name="And(System.Collections.BitArray)" />
+ <Member Name="Or(System.Collections.BitArray)" />
+ <Member Name="Xor(System.Collections.BitArray)" />
+ <Member Name="Not" />
+ <Member Name="set_Item(System.Int32,System.Boolean)" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ <Member Name="get_Length" />
+ <Member Name="set_Length(System.Int32)" />
+ <Member MemberType="Property" Name="Length" />
+ <Member Name="CopyTo(System.Array,System.Int32)" />
+ <Member Name="get_Count" />
+ <Member MemberType="Property" Name="Count" />
+ <Member Name="get_IsReadOnly" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member Name="get_IsSynchronized" />
+ <Member MemberType="Property" Name="IsSynchronized" />
+ <Member Name="get_SyncRoot" />
+ <Member MemberType="Property" Name="SyncRoot" />
+ <Member Name="Clone" />
+ <Member Name="GetEnumerator" />
+ </Type>
+ <Type Name="System.Collections.CollectionBase">
+ <Member Name="#ctor" />
+ <Member Name="get_List" />
+ <Member MemberType="Property" Name="List" />
+ </Type>
+ <Type Name="System.Collections.DictionaryEntry">
+ <Member Name="#ctor(System.Object,System.Object)" />
+ <Member Name="get_Key" />
+ <Member Name="get_Value" />
+ <Member Name="set_Key(System.Object)" />
+ <Member Name="set_Value(System.Object)" />
+ <Member MemberType="Property" Name="Key" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Collections.Generic.Comparer&lt;T&gt;">
+ <Member Name="#ctor" />
+ <Member Name="Compare(T,T)" />
+ <Member Name="Create(System.Comparison&lt;T&gt;)" />
+ <Member Name="get_Default" />
+ <Member MemberType="Property" Name="Default" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Collections.Generic.IDictionary&lt;TKey,TValue&gt;)" />
+ <Member Name="#ctor(System.Collections.Generic.IDictionary&lt;TKey,TValue&gt;,System.Collections.Generic.IEqualityComparer&lt;TKey&gt;)" />
+ <Member Name="#ctor(System.Collections.Generic.IEqualityComparer&lt;TKey&gt;)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Collections.Generic.IEqualityComparer&lt;TKey&gt;)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Add(TKey,TValue)" />
+ <Member Name="Clear" />
+ <Member Name="ContainsKey(TKey)" />
+ <Member Name="ContainsValue(TValue)" />
+ <Member Name="get_Comparer" />
+ <Member Name="get_Count" />
+ <Member Name="get_Item(TKey)" />
+ <Member Name="get_Keys" />
+ <Member Name="get_Values" />
+ <Member Name="GetEnumerator" />
+ <Member Name="Remove(TKey)" />
+ <Member Name="set_Item(TKey,TValue)" />
+ <Member Name="TryGetValue(TKey,TValue@)" />
+ <Member MemberType="Property" Name="Comparer" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Item(TKey)" />
+ <Member MemberType="Property" Name="Keys" />
+ <Member MemberType="Property" Name="Values" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;+Enumerator">
+ <Member Name="Dispose" />
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member MemberType="Property" Name="Current" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;+KeyCollection">
+ <Member Name="#ctor(System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;)" />
+ <Member Name="CopyTo(TKey[],System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="GetEnumerator" />
+ <Member MemberType="Property" Name="Count" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;+KeyCollection+Enumerator">
+ <Member Name="Dispose" />
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member MemberType="Property" Name="Current" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;+ValueCollection">
+ <Member Name="#ctor(System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;)" />
+ <Member Name="CopyTo(TValue[],System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="GetEnumerator" />
+ <Member MemberType="Property" Name="Count" />
+ </Type>
+ <Type Name="System.Collections.Generic.Dictionary&lt;TKey,TValue&gt;+ValueCollection+Enumerator">
+ <Member Name="Dispose" />
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member MemberType="Property" Name="Current" />
+ </Type>
+ <Type Name="System.Collections.Generic.EqualityComparer&lt;T&gt;">
+ <Member Name="#ctor" />
+ <Member Name="Equals(T,T)" />
+ <Member Name="get_Default" />
+ <Member Name="GetHashCode(T)" />
+ <Member MemberType="Property" Name="Default" />
+ </Type>
+ <Type Name="System.Collections.Generic.ICollection&lt;T&gt;">
+ <Member Name="Add(T)" />
+ <Member Name="Clear" />
+ <Member Name="Contains(T)" />
+ <Member Name="CopyTo(T[],System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="Remove(T)" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ </Type>
+ <Type Name="System.Collections.Generic.IComparer&lt;T&gt;">
+ <Member Name="Compare(T,T)" />
+ </Type>
+ <Type Name="System.Collections.Generic.IDictionary&lt;TKey,TValue&gt;">
+ <Member Name="Add(TKey,TValue)" />
+ <Member Name="ContainsKey(TKey)" />
+ <Member Name="get_Item(TKey)" />
+ <Member Name="get_Keys" />
+ <Member Name="get_Values" />
+ <Member Name="Remove(TKey)" />
+ <Member Name="set_Item(TKey,TValue)" />
+ <Member Name="TryGetValue(TKey,TValue@)" />
+ <Member MemberType="Property" Name="Item(TKey)" />
+ <Member MemberType="Property" Name="Keys" />
+ <Member MemberType="Property" Name="Values" />
+ </Type>
+ <Type Name="System.Collections.Generic.IEnumerable&lt;T&gt;">
+ <Member Name="GetEnumerator" />
+ </Type>
+ <Type Name="System.Collections.Generic.IEnumerator&lt;T&gt;">
+ <Member Name="get_Current" />
+ <Member MemberType="Property" Name="Current" />
+ </Type>
+ <Type Name="System.Collections.Generic.IEqualityComparer&lt;T&gt;">
+ <Member Name="Equals(T,T)" />
+ <Member Name="GetHashCode(T)" />
+ </Type>
+ <Type Name="System.Collections.Generic.IList&lt;T&gt;">
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="IndexOf(T)" />
+ <Member Name="Insert(System.Int32,T)" />
+ <Member Name="RemoveAt(System.Int32)" />
+ <Member Name="set_Item(System.Int32,T)" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ </Type>
+ <Type Name="System.Collections.Generic.IReadOnlyDictionary&lt;TKey,TValue&gt;">
+ <Member Name="ContainsKey(TKey)" />
+ <Member Name="get_Item(TKey)" />
+ <Member Name="get_Keys" />
+ <Member Name="get_Values" />
+ <Member Name="TryGetValue(TKey,TValue@)" />
+ <Member MemberType="Property" Name="Item(TKey)" />
+ <Member MemberType="Property" Name="Keys" />
+ <Member MemberType="Property" Name="Values" />
+ </Type>
+ <Type Name="System.Collections.Generic.IReadOnlyList&lt;T&gt;">
+ <Member Name="get_Item(System.Int32)" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ </Type>
+ <Type Name="System.Collections.Generic.IReadOnlyCollection&lt;T&gt;">
+ <Member MemberType="Property" Name="Count" />
+ </Type>
+ <Type Name="System.Collections.Generic.KeyNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Collections.Generic.KeyValuePair&lt;TKey,TValue&gt;">
+ <Member Name="#ctor(TKey,TValue)" />
+ <Member Name="get_Key" />
+ <Member Name="get_Value" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Key" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Collections.Generic.List&lt;T&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Collections.Generic.IEnumerable&lt;T&gt;)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="Add(T)" />
+ <Member Name="AddRange(System.Collections.Generic.IEnumerable&lt;T&gt;)" />
+ <Member Name="AsReadOnly" />
+ <Member Name="BinarySearch(System.Int32,System.Int32,T,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="BinarySearch(T)" />
+ <Member Name="BinarySearch(T,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="Clear" />
+ <Member Name="Contains(T)" />
+ <Member Name="ConvertAll&lt;TOutput&gt;(System.Converter&lt;T,TOutput&gt;)" />
+ <Member Name="CopyTo(System.Int32,T[],System.Int32,System.Int32)" />
+ <Member Name="CopyTo(T[])" />
+ <Member Name="CopyTo(T[],System.Int32)" />
+ <Member Name="Exists(System.Predicate&lt;T&gt;)" />
+ <Member Name="Find(System.Predicate&lt;T&gt;)" />
+ <Member Name="FindAll(System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex(System.Int32,System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex(System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindIndex(System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLast(System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex(System.Int32,System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex(System.Int32,System.Predicate&lt;T&gt;)" />
+ <Member Name="FindLastIndex(System.Predicate&lt;T&gt;)" />
+ <Member Name="ForEach(System.Action&lt;T&gt;)" />
+ <Member Name="get_Capacity" />
+ <Member Name="get_Count" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="GetEnumerator" />
+ <Member Name="GetRange(System.Int32,System.Int32)" />
+ <Member Name="IndexOf(T)" />
+ <Member Name="IndexOf(T,System.Int32)" />
+ <Member Name="IndexOf(T,System.Int32,System.Int32)" />
+ <Member Name="Insert(System.Int32,T)" />
+ <Member Name="InsertRange(System.Int32,System.Collections.Generic.IEnumerable&lt;T&gt;)" />
+ <Member Name="LastIndexOf(T)" />
+ <Member Name="LastIndexOf(T,System.Int32)" />
+ <Member Name="LastIndexOf(T,System.Int32,System.Int32)" />
+ <Member Name="Remove(T)" />
+ <Member Name="RemoveAll(System.Predicate&lt;T&gt;)" />
+ <Member Name="RemoveAt(System.Int32)" />
+ <Member Name="RemoveRange(System.Int32,System.Int32)" />
+ <Member Name="Reverse" />
+ <Member Name="Reverse(System.Int32,System.Int32)" />
+ <Member Name="set_Capacity(System.Int32)" />
+ <Member Name="set_Item(System.Int32,T)" />
+ <Member Name="Sort" />
+ <Member Name="Sort(System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="Sort(System.Comparison&lt;T&gt;)" />
+ <Member Name="Sort(System.Int32,System.Int32,System.Collections.Generic.IComparer&lt;T&gt;)" />
+ <Member Name="ToArray" />
+ <Member Name="TrimExcess" />
+ <Member MemberType="Property" Name="Capacity" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ <Member Name="TrueForAll(System.Predicate&lt;T&gt;)" />
+ </Type>
+ <Type Name="System.Collections.Generic.List&lt;T&gt;+Enumerator">
+ <Member Name="Dispose" />
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member MemberType="Property" Name="Current" />
+ <Member Name="System.Collections.IEnumerator.Reset" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.Generic.Mscorlib_CollectionDebugView&lt;T&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Collections.Generic.ICollection&lt;T&gt;)" />
+ <Member Status="ImplRoot" Name="get_Items" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Items" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.Generic.Mscorlib_DictionaryKeyCollectionDebugView&lt;TKey,TValue&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Collections.Generic.ICollection&lt;TKey&gt;)" />
+ <Member Status="ImplRoot" Name="get_Items" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Items" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.Generic.Mscorlib_DictionaryValueCollectionDebugView&lt;TKey,TValue&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Collections.Generic.ICollection&lt;TValue&gt;)" />
+ <Member Status="ImplRoot" Name="get_Items" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Items" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.Generic.Mscorlib_DictionaryDebugView&lt;K,V&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Collections.Generic.IDictionary&lt;K,V&gt;)" />
+ <Member Status="ImplRoot" Name="get_Items" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Items" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Collections.Generic.Mscorlib_KeyedCollectionDebugView&lt;K,T&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Collections.ObjectModel.KeyedCollection&lt;K,T&gt;)" />
+ <Member Status="ImplRoot" Name="get_Items" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Items" />
+ </Type>
+ <Type Name="System.Collections.ICollection">
+ <Member Name="CopyTo(System.Array,System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="get_IsSynchronized" />
+ <Member Name="get_SyncRoot" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="IsSynchronized" />
+ <Member MemberType="Property" Name="SyncRoot" />
+ </Type>
+ <Type Name="System.Collections.IComparer">
+ <Member Name="Compare(System.Object,System.Object)" />
+ </Type>
+ <Type Name="System.Collections.IDictionary">
+ <Member Name="Add(System.Object,System.Object)" />
+ <Member Name="Clear" />
+ <Member Name="Contains(System.Object)" />
+ <Member Name="get_IsFixedSize" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_Item(System.Object)" />
+ <Member Name="get_Keys" />
+ <Member Name="get_Values" />
+ <Member Name="GetEnumerator" />
+ <Member Name="Remove(System.Object)" />
+ <Member Name="set_Item(System.Object,System.Object)" />
+ <Member MemberType="Property" Name="IsFixedSize" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="Item(System.Object)" />
+ <Member MemberType="Property" Name="Keys" />
+ <Member MemberType="Property" Name="Values" />
+ </Type>
+ <Type Name="System.Collections.IDictionaryEnumerator">
+ <Member Name="get_Entry" />
+ <Member Name="get_Key" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Entry" />
+ <Member MemberType="Property" Name="Key" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Collections.IEnumerable">
+ <Member Name="GetEnumerator" />
+ </Type>
+ <Type Name="System.Collections.IEnumerator">
+ <Member Name="get_Current" />
+ <Member Name="MoveNext" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Current" />
+ </Type>
+ <Type Name="System.Collections.IEqualityComparer">
+ <Member Name="Equals(System.Object,System.Object)" />
+ <Member Name="GetHashCode(System.Object)" />
+ </Type>
+ <Type Name="System.Collections.IList">
+ <Member Name="Add(System.Object)" />
+ <Member Name="Clear" />
+ <Member Name="Contains(System.Object)" />
+ <Member Name="get_IsFixedSize" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="IndexOf(System.Object)" />
+ <Member Name="Insert(System.Int32,System.Object)" />
+ <Member Name="Remove(System.Object)" />
+ <Member Name="RemoveAt(System.Int32)" />
+ <Member Name="set_Item(System.Int32,System.Object)" />
+ <Member MemberType="Property" Name="IsFixedSize" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ </Type>
+ <Type Name="System.Collections.IStructuralComparable">
+ <Member Name="CompareTo(System.Object,System.Collections.IComparer)" />
+ </Type>
+ <Type Name="System.Collections.IStructuralEquatable">
+ <Member Name="Equals(System.Object,System.Collections.IEqualityComparer)" />
+ <Member Name="GetHashCode(System.Collections.IEqualityComparer)" />
+ </Type>
+ <Type Name="System.Collections.ObjectModel.Collection&lt;T&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Collections.Generic.IList&lt;T&gt;)" />
+ <Member Name="Add(T)" />
+ <Member Name="Clear" />
+ <Member Name="ClearItems" />
+ <Member Name="Contains(T)" />
+ <Member Name="CopyTo(T[],System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="get_Items" />
+ <Member Name="GetEnumerator" />
+ <Member Name="IndexOf(T)" />
+ <Member Name="Insert(System.Int32,T)" />
+ <Member Name="InsertItem(System.Int32,T)" />
+ <Member Name="Remove(T)" />
+ <Member Name="RemoveAt(System.Int32)" />
+ <Member Name="RemoveItem(System.Int32)" />
+ <Member Name="set_Item(System.Int32,T)" />
+ <Member Name="SetItem(System.Int32,T)" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ <Member MemberType="Property" Name="Items" />
+ </Type>
+ <Type Name="System.Collections.ObjectModel.KeyedCollection&lt;TKey,TItem&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Collections.Generic.IEqualityComparer&lt;TKey&gt;)" />
+ <Member Name="#ctor(System.Collections.Generic.IEqualityComparer&lt;TKey&gt;,System.Int32)" />
+ <Member Name="ChangeItemKey(TItem,TKey)" />
+ <Member Name="ClearItems" />
+ <Member Name="Contains(TKey)" />
+ <Member Name="get_Comparer" />
+ <Member Name="get_Dictionary" />
+ <Member Name="get_Item(TKey)" />
+ <Member Name="GetKeyForItem(TItem)" />
+ <Member Name="InsertItem(System.Int32,TItem)" />
+ <Member Name="Remove(TKey)" />
+ <Member Name="RemoveItem(System.Int32)" />
+ <Member Name="SetItem(System.Int32,TItem)" />
+ <Member MemberType="Property" Name="Comparer" />
+ <Member MemberType="Property" Name="Dictionary" />
+ <Member MemberType="Property" Name="Item(TKey)" />
+ </Type>
+ <Type Name="System.Collections.ObjectModel.ReadOnlyCollection&lt;T&gt;">
+ <Member Name="#ctor(System.Collections.Generic.IList&lt;T&gt;)" />
+ <Member Name="Contains(T)" />
+ <Member Name="CopyTo(T[],System.Int32)" />
+ <Member Name="get_Count" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="get_Items" />
+ <Member Name="GetEnumerator" />
+ <Member Name="IndexOf(T)" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ <Member MemberType="Property" Name="Items" />
+ </Type>
+
+ <Type Name="System.Collections.ObjectModel.ReadOnlyDictionary&lt;TKey,TValue&gt;">
+ <Member Name="#ctor(System.Collections.Generic.IDictionary&lt;TKey,TValue&gt;)" />
+ <Member Name="ContainsKey(TKey)" />
+ <Member Name="get_Count" />
+ <Member Name="get_Item(TKey)" />
+ <Member Name="GetEnumerator" />
+ <Member Name="TryGetValue(TKey,TValue@)" />
+ <Member MemberType="Property" Name="Count" />
+ <Member MemberType="Property" Name="Keys" />
+ <Member MemberType="Property" Name="Values" />
+ <Member MemberType="Property" Name="Dictionary" />
+ <Member MemberType="Property" Name="Item(TKey)" />
+ </Type>
+ <Type Name="System.GCCollectionMode">
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="Optimized" />
+ <Member MemberType="Field" Name="Forced" />
+ </Type>
+
+ <Type Name="System.Comparison&lt;T&gt;">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(T,T,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(T,T)" />
+ </Type>
+ <Type Name="System.Runtime.Loader.AssemblyLoadContext" condition="FEATURE_HOST_ASSEMBLY_RESOLVER">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="Default" />
+ <Member Name="GetAssemblyName(System.String)" />
+ <Member Name="GetLoadContext(System.Reflection.Assembly)" />
+ <Member Name="LoadFromAssemblyName(System.Reflection.AssemblyName)" />
+ <Member Name="Load(System.Reflection.AssemblyName)" />
+ <Member Name="LoadFromAssemblyPath(System.String)" />
+ <Member Name="LoadFromNativeImagePath(System.String,System.String)" />
+ <Member Name="LoadFromStream(System.IO.Stream)" />
+ <Member Name="LoadFromStream(System.IO.Stream,System.IO.Stream)" />
+ <Member Name="Resolve(System.IntPtr,System.Reflection.AssemblyName)" />
+ <Member Name="ResolveUsingResolvingEvent(System.IntPtr,System.Reflection.AssemblyName)" />
+ <Member Name="ResolveUnmanagedDll(System.String,System.IntPtr)" />
+ <Member Name="LoadUnmanagedDll(System.String)" />
+ <Member Name="LoadUnmanagedDllFromPath(System.String)" />
+ <Member Name="get_Default" />
+ <Member Name="SetProfileOptimizationRoot(System.String)" />
+ <Member Name="StartProfileOptimization(System.String)" />
+ <Member MemberType="Event" Name="Resolving" />
+ <Member MemberType="Event" Name="Unloading" />
+ </Type>
+ <Type Name="System.Reflection.Metadata.AssemblyExtensions">
+ <Member Name="TryGetRawMetadata(System.Reflection.Assembly,System.Byte*@,System.Int32@)"/>
+ </Type>
+ <Type Name="System.ContextBoundObject">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.ContextMarshalException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ContextStaticAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Convert">
+ <Member MemberType="Field" Name="DBNull" />
+ <Member Name="ChangeType(System.Object,System.Type)" />
+ <Member Name="ChangeType(System.Object,System.Type,System.IFormatProvider)" />
+ <Member Name="ChangeType(System.Object,System.TypeCode)" />
+ <Member Name="ChangeType(System.Object,System.TypeCode,System.IFormatProvider)" />
+ <Member Name="FromBase64CharArray(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="FromBase64String(System.String)" />
+ <Member Name="GetTypeCode(System.Object)" />
+ <Member Name="IsDBNull(System.Object)" />
+ <Member Name="ToBase64CharArray(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="ToBase64CharArray(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32,System.Base64FormattingOptions)" />
+ <Member Name="ToBase64String(System.Byte[])" />
+ <Member Name="ToBase64String(System.Byte[],System.Base64FormattingOptions)" />
+ <Member Name="ToBase64String(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ToBase64String(System.Byte[],System.Int32,System.Int32,System.Base64FormattingOptions)" />
+ <Member Name="ToBoolean(System.Boolean)" />
+ <Member Name="ToBoolean(System.Byte)" />
+ <Member Name="ToBoolean(System.Char)" />
+ <Member Name="ToBoolean(System.DateTime)" />
+ <Member Name="ToBoolean(System.Decimal)" />
+ <Member Name="ToBoolean(System.Double)" />
+ <Member Name="ToBoolean(System.Int16)" />
+ <Member Name="ToBoolean(System.Int32)" />
+ <Member Name="ToBoolean(System.Int64)" />
+ <Member Name="ToBoolean(System.Object)" />
+ <Member Name="ToBoolean(System.Object,System.IFormatProvider)" />
+ <Member Name="ToBoolean(System.SByte)" />
+ <Member Name="ToBoolean(System.Single)" />
+ <Member Name="ToBoolean(System.String)" />
+ <Member Name="ToBoolean(System.String,System.IFormatProvider)" />
+ <Member Name="ToBoolean(System.UInt16)" />
+ <Member Name="ToBoolean(System.UInt32)" />
+ <Member Name="ToBoolean(System.UInt64)" />
+ <Member Name="ToByte(System.Boolean)" />
+ <Member Name="ToByte(System.Byte)" />
+ <Member Name="ToByte(System.Char)" />
+ <Member Name="ToByte(System.DateTime)" />
+ <Member Name="ToByte(System.Decimal)" />
+ <Member Name="ToByte(System.Double)" />
+ <Member Name="ToByte(System.Int16)" />
+ <Member Name="ToByte(System.Int32)" />
+ <Member Name="ToByte(System.Int64)" />
+ <Member Name="ToByte(System.Object)" />
+ <Member Name="ToByte(System.Object,System.IFormatProvider)" />
+ <Member Name="ToByte(System.SByte)" />
+ <Member Name="ToByte(System.Single)" />
+ <Member Name="ToByte(System.String)" />
+ <Member Name="ToByte(System.String,System.IFormatProvider)" />
+ <Member Name="ToByte(System.String,System.Int32)" />
+ <Member Name="ToByte(System.UInt16)" />
+ <Member Name="ToByte(System.UInt32)" />
+ <Member Name="ToByte(System.UInt64)" />
+ <Member Name="ToChar(System.Boolean)" />
+ <Member Name="ToChar(System.Byte)" />
+ <Member Name="ToChar(System.Char)" />
+ <Member Name="ToChar(System.DateTime)" />
+ <Member Name="ToChar(System.Decimal)" />
+ <Member Name="ToChar(System.Double)" />
+ <Member Name="ToChar(System.Int16)" />
+ <Member Name="ToChar(System.Int32)" />
+ <Member Name="ToChar(System.Int64)" />
+ <Member Name="ToChar(System.Object)" />
+ <Member Name="ToChar(System.Object,System.IFormatProvider)" />
+ <Member Name="ToChar(System.SByte)" />
+ <Member Name="ToChar(System.Single)" />
+ <Member Name="ToChar(System.String)" />
+ <Member Name="ToChar(System.String,System.IFormatProvider)" />
+ <Member Name="ToChar(System.UInt16)" />
+ <Member Name="ToChar(System.UInt32)" />
+ <Member Name="ToChar(System.UInt64)" />
+ <Member Name="ToDateTime(System.Boolean)" />
+ <Member Name="ToDateTime(System.Byte)" />
+ <Member Name="ToDateTime(System.Char)" />
+ <Member Name="ToDateTime(System.DateTime)" />
+ <Member Name="ToDateTime(System.Decimal)" />
+ <Member Name="ToDateTime(System.Double)" />
+ <Member Name="ToDateTime(System.Int16)" />
+ <Member Name="ToDateTime(System.Int32)" />
+ <Member Name="ToDateTime(System.Int64)" />
+ <Member Name="ToDateTime(System.Object)" />
+ <Member Name="ToDateTime(System.Object,System.IFormatProvider)" />
+ <Member Name="ToDateTime(System.SByte)" />
+ <Member Name="ToDateTime(System.Single)" />
+ <Member Name="ToDateTime(System.String)" />
+ <Member Name="ToDateTime(System.String,System.IFormatProvider)" />
+ <Member Name="ToDateTime(System.UInt16)" />
+ <Member Name="ToDateTime(System.UInt32)" />
+ <Member Name="ToDateTime(System.UInt64)" />
+ <Member Name="ToDecimal(System.Boolean)" />
+ <Member Name="ToDecimal(System.Byte)" />
+ <Member Name="ToDecimal(System.Char)" />
+ <Member Name="ToDecimal(System.DateTime)" />
+ <Member Name="ToDecimal(System.Decimal)" />
+ <Member Name="ToDecimal(System.Double)" />
+ <Member Name="ToDecimal(System.Int16)" />
+ <Member Name="ToDecimal(System.Int32)" />
+ <Member Name="ToDecimal(System.Int64)" />
+ <Member Name="ToDecimal(System.Object)" />
+ <Member Name="ToDecimal(System.Object,System.IFormatProvider)" />
+ <Member Name="ToDecimal(System.SByte)" />
+ <Member Name="ToDecimal(System.Single)" />
+ <Member Name="ToDecimal(System.String)" />
+ <Member Name="ToDecimal(System.String,System.IFormatProvider)" />
+ <Member Name="ToDecimal(System.UInt16)" />
+ <Member Name="ToDecimal(System.UInt32)" />
+ <Member Name="ToDecimal(System.UInt64)" />
+ <Member Name="ToDouble(System.Boolean)" />
+ <Member Name="ToDouble(System.Byte)" />
+ <Member Name="ToDouble(System.Char)" />
+ <Member Name="ToDouble(System.DateTime)" />
+ <Member Name="ToDouble(System.Decimal)" />
+ <Member Name="ToDouble(System.Double)" />
+ <Member Name="ToDouble(System.Int16)" />
+ <Member Name="ToDouble(System.Int32)" />
+ <Member Name="ToDouble(System.Int64)" />
+ <Member Name="ToDouble(System.Object)" />
+ <Member Name="ToDouble(System.Object,System.IFormatProvider)" />
+ <Member Name="ToDouble(System.SByte)" />
+ <Member Name="ToDouble(System.Single)" />
+ <Member Name="ToDouble(System.String)" />
+ <Member Name="ToDouble(System.String,System.IFormatProvider)" />
+ <Member Name="ToDouble(System.UInt16)" />
+ <Member Name="ToDouble(System.UInt32)" />
+ <Member Name="ToDouble(System.UInt64)" />
+ <Member Name="ToInt16(System.Boolean)" />
+ <Member Name="ToInt16(System.Byte)" />
+ <Member Name="ToInt16(System.Char)" />
+ <Member Name="ToInt16(System.DateTime)" />
+ <Member Name="ToInt16(System.Decimal)" />
+ <Member Name="ToInt16(System.Double)" />
+ <Member Name="ToInt16(System.Int16)" />
+ <Member Name="ToInt16(System.Int32)" />
+ <Member Name="ToInt16(System.Int64)" />
+ <Member Name="ToInt16(System.Object)" />
+ <Member Name="ToInt16(System.Object,System.IFormatProvider)" />
+ <Member Name="ToInt16(System.SByte)" />
+ <Member Name="ToInt16(System.Single)" />
+ <Member Name="ToInt16(System.String)" />
+ <Member Name="ToInt16(System.String,System.IFormatProvider)" />
+ <Member Name="ToInt16(System.String,System.Int32)" />
+ <Member Name="ToInt16(System.UInt16)" />
+ <Member Name="ToInt16(System.UInt32)" />
+ <Member Name="ToInt16(System.UInt64)" />
+ <Member Name="ToInt32(System.Boolean)" />
+ <Member Name="ToInt32(System.Byte)" />
+ <Member Name="ToInt32(System.Char)" />
+ <Member Name="ToInt32(System.DateTime)" />
+ <Member Name="ToInt32(System.Decimal)" />
+ <Member Name="ToInt32(System.Double)" />
+ <Member Name="ToInt32(System.Int16)" />
+ <Member Name="ToInt32(System.Int32)" />
+ <Member Name="ToInt32(System.Int64)" />
+ <Member Name="ToInt32(System.Object)" />
+ <Member Name="ToInt32(System.Object,System.IFormatProvider)" />
+ <Member Name="ToInt32(System.SByte)" />
+ <Member Name="ToInt32(System.Single)" />
+ <Member Name="ToInt32(System.String)" />
+ <Member Name="ToInt32(System.String,System.IFormatProvider)" />
+ <Member Name="ToInt32(System.String,System.Int32)" />
+ <Member Name="ToInt32(System.UInt16)" />
+ <Member Name="ToInt32(System.UInt32)" />
+ <Member Name="ToInt32(System.UInt64)" />
+ <Member Name="ToInt64(System.Boolean)" />
+ <Member Name="ToInt64(System.Byte)" />
+ <Member Name="ToInt64(System.Char)" />
+ <Member Name="ToInt64(System.DateTime)" />
+ <Member Name="ToInt64(System.Decimal)" />
+ <Member Name="ToInt64(System.Double)" />
+ <Member Name="ToInt64(System.Int16)" />
+ <Member Name="ToInt64(System.Int32)" />
+ <Member Name="ToInt64(System.Int64)" />
+ <Member Name="ToInt64(System.Object)" />
+ <Member Name="ToInt64(System.Object,System.IFormatProvider)" />
+ <Member Name="ToInt64(System.SByte)" />
+ <Member Name="ToInt64(System.Single)" />
+ <Member Name="ToInt64(System.String)" />
+ <Member Name="ToInt64(System.String,System.IFormatProvider)" />
+ <Member Name="ToInt64(System.String,System.Int32)" />
+ <Member Name="ToInt64(System.UInt16)" />
+ <Member Name="ToInt64(System.UInt32)" />
+ <Member Name="ToInt64(System.UInt64)" />
+ <Member Name="ToSByte(System.Boolean)" />
+ <Member Name="ToSByte(System.Byte)" />
+ <Member Name="ToSByte(System.Char)" />
+ <Member Name="ToSByte(System.DateTime)" />
+ <Member Name="ToSByte(System.Decimal)" />
+ <Member Name="ToSByte(System.Double)" />
+ <Member Name="ToSByte(System.Int16)" />
+ <Member Name="ToSByte(System.Int32)" />
+ <Member Name="ToSByte(System.Int64)" />
+ <Member Name="ToSByte(System.Object)" />
+ <Member Name="ToSByte(System.Object,System.IFormatProvider)" />
+ <Member Name="ToSByte(System.SByte)" />
+ <Member Name="ToSByte(System.Single)" />
+ <Member Name="ToSByte(System.String)" />
+ <Member Name="ToSByte(System.String,System.IFormatProvider)" />
+ <Member Name="ToSByte(System.String,System.Int32)" />
+ <Member Name="ToSByte(System.UInt16)" />
+ <Member Name="ToSByte(System.UInt32)" />
+ <Member Name="ToSByte(System.UInt64)" />
+ <Member Name="ToSingle(System.Boolean)" />
+ <Member Name="ToSingle(System.Byte)" />
+ <Member Name="ToSingle(System.Char)" />
+ <Member Name="ToSingle(System.DateTime)" />
+ <Member Name="ToSingle(System.Decimal)" />
+ <Member Name="ToSingle(System.Double)" />
+ <Member Name="ToSingle(System.Int16)" />
+ <Member Name="ToSingle(System.Int32)" />
+ <Member Name="ToSingle(System.Int64)" />
+ <Member Name="ToSingle(System.Object)" />
+ <Member Name="ToSingle(System.Object,System.IFormatProvider)" />
+ <Member Name="ToSingle(System.SByte)" />
+ <Member Name="ToSingle(System.Single)" />
+ <Member Name="ToSingle(System.String)" />
+ <Member Name="ToSingle(System.String,System.IFormatProvider)" />
+ <Member Name="ToSingle(System.UInt16)" />
+ <Member Name="ToSingle(System.UInt32)" />
+ <Member Name="ToSingle(System.UInt64)" />
+ <Member Name="ToString(System.Boolean)" />
+ <Member Name="ToString(System.Boolean,System.IFormatProvider)" />
+ <Member Name="ToString(System.Byte)" />
+ <Member Name="ToString(System.Byte,System.IFormatProvider)" />
+ <Member Name="ToString(System.Byte,System.Int32)" />
+ <Member Name="ToString(System.Char)" />
+ <Member Name="ToString(System.Char,System.IFormatProvider)" />
+ <Member Name="ToString(System.DateTime)" />
+ <Member Name="ToString(System.DateTime,System.IFormatProvider)" />
+ <Member Name="ToString(System.Decimal)" />
+ <Member Name="ToString(System.Decimal,System.IFormatProvider)" />
+ <Member Name="ToString(System.Double)" />
+ <Member Name="ToString(System.Double,System.IFormatProvider)" />
+ <Member Name="ToString(System.Int16)" />
+ <Member Name="ToString(System.Int16,System.IFormatProvider)" />
+ <Member Name="ToString(System.Int16,System.Int32)" />
+ <Member Name="ToString(System.Int32)" />
+ <Member Name="ToString(System.Int32,System.IFormatProvider)" />
+ <Member Name="ToString(System.Int32,System.Int32)" />
+ <Member Name="ToString(System.Int64)" />
+ <Member Name="ToString(System.Int64,System.IFormatProvider)" />
+ <Member Name="ToString(System.Int64,System.Int32)" />
+ <Member Name="ToString(System.Object)" />
+ <Member Name="ToString(System.Object,System.IFormatProvider)" />
+ <Member Name="ToString(System.SByte)" />
+ <Member Name="ToString(System.SByte,System.IFormatProvider)" />
+ <Member Name="ToString(System.Single)" />
+ <Member Name="ToString(System.Single,System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="ToString(System.UInt16)" />
+ <Member Name="ToString(System.UInt16,System.IFormatProvider)" />
+ <Member Name="ToString(System.UInt32)" />
+ <Member Name="ToString(System.UInt32,System.IFormatProvider)" />
+ <Member Name="ToString(System.UInt64)" />
+ <Member Name="ToString(System.UInt64,System.IFormatProvider)" />
+ <Member Name="ToUInt16(System.Boolean)" />
+ <Member Name="ToUInt16(System.Byte)" />
+ <Member Name="ToUInt16(System.Char)" />
+ <Member Name="ToUInt16(System.DateTime)" />
+ <Member Name="ToUInt16(System.Decimal)" />
+ <Member Name="ToUInt16(System.Double)" />
+ <Member Name="ToUInt16(System.Int16)" />
+ <Member Name="ToUInt16(System.Int32)" />
+ <Member Name="ToUInt16(System.Int64)" />
+ <Member Name="ToUInt16(System.Object)" />
+ <Member Name="ToUInt16(System.Object,System.IFormatProvider)" />
+ <Member Name="ToUInt16(System.SByte)" />
+ <Member Name="ToUInt16(System.Single)" />
+ <Member Name="ToUInt16(System.String)" />
+ <Member Name="ToUInt16(System.String,System.IFormatProvider)" />
+ <Member Name="ToUInt16(System.String,System.Int32)" />
+ <Member Name="ToUInt16(System.UInt16)" />
+ <Member Name="ToUInt16(System.UInt32)" />
+ <Member Name="ToUInt16(System.UInt64)" />
+ <Member Name="ToUInt32(System.Boolean)" />
+ <Member Name="ToUInt32(System.Byte)" />
+ <Member Name="ToUInt32(System.Char)" />
+ <Member Name="ToUInt32(System.DateTime)" />
+ <Member Name="ToUInt32(System.Decimal)" />
+ <Member Name="ToUInt32(System.Double)" />
+ <Member Name="ToUInt32(System.Int16)" />
+ <Member Name="ToUInt32(System.Int32)" />
+ <Member Name="ToUInt32(System.Int64)" />
+ <Member Name="ToUInt32(System.Object)" />
+ <Member Name="ToUInt32(System.Object,System.IFormatProvider)" />
+ <Member Name="ToUInt32(System.SByte)" />
+ <Member Name="ToUInt32(System.Single)" />
+ <Member Name="ToUInt32(System.String)" />
+ <Member Name="ToUInt32(System.String,System.IFormatProvider)" />
+ <Member Name="ToUInt32(System.String,System.Int32)" />
+ <Member Name="ToUInt32(System.UInt16)" />
+ <Member Name="ToUInt32(System.UInt32)" />
+ <Member Name="ToUInt32(System.UInt64)" />
+ <Member Name="ToUInt64(System.Boolean)" />
+ <Member Name="ToUInt64(System.Byte)" />
+ <Member Name="ToUInt64(System.Char)" />
+ <Member Name="ToUInt64(System.DateTime)" />
+ <Member Name="ToUInt64(System.Decimal)" />
+ <Member Name="ToUInt64(System.Double)" />
+ <Member Name="ToUInt64(System.Int16)" />
+ <Member Name="ToUInt64(System.Int32)" />
+ <Member Name="ToUInt64(System.Int64)" />
+ <Member Name="ToUInt64(System.Object)" />
+ <Member Name="ToUInt64(System.Object,System.IFormatProvider)" />
+ <Member Name="ToUInt64(System.SByte)" />
+ <Member Name="ToUInt64(System.Single)" />
+ <Member Name="ToUInt64(System.String)" />
+ <Member Name="ToUInt64(System.String,System.IFormatProvider)" />
+ <Member Name="ToUInt64(System.String,System.Int32)" />
+ <Member Name="ToUInt64(System.UInt16)" />
+ <Member Name="ToUInt64(System.UInt32)" />
+ <Member Name="ToUInt64(System.UInt64)" />
+ </Type>
+ <Type Name="System.Converter&lt;TInput,TOutput&gt;">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(TInput,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(TInput)" />
+ </Type>
+ <Type Name="System.DataMisalignedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.DateTime">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Globalization.Calendar)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.DateTimeKind)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Globalization.Calendar)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.DateTimeKind)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Globalization.Calendar)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Globalization.Calendar,System.DateTimeKind)" />
+ <Member Name="#ctor(System.Int64)" />
+ <Member Name="#ctor(System.Int64,System.DateTimeKind)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Add(System.TimeSpan)" />
+ <Member Name="AddDays(System.Double)" />
+ <Member Name="AddHours(System.Double)" />
+ <Member Name="AddMilliseconds(System.Double)" />
+ <Member Name="AddMinutes(System.Double)" />
+ <Member Name="AddMonths(System.Int32)" />
+ <Member Name="AddSeconds(System.Double)" />
+ <Member Name="AddTicks(System.Int64)" />
+ <Member Name="AddYears(System.Int32)" />
+ <Member Name="Compare(System.DateTime,System.DateTime)" />
+ <Member Name="CompareTo(System.DateTime)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="DaysInMonth(System.Int32,System.Int32)" />
+ <Member Name="Equals(System.DateTime)" />
+ <Member Name="Equals(System.DateTime,System.DateTime)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="FromBinary(System.Int64)" />
+ <Member Name="FromFileTime(System.Int64)" />
+ <Member Name="FromFileTimeUtc(System.Int64)" />
+ <Member Name="FromOADate(System.Double)" />
+ <Member Name="get_Date" />
+ <Member Name="get_Day" />
+ <Member Name="get_DayOfWeek" />
+ <Member Name="get_DayOfYear" />
+ <Member Name="get_Hour" />
+ <Member Name="get_Kind" />
+ <Member Name="get_Millisecond" />
+ <Member Name="get_Minute" />
+ <Member Name="get_Month" />
+ <Member Name="get_Now" />
+ <Member Name="get_Second" />
+ <Member Name="get_Ticks" />
+ <Member Name="get_TimeOfDay" />
+ <Member Name="get_Today" />
+ <Member Name="get_UtcNow" />
+ <Member Name="get_Year" />
+ <Member Name="GetDateTimeFormats" />
+ <Member Name="GetDateTimeFormats(System.Char)" />
+ <Member Name="GetDateTimeFormats(System.Char,System.IFormatProvider)" />
+ <Member Name="GetDateTimeFormats(System.IFormatProvider)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="IsDaylightSavingTime" />
+ <Member Name="IsLeapYear(System.Int32)" />
+ <Member Name="op_Addition(System.DateTime,System.TimeSpan)" />
+ <Member Name="op_Equality(System.DateTime,System.DateTime)" />
+ <Member Name="op_GreaterThan(System.DateTime,System.DateTime)" />
+ <Member Name="op_GreaterThanOrEqual(System.DateTime,System.DateTime)" />
+ <Member Name="op_Inequality(System.DateTime,System.DateTime)" />
+ <Member Name="op_LessThan(System.DateTime,System.DateTime)" />
+ <Member Name="op_LessThanOrEqual(System.DateTime,System.DateTime)" />
+ <Member Name="op_Subtraction(System.DateTime,System.DateTime)" />
+ <Member Name="op_Subtraction(System.DateTime,System.TimeSpan)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="ParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="SpecifyKind(System.DateTime,System.DateTimeKind)" />
+ <Member Name="Subtract(System.DateTime)" />
+ <Member Name="Subtract(System.TimeSpan)" />
+ <Member Name="ToBinary" />
+ <Member Name="ToFileTime" />
+ <Member Name="ToFileTimeUtc" />
+ <Member Name="ToLocalTime" />
+ <Member Name="ToLongDateString" />
+ <Member Name="ToLongTimeString" />
+ <Member Name="ToOADate" />
+ <Member Name="ToShortDateString" />
+ <Member Name="ToShortTimeString" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="ToUniversalTime" />
+ <Member Name="TryParse(System.String,System.DateTime@)" />
+ <Member Name="TryParse(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime@)" />
+ <Member Name="TryParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime@)" />
+ <Member Name="TryParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime@)" />
+ <Member MemberType="Property" Name="Date" />
+ <Member MemberType="Property" Name="Day" />
+ <Member MemberType="Property" Name="DayOfWeek" />
+ <Member MemberType="Property" Name="DayOfYear" />
+ <Member MemberType="Property" Name="Hour" />
+ <Member MemberType="Property" Name="Kind" />
+ <Member MemberType="Property" Name="Millisecond" />
+ <Member MemberType="Property" Name="Minute" />
+ <Member MemberType="Property" Name="Month" />
+ <Member MemberType="Property" Name="Now" />
+ <Member MemberType="Property" Name="Second" />
+ <Member MemberType="Property" Name="Ticks" />
+ <Member MemberType="Property" Name="TimeOfDay" />
+ <Member MemberType="Property" Name="Today" />
+ <Member MemberType="Property" Name="UtcNow" />
+ <Member MemberType="Property" Name="Year" />
+ </Type>
+ <Type Name="System.DateTimeKind">
+ <Member MemberType="Field" Name="Local" />
+ <Member MemberType="Field" Name="Unspecified" />
+ <Member MemberType="Field" Name="Utc" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.DateTimeOffset">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="#ctor(System.DateTime)" />
+ <Member Name="#ctor(System.DateTime,System.TimeSpan)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.TimeSpan)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.TimeSpan)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Globalization.Calendar,System.TimeSpan)" />
+ <Member Name="#ctor(System.Int64,System.TimeSpan)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Add(System.TimeSpan)" />
+ <Member Name="AddDays(System.Double)" />
+ <Member Name="AddHours(System.Double)" />
+ <Member Name="AddMilliseconds(System.Double)" />
+ <Member Name="AddMinutes(System.Double)" />
+ <Member Name="AddMonths(System.Int32)" />
+ <Member Name="AddSeconds(System.Double)" />
+ <Member Name="AddTicks(System.Int64)" />
+ <Member Name="AddYears(System.Int32)" />
+ <Member Name="Compare(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="CompareTo(System.DateTimeOffset)" />
+ <Member Name="Equals(System.DateTimeOffset)" />
+ <Member Name="Equals(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="EqualsExact(System.DateTimeOffset)" />
+ <Member Name="FromFileTime(System.Int64)" />
+ <Member Name="FromUnixTimeSeconds(System.Int64)" />
+ <Member Name="FromUnixTimeMilliseconds(System.Int64)" />
+ <Member Name="get_DateTime" />
+ <Member Name="get_UtcDateTime" />
+ <Member Name="get_LocalDateTime" />
+ <Member Name="get_UtcTicks" />
+ <Member Name="get_Offset" />
+ <Member Name="get_Date" />
+ <Member Name="get_Day" />
+ <Member Name="get_DayOfWeek" />
+ <Member Name="get_DayOfYear" />
+ <Member Name="get_Hour" />
+ <Member Name="get_Millisecond" />
+ <Member Name="get_Minute" />
+ <Member Name="get_Month" />
+ <Member Name="get_Now" />
+ <Member Name="get_Second" />
+ <Member Name="get_Ticks" />
+ <Member Name="get_TimeOfDay" />
+ <Member Name="get_UtcNow" />
+ <Member Name="get_Year" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Addition(System.DateTimeOffset,System.TimeSpan)" />
+ <Member Name="op_Equality(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_GreaterThan(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_GreaterThanOrEqual(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_Inequality(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_LessThan(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_LessThanOrEqual(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_Subtraction(System.DateTimeOffset,System.DateTimeOffset)" />
+ <Member Name="op_Subtraction(System.DateTimeOffset,System.TimeSpan)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="ParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles)" />
+ <Member Name="TryParse(System.String,System.DateTimeOffset@)" />
+ <Member Name="TryParse(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset@)" />
+ <Member Name="TryParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset@)" />
+ <Member Name="TryParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset@)" />
+ <Member Name="Subtract(System.DateTimeOffset)" />
+ <Member Name="Subtract(System.TimeSpan)" />
+ <Member Name="ToFileTime" />
+ <Member Name="ToUnixTimeSeconds" />
+ <Member Name="ToUnixTimeMilliseconds" />
+ <Member Name="ToLocalTime" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="ToUniversalTime" />
+ <Member Name="ToOffset(System.TimeSpan)" />
+ <Member Name="op_Implicit(System.DateTime)" ReturnType="System.DateTimeOffset" />
+ <Member MemberType="Property" Name="DateTime" />
+ <Member MemberType="Property" Name="UtcDateTime" />
+ <Member MemberType="Property" Name="LocalDateTime" />
+ <Member MemberType="Property" Name="UtcTicks" />
+ <Member MemberType="Property" Name="Offset" />
+ <Member MemberType="Property" Name="Date" />
+ <Member MemberType="Property" Name="Day" />
+ <Member MemberType="Property" Name="DayOfWeek" />
+ <Member MemberType="Property" Name="DayOfYear" />
+ <Member MemberType="Property" Name="Hour" />
+ <Member MemberType="Property" Name="Millisecond" />
+ <Member MemberType="Property" Name="Minute" />
+ <Member MemberType="Property" Name="Month" />
+ <Member MemberType="Property" Name="Now" />
+ <Member MemberType="Property" Name="Second" />
+ <Member MemberType="Property" Name="Ticks" />
+ <Member MemberType="Property" Name="TimeOfDay" />
+ <Member MemberType="Property" Name="UtcNow" />
+ <Member MemberType="Property" Name="Year" />
+ </Type>
+ <Type Name="System.DayOfWeek">
+ <Member MemberType="Field" Name="Friday" />
+ <Member MemberType="Field" Name="Monday" />
+ <Member MemberType="Field" Name="Saturday" />
+ <Member MemberType="Field" Name="Sunday" />
+ <Member MemberType="Field" Name="Thursday" />
+ <Member MemberType="Field" Name="Tuesday" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Wednesday" />
+ </Type>
+ <Type Name="System.DBNull" >
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Field" Name="Value" />
+ <Member Name="GetTypeCode" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.Diagnostics.StackFrame">
+ <Member MemberType="Field" Name="OFFSET_UNKNOWN" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="#ctor(System.String,System.Int32,System.Int32)" />
+ <Member Name="GetFileColumnNumber" />
+ <Member Name="GetFileLineNumber" />
+ <Member Name="GetFileName" />
+ <Member Name="GetILOffset" />
+ <Member Name="GetMethod" />
+ <Member Name="GetNativeOffset" />
+ <Member Name="ToString" />
+ </Type>
+ <Type Name="System.Diagnostics.StackTrace">
+ <Member MemberType="Field" Name="METHODS_TO_SKIP" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="#ctor(System.Diagnostics.StackFrame)" />
+ <Member Name="#ctor(System.Exception)" />
+ <Member Name="#ctor(System.Exception,System.Boolean)" />
+ <Member Name="#ctor(System.Exception,System.Int32)" />
+ <Member Name="#ctor(System.Exception,System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.Threading.Thread,System.Boolean)" />
+ <Member Name="get_FrameCount" />
+ <Member Name="GetFrame(System.Int32)" />
+ <Member Name="GetFrames" />
+ <Member Name="GetManagedStackTraceStringHelper(System.Boolean)"/>
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="FrameCount" />
+ </Type>
+ <Type Name="System.Decimal">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinusOne" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member MemberType="Field" Name="One" />
+ <Member MemberType="Field" Name="Zero" />
+ <Member Name="#ctor(System.Double)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Boolean,System.Byte)" />
+ <Member Name="#ctor(System.Int32[])" />
+ <Member Name="#ctor(System.Int64)" />
+ <Member Name="#ctor(System.Single)" />
+ <Member Name="#ctor(System.UInt32)" />
+ <Member Name="#ctor(System.UInt64)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Currency)" /> <!-- EE - il stubs -->
+ <Member Name="Add(System.Decimal,System.Decimal)" />
+ <Member Name="Ceiling(System.Decimal)" />
+ <Member Name="Compare(System.Decimal,System.Decimal)" />
+ <Member Name="CompareTo(System.Decimal)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Divide(System.Decimal,System.Decimal)" />
+ <Member Name="Equals(System.Decimal)" />
+ <Member Name="Equals(System.Decimal,System.Decimal)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Floor(System.Decimal)" />
+ <Member Name="FromOACurrency(System.Int64)" />
+ <Member Name="GetBits(System.Decimal)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Multiply(System.Decimal,System.Decimal)" />
+ <Member Name="Negate(System.Decimal)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="op_Addition(System.Decimal,System.Decimal)" />
+ <Member Name="op_Decrement(System.Decimal)" />
+ <Member Name="op_Division(System.Decimal,System.Decimal)" />
+ <Member Name="op_Equality(System.Decimal,System.Decimal)" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Byte" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Char" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Double" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Int16" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Int32" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Int64" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.SByte" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.Single" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.UInt16" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.UInt32" />
+ <Member Name="op_Explicit(System.Decimal)" ReturnType="System.UInt64" />
+ <Member Name="op_Explicit(System.Double)" ReturnType="System.Decimal" />
+ <Member Name="op_Explicit(System.Single)" ReturnType="System.Decimal" />
+ <Member Name="op_GreaterThan(System.Decimal,System.Decimal)" />
+ <Member Name="op_GreaterThanOrEqual(System.Decimal,System.Decimal)" />
+ <Member Name="op_Implicit(System.Byte)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.Char)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.Int16)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.Int32)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.Int64)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.SByte)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.UInt16)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.UInt32)" ReturnType="System.Decimal" />
+ <Member Name="op_Implicit(System.UInt64)" ReturnType="System.Decimal" />
+ <Member Name="op_Increment(System.Decimal)" />
+ <Member Name="op_Inequality(System.Decimal,System.Decimal)" />
+ <Member Name="op_LessThan(System.Decimal,System.Decimal)" />
+ <Member Name="op_LessThanOrEqual(System.Decimal,System.Decimal)" />
+ <Member Name="op_Modulus(System.Decimal,System.Decimal)" />
+ <Member Name="op_Multiply(System.Decimal,System.Decimal)" />
+ <Member Name="op_Subtraction(System.Decimal,System.Decimal)" />
+ <Member Name="op_UnaryNegation(System.Decimal)" />
+ <Member Name="op_UnaryPlus(System.Decimal)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Decimal@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Decimal@)" />
+ <Member Name="Remainder(System.Decimal,System.Decimal)" />
+ <Member Name="Round(System.Decimal)" />
+ <Member Name="Round(System.Decimal,System.Int32)" />
+ <Member Name="Round(System.Decimal,System.Int32,System.MidpointRounding)" />
+ <Member Name="Round(System.Decimal,System.MidpointRounding)" />
+ <Member Name="Subtract(System.Decimal,System.Decimal)" />
+ <Member Name="ToByte(System.Decimal)" />
+ <Member Name="ToDouble(System.Decimal)" />
+ <Member Name="ToInt16(System.Decimal)" />
+ <Member Name="ToInt32(System.Decimal)" />
+ <Member Name="ToInt64(System.Decimal)" />
+ <Member Name="ToOACurrency(System.Decimal)" />
+ <Member Name="ToSByte(System.Decimal)" />
+ <Member Name="ToSingle(System.Decimal)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="ToUInt16(System.Decimal)" />
+ <Member Name="ToUInt32(System.Decimal)" />
+ <Member Name="ToUInt64(System.Decimal)" />
+ <Member Name="Truncate(System.Decimal)" />
+ </Type>
+ <Type Name="System.Delegate">
+ <Member Name="#ctor(System.Object,System.String)" />
+ <Member Name="#ctor(System.Type,System.String)" />
+ <Member Name="Clone" />
+ <Member Name="Combine(System.Delegate,System.Delegate)" />
+ <Member Name="Combine(System.Delegate[])" />
+ <Member Name="CombineImpl(System.Delegate)" />
+ <Member Name="CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo)" />
+ <Member Name="CreateDelegate(System.Type,System.Object,System.Reflection.MethodInfo,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type,System.Object,System.String)" />
+ <Member Name="CreateDelegate(System.Type,System.Object,System.String,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type,System.Object,System.String,System.Boolean,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type,System.Reflection.MethodInfo)" />
+ <Member Name="CreateDelegate(System.Type,System.Reflection.MethodInfo,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type,System.Type,System.String)" />
+ <Member Name="CreateDelegate(System.Type,System.Type,System.String,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type,System.Type,System.String,System.Boolean,System.Boolean)" />
+ <Member Name="DynamicInvoke(System.Object[])" />
+ <Member Name="DynamicInvokeImpl(System.Object[])" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Method" />
+ <Member Name="get_Target" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetInvocationList" />
+ <Member Name="GetMethodImpl" />
+ <Member Name="op_Equality(System.Delegate,System.Delegate)" />
+ <Member Name="op_Inequality(System.Delegate,System.Delegate)" />
+ <Member Name="Remove(System.Delegate,System.Delegate)" />
+ <Member Name="RemoveAll(System.Delegate,System.Delegate)" />
+ <Member Name="RemoveImpl(System.Delegate)" />
+ <Member MemberType="Property" Name="Target" />
+ <Member MemberType="Property" Name="Method" />
+ <Member Status="ImplRoot" Name="DelegateConstruct(System.Object,System.IntPtr)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.DelegateSerializationHolder">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Diagnostics.ConditionalAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_ConditionString" />
+ <Member MemberType="Property" Name="ConditionString" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggableAttribute">
+ <Member Name="#ctor(System.Boolean,System.Boolean)" />
+ <Member Name="#ctor(System.Diagnostics.DebuggableAttribute+DebuggingModes)" />
+ <Member Name="get_IsJITTrackingEnabled" />
+ <Member Name="get_IsJITOptimizerDisabled" />
+ <Member Name="get_DebuggingFlags" />
+ <Member MemberType="Property" Name="IsJITTrackingEnabled" />
+ <Member MemberType="Property" Name="IsJITOptimizerDisabled" />
+ <Member MemberType="Property" Name="DebuggingFlags" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggableAttribute+DebuggingModes">
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="DisableOptimizations" />
+ <Member MemberType="Field" Name="EnableEditAndContinue" />
+ <Member MemberType="Field" Name="IgnoreSymbolStoreSequencePoints" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Diagnostics.Debugger">
+ <Member Name="#ctor" />
+ <Member Name="Break" />
+ <Member Name="get_IsAttached" />
+ <Member Name="Launch" />
+ <Member Name="IsLogging" />
+ <Member Name="Log(System.Int32,System.String,System.String)" />
+ <Member MemberType="Property" Name="IsAttached" />
+ <Member Status="ImplRoot" Name="BreakCanThrow" /> <!-- EE -->
+ <Member Name="NotifyOfCrossThreadDependency" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerBrowsableAttribute">
+ <Member Name="#ctor(System.Diagnostics.DebuggerBrowsableState)" />
+ <Member Name="get_State" />
+ <Member MemberType="Property" Name="State" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerHiddenAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerNonUserCodeAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerStepThroughAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerDisplayAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Name" />
+ <Member Name="get_Target" />
+ <Member Name="get_TargetTypeName" />
+ <Member Name="get_Type" />
+ <Member Name="get_Value" />
+ <Member Name="set_Name(System.String)" />
+ <Member Name="set_Target(System.Type)" />
+ <Member Name="set_TargetTypeName(System.String)" />
+ <Member Name="set_Type(System.String)" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Target" />
+ <Member MemberType="Property" Name="TargetTypeName" />
+ <Member MemberType="Property" Name="Type" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Diagnostics.DebuggerTypeProxyAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_ProxyTypeName" />
+ <Member Name="get_Target" />
+ <Member Name="get_TargetTypeName" />
+ <Member Name="set_Target(System.Type)" />
+ <Member Name="set_TargetTypeName(System.String)" />
+ <Member MemberType="Property" Name="ProxyTypeName" />
+ <Member MemberType="Property" Name="Target" />
+ <Member MemberType="Property" Name="TargetTypeName" />
+ </Type>
+ <Type Name="System.DivideByZeroException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.DllNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Double">
+ <Member MemberType="Field" Name="Epsilon" />
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member MemberType="Field" Name="NaN" />
+ <Member MemberType="Field" Name="NegativeInfinity" />
+ <Member MemberType="Field" Name="PositiveInfinity" />
+ <Member Name="CompareTo(System.Double)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Double)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="IsInfinity(System.Double)" />
+ <Member Name="IsNaN(System.Double)" />
+ <Member Name="IsNegativeInfinity(System.Double)" />
+ <Member Name="IsPositiveInfinity(System.Double)" />
+ <Member Name="op_Equality(System.Double,System.Double)" />
+ <Member Name="op_GreaterThan(System.Double,System.Double)" />
+ <Member Name="op_GreaterThanOrEqual(System.Double,System.Double)" />
+ <Member Name="op_Inequality(System.Double,System.Double)" />
+ <Member Name="op_LessThan(System.Double,System.Double)" />
+ <Member Name="op_LessThanOrEqual(System.Double,System.Double)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Double@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Double@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.DuplicateWaitObjectException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ </Type>
+ <Type Name="System.EntryPointNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Enum">
+ <Member Name="#ctor" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Format(System.Type,System.Object,System.String)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetName(System.Type,System.Object)" />
+ <Member Name="GetNames(System.Type)" />
+ <Member Name="GetTypeCode" />
+ <Member Name="GetValues(System.Type)" />
+ <Member Name="GetUnderlyingType(System.Type)" />
+ <Member Name="HasFlag(System.Enum)" />
+ <Member Name="IsDefined(System.Type,System.Object)" />
+ <Member Name="Parse(System.Type,System.String)" />
+ <Member Name="Parse(System.Type,System.String,System.Boolean)" />
+ <Member Name="ToObject(System.Type,System.Byte)" />
+ <Member Name="ToObject(System.Type,System.Int16)" />
+ <Member Name="ToObject(System.Type,System.Int32)" />
+ <Member Name="ToObject(System.Type,System.Int64)" />
+ <Member Name="ToObject(System.Type,System.Object)" />
+ <Member Name="ToObject(System.Type,System.SByte)" />
+ <Member Name="ToObject(System.Type,System.UInt16)" />
+ <Member Name="ToObject(System.Type,System.UInt32)" />
+ <Member Name="ToObject(System.Type,System.UInt64)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse&lt;TEnum&gt;(System.String,TEnum@)" />
+ <Member Name="TryParse&lt;TEnum&gt;(System.String,System.Boolean,TEnum@)" />
+ </Type>
+ <Type Name="System.Environment">
+ <Member Name="get_CurrentManagedThreadId" />
+ <Member Name="get_MachineName" />
+ <Member Name="get_OSVersion" />
+ <Member Name="get_ProcessorCount" />
+ <Member Name="get_StackTrace" />
+ <Member Name="GetEnvironmentVariable(System.String)" />
+ <Member Name="GetEnvironmentVariables" />
+ <Member Name="GetCommandLineArgs" />
+ <Member Name="SetEnvironmentVariable(System.String,System.String)" />
+ <Member Name="ExpandEnvironmentVariables(System.String)" />
+ <Member MemberType="Property" Name="OSVersion" />
+ <Member MemberType="Property" Name="ProcessorCount" />
+ <Member MemberType="Property" Name="CurrentManagedThreadId" />
+ <Member MemberType="Property" Name="HasShutdownStarted" />
+ <Member MemberType="Property" Name="NewLine" />
+ <Member MemberType="Property" Name="StackTrace" />
+ <Member MemberType="Property" Name="TickCount" />
+ <Member MemberType="Property" Name="Version" />
+ <Member MemberType="Property" Name="ExitCode" />
+ <Member Status="ImplRoot" Name="GetResourceStringLocal(System.String)" />
+ <Member Status="ImplRoot" Name="SetCommandLineArgs(System.String[])" />
+ <Member Name="FailFast(System.String)" />
+ <Member Name="FailFast(System.String,System.Exception)" />
+ <Member Name="Exit(System.Int32)" />
+ </Type>
+ <Type Name="Internal.Runtime.Augments.EnvironmentAugments">
+ <Member MemberType="Property" Name="CurrentManagedThreadId" />
+ <Member MemberType="Property" Name="ExitCode" />
+ <Member MemberType="Property" Name="HasShutdownStarted" />
+ <Member MemberType="Property" Name="StackTrace" />
+ <Member MemberType="Property" Name="TickCount" />
+ <Member Name="get_CurrentManagedThreadId" />
+ <Member Name="get_ExitCode" />
+ <Member Name="set_ExitCode(System.Int32)" />
+ <Member Name="get_HasShutdownStarted" />
+ <Member Name="get_StackTrace" />
+ <Member Name="get_TickCount" />
+ <Member Name="Exit(System.Int32)" />
+ <Member Name="FailFast(System.String,System.Exception)" />
+ <Member Name="GetCommandLineArgs" />
+ </Type>
+ <Type Name="System.EventArgs">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.EventHandler">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.EventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,System.EventArgs)" />
+ </Type>
+ <Type Name="System.EventHandler&lt;TEventArgs&gt;">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,TEventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,TEventArgs)" />
+ </Type>
+ <Type Name="System.Exception">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_Data" />
+ <Member Name="get_HelpLink" />
+ <Member Name="get_HResult" />
+ <Member Name="get_InnerException" />
+ <Member Name="get_Message" />
+ <Member Name="get_StackTrace" />
+ <Member Name="get_Source" />
+ <Member Name="get_TargetSite" />
+ <Member Name="GetBaseException" />
+ <Member Name="GetType" />
+ <Member Name="set_HelpLink(System.String)" />
+ <Member Name="set_HResult(System.Int32)" />
+ <Member Name="set_Source(System.String)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Data" />
+ <Member MemberType="Property" Name="HelpLink" />
+ <Member MemberType="Property" Name="HResult" />
+ <Member MemberType="Property" Name="InnerException" />
+ <Member MemberType="Property" Name="Message" />
+ <Member MemberType="Property" Name="Source" />
+ <Member MemberType="Property" Name="StackTrace" />
+ <Member MemberType="Property" Name="TargetSite" />
+ <Member Status="ImplRoot" Name="InternalToString" />
+ <Member Status="ImplRoot" Name="InternalPreserveStackTrace" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_remoteStackIndex" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_exceptionMethod" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_exceptionMethodString" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_source" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_xptrs" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_xcode" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="_HResult" /> <!-- EE -->
+ <Member Status="ImplRoot" Name="AddExceptionDataForRestrictedErrorInfo(System.String,System.String,System.String,System.Object,System.Boolean)" Condition="FEATURE_COMINTEROP" />
+ <Member Status="ImplRoot" Name="TryGetRestrictedLanguageErrorObject(System.Object@)" Condition="FEATURE_COMINTEROP" />
+ </Type>
+ <Type Name="System.ExecutionEngineException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.FieldAccessException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.FlagsAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.FormatException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.FormattableString">
+ <Member Name="#ctor" />
+ <Member Name="get_Format" />
+ <Member MemberType="Property" Name="Format" />
+ <Member Name="GetArguments" />
+ <Member Name="get_ArgumentCount" />
+ <Member MemberType="Property" Name="ArgumentCount" />
+ <Member Name="GetArgument(System.Int32)" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="Invariant(System.FormattableString)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,T4,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,T4,T5,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,T4,T5,T6,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,T4,T5,T6,T7,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,T7,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6,T7)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Func&lt;T1,T2,T3,T4,T5,T6,T7,T8,TResult&gt;">
+ <Member Status="ApiRoot" Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(T1,T2,T3,T4,T5,T6,T7,T8,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(T1,T2,T3,T4,T5,T6,T7,T8)" />
+ </Type>
+ <Type Name="System.GC">
+ <Member Name="AddMemoryPressure(System.Int64)" />
+ <Member Name="CancelFullGCNotification" />
+ <Member Name="Collect" />
+ <Member Name="Collect(System.Int32)" />
+ <Member Name="Collect(System.Int32,System.GCCollectionMode)" />
+ <Member Name="Collect(System.Int32,System.GCCollectionMode,System.Boolean)" />
+ <Member Name="Collect(System.Int32,System.GCCollectionMode,System.Boolean,System.Boolean)" />
+ <Member Name="CollectionCount(System.Int32)" />
+ <Member Name="GetAllocatedBytesForCurrentThread" />
+ <Member Name="GetGeneration(System.Object)" />
+ <Member Name="GetGeneration(System.WeakReference)" />
+ <Member Name="get_MaxGeneration" />
+ <Member Name="GetTotalMemory(System.Boolean)" />
+ <Member Name="KeepAlive(System.Object)" />
+ <Member Name="RegisterForFullGCNotification(System.Int32,System.Int32)" />
+ <Member Name="RemoveMemoryPressure(System.Int64)" />
+ <Member Name="ReRegisterForFinalize(System.Object)" />
+ <Member Name="SuppressFinalize(System.Object)" />
+ <Member Name="WaitForFullGCApproach" />
+ <Member Name="WaitForFullGCApproach(System.Int32)" />
+ <Member Name="WaitForFullGCComplete" />
+ <Member Name="WaitForFullGCComplete(System.Int32)" />
+ <Member Name="WaitForPendingFinalizers" />
+ <Member MemberType="Property" Name="MaxGeneration" />
+ </Type>
+ <Type Name="System.GCNotificationStatus">
+ <Member MemberType="Field" Name="Canceled" />
+ <Member MemberType="Field" Name="Failed" />
+ <Member MemberType="Field" Name="NotApplicable" />
+ <Member MemberType="Field" Name="Succeeded" />
+ <Member MemberType="Field" Name="Timeout" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.Calendar">
+ <Member MemberType="Field" Name="CurrentEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddDays(System.DateTime,System.Int32)" />
+ <Member Name="AddHours(System.DateTime,System.Int32)" />
+ <Member Name="AddMilliseconds(System.DateTime,System.Double)" />
+ <Member Name="AddMinutes(System.DateTime,System.Int32)" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddSeconds(System.DateTime,System.Int32)" />
+ <Member Name="AddWeeks(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="Clone" />
+ <Member Name="get_Eras" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetHour(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32)" />
+ <Member Name="GetMilliseconds(System.DateTime)" />
+ <Member Name="GetMinute(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetSecond(System.DateTime)" />
+ <Member Name="GetWeekOfYear(System.DateTime,System.Globalization.CalendarWeekRule,System.DayOfWeek)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="ReadOnly(System.Globalization.Calendar)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN_ARABIC" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN_ME_FRENCH" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN_US" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN_XLIT_ENGLISH" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="CAL_GREGORIAN_XLIT_FRENCH" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ </Type>
+ <Type Name="System.Globalization.CalendarAlgorithmType">
+ <Member MemberType="Field" Name="LunarCalendar" />
+ <Member MemberType="Field" Name="LunisolarCalendar" />
+ <Member MemberType="Field" Name="SolarCalendar" />
+ <Member MemberType="Field" Name="Unknown" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.CalendarWeekRule">
+ <Member MemberType="Field" Name="FirstDay" />
+ <Member MemberType="Field" Name="FirstFourDayWeek" />
+ <Member MemberType="Field" Name="FirstFullWeek" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.CharUnicodeInfo">
+ <Member Name="GetDecimalDigitValue(System.Char)" />
+ <Member Name="GetDecimalDigitValue(System.String,System.Int32)" />
+ <Member Name="GetDigitValue(System.Char)" />
+ <Member Name="GetDigitValue(System.String,System.Int32)" />
+ <Member Name="GetNumericValue(System.Char)" />
+ <Member Name="GetNumericValue(System.String,System.Int32)" />
+ <Member Name="GetUnicodeCategory(System.Char)" />
+ <Member Name="GetUnicodeCategory(System.String,System.Int32)" />
+ </Type>
+ <Type Name="System.Globalization.ChineseLunisolarCalendar">
+ <Member MemberType="Field" Name="ChineseEra" />
+ <Member Name="#ctor" />
+ <Member Name="get_DaysInYearBeforeMinSupportedYear" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member MemberType="Property" Name="DaysInYearBeforeMinSupportedYear" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ </Type>
+ <Type Name="System.Globalization.CompareInfo">
+ <Member Name="Compare(System.String,System.Int32,System.Int32,System.String,System.Int32,System.Int32)" />
+ <Member Name="Compare(System.String,System.Int32,System.Int32,System.String,System.Int32,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="Compare(System.String,System.String)" />
+ <Member Name="Compare(System.String,System.String,System.Globalization.CompareOptions)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_LCID" />
+ <Member Name="get_Name" />
+ <Member Name="GetCompareInfo(System.Int32)" />
+ <Member Name="GetCompareInfo(System.Int32,System.Reflection.Assembly)" />
+ <Member Name="GetCompareInfo(System.String)" />
+ <Member Name="GetCompareInfo(System.String,System.Reflection.Assembly)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetHashCode(System.String,System.Globalization.CompareOptions)" />
+ <Member Name="GetSortKey(System.String)" />
+ <Member Name="GetSortKey(System.String,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.Char)" />
+ <Member Name="IndexOf(System.String,System.Char,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.Char,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.Char,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.Char,System.Int32,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.Char,System.Int32,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.String)" />
+ <Member Name="IndexOf(System.String,System.String,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.String,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.String,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="IndexOf(System.String,System.String,System.Int32,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.String,System.Int32,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="IsPrefix(System.String,System.String)" />
+ <Member Name="IsPrefix(System.String,System.String,System.Globalization.CompareOptions)" />
+ <Member Name="IsSortable(System.Char)" />
+ <Member Name="IsSortable(System.String)" />
+ <Member Name="IsSuffix(System.String,System.String)" />
+ <Member Name="IsSuffix(System.String,System.String,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.Char)" />
+ <Member Name="LastIndexOf(System.String,System.Char,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.Char,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.Char,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.Char,System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.Char,System.Int32,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.String)" />
+ <Member Name="LastIndexOf(System.String,System.String,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.String,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.String,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Name="LastIndexOf(System.String,System.String,System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.String,System.Int32,System.Int32,System.Globalization.CompareOptions)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(System.Object)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="LCID" />
+ <Member MemberType="Property" Name="Name" />
+ </Type>
+ <Type Name="System.Globalization.CompareOptions">
+ <Member MemberType="Field" Name="IgnoreCase" />
+ <Member MemberType="Field" Name="IgnoreKanaType" />
+ <Member MemberType="Field" Name="IgnoreNonSpace" />
+ <Member MemberType="Field" Name="IgnoreSymbols" />
+ <Member MemberType="Field" Name="IgnoreWidth" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Ordinal" />
+ <Member MemberType="Field" Name="OrdinalIgnoreCase" />
+ <Member MemberType="Field" Name="StringSort" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.CultureInfo">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Boolean)" />
+ <Member Name="ClearCachedData" />
+ <Member Name="Clone" />
+ <Member Name="CreateSpecificCulture(System.String)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Calendar" />
+ <Member Name="get_CompareInfo" />
+ <Member Name="get_CurrentCulture" />
+ <Member Name="get_CurrentUICulture" />
+ <Member Name="get_DefaultThreadCurrentCulture" />
+ <Member Name="get_DefaultThreadCurrentUICulture" />
+ <Member Name="get_DateTimeFormat" />
+ <Member Name="get_DisplayName" />
+ <Member Name="get_EnglishName" />
+ <Member Name="get_InstalledUICulture" />
+ <Member Name="get_InvariantCulture" />
+ <Member Name="get_IsNeutralCulture" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_LCID" />
+ <Member Name="get_Name" />
+ <Member Name="get_NativeName" />
+ <Member Name="get_NumberFormat" />
+ <Member Name="get_OptionalCalendars" />
+ <Member Name="get_Parent" />
+ <Member Name="get_TextInfo" />
+ <Member Name="get_ThreeLetterISOLanguageName" />
+ <Member Name="get_ThreeLetterWindowsLanguageName" />
+ <Member Name="get_TwoLetterISOLanguageName" />
+ <Member Name="get_UseUserOverride" />
+ <Member Name="GetCultureInfo(System.Int32)" />
+ <Member Name="GetCultureInfo(System.String)" />
+ <Member Name="GetCultureInfo(System.String,System.String)" />
+ <Member Name="GetCultureInfoByIetfLanguageTag(System.String)" />
+ <Member Name="GetCultures(System.Globalization.CultureTypes)" />
+ <Member Name="GetFormat(System.Type)" />
+ <Member Name="GetHashCode" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ReadOnly(System.Globalization.CultureInfo)" />
+ <Member Name="set_CurrentCulture(System.Globalization.CultureInfo)" />
+ <Member Name="set_CurrentUICulture(System.Globalization.CultureInfo)" />
+ <Member Name="set_DateTimeFormat(System.Globalization.DateTimeFormatInfo)" />
+ <Member Name="set_DefaultThreadCurrentCulture(System.Globalization.CultureInfo)" />
+ <Member Name="set_DefaultThreadCurrentUICulture(System.Globalization.CultureInfo)" />
+ <Member Name="set_NumberFormat(System.Globalization.NumberFormatInfo)" />
+ <Member Name="ToString" />
+ <Member Status="ImplRoot" Name="get_SortName" />
+ <Member MemberType="Property" Name="Calendar" />
+ <Member MemberType="Property" Name="CompareInfo" />
+ <Member MemberType="Property" Name="CurrentCulture" />
+ <Member MemberType="Property" Name="CurrentUICulture" />
+ <Member MemberType="Property" Name="DateTimeFormat" />
+ <Member MemberType="Property" Name="DefaultThreadCurrentCulture" />
+ <Member MemberType="Property" Name="DefaultThreadCurrentUICulture"/>
+ <Member MemberType="Property" Name="DisplayName" />
+ <Member MemberType="Property" Name="EnglishName" />
+ <Member MemberType="Property" Name="InstalledUICulture" />
+ <Member MemberType="Property" Name="InvariantCulture" />
+ <Member MemberType="Property" Name="IsNeutralCulture" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="LCID" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="NativeName" />
+ <Member MemberType="Property" Name="NumberFormat" />
+ <Member MemberType="Property" Name="OptionalCalendars" />
+ <Member MemberType="Property" Name="Parent" />
+ <Member MemberType="Property" Name="TextInfo" />
+ <Member MemberType="Property" Name="ThreeLetterISOLanguageName" />
+ <Member MemberType="Property" Name="ThreeLetterWindowsLanguageName" />
+ <Member MemberType="Property" Name="TwoLetterISOLanguageName" />
+ <Member MemberType="Property" Name="UseUserOverride" />
+ <Member Status="ImplRoot" MemberType="Property" Name="SortName" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_parent" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_useUserOverride" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ </Type>
+ <Type Name="System.Globalization.CultureNotFoundException">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Int32,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Int32,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_InvalidCultureId" />
+ <Member Name="get_InvalidCultureName" />
+ <Member Name="get_Message" />
+ <Member Name="GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Property" Name="InvalidCultureId" />
+ <Member MemberType="Property" Name="InvalidCultureName" />
+ <Member MemberType="Property" Name="Message" />
+ </Type>
+ <Type Name="System.Globalization.CultureTypes">
+ <Member MemberType="Field" Name="AllCultures" />
+ <Member MemberType="Field" Name="FrameworkCultures" />
+ <Member MemberType="Field" Name="InstalledWin32Cultures" />
+ <Member MemberType="Field" Name="NeutralCultures" />
+ <Member MemberType="Field" Name="ReplacementCultures" />
+ <Member MemberType="Field" Name="SpecificCultures" />
+ <Member MemberType="Field" Name="UserCustomCulture" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="WindowsOnlyCultures" />
+ </Type>
+ <Type Name="System.Globalization.DateTimeFormatInfo">
+ <Member Name="#ctor" />
+ <Member Name="Clone" />
+ <Member Name="get_AbbreviatedDayNames" />
+ <Member Name="get_AbbreviatedMonthGenitiveNames" />
+ <Member Name="get_AbbreviatedMonthNames" />
+ <Member Name="get_AMDesignator" />
+ <Member Name="get_Calendar" />
+ <Member Name="get_CalendarWeekRule" />
+ <Member Name="get_CurrentInfo" />
+ <Member Name="get_DateSeparator" />
+ <Member Name="get_DayNames" />
+ <Member Name="get_FirstDayOfWeek" />
+ <Member Name="get_FullDateTimePattern" />
+ <Member Name="get_InvariantInfo" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_LongDatePattern" />
+ <Member Name="get_LongTimePattern" />
+ <Member Name="get_MonthDayPattern" />
+ <Member Name="get_MonthGenitiveNames" />
+ <Member Name="get_MonthNames" />
+ <Member Name="get_NativeCalendarName" />
+ <Member Name="get_PMDesignator" />
+ <Member Name="get_RFC1123Pattern" />
+ <Member Name="get_ShortDatePattern" />
+ <Member Name="get_ShortestDayNames" />
+ <Member Name="get_ShortTimePattern" />
+ <Member Name="get_SortableDateTimePattern" />
+ <Member Name="get_TimeSeparator" />
+ <Member Name="get_UniversalSortableDateTimePattern" />
+ <Member Name="get_YearMonthPattern" />
+ <Member Name="GetAbbreviatedDayName(System.DayOfWeek)" />
+ <Member Name="GetAbbreviatedEraName(System.Int32)" />
+ <Member Name="GetAbbreviatedMonthName(System.Int32)" />
+ <Member Name="GetAllDateTimePatterns" />
+ <Member Name="GetAllDateTimePatterns(System.Char)" />
+ <Member Name="GetDayName(System.DayOfWeek)" />
+ <Member Name="GetEra(System.String)" />
+ <Member Name="GetEraName(System.Int32)" />
+ <Member Name="GetFormat(System.Type)" />
+ <Member Name="GetInstance(System.IFormatProvider)" />
+ <Member Name="GetMonthName(System.Int32)" />
+ <Member Name="GetShortestDayName(System.DayOfWeek)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ReadOnly(System.Globalization.DateTimeFormatInfo)" />
+ <Member Name="set_AbbreviatedDayNames(System.String[])" />
+ <Member Name="set_AbbreviatedMonthGenitiveNames(System.String[])" />
+ <Member Name="set_AbbreviatedMonthNames(System.String[])" />
+ <Member Name="set_AMDesignator(System.String)" />
+ <Member Name="set_Calendar(System.Globalization.Calendar)" />
+ <Member Name="set_CalendarWeekRule(System.Globalization.CalendarWeekRule)" />
+ <Member Name="set_DateSeparator(System.String)" />
+ <Member Name="set_DayNames(System.String[])" />
+ <Member Name="set_FirstDayOfWeek(System.DayOfWeek)" />
+ <Member Name="set_FullDateTimePattern(System.String)" />
+ <Member Name="set_LongDatePattern(System.String)" />
+ <Member Name="set_LongTimePattern(System.String)" />
+ <Member Name="set_MonthDayPattern(System.String)" />
+ <Member Name="set_MonthGenitiveNames(System.String[])" />
+ <Member Name="set_MonthNames(System.String[])" />
+ <Member Name="set_PMDesignator(System.String)" />
+ <Member Name="set_ShortDatePattern(System.String)" />
+ <Member Name="set_ShortestDayNames(System.String[])" />
+ <Member Name="set_ShortTimePattern(System.String)" />
+ <Member Name="set_TimeSeparator(System.String)" />
+ <Member Name="set_YearMonthPattern(System.String)" />
+ <Member Name="SetAllDateTimePatterns(System.String[],System.Char)" />
+ <Member MemberType="Property" Name="AbbreviatedDayNames" />
+ <Member MemberType="Property" Name="AbbreviatedMonthGenitiveNames" />
+ <Member MemberType="Property" Name="AbbreviatedMonthNames" />
+ <Member MemberType="Property" Name="AMDesignator" />
+ <Member MemberType="Property" Name="Calendar" />
+ <Member MemberType="Property" Name="CalendarWeekRule" />
+ <Member MemberType="Property" Name="CurrentInfo" />
+ <Member MemberType="Property" Name="DateSeparator" />
+ <Member MemberType="Property" Name="DayNames" />
+ <Member MemberType="Property" Name="FirstDayOfWeek" />
+ <Member MemberType="Property" Name="FullDateTimePattern" />
+ <Member MemberType="Property" Name="InvariantInfo" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="LongDatePattern" />
+ <Member MemberType="Property" Name="LongTimePattern" />
+ <Member MemberType="Property" Name="MonthDayPattern" />
+ <Member MemberType="Property" Name="MonthGenitiveNames" />
+ <Member MemberType="Property" Name="MonthNames" />
+ <Member MemberType="Property" Name="NativeCalendarName" />
+ <Member MemberType="Property" Name="PMDesignator" />
+ <Member MemberType="Property" Name="RFC1123Pattern" />
+ <Member MemberType="Property" Name="ShortDatePattern" />
+ <Member MemberType="Property" Name="ShortestDayNames" />
+ <Member MemberType="Property" Name="ShortTimePattern" />
+ <Member MemberType="Property" Name="SortableDateTimePattern" />
+ <Member MemberType="Property" Name="TimeSeparator" />
+ <Member MemberType="Property" Name="UniversalSortableDateTimePattern" />
+ <Member MemberType="Property" Name="YearMonthPattern" />
+ </Type>
+ <Type Name="System.Globalization.DateTimeStyles">
+ <Member MemberType="Field" Name="AdjustToUniversal" />
+ <Member MemberType="Field" Name="AllowInnerWhite" />
+ <Member MemberType="Field" Name="AllowLeadingWhite" />
+ <Member MemberType="Field" Name="AllowTrailingWhite" />
+ <Member MemberType="Field" Name="AllowWhiteSpaces" />
+ <Member MemberType="Field" Name="AssumeLocal" />
+ <Member MemberType="Field" Name="AssumeUniversal" />
+ <Member MemberType="Field" Name="NoCurrentDateDefault" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="RoundtripKind" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.DaylightTime">
+ <Member Name="#ctor(System.DateTime,System.DateTime,System.TimeSpan)" />
+ <Member Name="get_Delta" />
+ <Member Name="get_End" />
+ <Member Name="get_Start" />
+ <Member MemberType="Property" Name="Delta" />
+ <Member MemberType="Property" Name="End" />
+ <Member MemberType="Property" Name="Start" />
+ </Type>
+ <Type Name="System.Globalization.DigitShapes">
+ <Member MemberType="Field" Name="Context" />
+ <Member MemberType="Field" Name="NativeNational" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.PersianCalendar">
+ <Member MemberType="Field" Name="PersianEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+
+ <Type Name="System.Globalization.TimeSpanStyles">
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="AssumeNegative" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.EastAsianLunisolarCalendar">
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetCelestialStem(System.Int32)" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetSexagenaryYear(System.DateTime)" />
+ <Member Name="GetTerrestrialBranch(System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION"/>
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.GregorianCalendar">
+ <Member MemberType="Field" Name="ADEra" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Globalization.GregorianCalendarTypes)" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_CalendarType" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="set_CalendarType(System.Globalization.GregorianCalendarTypes)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="CalendarType" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.GregorianCalendarTypes">
+ <Member MemberType="Field" Name="Arabic" />
+ <Member MemberType="Field" Name="Localized" />
+ <Member MemberType="Field" Name="MiddleEastFrench" />
+ <Member MemberType="Field" Name="TransliteratedEnglish" />
+ <Member MemberType="Field" Name="TransliteratedFrench" />
+ <Member MemberType="Field" Name="USEnglish" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.JapaneseCalendar">
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetWeekOfYear(System.DateTime,System.Globalization.CalendarWeekRule,System.DayOfWeek)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.JapaneseLunisolarCalendar">
+ <Member MemberType="Field" Name="JapaneseEra" />
+ <Member Name="#ctor" />
+ <Member Name="get_DaysInYearBeforeMinSupportedYear" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member MemberType="Property" Name="DaysInYearBeforeMinSupportedYear" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ </Type>
+ <Type Name="System.Globalization.JulianCalendar">
+ <Member MemberType="Field" Name="JulianEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="AlgorithmType" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.HebrewCalendar">
+ <Member MemberType="Field" Name="HebrewEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.HijriCalendar">
+ <Member MemberType="Field" Name="HijriEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_HijriAdjustment" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_HijriAdjustment(System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="HijriAdjustment" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.IdnMapping">
+ <Member Name="#ctor" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_AllowUnassigned" />
+ <Member Name="get_UseStd3AsciiRules" />
+ <Member Name="GetAscii(System.String)" />
+ <Member Name="GetAscii(System.String,System.Int32)" />
+ <Member Name="GetAscii(System.String,System.Int32,System.Int32)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetUnicode(System.String)" />
+ <Member Name="GetUnicode(System.String,System.Int32)" />
+ <Member Name="GetUnicode(System.String,System.Int32,System.Int32)" />
+ <Member Name="set_AllowUnassigned(System.Boolean)" />
+ <Member Name="set_UseStd3AsciiRules(System.Boolean)" />
+ <Member MemberType="Property" Name="AllowUnassigned" />
+ <Member MemberType="Property" Name="UseStd3AsciiRules" />
+ </Type>
+ <Type Name="System.Globalization.KoreanCalendar">
+ <Member MemberType="Field" Name="KoreanEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetWeekOfYear(System.DateTime,System.Globalization.CalendarWeekRule,System.DayOfWeek)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.KoreanLunisolarCalendar">
+ <Member MemberType="Field" Name="GregorianEra" />
+ <Member Name="#ctor" />
+ <Member Name="get_DaysInYearBeforeMinSupportedYear" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member MemberType="Property" Name="DaysInYearBeforeMinSupportedYear" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ </Type>
+ <Type Name="System.Globalization.UmAlQuraCalendar">
+ <Member MemberType="Field" Name="UmAlQuraEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetLeapMonth(System.Int32,System.Int32)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.NumberFormatInfo">
+ <Member Name="#ctor" />
+ <Member Name="Clone" />
+ <Member Name="get_CurrencyDecimalDigits" />
+ <Member Name="get_CurrencyDecimalSeparator" />
+ <Member Name="get_CurrencyGroupSeparator" />
+ <Member Name="get_CurrencyGroupSizes" />
+ <Member Name="get_CurrencyNegativePattern" />
+ <Member Name="get_CurrencyPositivePattern" />
+ <Member Name="get_CurrencySymbol" />
+ <Member Name="get_CurrentInfo" />
+ <Member Name="get_DigitSubstitution" />
+ <Member Name="get_InvariantInfo" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_NaNSymbol" />
+ <Member Name="get_NativeDigits" />
+ <Member Name="get_NegativeInfinitySymbol" />
+ <Member Name="get_NegativeSign" />
+ <Member Name="get_NumberDecimalDigits" />
+ <Member Name="get_NumberDecimalSeparator" />
+ <Member Name="get_NumberGroupSeparator" />
+ <Member Name="get_NumberGroupSizes" />
+ <Member Name="get_NumberNegativePattern" />
+ <Member Name="get_PercentDecimalDigits" />
+ <Member Name="get_PercentDecimalSeparator" />
+ <Member Name="get_PercentGroupSeparator" />
+ <Member Name="get_PercentGroupSizes" />
+ <Member Name="get_PercentNegativePattern" />
+ <Member Name="get_PercentPositivePattern" />
+ <Member Name="get_PercentSymbol" />
+ <Member Name="get_PerMilleSymbol" />
+ <Member Name="get_PositiveInfinitySymbol" />
+ <Member Name="get_PositiveSign" />
+ <Member Name="GetFormat(System.Type)" />
+ <Member Name="GetInstance(System.IFormatProvider)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ReadOnly(System.Globalization.NumberFormatInfo)" />
+ <Member Name="set_CurrencyDecimalDigits(System.Int32)" />
+ <Member Name="set_CurrencyDecimalSeparator(System.String)" />
+ <Member Name="set_CurrencyGroupSeparator(System.String)" />
+ <Member Name="set_CurrencyGroupSizes(System.Int32[])" />
+ <Member Name="set_CurrencyNegativePattern(System.Int32)" />
+ <Member Name="set_CurrencyPositivePattern(System.Int32)" />
+ <Member Name="set_CurrencySymbol(System.String)" />
+ <Member Name="set_DigitSubstitution(System.Globalization.DigitShapes)" />
+ <Member Name="set_NaNSymbol(System.String)" />
+ <Member Name="set_NativeDigits(System.String[])" />
+ <Member Name="set_NegativeInfinitySymbol(System.String)" />
+ <Member Name="set_NegativeSign(System.String)" />
+ <Member Name="set_NumberDecimalDigits(System.Int32)" />
+ <Member Name="set_NumberDecimalSeparator(System.String)" />
+ <Member Name="set_NumberGroupSeparator(System.String)" />
+ <Member Name="set_NumberGroupSizes(System.Int32[])" />
+ <Member Name="set_NumberNegativePattern(System.Int32)" />
+ <Member Name="set_PercentDecimalDigits(System.Int32)" />
+ <Member Name="set_PercentDecimalSeparator(System.String)" />
+ <Member Name="set_PercentGroupSeparator(System.String)" />
+ <Member Name="set_PercentGroupSizes(System.Int32[])" />
+ <Member Name="set_PercentNegativePattern(System.Int32)" />
+ <Member Name="set_PercentPositivePattern(System.Int32)" />
+ <Member Name="set_PercentSymbol(System.String)" />
+ <Member Name="set_PerMilleSymbol(System.String)" />
+ <Member Name="set_PositiveInfinitySymbol(System.String)" />
+ <Member Name="set_PositiveSign(System.String)" />
+ <Member MemberType="Property" Name="CurrencyDecimalDigits" />
+ <Member MemberType="Property" Name="CurrencyDecimalSeparator" />
+ <Member MemberType="Property" Name="CurrencyGroupSeparator" />
+ <Member MemberType="Property" Name="CurrencyGroupSizes" />
+ <Member MemberType="Property" Name="CurrencyNegativePattern" />
+ <Member MemberType="Property" Name="CurrencyPositivePattern" />
+ <Member MemberType="Property" Name="CurrencySymbol" />
+ <Member MemberType="Property" Name="CurrentInfo" />
+ <Member MemberType="Property" Name="DigitSubstitution" />
+ <Member MemberType="Property" Name="InvariantInfo" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="NaNSymbol" />
+ <Member MemberType="Property" Name="NativeDigits" />
+ <Member MemberType="Property" Name="NegativeInfinitySymbol" />
+ <Member MemberType="Property" Name="NegativeSign" />
+ <Member MemberType="Property" Name="NumberDecimalDigits" />
+ <Member MemberType="Property" Name="NumberDecimalSeparator" />
+ <Member MemberType="Property" Name="NumberGroupSeparator" />
+ <Member MemberType="Property" Name="NumberGroupSizes" />
+ <Member MemberType="Property" Name="NumberNegativePattern" />
+ <Member MemberType="Property" Name="PercentDecimalDigits" />
+ <Member MemberType="Property" Name="PercentDecimalSeparator" />
+ <Member MemberType="Property" Name="PercentGroupSeparator" />
+ <Member MemberType="Property" Name="PercentGroupSizes" />
+ <Member MemberType="Property" Name="PercentNegativePattern" />
+ <Member MemberType="Property" Name="PercentPositivePattern" />
+ <Member MemberType="Property" Name="PercentSymbol" />
+ <Member MemberType="Property" Name="PerMilleSymbol" />
+ <Member MemberType="Property" Name="PositiveInfinitySymbol" />
+ <Member MemberType="Property" Name="PositiveSign" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_dataItem" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_useUserOverride" Condition="not FEATURE_COREFX_GLOBALIZATION" />
+ </Type>
+ <Type Name="System.Globalization.NumberStyles">
+ <Member MemberType="Field" Name="AllowCurrencySymbol" />
+ <Member MemberType="Field" Name="AllowDecimalPoint" />
+ <Member MemberType="Field" Name="AllowExponent" />
+ <Member MemberType="Field" Name="AllowHexSpecifier" />
+ <Member MemberType="Field" Name="AllowLeadingSign" />
+ <Member MemberType="Field" Name="AllowLeadingWhite" />
+ <Member MemberType="Field" Name="AllowParentheses" />
+ <Member MemberType="Field" Name="AllowThousands" />
+ <Member MemberType="Field" Name="AllowTrailingSign" />
+ <Member MemberType="Field" Name="AllowTrailingWhite" />
+ <Member MemberType="Field" Name="Any" />
+ <Member MemberType="Field" Name="Currency" />
+ <Member MemberType="Field" Name="Float" />
+ <Member MemberType="Field" Name="HexNumber" />
+ <Member MemberType="Field" Name="Integer" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Number" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Globalization.RegionInfo">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_CurrencySymbol" />
+ <Member Name="get_CurrencyEnglishName" />
+ <Member Name="get_CurrencyNativeName" />
+ <Member Name="get_CurrentRegion" />
+ <Member Name="get_DisplayName" />
+ <Member Name="get_EnglishName" />
+ <Member Name="get_GeoId" />
+ <Member Name="get_IsMetric" />
+ <Member Name="get_ISOCurrencySymbol" />
+ <Member Name="get_Name" />
+ <Member Name="get_NativeName" />
+ <Member Name="get_ThreeLetterISORegionName" />
+ <Member Name="get_ThreeLetterWindowsRegionName" />
+ <Member Name="get_TwoLetterISORegionName" />
+ <Member Name="GetHashCode" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="CurrencySymbol" />
+ <Member MemberType="Property" Name="CurrencyEnglishName" />
+ <Member MemberType="Property" Name="CurrencyNativeName" />
+ <Member MemberType="Property" Name="CurrentRegion" />
+ <Member MemberType="Property" Name="DisplayName" />
+ <Member MemberType="Property" Name="EnglishName" />
+ <Member MemberType="Property" Name="GeoId" />
+ <Member MemberType="Property" Name="IsMetric" />
+ <Member MemberType="Property" Name="ISOCurrencySymbol" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="NativeName" />
+ <Member MemberType="Property" Name="ThreeLetterISORegionName" />
+ <Member MemberType="Property" Name="ThreeLetterWindowsRegionName" />
+ <Member MemberType="Property" Name="TwoLetterISORegionName" />
+ </Type>
+ <Type Name="System.Globalization.SortKey">
+ <Member Name="Compare(System.Globalization.SortKey,System.Globalization.SortKey)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_KeyData" />
+ <Member Name="get_OriginalString" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="KeyData" />
+ <Member MemberType="Property" Name="OriginalString" />
+ </Type>
+ <Type Name="System.Globalization.SortVersion">
+ <Member Name="#ctor(System.Int32,System.Guid)" />
+ <Member Name="Equals(System.Globalization.SortVersion)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_FullVersion" />
+ <Member Name="get_SortId" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Globalization.SortVersion,System.Globalization.SortVersion)" />
+ <Member Name="op_Inequality(System.Globalization.SortVersion,System.Globalization.SortVersion)" />
+ <Member MemberType="Property" Name="FullVersion" />
+ <Member MemberType="Property" Name="SortId" />
+ </Type>
+ <Type Name="System.Globalization.StringInfo">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_LengthInTextElements" />
+ <Member Name="get_String" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetNextTextElement(System.String)" />
+ <Member Name="GetNextTextElement(System.String,System.Int32)" />
+ <Member Name="GetTextElementEnumerator(System.String)" />
+ <Member Name="GetTextElementEnumerator(System.String,System.Int32)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ParseCombiningCharacters(System.String)" />
+ <Member Name="set_String(System.String)" />
+ <Member Name="SubstringByTextElements(System.Int32)" />
+ <Member Name="SubstringByTextElements(System.Int32,System.Int32)" />
+ <Member MemberType="Property" Name="LengthInTextElements" />
+ <Member MemberType="Property" Name="String" />
+ </Type>
+ <Type Name="System.Globalization.TaiwanCalendar">
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetWeekOfYear(System.DateTime,System.Globalization.CalendarWeekRule,System.DayOfWeek)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.TaiwanLunisolarCalendar">
+ <Member Name="#ctor" />
+ <Member Name="get_DaysInYearBeforeMinSupportedYear" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member MemberType="Property" Name="DaysInYearBeforeMinSupportedYear" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ </Type>
+ <Type Name="System.Globalization.TextElementEnumerator">
+ <Member Name="get_Current" />
+ <Member Name="get_ElementIndex" />
+ <Member Name="GetTextElement" />
+ <Member Name="MoveNext" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Current" />
+ <Member MemberType="Property" Name="ElementIndex" />
+ </Type>
+ <Type Name="System.Globalization.TextInfo">
+ <Member Name="Clone" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_ANSICodePage" />
+ <Member Name="get_CultureName" />
+ <Member Name="get_EBCDICCodePage" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_IsRightToLeft" />
+ <Member Name="get_LCID" />
+ <Member Name="get_ListSeparator" />
+ <Member Name="get_MacCodePage" />
+ <Member Name="get_OEMCodePage" />
+ <Member Name="GetHashCode" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(System.Object)" />
+ <Member Name="ReadOnly(System.Globalization.TextInfo)" />
+ <Member Name="set_ListSeparator(System.String)" />
+ <Member Name="ToLower(System.Char)" />
+ <Member Name="ToLower(System.String)" />
+ <Member Name="ToString" />
+ <Member Name="ToTitleCase(System.String)" />
+ <Member Name="ToUpper(System.Char)" />
+ <Member Name="ToUpper(System.String)" />
+ <Member MemberType="Property" Name="ANSICodePage" />
+ <Member MemberType="Property" Name="CultureName" />
+ <Member MemberType="Property" Name="EBCDICCodePage" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="IsRightToLeft" />
+ <Member MemberType="Property" Name="LCID" />
+ <Member MemberType="Property" Name="ListSeparator" />
+ <Member MemberType="Property" Name="MacCodePage" />
+ <Member MemberType="Property" Name="OEMCodePage" />
+ </Type>
+ <Type Name="System.Globalization.ThaiBuddhistCalendar">
+ <Member MemberType="Field" Name="ThaiBuddhistEra" />
+ <Member Name="#ctor" />
+ <Member Name="AddMonths(System.DateTime,System.Int32)" />
+ <Member Name="AddYears(System.DateTime,System.Int32)" />
+ <Member Name="get_Eras" />
+ <Member Name="get_MaxSupportedDateTime" />
+ <Member Name="get_MinSupportedDateTime" />
+ <Member Name="get_TwoDigitYearMax" />
+ <Member Name="GetDayOfMonth(System.DateTime)" />
+ <Member Name="GetDayOfWeek(System.DateTime)" />
+ <Member Name="GetDayOfYear(System.DateTime)" />
+ <Member Name="GetDaysInMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="GetDaysInYear(System.Int32,System.Int32)" />
+ <Member Name="GetEra(System.DateTime)" />
+ <Member Name="GetMonth(System.DateTime)" />
+ <Member Name="GetMonthsInYear(System.Int32,System.Int32)" />
+ <Member Name="GetWeekOfYear(System.DateTime,System.Globalization.CalendarWeekRule,System.DayOfWeek)" />
+ <Member Name="GetYear(System.DateTime)" />
+ <Member Name="IsLeapDay(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapMonth(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="IsLeapYear(System.Int32,System.Int32)" />
+ <Member Name="set_TwoDigitYearMax(System.Int32)" />
+ <Member Name="ToDateTime(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="ToFourDigitYear(System.Int32)" />
+ <Member MemberType="Property" Name="Eras" />
+ <Member MemberType="Property" Name="MaxSupportedDateTime" />
+ <Member MemberType="Property" Name="MinSupportedDateTime" />
+ <Member MemberType="Property" Name="TwoDigitYearMax" />
+ </Type>
+ <Type Name="System.Globalization.UnicodeCategory">
+ <Member MemberType="Field" Name="ClosePunctuation" />
+ <Member MemberType="Field" Name="ConnectorPunctuation" />
+ <Member MemberType="Field" Name="Control" />
+ <Member MemberType="Field" Name="CurrencySymbol" />
+ <Member MemberType="Field" Name="DashPunctuation" />
+ <Member MemberType="Field" Name="DecimalDigitNumber" />
+ <Member MemberType="Field" Name="EnclosingMark" />
+ <Member MemberType="Field" Name="FinalQuotePunctuation" />
+ <Member MemberType="Field" Name="Format" />
+ <Member MemberType="Field" Name="InitialQuotePunctuation" />
+ <Member MemberType="Field" Name="LetterNumber" />
+ <Member MemberType="Field" Name="LineSeparator" />
+ <Member MemberType="Field" Name="LowercaseLetter" />
+ <Member MemberType="Field" Name="MathSymbol" />
+ <Member MemberType="Field" Name="ModifierLetter" />
+ <Member MemberType="Field" Name="ModifierSymbol" />
+ <Member MemberType="Field" Name="NonSpacingMark" />
+ <Member MemberType="Field" Name="OpenPunctuation" />
+ <Member MemberType="Field" Name="OtherLetter" />
+ <Member MemberType="Field" Name="OtherNotAssigned" />
+ <Member MemberType="Field" Name="OtherNumber" />
+ <Member MemberType="Field" Name="OtherPunctuation" />
+ <Member MemberType="Field" Name="OtherSymbol" />
+ <Member MemberType="Field" Name="ParagraphSeparator" />
+ <Member MemberType="Field" Name="PrivateUse" />
+ <Member MemberType="Field" Name="SpaceSeparator" />
+ <Member MemberType="Field" Name="SpacingCombiningMark" />
+ <Member MemberType="Field" Name="Surrogate" />
+ <Member MemberType="Field" Name="TitlecaseLetter" />
+ <Member MemberType="Field" Name="UppercaseLetter" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Guid">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="#ctor(System.Byte[])" />
+ <Member Name="#ctor(System.UInt32,System.UInt16,System.UInt16,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)" />
+ <Member Name="#ctor(System.Int32,System.Int16,System.Int16,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte)" />
+ <Member Name="#ctor(System.Int32,System.Int16,System.Int16,System.Byte[])" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="CompareTo(System.Guid)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Guid)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="NewGuid" />
+ <Member Name="op_Equality(System.Guid,System.Guid)" />
+ <Member Name="op_Inequality(System.Guid,System.Guid)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="ParseExact(System.String,System.String)" />
+ <Member Name="ToByteArray" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Guid@)" />
+ <Member Name="TryParseExact(System.String,System.String,System.Guid@)" />
+ </Type>
+ <Type Name="System.IAsyncResult">
+ <Member Name="get_AsyncState" />
+ <Member Name="get_AsyncWaitHandle" />
+ <Member Name="get_CompletedSynchronously" />
+ <Member Name="get_IsCompleted" />
+ <Member MemberType="Property" Name="AsyncState" />
+ <Member MemberType="Property" Name="AsyncWaitHandle" />
+ <Member MemberType="Property" Name="CompletedSynchronously" />
+ <Member MemberType="Property" Name="IsCompleted" />
+ </Type>
+ <Type Name="System.ICloneable">
+ <Member Name="Clone" />
+ </Type>
+ <Type Name="System.IComparable">
+ <Member Name="CompareTo(System.Object)" />
+ </Type>
+ <Type Name="System.IComparable&lt;T&gt;">
+ <Member Name="CompareTo(T)" />
+ </Type>
+ <Type Name="System.IConvertible">
+ <Member Name="GetTypeCode" />
+ <Member Name="ToBoolean(System.IFormatProvider)" />
+ <Member Name="ToByte(System.IFormatProvider)" />
+ <Member Name="ToChar(System.IFormatProvider)" />
+ <Member Name="ToDateTime(System.IFormatProvider)" />
+ <Member Name="ToDecimal(System.IFormatProvider)" />
+ <Member Name="ToDouble(System.IFormatProvider)" />
+ <Member Name="ToInt16(System.IFormatProvider)" />
+ <Member Name="ToInt32(System.IFormatProvider)" />
+ <Member Name="ToInt64(System.IFormatProvider)" />
+ <Member Name="ToSByte(System.IFormatProvider)" />
+ <Member Name="ToSingle(System.IFormatProvider)" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToType(System.Type,System.IFormatProvider)" />
+ <Member Name="ToUInt16(System.IFormatProvider)" />
+ <Member Name="ToUInt32(System.IFormatProvider)" />
+ <Member Name="ToUInt64(System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.ICustomFormatter">
+ <Member Name="Format(System.String,System.Object,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.IDisposable">
+ <Member Name="Dispose" />
+ </Type>
+ <Type Name="System.IEquatable&lt;T&gt;">
+ <Member Name="Equals(T)" />
+ </Type>
+ <Type Name="System.IFormatProvider">
+ <Member Name="GetFormat(System.Type)" />
+ </Type>
+ <Type Name="System.IFormattable">
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.IndexOutOfRangeException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.InsufficientExecutionStackException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Internal">
+ <Member Status="ImplRoot" Name="CommonlyUsedGenericInstantiations" />
+ <Member Status="ImplRoot" Name="CommonlyUsedWinRTRedirectedInterfaceStubs" Condition="FEATURE_COMINTEROP" />
+ </Type>
+ <Type Name="System.InsufficientMemoryException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ </Type>
+ <Type Name="System.Int16">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Int16)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Int16)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Int16@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int16@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.Int32">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Int32)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Int32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Int32@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int32@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.Int64">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Int64)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="Equals(System.Int64)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Int64@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int64@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.IntPtr">
+ <Member MemberType="Field" Name="Zero" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int64)" />
+ <Member Name="#ctor(System.Void*)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Add(System.IntPtr,System.Int32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Size" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Addition(System.IntPtr,System.Int32)" />
+ <Member Name="op_Equality(System.IntPtr,System.IntPtr)" />
+ <Member Name="op_Explicit(System.Int32)" ReturnType="System.IntPtr" />
+ <Member Name="op_Explicit(System.Int64)" ReturnType="System.IntPtr" />
+ <Member Name="op_Explicit(System.IntPtr)" ReturnType="System.Int32" />
+ <Member Name="op_Explicit(System.IntPtr)" ReturnType="System.Int64" />
+ <Member Name="op_Explicit(System.IntPtr)" ReturnType="System.Void*" />
+ <Member Name="op_Explicit(System.Void*)" ReturnType="System.IntPtr" />
+ <Member Name="op_Inequality(System.IntPtr,System.IntPtr)" />
+ <Member Name="op_Subtraction(System.IntPtr,System.Int32)" />
+ <Member Name="Subtract(System.IntPtr,System.Int32)" />
+ <Member Name="ToInt32" />
+ <Member Name="ToInt64" />
+ <Member Name="ToPointer" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.String)" />
+ <Member MemberType="Property" Name="Size" />
+ </Type>
+ <Type Name="System.InvalidCastException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.InvalidOperationException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.InvalidProgramException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.InvalidTimeZoneException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Status="ApiFxInternal" Name="System.IO.BufferedStream">
+ <Member Name="#ctor(System.IO.Stream,System.Int32)" />
+ <Member Name="get_UnderlyingStream" />
+ <Member Name="get_BufferSize" />
+ </Type>
+ <Type Name="System.IO.FileLoadException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String,System.Int32)" /> <!-- Used by EE, do not remove -->
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_FileName" />
+ </Type>
+ <Type Name="System.IObservable&lt;T&gt;">
+ <Member Name="Subscribe(System.IObserver&lt;T&gt;)"/>
+ </Type>
+ <Type Name="System.IObserver&lt;T&gt;">
+ <Member Name="OnCompleted"/>
+ <Member Name="OnError(System.Exception)"/>
+ <Member Name="OnNext(T)"/>
+ </Type>
+ <Type Name="System.IProgress&lt;T&gt;">
+ <Member Name="Report(T)" />
+ </Type>
+ <Type Name="System.IServiceProvider">
+ <Member Name="GetService(System.Type)" />
+ </Type>
+ <Type Name="System.Lazy&lt;T&gt;">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(T)"/>
+ <Member Name="#ctor(System.Func&lt;T&gt;)"/>
+ <Member Name="#ctor(System.Boolean)"/>
+ <Member Name="#ctor(System.Threading.LazyThreadSafetyMode)"/>
+ <Member Name="#ctor(System.Func&lt;T&gt;,System.Boolean)"/>
+ <Member Name="#ctor(System.Func&lt;T&gt;,System.Threading.LazyThreadSafetyMode)"/>
+ <Member MemberType="Property" Name="IsValueCreated"/>
+ <Member Name="get_IsValueCreated"/>
+ <Member MemberType="Property" Name="Value"/>
+ <Member Name="get_Value"/>
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.LoaderOptimization">
+ <Member MemberType="Field" Name="DisallowBindings" />
+ <Member MemberType="Field" Name="DomainMask" />
+ <Member MemberType="Field" Name="MultiDomain" />
+ <Member MemberType="Field" Name="MultiDomainHost" />
+ <Member MemberType="Field" Name="NotSpecified" />
+ <Member MemberType="Field" Name="SingleDomain" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.LoaderOptimizationAttribute">
+ <Member Name="#ctor(System.Byte)" />
+ <Member Name="#ctor(System.LoaderOptimization)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.LocalDataStoreSlot">
+ <Member Status="ImplRoot" Name="Finalize" />
+ </Type>
+ <Type Name="System.MarshalByRefObject">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.System_LazyDebugView&lt;T&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Lazy&lt;T&gt;)"/>
+ <Member Status="ImplRoot" MemberType="Property" Name="IsValueCreated"/>
+ <Member Status="ImplRoot" Name="get_IsValueCreated"/>
+ <Member Status="ImplRoot" MemberType="Property" Name="Value"/>
+ <Member Status="ImplRoot" Name="get_Value"/>
+ <Member Status="ImplRoot" MemberType="Property" Name="Mode"/>
+ <Member Status="ImplRoot" Name="get_Mode"/>
+ <Member Status="ImplRoot" MemberType="Property" Name="IsValueFaulted"/>
+ <Member Status="ImplRoot" Name="get_IsValueFaulted"/>
+ </Type>
+ <Type Name="System.Math">
+ <Member MemberType="Field" Name="E" />
+ <Member MemberType="Field" Name="PI" />
+ <Member Name="Abs(System.Decimal)" />
+ <Member Name="Abs(System.Double)" />
+ <Member Name="Abs(System.Int16)" />
+ <Member Name="Abs(System.Int32)" />
+ <Member Name="Abs(System.Int64)" />
+ <Member Name="Abs(System.SByte)" />
+ <Member Name="Abs(System.Single)" />
+ <Member Name="Acos(System.Double)" />
+ <Member Name="Asin(System.Double)" />
+ <Member Name="Atan(System.Double)" />
+ <Member Name="Atan2(System.Double,System.Double)" />
+ <Member Name="BigMul(System.Int32,System.Int32)" />
+ <Member Name="Ceiling(System.Decimal)" />
+ <Member Name="Ceiling(System.Double)"/>
+ <Member Name="Cos(System.Double)" />
+ <Member Name="Cosh(System.Double)" />
+ <Member Name="DivRem(System.Int32,System.Int32,System.Int32@)" />
+ <Member Name="DivRem(System.Int64,System.Int64,System.Int64@)" />
+ <Member Name="Exp(System.Double)" />
+ <Member Name="Floor(System.Decimal)" />
+ <Member Name="Floor(System.Double)" />
+ <Member Name="IEEERemainder(System.Double,System.Double)" />
+ <Member Name="Log(System.Double)" />
+ <Member Name="Log(System.Double,System.Double)" />
+ <Member Name="Log10(System.Double)" />
+ <Member Name="Max(System.Byte,System.Byte)" />
+ <Member Name="Max(System.Decimal,System.Decimal)" />
+ <Member Name="Max(System.Double,System.Double)" />
+ <Member Name="Max(System.Int16,System.Int16)" />
+ <Member Name="Max(System.Int32,System.Int32)" />
+ <Member Name="Max(System.Int64,System.Int64)" />
+ <Member Name="Max(System.SByte,System.SByte)" />
+ <Member Name="Max(System.Single,System.Single)" />
+ <Member Name="Max(System.UInt16,System.UInt16)" />
+ <Member Name="Max(System.UInt32,System.UInt32)" />
+ <Member Name="Max(System.UInt64,System.UInt64)" />
+ <Member Name="Min(System.Byte,System.Byte)" />
+ <Member Name="Min(System.Decimal,System.Decimal)" />
+ <Member Name="Min(System.Double,System.Double)" />
+ <Member Name="Min(System.Int16,System.Int16)" />
+ <Member Name="Min(System.Int32,System.Int32)" />
+ <Member Name="Min(System.Int64,System.Int64)" />
+ <Member Name="Min(System.SByte,System.SByte)" />
+ <Member Name="Min(System.Single,System.Single)" />
+ <Member Name="Min(System.UInt16,System.UInt16)" />
+ <Member Name="Min(System.UInt32,System.UInt32)" />
+ <Member Name="Min(System.UInt64,System.UInt64)" />
+ <Member Name="Pow(System.Double,System.Double)" />
+ <Member Name="Round(System.Decimal)" />
+ <Member Name="Round(System.Decimal,System.Int32)" />
+ <Member Name="Round(System.Decimal,System.Int32,System.MidpointRounding)" />
+ <Member Name="Round(System.Decimal,System.MidpointRounding)" />
+ <Member Name="Round(System.Double)" />
+ <Member Name="Round(System.Double,System.Int32)" />
+ <Member Name="Round(System.Double,System.Int32,System.MidpointRounding)" />
+ <Member Name="Round(System.Double,System.MidpointRounding)" />
+ <Member Name="Sign(System.Decimal)" />
+ <Member Name="Sign(System.Double)" />
+ <Member Name="Sign(System.Int16)" />
+ <Member Name="Sign(System.Int32)" />
+ <Member Name="Sign(System.Int64)" />
+ <Member Name="Sign(System.SByte)" />
+ <Member Name="Sign(System.Single)" />
+ <Member Name="Sin(System.Double)" />
+ <Member Name="Sinh(System.Double)" />
+ <Member Name="Sqrt(System.Double)" />
+ <Member Name="Tan(System.Double)" />
+ <Member Name="Tanh(System.Double)" />
+ <Member Name="Truncate(System.Decimal)" />
+ <Member Name="Truncate(System.Double)" />
+ </Type>
+ <Type Name="System.MemberAccessException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.MethodAccessException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.MidpointRounding">
+ <Member MemberType="Field" Name="AwayFromZero" />
+ <Member MemberType="Field" Name="ToEven" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.MissingFieldException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.MissingMemberException">
+ <Member MemberType="Field" Name="ClassName" />
+ <Member MemberType="Field" Name="MemberName" />
+ <Member MemberType="Field" Name="Signature" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.MissingMethodException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ModuleHandle">
+ <Member MemberType="Field" Name="EmptyHandle" />
+ <Member Name="GetHashCode" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.ModuleHandle)" />
+ <Member Name="get_MDStreamVersion" />
+ <Member Name="op_Equality(System.ModuleHandle,System.ModuleHandle)" />
+ <Member Name="op_Inequality(System.ModuleHandle,System.ModuleHandle)" />
+ <Member Name="GetRuntimeTypeHandleFromMetadataToken(System.Int32)" />
+ <Member Name="GetRuntimeMethodHandleFromMetadataToken(System.Int32)" />
+ <Member Name="GetRuntimeFieldHandleFromMetadataToken(System.Int32)" />
+ <Member Name="ResolveTypeHandle(System.Int32)" />
+ <Member Name="ResolveTypeHandle(System.Int32,System.RuntimeTypeHandle[],System.RuntimeTypeHandle[])" />
+ <Member Name="ResolveMethodHandle(System.Int32)" />
+ <Member Name="ResolveMethodHandle(System.Int32,System.RuntimeTypeHandle[],System.RuntimeTypeHandle[])" />
+ <Member Name="ResolveFieldHandle(System.Int32)" />
+ <Member Name="ResolveFieldHandle(System.Int32,System.RuntimeTypeHandle[],System.RuntimeTypeHandle[])" />
+ <Member MemberType="Property" Name="MDStreamVersion" />
+ </Type>
+ <Type Name="System.MTAThreadAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.MulticastDelegate">
+ <Member Name="#ctor(System.Object,System.String)" />
+ <Member Name="#ctor(System.Type,System.String)" />
+ <Member Name="CombineImpl(System.Delegate)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetInvocationList" />
+ <Member Name="GetMethodImpl" />
+ <Member Name="GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="op_Equality(System.MulticastDelegate,System.MulticastDelegate)" />
+ <Member Name="op_Inequality(System.MulticastDelegate,System.MulticastDelegate)" />
+ <Member Name="RemoveImpl(System.Delegate)" />
+ <Member Status="ImplRoot" Name="CtorClosed(System.Object,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorClosedStatic(System.Object,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorOpened(System.Object,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorRTClosed(System.Object,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorSecureClosed(System.Object,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorSecureClosedStatic(System.Object,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorSecureOpened(System.Object,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorSecureRTClosed(System.Object,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorSecureVirtualDispatch(System.Object,System.IntPtr,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorVirtualDispatch(System.Object,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorCollectibleClosedStatic(System.Object,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorCollectibleOpened(System.Object,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Status="ImplRoot" Name="CtorCollectibleVirtualDispatch(System.Object,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ </Type>
+ <Type Name="System.MulticastNotSupportedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.NonSerializedAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.NotFiniteNumberException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Double)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Double)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Double,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_OffendingNumber" />
+ <Member MemberType="Property" Name="OffendingNumber" />
+ </Type>
+ <Type Name="System.NotImplementedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.NotSupportedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Nullable">
+ <Member Name="Compare&lt;T&gt;(System.Nullable&lt;T&gt;,System.Nullable&lt;T&gt;)" />
+ <Member Name="Equals&lt;T&gt;(System.Nullable&lt;T&gt;,System.Nullable&lt;T&gt;)" />
+ <Member Name="GetUnderlyingType(System.Type)" />
+ </Type>
+ <Type Name="System.Nullable&lt;T&gt;">
+ <Member Name="#ctor(T)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_HasValue" />
+ <Member Name="get_Value" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetValueOrDefault" />
+ <Member Name="GetValueOrDefault(T)" />
+ <Member Name="op_Explicit(System.Nullable&lt;T&gt;)" ReturnType="T" />
+ <Member Name="op_Implicit(T)" ReturnType="System.Nullable&lt;T&gt;" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="HasValue" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.NullReferenceException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Object">
+ <Member Name="#ctor" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Object,System.Object)" />
+ <Member Name="Finalize" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetType" />
+ <Member Name="MemberwiseClone" />
+ <Member Name="ReferenceEquals(System.Object,System.Object)" />
+ <Member Name="ToString" />
+ <Member Status="ImplRoot" Name="FieldSetter(System.String,System.String,System.Object)" /> <!-- EE -->
+ <Member Status="ImplRoot" Name="FieldGetter(System.String,System.String,System.Object@)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.ObjectDisposedException">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_ObjectName" />
+ <Member MemberType="Property" Name="ObjectName" />
+ </Type>
+ <Type Name="System.ObsoleteAttribute">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Boolean)" />
+ <Member Name="get_IsError" />
+ <Member Name="get_Message" />
+ <Member MemberType="Property" Name="IsError" />
+ <Member MemberType="Property" Name="Message" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.OleAutBinder" Condition="FEATURE_COMINTEROP" />
+ <Type Name="System.OperatingSystem">
+ <Member Name="#ctor(System.PlatformID,System.Version)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Clone" />
+ <Member Name="get_Platform" />
+ <Member Name="get_Version" />
+ <Member Name="get_ServicePack" />
+ <Member Name="get_VersionString" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Platform" />
+ <Member MemberType="Property" Name="Version" />
+ <Member MemberType="Property" Name="ServicePack" />
+ <Member MemberType="Property" Name="VersionString" />
+ </Type>
+ <Type Name="System.OutOfMemoryException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.OverflowException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ParamArrayAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.ParseNumbers">
+ <Member Status="ImplRoot" Name="StringToInt(System.String,System.Int32,System.Int32,System.Int32@)" />
+ <Member Status="ImplRoot" Name="StringToInt(System.String,System.Int32,System.Int32,System.Int32*)" />
+ <Member Status="ImplRoot" Name="StringToLong(System.String,System.Int32,System.Int32,System.Int32@)" />
+ <Member Status="ImplRoot" Name="StringToLong(System.String,System.Int32,System.Int32,System.Int32*)" />
+ </Type>
+ <Type Name="System.PlatformNotSupportedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Predicate&lt;T&gt;">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(T,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(T)" />
+ </Type>
+ <Type Name="System.Progress&lt;T&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Action&lt;T&gt;)" />
+ <Member MemberType="Event" Name="ProgressChanged" />
+ <Member Name="OnReport(T)" />
+ </Type>
+ <Type Name="System.Random">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="Next" />
+ <Member Name="Next(System.Int32)" />
+ <Member Name="Next(System.Int32,System.Int32)" />
+ <Member Name="NextBytes(System.Byte[])" />
+ <Member Name="NextDouble" />
+ <Member Name="Sample" />
+ </Type>
+ <Type Name="System.RankException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.AmbiguousMatchException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyContentType">
+ <Member MemberType="Field" Name="Default"/>
+ <Member MemberType="Field" Name="WindowsRuntime"/>
+ <Member MemberType="Field" Name="value__"/>
+ </Type>
+ <Type Name="System.Reflection.Assembly">
+ <Member Name="#ctor" />
+ <Member Name="CreateInstance(System.String)" />
+ <Member Name="CreateInstance(System.String,System.Boolean)" />
+ <Member Name="CreateInstance(System.String,System.Boolean,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo,System.Object[])" />
+ <Member Name="CreateQualifiedName(System.String,System.String)" />
+ <Member Name="GetReferencedAssemblies" />
+ <Member Name="get_EntryPoint" />
+ <Member Name="get_FullName" />
+ <Member Name="get_ImageRuntimeVersion" />
+ <Member Name="get_IsDynamic" />
+ <Member Name="get_CodeBase" />
+ <Member Name="get_Location" />
+ <Member Name="get_ManifestModule" />
+ <Member Name="get_CustomAttributes" />
+ <Member Name="get_Modules" />
+ <Member Name="get_ReflectionOnly" />
+ <Member Name="GetAssembly(System.Type)" />
+ <Member Name="op_Equality(System.Reflection.Assembly,System.Reflection.Assembly)" />
+ <Member Name="op_Inequality(System.Reflection.Assembly,System.Reflection.Assembly)" />
+ <Member Name="GetCallingAssembly" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributesData" />
+ <Member Name="GetExecutingAssembly" />
+ <Member Name="GetEntryAssembly" />
+ <Member Name="GetExportedTypes" />
+ <Member Name="GetLoadedModules" />
+ <Member Name="GetLoadedModules(System.Boolean)" />
+ <Member Name="GetManifestResourceNames" />
+ <Member Name="GetManifestResourceStream(System.String)" />
+ <Member Name="GetManifestResourceInfo(System.String)" />
+ <Member Name="GetManifestResourceStream(System.Type,System.String)" />
+ <Member Name="GetModule(System.String)" />
+ <Member Name="GetModules" />
+ <Member Name="GetModules(System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetName(System.Boolean)" />
+ <Member Name="GetName" />
+ <Member Name="GetSatelliteAssembly(System.Globalization.CultureInfo)" />
+ <Member Name="GetSatelliteAssembly(System.Globalization.CultureInfo,System.Version)" />
+ <Member Name="GetType(System.String)" />
+ <Member Name="GetType(System.String,System.Boolean)" />
+ <Member Name="GetType(System.String,System.Boolean,System.Boolean)" />
+ <Member Name="GetTypes" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsDynamic" MemberType="Property" />
+ <Member Name="Load(System.Reflection.AssemblyName)" />
+ <Member Name="Load(System.String)" />
+ <Member Name="Load(System.Byte[])" />
+ <Member Name="Load(System.Byte[],System.Byte[])" />
+ <Member Name="ReflectionOnlyLoad(System.String)" />
+ <Member Name="ReflectionOnlyLoad(System.Byte[])" />
+ <Member Name="ReflectionOnlyLoadFrom(System.String)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="DefinedTypes" />
+ <Member MemberType="Property" Name="CustomAttributes" />
+ <Member MemberType="Property" Name="Modules" />
+ <Member MemberType="Property" Name="ExportedTypes" />
+ <Member MemberType="Property" Name="EntryPoint" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="CodeBase" />
+ <Member MemberType="Property" Name="ImageRuntimeVersion" />
+ <Member MemberType="Property" Name="Location" />
+ <Member MemberType="Property" Name="ManifestModule" />
+ <Member Status="ImplRoot" MemberType="Event" Name="ModuleResolve" />
+ </Type>
+ <Type Name="System.Reflection.IntrospectionExtensions">
+ <Member Name="GetTypeInfo(System.Type)" />
+ </Type>
+ <Type Name="System.Reflection.IReflectableType">
+ <Member Name="GetTypeInfo" />
+ </Type>
+ <Type Name="System.Reflection.ProcessorArchitecture">
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="MSIL" />
+ <Member MemberType="Field" Name="X86" />
+ <Member MemberType="Field" Name="IA64" />
+ <Member MemberType="Field" Name="Amd64" />
+ <Member MemberType="Field" Name="Arm" />
+ </Type>
+ <Type Name="System.Reflection.ReflectionContext">
+ <Member Name="#ctor" />
+ <Member Name="MapAssembly(System.Reflection.Assembly)" />
+ <Member Name="MapType(System.Reflection.TypeInfo)" />
+ <Member Name="GetTypeForObject(System.Object)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Reflection.ResourceLocation">
+ <Member MemberType="Field" Name="ContainedInAnotherAssembly" />
+ <Member MemberType="Field" Name="ContainedInManifestFile" />
+ <Member MemberType="Field" Name="Embedded" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.RuntimeAssembly">
+ <Member Status="ImplRoot" MemberType="Event" Name="_ModuleResolve" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_assembly" />
+ <Member Status="ImplRoot" Name="OnModuleResolveEvent(System.String)" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Property" Name="DefinedTypes" />
+ <!-- On Windows Phone Assembly.LoadFrom throws a NotSupportedException. Prevent this internal helper from being stripped by the rewriter so that tests may reflect and call it since they need LoadFrom functionality -->
+ <Member Status="ImplRoot" Name="InternalLoadFrom(System.String,System.Security.Policy.Evidence,System.Byte[],System.Configuration.Assemblies.AssemblyHashAlgorithm,System.Boolean,System.Boolean,System.Threading.StackCrawlMark@)" Condition="FEATURE_WINDOWSPHONE" />
+ </Type>
+ <Type Name="System.Reflection.TypeInfo">
+ <Member Name="#ctor" />
+ <Member Name="AsType" />
+ <Member MemberType="Property" Name="GenericTypeParameters" />
+ <Member Name="IsAssignableFrom(System.Reflection.TypeInfo)" />
+ <Member Name="GetDeclaredEvent(System.String)" />
+ <Member Name="GetDeclaredField(System.String)" />
+ <Member Name="GetDeclaredMethod(System.String)" />
+ <Member Name="GetDeclaredMethods(System.String)" />
+ <Member Name="GetDeclaredNestedType(System.String)" />
+ <Member Name="GetDeclaredProperty(System.String)" />
+ <Member MemberType="Property" Name="DeclaredConstructors" />
+ <Member MemberType="Property" Name="DeclaredEvents" />
+ <Member MemberType="Property" Name="DeclaredFields" />
+ <Member MemberType="Property" Name="DeclaredMembers" />
+ <Member MemberType="Property" Name="DeclaredMethods" />
+ <Member MemberType="Property" Name="DeclaredNestedTypes" />
+ <Member MemberType="Property" Name="DeclaredProperties" />
+ <Member MemberType="Property" Name="ImplementedInterfaces" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyAlgorithmIdAttribute">
+ <Member Name="#ctor(System.Configuration.Assemblies.AssemblyHashAlgorithm)" />
+ <Member Name="#ctor(System.UInt32)" />
+ <Member Name="get_AlgorithmId" />
+ <Member MemberType="Property" Name="AlgorithmId" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyCompanyAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Company" />
+ <Member MemberType="Property" Name="Company" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyConfigurationAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Configuration" />
+ <Member MemberType="Property" Name="Configuration" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyCopyrightAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Copyright" />
+ <Member MemberType="Property" Name="Copyright" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyCultureAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Culture" />
+ <Member MemberType="Property" Name="Culture" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyDefaultAliasAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_DefaultAlias" />
+ <Member MemberType="Property" Name="DefaultAlias" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyDelaySignAttribute">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_DelaySign" />
+ <Member MemberType="Property" Name="DelaySign" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyDescriptionAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Description" />
+ <Member MemberType="Property" Name="Description" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyMetadataAttribute">
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="get_Key" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Key" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyFlagsAttribute">
+ <Member Name="#ctor(System.UInt32)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Reflection.AssemblyNameFlags)" />
+ <Member Name="get_AssemblyFlags" />
+ <Member Name="get_Flags" />
+ <Member MemberType="Property" Name="AssemblyFlags" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyInformationalVersionAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_InformationalVersion" />
+ <Member MemberType="Property" Name="InformationalVersion" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyKeyFileAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_KeyFile" />
+ <Member MemberType="Property" Name="KeyFile" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyKeyNameAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_KeyName" />
+ <Member MemberType="Property" Name="KeyName" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyName">
+ <Member Name="#ctor" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_CultureInfo" />
+ <Member Name="get_CultureName" />
+ <Member Name="get_CodeBase" />
+ <Member Name="get_ContentType" />
+ <Member Name="get_Flags" />
+ <Member Name="get_FullName" />
+ <Member Name="get_HashAlgorithm" />
+ <Member Name="get_VersionCompatibility" />
+ <Member Name="get_Name" />
+ <Member Name="get_ProcessorArchitecture" />
+ <Member Name="get_Version" />
+ <Member Name="GetPublicKey" />
+ <Member Name="GetPublicKeyToken" />
+ <Member Name="set_CultureInfo(System.Globalization.CultureInfo)" />
+ <Member Name="set_CodeBase(System.String)" />
+ <Member Name="set_Flags(System.Reflection.AssemblyNameFlags)" />
+ <Member Name="set_HashAlgorithm(System.Configuration.Assemblies.AssemblyHashAlgorithm)" />
+ <Member Name="set_VersionCompatibility(System.Configuration.Assemblies.AssemblyVersionCompatibility)" />
+ <Member Name="set_Name(System.String)" />
+ <Member Name="set_ProcessorArchitecture(System.Reflection.ProcessorArchitecture)" />
+ <Member Name="set_Version(System.Version)" />
+ <Member Name="Clone" />
+ <Member Name="SetPublicKey(System.Byte[])" />
+ <Member Name="SetPublicKeyToken(System.Byte[])" />
+ <Member Name="ToString" />
+ <Member Name="GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="OnDeserialization(System.Object)" />
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="CodeBase" />
+ <Member MemberType="Property" Name="CultureInfo" />
+ <Member MemberType="Property" Name="CultureName" />
+ <Member MemberType="Property" Name="ContentType" />
+ <Member MemberType="Property" Name="Flags" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="HashAlgorithm" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ProcessorArchitecture" />
+ <Member MemberType="Property" Name="Version" />
+ <Member MemberType="Property" Name="VersionCompatibility" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyNameFlags">
+ <Member MemberType="Field" Name="EnableJITcompileOptimizer" />
+ <Member MemberType="Field" Name="EnableJITcompileTracking" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="PublicKey" />
+ <Member MemberType="Field" Name="Retargetable" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyProductAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Product" />
+ <Member MemberType="Property" Name="Product" />
+ </Type>
+ <Type Name="System.Reflection.AssemblySignatureKeyAttribute">
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="get_Countersignature" />
+ <Member Name="get_PublicKey" />
+ <Member MemberType="Property" Name="Countersignature" />
+ <Member MemberType="Property" Name="PublicKey" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyTitleAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Title" />
+ <Member MemberType="Property" Name="Title" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyTrademarkAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Trademark" />
+ <Member MemberType="Property" Name="Trademark" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyVersionAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Version" />
+ <Member MemberType="Property" Name="Version" />
+ </Type>
+ <Type Name="System.Reflection.Binder">
+ <Member Name="#ctor" />
+ <Member Name="BindToField(System.Reflection.BindingFlags,System.Reflection.FieldInfo[],System.Object,System.Globalization.CultureInfo)" />
+ <Member Name="BindToMethod(System.Reflection.BindingFlags,System.Reflection.MethodBase[],System.Object[]@,System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[],System.Object@)" />
+ <Member Name="ChangeType(System.Object,System.Type,System.Globalization.CultureInfo)" />
+ <Member Name="ReorderArgumentArray(System.Object[]@,System.Object)" />
+ <Member Name="SelectMethod(System.Reflection.BindingFlags,System.Reflection.MethodBase[],System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="SelectProperty(System.Reflection.BindingFlags,System.Reflection.PropertyInfo[],System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ </Type>
+ <Type Name="System.Reflection.BindingFlags">
+ <Member MemberType="Field" Name="CreateInstance" />
+ <Member MemberType="Field" Name="DeclaredOnly" />
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="ExactBinding" />
+ <Member MemberType="Field" Name="FlattenHierarchy" />
+ <Member MemberType="Field" Name="GetField" />
+ <Member MemberType="Field" Name="GetProperty" />
+ <Member MemberType="Field" Name="IgnoreCase" />
+ <Member MemberType="Field" Name="IgnoreReturn" />
+ <Member MemberType="Field" Name="Instance" />
+ <Member MemberType="Field" Name="InvokeMethod" />
+ <Member MemberType="Field" Name="NonPublic" />
+ <Member MemberType="Field" Name="OptionalParamBinding" />
+ <Member MemberType="Field" Name="Public" />
+ <Member MemberType="Field" Name="PutDispProperty" />
+ <Member MemberType="Field" Name="PutRefDispProperty" />
+ <Member MemberType="Field" Name="SetField" />
+ <Member MemberType="Field" Name="SetProperty" />
+ <Member MemberType="Field" Name="Static" />
+ <Member MemberType="Field" Name="SuppressChangeType" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.CallingConventions">
+ <Member MemberType="Field" Name="Any" />
+ <Member MemberType="Field" Name="ExplicitThis" />
+ <Member MemberType="Field" Name="HasThis" />
+ <Member MemberType="Field" Name="Standard" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VarArgs" />
+ </Type>
+ <Type Name="System.Reflection.ConstructorInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.ConstructorInfo,System.Reflection.ConstructorInfo)" />
+ <Member Name="op_Inequality(System.Reflection.ConstructorInfo,System.Reflection.ConstructorInfo)" />
+ <Member MemberType="Field" Name="ConstructorName" />
+ <Member MemberType="Field" Name="TypeConstructorName" />
+ <Member Name="get_MemberType" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="Invoke(System.Object[])" />
+ <Member Name="Invoke(System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="MemberType" />
+ </Type>
+ <Type Name="System.Reflection.CustomAttributeData">
+ <Member Name="#ctor" />
+ <Member Name="get_AttributeType" />
+ <Member Name="get_ConstructorArguments" />
+ <Member Name="get_NamedArguments" />
+ <Member Name="get_Constructor" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo)" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="AttributeType" />
+ <Member MemberType="Property" Name="Constructor" />
+ <Member MemberType="Property" Name="ConstructorArguments" />
+ <Member MemberType="Property" Name="NamedArguments" />
+ </Type>
+ <Type Name="System.Reflection.CustomAttributeExtensions">
+ <Member Name="GetCustomAttribute(System.Reflection.Assembly,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttribute(System.Reflection.Module,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="GetCustomAttribute(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.Assembly)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.MemberInfo)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.MemberInfo,System.Boolean)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.Module)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.ParameterInfo)" />
+ <Member Name="GetCustomAttribute&lt;T&gt;(System.Reflection.ParameterInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Assembly,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module)" />
+ <Member Name="GetCustomAttributes(System.Reflection.Module,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="GetCustomAttributes(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.Assembly)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.MemberInfo)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.MemberInfo,System.Boolean)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.Module)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.ParameterInfo)" />
+ <Member Name="GetCustomAttributes&lt;T&gt;(System.Reflection.ParameterInfo,System.Boolean)" />
+ <Member Name="IsDefined(System.Reflection.Assembly,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.MemberInfo,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.MemberInfo,System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Reflection.Module,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.ParameterInfo,System.Type)" />
+ <Member Name="IsDefined(System.Reflection.ParameterInfo,System.Type,System.Boolean)" />
+ </Type>
+ <Type Name="System.Reflection.RuntimeReflectionExtensions">
+ <Member Name="GetMethodInfo(System.Delegate)" />
+ <Member Name="GetRuntimeBaseDefinition(System.Reflection.MethodInfo)" />
+ <Member Name="GetRuntimeEvent(System.Type,System.String)" />
+ <Member Name="GetRuntimeEvents(System.Type)" />
+ <Member Name="GetRuntimeField(System.Type,System.String)" />
+ <Member Name="GetRuntimeFields(System.Type)" />
+ <Member Name="GetRuntimeInterfaceMap(System.Reflection.TypeInfo,System.Type)" />
+ <Member Name="GetRuntimeMethod(System.Type,System.String,System.Type[])" />
+ <Member Name="GetRuntimeMethods(System.Type)" />
+ <Member Name="GetRuntimeProperties(System.Type)" />
+ <Member Name="GetRuntimeProperty(System.Type,System.String)" />
+ </Type>
+ <Type Name="System.Reflection.CustomAttributeNamedArgument">
+ <Member Name="#ctor(System.Reflection.MemberInfo,System.Object)" />
+ <Member Name="#ctor(System.Reflection.MemberInfo,System.Reflection.CustomAttributeTypedArgument)" />
+ <Member Name="get_IsField" />
+ <Member Name="get_MemberInfo" />
+ <Member Name="get_MemberName" />
+ <Member Name="get_TypedValue" />
+ <Member Name="op_Equality(System.Reflection.CustomAttributeNamedArgument,System.Reflection.CustomAttributeNamedArgument)" />
+ <Member Name="op_Inequality(System.Reflection.CustomAttributeNamedArgument,System.Reflection.CustomAttributeNamedArgument)" />
+ <Member MemberType="Property" Name="IsField" />
+ <Member MemberType="Property" Name="MemberName" />
+ <Member MemberType="Property" Name="TypedValue" />
+ </Type>
+ <Type Name="System.Reflection.CustomAttributeTypedArgument">
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="#ctor(System.Type,System.Object)" />
+ <Member Name="get_ArgumentType" />
+ <Member Name="get_Value" />
+ <Member Name="op_Equality(System.Reflection.CustomAttributeTypedArgument,System.Reflection.CustomAttributeTypedArgument)" />
+ <Member Name="op_Inequality(System.Reflection.CustomAttributeTypedArgument,System.Reflection.CustomAttributeTypedArgument)" />
+ <Member MemberType="Property" Name="ArgumentType" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Reflection.CustomAttributeFormatException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.DefaultMemberAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_MemberName" />
+ <Member MemberType="Property" Name="MemberName" />
+ </Type>
+ <Type Name="System.Reflection.Emit.AssemblyBuilder">
+ <Member Name="DefineDynamicAssembly(System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess)" />
+ <Member Name="DefineDynamicAssembly(System.Reflection.AssemblyName,System.Reflection.Emit.AssemblyBuilderAccess,System.Collections.Generic.IEnumerable&lt;System.Reflection.Emit.CustomAttributeBuilder&gt;)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="DefineDynamicModule(System.String)" />
+ <Member Name="DefineDynamicModule(System.String,System.Boolean)" />
+ <Member Name="get_EntryPoint" />
+ <Member Name="get_ImageRuntimeVersion" />
+ <Member Name="GetDynamicModule(System.String)" />
+ <Member Name="GetExportedTypes" />
+ <Member Name="GetManifestResourceNames" />
+ <Member Name="GetManifestResourceStream(System.String)" />
+ <Member Name="GetManifestResourceStream(System.Type,System.String)" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member MemberType="Property" Name="EntryPoint" />
+ <Member MemberType="Property" Name="ImageRuntimeVersion" />
+ </Type>
+ <Type Name="System.Reflection.Emit.AssemblyBuilderAccess">
+ <Member MemberType="Field" Name="Run" />
+ <Member MemberType="Field" Name="RunAndCollect" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.Emit.ConstructorBuilder">
+ <Member Name="DefineParameter(System.Int32,System.Reflection.ParameterAttributes,System.String)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CallingConvention" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_InitLocals" />
+ <Member Name="get_MethodHandle" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_Signature" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetILGenerator" />
+ <Member Name="GetILGenerator(System.Int32)" />
+ <Member Name="GetMethodImplementationFlags" />
+ <Member Name="GetModule" />
+ <Member Name="GetParameters" />
+ <Member Name="GetToken" />
+ <Member Name="Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="Invoke(System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="set_InitLocals(System.Boolean)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetImplementationFlags(System.Reflection.MethodImplAttributes)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CallingConvention" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="InitLocals" />
+ <Member MemberType="Property" Name="MethodHandle" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="Signature" />
+ </Type>
+ <Type Name="System.Reflection.Emit.CustomAttributeBuilder">
+ <Member Name="#ctor(System.Reflection.ConstructorInfo,System.Object[])" />
+ <Member Name="#ctor(System.Reflection.ConstructorInfo,System.Object[],System.Reflection.FieldInfo[],System.Object[])" />
+ <Member Name="#ctor(System.Reflection.ConstructorInfo,System.Object[],System.Reflection.PropertyInfo[],System.Object[])" />
+ <Member Name="#ctor(System.Reflection.ConstructorInfo,System.Object[],System.Reflection.PropertyInfo[],System.Object[],System.Reflection.FieldInfo[],System.Object[])" />
+ </Type>
+ <Type Name="System.RuntimeArgumentHandle"> <!-- MC++ compiler asserts for no particularly good reason if this type is not public -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.RuntimeFieldInfoStub">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_keepalive" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_b" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_c" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_d" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_e" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_fieldHandle" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.RuntimeMethodInfoStub">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_a" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_b" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_c" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_d" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_e" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_f" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_g" />
+ </Type>
+ <Type Name="System.RuntimeTypeHandle">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Equals(System.RuntimeTypeHandle)" />
+ <Member Name="op_Equality(System.Object,System.RuntimeTypeHandle)" />
+ <Member Name="op_Equality(System.RuntimeTypeHandle,System.Object)" />
+ <Member Name="GetModuleHandle" />
+ <Member Name="op_Inequality(System.Object,System.RuntimeTypeHandle)" />
+ <Member Name="op_Inequality(System.RuntimeTypeHandle,System.Object)" />
+ <Member Status="ImplRoot" Name="GetTypeHelper(System.Type,System.Type[],System.IntPtr,System.Int32)" /> <!-- EE -->
+ <Member Status="ImplRoot" Name="GetValueInternal(System.RuntimeTypeHandle)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ <!-- EE -->
+ </Type>
+ <Type Name="System.Reflection.Emit.DynamicMethod">
+ <Member Name="#ctor(System.String,System.Type,System.Type[])" />
+ <Member Name="#ctor(System.String,System.Type,System.Type[],System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Reflection.Module,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Type,System.Type[],System.Reflection.Module)" />
+ <Member Name="#ctor(System.String,System.Type,System.Type[],System.Reflection.Module,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Type,System.Type[],System.Type)" />
+ <Member Name="#ctor(System.String,System.Type,System.Type[],System.Type,System.Boolean)" />
+ <Member Name="CreateDelegate(System.Type)" />
+ <Member Name="CreateDelegate(System.Type,System.Object)" />
+ <Member Name="DefineParameter(System.Int32,System.Reflection.ParameterAttributes,System.String)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CallingConvention" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_InitLocals" />
+ <Member Name="get_MethodHandle" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_ReturnParameter" />
+ <Member Name="get_ReturnType" />
+ <Member Name="get_ReturnTypeCustomAttributes" />
+ <Member Name="GetBaseDefinition" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetILGenerator" />
+ <Member Name="GetILGenerator(System.Int32)" />
+ <Member Name="GetMethodImplementationFlags" />
+ <Member Name="GetParameters" />
+ <Member Name="Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="set_InitLocals(System.Boolean)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CallingConvention" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="InitLocals" />
+ <Member MemberType="Property" Name="MethodHandle" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="ReturnParameter" />
+ <Member MemberType="Property" Name="ReturnType" />
+ <Member MemberType="Property" Name="ReturnTypeCustomAttributes" />
+ </Type>
+ <Type Name="System.Reflection.Emit.EnumBuilder">
+ <Member Name="CreateType" />
+ <Member Name="CreateTypeInfo" />
+ <Member Name="DefineLiteral(System.String,System.Object)" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_AssemblyQualifiedName" />
+ <Member Name="get_BaseType" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_FullName" />
+ <Member Name="get_GUID" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_Namespace" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_TypeHandle" />
+ <Member Name="get_TypeToken" />
+ <Member Name="get_UnderlyingField" />
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetAttributeFlagsImpl" />
+ <Member Name="GetConstructorImpl(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructors(System.Reflection.BindingFlags)" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetElementType" />
+ <Member Name="GetEvent(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents" />
+ <Member Name="GetEvents(System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetInterface(System.String,System.Boolean)" />
+ <Member Name="GetInterfaceMap(System.Type)" />
+ <Member Name="GetInterfaces" />
+ <Member Name="GetMember(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedType(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedTypes(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="GetPropertyImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="HasElementTypeImpl" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ <Member Name="IsArrayImpl" />
+ <Member Name="IsByRefImpl" />
+ <Member Name="IsCOMObjectImpl" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsPointerImpl" />
+ <Member Name="IsPrimitiveImpl" />
+ <Member Name="IsValueTypeImpl" />
+ <Member Name="MakeArrayType" />
+ <Member Name="MakeArrayType(System.Int32)" />
+ <Member Name="MakeByRefType" />
+ <Member Name="MakePointerType" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="AssemblyQualifiedName" />
+ <Member MemberType="Property" Name="BaseType" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="GUID" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Namespace" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="TypeHandle" />
+ <Member MemberType="Property" Name="TypeToken" />
+ <Member MemberType="Property" Name="UnderlyingField" />
+ <Member MemberType="Property" Name="UnderlyingSystemType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.EventBuilder">
+ <Member Name="AddOtherMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="GetEventToken" />
+ <Member Name="SetAddOnMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetRaiseMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="SetRemoveOnMethod(System.Reflection.Emit.MethodBuilder)" />
+ </Type>
+ <Type Name="System.Reflection.Emit.EventToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.EventToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.EventToken,System.Reflection.Emit.EventToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.EventToken,System.Reflection.Emit.EventToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.FieldBuilder">
+ <Member Name="get_Attributes" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_FieldHandle" />
+ <Member Name="get_FieldType" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetToken" />
+ <Member Name="GetValue(System.Object)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="SetConstant(System.Object)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetOffset(System.Int32)" />
+ <Member Name="SetValue(System.Object,System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="FieldHandle" />
+ <Member MemberType="Property" Name="FieldType" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.FieldToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.FieldToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.FieldToken,System.Reflection.Emit.FieldToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.FieldToken,System.Reflection.Emit.FieldToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.FlowControl">
+ <Member MemberType="Field" Name="Branch" />
+ <Member MemberType="Field" Name="Break" />
+ <Member MemberType="Field" Name="Call" />
+ <Member MemberType="Field" Name="Cond_Branch" />
+ <Member MemberType="Field" Name="Meta" />
+ <Member MemberType="Field" Name="Next" />
+ <Member MemberType="Field" Name="Return" />
+ <Member MemberType="Field" Name="Throw" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.Emit.GenericTypeParameterBuilder">
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_AssemblyQualifiedName" />
+ <Member Name="get_BaseType" />
+ <Member Name="get_ContainsGenericParameters" />
+ <Member Name="get_DeclaringMethod" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_FullName" />
+ <Member Name="get_GenericParameterPosition" />
+ <Member Name="get_GUID" />
+ <Member Name="get_IsGenericParameter" />
+ <Member Name="get_IsGenericType" />
+ <Member Name="get_IsGenericTypeDefinition" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_Namespace" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_TypeHandle" />
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetAttributeFlagsImpl" />
+ <Member Name="GetConstructorImpl(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructors(System.Reflection.BindingFlags)" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetElementType" />
+ <Member Name="GetEvent(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents" />
+ <Member Name="GetEvents(System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetGenericArguments" />
+ <Member Name="GetGenericTypeDefinition" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetInterface(System.String,System.Boolean)" />
+ <Member Name="GetInterfaceMap(System.Type)" />
+ <Member Name="GetInterfaces" />
+ <Member Name="GetMember(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedType(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedTypes(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="GetPropertyImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="HasElementTypeImpl" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ <Member Name="IsArrayImpl" />
+ <Member Name="IsAssignableFrom(System.Type)" />
+ <Member Name="IsAssignableFrom(System.Reflection.TypeInfo)" />
+ <Member Name="IsByRefImpl" />
+ <Member Name="IsCOMObjectImpl" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsPointerImpl" />
+ <Member Name="IsPrimitiveImpl" />
+ <Member Name="IsSubclassOf(System.Type)" />
+ <Member Name="IsValueTypeImpl" />
+ <Member Name="MakeArrayType" />
+ <Member Name="MakeArrayType(System.Int32)" />
+ <Member Name="MakeByRefType" />
+ <Member Name="MakeGenericType(System.Type[])" />
+ <Member Name="MakePointerType" />
+ <Member Name="SetBaseTypeConstraint(System.Type)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetGenericParameterAttributes(System.Reflection.GenericParameterAttributes)" />
+ <Member Name="SetInterfaceConstraints(System.Type[])" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="AssemblyQualifiedName" />
+ <Member MemberType="Property" Name="BaseType" />
+ <Member MemberType="Property" Name="ContainsGenericParameters" />
+ <Member MemberType="Property" Name="DeclaringMethod" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="GenericParameterPosition" />
+ <Member MemberType="Property" Name="GUID" />
+ <Member MemberType="Property" Name="IsGenericParameter" />
+ <Member MemberType="Property" Name="IsGenericType" />
+ <Member MemberType="Property" Name="IsGenericTypeDefinition" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Namespace" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="TypeHandle" />
+ <Member MemberType="Property" Name="UnderlyingSystemType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.ILGenerator">
+ <Member Name="BeginCatchBlock(System.Type)" />
+ <Member Name="BeginExceptFilterBlock" />
+ <Member Name="BeginExceptionBlock" />
+ <Member Name="BeginFaultBlock" />
+ <Member Name="BeginFinallyBlock" />
+ <Member Name="BeginScope" />
+ <Member Name="DeclareLocal(System.Type)" />
+ <Member Name="DeclareLocal(System.Type,System.Boolean)" />
+ <Member Name="DefineLabel" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Byte)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Double)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Int16)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Int32)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Int64)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.Emit.SignatureHelper)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.ConstructorInfo)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.Emit.Label)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.Emit.Label[])" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.Emit.LocalBuilder)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.FieldInfo)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Reflection.MethodInfo)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.SByte)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Single)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.String)" />
+ <Member Name="Emit(System.Reflection.Emit.OpCode,System.Type)" />
+ <Member Name="EmitCall(System.Reflection.Emit.OpCode,System.Reflection.MethodInfo,System.Type[])" />
+ <Member Name="EmitCalli(System.Reflection.Emit.OpCode,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[])" />
+ <Member Name="EmitWriteLine(System.Reflection.Emit.LocalBuilder)" />
+ <Member Name="EmitWriteLine(System.Reflection.FieldInfo)" />
+ <Member Name="EmitWriteLine(System.String)" />
+ <Member Name="EndExceptionBlock" />
+ <Member Name="EndScope" />
+ <Member Name="MarkLabel(System.Reflection.Emit.Label)" />
+ <Member Name="MarkSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="get_ILOffset" />
+ <Member Name="ThrowException(System.Type)" />
+ <Member Name="UsingNamespace(System.String)" />
+ <Member MemberType="Property" Name="ILOffset" />
+ </Type>
+ <Type Name="System.Diagnostics.CodeAnalysis.SuppressMessageAttribute">
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member MemberType="Property" Name="Category" />
+ <Member MemberType="Property" Name="CheckId" />
+ <Member MemberType="Property" Name="Scope" />
+ <Member MemberType="Property" Name="Target" />
+ <Member MemberType="Property" Name="MessageId" />
+ <Member MemberType="Property" Name="Justification" />
+ </Type>
+ <Type Name="System.Diagnostics.SymbolStore.ISymbolDocumentWriter">
+ <Member Name="SetSource(System.Byte[])" />
+ <Member Name="SetCheckSum(System.Guid,System.Byte[])" />
+ </Type>
+ <Type Name="System.Reflection.Emit.Label">
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.Label)" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.Label,System.Reflection.Emit.Label)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.Label,System.Reflection.Emit.Label)" />
+ </Type>
+ <Type Name="System.Reflection.Emit.LocalBuilder">
+ <Member Name="get_IsPinned" />
+ <Member Name="get_LocalIndex" />
+ <Member Name="get_LocalType" />
+ <Member Name="SetLocalSymInfo(System.String)" />
+ <Member Name="SetLocalSymInfo(System.String,System.Int32,System.Int32)" />
+ <Member MemberType="Property" Name="IsPinned" />
+ <Member MemberType="Property" Name="LocalIndex" />
+ <Member MemberType="Property" Name="LocalType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.MethodBuilder">
+ <Member Name="DefineGenericParameters(System.String[])" />
+ <Member Name="DefineParameter(System.Int32,System.Reflection.ParameterAttributes,System.String)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CallingConvention" />
+ <Member Name="get_ContainsGenericParameters" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_InitLocals" />
+ <Member Name="get_IsGenericMethod" />
+ <Member Name="get_IsGenericMethodDefinition" />
+ <Member Name="get_MethodHandle" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_ReturnParameter" />
+ <Member Name="get_ReturnTypeCustomAttributes" />
+ <Member Name="get_Signature" />
+ <Member Name="GetBaseDefinition" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetGenericArguments" />
+ <Member Name="GetGenericMethodDefinition" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetILGenerator" />
+ <Member Name="GetILGenerator(System.Int32)" />
+ <Member Name="GetMethodImplementationFlags" />
+ <Member Name="GetModule" />
+ <Member Name="GetParameters" />
+ <Member Name="GetToken" />
+ <Member Name="Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="MakeGenericMethod(System.Type[])" />
+ <Member Name="set_InitLocals(System.Boolean)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetImplementationFlags(System.Reflection.MethodImplAttributes)" />
+ <Member Name="SetParameters(System.Type[])" />
+ <Member Name="SetReturnType(System.Type)" />
+ <Member Name="SetSignature(System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CallingConvention" />
+ <Member MemberType="Property" Name="ContainsGenericParameters" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="InitLocals" />
+ <Member MemberType="Property" Name="IsGenericMethod" />
+ <Member MemberType="Property" Name="IsGenericMethodDefinition" />
+ <Member MemberType="Property" Name="MethodHandle" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="ReturnParameter" />
+ <Member MemberType="Property" Name="ReturnTypeCustomAttributes" />
+ <Member MemberType="Property" Name="Signature" />
+ </Type>
+ <Type Name="System.Reflection.Emit.MethodToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.MethodToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.MethodToken,System.Reflection.Emit.MethodToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.MethodToken,System.Reflection.Emit.MethodToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.ModuleBuilder">
+ <Member Name="CreateGlobalFunctions" />
+ <Member Name="DefineDocument(System.String,System.Guid,System.Guid,System.Guid)" />
+ <Member Name="DefineEnum(System.String,System.Reflection.TypeAttributes,System.Type)" />
+ <Member Name="DefineGlobalMethod(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[])" />
+ <Member Name="DefineGlobalMethod(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="DefineGlobalMethod(System.String,System.Reflection.MethodAttributes,System.Type,System.Type[])" />
+ <Member Name="DefineInitializedData(System.String,System.Byte[],System.Reflection.FieldAttributes)" />
+ <Member Name="DefineType(System.String)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes,System.Type)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes,System.Type,System.Int32)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes,System.Type,System.Reflection.Emit.PackingSize)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes,System.Type,System.Reflection.Emit.PackingSize,System.Int32)" />
+ <Member Name="DefineType(System.String,System.Reflection.TypeAttributes,System.Type,System.Type[])" />
+ <Member Name="DefineUninitializedData(System.String,System.Int32,System.Reflection.FieldAttributes)" />
+ <Member Name="get_FullyQualifiedName" />
+ <Member Name="GetArrayMethod(System.Type,System.String,System.Reflection.CallingConventions,System.Type,System.Type[])" />
+ <Member Name="GetArrayMethodToken(System.Type,System.String,System.Reflection.CallingConventions,System.Type,System.Type[])" />
+ <Member Name="GetConstructorToken(System.Reflection.ConstructorInfo)" />
+ <Member Name="GetFieldToken(System.Reflection.FieldInfo)" />
+ <Member Name="GetMethodToken(System.Reflection.MethodInfo)" />
+ <Member Name="GetSignatureToken(System.Byte[],System.Int32)" />
+ <Member Name="GetSignatureToken(System.Reflection.Emit.SignatureHelper)" />
+ <Member Name="GetStringConstant(System.String)" />
+ <Member Name="GetType(System.String)" />
+ <Member Name="GetType(System.String,System.Boolean)" />
+ <Member Name="GetType(System.String,System.Boolean,System.Boolean)" />
+ <Member Name="GetTypes" />
+ <Member Name="GetTypeToken(System.String)" />
+ <Member Name="GetTypeToken(System.Type)" />
+ <Member Name="IsTransient" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member MemberType="Property" Name="FullyQualifiedName" />
+ </Type>
+ <Type Name="System.Reflection.Emit.OpCode">
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.OpCode)" />
+ <Member Name="get_FlowControl" />
+ <Member Name="get_Name" />
+ <Member Name="get_OpCodeType" />
+ <Member Name="get_OperandType" />
+ <Member Name="get_Size" />
+ <Member Name="get_StackBehaviourPop" />
+ <Member Name="get_StackBehaviourPush" />
+ <Member Name="get_Value" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.OpCode,System.Reflection.Emit.OpCode)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.OpCode,System.Reflection.Emit.OpCode)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="FlowControl" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="OpCodeType" />
+ <Member MemberType="Property" Name="OperandType" />
+ <Member MemberType="Property" Name="Size" />
+ <Member MemberType="Property" Name="StackBehaviourPop" />
+ <Member MemberType="Property" Name="StackBehaviourPush" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Reflection.Emit.OpCodes">
+ <Member MemberType="Field" Name="Add" />
+ <Member MemberType="Field" Name="Add_Ovf" />
+ <Member MemberType="Field" Name="Add_Ovf_Un" />
+ <Member MemberType="Field" Name="And" />
+ <Member MemberType="Field" Name="Arglist" />
+ <Member MemberType="Field" Name="Beq" />
+ <Member MemberType="Field" Name="Beq_S" />
+ <Member MemberType="Field" Name="Bge" />
+ <Member MemberType="Field" Name="Bge_S" />
+ <Member MemberType="Field" Name="Bge_Un" />
+ <Member MemberType="Field" Name="Bge_Un_S" />
+ <Member MemberType="Field" Name="Bgt" />
+ <Member MemberType="Field" Name="Bgt_S" />
+ <Member MemberType="Field" Name="Bgt_Un" />
+ <Member MemberType="Field" Name="Bgt_Un_S" />
+ <Member MemberType="Field" Name="Ble" />
+ <Member MemberType="Field" Name="Ble_S" />
+ <Member MemberType="Field" Name="Ble_Un" />
+ <Member MemberType="Field" Name="Ble_Un_S" />
+ <Member MemberType="Field" Name="Blt" />
+ <Member MemberType="Field" Name="Blt_S" />
+ <Member MemberType="Field" Name="Blt_Un" />
+ <Member MemberType="Field" Name="Blt_Un_S" />
+ <Member MemberType="Field" Name="Bne_Un" />
+ <Member MemberType="Field" Name="Bne_Un_S" />
+ <Member MemberType="Field" Name="Box" />
+ <Member MemberType="Field" Name="Br" />
+ <Member MemberType="Field" Name="Br_S" />
+ <Member MemberType="Field" Name="Break" />
+ <Member MemberType="Field" Name="Brfalse" />
+ <Member MemberType="Field" Name="Brfalse_S" />
+ <Member MemberType="Field" Name="Brtrue" />
+ <Member MemberType="Field" Name="Brtrue_S" />
+ <Member MemberType="Field" Name="Call" />
+ <Member MemberType="Field" Name="Calli" />
+ <Member MemberType="Field" Name="Callvirt" />
+ <Member MemberType="Field" Name="Castclass" />
+ <Member MemberType="Field" Name="Ceq" />
+ <Member MemberType="Field" Name="Cgt" />
+ <Member MemberType="Field" Name="Cgt_Un" />
+ <Member MemberType="Field" Name="Ckfinite" />
+ <Member MemberType="Field" Name="Clt" />
+ <Member MemberType="Field" Name="Clt_Un" />
+ <Member MemberType="Field" Name="Constrained" />
+ <Member MemberType="Field" Name="Conv_I" />
+ <Member MemberType="Field" Name="Conv_I1" />
+ <Member MemberType="Field" Name="Conv_I2" />
+ <Member MemberType="Field" Name="Conv_I4" />
+ <Member MemberType="Field" Name="Conv_I8" />
+ <Member MemberType="Field" Name="Conv_Ovf_I" />
+ <Member MemberType="Field" Name="Conv_Ovf_I_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_I1" />
+ <Member MemberType="Field" Name="Conv_Ovf_I1_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_I2" />
+ <Member MemberType="Field" Name="Conv_Ovf_I2_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_I4" />
+ <Member MemberType="Field" Name="Conv_Ovf_I4_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_I8" />
+ <Member MemberType="Field" Name="Conv_Ovf_I8_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_U" />
+ <Member MemberType="Field" Name="Conv_Ovf_U_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_U1" />
+ <Member MemberType="Field" Name="Conv_Ovf_U1_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_U2" />
+ <Member MemberType="Field" Name="Conv_Ovf_U2_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_U4" />
+ <Member MemberType="Field" Name="Conv_Ovf_U4_Un" />
+ <Member MemberType="Field" Name="Conv_Ovf_U8" />
+ <Member MemberType="Field" Name="Conv_Ovf_U8_Un" />
+ <Member MemberType="Field" Name="Conv_R_Un" />
+ <Member MemberType="Field" Name="Conv_R4" />
+ <Member MemberType="Field" Name="Conv_R8" />
+ <Member MemberType="Field" Name="Conv_U" />
+ <Member MemberType="Field" Name="Conv_U1" />
+ <Member MemberType="Field" Name="Conv_U2" />
+ <Member MemberType="Field" Name="Conv_U4" />
+ <Member MemberType="Field" Name="Conv_U8" />
+ <Member MemberType="Field" Name="Cpblk" />
+ <Member MemberType="Field" Name="Cpobj" />
+ <Member MemberType="Field" Name="Div" />
+ <Member MemberType="Field" Name="Div_Un" />
+ <Member MemberType="Field" Name="Dup" />
+ <Member MemberType="Field" Name="Endfilter" />
+ <Member MemberType="Field" Name="Endfinally" />
+ <Member MemberType="Field" Name="Initblk" />
+ <Member MemberType="Field" Name="Initobj" />
+ <Member MemberType="Field" Name="Isinst" />
+ <Member MemberType="Field" Name="Jmp" />
+ <Member MemberType="Field" Name="Ldarg" />
+ <Member MemberType="Field" Name="Ldarg_0" />
+ <Member MemberType="Field" Name="Ldarg_1" />
+ <Member MemberType="Field" Name="Ldarg_2" />
+ <Member MemberType="Field" Name="Ldarg_3" />
+ <Member MemberType="Field" Name="Ldarg_S" />
+ <Member MemberType="Field" Name="Ldarga" />
+ <Member MemberType="Field" Name="Ldarga_S" />
+ <Member MemberType="Field" Name="Ldc_I4" />
+ <Member MemberType="Field" Name="Ldc_I4_0" />
+ <Member MemberType="Field" Name="Ldc_I4_1" />
+ <Member MemberType="Field" Name="Ldc_I4_2" />
+ <Member MemberType="Field" Name="Ldc_I4_3" />
+ <Member MemberType="Field" Name="Ldc_I4_4" />
+ <Member MemberType="Field" Name="Ldc_I4_5" />
+ <Member MemberType="Field" Name="Ldc_I4_6" />
+ <Member MemberType="Field" Name="Ldc_I4_7" />
+ <Member MemberType="Field" Name="Ldc_I4_8" />
+ <Member MemberType="Field" Name="Ldc_I4_M1" />
+ <Member MemberType="Field" Name="Ldc_I4_S" />
+ <Member MemberType="Field" Name="Ldc_I8" />
+ <Member MemberType="Field" Name="Ldc_R4" />
+ <Member MemberType="Field" Name="Ldc_R8" />
+ <Member MemberType="Field" Name="Ldelem" />
+ <Member MemberType="Field" Name="Ldelem_I" />
+ <Member MemberType="Field" Name="Ldelem_I1" />
+ <Member MemberType="Field" Name="Ldelem_I2" />
+ <Member MemberType="Field" Name="Ldelem_I4" />
+ <Member MemberType="Field" Name="Ldelem_I8" />
+ <Member MemberType="Field" Name="Ldelem_R4" />
+ <Member MemberType="Field" Name="Ldelem_R8" />
+ <Member MemberType="Field" Name="Ldelem_Ref" />
+ <Member MemberType="Field" Name="Ldelem_U1" />
+ <Member MemberType="Field" Name="Ldelem_U2" />
+ <Member MemberType="Field" Name="Ldelem_U4" />
+ <Member MemberType="Field" Name="Ldelema" />
+ <Member MemberType="Field" Name="Ldfld" />
+ <Member MemberType="Field" Name="Ldflda" />
+ <Member MemberType="Field" Name="Ldftn" />
+ <Member MemberType="Field" Name="Ldind_I" />
+ <Member MemberType="Field" Name="Ldind_I1" />
+ <Member MemberType="Field" Name="Ldind_I2" />
+ <Member MemberType="Field" Name="Ldind_I4" />
+ <Member MemberType="Field" Name="Ldind_I8" />
+ <Member MemberType="Field" Name="Ldind_R4" />
+ <Member MemberType="Field" Name="Ldind_R8" />
+ <Member MemberType="Field" Name="Ldind_Ref" />
+ <Member MemberType="Field" Name="Ldind_U1" />
+ <Member MemberType="Field" Name="Ldind_U2" />
+ <Member MemberType="Field" Name="Ldind_U4" />
+ <Member MemberType="Field" Name="Ldlen" />
+ <Member MemberType="Field" Name="Ldloc" />
+ <Member MemberType="Field" Name="Ldloc_0" />
+ <Member MemberType="Field" Name="Ldloc_1" />
+ <Member MemberType="Field" Name="Ldloc_2" />
+ <Member MemberType="Field" Name="Ldloc_3" />
+ <Member MemberType="Field" Name="Ldloc_S" />
+ <Member MemberType="Field" Name="Ldloca" />
+ <Member MemberType="Field" Name="Ldloca_S" />
+ <Member MemberType="Field" Name="Ldnull" />
+ <Member MemberType="Field" Name="Ldobj" />
+ <Member MemberType="Field" Name="Ldsfld" />
+ <Member MemberType="Field" Name="Ldsflda" />
+ <Member MemberType="Field" Name="Ldstr" />
+ <Member MemberType="Field" Name="Ldtoken" />
+ <Member MemberType="Field" Name="Ldvirtftn" />
+ <Member MemberType="Field" Name="Leave" />
+ <Member MemberType="Field" Name="Leave_S" />
+ <Member MemberType="Field" Name="Localloc" />
+ <Member MemberType="Field" Name="Mkrefany" />
+ <Member MemberType="Field" Name="Mul" />
+ <Member MemberType="Field" Name="Mul_Ovf" />
+ <Member MemberType="Field" Name="Mul_Ovf_Un" />
+ <Member MemberType="Field" Name="Neg" />
+ <Member MemberType="Field" Name="Newarr" />
+ <Member MemberType="Field" Name="Newobj" />
+ <Member MemberType="Field" Name="Nop" />
+ <Member MemberType="Field" Name="Not" />
+ <Member MemberType="Field" Name="Or" />
+ <Member MemberType="Field" Name="Pop" />
+ <Member MemberType="Field" Name="Prefix1" />
+ <Member MemberType="Field" Name="Prefix2" />
+ <Member MemberType="Field" Name="Prefix3" />
+ <Member MemberType="Field" Name="Prefix4" />
+ <Member MemberType="Field" Name="Prefix5" />
+ <Member MemberType="Field" Name="Prefix6" />
+ <Member MemberType="Field" Name="Prefix7" />
+ <Member MemberType="Field" Name="Prefixref" />
+ <Member MemberType="Field" Name="Readonly" />
+ <Member MemberType="Field" Name="Refanytype" />
+ <Member MemberType="Field" Name="Refanyval" />
+ <Member MemberType="Field" Name="Rem" />
+ <Member MemberType="Field" Name="Rem_Un" />
+ <Member MemberType="Field" Name="Ret" />
+ <Member MemberType="Field" Name="Rethrow" />
+ <Member MemberType="Field" Name="Shl" />
+ <Member MemberType="Field" Name="Shr" />
+ <Member MemberType="Field" Name="Shr_Un" />
+ <Member MemberType="Field" Name="Sizeof" />
+ <Member MemberType="Field" Name="Starg" />
+ <Member MemberType="Field" Name="Starg_S" />
+ <Member MemberType="Field" Name="Stelem" />
+ <Member MemberType="Field" Name="Stelem_I" />
+ <Member MemberType="Field" Name="Stelem_I1" />
+ <Member MemberType="Field" Name="Stelem_I2" />
+ <Member MemberType="Field" Name="Stelem_I4" />
+ <Member MemberType="Field" Name="Stelem_I8" />
+ <Member MemberType="Field" Name="Stelem_R4" />
+ <Member MemberType="Field" Name="Stelem_R8" />
+ <Member MemberType="Field" Name="Stelem_Ref" />
+ <Member MemberType="Field" Name="Stfld" />
+ <Member MemberType="Field" Name="Stind_I" />
+ <Member MemberType="Field" Name="Stind_I1" />
+ <Member MemberType="Field" Name="Stind_I2" />
+ <Member MemberType="Field" Name="Stind_I4" />
+ <Member MemberType="Field" Name="Stind_I8" />
+ <Member MemberType="Field" Name="Stind_R4" />
+ <Member MemberType="Field" Name="Stind_R8" />
+ <Member MemberType="Field" Name="Stind_Ref" />
+ <Member MemberType="Field" Name="Stloc" />
+ <Member MemberType="Field" Name="Stloc_0" />
+ <Member MemberType="Field" Name="Stloc_1" />
+ <Member MemberType="Field" Name="Stloc_2" />
+ <Member MemberType="Field" Name="Stloc_3" />
+ <Member MemberType="Field" Name="Stloc_S" />
+ <Member MemberType="Field" Name="Stobj" />
+ <Member MemberType="Field" Name="Stsfld" />
+ <Member MemberType="Field" Name="Sub" />
+ <Member MemberType="Field" Name="Sub_Ovf" />
+ <Member MemberType="Field" Name="Sub_Ovf_Un" />
+ <Member MemberType="Field" Name="Switch" />
+ <Member MemberType="Field" Name="Tailcall" />
+ <Member MemberType="Field" Name="Throw" />
+ <Member MemberType="Field" Name="Unaligned" />
+ <Member MemberType="Field" Name="Unbox" />
+ <Member MemberType="Field" Name="Unbox_Any" />
+ <Member MemberType="Field" Name="Volatile" />
+ <Member MemberType="Field" Name="Xor" />
+ <Member Name="TakesSingleByteArgument(System.Reflection.Emit.OpCode)" />
+ </Type>
+ <Type Name="System.Reflection.Emit.OpCodeType">
+ <Member MemberType="Field" Name="Macro" />
+ <Member MemberType="Field" Name="Nternal" />
+ <Member MemberType="Field" Name="Objmodel" />
+ <Member MemberType="Field" Name="Prefix" />
+ <Member MemberType="Field" Name="Primitive" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.Emit.OperandType">
+ <Member MemberType="Field" Name="InlineBrTarget" />
+ <Member MemberType="Field" Name="InlineField" />
+ <Member MemberType="Field" Name="InlineI" />
+ <Member MemberType="Field" Name="InlineI8" />
+ <Member MemberType="Field" Name="InlineMethod" />
+ <Member MemberType="Field" Name="InlineNone" />
+ <Member MemberType="Field" Name="InlineR" />
+ <Member MemberType="Field" Name="InlineSig" />
+ <Member MemberType="Field" Name="InlineString" />
+ <Member MemberType="Field" Name="InlineSwitch" />
+ <Member MemberType="Field" Name="InlineTok" />
+ <Member MemberType="Field" Name="InlineType" />
+ <Member MemberType="Field" Name="InlineVar" />
+ <Member MemberType="Field" Name="ShortInlineBrTarget" />
+ <Member MemberType="Field" Name="ShortInlineI" />
+ <Member MemberType="Field" Name="ShortInlineR" />
+ <Member MemberType="Field" Name="ShortInlineVar" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.Emit.PackingSize">
+ <Member MemberType="Field" Name="Size1" />
+ <Member MemberType="Field" Name="Size128" />
+ <Member MemberType="Field" Name="Size16" />
+ <Member MemberType="Field" Name="Size2" />
+ <Member MemberType="Field" Name="Size32" />
+ <Member MemberType="Field" Name="Size4" />
+ <Member MemberType="Field" Name="Size64" />
+ <Member MemberType="Field" Name="Size8" />
+ <Member MemberType="Field" Name="Unspecified" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.Emit.ParameterBuilder">
+ <Member Name="get_Attributes" />
+ <Member Name="get_IsIn" />
+ <Member Name="get_IsOptional" />
+ <Member Name="get_IsOut" />
+ <Member Name="get_Name" />
+ <Member Name="get_Position" />
+ <Member Name="GetToken" />
+ <Member Name="SetConstant(System.Object)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="IsIn" />
+ <Member MemberType="Property" Name="IsOptional" />
+ <Member MemberType="Property" Name="IsOut" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Position" />
+ </Type>
+ <Type Name="System.Reflection.Emit.ParameterToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.ParameterToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.ParameterToken,System.Reflection.Emit.ParameterToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.ParameterToken,System.Reflection.Emit.ParameterToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.PEFileKinds">
+ <Member MemberType="Field" Name="ConsoleApplication" />
+ <Member MemberType="Field" Name="Dll" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="WindowApplication" />
+ </Type>
+ <Type Name="System.Reflection.Emit.PropertyBuilder">
+ <Member Name="AddOtherMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_PropertyToken" />
+ <Member Name="get_PropertyType" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="GetAccessors(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetGetMethod(System.Boolean)" />
+ <Member Name="GetIndexParameters" />
+ <Member Name="GetSetMethod(System.Boolean)" />
+ <Member Name="GetValue(System.Object,System.Object[])" />
+ <Member Name="GetValue(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="SetConstant(System.Object)" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetGetMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="SetSetMethod(System.Reflection.Emit.MethodBuilder)" />
+ <Member Name="SetValue(System.Object,System.Object,System.Object[])" />
+ <Member Name="SetValue(System.Object,System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="PropertyToken" />
+ <Member MemberType="Property" Name="PropertyType" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.PropertyToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.PropertyToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.PropertyToken,System.Reflection.Emit.PropertyToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.PropertyToken,System.Reflection.Emit.PropertyToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.SignatureHelper">
+ <Member Name="AddArgument(System.Type)" />
+ <Member Name="AddArgument(System.Type,System.Boolean)" />
+ <Member Name="AddArgument(System.Type,System.Type[],System.Type[])" />
+ <Member Name="AddArguments(System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="AddSentinel" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetFieldSigHelper(System.Reflection.Module)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetLocalVarSigHelper" />
+ <Member Name="GetLocalVarSigHelper(System.Reflection.Module)" />
+ <Member Name="GetMethodSigHelper(System.Reflection.CallingConventions,System.Type)" />
+ <Member Name="GetMethodSigHelper(System.Reflection.Module,System.Reflection.CallingConventions,System.Type)" />
+ <Member Name="GetMethodSigHelper(System.Reflection.Module,System.Runtime.InteropServices.CallingConvention,System.Type)" />
+ <Member Name="GetMethodSigHelper(System.Reflection.Module,System.Type,System.Type[])" />
+ <Member Name="GetMethodSigHelper(System.Runtime.InteropServices.CallingConvention,System.Type)" />
+ <Member Name="GetPropertySigHelper(System.Reflection.Module,System.Type,System.Type[])" />
+ <Member Name="GetPropertySigHelper(System.Reflection.Module,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="GetPropertySigHelper(System.Reflection.Module,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="GetSignature" />
+ <Member Name="ToString" />
+ </Type>
+ <Type Name="System.Reflection.Emit.SignatureToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.SignatureToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.SignatureToken,System.Reflection.Emit.SignatureToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.SignatureToken,System.Reflection.Emit.SignatureToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.StackBehaviour">
+ <Member MemberType="Field" Name="Pop0" />
+ <Member MemberType="Field" Name="Pop1" />
+ <Member MemberType="Field" Name="Pop1_pop1" />
+ <Member MemberType="Field" Name="Popi" />
+ <Member MemberType="Field" Name="Popi_pop1" />
+ <Member MemberType="Field" Name="Popi_popi" />
+ <Member MemberType="Field" Name="Popi_popi_popi" />
+ <Member MemberType="Field" Name="Popi_popi8" />
+ <Member MemberType="Field" Name="Popi_popr4" />
+ <Member MemberType="Field" Name="Popi_popr8" />
+ <Member MemberType="Field" Name="Popref" />
+ <Member MemberType="Field" Name="Popref_pop1" />
+ <Member MemberType="Field" Name="Popref_popi" />
+ <Member MemberType="Field" Name="Popref_popi_pop1" />
+ <Member MemberType="Field" Name="Popref_popi_popi" />
+ <Member MemberType="Field" Name="Popref_popi_popi8" />
+ <Member MemberType="Field" Name="Popref_popi_popr4" />
+ <Member MemberType="Field" Name="Popref_popi_popr8" />
+ <Member MemberType="Field" Name="Popref_popi_popref" />
+ <Member MemberType="Field" Name="Push0" />
+ <Member MemberType="Field" Name="Push1" />
+ <Member MemberType="Field" Name="Push1_push1" />
+ <Member MemberType="Field" Name="Pushi" />
+ <Member MemberType="Field" Name="Pushi8" />
+ <Member MemberType="Field" Name="Pushr4" />
+ <Member MemberType="Field" Name="Pushr8" />
+ <Member MemberType="Field" Name="Pushref" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Varpop" />
+ <Member MemberType="Field" Name="Varpush" />
+ </Type>
+ <Type Name="System.Reflection.Emit.StringToken">
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.StringToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.StringToken,System.Reflection.Emit.StringToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.StringToken,System.Reflection.Emit.StringToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.Emit.TypeBuilder">
+ <Member MemberType="Field" Name="UnspecifiedTypeSize" />
+ <Member Name="AddInterfaceImplementation(System.Type)" />
+ <Member Name="CreateType" />
+ <Member Name="IsAssignableFrom(System.Reflection.TypeInfo)" />
+ <Member Name="CreateTypeInfo" />
+ <Member Name="DefineConstructor(System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type[])" />
+ <Member Name="DefineConstructor(System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="DefineDefaultConstructor(System.Reflection.MethodAttributes)" />
+ <Member Name="DefineEvent(System.String,System.Reflection.EventAttributes,System.Type)" />
+ <Member Name="DefineField(System.String,System.Type,System.Reflection.FieldAttributes)" />
+ <Member Name="DefineField(System.String,System.Type,System.Type[],System.Type[],System.Reflection.FieldAttributes)" />
+ <Member Name="DefineGenericParameters(System.String[])" />
+ <Member Name="DefineInitializedData(System.String,System.Byte[],System.Reflection.FieldAttributes)" />
+ <Member Name="DefineMethod(System.String,System.Reflection.MethodAttributes)" />
+ <Member Name="DefineMethod(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions)" />
+ <Member Name="DefineMethod(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[])" />
+ <Member Name="DefineMethod(System.String,System.Reflection.MethodAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="DefineMethod(System.String,System.Reflection.MethodAttributes,System.Type,System.Type[])" />
+ <Member Name="DefineMethodOverride(System.Reflection.MethodInfo,System.Reflection.MethodInfo)" />
+ <Member Name="DefineNestedType(System.String)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes,System.Type)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes,System.Type,System.Int32)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes,System.Type,System.Reflection.Emit.PackingSize)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes,System.Type,System.Reflection.Emit.PackingSize,System.Int32)" />
+ <Member Name="DefineNestedType(System.String,System.Reflection.TypeAttributes,System.Type,System.Type[])" />
+ <Member Name="DefineProperty(System.String,System.Reflection.PropertyAttributes,System.Type,System.Type[])" />
+ <Member Name="DefineProperty(System.String,System.Reflection.PropertyAttributes,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="DefineProperty(System.String,System.Reflection.PropertyAttributes,System.Reflection.CallingConventions,System.Type,System.Type[])" />
+ <Member Name="DefineProperty(System.String,System.Reflection.PropertyAttributes,System.Reflection.CallingConventions,System.Type,System.Type[],System.Type[],System.Type[],System.Type[][],System.Type[][])" />
+ <Member Name="DefineTypeInitializer" />
+ <Member Name="DefineUninitializedData(System.String,System.Int32,System.Reflection.FieldAttributes)" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_AssemblyQualifiedName" />
+ <Member Name="get_BaseType" />
+ <Member Name="get_DeclaringMethod" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_FullName" />
+ <Member Name="get_GenericParameterAttributes" />
+ <Member Name="get_GenericParameterPosition" />
+ <Member Name="get_GUID" />
+ <Member Name="get_IsGenericParameter" />
+ <Member Name="get_IsGenericType" />
+ <Member Name="get_IsGenericTypeDefinition" />
+ <Member Name="get_Module" />
+ <Member Name="get_Name" />
+ <Member Name="get_Namespace" />
+ <Member Name="get_PackingSize" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_Size" />
+ <Member Name="get_TypeHandle" />
+ <Member Name="get_TypeToken" />
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetAttributeFlagsImpl" />
+ <Member Name="GetConstructor(System.Type,System.Reflection.ConstructorInfo)" />
+ <Member Name="GetConstructorImpl(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructors(System.Reflection.BindingFlags)" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetElementType" />
+ <Member Name="GetEvent(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents" />
+ <Member Name="GetEvents(System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.Type,System.Reflection.FieldInfo)" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetGenericArguments" />
+ <Member Name="GetGenericTypeDefinition" />
+ <Member Name="GetInterface(System.String,System.Boolean)" />
+ <Member Name="GetInterfaceMap(System.Type)" />
+ <Member Name="GetInterfaces" />
+ <Member Name="GetMember(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.Type,System.Reflection.MethodInfo)" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedType(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedTypes(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="GetPropertyImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="HasElementTypeImpl" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ <Member Name="IsArrayImpl" />
+ <Member Name="IsAssignableFrom(System.Type)" />
+ <Member Name="IsByRefImpl" />
+ <Member Name="IsCOMObjectImpl" />
+ <Member Name="IsCreated" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsPointerImpl" />
+ <Member Name="IsPrimitiveImpl" />
+ <Member Name="IsSubclassOf(System.Type)" />
+ <Member Name="MakeArrayType" />
+ <Member Name="MakeArrayType(System.Int32)" />
+ <Member Name="MakeByRefType" />
+ <Member Name="MakeGenericType(System.Type[])" />
+ <Member Name="MakePointerType" />
+ <Member Name="SetCustomAttribute(System.Reflection.ConstructorInfo,System.Byte[])" />
+ <Member Name="SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder)" />
+ <Member Name="SetParent(System.Type)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="AssemblyQualifiedName" />
+ <Member MemberType="Property" Name="BaseType" />
+ <Member MemberType="Property" Name="DeclaringMethod" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="GenericParameterAttributes" />
+ <Member MemberType="Property" Name="GenericParameterPosition" />
+ <Member MemberType="Property" Name="GUID" />
+ <Member MemberType="Property" Name="IsGenericParameter" />
+ <Member MemberType="Property" Name="IsGenericType" />
+ <Member MemberType="Property" Name="IsGenericTypeDefinition" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Namespace" />
+ <Member MemberType="Property" Name="PackingSize" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="Size" />
+ <Member MemberType="Property" Name="TypeHandle" />
+ <Member MemberType="Property" Name="TypeToken" />
+ <Member MemberType="Property" Name="UnderlyingSystemType" />
+ </Type>
+ <Type Name="System.Reflection.Emit.TypeToken">
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Reflection.Emit.TypeToken)" />
+ <Member Name="get_Token" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Reflection.Emit.TypeToken,System.Reflection.Emit.TypeToken)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.TypeToken,System.Reflection.Emit.TypeToken)" />
+ <Member MemberType="Property" Name="Token" />
+ </Type>
+ <Type Name="System.Reflection.EventAttributes">
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="RTSpecialName" />
+ <Member MemberType="Field" Name="SpecialName" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.EventInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.EventInfo,System.Reflection.EventInfo)" />
+ <Member Name="op_Inequality(System.Reflection.EventInfo,System.Reflection.EventInfo)" />
+ <Member Name="AddEventHandler(System.Object,System.Delegate)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_AddMethod" />
+ <Member Name="get_RaiseMethod" />
+ <Member Name="get_RemoveMethod" />
+ <Member Name="get_EventHandlerType" />
+ <Member Name="get_IsMulticast" />
+ <Member Name="get_IsSpecialName" />
+ <Member Name="get_MemberType" />
+ <Member Name="GetAddMethod" />
+ <Member Name="GetAddMethod(System.Boolean)" />
+ <Member Name="GetOtherMethods" />
+ <Member Name="GetOtherMethods(System.Boolean)" />
+ <Member Name="GetRaiseMethod" />
+ <Member Name="GetRaiseMethod(System.Boolean)" />
+ <Member Name="GetRemoveMethod" />
+ <Member Name="GetRemoveMethod(System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="RemoveEventHandler(System.Object,System.Delegate)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="AddMethod" />
+ <Member MemberType="Property" Name="RaiseMethod" />
+ <Member MemberType="Property" Name="RemoveMethod" />
+ <Member MemberType="Property" Name="EventHandlerType" />
+ <Member MemberType="Property" Name="IsMulticast" />
+ <Member MemberType="Property" Name="IsSpecialName" />
+ <Member MemberType="Property" Name="MemberType" />
+ </Type>
+ <Type Name="System.Reflection.FieldAttributes">
+ <Member MemberType="Field" Name="Assembly" />
+ <Member MemberType="Field" Name="FamANDAssem" />
+ <Member MemberType="Field" Name="Family" />
+ <Member MemberType="Field" Name="FamORAssem" />
+ <Member MemberType="Field" Name="FieldAccessMask" />
+ <Member MemberType="Field" Name="HasDefault" />
+ <Member MemberType="Field" Name="HasFieldMarshal" />
+ <Member MemberType="Field" Name="HasFieldRVA" />
+ <Member MemberType="Field" Name="InitOnly" />
+ <Member MemberType="Field" Name="Literal" />
+ <Member MemberType="Field" Name="NotSerialized" />
+ <Member MemberType="Field" Name="PinvokeImpl" />
+ <Member MemberType="Field" Name="Private" />
+ <Member MemberType="Field" Name="PrivateScope" />
+ <Member MemberType="Field" Name="Public" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="RTSpecialName" />
+ <Member MemberType="Field" Name="SpecialName" />
+ <Member MemberType="Field" Name="Static" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.FieldInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.FieldInfo,System.Reflection.FieldInfo)" />
+ <Member Name="op_Inequality(System.Reflection.FieldInfo,System.Reflection.FieldInfo)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_FieldHandle" />
+ <Member Name="get_FieldType" />
+ <Member Name="get_IsAssembly" />
+ <Member Name="get_IsFamily" />
+ <Member Name="get_IsFamilyAndAssembly" />
+ <Member Name="get_IsFamilyOrAssembly" />
+ <Member Name="get_IsInitOnly" />
+ <Member Name="get_IsLiteral" />
+ <Member Name="get_IsNotSerialized" />
+ <Member Name="get_IsPinvokeImpl" />
+ <Member Name="get_IsPrivate" />
+ <Member Name="get_IsPublic" />
+ <Member Name="get_IsSecurityCritical" />
+ <Member Name="get_IsSecuritySafeCritical" />
+ <Member Name="get_IsSecurityTransparent" />
+ <Member Name="get_IsSpecialName" />
+ <Member Name="get_IsStatic" />
+ <Member Name="get_MemberType" />
+ <Member Name="GetFieldFromHandle(System.RuntimeFieldHandle)" />
+ <Member Name="GetFieldFromHandle(System.RuntimeFieldHandle,System.RuntimeTypeHandle)" />
+ <Member Name="GetValue(System.Object)" />
+ <Member Name="GetOptionalCustomModifiers" />
+ <Member Name="GetRequiredCustomModifiers" />
+ <Member Name="GetRawConstantValue" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="SetValue(System.Object,System.Object)" />
+ <Member Name="SetValue(System.Object,System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="FieldHandle" />
+ <Member MemberType="Property" Name="FieldType" />
+ <Member MemberType="Property" Name="IsAssembly" />
+ <Member MemberType="Property" Name="IsFamily" />
+ <Member MemberType="Property" Name="IsFamilyAndAssembly" />
+ <Member MemberType="Property" Name="IsFamilyOrAssembly" />
+ <Member MemberType="Property" Name="IsInitOnly" />
+ <Member MemberType="Property" Name="IsLiteral" />
+ <Member MemberType="Property" Name="IsNotSerialized" />
+ <Member MemberType="Property" Name="IsPinvokeImpl" />
+ <Member MemberType="Property" Name="IsPrivate" />
+ <Member MemberType="Property" Name="IsPublic" />
+ <Member MemberType="Property" Name="IsSpecialName" />
+ <Member MemberType="Property" Name="IsStatic" />
+ <Member MemberType="Property" Name="MemberType" />
+ </Type>
+ <Type Name="System.Reflection.ICustomAttributeProvider">
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ </Type>
+ <Type Name="System.Reflection.ImageFileMachine">
+ <Member MemberType="Field" Name="I386" />
+ <Member MemberType="Field" Name="IA64" />
+ <Member MemberType="Field" Name="AMD64" />
+ <Member MemberType="Field" Name="ARM" />
+ </Type>
+ <Type Name="System.Reflection.InvalidFilterCriteriaException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.InterfaceMapping">
+ <Member MemberType="Field" Name="InterfaceMethods" />
+ <Member MemberType="Field" Name="InterfaceType" />
+ <Member MemberType="Field" Name="TargetMethods" />
+ <Member MemberType="Field" Name="TargetType" />
+ </Type>
+ <Type Name="System.Reflection.IReflect" >
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetMember(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperty(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetProperty(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.LoaderAllocator">
+ <Member Status="ImplRoot" Name="#ctor" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_slots" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_slotsUsed" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Reflection.ManifestResourceInfo">
+ <Member Name="#ctor(System.Reflection.Assembly,System.String,System.Reflection.ResourceLocation)" />
+ <Member MemberType="Property" Name="FileName" />
+ <Member MemberType="Property" Name="ReferencedAssembly" />
+ <Member MemberType="Property" Name="ResourceLocation" />
+ </Type>
+ <Type Name="System.Reflection.MemberInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.MemberInfo,System.Reflection.MemberInfo)" />
+ <Member Name="op_Inequality(System.Reflection.MemberInfo,System.Reflection.MemberInfo)" />
+ <Member Name="get_CustomAttributes" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_MemberType" />
+ <Member Name="get_MetadataToken" />
+ <Member Name="get_Name" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributesData" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member MemberType="Property" Name="CustomAttributes" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="MemberType" />
+ <Member MemberType="Property" Name="MetadataToken" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ </Type>
+ <Type Name="System.Reflection.MemberTypes">
+ <Member MemberType="Field" Name="All" />
+ <Member MemberType="Field" Name="Constructor" />
+ <Member MemberType="Field" Name="Custom" />
+ <Member MemberType="Field" Name="Event" />
+ <Member MemberType="Field" Name="Field" />
+ <Member MemberType="Field" Name="Method" />
+ <Member MemberType="Field" Name="NestedType" />
+ <Member MemberType="Field" Name="Property" />
+ <Member MemberType="Field" Name="TypeInfo" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.MethodAttributes">
+ <Member MemberType="Field" Name="Abstract" />
+ <Member MemberType="Field" Name="Assembly" />
+ <Member MemberType="Field" Name="FamANDAssem" />
+ <Member MemberType="Field" Name="Family" />
+ <Member MemberType="Field" Name="FamORAssem" />
+ <Member MemberType="Field" Name="Final" />
+ <Member MemberType="Field" Name="HasSecurity" />
+ <Member MemberType="Field" Name="HideBySig" />
+ <Member MemberType="Field" Name="MemberAccessMask" />
+ <Member MemberType="Field" Name="NewSlot" />
+ <Member MemberType="Field" Name="PinvokeImpl" />
+ <Member MemberType="Field" Name="Private" />
+ <Member MemberType="Field" Name="PrivateScope" />
+ <Member MemberType="Field" Name="Public" />
+ <Member MemberType="Field" Name="RequireSecObject" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="ReuseSlot" />
+ <Member MemberType="Field" Name="RTSpecialName" />
+ <Member MemberType="Field" Name="SpecialName" />
+ <Member MemberType="Field" Name="Static" />
+ <Member MemberType="Field" Name="UnmanagedExport" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Virtual" />
+ <Member MemberType="Field" Name="VtableLayoutMask" />
+ </Type>
+ <Type Name="System.Reflection.MethodBase">
+ <Member Name="#ctor" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CallingConvention" />
+ <Member Name="get_ContainsGenericParameters" />
+ <Member Name="get_IsAbstract" />
+ <Member Name="get_IsAssembly" />
+ <Member Name="get_IsConstructor" />
+ <Member Name="get_IsFamily" />
+ <Member Name="get_IsFamilyAndAssembly" />
+ <Member Name="get_IsFamilyOrAssembly" />
+ <Member Name="get_IsFinal" />
+ <Member Name="get_IsGenericMethod" />
+ <Member Name="get_IsGenericMethodDefinition" />
+ <Member Name="get_IsHideBySig" />
+ <Member Name="get_IsPrivate" />
+ <Member Name="get_IsPublic" />
+ <Member Name="get_IsSpecialName" />
+ <Member Name="get_IsStatic" />
+ <Member Name="get_IsVirtual" />
+ <Member Name="get_MethodHandle" />
+ <Member Name="get_MethodImplementationFlags" />
+ <Member Name="GetGenericArguments" />
+ <Member Status="ImplRoot" Name="GetMethodDesc" />
+ <Member Name="GetMethodFromHandle(System.RuntimeMethodHandle)" />
+ <Member Name="GetMethodFromHandle(System.RuntimeMethodHandle,System.RuntimeTypeHandle)" />
+ <Member Name="GetMethodImplementationFlags" />
+ <Member Name="GetParameters" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="op_Equality(System.Reflection.MethodBase,System.Reflection.MethodBase)" />
+ <Member Name="op_Inequality(System.Reflection.MethodBase,System.Reflection.MethodBase)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMethodBody" />
+ <Member Name="Invoke(System.Object,System.Object[])" />
+ <Member Name="Invoke(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CallingConvention" />
+ <Member MemberType="Property" Name="ContainsGenericParameters" />
+ <Member MemberType="Property" Name="IsAbstract" />
+ <Member MemberType="Property" Name="IsAssembly" />
+ <Member MemberType="Property" Name="IsConstructor" />
+ <Member MemberType="Property" Name="IsFamily" />
+ <Member MemberType="Property" Name="IsFamilyAndAssembly" />
+ <Member MemberType="Property" Name="IsFamilyOrAssembly" />
+ <Member MemberType="Property" Name="IsFinal" />
+ <Member MemberType="Property" Name="IsGenericMethod" />
+ <Member MemberType="Property" Name="IsGenericMethodDefinition" />
+ <Member MemberType="Property" Name="IsHideBySig" />
+ <Member MemberType="Property" Name="IsPrivate" />
+ <Member MemberType="Property" Name="IsPublic" />
+ <Member MemberType="Property" Name="IsSpecialName" />
+ <Member MemberType="Property" Name="IsStatic" />
+ <Member MemberType="Property" Name="IsVirtual" />
+ <Member MemberType="Property" Name="MethodHandle" />
+ <Member MemberType="Property" Name="MethodImplementationFlags" />
+ <Member Name="GetCurrentMethod" />
+ </Type>
+ <Type Name="System.Reflection.MethodImplAttributes">
+ <Member MemberType="Field" Name="AggressiveInlining" />
+ <Member MemberType="Field" Name="CodeTypeMask" />
+ <Member MemberType="Field" Name="ForwardRef" />
+ <Member MemberType="Field" Name="IL" />
+ <Member MemberType="Field" Name="InternalCall" />
+ <Member MemberType="Field" Name="Managed" />
+ <Member MemberType="Field" Name="ManagedMask" />
+ <Member MemberType="Field" Name="MaxMethodImplVal" />
+ <Member MemberType="Field" Name="Native" />
+ <Member MemberType="Field" Name="NoInlining" />
+ <Member MemberType="Field" Name="OPTIL" />
+ <Member MemberType="Field" Name="PreserveSig" />
+ <Member MemberType="Field" Name="Runtime" />
+ <Member MemberType="Field" Name="Synchronized" />
+ <Member MemberType="Field" Name="Unmanaged" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.MethodInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.MethodInfo,System.Reflection.MethodInfo)" />
+ <Member Name="op_Inequality(System.Reflection.MethodInfo,System.Reflection.MethodInfo)" />
+ <Member Name="get_MemberType" />
+ <Member Name="get_ReturnParameter" />
+ <Member Name="get_ReturnType" />
+ <Member Name="get_ReturnTypeCustomAttributes" />
+ <Member Name="GetBaseDefinition" />
+ <Member Name="GetGenericArguments" />
+ <Member Name="GetGenericMethodDefinition" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="MakeGenericMethod(System.Type[])" />
+ <Member MemberType="Property" Name="MemberType" />
+ <Member MemberType="Property" Name="ReturnParameter" />
+ <Member MemberType="Property" Name="ReturnType" />
+ <Member MemberType="Property" Name="ReturnTypeCustomAttributes" />
+ </Type>
+ <Type Name="System.Reflection.Missing">
+ <Member MemberType="Field" Name="Value" />
+ <Member Name="System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.Module">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.Module,System.Reflection.Module)" />
+ <Member Name="op_Inequality(System.Reflection.Module,System.Reflection.Module)" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_CustomAttributes" />
+ <Member Name="get_FullyQualifiedName" />
+ <Member Name="get_MDStreamVersion" />
+ <Member Name="get_MetadataToken" />
+ <Member Name="get_ModuleHandle" />
+ <Member Name="get_ModuleVersionId" />
+ <Member Name="get_Name" />
+ <Member Name="get_ScopeName" />
+ <Member Name="FindTypes(System.Reflection.TypeFilter,System.Object)" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributesData" />
+ <Member Name="GetField(System.String)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.String)" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethod(System.String,System.Type[])" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetPEKind(System.Reflection.PortableExecutableKinds@,System.Reflection.ImageFileMachine@)" />
+ <Member Name="GetType(System.String)" />
+ <Member Name="GetType(System.String,System.Boolean)" />
+ <Member Name="GetType(System.String,System.Boolean,System.Boolean)" />
+ <Member Name="GetTypes" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsResource" />
+ <Member Name="ResolveMember(System.Int32)" />
+ <Member Name="ResolveMember(System.Int32,System.Type[],System.Type[])" />
+ <Member Name="ResolveMethod(System.Int32)" />
+ <Member Name="ResolveMethod(System.Int32,System.Type[],System.Type[])" />
+ <Member Name="ResolveField(System.Int32)" />
+ <Member Name="ResolveField(System.Int32,System.Type[],System.Type[])" />
+ <Member Name="ResolveSignature(System.Int32)" />
+ <Member Name="ResolveString(System.Int32)" />
+ <Member Name="ResolveType(System.Int32)" />
+ <Member Name="ResolveType(System.Int32,System.Type[],System.Type[])" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="CustomAttributes" />
+ <Member MemberType="Property" Name="FullyQualifiedName" />
+ <Member MemberType="Property" Name="MetadataToken" />
+ <Member MemberType="Property" Name="ModuleVersionId" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ScopeName" />
+ <Member MemberType="Field" Name="FilterTypeName" />
+ <Member MemberType="Field" Name="FilterTypeNameIgnoreCase" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.RuntimeModule">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_pData" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="m_pFields" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="m_pGlobals" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="m_pRefClass" /> <!-- EE -->
+ <Member Status="ImplRoot" MemberType="Field" Name="m_runtimeType" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Reflection.ModuleResolveEventHandler">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.ResolveEventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,System.ResolveEventArgs)" />
+ </Type>
+ <Type Name="System.Reflection.ObfuscateAssemblyAttribute">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_AssemblyIsPrivate" />
+ <Member Name="get_StripAfterObfuscation" />
+ <Member Name="set_StripAfterObfuscation(System.Boolean)" />
+ <Member MemberType="Property" Name="AssemblyIsPrivate" />
+ <Member MemberType="Property" Name="StripAfterObfuscation" />
+ </Type>
+ <Type Name="System.Reflection.ObfuscationAttribute">
+ <Member Name="#ctor" />
+ <Member Name="get_ApplyToMembers" />
+ <Member Name="get_Exclude" />
+ <Member Name="get_Feature" />
+ <Member Name="get_StripAfterObfuscation" />
+ <Member Name="set_ApplyToMembers(System.Boolean)" />
+ <Member Name="set_Exclude(System.Boolean)" />
+ <Member Name="set_Feature(System.String)" />
+ <Member Name="set_StripAfterObfuscation(System.Boolean)" />
+ <Member MemberType="Property" Name="ApplyToMembers" />
+ <Member MemberType="Property" Name="Exclude" />
+ <Member MemberType="Property" Name="Feature" />
+ <Member MemberType="Property" Name="StripAfterObfuscation" />
+ </Type>
+ <Type Name="System.Reflection.ParameterAttributes">
+ <Member MemberType="Field" Name="HasDefault" />
+ <Member MemberType="Field" Name="HasFieldMarshal" />
+ <Member MemberType="Field" Name="In" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Optional" />
+ <Member MemberType="Field" Name="Out" />
+ <Member MemberType="Field" Name="Reserved3" />
+ <Member MemberType="Field" Name="Reserved4" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="Retval" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.ParameterInfo">
+ <Member MemberType="Field" Name="AttrsImpl" />
+ <Member MemberType="Field" Name="ClassImpl" />
+ <Member MemberType="Field" Name="DefaultValueImpl" />
+ <Member MemberType="Field" Name="MemberImpl" />
+ <Member MemberType="Field" Name="NameImpl" />
+ <Member MemberType="Field" Name="PositionImpl" />
+ <Member Name="#ctor" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CustomAttributes" />
+ <Member Name="get_DefaultValue" />
+ <Member Name="get_HasDefaultValue" />
+ <Member Name="get_IsOptional" />
+ <Member Name="get_IsOut" />
+ <Member Name="get_IsIn" />
+ <Member Name="get_IsLcid" />
+ <Member Name="get_IsRetval" />
+ <Member Name="get_Member" />
+ <Member Name="get_MetadataToken" />
+ <Member Name="get_Name" />
+ <Member Name="get_ParameterType" />
+ <Member Name="get_Position" />
+ <Member Name="get_RawDefaultValue" />
+ <Member Name="GetOptionalCustomModifiers" />
+ <Member Name="GetRequiredCustomModifiers" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="GetCustomAttributesData" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CustomAttributes" />
+ <Member MemberType="Property" Name="DefaultValue" />
+ <Member MemberType="Property" Name="HasDefaultValue" />
+ <Member MemberType="Property" Name="IsOptional" />
+ <Member MemberType="Property" Name="IsOut" />
+ <Member MemberType="Property" Name="IsIn" />
+ <Member MemberType="Property" Name="IsRetval" />
+ <Member MemberType="Property" Name="Member" />
+ <Member MemberType="Property" Name="MetadataToken" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ParameterType" />
+ <Member MemberType="Property" Name="Position" />
+ <Member MemberType="Property" Name="RawDefaultValue" />
+ </Type>
+ <Type Name="System.Reflection.ParameterModifier">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="get_Item(System.Int32)" />
+ <Member Name="set_Item(System.Int32,System.Boolean)" />
+ <Member MemberType="Property" Name="Item(System.Int32)" />
+ </Type>
+ <Type Name="System.Reflection.Pointer" >
+ <Member Name="Box(System.Void*,System.Type)" />
+ <Member Name="Unbox(System.Object)" />
+ <Member Name="System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.PortableExecutableKinds">
+ <Member MemberType="Field" Name="NotAPortableExecutableImage" />
+ <Member MemberType="Field" Name="ILOnly" />
+ <Member MemberType="Field" Name="Required32Bit" />
+ <Member MemberType="Field" Name="PE32Plus" />
+ <Member MemberType="Field" Name="Unmanaged32Bit" />
+ <Member MemberType="Field" Name="Preferred32Bit" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.PropertyAttributes">
+ <Member MemberType="Field" Name="HasDefault" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Reserved2" />
+ <Member MemberType="Field" Name="Reserved3" />
+ <Member MemberType="Field" Name="Reserved4" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="RTSpecialName" />
+ <Member MemberType="Field" Name="SpecialName" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Reflection.PropertyInfo">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Reflection.PropertyInfo,System.Reflection.PropertyInfo)" />
+ <Member Name="op_Inequality(System.Reflection.PropertyInfo,System.Reflection.PropertyInfo)" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_GetMethod" />
+ <Member Name="get_IsSpecialName" />
+ <Member Name="get_MemberType" />
+ <Member Name="get_PropertyType" />
+ <Member Name="get_SetMethod" />
+ <Member Name="GetAccessors" />
+ <Member Name="GetAccessors(System.Boolean)" />
+ <Member Name="GetConstantValue" />
+ <Member Name="GetGetMethod" />
+ <Member Name="GetGetMethod(System.Boolean)" />
+ <Member Name="GetIndexParameters" />
+ <Member Name="GetOptionalCustomModifiers" />
+ <Member Name="GetRequiredCustomModifiers" />
+ <Member Name="GetRawConstantValue" />
+ <Member Name="GetSetMethod" />
+ <Member Name="GetSetMethod(System.Boolean)" />
+ <Member Name="GetValue(System.Object)" />
+ <Member Name="GetValue(System.Object,System.Object[])" />
+ <Member Name="GetValue(System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="SetValue(System.Object,System.Object)" />
+ <Member Name="SetValue(System.Object,System.Object,System.Object[])" />
+ <Member Name="SetValue(System.Object,System.Object,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object[],System.Globalization.CultureInfo)" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="GetMethod" />
+ <Member MemberType="Property" Name="SetMethod" />
+ <Member MemberType="Property" Name="IsSpecialName" />
+ <Member MemberType="Property" Name="MemberType" />
+ <Member MemberType="Property" Name="PropertyType" />
+ </Type>
+ <Type Name="System.Reflection.TargetException" >
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.TargetInvocationException">
+ <Member Name="#ctor(System.Exception)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.TargetParameterCountException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Reflection.TypeAttributes">
+ <Member MemberType="Field" Name="Abstract" />
+ <Member MemberType="Field" Name="AnsiClass" />
+ <Member MemberType="Field" Name="AutoClass" />
+ <Member MemberType="Field" Name="AutoLayout" />
+ <Member MemberType="Field" Name="BeforeFieldInit" />
+ <Member MemberType="Field" Name="Class" />
+ <Member MemberType="Field" Name="ClassSemanticsMask" />
+ <Member MemberType="Field" Name="ExplicitLayout" />
+ <Member MemberType="Field" Name="HasSecurity" />
+ <Member MemberType="Field" Name="Import" />
+ <Member MemberType="Field" Name="Interface" />
+ <Member MemberType="Field" Name="LayoutMask" />
+ <Member MemberType="Field" Name="NestedAssembly" />
+ <Member MemberType="Field" Name="NestedFamANDAssem" />
+ <Member MemberType="Field" Name="NestedFamily" />
+ <Member MemberType="Field" Name="NestedFamORAssem" />
+ <Member MemberType="Field" Name="NestedPrivate" />
+ <Member MemberType="Field" Name="NestedPublic" />
+ <Member MemberType="Field" Name="NotPublic" />
+ <Member MemberType="Field" Name="Public" />
+ <Member MemberType="Field" Name="ReservedMask" />
+ <Member MemberType="Field" Name="RTSpecialName" />
+ <Member MemberType="Field" Name="Sealed" />
+ <Member MemberType="Field" Name="SequentialLayout" />
+ <Member MemberType="Field" Name="Serializable" />
+ <Member MemberType="Field" Name="SpecialName" />
+ <Member MemberType="Field" Name="StringFormatMask" />
+ <Member MemberType="Field" Name="UnicodeClass" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VisibilityMask" />
+ </Type>
+ <Type Name="System.Reflection.TypeDelegator">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="get_GUID" />
+ <Member Name="get_MetadataToken" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ <Member Name="get_Module" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_TypeHandle" />
+ <Member Name="get_Name" />
+ <Member Name="get_FullName" />
+ <Member Name="get_Namespace" />
+ <Member Name="get_AssemblyQualifiedName" />
+ <Member Name="get_BaseType" />
+ <Member Name="GetConstructorImpl(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructors(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetInterface(System.String,System.Boolean)" />
+ <Member Name="GetInterfaces" />
+ <Member Name="GetEvent(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents" />
+ <Member Name="GetPropertyImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedTypes(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedType(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetMember(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetAttributeFlagsImpl" />
+ <Member Name="IsArrayImpl" />
+ <Member Name="IsPrimitiveImpl" />
+ <Member Name="IsByRefImpl" />
+ <Member Name="IsPointerImpl" />
+ <Member Name="IsValueTypeImpl" />
+ <Member Name="IsCOMObjectImpl" />
+ <Member Name="get_IsConstructedGenericType" />
+ <Member Name="GetElementType" />
+ <Member Name="HasElementTypeImpl" />
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetCustomAttributes(System.Boolean)" />
+ <Member Name="GetCustomAttributes(System.Type,System.Boolean)" />
+ <Member Name="IsDefined(System.Type,System.Boolean)" />
+ <Member Name="IsAssignableFrom(System.Reflection.TypeInfo)" />
+ <Member Name="GetInterfaceMap(System.Type)" />
+ <Member MemberType="Field" Name="typeImpl" />
+ <Member MemberType="Property" Name="GUID" />
+ <Member MemberType="Property" Name="MetadataToken" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="TypeHandle" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="Namespace" />
+ <Member MemberType="Property" Name="AssemblyQualifiedName" />
+ <Member MemberType="Property" Name="BaseType" />
+ <Member MemberType="Property" Name="IsConstructedGenericType" />
+ <Member MemberType="Property" Name="UnderlyingSystemType" />
+ </Type>
+ <Type Name="System.ResolveEventArgs">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Reflection.Assembly)" />
+ <Member Name="get_Name" />
+ <Member MemberType="Property" Name="Name" />
+ <Member Name="get_RequestingAssembly" />
+ <Member MemberType="Property" Name="RequestingAssembly" />
+ </Type>
+ <Type Name="System.ResolveEventHandler">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.ResolveEventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,System.ResolveEventArgs)" />
+ </Type>
+ <Type Name="System.Resources.MissingManifestResourceException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Resources.NeutralResourcesLanguageAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Resources.UltimateResourceFallbackLocation)" />
+ <Member Name="get_CultureName" />
+ <Member MemberType="Property" Name="CultureName" />
+ <Member Name="get_Location" />
+ <Member MemberType="Property" Name="Location" />
+ </Type>
+ <Type Name="System.Resources.ResourceManager">
+ <Member MemberType="Field" Name="BaseNameField" />
+ <Member MemberType="Field" Name="HeaderVersionNumber" />
+ <Member MemberType="Field" Name="MagicNumber" />
+ <Member MemberType="Field" Name="MainAssembly" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String,System.Reflection.Assembly)" />
+ <Member Name="#ctor(System.String,System.Reflection.Assembly,System.Type)" />
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="get_BaseName" />
+ <Member Name="get_IgnoreCase" />
+ <Member Name="get_ResourceSetType" />
+ <Member Name="GetNeutralResourcesLanguage(System.Reflection.Assembly)" />
+ <Member Name="GetObject(System.String)" />
+ <Member Name="GetObject(System.String,System.Globalization.CultureInfo)" />
+ <Member Name="GetResourceFileName(System.Globalization.CultureInfo)" />
+ <Member Name="GetResourceSet(System.Globalization.CultureInfo,System.Boolean,System.Boolean)" />
+ <Member Name="GetSatelliteContractVersion(System.Reflection.Assembly)" />
+ <Member Name="GetStream(System.String)" />
+ <Member Name="GetStream(System.String,System.Globalization.CultureInfo)" />
+ <Member Name="GetString(System.String)" />
+ <Member Name="GetString(System.String,System.Globalization.CultureInfo)" />
+ <Member Name="InternalGetResourceSet(System.Globalization.CultureInfo,System.Boolean,System.Boolean)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ReleaseAllResources" />
+ <Member Name="set_IgnoreCase(System.Boolean)" />
+ <Member MemberType="Property" Name="BaseName" />
+ <Member MemberType="Property" Name="IgnoreCase" />
+ <Member MemberType="Property" Name="ResourceSetType" />
+ </Type>
+ <Type Name="System.Resources.ResourceSet">
+ <Member MemberType="Field" Name="Reader" />
+ <Member MemberType="Field" Name="Table" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.IO.Stream)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="GetDefaultReader" />
+ <Member Name="GetEnumerator" />
+ <Member Name="GetObject(System.String)" />
+ <Member Name="GetObject(System.String,System.Boolean)" />
+ <Member Name="GetString(System.String)" />
+ <Member Name="GetString(System.String,System.Boolean)" />
+ <Member Name="ReadResources" />
+ </Type>
+ <Type Name="System.Resources.SatelliteContractVersionAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Version" />
+ <Member MemberType="Property" Name="Version" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.AccessedThroughPropertyAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_PropertyName" />
+ <Member MemberType="Property" Name="PropertyName" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CompilationRelaxations">
+ <Member MemberType="Field" Name="NoStringInterning" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CompilationRelaxationsAttribute">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Runtime.CompilerServices.CompilationRelaxations)" />
+ <Member MemberType="Property" Name="CompilationRelaxations" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CallConvCdecl" /> <!-- for MC++ -->
+ <Type Name="System.Runtime.CompilerServices.CallConvStdcall" /> <!-- for MC++ -->
+ <Type Name="System.Runtime.CompilerServices.CallConvThiscall" /> <!-- for MC++ -->
+ <Type Name="System.Runtime.CompilerServices.CallConvFastcall" /> <!-- for MC++ -->
+ <Type Name="System.Runtime.CompilerServices.CompilerMarshalOverride" />
+ <Type Name="System.Runtime.CompilerServices.CustomConstantAttribute">
+ <Member Name="#ctor" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <!-- If we do a Silverlight 6 release, this ContractHelper should be public in Silverlight. Tools may be able to work without it, but it helps if it's there. -->
+ <Type Name="System.Runtime.CompilerServices.ContractHelper">
+ <Member Name="RaiseContractFailedEvent(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.Exception)" />
+ <Member Name="TriggerFailure(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.String,System.Exception)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.DateTimeConstantAttribute">
+ <Member Name="#ctor(System.Int64)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.DecimalConstantAttribute">
+ <Member Name="#ctor(System.Byte,System.Byte,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Byte,System.Byte,System.UInt32,System.UInt32,System.UInt32)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.DisablePrivateReflectionAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ExtensionAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.FixedBufferAttribute">
+ <Member Name="#ctor(System.Type,System.Int32)" />
+ <Member Name="get_ElementType" />
+ <Member Name="get_Length" />
+ <Member MemberType="Property" Name="ElementType" />
+ <Member MemberType="Property" Name="Length" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.FixedAddressValueTypeAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.FormattableStringFactory">
+ <Member Name="Create(System.String,System.Object[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.CompilerServices.FriendAccessAllowedAttribute" />
+ <Type Name="System.Runtime.CompilerServices.IndexerNameAttribute">
+ <Member Name="#ctor(System.String)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_AssemblyName" />
+ <Member MemberType="Property" Name="AllInternalsVisible" />
+ <Member MemberType="Property" Name="AssemblyName" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.CompilerServices.JitHelpers">
+ <Member Status="ImplRoot" Name="UnsafeEnumCastLong&lt;T&gt;(T)" />
+ <Member Status="ImplRoot" Name="UnsafeEnumCastLongInternal&lt;T&gt;(T)" Condition="DEBUG" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.SpecialNameAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.UnsafeValueTypeAttribute"> <!-- C# 3.0 compiler requires this type -->
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.SuppressMergeCheckAttribute"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.RequiredAttributeAttribute"> <!-- for MC++ -->
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="get_RequiredContract" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsBoxed"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsByValue"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsConst"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsCopyConstructed"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ICastable">
+ <Member Name="IsInstanceOfInterface(System.RuntimeTypeHandle,System.Exception@)" /> <!-- EE -->
+ <Member Name="GetImplType(System.RuntimeTypeHandle)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ICastableHelpers">
+ <Member Name="IsInstanceOfInterface(System.Runtime.CompilerServices.ICastable,System.RuntimeType,System.Exception@)" /> <!-- EE -->
+ <Member Name="GetImplType(System.Runtime.CompilerServices.ICastable,System.RuntimeType)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsExplicitlyDereferenced"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsImplicitlyDereferenced"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsLong"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsJitIntrinsic"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsSignUnspecifiedByte"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsUdtReturn"> <!-- for MC++ -->
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.NativeCppClassAttribute"> <!-- for MC++ -->
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IsVolatile" /> <!-- for MC++ -->
+ <Type Name="System.Runtime.CompilerServices.MethodCodeType">
+ <Member MemberType="Field" Name="IL" />
+ <Member MemberType="Field" Name="Native" />
+ <Member MemberType="Field" Name="OPTIL" />
+ <Member MemberType="Field" Name="Runtime" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.MethodImplAttribute">
+ <Member MemberType="Field" Name="MethodCodeType" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Int16)" />
+ <Member Name="#ctor(System.Runtime.CompilerServices.MethodImplOptions)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Status="ImplRoot" Name="#ctor(System.Reflection.MethodImplAttributes)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.MethodImplOptions">
+ <Member MemberType="Field" Name="AggressiveInlining" />
+ <Member MemberType="Field" Name="ForwardRef" />
+ <Member MemberType="Field" Name="InternalCall" />
+ <Member MemberType="Field" Name="NoInlining" />
+ <Member MemberType="Field" Name="PreserveSig" />
+ <Member MemberType="Field" Name="Synchronized" />
+ <Member MemberType="Field" Name="Unmanaged" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.RuntimeHelpers">
+ <Member Name="GetUninitializedObject(System.Type)" />
+ <Member Name="EnsureSufficientExecutionStack" />
+ <Member Name="get_OffsetToStringData" />
+ <Member Name="GetObjectValue(System.Object)" />
+ <Member Name="InitializeArray(System.Array,System.RuntimeFieldHandle)" />
+ <Member Name="GetHashCode(System.Object)" />
+ <Member Name="RunClassConstructor(System.RuntimeTypeHandle)" />
+ <Member MemberType="Property" Name="OffsetToStringData" />
+ <Member Status="ImplRoot" Name="ExecuteBackoutCodeHelper(System.Object,System.Object,System.Boolean)" />
+ <Member Status="ImplRoot" Name="PrepareConstrainedRegionsNoOP" />
+ <Member Status="ImplRoot" Name="PrepareConstrainedRegions" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConditionalWeakTable&lt;TKey,TValue&gt;">
+ <Member Name="#ctor" />
+ <Member Name="Add(TKey,TValue)" />
+ <Member Name="Remove(TKey)" />
+ <Member Name="TryGetValue(TKey,TValue@)" />
+ <Member Name="GetValue(TKey,System.Runtime.CompilerServices.ConditionalWeakTable+CreateValueCallback)" />
+ <Member Name="GetOrCreateValue(TKey)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConditionalWeakTable&lt;TKey,TValue&gt;+CreateValueCallback">
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ReferenceAssemblyAttribute">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="Description" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.TypeForwardedToAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="Destination" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.TypeForwardedFromAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="AssemblyFullName" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.SuppressIldasmAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <!-- #if FEATURE_CORRUPTING_EXCEPTIONS -->
+ <Type Name="System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <!-- #endif FEATURE_CORRUPTING_EXCEPTIONS -->
+ <!-- #if FEATURE_EXCEPTIONDISPATCHINFO -->
+ <Type Status="ApiRoot" Name="System.Runtime.ExceptionServices.ExceptionDispatchInfo">
+ <Member Status="ApiRoot" Name="Capture(System.Exception)" />
+ <Member Status="ApiRoot" Name="Throw" />
+ <Member Name="get_SourceException" />
+ <Member MemberType="Property" Name="SourceException" />
+ </Type>
+ <!-- #endif FEATURE_EXCEPTIONDISPATCHINFO -->
+ <Type Name="System.Runtime.GCLatencyMode">
+ <Member MemberType="Field" Name="Batch" />
+ <Member MemberType="Field" Name="Interactive" />
+ <Member MemberType="Field" Name="LowLatency" />
+ <Member MemberType="Field" Name="SustainedLowLatency" />
+ </Type>
+ <Type Name="System.Runtime.GCSettings">
+ <Member Name="get_IsServerGC" />
+ <Member Name="get_LargeObjectHeapCompactionMode" />
+ <Member Name="set_LargeObjectHeapCompactionMode(System.Runtime.GCLargeObjectHeapCompactionMode)" />
+ <Member Name="get_LatencyMode" />
+ <Member Name="set_LatencyMode(System.Runtime.GCLatencyMode)" />
+ <Member MemberType="Property" Name="IsServerGC" />
+ <Member MemberType="Property" Name="LargeObjectHeapCompactionMode" />
+ <Member MemberType="Property" Name="LatencyMode" />
+ </Type>
+ <Type Name="System.Runtime.GCLargeObjectHeapCompactionMode">
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="CompactOnce" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.BStrWrapper">
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="WrappedObject" />
+ <Member Name="get_WrappedObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CurrencyWrapper">
+ <Member Name="#ctor(System.Decimal)" />
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="get_WrappedObject" />
+ <Member MemberType="Property" Name="WrappedObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DispatchWrapper">
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="get_WrappedObject" />
+ <Member MemberType="Property" Name="WrappedObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.UnknownWrapper">
+ <Member Name="#ctor(System.Object)" />
+ <Member MemberType="Property" Name="WrappedObject" />
+ <Member Name="get_WrappedObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.VariantWrapper">
+ <Member Name="#ctor(System.Object)" />
+ <Member MemberType="Property" Name="WrappedObject" />
+ <Member Name="get_WrappedObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ErrorWrapper">
+ <Member Name="#ctor(System.Exception)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Object)" />
+ <Member MemberType="Property" Name="ErrorCode" />
+ <Member Name="get_ErrorCode" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.LCIDConversionAttribute" Condition="FEATURE_COMINTEROP" />
+ <Type Name="System.Runtime.InteropServices.CallingConvention">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Winapi" />
+ <Member MemberType="Field" Name="Cdecl" />
+ <Member MemberType="Field" Name="StdCall" />
+ <Member MemberType="Field" Name="ThisCall" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CharSet">
+ <Member MemberType="Field" Name="Ansi" />
+ <Member MemberType="Field" Name="Auto" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Unicode" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ClassInterfaceAttribute"> <!-- for VB -->
+ <Member Name="#ctor(System.Int16)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.ClassInterfaceType)" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ClassInterfaceType"> <!-- for VB -->
+ <Member MemberType="Field" Name="AutoDispatch" />
+ <Member MemberType="Field" Name="AutoDual" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CoClassAttribute"> <!-- MC++ compiler asserts for no particularly good reason if this type is not public -->
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="CoClass" />
+ <Member Name="get_CoClass" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComDefaultInterfaceAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.COMException">
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="ToString" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComImportAttribute"> <!-- MC++ compiler asserts for no particularly good reason if this type is not public -->
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComInterfaceType">
+ <Member MemberType="Field" Name="InterfaceIsDual" />
+ <Member MemberType="Field" Name="InterfaceIsIUnknown" />
+ <Member MemberType="Field" Name="InterfaceIsIDispatch" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="InterfaceIsIInspectable" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.FILETIME">
+ <Member MemberType="Field" Name="dwHighDateTime" />
+ <Member MemberType="Field" Name="dwLowDateTime" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.STATSTG">
+ <Member MemberType="Field" Name="atime" />
+ <Member MemberType="Field" Name="cbSize" />
+ <Member MemberType="Field" Name="clsid" />
+ <Member MemberType="Field" Name="ctime" />
+ <Member MemberType="Field" Name="grfLocksSupported" />
+ <Member MemberType="Field" Name="grfMode" />
+ <Member MemberType="Field" Name="grfStateBits" />
+ <Member MemberType="Field" Name="mtime" />
+ <Member MemberType="Field" Name="pwcsName" />
+ <Member MemberType="Field" Name="reserved" />
+ <Member MemberType="Field" Name="type" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IStream">
+ <Member Name="Read(System.Byte[],System.Int32,System.IntPtr)" />
+ <Member Name="Write(System.Byte[],System.Int32,System.IntPtr)" />
+ <Member Name="Seek(System.Int64,System.Int32,System.IntPtr)" />
+ <Member Name="SetSize(System.Int64)" />
+ <Member Name="CopyTo(System.Runtime.InteropServices.ComTypes.IStream,System.Int64,System.IntPtr,System.IntPtr)" />
+ <Member Name="Commit(System.Int32)" />
+ <Member Name="Revert" />
+ <Member Name="LockRegion(System.Int64,System.Int64,System.Int32)" />
+ <Member Name="UnlockRegion(System.Int64,System.Int64,System.Int32)" />
+ <Member Name="Stat(System.Runtime.InteropServices.ComTypes.STATSTG@,System.Int32)" />
+ <Member Name="Clone(System.Runtime.InteropServices.ComTypes.IStream@)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DefaultCharSetAttribute"> <!-- MC++ compiler asserts for no particularly good reason if this type is not public -->
+ <Member Name="#ctor(System.Runtime.InteropServices.CharSet)" />
+ <Member MemberType="Property" Name="CharSet" />
+ <Member Name="get_CharSet" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DispIdAttribute">
+ <Member Name="#ctor(System.Int32)" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DllImportAttribute">
+ <Member MemberType="Field" Name="CallingConvention" />
+ <Member MemberType="Field" Name="CharSet" />
+ <Member MemberType="Field" Name="EntryPoint" />
+ <Member MemberType="Field" Name="PreserveSig" />
+ <Member MemberType="Field" Name="SetLastError" />
+ <Member MemberType="Field" Name="BestFitMapping" /> <!-- forced by desktop implementation -->
+ <Member MemberType="Field" Name="ExactSpelling" /> <!-- forced by desktop implementation -->
+ <!-- <Member MemberType="Field" Name="ThrowOnUnmappableChar" /><!- - forced by desktop implementation -->
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ <Member MemberType="Field" Name="ThrowOnUnmappableChar" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ExternalException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="get_ErrorCode" />
+ <Member MemberType="Property" Name="ErrorCode" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.FieldOffsetAttribute">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.GCHandle">
+ <Member Name="AddrOfPinnedObject" />
+ <Member Name="Alloc(System.Object)" />
+ <Member Name="Alloc(System.Object,System.Runtime.InteropServices.GCHandleType)" />
+ <Member Name="Free" />
+ <Member Name="FromIntPtr(System.IntPtr)" />
+ <Member Name="get_IsAllocated" />
+ <Member Name="get_Target" />
+ <Member Name="op_Explicit(System.IntPtr)" ReturnType="System.Runtime.InteropServices.GCHandle" />
+ <Member Name="op_Explicit(System.Runtime.InteropServices.GCHandle)" ReturnType="System.IntPtr" />
+ <Member Name="set_Target(System.Object)" />
+ <Member Name="ToIntPtr(System.Runtime.InteropServices.GCHandle)" />
+ <Member MemberType="Property" Name="IsAllocated" />
+ <Member MemberType="Property" Name="Target" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Runtime.InteropServices.GCHandle,System.Runtime.InteropServices.GCHandle)" />
+ <Member Name="op_Inequality(System.Runtime.InteropServices.GCHandle,System.Runtime.InteropServices.GCHandle)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.GCHandleType">
+ <Member MemberType="Field" Name="Normal" />
+ <Member MemberType="Field" Name="Pinned" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Weak" />
+ <Member MemberType="Field" Name="WeakTrackResurrection" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.GuidAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ICustomQueryInterface">
+ <Member Name="GetInterface(System.Guid@,System.IntPtr@)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.InAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.InterfaceTypeAttribute">
+ <Member Name="#ctor(System.Runtime.InteropServices.ComInterfaceType)" />
+ <Member Name="#ctor(System.Int16)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.InvalidComObjectException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.SafeArrayRankMismatchException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.SafeArrayTypeMismatchException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.LayoutKind">
+ <Member MemberType="Field" Name="Auto" />
+ <Member MemberType="Field" Name="Explicit" />
+ <Member MemberType="Field" Name="Sequential" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.NativeCallableAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Field" Name="CallingConvention" /> <!-- EE -->
+ <Member MemberType="Field" Name="EntryPoint" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Runtime.InteropServices.Marshal">
+ <Member MemberType="Field" Name="SystemDefaultCharSize" />
+ <Member Name="AddRef(System.IntPtr)" />
+ <Member Name="AllocHGlobal(System.Int32)" />
+ <Member Name="AllocCoTaskMem(System.Int32)" />
+ <Member Name="Copy(System.Byte[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.Char[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.Double[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.Int16[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.Int32[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.Int64[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Double[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Int16[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Int32[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Int64[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr,System.Single[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.Single[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="FinalReleaseComObject(System.Object)" />
+ <Member Name="FreeHGlobal(System.IntPtr)" />
+ <Member Name="FreeCoTaskMem(System.IntPtr)" />
+ <Member Name="GetComInterfaceForObject(System.Object,System.Type)" />
+ <Member Name="GetComInterfaceForObject(System.Object,System.Type,System.Runtime.InteropServices.CustomQueryInterfaceMode)" />
+ <Member Name="GetDelegateForFunctionPointer(System.IntPtr,System.Type)" />
+ <Member Name="GetExceptionForHR(System.Int32)" />
+ <Member Name="GetExceptionForHR(System.Int32,System.IntPtr)" />
+ <Member Name="GetFunctionPointerForDelegate(System.Delegate)" />
+ <Member Name="GetHRForException(System.Exception)" />
+ <Member Name="GetIUnknownForObject(System.Object)" />
+ <Member Name="GetLastWin32Error" />
+ <Member Name="GetHRForLastWin32Error" />
+ <Member Name="GetNativeVariantForObject(System.Object,System.IntPtr)" />
+ <Member Name="GetObjectForIUnknown(System.IntPtr)" />
+ <Member Name="GetObjectForNativeVariant(System.IntPtr)" />
+ <Member Name="GetUniqueObjectForIUnknown(System.IntPtr)" />
+ <Member Name="InitializeManagedWinRTFactoryObject(System.Object,System.RuntimeType)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="IsComObject(System.Object)" />
+ <Member Name="OffsetOf(System.Type,System.String)" />
+ <Member Name="Prelink(System.Reflection.MethodInfo)" />
+ <Member Name="PrelinkAll(System.Type)" />
+ <Member Name="PtrToStringAnsi(System.IntPtr)" />
+ <Member Name="PtrToStringAnsi(System.IntPtr,System.Int32)" />
+ <Member Name="PtrToStringUTF8(System.IntPtr)" />
+ <Member Name="PtrToStringUTF8(System.IntPtr,System.Int32)" />
+ <Member Name="PtrToStringUni(System.IntPtr)" />
+ <Member Name="PtrToStringUni(System.IntPtr,System.Int32)" />
+ <Member Name="PtrToStructure(System.IntPtr,System.Object)" />
+ <Member Name="PtrToStructure(System.IntPtr,System.Type)" />
+ <Member Name="QueryInterface(System.IntPtr,System.Guid@,System.IntPtr@)" />
+ <Member Name="ReadByte(System.IntPtr)" />
+ <Member Name="ReadByte(System.IntPtr,System.Int32)" />
+ <Member Name="ReadInt16(System.IntPtr)" />
+ <Member Name="ReadInt16(System.IntPtr,System.Int32)" />
+ <Member Name="ReadInt32(System.IntPtr)" />
+ <Member Name="ReadInt32(System.IntPtr,System.Int32)" />
+ <Member Name="ReadInt64(System.IntPtr)" />
+ <Member Name="ReadInt64(System.IntPtr,System.Int32)" />
+ <Member Name="ReadIntPtr(System.IntPtr)" />
+ <Member Name="ReadIntPtr(System.IntPtr,System.Int32)" />
+ <Member Name="Release(System.IntPtr)" />
+ <Member Name="ReleaseComObject(System.Object)" />
+ <Member Name="SetLastWin32Error(System.Int32)" />
+ <Member Name="SizeOf(System.Object)" />
+ <Member Name="SizeOf(System.Type)" />
+ <Member Name="StructureToPtr(System.Object,System.IntPtr,System.Boolean)" />
+ <Member Name="ThrowExceptionForHR(System.Int32)" />
+ <Member Name="ThrowExceptionForHR(System.Int32,System.IntPtr)" />
+ <Member Name="UnsafeAddrOfPinnedArrayElement(System.Array,System.Int32)" />
+ <Member Name="WriteByte(System.IntPtr,System.Byte)" />
+ <Member Name="WriteByte(System.IntPtr,System.Int32,System.Byte)" />
+ <Member Name="WriteInt16(System.IntPtr,System.Char)" />
+ <Member Name="WriteInt16(System.IntPtr,System.Int16)" />
+ <Member Name="WriteInt16(System.IntPtr,System.Int32,System.Char)" />
+ <Member Name="WriteInt16(System.IntPtr,System.Int32,System.Int16)" />
+ <Member Name="WriteInt32(System.IntPtr,System.Int32)" />
+ <Member Name="WriteInt32(System.IntPtr,System.Int32,System.Int32)" />
+ <Member Name="WriteInt64(System.IntPtr,System.Int32,System.Int64)" />
+ <Member Name="WriteInt64(System.IntPtr,System.Int64)" />
+ <Member Name="WriteIntPtr(System.IntPtr,System.Int32,System.IntPtr)" />
+ <Member Name="WriteIntPtr(System.IntPtr,System.IntPtr)" />
+ <Member Name="ZeroFreeCoTaskMemUnicode(System.IntPtr)" />
+ <Member Status="ImplRoot" Name="InitializeWrapperForWinRT(System.Object,System.IntPtr@)" Condition="FEATURE_COMINTEROP" />
+ <Member Status="ImplRoot" Name="LoadLicenseManager" Condition="FEATURE_COMINTEROP" /><Member MemberType="Field" Name="SystemMaxDBCSCharSize" />
+ <Member Name="AllocHGlobal(System.IntPtr)" />
+ <Member Name="AreComObjectsAvailableForCleanup" />
+ <Member Name="Copy(System.IntPtr,System.IntPtr[],System.Int32,System.Int32)" />
+ <Member Name="Copy(System.IntPtr[],System.Int32,System.IntPtr,System.Int32)" />
+ <Member Name="CreateAggregatedObject(System.IntPtr,System.Object)" />
+ <Member Name="CreateAggregatedObject&lt;T&gt;(System.IntPtr,T)" />
+ <Member Name="CreateWrapperOfType(System.Object,System.Type)" />
+ <Member Name="CreateWrapperOfType&lt;T,TWrapper&gt;(T)" />
+ <Member Name="DestroyStructure(System.IntPtr,System.Type)" />
+ <Member Name="DestroyStructure&lt;T&gt;(System.IntPtr)" />
+ <Member Name="FreeBSTR(System.IntPtr)" />
+ <Member Name="GetComInterfaceForObject&lt;T,TInterface&gt;(T)" />
+ <Member Name="GetDelegateForFunctionPointer&lt;TDelegate&gt;(System.IntPtr)" />
+ <Member Name="GetExceptionCode" />
+ <Member Name="GetFunctionPointerForDelegate&lt;TDelegate&gt;(TDelegate)" />
+ <Member Name="GetNativeVariantForObject&lt;T&gt;(T,System.IntPtr)" />
+ <Member Name="GetObjectForNativeVariant&lt;T&gt;(System.IntPtr)" />
+ <Member Name="GetObjectsForNativeVariants(System.IntPtr,System.Int32)" />
+ <Member Name="GetObjectsForNativeVariants&lt;T&gt;(System.IntPtr,System.Int32)" />
+ <Member Name="GetStartComSlot(System.Type)" />
+ <Member Name="GetTypeFromCLSID(System.Guid)" />
+ <Member Name="GetTypeInfoName(System.Runtime.InteropServices.ComTypes.ITypeInfo)" />
+ <Member Name="OffsetOf&lt;T&gt;(System.String)" />
+ <Member Name="PtrToStringBSTR(System.IntPtr)" />
+ <Member Name="PtrToStructure&lt;T&gt;(System.IntPtr)" />
+ <Member Name="PtrToStructure&lt;T&gt;(System.IntPtr,T)" />
+ <Member Name="ReadByte(System.Object,System.Int32)" />
+ <Member Name="ReadInt16(System.Object,System.Int32)" />
+ <Member Name="ReadInt32(System.Object,System.Int32)" />
+ <Member Name="ReadInt64(System.Object,System.Int32)" />
+ <Member Name="ReadIntPtr(System.Object,System.Int32)" />
+ <Member Name="ReAllocCoTaskMem(System.IntPtr,System.Int32)" />
+ <Member Name="ReAllocHGlobal(System.IntPtr,System.IntPtr)" />
+ <Member Name="SizeOf&lt;T&gt;" />
+ <Member Name="SizeOf&lt;T&gt;(T)" />
+ <Member Name="StringToBSTR(System.String)" />
+ <Member Name="StringToCoTaskMemAnsi(System.String)" />
+ <Member Name="StringToCoTaskMemUni(System.String)" />
+ <Member Name="StringToHGlobalAnsi(System.String)" />
+ <Member Name="StringToHGlobalUni(System.String)" />
+ <Member Name="StringToCoTaskMemUTF8(System.String)" />
+ <Member Name="StructureToPtr&lt;T&gt;(T,System.IntPtr,System.Boolean)" />
+ <Member Name="UnsafeAddrOfPinnedArrayElement&lt;T&gt;(T[],System.Int32)" />
+ <Member Name="WriteByte(System.Object,System.Int32,System.Byte)" />
+ <Member Name="WriteInt16(System.Object,System.Int32,System.Char)" />
+ <Member Name="WriteInt16(System.Object,System.Int32,System.Int16)" />
+ <Member Name="WriteInt32(System.Object,System.Int32,System.Int32)" />
+ <Member Name="WriteInt64(System.Object,System.Int32,System.Int64)" />
+ <Member Name="WriteIntPtr(System.Object,System.Int32,System.IntPtr)" />
+ <Member Name="ZeroFreeBSTR(System.IntPtr)" />
+ <Member Name="ZeroFreeCoTaskMemAnsi(System.IntPtr)" />
+ <Member Name="ZeroFreeGlobalAllocAnsi(System.IntPtr)" />
+ <Member Name="ZeroFreeGlobalAllocUnicode(System.IntPtr)" />
+ <Member Name="ZeroFreeCoTaskMemUTF8(System.IntPtr)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.MarshalAsAttribute">
+ <Member MemberType="Field" Name="ArraySubType" />
+ <Member MemberType="Field" Name="MarshalCookie" />
+ <Member MemberType="Field" Name="MarshalType" />
+ <Member MemberType="Field" Name="MarshalTypeRef" />
+ <Member MemberType="Field" Name="SizeConst" />
+ <Member MemberType="Field" Name="SizeParamIndex" />
+ <Member Name="#ctor(System.Int16)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.UnmanagedType)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ <Member MemberType="Field" Name="IidParameterIndex" />
+ <Member MemberType="Field" Name="SafeArraySubType" />
+ <Member MemberType="Field" Name="SafeArrayUserDefinedSubType" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.MarshalDirectiveException" >
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.OptionalAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.OutAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.PreserveSigAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.RuntimeEnvironment">
+ <Member Name="GetRuntimeDirectory" /> <!-- For use in the Framework, but not public in Win8P reference assemblies. -->
+ </Type>
+ <Type Name="System.Runtime.InteropServices.SafeHandle">
+ <Member MemberType="Field" Name="handle" />
+ <Member Name="#ctor(System.IntPtr,System.Boolean)" />
+ <Member Name="#ctor" />
+ <Member Name="Close" />
+ <Member Name="DangerousAddRef(System.Boolean@)" />
+ <Member Name="DangerousGetHandle" />
+ <Member Name="DangerousRelease" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Finalize" />
+ <Member Name="get_IsClosed" />
+ <Member Name="get_IsInvalid" />
+ <Member Name="ReleaseHandle" />
+ <Member Name="SetHandle(System.IntPtr)" />
+ <Member Name="SetHandleAsInvalid" />
+ <Member MemberType="Property" Name="IsClosed" />
+ <Member MemberType="Property" Name="IsInvalid" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CriticalHandle">
+ <Member MemberType="Field" Name="handle" />
+ <Member MemberType="Field" Name="_stackTrace" Flavor="chk,dbg" />
+ <Member Name="#ctor(System.IntPtr)" />
+ <Member Name="#ctor" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Finalize" />
+ <Member Name="get_IsClosed" />
+ <Member Name="get_IsInvalid" />
+ <Member Name="ReleaseHandle" />
+ <Member Name="SetHandle(System.IntPtr)" />
+ <Member Name="SetHandleAsInvalid" />
+ <Member MemberType="Property" Name="IsClosed" />
+ <Member MemberType="Property" Name="IsInvalid" />
+ </Type>
+ <Type Name="Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_IsInvalid" />
+ </Type>
+ <Type Name="Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_IsInvalid" />
+ </Type>
+ <Type Name="Microsoft.Win32.SafeHandles.SafeWaitHandle">
+ <Member Name="#ctor(System.IntPtr,System.Boolean)" />
+ <Member Status="ApiRoot" Name="ReleaseHandle" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.SEHException" >
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="CanResume" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.StructLayoutAttribute">
+ <Member MemberType="Field" Name="CharSet" />
+ <Member MemberType="Field" Name="Pack" />
+ <Member MemberType="Field" Name="Size" />
+ <Member Name="#ctor(System.Int16)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.LayoutKind)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute">
+ <Member Name="#ctor(System.Runtime.InteropServices.CallingConvention)" />
+ <Member MemberType="Property" Name="CallingConvention" />
+ <Member Name="get_CallingConvention" />
+ <Member MemberType="Field" Name="BestFitMapping" />
+ <Member MemberType="Field" Name="CharSet" />
+ <Member MemberType="Field" Name="SetLastError" />
+ <Member MemberType="Field" Name="ThrowOnUnmappableChar" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.UnmanagedType">
+ <Member MemberType="Field" Name="AnsiBStr" />
+ <Member MemberType="Field" Name="AsAny" />
+ <Member MemberType="Field" Name="Bool" />
+ <Member MemberType="Field" Name="BStr" />
+ <Member MemberType="Field" Name="ByValArray" />
+ <Member MemberType="Field" Name="ByValTStr" />
+ <Member MemberType="Field" Name="Currency" />
+ <Member MemberType="Field" Name="CustomMarshaler" />
+ <Member MemberType="Field" Name="Error" />
+ <Member MemberType="Field" Name="FunctionPtr" />
+ <Member MemberType="Field" Name="I1" />
+ <Member MemberType="Field" Name="I2" />
+ <Member MemberType="Field" Name="I4" />
+ <Member MemberType="Field" Name="I8" />
+ <Member MemberType="Field" Name="IDispatch" />
+ <Member MemberType="Field" Name="Interface" />
+ <Member MemberType="Field" Name="LPArray" />
+ <Member MemberType="Field" Name="LPStr" />
+ <Member MemberType="Field" Name="LPStruct" />
+ <Member MemberType="Field" Name="LPTStr" />
+ <Member MemberType="Field" Name="LPWStr" />
+ <Member MemberType="Field" Name="LPUTF8Str" />
+ <Member MemberType="Field" Name="R4" />
+ <Member MemberType="Field" Name="R8" />
+ <Member MemberType="Field" Name="SafeArray" />
+ <Member MemberType="Field" Name="Struct" />
+ <Member MemberType="Field" Name="SysInt" />
+ <Member MemberType="Field" Name="SysUInt" />
+ <Member MemberType="Field" Name="TBStr" />
+ <Member MemberType="Field" Name="U1" />
+ <Member MemberType="Field" Name="U2" />
+ <Member MemberType="Field" Name="U4" />
+ <Member MemberType="Field" Name="U8" />
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VariantBool" />
+ <Member MemberType="Field" Name="VBByRefStr" />
+ <Member MemberType="Field" Name="HString" />
+ <Member MemberType="Field" Name="IInspectable" />
+ <Member MemberType="Field" Name="IUnknown" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Versioning.ComponentGuaranteesAttribute">
+ <Member Name="#ctor(System.Runtime.Versioning.ComponentGuaranteesOptions)" />
+ <Member MemberType="Property" Name="Guarantees" />
+ </Type>
+ <Type Name="System.Runtime.Versioning.ComponentGuaranteesOptions">
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Exchange" />
+ <Member MemberType="Field" Name="Stable" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.RuntimeFieldHandle">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Equals(System.RuntimeFieldHandle)" />
+ <Member Name="get_Value" />
+ <Member Name="op_Equality(System.RuntimeFieldHandle,System.RuntimeFieldHandle)" />
+ <Member Name="op_Inequality(System.RuntimeFieldHandle,System.RuntimeFieldHandle)" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.RuntimeMethodHandle">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Equals(System.RuntimeMethodHandle)" />
+ <Member Status="ImplRoot" Name="GetValueInternal(System.RuntimeMethodHandle)" />
+ <Member Name="get_Value" />
+ <Member Name="GetFunctionPointer" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="op_Equality(System.RuntimeMethodHandle,System.RuntimeMethodHandle)" />
+ <Member Name="op_Inequality(System.RuntimeMethodHandle,System.RuntimeMethodHandle)" />
+ </Type>
+ <Type Name="System.SByte">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.SByte)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.SByte)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.SByte@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.SByte@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.Security.AllowPartiallyTrustedCallersAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Security.SecurityException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Security.SecurityState">
+ <Member Name="#ctor" />
+ <Member Name="IsStateAvailable" />
+ <Member Name="EnsureState" />
+ </Type>
+ <Type Name="System.SerializableAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Single">
+ <Member MemberType="Field" Name="Epsilon" />
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member MemberType="Field" Name="NaN" />
+ <Member MemberType="Field" Name="NegativeInfinity" />
+ <Member MemberType="Field" Name="PositiveInfinity" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.Single)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Single)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="IsInfinity(System.Single)" />
+ <Member Name="IsNaN(System.Single)" />
+ <Member Name="IsNegativeInfinity(System.Single)" />
+ <Member Name="IsPositiveInfinity(System.Single)" />
+ <Member Name="op_Equality(System.Single,System.Single)" />
+ <Member Name="op_GreaterThan(System.Single,System.Single)" />
+ <Member Name="op_GreaterThanOrEqual(System.Single,System.Single)" />
+ <Member Name="op_Inequality(System.Single,System.Single)" />
+ <Member Name="op_LessThan(System.Single,System.Single)" />
+ <Member Name="op_LessThanOrEqual(System.Single,System.Single)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.Single@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Single@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.StackOverflowException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.STAThreadAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.String">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_stringLength" />
+ <Member MemberType="Field" Name="Empty" />
+ <Member Name="#ctor(System.Char*)" />
+ <Member Name="#ctor(System.Char*,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Char,System.Int32)" />
+ <Member Name="#ctor(System.Char[])" />
+ <Member Name="#ctor(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.SByte*)" />
+ <Member Name="#ctor(System.SByte*,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.SByte*,System.Int32,System.Int32,System.Text.Encoding)" />
+ <Member Name="Clone" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Int32)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Int32,System.Boolean)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Int32,System.Boolean,System.Globalization.CultureInfo)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Int32,System.Globalization.CultureInfo,System.Globalization.CompareOptions)" />
+ <Member Name="Compare(System.String,System.Int32,System.String,System.Int32,System.Int32,System.StringComparison)" />
+ <Member Name="Compare(System.String,System.String)" />
+ <Member Name="Compare(System.String,System.String,System.Boolean)" />
+ <Member Name="Compare(System.String,System.String,System.Boolean,System.Globalization.CultureInfo)" />
+ <Member Name="Compare(System.String,System.String,System.Globalization.CultureInfo,System.Globalization.CompareOptions)" />
+ <Member Name="Compare(System.String,System.String,System.StringComparison)" />
+ <Member Name="CompareOrdinal(System.String,System.Int32,System.String,System.Int32,System.Int32)" />
+ <Member Name="CompareOrdinal(System.String,System.String)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.String)" />
+ <Member Name="Concat(System.Object)" />
+ <Member Name="Concat(System.Object,System.Object)" />
+ <Member Name="Concat(System.Object,System.Object,System.Object)" />
+ <Member Name="Concat(System.Object[])" />
+ <Member Name="Concat&lt;T&gt;(System.Collections.Generic.IEnumerable&lt;T&gt;)" />
+ <Member Name="Concat(System.Collections.Generic.IEnumerable&lt;System.String&gt;)" />
+ <Member Name="Concat(System.String,System.String)" />
+ <Member Name="Concat(System.String,System.String,System.String)" />
+ <Member Name="Concat(System.String,System.String,System.String,System.String)" />
+ <Member Name="Concat(System.String[])" />
+ <Member Name="Contains(System.String)" />
+ <Member Name="Copy(System.String)" />
+ <Member Name="CopyTo(System.Int32,System.Char[],System.Int32,System.Int32)" />
+ <Member Name="EndsWith(System.String)" />
+ <Member Name="EndsWith(System.String,System.Boolean,System.Globalization.CultureInfo)" />
+ <Member Name="EndsWith(System.String,System.StringComparison)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.String)" />
+ <Member Name="Equals(System.String,System.String)" />
+ <Member Name="Equals(System.String,System.String,System.StringComparison)" />
+ <Member Name="Equals(System.String,System.StringComparison)" />
+ <Member Name="Format(System.IFormatProvider,System.String,System.Object)" />
+ <Member Name="Format(System.IFormatProvider,System.String,System.Object,System.Object)" />
+ <Member Name="Format(System.IFormatProvider,System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="Format(System.IFormatProvider,System.String,System.Object[])" />
+ <Member Name="Format(System.String,System.Object)" />
+ <Member Name="Format(System.String,System.Object,System.Object)" />
+ <Member Name="Format(System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="Format(System.String,System.Object[])" />
+ <Member Name="get_Chars(System.Int32)" />
+ <Member Name="get_Length" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="IndexOf(System.Char)" />
+ <Member Name="IndexOf(System.Char,System.Int32)" />
+ <Member Name="IndexOf(System.Char,System.Int32,System.Int32)" />
+ <Member Name="IndexOf(System.String)" />
+ <Member Name="IndexOf(System.String,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.Int32,System.Int32)" />
+ <Member Name="IndexOf(System.String,System.Int32,System.Int32,System.StringComparison)" />
+ <Member Name="IndexOf(System.String,System.Int32,System.StringComparison)" />
+ <Member Name="IndexOf(System.String,System.StringComparison)" />
+ <Member Name="IndexOfAny(System.Char[])" />
+ <Member Name="IndexOfAny(System.Char[],System.Int32)" />
+ <Member Name="IndexOfAny(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Insert(System.Int32,System.String)" />
+ <Member Name="Intern(System.String)" />
+ <Member Name="IsInterned(System.String)" />
+ <Member Name="IsNormalized" />
+ <Member Name="IsNormalized(System.Text.NormalizationForm)" />
+ <Member Name="IsNullOrEmpty(System.String)" />
+ <Member Name="IsNullOrWhiteSpace(System.String)" />
+ <Member Name="Join(System.String,System.Object[])" />
+ <Member Name="Join&lt;T&gt;(System.String,System.Collections.Generic.IEnumerable&lt;T&gt;)" />
+ <Member Name="Join(System.String,System.Collections.Generic.IEnumerable&lt;System.String&gt;)" />
+ <Member Name="Join(System.String,System.String[])" />
+ <Member Name="Join(System.String,System.String[],System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf(System.Char)" />
+ <Member Name="LastIndexOf(System.Char,System.Int32)" />
+ <Member Name="LastIndexOf(System.Char,System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf(System.String)" />
+ <Member Name="LastIndexOf(System.String,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.Int32,System.Int32)" />
+ <Member Name="LastIndexOf(System.String,System.Int32,System.Int32,System.StringComparison)" />
+ <Member Name="LastIndexOf(System.String,System.Int32,System.StringComparison)" />
+ <Member Name="LastIndexOf(System.String,System.StringComparison)" />
+ <Member Name="LastIndexOfAny(System.Char[])" />
+ <Member Name="LastIndexOfAny(System.Char[],System.Int32)" />
+ <Member Name="LastIndexOfAny(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Normalize" />
+ <Member Name="Normalize(System.Text.NormalizationForm)" />
+ <Member Name="op_Equality(System.String,System.String)" />
+ <Member Name="op_Inequality(System.String,System.String)" />
+ <Member Name="PadLeft(System.Int32)" />
+ <Member Name="PadLeft(System.Int32,System.Char)" />
+ <Member Name="PadRight(System.Int32)" />
+ <Member Name="PadRight(System.Int32,System.Char)" />
+ <Member Name="Remove(System.Int32)" />
+ <Member Name="Remove(System.Int32,System.Int32)" />
+ <Member Name="Replace(System.Char,System.Char)" />
+ <Member Name="Replace(System.String,System.String)" />
+ <Member Name="Split(System.Char)" />
+ <Member Name="Split(System.Char,System.Int32,System.StringSplitOptions)" />
+ <Member Name="Split(System.Char,System.StringSplitOptions)"/>
+ <Member Name="Split(System.Char[])" />
+ <Member Name="Split(System.Char[],System.Int32)" />
+ <Member Name="Split(System.Char[],System.Int32,System.StringSplitOptions)" />
+ <Member Name="Split(System.Char[],System.StringSplitOptions)"/>
+ <Member Name="Split(System.String)" />
+ <Member Name="Split(System.String,System.Int32,System.StringSplitOptions)" />
+ <Member Name="Split(System.String,System.StringSplitOptions)"/>
+ <Member Name="Split(System.String[],System.Int32,System.StringSplitOptions)" />
+ <Member Name="Split(System.String[],System.StringSplitOptions)"/>
+ <Member Name="StartsWith(System.String)" />
+ <Member Name="StartsWith(System.String,System.Boolean,System.Globalization.CultureInfo)" />
+ <Member Name="StartsWith(System.String,System.StringComparison)" />
+ <Member Name="Substring(System.Int32)" />
+ <Member Name="Substring(System.Int32,System.Int32)" />
+ <Member Name="ToCharArray" />
+ <Member Name="ToCharArray(System.Int32,System.Int32)" />
+ <Member Name="ToLower" />
+ <Member Name="ToLower(System.Globalization.CultureInfo)" />
+ <Member Name="ToLowerInvariant" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToUpper" />
+ <Member Name="ToUpper(System.Globalization.CultureInfo)" />
+ <Member Name="ToUpperInvariant" />
+ <Member Name="Trim" />
+ <Member Name="Trim(System.Char[])" />
+ <Member Name="TrimEnd(System.Char[])" />
+ <Member Name="TrimStart(System.Char[])" />
+ <Member MemberType="Property" Name="Chars(System.Int32)" />
+ <Member MemberType="Property" Name="Length" />
+ <Member Status="ImplRoot" Name="System.Collections.Generic.IEnumerable&lt;System.Char&gt;.GetEnumerator" />
+ <Member Status="ImplRoot" Name="CtorCharArray(System.Char[])" />
+ <Member Status="ImplRoot" Name="CtorCharArrayStartLength(System.Char[],System.Int32,System.Int32)" />
+ <Member Status="ImplRoot" Name="CtorCharCount(System.Char,System.Int32)" />
+ <Member Status="ImplRoot" Name="CtorCharPtr(System.Char*)" />
+ <Member Status="ImplRoot" Name="CtorCharPtrStartLength(System.Char*,System.Int32,System.Int32)" />
+ <Member Status="ImplRoot" Name="CreateString(System.SByte*,System.Int32,System.Int32,System.Text.Encoding)" /> <!-- EE -->
+ <Member Status="ImplRoot" Name="InternalCopy(System.String,System.IntPtr,System.Int32)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Collections.StructuralComparisons">
+ <Member Name="get_StructuralComparer" />
+ <Member Name="get_StructuralEqualityComparer" />
+ <Member MemberType="Property" Name="StructuralComparer" />
+ <Member MemberType="Property" Name="StructuralEqualityComparer" />
+ </Type>
+ <Type Name="System.StringComparer">
+ <Member Name="#ctor" />
+ <Member Name="Compare(System.Object,System.Object)" />
+ <Member Name="Compare(System.String,System.String)" />
+ <Member Name="Create(System.Globalization.CultureInfo,System.Boolean)" />
+ <Member Name="Equals(System.Object,System.Object)" />
+ <Member Name="Equals(System.String,System.String)" />
+ <Member Name="get_CurrentCulture" />
+ <Member Name="get_CurrentCultureIgnoreCase" />
+ <Member Name="get_InvariantCulture" />
+ <Member Name="get_InvariantCultureIgnoreCase" />
+ <Member Name="get_Ordinal" />
+ <Member Name="get_OrdinalIgnoreCase" />
+ <Member Name="GetHashCode(System.Object)" />
+ <Member Name="GetHashCode(System.String)" />
+ <Member MemberType="Property" Name="CurrentCulture" />
+ <Member MemberType="Property" Name="CurrentCultureIgnoreCase" />
+ <Member MemberType="Property" Name="InvariantCulture" />
+ <Member MemberType="Property" Name="InvariantCultureIgnoreCase" />
+ <Member MemberType="Property" Name="Ordinal" />
+ <Member MemberType="Property" Name="OrdinalIgnoreCase" />
+ </Type>
+ <Type Name="System.StringComparison">
+ <Member MemberType="Field" Name="CurrentCulture" />
+ <Member MemberType="Field" Name="CurrentCultureIgnoreCase" />
+ <Member MemberType="Field" Name="InvariantCulture" />
+ <Member MemberType="Field" Name="InvariantCultureIgnoreCase" />
+ <Member MemberType="Field" Name="Ordinal" />
+ <Member MemberType="Field" Name="OrdinalIgnoreCase" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.SystemException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Text.ASCIIEncoding">
+ <Member Name="#ctor" />
+ <Member Name="get_IsSingleByte" />
+ <Member Name="GetByteCount(System.Char*,System.Int32)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetCharCount(System.Byte*,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetDecoder" />
+ <Member Name="GetEncoder" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetString(System.Byte[],System.Int32,System.Int32)" />
+ <Member MemberType="Property" Name="IsSingleByte" />
+ </Type>
+ <Type Name="System.Text.Decoder">
+ <Member Name="#ctor" />
+ <Member Name="Convert(System.Byte*,System.Int32,System.Char*,System.Int32,System.Boolean,System.Int32@,System.Int32@,System.Boolean@)" />
+ <Member Name="Convert(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32,System.Int32,System.Boolean,System.Int32@,System.Int32@,System.Boolean@)" />
+ <Member Name="get_Fallback" />
+ <Member Name="get_FallbackBuffer" />
+ <Member Name="GetCharCount(System.Byte*,System.Int32,System.Boolean)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32,System.Boolean)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32,System.Boolean)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32,System.Boolean)" />
+ <Member Name="Reset" />
+ <Member Name="set_Fallback(System.Text.DecoderFallback)" />
+ <Member MemberType="Property" Name="Fallback" />
+ <Member MemberType="Property" Name="FallbackBuffer" />
+ </Type>
+ <Type Name="System.Text.DecoderExceptionFallbackBuffer">
+ <Member Name="#ctor" />
+ <Member Name="Fallback(System.Byte[],System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.DecoderFallback">
+ <Member Name="#ctor" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="get_ReplacementFallback" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ <Member MemberType="Property" Name="ReplacementFallback" />
+ <Member Name="get_ExceptionFallback" />
+ <Member MemberType="Property" Name="ExceptionFallback" />
+ </Type>
+ <Type Name="System.Text.DecoderFallbackBuffer">
+ <Member Name="#ctor" />
+ <Member Name="Fallback(System.Byte[],System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.DecoderReplacementFallback">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_DefaultString" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="GetHashCode" />
+ <Member MemberType="Property" Name="DefaultString" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ </Type>
+ <Type Name="System.Text.DecoderReplacementFallbackBuffer">
+ <Member Name="#ctor(System.Text.DecoderReplacementFallback)" />
+ <Member Name="Fallback(System.Byte[],System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.DecoderExceptionFallback">
+ <Member Name="#ctor" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="GetHashCode" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ </Type>
+ <Type Name="System.Text.DecoderFallbackException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Byte[],System.Int32)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_BytesUnknown" />
+ <Member Name="get_Index" />
+ <Member MemberType="Property" Name="BytesUnknown" />
+ <Member MemberType="Property" Name="Index" />
+ </Type>
+ <Type Name="System.Text.Encoder">
+ <Member Name="#ctor" />
+ <Member Name="Convert(System.Char*,System.Int32,System.Byte*,System.Int32,System.Boolean,System.Int32@,System.Int32@,System.Boolean@)" />
+ <Member Name="Convert(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32,System.Int32,System.Boolean,System.Int32@,System.Int32@,System.Boolean@)" />
+ <Member Name="get_Fallback" />
+ <Member Name="get_FallbackBuffer" />
+ <Member Name="GetByteCount(System.Char*,System.Int32,System.Boolean)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32,System.Boolean)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32,System.Boolean)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32,System.Boolean)" />
+ <Member Name="Reset" />
+ <Member Name="set_Fallback(System.Text.EncoderFallback)" />
+ <Member MemberType="Property" Name="Fallback" />
+ <Member MemberType="Property" Name="FallbackBuffer" />
+ </Type>
+ <Type Name="System.Text.EncoderFallback">
+ <Member Name="#ctor" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="get_ReplacementFallback" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ <Member MemberType="Property" Name="ReplacementFallback" />
+ <Member Name="get_ExceptionFallback" />
+ <Member MemberType="Property" Name="ExceptionFallback" />
+ </Type>
+ <Type Name="System.Text.EncoderFallbackBuffer">
+ <Member Name="#ctor" />
+ <Member Name="Fallback(System.Char,System.Char,System.Int32)" />
+ <Member Name="Fallback(System.Char,System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.EncoderReplacementFallback">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_DefaultString" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="GetHashCode" />
+ <Member MemberType="Property" Name="DefaultString" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ </Type>
+ <Type Name="System.Text.EncoderExceptionFallback">
+ <Member Name="#ctor" />
+ <Member Name="CreateFallbackBuffer" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_MaxCharCount" />
+ <Member Name="GetHashCode" />
+ <Member MemberType="Property" Name="MaxCharCount" />
+ </Type>
+ <Type Name="System.Text.EncoderExceptionFallbackBuffer">
+ <Member Name="#ctor" />
+ <Member Name="Fallback(System.Char,System.Char,System.Int32)" />
+ <Member Name="Fallback(System.Char,System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.EncoderFallbackException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Char,System.Int32)" />
+ <Member Name="#ctor(System.String,System.Char,System.Char,System.Int32)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="IsUnknownSurrogate" />
+ <Member Name="get_CharUnknown" />
+ <Member Name="get_CharUnknownHigh" />
+ <Member Name="get_CharUnknownLow" />
+ <Member Name="get_Index" />
+ <Member MemberType="Property" Name="CharUnknown" />
+ <Member MemberType="Property" Name="CharUnknownHigh" />
+ <Member MemberType="Property" Name="CharUnknownLow" />
+ <Member MemberType="Property" Name="Index" />
+ </Type>
+ <Type Name="System.Text.EncoderReplacementFallbackBuffer">
+ <Member Name="#ctor(System.Text.EncoderReplacementFallback)" />
+ <Member Name="Fallback(System.Char,System.Char,System.Int32)" />
+ <Member Name="Fallback(System.Char,System.Int32)" />
+ <Member Name="get_Remaining" />
+ <Member Name="GetNextChar" />
+ <Member Name="MovePrevious" />
+ <Member Name="Reset" />
+ <Member MemberType="Property" Name="Remaining" />
+ </Type>
+ <Type Name="System.Text.EncodingProvider">
+ <Member Name="#ctor" />
+ <Member Name="GetEncoding(System.Int32)" />
+ <Member Name="GetEncoding(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback)" />
+ <Member Name="GetEncoding(System.String)" />
+ <Member Name="GetEncoding(System.String,System.Text.EncoderFallback,System.Text.DecoderFallback)" />
+ </Type>
+ <Type Name="System.Text.Encoding">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback)" />
+ <Member Name="Clone" />
+ <Member Name="Convert(System.Text.Encoding,System.Text.Encoding,System.Byte[])" />
+ <Member Name="Convert(System.Text.Encoding,System.Text.Encoding,System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_ASCII" />
+ <Member Name="get_BigEndianUnicode" />
+ <Member Name="get_BodyName" />
+ <Member Name="get_CodePage" />
+ <Member Name="get_DecoderFallback" />
+ <Member Name="get_Default" />
+ <Member Name="get_EncoderFallback" />
+ <Member Name="get_EncodingName" />
+ <Member Name="get_HeaderName" />
+ <Member Name="get_IsBrowserDisplay" />
+ <Member Name="get_IsBrowserSave" />
+ <Member Name="get_IsMailNewsDisplay" />
+ <Member Name="get_IsMailNewsSave" />
+ <Member Name="get_IsReadOnly" />
+ <Member Name="get_IsSingleByte" />
+ <Member Name="get_Unicode" />
+ <Member Name="get_UTF32" />
+ <Member Name="get_UTF7" />
+ <Member Name="get_UTF8" />
+ <Member Name="get_WebName" />
+ <Member Name="get_WindowsCodePage" />
+ <Member Name="GetByteCount(System.Char*,System.Int32)" />
+ <Member Name="GetByteCount(System.Char[])" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char[])" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[])" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)" />
+ <Member Name="GetChars(System.Byte[])" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetString(System.Byte*,System.Int32)" /> <!-- New exposed API in ProjectK -->
+ <Member Name="GetDecoder" />
+ <Member Name="GetEncoder" />
+ <Member Name="RegisterProvider(System.Text.EncodingProvider)" />
+ <Member Name="GetEncoding(System.Int32)"/> <!-- For use in Framework assemblies, but not public in Win8P reference assemblies. -->
+ <Member Name="GetEncoding(System.Int32,System.Text.EncoderFallback,System.Text.DecoderFallback)" />
+ <Member Name="GetEncoding(System.String)" />
+ <Member Name="GetEncoding(System.String,System.Text.EncoderFallback,System.Text.DecoderFallback)" />
+ <Member Name="GetEncodings" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetPreamble" />
+ <Member Name="GetString(System.Byte[])" />
+ <Member Name="GetString(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="IsAlwaysNormalized" />
+ <Member Name="IsAlwaysNormalized(System.Text.NormalizationForm)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="set_DecoderFallback(System.Text.DecoderFallback)" />
+ <Member Name="set_EncoderFallback(System.Text.EncoderFallback)" />
+ <Member MemberType="Property" Name="ASCII" />
+ <Member MemberType="Property" Name="BigEndianUnicode" />
+ <Member MemberType="Property" Name="BodyName" />
+ <Member MemberType="Property" Name="CodePage" />
+ <Member MemberType="Property" Name="DecoderFallback" />
+ <Member MemberType="Property" Name="Default" />
+ <Member MemberType="Property" Name="EncoderFallback" />
+ <Member MemberType="Property" Name="EncodingName" />
+ <Member MemberType="Property" Name="HeaderName" />
+ <Member MemberType="Property" Name="IsBrowserDisplay" />
+ <Member MemberType="Property" Name="IsBrowserSave" />
+ <Member MemberType="Property" Name="IsMailNewsDisplay" />
+ <Member MemberType="Property" Name="IsMailNewsSave" />
+ <Member MemberType="Property" Name="IsReadOnly" />
+ <Member MemberType="Property" Name="IsSingleByte" />
+ <Member MemberType="Property" Name="Unicode" />
+ <Member MemberType="Property" Name="UTF32" />
+ <Member MemberType="Property" Name="UTF7" />
+ <Member MemberType="Property" Name="UTF8" />
+ <Member MemberType="Property" Name="WebName" />
+ </Type>
+ <Type Name="System.Text.EncodingInfo">
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_CodePage" />
+ <Member Name="get_DisplayName" />
+ <Member Name="get_Name" />
+ <Member Name="GetEncoding" />
+ <Member Name="GetHashCode" />
+ <Member MemberType="Property" Name="CodePage" />
+ <Member MemberType="Property" Name="DisplayName" />
+ <Member MemberType="Property" Name="Name" />
+ </Type>
+ <Type Name="System.Text.NormalizationForm">
+ <Member MemberType="Field" Name="FormC" />
+ <Member MemberType="Field" Name="FormD" />
+ <Member MemberType="Field" Name="FormKC" />
+ <Member MemberType="Field" Name="FormKD" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Text.StringBuilder">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="#ctor(System.String,System.Int32,System.Int32,System.Int32)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Append(System.Boolean)" />
+ <Member Name="Append(System.Byte)" />
+ <Member Name="Append(System.Char)" />
+ <Member Name="Append(System.Char,System.Int32)" />
+ <Member Name="Append(System.Char[])" />
+ <Member Name="Append(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Append(System.Char*,System.Int32)" />
+ <Member Name="Append(System.Decimal)" />
+ <Member Name="Append(System.Double)" />
+ <Member Name="Append(System.Int16)" />
+ <Member Name="Append(System.Int32)" />
+ <Member Name="Append(System.Int64)" />
+ <Member Name="Append(System.Object)" />
+ <Member Name="Append(System.SByte)" />
+ <Member Name="Append(System.Single)" />
+ <Member Name="Append(System.String)" />
+ <Member Name="Append(System.String,System.Int32,System.Int32)" />
+ <Member Name="Append(System.UInt16)" />
+ <Member Name="Append(System.UInt32)" />
+ <Member Name="Append(System.UInt64)" />
+ <Member Name="AppendFormat(System.IFormatProvider,System.String,System.Object)" />
+ <Member Name="AppendFormat(System.IFormatProvider,System.String,System.Object,System.Object)" />
+ <Member Name="AppendFormat(System.IFormatProvider,System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="AppendFormat(System.IFormatProvider,System.String,System.Object[])" />
+ <Member Name="AppendFormat(System.String,System.Object)" />
+ <Member Name="AppendFormat(System.String,System.Object,System.Object)" />
+ <Member Name="AppendFormat(System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="AppendFormat(System.String,System.Object[])" />
+ <Member Name="AppendLine" />
+ <Member Name="AppendLine(System.String)" />
+ <Member Name="Clear" />
+ <Member Name="CopyTo(System.Int32,System.Char[],System.Int32,System.Int32)" />
+ <Member Name="EnsureCapacity(System.Int32)" />
+ <Member Name="Equals(System.Text.StringBuilder)" />
+ <Member Name="get_Capacity" />
+ <Member Name="get_Chars(System.Int32)" />
+ <Member Name="get_Length" />
+ <Member Name="get_MaxCapacity" />
+ <Member Name="Insert(System.Int32,System.Boolean)" />
+ <Member Name="Insert(System.Int32,System.Byte)" />
+ <Member Name="Insert(System.Int32,System.Char)" />
+ <Member Name="Insert(System.Int32,System.Char[])" />
+ <Member Name="Insert(System.Int32,System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Insert(System.Int32,System.Decimal)" />
+ <Member Name="Insert(System.Int32,System.Double)" />
+ <Member Name="Insert(System.Int32,System.Int16)" />
+ <Member Name="Insert(System.Int32,System.Int32)" />
+ <Member Name="Insert(System.Int32,System.Int64)" />
+ <Member Name="Insert(System.Int32,System.Object)" />
+ <Member Name="Insert(System.Int32,System.SByte)" />
+ <Member Name="Insert(System.Int32,System.Single)" />
+ <Member Name="Insert(System.Int32,System.String)" />
+ <Member Name="Insert(System.Int32,System.String,System.Int32)" />
+ <Member Name="Insert(System.Int32,System.UInt16)" />
+ <Member Name="Insert(System.Int32,System.UInt32)" />
+ <Member Name="Insert(System.Int32,System.UInt64)" />
+ <Member Name="Remove(System.Int32,System.Int32)" />
+ <Member Name="Replace(System.Char,System.Char)" />
+ <Member Name="Replace(System.Char,System.Char,System.Int32,System.Int32)" />
+ <Member Name="Replace(System.String,System.String)" />
+ <Member Name="Replace(System.String,System.String,System.Int32,System.Int32)" />
+ <Member Name="set_Capacity(System.Int32)" />
+ <Member Name="set_Chars(System.Int32,System.Char)" />
+ <Member Name="set_Length(System.Int32)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.Int32,System.Int32)" />
+ <Member MemberType="Property" Name="Capacity" />
+ <Member MemberType="Property" Name="Chars(System.Int32)" />
+ <Member MemberType="Property" Name="Length" />
+ <Member MemberType="Property" Name="MaxCapacity" />
+ <Member Status="ImplRoot" Name="InternalCopy(System.IntPtr,System.Int32)" /> <!-- EE - il stubs -->
+ <Member Status="ImplRoot" Name="ReplaceBufferInternal(System.Char*,System.Int32)" /> <!-- EE - il stubs -->
+ <Member Status="ImplRoot" Name="ReplaceBufferAnsiInternal(System.SByte*,System.Int32)" /> <!-- EE - il stubs -->
+ </Type>
+ <Type Name="System.Text.UnicodeEncoding">
+ <Member MemberType="Field" Name="CharSize" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean,System.Boolean)" />
+ <Member Name="#ctor(System.Boolean,System.Boolean,System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetByteCount(System.Char*,System.Int32)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetCharCount(System.Byte*,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetDecoder" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetPreamble" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Text.UTF32Encoding">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean,System.Boolean)" />
+ <Member Name="#ctor(System.Boolean,System.Boolean,System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetByteCount(System.Char*,System.Int32)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetCharCount(System.Byte*,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetDecoder" />
+ <Member Name="GetEncoder" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetPreamble" />
+ <Member Name="GetString(System.Byte[],System.Int32,System.Int32)" />
+ </Type>
+ <Type Name="System.Text.UTF7Encoding">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetByteCount(System.Char*,System.Int32)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char*,System.Int32,System.Byte*,System.Int32)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetCharCount(System.Byte*,System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte*,System.Int32,System.Char*,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetDecoder" />
+ <Member Name="GetEncoder" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetString(System.Byte[],System.Int32,System.Int32)" />
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnDeserializing(System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Text.UTF8Encoding">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="#ctor(System.Boolean,System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetByteCount(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="GetByteCount(System.String)" />
+ <Member Name="GetBytes(System.Char[],System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetBytes(System.String,System.Int32,System.Int32,System.Byte[],System.Int32)" />
+ <Member Name="GetCharCount(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="GetChars(System.Byte[],System.Int32,System.Int32,System.Char[],System.Int32)" />
+ <Member Name="GetDecoder" />
+ <Member Name="GetEncoder" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetMaxByteCount(System.Int32)" />
+ <Member Name="GetMaxCharCount(System.Int32)" />
+ <Member Name="GetPreamble" />
+ </Type>
+ <Type Name="System.Threading.AbandonedMutexException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Int32,System.Threading.WaitHandle)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Exception,System.Int32,System.Threading.WaitHandle)" />
+ <Member Name="#ctor(System.String,System.Int32,System.Threading.WaitHandle)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Property" Name="Mutex" />
+ <Member MemberType="Property" Name="MutexIndex" />
+ </Type>
+ <Type Name="System.Threading.AutoResetEvent">
+ <Member Name="#ctor(System.Boolean)" />
+ </Type>
+ <Type Name="System.Threading.EventWaitHandle">
+ <Member Name="#ctor(System.Boolean,System.Threading.EventResetMode)" />
+ <Member Name="#ctor(System.Boolean,System.Threading.EventResetMode,System.String)" />
+ <Member Name="#ctor(System.Boolean,System.Threading.EventResetMode,System.String,System.Boolean@)" />
+ <Member Name="OpenExisting(System.String)" />
+ <Member Name="Reset" />
+ <Member Name="Set" />
+ <Member Name="TryOpenExisting(System.String,System.Threading.EventWaitHandle@)" />
+ </Type>
+ <Type Name="System.Threading.Interlocked">
+ <Member Name="Add(System.Int32@,System.Int32)" />
+ <Member Name="Add(System.Int64@,System.Int64)" />
+ <Member Name="CompareExchange(System.Double@,System.Double,System.Double)" />
+ <Member Name="CompareExchange(System.Int32@,System.Int32,System.Int32)" />
+ <Member Name="CompareExchange(System.Int64@,System.Int64,System.Int64)" />
+ <Member Name="CompareExchange(System.IntPtr@,System.IntPtr,System.IntPtr)" />
+ <Member Name="CompareExchange(System.Object@,System.Object,System.Object)" />
+ <Member Name="CompareExchange(System.Single@,System.Single,System.Single)" />
+ <Member Name="CompareExchange&lt;T&gt;(T@,T,T)" />
+ <Member Name="Decrement(System.Int32@)" />
+ <Member Name="Decrement(System.Int64@)" />
+ <Member Name="Exchange(System.Double@,System.Double)" />
+ <Member Name="Exchange(System.Int32@,System.Int32)" />
+ <Member Name="Exchange(System.Int64@,System.Int64)" />
+ <Member Name="Exchange(System.IntPtr@,System.IntPtr)" />
+ <Member Name="Exchange(System.Object@,System.Object)" />
+ <Member Name="Exchange(System.Single@,System.Single)" />
+ <Member Name="Exchange&lt;T&gt;(T@,T)" />
+ <Member Name="Increment(System.Int32@)" />
+ <Member Name="Increment(System.Int64@)" />
+ <Member Name="MemoryBarrier" />
+ <Member Name="Read(System.Int64@)" />
+ </Type>
+ <Type Name="System.Threading.LockRecursionException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.Mutex">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="#ctor(System.Boolean,System.String)" />
+ <Member Name="#ctor(System.Boolean,System.String,System.Boolean@)" />
+ <Member Name="OpenExisting(System.String)" />
+ <Member Name="ReleaseMutex" />
+ <Member Name="TryOpenExisting(System.String,System.Threading.Mutex@)" />
+ </Type>
+ <Type Name="System.Threading.Volatile">
+ <Member Name="Read(System.Boolean@)"/>
+ <Member Name="Read(System.SByte@)"/>
+ <Member Name="Read(System.Byte@)"/>
+ <Member Name="Read(System.Int16@)"/>
+ <Member Name="Read(System.UInt16@)"/>
+ <Member Name="Read(System.Int32@)"/>
+ <Member Name="Read(System.UInt32@)"/>
+ <Member Name="Read(System.Int64@)"/>
+ <Member Name="Read(System.UInt64@)"/>
+ <Member Name="Read(System.IntPtr@)"/>
+ <Member Name="Read(System.UIntPtr@)"/>
+ <Member Name="Read(System.Single@)"/>
+ <Member Name="Read(System.Double@)"/>
+ <Member Name="Read&lt;T&gt;(T@)"/>
+ <Member Name="Write(System.Boolean@,System.Boolean)"/>
+ <Member Name="Write(System.SByte@,System.SByte)"/>
+ <Member Name="Write(System.Byte@,System.Byte)"/>
+ <Member Name="Write(System.Int16@,System.Int16)"/>
+ <Member Name="Write(System.UInt16@,System.UInt16)"/>
+ <Member Name="Write(System.Int32@,System.Int32)"/>
+ <Member Name="Write(System.UInt32@,System.UInt32)"/>
+ <Member Name="Write(System.Int64@,System.Int64)"/>
+ <Member Name="Write(System.UInt64@,System.UInt64)"/>
+ <Member Name="Write(System.IntPtr@,System.IntPtr)"/>
+ <Member Name="Write(System.UIntPtr@,System.UIntPtr)"/>
+ <Member Name="Write(System.Single@,System.Single)"/>
+ <Member Name="Write(System.Double@,System.Double)"/>
+ <Member Name="Write&lt;T&gt;(T@,T)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.IThreadPoolWorkItem">
+ <Member Status="ImplRoot" Name="ExecuteWorkItem"/>
+ </Type>
+ <Type Name="System.Threading.Monitor">
+ <Member Name="Enter(System.Object)" />
+ <Member Name="Enter(System.Object,System.Boolean@)" />
+ <Member Name="IsEntered(System.Object)" />
+ <Member Name="Exit(System.Object)" />
+ <Member Name="Pulse(System.Object)" />
+ <Member Name="PulseAll(System.Object)" />
+ <Member Name="TryEnter(System.Object)" />
+ <Member Name="TryEnter(System.Object,System.Int32)" />
+ <Member Name="TryEnter(System.Object,System.TimeSpan)" />
+ <Member Name="TryEnter(System.Object,System.Boolean@)" />
+ <Member Name="TryEnter(System.Object,System.Int32,System.Boolean@)" />
+ <Member Name="TryEnter(System.Object,System.TimeSpan,System.Boolean@)" />
+ <Member Name="Wait(System.Object)" />
+ <Member Name="Wait(System.Object,System.Int32)" />
+ <Member Name="Wait(System.Object,System.TimeSpan)" />
+ </Type>
+ <Type Name="System.Threading.ManualResetEvent">
+ <Member Name="#ctor(System.Boolean)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.QueueUserWorkItemCallback">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.WaitCallback,System.Object,System.Threading.ExecutionContext)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.QueueUserWorkItemCallbackDefaultContext">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.WaitCallback,System.Object)"/>
+ </Type>
+ <Type Name="System.Threading.SynchronizationContext">
+ <Member Name="#ctor"/>
+ <Member Name="Send(System.Threading.SendOrPostCallback,System.Object)"/>
+ <Member Name="Post(System.Threading.SendOrPostCallback,System.Object)"/>
+ <Member Name="OperationStarted"/>
+ <Member Name="OperationCompleted"/>
+ <Member Name="SetSynchronizationContext(System.Threading.SynchronizationContext)"/>
+ <Member Name="get_Current"/>
+ <Member Name="CreateCopy"/>
+ <Member MemberType="Property" Name="Current"/>
+ </Type>
+ <Type Name="System.Threading.SynchronizationLockException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.Thread">
+ <Member Name="#ctor(System.Threading.ThreadStart)" />
+ <Member Name="#ctor(System.Threading.ParameterizedThreadStart)" />
+ <Member Name="MemoryBarrier" />
+ <Member Name="Finalize" />
+ <Member Name="get_CurrentCulture" />
+ <Member Name="get_CurrentThread" />
+ <Member Name="get_CurrentUICulture" />
+ <Member Name="GetDomain" />
+ <Member Name="get_IsBackground" />
+ <Member Name="get_ManagedThreadId" />
+ <Member Name="get_Name" />
+ <Member Name="get_IsAlive" />
+ <Member Name="get_ThreadState" />
+ <Member Name="Join" />
+ <Member Name="Join(System.Int32)" />
+ <Member Name="set_IsBackground(System.Boolean)" />
+ <Member Name="set_Name(System.String)" />
+ <Member Name="Sleep(System.Int32)" />
+ <Member Name="Sleep(System.TimeSpan)" />
+ <Member Name="SpinWait(System.Int32)" />
+ <Member Name="Start" />
+ <Member Name="Start(System.Object)" />
+ <Member MemberType="Property" Name="CurrentCulture" />
+ <Member MemberType="Property" Name="CurrentThread" />
+ <Member MemberType="Property" Name="CurrentUICulture" />
+ <Member MemberType="Property" Name="IsBackground" />
+ <Member MemberType="Property" Name="ManagedThreadId" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="IsAlive" />
+ <Member MemberType="Property" Name="ThreadState" />
+ <Member Status="ImplRoot" Name="InternalGetCurrentThread" />
+ <Member Status="ImplRoot" MemberType="Field" Name="DONT_USE_InternalThread" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_Priority" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_ThreadStartArg" />
+ </Type>
+ <Type Name="System.Threading.ThreadAbortException">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.ThreadPool">
+ <Member Name="GetMaxThreads(System.Int32@,System.Int32@)" />
+ <Member Name="QueueUserWorkItem(System.Threading.WaitCallback)" />
+ <Member Name="QueueUserWorkItem(System.Threading.WaitCallback,System.Object)" />
+ <Member Name="SetMaxThreads(System.Int32,System.Int32)" />
+ <Member Name="BindHandle(System.Runtime.InteropServices.SafeHandle)" />
+ <Member Name="RegisterWaitForSingleObject(System.Threading.WaitHandle,System.Threading.WaitOrTimerCallback,System.Object,System.UInt32,System.Boolean)" />
+ <Member Name="RegisterWaitForSingleObject(System.Threading.WaitHandle,System.Threading.WaitOrTimerCallback,System.Object,System.Int32,System.Boolean)" />
+ <Member Name="RegisterWaitForSingleObject(System.Threading.WaitHandle,System.Threading.WaitOrTimerCallback,System.Object,System.Int64,System.Boolean)" />
+ <Member Name="RegisterWaitForSingleObject(System.Threading.WaitHandle,System.Threading.WaitOrTimerCallback,System.Object,System.TimeSpan,System.Boolean)" />
+ <Member Name="SetMinThreads(System.Int32,System.Int32)" />
+ <Member Name="GetMinThreads(System.Int32@,System.Int32@)" />
+ <Member Status="ImplRoot" Name="RegisterWaitForSingleObject(System.Threading.WaitHandle,System.Threading.WaitOrTimerCallback,System.Object,System.UInt32,System.Boolean,System.Threading.StackCrawlMark@,System.Boolean)" />
+ <Member Status="ImplRoot" Name="RegisterWaitForSingleObjectNative(System.Threading.WaitHandle,System.Object,System.UInt32,System.Boolean,System.Threading.RegisteredWaitHandle,System.Threading.StackCrawlMark@,System.Boolean)" />
+ <Member Status="ImplRoot" Name="UnsafeQueueCustomWorkItem(System.Threading.IThreadPoolWorkItem,System.Boolean)"/>
+ <Member Status="ImplRoot" Name="TryPopCustomWorkItem(System.Threading.IThreadPoolWorkItem)"/>
+ <Member Status="ImplRoot" Name="GetQueuedWorkItemsForDebugger"/>
+ <Member Status="ImplRoot" Name="GetGloballyQueuedWorkItemsForDebugger"/>
+ <Member Status="ImplRoot" Name="GetLocallyQueuedWorkItemsForDebugger"/>
+ <Member Status="ImplRoot" Name="NotifyWorkItemProgress"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.StackCrawlMark">
+ <Member MemberType="Field" Name="LookForMe" />
+ <Member MemberType="Field" Name="LookForMyCaller" />
+ <Member MemberType="Field" Name="LookForMyCallersCaller" />
+ <Member MemberType="Field" Name="LookForThread" />
+ </Type>
+ <Type Name="System.Threading.NativeOverlapped">
+ <Member MemberType="Field" Name="InternalLow" />
+ <Member MemberType="Field" Name="InternalHigh" />
+ <Member MemberType="Field" Name="OffsetLow" />
+ <Member MemberType="Field" Name="OffsetHigh" />
+ <Member MemberType="Field" Name="EventHandle" />
+ </Type>
+ <Type Name="System.Threading.Overlapped">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="AsyncResult" />
+ <Member MemberType="Property" Name="OffsetLow" />
+ <Member MemberType="Property" Name="OffsetHigh" />
+ <Member Name="Free(System.Threading.NativeOverlapped*)" />
+ <Member Name="Pack(System.Threading.IOCompletionCallback,System.Object)" />
+ <Member Name="Unpack(System.Threading.NativeOverlapped*)" />
+ <Member Name="UnsafePack(System.Threading.IOCompletionCallback,System.Object)" Condition="FEATURE_COMINTEROP" />
+ </Type>
+ <Type Name="System.Threading.IOCompletionCallback">
+ </Type>
+ <Type Name="System.Threading.RegisteredWaitHandle">
+ <Member Name="Unregister(System.Threading.WaitHandle)" />
+ <Member Status="ImplRoot" Name="SetHandle(System.IntPtr)" />
+ <Member Status="ImplRoot" Name="SetWaitObject(System.Threading.WaitHandle)" />
+ </Type>
+ <Type Name="System.Threading.ThreadState">
+ <Member MemberType="Field" Name="Running" />
+ <Member MemberType="Field" Name="StopRequested" />
+ <Member MemberType="Field" Name="SuspendRequested" />
+ <Member MemberType="Field" Name="Background" />
+ <Member MemberType="Field" Name="Unstarted" />
+ <Member MemberType="Field" Name="Stopped" />
+ <Member MemberType="Field" Name="WaitSleepJoin" />
+ <Member MemberType="Field" Name="Suspended" />
+ <Member MemberType="Field" Name="AbortRequested" />
+ <Member MemberType="Field" Name="Aborted" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Threading.ThreadStart">
+ </Type>
+ <Type Name="System.Threading.ParameterizedThreadStart">
+ </Type>
+ <Type Name="System.Threading.SendOrPostCallback">
+ </Type>
+ <Type Name="System.Threading.ThreadStartException">
+ <Member Status="ImplRoot" Name="#ctor(System.Exception)" /><!-- EE -->
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.ThreadStateException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.Timeout">
+ <Member MemberType="Field" Name="Infinite" />
+ <Member MemberType="Field" Name="InfiniteTimeSpan" />
+ </Type>
+ <Type Name="System.Threading.Timer">
+ <Member Name="#ctor(System.Threading.TimerCallback)" />
+ <Member Name="#ctor(System.Threading.TimerCallback,System.Object,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Threading.TimerCallback,System.Object,System.Int64,System.Int64)" />
+ <Member Name="#ctor(System.Threading.TimerCallback,System.Object,System.TimeSpan,System.TimeSpan)" />
+ <Member Name="#ctor(System.Threading.TimerCallback,System.Object,System.UInt32,System.UInt32)" />
+ <Member Name="Change(System.Int32,System.Int32)" />
+ <Member Name="Change(System.Int64,System.Int64)" />
+ <Member Name="Change(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="Change(System.UInt32,System.UInt32)" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Threading.WaitHandle)" />
+ </Type>
+ <Type Name="System.Threading.TimerCallback">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object)" />
+ </Type>
+ <Type Name="System.Threading.WaitCallback">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object)" />
+ </Type>
+ <Type Name="System.Threading.WaitOrTimerCallback">
+ </Type>
+ <Type Name="System.Threading.WaitHandle">
+ <Member MemberType="Field" Name="InvalidHandle" />
+ <Member MemberType="Field" Name="WaitTimeout" />
+ <Member Name="#ctor" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="get_Handle" />
+ <Member Name="set_Handle(System.IntPtr)" />
+ <Member Name="get_SafeWaitHandle" />
+ <Member Name="set_SafeWaitHandle(Microsoft.Win32.SafeHandles.SafeWaitHandle)" />
+ <Member Name="SignalAndWait(System.Threading.WaitHandle,System.Threading.WaitHandle)" />
+ <Member Name="SignalAndWait(System.Threading.WaitHandle,System.Threading.WaitHandle,System.Int32,System.Boolean)" />
+ <Member Name="SignalAndWait(System.Threading.WaitHandle,System.Threading.WaitHandle,System.TimeSpan,System.Boolean)" />
+ <Member Name="WaitAny(System.Threading.WaitHandle[])" />
+ <Member Name="WaitAny(System.Threading.WaitHandle[],System.Int32)" />
+ <Member Name="WaitAny(System.Threading.WaitHandle[],System.Int32,System.Boolean)" />
+ <Member Name="WaitAny(System.Threading.WaitHandle[],System.TimeSpan)" />
+ <Member Name="WaitAny(System.Threading.WaitHandle[],System.TimeSpan,System.Boolean)" />
+ <Member Name="WaitAll(System.Threading.WaitHandle[])" />
+ <Member Name="WaitAll(System.Threading.WaitHandle[],System.Int32)" />
+ <Member Name="WaitAll(System.Threading.WaitHandle[],System.Int32,System.Boolean)" />
+ <Member Name="WaitAll(System.Threading.WaitHandle[],System.TimeSpan)" />
+ <Member Name="WaitAll(System.Threading.WaitHandle[],System.TimeSpan,System.Boolean)" />
+ <Member Name="WaitOne" />
+ <Member Name="WaitOne(System.Int32)" />
+ <Member Name="WaitOne(System.Int32,System.Boolean)" />
+ <Member Name="WaitOne(System.TimeSpan)" />
+ <Member Name="WaitOne(System.TimeSpan,System.Boolean)" />
+ <Member MemberType="Property" Name="SafeWaitHandle" />
+ </Type>
+ <Type Name="System.Threading.WaitHandleExtensions">
+ <Member Name="GetSafeWaitHandle(System.Threading.WaitHandle)" />
+ <Member Name="SetSafeWaitHandle(System.Threading.WaitHandle,Microsoft.Win32.SafeHandles.SafeWaitHandle)" />
+ </Type>
+ <Type Name="System.Threading.WaitHandleCannotBeOpenedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.TimeoutException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.TimeSpan">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member MemberType="Field" Name="TicksPerDay" />
+ <Member MemberType="Field" Name="TicksPerHour" />
+ <Member MemberType="Field" Name="TicksPerMillisecond" />
+ <Member MemberType="Field" Name="TicksPerMinute" />
+ <Member MemberType="Field" Name="TicksPerSecond" />
+ <Member MemberType="Field" Name="Zero" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int64)" />
+ <Member Name="Add(System.TimeSpan)" />
+ <Member Name="Compare(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.TimeSpan)" />
+ <Member Name="Duration" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.TimeSpan)" />
+ <Member Name="Equals(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="FromDays(System.Double)" />
+ <Member Name="FromHours(System.Double)" />
+ <Member Name="FromMilliseconds(System.Double)" />
+ <Member Name="FromMinutes(System.Double)" />
+ <Member Name="FromSeconds(System.Double)" />
+ <Member Name="FromTicks(System.Int64)" />
+ <Member Name="get_Days" />
+ <Member Name="get_Hours" />
+ <Member Name="get_Milliseconds" />
+ <Member Name="get_Minutes" />
+ <Member Name="get_Seconds" />
+ <Member Name="get_Ticks" />
+ <Member Name="get_TotalDays" />
+ <Member Name="get_TotalHours" />
+ <Member Name="get_TotalMilliseconds" />
+ <Member Name="get_TotalMinutes" />
+ <Member Name="get_TotalSeconds" />
+ <Member Name="GetHashCode" />
+ <Member Name="Negate" />
+ <Member Name="op_Addition(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_Equality(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_GreaterThan(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_GreaterThanOrEqual(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_Inequality(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_LessThan(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_LessThanOrEqual(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_Subtraction(System.TimeSpan,System.TimeSpan)" />
+ <Member Name="op_UnaryPlus(System.TimeSpan)" />
+ <Member Name="op_UnaryNegation(System.TimeSpan)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider)" />
+ <Member Name="ParseExact(System.String,System.String[],System.IFormatProvider)" />
+ <Member Name="ParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.TimeSpanStyles)" />
+ <Member Name="ParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.TimeSpanStyles)" />
+ <Member Name="TryParse(System.String,System.TimeSpan@)" />
+ <Member Name="TryParse(System.String,System.IFormatProvider,System.TimeSpan@)" />
+ <Member Name="TryParseExact(System.String,System.String,System.IFormatProvider,System.TimeSpan@)" />
+ <Member Name="TryParseExact(System.String,System.String[],System.IFormatProvider,System.TimeSpan@)" />
+ <Member Name="TryParseExact(System.String,System.String,System.IFormatProvider,System.Globalization.TimeSpanStyles,System.TimeSpan@)" />
+ <Member Name="TryParseExact(System.String,System.String[],System.IFormatProvider,System.Globalization.TimeSpanStyles,System.TimeSpan@)" />
+ <Member Name="Subtract(System.TimeSpan)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.String)" />
+ <Member MemberType="Property" Name="Days" />
+ <Member MemberType="Property" Name="Hours" />
+ <Member MemberType="Property" Name="Milliseconds" />
+ <Member MemberType="Property" Name="Minutes" />
+ <Member MemberType="Property" Name="Seconds" />
+ <Member MemberType="Property" Name="Ticks" />
+ <Member MemberType="Property" Name="TotalDays" />
+ <Member MemberType="Property" Name="TotalHours" />
+ <Member MemberType="Property" Name="TotalMilliseconds" />
+ <Member MemberType="Property" Name="TotalMinutes" />
+ <Member MemberType="Property" Name="TotalSeconds" />
+ </Type>
+ <Type Name="System.TimeZone">
+ <Member Name="#ctor" />
+ <Member Name="get_DaylightName" />
+ <Member Name="get_StandardName" />
+ <Member Name="GetDaylightChanges(System.Int32)" />
+ <Member Name="GetUtcOffset(System.DateTime)" />
+ <Member Name="IsDaylightSavingTime(System.DateTime)" />
+ <Member Name="IsDaylightSavingTime(System.DateTime,System.Globalization.DaylightTime)" />
+ <Member Name="ToUniversalTime(System.DateTime)" />
+ <Member MemberType="Property" Name="DaylightName" />
+ <Member MemberType="Property" Name="StandardName" />
+<!-- This members need CurrentSystemTimeZone which needs Linux implementations
+ <Member Name="ToLocalTime(System.DateTime)" />
+ <Member MemberType="Property" Name="CurrentTimeZone" />
+ <Member Name="get_CurrentTimeZone" />
+-->
+ </Type>
+ <Type Name="System.TimeZoneInfo">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="ClearCachedData" />
+ <Member Name="ConvertTime(System.DateTime,System.TimeZoneInfo)" />
+ <Member Name="ConvertTime(System.DateTime,System.TimeZoneInfo,System.TimeZoneInfo)" />
+ <Member Name="ConvertTime(System.DateTimeOffset,System.TimeZoneInfo)" />
+<!-- Need Linux Implementation
+ <Member Name="ConvertTimeBySystemTimeZoneId(System.DateTime,System.String)" />
+ <Member Name="ConvertTimeBySystemTimeZoneId(System.DateTime,System.String,System.String)" />
+ <Member Name="ConvertTimeBySystemTimeZoneId(System.DateTimeOffset,System.String)" />
+-->
+ <Member Name="ConvertTimeFromUtc(System.DateTime,System.TimeZoneInfo)" />
+ <Member Name="ConvertTimeToUtc(System.DateTime)" />
+ <Member Name="ConvertTimeToUtc(System.DateTime,System.TimeZoneInfo)" />
+ <Member Name="CreateCustomTimeZone(System.String,System.TimeSpan,System.String,System.String)" />
+ <Member Name="CreateCustomTimeZone(System.String,System.TimeSpan,System.String,System.String,System.String,System.TimeZoneInfo+AdjustmentRule[])" />
+ <Member Name="CreateCustomTimeZone(System.String,System.TimeSpan,System.String,System.String,System.String,System.TimeZoneInfo+AdjustmentRule[],System.Boolean)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.TimeZoneInfo)" />
+ <Member Name="FindSystemTimeZoneById(System.String)" />
+ <Member Name="FromSerializedString(System.String)" />
+ <Member Name="get_BaseUtcOffset" />
+ <Member Name="get_DisplayName" />
+ <Member Name="get_DaylightName" />
+ <Member Name="get_StandardName" />
+ <Member Name="get_Id" />
+ <Member Name="get_Local" />
+ <Member Name="get_SupportsDaylightSavingTime" />
+ <Member Name="get_Utc" />
+ <Member Name="GetAdjustmentRules" />
+ <Member Name="GetAmbiguousTimeOffsets(System.DateTimeOffset)" />
+ <Member Name="GetAmbiguousTimeOffsets(System.DateTime)" />
+ <Member Name="GetUtcOffset(System.DateTimeOffset)" />
+ <Member Name="GetUtcOffset(System.DateTime)" />
+ <Member Name="HasSameRules(System.TimeZoneInfo)" />
+ <Member Name="IsAmbiguousTime(System.DateTimeOffset)" />
+ <Member Name="IsAmbiguousTime(System.DateTime)" />
+ <Member Name="IsDaylightSavingTime(System.DateTimeOffset)" />
+ <Member Name="IsDaylightSavingTime(System.DateTime)" />
+ <Member Name="IsInvalidTime(System.DateTime)" />
+ <Member Name="ToSerializedString" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetSystemTimeZones" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="DaylightName" />
+ <Member MemberType="Property" Name="DisplayName" />
+ <Member MemberType="Property" Name="Id" />
+ <Member MemberType="Property" Name="Local" />
+ <Member MemberType="Property" Name="StandardName" />
+ <Member MemberType="Property" Name="BaseUtcOffset" />
+ <Member MemberType="Property" Name="SupportsDaylightSavingTime" />
+ <Member MemberType="Property" Name="Utc" />
+ </Type>
+ <Type Name="System.TimeZoneInfo+AdjustmentRule">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <!-- CreateAdjustmentRule doesn't have a public contract, but tests and other callers can use Reflection to invoke it, so ensure it is left in mscorlib. -->
+ <Member Status="ApiRoot" Name="CreateAdjustmentRule(System.DateTime,System.DateTime,System.TimeSpan,System.TimeZoneInfo+TransitionTime,System.TimeZoneInfo+TransitionTime)" />
+ <Member Name="get_DateEnd" />
+ <Member Name="get_DateStart" />
+ <Member Name="get_DaylightDelta" />
+ <Member Name="get_DaylightTransitionEnd" />
+ <Member Name="get_DaylightTransitionStart" />
+ <Member MemberType="Property" Name="DateEnd" />
+ <Member MemberType="Property" Name="DateStart" />
+ <Member MemberType="Property" Name="DaylightDelta" />
+ <Member MemberType="Property" Name="DaylightTransitionEnd" />
+ <Member MemberType="Property" Name="DaylightTransitionStart" />
+ </Type>
+ <Type Name="System.TimeZoneInfo+TransitionTime">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="CreateFixedDateRule(System.DateTime,System.Int32,System.Int32)" />
+ <Member Name="CreateFloatingDateRule(System.DateTime,System.Int32,System.Int32,System.DayOfWeek)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.TimeZoneInfo+TransitionTime)" />
+ <Member Name="get_Day" />
+ <Member Name="get_DayOfWeek" />
+ <Member Name="get_IsFixedDateRule" />
+ <Member Name="get_Month" />
+ <Member Name="get_TimeOfDay" />
+ <Member Name="get_Week" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.TimeZoneInfo+TransitionTime,System.TimeZoneInfo+TransitionTime)" />
+ <Member Name="op_Inequality(System.TimeZoneInfo+TransitionTime,System.TimeZoneInfo+TransitionTime)" />
+ <Member MemberType="Property" Name="Day" />
+ <Member MemberType="Property" Name="DayOfWeek" />
+ <Member MemberType="Property" Name="IsFixedDateRule" />
+ <Member MemberType="Property" Name="Month" />
+ <Member MemberType="Property" Name="TimeOfDay" />
+ <Member MemberType="Property" Name="Week" />
+ </Type>
+ <Type Name="System.TimeZoneNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ </Type>
+ <Type Name="System.Tuple">
+ <Member Name="Create&lt;T1&gt;(T1)" />
+ <Member Name="Create&lt;T1,T2&gt;(T1,T2)" />
+ <Member Name="Create&lt;T1,T2,T3&gt;(T1,T2,T3)" />
+ <Member Name="Create&lt;T1,T2,T3,T4&gt;(T1,T2,T3,T4)" />
+ <Member Name="Create&lt;T1,T2,T3,T4,T5&gt;(T1,T2,T3,T4,T5)" />
+ <Member Name="Create&lt;T1,T2,T3,T4,T5,T6&gt;(T1,T2,T3,T4,T5,T6)" />
+ <Member Name="Create&lt;T1,T2,T3,T4,T5,T6,T7&gt;(T1,T2,T3,T4,T5,T6,T7)" />
+ <Member Name="Create&lt;T1,T2,T3,T4,T5,T6,T7,T8&gt;(T1,T2,T3,T4,T5,T6,T7,T8)" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1&gt;">
+ <Member Name="#ctor(T1)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2&gt;">
+ <Member Name="#ctor(T1,T2)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3&gt;">
+ <Member Name="#ctor(T1,T2,T3)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3,T4&gt;">
+ <Member Name="#ctor(T1,T2,T3,T4)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="get_Item4" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ <Member MemberType="Property" Name="Item4" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3,T4,T5&gt;">
+ <Member Name="#ctor(T1,T2,T3,T4,T5)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="get_Item4" />
+ <Member Name="get_Item5" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ <Member MemberType="Property" Name="Item4" />
+ <Member MemberType="Property" Name="Item5" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3,T4,T5,T6&gt;">
+ <Member Name="#ctor(T1,T2,T3,T4,T5,T6)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="get_Item4" />
+ <Member Name="get_Item5" />
+ <Member Name="get_Item6" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ <Member MemberType="Property" Name="Item4" />
+ <Member MemberType="Property" Name="Item5" />
+ <Member MemberType="Property" Name="Item6" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3,T4,T5,T6,T7&gt;">
+ <Member Name="#ctor(T1,T2,T3,T4,T5,T6,T7)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="get_Item4" />
+ <Member Name="get_Item5" />
+ <Member Name="get_Item6" />
+ <Member Name="get_Item7" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ <Member MemberType="Property" Name="Item4" />
+ <Member MemberType="Property" Name="Item5" />
+ <Member MemberType="Property" Name="Item6" />
+ <Member MemberType="Property" Name="Item7" />
+ </Type>
+ <Type Name="System.Tuple&lt;T1,T2,T3,T4,T5,T6,T7,TRest&gt;">
+ <Member Name="#ctor(T1,T2,T3,T4,T5,T6,T7,TRest)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Item1" />
+ <Member Name="get_Item2" />
+ <Member Name="get_Item3" />
+ <Member Name="get_Item4" />
+ <Member Name="get_Item5" />
+ <Member Name="get_Item6" />
+ <Member Name="get_Item7" />
+ <Member Name="get_Rest" />
+ <Member Name="GetHashCode" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Item1" />
+ <Member MemberType="Property" Name="Item2" />
+ <Member MemberType="Property" Name="Item3" />
+ <Member MemberType="Property" Name="Item4" />
+ <Member MemberType="Property" Name="Item5" />
+ <Member MemberType="Property" Name="Item6" />
+ <Member MemberType="Property" Name="Item7" />
+ <Member MemberType="Property" Name="Rest" />
+ </Type>
+ <Type Name="System.Type">
+ <Member Name="#ctor" />
+ <Member Name="op_Equality(System.Type,System.Type)" />
+ <Member Name="op_Inequality(System.Type,System.Type)" />
+ <Member MemberType="Field" Name="Delimiter" />
+ <Member MemberType="Field" Name="EmptyTypes" />
+ <Member MemberType="Field" Name="FilterAttribute" />
+ <Member MemberType="Field" Name="FilterName" />
+ <Member MemberType="Field" Name="FilterNameIgnoreCase" />
+ <Member MemberType="Field" Name="Missing" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Type)" />
+ <Member Name="FindMembers(System.Reflection.MemberTypes,System.Reflection.BindingFlags,System.Reflection.MemberFilter,System.Object)" />
+ <Member Name="get_Assembly" />
+ <Member Name="get_AssemblyQualifiedName" />
+ <Member Name="get_Attributes" />
+ <Member Name="get_BaseType" />
+ <Member Name="get_ContainsGenericParameters" />
+ <Member Name="get_DeclaringType" />
+ <Member Name="get_DeclaringMethod" />
+ <Member Name="get_DefaultBinder" />
+ <Member Name="get_FullName" />
+ <Member Name="get_GenericParameterAttributes" />
+ <Member Name="get_GenericParameterPosition" />
+ <Member Name="get_GenericTypeArguments" />
+ <Member Name="get_GUID" />
+ <Member Name="get_HasElementType" />
+ <Member Name="get_IsAbstract" />
+ <Member Name="get_IsAnsiClass" />
+ <Member Name="get_IsArray" />
+ <Member Name="get_IsAutoClass" />
+ <Member Name="get_IsAutoLayout" />
+ <Member Name="get_IsByRef" />
+ <Member Name="get_IsConstructedGenericType" />
+ <Member Name="get_IsClass" />
+ <Member Name="get_IsCOMObject" />
+ <Member Name="get_IsEnum" />
+ <Member Name="get_IsExplicitLayout" />
+ <Member Name="get_IsGenericParameter" />
+ <Member Name="get_IsGenericType" />
+ <Member Name="get_IsGenericTypeDefinition" />
+ <Member Name="get_IsImport" />
+ <Member Name="get_IsInterface" />
+ <Member Name="get_IsLayoutSequential" />
+ <Member Name="get_IsMarshalByRef" />
+ <Member Name="get_IsNested" />
+ <Member Name="get_IsNestedAssembly" />
+ <Member Name="get_IsNestedFamANDAssem" />
+ <Member Name="get_IsNestedFamily" />
+ <Member Name="get_IsNestedFamORAssem" />
+ <Member Name="get_IsNestedPrivate" />
+ <Member Name="get_IsNestedPublic" />
+ <Member Name="get_IsNotPublic" />
+ <Member Name="get_IsPointer" />
+ <Member Name="get_IsPrimitive" />
+ <Member Name="get_IsPublic" />
+ <Member Name="get_IsSealed" />
+ <Member Name="get_IsSerializable" />
+ <Member Name="get_IsSpecialName" />
+ <Member Name="get_IsUnicodeClass" />
+ <Member Name="get_IsValueType" />
+ <Member Name="get_IsVisible" />
+ <Member Name="get_MemberType" />
+ <Member Name="get_Module" />
+ <Member Name="get_Namespace" />
+ <Member Name="get_ReflectedType" />
+ <Member Name="get_TypeHandle" />
+ <Member Name="get_UnderlyingSystemType" />
+ <Member Name="GetArrayRank" />
+ <Member Name="GetAttributeFlagsImpl" />
+ <Member Name="GetConstructor(System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructor(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructor(System.Type[])" />
+ <Member Name="GetConstructorImpl(System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetConstructors" />
+ <Member Name="GetConstructors(System.Reflection.BindingFlags)" />
+ <Member Name="GetDefaultMembers" />
+ <Member Name="GetElementType" />
+ <Member Name="GetEvent(System.String)" />
+ <Member Name="GetEvent(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetEvents" />
+ <Member Name="GetEvents(System.Reflection.BindingFlags)" />
+ <Member Name="GetField(System.String)" />
+ <Member Name="GetField(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetFields" />
+ <Member Name="GetFields(System.Reflection.BindingFlags)" />
+ <Member Name="GetGenericArguments" />
+ <Member Name="GetGenericParameterConstraints" />
+ <Member Name="GetGenericTypeDefinition" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetInterface(System.String,System.Boolean)" />
+ <Member Name="GetInterfaceMap(System.Type)" />
+ <Member Name="GetInterfaces" />
+ <Member Name="GetMember(System.String)" />
+ <Member Name="GetMember(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetMember(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags)" />
+ <Member Name="GetMembers" />
+ <Member Name="GetMembers(System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.String)" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethod(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethod(System.String,System.Type[])" />
+ <Member Name="GetMethod(System.String,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethodImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetMethods" />
+ <Member Name="GetMethods(System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedType(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetNestedTypes(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperties" />
+ <Member Name="GetProperties(System.Reflection.BindingFlags)" />
+ <Member Name="GetProperty(System.String)" />
+ <Member Name="GetProperty(System.String,System.Reflection.BindingFlags)" />
+ <Member Name="GetProperty(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetProperty(System.String,System.Type)" />
+ <Member Name="GetProperty(System.String,System.Type,System.Type[])" />
+ <Member Name="GetProperty(System.String,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetPropertyImpl(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Type,System.Type[],System.Reflection.ParameterModifier[])" />
+ <Member Name="GetType" />
+ <Member Name="GetType(System.String)" />
+ <Member Name="GetType(System.String,System.Boolean)" />
+ <Member Name="GetType(System.String,System.Boolean,System.Boolean)" />
+ <Member Name="GetTypeArray(System.Object[])" />
+ <Member Name="GetTypeCode(System.Type)" />
+ <Member Name="GetTypeCodeImpl" />
+ <Member Name="GetTypeFromCLSID(System.Guid)" />
+ <Member Name="GetTypeFromCLSID(System.Guid,System.Boolean)" />
+ <Member Name="GetTypeFromCLSID(System.Guid,System.String)" />
+ <Member Name="GetTypeFromCLSID(System.Guid,System.String,System.Boolean)" />
+ <Member Name="GetTypeFromHandle(System.RuntimeTypeHandle)" />
+ <Member Name="GetTypeFromProgID(System.String)" />
+ <Member Name="GetTypeFromProgID(System.String,System.Boolean)" />
+ <Member Name="GetTypeFromProgID(System.String,System.String)" />
+ <Member Name="GetTypeFromProgID(System.String,System.String,System.Boolean)" />
+ <Member Name="GetTypeHandle(System.Object)" />
+ <Member Name="HasElementTypeImpl" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[])" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Globalization.CultureInfo)" />
+ <Member Name="InvokeMember(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Object,System.Object[],System.Reflection.ParameterModifier[],System.Globalization.CultureInfo,System.String[])" />
+ <Member Name="IsArrayImpl" />
+ <Member Name="IsAssignableFrom(System.Type)" />
+ <Member Name="IsByRefImpl" />
+ <Member Name="IsCOMObjectImpl" />
+ <Member Name="IsInstanceOfType(System.Object)" />
+ <Member Name="IsMarshalByRefImpl" />
+ <Member Name="IsPointerImpl" />
+ <Member Name="IsPrimitiveImpl" />
+ <Member Name="IsSubclassOf(System.Type)" />
+ <Member Name="IsEquivalentTo(System.Type)" />
+ <Member Name="IsValueTypeImpl" />
+ <Member Name="MakeArrayType" />
+ <Member Name="MakeArrayType(System.Int32)" />
+ <Member Name="MakeByRefType" />
+ <Member Name="MakeGenericType(System.Type[])" />
+ <Member Name="MakePointerType" />
+ <Member Name="ReflectionOnlyGetType(System.String,System.Boolean,System.Boolean)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Assembly" />
+ <Member MemberType="Property" Name="AssemblyQualifiedName" />
+ <Member MemberType="Property" Name="Attributes" />
+ <Member MemberType="Property" Name="BaseType" />
+ <Member MemberType="Property" Name="ContainsGenericParameters" />
+ <Member MemberType="Property" Name="DeclaringType" />
+ <Member MemberType="Property" Name="DeclaringMethod" />
+ <Member MemberType="Property" Name="DefaultBinder" />
+ <Member MemberType="Property" Name="FullName" />
+ <Member MemberType="Property" Name="GenericParameterAttributes" />
+ <Member MemberType="Property" Name="GenericParameterPosition" />
+ <Member MemberType="Property" Name="GenericTypeArguments" />
+ <Member MemberType="Property" Name="GUID" />
+ <Member MemberType="Property" Name="HasElementType" />
+ <Member MemberType="Property" Name="IsAbstract" />
+ <Member MemberType="Property" Name="IsAnsiClass" />
+ <Member MemberType="Property" Name="IsArray" />
+ <Member MemberType="Property" Name="IsAutoClass" />
+ <Member MemberType="Property" Name="IsAutoLayout" />
+ <Member MemberType="Property" Name="IsByRef" />
+ <Member MemberType="Property" Name="IsConstructedGenericType" />
+ <Member MemberType="Property" Name="IsClass" />
+ <Member MemberType="Property" Name="IsCOMObject" />
+ <Member MemberType="Property" Name="IsEnum" />
+ <Member MemberType="Property" Name="IsExplicitLayout" />
+ <Member MemberType="Property" Name="IsGenericParameter" />
+ <Member MemberType="Property" Name="IsGenericType" />
+ <Member MemberType="Property" Name="IsGenericTypeDefinition" />
+ <Member MemberType="Property" Name="IsImport" />
+ <Member MemberType="Property" Name="IsInterface" />
+ <Member MemberType="Property" Name="IsLayoutSequential" />
+ <Member MemberType="Property" Name="IsMarshalByRef" />
+ <Member MemberType="Property" Name="IsNested" />
+ <Member MemberType="Property" Name="IsNestedAssembly" />
+ <Member MemberType="Property" Name="IsNestedFamANDAssem" />
+ <Member MemberType="Property" Name="IsNestedFamily" />
+ <Member MemberType="Property" Name="IsNestedFamORAssem" />
+ <Member MemberType="Property" Name="IsNestedPrivate" />
+ <Member MemberType="Property" Name="IsNestedPublic" />
+ <Member MemberType="Property" Name="IsNotPublic" />
+ <Member MemberType="Property" Name="IsPointer" />
+ <Member MemberType="Property" Name="IsPrimitive" />
+ <Member MemberType="Property" Name="IsPublic" />
+ <Member MemberType="Property" Name="IsSealed" />
+ <Member MemberType="Property" Name="IsSerializable" />
+ <Member MemberType="Property" Name="IsSpecialName" />
+ <Member MemberType="Property" Name="IsUnicodeClass" />
+ <Member MemberType="Property" Name="IsValueType" />
+ <Member MemberType="Property" Name="IsVisible" />
+ <Member MemberType="Property" Name="MemberType" />
+ <Member MemberType="Property" Name="Module" />
+ <Member MemberType="Property" Name="Namespace" />
+ <Member MemberType="Property" Name="ReflectedType" />
+ <Member MemberType="Property" Name="TypeHandle" />
+ <Member MemberType="Property" Name="UnderlyingSystemType" />
+ <Member Name="GetEnumName(System.Object)" />
+ <Member Name="GetEnumNames" />
+ <Member Name="GetEnumUnderlyingType" />
+ <Member Name="GetEnumValues" />
+ <Member Name="GetInterface(System.String)" />
+ <Member Name="GetNestedType(System.String)" />
+ <Member Name="GetNestedTypes" />
+ <Member Name="GetProperty(System.String,System.Type[])" />
+ <Member Name="IsEnumDefined(System.Object)" />
+ <Member Name="get_StructLayoutAttribute" />
+ <Member Name="get_TypeInitializer" />
+ <Member Name="FindInterfaces(System.Reflection.TypeFilter,System.Object)" />
+ <Member MemberType="Property" Name="TypeInitializer" />
+ <Member MemberType="Property" Name="StructLayoutAttribute" />
+ </Type>
+ <Type Name="System.TypeAccessException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.TypeCode">
+ <Member MemberType="Field" Name="Boolean" />
+ <Member MemberType="Field" Name="Byte" />
+ <Member MemberType="Field" Name="Char" />
+ <Member MemberType="Field" Name="DateTime" />
+ <Member MemberType="Field" Name="DBNull" />
+ <Member MemberType="Field" Name="Decimal" />
+ <Member MemberType="Field" Name="Double" />
+ <Member MemberType="Field" Name="Empty" />
+ <Member MemberType="Field" Name="Int16" />
+ <Member MemberType="Field" Name="Int32" />
+ <Member MemberType="Field" Name="Int64" />
+ <Member MemberType="Field" Name="Object" />
+ <Member MemberType="Field" Name="SByte" />
+ <Member MemberType="Field" Name="Single" />
+ <Member MemberType="Field" Name="String" />
+ <Member MemberType="Field" Name="UInt16" />
+ <Member MemberType="Field" Name="UInt32" />
+ <Member MemberType="Field" Name="UInt64" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.TypeInitializationException" >
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_TypeName" />
+ <Member MemberType="Property" Name="TypeName" />
+ </Type>
+ <Type Name="System.TypedReference" />
+ <Type Name="System.TypeLoadException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.String,System.String,System.String,System.Int32)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_TypeName" />
+ <Member MemberType="Property" Name="TypeName" />
+ </Type>
+ <Type Name="System.TypeUnloadedException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ </Type>
+ <Type Name="System.UInt16">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.UInt16)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.UInt16)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.UInt16@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt16@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.UInt32">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.UInt32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.UInt32)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.UInt32@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt32@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.UInt64">
+ <Member MemberType="Field" Name="MaxValue" />
+ <Member MemberType="Field" Name="MinValue" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.UInt64)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.UInt64)" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetTypeCode" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles)" />
+ <Member Name="Parse(System.String,System.Globalization.NumberStyles,System.IFormatProvider)" />
+ <Member Name="Parse(System.String,System.IFormatProvider)" />
+ <Member Name="TryParse(System.String,System.UInt64@)" />
+ <Member Name="TryParse(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt64@)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.IFormatProvider)" />
+ <Member Name="ToString(System.String)" />
+ <Member Name="ToString(System.String,System.IFormatProvider)" />
+ </Type>
+ <Type Name="System.UIntPtr">
+ <Member MemberType="Field" Name="Zero" />
+ <Member Name="#ctor(System.UInt32)" />
+ <Member Name="#ctor(System.UInt64)" />
+ <Member Name="#ctor(System.Void*)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="Add(System.UIntPtr,System.Int32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="get_Size" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Addition(System.UIntPtr,System.Int32)" />
+ <Member Name="op_Equality(System.UIntPtr,System.UIntPtr)" />
+ <Member Name="op_Explicit(System.UInt32)" ReturnType="System.UIntPtr" />
+ <Member Name="op_Explicit(System.UInt64)" ReturnType="System.UIntPtr" />
+ <Member Name="op_Explicit(System.UIntPtr)" ReturnType="System.UInt32" />
+ <Member Name="op_Explicit(System.UIntPtr)" ReturnType="System.UInt64" />
+ <Member Name="op_Explicit(System.UIntPtr)" ReturnType="System.Void*" />
+ <Member Name="op_Explicit(System.Void*)" ReturnType="System.UIntPtr" />
+ <Member Name="op_Inequality(System.UIntPtr,System.UIntPtr)" />
+ <Member Name="op_Subtraction(System.UIntPtr,System.Int32)" />
+ <Member Name="Subtract(System.UIntPtr,System.Int32)" />
+ <Member Name="ToPointer" />
+ <Member Name="ToString" />
+ <Member Name="ToUInt32" />
+ <Member Name="ToUInt64" />
+ <Member MemberType="Property" Name="Size" />
+ </Type>
+ <Type Name="System.UnauthorizedAccessException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.UnhandledExceptionEventArgs">
+ <Member Name="#ctor(System.Object,System.Boolean)" />
+ <Member Name="get_ExceptionObject" />
+ <Member Name="get_IsTerminating" />
+ <Member MemberType="Property" Name="ExceptionObject" />
+ <Member MemberType="Property" Name="IsTerminating" />
+ </Type>
+ <Type Name="System.UnhandledExceptionEventHandler">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,System.UnhandledExceptionEventArgs,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,System.UnhandledExceptionEventArgs)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.UnitySerializationHolder">
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ValueType">
+ <Member Name="#ctor" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ </Type>
+ <Type Name="System.Variant" Condition="FEATURE_COMINTEROP">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_objref" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_data1" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_data2" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_flags" />
+ <Member Status="ImplRoot" Name="MarshalHelperConvertObjectToVariant(System.Object,System.Variant@)" />
+ <Member Status="ImplRoot" Name="MarshalHelperCastVariant(System.Object,System.Int32,System.Variant@)" />
+ <Member Status="ImplRoot" Name="MarshalHelperConvertVariantToObject(System.Variant@)" />
+ </Type>
+ <Type Name="System.Version">
+ <Member Name="#ctor(System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor" />
+ <Member Name="Clone" />
+ <Member Name="CompareTo(System.Object)" />
+ <Member Name="CompareTo(System.Version)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Version)" />
+ <Member Name="get_Build" />
+ <Member Name="get_Major" />
+ <Member Name="get_MajorRevision" />
+ <Member Name="get_Minor" />
+ <Member Name="get_MinorRevision" />
+ <Member Name="get_Revision" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Version,System.Version)" />
+ <Member Name="op_GreaterThan(System.Version,System.Version)" />
+ <Member Name="op_GreaterThanOrEqual(System.Version,System.Version)" />
+ <Member Name="op_Inequality(System.Version,System.Version)" />
+ <Member Name="op_LessThan(System.Version,System.Version)" />
+ <Member Name="op_LessThanOrEqual(System.Version,System.Version)" />
+ <Member Name="Parse(System.String)" />
+ <Member Name="ToString" />
+ <Member Name="ToString(System.Int32)" />
+ <Member Name="TryParse(System.String,System.Version@)" />
+ <Member MemberType="Property" Name="Build" />
+ <Member MemberType="Property" Name="Major" />
+ <Member MemberType="Property" Name="MajorRevision" />
+ <Member MemberType="Property" Name="Minor" />
+ <Member MemberType="Property" Name="MinorRevision" />
+ <Member MemberType="Property" Name="Revision" />
+ </Type>
+ <Type Name="System.Void" />
+ <Type Name="System.WeakReference">
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="#ctor(System.Object,System.Boolean)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="#ctor" />
+ <Member Name="get_IsAlive" />
+ <Member Name="get_Target" />
+ <Member Name="get_TrackResurrection" />
+ <Member Name="set_Target(System.Object)" />
+ <Member MemberType="Property" Name="IsAlive" />
+ <Member MemberType="Property" Name="Target" />
+ <Member MemberType="Property" Name="TrackResurrection" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.WeakReference&lt;T&gt;">
+ <Member Name="#ctor(T)" />
+ <Member Name="#ctor(T,System.Boolean)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="SetTarget(T)" />
+ <Member Name="TryGetTarget(T@)" />
+ <Member Status="ImplRoot" Name="Finalize" />
+ </Type>
+<!-- SMOSIER ADDED API ROOTS FOR C# -->
+ <Type Name="System.Runtime.CompilerServices.RuntimeCompatibilityAttribute">
+ <Member MemberType="Property" Name="WrapNonExceptionThrows" />
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.AsyncStateMachineAttribute">
+ <Member Name="#ctor(System.Type)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IteratorStateMachineAttribute">
+ <Member Name="#ctor(System.Type)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.StateMachineAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="get_StateMachineType" />
+ <Member MemberType="Property" Name="StateMachineType" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CallerFilePathAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CallerLineNumberAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CallerMemberNameAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.CompilerGeneratedAttribute">
+ <Member Name="#ctor" />
+ </Type>
+<!-- SMOSIER ADDED API ROOTS FOR our build process -->
+ <Type Name="System.Runtime.InteropServices.ComVisibleAttribute">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Name="System.Reflection.AssemblyFileVersionAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="get_Version" />
+ <Member MemberType="Property" Name="Version" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.Permissions.HostProtectionAttribute">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Security.Permissions.SecurityAction)" />
+ <Member Name="get_ExternalProcessMgmt" />
+ <Member Name="get_ExternalThreading" />
+ <Member Name="get_MayLeakOnAbort" />
+ <Member Name="get_Resources" />
+ <Member Name="get_SecurityInfrastructure" />
+ <Member Name="get_SelfAffectingProcessMgmt" />
+ <Member Name="get_SelfAffectingThreading" />
+ <Member Name="get_SharedState" />
+ <Member Name="get_Synchronization" />
+ <Member Name="get_UI" />
+ <Member Name="set_ExternalProcessMgmt(System.Boolean)" />
+ <Member Name="set_ExternalThreading(System.Boolean)" />
+ <Member Name="set_MayLeakOnAbort(System.Boolean)" />
+ <Member Name="set_Resources(System.Security.Permissions.HostProtectionResource)" />
+ <Member Name="set_SecurityInfrastructure(System.Boolean)" />
+ <Member Name="set_SelfAffectingProcessMgmt(System.Boolean)" />
+ <Member Name="set_SelfAffectingThreading(System.Boolean)" />
+ <Member Name="set_SharedState(System.Boolean)" />
+ <Member Name="set_Synchronization(System.Boolean)" />
+ <Member Name="set_UI(System.Boolean)" />
+ <Member MemberType="Property" Name="ExternalProcessMgmt" />
+ <Member MemberType="Property" Name="ExternalThreading" />
+ <Member MemberType="Property" Name="MayLeakOnAbort" />
+ <Member MemberType="Property" Name="Resources" />
+ <Member MemberType="Property" Name="SecurityInfrastructure" />
+ <Member MemberType="Property" Name="SelfAffectingProcessMgmt" />
+ <Member MemberType="Property" Name="SelfAffectingThreading" />
+ <Member MemberType="Property" Name="SharedState" />
+ <Member MemberType="Property" Name="Synchronization" />
+ <Member MemberType="Property" Name="UI" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.Permissions.HostProtectionResource" />
+ <Type Name="System.IO.BinaryReader">
+ <Member Name="#ctor(System.IO.Stream)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Boolean)" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="FillBuffer(System.Int32)" />
+ <Member Name="get_BaseStream" />
+ <Member Name="PeekChar" />
+ <Member Name="Read" />
+ <Member Name="Read7BitEncodedInt" />
+ <Member Name="Read(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="Read(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBoolean" />
+ <Member Name="ReadByte" />
+ <Member Name="ReadBytes(System.Int32)" />
+ <Member Name="ReadChar" />
+ <Member Name="ReadChars(System.Int32)" />
+ <Member Name="ReadDecimal" />
+ <Member Name="ReadDouble" />
+ <Member Name="ReadInt16" />
+ <Member Name="ReadInt32" />
+ <Member Name="ReadInt64" />
+ <Member Name="ReadSByte" />
+ <Member Name="ReadSingle" />
+ <Member Name="ReadString" />
+ <Member Name="ReadUInt16" />
+ <Member Name="ReadUInt32" />
+ <Member Name="ReadUInt64" />
+ <Member MemberType="Property" Name="BaseStream" />
+ </Type>
+ <Type Name="System.IO.BinaryWriter">
+ <Member MemberType="Field" Name="Null" />
+ <Member MemberType="Field" Name="OutStream" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.IO.Stream)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Boolean)" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Flush" />
+ <Member Name="get_BaseStream" />
+ <Member Name="Seek(System.Int32,System.IO.SeekOrigin)" />
+ <Member Name="Write(System.Boolean)" />
+ <Member Name="Write(System.Byte)" />
+ <Member Name="Write(System.Byte[])" />
+ <Member Name="Write(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="Write(System.Char)" />
+ <Member Name="Write(System.Char[])" />
+ <Member Name="Write(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Write(System.Decimal)" />
+ <Member Name="Write(System.Double)" />
+ <Member Name="Write(System.Int16)" />
+ <Member Name="Write(System.Int32)" />
+ <Member Name="Write(System.Int64)" />
+ <Member Name="Write(System.SByte)" />
+ <Member Name="Write(System.Single)" />
+ <Member Name="Write(System.String)" />
+ <Member Name="Write(System.UInt16)" />
+ <Member Name="Write(System.UInt32)" />
+ <Member Name="Write(System.UInt64)" />
+ <Member Name="Write7BitEncodedInt(System.Int32)" />
+ <Member MemberType="Property" Name="BaseStream" />
+ </Type>
+ <Type Name="System.IO.DirectoryNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.IO.EndOfStreamException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.IO.FileNotFoundException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member Name="#ctor(System.String,System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_FileName" />
+ <Member MemberType="Property" Name="FileName" />
+ <Member Status="ImplRoot" Name="#ctor(System.String,System.String,System.Int32)" />
+ </Type>
+ <Type Name="System.IO.IOException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.String,System.Int32)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.IO.MemoryStream">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Byte[])" />
+ <Member Name="#ctor(System.Byte[],System.Boolean)" />
+ <Member Name="#ctor(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Byte[],System.Int32,System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.Byte[],System.Int32,System.Int32,System.Boolean,System.Boolean)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="CopyToAsync(System.IO.Stream,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Flush" />
+ <Member Name="FlushAsync(System.Threading.CancellationToken)" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanSeek" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_Capacity" />
+ <Member Name="get_Length" />
+ <Member Name="get_Position" />
+ <Member Name="GetBuffer" />
+ <Member Name="TryGetBuffer(System.ArraySegment&lt;System.Byte&gt;@)" />
+ <Member Name="Read(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="ReadByte" />
+ <Member Name="Seek(System.Int64,System.IO.SeekOrigin)" />
+ <Member Name="set_Capacity(System.Int32)" />
+ <Member Name="set_Position(System.Int64)" />
+ <Member Name="SetLength(System.Int64)" />
+ <Member Name="ToArray" />
+ <Member Name="Write(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="WriteByte(System.Byte)" />
+ <Member Name="WriteTo(System.IO.Stream)" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanSeek" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="Capacity" />
+ <Member MemberType="Property" Name="Length" />
+ <Member MemberType="Property" Name="Position" />
+ <Member Status="ApiFxInternal" Name="InternalGetOriginAndLength(System.Int32@,System.Int32@)" Condition="FEATURE_COMINTEROP" />
+ </Type>
+ <Type Name="System.IO.Path">
+ <Member MemberType="Field" Name="AltDirectorySeparatorChar" />
+ <Member MemberType="Field" Name="DirectorySeparatorChar" />
+ <Member MemberType="Field" Name="PathSeparator" />
+ <Member MemberType="Field" Name="VolumeSeparatorChar" />
+ <Member Name="ChangeExtension(System.String,System.String)" />
+ <Member Name="Combine(System.String,System.String)" />
+ <Member Name="Combine(System.String,System.String,System.String)" />
+ <Member Name="Combine(System.String[])" />
+ <Member Name="GetDirectoryName(System.String)" />
+ <Member Name="GetExtension(System.String)" />
+ <Member Name="GetFileName(System.String)" />
+ <Member Name="GetFileNameWithoutExtension(System.String)" />
+ <Member Name="GetFullPath(System.String)" />
+ <Member Name="GetInvalidPathChars" />
+ <Member Name="GetInvalidFileNameChars" />
+ <Member Name="GetPathRoot(System.String)" />
+ <Member Name="HasExtension(System.String)" />
+ <Member Name="IsPathRooted(System.String)" />
+ <Member Name="GetRandomFileName" />
+ <Member Name="GetTempFileName" />
+ <Member Name="GetTempPath" />
+ </Type>
+ <Type Name="System.IO.PathTooLongException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.IO.SearchOption" Condition="FEATURE_LEGACYSURFACE">
+ <Member MemberType="Field" Name="TopDirectoryOnly" />
+ <Member MemberType="Field" Name="AllDirectories" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.IO.SeekOrigin" Condition="FEATURE_LEGACYSURFACE">
+ <Member MemberType="Field" Name="Begin" />
+ <Member MemberType="Field" Name="Current" />
+ <Member MemberType="Field" Name="End" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.IO.Stream">
+ <Member MemberType="Field" Name="Null" />
+ <Member Name="#ctor" />
+ <Member Name="BeginRead(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)" />
+ <Member Name="BeginWrite(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object)" />
+ <Member Name="CopyTo(System.IO.Stream)" />
+ <Member Name="CopyTo(System.IO.Stream,System.Int32)" />
+ <Member Name="CopyToAsync(System.IO.Stream)" />
+ <Member Name="CopyToAsync(System.IO.Stream,System.Int32)" />
+ <Member Name="CopyToAsync(System.IO.Stream,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="Close" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="EndRead(System.IAsyncResult)" />
+ <Member Name="EndWrite(System.IAsyncResult)" />
+ <Member Name="Flush" />
+ <Member Name="FlushAsync" />
+ <Member Name="FlushAsync(System.Threading.CancellationToken)" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanSeek" />
+ <Member Name="get_CanTimeout" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_Length" />
+ <Member Name="get_Position" />
+ <Member Name="get_ReadTimeout" />
+ <Member Name="get_WriteTimeout" />
+ <Member Name="Read(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ReadByte" />
+ <Member Name="ReadAsync(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ReadAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="Seek(System.Int64,System.IO.SeekOrigin)" />
+ <Member Name="set_Position(System.Int64)" />
+ <Member Name="set_ReadTimeout(System.Int32)" />
+ <Member Name="set_WriteTimeout(System.Int32)" />
+ <Member Name="SetLength(System.Int64)" />
+ <Member Name="Write(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="WriteByte(System.Byte)" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanSeek" />
+ <Member MemberType="Property" Name="CanTimeout" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="Length" />
+ <Member MemberType="Property" Name="Position" />
+ <Member MemberType="Property" Name="ReadTimeout" />
+ <Member MemberType="Property" Name="WriteTimeout" />
+ </Type>
+ <Type Name="System.IO.StreamReader">
+ <Member MemberType="Field" Name="Null" />
+ <Member Name="#ctor(System.IO.Stream)" />
+ <Member Name="#ctor(System.IO.Stream,System.Boolean)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Boolean)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Boolean,System.Int32)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Boolean,System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Text.Encoding)" />
+ <Member Name="#ctor(System.String,System.Text.Encoding,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Text.Encoding,System.Boolean,System.Int32)" />
+ <Member Name="Close" />
+ <Member Name="DiscardBufferedData" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="get_BaseStream" />
+ <Member Name="get_CurrentEncoding" />
+ <Member Name="get_EndOfStream" />
+ <Member Name="Peek" />
+ <Member Name="Read" />
+ <Member Name="Read(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBlock(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBlockAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadLine" />
+ <Member Name="ReadLineAsync" />
+ <Member Name="ReadToEnd" />
+ <Member Name="ReadToEndAsync" />
+ <Member MemberType="Property" Name="BaseStream" />
+ <Member MemberType="Property" Name="CurrentEncoding" />
+ <Member MemberType="Property" Name="EndOfStream" />
+ </Type>
+ <Type Name="System.IO.StreamWriter">
+ <Member MemberType="Field" Name="Null" />
+ <Member Name="#ctor(System.IO.Stream)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Int32)" />
+ <Member Name="#ctor(System.IO.Stream,System.Text.Encoding,System.Int32,System.Boolean)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.Boolean,System.Text.Encoding)" />
+ <Member Name="#ctor(System.String,System.Boolean,System.Text.Encoding,System.Int32)" />
+ <Member Name="Close" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Flush" />
+ <Member Name="FlushAsync" />
+ <Member Name="get_AutoFlush" />
+ <Member Name="get_BaseStream" />
+ <Member Name="get_Encoding" />
+ <Member Name="set_AutoFlush(System.Boolean)" />
+ <Member Name="Write(System.Char)" />
+ <Member Name="Write(System.Char[])" />
+ <Member Name="Write(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Write(System.String)" />
+ <Member Name="WriteAsync(System.Char)" />
+ <Member Name="WriteAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.String)" />
+ <Member Name="WriteLineAsync" />
+ <Member Name="WriteLineAsync(System.Char)" />
+ <Member Name="WriteLineAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteLineAsync(System.String)" />
+ <Member MemberType="Property" Name="AutoFlush" />
+ <Member MemberType="Property" Name="BaseStream" />
+ <Member MemberType="Property" Name="Encoding" />
+ </Type>
+ <Type Name="System.IO.StringReader">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="Close" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Peek" />
+ <Member Name="Read" />
+ <Member Name="Read(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBlockAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadLine" />
+ <Member Name="ReadLineAsync" />
+ <Member Name="ReadToEnd" />
+ <Member Name="ReadToEndAsync" />
+ </Type>
+ <Type Name="System.IO.StringWriter">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.IFormatProvider)" />
+ <Member Name="#ctor(System.Text.StringBuilder)" />
+ <Member Name="#ctor(System.Text.StringBuilder,System.IFormatProvider)" />
+ <Member Name="Close" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="FlushAsync" />
+ <Member Name="get_Encoding" />
+ <Member Name="GetStringBuilder" />
+ <Member Name="ToString" />
+ <Member Name="Write(System.Char)" />
+ <Member Name="Write(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Write(System.String)" />
+ <Member Name="WriteAsync(System.Char)" />
+ <Member Name="WriteAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.String)" />
+ <Member Name="WriteLineAsync(System.Char)" />
+ <Member Name="WriteLineAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteLineAsync(System.String)" />
+ <Member MemberType="Property" Name="Encoding" />
+ </Type>
+ <Type Name="System.IO.TextReader">
+ <Member MemberType="Field" Name="Null" />
+ <Member Name="#ctor" />
+ <Member Name="Close" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Peek" />
+ <Member Name="Read" />
+ <Member Name="Read(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBlock(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadBlockAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="ReadLine" />
+ <Member Name="ReadLineAsync" />
+ <Member Name="ReadToEnd" />
+ <Member Name="ReadToEndAsync" />
+ </Type>
+ <Type Name="System.IO.TextWriter">
+ <Member MemberType="Field" Name="CoreNewLine" />
+ <Member MemberType="Field" Name="Null" />
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.IFormatProvider)" />
+ <Member Name="Close" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Flush" />
+ <Member Name="FlushAsync" />
+ <Member Name="get_Encoding" />
+ <Member Name="get_FormatProvider" />
+ <Member Name="get_NewLine" />
+ <Member Name="set_NewLine(System.String)" />
+ <Member Name="Write(System.Boolean)" />
+ <Member Name="Write(System.Char)" />
+ <Member Name="Write(System.Char[])" />
+ <Member Name="Write(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="Write(System.Decimal)" />
+ <Member Name="Write(System.Double)" />
+ <Member Name="Write(System.Int32)" />
+ <Member Name="Write(System.Int64)" />
+ <Member Name="Write(System.Object)" />
+ <Member Name="Write(System.Single)" />
+ <Member Name="Write(System.String)" />
+ <Member Name="Write(System.String,System.Object)" />
+ <Member Name="Write(System.String,System.Object,System.Object)" />
+ <Member Name="Write(System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="Write(System.String,System.Object[])" />
+ <Member Name="Write(System.UInt32)" />
+ <Member Name="Write(System.UInt64)" />
+ <Member Name="WriteAsync(System.Char)" />
+ <Member Name="WriteAsync(System.Char[])" />
+ <Member Name="WriteAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteAsync(System.String)" />
+ <Member Name="WriteLine" />
+ <Member Name="WriteLine(System.Boolean)" />
+ <Member Name="WriteLine(System.Char)" />
+ <Member Name="WriteLine(System.Char[])" />
+ <Member Name="WriteLine(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteLine(System.Decimal)" />
+ <Member Name="WriteLine(System.Double)" />
+ <Member Name="WriteLine(System.Int32)" />
+ <Member Name="WriteLine(System.Int64)" />
+ <Member Name="WriteLine(System.Object)" />
+ <Member Name="WriteLine(System.Single)" />
+ <Member Name="WriteLine(System.String)" />
+ <Member Name="WriteLine(System.String,System.Object)" />
+ <Member Name="WriteLine(System.String,System.Object,System.Object)" />
+ <Member Name="WriteLine(System.String,System.Object,System.Object,System.Object)" />
+ <Member Name="WriteLine(System.String,System.Object[])" />
+ <Member Name="WriteLine(System.UInt32)" />
+ <Member Name="WriteLine(System.UInt64)" />
+ <Member Name="WriteLineAsync" />
+ <Member Name="WriteLineAsync(System.Char)" />
+ <Member Name="WriteLineAsync(System.Char[])" />
+ <Member Name="WriteLineAsync(System.Char[],System.Int32,System.Int32)" />
+ <Member Name="WriteLineAsync(System.String)" />
+ <Member MemberType="Property" Name="Encoding" />
+ <Member MemberType="Property" Name="FormatProvider" />
+ <Member MemberType="Property" Name="NewLine" />
+ </Type>
+ <Type Name="System.IO.UnmanagedMemoryAccessor">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_Capacity" />
+ <Member Name="get_IsOpen" />
+ <Member Name="Initialize(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="ReadBoolean(System.Int64)" />
+ <Member Name="ReadByte(System.Int64)" />
+ <Member Name="ReadChar(System.Int64)" />
+ <Member Name="ReadDecimal(System.Int64)" />
+ <Member Name="ReadDouble(System.Int64)" />
+ <Member Name="ReadInt16(System.Int64)" />
+ <Member Name="ReadInt32(System.Int64)" />
+ <Member Name="ReadInt64(System.Int64)" />
+ <Member Name="ReadSByte(System.Int64)" />
+ <Member Name="ReadSingle(System.Int64)" />
+ <Member Name="ReadUInt16(System.Int64)" />
+ <Member Name="ReadUInt32(System.Int64)" />
+ <Member Name="ReadUInt64(System.Int64)" />
+ <Member Name="Write(System.Int64,System.Boolean)" />
+ <Member Name="Write(System.Int64,System.Byte)" />
+ <Member Name="Write(System.Int64,System.Char)" />
+ <Member Name="Write(System.Int64,System.Decimal)" />
+ <Member Name="Write(System.Int64,System.Double)" />
+ <Member Name="Write(System.Int64,System.Int16)" />
+ <Member Name="Write(System.Int64,System.Int32)" />
+ <Member Name="Write(System.Int64,System.Int64)" />
+ <Member Name="Write(System.Int64,System.SByte)" />
+ <Member Name="Write(System.Int64,System.Single)" />
+ <Member Name="Write(System.Int64,System.UInt16)" />
+ <Member Name="Write(System.Int64,System.UInt32)" />
+ <Member Name="Write(System.Int64,System.UInt64)" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="Capacity" />
+ <Member MemberType="Property" Name="IsOpen" />
+ </Type>
+ <Type Name="System.IO.UnmanagedMemoryStream">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Byte*,System.Int64)" />
+ <Member Name="#ctor(System.Byte*,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64)" />
+ <Member Name="#ctor(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Flush" />
+ <Member Name="get_CanRead" />
+ <Member Name="get_CanSeek" />
+ <Member Name="get_CanWrite" />
+ <Member Name="get_Capacity" />
+ <Member Name="get_Length" />
+ <Member Name="get_Position" />
+ <Member Name="get_PositionPointer" />
+ <Member Name="Initialize(System.Byte*,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="Initialize(System.Runtime.InteropServices.SafeBuffer,System.Int64,System.Int64,System.IO.FileAccess)" />
+ <Member Name="Read(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="ReadByte" />
+ <Member Name="Seek(System.Int64,System.IO.SeekOrigin)" />
+ <Member Name="set_Position(System.Int64)" />
+ <Member Name="SetLength(System.Int64)" />
+ <Member Name="Write(System.Byte[],System.Int32,System.Int32)" />
+ <Member Name="WriteByte(System.Byte)" />
+ <Member MemberType="Property" Name="CanRead" />
+ <Member MemberType="Property" Name="CanSeek" />
+ <Member MemberType="Property" Name="CanWrite" />
+ <Member MemberType="Property" Name="Capacity" />
+ <Member MemberType="Property" Name="Length" />
+ <Member MemberType="Property" Name="Position" />
+ <Member MemberType="Property" Name="PositionPointer" />
+ </Type>
+ <Type Name="System.Security.Permissions.SecurityAttribute">
+ <Member Name="#ctor(System.Security.Permissions.SecurityAction)" />
+ <Member Name="get_Action" />
+ <Member Name="get_Unrestricted" />
+ <Member Name="set_Action(System.Security.Permissions.SecurityAction)" />
+ <Member Name="set_Unrestricted(System.Boolean)" />
+ <Member Name="FindSecurityAttributeTypeHandle(System.String)"/>
+ <Member MemberType="Property" Name="Action" />
+ <Member MemberType="Property" Name="Unrestricted" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.Contract" >
+ <Member MemberType="Event" Name="ContractFailed" />
+ <Member Name="Assert(System.Boolean)" />
+ <Member Name="Assert(System.Boolean,System.String)" />
+ <Member Name="Assume(System.Boolean)" />
+ <Member Name="Assume(System.Boolean,System.String)" />
+ <Member Name="EndContractBlock" />
+ <Member Name="Ensures(System.Boolean,System.String)" />
+ <Member Name="Ensures(System.Boolean)" />
+ <Member Name="EnsuresOnThrow&lt;TException&gt;(System.Boolean)" />
+ <Member Name="EnsuresOnThrow&lt;TException&gt;(System.Boolean,System.String)" />
+ <Member Name="Exists&lt;T&gt;(System.Collections.Generic.IEnumerable&lt;T&gt;,System.Predicate&lt;T&gt;)" />
+ <Member Name="Exists(System.Int32,System.Int32,System.Predicate&lt;System.Int32&gt;)" />
+ <Member Name="ForAll&lt;T&gt;(System.Collections.Generic.IEnumerable&lt;T&gt;,System.Predicate&lt;T&gt;)" />
+ <Member Name="ForAll(System.Int32,System.Int32,System.Predicate&lt;System.Int32&gt;)" />
+ <Member Name="Invariant(System.Boolean)" />
+ <Member Name="Invariant(System.Boolean,System.String)" />
+ <Member Name="OldValue&lt;T&gt;(T)" />
+ <Member Name="Requires(System.Boolean)" />
+ <Member Name="Requires(System.Boolean,System.String)" />
+ <Member Name="Requires&lt;TException&gt;(System.Boolean)" />
+ <Member Name="Requires&lt;TException&gt;(System.Boolean,System.String)" />
+ <Member Name="Result&lt;T&gt;" />
+ <Member Name="ValueAtReturn&lt;T&gt;(T@)" />
+ </Type>
+ <Type Name="System.Diagnostics.Contracts.ContractAbbreviatorAttribute" >
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Diagnostics.Contracts.ContractArgumentValidatorAttribute" >
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="Name" />
+ </Type>
+ <Type Name="System.Diagnostics.Contracts.ContractFailedEventArgs" >
+ <Member Name="#ctor(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.Exception)" />
+ <Member Name="get_Condition" />
+ <Member Name="get_FailureKind" />
+ <Member Name="get_Handled" />
+ <Member Name="get_Message" />
+ <Member Name="get_OriginalException" />
+ <Member Name="get_Unwind" />
+ <Member Name="SetHandled" />
+ <Member Name="SetUnwind" />
+ <Member MemberType="Property" Name="Condition" />
+ <Member MemberType="Property" Name="FailureKind" />
+ <Member MemberType="Property" Name="Handled" />
+ <Member MemberType="Property" Name="Message" />
+ <Member MemberType="Property" Name="OriginalException" />
+ <Member MemberType="Property" Name="Unwind" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractOptionAttribute" >
+ <Member Name="#ctor(System.String,System.String,System.Boolean)" />
+ <Member Name="#ctor(System.String,System.String,System.String)" />
+ <Member MemberType="Property" Name="Category" />
+ <Member MemberType="Property" Name="Setting" />
+ <Member MemberType="Property" Name="Enabled" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.PureAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractInvariantMethodAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractClassAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="TypeContainingContracts" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractClassForAttribute">
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="TypeContractsAreFor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.ContractVerificationAttribute">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Diagnostics.Contracts.Internal.ContractHelper">
+ <Member Name="RaiseContractFailedEvent(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.Exception)" />
+ <Member Name="TriggerFailure(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.String,System.Exception)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Diagnostics.Contracts.ContractException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Diagnostics.Contracts.ContractFailureKind,System.String,System.String,System.String,System.Exception)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Property" Name="Condition" />
+ <Member MemberType="Property" Name="Failure" />
+ <Member MemberType="Property" Name="Kind" />
+ <Member MemberType="Property" Name="UserMessage" />
+ </Type>
+ <Type Name="System.StringSplitOptions" />
+ <Type Status="ImplRoot" Name="System.__Canon" />
+ <Type Status="ImplRoot" Name="System.__ComObject" Condition="FEATURE_COMINTEROP">
+ <Member MemberType="Field" Name="m_ObjectToDataMap" />
+ <Member Name="ReleaseSelf" />
+ <Member Name="ReleaseAllData" />
+ <Member Name="GetEventProvider(System.RuntimeType)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.BCLDebug">
+ <Member Name="GetRegistryLoggingValues(System.Boolean@,System.Boolean@,System.Int32@,System.Boolean@,System.Boolean@,System.Boolean@)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Configuration.Assemblies.AssemblyHashAlgorithm" />
+ <Type Status="ImplRoot" Name="System.Configuration.Assemblies.AssemblyVersionCompatibility" />
+ <Type Status="ImplRoot" Name="System.CrossAppDomainMarshaledException">
+ <Member Name="#ctor(System.String,System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Currency">
+ <Member Status="ImplRoot" Name="#ctor(System.Decimal)" /> <!-- EE - il stubs -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Diagnostics.EditAndContinueHelper">
+ <Member MemberType="Field" Name="_objectReference" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Diagnostics.StackFrameHelper">
+ <Member Status="ImplRoot" Name="OnDeserialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerialized(System.Runtime.Serialization.StreamingContext)" />
+ <Member Status="ImplRoot" Name="OnSerializing(System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventAttribute">
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="get_EventId" />
+ <Member MemberType="Property" Name="ActivityOptions" />
+ <Member MemberType="Property" Name="Channel" />
+ <Member MemberType="Property" Name="Keywords" />
+ <Member MemberType="Property" Name="Level" />
+ <Member MemberType="Property" Name="Message" />
+ <Member MemberType="Property" Name="Opcode" />
+ <Member MemberType="Property" Name="Task" />
+ <Member MemberType="Property" Name="Version" />
+ <Member MemberType="Property" Name="Tags" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventActivityOptions">
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Detachable" />
+ <Member MemberType="Field" Name="Disable" />
+ <Member MemberType="Field" Name="Recursive" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventFieldFormat">
+ <Member MemberType="Field" Name="Boolean" />
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="Hexadecimal" />
+ <Member MemberType="Field" Name="HResult" />
+ <Member MemberType="Field" Name="Json" />
+ <Member MemberType="Field" Name="String" />
+ <Member MemberType="Field" Name="Xml" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventDescriptor">
+ <Member Name="#ctor(System.Int32,System.Byte,System.Byte,System.Int64)" />
+ <Member Name="#ctor(System.Int32,System.Byte,System.Byte,System.Byte,System.Byte,System.Int32,System.Int64)" />
+ <Member Name="get_EventId" />
+ <Member Name="get_Channel" />
+ <Member Name="get_Level" />
+ <Member Name="get_Opcode" />
+ <Member Name="get_Task" />
+ <Member Name="get_Version" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Diagnostics.Tracing.EventDescriptor)" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.EventChannel">
+ <Member MemberType="Field" Name="Admin" />
+ <Member MemberType="Field" Name="Analytic" />
+ <Member MemberType="Field" Name="Debug" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Operational" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventCommand">
+ <Member MemberType="Field" Name="Disable" />
+ <Member MemberType="Field" Name="Enable" />
+ <Member MemberType="Field" Name="SendManifest" />
+ <Member MemberType="Field" Name="Update" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventCommandEventArgs">
+ <Member Name="get_Arguments" />
+ <Member Name="get_Command" />
+ <Member Name="DisableEvent(System.Int32)" />
+ <Member Name="EnableEvent(System.Int32)" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventDataAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Level" />
+ <Member MemberType="Property" Name="Opcode" />
+ <Member MemberType="Property" Name="Keywords" />
+ <Member MemberType="Property" Name="Tags" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventKeywords">
+ <Member MemberType="Field" Name="AuditFailure" />
+ <Member MemberType="Field" Name="AuditSuccess" />
+ <Member MemberType="Field" Name="CorrelationHint" />
+ <Member MemberType="Field" Name="EventLogClassic" />
+ <Member MemberType="Field" Name="MicrosoftTelemetry" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="Sqm" />
+ <Member MemberType="Field" Name="WdiContext" />
+ <Member MemberType="Field" Name="WdiDiagnostic" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventLevel">
+ <Member MemberType="Field" Name="Critical" />
+ <Member MemberType="Field" Name="Error" />
+ <Member MemberType="Field" Name="Informational" />
+ <Member MemberType="Field" Name="LogAlways" />
+ <Member MemberType="Field" Name="Verbose" />
+ <Member MemberType="Field" Name="Warning" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventListener">
+ <Member Name="#ctor" />
+ <Member Name="DisableEvents(System.Diagnostics.Tracing.EventSource)" />
+ <Member Name="Dispose" />
+ <Member Name="EnableEvents(System.Diagnostics.Tracing.EventSource,System.Diagnostics.Tracing.EventLevel)" />
+ <Member Name="EnableEvents(System.Diagnostics.Tracing.EventSource,System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords)" />
+ <Member Name="EnableEvents(System.Diagnostics.Tracing.EventSource,System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords,System.Collections.Generic.IDictionary&lt;System.String,System.String&gt;)" />
+ <Member Name="EventSourceIndex(System.Diagnostics.Tracing.EventSource)" />
+ <Member Name="OnEventSourceCreated(System.Diagnostics.Tracing.EventSource)" />
+ <Member Name="OnEventWritten(System.Diagnostics.Tracing.EventWrittenEventArgs)" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.EventManifestOptions">
+ <Member MemberType="Field" Name="AllCultures" />
+ <Member MemberType="Field" Name="AllowEventSourceOverride" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="OnlyIfNeededForRegistration" />
+ <Member MemberType="Field" Name="Strict" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.EventOpcode">
+ <Member MemberType="Field" Name="DataCollectionStart" />
+ <Member MemberType="Field" Name="DataCollectionStop" />
+ <Member MemberType="Field" Name="Extension" />
+ <Member MemberType="Field" Name="Info" />
+ <Member MemberType="Field" Name="Receive" />
+ <Member MemberType="Field" Name="Reply" />
+ <Member MemberType="Field" Name="Resume" />
+ <Member MemberType="Field" Name="Send" />
+ <Member MemberType="Field" Name="Start" />
+ <Member MemberType="Field" Name="Stop" />
+ <Member MemberType="Field" Name="Suspend" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.EventSource">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member Name="#ctor(System.Diagnostics.Tracing.EventSourceSettings)" />
+ <Member Name="#ctor(System.Diagnostics.Tracing.EventSourceSettings,System.String[])" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Diagnostics.Tracing.EventSourceSettings)" />
+ <Member Name="#ctor(System.String,System.Diagnostics.Tracing.EventSourceSettings,System.String[])" />
+ <Member Name="get_Guid" />
+ <Member Name="get_Name" />
+ <Member MemberType="Property" Name="ConstructionException" />
+ <Member MemberType="Property" Name="CurrentThreadActivityId" />
+ <Member MemberType="Event" Name="EventCommandExecuted" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="GenerateManifest(System.Type,System.String)" />
+ <Member Name="GenerateManifest(System.Type,System.String,System.Diagnostics.Tracing.EventManifestOptions)" />
+ <Member Name="GetGuid(System.Type)" />
+ <Member Name="GetName(System.Type)" />
+ <Member Name="GetTrait(System.String)" />
+ <Member Name="GetSources" />
+ <Member Name="IsEnabled" />
+ <Member Name="IsEnabled(System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords)" />
+ <Member Name="IsEnabled(System.Diagnostics.Tracing.EventLevel,System.Diagnostics.Tracing.EventKeywords,System.Diagnostics.Tracing.EventChannel)" />
+ <Member Name="OnEventCommand(System.Diagnostics.Tracing.EventCommandEventArgs)" />
+ <Member Name="SendCommand(System.Diagnostics.Tracing.EventSource,System.Diagnostics.Tracing.EventCommand,System.Collections.Generic.IDictionary&lt;System.String,System.String&gt;)" />
+ <Member Name="SetCurrentThreadActivityId(System.Guid)" />
+ <Member Name="SetCurrentThreadActivityId(System.Guid,System.Guid@)" />
+ <Member MemberType="Property" Name="Settings" />
+ <Member Name="ToString" />
+ <Member Name="Write(System.String)" />
+ <Member Name="Write(System.String,System.Diagnostics.Tracing.EventSourceOptions)" />
+ <Member Name="Write&lt;T&gt;(System.String,T)" />
+ <Member Name="Write&lt;T&gt;(System.String,System.Diagnostics.Tracing.EventSourceOptions,T)" />
+ <Member Name="Write&lt;T&gt;(System.String,System.Diagnostics.Tracing.EventSourceOptions@,System.Guid@,System.Guid@,T@)" />
+ <Member Name="Write&lt;T&gt;(System.String,System.Diagnostics.Tracing.EventSourceOptions@,T@)" />
+ <Member Name="WriteEvent(System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.Byte[])" />
+ <Member Name="WriteEvent(System.Int32,System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.Int32,System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.Int32,System.Int32,System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.Int32,System.String)" />
+ <Member Name="WriteEvent(System.Int32,System.Int64)" />
+ <Member Name="WriteEvent(System.Int32,System.Int64,System.Byte[])" />
+ <Member Name="WriteEvent(System.Int32,System.Int64,System.Int64)" />
+ <Member Name="WriteEvent(System.Int32,System.Int64,System.Int64,System.Int64)" />
+ <Member Name="WriteEvent(System.Int32,System.Int64,System.String)" />
+ <Member Name="WriteEvent(System.Int32,System.Object[])" />
+ <Member Name="WriteEvent(System.Int32,System.String)" />
+ <Member Name="WriteEvent(System.Int32,System.String,System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.String,System.Int32,System.Int32)" />
+ <Member Name="WriteEvent(System.Int32,System.String,System.Int64)" />
+ <Member Name="WriteEvent(System.Int32,System.String,System.String)" />
+ <Member Name="WriteEvent(System.Int32,System.String,System.String,System.String)" />
+ <Member Name="WriteEventCore(System.Int32,System.Int32,System.Diagnostics.Tracing.EventSource+EventData*)" />
+ <Member Name="WriteEventWithRelatedActivityId(System.Int32,System.Guid,System.Object[])" />
+ <Member Name="WriteEventWithRelatedActivityIdCore(System.Int32,System.Guid*,System.Int32,System.Diagnostics.Tracing.EventSource+EventData*)" />
+ <Member Name="get_Settings" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventSource+EventData">
+ <Member MemberType="Property" Name="DataPointer" />
+ <Member MemberType="Property" Name="Size" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.EventSourceAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="Guid" />
+ <Member MemberType="Property" Name="LocalizationResources" />
+ <Member MemberType="Property" Name="Name" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventIgnoreAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventSourceException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventSourceOptions">
+ <Member MemberType="Property" Name="Keywords" />
+ <Member MemberType="Property" Name="Level" />
+ <Member MemberType="Property" Name="Opcode" />
+ <Member MemberType="Property" Name="Tags" />
+ <Member MemberType="Property" Name="ActivityOptions" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventSourceSettings">
+ <Member MemberType="Field" Name="Default" />
+ <Member MemberType="Field" Name="EtwManifestEventFormat" />
+ <Member MemberType="Field" Name="EtwSelfDescribingEventFormat" />
+ <Member MemberType="Field" Name="ThrowOnEventWriteErrors" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventTask">
+ <Member MemberType="Field" Name="None" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventTags">
+ <Member MemberType="Field" Name="None" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventFieldTags">
+ <Member MemberType="Field" Name="None" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventFieldAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="Tags" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Format" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.EventWrittenEventArgs">
+ <Member Name="get_Channel" />
+ <Member Name="get_EventId" />
+ <Member Name="get_EventSource" />
+ <Member Name="get_Keywords" />
+ <Member Name="get_Level" />
+ <Member Name="get_Message" />
+ <Member Name="get_Opcode" />
+ <Member Name="get_Payload" />
+ <Member Name="get_PayloadNames" />
+ <Member Name="get_Task" />
+ <Member Name="get_Version" />
+ <Member Name="get_Tags" />
+ <Member MemberType="Property" Name="ActivityId" />
+ <Member MemberType="Property" Name="EventName" />
+ <Member MemberType="Property" Name="RelatedActivityId" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.NonEventAttribute">
+ <Member Name="#ctor" />
+ </Type>
+
+ <Type Name="System.Diagnostics.Tracing.FrameworkEventSource+Tasks">
+ <Member MemberType="Field" Name="GetResponse" />
+ <Member MemberType="Field" Name="GetRequestStream" />
+ <Member MemberType="Field" Name="ThreadTransfer" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.FrameworkEventSource+Keywords">
+ <Member MemberType="Field" Name="Loader" />
+ <Member MemberType="Field" Name="ThreadPool" />
+ <Member MemberType="Field" Name="NetClient" />
+ <Member MemberType="Field" Name="DynamicTypeUsage" />
+ <Member MemberType="Field" Name="ThreadTransfer" />
+ </Type>
+ <Type Name="System.Diagnostics.Tracing.FrameworkEventSource+Opcodes">
+ <Member MemberType="Field" Name="ReceiveHandled" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.IO.Stream+SynchronousAsyncResult">
+ <Member Name="get_AsyncState" />
+ <Member Name="get_AsyncWaitHandle" />
+ <Member Name="get_CompletedSynchronously" />
+ <Member Name="get_IsCompleted" />
+ <Member MemberType="Property" Name="AsyncState" />
+ <Member MemberType="Property" Name="AsyncWaitHandle" />
+ <Member MemberType="Property" Name="CompletedSynchronously" />
+ <Member MemberType="Property" Name="IsCompleted" />
+ </Type>
+ <Type Name="System.OperationCanceledException" >
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.String,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.String,System.Exception,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_CancellationToken" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.CustomAttributeCtorParameter" />
+ <Type Status="ImplRoot" Name="System.Reflection.CustomAttributeEncodedArgument" />
+ <Type Status="ImplRoot" Name="System.Reflection.CustomAttributeNamedParameter" />
+ <Type Status="ImplRoot" Name="System.Reflection.CustomAttributeType" />
+ <Type Status="ImplRoot" Name="System.Reflection.Emit.DynamicResolver" />
+ <Type Status="ImplRoot" Name="System.Reflection.Emit.DynamicResolver+SecurityControlFlags" />
+ <Type Status="ImplRoot" Name="System.Reflection.Emit.DynamicScope" />
+ <Type Name="System.Reflection.ExceptionHandlingClause" >
+ <Member Name="#ctor" />
+ <Member Name="get_CatchType" />
+ <Member Name="get_FilterOffset" />
+ <Member Name="get_Flags" />
+ <Member Name="get_HandlerLength" />
+ <Member Name="get_HandlerOffset" />
+ <Member Name="get_TryLength" />
+ <Member Name="get_TryOffset" />
+ <Member Name="ToString" />
+ </Type>
+ <Type Name="System.Reflection.ExceptionHandlingClauseOptions" >
+ <Member MemberType="Field" Name="Clause" />
+ <Member MemberType="Field" Name="Fault" />
+ <Member MemberType="Field" Name="Filter" />
+ <Member MemberType="Field" Name="Finally" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Reflection.LocalVariableInfo">
+ <Member Name="#ctor" />
+ <Member Name="get_IsPinned" />
+ <Member Name="get_LocalIndex" />
+ <Member Name="get_LocalType" />
+ <Member MemberType="Property" Name="IsPinned" />
+ <Member MemberType="Property" Name="LocalIndex" />
+ <Member MemberType="Property" Name="LocalType" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.MetadataImport">
+ <Member Name="ThrowError(System.Int32)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Reflection.MethodBody">
+ <Member Name="#ctor" />
+ <Member Name="get_ExceptionHandlingClauses" />
+ <Member Name="get_InitLocals" />
+ <Member Name="get_LocalSignatureMetadataToken" />
+ <Member Name="get_LocalVariables" />
+ <Member Name="get_MaxStackSize" />
+ <Member Name="GetILAsByteArray" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_exceptionHandlingClauses" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_IL" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_initLocals" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_localSignatureMetadataToken" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_localVariables" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_maxStackSize" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.Emit.ExceptionHandler">
+ <Member Name="op_Equality(System.Reflection.Emit.ExceptionHandler,System.Reflection.Emit.ExceptionHandler)" />
+ <Member Name="op_Inequality(System.Reflection.Emit.ExceptionHandler,System.Reflection.Emit.ExceptionHandler)" />
+ </Type>
+ <Type Name="System.Reflection.ReflectionTypeLoadException">
+ <Member Name="#ctor(System.Type[],System.Exception[])" />
+ <Member Name="#ctor(System.Type[],System.Exception[],System.String)" />
+ <Member Status="ImplRoot" Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member MemberType="Property" Name="LoaderExceptions" />
+ <Member MemberType="Property" Name="Types" />
+ <Member Name="get_LoaderExceptions" />
+ <Member Name="get_Types" />
+ </Type>
+ <Type Name="System.Reflection.ResourceAttributes">
+ <Member MemberType="Field" Name="Private" />
+ <Member MemberType="Field" Name="Public" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.RtFieldInfo">
+ <Member Status="ImplRoot" Name="GetFieldHandle" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Reflection.RuntimeConstructorInfo">
+ <Member Status="ImplRoot" MemberType="Field" Name="_empty1" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_empty2" />
+ <Member Status="ImplRoot" MemberType="Field" Name="_empty3" />
+ </Type>
+ <Type Name="System.Reflection.TypeFilter">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Status="ApiRoot" Name="BeginInvoke(System.Type,System.Object,System.AsyncCallback,System.Object)" />
+ <Member Status="ApiRoot" Name="EndInvoke(System.IAsyncResult)" />
+ <Member Status="ApiRoot" Name="Invoke(System.Type,System.Object)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.ReflectionOnlyType" />
+ <Type Status="ImplRoot" Name="System.ResId" />
+ <Type Status="ImplRoot" Name="System.Resolver">
+ <Member Name="GetJitContext(System.Int32@)" /> <!-- EE -->
+ <Member Name="GetCodeInfo(System.Int32@,System.Int32@,System.Int32@)" /> <!-- EE -->
+ <Member Name="GetLocalsSignature" /> <!-- EE -->
+ <Member Name="GetEHInfo(System.Int32,System.Void*)" /> <!-- EE -->
+ <Member Name="GetRawEHInfo" /> <!-- EE -->
+ <Member Name="GetStringLiteral(System.Int32)" /> <!-- EE -->
+ <Member Name="ResolveToken(System.Int32,System.IntPtr@,System.IntPtr@,System.IntPtr@)" /> <!-- EE -->
+ <Member Name="ResolveSignature(System.Int32,System.Int32)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.CompilerServices.RuntimeWrappedException">
+ <Member Name="#ctor(System.Object)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.CompilerServices.TypeDependencyAttribute">
+ <Member Name="#ctor(System.String)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ArrayWithOffset">
+ <Member Name="#ctor(System.Object,System.Int32)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="Equals(System.Runtime.InteropServices.ArrayWithOffset)" />
+ <Member Name="GetArray" />
+ <Member Name="GetHashCode" />
+ <Member Name="GetOffset" />
+ <Member Name="op_Equality(System.Runtime.InteropServices.ArrayWithOffset,System.Runtime.InteropServices.ArrayWithOffset)" />
+ <Member Name="op_Inequality(System.Runtime.InteropServices.ArrayWithOffset,System.Runtime.InteropServices.ArrayWithOffset)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.ConstrainedExecution.ReliabilityContractAttribute" />
+ <Type Status="ImplRoot" Name="System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute" />
+ <Type Name="System.Runtime.ConstrainedExecution.CriticalFinalizerObject">
+ <Member Name="#ctor"/>
+ <Member Name="Finalize" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.Expando.IExpando">
+ <Member Name="AddField(System.String)" /> <!-- EE -->
+ <Member Name="RemoveMember(System.Reflection.MemberInfo)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.ICustomMarshaler">
+ <Member Name="MarshalNativeToManaged(System.IntPtr)" /> <!-- EE -->
+ <Member Name="MarshalManagedToNative(System.Object)" /> <!-- EE -->
+ <Member Name="CleanUpNativeData(System.IntPtr)" /> <!-- EE -->
+ <Member Name="CleanUpManagedData(System.Object)" /> <!-- EE -->
+ <Member Name="GetNativeDataSize" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Runtime.InteropServices.InvalidOleVariantTypeException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IStringable" Condition="FEATURE_COMINTEROP">
+ <Member Name="ToString"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IIterator&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="get_Current"/>
+ <Member Name="get_HasCurrent" />
+ <Member Name="MoveNext"/>
+ <Member Name="GetMany(T[])"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.BindableIterableToEnumerableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetEnumerator_Stub" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.BindableVectorToCollectionAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Count" />
+ <Member Name="IsSynchronized" />
+ <Member Name="SyncRoot" />
+ <Member Name="CopyTo(System.Array,System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.BindableVectorToListAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Indexer_Get(System.Int32)" />
+ <Member Name="Indexer_Set(System.Int32,System.Object)" />
+ <Member Name="Add(System.Object)" />
+ <Member Name="Contains(System.Object)" />
+ <Member Name="Clear" />
+ <Member Name="IsFixedSize" />
+ <Member Name="IsReadOnly" />
+ <Member Name="IndexOf(System.Object)" />
+ <Member Name="Insert(System.Int32,System.Object)" />
+ <Member Name="Remove(System.Object)" />
+ <Member Name="RemoveAt(System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.CLRIReferenceImpl&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="UnboxHelper(System.Object)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.CLRIKeyValuePairImpl&lt;K,V&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="BoxHelper(System.Object)" />
+ <Member Name="UnboxHelper(System.Object)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.CLRIReferenceArrayImpl&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="UnboxHelper(System.Object)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.DefaultInterfaceAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.Type)" />
+ <Member MemberType="Property" Name="DefaultInterface" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.ReadOnlyArrayAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.ReturnValueNameAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="Name" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.WriteOnlyArrayAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.DictionaryToMapAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Lookup&lt;K,V&gt;(K)" />
+ <Member Name="Size&lt;K,V&gt;" />
+ <Member Name="HasKey&lt;K,V&gt;(K)" />
+ <Member Name="GetView&lt;K,V&gt;" />
+ <Member Name="Insert&lt;K,V&gt;(K,V)" />
+ <Member Name="Remove&lt;K,V&gt;(K)" />
+ <Member Name="Clear&lt;K,V&gt;" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.VectorViewToReadOnlyCollectionAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Count&lt;T&gt;" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.MapViewToReadOnlyCollectionAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Count&lt;K,V&gt;" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.EnumerableToBindableIterableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="First_Stub" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.EnumerableToIterableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="First_Stub&lt;T&gt;" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken" Condition="FEATURE_COMINTEROP">
+ <Member Name="op_Equality(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken,System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)" />
+ <Member Name="op_Inequality(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken,System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor"/>
+ <Member Name="get_InvocationList"/>
+ <Member Name="set_InvocationList(T)"/>
+ <Member MemberType="Property" Name="InvocationList"/>
+ <Member Name="AddEventHandler(T)"/>
+ <Member Name="RemoveEventHandler(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)"/>
+ <Member Name="RemoveEventHandler(T)"/>
+ <Member Status="ApiFxInternal" Name="ExtractHandler(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken)" />
+ <Member Name="GetOrCreateEventRegistrationTokenTable(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable&lt;T&gt;@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.GetEnumerator_Delegate&lt;T@&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IActivationFactory" Condition="FEATURE_COMINTEROP">
+ <Member Name="ActivateInstance"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IBindableIterable" Condition="FEATURE_COMINTEROP">
+ <Member Name="First" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IBindableIterator" Condition="FEATURE_COMINTEROP">
+ <Member Name="get_Current" />
+ <Member MemberType="Property" Name="Current" />
+ <Member Name="get_HasCurrent" />
+ <Member MemberType="Property" Name="HasCurrent" />
+ <Member Name="MoveNext" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IBindableVector" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt(System.UInt32)" />
+ <Member Name="get_Size" />
+ <Member MemberType="Property" Name="Size" />
+ <Member Name="GetView" />
+ <Member Name="IndexOf(System.Object,System.UInt32@)" />
+ <Member Name="SetAt(System.UInt32,System.Object)" />
+ <Member Name="InsertAt(System.UInt32,System.Object)" />
+ <Member Name="RemoveAt(System.UInt32)" />
+ <Member Name="Append(System.Object)" />
+ <Member Name="RemoveAtEnd" />
+ <Member Name="Clear" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IBindableVectorView" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt(System.UInt32)" />
+ <Member Name="get_Size" />
+ <Member MemberType="Property" Name="Size" />
+ <Member Name="IndexOf(System.Object,System.UInt32@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IClosable" Condition="FEATURE_COMINTEROP">
+ <Member Name="Close"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IDisposableToIClosableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor"/>
+ <Member Name="Close"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IClosableToIDisposableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor"/>
+ <Member Name="Dispose"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.ICustomProperty" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetValue(System.Object)"/>
+ <Member Name="GetValue(System.Object,System.Object)"/>
+ <Member Name="SetValue(System.Object,System.Object)"/>
+ <Member Name="SetValue(System.Object,System.Object,System.Object)"/>
+ <Member Name="get_CanRead"/>
+ <Member Name="get_CanWrite"/>
+ <Member Name="get_Name"/>
+ <Member Name="get_Type"/>
+ <Member MemberType="Property" Name="CanRead"/>
+ <Member MemberType="Property" Name="CanWrite"/>
+ <Member MemberType="Property" Name="Name"/>
+ <Member MemberType="Property" Name="Type"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.ICustomPropertyProviderImpl" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateProperty(System.Object,System.String)" />
+ <Member Name="CreateIndexedProperty(System.Object,System.String,System.StubHelpers.TypeNameNative*)" />
+ <Member Name="GetType(System.Object,System.StubHelpers.TypeNameNative*)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.ICustomPropertyProviderProxy" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateInstance(System.Object)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IIterable&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="First" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IKeyValuePair&lt;K,V&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="get_Key" />
+ <Member Name="get_Value" />
+ <Member MemberType="Property" Name="Key" />
+ <Member MemberType="Property" Name="Value" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IMap&lt;K,V&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="Lookup(K)" />
+ <Member Name="get_Size" />
+ <Member Name="Size" MemberType="Property" />
+ <Member Name="HasKey(K)" />
+ <Member Name="GetView" />
+ <Member Name="Insert(K,V)" />
+ <Member Name="Remove(K)" />
+ <Member Name="Clear" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.Indexer_Get_Delegate&lt;T@&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Int32,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Int32)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.InteropServices.WindowsRuntime.InterfaceImplementedInVersionAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.Type,System.Byte,System.Byte,System.Byte,System.Byte)"/>
+ <Member MemberType="Property" Name="BuildVersion" />
+ <Member MemberType="Property" Name="MajorVersion" />
+ <Member MemberType="Property" Name="MinorVersion" />
+ <Member MemberType="Property" Name="RevisionVersion" />
+ <Member MemberType="Property" Name="InterfaceType" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IterableToEnumerableAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetEnumerator_Stub&lt;T&gt;" />
+ <Member Name="GetEnumerator_Variance_Stub&lt;T&gt;" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IMapView&lt;K,V&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="Lookup(K)" />
+ <Member Name="get_Size" />
+ <Member Name="Size" MemberType="Property" />
+ <Member Name="HasKey(K)" />
+ <Member Name="Split(System.Runtime.InteropServices.WindowsRuntime.IMapView&lt;K,V&gt;@,System.Runtime.InteropServices.WindowsRuntime.IMapView&lt;K,V&gt;@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IMapViewToIReadOnlyDictionaryAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Indexer_Get&lt;K,V&gt;(K)" />
+ <Member Name="Keys&lt;K,V&gt;" />
+ <Member Name="Values&lt;K,V&gt;" />
+ <Member Name="ContainsKey&lt;K,V&gt;(K)" />
+ <Member Name="TryGetValue&lt;K,V&gt;(K,V@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IPropertyValue" Condition="FEATURE_COMINTEROP">
+ <Member Name="get_Type"/>
+ <Member MemberType="Property" Name="Type"/>
+ <Member Name="get_IsNumericScalar"/>
+ <Member MemberType="Property" Name="IsNumericScalar"/>
+ <Member Name="GetUInt8" />
+ <Member Name="GetInt16" />
+ <Member Name="GetUInt16" />
+ <Member Name="GetInt32" />
+ <Member Name="GetUInt32" />
+ <Member Name="GetInt64" />
+ <Member Name="GetUInt64" />
+ <Member Name="GetSingle" />
+ <Member Name="GetDouble" />
+ <Member Name="GetChar16" />
+ <Member Name="GetBoolean" />
+ <Member Name="GetString" />
+ <Member Name="GetGuid" />
+ <Member Name="GetDateTime" />
+ <Member Name="GetTimeSpan" />
+ <Member Name="GetPoint" />
+ <Member Name="GetSize" />
+ <Member Name="GetRect" />
+ <Member Name="GetUInt8Array" />
+ <Member Name="GetInt16Array" />
+ <Member Name="GetUInt16Array" />
+ <Member Name="GetInt32Array" />
+ <Member Name="GetUInt32Array" />
+ <Member Name="GetInt64Array" />
+ <Member Name="GetUInt64Array" />
+ <Member Name="GetSingleArray" />
+ <Member Name="GetDoubleArray" />
+ <Member Name="GetChar16Array" />
+ <Member Name="GetBooleanArray" />
+ <Member Name="GetStringArray" />
+ <Member Name="GetInspectableArray" />
+ <Member Name="GetGuidArray" />
+ <Member Name="GetDateTimeArray" />
+ <Member Name="GetTimeSpanArray" />
+ <Member Name="GetPointArray" />
+ <Member Name="GetSizeArray" />
+ <Member Name="GetRectArray" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IReadOnlyDictionaryToIMapViewAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Lookup&lt;K,V&gt;(K)" />
+ <Member Name="Size&lt;K,V&gt;" />
+ <Member Name="HasKey&lt;K,V&gt;(K)" />
+ <Member Name="Split&lt;K,V&gt;(System.Runtime.InteropServices.WindowsRuntime.IMapView&lt;K,V&gt;@,System.Runtime.InteropServices.WindowsRuntime.IMapView&lt;K,V&gt;@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IReadOnlyListToIVectorViewAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt&lt;T&gt;(System.UInt32)" />
+ <Member Name="Size&lt;T&gt;" />
+ <Member Name="IndexOf&lt;T&gt;(T,System.UInt32@)" />
+ <Member Name="GetMany&lt;T&gt;(System.UInt32,T[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IReferenceFactory" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateIReference(System.Object)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IRestrictedErrorInfo" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetErrorDetails(System.String@,System.Int32@,System.String@,System.String@)" />
+ <Member Name="GetReference(System.String@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IVector&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt(System.UInt32)" />
+ <Member Name="get_Size" />
+ <Member Name="Size" MemberType="Property" />
+ <Member Name="GetView" />
+ <Member Name="IndexOf(T,System.UInt32@)" />
+ <Member Name="SetAt(System.UInt32,T)" />
+ <Member Name="RemoveAt(System.UInt32)" />
+ <Member Name="Append(T)" />
+ <Member Name="RemoveAtEnd" />
+ <Member Name="Clear" />
+ <Member Name="GetMany(System.UInt32,T[])" />
+ <Member Name="ReplaceAll(T[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IVectorView&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt(System.UInt32)" />
+ <Member Name="get_Size" />
+ <Member Name="Size" MemberType="Property" />
+ <Member Name="IndexOf(T,System.UInt32@)" />
+ <Member Name="GetMany(System.UInt32,T[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IVectorViewToIReadOnlyListAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Indexer_Get&lt;T&gt;(System.Int32)" />
+ <Member Name="Indexer_Get_Variance&lt;T&gt;(System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.ListToBindableVectorAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt(System.UInt32)" />
+ <Member Name="Size" />
+ <Member Name="GetView" />
+ <Member Name="IndexOf(System.Object,System.UInt32@)" />
+ <Member Name="SetAt(System.UInt32,System.Object)" />
+ <Member Name="InsertAt(System.UInt32,System.Object)" />
+ <Member Name="RemoveAt(System.UInt32)" />
+ <Member Name="Append(System.Object)" />
+ <Member Name="RemoveAtEnd" />
+ <Member Name="Clear" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.ListToVectorAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetAt&lt;T&gt;(System.UInt32)" />
+ <Member Name="Size&lt;T&gt;" />
+ <Member Name="GetView&lt;T&gt;" />
+ <Member Name="IndexOf&lt;T&gt;(T,System.UInt32@)" />
+ <Member Name="SetAt&lt;T&gt;(System.UInt32,T)" />
+ <Member Name="InsertAt&lt;T&gt;(System.UInt32,T)" />
+ <Member Name="RemoveAt&lt;T&gt;(System.UInt32)" />
+ <Member Name="Append&lt;T&gt;(T)" />
+ <Member Name="RemoveAtEnd&lt;T&gt;" />
+ <Member Name="Clear&lt;T&gt;" />
+ <Member Name="GetMany&lt;T&gt;(System.UInt32,T[])" />
+ <Member Name="ReplaceAll&lt;T&gt;(T[])" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.MapToCollectionAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Count&lt;K,V&gt;" />
+ <Member Name="IsReadOnly&lt;K,V&gt;" />
+ <Member Name="Add&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;)" />
+ <Member Name="Clear&lt;K,V&gt;" />
+ <Member Name="Contains&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;)" />
+ <Member Name="CopyTo&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;[],System.Int32)" />
+ <Member Name="Remove&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Indexer_Get&lt;K,V&gt;(K)" />
+ <Member Name="Indexer_Set&lt;K,V&gt;(K,V)" />
+ <Member Name="Keys&lt;K,V&gt;" />
+ <Member Name="Values&lt;K,V&gt;" />
+ <Member Name="ContainsKey&lt;K,V&gt;(K)" />
+ <Member Name="Add&lt;K,V&gt;(K,V)" />
+ <Member Name="Remove&lt;K,V&gt;(K)" />
+ <Member Name="TryGetValue&lt;K,V&gt;(K,V@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.RuntimeClass" Condition="FEATURE_COMINTEROP" />
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.VectorToCollectionAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Count&lt;T&gt;" />
+ <Member Name="IsReadOnly&lt;T&gt;" />
+ <Member Name="Add&lt;T&gt;(T)" />
+ <Member Name="Clear&lt;T&gt;" />
+ <Member Name="Contains&lt;T&gt;(T)" />
+ <Member Name="CopyTo&lt;T&gt;(T[],System.Int32)" />
+ <Member Name="Remove&lt;T&gt;(T)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.VectorToListAdapter" Condition="FEATURE_COMINTEROP">
+ <Member Name="Indexer_Get&lt;T&gt;(System.Int32)" />
+ <Member Name="Indexer_Set&lt;T&gt;(System.Int32,T)" />
+ <Member Name="IndexOf&lt;T&gt;(T)" />
+ <Member Name="Insert&lt;T&gt;(System.Int32,T)" />
+ <Member Name="RemoveAt&lt;T&gt;(System.Int32)" />
+ </Type>
+ <Type Status="ApiFxInternal" Name="System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeImportAttribute" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.WindowsFoundationEventHandler&lt;T&gt;" Condition="FEATURE_COMINTEROP">
+ <Member Name="#ctor(System.Object,System.IntPtr)" />
+ <Member Name="BeginInvoke(System.Object,T,System.AsyncCallback,System.Object)" />
+ <Member Name="EndInvoke(System.IAsyncResult)" />
+ <Member Name="Invoke(System.Object,T)" />
+ </Type>
+ <Type Status="ApiFxInternal" Name="System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferHelper" Condition="FEATURE_COMINTEROP">
+ <Member Name="StoreOverlappedPtrInCCW(System.Runtime.CompilerServices.ObjectHandleOnStack,System.Threading.NativeOverlapped*)" />
+ <Member Name="StoreOverlappedInCCW(System.Object,System.Threading.NativeOverlapped*)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.WindowsRuntime.IManagedActivationFactory" Condition="FEATURE_COMINTEROP">
+ <Member Name="RunClassConstructor" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal" Condition="FEATURE_COMINTEROP">
+ <Member Status="ApiRoot" Name="GetRegistrationTokenCacheSize" />
+ <Member Name="AddEventHandler&lt;T&gt;(System.Func&lt;T,System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken&gt;,System.Action&lt;System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken&gt;,T)" />
+ <Member Name="FreeHString(System.IntPtr)" />
+ <Member Name="GetActivationFactory(System.Type)" />
+ <Member Name="GetActivationFactoryForType(System.Type)" />
+ <Member Name="GetManagedActivationFactory(System.Type)" />
+ <Member Name="PtrToStringHString(System.IntPtr)" />
+ <Member Name="RemoveAllEventHandlers(System.Action&lt;System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken&gt;)" />
+ <Member Name="RemoveEventHandler&lt;T&gt;(System.Action&lt;System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken&gt;,T)" />
+ <Member Name="StringToHString(System.String)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.Versioning.ResourceConsumptionAttribute">
+ <Member Name="#ctor(System.Runtime.Versioning.ResourceScope)" />
+ <Member Name="#ctor(System.Runtime.Versioning.ResourceScope,System.Runtime.Versioning.ResourceScope)" />
+ <Member MemberType="Property" Name="ConsumptionScope" />
+ <Member MemberType="Property" Name="ResourceScope" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Versioning.ResourceExposureAttribute">
+ <Member Name="#ctor(System.Runtime.Versioning.ResourceScope)" />
+ <Member MemberType="Property" Name="ResourceExposureLevel" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Versioning.TargetFrameworkAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member MemberType="Property" Name="FrameworkName" />
+ <Member MemberType="Property" Name="FrameworkDisplayName" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Versioning.VersioningHelper">
+ <Member Name="MakeVersionSafeName(System.String,System.Runtime.Versioning.ResourceScope,System.Runtime.Versioning.ResourceScope)" />
+ <Member Name="MakeVersionSafeName(System.String,System.Runtime.Versioning.ResourceScope,System.Runtime.Versioning.ResourceScope,System.Type)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.FormatterServices">
+ <Member Name="GetUninitializedObject(System.Type)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.OptionalFieldAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Property" Name="VersionAdded" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.SerializationEntry">
+ <Member MemberType="Property" Name="Value" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="ObjectType" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.SerializationException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.SerializationInfo">
+ <Member Name="#ctor(System.Type,System.Runtime.Serialization.IFormatterConverter)" />
+ <Member Name="#ctor(System.Type,System.Runtime.Serialization.IFormatterConverter,System.Boolean)" />
+ <Member Name="SetType(System.Type)" />
+ <Member Name="GetEnumerator" />
+ <Member Name="AddValue(System.String,System.Object,System.Type)" />
+ <Member Name="AddValue(System.String,System.Object)" />
+ <Member Name="AddValue(System.String,System.Boolean)" />
+ <Member Name="AddValue(System.String,System.Char)" />
+ <Member Name="AddValue(System.String,System.SByte)" />
+ <Member Name="AddValue(System.String,System.Byte)" />
+ <Member Name="AddValue(System.String,System.Int16)" />
+ <Member Name="AddValue(System.String,System.UInt16)" />
+ <Member Name="AddValue(System.String,System.Int32)" />
+ <Member Name="AddValue(System.String,System.UInt32)" />
+ <Member Name="AddValue(System.String,System.Int64)" />
+ <Member Name="AddValue(System.String,System.UInt64)" />
+ <Member Name="AddValue(System.String,System.Single)" />
+ <Member Name="AddValue(System.String,System.Double)" />
+ <Member Name="AddValue(System.String,System.Decimal)" />
+ <Member Name="AddValue(System.String,System.DateTime)" />
+ <Member Name="GetValue(System.String,System.Type)" />
+ <Member Name="GetBoolean(System.String)" />
+ <Member Name="GetChar(System.String)" />
+ <Member Name="GetSByte(System.String)" />
+ <Member Name="GetByte(System.String)" />
+ <Member Name="GetInt16(System.String)" />
+ <Member Name="GetUInt16(System.String)" />
+ <Member Name="GetInt32(System.String)" />
+ <Member Name="GetUInt32(System.String)" />
+ <Member Name="GetInt64(System.String)" />
+ <Member Name="GetUInt64(System.String)" />
+ <Member Name="GetSingle(System.String)" />
+ <Member Name="GetDouble(System.String)" />
+ <Member Name="GetDecimal(System.String)" />
+ <Member Name="GetDateTime(System.String)" />
+ <Member Name="GetString(System.String)" />
+ <Member Name="UpdateValue(System.String,System.Object,System.Type)" />
+ <Member MemberType="Property" Name="FullTypeName" />
+ <Member MemberType="Property" Name="AssemblyName" />
+ <Member MemberType="Property" Name="MemberCount" />
+ <Member MemberType="Property" Name="ObjectType" />
+ <Member MemberType="Property" Name="IsFullTypeNameSetExplicit" />
+ <Member MemberType="Property" Name="IsAssemblyNameSetExplicit" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.SerializationInfoEnumerator">
+ <Member Name="MoveNext" />
+ <Member Name="Reset" />
+ <Member Name="System.Collections.IEnumerator.get_Current" />
+ <Member MemberType="Property" Name="Current" />
+ <Member MemberType="Property" Name="Name" />
+ <Member MemberType="Property" Name="Value" />
+ <Member MemberType="Property" Name="ObjectType" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.IObjectReference">
+ <Member Name="GetRealObject(System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.ISerializable">
+ <Member Name="GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.IFormatterConverter">
+ <Member Name="Convert(System.Object,System.Type)" />
+ <Member Name="Convert(System.Object,System.TypeCode)" />
+ <Member Name="ToBoolean(System.Object)" />
+ <Member Name="ToChar(System.Object)" />
+ <Member Name="ToSByte(System.Object)" />
+ <Member Name="ToByte(System.Object)" />
+ <Member Name="ToInt16(System.Object)" />
+ <Member Name="ToUInt16(System.Object)" />
+ <Member Name="ToInt32(System.Object)" />
+ <Member Name="ToUInt32(System.Object)" />
+ <Member Name="ToInt64(System.Object)" />
+ <Member Name="ToUInt64(System.Object)" />
+ <Member Name="ToSingle(System.Object)" />
+ <Member Name="ToDouble(System.Object)" />
+ <Member Name="ToDecimal(System.Object)" />
+ <Member Name="ToDateTime(System.Object)" />
+ <Member Name="ToString(System.Object)" />
+ </Type>
+ <Type Name="System.Runtime.Serialization.IDeserializationCallback">
+ <Member Name="OnDeserialization(System.Object)" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.OnSerializingAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.OnSerializedAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.OnDeserializingAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.OnDeserializedAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.StreamingContext">
+ <Member Name="#ctor(System.Runtime.Serialization.StreamingContextStates)" />
+ <Member Name="#ctor(System.Runtime.Serialization.StreamingContextStates,System.Object)" />
+ <Member MemberType="Property" Name="Context" />
+ <Member MemberType="Property" Name="State" />
+ </Type>
+ <Type Status="ApiRoot" Name="System.Runtime.Serialization.StreamingContextStates">
+ <Member MemberType="Field" Name="CrossProcess" />
+ <Member MemberType="Field" Name="CrossMachine" />
+ <Member MemberType="Field" Name="File" />
+ <Member MemberType="Field" Name="Persistence" />
+ <Member MemberType="Field" Name="Remoting" />
+ <Member MemberType="Field" Name="Other" />
+ <Member MemberType="Field" Name="Clone" />
+ <Member MemberType="Field" Name="CrossAppDomain" />
+ <Member MemberType="Field" Name="All" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.RuntimeType">
+ <Member Status="ImplRoot" MemberType="Field" Name="m_keepalive" />
+ <Member Name="GetPropertyInfo(System.RuntimeType,System.Int32)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.CodeAccessPermission" />
+ <Type Status="ImplRoot" Name="System.Security.PermissionType" />
+ <Type Status="ImplRoot" Name="System.Security.CodeAccessSecurityEngine">
+ <Member Name="CheckHelper(System.Object,System.Security.PermissionSet,System.Security.PermissionSet,System.Security.CodeAccessPermission,System.Security.PermissionToken,System.RuntimeMethodHandleInternal,System.Reflection.RuntimeAssembly,System.Security.Permissions.SecurityAction)" /> <!-- EE -->
+ <Member Name="CheckSetHelper(System.Object,System.Security.PermissionSet,System.Security.PermissionSet,System.Security.PermissionSet,System.RuntimeMethodHandleInternal,System.Reflection.RuntimeAssembly,System.Security.Permissions.SecurityAction)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.DynamicSecurityMethodAttribute" />
+ <Type Status="ImplRoot" Name="System.Security.FrameSecurityDescriptor">
+ <Member MemberType="Field" Name="m_callerToken" Condition="not FEATURE_PAL" />
+ <Member MemberType="Field" Name="m_DeclarativeDenials" />
+ <Member MemberType="Field" Name="m_DeclarativeRestrictions" />
+ <Member MemberType="Field" Name="m_denials" />
+ <Member MemberType="Field" Name="m_impToken" Condition="not FEATURE_PAL" />
+ <Member MemberType="Field" Name="m_restriction" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.PermissionListSet">
+ <Member Name="CheckDemandNoThrow(System.Security.CodeAccessPermission)" /> <!-- EE -->
+ <Member Name="CheckSetDemandNoThrow(System.Security.PermissionSet)" /> <!-- EE -->
+ <Member Name="Update(System.Security.PermissionSet)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.Permissions.PermissionState" />
+ <Type Name="System.Security.Permissions.SecurityAction" />
+ <Type Status="ImplRoot" Name="System.Security.Permissions.SecurityPermission" />
+ <Type Name="System.Security.Permissions.CodeAccessSecurityAttribute">
+ <Member Name="#ctor(System.Security.Permissions.SecurityAction)" />
+ </Type>
+ <Type Name="System.Security.Permissions.SecurityPermissionAttribute">
+ <Member Name="#ctor(System.Security.Permissions.SecurityAction)" />
+ <Member MemberType="Property" Name="ControlAppDomain" />
+ <Member MemberType="Property" Name="ControlDomainPolicy" />
+ <Member MemberType="Property" Name="ControlEvidence" />
+ <Member MemberType="Property" Name="ControlPolicy" />
+ <Member MemberType="Property" Name="ControlThread" />
+ <Member MemberType="Property" Name="Flags" />
+ <Member MemberType="Property" Name="UnmanagedCode" />
+ <Member MemberType="Property" Name="SkipVerification" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.PermissionSet">
+ <Member MemberType="Field" Name="m_serializedPermissionSet" /> <!-- smosier: avoid changing layout of objects mirrored in EE for now -->
+ <Member MemberType="Field" Name="m_unrestrictedPermSet" /> <!-- smosier: avoid changing layout of objects mirrored in EE for now -->
+ <Member MemberType="Field" Name="m_normalPermSet" /> <!-- smosier: avoid changing layout of objects mirrored in EE for now -->
+ <Member MemberType="Field" Name="readableonly" /> <!-- smosier: avoid changing layout of objects mirrored in EE for now -->
+ <Member Name="CreateSerialized(System.Object[],System.Boolean,System.Byte[]@,System.Security.PermissionSet@,System.Security.Permissions.HostProtectionResource,System.Boolean)" /> <!-- EE -->
+ <Member Name="Contains(System.Security.IPermission)" /> <!-- EE -->
+ <Member Name="Demand" /> <!-- EE -->
+ <Member Name="DemandNonCAS" /> <!-- EE -->
+ <Member Name="Union(System.Security.PermissionSet)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.PermissionToken" />
+ <Type Status="ImplRoot" Name="System.Security.Policy.Evidence" />
+ <Type Name="System.Security.Principal.IIdentity">
+ <Member MemberType="Property" Name="AuthenticationType" />
+ <Member MemberType="Property" Name="IsAuthenticated" />
+ <Member MemberType="Property" Name="Name" />
+ <Member Name="get_AuthenticationType" />
+ <Member Name="get_IsAuthenticated" />
+ <Member Name="get_Name" />
+ </Type>
+ <Type Name="System.Security.Principal.IPrincipal">
+ <Member MemberType="Property" Name="Identity" />
+ <Member Name="IsInRole(System.String)" />
+ <Member Name ="get_Identity" />
+ </Type>
+ <Type Name="System.Security.Principal.TokenImpersonationLevel">
+ <Member MemberType="Field" Name="Anonymous" />
+ <Member MemberType="Field" Name="Delegation" />
+ <Member MemberType="Field" Name="Identification" />
+ <Member MemberType="Field" Name="Impersonation" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Security.SecurityCriticalAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Security.SecurityRuntime">
+ <Member Name="FrameDescHelper(System.Security.FrameSecurityDescriptor,System.Security.IPermission,System.Security.PermissionToken,System.RuntimeMethodHandleInternal)" /> <!-- EE -->
+ <Member Name="FrameDescSetHelper(System.Security.FrameSecurityDescriptor,System.Security.PermissionSet,System.Security.PermissionSet@,System.RuntimeMethodHandleInternal)" /> <!-- EE -->
+ </Type>
+ <Type Name="System.Security.SecurityTransparentAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Security.SecuritySafeCriticalAttribute" >
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Security.UnverifiableCodeAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Name="System.Security.VerificationException" >
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.SharedStatics">
+ <Member MemberType="Field" Name="_sharedStatics" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.SZArrayHelper">
+ <Member Name="Add&lt;T&gt;(T)" />
+ <Member Name="Clear&lt;T&gt;" />
+ <Member Name="Contains&lt;T&gt;(T)" />
+ <Member Name="CopyTo&lt;T&gt;(T[],System.Int32)" />
+ <Member Name="get_Count&lt;T&gt;" />
+ <Member Name="get_IsReadOnly&lt;T&gt;" />
+ <Member Name="get_Item&lt;T&gt;(System.Int32)" />
+ <Member Name="GetEnumerator&lt;T&gt;" />
+ <Member Name="IndexOf&lt;T&gt;(T)" />
+ <Member Name="Insert&lt;T&gt;(System.Int32,T)" />
+ <Member Name="Remove&lt;T&gt;(T)" />
+ <Member Name="RemoveAt&lt;T&gt;(System.Int32)" />
+ <Member Name="set_Item&lt;T&gt;(System.Int32,T)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading._IOCompletionCallback">
+ <Member Name="PerformIOCompletionCallback(System.UInt32,System.UInt32,System.Threading.NativeOverlapped*)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading._ThreadPoolWaitCallback">
+ <Member Name="PerformWaitCallback" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading._ThreadPoolWaitOrTimerCallback">
+ <Member Name="PerformWaitOrTimerCallback(System.Object,System.Boolean)" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.TimerQueue">
+ <Member Name="AppDomainTimerCallback" /> <!-- EE -->
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.InternalCrossContextDelegate" />
+ <Type Status="ImplRoot" Name="System.Threading.OverlappedData" />
+ <Type Status="ImplRoot" Name="System.Threading.ThreadInterruptedException">
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.ThreadStaticAttribute">
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Runtime.InteropServices.PInvokeMap" />
+ <Type Name="System.ArgIterator"> <!-- for MC++ -->
+ <Member Status="ImplRoot" Name="#ctor(System.RuntimeArgumentHandle,System.Void*)" /> <!-- EE - il stubs -->
+ </Type>
+ <Type Name="System.Runtime.InteropServices.BestFitMappingAttribute">
+ <Member MemberType="Field" Name="ThrowOnUnmappableChar" />
+ <Member Name="#ctor(System.Boolean)" />
+ <Member MemberType="Property" Name="BestFitMapping" />
+ <Member Name="get_BestFitMapping" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComEventInterfaceAttribute">
+ <Member Name="#ctor(System.Type,System.Type)" />
+ <Member MemberType="Property" Name="EventProvider" />
+ <Member MemberType="Property" Name="SourceInterface" />
+ <Member Name="get_EventProvider" />
+ <Member Name="get_SourceInterface" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComEventsHelper">
+ <Member Name="Combine(System.Object,System.Guid,System.Int32,System.Delegate)" />
+ <Member Name="Remove(System.Object,System.Guid,System.Int32,System.Delegate)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComMemberType">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Method" />
+ <Member MemberType="Field" Name="PropGet" />
+ <Member MemberType="Field" Name="PropSet" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComSourceInterfacesAttribute">
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.Type)" />
+ <Member Name="#ctor(System.Type,System.Type)" />
+ <Member Name="#ctor(System.Type,System.Type,System.Type)" />
+ <Member Name="#ctor(System.Type,System.Type,System.Type,System.Type)" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Value" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CustomQueryInterfaceMode">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Allow" />
+ <Member MemberType="Field" Name="Ignore" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.CustomQueryInterfaceResult">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="Failed" />
+ <Member MemberType="Field" Name="Handled" />
+ <Member MemberType="Field" Name="NotHandled" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute">
+ <Member Name="#ctor(System.Runtime.InteropServices.DllImportSearchPath)" />
+ <Member MemberType="Property" Name="Paths" />
+ <Member Name="get_Paths" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.DllImportSearchPath">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="ApplicationDirectory" />
+ <Member MemberType="Field" Name="AssemblyDirectory" />
+ <Member MemberType="Field" Name="LegacyBehavior" />
+ <Member MemberType="Field" Name="SafeDirectories" />
+ <Member MemberType="Field" Name="System32" />
+ <Member MemberType="Field" Name="UseDllDirectoryForDependencies" />
+ <Member MemberType="Field" Name="UserDirectories" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ICustomAdapter">
+ <Member Name="GetUnderlyingObject" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.SafeBuffer">
+ <Member Name="#ctor(System.Boolean)" />
+ <Member MemberType="Property" Name="ByteLength" />
+ <Member Name="AcquirePointer(System.Byte*@)" />
+ <Member Name="get_ByteLength" />
+ <Member Name="Initialize(System.UInt32,System.UInt32)" />
+ <Member Name="Initialize(System.UInt64)" />
+ <Member Name="Initialize&lt;T&gt;(System.UInt32)" />
+ <Member Name="Read&lt;T&gt;(System.UInt64)" />
+ <Member Name="ReadArray&lt;T&gt;(System.UInt64,T[],System.Int32,System.Int32)" />
+ <Member Name="ReleasePointer" />
+ <Member Name="Write&lt;T&gt;(System.UInt64,T)" />
+ <Member Name="WriteArray&lt;T&gt;(System.UInt64,T[],System.Int32,System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.TypeIdentifierAttribute">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String,System.String)" />
+ <Member MemberType="Property" Name="Identifier" />
+ <Member MemberType="Property" Name="Scope" />
+ <Member Name="get_Identifier" />
+ <Member Name="get_Scope" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.VarEnum">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VT_ARRAY" />
+ <Member MemberType="Field" Name="VT_BLOB" />
+ <Member MemberType="Field" Name="VT_BLOB_OBJECT" />
+ <Member MemberType="Field" Name="VT_BOOL" />
+ <Member MemberType="Field" Name="VT_BSTR" />
+ <Member MemberType="Field" Name="VT_BYREF" />
+ <Member MemberType="Field" Name="VT_CARRAY" />
+ <Member MemberType="Field" Name="VT_CF" />
+ <Member MemberType="Field" Name="VT_CLSID" />
+ <Member MemberType="Field" Name="VT_CY" />
+ <Member MemberType="Field" Name="VT_DATE" />
+ <Member MemberType="Field" Name="VT_DECIMAL" />
+ <Member MemberType="Field" Name="VT_DISPATCH" />
+ <Member MemberType="Field" Name="VT_EMPTY" />
+ <Member MemberType="Field" Name="VT_ERROR" />
+ <Member MemberType="Field" Name="VT_FILETIME" />
+ <Member MemberType="Field" Name="VT_HRESULT" />
+ <Member MemberType="Field" Name="VT_I1" />
+ <Member MemberType="Field" Name="VT_I2" />
+ <Member MemberType="Field" Name="VT_I4" />
+ <Member MemberType="Field" Name="VT_I8" />
+ <Member MemberType="Field" Name="VT_INT" />
+ <Member MemberType="Field" Name="VT_LPSTR" />
+ <Member MemberType="Field" Name="VT_LPWSTR" />
+ <Member MemberType="Field" Name="VT_NULL" />
+ <Member MemberType="Field" Name="VT_PTR" />
+ <Member MemberType="Field" Name="VT_R4" />
+ <Member MemberType="Field" Name="VT_R8" />
+ <Member MemberType="Field" Name="VT_RECORD" />
+ <Member MemberType="Field" Name="VT_SAFEARRAY" />
+ <Member MemberType="Field" Name="VT_STORAGE" />
+ <Member MemberType="Field" Name="VT_STORED_OBJECT" />
+ <Member MemberType="Field" Name="VT_STREAM" />
+ <Member MemberType="Field" Name="VT_STREAMED_OBJECT" />
+ <Member MemberType="Field" Name="VT_UI1" />
+ <Member MemberType="Field" Name="VT_UI2" />
+ <Member MemberType="Field" Name="VT_UI4" />
+ <Member MemberType="Field" Name="VT_UI8" />
+ <Member MemberType="Field" Name="VT_UINT" />
+ <Member MemberType="Field" Name="VT_UNKNOWN" />
+ <Member MemberType="Field" Name="VT_USERDEFINED" />
+ <Member MemberType="Field" Name="VT_VARIANT" />
+ <Member MemberType="Field" Name="VT_VECTOR" />
+ <Member MemberType="Field" Name="VT_VOID" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.BIND_OPTS">
+ <Member MemberType="Field" Name="cbStruct" />
+ <Member MemberType="Field" Name="dwTickCountDeadline" />
+ <Member MemberType="Field" Name="grfFlags" />
+ <Member MemberType="Field" Name="grfMode" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.BINDPTR">
+ <Member MemberType="Field" Name="lpfuncdesc" />
+ <Member MemberType="Field" Name="lptcomp" />
+ <Member MemberType="Field" Name="lpvardesc" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.CALLCONV">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="CC_CDECL" />
+ <Member MemberType="Field" Name="CC_MACPASCAL" />
+ <Member MemberType="Field" Name="CC_MAX" />
+ <Member MemberType="Field" Name="CC_MPWCDECL" />
+ <Member MemberType="Field" Name="CC_MPWPASCAL" />
+ <Member MemberType="Field" Name="CC_MSCPASCAL" />
+ <Member MemberType="Field" Name="CC_PASCAL" />
+ <Member MemberType="Field" Name="CC_RESERVED" />
+ <Member MemberType="Field" Name="CC_STDCALL" />
+ <Member MemberType="Field" Name="CC_SYSCALL" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.CONNECTDATA">
+ <Member MemberType="Field" Name="dwCookie" />
+ <Member MemberType="Field" Name="pUnk" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.DESCKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="DESCKIND_FUNCDESC" />
+ <Member MemberType="Field" Name="DESCKIND_IMPLICITAPPOBJ" />
+ <Member MemberType="Field" Name="DESCKIND_MAX" />
+ <Member MemberType="Field" Name="DESCKIND_NONE" />
+ <Member MemberType="Field" Name="DESCKIND_TYPECOMP" />
+ <Member MemberType="Field" Name="DESCKIND_VARDESC" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.DISPPARAMS">
+ <Member MemberType="Field" Name="cArgs" />
+ <Member MemberType="Field" Name="cNamedArgs" />
+ <Member MemberType="Field" Name="rgdispidNamedArgs" />
+ <Member MemberType="Field" Name="rgvarg" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ELEMDESC">
+ <Member MemberType="Field" Name="desc" />
+ <Member MemberType="Field" Name="tdesc" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ELEMDESC+DESCUNION">
+ <Member MemberType="Field" Name="idldesc" />
+ <Member MemberType="Field" Name="paramdesc" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.EXCEPINFO">
+ <Member MemberType="Field" Name="wCode" />
+ <Member MemberType="Field" Name="wReserved" />
+ <Member MemberType="Field" Name="dwHelpContext" />
+ <Member MemberType="Field" Name="scode" />
+ <Member MemberType="Field" Name="pfnDeferredFillIn" />
+ <Member MemberType="Field" Name="pvReserved" />
+ <Member MemberType="Field" Name="bstrDescription" />
+ <Member MemberType="Field" Name="bstrHelpFile" />
+ <Member MemberType="Field" Name="bstrSource" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.FUNCDESC">
+ <Member MemberType="Field" Name="cParams" />
+ <Member MemberType="Field" Name="cParamsOpt" />
+ <Member MemberType="Field" Name="cScodes" />
+ <Member MemberType="Field" Name="oVft" />
+ <Member MemberType="Field" Name="wFuncFlags" />
+ <Member MemberType="Field" Name="memid" />
+ <Member MemberType="Field" Name="lprgelemdescParam" />
+ <Member MemberType="Field" Name="lprgscode" />
+ <Member MemberType="Field" Name="callconv" />
+ <Member MemberType="Field" Name="elemdescFunc" />
+ <Member MemberType="Field" Name="funckind" />
+ <Member MemberType="Field" Name="invkind" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.FUNCFLAGS">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="FUNCFLAG_FBINDABLE" />
+ <Member MemberType="Field" Name="FUNCFLAG_FDEFAULTBIND" />
+ <Member MemberType="Field" Name="FUNCFLAG_FDEFAULTCOLLELEM" />
+ <Member MemberType="Field" Name="FUNCFLAG_FDISPLAYBIND" />
+ <Member MemberType="Field" Name="FUNCFLAG_FHIDDEN" />
+ <Member MemberType="Field" Name="FUNCFLAG_FIMMEDIATEBIND" />
+ <Member MemberType="Field" Name="FUNCFLAG_FNONBROWSABLE" />
+ <Member MemberType="Field" Name="FUNCFLAG_FREPLACEABLE" />
+ <Member MemberType="Field" Name="FUNCFLAG_FREQUESTEDIT" />
+ <Member MemberType="Field" Name="FUNCFLAG_FRESTRICTED" />
+ <Member MemberType="Field" Name="FUNCFLAG_FSOURCE" />
+ <Member MemberType="Field" Name="FUNCFLAG_FUIDEFAULT" />
+ <Member MemberType="Field" Name="FUNCFLAG_FUSESGETLASTERROR" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.FUNCKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="FUNC_DISPATCH" />
+ <Member MemberType="Field" Name="FUNC_NONVIRTUAL" />
+ <Member MemberType="Field" Name="FUNC_PUREVIRTUAL" />
+ <Member MemberType="Field" Name="FUNC_STATIC" />
+ <Member MemberType="Field" Name="FUNC_VIRTUAL" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IBindCtx">
+ <Member Name="EnumObjectParam(System.Runtime.InteropServices.ComTypes.IEnumString@)" />
+ <Member Name="GetBindOptions(System.Runtime.InteropServices.ComTypes.BIND_OPTS@)" />
+ <Member Name="GetObjectParam(System.String,System.Object@)" />
+ <Member Name="GetRunningObjectTable(System.Runtime.InteropServices.ComTypes.IRunningObjectTable@)" />
+ <Member Name="RegisterObjectBound(System.Object)" />
+ <Member Name="RegisterObjectParam(System.String,System.Object)" />
+ <Member Name="ReleaseBoundObjects" />
+ <Member Name="RevokeObjectBound(System.Object)" />
+ <Member Name="RevokeObjectParam(System.String)" />
+ <Member Name="SetBindOptions(System.Runtime.InteropServices.ComTypes.BIND_OPTS@)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IConnectionPoint">
+ <Member Name="Advise(System.Object,System.Int32@)" />
+ <Member Name="EnumConnections(System.Runtime.InteropServices.ComTypes.IEnumConnections@)" />
+ <Member Name="GetConnectionInterface(System.Guid@)" />
+ <Member Name="GetConnectionPointContainer(System.Runtime.InteropServices.ComTypes.IConnectionPointContainer@)" />
+ <Member Name="Unadvise(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IConnectionPointContainer">
+ <Member Name="EnumConnectionPoints(System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints@)" />
+ <Member Name="FindConnectionPoint(System.Guid@,System.Runtime.InteropServices.ComTypes.IConnectionPoint@)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IDLDESC">
+ <Member MemberType="Field" Name="dwReserved" />
+ <Member MemberType="Field" Name="wIDLFlags" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IDLFLAG">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="IDLFLAG_FIN" />
+ <Member MemberType="Field" Name="IDLFLAG_FLCID" />
+ <Member MemberType="Field" Name="IDLFLAG_FOUT" />
+ <Member MemberType="Field" Name="IDLFLAG_FRETVAL" />
+ <Member MemberType="Field" Name="IDLFLAG_NONE" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints">
+ <Member Name="Clone(System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints@)" />
+ <Member Name="Next(System.Int32,System.Runtime.InteropServices.ComTypes.IConnectionPoint[],System.IntPtr)" />
+ <Member Name="Reset" />
+ <Member Name="Skip(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IEnumConnections">
+ <Member Name="Clone(System.Runtime.InteropServices.ComTypes.IEnumConnections@)" />
+ <Member Name="Next(System.Int32,System.Runtime.InteropServices.ComTypes.CONNECTDATA[],System.IntPtr)" />
+ <Member Name="Reset" />
+ <Member Name="Skip(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IEnumMoniker">
+ <Member Name="Clone(System.Runtime.InteropServices.ComTypes.IEnumMoniker@)" />
+ <Member Name="Next(System.Int32,System.Runtime.InteropServices.ComTypes.IMoniker[],System.IntPtr)" />
+ <Member Name="Reset" />
+ <Member Name="Skip(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IEnumString">
+ <Member Name="Clone(System.Runtime.InteropServices.ComTypes.IEnumString@)" />
+ <Member Name="Next(System.Int32,System.String[],System.IntPtr)" />
+ <Member Name="Reset" />
+ <Member Name="Skip(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IEnumVARIANT">
+ <Member Name="Clone" />
+ <Member Name="Next(System.Int32,System.Object[],System.IntPtr)" />
+ <Member Name="Reset" />
+ <Member Name="Skip(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IMoniker">
+ <Member Name="BindToObject(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.Guid@,System.Object@)" />
+ <Member Name="BindToStorage(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.Guid@,System.Object@)" />
+ <Member Name="CommonPrefixWith(System.Runtime.InteropServices.ComTypes.IMoniker,System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="ComposeWith(System.Runtime.InteropServices.ComTypes.IMoniker,System.Boolean,System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="Enum(System.Boolean,System.Runtime.InteropServices.ComTypes.IEnumMoniker@)" />
+ <Member Name="GetClassID(System.Guid@)" />
+ <Member Name="GetDisplayName(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.String@)" />
+ <Member Name="GetSizeMax(System.Int64@)" />
+ <Member Name="GetTimeOfLastChange(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.Runtime.InteropServices.ComTypes.FILETIME@)" />
+ <Member Name="Hash(System.Int32@)" />
+ <Member Name="Inverse(System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="IsDirty" />
+ <Member Name="IsEqual(System.Runtime.InteropServices.ComTypes.IMoniker)" />
+ <Member Name="IsRunning(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.Runtime.InteropServices.ComTypes.IMoniker)" />
+ <Member Name="IsSystemMoniker(System.Int32@)" />
+ <Member Name="Load(System.Runtime.InteropServices.ComTypes.IStream)" />
+ <Member Name="ParseDisplayName(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Runtime.InteropServices.ComTypes.IMoniker,System.String,System.Int32@,System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="Reduce(System.Runtime.InteropServices.ComTypes.IBindCtx,System.Int32,System.Runtime.InteropServices.ComTypes.IMoniker@,System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="RelativePathTo(System.Runtime.InteropServices.ComTypes.IMoniker,System.Runtime.InteropServices.ComTypes.IMoniker@)" />
+ <Member Name="Save(System.Runtime.InteropServices.ComTypes.IStream,System.Boolean)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="IMPLTYPEFLAG_FDEFAULT" />
+ <Member MemberType="Field" Name="IMPLTYPEFLAG_FDEFAULTVTABLE" />
+ <Member MemberType="Field" Name="IMPLTYPEFLAG_FRESTRICTED" />
+ <Member MemberType="Field" Name="IMPLTYPEFLAG_FSOURCE" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.INVOKEKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="INVOKE_FUNC" />
+ <Member MemberType="Field" Name="INVOKE_PROPERTYGET" />
+ <Member MemberType="Field" Name="INVOKE_PROPERTYPUT" />
+ <Member MemberType="Field" Name="INVOKE_PROPERTYPUTREF" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IPersistFile">
+ <Member Name="GetClassID(System.Guid@)" />
+ <Member Name="GetCurFile(System.String@)" />
+ <Member Name="IsDirty" />
+ <Member Name="Load(System.String,System.Int32)" />
+ <Member Name="Save(System.String,System.Boolean)" />
+ <Member Name="SaveCompleted(System.String)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.IRunningObjectTable">
+ <Member Name="EnumRunning(System.Runtime.InteropServices.ComTypes.IEnumMoniker@)" />
+ <Member Name="GetObject(System.Runtime.InteropServices.ComTypes.IMoniker,System.Object@)" />
+ <Member Name="GetTimeOfLastChange(System.Runtime.InteropServices.ComTypes.IMoniker,System.Runtime.InteropServices.ComTypes.FILETIME@)" />
+ <Member Name="IsRunning(System.Runtime.InteropServices.ComTypes.IMoniker)" />
+ <Member Name="NoteChangeTime(System.Int32,System.Runtime.InteropServices.ComTypes.FILETIME@)" />
+ <Member Name="Register(System.Int32,System.Object,System.Runtime.InteropServices.ComTypes.IMoniker)" />
+ <Member Name="Revoke(System.Int32)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ITypeComp">
+ <Member Name="Bind(System.String,System.Int32,System.Int16,System.Runtime.InteropServices.ComTypes.ITypeInfo@,System.Runtime.InteropServices.ComTypes.DESCKIND@,System.Runtime.InteropServices.ComTypes.BINDPTR@)" />
+ <Member Name="BindType(System.String,System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo@,System.Runtime.InteropServices.ComTypes.ITypeComp@)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ITypeInfo">
+ <Member Name="AddressOfMember(System.Int32,System.Runtime.InteropServices.ComTypes.INVOKEKIND,System.IntPtr@)" />
+ <Member Name="CreateInstance(System.Object,System.Guid@,System.Object@)" />
+ <Member Name="GetContainingTypeLib(System.Runtime.InteropServices.ComTypes.ITypeLib@,System.Int32@)" />
+ <Member Name="GetDllEntry(System.Int32,System.Runtime.InteropServices.ComTypes.INVOKEKIND,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Name="GetDocumentation(System.Int32,System.String@,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetFuncDesc(System.Int32,System.IntPtr@)" />
+ <Member Name="GetIDsOfNames(System.String[],System.Int32,System.Int32[])" />
+ <Member Name="GetImplTypeFlags(System.Int32,System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS@)" />
+ <Member Name="GetMops(System.Int32,System.String@)" />
+ <Member Name="GetNames(System.Int32,System.String[],System.Int32,System.Int32@)" />
+ <Member Name="GetRefTypeInfo(System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetRefTypeOfImplType(System.Int32,System.Int32@)" />
+ <Member Name="GetTypeAttr(System.IntPtr@)" />
+ <Member Name="GetTypeComp(System.Runtime.InteropServices.ComTypes.ITypeComp@)" />
+ <Member Name="GetVarDesc(System.Int32,System.IntPtr@)" />
+ <Member Name="Invoke(System.Object,System.Int32,System.Int16,System.Runtime.InteropServices.ComTypes.DISPPARAMS@,System.IntPtr,System.IntPtr,System.Int32@)" />
+ <Member Name="ReleaseFuncDesc(System.IntPtr)" />
+ <Member Name="ReleaseTypeAttr(System.IntPtr)" />
+ <Member Name="ReleaseVarDesc(System.IntPtr)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ITypeInfo2">
+ <Member Name="AddressOfMember(System.Int32,System.Runtime.InteropServices.ComTypes.INVOKEKIND,System.IntPtr@)" />
+ <Member Name="CreateInstance(System.Object,System.Guid@,System.Object@)" />
+ <Member Name="GetAllCustData(System.IntPtr)" />
+ <Member Name="GetAllFuncCustData(System.Int32,System.IntPtr)" />
+ <Member Name="GetAllImplTypeCustData(System.Int32,System.IntPtr)" />
+ <Member Name="GetAllParamCustData(System.Int32,System.Int32,System.IntPtr)" />
+ <Member Name="GetAllVarCustData(System.Int32,System.IntPtr)" />
+ <Member Name="GetContainingTypeLib(System.Runtime.InteropServices.ComTypes.ITypeLib@,System.Int32@)" />
+ <Member Name="GetCustData(System.Guid@,System.Object@)" />
+ <Member Name="GetDllEntry(System.Int32,System.Runtime.InteropServices.ComTypes.INVOKEKIND,System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Name="GetDocumentation(System.Int32,System.String@,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetDocumentation2(System.Int32,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetFuncCustData(System.Int32,System.Guid@,System.Object@)" />
+ <Member Name="GetFuncDesc(System.Int32,System.IntPtr@)" />
+ <Member Name="GetFuncIndexOfMemId(System.Int32,System.Runtime.InteropServices.ComTypes.INVOKEKIND,System.Int32@)" />
+ <Member Name="GetIDsOfNames(System.String[],System.Int32,System.Int32[])" />
+ <Member Name="GetImplTypeCustData(System.Int32,System.Guid@,System.Object@)" />
+ <Member Name="GetImplTypeFlags(System.Int32,System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS@)" />
+ <Member Name="GetMops(System.Int32,System.String@)" />
+ <Member Name="GetNames(System.Int32,System.String[],System.Int32,System.Int32@)" />
+ <Member Name="GetParamCustData(System.Int32,System.Int32,System.Guid@,System.Object@)" />
+ <Member Name="GetRefTypeInfo(System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetRefTypeOfImplType(System.Int32,System.Int32@)" />
+ <Member Name="GetTypeAttr(System.IntPtr@)" />
+ <Member Name="GetTypeComp(System.Runtime.InteropServices.ComTypes.ITypeComp@)" />
+ <Member Name="GetTypeFlags(System.Int32@)" />
+ <Member Name="GetTypeKind(System.Runtime.InteropServices.ComTypes.TYPEKIND@)" />
+ <Member Name="GetVarCustData(System.Int32,System.Guid@,System.Object@)" />
+ <Member Name="GetVarDesc(System.Int32,System.IntPtr@)" />
+ <Member Name="GetVarIndexOfMemId(System.Int32,System.Int32@)" />
+ <Member Name="Invoke(System.Object,System.Int32,System.Int16,System.Runtime.InteropServices.ComTypes.DISPPARAMS@,System.IntPtr,System.IntPtr,System.Int32@)" />
+ <Member Name="ReleaseFuncDesc(System.IntPtr)" />
+ <Member Name="ReleaseTypeAttr(System.IntPtr)" />
+ <Member Name="ReleaseVarDesc(System.IntPtr)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ITypeLib">
+ <Member Name="FindName(System.String,System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo[],System.Int32[],System.Int16@)" />
+ <Member Name="GetDocumentation(System.Int32,System.String@,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetLibAttr(System.IntPtr@)" />
+ <Member Name="GetTypeComp(System.Runtime.InteropServices.ComTypes.ITypeComp@)" />
+ <Member Name="GetTypeInfo(System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetTypeInfoCount" />
+ <Member Name="GetTypeInfoOfGuid(System.Guid@,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetTypeInfoType(System.Int32,System.Runtime.InteropServices.ComTypes.TYPEKIND@)" />
+ <Member Name="IsName(System.String,System.Int32)" />
+ <Member Name="ReleaseTLibAttr(System.IntPtr)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.ITypeLib2">
+ <Member Name="FindName(System.String,System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo[],System.Int32[],System.Int16@)" />
+ <Member Name="GetAllCustData(System.IntPtr)" />
+ <Member Name="GetCustData(System.Guid@,System.Object@)" />
+ <Member Name="GetDocumentation(System.Int32,System.String@,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetDocumentation2(System.Int32,System.String@,System.Int32@,System.String@)" />
+ <Member Name="GetLibAttr(System.IntPtr@)" />
+ <Member Name="GetLibStatistics(System.IntPtr,System.Int32@)" />
+ <Member Name="GetTypeComp(System.Runtime.InteropServices.ComTypes.ITypeComp@)" />
+ <Member Name="GetTypeInfo(System.Int32,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetTypeInfoCount" />
+ <Member Name="GetTypeInfoOfGuid(System.Guid@,System.Runtime.InteropServices.ComTypes.ITypeInfo@)" />
+ <Member Name="GetTypeInfoType(System.Int32,System.Runtime.InteropServices.ComTypes.TYPEKIND@)" />
+ <Member Name="IsName(System.String,System.Int32)" />
+ <Member Name="ReleaseTLibAttr(System.IntPtr)" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.LIBFLAGS">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="LIBFLAG_FCONTROL" />
+ <Member MemberType="Field" Name="LIBFLAG_FHASDISKIMAGE" />
+ <Member MemberType="Field" Name="LIBFLAG_FHIDDEN" />
+ <Member MemberType="Field" Name="LIBFLAG_FRESTRICTED" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.PARAMDESC">
+ <Member MemberType="Field" Name="lpVarValue" />
+ <Member MemberType="Field" Name="wParamFlags" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.PARAMFLAG">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="PARAMFLAG_FHASCUSTDATA" />
+ <Member MemberType="Field" Name="PARAMFLAG_FHASDEFAULT" />
+ <Member MemberType="Field" Name="PARAMFLAG_FIN" />
+ <Member MemberType="Field" Name="PARAMFLAG_FLCID" />
+ <Member MemberType="Field" Name="PARAMFLAG_FOPT" />
+ <Member MemberType="Field" Name="PARAMFLAG_FOUT" />
+ <Member MemberType="Field" Name="PARAMFLAG_FRETVAL" />
+ <Member MemberType="Field" Name="PARAMFLAG_NONE" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.SYSKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="SYS_MAC" />
+ <Member MemberType="Field" Name="SYS_WIN16" />
+ <Member MemberType="Field" Name="SYS_WIN32" />
+ <Member MemberType="Field" Name="SYS_WIN64" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.TYPEATTR">
+ <Member MemberType="Field" Name="guid" />
+ <Member MemberType="Field" Name="cbAlignment" />
+ <Member MemberType="Field" Name="cbSizeVft" />
+ <Member MemberType="Field" Name="cFuncs" />
+ <Member MemberType="Field" Name="cImplTypes" />
+ <Member MemberType="Field" Name="cVars" />
+ <Member MemberType="Field" Name="wMajorVerNum" />
+ <Member MemberType="Field" Name="wMinorVerNum" />
+ <Member MemberType="Field" Name="cbSizeInstance" />
+ <Member MemberType="Field" Name="dwReserved" />
+ <Member MemberType="Field" Name="lcid" />
+ <Member MemberType="Field" Name="MEMBER_ID_NIL" />
+ <Member MemberType="Field" Name="memidConstructor" />
+ <Member MemberType="Field" Name="memidDestructor" />
+ <Member MemberType="Field" Name="lpstrSchema" />
+ <Member MemberType="Field" Name="idldescType" />
+ <Member MemberType="Field" Name="tdescAlias" />
+ <Member MemberType="Field" Name="wTypeFlags" />
+ <Member MemberType="Field" Name="typekind" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.TYPEDESC">
+ <Member MemberType="Field" Name="vt" />
+ <Member MemberType="Field" Name="lpValue" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.TYPEFLAGS">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="TYPEFLAG_FAGGREGATABLE" />
+ <Member MemberType="Field" Name="TYPEFLAG_FAPPOBJECT" />
+ <Member MemberType="Field" Name="TYPEFLAG_FCANCREATE" />
+ <Member MemberType="Field" Name="TYPEFLAG_FCONTROL" />
+ <Member MemberType="Field" Name="TYPEFLAG_FDISPATCHABLE" />
+ <Member MemberType="Field" Name="TYPEFLAG_FDUAL" />
+ <Member MemberType="Field" Name="TYPEFLAG_FHIDDEN" />
+ <Member MemberType="Field" Name="TYPEFLAG_FLICENSED" />
+ <Member MemberType="Field" Name="TYPEFLAG_FNONEXTENSIBLE" />
+ <Member MemberType="Field" Name="TYPEFLAG_FOLEAUTOMATION" />
+ <Member MemberType="Field" Name="TYPEFLAG_FPREDECLID" />
+ <Member MemberType="Field" Name="TYPEFLAG_FPROXY" />
+ <Member MemberType="Field" Name="TYPEFLAG_FREPLACEABLE" />
+ <Member MemberType="Field" Name="TYPEFLAG_FRESTRICTED" />
+ <Member MemberType="Field" Name="TYPEFLAG_FREVERSEBIND" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.TYPEKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="TKIND_ALIAS" />
+ <Member MemberType="Field" Name="TKIND_COCLASS" />
+ <Member MemberType="Field" Name="TKIND_DISPATCH" />
+ <Member MemberType="Field" Name="TKIND_ENUM" />
+ <Member MemberType="Field" Name="TKIND_INTERFACE" />
+ <Member MemberType="Field" Name="TKIND_MAX" />
+ <Member MemberType="Field" Name="TKIND_MODULE" />
+ <Member MemberType="Field" Name="TKIND_RECORD" />
+ <Member MemberType="Field" Name="TKIND_UNION" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.TYPELIBATTR">
+ <Member MemberType="Field" Name="guid" />
+ <Member MemberType="Field" Name="wMajorVerNum" />
+ <Member MemberType="Field" Name="wMinorVerNum" />
+ <Member MemberType="Field" Name="lcid" />
+ <Member MemberType="Field" Name="wLibFlags" />
+ <Member MemberType="Field" Name="syskind" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.VARDESC">
+ <Member MemberType="Field" Name="desc" />
+ <Member MemberType="Field" Name="wVarFlags" />
+ <Member MemberType="Field" Name="memid" />
+ <Member MemberType="Field" Name="elemdescVar" />
+ <Member MemberType="Field" Name="varkind" />
+ <Member MemberType="Field" Name="lpstrSchema" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.VARDESC+DESCUNION">
+ <Member MemberType="Field" Name="oInst" />
+ <Member MemberType="Field" Name="lpvarValue" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.VARFLAGS">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VARFLAG_FBINDABLE" />
+ <Member MemberType="Field" Name="VARFLAG_FDEFAULTBIND" />
+ <Member MemberType="Field" Name="VARFLAG_FDEFAULTCOLLELEM" />
+ <Member MemberType="Field" Name="VARFLAG_FDISPLAYBIND" />
+ <Member MemberType="Field" Name="VARFLAG_FHIDDEN" />
+ <Member MemberType="Field" Name="VARFLAG_FIMMEDIATEBIND" />
+ <Member MemberType="Field" Name="VARFLAG_FNONBROWSABLE" />
+ <Member MemberType="Field" Name="VARFLAG_FREADONLY" />
+ <Member MemberType="Field" Name="VARFLAG_FREPLACEABLE" />
+ <Member MemberType="Field" Name="VARFLAG_FREQUESTEDIT" />
+ <Member MemberType="Field" Name="VARFLAG_FRESTRICTED" />
+ <Member MemberType="Field" Name="VARFLAG_FSOURCE" />
+ <Member MemberType="Field" Name="VARFLAG_FUIDEFAULT" />
+ </Type>
+ <Type Name="System.Runtime.InteropServices.ComTypes.VARKIND">
+ <Member MemberType="Field" Name="value__" />
+ <Member MemberType="Field" Name="VAR_CONST" />
+ <Member MemberType="Field" Name="VAR_DISPATCH" />
+ <Member MemberType="Field" Name="VAR_PERINSTANCE" />
+ <Member MemberType="Field" Name="VAR_STATIC" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.StubHelpers">
+ <Member Name="ClearLastError" />
+ <Member Name="SetLastError" />
+ <Member Name="IsQCall(System.IntPtr)" />
+ <Member Name="InitDeclaringType(System.IntPtr)" />
+ <Member Name="GetNDirectTarget(System.IntPtr)" />
+ <Member Name="GetDelegateTarget(System.Delegate,System.IntPtr@)" />
+ <Member Name="ThrowInteropParamException(System.Int32,System.Int32)" />
+ <Member Name="AddToCleanupList(System.StubHelpers.CleanupWorkList@,System.Runtime.InteropServices.SafeHandle)" />
+ <Member Name="DestroyCleanupList(System.StubHelpers.CleanupWorkList@)" />
+ <Member Name="GetHRExceptionObject(System.Int32)" />
+ <Member Name="CreateCustomMarshalerHelper(System.IntPtr,System.Int32,System.IntPtr)" />
+ <Member Name="CheckStringLength(System.Int32)" />
+ <Member Name="DecimalCanonicalizeInternal(System.Decimal@)" />
+ <Member Name="FmtClassUpdateNativeInternal(System.Object,System.Byte*,System.StubHelpers.CleanupWorkList@)" />
+ <Member Name="FmtClassUpdateCLRInternal(System.Object,System.Byte*)" />
+ <Member Name="LayoutDestroyNativeInternal(System.Byte*,System.IntPtr)" />
+ <Member Name="AllocateInternal(System.IntPtr)" />
+ <Member Name="strlen(System.SByte*)" />
+ <Member Name="MarshalToManagedVaListInternal(System.IntPtr,System.IntPtr)" />
+ <Member Name="MarshalToUnmanagedVaListInternal(System.IntPtr,System.UInt32,System.IntPtr)" />
+ <Member Name="CalcVaListSize(System.IntPtr)" />
+ <Member Name="ProfilerBeginTransitionCallback(System.IntPtr,System.IntPtr,System.Object)" /> <!-- EE -->
+ <Member Name="ProfilerEndTransitionCallback(System.IntPtr,System.IntPtr)" /> <!-- EE -->
+ <Member Name="SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle,System.Boolean@)" />
+ <Member Name="SafeHandleRelease(System.Runtime.InteropServices.SafeHandle)" />
+ <Member Name="ValidateObject(System.Object,System.IntPtr,System.Object)" />
+ <Member Name="ValidateByref(System.IntPtr,System.IntPtr,System.Object)" />
+ <Member Name="LogPinnedArgument(System.IntPtr,System.IntPtr)" />
+ <Member Name="GetStubContext" />
+ <Member Name="GetStubContextAddr" Architecture="amd64" />
+ <Member Name="GetStubContextAddr" Architecture="arm64" />
+ <Member Name="ArrayTypeCheck(System.Object,System.Object[])" Condition="FEATURE_ARRAYSTUB_AS_IL" />
+ <Member Name="MulticastDebuggerTraceHelper(System.Object,System.Int32)" Condition="FEATURE_STUBS_AS_IL" />
+ <Member Name="GetCOMHRExceptionObject(System.Int32,System.IntPtr,System.Object)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetCOMHRExceptionObject_WinRT(System.Int32,System.IntPtr,System.Object)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetCOMIPFromRCW(System.Object,System.IntPtr,System.IntPtr@,System.Boolean@)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetCOMIPFromRCW_WinRT(System.Object,System.IntPtr,System.IntPtr@)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetCOMIPFromRCW_WinRTSharedGeneric(System.Object,System.IntPtr,System.IntPtr@)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetCOMIPFromRCW_WinRTDelegate(System.Object,System.IntPtr,System.IntPtr@)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="ShouldCallWinRTInterface(System.Object,System.IntPtr)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="StubRegisterRCW(System.Object)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="StubUnregisterRCW(System.Object)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetDelegateInvokeMethod(System.Delegate)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetWinRTFactoryObject(System.IntPtr)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetWinRTFactoryReturnValue(System.Object,System.IntPtr)" Condition="FEATURE_COMINTEROP" />
+ <Member Name="GetOuterInspectable(System.Object,System.IntPtr)" Condition="FEATURE_COMINTEROP" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.AnsiCharMarshaler">
+ <Member Name="ConvertToNative(System.Char,System.Boolean,System.Boolean)" />
+ <Member Name="ConvertToManaged(System.Byte)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.AnsiBSTRMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.Int32,System.String)" />
+ <Member Name="ConvertToManaged(System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.BSTRMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.String,System.IntPtr)" />
+ <Member Name="ConvertToManaged(System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.CSTRMarshaler">
+ <Member Name="ConvertToNative(System.Int32,System.String,System.IntPtr)" />
+ <Member Name="ConvertToManaged(System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.UTF8Marshaler">
+ <Member Name="ConvertToNative(System.Int32,System.String,System.IntPtr)" />
+ <Member Name="ConvertToManaged(System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.UTF8BufferMarshaler">
+ <Member Name="ConvertToNative(System.Text.StringBuilder,System.IntPtr,System.Int32)" />
+ <Member Name="ConvertToManaged(System.Text.StringBuilder,System.IntPtr)" />
+ </Type>
+ <Type Status="ApiFxInternal" Name="System.StubHelpers.EventArgsMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateNativeNCCEventArgsInstance(System.Int32,System.Object,System.Object,System.Int32,System.Int32)"/>
+ <Member Name="CreateNativePCEventArgsInstance(System.String)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.HResultExceptionMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.Exception)" />
+ <Member Name="ConvertToManaged(System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.KeyValuePairMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;@)" />
+ <Member Name="ConvertToManaged&lt;K,V&gt;(System.IntPtr)" />
+ <Member Name="ConvertToManagedBox&lt;K,V&gt;(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.MngdSafeArrayMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateMarshaler(System.IntPtr,System.IntPtr,System.Int32,System.Int32)" />
+ <Member Name="ConvertSpaceToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative(System.IntPtr,System.Object@,System.IntPtr,System.Object)" />
+ <Member Name="ConvertSpaceToManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.MngdHiddenLengthArrayMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="CreateMarshaler(System.IntPtr,System.IntPtr,System.IntPtr,System.UInt16)" />
+ <Member Name="ConvertSpaceToManaged(System.IntPtr,System.Object@,System.IntPtr,System.Int32)" />
+ <Member Name="ConvertContentsToManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertSpaceToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ClearNativeContents(System.IntPtr,System.IntPtr,System.Int32)" />
+ <Member Name="ClearNativeContents_Type(System.IntPtr,System.Int32)" />
+ <Member Name="ConvertContentsToManaged_DateTime(System.DateTimeOffset[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged_Type(System.Type[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged_Exception(System.Exception[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged_Nullable&lt;T&gt;(System.Nullable&lt;T&gt;[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged_KeyValuePair&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative_DateTime(System.DateTimeOffset[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative_Type(System.Type[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative_Exception(System.Exception[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative_Nullable&lt;T&gt;(System.Nullable&lt;T&gt;[]@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative_KeyValuePair&lt;K,V&gt;(System.Collections.Generic.KeyValuePair&lt;K,V&gt;[]@,System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.NullableMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative&lt;T&gt;(System.Nullable&lt;T&gt;@)" />
+ <Member Name="ConvertToManaged&lt;T&gt;(System.IntPtr)" />
+ <Member Name="ConvertToManagedRetVoid&lt;T&gt;(System.IntPtr,System.Nullable&lt;T&gt;@)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.WSTRBufferMarshaler">
+ <Member Name="ConvertToNative(System.String)" />
+ <Member Name="ConvertToManaged(System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.ValueClassMarshaler">
+ <Member Name="ConvertToNative(System.IntPtr,System.IntPtr,System.IntPtr,System.StubHelpers.CleanupWorkList@)" />
+ <Member Name="ConvertToManaged(System.IntPtr,System.IntPtr,System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr,System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.DateMarshaler">
+ <Member Name="ConvertToNative(System.DateTime)" />
+ <Member Name="ConvertToManaged(System.Double)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.DateTimeOffsetMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.DateTimeOffset@,System.StubHelpers.DateTimeNative@)"/>
+ <Member Name="ConvertToManaged(System.DateTimeOffset@,System.StubHelpers.DateTimeNative@)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.HStringMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.String)"/>
+ <Member Name="ConvertToNativeReference(System.String,System.Runtime.InteropServices.WindowsRuntime.HSTRING_HEADER*)"/>
+ <Member Name="ConvertToManaged(System.IntPtr)"/>
+ <Member Name="ClearNative(System.IntPtr)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.ObjectMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.Object,System.IntPtr)"/>
+ <Member Name="ConvertToManaged(System.IntPtr)"/>
+ <Member Name="ClearNative(System.IntPtr)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.InterfaceMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="ConvertToNative(System.Object,System.IntPtr,System.IntPtr,System.Int32)"/>
+ <Member Name="ConvertToManaged(System.IntPtr,System.IntPtr,System.IntPtr,System.Int32)"/>
+ <Member Name="ClearNative(System.IntPtr)"/>
+ <Member Name="ConvertToManagedWithoutUnboxing(System.IntPtr)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.UriMarshaler" Condition="FEATURE_COMINTEROP">
+ <Member Name="GetRawUriFromNative(System.IntPtr)"/>
+ <Member Name="CreateNativeUriInstance(System.String)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.VBByValStrMarshaler">
+ <Member Name="ConvertToNative(System.String,System.Boolean,System.Boolean,System.Int32@)" />
+ <Member Name="ConvertToManaged(System.IntPtr,System.Int32)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.MngdNativeArrayMarshaler">
+ <Member Name="CreateMarshaler(System.IntPtr,System.IntPtr,System.Int32)" />
+ <Member Name="ConvertSpaceToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertSpaceToManaged(System.IntPtr,System.Object@,System.IntPtr,System.Int32)" />
+ <Member Name="ConvertContentsToManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr,System.IntPtr,System.Int32)" />
+ <Member Name="ClearNativeContents(System.IntPtr,System.IntPtr,System.Int32)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.MngdRefCustomMarshaler">
+ <Member Name="CreateMarshaler(System.IntPtr,System.IntPtr)" />
+ <Member Name="ConvertContentsToNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ConvertContentsToManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr,System.Object@,System.IntPtr)" />
+ <Member Name="ClearManaged(System.IntPtr,System.Object@,System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.AsAnyMarshaler">
+ <Member Name="#ctor(System.IntPtr)" />
+ <Member Name="ConvertToNative(System.Object,System.Int32)" />
+ <Member Name="ConvertToManaged(System.Object,System.IntPtr)" />
+ <Member Name="ClearNative(System.IntPtr)" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.NativeVariant" />
+ <Type Status="ImplRoot" Name="Microsoft.Win32.Win32Native+OSVERSIONINFOEX">
+ <Member MemberType="Field" Name="OSVersionInfoSize" />
+ <Member MemberType="Field" Name="MajorVersion" />
+ <Member MemberType="Field" Name="MinorVersion" />
+ <Member MemberType="Field" Name="BuildNumber" />
+ <Member MemberType="Field" Name="PlatformId" />
+ <Member MemberType="Field" Name="CSDVersion" />
+ <Member MemberType="Field" Name="ServicePackMajor" />
+ <Member MemberType="Field" Name="ServicePackMinor" />
+ <Member MemberType="Field" Name="SuiteMask" />
+ <Member MemberType="Field" Name="ProductType" />
+ <Member MemberType="Field" Name="Reserved" />
+ <Member Name="#ctor" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.StubHelpers.TypeNameNative" Condition="FEATURE_COMINTEROP">
+ <Member MemberType="Field" Name="typeName" />
+ <Member MemberType="Field" Name="typeKind" />
+ </Type>
+ <Type Status="ImplRoot" Name="Microsoft.Win32.Win32Native+WIN32_FIND_DATA">
+ <Member MemberType="Field" Name="cFileName" />
+ <Member MemberType="Field" Name="dwFileAttributes" />
+ <Member MemberType="Field" Name="dwReserved0" />
+ <Member MemberType="Field" Name="dwReserved1" />
+ <Member MemberType="Field" Name="ftCreationTime_dwHighDateTime" />
+ <Member MemberType="Field" Name="ftCreationTime_dwLowDateTime" />
+ <Member MemberType="Field" Name="ftLastAccessTime_dwHighDateTime" />
+ <Member MemberType="Field" Name="ftLastAccessTime_dwLowDateTime" />
+ <Member MemberType="Field" Name="ftLastWriteTime_dwHighDateTime" />
+ <Member MemberType="Field" Name="ftLastWriteTime_dwLowDateTime" />
+ <Member MemberType="Field" Name="nFileSizeHigh" />
+ <Member MemberType="Field" Name="nFileSizeLow" />
+ <Member MemberType="Field" Name="cAlternateFileName" />
+ <Member Name="#ctor" />
+ </Type>
+ <!-- PFX Types -->
+ <!-- System.Threading.Tasks namespace -->
+ <Type Name="System.Threading.Tasks.TaskScheduler">
+ <Member Name="#ctor" />
+ <Member Name="TryExecuteTaskInline(System.Threading.Tasks.Task,System.Boolean)" />
+ <Member Name="TryExecuteTask(System.Threading.Tasks.Task)" />
+ <Member Name="get_MaximumConcurrencyLevel" />
+ <Member Name="get_Default" />
+ <Member Name="get_Current" />
+ <Member Name="get_Id" />
+ <Member Name="QueueTask(System.Threading.Tasks.Task)" />
+ <Member Name="TryDequeue(System.Threading.Tasks.Task)" />
+ <Member Name="GetScheduledTasks" />
+ <Member Name="FromCurrentSynchronizationContext" />
+ <Member Status="ImplRoot" Name="GetTaskSchedulersForDebugger" />
+ <Member Status="ImplRoot" Name="GetScheduledTasksForDebugger" />
+ <Member MemberType="Event" Name="UnobservedTaskException" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.Tasks.TaskScheduler+SystemThreadingTasks_TaskSchedulerDebugView">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.Tasks.TaskScheduler)" />
+ <Member Status="ImplRoot" Name="get_ScheduledTasks" />
+ <Member Status="ImplRoot" Name="get_Id" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskSchedulerException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Exception)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.Tasks.Task">
+ <Member Name="#ctor(System.Action)" />
+ <Member Name="#ctor(System.Action,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Action&lt;System.Object&gt;,System.Object)" />
+ <Member Name="#ctor(System.Action,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Action&lt;System.Object&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Action,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Action&lt;System.Object&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Action&lt;System.Object&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&gt;)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task,System.Object&gt;,System.Object)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task,System.Object&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task,System.Object&gt;,System.Object,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task,System.Object&gt;,System.Object,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task,System.Object&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,TResult&gt;)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,System.Object,TResult&gt;,System.Object)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,System.Object,TResult&gt;,System.Object,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,System.Object,TResult&gt;,System.Object,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task,System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="FromResult&lt;TResult&gt;(TResult)" />
+ <Member Name="FromException(System.Exception)" />
+ <Member Name="FromException&lt;TResult&gt;(System.Exception)" />
+ <Member Name="FromCanceled(System.Threading.CancellationToken)" />
+ <Member Name="FromCanceled&lt;TResult&gt;(System.Threading.CancellationToken)" />
+ <Member Status="ApiFxInternal" Name="FromCancellation(System.Threading.CancellationToken)" />
+ <Member Status="ApiFxInternal" Name="FromCancellation&lt;TResult&gt;(System.Threading.CancellationToken)" />
+ <Member Name="Run(System.Action)" />
+ <Member Name="Run(System.Action,System.Threading.CancellationToken)" />
+ <Member Name="Run&lt;TResult&gt;(System.Func&lt;TResult&gt;)" />
+ <Member Name="Run&lt;TResult&gt;(System.Func&lt;TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="Run(System.Func&lt;System.Threading.Tasks.Task&gt;)" />
+ <Member Name="Run(System.Func&lt;System.Threading.Tasks.Task&gt;,System.Threading.CancellationToken)" />
+ <Member Name="Run&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;)" />
+ <Member Name="Run&lt;TResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;,System.Threading.CancellationToken)" />
+ <Member Name="Delay(System.TimeSpan)" />
+ <Member Name="Delay(System.TimeSpan,System.Threading.CancellationToken)" />
+ <Member Name="Delay(System.Int32)" />
+ <Member Name="Delay(System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="WhenAll(System.Collections.Generic.IEnumerable&lt;System.Threading.Tasks.Task&gt;)" />
+ <Member Name="WhenAll(System.Threading.Tasks.Task[])" />
+ <Member Name="WhenAll&lt;TResult&gt;(System.Collections.Generic.IEnumerable&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;)" />
+ <Member Name="WhenAll&lt;TResult&gt;(System.Threading.Tasks.Task&lt;TResult&gt;[])" />
+ <Member Name="WhenAny(System.Collections.Generic.IEnumerable&lt;System.Threading.Tasks.Task&gt;)" />
+ <Member Name="WhenAny(System.Threading.Tasks.Task[])" />
+ <Member Name="WhenAny&lt;TResult&gt;(System.Collections.Generic.IEnumerable&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;)" />
+ <Member Name="WhenAny&lt;TResult&gt;(System.Threading.Tasks.Task&lt;TResult&gt;[])" />
+ <Member Name="Dispose" />
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="RunSynchronously" />
+ <Member Name="RunSynchronously(System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="Start" />
+ <Member Name="Start(System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="Wait" />
+ <Member Name="Wait(System.Int32)" />
+ <Member Name="Wait(System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.TimeSpan)" />
+ <Member Name="Wait(System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="WaitAll(System.Threading.Tasks.Task[])" />
+ <Member Name="WaitAll(System.Threading.Tasks.Task[],System.Int32)" />
+ <Member Name="WaitAll(System.Threading.Tasks.Task[],System.Threading.CancellationToken)" />
+ <Member Name="WaitAll(System.Threading.Tasks.Task[],System.TimeSpan)" />
+ <Member Name="WaitAll(System.Threading.Tasks.Task[],System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="WaitAny(System.Threading.Tasks.Task[])" />
+ <Member Name="WaitAny(System.Threading.Tasks.Task[],System.Int32)" />
+ <Member Name="WaitAny(System.Threading.Tasks.Task[],System.Threading.CancellationToken)" />
+ <Member Name="WaitAny(System.Threading.Tasks.Task[],System.TimeSpan)" />
+ <Member Name="WaitAny(System.Threading.Tasks.Task[],System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="GetAwaiter" />
+ <Member Name="ConfigureAwait(System.Boolean)" />
+ <Member Name="Yield" />
+ <Member Name="get_AsyncState" />
+ <Member Name="get_CompletedTask" />
+ <Member Name="get_CreationOptions" />
+ <Member Name="get_CurrentId" />
+ <Member Name="get_Exception" />
+ <Member Name="get_Factory" />
+ <Member Name="get_Id" />
+ <Member Name="get_IsCanceled" />
+ <Member Name="get_IsCompleted" />
+ <Member Name="get_IsFaulted" />
+ <Member Name="get_Status" />
+ <Member Status="ImplRoot" Name="get_DebuggerDisplayMethodDescription" />
+ <!--Internal members exposed to be used by Unwrap extension method in System.Core.dll-->
+ <Member Status="ImplRoot" Name="CreateUnwrapPromise&lt;TResult&gt;(System.Threading.Tasks.Task,System.Boolean)" />
+ <Member Status="ImplRoot" Name="NotifyDebuggerOfWaitCompletion" />
+ <Member Status="ImplRoot" Name="SetNotificationForWaitCompletion(System.Boolean)" />
+ <!--Internal helper members exposed to be used by VS Debugger-->
+ <Member Status="ImplRoot" Name="GetDelegateContinuationsForDebugger" />
+ <Member Status="ImplRoot" Name="GetActiveTaskFromId(System.Int32)" />
+ <Member Status="ImplRoot" Name="GetActiveTasks" />
+ <Member Status="ImplRoot" Name="get_ParentForDebugger" />
+ <Member Status="ImplRoot" Name="get_StateFlagsForDebugger" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.Tasks.SystemThreadingTasks_TaskDebugView">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.Tasks.Task)" />
+ <Member Status="ImplRoot" Name="get_AsyncState" />
+ <Member Status="ImplRoot" Name="get_CreationOptions" />
+ <Member Status="ImplRoot" Name="get_Exception" />
+ <Member Status="ImplRoot" Name="get_Id" />
+ <Member Status="ImplRoot" Name="get_Status" />
+ <Member Status="ImplRoot" Name="get_CancellationPending" />
+ </Type>
+ <Type Name="System.Threading.Tasks.Task&lt;TResult&gt;">
+ <Member Name="#ctor(System.Func&lt;TResult&gt;)" />
+ <Member Name="#ctor(System.Func&lt;TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Func&lt;System.Object,TResult&gt;,System.Object)" />
+ <Member Name="#ctor(System.Func&lt;TResult&gt;,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Func&lt;TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object&gt;,System.Object)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object&gt;,System.Object,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object&gt;,System.Object,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith(System.Action&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,TNewResult&gt;)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,TNewResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,TNewResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,TNewResult&gt;,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,TNewResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object,TNewResult&gt;,System.Object)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object,TNewResult&gt;,System.Object,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object,TNewResult&gt;,System.Object,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object,TNewResult&gt;,System.Object,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWith&lt;TNewResult&gt;(System.Func&lt;System.Threading.Tasks.Task&lt;TResult&gt;,System.Object,TNewResult&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ConfigureAwait(System.Boolean)" />
+ <Member Name="GetAwaiter" />
+ <Member Name="get_Factory" />
+ <Member Name="get_Result" />
+ <!-- DebuggerDisplayMethodDescription ysed by the debugger display-->
+ <Member Status="ImplRoot" Name="get_DebuggerDisplayMethodDescription" />
+ <Member Status="ImplRoot" Name="get_DebuggerDisplayResultDescription" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.Tasks.SystemThreadingTasks_FutureDebugView&lt;TResult&gt;">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.Tasks.Task&lt;TResult&gt;)" />
+ <Member Status="ImplRoot" Name="get_AsyncState" />
+ <Member Status="ImplRoot" Name="get_CreationOptions" />
+ <Member Status="ImplRoot" Name="get_Exception" />
+ <Member Status="ImplRoot" Name="get_Id" />
+ <Member Status="ImplRoot" Name="get_Status" />
+ <Member Status="ImplRoot" Name="get_Result" />
+ <Member Status="ImplRoot" Name="get_CancellationPending" />
+ </Type>
+ <Type Name="System.Threading.Tasks.VoidTaskResult"/>
+ <Type Name="System.Threading.Tasks.TaskCanceledException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Threading.Tasks.Task)" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_Task" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskCompletionSource&lt;TResult&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Object)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="#ctor(System.Object,System.Threading.Tasks.TaskCreationOptions)" />
+ <Member Name="SetCanceled" />
+ <Member Name="SetException(System.Exception)" />
+ <Member Name="SetException(System.Collections.Generic.IEnumerable&lt;System.Exception&gt;)" />
+ <Member Name="SetResult(TResult)" />
+ <Member Name="TrySetCanceled" />
+ <Member Name="TrySetCanceled(System.Threading.CancellationToken)" />
+ <Member Name="TrySetException(System.Exception)" />
+ <Member Name="TrySetException(System.Collections.Generic.IEnumerable&lt;System.Exception&gt;)" />
+ <Member Name="TrySetResult(TResult)" />
+ <Member Name="get_Task" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskFactory">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="#ctor(System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task[]&gt;)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task[]&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task[]&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task[]&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;)" />
+ <Member Name="ContinueWhenAll&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[]&gt;)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[]&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[]&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[]&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task&gt;)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Action&lt;System.Threading.Tasks.Task&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;)" />
+ <Member Name="ContinueWhenAny&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny&lt;TResult&gt;(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;&gt;)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Action&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult,TResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="FromAsync(System.IAsyncResult,System.Action&lt;System.IAsyncResult&gt;)"/>
+ <Member Name="FromAsync(System.IAsyncResult,System.Action&lt;System.IAsyncResult&gt;,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync(System.IAsyncResult,System.Action&lt;System.IAsyncResult&gt;,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="FromAsync&lt;TResult&gt;(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;)"/>
+ <Member Name="FromAsync&lt;TResult&gt;(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TResult&gt;(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="FromAsync(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,System.Object)"/>
+ <Member Name="FromAsync(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TResult&gt;(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Object)"/>
+ <Member Name="FromAsync&lt;TResult&gt;(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TResult&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TResult&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,TArg2,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,TArg2,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TResult&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TResult&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,TArg2,TArg3,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Action&lt;System.IAsyncResult&gt;,TArg1,TArg2,TArg3,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3,TResult&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,TArg3,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3,TResult&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,TArg3,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Action)"/>
+ <Member Name="StartNew(System.Action,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew(System.Action,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Action,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="StartNew(System.Action&lt;System.Object&gt;,System.Object)"/>
+ <Member Name="StartNew(System.Action&lt;System.Object&gt;,System.Object,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew(System.Action&lt;System.Object&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Action&lt;System.Object&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;TResult&gt;)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;TResult&gt;,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;TResult&gt;,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;System.Object,TResult&gt;,System.Object)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew&lt;TResult&gt;(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="get_CancellationToken" />
+ <Member Name="get_CreationOptions" />
+ <Member Name="get_ContinuationOptions" />
+ <Member Name="get_Scheduler" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskFactory&lt;TResult&gt;">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Threading.CancellationToken)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="#ctor(System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task[],TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAll&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny(System.Threading.Tasks.Task[],System.Func&lt;System.Threading.Tasks.Task,TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.CancellationToken)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.Tasks.TaskContinuationOptions)" />
+ <Member Name="ContinueWhenAny&lt;TAntecedentResult&gt;(System.Threading.Tasks.Task&lt;TAntecedentResult&gt;[],System.Func&lt;System.Threading.Tasks.Task&lt;TAntecedentResult&gt;,TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskContinuationOptions,System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="FromAsync(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;)"/>
+ <Member Name="FromAsync(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync(System.IAsyncResult,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="FromAsync(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Object)"/>
+ <Member Name="FromAsync(System.Func&lt;System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1&gt;(System.Func&lt;TArg1,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2&gt;(System.Func&lt;TArg1,TArg2,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,TArg3,System.Object)"/>
+ <Member Name="FromAsync&lt;TArg1,TArg2,TArg3&gt;(System.Func&lt;TArg1,TArg2,TArg3,System.AsyncCallback,System.Object,System.IAsyncResult&gt;,System.Func&lt;System.IAsyncResult,TResult&gt;,TArg1,TArg2,TArg3,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Func&lt;TResult&gt;)"/>
+ <Member Name="StartNew(System.Func&lt;TResult&gt;,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew(System.Func&lt;TResult&gt;,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Func&lt;TResult&gt;,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="StartNew(System.Func&lt;System.Object,TResult&gt;,System.Object)"/>
+ <Member Name="StartNew(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken)"/>
+ <Member Name="StartNew(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.Tasks.TaskCreationOptions)"/>
+ <Member Name="StartNew(System.Func&lt;System.Object,TResult&gt;,System.Object,System.Threading.CancellationToken,System.Threading.Tasks.TaskCreationOptions,System.Threading.Tasks.TaskScheduler)"/>
+ <Member Name="get_CancellationToken" />
+ <Member Name="get_CreationOptions" />
+ <Member Name="get_ContinuationOptions" />
+ <Member Name="get_Scheduler" />
+ </Type>
+ <Type Name="System.Threading.Tasks.UnobservedTaskExceptionEventArgs">
+ <Member Name="#ctor(System.AggregateException)" />
+ <Member Name="SetObserved" />
+ <Member Name="get_Exception" />
+ <Member Name="get_Observed" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskContinuationOptions">
+ <Member MemberType="Field" Name="AttachedToParent" />
+ <Member MemberType="Field" Name="ExecuteSynchronously" />
+ <Member MemberType="Field" Name="LongRunning" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="NotOnCanceled" />
+ <Member MemberType="Field" Name="NotOnFaulted" />
+ <Member MemberType="Field" Name="NotOnRanToCompletion" />
+ <Member MemberType="Field" Name="OnlyOnCanceled" />
+ <Member MemberType="Field" Name="OnlyOnFaulted" />
+ <Member MemberType="Field" Name="OnlyOnRanToCompletion" />
+ <Member MemberType="Field" Name="PreferFairness" />
+ <Member MemberType="Field" Name="DenyChildAttach" />
+ <Member MemberType="Field" Name="HideScheduler" />
+ <Member MemberType="Field" Name="LazyCancellation" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskCreationOptions">
+ <Member MemberType="Field" Name="AttachedToParent" />
+ <Member MemberType="Field" Name="LongRunning" />
+ <Member MemberType="Field" Name="None" />
+ <Member MemberType="Field" Name="PreferFairness" />
+ <Member MemberType="Field" Name="DenyChildAttach" />
+ <Member MemberType="Field" Name="HideScheduler" />
+ <Member MemberType="Field" Name="RunContinuationsAsynchronously" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TaskStatus">
+ <Member MemberType="Field" Name="Created" />
+ <Member MemberType="Field" Name="WaitingForActivation" />
+ <Member MemberType="Field" Name="WaitingToRun" />
+ <Member MemberType="Field" Name="Running" />
+ <Member MemberType="Field" Name="WaitingForChildrenToComplete" />
+ <Member MemberType="Field" Name="RanToCompletion" />
+ <Member MemberType="Field" Name="Canceled" />
+ <Member MemberType="Field" Name="Faulted" />
+ <Member MemberType="Field" Name="value__" />
+ </Type>
+ <Type Name="System.Threading.Tasks.ConcurrentExclusiveSchedulerPair">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskScheduler)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskScheduler,System.Int32)" />
+ <Member Name="#ctor(System.Threading.Tasks.TaskScheduler,System.Int32,System.Int32)" />
+ <Member Name="Complete" />
+ <Member MemberType="Property" Name="Completion" />
+ <Member MemberType="Property" Name="ConcurrentScheduler" />
+ <Member MemberType="Property" Name="ExclusiveScheduler" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.Tasks.ConcurrentExclusiveSchedulerPair+DebugView">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.Tasks.ConcurrentExclusiveSchedulerPair)" />
+ <Member Status="ImplRoot" MemberType="Property" Name="Mode" />
+ <Member Status="ImplRoot" MemberType="Property" Name="ScheduledExclusive" />
+ <Member Status="ImplRoot" MemberType="Property" Name="ScheduledConcurrent" />
+ <Member Status="ImplRoot" MemberType="Property" Name="CurrentlyExecutingTaskCount" />
+ <Member Status="ImplRoot" MemberType="Property" Name="TargetScheduler" />
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.Tasks.ConcurrentExclusiveSchedulerPair+ConcurrentExclusiveTaskScheduler+DebugView">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.Tasks.ConcurrentExclusiveSchedulerPair+ConcurrentExclusiveTaskScheduler)" />
+ <Member Status="ImplRoot" MemberType="Property" Name="MaximumConcurrencyLevel" />
+ <Member Status="ImplRoot" MemberType="Property" Name="ScheduledTasks" />
+ <Member Status="ImplRoot" MemberType="Property" Name="SchedulerPair" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TplEtwProvider+Tasks">
+ <Member MemberType="Field" Name="Loop" />
+ <Member MemberType="Field" Name="Invoke" />
+ <Member MemberType="Field" Name="TaskExecute" />
+ <Member MemberType="Field" Name="TaskWait" />
+ <Member MemberType="Field" Name="ForkJoin" />
+ <Member MemberType="Field" Name="TaskScheduled" />
+ <Member MemberType="Field" Name="AwaitTaskContinuationScheduled" />
+ </Type>
+ <Type Name="System.Threading.Tasks.TplEtwProvider+Keywords">
+ <Member MemberType="Field" Name="TaskTransfer" />
+ <Member MemberType="Field" Name="Tasks" />
+ <Member MemberType="Field" Name="Parallel" />
+ </Type>
+
+ <!-- System.Runtime.CompilerServices namespace -->
+ <Type Name="System.Runtime.CompilerServices.TaskAwaiter">
+ <Member Name="get_IsCompleted" />
+ <Member Name="OnCompleted(System.Action)" />
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ <Member Name="GetResult" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.TaskAwaiter&lt;TResult&gt;">
+ <Member Name="get_IsCompleted" />
+ <Member Name="OnCompleted(System.Action)" />
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ <Member Name="GetResult" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConfiguredTaskAwaitable">
+ <Member Name="GetAwaiter" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter">
+ <Member Name="get_IsCompleted" />
+ <Member Name="OnCompleted(System.Action)" />
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ <Member Name="GetResult" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConfiguredTaskAwaitable&lt;TResult&gt;">
+ <Member Name="GetAwaiter" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ConfiguredTaskAwaitable&lt;TResult&gt;+ConfiguredTaskAwaiter">
+ <Member Name="get_IsCompleted" />
+ <Member Name="OnCompleted(System.Action)" />
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ <Member Name="GetResult" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.INotifyCompletion">
+ <Member Name="OnCompleted(System.Action)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.ICriticalNotifyCompletion">
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.YieldAwaitable">
+ <Member Name="GetAwaiter" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.YieldAwaitable+YieldAwaiter">
+ <Member Name="get_IsCompleted" />
+ <Member Name="OnCompleted(System.Action)" />
+ <Member Name="UnsafeOnCompleted(System.Action)" />
+ <Member Name="GetResult" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.IAsyncStateMachine">
+ <Member Name="MoveNext" />
+ <Member Name="SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.AsyncVoidMethodBuilder">
+ <Member Name="Create" />
+ <Member Name="Start&lt;TStateMachine&gt;(TStateMachine@)" />
+ <Member Name="SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" />
+ <Member Name="AwaitOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="AwaitUnsafeOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="SetResult" />
+ <Member Name="SetException(System.Exception)" />
+ <!-- These are required by the debugger team. Adding to the model file to prevent inadvertant thinning -->
+ <Member Status="ImplRoot" MemberType="Property" Name="ObjectIdForDebugger" />
+ <Member Status="ImplRoot" Name="get_ObjectIdForDebugger" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.AsyncTaskMethodBuilder">
+ <Member Name="Create" />
+ <Member Name="Start&lt;TStateMachine&gt;(TStateMachine@)" />
+ <Member Name="SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" />
+ <Member Name="AwaitOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="AwaitUnsafeOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="SetResult" />
+ <Member Name="SetException(System.Exception)" />
+ <Member Name="get_Task" />
+ <!-- These are required by the debugger team. Adding to the model file to prevent inadvertant thinning -->
+ <Member Status="ImplRoot" MemberType="Property" Name="ObjectIdForDebugger" />
+ <Member Status="ImplRoot" Name="get_ObjectIdForDebugger" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_builder" />
+ </Type>
+ <Type Name="System.Runtime.CompilerServices.AsyncTaskMethodBuilder&lt;TResult&gt;" >
+ <Member Name="Create" />
+ <Member Name="Start&lt;TStateMachine&gt;(TStateMachine@)" />
+ <Member Name="SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" />
+ <Member Name="AwaitOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="AwaitUnsafeOnCompleted&lt;TAwaiter,TStateMachine&gt;(TAwaiter@,TStateMachine@)" />
+ <Member Name="SetResult(TResult)" />
+ <Member Name="SetException(System.Exception)" />
+ <Member Name="get_Task" />
+ <!-- These are required by the debugger team. Adding to the model file to prevent inadvertant thinning -->
+ <Member Status="ImplRoot" MemberType="Property" Name="ObjectIdForDebugger" />
+ <Member Status="ImplRoot" Name="get_ObjectIdForDebugger" />
+ <Member Status="ImplRoot" MemberType="Field" Name="m_task" />
+ </Type>
+
+ <!-- System namespace -->
+ <Type Name="System.AggregateException">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.Collections.Generic.IEnumerable&lt;System.Exception&gt;)"/>
+ <Member Name="#ctor(System.Exception[])"/>
+ <Member Name="#ctor(System.String)"/>
+ <Member Name="#ctor(System.String,System.Collections.Generic.IEnumerable&lt;System.Exception&gt;)"/>
+ <Member Name="#ctor(System.String,System.Exception[])"/>
+ <Member Name="#ctor(System.String,System.Collections.Generic.IList&lt;System.Exception&gt;)"/>
+ <Member Name="#ctor(System.String,System.Exception)"/>
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ <Member Name="get_InnerExceptions" />
+ <Member Name="Handle(System.Func&lt;System.Exception,System.Boolean&gt;)"/>
+ <Member Name="Flatten"/>
+ <Member Name="GetBaseException"/>
+ <Member Name="ToString"/>
+ </Type>
+ <!-- System.Threading namespace -->
+ <Type Name="System.Threading.AsyncLocal&lt;T&gt;">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.Action&lt;System.Threading.AsyncLocalValueChangedArgs&lt;T&gt;&gt;)"/>
+ <Member Name="get_Value"/>
+ <Member Name="set_Value(T)"/>
+ </Type>
+ <Type Name="System.Threading.AsyncLocalValueChangedArgs&lt;T&gt;">
+ <Member Name="get_PreviousValue"/>
+ <Member Name="get_CurrentValue"/>
+ <Member Name="get_ThreadContextChanged"/>
+ </Type>
+ <Type Name="System.Threading.ExecutionContext">
+ <Member Name="Capture" />
+ <Member Name="Run(System.Threading.ExecutionContext,System.Threading.ContextCallback,System.Object)"/>
+ </Type>
+ <Type Name="System.Threading.CancellationToken">
+ <Member Name="#ctor(System.Boolean)"/>
+ <Member Name="get_None" />
+ <Member Name="get_IsCancellationRequested" />
+ <Member Name="get_CanBeCanceled" />
+ <Member Name="get_WaitHandle" />
+ <Member Name="Register(System.Action)" />
+ <Member Name="Register(System.Action,System.Boolean)" />
+ <Member Name="Register(System.Action&lt;System.Object&gt;,System.Object)" />
+ <Member Name="Register(System.Action&lt;System.Object&gt;,System.Object,System.Boolean)" />
+ <Member Name="Equals(System.Threading.CancellationToken)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Threading.CancellationToken,System.Threading.CancellationToken)" />
+ <Member Name="op_Inequality(System.Threading.CancellationToken,System.Threading.CancellationToken)" />
+ <Member Name="ThrowIfCancellationRequested" />
+ </Type>
+ <Type Name="System.Threading.CancellationTokenSource">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.TimeSpan)" />
+ <Member Name="#ctor(System.Int32)" />
+ <Member Name="Cancel"/>
+ <Member Name="Cancel(System.Boolean)"/>
+ <Member Name="CancelAfter(System.TimeSpan)" />
+ <Member Name="CancelAfter(System.Int32)" />
+ <Member Name="CreateLinkedTokenSource(System.Threading.CancellationToken,System.Threading.CancellationToken)"/>
+ <Member Name="CreateLinkedTokenSource(System.Threading.CancellationToken[])"/>
+ <Member Name="Dispose"/>
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="get_Token"/>
+ <Member Name="get_IsCancellationRequested"/>
+ <Member Status="ImplRoot" Name="get_CallbackCount" Condition="DEBUG"/>
+ </Type>
+ <Type Name="System.Threading.CancellationTokenRegistration">
+ <Member Name="Dispose"/>
+ <Member Name="Equals(System.Threading.CancellationTokenRegistration)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="op_Equality(System.Threading.CancellationTokenRegistration,System.Threading.CancellationTokenRegistration)" />
+ <Member Name="op_Inequality(System.Threading.CancellationTokenRegistration,System.Threading.CancellationTokenRegistration)" />
+ </Type>
+ <Type Name="System.Threading.SpinWait">
+ <Member Name="SpinOnce"/>
+ <Member Name="Reset" />
+ <Member Name="get_Count" />
+ <Member Name="get_NextSpinWillYield" />
+ <Member Name="SpinUntil(System.Func&lt;System.Boolean&gt;)" />
+ <Member Name="SpinUntil(System.Func&lt;System.Boolean&gt;,System.TimeSpan)" />
+ <Member Name="SpinUntil(System.Func&lt;System.Boolean&gt;,System.Int32)" />
+ </Type>
+ <Type Name="System.Threading.SpinLock">
+ <Member Name="#ctor(System.Boolean)"/>
+ <Member Name="Enter(System.Boolean@)" />
+ <Member Name="TryEnter(System.Boolean@)" />
+ <Member Name="TryEnter(System.TimeSpan,System.Boolean@)" />
+ <Member Name="TryEnter(System.Int32,System.Boolean@)" />
+ <Member Name="Exit" />
+ <Member Name="Exit(System.Boolean)" />
+ <Member Name="get_IsHeld"/>
+ <Member Name="get_IsHeldByCurrentThread"/>
+ <Member Name="get_IsThreadOwnerTrackingEnabled"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.SpinLock+SystemThreading_SpinLockDebugView">
+ <Member Status="ImplRoot" Name="#ctor(System.Threading.SpinLock)"/>
+ <Member Status="ImplRoot" Name="get_IsHeld"/>
+ <Member Status="ImplRoot" Name="get_IsHeldByCurrentThread"/>
+ <Member Status="ImplRoot" Name="get_OwnerThreadID"/>
+ </Type>
+ <Type Name="System.Threading.ManualResetEventSlim">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.Boolean)"/>
+ <Member Name="#ctor(System.Boolean,System.Int32)"/>
+ <Member Name="Dispose"/>
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Set" />
+ <Member Name="Reset" />
+ <Member Name="Wait" />
+ <Member Name="Wait(System.TimeSpan)" />
+ <Member Name="Wait(System.Int32)" />
+ <Member Name="Wait(System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.TimeSpan,System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="get_IsSet"/>
+ <Member Name="get_SpinCount"/>
+ <Member Name="get_WaitHandle"/>
+ </Type>
+ <Type Name="System.Threading.CountdownEvent">
+ <Member Name="#ctor(System.Int32)"/>
+ <Member Name="AddCount"/>
+ <Member Name="AddCount(System.Int32)"/>
+ <Member Name="Dispose"/>
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Reset" />
+ <Member Name="Reset(System.Int32)" />
+ <Member Name="Signal" />
+ <Member Name="Signal(System.Int32)" />
+ <Member Name="TryAddCount"/>
+ <Member Name="TryAddCount(System.Int32)"/>
+ <Member Name="Wait" />
+ <Member Name="Wait(System.TimeSpan)" />
+ <Member Name="Wait(System.Int32)" />
+ <Member Name="Wait(System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.TimeSpan,System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="get_CurrentCount"/>
+ <Member Name="get_InitialCount"/>
+ <Member Name="get_IsSet"/>
+ <Member Name="get_WaitHandle"/>
+ </Type>
+ <Type Name="System.Threading.Semaphore">
+ <Member Name="#ctor(System.Int32,System.Int32)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.String)" />
+ <Member Name="#ctor(System.Int32,System.Int32,System.String,System.Boolean@)" />
+ <Member Name="OpenExisting(System.String)" />
+ <Member Name="Release" />
+ <Member Name="Release(System.Int32)" />
+ <Member Name="TryOpenExisting(System.String,System.Threading.Semaphore@)" />
+ </Type>
+ <Type Name="System.Threading.SemaphoreSlim">
+ <Member Name="#ctor(System.Int32)"/>
+ <Member Name="#ctor(System.Int32,System.Int32)"/>
+ <Member Name="Dispose"/>
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="Release" />
+ <Member Name="Release(System.Int32)" />
+ <Member Name="Wait" />
+ <Member Name="Wait(System.TimeSpan)" />
+ <Member Name="Wait(System.Int32)" />
+ <Member Name="Wait(System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.TimeSpan,System.Threading.CancellationToken)" />
+ <Member Name="Wait(System.Int32,System.Threading.CancellationToken)" />
+ <!--WaitAsync only supported in CoreSys bcause CoreCLR build is still using V4.0 tools -->
+ <Member Name="WaitAsync" />
+ <Member Name="WaitAsync(System.TimeSpan)" />
+ <Member Name="WaitAsync(System.Int32)" />
+ <Member Name="WaitAsync(System.Threading.CancellationToken)" />
+ <Member Name="WaitAsync(System.TimeSpan,System.Threading.CancellationToken)" />
+ <Member Name="WaitAsync(System.Int32,System.Threading.CancellationToken)" />
+ <Member Name="get_CurrentCount"/>
+ <Member Name="get_AvailableWaitHandle"/>
+ </Type>
+ <Type Name="System.Threading.SemaphoreFullException">
+ <Member Name="#ctor" />
+ <Member Name="#ctor(System.String)" />
+ <Member Name="#ctor(System.String,System.Exception)" />
+ <Member Name="#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)" />
+ </Type>
+ <Type Name="System.Threading.ThreadLocal&lt;T&gt;">
+ <Member Name="#ctor"/>
+ <Member Name="#ctor(System.Boolean)"/>
+ <Member Name="#ctor(System.Func&lt;T&gt;)"/>
+ <Member Name="#ctor(System.Func&lt;T&gt;,System.Boolean)"/>
+ <Member Name="Dispose"/>
+ <Member Name="Dispose(System.Boolean)" />
+ <Member Name="ToString" />
+ <Member MemberType="Property" Name="Value" />
+ <Member Name="get_Values"/>
+ <Member Name="get_IsValueCreated"/>
+ </Type>
+ <Type Status="ImplRoot" Name="System.Threading.SystemThreading_ThreadLocalDebugView&lt;T&gt;">
+ <Member Name="#ctor(System.Threading.ThreadLocal&lt;T&gt;)"/>
+ <Member Status="ImplRoot" Name="get_Value"/>
+ <Member Status="ImplRoot" Name="get_IsValueCreated"/>
+ <Member Status="ImplRoot" Name="get_Values"/>
+ </Type>
+ <Type Name="System.Threading.LazyInitializer">
+ <Member Name="EnsureInitialized&lt;T&gt;(T@)"/>
+ <Member Name="EnsureInitialized&lt;T&gt;(T@,System.Func&lt;T&gt;)"/>
+ <Member Name="EnsureInitialized&lt;T&gt;(T@,System.Boolean@,System.Object@)"/>
+ <Member Name="EnsureInitialized&lt;T&gt;(T@,System.Boolean@,System.Object@,System.Func&lt;T&gt;)"/>
+ </Type>
+ <Type Status="ImplRoot" Name="Windows.Foundation.Diagnostics.ITracingStatusChangedEventArgs" Condition="FEATURE_COMINTEROP">
+ <Member Name="get_Enabled" />
+ <Member Name="get_TraceLevel" />
+ </Type>
+ <!--End of PFX types -->
+ <Type Name="System.Console">
+ <Member Name="Write(System.String)" />
+ <Member Name="WriteLine(System.String)" />
+ <Member Name="WriteLine" />
+ </Type>
+ </Assembly>
+</ThinModel>
diff --git a/src/mscorlib/mscorlib.shared.sources.props b/src/mscorlib/mscorlib.shared.sources.props
new file mode 100644
index 0000000000..fc5153f062
--- /dev/null
+++ b/src/mscorlib/mscorlib.shared.sources.props
@@ -0,0 +1,1195 @@
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AccessedThroughPropertyAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AssemblyAttributesGoHere.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CallingConvention.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeHelpers.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CompilerGeneratedAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CustomConstantAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\DateTimeConstantAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\DiscardableAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\DecimalConstantAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\DisablePrivateReflectionAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CompilationRelaxations.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CompilerGlobalScopeAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ExtensionAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\FormattableStringFactory.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\FixedBufferAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IndexerNameAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\InternalsVisibleToAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsVolatile.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\MethodImplAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\FixedAddressValueTypeAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\UnsafeValueTypeAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RequiredAttributeAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AssemblySettingAttributes.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeDependencyAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CompilerMarshalOverride.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\HasCopySemanticsAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsBoxed.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsByValue.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsConst.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsExplicitlyDereferenced.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsImplicitlyDereferenced.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsJitIntrinsic.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsLong.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsPinned.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsSignUnspecifiedByte.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsUdtReturn.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\jithelpers.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ScopelessEnumAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\SpecialNameAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\SuppressMergeCheckAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IsCopyConstructed.cs" />
+ <CompilerServicesSources Condition="'$(FeatureICastable)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ICastable.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\SuppressIldasmAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\NativeCppClassAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\DecoratedNameAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeForwardedToAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TypeForwardedFromAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ReferenceAssemblyAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeCompatibilityAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\RuntimeWrappedException.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\ConditionalWeakTable.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CallerFilePathAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CallerLineNumberAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\CallerMemberNameAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\StateMachineAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IteratorStateMachineAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncStateMachineAttribute.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\AsyncMethodBuilder.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IAsyncStateMachine.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\INotifyCompletion.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\TaskAwaiter.cs" />
+ <CompilerServicesSources Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\YieldAwaitable.cs" />
+ <CompilerServicesSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IDispatchConstantAttribute.cs" />
+ <CompilerServicesSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\CompilerServices\IUnknownConstantAttribute.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ReliabilitySources Include="$(BclSourcesRoot)\System\Runtime\Reliability\CriticalFinalizerObject.cs" />
+ <ReliabilitySources Include="$(BclSourcesRoot)\System\Runtime\Reliability\ReliabilityContractAttribute.cs" />
+ <ReliabilitySources Include="$(BclSourcesRoot)\System\Runtime\Reliability\PrePrepareMethodAttribute.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <RuntimeSources Include="$(BclSourcesRoot)\System\Runtime\MemoryFailPoint.cs" />
+ <RuntimeSources Include="$(BclSourcesRoot)\System\Runtime\GcSettings.cs" />
+ <RuntimeSources Condition="'$(FeatureMulticoreJIT)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\ProfileOptimization.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\CollectionBase.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\ArrayList.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\BitArray.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\Stack.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\Comparer.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\CompatibleComparer.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\ListDictionaryInternal.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\EmptyReadOnlyDictionaryInternal.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\Hashtable.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\DictionaryEntry.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\ICollection.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IComparer.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IDictionary.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IDictionaryEnumerator.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IEnumerable.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IEnumerator.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IEqualityComparer.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IHashCodeProvider.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IList.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\KeyValuePairs.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\SortedList.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IStructuralEquatable.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\IStructuralComparable.cs" />
+ <CollectionsSources Include="$(BclSourcesRoot)\System\Collections\StructuralComparisons.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ArrayWithOffset.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Attributes.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\CallingConvention.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\CharSet.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\COMException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\CriticalHandle.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ExternalException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\GcHandle.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\GCHandleCookieTable.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\HandleRef.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ICustomMarshaler.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\IException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidOleVariantTypeException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\LayoutKind.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Marshal.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\MarshalDirectiveException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\PInvokeMap.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\RuntimeEnvironment.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SEHException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeBuffer.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeHandle.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeHeapHandle.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\BStrWrapper.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\CurrencyWrapper.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ErrorWrapper.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UnknownWrapper.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\VariantWrapper.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComMemberType.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ICustomAdapter.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ICustomQueryInterface.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidComObjectException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeArrayRankMismatchException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeArrayTypeMismatchException.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeBuffer.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\StringBuffer.cs" />
+ <InteropSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeCallableAttribute.cs" />
+ <InteropSources Condition="'$(FeatureCominterop)' != 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NonPortable.cs" />
+ <InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\DispatchWrapper.cs" />
+ <InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ExtensibleClassFactory.cs" />
+ <InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ICustomFactory.cs" />
+ <InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ObjectCreationDelegate.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureClassicCominterop)' == 'true'">
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\IRegistrationServices.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ITypeLibConverter.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\RegistrationServices.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TypeLibConverter.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIBindCtx.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIConnectionPointContainer.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIConnectionPoint.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumerable.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumerator.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumMoniker.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumConnections.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumConnectionPoints.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumString.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIEnumVARIANT.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIExpando.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIMoniker.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIPersistFile.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIReflect.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIRunningObjectTable.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMIStream.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMITypeComp.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMITypeInfo.cs" />
+ <InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\UCOMITypeLib.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <InteropExpandoSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Expando\IExpando.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureClassicCominterop)' == 'true'">
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsHelper.cs" />
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsInfo.cs" />
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsMethod.cs" />
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComEventsSink.cs" />
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeMethods.cs" />
+ <InteropComeventsSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\Variant.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IBindCtx.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IConnectionPointContainer.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IConnectionPoint.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumerable.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumerator.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumMoniker.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumConnections.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumConnectionPoints.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumString.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IEnumVARIANT.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IExpando.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IMoniker.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IPersistFile.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IReflect.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IRunningObjectTable.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\IStream.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\ITypeComp.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\ITypeInfo.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\ITypeLib.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\ITypeLib2.cs" />
+ <InteropComtypesSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ComTypes\ITypeInfo2.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCominterop)' == 'true'">
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\Attributes.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ConstantSplittableMap.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\DictionaryKeyCollection.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\DictionaryValueCollection.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\EnumeratorToIteratorAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\VectorToListAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\VectorToCollectionAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\VectorViewToReadOnlyCollectionAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\MapToDictionaryAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\MapToCollectionAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\MapViewToReadOnlyCollectionAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ListToVectorAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\DictionaryToMapAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\BindableVectorToListAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\BindableVectorToCollectionAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ListToBindableVectorAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ListToBindableVectorViewAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\EventRegistrationToken.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\EventRegistrationTokenTable.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IActivationFactory.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IRestrictedErrorInfo.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IMapViewToIReadOnlyDictionaryAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IVectorViewToIReadOnlyListAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IReadOnlyDictionaryToIMapViewAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IReadOnlyListToIVectorViewAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IteratorToEnumeratorAdapter.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ManagedActivationFactory.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\NativeMethods.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\PropertyValue.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\WindowsRuntimeMarshal.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\WindowsRuntimeMetadata.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IClosable.cs" />
+ <InteropWinRTSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\RuntimeClass.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCominterop)' == 'true'">
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\CLRIPropertyValueImpl.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\CLRIReferenceImpl.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IPropertyValue.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IReference.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\WindowsFoundationEventHandler.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ICustomPropertyProvider.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\ICustomProperty.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\CustomPropertyImpl.cs' />
+ <WinRTTSources Include='$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\WindowsRuntimeBufferHelper.cs' />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCominterop)' == 'true'">
+ <WinRTCollectionSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IIterable.cs" />
+ <WinRTCollectionSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IIterator.cs" />
+ <WinRTCollectionSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IVector.cs" />
+ <WinRTCollectionSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\IMap.cs" />
+ <WinRTCollectionSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\WindowsRuntime\CLRIKeyValuePairImpl.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SystemSources Include="$(BclSourcesRoot)\System\AggregateException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppContext\AppContext.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppContext\AppContextSwitches.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.cs" />
+ <SystemSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.CoreClrOverrides.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppContext\AppContextDefaultValues.Defaults.Central.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CurrentTimeZone.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TimeZone.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Object.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ICloneable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Action.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Array.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArraySegment.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IComparable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IEquatable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ThrowHelper.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Tuple.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\String.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\String.Comparison.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\String.Manipulation.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\String.Searching.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StringComparer.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StringComparison.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StringSplitOptions.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Text\StringBuilder.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Text\StringBuilderCache.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Exception.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\FormattableString.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DateTime.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DateTimeKind.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DateTimeOffset.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\SystemException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\OutOfMemoryException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StackOverflowException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DataMisalignedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ExecutionEngineException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Delegate.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MulticastDelegate.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\__Filters.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\__HResults.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\BCLDebug.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MemberAccessException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Activator.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AccessViolationException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ApplicationException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppDomain.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppDomainSetup.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppDomainManager.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IAppDomainPauseManager.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IAppDomain.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IAppDomainSetup.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppDomainAttributes.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AppDomainUnloadedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ApplicationId.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArgumentException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArgumentNullException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArgumentOutOfRangeException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArgIterator.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArithmeticException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ArrayTypeMismatchException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AsyncCallback.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Attribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AttributeTargets.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\AttributeUsageAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\BadImageFormatException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\BitConverter.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Boolean.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Buffer.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Byte.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CannotUnloadAppDomainException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Char.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CharEnumerator.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CfgParser.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CLSCompliantAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeUnloadedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\cominterfaces.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CompatibilitySwitches.cs" />
+ <SystemSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(BclSourcesRoot)\System\LowLevelConsole.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ContextMarshalException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Convert.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ContextBoundObject.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ContextStaticAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StringFreezingAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Currency.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DayOfWeek.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DBNull.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Decimal.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DefaultBinder.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DelegateSerializationHolder.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DivideByZeroException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Double.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DuplicateWaitObjectException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Empty.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Enum.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\EntryPointNotFoundException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\DllNotFoundException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Environment.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\EventArgs.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\EventHandler.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\FieldAccessException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\FlagsAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\FormatException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\GC.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Guid.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IAsyncResult.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ICustomFormatter.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IDisposable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IFormatProvider.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IFormattable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IndexOutOfRangeException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IObservable.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IObserver.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IProgress.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InsufficientMemoryException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InsufficientExecutionStackException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Lazy.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Int16.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Int32.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Int64.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IntPtr.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Internal.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InvalidCastException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InvalidOperationException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InvalidProgramException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\InvalidTimeZoneException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IConvertible.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\IServiceObjectProvider.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\_LocalDataStore.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\_LocalDataStoreMgr.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MarshalByRefObject.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Math.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\mda.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MethodAccessException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MidpointRounding.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MissingFieldException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MissingMemberException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MissingMethodException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\MulticastNotSupportedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\NonSerializedAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\NotFiniteNumberException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\NotImplementedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\NotSupportedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\NullReferenceException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Number.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ObjectDisposedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ObsoleteAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\OperatingSystem.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\OperationCanceledException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\OverflowException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ParamArrayAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ParamsArray.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ParseNumbers.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\PlatformID.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\PlatformNotSupportedException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Progress.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Random.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\RankException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ResId.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\RtType.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\RuntimeArgumentHandle.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\RuntimeHandles.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\SByte.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\SerializableAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\SharedStatics.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Single.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\StubHelpers.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ThreadAttributes.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TimeoutException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TimeSpan.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TimeZoneInfo.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TimeZoneNotFoundException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Type.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeAccessException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeNameParser.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeCode.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypedReference.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeInitializationException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\TypeLoadException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UInt16.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UInt32.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UInt64.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UIntPtr.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UnauthorizedAccessException.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UnitySerializationHolder.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UnhandledExceptionEventArgs.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UnhandledExceptionEventHandler.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\UnSafeCharBuffer.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\ValueType.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Version.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\Void.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\WeakReference.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\WeakReferenceOfT.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\XmlIgnoreMemberAttribute.cs" />
+ <SystemSources Include="$(BclSourcesRoot)\System\CLRConfig.cs" />
+ <SystemSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\__ComObject.cs" />
+ <SystemSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Variant.cs" />
+ <SystemSources Condition="'$(FeatureClassicCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\OleAutBinder.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <InternalSources Condition="'$(FeatureCoreclr)' == 'true'" Include="$(BclSourcesRoot)\Internal\Runtime\Augments\EnvironmentAugments.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\__Filters.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\AmbiguousMatchException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Assembly.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\AssemblyAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\AssemblyName.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\AssemblyNameProxy.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\AssemblyNameFlags.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Associates.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\CustomAttributeExtensions.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\CustomAttributeFormatException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Binder.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\BindingFlags.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\CallingConventions.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ComInterfaces.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ConstructorInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\CustomAttribute.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\DefaultMemberAttribute.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\EventAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\EventInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\FieldAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\FieldInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\GenericParameterAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ICustomAttributeProvider.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\IReflectableType.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\IntrospectionExtensions.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\RuntimeReflectionExtensions.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\InterfaceMapping.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\InvalidFilterCriteriaException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\IReflect.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\LoaderAllocator.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ManifestResourceInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MdConstant.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MdImport.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MemberFilter.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MemberInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MemberInfoSerializationHolder.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MemberTypes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MethodAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MethodBase.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MethodImplAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MethodInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Missing.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Module.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ObfuscateAssemblyAttribute.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ObfuscationAttribute.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\MethodBody.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ParameterAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ParameterInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ParameterModifier.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\Pointer.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\PropertyAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\PropertyInfo.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ReflectionContext.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ReflectionTypeLoadException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\ResourceAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\StrongNameKeyPair.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TargetException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TargetInvocationException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TargetParameterCountException.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TypeAttributes.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TypeDelegator.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TypeFilter.cs" />
+ <ReflectionSources Include="$(BclSourcesRoot)\System\Reflection\TypeInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilderData.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\AssemblyBuilderAccess.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\AQNBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ComInterfaces.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ConstructorBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicILGenerator.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\DynamicMethod.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\EventBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\EventToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\FieldBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\FieldToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ILGenerator.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ISymWrapperCore.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\Label.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\LocalBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\MethodBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\MethodBuilderInstantiation.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\SymbolType.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\SymbolMethod.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\CustomAttributeBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\MethodToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ModuleBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ModuleBuilderData.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\PEFileKinds.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\OpCodes.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\Opcode.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\OpcodeType.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\StackBehaviour.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\OperandType.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\FlowControl.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ParameterBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\ParameterToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\PropertyBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\PropertyToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\SignatureHelper.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\SignatureToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\StringToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\TypeBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\TypeBuilderInstantiation.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\GenericTypeParameterBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\EnumBuilder.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\TypeToken.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\XXXOnTypeBuilderInstantiation.cs" />
+ <ReflectionEmitSources Include="$(BclSourcesRoot)\System\Reflection\Emit\UnmanagedMarshal.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCoreclr)' == 'true'">
+ <ReflectionMetadataSources Include="$(BclSourcesRoot)\System\Reflection\Metadata\AssemblyExtensions.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DateTimeFormat.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DateTimeParse.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DateTimeStyles.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\NumberStyles.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TimeSpanFormat.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TimeSpanParse.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DaylightTime.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCoreFxGlobalization)' != 'true'">
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\BidiCategory.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\Calendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CalendarData.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CalendarAlgorithmType.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CalendarWeekRule.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CalendricalCalculationsHelper.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CharUnicodeInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CompareInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CultureInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CultureNotFoundException.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CultureTypes.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DateTimeFormatInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DateTimeFormatInfoScanner.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\DigitShapes.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\EncodingDataItem.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\EncodingTable.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\GlobalizationAssembly.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\GregorianCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\GregorianCalendarTypes.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\GregorianCalendarHelper.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\HebrewCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\HijriCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\UmAlQuraCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\PersianCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\IdnMapping.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\JapaneseCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\KoreanCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\RegionInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\SortKey.cs" />
+ <GlobalizationSources Condition="'$(FeatureCoreclr)' == 'true'" Include="$(BclSourcesRoot)\System\Globalization\SortVersion.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\StringInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TaiwanCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TextElementEnumerator.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TextInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\ThaiBuddhistCalendar.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\TimeSpanStyles.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\NumberFormatInfo.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\UnicodeCategory.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\CultureData.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\HebrewNumber.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\ChineseLunisolarCalendar.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\EastAsianLunisolarCalendar.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\JapaneseLunisolarCalendar.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\JulianCalendar.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\KoreanLunisolarCalendar.cs" />
+ <GlobalizationSources Condition="'$(FeatureOnlyCoreCalendars)'==''" Include="$(BclSourcesRoot)\System\Globalization\TaiwanLunisolarCalendar.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCoreFxGlobalization)' == 'true'">
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\SR.cs" />
+ <GlobalizationSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(CoreFxSourcesRoot)\System\Globalization\STUBS.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\Calendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CalendarData.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CalendarWeekRule.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CalendricalCalculationsHelper.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CharUnicodeInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CharUnicodeInfoData.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\ChineseLunisolarCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CompareInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CultureData.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CultureInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CultureNotFoundException.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\DateTimeFormatInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\DateTimeFormatInfoScanner.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\EastAsianLunisolarCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\GregorianCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\GregorianCalendarHelper.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\GregorianCalendarTypes.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\HebrewCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\HebrewNumber.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\HijriCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\InternalGlobalizationHelper.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\JapaneseCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\JapaneseLunisolarCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\JulianCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\KoreanCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\KoreanLunisolarCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\NumberFormatInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\PersianCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\RegionInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\StringInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TaiwanCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TaiwanLunisolarCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TextElementEnumerator.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TextInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\ThaiBuddhistCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TimeSpanStyles.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\UmAlQuraCalendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\UnicodeCategory.cs " />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCoreFxGlobalization)' == 'true' and '$(TargetsUnix)' == 'true'">
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\EncodingTable.Unix.cs" />
+ <GlobalizationSources Include="$(BclSourcesRoot)\System\Globalization\EncodingDataItem.Unix.cs" />
+
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\Interop.Libraries.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Calendar.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Casing.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Collation.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Locale.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.ResultCode.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.TimeZoneInfo.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\Interop\Unix\System.Globalization.Native\Interop.Utils.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CalendarData.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CompareInfo.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CultureData.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\CultureInfo.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\HijriCalendar.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\JapaneseCalendar.Unix.cs" />
+ <GlobalizationSources Include="$(CoreFxSourcesRoot)\System\Globalization\TextInfo.Unix.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\AbandonedMutexException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\AsyncLocal.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\AutoResetEvent.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SendOrPostCallback.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\EventResetMode.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\EventWaitHandle.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ExecutionContext.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Interlocked.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\IObjectHandle.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\LockCookie.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\LockRecursionException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ManualResetEvent.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Mutex.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ParameterizedThreadStart.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ReaderWriterLock.cs" />
+ <ThreadingSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(BclSourcesRoot)\System\Threading\Semaphore.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SemaphoreFullException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SynchronizationLockException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadAbortException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadInterruptedException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadPool.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadPriority.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadStart.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadState.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadStateException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\ThreadStaticAttribute.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadStartException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Timeout.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Timer.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Volatile.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\WaitHandle.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\WaitHandleExtensions.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\WaitHandleCannotBeOpenedException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ApartmentState.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SpinLock.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SpinWait.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\CountdownEvent.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\LazyInitializer.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ThreadLocal.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\SemaphoreSlim.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\ManualResetEventSlim.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\CancellationTokenRegistration.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\CancellationTokenSource.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\CancellationToken.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\future.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\FutureFactory.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\Parallel.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\ParallelRangeManager.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\ParallelLoopState.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\Task.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskContinuation.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskCanceledException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskSchedulerException.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskExceptionHolder.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskFactory.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskScheduler.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\ThreadPoolTaskScheduler.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskCompletionSource.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\AsyncCausalityTracer.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\ConcurrentExclusiveSchedulerPair.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\ProducerConsumerQueues.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TPLETWProvider.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\BeginEndAwaitableAdapter.cs" />
+ <ThreadingSources Include="$(BclSourcesRoot)\System\Threading\Tasks\TaskToApm.cs" />
+ <ThreadingSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Threading\Tasks\IAsyncCausalityTracerStatics.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <IoSources Include="$(BclSourcesRoot)\System\IO\__DebugOutputTextWriter.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\__Error.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\__HResults.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\BinaryReader.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\BinaryWriter.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\BufferedStream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\Directory.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\DirectoryInfo.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\SearchOption.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\DirectoryNotFoundException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\DriveInfo.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\DriveNotFoundException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\EndOfStreamException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\File.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileAccess.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileInfo.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileLoadException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileMode.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileNotFoundException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileOptions.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileShare.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileStream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileSystemEnumerable.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileSystemInfo.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\FileAttributes.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\IOException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\MemoryStream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\Path.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\PathHelper.cs" />
+ <IoSources Condition="'$(TargetsUnix)' != 'true'" Include="$(BclSourcesRoot)\System\IO\LongPathHelper.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\PathInternal.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\PathTooLongException.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\PinnedBufferMemoryStream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\ReadLinesIterator.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\SeekOrigin.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\Stream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\StreamReader.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\StreamWriter.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\StringReader.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\StringWriter.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\TextReader.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\TextWriter.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\UnmanagedMemoryAccessor.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\UnmanagedMemoryStream.cs" />
+ <IoSources Include="$(BclSourcesRoot)\System\IO\UnmanagedMemoryStreamWrapper.cs" />
+ <IoSources Condition="'$(FeatureCoreclr)' == 'true'" Include="$(BclSourcesRoot)\System\IO\FileSecurityState.cs" />
+ <IoSources Condition="'$(FeatureCoreclr)' == 'true'" Include="$(BclSourcesRoot)\System\IO\FileSecurityStateAccess.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\Attributes.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\BuiltInPermissionSets.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\CodeAccessPermission.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\CodeAccessSecurityEngine.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\IEvidenceFactory.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\IPermission.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\ISecurityEncodable.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\ISecurityPolicyEncodable.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\IStackWalk.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\FrameSecurityDescriptor.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\HostSecurityManager.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\NamedPermissionSet.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\PermissionSetEnumerator.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\PermissionSet.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\PermissionToken.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\PermissionSetTriple.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\PermissionListSet.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SafeSecurityHandles.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityContext.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityException.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityState.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\HostProtectionException.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityManager.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityRuntime.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\SecurityZone.cs" />
+ <SecuritySources Include="$(BclSourcesRoot)\System\Security\VerificationException.cs" />
+ <SecuritySources Condition="'$(FeatureLegacySurface)' == 'true'" Include="$(BclSourcesRoot)\System\Security\securestring.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\Config.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\Hex.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\sitestring.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\StringExpressionSet.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\TokenBasedSet.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\TokenBasedSetEnumerator.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\URLString.cs" />
+ <SecUtilSources Include="$(BclSourcesRoot)\System\Security\Util\XMLUtil.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Assert.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\AssertFilter.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\AssertFilters.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\ConditionalAttribute.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Debugger.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\DebuggerAttributes.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\ICustomDebuggerNotification.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\log.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\LoggingLevels.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\LogSwitch.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Stacktrace.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Stackframe.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\EditAndContinueHelper.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\ActivityTracker.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventActivityOptions.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventDescriptor.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventProvider.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
+ <DiagnosticsSources Condition="'$(FeatureXplatEventSource)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\XplatEventLogger.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSourceException.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\FrameworkEventSource.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\StubEnvironment.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\Winmeta.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\ArrayTypeInfo.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\ConcurrentSet.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\ConcurrentSetItem.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\DataCollector.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EmptyStruct.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EnumerableTypeInfo.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EnumHelper.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventDataAttribute.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventFieldAttribute.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventFieldFormat.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventIgnoreAttribute.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventPayload.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventSourceActivity.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\EventSourceOptions.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\FieldMetadata.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\InvokeTypeInfo.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\NameInfo.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyValue.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyAnalysis.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleEventTypes.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleTypeInfos.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\Statics.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingDataCollector.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingDataType.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventSource.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventTraits.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventTypes.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingMetadataCollector.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingTypeInfo.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TypeAnalysis.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <DiagnosticsCodeanalysisSources Include="$(BclSourcesRoot)\System\Diagnostics\CodeAnalysis\SuppressMessageAttribute.cs" />
+ <DiagnosticsCodeanalysisSources Include="$(BclSourcesRoot)\System\Diagnostics\Contracts\Contracts.cs" />
+ <DiagnosticsCodeanalysisSources Include="$(BclSourcesRoot)\System\Diagnostics\Contracts\ContractsBCL.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymBinder.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymDocument.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymDocumentWriter.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymMethod.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymNamespace.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymReader.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymScope.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymVariable.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\ISymWriter.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\SymAddressKind.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\SymDocumentType.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\SymLanguageType.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\SymLanguageVendor.cs" />
+ <DiagnosticsSymbolstoreSources Include="$(BclSourcesRoot)\System\Diagnostics\SymbolStore\Token.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ExceptionservicesSources Condition="'$(FeatureCorruptingExceptions)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\ExceptionServices\CorruptingExceptionCommon.cs" />
+ <ExceptionservicesSources Condition="'$(FeatureExceptionDispatchInfo)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\ExceptionServices\ExceptionServicesCommon.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <HostingSources Condition="'$(FeatureHostAssemblyResolver)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\Loader\AssemblyLoadContext.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\FormatterConverter.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\FormatterServices.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\IDeserializationCallback.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\IFormatter.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\IFormatterConverter.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\IObjectReference.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\ISerializable.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\ISerializationSurrogate.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\ISurrogateSelector.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\MemberHolder.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationAttributes.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationBinder.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationException.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationFieldInfo.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationInfo.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\SerializationInfoEnumerator.cs" />
+ <SerializationSources Include="$(BclSourcesRoot)\System\Runtime\Serialization\StreamingContext.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\BinaryCompatibility.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\ComponentGuaranteesAttribute.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\ResourceAttributes.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\TargetFrameworkAttribute.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\TargetFrameworkId.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\CompatibilitySwitch.cs" />
+ <VersioningSources Include="$(BclSourcesRoot)\System\Runtime\Versioning\NonVersionableAttribute.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ConfigurationAssembliesSources Include="$(BclSourcesRoot)\System\Configuration\Assemblies\AssemblyHash.cs" />
+ <ConfigurationAssembliesSources Include="$(BclSourcesRoot)\System\Configuration\Assemblies\AssemblyHashAlgorithm.cs" />
+ <ConfigurationAssembliesSources Include="$(BclSourcesRoot)\System\Configuration\Assemblies\AssemblyVersionCompatibility.cs" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <RemotingSources Include="$(BclSourcesRoot)\System\Runtime\Remoting\ObjectHandle.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <TextSources Include="$(BclSourcesRoot)\System\Text\ASCIIEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\BaseCodePageEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\CodePageEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\Decoder.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DecoderNLS.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DecoderBestFitFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DecoderExceptionFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DecoderFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DecoderReplacementFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\Encoder.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncoderNLS.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncoderBestFitFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncoderExceptionFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncoderFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncoderReplacementFallback.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncodingForwarder.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncodingInfo.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncodingNLS.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EncodingProvider.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\ISCIIEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\Latin1Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\MLangCodePageEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\Normalization.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\DBCSCodePageEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\SBCSCodePageEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\SurrogateEncoder.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\UnicodeEncoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\UTF7Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\UTF8Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\UTF32Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\GB18030Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\ISO2022Encoding.cs" />
+ <TextSources Include="$(BclSourcesRoot)\System\Text\EUCJPEncoding.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SecurityAclSources Include="$(BclSourcesRoot)\System\Security\AccessControl\Enums.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureCasPolicy)' != 'true'">
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\ApplicationTrust.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\Evidence.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\EvidenceBase.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\EvidenceTypeDescriptor.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\IDelayEvaluatedEvidence.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\IIdentityPermissionFactory.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\IRuntimeEvidenceFactory.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\PolicyException.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\PolicyStatement.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\Site.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\StrongName.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\URL.cs" />
+ <SecurityPolicySources Include="$(BclSourcesRoot)\System\Security\Policy\Zone.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <XmlSources Include="$(BclSourcesRoot)\System\Security\SecurityElement.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Win32Sources Include="$(BclSourcesRoot)\Microsoft\Win32\UnsafeNativeMethods.cs" />
+ <Win32Sources Include="$(BclSourcesRoot)\Microsoft\Win32\Win32Native.cs" />
+ <Win32Sources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\Registry.cs" />
+ <Win32Sources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryKey.cs" />
+ <Win32Sources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryOptions.cs" />
+ <Win32Sources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryValueKind.cs" />
+ <Win32Sources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\RegistryView.cs" />
+ <Win32Sources Condition="'$(FeatureClassicCominterop)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\OAVariantLib.cs" />
+ </ItemGroup>
+ <ItemGroup Condition="'$(FeatureClassicCominterop)' == 'true'" >
+ <InteropTceadaptergenSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TCEAdapterGen\EventProviderWriter.cs" />
+ <InteropTceadaptergenSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TCEAdapterGen\EventSinkHelperWriter.cs" />
+ <InteropTceadaptergenSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TCEAdapterGen\EventItfInfo.cs" />
+ <InteropTceadaptergenSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TCEAdapterGen\NameSpaceExtractor.cs" />
+ <InteropTceadaptergenSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\TCEAdapterGen\TCEAdapterGenerator.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SecurityPrincipalSources Include="$(BclSourcesRoot)\System\Security\Principal\IIdentity.cs" />
+ <SecurityPrincipalSources Include="$(BclSourcesRoot)\System\Security\Principal\IPrincipal.cs" />
+ <SecurityPrincipalSources Include="$(BclSourcesRoot)\System\Security\Principal\TokenImpersonationLevel.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\__FastResourceComparer.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\__HResults.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\FileBasedResourceGroveler.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\IResourceGroveler.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\IResourceReader.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\IResourceWriter.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\LooselyLinkedResourceReference.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ManifestBasedResourceGroveler.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\MissingManifestResourceException.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\MissingSatelliteAssemblyException.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\NeutralResourcesLanguageAttribute.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ResourceFallbackManager.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ResourceManager.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ResourceReader.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ResourceSet.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\ResourceTypeCode.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\RuntimeResourceSet.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\SatelliteContractVersionAttribute.cs" />
+ <ResourcesSources Include="$(BclSourcesRoot)\System\Resources\UltimateResourceFallbackLocation.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\EnvironmentPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\FileDialogPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\FileIOPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\HostProtectionPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\IBuiltInPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\IsolatedStoragePermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\IsolatedStorageFilePermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\PermissionState.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\PermissionAttributes.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\ReflectionPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\SecurityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\SiteIdentityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\StrongNameIdentityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\StrongNamePublicKeyBlob.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\UIPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\URLIdentityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\ZoneIdentityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\GACIdentityPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\IUnrestrictedPermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\keycontainerpermission.cs" />
+ <PermissionsSources Include="$(BclSourcesRoot)\System\Security\Permissions\RegistryPermission.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <GenericsSources Include="$(BclSourcesRoot)\System\Nullable.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\Comparer.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\Dictionary.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\EqualityComparer.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\DebugView.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\ICollection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IComparer.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IDictionary.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IEnumerable.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IEnumerator.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IEqualityComparer.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IList.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IReadOnlyCollection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IReadOnlyList.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\IReadOnlyDictionary.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\KeyNotFoundException.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\KeyValuePair.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\List.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Generic\ArraySortHelper.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\ObjectModel\Collection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyCollection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\ObjectModel\ReadOnlyDictionary.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\ObjectModel\KeyedCollection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\ConcurrentStack.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\IProducerConsumerCollection.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\ConcurrentDictionary.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\ConcurrentQueue.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\Partitioner.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\OrderablePartitioner.cs" />
+ <GenericsSources Include="$(BclSourcesRoot)\System\Collections\Concurrent\PartitionerStatic.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeFileHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeFileMappingHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeFindHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeLocalAllocHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeLibraryHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeViewOfFileHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeWaitHandle.cs" />
+ <SafehandleSources Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\Win32SafeHandles.cs" />
+ <SafehandleSources Condition="'$(FeatureWin32Registry)' == 'true'" Include="$(BclSourcesRoot)\Microsoft\Win32\SafeHandles\SafeRegistryHandle.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <MscorlibSources Include="@(SystemSources)"/>
+ <MscorlibSources Include="@(ThreadingSources)"/>
+ <MscorlibSources Include="@(DeploymentSources)"/>
+ <MscorlibSources Include="@(CollectionsSources)"/>
+ <MscorlibSources Include="@(GenericsSources)"/>
+ <MscorlibSources Include="@(DiagnosticsSources)"/>
+ <MscorlibSources Include="@(DiagnosticsCodeanalysisSources)"/>
+ <MscorlibSources Include="@(DiagnosticsSymbolstoreSources)"/>
+ <MscorlibSources Include="@(ReflectionSources)"/>
+ <MscorlibSources Include="@(ExceptionservicesSources)"/>
+ <MscorlibSources Include="@(HostingSources)"/>
+ <MscorlibSources Include="@(SerializationSources)"/>
+ <MscorlibSources Include="@(GlobalizationSources)"/>
+ <MscorlibSources Include="@(TextSources)"/>
+ <MscorlibSources Include="@(ResourcesSources)"/>
+ <MscorlibSources Include="@(Win32Sources)"/>
+ <MscorlibSources Include="@(SafehandleSources)"/>
+ <MscorlibSources Include="@(SecUtilSources)"/>
+ <MscorlibSources Include="@(SecurityPolicySources)"/>
+ <MscorlibSources Include="@(SecurityPrincipalSources)"/>
+ <MscorlibSources Include="@(ReliabilitySources)"/>
+ <MscorlibSources Include="@(InteropSources)"/>
+ <MscorlibSources Include="@(InteropComtypesSources)"/>
+ <MscorlibSources Include="@(InteropComeventsSources)"/>
+ <MscorlibSources Include="@(InteropExpandoSources)"/>
+ <MscorlibSources Include="@(InteropWinRTSources)"/>
+ <MscorlibSources Include="@(WinRTTSources)"/>
+ <MscorlibSources Include="@(WinRTCollectionSources)"/>
+ <MscorlibSources Include="@(IoSources)"/>
+ <MscorlibSources Include="@(CompilerServicesSources)"/>
+ <MscorlibSources Include="@(RuntimeSources)"/>
+ <MscorlibSources Include="@(XmlSources)"/>
+ <MscorlibSources Include="@(PermissionsSources)"/>
+ <MscorlibSources Include="@(SecuritySources)"/>
+ <MscorlibSources Include="@(RemotingSources)"/>
+ <MscorlibSources Include="@(IsostoreSources)"/>
+ <MscorlibSources Include="@(SerializationFormattersSources)"/>
+ <MscorlibSources Include="@(SerializationFormattersBinarySources)"/>
+ <MscorlibSources Include="@(ReflectionEmitSources)"/>
+ <MscorlibSources Include="@(ReflectionMetadataSources)"/>
+ <MscorlibSources Include="@(ConfigurationAssembliesSources)"/>
+ <MscorlibSources Include="@(SecCryptographySources)"/>
+ <MscorlibSources Include="@(SecPublickeySources)"/>
+ <MscorlibSources Include="@(InteropTceadaptergenSources)"/>
+ <MscorlibSources Include="@(SecurityAclSources)"/>
+ <MscorlibSources Include="@(IdentitySources)"/>
+ <MscorlibSources Include="@(VersioningSources)"/>
+ <MscorlibSources Include="@(DesignerServicesSources)"/>
+ <MscorlibSources Include="@(InternalSources)"/>
+ <MscorlibSources Include="$(BclSourcesRoot)\GlobalSuppressions.cs"/>
+ </ItemGroup>
+</Project>
diff --git a/src/mscorlib/ref/mscorlib.cs b/src/mscorlib/ref/mscorlib.cs
new file mode 100644
index 0000000000..e5211ff4a8
--- /dev/null
+++ b/src/mscorlib/ref/mscorlib.cs
@@ -0,0 +1,13673 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Internal.Runtime.Augments
+{
+ public static partial class EnvironmentAugments
+ {
+ public static int CurrentManagedThreadId { get { throw null; } }
+ public static int ExitCode { get { throw null; } set { } }
+ public static bool HasShutdownStarted { get { throw null; } }
+ public static string StackTrace { get { throw null; } }
+ public static int TickCount { get { throw null; } }
+ public static void Exit(int exitCode) { }
+ public static void FailFast(string message, System.Exception error) { }
+ public static string[] GetCommandLineArgs() { throw null; }
+ }
+}
+namespace Microsoft.Win32.SafeHandles
+{
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class SafeHandleMinusOneIsInvalid : System.Runtime.InteropServices.SafeHandle
+ {
+ protected SafeHandleMinusOneIsInvalid(bool ownsHandle) { }
+ public override bool IsInvalid { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class SafeHandleZeroOrMinusOneIsInvalid : System.Runtime.InteropServices.SafeHandle
+ {
+ protected SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) { }
+ public override bool IsInvalid { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public sealed partial class SafeWaitHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
+ {
+ public SafeWaitHandle(System.IntPtr existingHandle, bool ownsHandle) : base(ownsHandle) { }
+ [System.Security.SecurityCriticalAttribute]
+ protected override bool ReleaseHandle() { throw null; }
+ }
+}
+namespace System
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class AccessViolationException : System.SystemException
+ {
+ public AccessViolationException() { }
+ public AccessViolationException(string message) { }
+ public AccessViolationException(string message, System.Exception innerException) { }
+ protected AccessViolationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate void Action();
+ public delegate void Action<in T>(T obj);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+ public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Activator
+ {
+ internal Activator() { }
+ public static System.Runtime.Remoting.ObjectHandle CreateComInstanceFrom(string assemblyName, string typeName) { throw null; }
+ public static System.Runtime.Remoting.ObjectHandle CreateComInstanceFrom(string assemblyName, string typeName, byte[] hashValue, System.Configuration.Assemblies.AssemblyHashAlgorithm hashAlgorithm) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstance(System.AppDomain domain, string assemblyName, string typeName) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstance(System.AppDomain domain, string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstance(string assemblyName, string typeName) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstance(string assemblyName, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttributes) { throw null; }
+ public static object CreateInstance(System.Type type) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static object CreateInstance(System.Type type, bool nonPublic) { throw null; }
+ public static object CreateInstance(System.Type type, params object[] args) { throw null; }
+ public static object CreateInstance(System.Type type, object[] args, object[] activationAttributes) { throw null; }
+ public static object CreateInstance(System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object CreateInstance(System.Type type, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static T CreateInstance<T>() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(System.AppDomain domain, string assemblyFile, string typeName) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(System.AppDomain domain, string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) { throw null; }
+ public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName) { throw null; }
+ public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) { throw null; }
+ public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, object[] activationAttributes) { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {InnerExceptionCount}")]
+ public partial class AggregateException : System.Exception
+ {
+ public AggregateException() { }
+ public AggregateException(System.Collections.Generic.IEnumerable<System.Exception> innerExceptions) { }
+ public AggregateException(params System.Exception[] innerExceptions) { }
+ public AggregateException(string message) { }
+ public AggregateException(string message, System.Collections.Generic.IEnumerable<System.Exception> innerExceptions) { }
+ public AggregateException(string message, System.Exception innerException) { }
+ public AggregateException(string message, params System.Exception[] innerExceptions) { }
+ protected AggregateException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public System.Collections.ObjectModel.ReadOnlyCollection<System.Exception> InnerExceptions { get { throw null; } }
+ public override string Message { get { throw null; } }
+ public System.AggregateException Flatten() { throw null; }
+ public override System.Exception GetBaseException() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public void Handle(System.Func<System.Exception, bool> predicate) { }
+ public override string ToString() { throw null; }
+ }
+ public static partial class AppContext
+ {
+ public static string BaseDirectory { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static string TargetFrameworkName { get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object GetData(string name) { throw null; }
+ public static void SetSwitch(string switchName, bool isEnabled) { }
+ public static bool TryGetSwitch(string switchName, out bool isEnabled) { isEnabled = default(bool); throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AppDomain
+ {
+ internal AppDomain() { }
+ public string BaseDirectory { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public static System.AppDomain CurrentDomain { get { throw null; } }
+ public bool IsFullyTrusted { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public object GetData(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public partial class AppDomainManager
+ {
+ public AppDomainManager() { }
+ public virtual bool CheckSecuritySettings(System.Security.SecurityState state) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void InitializeNewDomain(System.AppDomainSetup appDomainInfo) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AppDomainSetup
+ {
+ internal AppDomainSetup() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class AppDomainUnloadedException : System.SystemException
+ {
+ public AppDomainUnloadedException() { }
+ public AppDomainUnloadedException(string message) { }
+ public AppDomainUnloadedException(string message, System.Exception innerException) { }
+ protected AppDomainUnloadedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ApplicationId
+ {
+ public ApplicationId(byte[] publicKeyToken, string name, System.Version version, string processorArchitecture, string culture) { }
+ public string Culture { get { throw null; } }
+ public string Name { get { throw null; } }
+ public string ProcessorArchitecture { get { throw null; } }
+ public byte[] PublicKeyToken { get { throw null; } }
+ public System.Version Version { get { throw null; } }
+ public System.ApplicationId Copy() { throw null; }
+ public override bool Equals(object o) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ApplicationException : System.Exception
+ {
+ public ApplicationException() { }
+ public ApplicationException(string message) { }
+ public ApplicationException(string message, System.Exception innerException) { }
+ protected ApplicationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ArgIterator
+ {
+ public override bool Equals(object o) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ArgumentException : System.SystemException, System.Runtime.Serialization.ISerializable
+ {
+ public ArgumentException() { }
+ public ArgumentException(string message) { }
+ public ArgumentException(string message, System.Exception innerException) { }
+ public ArgumentException(string message, string paramName) { }
+ public ArgumentException(string message, string paramName, System.Exception innerException) { }
+ protected ArgumentException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public override string Message { get { throw null; } }
+ public virtual string ParamName { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ArgumentNullException : System.ArgumentException
+ {
+ public ArgumentNullException() { }
+ public ArgumentNullException(string paramName) { }
+ public ArgumentNullException(string message, System.Exception innerException) { }
+ public ArgumentNullException(string paramName, string message) { }
+ protected ArgumentNullException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ArgumentOutOfRangeException : System.ArgumentException, System.Runtime.Serialization.ISerializable
+ {
+ public ArgumentOutOfRangeException() { }
+ public ArgumentOutOfRangeException(string paramName) { }
+ public ArgumentOutOfRangeException(string message, System.Exception innerException) { }
+ public ArgumentOutOfRangeException(string paramName, object actualValue, string message) { }
+ public ArgumentOutOfRangeException(string paramName, string message) { }
+ protected ArgumentOutOfRangeException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public virtual object ActualValue { get { throw null; } }
+ public override string Message { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ArithmeticException : System.SystemException
+ {
+ public ArithmeticException() { }
+ public ArithmeticException(string message) { }
+ public ArithmeticException(string message, System.Exception innerException) { }
+ protected ArithmeticException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Array : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.ICloneable
+ {
+ internal Array() { }
+ public bool IsFixedSize { get { throw null; } }
+ public bool IsReadOnly { get { throw null; } }
+ public bool IsSynchronized { get { throw null; } }
+ public int Length { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public long LongLength { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public int Rank { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public object SyncRoot { get { throw null; } }
+ int System.Collections.ICollection.Count { get { throw null; } }
+ object System.Collections.IList.this[int index] { get { throw null; } set { } }
+ public static System.Collections.ObjectModel.ReadOnlyCollection<T> AsReadOnly<T>(T[] array) { throw null; }
+ public static int BinarySearch(System.Array array, int index, int length, object value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int BinarySearch(System.Array array, int index, int length, object value, System.Collections.IComparer comparer) { throw null; }
+ public static int BinarySearch(System.Array array, object value) { throw null; }
+ public static int BinarySearch(System.Array array, object value, System.Collections.IComparer comparer) { throw null; }
+ public static int BinarySearch<T>(T[] array, T value) { throw null; }
+ public static int BinarySearch<T>(T[] array, T value, System.Collections.Generic.IComparer<T> comparer) { throw null; }
+ public static int BinarySearch<T>(T[] array, int index, int length, T value) { throw null; }
+ public static int BinarySearch<T>(T[] array, int index, int length, T value, System.Collections.Generic.IComparer<T> comparer) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void Clear(System.Array array, int index, int length) { }
+ public object Clone() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void ConstrainedCopy(System.Array sourceArray, int sourceIndex, System.Array destinationArray, int destinationIndex, int length) { }
+ public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, System.Converter<TInput, TOutput> converter) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Copy(System.Array sourceArray, System.Array destinationArray, int length) { }
+ public static void Copy(System.Array sourceArray, System.Array destinationArray, long length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Copy(System.Array sourceArray, int sourceIndex, System.Array destinationArray, int destinationIndex, int length) { }
+ public static void Copy(System.Array sourceArray, long sourceIndex, System.Array destinationArray, long destinationIndex, long length) { }
+ public void CopyTo(System.Array array, int index) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void CopyTo(System.Array array, long index) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Array CreateInstance(System.Type elementType, int length) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Array CreateInstance(System.Type elementType, int length1, int length2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Array CreateInstance(System.Type elementType, int length1, int length2, int length3) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Array CreateInstance(System.Type elementType, params int[] lengths) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Array CreateInstance(System.Type elementType, int[] lengths, int[] lowerBounds) { throw null; }
+ public static System.Array CreateInstance(System.Type elementType, params long[] lengths) { throw null; }
+ public static T[] Empty<T>() { throw null; }
+ public static bool Exists<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static T Find<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static T[] FindAll<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static int FindIndex<T>(T[] array, int startIndex, int count, System.Predicate<T> match) { throw null; }
+ public static int FindIndex<T>(T[] array, int startIndex, System.Predicate<T> match) { throw null; }
+ public static int FindIndex<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static T FindLast<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static int FindLastIndex<T>(T[] array, int startIndex, int count, System.Predicate<T> match) { throw null; }
+ public static int FindLastIndex<T>(T[] array, int startIndex, System.Predicate<T> match) { throw null; }
+ public static int FindLastIndex<T>(T[] array, System.Predicate<T> match) { throw null; }
+ public static void ForEach<T>(T[] array, System.Action<T> action) { }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public int GetLength(int dimension) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public long GetLongLength(int dimension) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public int GetLowerBound(int dimension) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public int GetUpperBound(int dimension) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public object GetValue(int index) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public object GetValue(int index1, int index2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public object GetValue(int index1, int index2, int index3) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public object GetValue(params int[] indices) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public object GetValue(long index) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public object GetValue(long index1, long index2) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public object GetValue(long index1, long index2, long index3) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public object GetValue(params long[] indices) { throw null; }
+ public static int IndexOf(System.Array array, object value) { throw null; }
+ public static int IndexOf(System.Array array, object value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int IndexOf(System.Array array, object value, int startIndex, int count) { throw null; }
+ public static int IndexOf<T>(T[] array, T value) { throw null; }
+ public static int IndexOf<T>(T[] array, T value, int startIndex) { throw null; }
+ public static int IndexOf<T>(T[] array, T value, int startIndex, int count) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public void Initialize() { }
+ public static int LastIndexOf(System.Array array, object value) { throw null; }
+ public static int LastIndexOf(System.Array array, object value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int LastIndexOf(System.Array array, object value, int startIndex, int count) { throw null; }
+ public static int LastIndexOf<T>(T[] array, T value) { throw null; }
+ public static int LastIndexOf<T>(T[] array, T value, int startIndex) { throw null; }
+ public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count) { throw null; }
+ public static void Resize<T>(ref T[] array, int newSize) { }
+ public static void Reverse(System.Array array) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Reverse(System.Array array, int index, int length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetValue(object value, int index) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetValue(object value, int index1, int index2) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetValue(object value, int index1, int index2, int index3) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetValue(object value, params int[] indices) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetValue(object value, long index) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetValue(object value, long index1, long index2) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetValue(object value, long index1, long index2, long index3) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetValue(object value, params long[] indices) { }
+ public static void Sort(System.Array array) { }
+ public static void Sort(System.Array keys, System.Array items) { }
+ public static void Sort(System.Array keys, System.Array items, System.Collections.IComparer comparer) { }
+ public static void Sort(System.Array keys, System.Array items, int index, int length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Sort(System.Array keys, System.Array items, int index, int length, System.Collections.IComparer comparer) { }
+ public static void Sort(System.Array array, System.Collections.IComparer comparer) { }
+ public static void Sort(System.Array array, int index, int length) { }
+ public static void Sort(System.Array array, int index, int length, System.Collections.IComparer comparer) { }
+ public static void Sort<T>(T[] array) { }
+ public static void Sort<T>(T[] array, System.Collections.Generic.IComparer<T> comparer) { }
+ public static void Sort<T>(T[] array, System.Comparison<T> comparison) { }
+ public static void Sort<T>(T[] array, int index, int length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Sort<T>(T[] array, int index, int length, System.Collections.Generic.IComparer<T> comparer) { }
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items) { }
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, System.Collections.Generic.IComparer<TKey> comparer) { }
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer<TKey> comparer) { }
+ int System.Collections.IList.Add(object value) { throw null; }
+ void System.Collections.IList.Clear() { }
+ bool System.Collections.IList.Contains(object value) { throw null; }
+ int System.Collections.IList.IndexOf(object value) { throw null; }
+ void System.Collections.IList.Insert(int index, object value) { }
+ void System.Collections.IList.Remove(object value) { }
+ void System.Collections.IList.RemoveAt(int index) { }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ public static bool TrueForAll<T>(T[] array, System.Predicate<T> match) { throw null; }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ArraySegment<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.IEnumerable
+ {
+ public ArraySegment(T[] array) { throw null;}
+ public ArraySegment(T[] array, int offset, int count) { throw null;}
+ public T[] Array { get { throw null; } }
+ public int Count { get { throw null; } }
+ public int Offset { get { throw null; } }
+ bool System.Collections.Generic.ICollection<T>.IsReadOnly { get { throw null; } }
+ T System.Collections.Generic.IList<T>.this[int index] { get { throw null; } set { } }
+ T System.Collections.Generic.IReadOnlyList<T>.this[int index] { get { throw null; } }
+ public bool Equals(System.ArraySegment<T> obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.ArraySegment<T> a, System.ArraySegment<T> b) { throw null; }
+ public static bool operator !=(System.ArraySegment<T> a, System.ArraySegment<T> b) { throw null; }
+ void System.Collections.Generic.ICollection<T>.Add(T item) { }
+ void System.Collections.Generic.ICollection<T>.Clear() { }
+ bool System.Collections.Generic.ICollection<T>.Contains(T item) { throw null; }
+ void System.Collections.Generic.ICollection<T>.CopyTo(T[] array, int arrayIndex) { }
+ bool System.Collections.Generic.ICollection<T>.Remove(T item) { throw null; }
+ System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator() { throw null; }
+ int System.Collections.Generic.IList<T>.IndexOf(T item) { throw null; }
+ void System.Collections.Generic.IList<T>.Insert(int index, T item) { }
+ void System.Collections.Generic.IList<T>.RemoveAt(int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ArrayTypeMismatchException : System.SystemException
+ {
+ public ArrayTypeMismatchException() { }
+ public ArrayTypeMismatchException(string message) { }
+ public ArrayTypeMismatchException(string message, System.Exception innerException) { }
+ protected ArrayTypeMismatchException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class AssemblyLoadEventArgs : System.EventArgs
+ {
+ public AssemblyLoadEventArgs(System.Reflection.Assembly loadedAssembly) { }
+ public System.Reflection.Assembly LoadedAssembly { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void AssemblyLoadEventHandler(object sender, System.AssemblyLoadEventArgs args);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void AsyncCallback(System.IAsyncResult ar);
+ [System.AttributeUsageAttribute((System.AttributeTargets)(32767), Inherited = true, AllowMultiple = false)]
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Attribute
+ {
+ protected Attribute() { }
+ public virtual object TypeId { get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.Assembly element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.MemberInfo element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.MemberInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.Module element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Assembly element) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Assembly element, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Assembly element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.MemberInfo element) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.MemberInfo element, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.MemberInfo element, System.Type type) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.MemberInfo element, System.Type type, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Module element) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Module element, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.Module element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.ParameterInfo element) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.ParameterInfo element, bool inherit) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static System.Attribute[] GetCustomAttributes(System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public virtual bool IsDefaultAttribute() { throw null; }
+ public static bool IsDefined(System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(System.Reflection.Assembly element, System.Type attributeType, bool inherit) { throw null; }
+ public static bool IsDefined(System.Reflection.MemberInfo element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(System.Reflection.MemberInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static bool IsDefined(System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(System.Reflection.Module element, System.Type attributeType, bool inherit) { throw null; }
+ public static bool IsDefined(System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public virtual bool Match(object obj) { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum AttributeTargets
+ {
+ All = 32767,
+ Assembly = 1,
+ Class = 4,
+ Constructor = 32,
+ Delegate = 4096,
+ Enum = 16,
+ Event = 512,
+ Field = 256,
+ GenericParameter = 16384,
+ Interface = 1024,
+ Method = 64,
+ Module = 2,
+ Parameter = 2048,
+ Property = 128,
+ ReturnValue = 8192,
+ Struct = 8,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AttributeUsageAttribute : System.Attribute
+ {
+ public AttributeUsageAttribute(System.AttributeTargets validOn) { }
+ public bool AllowMultiple { get { throw null; } set { } }
+ public bool Inherited { get { throw null; } set { } }
+ public System.AttributeTargets ValidOn { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class BadImageFormatException : System.SystemException
+ {
+ public BadImageFormatException() { }
+ protected BadImageFormatException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public BadImageFormatException(string message) { }
+ public BadImageFormatException(string message, System.Exception inner) { }
+ public BadImageFormatException(string message, string fileName) { }
+ public BadImageFormatException(string message, string fileName, System.Exception inner) { }
+ public string FileName { get { throw null; } }
+ public string FusionLog { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public override string Message { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public override string ToString() { throw null; }
+ }
+ [System.FlagsAttribute]
+ public enum Base64FormattingOptions
+ {
+ InsertLineBreaks = 1,
+ None = 0,
+ }
+ public static partial class BitConverter
+ {
+ public static readonly bool IsLittleEndian;
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static long DoubleToInt64Bits(double value) { throw null; }
+ public static byte[] GetBytes(bool value) { throw null; }
+ public static byte[] GetBytes(char value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] GetBytes(double value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] GetBytes(short value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] GetBytes(int value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] GetBytes(long value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] GetBytes(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte[] GetBytes(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte[] GetBytes(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte[] GetBytes(ulong value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static double Int64BitsToDouble(long value) { throw null; }
+ public static bool ToBoolean(byte[] value, int startIndex) { throw null; }
+ public static char ToChar(byte[] value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static double ToDouble(byte[] value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static short ToInt16(byte[] value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int ToInt32(byte[] value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static long ToInt64(byte[] value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static float ToSingle(byte[] value, int startIndex) { throw null; }
+ public static string ToString(byte[] value) { throw null; }
+ public static string ToString(byte[] value, int startIndex) { throw null; }
+ public static string ToString(byte[] value, int startIndex, int length) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(byte[] value, int startIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(byte[] value, int startIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(byte[] value, int startIndex) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Boolean : System.IComparable, System.IComparable<bool>, System.IConvertible, System.IEquatable<bool>
+ {
+ public static readonly string FalseString;
+ public static readonly string TrueString;
+ public int CompareTo(System.Boolean value) { throw null; }
+ public int CompareTo(object obj) { throw null; }
+ public System.Boolean Equals(System.Boolean obj) { throw null; }
+ public override System.Boolean Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Boolean Parse(string value) { throw null; }
+ System.Boolean System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public static System.Boolean TryParse(string value, out System.Boolean result) { result = default(bool); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Buffer
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void BlockCopy(System.Array src, int srcOffset, System.Array dst, int dstOffset, int count) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int ByteLength(System.Array array) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte GetByte(System.Array array, int index) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)][System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)][System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SetByte(System.Array array, int index, byte value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Byte : System.IComparable, System.IComparable<byte>, System.IConvertible, System.IEquatable<byte>, System.IFormattable
+ {
+ public const byte MaxValue = (byte)255;
+ public const byte MinValue = (byte)0;
+ public int CompareTo(System.Byte value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public bool Equals(System.Byte obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Byte Parse(string s) { throw null; }
+ public static System.Byte Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Byte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Byte Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, out System.Byte result) { result = default(byte); throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Byte result) { result = default(byte); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CannotUnloadAppDomainException : System.SystemException
+ {
+ public CannotUnloadAppDomainException() { }
+ public CannotUnloadAppDomainException(string message) { }
+ public CannotUnloadAppDomainException(string message, System.Exception innerException) { }
+ protected CannotUnloadAppDomainException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Char : System.IComparable, System.IComparable<char>, System.IConvertible, System.IEquatable<char>
+ {
+ public const char MaxValue = '\uFFFF';
+ public const char MinValue = '\0';
+ public int CompareTo(System.Char value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ConvertFromUtf32(int utf32) { throw null; }
+ public static int ConvertToUtf32(System.Char highSurrogate, System.Char lowSurrogate) { throw null; }
+ public static int ConvertToUtf32(string s, int index) { throw null; }
+ public bool Equals(System.Char obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static double GetNumericValue(System.Char c) { throw null; }
+ public static double GetNumericValue(string s, int index) { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Globalization.UnicodeCategory GetUnicodeCategory(System.Char c) { throw null; }
+ public static System.Globalization.UnicodeCategory GetUnicodeCategory(string s, int index) { throw null; }
+ public static bool IsControl(System.Char c) { throw null; }
+ public static bool IsControl(string s, int index) { throw null; }
+ public static bool IsDigit(System.Char c) { throw null; }
+ public static bool IsDigit(string s, int index) { throw null; }
+ public static bool IsHighSurrogate(System.Char c) { throw null; }
+ public static bool IsHighSurrogate(string s, int index) { throw null; }
+ public static bool IsLetter(System.Char c) { throw null; }
+ public static bool IsLetter(string s, int index) { throw null; }
+ public static bool IsLetterOrDigit(System.Char c) { throw null; }
+ public static bool IsLetterOrDigit(string s, int index) { throw null; }
+ public static bool IsLower(System.Char c) { throw null; }
+ public static bool IsLower(string s, int index) { throw null; }
+ public static bool IsLowSurrogate(System.Char c) { throw null; }
+ public static bool IsLowSurrogate(string s, int index) { throw null; }
+ public static bool IsNumber(System.Char c) { throw null; }
+ public static bool IsNumber(string s, int index) { throw null; }
+ public static bool IsPunctuation(System.Char c) { throw null; }
+ public static bool IsPunctuation(string s, int index) { throw null; }
+ public static bool IsSeparator(System.Char c) { throw null; }
+ public static bool IsSeparator(string s, int index) { throw null; }
+ public static bool IsSurrogate(System.Char c) { throw null; }
+ public static bool IsSurrogate(string s, int index) { throw null; }
+ public static bool IsSurrogatePair(System.Char highSurrogate, System.Char lowSurrogate) { throw null; }
+ public static bool IsSurrogatePair(string s, int index) { throw null; }
+ public static bool IsSymbol(System.Char c) { throw null; }
+ public static bool IsSymbol(string s, int index) { throw null; }
+ public static bool IsUpper(System.Char c) { throw null; }
+ public static bool IsUpper(string s, int index) { throw null; }
+ public static bool IsWhiteSpace(System.Char c) { throw null; }
+ public static bool IsWhiteSpace(string s, int index) { throw null; }
+ public static System.Char Parse(string s) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ System.Char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ public static System.Char ToLower(System.Char c) { throw null; }
+ public static System.Char ToLower(System.Char c, System.Globalization.CultureInfo culture) { throw null; }
+ public static System.Char ToLowerInvariant(System.Char c) { throw null; }
+ public override string ToString() { throw null; }
+ public static string ToString(System.Char c) { throw null; }
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public static System.Char ToUpper(System.Char c) { throw null; }
+ public static System.Char ToUpper(System.Char c, System.Globalization.CultureInfo culture) { throw null; }
+ public static System.Char ToUpperInvariant(System.Char c) { throw null; }
+ public static bool TryParse(string s, out System.Char result) { result = default(char); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class CharEnumerator : System.Collections.Generic.IEnumerator<char>, System.Collections.IEnumerator, System.ICloneable, System.IDisposable
+ {
+ internal CharEnumerator() { }
+ public char Current { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public object Clone() { throw null; }
+ public void Dispose() { }
+ public bool MoveNext() { throw null; }
+ public void Reset() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(32767), Inherited=true, AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class CLSCompliantAttribute : System.Attribute
+ {
+ public CLSCompliantAttribute(bool isCompliant) { }
+ public bool IsCompliant { get { throw null; } }
+ }
+ public delegate int Comparison<in T>(T x, T y);
+ public static partial class Console
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Write(string s) { }
+ public static void WriteLine() { }
+ public static void WriteLine(string s) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class ContextBoundObject
+ {
+ protected ContextBoundObject() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ContextMarshalException : System.SystemException
+ {
+ public ContextMarshalException() { }
+ public ContextMarshalException(string message) { }
+ public ContextMarshalException(string message, System.Exception inner) { }
+ protected ContextMarshalException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ [System.ObsoleteAttribute("ContextStaticAttribute is not supported in this release. It has been left in so that legacy tools can be used with this release, but it cannot be used in your code.", true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ContextStaticAttribute : System.Attribute
+ {
+ public ContextStaticAttribute() { }
+ }
+ public static partial class Convert
+ {
+ public static readonly object DBNull;
+ public static object ChangeType(object value, System.Type conversionType) { throw null; }
+ public static object ChangeType(object value, System.Type conversionType, System.IFormatProvider provider) { throw null; }
+ public static object ChangeType(object value, System.TypeCode typeCode) { throw null; }
+ public static object ChangeType(object value, System.TypeCode typeCode, System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] FromBase64CharArray(char[] inArray, int offset, int length) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static byte[] FromBase64String(string s) { throw null; }
+ public static System.TypeCode GetTypeCode(object value) { throw null; }
+ public static bool IsDBNull(object value) { throw null; }
+ public static int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, System.Base64FormattingOptions options) { throw null; }
+ public static string ToBase64String(byte[] inArray) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static string ToBase64String(byte[] inArray, System.Base64FormattingOptions options) { throw null; }
+ public static string ToBase64String(byte[] inArray, int offset, int length) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ToBase64String(byte[] inArray, int offset, int length, System.Base64FormattingOptions options) { throw null; }
+ public static bool ToBoolean(bool value) { throw null; }
+ public static bool ToBoolean(byte value) { throw null; }
+ public static bool ToBoolean(char value) { throw null; }
+ public static bool ToBoolean(System.DateTime value) { throw null; }
+ public static bool ToBoolean(decimal value) { throw null; }
+ public static bool ToBoolean(double value) { throw null; }
+ public static bool ToBoolean(short value) { throw null; }
+ public static bool ToBoolean(int value) { throw null; }
+ public static bool ToBoolean(long value) { throw null; }
+ public static bool ToBoolean(object value) { throw null; }
+ public static bool ToBoolean(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool ToBoolean(sbyte value) { throw null; }
+ public static bool ToBoolean(float value) { throw null; }
+ public static bool ToBoolean(string value) { throw null; }
+ public static bool ToBoolean(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool ToBoolean(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool ToBoolean(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool ToBoolean(ulong value) { throw null; }
+ public static byte ToByte(bool value) { throw null; }
+ public static byte ToByte(byte value) { throw null; }
+ public static byte ToByte(char value) { throw null; }
+ public static byte ToByte(System.DateTime value) { throw null; }
+ public static byte ToByte(decimal value) { throw null; }
+ public static byte ToByte(double value) { throw null; }
+ public static byte ToByte(short value) { throw null; }
+ public static byte ToByte(int value) { throw null; }
+ public static byte ToByte(long value) { throw null; }
+ public static byte ToByte(object value) { throw null; }
+ public static byte ToByte(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte ToByte(sbyte value) { throw null; }
+ public static byte ToByte(float value) { throw null; }
+ public static byte ToByte(string value) { throw null; }
+ public static byte ToByte(string value, System.IFormatProvider provider) { throw null; }
+ public static byte ToByte(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte ToByte(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte ToByte(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static byte ToByte(ulong value) { throw null; }
+ public static char ToChar(bool value) { throw null; }
+ public static char ToChar(byte value) { throw null; }
+ public static char ToChar(char value) { throw null; }
+ public static char ToChar(System.DateTime value) { throw null; }
+ public static char ToChar(decimal value) { throw null; }
+ public static char ToChar(double value) { throw null; }
+ public static char ToChar(short value) { throw null; }
+ public static char ToChar(int value) { throw null; }
+ public static char ToChar(long value) { throw null; }
+ public static char ToChar(object value) { throw null; }
+ public static char ToChar(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static char ToChar(sbyte value) { throw null; }
+ public static char ToChar(float value) { throw null; }
+ public static char ToChar(string value) { throw null; }
+ public static char ToChar(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static char ToChar(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static char ToChar(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static char ToChar(ulong value) { throw null; }
+ public static System.DateTime ToDateTime(bool value) { throw null; }
+ public static System.DateTime ToDateTime(byte value) { throw null; }
+ public static System.DateTime ToDateTime(char value) { throw null; }
+ public static System.DateTime ToDateTime(System.DateTime value) { throw null; }
+ public static System.DateTime ToDateTime(decimal value) { throw null; }
+ public static System.DateTime ToDateTime(double value) { throw null; }
+ public static System.DateTime ToDateTime(short value) { throw null; }
+ public static System.DateTime ToDateTime(int value) { throw null; }
+ public static System.DateTime ToDateTime(long value) { throw null; }
+ public static System.DateTime ToDateTime(object value) { throw null; }
+ public static System.DateTime ToDateTime(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.DateTime ToDateTime(sbyte value) { throw null; }
+ public static System.DateTime ToDateTime(float value) { throw null; }
+ public static System.DateTime ToDateTime(string value) { throw null; }
+ public static System.DateTime ToDateTime(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.DateTime ToDateTime(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.DateTime ToDateTime(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.DateTime ToDateTime(ulong value) { throw null; }
+ public static decimal ToDecimal(bool value) { throw null; }
+ public static decimal ToDecimal(byte value) { throw null; }
+ public static decimal ToDecimal(char value) { throw null; }
+ public static decimal ToDecimal(System.DateTime value) { throw null; }
+ public static decimal ToDecimal(decimal value) { throw null; }
+ public static decimal ToDecimal(double value) { throw null; }
+ public static decimal ToDecimal(short value) { throw null; }
+ public static decimal ToDecimal(int value) { throw null; }
+ public static decimal ToDecimal(long value) { throw null; }
+ public static decimal ToDecimal(object value) { throw null; }
+ public static decimal ToDecimal(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static decimal ToDecimal(sbyte value) { throw null; }
+ public static decimal ToDecimal(float value) { throw null; }
+ public static decimal ToDecimal(string value) { throw null; }
+ public static decimal ToDecimal(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static decimal ToDecimal(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static decimal ToDecimal(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static decimal ToDecimal(ulong value) { throw null; }
+ public static double ToDouble(bool value) { throw null; }
+ public static double ToDouble(byte value) { throw null; }
+ public static double ToDouble(char value) { throw null; }
+ public static double ToDouble(System.DateTime value) { throw null; }
+ public static double ToDouble(decimal value) { throw null; }
+ public static double ToDouble(double value) { throw null; }
+ public static double ToDouble(short value) { throw null; }
+ public static double ToDouble(int value) { throw null; }
+ public static double ToDouble(long value) { throw null; }
+ public static double ToDouble(object value) { throw null; }
+ public static double ToDouble(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static double ToDouble(sbyte value) { throw null; }
+ public static double ToDouble(float value) { throw null; }
+ public static double ToDouble(string value) { throw null; }
+ public static double ToDouble(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static double ToDouble(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static double ToDouble(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static double ToDouble(ulong value) { throw null; }
+ public static short ToInt16(bool value) { throw null; }
+ public static short ToInt16(byte value) { throw null; }
+ public static short ToInt16(char value) { throw null; }
+ public static short ToInt16(System.DateTime value) { throw null; }
+ public static short ToInt16(decimal value) { throw null; }
+ public static short ToInt16(double value) { throw null; }
+ public static short ToInt16(short value) { throw null; }
+ public static short ToInt16(int value) { throw null; }
+ public static short ToInt16(long value) { throw null; }
+ public static short ToInt16(object value) { throw null; }
+ public static short ToInt16(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static short ToInt16(sbyte value) { throw null; }
+ public static short ToInt16(float value) { throw null; }
+ public static short ToInt16(string value) { throw null; }
+ public static short ToInt16(string value, System.IFormatProvider provider) { throw null; }
+ public static short ToInt16(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static short ToInt16(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static short ToInt16(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static short ToInt16(ulong value) { throw null; }
+ public static int ToInt32(bool value) { throw null; }
+ public static int ToInt32(byte value) { throw null; }
+ public static int ToInt32(char value) { throw null; }
+ public static int ToInt32(System.DateTime value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int ToInt32(decimal value) { throw null; }
+ public static int ToInt32(double value) { throw null; }
+ public static int ToInt32(short value) { throw null; }
+ public static int ToInt32(int value) { throw null; }
+ public static int ToInt32(long value) { throw null; }
+ public static int ToInt32(object value) { throw null; }
+ public static int ToInt32(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int ToInt32(sbyte value) { throw null; }
+ public static int ToInt32(float value) { throw null; }
+ public static int ToInt32(string value) { throw null; }
+ public static int ToInt32(string value, System.IFormatProvider provider) { throw null; }
+ public static int ToInt32(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int ToInt32(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int ToInt32(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int ToInt32(ulong value) { throw null; }
+ public static long ToInt64(bool value) { throw null; }
+ public static long ToInt64(byte value) { throw null; }
+ public static long ToInt64(char value) { throw null; }
+ public static long ToInt64(System.DateTime value) { throw null; }
+ public static long ToInt64(decimal value) { throw null; }
+ public static long ToInt64(double value) { throw null; }
+ public static long ToInt64(short value) { throw null; }
+ public static long ToInt64(int value) { throw null; }
+ public static long ToInt64(long value) { throw null; }
+ public static long ToInt64(object value) { throw null; }
+ public static long ToInt64(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static long ToInt64(sbyte value) { throw null; }
+ public static long ToInt64(float value) { throw null; }
+ public static long ToInt64(string value) { throw null; }
+ public static long ToInt64(string value, System.IFormatProvider provider) { throw null; }
+ public static long ToInt64(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static long ToInt64(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static long ToInt64(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static long ToInt64(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(bool value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(byte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(char value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(System.DateTime value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(double value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(short value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(int value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(string value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(ulong value) { throw null; }
+ public static float ToSingle(bool value) { throw null; }
+ public static float ToSingle(byte value) { throw null; }
+ public static float ToSingle(char value) { throw null; }
+ public static float ToSingle(System.DateTime value) { throw null; }
+ public static float ToSingle(decimal value) { throw null; }
+ public static float ToSingle(double value) { throw null; }
+ public static float ToSingle(short value) { throw null; }
+ public static float ToSingle(int value) { throw null; }
+ public static float ToSingle(long value) { throw null; }
+ public static float ToSingle(object value) { throw null; }
+ public static float ToSingle(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static float ToSingle(sbyte value) { throw null; }
+ public static float ToSingle(float value) { throw null; }
+ public static float ToSingle(string value) { throw null; }
+ public static float ToSingle(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static float ToSingle(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static float ToSingle(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static float ToSingle(ulong value) { throw null; }
+ public static string ToString(bool value) { throw null; }
+ public static string ToString(bool value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(byte value) { throw null; }
+ public static string ToString(byte value, System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ToString(byte value, int toBase) { throw null; }
+ public static string ToString(char value) { throw null; }
+ public static string ToString(char value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(System.DateTime value) { throw null; }
+ public static string ToString(System.DateTime value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(decimal value) { throw null; }
+ public static string ToString(decimal value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(double value) { throw null; }
+ public static string ToString(double value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(short value) { throw null; }
+ public static string ToString(short value, System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ToString(short value, int toBase) { throw null; }
+ public static string ToString(int value) { throw null; }
+ public static string ToString(int value, System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ToString(int value, int toBase) { throw null; }
+ public static string ToString(long value) { throw null; }
+ public static string ToString(long value, System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ToString(long value, int toBase) { throw null; }
+ public static string ToString(object value) { throw null; }
+ public static string ToString(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(sbyte value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(float value) { throw null; }
+ public static string ToString(float value, System.IFormatProvider provider) { throw null; }
+ public static string ToString(string value) { throw null; }
+ public static string ToString(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(ushort value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(uint value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static string ToString(ulong value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(bool value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(byte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(char value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(System.DateTime value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(double value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(short value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(int value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(string value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(bool value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(byte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(char value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(System.DateTime value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(double value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(short value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(int value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(string value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint ToUInt32(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(bool value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(byte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(char value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(System.DateTime value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(double value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(short value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(int value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(object value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(string value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(string value, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(string value, int fromBase) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong ToUInt64(ulong value) { throw null; }
+ }
+ public delegate TOutput Converter<in TInput, out TOutput>(TInput input);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DataMisalignedException : System.SystemException
+ {
+ public DataMisalignedException() { }
+ public DataMisalignedException(string message) { }
+ public DataMisalignedException(string message, System.Exception innerException) { }
+ }
+ public partial struct DateTime : System.IComparable, System.IComparable<System.DateTime>, System.IConvertible, System.IEquatable<System.DateTime>, System.IFormattable, System.Runtime.Serialization.ISerializable
+ {
+ public static readonly System.DateTime MaxValue;
+ public static readonly System.DateTime MinValue;
+ public DateTime(int year, int month, int day) { throw null;}
+ public DateTime(int year, int month, int day, System.Globalization.Calendar calendar) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, System.DateTimeKind kind) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, System.Globalization.Calendar calendar) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.DateTimeKind kind) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar) { throw null;}
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar, System.DateTimeKind kind) { throw null;}
+ public DateTime(long ticks) { throw null;}
+ public DateTime(long ticks, System.DateTimeKind kind) { throw null;}
+ public System.DateTime Date { get { throw null; } }
+ public int Day { get { throw null; } }
+ public System.DayOfWeek DayOfWeek { get { throw null; } }
+ public int DayOfYear { get { throw null; } }
+ public int Hour { get { throw null; } }
+ public System.DateTimeKind Kind { get { throw null; } }
+ public int Millisecond { get { throw null; } }
+ public int Minute { get { throw null; } }
+ public int Month { get { throw null; } }
+ public static System.DateTime Now { get { throw null; } }
+ public int Second { get { throw null; } }
+ public long Ticks { get { throw null; } }
+ public System.TimeSpan TimeOfDay { get { throw null; } }
+ public static System.DateTime Today { get { throw null; } }
+ public static System.DateTime UtcNow { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public int Year { get { throw null; } }
+ public System.DateTime Add(System.TimeSpan value) { throw null; }
+ public System.DateTime AddDays(double value) { throw null; }
+ public System.DateTime AddHours(double value) { throw null; }
+ public System.DateTime AddMilliseconds(double value) { throw null; }
+ public System.DateTime AddMinutes(double value) { throw null; }
+ public System.DateTime AddMonths(int months) { throw null; }
+ public System.DateTime AddSeconds(double value) { throw null; }
+ public System.DateTime AddTicks(long value) { throw null; }
+ public System.DateTime AddYears(int value) { throw null; }
+ public static int Compare(System.DateTime t1, System.DateTime t2) { throw null; }
+ public int CompareTo(System.DateTime value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public static int DaysInMonth(int year, int month) { throw null; }
+ public bool Equals(System.DateTime value) { throw null; }
+ public static bool Equals(System.DateTime t1, System.DateTime t2) { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public static System.DateTime FromBinary(long dateData) { throw null; }
+ public static System.DateTime FromFileTime(long fileTime) { throw null; }
+ public static System.DateTime FromFileTimeUtc(long fileTime) { throw null; }
+ public static System.DateTime FromOADate(double d) { throw null; }
+ public string[] GetDateTimeFormats() { throw null; }
+ public string[] GetDateTimeFormats(char format) { throw null; }
+ public string[] GetDateTimeFormats(char format, System.IFormatProvider provider) { throw null; }
+ public string[] GetDateTimeFormats(System.IFormatProvider provider) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public bool IsDaylightSavingTime() { throw null; }
+ public static bool IsLeapYear(int year) { throw null; }
+ public static System.DateTime operator +(System.DateTime d, System.TimeSpan t) { throw null; }
+ public static bool operator ==(System.DateTime d1, System.DateTime d2) { throw null; }
+ public static bool operator >(System.DateTime t1, System.DateTime t2) { throw null; }
+ public static bool operator >=(System.DateTime t1, System.DateTime t2) { throw null; }
+ public static bool operator !=(System.DateTime d1, System.DateTime d2) { throw null; }
+ public static bool operator <(System.DateTime t1, System.DateTime t2) { throw null; }
+ public static bool operator <=(System.DateTime t1, System.DateTime t2) { throw null; }
+ public static System.TimeSpan operator -(System.DateTime d1, System.DateTime d2) { throw null; }
+ public static System.DateTime operator -(System.DateTime d, System.TimeSpan t) { throw null; }
+ public static System.DateTime Parse(string s) { throw null; }
+ public static System.DateTime Parse(string s, System.IFormatProvider provider) { throw null; }
+ public static System.DateTime Parse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles) { throw null; }
+ public static System.DateTime ParseExact(string s, string format, System.IFormatProvider provider) { throw null; }
+ public static System.DateTime ParseExact(string s, string format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style) { throw null; }
+ public static System.DateTime ParseExact(string s, string[] formats, System.IFormatProvider provider, System.Globalization.DateTimeStyles style) { throw null; }
+ public static System.DateTime SpecifyKind(System.DateTime value, System.DateTimeKind kind) { throw null; }
+ public System.TimeSpan Subtract(System.DateTime value) { throw null; }
+ public System.DateTime Subtract(System.TimeSpan value) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public long ToBinary() { throw null; }
+ public long ToFileTime() { throw null; }
+ public long ToFileTimeUtc() { throw null; }
+ public System.DateTime ToLocalTime() { throw null; }
+ public string ToLongDateString() { throw null; }
+ public string ToLongTimeString() { throw null; }
+ public double ToOADate() { throw null; }
+ public string ToShortDateString() { throw null; }
+ public string ToShortTimeString() { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public string ToString(string format) { throw null; }
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public System.DateTime ToUniversalTime() { throw null; }
+ public static bool TryParse(string s, out System.DateTime result) { result = default(System.DateTime); throw null; }
+ public static bool TryParse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles, out System.DateTime result) { result = default(System.DateTime); throw null; }
+ public static bool TryParseExact(string s, string format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { result = default(System.DateTime); throw null; }
+ public static bool TryParseExact(string s, string[] formats, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateTime result) { result = default(System.DateTime); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DateTimeKind
+ {
+ Local = 2,
+ Unspecified = 0,
+ Utc = 1,
+ }
+ public partial struct DateTimeOffset : System.IComparable, System.IComparable<System.DateTimeOffset>, System.IEquatable<System.DateTimeOffset>, System.IFormattable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable
+ {
+ public static readonly System.DateTimeOffset MaxValue;
+ public static readonly System.DateTimeOffset MinValue;
+ public DateTimeOffset(System.DateTime dateTime) { throw null; }
+ public DateTimeOffset(System.DateTime dateTime, System.TimeSpan offset) { throw null; }
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar, System.TimeSpan offset) { throw null; }
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, System.TimeSpan offset) { throw null; }
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, System.TimeSpan offset) { throw null; }
+ public DateTimeOffset(long ticks, System.TimeSpan offset) { throw null; }
+ public System.DateTime Date { get { throw null; } }
+ public System.DateTime DateTime { get { throw null; } }
+ public int Day { get { throw null; } }
+ public System.DayOfWeek DayOfWeek { get { throw null; } }
+ public int DayOfYear { get { throw null; } }
+ public int Hour { get { throw null; } }
+ public System.DateTime LocalDateTime { get { throw null; } }
+ public int Millisecond { get { throw null; } }
+ public int Minute { get { throw null; } }
+ public int Month { get { throw null; } }
+ public static System.DateTimeOffset Now { get { throw null; } }
+ public System.TimeSpan Offset { get { throw null; } }
+ public int Second { get { throw null; } }
+ public long Ticks { get { throw null; } }
+ public System.TimeSpan TimeOfDay { get { throw null; } }
+ public System.DateTime UtcDateTime { get { throw null; } }
+ public static System.DateTimeOffset UtcNow { get { throw null; } }
+ public long UtcTicks { get { throw null; } }
+ public int Year { get { throw null; } }
+ public System.DateTimeOffset Add(System.TimeSpan timeSpan) { throw null; }
+ public System.DateTimeOffset AddDays(double days) { throw null; }
+ public System.DateTimeOffset AddHours(double hours) { throw null; }
+ public System.DateTimeOffset AddMilliseconds(double milliseconds) { throw null; }
+ public System.DateTimeOffset AddMinutes(double minutes) { throw null; }
+ public System.DateTimeOffset AddMonths(int months) { throw null; }
+ public System.DateTimeOffset AddSeconds(double seconds) { throw null; }
+ public System.DateTimeOffset AddTicks(long ticks) { throw null; }
+ public System.DateTimeOffset AddYears(int years) { throw null; }
+ public static int Compare(System.DateTimeOffset first, System.DateTimeOffset second) { throw null; }
+ public int CompareTo(System.DateTimeOffset other) { throw null; }
+ public bool Equals(System.DateTimeOffset other) { throw null; }
+ public static bool Equals(System.DateTimeOffset first, System.DateTimeOffset second) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool EqualsExact(System.DateTimeOffset other) { throw null; }
+ public static System.DateTimeOffset FromFileTime(long fileTime) { throw null; }
+ public static System.DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) { throw null; }
+ public static System.DateTimeOffset FromUnixTimeSeconds(long seconds) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static System.DateTimeOffset operator +(System.DateTimeOffset dateTimeOffset, System.TimeSpan timeSpan) { throw null; }
+ public static bool operator ==(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static bool operator >(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static bool operator >=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static implicit operator System.DateTimeOffset(System.DateTime dateTime) { throw null; }
+ public static bool operator !=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static bool operator <(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static bool operator <=(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static System.TimeSpan operator -(System.DateTimeOffset left, System.DateTimeOffset right) { throw null; }
+ public static System.DateTimeOffset operator -(System.DateTimeOffset dateTimeOffset, System.TimeSpan timeSpan) { throw null; }
+ public static System.DateTimeOffset Parse(string input) { throw null; }
+ public static System.DateTimeOffset Parse(string input, System.IFormatProvider formatProvider) { throw null; }
+ public static System.DateTimeOffset Parse(string input, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles) { throw null; }
+ public static System.DateTimeOffset ParseExact(string input, string format, System.IFormatProvider formatProvider) { throw null; }
+ public static System.DateTimeOffset ParseExact(string input, string format, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles) { throw null; }
+ public static System.DateTimeOffset ParseExact(string input, string[] formats, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles) { throw null; }
+ public System.TimeSpan Subtract(System.DateTimeOffset value) { throw null; }
+ public System.DateTimeOffset Subtract(System.TimeSpan value) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public long ToFileTime() { throw null; }
+ public System.DateTimeOffset ToLocalTime() { throw null; }
+ public System.DateTimeOffset ToOffset(System.TimeSpan offset) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider formatProvider) { throw null; }
+ public string ToString(string format) { throw null; }
+ public string ToString(string format, System.IFormatProvider formatProvider) { throw null; }
+ public System.DateTimeOffset ToUniversalTime() { throw null; }
+ public long ToUnixTimeMilliseconds() { throw null; }
+ public long ToUnixTimeSeconds() { throw null; }
+ public static bool TryParse(string input, out System.DateTimeOffset result) { result = default(System.DateTimeOffset); throw null; }
+ public static bool TryParse(string input, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { result = default(System.DateTimeOffset); throw null; }
+ public static bool TryParseExact(string input, string format, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { result = default(System.DateTimeOffset); throw null; }
+ public static bool TryParseExact(string input, string[] formats, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) { result = default(System.DateTimeOffset); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DayOfWeek
+ {
+ Friday = 5,
+ Monday = 1,
+ Saturday = 6,
+ Sunday = 0,
+ Thursday = 4,
+ Tuesday = 2,
+ Wednesday = 3,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DBNull : System.IConvertible, System.Runtime.Serialization.ISerializable
+ {
+ internal DBNull() { }
+ public static readonly System.DBNull Value;
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public System.TypeCode GetTypeCode() { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Decimal : System.IComparable, System.IComparable<decimal>, System.IConvertible, System.IEquatable<decimal>, System.IFormattable, System.Runtime.Serialization.IDeserializationCallback
+ {
+ [System.Runtime.CompilerServices.DecimalConstantAttribute((byte)0, (byte)0, (uint)4294967295, (uint)4294967295, (uint)4294967295)]
+ public static readonly decimal MaxValue;
+ [System.Runtime.CompilerServices.DecimalConstantAttribute((byte)0, (byte)128, (uint)0, (uint)0, (uint)1)]
+ public static readonly decimal MinusOne;
+ [System.Runtime.CompilerServices.DecimalConstantAttribute((byte)0, (byte)128, (uint)4294967295, (uint)4294967295, (uint)4294967295)]
+ public static readonly decimal MinValue;
+ [System.Runtime.CompilerServices.DecimalConstantAttribute((byte)0, (byte)0, (uint)0, (uint)0, (uint)1)]
+ public static readonly decimal One;
+ [System.Runtime.CompilerServices.DecimalConstantAttribute((byte)0, (byte)0, (uint)0, (uint)0, (uint)0)]
+ public static readonly decimal Zero;
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Decimal(double value) { throw null; }
+ public Decimal(int value) { throw null; }
+ public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) { throw null; }
+ public Decimal(int[] bits) { throw null; }
+ public Decimal(long value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Decimal(float value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public Decimal(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public Decimal(ulong value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Add(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal Ceiling(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int Compare(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int CompareTo(System.Decimal value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int CompareTo(object value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Divide(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Equals(System.Decimal value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool Equals(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Floor(System.Decimal d) { throw null; }
+ public static System.Decimal FromOACurrency(long cy) { throw null; }
+ public static int[] GetBits(System.Decimal d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Multiply(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal Negate(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal operator +(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal operator --(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal operator /(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator ==(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static explicit operator byte(System.Decimal value) { throw null; }
+ public static explicit operator char(System.Decimal value) { throw null; }
+ public static explicit operator double(System.Decimal value) { throw null; }
+ public static explicit operator short(System.Decimal value) { throw null; }
+ public static explicit operator int(System.Decimal value) { throw null; }
+ public static explicit operator long(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static explicit operator sbyte(System.Decimal value) { throw null; }
+ public static explicit operator float(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static explicit operator ushort(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static explicit operator uint(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static explicit operator ulong(System.Decimal value) { throw null; }
+ public static explicit operator System.Decimal(double value) { throw null; }
+ public static explicit operator System.Decimal(float value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator >(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator >=(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static implicit operator System.Decimal(byte value) { throw null; }
+ public static implicit operator System.Decimal(char value) { throw null; }
+ public static implicit operator System.Decimal(short value) { throw null; }
+ public static implicit operator System.Decimal(int value) { throw null; }
+ public static implicit operator System.Decimal(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static implicit operator System.Decimal(sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static implicit operator System.Decimal(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static implicit operator System.Decimal(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static implicit operator System.Decimal(ulong value) { throw null; }
+ public static System.Decimal operator ++(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator !=(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator <(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator <=(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal operator %(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal operator *(System.Decimal d1, System.Decimal d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal operator -(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal operator -(System.Decimal d) { throw null; }
+ public static System.Decimal operator +(System.Decimal d) { throw null; }
+ public static System.Decimal Parse(string s) { throw null; }
+ public static System.Decimal Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Decimal Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Decimal Parse(string s, System.IFormatProvider provider) { throw null; }
+ public static System.Decimal Remainder(System.Decimal d1, System.Decimal d2) { throw null; }
+ public static System.Decimal Round(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Round(System.Decimal d, int decimals) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Round(System.Decimal d, int decimals, System.MidpointRounding mode) { throw null; }
+ public static System.Decimal Round(System.Decimal d, System.MidpointRounding mode) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Subtract(System.Decimal d1, System.Decimal d2) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ System.Decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ public static byte ToByte(System.Decimal value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static double ToDouble(System.Decimal d) { throw null; }
+ public static short ToInt16(System.Decimal value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int ToInt32(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static long ToInt64(System.Decimal d) { throw null; }
+ public static long ToOACurrency(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte ToSByte(System.Decimal value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static float ToSingle(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort ToUInt16(System.Decimal value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static uint ToUInt32(System.Decimal d) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static ulong ToUInt64(System.Decimal d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Decimal Truncate(System.Decimal d) { throw null; }
+ public static bool TryParse(string s, out System.Decimal result) { result = default(decimal); throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Decimal result) { result = default(decimal); throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(2))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Delegate : System.ICloneable, System.Runtime.Serialization.ISerializable
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected Delegate(object target, string method) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected Delegate(System.Type target, string method) { }
+ public System.Reflection.MethodInfo Method { get { throw null; } }
+ public object Target { get { throw null; } }
+ public virtual object Clone() { throw null; }
+ public static System.Delegate Combine(System.Delegate a, System.Delegate b) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static System.Delegate Combine(params System.Delegate[] delegates) { throw null; }
+ protected virtual System.Delegate CombineImpl(System.Delegate d) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, object firstArgument, System.Reflection.MethodInfo method) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Delegate CreateDelegate(System.Type type, object firstArgument, System.Reflection.MethodInfo method, bool throwOnBindFailure) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, object target, string method) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, object target, string method, bool ignoreCase) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Delegate CreateDelegate(System.Type type, object target, string method, bool ignoreCase, bool throwOnBindFailure) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, System.Reflection.MethodInfo method) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Delegate CreateDelegate(System.Type type, System.Reflection.MethodInfo method, bool throwOnBindFailure) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, System.Type target, string method) { throw null; }
+ public static System.Delegate CreateDelegate(System.Type type, System.Type target, string method, bool ignoreCase) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Delegate CreateDelegate(System.Type type, System.Type target, string method, bool ignoreCase, bool throwOnBindFailure) { throw null; }
+ public object DynamicInvoke(params object[] args) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected virtual object DynamicInvokeImpl(object[] args) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public virtual System.Delegate[] GetInvocationList() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected virtual System.Reflection.MethodInfo GetMethodImpl() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public static bool operator ==(System.Delegate d1, System.Delegate d2) { throw null; }
+ public static bool operator !=(System.Delegate d1, System.Delegate d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Delegate Remove(System.Delegate source, System.Delegate value) { throw null; }
+ public static System.Delegate RemoveAll(System.Delegate source, System.Delegate value) { throw null; }
+ protected virtual System.Delegate RemoveImpl(System.Delegate d) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class DivideByZeroException : System.ArithmeticException
+ {
+ public DivideByZeroException() { }
+ public DivideByZeroException(string message) { }
+ public DivideByZeroException(string message, System.Exception innerException) { }
+ protected DivideByZeroException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class DllNotFoundException : System.TypeLoadException
+ {
+ public DllNotFoundException() { }
+ public DllNotFoundException(string message) { }
+ public DllNotFoundException(string message, System.Exception inner) { }
+ protected DllNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Double : System.IComparable, System.IComparable<double>, System.IConvertible, System.IEquatable<double>, System.IFormattable
+ {
+ public const double Epsilon = 4.94065645841247E-324;
+ public const double MaxValue = 1.7976931348623157E+308;
+ public const double MinValue = -1.7976931348623157E+308;
+ public const double NaN = 0.0 / 0.0;
+ public const double NegativeInfinity = -1.0 / 0.0;
+ public const double PositiveInfinity = 1.0 / 0.0;
+ public int CompareTo(System.Double value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public bool Equals(System.Double obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsInfinity(System.Double d) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsNaN(System.Double d) { throw null; }
+ public static bool IsNegativeInfinity(System.Double d) { throw null; }
+ public static bool IsPositiveInfinity(System.Double d) { throw null; }
+ public static bool operator ==(System.Double left, System.Double right) { throw null; }
+ public static bool operator >(System.Double left, System.Double right) { throw null; }
+ public static bool operator >=(System.Double left, System.Double right) { throw null; }
+ public static bool operator !=(System.Double left, System.Double right) { throw null; }
+ public static bool operator <(System.Double left, System.Double right) { throw null; }
+ public static bool operator <=(System.Double left, System.Double right) { throw null; }
+ public static System.Double Parse(string s) { throw null; }
+ public static System.Double Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Double Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Double Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ System.Double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, out System.Double result) { result = default(double); throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Double result) { result = default(double); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class DuplicateWaitObjectException : System.ArgumentException
+ {
+ public DuplicateWaitObjectException() { }
+ public DuplicateWaitObjectException(string parameterName) { }
+ public DuplicateWaitObjectException(string message, System.Exception innerException) { }
+ public DuplicateWaitObjectException(string parameterName, string message) { }
+ protected DuplicateWaitObjectException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class EntryPointNotFoundException : System.TypeLoadException
+ {
+ public EntryPointNotFoundException() { }
+ public EntryPointNotFoundException(string message) { }
+ public EntryPointNotFoundException(string message, System.Exception inner) { }
+ protected EntryPointNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Enum : System.ValueType, System.IComparable, System.IConvertible, System.IFormattable
+ {
+ protected Enum() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int CompareTo(object target) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static string Format(System.Type enumType, object value, string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static string GetName(System.Type enumType, object value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static string[] GetNames(System.Type enumType) { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static System.Type GetUnderlyingType(System.Type enumType) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static System.Array GetValues(System.Type enumType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool HasFlag(System.Enum flag) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static bool IsDefined(System.Type enumType, object value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static object Parse(System.Type enumType, string value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static object Parse(System.Type enumType, string value, bool ignoreCase) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, byte value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, short value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, int value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, long value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static object ToObject(System.Type enumType, object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, sbyte value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static object ToObject(System.Type enumType, ulong value) { throw null; }
+ public override string ToString() { throw null; }
+ [System.ObsoleteAttribute("The provider argument is not used. Please use ToString().")]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public string ToString(string format) { throw null; }
+ [System.ObsoleteAttribute("The provider argument is not used. Please use ToString(String).")]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse<TEnum>(string value, out TEnum result) where TEnum : struct { result = default(TEnum); throw null; }
+ public static bool TryParse<TEnum>(string value, bool ignoreCase, out TEnum result) where TEnum : struct { result = default(TEnum); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Environment
+ {
+ public static int CurrentManagedThreadId { get { throw null; } }
+ public static int ExitCode { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]set { } }
+ public static bool HasShutdownStarted { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public static string MachineName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static string NewLine { get { throw null; } }
+ public static System.OperatingSystem OSVersion { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static int ProcessorCount { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static string StackTrace { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static int TickCount { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public static System.Version Version { get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public static void Exit(int exitCode) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string ExpandEnvironmentVariables(string name) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static void FailFast(string message) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static void FailFast(string message, System.Exception exception) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string[] GetCommandLineArgs() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetEnvironmentVariable(string variable) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Collections.IDictionary GetEnvironmentVariables() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SetEnvironmentVariable(string variable, string value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class EventArgs
+ {
+ public static readonly System.EventArgs Empty;
+ public EventArgs() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void EventHandler(object sender, System.EventArgs e);
+ public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class Exception : System.Runtime.Serialization.ISerializable
+ {
+ public Exception() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected Exception(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public Exception(string message) { }
+ public Exception(string message, System.Exception innerException) { }
+ public virtual System.Collections.IDictionary Data { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string HelpLink { get { throw null; } set { } }
+ public int HResult { get { throw null; } protected set { } }
+ public System.Exception InnerException { get { throw null; } }
+ public virtual string Message { get { throw null; } }
+ public virtual string Source { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ public virtual string StackTrace { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public System.Reflection.MethodBase TargetSite { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual System.Exception GetBaseException() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public new System.Type GetType() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ }
+ [System.ObsoleteAttribute("This type previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ExecutionEngineException : System.SystemException
+ {
+ public ExecutionEngineException() { }
+ public ExecutionEngineException(string message) { }
+ public ExecutionEngineException(string message, System.Exception innerException) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class FieldAccessException : System.MemberAccessException
+ {
+ public FieldAccessException() { }
+ public FieldAccessException(string message) { }
+ public FieldAccessException(string message, System.Exception inner) { }
+ protected FieldAccessException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(16), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class FlagsAttribute : System.Attribute
+ {
+ public FlagsAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class FormatException : System.SystemException
+ {
+ public FormatException() { }
+ public FormatException(string message) { }
+ public FormatException(string message, System.Exception innerException) { }
+ protected FormatException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ public abstract partial class FormattableString : System.IFormattable
+ {
+ protected FormattableString() { }
+ public abstract int ArgumentCount { get; }
+ public abstract string Format { get; }
+ public abstract object GetArgument(int index);
+ public abstract object[] GetArguments();
+ public static string Invariant(System.FormattableString formattable) { throw null; }
+ string System.IFormattable.ToString(string ignored, System.IFormatProvider formatProvider) { throw null; }
+ public override string ToString() { throw null; }
+ public abstract string ToString(System.IFormatProvider formatProvider);
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate TResult Func<out TResult>();
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate TResult Func<in T, out TResult>(T arg);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 arg1, T2 arg2, T3 arg3);
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=2.0.5.0, Culture=Neutral, PublicKeyToken=7cec85d7bea7798e")]
+ public delegate TResult Func<in T1, in T2, in T3, in T4, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+ public static partial class GC
+ {
+ public static int MaxGeneration { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public static void AddMemoryPressure(long bytesAllocated) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void CancelFullGCNotification() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Collect() { }
+ public static void Collect(int generation) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Collect(int generation, System.GCCollectionMode mode) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Collect(int generation, System.GCCollectionMode mode, bool blocking) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Collect(int generation, System.GCCollectionMode mode, bool blocking, bool compacting) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int CollectionCount(int generation) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int GetGeneration(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int GetGeneration(System.WeakReference wo) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static long GetTotalMemory(bool forceFullCollection) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static void KeepAlive(object obj) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void RemoveMemoryPressure(long bytesAllocated) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void ReRegisterForFinalize(object obj) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SuppressFinalize(object obj) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.GCNotificationStatus WaitForFullGCApproach() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.GCNotificationStatus WaitForFullGCApproach(int millisecondsTimeout) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.GCNotificationStatus WaitForFullGCComplete() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.GCNotificationStatus WaitForFullGCComplete(int millisecondsTimeout) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void WaitForPendingFinalizers() { }
+ }
+ public enum GCNotificationStatus
+ {
+ Canceled = 2,
+ Failed = 1,
+ NotApplicable = 4,
+ Succeeded = 0,
+ Timeout = 3,
+ }
+ public enum GCCollectionMode
+ {
+ Default = 0,
+ Forced = 1,
+ Optimized = 2,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Guid : System.IComparable, System.IComparable<System.Guid>, System.IEquatable<System.Guid>, System.IFormattable
+ {
+ public static readonly System.Guid Empty;
+ public Guid(byte[] b) { throw null;}
+ public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) { throw null;}
+ public Guid(int a, short b, short c, byte[] d) { throw null;}
+ public Guid(string g) { throw null;}
+ [System.CLSCompliantAttribute(false)]
+ public Guid(uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k) { throw null;}
+ public int CompareTo(System.Guid value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public bool Equals(System.Guid g) { throw null; }
+ public override bool Equals(object o) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Guid NewGuid() { throw null; }
+ public static bool operator ==(System.Guid a, System.Guid b) { throw null; }
+ public static bool operator !=(System.Guid a, System.Guid b) { throw null; }
+ public static System.Guid Parse(string input) { throw null; }
+ public static System.Guid ParseExact(string input, string format) { throw null; }
+ public byte[] ToByteArray() { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string input, out System.Guid result) { result = default(System.Guid); throw null; }
+ public static bool TryParseExact(string input, string format, out System.Guid result) { result = default(System.Guid); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IAsyncResult
+ {
+ object AsyncState { get; }
+ System.Threading.WaitHandle AsyncWaitHandle { get; }
+ bool CompletedSynchronously { get; }
+ bool IsCompleted { get; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ICloneable
+ {
+ object Clone();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IComparable
+ {
+ int CompareTo(object obj);
+ }
+ public partial interface IComparable<in T>
+ {
+ int CompareTo(T other);
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IConvertible
+ {
+ System.TypeCode GetTypeCode();
+ bool ToBoolean(System.IFormatProvider provider);
+ byte ToByte(System.IFormatProvider provider);
+ char ToChar(System.IFormatProvider provider);
+ System.DateTime ToDateTime(System.IFormatProvider provider);
+ decimal ToDecimal(System.IFormatProvider provider);
+ double ToDouble(System.IFormatProvider provider);
+ short ToInt16(System.IFormatProvider provider);
+ int ToInt32(System.IFormatProvider provider);
+ long ToInt64(System.IFormatProvider provider);
+ sbyte ToSByte(System.IFormatProvider provider);
+ float ToSingle(System.IFormatProvider provider);
+ string ToString(System.IFormatProvider provider);
+ object ToType(System.Type conversionType, System.IFormatProvider provider);
+ ushort ToUInt16(System.IFormatProvider provider);
+ uint ToUInt32(System.IFormatProvider provider);
+ ulong ToUInt64(System.IFormatProvider provider);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ICustomFormatter
+ {
+ string Format(string format, object arg, System.IFormatProvider formatProvider);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IDisposable
+ {
+ void Dispose();
+ }
+ public partial interface IEquatable<T>
+ {
+ bool Equals(T other);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IFormatProvider
+ {
+ object GetFormat(System.Type formatType);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IFormattable
+ {
+ string ToString(string format, System.IFormatProvider formatProvider);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class IndexOutOfRangeException : System.SystemException
+ {
+ public IndexOutOfRangeException() { }
+ public IndexOutOfRangeException(string message) { }
+ public IndexOutOfRangeException(string message, System.Exception innerException) { }
+ }
+ public sealed partial class InsufficientExecutionStackException : System.SystemException
+ {
+ public InsufficientExecutionStackException() { }
+ public InsufficientExecutionStackException(string message) { }
+ public InsufficientExecutionStackException(string message, System.Exception innerException) { }
+ }
+ public sealed partial class InsufficientMemoryException : System.OutOfMemoryException
+ {
+ public InsufficientMemoryException() { }
+ public InsufficientMemoryException(string message) { }
+ public InsufficientMemoryException(string message, System.Exception innerException) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Int16 : System.IComparable, System.IComparable<short>, System.IConvertible, System.IEquatable<short>, System.IFormattable
+ {
+ public const short MaxValue = (short)32767;
+ public const short MinValue = (short)-32768;
+ public int CompareTo(System.Int16 value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public bool Equals(System.Int16 obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Int16 Parse(string s) { throw null; }
+ public static System.Int16 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Int16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Int16 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ System.Int16 System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public string ToString(string format) { throw null; }
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int16 result) { result = default(short); throw null; }
+ public static bool TryParse(string s, out System.Int16 result) { result = default(short); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Int32 : System.IComparable, System.IComparable<int>, System.IConvertible, System.IEquatable<int>, System.IFormattable
+ {
+ public const int MaxValue = 2147483647;
+ public const int MinValue = -2147483648;
+ public System.Int32 CompareTo(System.Int32 value) { throw null; }
+ public System.Int32 CompareTo(object value) { throw null; }
+ public bool Equals(System.Int32 obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override System.Int32 GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Int32 Parse(string s) { throw null; }
+ public static System.Int32 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Int32 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Int32 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ System.Int32 System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int32 result) { result = default(int); throw null; }
+ public static bool TryParse(string s, out System.Int32 result) { result = default(int); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Int64 : System.IComparable, System.IComparable<long>, System.IConvertible, System.IEquatable<long>, System.IFormattable
+ {
+ public const long MaxValue = (long)9223372036854775807;
+ public const long MinValue = (long)-9223372036854775808;
+ public int CompareTo(System.Int64 value) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public bool Equals(System.Int64 obj) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public static System.Int64 Parse(string s) { throw null; }
+ public static System.Int64 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Int64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Int64 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ System.Int64 System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int64 result) { result = default(long); throw null; }
+ public static bool TryParse(string s, out System.Int64 result) { result = default(long); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct IntPtr : System.Runtime.Serialization.ISerializable
+ {
+ public static readonly System.IntPtr Zero;
+ [System.Security.SecuritySafeCriticalAttribute]
+ public IntPtr(int value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public IntPtr(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe IntPtr(void* value) { throw null; }
+ public static int Size { get { throw null; } }
+ public static System.IntPtr Add(System.IntPtr pointer, int offset) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public static System.IntPtr operator +(System.IntPtr pointer, int offset) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator ==(System.IntPtr value1, System.IntPtr value2) { throw null; }
+ public static explicit operator System.IntPtr(int value) { throw null; }
+ public static explicit operator System.IntPtr(long value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static explicit operator int(System.IntPtr value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static explicit operator long(System.IntPtr value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public unsafe static explicit operator void* (System.IntPtr value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static explicit operator System.IntPtr(void* value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator !=(System.IntPtr value1, System.IntPtr value2) { throw null; }
+ public static System.IntPtr operator -(System.IntPtr pointer, int offset) { throw null; }
+ public static System.IntPtr Subtract(System.IntPtr pointer, int offset) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int ToInt32() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public long ToInt64() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public unsafe void* ToPointer() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class InvalidCastException : System.SystemException
+ {
+ public InvalidCastException() { }
+ public InvalidCastException(string message) { }
+ public InvalidCastException(string message, System.Exception innerException) { }
+ public InvalidCastException(string message, int errorCode) { }
+ protected InvalidCastException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class InvalidOperationException : System.SystemException
+ {
+ public InvalidOperationException() { }
+ public InvalidOperationException(string message) { }
+ public InvalidOperationException(string message, System.Exception innerException) { }
+ protected InvalidOperationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class InvalidProgramException : System.SystemException
+ {
+ public InvalidProgramException() { }
+ public InvalidProgramException(string message) { }
+ public InvalidProgramException(string message, System.Exception inner) { }
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+ public partial class InvalidTimeZoneException : System.Exception
+ {
+ public InvalidTimeZoneException() { }
+ public InvalidTimeZoneException(string message) { }
+ public InvalidTimeZoneException(string message, System.Exception innerException) { }
+ protected InvalidTimeZoneException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ public partial interface IObservable<out T>
+ {
+ System.IDisposable Subscribe(System.IObserver<T> observer);
+ }
+ public partial interface IObserver<in T>
+ {
+ void OnCompleted();
+ void OnError(System.Exception error);
+ void OnNext(T value);
+ }
+ public partial interface IProgress<in T>
+ {
+ void Report(T value);
+ }
+ public partial interface IServiceProvider
+ {
+ object GetService(System.Type serviceType);
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class Lazy<T>
+ {
+ public Lazy() { }
+ public Lazy(T value) { }
+ public Lazy(bool isThreadSafe) { }
+ public Lazy(System.Func<T> valueFactory) { }
+ public Lazy(System.Func<T> valueFactory, bool isThreadSafe) { }
+ public Lazy(System.Func<T> valueFactory, System.Threading.LazyThreadSafetyMode mode) { }
+ public Lazy(System.Threading.LazyThreadSafetyMode mode) { }
+ public bool IsValueCreated { get { throw null; } }
+ [System.Diagnostics.DebuggerBrowsableAttribute((System.Diagnostics.DebuggerBrowsableState)(0))]
+ public T Value { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum LoaderOptimization
+ {
+ [System.ObsoleteAttribute("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ DisallowBindings = 4,
+ [System.ObsoleteAttribute("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ DomainMask = 3,
+ MultiDomain = 2,
+ MultiDomainHost = 3,
+ NotSpecified = 0,
+ SingleDomain = 1,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class LoaderOptimizationAttribute : System.Attribute
+ {
+ public LoaderOptimizationAttribute(byte value) { }
+ public LoaderOptimizationAttribute(System.LoaderOptimization value) { }
+ public System.LoaderOptimization Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class LocalDataStoreSlot
+ {
+ internal LocalDataStoreSlot() { }
+ ~LocalDataStoreSlot() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class MarshalByRefObject
+ {
+ protected MarshalByRefObject() { }
+ }
+ public static partial class Math
+ {
+ public const double E = 2.7182818284590451;
+ public const double PI = 3.1415926535897931;
+ public static decimal Abs(decimal value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Abs(double value) { throw null; }
+ public static short Abs(short value) { throw null; }
+ public static int Abs(int value) { throw null; }
+ public static long Abs(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte Abs(sbyte value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Abs(float value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Acos(double d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Asin(double d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Atan(double d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Atan2(double y, double x) { throw null; }
+ public static long BigMul(int a, int b) { throw null; }
+ public static decimal Ceiling(decimal d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Ceiling(double a) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Cos(double d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Cosh(double value) { throw null; }
+ public static int DivRem(int a, int b, out int result) { result = default(int); throw null; }
+ public static long DivRem(long a, long b, out long result) { result = default(long); throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Exp(double d) { throw null; }
+ public static decimal Floor(decimal d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Floor(double d) { throw null; }
+ public static double IEEERemainder(double x, double y) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Log(double d) { throw null; }
+ public static double Log(double a, double newBase) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Log10(double d) { throw null; }
+ public static byte Max(byte val1, byte val2) { throw null; }
+ public static decimal Max(decimal val1, decimal val2) { throw null; }
+ public static double Max(double val1, double val2) { throw null; }
+ public static short Max(short val1, short val2) { throw null; }
+ public static int Max(int val1, int val2) { throw null; }
+ public static long Max(long val1, long val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte Max(sbyte val1, sbyte val2) { throw null; }
+ public static float Max(float val1, float val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort Max(ushort val1, ushort val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint Max(uint val1, uint val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong Max(ulong val1, ulong val2) { throw null; }
+ public static byte Min(byte val1, byte val2) { throw null; }
+ public static decimal Min(decimal val1, decimal val2) { throw null; }
+ public static double Min(double val1, double val2) { throw null; }
+ public static short Min(short val1, short val2) { throw null; }
+ public static int Min(int val1, int val2) { throw null; }
+ public static long Min(long val1, long val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte Min(sbyte val1, sbyte val2) { throw null; }
+ public static float Min(float val1, float val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort Min(ushort val1, ushort val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint Min(uint val1, uint val2) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ulong Min(ulong val1, ulong val2) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Pow(double x, double y) { throw null; }
+ public static decimal Round(decimal d) { throw null; }
+ public static decimal Round(decimal d, int decimals) { throw null; }
+ public static decimal Round(decimal d, int decimals, System.MidpointRounding mode) { throw null; }
+ public static decimal Round(decimal d, System.MidpointRounding mode) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Round(double a) { throw null; }
+ public static double Round(double value, int digits) { throw null; }
+ public static double Round(double value, int digits, System.MidpointRounding mode) { throw null; }
+ public static double Round(double value, System.MidpointRounding mode) { throw null; }
+ public static int Sign(decimal value) { throw null; }
+ public static int Sign(double value) { throw null; }
+ public static int Sign(short value) { throw null; }
+ public static int Sign(int value) { throw null; }
+ public static int Sign(long value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static int Sign(sbyte value) { throw null; }
+ public static int Sign(float value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Sin(double a) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Sinh(double value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Sqrt(double d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Tan(double a) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Tanh(double value) { throw null; }
+ public static decimal Truncate(decimal d) { throw null; }
+ public static double Truncate(double d) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MemberAccessException : System.SystemException
+ {
+ public MemberAccessException() { }
+ public MemberAccessException(string message) { }
+ public MemberAccessException(string message, System.Exception inner) { }
+ protected MemberAccessException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MethodAccessException : System.MemberAccessException
+ {
+ public MethodAccessException() { }
+ public MethodAccessException(string message) { }
+ public MethodAccessException(string message, System.Exception inner) { }
+ protected MethodAccessException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MidpointRounding
+ {
+ AwayFromZero = 1,
+ ToEven = 0,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MissingFieldException : System.MissingMemberException, System.Runtime.Serialization.ISerializable
+ {
+ public MissingFieldException() { }
+ protected MissingFieldException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public MissingFieldException(string message) { }
+ public MissingFieldException(string message, System.Exception inner) { }
+ public MissingFieldException(string className, string fieldName) { }
+ public override string Message { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MissingMemberException : System.MemberAccessException, System.Runtime.Serialization.ISerializable
+ {
+ protected string ClassName;
+ protected string MemberName;
+ protected byte[] Signature;
+ public MissingMemberException() { }
+ protected MissingMemberException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public MissingMemberException(string message) { }
+ public MissingMemberException(string message, System.Exception inner) { }
+ public MissingMemberException(string className, string memberName) { }
+ public override string Message { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MissingMethodException : System.MissingMemberException, System.Runtime.Serialization.ISerializable
+ {
+ public MissingMethodException() { }
+ protected MissingMethodException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public MissingMethodException(string message) { }
+ public MissingMethodException(string message, System.Exception inner) { }
+ public MissingMethodException(string className, string methodName) { }
+ public override string Message { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public unsafe struct ModuleHandle
+ {
+ public static readonly System.ModuleHandle EmptyHandle;
+ public int MDStreamVersion { get { throw null; } }
+ public override int GetHashCode() { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public unsafe bool Equals(System.ModuleHandle handle) { throw null; }
+ public static bool operator ==(System.ModuleHandle left, System.ModuleHandle right) { throw null; }
+ public static bool operator !=(System.ModuleHandle left, System.ModuleHandle right) { throw null; }
+ public System.RuntimeTypeHandle GetRuntimeTypeHandleFromMetadataToken(int typeToken) { throw null; }
+ public System.RuntimeTypeHandle ResolveTypeHandle(int typeToken) { throw null; }
+ public System.RuntimeTypeHandle ResolveTypeHandle(int typeToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext) { throw null; }
+ public System.RuntimeMethodHandle GetRuntimeMethodHandleFromMetadataToken(int methodToken) { throw null; }
+ public System.RuntimeMethodHandle ResolveMethodHandle(int methodToken) { throw null; }
+ public System.RuntimeMethodHandle ResolveMethodHandle(int methodToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext) { throw null; }
+ public System.RuntimeFieldHandle GetRuntimeFieldHandleFromMetadataToken(int fieldToken) { throw null; }
+ public System.RuntimeFieldHandle ResolveFieldHandle(int fieldToken) { throw null; }
+ public System.RuntimeFieldHandle ResolveFieldHandle(int fieldToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext) { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class MTAThreadAttribute : System.Attribute
+ {
+ public MTAThreadAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class MulticastDelegate : System.Delegate
+ {
+ protected MulticastDelegate(object target, string method) : base (default(object), default(string)) { }
+ protected MulticastDelegate(System.Type target, string method) : base (default(object), default(string)) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected sealed override System.Delegate CombineImpl(System.Delegate follow) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sealed override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sealed override int GetHashCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sealed override System.Delegate[] GetInvocationList() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected override System.Reflection.MethodInfo GetMethodImpl() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public static bool operator ==(System.MulticastDelegate d1, System.MulticastDelegate d2) { throw null; }
+ public static bool operator !=(System.MulticastDelegate d1, System.MulticastDelegate d2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected sealed override System.Delegate RemoveImpl(System.Delegate value) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class MulticastNotSupportedException : System.SystemException
+ {
+ public MulticastNotSupportedException() { }
+ public MulticastNotSupportedException(string message) { }
+ public MulticastNotSupportedException(string message, System.Exception inner) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class NonSerializedAttribute : System.Attribute
+ {
+ public NonSerializedAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class NotFiniteNumberException : System.ArithmeticException
+ {
+ public NotFiniteNumberException() { }
+ public NotFiniteNumberException(double offendingNumber) { }
+ public NotFiniteNumberException(string message) { }
+ public NotFiniteNumberException(string message, double offendingNumber) { }
+ public NotFiniteNumberException(string message, double offendingNumber, System.Exception innerException) { }
+ public NotFiniteNumberException(string message, System.Exception innerException) { }
+ protected NotFiniteNumberException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public double OffendingNumber { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class NotImplementedException : System.SystemException
+ {
+ public NotImplementedException() { }
+ public NotImplementedException(string message) { }
+ public NotImplementedException(string message, System.Exception inner) { }
+ protected NotImplementedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class NotSupportedException : System.SystemException
+ {
+ public NotSupportedException() { }
+ public NotSupportedException(string message) { }
+ public NotSupportedException(string message, System.Exception innerException) { }
+ protected NotSupportedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Nullable
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static int Compare<T>(System.Nullable<T> n1, System.Nullable<T> n2) where T : struct { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static bool Equals<T>(System.Nullable<T> n1, System.Nullable<T> n2) where T : struct { throw null; }
+ public static System.Type GetUnderlyingType(System.Type nullableType) { throw null; }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Nullable<T> where T : struct
+ {
+ public Nullable(T value) { throw null;}
+ public bool HasValue { get { throw null; } }
+ public T Value { get { throw null; } }
+ public override bool Equals(object other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public T GetValueOrDefault() { throw null; }
+ public T GetValueOrDefault(T defaultValue) { throw null; }
+ public static explicit operator T (System.Nullable<T> value) { throw null; }
+ public static implicit operator System.Nullable<T> (T value) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class NullReferenceException : System.SystemException
+ {
+ public NullReferenceException() { }
+ public NullReferenceException(string message) { }
+ public NullReferenceException(string message, System.Exception innerException) { }
+ protected NullReferenceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(2))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class Object
+ {
+ public Object() { }
+ public virtual bool Equals(System.Object obj) { throw null; }
+ public static bool Equals(System.Object objA, System.Object objB) { throw null; }
+ ~Object() { }
+ public virtual int GetHashCode() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public System.Type GetType() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ protected System.Object MemberwiseClone() { throw null; }
+ public static bool ReferenceEquals(System.Object objA, System.Object objB) { throw null; }
+ public virtual string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ObjectDisposedException : System.InvalidOperationException
+ {
+ public ObjectDisposedException(string objectName) { }
+ public ObjectDisposedException(string message, System.Exception innerException) { }
+ public ObjectDisposedException(string objectName, string message) { }
+ protected ObjectDisposedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public override string Message { get { throw null; } }
+ public string ObjectName { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(6140), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ObsoleteAttribute : System.Attribute
+ {
+ public ObsoleteAttribute() { }
+ public ObsoleteAttribute(string message) { }
+ public ObsoleteAttribute(string message, bool error) { }
+ public bool IsError { get { throw null; } }
+ public string Message { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OperatingSystem : System.ICloneable, System.Runtime.Serialization.ISerializable
+ {
+ public OperatingSystem(System.PlatformID platform, System.Version version) { }
+ public System.PlatformID Platform { get { throw null; } }
+ public string ServicePack { get { throw null; } }
+ public System.Version Version { get { throw null; } }
+ public string VersionString { get { throw null; } }
+ public object Clone() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class OperationCanceledException : System.SystemException
+ {
+ public OperationCanceledException() { }
+ public OperationCanceledException(string message) { }
+ public OperationCanceledException(string message, System.Exception innerException) { }
+ public OperationCanceledException(string message, System.Exception innerException, System.Threading.CancellationToken token) { }
+ public OperationCanceledException(string message, System.Threading.CancellationToken token) { }
+ public OperationCanceledException(System.Threading.CancellationToken token) { }
+ protected OperationCanceledException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public System.Threading.CancellationToken CancellationToken { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class OutOfMemoryException : System.SystemException
+ {
+ public OutOfMemoryException() { }
+ public OutOfMemoryException(string message) { }
+ public OutOfMemoryException(string message, System.Exception innerException) { }
+ protected OutOfMemoryException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class OverflowException : System.ArithmeticException
+ {
+ public OverflowException() { }
+ public OverflowException(string message) { }
+ public OverflowException(string message, System.Exception innerException) { }
+ protected OverflowException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=true, AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ParamArrayAttribute : System.Attribute
+ {
+ public ParamArrayAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum PlatformID
+ {
+ MacOSX = 6,
+ Unix = 4,
+ Win32NT = 2,
+ Win32S = 0,
+ Win32Windows = 1,
+ WinCE = 3,
+ Xbox = 5,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class PlatformNotSupportedException : System.NotSupportedException
+ {
+ public PlatformNotSupportedException() { }
+ public PlatformNotSupportedException(string message) { }
+ public PlatformNotSupportedException(string message, System.Exception inner) { }
+ protected PlatformNotSupportedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ public delegate bool Predicate<in T>(T obj);
+ public partial class Progress<T> : System.IProgress<T>
+ {
+ public Progress() { }
+ public Progress(System.Action<T> handler) { }
+ public event System.EventHandler<T> ProgressChanged { add { } remove { } }
+ protected virtual void OnReport(T value) { }
+ void System.IProgress<T>.Report(T value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class Random
+ {
+ public Random() { }
+ public Random(int Seed) { }
+ public virtual int Next() { throw null; }
+ public virtual int Next(int maxValue) { throw null; }
+ public virtual int Next(int minValue, int maxValue) { throw null; }
+ public virtual void NextBytes(byte[] buffer) { }
+ public virtual double NextDouble() { throw null; }
+ protected virtual double Sample() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class RankException : System.SystemException
+ {
+ public RankException() { }
+ public RankException(string message) { }
+ public RankException(string message, System.Exception innerException) { }
+ protected RankException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ResolveEventArgs : System.EventArgs
+ {
+ public ResolveEventArgs(string name) { }
+ public ResolveEventArgs(string name, System.Reflection.Assembly requestingAssembly) { }
+ public string Name { get { throw null; } }
+ public System.Reflection.Assembly RequestingAssembly { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public delegate System.Reflection.Assembly ResolveEventHandler(object sender, System.ResolveEventArgs args);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct RuntimeArgumentHandle
+ {
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct RuntimeFieldHandle : System.Runtime.Serialization.ISerializable
+ {
+ public System.IntPtr Value { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Equals(System.RuntimeFieldHandle handle) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public static bool operator ==(System.RuntimeFieldHandle left, System.RuntimeFieldHandle right) { throw null; }
+ public static bool operator !=(System.RuntimeFieldHandle left, System.RuntimeFieldHandle right) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct RuntimeMethodHandle : System.Runtime.Serialization.ISerializable
+ {
+ public System.IntPtr Value { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Equals(System.RuntimeMethodHandle handle) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.IntPtr GetFunctionPointer() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public static bool operator ==(System.RuntimeMethodHandle left, System.RuntimeMethodHandle right) { throw null; }
+ public static bool operator !=(System.RuntimeMethodHandle left, System.RuntimeMethodHandle right) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct RuntimeTypeHandle : System.Runtime.Serialization.ISerializable
+ {
+ public System.IntPtr Value { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.RuntimeTypeHandle handle) { throw null; }
+ public override int GetHashCode() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.ModuleHandle GetModuleHandle() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public static bool operator ==(object left, System.RuntimeTypeHandle right) { throw null; }
+ public static bool operator ==(System.RuntimeTypeHandle left, object right) { throw null; }
+ public static bool operator !=(object left, System.RuntimeTypeHandle right) { throw null; }
+ public static bool operator !=(System.RuntimeTypeHandle left, object right) { throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct SByte : System.IComparable, System.IComparable<sbyte>, System.IConvertible, System.IEquatable<sbyte>, System.IFormattable
+ {
+ public const sbyte MaxValue = (sbyte)127;
+ public const sbyte MinValue = (sbyte)-128;
+ public int CompareTo(object obj) { throw null; }
+ public int CompareTo(System.SByte value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.SByte obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.SByte Parse(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.SByte Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.SByte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.SByte Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ System.SByte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ public string ToString(string format) { throw null; }
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.SByte result) { result = default(sbyte); throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, out System.SByte result) { result = default(sbyte); throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4124), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SerializableAttribute : System.Attribute
+ {
+ public SerializableAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Single : System.IComparable, System.IComparable<float>, System.IConvertible, System.IEquatable<float>, System.IFormattable
+ {
+ public const float Epsilon = 1.401298E-45f;
+ public const float MaxValue = 3.40282347E+38f;
+ public const float MinValue = -3.40282347E+38f;
+ public const float NaN = 0.0f / 0.0f;
+ public const float NegativeInfinity = -1.0f / 0.0f;
+ public const float PositiveInfinity = 1.0f / 0.0f;
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.Single value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Single obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsInfinity(System.Single f) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsNaN(System.Single f) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsNegativeInfinity(System.Single f) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsPositiveInfinity(System.Single f) { throw null; }
+ public static bool operator ==(System.Single left, System.Single right) { throw null; }
+ public static bool operator >(System.Single left, System.Single right) { throw null; }
+ public static bool operator >=(System.Single left, System.Single right) { throw null; }
+ public static bool operator !=(System.Single left, System.Single right) { throw null; }
+ public static bool operator <(System.Single left, System.Single right) { throw null; }
+ public static bool operator <=(System.Single left, System.Single right) { throw null; }
+ public static System.Single Parse(string s) { throw null; }
+ public static System.Single Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ public static System.Single Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ public static System.Single Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ System.Single System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Single result) { result = default(float); throw null; }
+ public static bool TryParse(string s, out System.Single result) { result = default(float); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class StackOverflowException : System.SystemException
+ {
+ public StackOverflowException() { }
+ public StackOverflowException(string message) { }
+ public StackOverflowException(string message, System.Exception innerException) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class STAThreadAttribute : System.Attribute
+ {
+ public STAThreadAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class String : System.Collections.Generic.IEnumerable<char>, System.Collections.IEnumerable, System.ICloneable, System.IComparable, System.IComparable<string>, System.IConvertible, System.IEquatable<string>
+ {
+ public static readonly string Empty;
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe String(char* value) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe String(char* value, int startIndex, int length) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public String(char c, int count) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public String(char[] value) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public String(char[] value, int startIndex, int length) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe String(sbyte* value) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe String(sbyte* value, int startIndex, int length) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encoding enc) { }
+ [System.Runtime.CompilerServices.IndexerName("Chars")]
+ public char this[int index] { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public int Length { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public object Clone() { throw null; }
+ public static int Compare(System.String strA, int indexA, System.String strB, int indexB, int length) { throw null; }
+ public static int Compare(System.String strA, int indexA, System.String strB, int indexB, int length, bool ignoreCase) { throw null; }
+ public static int Compare(System.String strA, int indexA, System.String strB, int indexB, int length, bool ignoreCase, System.Globalization.CultureInfo culture) { throw null; }
+ public static int Compare(System.String strA, int indexA, System.String strB, int indexB, int length, System.Globalization.CultureInfo culture, System.Globalization.CompareOptions options) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int Compare(System.String strA, int indexA, System.String strB, int indexB, int length, System.StringComparison comparisonType) { throw null; }
+ public static int Compare(System.String strA, System.String strB) { throw null; }
+ public static int Compare(System.String strA, System.String strB, bool ignoreCase) { throw null; }
+ public static int Compare(System.String strA, System.String strB, bool ignoreCase, System.Globalization.CultureInfo culture) { throw null; }
+ public static int Compare(System.String strA, System.String strB, System.Globalization.CultureInfo culture, System.Globalization.CompareOptions options) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int Compare(System.String strA, System.String strB, System.StringComparison comparisonType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static int CompareOrdinal(System.String strA, int indexA, System.String strB, int indexB, int length) { throw null; }
+ public static int CompareOrdinal(System.String strA, System.String strB) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.String strB) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.String Concat(System.Collections.Generic.IEnumerable<string> values) { throw null; }
+ public static System.String Concat(object arg0) { throw null; }
+ public static System.String Concat(object arg0, object arg1) { throw null; }
+ public static System.String Concat(object arg0, object arg1, object arg2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Concat(params object[] args) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Concat(System.String str0, System.String str1) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Concat(System.String str0, System.String str1, System.String str2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Concat(System.String str0, System.String str1, System.String str2, System.String str3) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Concat(params string[] values) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.String Concat<T>(System.Collections.Generic.IEnumerable<T> values) { throw null; }
+ public bool Contains(System.String value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Copy(System.String str) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { }
+ public bool EndsWith(System.String value) { throw null; }
+ public bool EndsWith(System.String value, bool ignoreCase, System.Globalization.CultureInfo culture) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool EndsWith(System.String value, System.StringComparison comparisonType) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.String value) { throw null; }
+ public static bool Equals(System.String a, System.String b) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool Equals(System.String a, System.String b, System.StringComparison comparisonType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Equals(System.String value, System.StringComparison comparisonType) { throw null; }
+ public static System.String Format(System.IFormatProvider provider, System.String format, object arg0) { throw null; }
+ public static System.String Format(System.IFormatProvider provider, System.String format, object arg0, object arg1) { throw null; }
+ public static System.String Format(System.IFormatProvider provider, System.String format, object arg0, object arg1, object arg2) { throw null; }
+ public static System.String Format(System.IFormatProvider provider, System.String format, params object[] args) { throw null; }
+ public static System.String Format(System.String format, object arg0) { throw null; }
+ public static System.String Format(System.String format, object arg0, object arg1) { throw null; }
+ public static System.String Format(System.String format, object arg0, object arg1, object arg2) { throw null; }
+ public static System.String Format(System.String format, params object[] args) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ public int IndexOf(char value) { throw null; }
+ public int IndexOf(char value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int IndexOf(char value, int startIndex, int count) { throw null; }
+ public int IndexOf(System.String value) { throw null; }
+ public int IndexOf(System.String value, int startIndex) { throw null; }
+ public int IndexOf(System.String value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int IndexOf(System.String value, int startIndex, int count, System.StringComparison comparisonType) { throw null; }
+ public int IndexOf(System.String value, int startIndex, System.StringComparison comparisonType) { throw null; }
+ public int IndexOf(System.String value, System.StringComparison comparisonType) { throw null; }
+ public int IndexOfAny(char[] anyOf) { throw null; }
+ public int IndexOfAny(char[] anyOf, int startIndex) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int IndexOfAny(char[] anyOf, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String Insert(int startIndex, System.String value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Intern(System.String str) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String IsInterned(System.String str) { throw null; }
+ public bool IsNormalized() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool IsNormalized(System.Text.NormalizationForm normalizationForm) { throw null; }
+ public static bool IsNullOrEmpty(System.String value) { throw null; }
+ public static bool IsNullOrWhiteSpace(System.String value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.String Join(System.String separator, System.Collections.Generic.IEnumerable<string> values) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.String Join(System.String separator, params object[] values) { throw null; }
+ public static System.String Join(System.String separator, params string[] value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.String Join(System.String separator, string[] value, int startIndex, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.String Join<T>(System.String separator, System.Collections.Generic.IEnumerable<T> values) { throw null; }
+ public int LastIndexOf(char value) { throw null; }
+ public int LastIndexOf(char value, int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int LastIndexOf(char value, int startIndex, int count) { throw null; }
+ public int LastIndexOf(System.String value) { throw null; }
+ public int LastIndexOf(System.String value, int startIndex) { throw null; }
+ public int LastIndexOf(System.String value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int LastIndexOf(System.String value, int startIndex, int count, System.StringComparison comparisonType) { throw null; }
+ public int LastIndexOf(System.String value, int startIndex, System.StringComparison comparisonType) { throw null; }
+ public int LastIndexOf(System.String value, System.StringComparison comparisonType) { throw null; }
+ public int LastIndexOfAny(char[] anyOf) { throw null; }
+ public int LastIndexOfAny(char[] anyOf, int startIndex) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int LastIndexOfAny(char[] anyOf, int startIndex, int count) { throw null; }
+ public System.String Normalize() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String Normalize(System.Text.NormalizationForm normalizationForm) { throw null; }
+ public static bool operator ==(System.String a, System.String b) { throw null; }
+ public static bool operator !=(System.String a, System.String b) { throw null; }
+ public System.String PadLeft(int totalWidth) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String PadLeft(int totalWidth, char paddingChar) { throw null; }
+ public System.String PadRight(int totalWidth) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String PadRight(int totalWidth, char paddingChar) { throw null; }
+ public System.String Remove(int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String Remove(int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String Replace(char oldChar, char newChar) { throw null; }
+ public System.String Replace(System.String oldValue, System.String newValue) { throw null; }
+ public string[] Split(params char[] separator) { throw null; }
+ public string[] Split(char[] separator, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] Split(char[] separator, int count, System.StringSplitOptions options) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] Split(char[] separator, System.StringSplitOptions options) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] Split(string[] separator, int count, System.StringSplitOptions options) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] Split(string[] separator, System.StringSplitOptions options) { throw null; }
+ public bool StartsWith(System.String value) { throw null; }
+ public bool StartsWith(System.String value, bool ignoreCase, System.Globalization.CultureInfo culture) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool StartsWith(System.String value, System.StringComparison comparisonType) { throw null; }
+ public System.String Substring(int startIndex) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.String Substring(int startIndex, int length) { throw null; }
+ System.Collections.Generic.IEnumerator<char> System.Collections.Generic.IEnumerable<System.Char>.GetEnumerator() { throw null; }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public char[] ToCharArray() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public char[] ToCharArray(int startIndex, int length) { throw null; }
+ public System.String ToLower() { throw null; }
+ public System.String ToLower(System.Globalization.CultureInfo culture) { throw null; }
+ public System.String ToLowerInvariant() { throw null; }
+ public override System.String ToString() { throw null; }
+ public System.String ToString(System.IFormatProvider provider) { throw null; }
+ public System.String ToUpper() { throw null; }
+ public System.String ToUpper(System.Globalization.CultureInfo culture) { throw null; }
+ public System.String ToUpperInvariant() { throw null; }
+ public System.String Trim() { throw null; }
+ public System.String Trim(params char[] trimChars) { throw null; }
+ public System.String TrimEnd(params char[] trimChars) { throw null; }
+ public System.String TrimStart(params char[] trimChars) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class StringComparer : System.Collections.Generic.IComparer<string>, System.Collections.Generic.IEqualityComparer<string>, System.Collections.IComparer, System.Collections.IEqualityComparer
+ {
+ protected StringComparer() { }
+ public static System.StringComparer CurrentCulture { get { throw null; } }
+ public static System.StringComparer CurrentCultureIgnoreCase { get { throw null; } }
+ public static System.StringComparer InvariantCulture { get { throw null; } }
+ public static System.StringComparer InvariantCultureIgnoreCase { get { throw null; } }
+ public static System.StringComparer Ordinal { get { throw null; } }
+ public static System.StringComparer OrdinalIgnoreCase { get { throw null; } }
+ public int Compare(object x, object y) { throw null; }
+ public abstract int Compare(string x, string y);
+ public static System.StringComparer Create(System.Globalization.CultureInfo culture, bool ignoreCase) { throw null; }
+ public new bool Equals(object x, object y) { throw null; }
+ public abstract bool Equals(string x, string y);
+ public int GetHashCode(object obj) { throw null; }
+ public abstract int GetHashCode(string obj);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum StringComparison
+ {
+ CurrentCulture = 0,
+ CurrentCultureIgnoreCase = 1,
+ InvariantCulture = 2,
+ InvariantCultureIgnoreCase = 3,
+ Ordinal = 4,
+ OrdinalIgnoreCase = 5,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public enum StringSplitOptions
+ {
+ None = 0,
+ RemoveEmptyEntries = 1,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SystemException : System.Exception
+ {
+ public SystemException() { }
+ public SystemException(string message) { }
+ public SystemException(string message, System.Exception innerException) { }
+ protected SystemException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ThreadStaticAttribute : System.Attribute
+ {
+ public ThreadStaticAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TimeoutException : System.SystemException
+ {
+ public TimeoutException() { }
+ public TimeoutException(string message) { }
+ public TimeoutException(string message, System.Exception innerException) { }
+ protected TimeoutException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TimeSpan : System.IComparable, System.IComparable<System.TimeSpan>, System.IEquatable<System.TimeSpan>, System.IFormattable
+ {
+ public static readonly System.TimeSpan MaxValue;
+ public static readonly System.TimeSpan MinValue;
+ public const long TicksPerDay = (long)864000000000;
+ public const long TicksPerHour = (long)36000000000;
+ public const long TicksPerMillisecond = (long)10000;
+ public const long TicksPerMinute = (long)600000000;
+ public const long TicksPerSecond = (long)10000000;
+ public static readonly System.TimeSpan Zero;
+ public TimeSpan(int hours, int minutes, int seconds) { throw null;}
+ public TimeSpan(int days, int hours, int minutes, int seconds) { throw null;}
+ public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds) { throw null;}
+ public TimeSpan(long ticks) { throw null;}
+ public int Days { get { throw null; } }
+ public int Hours { get { throw null; } }
+ public int Milliseconds { get { throw null; } }
+ public int Minutes { get { throw null; } }
+ public int Seconds { get { throw null; } }
+ public long Ticks { get { throw null; } }
+ public double TotalDays { get { throw null; } }
+ public double TotalHours { get { throw null; } }
+ public double TotalMilliseconds { get { throw null; } }
+ public double TotalMinutes { get { throw null; } }
+ public double TotalSeconds { get { throw null; } }
+ public System.TimeSpan Add(System.TimeSpan ts) { throw null; }
+ public static int Compare(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.TimeSpan value) { throw null; }
+ public System.TimeSpan Duration() { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public bool Equals(System.TimeSpan obj) { throw null; }
+ public static bool Equals(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static System.TimeSpan FromDays(double value) { throw null; }
+ public static System.TimeSpan FromHours(double value) { throw null; }
+ public static System.TimeSpan FromMilliseconds(double value) { throw null; }
+ public static System.TimeSpan FromMinutes(double value) { throw null; }
+ public static System.TimeSpan FromSeconds(double value) { throw null; }
+ public static System.TimeSpan FromTicks(long value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TimeSpan Negate() { throw null; }
+ public static System.TimeSpan operator +(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator ==(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator >(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator >=(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator !=(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator <(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static bool operator <=(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static System.TimeSpan operator -(System.TimeSpan t1, System.TimeSpan t2) { throw null; }
+ public static System.TimeSpan operator -(System.TimeSpan t) { throw null; }
+ public static System.TimeSpan operator +(System.TimeSpan t) { throw null; }
+ public static System.TimeSpan Parse(string s) { throw null; }
+ public static System.TimeSpan Parse(string input, System.IFormatProvider formatProvider) { throw null; }
+ public static System.TimeSpan ParseExact(string input, string format, System.IFormatProvider formatProvider) { throw null; }
+ public static System.TimeSpan ParseExact(string input, string format, System.IFormatProvider formatProvider, System.Globalization.TimeSpanStyles styles) { throw null; }
+ public static System.TimeSpan ParseExact(string input, string[] formats, System.IFormatProvider formatProvider) { throw null; }
+ public static System.TimeSpan ParseExact(string input, string[] formats, System.IFormatProvider formatProvider, System.Globalization.TimeSpanStyles styles) { throw null; }
+ public System.TimeSpan Subtract(System.TimeSpan ts) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(string format) { throw null; }
+ public string ToString(string format, System.IFormatProvider formatProvider) { throw null; }
+ public static bool TryParse(string input, System.IFormatProvider formatProvider, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ public static bool TryParse(string s, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ public static bool TryParseExact(string input, string format, System.IFormatProvider formatProvider, System.Globalization.TimeSpanStyles styles, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ public static bool TryParseExact(string input, string format, System.IFormatProvider formatProvider, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ public static bool TryParseExact(string input, string[] formats, System.IFormatProvider formatProvider, System.Globalization.TimeSpanStyles styles, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ public static bool TryParseExact(string input, string[] formats, System.IFormatProvider formatProvider, out System.TimeSpan result) { result = default(System.TimeSpan); throw null; }
+ }
+ [System.ObsoleteAttribute("System.TimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo instead.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class TimeZone
+ {
+ protected TimeZone() { }
+ public abstract string DaylightName { get; }
+ public abstract string StandardName { get; }
+ public abstract System.Globalization.DaylightTime GetDaylightChanges(int year);
+ public abstract System.TimeSpan GetUtcOffset(System.DateTime time);
+ public virtual bool IsDaylightSavingTime(System.DateTime time) { throw null; }
+ public static bool IsDaylightSavingTime(System.DateTime time, System.Globalization.DaylightTime daylightTimes) { throw null; }
+ public virtual System.DateTime ToUniversalTime(System.DateTime time) { throw null; }
+ }
+ public sealed partial class TimeZoneInfo : System.IEquatable<System.TimeZoneInfo>, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable
+ {
+ internal TimeZoneInfo() { }
+ public System.TimeSpan BaseUtcOffset { get { throw null; } }
+ public string DaylightName { get { throw null; } }
+ public string DisplayName { get { throw null; } }
+ public string Id { get { throw null; } }
+ public static System.TimeZoneInfo Local { get { throw null; } }
+ public string StandardName { get { throw null; } }
+ public bool SupportsDaylightSavingTime { get { throw null; } }
+ public static System.TimeZoneInfo Utc { get { throw null; } }
+ public static void ClearCachedData() { }
+ public static System.DateTime ConvertTime(System.DateTime dateTime, System.TimeZoneInfo destinationTimeZone) { throw null; }
+ public static System.DateTime ConvertTime(System.DateTime dateTime, System.TimeZoneInfo sourceTimeZone, System.TimeZoneInfo destinationTimeZone) { throw null; }
+ public static System.DateTimeOffset ConvertTime(System.DateTimeOffset dateTimeOffset, System.TimeZoneInfo destinationTimeZone) { throw null; }
+ public static System.DateTime ConvertTimeFromUtc(System.DateTime dateTime, System.TimeZoneInfo destinationTimeZone) { throw null; }
+ public static System.DateTime ConvertTimeToUtc(System.DateTime dateTime) { throw null; }
+ public static System.DateTime ConvertTimeToUtc(System.DateTime dateTime, System.TimeZoneInfo sourceTimeZone) { throw null; }
+ public static System.TimeZoneInfo CreateCustomTimeZone(string id, System.TimeSpan baseUtcOffset, string displayName, string standardDisplayName) { throw null; }
+ public static System.TimeZoneInfo CreateCustomTimeZone(string id, System.TimeSpan baseUtcOffset, string displayName, string standardDisplayName, string daylightDisplayName, System.TimeZoneInfo.AdjustmentRule[] adjustmentRules) { throw null; }
+ public static System.TimeZoneInfo CreateCustomTimeZone(string id, System.TimeSpan baseUtcOffset, string displayName, string standardDisplayName, string daylightDisplayName, System.TimeZoneInfo.AdjustmentRule[] adjustmentRules, bool disableDaylightSavingTime) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.TimeZoneInfo other) { throw null; }
+ public static System.TimeZoneInfo FindSystemTimeZoneById(string id) { throw null; }
+ public static System.TimeZoneInfo FromSerializedString(string source) { throw null; }
+ public System.TimeZoneInfo.AdjustmentRule[] GetAdjustmentRules() { throw null; }
+ public System.TimeSpan[] GetAmbiguousTimeOffsets(System.DateTime dateTime) { throw null; }
+ public System.TimeSpan[] GetAmbiguousTimeOffsets(System.DateTimeOffset dateTimeOffset) { throw null; }
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Collections.ObjectModel.ReadOnlyCollection<System.TimeZoneInfo> GetSystemTimeZones() { throw null; }
+ public System.TimeSpan GetUtcOffset(System.DateTime dateTime) { throw null; }
+ public System.TimeSpan GetUtcOffset(System.DateTimeOffset dateTimeOffset) { throw null; }
+ public bool HasSameRules(System.TimeZoneInfo other) { throw null; }
+ public bool IsAmbiguousTime(System.DateTime dateTime) { throw null; }
+ public bool IsAmbiguousTime(System.DateTimeOffset dateTimeOffset) { throw null; }
+ public bool IsDaylightSavingTime(System.DateTime dateTime) { throw null; }
+ public bool IsDaylightSavingTime(System.DateTimeOffset dateTimeOffset) { throw null; }
+ public bool IsInvalidTime(System.DateTime dateTime) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public string ToSerializedString() { throw null; }
+ public override string ToString() { throw null; }
+ public sealed partial class AdjustmentRule : System.IEquatable<System.TimeZoneInfo.AdjustmentRule>, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable
+ {
+ internal AdjustmentRule() { }
+ public System.DateTime DateEnd { get { throw null; } }
+ public System.DateTime DateStart { get { throw null; } }
+ public System.TimeSpan DaylightDelta { get { throw null; } }
+ public System.TimeZoneInfo.TransitionTime DaylightTransitionEnd { get { throw null; } }
+ public System.TimeZoneInfo.TransitionTime DaylightTransitionStart { get { throw null; } }
+ public static System.TimeZoneInfo.AdjustmentRule CreateAdjustmentRule(System.DateTime dateStart, System.DateTime dateEnd, System.TimeSpan daylightDelta, System.TimeZoneInfo.TransitionTime daylightTransitionStart, System.TimeZoneInfo.TransitionTime daylightTransitionEnd) { throw null; }
+ public bool Equals(System.TimeZoneInfo.AdjustmentRule other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TransitionTime : System.IEquatable<System.TimeZoneInfo.TransitionTime>, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable
+ {
+ public int Day { get { throw null; } }
+ public System.DayOfWeek DayOfWeek { get { throw null; } }
+ public bool IsFixedDateRule { get { throw null; } }
+ public int Month { get { throw null; } }
+ public System.DateTime TimeOfDay { get { throw null; } }
+ public int Week { get { throw null; } }
+ public static System.TimeZoneInfo.TransitionTime CreateFixedDateRule(System.DateTime timeOfDay, int month, int day) { throw null; }
+ public static System.TimeZoneInfo.TransitionTime CreateFloatingDateRule(System.DateTime timeOfDay, int month, int week, System.DayOfWeek dayOfWeek) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.TimeZoneInfo.TransitionTime other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.TimeZoneInfo.TransitionTime t1, System.TimeZoneInfo.TransitionTime t2) { throw null; }
+ public static bool operator !=(System.TimeZoneInfo.TransitionTime t1, System.TimeZoneInfo.TransitionTime t2) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+ public partial class TimeZoneNotFoundException : System.Exception
+ {
+ public TimeZoneNotFoundException() { }
+ protected TimeZoneNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public TimeZoneNotFoundException(string message) { }
+ public TimeZoneNotFoundException(string message, System.Exception innerException) { }
+ }
+ public static partial class Tuple
+ {
+ public static System.Tuple<T1> Create<T1>(T1 item1) { throw null; }
+ public static System.Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) { throw null; }
+ public static System.Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3) { throw null; }
+ public static System.Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4) { throw null; }
+ public static System.Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) { throw null; }
+ public static System.Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) { throw null; }
+ public static System.Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) { throw null; }
+ public static System.Tuple<T1, T2, T3, T4, T5, T6, T7, System.Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) { throw null; }
+ }
+ public partial class Tuple<T1> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1) { }
+ public T1 Item1 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3, T4> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public T4 Item4 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3, T4, T5> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public T4 Item4 { get { throw null; } }
+ public T5 Item5 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3, T4, T5, T6> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public T4 Item4 { get { throw null; } }
+ public T5 Item5 { get { throw null; } }
+ public T6 Item6 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3, T4, T5, T6, T7> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public T4 Item4 { get { throw null; } }
+ public T5 Item5 { get { throw null; } }
+ public T6 Item6 { get { throw null; } }
+ public T7 Item7 { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable
+ {
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) { }
+ public T1 Item1 { get { throw null; } }
+ public T2 Item2 { get { throw null; } }
+ public T3 Item3 { get { throw null; } }
+ public T4 Item4 { get { throw null; } }
+ public T5 Item5 { get { throw null; } }
+ public T6 Item6 { get { throw null; } }
+ public T7 Item7 { get { throw null; } }
+ public TRest Rest { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ int System.Collections.IStructuralComparable.CompareTo(object other, System.Collections.IComparer comparer) { throw null; }
+ bool System.Collections.IStructuralEquatable.Equals(object other, System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.Collections.IStructuralEquatable.GetHashCode(System.Collections.IEqualityComparer comparer) { throw null; }
+ int System.IComparable.CompareTo(object obj) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Type : System.Reflection.MemberInfo, System.Reflection.IReflect
+ {
+ public static readonly char Delimiter;
+ public static readonly System.Type[] EmptyTypes;
+ public static readonly System.Reflection.MemberFilter FilterAttribute;
+ public static readonly System.Reflection.MemberFilter FilterName;
+ public static readonly System.Reflection.MemberFilter FilterNameIgnoreCase;
+ public static readonly object Missing;
+ protected Type() { }
+ [System.Security.SecuritySafeCriticalAttribute][System.Diagnostics.Contracts.PureAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ public static bool operator ==(System.Type left, System.Type right) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute][System.Diagnostics.Contracts.PureAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ public static bool operator !=(System.Type left, System.Type right) { throw null; }
+ public abstract System.Reflection.Assembly Assembly { get; }
+ public abstract string AssemblyQualifiedName { get; }
+ public System.Reflection.TypeAttributes Attributes { get { throw null; } }
+ public abstract System.Type BaseType { get; }
+ public virtual bool ContainsGenericParameters { get { throw null; } }
+ public virtual System.Reflection.MethodBase DeclaringMethod { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public static System.Reflection.Binder DefaultBinder { get { throw null; } }
+ public abstract string FullName { get; }
+ public virtual System.Reflection.GenericParameterAttributes GenericParameterAttributes { get { throw null; } }
+ public virtual int GenericParameterPosition { get { throw null; } }
+ public virtual System.Type[] GenericTypeArguments { get { throw null; } }
+ public abstract System.Guid GUID { get; }
+ public bool HasElementType { get { throw null; } }
+ public bool IsAbstract { get { throw null; } }
+ public bool IsAnsiClass { get { throw null; } }
+ public bool IsArray { get { throw null; } }
+ public bool IsAutoClass { get { throw null; } }
+ public bool IsAutoLayout { get { throw null; } }
+ public bool IsByRef { get { throw null; } }
+ public bool IsClass { get { throw null; } }
+ public bool IsCOMObject { get { throw null; } }
+ public virtual bool IsConstructedGenericType { get { throw null; } }
+ public bool IsContextful { [System.Diagnostics.Contracts.PureAttribute]get { throw null;} }
+ public bool IsEnum { get { throw null; } }
+ public bool IsExplicitLayout { get { throw null; } }
+ public virtual bool IsGenericParameter { get { throw null; } }
+ public virtual bool IsGenericType { get { throw null; } }
+ public virtual bool IsGenericTypeDefinition { get { throw null; } }
+ public bool IsImport { get { throw null; } }
+ public bool IsInterface { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public bool IsLayoutSequential { get { throw null; } }
+ public bool IsMarshalByRef { get { throw null; } }
+ public bool IsNested { get { throw null; } }
+ public bool IsNestedAssembly { get { throw null; } }
+ public bool IsNestedFamANDAssem { get { throw null; } }
+ public bool IsNestedFamily { get { throw null; } }
+ public bool IsNestedFamORAssem { get { throw null; } }
+ public bool IsNestedPrivate { get { throw null; } }
+ public bool IsNestedPublic { get { throw null; } }
+ public bool IsNotPublic { get { throw null; } }
+ public bool IsPointer { get { throw null; } }
+ public bool IsPrimitive { get { throw null; } }
+ public bool IsPublic { get { throw null; } }
+ public bool IsSealed { get { throw null; } }
+ public virtual bool IsSerializable { get { throw null; } }
+ public bool IsSpecialName { get { throw null; } }
+ public bool IsUnicodeClass { get { throw null; } }
+ public bool IsValueType { get { throw null; } }
+ public bool IsVisible { get { throw null; } }
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public abstract new System.Reflection.Module Module { get; }
+ public abstract string Namespace { get; }
+ public override System.Type ReflectedType { get { throw null; } }
+ public virtual System.Runtime.InteropServices.StructLayoutAttribute StructLayoutAttribute { get { throw null; } }
+ public virtual System.RuntimeTypeHandle TypeHandle { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.ConstructorInfo TypeInitializer { get { throw null; } }
+ public abstract System.Type UnderlyingSystemType { get; }
+ public override bool Equals(object o) { throw null; }
+ public bool Equals(System.Type o) { throw null; }
+ public virtual System.Type[] FindInterfaces(System.Reflection.TypeFilter filter, object filterCriteria) { throw null; }
+ public virtual System.Reflection.MemberInfo[] FindMembers(System.Reflection.MemberTypes memberType, System.Reflection.BindingFlags bindingAttr, System.Reflection.MemberFilter filter, object filterCriteria) { throw null; }
+ public virtual int GetArrayRank() { throw null; }
+ protected abstract System.Reflection.TypeAttributes GetAttributeFlagsImpl();
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.ConstructorInfo GetConstructor(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.ConstructorInfo GetConstructor(System.Type[] types) { throw null; }
+ protected abstract System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.ConstructorInfo[] GetConstructors() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.ConstructorInfo GetConstructor(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public virtual System.Reflection.MemberInfo[] GetDefaultMembers() { throw null; }
+ public abstract System.Type GetElementType();
+ public virtual string GetEnumName(object value) { throw null; }
+ public virtual string[] GetEnumNames() { throw null; }
+ public virtual System.Type GetEnumUnderlyingType() { throw null; }
+ public virtual System.Array GetEnumValues() { throw null; }
+ public System.Reflection.EventInfo GetEvent(string name) { throw null; }
+ public abstract System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr);
+ public virtual System.Reflection.EventInfo[] GetEvents() { throw null; }
+ public abstract System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr);
+ public System.Reflection.FieldInfo GetField(string name) { throw null; }
+ public abstract System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr);
+ public System.Reflection.FieldInfo[] GetFields() { throw null; }
+ public abstract System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr);
+ public virtual System.Type[] GetGenericArguments() { throw null; }
+ public virtual System.Type[] GetGenericParameterConstraints() { throw null; }
+ public virtual System.Type GetGenericTypeDefinition() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.Type GetInterface(string name) { throw null; }
+ public abstract System.Type GetInterface(string name, bool ignoreCase);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) { throw null; }
+ public abstract System.Type[] GetInterfaces();
+ public System.Reflection.MemberInfo[] GetMember(string name) { throw null; }
+ public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public virtual System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public System.Reflection.MemberInfo[] GetMembers() { throw null; }
+ public abstract System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr);
+ public System.Reflection.MethodInfo GetMethod(string name) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Type[] types) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ protected abstract System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ public System.Reflection.MethodInfo[] GetMethods() { throw null; }
+ public abstract System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr);
+ public System.Type GetNestedType(string name) { throw null; }
+ public abstract System.Type GetNestedType(string name, System.Reflection.BindingFlags bindingAttr);
+ public System.Type[] GetNestedTypes() { throw null; }
+ public abstract System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr);
+ public System.Reflection.PropertyInfo[] GetProperties() { throw null; }
+ public abstract System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr);
+ public System.Reflection.PropertyInfo GetProperty(string name) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Type returnType) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Type returnType, System.Type[] types) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.PropertyInfo GetProperty(string name, System.Type[] types) { throw null; }
+ protected abstract System.Reflection.PropertyInfo GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ public new System.Type GetType() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Type GetType(string typeName) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Type GetType(string typeName, bool throwOnError) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Type GetType(string typeName, bool throwOnError, bool ignoreCase) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static System.Type GetType(string typeName, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly> assemblyResolver, System.Func<System.Reflection.Assembly, string, bool, System.Type> typeResolver) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static System.Type GetType(string typeName, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly> assemblyResolver, System.Func<System.Reflection.Assembly, string, bool, System.Type> typeResolver, bool throwOnError) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static System.Type GetType(string typeName, System.Func<System.Reflection.AssemblyName, System.Reflection.Assembly> assemblyResolver, System.Func<System.Reflection.Assembly, string, bool, System.Type> typeResolver, bool throwOnError, bool ignoreCase) { throw null; }
+ public static System.Type[] GetTypeArray(System.Object[] args) { throw null; }
+ public static System.TypeCode GetTypeCode(System.Type type) { throw null; }
+ protected virtual System.TypeCode GetTypeCodeImpl() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]public static System.Type GetTypeFromCLSID(System.Guid clsid) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]public static System.Type GetTypeFromCLSID(System.Guid clsid, bool throwOnError) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]public static System.Type GetTypeFromCLSID(System.Guid clsid, string server) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]public static System.Type GetTypeFromCLSID(System.Guid clsid, string server, bool throwOnError) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Type GetTypeFromHandle(System.RuntimeTypeHandle handle) { throw null; }
+ [System.Security.SecurityCriticalAttribute]public static System.Type GetTypeFromProgID(string progID) { throw null; }
+ [System.Security.SecurityCriticalAttribute]public static System.Type GetTypeFromProgID(string progID, bool throwOnError) { throw null; }
+ [System.Security.SecurityCriticalAttribute]public static System.Type GetTypeFromProgID(string progID, string server) { throw null; }
+ [System.Security.SecurityCriticalAttribute]public static System.Type GetTypeFromProgID(string progID, string server, bool throwOnError) { throw null; }
+ public static System.RuntimeTypeHandle GetTypeHandle(object o) { throw null; }
+ protected abstract bool HasElementTypeImpl();
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args) { throw null; }
+ [System.Diagnostics.DebuggerStepThroughAttribute][System.Diagnostics.DebuggerHiddenAttribute]
+ public System.Object InvokeMember(System.String name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object target, System.Object[] args, System.Globalization.CultureInfo culture) { throw null; }
+ public abstract object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters);
+ protected abstract bool IsArrayImpl();
+ public virtual bool IsAssignableFrom(System.Type c) { throw null; }
+ protected abstract bool IsByRefImpl();
+ protected abstract bool IsCOMObjectImpl();
+ protected virtual bool IsContextfulImpl() { throw null; }
+ public virtual bool IsEnumDefined(object value) { throw null; }
+ public virtual bool IsEquivalentTo(System.Type other) { throw null; }
+ public virtual bool IsInstanceOfType(object o) { throw null; }
+ protected virtual bool IsMarshalByRefImpl() { throw null; }
+ protected abstract bool IsPointerImpl();
+ protected abstract bool IsPrimitiveImpl();
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual bool IsSubclassOf(System.Type c) { throw null; }
+ protected virtual bool IsValueTypeImpl() { throw null; }
+ public virtual System.Type MakeArrayType() { throw null; }
+ public virtual System.Type MakeArrayType(int rank) { throw null; }
+ public virtual System.Type MakeByRefType() { throw null; }
+ public virtual System.Type MakeGenericType(params System.Type[] typeArguments) { throw null; }
+ public virtual System.Type MakePointerType() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static System.Type ReflectionOnlyGetType(System.String typeName, bool throwIfNotFound, bool ignoreCase) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public partial class TypeAccessException : System.TypeLoadException
+ {
+ public TypeAccessException() { }
+ public TypeAccessException(string message) { }
+ public TypeAccessException(string message, System.Exception inner) { }
+ protected TypeAccessException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum TypeCode
+ {
+ Boolean = 3,
+ Byte = 6,
+ Char = 4,
+ DateTime = 16,
+ DBNull = 2,
+ Decimal = 15,
+ Double = 14,
+ Empty = 0,
+ Int16 = 7,
+ Int32 = 9,
+ Int64 = 11,
+ Object = 1,
+ SByte = 5,
+ Single = 13,
+ String = 18,
+ UInt16 = 8,
+ UInt32 = 10,
+ UInt64 = 12,
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TypedReference
+ {
+ public override bool Equals(object o) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class TypeInitializationException : System.SystemException
+ {
+ public TypeInitializationException(string fullTypeName, System.Exception innerException) { }
+ public string TypeName { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TypeLoadException : System.SystemException, System.Runtime.Serialization.ISerializable
+ {
+ public TypeLoadException() { }
+ public TypeLoadException(string message) { }
+ public TypeLoadException(string message, System.Exception inner) { }
+ protected TypeLoadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public override string Message { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public string TypeName { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TypeUnloadedException : System.SystemException
+ {
+ public TypeUnloadedException() { }
+ protected TypeUnloadedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public TypeUnloadedException(string message) { }
+ public TypeUnloadedException(string message, System.Exception innerException) { }
+ }
+ internal sealed class TypeNameParser : System.IDisposable
+ {
+ [System.Security.SecuritySafeCriticalAttribute]public void Dispose() { throw null; }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ internal class SafeTypeNameParserHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
+ {
+ public SafeTypeNameParserHandle(): base(default(bool)) { }
+ [System.Security.SecurityCriticalAttribute]
+ protected override bool ReleaseHandle() { throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct UInt16 : System.IComparable, System.IComparable<ushort>, System.IConvertible, System.IEquatable<ushort>, System.IFormattable
+ {
+ public const ushort MaxValue = (ushort)65535;
+ public const ushort MinValue = (ushort)0;
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.UInt16 value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.UInt16 obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt16 Parse(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt16 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt16 result) { result = default(ushort); throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, out System.UInt16 result) { result = default(ushort); throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct UInt32 : System.IComparable, System.IComparable<uint>, System.IConvertible, System.IEquatable<uint>, System.IFormattable
+ {
+ public const uint MaxValue = (uint)4294967295;
+ public const uint MinValue = (uint)0;
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.UInt32 value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.UInt32 obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt32 Parse(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt32 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ ulong System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt32 result) { result = default(uint); throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, out System.UInt32 result) { result = default(uint); throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct UInt64 : System.IComparable, System.IComparable<ulong>, System.IConvertible, System.IEquatable<ulong>, System.IFormattable
+ {
+ public const ulong MaxValue = (ulong)18446744073709551615;
+ public const ulong MinValue = (ulong)0;
+ public int CompareTo(object value) { throw null; }
+ public int CompareTo(System.UInt64 value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.UInt64 obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.TypeCode GetTypeCode() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt64 Parse(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UInt64 Parse(string s, System.IFormatProvider provider) { throw null; }
+ bool System.IConvertible.ToBoolean(System.IFormatProvider provider) { throw null; }
+ byte System.IConvertible.ToByte(System.IFormatProvider provider) { throw null; }
+ char System.IConvertible.ToChar(System.IFormatProvider provider) { throw null; }
+ System.DateTime System.IConvertible.ToDateTime(System.IFormatProvider provider) { throw null; }
+ decimal System.IConvertible.ToDecimal(System.IFormatProvider provider) { throw null; }
+ double System.IConvertible.ToDouble(System.IFormatProvider provider) { throw null; }
+ short System.IConvertible.ToInt16(System.IFormatProvider provider) { throw null; }
+ int System.IConvertible.ToInt32(System.IFormatProvider provider) { throw null; }
+ long System.IConvertible.ToInt64(System.IFormatProvider provider) { throw null; }
+ sbyte System.IConvertible.ToSByte(System.IFormatProvider provider) { throw null; }
+ float System.IConvertible.ToSingle(System.IFormatProvider provider) { throw null; }
+ object System.IConvertible.ToType(System.Type type, System.IFormatProvider provider) { throw null; }
+ ushort System.IConvertible.ToUInt16(System.IFormatProvider provider) { throw null; }
+ uint System.IConvertible.ToUInt32(System.IFormatProvider provider) { throw null; }
+ System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(System.IFormatProvider provider) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(string format, System.IFormatProvider provider) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt64 result) { result = default(ulong); throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static bool TryParse(string s, out System.UInt64 result) { result = default(ulong); throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct UIntPtr : System.Runtime.Serialization.ISerializable
+ {
+ public static readonly System.UIntPtr Zero;
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UIntPtr(uint value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UIntPtr(ulong value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe UIntPtr(void* value) { throw null; }
+ public static int Size { get { throw null; } }
+ public static System.UIntPtr Add(System.UIntPtr pointer, int offset) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public static System.UIntPtr operator +(System.UIntPtr pointer, int offset) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator ==(System.UIntPtr value1, System.UIntPtr value2) { throw null; }
+ public static explicit operator System.UIntPtr(uint value) { throw null; }
+ public static explicit operator System.UIntPtr(ulong value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static explicit operator uint(System.UIntPtr value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static explicit operator ulong(System.UIntPtr value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static explicit operator void* (System.UIntPtr value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static explicit operator System.UIntPtr(void* value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool operator !=(System.UIntPtr value1, System.UIntPtr value2) { throw null; }
+ public static System.UIntPtr operator -(System.UIntPtr pointer, int offset) { throw null; }
+ public static System.UIntPtr Subtract(System.UIntPtr pointer, int offset) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public unsafe void* ToPointer() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public uint ToUInt32() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public ulong ToUInt64() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class UnauthorizedAccessException : System.SystemException
+ {
+ public UnauthorizedAccessException() { }
+ public UnauthorizedAccessException(string message) { }
+ public UnauthorizedAccessException(string message, System.Exception inner) { }
+ protected UnauthorizedAccessException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class UnhandledExceptionEventArgs : System.EventArgs
+ {
+ public UnhandledExceptionEventArgs(object exception, bool isTerminating) { }
+ public object ExceptionObject { get { throw null; } }
+ public bool IsTerminating { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public delegate void UnhandledExceptionEventHandler(object sender, System.UnhandledExceptionEventArgs e);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class ValueType
+ {
+ protected ValueType() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public override int GetHashCode() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Version : System.ICloneable, System.IComparable, System.IComparable<System.Version>, System.IEquatable<System.Version>
+ {
+ public Version(int major, int minor) { }
+ public Version(int major, int minor, int build) { }
+ public Version(int major, int minor, int build, int revision) { }
+ public Version(string version) { }
+ public Version() { }
+ public int Build { get { throw null; } }
+ public int Major { get { throw null; } }
+ public short MajorRevision { get { throw null; } }
+ public int Minor { get { throw null; } }
+ public short MinorRevision { get { throw null; } }
+ public int Revision { get { throw null; } }
+ public object Clone() { throw null; }
+ public int CompareTo(object version) { throw null; }
+ public int CompareTo(System.Version value) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Version obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Version v1, System.Version v2) { throw null; }
+ public static bool operator >(System.Version v1, System.Version v2) { throw null; }
+ public static bool operator >=(System.Version v1, System.Version v2) { throw null; }
+ public static bool operator !=(System.Version v1, System.Version v2) { throw null; }
+ public static bool operator <(System.Version v1, System.Version v2) { throw null; }
+ public static bool operator <=(System.Version v1, System.Version v2) { throw null; }
+ public static System.Version Parse(string input) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToString(int fieldCount) { throw null; }
+ public static bool TryParse(string input, out System.Version result) { result = default(System.Version); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+ public partial struct Void
+ {
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class WeakReference : System.Runtime.Serialization.ISerializable
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected WeakReference() { }
+ public WeakReference(object target) { }
+ public WeakReference(object target, bool trackResurrection) { }
+ protected WeakReference(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public virtual bool IsAlive { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public virtual object Target { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]set { } }
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public virtual bool TrackResurrection { get { throw null; } }
+ ~WeakReference() { }
+ }
+ public sealed partial class WeakReference<T> : System.Runtime.Serialization.ISerializable where T : class
+ {
+ public WeakReference(T target) { }
+ public WeakReference(T target, bool trackResurrection) { }
+ ~WeakReference() { }
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public void SetTarget(T target) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]public bool TryGetTarget(out T target) { target = default(T); throw null; }
+ }
+}
+namespace System.Collections
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class BitArray : System.Collections.ICollection, System.Collections.IEnumerable, System.ICloneable
+ {
+ public BitArray(bool[] values) { }
+ public BitArray(byte[] bytes) { }
+ public BitArray(System.Collections.BitArray bits) { }
+ public BitArray(int length) { }
+ public BitArray(int length, bool defaultValue) { }
+ public BitArray(int[] values) { }
+ public int Count { get { throw null; } }
+ public bool IsReadOnly { get { throw null; } }
+ public bool IsSynchronized { get { throw null; } }
+ public bool this[int index] { get { throw null; } set { } }
+ public int Length { get { throw null; } set { } }
+ public object SyncRoot { get { throw null; } }
+ public System.Collections.BitArray And(System.Collections.BitArray value) { throw null; }
+ public object Clone() { throw null; }
+ public void CopyTo(System.Array array, int index) { }
+ public bool Get(int index) { throw null; }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public System.Collections.BitArray Not() { throw null; }
+ public System.Collections.BitArray Or(System.Collections.BitArray value) { throw null; }
+ public void Set(int index, bool value) { }
+ public void SetAll(bool value) { }
+ public System.Collections.BitArray Xor(System.Collections.BitArray value) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class CollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
+ {
+ protected CollectionBase() { }
+ public int Count { get { throw null; } }
+ protected System.Collections.IList List { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IList.IsFixedSize { get { throw null; } }
+ bool System.Collections.IList.IsReadOnly { get { throw null; } }
+ object System.Collections.IList.this[int index] { get { throw null; } set { } }
+ public void Clear() { }
+ public System.Collections.IEnumerator GetEnumerator() { throw null; }
+ public void RemoveAt(int index) { }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ int System.Collections.IList.Add(object value) { throw null; }
+ bool System.Collections.IList.Contains(object value) { throw null; }
+ int System.Collections.IList.IndexOf(object value) { throw null; }
+ void System.Collections.IList.Insert(int index, object value) { }
+ void System.Collections.IList.Remove(object value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct DictionaryEntry
+ {
+ public DictionaryEntry(object key, object value) { throw null;}
+ public object Key { get { throw null; } set { } }
+ public object Value { get { throw null; } set { } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ICollection : System.Collections.IEnumerable
+ {
+ int Count { get; }
+ bool IsSynchronized { get; }
+ object SyncRoot { get; }
+ void CopyTo(System.Array array, int index);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IComparer
+ {
+ int Compare(object x, object y);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IDictionary : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ bool IsFixedSize { get; }
+ bool IsReadOnly { get; }
+ object this[object key] { get; set; }
+ System.Collections.ICollection Keys { get; }
+ System.Collections.ICollection Values { get; }
+ void Add(object key, object value);
+ void Clear();
+ bool Contains(object key);
+ new System.Collections.IDictionaryEnumerator GetEnumerator();
+ void Remove(object key);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IDictionaryEnumerator : System.Collections.IEnumerator
+ {
+ System.Collections.DictionaryEntry Entry { get; }
+ object Key { get; }
+ object Value { get; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.GuidAttribute("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
+ public partial interface IEnumerable
+ {
+ [System.Runtime.InteropServices.DispIdAttribute(-4)]
+ System.Collections.IEnumerator GetEnumerator();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.GuidAttribute("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
+ public partial interface IEnumerator
+ {
+ object Current { get; }
+ bool MoveNext();
+ void Reset();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IEqualityComparer
+ {
+ bool Equals(object x, object y);
+ int GetHashCode(object obj);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IList : System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ bool IsFixedSize { get; }
+ bool IsReadOnly { get; }
+ object this[int index] { get; set; }
+ int Add(object value);
+ void Clear();
+ bool Contains(object value);
+ int IndexOf(object value);
+ void Insert(int index, object value);
+ void Remove(object value);
+ void RemoveAt(int index);
+ }
+ public partial interface IStructuralComparable
+ {
+ int CompareTo(object other, System.Collections.IComparer comparer);
+ }
+ public partial interface IStructuralEquatable
+ {
+ bool Equals(object other, System.Collections.IEqualityComparer comparer);
+ int GetHashCode(System.Collections.IEqualityComparer comparer);
+ }
+ public static partial class StructuralComparisons
+ {
+ public static System.Collections.IComparer StructuralComparer { get { throw null; } }
+ public static System.Collections.IEqualityComparer StructuralEqualityComparer { get { throw null; } }
+ }
+}
+namespace System.Collections.Generic
+{
+ public abstract partial class Comparer<T> : System.Collections.Generic.IComparer<T>, System.Collections.IComparer
+ {
+ protected Comparer() { }
+ public static System.Collections.Generic.Comparer<T> Default { get { throw null; } }
+ public abstract int Compare(T x, T y);
+ public static System.Collections.Generic.Comparer<T> Create(System.Comparison<T> comparison) { throw null; }
+ int System.Collections.IComparer.Compare(object x, object y) { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class Dictionary<TKey, TValue> : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IDictionary<TKey, TValue>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IReadOnlyCollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IReadOnlyDictionary<TKey, TValue>, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable
+ {
+ public Dictionary() { }
+ public Dictionary(System.Collections.Generic.IDictionary<TKey, TValue> dictionary) { }
+ public Dictionary(System.Collections.Generic.IDictionary<TKey, TValue> dictionary, System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+ public Dictionary(System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+ public Dictionary(int capacity) { }
+ public Dictionary(int capacity, System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+ protected Dictionary(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public System.Collections.Generic.IEqualityComparer<TKey> Comparer { get { throw null; } }
+ public int Count { get { throw null; } }
+ public TValue this[TKey key] { get { throw null; } set { } }
+ public System.Collections.Generic.Dictionary<TKey, TValue>.KeyCollection Keys { get { throw null; } }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.IsReadOnly { get { throw null; } }
+ System.Collections.Generic.ICollection<TKey> System.Collections.Generic.IDictionary<TKey,TValue>.Keys { get { throw null; } }
+ System.Collections.Generic.ICollection<TValue> System.Collections.Generic.IDictionary<TKey,TValue>.Values { get { throw null; } }
+ System.Collections.Generic.IEnumerable<TKey> System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Keys { get { throw null; } }
+ System.Collections.Generic.IEnumerable<TValue> System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Values { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IDictionary.IsFixedSize { get { throw null; } }
+ bool System.Collections.IDictionary.IsReadOnly { get { throw null; } }
+ object System.Collections.IDictionary.this[object key] { get { throw null; } set { } }
+ System.Collections.ICollection System.Collections.IDictionary.Keys { get { throw null; } }
+ System.Collections.ICollection System.Collections.IDictionary.Values { get { throw null; } }
+ public System.Collections.Generic.Dictionary<TKey, TValue>.ValueCollection Values { get { throw null; } }
+ public void Add(TKey key, TValue value) { }
+ public void Clear() { }
+ public bool ContainsKey(TKey key) { throw null; }
+ public bool ContainsValue(TValue value) { throw null; }
+ public System.Collections.Generic.Dictionary<TKey, TValue>.Enumerator GetEnumerator() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public virtual void OnDeserialization(object sender) { }
+ public bool Remove(TKey key) { throw null; }
+ void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Add(System.Collections.Generic.KeyValuePair<TKey, TValue> keyValuePair) { }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(System.Collections.Generic.KeyValuePair<TKey, TValue> keyValuePair) { throw null; }
+ void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(System.Collections.Generic.KeyValuePair<TKey, TValue>[] array, int index) { }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(System.Collections.Generic.KeyValuePair<TKey, TValue> keyValuePair) { throw null; }
+ System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<TKey, TValue>> System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey,TValue>>.GetEnumerator() { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ void System.Collections.IDictionary.Add(object key, object value) { }
+ bool System.Collections.IDictionary.Contains(object key) { throw null; }
+ System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; }
+ void System.Collections.IDictionary.Remove(object key) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ public bool TryGetValue(TKey key, out TValue value) { value = default(TValue); throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Enumerator : System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.IDictionaryEnumerator, System.Collections.IEnumerator, System.IDisposable
+ {
+ public System.Collections.Generic.KeyValuePair<TKey, TValue> Current { get { throw null; } }
+ System.Collections.DictionaryEntry System.Collections.IDictionaryEnumerator.Entry { get { throw null; } }
+ object System.Collections.IDictionaryEnumerator.Key { get { throw null; } }
+ object System.Collections.IDictionaryEnumerator.Value { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public void Dispose() { }
+ public bool MoveNext() { throw null; }
+ void System.Collections.IEnumerator.Reset() { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public sealed partial class KeyCollection : System.Collections.Generic.ICollection<TKey>, System.Collections.Generic.IEnumerable<TKey>, System.Collections.Generic.IReadOnlyCollection<TKey>, System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ public KeyCollection(System.Collections.Generic.Dictionary<TKey, TValue> dictionary) { }
+ public int Count { get { throw null; } }
+ bool System.Collections.Generic.ICollection<TKey>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ public void CopyTo(TKey[] array, int index) { }
+ public System.Collections.Generic.Dictionary<TKey, TValue>.KeyCollection.Enumerator GetEnumerator() { throw null; }
+ void System.Collections.Generic.ICollection<TKey>.Add(TKey item) { }
+ void System.Collections.Generic.ICollection<TKey>.Clear() { }
+ bool System.Collections.Generic.ICollection<TKey>.Contains(TKey item) { throw null; }
+ bool System.Collections.Generic.ICollection<TKey>.Remove(TKey item) { throw null; }
+ System.Collections.Generic.IEnumerator<TKey> System.Collections.Generic.IEnumerable<TKey>.GetEnumerator() { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Enumerator : System.Collections.Generic.IEnumerator<TKey>, System.Collections.IEnumerator, System.IDisposable
+ {
+ public TKey Current { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public void Dispose() { }
+ public bool MoveNext() { throw null; }
+ void System.Collections.IEnumerator.Reset() { }
+ }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public sealed partial class ValueCollection : System.Collections.Generic.ICollection<TValue>, System.Collections.Generic.IEnumerable<TValue>, System.Collections.Generic.IReadOnlyCollection<TValue>, System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ public ValueCollection(System.Collections.Generic.Dictionary<TKey, TValue> dictionary) { }
+ public int Count { get { throw null; } }
+ bool System.Collections.Generic.ICollection<TValue>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ public void CopyTo(TValue[] array, int index) { }
+ public System.Collections.Generic.Dictionary<TKey, TValue>.ValueCollection.Enumerator GetEnumerator() { throw null; }
+ void System.Collections.Generic.ICollection<TValue>.Add(TValue item) { }
+ void System.Collections.Generic.ICollection<TValue>.Clear() { }
+ bool System.Collections.Generic.ICollection<TValue>.Contains(TValue item) { throw null; }
+ bool System.Collections.Generic.ICollection<TValue>.Remove(TValue item) { throw null; }
+ System.Collections.Generic.IEnumerator<TValue> System.Collections.Generic.IEnumerable<TValue>.GetEnumerator() { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Enumerator : System.Collections.Generic.IEnumerator<TValue>, System.Collections.IEnumerator, System.IDisposable
+ {
+ public TValue Current { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public void Dispose() { }
+ public bool MoveNext() { throw null; }
+ void System.Collections.IEnumerator.Reset() { }
+ }
+ }
+ }
+ public abstract partial class EqualityComparer<T> : System.Collections.Generic.IEqualityComparer<T>, System.Collections.IEqualityComparer
+ {
+ protected EqualityComparer() { }
+ public static System.Collections.Generic.EqualityComparer<T> Default { get { throw null; } }
+ public abstract bool Equals(T x, T y);
+ public abstract int GetHashCode(T obj);
+ bool System.Collections.IEqualityComparer.Equals(object x, object y) { throw null; }
+ int System.Collections.IEqualityComparer.GetHashCode(object obj) { throw null; }
+ }
+ public partial interface ICollection<T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable
+ {
+ int Count { get; }
+ bool IsReadOnly { get; }
+ void Add(T item);
+ void Clear();
+ bool Contains(T item);
+ void CopyTo(T[] array, int arrayIndex);
+ bool Remove(T item);
+ }
+ public partial interface IComparer<in T>
+ {
+ int Compare(T x, T y);
+ }
+ public partial interface IDictionary<TKey, TValue> : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.IEnumerable
+ {
+ TValue this[TKey key] { get; set; }
+ System.Collections.Generic.ICollection<TKey> Keys { get; }
+ System.Collections.Generic.ICollection<TValue> Values { get; }
+ void Add(TKey key, TValue value);
+ bool ContainsKey(TKey key);
+ bool Remove(TKey key);
+ bool TryGetValue(TKey key, out TValue value);
+ }
+ public partial interface IEnumerable<out T> : System.Collections.IEnumerable
+ {
+ new System.Collections.Generic.IEnumerator<T> GetEnumerator();
+ }
+ public partial interface IEnumerator<out T> : System.Collections.IEnumerator, System.IDisposable
+ {
+ new T Current { get; }
+ }
+ public partial interface IEqualityComparer<in T>
+ {
+ bool Equals(T x, T y);
+ int GetHashCode(T obj);
+ }
+ public partial interface IList<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable
+ {
+ T this[int index] { get; set; }
+ int IndexOf(T item);
+ void Insert(int index, T item);
+ void RemoveAt(int index);
+ }
+ public partial interface IReadOnlyCollection<out T> : System.Collections.Generic.IEnumerable<T>, System.Collections.IEnumerable
+ {
+ int Count { get; }
+ }
+ public partial interface IReadOnlyDictionary<TKey, TValue> : System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IReadOnlyCollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.IEnumerable
+ {
+ TValue this[TKey key] { get; }
+ System.Collections.Generic.IEnumerable<TKey> Keys { get; }
+ System.Collections.Generic.IEnumerable<TValue> Values { get; }
+ bool ContainsKey(TKey key);
+ bool TryGetValue(TKey key, out TValue value);
+ }
+ public partial interface IReadOnlyList<out T> : System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.IEnumerable
+ {
+ T this[int index] { get; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class KeyNotFoundException : System.SystemException, System.Runtime.Serialization.ISerializable
+ {
+ public KeyNotFoundException() { }
+ public KeyNotFoundException(string message) { }
+ public KeyNotFoundException(string message, System.Exception innerException) { }
+ protected KeyNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct KeyValuePair<TKey, TValue>
+ {
+ public KeyValuePair(TKey key, TValue value) { throw null;}
+ public TKey Key { get { throw null; } }
+ public TValue Value { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public partial class List<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
+ {
+ public List() { }
+ public List(System.Collections.Generic.IEnumerable<T> collection) { }
+ public List(int capacity) { }
+ public int Capacity { get { throw null; } set { } }
+ public int Count { get { throw null; } }
+ public T this[int index] { get { throw null; } set { } }
+ bool System.Collections.Generic.ICollection<T>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IList.IsFixedSize { get { throw null; } }
+ bool System.Collections.IList.IsReadOnly { get { throw null; } }
+ object System.Collections.IList.this[int index] { get { throw null; } set { } }
+ public void Add(T item) { }
+ public void AddRange(System.Collections.Generic.IEnumerable<T> collection) { }
+ public System.Collections.ObjectModel.ReadOnlyCollection<T> AsReadOnly() { throw null; }
+ public int BinarySearch(T item) { throw null; }
+ public int BinarySearch(T item, System.Collections.Generic.IComparer<T> comparer) { throw null; }
+ public int BinarySearch(int index, int count, T item, System.Collections.Generic.IComparer<T> comparer) { throw null; }
+ public void Clear() { }
+ public bool Contains(T item) { throw null; }
+ public System.Collections.Generic.List<TOutput> ConvertAll<TOutput>(System.Converter<T, TOutput> converter) { throw null; }
+ public void CopyTo(T[] array) { }
+ public void CopyTo(T[] array, int arrayIndex) { }
+ public void CopyTo(int index, T[] array, int arrayIndex, int count) { }
+ public bool Exists(System.Predicate<T> match) { throw null; }
+ public T Find(System.Predicate<T> match) { throw null; }
+ public System.Collections.Generic.List<T> FindAll(System.Predicate<T> match) { throw null; }
+ public int FindIndex(int startIndex, int count, System.Predicate<T> match) { throw null; }
+ public int FindIndex(int startIndex, System.Predicate<T> match) { throw null; }
+ public int FindIndex(System.Predicate<T> match) { throw null; }
+ public T FindLast(System.Predicate<T> match) { throw null; }
+ public int FindLastIndex(int startIndex, int count, System.Predicate<T> match) { throw null; }
+ public int FindLastIndex(int startIndex, System.Predicate<T> match) { throw null; }
+ public int FindLastIndex(System.Predicate<T> match) { throw null; }
+ public void ForEach(System.Action<T> action) { }
+ public System.Collections.Generic.List<T>.Enumerator GetEnumerator() { throw null; }
+ public System.Collections.Generic.List<T> GetRange(int index, int count) { throw null; }
+ public int IndexOf(T item) { throw null; }
+ public int IndexOf(T item, int index) { throw null; }
+ public int IndexOf(T item, int index, int count) { throw null; }
+ public void Insert(int index, T item) { }
+ public void InsertRange(int index, System.Collections.Generic.IEnumerable<T> collection) { }
+ public int LastIndexOf(T item) { throw null; }
+ public int LastIndexOf(T item, int index) { throw null; }
+ public int LastIndexOf(T item, int index, int count) { throw null; }
+ public bool Remove(T item) { throw null; }
+ public int RemoveAll(System.Predicate<T> match) { throw null; }
+ public void RemoveAt(int index) { }
+ public void RemoveRange(int index, int count) { }
+ public void Reverse() { }
+ public void Reverse(int index, int count) { }
+ public void Sort() { }
+ public void Sort(System.Collections.Generic.IComparer<T> comparer) { }
+ public void Sort(System.Comparison<T> comparison) { }
+ public void Sort(int index, int count, System.Collections.Generic.IComparer<T> comparer) { }
+ System.Collections.Generic.IEnumerator<T> System.Collections.Generic.IEnumerable<T>.GetEnumerator() { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ int System.Collections.IList.Add(object item) { throw null; }
+ bool System.Collections.IList.Contains(object item) { throw null; }
+ int System.Collections.IList.IndexOf(object item) { throw null; }
+ void System.Collections.IList.Insert(int index, object item) { }
+ void System.Collections.IList.Remove(object item) { }
+ public T[] ToArray() { throw null; }
+ public void TrimExcess() { }
+ public bool TrueForAll(System.Predicate<T> match) { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Enumerator : System.Collections.Generic.IEnumerator<T>, System.Collections.IEnumerator, System.IDisposable
+ {
+ public T Current { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public void Dispose() { }
+ public bool MoveNext() { throw null; }
+ void System.Collections.IEnumerator.Reset() { }
+ }
+ }
+}
+namespace System.Collections.ObjectModel
+{
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class Collection<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
+ {
+ public Collection() { }
+ public Collection(System.Collections.Generic.IList<T> list) { }
+ public int Count { get { throw null; } }
+ public T this[int index] { get { throw null; } set { } }
+ protected System.Collections.Generic.IList<T> Items { get { throw null; } }
+ bool System.Collections.Generic.ICollection<T>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IList.IsFixedSize { get { throw null; } }
+ bool System.Collections.IList.IsReadOnly { get { throw null; } }
+ object System.Collections.IList.this[int index] { get { throw null; } set { } }
+ public void Add(T item) { }
+ public void Clear() { }
+ protected virtual void ClearItems() { }
+ public bool Contains(T item) { throw null; }
+ public void CopyTo(T[] array, int index) { }
+ public System.Collections.Generic.IEnumerator<T> GetEnumerator() { throw null; }
+ public int IndexOf(T item) { throw null; }
+ public void Insert(int index, T item) { }
+ protected virtual void InsertItem(int index, T item) { }
+ public bool Remove(T item) { throw null; }
+ public void RemoveAt(int index) { }
+ protected virtual void RemoveItem(int index) { }
+ protected virtual void SetItem(int index, T item) { }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ int System.Collections.IList.Add(object value) { throw null; }
+ bool System.Collections.IList.Contains(object value) { throw null; }
+ int System.Collections.IList.IndexOf(object value) { throw null; }
+ void System.Collections.IList.Insert(int index, object value) { }
+ void System.Collections.IList.Remove(object value) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public abstract partial class KeyedCollection<TKey, TItem> : System.Collections.ObjectModel.Collection<TItem>
+ {
+ protected KeyedCollection() { }
+ protected KeyedCollection(System.Collections.Generic.IEqualityComparer<TKey> comparer) { }
+ protected KeyedCollection(System.Collections.Generic.IEqualityComparer<TKey> comparer, int dictionaryCreationThreshold) { }
+ public System.Collections.Generic.IEqualityComparer<TKey> Comparer { get { throw null; } }
+ protected System.Collections.Generic.IDictionary<TKey, TItem> Dictionary { get { throw null; } }
+ public TItem this[TKey key] { get { throw null; } }
+ protected void ChangeItemKey(TItem item, TKey newKey) { }
+ protected override void ClearItems() { }
+ public bool Contains(TKey key) { throw null; }
+ protected abstract TKey GetKeyForItem(TItem item);
+ protected override void InsertItem(int index, TItem item) { }
+ public bool Remove(TKey key) { throw null; }
+ protected override void RemoveItem(int index) { }
+ protected override void SetItem(int index, TItem item) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class ReadOnlyCollection<T> : System.Collections.Generic.ICollection<T>, System.Collections.Generic.IEnumerable<T>, System.Collections.Generic.IList<T>, System.Collections.Generic.IReadOnlyCollection<T>, System.Collections.Generic.IReadOnlyList<T>, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList
+ {
+ public ReadOnlyCollection(System.Collections.Generic.IList<T> list) { }
+ public int Count { get { throw null; } }
+ public T this[int index] { get { throw null; } }
+ protected System.Collections.Generic.IList<T> Items { get { throw null; } }
+ bool System.Collections.Generic.ICollection<T>.IsReadOnly { get { throw null; } }
+ T System.Collections.Generic.IList<T>.this[int index] { get { throw null; } set { } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IList.IsFixedSize { get { throw null; } }
+ bool System.Collections.IList.IsReadOnly { get { throw null; } }
+ object System.Collections.IList.this[int index] { get { throw null; } set { } }
+ public bool Contains(T value) { throw null; }
+ public void CopyTo(T[] array, int index) { }
+ public System.Collections.Generic.IEnumerator<T> GetEnumerator() { throw null; }
+ public int IndexOf(T value) { throw null; }
+ void System.Collections.Generic.ICollection<T>.Add(T value) { }
+ void System.Collections.Generic.ICollection<T>.Clear() { }
+ bool System.Collections.Generic.ICollection<T>.Remove(T value) { throw null; }
+ void System.Collections.Generic.IList<T>.Insert(int index, T value) { }
+ void System.Collections.Generic.IList<T>.RemoveAt(int index) { }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ int System.Collections.IList.Add(object value) { throw null; }
+ void System.Collections.IList.Clear() { }
+ bool System.Collections.IList.Contains(object value) { throw null; }
+ int System.Collections.IList.IndexOf(object value) { throw null; }
+ void System.Collections.IList.Insert(int index, object value) { }
+ void System.Collections.IList.Remove(object value) { }
+ void System.Collections.IList.RemoveAt(int index) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public partial class ReadOnlyDictionary<TKey, TValue> : System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IDictionary<TKey, TValue>, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IReadOnlyCollection<System.Collections.Generic.KeyValuePair<TKey, TValue>>, System.Collections.Generic.IReadOnlyDictionary<TKey, TValue>, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable
+ {
+ public ReadOnlyDictionary(System.Collections.Generic.IDictionary<TKey, TValue> dictionary) { }
+ public int Count { get { throw null; } }
+ protected System.Collections.Generic.IDictionary<TKey, TValue> Dictionary { get { throw null; } }
+ public TValue this[TKey key] { get { throw null; } }
+ public System.Collections.ObjectModel.ReadOnlyDictionary<TKey, TValue>.KeyCollection Keys { get { throw null; } }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.IsReadOnly { get { throw null; } }
+ TValue System.Collections.Generic.IDictionary<TKey,TValue>.this[TKey key] { get { throw null; } set { } }
+ System.Collections.Generic.ICollection<TKey> System.Collections.Generic.IDictionary<TKey,TValue>.Keys { get { throw null; } }
+ System.Collections.Generic.ICollection<TValue> System.Collections.Generic.IDictionary<TKey,TValue>.Values { get { throw null; } }
+ System.Collections.Generic.IEnumerable<TKey> System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Keys { get { throw null; } }
+ System.Collections.Generic.IEnumerable<TValue> System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Values { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ bool System.Collections.IDictionary.IsFixedSize { get { throw null; } }
+ bool System.Collections.IDictionary.IsReadOnly { get { throw null; } }
+ object System.Collections.IDictionary.this[object key] { get { throw null; } set { } }
+ System.Collections.ICollection System.Collections.IDictionary.Keys { get { throw null; } }
+ System.Collections.ICollection System.Collections.IDictionary.Values { get { throw null; } }
+ public System.Collections.ObjectModel.ReadOnlyDictionary<TKey, TValue>.ValueCollection Values { get { throw null; } }
+ public bool ContainsKey(TKey key) { throw null; }
+ public System.Collections.Generic.IEnumerator<System.Collections.Generic.KeyValuePair<TKey, TValue>> GetEnumerator() { throw null; }
+ void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Add(System.Collections.Generic.KeyValuePair<TKey, TValue> item) { }
+ void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Clear() { }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Contains(System.Collections.Generic.KeyValuePair<TKey, TValue> item) { throw null; }
+ void System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.CopyTo(System.Collections.Generic.KeyValuePair<TKey, TValue>[] array, int arrayIndex) { }
+ bool System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<TKey,TValue>>.Remove(System.Collections.Generic.KeyValuePair<TKey, TValue> item) { throw null; }
+ void System.Collections.Generic.IDictionary<TKey,TValue>.Add(TKey key, TValue value) { }
+ bool System.Collections.Generic.IDictionary<TKey,TValue>.Remove(TKey key) { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ void System.Collections.IDictionary.Add(object key, object value) { }
+ void System.Collections.IDictionary.Clear() { }
+ bool System.Collections.IDictionary.Contains(object key) { throw null; }
+ System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() { throw null; }
+ void System.Collections.IDictionary.Remove(object key) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ public bool TryGetValue(TKey key, out TValue value) { value = default(TValue); throw null; }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public sealed partial class KeyCollection : System.Collections.Generic.ICollection<TKey>, System.Collections.Generic.IEnumerable<TKey>, System.Collections.Generic.IReadOnlyCollection<TKey>, System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ internal KeyCollection() { }
+ public int Count { get { throw null; } }
+ bool System.Collections.Generic.ICollection<TKey>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ public void CopyTo(TKey[] array, int arrayIndex) { }
+ public System.Collections.Generic.IEnumerator<TKey> GetEnumerator() { throw null; }
+ void System.Collections.Generic.ICollection<TKey>.Add(TKey item) { }
+ void System.Collections.Generic.ICollection<TKey>.Clear() { }
+ bool System.Collections.Generic.ICollection<TKey>.Contains(TKey item) { throw null; }
+ bool System.Collections.Generic.ICollection<TKey>.Remove(TKey item) { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Count = {Count}")]
+ public sealed partial class ValueCollection : System.Collections.Generic.ICollection<TValue>, System.Collections.Generic.IEnumerable<TValue>, System.Collections.Generic.IReadOnlyCollection<TValue>, System.Collections.ICollection, System.Collections.IEnumerable
+ {
+ internal ValueCollection() { }
+ public int Count { get { throw null; } }
+ bool System.Collections.Generic.ICollection<TValue>.IsReadOnly { get { throw null; } }
+ bool System.Collections.ICollection.IsSynchronized { get { throw null; } }
+ object System.Collections.ICollection.SyncRoot { get { throw null; } }
+ public void CopyTo(TValue[] array, int arrayIndex) { }
+ public System.Collections.Generic.IEnumerator<TValue> GetEnumerator() { throw null; }
+ void System.Collections.Generic.ICollection<TValue>.Add(TValue item) { }
+ void System.Collections.Generic.ICollection<TValue>.Clear() { }
+ bool System.Collections.Generic.ICollection<TValue>.Contains(TValue item) { throw null; }
+ bool System.Collections.Generic.ICollection<TValue>.Remove(TValue item) { throw null; }
+ void System.Collections.ICollection.CopyTo(System.Array array, int index) { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ }
+ }
+}
+namespace System.Configuration.Assemblies
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum AssemblyHashAlgorithm
+ {
+ MD5 = 32771,
+ None = 0,
+ SHA1 = 32772,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ SHA256 = 32780,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ SHA384 = 32781,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ SHA512 = 32782,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum AssemblyVersionCompatibility
+ {
+ SameMachine = 1,
+ SameProcess = 2,
+ SameDomain = 3,
+ }
+}
+namespace System.Diagnostics
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(68), AllowMultiple=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ConditionalAttribute : System.Attribute
+ {
+ public ConditionalAttribute(string conditionString) { }
+ public string ConditionString { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(3), AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggableAttribute : System.Attribute
+ {
+ public DebuggableAttribute(bool isJITTrackingEnabled, bool isJITOptimizerDisabled) { }
+ public DebuggableAttribute(System.Diagnostics.DebuggableAttribute.DebuggingModes modes) { }
+ public System.Diagnostics.DebuggableAttribute.DebuggingModes DebuggingFlags { get { throw null; } }
+ public bool IsJITOptimizerDisabled { get { throw null; } }
+ public bool IsJITTrackingEnabled { get { throw null; } }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DebuggingModes
+ {
+ Default = 1,
+ DisableOptimizations = 256,
+ EnableEditAndContinue = 4,
+ IgnoreSymbolStoreSequencePoints = 2,
+ None = 0,
+ }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Debugger
+ {
+ [System.ObsoleteAttribute("Do not create instances of the Debugger class. Call the static methods directly on this type instead", true)]
+ public Debugger() { }
+ public static bool IsAttached { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Break() { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsLogging() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool Launch() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void Log(int level, string category, string message) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static void NotifyOfCrossThreadDependency() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(384), AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerBrowsableAttribute : System.Attribute
+ {
+ public DebuggerBrowsableAttribute(System.Diagnostics.DebuggerBrowsableState state) { }
+ public System.Diagnostics.DebuggerBrowsableState State { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DebuggerBrowsableState
+ {
+ Collapsed = 2,
+ Never = 0,
+ RootHidden = 3,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4509), AllowMultiple=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerDisplayAttribute : System.Attribute
+ {
+ public DebuggerDisplayAttribute(string value) { }
+ public string Name { get { throw null; } set { } }
+ public System.Type Target { get { throw null; } set { } }
+ public string TargetTypeName { get { throw null; } set { } }
+ public string Type { get { throw null; } set { } }
+ public string Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(224), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerHiddenAttribute : System.Attribute
+ {
+ public DebuggerHiddenAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(236), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerNonUserCodeAttribute : System.Attribute
+ {
+ public DebuggerNonUserCodeAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(108), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerStepThroughAttribute : System.Attribute
+ {
+ public DebuggerStepThroughAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(13), AllowMultiple=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DebuggerTypeProxyAttribute : System.Attribute
+ {
+ public DebuggerTypeProxyAttribute(string typeName) { }
+ public DebuggerTypeProxyAttribute(System.Type type) { }
+ public string ProxyTypeName { get { throw null; } }
+ public System.Type Target { get { throw null; } set { } }
+ public string TargetTypeName { get { throw null; } set { } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StackFrame
+ {
+ public const int OFFSET_UNKNOWN = -1;
+ [System.Security.SecuritySafeCriticalAttribute]
+ public StackFrame() { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackFrame(bool fNeedFileInfo) { }
+ public StackFrame(int skipFrames) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackFrame(int skipFrames, bool fNeedFileInfo) { }
+ public StackFrame(string fileName, int lineNumber) { }
+ public StackFrame(string fileName, int lineNumber, int colNumber) { }
+ public virtual int GetFileColumnNumber() { throw null; }
+ public virtual int GetFileLineNumber() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual string GetFileName() { throw null; }
+ public virtual int GetILOffset() { throw null; }
+ public virtual System.Reflection.MethodBase GetMethod() { throw null; }
+ public virtual int GetNativeOffset() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StackTrace
+ {
+ public const int METHODS_TO_SKIP = 0;
+ [System.Security.SecuritySafeCriticalAttribute]
+ public StackTrace() { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(bool fNeedFileInfo) { }
+ public StackTrace(System.Diagnostics.StackFrame frame) { }
+ public StackTrace(System.Exception e) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(System.Exception e, bool fNeedFileInfo) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(System.Exception e, int skipFrames) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(System.Exception e, int skipFrames, bool fNeedFileInfo) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(int skipFrames) { }
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(int skipFrames, bool fNeedFileInfo) { }
+ [System.ObsoleteAttribute("This constructor has been deprecated. Please use a constructor that does not require a Thread parameter. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [System.Security.SecurityCriticalAttribute]
+ public StackTrace(System.Threading.Thread targetThread, bool needFileInfo) { }
+ public virtual int FrameCount { get { throw null; } }
+ public virtual System.Diagnostics.StackFrame GetFrame(int index) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Diagnostics.StackFrame[] GetFrames() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ }
+}
+namespace System.Diagnostics.CodeAnalysis
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(32767), Inherited=false, AllowMultiple=true)]
+ [System.Diagnostics.ConditionalAttribute("CODE_ANALYSIS")]
+ public sealed partial class SuppressMessageAttribute : System.Attribute
+ {
+ public SuppressMessageAttribute(string category, string checkId) { }
+ public string Category { get { throw null; } }
+ public string CheckId { get { throw null; } }
+ public string Justification { get { throw null; } set { } }
+ public string MessageId { get { throw null; } set { } }
+ public string Scope { get { throw null; } set { } }
+ public string Target { get { throw null; } set { } }
+ }
+}
+namespace System.Diagnostics.Contracts
+{
+ public static partial class Contract
+ {
+ public static event System.EventHandler<System.Diagnostics.Contracts.ContractFailedEventArgs> ContractFailed { add { } remove { } }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ [System.Diagnostics.ConditionalAttribute("DEBUG")]
+ public static void Assert(bool condition) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ [System.Diagnostics.ConditionalAttribute("DEBUG")]
+ public static void Assert(bool condition, string userMessage) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ [System.Diagnostics.ConditionalAttribute("DEBUG")]
+ public static void Assume(bool condition) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ [System.Diagnostics.ConditionalAttribute("DEBUG")]
+ public static void Assume(bool condition, string userMessage) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void EndContractBlock() { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Ensures(bool condition) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Ensures(bool condition, string userMessage) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification="Exception type used in tools.")]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void EnsuresOnThrow<TException>(bool condition) where TException : System.Exception { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification="Exception type used in tools.")]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void EnsuresOnThrow<TException>(bool condition, string userMessage) where TException : System.Exception { }
+ public static bool Exists(int fromInclusive, int toExclusive, System.Predicate<int> predicate) { throw null; }
+ public static bool Exists<T>(System.Collections.Generic.IEnumerable<T> collection, System.Predicate<T> predicate) { throw null; }
+ public static bool ForAll(int fromInclusive, int toExclusive, System.Predicate<int> predicate) { throw null; }
+ public static bool ForAll<T>(System.Collections.Generic.IEnumerable<T> collection, System.Predicate<T> predicate) { throw null; }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Invariant(bool condition) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Invariant(bool condition, string userMessage) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="value")]
+ public static T OldValue<T>(T value) { throw null; }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Requires(bool condition) { }
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public static void Requires(bool condition, string userMessage) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="condition")]
+ public static void Requires<TException>(bool condition) where TException : System.Exception { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="condition")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId="userMessage")]
+ public static void Requires<TException>(bool condition, string userMessage) where TException : System.Exception { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification="Not intended to be called at runtime.")]
+ public static T Result<T>() { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId="0#", Justification="Not intended to be called at runtime.")]
+ public static T ValueAtReturn<T>(out T value) { value = default(T); throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), AllowMultiple=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractAbbreviatorAttribute : System.Attribute
+ {
+ public ContractAbbreviatorAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), AllowMultiple=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractArgumentValidatorAttribute : System.Attribute
+ {
+ public ContractArgumentValidatorAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5124), AllowMultiple=false, Inherited=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ [System.Diagnostics.ConditionalAttribute("DEBUG")]
+ public sealed partial class ContractClassAttribute : System.Attribute
+ {
+ public ContractClassAttribute(System.Type typeContainingContracts) { }
+ public System.Type TypeContainingContracts { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4), AllowMultiple=false, Inherited=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractClassForAttribute : System.Attribute
+ {
+ public ContractClassForAttribute(System.Type typeContractsAreFor) { }
+ public System.Type TypeContractsAreFor { get { throw null; } }
+ }
+ public sealed partial class ContractFailedEventArgs : System.EventArgs
+ {
+ public ContractFailedEventArgs(System.Diagnostics.Contracts.ContractFailureKind failureKind, string message, string condition, System.Exception originalException) { }
+ public string Condition { get { throw null; } }
+ public System.Diagnostics.Contracts.ContractFailureKind FailureKind { get { throw null; } }
+ public bool Handled { get { throw null; } }
+ public string Message { get { throw null; } }
+ public System.Exception OriginalException { get { throw null; } }
+ public bool Unwind { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public void SetHandled() { }
+ [System.Security.SecurityCriticalAttribute]
+ public void SetUnwind() { }
+ }
+ public enum ContractFailureKind
+ {
+ Assert = 4,
+ Assume = 5,
+ Invariant = 3,
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Postcondition")]
+ Postcondition = 1,
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId="Postcondition")]
+ PostconditionOnException = 2,
+ Precondition = 0,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), AllowMultiple=false, Inherited=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractInvariantMethodAttribute : System.Attribute
+ {
+ public ContractInvariantMethodAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(32767), AllowMultiple=true, Inherited=false)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractOptionAttribute : System.Attribute
+ {
+ public ContractOptionAttribute(string category, string setting, bool enabled) { }
+ public ContractOptionAttribute(string category, string setting, string value) { }
+ public string Category { get { throw null; } }
+ public bool Enabled { get { throw null; } }
+ public string Setting { get { throw null; } }
+ public string Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256))]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification="Thank you very much, but we like the names we've defined for the accessors")]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractPublicPropertyNameAttribute : System.Attribute
+ {
+ public ContractPublicPropertyNameAttribute(string name) { }
+ public string Name { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1))]
+ public sealed partial class ContractReferenceAssemblyAttribute : System.Attribute
+ {
+ public ContractReferenceAssemblyAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(192), AllowMultiple=false, Inherited=true)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractRuntimeIgnoredAttribute : System.Attribute
+ {
+ public ContractRuntimeIgnoredAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(237))]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class ContractVerificationAttribute : System.Attribute
+ {
+ public ContractVerificationAttribute(bool value) { }
+ public bool Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(6884), AllowMultiple=false, Inherited=true)]
+ [System.Diagnostics.ConditionalAttribute("CONTRACTS_FULL")]
+ public sealed partial class PureAttribute : System.Attribute
+ {
+ public PureAttribute() { }
+ }
+}
+namespace System.Diagnostics.Contracts.Internal
+{
+ [System.ObsoleteAttribute("Use the ContractHelper class in the System.Runtime.CompilerServices namespace instead.")]
+ public static partial class ContractHelper
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static string RaiseContractFailedEvent(System.Diagnostics.Contracts.ContractFailureKind failureKind, string userMessage, string conditionText, System.Exception innerException) { throw null; }
+ [System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static void TriggerFailure(System.Diagnostics.Contracts.ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, System.Exception innerException) { }
+ }
+}
+namespace System.Diagnostics.SymbolStore
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ISymbolDocumentWriter
+ {
+ void SetCheckSum(System.Guid algorithmId, byte[] checkSum);
+ void SetSource(byte[] source);
+ }
+}
+namespace System.Diagnostics.Tracing
+{
+ [System.FlagsAttribute]
+ public enum EventActivityOptions
+ {
+ Detachable = 8,
+ Disable = 2,
+ None = 0,
+ Recursive = 4,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ public sealed partial class EventAttribute : System.Attribute
+ {
+ public EventAttribute(int eventId) { }
+ public System.Diagnostics.Tracing.EventActivityOptions ActivityOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public System.Diagnostics.Tracing.EventChannel Channel { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public int EventId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public System.Diagnostics.Tracing.EventKeywords Keywords { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public System.Diagnostics.Tracing.EventLevel Level { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public string Message { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public System.Diagnostics.Tracing.EventOpcode Opcode { get { throw null; } set { } }
+ public System.Diagnostics.Tracing.EventTags Tags { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public System.Diagnostics.Tracing.EventTask Task { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public byte Version { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification="Backwards compatibility")]
+ public enum EventChannel : byte
+ {
+ Admin = (byte)16,
+ Analytic = (byte)18,
+ Debug = (byte)19,
+ None = (byte)0,
+ Operational = (byte)17,
+ }
+ public enum EventCommand
+ {
+ Disable = -3,
+ Enable = -2,
+ SendManifest = -1,
+ Update = 0,
+ }
+ public partial class EventCommandEventArgs : System.EventArgs
+ {
+ internal EventCommandEventArgs() { }
+ public System.Collections.Generic.IDictionary<string, string> Arguments { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public System.Diagnostics.Tracing.EventCommand Command { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public bool DisableEvent(int eventId) { throw null; }
+ public bool EnableEvent(int eventId) { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(12), Inherited=false)]
+ public partial class EventDataAttribute : System.Attribute
+ {
+ public EventDataAttribute() { }
+ public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public partial class EventFieldAttribute : System.Attribute
+ {
+ public EventFieldAttribute() { }
+ public System.Diagnostics.Tracing.EventFieldFormat Format { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public System.Diagnostics.Tracing.EventFieldTags Tags { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ }
+ public enum EventFieldFormat
+ {
+ Boolean = 3,
+ Default = 0,
+ Hexadecimal = 4,
+ HResult = 15,
+ Json = 12,
+ String = 2,
+ Xml = 11,
+ }
+ [System.FlagsAttribute]
+ public enum EventFieldTags
+ {
+ None = 0,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128))]
+ public partial class EventIgnoreAttribute : System.Attribute
+ {
+ public EventIgnoreAttribute() { }
+ }
+ [System.FlagsAttribute]
+ public enum EventKeywords : long
+ {
+ All = (long)-1,
+ AuditFailure = (long)4503599627370496,
+ AuditSuccess = (long)9007199254740992,
+ CorrelationHint = (long)4503599627370496,
+ EventLogClassic = (long)36028797018963968,
+ MicrosoftTelemetry = (long)562949953421312,
+ None = (long)0,
+ Sqm = (long)2251799813685248,
+ WdiContext = (long)562949953421312,
+ WdiDiagnostic = (long)1125899906842624,
+ }
+ public enum EventLevel
+ {
+ Critical = 1,
+ Error = 2,
+ Informational = 4,
+ LogAlways = 0,
+ Verbose = 5,
+ Warning = 3,
+ }
+ public partial class EventListener : System.IDisposable
+ {
+ public EventListener() { }
+ public void DisableEvents(System.Diagnostics.Tracing.EventSource eventSource) { }
+ public virtual void Dispose() { }
+ public void EnableEvents(System.Diagnostics.Tracing.EventSource eventSource, System.Diagnostics.Tracing.EventLevel level) { }
+ public void EnableEvents(System.Diagnostics.Tracing.EventSource eventSource, System.Diagnostics.Tracing.EventLevel level, System.Diagnostics.Tracing.EventKeywords matchAnyKeyword) { }
+ public void EnableEvents(System.Diagnostics.Tracing.EventSource eventSource, System.Diagnostics.Tracing.EventLevel level, System.Diagnostics.Tracing.EventKeywords matchAnyKeyword, System.Collections.Generic.IDictionary<string, string> arguments) { }
+ public static int EventSourceIndex(System.Diagnostics.Tracing.EventSource eventSource) { throw null; }
+ protected internal virtual void OnEventSourceCreated(System.Diagnostics.Tracing.EventSource eventSource) { }
+ protected internal virtual void OnEventWritten(System.Diagnostics.Tracing.EventWrittenEventArgs eventData) { }
+ }
+ [System.FlagsAttribute]
+ public enum EventManifestOptions
+ {
+ AllCultures = 2,
+ AllowEventSourceOverride = 8,
+ None = 0,
+ OnlyIfNeededForRegistration = 4,
+ Strict = 1,
+ }
+ public enum EventOpcode
+ {
+ DataCollectionStart = 3,
+ DataCollectionStop = 4,
+ Extension = 5,
+ Info = 0,
+ Receive = 240,
+ Reply = 6,
+ Resume = 7,
+ Send = 9,
+ Start = 1,
+ Stop = 2,
+ Suspend = 8,
+ }
+ public partial class EventSource : System.IDisposable
+ {
+ protected EventSource() { }
+ protected EventSource(bool throwOnEventWriteErrors) { }
+ protected EventSource(System.Diagnostics.Tracing.EventSourceSettings settings) { }
+ protected EventSource(System.Diagnostics.Tracing.EventSourceSettings settings, params string[] traits) { }
+ public EventSource(string eventSourceName) { }
+ public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config) { }
+ public EventSource(string eventSourceName, System.Diagnostics.Tracing.EventSourceSettings config, params string[] traits) { }
+ public System.Exception ConstructionException { get { throw null; } }
+ public static System.Guid CurrentThreadActivityId { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public System.Guid Guid { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Diagnostics.Tracing.EventSourceSettings Settings { get { throw null; } }
+ public event System.EventHandler<System.Diagnostics.Tracing.EventCommandEventArgs> EventCommandExecuted { add { } remove { } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ ~EventSource() { }
+ public static string GenerateManifest(System.Type eventSourceType, string assemblyPathToIncludeInManifest) { throw null; }
+ public static string GenerateManifest(System.Type eventSourceType, string assemblyPathToIncludeInManifest, System.Diagnostics.Tracing.EventManifestOptions flags) { throw null; }
+ public static System.Guid GetGuid(System.Type eventSourceType) { throw null; }
+ public static string GetName(System.Type eventSourceType) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Diagnostics.Tracing.EventSource> GetSources() { throw null; }
+ public string GetTrait(string key) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ public bool IsEnabled() { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ public bool IsEnabled(System.Diagnostics.Tracing.EventLevel level, System.Diagnostics.Tracing.EventKeywords keywords) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ public bool IsEnabled(System.Diagnostics.Tracing.EventLevel level, System.Diagnostics.Tracing.EventKeywords keywords, System.Diagnostics.Tracing.EventChannel channel) { throw null; }
+ protected virtual void OnEventCommand(System.Diagnostics.Tracing.EventCommandEventArgs command) { }
+ public static void SendCommand(System.Diagnostics.Tracing.EventSource eventSource, System.Diagnostics.Tracing.EventCommand command, System.Collections.Generic.IDictionary<string, string> commandArguments) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SetCurrentThreadActivityId(System.Guid activityId) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SetCurrentThreadActivityId(System.Guid activityId, out System.Guid oldActivityThatWillContinue) { oldActivityThatWillContinue = default(System.Guid); }
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(string eventName) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(string eventName, System.Diagnostics.Tracing.EventSourceOptions options) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write<T>(string eventName, T data) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write<T>(string eventName, System.Diagnostics.Tracing.EventSourceOptions options, T data) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write<T>(string eventName, ref System.Diagnostics.Tracing.EventSourceOptions options, ref T data) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write<T>(string eventName, ref System.Diagnostics.Tracing.EventSourceOptions options, ref System.Guid activityId, ref System.Guid relatedActivityId, ref T data) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, byte[] arg1) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, int arg1) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, int arg1, int arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, int arg1, int arg2, int arg3) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, int arg1, string arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, long arg1) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, long arg1, byte[] arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, long arg1, long arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, long arg1, long arg2, long arg3) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, long arg1, string arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, params object[] args) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1, int arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1, int arg2, int arg3) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1, long arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1, string arg2) { }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Concurrency", "CA8001", Justification="This does not need to be correct when racing with other threads")]
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEvent(int eventId, string arg1, string arg2, string arg3) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ protected unsafe void WriteEventCore(int eventId, int eventDataCount, System.Diagnostics.Tracing.EventSource.EventData* data) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void WriteEventWithRelatedActivityId(int eventId, System.Guid relatedActivityId, params object[] args) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, System.Guid* relatedActivityId, int eventDataCount, System.Diagnostics.Tracing.EventSource.EventData* data) { }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ protected internal partial struct EventData
+ {
+ public System.IntPtr DataPointer { get { throw null; } set { } }
+ public int Size { get { throw null; } set { } }
+ }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4))]
+ public sealed partial class EventSourceAttribute : System.Attribute
+ {
+ public EventSourceAttribute() { }
+ public string Guid { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public string LocalizationResources { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
+ }
+ public partial class EventSourceException : System.Exception
+ {
+ public EventSourceException() { }
+ public EventSourceException(string message) { }
+ public EventSourceException(string message, System.Exception innerException) { }
+ protected EventSourceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct EventSourceOptions
+ {
+ public System.Diagnostics.Tracing.EventActivityOptions ActivityOptions { get { throw null; } set { } }
+ public System.Diagnostics.Tracing.EventKeywords Keywords { get { throw null; } set { } }
+ public System.Diagnostics.Tracing.EventLevel Level { get { throw null; } set { } }
+ public System.Diagnostics.Tracing.EventOpcode Opcode { get { throw null; } set { } }
+ public System.Diagnostics.Tracing.EventTags Tags { get { throw null; } set { } }
+ }
+ [System.FlagsAttribute]
+ public enum EventSourceSettings
+ {
+ Default = 0,
+ EtwManifestEventFormat = 4,
+ EtwSelfDescribingEventFormat = 8,
+ ThrowOnEventWriteErrors = 1,
+ }
+ [System.FlagsAttribute]
+ public enum EventTags
+ {
+ None = 0,
+ }
+ public enum EventTask
+ {
+ None = 0,
+ }
+ public partial class EventWrittenEventArgs : System.EventArgs
+ {
+ internal EventWrittenEventArgs() { }
+ public System.Guid ActivityId { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public System.Diagnostics.Tracing.EventChannel Channel { get { throw null; } }
+ public int EventId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public string EventName { get { throw null; } }
+ public System.Diagnostics.Tracing.EventSource EventSource { get { throw null; } }
+ public System.Diagnostics.Tracing.EventKeywords Keywords { get { throw null; } }
+ public System.Diagnostics.Tracing.EventLevel Level { get { throw null; } }
+ public string Message { get { throw null; } }
+ public System.Diagnostics.Tracing.EventOpcode Opcode { get { throw null; } }
+ public System.Collections.ObjectModel.ReadOnlyCollection<object> Payload { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public System.Collections.ObjectModel.ReadOnlyCollection<string> PayloadNames { get { throw null; } }
+ public System.Guid RelatedActivityId { [System.Runtime.CompilerServices.CompilerGeneratedAttribute, System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public System.Diagnostics.Tracing.EventTags Tags { get { throw null; } }
+ public System.Diagnostics.Tracing.EventTask Task { get { throw null; } }
+ public byte Version { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ public sealed partial class NonEventAttribute : System.Attribute
+ {
+ public NonEventAttribute() { }
+ }
+}
+namespace System.Globalization
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Calendar : System.ICloneable
+ {
+ public const int CurrentEra = 0;
+ protected Calendar() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+ protected virtual int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public abstract int[] Eras { get; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public bool IsReadOnly { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.DateTime MinSupportedDateTime { get { throw null; } }
+ public virtual int TwoDigitYearMax { get { throw null; } set { } }
+ public virtual System.DateTime AddDays(System.DateTime time, int days) { throw null; }
+ public virtual System.DateTime AddHours(System.DateTime time, int hours) { throw null; }
+ public virtual System.DateTime AddMilliseconds(System.DateTime time, double milliseconds) { throw null; }
+ public virtual System.DateTime AddMinutes(System.DateTime time, int minutes) { throw null; }
+ public abstract System.DateTime AddMonths(System.DateTime time, int months);
+ public virtual System.DateTime AddSeconds(System.DateTime time, int seconds) { throw null; }
+ public virtual System.DateTime AddWeeks(System.DateTime time, int weeks) { throw null; }
+ public abstract System.DateTime AddYears(System.DateTime time, int years);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual object Clone() { throw null; }
+ public abstract int GetDayOfMonth(System.DateTime time);
+ public abstract System.DayOfWeek GetDayOfWeek(System.DateTime time);
+ public abstract int GetDayOfYear(System.DateTime time);
+ public virtual int GetDaysInMonth(int year, int month) { throw null; }
+ public abstract int GetDaysInMonth(int year, int month, int era);
+ public virtual int GetDaysInYear(int year) { throw null; }
+ public abstract int GetDaysInYear(int year, int era);
+ public abstract int GetEra(System.DateTime time);
+ public virtual int GetHour(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GetLeapMonth(int year) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GetLeapMonth(int year, int era) { throw null; }
+ public virtual double GetMilliseconds(System.DateTime time) { throw null; }
+ public virtual int GetMinute(System.DateTime time) { throw null; }
+ public abstract int GetMonth(System.DateTime time);
+ public virtual int GetMonthsInYear(int year) { throw null; }
+ public abstract int GetMonthsInYear(int year, int era);
+ public virtual int GetSecond(System.DateTime time) { throw null; }
+ public virtual int GetWeekOfYear(System.DateTime time, System.Globalization.CalendarWeekRule rule, System.DayOfWeek firstDayOfWeek) { throw null; }
+ public abstract int GetYear(System.DateTime time);
+ public virtual bool IsLeapDay(int year, int month, int day) { throw null; }
+ public abstract bool IsLeapDay(int year, int month, int day, int era);
+ public virtual bool IsLeapMonth(int year, int month) { throw null; }
+ public abstract bool IsLeapMonth(int year, int month, int era);
+ public virtual bool IsLeapYear(int year) { throw null; }
+ public abstract bool IsLeapYear(int year, int era);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.Globalization.Calendar ReadOnly(System.Globalization.Calendar calendar) { throw null; }
+ public virtual System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) { throw null; }
+ public abstract System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
+ public virtual int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CalendarAlgorithmType
+ {
+ LunarCalendar = 2,
+ LunisolarCalendar = 3,
+ SolarCalendar = 1,
+ Unknown = 0,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CalendarWeekRule
+ {
+ FirstDay = 0,
+ FirstFourDayWeek = 2,
+ FirstFullWeek = 1,
+ }
+ public static partial class CharUnicodeInfo
+ {
+ public static int GetDecimalDigitValue(char ch) { throw null; }
+ public static int GetDecimalDigitValue(string s, int index) { throw null; }
+ public static int GetDigitValue(char ch) { throw null; }
+ public static int GetDigitValue(string s, int index) { throw null; }
+ public static double GetNumericValue(char ch) { throw null; }
+ public static double GetNumericValue(string s, int index) { throw null; }
+ public static System.Globalization.UnicodeCategory GetUnicodeCategory(char ch) { throw null; }
+ public static System.Globalization.UnicodeCategory GetUnicodeCategory(string s, int index) { throw null; }
+ }
+ public partial class ChineseLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar
+ {
+ public const int ChineseEra = 1;
+ public ChineseLunisolarCalendar() { }
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetEra(System.DateTime time) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CompareInfo : System.Runtime.Serialization.IDeserializationCallback
+ {
+ public int LCID { get { throw null; } }
+ internal CompareInfo() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string Name { get { throw null; } }
+ public virtual int Compare(string string1, int offset1, int length1, string string2, int offset2, int length2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int Compare(string string1, int offset1, int length1, string string2, int offset2, int length2, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int Compare(string string1, int offset1, string string2, int offset2) { throw null; }
+ public virtual int Compare(string string1, int offset1, string string2, int offset2, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int Compare(string string1, string string2) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int Compare(string string1, string string2, System.Globalization.CompareOptions options) { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public static System.Globalization.CompareInfo GetCompareInfo(int culture) { throw null; }
+ public static System.Globalization.CompareInfo GetCompareInfo(int culture, System.Reflection.Assembly assembly) { throw null; }
+ public static System.Globalization.CompareInfo GetCompareInfo(string name) { throw null; }
+ public static System.Globalization.CompareInfo GetCompareInfo(string name, System.Reflection.Assembly assembly) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public virtual int GetHashCode(string source, System.Globalization.CompareOptions options) { throw null; }
+ public virtual System.Globalization.SortKey GetSortKey(string source) { throw null; }
+ public virtual System.Globalization.SortKey GetSortKey(string source, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, char value) { throw null; }
+ public virtual int IndexOf(string source, char value, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, char value, int startIndex) { throw null; }
+ public virtual int IndexOf(string source, char value, int startIndex, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, char value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int IndexOf(string source, char value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, string value) { throw null; }
+ public virtual int IndexOf(string source, string value, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, string value, int startIndex) { throw null; }
+ public virtual int IndexOf(string source, string value, int startIndex, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int IndexOf(string source, string value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int IndexOf(string source, string value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; }
+ public virtual bool IsPrefix(string source, string prefix) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual bool IsPrefix(string source, string prefix, System.Globalization.CompareOptions options) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static bool IsSortable(char ch) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsSortable(string text) { throw null; }
+ public virtual bool IsSuffix(string source, string suffix) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual bool IsSuffix(string source, string suffix, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, char value) { throw null; }
+ public virtual int LastIndexOf(string source, char value, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, char value, int startIndex) { throw null; }
+ public virtual int LastIndexOf(string source, char value, int startIndex, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, char value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int LastIndexOf(string source, char value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, string value) { throw null; }
+ public virtual int LastIndexOf(string source, string value, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, string value, int startIndex) { throw null; }
+ public virtual int LastIndexOf(string source, string value, int startIndex, System.Globalization.CompareOptions options) { throw null; }
+ public virtual int LastIndexOf(string source, string value, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int LastIndexOf(string source, string value, int startIndex, int count, System.Globalization.CompareOptions options) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { }
+ public override string ToString() { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CompareOptions
+ {
+ IgnoreCase = 1,
+ IgnoreKanaType = 8,
+ IgnoreNonSpace = 2,
+ IgnoreSymbols = 4,
+ IgnoreWidth = 16,
+ None = 0,
+ Ordinal = 1073741824,
+ OrdinalIgnoreCase = 268435456,
+ StringSort = 536870912,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CultureInfo : System.ICloneable, System.IFormatProvider
+ {
+ public CultureInfo(int culture) { throw null; }
+ public CultureInfo(int culture, bool useUserOverride) { throw null; }
+ public CultureInfo(string name) { }
+ public CultureInfo(string name, bool useUserOverride) { throw null; }
+ public virtual System.Globalization.Calendar Calendar { get { throw null; } }
+ public virtual System.Globalization.CompareInfo CompareInfo { get { throw null; } }
+ public static System.Globalization.CultureInfo CurrentCulture { get { throw null; } set { } }
+ public static System.Globalization.CultureInfo CurrentUICulture { get { throw null; } set { } }
+ public virtual System.Globalization.DateTimeFormatInfo DateTimeFormat { get { throw null; } set { } }
+ public static System.Globalization.CultureInfo DefaultThreadCurrentCulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public static System.Globalization.CultureInfo DefaultThreadCurrentUICulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public virtual string DisplayName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string EnglishName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static System.Globalization.CultureInfo InstalledUICulture { get { throw null; } }
+ public static System.Globalization.CultureInfo InvariantCulture { get { throw null; } }
+ public virtual bool IsNeutralCulture { get { throw null; } }
+ public bool IsReadOnly { get { throw null; } }
+ public virtual int LCID { get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ public virtual string NativeName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual System.Globalization.NumberFormatInfo NumberFormat { get { throw null; } set { } }
+ public virtual System.Globalization.Calendar[] OptionalCalendars { get { throw null; } }
+ public virtual System.Globalization.CultureInfo Parent { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual System.Globalization.TextInfo TextInfo { get { throw null; } }
+ public virtual string ThreeLetterISOLanguageName { get { throw null; } }
+ public virtual string ThreeLetterWindowsLanguageName { get { throw null; } }
+ public virtual string TwoLetterISOLanguageName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public bool UseUserOverride { get { throw null; } }
+ public void ClearCachedData() { throw null; }
+ public virtual object Clone() { throw null; }
+ public static System.Globalization.CultureInfo CreateSpecificCulture(string name) { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public static System.Globalization.CultureInfo GetCultureInfo(int culture) { throw null; }
+ public static System.Globalization.CultureInfo GetCultureInfo(string name) { throw null; }
+ public static System.Globalization.CultureInfo GetCultureInfo(string name, string altName) { throw null; }
+ public static System.Globalization.CultureInfo GetCultureInfoByIetfLanguageTag(string name) { throw null; }
+ public static System.Globalization.CultureInfo[] GetCultures(System.Globalization.CultureTypes types) { throw null; }
+ public virtual object GetFormat(System.Type formatType) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static System.Globalization.CultureInfo ReadOnly(System.Globalization.CultureInfo ci) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CultureNotFoundException : System.ArgumentException, System.Runtime.Serialization.ISerializable
+ {
+ public CultureNotFoundException() { }
+ public CultureNotFoundException(string message) { }
+ public CultureNotFoundException(string message, System.Exception innerException) { }
+ public CultureNotFoundException(string message, int invalidCultureId, System.Exception innerException) { }
+ public CultureNotFoundException(string paramName, int invalidCultureId, string message) { }
+ public CultureNotFoundException(string paramName, string message) { }
+ public CultureNotFoundException(string message, string invalidCultureName, System.Exception innerException) { }
+ public CultureNotFoundException(string paramName, string invalidCultureName, string message) { }
+ protected CultureNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public virtual System.Nullable<int> InvalidCultureId { get { throw null; } }
+ public virtual string InvalidCultureName { get { throw null; } }
+ public override string Message { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DateTimeFormatInfo : System.ICloneable, System.IFormatProvider
+ {
+ public DateTimeFormatInfo() { }
+ public string[] AbbreviatedDayNames { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] AbbreviatedMonthGenitiveNames { get { throw null; } set { } }
+ public string[] AbbreviatedMonthNames { get { throw null; } set { } }
+ public string AMDesignator { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } set { } }
+ public System.Globalization.Calendar Calendar { get { throw null; } set { } }
+ public System.Globalization.CalendarWeekRule CalendarWeekRule { get { throw null; } set { } }
+ public static System.Globalization.DateTimeFormatInfo CurrentInfo { get { throw null; } }
+ public string DateSeparator { get { throw null; } set { throw null; } }
+ public string[] DayNames { get { throw null; } set { } }
+ public System.DayOfWeek FirstDayOfWeek { get { throw null; } set { } }
+ public string FullDateTimePattern { get { throw null; } set { } }
+ public static System.Globalization.DateTimeFormatInfo InvariantInfo { get { throw null; } }
+ public bool IsReadOnly { get { throw null; } }
+ public string LongDatePattern { get { throw null; } set { } }
+ public string LongTimePattern { get { throw null; } set { } }
+ public string MonthDayPattern { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] MonthGenitiveNames { get { throw null; } set { } }
+ public string[] MonthNames { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string NativeCalendarName { get { throw null; } }
+ public string PMDesignator { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } set { } }
+ public string RFC1123Pattern { get { throw null; } }
+ public string ShortDatePattern { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] ShortestDayNames { get { throw null; } set { } }
+ public string ShortTimePattern { get { throw null; } set { } }
+ public string SortableDateTimePattern { get { throw null; } }
+ public string TimeSeparator { get { throw null; } set { throw null; } }
+ public string UniversalSortableDateTimePattern { get { throw null; } }
+ public string YearMonthPattern { get { throw null; } set { } }
+ public object Clone() { throw null; }
+ public string GetAbbreviatedDayName(System.DayOfWeek dayofweek) { throw null; }
+ public string GetAbbreviatedEraName(int era) { throw null; }
+ public string GetAbbreviatedMonthName(int month) { throw null; }
+ public string[] GetAllDateTimePatterns() { throw null; }
+ public string[] GetAllDateTimePatterns(char format) { throw null; }
+ public string GetDayName(System.DayOfWeek dayofweek) { throw null; }
+ public int GetEra(string eraName) { throw null; }
+ public string GetEraName(int era) { throw null; }
+ public object GetFormat(System.Type formatType) { throw null; }
+ public static System.Globalization.DateTimeFormatInfo GetInstance(System.IFormatProvider provider) { throw null; }
+ public string GetMonthName(int month) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string GetShortestDayName(System.DayOfWeek dayOfWeek) { throw null; }
+ public static System.Globalization.DateTimeFormatInfo ReadOnly(System.Globalization.DateTimeFormatInfo dtfi) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public void SetAllDateTimePatterns(string[] patterns, char format) { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DateTimeStyles
+ {
+ AdjustToUniversal = 16,
+ AllowInnerWhite = 4,
+ AllowLeadingWhite = 1,
+ AllowTrailingWhite = 2,
+ AllowWhiteSpaces = 7,
+ AssumeLocal = 32,
+ AssumeUniversal = 64,
+ NoCurrentDateDefault = 8,
+ None = 0,
+ RoundtripKind = 128,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class DaylightTime
+ {
+ public DaylightTime(System.DateTime start, System.DateTime end, System.TimeSpan delta) { throw null; }
+ public System.TimeSpan Delta { get { throw null; } }
+ public System.DateTime End { get { throw null; } }
+ public System.DateTime Start { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum DigitShapes
+ {
+ Context = 0,
+ NativeNational = 2,
+ None = 1,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class EastAsianLunisolarCalendar : System.Globalization.Calendar
+ {
+ internal EastAsianLunisolarCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public int GetCelestialStem(int sexagenaryYear) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public virtual int GetSexagenaryYear(System.DateTime time) { throw null; }
+ public int GetTerrestrialBranch(int sexagenaryYear) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class GregorianCalendar : System.Globalization.Calendar
+ {
+ public const int ADEra = 1;
+ public GregorianCalendar() { }
+ public GregorianCalendar(System.Globalization.GregorianCalendarTypes type) { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public virtual System.Globalization.GregorianCalendarTypes CalendarType { get { throw null; } set { } }
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum GregorianCalendarTypes
+ {
+ Arabic = 10,
+ Localized = 1,
+ MiddleEastFrench = 9,
+ TransliteratedEnglish = 11,
+ TransliteratedFrench = 12,
+ USEnglish = 2,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class HebrewCalendar : System.Globalization.Calendar
+ {
+ public static readonly int HebrewEra;
+ public HebrewCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class HijriCalendar : System.Globalization.Calendar
+ {
+ public static readonly int HijriEra;
+ public HijriCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public override int[] Eras { get { throw null; } }
+ public int HijriAdjustment { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ public sealed partial class IdnMapping
+ {
+ public IdnMapping() { }
+ public bool AllowUnassigned { get { throw null; } set { throw null; } }
+ public bool UseStd3AsciiRules { get { throw null; } set { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public string GetAscii(string unicode) { throw null; }
+ public string GetAscii(string unicode, int index) { throw null; }
+ public string GetAscii(string unicode, int index, int count) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public string GetUnicode(string ascii) { throw null; }
+ public string GetUnicode(string ascii, int index) { throw null; }
+ public string GetUnicode(string ascii, int index, int count) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class JapaneseCalendar : System.Globalization.Calendar
+ {
+ public JapaneseCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Contracts", "CC1055")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetWeekOfYear(System.DateTime time, System.Globalization.CalendarWeekRule rule, System.DayOfWeek firstDayOfWeek) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ public partial class JapaneseLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar
+ {
+ public const int JapaneseEra = 1;
+ public JapaneseLunisolarCalendar() { }
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int GetEra(System.DateTime time) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class JulianCalendar : System.Globalization.Calendar
+ {
+ public static readonly int JulianEra;
+ public JulianCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class KoreanCalendar : System.Globalization.Calendar
+ {
+ public const int KoreanEra = 1;
+ public KoreanCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Contracts", "CC1055")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetWeekOfYear(System.DateTime time, System.Globalization.CalendarWeekRule rule, System.DayOfWeek firstDayOfWeek) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ public partial class KoreanLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar
+ {
+ public const int GregorianEra = 1;
+ public KoreanLunisolarCalendar() { }
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int GetEra(System.DateTime time) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class NumberFormatInfo : System.ICloneable, System.IFormatProvider
+ {
+ public NumberFormatInfo() { }
+ public int CurrencyDecimalDigits { get { throw null; } set { } }
+ public string CurrencyDecimalSeparator { get { throw null; } set { } }
+ public string CurrencyGroupSeparator { get { throw null; } set { } }
+ public int[] CurrencyGroupSizes { get { throw null; } set { } }
+ public int CurrencyNegativePattern { get { throw null; } set { } }
+ public int CurrencyPositivePattern { get { throw null; } set { } }
+ public string CurrencySymbol { get { throw null; } set { } }
+ public static System.Globalization.NumberFormatInfo CurrentInfo { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Globalization.DigitShapes DigitSubstitution { get { throw null; } set { throw null; } }
+ public static System.Globalization.NumberFormatInfo InvariantInfo { get { throw null; } }
+ public bool IsReadOnly { get { throw null; } }
+ public string NaNSymbol { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string[] NativeDigits { get { throw null; } set { throw null; } }
+ public string NegativeInfinitySymbol { get { throw null; } set { } }
+ public string NegativeSign { get { throw null; } set { } }
+ public int NumberDecimalDigits { get { throw null; } set { } }
+ public string NumberDecimalSeparator { get { throw null; } set { } }
+ public string NumberGroupSeparator { get { throw null; } set { } }
+ public int[] NumberGroupSizes { get { throw null; } set { } }
+ public int NumberNegativePattern { get { throw null; } set { } }
+ public int PercentDecimalDigits { get { throw null; } set { } }
+ public string PercentDecimalSeparator { get { throw null; } set { } }
+ public string PercentGroupSeparator { get { throw null; } set { } }
+ public int[] PercentGroupSizes { get { throw null; } set { } }
+ public int PercentNegativePattern { get { throw null; } set { } }
+ public int PercentPositivePattern { get { throw null; } set { } }
+ public string PercentSymbol { get { throw null; } set { } }
+ public string PerMilleSymbol { get { throw null; } set { } }
+ public string PositiveInfinitySymbol { get { throw null; } set { } }
+ public string PositiveSign { get { throw null; } set { } }
+ public object Clone() { throw null; }
+ public object GetFormat(System.Type formatType) { throw null; }
+ public static System.Globalization.NumberFormatInfo GetInstance(System.IFormatProvider formatProvider) { throw null; }
+ public static System.Globalization.NumberFormatInfo ReadOnly(System.Globalization.NumberFormatInfo nfi) { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum NumberStyles
+ {
+ AllowCurrencySymbol = 256,
+ AllowDecimalPoint = 32,
+ AllowExponent = 128,
+ AllowHexSpecifier = 512,
+ AllowLeadingSign = 4,
+ AllowLeadingWhite = 1,
+ AllowParentheses = 16,
+ AllowThousands = 64,
+ AllowTrailingSign = 8,
+ AllowTrailingWhite = 2,
+ Any = 511,
+ Currency = 383,
+ Float = 167,
+ HexNumber = 515,
+ Integer = 7,
+ None = 0,
+ Number = 111,
+ }
+ public partial class PersianCalendar : System.Globalization.Calendar
+ {
+ public static readonly int PersianEra;
+ public PersianCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class RegionInfo
+ {
+ public RegionInfo(int culture) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public RegionInfo(string name) { }
+ public virtual string CurrencySymbol { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string CurrencyEnglishName { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string CurrencyNativeName { get { throw null; } }
+ public static System.Globalization.RegionInfo CurrentRegion { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string DisplayName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string EnglishName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GeoId { get { throw null; } }
+ public virtual bool IsMetric { get { throw null; } }
+ public virtual string ISOCurrencySymbol { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string NativeName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public virtual string ThreeLetterISORegionName { get { throw null; } }
+ public virtual string ThreeLetterWindowsRegionName { get { throw null; } }
+ public virtual string TwoLetterISORegionName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SortKey
+ {
+ internal SortKey() { throw null; }
+ public virtual byte[] KeyData { get { throw null; } }
+ public virtual string OriginalString { get { throw null; } }
+ public static int Compare(System.Globalization.SortKey sortkey1, System.Globalization.SortKey sortkey2) { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public sealed partial class SortVersion : System.IEquatable<System.Globalization.SortVersion>
+ {
+ public SortVersion(int fullVersion, System.Guid sortId) { throw null; }
+ public int FullVersion { get { throw null; } }
+ public System.Guid SortId { get { throw null; } }
+ public bool Equals(System.Globalization.SortVersion other) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw null; }
+ public static bool operator !=(System.Globalization.SortVersion left, System.Globalization.SortVersion right) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StringInfo
+ {
+ public StringInfo() { }
+ public StringInfo(string value) { }
+ public int LengthInTextElements { get { throw null; } }
+ public string String { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override bool Equals(object value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetHashCode() { throw null; }
+ public static string GetNextTextElement(string str) { throw null; }
+ public static string GetNextTextElement(string str, int index) { throw null; }
+ public static System.Globalization.TextElementEnumerator GetTextElementEnumerator(string str) { throw null; }
+ public static System.Globalization.TextElementEnumerator GetTextElementEnumerator(string str, int index) { throw null; }
+ public static int[] ParseCombiningCharacters(string str) { throw null; }
+ public string SubstringByTextElements(int startingTextElement) { throw null; }
+ public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TaiwanCalendar : System.Globalization.Calendar
+ {
+ public TaiwanCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Contracts", "CC1055")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetWeekOfYear(System.DateTime time, System.Globalization.CalendarWeekRule rule, System.DayOfWeek firstDayOfWeek) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ public partial class TaiwanLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar
+ {
+ public TaiwanLunisolarCalendar() { }
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int GetEra(System.DateTime time) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TextElementEnumerator : System.Collections.IEnumerator
+ {
+ internal TextElementEnumerator() { }
+ public object Current { get { throw null; } }
+ public int ElementIndex { get { throw null; } }
+ public string GetTextElement() { throw null; }
+ public bool MoveNext() { throw null; }
+ public void Reset() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TextInfo : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback
+ {
+ internal TextInfo() { }
+ public virtual int ANSICodePage { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public string CultureName { get { throw null; } }
+ public virtual int EBCDICCodePage { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public bool IsReadOnly { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public bool IsRightToLeft { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public int LCID { get { throw null; } }
+ public virtual string ListSeparator { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Runtime.InteropServices.ComVisibleAttribute(false)]set { } }
+ public virtual int MacCodePage { get { throw null; } }
+ public virtual int OEMCodePage { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual object Clone() { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.Globalization.TextInfo ReadOnly(System.Globalization.TextInfo textInfo) { throw null; }
+ void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual char ToLower(char c) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual string ToLower(string str) { throw null; }
+ public override string ToString() { throw null; }
+ public string ToTitleCase(string str) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual char ToUpper(char c) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual string ToUpper(string str) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ThaiBuddhistCalendar : System.Globalization.Calendar
+ {
+ public const int ThaiBuddhistEra = 1;
+ public ThaiBuddhistCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ public override int[] Eras { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Contracts", "CC1055")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetWeekOfYear(System.DateTime time, System.Globalization.CalendarWeekRule rule, System.DayOfWeek firstDayOfWeek) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.FlagsAttribute]
+ public enum TimeSpanStyles
+ {
+ AssumeNegative = 1,
+ None = 0,
+ }
+ public partial class UmAlQuraCalendar : System.Globalization.Calendar
+ {
+ public const int UmAlQuraEra = 1;
+ public UmAlQuraCalendar() { }
+#if FEATURE_COREFX_GLOBALIZATION
+ public override System.Globalization.CalendarAlgorithmType AlgorithmType { get { throw null; } }
+#endif
+ protected override int DaysInYearBeforeMinSupportedYear { get { throw null; } }
+ public override int[] Eras { get { throw null; } }
+ public override System.DateTime MaxSupportedDateTime { get { throw null; } }
+ public override System.DateTime MinSupportedDateTime { get { throw null; } }
+ public override int TwoDigitYearMax { get { throw null; } set { } }
+ public override System.DateTime AddMonths(System.DateTime time, int months) { throw null; }
+ public override System.DateTime AddYears(System.DateTime time, int years) { throw null; }
+ public override int GetDayOfMonth(System.DateTime time) { throw null; }
+ public override System.DayOfWeek GetDayOfWeek(System.DateTime time) { throw null; }
+ public override int GetDayOfYear(System.DateTime time) { throw null; }
+ public override int GetDaysInMonth(int year, int month, int era) { throw null; }
+ public override int GetDaysInYear(int year, int era) { throw null; }
+ public override int GetEra(System.DateTime time) { throw null; }
+ public override int GetLeapMonth(int year, int era) { throw null; }
+ public override int GetMonth(System.DateTime time) { throw null; }
+ public override int GetMonthsInYear(int year, int era) { throw null; }
+ public override int GetYear(System.DateTime time) { throw null; }
+ public override bool IsLeapDay(int year, int month, int day, int era) { throw null; }
+ public override bool IsLeapMonth(int year, int month, int era) { throw null; }
+ public override bool IsLeapYear(int year, int era) { throw null; }
+ public override System.DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) { throw null; }
+ public override int ToFourDigitYear(int year) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum UnicodeCategory
+ {
+ ClosePunctuation = 21,
+ ConnectorPunctuation = 18,
+ Control = 14,
+ CurrencySymbol = 26,
+ DashPunctuation = 19,
+ DecimalDigitNumber = 8,
+ EnclosingMark = 7,
+ FinalQuotePunctuation = 23,
+ Format = 15,
+ InitialQuotePunctuation = 22,
+ LetterNumber = 9,
+ LineSeparator = 12,
+ LowercaseLetter = 1,
+ MathSymbol = 25,
+ ModifierLetter = 3,
+ ModifierSymbol = 27,
+ NonSpacingMark = 5,
+ OpenPunctuation = 20,
+ OtherLetter = 4,
+ OtherNotAssigned = 29,
+ OtherNumber = 10,
+ OtherPunctuation = 24,
+ OtherSymbol = 28,
+ ParagraphSeparator = 13,
+ PrivateUse = 17,
+ SpaceSeparator = 11,
+ SpacingCombiningMark = 6,
+ Surrogate = 16,
+ TitlecaseLetter = 2,
+ UppercaseLetter = 0,
+ }
+}
+namespace System.IO
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class BinaryReader : System.IDisposable
+ {
+ public BinaryReader(System.IO.Stream input) { }
+ public BinaryReader(System.IO.Stream input, System.Text.Encoding encoding) { }
+ public BinaryReader(System.IO.Stream input, System.Text.Encoding encoding, bool leaveOpen) { }
+ public virtual System.IO.Stream BaseStream { get { throw null; } }
+ public virtual void Close() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ protected virtual void FillBuffer(int numBytes) { }
+ public virtual int PeekChar() { throw null; }
+ public virtual int Read() { throw null; }
+ public virtual int Read(byte[] buffer, int index, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual int Read(char[] buffer, int index, int count) { throw null; }
+ protected internal int Read7BitEncodedInt() { throw null; }
+ public virtual bool ReadBoolean() { throw null; }
+ public virtual byte ReadByte() { throw null; }
+ public virtual byte[] ReadBytes(int count) { throw null; }
+ public virtual char ReadChar() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual char[] ReadChars(int count) { throw null; }
+ public virtual decimal ReadDecimal() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual double ReadDouble() { throw null; }
+ public virtual short ReadInt16() { throw null; }
+ public virtual int ReadInt32() { throw null; }
+ public virtual long ReadInt64() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public virtual sbyte ReadSByte() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual float ReadSingle() { throw null; }
+ public virtual string ReadString() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public virtual ushort ReadUInt16() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public virtual uint ReadUInt32() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public virtual ulong ReadUInt64() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class BinaryWriter : System.IDisposable
+ {
+ public static readonly System.IO.BinaryWriter Null;
+ protected System.IO.Stream OutStream;
+ protected BinaryWriter() { }
+ public BinaryWriter(System.IO.Stream output) { }
+ public BinaryWriter(System.IO.Stream output, System.Text.Encoding encoding) { }
+ public BinaryWriter(System.IO.Stream output, System.Text.Encoding encoding, bool leaveOpen) { }
+ public virtual System.IO.Stream BaseStream { get { throw null; } }
+ public virtual void Close() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public virtual void Flush() { }
+ public virtual long Seek(int offset, System.IO.SeekOrigin origin) { throw null; }
+ public virtual void Write(bool value) { }
+ public virtual void Write(byte value) { }
+ public virtual void Write(byte[] buffer) { }
+ public virtual void Write(byte[] buffer, int index, int count) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Write(char ch) { }
+ public virtual void Write(char[] chars) { }
+ public virtual void Write(char[] chars, int index, int count) { }
+ public virtual void Write(decimal value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Write(double value) { }
+ public virtual void Write(short value) { }
+ public virtual void Write(int value) { }
+ public virtual void Write(long value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(sbyte value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Write(float value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Write(string value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(ushort value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(ulong value) { }
+ protected void Write7BitEncodedInt(int value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class DirectoryNotFoundException : System.IO.IOException
+ {
+ public DirectoryNotFoundException() { }
+ public DirectoryNotFoundException(string message) { }
+ public DirectoryNotFoundException(string message, System.Exception innerException) { }
+ protected DirectoryNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class EndOfStreamException : System.IO.IOException
+ {
+ public EndOfStreamException() { }
+ public EndOfStreamException(string message) { }
+ public EndOfStreamException(string message, System.Exception innerException) { }
+ protected EndOfStreamException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum FileAccess
+ {
+ Read = 1,
+ ReadWrite = 3,
+ Write = 2,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class FileLoadException : System.IO.IOException
+ {
+ public FileLoadException() { }
+ public FileLoadException(string message) { }
+ public FileLoadException(string message, System.Exception inner) { }
+ public FileLoadException(string message, string fileName) { }
+ public FileLoadException(string message, string fileName, System.Exception inner) { }
+ protected FileLoadException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public string FileName { get { throw null; } }
+ public override string Message { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class FileNotFoundException : System.IO.IOException
+ {
+ public FileNotFoundException() { }
+ public FileNotFoundException(string message) { }
+ public FileNotFoundException(string message, System.Exception innerException) { }
+ public FileNotFoundException(string message, string fileName) { }
+ public FileNotFoundException(string message, string fileName, System.Exception innerException) { }
+ protected FileNotFoundException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public string FileName { get { throw null; } }
+ public override string Message { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class IOException : System.SystemException
+ {
+ public IOException() { }
+ public IOException(string message) { }
+ public IOException(string message, System.Exception innerException) { }
+ public IOException(string message, int hresult) { }
+ protected IOException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MemoryStream : System.IO.Stream
+ {
+ public MemoryStream() { }
+ public MemoryStream(byte[] buffer) { }
+ public MemoryStream(byte[] buffer, bool writable) { }
+ public MemoryStream(byte[] buffer, int index, int count) { }
+ public MemoryStream(byte[] buffer, int index, int count, bool writable) { }
+ public MemoryStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) { }
+ public MemoryStream(int capacity) { }
+ public override bool CanRead { get { throw null; } }
+ public override bool CanSeek { get { throw null; } }
+ public override bool CanWrite { get { throw null; } }
+ public virtual int Capacity { get { throw null; } set { } }
+ public override long Length { get { throw null; } }
+ public override long Position { get { throw null; } set { } }
+ public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) { throw null; }
+ protected override void Dispose(bool disposing) { }
+ public override void Flush() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public virtual byte[] GetBuffer() { throw null; }
+ public override int Read(byte[] buffer, int offset, int count) { buffer = default(byte[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override int ReadByte() { throw null; }
+ public override long Seek(long offset, System.IO.SeekOrigin loc) { throw null; }
+ public override void SetLength(long value) { }
+ public virtual byte[] ToArray() { throw null; }
+ public virtual bool TryGetBuffer(out System.ArraySegment<byte> buffer) { buffer = default(System.ArraySegment<byte>); throw null; }
+ public override void Write(byte[] buffer, int offset, int count) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override void WriteByte(byte value) { }
+ public virtual void WriteTo(System.IO.Stream stream) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Path
+ {
+ public static readonly char AltDirectorySeparatorChar;
+ public static readonly char DirectorySeparatorChar;
+ public static readonly char PathSeparator;
+ public static readonly char VolumeSeparatorChar;
+ public static string ChangeExtension(string path, string extension) { throw null; }
+ public static string Combine(string path1, string path2) { throw null; }
+ public static string Combine(string path1, string path2, string path3) { throw null; }
+ public static string Combine(params string[] paths) { throw null; }
+ public static string GetDirectoryName(string path) { throw null; }
+ public static string GetExtension(string path) { throw null; }
+ public static string GetFileName(string path) { throw null; }
+ public static string GetFileNameWithoutExtension(string path) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetFullPath(string path) { throw null; }
+ public static char[] GetInvalidFileNameChars() { throw null; }
+ public static char[] GetInvalidPathChars() { throw null; }
+ public static string GetPathRoot(string path) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetRandomFileName() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetTempFileName() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetTempPath() { throw null; }
+ public static bool HasExtension(string path) { throw null; }
+ public static bool IsPathRooted(string path) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class PathTooLongException : System.IO.IOException
+ {
+ public PathTooLongException() { }
+ public PathTooLongException(string message) { }
+ public PathTooLongException(string message, System.Exception innerException) { }
+ protected PathTooLongException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum SeekOrigin
+ {
+ Begin = 0,
+ Current = 1,
+ End = 2,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Stream : System.IDisposable
+ {
+ public static readonly System.IO.Stream Null;
+ protected Stream() { }
+ public abstract bool CanRead { get; }
+ public abstract bool CanSeek { get; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual bool CanTimeout { get { throw null; } }
+ public abstract bool CanWrite { get; }
+ public abstract long Length { get; }
+ public abstract long Position { get; set; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int ReadTimeout { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int WriteTimeout { get { throw null; } set { } }
+ public virtual System.IAsyncResult BeginRead(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) { throw null; }
+ public virtual System.IAsyncResult BeginWrite(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) { throw null; }
+ public virtual void Close() { }
+ public void CopyTo(System.IO.Stream destination) { }
+ public void CopyTo(System.IO.Stream destination, int bufferSize) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public virtual int EndRead(System.IAsyncResult asyncResult) { throw null; }
+ public virtual void EndWrite(System.IAsyncResult asyncResult) { }
+ public abstract void Flush();
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task FlushAsync() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public abstract int Read(byte[] buffer, int offset, int count);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task<int> ReadAsync(byte[] buffer, int offset, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public virtual int ReadByte() { throw null; }
+ public abstract long Seek(long offset, System.IO.SeekOrigin origin);
+ public abstract void SetLength(long value);
+ public abstract void Write(byte[] buffer, int offset, int count);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public virtual void WriteByte(byte value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StreamReader : System.IO.TextReader
+ {
+ public static readonly new System.IO.StreamReader Null;
+ public StreamReader(System.IO.Stream stream) { }
+ public StreamReader(System.IO.Stream stream, bool detectEncodingFromByteOrderMarks) { }
+ public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding) { }
+ public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks) { }
+ public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) { }
+ public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen) { }
+ public StreamReader(string path) { }
+ public StreamReader(string path, bool detectEncodingFromByteOrderMarks) { }
+ public StreamReader(string path, System.Text.Encoding encoding) { }
+ public StreamReader(string path, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public StreamReader(string path, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize) { }
+ public virtual System.IO.Stream BaseStream { get { throw null; } }
+ public virtual System.Text.Encoding CurrentEncoding { get { throw null; } }
+ public bool EndOfStream { get { throw null; } }
+ public override void Close() { }
+ public void DiscardBufferedData() { }
+ protected override void Dispose(bool disposing) { }
+ public override int Peek() { throw null; }
+ public override int Read() { throw null; }
+ public override int Read(char[] buffer, int index, int count) { buffer = default(char[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadAsync(char[] buffer, int index, int count) { throw null; }
+ public override int ReadBlock(char[] buffer, int index, int count) { buffer = default(char[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadBlockAsync(char[] buffer, int index, int count) { throw null; }
+ public override string ReadLine() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<string> ReadLineAsync() { throw null; }
+ public override string ReadToEnd() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<string> ReadToEndAsync() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StreamWriter : System.IO.TextWriter
+ {
+ public static readonly new System.IO.StreamWriter Null;
+ public StreamWriter(System.IO.Stream stream) { }
+ public StreamWriter(System.IO.Stream stream, System.Text.Encoding encoding) { }
+ public StreamWriter(System.IO.Stream stream, System.Text.Encoding encoding, int bufferSize) { }
+ public StreamWriter(System.IO.Stream stream, System.Text.Encoding encoding, int bufferSize, bool leaveOpen) { }
+ public StreamWriter(string path) { }
+ public StreamWriter(string path, bool append) { }
+ public StreamWriter(string path, bool append, System.Text.Encoding encoding) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public StreamWriter(string path, bool append, System.Text.Encoding encoding, int bufferSize) { }
+ public virtual bool AutoFlush { get { throw null; } set { } }
+ public virtual System.IO.Stream BaseStream { get { throw null; } }
+ public override System.Text.Encoding Encoding { get { throw null; } }
+ public override void Close() { }
+ protected override void Dispose(bool disposing) { }
+ public override void Flush() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task FlushAsync() { throw null; }
+ public override void Write(char value) { }
+ public override void Write(char[] buffer) { }
+ public override void Write(char[] buffer, int index, int count) { }
+ public override void Write(string value) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(string value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(string value) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StringReader : System.IO.TextReader
+ {
+ public StringReader(string s) { }
+ public override void Close() { }
+ protected override void Dispose(bool disposing) { }
+ public override int Peek() { throw null; }
+ public override int Read() { throw null; }
+ public override int Read(char[] buffer, int index, int count) { buffer = default(char[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadBlockAsync(char[] buffer, int index, int count) { throw null; }
+ public override string ReadLine() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<string> ReadLineAsync() { throw null; }
+ public override string ReadToEnd() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<string> ReadToEndAsync() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class StringWriter : System.IO.TextWriter
+ {
+ public StringWriter() { }
+ public StringWriter(System.IFormatProvider formatProvider) { }
+ public StringWriter(System.Text.StringBuilder sb) { }
+ public StringWriter(System.Text.StringBuilder sb, System.IFormatProvider formatProvider) { }
+ public override System.Text.Encoding Encoding { get { throw null; } }
+ public override void Close() { }
+ protected override void Dispose(bool disposing) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task FlushAsync() { throw null; }
+ public virtual System.Text.StringBuilder GetStringBuilder() { throw null; }
+ public override string ToString() { throw null; }
+ public override void Write(char value) { }
+ public override void Write(char[] buffer, int index, int count) { }
+ public override void Write(string value) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(string value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteLineAsync(string value) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class TextReader : System.IDisposable
+ {
+ public static readonly System.IO.TextReader Null;
+ protected TextReader() { }
+ public virtual void Close() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public virtual int Peek() { throw null; }
+ public virtual int Read() { throw null; }
+ public virtual int Read(char[] buffer, int index, int count) { buffer = default(char[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task<int> ReadAsync(char[] buffer, int index, int count) { throw null; }
+ public virtual int ReadBlock(char[] buffer, int index, int count) { buffer = default(char[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task<int> ReadBlockAsync(char[] buffer, int index, int count) { throw null; }
+ public virtual string ReadLine() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task<string> ReadLineAsync() { throw null; }
+ public virtual string ReadToEnd() { throw null; }
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task<string> ReadToEndAsync() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class TextWriter : System.IDisposable
+ {
+ protected char[] CoreNewLine;
+ public static readonly System.IO.TextWriter Null;
+ protected TextWriter() { }
+ protected TextWriter(System.IFormatProvider formatProvider) { }
+ public abstract System.Text.Encoding Encoding { get; }
+ public virtual System.IFormatProvider FormatProvider { get { throw null; } }
+ public virtual string NewLine { get { throw null; } set { } }
+ public virtual void Close() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public virtual void Flush() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task FlushAsync() { throw null; }
+ public virtual void Write(bool value) { }
+ public virtual void Write(char value) { }
+ public virtual void Write(char[] buffer) { }
+ public virtual void Write(char[] buffer, int index, int count) { }
+ public virtual void Write(decimal value) { }
+ public virtual void Write(double value) { }
+ public virtual void Write(int value) { }
+ public virtual void Write(long value) { }
+ public virtual void Write(object value) { }
+ public virtual void Write(float value) { }
+ public virtual void Write(string value) { }
+ public virtual void Write(string format, object arg0) { }
+ public virtual void Write(string format, object arg0, object arg1) { }
+ public virtual void Write(string format, object arg0, object arg1, object arg2) { }
+ public virtual void Write(string format, params object[] arg) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void Write(ulong value) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task WriteAsync(char[] buffer) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteAsync(string value) { throw null; }
+ public virtual void WriteLine() { }
+ public virtual void WriteLine(bool value) { }
+ public virtual void WriteLine(char value) { }
+ public virtual void WriteLine(char[] buffer) { }
+ public virtual void WriteLine(char[] buffer, int index, int count) { }
+ public virtual void WriteLine(decimal value) { }
+ public virtual void WriteLine(double value) { }
+ public virtual void WriteLine(int value) { }
+ public virtual void WriteLine(long value) { }
+ public virtual void WriteLine(object value) { }
+ public virtual void WriteLine(float value) { }
+ public virtual void WriteLine(string value) { }
+ public virtual void WriteLine(string format, object arg0) { }
+ public virtual void WriteLine(string format, object arg0, object arg1) { }
+ public virtual void WriteLine(string format, object arg0, object arg1, object arg2) { }
+ public virtual void WriteLine(string format, params object[] arg) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void WriteLine(uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ public virtual void WriteLine(ulong value) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteLineAsync() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteLineAsync(char value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Threading.Tasks.Task WriteLineAsync(char[] buffer) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteLineAsync(char[] buffer, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Threading.Tasks.Task WriteLineAsync(string value) { throw null; }
+ }
+ public partial class UnmanagedMemoryAccessor : System.IDisposable
+ {
+ protected UnmanagedMemoryAccessor() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UnmanagedMemoryAccessor(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long capacity) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UnmanagedMemoryAccessor(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long capacity, System.IO.FileAccess access) { }
+ public bool CanRead { get { throw null; } }
+ public bool CanWrite { get { throw null; } }
+ public long Capacity { get { throw null; } }
+ protected bool IsOpen { get { throw null; } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ protected void Initialize(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long capacity, System.IO.FileAccess access) { }
+ public bool ReadBoolean(long position) { throw null; }
+ public byte ReadByte(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public char ReadChar(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public decimal ReadDecimal(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public double ReadDouble(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public short ReadInt16(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int ReadInt32(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public long ReadInt64(long position) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sbyte ReadSByte(long position) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public float ReadSingle(long position) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public ushort ReadUInt16(long position) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public uint ReadUInt32(long position) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public ulong ReadUInt64(long position) { throw null; }
+ public void Write(long position, bool value) { }
+ public void Write(long position, byte value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, char value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, decimal value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, double value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, short value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, int value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, long value) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, sbyte value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, float value) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, ushort value) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Write(long position, ulong value) { }
+ }
+ public partial class UnmanagedMemoryStream : System.IO.Stream
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected UnmanagedMemoryStream() { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe UnmanagedMemoryStream(byte* pointer, long length) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, System.IO.FileAccess access) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UnmanagedMemoryStream(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long length) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public UnmanagedMemoryStream(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long length, System.IO.FileAccess access) { }
+ public override bool CanRead { get { throw null; } }
+ public override bool CanSeek { get { throw null; } }
+ public override bool CanWrite { get { throw null; } }
+ public long Capacity { get { throw null; } }
+ public override long Length { get { throw null; } }
+ public override long Position { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ [System.CLSCompliantAttribute(false)]
+ public unsafe byte* PositionPointer { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected override void Dispose(bool disposing) { }
+ public override void Flush() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ protected unsafe void Initialize(byte* pointer, long length, long capacity, System.IO.FileAccess access) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected void Initialize(System.Runtime.InteropServices.SafeBuffer buffer, long offset, long length, System.IO.FileAccess access) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int Read(byte[] buffer, int offset, int count) { buffer = default(byte[]); throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override int ReadByte() { throw null; }
+ public override long Seek(long offset, System.IO.SeekOrigin loc) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override void SetLength(long value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override void Write(byte[] buffer, int offset, int count) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override void WriteByte(byte value) { }
+ }
+}
+namespace System.Reflection
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AmbiguousMatchException : System.SystemException
+ {
+ public AmbiguousMatchException() { }
+ public AmbiguousMatchException(string message) { }
+ public AmbiguousMatchException(string message, System.Exception inner) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Assembly : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.ISerializable
+ {
+ protected Assembly() { }
+ public virtual string CodeBase { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.CustomAttributeData> CustomAttributes { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.TypeInfo> DefinedTypes { get { throw null; } }
+ public virtual System.Reflection.MethodInfo EntryPoint { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Type> ExportedTypes { get { throw null; } }
+ public virtual string FullName { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual string ImageRuntimeVersion { get { throw null; } }
+ public virtual bool IsDynamic { get { throw null; } }
+ public virtual string Location { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Reflection.Module ManifestModule { get { throw null; } }
+ public virtual event ModuleResolveEventHandler ModuleResolve { [System.Security.SecurityCriticalAttribute]add { } [System.Security.SecurityCriticalAttribute]remove { } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.Module> Modules { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual bool ReflectionOnly { get { throw null; } }
+ public object CreateInstance(string typeName) { throw null; }
+ public object CreateInstance(string typeName, bool ignoreCase) { throw null; }
+ public virtual object CreateInstance(String typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, System.Globalization.CultureInfo culture, Object[] activationAttributes) { throw null; }
+ public static string CreateQualifiedName(string assemblyName, string typeName) { throw null; }
+ public override bool Equals(object o) { throw null; }
+ public static Assembly GetAssembly(Type type) { throw null; }
+ public static bool operator ==(System.Reflection.Assembly left, System.Reflection.Assembly right) { throw null; }
+ public static bool operator !=(System.Reflection.Assembly left, System.Reflection.Assembly right) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Assembly GetCallingAssembly() { throw null; }
+ public virtual object[] GetCustomAttributes(bool inherit) { throw null; }
+ public virtual object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public virtual System.Collections.Generic.IList<CustomAttributeData> GetCustomAttributesData() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Assembly GetEntryAssembly() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Assembly GetExecutingAssembly() { throw null; }
+ public virtual System.Type[] GetExportedTypes() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.Reflection.Module[] GetLoadedModules() { throw null; }
+ public virtual System.Reflection.Module[] GetLoadedModules(bool getResourceModules) { throw null; }
+ public virtual System.Reflection.ManifestResourceInfo GetManifestResourceInfo(string resourceName) { throw null; }
+ public virtual string[] GetManifestResourceNames() { throw null; }
+ public virtual System.IO.Stream GetManifestResourceStream(string name) { throw null; }
+ public virtual System.IO.Stream GetManifestResourceStream(System.Type type, string name) { throw null; }
+ public virtual System.Reflection.Module GetModule(String name) { throw null; }
+ public System.Reflection.Module[] GetModules() { throw null; }
+ public virtual System.Reflection.Module[] GetModules(bool getResourceModules) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual System.Reflection.AssemblyName GetName(bool copiedName) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual System.Reflection.AssemblyName GetName() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public virtual System.Reflection.AssemblyName[] GetReferencedAssemblies() { throw null; }
+ public virtual System.Reflection.Assembly GetSatelliteAssembly(System.Globalization.CultureInfo culture) { throw null; }
+ public virtual System.Reflection.Assembly GetSatelliteAssembly(System.Globalization.CultureInfo culture, System.Version version) { throw null; }
+ public virtual System.Type GetType(string name) { throw null; }
+ public virtual System.Type GetType(string name, bool throwOnError) { throw null; }
+ public virtual System.Type GetType(string name, bool throwOnError, bool ignoreCase) { throw null; }
+ public virtual System.Type[] GetTypes() { throw null; }
+ public virtual bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public static System.Reflection.Assembly Load(byte[] rawAssembly) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public static System.Reflection.Assembly Load(byte[] rawAssembly, byte[] rawSymbolStore) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public static System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyRef) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Assembly Load(string assemblyString) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static Assembly ReflectionOnlyLoad(byte[] rawAssembly) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static Assembly ReflectionOnlyLoad(String assemblyString) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static Assembly ReflectionOnlyLoadFrom(string assemblyFile) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyAlgorithmIdAttribute : System.Attribute
+ {
+ public AssemblyAlgorithmIdAttribute(System.Configuration.Assemblies.AssemblyHashAlgorithm algorithmId) { }
+ [System.CLSCompliantAttribute(false)]
+ public AssemblyAlgorithmIdAttribute(uint algorithmId) { }
+ [System.CLSCompliantAttribute(false)]
+ public uint AlgorithmId { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyCompanyAttribute : System.Attribute
+ {
+ public AssemblyCompanyAttribute(string company) { }
+ public string Company { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyConfigurationAttribute : System.Attribute
+ {
+ public AssemblyConfigurationAttribute(string configuration) { }
+ public string Configuration { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public enum AssemblyContentType
+ {
+ Default = 0,
+ WindowsRuntime = 1,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyCopyrightAttribute : System.Attribute
+ {
+ public AssemblyCopyrightAttribute(string copyright) { }
+ public string Copyright { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyCultureAttribute : System.Attribute
+ {
+ public AssemblyCultureAttribute(string culture) { }
+ public string Culture { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyDefaultAliasAttribute : System.Attribute
+ {
+ public AssemblyDefaultAliasAttribute(string defaultAlias) { }
+ public string DefaultAlias { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyDelaySignAttribute : System.Attribute
+ {
+ public AssemblyDelaySignAttribute(bool delaySign) { }
+ public bool DelaySign { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyDescriptionAttribute : System.Attribute
+ {
+ public AssemblyDescriptionAttribute(string description) { }
+ public string Description { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyFileVersionAttribute : System.Attribute
+ {
+ public AssemblyFileVersionAttribute(string version) { }
+ public string Version { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyFlagsAttribute : System.Attribute
+ {
+ [System.CLSCompliantAttribute(false)]
+ public AssemblyFlagsAttribute(uint flags) { }
+ public AssemblyFlagsAttribute(int assemblyFlags) { }
+ public AssemblyFlagsAttribute(System.Reflection.AssemblyNameFlags assemblyFlags) { }
+ public int AssemblyFlags { get { throw null; } }
+ [System.CLSCompliantAttribute(false)]
+ public uint Flags { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyInformationalVersionAttribute : System.Attribute
+ {
+ public AssemblyInformationalVersionAttribute(string informationalVersion) { }
+ public string InformationalVersion { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyKeyFileAttribute : System.Attribute
+ {
+ public AssemblyKeyFileAttribute(string keyFile) { }
+ public string KeyFile { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyKeyNameAttribute : System.Attribute
+ {
+ public AssemblyKeyNameAttribute(string keyName) { }
+ public string KeyName { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=true, Inherited=false)]
+ public sealed partial class AssemblyMetadataAttribute : System.Attribute
+ {
+ public AssemblyMetadataAttribute(string key, string value) { }
+ public string Key { get { throw null; } }
+ public string Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyName : System.ICloneable, System.Runtime.Serialization.ISerializable, System.Runtime.Serialization.IDeserializationCallback
+ {
+ public AssemblyName() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public AssemblyName(string assemblyName) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Reflection.AssemblyContentType ContentType { get { throw null; } set { } }
+ public System.Globalization.CultureInfo CultureInfo { get { throw null; } set { } }
+ public string CultureName { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ public string CodeBase { get { throw null; } set { } }
+ public System.Reflection.AssemblyNameFlags Flags { get { throw null; } set { } }
+ public string FullName { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public System.Configuration.Assemblies.AssemblyHashAlgorithm HashAlgorithm { get { throw null; } set { } }
+ public System.Configuration.Assemblies.AssemblyVersionCompatibility VersionCompatibility { get { throw null; } set { } }
+ public string Name { get { throw null; } set { } }
+ public System.Reflection.ProcessorArchitecture ProcessorArchitecture { get { throw null; } set { } }
+ public System.Version Version { get { throw null; } set { } }
+ public object Clone() { throw null; }
+ public byte[] GetPublicKey() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public byte[] GetPublicKeyToken() { throw null; }
+ public void SetPublicKey(byte[] publicKey) { }
+ public void SetPublicKeyToken(byte[] publicKeyToken) { }
+ public override string ToString() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { throw null; }
+ public void OnDeserialization(Object sender) { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum AssemblyNameFlags
+ {
+ EnableJITcompileOptimizer = 16384,
+ EnableJITcompileTracking = 32768,
+ None = 0,
+ PublicKey = 1,
+ Retargetable = 256,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyProductAttribute : System.Attribute
+ {
+ public AssemblyProductAttribute(string product) { }
+ public string Product { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false, AllowMultiple=false)]
+ public sealed partial class AssemblySignatureKeyAttribute : System.Attribute
+ {
+ public AssemblySignatureKeyAttribute(string publicKey, string countersignature) { }
+ public string Countersignature { get { throw null; } }
+ public string PublicKey { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyTitleAttribute : System.Attribute
+ {
+ public AssemblyTitleAttribute(string title) { }
+ public string Title { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyTrademarkAttribute : System.Attribute
+ {
+ public AssemblyTrademarkAttribute(string trademark) { }
+ public string Trademark { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyVersionAttribute : System.Attribute
+ {
+ public AssemblyVersionAttribute(string version) { }
+ public string Version { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(2))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Binder
+ {
+ protected Binder() { }
+ public abstract System.Reflection.FieldInfo BindToField(System.Reflection.BindingFlags bindingAttr, System.Reflection.FieldInfo[] match, object value, System.Globalization.CultureInfo culture);
+ public abstract System.Reflection.MethodBase BindToMethod(System.Reflection.BindingFlags bindingAttr, System.Reflection.MethodBase[] match, ref object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] names, out object state);
+ public abstract object ChangeType(object value, System.Type type, System.Globalization.CultureInfo culture);
+ public abstract void ReorderArgumentArray(ref object[] args, object state);
+ public abstract System.Reflection.MethodBase SelectMethod(System.Reflection.BindingFlags bindingAttr, System.Reflection.MethodBase[] match, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ public abstract System.Reflection.PropertyInfo SelectProperty(System.Reflection.BindingFlags bindingAttr, System.Reflection.PropertyInfo[] match, System.Type returnType, System.Type[] indexes, System.Reflection.ParameterModifier[] modifiers);
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum BindingFlags
+ {
+ CreateInstance = 512,
+ DeclaredOnly = 2,
+ Default = 0,
+ ExactBinding = 65536,
+ FlattenHierarchy = 64,
+ GetField = 1024,
+ GetProperty = 4096,
+ IgnoreCase = 1,
+ IgnoreReturn = 16777216,
+ Instance = 4,
+ InvokeMethod = 256,
+ NonPublic = 32,
+ OptionalParamBinding = 262144,
+ Public = 16,
+ PutDispProperty = 16384,
+ PutRefDispProperty = 32768,
+ SetField = 2048,
+ SetProperty = 8192,
+ Static = 8,
+ SuppressChangeType = 131072,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CallingConventions
+ {
+ Any = 3,
+ ExplicitThis = 64,
+ HasThis = 32,
+ Standard = 1,
+ VarArgs = 2,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class ConstructorInfo : System.Reflection.MethodBase
+ {
+ public static bool operator ==(System.Reflection.ConstructorInfo left, System.Reflection.ConstructorInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.ConstructorInfo left, System.Reflection.ConstructorInfo right) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static readonly string ConstructorName;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static readonly string TypeConstructorName;
+ protected ConstructorInfo() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public object Invoke(object[] parameters) { throw null; }
+ public abstract object Invoke(System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CustomAttributeData
+ {
+ protected CustomAttributeData() { }
+ public System.Type AttributeType { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Reflection.ConstructorInfo Constructor { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Collections.Generic.IList<System.Reflection.CustomAttributeTypedArgument> ConstructorArguments { get { throw null; } }
+ public virtual System.Collections.Generic.IList<System.Reflection.CustomAttributeNamedArgument> NamedArguments { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public static System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributes(System.Reflection.Assembly target) { throw null; }
+ public static System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributes(System.Reflection.MemberInfo target) { throw null; }
+ public static System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributes(System.Reflection.Module target) { throw null; }
+ public static System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributes(System.Reflection.ParameterInfo target) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public static partial class CustomAttributeExtensions
+ {
+ public static System.Attribute GetCustomAttribute(this System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(this System.Reflection.MemberInfo element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(this System.Reflection.MemberInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Attribute GetCustomAttribute(this System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(this System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static System.Attribute GetCustomAttribute(this System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.Assembly element) where T : System.Attribute { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.MemberInfo element) where T : System.Attribute { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.MemberInfo element, bool inherit) where T : System.Attribute { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.Module element) where T : System.Attribute { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.ParameterInfo element) where T : System.Attribute { throw null; }
+ public static T GetCustomAttribute<T>(this System.Reflection.ParameterInfo element, bool inherit) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.Assembly element) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.MemberInfo element) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.MemberInfo element, bool inherit) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.MemberInfo element, System.Type attributeType) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.MemberInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.Module element) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.ParameterInfo element) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.ParameterInfo element, bool inherit) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Attribute> GetCustomAttributes(this System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.Assembly element) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.MemberInfo element) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.MemberInfo element, bool inherit) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.Module element) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.ParameterInfo element) where T : System.Attribute { throw null; }
+ public static System.Collections.Generic.IEnumerable<T> GetCustomAttributes<T>(this System.Reflection.ParameterInfo element, bool inherit) where T : System.Attribute { throw null; }
+ public static bool IsDefined(this System.Reflection.Assembly element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(this System.Reflection.MemberInfo element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(this System.Reflection.MemberInfo element, System.Type attributeType, bool inherit) { throw null; }
+ public static bool IsDefined(this System.Reflection.Module element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(this System.Reflection.ParameterInfo element, System.Type attributeType) { throw null; }
+ public static bool IsDefined(this System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CustomAttributeFormatException : System.FormatException
+ {
+ public CustomAttributeFormatException() { }
+ public CustomAttributeFormatException(string message) { }
+ public CustomAttributeFormatException(string message, System.Exception inner) { }
+ protected CustomAttributeFormatException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct CustomAttributeNamedArgument
+ {
+ public CustomAttributeNamedArgument(System.Reflection.MemberInfo memberInfo, object value) { }
+ public CustomAttributeNamedArgument(System.Reflection.MemberInfo memberInfo, System.Reflection.CustomAttributeTypedArgument typedArgument) { }
+ public bool IsField { get { throw null; } }
+ public System.Reflection.MemberInfo MemberInfo { get { throw null; } }
+ public string MemberName { get { throw null; } }
+ public System.Reflection.CustomAttributeTypedArgument TypedValue { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; }
+ public static bool operator !=(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct CustomAttributeTypedArgument
+ {
+ public CustomAttributeTypedArgument(System.Type argumentType, object value) { }
+ public CustomAttributeTypedArgument(object value) { }
+ public System.Type ArgumentType { get { throw null; } }
+ public object Value { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; }
+ public static bool operator !=(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1036))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DefaultMemberAttribute : System.Attribute
+ {
+ public DefaultMemberAttribute(string memberName) { }
+ public string MemberName { get { throw null; } }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum EventAttributes
+ {
+ None = 0,
+ ReservedMask = 1024,
+ RTSpecialName = 1024,
+ SpecialName = 512,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class EventInfo : System.Reflection.MemberInfo
+ {
+ protected EventInfo() { }
+ public static bool operator ==(System.Reflection.EventInfo left, System.Reflection.EventInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.EventInfo left, System.Reflection.EventInfo right) { throw null; }
+ public virtual System.Reflection.MethodInfo AddMethod { get { throw null; } }
+ public abstract System.Reflection.EventAttributes Attributes { get; }
+ public virtual System.Type EventHandlerType { get { throw null; } }
+ public virtual bool IsMulticast { get { throw null; } }
+ public bool IsSpecialName { get { throw null; } }
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public virtual System.Reflection.MethodInfo RaiseMethod { get { throw null; } }
+ public virtual System.Reflection.MethodInfo RemoveMethod { get { throw null; } }
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public virtual void AddEventHandler(object target, System.Delegate handler) { }
+ public override bool Equals(object obj) { throw null; }
+ public System.Reflection.MethodInfo GetAddMethod() { throw null; }
+ public abstract System.Reflection.MethodInfo GetAddMethod(bool nonPublic);
+ public override int GetHashCode() { throw null; }
+ public System.Reflection.MethodInfo[] GetOtherMethods() { throw null; }
+ public virtual System.Reflection.MethodInfo[] GetOtherMethods(bool nonPublic) { throw null; }
+ public System.Reflection.MethodInfo GetRaiseMethod() { throw null; }
+ public abstract System.Reflection.MethodInfo GetRaiseMethod(bool nonPublic);
+ public System.Reflection.MethodInfo GetRemoveMethod() { throw null; }
+ public abstract System.Reflection.MethodInfo GetRemoveMethod(bool nonPublic);
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public virtual void RemoveEventHandler(object target, System.Delegate handler) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public class ExceptionHandlingClause
+ {
+ protected ExceptionHandlingClause() { }
+ public virtual System.Reflection.ExceptionHandlingClauseOptions Flags { get { throw null; } }
+ public virtual int TryOffset { get { throw null; } }
+ public virtual int TryLength { get { throw null; } }
+ public virtual int HandlerOffset { get { throw null; } }
+ public virtual int HandlerLength { get { throw null; } }
+ public virtual int FilterOffset { get { throw null; } }
+ public virtual System.Type CatchType { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ExceptionHandlingClauseOptions: int
+ {
+ Clause = 0,
+ Filter = 1,
+ Finally = 2,
+ Fault = 4,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum FieldAttributes
+ {
+ Assembly = 3,
+ FamANDAssem = 2,
+ Family = 4,
+ FamORAssem = 5,
+ FieldAccessMask = 7,
+ HasDefault = 32768,
+ HasFieldMarshal = 4096,
+ HasFieldRVA = 256,
+ InitOnly = 32,
+ Literal = 64,
+ NotSerialized = 128,
+ PinvokeImpl = 8192,
+ Private = 1,
+ PrivateScope = 0,
+ Public = 6,
+ ReservedMask = 38144,
+ RTSpecialName = 1024,
+ SpecialName = 512,
+ Static = 16,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class FieldInfo : System.Reflection.MemberInfo
+ {
+ protected FieldInfo() { }
+ public static bool operator ==(System.Reflection.FieldInfo left, System.Reflection.FieldInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.FieldInfo left, System.Reflection.FieldInfo right) { throw null; }
+ public abstract System.Reflection.FieldAttributes Attributes { get; }
+ public abstract System.RuntimeFieldHandle FieldHandle { get; }
+ public abstract System.Type FieldType { get; }
+ public bool IsAssembly { get { throw null; } }
+ public bool IsFamily { get { throw null; } }
+ public bool IsFamilyAndAssembly { get { throw null; } }
+ public bool IsFamilyOrAssembly { get { throw null; } }
+ public bool IsInitOnly { get { throw null; } }
+ public bool IsLiteral { get { throw null; } }
+ public bool IsNotSerialized { get { throw null; } }
+ public bool IsPinvokeImpl { get { throw null; } }
+ public bool IsPrivate { get { throw null; } }
+ public bool IsPublic { get { throw null; } }
+ public virtual bool IsSecurityCritical { get { throw null; } }
+ public virtual bool IsSecuritySafeCritical { get { throw null; } }
+ public virtual bool IsSecurityTransparent { get { throw null; } }
+ public bool IsSpecialName { get { throw null; } }
+ public bool IsStatic { get { throw null; } }
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public static System.Reflection.FieldInfo GetFieldFromHandle(System.RuntimeFieldHandle handle) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.Reflection.FieldInfo GetFieldFromHandle(System.RuntimeFieldHandle handle, System.RuntimeTypeHandle declaringType) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public virtual System.Type[] GetOptionalCustomModifiers() { throw null; }
+ public virtual object GetRawConstantValue() { throw null; }
+ public virtual System.Type[] GetRequiredCustomModifiers() { throw null; }
+ public abstract object GetValue(object obj);
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public void SetValue(object obj, object value) { }
+ public abstract void SetValue(object obj, object value, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture);
+ }
+ [System.FlagsAttribute]
+ public enum GenericParameterAttributes
+ {
+ Contravariant = 2,
+ Covariant = 1,
+ DefaultConstructorConstraint = 16,
+ None = 0,
+ NotNullableValueTypeConstraint = 8,
+ ReferenceTypeConstraint = 4,
+ SpecialConstraintMask = 28,
+ VarianceMask = 3,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ICustomAttributeProvider
+ {
+ object[] GetCustomAttributes(bool inherit);
+ object[] GetCustomAttributes(System.Type attributeType, bool inherit);
+ bool IsDefined(System.Type attributeType, bool inherit);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ImageFileMachine
+ {
+ I386 = 332,
+ IA64 = 512,
+ AMD64 = 34404,
+ ARM = 452,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct InterfaceMapping
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.MethodInfo[] InterfaceMethods;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Type InterfaceType;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.MethodInfo[] TargetMethods;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Type TargetType;
+ }
+ public static partial class IntrospectionExtensions
+ {
+ public static System.Reflection.TypeInfo GetTypeInfo(this System.Type type) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class InvalidFilterCriteriaException : System.Exception
+ {
+ public InvalidFilterCriteriaException() { }
+ public InvalidFilterCriteriaException(string message) { }
+ public InvalidFilterCriteriaException(string message, System.Exception inner) { }
+ protected InvalidFilterCriteriaException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.GuidAttribute("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")]
+ public partial interface IReflect
+ {
+ System.Type UnderlyingSystemType { get; }
+ System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.PropertyInfo GetProperty(string name, System.Reflection.BindingFlags bindingAttr);
+ System.Reflection.PropertyInfo GetProperty(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers);
+ object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters);
+ }
+ public partial interface IReflectableType
+ {
+ System.Reflection.TypeInfo GetTypeInfo();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class LocalVariableInfo
+ {
+ protected LocalVariableInfo() { }
+ public virtual bool IsPinned { get { throw null; } }
+ public virtual int LocalIndex { get { throw null; } }
+ public virtual System.Type LocalType { get { throw null; } }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ManifestResourceInfo
+ {
+ public ManifestResourceInfo(System.Reflection.Assembly containingAssembly, string containingFileName, System.Reflection.ResourceLocation resourceLocation) { }
+ public virtual string FileName { get { throw null; } }
+ public virtual System.Reflection.Assembly ReferencedAssembly { get { throw null; } }
+ public virtual System.Reflection.ResourceLocation ResourceLocation { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate bool MemberFilter(System.Reflection.MemberInfo m, object filterCriteria);
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class MemberInfo : System.Reflection.ICustomAttributeProvider
+ {
+ protected MemberInfo() { }
+ public static bool operator ==(System.Reflection.MemberInfo left, System.Reflection.MemberInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.MemberInfo left, System.Reflection.MemberInfo right) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.CustomAttributeData> CustomAttributes { get { throw null; } }
+ public abstract System.Type DeclaringType { get; }
+ public abstract System.Reflection.MemberTypes MemberType { get; }
+ public virtual int MetadataToken { get { throw null; } }
+ public virtual System.Reflection.Module Module { get { throw null; } }
+ public abstract string Name { get; }
+ public abstract System.Type ReflectedType { get; }
+ public override bool Equals(object obj) { throw null; }
+ public abstract object[] GetCustomAttributes(bool inherit);
+ public abstract object[] GetCustomAttributes(System.Type attributeType, bool inherit);
+ public virtual System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributesData() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public abstract bool IsDefined(System.Type attributeType, bool inherit);
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MemberTypes
+ {
+ All = 191,
+ Constructor = 1,
+ Custom = 64,
+ Event = 2,
+ Field = 4,
+ Method = 8,
+ NestedType = 128,
+ Property = 16,
+ TypeInfo = 32,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MethodAttributes
+ {
+ Abstract = 1024,
+ Assembly = 3,
+ CheckAccessOnOverride = 512,
+ FamANDAssem = 2,
+ Family = 4,
+ FamORAssem = 5,
+ Final = 32,
+ HasSecurity = 16384,
+ HideBySig = 128,
+ MemberAccessMask = 7,
+ NewSlot = 256,
+ PinvokeImpl = 8192,
+ Private = 1,
+ PrivateScope = 0,
+ Public = 6,
+ RequireSecObject = 32768,
+ ReservedMask = 53248,
+ ReuseSlot = 0,
+ RTSpecialName = 4096,
+ SpecialName = 2048,
+ Static = 16,
+ UnmanagedExport = 8,
+ Virtual = 64,
+ VtableLayoutMask = 256,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class MethodBase : System.Reflection.MemberInfo
+ {
+ protected MethodBase() { }
+ public abstract System.Reflection.MethodAttributes Attributes { get; }
+ public virtual System.Reflection.CallingConventions CallingConvention { get { throw null; } }
+ public virtual bool ContainsGenericParameters { get { throw null; } }
+ public bool IsAbstract { get { throw null; } }
+ public bool IsAssembly { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public bool IsConstructor { get { throw null; } }
+ public bool IsFamily { get { throw null; } }
+ public bool IsFamilyAndAssembly { get { throw null; } }
+ public bool IsFamilyOrAssembly { get { throw null; } }
+ public bool IsFinal { get { throw null; } }
+ public virtual bool IsGenericMethod { get { throw null; } }
+ public virtual bool IsGenericMethodDefinition { get { throw null; } }
+ public bool IsHideBySig { get { throw null; } }
+ public bool IsPrivate { get { throw null; } }
+ public bool IsPublic { get { throw null; } }
+ public bool IsSpecialName { get { throw null; } }
+ public bool IsStatic { get { throw null; } }
+ public bool IsVirtual { get { throw null; } }
+ public abstract System.RuntimeMethodHandle MethodHandle { get; }
+ public virtual System.Reflection.MethodImplAttributes MethodImplementationFlags { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public static bool operator ==(System.Reflection.MethodBase left, System.Reflection.MethodBase right) { throw null; }
+ public static bool operator !=(System.Reflection.MethodBase left, System.Reflection.MethodBase right) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ public static System.Reflection.MethodBase GetCurrentMethod() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Type[] GetGenericArguments() { throw null; }
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual System.Reflection.MethodBody GetMethodBody() { throw null; }
+ public static System.Reflection.MethodBase GetMethodFromHandle(System.RuntimeMethodHandle handle) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static System.Reflection.MethodBase GetMethodFromHandle(System.RuntimeMethodHandle handle, System.RuntimeTypeHandle declaringType) { throw null; }
+ public abstract System.Reflection.MethodImplAttributes GetMethodImplementationFlags();
+ public abstract System.Reflection.ParameterInfo[] GetParameters();
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public object Invoke(object obj, object[] parameters) { throw null; }
+ public abstract object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public class MethodBody
+ {
+ protected MethodBody() { }
+ public virtual int LocalSignatureMetadataToken { get { throw null; } }
+ public virtual System.Collections.Generic.IList<LocalVariableInfo> LocalVariables { get { throw null; } }
+ public virtual int MaxStackSize { get { throw null; } }
+ public virtual bool InitLocals { get { throw null; } }
+ public virtual byte[] GetILAsByteArray() { throw null; }
+ public virtual System.Collections.Generic.IList<ExceptionHandlingClause> ExceptionHandlingClauses { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MethodImplAttributes
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ AggressiveInlining = 256,
+ CodeTypeMask = 3,
+ ForwardRef = 16,
+ IL = 0,
+ InternalCall = 4096,
+ Managed = 0,
+ ManagedMask = 4,
+ MaxMethodImplVal = 65535,
+ Native = 1,
+ NoInlining = 8,
+ NoOptimization = 64,
+ OPTIL = 2,
+ PreserveSig = 128,
+ Runtime = 3,
+ Synchronized = 32,
+ Unmanaged = 4,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class MethodInfo : System.Reflection.MethodBase
+ {
+ protected MethodInfo() { }
+ public static bool operator ==(System.Reflection.MethodInfo left, System.Reflection.MethodInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.MethodInfo left, System.Reflection.MethodInfo right) { throw null; }
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public virtual System.Reflection.ParameterInfo ReturnParameter { get { throw null; } }
+ public virtual System.Type ReturnType { get { throw null; } }
+ public abstract System.Reflection.ICustomAttributeProvider ReturnTypeCustomAttributes { get; }
+ public virtual System.Delegate CreateDelegate(System.Type delegateType) { throw null; }
+ public virtual System.Delegate CreateDelegate(System.Type delegateType, object target) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public abstract System.Reflection.MethodInfo GetBaseDefinition();
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Type[] GetGenericArguments() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Reflection.MethodInfo GetGenericMethodDefinition() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public virtual System.Reflection.MethodInfo MakeGenericMethod(params System.Type[] typeArguments) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Missing : System.Runtime.Serialization.ISerializable
+ {
+ internal Missing() { }
+ public static readonly System.Reflection.Missing Value;
+ [System.Security.SecurityCriticalAttribute]
+ void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Module : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.ISerializable
+ {
+ public static readonly System.Reflection.TypeFilter FilterTypeName;
+ public static readonly System.Reflection.TypeFilter FilterTypeNameIgnoreCase;
+ protected Module() { }
+ public static bool operator ==(System.Reflection.Module left, System.Reflection.Module right) { throw null; }
+ public static bool operator !=(System.Reflection.Module left, System.Reflection.Module right) { throw null; }
+ public virtual System.Reflection.Assembly Assembly { get { throw null; } }
+ public System.ModuleHandle ModuleHandle { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.CustomAttributeData> CustomAttributes { get { throw null; } }
+ public virtual string FullyQualifiedName { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public virtual int MDStreamVersion { get { throw null; } }
+ public virtual int MetadataToken { get { throw null; } }
+ public virtual System.Guid ModuleVersionId { get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ public virtual string ScopeName { get { throw null; } }
+ public override bool Equals(object o) { throw null; }
+ public virtual System.Type[] FindTypes(System.Reflection.TypeFilter filter, object filterCriteria) { throw null; }
+ public virtual object[] GetCustomAttributes(bool inherit) { throw null; }
+ public virtual object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public System.Reflection.FieldInfo GetField(string name) { throw null; }
+ public virtual System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public System.Reflection.FieldInfo[] GetFields() { throw null; }
+ public virtual System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingFlags) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.MethodInfo GetMethod(string name, System.Type[] types) { throw null; }
+ protected virtual System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public System.Reflection.MethodInfo[] GetMethods() { throw null; }
+ public virtual System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingFlags) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public virtual void GetPEKind(out System.Reflection.PortableExecutableKinds peKind, out System.Reflection.ImageFileMachine machine) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Type GetType(string className) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Type GetType(string className, bool ignoreCase) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public virtual System.Type GetType(string className, bool throwOnError, bool ignoreCase) { throw null; }
+ public virtual System.Type[] GetTypes() { throw null; }
+ public virtual bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ public virtual bool IsResource() { throw null; }
+ public virtual System.Collections.Generic.IList<CustomAttributeData> GetCustomAttributesData() { throw null; }
+ public System.Reflection.FieldInfo ResolveField(int metadataToken) { throw null; }
+ public virtual System.Reflection.FieldInfo ResolveField(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public System.Reflection.MemberInfo ResolveMember(int metadataToken) { throw null; }
+ public virtual System.Reflection.MemberInfo ResolveMember(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public System.Reflection.MethodBase ResolveMethod(int metadataToken) { throw null; }
+ public virtual System.Reflection.MethodBase ResolveMethod(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public virtual byte[] ResolveSignature(int metadataToken) { throw null; }
+ public virtual string ResolveString(int metadataToken) { throw null; }
+ public System.Type ResolveType(int metadataToken) { throw null; }
+ public virtual System.Type ResolveType(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed class ObfuscateAssemblyAttribute : System.Attribute
+ {
+ public ObfuscateAssemblyAttribute(bool assemblyIsPrivate) { throw null; }
+ public bool AssemblyIsPrivate { get { throw null; } }
+ public bool StripAfterObfuscation { get { throw null; } set { } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1) | (System.AttributeTargets)(4) | (System.AttributeTargets)(8) | (System.AttributeTargets)(64) | (System.AttributeTargets)(2048) | (System.AttributeTargets)(256) | (System.AttributeTargets)(128) | (System.AttributeTargets)(512) | (System.AttributeTargets)(1024) | (System.AttributeTargets)(16) | (System.AttributeTargets)(4096),
+ AllowMultiple = true, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed class ObfuscationAttribute: System.Attribute
+ {
+ public ObfuscationAttribute() { }
+ public bool StripAfterObfuscation { get { throw null; } set { } }
+ public bool Exclude { get { throw null; } set { } }
+ public bool ApplyToMembers { get { throw null; } set { } }
+ public string Feature { get { throw null; } set { } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate System.Reflection.Module ModuleResolveEventHandler(object sender, System.ResolveEventArgs e);
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ParameterAttributes
+ {
+ HasDefault = 4096,
+ HasFieldMarshal = 8192,
+ In = 1,
+ Lcid = 4,
+ None = 0,
+ Optional = 16,
+ Out = 2,
+ Reserved3 = 16384,
+ Reserved4 = 32768,
+ ReservedMask = 61440,
+ Retval = 8,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ParameterInfo : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.IObjectReference
+ {
+ protected String NameImpl;
+ protected Type ClassImpl;
+ protected int PositionImpl;
+ protected System.Reflection.ParameterAttributes AttrsImpl;
+ protected Object DefaultValueImpl;
+ protected MemberInfo MemberImpl;
+ protected ParameterInfo() { }
+ public virtual System.Reflection.ParameterAttributes Attributes { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.CustomAttributeData> CustomAttributes { get { throw null; } }
+ public virtual object DefaultValue { get { throw null; } }
+ public virtual bool HasDefaultValue { get { throw null; } }
+ public bool IsIn { get { throw null; } }
+ public bool IsLcid { get { throw null; } }
+ public bool IsOptional { get { throw null; } }
+ public bool IsOut { get { throw null; } }
+ public bool IsRetval { get { throw null; } }
+ public virtual System.Reflection.MemberInfo Member { get { throw null; } }
+ public virtual int MetadataToken { get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ public virtual System.Type ParameterType { get { throw null; } }
+ public virtual int Position { get { throw null; } }
+ public virtual object RawDefaultValue { get { throw null; } }
+ public virtual object[] GetCustomAttributes(bool inherit) { throw null; }
+ public virtual object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public virtual System.Collections.Generic.IList<System.Reflection.CustomAttributeData> GetCustomAttributesData() { throw null; }
+ public virtual System.Type[] GetOptionalCustomModifiers() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public object GetRealObject(System.Runtime.Serialization.StreamingContext context) { throw null; }
+ public virtual System.Type[] GetRequiredCustomModifiers() { throw null; }
+ public virtual bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ParameterModifier
+ {
+ public ParameterModifier(int parameterCount) { throw null;}
+ public bool this[int index] { get { throw null; } set { } }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed class Pointer : System.Runtime.Serialization.ISerializable
+ {
+ private Pointer() { }
+ [System.Security.SecurityCriticalAttribute]
+ public static unsafe Object Box(void *ptr, System.Type type) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static unsafe void* Unbox(object ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ unsafe void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum PortableExecutableKinds
+ {
+ NotAPortableExecutableImage = 0,
+ ILOnly = 1,
+ Required32Bit = 2,
+ PE32Plus = 4,
+ Unmanaged32Bit = 8,
+ [System.Runtime.InteropServices.ComVisible(false)]
+ Preferred32Bit = 16,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ProcessorArchitecture
+ {
+ Amd64 = 4,
+ Arm = 5,
+ IA64 = 3,
+ MSIL = 1,
+ None = 0,
+ X86 = 2,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum PropertyAttributes
+ {
+ HasDefault = 4096,
+ None = 0,
+ Reserved2 = 8192,
+ Reserved3 = 16384,
+ Reserved4 = 32768,
+ ReservedMask = 62464,
+ RTSpecialName = 1024,
+ SpecialName = 512,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class PropertyInfo : System.Reflection.MemberInfo
+ {
+ protected PropertyInfo() { }
+ public static bool operator ==(System.Reflection.PropertyInfo left, System.Reflection.PropertyInfo right) { throw null; }
+ public static bool operator !=(System.Reflection.PropertyInfo left, System.Reflection.PropertyInfo right) { throw null; }
+ public abstract System.Reflection.PropertyAttributes Attributes { get; }
+ public abstract bool CanRead { get; }
+ public abstract bool CanWrite { get; }
+ public virtual System.Reflection.MethodInfo GetMethod { get { throw null; } }
+ public bool IsSpecialName { get { throw null; } }
+ public override System.Reflection.MemberTypes MemberType { get { throw null; } }
+ public abstract System.Type PropertyType { get; }
+ public virtual System.Reflection.MethodInfo SetMethod { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public System.Reflection.MethodInfo[] GetAccessors() { throw null; }
+ public abstract System.Reflection.MethodInfo[] GetAccessors(bool nonPublic);
+ public virtual object GetConstantValue() { throw null; }
+ public System.Reflection.MethodInfo GetGetMethod() { throw null; }
+ public abstract System.Reflection.MethodInfo GetGetMethod(bool nonPublic);
+ public override int GetHashCode() { throw null; }
+ public abstract System.Reflection.ParameterInfo[] GetIndexParameters();
+ public virtual System.Type[] GetOptionalCustomModifiers() { throw null; }
+ public virtual object GetRawConstantValue() { throw null; }
+ public virtual System.Type[] GetRequiredCustomModifiers() { throw null; }
+ public System.Reflection.MethodInfo GetSetMethod() { throw null; }
+ public abstract System.Reflection.MethodInfo GetSetMethod(bool nonPublic);
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public object GetValue(object obj) { throw null; }
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public virtual object GetValue(object obj, object[] index) { throw null; }
+ public abstract object GetValue(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] index, System.Globalization.CultureInfo culture);
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public void SetValue(object obj, object value) { }
+ [System.Diagnostics.DebuggerHiddenAttribute]
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ public virtual void SetValue(object obj, object value, object[] index) { }
+ public abstract void SetValue(object obj, object value, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] index, System.Globalization.CultureInfo culture);
+ }
+ public abstract partial class ReflectionContext
+ {
+ protected ReflectionContext() { }
+ public virtual System.Reflection.TypeInfo GetTypeForObject(object value) { throw null; }
+ public abstract System.Reflection.Assembly MapAssembly(System.Reflection.Assembly assembly);
+ public abstract System.Reflection.TypeInfo MapType(System.Reflection.TypeInfo type);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ReflectionTypeLoadException : System.SystemException, System.Runtime.Serialization.ISerializable
+ {
+ public ReflectionTypeLoadException(System.Type[] classes, System.Exception[] exceptions) { }
+ public ReflectionTypeLoadException(System.Type[] classes, System.Exception[] exceptions, string message) { }
+ public System.Exception[] LoaderExceptions { get { throw null; } }
+ public System.Type[] Types { get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ResourceAttributes
+ {
+ Private = 2,
+ Public = 1,
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ResourceLocation
+ {
+ ContainedInAnotherAssembly = 2,
+ ContainedInManifestFile = 4,
+ Embedded = 1,
+ }
+ public static partial class RuntimeReflectionExtensions
+ {
+ public static System.Reflection.MethodInfo GetMethodInfo(this System.Delegate del) { throw null; }
+ public static System.Reflection.MethodInfo GetRuntimeBaseDefinition(this System.Reflection.MethodInfo method) { throw null; }
+ public static System.Reflection.EventInfo GetRuntimeEvent(this System.Type type, string name) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Reflection.EventInfo> GetRuntimeEvents(this System.Type type) { throw null; }
+ public static System.Reflection.FieldInfo GetRuntimeField(this System.Type type, string name) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Reflection.FieldInfo> GetRuntimeFields(this System.Type type) { throw null; }
+ public static System.Reflection.InterfaceMapping GetRuntimeInterfaceMap(this System.Reflection.TypeInfo typeInfo, System.Type interfaceType) { throw null; }
+ public static System.Reflection.MethodInfo GetRuntimeMethod(this System.Type type, string name, System.Type[] parameters) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo> GetRuntimeMethods(this System.Type type) { throw null; }
+ public static System.Collections.Generic.IEnumerable<System.Reflection.PropertyInfo> GetRuntimeProperties(this System.Type type) { throw null; }
+ public static System.Reflection.PropertyInfo GetRuntimeProperty(this System.Type type, string name) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class TargetException : System.Exception
+ {
+ public TargetException() { }
+ public TargetException(string message) { }
+ public TargetException(string message, System.Exception inner) { }
+ protected TargetException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class TargetInvocationException : System.Exception
+ {
+ public TargetInvocationException(System.Exception inner) { }
+ public TargetInvocationException(string message, System.Exception inner) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class TargetParameterCountException : System.Exception
+ {
+ public TargetParameterCountException() { }
+ public TargetParameterCountException(string message) { }
+ public TargetParameterCountException(string message, System.Exception inner) { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum TypeAttributes
+ {
+ Abstract = 128,
+ AnsiClass = 0,
+ AutoClass = 131072,
+ AutoLayout = 0,
+ BeforeFieldInit = 1048576,
+ Class = 0,
+ ClassSemanticsMask = 32,
+ CustomFormatClass = 196608,
+ CustomFormatMask = 12582912,
+ ExplicitLayout = 16,
+ HasSecurity = 262144,
+ Import = 4096,
+ Interface = 32,
+ LayoutMask = 24,
+ NestedAssembly = 5,
+ NestedFamANDAssem = 6,
+ NestedFamily = 4,
+ NestedFamORAssem = 7,
+ NestedPrivate = 3,
+ NestedPublic = 2,
+ NotPublic = 0,
+ Public = 1,
+ ReservedMask = 264192,
+ RTSpecialName = 2048,
+ Sealed = 256,
+ SequentialLayout = 8,
+ Serializable = 8192,
+ SpecialName = 1024,
+ StringFormatMask = 196608,
+ UnicodeClass = 65536,
+ VisibilityMask = 7,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ WindowsRuntime = 16384,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public class TypeDelegator : System.Reflection.TypeInfo
+ {
+ protected System.Type typeImpl;
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected TypeDelegator() { }
+ public TypeDelegator(System.Type delegatingType) { }
+ public override System.Guid GUID { get { throw null; } }
+ public override int MetadataToken { get { throw null; } }
+ public override object InvokeMember(System.String name,System.Reflection.BindingFlags invokeAttr,System.Reflection.Binder binder,System.Object target, System.Object[] args,System.Reflection.ParameterModifier[] modifiers,System.Globalization.CultureInfo culture,System.String[] namedParameters) { throw null; }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override System.Reflection.Assembly Assembly { get { throw null; } }
+ public override System.RuntimeTypeHandle TypeHandle { get { throw null; } }
+ public override System.String Name { get { throw null; } }
+ public override System.String FullName { get { throw null; } }
+ public override System.String Namespace { get { throw null; } }
+ public override System.String AssemblyQualifiedName { get { throw null; } }
+ public override System.Type BaseType { get { throw null; } }
+ protected override System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr,System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.MethodInfo GetMethodImpl(System.String name,System.Reflection.BindingFlags bindingAttr,System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types,System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo GetField(System.String name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetInterface(System.String name, bool ignoreCase) { throw null; }
+ public override System.Type[] GetInterfaces() { throw null; }
+ public override System.Reflection.EventInfo GetEvent(System.String name,System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents() { throw null; }
+ protected override System.Reflection.PropertyInfo GetPropertyImpl(System.String name,System.Reflection.BindingFlags bindingAttr,System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetNestedType(System.String name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.MemberInfo[] GetMember(System.String name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override TypeAttributes GetAttributeFlagsImpl() { throw null; }
+ protected override bool IsArrayImpl() { throw null; }
+ protected override bool IsPrimitiveImpl() { throw null; }
+ protected override bool IsByRefImpl() { throw null; }
+ protected override bool IsPointerImpl() { throw null; }
+ protected override bool IsValueTypeImpl() { throw null; }
+ protected override bool IsCOMObjectImpl() { throw null; }
+ public override bool IsConstructedGenericType { get { throw null; } }
+ public override System.Type GetElementType() { throw null; }
+ protected override bool HasElementTypeImpl() { throw null; }
+ public override System.Type UnderlyingSystemType { get { throw null; } }
+ public override System.Object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override System.Object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate bool TypeFilter(System.Type m, object filterCriteria);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class TypeInfo : System.Type, System.Reflection.IReflectableType
+ {
+ internal TypeInfo() { }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.ConstructorInfo> DeclaredConstructors { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.EventInfo> DeclaredEvents { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.FieldInfo> DeclaredFields { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.MemberInfo> DeclaredMembers { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo> DeclaredMethods { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.TypeInfo> DeclaredNestedTypes { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.PropertyInfo> DeclaredProperties { get { throw null; } }
+ public virtual System.Type[] GenericTypeParameters { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Type> ImplementedInterfaces { get { throw null; } }
+ public virtual System.Type AsType() { throw null; }
+ public virtual System.Reflection.EventInfo GetDeclaredEvent(string name) { throw null; }
+ public virtual System.Reflection.FieldInfo GetDeclaredField(string name) { throw null; }
+ public virtual System.Reflection.MethodInfo GetDeclaredMethod(string name) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Reflection.MethodInfo> GetDeclaredMethods(string name) { throw null; }
+ public virtual System.Reflection.TypeInfo GetDeclaredNestedType(string name) { throw null; }
+ public virtual System.Reflection.PropertyInfo GetDeclaredProperty(string name) { throw null; }
+ public virtual bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; }
+ System.Reflection.TypeInfo System.Reflection.IReflectableType.GetTypeInfo() { throw null; }
+ }
+}
+namespace System.Reflection.Emit
+{
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AssemblyBuilder : System.Reflection.Assembly
+ {
+ internal AssemblyBuilder() { }
+ public override string CodeBase { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public override System.Reflection.MethodInfo EntryPoint { get { throw null; } }
+ public override string FullName { get { throw null; } }
+ public override string ImageRuntimeVersion { get { throw null; } }
+ public override bool IsDynamic { get { throw null; } }
+ public override string Location { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public override System.Reflection.Module ManifestModule { get { throw null; } }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.AssemblyBuilder DefineDynamicAssembly(System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.AssemblyBuilder DefineDynamicAssembly(System.Reflection.AssemblyName name, System.Reflection.Emit.AssemblyBuilderAccess access, System.Collections.Generic.IEnumerable<System.Reflection.Emit.CustomAttributeBuilder> assemblyAttributes) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ModuleBuilder DefineDynamicModule(string name) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ModuleBuilder DefineDynamicModule(string name, bool emitSymbolInfo) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public System.Reflection.Emit.ModuleBuilder GetDynamicModule(string name) { throw null; }
+ public override System.Type[] GetExportedTypes() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override System.Reflection.ManifestResourceInfo GetManifestResourceInfo(string resourceName) { throw null; }
+ public override string[] GetManifestResourceNames() { throw null; }
+ public override System.IO.Stream GetManifestResourceStream(string name) { throw null; }
+ public override System.IO.Stream GetManifestResourceStream(System.Type type, string name) { throw null; }
+ public override System.Reflection.AssemblyName[] GetReferencedAssemblies() { throw null; }
+ public override System.Type GetType(string name, bool throwOnError, bool ignoreCase) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum AssemblyBuilderAccess
+ {
+ Run = 1,
+ RunAndCollect = 9,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ConstructorBuilder : System.Reflection.ConstructorInfo
+ {
+ internal ConstructorBuilder() { }
+ public override System.Reflection.MethodAttributes Attributes { get { throw null; } }
+ public override System.Reflection.CallingConventions CallingConvention { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public bool InitLocals { get { throw null; } set { } }
+ public override System.RuntimeMethodHandle MethodHandle { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public string Signature { get { throw null; } }
+ public System.Reflection.Emit.ParameterBuilder DefineParameter(int iSequence, System.Reflection.ParameterAttributes attributes, string strParamName) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public System.Reflection.Emit.ILGenerator GetILGenerator() { throw null; }
+ public System.Reflection.Emit.ILGenerator GetILGenerator(int streamSize) { throw null; }
+ public override System.Reflection.MethodImplAttributes GetMethodImplementationFlags() { throw null; }
+ public System.Reflection.Module GetModule() { throw null; }
+ public override System.Reflection.ParameterInfo[] GetParameters() { throw null; }
+ public System.Reflection.Emit.MethodToken GetToken() { throw null; }
+ public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { throw null; }
+ public override object Invoke(System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ public void SetImplementationFlags(System.Reflection.MethodImplAttributes attributes) { }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CustomAttributeBuilder
+ {
+ public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs) { }
+ public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs, System.Reflection.FieldInfo[] namedFields, object[] fieldValues) { }
+ public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs, System.Reflection.PropertyInfo[] namedProperties, object[] propertyValues) { }
+ public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs, System.Reflection.PropertyInfo[] namedProperties, object[] propertyValues, System.Reflection.FieldInfo[] namedFields, object[] fieldValues) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DynamicMethod : System.Reflection.MethodInfo
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes, System.Reflection.Module m, bool skipVisibility) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes, System.Type owner, bool skipVisibility) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes, bool restrictedSkipVisibility) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes, System.Reflection.Module m) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes, System.Reflection.Module m, bool skipVisibility) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecurityCriticalAttribute]
+ public DynamicMethod(string name, System.Type returnType, System.Type[] parameterTypes, System.Type owner, bool skipVisibility) { }
+ public override System.Reflection.MethodAttributes Attributes { get { throw null; } }
+ public override System.Reflection.CallingConventions CallingConvention { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public bool InitLocals { get { throw null; } set { } }
+ public override System.RuntimeMethodHandle MethodHandle { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public override System.Reflection.ParameterInfo ReturnParameter { get { throw null; } }
+ public override System.Type ReturnType { get { throw null; } }
+ public override System.Reflection.ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sealed override System.Delegate CreateDelegate(System.Type delegateType) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public sealed override System.Delegate CreateDelegate(System.Type delegateType, object target) { throw null; }
+ public System.Reflection.Emit.ParameterBuilder DefineParameter(int position, System.Reflection.ParameterAttributes attributes, string parameterName) { throw null; }
+ public override System.Reflection.MethodInfo GetBaseDefinition() { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public System.Reflection.Emit.ILGenerator GetILGenerator() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ILGenerator GetILGenerator(int streamSize) { throw null; }
+ public override System.Reflection.MethodImplAttributes GetMethodImplementationFlags() { throw null; }
+ public override System.Reflection.ParameterInfo[] GetParameters() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class EnumBuilder : System.Reflection.TypeInfo
+ {
+ internal EnumBuilder() { }
+ public override System.Reflection.Assembly Assembly { get { throw null; } }
+ public override string AssemblyQualifiedName { get { throw null; } }
+ public override System.Type BaseType { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public override string FullName { get { throw null; } }
+ public override System.Guid GUID { get { throw null; } }
+ public override bool IsConstructedGenericType { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override string Namespace { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public override System.RuntimeTypeHandle TypeHandle { get { throw null; } }
+ public System.Reflection.Emit.TypeToken TypeToken { get { throw null; } }
+ public System.Reflection.Emit.FieldBuilder UnderlyingField { get { throw null; } }
+ public override System.Type UnderlyingSystemType { get { throw null; } }
+ public System.Type CreateType() { throw null; }
+ public System.Reflection.TypeInfo CreateTypeInfo() { throw null; }
+ public System.Reflection.Emit.FieldBuilder DefineLiteral(string literalName, object literalValue) { throw null; }
+ protected override System.Reflection.TypeAttributes GetAttributeFlagsImpl() { throw null; }
+ protected override System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Type GetElementType() { throw null; }
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Contracts", "CC1055")]
+ public override System.Type GetEnumUnderlyingType() { throw null; }
+ public override System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents() { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetInterface(string name, bool ignoreCase) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) { throw null; }
+ public override System.Type[] GetInterfaces() { throw null; }
+ public override System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetNestedType(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.PropertyInfo GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ protected override bool HasElementTypeImpl() { throw null; }
+ public override object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { throw null; }
+ protected override bool IsArrayImpl() { throw null; }
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; }
+ protected override bool IsByRefImpl() { throw null; }
+ protected override bool IsCOMObjectImpl() { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ protected override bool IsPointerImpl() { throw null; }
+ protected override bool IsPrimitiveImpl() { throw null; }
+ protected override bool IsValueTypeImpl() { throw null; }
+ public override System.Type MakeArrayType() { throw null; }
+ public override System.Type MakeArrayType(int rank) { throw null; }
+ public override System.Type MakeByRefType() { throw null; }
+ public override System.Type MakePointerType() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class EventBuilder
+ {
+ internal EventBuilder() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AddOtherMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ public System.Reflection.Emit.EventToken GetEventToken() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetAddOnMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetRaiseMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetRemoveOnMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct EventToken
+ {
+ public static readonly System.Reflection.Emit.EventToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.EventToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.EventToken a, System.Reflection.Emit.EventToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.EventToken a, System.Reflection.Emit.EventToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class FieldBuilder : System.Reflection.FieldInfo
+ {
+ internal FieldBuilder() { }
+ public override System.Reflection.FieldAttributes Attributes { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public override System.RuntimeFieldHandle FieldHandle { get { throw null; } }
+ public override System.Type FieldType { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public System.Reflection.Emit.FieldToken GetToken() { throw null; }
+ public override object GetValue(object obj) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetConstant(object defaultValue) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void SetOffset(int iOffset) { }
+ public override void SetValue(object obj, object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct FieldToken
+ {
+ public static readonly System.Reflection.Emit.FieldToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.FieldToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.FieldToken a, System.Reflection.Emit.FieldToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.FieldToken a, System.Reflection.Emit.FieldToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum FlowControl
+ {
+ Branch = 0,
+ Break = 1,
+ Call = 2,
+ Cond_Branch = 3,
+ Meta = 4,
+ Next = 5,
+ Return = 7,
+ Throw = 8,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class GenericTypeParameterBuilder : System.Reflection.TypeInfo
+ {
+ internal GenericTypeParameterBuilder() { }
+ public override System.Reflection.Assembly Assembly { get { throw null; } }
+ public override string AssemblyQualifiedName { get { throw null; } }
+ public override System.Type BaseType { get { throw null; } }
+ public override bool ContainsGenericParameters { get { throw null; } }
+ public override System.Reflection.MethodBase DeclaringMethod { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public override string FullName { get { throw null; } }
+ public override System.Reflection.GenericParameterAttributes GenericParameterAttributes { get { throw null; } }
+ public override int GenericParameterPosition { get { throw null; } }
+ public override System.Guid GUID { get { throw null; } }
+ public override bool IsConstructedGenericType { get { throw null; } }
+ public override bool IsGenericParameter { get { throw null; } }
+ public override bool IsGenericType { get { throw null; } }
+ public override bool IsGenericTypeDefinition { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override string Namespace { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public override System.RuntimeTypeHandle TypeHandle { get { throw null; } }
+ public override System.Type UnderlyingSystemType { get { throw null; } }
+ public override bool Equals(object o) { throw null; }
+ protected override System.Reflection.TypeAttributes GetAttributeFlagsImpl() { throw null; }
+ protected override System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Type GetElementType() { throw null; }
+ public override System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents() { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetGenericArguments() { throw null; }
+ public override System.Type GetGenericTypeDefinition() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override System.Type GetInterface(string name, bool ignoreCase) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) { throw null; }
+ public override System.Type[] GetInterfaces() { throw null; }
+ public override System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetNestedType(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.PropertyInfo GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ protected override bool HasElementTypeImpl() { throw null; }
+ public override object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { throw null; }
+ protected override bool IsArrayImpl() { throw null; }
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; }
+ public override bool IsAssignableFrom(System.Type c) { throw null; }
+ protected override bool IsByRefImpl() { throw null; }
+ protected override bool IsCOMObjectImpl() { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ protected override bool IsPointerImpl() { throw null; }
+ protected override bool IsPrimitiveImpl() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override bool IsSubclassOf(System.Type c) { throw null; }
+ protected override bool IsValueTypeImpl() { throw null; }
+ public override System.Type MakeArrayType() { throw null; }
+ public override System.Type MakeArrayType(int rank) { throw null; }
+ public override System.Type MakeByRefType() { throw null; }
+ public override System.Type MakeGenericType(params System.Type[] typeArguments) { throw null; }
+ public override System.Type MakePointerType() { throw null; }
+ public void SetBaseTypeConstraint(System.Type baseTypeConstraint) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ public void SetGenericParameterAttributes(System.Reflection.GenericParameterAttributes genericParameterAttributes) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public void SetInterfaceConstraints(params System.Type[] interfaceConstraints) { }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ILGenerator
+ {
+ internal ILGenerator() { }
+ public virtual int ILOffset { get { throw null; } }
+ public virtual void BeginCatchBlock(System.Type exceptionType) { }
+ public virtual void BeginExceptFilterBlock() { }
+ public virtual System.Reflection.Emit.Label BeginExceptionBlock() { throw null; }
+ public virtual void BeginFaultBlock() { }
+ public virtual void BeginFinallyBlock() { }
+ public virtual void BeginScope() { }
+ public virtual System.Reflection.Emit.LocalBuilder DeclareLocal(System.Type localType) { throw null; }
+ public virtual System.Reflection.Emit.LocalBuilder DeclareLocal(System.Type localType, bool pinned) { throw null; }
+ public virtual System.Reflection.Emit.Label DefineLabel() { throw null; }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, byte arg) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, double arg) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, short arg) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, int arg) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, long arg) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth) { }
+ [System.CLSCompliantAttribute(false)]
+ public void Emit(System.Reflection.Emit.OpCode opcode, sbyte arg) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, float arg) { }
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, string str) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void Emit(System.Reflection.Emit.OpCode opcode, System.Type cls) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void EmitCall(System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo methodInfo, System.Type[] optionalParameterTypes) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void EmitCalli(System.Reflection.Emit.OpCode opcode, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes, System.Type[] optionalParameterTypes) { }
+ public virtual void EmitWriteLine(System.Reflection.Emit.LocalBuilder localBuilder) { }
+ public virtual void EmitWriteLine(System.Reflection.FieldInfo fld) { }
+ public virtual void EmitWriteLine(string value) { }
+ public virtual void EndExceptionBlock() { }
+ public virtual void EndScope() { }
+ public virtual void MarkLabel(System.Reflection.Emit.Label loc) { }
+ public virtual void MarkSequencePoint(System.Diagnostics.SymbolStore.ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn) { }
+ public virtual void ThrowException(System.Type excType) { }
+ public virtual void UsingNamespace(string usingNamespace) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct Label
+ {
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.Label obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.Label a, System.Reflection.Emit.Label b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.Label a, System.Reflection.Emit.Label b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class LocalBuilder : System.Reflection.LocalVariableInfo
+ {
+ internal LocalBuilder() { }
+ public override bool IsPinned { get { throw null; } }
+ public override int LocalIndex { get { throw null; } }
+ public override System.Type LocalType { get { throw null; } }
+ public void SetLocalSymInfo(string name) { }
+ public void SetLocalSymInfo(string name, int startOffset, int endOffset) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class MethodBuilder : System.Reflection.MethodInfo
+ {
+ internal MethodBuilder() { }
+ public override System.Reflection.MethodAttributes Attributes { get { throw null; } }
+ public override System.Reflection.CallingConventions CallingConvention { get { throw null; } }
+ public override bool ContainsGenericParameters { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public bool InitLocals { get { throw null; } set { } }
+ public override bool IsGenericMethod { get { throw null; } }
+ public override bool IsGenericMethodDefinition { get { throw null; } }
+ public override System.RuntimeMethodHandle MethodHandle { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public override System.Reflection.ParameterInfo ReturnParameter { get { throw null; } }
+ public override System.Type ReturnType { get { throw null; } }
+ public override System.Reflection.ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw null; } }
+ public string Signature { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public System.Reflection.Emit.GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ParameterBuilder DefineParameter(int position, System.Reflection.ParameterAttributes attributes, string strParamName) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool Equals(object obj) { throw null; }
+ public override System.Reflection.MethodInfo GetBaseDefinition() { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Type[] GetGenericArguments() { throw null; }
+ public override System.Reflection.MethodInfo GetGenericMethodDefinition() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public System.Reflection.Emit.ILGenerator GetILGenerator() { throw null; }
+ public System.Reflection.Emit.ILGenerator GetILGenerator(int size) { throw null; }
+ public override System.Reflection.MethodImplAttributes GetMethodImplementationFlags() { throw null; }
+ public System.Reflection.Module GetModule() { throw null; }
+ public override System.Reflection.ParameterInfo[] GetParameters() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.MethodToken GetToken() { throw null; }
+ public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Reflection.MethodInfo MakeGenericMethod(params System.Type[] typeArguments) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetImplementationFlags(System.Reflection.MethodImplAttributes attributes) { }
+ public void SetParameters(params System.Type[] parameterTypes) { }
+ public void SetReturnType(System.Type returnType) { }
+ public void SetSignature(System.Type returnType, System.Type[] returnTypeRequiredCustomModifiers, System.Type[] returnTypeOptionalCustomModifiers, System.Type[] parameterTypes, System.Type[][] parameterTypeRequiredCustomModifiers, System.Type[][] parameterTypeOptionalCustomModifiers) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct MethodToken
+ {
+ public static readonly System.Reflection.Emit.MethodToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.MethodToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.MethodToken a, System.Reflection.Emit.MethodToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.MethodToken a, System.Reflection.Emit.MethodToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ModuleBuilder : System.Reflection.Module
+ {
+ internal ModuleBuilder() { }
+ public override System.Reflection.Assembly Assembly { get { throw null; } }
+ public override string FullyQualifiedName { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ public override int MetadataToken { get { throw null; } }
+ public override System.Guid ModuleVersionId { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override string ScopeName { get { throw null; } }
+ public void CreateGlobalFunctions() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Diagnostics.SymbolStore.ISymbolDocumentWriter DefineDocument(string url, System.Guid language, System.Guid languageVendor, System.Guid documentType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.EnumBuilder DefineEnum(string name, System.Reflection.TypeAttributes visibility, System.Type underlyingType) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineGlobalMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineGlobalMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] requiredReturnTypeCustomModifiers, System.Type[] optionalReturnTypeCustomModifiers, System.Type[] parameterTypes, System.Type[][] requiredParameterTypeCustomModifiers, System.Type[][] optionalParameterTypeCustomModifiers) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineGlobalMethod(string name, System.Reflection.MethodAttributes attributes, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.FieldBuilder DefineInitializedData(string name, byte[] data, System.Reflection.FieldAttributes attributes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr, System.Type parent) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr, System.Type parent, int typesize) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Reflection.Emit.PackingSize packsize) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Reflection.Emit.PackingSize packingSize, int typesize) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Type[] interfaces) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.FieldBuilder DefineUninitializedData(string name, int size, System.Reflection.FieldAttributes attributes) { throw null; }
+ public override bool Equals(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.MethodInfo GetArrayMethod(System.Type arrayClass, string methodName, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.MethodToken GetArrayMethodToken(System.Type arrayClass, string methodName, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.MethodToken GetConstructorToken(System.Reflection.ConstructorInfo con) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingFlags) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.FieldToken GetFieldToken(System.Reflection.FieldInfo field) { throw null; }
+ public override int GetHashCode() { throw null; }
+ protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingFlags) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.MethodToken GetMethodToken(System.Reflection.MethodInfo method) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.SignatureToken GetSignatureToken(System.Reflection.Emit.SignatureHelper sigHelper) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.StringToken GetStringConstant(string str) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Type GetType(string className) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Type GetType(string className, bool ignoreCase) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Type GetType(string className, bool throwOnError, bool ignoreCase) { throw null; }
+ public override System.Type[] GetTypes() { throw null; }
+ public System.Reflection.Emit.TypeToken GetTypeToken(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeToken GetTypeToken(System.Type type) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ public bool IsTransient() { throw null; }
+ public override System.Reflection.FieldInfo ResolveField(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public override System.Reflection.MethodBase ResolveMethod(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ public override string ResolveString(int metadataToken) { throw null; }
+ public override System.Type ResolveType(int metadataToken, System.Type[] genericTypeArguments, System.Type[] genericMethodArguments) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct OpCode
+ {
+ public System.Reflection.Emit.FlowControl FlowControl { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Reflection.Emit.OpCodeType OpCodeType { get { throw null; } }
+ public System.Reflection.Emit.OperandType OperandType { get { throw null; } }
+ public int Size { get { throw null; } }
+ public System.Reflection.Emit.StackBehaviour StackBehaviourPop { get { throw null; } }
+ public System.Reflection.Emit.StackBehaviour StackBehaviourPush { get { throw null; } }
+ public short Value { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.OpCode obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.OpCode a, System.Reflection.Emit.OpCode b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.OpCode a, System.Reflection.Emit.OpCode b) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class OpCodes
+ {
+ internal OpCodes() { }
+ public static readonly System.Reflection.Emit.OpCode Add;
+ public static readonly System.Reflection.Emit.OpCode Add_Ovf;
+ public static readonly System.Reflection.Emit.OpCode Add_Ovf_Un;
+ public static readonly System.Reflection.Emit.OpCode And;
+ public static readonly System.Reflection.Emit.OpCode Arglist;
+ public static readonly System.Reflection.Emit.OpCode Beq;
+ public static readonly System.Reflection.Emit.OpCode Beq_S;
+ public static readonly System.Reflection.Emit.OpCode Bge;
+ public static readonly System.Reflection.Emit.OpCode Bge_S;
+ public static readonly System.Reflection.Emit.OpCode Bge_Un;
+ public static readonly System.Reflection.Emit.OpCode Bge_Un_S;
+ public static readonly System.Reflection.Emit.OpCode Bgt;
+ public static readonly System.Reflection.Emit.OpCode Bgt_S;
+ public static readonly System.Reflection.Emit.OpCode Bgt_Un;
+ public static readonly System.Reflection.Emit.OpCode Bgt_Un_S;
+ public static readonly System.Reflection.Emit.OpCode Ble;
+ public static readonly System.Reflection.Emit.OpCode Ble_S;
+ public static readonly System.Reflection.Emit.OpCode Ble_Un;
+ public static readonly System.Reflection.Emit.OpCode Ble_Un_S;
+ public static readonly System.Reflection.Emit.OpCode Blt;
+ public static readonly System.Reflection.Emit.OpCode Blt_S;
+ public static readonly System.Reflection.Emit.OpCode Blt_Un;
+ public static readonly System.Reflection.Emit.OpCode Blt_Un_S;
+ public static readonly System.Reflection.Emit.OpCode Bne_Un;
+ public static readonly System.Reflection.Emit.OpCode Bne_Un_S;
+ public static readonly System.Reflection.Emit.OpCode Box;
+ public static readonly System.Reflection.Emit.OpCode Br;
+ public static readonly System.Reflection.Emit.OpCode Br_S;
+ public static readonly System.Reflection.Emit.OpCode Break;
+ public static readonly System.Reflection.Emit.OpCode Brfalse;
+ public static readonly System.Reflection.Emit.OpCode Brfalse_S;
+ public static readonly System.Reflection.Emit.OpCode Brtrue;
+ public static readonly System.Reflection.Emit.OpCode Brtrue_S;
+ public static readonly System.Reflection.Emit.OpCode Call;
+ public static readonly System.Reflection.Emit.OpCode Calli;
+ public static readonly System.Reflection.Emit.OpCode Callvirt;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static readonly System.Reflection.Emit.OpCode Castclass;
+ public static readonly System.Reflection.Emit.OpCode Ceq;
+ public static readonly System.Reflection.Emit.OpCode Cgt;
+ public static readonly System.Reflection.Emit.OpCode Cgt_Un;
+ public static readonly System.Reflection.Emit.OpCode Ckfinite;
+ public static readonly System.Reflection.Emit.OpCode Clt;
+ public static readonly System.Reflection.Emit.OpCode Clt_Un;
+ public static readonly System.Reflection.Emit.OpCode Constrained;
+ public static readonly System.Reflection.Emit.OpCode Conv_I;
+ public static readonly System.Reflection.Emit.OpCode Conv_I1;
+ public static readonly System.Reflection.Emit.OpCode Conv_I2;
+ public static readonly System.Reflection.Emit.OpCode Conv_I4;
+ public static readonly System.Reflection.Emit.OpCode Conv_I8;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I1;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I1_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I2;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I2_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I4;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I4_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I8;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_I8_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U1;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U1_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U2;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U2_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U4;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U4_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U8;
+ public static readonly System.Reflection.Emit.OpCode Conv_Ovf_U8_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_R_Un;
+ public static readonly System.Reflection.Emit.OpCode Conv_R4;
+ public static readonly System.Reflection.Emit.OpCode Conv_R8;
+ public static readonly System.Reflection.Emit.OpCode Conv_U;
+ public static readonly System.Reflection.Emit.OpCode Conv_U1;
+ public static readonly System.Reflection.Emit.OpCode Conv_U2;
+ public static readonly System.Reflection.Emit.OpCode Conv_U4;
+ public static readonly System.Reflection.Emit.OpCode Conv_U8;
+ public static readonly System.Reflection.Emit.OpCode Cpblk;
+ public static readonly System.Reflection.Emit.OpCode Cpobj;
+ public static readonly System.Reflection.Emit.OpCode Div;
+ public static readonly System.Reflection.Emit.OpCode Div_Un;
+ public static readonly System.Reflection.Emit.OpCode Dup;
+ public static readonly System.Reflection.Emit.OpCode Endfilter;
+ public static readonly System.Reflection.Emit.OpCode Endfinally;
+ public static readonly System.Reflection.Emit.OpCode Initblk;
+ public static readonly System.Reflection.Emit.OpCode Initobj;
+ public static readonly System.Reflection.Emit.OpCode Isinst;
+ public static readonly System.Reflection.Emit.OpCode Jmp;
+ public static readonly System.Reflection.Emit.OpCode Ldarg;
+ public static readonly System.Reflection.Emit.OpCode Ldarg_0;
+ public static readonly System.Reflection.Emit.OpCode Ldarg_1;
+ public static readonly System.Reflection.Emit.OpCode Ldarg_2;
+ public static readonly System.Reflection.Emit.OpCode Ldarg_3;
+ public static readonly System.Reflection.Emit.OpCode Ldarg_S;
+ public static readonly System.Reflection.Emit.OpCode Ldarga;
+ public static readonly System.Reflection.Emit.OpCode Ldarga_S;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_0;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_1;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_2;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_3;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_4;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_5;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_6;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_7;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_8;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_M1;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I4_S;
+ public static readonly System.Reflection.Emit.OpCode Ldc_I8;
+ public static readonly System.Reflection.Emit.OpCode Ldc_R4;
+ public static readonly System.Reflection.Emit.OpCode Ldc_R8;
+ public static readonly System.Reflection.Emit.OpCode Ldelem;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_I;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_I1;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_I2;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_I4;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_I8;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_R4;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_R8;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_Ref;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_U1;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_U2;
+ public static readonly System.Reflection.Emit.OpCode Ldelem_U4;
+ public static readonly System.Reflection.Emit.OpCode Ldelema;
+ public static readonly System.Reflection.Emit.OpCode Ldfld;
+ public static readonly System.Reflection.Emit.OpCode Ldflda;
+ public static readonly System.Reflection.Emit.OpCode Ldftn;
+ public static readonly System.Reflection.Emit.OpCode Ldind_I;
+ public static readonly System.Reflection.Emit.OpCode Ldind_I1;
+ public static readonly System.Reflection.Emit.OpCode Ldind_I2;
+ public static readonly System.Reflection.Emit.OpCode Ldind_I4;
+ public static readonly System.Reflection.Emit.OpCode Ldind_I8;
+ public static readonly System.Reflection.Emit.OpCode Ldind_R4;
+ public static readonly System.Reflection.Emit.OpCode Ldind_R8;
+ public static readonly System.Reflection.Emit.OpCode Ldind_Ref;
+ public static readonly System.Reflection.Emit.OpCode Ldind_U1;
+ public static readonly System.Reflection.Emit.OpCode Ldind_U2;
+ public static readonly System.Reflection.Emit.OpCode Ldind_U4;
+ public static readonly System.Reflection.Emit.OpCode Ldlen;
+ public static readonly System.Reflection.Emit.OpCode Ldloc;
+ public static readonly System.Reflection.Emit.OpCode Ldloc_0;
+ public static readonly System.Reflection.Emit.OpCode Ldloc_1;
+ public static readonly System.Reflection.Emit.OpCode Ldloc_2;
+ public static readonly System.Reflection.Emit.OpCode Ldloc_3;
+ public static readonly System.Reflection.Emit.OpCode Ldloc_S;
+ public static readonly System.Reflection.Emit.OpCode Ldloca;
+ public static readonly System.Reflection.Emit.OpCode Ldloca_S;
+ public static readonly System.Reflection.Emit.OpCode Ldnull;
+ public static readonly System.Reflection.Emit.OpCode Ldobj;
+ public static readonly System.Reflection.Emit.OpCode Ldsfld;
+ public static readonly System.Reflection.Emit.OpCode Ldsflda;
+ public static readonly System.Reflection.Emit.OpCode Ldstr;
+ public static readonly System.Reflection.Emit.OpCode Ldtoken;
+ public static readonly System.Reflection.Emit.OpCode Ldvirtftn;
+ public static readonly System.Reflection.Emit.OpCode Leave;
+ public static readonly System.Reflection.Emit.OpCode Leave_S;
+ public static readonly System.Reflection.Emit.OpCode Localloc;
+ public static readonly System.Reflection.Emit.OpCode Mkrefany;
+ public static readonly System.Reflection.Emit.OpCode Mul;
+ public static readonly System.Reflection.Emit.OpCode Mul_Ovf;
+ public static readonly System.Reflection.Emit.OpCode Mul_Ovf_Un;
+ public static readonly System.Reflection.Emit.OpCode Neg;
+ public static readonly System.Reflection.Emit.OpCode Newarr;
+ public static readonly System.Reflection.Emit.OpCode Newobj;
+ public static readonly System.Reflection.Emit.OpCode Nop;
+ public static readonly System.Reflection.Emit.OpCode Not;
+ public static readonly System.Reflection.Emit.OpCode Or;
+ public static readonly System.Reflection.Emit.OpCode Pop;
+ public static readonly System.Reflection.Emit.OpCode Prefix1;
+ public static readonly System.Reflection.Emit.OpCode Prefix2;
+ public static readonly System.Reflection.Emit.OpCode Prefix3;
+ public static readonly System.Reflection.Emit.OpCode Prefix4;
+ public static readonly System.Reflection.Emit.OpCode Prefix5;
+ public static readonly System.Reflection.Emit.OpCode Prefix6;
+ public static readonly System.Reflection.Emit.OpCode Prefix7;
+ public static readonly System.Reflection.Emit.OpCode Prefixref;
+ public static readonly System.Reflection.Emit.OpCode Readonly;
+ public static readonly System.Reflection.Emit.OpCode Refanytype;
+ public static readonly System.Reflection.Emit.OpCode Refanyval;
+ public static readonly System.Reflection.Emit.OpCode Rem;
+ public static readonly System.Reflection.Emit.OpCode Rem_Un;
+ public static readonly System.Reflection.Emit.OpCode Ret;
+ public static readonly System.Reflection.Emit.OpCode Rethrow;
+ public static readonly System.Reflection.Emit.OpCode Shl;
+ public static readonly System.Reflection.Emit.OpCode Shr;
+ public static readonly System.Reflection.Emit.OpCode Shr_Un;
+ public static readonly System.Reflection.Emit.OpCode Sizeof;
+ public static readonly System.Reflection.Emit.OpCode Starg;
+ public static readonly System.Reflection.Emit.OpCode Starg_S;
+ public static readonly System.Reflection.Emit.OpCode Stelem;
+ public static readonly System.Reflection.Emit.OpCode Stelem_I;
+ public static readonly System.Reflection.Emit.OpCode Stelem_I1;
+ public static readonly System.Reflection.Emit.OpCode Stelem_I2;
+ public static readonly System.Reflection.Emit.OpCode Stelem_I4;
+ public static readonly System.Reflection.Emit.OpCode Stelem_I8;
+ public static readonly System.Reflection.Emit.OpCode Stelem_R4;
+ public static readonly System.Reflection.Emit.OpCode Stelem_R8;
+ public static readonly System.Reflection.Emit.OpCode Stelem_Ref;
+ public static readonly System.Reflection.Emit.OpCode Stfld;
+ public static readonly System.Reflection.Emit.OpCode Stind_I;
+ public static readonly System.Reflection.Emit.OpCode Stind_I1;
+ public static readonly System.Reflection.Emit.OpCode Stind_I2;
+ public static readonly System.Reflection.Emit.OpCode Stind_I4;
+ public static readonly System.Reflection.Emit.OpCode Stind_I8;
+ public static readonly System.Reflection.Emit.OpCode Stind_R4;
+ public static readonly System.Reflection.Emit.OpCode Stind_R8;
+ public static readonly System.Reflection.Emit.OpCode Stind_Ref;
+ public static readonly System.Reflection.Emit.OpCode Stloc;
+ public static readonly System.Reflection.Emit.OpCode Stloc_0;
+ public static readonly System.Reflection.Emit.OpCode Stloc_1;
+ public static readonly System.Reflection.Emit.OpCode Stloc_2;
+ public static readonly System.Reflection.Emit.OpCode Stloc_3;
+ public static readonly System.Reflection.Emit.OpCode Stloc_S;
+ public static readonly System.Reflection.Emit.OpCode Stobj;
+ public static readonly System.Reflection.Emit.OpCode Stsfld;
+ public static readonly System.Reflection.Emit.OpCode Sub;
+ public static readonly System.Reflection.Emit.OpCode Sub_Ovf;
+ public static readonly System.Reflection.Emit.OpCode Sub_Ovf_Un;
+ public static readonly System.Reflection.Emit.OpCode Switch;
+ public static readonly System.Reflection.Emit.OpCode Tailcall;
+ public static readonly System.Reflection.Emit.OpCode Throw;
+ public static readonly System.Reflection.Emit.OpCode Unaligned;
+ public static readonly System.Reflection.Emit.OpCode Unbox;
+ public static readonly System.Reflection.Emit.OpCode Unbox_Any;
+ public static readonly System.Reflection.Emit.OpCode Volatile;
+ public static readonly System.Reflection.Emit.OpCode Xor;
+ public static bool TakesSingleByteArgument(System.Reflection.Emit.OpCode inst) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum OpCodeType
+ {
+ Macro = 1,
+ Nternal = 2,
+ Objmodel = 3,
+ Prefix = 4,
+ Primitive = 5,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum OperandType
+ {
+ InlineBrTarget = 0,
+ InlineField = 1,
+ InlineI = 2,
+ InlineI8 = 3,
+ InlineMethod = 4,
+ InlineNone = 5,
+ InlineR = 7,
+ InlineSig = 9,
+ InlineString = 10,
+ InlineSwitch = 11,
+ InlineTok = 12,
+ InlineType = 13,
+ InlineVar = 14,
+ ShortInlineBrTarget = 15,
+ ShortInlineI = 16,
+ ShortInlineR = 17,
+ ShortInlineVar = 18,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum PackingSize
+ {
+ Size1 = 1,
+ Size128 = 128,
+ Size16 = 16,
+ Size2 = 2,
+ Size32 = 32,
+ Size4 = 4,
+ Size64 = 64,
+ Size8 = 8,
+ Unspecified = 0,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ParameterBuilder
+ {
+ internal ParameterBuilder() { }
+ public virtual int Attributes { get { throw null; } }
+ public bool IsIn { get { throw null; } }
+ public bool IsOptional { get { throw null; } }
+ public bool IsOut { get { throw null; } }
+ public virtual string Name { get { throw null; } }
+ public virtual int Position { get { throw null; } }
+ public virtual System.Reflection.Emit.ParameterToken GetToken() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public virtual void SetConstant(object defaultValue) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ParameterToken
+ {
+ public static readonly System.Reflection.Emit.ParameterToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.ParameterToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.ParameterToken a, System.Reflection.Emit.ParameterToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.ParameterToken a, System.Reflection.Emit.ParameterToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum PEFileKinds
+ {
+ ConsoleApplication = 2,
+ Dll = 1,
+ WindowApplication = 3,
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class PropertyBuilder : System.Reflection.PropertyInfo
+ {
+ internal PropertyBuilder() { }
+ public override System.Reflection.PropertyAttributes Attributes { get { throw null; } }
+ public override bool CanRead { get { throw null; } }
+ public override bool CanWrite { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public System.Reflection.Emit.PropertyToken PropertyToken { get { throw null; } }
+ public override System.Type PropertyType { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AddOtherMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ public override System.Reflection.MethodInfo[] GetAccessors(bool nonPublic) { throw null; }
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Reflection.MethodInfo GetGetMethod(bool nonPublic) { throw null; }
+ public override System.Reflection.ParameterInfo[] GetIndexParameters() { throw null; }
+ public override System.Reflection.MethodInfo GetSetMethod(bool nonPublic) { throw null; }
+ public override object GetValue(object obj, object[] index) { throw null; }
+ public override object GetValue(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] index, System.Globalization.CultureInfo culture) { throw null; }
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetConstant(object defaultValue) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetGetMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetSetMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
+ public override void SetValue(object obj, object value, object[] index) { }
+ public override void SetValue(object obj, object value, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] index, System.Globalization.CultureInfo culture) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct PropertyToken
+ {
+ public static readonly System.Reflection.Emit.PropertyToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.PropertyToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.PropertyToken a, System.Reflection.Emit.PropertyToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.PropertyToken a, System.Reflection.Emit.PropertyToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SignatureHelper
+ {
+ internal SignatureHelper() { }
+ public void AddArgument(System.Type clsArgument) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AddArgument(System.Type argument, bool pinned) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AddArgument(System.Type argument, System.Type[] requiredCustomModifiers, System.Type[] optionalCustomModifiers) { }
+ public void AddArguments(System.Type[] arguments, System.Type[][] requiredCustomModifiers, System.Type[][] optionalCustomModifiers) { }
+ public void AddSentinel() { }
+ public override bool Equals(object obj) { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetFieldSigHelper(System.Reflection.Module mod) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetLocalVarSigHelper() { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetLocalVarSigHelper(System.Reflection.Module mod) { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetMethodSigHelper(System.Reflection.CallingConventions callingConvention, System.Type returnType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.SignatureHelper GetMethodSigHelper(System.Reflection.Module mod, System.Reflection.CallingConventions callingConvention, System.Type returnType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.SignatureHelper GetMethodSigHelper(System.Reflection.Module mod, System.Runtime.InteropServices.CallingConvention unmanagedCallConv, System.Type returnType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.SignatureHelper GetMethodSigHelper(System.Reflection.Module mod, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetMethodSigHelper(System.Runtime.InteropServices.CallingConvention unmanagedCallingConvention, System.Type returnType) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Reflection.Emit.SignatureHelper GetPropertySigHelper(System.Reflection.Module mod, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] requiredReturnTypeCustomModifiers, System.Type[] optionalReturnTypeCustomModifiers, System.Type[] parameterTypes, System.Type[][] requiredParameterTypeCustomModifiers, System.Type[][] optionalParameterTypeCustomModifiers) { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetPropertySigHelper(System.Reflection.Module mod, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ public static System.Reflection.Emit.SignatureHelper GetPropertySigHelper(System.Reflection.Module mod, System.Type returnType, System.Type[] requiredReturnTypeCustomModifiers, System.Type[] optionalReturnTypeCustomModifiers, System.Type[] parameterTypes, System.Type[][] requiredParameterTypeCustomModifiers, System.Type[][] optionalParameterTypeCustomModifiers) { throw null; }
+ public byte[] GetSignature() { throw null; }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct SignatureToken
+ {
+ public static readonly System.Reflection.Emit.SignatureToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.SignatureToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.SignatureToken a, System.Reflection.Emit.SignatureToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.SignatureToken a, System.Reflection.Emit.SignatureToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum StackBehaviour
+ {
+ Pop0 = 0,
+ Pop1 = 1,
+ Pop1_pop1 = 2,
+ Popi = 3,
+ Popi_pop1 = 4,
+ Popi_popi = 5,
+ Popi_popi_popi = 7,
+ Popi_popi8 = 6,
+ Popi_popr4 = 8,
+ Popi_popr8 = 9,
+ Popref = 10,
+ Popref_pop1 = 11,
+ Popref_popi = 12,
+ Popref_popi_pop1 = 28,
+ Popref_popi_popi = 13,
+ Popref_popi_popi8 = 14,
+ Popref_popi_popr4 = 15,
+ Popref_popi_popr8 = 16,
+ Popref_popi_popref = 17,
+ Push0 = 18,
+ Push1 = 19,
+ Push1_push1 = 20,
+ Pushi = 21,
+ Pushi8 = 22,
+ Pushr4 = 23,
+ Pushr8 = 24,
+ Pushref = 25,
+ Varpop = 26,
+ Varpush = 27,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct StringToken
+ {
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.StringToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.StringToken a, System.Reflection.Emit.StringToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.StringToken a, System.Reflection.Emit.StringToken b) { throw null; }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class TypeBuilder : System.Reflection.TypeInfo
+ {
+ internal TypeBuilder() { }
+ public const int UnspecifiedTypeSize = 0;
+ public override System.Reflection.Assembly Assembly { get { throw null; } }
+ public override string AssemblyQualifiedName { get { throw null; } }
+ public override System.Type BaseType { get { throw null; } }
+ public override System.Reflection.MethodBase DeclaringMethod { get { throw null; } }
+ public override System.Type DeclaringType { get { throw null; } }
+ public override string FullName { get { throw null; } }
+ public override System.Reflection.GenericParameterAttributes GenericParameterAttributes { get { throw null; } }
+ public override int GenericParameterPosition { get { throw null; } }
+ public override System.Guid GUID { get { throw null; } }
+ public override bool IsConstructedGenericType { get { throw null; } }
+ public override bool IsGenericParameter { get { throw null; } }
+ public override bool IsGenericType { get { throw null; } }
+ public override bool IsGenericTypeDefinition { get { throw null; } }
+ public override System.Reflection.Module Module { get { throw null; } }
+ public override string Name { get { throw null; } }
+ public override string Namespace { get { throw null; } }
+ public System.Reflection.Emit.PackingSize PackingSize { get { throw null; } }
+ public override System.Type ReflectedType { get { throw null; } }
+ public int Size { get { throw null; } }
+ public override System.RuntimeTypeHandle TypeHandle { get { throw null; } }
+ public System.Reflection.Emit.TypeToken TypeToken { get { throw null; } }
+ public override System.Type UnderlyingSystemType { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AddInterfaceImplementation(System.Type interfaceType) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Type CreateType() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.TypeInfo CreateTypeInfo() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.Emit.ConstructorBuilder DefineConstructor(System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type[] parameterTypes) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ConstructorBuilder DefineConstructor(System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type[] parameterTypes, System.Type[][] requiredCustomModifiers, System.Type[][] optionalCustomModifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Reflection.Emit.ConstructorBuilder DefineDefaultConstructor(System.Reflection.MethodAttributes attributes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.EventBuilder DefineEvent(string name, System.Reflection.EventAttributes attributes, System.Type eventtype) { throw null; }
+ public System.Reflection.Emit.FieldBuilder DefineField(string fieldName, System.Type type, System.Reflection.FieldAttributes attributes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.FieldBuilder DefineField(string fieldName, System.Type type, System.Type[] requiredCustomModifiers, System.Type[] optionalCustomModifiers, System.Reflection.FieldAttributes attributes) { throw null; }
+ public System.Reflection.Emit.GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.FieldBuilder DefineInitializedData(string name, byte[] data, System.Reflection.FieldAttributes attributes) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineMethod(string name, System.Reflection.MethodAttributes attributes) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineMethod(string name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] returnTypeRequiredCustomModifiers, System.Type[] returnTypeOptionalCustomModifiers, System.Type[] parameterTypes, System.Type[][] parameterTypeRequiredCustomModifiers, System.Type[][] parameterTypeOptionalCustomModifiers) { throw null; }
+ public System.Reflection.Emit.MethodBuilder DefineMethod(string name, System.Reflection.MethodAttributes attributes, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void DefineMethodOverride(System.Reflection.MethodInfo methodInfoBody, System.Reflection.MethodInfo methodInfoDeclaration) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr, System.Type parent) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr, System.Type parent, int typeSize) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Reflection.Emit.PackingSize packSize) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Reflection.Emit.PackingSize packSize, int typeSize) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.TypeBuilder DefineNestedType(string name, System.Reflection.TypeAttributes attr, System.Type parent, System.Type[] interfaces) { throw null; }
+ public System.Reflection.Emit.PropertyBuilder DefineProperty(string name, System.Reflection.PropertyAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.PropertyBuilder DefineProperty(string name, System.Reflection.PropertyAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] returnTypeRequiredCustomModifiers, System.Type[] returnTypeOptionalCustomModifiers, System.Type[] parameterTypes, System.Type[][] parameterTypeRequiredCustomModifiers, System.Type[][] parameterTypeOptionalCustomModifiers) { throw null; }
+ public System.Reflection.Emit.PropertyBuilder DefineProperty(string name, System.Reflection.PropertyAttributes attributes, System.Type returnType, System.Type[] parameterTypes) { throw null; }
+ public System.Reflection.Emit.PropertyBuilder DefineProperty(string name, System.Reflection.PropertyAttributes attributes, System.Type returnType, System.Type[] returnTypeRequiredCustomModifiers, System.Type[] returnTypeOptionalCustomModifiers, System.Type[] parameterTypes, System.Type[][] parameterTypeRequiredCustomModifiers, System.Type[][] parameterTypeOptionalCustomModifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Reflection.Emit.ConstructorBuilder DefineTypeInitializer() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public System.Reflection.Emit.FieldBuilder DefineUninitializedData(string name, int size, System.Reflection.FieldAttributes attributes) { throw null; }
+ protected override System.Reflection.TypeAttributes GetAttributeFlagsImpl() { throw null; }
+ public static System.Reflection.ConstructorInfo GetConstructor(System.Type type, System.Reflection.ConstructorInfo constructor) { throw null; }
+ protected override System.Reflection.ConstructorInfo GetConstructorImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.ConstructorInfo[] GetConstructors(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override object[] GetCustomAttributes(bool inherit) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override object[] GetCustomAttributes(System.Type attributeType, bool inherit) { throw null; }
+ public override System.Type GetElementType() { throw null; }
+ public override System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents() { throw null; }
+ public override System.Reflection.EventInfo[] GetEvents(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public static System.Reflection.FieldInfo GetField(System.Type type, System.Reflection.FieldInfo field) { throw null; }
+ public override System.Reflection.FieldInfo[] GetFields(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetGenericArguments() { throw null; }
+ public override System.Type GetGenericTypeDefinition() { throw null; }
+ public override System.Type GetInterface(string name, bool ignoreCase) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) { throw null; }
+ public override System.Type[] GetInterfaces() { throw null; }
+ public override System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public static System.Reflection.MethodInfo GetMethod(System.Type type, System.Reflection.MethodInfo method) { throw null; }
+ protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type GetNestedType(string name, System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Type[] GetNestedTypes(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ public override System.Reflection.PropertyInfo[] GetProperties(System.Reflection.BindingFlags bindingAttr) { throw null; }
+ protected override System.Reflection.PropertyInfo GetPropertyImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Type returnType, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) { throw null; }
+ protected override bool HasElementTypeImpl() { throw null; }
+ public override object InvokeMember(string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object target, object[] args, System.Reflection.ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters) { throw null; }
+ protected override bool IsArrayImpl() { throw null; }
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo) { throw null; }
+ public override bool IsAssignableFrom(System.Type c) { throw null; }
+ protected override bool IsByRefImpl() { throw null; }
+ protected override bool IsCOMObjectImpl() { throw null; }
+ public bool IsCreated() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
+ protected override bool IsPointerImpl() { throw null; }
+ protected override bool IsPrimitiveImpl() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public override bool IsSubclassOf(System.Type c) { throw null; }
+ public override System.Type MakeArrayType() { throw null; }
+ public override System.Type MakeArrayType(int rank) { throw null; }
+ public override System.Type MakeByRefType() { throw null; }
+ public override System.Type MakeGenericType(params System.Type[] typeArguments) { throw null; }
+ public override System.Type MakePointerType() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
+ public void SetParent(System.Type parent) { }
+ public override string ToString() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TypeToken
+ {
+ public static readonly System.Reflection.Emit.TypeToken Empty;
+ public int Token { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Reflection.Emit.TypeToken obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Reflection.Emit.TypeToken a, System.Reflection.Emit.TypeToken b) { throw null; }
+ public static bool operator !=(System.Reflection.Emit.TypeToken a, System.Reflection.Emit.TypeToken b) { throw null; }
+ }
+}
+namespace System.Reflection.Metadata
+{
+ public static partial class AssemblyExtensions
+ {
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static bool TryGetRawMetadata(this System.Reflection.Assembly assembly, out byte* blob, out int length) { blob = default(byte*); length = default(int); throw null; }
+ }
+}
+namespace System.Resources
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IResourceReader : System.Collections.IEnumerable, System.IDisposable
+ {
+ new System.Collections.IDictionaryEnumerator GetEnumerator();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MissingManifestResourceException : System.SystemException
+ {
+ public MissingManifestResourceException() { }
+ public MissingManifestResourceException(string message) { }
+ public MissingManifestResourceException(string message, System.Exception inner) { }
+ protected MissingManifestResourceException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class NeutralResourcesLanguageAttribute : System.Attribute
+ {
+ public NeutralResourcesLanguageAttribute(string cultureName) { }
+ public NeutralResourcesLanguageAttribute(string cultureName, System.Resources.UltimateResourceFallbackLocation location) { }
+ public string CultureName { get { throw null; } }
+ public System.Resources.UltimateResourceFallbackLocation Location { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ResourceManager
+ {
+ protected string BaseNameField;
+ public static readonly int HeaderVersionNumber;
+ public static readonly int MagicNumber;
+ protected System.Reflection.Assembly MainAssembly;
+ protected ResourceManager() { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public ResourceManager(string baseName, System.Reflection.Assembly assembly) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public ResourceManager(string baseName, System.Reflection.Assembly assembly, System.Type usingResourceSet) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public ResourceManager(System.Type resourceSource) { }
+ public virtual string BaseName { get { throw null; } }
+ public virtual bool IgnoreCase { get { throw null; } set { } }
+ public virtual System.Type ResourceSetType { get { throw null; } }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected static System.Globalization.CultureInfo GetNeutralResourcesLanguage(System.Reflection.Assembly a) { throw null; }
+ public virtual object GetObject(string name) { throw null; }
+ public virtual object GetObject(string name, System.Globalization.CultureInfo culture) { throw null; }
+ protected virtual string GetResourceFileName(System.Globalization.CultureInfo culture) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public virtual System.Resources.ResourceSet GetResourceSet(System.Globalization.CultureInfo culture, bool createIfNotExists, bool tryParents) { throw null; }
+ protected static System.Version GetSatelliteContractVersion(System.Reflection.Assembly a) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.IO.UnmanagedMemoryStream GetStream(string name) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.IO.UnmanagedMemoryStream GetStream(string name, System.Globalization.CultureInfo culture) { throw null; }
+ public virtual string GetString(string name) { throw null; }
+ public virtual string GetString(string name, System.Globalization.CultureInfo culture) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ protected virtual System.Resources.ResourceSet InternalGetResourceSet(System.Globalization.CultureInfo culture, bool createIfNotExists, bool tryParents) { throw null; }
+ public virtual void ReleaseAllResources() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ResourceSet : System.Collections.IEnumerable, System.IDisposable
+ {
+ protected System.Resources.IResourceReader Reader;
+ protected ResourceSet() { }
+ [System.Security.SecurityCriticalAttribute]
+ public ResourceSet(System.IO.Stream stream) { }
+ [System.Security.SecurityCriticalAttribute]
+ public ResourceSet(string fileName) { }
+ public virtual void Close() { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public virtual System.Type GetDefaultReader() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual System.Collections.IDictionaryEnumerator GetEnumerator() { throw null; }
+ public virtual object GetObject(string name) { throw null; }
+ public virtual object GetObject(string name, bool ignoreCase) { throw null; }
+ public virtual string GetString(string name) { throw null; }
+ public virtual string GetString(string name, bool ignoreCase) { throw null; }
+ protected virtual void ReadResources() { }
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SatelliteContractVersionAttribute : System.Attribute
+ {
+ public SatelliteContractVersionAttribute(string version) { }
+ public string Version { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum UltimateResourceFallbackLocation
+ {
+ MainAssembly = 0,
+ Satellite = 1,
+ }
+}
+namespace System.Runtime
+{
+ public enum GCLargeObjectHeapCompactionMode
+ {
+ CompactOnce = 2,
+ Default = 1,
+ }
+ public enum GCLatencyMode
+ {
+ Batch = 0,
+ Interactive = 1,
+ LowLatency = 2,
+ NoGCRegion = 4,
+ SustainedLowLatency = 3,
+ }
+ public static partial class GCSettings
+ {
+ public static bool IsServerGC { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public static System.Runtime.GCLargeObjectHeapCompactionMode LargeObjectHeapCompactionMode { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ public static System.Runtime.GCLatencyMode LatencyMode { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ }
+}
+namespace System.Runtime.CompilerServices
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AccessedThroughPropertyAttribute : System.Attribute
+ {
+ public AccessedThroughPropertyAttribute(string propertyName) { }
+ public string PropertyName { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false, AllowMultiple=false)]
+ public sealed partial class AsyncStateMachineAttribute : System.Runtime.CompilerServices.StateMachineAttribute
+ {
+ public AsyncStateMachineAttribute(System.Type stateMachineType) : base (default(System.Type)) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct AsyncTaskMethodBuilder
+ {
+ public System.Threading.Tasks.Task Task { get { throw null; } }
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ public static System.Runtime.CompilerServices.AsyncTaskMethodBuilder Create() { throw null; }
+ public void SetException(System.Exception exception) { }
+ public void SetResult() { }
+ public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct AsyncTaskMethodBuilder<TResult>
+ {
+ public System.Threading.Tasks.Task<TResult> Task { get { throw null; } }
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ public static System.Runtime.CompilerServices.AsyncTaskMethodBuilder<TResult> Create() { throw null; }
+ public void SetException(System.Exception exception) { }
+ public void SetResult(TResult result) { }
+ public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct AsyncVoidMethodBuilder
+ {
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ public static System.Runtime.CompilerServices.AsyncVoidMethodBuilder Create() { throw null; }
+ public void SetException(System.Exception exception) { }
+ public void SetResult() { }
+ public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
+ [System.Diagnostics.DebuggerStepThroughAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CallConvCdecl
+ {
+ internal CallConvCdecl() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CallConvFastcall
+ {
+ internal CallConvFastcall() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CallConvStdcall
+ {
+ internal CallConvStdcall() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CallConvThiscall
+ {
+ internal CallConvThiscall() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ public sealed partial class CallerFilePathAttribute : System.Attribute
+ {
+ public CallerFilePathAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ public sealed partial class CallerLineNumberAttribute : System.Attribute
+ {
+ public CallerLineNumberAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ public sealed partial class CallerMemberNameAttribute : System.Attribute
+ {
+ public CallerMemberNameAttribute() { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CompilationRelaxations
+ {
+ NoStringInterning = 8,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(71))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class CompilationRelaxationsAttribute : System.Attribute
+ {
+ public CompilationRelaxationsAttribute(int relaxations) { }
+ public CompilationRelaxationsAttribute(System.Runtime.CompilerServices.CompilationRelaxations relaxations) { }
+ public int CompilationRelaxations { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(32767), Inherited=true)]
+ public sealed partial class CompilerGeneratedAttribute : System.Attribute
+ {
+ public CompilerGeneratedAttribute() { }
+ }
+ public static partial class CompilerMarshalOverride
+ {
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public sealed partial class ConditionalWeakTable<TKey, TValue> where TKey : class where TValue : class
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public ConditionalWeakTable() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Add(TKey key, TValue value) { }
+ ~ConditionalWeakTable() { }
+ public TValue GetOrCreateValue(TKey key) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public TValue GetValue(TKey key, System.Runtime.CompilerServices.ConditionalWeakTable<TKey, TValue>.CreateValueCallback createValueCallback) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Remove(TKey key) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool TryGetValue(TKey key, out TValue value) { value = default(TValue); throw null; }
+ public delegate TValue CreateValueCallback(TKey key);
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ConfiguredTaskAwaitable
+ {
+ public System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ConfiguredTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
+ {
+ public bool IsCompleted { get { throw null; } }
+ public void GetResult() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void OnCompleted(System.Action continuation) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void UnsafeOnCompleted(System.Action continuation) { }
+ }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ConfiguredTaskAwaitable<TResult>
+ {
+ public System.Runtime.CompilerServices.ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter GetAwaiter() { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ConfiguredTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
+ {
+ public bool IsCompleted { get { throw null; } }
+ public TResult GetResult() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void OnCompleted(System.Action continuation) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void UnsafeOnCompleted(System.Action continuation) { }
+ }
+ }
+ public static partial class ContractHelper
+ {
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static string RaiseContractFailedEvent(System.Diagnostics.Contracts.ContractFailureKind failureKind, string userMessage, string conditionText, System.Exception innerException) { throw null; }
+ [System.Diagnostics.DebuggerNonUserCodeAttribute]
+ public static void TriggerFailure(System.Diagnostics.Contracts.ContractFailureKind kind, string displayMessage, string userMessage, string conditionText, System.Exception innerException) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2304), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class CustomConstantAttribute : System.Attribute
+ {
+ protected CustomConstantAttribute() { }
+ public abstract object Value { get; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2304), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DateTimeConstantAttribute : System.Runtime.CompilerServices.CustomConstantAttribute
+ {
+ public DateTimeConstantAttribute(long ticks) { }
+ public override object Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2304), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DecimalConstantAttribute : System.Attribute
+ {
+ public DecimalConstantAttribute(byte scale, byte sign, int hi, int mid, int low) { }
+ [System.CLSCompliantAttribute(false)]
+ public DecimalConstantAttribute(byte scale, byte sign, uint hi, uint mid, uint low) { }
+ public decimal Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)]
+ public sealed partial class DisablePrivateReflectionAttribute : System.Attribute
+ {
+ public DisablePrivateReflectionAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(69))]
+ public sealed partial class ExtensionAttribute : System.Attribute
+ {
+ public ExtensionAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256))]
+ public sealed partial class FixedAddressValueTypeAttribute : System.Attribute
+ {
+ public FixedAddressValueTypeAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ public sealed partial class FixedBufferAttribute : System.Attribute
+ {
+ public FixedBufferAttribute(System.Type elementType, int length) { }
+ public System.Type ElementType { get { throw null; } }
+ public int Length { get { throw null; } }
+ }
+ public static partial class FormattableStringFactory
+ {
+ public static System.FormattableString Create(string format, params object[] arguments) { throw null; }
+ }
+ public partial interface IAsyncStateMachine
+ {
+ void MoveNext();
+ void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine);
+ }
+ public partial interface ICastable
+ {
+ System.RuntimeTypeHandle GetImplType(System.RuntimeTypeHandle interfaceType);
+ bool IsInstanceOfInterface(System.RuntimeTypeHandle interfaceType, out System.Exception castError);
+ }
+ public partial interface ICriticalNotifyCompletion : System.Runtime.CompilerServices.INotifyCompletion
+ {
+ [System.Security.SecurityCriticalAttribute]
+ void UnsafeOnCompleted(System.Action continuation);
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(128), Inherited=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class IndexerNameAttribute : System.Attribute
+ {
+ public IndexerNameAttribute(string indexerName) { }
+ }
+ public partial interface INotifyCompletion
+ {
+ void OnCompleted(System.Action continuation);
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=true, Inherited=false)]
+ public sealed partial class InternalsVisibleToAttribute : System.Attribute
+ {
+ public InternalsVisibleToAttribute(string assemblyName) { }
+ public bool AllInternalsVisible { get { throw null; } set { } }
+ public string AssemblyName { get { throw null; } }
+ }
+ public static partial class IsBoxed
+ {
+ }
+ public static partial class IsByValue
+ {
+ }
+ public static partial class IsConst
+ {
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class IsCopyConstructed
+ {
+ }
+ public static partial class IsExplicitlyDereferenced
+ {
+ }
+ public static partial class IsImplicitlyDereferenced
+ {
+ }
+ public static partial class IsJitIntrinsic
+ {
+ }
+ public static partial class IsLong
+ {
+ }
+ public static partial class IsSignUnspecifiedByte
+ {
+ }
+ public static partial class IsUdtReturn
+ {
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class IsVolatile
+ {
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false, AllowMultiple=false)]
+ public sealed partial class IteratorStateMachineAttribute : System.Runtime.CompilerServices.StateMachineAttribute
+ {
+ public IteratorStateMachineAttribute(System.Type stateMachineType) : base (default(System.Type)) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MethodCodeType
+ {
+ IL = 0,
+ Native = 1,
+ OPTIL = 2,
+ Runtime = 3,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(96), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class MethodImplAttribute : System.Attribute
+ {
+ public System.Runtime.CompilerServices.MethodCodeType MethodCodeType;
+ public MethodImplAttribute() { }
+ public MethodImplAttribute(short value) { }
+ public MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions methodImplOptions) { }
+ public System.Runtime.CompilerServices.MethodImplOptions Value { get { throw null; } }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum MethodImplOptions
+ {
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ AggressiveInlining = 256,
+ ForwardRef = 16,
+ InternalCall = 4096,
+ NoInlining = 8,
+ NoOptimization = 64,
+ PreserveSig = 128,
+ Synchronized = 32,
+ Unmanaged = 4,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(8), Inherited=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class NativeCppClassAttribute : System.Attribute
+ {
+ public NativeCppClassAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false)]
+ public sealed partial class ReferenceAssemblyAttribute : System.Attribute
+ {
+ public ReferenceAssemblyAttribute() { }
+ public ReferenceAssemblyAttribute(string description) { }
+ public string Description { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1052), AllowMultiple=true, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class RequiredAttributeAttribute : System.Attribute
+ {
+ public RequiredAttributeAttribute(System.Type requiredContract) { }
+ public System.Type RequiredContract { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), Inherited=false, AllowMultiple=false)]
+ public sealed partial class RuntimeCompatibilityAttribute : System.Attribute
+ {
+ public RuntimeCompatibilityAttribute() { }
+ public bool WrapNonExceptionThrows { get { throw null; } set { } }
+ }
+ public static partial class RuntimeHelpers
+ {
+ public static int OffsetToStringData { get { throw null; } }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void EnsureSufficientExecutionStack() { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static int GetHashCode(object o) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static object GetObjectValue(object obj) { throw null; }
+ public static object GetUninitializedObject(System.Type type) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void InitializeArray(System.Array array, System.RuntimeFieldHandle fldHandle) { }
+ public static void RunClassConstructor(System.RuntimeTypeHandle type) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(972))]
+ public sealed partial class SpecialNameAttribute : System.Attribute
+ {
+ public SpecialNameAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false, AllowMultiple=false)]
+ public partial class StateMachineAttribute : System.Attribute
+ {
+ public StateMachineAttribute(System.Type stateMachineType) { }
+ public System.Type StateMachineType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ }
+ [System.AttributeUsage((System.AttributeTargets)(1) | (System.AttributeTargets)(2))]
+ public sealed partial class SuppressIldasmAttribute : System.Attribute
+ {
+ public SuppressIldasmAttribute() { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
+ {
+ public bool IsCompleted { get { throw null; } }
+ public void GetResult() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void OnCompleted(System.Action continuation) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void UnsafeOnCompleted(System.Action continuation) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TaskAwaiter<TResult> : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
+ {
+ public bool IsCompleted { get { throw null; } }
+ public TResult GetResult() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void OnCompleted(System.Action continuation) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void UnsafeOnCompleted(System.Action continuation) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5148), Inherited=false, AllowMultiple=false)]
+ public sealed partial class TypeForwardedFromAttribute : System.Attribute
+ {
+ public TypeForwardedFromAttribute(string assemblyFullName) { }
+ public string AssemblyFullName { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=true, Inherited=false)]
+ public sealed partial class TypeForwardedToAttribute : System.Attribute
+ {
+ public TypeForwardedToAttribute(System.Type destination) { }
+ public System.Type Destination { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(8))]
+ public sealed partial class UnsafeValueTypeAttribute : System.Attribute
+ {
+ public UnsafeValueTypeAttribute() { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+ public partial struct YieldAwaitable
+ {
+ public System.Runtime.CompilerServices.YieldAwaitable.YieldAwaiter GetAwaiter() { throw null; }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Size=1)]
+ public partial struct YieldAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
+ {
+ public bool IsCompleted { get { throw null; } }
+ public void GetResult() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void OnCompleted(System.Action continuation) { }
+ [System.Security.SecurityCriticalAttribute]
+ public void UnsafeOnCompleted(System.Action continuation) { }
+ }
+ }
+}
+namespace System.Runtime.ConstrainedExecution
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class CriticalFinalizerObject
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected CriticalFinalizerObject() { }
+ ~CriticalFinalizerObject() { }
+ }
+}
+namespace System.Runtime.ExceptionServices
+{
+ public sealed partial class ExceptionDispatchInfo
+ {
+ internal ExceptionDispatchInfo() { }
+ public System.Exception SourceException { get { throw null; } }
+ public static System.Runtime.ExceptionServices.ExceptionDispatchInfo Capture(System.Exception source) { throw null; }
+ public void Throw() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), AllowMultiple=false, Inherited=false)]
+ public sealed partial class HandleProcessCorruptedStateExceptionsAttribute : System.Attribute
+ {
+ public HandleProcessCorruptedStateExceptionsAttribute() { }
+ }
+}
+namespace System.Runtime.InteropServices
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), AllowMultiple=false, Inherited=false)]
+ public sealed partial class AllowReversePInvokeCallsAttribute : System.Attribute
+ {
+ public AllowReversePInvokeCallsAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ArrayWithOffset
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public ArrayWithOffset(object array, int offset) { throw null;}
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Runtime.InteropServices.ArrayWithOffset obj) { throw null; }
+ public object GetArray() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public int GetOffset() { throw null; }
+ public static bool operator ==(System.Runtime.InteropServices.ArrayWithOffset a, System.Runtime.InteropServices.ArrayWithOffset b) { throw null; }
+ public static bool operator !=(System.Runtime.InteropServices.ArrayWithOffset a, System.Runtime.InteropServices.ArrayWithOffset b) { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1037), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class BestFitMappingAttribute : System.Attribute
+ {
+ public bool ThrowOnUnmappableChar;
+ public BestFitMappingAttribute(bool BestFitMapping) { }
+ public bool BestFitMapping { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class BStrWrapper
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public BStrWrapper(object value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public BStrWrapper(string value) { }
+ public string WrappedObject { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CallingConvention
+ {
+ Cdecl = 2,
+ FastCall = 5,
+ StdCall = 3,
+ ThisCall = 4,
+ Winapi = 1,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CharSet
+ {
+ Ansi = 2,
+ Auto = 4,
+ None = 1,
+ Unicode = 3,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ClassInterfaceAttribute : System.Attribute
+ {
+ public ClassInterfaceAttribute(short classInterfaceType) { }
+ public ClassInterfaceAttribute(System.Runtime.InteropServices.ClassInterfaceType classInterfaceType) { }
+ public System.Runtime.InteropServices.ClassInterfaceType Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ClassInterfaceType
+ {
+ AutoDispatch = 1,
+ AutoDual = 2,
+ None = 0,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1024), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class CoClassAttribute : System.Attribute
+ {
+ public CoClassAttribute(System.Type coClass) { }
+ public System.Type CoClass { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ComDefaultInterfaceAttribute : System.Attribute
+ {
+ public ComDefaultInterfaceAttribute(System.Type defaultInterface) { }
+ public System.Type Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1024), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ComEventInterfaceAttribute : System.Attribute
+ {
+ public ComEventInterfaceAttribute(System.Type SourceInterface, System.Type EventProvider) { }
+ public System.Type EventProvider { get { throw null; } }
+ public System.Type SourceInterface { get { throw null; } }
+ }
+ public static partial class ComEventsHelper
+ {
+ [System.Security.SecurityCriticalAttribute]
+ public static void Combine(object rcw, System.Guid iid, int dispid, System.Delegate d) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Delegate Remove(object rcw, System.Guid iid, int dispid, System.Delegate d) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class COMException : System.Runtime.InteropServices.ExternalException
+ {
+ public COMException() { }
+ public COMException(string message) { }
+ public COMException(string message, System.Exception inner) { }
+ public COMException(string message, int errorCode) { }
+ protected COMException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public override string ToString() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1028), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ComImportAttribute : System.Attribute
+ {
+ public ComImportAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ComInterfaceType
+ {
+ InterfaceIsDual = 0,
+ InterfaceIsIDispatch = 2,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ InterfaceIsIInspectable = 3,
+ InterfaceIsIUnknown = 1,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ComMemberType
+ {
+ Method = 0,
+ PropGet = 1,
+ PropSet = 2,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=true)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ComSourceInterfacesAttribute : System.Attribute
+ {
+ public ComSourceInterfacesAttribute(string sourceInterfaces) { }
+ public ComSourceInterfacesAttribute(System.Type sourceInterface) { }
+ public ComSourceInterfacesAttribute(System.Type sourceInterface1, System.Type sourceInterface2) { }
+ public ComSourceInterfacesAttribute(System.Type sourceInterface1, System.Type sourceInterface2, System.Type sourceInterface3) { }
+ public ComSourceInterfacesAttribute(System.Type sourceInterface1, System.Type sourceInterface2, System.Type sourceInterface3, System.Type sourceInterface4) { }
+ public string Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5597), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ComVisibleAttribute : System.Attribute
+ {
+ public ComVisibleAttribute(bool visibility) { }
+ public bool Value { get { throw null; } }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class CriticalHandle : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable
+ {
+ protected System.IntPtr handle;
+ protected CriticalHandle(System.IntPtr invalidHandleValue) { }
+ public bool IsClosed { get { throw null; } }
+ public abstract bool IsInvalid { get; }
+ [System.Security.SecurityCriticalAttribute]
+ public void Close() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Dispose() { }
+ [System.Security.SecurityCriticalAttribute]
+ protected virtual void Dispose(bool disposing) { }
+ ~CriticalHandle() { }
+ protected abstract bool ReleaseHandle();
+ protected void SetHandle(System.IntPtr handle) { }
+ public void SetHandleAsInvalid() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class CurrencyWrapper
+ {
+ public CurrencyWrapper(decimal obj) { }
+ public CurrencyWrapper(object obj) { }
+ public decimal WrappedObject { get { throw null; } }
+ }
+ public enum CustomQueryInterfaceMode
+ {
+ Allow = 1,
+ Ignore = 0,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public enum CustomQueryInterfaceResult
+ {
+ Failed = 2,
+ Handled = 0,
+ NotHandled = 1,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DefaultCharSetAttribute : System.Attribute
+ {
+ public DefaultCharSetAttribute(System.Runtime.InteropServices.CharSet charSet) { }
+ public System.Runtime.InteropServices.CharSet CharSet { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(65), AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public sealed partial class DefaultDllImportSearchPathsAttribute : System.Attribute
+ {
+ public DefaultDllImportSearchPathsAttribute(System.Runtime.InteropServices.DllImportSearchPath paths) { }
+ public System.Runtime.InteropServices.DllImportSearchPath Paths { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DispatchWrapper
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public DispatchWrapper(object obj) { }
+ public object WrappedObject { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(960), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DispIdAttribute : System.Attribute
+ {
+ public DispIdAttribute(int dispId) { }
+ public int Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class DllImportAttribute : System.Attribute
+ {
+ public bool BestFitMapping;
+ public System.Runtime.InteropServices.CallingConvention CallingConvention;
+ public System.Runtime.InteropServices.CharSet CharSet;
+ public string EntryPoint;
+ public bool ExactSpelling;
+ public bool PreserveSig;
+ public bool SetLastError;
+ public bool ThrowOnUnmappableChar;
+ public DllImportAttribute(string dllName) { }
+ public string Value { get { throw null; } }
+ }
+ [System.FlagsAttribute]
+ public enum DllImportSearchPath
+ {
+ ApplicationDirectory = 512,
+ AssemblyDirectory = 2,
+ LegacyBehavior = 0,
+ SafeDirectories = 4096,
+ System32 = 2048,
+ UseDllDirectoryForDependencies = 256,
+ UserDirectories = 1024,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ErrorWrapper
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public ErrorWrapper(System.Exception e) { }
+ public ErrorWrapper(int errorCode) { }
+ public ErrorWrapper(object errorCode) { }
+ public int ErrorCode { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ExternalException : System.SystemException
+ {
+ public ExternalException() { }
+ protected ExternalException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public ExternalException(string message) { }
+ public ExternalException(string message, System.Exception inner) { }
+ public ExternalException(string message, int errorCode) { }
+ public virtual int ErrorCode { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class FieldOffsetAttribute : System.Attribute
+ {
+ public FieldOffsetAttribute(int offset) { }
+ public int Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct GCHandle
+ {
+ public bool IsAllocated { get { throw null; } }
+ public object Target { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ [System.Security.SecurityCriticalAttribute]
+ public System.IntPtr AddrOfPinnedObject() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.InteropServices.GCHandle Alloc(object value) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.InteropServices.GCHandle Alloc(object value, System.Runtime.InteropServices.GCHandleType type) { throw null; }
+ public override bool Equals(object o) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public void Free() { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.InteropServices.GCHandle FromIntPtr(System.IntPtr value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Runtime.InteropServices.GCHandle a, System.Runtime.InteropServices.GCHandle b) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static explicit operator System.Runtime.InteropServices.GCHandle (System.IntPtr value) { throw null; }
+ public static explicit operator System.IntPtr (System.Runtime.InteropServices.GCHandle value) { throw null; }
+ public static bool operator !=(System.Runtime.InteropServices.GCHandle a, System.Runtime.InteropServices.GCHandle b) { throw null; }
+ public static System.IntPtr ToIntPtr(System.Runtime.InteropServices.GCHandle value) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum GCHandleType
+ {
+ Normal = 2,
+ Pinned = 3,
+ Weak = 0,
+ WeakTrackResurrection = 1,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5149), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class GuidAttribute : System.Attribute
+ {
+ public GuidAttribute(string guid) { }
+ public string Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ICustomAdapter
+ {
+ object GetUnderlyingObject();
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial interface ICustomQueryInterface
+ {
+ [System.Security.SecurityCriticalAttribute]
+ System.Runtime.InteropServices.CustomQueryInterfaceResult GetInterface(ref System.Guid iid, out System.IntPtr ppv);
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class InAttribute : System.Attribute
+ {
+ public InAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1024), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class InterfaceTypeAttribute : System.Attribute
+ {
+ public InterfaceTypeAttribute(short interfaceType) { }
+ public InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType interfaceType) { }
+ public System.Runtime.InteropServices.ComInterfaceType Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class InvalidComObjectException : System.SystemException
+ {
+ public InvalidComObjectException() { }
+ public InvalidComObjectException(string message) { }
+ public InvalidComObjectException(string message, System.Exception inner) { }
+ protected InvalidComObjectException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class InvalidOleVariantTypeException : System.SystemException
+ {
+ public InvalidOleVariantTypeException() { }
+ public InvalidOleVariantTypeException(string message) { }
+ public InvalidOleVariantTypeException(string message, System.Exception inner) { }
+ protected InvalidOleVariantTypeException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum LayoutKind
+ {
+ Auto = 3,
+ Explicit = 2,
+ Sequential = 0,
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public static partial class Marshal
+ {
+ public static readonly int SystemDefaultCharSize;
+ public static readonly int SystemMaxDBCSCharSize;
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int AddRef(System.IntPtr pUnk) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr AllocCoTaskMem(int cb) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr AllocHGlobal(int cb) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr AllocHGlobal(System.IntPtr cb) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static bool AreComObjectsAvailableForCleanup() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(byte[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(char[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(double[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(short[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(int[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(long[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, byte[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, char[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, double[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, short[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, int[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, long[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, System.IntPtr[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr source, float[] destination, int startIndex, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(System.IntPtr[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Copy(float[] source, int startIndex, System.IntPtr destination, int length) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr CreateAggregatedObject(System.IntPtr pOuter, object o) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr CreateAggregatedObject<T>(System.IntPtr pOuter, T o) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static object CreateWrapperOfType(object o, System.Type t) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static TWrapper CreateWrapperOfType<T, TWrapper>(T o) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public static void DestroyStructure(System.IntPtr ptr, System.Type structuretype) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void DestroyStructure<T>(System.IntPtr ptr) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static int FinalReleaseComObject(object o) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void FreeBSTR(System.IntPtr ptr) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void FreeCoTaskMem(System.IntPtr ptr) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void FreeHGlobal(System.IntPtr hglobal) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject(object o, System.Type T) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject(object o, System.Type T, System.Runtime.InteropServices.CustomQueryInterfaceMode mode) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject<T, TInterface>(T o) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Delegate GetDelegateForFunctionPointer(System.IntPtr ptr, System.Type t) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static TDelegate GetDelegateForFunctionPointer<TDelegate>(System.IntPtr ptr) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int GetExceptionCode() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Exception GetExceptionForHR(int errorCode) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Exception GetExceptionForHR(int errorCode, System.IntPtr errorInfo) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetFunctionPointerForDelegate(System.Delegate d) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int GetHRForException(System.Exception e) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static int GetHRForLastWin32Error() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetIUnknownForObject(object o) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int GetLastWin32Error() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static void GetNativeVariantForObject(object obj, System.IntPtr pDstNativeVariant) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void GetNativeVariantForObject<T>(T obj, System.IntPtr pDstNativeVariant) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static object GetObjectForIUnknown(System.IntPtr pUnk) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static object GetObjectForNativeVariant(System.IntPtr pSrcNativeVariant) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static T GetObjectForNativeVariant<T>(System.IntPtr pSrcNativeVariant) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static object[] GetObjectsForNativeVariants(System.IntPtr aSrcNativeVariant, int cVars) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static T[] GetObjectsForNativeVariants<T>(System.IntPtr aSrcNativeVariant, int cVars) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int GetStartComSlot(System.Type t) { throw null; }
+ public static System.Type GetTypeFromCLSID(System.Guid clsid) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string GetTypeInfoName(System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static object GetUniqueObjectForIUnknown(System.IntPtr unknown) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]public static bool IsComObject(object o) { throw null; }
+ public static System.IntPtr OffsetOf(System.Type t, string fieldName) { throw null; }
+ public static System.IntPtr OffsetOf<T>(string fieldName) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void Prelink(System.Reflection.MethodInfo m) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void PrelinkAll(System.Type c) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringAnsi(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringAnsi(System.IntPtr ptr, int len) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringBSTR(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringUni(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringUni(System.IntPtr ptr, int len) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringUTF8(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringUTF8(System.IntPtr ptr, int byteLen) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public static void PtrToStructure(System.IntPtr ptr, object structure) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public static object PtrToStructure(System.IntPtr ptr, System.Type structureType) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static T PtrToStructure<T>(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void PtrToStructure<T>(System.IntPtr ptr, T structure) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int QueryInterface(System.IntPtr pUnk, ref System.Guid iid, out System.IntPtr ppv) { ppv = default(System.IntPtr); throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static byte ReadByte(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static byte ReadByte(System.IntPtr ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static byte ReadByte(object ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static short ReadInt16(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static short ReadInt16(System.IntPtr ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static short ReadInt16(object ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static int ReadInt32(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static int ReadInt32(System.IntPtr ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static int ReadInt32(object ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static long ReadInt64(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static long ReadInt64(System.IntPtr ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static long ReadInt64(object ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr ReadIntPtr(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr ReadIntPtr(System.IntPtr ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr ReadIntPtr(object ptr, int ofs) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr ReAllocCoTaskMem(System.IntPtr pv, int cb) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr ReAllocHGlobal(System.IntPtr pv, System.IntPtr cb) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static int Release(System.IntPtr pUnk) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static int ReleaseComObject(object o) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static int SizeOf(object structure) { throw null; }
+ public static int SizeOf(System.Type t) { throw null; }
+ public static int SizeOf<T>() { throw null; }
+ public static int SizeOf<T>(T structure) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToBSTR(string s) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToCoTaskMemAnsi(string s) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToCoTaskMemUni(string s) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToCoTaskMemUTF8(string s) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToHGlobalAnsi(string s) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToHGlobalUni(string s) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public static void StructureToPtr(object structure, System.IntPtr ptr, bool fDeleteOld) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void StructureToPtr<T>(T structure, System.IntPtr ptr, bool fDeleteOld) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ThrowExceptionForHR(int errorCode) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ThrowExceptionForHR(int errorCode, System.IntPtr errorInfo) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr UnsafeAddrOfPinnedArrayElement(System.Array arr, int index) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteByte(System.IntPtr ptr, byte val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteByte(System.IntPtr ptr, int ofs, byte val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteByte(object ptr, int ofs, byte val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(System.IntPtr ptr, char val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(System.IntPtr ptr, short val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(System.IntPtr ptr, int ofs, char val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(System.IntPtr ptr, int ofs, short val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(object ptr, int ofs, char val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt16(object ptr, int ofs, short val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt32(System.IntPtr ptr, int val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt32(System.IntPtr ptr, int ofs, int val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt32(object ptr, int ofs, int val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt64(System.IntPtr ptr, int ofs, long val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt64(System.IntPtr ptr, long val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteInt64(object ptr, int ofs, long val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteIntPtr(System.IntPtr ptr, int ofs, System.IntPtr val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteIntPtr(System.IntPtr ptr, System.IntPtr val) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void WriteIntPtr(object ptr, int ofs, System.IntPtr val) { ptr = default(object); }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeBSTR(System.IntPtr s) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeCoTaskMemAnsi(System.IntPtr s) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeCoTaskMemUnicode(System.IntPtr s) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeCoTaskMemUTF8(System.IntPtr s) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeGlobalAllocAnsi(System.IntPtr s) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeGlobalAllocUnicode(System.IntPtr s) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(10496), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class MarshalAsAttribute : System.Attribute
+ {
+ public System.Runtime.InteropServices.UnmanagedType ArraySubType;
+ public int IidParameterIndex;
+ public string MarshalCookie;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public string MarshalType;
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public System.Type MarshalTypeRef;
+ public System.Runtime.InteropServices.VarEnum SafeArraySubType;
+ public System.Type SafeArrayUserDefinedSubType;
+ public int SizeConst;
+ public short SizeParamIndex;
+ public MarshalAsAttribute(short unmanagedType) { }
+ public MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType unmanagedType) { }
+ public System.Runtime.InteropServices.UnmanagedType Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class MarshalDirectiveException : System.SystemException
+ {
+ public MarshalDirectiveException() { }
+ public MarshalDirectiveException(string message) { }
+ public MarshalDirectiveException(string message, System.Exception inner) { }
+ protected MarshalDirectiveException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64))]
+ public sealed partial class NativeCallableAttribute : System.Attribute
+ {
+ public System.Runtime.InteropServices.CallingConvention CallingConvention;
+ public string EntryPoint;
+ public NativeCallableAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OptionalAttribute : System.Attribute
+ {
+ public OptionalAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OutAttribute : System.Attribute
+ {
+ public OutAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class PreserveSigAttribute : System.Attribute
+ {
+ public PreserveSigAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class RuntimeEnvironment
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string GetRuntimeDirectory() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SafeArrayRankMismatchException : System.SystemException
+ {
+ public SafeArrayRankMismatchException() { }
+ public SafeArrayRankMismatchException(string message) { }
+ public SafeArrayRankMismatchException(string message, System.Exception inner) { }
+ protected SafeArrayRankMismatchException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SafeArrayTypeMismatchException : System.SystemException
+ {
+ public SafeArrayTypeMismatchException() { }
+ public SafeArrayTypeMismatchException(string message) { }
+ public SafeArrayTypeMismatchException(string message, System.Exception inner) { }
+ protected SafeArrayTypeMismatchException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class SafeBuffer : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
+ {
+ protected SafeBuffer(bool ownsHandle) : base(ownsHandle) { }
+ [System.CLSCompliantAttribute(false)]
+ public ulong ByteLength { get { throw null; } }
+ [System.CLSCompliantAttribute(false)]
+ public unsafe void AcquirePointer(ref byte* pointer) { }
+ [System.CLSCompliantAttribute(false)]
+ public void Initialize(uint numElements, uint sizeOfEachElement) { }
+ [System.CLSCompliantAttribute(false)]
+ public void Initialize(ulong numBytes) { }
+ [System.CLSCompliantAttribute(false)]
+ public void Initialize<T>(uint numElements) where T : struct { }
+ [System.CLSCompliantAttribute(false)]
+ public T Read<T>(ulong byteOffset) where T : struct { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public void ReadArray<T>(ulong byteOffset, T[] array, int index, int count) where T : struct { }
+ public void ReleasePointer() { }
+ [System.CLSCompliantAttribute(false)]
+ public void Write<T>(ulong byteOffset, T value) where T : struct { }
+ [System.CLSCompliantAttribute(false)]
+ public void WriteArray<T>(ulong byteOffset, T[] array, int index, int count) where T : struct { }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class SafeHandle : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable
+ {
+ protected System.IntPtr handle;
+ protected SafeHandle() { }
+ protected SafeHandle(System.IntPtr invalidHandleValue, bool ownsHandle) { }
+ public bool IsClosed { get { throw null; } }
+ public abstract bool IsInvalid { get; }
+ [System.Security.SecurityCriticalAttribute]
+ public void Close() { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public void DangerousAddRef(ref bool success) { }
+ public System.IntPtr DangerousGetHandle() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public void DangerousRelease() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Dispose() { }
+ [System.Security.SecurityCriticalAttribute]
+ protected virtual void Dispose(bool disposing) { }
+ ~SafeHandle() { }
+ protected abstract bool ReleaseHandle();
+ protected void SetHandle(System.IntPtr handle) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecurityCriticalAttribute]
+ public void SetHandleAsInvalid() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SEHException : System.Runtime.InteropServices.ExternalException
+ {
+ public SEHException() { }
+ public SEHException(string message) { }
+ public SEHException(string message, System.Exception inner) { }
+ protected SEHException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public virtual bool CanResume() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(12), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class StructLayoutAttribute : System.Attribute
+ {
+ public System.Runtime.InteropServices.CharSet CharSet;
+ public int Pack;
+ public int Size;
+ public StructLayoutAttribute(short layoutKind) { }
+ public StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind layoutKind) { }
+ public System.Runtime.InteropServices.LayoutKind Value { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5144), AllowMultiple=false, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public sealed partial class TypeIdentifierAttribute : System.Attribute
+ {
+ public TypeIdentifierAttribute() { }
+ public TypeIdentifierAttribute(string scope, string identifier) { }
+ public string Identifier { get { throw null; } }
+ public string Scope { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class UnknownWrapper
+ {
+ public UnknownWrapper(object obj) { }
+ public object WrappedObject { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(4096), AllowMultiple=false, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class UnmanagedFunctionPointerAttribute : System.Attribute
+ {
+ public bool BestFitMapping;
+ public System.Runtime.InteropServices.CharSet CharSet;
+ public bool SetLastError;
+ public bool ThrowOnUnmappableChar;
+ public UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention callingConvention) { }
+ public System.Runtime.InteropServices.CallingConvention CallingConvention { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum UnmanagedType
+ {
+ AnsiBStr = 35,
+ AsAny = 40,
+ Bool = 2,
+ BStr = 19,
+ ByValArray = 30,
+ ByValTStr = 23,
+ Currency = 15,
+ CustomMarshaler = 44,
+ Error = 45,
+ FunctionPtr = 38,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ HString = 47,
+ I1 = 3,
+ I2 = 5,
+ I4 = 7,
+ I8 = 9,
+ IDispatch = 26,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ IInspectable = 46,
+ Interface = 28,
+ IUnknown = 25,
+ LPArray = 42,
+ LPStr = 20,
+ LPStruct = 43,
+ LPTStr = 22,
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ LPUTF8Str = 48,
+ LPWStr = 21,
+ R4 = 11,
+ R8 = 12,
+ SafeArray = 29,
+ Struct = 27,
+ SysInt = 31,
+ SysUInt = 32,
+ TBStr = 36,
+ U1 = 4,
+ U2 = 6,
+ U4 = 8,
+ U8 = 10,
+ VariantBool = 37,
+ VBByRefStr = 34,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum VarEnum
+ {
+ VT_ARRAY = 8192,
+ VT_BLOB = 65,
+ VT_BLOB_OBJECT = 70,
+ VT_BOOL = 11,
+ VT_BSTR = 8,
+ VT_BYREF = 16384,
+ VT_CARRAY = 28,
+ VT_CF = 71,
+ VT_CLSID = 72,
+ VT_CY = 6,
+ VT_DATE = 7,
+ VT_DECIMAL = 14,
+ VT_DISPATCH = 9,
+ VT_EMPTY = 0,
+ VT_ERROR = 10,
+ VT_FILETIME = 64,
+ VT_HRESULT = 25,
+ VT_I1 = 16,
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_I8 = 20,
+ VT_INT = 22,
+ VT_LPSTR = 30,
+ VT_LPWSTR = 31,
+ VT_NULL = 1,
+ VT_PTR = 26,
+ VT_R4 = 4,
+ VT_R8 = 5,
+ VT_RECORD = 36,
+ VT_SAFEARRAY = 27,
+ VT_STORAGE = 67,
+ VT_STORED_OBJECT = 69,
+ VT_STREAM = 66,
+ VT_STREAMED_OBJECT = 68,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_UI8 = 21,
+ VT_UINT = 23,
+ VT_UNKNOWN = 13,
+ VT_USERDEFINED = 29,
+ VT_VARIANT = 12,
+ VT_VECTOR = 4096,
+ VT_VOID = 24,
+ }
+ public sealed partial class VariantWrapper
+ {
+ public VariantWrapper(object obj) { }
+ public object WrappedObject { get { throw null; } }
+ }
+}
+namespace System.Runtime.InteropServices.ComTypes
+{
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct BIND_OPTS
+ {
+ public int cbStruct;
+ public int dwTickCountDeadline;
+ public int grfFlags;
+ public int grfMode;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
+ public partial struct BINDPTR
+ {
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.IntPtr lpfuncdesc;
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.IntPtr lptcomp;
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.IntPtr lpvardesc;
+ }
+ public enum CALLCONV
+ {
+ CC_CDECL = 1,
+ CC_MACPASCAL = 3,
+ CC_MAX = 9,
+ CC_MPWCDECL = 7,
+ CC_MPWPASCAL = 8,
+ CC_MSCPASCAL = 2,
+ CC_PASCAL = 2,
+ CC_RESERVED = 5,
+ CC_STDCALL = 4,
+ CC_SYSCALL = 6,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct CONNECTDATA
+ {
+ public int dwCookie;
+ public object pUnk;
+ }
+ public enum DESCKIND
+ {
+ DESCKIND_FUNCDESC = 1,
+ DESCKIND_IMPLICITAPPOBJ = 4,
+ DESCKIND_MAX = 5,
+ DESCKIND_NONE = 0,
+ DESCKIND_TYPECOMP = 3,
+ DESCKIND_VARDESC = 2,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct DISPPARAMS
+ {
+ public int cArgs;
+ public int cNamedArgs;
+ public System.IntPtr rgdispidNamedArgs;
+ public System.IntPtr rgvarg;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct ELEMDESC
+ {
+ public System.Runtime.InteropServices.ComTypes.ELEMDESC.DESCUNION desc;
+ public System.Runtime.InteropServices.ComTypes.TYPEDESC tdesc;
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
+ public partial struct DESCUNION
+ {
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.Runtime.InteropServices.ComTypes.IDLDESC idldesc;
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.Runtime.InteropServices.ComTypes.PARAMDESC paramdesc;
+ }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct EXCEPINFO
+ {
+ public string bstrDescription;
+ public string bstrHelpFile;
+ public string bstrSource;
+ public int dwHelpContext;
+ public System.IntPtr pfnDeferredFillIn;
+ public System.IntPtr pvReserved;
+ public int scode;
+ public short wCode;
+ public short wReserved;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct FILETIME
+ {
+ public int dwHighDateTime;
+ public int dwLowDateTime;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct FUNCDESC
+ {
+ public System.Runtime.InteropServices.ComTypes.CALLCONV callconv;
+ public short cParams;
+ public short cParamsOpt;
+ public short cScodes;
+ public System.Runtime.InteropServices.ComTypes.ELEMDESC elemdescFunc;
+ public System.Runtime.InteropServices.ComTypes.FUNCKIND funckind;
+ public System.Runtime.InteropServices.ComTypes.INVOKEKIND invkind;
+ public System.IntPtr lprgelemdescParam;
+ public System.IntPtr lprgscode;
+ public int memid;
+ public short oVft;
+ public short wFuncFlags;
+ }
+ [System.FlagsAttribute]
+ public enum FUNCFLAGS : short
+ {
+ FUNCFLAG_FBINDABLE = (short)4,
+ FUNCFLAG_FDEFAULTBIND = (short)32,
+ FUNCFLAG_FDEFAULTCOLLELEM = (short)256,
+ FUNCFLAG_FDISPLAYBIND = (short)16,
+ FUNCFLAG_FHIDDEN = (short)64,
+ FUNCFLAG_FIMMEDIATEBIND = (short)4096,
+ FUNCFLAG_FNONBROWSABLE = (short)1024,
+ FUNCFLAG_FREPLACEABLE = (short)2048,
+ FUNCFLAG_FREQUESTEDIT = (short)8,
+ FUNCFLAG_FRESTRICTED = (short)1,
+ FUNCFLAG_FSOURCE = (short)2,
+ FUNCFLAG_FUIDEFAULT = (short)512,
+ FUNCFLAG_FUSESGETLASTERROR = (short)128,
+ }
+ public enum FUNCKIND
+ {
+ FUNC_DISPATCH = 4,
+ FUNC_NONVIRTUAL = 2,
+ FUNC_PUREVIRTUAL = 1,
+ FUNC_STATIC = 3,
+ FUNC_VIRTUAL = 0,
+ }
+ [System.Runtime.InteropServices.GuidAttribute("0000000e-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IBindCtx
+ {
+ void EnumObjectParam(out System.Runtime.InteropServices.ComTypes.IEnumString ppenum);
+ void GetBindOptions(ref System.Runtime.InteropServices.ComTypes.BIND_OPTS pbindopts);
+ void GetObjectParam(string pszKey, out object ppunk);
+ void GetRunningObjectTable(out System.Runtime.InteropServices.ComTypes.IRunningObjectTable pprot);
+ void RegisterObjectBound(object punk);
+ void RegisterObjectParam(string pszKey, object punk);
+ void ReleaseBoundObjects();
+ void RevokeObjectBound(object punk);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int RevokeObjectParam(string pszKey);
+ void SetBindOptions(ref System.Runtime.InteropServices.ComTypes.BIND_OPTS pbindopts);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("B196B286-BAB4-101A-B69C-00AA00341D07")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IConnectionPoint
+ {
+ void Advise(object pUnkSink, out int pdwCookie);
+ void EnumConnections(out System.Runtime.InteropServices.ComTypes.IEnumConnections ppEnum);
+ void GetConnectionInterface(out System.Guid pIID);
+ void GetConnectionPointContainer(out System.Runtime.InteropServices.ComTypes.IConnectionPointContainer ppCPC);
+ void Unadvise(int dwCookie);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("B196B284-BAB4-101A-B69C-00AA00341D07")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IConnectionPointContainer
+ {
+ void EnumConnectionPoints(out System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints ppEnum);
+ void FindConnectionPoint(ref System.Guid riid, out System.Runtime.InteropServices.ComTypes.IConnectionPoint ppCP);
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct IDLDESC
+ {
+ public System.IntPtr dwReserved;
+ public System.Runtime.InteropServices.ComTypes.IDLFLAG wIDLFlags;
+ }
+ [System.FlagsAttribute]
+ public enum IDLFLAG : short
+ {
+ IDLFLAG_FIN = (short)1,
+ IDLFLAG_FLCID = (short)4,
+ IDLFLAG_FOUT = (short)2,
+ IDLFLAG_FRETVAL = (short)8,
+ IDLFLAG_NONE = (short)0,
+ }
+ [System.Runtime.InteropServices.GuidAttribute("B196B285-BAB4-101A-B69C-00AA00341D07")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IEnumConnectionPoints
+ {
+ void Clone(out System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints ppenum);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Next(int celt, System.Runtime.InteropServices.ComTypes.IConnectionPoint[] rgelt, System.IntPtr pceltFetched);
+ void Reset();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Skip(int celt);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("B196B287-BAB4-101A-B69C-00AA00341D07")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IEnumConnections
+ {
+ void Clone(out System.Runtime.InteropServices.ComTypes.IEnumConnections ppenum);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Next(int celt, System.Runtime.InteropServices.ComTypes.CONNECTDATA[] rgelt, System.IntPtr pceltFetched);
+ void Reset();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Skip(int celt);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00000102-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IEnumMoniker
+ {
+ void Clone(out System.Runtime.InteropServices.ComTypes.IEnumMoniker ppenum);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Next(int celt, System.Runtime.InteropServices.ComTypes.IMoniker[] rgelt, System.IntPtr pceltFetched);
+ void Reset();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Skip(int celt);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00000101-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IEnumString
+ {
+ void Clone(out System.Runtime.InteropServices.ComTypes.IEnumString ppenum);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Next(int celt, string[] rgelt, System.IntPtr pceltFetched);
+ void Reset();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Skip(int celt);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020404-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IEnumVARIANT
+ {
+ System.Runtime.InteropServices.ComTypes.IEnumVARIANT Clone();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Next(int celt, object[] rgVar, System.IntPtr pceltFetched);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Reset();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int Skip(int celt);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("0000000f-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IMoniker
+ {
+ void BindToObject(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, ref System.Guid riidResult, out object ppvResult);
+ void BindToStorage(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, ref System.Guid riid, out object ppvObj);
+ void CommonPrefixWith(System.Runtime.InteropServices.ComTypes.IMoniker pmkOther, out System.Runtime.InteropServices.ComTypes.IMoniker ppmkPrefix);
+ void ComposeWith(System.Runtime.InteropServices.ComTypes.IMoniker pmkRight, bool fOnlyIfNotGeneric, out System.Runtime.InteropServices.ComTypes.IMoniker ppmkComposite);
+ void Enum(bool fForward, out System.Runtime.InteropServices.ComTypes.IEnumMoniker ppenumMoniker);
+ void GetClassID(out System.Guid pClassID);
+ void GetDisplayName(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, out string ppszDisplayName);
+ void GetSizeMax(out long pcbSize);
+ void GetTimeOfLastChange(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, out System.Runtime.InteropServices.ComTypes.FILETIME pFileTime);
+ void Hash(out int pdwHash);
+ void Inverse(out System.Runtime.InteropServices.ComTypes.IMoniker ppmk);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsDirty();
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsEqual(System.Runtime.InteropServices.ComTypes.IMoniker pmkOtherMoniker);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsRunning(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, System.Runtime.InteropServices.ComTypes.IMoniker pmkNewlyRunning);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsSystemMoniker(out int pdwMksys);
+ void Load(System.Runtime.InteropServices.ComTypes.IStream pStm);
+ void ParseDisplayName(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, string pszDisplayName, out int pchEaten, out System.Runtime.InteropServices.ComTypes.IMoniker ppmkOut);
+ void Reduce(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, int dwReduceHowFar, ref System.Runtime.InteropServices.ComTypes.IMoniker ppmkToLeft, out System.Runtime.InteropServices.ComTypes.IMoniker ppmkReduced);
+ void RelativePathTo(System.Runtime.InteropServices.ComTypes.IMoniker pmkOther, out System.Runtime.InteropServices.ComTypes.IMoniker ppmkRelPath);
+ void Save(System.Runtime.InteropServices.ComTypes.IStream pStm, bool fClearDirty);
+ }
+ [System.FlagsAttribute]
+ public enum IMPLTYPEFLAGS
+ {
+ IMPLTYPEFLAG_FDEFAULT = 1,
+ IMPLTYPEFLAG_FDEFAULTVTABLE = 8,
+ IMPLTYPEFLAG_FRESTRICTED = 4,
+ IMPLTYPEFLAG_FSOURCE = 2,
+ }
+ [System.FlagsAttribute]
+ public enum INVOKEKIND
+ {
+ INVOKE_FUNC = 1,
+ INVOKE_PROPERTYGET = 2,
+ INVOKE_PROPERTYPUT = 4,
+ INVOKE_PROPERTYPUTREF = 8,
+ }
+ [System.Runtime.InteropServices.GuidAttribute("0000010b-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IPersistFile
+ {
+ void GetClassID(out System.Guid pClassID);
+ void GetCurFile(out string ppszFileName);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsDirty();
+ void Load(string pszFileName, int dwMode);
+ void Save(string pszFileName, bool fRemember);
+ void SaveCompleted(string pszFileName);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00000010-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IRunningObjectTable
+ {
+ void EnumRunning(out System.Runtime.InteropServices.ComTypes.IEnumMoniker ppenumMoniker);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int GetObject(System.Runtime.InteropServices.ComTypes.IMoniker pmkObjectName, out object ppunkObject);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int GetTimeOfLastChange(System.Runtime.InteropServices.ComTypes.IMoniker pmkObjectName, out System.Runtime.InteropServices.ComTypes.FILETIME pfiletime);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int IsRunning(System.Runtime.InteropServices.ComTypes.IMoniker pmkObjectName);
+ void NoteChangeTime(int dwRegister, ref System.Runtime.InteropServices.ComTypes.FILETIME pfiletime);
+ int Register(int grfFlags, object punkObject, System.Runtime.InteropServices.ComTypes.IMoniker pmkObjectName);
+ void Revoke(int dwRegister);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("0000000c-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface IStream
+ {
+ void Clone(out System.Runtime.InteropServices.ComTypes.IStream ppstm);
+ void Commit(int grfCommitFlags);
+ void CopyTo(System.Runtime.InteropServices.ComTypes.IStream pstm, long cb, System.IntPtr pcbRead, System.IntPtr pcbWritten);
+ void LockRegion(long libOffset, long cb, int dwLockType);
+ void Read(byte[] pv, int cb, System.IntPtr pcbRead);
+ void Revert();
+ void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPosition);
+ void SetSize(long libNewSize);
+ void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag);
+ void UnlockRegion(long libOffset, long cb, int dwLockType);
+ void Write(byte[] pv, int cb, System.IntPtr pcbWritten);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020403-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface ITypeComp
+ {
+ void Bind(string szName, int lHashVal, short wFlags, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo, out System.Runtime.InteropServices.ComTypes.DESCKIND pDescKind, out System.Runtime.InteropServices.ComTypes.BINDPTR pBindPtr);
+ void BindType(string szName, int lHashVal, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo, out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020401-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface ITypeInfo
+ {
+ void AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out System.IntPtr ppv);
+ void CreateInstance(object pUnkOuter, ref System.Guid riid, out object ppvObj);
+ void GetContainingTypeLib(out System.Runtime.InteropServices.ComTypes.ITypeLib ppTLB, out int pIndex);
+ void GetDllEntry(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, System.IntPtr pBstrDllName, System.IntPtr pBstrName, System.IntPtr pwOrdinal);
+ void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
+ void GetFuncDesc(int index, out System.IntPtr ppFuncDesc);
+ void GetIDsOfNames(string[] rgszNames, int cNames, int[] pMemId);
+ void GetImplTypeFlags(int index, out System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS pImplTypeFlags);
+ void GetMops(int memid, out string pBstrMops);
+ void GetNames(int memid, string[] rgBstrNames, int cMaxNames, out int pcNames);
+ void GetRefTypeInfo(int hRef, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTI);
+ void GetRefTypeOfImplType(int index, out int href);
+ void GetTypeAttr(out System.IntPtr ppTypeAttr);
+ void GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
+ void GetVarDesc(int index, out System.IntPtr ppVarDesc);
+ void Invoke(object pvInstance, int memid, short wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, System.IntPtr pVarResult, System.IntPtr pExcepInfo, out int puArgErr);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]void ReleaseFuncDesc(System.IntPtr pFuncDesc);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]void ReleaseTypeAttr(System.IntPtr pTypeAttr);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]void ReleaseVarDesc(System.IntPtr pVarDesc);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020412-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface ITypeInfo2 : System.Runtime.InteropServices.ComTypes.ITypeInfo
+ {
+ new void AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out System.IntPtr ppv);
+ new void CreateInstance(object pUnkOuter, ref System.Guid riid, out object ppvObj);
+ void GetAllCustData(System.IntPtr pCustData);
+ void GetAllFuncCustData(int index, System.IntPtr pCustData);
+ void GetAllImplTypeCustData(int index, System.IntPtr pCustData);
+ void GetAllParamCustData(int indexFunc, int indexParam, System.IntPtr pCustData);
+ void GetAllVarCustData(int index, System.IntPtr pCustData);
+ new void GetContainingTypeLib(out System.Runtime.InteropServices.ComTypes.ITypeLib ppTLB, out int pIndex);
+ void GetCustData(ref System.Guid guid, out object pVarVal);
+ new void GetDllEntry(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, System.IntPtr pBstrDllName, System.IntPtr pBstrName, System.IntPtr pwOrdinal);
+ new void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
+ void GetDocumentation2(int memid, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
+ void GetFuncCustData(int index, ref System.Guid guid, out object pVarVal);
+ new void GetFuncDesc(int index, out System.IntPtr ppFuncDesc);
+ void GetFuncIndexOfMemId(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out int pFuncIndex);
+ new void GetIDsOfNames(string[] rgszNames, int cNames, int[] pMemId);
+ void GetImplTypeCustData(int index, ref System.Guid guid, out object pVarVal);
+ new void GetImplTypeFlags(int index, out System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS pImplTypeFlags);
+ new void GetMops(int memid, out string pBstrMops);
+ new void GetNames(int memid, string[] rgBstrNames, int cMaxNames, out int pcNames);
+ void GetParamCustData(int indexFunc, int indexParam, ref System.Guid guid, out object pVarVal);
+ new void GetRefTypeInfo(int hRef, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTI);
+ new void GetRefTypeOfImplType(int index, out int href);
+ new void GetTypeAttr(out System.IntPtr ppTypeAttr);
+ new void GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
+ void GetTypeFlags(out int pTypeFlags);
+ void GetTypeKind(out System.Runtime.InteropServices.ComTypes.TYPEKIND pTypeKind);
+ void GetVarCustData(int index, ref System.Guid guid, out object pVarVal);
+ new void GetVarDesc(int index, out System.IntPtr ppVarDesc);
+ void GetVarIndexOfMemId(int memid, out int pVarIndex);
+ new void Invoke(object pvInstance, int memid, short wFlags, ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, System.IntPtr pVarResult, System.IntPtr pExcepInfo, out int puArgErr);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]new void ReleaseFuncDesc(System.IntPtr pFuncDesc);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]new void ReleaseTypeAttr(System.IntPtr pTypeAttr);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]new void ReleaseVarDesc(System.IntPtr pVarDesc);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020402-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface ITypeLib
+ {
+ void FindName(string szNameBuf, int lHashVal, System.Runtime.InteropServices.ComTypes.ITypeInfo[] ppTInfo, int[] rgMemId, ref short pcFound);
+ void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
+ void GetLibAttr(out System.IntPtr ppTLibAttr);
+ void GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
+ void GetTypeInfo(int index, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTI);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]int GetTypeInfoCount();
+ void GetTypeInfoOfGuid(ref System.Guid guid, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo);
+ void GetTypeInfoType(int index, out System.Runtime.InteropServices.ComTypes.TYPEKIND pTKind);
+ bool IsName(string szNameBuf, int lHashVal);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]void ReleaseTLibAttr(System.IntPtr pTLibAttr);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00020411-0000-0000-C000-000000000046")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ public partial interface ITypeLib2 : System.Runtime.InteropServices.ComTypes.ITypeLib
+ {
+ new void FindName(string szNameBuf, int lHashVal, System.Runtime.InteropServices.ComTypes.ITypeInfo[] ppTInfo, int[] rgMemId, ref short pcFound);
+ void GetAllCustData(System.IntPtr pCustData);
+ void GetCustData(ref System.Guid guid, out object pVarVal);
+ new void GetDocumentation(int index, out string strName, out string strDocString, out int dwHelpContext, out string strHelpFile);
+ void GetDocumentation2(int index, out string pbstrHelpString, out int pdwHelpStringContext, out string pbstrHelpStringDll);
+ new void GetLibAttr(out System.IntPtr ppTLibAttr);
+ void GetLibStatistics(System.IntPtr pcUniqueNames, out int pcchUniqueNames);
+ new void GetTypeComp(out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp);
+ new void GetTypeInfo(int index, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTI);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]new int GetTypeInfoCount();
+ new void GetTypeInfoOfGuid(ref System.Guid guid, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo);
+ new void GetTypeInfoType(int index, out System.Runtime.InteropServices.ComTypes.TYPEKIND pTKind);
+ new bool IsName(string szNameBuf, int lHashVal);
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]new void ReleaseTLibAttr(System.IntPtr pTLibAttr);
+ }
+ [System.FlagsAttribute]
+ public enum LIBFLAGS : short
+ {
+ LIBFLAG_FCONTROL = (short)2,
+ LIBFLAG_FHASDISKIMAGE = (short)8,
+ LIBFLAG_FHIDDEN = (short)4,
+ LIBFLAG_FRESTRICTED = (short)1,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct PARAMDESC
+ {
+ public System.IntPtr lpVarValue;
+ public System.Runtime.InteropServices.ComTypes.PARAMFLAG wParamFlags;
+ }
+ [System.FlagsAttribute]
+ public enum PARAMFLAG : short
+ {
+ PARAMFLAG_FHASCUSTDATA = (short)64,
+ PARAMFLAG_FHASDEFAULT = (short)32,
+ PARAMFLAG_FIN = (short)1,
+ PARAMFLAG_FLCID = (short)4,
+ PARAMFLAG_FOPT = (short)16,
+ PARAMFLAG_FOUT = (short)2,
+ PARAMFLAG_FRETVAL = (short)8,
+ PARAMFLAG_NONE = (short)0,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct STATSTG
+ {
+ public System.Runtime.InteropServices.ComTypes.FILETIME atime;
+ public long cbSize;
+ public System.Guid clsid;
+ public System.Runtime.InteropServices.ComTypes.FILETIME ctime;
+ public int grfLocksSupported;
+ public int grfMode;
+ public int grfStateBits;
+ public System.Runtime.InteropServices.ComTypes.FILETIME mtime;
+ public string pwcsName;
+ public int reserved;
+ public int type;
+ }
+ public enum SYSKIND
+ {
+ SYS_MAC = 2,
+ SYS_WIN16 = 0,
+ SYS_WIN32 = 1,
+ SYS_WIN64 = 3,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TYPEATTR
+ {
+ public short cbAlignment;
+ public int cbSizeInstance;
+ public short cbSizeVft;
+ public short cFuncs;
+ public short cImplTypes;
+ public short cVars;
+ public int dwReserved;
+ public System.Guid guid;
+ public System.Runtime.InteropServices.ComTypes.IDLDESC idldescType;
+ public int lcid;
+ public System.IntPtr lpstrSchema;
+ public const int MEMBER_ID_NIL = -1;
+ public int memidConstructor;
+ public int memidDestructor;
+ public System.Runtime.InteropServices.ComTypes.TYPEDESC tdescAlias;
+ public System.Runtime.InteropServices.ComTypes.TYPEKIND typekind;
+ public short wMajorVerNum;
+ public short wMinorVerNum;
+ public System.Runtime.InteropServices.ComTypes.TYPEFLAGS wTypeFlags;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TYPEDESC
+ {
+ public System.IntPtr lpValue;
+ public short vt;
+ }
+ [System.FlagsAttribute]
+ public enum TYPEFLAGS : short
+ {
+ TYPEFLAG_FAGGREGATABLE = (short)1024,
+ TYPEFLAG_FAPPOBJECT = (short)1,
+ TYPEFLAG_FCANCREATE = (short)2,
+ TYPEFLAG_FCONTROL = (short)32,
+ TYPEFLAG_FDISPATCHABLE = (short)4096,
+ TYPEFLAG_FDUAL = (short)64,
+ TYPEFLAG_FHIDDEN = (short)16,
+ TYPEFLAG_FLICENSED = (short)4,
+ TYPEFLAG_FNONEXTENSIBLE = (short)128,
+ TYPEFLAG_FOLEAUTOMATION = (short)256,
+ TYPEFLAG_FPREDECLID = (short)8,
+ TYPEFLAG_FPROXY = (short)16384,
+ TYPEFLAG_FREPLACEABLE = (short)2048,
+ TYPEFLAG_FRESTRICTED = (short)512,
+ TYPEFLAG_FREVERSEBIND = (short)8192,
+ }
+ public enum TYPEKIND
+ {
+ TKIND_ALIAS = 6,
+ TKIND_COCLASS = 5,
+ TKIND_DISPATCH = 4,
+ TKIND_ENUM = 0,
+ TKIND_INTERFACE = 3,
+ TKIND_MAX = 8,
+ TKIND_MODULE = 2,
+ TKIND_RECORD = 1,
+ TKIND_UNION = 7,
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct TYPELIBATTR
+ {
+ public System.Guid guid;
+ public int lcid;
+ public System.Runtime.InteropServices.ComTypes.SYSKIND syskind;
+ public System.Runtime.InteropServices.ComTypes.LIBFLAGS wLibFlags;
+ public short wMajorVerNum;
+ public short wMinorVerNum;
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct VARDESC
+ {
+ public System.Runtime.InteropServices.ComTypes.VARDESC.DESCUNION desc;
+ public System.Runtime.InteropServices.ComTypes.ELEMDESC elemdescVar;
+ public string lpstrSchema;
+ public int memid;
+ public System.Runtime.InteropServices.ComTypes.VARKIND varkind;
+ public short wVarFlags;
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Explicit)]
+ public partial struct DESCUNION
+ {
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public System.IntPtr lpvarValue;
+ [System.Runtime.InteropServices.FieldOffsetAttribute(0)]
+ public int oInst;
+ }
+ }
+ [System.FlagsAttribute]
+ public enum VARFLAGS : short
+ {
+ VARFLAG_FBINDABLE = (short)4,
+ VARFLAG_FDEFAULTBIND = (short)32,
+ VARFLAG_FDEFAULTCOLLELEM = (short)256,
+ VARFLAG_FDISPLAYBIND = (short)16,
+ VARFLAG_FHIDDEN = (short)64,
+ VARFLAG_FIMMEDIATEBIND = (short)4096,
+ VARFLAG_FNONBROWSABLE = (short)1024,
+ VARFLAG_FREADONLY = (short)1,
+ VARFLAG_FREPLACEABLE = (short)2048,
+ VARFLAG_FREQUESTEDIT = (short)8,
+ VARFLAG_FRESTRICTED = (short)128,
+ VARFLAG_FSOURCE = (short)2,
+ VARFLAG_FUIDEFAULT = (short)512,
+ }
+ public enum VARKIND
+ {
+ VAR_CONST = 2,
+ VAR_DISPATCH = 3,
+ VAR_PERINSTANCE = 0,
+ VAR_STATIC = 1,
+ }
+}
+namespace System.Runtime.Loader
+{
+ [System.Security.SecuritySafeCriticalAttribute]
+ public abstract partial class AssemblyLoadContext
+ {
+ protected AssemblyLoadContext() { }
+ public static System.Runtime.Loader.AssemblyLoadContext Default { get { throw null; } }
+ public event System.Func<System.Runtime.Loader.AssemblyLoadContext, System.Reflection.AssemblyName, System.Reflection.Assembly> Resolving { add { } remove { } }
+ public event System.Action<System.Runtime.Loader.AssemblyLoadContext> Unloading { add { } remove { } }
+ public static System.Reflection.AssemblyName GetAssemblyName(string assemblyPath) { throw null; }
+ public static System.Runtime.Loader.AssemblyLoadContext GetLoadContext(System.Reflection.Assembly assembly) { throw null; }
+ protected abstract System.Reflection.Assembly Load(System.Reflection.AssemblyName assemblyName);
+ public System.Reflection.Assembly LoadFromAssemblyName(System.Reflection.AssemblyName assemblyName) { throw null; }
+ public System.Reflection.Assembly LoadFromAssemblyPath(string assemblyPath) { throw null; }
+ public System.Reflection.Assembly LoadFromNativeImagePath(string nativeImagePath, string assemblyPath) { throw null; }
+ public System.Reflection.Assembly LoadFromStream(System.IO.Stream assembly) { throw null; }
+ public System.Reflection.Assembly LoadFromStream(System.IO.Stream assembly, System.IO.Stream assemblySymbols) { throw null; }
+ protected virtual System.IntPtr LoadUnmanagedDll(string unmanagedDllName) { throw null; }
+ protected System.IntPtr LoadUnmanagedDllFromPath(string unmanagedDllPath) { throw null; }
+ public void SetProfileOptimizationRoot(string directoryPath) { }
+ public void StartProfileOptimization(string profile) { }
+ }
+}
+namespace System.Runtime.Remoting
+{
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(2))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ObjectHandle
+ {
+ internal ObjectHandle() { }
+ }
+}
+namespace System.Runtime.Serialization
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class FormatterServices
+ {
+ [System.Security.SecurityCriticalAttribute]
+ public static object GetUninitializedObject(System.Type type) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IDeserializationCallback
+ {
+ void OnDeserialization(object sender);
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IFormatterConverter
+ {
+ object Convert(object value, System.Type type);
+ object Convert(object value, System.TypeCode typeCode);
+ bool ToBoolean(object value);
+ byte ToByte(object value);
+ char ToChar(object value);
+ System.DateTime ToDateTime(object value);
+ decimal ToDecimal(object value);
+ double ToDouble(object value);
+ short ToInt16(object value);
+ int ToInt32(object value);
+ long ToInt64(object value);
+ sbyte ToSByte(object value);
+ float ToSingle(object value);
+ string ToString(object value);
+ ushort ToUInt16(object value);
+ uint ToUInt32(object value);
+ ulong ToUInt64(object value);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IObjectReference
+ {
+ [System.Security.SecurityCriticalAttribute]
+ object GetRealObject(System.Runtime.Serialization.StreamingContext context);
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface ISerializable
+ {
+ [System.Security.SecurityCriticalAttribute]
+ void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context);
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OnDeserializedAttribute : System.Attribute
+ {
+ public OnDeserializedAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OnDeserializingAttribute : System.Attribute
+ {
+ public OnDeserializingAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OnSerializedAttribute : System.Attribute
+ {
+ public OnSerializedAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(64), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OnSerializingAttribute : System.Attribute
+ {
+ public OnSerializingAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(256), Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class OptionalFieldAttribute : System.Attribute
+ {
+ public OptionalFieldAttribute() { }
+ public int VersionAdded { get { throw null; } set { } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct SerializationEntry
+ {
+ public string Name { get { throw null; } }
+ public System.Type ObjectType { get { throw null; } }
+ public object Value { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SerializationException : System.SystemException
+ {
+ public SerializationException() { }
+ public SerializationException(string message) { }
+ public SerializationException(string message, System.Exception innerException) { }
+ protected SerializationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SerializationInfo
+ {
+ [System.CLSCompliantAttribute(false)]
+ public SerializationInfo(System.Type type, System.Runtime.Serialization.IFormatterConverter converter) { }
+ [System.CLSCompliantAttribute(false)]
+ public SerializationInfo(System.Type type, System.Runtime.Serialization.IFormatterConverter converter, bool requireSameTokenInPartialTrust) { }
+ public string AssemblyName { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public string FullTypeName { get { throw null; } set { } }
+ public bool IsAssemblyNameSetExplicit { get { throw null; } }
+ public bool IsFullTypeNameSetExplicit { get { throw null; } }
+ public int MemberCount { get { throw null; } }
+ public System.Type ObjectType { get { throw null; } }
+ public void AddValue(string name, bool value) { }
+ public void AddValue(string name, byte value) { }
+ public void AddValue(string name, char value) { }
+ public void AddValue(string name, System.DateTime value) { }
+ public void AddValue(string name, decimal value) { }
+ public void AddValue(string name, double value) { }
+ public void AddValue(string name, short value) { }
+ public void AddValue(string name, int value) { }
+ public void AddValue(string name, long value) { }
+ public void AddValue(string name, object value) { }
+ public void AddValue(string name, object value, System.Type type) { }
+ [System.CLSCompliantAttribute(false)]
+ public void AddValue(string name, sbyte value) { }
+ public void AddValue(string name, float value) { }
+ [System.CLSCompliantAttribute(false)]
+ public void AddValue(string name, ushort value) { }
+ [System.CLSCompliantAttribute(false)]
+ public void AddValue(string name, uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ public void AddValue(string name, ulong value) { }
+ public bool GetBoolean(string name) { throw null; }
+ public byte GetByte(string name) { throw null; }
+ public char GetChar(string name) { throw null; }
+ public System.DateTime GetDateTime(string name) { throw null; }
+ public decimal GetDecimal(string name) { throw null; }
+ public double GetDouble(string name) { throw null; }
+ public System.Runtime.Serialization.SerializationInfoEnumerator GetEnumerator() { throw null; }
+ public short GetInt16(string name) { throw null; }
+ public int GetInt32(string name) { throw null; }
+ public long GetInt64(string name) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public sbyte GetSByte(string name) { throw null; }
+ public float GetSingle(string name) { throw null; }
+ public string GetString(string name) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public ushort GetUInt16(string name) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public uint GetUInt32(string name) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public ulong GetUInt64(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public object GetValue(string name, System.Type type) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void SetType(System.Type type) { }
+ public void UpdateValue(string name, object value, System.Type type) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SerializationInfoEnumerator : System.Collections.IEnumerator
+ {
+ internal SerializationInfoEnumerator() { }
+ public System.Runtime.Serialization.SerializationEntry Current { get { throw null; } }
+ public string Name { get { throw null; } }
+ public System.Type ObjectType { get { throw null; } }
+ object System.Collections.IEnumerator.Current { get { throw null; } }
+ public object Value { get { throw null; } }
+ public bool MoveNext() { throw null; }
+ public void Reset() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct StreamingContext
+ {
+ public StreamingContext(System.Runtime.Serialization.StreamingContextStates state) { throw null;}
+ public StreamingContext(System.Runtime.Serialization.StreamingContextStates state, object additional) { throw null;}
+ public object Context { get { throw null; } }
+ public System.Runtime.Serialization.StreamingContextStates State { get { throw null; } }
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum StreamingContextStates
+ {
+ All = 255,
+ Clone = 64,
+ CrossAppDomain = 128,
+ CrossMachine = 2,
+ CrossProcess = 1,
+ File = 4,
+ Other = 32,
+ Persistence = 8,
+ Remoting = 16,
+ }
+}
+namespace System.Runtime.Versioning
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5887), AllowMultiple=false, Inherited=false)]
+ public sealed partial class ComponentGuaranteesAttribute : System.Attribute
+ {
+ public ComponentGuaranteesAttribute(System.Runtime.Versioning.ComponentGuaranteesOptions guarantees) { }
+ public System.Runtime.Versioning.ComponentGuaranteesOptions Guarantees { get { throw null; } }
+ }
+ [System.FlagsAttribute]
+ public enum ComponentGuaranteesOptions
+ {
+ Exchange = 1,
+ None = 0,
+ SideBySide = 4,
+ Stable = 2,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(480), Inherited=false)]
+ [System.Diagnostics.ConditionalAttribute("RESOURCE_ANNOTATION_WORK")]
+ public sealed partial class ResourceExposureAttribute : System.Attribute
+ {
+ public ResourceExposureAttribute(System.Runtime.Versioning.ResourceScope exposureLevel) { }
+ public System.Runtime.Versioning.ResourceScope ResourceExposureLevel { get { throw null; } }
+ }
+ [System.FlagsAttribute]
+ public enum ResourceScope
+ {
+ AppDomain = 4,
+ Assembly = 32,
+ Library = 8,
+ Machine = 1,
+ None = 0,
+ Private = 16,
+ Process = 2,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)]
+ public sealed partial class TargetFrameworkAttribute : System.Attribute
+ {
+ public TargetFrameworkAttribute(string frameworkName) { }
+ public string FrameworkDisplayName { get { throw null; } set { } }
+ public string FrameworkName { get { throw null; } }
+ }
+ public static partial class VersioningHelper
+ {
+ public static string MakeVersionSafeName(string name, System.Runtime.Versioning.ResourceScope from, System.Runtime.Versioning.ResourceScope to) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static string MakeVersionSafeName(string name, System.Runtime.Versioning.ResourceScope from, System.Runtime.Versioning.ResourceScope to, System.Type type) { throw null; }
+ }
+}
+namespace System.Security
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AllowPartiallyTrustedCallersAttribute : System.Attribute
+ {
+ public AllowPartiallyTrustedCallersAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5501), AllowMultiple=false, Inherited=false)]
+ public sealed partial class SecurityCriticalAttribute : System.Attribute
+ {
+ public SecurityCriticalAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SecurityException : System.SystemException
+ {
+ public SecurityException() { }
+ public SecurityException(string message) { }
+ public SecurityException(string message, System.Exception inner) { }
+ protected SecurityException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ [System.Security.SecurityCriticalAttribute]
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
+ public override string ToString() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5500), AllowMultiple=false, Inherited=false)]
+ public sealed partial class SecuritySafeCriticalAttribute : System.Attribute
+ {
+ public SecuritySafeCriticalAttribute() { }
+ }
+ [System.Security.SecurityCriticalAttribute]
+ public abstract partial class SecurityState
+ {
+ protected SecurityState() { }
+ public abstract void EnsureState();
+ [System.Security.SecurityCriticalAttribute]
+ public bool IsStateAvailable() { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1), AllowMultiple=false, Inherited=false)]
+ public sealed partial class SecurityTransparentAttribute : System.Attribute
+ {
+ public SecurityTransparentAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2), AllowMultiple=true, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class UnverifiableCodeAttribute : System.Attribute
+ {
+ public UnverifiableCodeAttribute() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class VerificationException : System.SystemException
+ {
+ public VerificationException() { }
+ public VerificationException(string message) { }
+ public VerificationException(string message, System.Exception innerException) { }
+ protected VerificationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+}
+namespace System.Security.Permissions
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(109), AllowMultiple=true, Inherited=false)]
+ [System.ObsoleteAttribute("CodeAccessSecurityAttribute is no longer accessible to application code.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class CodeAccessSecurityAttribute : System.Security.Permissions.SecurityAttribute
+ {
+ protected CodeAccessSecurityAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { }
+ }
+ [System.ObsoleteAttribute("SecurityAction is no longer accessible to application code.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum SecurityAction
+ {
+ Assert = 3,
+ Demand = 2,
+ [System.ObsoleteAttribute("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ Deny = 4,
+ InheritanceDemand = 7,
+ LinkDemand = 6,
+ PermitOnly = 5,
+ [System.ObsoleteAttribute("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestMinimum = 8,
+ [System.ObsoleteAttribute("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestOptional = 9,
+ [System.ObsoleteAttribute("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestRefuse = 10,
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(109), AllowMultiple=true, Inherited=false)]
+ [System.ObsoleteAttribute("SecurityAttribute is no longer accessible to application code.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class SecurityAttribute : System.Attribute
+ {
+ protected SecurityAttribute(System.Security.Permissions.SecurityAction action) { }
+ public System.Security.Permissions.SecurityAction Action { get { throw null; } set { } }
+ public bool Unrestricted { get { throw null; } set { } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(109), AllowMultiple=true, Inherited=false)]
+ [System.ObsoleteAttribute("SecurityPermissionAttribute is no longer accessible to application code.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class SecurityPermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute
+ {
+ public SecurityPermissionAttribute(System.Security.Permissions.SecurityAction action) : base (default(System.Security.Permissions.SecurityAction)) { }
+ public bool ControlAppDomain { get { throw null; } set { } }
+ public bool ControlDomainPolicy { get { throw null; } set { } }
+ public bool ControlEvidence { get { throw null; } set { } }
+ public bool ControlPolicy { get { throw null; } set { } }
+ public bool ControlThread { get { throw null; } set { } }
+ public System.Security.Permissions.SecurityPermissionFlag Flags { get { throw null; } set { } }
+ public bool SkipVerification { get { throw null; } set { } }
+ public bool UnmanagedCode { get { throw null; } set { } }
+ }
+ [System.FlagsAttribute]
+ [System.ObsoleteAttribute("SecurityPermissionFlag is no longer accessible to application code.")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum SecurityPermissionFlag
+ {
+ AllFlags = 16383,
+ Assertion = 1,
+ BindingRedirects = 8192,
+ ControlAppDomain = 1024,
+ ControlDomainPolicy = 256,
+ ControlEvidence = 32,
+ ControlPolicy = 64,
+ ControlPrincipal = 512,
+ ControlThread = 16,
+ Execution = 8,
+ Infrastructure = 4096,
+ NoFlags = 0,
+ RemotingConfiguration = 2048,
+ SerializationFormatter = 128,
+ SkipVerification = 4,
+ UnmanagedCode = 2,
+ }
+}
+namespace System.Security.Principal
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IIdentity
+ {
+ string AuthenticationType { get; }
+ bool IsAuthenticated { get; }
+ string Name { get; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial interface IPrincipal
+ {
+ System.Security.Principal.IIdentity Identity { get; }
+ bool IsInRole(string role);
+ }
+ public enum TokenImpersonationLevel
+ {
+ Anonymous = 1,
+ Delegation = 4,
+ Identification = 2,
+ Impersonation = 3,
+ None = 0,
+ }
+}
+namespace System.Text
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ASCIIEncoding : System.Text.Encoding
+ {
+ public ASCIIEncoding() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override bool IsSingleByte { get { throw null; } }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetByteCount(char* chars, int count) { throw null; }
+ public override int GetByteCount(char[] chars, int index, int count) { throw null; }
+ public override int GetByteCount(string chars) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ public override int GetBytes(string chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetCharCount(byte* bytes, int count) { throw null; }
+ public override int GetCharCount(byte[] bytes, int index, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Text.Decoder GetDecoder() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Text.Encoder GetEncoder() { throw null; }
+ public override int GetMaxByteCount(int charCount) { throw null; }
+ public override int GetMaxCharCount(int byteCount) { throw null; }
+ public override string GetString(byte[] bytes, int byteIndex, int byteCount) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Decoder
+ {
+ protected Decoder() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.DecoderFallback Fallback { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.DecoderFallbackBuffer FallbackBuffer { get { throw null; } }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual void Convert(byte* bytes, int byteCount, char* chars, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed) { bytesUsed = default(int); charsUsed = default(int); completed = default(bool); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual void Convert(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed) { bytesUsed = default(int); charsUsed = default(int); completed = default(bool); }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetCharCount(byte* bytes, int count, bool flush) { throw null; }
+ public abstract int GetCharCount(byte[] bytes, int index, int count);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual int GetCharCount(byte[] bytes, int index, int count, bool flush) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetChars(byte* bytes, int byteCount, char* chars, int charCount, bool flush) { throw null; }
+ public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex);
+ public virtual int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex, bool flush) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual void Reset() { }
+ }
+ public sealed partial class DecoderExceptionFallback : System.Text.DecoderFallback
+ {
+ public DecoderExceptionFallback() { }
+ public override int MaxCharCount { get { throw null; } }
+ public override System.Text.DecoderFallbackBuffer CreateFallbackBuffer() { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ public sealed partial class DecoderExceptionFallbackBuffer : System.Text.DecoderFallbackBuffer
+ {
+ public DecoderExceptionFallbackBuffer() { }
+ public override int Remaining { get { throw null; } }
+ public override bool Fallback(byte[] bytesUnknown, int index) { throw null; }
+ public override char GetNextChar() { throw null; }
+ public override bool MovePrevious() { throw null; }
+ }
+ public abstract partial class DecoderFallback
+ {
+ protected DecoderFallback() { }
+ public static System.Text.DecoderFallback ExceptionFallback { get { throw null; } }
+ public abstract int MaxCharCount { get; }
+ public static System.Text.DecoderFallback ReplacementFallback { get { throw null; } }
+ public abstract System.Text.DecoderFallbackBuffer CreateFallbackBuffer();
+ }
+ public abstract partial class DecoderFallbackBuffer
+ {
+ protected DecoderFallbackBuffer() { }
+ public abstract int Remaining { get; }
+ public abstract bool Fallback(byte[] bytesUnknown, int index);
+ public abstract char GetNextChar();
+ public abstract bool MovePrevious();
+ public virtual void Reset() { }
+ }
+ public sealed partial class DecoderFallbackException : System.ArgumentException
+ {
+ public DecoderFallbackException() { }
+ public DecoderFallbackException(string message) { }
+ public DecoderFallbackException(string message, byte[] bytesUnknown, int index) { }
+ public DecoderFallbackException(string message, System.Exception innerException) { }
+ public byte[] BytesUnknown { get { throw null; } }
+ public int Index { get { throw null; } }
+ }
+ public sealed partial class DecoderReplacementFallback : System.Text.DecoderFallback
+ {
+ public DecoderReplacementFallback() { }
+ public DecoderReplacementFallback(string replacement) { }
+ public string DefaultString { get { throw null; } }
+ public override int MaxCharCount { get { throw null; } }
+ public override System.Text.DecoderFallbackBuffer CreateFallbackBuffer() { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ public sealed partial class DecoderReplacementFallbackBuffer : System.Text.DecoderFallbackBuffer
+ {
+ public DecoderReplacementFallbackBuffer(System.Text.DecoderReplacementFallback fallback) { }
+ public override int Remaining { get { throw null; } }
+ public override bool Fallback(byte[] bytesUnknown, int index) { throw null; }
+ public override char GetNextChar() { throw null; }
+ public override bool MovePrevious() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override void Reset() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Encoder
+ {
+ protected Encoder() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.EncoderFallback Fallback { get { throw null; } set { } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.EncoderFallbackBuffer FallbackBuffer { get { throw null; } }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual void Convert(char* chars, int charCount, byte* bytes, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed) { charsUsed = default(int); bytesUsed = default(int); completed = default(bool); }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual void Convert(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed) { charsUsed = default(int); bytesUsed = default(int); completed = default(bool); }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetByteCount(char* chars, int count, bool flush) { throw null; }
+ public abstract int GetByteCount(char[] chars, int index, int count, bool flush);
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush) { throw null; }
+ public abstract int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex, bool flush);
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual void Reset() { }
+ }
+ public sealed partial class EncoderExceptionFallback : System.Text.EncoderFallback
+ {
+ public EncoderExceptionFallback() { }
+ public override int MaxCharCount { get { throw null; } }
+ public override System.Text.EncoderFallbackBuffer CreateFallbackBuffer() { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ public sealed partial class EncoderExceptionFallbackBuffer : System.Text.EncoderFallbackBuffer
+ {
+ public EncoderExceptionFallbackBuffer() { }
+ public override int Remaining { get { throw null; } }
+ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index) { throw null; }
+ public override bool Fallback(char charUnknown, int index) { throw null; }
+ public override char GetNextChar() { throw null; }
+ public override bool MovePrevious() { throw null; }
+ }
+ public abstract partial class EncoderFallback
+ {
+ protected EncoderFallback() { }
+ public static System.Text.EncoderFallback ExceptionFallback { get { throw null; } }
+ public abstract int MaxCharCount { get; }
+ public static System.Text.EncoderFallback ReplacementFallback { get { throw null; } }
+ public abstract System.Text.EncoderFallbackBuffer CreateFallbackBuffer();
+ }
+ public abstract partial class EncoderFallbackBuffer
+ {
+ protected EncoderFallbackBuffer() { }
+ public abstract int Remaining { get; }
+ public abstract bool Fallback(char charUnknownHigh, char charUnknownLow, int index);
+ public abstract bool Fallback(char charUnknown, int index);
+ public abstract char GetNextChar();
+ public abstract bool MovePrevious();
+ public virtual void Reset() { }
+ }
+ public sealed partial class EncoderFallbackException : System.ArgumentException
+ {
+ public EncoderFallbackException() { }
+ public EncoderFallbackException(string message) { }
+ public EncoderFallbackException(string message, System.Exception innerException) { }
+ public char CharUnknown { get { throw null; } }
+ public char CharUnknownHigh { get { throw null; } }
+ public char CharUnknownLow { get { throw null; } }
+ public int Index { get { throw null; } }
+ public bool IsUnknownSurrogate() { throw null; }
+ }
+ public sealed partial class EncoderReplacementFallback : System.Text.EncoderFallback
+ {
+ public EncoderReplacementFallback() { }
+ public EncoderReplacementFallback(string replacement) { }
+ public string DefaultString { get { throw null; } }
+ public override int MaxCharCount { get { throw null; } }
+ public override System.Text.EncoderFallbackBuffer CreateFallbackBuffer() { throw null; }
+ public override bool Equals(object value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ public sealed partial class EncoderReplacementFallbackBuffer : System.Text.EncoderFallbackBuffer
+ {
+ public EncoderReplacementFallbackBuffer(System.Text.EncoderReplacementFallback fallback) { }
+ public override int Remaining { get { throw null; } }
+ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index) { throw null; }
+ public override bool Fallback(char charUnknown, int index) { throw null; }
+ public override char GetNextChar() { throw null; }
+ public override bool MovePrevious() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override void Reset() { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class Encoding : System.ICloneable
+ {
+ protected Encoding() { }
+ protected Encoding(int codePage) { }
+ protected Encoding(int codePage, System.Text.EncoderFallback encoderFallback, System.Text.DecoderFallback decoderFallback) { }
+ public static System.Text.Encoding ASCII { get { throw null; } }
+ public static System.Text.Encoding BigEndianUnicode { get { throw null; } }
+ public virtual string BodyName { get { throw null; } }
+ public virtual int CodePage { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.DecoderFallback DecoderFallback { get { throw null; } set { } }
+ public static System.Text.Encoding Default { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.EncoderFallback EncoderFallback { get { throw null; } set { } }
+ public virtual string EncodingName { get { throw null; } }
+ public virtual string HeaderName { get { throw null; } }
+ public virtual bool IsBrowserDisplay { get { throw null; } }
+ public virtual bool IsBrowserSave { get { throw null; } }
+ public virtual bool IsMailNewsDisplay { get { throw null; } }
+ public virtual bool IsMailNewsSave { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public bool IsReadOnly { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual bool IsSingleByte { get { throw null; } }
+ public static System.Text.Encoding Unicode { get { throw null; } }
+ public static System.Text.Encoding UTF32 { get { throw null; } }
+ public static System.Text.Encoding UTF7 { get { throw null; } }
+ public static System.Text.Encoding UTF8 { get { throw null; } }
+ public virtual string WebName { get { throw null; } }
+ public virtual int WindowsCodePage { get { throw null; } }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual object Clone() { throw null; }
+ public static byte[] Convert(System.Text.Encoding srcEncoding, System.Text.Encoding dstEncoding, byte[] bytes) { throw null; }
+ public static byte[] Convert(System.Text.Encoding srcEncoding, System.Text.Encoding dstEncoding, byte[] bytes, int index, int count) { throw null; }
+ public override bool Equals(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetByteCount(char* chars, int count) { throw null; }
+ public virtual int GetByteCount(char[] chars) { throw null; }
+ public abstract int GetByteCount(char[] chars, int index, int count);
+ public virtual int GetByteCount(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public virtual byte[] GetBytes(char[] chars) { throw null; }
+ public virtual byte[] GetBytes(char[] chars, int index, int count) { throw null; }
+ public abstract int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex);
+ public virtual byte[] GetBytes(string s) { throw null; }
+ public virtual int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetCharCount(byte* bytes, int count) { throw null; }
+ public virtual int GetCharCount(byte[] bytes) { throw null; }
+ public abstract int GetCharCount(byte[] bytes, int index, int count);
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe virtual int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public virtual char[] GetChars(byte[] bytes) { throw null; }
+ public virtual char[] GetChars(byte[] bytes, int index, int count) { throw null; }
+ public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex);
+ public virtual System.Text.Decoder GetDecoder() { throw null; }
+ public virtual System.Text.Encoder GetEncoder() { throw null; }
+ public static System.Text.Encoding GetEncoding(int codepage) { throw null; }
+ public static System.Text.Encoding GetEncoding(int codepage, System.Text.EncoderFallback encoderFallback, System.Text.DecoderFallback decoderFallback) { throw null; }
+ public static System.Text.Encoding GetEncoding(string name) { throw null; }
+ public static System.Text.Encoding GetEncoding(string name, System.Text.EncoderFallback encoderFallback, System.Text.DecoderFallback decoderFallback) { throw null; }
+ public static System.Text.EncodingInfo[] GetEncodings() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public abstract int GetMaxByteCount(int charCount);
+ public abstract int GetMaxCharCount(int byteCount);
+ public virtual byte[] GetPreamble() { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe string GetString(byte* bytes, int byteCount) { throw null; }
+ public virtual string GetString(byte[] bytes) { throw null; }
+ public virtual string GetString(byte[] bytes, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public bool IsAlwaysNormalized() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public virtual bool IsAlwaysNormalized(System.Text.NormalizationForm form) { throw null; }
+ public static void RegisterProvider(System.Text.EncodingProvider provider) { }
+ }
+ public sealed partial class EncodingInfo
+ {
+ internal EncodingInfo() { }
+ public int CodePage { get { throw null; } }
+ public string DisplayName { get { throw null; } }
+ public string Name { get { throw null; } }
+ public override bool Equals(object value) { throw null; }
+ public System.Text.Encoding GetEncoding() { throw null; }
+ public override int GetHashCode() { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class EncodingProvider
+ {
+ public EncodingProvider() { }
+ public abstract System.Text.Encoding GetEncoding(int codepage);
+ public virtual System.Text.Encoding GetEncoding(int codepage, System.Text.EncoderFallback encoderFallback, System.Text.DecoderFallback decoderFallback) { throw null; }
+ public abstract System.Text.Encoding GetEncoding(string name);
+ public virtual System.Text.Encoding GetEncoding(string name, System.Text.EncoderFallback encoderFallback, System.Text.DecoderFallback decoderFallback) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum NormalizationForm
+ {
+ FormC = 1,
+ FormD = 2,
+ FormKC = 5,
+ FormKD = 6,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class StringBuilder
+ {
+ public StringBuilder() { }
+ public StringBuilder(int capacity) { }
+ public StringBuilder(int capacity, int maxCapacity) { }
+ public StringBuilder(string value) { }
+ public StringBuilder(string value, int capacity) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public StringBuilder(string value, int startIndex, int length, int capacity) { }
+ public int Capacity { get { throw null; } set { } }
+ [System.Runtime.CompilerServices.IndexerName("Chars")]
+ public char this[int index] { get { throw null; } set { } }
+ public int Length { get { throw null; } set { } }
+ public int MaxCapacity { get { throw null; } }
+ public System.Text.StringBuilder Append(bool value) { throw null; }
+ public System.Text.StringBuilder Append(byte value) { throw null; }
+ public System.Text.StringBuilder Append(char value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe System.Text.StringBuilder Append(char* value, int valueCount) { throw null; }
+ public System.Text.StringBuilder Append(char value, int repeatCount) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Append(char[] value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Append(char[] value, int startIndex, int charCount) { throw null; }
+ public System.Text.StringBuilder Append(decimal value) { throw null; }
+ public System.Text.StringBuilder Append(double value) { throw null; }
+ public System.Text.StringBuilder Append(short value) { throw null; }
+ public System.Text.StringBuilder Append(int value) { throw null; }
+ public System.Text.StringBuilder Append(long value) { throw null; }
+ public System.Text.StringBuilder Append(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Append(sbyte value) { throw null; }
+ public System.Text.StringBuilder Append(float value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Append(string value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Append(string value, int startIndex, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Append(ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Append(uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Append(ulong value) { throw null; }
+ public System.Text.StringBuilder AppendFormat(System.IFormatProvider provider, string format, object arg0) { throw null; }
+ public System.Text.StringBuilder AppendFormat(System.IFormatProvider provider, string format, object arg0, object arg1) { throw null; }
+ public System.Text.StringBuilder AppendFormat(System.IFormatProvider provider, string format, object arg0, object arg1, object arg2) { throw null; }
+ public System.Text.StringBuilder AppendFormat(System.IFormatProvider provider, string format, params object[] args) { throw null; }
+ public System.Text.StringBuilder AppendFormat(string format, object arg0) { throw null; }
+ public System.Text.StringBuilder AppendFormat(string format, object arg0, object arg1) { throw null; }
+ public System.Text.StringBuilder AppendFormat(string format, object arg0, object arg1, object arg2) { throw null; }
+ public System.Text.StringBuilder AppendFormat(string format, params object[] args) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.StringBuilder AppendLine() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public System.Text.StringBuilder AppendLine(string value) { throw null; }
+ public System.Text.StringBuilder Clear() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { }
+ public int EnsureCapacity(int capacity) { throw null; }
+ public bool Equals(System.Text.StringBuilder sb) { throw null; }
+ public System.Text.StringBuilder Insert(int index, bool value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, byte value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Insert(int index, char value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, char[] value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Insert(int index, char[] value, int startIndex, int charCount) { throw null; }
+ public System.Text.StringBuilder Insert(int index, decimal value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, double value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, short value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, int value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, long value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Insert(int index, sbyte value) { throw null; }
+ public System.Text.StringBuilder Insert(int index, float value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Insert(int index, string value) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public System.Text.StringBuilder Insert(int index, string value, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Insert(int index, ushort value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Insert(int index, uint value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public System.Text.StringBuilder Insert(int index, ulong value) { throw null; }
+ public System.Text.StringBuilder Remove(int startIndex, int length) { throw null; }
+ public System.Text.StringBuilder Replace(char oldChar, char newChar) { throw null; }
+ public System.Text.StringBuilder Replace(char oldChar, char newChar, int startIndex, int count) { throw null; }
+ public System.Text.StringBuilder Replace(string oldValue, string newValue) { throw null; }
+ public System.Text.StringBuilder Replace(string oldValue, string newValue, int startIndex, int count) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public override string ToString() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public string ToString(int startIndex, int length) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class UnicodeEncoding : System.Text.Encoding
+ {
+ public const int CharSize = 2;
+ public UnicodeEncoding() { }
+ public UnicodeEncoding(bool bigEndian, bool byteOrderMark) { }
+ public UnicodeEncoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidBytes) { }
+ public override bool Equals(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetByteCount(char* chars, int count) { throw null; }
+ public override int GetByteCount(char[] chars, int index, int count) { throw null; }
+ public override int GetByteCount(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetCharCount(byte* bytes, int count) { throw null; }
+ public override int GetCharCount(byte[] bytes, int index, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { throw null; }
+ public override System.Text.Decoder GetDecoder() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override System.Text.Encoder GetEncoder() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override int GetMaxByteCount(int charCount) { throw null; }
+ public override int GetMaxCharCount(int byteCount) { throw null; }
+ public override byte[] GetPreamble() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override string GetString(byte[] bytes, int index, int count) { throw null; }
+ }
+ public sealed partial class UTF32Encoding : System.Text.Encoding
+ {
+ public UTF32Encoding() { }
+ public UTF32Encoding(bool bigEndian, bool byteOrderMark) { }
+ public UTF32Encoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidCharacters) { }
+ public override bool Equals(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetByteCount(char* chars, int count) { throw null; }
+ public override int GetByteCount(char[] chars, int index, int count) { throw null; }
+ public override int GetByteCount(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetCharCount(byte* bytes, int count) { throw null; }
+ public override int GetCharCount(byte[] bytes, int index, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { throw null; }
+ public override System.Text.Decoder GetDecoder() { throw null; }
+ public override System.Text.Encoder GetEncoder() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override int GetMaxByteCount(int charCount) { throw null; }
+ public override int GetMaxCharCount(int byteCount) { throw null; }
+ public override byte[] GetPreamble() { throw null; }
+ public override string GetString(byte[] bytes, int index, int count) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class UTF7Encoding : System.Text.Encoding
+ {
+ public UTF7Encoding() { }
+ public UTF7Encoding(bool allowOptionals) { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override bool Equals(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetByteCount(char* chars, int count) { throw null; }
+ public override int GetByteCount(char[] chars, int index, int count) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetByteCount(string s) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetCharCount(byte* bytes, int count) { throw null; }
+ public override int GetCharCount(byte[] bytes, int index, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { throw null; }
+ public override System.Text.Decoder GetDecoder() { throw null; }
+ public override System.Text.Encoder GetEncoder() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetHashCode() { throw null; }
+ public override int GetMaxByteCount(int charCount) { throw null; }
+ public override int GetMaxCharCount(int byteCount) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override string GetString(byte[] bytes, int index, int count) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class UTF8Encoding : System.Text.Encoding
+ {
+ public UTF8Encoding() { }
+ public UTF8Encoding(bool encoderShouldEmitUTF8Identifier) { }
+ public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes) { }
+ public override bool Equals(object value) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetByteCount(char* chars, int count) { throw null; }
+ public override int GetByteCount(char[] chars, int index, int count) { throw null; }
+ public override int GetByteCount(string chars) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount) { throw null; }
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ public override int GetBytes(string s, int charIndex, int charCount, byte[] bytes, int byteIndex) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetCharCount(byte* bytes, int count) { throw null; }
+ public override int GetCharCount(byte[] bytes, int index, int count) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount) { throw null; }
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex) { throw null; }
+ public override System.Text.Decoder GetDecoder() { throw null; }
+ public override System.Text.Encoder GetEncoder() { throw null; }
+ public override int GetHashCode() { throw null; }
+ public override int GetMaxByteCount(int charCount) { throw null; }
+ public override int GetMaxCharCount(int byteCount) { throw null; }
+ public override byte[] GetPreamble() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override string GetString(byte[] bytes, int index, int count) { throw null; }
+ }
+}
+namespace System.Threading
+{
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class AbandonedMutexException : System.SystemException
+ {
+ public AbandonedMutexException() { }
+ public AbandonedMutexException(int location, System.Threading.WaitHandle handle) { }
+ public AbandonedMutexException(string message) { }
+ public AbandonedMutexException(string message, System.Exception inner) { }
+ public AbandonedMutexException(string message, System.Exception inner, int location, System.Threading.WaitHandle handle) { }
+ public AbandonedMutexException(string message, int location, System.Threading.WaitHandle handle) { }
+ protected AbandonedMutexException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public System.Threading.Mutex Mutex { get { throw null; } }
+ public int MutexIndex { get { throw null; } }
+ }
+ public sealed partial class AsyncLocal<T>
+ {
+ public AsyncLocal() { }
+ [System.Security.SecurityCriticalAttribute]
+ public AsyncLocal(System.Action<System.Threading.AsyncLocalValueChangedArgs<T>> valueChangedHandler) { }
+ public T Value { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct AsyncLocalValueChangedArgs<T>
+ {
+ public T CurrentValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public T PreviousValue { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ public bool ThreadContextChanged { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class AutoResetEvent : System.Threading.EventWaitHandle
+ {
+ public AutoResetEvent(bool initialState) : base (default(bool), default(System.Threading.EventResetMode)) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("IsCancellationRequested = {IsCancellationRequested}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct CancellationToken
+ {
+ public CancellationToken(bool canceled) { throw null;}
+ public bool CanBeCanceled { get { throw null; } }
+ public bool IsCancellationRequested { get { throw null; } }
+ public static System.Threading.CancellationToken None { get { throw null; } }
+ public System.Threading.WaitHandle WaitHandle { get { throw null; } }
+ public override bool Equals(object other) { throw null; }
+ public bool Equals(System.Threading.CancellationToken other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Threading.CancellationToken left, System.Threading.CancellationToken right) { throw null; }
+ public static bool operator !=(System.Threading.CancellationToken left, System.Threading.CancellationToken right) { throw null; }
+ public System.Threading.CancellationTokenRegistration Register(System.Action callback) { throw null; }
+ public System.Threading.CancellationTokenRegistration Register(System.Action callback, bool useSynchronizationContext) { throw null; }
+ public System.Threading.CancellationTokenRegistration Register(System.Action<object> callback, object state) { throw null; }
+ public System.Threading.CancellationTokenRegistration Register(System.Action<object> callback, object state, bool useSynchronizationContext) { throw null; }
+ public void ThrowIfCancellationRequested() { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct CancellationTokenRegistration : System.IDisposable, System.IEquatable<System.Threading.CancellationTokenRegistration>
+ {
+ public void Dispose() { }
+ public override bool Equals(object obj) { throw null; }
+ public bool Equals(System.Threading.CancellationTokenRegistration other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Threading.CancellationTokenRegistration left, System.Threading.CancellationTokenRegistration right) { throw null; }
+ public static bool operator !=(System.Threading.CancellationTokenRegistration left, System.Threading.CancellationTokenRegistration right) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class CancellationTokenSource : System.IDisposable
+ {
+ public CancellationTokenSource() { }
+ public CancellationTokenSource(int millisecondsDelay) { }
+ public CancellationTokenSource(System.TimeSpan delay) { }
+ public bool IsCancellationRequested { get { throw null; } }
+ public System.Threading.CancellationToken Token { get { throw null; } }
+ public void Cancel() { }
+ public void Cancel(bool throwOnFirstException) { }
+ public void CancelAfter(int millisecondsDelay) { }
+ public void CancelAfter(System.TimeSpan delay) { }
+ public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(System.Threading.CancellationToken token1, System.Threading.CancellationToken token2) { throw null; }
+ public static System.Threading.CancellationTokenSource CreateLinkedTokenSource(params System.Threading.CancellationToken[] tokens) { throw null; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public delegate void ContextCallback(object state);
+ [System.Diagnostics.DebuggerDisplayAttribute("Initial Count={InitialCount}, Current Count={CurrentCount}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class CountdownEvent : System.IDisposable
+ {
+ public CountdownEvent(int initialCount) { }
+ public int CurrentCount { get { throw null; } }
+ public int InitialCount { get { throw null; } }
+ public bool IsSet { get { throw null; } }
+ public System.Threading.WaitHandle WaitHandle { get { throw null; } }
+ public void AddCount() { }
+ public void AddCount(int signalCount) { }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public void Reset() { }
+ public void Reset(int count) { }
+ public bool Signal() { throw null; }
+ public bool Signal(int signalCount) { throw null; }
+ public bool TryAddCount() { throw null; }
+ public bool TryAddCount(int signalCount) { throw null; }
+ public void Wait() { }
+ public bool Wait(int millisecondsTimeout) { throw null; }
+ public bool Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Wait(System.Threading.CancellationToken cancellationToken) { }
+ public bool Wait(System.TimeSpan timeout) { throw null; }
+ public bool Wait(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public enum EventResetMode
+ {
+ AutoReset = 0,
+ ManualReset = 1,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class EventWaitHandle : System.Threading.WaitHandle
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode) { }
+ [System.Security.SecurityCriticalAttribute]
+ public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string name) { }
+ [System.Security.SecurityCriticalAttribute]
+ public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode, string name, out bool createdNew) { createdNew = default(bool); }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Threading.EventWaitHandle OpenExisting(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Reset() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Set() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static bool TryOpenExisting(string name, out System.Threading.EventWaitHandle result) { result = default(System.Threading.EventWaitHandle); throw null; }
+ }
+ public sealed partial class ExecutionContext : System.IDisposable
+ {
+ internal ExecutionContext() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Threading.ExecutionContext Capture() { throw null; }
+ public void Dispose() { }
+ [System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute]
+ [System.Security.SecurityCriticalAttribute]
+ public static void Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) { }
+ }
+ public static partial class Interlocked
+ {
+ public static int Add(ref int location1, int value) { throw null; }
+ public static long Add(ref long location1, long value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double CompareExchange(ref double location1, double value, double comparand) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static int CompareExchange(ref int location1, int value, int comparand) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static long CompareExchange(ref long location1, long value, long comparand) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.IntPtr CompareExchange(ref System.IntPtr location1, System.IntPtr value, System.IntPtr comparand) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static object CompareExchange(ref object location1, object value, object comparand) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float CompareExchange(ref float location1, float value, float comparand) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class { throw null; }
+ public static int Decrement(ref int location) { throw null; }
+ public static long Decrement(ref long location) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static double Exchange(ref double location1, double value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static int Exchange(ref int location1, int value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static long Exchange(ref long location1, long value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.IntPtr Exchange(ref System.IntPtr location1, System.IntPtr value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static object Exchange(ref object location1, object value) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static float Exchange(ref float location1, float value) { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static T Exchange<T>(ref T location1, T value) where T : class { throw null; }
+ public static int Increment(ref int location) { throw null; }
+ public static long Increment(ref long location) { throw null; }
+ public static void MemoryBarrier() { }
+ public static long Read(ref long location) { throw null; }
+ }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe delegate void IOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP);
+ public static partial class LazyInitializer
+ {
+ public static T EnsureInitialized<T>(ref T target) where T : class { throw null; }
+ public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock) { throw null; }
+ public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock, System.Func<T> valueFactory) { throw null; }
+ public static T EnsureInitialized<T>(ref T target, System.Func<T> valueFactory) where T : class { throw null; }
+ }
+ public enum LazyThreadSafetyMode
+ {
+ ExecutionAndPublication = 2,
+ None = 0,
+ PublicationOnly = 1,
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+ public partial class LockRecursionException : System.Exception
+ {
+ public LockRecursionException() { }
+ public LockRecursionException(string message) { }
+ public LockRecursionException(string message, System.Exception innerException) { }
+ protected LockRecursionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ManualResetEvent : System.Threading.EventWaitHandle
+ {
+ public ManualResetEvent(bool initialState) : base (default(bool), default(System.Threading.EventResetMode)) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Set = {IsSet}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class ManualResetEventSlim : System.IDisposable
+ {
+ public ManualResetEventSlim() { }
+ public ManualResetEventSlim(bool initialState) { }
+ public ManualResetEventSlim(bool initialState, int spinCount) { }
+ public bool IsSet { get { throw null; } }
+ public int SpinCount { get { throw null; } }
+ public System.Threading.WaitHandle WaitHandle { get { throw null; } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public void Reset() { }
+ public void Set() { }
+ public void Wait() { }
+ public bool Wait(int millisecondsTimeout) { throw null; }
+ public bool Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Wait(System.Threading.CancellationToken cancellationToken) { }
+ public bool Wait(System.TimeSpan timeout) { throw null; }
+ public bool Wait(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Monitor
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void Enter(object obj) { }
+ public static void Enter(object obj, ref bool lockTaken) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void Exit(object obj) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static bool IsEntered(object obj) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Pulse(object obj) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void PulseAll(object obj) { }
+ public static bool TryEnter(object obj) { throw null; }
+ public static void TryEnter(object obj, ref bool lockTaken) { }
+ public static bool TryEnter(object obj, int millisecondsTimeout) { throw null; }
+ public static void TryEnter(object obj, int millisecondsTimeout, ref bool lockTaken) { }
+ public static bool TryEnter(object obj, System.TimeSpan timeout) { throw null; }
+ public static void TryEnter(object obj, System.TimeSpan timeout, ref bool lockTaken) { }
+ public static bool Wait(object obj) { throw null; }
+ public static bool Wait(object obj, int millisecondsTimeout) { throw null; }
+ public static bool Wait(object obj, System.TimeSpan timeout) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Mutex : System.Threading.WaitHandle
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Mutex() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Mutex(bool initiallyOwned) { }
+ [System.Security.SecurityCriticalAttribute]
+ public Mutex(bool initiallyOwned, string name) { }
+ [System.Security.SecurityCriticalAttribute]
+ public Mutex(bool initiallyOwned, string name, out bool createdNew) { createdNew = default(bool); }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Threading.Mutex OpenExisting(string name) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void ReleaseMutex() { }
+ [System.Security.SecurityCriticalAttribute]
+ public static bool TryOpenExisting(string name, out System.Threading.Mutex result) { result = default(System.Threading.Mutex); throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct NativeOverlapped
+ {
+ public System.IntPtr EventHandle;
+ public System.IntPtr InternalHigh;
+ public System.IntPtr InternalLow;
+ public int OffsetHigh;
+ public int OffsetLow;
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class Overlapped
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Overlapped() { }
+ public System.IAsyncResult AsyncResult { get { throw null; } set { } }
+ public int OffsetHigh { get { throw null; } set { } }
+ public int OffsetLow { get { throw null; } set { } }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static void Free(System.Threading.NativeOverlapped* nativeOverlappedPtr) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe System.Threading.NativeOverlapped* Pack(System.Threading.IOCompletionCallback iocb, object userData) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe static System.Threading.Overlapped Unpack(System.Threading.NativeOverlapped* nativeOverlappedPtr) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Security.SecurityCriticalAttribute]
+ public unsafe System.Threading.NativeOverlapped* UnsafePack(System.Threading.IOCompletionCallback iocb, object userData) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public delegate void ParameterizedThreadStart(object obj);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class RegisteredWaitHandle
+ {
+ internal RegisteredWaitHandle() { }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Unregister(System.Threading.WaitHandle waitObject) { throw null; }
+ }
+ public sealed partial class Semaphore : System.Threading.WaitHandle
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Semaphore(int initialCount, int maximumCount) { }
+ [System.Security.SecurityCriticalAttribute]
+ public Semaphore(int initialCount, int maximumCount, string name) { }
+ [System.Security.SecurityCriticalAttribute]
+ public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew) { createdNew = default(bool); }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Threading.Semaphore OpenExisting(string name) { throw null; }
+ public int Release() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public int Release(int releaseCount) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static bool TryOpenExisting(string name, out System.Threading.Semaphore result) { result = default(System.Threading.Semaphore); throw null; }
+ }
+ [System.Runtime.CompilerServices.TypeForwardedFromAttribute("System, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class SemaphoreFullException : System.SystemException
+ {
+ public SemaphoreFullException() { }
+ public SemaphoreFullException(string message) { }
+ public SemaphoreFullException(string message, System.Exception innerException) { }
+ protected SemaphoreFullException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Current Count = {m_currentCount}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class SemaphoreSlim : System.IDisposable
+ {
+ public SemaphoreSlim(int initialCount) { }
+ public SemaphoreSlim(int initialCount, int maxCount) { }
+ public System.Threading.WaitHandle AvailableWaitHandle { get { throw null; } }
+ public int CurrentCount { get { throw null; } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public int Release() { throw null; }
+ public int Release(int releaseCount) { throw null; }
+ public void Wait() { }
+ public bool Wait(int millisecondsTimeout) { throw null; }
+ public bool Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Wait(System.Threading.CancellationToken cancellationToken) { }
+ public bool Wait(System.TimeSpan timeout) { throw null; }
+ public bool Wait(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task WaitAsync() { throw null; }
+ public System.Threading.Tasks.Task<bool> WaitAsync(int millisecondsTimeout) { throw null; }
+ public System.Threading.Tasks.Task<bool> WaitAsync(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task WaitAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public System.Threading.Tasks.Task<bool> WaitAsync(System.TimeSpan timeout) { throw null; }
+ public System.Threading.Tasks.Task<bool> WaitAsync(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ }
+ public delegate void SendOrPostCallback(object state);
+ [System.Diagnostics.DebuggerDisplayAttribute("IsHeld = {IsHeld}")]
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct SpinLock
+ {
+ public SpinLock(bool enableThreadOwnerTracking) { throw null;}
+ public bool IsHeld { get { throw null; } }
+ public bool IsHeldByCurrentThread { get { throw null; } }
+ public bool IsThreadOwnerTrackingEnabled { get { throw null; } }
+ public void Enter(ref bool lockTaken) { }
+ public void Exit() { }
+ public void Exit(bool useMemoryBarrier) { }
+ public void TryEnter(ref bool lockTaken) { }
+ public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { }
+ public void TryEnter(System.TimeSpan timeout, ref bool lockTaken) { }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct SpinWait
+ {
+ public int Count { get { throw null; } }
+ public bool NextSpinWillYield { get { throw null; } }
+ public void Reset() { }
+ public void SpinOnce() { }
+ public static void SpinUntil(System.Func<bool> condition) { }
+ public static bool SpinUntil(System.Func<bool> condition, int millisecondsTimeout) { throw null; }
+ public static bool SpinUntil(System.Func<bool> condition, System.TimeSpan timeout) { throw null; }
+ }
+ public partial class SynchronizationContext
+ {
+ public SynchronizationContext() { }
+ public static System.Threading.SynchronizationContext Current { get { throw null; } }
+ public virtual System.Threading.SynchronizationContext CreateCopy() { throw null; }
+ public virtual void OperationCompleted() { }
+ public virtual void OperationStarted() { }
+ public virtual void Post(System.Threading.SendOrPostCallback d, object state) { }
+ public virtual void Send(System.Threading.SendOrPostCallback d, object state) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void SetSynchronizationContext(System.Threading.SynchronizationContext syncContext) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class SynchronizationLockException : System.SystemException
+ {
+ public SynchronizationLockException() { }
+ public SynchronizationLockException(string message) { }
+ public SynchronizationLockException(string message, System.Exception innerException) { }
+ protected SynchronizationLockException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ClassInterfaceAttribute((System.Runtime.InteropServices.ClassInterfaceType)(0))]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject
+ {
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Thread(System.Threading.ParameterizedThreadStart start) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Thread(System.Threading.ThreadStart start) { }
+ public System.Globalization.CultureInfo CurrentCulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public static System.Threading.Thread CurrentThread { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ public System.Globalization.CultureInfo CurrentUICulture { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public bool IsAlive { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public bool IsBackground { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public int ManagedThreadId { [System.Security.SecuritySafeCriticalAttribute][System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public string Name { get { throw null; } [System.Security.SecuritySafeCriticalAttribute]set { } }
+ public System.Threading.ThreadState ThreadState { [System.Security.SecuritySafeCriticalAttribute]get { throw null; } }
+ ~Thread() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.AppDomain GetDomain() { throw null; }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public override int GetHashCode() { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public void Join() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public bool Join(int millisecondsTimeout) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)][System.Security.SecuritySafeCriticalAttribute]
+ public static void MemoryBarrier() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Sleep(int millisecondsTimeout) { }
+ public static void Sleep(System.TimeSpan timeout) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void SpinWait(int iterations) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public void Start() { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public void Start(object parameter) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class ThreadAbortException : System.SystemException
+ {
+ internal ThreadAbortException() { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")]
+ public partial class ThreadLocal<T> : System.IDisposable
+ {
+ public ThreadLocal() { }
+ public ThreadLocal(bool trackAllValues) { }
+ public ThreadLocal(System.Func<T> valueFactory) { }
+ public ThreadLocal(System.Func<T> valueFactory, bool trackAllValues) { }
+ public bool IsValueCreated { get { throw null; } }
+ [System.Diagnostics.DebuggerBrowsableAttribute((System.Diagnostics.DebuggerBrowsableState)(0))]
+ public T Value { get { throw null; } set { } }
+ public System.Collections.Generic.IList<T> Values { get { throw null; } }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ ~ThreadLocal() { }
+ public override string ToString() { throw null; }
+ }
+ public static partial class ThreadPool
+ {
+ [System.Security.SecurityCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, Flags=(System.Security.Permissions.SecurityPermissionFlag)(2))]
+ public static bool BindHandle(System.Runtime.InteropServices.SafeHandle osHandle) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void GetMaxThreads(out int workerThreads, out int completionPortThreads) { workerThreads = default(int); completionPortThreads = default(int); }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void GetMinThreads(out int workerThreads, out int completionPortThreads) { workerThreads = default(int); completionPortThreads = default(int); }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static bool QueueUserWorkItem(System.Threading.WaitCallback callBack) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static bool QueueUserWorkItem(System.Threading.WaitCallback callBack, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, int millisecondsTimeOutInterval, bool executeOnlyOnce) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, long millisecondsTimeOutInterval, bool executeOnlyOnce) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, System.TimeSpan timeout, bool executeOnlyOnce) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static System.Threading.RegisteredWaitHandle RegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, uint millisecondsTimeOutInterval, bool executeOnlyOnce) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, ControlThread=true)]
+ public static bool SetMaxThreads(int workerThreads, int completionPortThreads) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.Demand, ControlThread=true)]
+ public static bool SetMinThreads(int workerThreads, int completionPortThreads) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void ThreadStart();
+ public sealed partial class ThreadStartException : System.SystemException
+ {
+ internal ThreadStartException() { }
+ }
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum ThreadState
+ {
+ Aborted = 256,
+ AbortRequested = 128,
+ Background = 4,
+ Running = 0,
+ Stopped = 16,
+ StopRequested = 1,
+ Suspended = 64,
+ SuspendRequested = 2,
+ Unstarted = 8,
+ WaitSleepJoin = 32,
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public partial class ThreadStateException : System.SystemException
+ {
+ public ThreadStateException() { }
+ public ThreadStateException(string message) { }
+ public ThreadStateException(string message, System.Exception innerException) { }
+ protected ThreadStateException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public static partial class Timeout
+ {
+ public const int Infinite = -1;
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public static readonly System.TimeSpan InfiniteTimeSpan;
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public sealed partial class Timer : System.IDisposable
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public Timer(System.Threading.TimerCallback callback) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public Timer(System.Threading.TimerCallback callback, object state, int dueTime, int period) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public Timer(System.Threading.TimerCallback callback, object state, long dueTime, long period) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.Security.SecuritySafeCriticalAttribute]
+ public Timer(System.Threading.TimerCallback callback, object state, System.TimeSpan dueTime, System.TimeSpan period) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)][System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public Timer(System.Threading.TimerCallback callback, object state, uint dueTime, uint period) { }
+ public bool Change(int dueTime, int period) { throw null; }
+ public bool Change(long dueTime, long period) { throw null; }
+ public bool Change(System.TimeSpan dueTime, System.TimeSpan period) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public bool Change(uint dueTime, uint period) { throw null; }
+ public void Dispose() { }
+ public bool Dispose(System.Threading.WaitHandle notifyObject) { throw null; }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void TimerCallback(object state);
+ public static partial class Volatile
+ {
+ public static bool Read(ref bool location) { throw null; }
+ public static byte Read(ref byte location) { throw null; }
+ public static double Read(ref double location) { throw null; }
+ public static short Read(ref short location) { throw null; }
+ public static int Read(ref int location) { throw null; }
+ public static long Read(ref long location) { throw null; }
+ public static System.IntPtr Read(ref System.IntPtr location) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static sbyte Read(ref sbyte location) { throw null; }
+ public static float Read(ref float location) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static ushort Read(ref ushort location) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static uint Read(ref uint location) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static ulong Read(ref ulong location) { throw null; }
+ [System.CLSCompliantAttribute(false)]
+ public static System.UIntPtr Read(ref System.UIntPtr location) { throw null; }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static T Read<T>(ref T location) where T : class { throw null; }
+ public static void Write(ref bool location, bool value) { }
+ public static void Write(ref byte location, byte value) { }
+ public static void Write(ref double location, double value) { }
+ public static void Write(ref short location, short value) { }
+ public static void Write(ref int location, int value) { }
+ public static void Write(ref long location, long value) { }
+ public static void Write(ref System.IntPtr location, System.IntPtr value) { }
+ [System.CLSCompliantAttribute(false)]
+ public static void Write(ref sbyte location, sbyte value) { }
+ public static void Write(ref float location, float value) { }
+ [System.CLSCompliantAttribute(false)]
+ public static void Write(ref ushort location, ushort value) { }
+ [System.CLSCompliantAttribute(false)]
+ public static void Write(ref uint location, uint value) { }
+ [System.CLSCompliantAttribute(false)]
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Write(ref ulong location, ulong value) { }
+ [System.CLSCompliantAttribute(false)]
+ public static void Write(ref System.UIntPtr location, System.UIntPtr value) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ public static void Write<T>(ref T location, T value) where T : class { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void WaitCallback(object state);
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public abstract partial class WaitHandle : System.IDisposable
+ {
+ protected static readonly System.IntPtr InvalidHandle;
+ public const int WaitTimeout = 258;
+ protected WaitHandle() { }
+ [System.ObsoleteAttribute("Use the SafeWaitHandle property instead.")]
+ public virtual System.IntPtr Handle { [System.Security.SecuritySafeCriticalAttribute]get { return default(System.IntPtr); } [System.Security.SecurityCriticalAttribute]set { } }
+ public Microsoft.Win32.SafeHandles.SafeWaitHandle SafeWaitHandle { [System.Security.SecurityCriticalAttribute]get { throw null; } [System.Security.SecurityCriticalAttribute]set { } }
+ public virtual void Close() { }
+ public void Dispose() { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ protected virtual void Dispose(bool explicitDisposing) { }
+ public static bool SignalAndWait(System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn) { return default(bool); }
+ public static bool SignalAndWait(System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn, int millisecondsTimeout, bool exitContext) { return default(bool); }
+ public static bool SignalAndWait(System.Threading.WaitHandle toSignal, System.Threading.WaitHandle toWaitOn, System.TimeSpan timeout, bool exitContext) { return default(bool); }
+ public static bool WaitAll(System.Threading.WaitHandle[] waitHandles) { throw null; }
+ public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout) { throw null; }
+ public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { return default(bool); }
+ public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, System.TimeSpan timeout) { throw null; }
+ public static bool WaitAll(System.Threading.WaitHandle[] waitHandles, System.TimeSpan timeout, bool exitContext) { return default(bool); }
+ public static int WaitAny(System.Threading.WaitHandle[] waitHandles) { throw null; }
+ public static int WaitAny(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout) { throw null; }
+ public static int WaitAny(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) { return default(int); }
+ public static int WaitAny(System.Threading.WaitHandle[] waitHandles, System.TimeSpan timeout) { throw null; }
+ public static int WaitAny(System.Threading.WaitHandle[] waitHandles, System.TimeSpan timeout, bool exitContext) { return default(int); }
+ public virtual bool WaitOne() { throw null; }
+ public virtual bool WaitOne(int millisecondsTimeout) { throw null; }
+ public virtual bool WaitOne(int millisecondsTimeout, bool exitContext) { return default(bool); }
+ public virtual bool WaitOne(System.TimeSpan timeout) { throw null; }
+ public virtual bool WaitOne(System.TimeSpan timeout, bool exitContext) { return default(bool); }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(false)]
+ public partial class WaitHandleCannotBeOpenedException : System.Exception
+ {
+ public WaitHandleCannotBeOpenedException() { }
+ public WaitHandleCannotBeOpenedException(string message) { }
+ public WaitHandleCannotBeOpenedException(string message, System.Exception innerException) { }
+ protected WaitHandleCannotBeOpenedException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ public static partial class WaitHandleExtensions
+ {
+ [System.Security.SecurityCriticalAttribute]
+ public static Microsoft.Win32.SafeHandles.SafeWaitHandle GetSafeWaitHandle(this System.Threading.WaitHandle waitHandle) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void SetSafeWaitHandle(this System.Threading.WaitHandle waitHandle, Microsoft.Win32.SafeHandles.SafeWaitHandle value) { }
+ }
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public delegate void WaitOrTimerCallback(object state, bool timedOut);
+}
+namespace System.Threading.Tasks
+{
+ [System.Diagnostics.DebuggerDisplayAttribute("Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger}")]
+ public partial class ConcurrentExclusiveSchedulerPair
+ {
+ public ConcurrentExclusiveSchedulerPair() { }
+ public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler) { }
+ public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler, int maxConcurrencyLevel) { }
+ public ConcurrentExclusiveSchedulerPair(System.Threading.Tasks.TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask) { }
+ public System.Threading.Tasks.Task Completion { get { throw null; } }
+ public System.Threading.Tasks.TaskScheduler ConcurrentScheduler { get { throw null; } }
+ public System.Threading.Tasks.TaskScheduler ExclusiveScheduler { get { throw null; } }
+ public void Complete() { }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
+ public partial class Task : System.IAsyncResult, System.IDisposable
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action action) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action action, System.Threading.CancellationToken cancellationToken) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action action, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action action, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action<object> action, object state) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action<object> action, object state, System.Threading.CancellationToken cancellationToken) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action<object> action, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Action<object> action, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ public object AsyncState { get { throw null; } }
+ public static System.Threading.Tasks.Task CompletedTask { get { throw null; } }
+ public System.Threading.Tasks.TaskCreationOptions CreationOptions { get { throw null; } }
+ public static System.Nullable<int> CurrentId { get { throw null; } }
+ public System.AggregateException Exception { get { throw null; } }
+ public static System.Threading.Tasks.TaskFactory Factory { get { throw null; } }
+ public int Id { get { throw null; } }
+ public bool IsCanceled { get { throw null; } }
+ public bool IsCompleted { get { throw null; } }
+ public bool IsFaulted { get { throw null; } }
+ public System.Threading.Tasks.TaskStatus Status { get { throw null; } }
+ System.Threading.WaitHandle System.IAsyncResult.AsyncWaitHandle { get { throw null; } }
+ bool System.IAsyncResult.CompletedSynchronously { get { throw null; } }
+ public System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task, object> continuationAction, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task, object> continuationAction, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task, object> continuationAction, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task, object> continuationAction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task, object> continuationAction, object state, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, object, TResult> continuationFunction, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, object, TResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, object, TResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, object, TResult> continuationFunction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWith<TResult>(System.Func<System.Threading.Tasks.Task, object, TResult> continuationFunction, object state, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ public static System.Threading.Tasks.Task Delay(int millisecondsDelay) { throw null; }
+ public static System.Threading.Tasks.Task Delay(int millisecondsDelay, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task Delay(System.TimeSpan delay) { throw null; }
+ public static System.Threading.Tasks.Task Delay(System.TimeSpan delay, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public static System.Threading.Tasks.Task FromCanceled(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<TResult> FromCanceled<TResult>(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task FromException(System.Exception exception) { throw null; }
+ public static System.Threading.Tasks.Task<TResult> FromException<TResult>(System.Exception exception) { throw null; }
+ public static System.Threading.Tasks.Task<TResult> FromResult<TResult>(TResult result) { throw null; }
+ public System.Runtime.CompilerServices.TaskAwaiter GetAwaiter() { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Threading.Tasks.Task Run(System.Action action) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Threading.Tasks.Task Run(System.Action action, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task Run(System.Func<System.Threading.Tasks.Task> function) { throw null; }
+ public static System.Threading.Tasks.Task Run(System.Func<System.Threading.Tasks.Task> function, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Threading.Tasks.Task<TResult> Run<TResult>(System.Func<TResult> function) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public static System.Threading.Tasks.Task<TResult> Run<TResult>(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public static System.Threading.Tasks.Task<TResult> Run<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> function) { throw null; }
+ public static System.Threading.Tasks.Task<TResult> Run<TResult>(System.Func<System.Threading.Tasks.Task<TResult>> function, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void RunSynchronously() { }
+ public void RunSynchronously(System.Threading.Tasks.TaskScheduler scheduler) { }
+ public void Start() { }
+ public void Start(System.Threading.Tasks.TaskScheduler scheduler) { }
+ public void Wait() { }
+ public bool Wait(int millisecondsTimeout) { throw null; }
+ public bool Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public void Wait(System.Threading.CancellationToken cancellationToken) { }
+ public bool Wait(System.TimeSpan timeout) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static void WaitAll(params System.Threading.Tasks.Task[] tasks) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static bool WaitAll(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static bool WaitAll(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static void WaitAll(System.Threading.Tasks.Task[] tasks, System.Threading.CancellationToken cancellationToken) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static bool WaitAll(System.Threading.Tasks.Task[] tasks, System.TimeSpan timeout) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static int WaitAny(params System.Threading.Tasks.Task[] tasks) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static int WaitAny(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static int WaitAny(System.Threading.Tasks.Task[] tasks, int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static int WaitAny(System.Threading.Tasks.Task[] tasks, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoOptimization)]public static int WaitAny(System.Threading.Tasks.Task[] tasks, System.TimeSpan timeout) { throw null; }
+ public static System.Threading.Tasks.Task WhenAll(System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task> tasks) { throw null; }
+ public static System.Threading.Tasks.Task WhenAll(params System.Threading.Tasks.Task[] tasks) { throw null; }
+ public static System.Threading.Tasks.Task<TResult[]> WhenAll<TResult>(System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<TResult>> tasks) { throw null; }
+ public static System.Threading.Tasks.Task<TResult[]> WhenAll<TResult>(params System.Threading.Tasks.Task<TResult>[] tasks) { throw null; }
+ public static System.Threading.Tasks.Task<System.Threading.Tasks.Task> WhenAny(System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task> tasks) { throw null; }
+ public static System.Threading.Tasks.Task<System.Threading.Tasks.Task> WhenAny(params System.Threading.Tasks.Task[] tasks) { throw null; }
+ public static System.Threading.Tasks.Task<System.Threading.Tasks.Task<TResult>> WhenAny<TResult>(System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<TResult>> tasks) { throw null; }
+ public static System.Threading.Tasks.Task<System.Threading.Tasks.Task<TResult>> WhenAny<TResult>(params System.Threading.Tasks.Task<TResult>[] tasks) { throw null; }
+ public static System.Runtime.CompilerServices.YieldAwaitable Yield() { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
+ public partial class Task<TResult> : System.Threading.Tasks.Task
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<TResult> function) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<TResult> function, System.Threading.Tasks.TaskCreationOptions creationOptions) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<object, TResult> function, object state) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions) : base (default(System.Action)) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public Task(System.Func<object, TResult> function, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) : base (default(System.Action)) { }
+ public static new System.Threading.Tasks.TaskFactory<TResult> Factory { get { throw null; } }
+ [System.Diagnostics.DebuggerBrowsableAttribute((System.Diagnostics.DebuggerBrowsableState)(0))]
+ public TResult Result { get { throw null; } }
+ public new System.Runtime.CompilerServices.ConfiguredTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>, object> continuationAction, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>, object> continuationAction, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>, object> continuationAction, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>, object> continuationAction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>, object> continuationAction, object state, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWith(System.Action<System.Threading.Tasks.Task<TResult>> continuationAction, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, TNewResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, TNewResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, TNewResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, TNewResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, TNewResult> continuationFunction, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, object, TNewResult> continuationFunction, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, object, TNewResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, object, TNewResult> continuationFunction, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, object, TNewResult> continuationFunction, object state, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TNewResult> ContinueWith<TNewResult>(System.Func<System.Threading.Tasks.Task<TResult>, object, TNewResult> continuationFunction, object state, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ public new System.Runtime.CompilerServices.TaskAwaiter<TResult> GetAwaiter() { throw null; }
+ }
+ public partial class TaskCanceledException : System.OperationCanceledException
+ {
+ public TaskCanceledException() { }
+ public TaskCanceledException(string message) { }
+ public TaskCanceledException(string message, System.Exception innerException) { }
+ public TaskCanceledException(System.Threading.Tasks.Task task) { }
+ protected TaskCanceledException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ public System.Threading.Tasks.Task Task { get { throw null; } }
+ }
+ public partial class TaskCompletionSource<TResult>
+ {
+ public TaskCompletionSource() { }
+ public TaskCompletionSource(object state) { }
+ public TaskCompletionSource(object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ public TaskCompletionSource(System.Threading.Tasks.TaskCreationOptions creationOptions) { }
+ public System.Threading.Tasks.Task<TResult> Task { get { throw null; } }
+ public void SetCanceled() { }
+ public void SetException(System.Collections.Generic.IEnumerable<System.Exception> exceptions) { }
+ public void SetException(System.Exception exception) { }
+ public void SetResult(TResult result) { }
+ public bool TrySetCanceled() { throw null; }
+ public bool TrySetCanceled(System.Threading.CancellationToken cancellationToken) { throw null; }
+ public bool TrySetException(System.Collections.Generic.IEnumerable<System.Exception> exceptions) { throw null; }
+ public bool TrySetException(System.Exception exception) { throw null; }
+ public bool TrySetResult(TResult result) { throw null; }
+ }
+ [System.FlagsAttribute]
+ public enum TaskContinuationOptions
+ {
+ AttachedToParent = 4,
+ DenyChildAttach = 8,
+ ExecuteSynchronously = 524288,
+ HideScheduler = 16,
+ LazyCancellation = 32,
+ LongRunning = 2,
+ None = 0,
+ NotOnCanceled = 262144,
+ NotOnFaulted = 131072,
+ NotOnRanToCompletion = 65536,
+ OnlyOnCanceled = 196608,
+ OnlyOnFaulted = 327680,
+ OnlyOnRanToCompletion = 393216,
+ PreferFairness = 1,
+ RunContinuationsAsynchronously = 64,
+ }
+ [System.FlagsAttribute]
+ public enum TaskCreationOptions
+ {
+ AttachedToParent = 4,
+ DenyChildAttach = 8,
+ HideScheduler = 16,
+ LongRunning = 2,
+ None = 0,
+ PreferFairness = 1,
+ RunContinuationsAsynchronously = 64,
+ }
+ public partial class TaskFactory
+ {
+ public TaskFactory() { }
+ public TaskFactory(System.Threading.CancellationToken cancellationToken) { }
+ public TaskFactory(System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { }
+ public TaskFactory(System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { }
+ public TaskFactory(System.Threading.Tasks.TaskScheduler scheduler) { }
+ public System.Threading.CancellationToken CancellationToken { get { throw null; } }
+ public System.Threading.Tasks.TaskContinuationOptions ContinuationOptions { get { throw null; } }
+ public System.Threading.Tasks.TaskCreationOptions CreationOptions { get { throw null; } }
+ public System.Threading.Tasks.TaskScheduler Scheduler { get { throw null; } }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task[]> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task[]> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task[]> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task[]> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>[]> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>[]> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>[]> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>[]> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Action<System.Threading.Tasks.Task> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TResult>(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>> continuationAction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>> continuationAction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>> continuationAction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Action<System.Threading.Tasks.Task<TAntecedentResult>> continuationAction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ public System.Threading.Tasks.Task FromAsync(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, object state) { throw null; }
+ public System.Threading.Tasks.Task FromAsync(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task FromAsync(System.IAsyncResult asyncResult, System.Action<System.IAsyncResult> endMethod) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task FromAsync(System.IAsyncResult asyncResult, System.Action<System.IAsyncResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task FromAsync(System.IAsyncResult asyncResult, System.Action<System.IAsyncResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, object state) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TResult>(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TResult>(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync<TResult>(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync<TResult>(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync<TResult>(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1, TArg2>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, TArg2 arg2, object state) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1, TArg2>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, TArg2 arg2, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TResult>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TResult>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1, TArg2, TArg3>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state) { throw null; }
+ public System.Threading.Tasks.Task FromAsync<TArg1, TArg2, TArg3>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Action<System.IAsyncResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TResult>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TResult>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action action) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action action, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action action, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action action, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action<object> action, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action<object> action, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action<object> action, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task StartNew(System.Action<object> action, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<TResult> function) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<TResult> function, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<object, TResult> function, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew<TResult>(System.Func<object, TResult> function, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ }
+ public partial class TaskFactory<TResult>
+ {
+ public TaskFactory() { }
+ public TaskFactory(System.Threading.CancellationToken cancellationToken) { }
+ public TaskFactory(System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { }
+ public TaskFactory(System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { }
+ public TaskFactory(System.Threading.Tasks.TaskScheduler scheduler) { }
+ public System.Threading.CancellationToken CancellationToken { get { throw null; } }
+ public System.Threading.Tasks.TaskContinuationOptions ContinuationOptions { get { throw null; } }
+ public System.Threading.Tasks.TaskCreationOptions CreationOptions { get { throw null; } }
+ public System.Threading.Tasks.TaskScheduler Scheduler { get { throw null; } }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task[], TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAll<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>[], TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny(System.Threading.Tasks.Task[] tasks, System.Func<System.Threading.Tasks.Task, TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> ContinueWhenAny<TAntecedentResult>(System.Threading.Tasks.Task<TAntecedentResult>[] tasks, System.Func<System.Threading.Tasks.Task<TAntecedentResult>, TResult> continuationFunction, System.Threading.Tasks.TaskContinuationOptions continuationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync(System.Func<System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> FromAsync(System.IAsyncResult asyncResult, System.Func<System.IAsyncResult, TResult> endMethod, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1>(System.Func<TArg1, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2>(System.Func<TArg1, TArg2, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TArg3>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state) { throw null; }
+ public System.Threading.Tasks.Task<TResult> FromAsync<TArg1, TArg2, TArg3>(System.Func<TArg1, TArg2, TArg3, System.AsyncCallback, object, System.IAsyncResult> beginMethod, System.Func<System.IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<TResult> function) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<TResult> function, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<TResult> function, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<object, TResult> function, object state) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<object, TResult> function, object state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskCreationOptions creationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]public System.Threading.Tasks.Task<TResult> StartNew(System.Func<object, TResult> function, object state, System.Threading.Tasks.TaskCreationOptions creationOptions) { throw null; }
+ }
+ [System.Diagnostics.DebuggerDisplayAttribute("Id={Id}")]
+ public abstract partial class TaskScheduler
+ {
+ protected TaskScheduler() { }
+ public static System.Threading.Tasks.TaskScheduler Current { get { throw null; } }
+ public static System.Threading.Tasks.TaskScheduler Default { get { throw null; } }
+ public int Id { get { throw null; } }
+ public virtual int MaximumConcurrencyLevel { get { throw null; } }
+ public static event System.EventHandler<System.Threading.Tasks.UnobservedTaskExceptionEventArgs> UnobservedTaskException { add { } remove { } }
+ public static System.Threading.Tasks.TaskScheduler FromCurrentSynchronizationContext() { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ protected abstract System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task> GetScheduledTasks();
+ [System.Security.SecurityCriticalAttribute]
+ protected internal abstract void QueueTask(System.Threading.Tasks.Task task);
+ [System.Security.SecurityCriticalAttribute]
+ protected internal virtual bool TryDequeue(System.Threading.Tasks.Task task) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ protected bool TryExecuteTask(System.Threading.Tasks.Task task) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ protected abstract bool TryExecuteTaskInline(System.Threading.Tasks.Task task, bool taskWasPreviouslyQueued);
+ }
+ public partial class TaskSchedulerException : System.Exception
+ {
+ public TaskSchedulerException() { }
+ public TaskSchedulerException(System.Exception innerException) { }
+ public TaskSchedulerException(string message) { }
+ public TaskSchedulerException(string message, System.Exception innerException) { }
+ protected TaskSchedulerException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
+ }
+ public enum TaskStatus
+ {
+ Canceled = 6,
+ Created = 0,
+ Faulted = 7,
+ RanToCompletion = 5,
+ Running = 3,
+ WaitingForActivation = 1,
+ WaitingForChildrenToComplete = 4,
+ WaitingToRun = 2,
+ }
+ public partial class UnobservedTaskExceptionEventArgs : System.EventArgs
+ {
+ public UnobservedTaskExceptionEventArgs(System.AggregateException exception) { }
+ public System.AggregateException Exception { get { throw null; } }
+ public bool Observed { get { throw null; } }
+ public void SetObserved() { }
+ }
+}
diff --git a/src/mscorlib/ref/mscorlib.csproj b/src/mscorlib/ref/mscorlib.csproj
new file mode 100644
index 0000000000..30da2de8f3
--- /dev/null
+++ b/src/mscorlib/ref/mscorlib.csproj
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+
+ <!-- Include common build properties -->
+ <Import Project="..\..\..\dir.props" />
+
+ <!-- Compilation options -->
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">$(BuildType)</Configuration>
+ <PlatformTarget>AnyCPU</PlatformTarget>
+
+ <ProjectGuid>{B8ADD332-40B6-4916-B418-FBB79E5898B3}</ProjectGuid>
+
+ <OutputType>Library</OutputType>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+
+ <!-- This prevents the default MsBuild targets from referencing System.Core.dll -->
+ <AddAdditionalExplicitAssemblyReferences>false</AddAdditionalExplicitAssemblyReferences>
+ <!-- These prevent the default MsBuild targets from referencing System.dll and mscorlib.dll -->
+ <NoStdLib>true</NoStdLib>
+ <NoCompilerStandardLib>true</NoCompilerStandardLib>
+
+ <ErrorReport>prompt</ErrorReport>
+ <Optimize Condition="'$(Optimize)' == ''">true</Optimize>
+ <CLSCompliant>true</CLSCompliant>
+ <WarningLevel>4</WarningLevel>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <WarningsNotAsErrors>$(WarningsNotAsErrors);618</WarningsNotAsErrors>
+ <NoWarn>618,649,3019,414,169,3015,3021</NoWarn>
+ <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
+
+ <SignAssembly>true</SignAssembly>
+ <DelaySign>true</DelaySign>
+ </PropertyGroup>
+
+ <!-- On Windows we support FEATURE_COMINTEROP and FEATURE_COREFX_GLOBALIZATION -->
+ <PropertyGroup Condition="'$(TargetsUnix)'!='true'">
+ <DefineConstants>$(DefineConstants);FEATURE_COREFX_GLOBALIZATION;FEATURE_COMINTEROP</DefineConstants>
+ </PropertyGroup>
+
+ <!-- Roslyn does not support writing PDBs on Unix -->
+ <PropertyGroup Condition="'$(OsEnvironment)' == 'Unix'">
+ <DebugSymbols>false</DebugSymbols>
+ <DebugType>none</DebugType>
+ </PropertyGroup>
+
+ <!-- Assembly attributes -->
+ <PropertyGroup>
+ <AssemblyName>mscorlib</AssemblyName>
+ <AssemblyVersion>4.0.0.0</AssemblyVersion>
+ <MajorVersion>4</MajorVersion>
+ <MinorVersion>6</MinorVersion>
+ </PropertyGroup>
+
+ <!-- Output paths -->
+ <PropertyGroup>
+ <BaseIntermediateOutputPath>$(RootBinDir)\obj</BaseIntermediateOutputPath>
+ <IntermediateOutputPath>$(BaseIntermediateOutputPath)\$(BuildOS).$(BuildArch).$(Configuration)\ref</IntermediateOutputPath>
+ <OutputPath>$(BinDir)\ref</OutputPath>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <Compile Include="$(MSBuildThisFileDirectory)\mscorlib.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)\mscorlib.manual.cs" />
+ </ItemGroup>
+
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.Targets" />
+
+ <PropertyGroup>
+ <StrongNameSig>Silverlight</StrongNameSig>
+ </PropertyGroup>
+
+ <!-- Import signing tools -->
+ <Import Condition="Exists('$(ToolsDir)\sign.targets')" Project="$(ToolsDir)\sign.targets" />
+
+ <!-- Overwrite the key that we are going to use for signing -->
+ <PropertyGroup>
+ <AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)..\Tools\Signing\mscorlib.snk</AssemblyOriginatorKeyFile>
+ </PropertyGroup>
+
+ <Import Project="$(MSBuildThisFileDirectory)..\Tools\Versioning\GenerateVersionInfo.targets"/>
+ <!-- Override versioning targets -->
+ <Import Condition="Exists('$(ToolsDir)versioning.targets')" Project="$(ToolsDir)versioning.targets" />
+ <Import Project="..\GenerateCompilerResponseFile.targets"/>
+</Project>
diff --git a/src/mscorlib/ref/mscorlib.manual.cs b/src/mscorlib/ref/mscorlib.manual.cs
new file mode 100644
index 0000000000..d7c1f5e274
--- /dev/null
+++ b/src/mscorlib/ref/mscorlib.manual.cs
@@ -0,0 +1,785 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+[assembly:System.Runtime.CompilerServices.InternalsVisibleTo("System.Runtime.WindowsRuntime, PublicKey=00000000000000000400000000000000")]
+
+namespace System
+{
+ partial class Exception
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal void AddExceptionDataForRestrictedErrorInfo(string restrictedError, string restrictedErrorReference, string restrictedCapabilitySid, object restrictedErrorObject, bool hasrestrictedLanguageErrorObject = false) { }
+ }
+}
+
+namespace System.Diagnostics.Tracing
+{
+ [System.Diagnostics.Tracing.EventSourceAttribute(Guid = "8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1", Name = "System.Diagnostics.Eventing.FrameworkEventSource")]
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal sealed partial class FrameworkEventSource : System.Diagnostics.Tracing.EventSource
+ {
+ internal static readonly System.Diagnostics.Tracing.FrameworkEventSource Log;
+ private FrameworkEventSource() { }
+ internal static bool IsInitialized { get { throw null; } }
+ [System.Diagnostics.Tracing.EventAttribute(31, Level = (System.Diagnostics.Tracing.EventLevel)(5), Keywords = (System.Diagnostics.Tracing.EventKeywords)(18))]
+ internal void ThreadPoolDequeueWork(long workID) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal void ThreadPoolDequeueWorkObject(object workID) { }
+ [System.Diagnostics.Tracing.EventAttribute(30, Level = (System.Diagnostics.Tracing.EventLevel)(5), Keywords = (System.Diagnostics.Tracing.EventKeywords)(18))]
+ internal void ThreadPoolEnqueueWork(long workID) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal void ThreadPoolEnqueueWorkObject(object workID) { }
+ [System.Diagnostics.Tracing.EventAttribute(151, Level = (System.Diagnostics.Tracing.EventLevel)(4), Keywords = (System.Diagnostics.Tracing.EventKeywords)(16), Task = (System.Diagnostics.Tracing.EventTask)(3), Opcode = (System.Diagnostics.Tracing.EventOpcode)(240))]
+ internal void ThreadTransferReceive(long id, int kind, string info) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal void ThreadTransferReceiveObj(object id, int kind, string info) { }
+ [System.Diagnostics.Tracing.EventAttribute(150, Level = (System.Diagnostics.Tracing.EventLevel)(4), Keywords = (System.Diagnostics.Tracing.EventKeywords)(16), Task = (System.Diagnostics.Tracing.EventTask)(3), Opcode = (System.Diagnostics.Tracing.EventOpcode)(9))]
+ internal void ThreadTransferSend(long id, int kind, string info, bool multiDequeues) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal void ThreadTransferSendObj(object id, int kind, string info, bool multiDequeues) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ private void WriteEvent(int eventId, long arg1, int arg2, string arg3) { }
+ [System.Diagnostics.Tracing.NonEventAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ private void WriteEvent(int eventId, long arg1, int arg2, string arg3, bool arg4) { }
+ public static partial class Keywords
+ {
+ public const System.Diagnostics.Tracing.EventKeywords DynamicTypeUsage = (System.Diagnostics.Tracing.EventKeywords)8;
+ public const System.Diagnostics.Tracing.EventKeywords Loader = (System.Diagnostics.Tracing.EventKeywords)1;
+ public const System.Diagnostics.Tracing.EventKeywords NetClient = (System.Diagnostics.Tracing.EventKeywords)4;
+ public const System.Diagnostics.Tracing.EventKeywords ThreadPool = (System.Diagnostics.Tracing.EventKeywords)2;
+ public const System.Diagnostics.Tracing.EventKeywords ThreadTransfer = (System.Diagnostics.Tracing.EventKeywords)16;
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ public static partial class Opcodes
+ {
+ public const System.Diagnostics.Tracing.EventOpcode ReceiveHandled = (System.Diagnostics.Tracing.EventOpcode)11;
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ public static partial class Tasks
+ {
+ public const System.Diagnostics.Tracing.EventTask GetRequestStream = (System.Diagnostics.Tracing.EventTask) 2;
+ public const System.Diagnostics.Tracing.EventTask GetResponse = (System.Diagnostics.Tracing.EventTask)1;
+ public const System.Diagnostics.Tracing.EventTask ThreadTransfer = (System.Diagnostics.Tracing.EventTask)3;
+ }
+ }
+}
+
+namespace System.Globalization
+{
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal partial class CultureData
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static System.Globalization.CultureData GetCultureData(string cultureName, bool useUserOverride) { throw null; }
+ }
+
+ [System.FlagsAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ public enum CultureTypes
+ {
+ AllCultures = 7,
+ [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")]
+ FrameworkCultures = 64,
+ InstalledWin32Cultures = 4,
+ NeutralCultures = 1,
+ ReplacementCultures = 16,
+ SpecificCultures = 2,
+ UserCustomCulture = 8,
+ [System.ObsoleteAttribute("This value has been deprecated. Please use other values in CultureTypes.")]
+ WindowsOnlyCultures = 32,
+ }
+}
+
+namespace System.IO
+{
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Runtime.InteropServices.ComVisibleAttribute(true)]
+ internal sealed partial class BufferedStream : System.IO.Stream
+ {
+ private byte[] _buffer;
+ private readonly int _bufferSize;
+ private const int _DefaultBufferSize = 4096;
+ private System.Threading.Tasks.Task<int> _lastSyncCompletedReadTask;
+ private int _readLen;
+ private int _readPos;
+ private System.IO.Stream _stream;
+ private int _writePos;
+ private const int MaxShadowBufferSize = 81920;
+ private BufferedStream() { }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal BufferedStream(System.IO.Stream stream, int bufferSize) { }
+ internal int BufferSize { [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]get { throw null; } }
+ public override bool CanRead { get { throw null; } }
+ public override bool CanSeek { get { throw null; } }
+ public override bool CanWrite { get { throw null; } }
+ public override long Length { get { throw null; } }
+ public override long Position { get { throw null; } set { } }
+ internal System.IO.Stream UnderlyingStream { [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]get { throw null; } }
+ public override System.IAsyncResult BeginRead(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) { throw null; }
+ private System.IAsyncResult BeginReadFromUnderlyingStream(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state, int bytesAlreadySatisfied, System.Threading.Tasks.Task semaphoreLockTask) { throw null; }
+ public override System.IAsyncResult BeginWrite(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) { throw null; }
+ private System.IAsyncResult BeginWriteToUnderlyingStream(byte[] buffer, int offset, int count, System.AsyncCallback callback, object state, System.Threading.Tasks.Task semaphoreLockTask) { throw null; }
+ private void ClearReadBufferBeforeWrite() { }
+ protected override void Dispose(bool disposing) { }
+ public override int EndRead(System.IAsyncResult asyncResult) { throw null; }
+ public override void EndWrite(System.IAsyncResult asyncResult) { }
+ private void EnsureBeginEndAwaitableAllocated() { }
+ private void EnsureBufferAllocated() { }
+ private void EnsureCanRead() { }
+ private void EnsureCanSeek() { }
+ private void EnsureCanWrite() { }
+ private void EnsureNotClosed() { }
+ private void EnsureShadowBufferAllocated() { }
+ public override void Flush() { }
+ public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ private static System.Threading.Tasks.Task FlushAsyncInternal(System.Threading.CancellationToken cancellationToken, System.IO.BufferedStream _this, System.IO.Stream stream, int writePos, int readPos, int readLen) { throw null; }
+ private void FlushRead() { }
+ private void FlushWrite() { }
+ private System.Threading.Tasks.Task FlushWriteAsync(System.Threading.CancellationToken cancellationToken) { throw null; }
+ private System.Threading.Tasks.Task<int> LastSyncCompletedReadTask(int val) { throw null; }
+ public override int Read(byte[] array, int offset, int count) { array = default(byte[]); throw null; }
+ public override System.Threading.Tasks.Task<int> ReadAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override int ReadByte() { throw null; }
+ private int ReadFromBuffer(byte[] array, int offset, int count) { throw null; }
+ private int ReadFromBuffer(byte[] array, int offset, int count, out System.Exception error) { error = default(System.Exception); throw null; }
+ private System.Threading.Tasks.Task<int> ReadFromUnderlyingStreamAsync(byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken, int bytesAlreadySatisfied, System.Threading.Tasks.Task semaphoreLockTask, bool useApmPattern) { throw null; }
+ public override long Seek(long offset, System.IO.SeekOrigin origin) { throw null; }
+ public override void SetLength(long value) { }
+ public override void Write(byte[] array, int offset, int count) { }
+ public override System.Threading.Tasks.Task WriteAsync(byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) { throw null; }
+ public override void WriteByte(byte value) { }
+ private void WriteToBuffer(byte[] array, ref int offset, ref int count) { }
+ private void WriteToBuffer(byte[] array, ref int offset, ref int count, out System.Exception error) { error = default(System.Exception); }
+ private System.Threading.Tasks.Task WriteToUnderlyingStreamAsync(byte[] array, int offset, int count, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.Task semaphoreLockTask, bool useApmPattern) { throw null; }
+ }
+}
+
+namespace System.Resources
+{
+ [System.Security.SecurityCriticalAttribute]
+ internal partial class WindowsRuntimeResourceManagerBase
+ {
+ public WindowsRuntimeResourceManagerBase() { }
+ public virtual System.Globalization.CultureInfo GlobalResourceContextBestFitCultureInfo { [System.Security.SecurityCriticalAttribute]get { throw null; } }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual string GetString(string stringName, string startingCulture, string neutralResourcesCulture) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual bool Initialize(string libpath, string reswFilename, out System.Resources.PRIExceptionInfo exceptionInfo) { exceptionInfo = default(System.Resources.PRIExceptionInfo); throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual bool SetGlobalResourceContextDefaultCulture(System.Globalization.CultureInfo ci) { throw null; }
+ }
+
+ internal partial class PRIExceptionInfo
+ {
+ [System.CLSCompliantAttribute(false)]
+ public string _PackageSimpleName;
+ [System.CLSCompliantAttribute(false)]
+ public string _ResWFile;
+ public PRIExceptionInfo() { }
+ }
+}
+
+namespace System.Runtime.CompilerServices
+{
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static partial class JitHelpers
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecurityCriticalAttribute]
+ internal static T UnsafeCast<T>(object o) where T : class { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2044), AllowMultiple = false, Inherited = false)]
+ internal sealed partial class FriendAccessAllowedAttribute : System.Attribute
+ {
+ public FriendAccessAllowedAttribute() { }
+ }
+ partial class ConditionalWeakTable<TKey, TValue>
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value) { value = default(TValue); throw null; }
+ }
+}
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [System.AttributeUsageAttribute((System.AttributeTargets)(5148), Inherited = false)]
+ internal sealed partial class WindowsRuntimeImportAttribute : System.Attribute
+ {
+ internal WindowsRuntimeImportAttribute() { }
+ }
+
+ [System.Runtime.InteropServices.GuidAttribute("82BA7092-4C88-427D-A7BC-16DD93FEB67E")]
+ [System.Runtime.InteropServices.InterfaceTypeAttribute((System.Runtime.InteropServices.ComInterfaceType)(1))]
+ internal partial interface IRestrictedErrorInfo
+ {
+ void GetErrorDetails(out string description, out int error, out string restrictedDescription, out string capabilitySid);
+ void GetReference(out string reference);
+ }
+
+#if FEATURE_COMINTEROP
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1028), AllowMultiple=false, Inherited=false)]
+ public sealed partial class DefaultInterfaceAttribute : System.Attribute
+ {
+ public DefaultInterfaceAttribute(System.Type defaultInterface) { }
+ public System.Type DefaultInterface { get { throw null; } }
+ }
+ [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
+ public partial struct EventRegistrationToken
+ {
+ public override bool Equals(object obj) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public static bool operator ==(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken left, System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken right) { throw null; }
+ public static bool operator !=(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken left, System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken right) { throw null; }
+ }
+ public sealed partial class EventRegistrationTokenTable<T> where T : class
+ {
+ public EventRegistrationTokenTable() { }
+ public T InvocationList { get { throw null; } set { } }
+ public System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken AddEventHandler(T handler) { throw null; }
+ public static System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable<T> GetOrCreateEventRegistrationTokenTable(ref System.Runtime.InteropServices.WindowsRuntime.EventRegistrationTokenTable<T> refEventTable) { throw null; }
+ public void RemoveEventHandler(T handler) { }
+ public void RemoveEventHandler(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken token) { }
+
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal T ExtractHandler(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken token) { throw null; }
+ }
+ [System.Runtime.InteropServices.GuidAttribute("00000035-0000-0000-C000-000000000046")]
+ public partial interface IActivationFactory
+ {
+ object ActivateInstance();
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(1028), Inherited=false, AllowMultiple=true)]
+ public sealed partial class InterfaceImplementedInVersionAttribute : System.Attribute
+ {
+ public InterfaceImplementedInVersionAttribute(System.Type interfaceType, byte majorVersion, byte minorVersion, byte buildVersion, byte revisionVersion) { }
+ public byte BuildVersion { get { throw null; } }
+ public System.Type InterfaceType { get { throw null; } }
+ public byte MajorVersion { get { throw null; } }
+ public byte MinorVersion { get { throw null; } }
+ public byte RevisionVersion { get { throw null; } }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false, AllowMultiple=false)]
+ public sealed partial class ReadOnlyArrayAttribute : System.Attribute
+ {
+ public ReadOnlyArrayAttribute() { }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(12288), AllowMultiple=false, Inherited=false)]
+ public sealed partial class ReturnValueNameAttribute : System.Attribute
+ {
+ public ReturnValueNameAttribute(string name) { }
+ public string Name { get { throw null; } }
+ }
+ public static partial class WindowsRuntimeMarshal
+ {
+ [System.Security.SecurityCriticalAttribute]
+ public static void AddEventHandler<T>(System.Func<T, System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken> addMethod, System.Action<System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken> removeMethod, T handler) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void FreeHString(System.IntPtr ptr) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Runtime.InteropServices.WindowsRuntime.IActivationFactory GetActivationFactory(System.Type type) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static string PtrToStringHString(System.IntPtr ptr) { throw null; }
+ [System.Security.SecurityCriticalAttribute]
+ public static void RemoveAllEventHandlers(System.Action<System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken> removeMethod) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static void RemoveEventHandler<T>(System.Action<System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken> removeMethod, T handler) { }
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr StringToHString(string s) { throw null; }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecuritySafeCriticalAttribute]
+ internal static bool ReportUnhandledError(System.Exception e) { throw null; }
+ }
+ [System.AttributeUsageAttribute((System.AttributeTargets)(2048), Inherited=false, AllowMultiple=false)]
+ public sealed partial class WriteOnlyArrayAttribute : System.Attribute
+ {
+ public WriteOnlyArrayAttribute() { }
+ }
+#endif //FEATURE_COMINTEROP
+}
+
+namespace System.StubHelpers
+{
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static partial class EventArgsMarshaler
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecurityCriticalAttribute]
+ internal static System.IntPtr CreateNativeNCCEventArgsInstance(int action, object newItems, object oldItems, int newIndex, int oldIndex) { throw null; }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.PreserveSig)]
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecurityCriticalAttribute]
+ internal static System.IntPtr CreateNativePCEventArgsInstance(string name) { throw null; }
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static partial class InterfaceMarshaler
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static object ConvertToManagedWithoutUnboxing(System.IntPtr pNative) { throw null; }
+ }
+}
+
+namespace System.Threading
+{
+ internal enum StackCrawlMark
+ {
+ LookForMe = 0,
+ LookForMyCaller = 1,
+ LookForMyCallersCaller = 2,
+ LookForThread = 3,
+ }
+ [System.Security.SecurityCriticalAttribute]
+ internal partial class WinRTSynchronizationContextFactoryBase
+ {
+ public WinRTSynchronizationContextFactoryBase() { }
+ [System.Security.SecurityCriticalAttribute]
+ public virtual System.Threading.SynchronizationContext Create(object coreDispatcher) { throw null; }
+ }
+ partial struct CancellationTokenRegistration
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal bool TryDeregister() { throw null; }
+ }
+ partial class ExecutionContext
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ [System.Security.SecurityCriticalAttribute]
+ internal static void Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) { }
+ internal static System.Threading.ExecutionContext FastCapture() { return default(System.Threading.ExecutionContext); }
+ }
+}
+
+namespace System.Threading.Tasks
+{
+#if FEATURE_COMINTEROP
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal enum AsyncCausalityStatus
+ {
+ Canceled = 2,
+ Completed = 1,
+ Error = 3,
+ Started = 0,
+ }
+ internal enum CausalityRelation
+ {
+ AssignDelegate = 0,
+ Cancel = 3,
+ Choice = 2,
+ Error = 4,
+ Join = 1,
+ }
+ internal enum CausalitySynchronousWork
+ {
+ CompletionNotification = 0,
+ Execution = 2,
+ ProgressNotification = 1,
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static partial class AsyncCausalityTracer
+ {
+ private static System.Threading.Tasks.AsyncCausalityTracer.Loggers f_LoggingOn;
+ //private const Windows.Foundation.Diagnostics.CausalitySource s_CausalitySource = 1;
+ private static readonly System.Guid s_PlatformId;
+ private static Windows.Foundation.Diagnostics.IAsyncCausalityTracerStatics s_TracerFactory;
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static bool LoggingOn { [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]get { throw null; } }
+ internal static void EnableToETW(bool enabled) { }
+ private static ulong GetOperationId(uint taskId) { throw null; }
+ private static void LogAndDisable(System.Exception ex) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static void TraceOperationCompletion(System.Threading.Tasks.CausalityTraceLevel traceLevel, int taskId, System.Threading.Tasks.AsyncCausalityStatus status) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static void TraceOperationCreation(System.Threading.Tasks.CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ internal static void TraceOperationRelation(System.Threading.Tasks.CausalityTraceLevel traceLevel, int taskId, System.Threading.Tasks.CausalityRelation relation) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ internal static void TraceSynchronousWorkCompletion(System.Threading.Tasks.CausalityTraceLevel traceLevel, System.Threading.Tasks.CausalitySynchronousWork work) { }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ internal static void TraceSynchronousWorkStart(System.Threading.Tasks.CausalityTraceLevel traceLevel, int taskId, System.Threading.Tasks.CausalitySynchronousWork work) { }
+ [System.Security.SecuritySafeCriticalAttribute]
+ private static void TracingStatusChangedHandler(object sender, Windows.Foundation.Diagnostics.TracingStatusChangedEventArgs args) { }
+ [System.FlagsAttribute]
+ private enum Loggers : byte
+ {
+ CausalityTracer = (byte)1,
+ ETW = (byte)2,
+ }
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal enum CausalityTraceLevel
+ {
+ Important = 1,
+ Required = 0,
+ Verbose = 2,
+ }
+#endif
+
+ partial class Task
+ {
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static bool s_asyncDebuggingEnabled;
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static bool AddToActiveTasks(System.Threading.Tasks.Task task) { throw null; }
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+ internal static void RemoveFromActiveTasks(int taskId) { }
+ }
+}
+
+namespace System.Security.Cryptography
+{
+ public abstract class HashAlgorithm : System.IDisposable, System.Security.Cryptography.ICryptoTransform
+ {
+ protected internal byte[] HashValue;
+ protected int HashSizeValue;
+ protected int State;
+ protected HashAlgorithm() { }
+ public virtual bool CanReuseTransform { get { throw null; } }
+ public virtual bool CanTransformMultipleBlocks { get { throw null; } }
+ public virtual byte[] Hash { get { throw null; } }
+ public virtual int HashSize { get { throw null; } }
+ public virtual int InputBlockSize { get { throw null; } }
+ public virtual int OutputBlockSize { get { throw null; } }
+ public void Clear() { }
+ public byte[] ComputeHash(byte[] buffer) { throw null; }
+ public byte[] ComputeHash(byte[] buffer, int offset, int count) { throw null; }
+ public byte[] ComputeHash(System.IO.Stream inputStream) { throw null; }
+ public static HashAlgorithm Create() { throw null; }
+ public static HashAlgorithm Create(string hashName) { throw null; }
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ protected abstract void HashCore(byte[] array, int ibStart, int cbSize);
+ protected abstract byte[] HashFinal();
+ public abstract void Initialize();
+ public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { throw null; }
+ public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { throw null; }
+ }
+
+ public abstract class SymmetricAlgorithm : System.IDisposable
+ {
+ protected byte[] IVValue;
+ protected byte[] KeyValue;
+ protected int BlockSizeValue;
+ protected int FeedbackSizeValue;
+ protected int KeySizeValue;
+ protected CipherMode ModeValue;
+ protected KeySizes[] LegalBlockSizesValue;
+ protected KeySizes[] LegalKeySizesValue;
+ protected PaddingMode PaddingValue;
+ protected SymmetricAlgorithm() { }
+ public virtual int BlockSize { get; set; }
+ public virtual int FeedbackSize { get; set; }
+ public virtual byte[] IV { get; set; }
+ public virtual byte[] Key { get; set; }
+ public virtual int KeySize { get; set; }
+ public virtual KeySizes[] LegalBlockSizes { get; }
+ public virtual KeySizes[] LegalKeySizes { get; }
+ public virtual CipherMode Mode { get; set; }
+ public virtual PaddingMode Padding { get; set; }
+ public void Clear() { }
+ public static SymmetricAlgorithm Create() { throw null; }
+ public static SymmetricAlgorithm Create(string algName) { throw null; }
+ public virtual ICryptoTransform CreateDecryptor() { throw null; }
+ public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
+ public virtual ICryptoTransform CreateEncryptor() { throw null; }
+ public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
+ public void Dispose() { }
+ protected virtual void Dispose(bool disposing) { }
+ public abstract void GenerateIV();
+ public abstract void GenerateKey();
+ public bool ValidKeySize(int bitLength) { throw null; }
+ }
+
+ public interface ICryptoTransform : System.IDisposable
+ {
+ int InputBlockSize { get; }
+ int OutputBlockSize { get; }
+ bool CanTransformMultipleBlocks { get; }
+ bool CanReuseTransform { get; }
+ int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+ byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
+ }
+
+ public sealed class KeySizes
+ {
+ public KeySizes(int minSize, int maxSize, int skipSize) { }
+ public int MaxSize { get; }
+ public int MinSize { get; }
+ public int SkipSize { get; }
+ }
+
+ public enum PaddingMode
+ {
+ ANSIX923 = 4,
+ ISO10126 = 5,
+ None = 1,
+ PKCS7 = 2,
+ Zeros = 3,
+ }
+
+ public enum CipherMode
+ {
+ CBC = 1,
+ CFB = 4,
+ CTS = 5,
+ ECB = 2,
+ OFB = 3,
+ }
+}
+
+#if FEATURE_COMINTEROP
+namespace Windows.Foundation.Diagnostics
+{
+ internal enum AsyncCausalityStatus
+ {
+ Canceled = 2,
+ Completed = 1,
+ Error = 3,
+ Started = 0,
+ }
+ internal enum CausalityRelation
+ {
+ AssignDelegate = 0,
+ Cancel = 3,
+ Choice = 2,
+ Error = 4,
+ Join = 1,
+ }
+ internal enum CausalitySource
+ {
+ Application = 0,
+ Library = 1,
+ System = 2,
+ }
+ internal enum CausalitySynchronousWork
+ {
+ CompletionNotification = 0,
+ Execution = 2,
+ ProgressNotification = 1,
+ }
+ internal enum CausalityTraceLevel
+ {
+ Important = 1,
+ Required = 0,
+ Verbose = 2,
+ }
+ [System.Runtime.InteropServices.GuidAttribute("50850B26-267E-451B-A890-AB6A370245EE")]
+ internal partial interface IAsyncCausalityTracerStatics
+ {
+ System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken add_TracingStatusChanged(System.EventHandler<Windows.Foundation.Diagnostics.TracingStatusChangedEventArgs> eventHandler);
+ void TraceOperationCompletion(Windows.Foundation.Diagnostics.CausalityTraceLevel traceLevel, Windows.Foundation.Diagnostics.CausalitySource source, System.Guid platformId, ulong operationId, Windows.Foundation.Diagnostics.AsyncCausalityStatus status);
+ void TraceOperationCreation(Windows.Foundation.Diagnostics.CausalityTraceLevel traceLevel, Windows.Foundation.Diagnostics.CausalitySource source, System.Guid platformId, ulong operationId, string operationName, ulong relatedContext);
+ void TraceOperationRelation(Windows.Foundation.Diagnostics.CausalityTraceLevel traceLevel, Windows.Foundation.Diagnostics.CausalitySource source, System.Guid platformId, ulong operationId, Windows.Foundation.Diagnostics.CausalityRelation relation);
+ void TraceSynchronousWorkCompletion(Windows.Foundation.Diagnostics.CausalityTraceLevel traceLevel, Windows.Foundation.Diagnostics.CausalitySource source, Windows.Foundation.Diagnostics.CausalitySynchronousWork work);
+ void TraceSynchronousWorkStart(Windows.Foundation.Diagnostics.CausalityTraceLevel traceLevel, Windows.Foundation.Diagnostics.CausalitySource source, System.Guid platformId, ulong operationId, Windows.Foundation.Diagnostics.CausalitySynchronousWork work);
+ }
+ [System.Runtime.InteropServices.GuidAttribute("410B7711-FF3B-477F-9C9A-D2EFDA302DC3")]
+ internal partial interface ITracingStatusChangedEventArgs
+ {
+ bool Enabled { get; }
+ Windows.Foundation.Diagnostics.CausalityTraceLevel TraceLevel { get; }
+ }
+ [System.Runtime.InteropServices.GuidAttribute("410B7711-FF3B-477F-9C9A-D2EFDA302DC3")]
+ internal sealed partial class TracingStatusChangedEventArgs : Windows.Foundation.Diagnostics.ITracingStatusChangedEventArgs
+ {
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]
+ public TracingStatusChangedEventArgs() { }
+ public bool Enabled { [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ public Windows.Foundation.Diagnostics.CausalityTraceLevel TraceLevel { [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.InternalCall)]get { throw null; } }
+ }
+}
+#endif
+
+namespace System.Security.Claims
+{
+ public partial class Claim
+ {
+ public Claim(System.IO.BinaryReader reader) { }
+ public Claim(System.IO.BinaryReader reader, System.Security.Claims.ClaimsIdentity subject) { }
+ protected Claim(System.Security.Claims.Claim other) { }
+ protected Claim(System.Security.Claims.Claim other, System.Security.Claims.ClaimsIdentity subject) { }
+ public Claim(string type, string value) { }
+ public Claim(string type, string value, string valueType) { }
+ public Claim(string type, string value, string valueType, string issuer) { }
+ public Claim(string type, string value, string valueType, string issuer, string originalIssuer) { }
+ public Claim(string type, string value, string valueType, string issuer, string originalIssuer, System.Security.Claims.ClaimsIdentity subject) { }
+ protected virtual byte[] CustomSerializationData { get { throw null; } }
+ public string Issuer { get { throw null; } }
+ public string OriginalIssuer { get { throw null; } }
+ public System.Collections.Generic.IDictionary<string, string> Properties { get { throw null; } }
+ public System.Security.Claims.ClaimsIdentity Subject { get { throw null; } }
+ public string Type { get { throw null; } }
+ public string Value { get { throw null; } }
+ public string ValueType { get { throw null; } }
+ public virtual System.Security.Claims.Claim Clone() { throw null; }
+ public virtual System.Security.Claims.Claim Clone(System.Security.Claims.ClaimsIdentity identity) { throw null; }
+ public override string ToString() { throw null; }
+ public virtual void WriteTo(System.IO.BinaryWriter writer) { }
+ protected virtual void WriteTo(System.IO.BinaryWriter writer, byte[] userData) { }
+ }
+ public partial class ClaimsIdentity : System.Security.Principal.IIdentity
+ {
+ public const string DefaultIssuer = "LOCAL AUTHORITY";
+ public const string DefaultNameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
+ public const string DefaultRoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
+ public ClaimsIdentity() { }
+ public ClaimsIdentity(System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims) { }
+ public ClaimsIdentity(System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims, string authenticationType) { }
+ public ClaimsIdentity(System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims, string authenticationType, string nameType, string roleType) { }
+ public ClaimsIdentity(System.IO.BinaryReader reader) { }
+ protected ClaimsIdentity(System.Security.Claims.ClaimsIdentity other) { }
+ public ClaimsIdentity(System.Security.Principal.IIdentity identity) { }
+ public ClaimsIdentity(System.Security.Principal.IIdentity identity, System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims) { }
+ public ClaimsIdentity(System.Security.Principal.IIdentity identity, System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims, string authenticationType, string nameType, string roleType) { }
+ public ClaimsIdentity(string authenticationType) { }
+ public ClaimsIdentity(string authenticationType, string nameType, string roleType) { }
+ public System.Security.Claims.ClaimsIdentity Actor { get { throw null; } set { } }
+ public virtual string AuthenticationType { get { throw null; } }
+ public object BootstrapContext { get { throw null; } set { } }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> Claims { get { throw null; } }
+ protected virtual byte[] CustomSerializationData { get { throw null; } }
+ public virtual bool IsAuthenticated { get { throw null; } }
+ public string Label { get { throw null; } set { } }
+ public virtual string Name { get { throw null; } }
+ public string NameClaimType { get { throw null; } }
+ public string RoleClaimType { get { throw null; } }
+ public virtual void AddClaim(System.Security.Claims.Claim claim) { }
+ public virtual void AddClaims(System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> claims) { }
+ public virtual System.Security.Claims.ClaimsIdentity Clone() { throw null; }
+ protected virtual System.Security.Claims.Claim CreateClaim(System.IO.BinaryReader reader) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> FindAll(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> FindAll(string type) { throw null; }
+ public virtual System.Security.Claims.Claim FindFirst(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual System.Security.Claims.Claim FindFirst(string type) { throw null; }
+ public virtual bool HasClaim(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual bool HasClaim(string type, string value) { throw null; }
+ public virtual void RemoveClaim(System.Security.Claims.Claim claim) { }
+ public virtual bool TryRemoveClaim(System.Security.Claims.Claim claim) { throw null; }
+ public virtual void WriteTo(System.IO.BinaryWriter writer) { }
+ protected virtual void WriteTo(System.IO.BinaryWriter writer, byte[] userData) { }
+ }
+ public partial class ClaimsPrincipal : System.Security.Principal.IPrincipal
+ {
+ public ClaimsPrincipal() { }
+ public ClaimsPrincipal(System.Collections.Generic.IEnumerable<System.Security.Claims.ClaimsIdentity> identities) { }
+ public ClaimsPrincipal(System.IO.BinaryReader reader) { }
+ public ClaimsPrincipal(System.Security.Principal.IIdentity identity) { }
+ public ClaimsPrincipal(System.Security.Principal.IPrincipal principal) { }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> Claims { get { throw null; } }
+ public static System.Func<System.Security.Claims.ClaimsPrincipal> ClaimsPrincipalSelector { get { throw null; } set { } }
+ public static System.Security.Claims.ClaimsPrincipal Current { get { throw null; } }
+ protected virtual byte[] CustomSerializationData { get { throw null; } }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.ClaimsIdentity> Identities { get { throw null; } }
+ public virtual System.Security.Principal.IIdentity Identity { get { throw null; } }
+ public static System.Func<System.Collections.Generic.IEnumerable<System.Security.Claims.ClaimsIdentity>, System.Security.Claims.ClaimsIdentity> PrimaryIdentitySelector { get { throw null; } set { } }
+ public virtual void AddIdentities(System.Collections.Generic.IEnumerable<System.Security.Claims.ClaimsIdentity> identities) { }
+ public virtual void AddIdentity(System.Security.Claims.ClaimsIdentity identity) { }
+ public virtual System.Security.Claims.ClaimsPrincipal Clone() { throw null; }
+ protected virtual System.Security.Claims.ClaimsIdentity CreateClaimsIdentity(System.IO.BinaryReader reader) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> FindAll(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> FindAll(string type) { throw null; }
+ public virtual System.Security.Claims.Claim FindFirst(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual System.Security.Claims.Claim FindFirst(string type) { throw null; }
+ public virtual bool HasClaim(System.Predicate<System.Security.Claims.Claim> match) { throw null; }
+ public virtual bool HasClaim(string type, string value) { throw null; }
+ public virtual bool IsInRole(string role) { throw null; }
+ public virtual void WriteTo(System.IO.BinaryWriter writer) { }
+ protected virtual void WriteTo(System.IO.BinaryWriter writer, byte[] userData) { }
+ }
+ public static partial class ClaimTypes
+ {
+ public const string Actor = "http://schemas.xmlsoap.org/ws/2009/09/identity/claims/actor";
+ public const string Anonymous = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/anonymous";
+ public const string Authentication = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication";
+ public const string AuthenticationInstant = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationinstant";
+ public const string AuthenticationMethod = "http://schemas.microsoft.com/ws/2008/06/identity/claims/authenticationmethod";
+ public const string AuthorizationDecision = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authorizationdecision";
+ public const string CookiePath = "http://schemas.microsoft.com/ws/2008/06/identity/claims/cookiepath";
+ public const string Country = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/country";
+ public const string DateOfBirth = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dateofbirth";
+ public const string DenyOnlyPrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarygroupsid";
+ public const string DenyOnlyPrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlyprimarysid";
+ public const string DenyOnlySid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/denyonlysid";
+ public const string DenyOnlyWindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/denyonlywindowsdevicegroup";
+ public const string Dns = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/dns";
+ public const string Dsa = "http://schemas.microsoft.com/ws/2008/06/identity/claims/dsa";
+ public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
+ public const string Expiration = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expiration";
+ public const string Expired = "http://schemas.microsoft.com/ws/2008/06/identity/claims/expired";
+ public const string Gender = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/gender";
+ public const string GivenName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname";
+ public const string GroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/groupsid";
+ public const string Hash = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/hash";
+ public const string HomePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/homephone";
+ public const string IsPersistent = "http://schemas.microsoft.com/ws/2008/06/identity/claims/ispersistent";
+ public const string Locality = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/locality";
+ public const string MobilePhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/mobilephone";
+ public const string Name = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name";
+ public const string NameIdentifier = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";
+ public const string OtherPhone = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/otherphone";
+ public const string PostalCode = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode";
+ public const string PrimaryGroupSid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid";
+ public const string PrimarySid = "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarysid";
+ public const string Role = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role";
+ public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";
+ public const string SerialNumber = "http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber";
+ public const string Sid = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/sid";
+ public const string Spn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/spn";
+ public const string StateOrProvince = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/stateorprovince";
+ public const string StreetAddress = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/streetaddress";
+ public const string Surname = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname";
+ public const string System = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/system";
+ public const string Thumbprint = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/thumbprint";
+ public const string Upn = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";
+ public const string Uri = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/uri";
+ public const string UserData = "http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata";
+ public const string Version = "http://schemas.microsoft.com/ws/2008/06/identity/claims/version";
+ public const string Webpage = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/webpage";
+ public const string WindowsAccountName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname";
+ public const string WindowsDeviceClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdeviceclaim";
+ public const string WindowsDeviceGroup = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsdevicegroup";
+ public const string WindowsFqbnVersion = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsfqbnversion";
+ public const string WindowsSubAuthority = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowssubauthority";
+ public const string WindowsUserClaim = "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsuserclaim";
+ public const string X500DistinguishedName = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/x500distinguishedname";
+ }
+ public static partial class ClaimValueTypes
+ {
+ public const string Base64Binary = "http://www.w3.org/2001/XMLSchema#base64Binary";
+ public const string Base64Octet = "http://www.w3.org/2001/XMLSchema#base64Octet";
+ public const string Boolean = "http://www.w3.org/2001/XMLSchema#boolean";
+ public const string Date = "http://www.w3.org/2001/XMLSchema#date";
+ public const string DateTime = "http://www.w3.org/2001/XMLSchema#dateTime";
+ public const string DaytimeDuration = "http://www.w3.org/TR/2002/WD-xquery-operators-20020816#dayTimeDuration";
+ public const string DnsName = "http://schemas.xmlsoap.org/claims/dns";
+ public const string Double = "http://www.w3.org/2001/XMLSchema#double";
+ public const string DsaKeyValue = "http://www.w3.org/2000/09/xmldsig#DSAKeyValue";
+ public const string Email = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
+ public const string Fqbn = "http://www.w3.org/2001/XMLSchema#fqbn";
+ public const string HexBinary = "http://www.w3.org/2001/XMLSchema#hexBinary";
+ public const string Integer = "http://www.w3.org/2001/XMLSchema#integer";
+ public const string Integer32 = "http://www.w3.org/2001/XMLSchema#integer32";
+ public const string Integer64 = "http://www.w3.org/2001/XMLSchema#integer64";
+ public const string KeyInfo = "http://www.w3.org/2000/09/xmldsig#KeyInfo";
+ public const string Rfc822Name = "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name";
+ public const string Rsa = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/rsa";
+ public const string RsaKeyValue = "http://www.w3.org/2000/09/xmldsig#RSAKeyValue";
+ public const string Sid = "http://www.w3.org/2001/XMLSchema#sid";
+ public const string String = "http://www.w3.org/2001/XMLSchema#string";
+ public const string Time = "http://www.w3.org/2001/XMLSchema#time";
+ public const string UInteger32 = "http://www.w3.org/2001/XMLSchema#uinteger32";
+ public const string UInteger64 = "http://www.w3.org/2001/XMLSchema#uinteger64";
+ public const string UpnName = "http://schemas.xmlsoap.org/claims/UPN";
+ public const string X500Name = "urn:oasis:names:tc:xacml:1.0:data-type:x500Name";
+ public const string YearMonthDuration = "http://www.w3.org/TR/2002/WD-xquery-operators-20020816#yearMonthDuration";
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/GlobalSuppressions.cs b/src/mscorlib/src/GlobalSuppressions.cs
new file mode 100644
index 0000000000..f1006dc647
--- /dev/null
+++ b/src/mscorlib/src/GlobalSuppressions.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Diagnostics.CodeAnalysis;
+
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.BINDPTR.#lpfuncdesc", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.BINDPTR.#lptcomp", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.BINDPTR.#lpvardesc", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.CriticalHandle.#handle", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.DISPPARAMS.#rgdispidNamedArgs", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.DISPPARAMS.#rgvarg", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.EXCEPINFO.#pfnDeferredFillIn", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.EXCEPINFO.#pvReserved", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.FUNCDESC.#lprgelemdescParam", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.FUNCDESC.#lprgscode", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.PARAMDESC.#lpVarValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.SafeHandle.#handle", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.TYPEATTR.#lpstrSchema", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.TYPEDESC.#lpValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.VARDESC+DESCUNION.#lpvarValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.BINDPTR.#lpfuncdesc", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.BINDPTR.#lptcomp", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.BINDPTR.#lpvardesc", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.DISPPARAMS.#rgdispidNamedArgs", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.DISPPARAMS.#rgvarg", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.EXCEPINFO.#pfnDeferredFillIn", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.EXCEPINFO.#pvReserved", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.FUNCDESC.#lprgelemdescParam", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.FUNCDESC.#lprgscode", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.IDLDESC.#dwReserved", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.PARAMDESC.#lpVarValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.TYPEATTR.#lpstrSchema", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.TYPEDESC.#lpValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Runtime.InteropServices.ComTypes.VARDESC+DESCUNION.#lpvarValue", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Threading.NativeOverlapped.#EventHandle", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Threading.NativeOverlapped.#InternalHigh", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2111:PointersShouldNotBeVisible", Scope="member", Target="System.Threading.NativeOverlapped.#InternalLow", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2105:ArrayFieldsShouldNotBeReadOnly", Scope="member", Target="System.IO.Path.#InvalidPathChars", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2105:ArrayFieldsShouldNotBeReadOnly", Scope="member", Target="System.Type.#EmptyTypes", Justification="matell: We already shipped this and it would be a breaking change to fix it")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.BinaryWriter.#Null", Justification="matell: Underlying type is actually immutable")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.Stream.#Null", Justification="matell: Underlying type is actually immutable")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.StreamReader.#Null", Justification="matell: Underlying type is actually immutable")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.StreamWriter.#Null", Justification="matell: Underlying type is actually Immutable")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.TextReader.#Null", Justification="matell: Underlying type is actually immutable")]
+[module: SuppressMessage("Microsoft.Security","CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Scope="member", Target="System.IO.TextWriter.#Null", Justification="matell: Underlying type is actually immutable")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Diagnostics.Tracing.EventSource.#GenerateGuidFromName(System.String)", Justification="matell: Existing code that needs to interop with other components using SHA-1")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.IO.IsolatedStorage.IsolatedStorage.#GetHash(System.IO.Stream)", Justification="matell: Existing code that needs to interop with other components using SHA-1")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.IO.IsolatedStorage.IsolatedStorageFile.#GetStrongHashSuitableForObjectName(System.String)", Justification="matell: Existing code that needs to interop with other components using SHA-1")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Policy.HashMembershipCondition.#ParseHashAlgorithm()", Justification="matell: Existing code that needs to interop with other components using SHA-1")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Policy.HashMembershipCondition.#.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)", Justification="matell: Existing code that needs to interop with other components using SHA-1")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DES.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DES.#IsSemiWeakKey(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DES.#IsWeakKey(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DES.#get_Key()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DES.#set_Key(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DESCryptoServiceProvider.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DESCryptoServiceProvider.#CreateDecryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DESCryptoServiceProvider.#CreateEncryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5351:DESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.DESCryptoServiceProvider.#GenerateKey()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.DSACryptoServiceProvider.#.ctor(System.Int32,System.Security.Cryptography.CspParameters)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5356:DSACannotBeUsed", Scope="member", Target="System.Security.Cryptography.DSASignatureFormatter.#CreateSignature(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5350:MD5CannotBeUsed", Scope="member", Target="System.Security.Cryptography.HMACMD5.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5350:MD5CannotBeUsed", Scope="member", Target="System.Security.Cryptography.HMACMD5.#.ctor(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.HMACRIPEMD160.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.HMACRIPEMD160.#.ctor(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.HMACSHA1.#.ctor(System.Byte[],System.Boolean)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.MACTripleDES.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.MACTripleDES.#.ctor(System.String,System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5350:MD5CannotBeUsed", Scope="member", Target="System.Security.Cryptography.MD5.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5350:MD5CannotBeUsed", Scope="member", Target="System.Security.Cryptography.MD5CryptoServiceProvider.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5352:RC2CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RC2.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5352:RC2CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RC2CryptoServiceProvider.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5352:RC2CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RC2CryptoServiceProvider.#CreateDecryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5352:RC2CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RC2CryptoServiceProvider.#CreateEncryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#HashCore(System.Byte[],System.Int32,System.Int32)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#HashFinal()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#Initialize()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#MDTransform(System.UInt32*,System.UInt32*,System.Byte*)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#_EndHash()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5355:RIPEMD160IsNotRecommended", Scope="member", Target="System.Security.Cryptography.RIPEMD160Managed.#_HashData(System.Byte[],System.Int32,System.Int32)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter.#DecryptKeyExchange(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.RSAOAEPKeyExchangeFormatter.#CreateKeyExchange(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5357:RijndaelCannotBeUsed", Scope="member", Target="System.Security.Cryptography.Rijndael.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5357:RijndaelCannotBeUsed", Scope="member", Target="System.Security.Cryptography.RijndaelManaged.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5357:RijndaelCannotBeUsed", Scope="member", Target="System.Security.Cryptography.RijndaelManaged.#CreateDecryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5357:RijndaelCannotBeUsed", Scope="member", Target="System.Security.Cryptography.RijndaelManaged.#CreateEncryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1CryptoServiceProvider.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#HashCore(System.Byte[],System.Int32,System.Int32)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#HashFinal()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#Initialize()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#SHATransform(System.UInt32*,System.UInt32*,System.Byte*)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#_EndHash()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5354:SHA1CannotBeUsed", Scope="member", Target="System.Security.Cryptography.SHA1Managed.#_HashData(System.Byte[],System.Int32,System.Int32)", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDES.#Create()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDES.#IsWeakKey(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDES.#get_Key()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDES.#set_Key(System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDESCryptoServiceProvider.#.ctor()", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDESCryptoServiceProvider.#CreateDecryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDESCryptoServiceProvider.#CreateEncryptor(System.Byte[],System.Byte[])", Justification="matell: By design. Needed for implementation of security algorithms")]
+[module: SuppressMessage("Microsoft.Cryptographic.Standard","CA5353:TripleDESCannotBeUsed", Scope="member", Target="System.Security.Cryptography.TripleDESCryptoServiceProvider.#GenerateKey()", Justification="matell: By design. Needed for implementation of security algorithms")]
diff --git a/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs b/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs
new file mode 100644
index 0000000000..28104683c7
--- /dev/null
+++ b/src/mscorlib/src/Internal/Runtime/Augments/EnvironmentAugments.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace Internal.Runtime.Augments
+{
+ /// <summary>For internal use only. Exposes runtime functionality to the Environments implementation in corefx.</summary>
+ public static class EnvironmentAugments
+ {
+ public static int CurrentManagedThreadId => Environment.CurrentManagedThreadId;
+ public static void Exit(int exitCode) => Environment.Exit(exitCode);
+ public static int ExitCode { get { return Environment.ExitCode; } set { Environment.ExitCode = value; } }
+ public static void FailFast(string message, Exception error) => Environment.FailFast(message, error);
+ public static string[] GetCommandLineArgs() => Environment.GetCommandLineArgs();
+ public static bool HasShutdownStarted => Environment.HasShutdownStarted;
+ public static string StackTrace => Environment.StackTrace;
+ public static int TickCount => Environment.TickCount;
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs
new file mode 100644
index 0000000000..118c69b8b7
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/OAVariantLib.cs
@@ -0,0 +1,134 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class only exists to provide support for
+** implenting IDispatch on managed objects. It is
+** used to provide OleAut style coercion rules.
+**
+**
+===========================================================*/
+namespace Microsoft.Win32 {
+
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ internal static class OAVariantLib
+ {
+ #region Constants
+
+ // Constants for VariantChangeType from OleAuto.h
+ public const int NoValueProp = 0x01;
+ public const int AlphaBool = 0x02;
+ public const int NoUserOverride = 0x04;
+ public const int CalendarHijri = 0x08;
+ public const int LocalBool = 0x10;
+
+ internal static readonly Type [] ClassTypes = {
+ typeof(Empty),
+ typeof(void),
+ typeof(Boolean),
+ typeof(Char),
+ typeof(SByte),
+ typeof(Byte),
+ typeof(Int16),
+ typeof(UInt16),
+ typeof(Int32),
+ typeof(UInt32),
+ typeof(Int64),
+ typeof(UInt64),
+ typeof(Single),
+ typeof(Double),
+ typeof(String),
+ typeof(void),
+ typeof(DateTime),
+ typeof(TimeSpan),
+ typeof(Object),
+ typeof(Decimal),
+ null, // Enums - what do we do here?
+ typeof(Missing),
+ typeof(DBNull),
+ };
+
+ // Keep these numbers in sync w/ the above array.
+ private const int CV_OBJECT=0x12;
+
+ #endregion
+
+
+ #region Internal Methods
+
+ /**
+ * Changes a Variant from one type to another, calling the OLE
+ * Automation VariantChangeTypeEx routine. Note the legal types here are
+ * restricted to the subset of what can be legally found in a VB
+ * Variant and the types that CLR supports explicitly in the
+ * CLR Variant class.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Variant ChangeType(Variant source, Type targetClass, short options, CultureInfo culture)
+ {
+ if (targetClass == null)
+ throw new ArgumentNullException("targetClass");
+ if (culture == null)
+ throw new ArgumentNullException("culture");
+ Variant result = new Variant ();
+ ChangeTypeEx(ref result, ref source,
+#if FEATURE_USE_LCID
+ culture.LCID,
+#else
+ // @CORESYSTODO: what does CoreSystem expect for this argument?
+ 0,
+#endif
+ targetClass.TypeHandle.Value, GetCVTypeFromClass(targetClass), options);
+ return result;
+ }
+
+ #endregion
+
+
+ #region Private Helpers
+
+ private static int GetCVTypeFromClass(Type ctype)
+ {
+ Contract.Requires(ctype != null);
+#if _DEBUG
+ BCLDebug.Assert(ClassTypes[CV_OBJECT] == typeof(Object), "OAVariantLib::ClassTypes[CV_OBJECT] == Object.class");
+#endif
+
+ int cvtype=-1;
+ for (int i=0; i<ClassTypes.Length; i++) {
+ if (ctype.Equals(ClassTypes[i])) {
+ cvtype=i;
+ break;
+ }
+ }
+
+ // OleAut Binder works better if unrecognized
+ // types were changed to Object. So don't throw here.
+ if (cvtype == -1)
+ cvtype = CV_OBJECT;
+
+ return cvtype;
+ }
+
+ #endregion
+
+
+ #region Private FCalls
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ChangeTypeEx(ref Variant result, ref Variant source, int lcid, IntPtr typeHandle, int cvType, short flags);
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/Registry.cs b/src/mscorlib/src/Microsoft/Win32/Registry.cs
new file mode 100644
index 0000000000..4faf29da7f
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/Registry.cs
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace Microsoft.Win32 {
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+
+ /**
+ * Registry encapsulation. Contains members representing all top level system
+ * keys.
+ *
+ * @security(checkClassLinking=on)
+ */
+ //This class contains only static members and does not need to be serializable.
+ [ComVisible(true)]
+ public static class Registry {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static Registry()
+ {
+ }
+
+ /**
+ * Current User Key.
+ *
+ * This key should be used as the root for all user specific settings.
+ */
+ public static readonly RegistryKey CurrentUser = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_USER);
+
+ /**
+ * Local Machine Key.
+ *
+ * This key should be used as the root for all machine specific settings.
+ */
+ public static readonly RegistryKey LocalMachine = RegistryKey.GetBaseKey(RegistryKey.HKEY_LOCAL_MACHINE);
+
+ /**
+ * Classes Root Key.
+ *
+ * This is the root key of class information.
+ */
+ public static readonly RegistryKey ClassesRoot = RegistryKey.GetBaseKey(RegistryKey.HKEY_CLASSES_ROOT);
+
+ /**
+ * Users Root Key.
+ *
+ * This is the root of users.
+ */
+ public static readonly RegistryKey Users = RegistryKey.GetBaseKey(RegistryKey.HKEY_USERS);
+
+ /**
+ * Performance Root Key.
+ *
+ * This is where dynamic performance data is stored on NT.
+ */
+ public static readonly RegistryKey PerformanceData = RegistryKey.GetBaseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
+
+ /**
+ * Current Config Root Key.
+ *
+ * This is where current configuration information is stored.
+ */
+ public static readonly RegistryKey CurrentConfig = RegistryKey.GetBaseKey(RegistryKey.HKEY_CURRENT_CONFIG);
+
+#if !FEATURE_CORECLR
+ /**
+ * Dynamic Data Root Key.
+ *
+ * LEGACY: This is where dynamic performance data is stored on Win9X.
+ * This does not exist on NT.
+ */
+ [Obsolete("The DynData registry key only works on Win9x, which is no longer supported by the CLR. On NT-based operating systems, use the PerformanceData registry key instead.")]
+ public static readonly RegistryKey DynData = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
+#endif
+
+ //
+ // Following function will parse a keyName and returns the basekey for it.
+ // It will also store the subkey name in the out parameter.
+ // If the keyName is not valid, we will throw ArgumentException.
+ // The return value shouldn't be null.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ private static RegistryKey GetBaseKeyFromKeyName(string keyName, out string subKeyName) {
+ if( keyName == null) {
+ throw new ArgumentNullException("keyName");
+ }
+
+ string basekeyName;
+ int i = keyName.IndexOf('\\');
+ if( i != -1) {
+ basekeyName = keyName.Substring(0, i).ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ }
+ else {
+ basekeyName = keyName.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
+ }
+ RegistryKey basekey = null;
+
+ switch(basekeyName) {
+ case "HKEY_CURRENT_USER":
+ basekey = Registry.CurrentUser;
+ break;
+ case "HKEY_LOCAL_MACHINE":
+ basekey = Registry.LocalMachine;
+ break;
+ case "HKEY_CLASSES_ROOT":
+ basekey = Registry.ClassesRoot;
+ break;
+ case "HKEY_USERS":
+ basekey = Registry.Users;
+ break;
+ case "HKEY_PERFORMANCE_DATA":
+ basekey = Registry.PerformanceData;
+ break;
+ case "HKEY_CURRENT_CONFIG":
+ basekey = Registry.CurrentConfig;
+ break;
+#if !FEATURE_CORECLR
+ case "HKEY_DYN_DATA":
+ basekey = RegistryKey.GetBaseKey(RegistryKey.HKEY_DYN_DATA);
+ break;
+#endif
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegInvalidKeyName", "keyName"));
+ }
+ if( i == -1 || i == keyName.Length) {
+ subKeyName = string.Empty;
+ }
+ else {
+ subKeyName = keyName.Substring(i + 1, keyName.Length - i - 1);
+ }
+ return basekey;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static object GetValue(string keyName, string valueName, object defaultValue ) {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+ BCLDebug.Assert(basekey != null, "basekey can't be null.");
+ RegistryKey key = basekey.OpenSubKey(subKeyName);
+ if(key == null) { // if the key doesn't exist, do nothing
+ return null;
+ }
+ try {
+ return key.GetValue(valueName, defaultValue);
+ }
+ finally {
+ key.Close();
+ }
+ }
+
+ public static void SetValue(string keyName, string valueName, object value ) {
+ SetValue(keyName, valueName, value, RegistryValueKind.Unknown);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetValue(string keyName, string valueName, object value, RegistryValueKind valueKind ) {
+ string subKeyName;
+ RegistryKey basekey = GetBaseKeyFromKeyName(keyName, out subKeyName);
+ BCLDebug.Assert(basekey != null, "basekey can't be null!");
+ RegistryKey key = basekey.CreateSubKey(subKeyName);
+ BCLDebug.Assert(key != null, "An exception should be thrown if failed!");
+ try {
+ key.SetValue(valueName, value, valueKind);
+ }
+ finally {
+ key.Close();
+ }
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
new file mode 100644
index 0000000000..dcf31dc60c
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryKey.cs
@@ -0,0 +1,2166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*
+ Note on transaction support:
+ Eventually we will want to add support for NT's transactions to our
+ RegistryKey API's (possibly Whidbey M3?). When we do this, here's
+ the list of API's we need to make transaction-aware:
+
+ RegCreateKeyEx
+ RegDeleteKey
+ RegDeleteValue
+ RegEnumKeyEx
+ RegEnumValue
+ RegOpenKeyEx
+ RegQueryInfoKey
+ RegQueryValueEx
+ RegSetValueEx
+
+ We can ignore RegConnectRegistry (remote registry access doesn't yet have
+ transaction support) and RegFlushKey. RegCloseKey doesn't require any
+ additional work. .
+ */
+
+/*
+ Note on ACL support:
+ The key thing to note about ACL's is you set them on a kernel object like a
+ registry key, then the ACL only gets checked when you construct handles to
+ them. So if you set an ACL to deny read access to yourself, you'll still be
+ able to read with that handle, but not with new handles.
+
+ Another peculiarity is a Terminal Server app compatibility workaround. The OS
+ will second guess your attempt to open a handle sometimes. If a certain
+ combination of Terminal Server app compat registry keys are set, then the
+ OS will try to reopen your handle with lesser permissions if you couldn't
+ open it in the specified mode. So on some machines, we will see handles that
+ may not be able to read or write to a registry key. It's very strange. But
+ the real test of these handles is attempting to read or set a value in an
+ affected registry key.
+
+ For reference, at least two registry keys must be set to particular values
+ for this behavior:
+ HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Terminal Server\RegistryExtensionFlags, the least significant bit must be 1.
+ HKLM\SYSTEM\CurrentControlSet\Control\TerminalServer\TSAppCompat must be 1
+ There might possibly be an interaction with yet a third registry key as well.
+
+*/
+
+
+namespace Microsoft.Win32 {
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security;
+#if FEATURE_MACL
+ using System.Security.AccessControl;
+#endif
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+ using System.IO;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.Versioning;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+ /**
+ * Registry hive values. Useful only for GetRemoteBaseKey
+ */
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum RegistryHive
+ {
+ ClassesRoot = unchecked((int)0x80000000),
+ CurrentUser = unchecked((int)0x80000001),
+ LocalMachine = unchecked((int)0x80000002),
+ Users = unchecked((int)0x80000003),
+ PerformanceData = unchecked((int)0x80000004),
+ CurrentConfig = unchecked((int)0x80000005),
+#if !FEATURE_CORECLR
+ DynData = unchecked((int)0x80000006),
+#endif
+ }
+
+ /**
+ * Registry encapsulation. To get an instance of a RegistryKey use the
+ * Registry class's static members then call OpenSubKey.
+ *
+ * @see Registry
+ * @security(checkDllCalls=off)
+ * @security(checkClassLinking=on)
+ */
+#if FEATURE_REMOTING
+ [ComVisible(true)]
+ public sealed class RegistryKey : MarshalByRefObject, IDisposable
+#else
+ [ComVisible(true)]
+ public sealed class RegistryKey : IDisposable
+#endif
+ {
+
+ // We could use const here, if C# supported ELEMENT_TYPE_I fully.
+ internal static readonly IntPtr HKEY_CLASSES_ROOT = new IntPtr(unchecked((int)0x80000000));
+ internal static readonly IntPtr HKEY_CURRENT_USER = new IntPtr(unchecked((int)0x80000001));
+ internal static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(unchecked((int)0x80000002));
+ internal static readonly IntPtr HKEY_USERS = new IntPtr(unchecked((int)0x80000003));
+ internal static readonly IntPtr HKEY_PERFORMANCE_DATA = new IntPtr(unchecked((int)0x80000004));
+ internal static readonly IntPtr HKEY_CURRENT_CONFIG = new IntPtr(unchecked((int)0x80000005));
+#if !FEATURE_CORECLR
+ internal static readonly IntPtr HKEY_DYN_DATA = new IntPtr(unchecked((int)0x80000006));
+#endif
+
+ // Dirty indicates that we have munged data that should be potentially
+ // written to disk.
+ //
+ private const int STATE_DIRTY = 0x0001;
+
+ // SystemKey indicates that this is a "SYSTEMKEY" and shouldn't be "opened"
+ // or "closed".
+ //
+ private const int STATE_SYSTEMKEY = 0x0002;
+
+ // Access
+ //
+ private const int STATE_WRITEACCESS = 0x0004;
+
+ // Indicates if this key is for HKEY_PERFORMANCE_DATA
+ private const int STATE_PERF_DATA = 0x0008;
+
+ // Names of keys. This array must be in the same order as the HKEY values listed above.
+ //
+ private static readonly String[] hkeyNames = new String[] {
+ "HKEY_CLASSES_ROOT",
+ "HKEY_CURRENT_USER",
+ "HKEY_LOCAL_MACHINE",
+ "HKEY_USERS",
+ "HKEY_PERFORMANCE_DATA",
+ "HKEY_CURRENT_CONFIG",
+#if !FEATURE_CORECLR
+ "HKEY_DYN_DATA"
+#endif
+ };
+
+ // MSDN defines the following limits for registry key names & values:
+ // Key Name: 255 characters
+ // Value name: 16,383 Unicode characters
+ // Value: either 1 MB or current available memory, depending on registry format.
+ private const int MaxKeyLength = 255;
+ private const int MaxValueLength = 16383;
+
+ [System.Security.SecurityCritical] // auto-generated
+ private volatile SafeRegistryHandle hkey = null;
+ private volatile int state = 0;
+ private volatile String keyName;
+ private volatile bool remoteKey = false;
+ private volatile RegistryKeyPermissionCheck checkMode;
+ private volatile RegistryView regView = RegistryView.Default;
+
+ /**
+ * RegistryInternalCheck values. Useful only for CheckPermission
+ */
+ private enum RegistryInternalCheck {
+ CheckSubKeyWritePermission = 0,
+ CheckSubKeyReadPermission = 1,
+ CheckSubKeyCreatePermission = 2,
+ CheckSubTreeReadPermission = 3,
+ CheckSubTreeWritePermission = 4,
+ CheckSubTreeReadWritePermission = 5,
+ CheckValueWritePermission = 6,
+ CheckValueCreatePermission = 7,
+ CheckValueReadPermission = 8,
+ CheckKeyReadPermission = 9,
+ CheckSubTreePermission = 10,
+ CheckOpenSubKeyWithWritablePermission = 11,
+ CheckOpenSubKeyPermission = 12
+ };
+
+
+ /**
+ * Creates a RegistryKey.
+ *
+ * This key is bound to hkey, if writable is <b>false</b> then no write operations
+ * will be allowed.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey(SafeRegistryHandle hkey, bool writable, RegistryView view)
+ : this(hkey, writable, false, false, false, view) {
+ }
+
+
+ /**
+ * Creates a RegistryKey.
+ *
+ * This key is bound to hkey, if writable is <b>false</b> then no write operations
+ * will be allowed. If systemkey is set then the hkey won't be released
+ * when the object is GC'ed.
+ * The remoteKey flag when set to true indicates that we are dealing with registry entries
+ * on a remote machine and requires the program making these calls to have full trust.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey(SafeRegistryHandle hkey, bool writable, bool systemkey, bool remoteKey, bool isPerfData, RegistryView view) {
+ this.hkey = hkey;
+ this.keyName = "";
+ this.remoteKey = remoteKey;
+ this.regView = view;
+ if (systemkey) {
+ this.state |= STATE_SYSTEMKEY;
+ }
+ if (writable) {
+ this.state |= STATE_WRITEACCESS;
+ }
+ if (isPerfData)
+ this.state |= STATE_PERF_DATA;
+ ValidateKeyView(view);
+ }
+
+ /**
+ * Closes this key, flushes it to disk if the contents have been modified.
+ */
+ public void Close() {
+ Dispose(true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void Dispose(bool disposing) {
+ if (hkey != null) {
+
+ if (!IsSystemKey()) {
+ try {
+ hkey.Dispose();
+ }
+ catch (IOException){
+ // we don't really care if the handle is invalid at this point
+ }
+ finally
+ {
+ hkey = null;
+ }
+ }
+ else if (disposing && IsPerfDataKey()) {
+ // System keys should never be closed. However, we want to call RegCloseKey
+ // on HKEY_PERFORMANCE_DATA when called from PerformanceCounter.CloseSharedResources
+ // (i.e. when disposing is true) so that we release the PERFLIB cache and cause it
+ // to be refreshed (by re-reading the registry) when accessed subsequently.
+ // This is the only way we can see the just installed perf counter.
+ // NOTE: since HKEY_PERFORMANCE_DATA is process wide, there is inherent race condition in closing
+ // the key asynchronously. While Vista is smart enough to rebuild the PERFLIB resources
+ // in this situation the down level OSes are not. We have a small window between
+ // the dispose below and usage elsewhere (other threads). This is By Design.
+ // This is less of an issue when OS > NT5 (i.e Vista & higher), we can close the perfkey
+ // (to release & refresh PERFLIB resources) and the OS will rebuild PERFLIB as necessary.
+ SafeRegistryHandle.RegCloseKey(RegistryKey.HKEY_PERFORMANCE_DATA);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Flush() {
+ if (hkey != null) {
+ if (IsDirty()) {
+ Win32Native.RegFlushKey(hkey);
+ }
+ }
+ }
+
+#if FEATURE_CORECLR
+ void IDisposable.Dispose()
+#else
+ public void Dispose()
+#endif
+ {
+ Dispose(true);
+ }
+
+ /**
+ * Creates a new subkey, or opens an existing one.
+ *
+ * @param subkey Name or path to subkey to create or open.
+ *
+ * @return the subkey, or <b>null</b> if the operation failed.
+ */
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public RegistryKey CreateSubKey(String subkey) {
+ return CreateSubKey(subkey, checkMode);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, null, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions options)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, null, options);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, bool writable)
+ {
+ return CreateSubKeyInternal(subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, null, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public RegistryKey CreateSubKey(String subkey, bool writable, RegistryOptions options)
+ {
+ return CreateSubKeyInternal(subkey, writable ? RegistryKeyPermissionCheck.ReadWriteSubTree : RegistryKeyPermissionCheck.ReadSubTree, null, options);
+ }
+
+
+#if FEATURE_MACL
+ [ComVisible(false)]
+ public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistrySecurity registrySecurity)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, RegistryOptions.None);
+ }
+
+ [ComVisible(false)]
+ public unsafe RegistryKey CreateSubKey(String subkey, RegistryKeyPermissionCheck permissionCheck, RegistryOptions registryOptions, RegistrySecurity registrySecurity)
+ {
+ return CreateSubKeyInternal(subkey, permissionCheck, registrySecurity, registryOptions);
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ private unsafe RegistryKey CreateSubKeyInternal(String subkey, RegistryKeyPermissionCheck permissionCheck, object registrySecurityObj, RegistryOptions registryOptions)
+ {
+ ValidateKeyOptions(registryOptions);
+ ValidateKeyName(subkey);
+ ValidateKeyMode(permissionCheck);
+ EnsureWriteable();
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+
+ // only keys opened under read mode is not writable
+ if (!remoteKey) {
+ RegistryKey key = InternalOpenSubKey(subkey, (permissionCheck != RegistryKeyPermissionCheck.ReadSubTree));
+ if (key != null) { // Key already exits
+ CheckPermission(RegistryInternalCheck.CheckSubKeyWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, subkey, false, permissionCheck);
+ key.checkMode = permissionCheck;
+ return key;
+ }
+ }
+
+ CheckPermission(RegistryInternalCheck.CheckSubKeyCreatePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if FEATURE_MACL
+ RegistrySecurity registrySecurity = (RegistrySecurity)registrySecurityObj;
+ // For ACL's, get the security descriptor from the RegistrySecurity.
+ if (registrySecurity != null) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ byte[] sd = registrySecurity.GetSecurityDescriptorBinaryForm();
+ // We allocate memory on the stack to improve the speed.
+ // So this part of code can't be refactored into a method.
+ byte* pSecDescriptor = stackalloc byte[sd.Length];
+ Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length);
+ secAttrs.pSecurityDescriptor = pSecDescriptor;
+ }
+#endif
+ int disposition = 0;
+
+ // By default, the new key will be writable.
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegCreateKeyEx(hkey,
+ subkey,
+ 0,
+ null,
+ (int)registryOptions /* specifies if the key is volatile */,
+ GetRegistryKeyAccess(permissionCheck != RegistryKeyPermissionCheck.ReadSubTree) | (int)regView,
+ secAttrs,
+ out result,
+ out disposition);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, (permissionCheck != RegistryKeyPermissionCheck.ReadSubTree), false, remoteKey, false, regView);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, subkey, false, permissionCheck);
+ key.checkMode = permissionCheck;
+
+ if (subkey.Length == 0)
+ key.keyName = keyName;
+ else
+ key.keyName = keyName + "\\" + subkey;
+ return key;
+ }
+ else if (ret != 0) // syscall failed, ret is an error code.
+ Win32Error(ret, keyName + "\\" + subkey); // Access denied?
+
+ BCLDebug.Assert(false, "Unexpected code path in RegistryKey::CreateSubKey");
+ return null;
+ }
+
+ /**
+ * Deletes the specified subkey. Will throw an exception if the subkey has
+ * subkeys. To delete a tree of subkeys use, DeleteSubKeyTree.
+ *
+ * @param subkey SubKey to delete.
+ *
+ * @exception InvalidOperationException thrown if the subkey has child subkeys.
+ */
+ public void DeleteSubKey(String subkey) {
+ DeleteSubKey(subkey, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DeleteSubKey(String subkey, bool throwOnMissingSubKey) {
+ ValidateKeyName(subkey);
+ EnsureWriteable();
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+ CheckPermission(RegistryInternalCheck.CheckSubKeyWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ // Open the key we are deleting and check for children. Be sure to
+ // explicitly call close to avoid keeping an extra HKEY open.
+ //
+ RegistryKey key = InternalOpenSubKey(subkey,false);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_RegRemoveSubKey);
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+
+ if (ret!=0) {
+ if (ret == Win32Native.ERROR_FILE_NOT_FOUND) {
+ if (throwOnMissingSubKey)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ else
+ Win32Error(ret, null);
+ }
+ }
+ else { // there is no key which also means there is no subkey
+ if (throwOnMissingSubKey)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ /**
+ * Recursively deletes a subkey and any child subkeys.
+ *
+ * @param subkey SubKey to delete.
+ */
+ public void DeleteSubKeyTree(String subkey) {
+ DeleteSubKeyTree(subkey, true /*throwOnMissingSubKey*/);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public void DeleteSubKeyTree(String subkey, Boolean throwOnMissingSubKey) {
+ ValidateKeyName(subkey);
+
+ // Security concern: Deleting a hive's "" subkey would delete all
+ // of that hive's contents. Don't allow "".
+ if (subkey.Length==0 && IsSystemKey()) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyDelHive);
+ }
+
+ EnsureWriteable();
+
+ subkey = FixupName(subkey); // Fixup multiple slashes to a single slash
+ CheckPermission(RegistryInternalCheck.CheckSubTreeWritePermission, subkey, false, RegistryKeyPermissionCheck.Default);
+
+ RegistryKey key = InternalOpenSubKey(subkey, true);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ String[] keys = key.InternalGetSubKeyNames();
+
+ for (int i=0; i<keys.Length; i++) {
+ key.DeleteSubKeyTreeInternal(keys[i]);
+ }
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+
+ if (ret!=0) Win32Error(ret, null);
+ }
+ else if(throwOnMissingSubKey) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ // An internal version which does no security checks or argument checking. Skipping the
+ // security checks should give us a slight perf gain on large trees.
+ [System.Security.SecurityCritical] // auto-generated
+ private void DeleteSubKeyTreeInternal(string subkey) {
+ RegistryKey key = InternalOpenSubKey(subkey, true);
+ if (key != null) {
+ try {
+ if (key.InternalSubKeyCount() > 0) {
+ String[] keys = key.InternalGetSubKeyNames();
+
+ for (int i=0; i<keys.Length; i++) {
+ key.DeleteSubKeyTreeInternal(keys[i]);
+ }
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ int ret;
+ try {
+ ret = Win32Native.RegDeleteKeyEx(hkey, subkey, (int)regView, 0);
+ }
+ catch (EntryPointNotFoundException) {
+ ret = Win32Native.RegDeleteKey(hkey, subkey);
+ }
+ if (ret!=0) Win32Error(ret, null);
+ }
+ else {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyAbsent);
+ }
+ }
+
+ /**
+ * Deletes the specified value from this key.
+ *
+ * @param name Name of value to delete.
+ */
+ public void DeleteValue(String name) {
+ DeleteValue(name, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DeleteValue(String name, bool throwOnMissingValue) {
+ EnsureWriteable();
+ CheckPermission(RegistryInternalCheck.CheckValueWritePermission, name, false, RegistryKeyPermissionCheck.Default);
+ int errorCode = Win32Native.RegDeleteValue(hkey, name);
+
+ //
+ // From windows 2003 server, if the name is too long we will get error code ERROR_FILENAME_EXCED_RANGE
+ // This still means the name doesn't exist. We need to be consistent with previous OS.
+ //
+ if (errorCode == Win32Native.ERROR_FILE_NOT_FOUND || errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) {
+ if (throwOnMissingValue) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSubKeyValueAbsent);
+ }
+ // Otherwise, just return giving no indication to the user.
+ // (For compatibility)
+ }
+ // We really should throw an exception here if errorCode was bad,
+ // but we can't for compatibility reasons.
+ BCLDebug.Correctness(errorCode == 0, "RegDeleteValue failed. Here's your error code: "+errorCode);
+ }
+
+ /**
+ * Retrieves a new RegistryKey that represents the requested key. Valid
+ * values are:
+ *
+ * HKEY_CLASSES_ROOT,
+ * HKEY_CURRENT_USER,
+ * HKEY_LOCAL_MACHINE,
+ * HKEY_USERS,
+ * HKEY_PERFORMANCE_DATA,
+ * HKEY_CURRENT_CONFIG,
+ * HKEY_DYN_DATA.
+ *
+ * @param hKey HKEY_* to open.
+ *
+ * @return the RegistryKey requested.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RegistryKey GetBaseKey(IntPtr hKey) {
+ return GetBaseKey(hKey, RegistryView.Default);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RegistryKey GetBaseKey(IntPtr hKey, RegistryView view) {
+
+ int index = ((int)hKey) & 0x0FFFFFFF;
+ BCLDebug.Assert(index >= 0 && index < hkeyNames.Length, "index is out of range!");
+ BCLDebug.Assert((((int)hKey) & 0xFFFFFFF0) == 0x80000000, "Invalid hkey value!");
+
+ bool isPerf = hKey == HKEY_PERFORMANCE_DATA;
+ // only mark the SafeHandle as ownsHandle if the key is HKEY_PERFORMANCE_DATA.
+ SafeRegistryHandle srh = new SafeRegistryHandle(hKey, isPerf);
+
+ RegistryKey key = new RegistryKey(srh, true, true,false, isPerf, view);
+ key.checkMode = RegistryKeyPermissionCheck.Default;
+ key.keyName = hkeyNames[index];
+ return key;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public static RegistryKey OpenBaseKey(RegistryHive hKey, RegistryView view) {
+ ValidateKeyView(view);
+ CheckUnmanagedCodePermission();
+ return GetBaseKey((IntPtr)((int)hKey), view);
+ }
+
+ /**
+ * Retrieves a new RegistryKey that represents the requested key on a foreign
+ * machine. Valid values for hKey are members of the RegistryHive enum, or
+ * Win32 integers such as:
+ *
+ * HKEY_CLASSES_ROOT,
+ * HKEY_CURRENT_USER,
+ * HKEY_LOCAL_MACHINE,
+ * HKEY_USERS,
+ * HKEY_PERFORMANCE_DATA,
+ * HKEY_CURRENT_CONFIG,
+ * HKEY_DYN_DATA.
+ *
+ * @param hKey HKEY_* to open.
+ * @param machineName the machine to connect to
+ *
+ * @return the RegistryKey requested.
+ */
+ public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, String machineName) {
+ return OpenRemoteBaseKey(hKey, machineName, RegistryView.Default);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public static RegistryKey OpenRemoteBaseKey(RegistryHive hKey, String machineName, RegistryView view) {
+ if (machineName==null)
+ throw new ArgumentNullException("machineName");
+ int index = (int)hKey & 0x0FFFFFFF;
+ if (index < 0 || index >= hkeyNames.Length || ((int)hKey & 0xFFFFFFF0) != 0x80000000) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegKeyOutOfRange"));
+ }
+ ValidateKeyView(view);
+
+ CheckUnmanagedCodePermission();
+ // connect to the specified remote registry
+ SafeRegistryHandle foreignHKey = null;
+ int ret = Win32Native.RegConnectRegistry(machineName, new SafeRegistryHandle(new IntPtr((int)hKey), false), out foreignHKey);
+
+ if (ret == Win32Native.ERROR_DLL_INIT_FAILED)
+ // return value indicates an error occurred
+ throw new ArgumentException(Environment.GetResourceString("Arg_DllInitFailure"));
+
+ if (ret != 0)
+ Win32ErrorStatic(ret, null);
+
+ if (foreignHKey.IsInvalid)
+ // return value indicates an error occurred
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegKeyNoRemoteConnect", machineName));
+
+ RegistryKey key = new RegistryKey(foreignHKey, true, false, true, ((IntPtr) hKey) == HKEY_PERFORMANCE_DATA, view);
+ key.checkMode = RegistryKeyPermissionCheck.Default;
+ key.keyName = hkeyNames[index];
+ return key;
+ }
+
+ /**
+ * Retrieves a subkey. If readonly is <b>true</b>, then the subkey is opened with
+ * read-only access.
+ *
+ * @param name Name or path of subkey to open.
+ * @param readonly Set to <b>true</b> if you only need readonly access.
+ *
+ * @return the Subkey requested, or <b>null</b> if the operation failed.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public RegistryKey OpenSubKey(string name, bool writable ) {
+ ValidateKeyName(name);
+ EnsureNotDisposed();
+ name = FixupName(name); // Fixup multiple slashes to a single slash
+
+ CheckPermission(RegistryInternalCheck.CheckOpenSubKeyWithWritablePermission, name, writable, RegistryKeyPermissionCheck.Default);
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey,
+ name,
+ 0,
+ GetRegistryKeyAccess(writable) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, writable, false, remoteKey, false, regView);
+ key.checkMode = GetSubKeyPermissonCheck(writable);
+ key.keyName = keyName + "\\" + name;
+ return key;
+ }
+
+ // Return null if we didn't find the key.
+ if (ret == Win32Native.ERROR_ACCESS_DENIED || ret == Win32Native.ERROR_BAD_IMPERSONATION_LEVEL) {
+ // We need to throw SecurityException here for compatibility reasons,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+
+ return null;
+ }
+
+#if FEATURE_MACL
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck) {
+ ValidateKeyMode(permissionCheck);
+ return InternalOpenSubKey(name, permissionCheck, GetRegistryKeyAccess(permissionCheck));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryRights rights)
+ {
+ return InternalOpenSubKey(name, this.checkMode, (int)rights);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryKey OpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, RegistryRights rights) {
+ return InternalOpenSubKey(name, permissionCheck, (int)rights);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private RegistryKey InternalOpenSubKey(String name, RegistryKeyPermissionCheck permissionCheck, int rights) {
+ ValidateKeyName(name);
+ ValidateKeyMode(permissionCheck);
+
+ ValidateKeyRights(rights);
+
+ EnsureNotDisposed();
+ name = FixupName(name); // Fixup multiple slashes to a single slash
+
+ CheckPermission(RegistryInternalCheck.CheckOpenSubKeyPermission, name, false, permissionCheck);
+ CheckPermission(RegistryInternalCheck.CheckSubTreePermission, name, false, permissionCheck);
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey, name, 0, (rights | (int)regView), out result);
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, (permissionCheck == RegistryKeyPermissionCheck.ReadWriteSubTree), false, remoteKey, false, regView);
+ key.keyName = keyName + "\\" + name;
+ key.checkMode = permissionCheck;
+ return key;
+ }
+
+ // Return null if we didn't find the key.
+ if (ret == Win32Native.ERROR_ACCESS_DENIED || ret == Win32Native.ERROR_BAD_IMPERSONATION_LEVEL) {
+ // We need to throw SecurityException here for compatiblity reason,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+
+ return null;
+ }
+#endif
+
+ // This required no security checks. This is to get around the Deleting SubKeys which only require
+ // write permission. They call OpenSubKey which required read. Now instead call this function w/o security checks
+ [System.Security.SecurityCritical] // auto-generated
+ internal RegistryKey InternalOpenSubKey(String name, bool writable) {
+ ValidateKeyName(name);
+ EnsureNotDisposed();
+
+ SafeRegistryHandle result = null;
+ int ret = Win32Native.RegOpenKeyEx(hkey,
+ name,
+ 0,
+ GetRegistryKeyAccess(writable) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ RegistryKey key = new RegistryKey(result, writable, false, remoteKey, false, regView);
+ key.keyName = keyName + "\\" + name;
+ return key;
+ }
+ return null;
+ }
+
+ /**
+ * Returns a subkey with read only permissions.
+ *
+ * @param name Name or path of subkey to open.
+ *
+ * @return the Subkey requested, or <b>null</b> if the operation failed.
+ */
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+#endif
+ public RegistryKey OpenSubKey(String name) {
+ return OpenSubKey(name, false);
+ }
+
+ /**
+ * Retrieves the count of subkeys.
+ *
+ * @return a count of subkeys.
+ */
+ public int SubKeyCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalSubKeyCount();
+ }
+ }
+
+ [ComVisible(false)]
+ public RegistryView View {
+ [System.Security.SecuritySafeCritical]
+ get {
+ EnsureNotDisposed();
+ return regView;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [ComVisible(false)]
+ public SafeRegistryHandle Handle {
+ [System.Security.SecurityCritical]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ get {
+ EnsureNotDisposed();
+ int ret = Win32Native.ERROR_INVALID_HANDLE;
+ if (IsSystemKey()) {
+ IntPtr baseKey = (IntPtr)0;
+ switch (keyName) {
+ case "HKEY_CLASSES_ROOT":
+ baseKey = HKEY_CLASSES_ROOT;
+ break;
+ case "HKEY_CURRENT_USER":
+ baseKey = HKEY_CURRENT_USER;
+ break;
+ case "HKEY_LOCAL_MACHINE":
+ baseKey = HKEY_LOCAL_MACHINE;
+ break;
+ case "HKEY_USERS":
+ baseKey = HKEY_USERS;
+ break;
+ case "HKEY_PERFORMANCE_DATA":
+ baseKey = HKEY_PERFORMANCE_DATA;
+ break;
+ case "HKEY_CURRENT_CONFIG":
+ baseKey = HKEY_CURRENT_CONFIG;
+ break;
+ case "HKEY_DYN_DATA":
+ baseKey = HKEY_DYN_DATA;
+ break;
+ default:
+ Win32Error(ret, null);
+ break;
+ }
+ // open the base key so that RegistryKey.Handle will return a valid handle
+ SafeRegistryHandle result;
+ ret = Win32Native.RegOpenKeyEx(baseKey,
+ null,
+ 0,
+ GetRegistryKeyAccess(IsWritable()) | (int)regView,
+ out result);
+
+ if (ret == 0 && !result.IsInvalid) {
+ return result;
+ }
+ else {
+ Win32Error(ret, null);
+ }
+ }
+ else {
+ return hkey;
+ }
+ throw new IOException(Win32Native.GetMessage(ret), ret);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ [ComVisible(false)]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public static RegistryKey FromHandle(SafeRegistryHandle handle) {
+ return FromHandle(handle, RegistryView.Default);
+ }
+
+ [System.Security.SecurityCritical]
+ [ComVisible(false)]
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public static RegistryKey FromHandle(SafeRegistryHandle handle, RegistryView view) {
+ if (handle == null) throw new ArgumentNullException("handle");
+ ValidateKeyView(view);
+
+ return new RegistryKey(handle, true /* isWritable */, view);
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int InternalSubKeyCount() {
+ EnsureNotDisposed();
+
+ int subkeys = 0;
+ int junk = 0;
+ int ret = Win32Native.RegQueryInfoKey(hkey,
+ null,
+ null,
+ IntPtr.Zero,
+ ref subkeys, // subkeys
+ null,
+ null,
+ ref junk, // values
+ null,
+ null,
+ null,
+ null);
+
+ if (ret != 0)
+ Win32Error(ret, null);
+ return subkeys;
+ }
+
+ /**
+ * Retrieves an array of strings containing all the subkey names.
+ *
+ * @return all subkey names.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public String[] GetSubKeyNames() {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetSubKeyNames();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe String[] InternalGetSubKeyNames() {
+ EnsureNotDisposed();
+ int subkeys = InternalSubKeyCount();
+ String[] names = new String[subkeys]; // Returns 0-length array if empty.
+
+ if (subkeys > 0) {
+ char[] name = new char[MaxKeyLength + 1];
+
+ int namelen;
+
+ fixed (char *namePtr = &name[0])
+ {
+ for (int i=0; i<subkeys; i++) {
+ namelen = name.Length; // Don't remove this. The API's doesn't work if this is not properly initialised.
+ int ret = Win32Native.RegEnumKeyEx(hkey,
+ i,
+ namePtr,
+ ref namelen,
+ null,
+ null,
+ null,
+ null);
+ if (ret != 0)
+ Win32Error(ret, null);
+ names[i] = new String(namePtr);
+ }
+ }
+ }
+
+ return names;
+ }
+
+ /**
+ * Retrieves the count of values.
+ *
+ * @return a count of values.
+ */
+ public int ValueCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ return InternalValueCount();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int InternalValueCount() {
+ EnsureNotDisposed();
+ int values = 0;
+ int junk = 0;
+ int ret = Win32Native.RegQueryInfoKey(hkey,
+ null,
+ null,
+ IntPtr.Zero,
+ ref junk, // subkeys
+ null,
+ null,
+ ref values, // values
+ null,
+ null,
+ null,
+ null);
+ if (ret != 0)
+ Win32Error(ret, null);
+ return values;
+ }
+
+ /**
+ * Retrieves an array of strings containing all the value names.
+ *
+ * @return all value names.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe String[] GetValueNames() {
+ CheckPermission(RegistryInternalCheck.CheckKeyReadPermission, null, false, RegistryKeyPermissionCheck.Default);
+ EnsureNotDisposed();
+
+ int values = InternalValueCount();
+ String[] names = new String[values];
+
+ if (values > 0) {
+ char[] name = new char[MaxValueLength + 1];
+ int namelen;
+
+ fixed (char *namePtr = &name[0])
+ {
+ for (int i=0; i<values; i++) {
+ namelen = name.Length;
+
+ int ret = Win32Native.RegEnumValue(hkey,
+ i,
+ namePtr,
+ ref namelen,
+ IntPtr.Zero,
+ null,
+ null,
+ null);
+
+ if (ret != 0) {
+ // ignore ERROR_MORE_DATA if we're querying HKEY_PERFORMANCE_DATA
+ if (!(IsPerfDataKey() && ret == Win32Native.ERROR_MORE_DATA))
+ Win32Error(ret, null);
+ }
+
+ names[i] = new String(namePtr);
+ }
+ }
+ }
+
+ return names;
+ }
+
+ /**
+ * Retrieves the specified value. <b>null</b> is returned if the value
+ * doesn't exist.
+ *
+ * Note that <var>name</var> can be null or "", at which point the
+ * unnamed or default value of this Registry key is returned, if any.
+ *
+ * @param name Name of value to retrieve.
+ *
+ * @return the data associated with the value.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Object GetValue(String name) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, null, false, true);
+ }
+
+ /**
+ * Retrieves the specified value. <i>defaultValue</i> is returned if the value doesn't exist.
+ *
+ * Note that <var>name</var> can be null or "", at which point the
+ * unnamed or default value of this Registry key is returned, if any.
+ * The default values for RegistryKeys are OS-dependent. NT doesn't
+ * have them by default, but they can exist and be of any type. On
+ * Win95, the default value is always an empty key of type REG_SZ.
+ * Win98 supports default values of any type, but defaults to REG_SZ.
+ *
+ * @param name Name of value to retrieve.
+ * @param defaultValue Value to return if <i>name</i> doesn't exist.
+ *
+ * @return the data associated with the value.
+ */
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public Object GetValue(String name, Object defaultValue) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, defaultValue, false, true);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [ComVisible(false)]
+ public Object GetValue(String name, Object defaultValue, RegistryValueOptions options) {
+ if( options < RegistryValueOptions.None || options > RegistryValueOptions.DoNotExpandEnvironmentNames) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options), "options");
+ }
+ bool doNotExpand = (options == RegistryValueOptions.DoNotExpandEnvironmentNames);
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ return InternalGetValue(name, defaultValue, doNotExpand, true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object InternalGetValue(String name, Object defaultValue, bool doNotExpand, bool checkSecurity) {
+ if (checkSecurity) {
+ // Name can be null! It's the most common use of RegQueryValueEx
+ EnsureNotDisposed();
+ }
+
+ Object data = defaultValue;
+ int type = 0;
+ int datasize = 0;
+
+ int ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+
+ if (ret != 0) {
+ if (IsPerfDataKey()) {
+ int size = 65000;
+ int sizeInput = size;
+
+ int r;
+ byte[] blob = new byte[size];
+ while (Win32Native.ERROR_MORE_DATA == (r = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref sizeInput))) {
+ if (size == Int32.MaxValue) {
+ // ERROR_MORE_DATA was returned however we cannot increase the buffer size beyond Int32.MaxValue
+ Win32Error(r, name);
+ }
+ else if (size > (Int32.MaxValue / 2)) {
+ // at this point in the loop "size * 2" would cause an overflow
+ size = Int32.MaxValue;
+ }
+ else {
+ size *= 2;
+ }
+ sizeInput = size;
+ blob = new byte[size];
+ }
+ if (r != 0)
+ Win32Error(r, name);
+ return blob;
+ }
+ else {
+ // For stuff like ERROR_FILE_NOT_FOUND, we want to return null (data).
+ // Some OS's returned ERROR_MORE_DATA even in success cases, so we
+ // want to continue on through the function.
+ if (ret != Win32Native.ERROR_MORE_DATA)
+ return data;
+ }
+ }
+
+ if (datasize < 0) {
+ // unexpected code path
+ BCLDebug.Assert(false, "[InternalGetValue] RegQueryValue returned ERROR_SUCCESS but gave a negative datasize");
+ datasize = 0;
+ }
+
+
+ switch (type) {
+ case Win32Native.REG_NONE:
+ case Win32Native.REG_DWORD_BIG_ENDIAN:
+ case Win32Native.REG_BINARY: {
+ byte[] blob = new byte[datasize];
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+ data = blob;
+ }
+ break;
+ case Win32Native.REG_QWORD:
+ { // also REG_QWORD_LITTLE_ENDIAN
+ if (datasize > 8) {
+ // prevent an AV in the edge case that datasize is larger than sizeof(long)
+ goto case Win32Native.REG_BINARY;
+ }
+ long blob = 0;
+ BCLDebug.Assert(datasize==8, "datasize==8");
+ // Here, datasize must be 8 when calling this
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, ref blob, ref datasize);
+
+ data = blob;
+ }
+ break;
+ case Win32Native.REG_DWORD:
+ { // also REG_DWORD_LITTLE_ENDIAN
+ if (datasize > 4) {
+ // prevent an AV in the edge case that datasize is larger than sizeof(int)
+ goto case Win32Native.REG_QWORD;
+ }
+ int blob = 0;
+ BCLDebug.Assert(datasize==4, "datasize==4");
+ // Here, datasize must be four when calling this
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, ref blob, ref datasize);
+
+ data = blob;
+ }
+ break;
+
+ case Win32Native.REG_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+ if (blob.Length > 0 && blob[blob.Length - 1] == (char)0) {
+ data = new String(blob, 0, blob.Length - 1);
+ }
+ else {
+ // in the very unlikely case the data is missing null termination,
+ // pass in the whole char[] to prevent truncating a character
+ data = new String(blob);
+ }
+ }
+ break;
+
+ case Win32Native.REG_EXPAND_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+
+ if (blob.Length > 0 && blob[blob.Length - 1] == (char)0) {
+ data = new String(blob, 0, blob.Length - 1);
+ }
+ else {
+ // in the very unlikely case the data is missing null termination,
+ // pass in the whole char[] to prevent truncating a character
+ data = new String(blob);
+ }
+
+ if (!doNotExpand)
+ data = Environment.ExpandEnvironmentVariables((String)data);
+ }
+ break;
+ case Win32Native.REG_MULTI_SZ:
+ {
+ if (datasize % 2 == 1) {
+ // handle the case where the registry contains an odd-byte length (corrupt data?)
+ try {
+ datasize = checked(datasize + 1);
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ }
+ char[] blob = new char[datasize/2];
+
+ ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref datasize);
+
+ // make sure the string is null terminated before processing the data
+ if (blob.Length > 0 && blob[blob.Length - 1] != (char)0) {
+ try {
+ char[] newBlob = new char[checked(blob.Length + 1)];
+ for (int i = 0; i < blob.Length; i++) {
+ newBlob[i] = blob[i];
+ }
+ newBlob[newBlob.Length - 1] = (char)0;
+ blob = newBlob;
+ }
+ catch (OverflowException e) {
+ throw new IOException(Environment.GetResourceString("Arg_RegGetOverflowBug"), e);
+ }
+ blob[blob.Length - 1] = (char)0;
+ }
+
+
+ IList<String> strings = new List<String>();
+ int cur = 0;
+ int len = blob.Length;
+
+ while (ret == 0 && cur < len) {
+ int nextNull = cur;
+ while (nextNull < len && blob[nextNull] != (char)0) {
+ nextNull++;
+ }
+
+ if (nextNull < len) {
+ BCLDebug.Assert(blob[nextNull] == (char)0, "blob[nextNull] should be 0");
+ if (nextNull-cur > 0) {
+ strings.Add(new String(blob, cur, nextNull-cur));
+ }
+ else {
+ // we found an empty string. But if we're at the end of the data,
+ // it's just the extra null terminator.
+ if (nextNull != len-1)
+ strings.Add(String.Empty);
+ }
+ }
+ else {
+ strings.Add(new String(blob, cur, len-cur));
+ }
+ cur = nextNull+1;
+ }
+
+ data = new String[strings.Count];
+ strings.CopyTo((String[])data, 0);
+ }
+ break;
+ case Win32Native.REG_LINK:
+ default:
+ break;
+ }
+
+ return data;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public RegistryValueKind GetValueKind(string name) {
+ CheckPermission(RegistryInternalCheck.CheckValueReadPermission, name, false, RegistryKeyPermissionCheck.Default);
+ EnsureNotDisposed();
+
+ int type = 0;
+ int datasize = 0;
+ int ret = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+ if (ret != 0)
+ Win32Error(ret, null);
+ if (type == Win32Native.REG_NONE)
+ return RegistryValueKind.None;
+ else if (!Enum.IsDefined(typeof(RegistryValueKind), type))
+ return RegistryValueKind.Unknown;
+ else
+ return (RegistryValueKind) type;
+ }
+
+ /**
+ * Retrieves the current state of the dirty property.
+ *
+ * A key is marked as dirty if any operation has occurred that modifies the
+ * contents of the key.
+ *
+ * @return <b>true</b> if the key has been modified.
+ */
+ private bool IsDirty() {
+ return (this.state & STATE_DIRTY) != 0;
+ }
+
+ private bool IsSystemKey() {
+ return (this.state & STATE_SYSTEMKEY) != 0;
+ }
+
+ private bool IsWritable() {
+ return (this.state & STATE_WRITEACCESS) != 0;
+ }
+
+ private bool IsPerfDataKey() {
+ return (this.state & STATE_PERF_DATA) != 0;
+ }
+
+ public String Name {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ EnsureNotDisposed();
+ return keyName;
+ }
+ }
+
+ private void SetDirty() {
+ this.state |= STATE_DIRTY;
+ }
+
+ /**
+ * Sets the specified value.
+ *
+ * @param name Name of value to store data in.
+ * @param value Data to store.
+ */
+ public void SetValue(String name, Object value) {
+ SetValue(name, value, RegistryValueKind.Unknown);
+ }
+
+ [System.Security.SecuritySafeCritical] //auto-generated
+ [ComVisible(false)]
+ public unsafe void SetValue(String name, Object value, RegistryValueKind valueKind) {
+ if (value==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+
+ if (name != null && name.Length > MaxValueLength) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegValStrLenBug"));
+ }
+
+ if (!Enum.IsDefined(typeof(RegistryValueKind), valueKind))
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegBadKeyKind"), "valueKind");
+
+ EnsureWriteable();
+
+ if (!remoteKey && ContainsRegistryValue(name)) { // Existing key
+ CheckPermission(RegistryInternalCheck.CheckValueWritePermission, name, false, RegistryKeyPermissionCheck.Default);
+ }
+ else { // Creating a new value
+ CheckPermission(RegistryInternalCheck.CheckValueCreatePermission, name, false, RegistryKeyPermissionCheck.Default);
+ }
+
+ if (valueKind == RegistryValueKind.Unknown) {
+ // this is to maintain compatibility with the old way of autodetecting the type.
+ // SetValue(string, object) will come through this codepath.
+ valueKind = CalculateValueKind(value);
+ }
+
+ int ret = 0;
+ try {
+ switch (valueKind) {
+ case RegistryValueKind.ExpandString:
+ case RegistryValueKind.String:
+ {
+ String data = value.ToString();
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ valueKind,
+ data,
+ checked(data.Length * 2 + 2));
+ break;
+ }
+
+ case RegistryValueKind.MultiString:
+ {
+ // Other thread might modify the input array after we calculate the buffer length.
+ // Make a copy of the input array to be safe.
+ string[] dataStrings = (string[])(((string[])value).Clone());
+ int sizeInBytes = 0;
+
+ // First determine the size of the array
+ //
+ for (int i=0; i<dataStrings.Length; i++) {
+ if (dataStrings[i] == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetStrArrNull);
+ }
+ sizeInBytes = checked(sizeInBytes + (dataStrings[i].Length+1) * 2);
+ }
+ sizeInBytes = checked(sizeInBytes + 2);
+
+ byte[] basePtr = new byte[sizeInBytes];
+ fixed(byte* b = basePtr) {
+ IntPtr currentPtr = new IntPtr( (void *) b);
+
+ // Write out the strings...
+ //
+ for (int i=0; i<dataStrings.Length; i++) {
+ // Assumes that the Strings are always null terminated.
+ String.InternalCopy(dataStrings[i],currentPtr,(checked(dataStrings[i].Length*2)));
+ currentPtr = new IntPtr((long)currentPtr + (checked(dataStrings[i].Length*2)));
+ *(char*)(currentPtr.ToPointer()) = '\0';
+ currentPtr = new IntPtr((long)currentPtr + 2);
+ }
+
+ *(char*)(currentPtr.ToPointer()) = '\0';
+ currentPtr = new IntPtr((long)currentPtr + 2);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.MultiString,
+ basePtr,
+ sizeInBytes);
+ }
+ break;
+ }
+
+ case RegistryValueKind.None:
+ case RegistryValueKind.Binary:
+ byte[] dataBytes = (byte[]) value;
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ (valueKind == RegistryValueKind.None ? Win32Native.REG_NONE: RegistryValueKind.Binary),
+ dataBytes,
+ dataBytes.Length);
+ break;
+
+ case RegistryValueKind.DWord:
+ {
+ // We need to use Convert here because we could have a boxed type cannot be
+ // unboxed and cast at the same time. I.e. ((int)(object)(short) 5) will fail.
+ int data = Convert.ToInt32(value, System.Globalization.CultureInfo.InvariantCulture);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.DWord,
+ ref data,
+ 4);
+ break;
+ }
+
+ case RegistryValueKind.QWord:
+ {
+ long data = Convert.ToInt64(value, System.Globalization.CultureInfo.InvariantCulture);
+
+ ret = Win32Native.RegSetValueEx(hkey,
+ name,
+ 0,
+ RegistryValueKind.QWord,
+ ref data,
+ 8);
+ break;
+ }
+ }
+ }
+ catch (OverflowException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (InvalidOperationException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (FormatException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegSetMismatchedKind);
+ }
+
+ if (ret == 0) {
+ SetDirty();
+ }
+ else
+ Win32Error(ret, null);
+
+ }
+
+ private RegistryValueKind CalculateValueKind(Object value) {
+ // This logic matches what used to be in SetValue(string name, object value) in the v1.0 and v1.1 days.
+ // Even though we could add detection for an int64 in here, we want to maintain compatibility with the
+ // old behavior.
+ if (value is Int32)
+ return RegistryValueKind.DWord;
+ else if (value is Array) {
+ if (value is byte[])
+ return RegistryValueKind.Binary;
+ else if (value is String[])
+ return RegistryValueKind.MultiString;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Arg_RegSetBadArrType", value.GetType().Name));
+ }
+ else
+ return RegistryValueKind.String;
+ }
+
+ /**
+ * Retrieves a string representation of this key.
+ *
+ * @return a string representing the key.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ EnsureNotDisposed();
+ return keyName;
+ }
+
+#if FEATURE_MACL
+ public RegistrySecurity GetAccessControl() {
+ return GetAccessControl(AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public RegistrySecurity GetAccessControl(AccessControlSections includeSections) {
+ EnsureNotDisposed();
+ return new RegistrySecurity(hkey, keyName, includeSections);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAccessControl(RegistrySecurity registrySecurity) {
+ EnsureWriteable();
+ if (registrySecurity == null)
+ throw new ArgumentNullException("registrySecurity");
+
+ registrySecurity.Persist(hkey, keyName);
+ }
+#endif
+
+ /**
+ * After calling GetLastWin32Error(), it clears the last error field,
+ * so you must save the HResult and pass it to this method. This method
+ * will determine the appropriate exception to throw dependent on your
+ * error, and depending on the error, insert a string into the message
+ * gotten from the ResourceManager.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal void Win32Error(int errorCode, String str) {
+ switch (errorCode) {
+ case Win32Native.ERROR_ACCESS_DENIED:
+ if (str != null)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_RegistryKeyGeneric_Key", str));
+ else
+ throw new UnauthorizedAccessException();
+
+ case Win32Native.ERROR_INVALID_HANDLE:
+ /**
+ * For normal RegistryKey instances we dispose the SafeRegHandle and throw IOException.
+ * However, for HKEY_PERFORMANCE_DATA (on a local or remote machine) we avoid disposing the
+ * SafeRegHandle and only throw the IOException. This is to workaround reentrancy issues
+ * in PerformanceCounter.NextValue() where the API could throw {NullReference, ObjectDisposed, ArgumentNull}Exception
+ * on reentrant calls because of this error code path in RegistryKey
+ *
+ * Normally we'd make our caller synchronize access to a shared RegistryKey instead of doing something like this,
+ * however we shipped PerformanceCounter.NextValue() un-synchronized in v2.0RTM and customers have taken a dependency on
+ * this behavior (being able to simultaneously query multiple remote-machine counters on multiple threads, instead of
+ * having serialized access).
+ */
+ if (!IsPerfDataKey()) {
+ this.hkey.SetHandleAsInvalid();
+ this.hkey = null;
+ }
+ goto default;
+
+ case Win32Native.ERROR_FILE_NOT_FOUND:
+ throw new IOException(Environment.GetResourceString("Arg_RegKeyNotFound"), errorCode);
+
+ default:
+ throw new IOException(Win32Native.GetMessage(errorCode), errorCode);
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal static void Win32ErrorStatic(int errorCode, String str) {
+ switch (errorCode) {
+ case Win32Native.ERROR_ACCESS_DENIED:
+ if (str != null)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_RegistryKeyGeneric_Key", str));
+ else
+ throw new UnauthorizedAccessException();
+
+ default:
+ throw new IOException(Win32Native.GetMessage(errorCode), errorCode);
+ }
+ }
+
+ internal static String FixupName(String name)
+ {
+ BCLDebug.Assert(name!=null,"[FixupName]name!=null");
+ if (name.IndexOf('\\') == -1)
+ return name;
+
+ StringBuilder sb = new StringBuilder(name);
+ FixupPath(sb);
+ int temp = sb.Length - 1;
+ if (temp >= 0 && sb[temp] == '\\') // Remove trailing slash
+ sb.Length = temp;
+ return sb.ToString();
+ }
+
+
+ private static void FixupPath(StringBuilder path)
+ {
+ Contract.Requires(path != null);
+ int length = path.Length;
+ bool fixup = false;
+ char markerChar = (char)0xFFFF;
+
+ int i = 1;
+ while (i < length - 1)
+ {
+ if (path[i] == '\\')
+ {
+ i++;
+ while (i < length)
+ {
+ if (path[i] == '\\')
+ {
+ path[i] = markerChar;
+ i++;
+ fixup = true;
+ }
+ else
+ break;
+ }
+
+ }
+ i++;
+ }
+
+ if (fixup)
+ {
+ i = 0;
+ int j = 0;
+ while (i < length)
+ {
+ if(path[i] == markerChar)
+ {
+ i++;
+ continue;
+ }
+ path[j] = path[i];
+ i++;
+ j++;
+ }
+ path.Length += j - i;
+ }
+
+ }
+
+ //
+ // Read/Write/Create SubKey Permission
+ //
+ private void GetSubKeyReadPermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+ private void GetSubKeyWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ // If we want to open a subkey of a read-only key as writeable, we need to do the check.
+ access = RegistryPermissionAccess.Write;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+ private void GetSubKeyCreatePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Create;
+ path = keyName + "\\" + subkeyName + "\\.";
+ }
+
+ //
+ // Read/Write/ReadWrite SubTree Permission
+ //
+ private void GetSubTreeReadPermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName + "\\";
+ }
+ private void GetSubTreeWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write;
+ path = keyName + "\\" + subkeyName + "\\";
+ }
+ private void GetSubTreeReadWritePermission(string subkeyName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write | RegistryPermissionAccess.Read;
+ path = keyName + "\\" + subkeyName;
+ }
+
+ //
+ // Read/Write/Create Value Permission
+ //
+ private void GetValueReadPermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName+"\\"+valueName;
+ }
+ private void GetValueWritePermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Write;
+ path = keyName+"\\"+valueName;
+ }
+ private void GetValueCreatePermission(string valueName, out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Create;
+ path = keyName+"\\"+valueName;
+ }
+
+ // Read Key Permission
+ private void GetKeyReadPermission(out RegistryPermissionAccess access, out string path) {
+ access = RegistryPermissionAccess.Read;
+ path = keyName + "\\.";
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void CheckPermission(RegistryInternalCheck check, string item, bool subKeyWritable, RegistryKeyPermissionCheck subKeyCheck) {
+ bool demand = false;
+ RegistryPermissionAccess access = RegistryPermissionAccess.NoAccess;
+ string path = null;
+
+#if !FEATURE_CORECLR
+ if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) {
+ return; // full trust fast path
+ }
+#endif // !FEATURE_CORECLR
+
+ switch (check) {
+ //
+ // Read/Write/Create SubKey Permission
+ //
+ case RegistryInternalCheck.CheckSubKeyReadPermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode == RegistryKeyPermissionCheck.Default, "Should be called from a key opened under default mode only!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ break;
+ case RegistryInternalCheck.CheckSubKeyWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating sub key under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubKeyWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubKeyCreatePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating sub key under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubKeyCreatePermission(item, out access, out path);
+ }
+ }
+ break;
+ //
+ // Read/Write/ReadWrite SubTree Permission
+ //
+ case RegistryInternalCheck.CheckSubTreeReadPermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubTreeReadPermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubTreeWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow writing value to read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetSubTreeWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckSubTreeReadWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // If we want to open a subkey of a read-only key as writeable, we need to do the check.
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ break;
+ //
+ // Read/Write/Create Value Permission
+ //
+ case RegistryInternalCheck.CheckValueReadPermission:
+ ///*** no remoteKey check ***///
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ // only need to check for default mode (dynamice check)
+ demand = true;
+ GetValueReadPermission(item, out access, out path);
+ }
+ break;
+ case RegistryInternalCheck.CheckValueWritePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow writing value to read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // skip the security check if the key is opened under write mode
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetValueWritePermission(item, out access, out path);
+ }
+ }
+ break;
+ case RegistryInternalCheck.CheckValueCreatePermission:
+ if (remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ BCLDebug.Assert(checkMode != RegistryKeyPermissionCheck.ReadSubTree, "We shouldn't allow creating value under read-only key!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // skip the security check if the key is opened under write mode
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ demand = true;
+ GetValueCreatePermission(item, out access, out path);
+ }
+ }
+ break;
+ //
+ // CheckKeyReadPermission
+ //
+ case RegistryInternalCheck.CheckKeyReadPermission:
+ ///*** no remoteKey check ***///
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ BCLDebug.Assert(item == null, "CheckKeyReadPermission should never have a non-null item parameter!");
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+
+ // only need to check for default mode (dynamice check)
+ demand = true;
+ GetKeyReadPermission(out access, out path);
+ }
+ break;
+ //
+ // CheckSubTreePermission
+ //
+ case RegistryInternalCheck.CheckSubTreePermission:
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ if( subKeyCheck == RegistryKeyPermissionCheck.ReadSubTree) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadPermission(item, out access, out path);
+ }
+ }
+ }
+ else if(subKeyCheck == RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ if( checkMode != RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ }
+ }
+ break;
+
+ //
+ // CheckOpenSubKeyWithWritablePermission uses the 'subKeyWritable' parameter
+ //
+ case RegistryInternalCheck.CheckOpenSubKeyWithWritablePermission:
+ BCLDebug.Assert(subKeyCheck == RegistryKeyPermissionCheck.Default, "subKeyCheck should be Default (unused)");
+ // If the parent key is not opened under default mode, we have access already.
+ // If the parent key is opened under default mode, we need to check for permission.
+ if(checkMode == RegistryKeyPermissionCheck.Default) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ break;
+ }
+ if( subKeyWritable && (checkMode == RegistryKeyPermissionCheck.ReadSubTree)) {
+ if( remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubTreeReadWritePermission(item, out access, out path);
+ }
+ break;
+ }
+ break;
+
+ //
+ // CheckOpenSubKeyPermission uses the 'subKeyCheck' parameter
+ //
+ case RegistryInternalCheck.CheckOpenSubKeyPermission:
+ BCLDebug.Assert(subKeyWritable == false, "subKeyWritable should be false (unused)");
+ if(subKeyCheck == RegistryKeyPermissionCheck.Default) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ if(remoteKey) {
+ CheckUnmanagedCodePermission();
+ }
+ else {
+ demand = true;
+ GetSubKeyReadPermission(item, out access, out path);
+ }
+ }
+ }
+ break;
+
+ default:
+ BCLDebug.Assert(false, "CheckPermission default switch case should never be hit!");
+ break;
+ }
+
+ if (demand) {
+ new RegistryPermission(access, path).Demand();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private void CheckUnmanagedCodePermission() {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool ContainsRegistryValue(string name) {
+ int type = 0;
+ int datasize = 0;
+ int retval = Win32Native.RegQueryValueEx(hkey, name, null, ref type, (byte[])null, ref datasize);
+ return retval == 0;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureNotDisposed(){
+ if (hkey == null) {
+ ThrowHelper.ThrowObjectDisposedException(keyName, ExceptionResource.ObjectDisposed_RegKeyClosed);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureWriteable() {
+ EnsureNotDisposed();
+ if (!IsWritable()) {
+ ThrowHelper.ThrowUnauthorizedAccessException(ExceptionResource.UnauthorizedAccess_RegistryNoWrite);
+ }
+ }
+
+ static int GetRegistryKeyAccess(bool isWritable) {
+ int winAccess;
+ if (!isWritable) {
+ winAccess = Win32Native.KEY_READ;
+ }
+ else {
+ winAccess = Win32Native.KEY_READ | Win32Native.KEY_WRITE;
+ }
+
+ return winAccess;
+ }
+
+ static int GetRegistryKeyAccess(RegistryKeyPermissionCheck mode) {
+ int winAccess = 0;
+ switch(mode) {
+ case RegistryKeyPermissionCheck.ReadSubTree:
+ case RegistryKeyPermissionCheck.Default:
+ winAccess = Win32Native.KEY_READ;
+ break;
+
+ case RegistryKeyPermissionCheck.ReadWriteSubTree:
+ winAccess = Win32Native.KEY_READ| Win32Native.KEY_WRITE;
+ break;
+
+ default:
+ BCLDebug.Assert(false, "unexpected code path");
+ break;
+ }
+
+ return winAccess;
+ }
+
+ private RegistryKeyPermissionCheck GetSubKeyPermissonCheck(bool subkeyWritable) {
+ if( checkMode == RegistryKeyPermissionCheck.Default) {
+ return checkMode;
+ }
+
+ if(subkeyWritable) {
+ return RegistryKeyPermissionCheck.ReadWriteSubTree;
+ }
+ else {
+ return RegistryKeyPermissionCheck.ReadSubTree;
+ }
+ }
+
+ static private void ValidateKeyName(string name) {
+ Contract.Ensures(name != null);
+ if (name == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.name);
+ }
+
+ int nextSlash = name.IndexOf("\\", StringComparison.OrdinalIgnoreCase);
+ int current = 0;
+ while (nextSlash != -1) {
+ if ((nextSlash - current) > MaxKeyLength)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
+
+ current = nextSlash + 1;
+ nextSlash = name.IndexOf("\\", current, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if ((name.Length - current) > MaxKeyLength)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RegKeyStrLenBug);
+
+ }
+
+ static private void ValidateKeyMode(RegistryKeyPermissionCheck mode) {
+ if( mode < RegistryKeyPermissionCheck.Default || mode > RegistryKeyPermissionCheck.ReadWriteSubTree) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryKeyPermissionCheck, ExceptionArgument.mode);
+ }
+ }
+
+ static private void ValidateKeyOptions(RegistryOptions options) {
+ if (options < RegistryOptions.None || options > RegistryOptions.Volatile) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryOptionsCheck, ExceptionArgument.options);
+ }
+ }
+
+ static private void ValidateKeyView(RegistryView view) {
+ if (view != RegistryView.Default && view != RegistryView.Registry32 && view != RegistryView.Registry64) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidRegistryViewCheck, ExceptionArgument.view);
+ }
+ }
+
+
+#if FEATURE_MACL
+ static private void ValidateKeyRights(int rights) {
+ if(0 != (rights & ~((int)RegistryRights.FullControl))) {
+ // We need to throw SecurityException here for compatiblity reason,
+ // although UnauthorizedAccessException will make more sense.
+ ThrowHelper.ThrowSecurityException(ExceptionResource.Security_RegistryPermission);
+ }
+ }
+#endif
+ // Win32 constants for error handling
+ private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+ private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+ private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
+ }
+
+ [Flags]
+ public enum RegistryValueOptions {
+ None = 0,
+ DoNotExpandEnvironmentNames = 1
+ }
+
+ // the name for this API is meant to mimic FileMode, which has similar values
+
+ public enum RegistryKeyPermissionCheck {
+ Default = 0,
+ ReadSubTree = 1,
+ ReadWriteSubTree = 2
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs b/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs
new file mode 100644
index 0000000000..4d5e3aaab1
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryOptions.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.RegistryOptions
+//
+// ======================================================================================
+namespace Microsoft.Win32 {
+ using System;
+
+ [Flags]
+ public enum RegistryOptions {
+ None = Win32Native.REG_OPTION_NON_VOLATILE, // 0x0000
+ Volatile = Win32Native.REG_OPTION_VOLATILE, // 0x0001
+///
+/// Consider exposing more options in a future release. Users can access this
+/// functionality by calling [RegistryKey].Handle and pinvoking
+///
+/// CreateLink = Win32Native.REG_OPTION_CREATE_LINK, // 0x0002
+/// BackupRestore = Win32Native.REG_OPTION_BACKUP_RESTORE,// 0x0004
+ };
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs b/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs
new file mode 100644
index 0000000000..c88d5f920a
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryValueKind.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace Microsoft.Win32 {
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum RegistryValueKind {
+ String = Win32Native.REG_SZ,
+ ExpandString = Win32Native.REG_EXPAND_SZ,
+ Binary = Win32Native.REG_BINARY,
+ DWord = Win32Native.REG_DWORD,
+ MultiString = Win32Native.REG_MULTI_SZ,
+ QWord = Win32Native.REG_QWORD,
+ Unknown = 0, // REG_NONE is defined as zero but BCL
+ [System.Runtime.InteropServices.ComVisible(false)]
+ None = unchecked((int)0xFFFFFFFF), // mistakingly overrode this value.
+ } // Now instead of using Win32Native.REG_NONE we use "-1" and play games internally.
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/RegistryView.cs b/src/mscorlib/src/Microsoft/Win32/RegistryView.cs
new file mode 100644
index 0000000000..7fbc2b3391
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/RegistryView.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.RegistryView
+//
+// ======================================================================================
+namespace Microsoft.Win32 {
+ using System;
+
+ public enum RegistryView {
+ Default = 0, // 0x0000 operate on the default registry view
+ Registry64 = Win32Native.KEY_WOW64_64KEY, // 0x0100 operate on the 64-bit registry view
+ Registry32 = Win32Native.KEY_WOW64_32KEY, // 0x0200 operate on the 32-bit registry view
+ };
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs
new file mode 100644
index 0000000000..ab06347ee4
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileHandle.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+
+namespace Microsoft.Win32.SafeHandles {
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public sealed class SafeFileHandle: SafeHandleZeroOrMinusOneIsInvalid {
+
+ private SafeFileHandle() : base(true)
+ {
+ }
+
+ public SafeFileHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) {
+ SetHandle(preexistingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs
new file mode 100644
index 0000000000..5e1b5100bc
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFileMappingHandle.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeFileMappingHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFileMappingHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFileMappingHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle)
+ {
+ SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs
new file mode 100644
index 0000000000..b24535f997
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeFindHandle.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for find handles
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using Microsoft.Win32;
+
+namespace Microsoft.Win32.SafeHandles {
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeFindHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeFindHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.FindClose(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
new file mode 100644
index 0000000000..d2ea42b14e
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLibraryHandle.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32 {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [HostProtectionAttribute(MayLeakOnAbort = true)]
+ sealed internal class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ internal SafeLibraryHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return UnsafeNativeMethods.FreeLibrary(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs
new file mode 100644
index 0000000000..3eea2b9937
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeLocalAllocHandle.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace Microsoft.Win32.SafeHandles {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLocalAllocHandle : SafeBuffer {
+ private SafeLocalAllocHandle () : base(true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLocalAllocHandle (IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLocalAllocHandle InvalidHandle {
+ get { return new SafeLocalAllocHandle(IntPtr.Zero); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.LocalFree(handle) == IntPtr.Zero;
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
new file mode 100644
index 0000000000..d0e3f048f2
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeRegistryHandle.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements Microsoft.Win32.SafeHandles.SafeRegistryHandle
+//
+// ======================================================================================
+namespace Microsoft.Win32.SafeHandles {
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+
+ [System.Security.SecurityCritical]
+ public sealed class SafeRegistryHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ [System.Security.SecurityCritical]
+ internal SafeRegistryHandle() : base(true) {}
+
+ [System.Security.SecurityCritical]
+ public SafeRegistryHandle(IntPtr preexistingHandle, bool ownsHandle) : base(ownsHandle) {
+ SetHandle(preexistingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle() {
+ return (RegCloseKey(handle) == Win32Native.ERROR_SUCCESS);
+ }
+
+ [DllImport(Win32Native.ADVAPI32)]
+ [SuppressUnmanagedCodeSecurity]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int RegCloseKey(IntPtr hKey);
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs
new file mode 100644
index 0000000000..01ec4d2ad8
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeViewOfFileHandle.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for file handles
+**
+**
+===========================================================*/
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace Microsoft.Win32.SafeHandles
+{
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeViewOfFileHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeViewOfFileHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal SafeViewOfFileHandle(IntPtr handle, bool ownsHandle) : base (ownsHandle) {
+ SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ if (Win32Native.UnmapViewOfFile(handle))
+ {
+ handle = IntPtr.Zero;
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
new file mode 100644
index 0000000000..fa24c96718
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/SafeWaitHandle.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A wrapper for Win32 events (mutexes, auto reset events, and
+** manual reset events). Used by WaitHandle.
+**
+**
+===========================================================*/
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using System.Threading;
+
+namespace Microsoft.Win32.SafeHandles {
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public sealed class SafeWaitHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ // Called by P/Invoke marshaler
+ private SafeWaitHandle() : base(true)
+ {
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public SafeWaitHandle(IntPtr existingHandle, bool ownsHandle) : base(ownsHandle)
+ {
+ SetHandle(existingHandle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs
new file mode 100644
index 0000000000..58e0d7ad1d
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/SafeHandles/Win32SafeHandles.cs
@@ -0,0 +1,112 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Abstract derivations of SafeHandle designed to provide the common
+// functionality supporting Win32 handles. More specifically, they describe how
+// an invalid handle looks (for instance, some handles use -1 as an invalid
+// handle value, others use 0).
+//
+// Further derivations of these classes can specialise this even further (e.g.
+// file or registry handles).
+//
+//
+
+namespace Microsoft.Win32.SafeHandles
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Runtime.ConstrainedExecution;
+
+ // Class of safe handle which uses 0 or -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class SafeHandleZeroOrMinusOneIsInvalid : SafeHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
+ {
+ }
+
+#if FEATURE_CORECLR
+ // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime
+ protected SafeHandleZeroOrMinusOneIsInvalid()
+ {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_CORECLR
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle.IsNull() || handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of safe handle which uses only -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class SafeHandleMinusOneIsInvalid : SafeHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected SafeHandleMinusOneIsInvalid(bool ownsHandle) : base(new IntPtr(-1), ownsHandle)
+ {
+ }
+
+#if FEATURE_CORECLR
+ // A default constructor is needed to satisfy CoreCLR inheritence rules. It should not be called at runtime
+ protected SafeHandleMinusOneIsInvalid()
+ {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_CORECLR
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of critical handle which uses 0 or -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class CriticalHandleZeroOrMinusOneIsInvalid : CriticalHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalHandleZeroOrMinusOneIsInvalid() : base(IntPtr.Zero)
+ {
+ }
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle.IsNull() || handle == new IntPtr(-1); }
+ }
+ }
+
+ // Class of critical handle which uses only -1 as an invalid handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ public abstract class CriticalHandleMinusOneIsInvalid : CriticalHandle
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalHandleMinusOneIsInvalid() : base(new IntPtr(-1))
+ {
+ }
+
+ public override bool IsInvalid {
+ [System.Security.SecurityCritical]
+ get { return handle == new IntPtr(-1); }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs
new file mode 100644
index 0000000000..9da9811ee8
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/UnsafeNativeMethods.cs
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.Win32 {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Diagnostics.Tracing;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class UnsafeNativeMethods {
+
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
+ internal static extern int GetTimeZoneInformation(out Win32Native.TimeZoneInformation lpTimeZoneInformation);
+
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetDynamicTimeZoneInformation", SetLastError = true, ExactSpelling = true)]
+ internal static extern int GetDynamicTimeZoneInformation(out Win32Native.DynamicTimeZoneInformation lpDynamicTimeZoneInformation);
+
+ //
+ // BOOL GetFileMUIPath(
+ // DWORD dwFlags,
+ // PCWSTR pcwszFilePath,
+ // PWSTR pwszLanguage,
+ // PULONG pcchLanguage,
+ // PWSTR pwszFileMUIPath,
+ // PULONG pcchFileMUIPath,
+ // PULONGLONG pululEnumerator
+ // );
+ //
+ [DllImport(Win32Native.KERNEL32, EntryPoint="GetFileMUIPath", SetLastError = true, ExactSpelling = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetFileMUIPath(
+ int flags,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ String filePath,
+ [MarshalAs(UnmanagedType.LPWStr)]
+ StringBuilder language,
+ ref int languageLength,
+ [Out, MarshalAs(UnmanagedType.LPWStr)]
+ StringBuilder fileMuiPath,
+ ref int fileMuiPathLength,
+ ref Int64 enumerator);
+
+
+ [DllImport(Win32Native.USER32, EntryPoint="LoadStringW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
+ internal static extern int LoadString(SafeLibraryHandle handle, int id, [Out] StringBuilder buffer, int bufferLength);
+
+ [DllImport(Win32Native.KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Unicode, SetLastError=true)]
+ internal static extern SafeLibraryHandle LoadLibraryEx(string libFilename, IntPtr reserved, int flags);
+
+ [DllImport(Win32Native.KERNEL32, CharSet=System.Runtime.InteropServices.CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool FreeLibrary(IntPtr hModule);
+
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static unsafe class ManifestEtw
+ {
+ //
+ // Constants error coded returned by ETW APIs
+ //
+
+ // The event size is larger than the allowed maximum (64k - header).
+ internal const int ERROR_ARITHMETIC_OVERFLOW = 534;
+
+ // Occurs when filled buffers are trying to flush to disk,
+ // but disk IOs are not happening fast enough.
+ // This happens when the disk is slow and event traffic is heavy.
+ // Eventually, there are no more free (empty) buffers and the event is dropped.
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 8;
+
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_NOT_SUPPORTED = 50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57;
+
+ //
+ // ETW Methods
+ //
+
+ internal const int EVENT_CONTROL_CODE_DISABLE_PROVIDER = 0;
+ internal const int EVENT_CONTROL_CODE_ENABLE_PROVIDER = 1;
+ internal const int EVENT_CONTROL_CODE_CAPTURE_STATE = 2;
+
+ //
+ // Callback
+ //
+ [SecurityCritical]
+ internal unsafe delegate void EtwEnableCallback(
+ [In] ref Guid sourceId,
+ [In] int isEnabled,
+ [In] byte level,
+ [In] long matchAnyKeywords,
+ [In] long matchAllKeywords,
+ [In] EVENT_FILTER_DESCRIPTOR* filterData,
+ [In] void* callbackContext
+ );
+
+ //
+ // Registration APIs
+ //
+ [SecurityCritical]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventRegister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe uint EventRegister(
+ [In] ref Guid providerId,
+ [In]EtwEnableCallback enableCallback,
+ [In]void* callbackContext,
+ [In][Out]ref long registrationHandle
+ );
+
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventUnregister", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern uint EventUnregister([In] long registrationHandle);
+
+ //
+ // Writing (Publishing/Logging) APIs
+ //
+ //
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWrite", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWrite(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ [SecurityCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteString", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ internal static extern unsafe int EventWriteString(
+ [In] long registrationHandle,
+ [In] byte level,
+ [In] long keyword,
+ [In] string msg
+ );
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe internal struct EVENT_FILTER_DESCRIPTOR
+ {
+ public long Ptr;
+ public int Size;
+ public int Type;
+ };
+
+ /// <summary>
+ /// Call the ETW native API EventWriteTransfer and checks for invalid argument error.
+ /// The implementation of EventWriteTransfer on some older OSes (Windows 2008) does not accept null relatedActivityId.
+ /// So, for these cases we will retry the call with an empty Guid.
+ /// </summary>
+ internal static int EventWriteTransferWrapper(long registrationHandle,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityId,
+ Guid* relatedActivityId,
+ int userDataCount,
+ EventProvider.EventData* userData)
+ {
+ int HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, relatedActivityId, userDataCount, userData);
+ if (HResult == ERROR_INVALID_PARAMETER && relatedActivityId == null)
+ {
+ Guid emptyGuid = Guid.Empty;
+ HResult = EventWriteTransfer(registrationHandle, ref eventDescriptor, activityId, &emptyGuid, userDataCount, userData);
+ }
+
+ return HResult;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventWriteTransfer", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ private static extern int EventWriteTransfer(
+ [In] long registrationHandle,
+ [In] ref EventDescriptor eventDescriptor,
+ [In] Guid* activityId,
+ [In] Guid* relatedActivityId,
+ [In] int userDataCount,
+ [In] EventProvider.EventData* userData
+ );
+
+ internal enum ActivityControl : uint
+ {
+ EVENT_ACTIVITY_CTRL_GET_ID = 1,
+ EVENT_ACTIVITY_CTRL_SET_ID = 2,
+ EVENT_ACTIVITY_CTRL_CREATE_ID = 3,
+ EVENT_ACTIVITY_CTRL_GET_SET_ID = 4,
+ EVENT_ACTIVITY_CTRL_CREATE_SET_ID = 5
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventActivityIdControl", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventActivityIdControl([In] ActivityControl ControlCode, [In][Out] ref Guid ActivityId);
+
+ internal enum EVENT_INFO_CLASS
+ {
+ BinaryTrackInfo,
+ SetEnableAllKeywords,
+ SetTraits,
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EventSetInformation", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EventSetInformation(
+ [In] long registrationHandle,
+ [In] EVENT_INFO_CLASS informationClass,
+ [In] void* eventInformation,
+ [In] int informationLength);
+
+ // Support for EnumerateTraceGuidsEx
+ internal enum TRACE_QUERY_INFO_CLASS
+ {
+ TraceGuidQueryList,
+ TraceGuidQueryInfo,
+ TraceGuidQueryProcess,
+ TraceStackTracingInfo,
+ MaxTraceSetInfoClass
+ };
+
+ internal struct TRACE_GUID_INFO
+ {
+ public int InstanceCount;
+ public int Reserved;
+ };
+
+ internal struct TRACE_PROVIDER_INSTANCE_INFO
+ {
+ public int NextOffset;
+ public int EnableCount;
+ public int Pid;
+ public int Flags;
+ };
+
+ internal struct TRACE_ENABLE_INFO
+ {
+ public int IsEnabled;
+ public byte Level;
+ public byte Reserved1;
+ public ushort LoggerId;
+ public int EnableProperty;
+ public int Reserved2;
+ public long MatchAnyKeyword;
+ public long MatchAllKeyword;
+ };
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage")]
+ [DllImport(Win32Native.ADVAPI32, ExactSpelling = true, EntryPoint = "EnumerateTraceGuidsEx", CharSet = System.Runtime.InteropServices.CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute] // Don't do security checks
+ internal static extern int EnumerateTraceGuidsEx(
+ TRACE_QUERY_INFO_CLASS TraceQueryInfoClass,
+ void* InBuffer,
+ int InBufferSize,
+ void* OutBuffer,
+ int OutBufferSize,
+ ref int ReturnLength);
+
+ }
+#if FEATURE_COMINTEROP
+ [SecurityCritical]
+ [DllImport("combase.dll", PreserveSig = true)]
+ internal static extern int RoGetActivationFactory(
+ [MarshalAs(UnmanagedType.HString)] string activatableClassId,
+ [In] ref Guid iid,
+ [Out,MarshalAs(UnmanagedType.IInspectable)] out Object factory);
+#endif
+
+ }
+}
diff --git a/src/mscorlib/src/Microsoft/Win32/Win32Native.cs b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs
new file mode 100644
index 0000000000..ebe53f45af
--- /dev/null
+++ b/src/mscorlib/src/Microsoft/Win32/Win32Native.cs
@@ -0,0 +1,2455 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The CLR wrapper for all Win32 as well as
+** ROTOR-style Unix PAL, etc. native operations
+**
+**
+===========================================================*/
+/**
+ * Notes to PInvoke users: Getting the syntax exactly correct is crucial, and
+ * more than a little confusing. Here's some guidelines.
+ *
+ * For handles, you should use a SafeHandle subclass specific to your handle
+ * type. For files, we have the following set of interesting definitions:
+ *
+ * [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ * private static extern SafeFileHandle CreateFile(...);
+ *
+ * [DllImport(KERNEL32, SetLastError=true)]
+ * unsafe internal static extern int ReadFile(SafeFileHandle handle, ...);
+ *
+ * [DllImport(KERNEL32, SetLastError=true)]
+ * internal static extern bool CloseHandle(IntPtr handle);
+ *
+ * P/Invoke will create the SafeFileHandle instance for you and assign the
+ * return value from CreateFile into the handle atomically. When we call
+ * ReadFile, P/Invoke will increment a ref count, make the call, then decrement
+ * it (preventing handle recycling vulnerabilities). Then SafeFileHandle's
+ * ReleaseHandle method will call CloseHandle, passing in the handle field
+ * as an IntPtr.
+ *
+ * If for some reason you cannot use a SafeHandle subclass for your handles,
+ * then use IntPtr as the handle type (or possibly HandleRef - understand when
+ * to use GC.KeepAlive). If your code will run in SQL Server (or any other
+ * long-running process that can't be recycled easily), use a constrained
+ * execution region to prevent thread aborts while allocating your
+ * handle, and consider making your handle wrapper subclass
+ * CriticalFinalizerObject to ensure you can free the handle. As you can
+ * probably guess, SafeHandle will save you a lot of headaches if your code
+ * needs to be robust to thread aborts and OOM.
+ *
+ *
+ * If you have a method that takes a native struct, you have two options for
+ * declaring that struct. You can make it a value type ('struct' in CSharp),
+ * or a reference type ('class'). This choice doesn't seem very interesting,
+ * but your function prototype must use different syntax depending on your
+ * choice. For example, if your native method is prototyped as such:
+ *
+ * bool GetVersionEx(OSVERSIONINFO & lposvi);
+ *
+ *
+ * you must use EITHER THIS OR THE NEXT syntax:
+ *
+ * [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ * internal struct OSVERSIONINFO { ... }
+ *
+ * [DllImport(KERNEL32, CharSet=CharSet.Auto)]
+ * internal static extern bool GetVersionEx(ref OSVERSIONINFO lposvi);
+ *
+ * OR:
+ *
+ * [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ * internal class OSVERSIONINFO { ... }
+ *
+ * [DllImport(KERNEL32, CharSet=CharSet.Auto)]
+ * internal static extern bool GetVersionEx([In, Out] OSVERSIONINFO lposvi);
+ *
+ * Note that classes require being marked as [In, Out] while value types must
+ * be passed as ref parameters.
+ *
+ * Also note the CharSet.Auto on GetVersionEx - while it does not take a String
+ * as a parameter, the OSVERSIONINFO contains an embedded array of TCHARs, so
+ * the size of the struct varies on different platforms, and there's a
+ * GetVersionExA & a GetVersionExW. Also, the OSVERSIONINFO struct has a sizeof
+ * field so the OS can ensure you've passed in the correctly-sized copy of an
+ * OSVERSIONINFO. You must explicitly set this using Marshal.SizeOf(Object);
+ *
+ * For security reasons, if you're making a P/Invoke method to a Win32 method
+ * that takes an ANSI String and that String is the name of some resource you've
+ * done a security check on (such as a file name), you want to disable best fit
+ * mapping in WideCharToMultiByte. Do this by setting BestFitMapping=false
+ * in your DllImportAttribute.
+ */
+
+namespace Microsoft.Win32 {
+ using System;
+ using System.Security;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Text;
+ using System.Configuration.Assemblies;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+
+ using BOOL = System.Int32;
+ using DWORD = System.UInt32;
+ using ULONG = System.UInt32;
+
+ /**
+ * Win32 encapsulation for MSCORLIB.
+ */
+ // Remove the default demands for all P/Invoke methods with this
+ // global declaration on the class.
+
+ [System.Security.SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class Win32Native {
+
+ internal const int KEY_QUERY_VALUE = 0x0001;
+ internal const int KEY_SET_VALUE = 0x0002;
+ internal const int KEY_CREATE_SUB_KEY = 0x0004;
+ internal const int KEY_ENUMERATE_SUB_KEYS = 0x0008;
+ internal const int KEY_NOTIFY = 0x0010;
+ internal const int KEY_CREATE_LINK = 0x0020;
+ internal const int KEY_READ =((STANDARD_RIGHTS_READ |
+ KEY_QUERY_VALUE |
+ KEY_ENUMERATE_SUB_KEYS |
+ KEY_NOTIFY)
+ &
+ (~SYNCHRONIZE));
+
+ internal const int KEY_WRITE =((STANDARD_RIGHTS_WRITE |
+ KEY_SET_VALUE |
+ KEY_CREATE_SUB_KEY)
+ &
+ (~SYNCHRONIZE));
+ internal const int KEY_WOW64_64KEY = 0x0100; //
+ internal const int KEY_WOW64_32KEY = 0x0200; //
+ internal const int REG_OPTION_NON_VOLATILE= 0x0000; // (default) keys are persisted beyond reboot/unload
+ internal const int REG_OPTION_VOLATILE = 0x0001; // All keys created by the function are volatile
+ internal const int REG_OPTION_CREATE_LINK = 0x0002; // They key is a symbolic link
+ internal const int REG_OPTION_BACKUP_RESTORE = 0x0004; // Use SE_BACKUP_NAME process special privileges
+ internal const int REG_NONE = 0; // No value type
+ internal const int REG_SZ = 1; // Unicode nul terminated string
+ internal const int REG_EXPAND_SZ = 2; // Unicode nul terminated string
+ // (with environment variable references)
+ internal const int REG_BINARY = 3; // Free form binary
+ internal const int REG_DWORD = 4; // 32-bit number
+ internal const int REG_DWORD_LITTLE_ENDIAN = 4; // 32-bit number (same as REG_DWORD)
+ internal const int REG_DWORD_BIG_ENDIAN = 5; // 32-bit number
+ internal const int REG_LINK = 6; // Symbolic Link (unicode)
+ internal const int REG_MULTI_SZ = 7; // Multiple Unicode strings
+ internal const int REG_RESOURCE_LIST = 8; // Resource list in the resource map
+ internal const int REG_FULL_RESOURCE_DESCRIPTOR = 9; // Resource list in the hardware description
+ internal const int REG_RESOURCE_REQUIREMENTS_LIST = 10;
+ internal const int REG_QWORD = 11; // 64-bit number
+
+ internal const int HWND_BROADCAST = 0xffff;
+ internal const int WM_SETTINGCHANGE = 0x001A;
+
+ // CryptProtectMemory and CryptUnprotectMemory.
+ internal const uint CRYPTPROTECTMEMORY_BLOCK_SIZE = 16;
+ internal const uint CRYPTPROTECTMEMORY_SAME_PROCESS = 0x00;
+ internal const uint CRYPTPROTECTMEMORY_CROSS_PROCESS = 0x01;
+ internal const uint CRYPTPROTECTMEMORY_SAME_LOGON = 0x02;
+
+ // Security Quality of Service flags
+ internal const int SECURITY_ANONYMOUS = ((int)SECURITY_IMPERSONATION_LEVEL.Anonymous << 16);
+ internal const int SECURITY_SQOS_PRESENT = 0x00100000;
+
+ // Access Control library.
+ internal const string MICROSOFT_KERBEROS_NAME = "Kerberos";
+ internal const uint ANONYMOUS_LOGON_LUID = 0x3e6;
+
+ internal const int SECURITY_ANONYMOUS_LOGON_RID = 0x00000007;
+ internal const int SECURITY_AUTHENTICATED_USER_RID = 0x0000000B;
+ internal const int SECURITY_LOCAL_SYSTEM_RID = 0x00000012;
+ internal const int SECURITY_BUILTIN_DOMAIN_RID = 0x00000020;
+
+ internal const uint SE_PRIVILEGE_DISABLED = 0x00000000;
+ internal const uint SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001;
+ internal const uint SE_PRIVILEGE_ENABLED = 0x00000002;
+ internal const uint SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000;
+
+ internal const uint SE_GROUP_MANDATORY = 0x00000001;
+ internal const uint SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002;
+ internal const uint SE_GROUP_ENABLED = 0x00000004;
+ internal const uint SE_GROUP_OWNER = 0x00000008;
+ internal const uint SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010;
+ internal const uint SE_GROUP_LOGON_ID = 0xC0000000;
+ internal const uint SE_GROUP_RESOURCE = 0x20000000;
+
+ internal const uint DUPLICATE_CLOSE_SOURCE = 0x00000001;
+ internal const uint DUPLICATE_SAME_ACCESS = 0x00000002;
+ internal const uint DUPLICATE_SAME_ATTRIBUTES = 0x00000004;
+
+ // TimeZone
+ internal const int TIME_ZONE_ID_INVALID = -1;
+ internal const int TIME_ZONE_ID_UNKNOWN = 0;
+ internal const int TIME_ZONE_ID_STANDARD = 1;
+ internal const int TIME_ZONE_ID_DAYLIGHT = 2;
+ internal const int MAX_PATH = 260;
+
+ internal const int MUI_LANGUAGE_ID = 0x4;
+ internal const int MUI_LANGUAGE_NAME = 0x8;
+ internal const int MUI_PREFERRED_UI_LANGUAGES = 0x10;
+ internal const int MUI_INSTALLED_LANGUAGES = 0x20;
+ internal const int MUI_ALL_LANGUAGES = 0x40;
+ internal const int MUI_LANG_NEUTRAL_PE_FILE = 0x100;
+ internal const int MUI_NON_LANG_NEUTRAL_FILE = 0x200;
+
+ internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
+ internal const int LOAD_STRING_MAX_LENGTH = 500;
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SystemTime {
+ [MarshalAs(UnmanagedType.U2)]
+ public short Year;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Month;
+ [MarshalAs(UnmanagedType.U2)]
+ public short DayOfWeek;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Day;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Hour;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Minute;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Second;
+ [MarshalAs(UnmanagedType.U2)]
+ public short Milliseconds;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct TimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string StandardName;
+ public SystemTime StandardDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string DaylightName;
+ public SystemTime DaylightDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+
+ public TimeZoneInformation(Win32Native.DynamicTimeZoneInformation dtzi) {
+ Bias = dtzi.Bias;
+ StandardName = dtzi.StandardName;
+ StandardDate = dtzi.StandardDate;
+ StandardBias = dtzi.StandardBias;
+ DaylightName = dtzi.DaylightName;
+ DaylightDate = dtzi.DaylightDate;
+ DaylightBias = dtzi.DaylightBias;
+ }
+ }
+
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct DynamicTimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string StandardName;
+ public SystemTime StandardDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string DaylightName;
+ public SystemTime DaylightDate;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string TimeZoneKeyName;
+ [MarshalAs(UnmanagedType.Bool)]
+ public bool DynamicDaylightTimeDisabled;
+ }
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct RegistryTimeZoneInformation {
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 Bias;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 StandardBias;
+ [MarshalAs(UnmanagedType.I4)]
+ public Int32 DaylightBias;
+ public SystemTime StandardDate;
+ public SystemTime DaylightDate;
+
+ public RegistryTimeZoneInformation(Win32Native.TimeZoneInformation tzi) {
+ Bias = tzi.Bias;
+ StandardDate = tzi.StandardDate;
+ StandardBias = tzi.StandardBias;
+ DaylightDate = tzi.DaylightDate;
+ DaylightBias = tzi.DaylightBias;
+ }
+
+ public RegistryTimeZoneInformation(Byte[] bytes) {
+ //
+ // typedef struct _REG_TZI_FORMAT {
+ // [00-03] LONG Bias;
+ // [04-07] LONG StandardBias;
+ // [08-11] LONG DaylightBias;
+ // [12-27] SYSTEMTIME StandardDate;
+ // [12-13] WORD wYear;
+ // [14-15] WORD wMonth;
+ // [16-17] WORD wDayOfWeek;
+ // [18-19] WORD wDay;
+ // [20-21] WORD wHour;
+ // [22-23] WORD wMinute;
+ // [24-25] WORD wSecond;
+ // [26-27] WORD wMilliseconds;
+ // [28-43] SYSTEMTIME DaylightDate;
+ // [28-29] WORD wYear;
+ // [30-31] WORD wMonth;
+ // [32-33] WORD wDayOfWeek;
+ // [34-35] WORD wDay;
+ // [36-37] WORD wHour;
+ // [38-39] WORD wMinute;
+ // [40-41] WORD wSecond;
+ // [42-43] WORD wMilliseconds;
+ // } REG_TZI_FORMAT;
+ //
+ if (bytes == null || bytes.Length != 44) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidREG_TZI_FORMAT"), "bytes");
+ }
+ Bias = BitConverter.ToInt32(bytes, 0);
+ StandardBias = BitConverter.ToInt32(bytes, 4);
+ DaylightBias = BitConverter.ToInt32(bytes, 8);
+
+ StandardDate.Year = BitConverter.ToInt16(bytes, 12);
+ StandardDate.Month = BitConverter.ToInt16(bytes, 14);
+ StandardDate.DayOfWeek = BitConverter.ToInt16(bytes, 16);
+ StandardDate.Day = BitConverter.ToInt16(bytes, 18);
+ StandardDate.Hour = BitConverter.ToInt16(bytes, 20);
+ StandardDate.Minute = BitConverter.ToInt16(bytes, 22);
+ StandardDate.Second = BitConverter.ToInt16(bytes, 24);
+ StandardDate.Milliseconds = BitConverter.ToInt16(bytes, 26);
+
+ DaylightDate.Year = BitConverter.ToInt16(bytes, 28);
+ DaylightDate.Month = BitConverter.ToInt16(bytes, 30);
+ DaylightDate.DayOfWeek = BitConverter.ToInt16(bytes, 32);
+ DaylightDate.Day = BitConverter.ToInt16(bytes, 34);
+ DaylightDate.Hour = BitConverter.ToInt16(bytes, 36);
+ DaylightDate.Minute = BitConverter.ToInt16(bytes, 38);
+ DaylightDate.Second = BitConverter.ToInt16(bytes, 40);
+ DaylightDate.Milliseconds = BitConverter.ToInt16(bytes, 42);
+ }
+ }
+
+ // end of TimeZone
+
+
+ // Win32 ACL-related constants:
+ internal const int READ_CONTROL = 0x00020000;
+ internal const int SYNCHRONIZE = 0x00100000;
+
+ internal const int STANDARD_RIGHTS_READ = READ_CONTROL;
+ internal const int STANDARD_RIGHTS_WRITE = READ_CONTROL;
+
+ // STANDARD_RIGHTS_REQUIRED (0x000F0000L)
+ // SEMAPHORE_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+
+ // SEMAPHORE and Event both use 0x0002
+ // MUTEX uses 0x001 (MUTANT_QUERY_STATE)
+
+ // Note that you may need to specify the SYNCHRONIZE bit as well
+ // to be able to open a synchronization primitive.
+ internal const int SEMAPHORE_MODIFY_STATE = 0x00000002;
+ internal const int EVENT_MODIFY_STATE = 0x00000002;
+ internal const int MUTEX_MODIFY_STATE = 0x00000001;
+ internal const int MUTEX_ALL_ACCESS = 0x001F0001;
+
+
+ internal const int LMEM_FIXED = 0x0000;
+ internal const int LMEM_ZEROINIT = 0x0040;
+ internal const int LPTR = (LMEM_FIXED | LMEM_ZEROINIT);
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal class OSVERSIONINFO {
+ internal OSVERSIONINFO() {
+ OSVersionInfoSize = (int)Marshal.SizeOf(this);
+ }
+
+ // The OSVersionInfoSize field must be set to Marshal.SizeOf(this)
+ internal int OSVersionInfoSize = 0;
+ internal int MajorVersion = 0;
+ internal int MinorVersion = 0;
+ internal int BuildNumber = 0;
+ internal int PlatformId = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
+ internal String CSDVersion = null;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal class OSVERSIONINFOEX {
+
+ public OSVERSIONINFOEX() {
+ OSVersionInfoSize = (int)Marshal.SizeOf(this);
+ }
+
+ // The OSVersionInfoSize field must be set to Marshal.SizeOf(this)
+ internal int OSVersionInfoSize = 0;
+ internal int MajorVersion = 0;
+ internal int MinorVersion = 0;
+ internal int BuildNumber = 0;
+ internal int PlatformId = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)]
+ internal string CSDVersion = null;
+ internal ushort ServicePackMajor = 0;
+ internal ushort ServicePackMinor = 0;
+ internal short SuiteMask = 0;
+ internal byte ProductType = 0;
+ internal byte Reserved = 0;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SYSTEM_INFO {
+ internal int dwOemId; // This is a union of a DWORD and a struct containing 2 WORDs.
+ internal int dwPageSize;
+ internal IntPtr lpMinimumApplicationAddress;
+ internal IntPtr lpMaximumApplicationAddress;
+ internal IntPtr dwActiveProcessorMask;
+ internal int dwNumberOfProcessors;
+ internal int dwProcessorType;
+ internal int dwAllocationGranularity;
+ internal short wProcessorLevel;
+ internal short wProcessorRevision;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class SECURITY_ATTRIBUTES {
+ internal int nLength = 0;
+ // don't remove null, or this field will disappear in bcl.small
+ internal unsafe byte * pSecurityDescriptor = null;
+ internal int bInheritHandle = 0;
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct WIN32_FILE_ATTRIBUTE_DATA {
+ internal int fileAttributes;
+ internal uint ftCreationTimeLow;
+ internal uint ftCreationTimeHigh;
+ internal uint ftLastAccessTimeLow;
+ internal uint ftLastAccessTimeHigh;
+ internal uint ftLastWriteTimeLow;
+ internal uint ftLastWriteTimeHigh;
+ internal int fileSizeHigh;
+ internal int fileSizeLow;
+
+ [System.Security.SecurityCritical]
+ internal void PopulateFrom(WIN32_FIND_DATA findData) {
+ // Copy the information to data
+ fileAttributes = findData.dwFileAttributes;
+ ftCreationTimeLow = findData.ftCreationTime_dwLowDateTime;
+ ftCreationTimeHigh = findData.ftCreationTime_dwHighDateTime;
+ ftLastAccessTimeLow = findData.ftLastAccessTime_dwLowDateTime;
+ ftLastAccessTimeHigh = findData.ftLastAccessTime_dwHighDateTime;
+ ftLastWriteTimeLow = findData.ftLastWriteTime_dwLowDateTime;
+ ftLastWriteTimeHigh = findData.ftLastWriteTime_dwHighDateTime;
+ fileSizeHigh = findData.nFileSizeHigh;
+ fileSizeLow = findData.nFileSizeLow;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct FILE_TIME {
+ public FILE_TIME(long fileTime) {
+ ftTimeLow = (uint) fileTime;
+ ftTimeHigh = (uint) (fileTime >> 32);
+ }
+
+ public long ToTicks() {
+ return ((long) ftTimeHigh << 32) + ftTimeLow;
+ }
+
+ internal uint ftTimeLow;
+ internal uint ftTimeHigh;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct KERB_S4U_LOGON {
+ internal uint MessageType;
+ internal uint Flags;
+ internal UNICODE_INTPTR_STRING ClientUpn; // REQUIRED: UPN for client
+ internal UNICODE_INTPTR_STRING ClientRealm; // Optional: Client Realm, if known
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_OBJECT_ATTRIBUTES {
+ internal int Length;
+ internal IntPtr RootDirectory;
+ internal IntPtr ObjectName;
+ internal int Attributes;
+ internal IntPtr SecurityDescriptor;
+ internal IntPtr SecurityQualityOfService;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct UNICODE_STRING {
+ internal ushort Length;
+ internal ushort MaximumLength;
+ [MarshalAs(UnmanagedType.LPWStr)] internal string Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct UNICODE_INTPTR_STRING {
+ /// <remarks>
+ /// Note - this constructor extracts the raw pointer from the safe handle, so any
+ /// strings created with this version of the constructor will be unsafe to use after the buffer
+ /// has been freed.
+ /// </remarks>
+ [System.Security.SecurityCritical] // auto-generated
+ internal UNICODE_INTPTR_STRING (int stringBytes, SafeLocalAllocHandle buffer) {
+ BCLDebug.Assert(buffer == null || (stringBytes >= 0 && (ulong)stringBytes <= buffer.ByteLength),
+ "buffer == null || (stringBytes >= 0 && stringBytes <= buffer.ByteLength)");
+
+ this.Length = (ushort) stringBytes;
+ this.MaxLength = (ushort) buffer.ByteLength;
+
+ // Marshaling with a SafePointer does not work correctly, so unfortunately we need to extract
+ // the raw handle here.
+ this.Buffer = buffer.DangerousGetHandle();
+ }
+
+ /// <remarks>
+ /// This constructor should be used for constructing UNICODE_STRING structures with pointers
+ /// into a block of memory managed by a SafeHandle or the GC. It shouldn't be used to own
+ /// any memory on its own.
+ /// </remarks>
+ internal UNICODE_INTPTR_STRING(int stringBytes, IntPtr buffer) {
+ BCLDebug.Assert((stringBytes == 0 && buffer == IntPtr.Zero) || (stringBytes > 0 && stringBytes <= UInt16.MaxValue && buffer != IntPtr.Zero),
+ "(stringBytes == 0 && buffer == IntPtr.Zero) || (stringBytes > 0 && stringBytes <= UInt16.MaxValue && buffer != IntPtr.Zero)");
+
+ this.Length = (ushort)stringBytes;
+ this.MaxLength = (ushort)stringBytes;
+ this.Buffer = buffer;
+ }
+
+ internal ushort Length;
+ internal ushort MaxLength;
+ internal IntPtr Buffer;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_NAME {
+ internal int Use;
+ internal UNICODE_INTPTR_STRING Name;
+ internal int DomainIndex;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_SID {
+ internal int Use;
+ internal uint Rid;
+ internal int DomainIndex;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct LSA_TRANSLATED_SID2 {
+ internal int Use;
+ internal IntPtr Sid;
+ internal int DomainIndex;
+ uint Flags;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_TRUST_INFORMATION {
+ internal UNICODE_INTPTR_STRING Name;
+ internal IntPtr Sid;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct LSA_REFERENCED_DOMAIN_LIST {
+ internal int Entries;
+ internal IntPtr Domains;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct LUID {
+ internal uint LowPart;
+ internal uint HighPart;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct LUID_AND_ATTRIBUTES {
+ internal LUID Luid;
+ internal uint Attributes;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct QUOTA_LIMITS {
+ internal IntPtr PagedPoolLimit;
+ internal IntPtr NonPagedPoolLimit;
+ internal IntPtr MinimumWorkingSetSize;
+ internal IntPtr MaximumWorkingSetSize;
+ internal IntPtr PagefileLimit;
+ internal IntPtr TimeLimit;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct SECURITY_LOGON_SESSION_DATA {
+ internal uint Size;
+ internal LUID LogonId;
+ internal UNICODE_INTPTR_STRING UserName;
+ internal UNICODE_INTPTR_STRING LogonDomain;
+ internal UNICODE_INTPTR_STRING AuthenticationPackage;
+ internal uint LogonType;
+ internal uint Session;
+ internal IntPtr Sid;
+ internal long LogonTime;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct SID_AND_ATTRIBUTES {
+ internal IntPtr Sid;
+ internal uint Attributes;
+ internal static readonly long SizeOf = (long)Marshal.SizeOf(typeof(SID_AND_ATTRIBUTES));
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_GROUPS {
+ internal uint GroupCount;
+ internal SID_AND_ATTRIBUTES Groups; // SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY];
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
+ internal struct TOKEN_PRIMARY_GROUP
+ {
+ internal IntPtr PrimaryGroup;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_PRIVILEGE {
+ internal uint PrivilegeCount;
+ internal LUID_AND_ATTRIBUTES Privilege;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_SOURCE {
+ private const int TOKEN_SOURCE_LENGTH = 8;
+
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst=TOKEN_SOURCE_LENGTH)]
+ internal char[] Name;
+ internal LUID SourceIdentifier;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_STATISTICS {
+ internal LUID TokenId;
+ internal LUID AuthenticationId;
+ internal long ExpirationTime;
+ internal uint TokenType;
+ internal uint ImpersonationLevel;
+ internal uint DynamicCharged;
+ internal uint DynamicAvailable;
+ internal uint GroupCount;
+ internal uint PrivilegeCount;
+ internal LUID ModifiedId;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ internal struct TOKEN_USER {
+ internal SID_AND_ATTRIBUTES User;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MEMORYSTATUSEX {
+ // The length field must be set to the size of this data structure.
+ internal int length;
+ internal int memoryLoad;
+ internal ulong totalPhys;
+ internal ulong availPhys;
+ internal ulong totalPageFile;
+ internal ulong availPageFile;
+ internal ulong totalVirtual;
+ internal ulong availVirtual;
+ internal ulong availExtendedVirtual;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct MEMORY_BASIC_INFORMATION {
+ internal void* BaseAddress;
+ internal void* AllocationBase;
+ internal uint AllocationProtect;
+ internal UIntPtr RegionSize;
+ internal uint State;
+ internal uint Protect;
+ internal uint Type;
+ }
+
+#if !FEATURE_PAL
+ internal const String KERNEL32 = "kernel32.dll";
+ internal const String USER32 = "user32.dll";
+ internal const String OLE32 = "ole32.dll";
+ internal const String OLEAUT32 = "oleaut32.dll";
+ internal const String NTDLL = "ntdll.dll";
+#else //FEATURE_PAL
+ internal const String KERNEL32 = "libcoreclr";
+ internal const String USER32 = "libcoreclr";
+ internal const String OLE32 = "libcoreclr";
+ internal const String OLEAUT32 = "libcoreclr";
+ internal const String NTDLL = "libcoreclr";
+#endif //FEATURE_PAL
+ internal const String ADVAPI32 = "advapi32.dll";
+ internal const String SHELL32 = "shell32.dll";
+ internal const String SHIM = "mscoree.dll";
+ internal const String CRYPT32 = "crypt32.dll";
+ internal const String SECUR32 = "secur32.dll";
+#if FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+ internal const String MSCORWKS = "coreclr.dll";
+#else //FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+ internal const String MSCORWKS = "clr.dll";
+#endif //FEATURE_MAIN_CLR_MODULE_USES_CORE_NAME
+
+ // From WinBase.h
+ internal const int SEM_FAILCRITICALERRORS = 1;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=true)]
+ internal static extern int FormatMessage(int dwFlags, IntPtr lpSource,
+ int dwMessageId, int dwLanguageId, [Out]StringBuilder lpBuffer,
+ int nSize, IntPtr va_list_arguments);
+
+ // Gets an error message for a Win32 error code.
+ internal static String GetMessage(int errorCode) {
+ StringBuilder sb = StringBuilderCache.Acquire(512);
+ int result = Win32Native.FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
+ IntPtr.Zero, errorCode, 0, sb, sb.Capacity, IntPtr.Zero);
+ if (result != 0) {
+ // result is the # of characters copied to the StringBuilder.
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ else {
+ StringBuilderCache.Release(sb);
+ return Environment.GetResourceString("UnknownError_Num", errorCode);
+ }
+ }
+
+ [DllImport(KERNEL32, EntryPoint="LocalAlloc")]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr LocalAlloc_NoSafeHandle(int uFlags, UIntPtr sizetdwBytes);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ SafeLocalAllocHandle LocalAlloc(
+ [In] int uFlags,
+ [In] UIntPtr sizetdwBytes);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern IntPtr LocalFree(IntPtr handle);
+
+ // MSDN says the length is a SIZE_T.
+ [DllImport(NTDLL, EntryPoint = "RtlZeroMemory")]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern void ZeroMemory(IntPtr address, UIntPtr length);
+
+ internal static bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX buffer)
+ {
+ buffer.length = Marshal.SizeOf(typeof(MEMORYSTATUSEX));
+ return GlobalMemoryStatusExNative(ref buffer);
+ }
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="GlobalMemoryStatusEx")]
+ private static extern bool GlobalMemoryStatusExNative([In, Out] ref MEMORYSTATUSEX buffer);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern UIntPtr VirtualQuery(void* address, ref MEMORY_BASIC_INFORMATION buffer, UIntPtr sizeOfBuffer);
+
+ // VirtualAlloc should generally be avoided, but is needed in
+ // the MemoryFailPoint implementation (within a CER) to increase the
+ // size of the page file, ignoring any host memory allocators.
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ unsafe internal static extern void * VirtualAlloc(void* address, UIntPtr numBytes, int commitOrReserve, int pageProtectionMode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ unsafe internal static extern bool VirtualFree(void* address, UIntPtr numBytes, int pageFreeMode);
+
+
+
+ // 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)]
+ private static extern IntPtr GetProcAddress(IntPtr hModule, String methodName);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern IntPtr GetModuleHandle(String moduleName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal 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 = Win32Native.GetModuleHandle(moduleName);
+ if (hModule == IntPtr.Zero) {
+ BCLDebug.Assert(hModule != IntPtr.Zero, "GetModuleHandle failed. Dll isn't loaded?");
+ return false;
+ }
+ IntPtr functionPointer = Win32Native.GetProcAddress(hModule, methodName);
+ return (functionPointer != IntPtr.Zero);
+ }
+
+ // There is no need to call CloseProcess or to use a SafeHandle if you get the handle
+ // using GetCurrentProcess as it returns a pseudohandle
+ [DllImport(KERNEL32, SetLastError = true, CallingConvention = CallingConvention.Winapi)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool IsWow64Process(
+ [In]
+ IntPtr hSourceProcessHandle,
+ [Out, MarshalAs(UnmanagedType.Bool)]
+ out bool isWow64);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern uint GetTempPath(int bufferLen, [Out]StringBuilder buffer);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Ansi, ExactSpelling=true, EntryPoint="lstrlenA")]
+ internal static extern int lstrlenA(IntPtr ptr);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, ExactSpelling=true, EntryPoint="lstrlenW")]
+ internal static extern int lstrlenW(IntPtr ptr);
+
+ [DllImport(Win32Native.OLEAUT32, CharSet = CharSet.Unicode)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr SysAllocStringLen(String src, int len); // BSTR
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringLen(IntPtr bstr);
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern void SysFreeString(IntPtr bstr);
+
+#if FEATURE_COMINTEROP
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern IntPtr SysAllocStringByteLen(byte[] str, uint len); // BSTR
+
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringByteLen(IntPtr bstr);
+
+#if FEATURE_LEGACYSURFACE
+ [DllImport(Win32Native.OLEAUT32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SysStringLen(SafeBSTRHandle bstr);
+#endif
+
+#endif
+
+ [DllImport(KERNEL32)]
+ internal static extern int GetACP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetEvent(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool ResetEvent(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle CreateEvent(SECURITY_ATTRIBUTES lpSecurityAttributes, bool isManualReset, bool initialState, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle OpenEvent(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern SafeWaitHandle CreateMutex(SECURITY_ATTRIBUTES lpSecurityAttributes, bool initialOwner, String name);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeWaitHandle OpenMutex(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern bool ReleaseMutex(SafeWaitHandle handle);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal unsafe static extern int GetFullPathName(char* path, int numBufferChars, char* buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int GetFullPathName(String path, int numBufferChars, [Out]StringBuilder buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal unsafe static extern int GetLongPathName(char* path, char* longPathBuffer, int bufferLength);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal unsafe static extern uint GetFullPathNameW(char* path, uint numBufferChars, SafeHandle buffer, IntPtr mustBeZero);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern int GetLongPathName(String path, [Out]StringBuilder longPathBuffer, int bufferLength);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal static extern uint GetLongPathNameW(SafeHandle lpszShortPath, SafeHandle lpszLongPath, uint cchBuffer);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)]
+ 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
+ // a web client asking a server for "http://server/com1.aspx" and
+ // then causing a worker process to hang.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SafeFileHandle SafeCreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile)
+ {
+ SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode,
+ securityAttrs, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile );
+
+ if (!handle.IsInvalid)
+ {
+ int fileType = Win32Native.GetFileType(handle);
+ if (fileType != Win32Native.FILE_TYPE_DISK) {
+ handle.Dispose();
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
+ }
+ }
+
+ return handle;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SafeFileHandle UnsafeCreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile)
+ {
+ SafeFileHandle handle = CreateFile( lpFileName, dwDesiredAccess, dwShareMode,
+ securityAttrs, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile );
+
+ return handle;
+ }
+
+ // Do not use these directly, use the safe or unsafe versions above.
+ // The safe version does not support devices (aka if will only open
+ // files on disk), while the unsafe version give you the full semantic
+ // of the native version.
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern SafeFileHandle CreateFile(String lpFileName,
+ int dwDesiredAccess, System.IO.FileShare dwShareMode,
+ SECURITY_ATTRIBUTES securityAttrs, System.IO.FileMode dwCreationDisposition,
+ int dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeFileMappingHandle CreateFileMapping(SafeFileHandle hFile, IntPtr lpAttributes, uint fProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, String lpName);
+
+ [DllImport(KERNEL32, SetLastError=true, ExactSpelling=true)]
+ internal static extern IntPtr MapViewOfFile(
+ SafeFileMappingHandle handle, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, UIntPtr dwNumerOfBytesToMap);
+
+ [DllImport(KERNEL32, ExactSpelling=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress );
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool CloseHandle(IntPtr handle);
+
+ [DllImport(KERNEL32)]
+ internal static extern int GetFileType(SafeFileHandle handle);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetEndOfFile(SafeFileHandle hFile);
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool FlushFileBuffers(SafeFileHandle hFile);
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="SetFilePointer")]
+ private unsafe static extern int SetFilePointerWin32(SafeFileHandle handle, int lo, int * hi, int origin);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static long SetFilePointer(SafeFileHandle handle, long offset, System.IO.SeekOrigin origin, out int hr) {
+ hr = 0;
+ int lo = (int) offset;
+ int hi = (int) (offset >> 32);
+ lo = SetFilePointerWin32(handle, lo, &hi, (int) origin);
+
+ if (lo == -1 && ((hr = Marshal.GetLastWin32Error()) != 0))
+ return -1;
+ return (long) (((ulong) ((uint) hi)) << 32) | ((uint) lo);
+ }
+
+ // Note there are two different ReadFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
+ // Win32's async IO support. You can't do the following three things
+ // simultaneously: overlapped IO, free the memory for the overlapped
+ // struct in a callback (or an EndRead method called by that callback),
+ // and pass in an address for the numBytesRead parameter.
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, IntPtr numBytesRead_mustBeZero, NativeOverlapped* overlapped);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ unsafe internal static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
+
+ // Note there are two different WriteFile prototypes - this is to use
+ // the type system to force you to not trip across a "feature" in
+ // Win32's async IO support. You can't do the following three things
+ // simultaneously: overlapped IO, free the memory for the overlapped
+ // struct in a callback (or an EndWrite method called by that callback),
+ // and pass in an address for the numBytesRead parameter.
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern int WriteFile(SafeFileHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero);
+
+ // This is only available on Vista or higher
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool CancelIoEx(SafeFileHandle handle, NativeOverlapped* lpOverlapped);
+
+ // NOTE: The out parameters are PULARGE_INTEGERs and may require
+ // some byte munging magic.
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool GetDiskFreeSpaceEx(String drive, out long freeBytesForUser, out long totalBytes, out long freeBytes);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetDriveType(String drive);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool GetVolumeInformation(String drive, [Out]StringBuilder volumeName, int volumeNameBufLen, out int volSerialNumber, out int maxFileNameLen, out int fileSystemFlags, [Out]StringBuilder fileSystemName, int fileSystemNameBufLen);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool SetVolumeLabel(String driveLetter, String volumeName);
+
+ // The following 4 methods are used by Microsoft.WlcProfile
+ [DllImport(KERNEL32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool QueryPerformanceCounter(out long value);
+
+ [DllImport(KERNEL32)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool QueryPerformanceFrequency(out long value);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern SafeWaitHandle CreateSemaphore(SECURITY_ATTRIBUTES lpSecurityAttributes, int initialCount, int maximumCount, String name);
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool ReleaseSemaphore(SafeWaitHandle handle, int releaseCount, out int previousCount);
+
+ [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)]
+ internal static extern SafeWaitHandle OpenSemaphore(/* DWORD */ int desiredAccess, bool inheritHandle, String name);
+
+ // Will be in winnls.h
+ internal const int FIND_STARTSWITH = 0x00100000; // see if value is at the beginning of source
+ internal const int FIND_ENDSWITH = 0x00200000; // see if value is at the end of source
+ internal const int FIND_FROMSTART = 0x00400000; // look for value in source, starting at the beginning
+ internal const int FIND_FROMEND = 0x00800000; // look for value in source, starting at the end
+
+#if !FEATURE_CORECLR
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NlsVersionInfoEx
+ {
+ internal int dwNLSVersionInfoSize;
+ internal int dwNLSVersion;
+ internal int dwDefinedVersion;
+ internal int dwEffectiveId;
+ internal Guid guidCustomVersion;
+ }
+#endif
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetWindowsDirectory([Out]StringBuilder sb, int length);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetSystemDirectory([Out]StringBuilder sb, int length);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal unsafe static extern bool SetFileTime(SafeFileHandle hFile, FILE_TIME* creationTime,
+ FILE_TIME* lastAccessTime, FILE_TIME* lastWriteTime);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern int GetFileSize(SafeFileHandle hFile, out int highSize);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool LockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool UnlockFile(SafeFileHandle handle, int offsetLow, int offsetHigh, int countLow, int countHigh);
+
+ internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); // WinBase.h
+
+ // Note, these are #defines used to extract handles, and are NOT handles.
+ internal const int STD_INPUT_HANDLE = -10;
+ internal const int STD_OUTPUT_HANDLE = -11;
+ internal const int STD_ERROR_HANDLE = -12;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern IntPtr GetStdHandle(int nStdHandle); // param is NOT a handle, but it returns one!
+
+ // From wincon.h
+ internal const int CTRL_C_EVENT = 0;
+ internal const int CTRL_BREAK_EVENT = 1;
+ internal const int CTRL_CLOSE_EVENT = 2;
+ internal const int CTRL_LOGOFF_EVENT = 5;
+ internal const int CTRL_SHUTDOWN_EVENT = 6;
+ internal const short KEY_EVENT = 1;
+
+ // From WinBase.h
+ internal const int FILE_TYPE_DISK = 0x0001;
+ internal const int FILE_TYPE_CHAR = 0x0002;
+ internal const int FILE_TYPE_PIPE = 0x0003;
+
+ internal const int REPLACEFILE_WRITE_THROUGH = 0x1;
+ internal const int REPLACEFILE_IGNORE_MERGE_ERRORS = 0x2;
+
+ private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x00000200;
+ private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000;
+ private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000;
+
+ internal const uint FILE_MAP_WRITE = 0x0002;
+ internal const uint FILE_MAP_READ = 0x0004;
+
+ // Constants from WinNT.h
+ internal const int FILE_ATTRIBUTE_READONLY = 0x00000001;
+ internal const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
+ internal const int FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
+
+ internal const int IO_REPARSE_TAG_MOUNT_POINT = unchecked((int)0xA0000003);
+
+ internal const int PAGE_READWRITE = 0x04;
+
+ internal const int MEM_COMMIT = 0x1000;
+ internal const int MEM_RESERVE = 0x2000;
+ internal const int MEM_RELEASE = 0x8000;
+ internal const int MEM_FREE = 0x10000;
+
+ // Error codes from WinError.h
+ internal const int ERROR_SUCCESS = 0x0;
+ internal const int ERROR_INVALID_FUNCTION = 0x1;
+ internal const int ERROR_FILE_NOT_FOUND = 0x2;
+ internal const int ERROR_PATH_NOT_FOUND = 0x3;
+ internal const int ERROR_ACCESS_DENIED = 0x5;
+ internal const int ERROR_INVALID_HANDLE = 0x6;
+ internal const int ERROR_NOT_ENOUGH_MEMORY = 0x8;
+ internal const int ERROR_INVALID_DATA = 0xd;
+ internal const int ERROR_INVALID_DRIVE = 0xf;
+ internal const int ERROR_NO_MORE_FILES = 0x12;
+ internal const int ERROR_NOT_READY = 0x15;
+ internal const int ERROR_BAD_LENGTH = 0x18;
+ internal const int ERROR_SHARING_VIOLATION = 0x20;
+ internal const int ERROR_NOT_SUPPORTED = 0x32;
+ internal const int ERROR_FILE_EXISTS = 0x50;
+ internal const int ERROR_INVALID_PARAMETER = 0x57;
+ internal const int ERROR_BROKEN_PIPE = 0x6D;
+ internal const int ERROR_CALL_NOT_IMPLEMENTED = 0x78;
+ internal const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
+ internal const int ERROR_INVALID_NAME = 0x7B;
+ internal const int ERROR_BAD_PATHNAME = 0xA1;
+ internal const int ERROR_ALREADY_EXISTS = 0xB7;
+ internal const int ERROR_ENVVAR_NOT_FOUND = 0xCB;
+ internal const int ERROR_FILENAME_EXCED_RANGE = 0xCE; // filename too long.
+ internal const int ERROR_NO_DATA = 0xE8;
+ internal const int ERROR_PIPE_NOT_CONNECTED = 0xE9;
+ internal const int ERROR_MORE_DATA = 0xEA;
+ internal const int ERROR_DIRECTORY = 0x10B;
+ internal const int ERROR_OPERATION_ABORTED = 0x3E3; // 995; For IO Cancellation
+ internal const int ERROR_NOT_FOUND = 0x490; // 1168; For IO Cancellation
+ internal const int ERROR_NO_TOKEN = 0x3f0;
+ internal const int ERROR_DLL_INIT_FAILED = 0x45A;
+ internal const int ERROR_NON_ACCOUNT_SID = 0x4E9;
+ internal const int ERROR_NOT_ALL_ASSIGNED = 0x514;
+ internal const int ERROR_UNKNOWN_REVISION = 0x519;
+ internal const int ERROR_INVALID_OWNER = 0x51B;
+ internal const int ERROR_INVALID_PRIMARY_GROUP = 0x51C;
+ internal const int ERROR_NO_SUCH_PRIVILEGE = 0x521;
+ internal const int ERROR_PRIVILEGE_NOT_HELD = 0x522;
+ internal const int ERROR_NONE_MAPPED = 0x534;
+ internal const int ERROR_INVALID_ACL = 0x538;
+ internal const int ERROR_INVALID_SID = 0x539;
+ internal const int ERROR_INVALID_SECURITY_DESCR = 0x53A;
+ internal const int ERROR_BAD_IMPERSONATION_LEVEL = 0x542;
+ internal const int ERROR_CANT_OPEN_ANONYMOUS = 0x543;
+ internal const int ERROR_NO_SECURITY_ON_OBJECT = 0x546;
+ internal const int ERROR_TRUSTED_RELATIONSHIP_FAILURE = 0x6FD;
+
+ // Error codes from ntstatus.h
+ internal const uint STATUS_SUCCESS = 0x00000000;
+ internal const uint STATUS_SOME_NOT_MAPPED = 0x00000107;
+ internal const uint STATUS_NO_MEMORY = 0xC0000017;
+ internal const uint STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
+ internal const uint STATUS_NONE_MAPPED = 0xC0000073;
+ internal const uint STATUS_INSUFFICIENT_RESOURCES = 0xC000009A;
+ internal const uint STATUS_ACCESS_DENIED = 0xC0000022;
+
+ internal const int INVALID_FILE_SIZE = -1;
+
+ // From WinStatus.h
+ internal const int STATUS_ACCOUNT_RESTRICTION = unchecked((int) 0xC000006E);
+
+ // Use this to translate error codes like the above into HRESULTs like
+ // 0x80070006 for ERROR_INVALID_HANDLE
+ internal static int MakeHRFromErrorCode(int errorCode)
+ {
+ BCLDebug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!");
+ return unchecked(((int)0x80070000) | errorCode);
+ }
+
+ // Win32 Structs in N/Direct style
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ [BestFitMapping(false)]
+ internal class WIN32_FIND_DATA {
+ internal int dwFileAttributes = 0;
+ // ftCreationTime was a by-value FILETIME structure
+ internal uint ftCreationTime_dwLowDateTime = 0 ;
+ internal uint ftCreationTime_dwHighDateTime = 0;
+ // ftLastAccessTime was a by-value FILETIME structure
+ internal uint ftLastAccessTime_dwLowDateTime = 0;
+ internal uint ftLastAccessTime_dwHighDateTime = 0;
+ // ftLastWriteTime was a by-value FILETIME structure
+ internal uint ftLastWriteTime_dwLowDateTime = 0;
+ internal uint ftLastWriteTime_dwHighDateTime = 0;
+ internal int nFileSizeHigh = 0;
+ internal int nFileSizeLow = 0;
+ // If the file attributes' reparse point flag is set, then
+ // dwReserved0 is the file tag (aka reparse tag) for the
+ // reparse point. Use this to figure out whether something is
+ // a volume mount point or a symbolic link.
+ internal int dwReserved0 = 0;
+ internal int dwReserved1 = 0;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=260)]
+ internal String cFileName = null;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst=14)]
+ internal String cAlternateFileName = null;
+ }
+
+#if FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern bool CopyFileEx(String src,
+ String dst,
+ IntPtr progressRoutine,
+ IntPtr progressData,
+ ref uint cancel,
+ uint flags);
+
+ internal static bool CopyFile(String src, String dst, bool failIfExists)
+ {
+ uint cancel = 0;
+ return CopyFileEx(src, dst, IntPtr.Zero, IntPtr.Zero, ref cancel, failIfExists ? 1U : 0U);
+ }
+#else // FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool CopyFile(
+ String src, String dst, bool failIfExists);
+#endif // FEATURE_CORESYSTEM
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool CreateDirectory(
+ String path, SECURITY_ATTRIBUTES lpSecurityAttributes);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DeleteFile(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool ReplaceFile(String replacedFileName, String replacementFileName, String backupFileName, int dwReplaceFlags, IntPtr lpExclude, IntPtr lpReserved);
+
+ [DllImport(ADVAPI32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DecryptFile(String path, int reservedMustBeZero);
+
+ [DllImport(ADVAPI32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool EncryptFile(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] Win32Native.WIN32_FIND_DATA data);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool FindNextFile(
+ SafeFindHandle hndFindFile,
+ [In, Out, MarshalAs(UnmanagedType.LPStruct)]
+ WIN32_FIND_DATA lpFindFileData);
+
+ [DllImport(KERNEL32)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool FindClose(IntPtr handle);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int GetCurrentDirectory(
+ int nBufferLength,
+ [Out]StringBuilder lpBuffer);
+
+ [DllImport(KERNEL32, SetLastError = true, ExactSpelling = true)]
+ internal static extern uint GetCurrentDirectoryW(uint nBufferLength, SafeHandle lpBuffer);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool GetFileAttributesEx(String name, int fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool SetFileAttributes(String name, int attr);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern int GetLogicalDrives();
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern uint GetTempFileName(String tmpPath, String prefix, uint uniqueIdOrZero, [Out]StringBuilder tmpFileName);
+
+#if FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ private static extern bool MoveFileEx(String src, String dst, uint flags);
+
+ internal static bool MoveFile(String src, String dst)
+ {
+ return MoveFileEx(src, dst, 2 /* MOVEFILE_COPY_ALLOWED */);
+ }
+#else // FEATURE_CORESYSTEM
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool MoveFile(String src, String dst);
+#endif // FEATURE_CORESYSTEM
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool DeleteVolumeMountPoint(String mountPoint);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool RemoveDirectory(String path);
+
+ [DllImport(KERNEL32, SetLastError=true, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern bool SetCurrentDirectory(String path);
+
+ [DllImport(KERNEL32, SetLastError=false, EntryPoint="SetErrorMode", ExactSpelling=true)]
+ private static extern int SetErrorMode_VistaAndOlder(int newMode);
+
+ [DllImport(KERNEL32, SetLastError=true, EntryPoint="SetThreadErrorMode")]
+ private static extern bool SetErrorMode_Win7AndNewer(int newMode, out int oldMode);
+
+ // RTM versions of Win7 and Windows Server 2008 R2
+ private static readonly Version ThreadErrorModeMinOsVersion = new Version(6, 1, 7600);
+
+ // this method uses the thread-safe version of SetErrorMode on Windows 7 / Windows Server 2008 R2 operating systems.
+ internal static int SetErrorMode(int newMode)
+ {
+#if !FEATURE_CORESYSTEM // ARMSTUB
+ if (Environment.OSVersion.Version >= ThreadErrorModeMinOsVersion)
+ {
+ int oldMode;
+ SetErrorMode_Win7AndNewer(newMode, out oldMode);
+ return oldMode;
+ }
+#endif
+ return SetErrorMode_VistaAndOlder(newMode);
+ }
+
+ internal const int LCID_SUPPORTED = 0x00000002; // supported locale ids
+
+ [DllImport(KERNEL32)]
+ internal static extern unsafe int WideCharToMultiByte(uint cp, uint flags, char* pwzSource, int cchSource, byte* pbDestBuffer, int cbDestBuffer, IntPtr null1, IntPtr null2);
+
+ // A Win32 HandlerRoutine
+ internal delegate bool ConsoleCtrlHandlerRoutine(int controlType);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool SetConsoleCtrlHandler(ConsoleCtrlHandlerRoutine handler, bool addOrRemove);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool SetEnvironmentVariable(string lpName, string lpValue);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int GetEnvironmentVariable(string lpName, [Out]StringBuilder lpValue, int size);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ internal static unsafe extern char * GetEnvironmentStrings();
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ internal static unsafe extern bool FreeEnvironmentStrings(char * pStrings);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern uint GetCurrentProcessId();
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto)]
+ internal static extern bool GetUserName([Out]StringBuilder lpBuffer, ref int nSize);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal extern static int GetComputerName([Out]StringBuilder nameBuffer, ref int bufferSize);
+
+ [DllImport(OLE32)]
+ internal extern static int CoCreateGuid(out Guid guid);
+
+ [DllImport(OLE32)]
+ internal static extern IntPtr CoTaskMemAlloc(UIntPtr cb);
+
+ [DllImport(OLE32)]
+ internal static extern void CoTaskMemFree(IntPtr ptr);
+
+ [DllImport(OLE32)]
+ internal static extern IntPtr CoTaskMemRealloc(IntPtr pv, UIntPtr cb);
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct COORD
+ {
+ internal short X;
+ internal short Y;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct SMALL_RECT
+ {
+ internal short Left;
+ internal short Top;
+ internal short Right;
+ internal short Bottom;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct CONSOLE_SCREEN_BUFFER_INFO
+ {
+ internal COORD dwSize;
+ internal COORD dwCursorPosition;
+ internal short wAttributes;
+ internal SMALL_RECT srWindow;
+ internal COORD dwMaximumWindowSize;
+ }
+
+ [StructLayoutAttribute(LayoutKind.Sequential)]
+ internal struct CONSOLE_CURSOR_INFO
+ {
+ internal int dwSize;
+ internal bool bVisible;
+ }
+
+ // Win32's KEY_EVENT_RECORD
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal struct KeyEventRecord
+ {
+ internal bool keyDown;
+ internal short repeatCount;
+ internal short virtualKeyCode;
+ internal short virtualScanCode;
+ internal char uChar; // Union between WCHAR and ASCII char
+ internal int controlKeyState;
+ }
+
+ // Really, this is a union of KeyEventRecords and other types.
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
+ internal struct InputRecord
+ {
+ internal short eventType;
+ internal KeyEventRecord keyEvent;
+ // This struct is a union! Word alighment should take care of padding!
+ }
+
+[Serializable]
+ [Flags]
+ internal enum Color : short
+ {
+ Black = 0,
+ ForegroundBlue = 0x1,
+ ForegroundGreen = 0x2,
+ ForegroundRed = 0x4,
+ ForegroundYellow = 0x6,
+ ForegroundIntensity = 0x8,
+ BackgroundBlue = 0x10,
+ BackgroundGreen = 0x20,
+ BackgroundRed = 0x40,
+ BackgroundYellow = 0x60,
+ BackgroundIntensity = 0x80,
+
+ ForegroundMask = 0xf,
+ BackgroundMask = 0xf0,
+ ColorMask = 0xff
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct CHAR_INFO
+ {
+ ushort charData; // Union between WCHAR and ASCII char
+ short attributes;
+ }
+
+ internal const int ENABLE_PROCESSED_INPUT = 0x0001;
+ internal const int ENABLE_LINE_INPUT = 0x0002;
+ internal const int ENABLE_ECHO_INPUT = 0x0004;
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleMode(IntPtr hConsoleHandle, int mode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int mode);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool Beep(int frequency, int duration);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput,
+ out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, COORD size);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern COORD GetLargestConsoleWindowSize(IntPtr hConsoleOutput);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool FillConsoleOutputCharacter(IntPtr hConsoleOutput,
+ char character, int nLength, COORD dwWriteCoord, out int pNumCharsWritten);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool FillConsoleOutputAttribute(IntPtr hConsoleOutput,
+ short wColorAttribute, int numCells, COORD startCoord, out int pNumBytesWritten);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool SetConsoleWindowInfo(IntPtr hConsoleOutput,
+ bool absolute, SMALL_RECT* consoleWindow);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleTextAttribute(IntPtr hConsoleOutput, short attributes);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput,
+ COORD cursorPosition);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput,
+ out CONSOLE_CURSOR_INFO cci);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCursorInfo(IntPtr hConsoleOutput,
+ ref CONSOLE_CURSOR_INFO cci);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=true)]
+ internal static extern bool SetConsoleTitle(String title);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern bool PeekConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static unsafe extern bool ReadConsoleW(SafeFileHandle hConsoleInput, Byte* lpBuffer, Int32 nNumberOfCharsToRead, out Int32 lpNumberOfCharsRead, IntPtr pInputControl);
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static unsafe extern bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static unsafe extern bool WriteConsoleW(SafeFileHandle hConsoleOutput, Byte* lpBuffer, Int32 nNumberOfCharsToWrite, out Int32 lpNumberOfCharsWritten, IntPtr lpReservedMustBeNull);
+
+ [DllImport(USER32)] // Appears to always succeed
+ internal static extern short GetKeyState(int virtualKeyCode);
+
+ [DllImport(KERNEL32, SetLastError=false)]
+ internal static extern uint GetConsoleCP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleCP(uint codePage);
+
+ [DllImport(KERNEL32, SetLastError=false)]
+ internal static extern uint GetConsoleOutputCP();
+
+ [DllImport(KERNEL32, SetLastError=true)]
+ internal static extern bool SetConsoleOutputCP(uint codePage);
+
+#if FEATURE_WIN32_REGISTRY
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegConnectRegistry(String machineName,
+ SafeRegistryHandle key, out SafeRegistryHandle result);
+
+ // Note: RegCreateKeyEx won't set the last error on failure - it returns
+ // an error code if it fails.
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegCreateKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int Reserved, String lpClass, int dwOptions,
+ int samDesired, SECURITY_ATTRIBUTES lpSecurityAttributes,
+ out SafeRegistryHandle hkResult, out int lpdwDisposition);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteKey(SafeRegistryHandle hKey, String lpSubKey);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int samDesired, int Reserved);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegDeleteValue(SafeRegistryHandle hKey, String lpValueName);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int RegEnumKeyEx(SafeRegistryHandle hKey, int dwIndex,
+ char *lpName, ref int lpcbName, int[] lpReserved,
+ [Out]StringBuilder lpClass, int[] lpcbClass,
+ long[] lpftLastWriteTime);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal unsafe static extern int RegEnumValue(SafeRegistryHandle hKey, int dwIndex,
+ char *lpValueName, ref int lpcbValueName,
+ IntPtr lpReserved_MustBeZero, int[] lpType, byte[] lpData,
+ int[] lpcbData);
+
+
+ [DllImport(ADVAPI32)]
+ internal static extern int RegFlushKey(SafeRegistryHandle hKey);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegOpenKeyEx(SafeRegistryHandle hKey, String lpSubKey,
+ int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegOpenKeyEx(IntPtr hKey, String lpSubKey,
+ int ulOptions, int samDesired, out SafeRegistryHandle hkResult);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryInfoKey(SafeRegistryHandle hKey, [Out]StringBuilder lpClass,
+ int[] lpcbClass, IntPtr lpReserved_MustBeZero, ref int lpcSubKeys,
+ int[] lpcbMaxSubKeyLen, int[] lpcbMaxClassLen,
+ ref int lpcValues, int[] lpcbMaxValueNameLen,
+ int[] lpcbMaxValueLen, int[] lpcbSecurityDescriptor,
+ int[] lpftLastWriteTime);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] byte[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref int lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, ref long lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out] char[] lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int[] lpReserved, ref int lpType, [Out]StringBuilder lpData,
+ ref int lpcbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, byte[] lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, ref int lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, ref long lpData, int cbData);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int RegSetValueEx(SafeRegistryHandle hKey, String lpValueName,
+ int Reserved, RegistryValueKind dwType, String lpData, int cbData);
+#endif // FEATURE_WIN32_REGISTRY
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern int ExpandEnvironmentStrings(String lpSrc, [Out]StringBuilder lpDst, int nSize);
+
+ [DllImport(KERNEL32)]
+ internal static extern IntPtr LocalReAlloc(IntPtr handle, IntPtr sizetcbBytes, int uFlags);
+
+ internal const int SHGFP_TYPE_CURRENT = 0; // the current (user) folder path setting
+ internal const int UOI_FLAGS = 1;
+ internal const int WSF_VISIBLE = 1;
+
+ // .NET Framework 4.0 and newer - all versions of windows ||| \public\sdk\inc\shlobj.h
+ internal const int CSIDL_FLAG_CREATE = 0x8000; // force folder creation in SHGetFolderPath
+ internal const int CSIDL_FLAG_DONT_VERIFY = 0x4000; // return an unverified folder path
+ internal const int CSIDL_ADMINTOOLS = 0x0030; // <user name>\Start Menu\Programs\Administrative Tools
+ internal const int CSIDL_CDBURN_AREA = 0x003b; // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
+ internal const int CSIDL_COMMON_ADMINTOOLS = 0x002f; // All Users\Start Menu\Programs\Administrative Tools
+ internal const int CSIDL_COMMON_DOCUMENTS = 0x002e; // All Users\Documents
+ internal const int CSIDL_COMMON_MUSIC = 0x0035; // All Users\My Music
+ internal const int CSIDL_COMMON_OEM_LINKS = 0x003a; // Links to All Users OEM specific apps
+ internal const int CSIDL_COMMON_PICTURES = 0x0036; // All Users\My Pictures
+ internal const int CSIDL_COMMON_STARTMENU = 0x0016; // All Users\Start Menu
+ internal const int CSIDL_COMMON_PROGRAMS = 0X0017; // All Users\Start Menu\Programs
+ internal const int CSIDL_COMMON_STARTUP = 0x0018; // All Users\Startup
+ internal const int CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019; // All Users\Desktop
+ internal const int CSIDL_COMMON_TEMPLATES = 0x002d; // All Users\Templates
+ internal const int CSIDL_COMMON_VIDEO = 0x0037; // All Users\My Video
+ internal const int CSIDL_FONTS = 0x0014; // windows\fonts
+ internal const int CSIDL_MYVIDEO = 0x000e; // "My Videos" folder
+ internal const int CSIDL_NETHOOD = 0x0013; // %APPDATA%\Microsoft\Windows\Network Shortcuts
+ internal const int CSIDL_PRINTHOOD = 0x001b; // %APPDATA%\Microsoft\Windows\Printer Shortcuts
+ internal const int CSIDL_PROFILE = 0x0028; // %USERPROFILE% (%SystemDrive%\Users\%USERNAME%)
+ internal const int CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c; // x86 Program Files\Common on RISC
+ internal const int CSIDL_PROGRAM_FILESX86 = 0x002a; // x86 C:\Program Files on RISC
+ internal const int CSIDL_RESOURCES = 0x0038; // %windir%\Resources
+ internal const int CSIDL_RESOURCES_LOCALIZED = 0x0039; // %windir%\resources\0409 (code page)
+ internal const int CSIDL_SYSTEMX86 = 0x0029; // %windir%\system32
+ internal const int CSIDL_WINDOWS = 0x0024; // GetWindowsDirectory()
+
+ // .NET Framework 3.5 and earlier - all versions of windows
+ internal const int CSIDL_APPDATA = 0x001a;
+ internal const int CSIDL_COMMON_APPDATA = 0x0023;
+ internal const int CSIDL_LOCAL_APPDATA = 0x001c;
+ internal const int CSIDL_COOKIES = 0x0021;
+ internal const int CSIDL_FAVORITES = 0x0006;
+ internal const int CSIDL_HISTORY = 0x0022;
+ internal const int CSIDL_INTERNET_CACHE = 0x0020;
+ internal const int CSIDL_PROGRAMS = 0x0002;
+ internal const int CSIDL_RECENT = 0x0008;
+ internal const int CSIDL_SENDTO = 0x0009;
+ internal const int CSIDL_STARTMENU = 0x000b;
+ internal const int CSIDL_STARTUP = 0x0007;
+ internal const int CSIDL_SYSTEM = 0x0025;
+ internal const int CSIDL_TEMPLATES = 0x0015;
+ internal const int CSIDL_DESKTOPDIRECTORY = 0x0010;
+ internal const int CSIDL_PERSONAL = 0x0005;
+ internal const int CSIDL_PROGRAM_FILES = 0x0026;
+ internal const int CSIDL_PROGRAM_FILES_COMMON = 0x002b;
+ internal const int CSIDL_DESKTOP = 0x0000;
+ internal const int CSIDL_DRIVES = 0x0011;
+ internal const int CSIDL_MYMUSIC = 0x000d;
+ internal const int CSIDL_MYPICTURES = 0x0027;
+
+ [DllImport(SHELL32, CharSet=CharSet.Auto, BestFitMapping=false)]
+ internal static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken, int dwFlags, [Out]StringBuilder lpszPath);
+
+ internal const int NameSamCompatible = 2;
+
+ [DllImport(SECUR32, CharSet=CharSet.Unicode, SetLastError=true)]
+ // Win32 return type is BOOLEAN (which is 1 byte and not BOOL which is 4bytes)
+ internal static extern byte GetUserNameEx(int format, [Out]StringBuilder domainName, ref uint domainNameLen);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true, BestFitMapping=false)]
+ internal static extern bool LookupAccountName(string machineName, string accountName, byte[] sid,
+ ref int sidLen, [Out]StringBuilder domainName, ref uint domainNameLen, out int peUse);
+
+ // Note: This returns a handle, but it shouldn't be closed. The Avalon
+ // team says CloseWindowStation would ignore this handle. So there
+ // isn't a lot of value to switching to SafeHandle here.
+ [DllImport(USER32, ExactSpelling=true)]
+ internal static extern IntPtr GetProcessWindowStation();
+
+ [DllImport(USER32, SetLastError=true)]
+ internal static extern bool GetUserObjectInformation(IntPtr hObj, int nIndex,
+ [MarshalAs(UnmanagedType.LPStruct)] USEROBJECTFLAGS pvBuffer, int nLength, ref int lpnLengthNeeded);
+
+ [DllImport(USER32, SetLastError=true, BestFitMapping=false)]
+ internal static extern IntPtr SendMessageTimeout(IntPtr hWnd, int Msg, IntPtr wParam, String lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult);
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class USEROBJECTFLAGS {
+ internal int fInherit = 0;
+ internal int fReserved = 0;
+ internal int dwFlags = 0;
+ }
+
+ //
+ // DPAPI
+ //
+
+#if FEATURE_LEGACYSURFACE
+ //
+ // RtlEncryptMemory and RtlDecryptMemory are declared in the internal header file crypt.h.
+ // They were also recently declared in the public header file ntsecapi.h (in the Platform SDK as well as the current build of Server 2003).
+ // We use them instead of CryptProtectMemory and CryptUnprotectMemory because
+ // they are available in both WinXP and in Windows Server 2003.
+ //
+
+ [DllImport(Win32Native.ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern
+ int SystemFunction040 (
+ [In,Out] SafeBSTRHandle pDataIn,
+ [In] uint cbDataIn, // multiple of RTL_ENCRYPT_MEMORY_SIZE
+ [In] uint dwFlags);
+
+ [DllImport(Win32Native.ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ int SystemFunction041 (
+ [In,Out] SafeBSTRHandle pDataIn,
+ [In] uint cbDataIn, // multiple of RTL_ENCRYPT_MEMORY_SIZE
+ [In] uint dwFlags);
+#endif // FEATURE_LEGACYSURFACE
+
+#if FEATURE_CORECLR
+ [DllImport(NTDLL, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ int RtlNtStatusToDosError (
+ [In] int status);
+#else
+ // identical to RtlNtStatusToDosError, but we are in ask mode for desktop CLR
+ [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)]
+ internal static extern
+ int LsaNtStatusToWinError (
+ [In] int status);
+#endif
+ // Get the current FIPS policy setting on Vista and above
+ [DllImport("bcrypt.dll")]
+ internal static extern uint BCryptGetFipsAlgorithmMode(
+ [MarshalAs(UnmanagedType.U1), Out]out bool pfEnabled);
+
+ //
+ // Managed ACLs
+ //
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool AdjustTokenPrivileges (
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] bool DisableAllPrivileges,
+ [In] ref TOKEN_PRIVILEGE NewState,
+ [In] uint BufferLength,
+ [In,Out] ref TOKEN_PRIVILEGE PreviousState,
+ [In,Out] ref uint ReturnLength);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool AllocateLocallyUniqueId(
+ [In,Out] ref LUID Luid);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool CheckTokenMembership(
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] byte[] SidToCheck,
+ [In,Out] ref bool IsMember);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertSecurityDescriptorToStringSecurityDescriptorW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertSdToStringSd(
+ byte[] securityDescriptor,
+ /* DWORD */ uint requestedRevision,
+ ULONG securityInformation,
+ out IntPtr resultString,
+ ref ULONG resultStringLength );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertStringSecurityDescriptorToSecurityDescriptorW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertStringSdToSd(
+ string stringSd,
+ /* DWORD */ uint stringSdRevision,
+ out IntPtr resultSd,
+ ref ULONG resultSdLength );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="ConvertStringSidToSidW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL ConvertStringSidToSid(
+ string stringSid,
+ out IntPtr ByteArray
+ );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint = "ConvertSidToStringSidW",
+ CallingConvention = CallingConvention.Winapi,
+ SetLastError = true,
+ ExactSpelling = true,
+ CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool ConvertSidToStringSid(
+ IntPtr Sid,
+ ref IntPtr StringSid
+ );
+
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="CreateWellKnownSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL CreateWellKnownSid(
+ int sidType,
+ byte[] domainSid,
+ [Out] byte[] resultSid,
+ ref /*DWORD*/ uint resultSidLength );
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateHandle (
+ [In] IntPtr hSourceProcessHandle,
+ [In] IntPtr hSourceHandle,
+ [In] IntPtr hTargetProcessHandle,
+ [In,Out] ref SafeAccessTokenHandle lpTargetHandle,
+ [In] uint dwDesiredAccess,
+ [In] bool bInheritHandle,
+ [In] uint dwOptions);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateHandle (
+ [In] IntPtr hSourceProcessHandle,
+ [In] SafeAccessTokenHandle hSourceHandle,
+ [In] IntPtr hTargetProcessHandle,
+ [In,Out] ref SafeAccessTokenHandle lpTargetHandle,
+ [In] uint dwDesiredAccess,
+ [In] bool bInheritHandle,
+ [In] uint dwOptions);
+
+#if FEATURE_IMPERSONATION
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateTokenEx (
+ [In] SafeAccessTokenHandle ExistingTokenHandle,
+ [In] TokenAccessLevels DesiredAccess,
+ [In] IntPtr TokenAttributes,
+ [In] SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
+ [In] System.Security.Principal.TokenType TokenType,
+ [In,Out] ref SafeAccessTokenHandle DuplicateTokenHandle );
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool DuplicateTokenEx (
+ [In] SafeAccessTokenHandle hExistingToken,
+ [In] uint dwDesiredAccess,
+ [In] IntPtr lpTokenAttributes, // LPSECURITY_ATTRIBUTES
+ [In] uint ImpersonationLevel,
+ [In] uint TokenType,
+ [In,Out] ref SafeAccessTokenHandle phNewToken);
+#endif
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="EqualDomainSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL IsEqualDomainSid(
+ byte[] sid1,
+ byte[] sid2,
+ out bool result);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern IntPtr GetCurrentProcess();
+
+ [DllImport(KERNEL32, CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr GetCurrentThread();
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetSecurityDescriptorLength",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityDescriptorLength(
+ IntPtr byteArray );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetSecurityInfo",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityInfoByHandle(
+ SafeHandle handle,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ out IntPtr sidOwner,
+ out IntPtr sidGroup,
+ out IntPtr dacl,
+ out IntPtr sacl,
+ out IntPtr securityDescriptor );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetNamedSecurityInfoW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint GetSecurityInfoByName(
+ string name,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ out IntPtr sidOwner,
+ out IntPtr sidGroup,
+ out IntPtr dacl,
+ out IntPtr sacl,
+ out IntPtr securityDescriptor );
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool GetTokenInformation (
+ [In] IntPtr TokenHandle,
+ [In] uint TokenInformationClass,
+ [In] SafeLocalAllocHandle TokenInformation,
+ [In] uint TokenInformationLength,
+ [Out] out uint ReturnLength);
+
+ [DllImport(ADVAPI32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ bool GetTokenInformation (
+ [In] SafeAccessTokenHandle TokenHandle,
+ [In] uint TokenInformationClass,
+ [In] SafeLocalAllocHandle TokenInformation,
+ [In] uint TokenInformationLength,
+ [Out] out uint ReturnLength);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="GetWindowsAccountDomainSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL GetWindowsAccountDomainSid(
+ byte[] sid,
+ [Out] byte[] resultSid,
+ ref /*DWORD*/ uint resultSidLength );
+
+ internal enum SECURITY_IMPERSONATION_LEVEL
+ {
+ Anonymous = 0,
+ Identification = 1,
+ Impersonation = 2,
+ Delegation = 3,
+ }
+
+ // Structures and definitions for Claims that are being introduced in Win8
+ // inside the NTTOken - see winnt.h. They will be surfaced through WindowsIdentity.Claims
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID -> 0x00
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_INVALID = 0;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 -> 0x01
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_INT64 = 1;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 -> 0x02
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_UINT64 = 2;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING -> 0x03
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_STRING = 3;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN -> 0x04
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_FQBN = 4;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_SID -> 0x05
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_SID = 5;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN -> 0x06
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_BOOLEAN = 6;
+
+ // CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING -> 0x10
+ internal const int CLAIM_SECURITY_ATTRIBUTE_TYPE_OCTET_STRING = 16;
+
+ // CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE -> 0x0001
+ internal const int CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE = 1;
+
+ // CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE -> 0x0002
+ internal const int CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE = 2;
+
+ // CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY -> 0x0004
+ internal const int CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY = 4;
+
+ // CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT -> 0x0008
+ internal const int CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT = 8;
+
+ // CLAIM_SECURITY_ATTRIBUTE_DISABLED -> 0x0010
+ internal const int CLAIM_SECURITY_ATTRIBUTE_DISABLED = 16;
+
+ // CLAIM_SECURITY_ATTRIBUTE_MANDATORY -> 0x0020
+ internal const int CLAIM_SECURITY_ATTRIBUTE_MANDATORY = 32;
+
+ internal const int CLAIM_SECURITY_ATTRIBUTE_VALID_FLAGS =
+ CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE
+ | CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
+ | CLAIM_SECURITY_ATTRIBUTE_USE_FOR_DENY_ONLY
+ | CLAIM_SECURITY_ATTRIBUTE_DISABLED_BY_DEFAULT
+ | CLAIM_SECURITY_ATTRIBUTE_DISABLED
+ | CLAIM_SECURITY_ATTRIBUTE_MANDATORY;
+
+
+ [StructLayoutAttribute( LayoutKind.Explicit )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_INFORMATION_V1
+ {
+ // defined as union in CLAIM_SECURITY_ATTRIBUTES_INFORMATION
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pAttributeV1;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential )]
+ internal struct CLAIM_SECURITY_ATTRIBUTES_INFORMATION
+ {
+ /// WORD->unsigned short
+ public ushort Version;
+
+ /// WORD->unsigned short
+ public ushort Reserved;
+
+ /// DWORD->unsigned int
+ public uint AttributeCount;
+
+ /// CLAIM_SECURITY_ATTRIBUTE_V1
+ public CLAIM_SECURITY_ATTRIBUTE_INFORMATION_V1 Attribute;
+ }
+
+ //
+ // Fully-qualified binary name.
+ //
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE
+ {
+ // DWORD64->unsigned __int64
+ public ulong Version;
+
+ // PWSTR->WCHAR*
+ [MarshalAsAttribute( UnmanagedType.LPWStr )]
+ public string Name;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE
+ {
+ /// PVOID->void*
+ public IntPtr pValue;
+
+ /// DWORD->unsigned int
+ public uint ValueLength;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Explicit, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_VALUES_ATTRIBUTE_V1
+ {
+ // PLONG64->__int64*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pInt64;
+
+ // PDWORD64->unsigned __int64*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pUint64;
+
+ // PWSTR*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr ppString;
+
+ // PCLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE->_CLAIM_SECURITY_ATTRIBUTE_FQBN_VALUE*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pFqbn;
+
+ // PCLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE->_CLAIM_SECURITY_ATTRIBUTE_OCTET_STRING_VALUE*
+ [FieldOffsetAttribute( 0 )]
+ public IntPtr pOctetString;
+ }
+
+ [StructLayoutAttribute( LayoutKind.Sequential, CharSet = CharSet.Unicode )]
+ internal struct CLAIM_SECURITY_ATTRIBUTE_V1
+ {
+ // PWSTR->WCHAR*
+ [MarshalAsAttribute( UnmanagedType.LPWStr )]
+ public string Name;
+
+ // WORD->unsigned short
+ public ushort ValueType;
+
+ // WORD->unsigned short
+ public ushort Reserved;
+
+ // DWORD->unsigned int
+ public uint Flags;
+
+ // DWORD->unsigned int
+ public uint ValueCount;
+
+ // struct CLAIM_VALUES - a union of 4 possible values
+ public CLAIM_VALUES_ATTRIBUTE_V1 Values;
+ }
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="IsWellKnownSid",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern BOOL IsWellKnownSid(
+ byte[] sid,
+ int type );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaOpenPolicy",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaOpenPolicy(
+ string systemName,
+ ref LSA_OBJECT_ATTRIBUTES attributes,
+ int accessMask,
+ out SafeLsaPolicyHandle handle
+ );
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LookupPrivilegeValueW",
+ CharSet=CharSet.Auto,
+ SetLastError=true,
+ ExactSpelling=true,
+ BestFitMapping=false)]
+ internal static extern
+ bool LookupPrivilegeValue (
+ [In] string lpSystemName,
+ [In] string lpName,
+ [In,Out] ref LUID Luid);
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupSids",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupSids(
+ SafeLsaPolicyHandle handle,
+ int count,
+ IntPtr[] sids,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle names
+ );
+
+ [DllImport(ADVAPI32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaFreeMemory( IntPtr handle );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupNames",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupNames(
+ SafeLsaPolicyHandle handle,
+ int count,
+ UNICODE_STRING[] names,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle sids
+ );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="LsaLookupNames2",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint LsaLookupNames2(
+ SafeLsaPolicyHandle handle,
+ int flags,
+ int count,
+ UNICODE_STRING[] names,
+ ref SafeLsaMemoryHandle referencedDomains,
+ ref SafeLsaMemoryHandle sids
+ );
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaConnectUntrusted (
+ [In,Out] ref SafeLsaLogonProcessHandle LsaHandle);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaGetLogonSessionData (
+ [In] ref LUID LogonId,
+ [In,Out] ref SafeLsaReturnBufferHandle ppLogonSessionData);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaLogonUser (
+ [In] SafeLsaLogonProcessHandle LsaHandle,
+ [In] ref UNICODE_INTPTR_STRING OriginName,
+ [In] uint LogonType,
+ [In] uint AuthenticationPackage,
+ [In] IntPtr AuthenticationInformation,
+ [In] uint AuthenticationInformationLength,
+ [In] IntPtr LocalGroups,
+ [In] ref TOKEN_SOURCE SourceContext,
+ [In,Out] ref SafeLsaReturnBufferHandle ProfileBuffer,
+ [In,Out] ref uint ProfileBufferLength,
+ [In,Out] ref LUID LogonId,
+ [In,Out] ref SafeAccessTokenHandle Token,
+ [In,Out] ref QUOTA_LIMITS Quotas,
+ [In,Out] ref int SubStatus);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaLookupAuthenticationPackage (
+ [In] SafeLsaLogonProcessHandle LsaHandle,
+ [In] ref UNICODE_INTPTR_STRING PackageName,
+ [In,Out] ref uint AuthenticationPackage);
+
+ [DllImport(SECUR32, CharSet=CharSet.Auto, SetLastError=true)]
+ internal static extern
+ int LsaRegisterLogonProcess (
+ [In] ref UNICODE_INTPTR_STRING LogonProcessName,
+ [In,Out] ref SafeLsaLogonProcessHandle LsaHandle,
+ [In,Out] ref IntPtr SecurityMode);
+
+ [DllImport(SECUR32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaDeregisterLogonProcess(IntPtr handle);
+
+ [DllImport(ADVAPI32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaClose( IntPtr handle );
+
+ [DllImport(SECUR32, SetLastError=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int LsaFreeReturnBuffer(IntPtr handle);
+
+#if FEATURE_IMPERSONATION
+ [DllImport (ADVAPI32, CharSet=CharSet.Unicode, SetLastError=true)]
+ internal static extern
+ bool OpenProcessToken (
+ [In] IntPtr ProcessToken,
+ [In] TokenAccessLevels DesiredAccess,
+ [Out] out SafeAccessTokenHandle TokenHandle);
+#endif
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="SetNamedSecurityInfoW",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint SetSecurityInfoByName(
+ string name,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ byte[] owner,
+ byte[] group,
+ byte[] dacl,
+ byte[] sacl );
+
+ [DllImport(
+ ADVAPI32,
+ EntryPoint="SetSecurityInfo",
+ CallingConvention=CallingConvention.Winapi,
+ SetLastError=true,
+ ExactSpelling=true,
+ CharSet=CharSet.Unicode)]
+ internal static extern /*DWORD*/ uint SetSecurityInfoByHandle(
+ SafeHandle handle,
+ /*DWORD*/ uint objectType,
+ /*DWORD*/ uint securityInformation,
+ byte[] owner,
+ byte[] group,
+ byte[] dacl,
+ byte[] sacl );
+
+ // Fusion APIs
+#if FEATURE_FUSION
+ [DllImport(MSCORWKS, CharSet=CharSet.Unicode)]
+ internal static extern int CreateAssemblyNameObject(out IAssemblyName ppEnum, String szAssemblyName, uint dwFlags, IntPtr pvReserved);
+
+ [DllImport(MSCORWKS, CharSet=CharSet.Auto)]
+ internal static extern int CreateAssemblyEnum(out IAssemblyEnum ppEnum, IApplicationContext pAppCtx, IAssemblyName pName, uint dwFlags, IntPtr pvReserved);
+#endif // FEATURE_FUSION
+
+#if FEATURE_CORECLR
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal unsafe static extern int WideCharToMultiByte(
+ int CodePage,
+ UInt32 dwFlags,
+ char* lpWideCharStr,
+ int cchWideChar,
+ byte* lpMultiByteStr,
+ int cchMultiByte,
+ char* lpDefaultChar,
+ bool* lpUsedDefaultChar);
+
+ [DllImport(KERNEL32, CharSet=CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal unsafe static extern int MultiByteToWideChar(
+ int CodePage,
+ UInt32 dwFlags,
+ byte* lpMultiByteStr,
+ int cchMultiByte,
+ char* lpWideCharStr,
+ int cchWideChar);
+#endif // FEATURE_CORECLR
+
+ [DllImport(KERNEL32, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal extern static bool QueryUnbiasedInterruptTime(out ulong UnbiasedTime);
+
+#if FEATURE_CORECLR
+#if FEATURE_PAL
+ [DllImport(KERNEL32, EntryPoint = "PAL_Random")]
+ internal extern static bool Random(bool bStrong,
+ [Out, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, int length);
+#else
+ private const int BCRYPT_USE_SYSTEM_PREFERRED_RNG = 0x00000002;
+
+ [DllImport("BCrypt.dll", CharSet = CharSet.Unicode)]
+ private static extern uint BCryptGenRandom(IntPtr hAlgorithm, [In, Out] byte[] pbBuffer, int cbBuffer, int dwFlags);
+
+ internal static void Random(bool bStrong, byte[] buffer, int length)
+ {
+ uint status = BCryptGenRandom(IntPtr.Zero, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG);
+ if (status != STATUS_SUCCESS)
+ {
+ if (status == STATUS_NO_MEMORY)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+#endif
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System.Private.CoreLib.txt b/src/mscorlib/src/System.Private.CoreLib.txt
new file mode 100644
index 0000000000..0369344328
--- /dev/null
+++ b/src/mscorlib/src/System.Private.CoreLib.txt
@@ -0,0 +1,3495 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+; These are the managed resources for mscorlib.dll.
+; See those first three bytes in the file? This is in UTF-8. Leave the
+; Unicode byte order mark (U+FEFF) written in UTF-8 at the start of this file.
+
+; For resource info, see the ResourceManager documentation and the ResGen tool,
+; which is a managed app using ResourceWriter.
+; ResGen now supports limited preprocessing of txt files, you can use
+; #if SYMBOL and #if !SYMBOL to control what sets of resources are included in
+; the resulting resources.
+
+; The naming scheme is: [Namespace.] ExceptionName _ Reason
+; We'll suppress "System." where possible.
+; Examples:
+; Argument_Null
+; Reflection.TargetInvokation_someReason
+
+; Usage Notes:
+; * Keep exceptions in alphabetical order by package
+; * A single space may exist on either side of the equal sign.
+; * Follow the naming conventions.
+; * Any lines starting with a '#' or ';' are ignored
+; * Equal signs aren't legal characters for keys, but may occur in values.
+; * Correctly punctuate all sentences. Most resources should end in a period.
+; Remember, your mother will probably read some of these messages.
+; * You may use " (quote), \n and \t. Use \\ for a single '\' character.
+; * String inserts work. i.e., BadNumber_File = Wrong number in file "{0}".
+
+; Real words, used by code like Environment.StackTrace
+#if INCLUDE_RUNTIME
+Word_At = at
+StackTrace_InFileLineNumber = in {0}:line {1}
+UnknownError_Num = Unknown error "{0}".
+AllocatedFrom = Allocated from:
+
+; Note this one is special, used as a divider between stack traces!
+Exception_EndOfInnerExceptionStack = --- End of inner exception stack trace ---
+Exception_WasThrown = Exception of type '{0}' was thrown.
+
+; The following are used in the implementation of ExceptionDispatchInfo
+Exception_EndStackTraceFromPreviousThrow = --- End of stack trace from previous location where exception was thrown ---
+
+Arg_ParamName_Name = Parameter name: {0}
+ArgumentOutOfRange_ActualValue = Actual value was {0}.
+
+NoDebugResources = [{0}]\r\nArguments: {1}\r\nDebugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version={2}&File={3}&Key={4}
+#endif // INCLUDE_RUNTIME
+
+#if !FEATURE_CORECLR
+UnknownError = Unknown error.
+#endif // !FEATURE_CORECLR
+
+#if INCLUDE_DEBUG
+
+; For code contracts
+AssumptionFailed = Assumption failed.
+AssumptionFailed_Cnd = Assumption failed: {0}
+AssertionFailed = Assertion failed.
+AssertionFailed_Cnd = Assertion failed: {0}
+PreconditionFailed = Precondition failed.
+PreconditionFailed_Cnd = Precondition failed: {0}
+PostconditionFailed = Postcondition failed.
+PostconditionFailed_Cnd = Postcondition failed: {0}
+PostconditionOnExceptionFailed = Postcondition failed after throwing an exception.
+PostconditionOnExceptionFailed_Cnd = Postcondition failed after throwing an exception: {0}
+InvariantFailed = Invariant failed.
+InvariantFailed_Cnd = Invariant failed: {0}
+MustUseCCRewrite = An assembly (probably "{1}") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.{0} and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. \r\nAfter the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL.
+
+; Access Control
+#if FEATURE_MACL
+AccessControl_MustSpecifyContainerAcl = The named parameter must be a container ACL.
+AccessControl_MustSpecifyLeafObjectAcl = The named parameter must be a non-container ACL.
+AccessControl_AclTooLong = Length of the access control list exceed the allowed maximum.
+AccessControl_MustSpecifyDirectoryObjectAcl = The named parameter must be a directory-object ACL.
+AccessControl_MustSpecifyNonDirectoryObjectAcl = The named parameter must be a non-directory-object ACL.
+AccessControl_InvalidSecurityDescriptorRevision = Security descriptor with revision other than '1' are not legal.
+AccessControl_InvalidSecurityDescriptorSelfRelativeForm = Security descriptor must be in the self-relative form.
+AccessControl_NoAssociatedSecurity = Unable to perform a security operation on an object that has no associated security. This can happen when trying to get an ACL of an anonymous kernel object.
+AccessControl_InvalidHandle = The supplied handle is invalid. This can happen when trying to set an ACL on an anonymous kernel object.
+AccessControl_UnexpectedError = Method failed with unexpected error code {0}.
+AccessControl_InvalidSidInSDDLString = The SDDL string contains an invalid sid or a sid that cannot be translated.
+AccessControl_InvalidOwner = The security identifier is not allowed to be the owner of this object.
+AccessControl_InvalidGroup = The security identifier is not allowed to be the primary group of this object.
+AccessControl_InvalidAccessRuleType = The access rule is not the correct type.
+AccessControl_InvalidAuditRuleType = The audit rule is not the correct type.
+#endif // FEATURE_MACL
+
+; Identity Reference Library
+#if FEATURE_IDENTITY_REFERENCE
+IdentityReference_IdentityNotMapped = Some or all identity references could not be translated.
+IdentityReference_MustBeIdentityReference = The targetType parameter must be of IdentityReference type.
+IdentityReference_AccountNameTooLong = Account name is too long.
+IdentityReference_DomainNameTooLong = Domain name is too long.
+IdentityReference_InvalidNumberOfSubauthorities = The number of sub-authorities must not exceed {0}.
+IdentityReference_IdentifierAuthorityTooLarge = The size of the identifier authority must not exceed 6 bytes.
+IdentityReference_InvalidSidRevision = SIDs with revision other than '1' are not supported.
+IdentityReference_CannotCreateLogonIdsSid = Well-known SIDs of type LogonIdsSid cannot be created.
+IdentityReference_DomainSidRequired = The domainSid parameter must be specified for creating well-known SID of type {0}.
+IdentityReference_NotAWindowsDomain = The domainSid parameter is not a valid Windows domain SID.
+#endif // FEATURE_IDENTITY_REFERENCE
+
+; AccessException
+Acc_CreateGeneric = Cannot create a type for which Type.ContainsGenericParameters is true.
+Acc_CreateAbst = Cannot create an abstract class.
+Acc_CreateInterface = Cannot create an instance of an interface.
+Acc_NotClassInit = Type initializer was not callable.
+Acc_CreateGenericEx = Cannot create an instance of {0} because Type.ContainsGenericParameters is true.
+Acc_CreateArgIterator = Cannot dynamically create an instance of ArgIterator.
+Acc_CreateAbstEx = Cannot create an instance of {0} because it is an abstract class.
+Acc_CreateInterfaceEx = Cannot create an instance of {0} because it is an interface.
+Acc_CreateVoid = Cannot dynamically create an instance of System.Void.
+Acc_ReadOnly = Cannot set a constant field.
+Acc_RvaStatic = SkipVerification permission is needed to modify an image-based (RVA) static field.
+Access_Void = Cannot create an instance of void.
+
+; ArgumentException
+Arg_TypedReference_Null = The TypedReference must be initialized.
+Argument_AddingDuplicate__ = Item has already been added. Key in dictionary: '{0}' Key being added: '{1}'
+Argument_AddingDuplicate = An item with the same key has already been added.
+#if FEATURE_CORECLR
+Argument_AddingDuplicateWithKey = An item with the same key has already been added. Key: {0}
+#endif // FEATURE_CORECLR
+Argument_MethodDeclaringTypeGenericLcg = Method '{0}' has a generic declaring type '{1}'. Explicitly provide the declaring type to GetTokenFor.
+Argument_MethodDeclaringTypeGeneric = Cannot resolve method {0} because the declaring type of the method handle {1} is generic. Explicitly provide the declaring type to GetMethodFromHandle.
+Argument_FieldDeclaringTypeGeneric = Cannot resolve field {0} because the declaring type of the field handle {1} is generic. Explicitly provide the declaring type to GetFieldFromHandle.
+Argument_ApplicationTrustShouldHaveIdentity = An ApplicationTrust must have an application identity before it can be persisted.
+Argument_ConversionOverflow = Conversion buffer overflow.
+Argument_CodepageNotSupported = {0} is not a supported code page.
+Argument_CultureNotSupported = Culture is not supported.
+Argument_CultureInvalidIdentifier = {0} is an invalid culture identifier.
+Argument_OneOfCulturesNotSupported = Culture name {0} or {1} is not supported.
+Argument_CultureIetfNotSupported = Culture IETF Name {0} is not a recognized IETF name.
+Argument_CultureIsNeutral = Culture ID {0} (0x{0:X4}) is a neutral culture; a region cannot be created from it.
+Argument_InvalidNeutralRegionName = The region name {0} should not correspond to neutral culture; a specific culture name is required.
+Argument_InvalidGenericInstArray = Generic arguments must be provided for each generic parameter and each generic argument must be a RuntimeType.
+Argument_GenericArgsCount = The number of generic arguments provided doesn't equal the arity of the generic type definition.
+Argument_CultureInvalidFormat = Culture '{0}' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture.
+Argument_CompareOptionOrdinal = CompareOption.Ordinal cannot be used with other options.
+Argument_CustomCultureCannotBePassedByNumber = Customized cultures cannot be passed by LCID, only by name.
+Argument_EncodingConversionOverflowChars = The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'.
+Argument_EncodingConversionOverflowBytes = The output byte buffer is too small to contain the encoded data, encoding '{0}' fallback '{1}'.
+Argument_EncoderFallbackNotEmpty = Must complete Convert() operation or call Encoder.Reset() before calling GetBytes() or GetByteCount(). Encoder '{0}' fallback '{1}'.
+Argument_EmptyFileName = Empty file name is not legal.
+Argument_EmptyPath = Empty path name is not legal.
+Argument_EmptyName = Empty name is not legal.
+Argument_ImplementIComparable = At least one object must implement IComparable.
+Argument_InvalidType = The type of arguments passed into generic comparer methods is invalid.
+Argument_InvalidTypeForCA=Cannot build type parameter for custom attribute with a type that does not support the AssemblyQualifiedName property. The type instance supplied was of type '{0}'.
+Argument_IllegalEnvVarName = Environment variable name cannot contain equal character.
+Argument_IllegalAppId = Application identity does not have same number of components as manifest paths.
+Argument_IllegalAppBase = The application base specified is not valid.
+Argument_UnableToParseManifest = Unexpected error while parsing the specified manifest.
+Argument_IllegalAppIdMismatch = Application identity does not match identities in manifests.
+Argument_InvalidAppId = Invalid identity: no deployment or application identity specified.
+Argument_InvalidGenericArg = The generic type parameter was not valid
+Argument_InvalidArrayLength = Length of the array must be {0}.
+Argument_InvalidArrayType = Target array type is not compatible with the type of items in the collection.
+Argument_InvalidAppendMode = Append access can be requested only in write-only mode.
+Argument_InvalidEnumValue = The value '{0}' is not valid for this usage of the type {1}.
+Argument_EnumIsNotIntOrShort = The underlying type of enum argument must be Int32 or Int16.
+Argument_InvalidEnum = The Enum type should contain one and only one instance field.
+Argument_InvalidKeyStore = '{0}' is not a valid KeyStore name.
+Argument_InvalidFileMode&AccessCombo = Combining FileMode: {0} with FileAccess: {1} is invalid.
+Argument_InvalidFileMode&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid.
+Argument_InvalidFileModeTruncate&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid. FileMode.Truncate is valid only when used with FileSystemRights.Write.
+Argument_InvalidFlag = Value of flags is invalid.
+Argument_InvalidAnyFlag = No flags can be set.
+Argument_InvalidHandle = The handle is invalid.
+Argument_InvalidRegistryKeyPermissionCheck = The specified RegistryKeyPermissionCheck value is invalid.
+Argument_InvalidRegistryOptionsCheck = The specified RegistryOptions value is invalid.
+Argument_InvalidRegistryViewCheck = The specified RegistryView value is invalid.
+Argument_InvalidSubPath = The directory specified, '{0}', is not a subdirectory of '{1}'.
+Argument_NoRegionInvariantCulture = There is no region associated with the Invariant Culture (Culture ID: 0x7F).
+Argument_ResultCalendarRange = The result is out of the supported range for this calendar. The result should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive.
+Argument_ResultIslamicCalendarRange = The date is out of the supported range for the Islamic calendar. The date should be greater than July 18th, 622 AD (Gregorian date).
+Argument_NeverValidGenericArgument = The type '{0}' may not be used as a type argument.
+Argument_NotEnoughGenArguments = The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter.
+Argument_NullFullTrustAssembly = A null StrongName was found in the full trust assembly list.
+Argument_GenConstraintViolation = GenericArguments[{0}], '{1}', on '{2}' violates the constraint of type '{3}'.
+Argument_InvalidToken = Token {0:x} is not valid in the scope of module {1}.
+Argument_InvalidTypeToken = Token {0:x} is not a valid Type token.
+Argument_ResolveType = Token {0:x} is not a valid Type token in the scope of module {1}.
+Argument_ResolveMethod = Token {0:x} is not a valid MethodBase token in the scope of module {1}.
+Argument_ResolveField = Token {0:x} is not a valid FieldInfo token in the scope of module {1}.
+Argument_ResolveMember = Token {0:x} is not a valid MemberInfo token in the scope of module {1}.
+Argument_ResolveString = Token {0:x} is not a valid string token in the scope of module {1}.
+Argument_ResolveModuleType = Token {0} resolves to the special module type representing this module.
+Argument_ResolveMethodHandle = Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase.
+Argument_ResolveFieldHandle = Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo.
+Argument_ResourceScopeWrongDirection = Resource type in the ResourceScope enum is going from a more restrictive resource type to a more general one. From: "{0}" To: "{1}"
+Argument_BadResourceScopeTypeBits = Unknown value for the ResourceScope: {0} Too many resource type bits may be set.
+Argument_BadResourceScopeVisibilityBits = Unknown value for the ResourceScope: {0} Too many resource visibility bits may be set.
+Argument_WaitHandleNameTooLong = The name can be no more than {0} characters in length.
+Argument_EnumTypeDoesNotMatch = The argument type, '{0}', is not the same as the enum type '{1}'.
+InvalidOperation_MethodBuilderBaked = The signature of the MethodBuilder can no longer be modified because an operation on the MethodBuilder caused the methodDef token to be created. For example, a call to SetCustomAttribute requires the methodDef token to emit the CustomAttribute token.
+InvalidOperation_GenericParametersAlreadySet = The generic parameters are already defined on this MethodBuilder.
+Arg_AccessException = Cannot access member.
+Arg_AppDomainUnloadedException = Attempted to access an unloaded AppDomain.
+Arg_ApplicationException = Error in the application.
+Arg_ArgumentOutOfRangeException = Specified argument was out of the range of valid values.
+Arg_ArithmeticException = Overflow or underflow in the arithmetic operation.
+Arg_ArrayLengthsDiffer = Array lengths must be the same.
+Arg_ArrayPlusOffTooSmall = Destination array is not long enough to copy all the items in the collection. Check array index and length.
+Arg_ArrayTypeMismatchException = Attempted to access an element as a type incompatible with the array.
+Arg_BadImageFormatException = Format of the executable (.exe) or library (.dll) is invalid.
+Argument_BadImageFormatExceptionResolve = A BadImageFormatException has been thrown while parsing the signature. This is likely due to lack of a generic context. Ensure genericTypeArguments and genericMethodArguments are provided and contain enough context.
+Arg_BufferTooSmall = Not enough space available in the buffer.
+Arg_CATypeResolutionFailed = Failed to resolve type from string "{0}" which was embedded in custom attribute blob.
+Arg_CannotHaveNegativeValue = String cannot contain a minus sign if the base is not 10.
+Arg_CannotUnloadAppDomainException = Attempt to unload the AppDomain failed.
+Arg_CannotMixComparisonInfrastructure = The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other.
+Arg_ContextMarshalException = Attempted to marshal an object across a context boundary.
+Arg_DataMisalignedException = A datatype misalignment was detected in a load or store instruction.
+Arg_DevicesNotSupported = FileStream will not open Win32 devices such as disk partitions and tape drives. Avoid use of "\\\\.\\" in the path.
+Arg_DuplicateWaitObjectException = Duplicate objects in argument.
+Arg_EntryPointNotFoundException = Entry point was not found.
+Arg_DllNotFoundException = Dll was not found.
+Arg_ExecutionEngineException = Internal error in the runtime.
+Arg_FieldAccessException = Attempted to access a field that is not accessible by the caller.
+Arg_FileIsDirectory_Name = The target file "{0}" is a directory, not a file.
+Arg_FormatException = One of the identified items was in an invalid format.
+Arg_IndexOutOfRangeException = Index was outside the bounds of the array.
+Arg_InsufficientExecutionStackException = Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.
+Arg_InvalidCastException = Specified cast is not valid.
+Arg_InvalidOperationException = Operation is not valid due to the current state of the object.
+Arg_CorruptedCustomCultureFile = The file of the custom culture {0} is corrupt. Try to unregister this culture.
+Arg_InvokeMember = InvokeMember can be used only for COM objects.
+Arg_InvalidNeutralResourcesLanguage_Asm_Culture = The NeutralResourcesLanguageAttribute on the assembly "{0}" specifies an invalid culture name: "{1}".
+Arg_InvalidNeutralResourcesLanguage_FallbackLoc = The NeutralResourcesLanguageAttribute specifies an invalid or unrecognized ultimate resource fallback location: "{0}".
+Arg_InvalidSatelliteContract_Asm_Ver = Satellite contract version attribute on the assembly '{0}' specifies an invalid version: {1}.
+Arg_MethodAccessException = Attempt to access the method failed.
+Arg_MethodAccessException_WithMethodName = Attempt to access the method "{0}" on type "{1}" failed.
+Arg_MethodAccessException_WithCaller = Attempt by security transparent method '{0}' to access security critical method '{1}' failed.
+Arg_MissingFieldException = Attempted to access a non-existing field.
+Arg_MissingMemberException = Attempted to access a missing member.
+Arg_MissingMethodException = Attempted to access a missing method.
+Arg_MulticastNotSupportedException = Attempted to add multiple callbacks to a delegate that does not support multicast.
+Arg_NotFiniteNumberException = Number encountered was not a finite quantity.
+Arg_NotSupportedException = Specified method is not supported.
+Arg_UnboundGenParam = Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
+Arg_UnboundGenField = Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.
+Arg_NotGenericParameter = Method may only be called on a Type for which Type.IsGenericParameter is true.
+Arg_GenericParameter = Method must be called on a Type for which Type.IsGenericParameter is false.
+Arg_NotGenericTypeDefinition = {0} is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true.
+Arg_NotGenericMethodDefinition = {0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.
+Arg_BadLiteralFormat = Encountered an invalid type for a default value.
+Arg_MissingActivationArguments = The AppDomainSetup must specify the activation arguments for this call.
+Argument_BadParameterTypeForCAB = Cannot emit a CustomAttribute with argument of type {0}.
+Argument_InvalidMemberForNamedArgument = The member must be either a field or a property.
+Argument_InvalidTypeName = The name of the type is invalid.
+
+; Note - don't change the NullReferenceException default message. This was
+; negotiated carefully with the VB team to avoid saying "null" or "nothing".
+Arg_NullReferenceException = Object reference not set to an instance of an object.
+
+Arg_AccessViolationException = Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
+Arg_OverflowException = Arithmetic operation resulted in an overflow.
+Arg_PathGlobalRoot = Paths that begin with \\\\?\\GlobalRoot are internal to the kernel and should not be opened by managed applications.
+Arg_PathIllegal = The path is not of a legal form.
+Arg_PathIllegalUNC = The UNC path should be of the form \\\\server\\share.
+Arg_RankException = Attempted to operate on an array with the incorrect number of dimensions.
+Arg_RankMultiDimNotSupported = Only single dimensional arrays are supported for the requested action.
+Arg_NonZeroLowerBound = The lower bound of target array must be zero.
+Arg_RegSubKeyValueAbsent = No value exists with that name.
+Arg_ResourceFileUnsupportedVersion = The ResourceReader class does not know how to read this version of .resources files. Expected version: {0} This file: {1}
+Arg_ResourceNameNotExist = The specified resource name "{0}" does not exist in the resource file.
+Arg_SecurityException = Security error.
+Arg_SerializationException = Serialization error.
+Arg_StackOverflowException = Operation caused a stack overflow.
+Arg_SurrogatesNotAllowedAsSingleChar = Unicode surrogate characters must be written out as pairs together in the same call, not individually. Consider passing in a character array instead.
+Arg_SynchronizationLockException = Object synchronization method was called from an unsynchronized block of code.
+Arg_RWLockRestoreException = ReaderWriterLock.RestoreLock was called without releasing all locks acquired since the call to ReleaseLock.
+Arg_SystemException = System error.
+Arg_TimeoutException = The operation has timed out.
+Arg_UnauthorizedAccessException = Attempted to perform an unauthorized operation.
+Arg_ArgumentException = Value does not fall within the expected range.
+Arg_DirectoryNotFoundException = Attempted to access a path that is not on the disk.
+Arg_DriveNotFoundException = Attempted to access a drive that is not available.
+Arg_EndOfStreamException = Attempted to read past the end of the stream.
+Arg_HexStyleNotSupported = The number style AllowHexSpecifier is not supported on floating point data types.
+Arg_IOException = I/O error occurred.
+Arg_InvalidHexStyle = With the AllowHexSpecifier bit set in the enum bit field, the only other valid bits that can be combined into the enum value must be a subset of those in HexNumber.
+Arg_KeyNotFound = The given key was not present in the dictionary.
+Argument_InvalidNumberStyles = An undefined NumberStyles value is being used.
+Argument_InvalidDateTimeStyles = An undefined DateTimeStyles value is being used.
+Argument_InvalidTimeSpanStyles = An undefined TimeSpanStyles value is being used.
+Argument_DateTimeOffsetInvalidDateTimeStyles = The DateTimeStyles value 'NoCurrentDateDefault' is not allowed when parsing DateTimeOffset.
+Argument_NativeResourceAlreadyDefined = Native resource has already been defined.
+Argument_BadObjRef = Invalid ObjRef provided to '{0}'.
+Argument_InvalidCultureName = Culture name '{0}' is not supported.
+Argument_NameTooLong = The name '{0}' is too long to be a Culture or Region name, which is limited to {1} characters.
+Argument_NameContainsInvalidCharacters = The name '{0}' contains characters that are not valid for a Culture or Region.
+Argument_InvalidRegionName = Region name '{0}' is not supported.
+Argument_CannotCreateTypedReference = Cannot use function evaluation to create a TypedReference object.
+Arg_ArrayZeroError = Array must not be of length zero.
+Arg_BogusIComparer = Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: '{0}'.
+Arg_CreatInstAccess = Cannot specify both CreateInstance and another access type.
+Arg_CryptographyException = Error occurred during a cryptographic operation.
+Arg_DateTimeRange = Combination of arguments to the DateTime constructor is out of the legal range.
+Arg_DecBitCtor = Decimal byte array constructor requires an array of length four containing valid decimal bytes.
+Arg_DlgtTargMeth = Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
+Arg_DlgtTypeMis = Delegates must be of the same type.
+Arg_DlgtNullInst = Delegate to an instance method cannot have null 'this'.
+Arg_DllInitFailure = One machine may not have remote administration enabled, or both machines may not be running the remote registry service.
+Arg_EmptyArray = Array may not be empty.
+Arg_EmptyOrNullArray = Array may not be empty or null.
+Arg_EmptyCollection = Collection must not be empty.
+Arg_EmptyOrNullString = String may not be empty or null.
+Argument_ItemNotExist = The specified item does not exist in this KeyedCollection.
+Argument_EncodingNotSupported = '{0}' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
+Argument_FallbackBufferNotEmpty = Cannot change fallback when buffer is not empty. Previous Convert() call left data in the fallback buffer.
+Argument_InvalidCodePageConversionIndex = Unable to translate Unicode character \\u{0:X4} at index {1} to specified code page.
+Argument_InvalidCodePageBytesIndex = Unable to translate bytes {0} at index {1} from specified code page to Unicode.
+Argument_RecursiveFallback = Recursive fallback not allowed for character \\u{0:X4}.
+Argument_RecursiveFallbackBytes = Recursive fallback not allowed for bytes {0}.
+Arg_EnumAndObjectMustBeSameType = Object must be the same type as the enum. The type passed in was '{0}'; the enum type was '{1}'.
+Arg_EnumIllegalVal = Illegal enum value: {0}.
+Arg_EnumNotSingleFlag = Must set exactly one flag.
+Arg_EnumAtLeastOneFlag = Must set at least one flag.
+Arg_EnumUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object must be a String. Type passed in was '{0}'; the enum underlying type was '{1}'.
+Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object. Type passed in was '{0}'; the enum underlying type was '{1}'.
+Arg_EnumMustHaveUnderlyingValueField = All enums must have an underlying value__ field.
+Arg_COMAccess = Must specify property Set or Get or method call for a COM Object.
+Arg_COMPropSetPut = Only one of the following binding flags can be set: BindingFlags.SetProperty, BindingFlags.PutDispProperty, BindingFlags.PutRefDispProperty.
+Arg_FldSetGet = Cannot specify both Get and Set on a field.
+Arg_PropSetGet = Cannot specify both Get and Set on a property.
+Arg_CannotBeNaN = TimeSpan does not accept floating point Not-a-Number values.
+Arg_FldGetPropSet = Cannot specify both GetField and SetProperty.
+Arg_FldSetPropGet = Cannot specify both SetField and GetProperty.
+Arg_FldSetInvoke = Cannot specify Set on a Field and Invoke on a method.
+Arg_FldGetArgErr = No arguments can be provided to Get a field value.
+Arg_FldSetArgErr = Only the field value can be specified to set a field value.
+Arg_GetMethNotFnd = Property Get method was not found.
+Arg_GuidArrayCtor = Byte array for GUID must be exactly {0} bytes long.
+Arg_HandleNotAsync = Handle does not support asynchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened synchronously (that is, it was not opened for overlapped I/O).
+Arg_HandleNotSync = Handle does not support synchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened asynchronously (that is, it was opened explicitly for overlapped I/O).
+Arg_HTCapacityOverflow = Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.
+Arg_IndexMustBeInt = All indexes must be of type Int32.
+Arg_InvalidConsoleColor = The ConsoleColor enum value was not defined on that enum. Please use a defined color from the enum.
+Arg_InvalidFileAttrs = Invalid File or Directory attributes value.
+Arg_InvalidHandle = Invalid handle.
+Arg_InvalidTypeInSignature = The signature Type array contains some invalid type (i.e. null, void)
+Arg_InvalidTypeInRetType = The return Type contains some invalid type (i.e. null, ByRef)
+Arg_EHClauseNotFilter = This ExceptionHandlingClause is not a filter.
+Arg_EHClauseNotClause = This ExceptionHandlingClause is not a clause.
+Arg_ReflectionOnlyCA = It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType (see Assembly.ReflectionOnly) -- use CustomAttributeData instead.
+Arg_ReflectionOnlyInvoke = It is illegal to invoke a method on a Type loaded via ReflectionOnlyGetType.
+Arg_ReflectionOnlyField = It is illegal to get or set the value on a field on a Type loaded via ReflectionOnlyGetType.
+Arg_MemberInfoNullModule = The Module object containing the member cannot be null.
+Arg_ParameterInfoNullMember = The MemberInfo object defining the parameter cannot be null.
+Arg_ParameterInfoNullModule = The Module object containing the parameter cannot be null.
+Arg_AssemblyNullModule = The manifest module of the assembly cannot be null.
+Arg_LongerThanSrcArray = Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
+Arg_LongerThanDestArray = Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
+Arg_LowerBoundsMustMatch = The arrays' lower bounds must be identical.
+Arg_MustBeBoolean = Object must be of type Boolean.
+Arg_MustBeByte = Object must be of type Byte.
+Arg_MustBeChar = Object must be of type Char.
+Arg_MustBeDateTime = Object must be of type DateTime.
+Arg_MustBeDateTimeOffset = Object must be of type DateTimeOffset.
+Arg_MustBeDecimal = Object must be of type Decimal.
+Arg_MustBeDelegate = Type must derive from Delegate.
+Arg_MustBeDouble = Object must be of type Double.
+Arg_MustBeDriveLetterOrRootDir = Object must be a root directory ("C:\\") or a drive letter ("C").
+Arg_MustBeEnum = Type provided must be an Enum.
+Arg_MustBeEnumBaseTypeOrEnum = The value passed in must be an enum base or an underlying type for an enum, such as an Int32.
+Arg_MustBeGuid = Object must be of type GUID.
+Arg_MustBeIdentityReferenceType = Type must be an IdentityReference, such as NTAccount or SecurityIdentifier.
+Arg_MustBeInterface = Type passed must be an interface.
+Arg_MustBeInt16 = Object must be of type Int16.
+Arg_MustBeInt32 = Object must be of type Int32.
+Arg_MustBeInt64 = Object must be of type Int64.
+Arg_MustBePrimArray = Object must be an array of primitives.
+Arg_MustBePointer = Type must be a Pointer.
+Arg_MustBeStatic = Method must be a static method.
+Arg_MustBeString = Object must be of type String.
+Arg_MustBeStringPtrNotAtom = The pointer passed in as a String must not be in the bottom 64K of the process's address space.
+Arg_MustBeSByte = Object must be of type SByte.
+Arg_MustBeSingle = Object must be of type Single.
+Arg_MustBeTimeSpan = Object must be of type TimeSpan.
+Arg_MustBeType = Type must be a type provided by the runtime.
+Arg_MustBeUInt16 = Object must be of type UInt16.
+Arg_MustBeUInt32 = Object must be of type UInt32.
+Arg_MustBeUInt64 = Object must be of type UInt64.
+Arg_MustBeVersion = Object must be of type Version.
+Arg_MustBeTrue = Argument must be true.
+Arg_MustAllBeRuntimeType = At least one type argument is not a runtime type.
+Arg_NamedParamNull = Named parameter value must not be null.
+Arg_NamedParamTooBig = Named parameter array cannot be bigger than argument array.
+Arg_Need1DArray = Array was not a one-dimensional array.
+Arg_Need2DArray = Array was not a two-dimensional array.
+Arg_Need3DArray = Array was not a three-dimensional array.
+Arg_NeedAtLeast1Rank = Must provide at least one rank.
+Arg_NoDefCTor = No parameterless constructor defined for this object.
+Arg_BitArrayTypeUnsupported = Only supported array types for CopyTo on BitArrays are Boolean[], Int32[] and Byte[].
+Arg_DivideByZero = Attempted to divide by zero.
+Arg_NoAccessSpec = Must specify binding flags describing the invoke operation required (BindingFlags.InvokeMethod CreateInstance GetField SetField GetProperty SetProperty).
+Arg_NoStaticVirtual = Method cannot be both static and virtual.
+Arg_NotFoundIFace = Interface not found.
+Arg_ObjObjEx = Object of type '{0}' cannot be converted to type '{1}'.
+Arg_ObjObj = Object type cannot be converted to target type.
+Arg_FieldDeclTarget = Field '{0}' defined on type '{1}' is not a field on the target object which is of type '{2}'.
+Arg_OleAutDateInvalid = Not a legal OleAut date.
+Arg_OleAutDateScale = OleAut date did not convert to a DateTime correctly.
+Arg_PlatformNotSupported = Operation is not supported on this platform.
+Arg_PlatformSecureString = SecureString is only supported on Windows 2000 SP3 and higher platforms.
+Arg_ParmCnt = Parameter count mismatch.
+Arg_ParmArraySize = Must specify one or more parameters.
+Arg_Path2IsRooted = Second path fragment must not be a drive or UNC name.
+Arg_PathIsVolume = Path must not be a drive.
+Arg_PrimWiden = Cannot widen from source type to target type either because the source type is a not a primitive type or the conversion cannot be accomplished.
+Arg_NullIndex = Arrays indexes must be set to an object instance.
+Arg_VarMissNull = Missing parameter does not have a default value.
+Arg_PropSetInvoke = Cannot specify Set on a property and Invoke on a method.
+Arg_PropNotFound = Could not find the specified property.
+Arg_RankIndices = Indices length does not match the array rank.
+Arg_RanksAndBounds = Number of lengths and lowerBounds must match.
+Arg_RegSubKeyAbsent = Cannot delete a subkey tree because the subkey does not exist.
+Arg_RemoveArgNotFound = Cannot remove the specified item because it was not found in the specified Collection.
+Arg_RegKeyDelHive = Cannot delete a registry hive's subtree.
+Arg_RegKeyNoRemoteConnect = No remote connection to '{0}' while trying to read the registry.
+Arg_RegKeyOutOfRange = Registry HKEY was out of the legal range.
+Arg_RegKeyNotFound = The specified registry key does not exist.
+Arg_RegKeyStrLenBug = Registry key names should not be greater than 255 characters.
+Arg_RegValStrLenBug = Registry value names should not be greater than 16,383 characters.
+Arg_RegBadKeyKind = The specified RegistryValueKind is an invalid value.
+Arg_RegGetOverflowBug = RegistryKey.GetValue does not allow a String that has a length greater than Int32.MaxValue.
+Arg_RegSetMismatchedKind = The type of the value object did not match the specified RegistryValueKind or the object could not be properly converted.
+Arg_RegSetBadArrType = RegistryKey.SetValue does not support arrays of type '{0}'. Only Byte[] and String[] are supported.
+Arg_RegSetStrArrNull = RegistryKey.SetValue does not allow a String[] that contains a null String reference.
+Arg_RegInvalidKeyName = Registry key name must start with a valid base key name.
+Arg_ResMgrNotResSet = Type parameter must refer to a subclass of ResourceSet.
+Arg_SetMethNotFnd = Property set method not found.
+Arg_TypeRefPrimitve = TypedReferences cannot be redefined as primitives.
+Arg_UnknownTypeCode = Unknown TypeCode value.
+Arg_VersionString = Version string portion was too short or too long.
+Arg_NoITypeInfo = Specified TypeInfo was invalid because it did not support the ITypeInfo interface.
+Arg_NoITypeLib = Specified TypeLib was invalid because it did not support the ITypeLib interface.
+Arg_NoImporterCallback = Specified type library importer callback was invalid because it did not support the ITypeLibImporterNotifySink interface.
+Arg_ImporterLoadFailure = The type library importer encountered an error during type verification. Try importing without class members.
+Arg_InvalidBase = Invalid Base.
+Arg_EnumValueNotFound = Requested value '{0}' was not found.
+Arg_EnumLitValueNotFound = Literal value was not found.
+Arg_MustContainEnumInfo = Must specify valid information for parsing in the string.
+Arg_InvalidSearchPattern = Search pattern cannot contain ".." to move up directories and can be contained only internally in file/directory names, as in "a..b".
+Arg_NegativeArgCount = Argument count must not be negative.
+Arg_InvalidAccessEntry = Specified access entry is invalid because it is unrestricted. The global flags should be specified instead.
+Arg_InvalidFileName = Specified file name was invalid.
+Arg_InvalidFileExtension = Specified file extension was not a valid extension.
+Arg_COMException = Error HRESULT E_FAIL has been returned from a call to a COM component.
+Arg_ExternalException = External component has thrown an exception.
+Arg_InvalidComObjectException = Attempt has been made to use a COM object that does not have a backing class factory.
+Arg_InvalidOleVariantTypeException = Specified OLE variant was invalid.
+Arg_MarshalDirectiveException = Marshaling directives are invalid.
+Arg_MarshalAsAnyRestriction = AsAny cannot be used on return types, ByRef parameters, ArrayWithOffset, or parameters passed from unmanaged to managed.
+Arg_NDirectBadObject = No PInvoke conversion exists for value passed to Object-typed parameter.
+Arg_SafeArrayTypeMismatchException = Specified array was not of the expected type.
+Arg_VTableCallsNotSupportedException = Attempted to make an early bound call on a COM dispatch-only interface.
+Arg_SafeArrayRankMismatchException = Specified array was not of the expected rank.
+Arg_AmbiguousMatchException = Ambiguous match found.
+Arg_CustomAttributeFormatException = Binary format of the specified custom attribute was invalid.
+Arg_InvalidFilterCriteriaException = Specified filter criteria was invalid.
+Arg_TypeLoadNullStr = A null or zero length string does not represent a valid Type.
+Arg_TargetInvocationException = Exception has been thrown by the target of an invocation.
+Arg_TargetParameterCountException = Number of parameters specified does not match the expected number.
+Arg_TypeAccessException = Attempt to access the type failed.
+Arg_TypeLoadException = Failure has occurred while loading a type.
+Arg_TypeUnloadedException = Type had been unloaded.
+Arg_ThreadStateException = Thread was in an invalid state for the operation being executed.
+Arg_ThreadStartException = Thread failed to start.
+Arg_WrongAsyncResult = IAsyncResult object did not come from the corresponding async method on this type.
+Arg_WrongType = The value "{0}" is not of type "{1}" and cannot be used in this generic collection.
+Argument_InvalidArgumentForComparison = Type of argument is not compatible with the generic comparer.
+Argument_ALSInvalidCapacity = Specified capacity must not be less than the current capacity.
+Argument_ALSInvalidSlot = Specified slot number was invalid.
+Argument_IdnIllegalName = Decoded string is not a valid IDN name.
+Argument_IdnBadBidi = Left to right characters may not be mixed with right to left characters in IDN labels.
+Argument_IdnBadLabelSize = IDN labels must be between 1 and 63 characters long.
+Argument_IdnBadNameSize = IDN names must be between 1 and {0} characters long.
+Argument_IdnBadPunycode = Invalid IDN encoded string.
+Argument_IdnBadStd3 = Label contains character '{0}' not allowed with UseStd3AsciiRules
+Arg_InvalidANSIString = The ANSI string passed in could not be converted from the default ANSI code page to Unicode.
+Arg_InvalidUTF8String = The UTF8 string passed in could not be converted to Unicode.
+Argument_InvalidCharSequence = Invalid Unicode code point found at index {0}.
+Argument_InvalidCharSequenceNoIndex = String contains invalid Unicode code points.
+Argument_InvalidCalendar = Not a valid calendar for the given culture.
+Argument_InvalidNormalizationForm = Invalid or unsupported normalization form.
+Argument_InvalidPathChars = Illegal characters in path.
+Argument_InvalidOffLen = Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
+Argument_InvalidSeekOrigin = Invalid seek origin.
+Argument_SeekOverflow = The specified seek offset '{0}' would result in a negative Stream position.
+Argument_InvalidUnity = Invalid Unity type.
+Argument_LongEnvVarName = Environment variable name cannot contain 1024 or more characters.
+Argument_LongEnvVarValue = Environment variable name or value is too long.
+Argument_StringFirstCharIsZero = The first char in the string is the null character.
+Argument_OnlyMscorlib = Only mscorlib's assembly is valid.
+Argument_PathEmpty = Path cannot be the empty string or all whitespace.
+Argument_PathFormatNotSupported = The given path's format is not supported.
+Argument_PathUriFormatNotSupported = URI formats are not supported.
+Argument_TypeNameTooLong = Type name was too long. The fully qualified type name must be less than 1,024 characters.
+Argument_StreamNotReadable = Stream was not readable.
+Argument_StreamNotWritable = Stream was not writable.
+Argument_InvalidNumberOfMembers = MemberData contains an invalid number of members.
+Argument_InvalidValue = Value was invalid.
+Argument_InvalidKey = Key was invalid.
+Argument_MinMaxValue = '{0}' cannot be greater than {1}.
+Argument_InvalidGroupSize = Every element in the value array should be between one and nine, except for the last element, which can be zero.
+Argument_MustHaveAttributeBaseClass = Type passed in must be derived from System.Attribute or System.Attribute itself.
+Argument_NoUninitializedStrings = Uninitialized Strings cannot be created.
+Argument_UnequalMembers = Supplied MemberInfo does not match the expected type.
+Argument_BadFormatSpecifier = Format specifier was invalid.
+Argument_InvalidHighSurrogate = Found a high surrogate char without a following low surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters.
+Argument_InvalidLowSurrogate = Found a low surrogate char without a preceding high surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters.
+Argument_UnmatchingSymScope = Non-matching symbol scope.
+Argument_NotInExceptionBlock = Not currently in an exception block.
+Argument_BadExceptionCodeGen = Incorrect code generation for exception block.
+Argument_NotExceptionType = Does not extend Exception.
+Argument_DuplicateResourceName = Duplicate resource name within an assembly.
+Argument_BadPersistableModuleInTransientAssembly = Cannot have a persistable module in a transient assembly.
+Argument_InvalidPermissionState = Invalid permission state.
+Argument_UnrestrictedIdentityPermission = Identity permissions cannot be unrestricted.
+Argument_WrongType = Operation on type '{0}' attempted with target of incorrect type.
+Argument_IllegalZone = Illegal security permission zone specified.
+Argument_HasToBeArrayClass = Must be an array type.
+Argument_InvalidDirectory = Invalid directory, '{0}'.
+Argument_DataLengthDifferent = Parameters 'members' and 'data' must have the same length.
+Argument_SigIsFinalized = Completed signature cannot be modified.
+Argument_ArraysInvalid = Array or pointer types are not valid.
+Argument_GenericsInvalid = Generic types are not valid.
+Argument_LargeInteger = Integer or token was too large to be encoded.
+Argument_BadSigFormat = Incorrect signature format.
+Argument_UnmatchedMethodForLocal = Local passed in does not belong to this ILGenerator.
+Argument_DuplicateName = Tried to add NamedPermissionSet with non-unique name.
+Argument_InvalidXMLElement = Invalid XML. Missing required tag <{0}> for type '{1}'.
+Argument_InvalidXMLMissingAttr = Invalid XML. Missing required attribute '{0}'.
+Argument_CannotGetTypeTokenForByRef = Cannot get TypeToken for a ByRef type.
+Argument_NotASimpleNativeType = The UnmanagedType passed to DefineUnmanagedMarshal is not a simple type. None of the following values may be used: UnmanagedType.ByValTStr, UnmanagedType.SafeArray, UnmanagedType.ByValArray, UnmanagedType.LPArray, UnmanagedType.CustomMarshaler.
+Argument_NotACustomMarshaler = Not a custom marshal.
+Argument_NoUnmanagedElementCount = Unmanaged marshal does not have ElementCount.
+Argument_NoNestedMarshal = Only LPArray or SafeArray has nested unmanaged marshal.
+Argument_InvalidXML = Invalid Xml.
+Argument_NoUnderlyingCCW = The object has no underlying COM data associated with it.
+Argument_BadFieldType = Bad field type in defining field.
+Argument_InvalidXMLBadVersion = Invalid Xml - can only parse elements of version one.
+Argument_NotAPermissionElement = 'elem' was not a permission element.
+Argument_NPMSInvalidName = Name can be neither null nor empty.
+Argument_InvalidElementTag = Invalid element tag '{0}'.
+Argument_InvalidElementText = Invalid element text '{0}'.
+Argument_InvalidElementName = Invalid element name '{0}'.
+Argument_InvalidElementValue = Invalid element value '{0}'.
+Argument_AttributeNamesMustBeUnique = Attribute names must be unique.
+#if FEATURE_CAS_POLICY
+Argument_UninitializedCertificate = Uninitialized certificate object.
+Argument_MembershipConditionElement = Element must be a <IMembershipCondition> element.
+Argument_ReservedNPMS = Cannot remove or modify reserved permissions set '{0}'.
+Argument_NPMSInUse = Permission set '{0}' was in use and could not be deleted.
+Argument_StrongNameGetPublicKey = Unable to obtain public key for StrongNameKeyPair.
+Argument_SiteCannotBeNull = Site name must be specified.
+Argument_BlobCannotBeNull = Public key must be specified.
+Argument_ZoneCannotBeNull = Zone must be specified.
+Argument_UrlCannotBeNull = URL must be specified.
+Argument_NoNPMS = Unable to find a permission set with the provided name.
+Argument_FailedCodeGroup = Failed to create a code group of type '{0}'.
+Argument_CodeGroupChildrenMustBeCodeGroups = All objects in the input list must have a parent type of 'CodeGroup'.
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_IMPERSONATION
+Argument_InvalidPrivilegeName = Privilege '{0}' is not valid on this system.
+Argument_TokenZero = Token cannot be zero.
+Argument_InvalidImpersonationToken = Invalid token for impersonation - it cannot be duplicated.
+Argument_ImpersonateUser = Unable to impersonate user.
+#endif // FEATURE_IMPERSONATION
+Argument_InvalidHexFormat = Improperly formatted hex string.
+Argument_InvalidSite = Invalid site.
+Argument_InterfaceMap = 'this' type cannot be an interface itself.
+Argument_ArrayGetInterfaceMap = Interface maps for generic interfaces on arrays cannot be retrieved.
+Argument_InvalidName = Invalid name.
+Argument_InvalidDirectoryOnUrl = Invalid directory on URL.
+Argument_InvalidUrl = Invalid URL.
+Argument_InvalidKindOfTypeForCA = This type cannot be represented as a custom attribute.
+Argument_MustSupplyContainer = When supplying a FieldInfo for fixing up a nested type, a valid ID for that containing object must also be supplied.
+Argument_MustSupplyParent = When supplying the ID of a containing object, the FieldInfo that identifies the current field within that object must also be supplied.
+Argument_NoClass = Element does not specify a class.
+Argument_WrongElementType = '{0}' element required.
+Argument_UnableToGeneratePermissionSet = Unable to generate permission set; input XML may be malformed.
+Argument_NoEra = No Era was supplied.
+Argument_AssemblyAlreadyFullTrust = Assembly was already fully trusted.
+Argument_AssemblyNotFullTrust = Assembly was not fully trusted.
+Argument_AssemblyWinMD = Assembly must not be a Windows Runtime assembly.
+Argument_MemberAndArray = Cannot supply both a MemberInfo and an Array to indicate the parent of a value type.
+Argument_ObjNotComObject = The object's type must be __ComObject or derived from __ComObject.
+Argument_ObjIsWinRTObject = The object's type must not be a Windows Runtime type.
+Argument_TypeNotComObject = The type must be __ComObject or be derived from __ComObject.
+Argument_TypeIsWinRTType = The type must not be a Windows Runtime type.
+Argument_CantCallSecObjFunc = Cannot evaluate a security function.
+Argument_StructMustNotBeValueClass = The structure must not be a value class.
+Argument_NoSpecificCulture = Please select a specific culture, such as zh-CN, zh-HK, zh-TW, zh-MO, zh-SG.
+Argument_InvalidResourceCultureName = The given culture name '{0}' cannot be used to locate a resource file. Resource filenames must consist of only letters, numbers, hyphens or underscores.
+Argument_InvalidParamInfo = Invalid type for ParameterInfo member in Attribute class.
+Argument_EmptyDecString = Decimal separator cannot be the empty string.
+Argument_OffsetOfFieldNotFound = Field passed in is not a marshaled member of the type '{0}'.
+Argument_EmptyStrongName = StrongName cannot have an empty string for the assembly name.
+Argument_NotSerializable = Argument passed in is not serializable.
+Argument_EmptyApplicationName = ApplicationId cannot have an empty string for the name.
+Argument_NoDomainManager = The domain manager specified by the host could not be instantiated.
+Argument_NoMain = Main entry point not defined.
+Argument_InvalidDateTimeKind = Invalid DateTimeKind value.
+Argument_ConflictingDateTimeStyles = The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together.
+Argument_ConflictingDateTimeRoundtripStyles = The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, AssumeUniversal or AdjustToUniversal.
+Argument_InvalidDigitSubstitution = The DigitSubstitution property must be of a valid member of the DigitShapes enumeration. Valid entries include Context, NativeNational or None.
+Argument_InvalidNativeDigitCount = The NativeDigits array must contain exactly ten members.
+Argument_InvalidNativeDigitValue = Each member of the NativeDigits array must be a single text element (one or more UTF16 code points) with a Unicode Nd (Number, Decimal Digit) property indicating it is a digit.
+ArgumentException_InvalidAceBinaryForm = The binary form of an ACE object is invalid.
+ArgumentException_InvalidAclBinaryForm = The binary form of an ACL object is invalid.
+ArgumentException_InvalidSDSddlForm = The SDDL form of a security descriptor object is invalid.
+Argument_InvalidSafeHandle = The SafeHandle is invalid.
+Argument_CannotPrepareAbstract = Abstract methods cannot be prepared.
+Argument_ArrayTooLarge = The input array length must not exceed Int32.MaxValue / {0}. Otherwise BitArray.Length would exceed Int32.MaxValue.
+Argument_RelativeUrlMembershipCondition = UrlMembershipCondition requires an absolute URL.
+Argument_EmptyWaithandleArray = Waithandle array may not be empty.
+Argument_InvalidSafeBufferOffLen = Offset and length were greater than the size of the SafeBuffer.
+Argument_NotEnoughBytesToRead = There are not enough bytes remaining in the accessor to read at this position.
+Argument_NotEnoughBytesToWrite = There are not enough bytes remaining in the accessor to write at this position.
+Argument_OffsetAndLengthOutOfBounds = Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
+Argument_OffsetAndCapacityOutOfBounds = Offset and capacity were greater than the size of the view.
+Argument_UnmanagedMemAccessorWrapAround = The UnmanagedMemoryAccessor capacity and offset would wrap around the high end of the address space.
+Argument_UnrecognizedLoaderOptimization = Unrecognized LOADER_OPTIMIZATION property value. Supported values may include "SingleDomain", "MultiDomain", "MultiDomainHost", and "NotSpecified".
+ArgumentException_NotAllCustomSortingFuncsDefined = Implementations of all the NLS functions must be provided.
+ArgumentException_MinSortingVersion = The runtime does not support a version of "{0}" less than {1}.
+
+;
+; =====================================================
+; Reflection Emit resource strings
+Arugment_EmitMixedContext1 = Type '{0}' was loaded in the ReflectionOnly context but the AssemblyBuilder was not created as AssemblyBuilderAccess.ReflectionOnly.
+Arugment_EmitMixedContext2 = Type '{0}' was not loaded in the ReflectionOnly context but the AssemblyBuilder was created as AssemblyBuilderAccess.ReflectionOnly.
+Argument_BadSizeForData = Data size must be > 0 and < 0x3f0000
+Argument_InvalidLabel = Invalid Label.
+Argument_RedefinedLabel = Label multiply defined.
+Argument_UnclosedExceptionBlock = The IL Generator cannot be used while there are unclosed exceptions.
+Argument_MissingDefaultConstructor = was missing default constructor.
+Argument_TooManyFinallyClause = Exception blocks may have at most one finally clause.
+Argument_NotInTheSameModuleBuilder = The argument passed in was not from the same ModuleBuilder.
+Argument_BadCurrentLocalVariable = Bad current local variable for setting symbol information.
+Argument_DuplicateModuleName = Duplicate dynamic module name within an assembly.
+Argument_DuplicateTypeName = Duplicate type name within an assembly.
+Argument_InvalidAssemblyName = Assembly names may not begin with whitespace or contain the characters '/', or '\\' or ':'.
+Argument_InvalidGenericInstantiation = The given generic instantiation was invalid.
+Argument_DuplicatedFileName = Duplicate file names.
+Argument_GlobalFunctionHasToBeStatic = Global members must be static.
+Argument_BadPInvokeOnInterface = PInvoke methods cannot exist on interfaces.
+Argument_BadPInvokeMethod = PInvoke methods must be static and native and cannot be abstract.
+Argument_MethodRedefined = Method has been already defined.
+Argument_BadTypeAttrAbstractNFinal = Bad type attributes. A type cannot be both abstract and final.
+Argument_BadTypeAttrNestedVisibilityOnNonNestedType = Bad type attributes. Nested visibility flag set on a non-nested type.
+Argument_BadTypeAttrNonNestedVisibilityNestedType = Bad type attributes. Non-nested visibility flag set on a nested type.
+Argument_BadTypeAttrInvalidLayout = Bad type attributes. Invalid layout attribute specified.
+Argument_BadTypeAttrReservedBitsSet = Bad type attributes. Reserved bits set on the type.
+Argument_BadFieldSig = Field signatures do not have return types.
+Argument_ShouldOnlySetVisibilityFlags = Should only set visibility flags when creating EnumBuilder.
+Argument_BadNestedTypeFlags = Visibility of interfaces must be one of the following: NestedAssembly, NestedFamANDAssem, NestedFamily, NestedFamORAssem, NestedPrivate or NestedPublic.
+Argument_ShouldNotSpecifyExceptionType = Should not specify exception type for catch clause for filter block.
+Argument_BadLabel = Bad label in ILGenerator.
+Argument_BadLabelContent = Bad label content in ILGenerator.
+Argument_EmitWriteLineType = EmitWriteLine does not support this field or local type.
+Argument_ConstantNull = Null is not a valid constant value for this type.
+Argument_ConstantDoesntMatch = Constant does not match the defined type.
+Argument_ConstantNotSupported = {0} is not a supported constant type.
+Argument_BadConstructor = Cannot have private or static constructor.
+Argument_BadConstructorCallConv = Constructor must have standard calling convention.
+Argument_BadPropertyForConstructorBuilder = Property must be on the same type of the given ConstructorInfo.
+Argument_NotAWritableProperty = Not a writable property.
+Argument_BadFieldForConstructorBuilder = Field must be on the same type of the given ConstructorInfo.
+Argument_BadAttributeOnInterfaceMethod = Interface method must be abstract and virtual.
+ArgumentException_BadMethodImplBody = MethodOverride's body must be from this type.
+Argument_BadParameterCountsForConstructor = Parameter count does not match passed in argument value count.
+Argument_BadParameterTypeForConstructor = Passed in argument value at index {0} does not match the parameter type.
+Argument_BadTypeInCustomAttribute = An invalid type was used as a custom attribute constructor argument, field or property.
+Argument_DateTimeBadBinaryData = The binary data must result in a DateTime with ticks between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+Argument_VerStringTooLong = The unmanaged Version information is too large to persist.
+Argument_UnknownUnmanagedCallConv = Unknown unmanaged calling convention for function signature.
+Argument_BadConstantValue = Bad default value.
+Argument_IllegalName = Illegal name.
+Argument_cvtres_NotFound = Cannot find cvtres.exe
+Argument_BadCAForUnmngRSC = Bad '{0}' while generating unmanaged resource information.
+Argument_MustBeInterfaceMethod = The MemberInfo must be an interface method.
+Argument_CORDBBadVarArgCallConv = Cannot evaluate a VarArgs function.
+Argument_CORDBBadMethod = Cannot find the method on the object instance.
+Argument_InvalidOpCodeOnDynamicMethod = Ldtoken, Ldftn and Ldvirtftn OpCodes cannot target DynamicMethods.
+Argument_InvalidTypeForDynamicMethod = Invalid type owner for DynamicMethod.
+Argument_NeedGenericMethodDefinition = Method must represent a generic method definition on a generic type definition.
+Argument_MethodNeedGenericDeclaringType = The specified method cannot be dynamic or global and must be declared on a generic type definition.
+Argument_ConstructorNeedGenericDeclaringType = The specified constructor must be declared on a generic type definition.
+Argument_FieldNeedGenericDeclaringType = The specified field must be declared on a generic type definition.
+Argument_InvalidMethodDeclaringType = The specified method must be declared on the generic type definition of the specified type.
+Argument_InvalidConstructorDeclaringType = The specified constructor must be declared on the generic type definition of the specified type.
+Argument_InvalidFieldDeclaringType = The specified field must be declared on the generic type definition of the specified type.
+Argument_NeedNonGenericType = The specified Type must not be a generic type definition.
+Argument_MustBeTypeBuilder = 'type' must contain a TypeBuilder as a generic argument.
+Argument_CannotSetParentToInterface = Cannot set parent to an interface.
+Argument_MismatchedArrays = Two arrays, {0} and {1}, must be of the same size.
+Argument_NeedNonGenericObject = The specified object must not be an instance of a generic type.
+Argument_NeedStructWithNoRefs = The specified Type must be a struct containing no references.
+Argument_NotMethodCallOpcode = The specified opcode cannot be passed to EmitCall.
+
+; =====================================================
+;
+Argument_ModuleAlreadyLoaded = The specified module has already been loaded.
+Argument_MustHaveLayoutOrBeBlittable = The specified structure must be blittable or have layout information.
+Argument_NotSimpleFileName = The filename must not include a path specification.
+Argument_TypeMustBeVisibleFromCom = The specified type must be visible from COM.
+Argument_TypeMustBeComCreatable = The type must be creatable from COM.
+Argument_TypeMustNotBeComImport = The type must not be imported from COM.
+Argument_PolicyFileDoesNotExist = The requested policy file does not exist.
+Argument_NonNullObjAndCtx = Either obj or ctx must be null.
+Argument_NoModuleFileExtension = Module file name '{0}' must have file extension.
+Argument_TypeDoesNotContainMethod = Type does not contain the given method.
+Argument_StringZeroLength = String cannot be of zero length.
+Argument_MustBeString = String is too long or has invalid contents.
+Argument_AbsolutePathRequired = Absolute path information is required.
+Argument_ManifestFileDoesNotExist = The specified manifest file does not exist.
+Argument_MustBeRuntimeType = Type must be a runtime Type object.
+Argument_TypeNotValid = The Type object is not valid.
+Argument_MustBeRuntimeMethodInfo = MethodInfo must be a runtime MethodInfo object.
+Argument_MustBeRuntimeFieldInfo = FieldInfo must be a runtime FieldInfo object.
+Argument_InvalidFieldInfo = The FieldInfo object is not valid.
+Argument_InvalidConstructorInfo = The ConstructorInfo object is not valid.
+Argument_MustBeRuntimeAssembly = Assembly must be a runtime Assembly object.
+Argument_MustBeRuntimeModule = Module must be a runtime Module object.
+Argument_MustBeRuntimeParameterInfo = ParameterInfo must be a runtime ParameterInfo object.
+Argument_InvalidParameterInfo = The ParameterInfo object is not valid.
+Argument_MustBeRuntimeReflectionObject = The object must be a runtime Reflection object.
+Argument_InvalidMarshalByRefObject = The MarshalByRefObject is not valid.
+Argument_TypedReferenceInvalidField = Field in TypedReferences cannot be static or init only.
+Argument_HandleLeak = Cannot pass a GCHandle across AppDomains.
+Argument_ArgumentZero = Argument cannot be zero.
+Argument_ImproperType = Improper types in collection.
+Argument_NotAMembershipCondition = The type does not implement IMembershipCondition
+Argument_NotAPermissionType = The type does not implement IPermission
+Argument_NotACodeGroupType = The type does not inherit from CodeGroup
+Argument_NotATP = Type must be a TransparentProxy
+Argument_AlreadyACCW = The object already has a CCW associated with it.
+Argument_OffsetLocalMismatch = The UTC Offset of the local dateTime parameter does not match the offset argument.
+Argument_OffsetUtcMismatch = The UTC Offset for Utc DateTime instances must be 0.
+Argument_UTCOutOfRange = The UTC time represented when the offset is applied must be between year 0 and 10,000.
+Argument_OffsetOutOfRange = Offset must be within plus or minus 14 hours.
+Argument_OffsetPrecision = Offset must be specified in whole minutes.
+Argument_FlagNotSupported = One or more flags are not supported.
+Argument_MustBeFalse = Argument must be initialized to false
+Argument_ToExclusiveLessThanFromExclusive = fromInclusive must be less than or equal to toExclusive.
+Argument_FrameworkNameTooShort=FrameworkName cannot have less than two components or more than three components.
+Argument_FrameworkNameInvalid=FrameworkName is invalid.
+Argument_FrameworkNameMissingVersion=FrameworkName version component is missing.
+#if FEATURE_COMINTEROP
+Argument_TypeNotActivatableViaWindowsRuntime = Type '{0}' does not have an activation factory because it is not activatable by Windows Runtime.
+Argument_WinRTSystemRuntimeType = Cannot marshal type '{0}' to Windows Runtime. Only 'System.RuntimeType' is supported.
+Argument_Unexpected_TypeSource = Unexpected TypeKind when marshaling Windows.Foundation.TypeName.
+#endif // FEATURE_COMINTEROP
+
+; ArgumentNullException
+ArgumentNull_Array = Array cannot be null.
+ArgumentNull_ArrayValue = Found a null value within an array.
+ArgumentNull_ArrayElement = At least one element in the specified array was null.
+ArgumentNull_Assembly = Assembly cannot be null.
+ArgumentNull_AssemblyName = AssemblyName cannot be null.
+ArgumentNull_AssemblyNameName = AssemblyName.Name cannot be null or an empty string.
+ArgumentNull_Buffer = Buffer cannot be null.
+ArgumentNull_Collection = Collection cannot be null.
+ArgumentNull_CultureInfo = CultureInfo cannot be null.
+ArgumentNull_Dictionary = Dictionary cannot be null.
+ArgumentNull_FileName = File name cannot be null.
+ArgumentNull_Key = Key cannot be null.
+ArgumentNull_Graph = Object Graph cannot be null.
+ArgumentNull_Path = Path cannot be null.
+ArgumentNull_Stream = Stream cannot be null.
+ArgumentNull_String = String reference not set to an instance of a String.
+ArgumentNull_Type = Type cannot be null.
+ArgumentNull_Obj = Object cannot be null.
+ArgumentNull_GUID = GUID cannot be null.
+ArgumentNull_NullMember = Member at position {0} was null.
+ArgumentNull_Generic = Value cannot be null.
+ArgumentNull_WithParamName = Parameter '{0}' cannot be null.
+ArgumentNull_Child = Cannot have a null child.
+ArgumentNull_SafeHandle = SafeHandle cannot be null.
+ArgumentNull_CriticalHandle = CriticalHandle cannot be null.
+ArgumentNull_TypedRefType = Type in TypedReference cannot be null.
+ArgumentNull_ApplicationTrust = The application trust cannot be null.
+ArgumentNull_TypeRequiredByResourceScope = The type parameter cannot be null when scoping the resource's visibility to Private or Assembly.
+ArgumentNull_Waithandles = The waitHandles parameter cannot be null.
+
+; ArgumentOutOfRangeException
+ArgumentOutOfRange_AddressSpace = The number of bytes cannot exceed the virtual address space on a 32 bit machine.
+ArgumentOutOfRange_ArrayLB = Number was less than the array's lower bound in the first dimension.
+ArgumentOutOfRange_ArrayLBAndLength = Higher indices will exceed Int32.MaxValue because of large lower bound and/or length.
+ArgumentOutOfRange_ArrayLength = The length of the array must be between {0} and {1}, inclusive.
+ArgumentOutOfRange_ArrayLengthMultiple = The length of the array must be a multiple of {0}.
+ArgumentOutOfRange_ArrayListInsert = Insertion index was out of range. Must be non-negative and less than or equal to size.
+ArgumentOutOfRange_ArrayTooSmall = Destination array is not long enough to copy all the required data. Check array length and offset.
+ArgumentOutOfRange_BeepFrequency = Console.Beep's frequency must be between {0} and {1}.
+ArgumentOutOfRange_BiggerThanCollection = Larger than collection size.
+ArgumentOutOfRange_Bounds_Lower_Upper = Argument must be between {0} and {1}.
+ArgumentOutOfRange_Count = Count must be positive and count must refer to a location within the string/array/collection.
+ArgumentOutOfRange_CalendarRange = Specified time is not supported in this calendar. It should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive.
+ArgumentOutOfRange_ConsoleBufferBoundaries = The value must be greater than or equal to zero and less than the console's buffer size in that dimension.
+ArgumentOutOfRange_ConsoleBufferLessThanWindowSize = The console buffer size must not be less than the current size and position of the console window, nor greater than or equal to Int16.MaxValue.
+ArgumentOutOfRange_ConsoleWindowBufferSize = The new console window size would force the console buffer size to be too large.
+ArgumentOutOfRange_ConsoleTitleTooLong = The console title is too long.
+ArgumentOutOfRange_ConsoleWindowPos = The window position must be set such that the current window size fits within the console's buffer, and the numbers must not be negative.
+ArgumentOutOfRange_ConsoleWindowSize_Size = The value must be less than the console's current maximum window size of {0} in that dimension. Note that this value depends on screen resolution and the console font.
+ArgumentOutOfRange_ConsoleKey = Console key values must be between 0 and 255.
+ArgumentOutOfRange_CursorSize = The cursor size is invalid. It must be a percentage between 1 and 100.
+ArgumentOutOfRange_BadYearMonthDay = Year, Month, and Day parameters describe an un-representable DateTime.
+ArgumentOutOfRange_BadHourMinuteSecond = Hour, Minute, and Second parameters describe an un-representable DateTime.
+ArgumentOutOfRange_DateArithmetic = The added or subtracted value results in an un-representable DateTime.
+ArgumentOutOfRange_DateTimeBadMonths = Months value must be between +/-120000.
+ArgumentOutOfRange_DateTimeBadYears = Years value must be between +/-10000.
+ArgumentOutOfRange_DateTimeBadTicks = Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+ArgumentOutOfRange_Day = Day must be between 1 and {0} for month {1}.
+ArgumentOutOfRange_DecimalRound = Decimal can only round to between 0 and 28 digits of precision.
+ArgumentOutOfRange_DecimalScale = Decimal's scale value must be between 0 and 28, inclusive.
+ArgumentOutOfRange_Era = Time value was out of era range.
+ArgumentOutOfRange_Enum = Enum value was out of legal range.
+ArgumentOutOfRange_FileLengthTooBig = Specified file length was too large for the file system.
+ArgumentOutOfRange_FileTimeInvalid = Not a valid Win32 FileTime.
+ArgumentOutOfRange_GetByteCountOverflow = Too many characters. The resulting number of bytes is larger than what can be returned as an int.
+ArgumentOutOfRange_GetCharCountOverflow = Too many bytes. The resulting number of chars is larger than what can be returned as an int.
+ArgumentOutOfRange_HashtableLoadFactor = Load factor needs to be between 0.1 and 1.0.
+ArgumentOutOfRange_HugeArrayNotSupported = Arrays larger than 2GB are not supported.
+ArgumentOutOfRange_InvalidHighSurrogate = A valid high surrogate character is between 0xd800 and 0xdbff, inclusive.
+ArgumentOutOfRange_InvalidLowSurrogate = A valid low surrogate character is between 0xdc00 and 0xdfff, inclusive.
+ArgumentOutOfRange_InvalidEraValue = Era value was not valid.
+ArgumentOutOfRange_InvalidUserDefinedAceType = User-defined ACEs must not have a well-known ACE type.
+ArgumentOutOfRange_InvalidUTF32 = A valid UTF32 value is between 0x000000 and 0x10ffff, inclusive, and should not include surrogate codepoint values (0x00d800 ~ 0x00dfff).
+ArgumentOutOfRange_Index = Index was out of range. Must be non-negative and less than the size of the collection.
+ArgumentOutOfRange_IndexString = Index was out of range. Must be non-negative and less than the length of the string.
+ArgumentOutOfRange_StreamLength = Stream length must be non-negative and less than 2^31 - 1 - origin.
+ArgumentOutOfRange_LessEqualToIntegerMaxVal = Argument must be less than or equal to 2^31 - 1 milliseconds.
+ArgumentOutOfRange_Month = Month must be between one and twelve.
+ArgumentOutOfRange_MustBeNonNegInt32 = Value must be non-negative and less than or equal to Int32.MaxValue.
+ArgumentOutOfRange_NeedNonNegNum = Non-negative number required.
+ArgumentOutOfRange_NeedNonNegOrNegative1 = Number must be either non-negative and less than or equal to Int32.MaxValue or -1.
+ArgumentOutOfRange_NeedPosNum = Positive number required.
+ArgumentOutOfRange_NegativeCapacity = Capacity must be positive.
+ArgumentOutOfRange_NegativeCount = Count cannot be less than zero.
+ArgumentOutOfRange_NegativeLength = Length cannot be less than zero.
+ArgumentOutOfRange_NegFileSize = Length must be non-negative.
+ArgumentOutOfRange_ObjectID = objectID cannot be less than or equal to zero.
+ArgumentOutOfRange_SmallCapacity = capacity was less than the current size.
+ArgumentOutOfRange_QueueGrowFactor = Queue grow factor must be between {0} and {1}.
+ArgumentOutOfRange_RoundingDigits = Rounding digits must be between 0 and 15, inclusive.
+ArgumentOutOfRange_StartIndex = StartIndex cannot be less than zero.
+ArgumentOutOfRange_MustBePositive = '{0}' must be greater than zero.
+ArgumentOutOfRange_MustBeNonNegNum = '{0}' must be non-negative.
+ArgumentOutOfRange_LengthGreaterThanCapacity = The length cannot be greater than the capacity.
+ArgumentOutOfRange_ListInsert = Index must be within the bounds of the List.
+ArgumentOutOfRange_StartIndexLessThanLength = startIndex must be less than length of string.
+ArgumentOutOfRange_StartIndexLargerThanLength = startIndex cannot be larger than length of string.
+ArgumentOutOfRange_EndIndexStartIndex = endIndex cannot be greater than startIndex.
+ArgumentOutOfRange_IndexCount = Index and count must refer to a location within the string.
+ArgumentOutOfRange_IndexCountBuffer = Index and count must refer to a location within the buffer.
+ArgumentOutOfRange_IndexLength = Index and length must refer to a location within the string.
+ArgumentOutOfRange_InvalidThreshold = The specified threshold for creating dictionary is out of range.
+ArgumentOutOfRange_Capacity = Capacity exceeds maximum capacity.
+ArgumentOutOfRange_Length = The specified length exceeds maximum capacity of SecureString.
+ArgumentOutOfRange_LengthTooLarge = The specified length exceeds the maximum value of {0}.
+ArgumentOutOfRange_SmallMaxCapacity = MaxCapacity must be one or greater.
+ArgumentOutOfRange_GenericPositive = Value must be positive.
+ArgumentOutOfRange_Range = Valid values are between {0} and {1}, inclusive.
+ArgumentOutOfRange_AddValue = Value to add was out of range.
+ArgumentOutOfRange_OffsetLength = Offset and length must refer to a position in the string.
+ArgumentOutOfRange_OffsetOut = Either offset did not refer to a position in the string, or there is an insufficient length of destination character array.
+ArgumentOutOfRange_PartialWCHAR = Pointer startIndex and length do not refer to a valid string.
+ArgumentOutOfRange_ParamSequence = The specified parameter index is not in range.
+ArgumentOutOfRange_Version = Version's parameters must be greater than or equal to zero.
+ArgumentOutOfRange_TimeoutTooLarge = Time-out interval must be less than 2^32-2.
+ArgumentOutOfRange_UIntPtrMax-1 = The length of the buffer must be less than the maximum UIntPtr value for your platform.
+ArgumentOutOfRange_UnmanagedMemStreamLength = UnmanagedMemoryStream length must be non-negative and less than 2^63 - 1 - baseAddress.
+ArgumentOutOfRange_UnmanagedMemStreamWrapAround = The UnmanagedMemoryStream capacity would wrap around the high end of the address space.
+ArgumentOutOfRange_PeriodTooLarge = Period must be less than 2^32-2.
+ArgumentOutOfRange_Year = Year must be between 1 and 9999.
+ArgumentOutOfRange_BinaryReaderFillBuffer = The number of bytes requested does not fit into BinaryReader's internal buffer.
+ArgumentOutOfRange_PositionLessThanCapacityRequired = The position may not be greater or equal to the capacity of the accessor.
+
+; ArithmeticException
+Arithmetic_NaN = Function does not accept floating point Not-a-Number values.
+
+; ArrayTypeMismatchException
+ArrayTypeMismatch_CantAssignType = Source array type cannot be assigned to destination array type.
+ArrayTypeMismatch_ConstrainedCopy = Array.ConstrainedCopy will only work on array types that are provably compatible, without any form of boxing, unboxing, widening, or casting of each array element. Change the array types (i.e., copy a Derived[] to a Base[]), or use a mitigation strategy in the CER for Array.Copy's less powerful reliability contract, such as cloning the array or throwing away the potentially corrupt destination array.
+
+; BadImageFormatException
+BadImageFormat_ResType&SerBlobMismatch = The type serialized in the .resources file was not the same type that the .resources file said it contained. Expected '{0}' but read '{1}'.
+BadImageFormat_ResourcesIndexTooLong = Corrupt .resources file. String for name index '{0}' extends past the end of the file.
+BadImageFormat_ResourcesNameTooLong = Corrupt .resources file. Resource name extends past the end of the file.
+BadImageFormat_ResourcesNameInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into name section.
+BadImageFormat_ResourcesHeaderCorrupted = Corrupt .resources file. Unable to read resources from this file because of invalid header information. Try regenerating the .resources file.
+BadImageFormat_ResourceNameCorrupted = Corrupt .resources file. A resource name extends past the end of the stream.
+BadImageFormat_ResourceNameCorrupted_NameIndex = Corrupt .resources file. The resource name for name index {0} extends past the end of the stream.
+BadImageFormat_ResourceDataLengthInvalid = Corrupt .resources file. The specified data length '{0}' is not a valid position in the stream.
+BadImageFormat_TypeMismatch = Corrupt .resources file. The specified type doesn't match the available data in the stream.
+BadImageFormat_InvalidType = Corrupt .resources file. The specified type doesn't exist.
+BadImageFormat_ResourcesIndexInvalid = Corrupt .resources file. The resource index '{0}' is outside the valid range.
+BadImageFormat_StreamPositionInvalid = Corrupt .resources file. The specified position '{0}' is not a valid position in the stream.
+BadImageFormat_ResourcesDataInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into data section.
+BadImageFormat_NegativeStringLength = Corrupt .resources file. String length must be non-negative.
+BadImageFormat_ParameterSignatureMismatch = The parameters and the signature of the method don't match.
+
+; Cryptography
+; These strings still appear in bcl.small but should go away eventually
+Cryptography_CSSM_Error = Error 0x{0} from the operating system security framework: '{1}'.
+Cryptography_CSSM_Error_Unknown = Error 0x{0} from the operating system security framework.
+Cryptography_InvalidDSASignatureSize = Length of the DSA signature was not 40 bytes.
+Cryptography_InvalidHandle = {0} is an invalid handle.
+Cryptography_InvalidOID = Object identifier (OID) is unknown.
+Cryptography_OAEPDecoding = Error occurred while decoding OAEP padding.
+Cryptography_PasswordDerivedBytes_InvalidIV = The Initialization vector should have the same length as the algorithm block size in bytes.
+Cryptography_SSE_InvalidDataSize = Length of the data to encrypt is invalid.
+Cryptography_X509_ExportFailed = The certificate export operation failed.
+Cryptography_X509_InvalidContentType = Invalid content type.
+Cryptography_CryptoStream_FlushFinalBlockTwice = FlushFinalBlock() method was called twice on a CryptoStream. It can only be called once.
+Cryptography_HashKeySet = Hash key cannot be changed after the first write to the stream.
+Cryptography_HashNotYetFinalized = Hash must be finalized before the hash value is retrieved.
+Cryptography_InsufficientBuffer = Input buffer contains insufficient data.
+Cryptography_InvalidBlockSize = Specified block size is not valid for this algorithm.
+Cryptography_InvalidCipherMode = Specified cipher mode is not valid for this algorithm.
+Cryptography_InvalidIVSize = Specified initialization vector (IV) does not match the block size for this algorithm.
+Cryptography_InvalidKeySize = Specified key is not a valid size for this algorithm.
+Cryptography_PasswordDerivedBytes_FewBytesSalt = Salt is not at least eight bytes.
+Cryptography_PKCS7_InvalidPadding = Padding is invalid and cannot be removed.
+Cryptography_UnknownHashAlgorithm='{0}' is not a known hash algorithm.
+
+#if FEATURE_CRYPTO
+Cryptography_Config_EncodedOIDError = Encoded OID length is too large (greater than 0x7f bytes).
+Cryptography_CSP_AlgKeySizeNotAvailable = Algorithm implementation does not support a key size of {0}.
+Cryptography_CSP_AlgorithmNotAvailable = Cryptographic service provider (CSP) could not be found for this algorithm.
+Cryptography_CSP_CFBSizeNotSupported = Feedback size for the cipher feedback mode (CFB) must be 8 bits.
+Cryptography_CSP_NotFound = The requested key container was not found.
+Cryptography_CSP_NoPrivateKey = Object contains only the public half of a key pair. A private key must also be provided.
+Cryptography_CSP_OFBNotSupported = Output feedback mode (OFB) is not supported by this implementation.
+Cryptography_CSP_WrongKeySpec = The specified cryptographic service provider (CSP) does not support this key algorithm.
+Cryptography_HashNameSet = Hash name cannot be changed after the first write to the stream.
+Cryptography_HashAlgorithmNameNullOrEmpty = The hash algorithm name cannot be null or empty.
+Cryptography_InvalidHashSize = {0} algorithm hash size is {1} bytes.
+Cryptography_InvalidKey_Weak = Specified key is a known weak key for '{0}' and cannot be used.
+Cryptography_InvalidKey_SemiWeak = Specified key is a known semi-weak key for '{0}' and cannot be used.
+Cryptography_InvalidKeyParameter = Parameter '{0}' is not a valid key parameter.
+Cryptography_InvalidFeedbackSize = Specified feedback size is invalid.
+Cryptography_InvalidOperation = This operation is not supported for this class.
+Cryptography_InvalidPaddingMode = Specified padding mode is not valid for this algorithm.
+Cryptography_InvalidFromXmlString = Input string does not contain a valid encoding of the '{0}' '{1}' parameter.
+Cryptography_MissingKey = No asymmetric key object has been associated with this formatter object.
+Cryptography_MissingOID = Required object identifier (OID) cannot be found.
+Cryptography_NotInteractive = The current session is not interactive.
+Cryptography_NonCompliantFIPSAlgorithm = This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
+Cryptography_Padding_Win2KEnhOnly = Direct Encryption and decryption using RSA are not available on this platform.
+Cryptography_Padding_EncDataTooBig = The data to be encrypted exceeds the maximum for this modulus of {0} bytes.
+Cryptography_Padding_DecDataTooBig = The data to be decrypted exceeds the maximum for this modulus of {0} bytes.
+Cryptography_PasswordDerivedBytes_ValuesFixed = Value of '{0}' cannot be changed after the bytes have been retrieved.
+Cryptography_PasswordDerivedBytes_TooManyBytes = Requested number of bytes exceeds the maximum.
+Cryptography_PasswordDerivedBytes_InvalidAlgorithm = Algorithm is unavailable or is not supported for this operation.
+Cryptography_PKCS1Decoding = Error occurred while decoding PKCS1 padding.
+Cryptography_RC2_EKSKS = EffectiveKeySize value must be at least as large as the KeySize value.
+Cryptography_RC2_EKSKS2 = EffectiveKeySize must be the same as KeySize in this implementation.
+Cryptography_RC2_EKS40 = EffectiveKeySize value must be at least 40 bits.
+Cryptography_SSD_InvalidDataSize = Length of the data to decrypt is invalid.
+Cryptography_AddNullOrEmptyName = CryptoConfig cannot add a mapping for a null or empty name.
+Cryptography_AlgorithmTypesMustBeVisible = Algorithms added to CryptoConfig must be accessable from outside their assembly.
+#endif // FEATURE_CRYPTO
+
+; EventSource
+EventSource_ToString = EventSource({0}, {1})
+EventSource_EventSourceGuidInUse = An instance of EventSource with Guid {0} already exists.
+EventSource_KeywordNeedPowerOfTwo = Value {0} for keyword {1} needs to be a power of 2.
+EventSource_UndefinedKeyword = Use of undefined keyword value {0} for event {1}.
+EventSource_UnsupportedEventTypeInManifest = Unsupported type {0} in event source.
+EventSource_ListenerNotFound = Listener not found.
+EventSource_ListenerCreatedInsideCallback = Creating an EventListener inside a EventListener callback.
+EventSource_AttributeOnNonVoid = Event attribute placed on method {0} which does not return 'void'.
+EventSource_NeedPositiveId = Event IDs must be positive integers.
+EventSource_ReservedOpcode = Opcode values less than 11 are reserved for system use.
+EventSource_ReservedKeywords = Keywords values larger than 0x0000100000000000 are reserved for system use
+EventSource_PayloadTooBig=The payload for a single event is too large.
+EventSource_NoFreeBuffers=No Free Buffers available from the operating system (e.g. event rate too fast).
+EventSource_NullInput=Null passed as a event argument.
+EventSource_TooManyArgs=Too many arguments.
+EventSource_SessionIdError=Bit position in AllKeywords ({0}) must equal the command argument named "EtwSessionKeyword" ({1}).
+EventSource_EnumKindMismatch = The type of {0} is not expected in {1}.
+EventSource_MismatchIdToWriteEvent = Event {0} is givien event ID {1} but {2} was passed to WriteEvent.
+EventSource_EventIdReused = Event {0} has ID {1} which is already in use.
+EventSource_EventNameReused = Event name {0} used more than once. If you wish to overload a method, the overloaded method should have a NonEvent attribute.
+EventSource_UndefinedChannel = Use of undefined channel value {0} for event {1}.
+EventSource_UndefinedOpcode = Use of undefined opcode value {0} for event {1}.
+ArgumentOutOfRange_MaxArgExceeded = The total number of parameters must not exceed {0}.
+ArgumentOutOfRange_MaxStringsExceeded = The number of String parameters must not exceed {0}.
+ArgumentOutOfRange_NeedValidId = The ID parameter must be in the range {0} through {1}.
+EventSource_NeedGuid = The Guid of an EventSource must be non zero.
+EventSource_NeedName = The name of an EventSource must not be null.
+EventSource_EtwAlreadyRegistered = The provider has already been registered with the operating system.
+EventSource_ListenerWriteFailure = An error occurred when writing to a listener.
+EventSource_TypeMustDeriveFromEventSource = Event source types must derive from EventSource.
+EventSource_TypeMustBeSealedOrAbstract = Event source types must be sealed or abstract.
+EventSource_TaskOpcodePairReused = Event {0} (with ID {1}) has the same task/opcode pair as event {2} (with ID {3}).
+EventSource_EventMustHaveTaskIfNonDefaultOpcode = Event {0} (with ID {1}) has a non-default opcode but not a task.
+EventSource_EventNameDoesNotEqualTaskPlusOpcode = Event {0} (with ID {1}) has a name that is not the concatenation of its task name and opcode.
+EventSource_PeriodIllegalInProviderName = Period character ('.') is illegal in an ETW provider name ({0}).
+EventSource_IllegalOpcodeValue = Opcode {0} has a value of {1} which is outside the legal range (11-238).
+EventSource_OpcodeCollision = Opcodes {0} and {1} are defined with the same value ({2}).
+EventSource_IllegalTaskValue = Task {0} has a value of {1} which is outside the legal range (1-65535).
+EventSource_TaskCollision = Tasks {0} and {1} are defined with the same value ({2}).
+EventSource_IllegalKeywordsValue = Keyword {0} has a value of {1} which is outside the legal range (0-0x0000080000000000).
+EventSource_KeywordCollision = Keywords {0} and {1} are defined with the same value ({2}).
+EventSource_EventChannelOutOfRange = Channel {0} has a value of {1} which is outside the legal range (16-254).
+EventSource_ChannelTypeDoesNotMatchEventChannelValue = Channel {0} does not match event channel value {1}.
+EventSource_MaxChannelExceeded = Attempt to define more than the maximum limit of 8 channels for a provider.
+EventSource_DuplicateStringKey = Multiple definitions for string "{0}".
+EventSource_EventWithAdminChannelMustHaveMessage = Event {0} specifies an Admin channel {1}. It must specify a Message property.
+EventSource_UnsupportedMessageProperty = Event {0} specifies an illegal or unsupported formatting message ("{1}").
+EventSource_AbstractMustNotDeclareKTOC = Abstract event source must not declare {0} nested type.
+EventSource_AbstractMustNotDeclareEventMethods = Abstract event source must not declare event methods ({0} with ID {1}).
+EventSource_EventMustNotBeExplicitImplementation = Event method {0} (with ID {1}) is an explicit interface method implementation. Re-write method as implicit implementation.
+EventSource_EventParametersMismatch = Event {0} was called with {1} argument(s), but it is defined with {2} parameter(s).
+EventSource_InvalidCommand = Invalid command value.
+EventSource_InvalidEventFormat = Can't specify both etw event format flags.
+EventSource_AddScalarOutOfRange = Getting out of bounds during scalar addition.
+EventSource_PinArrayOutOfRange = Pins are out of range.
+EventSource_DataDescriptorsOutOfRange = Data descriptors are out of range.
+EventSource_NotSupportedArrayOfNil = Arrays of Nil are not supported.
+EventSource_NotSupportedArrayOfBinary = Arrays of Binary are not supported.
+EventSource_NotSupportedArrayOfNullTerminatedString = Arrays of null-terminated string are not supported.
+EventSource_TooManyFields = Too many fields in structure.
+EventSource_RecursiveTypeDefinition = Recursive type definition is not supported.
+EventSource_NotSupportedEnumType = Enum type {0} underlying type {1} is not supported for serialization.
+EventSource_NonCompliantTypeError = The API supports only anonymous types or types decorated with the EventDataAttribute. Non-compliant type: {0} dataType.
+EventSource_NotSupportedNestedArraysEnums = Nested arrays/enumerables are not supported.
+EventSource_IncorrentlyAuthoredTypeInfo = Incorrectly-authored TypeInfo - a type should be serialized as one field or as one group
+EventSource_NotSupportedCustomSerializedData = Enumerables of custom-serialized data are not supported
+EventSource_StopsFollowStarts = An event with stop suffix must follow a corresponding event with a start suffix.
+EventSource_NoRelatedActivityId = EventSource expects the first parameter of the Event method to be of type Guid and to be named "relatedActivityId" when calling WriteEventWithRelatedActivityId.
+EventSource_VarArgsParameterMismatch = The parameters to the Event method do not match the parameters to the WriteEvent method. This may cause the event to be displayed incorrectly.
+
+; ExecutionEngineException
+ExecutionEngine_InvalidAttribute = Attribute cannot have multiple definitions.
+ExecutionEngine_MissingSecurityDescriptor = Unable to retrieve security descriptor for this frame.
+
+;;ExecutionContext
+ExecutionContext_UndoFailed = Undo operation on a component context threw an exception
+ExecutionContext_ExceptionInAsyncLocalNotification = An exception was not handled in an AsyncLocal<T> notification callback.
+
+
+; FieldAccessException
+FieldAccess_InitOnly = InitOnly (aka ReadOnly) fields can only be initialized in the type/instance constructor.
+
+; FormatException
+Format_AttributeUsage = Duplicate AttributeUsageAttribute found on attribute type {0}.
+Format_Bad7BitInt32 = Too many bytes in what should have been a 7 bit encoded Int32.
+Format_BadBase = Invalid digits for the specified base.
+Format_BadBase64Char = The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
+Format_BadBase64CharArrayLength = Invalid length for a Base-64 char array or string.
+Format_BadBoolean = String was not recognized as a valid Boolean.
+Format_BadDateTime = String was not recognized as a valid DateTime.
+Format_BadDateTimeCalendar = The DateTime represented by the string is not supported in calendar {0}.
+Format_BadDayOfWeek = String was not recognized as a valid DateTime because the day of week was incorrect.
+Format_DateOutOfRange = The DateTime represented by the string is out of range.
+Format_BadDatePattern = Could not determine the order of year, month, and date from '{0}'.
+Format_BadFormatSpecifier = Format specifier was invalid.
+Format_BadTimeSpan = String was not recognized as a valid TimeSpan.
+Format_BadQuote = Cannot find a matching quote character for the character '{0}'.
+Format_EmptyInputString = Input string was either empty or contained only whitespace.
+Format_ExtraJunkAtEnd = Additional non-parsable characters are at the end of the string.
+Format_GuidBrace = Expected {0xdddddddd, etc}.
+Format_GuidComma = Could not find a comma, or the length between the previous token and the comma was zero (i.e., '0x,'etc.).
+Format_GuidBraceAfterLastNumber = Could not find a brace, or the length between the previous token and the brace was zero (i.e., '0x,'etc.).
+Format_GuidDashes = Dashes are in the wrong position for GUID parsing.
+Format_GuidEndBrace = Could not find the ending brace.
+Format_GuidHexPrefix = Expected hex 0x in '{0}'.
+Format_GuidInvLen = Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
+Format_GuidInvalidChar = Guid string should only contain hexadecimal characters.
+Format_GuidUnrecognized = Unrecognized Guid format.
+Format_InvalidEnumFormatSpecification = Format String can be only "G", "g", "X", "x", "F", "f", "D" or "d".
+Format_InvalidGuidFormatSpecification = Format String can be only "D", "d", "N", "n", "P", "p", "B", "b", "X" or "x".
+Format_InvalidString = Input string was not in a correct format.
+Format_IndexOutOfRange = Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
+Format_UnknowDateTimeWord = The string was not recognized as a valid DateTime. There is an unknown word starting at index {0}.
+Format_NeedSingleChar = String must be exactly one character long.
+Format_NoParsibleDigits = Could not find any recognizable digits.
+Format_RepeatDateTimePattern = DateTime pattern '{0}' appears more than once with different values.
+Format_StringZeroLength = String cannot have zero length.
+Format_TwoTimeZoneSpecifiers = The String being parsed cannot contain two TimeZone specifiers.
+Format_UTCOutOfRange= The UTC representation of the date falls outside the year range 1-9999.
+Format_OffsetOutOfRange=The time zone offset must be within plus or minus 14 hours.
+Format_MissingIncompleteDate=There must be at least a partial date with a year present in the input.
+
+; IndexOutOfRangeException
+IndexOutOfRange_ArrayRankIndex = Array does not have that many dimensions.
+IndexOutOfRange_IORaceCondition = Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and StreamReader.
+IndexOutOfRange_UMSPosition = Unmanaged memory stream position was beyond the capacity of the stream.
+
+; InsufficientMemoryException
+InsufficientMemory_MemFailPoint = Insufficient available memory to meet the expected demands of an operation at this time. Please try again later.
+InsufficientMemory_MemFailPoint_TooBig = Insufficient memory to meet the expected demands of an operation, and this system is likely to never satisfy this request. If this is a 32 bit system, consider booting in 3 GB mode.
+InsufficientMemory_MemFailPoint_VAFrag = Insufficient available memory to meet the expected demands of an operation at this time, possibly due to virtual address space fragmentation. Please try again later.
+
+
+; InvalidCastException
+InvalidCast_DBNull = Object cannot be cast to DBNull.
+InvalidCast_DownCastArrayElement = At least one element in the source array could not be cast down to the destination array type.
+InvalidCast_Empty = Object cannot be cast to Empty.
+InvalidCast_FromDBNull = Object cannot be cast from DBNull to other types.
+InvalidCast_FromTo = Invalid cast from '{0}' to '{1}'.
+InvalidCast_IConvertible = Object must implement IConvertible.
+InvalidCast_OATypeMismatch = OleAut reported a type mismatch.
+InvalidCast_StoreArrayElement = Object cannot be stored in an array of this type.
+InvalidCast_CannotCoerceByRefVariant = Object cannot be coerced to the original type of the ByRef VARIANT it was obtained from.
+InvalidCast_CannotCastNullToValueType = Null object cannot be converted to a value type.
+#if FEATURE_COMINTEROP
+InvalidCast_WinRTIPropertyValueElement = Object in an IPropertyValue is of type '{0}', which cannot be converted to a '{1}'.
+InvalidCast_WinRTIPropertyValueCoersion = Object in an IPropertyValue is of type '{0}' with value '{1}', which cannot be converted to a '{2}'.
+InvalidCast_WinRTIPropertyValueArrayCoersion = Object in an IPropertyValue is of type '{0}' which cannot be convereted to a '{1}' due to array element '{2}': {3}.
+#endif // FEATURE_COMINTEROP
+
+; InvalidOperationException
+InvalidOperation_ActivationArgsAppTrustMismatch = The activation arguments and application trust for the AppDomain must correspond to the same application identity.
+InvalidOperation_AddContextFrozen = Attempted to add properties to a frozen context.
+InvalidOperation_AppDomainSandboxAPINeedsExplicitAppBase = This API requires the ApplicationBase to be specified explicitly in the AppDomainSetup parameter.
+InvalidOperation_CantCancelCtrlBreak = Applications may not prevent control-break from terminating their process.
+InvalidOperation_CalledTwice = The method cannot be called twice on the same instance.
+InvalidOperation_CollectionCorrupted = A prior operation on this collection was interrupted by an exception. Collection's state is no longer trusted.
+InvalidOperation_CriticalTransparentAreMutuallyExclusive = SecurityTransparent and SecurityCritical attributes cannot be applied to the assembly scope at the same time.
+InvalidOperation_SubclassedObject = Cannot set sub-classed {0} object to {1} object.
+InvalidOperation_ExceptionStateCrossAppDomain = Thread.ExceptionState cannot access an ExceptionState from a different AppDomain.
+InvalidOperation_DebuggerLaunchFailed = Debugger unable to launch.
+InvalidOperation_ApartmentStateSwitchFailed = Failed to set the specified COM apartment state.
+InvalidOperation_EmptyQueue = Queue empty.
+InvalidOperation_EmptyStack = Stack empty.
+InvalidOperation_CannotRemoveFromStackOrQueue = Removal is an invalid operation for Stack or Queue.
+InvalidOperation_EnumEnded = Enumeration already finished.
+InvalidOperation_EnumFailedVersion = Collection was modified; enumeration operation may not execute.
+InvalidOperation_EnumNotStarted = Enumeration has not started. Call MoveNext.
+InvalidOperation_EnumOpCantHappen = Enumeration has either not started or has already finished.
+InvalidOperation_ModifyRONumFmtInfo = Unable to modify a read-only NumberFormatInfo object.
+#if FEATURE_CAS_POLICY
+InvalidOperation_ModifyROPermSet = ReadOnlyPermissionSet objects may not be modified.
+#endif // FEATURE_CAS_POLICY
+InvalidOperation_MustBeSameThread = This operation must take place on the same thread on which the object was created.
+InvalidOperation_MustRevertPrivilege = Must revert the privilege prior to attempting this operation.
+InvalidOperation_ReadOnly = Instance is read-only.
+InvalidOperation_RegRemoveSubKey = Registry key has subkeys and recursive removes are not supported by this method.
+InvalidOperation_IComparerFailed = Failed to compare two elements in the array.
+InvalidOperation_InternalState = Invalid internal state.
+InvalidOperation_DuplicatePropertyName = Another property by this name already exists.
+InvalidOperation_NotCurrentDomain = You can only define a dynamic assembly on the current AppDomain.
+InvalidOperation_ContextAlreadyFrozen = Context is already frozen.
+InvalidOperation_WriteOnce = This property has already been set and cannot be modified.
+InvalidOperation_MethodBaked = Type definition of the method is complete.
+InvalidOperation_MethodHasBody = Method already has a body.
+InvalidOperation_ModificationOfNonCanonicalAcl = This access control list is not in canonical form and therefore cannot be modified.
+InvalidOperation_Method = This method is not supported by the current object.
+InvalidOperation_NotADebugModule = Not a debug ModuleBuilder.
+InvalidOperation_NoMultiModuleAssembly = You cannot have more than one dynamic module in each dynamic assembly in this version of the runtime.
+InvalidOperation_OpenLocalVariableScope = Local variable scope was not properly closed.
+InvalidOperation_SetVolumeLabelFailed = Volume labels can only be set for writable local volumes.
+InvalidOperation_SetData = An additional permission should not be supplied for setting loader information.
+InvalidOperation_SetData_OnlyOnce = SetData can only be used to set the value of a given name once.
+InvalidOperation_SetData_OnlyLocationURI = SetData cannot be used to set the value for '{0}'.
+InvalidOperation_TypeHasBeenCreated = Unable to change after type has been created.
+InvalidOperation_TypeNotCreated = Type has not been created.
+InvalidOperation_NoUnderlyingTypeOnEnum = Underlying type information on enumeration is not specified.
+InvalidOperation_ResMgrBadResSet_Type = '{0}': ResourceSet derived classes must provide a constructor that takes a String file name and a constructor that takes a Stream.
+InvalidOperation_AssemblyHasBeenSaved = Assembly '{0}' has been saved.
+InvalidOperation_ModuleHasBeenSaved = Module '{0}' has been saved.
+InvalidOperation_CannotAlterAssembly = Unable to alter assembly information.
+InvalidOperation_BadTransientModuleReference = Unable to make a reference to a transient module from a non-transient module.
+InvalidOperation_BadILGeneratorUsage = ILGenerator usage is invalid.
+InvalidOperation_BadInstructionOrIndexOutOfBound = MSIL instruction is invalid or index is out of bounds.
+InvalidOperation_ShouldNotHaveMethodBody = Method body should not exist.
+InvalidOperation_EntryMethodNotDefinedInAssembly = Entry method is not defined in the same assembly.
+InvalidOperation_CantSaveTransientAssembly = Cannot save a transient assembly.
+InvalidOperation_BadResourceContainer = Unable to add resource to transient module or transient assembly.
+InvalidOperation_CantInstantiateAbstractClass = Instances of abstract classes cannot be created.
+InvalidOperation_CantInstantiateFunctionPointer = Instances of function pointers cannot be created.
+InvalidOperation_BadTypeAttributesNotAbstract = Type must be declared abstract if any of its methods are abstract.
+InvalidOperation_BadInterfaceNotAbstract = Interface must be declared abstract.
+InvalidOperation_ConstructorNotAllowedOnInterface = Interface cannot have constructors.
+InvalidOperation_BadMethodBody = Method '{0}' cannot have a method body.
+InvalidOperation_MetaDataError = Metadata operation failed.
+InvalidOperation_BadEmptyMethodBody = Method '{0}' does not have a method body.
+InvalidOperation_EndInvokeCalledMultiple = EndInvoke can only be called once for each asynchronous operation.
+InvalidOperation_EndReadCalledMultiple = EndRead can only be called once for each asynchronous operation.
+InvalidOperation_EndWriteCalledMultiple = EndWrite can only be called once for each asynchronous operation.
+InvalidOperation_AsmLoadedForReflectionOnly = Assembly has been loaded as ReflectionOnly. This API requires an assembly capable of execution.
+InvalidOperation_NoAsmName = Assembly does not have an assembly name. In order to be registered for use by COM, an assembly must have a valid assembly name.
+InvalidOperation_NoAsmCodeBase = Assembly does not have a code base.
+InvalidOperation_HandleIsNotInitialized = Handle is not initialized.
+InvalidOperation_HandleIsNotPinned = Handle is not pinned.
+InvalidOperation_SlotHasBeenFreed = LocalDataStoreSlot storage has been freed.
+InvalidOperation_GlobalsHaveBeenCreated = Type definition of the global function has been completed.
+InvalidOperation_NotAVarArgCallingConvention = Calling convention must be VarArgs.
+InvalidOperation_CannotImportGlobalFromDifferentModule = Unable to import a global method or field from a different module.
+InvalidOperation_NonStaticComRegFunction = COM register function must be static.
+InvalidOperation_NonStaticComUnRegFunction = COM unregister function must be static.
+InvalidOperation_InvalidComRegFunctionSig = COM register function must have a System.Type parameter and a void return type.
+InvalidOperation_InvalidComUnRegFunctionSig = COM unregister function must have a System.Type parameter and a void return type.
+InvalidOperation_MultipleComRegFunctions = Type '{0}' has more than one COM registration function.
+InvalidOperation_MultipleComUnRegFunctions = Type '{0}' has more than one COM unregistration function.
+InvalidOperation_MustCallInitialize = You must call Initialize on this object instance before using it.
+InvalidOperation_MustLockForReadOrWrite = Object must be locked for read or write.
+InvalidOperation_MustLockForWrite = Object must be locked for read.
+InvalidOperation_NoValue = Nullable object must have a value.
+InvalidOperation_ResourceNotStream_Name = Resource '{0}' was not a Stream - call GetObject instead.
+InvalidOperation_ResourceNotString_Name = Resource '{0}' was not a String - call GetObject instead.
+InvalidOperation_ResourceNotString_Type = Resource was of type '{0}' instead of String - call GetObject instead.
+InvalidOperation_ResourceWriterSaved = The resource writer has already been closed and cannot be edited.
+InvalidOperation_UnderlyingArrayListChanged = This range in the underlying list is invalid. A possible cause is that elements were removed.
+InvalidOperation_AnonymousCannotImpersonate = An anonymous identity cannot perform an impersonation.
+InvalidOperation_DefaultConstructorILGen = Unable to access ILGenerator on a constructor created with DefineDefaultConstructor.
+InvalidOperation_DefaultConstructorDefineBody = The method body of the default constructor cannot be changed.
+InvalidOperation_ComputerName = Computer name could not be obtained.
+InvalidOperation_MismatchedAsyncResult = The IAsyncResult object provided does not match this delegate.
+InvalidOperation_PIAMustBeStrongNamed = Primary interop assemblies must be strongly named.
+InvalidOperation_HashInsertFailed = Hashtable insert failed. Load factor too high. The most common cause is multiple threads writing to the Hashtable simultaneously.
+InvalidOperation_UnknownEnumType = Unknown enum type.
+InvalidOperation_GetVersion = OSVersion's call to GetVersionEx failed.
+InvalidOperation_DateTimeParsing = Internal Error in DateTime and Calendar operations.
+InvalidOperation_UserDomainName = UserDomainName native call failed.
+InvalidOperation_WaitOnTransparentProxy = Cannot wait on a transparent proxy.
+InvalidOperation_NoPublicAddMethod = Cannot add the event handler since no public add method exists for the event.
+InvalidOperation_NoPublicRemoveMethod = Cannot remove the event handler since no public remove method exists for the event.
+InvalidOperation_NotSupportedOnWinRTEvent = Adding or removing event handlers dynamically is not supported on WinRT events.
+InvalidOperation_ConsoleKeyAvailableOnFile = Cannot see if a key has been pressed when either application does not have a console or when console input has been redirected from a file. Try Console.In.Peek.
+InvalidOperation_ConsoleReadKeyOnFile = Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.
+InvalidOperation_ThreadWrongThreadStart = The thread was created with a ThreadStart delegate that does not accept a parameter.
+InvalidOperation_ThreadAPIsNotSupported = Use CompressedStack.(Capture/Run) or ExecutionContext.(Capture/Run) APIs instead.
+InvalidOperation_NotNewCaptureContext = Cannot apply a context that has been marshaled across AppDomains, that was not acquired through a Capture operation or that has already been the argument to a Set call.
+InvalidOperation_NullContext = Cannot call Set on a null context
+InvalidOperation_CannotCopyUsedContext = Only newly captured contexts can be copied
+InvalidOperation_CannotUseSwitcherOtherThread = Undo operation must be performed on the thread where the corresponding context was Set.
+InvalidOperation_SwitcherCtxMismatch = The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone).
+InvalidOperation_CannotOverrideSetWithoutRevert = Must override both HostExecutionContextManager.SetHostExecutionContext and HostExecutionContextManager.Revert.
+InvalidOperation_CannotUseAFCOtherThread = AsyncFlowControl object must be used on the thread where it was created.
+InvalidOperation_CannotRestoreUnsupressedFlow = Cannot restore context flow when it is not suppressed.
+InvalidOperation_CannotSupressFlowMultipleTimes = Context flow is already suppressed.
+InvalidOperation_CannotUseAFCMultiple = AsyncFlowControl object can be used only once to call Undo().
+InvalidOperation_AsyncFlowCtrlCtxMismatch = AsyncFlowControl objects can be used to restore flow only on the Context that had its flow suppressed.
+InvalidOperation_TimeoutsNotSupported = Timeouts are not supported on this stream.
+InvalidOperation_Overlapped_Pack = Cannot pack a packed Overlapped again.
+InvalidOperation_OnlyValidForDS = Adding ACEs with Object Flags and Object GUIDs is only valid for directory-object ACLs.
+InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndRead was called multiple times with the same IAsyncResult.
+InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndWrite was called multiple times with the same IAsyncResult.
+InvalidOperation_WrongAsyncResultOrEndCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or the End method was called multiple times with the same IAsyncResult.
+InvalidOperation_NoSecurityDescriptor = The object does not contain a security descriptor.
+InvalidOperation_NotAllowedInReflectionOnly = The requested operation is invalid in the ReflectionOnly context.
+InvalidOperation_NotAllowedInDynamicMethod = The requested operation is invalid for DynamicMethod.
+InvalidOperation_PropertyInfoNotAvailable = This API does not support PropertyInfo tokens.
+InvalidOperation_EventInfoNotAvailable = This API does not support EventInfo tokens.
+InvalidOperation_UnexpectedWin32Error = Unexpected error when calling an operating system function. The returned error code is 0x{0:x}.
+InvalidOperation_AssertTransparentCode = Cannot perform CAS Asserts in Security Transparent methods
+InvalidOperation_NullModuleHandle = The requested operation is invalid when called on a null ModuleHandle.
+InvalidOperation_NotWithConcurrentGC = This API is not available when the concurrent GC is enabled.
+InvalidOperation_WithoutARM = This API is not available when AppDomain Resource Monitoring is not turned on.
+InvalidOperation_NotGenericType = This operation is only valid on generic types.
+InvalidOperation_TypeCannotBeBoxed = The given type cannot be boxed.
+InvalidOperation_HostModifiedSecurityState = The security state of an AppDomain was modified by an AppDomainManager configured with the NoSecurityChanges flag.
+InvalidOperation_StrongNameKeyPairRequired = A strong name key pair is required to emit a strong-named dynamic assembly.
+#if FEATURE_COMINTEROP
+InvalidOperation_EventTokenTableRequiresDelegate = Type '{0}' is not a delegate type. EventTokenTable may only be used with delegate types.
+#endif // FEATURE_COMINTEROP
+InvalidOperation_NullArray = The underlying array is null.
+;system.security.claims
+InvalidOperation_ClaimCannotBeRemoved = The Claim '{0}' was not able to be removed. It is either not part of this Identity or it is a claim that is owned by the Principal that contains this Identity. For example, the Principal will own the claim when creating a GenericPrincipal with roles. The roles will be exposed through the Identity that is passed in the constructor, but not actually owned by the Identity. Similar logic exists for a RolePrincipal.
+InvalidOperationException_ActorGraphCircular = Actor cannot be set so that circular directed graph will exist chaining the subjects together.
+InvalidOperation_AsyncIOInProgress = The stream is currently in use by a previous operation on the stream.
+InvalidOperation_APIInvalidForCurrentContext = The API '{0}' cannot be used on the current platform. See http://go.microsoft.com/fwlink/?LinkId=248273 for more information.
+
+; InvalidProgramException
+InvalidProgram_Default = Common Language Runtime detected an invalid program.
+
+; Isolated Storage
+#if FEATURE_ISOSTORE
+IsolatedStorage_AssemblyMissingIdentity = Unable to determine assembly of the caller.
+IsolatedStorage_ApplicationMissingIdentity = Unable to determine application identity of the caller.
+IsolatedStorage_DomainMissingIdentity = Unable to determine domain of the caller.
+IsolatedStorage_AssemblyGrantSet = Unable to determine granted permission for assembly.
+IsolatedStorage_DomainGrantSet = Unable to determine granted permission for domain.
+IsolatedStorage_ApplicationGrantSet = Unable to determine granted permission for application.
+IsolatedStorage_Init = Initialization failed.
+IsolatedStorage_ApplicationNoEvidence = Unable to determine identity of application.
+IsolatedStorage_AssemblyNoEvidence = Unable to determine identity of assembly.
+IsolatedStorage_DomainNoEvidence = Unable to determine the identity of domain.
+IsolatedStorage_DeleteDirectories = Unable to delete; directory or files in the directory could be in use.
+IsolatedStorage_DeleteFile = Unable to delete file.
+IsolatedStorage_CreateDirectory = Unable to create directory.
+IsolatedStorage_DeleteDirectory = Unable to delete, directory not empty or does not exist.
+IsolatedStorage_Operation_ISFS = Operation not permitted on IsolatedStorageFileStream.
+IsolatedStorage_Operation = Operation not permitted.
+IsolatedStorage_Path = Path must be a valid file name.
+IsolatedStorage_FileOpenMode = Invalid mode, see System.IO.FileMode.
+IsolatedStorage_SeekOrigin = Invalid origin, see System.IO.SeekOrigin.
+IsolatedStorage_Scope_U_R_M = Invalid scope, expected User, User|Roaming or Machine.
+IsolatedStorage_Scope_Invalid = Invalid scope.
+IsolatedStorage_Exception = An error occurred while accessing IsolatedStorage.
+IsolatedStorage_QuotaIsUndefined = {0} is not defined for this store. An operation was performed that requires access to {0}. Stores obtained using enumeration APIs do not have a well-defined {0}, since partial evidence is used to open the store.
+IsolatedStorage_CurrentSizeUndefined = Current size cannot be determined for this store.
+IsolatedStorage_DomainUndefined = Domain cannot be determined on an Assembly or Application store.
+IsolatedStorage_ApplicationUndefined = Application cannot be determined on an Assembly or Domain store.
+IsolatedStorage_AssemblyUndefined = Assembly cannot be determined for an Application store.
+IsolatedStorage_StoreNotOpen = Store must be open for this operation.
+IsolatedStorage_OldQuotaLarger = The new quota must be larger than the old quota.
+IsolatedStorage_UsageWillExceedQuota = There is not enough free space to perform the operation.
+IsolatedStorage_NotValidOnDesktop = The Site scope is currently not supported.
+IsolatedStorage_OnlyIncreaseUserApplicationStore = Increasing the quota of this scope is not supported. Only the user application scope’s quota can be increased.
+#endif // FEATURE_ISOSTORE
+
+; Verification Exception
+Verification_Exception = Operation could destabilize the runtime.
+
+; IL stub marshaler exceptions
+Marshaler_StringTooLong = Marshaler restriction: Excessively long string.
+
+; Missing (General)
+MissingConstructor_Name = Constructor on type '{0}' not found.
+MissingField = Field not found.
+MissingField_Name = Field '{0}' not found.
+MissingMember = Member not found.
+MissingMember_Name = Member '{0}' not found.
+MissingMethod_Name = Method '{0}' not found.
+MissingModule = Module '{0}' not found.
+MissingType = Type '{0}' not found.
+
+; MissingManifestResourceException
+Arg_MissingManifestResourceException = Unable to find manifest resource.
+MissingManifestResource_LooselyLinked = Could not find a manifest resource entry called "{0}" in assembly "{1}". Please check spelling, capitalization, and build rules to ensure "{0}" is being linked into the assembly.
+MissingManifestResource_NoNeutralAsm = Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "{0}" was correctly embedded or linked into assembly "{1}" at compile time, or that all the satellite assemblies required are loadable and fully signed.
+MissingManifestResource_NoNeutralDisk = Could not find any resources appropriate for the specified culture (or the neutral culture) on disk.
+MissingManifestResource_MultipleBlobs = A case-insensitive lookup for resource file "{0}" in assembly "{1}" found multiple entries. Remove the duplicates or specify the exact case.
+MissingManifestResource_ResWFileNotLoaded = Unable to load resources for resource file "{0}" in package "{1}".
+MissingManifestResource_NoPRIresources = Unable to open Package Resource Index.
+
+; MissingMember
+MissingMemberTypeRef = FieldInfo does not match the target Type.
+MissingMemberNestErr = TypedReference can only be made on nested value Types.
+
+; MissingSatelliteAssemblyException
+MissingSatelliteAssembly_Default = Resource lookup fell back to the ultimate fallback resources in a satellite assembly, but that satellite either was not found or could not be loaded. Please consider reinstalling or repairing the application.
+MissingSatelliteAssembly_Culture_Name = The satellite assembly named "{1}" for fallback culture "{0}" either could not be found or could not be loaded. This is generally a setup problem. Please consider reinstalling or repairing the application.
+
+; MulticastNotSupportedException
+Multicast_Combine = Delegates that are not of type MulticastDelegate may not be combined.
+
+; NotImplementedException
+Arg_NotImplementedException = The method or operation is not implemented.
+NotImplemented_ResourcesLongerThan2^63 = Resource files longer than 2^63 bytes are not currently implemented.
+
+; NotSupportedException
+NotSupported_NYI = This feature is not currently implemented.
+NotSupported_AbstractNonCLS = This non-CLS method is not implemented.
+NotSupported_ChangeType = ChangeType operation is not supported.
+NotSupported_ByRefLike = Cannot create boxed ByRef-like values.
+NotSupported_ByRefLike[] = Cannot create arrays of ByRef-like values.
+NotSupported_OpenType = Cannot create arrays of open type.
+NotSupported_DBNullSerial = Only one DBNull instance may exist, and calls to DBNull deserialization methods are not allowed.
+NotSupported_DelegateSerHolderSerial = DelegateSerializationHolder objects are designed to represent a delegate during serialization and are not serializable themselves.
+NotSupported_DelegateCreationFromPT = Application code cannot use Activator.CreateInstance to create types that derive from System.Delegate. Delegate.CreateDelegate can be used instead.
+NotSupported_EncryptionNeedsNTFS = File encryption support only works on NTFS partitions.
+NotSupported_FileStreamOnNonFiles = FileStream was asked to open a device that was not a file. For support for devices like 'com1:' or 'lpt1:', call CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr.
+NotSupported_FixedSizeCollection = Collection was of a fixed size.
+NotSupported_KeyCollectionSet = Mutating a key collection derived from a dictionary is not allowed.
+NotSupported_ValueCollectionSet = Mutating a value collection derived from a dictionary is not allowed.
+NotSupported_MemStreamNotExpandable = Memory stream is not expandable.
+NotSupported_ObsoleteResourcesFile = Found an obsolete .resources file in assembly '{0}'. Rebuild that .resources file then rebuild that assembly.
+NotSupported_OleAutBadVarType = The given Variant type is not supported by this OleAut function.
+NotSupported_PopulateData = This Surrogate does not support PopulateData().
+NotSupported_ReadOnlyCollection = Collection is read-only.
+NotSupported_RangeCollection = The specified operation is not supported on Ranges.
+NotSupported_SortedListNestedWrite = This operation is not supported on SortedList nested types because they require modifying the original SortedList.
+NotSupported_SubclassOverride = Derived classes must provide an implementation.
+NotSupported_TypeCannotDeserialized = Direct deserialization of type '{0}' is not supported.
+NotSupported_UnreadableStream = Stream does not support reading.
+NotSupported_UnseekableStream = Stream does not support seeking.
+NotSupported_UnwritableStream = Stream does not support writing.
+NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed = Cannot write to a BufferedStream while the read buffer is not empty if the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream can seek or avoid interleaving read and write operations on this BufferedStream.
+NotSupported_Method = Method is not supported.
+NotSupported_Constructor = Object cannot be created through this constructor.
+NotSupported_DynamicModule = The invoked member is not supported in a dynamic module.
+NotSupported_TypeNotYetCreated = The invoked member is not supported before the type is created.
+NotSupported_SymbolMethod = Not supported in an array method of a type definition that is not complete.
+NotSupported_NotDynamicModule = The MethodRental.SwapMethodBody method can only be called to swap the method body of a method in a dynamic module.
+NotSupported_DynamicAssembly = The invoked member is not supported in a dynamic assembly.
+NotSupported_NotAllTypesAreBaked = Type '{0}' was not completed.
+NotSupported_CannotSaveModuleIndividually = Unable to save a ModuleBuilder if it was created underneath an AssemblyBuilder. Call Save on the AssemblyBuilder instead.
+NotSupported_MaxWaitHandles = The number of WaitHandles must be less than or equal to 64.
+NotSupported_IllegalOneByteBranch = Illegal one-byte branch at position: {0}. Requested branch was: {1}.
+NotSupported_OutputStreamUsingTypeBuilder = Output streams do not support TypeBuilders.
+NotSupported_ValueClassCM = Custom marshalers for value types are not currently supported.
+NotSupported_Void[] = Arrays of System.Void are not supported.
+NotSupported_NoParentDefaultConstructor = Parent does not have a default constructor. The default constructor must be explicitly defined.
+NotSupported_NonReflectedType = Not supported in a non-reflected type.
+NotSupported_GlobalFunctionNotBaked = The type definition of the global function is not completed.
+NotSupported_SecurityPermissionUnion = Union is not implemented.
+NotSupported_UnitySerHolder = The UnitySerializationHolder object is designed to transmit information about other types and is not serializable itself.
+NotSupported_UnknownTypeCode = TypeCode '{0}' was not valid.
+NotSupported_WaitAllSTAThread = WaitAll for multiple handles on a STA thread is not supported.
+NotSupported_SignalAndWaitSTAThread = SignalAndWait on a STA thread is not supported.
+NotSupported_CreateInstanceWithTypeBuilder = CreateInstance cannot be used with an object of type TypeBuilder.
+NotSupported_NonUrlAttrOnMBR = UrlAttribute is the only attribute supported for MarshalByRefObject.
+NotSupported_ActivAttrOnNonMBR = Activation Attributes are not supported for types not deriving from MarshalByRefObject.
+NotSupported_ActivForCom = Activation Attributes not supported for COM Objects.
+NotSupported_NoCodepageData = No data is available for encoding {0}. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
+NotSupported_CodePage50229 = The ISO-2022-CN Encoding (Code page 50229) is not supported.
+NotSupported_DynamicAssemblyNoRunAccess = Cannot execute code on a dynamic assembly without run access.
+NotSupported_IDispInvokeDefaultMemberWithNamedArgs = Invoking default method with named arguments is not supported.
+NotSupported_Type = Type is not supported.
+NotSupported_GetMethod = The 'get' method is not supported on this property.
+NotSupported_SetMethod = The 'set' method is not supported on this property.
+NotSupported_DeclarativeUnion = Declarative unionizing of these permissions is not supported.
+NotSupported_StringComparison = The string comparison type passed in is currently not supported.
+NotSupported_WrongResourceReader_Type = This .resources file should not be read with this reader. The resource reader type is "{0}".
+NotSupported_MustBeModuleBuilder = Module argument must be a ModuleBuilder.
+NotSupported_CallToVarArg = Vararg calling convention not supported.
+NotSupported_TooManyArgs = Stack size too deep. Possibly too many arguments.
+NotSupported_DeclSecVarArg = Assert, Deny, and PermitOnly are not supported on methods with a Vararg calling convention.
+NotSupported_AmbiguousIdentity = The operation is ambiguous because the permission represents multiple identities.
+NotSupported_DynamicMethodFlags = Wrong MethodAttributes or CallingConventions for DynamicMethod. Only public, static, standard supported
+NotSupported_GlobalMethodSerialization = Serialization of global methods (including implicit serialization via the use of asynchronous delegates) is not supported.
+NotSupported_InComparableType = A type must implement IComparable<T> or IComparable to support comparison.
+NotSupported_ManagedActivation = Cannot create uninitialized instances of types requiring managed activation.
+NotSupported_ByRefReturn = ByRef return value not supported in reflection invocation.
+NotSupported_DelegateMarshalToWrongDomain = Delegates cannot be marshaled from native code into a domain other than their home domain.
+NotSupported_ResourceObjectSerialization = Cannot read resources that depend on serialization.
+NotSupported_One = The arithmetic type '{0}' cannot represent the number one.
+NotSupported_Zero = The arithmetic type '{0}' cannot represent the number zero.
+NotSupported_MaxValue = The arithmetic type '{0}' does not have a maximum value.
+NotSupported_MinValue = The arithmetic type '{0}' does not have a minimum value.
+NotSupported_PositiveInfinity = The arithmetic type '{0}' cannot represent positive infinity.
+NotSupported_NegativeInfinity = The arithmetic type '{0}' cannot represent negative infinity.
+NotSupported_UmsSafeBuffer = This operation is not supported for an UnmanagedMemoryStream created from a SafeBuffer.
+NotSupported_Reading = Accessor does not support reading.
+NotSupported_Writing = Accessor does not support writing.
+NotSupported_UnsafePointer = This accessor was created with a SafeBuffer; use the SafeBuffer to gain access to the pointer.
+NotSupported_CollectibleCOM = COM Interop is not supported for collectible types.
+NotSupported_CollectibleAssemblyResolve = Resolving to a collectible assembly is not supported.
+NotSupported_CollectibleBoundNonCollectible = A non-collectible assembly may not reference a collectible assembly.
+NotSupported_CollectibleDelegateMarshal = Delegate marshaling for types within collectible assemblies is not supported.
+NotSupported_NonStaticMethod = Non-static methods with NativeCallableAttribute are not supported.
+NotSupported_NativeCallableTarget = Methods with NativeCallableAttribute cannot be used as delegate target.
+NotSupported_GenericMethod = Generic methods with NativeCallableAttribute are not supported.
+NotSupported_NonBlittableTypes = Non-blittable parameter types are not supported for NativeCallable methods.
+
+#if FEATURE_WINDOWSPHONE
+NotSupported_UserDllImport = DllImport cannot be used on user-defined methods.
+NotSupported_UserCOM = COM Interop is not supported for user-defined types.
+#endif //FEATURE_WINDOWSPHONE
+#if FEATURE_CAS_POLICY
+NotSupported_RequiresCasPolicyExplicit = This method explicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information.
+NotSupported_RequiresCasPolicyImplicit = This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information.
+NotSupported_CasDeny = The Deny stack modifier has been obsoleted by the .NET Framework. Please see http://go.microsoft.com/fwlink/?LinkId=155571 for more information.
+NotSupported_SecurityContextSourceAppDomainInHeterogenous = SecurityContextSource.CurrentAppDomain is not supported in heterogenous AppDomains.
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_APPX
+NotSupported_AppX = {0} is not supported in AppX.
+LoadOfFxAssemblyNotSupported_AppX = {0} of .NET Framework assemblies is not supported in AppX.
+#endif
+#if FEATURE_COMINTEROP
+NotSupported_WinRT_PartialTrust = Windows Runtime is not supported in partial trust.
+#endif // FEATURE_COMINTEROP
+; ReflectionTypeLoadException
+ReflectionTypeLoad_LoadFailed = Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
+#if !FEATURE_CORECLR
+NotSupported_NoTypeInfo = Cannot resolve {0} to a TypeInfo object.
+#endif
+#if FEATURE_COMINTEROP
+NotSupported_PIAInAppxProcess = A Primary Interop Assembly is not supported in AppX.
+#endif
+#if FEATURE_WINDOWSPHONE
+; Not referring to "Windows Phone" in the messages, as FEATURE_WINDOWSPHONE is defined for .NET Core as well.
+NotSupported_WindowsPhone = {0} is not supported.
+NotSupported_AssemblyLoadCodeBase = Assembly.Load with a Codebase is not supported.
+#endif
+
+; TypeLoadException
+TypeLoad_ResolveType = Could not resolve type '{0}'.
+TypeLoad_ResolveTypeFromAssembly = Could not resolve type '{0}' in assembly '{1}'.
+TypeLoad_ResolveNestedType = Could not resolve nested type '{0}' in type "{1}'.
+FileNotFound_ResolveAssembly = Could not resolve assembly '{0}'.
+
+; NullReferenceException
+NullReference_This = The pointer for this method was null.
+
+; ObjectDisposedException
+ObjectDisposed_Generic = Cannot access a disposed object.
+ObjectDisposed_FileClosed = Cannot access a closed file.
+ObjectDisposed_ObjectName_Name = Object name: '{0}'.
+ObjectDisposed_ReaderClosed = Cannot read from a closed TextReader.
+ObjectDisposed_ResourceSet = Cannot access a closed resource set.
+ObjectDisposed_RegKeyClosed = Cannot access a closed registry key.
+ObjectDisposed_StreamClosed = Cannot access a closed Stream.
+ObjectDisposed_WriterClosed = Cannot write to a closed TextWriter.
+ObjectDisposed_ViewAccessorClosed = Cannot access a closed accessor.
+
+; OperationCanceledException
+OperationCanceled = The operation was canceled.
+
+; OutOfMemoryException
+OutOfMemory_GCHandleMDA = The GCHandle MDA has run out of available cookies.
+
+; OverflowException
+Overflow_Byte = Value was either too large or too small for an unsigned byte.
+Overflow_Char = Value was either too large or too small for a character.
+Overflow_Currency = Value was either too large or too small for a Currency.
+Overflow_Decimal = Value was either too large or too small for a Decimal.
+Overflow_Int16 = Value was either too large or too small for an Int16.
+Overflow_Int32 = Value was either too large or too small for an Int32.
+Overflow_Int64 = Value was either too large or too small for an Int64.
+Overflow_NegateTwosCompNum = Negating the minimum value of a twos complement number is invalid.
+Overflow_NegativeUnsigned = The string was being parsed as an unsigned number and could not have a negative sign.
+Overflow_SByte = Value was either too large or too small for a signed byte.
+Overflow_Single = Value was either too large or too small for a Single.
+Overflow_Double = Value was either too large or too small for a Double.
+Overflow_TimeSpanTooLong = TimeSpan overflowed because the duration is too long.
+Overflow_TimeSpanElementTooLarge = The TimeSpan could not be parsed because at least one of the numeric components is out of range or contains too many digits.
+Overflow_Duration = The duration cannot be returned for TimeSpan.MinValue because the absolute value of TimeSpan.MinValue exceeds the value of TimeSpan.MaxValue.
+Overflow_UInt16 = Value was either too large or too small for a UInt16.
+Overflow_UInt32 = Value was either too large or too small for a UInt32.
+Overflow_UInt64 = Value was either too large or too small for a UInt64.
+
+; PlatformNotsupportedException
+PlatformNotSupported_RequiresLonghorn = This operation is only supported on Windows Vista and above.
+PlatformNotSupported_RequiresNT = This operation is only supported on Windows 2000, Windows XP, and higher.
+PlatformNotSupported_RequiresW2kSP3 = This operation is only supported on Windows 2000 SP3 or later operating systems.
+#if FEATURE_COMINTEROP
+PlatformNotSupported_WinRT = Windows Runtime is not supported on this operating system.
+#endif // FEATURE_COMINTEROP
+
+; PolicyException
+; This still appears in bcl.small but should go away eventually
+Policy_Default = Error occurred while performing a policy operation.
+Policy_CannotLoadSemiTrustAssembliesDuringInit = All assemblies loaded as part of AppDomain initialization must be fully trusted.
+#if FEATURE_IMPERSONATION
+Policy_PrincipalTwice = Default principal object cannot be set twice.
+#endif // FEATURE_IMPERSONATION
+#if FEATURE_CAS_POLICY
+Policy_PolicyAlreadySet = Policy for this domain cannot be set twice.
+Policy_NoExecutionPermission = Execution permission cannot be acquired.
+Policy_NoRequiredPermission = Required permissions cannot be acquired.
+Policy_MultipleExclusive = More than one exclusive group is not allowed.
+Policy_RecoverNotFileBased = PolicyLevel object not based on a file cannot be recovered.
+Policy_RecoverNoConfigFile = No old configuration file exists to recover.
+Policy_UnableToSave = Policy level '{0}' could not be saved: {1}.
+Policy_BadXml = Policy configuration XML is invalid. The required tag '{0}' is missing.
+Policy_NonFullTrustAssembly = Policy references an assembly not in the full trust assemblies list.
+Policy_MissingActivationContextInAppEvidence = The application evidence does not contain a Fusion activation context.
+Policy_NoTrustManager = A trust manager could not be loaded for this application.
+Policy_GrantSetDoesNotMatchDomain = An assembly was provided an invalid grant set by runtime host '{0}'. In a homogenous AppDomain, the only valid grant sets are FullTrust and the AppDomain's sandbox grant set.
+#endif // FEATURE_CAS_POLICY
+Policy_SaveNotFileBased = PolicyLevel object not based on a file cannot be saved.
+Policy_AppTrustMustGrantAppRequest = ApplicationTrust grant set does not contain ActivationContext's minimum request set.
+
+Error_SecurityPolicyFileParse = Error occurred while parsing the '{0}' policy level. The default policy level was used instead.
+Error_SecurityPolicyFileParseEx = Error '{1}' occurred while parsing the '{0}' policy level. The default policy level was used instead.
+
+#if FEATURE_CAS_POLICY
+Policy_EvidenceMustBeSerializable = Objects used as evidence must be serializable.
+Policy_DuplicateEvidence = The evidence collection already contains evidence of type '{0}'. Multiple pieces of the same type of evidence are not allowed.
+Policy_IncorrectHostEvidence = Runtime host '{0}' returned evidence of type '{1}' from a request for evidence of type '{2}'.
+Policy_NullHostEvidence = Runtime host '{0}' returned null when asked for assembly evidence for assembly '{1}'.
+Policy_NullHostGrantSet = Runtime host '{0}' returned a null grant set from ResolvePolicy.
+#endif // FEATURE_CAS_POLICY
+
+; Policy codegroup and permission set names and descriptions
+#if FEATURE_CAS_POLICY
+Policy_AllCode_Name = All_Code
+Policy_AllCode_DescriptionFullTrust = Code group grants all code full trust and forms the root of the code group tree.
+Policy_AllCode_DescriptionNothing = Code group grants no permissions and forms the root of the code group tree.
+Policy_MyComputer_Name = My_Computer_Zone
+Policy_MyComputer_Description = Code group grants full trust to all code originating on the local computer
+Policy_Intranet_Name = LocalIntranet_Zone
+Policy_Intranet_Description = Code group grants the intranet permission set to code from the intranet zone. This permission set grants intranet code the right to use isolated storage, full UI access, some capability to do reflection, and limited access to environment variables.
+Policy_IntranetNet_Name = Intranet_Same_Site_Access
+Policy_IntranetNet_Description = All intranet code gets the right to connect back to the site of its origin.
+Policy_IntranetFile_Name = Intranet_Same_Directory_Access
+Policy_IntranetFile_Description = All intranet code gets the right to read from its install directory.
+Policy_Internet_Name = Internet_Zone
+Policy_Internet_Description = Code group grants code from the Internet zone the Internet permission set. This permission set grants Internet code the right to use isolated storage and limited UI access.
+Policy_InternetNet_Name = Internet_Same_Site_Access
+Policy_InternetNet_Description = All Internet code gets the right to connect back to the site of its origin.
+Policy_Trusted_Name = Trusted_Zone
+Policy_Trusted_Description = Code from a trusted zone is granted the Internet permission set. This permission set grants the right to use isolated storage and limited UI access.
+Policy_TrustedNet_Name = Trusted_Same_Site_Access
+Policy_TrustedNet_Description = All Trusted Code gets the right to connect back to the site of its origin.
+Policy_Untrusted_Name = Restricted_Zone
+Policy_Untrusted_Description = Code coming from a restricted zone does not receive any permissions.
+Policy_Microsoft_Name = Microsoft_Strong_Name
+Policy_Microsoft_Description = Code group grants full trust to code signed with the Microsoft strong name.
+Policy_Ecma_Name = ECMA_Strong_Name
+Policy_Ecma_Description = Code group grants full trust to code signed with the ECMA strong name.
+
+; Policy permission set descriptions
+Policy_PS_FullTrust = Allows full access to all resources
+Policy_PS_Everything = Allows unrestricted access to all resources covered by built-in permissions
+Policy_PS_Nothing = Denies all resources, including the right to execute
+Policy_PS_Execution = Permits execution
+Policy_PS_SkipVerification = Grants right to bypass the verification
+Policy_PS_Internet = Default rights given to Internet applications
+Policy_PS_LocalIntranet = Default rights given to applications on the local intranet
+
+; default Policy level names
+Policy_PL_Enterprise = Enterprise
+Policy_PL_Machine = Machine
+Policy_PL_User = User
+Policy_PL_AppDomain = AppDomain
+#endif // FEATURE_CAS_POLICY
+
+; RankException
+Rank_MultiDimNotSupported = Only single dimension arrays are supported here.
+Rank_MustMatch = The specified arrays must have the same number of dimensions.
+
+; TypeInitializationException
+TypeInitialization_Default = Type constructor threw an exception.
+TypeInitialization_Type = The type initializer for '{0}' threw an exception.
+
+; TypeLoadException
+
+
+;
+; Reflection exceptions
+;
+RtType.InvalidCaller = Caller is not a friend.
+
+;CustomAttributeFormatException
+RFLCT.InvalidPropFail = '{0}' property specified was not found.
+RFLCT.InvalidFieldFail = '{0}' field specified was not found.
+
+;InvalidFilterCriteriaException
+RFLCT.FltCritString = A String must be provided for the filter criteria.
+RFLCT.FltCritInt = An Int32 must be provided for the filter criteria.
+
+; TargetException
+RFLCT.Targ_ITargMismatch = Object does not match target type.
+RFLCT.Targ_StatMethReqTarg = Non-static method requires a target.
+RFLCT.Targ_StatFldReqTarg = Non-static field requires a target.
+
+;AmbiguousMatchException
+RFLCT.Ambiguous = Ambiguous match found.
+RFLCT.AmbigCust = Multiple custom attributes of the same type found.
+
+;
+; Remoting exceptions
+;
+Remoting_AppDomainUnloaded_ThreadUnwound = The application domain in which the thread was running has been unloaded.
+Remoting_AppDomainUnloaded = The target application domain has been unloaded.
+Remoting_CantRemotePointerType = Pointer types cannot be passed in a remote call.
+Remoting_TypeCantBeRemoted = The given type cannot be passed in a remote call.
+Remoting_Delegate_TooManyTargets = The delegate must have only one target.
+Remoting_InvalidContext = The context is not valid.
+Remoting_InvalidValueTypeFieldAccess = An attempt was made to calculate the address of a value type field on a remote object. This was likely caused by an attempt to directly get or set the value of a field within this embedded value type. Avoid this and instead provide and use access methods for each field in the object that will be accessed remotely.
+Remoting_Message_BadRetValOrOutArg = Bad return value or out-argument inside the return message.
+Remoting_NonPublicOrStaticCantBeCalledRemotely = Permission denied: cannot call non-public or static methods remotely.
+Remoting_Proxy_ProxyTypeIsNotMBR = classToProxy argument must derive from MarshalByRef type.
+Remoting_TP_NonNull = The transparent proxy field of a real proxy must be null.
+#if FEATURE_REMOTING
+Remoting_Activation_BadAttribute = Activation attribute does not implement the IContextAttribute interface.
+Remoting_Activation_BadObject = Proxy Attribute returned an incompatible object when constructing an instance of type {0}.
+Remoting_Activation_MBR_ProxyAttribute = Proxy Attributes are supported on ContextBound types only.
+Remoting_Activation_ConnectFailed = An attempt to connect to the remote activator failed with exception '{0}'.
+Remoting_Activation_Failed = Activation failed due to an unknown reason.
+Remoting_Activation_InconsistentState = Inconsistent state during activation; there may be two proxies for the same object.
+Remoting_Activation_MissingRemoteAppEntry = Cannot find an entry for remote application '{0}'.
+Remoting_Activation_NullReturnValue = Return value of construction call was null.
+Remoting_Activation_NullFromInternalUnmarshal = InternalUnmarshal of returned ObjRef from activation call returned null.
+Remoting_Activation_WellKnownCTOR = Cannot run a non-default constructor when connecting to well-known objects.
+Remoting_Activation_PermissionDenied = Type '{0}' is not registered for activation.
+Remoting_Activation_PropertyUnhappy = A context property did not approve the candidate context for activating the object.
+Remoting_Activation_AsyncUnsupported = Async Activation not supported.
+Remoting_AmbiguousCTOR = Cannot resolve the invocation to the correct constructor.
+Remoting_AmbiguousMethod = Cannot resolve the invocation to the correct method.
+Remoting_AppDomains_NYI = This feature is not yet supported for cross-application domain.
+Remoting_AppDomainsCantBeCalledRemotely = Permission denied: cannot call methods on the AppDomain class remotely.
+Remoting_AssemblyLoadFailed = Cannot load assembly '{0}'.
+Remoting_Attribute_UseAttributeNotsettable = UseAttribute not allowed in SoapTypeAttribute.
+Remoting_BadType = Cannot load type '{0}'.
+Remoting_BadField = Remoting cannot find field '{0}' on type '{1}'.
+Remoting_BadInternalState_ActivationFailure = Invalid internal state: Activation service failed to initialize.
+Remoting_BadInternalState_ProxySameAppDomain = Invalid internal state: A marshal by ref object should not have a proxy in its own AppDomain.
+Remoting_BadInternalState_FailEnvoySink = Invalid internal state: Failed to create an envoy sink for the object.
+Remoting_CantDisconnectClientProxy = Cannot call disconnect on a proxy.
+Remoting_CantInvokeIRemoteDispatch = Cannot invoke methods on IRemoteDispatch.
+Remoting_ChannelNameAlreadyRegistered = The channel '{0}' is already registered.
+Remoting_ChannelNotRegistered = The channel '{0}' is not registered with remoting services.
+Remoting_Channel_PopOnEmptySinkStack = Tried to pop data from an empty channel sink stack.
+Remoting_Channel_PopFromSinkStackWithoutPush = A channel sink tried to pop data from the stack without first pushing data onto the stack.
+Remoting_Channel_StoreOnEmptySinkStack = A channel sink called the Store method when the sink stack was empty.
+Remoting_Channel_StoreOnSinkStackWithoutPush = A channel sink called the Store method on the sink stack without first pushing data onto the stack.
+Remoting_Channel_CantCallAPRWhenStackEmpty = Cannot call the AsyncProcessResponse method on the previous channel sink because the stack is empty.
+Remoting_Channel_CantCallFRSWhenStackEmtpy = Called FlipRememberedStack() when stack was not null.
+Remoting_Channel_CantCallGetResponseStreamWhenStackEmpty = Cannot call the GetResponseStream method on the previous channel sink because the stack is empty.
+Remoting_Channel_DispatchSinkMessageMissing = No message was deserialized prior to calling the DispatchChannelSink.
+Remoting_Channel_DispatchSinkWantsNullRequestStream = The request stream should be null when the DispatchChannelSink is called.
+Remoting_Channel_CannotBeSecured = Channel {0} cannot be secured. Please consider using a channel that implements ISecurableChannel
+Remoting_Config_ChannelMissingCtor = To be used from a .config file, the channel type '{0}' must have a constructor of the form '{1}'
+Remoting_Config_SinkProviderMissingCtor = To be used from a .config file, the sink provider type '{0}' must have a constructor of the form '{1}'
+Remoting_Config_SinkProviderNotFormatter = A sink provider of type '{0}' is incorrectly labeled as a 'formatter'.
+Remoting_Config_ConfigurationFailure = Remoting configuration failed with the exception '{0}'.
+Remoting_Config_InvalidTimeFormat = Invalid time format '{0}'. Examples of valid time formats include 7D, 10H, 5M, 30S, or 20MS.
+Remoting_Config_AppNameSet = The remoting application name, '{0}', had already been set.
+Remoting_Config_ErrorsModeSet = The remoting custom errors mode had already been set.
+Remoting_Config_CantRedirectActivationOfWellKnownService = Attempt to redirect activation for type '{0}, {1}'. This is not allowed since either a well-known service type has already been registered with that type or that type has been registered has a activated service type.
+Remoting_Config_CantUseRedirectedTypeForWellKnownService = Attempt to register a well-known or activated service type of type '{0}, {1}'. This is not allowed since the type has already been redirected to activate elsewhere.
+Remoting_Config_InvalidChannelType = '{0}' does not implement IChannelReceiver or IChannelSender. All channels must implement one of these interfaces.
+Remoting_Config_InvalidSinkProviderType = Unable to use '{0}' as a channel sink provider. It does not implement '{1}'.
+Remoting_Config_MissingWellKnownModeAttribute = Well-known service entries must contain a 'mode' attribute with a value of 'Singleton' or 'SingleCall'.
+Remoting_Config_MissingTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'typeName, assemblyName'.
+Remoting_Config_MissingXmlTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'xmlTypeName, xmlTypeNamespace'.
+Remoting_Config_NoAppName = Improper remoting configuration: missing ApplicationName property.
+Remoting_Config_NonTemplateIdAttribute = Only '{0}' templates can have an 'id' attribute.
+Remoting_Config_PreloadRequiresTypeOrAssembly = Preload entries require a type or assembly attribute.
+Remoting_Config_ProviderNeedsElementName = Sink providers must have an element name of 'formatter' or 'provider'.
+Remoting_Config_RequiredXmlAttribute = '{0}' entries require a '{1}' attribute.
+Remoting_Config_ReadFailure = .Config file '{0}' cannot be read successfully due to exception '{1}'.
+Remoting_Config_NodeMustBeUnique = There can be only one '{0}' node in the '{1}' section of a config file.
+Remoting_Config_TemplateCannotReferenceTemplate = A '{0}' template cannot reference another '{0}' template.
+Remoting_Config_TypeAlreadyRedirected = Attempt to redirect activation of type '{0}, {1}' which is already redirected.
+Remoting_Config_UnknownValue = Unknown value {1} was found on the {0} node.
+Remoting_Config_UnableToResolveTemplate = Cannot resolve '{0}' template reference: '{1}'.
+Remoting_Config_VersionPresent = Version information is present in the assembly name '{0}' which is not allowed for '{1}' entries.
+Remoting_Contexts_BadProperty = A property that contributed a bad sink to the chain was found.
+Remoting_Contexts_NoProperty = A property with the name '{0}' was not found.
+Remoting_Contexts_ContextNotFrozenForCallBack = Context should be frozen before calling the DoCallBack method.
+Remoting_Default = Unknown remoting error.
+Remoting_HandlerNotRegistered = The tracking handler of type '{0}' is not registered with Remoting Services.
+Remoting_InvalidMsg = Invalid Message Object.
+Remoting_InvalidCallingType = Attempted to call a method declared on type '{0}' on an object which exposes '{1}'.
+Remoting_InvalidRequestedType = The server object type cannot be cast to the requested type '{0}'.
+Remoting_InternalError = Server encountered an internal error. For more information, turn off customErrors in the server's .config file.
+Remoting_Lifetime_ILeaseReturn = Expected a return object of type ILease, but received '{0}'.
+Remoting_Lifetime_InitialStateInitialLeaseTime = InitialLeaseTime property can only be set when the lease is in initial state. The state is '{0}'.
+Remoting_Lifetime_InitialStateRenewOnCall = RenewOnCallTime property can only be set when the lease is in initial state. The state is '{0}'.
+Remoting_Lifetime_InitialStateSponsorshipTimeout = SponsorshipTimeout property can only be set when the lease is in initial state. State is '{0}'.
+Remoting_Lifetime_SetOnce = '{0}' can only be set once within an AppDomain.
+Remoting_Message_ArgMismatch = {2} arguments were passed to '{0}::{1}'. {3} arguments were expected by this method.
+Remoting_Message_BadAsyncResult = The async result object is null or of an unexpected type.
+Remoting_Message_BadType = The method was called with a Message of an unexpected type.
+Remoting_Message_CoercionFailed = The argument type '{0}' cannot be converted into parameter type '{1}'.
+Remoting_Message_MissingArgValue = Expecting an instance of type '{0}' at pos {1} in the args array.
+Remoting_Message_BadSerialization = Invalid or malformed serialization information for the message object.
+Remoting_NoIdentityEntry = No remoting information was found for this object.
+Remoting_NotRemotableByReference = Trying to create a proxy to an unbound type.
+Remoting_NullMessage = The method was called with a null message.
+Remoting_Proxy_BadType = The proxy is of an unsupported type.
+Remoting_ResetURI = Attempt to reset the URI for an object from '{0}' to '{1}'.
+Remoting_ServerObjectNotFound = The server object for URI '{0}' is not registered with the remoting infrastructure (it may have been disconnected).
+Remoting_SetObjectUriForMarshal__ObjectNeedsToBeLocal = SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.
+Remoting_SetObjectUriForMarshal__UriExists = SetObjectUriForMarshal method has already been called on this object or the object has already been marshaled.
+Remoting_Proxy_BadReturnType = Return argument has an invalid type.
+Remoting_Proxy_ReturnValueTypeCannotBeNull = ByRef value type parameter cannot be null.
+Remoting_Proxy_BadReturnTypeForActivation = Bad return type for activation call via Invoke: must be of type IConstructionReturnMessage.
+Remoting_Proxy_BadTypeForActivation = Type mismatch between proxy type '{0}' and activation type '{1}'.
+Remoting_Proxy_ExpectedOriginalMessage = The message passed to Invoke should be passed to PropagateOutParameters.
+Remoting_Proxy_InvalidCall = Trying to call proxy while constructor call is in progress.
+Remoting_Proxy_InvalidState = Channel sink does not exist. Failed to dispatch async call.
+Remoting_Proxy_NoChannelSink = This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server.
+Remoting_Proxy_InvalidCallType = Only the synchronous call type is supported for messages that are not of type Message.
+Remoting_Proxy_WrongContext = ExecuteMessage can be called only from the native context of the object.
+Remoting_SOAPInteropxsdInvalid = Soap Parse error, xsd:type '{0}' invalid {1}
+Remoting_SOAPQNameNamespace = SoapQName missing a Namespace value '{0}'.
+Remoting_ThreadAffinity_InvalidFlag = The specified flag '{0}' does not have one of the valid values.
+Remoting_TrackingHandlerAlreadyRegistered = The handler has already been registered with TrackingServices.
+Remoting_URIClash = Found two different objects associated with the same URI, '{0}'.
+Remoting_URIExists = The remoted object already has an associated URI.
+Remoting_URIToProxy = Trying to associate the URI with a proxy.
+Remoting_WellKnown_MustBeMBR = Attempted to create well-known object of type '{0}'. Well-known objects must derive from the MarshalByRefObject class.
+Remoting_WellKnown_CtorCantMarshal = '{0}': A well-known object cannot marshal itself in its constructor, or perform any action that would cause it to be marshaled (such as passing the 'this' pointer as a parameter to a remote method).
+Remoting_WellKnown_CantDirectlyConnect = Attempt to connect to a server using its object URI: '{0}'. A valid, complete URL must be used.
+Remoting_Connect_CantCreateChannelSink = Cannot create channel sink to connect to URL '{0}'. An appropriate channel has probably not been registered.
+Remoting_UnexpectedNullTP = Failed to create a transparent proxy. If a custom RealProxy is being used ensure it sets the proxy type.
+; The following remoting exception messages appear in native resources too (mscorrc.rc)
+Remoting_Disconnected = Object '{0}' has been disconnected or does not exist at the server.
+Remoting_Message_MethodMissing = The method '{0}' was not found on the interface/type '{1}'.
+#endif // FEATURE_REMOTING
+
+; Resources exceptions
+;
+Resources_StreamNotValid = Stream is not a valid resource file.
+ResourceReaderIsClosed = ResourceReader is closed.
+
+; RuntimeWrappedException
+RuntimeWrappedException = An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException.
+
+; UnauthorizedAccessException
+UnauthorizedAccess_MemStreamBuffer = MemoryStream's internal buffer cannot be accessed.
+UnauthorizedAccess_IODenied_Path = Access to the path '{0}' is denied.
+UnauthorizedAccess_IODenied_NoPathName = Access to the path is denied.
+UnauthorizedAccess_RegistryKeyGeneric_Key = Access to the registry key '{0}' is denied.
+UnauthorizedAccess_RegistryNoWrite = Cannot write to the registry key.
+UnauthorizedAccess_SystemDomain = Cannot execute an assembly in the system domain.
+
+;
+; Security exceptions
+;
+
+;SecurityException
+; These still appear in bcl.small but should go away eventually
+Security_Generic = Request for the permission of type '{0}' failed.
+Security_GenericNoType = Request failed.
+Security_NoAPTCA = That assembly does not allow partially trusted callers.
+Security_RegistryPermission = Requested registry access is not allowed.
+Security_MustRevertOverride = Stack walk modifier must be reverted before another modification of the same type can be performed.
+#if FEATURE_CAS_POLICY
+Security_CannotGenerateHash = Hash for the assembly cannot be generated.
+Security_CannotGetRawData = Assembly bytes could not be retrieved.
+Security_PrincipalPermission = Request for principal permission failed.
+Security_Action = The action that failed was:
+Security_TypeFirstPermThatFailed = The type of the first permission that failed was:
+Security_FirstPermThatFailed = The first permission that failed was:
+Security_Demanded = The demand was for:
+Security_GrantedSet = The granted set of the failing assembly was:
+Security_RefusedSet = The refused set of the failing assembly was:
+Security_Denied = The denied permissions were:
+Security_PermitOnly = The only permitted permissions were:
+Security_Assembly = The assembly or AppDomain that failed was:
+Security_Method = The method that caused the failure was:
+Security_Zone = The Zone of the assembly that failed was:
+Security_Url = The Url of the assembly that failed was:
+Security_AnonymouslyHostedDynamicMethodCheckFailed = The demand failed due to the code access security information captured during the creation of an anonymously hosted dynamic method. In order for this operation to succeed, ensure that the demand would have succeeded at the time the method was created. See http://go.microsoft.com/fwlink/?LinkId=288746 for more information.
+#endif // FEATURE_CAS_POLICY
+
+;
+; HostProtection exceptions
+;
+
+HostProtection_HostProtection = Attempted to perform an operation that was forbidden by the CLR host.
+HostProtection_ProtectedResources = The protected resources (only available with full trust) were:
+HostProtection_DemandedResources = The demanded resources were:
+
+;
+; IO exceptions
+;
+
+; EOFException
+IO.EOF_ReadBeyondEOF = Unable to read beyond the end of the stream.
+
+; FileNotFoundException
+IO.FileNotFound = Unable to find the specified file.
+IO.FileNotFound_FileName = Could not find file '{0}'.
+IO.FileName_Name = File name: '{0}'
+IO.FileLoad = Could not load the specified file.
+
+; IOException
+IO.IO_AlreadyExists_Name = Cannot create "{0}" because a file or directory with the same name already exists.
+IO.IO_BindHandleFailed = BindHandle for ThreadPool failed on this handle.
+IO.IO_FileExists_Name = The file '{0}' already exists.
+IO.IO_FileStreamHandlePosition = The OS handle's position is not what FileStream expected. Do not use a handle simultaneously in one FileStream and in Win32 code or another FileStream. This may cause data loss.
+IO.IO_FileTooLong2GB = The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size.
+IO.IO_FileTooLongOrHandleNotSync = IO operation will not work. Most likely the file will become too long or the handle was not opened to support synchronous IO operations.
+IO.IO_FixedCapacity = Unable to expand length of this stream beyond its capacity.
+IO.IO_InvalidStringLen_Len = BinaryReader encountered an invalid string length of {0} characters.
+IO.IO_NoConsole = There is no console.
+IO.IO_NoPermissionToDirectoryName = <Path discovery permission to the specified directory was denied.>
+IO.IO_SeekBeforeBegin = An attempt was made to move the position before the beginning of the stream.
+IO.IO_SeekAppendOverwrite = Unable seek backward to overwrite data that previously existed in a file opened in Append mode.
+IO.IO_SetLengthAppendTruncate = Unable to truncate data that previously existed in a file opened in Append mode.
+IO.IO_SharingViolation_File = The process cannot access the file '{0}' because it is being used by another process.
+IO.IO_SharingViolation_NoFileName = The process cannot access the file because it is being used by another process.
+IO.IO_StreamTooLong = Stream was too long.
+IO.IO_CannotCreateDirectory = The specified directory '{0}' cannot be created.
+IO.IO_SourceDestMustBeDifferent = Source and destination path must be different.
+IO.IO_SourceDestMustHaveSameRoot = Source and destination path must have identical roots. Move will not work across volumes.
+
+; DirectoryNotFoundException
+IO.DriveNotFound_Drive = Could not find the drive '{0}'. The drive might not be ready or might not be mapped.
+IO.PathNotFound_Path = Could not find a part of the path '{0}'.
+IO.PathNotFound_NoPathName = Could not find a part of the path.
+
+; PathTooLongException
+IO.PathTooLong = The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
+
+#if FEATURE_CORECLR
+; SecurityException
+FileSecurityState_OperationNotPermitted = File operation not permitted. Access to path '{0}' is denied.
+#endif
+
+; PrivilegeNotHeldException
+PrivilegeNotHeld_Default = The process does not possess some privilege required for this operation.
+PrivilegeNotHeld_Named = The process does not possess the '{0}' privilege which is required for this operation.
+
+; General strings used in the IO package
+IO_UnknownFileName = [Unknown]
+IO_StreamWriterBufferedDataLost = A StreamWriter was not closed and all buffered data within that StreamWriter was not flushed to the underlying stream. (This was detected when the StreamWriter was finalized with data in its buffer.) A portion of the data was lost. Consider one of calling Close(), Flush(), setting the StreamWriter's AutoFlush property to true, or allocating the StreamWriter with a "using" statement. Stream type: {0}\r\nFile name: {1}\r\nAllocated from:\r\n {2}
+IO_StreamWriterBufferedDataLostCaptureAllocatedFromCallstackNotEnabled = callstack information is not captured by default for performance reasons. Please enable captureAllocatedCallStack config switch for streamWriterBufferedDataLost MDA (refer to MSDN MDA documentation for how to do this).
+
+;
+; Serialization Exceptions
+;
+; SerializationException
+Serialization_InvalidData=An error occurred while deserializing the object. The serialized data is corrupt.
+Serialization_InvalidPtrValue = An IntPtr or UIntPtr with an eight byte value cannot be deserialized on a machine with a four byte word size.
+Serialization_MemberTypeNotRecognized = Unknown member type.
+Serialization_InsufficientState = Insufficient state to return the real object.
+Serialization_InvalidFieldState = Object fields may not be properly initialized.
+Serialization_MissField = Field {0} is missing.
+Serialization_NullSignature = The method signature cannot be null.
+Serialization_UnknownMember = Cannot get the member '{0}'.
+Serialization_InsufficientDeserializationState = Insufficient state to deserialize the object. Missing field '{0}'. More information is needed.
+Serialization_UnableToFindModule = The given module {0} cannot be found within the assembly {1}.
+Serialization_InvalidOnDeser = OnDeserialization method was called while the object was not being deserialized.
+Serialization_MissingKeys = The Keys for this Hashtable are missing.
+Serialization_MissingValues = The values for this dictionary are missing.
+Serialization_NullKey = One of the serialized keys is null.
+Serialization_KeyValueDifferentSizes = The keys and values arrays have different sizes.
+Serialization_SameNameTwice = Cannot add the same member twice to a SerializationInfo object.
+Serialization_BadParameterInfo = Non existent ParameterInfo. Position bigger than member's parameters length.
+Serialization_NoParameterInfo = Serialized member does not have a ParameterInfo.
+Serialization_NotFound = Member '{0}' was not found.
+Serialization_StringBuilderMaxCapacity = The serialized MaxCapacity property of StringBuilder must be positive and greater than or equal to the String length.
+Serialization_StringBuilderCapacity = The serialized Capacity property of StringBuilder must be positive, less than or equal to MaxCapacity and greater than or equal to the String length.
+Serialization_InvalidDelegateType = Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator's assembly.
+Serialization_OptionalFieldVersionValue = Version value must be positive.
+Serialization_MissingDateTimeData = Invalid serialized DateTime data. Unable to find 'ticks' or 'dateData'.
+Serialization_DateTimeTicksOutOfRange = Invalid serialized DateTime data. Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_MemberOutOfRange = The deserialized value of the member "{0}" in the class "{1}" is out of range.
+
+#if FEATURE_SERIALIZATION
+Serialization_NoID = Object has never been assigned an objectID.
+Serialization_UnknownMemberInfo = Only FieldInfo, PropertyInfo, and SerializationMemberInfo are recognized.
+Serialization_UnableToFixup = Cannot perform fixup.
+Serialization_NoType = Object does not specify a type.
+Serialization_ValueTypeFixup = ValueType fixup on Arrays is not implemented.
+Serialization_PartialValueTypeFixup = Fixing up a partially available ValueType chain is not implemented.
+Serialization_InvalidID = Object specifies an invalid ID.
+Serialization_DuplicateSelector = Selector is already on the list of checked selectors.
+Serialization_NoBaseType = Object does not specify a base type.
+Serialization_ArrayNoLength = Array does not specify a length.
+Serialization_CannotGetType = Cannot get the type '{0}'.
+Serialization_AssemblyNotFound = Unable to find assembly '{0}'.
+Serialization_ArrayInvalidLength = Array specifies an invalid length.
+Serialization_MalformedArray = The array information in the stream is invalid.
+Serialization_MultipleMembers = Cannot resolve multiple members with the same name.
+Serialization_ObjectUsedBeforeDeserCallback = An object was used before its deserialization callback ran, which may break higher-level consistency guarantees in the application.
+Serialization_RegisterTwice = An object cannot be registered twice.
+Serialization_IdTooSmall = Object IDs must be greater than zero.
+Serialization_TooManyReferences = The implementation of the IObjectReference interface returns too many nested references to other objects that implement IObjectReference.
+Serialization_NotISer = The given object does not implement the ISerializable interface.
+Serialization_MissingKeyValuePairs = The KeyValuePairs for this Dictionary are missing.
+Serialization_SurrogateCycleInArgument = Selector contained a cycle.
+Serialization_SurrogateCycle = Adding selector will introduce a cycle.
+Serialization_NeverSeen = A fixup is registered to the object with ID {0}, but the object does not appear in the graph.
+Serialization_IORIncomplete = The object with ID {0} implements the IObjectReference interface for which all dependencies cannot be resolved. The likely cause is two instances of IObjectReference that have a mutual dependency on each other.
+Serialization_NotCyclicallyReferenceableSurrogate = {0}.SetObjectData returns a value that is neither null nor equal to the first parameter. Such Surrogates cannot be part of cyclical reference.
+Serialization_ObjectNotSupplied = The object with ID {0} was referenced in a fixup but does not exist.
+Serialization_TooManyElements = The internal array cannot expand to greater than Int32.MaxValue elements.
+Serialization_InvalidType = Only system-provided types can be passed to the GetUninitializedObject method. '{0}' is not a valid instance of a type.
+Serialization_MissingObject = The object with ID {0} was referenced in a fixup but has not been registered.
+Serialization_InvalidFixupType = A member fixup was registered for an object which implements ISerializable or has a surrogate. In this situation, a delayed fixup must be used.
+Serialization_InvalidFixupDiscovered = A fixup on an object implementing ISerializable or having a surrogate was discovered for an object which does not have a SerializationInfo available.
+Serialization_InvalidFormat = The input stream is not a valid binary format. The starting contents (in bytes) are: {0} ...
+Serialization_ParentChildIdentical = The ID of the containing object cannot be the same as the object ID.
+Serialization_IncorrectNumberOfFixups = The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_NonSerType = Type '{0}' in Assembly '{1}' is not marked as serializable.
+Serialization_ConstructorNotFound = The constructor to deserialize an object of type '{0}' was not found.
+
+; SerializationException used by Formatters
+Serialization_ArrayType = Invalid array type '{0}'.
+Serialization_ArrayTypeObject = Array element type is Object, 'dt' attribute is null.
+Serialization_Assembly = No assembly information is available for object on the wire, '{0}'.
+Serialization_AssemblyId = No assembly ID for object type '{0}'.
+Serialization_BinaryHeader = Binary stream '{0}' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
+Serialization_CrossAppDomainError = Cross-AppDomain BinaryFormatter error; expected '{0}' but received '{1}'.
+Serialization_CorruptedStream = Invalid BinaryFormatter stream.
+Serialization_HeaderReflection = Header reflection error: number of value members: {0}.
+Serialization_ISerializableTypes = Types not available for ISerializable object '{0}'.
+Serialization_ISerializableMemberInfo = MemberInfo requested for ISerializable type.
+Serialization_MBRAsMBV = Type {0} must be marshaled by reference in this context.
+Serialization_Map = No map for object '{0}'.
+Serialization_MemberInfo = MemberInfo cannot be obtained for ISerialized Object '{0}'.
+Serialization_Method = Invalid MethodCall or MethodReturn stream format.
+Serialization_MissingMember = Member '{0}' in class '{1}' is not present in the serialized stream and is not marked with {2}.
+Serialization_NoMemberInfo = No MemberInfo for Object {0}.
+Serialization_ObjNoID = Object {0} has never been assigned an objectID.
+Serialization_ObjectTypeEnum = Invalid ObjectTypeEnum {0}.
+Serialization_ParseError = Parse error. Current element is not compatible with the next element, {0}.
+Serialization_SerMemberInfo = MemberInfo type {0} cannot be serialized.
+Serialization_Stream = Attempting to deserialize an empty stream.
+Serialization_StreamEnd = End of Stream encountered before parsing was completed.
+Serialization_TopObject = No top object.
+Serialization_TopObjectInstantiate = Top object cannot be instantiated for element '{0}'.
+Serialization_TypeCode = Invalid type code in stream '{0}'.
+Serialization_TypeExpected = Invalid expected type.
+Serialization_TypeMissing = Type is missing for member of type Object '{0}'.
+Serialization_TypeRead = Invalid read type request '{0}'.
+Serialization_TypeSecurity = Type {0} and the types derived from it (such as {1}) are not permitted to be deserialized at this security level.
+Serialization_TypeWrite = Invalid write type request '{0}'.
+Serialization_XMLElement = Invalid element '{0}'.
+Serialization_Security = Because of security restrictions, the type {0} cannot be accessed.
+Serialization_TypeLoadFailure = Unable to load type {0} required for deserialization.
+Serialization_RequireFullTrust = A type '{0}' that is defined in a partially trusted assembly cannot be type forwarded from an assembly with a different Public Key Token or without a public key token. To fix this, please either turn on unsafeTypeForwarding flag in the configuration file or remove the TypeForwardedFrom attribute.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_TypeResolved = Type is not resolved for member '{0}'.
+Serialization_MemberOutOfRange = The deserialized value of the member "{0}" in the class "{1}" is out of range.
+#endif // FEATURE_SERIALIZATION
+
+;
+; StringBuilder Exceptions
+;
+Arg_LongerThanSrcString = Source string was not long enough. Check sourceIndex and count.
+
+
+;
+; System.Threading
+;
+
+;
+; Thread Exceptions
+;
+ThreadState_NoAbortRequested = Unable to reset abort because no abort was requested.
+Threading.WaitHandleTooManyPosts = The WaitHandle cannot be signaled because it would exceed its maximum count.
+;
+; WaitHandleCannotBeOpenedException
+;
+Threading.WaitHandleCannotBeOpenedException = No handle of the given name exists.
+Threading.WaitHandleCannotBeOpenedException_InvalidHandle = A WaitHandle with system-wide name '{0}' cannot be created. A WaitHandle of a different type might have the same name.
+
+;
+; AbandonedMutexException
+;
+Threading.AbandonedMutexException = The wait completed due to an abandoned mutex.
+
+; AggregateException
+AggregateException_ctor_DefaultMessage=One or more errors occurred.
+AggregateException_ctor_InnerExceptionNull=An element of innerExceptions was null.
+AggregateException_DeserializationFailure=The serialization stream contains no inner exceptions.
+AggregateException_ToString={0}{1}---> (Inner Exception #{2}) {3}{4}{5}
+
+; Cancellation
+CancellationToken_CreateLinkedToken_TokensIsEmpty=No tokens were supplied.
+CancellationTokenSource_Disposed=The CancellationTokenSource has been disposed.
+CancellationToken_SourceDisposed=The CancellationTokenSource associated with this CancellationToken has been disposed.
+
+; Exceptions shared by all concurrent collection
+ConcurrentCollection_SyncRoot_NotSupported=The SyncRoot property may not be used for the synchronization of concurrent collections.
+
+; Exceptions shared by ConcurrentStack and ConcurrentQueue
+ConcurrentStackQueue_OnDeserialization_NoData=The serialization stream contains no elements.
+
+; ConcurrentStack<T>
+ConcurrentStack_PushPopRange_StartOutOfRange=The startIndex argument must be greater than or equal to zero.
+ConcurrentStack_PushPopRange_CountOutOfRange=The count argument must be greater than or equal to zero.
+ConcurrentStack_PushPopRange_InvalidCount=The sum of the startIndex and count arguments must be less than or equal to the collection's Count.
+
+; ConcurrentDictionary<TKey, TValue>
+ConcurrentDictionary_ItemKeyIsNull=TKey is a reference type and item.Key is null.
+ConcurrentDictionary_SourceContainsDuplicateKeys=The source argument contains duplicate keys.
+ConcurrentDictionary_IndexIsNegative=The index argument is less than zero.
+ConcurrentDictionary_ConcurrencyLevelMustBePositive=The concurrencyLevel argument must be positive.
+ConcurrentDictionary_CapacityMustNotBeNegative=The capacity argument must be greater than or equal to zero.
+ConcurrentDictionary_ArrayNotLargeEnough=The index is equal to or greater than the length of the array, or the number of elements in the dictionary is greater than the available space from index to the end of the destination array.
+ConcurrentDictionary_ArrayIncorrectType=The array is multidimensional, or the type parameter for the set cannot be cast automatically to the type of the destination array.
+ConcurrentDictionary_KeyAlreadyExisted=The key already existed in the dictionary.
+ConcurrentDictionary_TypeOfKeyIncorrect=The key was of an incorrect type for this dictionary.
+ConcurrentDictionary_TypeOfValueIncorrect=The value was of an incorrect type for this dictionary.
+
+; Partitioner
+Partitioner_DynamicPartitionsNotSupported=Dynamic partitions are not supported by this partitioner.
+
+; OrderablePartitioner
+OrderablePartitioner_GetPartitions_WrongNumberOfPartitions=GetPartitions returned an incorrect number of partitions.
+
+; PartitionerStatic
+PartitionerStatic_CurrentCalledBeforeMoveNext=MoveNext must be called at least once before calling Current.
+PartitionerStatic_CanNotCallGetEnumeratorAfterSourceHasBeenDisposed=Can not call GetEnumerator on partitions after the source enumerable is disposed
+
+; CDSCollectionETWBCLProvider events
+event_ConcurrentStack_FastPushFailed=Push to ConcurrentStack spun {0} time(s).
+event_ConcurrentStack_FastPopFailed=Pop from ConcurrentStack spun {0} time(s).
+event_ConcurrentDictionary_AcquiringAllLocks=ConcurrentDictionary acquiring all locks on {0} bucket(s).
+event_ConcurrentBag_TryTakeSteals=ConcurrentBag stealing in TryTake.
+event_ConcurrentBag_TryPeekSteals=ConcurrentBag stealing in TryPeek.
+
+; CountdownEvent
+CountdownEvent_Decrement_BelowZero=Invalid attempt made to decrement the event's count below zero.
+CountdownEvent_Increment_AlreadyZero=The event is already signaled and cannot be incremented.
+CountdownEvent_Increment_AlreadyMax=The increment operation would cause the CurrentCount to overflow.
+
+; Parallel
+Parallel_Invoke_ActionNull=One of the actions was null.
+Parallel_ForEach_OrderedPartitionerKeysNotNormalized=This method requires the use of an OrderedPartitioner with the KeysNormalized property set to true.
+Parallel_ForEach_PartitionerNotDynamic=The Partitioner used here must support dynamic partitioning.
+Parallel_ForEach_PartitionerReturnedNull=The Partitioner used here returned a null partitioner source.
+Parallel_ForEach_NullEnumerator=The Partitioner source returned a null enumerator.
+
+; Semaphore
+Argument_SemaphoreInitialMaximum=The initial count for the semaphore must be greater than or equal to zero and less than the maximum count.
+
+; SemaphoreFullException
+Threading_SemaphoreFullException=Adding the specified count to the semaphore would cause it to exceed its maximum count.
+
+; Lazy
+Lazy_ctor_ValueSelectorNull=The valueSelector argument is null.
+Lazy_ctor_InfoNull=The info argument is null.
+Lazy_ctor_deserialization_ValueInvalid=The Value cannot be null.
+Lazy_ctor_ModeInvalid=The mode argument specifies an invalid value.
+Lazy_CreateValue_NoParameterlessCtorForT=The lazily-initialized type does not have a public, parameterless constructor.
+Lazy_StaticInit_InvalidOperation=ValueFactory returned null.
+Lazy_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance.
+Lazy_ToString_ValueNotCreated=Value is not created.
+
+
+;ThreadLocal
+ThreadLocal_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance.
+ThreadLocal_Disposed=The ThreadLocal object has been disposed.
+ThreadLocal_ValuesNotAvailable=The ThreadLocal object is not tracking values. To use the Values property, use a ThreadLocal constructor that accepts the trackAllValues parameter and set the parameter to true.
+
+; SemaphoreSlim
+SemaphoreSlim_ctor_InitialCountWrong=The initialCount argument must be non-negative and less than or equal to the maximumCount.
+SemaphoreSlim_ctor_MaxCountWrong=The maximumCount argument must be a positive number. If a maximum is not required, use the constructor without a maxCount parameter.
+SemaphoreSlim_Wait_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive.
+SemaphoreSlim_Release_CountWrong=The releaseCount argument must be greater than zero.
+SemaphoreSlim_Disposed=The semaphore has been disposed.
+
+; ManualResetEventSlim
+ManualResetEventSlim_ctor_SpinCountOutOfRange=The spinCount argument must be in the range 0 to {0}, inclusive.
+ManualResetEventSlim_ctor_TooManyWaiters=There are too many threads currently waiting on the event. A maximum of {0} waiting threads are supported.
+ManualResetEventSlim_Disposed=The event has been disposed.
+
+; SpinLock
+SpinLock_TryEnter_ArgumentOutOfRange=The timeout must be a value between -1 and Int32.MaxValue, inclusive.
+SpinLock_TryEnter_LockRecursionException=The calling thread already holds the lock.
+SpinLock_TryReliableEnter_ArgumentException=The tookLock argument must be set to false before calling this method.
+SpinLock_Exit_SynchronizationLockException=The calling thread does not hold the lock.
+SpinLock_IsHeldByCurrentThread=Thread tracking is disabled.
+
+; SpinWait
+SpinWait_SpinUntil_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive.
+SpinWait_SpinUntil_ArgumentNull=The condition argument is null.
+
+; CdsSyncEtwBCLProvider events
+event_SpinLock_FastPathFailed=SpinLock beginning to spin.
+event_SpinWait_NextSpinWillYield=Next spin will yield.
+event_Barrier_PhaseFinished=Barrier finishing phase {1}.
+
+#if PLATFORM_UNIX
+; Unix threading
+PlatformNotSupported_NamedSynchronizationPrimitives=The named version of this synchronization primitive is not supported on this platform.
+PlatformNotSupported_NamedSyncObjectWaitAnyWaitAll=Wait operations on multiple wait handles including a named synchronization primitive are not supported on this platform.
+#endif
+
+;
+; System.Threading.Tasks
+;
+
+; AsyncMethodBuilder
+AsyncMethodBuilder_InstanceNotInitialized=The builder was not properly initialized.
+
+; TaskAwaiter and YieldAwaitable
+AwaitableAwaiter_InstanceNotInitialized=The awaitable or awaiter was not properly initialized.
+TaskAwaiter_TaskNotCompleted=The awaited task has not yet completed.
+
+; Task<T>
+TaskT_SetException_HasAnInitializer=A task's Exception may only be set directly if the task was created without a function.
+TaskT_TransitionToFinal_AlreadyCompleted=An attempt was made to transition a task to a final state when it had already completed.
+TaskT_ctor_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating for a Task<TResult>.
+TaskT_DebuggerNoResult={Not yet computed}
+
+; Task
+Task_ctor_LRandSR=(Internal)An attempt was made to create a LongRunning SelfReplicating task.
+Task_ThrowIfDisposed=The task has been disposed.
+Task_Dispose_NotCompleted=A task may only be disposed if it is in a completion state (RanToCompletion, Faulted or Canceled).
+Task_Start_Promise=Start may not be called on a promise-style task.
+Task_Start_AlreadyStarted=Start may not be called on a task that was already started.
+Task_Start_TaskCompleted=Start may not be called on a task that has completed.
+Task_Start_ContinuationTask=Start may not be called on a continuation task.
+Task_RunSynchronously_AlreadyStarted=RunSynchronously may not be called on a task that was already started.
+Task_RunSynchronously_TaskCompleted=RunSynchronously may not be called on a task that has already completed.
+Task_RunSynchronously_Promise=RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
+Task_RunSynchronously_Continuation=RunSynchronously may not be called on a continuation task.
+Task_ContinueWith_NotOnAnything=The specified TaskContinuationOptions excluded all continuation kinds.
+Task_ContinueWith_ESandLR=The specified TaskContinuationOptions combined LongRunning and ExecuteSynchronously. Synchronous continuations should not be long running.
+Task_MultiTaskContinuation_NullTask=The tasks argument included a null value.
+Task_MultiTaskContinuation_FireOptions=It is invalid to exclude specific continuation kinds for continuations off of multiple tasks.
+Task_MultiTaskContinuation_EmptyTaskList=The tasks argument contains no tasks.
+Task_FromAsync_TaskManagerShutDown=FromAsync was called with a TaskManager that had already shut down.
+Task_FromAsync_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating in calls to FromAsync.
+Task_FromAsync_LongRunning=It is invalid to specify TaskCreationOptions.LongRunning in calls to FromAsync.
+Task_FromAsync_PreferFairness=It is invalid to specify TaskCreationOptions.PreferFairness in calls to FromAsync.
+Task_WaitMulti_NullTask=The tasks array included at least one null element.
+Task_Delay_InvalidMillisecondsDelay=The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer.
+Task_Delay_InvalidDelay=The value needs to translate in milliseconds to -1 (signifying an infinite timeout), 0 or a positive integer less than or equal to Int32.MaxValue.
+
+; TaskCanceledException
+TaskCanceledException_ctor_DefaultMessage=A task was canceled.
+
+;TaskCompletionSource<T>
+TaskCompletionSourceT_TrySetException_NullException=The exceptions collection included at least one null element.
+TaskCompletionSourceT_TrySetException_NoExceptions=The exceptions collection was empty.
+
+;TaskExceptionHolder
+TaskExceptionHolder_UnknownExceptionType=(Internal)Expected an Exception or an IEnumerable<Exception>
+TaskExceptionHolder_UnhandledException=A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
+
+; TaskScheduler
+TaskScheduler_ExecuteTask_TaskAlreadyExecuted=ExecuteTask may not be called for a task which was already executed.
+TaskScheduler_ExecuteTask_WrongTaskScheduler=ExecuteTask may not be called for a task which was previously queued to a different TaskScheduler.
+TaskScheduler_InconsistentStateAfterTryExecuteTaskInline=The TryExecuteTaskInline call to the underlying scheduler succeeded, but the task body was not invoked.
+TaskScheduler_FromCurrentSynchronizationContext_NoCurrent=The current SynchronizationContext may not be used as a TaskScheduler.
+
+; TaskSchedulerException
+TaskSchedulerException_ctor_DefaultMessage=An exception was thrown by a TaskScheduler.
+
+;
+; ParallelState ( used in Parallel.For(), Parallel.ForEach() )
+ParallelState_Break_InvalidOperationException_BreakAfterStop=Break was called after Stop was called.
+ParallelState_Stop_InvalidOperationException_StopAfterBreak=Stop was called after Break was called.
+ParallelState_NotSupportedException_UnsupportedMethod=This method is not supported.
+
+;
+; TPLETWProvider events
+event_ParallelLoopBegin=Beginning {3} loop {2} from Task {1}.
+event_ParallelLoopEnd=Ending loop {2} after {3} iterations.
+event_ParallelInvokeBegin=Beginning ParallelInvoke {2} from Task {1} for {4} actions.
+event_ParallelInvokeEnd=Ending ParallelInvoke {2}.
+event_ParallelFork=Task {1} entering fork/join {2}.
+event_ParallelJoin=Task {1} leaving fork/join {2}.
+event_TaskScheduled=Task {2} scheduled to TaskScheduler {0}.
+event_TaskStarted=Task {2} executing.
+event_TaskCompleted=Task {2} completed.
+event_TaskWaitBegin=Beginning wait ({3}) on Task {2}.
+event_TaskWaitEnd=Ending wait on Task {2}.
+
+
+;
+; Weak Reference Exception
+;
+WeakReference_NoLongerValid = The weak reference is no longer valid.
+
+
+;
+; Interop Exceptions
+;
+Interop.COM_TypeMismatch = Type mismatch between source and destination types.
+Interop_Marshal_Unmappable_Char = Cannot marshal: Encountered unmappable character.
+
+#if FEATURE_COMINTEROP_WINRT_DESKTOP_HOST
+WinRTHostDomainName = Windows Runtime Object Host Domain for '{0}'
+#endif
+
+;
+; Loader Exceptions
+;
+Loader_InvalidPath = Relative path must be a string that contains the substring, "..", or does not contain a root directory.
+Loader_Name = Name:
+Loader_NoContextPolicies = There are no context policies.
+Loader_ContextPolicies = Context Policies:
+
+;
+; AppDomain Exceptions
+AppDomain_RequireApplicationName = ApplicationName must be set before the DynamicBase can be set.
+AppDomain_AppBaseNotSet = The ApplicationBase must be set before retrieving this property.
+
+#if FEATURE_HOST_ASSEMBLY_RESOLVER
+AppDomain_BindingModelIsLocked = Binding model is already locked for the AppDomain and cannot be reset.
+Argument_CustomAssemblyLoadContextRequestedNameMismatch = Resolved assembly's simple name should be the same as of the requested assembly.
+#endif // FEATURE_HOST_ASSEMBLY_RESOLVER
+;
+; XMLSyntaxExceptions
+XMLSyntax_UnexpectedEndOfFile = Unexpected end of file.
+XMLSyntax_ExpectedCloseBracket = Expected > character.
+XMLSyntax_ExpectedSlashOrString = Expected / character or string.
+XMLSyntax_UnexpectedCloseBracket = Unexpected > character.
+XMLSyntax_SyntaxError = Invalid syntax on line {0}.
+XMLSyntax_SyntaxErrorEx = Invalid syntax on line {0} - '{1}'.
+XMLSyntax_InvalidSyntax = Invalid syntax.
+XML_Syntax_InvalidSyntaxInFile = Invalid XML in file '{0}' near element '{1}'.
+XMLSyntax_InvalidSyntaxSatAssemTag = Invalid XML in file "{0}" near element "{1}". The <satelliteassemblies> section only supports <assembly> tags.
+XMLSyntax_InvalidSyntaxSatAssemTagBadAttr = Invalid XML in file "{0}" near "{1}" and "{2}". In the <satelliteassemblies> section, the <assembly> tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name.
+XMLSyntax_InvalidSyntaxSatAssemTagNoAttr = Invalid XML in file "{0}". In the <satelliteassemblies> section, the <assembly> tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name.
+
+; CodeGroup
+#if FEATURE_CAS_POLICY
+NetCodeGroup_PermissionSet = Same site Web
+MergeLogic_Union = Union
+MergeLogic_FirstMatch = First Match
+FileCodeGroup_PermissionSet = Same directory FileIO - '{0}'
+#endif // FEATURE_CAS_POLICY
+
+; MembershipConditions
+StrongName_ToString = StrongName - {0}{1}{2}
+StrongName_Name = name = {0}
+StrongName_Version = version = {0}
+Site_ToString = Site
+Publisher_ToString = Publisher
+Hash_ToString = Hash - {0} = {1}
+ApplicationDirectory_ToString = ApplicationDirectory
+Zone_ToString = Zone - {0}
+All_ToString = All code
+Url_ToString = Url
+GAC_ToString = GAC
+#if FEATURE_CAS_POLICY
+Site_ToStringArg = Site - {0}
+Publisher_ToStringArg = Publisher - {0}
+Url_ToStringArg = Url - {0}
+#endif // FEATURE_CAS_POLICY
+
+
+; Interop non exception strings.
+TypeLibConverter_ImportedTypeLibProductName = Assembly imported from type library '{0}'.
+
+;
+; begin System.TimeZoneInfo ArgumentException's
+;
+Argument_AdjustmentRulesNoNulls = The AdjustmentRule array cannot contain null elements.
+Argument_AdjustmentRulesOutOfOrder = The elements of the AdjustmentRule array must be in chronological order and must not overlap.
+Argument_AdjustmentRulesAmbiguousOverlap = The elements of the AdjustmentRule array must not contain ambiguous time periods that extend beyond the DateStart or DateEnd properties of the element.
+Argument_AdjustmentRulesrDaylightSavingTimeOverlap = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap adjacent elements in such a way as to cause invalid or ambiguous time periods.
+Argument_AdjustmentRulesrDaylightSavingTimeOverlapNonRuleRange = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap the DateStart or DateEnd properties in such a way as to cause invalid or ambiguous time periods.
+Argument_AdjustmentRulesInvalidOverlap = The elements of the AdjustmentRule array must not contain invalid time periods that extend beyond the DateStart or DateEnd properties of the element.
+Argument_ConvertMismatch = The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local.
+Argument_DateTimeHasTimeOfDay = The supplied DateTime includes a TimeOfDay setting. This is not supported.
+Argument_DateTimeIsInvalid = The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid.
+Argument_DateTimeIsNotAmbiguous = The supplied DateTime is not in an ambiguous time range.
+Argument_DateTimeOffsetIsNotAmbiguous = The supplied DateTimeOffset is not in an ambiguous time range.
+Argument_DateTimeKindMustBeUnspecifiedOrUtc = The supplied DateTime must have the Kind property set to DateTimeKind.Unspecified or DateTimeKind.Utc.
+Argument_DateTimeHasTicks = The supplied DateTime must have the Year, Month, and Day properties set to 1. The time cannot be specified more precisely than whole milliseconds.
+Argument_InvalidId = The specified ID parameter '{0}' is not supported.
+Argument_InvalidSerializedString = The specified serialized string '{0}' is not supported.
+Argument_InvalidREG_TZI_FORMAT = The REG_TZI_FORMAT structure is corrupt.
+Argument_OutOfOrderDateTimes = The DateStart property must come before the DateEnd property.
+Argument_TimeSpanHasSeconds = The TimeSpan parameter cannot be specified more precisely than whole minutes.
+Argument_TimeZoneInfoBadTZif = The tzfile does not begin with the magic characters 'TZif'. Please verify that the file is not corrupt.
+Argument_TimeZoneInfoInvalidTZif = The TZif data structure is corrupt.
+Argument_TransitionTimesAreIdentical = The DaylightTransitionStart property must not equal the DaylightTransitionEnd property.
+;
+; begin System.TimeZoneInfo ArgumentOutOfRangeException's
+;
+ArgumentOutOfRange_DayParam = The Day parameter must be in the range 1 through 31.
+ArgumentOutOfRange_DayOfWeek = The DayOfWeek enumeration must be in the range 0 through 6.
+ArgumentOutOfRange_MonthParam = The Month parameter must be in the range 1 through 12.
+ArgumentOutOfRange_UtcOffset = The TimeSpan parameter must be within plus or minus 14.0 hours.
+ArgumentOutOfRange_UtcOffsetAndDaylightDelta = The sum of the BaseUtcOffset and DaylightDelta properties must within plus or minus 14.0 hours.
+ArgumentOutOfRange_Week = The Week parameter must be in the range 1 through 5.
+;
+; begin System.TimeZoneInfo InvalidTimeZoneException's
+;
+InvalidTimeZone_InvalidRegistryData = The time zone ID '{0}' was found on the local computer, but the registry information was corrupt.
+InvalidTimeZone_InvalidFileData = The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt.
+InvalidTimeZone_InvalidWin32APIData = The Local time zone was found on the local computer, but the data was corrupt.
+InvalidTimeZone_NoTTInfoStructures = There are no ttinfo structures in the tzfile. At least one ttinfo structure is required in order to construct a TimeZoneInfo object.
+InvalidTimeZone_UnparseablePosixMDateString = '{0}' is not a valid POSIX-TZ-environment-variable MDate rule. A valid rule has the format 'Mm.w.d'.
+InvalidTimeZone_JulianDayNotSupported = Julian dates in POSIX strings are unsupported.
+;
+; begin System.TimeZoneInfo SecurityException's
+;
+Security_CannotReadRegistryData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the registry information.
+Security_CannotReadFileData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the file.
+;
+; begin System.TimeZoneInfo SerializationException's
+;
+Serialization_CorruptField = The value of the field '{0}' is invalid. The serialized data is corrupt.
+Serialization_InvalidEscapeSequence = The serialized data contained an invalid escape sequence '\\{0}'.
+;
+; begin System.TimeZoneInfo TimeZoneNotFoundException's
+;
+TimeZoneNotFound_MissingData = The time zone ID '{0}' was not found on the local computer.
+;
+; end System.TimeZoneInfo
+;
+
+
+; Tuple
+ArgumentException_TupleIncorrectType=Argument must be of type {0}.
+ArgumentException_TupleNonIComparableElement=The tuple contains an element of type {0} which does not implement the IComparable interface.
+ArgumentException_TupleLastArgumentNotATuple=The last element of an eight element tuple must be a Tuple.
+ArgumentException_OtherNotArrayOfCorrectLength=Object is not a array with the same number of elements as the array to compare it to.
+
+; WinRT collection adapters
+Argument_IndexOutOfArrayBounds=The specified index is out of bounds of the specified array.
+Argument_InsufficientSpaceToCopyCollection=The specified space is not sufficient to copy the elements from this Collection.
+ArgumentOutOfRange_IndexLargerThanMaxValue=This collection cannot work with indices larger than Int32.MaxValue - 1 (0x7FFFFFFF - 1).
+ArgumentOutOfRange_IndexOutOfRange=The specified index is outside the current index range of this collection.
+InvalidOperation_CollectionBackingListTooLarge=The collection backing this List contains too many elements.
+InvalidOperation_CollectionBackingDictionaryTooLarge=The collection backing this Dictionary contains too many elements.
+InvalidOperation_CannotRemoveLastFromEmptyCollection=Cannot remove the last element from an empty collection.
+
+; Globalization resources
+;------------------
+
+#if !FEATURE_CORECLR
+Globalization.LegacyModifier = Legacy
+
+;
+;Total items: 809
+;
+Globalization.ci_ = Invariant Language (Invariant Country)
+Globalization.ci_aa = Afar
+Globalization.ci_aa-DJ = Afar (Djibouti)
+Globalization.ci_aa-ER = Afar (Eritrea)
+Globalization.ci_aa-ET = Afar (Ethiopia)
+Globalization.ci_af = Afrikaans
+Globalization.ci_af-NA = Afrikaans (Namibia)
+Globalization.ci_af-ZA = Afrikaans (South Africa)
+Globalization.ci_agq = Aghem
+Globalization.ci_agq-CM = Aghem (Cameroon)
+Globalization.ci_ak = Akan
+Globalization.ci_ak-GH = Akan (Ghana)
+Globalization.ci_am = Amharic
+Globalization.ci_am-ET = Amharic (Ethiopia)
+Globalization.ci_ar = Arabic
+Globalization.ci_ar-001 = Arabic (World)
+Globalization.ci_ar-AE = Arabic (U.A.E.)
+Globalization.ci_ar-BH = Arabic (Bahrain)
+Globalization.ci_ar-DJ = Arabic (Djibouti)
+Globalization.ci_ar-DZ = Arabic (Algeria)
+Globalization.ci_ar-EG = Arabic (Egypt)
+Globalization.ci_ar-ER = Arabic (Eritrea)
+Globalization.ci_ar-IL = Arabic (Israel)
+Globalization.ci_ar-IQ = Arabic (Iraq)
+Globalization.ci_ar-JO = Arabic (Jordan)
+Globalization.ci_ar-KM = Arabic (Comoros)
+Globalization.ci_ar-KW = Arabic (Kuwait)
+Globalization.ci_ar-LB = Arabic (Lebanon)
+Globalization.ci_ar-LY = Arabic (Libya)
+Globalization.ci_ar-MA = Arabic (Morocco)
+Globalization.ci_ar-MR = Arabic (Mauritania)
+Globalization.ci_ar-OM = Arabic (Oman)
+Globalization.ci_ar-PS = Arabic (Palestinian Authority)
+Globalization.ci_ar-QA = Arabic (Qatar)
+Globalization.ci_ar-SA = Arabic (Saudi Arabia)
+Globalization.ci_ar-SD = Arabic (Sudan)
+Globalization.ci_ar-SO = Arabic (Somalia)
+Globalization.ci_ar-SS = Arabic (South Sudan)
+Globalization.ci_ar-SY = Arabic (Syria)
+Globalization.ci_ar-TD = Arabic (Chad)
+Globalization.ci_ar-TN = Arabic (Tunisia)
+Globalization.ci_ar-YE = Arabic (Yemen)
+Globalization.ci_arn = Mapudungun
+Globalization.ci_arn-CL = Mapudungun (Chile)
+Globalization.ci_as = Assamese
+Globalization.ci_as-IN = Assamese (India)
+Globalization.ci_asa = Asu
+Globalization.ci_asa-TZ = Asu (Tanzania)
+Globalization.ci_ast = Asturian
+Globalization.ci_ast-ES = Asturian (Spain)
+Globalization.ci_az = Azerbaijani
+Globalization.ci_az-Cyrl = Azerbaijani (Cyrillic)
+Globalization.ci_az-Cyrl-AZ = Azerbaijani (Cyrillic, Azerbaijan)
+Globalization.ci_az-Latn = Azerbaijani (Latin)
+Globalization.ci_az-Latn-AZ = Azerbaijani (Latin, Azerbaijan)
+Globalization.ci_ba = Bashkir
+Globalization.ci_ba-RU = Bashkir (Russia)
+Globalization.ci_bas = Basaa
+Globalization.ci_bas-CM = Basaa (Cameroon)
+Globalization.ci_be = Belarusian
+Globalization.ci_be-BY = Belarusian (Belarus)
+Globalization.ci_bem = Bemba
+Globalization.ci_bem-ZM = Bemba (Zambia)
+Globalization.ci_bez = Bena
+Globalization.ci_bez-TZ = Bena (Tanzania)
+Globalization.ci_bg = Bulgarian
+Globalization.ci_bg-BG = Bulgarian (Bulgaria)
+Globalization.ci_bm = Bambara
+Globalization.ci_bm-Latn = Bambara (Latin)
+Globalization.ci_bm-Latn-ML = Bambara (Latin, Mali)
+Globalization.ci_bm-ML = Bamanankan (Latin, Mali)
+Globalization.ci_bn = Bangla
+Globalization.ci_bn-BD = Bangla (Bangladesh)
+Globalization.ci_bn-IN = Bangla (India)
+Globalization.ci_bo = Tibetan
+Globalization.ci_bo-CN = Tibetan (PRC)
+Globalization.ci_bo-IN = Tibetan (India)
+Globalization.ci_br = Breton
+Globalization.ci_br-FR = Breton (France)
+Globalization.ci_brx = Bodo
+Globalization.ci_brx-IN = Bodo (India)
+Globalization.ci_bs = Bosnian
+Globalization.ci_bs-Cyrl = Bosnian (Cyrillic)
+Globalization.ci_bs-Cyrl-BA = Bosnian (Cyrillic, Bosnia and Herzegovina)
+Globalization.ci_bs-Latn = Bosnian (Latin)
+Globalization.ci_bs-Latn-BA = Bosnian (Latin, Bosnia and Herzegovina)
+Globalization.ci_byn = Blin
+Globalization.ci_byn-ER = Blin (Eritrea)
+Globalization.ci_ca = Catalan
+Globalization.ci_ca-AD = Catalan (Andorra)
+Globalization.ci_ca-ES = Catalan (Catalan)
+Globalization.ci_ca-ES-valencia = Valencian (Spain)
+Globalization.ci_ca-FR = Catalan (France)
+Globalization.ci_ca-IT = Catalan (Italy)
+Globalization.ci_cgg = Chiga
+Globalization.ci_cgg-UG = Chiga (Uganda)
+Globalization.ci_chr = Cherokee
+Globalization.ci_chr-Cher = Cherokee (Cherokee)
+Globalization.ci_chr-Cher-US = Cherokee (Cherokee)
+Globalization.ci_co = Corsican
+Globalization.ci_co-FR = Corsican (France)
+Globalization.ci_cs = Czech
+Globalization.ci_cs-CZ = Czech (Czech Republic)
+Globalization.ci_cy = Welsh
+Globalization.ci_cy-GB = Welsh (United Kingdom)
+Globalization.ci_da = Danish
+Globalization.ci_da-DK = Danish (Denmark)
+Globalization.ci_da-GL = Danish (Greenland)
+Globalization.ci_dav = Taita
+Globalization.ci_dav-KE = Taita (Kenya)
+Globalization.ci_de = German
+Globalization.ci_de-AT = German (Austria)
+Globalization.ci_de-BE = German (Belgium)
+Globalization.ci_de-CH = German (Switzerland)
+Globalization.ci_de-DE = German (Germany)
+Globalization.ci_de-DE_phoneb = German (Germany)
+Globalization.ci_de-LI = German (Liechtenstein)
+Globalization.ci_de-LU = German (Luxembourg)
+Globalization.ci_dje = Zarma
+Globalization.ci_dje-NE = Zarma (Niger)
+Globalization.ci_dsb = Lower Sorbian
+Globalization.ci_dsb-DE = Lower Sorbian (Germany)
+Globalization.ci_dua = Duala
+Globalization.ci_dua-CM = Duala (Cameroon)
+Globalization.ci_dv = Divehi
+Globalization.ci_dv-MV = Divehi (Maldives)
+Globalization.ci_dyo = Jola-Fonyi
+Globalization.ci_dyo-SN = Jola-Fonyi (Senegal)
+Globalization.ci_dz = Dzongkha
+Globalization.ci_dz-BT = Dzongkha (Bhutan)
+Globalization.ci_ebu = Embu
+Globalization.ci_ebu-KE = Embu (Kenya)
+Globalization.ci_ee = Ewe
+Globalization.ci_ee-GH = Ewe (Ghana)
+Globalization.ci_ee-TG = Ewe (Togo)
+Globalization.ci_el = Greek
+Globalization.ci_el-CY = Greek (Cyprus)
+Globalization.ci_el-GR = Greek (Greece)
+Globalization.ci_en = English
+Globalization.ci_en-001 = English (World)
+Globalization.ci_en-029 = English (Caribbean)
+Globalization.ci_en-150 = English (Europe)
+Globalization.ci_en-AG = English (Antigua and Barbuda)
+Globalization.ci_en-AI = English (Anguilla)
+Globalization.ci_en-AS = English (American Samoa)
+Globalization.ci_en-AU = English (Australia)
+Globalization.ci_en-BB = English (Barbados)
+Globalization.ci_en-BE = English (Belgium)
+Globalization.ci_en-BM = English (Bermuda)
+Globalization.ci_en-BS = English (Bahamas)
+Globalization.ci_en-BW = English (Botswana)
+Globalization.ci_en-BZ = English (Belize)
+Globalization.ci_en-CA = English (Canada)
+Globalization.ci_en-CC = English (Cocos [Keeling] Islands)
+Globalization.ci_en-CK = English (Cook Islands)
+Globalization.ci_en-CM = English (Cameroon)
+Globalization.ci_en-CX = English (Christmas Island)
+Globalization.ci_en-DM = English (Dominica)
+Globalization.ci_en-ER = English (Eritrea)
+Globalization.ci_en-FJ = English (Fiji)
+Globalization.ci_en-FK = English (Falkland Islands)
+Globalization.ci_en-FM = English (Micronesia)
+Globalization.ci_en-GB = English (United Kingdom)
+Globalization.ci_en-GD = English (Grenada)
+Globalization.ci_en-GG = English (Guernsey)
+Globalization.ci_en-GH = English (Ghana)
+Globalization.ci_en-GI = English (Gibraltar)
+Globalization.ci_en-GM = English (Gambia)
+Globalization.ci_en-GU = English (Guam)
+Globalization.ci_en-GY = English (Guyana)
+Globalization.ci_en-HK = English (Hong Kong SAR)
+Globalization.ci_en-IE = English (Ireland)
+Globalization.ci_en-IM = English (Isle of Man)
+Globalization.ci_en-IN = English (India)
+Globalization.ci_en-IO = English (British Indian Ocean Territory)
+Globalization.ci_en-JE = English (Jersey)
+Globalization.ci_en-JM = English (Jamaica)
+Globalization.ci_en-KE = English (Kenya)
+Globalization.ci_en-KI = English (Kiribati)
+Globalization.ci_en-KN = English (Saint Kitts and Nevis)
+Globalization.ci_en-KY = English (Cayman Islands)
+Globalization.ci_en-LC = English (Saint Lucia)
+Globalization.ci_en-LR = English (Liberia)
+Globalization.ci_en-LS = English (Lesotho)
+Globalization.ci_en-MG = English (Madagascar)
+Globalization.ci_en-MH = English (Marshall Islands)
+Globalization.ci_en-MO = English (Macao SAR)
+Globalization.ci_en-MP = English (Northern Mariana Islands)
+Globalization.ci_en-MS = English (Montserrat)
+Globalization.ci_en-MT = English (Malta)
+Globalization.ci_en-MU = English (Mauritius)
+Globalization.ci_en-MW = English (Malawi)
+Globalization.ci_en-MY = English (Malaysia)
+Globalization.ci_en-NA = English (Namibia)
+Globalization.ci_en-NF = English (Norfolk Island)
+Globalization.ci_en-NG = English (Nigeria)
+Globalization.ci_en-NR = English (Nauru)
+Globalization.ci_en-NU = English (Niue)
+Globalization.ci_en-NZ = English (New Zealand)
+Globalization.ci_en-PG = English (Papua New Guinea)
+Globalization.ci_en-PH = English (Republic of the Philippines)
+Globalization.ci_en-PK = English (Pakistan)
+Globalization.ci_en-PN = English (Pitcairn Islands)
+Globalization.ci_en-PR = English (Puerto Rico)
+Globalization.ci_en-PW = English (Palau)
+Globalization.ci_en-RW = English (Rwanda)
+Globalization.ci_en-SB = English (Solomon Islands)
+Globalization.ci_en-SC = English (Seychelles)
+Globalization.ci_en-SD = English (Sudan)
+Globalization.ci_en-SG = English (Singapore)
+Globalization.ci_en-SH = English (St Helena, Ascension, Tristan da Cunha)
+Globalization.ci_en-SL = English (Sierra Leone)
+Globalization.ci_en-SS = English (South Sudan)
+Globalization.ci_en-SX = English (Sint Maarten)
+Globalization.ci_en-SZ = English (Swaziland)
+Globalization.ci_en-TC = English (Turks and Caicos Islands)
+Globalization.ci_en-TK = English (Tokelau)
+Globalization.ci_en-TO = English (Tonga)
+Globalization.ci_en-TT = English (Trinidad and Tobago)
+Globalization.ci_en-TV = English (Tuvalu)
+Globalization.ci_en-TZ = English (Tanzania)
+Globalization.ci_en-UG = English (Uganda)
+Globalization.ci_en-UM = English (US Minor Outlying Islands)
+Globalization.ci_en-US = English (United States)
+Globalization.ci_en-VC = English (Saint Vincent and the Grenadines)
+Globalization.ci_en-VG = English (British Virgin Islands)
+Globalization.ci_en-VI = English (US Virgin Islands)
+Globalization.ci_en-VU = English (Vanuatu)
+Globalization.ci_en-WS = English (Samoa)
+Globalization.ci_en-ZA = English (South Africa)
+Globalization.ci_en-ZM = English (Zambia)
+Globalization.ci_en-ZW = English (Zimbabwe)
+Globalization.ci_eo = Esperanto
+Globalization.ci_eo-001 = Esperanto (World)
+Globalization.ci_es = Spanish
+Globalization.ci_es-419 = Spanish (Latin America)
+Globalization.ci_es-AR = Spanish (Argentina)
+Globalization.ci_es-BO = Spanish (Bolivia)
+Globalization.ci_es-CL = Spanish (Chile)
+Globalization.ci_es-CO = Spanish (Colombia)
+Globalization.ci_es-CR = Spanish (Costa Rica)
+Globalization.ci_es-CU = Spanish (Cuba)
+Globalization.ci_es-DO = Spanish (Dominican Republic)
+Globalization.ci_es-EC = Spanish (Ecuador)
+Globalization.ci_es-ES = Spanish (Spain)
+Globalization.ci_es-ES_tradnl = Spanish (Spain)
+Globalization.ci_es-GQ = Spanish (Equatorial Guinea)
+Globalization.ci_es-GT = Spanish (Guatemala)
+Globalization.ci_es-HN = Spanish (Honduras)
+Globalization.ci_es-MX = Spanish (Mexico)
+Globalization.ci_es-NI = Spanish (Nicaragua)
+Globalization.ci_es-PA = Spanish (Panama)
+Globalization.ci_es-PE = Spanish (Peru)
+Globalization.ci_es-PH = Spanish (Philippines)
+Globalization.ci_es-PR = Spanish (Puerto Rico)
+Globalization.ci_es-PY = Spanish (Paraguay)
+Globalization.ci_es-SV = Spanish (El Salvador)
+Globalization.ci_es-US = Spanish (United States)
+Globalization.ci_es-UY = Spanish (Uruguay)
+Globalization.ci_es-VE = Spanish (Bolivarian Republic of Venezuela)
+Globalization.ci_et = Estonian
+Globalization.ci_et-EE = Estonian (Estonia)
+Globalization.ci_eu = Basque
+Globalization.ci_eu-ES = Basque (Basque)
+Globalization.ci_ewo = Ewondo
+Globalization.ci_ewo-CM = Ewondo (Cameroon)
+Globalization.ci_fa = Persian
+Globalization.ci_fa-AF = Persian (Afghanistan)
+Globalization.ci_fa-IR = Persian (Iran)
+Globalization.ci_ff = Fulah
+Globalization.ci_ff-CM = Fulah (Cameroon)
+Globalization.ci_ff-GN = Fulah (Guinea)
+Globalization.ci_ff-Latn = Fulah (Latin)
+Globalization.ci_ff-Latn-SN = Fulah (Latin, Senegal)
+Globalization.ci_ff-MR = Fulah (Mauritania)
+Globalization.ci_fi = Finnish
+Globalization.ci_fi-FI = Finnish (Finland)
+Globalization.ci_fil = Filipino
+Globalization.ci_fil-PH = Filipino (Philippines)
+Globalization.ci_fo = Faroese
+Globalization.ci_fo-FO = Faroese (Faroe Islands)
+Globalization.ci_fr = French
+Globalization.ci_fr-BE = French (Belgium)
+Globalization.ci_fr-BF = French (Burkina Faso)
+Globalization.ci_fr-BI = French (Burundi)
+Globalization.ci_fr-BJ = French (Benin)
+Globalization.ci_fr-BL = French (Saint Barthélemy)
+Globalization.ci_fr-CA = French (Canada)
+Globalization.ci_fr-CD = French (Congo DRC)
+Globalization.ci_fr-CF = French (Central African Republic)
+Globalization.ci_fr-CG = French (Congo)
+Globalization.ci_fr-CH = French (Switzerland)
+Globalization.ci_fr-CI = French (Côte d’Ivoire)
+Globalization.ci_fr-CM = French (Cameroon)
+Globalization.ci_fr-DJ = French (Djibouti)
+Globalization.ci_fr-DZ = French (Algeria)
+Globalization.ci_fr-FR = French (France)
+Globalization.ci_fr-GA = French (Gabon)
+Globalization.ci_fr-GF = French (French Guiana)
+Globalization.ci_fr-GN = French (Guinea)
+Globalization.ci_fr-GP = French (Guadeloupe)
+Globalization.ci_fr-GQ = French (Equatorial Guinea)
+Globalization.ci_fr-HT = French (Haiti)
+Globalization.ci_fr-KM = French (Comoros)
+Globalization.ci_fr-LU = French (Luxembourg)
+Globalization.ci_fr-MA = French (Morocco)
+Globalization.ci_fr-MC = French (Monaco)
+Globalization.ci_fr-MF = French (Saint Martin)
+Globalization.ci_fr-MG = French (Madagascar)
+Globalization.ci_fr-ML = French (Mali)
+Globalization.ci_fr-MQ = French (Martinique)
+Globalization.ci_fr-MR = French (Mauritania)
+Globalization.ci_fr-MU = French (Mauritius)
+Globalization.ci_fr-NC = French (New Caledonia)
+Globalization.ci_fr-NE = French (Niger)
+Globalization.ci_fr-PF = French (French Polynesia)
+Globalization.ci_fr-PM = French (Saint Pierre and Miquelon)
+Globalization.ci_fr-RE = French (Reunion)
+Globalization.ci_fr-RW = French (Rwanda)
+Globalization.ci_fr-SC = French (Seychelles)
+Globalization.ci_fr-SN = French (Senegal)
+Globalization.ci_fr-SY = French (Syria)
+Globalization.ci_fr-TD = French (Chad)
+Globalization.ci_fr-TG = French (Togo)
+Globalization.ci_fr-TN = French (Tunisia)
+Globalization.ci_fr-VU = French (Vanuatu)
+Globalization.ci_fr-WF = French (Wallis and Futuna)
+Globalization.ci_fr-YT = French (Mayotte)
+Globalization.ci_fur = Friulian
+Globalization.ci_fur-IT = Friulian (Italy)
+Globalization.ci_fy = Frisian
+Globalization.ci_fy-NL = Frisian (Netherlands)
+Globalization.ci_ga = Irish
+Globalization.ci_ga-IE = Irish (Ireland)
+Globalization.ci_gd = Scottish Gaelic
+Globalization.ci_gd-GB = Scottish Gaelic (United Kingdom)
+Globalization.ci_gl = Galician
+Globalization.ci_gl-ES = Galician (Galician)
+Globalization.ci_gn = Guarani
+Globalization.ci_gn-PY = Guarani (Paraguay)
+Globalization.ci_gsw = Alsatian
+Globalization.ci_gsw-CH = Alsatian (Switzerland)
+Globalization.ci_gsw-FR = Alsatian (France)
+Globalization.ci_gsw-LI = Alsatian (Liechtenstein)
+Globalization.ci_gu = Gujarati
+Globalization.ci_gu-IN = Gujarati (India)
+Globalization.ci_guz = Gusii
+Globalization.ci_guz-KE = Gusii (Kenya)
+Globalization.ci_gv = Manx
+Globalization.ci_gv-IM = Manx (Isle of Man)
+Globalization.ci_ha = Hausa
+Globalization.ci_ha-Latn = Hausa (Latin)
+Globalization.ci_ha-Latn-GH = Hausa (Latin, Ghana)
+Globalization.ci_ha-Latn-NE = Hausa (Latin, Niger)
+Globalization.ci_ha-Latn-NG = Hausa (Latin, Nigeria)
+Globalization.ci_haw = Hawaiian
+Globalization.ci_haw-US = Hawaiian (United States)
+Globalization.ci_he = Hebrew
+Globalization.ci_he-IL = Hebrew (Israel)
+Globalization.ci_hi = Hindi
+Globalization.ci_hi-IN = Hindi (India)
+Globalization.ci_hr = Croatian
+Globalization.ci_hr-BA = Croatian (Latin, Bosnia and Herzegovina)
+Globalization.ci_hr-HR = Croatian (Croatia)
+Globalization.ci_hsb = Upper Sorbian
+Globalization.ci_hsb-DE = Upper Sorbian (Germany)
+Globalization.ci_hu = Hungarian
+Globalization.ci_hu-HU = Hungarian (Hungary)
+Globalization.ci_hu-HU_technl = Hungarian (Hungary)
+Globalization.ci_hy = Armenian
+Globalization.ci_hy-AM = Armenian (Armenia)
+Globalization.ci_ia = Interlingua
+Globalization.ci_ia-001 = Interlingua (World)
+Globalization.ci_ia-FR = Interlingua (France)
+Globalization.ci_id = Indonesian
+Globalization.ci_id-ID = Indonesian (Indonesia)
+Globalization.ci_ig = Igbo
+Globalization.ci_ig-NG = Igbo (Nigeria)
+Globalization.ci_ii = Yi
+Globalization.ci_ii-CN = Yi (PRC)
+Globalization.ci_is = Icelandic
+Globalization.ci_is-IS = Icelandic (Iceland)
+Globalization.ci_it = Italian
+Globalization.ci_it-CH = Italian (Switzerland)
+Globalization.ci_it-IT = Italian (Italy)
+Globalization.ci_it-SM = Italian (San Marino)
+Globalization.ci_iu = Inuktitut
+Globalization.ci_iu-Cans = Inuktitut (Syllabics)
+Globalization.ci_iu-Cans-CA = Inuktitut (Syllabics, Canada)
+Globalization.ci_iu-Latn = Inuktitut (Latin)
+Globalization.ci_iu-Latn-CA = Inuktitut (Latin, Canada)
+Globalization.ci_ja = Japanese
+Globalization.ci_ja-JP = Japanese (Japan)
+Globalization.ci_ja-JP_radstr = Japanese (Japan)
+Globalization.ci_jgo = Ngomba
+Globalization.ci_jgo-CM = Ngomba (Cameroon)
+Globalization.ci_jmc = Machame
+Globalization.ci_jmc-TZ = Machame (Tanzania)
+Globalization.ci_jv = Javanese
+Globalization.ci_jv-Latn = Javanese
+Globalization.ci_jv-Latn-ID = Javanese (Indonesia)
+Globalization.ci_ka = Georgian
+Globalization.ci_ka-GE = Georgian (Georgia)
+Globalization.ci_ka-GE_modern = Georgian (Georgia)
+Globalization.ci_kab = Kabyle
+Globalization.ci_kab-DZ = Kabyle (Algeria)
+Globalization.ci_kam = Kamba
+Globalization.ci_kam-KE = Kamba (Kenya)
+Globalization.ci_kde = Makonde
+Globalization.ci_kde-TZ = Makonde (Tanzania)
+Globalization.ci_kea = Kabuverdianu
+Globalization.ci_kea-CV = Kabuverdianu (Cabo Verde)
+Globalization.ci_khq = Koyra Chiini
+Globalization.ci_khq-ML = Koyra Chiini (Mali)
+Globalization.ci_ki = Kikuyu
+Globalization.ci_ki-KE = Kikuyu (Kenya)
+Globalization.ci_kk = Kazakh
+Globalization.ci_kk-KZ = Kazakh (Kazakhstan)
+Globalization.ci_kkj = Kako
+Globalization.ci_kkj-CM = Kako (Cameroon)
+Globalization.ci_kl = Greenlandic
+Globalization.ci_kl-GL = Greenlandic (Greenland)
+Globalization.ci_kln = Kalenjin
+Globalization.ci_kln-KE = Kalenjin (Kenya)
+Globalization.ci_km = Khmer
+Globalization.ci_km-KH = Khmer (Cambodia)
+Globalization.ci_kn = Kannada
+Globalization.ci_kn-IN = Kannada (India)
+Globalization.ci_ko = Korean
+Globalization.ci_ko-KR = Korean (Korea)
+Globalization.ci_kok = Konkani
+Globalization.ci_kok-IN = Konkani (India)
+Globalization.ci_ks = Kashmiri
+Globalization.ci_ks-Arab = Kashmiri (Perso-Arabic)
+Globalization.ci_ks-Arab-IN = Kashmiri (Perso-Arabic)
+Globalization.ci_ksb = Shambala
+Globalization.ci_ksb-TZ = Shambala (Tanzania)
+Globalization.ci_ksf = Bafia
+Globalization.ci_ksf-CM = Bafia (Cameroon)
+Globalization.ci_ksh = Colognian
+Globalization.ci_ksh-DE = Ripuarian (Germany)
+Globalization.ci_ku = Central Kurdish
+Globalization.ci_ku-Arab = Central Kurdish (Arabic)
+Globalization.ci_ku-Arab-IQ = Central Kurdish (Iraq)
+Globalization.ci_kw = Cornish
+Globalization.ci_kw-GB = Cornish (United Kingdom)
+Globalization.ci_ky = Kyrgyz
+Globalization.ci_ky-KG = Kyrgyz (Kyrgyzstan)
+Globalization.ci_lag = Langi
+Globalization.ci_lag-TZ = Langi (Tanzania)
+Globalization.ci_lb = Luxembourgish
+Globalization.ci_lb-LU = Luxembourgish (Luxembourg)
+Globalization.ci_lg = Ganda
+Globalization.ci_lg-UG = Ganda (Uganda)
+Globalization.ci_lkt = Lakota
+Globalization.ci_lkt-US = Lakota (United States)
+Globalization.ci_ln = Lingala
+Globalization.ci_ln-AO = Lingala (Angola)
+Globalization.ci_ln-CD = Lingala (Congo DRC)
+Globalization.ci_ln-CF = Lingala (Central African Republic)
+Globalization.ci_ln-CG = Lingala (Congo)
+Globalization.ci_lo = Lao
+Globalization.ci_lo-LA = Lao (Lao P.D.R.)
+Globalization.ci_lt = Lithuanian
+Globalization.ci_lt-LT = Lithuanian (Lithuania)
+Globalization.ci_lu = Luba-Katanga
+Globalization.ci_lu-CD = Luba-Katanga (Congo DRC)
+Globalization.ci_luo = Luo
+Globalization.ci_luo-KE = Luo (Kenya)
+Globalization.ci_luy = Luyia
+Globalization.ci_luy-KE = Luyia (Kenya)
+Globalization.ci_lv = Latvian
+Globalization.ci_lv-LV = Latvian (Latvia)
+Globalization.ci_mas = Masai
+Globalization.ci_mas-KE = Masai (Kenya)
+Globalization.ci_mas-TZ = Masai (Tanzania)
+Globalization.ci_mer = Meru
+Globalization.ci_mer-KE = Meru (Kenya)
+Globalization.ci_mfe = Morisyen
+Globalization.ci_mfe-MU = Morisyen (Mauritius)
+Globalization.ci_mg = Malagasy
+Globalization.ci_mg-MG = Malagasy (Madagascar)
+Globalization.ci_mgh = Makhuwa-Meetto
+Globalization.ci_mgh-MZ = Makhuwa-Meetto (Mozambique)
+Globalization.ci_mgo = Meta'
+Globalization.ci_mgo-CM = Meta' (Cameroon)
+Globalization.ci_mi = Maori
+Globalization.ci_mi-NZ = Maori (New Zealand)
+Globalization.ci_mk = Macedonian (FYROM)
+Globalization.ci_mk-MK = Macedonian (Former Yugoslav Republic of Macedonia)
+Globalization.ci_ml = Malayalam
+Globalization.ci_ml-IN = Malayalam (India)
+Globalization.ci_mn = Mongolian
+Globalization.ci_mn-Cyrl = Mongolian (Cyrillic)
+Globalization.ci_mn-MN = Mongolian (Cyrillic, Mongolia)
+Globalization.ci_mn-Mong = Mongolian (Traditional Mongolian)
+Globalization.ci_mn-Mong-CN = Mongolian (Traditional Mongolian, PRC)
+Globalization.ci_mn-Mong-MN = Mongolian (Traditional Mongolian, Mongolia)
+Globalization.ci_moh = Mohawk
+Globalization.ci_moh-CA = Mohawk (Mohawk)
+Globalization.ci_mr = Marathi
+Globalization.ci_mr-IN = Marathi (India)
+Globalization.ci_ms = Malay
+Globalization.ci_ms-BN = Malay (Brunei Darussalam)
+Globalization.ci_ms-MY = Malay (Malaysia)
+Globalization.ci_ms-SG = Malay (Latin, Singapore)
+Globalization.ci_mt = Maltese
+Globalization.ci_mt-MT = Maltese (Malta)
+Globalization.ci_mua = Mundang
+Globalization.ci_mua-CM = Mundang (Cameroon)
+Globalization.ci_my = Burmese
+Globalization.ci_my-MM = Burmese (Myanmar)
+Globalization.ci_naq = Nama
+Globalization.ci_naq-NA = Nama (Namibia)
+Globalization.ci_nb = Norwegian (Bokmål)
+Globalization.ci_nb-NO = Norwegian, Bokmål (Norway)
+Globalization.ci_nb-SJ = Norwegian, Bokmål (Svalbard and Jan Mayen)
+Globalization.ci_nd = North Ndebele
+Globalization.ci_nd-ZW = North Ndebele (Zimbabwe)
+Globalization.ci_ne = Nepali
+Globalization.ci_ne-IN = Nepali (India)
+Globalization.ci_ne-NP = Nepali (Nepal)
+Globalization.ci_nl = Dutch
+Globalization.ci_nl-AW = Dutch (Aruba)
+Globalization.ci_nl-BE = Dutch (Belgium)
+Globalization.ci_nl-BQ = Dutch (Bonaire, Sint Eustatius and Saba)
+Globalization.ci_nl-CW = Dutch (Curaçao)
+Globalization.ci_nl-NL = Dutch (Netherlands)
+Globalization.ci_nl-SR = Dutch (Suriname)
+Globalization.ci_nl-SX = Dutch (Sint Maarten)
+Globalization.ci_nmg = Kwasio
+Globalization.ci_nmg-CM = Kwasio (Cameroon)
+Globalization.ci_nn = Norwegian (Nynorsk)
+Globalization.ci_nn-NO = Norwegian, Nynorsk (Norway)
+Globalization.ci_nnh = Ngiemboon
+Globalization.ci_nnh-CM = Ngiemboon (Cameroon)
+Globalization.ci_no = Norwegian
+Globalization.ci_nqo = N'ko
+Globalization.ci_nqo-GN = N'ko (Guinea)
+Globalization.ci_nr = South Ndebele
+Globalization.ci_nr-ZA = South Ndebele (South Africa)
+Globalization.ci_nso = Sesotho sa Leboa
+Globalization.ci_nso-ZA = Sesotho sa Leboa (South Africa)
+Globalization.ci_nus = Nuer
+Globalization.ci_nus-SD = Nuer (Sudan)
+Globalization.ci_nyn = Nyankole
+Globalization.ci_nyn-UG = Nyankole (Uganda)
+Globalization.ci_oc = Occitan
+Globalization.ci_oc-FR = Occitan (France)
+Globalization.ci_om = Oromo
+Globalization.ci_om-ET = Oromo (Ethiopia)
+Globalization.ci_om-KE = Oromo (Kenya)
+Globalization.ci_or = Odia
+Globalization.ci_or-IN = Odia (India)
+Globalization.ci_os = Ossetic
+Globalization.ci_os-GE = Ossetian (Cyrillic, Georgia)
+Globalization.ci_os-RU = Ossetian (Cyrillic, Russia)
+Globalization.ci_pa = Punjabi
+Globalization.ci_pa-Arab = Punjabi (Arabic)
+Globalization.ci_pa-Arab-PK = Punjabi (Islamic Republic of Pakistan)
+Globalization.ci_pa-IN = Punjabi (India)
+Globalization.ci_pl = Polish
+Globalization.ci_pl-PL = Polish (Poland)
+Globalization.ci_prs = Dari
+Globalization.ci_prs-AF = Dari (Afghanistan)
+Globalization.ci_ps = Pashto
+Globalization.ci_ps-AF = Pashto (Afghanistan)
+Globalization.ci_pt = Portuguese
+Globalization.ci_pt-AO = Portuguese (Angola)
+Globalization.ci_pt-BR = Portuguese (Brazil)
+Globalization.ci_pt-CV = Portuguese (Cabo Verde)
+Globalization.ci_pt-GW = Portuguese (Guinea-Bissau)
+Globalization.ci_pt-MO = Portuguese (Macao SAR)
+Globalization.ci_pt-MZ = Portuguese (Mozambique)
+Globalization.ci_pt-PT = Portuguese (Portugal)
+Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe)
+Globalization.ci_pt-TL = Portuguese (Timor-Leste)
+Globalization.ci_qps-ploc = Pseudo Language (Pseudo)
+Globalization.ci_qps-ploca = Pseudo Language (Pseudo Asia)
+Globalization.ci_qps-plocm = Pseudo Language (Pseudo Mirrored)
+Globalization.ci_qu = Quechua
+Globalization.ci_qu-BO = Quechua (Bolivia)
+Globalization.ci_qu-EC = Quechua (Ecuador)
+Globalization.ci_qu-PE = Quechua (Peru)
+Globalization.ci_quc = K'iche'
+Globalization.ci_quc-Latn = K'iche'
+Globalization.ci_quc-Latn-GT = K'iche' (Guatemala)
+Globalization.ci_qut = K'iche
+Globalization.ci_qut-GT = K'iche (Guatemala)
+Globalization.ci_quz = Quechua
+Globalization.ci_quz-BO = Quechua (Bolivia)
+Globalization.ci_quz-EC = Quechua (Ecuador)
+Globalization.ci_quz-PE = Quechua (Peru)
+Globalization.ci_rm = Romansh
+Globalization.ci_rm-CH = Romansh (Switzerland)
+Globalization.ci_rn = Rundi
+Globalization.ci_rn-BI = Rundi (Burundi)
+Globalization.ci_ro = Romanian
+Globalization.ci_ro-MD = Romanian (Moldova)
+Globalization.ci_ro-RO = Romanian (Romania)
+Globalization.ci_rof = Rombo
+Globalization.ci_rof-TZ = Rombo (Tanzania)
+Globalization.ci_ru = Russian
+Globalization.ci_ru-BY = Russian (Belarus)
+Globalization.ci_ru-KG = Russian (Kyrgyzstan)
+Globalization.ci_ru-KZ = Russian (Kazakhstan)
+Globalization.ci_ru-MD = Russian (Moldova)
+Globalization.ci_ru-RU = Russian (Russia)
+Globalization.ci_ru-UA = Russian (Ukraine)
+Globalization.ci_rw = Kinyarwanda
+Globalization.ci_rw-RW = Kinyarwanda (Rwanda)
+Globalization.ci_rwk = Rwa
+Globalization.ci_rwk-TZ = Rwa (Tanzania)
+Globalization.ci_sa = Sanskrit
+Globalization.ci_sa-IN = Sanskrit (India)
+Globalization.ci_sah = Sakha
+Globalization.ci_sah-RU = Sakha (Russia)
+Globalization.ci_saq = Samburu
+Globalization.ci_saq-KE = Samburu (Kenya)
+Globalization.ci_sbp = Sangu
+Globalization.ci_sbp-TZ = Sangu (Tanzania)
+Globalization.ci_sd = Sindhi
+Globalization.ci_sd-Arab = Sindhi (Arabic)
+Globalization.ci_sd-Arab-PK = Sindhi (Islamic Republic of Pakistan)
+Globalization.ci_se = Sami (Northern)
+Globalization.ci_se-FI = Sami, Northern (Finland)
+Globalization.ci_se-NO = Sami, Northern (Norway)
+Globalization.ci_se-SE = Sami, Northern (Sweden)
+Globalization.ci_seh = Sena
+Globalization.ci_seh-MZ = Sena (Mozambique)
+Globalization.ci_ses = Koyraboro Senni
+Globalization.ci_ses-ML = Koyraboro Senni (Mali)
+Globalization.ci_sg = Sango
+Globalization.ci_sg-CF = Sango (Central African Republic)
+Globalization.ci_shi = Tachelhit
+Globalization.ci_shi-Latn = Tachelhit (Latin)
+Globalization.ci_shi-Latn-MA = Tachelhit (Latin, Morocco)
+Globalization.ci_shi-Tfng = Tachelhit (Tifinagh)
+Globalization.ci_shi-Tfng-MA = Tachelhit (Tifinagh, Morocco)
+Globalization.ci_si = Sinhala
+Globalization.ci_si-LK = Sinhala (Sri Lanka)
+Globalization.ci_sk = Slovak
+Globalization.ci_sk-SK = Slovak (Slovakia)
+Globalization.ci_sl = Slovenian
+Globalization.ci_sl-SI = Slovenian (Slovenia)
+Globalization.ci_sma = Sami (Southern)
+Globalization.ci_sma-NO = Sami, Southern (Norway)
+Globalization.ci_sma-SE = Sami, Southern (Sweden)
+Globalization.ci_smj = Sami (Lule)
+Globalization.ci_smj-NO = Sami, Lule (Norway)
+Globalization.ci_smj-SE = Sami, Lule (Sweden)
+Globalization.ci_smn = Sami (Inari)
+Globalization.ci_smn-FI = Sami, Inari (Finland)
+Globalization.ci_sms = Sami (Skolt)
+Globalization.ci_sms-FI = Sami, Skolt (Finland)
+Globalization.ci_sn = Shona
+Globalization.ci_sn-Latn = Shona (Latin)
+Globalization.ci_sn-Latn-ZW = Shona (Latin, Zimbabwe)
+Globalization.ci_so = Somali
+Globalization.ci_so-DJ = Somali (Djibouti)
+Globalization.ci_so-ET = Somali (Ethiopia)
+Globalization.ci_so-KE = Somali (Kenya)
+Globalization.ci_so-SO = Somali (Somalia)
+Globalization.ci_sq = Albanian
+Globalization.ci_sq-AL = Albanian (Albania)
+Globalization.ci_sq-MK = Albanian (Macedonia, FYRO)
+Globalization.ci_sr = Serbian
+Globalization.ci_sr-Cyrl = Serbian (Cyrillic)
+Globalization.ci_sr-Cyrl-BA = Serbian (Cyrillic, Bosnia and Herzegovina)
+Globalization.ci_sr-Cyrl-CS = Serbian (Cyrillic, Serbia and Montenegro (Former))
+Globalization.ci_sr-Cyrl-ME = Serbian (Cyrillic, Montenegro)
+Globalization.ci_sr-Cyrl-RS = Serbian (Cyrillic, Serbia)
+Globalization.ci_sr-Latn = Serbian (Latin)
+Globalization.ci_sr-Latn-BA = Serbian (Latin, Bosnia and Herzegovina)
+Globalization.ci_sr-Latn-CS = Serbian (Latin, Serbia and Montenegro (Former))
+Globalization.ci_sr-Latn-ME = Serbian (Latin, Montenegro)
+Globalization.ci_sr-Latn-RS = Serbian (Latin, Serbia)
+Globalization.ci_ss = Swati
+Globalization.ci_ss-SZ = Swati (Swaziland)
+Globalization.ci_ss-ZA = Swati (South Africa)
+Globalization.ci_ssy = Saho
+Globalization.ci_ssy-ER = Saho (Eritrea)
+Globalization.ci_st = Southern Sotho
+Globalization.ci_st-LS = Sesotho (Lesotho)
+Globalization.ci_st-ZA = Southern Sotho (South Africa)
+Globalization.ci_sv = Swedish
+Globalization.ci_sv-AX = Swedish (Ã…land Islands)
+Globalization.ci_sv-FI = Swedish (Finland)
+Globalization.ci_sv-SE = Swedish (Sweden)
+Globalization.ci_sw = Kiswahili
+Globalization.ci_sw-KE = Kiswahili (Kenya)
+Globalization.ci_sw-TZ = Kiswahili (Tanzania)
+Globalization.ci_sw-UG = Kiswahili (Uganda)
+Globalization.ci_swc = Congo Swahili
+Globalization.ci_swc-CD = Congo Swahili (Congo DRC)
+Globalization.ci_syr = Syriac
+Globalization.ci_syr-SY = Syriac (Syria)
+Globalization.ci_ta = Tamil
+Globalization.ci_ta-IN = Tamil (India)
+Globalization.ci_ta-LK = Tamil (Sri Lanka)
+Globalization.ci_ta-MY = Tamil (Malaysia)
+Globalization.ci_ta-SG = Tamil (Singapore)
+Globalization.ci_te = Telugu
+Globalization.ci_te-IN = Telugu (India)
+Globalization.ci_teo = Teso
+Globalization.ci_teo-KE = Teso (Kenya)
+Globalization.ci_teo-UG = Teso (Uganda)
+Globalization.ci_tg = Tajik
+Globalization.ci_tg-Cyrl = Tajik (Cyrillic)
+Globalization.ci_tg-Cyrl-TJ = Tajik (Cyrillic, Tajikistan)
+Globalization.ci_th = Thai
+Globalization.ci_th-TH = Thai (Thailand)
+Globalization.ci_ti = Tigrinya
+Globalization.ci_ti-ER = Tigrinya (Eritrea)
+Globalization.ci_ti-ET = Tigrinya (Ethiopia)
+Globalization.ci_tig = Tigre
+Globalization.ci_tig-ER = Tigre (Eritrea)
+Globalization.ci_tk = Turkmen
+Globalization.ci_tk-TM = Turkmen (Turkmenistan)
+Globalization.ci_tn = Setswana
+Globalization.ci_tn-BW = Setswana (Botswana)
+Globalization.ci_tn-ZA = Setswana (South Africa)
+Globalization.ci_to = Tongan
+Globalization.ci_to-TO = Tongan (Tonga)
+Globalization.ci_tr = Turkish
+Globalization.ci_tr-CY = Turkish (Cyprus)
+Globalization.ci_tr-TR = Turkish (Turkey)
+Globalization.ci_ts = Tsonga
+Globalization.ci_ts-ZA = Tsonga (South Africa)
+Globalization.ci_tt = Tatar
+Globalization.ci_tt-RU = Tatar (Russia)
+Globalization.ci_twq = Tasawaq
+Globalization.ci_twq-NE = Tasawaq (Niger)
+Globalization.ci_tzm = Tamazight
+Globalization.ci_tzm-Latn = Tamazight (Latin)
+Globalization.ci_tzm-Latn-DZ = Tamazight (Latin, Algeria)
+Globalization.ci_tzm-Latn-MA = Central Atlas Tamazight (Latin, Morocco)
+Globalization.ci_tzm-Tfng = Tamazight (Tifinagh)
+Globalization.ci_tzm-Tfng-MA = Central Atlas Tamazight (Tifinagh, Morocco)
+Globalization.ci_ug = Uyghur
+Globalization.ci_ug-CN = Uyghur (PRC)
+Globalization.ci_uk = Ukrainian
+Globalization.ci_uk-UA = Ukrainian (Ukraine)
+Globalization.ci_ur = Urdu
+Globalization.ci_ur-IN = Urdu (India)
+Globalization.ci_ur-PK = Urdu (Islamic Republic of Pakistan)
+Globalization.ci_uz = Uzbek
+Globalization.ci_uz-Arab = Uzbek (Perso-Arabic)
+Globalization.ci_uz-Arab-AF = Uzbek (Perso-Arabic, Afghanistan)
+Globalization.ci_uz-Cyrl = Uzbek (Cyrillic)
+Globalization.ci_uz-Cyrl-UZ = Uzbek (Cyrillic, Uzbekistan)
+Globalization.ci_uz-Latn = Uzbek (Latin)
+Globalization.ci_uz-Latn-UZ = Uzbek (Latin, Uzbekistan)
+Globalization.ci_vai = Vai
+Globalization.ci_vai-Latn = Vai (Latin)
+Globalization.ci_vai-Latn-LR = Vai (Latin, Liberia)
+Globalization.ci_vai-Vaii = Vai (Vai)
+Globalization.ci_vai-Vaii-LR = Vai (Vai, Liberia)
+Globalization.ci_ve = Venda
+Globalization.ci_ve-ZA = Venda (South Africa)
+Globalization.ci_vi = Vietnamese
+Globalization.ci_vi-VN = Vietnamese (Vietnam)
+Globalization.ci_vo = Volapük
+Globalization.ci_vo-001 = Volapük (World)
+Globalization.ci_vun = Vunjo
+Globalization.ci_vun-TZ = Vunjo (Tanzania)
+Globalization.ci_wae = Walser
+Globalization.ci_wae-CH = Walser (Switzerland)
+Globalization.ci_wal = Wolaytta
+Globalization.ci_wal-ET = Wolaytta (Ethiopia)
+Globalization.ci_wo = Wolof
+Globalization.ci_wo-SN = Wolof (Senegal)
+Globalization.ci_x-IV = Invariant Language (Invariant Country)
+Globalization.ci_x-IV_mathan = Invariant Language (Invariant Country)
+Globalization.ci_xh = isiXhosa
+Globalization.ci_xh-ZA = isiXhosa (South Africa)
+Globalization.ci_xog = Soga
+Globalization.ci_xog-UG = Soga (Uganda)
+Globalization.ci_yav = Yangben
+Globalization.ci_yav-CM = Yangben (Cameroon)
+Globalization.ci_yi = Yiddish
+Globalization.ci_yi-001 = Yiddish (World)
+Globalization.ci_yo = Yoruba
+Globalization.ci_yo-BJ = Yoruba (Benin)
+Globalization.ci_yo-NG = Yoruba (Nigeria)
+Globalization.ci_zgh = Standard Moroccan Tamazight
+Globalization.ci_zgh-Tfng = Standard Moroccan Tamazight (Tifinagh)
+Globalization.ci_zgh-Tfng-MA = Standard Moroccan Tamazight (Tifinagh, Morocco)
+Globalization.ci_zh = Chinese
+Globalization.ci_zh-CHS = Chinese (Simplified) Legacy
+Globalization.ci_zh-CHT = Chinese (Traditional) Legacy
+Globalization.ci_zh-CN = Chinese (Simplified, PRC)
+Globalization.ci_zh-CN_stroke = Chinese (Simplified, PRC)
+Globalization.ci_zh-Hans = Chinese (Simplified)
+Globalization.ci_zh-Hant = Chinese (Traditional)
+Globalization.ci_zh-HK = Chinese (Traditional, Hong Kong S.A.R.)
+Globalization.ci_zh-HK_radstr = Chinese (Traditional, Hong Kong S.A.R.)
+Globalization.ci_zh-MO = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-MO_radstr = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-MO_stroke = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-SG = Chinese (Simplified, Singapore)
+Globalization.ci_zh-SG_stroke = Chinese (Simplified, Singapore)
+Globalization.ci_zh-TW = Chinese (Traditional, Taiwan)
+Globalization.ci_zh-TW_pronun = Chinese (Traditional, Taiwan)
+Globalization.ci_zh-TW_radstr = Chinese (Traditional, Taiwan)
+Globalization.ci_zu = isiZulu
+Globalization.ci_zu-ZA = isiZulu (South Africa)
+;------------------
+;
+;Total items: 129
+;
+Globalization.ri_029 = Caribbean
+Globalization.ri_AE = U.A.E.
+Globalization.ri_AF = Afghanistan
+Globalization.ri_AL = Albania
+Globalization.ri_AM = Armenia
+Globalization.ri_AR = Argentina
+Globalization.ri_AT = Austria
+Globalization.ri_AU = Australia
+Globalization.ri_AZ = Azerbaijan
+Globalization.ri_BA = Bosnia and Herzegovina
+Globalization.ri_BD = Bangladesh
+Globalization.ri_BE = Belgium
+Globalization.ri_BG = Bulgaria
+Globalization.ri_BH = Bahrain
+Globalization.ri_BN = Brunei Darussalam
+Globalization.ri_BO = Bolivia
+Globalization.ri_BR = Brazil
+Globalization.ri_BY = Belarus
+Globalization.ri_BZ = Belize
+Globalization.ri_CA = Canada
+Globalization.ri_CH = Switzerland
+Globalization.ri_CL = Chile
+Globalization.ri_CN = People's Republic of China
+Globalization.ri_CO = Colombia
+Globalization.ri_CR = Costa Rica
+Globalization.ri_CS = Serbia and Montenegro (Former)
+Globalization.ri_CZ = Czech Republic
+Globalization.ri_DE = Germany
+Globalization.ri_DK = Denmark
+Globalization.ri_DO = Dominican Republic
+Globalization.ri_DZ = Algeria
+Globalization.ri_EC = Ecuador
+Globalization.ri_EE = Estonia
+Globalization.ri_EG = Egypt
+Globalization.ri_ER = Eritrea
+Globalization.ri_ES = Spain
+Globalization.ri_ET = Ethiopia
+Globalization.ri_FI = Finland
+Globalization.ri_FO = Faroe Islands
+Globalization.ri_FR = France
+Globalization.ri_GB = United Kingdom
+Globalization.ri_GE = Georgia
+Globalization.ri_GL = Greenland
+Globalization.ri_GR = Greece
+Globalization.ri_GT = Guatemala
+Globalization.ri_HK = Hong Kong S.A.R.
+Globalization.ri_HN = Honduras
+Globalization.ri_HR = Croatia
+Globalization.ri_HU = Hungary
+Globalization.ri_ID = Indonesia
+Globalization.ri_IE = Ireland
+Globalization.ri_IL = Israel
+Globalization.ri_IN = India
+Globalization.ri_IQ = Iraq
+Globalization.ri_IR = Iran
+Globalization.ri_IS = Iceland
+Globalization.ri_IT = Italy
+Globalization.ri_IV = Invariant Country
+Globalization.ri_JM = Jamaica
+Globalization.ri_JO = Jordan
+Globalization.ri_JP = Japan
+Globalization.ri_KE = Kenya
+Globalization.ri_KG = Kyrgyzstan
+Globalization.ri_KH = Cambodia
+Globalization.ri_KR = Korea
+Globalization.ri_KW = Kuwait
+Globalization.ri_KZ = Kazakhstan
+Globalization.ri_LA = Lao P.D.R.
+Globalization.ri_LB = Lebanon
+Globalization.ri_LI = Liechtenstein
+Globalization.ri_LK = Sri Lanka
+Globalization.ri_LT = Lithuania
+Globalization.ri_LU = Luxembourg
+Globalization.ri_LV = Latvia
+Globalization.ri_LY = Libya
+Globalization.ri_MA = Morocco
+Globalization.ri_MC = Principality of Monaco
+Globalization.ri_ME = Montenegro
+Globalization.ri_MK = Macedonia (FYROM)
+Globalization.ri_MN = Mongolia
+Globalization.ri_MO = Macao S.A.R.
+Globalization.ri_MT = Malta
+Globalization.ri_MV = Maldives
+Globalization.ri_MX = Mexico
+Globalization.ri_MY = Malaysia
+Globalization.ri_NG = Nigeria
+Globalization.ri_NI = Nicaragua
+Globalization.ri_NL = Netherlands
+Globalization.ri_NO = Norway
+Globalization.ri_NP = Nepal
+Globalization.ri_NZ = New Zealand
+Globalization.ri_OM = Oman
+Globalization.ri_PA = Panama
+Globalization.ri_PE = Peru
+Globalization.ri_PH = Philippines
+Globalization.ri_PK = Islamic Republic of Pakistan
+Globalization.ri_PL = Poland
+Globalization.ri_PR = Puerto Rico
+Globalization.ri_PT = Portugal
+Globalization.ri_PY = Paraguay
+Globalization.ri_QA = Qatar
+Globalization.ri_RO = Romania
+Globalization.ri_RS = Serbia
+Globalization.ri_RU = Russia
+Globalization.ri_RW = Rwanda
+Globalization.ri_SA = Saudi Arabia
+Globalization.ri_SE = Sweden
+Globalization.ri_SG = Singapore
+Globalization.ri_SI = Slovenia
+Globalization.ri_SK = Slovakia
+Globalization.ri_SN = Senegal
+Globalization.ri_SV = El Salvador
+Globalization.ri_SY = Syria
+Globalization.ri_TH = Thailand
+Globalization.ri_TJ = Tajikistan
+Globalization.ri_TM = Turkmenistan
+Globalization.ri_TN = Tunisia
+Globalization.ri_TR = Turkey
+Globalization.ri_TT = Trinidad and Tobago
+Globalization.ri_TW = Taiwan
+Globalization.ri_UA = Ukraine
+Globalization.ri_US = United States
+Globalization.ri_UY = Uruguay
+Globalization.ri_UZ = Uzbekistan
+Globalization.ri_VE = Bolivarian Republic of Venezuela
+Globalization.ri_VN = Vietnam
+Globalization.ri_YE = Yemen
+Globalization.ri_ZA = South Africa
+Globalization.ri_ZW = Zimbabwe
+#endif //!FEATURE_CORECLR
+
+;------------------
+; Encoding names:
+;
+;Total items: 147
+;
+Globalization.cp_1200 = Unicode
+Globalization.cp_1201 = Unicode (Big-Endian)
+Globalization.cp_65001 = Unicode (UTF-8)
+Globalization.cp_65000 = Unicode (UTF-7)
+Globalization.cp_12000 = Unicode (UTF-32)
+Globalization.cp_12001 = Unicode (UTF-32 Big-Endian)
+Globalization.cp_20127 = US-ASCII
+Globalization.cp_28591 = Western European (ISO)
+
+#if FEATURE_NON_UNICODE_CODE_PAGES
+Globalization.cp_37 = IBM EBCDIC (US-Canada)
+Globalization.cp_437 = OEM United States
+Globalization.cp_500 = IBM EBCDIC (International)
+Globalization.cp_708 = Arabic (ASMO 708)
+Globalization.cp_720 = Arabic (DOS)
+Globalization.cp_737 = Greek (DOS)
+Globalization.cp_775 = Baltic (DOS)
+Globalization.cp_850 = Western European (DOS)
+Globalization.cp_852 = Central European (DOS)
+Globalization.cp_855 = OEM Cyrillic
+Globalization.cp_857 = Turkish (DOS)
+Globalization.cp_858 = OEM Multilingual Latin I
+Globalization.cp_860 = Portuguese (DOS)
+Globalization.cp_861 = Icelandic (DOS)
+Globalization.cp_862 = Hebrew (DOS)
+Globalization.cp_863 = French Canadian (DOS)
+Globalization.cp_864 = Arabic (864)
+Globalization.cp_865 = Nordic (DOS)
+Globalization.cp_866 = Cyrillic (DOS)
+Globalization.cp_869 = Greek, Modern (DOS)
+Globalization.cp_870 = IBM EBCDIC (Multilingual Latin-2)
+Globalization.cp_874 = Thai (Windows)
+Globalization.cp_875 = IBM EBCDIC (Greek Modern)
+Globalization.cp_932 = Japanese (Shift-JIS)
+Globalization.cp_936 = Chinese Simplified (GB2312)
+Globalization.cp_949 = Korean
+Globalization.cp_950 = Chinese Traditional (Big5)
+Globalization.cp_1026 = IBM EBCDIC (Turkish Latin-5)
+Globalization.cp_1047 = IBM Latin-1
+Globalization.cp_1140 = IBM EBCDIC (US-Canada-Euro)
+Globalization.cp_1141 = IBM EBCDIC (Germany-Euro)
+Globalization.cp_1142 = IBM EBCDIC (Denmark-Norway-Euro)
+Globalization.cp_1143 = IBM EBCDIC (Finland-Sweden-Euro)
+Globalization.cp_1144 = IBM EBCDIC (Italy-Euro)
+Globalization.cp_1145 = IBM EBCDIC (Spain-Euro)
+Globalization.cp_1146 = IBM EBCDIC (UK-Euro)
+Globalization.cp_1147 = IBM EBCDIC (France-Euro)
+Globalization.cp_1148 = IBM EBCDIC (International-Euro)
+Globalization.cp_1149 = IBM EBCDIC (Icelandic-Euro)
+Globalization.cp_1250 = Central European (Windows)
+Globalization.cp_1251 = Cyrillic (Windows)
+Globalization.cp_1252 = Western European (Windows)
+Globalization.cp_1253 = Greek (Windows)
+Globalization.cp_1254 = Turkish (Windows)
+Globalization.cp_1255 = Hebrew (Windows)
+Globalization.cp_1256 = Arabic (Windows)
+Globalization.cp_1257 = Baltic (Windows)
+Globalization.cp_1258 = Vietnamese (Windows)
+Globalization.cp_1361 = Korean (Johab)
+Globalization.cp_10000 = Western European (Mac)
+Globalization.cp_10001 = Japanese (Mac)
+Globalization.cp_10002 = Chinese Traditional (Mac)
+Globalization.cp_10003 = Korean (Mac)
+Globalization.cp_10004 = Arabic (Mac)
+Globalization.cp_10005 = Hebrew (Mac)
+Globalization.cp_10006 = Greek (Mac)
+Globalization.cp_10007 = Cyrillic (Mac)
+Globalization.cp_10008 = Chinese Simplified (Mac)
+Globalization.cp_10010 = Romanian (Mac)
+Globalization.cp_10017 = Ukrainian (Mac)
+Globalization.cp_10021 = Thai (Mac)
+Globalization.cp_10029 = Central European (Mac)
+Globalization.cp_10079 = Icelandic (Mac)
+Globalization.cp_10081 = Turkish (Mac)
+Globalization.cp_10082 = Croatian (Mac)
+Globalization.cp_20000 = Chinese Traditional (CNS)
+Globalization.cp_20001 = TCA Taiwan
+Globalization.cp_20002 = Chinese Traditional (Eten)
+Globalization.cp_20003 = IBM5550 Taiwan
+Globalization.cp_20004 = TeleText Taiwan
+Globalization.cp_20005 = Wang Taiwan
+Globalization.cp_20105 = Western European (IA5)
+Globalization.cp_20106 = German (IA5)
+Globalization.cp_20107 = Swedish (IA5)
+Globalization.cp_20108 = Norwegian (IA5)
+Globalization.cp_20261 = T.61
+Globalization.cp_20269 = ISO-6937
+Globalization.cp_20273 = IBM EBCDIC (Germany)
+Globalization.cp_20277 = IBM EBCDIC (Denmark-Norway)
+Globalization.cp_20278 = IBM EBCDIC (Finland-Sweden)
+Globalization.cp_20280 = IBM EBCDIC (Italy)
+Globalization.cp_20284 = IBM EBCDIC (Spain)
+Globalization.cp_20285 = IBM EBCDIC (UK)
+Globalization.cp_20290 = IBM EBCDIC (Japanese katakana)
+Globalization.cp_20297 = IBM EBCDIC (France)
+Globalization.cp_20420 = IBM EBCDIC (Arabic)
+Globalization.cp_20423 = IBM EBCDIC (Greek)
+Globalization.cp_20424 = IBM EBCDIC (Hebrew)
+Globalization.cp_20833 = IBM EBCDIC (Korean Extended)
+Globalization.cp_20838 = IBM EBCDIC (Thai)
+Globalization.cp_20866 = Cyrillic (KOI8-R)
+Globalization.cp_20871 = IBM EBCDIC (Icelandic)
+Globalization.cp_20880 = IBM EBCDIC (Cyrillic Russian)
+Globalization.cp_20905 = IBM EBCDIC (Turkish)
+Globalization.cp_20924 = IBM Latin-1
+Globalization.cp_20932 = Japanese (JIS 0208-1990 and 0212-1990)
+Globalization.cp_20936 = Chinese Simplified (GB2312-80)
+Globalization.cp_20949 = Korean Wansung
+Globalization.cp_21025 = IBM EBCDIC (Cyrillic Serbian-Bulgarian)
+Globalization.cp_21027 = Ext Alpha Lowercase
+Globalization.cp_21866 = Cyrillic (KOI8-U)
+Globalization.cp_28592 = Central European (ISO)
+Globalization.cp_28593 = Latin 3 (ISO)
+Globalization.cp_28594 = Baltic (ISO)
+Globalization.cp_28595 = Cyrillic (ISO)
+Globalization.cp_28596 = Arabic (ISO)
+Globalization.cp_28597 = Greek (ISO)
+Globalization.cp_28598 = Hebrew (ISO-Visual)
+Globalization.cp_28599 = Turkish (ISO)
+Globalization.cp_28603 = Estonian (ISO)
+Globalization.cp_28605 = Latin 9 (ISO)
+Globalization.cp_29001 = Europa
+Globalization.cp_38598 = Hebrew (ISO-Logical)
+Globalization.cp_50000 = User Defined
+Globalization.cp_50220 = Japanese (JIS)
+Globalization.cp_50221 = Japanese (JIS-Allow 1 byte Kana)
+Globalization.cp_50222 = Japanese (JIS-Allow 1 byte Kana - SO/SI)
+Globalization.cp_50225 = Korean (ISO)
+Globalization.cp_50227 = Chinese Simplified (ISO-2022)
+Globalization.cp_50229 = Chinese Traditional (ISO-2022)
+Globalization.cp_50930 = IBM EBCDIC (Japanese and Japanese Katakana)
+Globalization.cp_50931 = IBM EBCDIC (Japanese and US-Canada)
+Globalization.cp_50933 = IBM EBCDIC (Korean and Korean Extended)
+Globalization.cp_50935 = IBM EBCDIC (Simplified Chinese)
+Globalization.cp_50937 = IBM EBCDIC (Traditional Chinese)
+Globalization.cp_50939 = IBM EBCDIC (Japanese and Japanese-Latin)
+Globalization.cp_51932 = Japanese (EUC)
+Globalization.cp_51936 = Chinese Simplified (EUC)
+Globalization.cp_51949 = Korean (EUC)
+Globalization.cp_52936 = Chinese Simplified (HZ)
+Globalization.cp_54936 = Chinese Simplified (GB18030)
+Globalization.cp_57002 = ISCII Devanagari
+Globalization.cp_57003 = ISCII Bengali
+Globalization.cp_57004 = ISCII Tamil
+Globalization.cp_57005 = ISCII Telugu
+Globalization.cp_57006 = ISCII Assamese
+Globalization.cp_57007 = ISCII Oriya
+Globalization.cp_57008 = ISCII Kannada
+Globalization.cp_57009 = ISCII Malayalam
+Globalization.cp_57010 = ISCII Gujarati
+Globalization.cp_57011 = ISCII Punjabi
+#endif // FEATURE_NON_UNICODE_CODE_PAGES
+#endif // INCLUDE_DEBUG
+
+;------------------
+
diff --git a/src/mscorlib/src/System/AccessViolationException.cs b/src/mscorlib/src/System/AccessViolationException.cs
new file mode 100644
index 0000000000..308d52e9ed
--- /dev/null
+++ b/src/mscorlib/src/System/AccessViolationException.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class representing an AV that was deemed unsafe and may have corrupted the application.
+**
+**
+=============================================================================*/
+
+namespace System
+{
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class AccessViolationException : SystemException
+ {
+ public AccessViolationException()
+ : base(Environment.GetResourceString("Arg_AccessViolationException"))
+ {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ public AccessViolationException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ public AccessViolationException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ protected AccessViolationException(SerializationInfo info, StreamingContext context) : base(info, context) {}
+
+#pragma warning disable 169 // Field is not used from managed.
+ private IntPtr _ip; // Address of faulting instruction.
+ private IntPtr _target; // Address that could not be accessed.
+ private int _accessType; // 0:read, 1:write
+#pragma warning restore 169
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Action.cs b/src/mscorlib/src/System/Action.cs
new file mode 100644
index 0000000000..d6653c7979
--- /dev/null
+++ b/src/mscorlib/src/System/Action.cs
@@ -0,0 +1,78 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System {
+ using System.Runtime.CompilerServices;
+
+ public delegate void Action<in T>(T obj);
+
+ // Action/Func delegates first shipped with .NET Framework 3.5 in System.Core.dll as part of LINQ
+ // These were type forwarded to mscorlib.dll in .NET Framework 4.0 and in Silverlight 5.0
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate void Action();
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate void Action<in T1,in T2>(T1 arg1, T2 arg2);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate void Action<in T1,in T2,in T3>(T1 arg1, T2 arg2, T3 arg3);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate void Action<in T1,in T2,in T3,in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate TResult Func<out TResult>();
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate TResult Func<in T, out TResult>(T arg);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate TResult Func<in T1, in T2, in T3, out TResult>(T1 arg1, T2 arg2, T3 arg3);
+
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public delegate TResult Func<in T1, in T2, in T3, in T4, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+
+
+ public delegate void Action<in T1,in T2,in T3,in T4,in T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+ public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+ public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+ public delegate void Action<in T1,in T2,in T3,in T4,in T5,in T6,in T7,in T8>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7);
+ public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8);
+
+ public delegate int Comparison<in T>(T x, T y);
+
+ public delegate TOutput Converter<in TInput, out TOutput>(TInput input);
+
+ public delegate bool Predicate<in T>(T obj);
+
+}
+
diff --git a/src/mscorlib/src/System/Activator.cs b/src/mscorlib/src/System/Activator.cs
new file mode 100644
index 0000000000..274b0e7ec5
--- /dev/null
+++ b/src/mscorlib/src/System/Activator.cs
@@ -0,0 +1,688 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// Activator is an object that contains the Activation (CreateInstance/New)
+// methods for late bound support.
+//
+//
+//
+//
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Activation;
+ using Message = System.Runtime.Remoting.Messaging.Message;
+#endif
+ using System.Security;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using Evidence = System.Security.Policy.Evidence;
+ using StackCrawlMark = System.Threading.StackCrawlMark;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using AssemblyHashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // Only statics, does not need to be marked with the serializable attribute
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Activator))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Activator : _Activator
+ {
+ internal const int LookupMask = 0x000000FF;
+ internal const BindingFlags ConLookup = (BindingFlags) (BindingFlags.Instance | BindingFlags.Public);
+ internal const BindingFlags ConstructorDefault= BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
+
+ // This class only contains statics, so hide the worthless constructor
+ private Activator()
+ {
+ }
+
+ // CreateInstance
+ // The following methods will create a new instance of an Object
+ // Full Binding Support
+ // For all of these methods we need to get the underlying RuntimeType and
+ // call the Impl version.
+ static public Object CreateInstance(Type type,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture)
+ {
+ return CreateInstance(type, bindingAttr, binder, args, culture, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public Object CreateInstance(Type type,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes)
+ {
+ if ((object)type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ if (type is System.Reflection.Emit.TypeBuilder)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CreateInstanceWithTypeBuilder"));
+
+ // If they didn't specify a lookup, then we will provide the default lookup.
+ if ((bindingAttr & (BindingFlags) LookupMask) == 0)
+ bindingAttr |= Activator.ConstructorDefault;
+
+ if (activationAttributes != null && activationAttributes.Length > 0){
+ // If type does not derive from MBR
+ // throw notsupportedexception
+#if FEATURE_REMOTING
+ if(type.IsMarshalByRef){
+ // The fix below is preventative.
+ //
+ if(!(type.IsContextful)){
+ if(activationAttributes.Length > 1 || !(activationAttributes[0] is UrlAttribute))
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonUrlAttrOnMBR"));
+ }
+ }
+ else
+#endif
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ActivAttrOnNonMBR" ));
+ }
+
+ RuntimeType rt = type.UnderlyingSystemType as RuntimeType;
+
+ if (rt == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"type");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return rt.CreateInstanceImpl(bindingAttr,binder,args,culture,activationAttributes, ref stackMark);
+ }
+
+ static public Object CreateInstance(Type type, params Object[] args)
+ {
+ return CreateInstance(type,
+ Activator.ConstructorDefault,
+ null,
+ args,
+ null,
+ null);
+ }
+
+ static public Object CreateInstance(Type type,
+ Object[] args,
+ Object[] activationAttributes)
+ {
+ return CreateInstance(type,
+ Activator.ConstructorDefault,
+ null,
+ args,
+ null,
+ activationAttributes);
+ }
+
+ static public Object CreateInstance(Type type)
+ {
+ return Activator.CreateInstance(type, false);
+ }
+
+ /*
+ * Create an instance using the name of type and the assembly where it exists. This allows
+ * types to be created remotely without having to load the type locally.
+ */
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public ObjectHandle CreateInstance(String assemblyName,
+ String typeName)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return CreateInstance(assemblyName,
+ typeName,
+ false,
+ Activator.ConstructorDefault,
+ null,
+ null,
+ null,
+ null,
+ null,
+ ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ Object[] activationAttributes)
+
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return CreateInstance(assemblyName,
+ typeName,
+ false,
+ Activator.ConstructorDefault,
+ null,
+ null,
+ null,
+ activationAttributes,
+ null,
+ ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public Object CreateInstance(Type type, bool nonPublic)
+ {
+ if ((object)type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ RuntimeType rt = type.UnderlyingSystemType as RuntimeType;
+
+ if (rt == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return rt.CreateInstanceDefaultCtor(!nonPublic, false, true, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public T CreateInstance<T>()
+ {
+ RuntimeType rt = typeof(T) as RuntimeType;
+
+ // This is a workaround to maintain compatibility with V2. Without this we would throw a NotSupportedException for void[].
+ // Array, Ref, and Pointer types don't have default constructors.
+ if (rt.HasElementType)
+ throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor"));
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // Skip the CreateInstanceCheckThis call to avoid perf cost and to maintain compatibility with V2 (throwing the same exceptions).
+ return (T)rt.CreateInstanceDefaultCtor(true /*publicOnly*/, true /*skipCheckThis*/, true /*fillCache*/, ref stackMark);
+ }
+
+ static public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName)
+
+ {
+ return CreateInstanceFrom(assemblyFile, typeName, null);
+ }
+
+ static public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ Object[] activationAttributes)
+
+ {
+ return CreateInstanceFrom(assemblyFile,
+ typeName,
+ false,
+ Activator.ConstructorDefault,
+ null,
+ null,
+ null,
+ activationAttributes);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityInfo)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ securityInfo,
+ ref stackMark);
+ }
+
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static ObjectHandle CreateInstance(string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ null,
+ ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal ObjectHandle CreateInstance(String assemblyString,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityInfo,
+ ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ if (securityInfo != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ Type type = null;
+ Assembly assembly = null;
+ if (assemblyString == null) {
+ assembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ } else {
+ RuntimeAssembly assemblyFromResolveEvent;
+ AssemblyName assemblyName = RuntimeAssembly.CreateAssemblyName(assemblyString, false /*forIntrospection*/, out assemblyFromResolveEvent);
+ if (assemblyFromResolveEvent != null) {
+ // Assembly was resolved via AssemblyResolve event
+ assembly = assemblyFromResolveEvent;
+ } else if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime) {
+ // WinRT type - we have to use Type.GetType
+ type = Type.GetType(typeName + ", " + assemblyString, true /*throwOnError*/, ignoreCase);
+ } else {
+ // Classic managed type
+ assembly = RuntimeAssembly.InternalLoadAssemblyName(
+ assemblyName, securityInfo, null, ref stackMark,
+ true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/);
+ }
+ }
+
+ if (type == null) {
+ // It's classic managed type (not WinRT type)
+ Log(assembly != null, "CreateInstance:: ", "Loaded " + assembly.FullName, "Failed to Load: " + assemblyString);
+ if(assembly == null) return null;
+
+ type = assembly.GetType(typeName, true /*throwOnError*/, ignoreCase);
+ }
+
+ Object o = Activator.CreateInstance(type,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+
+ Log(o != null, "CreateInstance:: ", "Created Instance of class " + typeName, "Failed to create instance of class " + typeName);
+ if(o == null)
+ return null;
+ else {
+ ObjectHandle Handle = new ObjectHandle(o);
+ return Handle;
+ }
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityInfo)
+
+ {
+#if FEATURE_CAS_POLICY
+ if (securityInfo != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ return CreateInstanceFromInternal(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ securityInfo);
+ }
+
+ public static ObjectHandle CreateInstanceFrom(string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ return CreateInstanceFromInternal(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ null);
+ }
+
+ private static ObjectHandle CreateInstanceFromInternal(String assemblyFile,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityInfo)
+ {
+#if FEATURE_CAS_POLICY
+ Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled || securityInfo == null);
+#endif // FEATURE_CAS_POLICY
+
+#pragma warning disable 618
+ Assembly assembly = Assembly.LoadFrom(assemblyFile, securityInfo);
+#pragma warning restore 618
+ Type t = assembly.GetType(typeName, true, ignoreCase);
+
+ Object o = Activator.CreateInstance(t,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+
+ Log(o != null, "CreateInstanceFrom:: ", "Created Instance of class " + typeName, "Failed to create instance of class " + typeName);
+ if(o == null)
+ return null;
+ else {
+ ObjectHandle Handle = new ObjectHandle(o);
+ return Handle;
+ }
+ }
+
+ //
+ // This API is designed to be used when a host needs to execute code in an AppDomain
+ // with restricted security permissions. In that case, we demand in the client domain
+ // and assert in the server domain because the server domain might not be trusted enough
+ // to pass the security checks when activating the type.
+ //
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static ObjectHandle CreateInstance (AppDomain domain, string assemblyName, string typeName) {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+ return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static ObjectHandle CreateInstance (AppDomain domain,
+ string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes) {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+
+#if FEATURE_CAS_POLICY
+ if (securityAttributes != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ return domain.InternalCreateInstanceWithNoSecurity(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes);
+ }
+
+ [SecurityCritical]
+ public static ObjectHandle CreateInstance(AppDomain domain,
+ string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+
+ return domain.InternalCreateInstanceWithNoSecurity(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ null);
+ }
+
+ //
+ // This API is designed to be used when a host needs to execute code in an AppDomain
+ // with restricted security permissions. In that case, we demand in the client domain
+ // and assert in the server domain because the server domain might not be trusted enough
+ // to pass the security checks when activating the type.
+ //
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static ObjectHandle CreateInstanceFrom (AppDomain domain, string assemblyFile, string typeName) {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+ return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Methods which use Evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static ObjectHandle CreateInstanceFrom (AppDomain domain,
+ string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes) {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+
+#if FEATURE_CAS_POLICY
+ if (securityAttributes != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes);
+ }
+
+ [SecurityCritical]
+ public static ObjectHandle CreateInstanceFrom(AppDomain domain,
+ string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+
+ return domain.InternalCreateInstanceFromWithNoSecurity(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ null);
+ }
+
+#if FEATURE_CLICKONCE
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static ObjectHandle CreateInstance (ActivationContext activationContext) {
+ AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
+ if (domainManager == null)
+ domainManager = new AppDomainManager();
+
+ return domainManager.ApplicationActivator.CreateInstance(activationContext);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static ObjectHandle CreateInstance (ActivationContext activationContext, string[] activationCustomData) {
+ AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
+ if (domainManager == null)
+ domainManager = new AppDomainManager();
+
+ return domainManager.ApplicationActivator.CreateInstance(activationContext, activationCustomData);
+ }
+#endif // FEATURE_CLICKONCE
+
+ public static ObjectHandle CreateComInstanceFrom(String assemblyName,
+ String typeName)
+ {
+ return CreateComInstanceFrom(assemblyName,
+ typeName,
+ null,
+ AssemblyHashAlgorithm.None);
+
+ }
+
+ public static ObjectHandle CreateComInstanceFrom(String assemblyName,
+ String typeName,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+ {
+ Assembly assembly = Assembly.LoadFrom(assemblyName, hashValue, hashAlgorithm);
+
+ Type t = assembly.GetType(typeName, true, false);
+
+ Object[] Attr = t.GetCustomAttributes(typeof(ComVisibleAttribute),false);
+ if (Attr.Length > 0)
+ {
+ if (((ComVisibleAttribute)Attr[0]).Value == false)
+ throw new TypeLoadException(Environment.GetResourceString( "Argument_TypeMustBeVisibleFromCom" ));
+ }
+
+ Log(assembly != null, "CreateInstance:: ", "Loaded " + assembly.FullName, "Failed to Load: " + assemblyName);
+
+ if(assembly == null) return null;
+
+
+ Object o = Activator.CreateInstance(t,
+ Activator.ConstructorDefault,
+ null,
+ null,
+ null,
+ null);
+
+ Log(o != null, "CreateInstance:: ", "Created Instance of class " + typeName, "Failed to create instance of class " + typeName);
+ if(o == null)
+ return null;
+ else {
+ ObjectHandle Handle = new ObjectHandle(o);
+ return Handle;
+ }
+ }
+
+#if FEATURE_REMOTING
+ // This method is a helper method and delegates to the remoting
+ // services to do the actual work.
+ [System.Security.SecurityCritical] // auto-generated_required
+ static public Object GetObject(Type type, String url)
+ {
+ return GetObject(type, url, null);
+ }
+
+ // This method is a helper method and delegates to the remoting
+ // services to do the actual work.
+ [System.Security.SecurityCritical] // auto-generated_required
+ static public Object GetObject(Type type, String url, Object state)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ return RemotingServices.Connect(type, url, state);
+ }
+#endif
+
+ [System.Diagnostics.Conditional("_DEBUG")]
+ private static void Log(bool test, string title, string success, string failure)
+ {
+#if FEATURE_REMOTING
+ if(test)
+ BCLDebug.Trace("REMOTE", "{0}{1}", title, success);
+ else
+ BCLDebug.Trace("REMOTE", "{0}{1}", title, failure);
+#endif
+ }
+
+ void _Activator.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Activator.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Activator.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _Activator.Invoke in VM\DangerousAPIs.h and
+ // include _Activator in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _Activator.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/AggregateException.cs b/src/mscorlib/src/System/AggregateException.cs
new file mode 100644
index 0000000000..064432aaaa
--- /dev/null
+++ b/src/mscorlib/src/System/AggregateException.cs
@@ -0,0 +1,497 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Public type to communicate multiple failures to an end-user.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.ExceptionServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Text;
+using System.Threading;
+
+namespace System
+{
+
+ /// <summary>Represents one or more errors that occur during application execution.</summary>
+ /// <remarks>
+ /// <see cref="AggregateException"/> is used to consolidate multiple failures into a single, throwable
+ /// exception object.
+ /// </remarks>
+ [Serializable]
+ [DebuggerDisplay("Count = {InnerExceptionCount}")]
+ public class AggregateException : Exception
+ {
+
+ private ReadOnlyCollection<Exception> m_innerExceptions; // Complete set of exceptions.
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class.
+ /// </summary>
+ public AggregateException()
+ : base(Environment.GetResourceString("AggregateException_ctor_DefaultMessage"))
+ {
+ m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[0]);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// a specified error message.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ public AggregateException(string message)
+ : base(message)
+ {
+ m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[0]);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and a reference to the inner exception that is the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerException"/> argument
+ /// is null.</exception>
+ public AggregateException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ if (innerException == null)
+ {
+ throw new ArgumentNullException("innerException");
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(new Exception[] { innerException });
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(IEnumerable<Exception> innerExceptions) :
+ this(Environment.GetResourceString("AggregateException_ctor_DefaultMessage"), innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(params Exception[] innerExceptions) :
+ this(Environment.GetResourceString("AggregateException_ctor_DefaultMessage"), innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(string message, IEnumerable<Exception> innerExceptions)
+ // If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ : this(message, innerExceptions as IList<Exception> ?? (innerExceptions == null ? (List<Exception>)null : new List<Exception>(innerExceptions)))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exceptions that are the cause of this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ public AggregateException(string message, params Exception[] innerExceptions) :
+ this(message, (IList<Exception>)innerExceptions)
+ {
+ }
+
+ /// <summary>
+ /// Allocates a new aggregate exception with the specified message and list of inner exceptions.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptions">The exceptions that are the cause of the current exception.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptions"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptions"/> is
+ /// null.</exception>
+ private AggregateException(string message, IList<Exception> innerExceptions)
+ : base(message, innerExceptions != null && innerExceptions.Count > 0 ? innerExceptions[0] : null)
+ {
+ if (innerExceptions == null)
+ {
+ throw new ArgumentNullException("innerExceptions");
+ }
+
+ // Copy exceptions to our internal array and validate them. We must copy them,
+ // because we're going to put them into a ReadOnlyCollection which simply reuses
+ // the list passed in to it. We don't want callers subsequently mutating.
+ Exception[] exceptionsCopy = new Exception[innerExceptions.Count];
+
+ for (int i = 0; i < exceptionsCopy.Length; i++)
+ {
+ exceptionsCopy[i] = innerExceptions[i];
+
+ if (exceptionsCopy[i] == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("AggregateException_ctor_InnerExceptionNull"));
+ }
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(exceptionsCopy);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with
+ /// references to the inner exception dispatch info objects that represent the cause of this exception.
+ /// </summary>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ internal AggregateException(IEnumerable<ExceptionDispatchInfo> innerExceptionInfos) :
+ this(Environment.GetResourceString("AggregateException_ctor_DefaultMessage"), innerExceptionInfos)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with a specified error
+ /// message and references to the inner exception dispatch info objects that represent the cause of
+ /// this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ internal AggregateException(string message, IEnumerable<ExceptionDispatchInfo> innerExceptionInfos)
+ // If it's already an IList, pass that along (a defensive copy will be made in the delegated ctor). If it's null, just pass along
+ // null typed correctly. Otherwise, create an IList from the enumerable and pass that along.
+ : this(message, innerExceptionInfos as IList<ExceptionDispatchInfo> ??
+ (innerExceptionInfos == null ?
+ (List<ExceptionDispatchInfo>)null :
+ new List<ExceptionDispatchInfo>(innerExceptionInfos)))
+ {
+ }
+
+ /// <summary>
+ /// Allocates a new aggregate exception with the specified message and list of inner
+ /// exception dispatch info objects.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerExceptionInfos">
+ /// Information about the exceptions that are the cause of the current exception.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="innerExceptionInfos"/> argument
+ /// is null.</exception>
+ /// <exception cref="T:System.ArgumentException">An element of <paramref name="innerExceptionInfos"/> is
+ /// null.</exception>
+ private AggregateException(string message, IList<ExceptionDispatchInfo> innerExceptionInfos)
+ : base(message, innerExceptionInfos != null && innerExceptionInfos.Count > 0 && innerExceptionInfos[0] != null ?
+ innerExceptionInfos[0].SourceException : null)
+ {
+ if (innerExceptionInfos == null)
+ {
+ throw new ArgumentNullException("innerExceptionInfos");
+ }
+
+ // Copy exceptions to our internal array and validate them. We must copy them,
+ // because we're going to put them into a ReadOnlyCollection which simply reuses
+ // the list passed in to it. We don't want callers subsequently mutating.
+ Exception[] exceptionsCopy = new Exception[innerExceptionInfos.Count];
+
+ for (int i = 0; i < exceptionsCopy.Length; i++)
+ {
+ var edi = innerExceptionInfos[i];
+ if (edi != null) exceptionsCopy[i] = edi.SourceException;
+
+ if (exceptionsCopy[i] == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("AggregateException_ctor_InnerExceptionNull"));
+ }
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(exceptionsCopy);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="AggregateException"/> class with serialized data.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
+ /// the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that
+ /// contains contextual information about the source or destination. </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> argument is null.</exception>
+ /// <exception cref="T:System.Runtime.Serialization.SerializationException">The exception could not be deserialized correctly.</exception>
+ [SecurityCritical]
+ protected AggregateException(SerializationInfo info, StreamingContext context) :
+ base(info, context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+
+ Exception[] innerExceptions = info.GetValue("InnerExceptions", typeof(Exception[])) as Exception[];
+ if (innerExceptions == null)
+ {
+ throw new SerializationException(Environment.GetResourceString("AggregateException_DeserializationFailure"));
+ }
+
+ m_innerExceptions = new ReadOnlyCollection<Exception>(innerExceptions);
+ }
+
+ /// <summary>
+ /// Sets the <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with information about
+ /// the exception.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
+ /// the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that
+ /// contains contextual information about the source or destination. </param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> argument is null.</exception>
+ [SecurityCritical]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+
+ base.GetObjectData(info, context);
+
+ Exception[] innerExceptions = new Exception[m_innerExceptions.Count];
+ m_innerExceptions.CopyTo(innerExceptions, 0);
+ info.AddValue("InnerExceptions", innerExceptions, typeof(Exception[]));
+ }
+
+ /// <summary>
+ /// Returns the <see cref="System.AggregateException"/> that is the root cause of this exception.
+ /// </summary>
+ public override Exception GetBaseException()
+ {
+ // Returns the first inner AggregateException that contains more or less than one inner exception
+
+ // Recursively traverse the inner exceptions as long as the inner exception of type AggregateException and has only one inner exception
+ Exception back = this;
+ AggregateException backAsAggregate = this;
+ while (backAsAggregate != null && backAsAggregate.InnerExceptions.Count == 1)
+ {
+ back = back.InnerException;
+ backAsAggregate = back as AggregateException;
+ }
+ return back;
+ }
+
+ /// <summary>
+ /// Gets a read-only collection of the <see cref="T:System.Exception"/> instances that caused the
+ /// current exception.
+ /// </summary>
+ public ReadOnlyCollection<Exception> InnerExceptions
+ {
+ get { return m_innerExceptions; }
+ }
+
+
+ /// <summary>
+ /// Invokes a handler on each <see cref="T:System.Exception"/> contained by this <see
+ /// cref="AggregateException"/>.
+ /// </summary>
+ /// <param name="predicate">The predicate to execute for each exception. The predicate accepts as an
+ /// argument the <see cref="T:System.Exception"/> to be processed and returns a Boolean to indicate
+ /// whether the exception was handled.</param>
+ /// <remarks>
+ /// Each invocation of the <paramref name="predicate"/> returns true or false to indicate whether the
+ /// <see cref="T:System.Exception"/> was handled. After all invocations, if any exceptions went
+ /// unhandled, all unhandled exceptions will be put into a new <see cref="AggregateException"/>
+ /// which will be thrown. Otherwise, the <see cref="Handle"/> method simply returns. If any
+ /// invocations of the <paramref name="predicate"/> throws an exception, it will halt the processing
+ /// of any more exceptions and immediately propagate the thrown exception as-is.
+ /// </remarks>
+ /// <exception cref="AggregateException">An exception contained by this <see
+ /// cref="AggregateException"/> was not handled.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="predicate"/> argument is
+ /// null.</exception>
+ public void Handle(Func<Exception, bool> predicate)
+ {
+ if (predicate == null)
+ {
+ throw new ArgumentNullException("predicate");
+ }
+
+ List<Exception> unhandledExceptions = null;
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ // If the exception was not handled, lazily allocate a list of unhandled
+ // exceptions (to be rethrown later) and add it.
+ if (!predicate(m_innerExceptions[i]))
+ {
+ if (unhandledExceptions == null)
+ {
+ unhandledExceptions = new List<Exception>();
+ }
+
+ unhandledExceptions.Add(m_innerExceptions[i]);
+ }
+ }
+
+ // If there are unhandled exceptions remaining, throw them.
+ if (unhandledExceptions != null)
+ {
+ throw new AggregateException(Message, unhandledExceptions);
+ }
+ }
+
+
+ /// <summary>
+ /// Flattens an <see cref="AggregateException"/> instances into a single, new instance.
+ /// </summary>
+ /// <returns>A new, flattened <see cref="AggregateException"/>.</returns>
+ /// <remarks>
+ /// If any inner exceptions are themselves instances of
+ /// <see cref="AggregateException"/>, this method will recursively flatten all of them. The
+ /// inner exceptions returned in the new <see cref="AggregateException"/>
+ /// will be the union of all of the the inner exceptions from exception tree rooted at the provided
+ /// <see cref="AggregateException"/> instance.
+ /// </remarks>
+ public AggregateException Flatten()
+ {
+ // Initialize a collection to contain the flattened exceptions.
+ List<Exception> flattenedExceptions = new List<Exception>();
+
+ // Create a list to remember all aggregates to be flattened, this will be accessed like a FIFO queue
+ List<AggregateException> exceptionsToFlatten = new List<AggregateException>();
+ exceptionsToFlatten.Add(this);
+ int nDequeueIndex = 0;
+
+ // Continue removing and recursively flattening exceptions, until there are no more.
+ while (exceptionsToFlatten.Count > nDequeueIndex)
+ {
+ // dequeue one from exceptionsToFlatten
+ IList<Exception> currentInnerExceptions = exceptionsToFlatten[nDequeueIndex++].InnerExceptions;
+
+ for (int i = 0; i < currentInnerExceptions.Count; i++)
+ {
+ Exception currentInnerException = currentInnerExceptions[i];
+
+ if (currentInnerException == null)
+ {
+ continue;
+ }
+
+ AggregateException currentInnerAsAggregate = currentInnerException as AggregateException;
+
+ // If this exception is an aggregate, keep it around for later. Otherwise,
+ // simply add it to the list of flattened exceptions to be returned.
+ if (currentInnerAsAggregate != null)
+ {
+ exceptionsToFlatten.Add(currentInnerAsAggregate);
+ }
+ else
+ {
+ flattenedExceptions.Add(currentInnerException);
+ }
+ }
+ }
+
+
+ return new AggregateException(Message, flattenedExceptions);
+ }
+
+ /// <summary>Gets a message that describes the exception.</summary>
+ public override string Message
+ {
+ get
+ {
+ if (m_innerExceptions.Count == 0)
+ {
+ return base.Message;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ sb.Append(base.Message);
+ sb.Append(' ');
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ sb.Append('(');
+ sb.Append(m_innerExceptions[i].Message);
+ sb.Append(") ");
+ }
+ sb.Length -= 1;
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ }
+
+ /// <summary>
+ /// Creates and returns a string representation of the current <see cref="AggregateException"/>.
+ /// </summary>
+ /// <returns>A string representation of the current exception.</returns>
+ public override string ToString()
+ {
+ string text = base.ToString();
+
+ for (int i = 0; i < m_innerExceptions.Count; i++)
+ {
+ text = String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("AggregateException_ToString"),
+ text, Environment.NewLine, i, m_innerExceptions[i].ToString(), "<---", Environment.NewLine);
+ }
+
+ return text;
+ }
+
+ /// <summary>
+ /// This helper property is used by the DebuggerDisplay.
+ ///
+ /// Note that we don't want to remove this property and change the debugger display to {InnerExceptions.Count}
+ /// because DebuggerDisplay should be a single property access or parameterless method call, so that the debugger
+ /// can use a fast path without using the expression evaluator.
+ ///
+ /// See http://msdn.microsoft.com/en-us/library/x810d419.aspx
+ /// </summary>
+ private int InnerExceptionCount
+ {
+ get
+ {
+ return InnerExceptions.Count;
+ }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContext.cs b/src/mscorlib/src/System/AppContext/AppContext.cs
new file mode 100644
index 0000000000..0b0643d7b4
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContext.cs
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Collections.Generic;
+
+namespace System
+{
+ public static class AppContext
+ {
+ [Flags]
+ private enum SwitchValueState
+ {
+ HasFalseValue = 0x1,
+ HasTrueValue = 0x2,
+ HasLookedForOverride = 0x4,
+ UnknownValue = 0x8 // Has no default and could not find an override
+ }
+ private static readonly Dictionary<string, SwitchValueState> s_switchMap = new Dictionary<string, SwitchValueState>();
+
+ public static string BaseDirectory
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ get
+ {
+ // The value of APP_CONTEXT_BASE_DIRECTORY key has to be a string and it is not allowed to be any other type.
+ // Otherwise the caller will get invalid cast exception
+ return (string) AppDomain.CurrentDomain.GetData("APP_CONTEXT_BASE_DIRECTORY") ?? AppDomain.CurrentDomain.BaseDirectory;
+ }
+ }
+
+ public static string TargetFrameworkName
+ {
+ get
+ {
+ // Forward the value that is set on the current domain.
+ return AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public static object GetData(string name)
+ {
+ return AppDomain.CurrentDomain.GetData(name);
+ }
+
+ #region Switch APIs
+ static AppContext()
+ {
+ // populate the AppContext with the default set of values
+ AppContextDefaultValues.PopulateDefaultValues();
+ }
+
+ /// <summary>
+ /// Try to get the value of the switch.
+ /// </summary>
+ /// <param name="switchName">The name of the switch</param>
+ /// <param name="isEnabled">A variable where to place the value of the switch</param>
+ /// <returns>A return value of true represents that the switch was set and <paramref name="isEnabled"/> contains the value of the switch</returns>
+ public static bool TryGetSwitch(string switchName, out bool isEnabled)
+ {
+ if (switchName == null)
+ throw new ArgumentNullException("switchName");
+ if (switchName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
+
+ // By default, the switch is not enabled.
+ isEnabled = false;
+
+ SwitchValueState switchValue;
+ lock (s_switchMap)
+ {
+ if (s_switchMap.TryGetValue(switchName, out switchValue))
+ {
+ // The value is in the dictionary.
+ // There are 3 cases here:
+ // 1. The value of the switch is 'unknown'. This means that the switch name is not known to the system (either via defaults or checking overrides).
+ // Example: This is the case when, during a servicing event, a switch is added to System.Xml which ships before mscorlib. The value of the switch
+ // Will be unknown to mscorlib.dll and we want to prevent checking the overrides every time we check this switch
+ // 2. The switch has a valid value AND we have read the overrides for it
+ // Example: TryGetSwitch is called for a switch set via SetSwitch
+ // 3. The switch has the default value and we need to check for overrides
+ // Example: TryGetSwitch is called for the first time for a switch that has a default value
+
+ // 1. The value is unknown
+ if (switchValue == SwitchValueState.UnknownValue)
+ {
+ isEnabled = false;
+ return false;
+ }
+
+ // We get the value of isEnabled from the value that we stored in the dictionary
+ isEnabled = (switchValue & SwitchValueState.HasTrueValue) == SwitchValueState.HasTrueValue;
+
+ // 2. The switch has a valid value AND we have checked for overrides
+ if ((switchValue & SwitchValueState.HasLookedForOverride) == SwitchValueState.HasLookedForOverride)
+ {
+ return true;
+ }
+
+ // 3. The switch has a valid value, but we need to check for overrides.
+ // Regardless of whether or not the switch has an override, we need to update the value to reflect
+ // the fact that we checked for overrides.
+ bool overrideValue;
+ if (AppContextDefaultValues.TryGetSwitchOverride(switchName, out overrideValue))
+ {
+ // we found an override!
+ isEnabled = overrideValue;
+ }
+
+ // Update the switch in the dictionary to mark it as 'checked for override'
+ s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
+ | SwitchValueState.HasLookedForOverride;
+
+ return true;
+ }
+ else
+ {
+ // The value is NOT in the dictionary
+ // In this case we need to see if we have an override defined for the value.
+ // There are 2 cases:
+ // 1. The value has an override specified. In this case we need to add the value to the dictionary
+ // and mark it as checked for overrides
+ // Example: In a servicing event, System.Xml introduces a switch and an override is specified.
+ // The value is not found in mscorlib (as System.Xml ships independent of mscorlib)
+ // 2. The value does not have an override specified
+ // In this case, we want to capture the fact that we looked for a value and found nothing by adding
+ // an entry in the dictionary with the 'sentinel' value of 'SwitchValueState.UnknownValue'.
+ // Example: This will prevent us from trying to find overrides for values that we don't have in the dictionary
+
+ // 1. The value has an override specified.
+ bool overrideValue;
+ if (AppContextDefaultValues.TryGetSwitchOverride(switchName, out overrideValue))
+ {
+ isEnabled = overrideValue;
+
+ // Update the switch in the dictionary to mark it as 'checked for override'
+ s_switchMap[switchName] = (isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue)
+ | SwitchValueState.HasLookedForOverride;
+
+ return true;
+ }
+
+ // 2. The value does not have an override.
+ s_switchMap[switchName] = SwitchValueState.UnknownValue;
+ }
+ }
+ return false; // we did not find a value for the switch
+ }
+
+ /// <summary>
+ /// Assign a switch a value
+ /// </summary>
+ /// <param name="switchName">The name of the switch</param>
+ /// <param name="isEnabled">The value to assign</param>
+ public static void SetSwitch(string switchName, bool isEnabled)
+ {
+ if (switchName == null)
+ throw new ArgumentNullException("switchName");
+ if (switchName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "switchName");
+
+ 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] = switchValue;
+ }
+ }
+
+ /// <summary>
+ /// This method is going to be called from the AppContextDefaultValues class when setting up the
+ /// default values for the switches. !!!! This method is called during the static constructor so it does not
+ /// take a lock !!!! If you are planning to use this outside of that, please ensure proper locking.
+ /// </summary>
+ internal static void DefineSwitchDefault(string switchName, bool isEnabled)
+ {
+ s_switchMap[switchName] = isEnabled ? SwitchValueState.HasTrueValue : SwitchValueState.HasFalseValue;
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.CoreClrOverrides.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.CoreClrOverrides.cs
new file mode 100644
index 0000000000..89893c6bee
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.CoreClrOverrides.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ internal static partial class AppContextDefaultValues
+ {
+ static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue)
+ {
+ overrideFound = false;
+ overrideValue = false;
+
+ string value = AppContext.GetData(switchName) as string;
+ if (value != null)
+ {
+ overrideFound = bool.TryParse(value, out overrideValue);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.Central.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.Central.cs
new file mode 100644
index 0000000000..92c9917113
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.Central.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+// This file is used to provide an implementation for defining a default value
+// This should be compiled only in mscorlib where the AppContext class is available
+//
+
+namespace System
+{
+ internal static partial class AppContextDefaultValues
+ {
+ /// <summary>
+ /// This method allows reading the override for a switch.
+ /// The implementation is platform specific
+ /// </summary>
+ public static bool TryGetSwitchOverride(string switchName, out bool overrideValue)
+ {
+ // The default value for a switch is 'false'
+ overrideValue = false;
+
+ // Read the override value
+ bool overrideFound = false;
+
+ // This partial method will be removed if there are no implementations of it.
+ TryGetSwitchOverridePartial(switchName, ref overrideFound, ref overrideValue);
+
+ return overrideFound;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs
new file mode 100644
index 0000000000..c80913e3a6
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.Defaults.cs
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System
+{
+ internal static partial class AppContextDefaultValues
+ {
+
+ 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";
+#if FEATURE_PATHCOMPAT
+ internal static readonly string SwitchUseLegacyPathHandling = "Switch.System.IO.UseLegacyPathHandling";
+ internal static readonly string SwitchBlockLongPaths = "Switch.System.IO.BlockLongPaths";
+#endif
+
+ // 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
+ // We are going to have an implementation of this method for the Desktop platform that will read the overrides from app.config, registry and
+ // the shim database. Additional implementation can be provided for other platforms.
+ static partial void PopulateOverrideValuesPartial();
+
+ static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version)
+ {
+ // When defining a new switch you should add it to the last known version.
+ // For instance, if you are adding a switch in .NET 4.6 (the release after 4.5.2) you should defined your switch
+ // like this:
+ // if (version <= 40502) ...
+ // This ensures that all previous versions of that platform (up-to 4.5.2) will get the old behavior by default
+ // NOTE: When adding a default value for a switch please make sure that the default value is added to ALL of the existing platforms!
+ // NOTE: When adding a new if statement for the version please ensure that ALL previous switches are enabled (ie. don't use else if)
+ switch (platformIdentifier)
+ {
+ case ".NETCore":
+ case ".NETFramework":
+ {
+ if (version <= 40502)
+ {
+ AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
+ AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
+ }
+#if FEATURE_PATHCOMPAT
+ if (version <= 40601)
+ {
+ AppContext.DefineSwitchDefault(SwitchUseLegacyPathHandling, true);
+ AppContext.DefineSwitchDefault(SwitchBlockLongPaths, true);
+ }
+#endif
+ break;
+ }
+ case "WindowsPhone":
+ case "WindowsPhoneApp":
+ {
+ if (version <= 80100)
+ {
+ AppContext.DefineSwitchDefault(SwitchNoAsyncCurrentCulture, true);
+ AppContext.DefineSwitchDefault(SwitchThrowExceptionIfDisposedCancellationTokenSource, true);
+ }
+ break;
+ }
+ }
+
+ // At this point we should read the overrides if any are defined
+ PopulateOverrideValuesPartial();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs
new file mode 100644
index 0000000000..7ab7ffbc04
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContextDefaultValues.cs
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+namespace System
+{
+ internal static partial class AppContextDefaultValues
+ {
+ public static void PopulateDefaultValues()
+ {
+ string platformIdentifier, profile;
+ int version;
+
+ ParseTargetFrameworkName(out platformIdentifier, out profile, out version);
+
+ // Call into each library to populate their default switches
+ PopulateDefaultValuesPartial(platformIdentifier, profile, version);
+ }
+
+ /// <summary>
+ /// We have this separate method for getting the parsed elements out of the TargetFrameworkName so we can
+ /// more easily support this on other platforms.
+ /// </summary>
+ private static void ParseTargetFrameworkName(out string identifier, out string profile, out int version)
+ {
+ string targetFrameworkMoniker = AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName;
+
+ if (!TryParseFrameworkName(targetFrameworkMoniker, out identifier, out version, out profile))
+ {
+#if FEATURE_CORECLR
+ // If we can't parse the TFM or we don't have a TFM, default to latest behavior for all
+ // switches (ie. all of them false).
+ // If we want to use the latest behavior it is enough to set the value of the switch to string.Empty.
+ // When the get to the caller of this method (PopulateDefaultValuesPartial) we are going to use the
+ // identifier we just set to decide which switches to turn on. By having an empty string as the
+ // identifier we are simply saying -- don't turn on any switches, and we are going to get the latest
+ // behavior for all the switches
+ identifier = string.Empty;
+#else
+ identifier = ".NETFramework";
+ version = 40000;
+ profile = string.Empty;
+#endif
+ }
+ }
+
+ // This code was a constructor copied from the FrameworkName class, which is located in System.dll.
+ // Parses strings in the following format: "<identifier>, Version=[v|V]<version>, Profile=<profile>"
+ // - The identifier and version is required, profile is optional
+ // - Only three components are allowed.
+ // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
+ private static bool TryParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
+ {
+ // For parsing a target Framework moniker, from the FrameworkName class
+ const char c_componentSeparator = ',';
+ const char c_keyValueSeparator = '=';
+ const char c_versionValuePrefix = 'v';
+ const String c_versionKey = "Version";
+ const String c_profileKey = "Profile";
+
+ identifier = profile = string.Empty;
+ version = 0;
+
+ if (frameworkName == null || frameworkName.Length == 0)
+ {
+ return false;
+ }
+
+ String[] components = frameworkName.Split(c_componentSeparator);
+ version = 0;
+
+ // Identifer and Version are required, Profile is optional.
+ if (components.Length < 2 || components.Length > 3)
+ {
+ return false;
+ }
+
+ //
+ // 1) Parse the "Identifier", which must come first. Trim any whitespace
+ //
+ identifier = components[0].Trim();
+
+ if (identifier.Length == 0)
+ {
+ return false;
+ }
+
+ bool versionFound = false;
+ profile = null;
+
+ //
+ // The required "Version" and optional "Profile" component can be in any order
+ //
+ for (int i = 1; i < components.Length; i++)
+ {
+ // Get the key/value pair separated by '='
+ string[] keyValuePair = components[i].Split(c_keyValueSeparator);
+
+ if (keyValuePair.Length != 2)
+ {
+ return false;
+ }
+
+ // Get the key and value, trimming any whitespace
+ string key = keyValuePair[0].Trim();
+ string value = keyValuePair[1].Trim();
+
+ //
+ // 2) Parse the required "Version" key value
+ //
+ if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase))
+ {
+ versionFound = true;
+
+ // Allow the version to include a 'v' or 'V' prefix...
+ if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
+ {
+ value = value.Substring(1);
+ }
+ Version realVersion = new Version(value);
+ // The version class will represent some unset values as -1 internally (instead of 0).
+ version = realVersion.Major * 10000;
+ if (realVersion.Minor > 0)
+ version += realVersion.Minor * 100;
+ if (realVersion.Build > 0)
+ version += realVersion.Build;
+ }
+ //
+ // 3) Parse the optional "Profile" key value
+ //
+ else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!String.IsNullOrEmpty(value))
+ {
+ profile = value;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if (!versionFound)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ // This is a partial method. Platforms (such as Desktop) can provide an implementation of it that will read override value
+ // 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
+ static partial void TryGetSwitchOverridePartial(string switchName, ref bool overrideFound, ref bool overrideValue);
+
+ /// This is a partial method. This method is responsible for populating the default values based on a TFM.
+ /// It is partial because each library should define this method in their code to contain their defaults.
+ static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version);
+ }
+}
diff --git a/src/mscorlib/src/System/AppContext/AppContextSwitches.cs b/src/mscorlib/src/System/AppContext/AppContextSwitches.cs
new file mode 100644
index 0000000000..3a96ec2159
--- /dev/null
+++ b/src/mscorlib/src/System/AppContext/AppContextSwitches.cs
@@ -0,0 +1,110 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ using System;
+ using System.Runtime.CompilerServices;
+
+ internal static class AppContextSwitches
+ {
+ private static int _noAsyncCurrentCulture;
+ public static bool NoAsyncCurrentCulture
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return GetCachedSwitchValue(AppContextDefaultValues.SwitchNoAsyncCurrentCulture, ref _noAsyncCurrentCulture);
+ }
+ }
+
+ private static int _throwExceptionIfDisposedCancellationTokenSource;
+ public static bool ThrowExceptionIfDisposedCancellationTokenSource
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return GetCachedSwitchValue(AppContextDefaultValues.SwitchThrowExceptionIfDisposedCancellationTokenSource, ref _throwExceptionIfDisposedCancellationTokenSource);
+ }
+ }
+
+ private static int _preserveEventListnerObjectIdentity;
+ public static bool PreserveEventListnerObjectIdentity
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return GetCachedSwitchValue(AppContextDefaultValues.SwitchPreserveEventListnerObjectIdentity, ref _preserveEventListnerObjectIdentity);
+ }
+ }
+
+#if FEATURE_PATHCOMPAT
+ 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);
+ }
+ }
+#endif // FEATURE_PATHCOMPAT
+
+ //
+ // Implementation details
+ //
+
+ private static bool DisableCaching { get; set; }
+
+ static AppContextSwitches()
+ {
+ bool isEnabled;
+ if (AppContext.TryGetSwitch(@"TestSwitch.LocalAppContext.DisableCaching", out isEnabled))
+ {
+ DisableCaching = isEnabled;
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool GetCachedSwitchValue(string switchName, ref int switchValue)
+ {
+ if (switchValue < 0) return false;
+ if (switchValue > 0) return true;
+
+ return GetCachedSwitchValueInternal(switchName, ref switchValue);
+ }
+
+ private static bool GetCachedSwitchValueInternal(string switchName, ref int switchValue)
+ {
+ bool isSwitchEnabled;
+ AppContext.TryGetSwitch(switchName, out isSwitchEnabled);
+
+ if (DisableCaching)
+ {
+ return isSwitchEnabled;
+ }
+
+ switchValue = isSwitchEnabled ? 1 /*true*/ : -1 /*false*/;
+ return isSwitchEnabled;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/AppDomain.cs b/src/mscorlib/src/System/AppDomain.cs
new file mode 100644
index 0000000000..abaaf48770
--- /dev/null
+++ b/src/mscorlib/src/System/AppDomain.cs
@@ -0,0 +1,4681 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Domains represent an application within the runtime. Objects can
+** not be shared between domains and each domain can be configured
+** independently.
+**
+**
+=============================================================================*/
+
+namespace System {
+ using System;
+#if FEATURE_CLICKONCE
+ using System.Deployment.Internal.Isolation;
+ using System.Deployment.Internal.Isolation.Manifest;
+ using System.Runtime.Hosting;
+#endif
+ using System.Reflection;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Channels;
+ using System.Runtime.Remoting.Contexts;
+#endif
+ using System.Security;
+ using System.Security.Permissions;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Security.Policy;
+ using System.Security.Util;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+ using Context = System.Runtime.Remoting.Contexts.Context;
+#endif
+ using System.Reflection.Emit;
+ using CultureInfo = System.Globalization.CultureInfo;
+#if !FEATURE_CORECLR
+ using System.Globalization;
+#endif
+ using System.IO;
+ using AssemblyHashAlgorithm = System.Configuration.Assemblies.AssemblyHashAlgorithm;
+ using System.Text;
+ using Microsoft.Win32;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+#if FEATURE_EXCEPTION_NOTIFICATIONS
+ using System.Runtime.ExceptionServices;
+#endif // FEATURE_EXCEPTION_NOTIFICATIONS
+
+ [ComVisible(true)]
+ public class ResolveEventArgs : EventArgs
+ {
+ private String _Name;
+ private Assembly _RequestingAssembly;
+
+ public String Name {
+ get {
+ return _Name;
+ }
+ }
+
+ public Assembly RequestingAssembly
+ {
+ get
+ {
+ return _RequestingAssembly;
+ }
+ }
+
+ public ResolveEventArgs(String name)
+ {
+ _Name = name;
+ }
+
+ public ResolveEventArgs(String name, Assembly requestingAssembly)
+ {
+ _Name = name;
+ _RequestingAssembly = requestingAssembly;
+ }
+ }
+
+ [ComVisible(true)]
+ public class AssemblyLoadEventArgs : EventArgs
+ {
+ private Assembly _LoadedAssembly;
+
+ public Assembly LoadedAssembly {
+ get {
+ return _LoadedAssembly;
+ }
+ }
+
+ public AssemblyLoadEventArgs(Assembly loadedAssembly)
+ {
+ _LoadedAssembly = loadedAssembly;
+ }
+ }
+
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ [Serializable]
+ [ComVisible(true)]
+ public delegate Assembly ResolveEventHandler(Object sender, ResolveEventArgs args);
+
+ [Serializable]
+ [ComVisible(true)]
+ public delegate void AssemblyLoadEventHandler(Object sender, AssemblyLoadEventArgs args);
+
+ [Serializable]
+ [ComVisible(true)]
+ public delegate void AppDomainInitializer(string[] args);
+
+ internal class AppDomainInitializerInfo
+ {
+ internal class ItemInfo
+ {
+ public string TargetTypeAssembly;
+ public string TargetTypeName;
+ public string MethodName;
+ }
+
+ internal ItemInfo[] Info;
+
+ internal AppDomainInitializerInfo(AppDomainInitializer init)
+ {
+ Info=null;
+ if (init==null)
+ return;
+ List<ItemInfo> itemInfo = new List<ItemInfo>();
+ List<AppDomainInitializer> nestedDelegates = new List<AppDomainInitializer>();
+ nestedDelegates.Add(init);
+ int idx=0;
+
+ while (nestedDelegates.Count>idx)
+ {
+ AppDomainInitializer curr = nestedDelegates[idx++];
+ Delegate[] list= curr.GetInvocationList();
+ for (int i=0;i<list.Length;i++)
+ {
+ if (!list[i].Method.IsStatic)
+ {
+ if(list[i].Target==null)
+ continue;
+
+ AppDomainInitializer nested = list[i].Target as AppDomainInitializer;
+ if (nested!=null)
+ nestedDelegates.Add(nested);
+ else
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeStatic"),
+ list[i].Method.ReflectedType.FullName+"::"+list[i].Method.Name);
+ }
+ else
+ {
+ ItemInfo info=new ItemInfo();
+ info.TargetTypeAssembly=list[i].Method.ReflectedType.Module.Assembly.FullName;
+ info.TargetTypeName=list[i].Method.ReflectedType.FullName;
+ info.MethodName=list[i].Method.Name;
+ itemInfo.Add(info);
+ }
+
+ }
+ }
+
+ Info = itemInfo.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal AppDomainInitializer Unwrap()
+ {
+ if (Info==null)
+ return null;
+ AppDomainInitializer retVal=null;
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
+ for (int i=0;i<Info.Length;i++)
+ {
+ Assembly assembly=Assembly.Load(Info[i].TargetTypeAssembly);
+ AppDomainInitializer newVal=(AppDomainInitializer)Delegate.CreateDelegate(typeof(AppDomainInitializer),
+ assembly.GetType(Info[i].TargetTypeName),
+ Info[i].MethodName);
+ if(retVal==null)
+ retVal=newVal;
+ else
+ retVal+=newVal;
+ }
+ return retVal;
+ }
+ }
+
+
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(System._AppDomain))]
+ [ComVisible(true)]
+ public sealed class AppDomain :
+#if FEATURE_REMOTING
+ MarshalByRefObject,
+#endif
+ _AppDomain, IEvidenceFactory
+ {
+ // Domain security information
+ // These fields initialized from the other side only. (NOTE: order
+ // of these fields cannot be changed without changing the layout in
+ // the EE)
+
+ [System.Security.SecurityCritical] // auto-generated
+ private AppDomainManager _domainManager;
+ private Dictionary<String, Object[]> _LocalStore;
+ private AppDomainSetup _FusionStore;
+ private Evidence _SecurityIdentity;
+#pragma warning disable 169
+ private Object[] _Policies; // Called from the VM.
+#pragma warning restore 169
+ [method: System.Security.SecurityCritical]
+ public event AssemblyLoadEventHandler AssemblyLoad;
+
+ [System.Security.SecurityCritical]
+ private ResolveEventHandler _TypeResolve;
+
+ public event ResolveEventHandler TypeResolve
+ {
+ [System.Security.SecurityCritical]
+ add
+ {
+ lock (this)
+ {
+ _TypeResolve += value;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ remove
+ {
+ lock (this)
+ {
+ _TypeResolve -= value;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private ResolveEventHandler _ResourceResolve;
+
+ public event ResolveEventHandler ResourceResolve
+ {
+ [System.Security.SecurityCritical]
+ add
+ {
+ lock (this)
+ {
+ _ResourceResolve += value;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ remove
+ {
+ lock (this)
+ {
+ _ResourceResolve -= value;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private ResolveEventHandler _AssemblyResolve;
+
+ public event ResolveEventHandler AssemblyResolve
+ {
+ [System.Security.SecurityCritical]
+ add
+ {
+ lock (this)
+ {
+ _AssemblyResolve += value;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ remove
+ {
+ lock (this)
+ {
+ _AssemblyResolve -= value;
+ }
+ }
+ }
+
+#if FEATURE_REFLECTION_ONLY_LOAD
+ [method: System.Security.SecurityCritical]
+ public event ResolveEventHandler ReflectionOnlyAssemblyResolve;
+#endif // FEATURE_REFLECTION_ONLY
+
+#if FEATURE_REMOTING
+ private Context _DefaultContext;
+#endif
+
+#if FEATURE_CLICKONCE
+ private ActivationContext _activationContext;
+ private ApplicationIdentity _applicationIdentity;
+#endif
+ private ApplicationTrust _applicationTrust;
+
+#if FEATURE_IMPERSONATION
+ private IPrincipal _DefaultPrincipal;
+#endif // FEATURE_IMPERSONATION
+#if FEATURE_REMOTING
+ private DomainSpecificRemotingData _RemotingData;
+#endif
+ private EventHandler _processExit;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+ #endif
+ private EventHandler _domainUnload;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ private UnhandledExceptionEventHandler _unhandledException;
+
+#if FEATURE_APTCA
+ private String[] _aptcaVisibleAssemblies;
+#endif
+
+ // The compat flags are set at domain creation time to indicate that the given breaking
+ // changes (named in the strings) should not be used in this domain. We only use the
+ // keys, the vhe values are ignored.
+ private Dictionary<String, object> _compatFlags;
+
+#if FEATURE_EXCEPTION_NOTIFICATIONS
+ // Delegate that will hold references to FirstChance exception notifications
+ private EventHandler<FirstChanceExceptionEventArgs> _firstChanceException;
+#endif // FEATURE_EXCEPTION_NOTIFICATIONS
+
+ private IntPtr _pDomain; // this is an unmanaged pointer (AppDomain * m_pDomain)` used from the VM.
+
+#if FEATURE_CAS_POLICY
+ private PrincipalPolicy _PrincipalPolicy; // this is an enum
+#endif
+ private bool _HasSetPolicy;
+ private bool _IsFastFullTrustDomain; // quick check to see if the AppDomain is fully trusted and homogenous
+ private bool _compatFlagsInitialized;
+
+ internal const String TargetFrameworkNameAppCompatSetting = "TargetFrameworkName";
+
+#if FEATURE_APPX
+ private static APPX_FLAGS s_flags;
+
+ //
+ // Keep in async with vm\appdomainnative.cpp
+ //
+ [Flags]
+ private enum APPX_FLAGS
+ {
+ APPX_FLAGS_INITIALIZED = 0x01,
+
+ APPX_FLAGS_APPX_MODEL = 0x02,
+ APPX_FLAGS_APPX_DESIGN_MODE = 0x04,
+ APPX_FLAGS_APPX_NGEN = 0x08,
+ APPX_FLAGS_APPX_MASK = APPX_FLAGS_APPX_MODEL |
+ APPX_FLAGS_APPX_DESIGN_MODE |
+ APPX_FLAGS_APPX_NGEN,
+
+ APPX_FLAGS_API_CHECK = 0x10,
+ }
+
+ private static APPX_FLAGS Flags
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if (s_flags == 0)
+ s_flags = nGetAppXFlags();
+
+ Contract.Assert(s_flags != 0);
+ return s_flags;
+ }
+ }
+
+ internal static bool ProfileAPICheck
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ return (Flags & APPX_FLAGS.APPX_FLAGS_API_CHECK) != 0;
+ }
+ }
+
+ internal static bool IsAppXNGen
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ return (Flags & APPX_FLAGS.APPX_FLAGS_APPX_NGEN) != 0;
+ }
+ }
+#endif // FEATURE_APPX
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool DisableFusionUpdatesFromADManager(AppDomainHandle domain);
+
+#if FEATURE_APPX
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.I4)]
+ private static extern APPX_FLAGS nGetAppXFlags();
+#endif
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetAppDomainManagerType(AppDomainHandle domain,
+ StringHandleOnStack retAssembly,
+ StringHandleOnStack retType);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void SetAppDomainManagerType(AppDomainHandle domain,
+ string assembly,
+ string type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nSetHostSecurityManagerFlags (HostSecurityManagerOptions flags);
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void SetSecurityHomogeneousFlag(AppDomainHandle domain,
+ [MarshalAs(UnmanagedType.Bool)] bool runtimeSuppliedHomogenousGrantSet);
+
+#if FEATURE_CAS_POLICY
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void SetLegacyCasPolicyEnabled(AppDomainHandle domain);
+
+ [SecurityCritical]
+ private void SetLegacyCasPolicyEnabled()
+ {
+ SetLegacyCasPolicyEnabled(GetNativeHandle());
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <summary>
+ /// Get a handle used to make a call into the VM pointing to this domain
+ /// </summary>
+ internal AppDomainHandle GetNativeHandle()
+ {
+ // This should never happen under normal circumstances. However, there ar ways to create an
+ // uninitialized object through remoting, etc.
+ if (_pDomain.IsNull())
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Argument_InvalidHandle"));
+ }
+
+#if FEATURE_REMOTING
+ BCLDebug.Assert(!RemotingServices.IsTransparentProxy(this), "QCalls should be made with the real AppDomain object rather than a transparent proxy");
+#endif // FEATURE_REMOTING
+ return new AppDomainHandle(_pDomain);
+ }
+
+ /// <summary>
+ /// If this AppDomain is configured to have an AppDomain manager then create the instance of it.
+ /// This method is also called from the VM to create the domain manager in the default domain.
+ /// </summary>
+ [SecuritySafeCritical]
+ private void CreateAppDomainManager()
+ {
+ Contract.Assert(_domainManager == null, "_domainManager == null");
+
+ AppDomainSetup adSetup = FusionStore;
+#if FEATURE_VERSIONING
+ String trustedPlatformAssemblies = (String)(GetData("TRUSTED_PLATFORM_ASSEMBLIES"));
+ if (trustedPlatformAssemblies != null)
+ {
+ String platformResourceRoots = (String)(GetData("PLATFORM_RESOURCE_ROOTS"));
+ if (platformResourceRoots == null)
+ {
+ platformResourceRoots = String.Empty;
+ }
+
+ String appPaths = (String)(GetData("APP_PATHS"));
+ if (appPaths == null)
+ {
+ appPaths = String.Empty;
+ }
+
+ String appNiPaths = (String)(GetData("APP_NI_PATHS"));
+ if (appNiPaths == null)
+ {
+ appNiPaths = String.Empty;
+ }
+
+ String appLocalWinMD = (String)(GetData("APP_LOCAL_WINMETADATA"));
+ if (appLocalWinMD == null)
+ {
+ appLocalWinMD = String.Empty;
+ }
+ SetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPaths, appNiPaths, appLocalWinMD);
+ }
+#endif // FEATURE_VERSIONING
+
+ string domainManagerAssembly;
+ string domainManagerType;
+ GetAppDomainManagerType(out domainManagerAssembly, out domainManagerType);
+
+ if (domainManagerAssembly != null && domainManagerType != null)
+ {
+ try
+ {
+ new PermissionSet(PermissionState.Unrestricted).Assert();
+ _domainManager = CreateInstanceAndUnwrap(domainManagerAssembly, domainManagerType) as AppDomainManager;
+ CodeAccessPermission.RevertAssert();
+ }
+ catch (FileNotFoundException e)
+ {
+ throw new TypeLoadException(Environment.GetResourceString("Argument_NoDomainManager"), e);
+ }
+ catch (SecurityException e)
+ {
+ throw new TypeLoadException(Environment.GetResourceString("Argument_NoDomainManager"), e);
+ }
+ catch (TypeLoadException e)
+ {
+ throw new TypeLoadException(Environment.GetResourceString("Argument_NoDomainManager"), e);
+ }
+
+ if (_domainManager == null)
+ {
+ throw new TypeLoadException(Environment.GetResourceString("Argument_NoDomainManager"));
+ }
+
+ // If this domain was not created by a managed call to CreateDomain, then the AppDomainSetup
+ // will not have the correct values for the AppDomainManager set.
+ FusionStore.AppDomainManagerAssembly = domainManagerAssembly;
+ FusionStore.AppDomainManagerType = domainManagerType;
+
+ bool notifyFusion = _domainManager.GetType() != typeof(System.AppDomainManager) && !DisableFusionUpdatesFromADManager();
+
+
+
+ AppDomainSetup FusionStoreOld = null;
+ if (notifyFusion)
+ FusionStoreOld = new AppDomainSetup(FusionStore, true);
+
+ // Initialize the AppDomainMAnager and register the instance with the native host if requested
+ _domainManager.InitializeNewDomain(FusionStore);
+
+ if (notifyFusion)
+ SetupFusionStore(_FusionStore, FusionStoreOld); // Notify Fusion about the changes the user implementation of InitializeNewDomain may have made to the FusionStore object.
+
+#if FEATURE_APPDOMAINMANAGER_INITOPTIONS
+ AppDomainManagerInitializationOptions flags = _domainManager.InitializationFlags;
+ if ((flags & AppDomainManagerInitializationOptions.RegisterWithHost) == AppDomainManagerInitializationOptions.RegisterWithHost)
+ {
+ _domainManager.RegisterWithHost();
+ }
+#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS
+ }
+
+ InitializeCompatibilityFlags();
+ }
+
+ /// <summary>
+ /// Initialize the compatibility flags to non-NULL values.
+ /// This method is also called from the VM when the default domain dosen't have a domain manager.
+ /// </summary>
+ private void InitializeCompatibilityFlags()
+ {
+ AppDomainSetup adSetup = FusionStore;
+
+ // set up shim flags regardless of whether we create a DomainManager in this method.
+ if (adSetup.GetCompatibilityFlags() != null)
+ {
+ _compatFlags = new Dictionary<String, object>(adSetup.GetCompatibilityFlags(), StringComparer.OrdinalIgnoreCase);
+ }
+
+ // for perf, we don't intialize the _compatFlags dictionary when we don't need to. However, we do need to make a
+ // note that we've run this method, because IsCompatibilityFlagsSet needs to return different values for the
+ // case where the compat flags have been setup.
+ Contract.Assert(!_compatFlagsInitialized);
+ _compatFlagsInitialized = true;
+
+ CompatibilitySwitches.InitializeSwitches();
+ }
+
+ // Retrieves a possibly-cached target framework name for this appdomain. This could be set
+ // either by a host in native, a host in managed using an AppDomainSetup, or by the
+ // TargetFrameworkAttribute on the executable (VS emits its target framework moniker using this
+ // attribute starting in version 4).
+ [SecuritySafeCritical]
+ internal String GetTargetFrameworkName()
+ {
+ String targetFrameworkName = _FusionStore.TargetFrameworkName;
+
+ if (targetFrameworkName == null && IsDefaultAppDomain() && !_FusionStore.CheckedForTargetFrameworkName)
+ {
+ // This should only be run in the default appdomain. All other appdomains should have
+ // values copied from the default appdomain and/or specified by the host.
+ Assembly assembly = Assembly.GetEntryAssembly();
+ if (assembly != null)
+ {
+ TargetFrameworkAttribute[] attrs = (TargetFrameworkAttribute[])assembly.GetCustomAttributes(typeof(TargetFrameworkAttribute));
+ if (attrs != null && attrs.Length > 0)
+ {
+ Contract.Assert(attrs.Length == 1);
+ targetFrameworkName = attrs[0].FrameworkName;
+ _FusionStore.TargetFrameworkName = targetFrameworkName;
+ }
+ }
+ _FusionStore.CheckedForTargetFrameworkName = true;
+ }
+
+ return targetFrameworkName;
+ }
+
+ /// <summary>
+ /// Returns the setting of the corresponding compatibility config switch (see CreateAppDomainManager for the impact).
+ /// </summary>
+ [SecuritySafeCritical]
+ internal bool DisableFusionUpdatesFromADManager()
+ {
+ return DisableFusionUpdatesFromADManager(GetNativeHandle());
+ }
+
+ /// <summary>
+ /// Returns whether the current AppDomain follows the AppX rules.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static bool IsAppXModel()
+ {
+#if FEATURE_APPX
+ return (Flags & APPX_FLAGS.APPX_FLAGS_APPX_MODEL) != 0;
+#else
+ return false;
+#endif
+ }
+
+ /// <summary>
+ /// Returns the setting of the AppXDevMode config switch.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static bool IsAppXDesignMode()
+ {
+#if FEATURE_APPX
+ return (Flags & APPX_FLAGS.APPX_FLAGS_APPX_MASK) == (APPX_FLAGS.APPX_FLAGS_APPX_MODEL | APPX_FLAGS.APPX_FLAGS_APPX_DESIGN_MODE);
+#else
+ return false;
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports Assembly.LoadFrom.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckLoadFromSupported()
+ {
+#if FEATURE_APPX
+ if (IsAppXModel())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.LoadFrom"));
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports Assembly.LoadFile.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckLoadFileSupported()
+ {
+#if FEATURE_APPX
+ if (IsAppXModel())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.LoadFile"));
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports Assembly.ReflectionOnlyLoad.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckReflectionOnlyLoadSupported()
+ {
+#if FEATURE_APPX
+ if (IsAppXModel())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.ReflectionOnlyLoad"));
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports Assembly.LoadWithPartialName.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckLoadWithPartialNameSupported(StackCrawlMark stackMark)
+ {
+#if FEATURE_APPX
+ if (IsAppXModel())
+ {
+ RuntimeAssembly callingAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ bool callerIsFxAssembly = callingAssembly != null && callingAssembly.IsFrameworkAssembly();
+ if (!callerIsFxAssembly)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.LoadWithPartialName"));
+ }
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports DefinePInvokeMethod.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckDefinePInvokeSupported()
+ {
+ // We don't want users to use DefinePInvokeMethod in RefEmit to bypass app store validation on allowed native libraries.
+#if FEATURE_APPX
+ if (IsAppXModel())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "DefinePInvokeMethod"));
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports Assembly.Load(byte[] ...).
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckLoadByteArraySupported()
+ {
+#if FEATURE_APPX
+ if (IsAppXModel())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "Assembly.Load(byte[], ...)"));
+#endif
+ }
+
+ /// <summary>
+ /// Checks (and throws on failure) if the domain supports AppDomain.CreateDomain.
+ /// </summary>
+ [SecuritySafeCritical]
+ [Pure]
+ internal static void CheckCreateDomainSupported()
+ {
+#if FEATURE_APPX
+ // Can create a new domain in an AppX process only when DevMode is enabled and
+ // AssemblyLoadingCompat is not enabled (since there is no multi-domain support
+ // for LoadFrom and LoadFile in AppX.
+ if(IsAppXModel())
+ {
+ if (!IsAppXDesignMode())
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AppX", "AppDomain.CreateDomain"));
+ }
+ }
+#endif
+ }
+
+ /// <summary>
+ /// Get the name of the assembly and type that act as the AppDomainManager for this domain
+ /// </summary>
+ [SecuritySafeCritical]
+ internal void GetAppDomainManagerType(out string assembly, out string type)
+ {
+ // We can't just use our parameters because we need to ensure that the strings used for hte QCall
+ // are on the stack.
+ string localAssembly = null;
+ string localType = null;
+
+ GetAppDomainManagerType(GetNativeHandle(),
+ JitHelpers.GetStringHandleOnStack(ref localAssembly),
+ JitHelpers.GetStringHandleOnStack(ref localType));
+
+ assembly = localAssembly;
+ type = localType;
+ }
+
+ /// <summary>
+ /// Set the assembly and type which act as the AppDomainManager for this domain
+ /// </summary>
+ [SecuritySafeCritical]
+ private void SetAppDomainManagerType(string assembly, string type)
+ {
+ Contract.Assert(assembly != null, "assembly != null");
+ Contract.Assert(type != null, "type != null");
+ SetAppDomainManagerType(GetNativeHandle(), assembly, type);
+ }
+
+#if FEATURE_APTCA
+ internal String[] PartialTrustVisibleAssemblies
+ {
+ get { return _aptcaVisibleAssemblies; }
+
+ [SecuritySafeCritical]
+ set
+ {
+ _aptcaVisibleAssemblies = value;
+
+ // Build up the canonical representaiton of this list to allow the VM to do optimizations in
+ // common cases
+ string canonicalConditionalAptcaList = null;
+ if (value != null)
+ {
+ StringBuilder conditionalAptcaListBuilder = StringBuilderCache.Acquire();
+ for (int i = 0; i < value.Length; ++i)
+ {
+ if (value[i] != null)
+ {
+ conditionalAptcaListBuilder.Append(value[i].ToUpperInvariant());
+ if (i != value.Length - 1)
+ {
+ conditionalAptcaListBuilder.Append(';');
+ }
+ }
+ }
+
+ canonicalConditionalAptcaList = StringBuilderCache.GetStringAndRelease(conditionalAptcaListBuilder);
+ }
+
+ SetCanonicalConditionalAptcaList(canonicalConditionalAptcaList);
+ }
+ }
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void SetCanonicalConditionalAptcaList(AppDomainHandle appDomain, string canonicalList);
+
+ [SecurityCritical]
+ private void SetCanonicalConditionalAptcaList(string canonicalList)
+ {
+ SetCanonicalConditionalAptcaList(GetNativeHandle(), canonicalList);
+ }
+#endif // FEATURE_APTCA
+
+#if FEATURE_CLICKONCE
+ /// <summary>
+ /// If the CLR is being started up to run a ClickOnce applicaiton, setup the default AppDomain
+ /// with information about that application.
+ /// </summary>
+ private void SetupDefaultClickOnceDomain(string fullName, string[] manifestPaths, string[] activationData)
+ {
+ Contract.Requires(fullName != null, "fullName != null");
+ FusionStore.ActivationArguments = new ActivationArguments(fullName, manifestPaths, activationData);
+ }
+#endif // FEATURE_CLICKONCE
+
+ /// <summary>
+ /// Called for every AppDomain (including the default domain) to initialize the security of the AppDomain)
+ /// </summary>
+ [SecurityCritical]
+ private void InitializeDomainSecurity(Evidence providedSecurityInfo,
+ Evidence creatorsSecurityInfo,
+ bool generateDefaultEvidence,
+ IntPtr parentSecurityDescriptor,
+ bool publishAppDomain)
+ {
+ AppDomainSetup adSetup = FusionStore;
+
+#if FEATURE_CAS_POLICY
+ // If the AppDomain is setup to use legacy CAS policy, then set that bit in the application
+ // security descriptor.
+ if (CompatibilitySwitches.IsNetFx40LegacySecurityPolicy)
+ {
+ SetLegacyCasPolicyEnabled();
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CLICKONCE
+
+ // Check if the domain manager set an ActivationContext (Debug-In-Zone for example)
+ // or if this is an AppDomain with an ApplicationTrust.
+ if (adSetup.ActivationArguments != null) {
+ // Merge the new evidence with the manifest's evidence if applicable
+ ActivationContext activationContext = null;
+ ApplicationIdentity appIdentity = null;
+ string[] activationData = null;
+ CmsUtils.CreateActivationContext(adSetup.ActivationArguments.ApplicationFullName,
+ adSetup.ActivationArguments.ApplicationManifestPaths,
+ adSetup.ActivationArguments.UseFusionActivationContext,
+ out appIdentity, out activationContext);
+ activationData = adSetup.ActivationArguments.ActivationData;
+ providedSecurityInfo = CmsUtils.MergeApplicationEvidence(providedSecurityInfo,
+ appIdentity,
+ activationContext,
+ activationData,
+ adSetup.ApplicationTrust);
+ SetupApplicationHelper(providedSecurityInfo, creatorsSecurityInfo, appIdentity, activationContext, activationData);
+ }
+ else
+#endif // FEATURE_CLICKONCE
+ {
+ bool runtimeSuppliedHomogenousGrant = false;
+ ApplicationTrust appTrust = adSetup.ApplicationTrust;
+
+#if FEATURE_CAS_POLICY
+ // In non-legacy CAS mode, domains should be homogenous. If the host has not specified a sandbox
+ // of their own, we'll set it up to be fully trusted. We must read the IsLegacyCasPolicy
+ // enabled property here rathern than just reading the switch from above because the entire
+ // process may also be opted into legacy CAS policy mode.
+ if (appTrust == null && !IsLegacyCasPolicyEnabled) {
+ _IsFastFullTrustDomain = true;
+ runtimeSuppliedHomogenousGrant = true;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ if (appTrust != null) {
+ SetupDomainSecurityForHomogeneousDomain(appTrust, runtimeSuppliedHomogenousGrant);
+ }
+ else if (_IsFastFullTrustDomain) {
+ SetSecurityHomogeneousFlag(GetNativeHandle(), runtimeSuppliedHomogenousGrant);
+ }
+ }
+
+ // Get the evidence supplied for the domain. If no evidence was supplied, it means that we want
+ // to use the default evidence creation strategy for this domain
+ Evidence newAppDomainEvidence = (providedSecurityInfo != null ? providedSecurityInfo : creatorsSecurityInfo);
+ if (newAppDomainEvidence == null && generateDefaultEvidence) {
+#if FEATURE_CAS_POLICY
+ newAppDomainEvidence = new Evidence(new AppDomainEvidenceFactory(this));
+#else // !FEATURE_CAS_POLICY
+ newAppDomainEvidence = new Evidence();
+#endif // FEATURE_CAS_POLICY
+ }
+
+#if FEATURE_CAS_POLICY
+ if (_domainManager != null) {
+ // Give the host a chance to alter the AppDomain evidence
+ HostSecurityManager securityManager = _domainManager.HostSecurityManager;
+ if (securityManager != null) {
+ nSetHostSecurityManagerFlags (securityManager.Flags);
+ if ((securityManager.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence) {
+ newAppDomainEvidence = securityManager.ProvideAppDomainEvidence(newAppDomainEvidence);
+ // If this is a disconnected evidence collection, then attach it to the AppDomain,
+ // allowing the host security manager to get callbacks for delay generated evidence
+ if (newAppDomainEvidence != null && newAppDomainEvidence.Target == null) {
+ newAppDomainEvidence.Target = new AppDomainEvidenceFactory(this);
+ }
+ }
+ }
+ }
+
+#endif // FEATURE_CAS_POLICY
+
+ // Set the evidence on the managed side
+ _SecurityIdentity = newAppDomainEvidence;
+
+ // Set the evidence of the AppDomain in the VM.
+ // Also, now that the initialization is complete, signal that to the security system.
+ // Finish the AppDomain initialization and resolve the policy for the AppDomain evidence.
+ SetupDomainSecurity(newAppDomainEvidence,
+ parentSecurityDescriptor,
+ publishAppDomain);
+
+#if FEATURE_CAS_POLICY
+ // The AppDomain is now resolved. Go ahead and set the PolicyLevel
+ // from the HostSecurityManager if specified.
+ if (_domainManager != null)
+ RunDomainManagerPostInitialization(_domainManager);
+#endif // FEATURE_CAS_POLICY
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ private void RunDomainManagerPostInitialization (AppDomainManager domainManager)
+ {
+ // force creation of the HostExecutionContextManager for the current AppDomain
+ HostExecutionContextManager contextManager = domainManager.HostExecutionContextManager;
+
+ if (IsLegacyCasPolicyEnabled)
+ {
+#pragma warning disable 618
+ HostSecurityManager securityManager = domainManager.HostSecurityManager;
+ if (securityManager != null)
+ {
+ if ((securityManager.Flags & HostSecurityManagerOptions.HostPolicyLevel) == HostSecurityManagerOptions.HostPolicyLevel)
+ {
+ // set AppDomain policy if specified
+ PolicyLevel level = securityManager.DomainPolicy;
+ if (level != null)
+ SetAppDomainPolicy(level);
+ }
+ }
+#pragma warning restore 618
+ }
+ }
+#endif
+
+
+#if FEATURE_CLICKONCE
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupApplicationHelper (Evidence providedSecurityInfo, Evidence creatorsSecurityInfo, ApplicationIdentity appIdentity, ActivationContext activationContext, string[] activationData) {
+ Contract.Requires(providedSecurityInfo != null);
+ HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager;
+ ApplicationTrust appTrust = securityManager.DetermineApplicationTrust(providedSecurityInfo, creatorsSecurityInfo, new TrustManagerContext());
+ if (appTrust == null || !appTrust.IsApplicationTrustedToRun)
+ throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"),
+ System.__HResults.CORSEC_E_NO_EXEC_PERM,
+ null);
+
+ // The application is trusted to run. Set up the AppDomain according to the manifests.
+ if (activationContext != null)
+ SetupDomainForApplication(activationContext, activationData);
+ SetupDomainSecurityForApplication(appIdentity, appTrust);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupDomainForApplication(ActivationContext activationContext, string[] activationData) {
+ Contract.Requires(activationContext != null);
+ if (IsDefaultAppDomain()) {
+ // make the ActivationArguments available off the AppDomain object.
+ AppDomainSetup adSetup = this.FusionStore;
+ adSetup.ActivationArguments = new ActivationArguments(activationContext, activationData);
+
+ // set the application base to point at where the application resides
+ string entryPointPath = CmsUtils.GetEntryPointFullPath(activationContext);
+ if (!String.IsNullOrEmpty(entryPointPath))
+ adSetup.SetupDefaults(entryPointPath);
+ else
+ adSetup.ApplicationBase = activationContext.ApplicationDirectory;
+
+ // update fusion context
+ SetupFusionStore(adSetup, null);
+ }
+
+ // perform app data directory migration.
+ activationContext.PrepareForExecution();
+ activationContext.SetApplicationState(ActivationContext.ApplicationState.Starting);
+ // set current app data directory.
+ activationContext.SetApplicationState(ActivationContext.ApplicationState.Running);
+
+ // make data directory path available.
+ IPermission permission = null;
+ string dataDirectory = activationContext.DataDirectory;
+ if (dataDirectory != null && dataDirectory.Length > 0)
+ permission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dataDirectory);
+ this.SetData("DataDirectory", dataDirectory, permission);
+
+ _activationContext = activationContext;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupDomainSecurityForApplication(ApplicationIdentity appIdentity,
+ ApplicationTrust appTrust)
+ {
+ // Set the Application trust on the managed side.
+ _applicationIdentity = appIdentity;
+ SetupDomainSecurityForHomogeneousDomain(appTrust, false);
+ }
+#endif // FEATURE_CLICKONCE
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupDomainSecurityForHomogeneousDomain(ApplicationTrust appTrust,
+ bool runtimeSuppliedHomogenousGrantSet)
+ {
+ // If the CLR has supplied the homogenous grant set (that is, this domain would have been
+ // heterogenous in v2.0), then we need to strip the ApplicationTrust from the AppDomainSetup of
+ // the current domain. This prevents code which does:
+ // AppDomain.CreateDomain(..., AppDomain.CurrentDomain.SetupInformation);
+ //
+ // From looking like it is trying to create a homogenous domain intentionally, and therefore
+ // having its evidence check bypassed.
+ if (runtimeSuppliedHomogenousGrantSet)
+ {
+ BCLDebug.Assert(_FusionStore.ApplicationTrust != null, "Expected to find runtime supplied ApplicationTrust");
+#if FEATURE_CAS_POLICY
+ _FusionStore.ApplicationTrust = null;
+#endif // FEATURE_CAS_POLICY
+ }
+
+ _applicationTrust = appTrust;
+
+ // Set the homogeneous bit in the VM's ApplicationSecurityDescriptor.
+ SetSecurityHomogeneousFlag(GetNativeHandle(),
+ runtimeSuppliedHomogenousGrantSet);
+ }
+
+ // This method is called from CorHost2::ExecuteApplication to activate a ClickOnce application in the default AppDomain.
+#if FEATURE_CLICKONCE
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private int ActivateApplication () {
+ ObjectHandle oh = Activator.CreateInstance(AppDomain.CurrentDomain.ActivationContext);
+ return (int) oh.Unwrap();
+ }
+#endif //FEATURE_CLICKONCE
+
+ public AppDomainManager DomainManager {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get {
+ return _domainManager;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ internal HostSecurityManager HostSecurityManager {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ HostSecurityManager securityManager = null;
+ AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
+ if (domainManager != null)
+ securityManager = domainManager.HostSecurityManager;
+
+ if (securityManager == null)
+ securityManager = new HostSecurityManager();
+ return securityManager;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_REFLECTION_ONLY_LOAD
+ private Assembly ResolveAssemblyForIntrospection(Object sender, ResolveEventArgs args)
+ {
+ Contract.Requires(args != null);
+ return Assembly.ReflectionOnlyLoad(ApplyPolicy(args.Name));
+ }
+
+ // Helper class for method code:EnableResolveAssembliesForIntrospection
+ private class NamespaceResolverForIntrospection
+ {
+ private IEnumerable<string> _packageGraphFilePaths;
+ public NamespaceResolverForIntrospection(IEnumerable<string> packageGraphFilePaths)
+ {
+ _packageGraphFilePaths = packageGraphFilePaths;
+ }
+
+ [System.Security.SecurityCritical]
+ public void ResolveNamespace(
+ object sender,
+ System.Runtime.InteropServices.WindowsRuntime.NamespaceResolveEventArgs args)
+ {
+ Contract.Requires(args != null);
+
+ IEnumerable<string> fileNames = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.ResolveNamespace(
+ args.NamespaceName,
+ null, // windowsSdkFilePath ... Use OS installed .winmd files
+ _packageGraphFilePaths);
+ foreach (string fileName in fileNames)
+ {
+ args.ResolvedAssemblies.Add(Assembly.ReflectionOnlyLoadFrom(fileName));
+ }
+ }
+ }
+
+ // Called only by native function code:ValidateWorker
+ [System.Security.SecuritySafeCritical]
+ private void EnableResolveAssembliesForIntrospection(string verifiedFileDirectory)
+ {
+ CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(ResolveAssemblyForIntrospection);
+
+ string[] packageGraphFilePaths = null;
+ if (verifiedFileDirectory != null)
+ packageGraphFilePaths = new string[] { verifiedFileDirectory };
+ NamespaceResolverForIntrospection namespaceResolver = new NamespaceResolverForIntrospection(packageGraphFilePaths);
+
+ System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.ReflectionOnlyNamespaceResolve +=
+ new EventHandler<System.Runtime.InteropServices.WindowsRuntime.NamespaceResolveEventArgs>(namespaceResolver.ResolveNamespace);
+ }
+#endif // FEATURE_REFLECTION_ONLY_LOAD
+
+
+ /**********************************************
+ * If an AssemblyName has a public key specified, the assembly is assumed
+ * to have a strong name and a hash will be computed when the assembly
+ * is saved.
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, null,
+ null, null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ null, null, null, null, null,
+ ref stackMark,
+ assemblyAttributes, SecurityContextSource.CurrentAssembly);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Due to the stack crawl mark
+ [SecuritySafeCritical]
+ public AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes,
+ SecurityContextSource securityContextSource)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ null, null, null, null, null,
+ ref stackMark,
+ assemblyAttributes,
+ securityContextSource);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, dir,
+ null, null, null, null,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ Evidence evidence)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, null,
+ evidence, null, null, null,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, null, null,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of DefineDynamicAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, dir, evidence,
+ null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, dir, null,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, null,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. Please see http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, dir,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ bool isSynchronized)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ dir,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ null,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ bool isSynchronized,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ dir,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ assemblyAttributes,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ bool isSynchronized,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ dir,
+ null,
+ null,
+ null,
+ null,
+ ref stackMark,
+ assemblyAttributes,
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private AssemblyBuilder InternalDefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ ref StackCrawlMark stackMark,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes,
+ SecurityContextSource securityContextSource)
+ {
+ return AssemblyBuilder.InternalDefineDynamicAssembly(name,
+ access,
+ dir,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ assemblyAttributes,
+ securityContextSource);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern String nApplyPolicy(AssemblyName an);
+
+ // Return the assembly name that results from applying policy.
+ [ComVisible(false)]
+ public String ApplyPolicy(String assemblyName)
+ {
+ AssemblyName asmName = new AssemblyName(assemblyName);
+
+ byte[] pk = asmName.GetPublicKeyToken();
+ if (pk == null)
+ pk = asmName.GetPublicKey();
+
+ // Simply-named assemblies cannot have policy, so for those,
+ // we simply return the passed-in assembly name.
+ if ((pk == null) || (pk.Length == 0))
+ return assemblyName;
+ else
+ return nApplyPolicy(asmName);
+ }
+
+
+ public ObjectHandle CreateInstance(String assemblyName,
+ String typeName)
+
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+
+ if (assemblyName == null)
+ throw new ArgumentNullException("assemblyName");
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstance(assemblyName,
+ typeName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName, string typeName) {
+ PermissionSet.s_fullTrust.Assert();
+ return CreateInstance(assemblyName, typeName);
+ }
+
+ public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName)
+
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstanceFrom(assemblyFile,
+ typeName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName, string typeName) {
+ PermissionSet.s_fullTrust.Assert();
+ return CreateInstanceFrom(assemblyName, typeName);
+ }
+
+#if FEATURE_COMINTEROP
+ // The first parameter should be named assemblyFile, but it was incorrectly named in a previous
+ // release, and the compatibility police won't let us change the name now.
+ public ObjectHandle CreateComInstanceFrom(String assemblyName,
+ String typeName)
+
+ {
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ return Activator.CreateComInstanceFrom(assemblyName,
+ typeName);
+ }
+
+ public ObjectHandle CreateComInstanceFrom(String assemblyFile,
+ String typeName,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+
+ {
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ return Activator.CreateComInstanceFrom(assemblyFile,
+ typeName,
+ hashValue,
+ hashAlgorithm);
+ }
+
+#endif // FEATURE_COMINTEROP
+
+ public ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ Object[] activationAttributes)
+
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+
+ if (assemblyName == null)
+ throw new ArgumentNullException("assemblyName");
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstance(assemblyName,
+ typeName,
+ activationAttributes);
+ }
+
+ public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ Object[] activationAttributes)
+
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstanceFrom(assemblyFile,
+ typeName,
+ activationAttributes);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstance which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+
+ if (assemblyName == null)
+ throw new ArgumentNullException("assemblyName");
+ Contract.EndContractBlock();
+
+#if FEATURE_CAS_POLICY
+ if (securityAttributes != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+#pragma warning disable 618
+ return Activator.CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ securityAttributes);
+#pragma warning restore 618
+ }
+
+ public ObjectHandle CreateInstance(string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+
+ if (assemblyName == null)
+ throw new ArgumentNullException("assemblyName");
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ObjectHandle InternalCreateInstanceWithNoSecurity (string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+ {
+#if FEATURE_CAS_POLICY
+ Contract.Assert(IsLegacyCasPolicyEnabled || securityAttributes == null);
+#endif // FEATURE_CAS_POLICY
+
+ PermissionSet.s_fullTrust.Assert();
+#pragma warning disable 618
+ return CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes);
+#pragma warning restore 618
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+#if FEATURE_CAS_POLICY
+ if (securityAttributes != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ return Activator.CreateInstanceFrom(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes,
+ securityAttributes);
+ }
+
+ public ObjectHandle CreateInstanceFrom(string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ // jit does not check for that, so we should do it ...
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ return Activator.CreateInstanceFrom(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ObjectHandle InternalCreateInstanceFromWithNoSecurity (string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+ {
+#if FEATURE_CAS_POLICY
+ Contract.Assert(IsLegacyCasPolicyEnabled || securityAttributes == null);
+#endif // FEATURE_CAS_POLICY
+
+ PermissionSet.s_fullTrust.Assert();
+#pragma warning disable 618
+ return CreateInstanceFrom(assemblyName, typeName, ignoreCase, bindingAttr, binder, args, culture, activationAttributes, securityAttributes);
+#pragma warning restore 618
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Assembly Load(AssemblyName assemblyRef)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Assembly Load(String assemblyString)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Assembly Load(byte[] rawAssembly)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(rawAssembly,
+ null, // symbol store
+ null, // evidence
+ ref stackMark,
+ false,
+ SecurityContextSource.CurrentAssembly);
+
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(rawAssembly,
+ rawSymbolStore,
+ null, // evidence
+ ref stackMark,
+ false, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)]
+#pragma warning restore 618
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkId=155570 for more information.")]
+ public Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore,
+ Evidence securityEvidence)
+ {
+#if FEATURE_CAS_POLICY
+ if (securityEvidence != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(rawAssembly,
+ rawSymbolStore,
+ securityEvidence,
+ ref stackMark,
+ false, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public Assembly Load(AssemblyName assemblyRef,
+ Evidence assemblySecurity)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, assemblySecurity, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public Assembly Load(String assemblyString,
+ Evidence assemblySecurity)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoad(assemblyString, assemblySecurity, ref stackMark, false);
+ }
+
+ public int ExecuteAssembly(String assemblyFile)
+ {
+ return ExecuteAssembly(assemblyFile, (string[])null);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssembly(String assemblyFile,
+ Evidence assemblySecurity)
+ {
+ return ExecuteAssembly(assemblyFile, assemblySecurity, null);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssembly(String assemblyFile,
+ Evidence assemblySecurity,
+ String[] args)
+ {
+#if FEATURE_CAS_POLICY
+ if (assemblySecurity != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile, assemblySecurity);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ public int ExecuteAssembly(string assemblyFile, string[] args)
+ {
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssembly which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssembly(String assemblyFile,
+ Evidence assemblySecurity,
+ String[] args,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+ {
+#if FEATURE_CAS_POLICY
+ if (assemblySecurity != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile,
+ assemblySecurity,
+ hashValue,
+ hashAlgorithm);
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ public int ExecuteAssembly(string assemblyFile,
+ string[] args,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+ {
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.LoadFrom(assemblyFile,
+ hashValue,
+ hashAlgorithm);
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public int ExecuteAssemblyByName(String assemblyName)
+ {
+ return ExecuteAssemblyByName(assemblyName, (string[])null);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssemblyByName(String assemblyName,
+ Evidence assemblySecurity)
+ {
+#pragma warning disable 618
+ return ExecuteAssemblyByName(assemblyName, assemblySecurity, null);
+#pragma warning restore 618
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssemblyByName(String assemblyName,
+ Evidence assemblySecurity,
+ params String[] args)
+ {
+#if FEATURE_CAS_POLICY
+ if (assemblySecurity != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ public int ExecuteAssemblyByName(string assemblyName, params string[] args)
+ {
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of ExecuteAssemblyByName which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public int ExecuteAssemblyByName(AssemblyName assemblyName,
+ Evidence assemblySecurity,
+ params String[] args)
+ {
+#if FEATURE_CAS_POLICY
+ if (assemblySecurity != null && !IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName, assemblySecurity);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ public int ExecuteAssemblyByName(AssemblyName assemblyName, params string[] args)
+ {
+ RuntimeAssembly assembly = (RuntimeAssembly)Assembly.Load(assemblyName);
+
+ if (args == null)
+ args = new String[0];
+
+ return nExecuteAssembly(assembly, args);
+ }
+
+ public static AppDomain CurrentDomain
+ {
+ get {
+ Contract.Ensures(Contract.Result<AppDomain>() != null);
+ return Thread.GetDomain();
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ public Evidence Evidence
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)]
+ get {
+ return EvidenceNoDemand;
+ }
+ }
+
+ internal Evidence EvidenceNoDemand {
+ [SecurityCritical]
+ get {
+ if (_SecurityIdentity == null) {
+ if (!IsDefaultAppDomain() && nIsDefaultAppDomainForEvidence()) {
+#if !FEATURE_CORECLR
+ //
+ // V1.x compatibility: If this is an AppDomain created
+ // by the default appdomain without an explicit evidence
+ // then reuse the evidence of the default AppDomain.
+ //
+ return GetDefaultDomain().Evidence;
+#else
+ Contract.Assert(false,"This code should not be called for core CLR");
+
+ // This operation is not allowed
+ throw new InvalidOperationException();
+#endif
+ }
+ else {
+ // We can't cache this value, since the VM needs to differentiate between AppDomains
+ // which have no user supplied evidence and those which do and it uses the presence
+ // of Evidence on the domain to make that switch.
+ return new Evidence(new AppDomainEvidenceFactory(this));
+ }
+ }
+ else {
+ return _SecurityIdentity.Clone();
+ }
+ }
+ }
+
+ internal Evidence InternalEvidence
+ {
+ get {
+ return _SecurityIdentity;
+ }
+ }
+
+ internal EvidenceBase GetHostEvidence(Type type)
+ {
+ if (_SecurityIdentity != null)
+ {
+ return _SecurityIdentity.GetHostEvidence(type);
+ }
+ else
+ {
+ return new Evidence(new AppDomainEvidenceFactory(this)).GetHostEvidence(type);
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public String FriendlyName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return nGetFriendlyName(); }
+ }
+
+ public String BaseDirectory
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+#endif
+ get {
+ return FusionStore.ApplicationBase;
+ }
+ }
+
+#if FEATURE_FUSION
+ public String RelativeSearchPath
+ {
+ get { return FusionStore.PrivateBinPath; }
+ }
+
+ public bool ShadowCopyFiles
+ {
+ get {
+ String s = FusionStore.ShadowCopyFiles;
+ if((s != null) &&
+ (String.Compare(s, "true", StringComparison.OrdinalIgnoreCase) == 0))
+ return true;
+ else
+ return false;
+ }
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString()
+ {
+ StringBuilder sb = StringBuilderCache.Acquire();
+
+ String fn = nGetFriendlyName();
+ if (fn != null) {
+ sb.Append(Environment.GetResourceString("Loader_Name") + fn);
+ sb.Append(Environment.NewLine);
+ }
+
+ if(_Policies == null || _Policies.Length == 0)
+ sb.Append(Environment.GetResourceString("Loader_NoContextPolicies")
+ + Environment.NewLine);
+ else {
+ sb.Append(Environment.GetResourceString("Loader_ContextPolicies")
+ + Environment.NewLine);
+ for(int i = 0;i < _Policies.Length; i++) {
+ sb.Append(_Policies[i]);
+ sb.Append(Environment.NewLine);
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ public Assembly[] GetAssemblies()
+ {
+ return nGetAssemblies(false /* forIntrospection */);
+ }
+
+
+ public Assembly[] ReflectionOnlyGetAssemblies()
+ {
+ return nGetAssemblies(true /* forIntrospection */);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Assembly[] nGetAssemblies(bool forIntrospection);
+
+ // this is true when we've removed the handles etc so really can't do anything
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern bool IsUnloadingForcedFinalize();
+
+ // this is true when we've just started going through the finalizers and are forcing objects to finalize
+ // so must be aware that certain infrastructure may have gone away
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern bool IsFinalizingForUnload();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void PublishAnonymouslyHostedDynamicMethodsAssembly(RuntimeAssembly assemblyHandle);
+
+#if FEATURE_FUSION
+ // Appends the following string to the private path. Valid paths
+ // are of the form "bin;util/i386" etc.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.AppendPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void AppendPrivatePath(String path)
+ {
+ if(path == null || path.Length == 0)
+ return;
+
+ String current = FusionStore.Value[(int) AppDomainSetup.LoaderInformation.PrivateBinPathValue];
+ StringBuilder appendPath = StringBuilderCache.Acquire();
+
+ if(current != null && current.Length > 0) {
+ // See if the last character is a separator
+ appendPath.Append(current);
+ if((current[current.Length-1] != Path.PathSeparator) &&
+ (path[0] != Path.PathSeparator))
+ appendPath.Append(Path.PathSeparator);
+ }
+ appendPath.Append(path);
+
+ String result = StringBuilderCache.GetStringAndRelease(appendPath);
+ InternalSetPrivateBinPath(result);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.ClearPrivatePath has been deprecated. Please investigate the use of AppDomainSetup.PrivateBinPath instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void ClearPrivatePath()
+ {
+ InternalSetPrivateBinPath(String.Empty);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.ClearShadowCopyPath has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void ClearShadowCopyPath()
+ {
+ InternalSetShadowCopyPath(String.Empty);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.SetCachePath has been deprecated. Please investigate the use of AppDomainSetup.CachePath instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetCachePath(String path)
+ {
+ InternalSetCachePath(path);
+ }
+#endif // FEATURE_FUSION
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void SetData (string name, object data) {
+#if FEATURE_CORECLR
+ if (!name.Equals("LOCATION_URI"))
+ {
+ // Only LOCATION_URI can be set using AppDomain.SetData
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyLocationURI", name));
+ }
+#endif // FEATURE_CORECLR
+ SetDataHelper(name, data, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void SetData (string name, object data, IPermission permission) {
+#if FEATURE_CORECLR
+ if (!name.Equals("LOCATION_URI"))
+ {
+ // Only LOCATION_URI can be set using AppDomain.SetData
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyLocationURI", name));
+ }
+#endif // FEATURE_CORECLR
+ SetDataHelper(name, data, permission);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetDataHelper (string name, object data, IPermission permission) {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ //
+ // Synopsis:
+ // IgnoreSystemPolicy is provided as a legacy flag to allow callers to
+ // skip enterprise, machine and user policy levels. When this flag is set,
+ // any demands triggered in this AppDomain will be evaluated against the
+ // AppDomain CAS policy level that is set on the AppDomain.
+ // Security Requirements:
+ // The caller needs to be fully trusted in order to be able to set
+ // this legacy mode.
+ // Remarks:
+ // There needs to be an AppDomain policy level set before this compat
+ // switch can be set on the AppDomain.
+ //
+#if FEATURE_FUSION
+ if (name.Equals(TargetFrameworkNameAppCompatSetting)) {
+ _FusionStore.TargetFrameworkName = (String) data;
+ return;
+ }
+#if FEATURE_CAS_POLICY
+ if (name.Equals("IgnoreSystemPolicy")) {
+ lock (this) {
+ if (!_HasSetPolicy)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData"));
+ }
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+ }
+#endif
+ int key = AppDomainSetup.Locate(name);
+
+ if(key == -1) {
+ lock (((ICollection)LocalStore).SyncRoot) {
+ LocalStore[name] = new object[] {data, permission};
+ }
+ }
+ else {
+ if (permission != null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData"));
+ // Be sure to call these properties, not Value, since
+ // these do more than call Value.
+ switch(key) {
+ case (int) AppDomainSetup.LoaderInformation.DynamicBaseValue:
+ FusionStore.DynamicBase = (string) data;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.DevPathValue:
+ FusionStore.DeveloperPath = (string) data;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.ShadowCopyDirectoriesValue:
+ FusionStore.ShadowCopyDirectories = (string) data;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.DisallowPublisherPolicyValue:
+ if(data != null)
+ FusionStore.DisallowPublisherPolicy = true;
+ else
+ FusionStore.DisallowPublisherPolicy = false;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.DisallowCodeDownloadValue:
+ if (data != null)
+ FusionStore.DisallowCodeDownload = true;
+ else
+ FusionStore.DisallowCodeDownload = false;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.DisallowBindingRedirectsValue:
+ if(data != null)
+ FusionStore.DisallowBindingRedirects = true;
+ else
+ FusionStore.DisallowBindingRedirects = false;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.DisallowAppBaseProbingValue:
+ if(data != null)
+ FusionStore.DisallowApplicationBaseProbing = true;
+ else
+ FusionStore.DisallowApplicationBaseProbing = false;
+ break;
+ case (int) AppDomainSetup.LoaderInformation.ConfigurationBytesValue:
+ FusionStore.SetConfigurationBytes((byte[]) data);
+ break;
+ default:
+ FusionStore.Value[key] = (string) data;
+ break;
+ }
+ }
+#else // FEATURE_FUSION
+#if FEATURE_CORECLR
+ // SetData should only be used to set values that don't already exist.
+ {
+ object[] currentVal;
+ lock (((ICollection)LocalStore).SyncRoot) {
+ LocalStore.TryGetValue(name, out currentVal);
+ }
+ if (currentVal != null && currentVal[0] != null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SetData_OnlyOnce"));
+ }
+ }
+
+#endif // FEATURE_CORECLR
+ lock (((ICollection)LocalStore).SyncRoot) {
+ LocalStore[name] = new object[] {data, permission};
+ }
+#endif // FEATURE_FUSION
+ }
+
+ [Pure]
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public Object GetData(string name)
+ {
+ if(name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ int key = AppDomainSetup.Locate(name);
+ if(key == -1)
+ {
+#if FEATURE_LOADER_OPTIMIZATION
+ if(name.Equals(AppDomainSetup.LoaderOptimizationKey))
+ return FusionStore.LoaderOptimization;
+ else
+#endif // FEATURE_LOADER_OPTIMIZATION
+ {
+ object[] data;
+ lock (((ICollection)LocalStore).SyncRoot) {
+ LocalStore.TryGetValue(name, out data);
+ }
+ if (data == null)
+ return null;
+ if (data[1] != null) {
+ IPermission permission = (IPermission) data[1];
+ permission.Demand();
+ }
+ return data[0];
+ }
+ }
+ else {
+ // Be sure to call these properties, not Value, so
+ // that the appropriate permission demand will be done
+ switch(key) {
+ case (int) AppDomainSetup.LoaderInformation.ApplicationBaseValue:
+ return FusionStore.ApplicationBase;
+ case (int) AppDomainSetup.LoaderInformation.ApplicationNameValue:
+ return FusionStore.ApplicationName;
+#if FEATURE_FUSION
+ case (int) AppDomainSetup.LoaderInformation.ConfigurationFileValue:
+ return FusionStore.ConfigurationFile;
+ case (int) AppDomainSetup.LoaderInformation.DynamicBaseValue:
+ return FusionStore.DynamicBase;
+ case (int) AppDomainSetup.LoaderInformation.DevPathValue:
+ return FusionStore.DeveloperPath;
+ case (int) AppDomainSetup.LoaderInformation.PrivateBinPathValue:
+ return FusionStore.PrivateBinPath;
+ case (int) AppDomainSetup.LoaderInformation.PrivateBinPathProbeValue:
+ return FusionStore.PrivateBinPathProbe;
+ case (int) AppDomainSetup.LoaderInformation.ShadowCopyDirectoriesValue:
+ return FusionStore.ShadowCopyDirectories;
+ case (int) AppDomainSetup.LoaderInformation.ShadowCopyFilesValue:
+ return FusionStore.ShadowCopyFiles;
+ case (int) AppDomainSetup.LoaderInformation.CachePathValue:
+ return FusionStore.CachePath;
+ case (int) AppDomainSetup.LoaderInformation.LicenseFileValue:
+ return FusionStore.LicenseFile;
+ case (int) AppDomainSetup.LoaderInformation.DisallowPublisherPolicyValue:
+ return FusionStore.DisallowPublisherPolicy;
+ case (int) AppDomainSetup.LoaderInformation.DisallowCodeDownloadValue:
+ return FusionStore.DisallowCodeDownload;
+ case (int) AppDomainSetup.LoaderInformation.DisallowBindingRedirectsValue:
+ return FusionStore.DisallowBindingRedirects;
+ case (int) AppDomainSetup.LoaderInformation.DisallowAppBaseProbingValue:
+ return FusionStore.DisallowApplicationBaseProbing;
+ case (int) AppDomainSetup.LoaderInformation.ConfigurationBytesValue:
+ return FusionStore.GetConfigurationBytes();
+#endif //FEATURE_FUSION
+
+ default:
+ Contract.Assert(false, "Need to handle new LoaderInformation value in AppDomain.GetData()");
+ return null;
+ }
+ }
+
+ }
+
+ // The compat flags are set at domain creation time to indicate that the given breaking
+ // change should not be used in this domain.
+ //
+ // After the domain has been created, this Nullable boolean returned by this method should
+ // always have a value. Code in the runtime uses this to know if it is safe to cache values
+ // that might change if the compatibility switches have not been set yet.
+ public Nullable<bool> IsCompatibilitySwitchSet(String value)
+ {
+ Nullable<bool> fReturn;
+
+ if (_compatFlagsInitialized == false)
+ {
+ fReturn = new Nullable<bool>();
+ }
+ else
+ {
+ fReturn = new Nullable<bool>(_compatFlags != null && _compatFlags.ContainsKey(value));
+ }
+
+ return fReturn;
+ }
+
+ [Obsolete("AppDomain.GetCurrentThreadId has been deprecated because it does not provide a stable Id when managed threads are running on fibers (aka lightweight threads). To get a stable identifier for a managed thread, use the ManagedThreadId property on Thread. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [DllImport(Microsoft.Win32.Win32Native.KERNEL32)]
+ public static extern int GetCurrentThreadId();
+
+#if FEATURE_REMOTING
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, ControlAppDomain = true ),
+ ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.MayFail)]
+ public static void Unload(AppDomain domain)
+ {
+ if (domain == null)
+ throw new ArgumentNullException("domain");
+ Contract.EndContractBlock();
+
+ try {
+ Int32 domainID = AppDomain.GetIdForUnload(domain);
+ if (domainID==0)
+ throw new CannotUnloadAppDomainException();
+ AppDomain.nUnload(domainID);
+ }
+ catch(Exception e) {
+ throw e; // throw it again to reset stack trace
+ }
+ }
+#endif
+
+ // Explicitly set policy for a domain (providing policy hasn't been set
+ // previously). Making this call will guarantee that previously loaded
+ // assemblies will be granted permissions based on the default machine
+ // policy that was in place prior to this call.
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain policy levels are obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public void SetAppDomainPolicy(PolicyLevel domainPolicy)
+ {
+ if (domainPolicy == null)
+ throw new ArgumentNullException("domainPolicy");
+ Contract.EndContractBlock();
+
+ if (!IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ // Check that policy has not been set previously.
+ lock (this) {
+ if (_HasSetPolicy)
+ throw new PolicyException(Environment.GetResourceString("Policy_PolicyAlreadySet"));
+ _HasSetPolicy = true;
+
+ // Make sure that the loader allows us to change security policy
+ // at this time (this will throw if not.)
+ nChangeSecurityPolicy();
+ }
+
+ // Add the new policy level.
+ SecurityManager.PolicyManager.AddLevel(domainPolicy);
+ }
+#endif //#if !FEATURE_CAS_POLICY
+#if FEATURE_CLICKONCE
+ public ActivationContext ActivationContext {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get {
+ return _activationContext;
+ }
+ }
+
+ public ApplicationIdentity ApplicationIdentity {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get {
+ return _applicationIdentity;
+ }
+ }
+#endif // FEATURE_CLICKONCE
+
+
+#if FEATURE_CLICKONCE
+ public ApplicationTrust ApplicationTrust {
+ [System.Security.SecurityCritical] // auto-generated_required
+#else // FEATURE_CLICKONCE
+ internal ApplicationTrust ApplicationTrust {
+#endif // FEATURE_CLICKONCE
+ get {
+ if (_applicationTrust == null && _IsFastFullTrustDomain) {
+ _applicationTrust = new ApplicationTrust(new PermissionSet(PermissionState.Unrestricted));
+ }
+
+ return _applicationTrust;
+ }
+ }
+
+#if FEATURE_IMPERSONATION
+ // Set the default principal object to be attached to threads if they
+ // attempt to bind to a principal while executing in this appdomain. The
+ // default can only be set once.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
+ public void SetThreadPrincipal(IPrincipal principal)
+ {
+ if (principal == null)
+ throw new ArgumentNullException("principal");
+ Contract.EndContractBlock();
+
+ lock (this) {
+ // Check that principal has not been set previously.
+ if (_DefaultPrincipal != null)
+ throw new PolicyException(Environment.GetResourceString("Policy_PrincipalTwice"));
+
+ _DefaultPrincipal = principal;
+ }
+ }
+#endif // FEATURE_IMPERSONATION
+
+#if FEATURE_CAS_POLICY
+ // Similar to the above, but sets the class of principal to be created
+ // instead.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
+ public void SetPrincipalPolicy(PrincipalPolicy policy)
+ {
+ _PrincipalPolicy = policy;
+ }
+#endif
+
+
+#if FEATURE_REMOTING
+ // This method gives AppDomain an infinite life time by preventing a lease from being
+ // created
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override Object InitializeLifetimeService()
+ {
+ return null;
+ }
+ // This is useful for requesting execution of some code
+ // in another appDomain ... the delegate may be defined
+ // on a marshal-by-value object or a marshal-by-ref or
+ // contextBound object.
+ public void DoCallBack(CrossAppDomainDelegate callBackDelegate)
+ {
+ if (callBackDelegate == null)
+ throw new ArgumentNullException("callBackDelegate");
+ Contract.EndContractBlock();
+
+ callBackDelegate();
+ }
+#endif
+
+
+ public String DynamicDirectory
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ String dyndir = GetDynamicDir();
+ if (dyndir != null)
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dyndir ).Demand();
+
+ return dyndir;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ public static AppDomain CreateDomain(String friendlyName,
+ Evidence securityInfo) // Optional
+ {
+ return CreateDomain(friendlyName,
+ securityInfo,
+ null);
+ }
+
+ public static AppDomain CreateDomain(String friendlyName,
+ Evidence securityInfo, // Optional
+ String appBasePath,
+ String appRelativeSearchPath,
+ bool shadowCopyFiles)
+ {
+ AppDomainSetup info = new AppDomainSetup();
+ info.ApplicationBase = appBasePath;
+ info.PrivateBinPath = appRelativeSearchPath;
+ if(shadowCopyFiles)
+ info.ShadowCopyFiles = "true";
+
+ return CreateDomain(friendlyName,
+ securityInfo,
+ info);
+ }
+#endif // #if FEATURE_CAS_POLICY (not exposed in core)
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern private String GetDynamicDir();
+
+ // Private helpers called from unmanaged code.
+
+#if FEATURE_REMOTING
+
+ public static AppDomain CreateDomain(String friendlyName)
+ {
+ return CreateDomain(friendlyName, null, null);
+ }
+
+
+ // Marshal a single object into a serialized blob.
+ [System.Security.SecurityCritical] // auto-generated
+ private static byte[] MarshalObject(Object o)
+ {
+ CodeAccessPermission.Assert(true);
+
+ return Serialize(o);
+ }
+
+ // Marshal two objects into serialized blobs.
+ [System.Security.SecurityCritical] // auto-generated
+ private static byte[] MarshalObjects(Object o1, Object o2, out byte[] blob2)
+ {
+ CodeAccessPermission.Assert(true);
+
+ byte[] blob1 = Serialize(o1);
+ blob2 = Serialize(o2);
+ return blob1;
+ }
+
+ // Unmarshal a single object from a serialized blob.
+ [System.Security.SecurityCritical] // auto-generated
+ private static Object UnmarshalObject(byte[] blob)
+ {
+ CodeAccessPermission.Assert(true);
+
+ return Deserialize(blob);
+ }
+
+ // Unmarshal two objects from serialized blobs.
+ [System.Security.SecurityCritical] // auto-generated
+ private static Object UnmarshalObjects(byte[] blob1, byte[] blob2, out Object o2)
+ {
+ CodeAccessPermission.Assert(true);
+
+ Object o1 = Deserialize(blob1);
+ o2 = Deserialize(blob2);
+ return o1;
+ }
+
+ // Helper routines.
+ [System.Security.SecurityCritical] // auto-generated
+ private static byte[] Serialize(Object o)
+ {
+ if (o == null)
+ {
+ return null;
+ }
+ else if (o is ISecurityEncodable)
+ {
+ SecurityElement element = ((ISecurityEncodable)o).ToXml();
+ MemoryStream ms = new MemoryStream( 4096 );
+ ms.WriteByte( 0 );
+ StreamWriter writer = new StreamWriter( ms, Encoding.UTF8 );
+ element.ToWriter( writer );
+ writer.Flush();
+ return ms.ToArray();
+ }
+ else
+ {
+ MemoryStream ms = new MemoryStream();
+ ms.WriteByte( 1 );
+ CrossAppDomainSerializer.SerializeObject(o, ms);
+ return ms.ToArray();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static Object Deserialize(byte[] blob)
+ {
+ if (blob == null)
+ return null;
+
+ if (blob[0] == 0)
+ {
+ Parser parser = new Parser( blob, Tokenizer.ByteTokenEncoding.UTF8Tokens, 1 );
+ SecurityElement root = parser.GetTopElement();
+ if (root.Tag.Equals( "IPermission" ) || root.Tag.Equals( "Permission" ))
+ {
+ IPermission ip = System.Security.Util.XMLUtil.CreatePermission( root, PermissionState.None, false );
+
+ if (ip == null)
+ {
+ return null;
+ }
+
+ ip.FromXml( root );
+
+ return ip;
+ }
+ else if (root.Tag.Equals( "PermissionSet" ))
+ {
+ PermissionSet permissionSet = new PermissionSet();
+
+ permissionSet.FromXml( root, false, false );
+
+ return permissionSet;
+ }
+ else if (root.Tag.Equals( "PermissionToken" ))
+ {
+ PermissionToken pToken = new PermissionToken();
+
+ pToken.FromXml( root );
+
+ return pToken;
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+ else
+ {
+ Object obj = null;
+ using(MemoryStream stream = new MemoryStream( blob, 1, blob.Length - 1 )) {
+ obj = CrossAppDomainSerializer.DeserializeObject(stream);
+ }
+
+ Contract.Assert( !(obj is IPermission), "IPermission should be xml deserialized" );
+ Contract.Assert( !(obj is PermissionSet), "PermissionSet should be xml deserialized" );
+
+ return obj;
+ }
+ }
+
+#endif // FEATURE_REMOTING
+
+#if !FEATURE_CORECLR
+ //
+ // Called by the VM if ICLRExecutionManager::Pause is called with the PAUSE_APP_DOMAINS flag.
+ // This mimics the behavior of the CoreCLR FAS (fast application switching) model, to ensure
+ // that code that depends on things happening in a particular order will work.
+ //
+ [System.Security.SecurityCritical]
+ internal static void Pause()
+ {
+ AppDomainPauseManager.Instance.Pausing();
+ AppDomainPauseManager.Instance.Paused();
+ }
+
+ //
+ // Called by the VM if ICLRExecutionManager::Resume is called after ICLRExecutionManager::Pause
+ // was called with the PAUSE_APP_DOMAINS flag.
+ // This mimics the behavior of the CoreCLR FAS (fast application switching) model, to ensure
+ // that code that depends on things happening in a particular order will work.
+ //
+ [System.Security.SecurityCritical]
+ internal static void Resume()
+ {
+ if (AppDomainPauseManager.IsPaused)
+ {
+ AppDomainPauseManager.Instance.Resuming();
+ AppDomainPauseManager.Instance.Resumed();
+ }
+ }
+#endif
+
+ private AppDomain() {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Constructor));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int _nExecuteAssembly(RuntimeAssembly assembly, String[] args);
+ internal int nExecuteAssembly(RuntimeAssembly assembly, String[] args)
+ {
+ return _nExecuteAssembly(assembly, args);
+ }
+
+#if FEATURE_VERSIONING
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void nCreateContext();
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void nSetupBindingPaths(String trustedPlatformAssemblies, String platformResourceRoots, String appPath, String appNiPaths, String appLocalWinMD);
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void SetupBindingPaths(String trustedPlatformAssemblies, String platformResourceRoots, String appPath, String appNiPaths, String appLocalWinMD)
+ {
+ nSetupBindingPaths(trustedPlatformAssemblies, platformResourceRoots, appPath, appNiPaths, appLocalWinMD);
+ }
+#endif // FEATURE_VERSIONING
+
+#if FEATURE_REMOTING
+ internal void CreateRemotingData()
+ {
+ lock(this) {
+ if (_RemotingData == null)
+ _RemotingData = new DomainSpecificRemotingData();
+ }
+ }
+
+ internal DomainSpecificRemotingData RemotingData
+ {
+ get
+ {
+ if (_RemotingData == null)
+ CreateRemotingData();
+
+ return _RemotingData;
+ }
+ }
+#endif // FEATURE_REMOTING
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern String nGetFriendlyName();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool nIsDefaultAppDomainForEvidence();
+
+ // support reliability for certain event handlers, if the target
+ // methods also participate in this discipline. If caller passes
+ // an existing MulticastDelegate, then we could use a MDA to indicate
+ // that reliability is not guaranteed. But if it is a single cast
+ // scenario, we can make it work.
+
+ public event EventHandler ProcessExit
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated_required
+ add
+ {
+ if (value != null)
+ {
+ RuntimeHelpers.PrepareContractedDelegate(value);
+ lock(this)
+ _processExit += value;
+ }
+ }
+ remove
+ {
+ lock(this)
+ _processExit -= value;
+ }
+ }
+
+
+ public event EventHandler DomainUnload
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated_required
+ add
+ {
+ if (value != null)
+ {
+ RuntimeHelpers.PrepareContractedDelegate(value);
+ lock(this)
+ _domainUnload += value;
+ }
+ }
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ remove
+ {
+ lock(this)
+ _domainUnload -= value;
+ }
+ }
+
+
+ public event UnhandledExceptionEventHandler UnhandledException
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ add
+ {
+ if (value != null)
+ {
+ RuntimeHelpers.PrepareContractedDelegate(value);
+ lock(this)
+ _unhandledException += value;
+ }
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ remove
+ {
+ lock(this)
+ _unhandledException -= value;
+ }
+ }
+
+#if FEATURE_EXCEPTION_NOTIFICATIONS
+ // This is the event managed code can wireup against to be notified
+ // about first chance exceptions.
+ //
+ // To register/unregister the callback, the code must be SecurityCritical.
+ public event EventHandler<FirstChanceExceptionEventArgs> FirstChanceException
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ add
+ {
+ if (value != null)
+ {
+ RuntimeHelpers.PrepareContractedDelegate(value);
+ lock(this)
+ _firstChanceException += value;
+ }
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ remove
+ {
+ lock(this)
+ _firstChanceException -= value;
+ }
+ }
+#endif // FEATURE_EXCEPTION_NOTIFICATIONS
+
+ private void OnAssemblyLoadEvent(RuntimeAssembly LoadedAssembly)
+ {
+ AssemblyLoadEventHandler eventHandler = AssemblyLoad;
+ if (eventHandler != null) {
+ AssemblyLoadEventArgs ea = new AssemblyLoadEventArgs(LoadedAssembly);
+ eventHandler(this, ea);
+ }
+ }
+
+ // This method is called by the VM.
+ [System.Security.SecurityCritical]
+ private RuntimeAssembly OnResourceResolveEvent(RuntimeAssembly assembly, String resourceName)
+ {
+ ResolveEventHandler eventHandler = _ResourceResolve;
+ if ( eventHandler == null)
+ return null;
+
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++) {
+ Assembly asm = ((ResolveEventHandler)ds[i])(this, new ResolveEventArgs(resourceName, assembly));
+ RuntimeAssembly ret = GetRuntimeAssembly(asm);
+ if (ret != null)
+ return ret;
+ }
+
+ return null;
+ }
+
+ // This method is called by the VM
+ [System.Security.SecurityCritical]
+ private RuntimeAssembly OnTypeResolveEvent(RuntimeAssembly assembly, String typeName)
+ {
+ ResolveEventHandler eventHandler = _TypeResolve;
+ if (eventHandler == null)
+ return null;
+
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++) {
+ Assembly asm = ((ResolveEventHandler)ds[i])(this, new ResolveEventArgs(typeName, assembly));
+ RuntimeAssembly ret = GetRuntimeAssembly(asm);
+ if (ret != null)
+ return ret;
+ }
+
+ return null;
+ }
+
+ // This method is called by the VM.
+ [System.Security.SecurityCritical]
+ private RuntimeAssembly OnAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
+ {
+ ResolveEventHandler eventHandler = _AssemblyResolve;
+
+ if (eventHandler == null)
+ {
+ return null;
+ }
+
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++) {
+ Assembly asm = ((ResolveEventHandler)ds[i])(this, new ResolveEventArgs(assemblyFullName, assembly));
+ RuntimeAssembly ret = GetRuntimeAssembly(asm);
+ if (ret != null)
+ return ret;
+ }
+
+ return null;
+ }
+
+#if FEATURE_REFLECTION_ONLY_LOAD
+
+ private RuntimeAssembly OnReflectionOnlyAssemblyResolveEvent(RuntimeAssembly assembly, String assemblyFullName)
+ {
+ ResolveEventHandler eventHandler = ReflectionOnlyAssemblyResolve;
+ if (eventHandler != null) {
+
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++) {
+ Assembly asm = ((ResolveEventHandler)ds[i])(this, new ResolveEventArgs(assemblyFullName, assembly));
+ RuntimeAssembly ret = GetRuntimeAssembly(asm);
+ if (ret != null)
+ return ret;
+ }
+ }
+
+ return null;
+ }
+
+#if FEATURE_COMINTEROP
+ // Called by VM - code:CLRPrivTypeCacheReflectionOnlyWinRT::RaiseNamespaceResolveEvent
+ private RuntimeAssembly[] OnReflectionOnlyNamespaceResolveEvent(RuntimeAssembly assembly, string namespaceName)
+ {
+ return System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.OnReflectionOnlyNamespaceResolveEvent(this, assembly, namespaceName);
+ }
+#endif // FEATURE_COMINTEROP
+
+#endif // FEATURE_REFLECTION_ONLY_LOAD
+
+#if FEATURE_COMINTEROP
+ // Called by VM - code:CLRPrivTypeCacheWinRT::RaiseDesignerNamespaceResolveEvent
+ private string[] OnDesignerNamespaceResolveEvent(string namespaceName)
+ {
+ return System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMetadata.OnDesignerNamespaceResolveEvent(this, namespaceName);
+ }
+#endif // FEATURE_COMINTEROP
+
+ internal AppDomainSetup FusionStore
+ {
+ get {
+ Contract.Assert(_FusionStore != null,
+ "Fusion store has not been correctly setup in this domain");
+ return _FusionStore;
+ }
+ }
+
+ internal static RuntimeAssembly GetRuntimeAssembly(Assembly asm)
+ {
+ if (asm == null)
+ return null;
+
+ RuntimeAssembly rtAssembly = asm as RuntimeAssembly;
+ if (rtAssembly != null)
+ return rtAssembly;
+
+ AssemblyBuilder ab = asm as AssemblyBuilder;
+ if (ab != null)
+ return ab.InternalAssembly;
+
+ return null;
+ }
+
+ private Dictionary<String, Object[]> LocalStore
+ {
+ get {
+ if (_LocalStore != null)
+ return _LocalStore;
+ else {
+ _LocalStore = new Dictionary<String, Object[]>();
+ return _LocalStore;
+ }
+ }
+ }
+
+#if FEATURE_FUSION
+ private void TurnOnBindingRedirects()
+ {
+ _FusionStore.DisallowBindingRedirects = false;
+ }
+#endif
+
+ // This will throw a CannotUnloadAppDomainException if the appdomain is
+ // in another process.
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static Int32 GetIdForUnload(AppDomain domain)
+ {
+ if (RemotingServices.IsTransparentProxy(domain))
+ {
+ return RemotingServices.GetServerDomainIdForProxy(domain);
+ }
+ else
+ return domain.Id;
+ }
+#endif
+
+ // Used to determine if server object context is valid in
+ // x-domain remoting scenarios.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool IsDomainIdValid(Int32 id);
+
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern AppDomain GetDefaultDomain();
+#endif
+
+#if FEATURE_IMPERSONATION
+ // Internal routine to retrieve the default principal object. If this is
+ // called before the principal has been explicitly set, it will
+ // automatically allocate a default principal based on the policy set by
+ // SetPrincipalPolicy.
+ internal IPrincipal GetThreadPrincipal()
+ {
+ IPrincipal principal = null;
+ if (_DefaultPrincipal == null) {
+#if FEATURE_CAS_POLICY
+ switch (_PrincipalPolicy) {
+ case PrincipalPolicy.NoPrincipal:
+ principal = null;
+ break;
+ case PrincipalPolicy.UnauthenticatedPrincipal:
+ principal = new GenericPrincipal(new GenericIdentity("", ""),
+ new String[] {""});
+ break;
+ case PrincipalPolicy.WindowsPrincipal:
+ principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
+ break;
+ default:
+ principal = null;
+ break;
+ }
+#else
+ principal = new GenericPrincipal(new GenericIdentity("", ""),
+ new String[] {""});
+
+#endif
+ }
+ else
+ principal = _DefaultPrincipal;
+
+ return principal;
+ }
+#endif // FEATURE_IMPERSONATION
+
+#if FEATURE_REMOTING
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void CreateDefaultContext()
+ {
+ lock(this) {
+ // if it has not been created we ask the Context class to
+ // create a new default context for this appdomain.
+ if (_DefaultContext == null)
+ _DefaultContext = Context.CreateDefaultContext();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Context GetDefaultContext()
+ {
+ if (_DefaultContext == null)
+ CreateDefaultContext();
+ return _DefaultContext;
+ }
+
+ // Ensure that evidence provided when creating an AppDomain would not have been used to create a
+ // sandbox in legacy CAS mode. If it could have been used to create a sandbox, and we're not in CAS
+ // mode, then we throw an exception to prevent acciental creation of unsandboxed domains where a
+ // sandbox would have been expected.
+ [SecuritySafeCritical]
+ internal static void CheckDomainCreationEvidence(AppDomainSetup creationDomainSetup,
+ Evidence creationEvidence)
+ {
+ if (creationEvidence != null && !CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ if (creationDomainSetup == null || creationDomainSetup.ApplicationTrust == null)
+ {
+ // We allow non-null evidence in CAS mode to support the common pattern of passing in
+ // AppDomain.CurrentDomain.Evidence. Since the zone evidence must have been changed
+ // if the user has any expectation of sandboxing the domain under legacy CAS policy,
+ // we use a zone comparison to check for this pattern. A strict comparison will not
+ // work, since MSDN samples for creating a domain show using a modified version of the
+ // current domain's evidence and we would capturce people who copied and pasted these
+ // samples without intending to sandbox.
+ Zone creatorsZone = CurrentDomain.EvidenceNoDemand.GetHostEvidence<Zone>();
+ SecurityZone creatorsSecurityZone = creatorsZone != null ?
+ creatorsZone.SecurityZone :
+ SecurityZone.MyComputer;
+
+ Zone suppliedZone = creationEvidence.GetHostEvidence<Zone>();
+ if (suppliedZone != null)
+ {
+ if (suppliedZone.SecurityZone != creatorsSecurityZone &&
+ suppliedZone.SecurityZone != SecurityZone.MyComputer)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+ }
+ }
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, ControlAppDomain = true )]
+ public static AppDomain CreateDomain(String friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup info)
+ {
+ return InternalCreateDomain(friendlyName, securityInfo, info);
+ }
+#else
+ internal static AppDomain CreateDomain(String friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup info)
+ {
+ return InternalCreateDomain(friendlyName, securityInfo, info);
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static AppDomain InternalCreateDomain(String friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup info)
+ {
+ if (friendlyName == null)
+ throw new ArgumentNullException("friendlyName", Environment.GetResourceString("ArgumentNull_String"));
+
+ Contract.EndContractBlock();
+
+ AppDomain.CheckCreateDomainSupported();
+
+ if (info == null)
+ info = new AppDomainSetup();
+ if (info.TargetFrameworkName == null)
+ info.TargetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName();
+
+ AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
+ if (domainManager != null)
+ return domainManager.CreateDomain(friendlyName, securityInfo, info);
+
+ // No AppDomainManager is set up for this domain
+
+ // If evidence is provided, we check to make sure that is allowed.
+ if (securityInfo != null)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+
+ // If we're potentially trying to sandbox without using a homogenous domain, we need to reject
+ // the domain creation.
+ CheckDomainCreationEvidence(info, securityInfo);
+ }
+
+ return nCreateDomain(friendlyName,
+ info,
+ securityInfo,
+ securityInfo == null ? AppDomain.CurrentDomain.InternalEvidence : null,
+ AppDomain.CurrentDomain.GetSecurityDescriptor());
+ }
+#endif // FEATURE_REMOTING
+
+#if FEATURE_CAS_POLICY
+
+ public static AppDomain CreateDomain (string friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup info,
+ PermissionSet grantSet,
+ params StrongName[] fullTrustAssemblies)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ if (info.ApplicationBase == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AppDomainSandboxAPINeedsExplicitAppBase"));
+ Contract.EndContractBlock();
+
+ if (fullTrustAssemblies == null)
+ {
+ fullTrustAssemblies = new StrongName[0];
+ }
+
+ info.ApplicationTrust = new ApplicationTrust(grantSet, fullTrustAssemblies);
+ return CreateDomain(friendlyName, securityInfo, info);
+ }
+
+ public static AppDomain CreateDomain(String friendlyName,
+ Evidence securityInfo, // Optional
+ String appBasePath,
+ String appRelativeSearchPath,
+ bool shadowCopyFiles,
+ AppDomainInitializer adInit,
+ string[] adInitArgs)
+ {
+ AppDomainSetup info = new AppDomainSetup();
+ info.ApplicationBase = appBasePath;
+ info.PrivateBinPath = appRelativeSearchPath;
+ info.AppDomainInitializer=adInit;
+ info.AppDomainInitializerArguments=adInitArgs;
+ if(shadowCopyFiles)
+ info.ShadowCopyFiles = "true";
+
+ return CreateDomain(friendlyName,
+ securityInfo,
+ info);
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void nSetNativeDllSearchDirectories(string paths);
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupFusionStore(AppDomainSetup info, AppDomainSetup oldInfo)
+ {
+ Contract.Requires(info != null);
+
+#if FEATURE_FUSION
+ if (oldInfo == null) {
+
+ // Create the application base and configuration file from the imagelocation
+ // passed in or use the Win32 Image name.
+ if(info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] == null ||
+ info.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] == null )
+#else
+ if (info.ApplicationBase == null)
+#endif
+
+ {
+#if FEATURE_FUSION
+ AppDomain defaultDomain = GetDefaultDomain();
+ if (this == defaultDomain) {
+ // The default domain gets its defaults from the main process.
+ info.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true);
+ }
+ else {
+ // Other domains get their defaults from the default domain. This way, a host process
+ // can use AppDomainManager to set up the defaults for every domain created in the process.
+ if (info.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] == null)
+ info.ConfigurationFile = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue];
+ if (info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] == null)
+ info.ApplicationBase = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue];
+ if (info.Value[(int) AppDomainSetup.LoaderInformation.ApplicationNameValue] == null)
+ info.ApplicationName = defaultDomain.FusionStore.Value[(int) AppDomainSetup.LoaderInformation.ApplicationNameValue];
+ }
+#else
+ info.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true);
+#endif
+
+ }
+
+#if FEATURE_FUSION
+ // If there is no relative path then check the
+ // environment
+ if(info.Value[(int) AppDomainSetup.LoaderInformation.PrivateBinPathValue] == null)
+ info.PrivateBinPath = Environment.nativeGetEnvironmentVariable(AppDomainSetup.PrivateBinPathEnvironmentVariable);
+
+ // Add the developer path if it exists on this
+ // machine.
+ if(info.DeveloperPath == null)
+ info.DeveloperPath = RuntimeEnvironment.GetDeveloperPath();
+
+ }
+
+ // Set up the fusion context
+ IntPtr fusionContext = GetFusionContext();
+ info.SetupFusionContext(fusionContext, oldInfo);
+
+ // Set loader optimization policy
+#else
+#if FEATURE_VERSIONING
+ nCreateContext();
+#endif // FEATURE_VERSIONING
+#endif // FEATURE_FUSION
+
+#if FEATURE_LOADER_OPTIMIZATION
+ if (info.LoaderOptimization != LoaderOptimization.NotSpecified || (oldInfo != null && info.LoaderOptimization != oldInfo.LoaderOptimization))
+ UpdateLoaderOptimization(info.LoaderOptimization);
+#endif
+
+
+
+ // This must be the last action taken
+ _FusionStore = info;
+ }
+
+ // used to package up evidence, so it can be serialized
+ // for the call to InternalRemotelySetupRemoteDomain
+ [Serializable]
+ private class EvidenceCollection
+ {
+ public Evidence ProvidedSecurityInfo;
+ public Evidence CreatorsSecurityInfo;
+ }
+
+ private static void RunInitializer(AppDomainSetup setup)
+ {
+ if (setup.AppDomainInitializer!=null)
+ {
+ string[] args=null;
+ if (setup.AppDomainInitializerArguments!=null)
+ args=(string[])setup.AppDomainInitializerArguments.Clone();
+ setup.AppDomainInitializer(args);
+ }
+ }
+
+ // Used to switch into other AppDomain and call SetupRemoteDomain.
+ // We cannot simply call through the proxy, because if there
+ // are any remoting sinks registered, they can add non-mscorlib
+ // objects to the message (causing an assembly load exception when
+ // we try to deserialize it on the other side)
+ [System.Security.SecurityCritical] // auto-generated
+ private static object PrepareDataForSetup(String friendlyName,
+ AppDomainSetup setup,
+ Evidence providedSecurityInfo,
+ Evidence creatorsSecurityInfo,
+ IntPtr parentSecurityDescriptor,
+ string sandboxName,
+ string[] propertyNames,
+ string[] propertyValues)
+ {
+ byte[] serializedEvidence = null;
+ bool generateDefaultEvidence = false;
+
+#if FEATURE_CAS_POLICY
+ // serialize evidence
+ EvidenceCollection evidenceCollection = null;
+
+ if (providedSecurityInfo != null || creatorsSecurityInfo != null)
+ {
+ // If we're just passing through AppDomain.CurrentDomain.Evidence, and that evidence is just
+ // using the standard runtime AppDomainEvidenceFactory, don't waste time serializing it and
+ // deserializing it back -- instead, we can recreate a new AppDomainEvidenceFactory in the new
+ // domain. We only want to do this if there is no HostSecurityManager, otherwise the
+ // HostSecurityManager could have added additional evidence on top of our standard factory.
+ HostSecurityManager hsm = CurrentDomain.DomainManager != null ? CurrentDomain.DomainManager.HostSecurityManager : null;
+ bool hostMayContributeEvidence = hsm != null &&
+ hsm.GetType() != typeof(HostSecurityManager) &&
+ (hsm.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence;
+ if (!hostMayContributeEvidence)
+ {
+ if (providedSecurityInfo != null &&
+ providedSecurityInfo.IsUnmodified &&
+ providedSecurityInfo.Target != null &&
+ providedSecurityInfo.Target is AppDomainEvidenceFactory)
+ {
+ providedSecurityInfo = null;
+ generateDefaultEvidence = true;
+ }
+ if (creatorsSecurityInfo != null &&
+ creatorsSecurityInfo.IsUnmodified &&
+ creatorsSecurityInfo.Target != null &&
+ creatorsSecurityInfo.Target is AppDomainEvidenceFactory)
+ {
+ creatorsSecurityInfo = null;
+ generateDefaultEvidence = true;
+ }
+ }
+ }
+ if ((providedSecurityInfo != null) ||
+ (creatorsSecurityInfo != null)) {
+ evidenceCollection = new EvidenceCollection();
+ evidenceCollection.ProvidedSecurityInfo = providedSecurityInfo;
+ evidenceCollection.CreatorsSecurityInfo = creatorsSecurityInfo;
+ }
+
+ if (evidenceCollection != null) {
+ serializedEvidence =
+ CrossAppDomainSerializer.SerializeObject(evidenceCollection).GetBuffer();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ AppDomainInitializerInfo initializerInfo = null;
+ if (setup!=null && setup.AppDomainInitializer!=null)
+ initializerInfo=new AppDomainInitializerInfo(setup.AppDomainInitializer);
+
+ // will travel x-Ad, drop non-agile data
+ AppDomainSetup newSetup = new AppDomainSetup(setup, false);
+
+#if FEATURE_CORECLR
+ // Remove the special AppDomainCompatSwitch entries from the set of name value pairs
+ // And add them to the AppDomainSetup
+ //
+ // This is only supported on CoreCLR through ICLRRuntimeHost2.CreateAppDomainWithManager
+ // Desktop code should use System.AppDomain.CreateDomain() or
+ // System.AppDomainManager.CreateDomain() and add the flags to the AppDomainSetup
+ List<String> compatList = new List<String>();
+
+ if(propertyNames!=null && propertyValues != null)
+ {
+ for (int i=0; i<propertyNames.Length; i++)
+ {
+ if(String.Compare(propertyNames[i], "AppDomainCompatSwitch", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ compatList.Add(propertyValues[i]);
+ propertyNames[i] = null;
+ propertyValues[i] = null;
+ }
+
+ }
+
+ if (compatList.Count > 0)
+ {
+ newSetup.SetCompatibilitySwitches(compatList);
+ }
+ }
+#endif // FEATURE_CORECLR
+
+
+ return new Object[]
+ {
+ friendlyName,
+ newSetup,
+ parentSecurityDescriptor,
+ generateDefaultEvidence,
+ serializedEvidence,
+ initializerInfo,
+ sandboxName,
+ propertyNames,
+ propertyValues
+ };
+ } // PrepareDataForSetup
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ private static Object Setup(Object arg)
+ {
+ Contract.Requires(arg != null && arg is Object[]);
+ Contract.Requires(((Object[])arg).Length >= 8);
+
+ Object[] args=(Object[])arg;
+ String friendlyName = (String)args[0];
+ AppDomainSetup setup = (AppDomainSetup)args[1];
+ IntPtr parentSecurityDescriptor = (IntPtr)args[2];
+ bool generateDefaultEvidence = (bool)args[3];
+ byte[] serializedEvidence = (byte[])args[4];
+ 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
+ // extract evidence
+ Evidence providedSecurityInfo = null;
+ Evidence creatorsSecurityInfo = null;
+
+
+ AppDomain ad = AppDomain.CurrentDomain;
+ AppDomainSetup newSetup=new AppDomainSetup(setup,false);
+
+ if(propertyNames!=null && propertyValues != null)
+ {
+#if FEATURE_CORECLR
+ StringBuilder normalisedAppPathList = null;
+#endif // FEATURE_CORECLR
+ for (int i=0; i<propertyNames.Length; i++)
+ {
+ if(propertyNames[i]=="APPBASE") // make sure in sync with Fusion
+ {
+ if(propertyValues[i]==null)
+ throw new ArgumentNullException("APPBASE");
+
+ if (Path.IsRelative(propertyValues[i]))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+
+ 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);
+ }
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_LOADER_OPTIMIZATION
+ else
+ if(propertyNames[i]=="LOADER_OPTIMIZATION")
+ {
+ if(propertyValues[i]==null)
+ throw new ArgumentNullException("LOADER_OPTIMIZATION");
+
+ switch(propertyValues[i])
+ {
+ case "SingleDomain": newSetup.LoaderOptimization=LoaderOptimization.SingleDomain;break;
+ case "MultiDomain": newSetup.LoaderOptimization=LoaderOptimization.MultiDomain;break;
+ case "MultiDomainHost": newSetup.LoaderOptimization=LoaderOptimization.MultiDomainHost;break;
+ case "NotSpecified": newSetup.LoaderOptimization=LoaderOptimization.NotSpecified;break;
+ default: throw new ArgumentException(Environment.GetResourceString("Argument_UnrecognizedLoaderOptimization"), "LOADER_OPTIMIZATION");
+ }
+ }
+#endif // FEATURE_LOADER_OPTIMIZATION
+#if FEATURE_CORECLR
+ else
+ if(propertyNames[i]=="NATIVE_DLL_SEARCH_DIRECTORIES")
+ {
+ if(propertyValues[i]==null)
+ throw new ArgumentNullException("NATIVE_DLL_SEARCH_DIRECTORIES");
+ ad.SetDataHelper(propertyNames[i],propertyValues[i],null);
+ string paths = (string)propertyValues[i];
+ if( paths.Length==0 )
+ continue;
+ nSetNativeDllSearchDirectories(paths);
+ }
+ else
+ if(propertyNames[i]=="TRUSTED_PLATFORM_ASSEMBLIES" ||
+ propertyNames[i]=="PLATFORM_RESOURCE_ROOTS" ||
+ propertyNames[i]=="APP_PATHS" ||
+ propertyNames[i]=="APP_NI_PATHS")
+ {
+ string values = propertyValues[i];
+ if(values==null)
+ throw new ArgumentNullException(propertyNames[i]);
+
+ int estimatedLength = values.Length + 1; // +1 for extra separator temporarily added at end
+ if (normalisedAppPathList == null) {
+ normalisedAppPathList = new StringBuilder(estimatedLength);
+ }
+ else {
+ normalisedAppPathList.Clear();
+ if (normalisedAppPathList.Capacity < estimatedLength)
+ normalisedAppPathList.Capacity = estimatedLength;
+ }
+
+ for (int pos = 0; pos < values.Length; pos++)
+ {
+ string path;
+
+ int nextPos = values.IndexOf(Path.PathSeparator, pos);
+ if (nextPos == -1)
+ {
+ path = values.Substring(pos);
+ pos = values.Length - 1;
+ }
+ else
+ {
+ path = values.Substring(pos, nextPos - pos);
+ pos = nextPos;
+ }
+
+ if( path.Length==0 ) // skip empty dirs
+ continue;
+
+ if (Path.IsRelative(path))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+
+ string appPath = NormalizePath(path, fullCheck: true);
+ normalisedAppPathList.Append(appPath);
+ normalisedAppPathList.Append(Path.PathSeparator);
+ }
+ // Strip the last separator
+ if (normalisedAppPathList.Length > 0)
+ {
+ normalisedAppPathList.Remove(normalisedAppPathList.Length - 1, 1);
+ }
+ 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
+ }
+#endif
+
+ }
+ }
+
+#if !FEATURE_CORECLR
+ AppDomainSortingSetupInfo sortingSetup = newSetup._AppDomainSortingSetupInfo;
+
+ if(sortingSetup != null)
+ {
+ if(sortingSetup._pfnIsNLSDefinedString == IntPtr.Zero || sortingSetup._pfnCompareStringEx == IntPtr.Zero || sortingSetup._pfnLCMapStringEx == IntPtr.Zero || sortingSetup._pfnFindNLSStringEx == IntPtr.Zero
+ || sortingSetup._pfnCompareStringOrdinal == IntPtr.Zero || sortingSetup._pfnGetNLSVersionEx == IntPtr.Zero)
+ {
+
+ if(!(sortingSetup._pfnIsNLSDefinedString == IntPtr.Zero && sortingSetup._pfnCompareStringEx == IntPtr.Zero && sortingSetup._pfnLCMapStringEx == IntPtr.Zero && sortingSetup._pfnFindNLSStringEx == IntPtr.Zero
+ && sortingSetup._pfnCompareStringOrdinal == IntPtr.Zero && sortingSetup._pfnGetNLSVersionEx == IntPtr.Zero))
+ {
+ // Some functions defined but not all of them.
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_NotAllCustomSortingFuncsDefined"));
+ }
+
+ }
+ }
+#endif
+
+ ad.SetupFusionStore(newSetup, null); // makes FusionStore a ref to newSetup
+
+ // technically, we don't need this, newSetup refers to the same object as FusionStore
+ // but it's confusing since it isn't immediately obvious whether we have a ref or a copy
+ AppDomainSetup adSetup = ad.FusionStore;
+
+#if FEATURE_CORECLR
+ adSetup.InternalSetApplicationTrust(sandboxName);
+#endif // FEATURE_CORECLR
+
+#if !FEATURE_CORECLR // not used by coreclr
+ if (serializedEvidence != null) {
+ EvidenceCollection evidenceCollection = (EvidenceCollection)
+ CrossAppDomainSerializer.DeserializeObject(new MemoryStream(serializedEvidence));
+ providedSecurityInfo = evidenceCollection.ProvidedSecurityInfo;
+ creatorsSecurityInfo = evidenceCollection.CreatorsSecurityInfo;
+ }
+#endif
+ // set up the friendly name
+ ad.nSetupFriendlyName(friendlyName);
+
+#if FEATURE_COMINTEROP
+ if (setup != null && setup.SandboxInterop)
+ {
+ ad.nSetDisableInterfaceCache();
+ }
+#endif // FEATURE_COMINTEROP
+
+ // set up the AppDomainManager for this domain and initialize security.
+ if (adSetup.AppDomainManagerAssembly != null && adSetup.AppDomainManagerType != null)
+ {
+ ad.SetAppDomainManagerType(adSetup.AppDomainManagerAssembly, adSetup.AppDomainManagerType);
+ }
+
+#if FEATURE_APTCA
+ // set any conditial-aptca visible assemblies
+ ad.PartialTrustVisibleAssemblies = adSetup.PartialTrustVisibleAssemblies;
+#endif // FEATURE_APTCA
+
+ ad.CreateAppDomainManager(); // could modify FusionStore's object
+ ad.InitializeDomainSecurity(providedSecurityInfo,
+ creatorsSecurityInfo,
+ generateDefaultEvidence,
+ parentSecurityDescriptor,
+ true);
+
+ // can load user code now
+ if(initializerInfo!=null)
+ adSetup.AppDomainInitializer=initializerInfo.Unwrap();
+ RunInitializer(adSetup);
+
+ // Activate the application if needed.
+#if FEATURE_CLICKONCE
+ ObjectHandle oh = null;
+ if (adSetup.ActivationArguments != null && adSetup.ActivationArguments.ActivateInstance)
+ oh = Activator.CreateInstance(ad.ActivationContext);
+ return RemotingServices.MarshalInternal(oh, null, null);
+#else
+ return null;
+#endif // FEATURE_CLICKONCE
+ }
+
+ [SecuritySafeCritical]
+ internal static string NormalizePath(string path, bool fullCheck)
+ {
+#if FEATURE_PATHCOMPAT
+ // Appcontext switches can't currently be safely hit during AppDomain bringup
+ return Path.LegacyNormalizePath(
+ path: path,
+ fullCheck: fullCheck,
+ maxPathLength: PathInternal.MaxShortPath,
+ expandShortPaths: true);
+#else
+ return Path.NormalizePath(
+ path: path,
+ fullCheck: fullCheck,
+ expandShortPaths: true);
+#endif
+ }
+
+#if FEATURE_APTCA
+ // Called from DomainAssembly in Conditional APTCA cases
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+ [SecuritySafeCritical]
+ private bool IsAssemblyOnAptcaVisibleList(RuntimeAssembly assembly)
+ {
+ if (_aptcaVisibleAssemblies == null)
+ return false;
+
+ AssemblyName assemblyName = assembly.GetName();
+ String name = assemblyName.GetNameWithPublicKey();
+
+ name = name.ToUpperInvariant();
+
+ int index = Array.BinarySearch<string>(_aptcaVisibleAssemblies, name,
+ StringComparer.OrdinalIgnoreCase);
+ return (index >=0);
+
+ }
+
+ //Used to binary search the list of C-APTCA strings for an AssemblyName. It compares assembly name
+ //and public key token.
+ private class CAPTCASearcher : IComparer
+ {
+ int IComparer.Compare(object /*string*/lhs, object /*AssemblyName*/rhs)
+ {
+ AssemblyName captcaEntry = new AssemblyName((string)lhs);
+ AssemblyName comparand = (AssemblyName)rhs;
+ int nameComp = string.Compare(captcaEntry.Name,
+ comparand.Name,
+ StringComparison.OrdinalIgnoreCase);
+ if (nameComp != 0)
+ {
+ return nameComp;
+ }
+
+ //simple names match. Compare public key tokens.
+ byte[] lhsKey = captcaEntry.GetPublicKeyToken();
+ byte[] rhsKey = comparand.GetPublicKeyToken();
+
+ // We require both sides have a public key token
+ if (lhsKey == null)
+ {
+ return -1;
+ }
+ if (rhsKey == null)
+ {
+ return 1;
+ }
+ if (lhsKey.Length < rhsKey.Length)
+ {
+ return -1;
+ }
+ if (lhsKey.Length > rhsKey.Length)
+ {
+ return 1;
+ }
+
+ // Tokens seem valid - make sure the compare correctly
+ for (int i = 0; i < lhsKey.Length; ++i)
+ {
+ byte lhsByte = lhsKey[i];
+ byte rhsByte = rhsKey[i];
+
+ if (lhsByte < rhsByte)
+ {
+ return -1;
+ }
+ if (lhsByte > rhsByte)
+ {
+ return 1;
+ }
+ }
+
+ //They match.
+ return 0;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe bool IsAssemblyOnAptcaVisibleListRaw(char * namePtr, int nameLen, byte * keyTokenPtr,
+ int keyTokenLen)
+ {
+ //This version is used for checking ngen dependencies against the C-APTCA list. It lets us
+ //reject ngen images that depend on an assembly that has been disabled in the current domain.
+ //Since we only have the public key token in the ngen image, we'll check against that. The
+ //rationale is that if you have a public key token collision in your process you have many
+ //problems. Since the source of this public key token is an ngen image for a full trust
+ //assembly, there is essentially no risk to the reduced check.
+ if (_aptcaVisibleAssemblies == null)
+ return false;
+
+ string name = new string(namePtr, 0, nameLen);
+ byte[] keyToken = new byte[keyTokenLen];
+ for( int i = 0; i < keyToken.Length; ++i )
+ keyToken[i] = keyTokenPtr[i];
+
+ AssemblyName asmName = new AssemblyName();
+ asmName.Name = name;
+ asmName.SetPublicKeyToken(keyToken);
+ try
+ {
+ int index = Array.BinarySearch(_aptcaVisibleAssemblies, asmName, new CAPTCASearcher());
+ return (index >= 0);
+ }
+ catch (InvalidOperationException) { /* Can happen for poorly formed assembly names */ return false; }
+ }
+
+#endif
+
+ // This routine is called from unmanaged code to
+ // set the default fusion context.
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupDomain(bool allowRedirects, String path, String configFile, String[] propertyNames, String[] propertyValues)
+ {
+ // It is possible that we could have multiple threads initializing
+ // the default domain. We will just take the winner of these two.
+ // (eg. one thread doing a com call and another doing attach for IJW)
+ lock (this) {
+ if(_FusionStore == null) {
+ AppDomainSetup setup = new AppDomainSetup();
+#if FEATURE_CORECLR
+ // always use internet permission set
+ setup.InternalSetApplicationTrust("Internet");
+#endif // FEATURE_CORECLR
+#if FEATURE_FUSION
+ setup.SetupDefaults(RuntimeEnvironment.GetModuleFileName(), imageLocationAlreadyNormalized : true);
+ if(path != null)
+ setup.Value[(int) AppDomainSetup.LoaderInformation.ApplicationBaseValue] = path;
+ if(configFile != null)
+ setup.Value[(int) AppDomainSetup.LoaderInformation.ConfigurationFileValue] = configFile;
+
+ // Default fusion context starts with binding redirects turned off.
+ if (!allowRedirects)
+ setup.DisallowBindingRedirects = true;
+#endif
+
+#if !FEATURE_CORECLR
+ if (propertyNames != null) {
+ BCLDebug.Assert(propertyValues != null, "propertyValues != null");
+ BCLDebug.Assert(propertyNames.Length == propertyValues.Length, "propertyNames.Length == propertyValues.Length");
+
+ for (int i = 0; i < propertyNames.Length; ++i) {
+ if (String.Equals(propertyNames[i], "PARTIAL_TRUST_VISIBLE_ASSEMBLIES", StringComparison.Ordinal)) {
+ // The value of the PARTIAL_TRUST_VISIBLE_ASSEMBLIES property is a semicolon
+ // delimited list of assembly names to add to the
+ // PartialTrustVisibleAssemblies setting of the domain setup
+ if (propertyValues[i] != null) {
+ if (propertyValues[i].Length > 0) {
+ setup.PartialTrustVisibleAssemblies = propertyValues[i].Split(';');
+ }
+ else {
+ setup.PartialTrustVisibleAssemblies = new string[0];
+ }
+ }
+ }
+ else {
+ // In v4 we disallow anything but PARTIAL_TRUST_VISIBLE_ASSEMBLIES to come
+ // in via the default domain properties. That restriction could be lifted
+ // in a future release, at which point this assert should be removed.
+ //
+ // This should be kept in sync with the real externally facing filter code
+ // in CorHost2::SetPropertiesForDefaultAppDomain
+ BCLDebug.Assert(false, "Unexpected default domain property");
+ }
+ }
+ }
+#endif // !FEATURE_CORECLR
+
+#if FEATURE_APTCA
+ // Propigate the set of conditional APTCA assemblies that will be used in the default
+ // domain onto the domain itself and also into the VM
+ PartialTrustVisibleAssemblies = setup.PartialTrustVisibleAssemblies;
+#endif // FEATURE_APTCA
+
+ SetupFusionStore(setup, null);
+ }
+ }
+ }
+
+#if FEATURE_LOADER_OPTIMIZATION
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetupLoaderOptimization(LoaderOptimization policy)
+ {
+ if(policy != LoaderOptimization.NotSpecified) {
+ Contract.Assert(FusionStore.LoaderOptimization == LoaderOptimization.NotSpecified,
+ "It is illegal to change the Loader optimization on a domain");
+
+ FusionStore.LoaderOptimization = policy;
+ UpdateLoaderOptimization(FusionStore.LoaderOptimization);
+ }
+ }
+#endif
+
+#if FEATURE_FUSION
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetFusionContext();
+#endif // FEATURE_FUSION
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetSecurityDescriptor();
+
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern AppDomain nCreateDomain(String friendlyName,
+ AppDomainSetup setup,
+ Evidence providedSecurityInfo,
+ Evidence creatorsSecurityInfo,
+ IntPtr parentSecurityDescriptor);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern ObjRef nCreateInstance(String friendlyName,
+ AppDomainSetup setup,
+ Evidence providedSecurityInfo,
+ Evidence creatorsSecurityInfo,
+ IntPtr parentSecurityDescriptor);
+#endif
+
+ [SecurityCritical]
+ private void SetupDomainSecurity(Evidence appDomainEvidence,
+ IntPtr creatorsSecurityDescriptor,
+ bool publishAppDomain)
+ {
+ Evidence stackEvidence = appDomainEvidence;
+ SetupDomainSecurity(GetNativeHandle(),
+ JitHelpers.GetObjectHandleOnStack(ref stackEvidence),
+ creatorsSecurityDescriptor,
+ publishAppDomain);
+
+ }
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void SetupDomainSecurity(AppDomainHandle appDomain,
+ ObjectHandleOnStack appDomainEvidence,
+ IntPtr creatorsSecurityDescriptor,
+ [MarshalAs(UnmanagedType.Bool)] bool publishAppDomain);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void nSetupFriendlyName(string friendlyName);
+
+#if FEATURE_COMINTEROP
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void nSetDisableInterfaceCache();
+#endif // FEATURE_COMINTEROP
+
+#if FEATURE_LOADER_OPTIMIZATION
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void UpdateLoaderOptimization(LoaderOptimization optimization);
+#endif
+
+#if FEATURE_FUSION
+ //
+ // This is just designed to prevent compiler warnings.
+ // This field is used from native, but we need to prevent the compiler warnings.
+ //
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.SetShadowCopyPath has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyDirectories instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetShadowCopyPath(String path)
+ {
+ InternalSetShadowCopyPath(path);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.SetShadowCopyFiles has been deprecated. Please investigate the use of AppDomainSetup.ShadowCopyFiles instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetShadowCopyFiles()
+ {
+ InternalSetShadowCopyFiles();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("AppDomain.SetDynamicBase has been deprecated. Please investigate the use of AppDomainSetup.DynamicBase instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetDynamicBase(String path)
+ {
+ InternalSetDynamicBase(path);
+ }
+#endif // FEATURE_FUSION
+
+ public AppDomainSetup SetupInformation
+ {
+ get {
+ return new AppDomainSetup(FusionStore,true);
+ }
+ }
+
+#if FEATURE_FUSION
+ [System.Security.SecurityCritical] // auto-generated
+ internal void InternalSetShadowCopyPath(String path)
+ {
+ if (path != null)
+ {
+ IntPtr fusionContext = GetFusionContext();
+ AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.ShadowCopyDirectoriesKey, path);
+ }
+ FusionStore.ShadowCopyDirectories = path;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void InternalSetShadowCopyFiles()
+ {
+ IntPtr fusionContext = GetFusionContext();
+ AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.ShadowCopyFilesKey, "true");
+ FusionStore.ShadowCopyFiles = "true";
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void InternalSetCachePath(String path)
+ {
+ FusionStore.CachePath = path;
+ if (FusionStore.Value[(int) AppDomainSetup.LoaderInformation.CachePathValue] != null)
+ {
+ IntPtr fusionContext = GetFusionContext();
+ AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.CachePathKey,
+ FusionStore.Value[(int) AppDomainSetup.LoaderInformation.CachePathValue]);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void InternalSetPrivateBinPath(String path)
+ {
+ IntPtr fusionContext = GetFusionContext();
+ AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.PrivateBinPathKey, path);
+ FusionStore.PrivateBinPath = path;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void InternalSetDynamicBase(String path)
+ {
+ FusionStore.DynamicBase = path;
+ if (FusionStore.Value[(int) AppDomainSetup.LoaderInformation.DynamicBaseValue] != null)
+ {
+ IntPtr fusionContext = GetFusionContext();
+ AppDomainSetup.UpdateContextProperty(fusionContext, AppDomainSetup.DynamicBaseKey,
+ FusionStore.Value[(int) AppDomainSetup.LoaderInformation.DynamicBaseValue]);
+ }
+ }
+#endif // FEATURE_FUSION
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern String IsStringInterned(String str);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern String GetOrInternString(String str);
+
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void GetGrantSet(AppDomainHandle domain, ObjectHandleOnStack retGrantSet);
+
+#if FEATURE_CAS_POLICY
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetIsLegacyCasPolicyEnabled(AppDomainHandle domain);
+#endif // FEATURE_CAS_POLICY
+
+ public PermissionSet PermissionSet
+ {
+ // SecurityCritical because permissions can contain sensitive information such as paths
+ [SecurityCritical]
+ get
+ {
+ PermissionSet grantSet = null;
+ GetGrantSet(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref grantSet));
+
+ if (grantSet != null)
+ {
+ return grantSet.Copy();
+ }
+ else
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ }
+ }
+
+ public bool IsFullyTrusted
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ PermissionSet grantSet = null;
+ GetGrantSet(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref grantSet));
+
+ return grantSet == null || grantSet.IsUnrestricted();
+ }
+ }
+
+ public bool IsHomogenous
+ {
+ get
+ {
+ // Homogenous AppDomains always have an ApplicationTrust associated with them
+ return _IsFastFullTrustDomain || _applicationTrust != null;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ internal bool IsLegacyCasPolicyEnabled
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ return GetIsLegacyCasPolicyEnabled(GetNativeHandle());
+ }
+ }
+
+ // Determine what this homogenous domain thinks the grant set should be for a specific set of evidence
+ [SecuritySafeCritical]
+ internal PermissionSet GetHomogenousGrantSet(Evidence evidence)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(IsHomogenous);
+ Contract.Assert(evidence.GetHostEvidence<GacInstalled>() == null);
+
+ if (_IsFastFullTrustDomain)
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+
+ // If the ApplicationTrust's full trust list calls out the assembly, then it is fully trusted
+ if (evidence.GetDelayEvaluatedHostEvidence<StrongName>() != null)
+ {
+ foreach (StrongName fullTrustAssembly in ApplicationTrust.FullTrustAssemblies)
+ {
+ StrongNameMembershipCondition sn = new StrongNameMembershipCondition(fullTrustAssembly.PublicKey,
+ fullTrustAssembly.Name,
+ fullTrustAssembly.Version);
+
+ object usedEvidence = null;
+ if ((sn as IReportMatchMembershipCondition).Check(evidence, out usedEvidence))
+ {
+ IDelayEvaluatedEvidence delayEvidence = usedEvidence as IDelayEvaluatedEvidence;
+ if (usedEvidence != null)
+ {
+ delayEvidence.MarkUsed();
+ }
+
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ }
+ }
+
+ // Otherwise, the grant set is just the default grant set
+ return ApplicationTrust.DefaultGrantSet.PermissionSet.Copy();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void nChangeSecurityPolicy();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.MayCorruptAppDomain, Cer.MayFail)]
+ internal static extern void nUnload(Int32 domainInternal);
+
+ public Object CreateInstanceAndUnwrap(String assemblyName,
+ String typeName)
+ {
+ ObjectHandle oh = CreateInstance(assemblyName, typeName);
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+
+ public Object CreateInstanceAndUnwrap(String assemblyName,
+ String typeName,
+ Object[] activationAttributes)
+ {
+ ObjectHandle oh = CreateInstance(assemblyName, typeName, activationAttributes);
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceAndUnwrap which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public Object CreateInstanceAndUnwrap(String assemblyName,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+ {
+#pragma warning disable 618
+ ObjectHandle oh = CreateInstance(assemblyName, typeName, ignoreCase, bindingAttr,
+ binder, args, culture, activationAttributes, securityAttributes);
+#pragma warning restore 618
+
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+ public object CreateInstanceAndUnwrap(string assemblyName,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ ObjectHandle oh = CreateInstance(assemblyName,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+
+ if (oh == null)
+ {
+ return null;
+ }
+
+ return oh.Unwrap();
+ }
+
+ // The first parameter should be named assemblyFile, but it was incorrectly named in a previous
+ // release, and the compatibility police won't let us change the name now.
+ public Object CreateInstanceFromAndUnwrap(String assemblyName,
+ String typeName)
+ {
+ ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName);
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+
+ // The first parameter should be named assemblyFile, but it was incorrectly named in a previous
+ // release, and the compatibility police won't let us change the name now.
+ public Object CreateInstanceFromAndUnwrap(String assemblyName,
+ String typeName,
+ Object[] activationAttributes)
+ {
+ ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName, activationAttributes);
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+
+ // The first parameter should be named assemblyFile, but it was incorrectly named in a previous
+ // release, and the compatibility police won't let us change the name now.
+ [Obsolete("Methods which use evidence to sandbox are obsolete and will be removed in a future release of the .NET Framework. Please use an overload of CreateInstanceFromAndUnwrap which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public Object CreateInstanceFromAndUnwrap(String assemblyName,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes)
+ {
+#pragma warning disable 618
+ ObjectHandle oh = CreateInstanceFrom(assemblyName, typeName, ignoreCase, bindingAttr,
+ binder, args, culture, activationAttributes, securityAttributes);
+#pragma warning restore 618
+
+ if (oh == null)
+ return null;
+
+ return oh.Unwrap();
+ } // CreateInstanceAndUnwrap
+
+ public object CreateInstanceFromAndUnwrap(string assemblyFile,
+ string typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ object[] args,
+ CultureInfo culture,
+ object[] activationAttributes)
+ {
+ ObjectHandle oh = CreateInstanceFrom(assemblyFile,
+ typeName,
+ ignoreCase,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+ if (oh == null)
+ {
+ return null;
+ }
+
+ return oh.Unwrap();
+ }
+
+ public Int32 Id
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get {
+ return GetId();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern Int32 GetId();
+
+ internal const Int32 DefaultADID = 1;
+
+ public bool IsDefaultAppDomain()
+ {
+ if (GetId()==DefaultADID)
+ return true;
+ return false;
+ }
+
+#if FEATURE_FUSION
+ private static AppDomainSetup InternalCreateDomainSetup(String imageLocation)
+ {
+ int i = imageLocation.LastIndexOf('\\');
+
+ 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));
+ config.Append(AppDomainSetup.ConfigurationExtension);
+ info.ConfigurationFile = config.ToString();
+
+ return info;
+ }
+
+ // Used by the validator for testing but not executing an assembly
+ private static AppDomain InternalCreateDomain(String imageLocation)
+ {
+ AppDomainSetup info = InternalCreateDomainSetup(imageLocation);
+ return CreateDomain("Validator",
+ null,
+ info);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void InternalSetDomainContext(String imageLocation)
+ {
+ SetupFusionStore(InternalCreateDomainSetup(imageLocation), null);
+ }
+#endif
+
+#if FEATURE_APPDOMAIN_RESOURCE_MONITORING
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nEnableMonitoring();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool nMonitoringIsEnabled();
+
+ // return -1 if ARM is not supported.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Int64 nGetTotalProcessorTime();
+
+ // return -1 if ARM is not supported.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Int64 nGetTotalAllocatedMemorySize();
+
+ // return -1 if ARM is not supported.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Int64 nGetLastSurvivedMemorySize();
+
+ // return -1 if ARM is not supported.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Int64 nGetLastSurvivedProcessMemorySize();
+
+ public static bool MonitoringIsEnabled
+ {
+ [System.Security.SecurityCritical]
+ get {
+ return nMonitoringIsEnabled();
+ }
+
+ [System.Security.SecurityCritical]
+ set {
+ if (value == false)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeTrue"));
+ }
+ else
+ {
+ nEnableMonitoring();
+ }
+ }
+ }
+
+ // Gets the total processor time for this AppDomain.
+ // Throws NotSupportedException if ARM is not enabled.
+ public TimeSpan MonitoringTotalProcessorTime
+ {
+ [System.Security.SecurityCritical]
+ get {
+ Int64 i64ProcessorTime = nGetTotalProcessorTime();
+ if (i64ProcessorTime == -1)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM"));
+ }
+ return new TimeSpan(i64ProcessorTime);
+ }
+ }
+
+ // Gets the number of bytes allocated in this AppDomain since
+ // the AppDomain was created.
+ // Throws NotSupportedException if ARM is not enabled.
+ public Int64 MonitoringTotalAllocatedMemorySize
+ {
+ [System.Security.SecurityCritical]
+ get {
+ Int64 i64AllocatedMemory = nGetTotalAllocatedMemorySize();
+ if (i64AllocatedMemory == -1)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM"));
+ }
+ return i64AllocatedMemory;
+ }
+ }
+
+ // Gets the number of bytes survived after the last collection
+ // that are known to be held by this AppDomain. After a full
+ // collection this number is accurate and complete. After an
+ // ephemeral collection this number is potentially incomplete.
+ // Throws NotSupportedException if ARM is not enabled.
+ public Int64 MonitoringSurvivedMemorySize
+ {
+ [System.Security.SecurityCritical]
+ get {
+ Int64 i64LastSurvivedMemory = nGetLastSurvivedMemorySize();
+ if (i64LastSurvivedMemory == -1)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM"));
+ }
+ return i64LastSurvivedMemory;
+ }
+ }
+
+ // Gets the total bytes survived from the last collection. After
+ // a full collection this number represents the number of the bytes
+ // being held live in managed heaps. (This number should be close
+ // to the number obtained from GC.GetTotalMemory for a full collection.)
+ // After an ephemeral collection this number represents the number
+ // of bytes being held live in ephemeral generations.
+ // Throws NotSupportedException if ARM is not enabled.
+ public static Int64 MonitoringSurvivedProcessMemorySize
+ {
+ [System.Security.SecurityCritical]
+ get {
+ Int64 i64LastSurvivedProcessMemory = nGetLastSurvivedProcessMemorySize();
+ if (i64LastSurvivedProcessMemory == -1)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WithoutARM"));
+ }
+ return i64LastSurvivedProcessMemory;
+ }
+ }
+#endif
+
+#if !FEATURE_CORECLR
+ // this method is required so Object.GetType is not made virtual by the compiler
+ // _AppDomain.GetType()
+ public new Type GetType()
+ {
+ return base.GetType();
+ }
+
+ void _AppDomain.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AppDomain.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AppDomain.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _AppDomain.Invoke in VM\DangerousAPIs.h and
+ // include _AppDomain in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _AppDomain.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ // CallBacks provide a facility to request execution of some code
+ // in another context/appDomain.
+ // CrossAppDomainDelegate type is defined for appdomain call backs.
+ // The delegate used to request a callbak through the DoCallBack method
+ // must be of CrossContextDelegate type.
+#if FEATURE_REMOTING
+[System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void CrossAppDomainDelegate();
+#endif
+
+ /// <summary>
+ /// Handle used to marshal an AppDomain to the VM (eg QCall). When marshaled via a QCall, the target
+ /// method in the VM will recieve a QCall::AppDomainHandle parameter.
+ /// </summary>
+ internal struct AppDomainHandle
+ {
+ private IntPtr m_appDomainHandle;
+
+ // Note: generall an AppDomainHandle should not be directly constructed, instead the
+ // code:System.AppDomain.GetNativeHandle method should be called to get the handle for a specific
+ // AppDomain.
+ internal AppDomainHandle(IntPtr domainHandle)
+ {
+ m_appDomainHandle = domainHandle;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/AppDomainAttributes.cs b/src/mscorlib/src/System/AppDomainAttributes.cs
new file mode 100644
index 0000000000..0980b5fe90
--- /dev/null
+++ b/src/mscorlib/src/System/AppDomainAttributes.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: For AppDomain-related custom attributes.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum LoaderOptimization
+ {
+ NotSpecified = 0,
+ SingleDomain = 1,
+ MultiDomain = 2,
+ MultiDomainHost = 3,
+ [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ DomainMask = 3,
+ [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ DisallowBindings = 4
+ }
+
+ [AttributeUsage (AttributeTargets.Method)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class LoaderOptimizationAttribute : Attribute
+ {
+ internal byte _val;
+
+ public LoaderOptimizationAttribute(byte value)
+ {
+ _val = value;
+ }
+ public LoaderOptimizationAttribute(LoaderOptimization value)
+ {
+ _val = (byte) value;
+ }
+ public LoaderOptimization Value
+ { get {return (LoaderOptimization) _val;} }
+ }
+}
+
diff --git a/src/mscorlib/src/System/AppDomainManager.cs b/src/mscorlib/src/System/AppDomainManager.cs
new file mode 100644
index 0000000000..291099e199
--- /dev/null
+++ b/src/mscorlib/src/System/AppDomainManager.cs
@@ -0,0 +1,220 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+// An AppDomainManager gives a hosting application the chance to
+// participate in the creation and control the settings of new AppDomains.
+//
+
+namespace System {
+ using System.Collections;
+ using System.Globalization;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Security.Policy;
+ using System.Threading;
+#if FEATURE_CLICKONCE
+ using System.Runtime.Hosting;
+#endif
+ using System.Runtime.Versioning;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+#if FEATURE_APPDOMAINMANAGER_INITOPTIONS
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum AppDomainManagerInitializationOptions {
+ None = 0x0000,
+ RegisterWithHost = 0x0001
+ }
+#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags = SecurityPermissionFlag.Infrastructure)]
+#endif
+#if FEATURE_REMOTING
+ public class AppDomainManager : MarshalByRefObject {
+#else // FEATURE_REMOTING
+ public class AppDomainManager {
+#endif // FEATURE_REMOTING
+ public AppDomainManager () {}
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated
+ public virtual AppDomain CreateDomain (string friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup appDomainInfo) {
+ return CreateDomainHelper(friendlyName, securityInfo, appDomainInfo);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlAppDomain = true)]
+ protected static AppDomain CreateDomainHelper (string friendlyName,
+ Evidence securityInfo,
+ AppDomainSetup appDomainInfo) {
+ if (friendlyName == null)
+ throw new ArgumentNullException("friendlyName", Environment.GetResourceString("ArgumentNull_String"));
+
+ Contract.EndContractBlock();
+ // If evidence is provided, we check to make sure that is allowed.
+ if (securityInfo != null) {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+
+ // Check the evidence to ensure that if it expects a sandboxed domain, it actually gets one.
+ AppDomain.CheckDomainCreationEvidence(appDomainInfo, securityInfo);
+ }
+
+ if (appDomainInfo == null) {
+ appDomainInfo = new AppDomainSetup();
+ }
+
+ // If there was no specified AppDomainManager for the new domain, default it to being the same
+ // as the current domain's AppDomainManager.
+ if (appDomainInfo.AppDomainManagerAssembly == null || appDomainInfo.AppDomainManagerType == null) {
+ string inheritedDomainManagerAssembly;
+ string inheritedDomainManagerType;
+
+ AppDomain.CurrentDomain.GetAppDomainManagerType(out inheritedDomainManagerAssembly,
+ out inheritedDomainManagerType);
+
+ if (appDomainInfo.AppDomainManagerAssembly == null) {
+ appDomainInfo.AppDomainManagerAssembly = inheritedDomainManagerAssembly;
+ }
+ if (appDomainInfo.AppDomainManagerType == null) {
+ appDomainInfo.AppDomainManagerType = inheritedDomainManagerType;
+ }
+ }
+
+ // If there was no specified TargetFrameworkName for the new domain, default it to the current domain's.
+ if (appDomainInfo.TargetFrameworkName == null)
+ appDomainInfo.TargetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName();
+
+ return AppDomain.nCreateDomain(friendlyName,
+ appDomainInfo,
+ securityInfo,
+ securityInfo == null ? AppDomain.CurrentDomain.InternalEvidence : null,
+ AppDomain.CurrentDomain.GetSecurityDescriptor());
+ }
+#endif // FEATURE_REMOTING
+
+ [System.Security.SecurityCritical]
+ public virtual void InitializeNewDomain (AppDomainSetup appDomainInfo) {
+ // By default, InitializeNewDomain does nothing. AppDomain.CreateAppDomainManager relies on this fact.
+ }
+
+#if FEATURE_APPDOMAINMANAGER_INITOPTIONS
+
+ private AppDomainManagerInitializationOptions m_flags = AppDomainManagerInitializationOptions.None;
+ public AppDomainManagerInitializationOptions InitializationFlags {
+ get {
+ return m_flags;
+ }
+ set {
+ m_flags = value;
+ }
+ }
+#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS
+
+#if FEATURE_CLICKONCE
+ private ApplicationActivator m_appActivator = null;
+ public virtual ApplicationActivator ApplicationActivator {
+ get {
+ if (m_appActivator == null)
+ m_appActivator = new ApplicationActivator();
+ return m_appActivator;
+ }
+ }
+#endif //#if FEATURE_CLICKONCE
+
+#if FEATURE_CAS_POLICY
+ public virtual HostSecurityManager HostSecurityManager {
+ get {
+ return null;
+ }
+ }
+
+ public virtual HostExecutionContextManager HostExecutionContextManager {
+ get {
+ // By default, the AppDomainManager returns the HostExecutionContextManager.
+ return HostExecutionContextManager.GetInternalHostExecutionContextManager();
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void GetEntryAssembly(ObjectHandleOnStack retAssembly);
+
+ private Assembly m_entryAssembly = null;
+ public virtual Assembly EntryAssembly {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ // The default AppDomainManager sets the EntryAssembly depending on whether the
+ // AppDomain is a manifest application domain or not. In the first case, we parse
+ // the application manifest to find out the entry point assembly and return that assembly.
+ // In the second case, we maintain the old behavior by calling GetEntryAssembly().
+ if (m_entryAssembly == null)
+ {
+
+#if FEATURE_CLICKONCE
+ AppDomain domain = AppDomain.CurrentDomain;
+ if (domain.IsDefaultAppDomain() && domain.ActivationContext != null) {
+ ManifestRunner runner = new ManifestRunner(domain, domain.ActivationContext);
+ m_entryAssembly = runner.EntryAssembly;
+ } else
+#endif //#if FEATURE_CLICKONCE
+ {
+ RuntimeAssembly entryAssembly = null;
+ GetEntryAssembly(JitHelpers.GetObjectHandleOnStack(ref entryAssembly));
+ m_entryAssembly = entryAssembly;
+ }
+ }
+ return m_entryAssembly;
+ }
+ }
+
+ internal static AppDomainManager CurrentAppDomainManager {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ return AppDomain.CurrentDomain.DomainManager;
+ }
+ }
+
+ public virtual bool CheckSecuritySettings (SecurityState state)
+ {
+ return false;
+ }
+
+#if FEATURE_APPDOMAINMANAGER_INITOPTIONS
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool HasHost();
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void RegisterWithHost(IntPtr appDomainManager);
+
+ internal void RegisterWithHost() {
+ if (HasHost()) {
+ IntPtr punkAppDomainManager = IntPtr.Zero;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ punkAppDomainManager = Marshal.GetIUnknownForObject(this);
+ RegisterWithHost(punkAppDomainManager);
+ }
+ finally {
+ if (!punkAppDomainManager.IsNull()) {
+ Marshal.Release(punkAppDomainManager);
+ }
+ }
+ }
+ }
+#endif // FEATURE_APPDOMAINMANAGER_INITOPTIONS
+ }
+}
diff --git a/src/mscorlib/src/System/AppDomainSetup.cs b/src/mscorlib/src/System/AppDomainSetup.cs
new file mode 100644
index 0000000000..f1057da082
--- /dev/null
+++ b/src/mscorlib/src/System/AppDomainSetup.cs
@@ -0,0 +1,1444 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Class: AppDomainSetup
+**
+** Purpose: Defines the settings that the loader uses to find assemblies in an
+** AppDomain
+**
+** Date: Dec 22, 2000
+**
+=============================================================================*/
+
+namespace System {
+ using System;
+#if FEATURE_CLICKONCE
+ using System.Deployment.Internal.Isolation;
+ using System.Deployment.Internal.Isolation.Manifest;
+ using System.Runtime.Hosting;
+#endif
+ using System.Runtime.CompilerServices;
+ using System.Runtime;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Security.Policy;
+ using System.Globalization;
+ using Path = System.IO.Path;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AppDomainSetup :
+ IAppDomainSetup
+ {
+ [Serializable]
+ internal enum LoaderInformation
+ {
+ // If you add a new value, add the corresponding property
+ // to AppDomain.GetData() and SetData()'s switch statements,
+ // as well as fusionsetup.h.
+ ApplicationBaseValue = 0, // LOADER_APPLICATION_BASE
+ ConfigurationFileValue = 1, // LOADER_CONFIGURATION_BASE
+ DynamicBaseValue = 2, // LOADER_DYNAMIC_BASE
+ DevPathValue = 3, // LOADER_DEVPATH
+ ApplicationNameValue = 4, // LOADER_APPLICATION_NAME
+ PrivateBinPathValue = 5, // LOADER_PRIVATE_PATH
+ PrivateBinPathProbeValue = 6, // LOADER_PRIVATE_BIN_PATH_PROBE
+ ShadowCopyDirectoriesValue = 7, // LOADER_SHADOW_COPY_DIRECTORIES
+ ShadowCopyFilesValue = 8, // LOADER_SHADOW_COPY_FILES
+ CachePathValue = 9, // LOADER_CACHE_PATH
+ LicenseFileValue = 10, // LOADER_LICENSE_FILE
+ DisallowPublisherPolicyValue = 11, // LOADER_DISALLOW_PUBLISHER_POLICY
+ DisallowCodeDownloadValue = 12, // LOADER_DISALLOW_CODE_DOWNLOAD
+ DisallowBindingRedirectsValue = 13, // LOADER_DISALLOW_BINDING_REDIRECTS
+ DisallowAppBaseProbingValue = 14, // LOADER_DISALLOW_APPBASE_PROBING
+ ConfigurationBytesValue = 15, // LOADER_CONFIGURATION_BYTES
+ LoaderMaximum = 18 // LOADER_MAXIMUM
+ }
+
+ // Constants from fusionsetup.h.
+ private const string LOADER_OPTIMIZATION = "LOADER_OPTIMIZATION";
+ private const string CONFIGURATION_EXTENSION = ".config";
+ private const string APPENV_RELATIVEPATH = "RELPATH";
+ private const string MACHINE_CONFIGURATION_FILE = "config\\machine.config";
+ private const string ACTAG_HOST_CONFIG_FILE = "HOST_CONFIG";
+
+#if FEATURE_FUSION
+ private const string LICENSE_FILE = "LICENSE_FILE";
+#endif
+
+ // Constants from fusionpriv.h
+ private const string ACTAG_APP_CONFIG_FILE = "APP_CONFIG_FILE";
+ private const string ACTAG_MACHINE_CONFIG = "MACHINE_CONFIG";
+ private const string ACTAG_APP_BASE_URL = "APPBASE";
+ private const string ACTAG_APP_NAME = "APP_NAME";
+ private const string ACTAG_BINPATH_PROBE_ONLY = "BINPATH_PROBE_ONLY";
+ private const string ACTAG_APP_CACHE_BASE = "CACHE_BASE";
+ private const string ACTAG_DEV_PATH = "DEV_PATH";
+ private const string ACTAG_APP_DYNAMIC_BASE = "DYNAMIC_BASE";
+ private const string ACTAG_FORCE_CACHE_INSTALL = "FORCE_CACHE_INSTALL";
+ private const string ACTAG_APP_PRIVATE_BINPATH = "PRIVATE_BINPATH";
+ private const string ACTAG_APP_SHADOW_COPY_DIRS = "SHADOW_COPY_DIRS";
+ private const string ACTAG_DISALLOW_APPLYPUBLISHERPOLICY = "DISALLOW_APP";
+ private const string ACTAG_CODE_DOWNLOAD_DISABLED = "CODE_DOWNLOAD_DISABLED";
+ private const string ACTAG_DISALLOW_APP_BINDING_REDIRECTS = "DISALLOW_APP_REDIRECTS";
+ private const string ACTAG_DISALLOW_APP_BASE_PROBING = "DISALLOW_APP_BASE_PROBING";
+ private const string ACTAG_APP_CONFIG_BLOB = "APP_CONFIG_BLOB";
+
+ // This class has an unmanaged representation so be aware you will need to make edits in vm\object.h if you change the order
+ // of these fields or add new ones.
+
+ private string[] _Entries;
+ private LoaderOptimization _LoaderOptimization;
+#pragma warning disable 169
+ private String _AppBase; // for compat with v1.1
+#pragma warning restore 169
+ [OptionalField(VersionAdded = 2)]
+ private AppDomainInitializer _AppDomainInitializer;
+ [OptionalField(VersionAdded = 2)]
+ private string[] _AppDomainInitializerArguments;
+#if FEATURE_CLICKONCE
+ [OptionalField(VersionAdded = 2)]
+ private ActivationArguments _ActivationArguments;
+#endif
+#if FEATURE_CORECLR
+ // On the CoreCLR, this contains just the name of the permission set that we install in the new appdomain.
+ // Not the ToXml().ToString() of an ApplicationTrust object.
+#endif
+ [OptionalField(VersionAdded = 2)]
+ private string _ApplicationTrust;
+ [OptionalField(VersionAdded = 2)]
+ private byte[] _ConfigurationBytes;
+#if FEATURE_COMINTEROP
+ [OptionalField(VersionAdded = 3)]
+ private bool _DisableInterfaceCache = false;
+#endif // FEATURE_COMINTEROP
+ [OptionalField(VersionAdded = 4)]
+ private string _AppDomainManagerAssembly;
+ [OptionalField(VersionAdded = 4)]
+ private string _AppDomainManagerType;
+
+#if FEATURE_APTCA
+ [OptionalField(VersionAdded = 4)]
+ private string[] _AptcaVisibleAssemblies;
+#endif
+
+ // A collection of strings used to indicate which breaking changes shouldn't be applied
+ // to an AppDomain. We only use the keys, the values are ignored.
+ [OptionalField(VersionAdded = 4)]
+ private Dictionary<string, object> _CompatFlags;
+
+ [OptionalField(VersionAdded = 5)] // This was added in .NET FX v4.5
+ private String _TargetFrameworkName;
+
+#if !FEATURE_CORECLR
+ [NonSerialized]
+ internal AppDomainSortingSetupInfo _AppDomainSortingSetupInfo;
+#endif
+
+ [OptionalField(VersionAdded = 5)] // This was added in .NET FX v4.5
+ private bool _CheckedForTargetFrameworkName;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ [OptionalField(VersionAdded = 5)] // This was added in .NET FX v4.5
+ private bool _UseRandomizedStringHashing;
+#endif
+
+ [SecuritySafeCritical]
+ internal AppDomainSetup(AppDomainSetup copy, bool copyDomainBoundData)
+ {
+ string[] mine = Value;
+ if(copy != null) {
+ string[] other = copy.Value;
+ int mineSize = _Entries.Length;
+ int otherSize = other.Length;
+ int size = (otherSize < mineSize) ? otherSize : mineSize;
+
+ for (int i = 0; i < size; i++)
+ mine[i] = other[i];
+
+ if (size < mineSize)
+ {
+ // This case can happen when the copy is a deserialized version of
+ // an AppDomainSetup object serialized by Everett.
+ for (int i = size; i < mineSize; i++)
+ mine[i] = null;
+ }
+
+ _LoaderOptimization = copy._LoaderOptimization;
+
+ _AppDomainInitializerArguments = copy.AppDomainInitializerArguments;
+#if FEATURE_CLICKONCE
+ _ActivationArguments = copy.ActivationArguments;
+#endif
+ _ApplicationTrust = copy._ApplicationTrust;
+ if (copyDomainBoundData)
+ _AppDomainInitializer = copy.AppDomainInitializer;
+ else
+ _AppDomainInitializer = null;
+
+ _ConfigurationBytes = copy.GetConfigurationBytes();
+#if FEATURE_COMINTEROP
+ _DisableInterfaceCache = copy._DisableInterfaceCache;
+#endif // FEATURE_COMINTEROP
+ _AppDomainManagerAssembly = copy.AppDomainManagerAssembly;
+ _AppDomainManagerType = copy.AppDomainManagerType;
+#if FEATURE_APTCA
+ _AptcaVisibleAssemblies = copy.PartialTrustVisibleAssemblies;
+#endif
+
+ if (copy._CompatFlags != null)
+ {
+ SetCompatibilitySwitches(copy._CompatFlags.Keys);
+ }
+
+#if !FEATURE_CORECLR
+ if(copy._AppDomainSortingSetupInfo != null)
+ {
+ _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo(copy._AppDomainSortingSetupInfo);
+ }
+#endif
+ _TargetFrameworkName = copy._TargetFrameworkName;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ _UseRandomizedStringHashing = copy._UseRandomizedStringHashing;
+#endif
+
+ }
+ else
+ _LoaderOptimization = LoaderOptimization.NotSpecified;
+ }
+
+ public AppDomainSetup()
+ {
+ _LoaderOptimization = LoaderOptimization.NotSpecified;
+ }
+
+#if FEATURE_CLICKONCE
+ // Creates an AppDomainSetup object from an application identity.
+ public AppDomainSetup (ActivationContext activationContext) : this (new ActivationArguments(activationContext)) {}
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public AppDomainSetup (ActivationArguments activationArguments) {
+ if (activationArguments == null)
+ throw new ArgumentNullException("activationArguments");
+ Contract.EndContractBlock();
+
+ _LoaderOptimization = LoaderOptimization.NotSpecified;
+ ActivationArguments = activationArguments;
+
+ Contract.Assert(activationArguments.ActivationContext != null, "Cannot set base directory without activation context");
+ string entryPointPath = CmsUtils.GetEntryPointFullPath(activationArguments);
+ if (!String.IsNullOrEmpty(entryPointPath))
+ SetupDefaults(entryPointPath);
+ else
+ ApplicationBase = activationArguments.ActivationContext.ApplicationDirectory;
+
+ }
+#endif // !FEATURE_CLICKONCE
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void SetupDefaults(string imageLocation, bool imageLocationAlreadyNormalized = false) {
+ char[] sep = {'\\', '/'};
+ int i = imageLocation.LastIndexOfAny(sep);
+
+ if (i == -1) {
+ ApplicationName = imageLocation;
+ }
+ else {
+ ApplicationName = imageLocation.Substring(i+1);
+ string appBase = imageLocation.Substring(0, i+1);
+
+ if (imageLocationAlreadyNormalized)
+ Value[(int) LoaderInformation.ApplicationBaseValue] = appBase;
+ else
+ ApplicationBase = appBase;
+ }
+ ConfigurationFile = ApplicationName + AppDomainSetup.ConfigurationExtension;
+ }
+
+ internal string[] Value
+ {
+ get {
+ if( _Entries == null)
+ _Entries = new String[(int)LoaderInformation.LoaderMaximum];
+ return _Entries;
+ }
+ }
+
+ internal String GetUnsecureApplicationBase()
+ {
+ return Value[(int) LoaderInformation.ApplicationBaseValue];
+ }
+
+ public string AppDomainManagerAssembly
+ {
+ get { return _AppDomainManagerAssembly; }
+ set { _AppDomainManagerAssembly = value; }
+ }
+
+ public string AppDomainManagerType
+ {
+ get { return _AppDomainManagerType; }
+ set { _AppDomainManagerType = value; }
+ }
+
+#if FEATURE_APTCA
+ public string[] PartialTrustVisibleAssemblies
+ {
+ get { return _AptcaVisibleAssemblies; }
+ set {
+ if (value != null) {
+ _AptcaVisibleAssemblies = (string[])value.Clone();
+ Array.Sort<string>(_AptcaVisibleAssemblies, StringComparer.OrdinalIgnoreCase);
+ }
+ else {
+ _AptcaVisibleAssemblies = null;
+ }
+ }
+ }
+#endif
+
+ public String ApplicationBase
+ {
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [Pure]
+ get {
+ return VerifyDir(GetUnsecureApplicationBase(), false);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ set {
+ Value[(int) LoaderInformation.ApplicationBaseValue] = NormalizePath(value, false);
+ }
+ }
+
+ 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 = Security.Util.URLString.PreProcessForExtendedPathRemoval(
+ checkPathLength: false,
+ url: path,
+ isFileUrl: false);
+
+
+ int len = path.Length;
+ if (len == 0)
+ return null;
+
+#if !PLATFORM_UNIX
+ bool UNCpath = false;
+#endif // !PLATFORM_UNIX
+
+ if ((len > 7) &&
+ (String.Compare( path, 0, "file:", 0, 5, StringComparison.OrdinalIgnoreCase) == 0)) {
+ int trim;
+
+ if (path[6] == '\\') {
+ if ((path[7] == '\\') || (path[7] == '/')) {
+
+ // Don't allow "file:\\\\", because we can't tell the difference
+ // with it for "file:\\" + "\\server" and "file:\\\" + "\localpath"
+ if ( (len > 8) &&
+ ((path[8] == '\\') || (path[8] == '/')) )
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+
+ // file:\\\ means local path
+ else
+#if !PLATFORM_UNIX
+ trim = 8;
+#else
+ // For Unix platform, trim the first 7 charcaters only.
+ // Trimming the first 8 characters will cause
+ // the root path separator to be trimmed away,
+ // and the absolute local path becomes a relative local path.
+ trim = 7;
+#endif // !PLATFORM_UNIX
+ }
+
+ // file:\\ means remote server
+ else {
+ trim = 5;
+#if !PLATFORM_UNIX
+ UNCpath = true;
+#endif // !PLATFORM_UNIX
+ }
+ }
+
+ // local path
+ else if (path[7] == '/')
+#if !PLATFORM_UNIX
+ trim = 8;
+#else
+ // For Unix platform, trim the first 7 characters only.
+ // Trimming the first 8 characters will cause
+ // the root path separator to be trimmed away,
+ // and the absolute local path becomes a relative local path.
+ trim = 7;
+#endif // !PLATFORM_UNIX
+
+ // remote
+ else {
+ // file://\\remote
+ if ( (len > 8) && (path[7] == '\\') && (path[8] == '\\') )
+ trim = 7;
+ else { // file://remote
+ trim = 5;
+#if !PLATFORM_UNIX
+ // Create valid UNC path by changing
+ // all occurences of '/' to '\\' in path
+ System.Text.StringBuilder winPathBuilder =
+ new System.Text.StringBuilder(len);
+ for (int i = 0; i < len; i++) {
+ char c = path[i];
+ if (c == '/')
+ winPathBuilder.Append('\\');
+ else
+ winPathBuilder.Append(c);
+ }
+ path = winPathBuilder.ToString();
+#endif // !PLATFORM_UNIX
+ }
+#if !PLATFORM_UNIX
+ UNCpath = true;
+#endif // !PLATFORM_UNIX
+ }
+
+ path = path.Substring(trim);
+ len -= trim;
+ }
+
+#if !PLATFORM_UNIX
+ bool localPath;
+
+ // UNC
+ if (UNCpath ||
+ ( (len > 1) &&
+ ( (path[0] == '/') || (path[0] == '\\') ) &&
+ ( (path[1] == '/') || (path[1] == '\\') ) ))
+ localPath = false;
+
+ else {
+ int colon = path.IndexOf(':') + 1;
+
+ // protocol other than file:
+ if ((colon != 0) &&
+ (len > colon+1) &&
+ ( (path[colon] == '/') || (path[colon] == '\\') ) &&
+ ( (path[colon+1] == '/') || (path[colon+1] == '\\') ))
+ localPath = false;
+
+ else
+ localPath = true;
+ }
+
+ if (localPath)
+#else
+ if ( (len == 1) ||
+ ( (path[0] != '/') && (path[0] != '\\') ) )
+#endif // !PLATFORM_UNIX
+ {
+
+ if (useAppBase &&
+ ( (len == 1) || (path[1] != ':') )) {
+ String appBase = Value[(int) LoaderInformation.ApplicationBaseValue];
+
+ if ((appBase == null) || (appBase.Length == 0))
+ throw new MemberAccessException(Environment.GetResourceString("AppDomain_AppBaseNotSet"));
+
+ StringBuilder result = StringBuilderCache.Acquire();
+
+ bool slash = false;
+ if ((path[0] == '/') || (path[0] == '\\')) {
+ string pathRoot = AppDomain.NormalizePath(appBase, fullCheck: false);
+ pathRoot = pathRoot.Substring(0, IO.PathInternal.GetRootLength(pathRoot));
+
+ if (pathRoot.Length == 0) { // URL
+ int index = appBase.IndexOf(":/", StringComparison.Ordinal);
+ if (index == -1)
+ index = appBase.IndexOf(":\\", StringComparison.Ordinal);
+
+ // Get past last slashes of "url:http://"
+ int urlLen = appBase.Length;
+ for (index += 1;
+ (index < urlLen) && ((appBase[index] == '/') || (appBase[index] == '\\'));
+ index++);
+
+ // Now find the next slash to get domain name
+ for(; (index < urlLen) && (appBase[index] != '/') && (appBase[index] != '\\');
+ index++);
+
+ pathRoot = appBase.Substring(0, index);
+ }
+
+ result.Append(pathRoot);
+ slash = true;
+ }
+ else
+ result.Append(appBase);
+
+ // Make sure there's a slash separator (and only one)
+ int aLen = result.Length - 1;
+ if ((result[aLen] != '/') &&
+ (result[aLen] != '\\')) {
+ if (!slash) {
+#if !PLATFORM_UNIX
+ if (appBase.IndexOf(":/", StringComparison.Ordinal) == -1)
+ result.Append('\\');
+ else
+#endif // !PLATFORM_UNIX
+ result.Append('/');
+ }
+ }
+ else if (slash)
+ result.Remove(aLen, 1);
+
+ result.Append(path);
+ path = StringBuilderCache.GetStringAndRelease(result);
+ }
+ else
+ path = AppDomain.NormalizePath(path, fullCheck: true);
+ }
+
+ return path;
+ }
+
+ private bool IsFilePath(String path)
+ {
+#if !PLATFORM_UNIX
+ return (path[1] == ':') || ( (path[0] == '\\') && (path[1] == '\\') );
+#else
+ return (path[0] == '/');
+#endif // !PLATFORM_UNIX
+ }
+
+ internal static String ApplicationBaseKey
+ {
+ get {
+ return ACTAG_APP_BASE_URL;
+ }
+ }
+
+ public String ConfigurationFile
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return VerifyDir(Value[(int) LoaderInformation.ConfigurationFileValue], true);
+ }
+
+ set {
+ Value[(int) LoaderInformation.ConfigurationFileValue] = value;
+ }
+ }
+
+ // Used by the ResourceManager internally. This must not do any
+ // security checks to avoid infinite loops.
+ internal String ConfigurationFileInternal
+ {
+ get {
+ return NormalizePath(Value[(int) LoaderInformation.ConfigurationFileValue], true);
+ }
+ }
+
+ internal static String ConfigurationFileKey
+ {
+ get {
+ return ACTAG_APP_CONFIG_FILE;
+ }
+ }
+
+ public byte[] GetConfigurationBytes()
+ {
+ if (_ConfigurationBytes == null)
+ return null;
+
+ return (byte[]) _ConfigurationBytes.Clone();
+ }
+
+ public void SetConfigurationBytes(byte[] value)
+ {
+ _ConfigurationBytes = value;
+ }
+
+ private static String ConfigurationBytesKey
+ {
+ get {
+ return ACTAG_APP_CONFIG_BLOB;
+ }
+ }
+
+ // only needed by AppDomain.Setup(). Not really needed by users.
+ internal Dictionary<string, object> GetCompatibilityFlags()
+ {
+ return _CompatFlags;
+ }
+
+ public void SetCompatibilitySwitches(IEnumerable<String> switches)
+ {
+
+#if !FEATURE_CORECLR
+ if(_AppDomainSortingSetupInfo != null)
+ {
+ _AppDomainSortingSetupInfo._useV2LegacySorting = false;
+ _AppDomainSortingSetupInfo._useV4LegacySorting = false;
+ }
+#endif
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ _UseRandomizedStringHashing = false;
+#endif
+ if (switches != null)
+ {
+ _CompatFlags = new Dictionary<string, object>();
+ foreach (String str in switches)
+ {
+#if !FEATURE_CORECLR
+ if(StringComparer.OrdinalIgnoreCase.Equals("NetFx40_Legacy20SortingBehavior", str)) {
+ if(_AppDomainSortingSetupInfo == null)
+ {
+ _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo();
+ }
+ _AppDomainSortingSetupInfo._useV2LegacySorting = true;
+ }
+
+ if(StringComparer.OrdinalIgnoreCase.Equals("NetFx45_Legacy40SortingBehavior", str)) {
+ if(_AppDomainSortingSetupInfo == null)
+ {
+ _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo();
+ }
+ _AppDomainSortingSetupInfo._useV4LegacySorting = true;
+ }
+#endif
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ if(StringComparer.OrdinalIgnoreCase.Equals("UseRandomizedStringHashAlgorithm", str)) {
+ _UseRandomizedStringHashing = true;
+ }
+#endif
+
+ _CompatFlags.Add(str, null);
+ }
+ }
+ else
+ {
+ _CompatFlags = null;
+ }
+
+ }
+
+ // A target Framework moniker, in a format parsible by the FrameworkName class.
+ public String TargetFrameworkName {
+ get {
+ return _TargetFrameworkName;
+ }
+ set {
+ _TargetFrameworkName = value;
+ }
+ }
+
+ internal bool CheckedForTargetFrameworkName
+ {
+ get { return _CheckedForTargetFrameworkName; }
+ set { _CheckedForTargetFrameworkName = value; }
+ }
+
+#if !FEATURE_CORECLR
+ [SecurityCritical]
+ public void SetNativeFunction(string functionName, int functionVersion, IntPtr functionPointer)
+ {
+ if(functionName == null)
+ {
+ throw new ArgumentNullException("functionName");
+ }
+
+ if(functionPointer == IntPtr.Zero)
+ {
+ throw new ArgumentNullException("functionPointer");
+ }
+
+ if(String.IsNullOrWhiteSpace(functionName))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NPMSInvalidName"), "functionName");
+ }
+
+ Contract.EndContractBlock();
+
+ if(functionVersion < 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_MinSortingVersion", 1, functionName));
+ }
+
+ if(_AppDomainSortingSetupInfo == null)
+ {
+ _AppDomainSortingSetupInfo = new AppDomainSortingSetupInfo();
+ }
+
+ if(String.Equals(functionName, "IsNLSDefinedString", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnIsNLSDefinedString = functionPointer;
+ }
+
+ if (String.Equals(functionName, "CompareStringEx", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnCompareStringEx = functionPointer;
+ }
+
+ if (String.Equals(functionName, "LCMapStringEx", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnLCMapStringEx = functionPointer;
+ }
+
+ if (String.Equals(functionName, "FindNLSStringEx", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnFindNLSStringEx = functionPointer;
+ }
+
+ if (String.Equals(functionName, "CompareStringOrdinal", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnCompareStringOrdinal = functionPointer;
+ }
+
+ if (String.Equals(functionName, "GetNLSVersionEx", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnGetNLSVersionEx = functionPointer;
+ }
+
+ if (String.Equals(functionName, "FindStringOrdinal", StringComparison.OrdinalIgnoreCase))
+ {
+ _AppDomainSortingSetupInfo._pfnFindStringOrdinal = functionPointer;
+ }
+ }
+#endif
+
+ public String DynamicBase
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return VerifyDir(Value[(int) LoaderInformation.DynamicBaseValue], true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ set {
+ if (value == null)
+ Value[(int) LoaderInformation.DynamicBaseValue] = null;
+ else {
+ if(ApplicationName == null)
+ throw new MemberAccessException(Environment.GetResourceString("AppDomain_RequireApplicationName"));
+
+ StringBuilder s = new StringBuilder( NormalizePath(value, false) );
+ s.Append('\\');
+ string h = ParseNumbers.IntToString(ApplicationName.GetLegacyNonRandomizedHashCode(),
+ 16, 8, '0', ParseNumbers.PrintAsI4);
+ s.Append(h);
+
+ Value[(int) LoaderInformation.DynamicBaseValue] = s.ToString();
+ }
+ }
+ }
+
+ internal static String DynamicBaseKey
+ {
+ get {
+ return ACTAG_APP_DYNAMIC_BASE;
+ }
+ }
+
+
+ public bool DisallowPublisherPolicy
+ {
+ get
+ {
+ return (Value[(int) LoaderInformation.DisallowPublisherPolicyValue] != null);
+ }
+ set
+ {
+ if (value)
+ Value[(int) LoaderInformation.DisallowPublisherPolicyValue]="true";
+ else
+ Value[(int) LoaderInformation.DisallowPublisherPolicyValue]=null;
+ }
+ }
+
+
+ public bool DisallowBindingRedirects
+ {
+ get
+ {
+ return (Value[(int) LoaderInformation.DisallowBindingRedirectsValue] != null);
+ }
+ set
+ {
+ if (value)
+ Value[(int) LoaderInformation.DisallowBindingRedirectsValue] = "true";
+ else
+ Value[(int) LoaderInformation.DisallowBindingRedirectsValue] = null;
+ }
+ }
+
+ public bool DisallowCodeDownload
+ {
+ get
+ {
+ return (Value[(int) LoaderInformation.DisallowCodeDownloadValue] != null);
+ }
+ set
+ {
+ if (value)
+ Value[(int) LoaderInformation.DisallowCodeDownloadValue] = "true";
+ else
+ Value[(int) LoaderInformation.DisallowCodeDownloadValue] = null;
+ }
+ }
+
+
+ public bool DisallowApplicationBaseProbing
+ {
+ get
+ {
+ return (Value[(int) LoaderInformation.DisallowAppBaseProbingValue] != null);
+ }
+ set
+ {
+ if (value)
+ Value[(int) LoaderInformation.DisallowAppBaseProbingValue] = "true";
+ else
+ Value[(int) LoaderInformation.DisallowAppBaseProbingValue] = null;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private String VerifyDir(String dir, bool normalize)
+ {
+ if (dir != null) {
+ if (dir.Length == 0)
+ dir = null;
+ 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
+#if !FEATURE_CORECLR
+ if (IsFilePath(dir))
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, dir ).Demand();
+#endif // !FEATURE_CORECLR
+ }
+ }
+
+ return dir;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void VerifyDirList(String dirs)
+ {
+ if (dirs != null) {
+ String[] dirArray = dirs.Split(';');
+ int len = dirArray.Length;
+
+ for (int i = 0; i < len; i++)
+ VerifyDir(dirArray[i], true);
+ }
+ }
+
+ internal String DeveloperPath
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ String dirs = Value[(int) LoaderInformation.DevPathValue];
+ VerifyDirList(dirs);
+ return dirs;
+ }
+
+ set {
+ if(value == null)
+ Value[(int) LoaderInformation.DevPathValue] = null;
+ else {
+ String[] directories = value.Split(';');
+ int size = directories.Length;
+ StringBuilder newPath = StringBuilderCache.Acquire();
+ bool fDelimiter = false;
+
+ for(int i = 0; i < size; i++) {
+ if(directories[i].Length != 0) {
+ if(fDelimiter)
+ newPath.Append(";");
+ else
+ fDelimiter = true;
+
+ newPath.Append(Path.GetFullPathInternal(directories[i]));
+ }
+ }
+
+ String newString = StringBuilderCache.GetStringAndRelease(newPath);
+ if (newString.Length == 0)
+ Value[(int) LoaderInformation.DevPathValue] = null;
+ else
+ Value[(int) LoaderInformation.DevPathValue] = newString;
+ }
+ }
+ }
+
+ internal static String DisallowPublisherPolicyKey
+ {
+ get
+ {
+ return ACTAG_DISALLOW_APPLYPUBLISHERPOLICY;
+ }
+ }
+
+ internal static String DisallowCodeDownloadKey
+ {
+ get
+ {
+ return ACTAG_CODE_DOWNLOAD_DISABLED;
+ }
+ }
+
+ internal static String DisallowBindingRedirectsKey
+ {
+ get
+ {
+ return ACTAG_DISALLOW_APP_BINDING_REDIRECTS;
+ }
+ }
+
+ internal static String DeveloperPathKey
+ {
+ get {
+ return ACTAG_DEV_PATH;
+ }
+ }
+
+ internal static String DisallowAppBaseProbingKey
+ {
+ get
+ {
+ return ACTAG_DISALLOW_APP_BASE_PROBING;
+ }
+ }
+
+ public String ApplicationName
+ {
+ get {
+ return Value[(int) LoaderInformation.ApplicationNameValue];
+ }
+
+ set {
+ Value[(int) LoaderInformation.ApplicationNameValue] = value;
+ }
+ }
+
+ internal static String ApplicationNameKey
+ {
+ get {
+ return ACTAG_APP_NAME;
+ }
+ }
+
+ [XmlIgnoreMember]
+ public AppDomainInitializer AppDomainInitializer
+ {
+ get {
+ return _AppDomainInitializer;
+ }
+
+ set {
+ _AppDomainInitializer = value;
+ }
+ }
+ public string[] AppDomainInitializerArguments
+ {
+ get {
+ return _AppDomainInitializerArguments;
+ }
+
+ set {
+ _AppDomainInitializerArguments = value;
+ }
+ }
+
+#if FEATURE_CLICKONCE
+ [XmlIgnoreMember]
+ public ActivationArguments ActivationArguments {
+ [Pure]
+ get {
+ return _ActivationArguments;
+ }
+ set {
+ _ActivationArguments = value;
+ }
+ }
+#endif // !FEATURE_CLICKONCE
+
+ internal ApplicationTrust InternalGetApplicationTrust()
+ {
+
+ if (_ApplicationTrust == null) return null;
+
+
+#if FEATURE_CORECLR
+ ApplicationTrust grantSet = new ApplicationTrust(NamedPermissionSet.GetBuiltInSet(_ApplicationTrust));
+#else
+ SecurityElement securityElement = SecurityElement.FromString(_ApplicationTrust);
+ ApplicationTrust grantSet = new ApplicationTrust();
+ grantSet.FromXml(securityElement);
+#endif
+ return grantSet;
+ }
+
+#if FEATURE_CORECLR
+ internal void InternalSetApplicationTrust(String permissionSetName)
+ {
+ _ApplicationTrust = permissionSetName;
+ }
+#else
+ internal void InternalSetApplicationTrust(ApplicationTrust value)
+ {
+ if (value != null)
+ {
+ _ApplicationTrust = value.ToXml().ToString();
+ }
+ else
+ {
+ _ApplicationTrust = null;
+ }
+ }
+#endif
+
+#if FEATURE_CLICKONCE
+ [XmlIgnoreMember]
+ public ApplicationTrust ApplicationTrust
+ {
+ get {
+ return InternalGetApplicationTrust();
+ }
+ set {
+ InternalSetApplicationTrust(value);
+ }
+ }
+#else // FEATURE_CLICKONCE
+ [XmlIgnoreMember]
+ internal ApplicationTrust ApplicationTrust
+ {
+ get {
+ return InternalGetApplicationTrust();
+ }
+#if !FEATURE_CORECLR
+ set {
+ InternalSetApplicationTrust(value);
+ }
+#endif
+ }
+#endif // FEATURE_CLICKONCE
+
+ public String PrivateBinPath
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ String dirs = Value[(int) LoaderInformation.PrivateBinPathValue];
+ VerifyDirList(dirs);
+ return dirs;
+ }
+
+ set {
+ Value[(int) LoaderInformation.PrivateBinPathValue] = value;
+ }
+ }
+
+ internal static String PrivateBinPathKey
+ {
+ get {
+ return ACTAG_APP_PRIVATE_BINPATH;
+ }
+ }
+
+
+ public String PrivateBinPathProbe
+ {
+ get {
+ return Value[(int) LoaderInformation.PrivateBinPathProbeValue];
+ }
+
+ set {
+ Value[(int) LoaderInformation.PrivateBinPathProbeValue] = value;
+ }
+ }
+
+ internal static String PrivateBinPathProbeKey
+ {
+ get {
+ return ACTAG_BINPATH_PROBE_ONLY;
+ }
+ }
+
+ public String ShadowCopyDirectories
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ String dirs = Value[(int) LoaderInformation.ShadowCopyDirectoriesValue];
+ VerifyDirList(dirs);
+ return dirs;
+ }
+
+ set {
+ Value[(int) LoaderInformation.ShadowCopyDirectoriesValue] = value;
+ }
+ }
+
+ internal static String ShadowCopyDirectoriesKey
+ {
+ get {
+ return ACTAG_APP_SHADOW_COPY_DIRS;
+ }
+ }
+
+ public String ShadowCopyFiles
+ {
+ get {
+ return Value[(int) LoaderInformation.ShadowCopyFilesValue];
+ }
+
+ set {
+ if((value != null) &&
+ (String.Compare(value, "true", StringComparison.OrdinalIgnoreCase) == 0))
+ Value[(int) LoaderInformation.ShadowCopyFilesValue] = value;
+ else
+ Value[(int) LoaderInformation.ShadowCopyFilesValue] = null;
+ }
+ }
+
+ internal static String ShadowCopyFilesKey
+ {
+ get {
+ return ACTAG_FORCE_CACHE_INSTALL;
+ }
+ }
+
+ public String CachePath
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return VerifyDir(Value[(int) LoaderInformation.CachePathValue], false);
+ }
+
+ set {
+ Value[(int) LoaderInformation.CachePathValue] = NormalizePath(value, false);
+ }
+ }
+
+ internal static String CachePathKey
+ {
+ get {
+ return ACTAG_APP_CACHE_BASE;
+ }
+ }
+
+ public String LicenseFile
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return VerifyDir(Value[(int) LoaderInformation.LicenseFileValue], true);
+ }
+
+ set {
+ Value[(int) LoaderInformation.LicenseFileValue] = value;
+ }
+ }
+
+ public LoaderOptimization LoaderOptimization
+ {
+ get {
+ return _LoaderOptimization;
+ }
+
+ set {
+ _LoaderOptimization = value;
+ }
+ }
+
+ internal static string LoaderOptimizationKey
+ {
+ get {
+ return LOADER_OPTIMIZATION;
+ }
+ }
+
+ internal static string ConfigurationExtension
+ {
+ get {
+ return CONFIGURATION_EXTENSION;
+ }
+ }
+
+ internal static String PrivateBinPathEnvironmentVariable
+ {
+ get {
+ return APPENV_RELATIVEPATH;
+ }
+ }
+
+ internal static string RuntimeConfigurationFile
+ {
+ get {
+ return MACHINE_CONFIGURATION_FILE;
+ }
+ }
+
+ internal static string MachineConfigKey
+ {
+ get {
+ return ACTAG_MACHINE_CONFIG;
+ }
+ }
+
+ internal static string HostBindingKey
+ {
+ get {
+ return ACTAG_HOST_CONFIG_FILE;
+ }
+ }
+
+#if FEATURE_FUSION
+ [SecurityCritical]
+ internal bool UpdateContextPropertyIfNeeded(LoaderInformation FieldValue, String FieldKey, String UpdatedField, IntPtr fusionContext, AppDomainSetup oldADS)
+ {
+ String FieldString = Value[(int) FieldValue],
+ OldFieldString = (oldADS == null ? null : oldADS.Value[(int) FieldValue]);
+ if (FieldString != OldFieldString) { // Compare references since strings are immutable
+ UpdateContextProperty(fusionContext, FieldKey, UpdatedField == null ? FieldString : UpdatedField);
+ return true;
+ }
+
+ return false;
+ }
+
+ [SecurityCritical]
+ internal void UpdateBooleanContextPropertyIfNeeded(LoaderInformation FieldValue, String FieldKey, IntPtr fusionContext, AppDomainSetup oldADS)
+ {
+ if (Value[(int) FieldValue] != null)
+ UpdateContextProperty(fusionContext, FieldKey, "true");
+ else if (oldADS != null && oldADS.Value[(int) FieldValue] != null)
+ UpdateContextProperty(fusionContext, FieldKey, "false");
+ }
+
+ [SecurityCritical]
+ internal static bool ByteArraysAreDifferent(Byte[] A, Byte[] B)
+ {
+ int length = A.Length;
+ if (length != B.Length)
+ return true;
+
+ for(int i = 0; i < length; i++) {
+ if (A[i] != B[i])
+ return true;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void UpdateByteArrayContextPropertyIfNeeded(Byte[] NewArray, Byte[] OldArray, String FieldKey, IntPtr fusionContext)
+ {
+ if ((NewArray != null && OldArray == null) ||
+ (NewArray == null && OldArray != null) ||
+ (NewArray != null && OldArray != null && ByteArraysAreDifferent(NewArray, OldArray)))
+ UpdateContextProperty(fusionContext, FieldKey, NewArray);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetupFusionContext(IntPtr fusionContext, AppDomainSetup oldADS)
+ {
+ UpdateContextPropertyIfNeeded(LoaderInformation.ApplicationBaseValue, ApplicationBaseKey, null, fusionContext, oldADS);
+ UpdateContextPropertyIfNeeded(LoaderInformation.PrivateBinPathValue, PrivateBinPathKey, null, fusionContext, oldADS);
+ UpdateContextPropertyIfNeeded(LoaderInformation.DevPathValue, DeveloperPathKey, null, fusionContext, oldADS);
+
+ UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowPublisherPolicyValue, DisallowPublisherPolicyKey, fusionContext, oldADS);
+ UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowCodeDownloadValue, DisallowCodeDownloadKey, fusionContext, oldADS);
+ UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowBindingRedirectsValue, DisallowBindingRedirectsKey, fusionContext, oldADS);
+ UpdateBooleanContextPropertyIfNeeded(LoaderInformation.DisallowAppBaseProbingValue, DisallowAppBaseProbingKey, fusionContext, oldADS);
+
+ if(UpdateContextPropertyIfNeeded(LoaderInformation.ShadowCopyFilesValue, ShadowCopyFilesKey, ShadowCopyFiles, fusionContext, oldADS)) {
+
+ // If we are asking for shadow copy directories then default to
+ // only to the ones that are in the private bin path.
+ if(Value[(int) LoaderInformation.ShadowCopyDirectoriesValue] == null)
+ ShadowCopyDirectories = BuildShadowCopyDirectories();
+
+ UpdateContextPropertyIfNeeded(LoaderInformation.ShadowCopyDirectoriesValue, ShadowCopyDirectoriesKey, null, fusionContext, oldADS);
+ }
+
+ UpdateContextPropertyIfNeeded(LoaderInformation.CachePathValue, CachePathKey, null, fusionContext, oldADS);
+ UpdateContextPropertyIfNeeded(LoaderInformation.PrivateBinPathProbeValue, PrivateBinPathProbeKey, PrivateBinPathProbe, fusionContext, oldADS);
+ UpdateContextPropertyIfNeeded(LoaderInformation.ConfigurationFileValue, ConfigurationFileKey, null, fusionContext, oldADS);
+
+ UpdateByteArrayContextPropertyIfNeeded(_ConfigurationBytes, oldADS == null ? null : oldADS.GetConfigurationBytes(), ConfigurationBytesKey, fusionContext);
+
+ UpdateContextPropertyIfNeeded(LoaderInformation.ApplicationNameValue, ApplicationNameKey, ApplicationName, fusionContext, oldADS);
+ UpdateContextPropertyIfNeeded(LoaderInformation.DynamicBaseValue, DynamicBaseKey, null, fusionContext, oldADS);
+
+ // Always add the runtime configuration file to the appdomain
+ UpdateContextProperty(fusionContext, MachineConfigKey, RuntimeEnvironment.GetRuntimeDirectoryImpl() + RuntimeConfigurationFile);
+
+ String hostBindingFile = RuntimeEnvironment.GetHostBindingFile();
+ if(hostBindingFile != null || oldADS != null) // If oldADS != null, we don't know the old value of the hostBindingFile, so we force an update even when hostBindingFile == null.
+ UpdateContextProperty(fusionContext, HostBindingKey, hostBindingFile);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void UpdateContextProperty(IntPtr fusionContext, string key, Object value);
+#endif // FEATURE_FUSION
+
+ static internal int Locate(String s)
+ {
+ if(String.IsNullOrEmpty(s))
+ return -1;
+#if FEATURE_FUSION
+
+ // verify assumptions hardcoded into the switch below
+ Contract.Assert('A' == ACTAG_APP_CONFIG_FILE[0] , "Assumption violated");
+ Contract.Assert('A' == ACTAG_APP_NAME[0] , "Assumption violated");
+ Contract.Assert('A' == ACTAG_APP_BASE_URL[0] , "Assumption violated");
+ Contract.Assert('B' == ACTAG_BINPATH_PROBE_ONLY[0] , "Assumption violated");
+ Contract.Assert('C' == ACTAG_APP_CACHE_BASE[0] , "Assumption violated");
+ Contract.Assert('D' == ACTAG_DEV_PATH[0] , "Assumption violated");
+ Contract.Assert('D' == ACTAG_APP_DYNAMIC_BASE[0] , "Assumption violated");
+ Contract.Assert('F' == ACTAG_FORCE_CACHE_INSTALL[0] , "Assumption violated");
+ Contract.Assert('L' == LICENSE_FILE[0] , "Assumption violated");
+ Contract.Assert('P' == ACTAG_APP_PRIVATE_BINPATH[0] , "Assumption violated");
+ Contract.Assert('S' == ACTAG_APP_SHADOW_COPY_DIRS[0], "Assumption violated");
+ Contract.Assert('D' == ACTAG_DISALLOW_APPLYPUBLISHERPOLICY[0], "Assumption violated");
+ Contract.Assert('C' == ACTAG_CODE_DOWNLOAD_DISABLED[0], "Assumption violated");
+ Contract.Assert('D' == ACTAG_DISALLOW_APP_BINDING_REDIRECTS[0], "Assumption violated");
+ Contract.Assert('D' == ACTAG_DISALLOW_APP_BASE_PROBING[0], "Assumption violated");
+ Contract.Assert('A' == ACTAG_APP_CONFIG_BLOB[0], "Assumption violated");
+
+ switch (s[0]) {
+ case 'A':
+ if (s == ACTAG_APP_CONFIG_FILE) return (int)LoaderInformation.ConfigurationFileValue;
+ if (s == ACTAG_APP_NAME) return (int)LoaderInformation.ApplicationNameValue;
+ if (s == ACTAG_APP_BASE_URL) return (int)LoaderInformation.ApplicationBaseValue;
+ if (s == ACTAG_APP_CONFIG_BLOB) return (int)LoaderInformation.ConfigurationBytesValue;
+ break;
+ case 'B':
+ if (s == ACTAG_BINPATH_PROBE_ONLY) return (int)LoaderInformation.PrivateBinPathProbeValue;
+ break;
+ case 'C':
+ if (s == ACTAG_APP_CACHE_BASE) return (int)LoaderInformation.CachePathValue;
+ if (s == ACTAG_CODE_DOWNLOAD_DISABLED) return (int)LoaderInformation.DisallowCodeDownloadValue;
+ break;
+ case 'D':
+ if (s == ACTAG_DEV_PATH) return (int)LoaderInformation.DevPathValue;
+ if (s == ACTAG_APP_DYNAMIC_BASE) return (int)LoaderInformation.DynamicBaseValue;
+ if (s == ACTAG_DISALLOW_APPLYPUBLISHERPOLICY) return (int)LoaderInformation.DisallowPublisherPolicyValue;
+ if (s == ACTAG_DISALLOW_APP_BINDING_REDIRECTS) return (int)LoaderInformation.DisallowBindingRedirectsValue;
+ if (s == ACTAG_DISALLOW_APP_BASE_PROBING) return (int)LoaderInformation.DisallowAppBaseProbingValue;
+ break;
+ case 'F':
+ if (s == ACTAG_FORCE_CACHE_INSTALL) return (int)LoaderInformation.ShadowCopyFilesValue;
+ break;
+ case 'L':
+ if (s == LICENSE_FILE) return (int)LoaderInformation.LicenseFileValue;
+ break;
+ case 'P':
+ if (s == ACTAG_APP_PRIVATE_BINPATH) return (int)LoaderInformation.PrivateBinPathValue;
+ break;
+ case 'S':
+ if (s == ACTAG_APP_SHADOW_COPY_DIRS) return (int)LoaderInformation.ShadowCopyDirectoriesValue;
+ break;
+ }
+#else
+ Contract.Assert('A' == ACTAG_APP_BASE_URL[0] , "Assumption violated");
+ if (s[0]=='A' && s == ACTAG_APP_BASE_URL)
+ return (int)LoaderInformation.ApplicationBaseValue;
+
+#endif //FEATURE_FUSION
+
+ return -1;
+ }
+#if FEATURE_FUSION
+ private string BuildShadowCopyDirectories()
+ {
+ // Default to only to the ones that are in the private bin path.
+ String binPath = Value[(int) LoaderInformation.PrivateBinPathValue];
+ if(binPath == null)
+ return null;
+
+ StringBuilder result = StringBuilderCache.Acquire();
+ String appBase = Value[(int) LoaderInformation.ApplicationBaseValue];
+ if(appBase != null) {
+ char[] sep = {';'};
+ string[] directories = binPath.Split(sep);
+ int size = directories.Length;
+ bool appendSlash = !( (appBase[appBase.Length-1] == '/') ||
+ (appBase[appBase.Length-1] == '\\') );
+
+ if (size == 0) {
+ result.Append(appBase);
+ if (appendSlash)
+ result.Append('\\');
+ result.Append(binPath);
+ }
+ else {
+ for(int i = 0; i < size; i++) {
+ result.Append(appBase);
+ if (appendSlash)
+ result.Append('\\');
+ result.Append(directories[i]);
+
+ if (i < size-1)
+ result.Append(';');
+ }
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+#endif // FEATURE_FUSION
+
+#if FEATURE_COMINTEROP
+ public bool SandboxInterop
+ {
+ get
+ {
+ return _DisableInterfaceCache;
+ }
+ set
+ {
+ _DisableInterfaceCache = value;
+ }
+ }
+#endif // FEATURE_COMINTEROP
+ }
+}
diff --git a/src/mscorlib/src/System/AppDomainUnloadedException.cs b/src/mscorlib/src/System/AppDomainUnloadedException.cs
new file mode 100644
index 0000000000..8ba37dc4c5
--- /dev/null
+++ b/src/mscorlib/src/System/AppDomainUnloadedException.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for attempt to access an unloaded AppDomain
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class AppDomainUnloadedException : SystemException {
+ public AppDomainUnloadedException()
+ : base(Environment.GetResourceString("Arg_AppDomainUnloadedException")) {
+ SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED);
+ }
+
+ public AppDomainUnloadedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED);
+ }
+
+ public AppDomainUnloadedException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_APPDOMAINUNLOADED);
+ }
+
+ //
+ //This constructor is required for serialization.
+ //
+ protected AppDomainUnloadedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/ApplicationException.cs b/src/mscorlib/src/System/ApplicationException.cs
new file mode 100644
index 0000000000..c56746fae0
--- /dev/null
+++ b/src/mscorlib/src/System/ApplicationException.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The base class for all "less serious" exceptions that must be
+** declared or caught.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+ // The ApplicationException is the base class for nonfatal,
+ // application errors that occur. These exceptions are generated
+ // (i.e., thrown) by an application, not the Runtime. Applications that need
+ // to create their own exceptions do so by extending this class.
+ // ApplicationException extends but adds no new functionality to
+ // RecoverableException.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ApplicationException : Exception {
+
+ // Creates a new ApplicationException with its message string set to
+ // the empty string, its HRESULT set to COR_E_APPLICATION,
+ // and its ExceptionInfo reference set to null.
+ public ApplicationException()
+ : base(Environment.GetResourceString("Arg_ApplicationException")) {
+ SetErrorCode(__HResults.COR_E_APPLICATION);
+ }
+
+ // Creates a new ApplicationException with its message string set to
+ // message, its HRESULT set to COR_E_APPLICATION,
+ // and its ExceptionInfo reference set to null.
+ //
+ public ApplicationException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_APPLICATION);
+ }
+
+ public ApplicationException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_APPLICATION);
+ }
+
+ protected ApplicationException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/ApplicationId.cs b/src/mscorlib/src/System/ApplicationId.cs
new file mode 100644
index 0000000000..fa8be957e2
--- /dev/null
+++ b/src/mscorlib/src/System/ApplicationId.cs
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+//
+// This class identifies a deployment or manifest identity.
+//
+
+namespace System {
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Policy;
+ using System.Security.Util;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ApplicationId {
+ private string m_name;
+ private Version m_version;
+ private string m_processorArchitecture;
+ private string m_culture;
+ internal byte[] m_publicKeyToken;
+
+ internal ApplicationId () {}
+
+ //
+ // Public.
+ //
+
+ public ApplicationId (byte[] publicKeyToken, string name, Version version, string processorArchitecture, string culture) {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyApplicationName"));
+ if (version == null)
+ throw new ArgumentNullException("version");
+ if (publicKeyToken == null)
+ throw new ArgumentNullException("publicKeyToken");
+ Contract.EndContractBlock();
+
+ m_publicKeyToken = new byte[publicKeyToken.Length];
+ Array.Copy(publicKeyToken, 0, m_publicKeyToken, 0, publicKeyToken.Length);
+ m_name = name;
+ m_version = version;
+ m_processorArchitecture = processorArchitecture;
+ m_culture = culture;
+ }
+
+ public byte[] PublicKeyToken {
+ get {
+ byte[] publicKeyToken = new byte[m_publicKeyToken.Length];
+ Array.Copy(m_publicKeyToken, 0, publicKeyToken, 0, m_publicKeyToken.Length);
+ return publicKeyToken;
+ }
+ }
+
+ public string Name {
+ get {
+ return m_name;
+ }
+ }
+
+ public Version Version {
+ get {
+ return m_version;
+ }
+ }
+
+ public string ProcessorArchitecture {
+ get {
+ return m_processorArchitecture;
+ }
+ }
+
+ public string Culture {
+ get {
+ return m_culture;
+ }
+ }
+
+ public ApplicationId Copy () {
+ return new ApplicationId(m_publicKeyToken, m_name, m_version, m_processorArchitecture, m_culture);
+ }
+
+ public override string ToString () {
+ StringBuilder sb = StringBuilderCache.Acquire();
+ sb.Append(this.m_name);
+ if (m_culture != null) {
+ sb.Append(", culture=\"");
+ sb.Append(m_culture);
+ sb.Append("\"");
+ }
+ sb.Append(", version=\"");
+ sb.Append(m_version.ToString());
+ sb.Append("\"");
+ if (m_publicKeyToken != null) {
+ sb.Append(", publicKeyToken=\"");
+ sb.Append(Hex.EncodeHexString(m_publicKeyToken));
+ sb.Append("\"");
+ }
+ if (m_processorArchitecture != null) {
+ sb.Append(", processorArchitecture =\"");
+ sb.Append(this.m_processorArchitecture);
+ sb.Append("\"");
+ }
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ public override bool Equals (Object o) {
+ ApplicationId other = (o as ApplicationId);
+ if (other == null)
+ return false;
+
+ if (!(Equals(this.m_name, other.m_name) &&
+ Equals(this.m_version, other.m_version) &&
+ Equals(this.m_processorArchitecture, other.m_processorArchitecture) &&
+ Equals(this.m_culture, other.m_culture)))
+ return false;
+
+ if (this.m_publicKeyToken.Length != other.m_publicKeyToken.Length)
+ return false;
+
+ for (int i = 0; i < this.m_publicKeyToken.Length; ++i) {
+ if (this.m_publicKeyToken[i] != other.m_publicKeyToken[i])
+ return false;
+ }
+
+ return true;
+ }
+
+ public override int GetHashCode() {
+ // Note: purposely skipping publicKeyToken, processor architecture and culture as they
+ // are less likely to make things not equal than name and version.
+ return m_name.GetHashCode() ^ m_version.GetHashCode();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ArgIterator.cs b/src/mscorlib/src/System/ArgIterator.cs
new file mode 100644
index 0000000000..0ce27ed24a
--- /dev/null
+++ b/src/mscorlib/src/System/ArgIterator.cs
@@ -0,0 +1,148 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // This class will not be marked serializable
+ // Note: This type must have the same layout as the CLR's VARARGS type in CLRVarArgs.h.
+ // It also contains an inline SigPointer data structure - must keep those fields in sync.
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ArgIterator
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern ArgIterator(IntPtr arglist);
+
+ // create an arg iterator that points at the first argument that
+ // is not statically declared (that is the first ... arg)
+ // 'arglist' is the value returned by the ARGLIST instruction
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ArgIterator(RuntimeArgumentHandle arglist) : this(arglist.Value)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe extern ArgIterator(IntPtr arglist, void *ptr);
+
+ // create an arg iterator that points just past 'firstArg'.
+ // 'arglist' is the value returned by the ARGLIST instruction
+ // This is much like the C va_start macro
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+
+ public unsafe ArgIterator(RuntimeArgumentHandle arglist, void* ptr) : this(arglist.Value, ptr)
+ {
+ }
+
+ // Fetch an argument as a typed referece, advance the iterator.
+ // Throws an exception if past end of argument list
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public TypedReference GetNextArg()
+ {
+ TypedReference result = new TypedReference ();
+ // reference to TypedReference is banned, so have to pass result as pointer
+ unsafe
+ {
+ FCallGetNextArg (&result);
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ // reference to TypedReference is banned, so have to pass result as void pointer
+ private unsafe extern void FCallGetNextArg(void * result);
+
+ // Alternate version of GetNextArg() intended primarily for IJW code
+ // generated by VC's "va_arg()" construct.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public TypedReference GetNextArg(RuntimeTypeHandle rth)
+ {
+ if (sigPtr != IntPtr.Zero)
+ {
+ // This is an ordinary ArgIterator capable of determining
+ // types from a signature. Just do a regular GetNextArg.
+ return GetNextArg();
+ }
+ else
+ {
+ // Prevent abuse of this API with a default ArgIterator (it
+ // doesn't require permission to create a zero-inited value
+ // type). Check that ArgPtr isn't zero or this API will allow a
+ // malicious caller to increment the pointer to an arbitrary
+ // location in memory and read the contents.
+ if (ArgPtr == IntPtr.Zero)
+ throw new ArgumentNullException();
+
+ TypedReference result = new TypedReference ();
+ // reference to TypedReference is banned, so have to pass result as pointer
+ unsafe
+ {
+ InternalGetNextArg(&result, rth.GetRuntimeType());
+ }
+ return result;
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ // reference to TypedReference is banned, so have to pass result as void pointer
+ private unsafe extern void InternalGetNextArg(void * result, RuntimeType rt);
+
+ // This method should invalidate the iterator (va_end). It is not supported yet.
+ public void End()
+ {
+ }
+
+ // How many arguments are left in the list
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern int GetRemainingCount();
+
+ // Gets the type of the current arg, does NOT advance the iterator
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern unsafe void* _GetNextArgType();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe RuntimeTypeHandle GetNextArgType()
+ {
+ return new RuntimeTypeHandle(Type.GetTypeFromHandleUnsafe((IntPtr)_GetNextArgType()));
+ }
+
+ public override int GetHashCode()
+ {
+ return ValueType.GetHashCodeOfPtr(ArgCookie);
+ }
+
+ // Inherited from object
+ public override bool Equals(Object o)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
+ }
+
+ private IntPtr ArgCookie; // Cookie from the EE.
+
+ // The SigPointer structure consists of the following members. (Note: this is an inline native SigPointer data type)
+ private IntPtr sigPtr; // Pointer to remaining signature.
+ private IntPtr sigPtrLen; // Remaining length of the pointer
+
+ // Note, sigPtrLen is actually a DWORD, but on 64bit systems this structure becomes
+ // 8-byte aligned, which requires us to pad it.
+
+ private IntPtr ArgPtr; // Pointer to remaining args.
+ private int RemainingArgs; // # of remaining args.
+ }
+}
diff --git a/src/mscorlib/src/System/ArgumentException.cs b/src/mscorlib/src/System/ArgumentException.cs
new file mode 100644
index 0000000000..8edb7e4279
--- /dev/null
+++ b/src/mscorlib/src/System/ArgumentException.cs
@@ -0,0 +1,95 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for invalid arguments to a method.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+ // The ArgumentException is thrown when an argument does not meet
+ // the contract of the method. Ideally it should give a meaningful error
+ // message describing what was wrong and which parameter is incorrect.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ArgumentException : SystemException, ISerializable {
+ private String m_paramName;
+
+ // Creates a new ArgumentException with its message
+ // string set to the empty string.
+ public ArgumentException()
+ : base(Environment.GetResourceString("Arg_ArgumentException")) {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ // Creates a new ArgumentException with its message
+ // string set to message.
+ //
+ public ArgumentException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public ArgumentException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public ArgumentException(String message, String paramName, Exception innerException)
+ : base(message, innerException) {
+ m_paramName = paramName;
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public ArgumentException (String message, String paramName)
+
+ : base (message) {
+ m_paramName = paramName;
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ protected ArgumentException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ m_paramName = info.GetString("ParamName");
+ }
+
+ public override String Message
+ {
+ get {
+ String s = base.Message;
+ if (!String.IsNullOrEmpty(m_paramName)) {
+ String resourceString = Environment.GetResourceString("Arg_ParamName_Name", m_paramName);
+ return s + Environment.NewLine + resourceString;
+ }
+ else
+ return s;
+ }
+ }
+
+ public virtual String ParamName {
+ get { return m_paramName; }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("ParamName", m_paramName, typeof(String));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ArgumentNullException.cs b/src/mscorlib/src/System/ArgumentNullException.cs
new file mode 100644
index 0000000000..4bcb537b81
--- /dev/null
+++ b/src/mscorlib/src/System/ArgumentNullException.cs
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for null arguments to a method.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.Remoting;
+ using System.Security.Permissions;
+
+ // The ArgumentException is thrown when an argument
+ // is null when it shouldn't be.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ArgumentNullException : ArgumentException
+ {
+ // Creates a new ArgumentNullException with its message
+ // string set to a default message explaining an argument was null.
+ public ArgumentNullException()
+ : base(Environment.GetResourceString("ArgumentNull_Generic")) {
+ // Use E_POINTER - COM used that for null pointers. Description is "invalid pointer"
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ public ArgumentNullException(String paramName)
+ : base(Environment.GetResourceString("ArgumentNull_Generic"), paramName) {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ public ArgumentNullException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ public ArgumentNullException(String paramName, String message)
+ : base(message, paramName) {
+ SetErrorCode(__HResults.E_POINTER);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ protected ArgumentNullException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ArgumentOutOfRangeException.cs b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs
new file mode 100644
index 0000000000..a54380b39d
--- /dev/null
+++ b/src/mscorlib/src/System/ArgumentOutOfRangeException.cs
@@ -0,0 +1,106 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for method arguments outside of the legal range.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // The ArgumentOutOfRangeException is thrown when an argument
+ // is outside the legal range for that argument.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ArgumentOutOfRangeException : ArgumentException, ISerializable {
+
+ private static volatile String _rangeMessage;
+ private Object m_actualValue;
+
+ private static String RangeMessage {
+ get {
+ if (_rangeMessage == null)
+ _rangeMessage = Environment.GetResourceString("Arg_ArgumentOutOfRangeException");
+ return _rangeMessage;
+ }
+ }
+
+ // Creates a new ArgumentOutOfRangeException with its message
+ // string set to a default message explaining an argument was out of range.
+ public ArgumentOutOfRangeException()
+ : base(RangeMessage) {
+ SetErrorCode(__HResults.COR_E_ARGUMENTOUTOFRANGE);
+ }
+
+ public ArgumentOutOfRangeException(String paramName)
+ : base(RangeMessage, paramName) {
+ SetErrorCode(__HResults.COR_E_ARGUMENTOUTOFRANGE);
+ }
+
+ public ArgumentOutOfRangeException(String paramName, String message)
+ : base(message, paramName) {
+ SetErrorCode(__HResults.COR_E_ARGUMENTOUTOFRANGE);
+ }
+
+ public ArgumentOutOfRangeException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_ARGUMENTOUTOFRANGE);
+ }
+
+ // We will not use this in the classlibs, but we'll provide it for
+ // anyone that's really interested so they don't have to stick a bunch
+ // of printf's in their code.
+ public ArgumentOutOfRangeException(String paramName, Object actualValue, String message)
+ : base(message, paramName) {
+ m_actualValue = actualValue;
+ SetErrorCode(__HResults.COR_E_ARGUMENTOUTOFRANGE);
+ }
+
+ public override String Message {
+ get {
+ String s = base.Message;
+ if (m_actualValue != null) {
+ String valueMessage = Environment.GetResourceString("ArgumentOutOfRange_ActualValue", m_actualValue.ToString());
+ if (s == null)
+ return valueMessage;
+ return s + Environment.NewLine + valueMessage;
+ }
+ return s;
+ }
+ }
+
+ // Gets the value of the argument that caused the exception.
+ // Note - we don't set this anywhere in the class libraries in
+ // version 1, but it might come in handy for other developers who
+ // want to avoid sticking printf's in their code.
+ public virtual Object ActualValue {
+ get { return m_actualValue; }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("ActualValue", m_actualValue, typeof(Object));
+ }
+
+ protected ArgumentOutOfRangeException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ m_actualValue = info.GetValue("ActualValue", typeof(Object));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ArithmeticException.cs b/src/mscorlib/src/System/ArithmeticException.cs
new file mode 100644
index 0000000000..f5360939cc
--- /dev/null
+++ b/src/mscorlib/src/System/ArithmeticException.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for bad arithmetic conditions!
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ // The ArithmeticException is thrown when overflow or underflow
+ // occurs.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ArithmeticException : SystemException
+ {
+ // Creates a new ArithmeticException with its message string set to
+ // the empty string, its HRESULT set to COR_E_ARITHMETIC,
+ // and its ExceptionInfo reference set to null.
+ public ArithmeticException()
+ : base(Environment.GetResourceString("Arg_ArithmeticException")) {
+ SetErrorCode(__HResults.COR_E_ARITHMETIC);
+ }
+
+ // Creates a new ArithmeticException with its message string set to
+ // message, its HRESULT set to COR_E_ARITHMETIC,
+ // and its ExceptionInfo reference set to null.
+ //
+ public ArithmeticException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ARITHMETIC);
+ }
+
+ public ArithmeticException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_ARITHMETIC);
+ }
+
+ protected ArithmeticException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Array.cs b/src/mscorlib/src/System/Array.cs
new file mode 100644
index 0000000000..08790490f4
--- /dev/null
+++ b/src/mscorlib/src/System/Array.cs
@@ -0,0 +1,2858 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: Base class which can be used to access any array
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // Note that we make a T[] (single-dimensional w/ zero as the lower bound) implement both
+ // IList<U> and IReadOnlyList<U>, where T : U dynamically. See the SZArrayHelper class for details.
+ [Serializable]
+ [ComVisible(true)]
+ public abstract class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable
+ {
+ // This ctor exists solely to prevent C# from generating a protected .ctor that violates the surface area. I really want this to be a
+ // "protected-and-internal" rather than "internal" but C# has no keyword for the former.
+ internal Array() {}
+
+ public static ReadOnlyCollection<T> AsReadOnly<T>(T[] array) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<ReadOnlyCollection<T>>() != null);
+
+ // T[] implements IList<T>.
+ return new ReadOnlyCollection<T>(array);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static void Resize<T>(ref T[] array, int newSize) {
+ if (newSize < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.newSize, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.Ensures(Contract.ValueAtReturn(out array) != null);
+ Contract.Ensures(Contract.ValueAtReturn(out array).Length == newSize);
+ Contract.EndContractBlock();
+
+ T[] larray = array;
+ if (larray == null) {
+ array = new T[newSize];
+ return;
+ }
+
+ if (larray.Length != newSize) {
+ T[] newArray = new T[newSize];
+ Array.Copy(larray, 0, newArray, 0, larray.Length > newSize? newSize : larray.Length);
+ array = newArray;
+ }
+ }
+
+ // Create instance will create an array
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Array CreateInstance(Type elementType, int length)
+ {
+ if ((object)elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Length == length);
+ Contract.Ensures(Contract.Result<Array>().Rank == 1);
+ Contract.EndContractBlock();
+
+ RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+ return InternalCreate((void*)t.TypeHandle.Value,1,&length,null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Array CreateInstance(Type elementType, int length1, int length2)
+ {
+ if ((object)elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length1 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length2 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Rank == 2);
+ Contract.Ensures(Contract.Result<Array>().GetLength(0) == length1);
+ Contract.Ensures(Contract.Result<Array>().GetLength(1) == length2);
+
+ RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+ int* pLengths = stackalloc int[2];
+ pLengths[0] = length1;
+ pLengths[1] = length2;
+ return InternalCreate((void*)t.TypeHandle.Value,2,pLengths,null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Array CreateInstance(Type elementType, int length1, int length2, int length3)
+ {
+ if ((object)elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (length1 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length1, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length2 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length2, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (length3 < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length3, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Rank == 3);
+ Contract.Ensures(Contract.Result<Array>().GetLength(0) == length1);
+ Contract.Ensures(Contract.Result<Array>().GetLength(1) == length2);
+ Contract.Ensures(Contract.Result<Array>().GetLength(2) == length3);
+
+ RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+ int* pLengths = stackalloc int[3];
+ pLengths[0] = length1;
+ pLengths[1] = length2;
+ pLengths[2] = length3;
+ return InternalCreate((void*)t.TypeHandle.Value,3,pLengths,null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Array CreateInstance(Type elementType, params int[] lengths)
+ {
+ if ((object)elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (lengths == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
+ if (lengths.Length == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
+ Contract.EndContractBlock();
+
+ RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ // Check to make sure the lenghts are all positive. Note that we check this here to give
+ // a good exception message if they are not; however we check this again inside the execution
+ // engine's low level allocation function after having made a copy of the array to prevent a
+ // malicious caller from mutating the array after this check.
+ for (int i = 0; i < lengths.Length; i++)
+ if (lengths[i] < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ fixed (int* pLengths = lengths)
+ return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,null);
+ }
+
+ public static Array CreateInstance(Type elementType, params long[] lengths)
+ {
+ if( lengths == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
+ }
+ if (lengths.Length == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
+ Contract.EndContractBlock();
+
+ int[] intLengths = new int[lengths.Length];
+
+ for (int i = 0; i < lengths.Length; ++i)
+ {
+ long len = lengths[i];
+ if (len > Int32.MaxValue || len < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.len, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ intLengths[i] = (int) len;
+ }
+
+ return Array.CreateInstance(elementType, intLengths);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Array CreateInstance(Type elementType, int[] lengths,int[] lowerBounds)
+ {
+ if (elementType == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.elementType);
+ if (lengths == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lengths);
+ if (lowerBounds == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.lowerBounds);
+ if (lengths.Length != lowerBounds.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RanksAndBounds);
+ if (lengths.Length == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NeedAtLeast1Rank);
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.Ensures(Contract.Result<Array>().Rank == lengths.Length);
+ Contract.EndContractBlock();
+
+ RuntimeType t = elementType.UnderlyingSystemType as RuntimeType;
+ if (t == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_MustBeType, ExceptionArgument.elementType);
+
+ // Check to make sure the lenghts are all positive. Note that we check this here to give
+ // a good exception message if they are not; however we check this again inside the execution
+ // engine's low level allocation function after having made a copy of the array to prevent a
+ // malicious caller from mutating the array after this check.
+ for (int i=0;i<lengths.Length;i++)
+ if (lengths[i] < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.lengths, i, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ fixed (int* pLengths = lengths)
+ fixed(int* pLowerBounds = lowerBounds)
+ return InternalCreate((void*)t.TypeHandle.Value,lengths.Length,pLengths,pLowerBounds);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe static extern Array InternalCreate(void* elementType,int rank,int *pLengths,int *pLowerBounds);
+
+ [SecurityCritical]
+#if !FEATURE_CORECLR
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+#endif
+ internal static Array UnsafeCreateInstance(Type elementType, int length)
+ {
+ return CreateInstance(elementType, length);
+ }
+
+ [SecurityCritical]
+#if !FEATURE_CORECLR
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+#endif
+ internal static Array UnsafeCreateInstance(Type elementType, int length1, int length2)
+ {
+ return CreateInstance(elementType, length1, length2);
+ }
+
+ [SecurityCritical]
+#if !FEATURE_CORECLR
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+#endif
+ internal static Array UnsafeCreateInstance(Type elementType, params int[] lengths)
+ {
+ return CreateInstance(elementType, lengths);
+ }
+
+ [SecurityCritical]
+#if !FEATURE_CORECLR
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+#endif
+ internal static Array UnsafeCreateInstance(Type elementType, int[] lengths, int[] lowerBounds)
+ {
+ return CreateInstance(elementType, lengths, lowerBounds);
+ }
+
+ // Copies length elements from sourceArray, starting at index 0, to
+ // destinationArray, starting at index 0.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Copy(Array sourceArray, Array destinationArray, int length)
+ {
+ if (sourceArray == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.sourceArray);
+ if (destinationArray == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.destinationArray);
+ /*
+ Contract.Requires(sourceArray.Rank == destinationArray.Rank);
+ Contract.Requires(length >= 0);
+ Contract.Requires(length <= sourceArray.GetLowerBound(0) + sourceArray.Length);
+ Contract.Requires(length <= destinationArray.GetLowerBound(0) + destinationArray.Length);
+ */
+ Contract.EndContractBlock();
+
+ Copy(sourceArray, sourceArray.GetLowerBound(0), destinationArray, destinationArray.GetLowerBound(0), length, false);
+ }
+
+ // Copies length elements from sourceArray, starting at sourceIndex, to
+ // destinationArray, starting at destinationIndex.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
+ {
+ Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, false);
+ }
+
+ // Reliability-wise, this method will either possibly corrupt your
+ // instance & might fail when called from within a CER, or if the
+ // reliable flag is true, it will either always succeed or always
+ // throw an exception with no side effects.
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
+
+ // Provides a strong exception guarantee - either it succeeds, or
+ // it throws an exception with no side effects. The arrays must be
+ // compatible array types based on the array element type - this
+ // method does not support casting, boxing, or primitive widening.
+ // It will up-cast, assuming the array types are correct.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void ConstrainedCopy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length)
+ {
+ Copy(sourceArray, sourceIndex, destinationArray, destinationIndex, length, true);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Copy(Array sourceArray, Array destinationArray, long length)
+ {
+ if (length > Int32.MaxValue || length < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+
+ Array.Copy(sourceArray, destinationArray, (int) length);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Copy(Array sourceArray, long sourceIndex, Array destinationArray, long destinationIndex, long length)
+ {
+ if (sourceIndex > Int32.MaxValue || sourceIndex < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (destinationIndex > Int32.MaxValue || destinationIndex < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.destinationIndex, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (length > Int32.MaxValue || length < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+
+ Array.Copy(sourceArray, (int) sourceIndex, destinationArray, (int) destinationIndex, (int) length);
+ }
+
+
+ // Sets length elements in array to 0 (or null for Object arrays), starting
+ // at index.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern void Clear(Array array, int index, int length);
+
+ // The various Get values...
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe Object GetValue(params int[] indices)
+ {
+ if (indices == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
+ if (Rank != indices.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
+ Contract.EndContractBlock();
+
+ TypedReference elemref = new TypedReference();
+ fixed(int* pIndices = indices)
+ InternalGetReference(&elemref, indices.Length, pIndices);
+ return TypedReference.InternalToObject(&elemref);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe Object GetValue(int index)
+ {
+ if (Rank != 1)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray);
+ Contract.EndContractBlock();
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 1, &index);
+ return TypedReference.InternalToObject(&elemref);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe Object GetValue(int index1, int index2)
+ {
+ if (Rank != 2)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray);
+ Contract.EndContractBlock();
+
+ int* pIndices = stackalloc int[2];
+ pIndices[0] = index1;
+ pIndices[1] = index2;
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 2, pIndices);
+ return TypedReference.InternalToObject(&elemref);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe Object GetValue(int index1, int index2, int index3)
+ {
+ if (Rank != 3)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray);
+ Contract.EndContractBlock();
+
+ int* pIndices = stackalloc int[3];
+ pIndices[0] = index1;
+ pIndices[1] = index2;
+ pIndices[2] = index3;
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 3, pIndices);
+ return TypedReference.InternalToObject(&elemref);
+ }
+
+ [ComVisible(false)]
+ public Object GetValue(long index)
+ {
+ if (index > Int32.MaxValue || index < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ return this.GetValue((int) index);
+ }
+
+ [ComVisible(false)]
+ public Object GetValue(long index1, long index2)
+ {
+ if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ return this.GetValue((int) index1, (int) index2);
+ }
+
+ [ComVisible(false)]
+ public Object GetValue(long index1, long index2, long index3)
+ {
+ if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index3 > Int32.MaxValue || index3 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index3, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ return this.GetValue((int) index1, (int) index2, (int) index3);
+ }
+
+ [ComVisible(false)]
+ public Object GetValue(params long[] indices)
+ {
+ if (indices == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
+ if (Rank != indices.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
+ Contract.EndContractBlock();
+
+ int[] intIndices = new int[indices.Length];
+
+ for (int i = 0; i < indices.Length; ++i)
+ {
+ long index = indices[i];
+ if (index > Int32.MaxValue || index < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ intIndices[i] = (int) index;
+ }
+
+ return this.GetValue(intIndices);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe void SetValue(Object value,int index)
+ {
+ if (Rank != 1)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need1DArray);
+ Contract.EndContractBlock();
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 1, &index);
+ InternalSetValue(&elemref,value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe void SetValue(Object value,int index1, int index2)
+ {
+ if (Rank != 2)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need2DArray);
+ Contract.EndContractBlock();
+
+ int* pIndices = stackalloc int[2];
+ pIndices[0] = index1;
+ pIndices[1] = index2;
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 2, pIndices);
+ InternalSetValue(&elemref,value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe void SetValue(Object value,int index1, int index2, int index3)
+ {
+ if (Rank != 3)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_Need3DArray);
+ Contract.EndContractBlock();
+
+ int* pIndices = stackalloc int[3];
+ pIndices[0] = index1;
+ pIndices[1] = index2;
+ pIndices[2] = index3;
+
+ TypedReference elemref = new TypedReference();
+ InternalGetReference(&elemref, 3, pIndices);
+ InternalSetValue(&elemref,value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe void SetValue(Object value,params int[] indices)
+ {
+ if (indices == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
+ if (Rank != indices.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
+ Contract.EndContractBlock();
+
+ TypedReference elemref = new TypedReference();
+ fixed(int* pIndices = indices)
+ InternalGetReference(&elemref, indices.Length, pIndices);
+ InternalSetValue(&elemref,value);
+ }
+
+ [ComVisible(false)]
+ public void SetValue(Object value, long index)
+ {
+ if (index > Int32.MaxValue || index < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ this.SetValue(value, (int) index);
+ }
+
+ [ComVisible(false)]
+ public void SetValue(Object value, long index1, long index2)
+ {
+ if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ this.SetValue(value, (int) index1, (int) index2);
+ }
+
+ [ComVisible(false)]
+ public void SetValue(Object value, long index1, long index2, long index3)
+ {
+ if (index1 > Int32.MaxValue || index1 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index1, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index2 > Int32.MaxValue || index2 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index2, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ if (index3 > Int32.MaxValue || index3 < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index3, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ this.SetValue(value, (int) index1, (int) index2, (int) index3);
+ }
+
+ [ComVisible(false)]
+ public void SetValue(Object value, params long[] indices)
+ {
+ if (indices == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.indices);
+ if (Rank != indices.Length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankIndices);
+ Contract.EndContractBlock();
+
+ int[] intIndices = new int[indices.Length];
+
+ for (int i = 0; i < indices.Length; ++i)
+ {
+ long index = indices[i];
+ if (index > Int32.MaxValue || index < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ intIndices[i] = (int) index;
+ }
+
+ this.SetValue(value, intIndices);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ // reference to TypedReference is banned, so have to pass result as pointer
+ private unsafe extern void InternalGetReference(void * elemRef, int rank, int * pIndices);
+
+ // Ideally, we would like to use TypedReference.SetValue instead. Unfortunately, TypedReference.SetValue
+ // always throws not-supported exception
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe extern static void InternalSetValue(void * target, Object value);
+
+ public extern int Length {
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static int GetMedian(int low, int hi) {
+ // Note both may be negative, if we are dealing with arrays w/ negative lower bounds.
+ Contract.Requires(low <= hi);
+ Contract.Assert( hi - low >= 0, "Length overflow!");
+ return low + ((hi - low) >> 1);
+ }
+
+ // We impose limits on maximum array lenght in each dimension to allow efficient
+ // implementation of advanced range check elimination in future.
+ // Keep in sync with vm\gcscan.cpp and HashHelpers.MaxPrimeArrayLength.
+ // The constants are defined in this method: inline SIZE_T MaxArrayLength(SIZE_T componentSize) from gcscan
+ // We have different max sizes for arrays with elements of size 1 for backwards compatibility
+ internal const int MaxArrayLength = 0X7FEFFFFF;
+ internal const int MaxByteArrayLength = 0x7FFFFFC7;
+
+ [ComVisible(false)]
+ public extern long LongLength {
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern int GetLength(int dimension);
+
+ [Pure]
+ [ComVisible(false)]
+ public long GetLongLength(int dimension) {
+ //This method should throw an IndexOufOfRangeException for compat if dimension < 0 or >= Rank
+ return GetLength(dimension);
+ }
+
+ public extern int Rank {
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public extern int GetUpperBound(int dimension);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern int GetLowerBound(int dimension);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern int GetDataPtrOffsetInternal();
+
+ // Number of elements in the Array.
+ int ICollection.Count
+ { get { return Length; } }
+
+
+ // Returns an object appropriate for synchronizing access to this
+ // Array.
+ public Object SyncRoot
+ { get { return this; } }
+
+ // Is this Array read-only?
+ public bool IsReadOnly
+ { get { return false; } }
+
+ public bool IsFixedSize {
+ get { return true; }
+ }
+
+ // Is this Array synchronized (i.e., thread-safe)? If you want a synchronized
+ // collection, you can use SyncRoot as an object to synchronize your
+ // collection with. You could also call GetSynchronized()
+ // to get a synchronized wrapper around the Array.
+ public bool IsSynchronized
+ { get { return false; } }
+
+
+ Object IList.this[int index] {
+ get { return GetValue(index); }
+ set { SetValue(value, index); }
+ }
+
+ int IList.Add(Object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ return default(int);
+ }
+
+ bool IList.Contains(Object value)
+ {
+ return Array.IndexOf(this, value) >= this.GetLowerBound(0);
+ }
+
+ void IList.Clear()
+ {
+ Array.Clear(this, this.GetLowerBound(0), this.Length);
+ }
+
+ int IList.IndexOf(Object value)
+ {
+ return Array.IndexOf(this, value);
+ }
+
+ void IList.Insert(int index, Object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ void IList.Remove(Object value)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ // Make a new array which is a shallow copy of the original array.
+ //
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) {
+ return 1;
+ }
+
+ Array o = other as Array;
+
+ if (o == null || this.Length != o.Length)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.ArgumentException_OtherNotArrayOfCorrectLength, ExceptionArgument.other);
+ }
+
+ int i = 0;
+ int c = 0;
+
+ while (i < o.Length && c == 0) {
+ object left = GetValue(i);
+ object right = o.GetValue(i);
+
+ c = comparer.Compare(left, right);
+ i++;
+ }
+
+ return c;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+
+ if (other == null) {
+ return false;
+ }
+
+ if (Object.ReferenceEquals(this, other)) {
+ return true;
+ }
+
+ Array o = other as Array;
+
+ if (o == null || o.Length != this.Length) {
+ return false;
+ }
+
+ int i = 0;
+ while (i < o.Length) {
+ object left = GetValue(i);
+ object right = o.GetValue(i);
+
+ if (!comparer.Equals(left, right)) {
+ return false;
+ }
+ i++;
+ }
+
+ return true;
+ }
+
+ // From System.Web.Util.HashCodeCombiner
+ internal static int CombineHashCodes(int h1, int h2) {
+ return (((h1 << 5) + h1) ^ h2);
+ }
+
+ int IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ if (comparer == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparer);
+ Contract.EndContractBlock();
+
+ int ret = 0;
+
+ for (int i = (this.Length >= 8 ? this.Length - 8 : 0); i < this.Length; i++) {
+ ret = CombineHashCodes(ret, comparer.GetHashCode(GetValue(i)));
+ }
+
+ return ret;
+ }
+
+ // Searches an array for a given element using a binary search algorithm.
+ // Elements of the array are compared to the search value using the
+ // IComparable interface, which must be implemented by all elements
+ // of the array and the given search value. This method assumes that the
+ // array is already sorted according to the IComparable interface;
+ // if this is not the case, the result will be incorrect.
+ //
+ // The method returns the index of the given value in the array. If the
+ // array does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value.
+ //
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch(Array array, Object value) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures((Contract.Result<int>() >= array.GetLowerBound(0) && Contract.Result<int>() <= array.GetUpperBound(0)) || (Contract.Result<int>() < array.GetLowerBound(0) && ~Contract.Result<int>() <= array.GetUpperBound(0) + 1));
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return BinarySearch(array, lb, array.Length, value, null);
+ }
+
+ // Searches a section of an array for a given element using a binary search
+ // algorithm. Elements of the array are compared to the search value using
+ // the IComparable interface, which must be implemented by all
+ // elements of the array and the given search value. This method assumes
+ // that the array is already sorted according to the IComparable
+ // interface; if this is not the case, the result will be incorrect.
+ //
+ // The method returns the index of the given value in the array. If the
+ // array does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value.
+ //
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch(Array array, int index, int length, Object value) {
+ return BinarySearch(array, index, length, value, null);
+ }
+
+ // Searches an array for a given element using a binary search algorithm.
+ // Elements of the array are compared to the search value using the given
+ // IComparer interface. If comparer is null, elements of the
+ // array are compared to the search value using the IComparable
+ // interface, which in that case must be implemented by all elements of the
+ // array and the given search value. This method assumes that the array is
+ // already sorted; if this is not the case, the result will be incorrect.
+ //
+ // The method returns the index of the given value in the array. If the
+ // array does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value.
+ //
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch(Array array, Object value, IComparer comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return BinarySearch(array, lb, array.Length, value, comparer);
+ }
+
+ // Searches a section of an array for a given element using a binary search
+ // algorithm. Elements of the array are compared to the search value using
+ // the given IComparer interface. If comparer is null,
+ // elements of the array are compared to the search value using the
+ // IComparable interface, which in that case must be implemented by
+ // all elements of the array and the given search value. This method
+ // assumes that the array is already sorted; if this is not the case, the
+ // result will be incorrect.
+ //
+ // The method returns the index of the given value in the array. If the
+ // array does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value.
+ //
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch(Array array, int index, int length, Object value, IComparer comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ if (index < lb)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - (index - lb) < length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ if (array.Rank != 1)
+ ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
+
+ if (comparer == null) comparer = Comparer.Default;
+ if (comparer == Comparer.Default) {
+ int retval;
+ bool r = TrySZBinarySearch(array, index, length, value, out retval);
+ if (r)
+ return retval;
+ }
+
+ int lo = index;
+ int hi = index + length - 1;
+ Object[] objArray = array as Object[];
+ if(objArray != null) {
+ while (lo <= hi) {
+ // i might overflow if lo and hi are both large positive numbers.
+ int i = GetMedian(lo, hi);
+
+ int c = 0;
+ try {
+ c = comparer.Compare(objArray[i], value);
+ }
+ catch (Exception e) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ if (c == 0) return i;
+ if (c < 0) {
+ lo = i + 1;
+ }
+ else {
+ hi = i - 1;
+ }
+ }
+ }
+ else {
+ while (lo <= hi) {
+ int i = GetMedian(lo, hi);
+
+ int c = 0;
+ try {
+ c = comparer.Compare(array.GetValue(i), value);
+ }
+ catch (Exception e) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ if (c == 0) return i;
+ if (c < 0) {
+ lo = i + 1;
+ }
+ else {
+ hi = i - 1;
+ }
+ }
+ }
+ return ~lo;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern bool TrySZBinarySearch(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch<T>(T[] array, T value) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ return BinarySearch<T>(array, 0, array.Length, value, null);
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch<T>(T[] array, T value, System.Collections.Generic.IComparer<T> comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ return BinarySearch<T>(array, 0, array.Length, value, comparer);
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch<T>(T[] array, int index, int length, T value) {
+ return BinarySearch<T>(array, index, length, value, null);
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int BinarySearch<T>(T[] array, int index, int length, T value, System.Collections.Generic.IComparer<T> comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (index < 0)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (array.Length - index < length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ return ArraySortHelper<T>.Default.BinarySearch(array, index, length, value, comparer);
+ }
+
+ public static TOutput[] ConvertAll<TInput, TOutput>(TInput[] array, Converter<TInput,TOutput> converter) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( converter == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
+ }
+ Contract.Ensures(Contract.Result<TOutput[]>() != null);
+ Contract.Ensures(Contract.Result<TOutput[]>().Length == array.Length);
+ Contract.EndContractBlock();
+
+ TOutput[] newArray = new TOutput[array.Length];
+ for( int i = 0; i< array.Length; i++) {
+ newArray[i] = converter(array[i]);
+ }
+ return newArray;
+ }
+
+ // CopyTo copies a collection into an Array, starting at a particular
+ // index into the array.
+ //
+ // This method is to support the ICollection interface, and calls
+ // Array.Copy internally. If you aren't using ICollection explicitly,
+ // call Array.Copy to avoid an extra indirection.
+ //
+ [Pure]
+ public void CopyTo(Array array, int index)
+ {
+ if (array != null && array.Rank != 1)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ Contract.EndContractBlock();
+ // Note: Array.Copy throws a RankException and we want a consistent ArgumentException for all the IList CopyTo methods.
+ Array.Copy(this, GetLowerBound(0), array, index, Length);
+ }
+
+ [Pure]
+ [ComVisible(false)]
+ public void CopyTo(Array array, long index)
+ {
+ if (index > Int32.MaxValue || index < Int32.MinValue)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_HugeArrayNotSupported);
+ Contract.EndContractBlock();
+
+ this.CopyTo(array, (int) index);
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static T[] Empty<T>()
+ {
+ Contract.Ensures(Contract.Result<T[]>() != null);
+ Contract.Ensures(Contract.Result<T[]>().Length == 0);
+ Contract.EndContractBlock();
+
+ return EmptyArray<T>.Value;
+ }
+
+ public static bool Exists<T>(T[] array, Predicate<T> match) {
+ return Array.FindIndex(array, match) != -1;
+ }
+
+ public static T Find<T>(T[] array, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0 ; i < array.Length; i++) {
+ if(match(array[i])) {
+ return array[i];
+ }
+ }
+ return default(T);
+ }
+
+ public static T[] FindAll<T>(T[] array, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ List<T> list = new List<T>();
+ for(int i = 0 ; i < array.Length; i++) {
+ if(match(array[i])) {
+ list.Add(array[i]);
+ }
+ }
+ return list.ToArray();
+ }
+
+ public static int FindIndex<T>(T[] array, Predicate<T> match) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ return FindIndex(array, 0, array.Length, match);
+ }
+
+ public static int FindIndex<T>(T[] array, int startIndex, Predicate<T> match) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ return FindIndex(array, startIndex, array.Length - startIndex, match);
+ }
+
+ public static int FindIndex<T>(T[] array, int startIndex, int count, Predicate<T> match) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( startIndex < 0 || startIndex > array.Length ) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (count < 0 || startIndex > array.Length - count) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ int endIndex = startIndex + count;
+ for( int i = startIndex; i < endIndex; i++) {
+ if( match(array[i])) return i;
+ }
+ return -1;
+ }
+
+ public static T FindLast<T>(T[] array, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = array.Length - 1 ; i >= 0; i--) {
+ if(match(array[i])) {
+ return array[i];
+ }
+ }
+ return default(T);
+ }
+
+ public static int FindLastIndex<T>(T[] array, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.EndContractBlock();
+
+ return FindLastIndex(array, array.Length - 1, array.Length, match);
+ }
+
+ public static int FindLastIndex<T>(T[] array, int startIndex, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.EndContractBlock();
+
+ return FindLastIndex(array, startIndex, startIndex + 1, match);
+ }
+
+ public static int FindLastIndex<T>(T[] array, int startIndex, int count, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ if(array.Length == 0) {
+ // Special case for 0 length List
+ if( startIndex != -1) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+ }
+ else {
+ // Make sure we're not out of range
+ if ( startIndex < 0 || startIndex >= array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+ }
+
+ // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+
+ int endIndex = startIndex - count;
+ for( int i = startIndex; i > endIndex; i--) {
+ if( match(array[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public static void ForEach<T>(T[] array, Action<T> action) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( action == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0 ; i < array.Length; i++) {
+ action(array[i]);
+ }
+ }
+
+ // GetEnumerator returns an IEnumerator over this Array.
+ //
+ // Currently, only one dimensional arrays are supported.
+ //
+ public IEnumerator GetEnumerator()
+ {
+ int lowerBound = GetLowerBound(0);
+ if (Rank == 1 && lowerBound == 0)
+ return new SZArrayEnumerator(this);
+ else
+ return new ArrayEnumerator(this, lowerBound, Length);
+ }
+
+ // Returns the index of the first occurrence of a given value in an array.
+ // The array is searched forwards, and the elements of the array are
+ // compared to the given value using the Object.Equals method.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int IndexOf(Array array, Object value) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return IndexOf(array, value, lb, array.Length);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // an array. The array is searched forwards, starting at index
+ // startIndex and ending at the last element of the array. The
+ // elements of the array are compared to the given value using the
+ // Object.Equals method.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int IndexOf(Array array, Object value, int startIndex) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return IndexOf(array, value, startIndex, array.Length - startIndex + lb);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // an array. The array is searched forwards, starting at index
+ // startIndex and upto count elements. The
+ // elements of the array are compared to the given value using the
+ // Object.Equals method.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int IndexOf(Array array, Object value, int startIndex, int count) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (array.Rank != 1)
+ ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+
+ int lb = array.GetLowerBound(0);
+ if (startIndex < lb || startIndex > array.Length + lb)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (count < 0 || count > array.Length - startIndex + lb)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+
+ // Try calling a quick native method to handle primitive types.
+ int retVal;
+ bool r = TrySZIndexOf(array, startIndex, count, value, out retVal);
+ if (r)
+ return retVal;
+
+ Object[] objArray = array as Object[];
+ int endIndex = startIndex + count;
+ if (objArray != null) {
+ if (value == null) {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (objArray[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i < endIndex; i++) {
+ Object obj = objArray[i];
+ if (obj != null && obj.Equals(value)) return i;
+ }
+ }
+ }
+ else {
+ for (int i = startIndex; i < endIndex; i++) {
+ Object obj = array.GetValue(i);
+ if( obj == null) {
+ if(value == null) return i;
+ }
+ else {
+ if( obj.Equals(value)) return i;
+ }
+ }
+ }
+ // Return one less than the lower bound of the array. This way,
+ // for arrays with a lower bound of -1 we will not return -1 when the
+ // item was not found. And for SZArrays (the vast majority), -1 still
+ // works for them.
+ return lb-1;
+ }
+
+ [Pure]
+ public static int IndexOf<T>(T[] array, T value) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures((Contract.Result<int>() < 0) ||
+ (Contract.Result<int>() >= 0 && Contract.Result<int>() < array.Length && EqualityComparer<T>.Default.Equals(value, array[Contract.Result<int>()])));
+ Contract.EndContractBlock();
+
+ return IndexOf(array, value, 0, array.Length);
+ }
+
+ public static int IndexOf<T>(T[] array, T value, int startIndex) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ return IndexOf(array, value, startIndex, array.Length - startIndex);
+ }
+
+ public static int IndexOf<T>(T[] array, T value, int startIndex, int count) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (startIndex < 0 || startIndex > array.Length ) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (count < 0 || count > array.Length - startIndex) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ return EqualityComparer<T>.Default.IndexOf(array, value, startIndex, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern bool TrySZIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
+
+
+ // Returns the index of the last occurrence of a given value in an array.
+ // The array is searched backwards, and the elements of the array are
+ // compared to the given value using the Object.Equals method.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int LastIndexOf(Array array, Object value) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return LastIndexOf(array, value, array.Length - 1 + lb, array.Length);
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // an array. The array is searched backwards, starting at index
+ // startIndex and ending at index 0. The elements of the array are
+ // compared to the given value using the Object.Equals method.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int LastIndexOf(Array array, Object value, int startIndex) {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ return LastIndexOf(array, value, startIndex, startIndex + 1 - lb);
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // an array. The array is searched backwards, starting at index
+ // startIndex and counting uptocount elements. The elements of
+ // the array are compared to the given value using the Object.Equals
+ // method.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int LastIndexOf(Array array, Object value, int startIndex, int count) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.Ensures(Contract.Result<int>() < array.GetLowerBound(0) + array.Length);
+ Contract.EndContractBlock();
+ int lb = array.GetLowerBound(0);
+ if (array.Length == 0) {
+ return lb-1;
+ }
+
+ if (startIndex < lb || startIndex >= array.Length + lb)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (count < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ if (count > startIndex - lb + 1)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.endIndex, ExceptionResource.ArgumentOutOfRange_EndIndexStartIndex);
+ if (array.Rank != 1)
+ ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
+
+ // Try calling a quick native method to handle primitive types.
+ int retVal;
+ bool r = TrySZLastIndexOf(array, startIndex, count, value, out retVal);
+ if (r)
+ return retVal;
+
+ Object[] objArray = array as Object[];
+ int endIndex = startIndex - count + 1;
+ if (objArray!=null) {
+ if (value == null) {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (objArray[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i >= endIndex; i--) {
+ Object obj = objArray[i];
+ if (obj != null && obj.Equals(value)) return i;
+ }
+ }
+ }
+ else {
+ for (int i = startIndex; i >= endIndex; i--) {
+ Object obj = array.GetValue(i);
+ if( obj == null) {
+ if(value == null) return i;
+ }
+ else {
+ if( obj.Equals(value)) return i;
+ }
+ }
+ }
+ return lb-1; // Return lb-1 for arrays with negative lower bounds.
+ }
+
+ public static int LastIndexOf<T>(T[] array, T value) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ return LastIndexOf(array, value, array.Length - 1, array.Length);
+ }
+
+ public static int LastIndexOf<T>(T[] array, T value, int startIndex) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+ // if array is empty and startIndex is 0, we need to pass 0 as count
+ return LastIndexOf(array, value, startIndex, (array.Length == 0)? 0 : (startIndex + 1));
+ }
+
+ public static int LastIndexOf<T>(T[] array, T value, int startIndex, int count) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+ Contract.Ensures(Contract.Result<int>() < array.Length);
+ Contract.EndContractBlock();
+
+ if(array.Length == 0) {
+ //
+ // Special case for 0 length List
+ // accept -1 and 0 as valid startIndex for compablility reason.
+ //
+ if( startIndex != -1 && startIndex != 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ // only 0 is a valid value for count if array is empty
+ if( count != 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+ return -1;
+ }
+
+ // Make sure we're not out of range
+ if ( startIndex < 0 || startIndex >= array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+
+ return EqualityComparer<T>.Default.LastIndexOf(array, value, startIndex, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern bool TrySZLastIndexOf(Array sourceArray, int sourceIndex, int count, Object value, out int retVal);
+
+
+ // Reverses all elements of the given array. Following a call to this
+ // method, an element previously located at index i will now be
+ // located at index length - i - 1, where length is the
+ // length of the array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Reverse(Array array) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ Reverse(array, array.GetLowerBound(0), array.Length);
+ }
+
+ // Reverses the elements in a range of an array. Following a call to this
+ // method, an element in the range given by index and count
+ // which was previously located at index i will now be located at
+ // index index + (index + count - i - 1).
+ // Reliability note: This may fail because it may have to box objects.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Reverse(Array array, int index, int length) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ int lowerBound = array.GetLowerBound(0);
+ if (index < lowerBound)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (array.Length - (index - lowerBound) < length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ if (array.Rank != 1)
+ ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
+ Contract.EndContractBlock();
+
+ bool r = TrySZReverse(array, index, length);
+ if (r)
+ return;
+
+ int i = index;
+ int j = index + length - 1;
+ Object[] objArray = array as Object[];
+ if (objArray!=null) {
+ while (i < j) {
+ Object temp = objArray[i];
+ objArray[i] = objArray[j];
+ objArray[j] = temp;
+ i++;
+ j--;
+ }
+ }
+ else {
+ while (i < j) {
+ Object temp = array.GetValue(i);
+ array.SetValue(array.GetValue(j), i);
+ array.SetValue(temp, j);
+ i++;
+ j--;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ private static extern bool TrySZReverse(Array array, int index, int count);
+
+ // Sorts the elements of an array. The sort compares the elements to each
+ // other using the IComparable interface, which must be implemented
+ // by all elements of the array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array array) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ Sort(array, null, array.GetLowerBound(0), array.Length, null);
+ }
+
+ // Sorts the elements of two arrays based on the keys in the first array.
+ // Elements in the keys array specify the sort keys for
+ // corresponding elements in the items array. The sort compares the
+ // keys to each other using the IComparable interface, which must be
+ // implemented by all elements of the keys array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array keys, Array items) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ Contract.EndContractBlock();
+ Sort(keys, items, keys.GetLowerBound(0), keys.Length, null);
+ }
+
+ // Sorts the elements in a section of an array. The sort compares the
+ // elements to each other using the IComparable interface, which
+ // must be implemented by all elements in the given section of the array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array array, int index, int length) {
+ Sort(array, null, index, length, null);
+ }
+
+ // Sorts the elements in a section of two arrays based on the keys in the
+ // first array. Elements in the keys array specify the sort keys for
+ // corresponding elements in the items array. The sort compares the
+ // keys to each other using the IComparable interface, which must be
+ // implemented by all elements of the keys array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array keys, Array items, int index, int length) {
+ Sort(keys, items, index, length, null);
+ }
+
+ // Sorts the elements of an array. The sort compares the elements to each
+ // other using the given IComparer interface. If comparer is
+ // null, the elements are compared to each other using the
+ // IComparable interface, which in that case must be implemented by
+ // all elements of the array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array array, IComparer comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ Sort(array, null, array.GetLowerBound(0), array.Length, comparer);
+ }
+
+ // Sorts the elements of two arrays based on the keys in the first array.
+ // Elements in the keys array specify the sort keys for
+ // corresponding elements in the items array. The sort compares the
+ // keys to each other using the given IComparer interface. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented
+ // by all elements of the keys array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array keys, Array items, IComparer comparer) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ Contract.EndContractBlock();
+ Sort(keys, items, keys.GetLowerBound(0), keys.Length, comparer);
+ }
+
+ // Sorts the elements in a section of an array. The sort compares the
+ // elements to each other using the given IComparer interface. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented
+ // by all elements in the given section of the array.
+ //
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array array, int index, int length, IComparer comparer) {
+ Sort(array, null, index, length, comparer);
+ }
+
+ // Sorts the elements in a section of two arrays based on the keys in the
+ // first array. Elements in the keys array specify the sort keys for
+ // corresponding elements in the items array. The sort compares the
+ // keys to each other using the given IComparer interface. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented
+ // by all elements of the given section of the keys array.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort(Array keys, Array items, int index, int length, IComparer comparer) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ if (keys.Rank != 1 || (items != null && items.Rank != 1))
+ ThrowHelper.ThrowRankException(ExceptionResource.Rank_MultiDimNotSupported);
+ int keysLowerBound = keys.GetLowerBound(0);
+ if (items != null && keysLowerBound != items.GetLowerBound(0))
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_LowerBoundsMustMatch);
+ if (index < keysLowerBound)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+ if (keys.Length - (index - keysLowerBound) < length || (items != null && (index - keysLowerBound) > items.Length - length))
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+
+ Contract.EndContractBlock();
+
+ if (length > 1) {
+ if (comparer == Comparer.Default || comparer == null) {
+ bool r = TrySZSort(keys, items, index, index + length - 1);
+ if (r)
+ return;
+ }
+
+ Object[] objKeys = keys as Object[];
+ Object[] objItems = null;
+ if (objKeys != null)
+ objItems = items as Object[];
+ if (objKeys != null && (items==null || objItems != null)) {
+ SorterObjectArray sorter = new SorterObjectArray(objKeys, objItems, comparer);
+ sorter.Sort(index, length);
+ }
+ else {
+ SorterGenericArray sorter = new SorterGenericArray(keys, items, comparer);
+ sorter.Sort(index, length);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ private static extern bool TrySZSort(Array keys, Array items, int left, int right);
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<T>(T[] array) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ Sort<T>(array, 0, array.Length, null);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ Contract.EndContractBlock();
+ Sort<TKey, TValue>(keys, items, 0, keys.Length, null);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<T>(T[] array, int index, int length) {
+ Sort<T>(array, index, length, null);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length) {
+ Sort<TKey, TValue>(keys, items, index, length, null);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<T>(T[] array, System.Collections.Generic.IComparer<T> comparer) {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+ Sort<T>(array, 0, array.Length, comparer);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, System.Collections.Generic.IComparer<TKey> comparer) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ Contract.EndContractBlock();
+ Sort<TKey, TValue>(keys, items, 0, keys.Length, comparer);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<T>(T[] array, int index, int length, System.Collections.Generic.IComparer<T> comparer) {
+ if (array==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (index < 0)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - index < length)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ if (length > 1) {
+ if ( comparer == null || comparer == Comparer<T>.Default ) {
+ if(TrySZSort(array, null, index, index + length - 1)) {
+ return;
+ }
+ }
+
+ ArraySortHelper<T>.Default.Sort(array, index, length, comparer);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ public static void Sort<TKey, TValue>(TKey[] keys, TValue[] items, int index, int length, System.Collections.Generic.IComparer<TKey> comparer) {
+ if (keys==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys);
+ if (index < 0)
+ ThrowHelper.ThrowIndexArgumentOutOfRange_NeedNonNegNumException();
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (keys.Length - index < length || (items != null && index > items.Length - length))
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ if (length > 1) {
+ if ( comparer == null || comparer == Comparer<TKey>.Default ) {
+ if(TrySZSort(keys, items, index, index + length - 1)) {
+ return;
+ }
+ }
+
+ if (items == null)
+ {
+ Sort<TKey>(keys, index, length, comparer);
+ return;
+ }
+
+ ArraySortHelper<TKey, TValue>.Default.Sort(keys, items, index, length, comparer);
+ }
+ }
+
+ public static void Sort<T>(T[] array, Comparison<T> comparison) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( comparison == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
+ }
+ Contract.EndContractBlock();
+
+ IComparer<T> comparer = Comparer<T>.Create(comparison);
+ Array.Sort(array, comparer);
+ }
+
+ public static bool TrueForAll<T>(T[] array, Predicate<T> match) {
+ if( array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0 ; i < array.Length; i++) {
+ if( !match(array[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ // Private value type used by the Sort methods.
+ private struct SorterObjectArray
+ {
+ private Object[] keys;
+ private Object[] items;
+ private IComparer comparer;
+
+ internal SorterObjectArray(Object[] keys, Object[] items, IComparer comparer) {
+ if (comparer == null) comparer = Comparer.Default;
+ this.keys = keys;
+ this.items = items;
+ this.comparer = comparer;
+ }
+
+ internal void SwapIfGreaterWithItems(int a, int b)
+ {
+ if (a != b)
+ {
+ if (comparer.Compare(keys[a], keys[b]) > 0)
+ {
+ Object temp = keys[a];
+ keys[a] = keys[b];
+ keys[b] = temp;
+ if (items != null)
+ {
+ Object item = items[a];
+ items[a] = items[b];
+ items[b] = item;
+ }
+ }
+ }
+ }
+
+ private void Swap(int i, int j)
+ {
+ Object t = keys[i];
+ keys[i] = keys[j];
+ keys[j] = t;
+
+ if (items != null)
+ {
+ Object item = items[i];
+ items[i] = items[j];
+ items[j] = item;
+ }
+ }
+
+ internal void Sort(int left, int length)
+ {
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(left, length);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(left, length);
+ }
+ else
+ {
+ DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+
+ private void DepthLimitedQuickSort(int left, int right, int depthLimit)
+ {
+ // Can use the much faster jit helpers for array access.
+ do
+ {
+ if (depthLimit == 0)
+ {
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ Heapsort(left, right);
+ return;
+ }
+ catch (IndexOutOfRangeException)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = GetMedian(i, j);
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(i, j); // swap the low with the high
+ SwapIfGreaterWithItems(middle, j); // swap the middle with the high
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ Object x = keys[middle];
+ do
+ {
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ while (comparer.Compare(keys[i], x) < 0) i++;
+ while (comparer.Compare(x, keys[j]) < 0) j--;
+ }
+ catch (IndexOutOfRangeException)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ Object key = keys[i];
+ keys[i] = keys[j];
+ keys[j] = key;
+ if (items != null)
+ {
+ Object item = items[i];
+ items[i] = items[j];
+ items[j] = item;
+ }
+ }
+ i++;
+ j--;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(left, j, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(i, right, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ private void IntrospectiveSort(int left, int length)
+ {
+ if (length < 2)
+ return;
+
+ try
+ {
+ IntroSort(left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private void IntroSort(int lo, int hi, int depthLimit)
+ {
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(lo, hi-1);
+ SwapIfGreaterWithItems(lo, hi);
+ SwapIfGreaterWithItems(hi-1, hi);
+ return;
+ }
+
+ InsertionSort(lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(lo, hi);
+ IntroSort(p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private int PickPivotAndPartition(int lo, int hi)
+ {
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int mid = lo + (hi - lo) / 2;
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(lo, mid);
+ SwapIfGreaterWithItems(lo, hi);
+ SwapIfGreaterWithItems(mid, hi);
+
+ Object pivot = keys[mid];
+ Swap(mid, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys[++left], pivot) < 0) ;
+ while (comparer.Compare(pivot, keys[--right]) < 0) ;
+
+ if(left >= right)
+ break;
+
+ Swap(left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(left, (hi - 1));
+ return left;
+ }
+
+ private void Heapsort(int lo, int hi)
+ {
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(lo, lo + i - 1);
+
+ DownHeap(1, i - 1, lo);
+ }
+ }
+
+ private void DownHeap(int i, int n, int lo)
+ {
+ Object d = keys[lo + i - 1];
+ Object dt = (items != null) ? items[lo + i - 1] : null;
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ if(items != null)
+ items[lo + i - 1] = items[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ if (items != null)
+ items[lo + i - 1] = dt;
+ }
+
+ private void InsertionSort(int lo, int hi)
+ {
+ int i, j;
+ Object t, ti;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ ti = (items != null) ? items[i + 1] : null;
+ while (j >= lo && comparer.Compare(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ if(items != null)
+ items[j + 1] = items[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ if(items != null)
+ items[j + 1] = ti;
+ }
+ }
+ }
+
+ // Private value used by the Sort methods for instances of Array.
+ // This is slower than the one for Object[], since we can't use the JIT helpers
+ // to access the elements. We must use GetValue & SetValue.
+ private struct SorterGenericArray
+ {
+ private Array keys;
+ private Array items;
+ private IComparer comparer;
+
+ internal SorterGenericArray(Array keys, Array items, IComparer comparer)
+ {
+ if (comparer == null) comparer = Comparer.Default;
+ this.keys = keys;
+ this.items = items;
+ this.comparer = comparer;
+ }
+
+ internal void SwapIfGreaterWithItems(int a, int b)
+ {
+ if (a != b)
+ {
+ if (comparer.Compare(keys.GetValue(a), keys.GetValue(b)) > 0)
+ {
+ Object key = keys.GetValue(a);
+ keys.SetValue(keys.GetValue(b), a);
+ keys.SetValue(key, b);
+ if (items != null)
+ {
+ Object item = items.GetValue(a);
+ items.SetValue(items.GetValue(b), a);
+ items.SetValue(item, b);
+ }
+ }
+ }
+ }
+
+ private void Swap(int i, int j)
+ {
+ Object t1 = keys.GetValue(i);
+ keys.SetValue(keys.GetValue(j), i);
+ keys.SetValue(t1, j);
+
+ if(items != null)
+ {
+ Object t2 = items.GetValue(i);
+ items.SetValue(items.GetValue(j), i);
+ items.SetValue(t2, j);
+ }
+ }
+
+ internal void Sort(int left, int length)
+ {
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(left, length);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(left, length);
+ }
+ else
+ {
+ DepthLimitedQuickSort(left, length + left - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+
+ private void DepthLimitedQuickSort(int left, int right, int depthLimit)
+ {
+ // Must use slow Array accessors (GetValue & SetValue)
+ do
+ {
+ if (depthLimit == 0)
+ {
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ Heapsort(left, right);
+ return;
+ }
+ catch (IndexOutOfRangeException)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = GetMedian(i, j);
+ try
+ {
+ SwapIfGreaterWithItems(i, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(i, j); // swap the low with the high
+ SwapIfGreaterWithItems(middle, j); // swap the middle with the high
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+
+ Object x = keys.GetValue(middle);
+ do
+ {
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ while (comparer.Compare(keys.GetValue(i), x) < 0) i++;
+ while (comparer.Compare(x, keys.GetValue(j)) < 0) j--;
+ }
+ catch (IndexOutOfRangeException)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_BogusIComparer, ExceptionArgument.comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ Object key = keys.GetValue(i);
+ keys.SetValue(keys.GetValue(j), i);
+ keys.SetValue(key, j);
+ if (items != null)
+ {
+ Object item = items.GetValue(i);
+ items.SetValue(items.GetValue(j), i);
+ items.SetValue(item, j);
+ }
+ }
+ if (i != Int32.MaxValue) ++i;
+ if (j != Int32.MinValue) --j;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(left, j, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(i, right, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ private void IntrospectiveSort(int left, int length)
+ {
+ if (length < 2)
+ return;
+
+ try
+ {
+ IntroSort(left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_IComparerFailed, e);
+ }
+ }
+
+ private void IntroSort(int lo, int hi, int depthLimit)
+ {
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(lo, hi-1);
+ SwapIfGreaterWithItems(lo, hi);
+ SwapIfGreaterWithItems(hi-1, hi);
+ return;
+ }
+
+ InsertionSort(lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(lo, hi);
+ IntroSort(p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private int PickPivotAndPartition(int lo, int hi)
+ {
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int mid = lo + (hi - lo) / 2;
+
+ SwapIfGreaterWithItems(lo, mid);
+ SwapIfGreaterWithItems(lo, hi);
+ SwapIfGreaterWithItems(mid, hi);
+
+ Object pivot = keys.GetValue(mid);
+ Swap(mid, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys.GetValue(++left), pivot) < 0) ;
+ while (comparer.Compare(pivot, keys.GetValue(--right)) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(left, (hi - 1));
+ return left;
+ }
+
+ private void Heapsort(int lo, int hi)
+ {
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(lo, lo + i - 1);
+
+ DownHeap(1, i - 1, lo);
+ }
+ }
+
+ private void DownHeap(int i, int n, int lo)
+ {
+ Object d = keys.GetValue(lo + i - 1);
+ Object dt = (items != null)? items.GetValue(lo + i - 1) : null;
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys.GetValue(lo + child - 1), keys.GetValue(lo + child)) < 0)
+ {
+ child++;
+ }
+
+ if (!(comparer.Compare(d, keys.GetValue(lo + child - 1)) < 0))
+ break;
+
+ keys.SetValue(keys.GetValue(lo + child - 1), lo + i - 1);
+ if(items != null)
+ items.SetValue(items.GetValue(lo + child - 1), lo + i - 1);
+ i = child;
+ }
+ keys.SetValue(d, lo + i - 1);
+ if(items != null)
+ items.SetValue(dt, lo + i - 1);
+ }
+
+ private void InsertionSort(int lo, int hi)
+ {
+ int i, j;
+ Object t, dt;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys.GetValue(i + 1);
+ dt = (items != null)? items.GetValue(i + 1) : null;
+
+ while (j >= lo && comparer.Compare(t, keys.GetValue(j)) < 0)
+ {
+ keys.SetValue(keys.GetValue(j), j + 1);
+ if(items != null)
+ items.SetValue(items.GetValue(j), j + 1);
+ j--;
+ }
+
+ keys.SetValue(t, j + 1);
+ if(items != null)
+ items.SetValue(dt, j + 1);
+ }
+ }
+ }
+
+ [Serializable] private sealed class SZArrayEnumerator : IEnumerator, ICloneable
+ {
+ private Array _array;
+ private int _index;
+ private int _endIndex; // cache array length, since it's a little slow.
+
+ internal SZArrayEnumerator(Array array) {
+ Contract.Assert(array.Rank == 1 && array.GetLowerBound(0) == 0, "SZArrayEnumerator only works on single dimension arrays w/ a lower bound of zero.");
+ _array = array;
+ _index = -1;
+ _endIndex = array.Length;
+ }
+
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ public bool MoveNext() {
+ if (_index < _endIndex) {
+ _index++;
+ return (_index < _endIndex);
+ }
+ return false;
+ }
+
+ public Object Current {
+ get {
+ if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return _array.GetValue(_index);
+ }
+ }
+
+ public void Reset() {
+ _index = -1;
+ }
+ }
+
+ [Serializable] private sealed class ArrayEnumerator : IEnumerator, ICloneable
+ {
+ private Array array;
+ private int index;
+ private int endIndex;
+ private int startIndex; // Save for Reset.
+ private int[] _indices; // The current position in a multidim array
+ private bool _complete;
+
+ internal ArrayEnumerator(Array array, int index, int count) {
+ this.array = array;
+ this.index = index - 1;
+ startIndex = index;
+ endIndex = index + count;
+ _indices = new int[array.Rank];
+ int checkForZero = 1; // Check for dimensions of size 0.
+ for(int i=0; i<array.Rank; i++) {
+ _indices[i] = array.GetLowerBound(i);
+ checkForZero *= array.GetLength(i);
+ }
+ // To make MoveNext simpler, decrement least significant index.
+ _indices[_indices.Length-1]--;
+ _complete = (checkForZero == 0);
+ }
+
+ private void IncArray() {
+ // This method advances us to the next valid array index,
+ // handling all the multiple dimension & bounds correctly.
+ // Think of it like an odometer in your car - we start with
+ // the last digit, increment it, and check for rollover. If
+ // it rolls over, we set all digits to the right and including
+ // the current to the appropriate lower bound. Do these overflow
+ // checks for each dimension, and if the most significant digit
+ // has rolled over it's upper bound, we're done.
+ //
+ int rank = array.Rank;
+ _indices[rank-1]++;
+ for(int dim=rank-1; dim>=0; dim--) {
+ if (_indices[dim] > array.GetUpperBound(dim)) {
+ if (dim==0) {
+ _complete = true;
+ break;
+ }
+ for(int j=dim; j<rank; j++)
+ _indices[j] = array.GetLowerBound(j);
+ _indices[dim-1]++;
+ }
+ }
+ }
+
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ public bool MoveNext() {
+ if (_complete) {
+ index = endIndex;
+ return false;
+ }
+ index++;
+ IncArray();
+ return !_complete;
+ }
+
+ public Object Current {
+ get {
+ if (index < startIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ if (_complete) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return array.GetValue(_indices);
+ }
+ }
+
+ public void Reset() {
+ index = startIndex - 1;
+ int checkForZero = 1;
+ for(int i=0; i<array.Rank; i++) {
+ _indices[i] = array.GetLowerBound(i);
+ checkForZero *= array.GetLength(i);
+ }
+ _complete = (checkForZero == 0);
+ // To make MoveNext simpler, decrement least significant index.
+ _indices[_indices.Length-1]--;
+ }
+ }
+
+
+ // if this is an array of value classes and that value class has a default constructor
+ // then this calls this default constructor on every element in the value class array.
+ // otherwise this is a no-op. Generally this method is called automatically by the compiler
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void Initialize();
+ }
+
+
+
+
+
+
+
+ //----------------------------------------------------------------------------------------
+ // ! READ THIS BEFORE YOU WORK ON THIS CLASS.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not SZArrayHelper objects. Rather, they are of type U[]
+ // where U[] is castable to T[]. No actual SZArrayHelper object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" "T[]".
+ //
+ // This class is needed to allow an SZ array of type T[] to expose IList<T>,
+ // IList<T.BaseType>, etc., etc. all the way up to IList<Object>. When the following call is
+ // made:
+ //
+ // ((IList<T>) (new U[n])).SomeIListMethod()
+ //
+ // the interface stub dispatcher treats this as a special case, loads up SZArrayHelper,
+ // finds the corresponding generic method (matched simply by method name), instantiates
+ // it for type <T> and executes it.
+ //
+ // The "T" will reflect the interface used to invoke the method. The actual runtime "this" will be
+ // array that is castable to "T[]" (i.e. for primitivs and valuetypes, it will be exactly
+ // "T[]" - for orefs, it may be a "U[]" where U derives from T.)
+ //----------------------------------------------------------------------------------------
+ sealed class SZArrayHelper {
+ // It is never legal to instantiate this class.
+ private SZArrayHelper() {
+ Contract.Assert(false, "Hey! How'd I get here?");
+ }
+
+ // -----------------------------------------------------------
+ // ------- Implement IEnumerable<T> interface methods --------
+ // -----------------------------------------------------------
+ [SecuritySafeCritical]
+ internal IEnumerator<T> GetEnumerator<T>() {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ int length = _this.Length;
+ return length == 0 ? SZGenericArrayEnumerator<T>.Empty : new SZGenericArrayEnumerator<T>(_this, length);
+ }
+
+ // -----------------------------------------------------------
+ // ------- Implement ICollection<T> interface methods --------
+ // -----------------------------------------------------------
+ [SecuritySafeCritical]
+ void CopyTo<T>(T[] array, int index) {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ Array.Copy(_this, 0, array, index, _this.Length);
+ }
+
+ [SecuritySafeCritical]
+ internal int get_Count<T>() {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ return _this.Length;
+ }
+
+ // -----------------------------------------------------------
+ // ---------- Implement IList<T> interface methods -----------
+ // -----------------------------------------------------------
+ [SecuritySafeCritical]
+ internal T get_Item<T>(int index) {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ if ((uint)index >= (uint)_this.Length) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ return _this[index];
+ }
+
+ [SecuritySafeCritical]
+ internal void set_Item<T>(int index, T value) {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ if ((uint)index >= (uint)_this.Length) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ _this[index] = value;
+ }
+
+ void Add<T>(T value) {
+ // Not meaningful for arrays.
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ [SecuritySafeCritical]
+ bool Contains<T>(T value) {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ return Array.IndexOf(_this, value) != -1;
+ }
+
+ bool get_IsReadOnly<T>() {
+ return true;
+ }
+
+ void Clear<T>() {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ [SecuritySafeCritical]
+ int IndexOf<T>(T value) {
+ //! Warning: "this" is an array, not an SZArrayHelper. See comments above
+ //! or you may introduce a security hole!
+ T[] _this = JitHelpers.UnsafeCast<T[]>(this);
+ return Array.IndexOf(_this, value);
+ }
+
+ void Insert<T>(int index, T value) {
+ // Not meaningful for arrays
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ bool Remove<T>(T value) {
+ // Not meaningful for arrays
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ return default(bool);
+ }
+
+ void RemoveAt<T>(int index) {
+ // Not meaningful for arrays
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_FixedSizeCollection);
+ }
+
+ // This is a normal generic Enumerator for SZ arrays. It doesn't have any of the "this" stuff
+ // that SZArrayHelper does.
+ //
+ [Serializable] private sealed class SZGenericArrayEnumerator<T> : IEnumerator<T> {
+ private T[] _array;
+ private int _index;
+ private int _endIndex; // cache array length, since it's a little slow.
+
+ // Passing -1 for endIndex so that MoveNext always returns false without mutating _index
+ internal static readonly SZGenericArrayEnumerator<T> Empty = new SZGenericArrayEnumerator<T>(null, -1);
+
+ internal SZGenericArrayEnumerator(T[] array, int endIndex) {
+ // We allow passing null array in case of empty enumerator.
+ Contract.Assert(array != null || endIndex == -1, "endIndex should be -1 in the case of a null array (for the empty enumerator).");
+ _array = array;
+ _index = -1;
+ _endIndex = endIndex;
+ }
+
+ public bool MoveNext() {
+ if (_index < _endIndex) {
+ _index++;
+ return (_index < _endIndex);
+ }
+ return false;
+ }
+
+ public T Current {
+ get {
+ if (_index < 0) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ if (_index >= _endIndex) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return _array[_index];
+ }
+ }
+
+ object IEnumerator.Current {
+ get {
+ return Current;
+ }
+ }
+
+ void IEnumerator.Reset() {
+ _index = -1;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+ }
+}
+
+// Useful in number of places that return an empty byte array to avoid unnecessary memory allocation.
+internal static class EmptyArray<T>
+{
+ public static readonly T[] Value = new T[0];
+}
diff --git a/src/mscorlib/src/System/ArraySegment.cs b/src/mscorlib/src/System/ArraySegment.cs
new file mode 100644
index 0000000000..bc39c2474f
--- /dev/null
+++ b/src/mscorlib/src/System/ArraySegment.cs
@@ -0,0 +1,342 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Convenient wrapper for an array, an offset, and
+** a count. Ideally used in streams & collections.
+** Net Classes will consume an array of these.
+**
+**
+===========================================================*/
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ // Note: users should make sure they copy the fields out of an ArraySegment onto their stack
+ // then validate that the fields describe valid bounds within the array. This must be done
+ // because assignments to value types are not atomic, and also because one thread reading
+ // three fields from an ArraySegment may not see the same ArraySegment from one call to another
+ // (ie, users could assign a new value to the old location).
+ [Serializable]
+ public struct ArraySegment<T> : IList<T>, IReadOnlyList<T>
+ {
+ private T[] _array;
+ private int _offset;
+ private int _count;
+
+ public ArraySegment(T[] array)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ Contract.EndContractBlock();
+
+ _array = array;
+ _offset = 0;
+ _count = array.Length;
+ }
+
+ public ArraySegment(T[] array, int offset, int count)
+ {
+ if (array == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ if (offset < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (count < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (array.Length - offset < count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ _array = array;
+ _offset = offset;
+ _count = count;
+ }
+
+ public T[] Array
+ {
+ get
+ {
+ Contract.Assert( (null == _array && 0 == _offset && 0 == _count)
+ || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
+ "ArraySegment is invalid");
+
+ return _array;
+ }
+ }
+
+ public int Offset
+ {
+ get
+ {
+ // Since copying value types is not atomic & callers cannot atomically
+ // read all three fields, we cannot guarantee that Offset is within
+ // the bounds of Array. That is our intent, but let's not specify
+ // it as a postcondition - force callers to re-verify this themselves
+ // after reading each field out of an ArraySegment into their stack.
+ Contract.Ensures(Contract.Result<int>() >= 0);
+
+ Contract.Assert( (null == _array && 0 == _offset && 0 == _count)
+ || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
+ "ArraySegment is invalid");
+
+ return _offset;
+ }
+ }
+
+ public int Count
+ {
+ get
+ {
+ // Since copying value types is not atomic & callers cannot atomically
+ // read all three fields, we cannot guarantee that Count is within
+ // the bounds of Array. That's our intent, but let's not specify
+ // it as a postcondition - force callers to re-verify this themselves
+ // after reading each field out of an ArraySegment into their stack.
+ Contract.Ensures(Contract.Result<int>() >= 0);
+
+ Contract.Assert( (null == _array && 0 == _offset && 0 == _count)
+ || (null != _array && _offset >= 0 && _count >= 0 && _offset + _count <= _array.Length),
+ "ArraySegment is invalid");
+
+ return _count;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ return null == _array
+ ? 0
+ : _array.GetHashCode() ^ _offset ^ _count;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is ArraySegment<T>)
+ return Equals((ArraySegment<T>)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(ArraySegment<T> obj)
+ {
+ return obj._array == _array && obj._offset == _offset && obj._count == _count;
+ }
+
+ public static bool operator ==(ArraySegment<T> a, ArraySegment<T> b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(ArraySegment<T> a, ArraySegment<T> b)
+ {
+ return !(a == b);
+ }
+
+ #region IList<T>
+ T IList<T>.this[int index]
+ {
+ get
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ if (index < 0 || index >= _count)
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ Contract.EndContractBlock();
+
+ return _array[_offset + index];
+ }
+
+ set
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ if (index < 0 || index >= _count)
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ Contract.EndContractBlock();
+
+ _array[_offset + index] = value;
+ }
+ }
+
+ int IList<T>.IndexOf(T item)
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ Contract.EndContractBlock();
+
+ int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
+
+ Contract.Assert(index == -1 ||
+ (index >= _offset && index < _offset + _count));
+
+ return index >= 0 ? index - _offset : -1;
+ }
+
+ void IList<T>.Insert(int index, T item)
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ }
+
+ void IList<T>.RemoveAt(int index)
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ }
+ #endregion
+
+ #region IReadOnlyList<T>
+ T IReadOnlyList<T>.this[int index]
+ {
+ get
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ if (index < 0 || index >= _count)
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ Contract.EndContractBlock();
+
+ return _array[_offset + index];
+ }
+ }
+ #endregion IReadOnlyList<T>
+
+ #region ICollection<T>
+ bool ICollection<T>.IsReadOnly
+ {
+ get
+ {
+ // the indexer setter does not throw an exception although IsReadOnly is true.
+ // This is to match the behavior of arrays.
+ return true;
+ }
+ }
+
+ void ICollection<T>.Add(T item)
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ }
+
+ void ICollection<T>.Clear()
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ }
+
+ bool ICollection<T>.Contains(T item)
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ Contract.EndContractBlock();
+
+ int index = System.Array.IndexOf<T>(_array, item, _offset, _count);
+
+ Contract.Assert(index == -1 ||
+ (index >= _offset && index < _offset + _count));
+
+ return index >= 0;
+ }
+
+ void ICollection<T>.CopyTo(T[] array, int arrayIndex)
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ Contract.EndContractBlock();
+
+ System.Array.Copy(_array, _offset, array, arrayIndex, _count);
+ }
+
+ bool ICollection<T>.Remove(T item)
+ {
+ ThrowHelper.ThrowNotSupportedException();
+ return default(bool);
+ }
+ #endregion
+
+ #region IEnumerable<T>
+ IEnumerator<T> IEnumerable<T>.GetEnumerator()
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ Contract.EndContractBlock();
+
+ return new ArraySegmentEnumerator(this);
+ }
+ #endregion
+
+ #region IEnumerable
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ if (_array == null)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NullArray);
+ Contract.EndContractBlock();
+
+ return new ArraySegmentEnumerator(this);
+ }
+ #endregion
+
+ [Serializable]
+ private sealed class ArraySegmentEnumerator : IEnumerator<T>
+ {
+ private T[] _array;
+ private int _start;
+ private int _end;
+ private int _current;
+
+ internal ArraySegmentEnumerator(ArraySegment<T> arraySegment)
+ {
+ Contract.Requires(arraySegment.Array != null);
+ Contract.Requires(arraySegment.Offset >= 0);
+ Contract.Requires(arraySegment.Count >= 0);
+ Contract.Requires(arraySegment.Offset + arraySegment.Count <= arraySegment.Array.Length);
+
+ _array = arraySegment._array;
+ _start = arraySegment._offset;
+ _end = _start + arraySegment._count;
+ _current = _start - 1;
+ }
+
+ public bool MoveNext()
+ {
+ if (_current < _end)
+ {
+ _current++;
+ return (_current < _end);
+ }
+ return false;
+ }
+
+ public T Current
+ {
+ get
+ {
+ if (_current < _start) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ if (_current >= _end) ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return _array[_current];
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ return Current;
+ }
+ }
+
+ void IEnumerator.Reset()
+ {
+ _current = _start - 1;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ArrayTypeMismatchException.cs b/src/mscorlib/src/System/ArrayTypeMismatchException.cs
new file mode 100644
index 0000000000..4f24b9d3c7
--- /dev/null
+++ b/src/mscorlib/src/System/ArrayTypeMismatchException.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The arrays are of different primitive types.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ // The ArrayMismatchException is thrown when an attempt to store
+ // an object of the wrong type within an array occurs.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ArrayTypeMismatchException : SystemException {
+
+ // Creates a new ArrayMismatchException with its message string set to
+ // the empty string, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
+ // and its ExceptionInfo reference set to null.
+ public ArrayTypeMismatchException()
+ : base(Environment.GetResourceString("Arg_ArrayTypeMismatchException")) {
+ SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH);
+ }
+
+ // Creates a new ArrayMismatchException with its message string set to
+ // message, its HRESULT set to COR_E_ARRAYTYPEMISMATCH,
+ // and its ExceptionInfo reference set to null.
+ //
+ public ArrayTypeMismatchException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH);
+ }
+
+ public ArrayTypeMismatchException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_ARRAYTYPEMISMATCH);
+ }
+
+ protected ArrayTypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/AsyncCallback.cs b/src/mscorlib/src/System/AsyncCallback.cs
new file mode 100644
index 0000000000..69a03812e1
--- /dev/null
+++ b/src/mscorlib/src/System/AsyncCallback.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: AsyncCallbackDelegate
+**
+** Purpose: Type of callback for async operations
+**
+===========================================================*/
+namespace System {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void AsyncCallback(IAsyncResult ar);
+
+}
diff --git a/src/mscorlib/src/System/Attribute.cs b/src/mscorlib/src/System/Attribute.cs
new file mode 100644
index 0000000000..6475d8d7e7
--- /dev/null
+++ b/src/mscorlib/src/System/Attribute.cs
@@ -0,0 +1,975 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Collections.Generic;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [AttributeUsageAttribute(AttributeTargets.All, Inherited = true, AllowMultiple=false)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Attribute))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Attribute : _Attribute
+ {
+ #region Private Statics
+
+ #region PropertyInfo
+ private static Attribute[] InternalGetCustomAttributes(PropertyInfo element, Type type, bool inherit)
+ {
+ Contract.Requires(element != null);
+ Contract.Requires(type != null);
+ Contract.Requires(type.IsSubclassOf(typeof(Attribute)) || type == typeof(Attribute));
+
+ // walk up the hierarchy chain
+ Attribute[] attributes = (Attribute[])element.GetCustomAttributes(type, inherit);
+
+ if (!inherit)
+ return attributes;
+
+ // create the hashtable that keeps track of inherited types
+ Dictionary<Type, AttributeUsageAttribute> types = new Dictionary<Type, AttributeUsageAttribute>(11);
+
+ // create an array list to collect all the requested attibutes
+ List<Attribute> attributeList = new List<Attribute>();
+ CopyToArrayList(attributeList, attributes, types);
+
+ //if this is an index we need to get the parameter types to help disambiguate
+ Type[] indexParamTypes = GetIndexParameterTypes(element);
+
+
+ PropertyInfo baseProp = GetParentDefinition(element, indexParamTypes);
+ while (baseProp != null)
+ {
+ attributes = GetCustomAttributes(baseProp, type, false);
+ AddAttributesToList(attributeList, attributes, types);
+ baseProp = GetParentDefinition(baseProp, indexParamTypes);
+ }
+ Array array = CreateAttributeArrayHelper(type, attributeList.Count);
+ Array.Copy(attributeList.ToArray(), 0, array, 0, attributeList.Count);
+ return (Attribute[])array;
+ }
+
+ private static bool InternalIsDefined(PropertyInfo element, Type attributeType, bool inherit)
+ {
+ // walk up the hierarchy chain
+ if (element.IsDefined(attributeType, inherit))
+ return true;
+
+ if (inherit)
+ {
+ AttributeUsageAttribute usage = InternalGetAttributeUsage(attributeType);
+
+ if (!usage.Inherited)
+ return false;
+
+ //if this is an index we need to get the parameter types to help disambiguate
+ Type[] indexParamTypes = GetIndexParameterTypes(element);
+
+ PropertyInfo baseProp = GetParentDefinition(element, indexParamTypes);
+
+ while (baseProp != null)
+ {
+ if (baseProp.IsDefined(attributeType, false))
+ return true;
+
+ baseProp = GetParentDefinition(baseProp, indexParamTypes);
+ }
+ }
+
+ return false;
+ }
+
+ private static PropertyInfo GetParentDefinition(PropertyInfo property, Type[] propertyParameters)
+ {
+ Contract.Requires(property != null);
+
+ // for the current property get the base class of the getter and the setter, they might be different
+ // note that this only works for RuntimeMethodInfo
+ MethodInfo propAccessor = property.GetGetMethod(true);
+
+ if (propAccessor == null)
+ propAccessor = property.GetSetMethod(true);
+
+ RuntimeMethodInfo rtPropAccessor = propAccessor as RuntimeMethodInfo;
+
+ if (rtPropAccessor != null)
+ {
+ rtPropAccessor = rtPropAccessor.GetParentDefinition();
+
+ if (rtPropAccessor != null)
+ {
+ // There is a public overload of Type.GetProperty that takes both a BingingFlags enum and a return type.
+ // However, we cannot use that because it doesn't accept null for "types".
+ return rtPropAccessor.DeclaringType.GetProperty(
+ property.Name,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
+ null, //will use default binder
+ property.PropertyType,
+ propertyParameters, //used for index properties
+ null);
+ }
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ #region EventInfo
+ private static Attribute[] InternalGetCustomAttributes(EventInfo element, Type type, bool inherit)
+ {
+ Contract.Requires(element != null);
+ Contract.Requires(type != null);
+ Contract.Requires(type.IsSubclassOf(typeof(Attribute)) || type == typeof(Attribute));
+
+ // walk up the hierarchy chain
+ Attribute[] attributes = (Attribute[])element.GetCustomAttributes(type, inherit);
+ if (inherit)
+ {
+ // create the hashtable that keeps track of inherited types
+ Dictionary<Type, AttributeUsageAttribute> types = new Dictionary<Type, AttributeUsageAttribute>(11);
+ // create an array list to collect all the requested attibutes
+ List<Attribute> attributeList = new List<Attribute>();
+ CopyToArrayList(attributeList, attributes, types);
+
+ EventInfo baseEvent = GetParentDefinition(element);
+ while (baseEvent != null)
+ {
+ attributes = GetCustomAttributes(baseEvent, type, false);
+ AddAttributesToList(attributeList, attributes, types);
+ baseEvent = GetParentDefinition(baseEvent);
+ }
+ Array array = CreateAttributeArrayHelper(type, attributeList.Count);
+ Array.Copy(attributeList.ToArray(), 0, array, 0, attributeList.Count);
+ return (Attribute[])array;
+ }
+ else
+ return attributes;
+ }
+
+ private static EventInfo GetParentDefinition(EventInfo ev)
+ {
+ Contract.Requires(ev != null);
+
+ // note that this only works for RuntimeMethodInfo
+ MethodInfo add = ev.GetAddMethod(true);
+
+ RuntimeMethodInfo rtAdd = add as RuntimeMethodInfo;
+
+ if (rtAdd != null)
+ {
+ rtAdd = rtAdd.GetParentDefinition();
+ if (rtAdd != null)
+ return rtAdd.DeclaringType.GetEvent(ev.Name);
+ }
+ return null;
+ }
+
+ private static bool InternalIsDefined (EventInfo element, Type attributeType, bool inherit)
+ {
+ Contract.Requires(element != null);
+
+ // walk up the hierarchy chain
+ if (element.IsDefined(attributeType, inherit))
+ return true;
+
+ if (inherit)
+ {
+ AttributeUsageAttribute usage = InternalGetAttributeUsage(attributeType);
+
+ if (!usage.Inherited)
+ return false;
+
+ EventInfo baseEvent = GetParentDefinition(element);
+
+ while (baseEvent != null)
+ {
+ if (baseEvent.IsDefined(attributeType, false))
+ return true;
+ baseEvent = GetParentDefinition(baseEvent);
+ }
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ #region ParameterInfo
+ private static ParameterInfo GetParentDefinition(ParameterInfo param)
+ {
+ Contract.Requires(param != null);
+
+ // note that this only works for RuntimeMethodInfo
+ RuntimeMethodInfo rtMethod = param.Member as RuntimeMethodInfo;
+
+ if (rtMethod != null)
+ {
+ rtMethod = rtMethod.GetParentDefinition();
+
+ if (rtMethod != null)
+ {
+ // Find the ParameterInfo on this method
+ int position = param.Position;
+ if (position == -1)
+ {
+ return rtMethod.ReturnParameter;
+ }
+ else
+ {
+ ParameterInfo[] parameters = rtMethod.GetParameters();
+ return parameters[position]; // Point to the correct ParameterInfo of the method
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Attribute[] InternalParamGetCustomAttributes(ParameterInfo param, Type type, bool inherit)
+ {
+ Contract.Requires(param != null);
+
+ // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain that
+ // have this ParameterInfo defined. .We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
+ // that are marked inherited from the remainder of the MethodInfo's in the inheritance chain.
+ // For MethodInfo's on an interface we do not do an inheritance walk so the default ParameterInfo attributes are returned.
+ // For MethodInfo's on a class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the
+ // class inherits from and return the respective ParameterInfo attributes
+
+ List<Type> disAllowMultiple = new List<Type>();
+ Object [] objAttr;
+
+ if (type == null)
+ type = typeof(Attribute);
+
+ objAttr = param.GetCustomAttributes(type, false);
+
+ for (int i =0;i < objAttr.Length;i++)
+ {
+ Type objType = objAttr[i].GetType();
+ AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
+ if (attribUsage.AllowMultiple == false)
+ disAllowMultiple.Add(objType);
+ }
+
+ // Get all the attributes that have Attribute as the base class
+ Attribute [] ret = null;
+ if (objAttr.Length == 0)
+ ret = CreateAttributeArrayHelper(type,0);
+ else
+ ret = (Attribute[])objAttr;
+
+ if (param.Member.DeclaringType == null) // This is an interface so we are done.
+ return ret;
+
+ if (!inherit)
+ return ret;
+
+ ParameterInfo baseParam = GetParentDefinition(param);
+
+ while (baseParam != null)
+ {
+ objAttr = baseParam.GetCustomAttributes(type, false);
+
+ int count = 0;
+ for (int i =0;i < objAttr.Length;i++)
+ {
+ Type objType = objAttr[i].GetType();
+ AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
+
+ if ((attribUsage.Inherited) && (disAllowMultiple.Contains(objType) == false))
+ {
+ if (attribUsage.AllowMultiple == false)
+ disAllowMultiple.Add(objType);
+ count++;
+ }
+ else
+ objAttr[i] = null;
+ }
+
+ // Get all the attributes that have Attribute as the base class
+ Attribute [] attributes = CreateAttributeArrayHelper(type,count);
+
+ count = 0;
+ for (int i =0;i < objAttr.Length;i++)
+ {
+ if (objAttr[i] != null)
+ {
+ attributes[count] = (Attribute)objAttr[i];
+ count++;
+ }
+ }
+
+ Attribute [] temp = ret;
+ ret = CreateAttributeArrayHelper(type,temp.Length + count);
+ Array.Copy(temp,ret,temp.Length);
+
+ int offset = temp.Length;
+
+ for (int i =0;i < attributes.Length;i++)
+ ret[offset + i] = attributes[i];
+
+ baseParam = GetParentDefinition(baseParam);
+ }
+
+ return ret;
+ }
+
+ private static bool InternalParamIsDefined(ParameterInfo param, Type type, bool inherit)
+ {
+ Contract.Requires(param != null);
+ Contract.Requires(type != null);
+
+ // For ParameterInfo's we need to make sure that we chain through all the MethodInfo's in the inheritance chain.
+ // We pick up all the CustomAttributes for the starting ParameterInfo. We need to pick up only attributes
+ // that are marked inherited from the remainder of the ParameterInfo's in the inheritance chain.
+ // For MethodInfo's on an interface we do not do an inheritance walk. For ParameterInfo's on a
+ // Class we walk up the inheritance chain but do not look at the MethodInfo's on the interfaces that the class inherits from.
+
+ if (param.IsDefined(type, false))
+ return true;
+
+ if (param.Member.DeclaringType == null || !inherit) // This is an interface so we are done.
+ return false;
+
+ ParameterInfo baseParam = GetParentDefinition(param);
+
+ while (baseParam != null)
+ {
+ Object[] objAttr = baseParam.GetCustomAttributes(type, false);
+
+ for (int i =0; i < objAttr.Length; i++)
+ {
+ Type objType = objAttr[i].GetType();
+ AttributeUsageAttribute attribUsage = InternalGetAttributeUsage(objType);
+
+ if ((objAttr[i] is Attribute) && (attribUsage.Inherited))
+ return true;
+ }
+
+ baseParam = GetParentDefinition(baseParam);
+ }
+
+ return false;
+ }
+
+ #endregion
+
+ #region Utility
+ private static void CopyToArrayList(List<Attribute> attributeList,Attribute[] attributes,Dictionary<Type, AttributeUsageAttribute> types)
+ {
+ for (int i = 0; i < attributes.Length; i++)
+ {
+ attributeList.Add(attributes[i]);
+
+ Type attrType = attributes[i].GetType();
+
+ if (!types.ContainsKey(attrType))
+ types[attrType] = InternalGetAttributeUsage(attrType);
+ }
+ }
+
+ private static Type[] GetIndexParameterTypes(PropertyInfo element)
+ {
+ ParameterInfo[] indexParams = element.GetIndexParameters();
+
+ if (indexParams.Length > 0)
+ {
+ Type[] indexParamTypes = new Type[indexParams.Length];
+ for (int i = 0; i < indexParams.Length; i++)
+ {
+ indexParamTypes[i] = indexParams[i].ParameterType;
+ }
+ return indexParamTypes;
+ }
+
+ return Array.Empty<Type>();
+ }
+
+ private static void AddAttributesToList(List<Attribute> attributeList, Attribute[] attributes, Dictionary<Type, AttributeUsageAttribute> types)
+ {
+ for (int i = 0; i < attributes.Length; i++)
+ {
+ Type attrType = attributes[i].GetType();
+ AttributeUsageAttribute usage = null;
+ types.TryGetValue(attrType, out usage);
+
+ if (usage == null)
+ {
+ // the type has never been seen before if it's inheritable add it to the list
+ usage = InternalGetAttributeUsage(attrType);
+ types[attrType] = usage;
+
+ if (usage.Inherited)
+ attributeList.Add(attributes[i]);
+ }
+ else if (usage.Inherited && usage.AllowMultiple)
+ {
+ // we saw this type already add it only if it is inheritable and it does allow multiple
+ attributeList.Add(attributes[i]);
+ }
+ }
+ }
+
+ private static AttributeUsageAttribute InternalGetAttributeUsage(Type type)
+ {
+ // Check if the custom attributes is Inheritable
+ Object [] obj = type.GetCustomAttributes(typeof(AttributeUsageAttribute), false);
+
+ if (obj.Length == 1)
+ return (AttributeUsageAttribute)obj[0];
+
+ if (obj.Length == 0)
+ return AttributeUsageAttribute.Default;
+
+ throw new FormatException(
+ Environment.GetResourceString("Format_AttributeUsage", type));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static Attribute[] CreateAttributeArrayHelper(Type elementType, int elementCount)
+ {
+ return (Attribute[])Array.UnsafeCreateInstance(elementType, elementCount);
+ }
+ #endregion
+
+ #endregion
+
+ #region Public Statics
+
+ #region MemberInfo
+ public static Attribute[] GetCustomAttributes(MemberInfo element, Type type)
+ {
+ return GetCustomAttributes(element, type, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(MemberInfo element, Type type, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ if (!type.IsSubclassOf(typeof(Attribute)) && type != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ switch (element.MemberType)
+ {
+ case MemberTypes.Property:
+ return InternalGetCustomAttributes((PropertyInfo)element, type, inherit);
+
+ case MemberTypes.Event:
+ return InternalGetCustomAttributes((EventInfo)element, type, inherit);
+
+ default:
+ return element.GetCustomAttributes(type, inherit) as Attribute[];
+ }
+ }
+
+ public static Attribute[] GetCustomAttributes(MemberInfo element)
+ {
+ return GetCustomAttributes(element, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(MemberInfo element, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+ Contract.EndContractBlock();
+
+ switch (element.MemberType)
+ {
+ case MemberTypes.Property:
+ return InternalGetCustomAttributes((PropertyInfo)element, typeof(Attribute), inherit);
+
+ case MemberTypes.Event:
+ return InternalGetCustomAttributes((EventInfo)element, typeof(Attribute), inherit);
+
+ default:
+ return element.GetCustomAttributes(typeof(Attribute), inherit) as Attribute[];
+ }
+ }
+
+ public static bool IsDefined(MemberInfo element, Type attributeType)
+ {
+ return IsDefined(element, attributeType, true);
+ }
+
+ public static bool IsDefined(MemberInfo element, Type attributeType, bool inherit)
+ {
+ // Returns true if a custom attribute subclass of attributeType class/interface with inheritance walk
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ switch(element.MemberType)
+ {
+ case MemberTypes.Property:
+ return InternalIsDefined((PropertyInfo)element, attributeType, inherit);
+
+ case MemberTypes.Event:
+ return InternalIsDefined((EventInfo)element, attributeType, inherit);
+
+ default:
+ return element.IsDefined(attributeType, inherit);
+ }
+
+ }
+
+ public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType)
+ {
+ return GetCustomAttribute(element, attributeType, true);
+ }
+
+ public static Attribute GetCustomAttribute(MemberInfo element, Type attributeType, bool inherit)
+ {
+ Attribute[] attrib = GetCustomAttributes(element, attributeType, inherit);
+
+ if (attrib == null || attrib.Length == 0)
+ return null;
+
+ if (attrib.Length == 1)
+ return attrib[0];
+
+ throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
+ }
+
+ #endregion
+
+ #region ParameterInfo
+ public static Attribute[] GetCustomAttributes(ParameterInfo element)
+ {
+ return GetCustomAttributes(element, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType)
+ {
+ return (Attribute[])GetCustomAttributes(element, attributeType, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(ParameterInfo element, Type attributeType, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+
+ if (element.Member == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element");
+
+ Contract.EndContractBlock();
+
+ MemberInfo member = element.Member;
+ if (member.MemberType == MemberTypes.Method && inherit)
+ return InternalParamGetCustomAttributes(element, attributeType, inherit) as Attribute[];
+
+ return element.GetCustomAttributes(attributeType, inherit) as Attribute[];
+ }
+
+ public static Attribute[] GetCustomAttributes(ParameterInfo element, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (element.Member == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParameterInfo"), "element");
+
+ Contract.EndContractBlock();
+
+ MemberInfo member = element.Member;
+ if (member.MemberType == MemberTypes.Method && inherit)
+ return InternalParamGetCustomAttributes(element, null, inherit) as Attribute[];
+
+ return element.GetCustomAttributes(typeof(Attribute), inherit) as Attribute[];
+ }
+
+ public static bool IsDefined(ParameterInfo element, Type attributeType)
+ {
+ return IsDefined(element, attributeType, true);
+ }
+
+ public static bool IsDefined(ParameterInfo element, Type attributeType, bool inherit)
+ {
+ // Returns true is a custom attribute subclass of attributeType class/interface with inheritance walk
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ MemberInfo member = element.Member;
+
+ switch(member.MemberType)
+ {
+ case MemberTypes.Method: // We need to climb up the member hierarchy
+ return InternalParamIsDefined(element, attributeType, inherit);
+
+ case MemberTypes.Constructor:
+ return element.IsDefined(attributeType, false);
+
+ case MemberTypes.Property:
+ return element.IsDefined(attributeType, false);
+
+ default:
+ Contract.Assert(false, "Invalid type for ParameterInfo member in Attribute class");
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidParamInfo"));
+ }
+ }
+
+ public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType)
+ {
+ return GetCustomAttribute(element, attributeType, true);
+ }
+
+ public static Attribute GetCustomAttribute(ParameterInfo element, Type attributeType, bool inherit)
+ {
+ // Returns an Attribute of base class/inteface attributeType on the ParameterInfo or null if none exists.
+ // throws an AmbiguousMatchException if there are more than one defined.
+ Attribute[] attrib = GetCustomAttributes(element, attributeType, inherit);
+
+ if (attrib == null || attrib.Length == 0)
+ return null;
+
+ if (attrib.Length == 0)
+ return null;
+
+ if (attrib.Length == 1)
+ return attrib[0];
+
+ throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
+ }
+
+ #endregion
+
+ #region Module
+ public static Attribute[] GetCustomAttributes(Module element, Type attributeType)
+ {
+ return GetCustomAttributes (element, attributeType, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(Module element)
+ {
+ return GetCustomAttributes(element, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(Module element, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+ Contract.EndContractBlock();
+
+ return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit);
+ }
+
+ public static Attribute[] GetCustomAttributes(Module element, Type attributeType, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ return (Attribute[])element.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public static bool IsDefined(Module element, Type attributeType)
+ {
+ return IsDefined(element, attributeType, false);
+ }
+
+ public static bool IsDefined(Module element, Type attributeType, bool inherit)
+ {
+ // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ return element.IsDefined(attributeType,false);
+ }
+
+ public static Attribute GetCustomAttribute(Module element, Type attributeType)
+ {
+ return GetCustomAttribute(element, attributeType, true);
+ }
+
+ public static Attribute GetCustomAttribute(Module element, Type attributeType, bool inherit)
+ {
+ // Returns an Attribute of base class/inteface attributeType on the Module or null if none exists.
+ // throws an AmbiguousMatchException if there are more than one defined.
+ Attribute[] attrib = GetCustomAttributes(element,attributeType,inherit);
+
+ if (attrib == null || attrib.Length == 0)
+ return null;
+
+ if (attrib.Length == 1)
+ return attrib[0];
+
+ throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
+ }
+
+ #endregion
+
+ #region Assembly
+ public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType)
+ {
+ return GetCustomAttributes(element, attributeType, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(Assembly element, Type attributeType, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ return (Attribute[])element.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public static Attribute[] GetCustomAttributes(Assembly element)
+ {
+ return GetCustomAttributes(element, true);
+ }
+
+ public static Attribute[] GetCustomAttributes(Assembly element, bool inherit)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+ Contract.EndContractBlock();
+
+ return (Attribute[])element.GetCustomAttributes(typeof(Attribute), inherit);
+ }
+
+ public static bool IsDefined (Assembly element, Type attributeType)
+ {
+ return IsDefined (element, attributeType, true);
+ }
+
+ public static bool IsDefined (Assembly element, Type attributeType, bool inherit)
+ {
+ // Returns true is a custom attribute subclass of attributeType class/interface with no inheritance walk
+ if (element == null)
+ throw new ArgumentNullException("element");
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+
+ if (!attributeType.IsSubclassOf(typeof(Attribute)) && attributeType != typeof(Attribute))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustHaveAttributeBaseClass"));
+ Contract.EndContractBlock();
+
+ return element.IsDefined(attributeType, false);
+ }
+
+ public static Attribute GetCustomAttribute(Assembly element, Type attributeType)
+ {
+ return GetCustomAttribute (element, attributeType, true);
+ }
+
+ public static Attribute GetCustomAttribute(Assembly element, Type attributeType, bool inherit)
+ {
+ // Returns an Attribute of base class/inteface attributeType on the Assembly or null if none exists.
+ // throws an AmbiguousMatchException if there are more than one defined.
+ Attribute[] attrib = GetCustomAttributes(element,attributeType,inherit);
+
+ if (attrib == null || attrib.Length == 0)
+ return null;
+
+ if (attrib.Length == 1)
+ return attrib[0];
+
+ throw new AmbiguousMatchException(Environment.GetResourceString("RFLCT.AmbigCust"));
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Constructor
+ protected Attribute() { }
+ #endregion
+
+ #region Object Overrides
+ [SecuritySafeCritical]
+ public override bool Equals(Object obj)
+ {
+ if (obj == null)
+ return false;
+
+ RuntimeType thisType = (RuntimeType)this.GetType();
+ RuntimeType thatType = (RuntimeType)obj.GetType();
+
+ if (thatType != thisType)
+ return false;
+
+ Object thisObj = this;
+ Object thisResult, thatResult;
+
+ FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+
+ for (int i = 0; i < thisFields.Length; i++)
+ {
+ // Visibility check and consistency check are not necessary.
+ thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
+ thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);
+
+ if (!AreFieldValuesEqual(thisResult, thatResult))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ // Compares values of custom-attribute fields.
+ private static bool AreFieldValuesEqual(Object thisValue, Object thatValue)
+ {
+ if (thisValue == null && thatValue == null)
+ return true;
+ if (thisValue == null || thatValue == null)
+ return false;
+
+ if (thisValue.GetType().IsArray)
+ {
+ // Ensure both are arrays of the same type.
+ if (!thisValue.GetType().Equals(thatValue.GetType()))
+ {
+ return false;
+ }
+
+ Array thisValueArray = thisValue as Array;
+ Array thatValueArray = thatValue as Array;
+ if (thisValueArray.Length != thatValueArray.Length)
+ {
+ return false;
+ }
+
+ // Attributes can only contain single-dimension arrays, so we don't need to worry about
+ // multidimensional arrays.
+ Contract.Assert(thisValueArray.Rank == 1 && thatValueArray.Rank == 1);
+ for (int j = 0; j < thisValueArray.Length; j++)
+ {
+ if (!AreFieldValuesEqual(thisValueArray.GetValue(j), thatValueArray.GetValue(j)))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ // An object of type Attribute will cause a stack overflow.
+ // However, this should never happen because custom attributes cannot contain values other than
+ // constants, single-dimensional arrays and typeof expressions.
+ Contract.Assert(!(thisValue is Attribute));
+ if (!thisValue.Equals(thatValue))
+ return false;
+ }
+
+ return true;
+ }
+
+ [SecuritySafeCritical]
+ public override int GetHashCode()
+ {
+ Type type = GetType();
+
+ FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ Object vThis = null;
+
+ for (int i = 0; i < fields.Length; i++)
+ {
+ // Visibility check and consistency check are not necessary.
+ Object fieldValue = ((RtFieldInfo)fields[i]).UnsafeGetValue(this);
+
+ // The hashcode of an array ignores the contents of the array, so it can produce
+ // different hashcodes for arrays with the same contents.
+ // Since we do deep comparisons of arrays in Equals(), this means Equals and GetHashCode will
+ // be inconsistent for arrays. Therefore, we ignore hashes of arrays.
+ if (fieldValue != null && !fieldValue.GetType().IsArray)
+ vThis = fieldValue;
+
+ if (vThis != null)
+ break;
+ }
+
+ if (vThis != null)
+ return vThis.GetHashCode();
+
+ return type.GetHashCode();
+ }
+ #endregion
+
+ #region Public Virtual Members
+ public virtual Object TypeId { get { return GetType(); } }
+
+ public virtual bool Match(Object obj) { return Equals(obj); }
+ #endregion
+
+ #region Public Members
+ public virtual bool IsDefaultAttribute() { return false; }
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _Attribute.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Attribute.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Attribute.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Attribute.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/AttributeTargets.cs b/src/mscorlib/src/System/AttributeTargets.cs
new file mode 100644
index 0000000000..33617e9623
--- /dev/null
+++ b/src/mscorlib/src/System/AttributeTargets.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System {
+
+ using System;
+
+ // Enum used to indicate all the elements of the
+ // VOS it is valid to attach this element to.
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum AttributeTargets
+ {
+ Assembly = 0x0001,
+ Module = 0x0002,
+ Class = 0x0004,
+ Struct = 0x0008,
+ Enum = 0x0010,
+ Constructor = 0x0020,
+ Method = 0x0040,
+ Property = 0x0080,
+ Field = 0x0100,
+ Event = 0x0200,
+ Interface = 0x0400,
+ Parameter = 0x0800,
+ Delegate = 0x1000,
+ ReturnValue = 0x2000,
+ //@todo GENERICS: document GenericParameter
+ GenericParameter = 0x4000,
+
+
+ All = Assembly | Module | Class | Struct | Enum | Constructor |
+ Method | Property | Field | Event | Interface | Parameter |
+ Delegate | ReturnValue | GenericParameter,
+ }
+}
diff --git a/src/mscorlib/src/System/AttributeUsageAttribute.cs b/src/mscorlib/src/System/AttributeUsageAttribute.cs
new file mode 100644
index 0000000000..0c2e11caff
--- /dev/null
+++ b/src/mscorlib/src/System/AttributeUsageAttribute.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The class denotes how to specify the usage of an attribute
+**
+**
+===========================================================*/
+namespace System {
+
+ using System.Reflection;
+ /* By default, attributes are inherited and multiple attributes are not allowed */
+[Serializable]
+ [AttributeUsage(AttributeTargets.Class, Inherited = true)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AttributeUsageAttribute : Attribute
+ {
+ internal AttributeTargets m_attributeTarget = AttributeTargets.All; // Defaults to all
+ internal bool m_allowMultiple = false; // Defaults to false
+ internal bool m_inherited = true; // Defaults to true
+
+ internal static AttributeUsageAttribute Default = new AttributeUsageAttribute(AttributeTargets.All);
+
+ //Constructors
+ public AttributeUsageAttribute(AttributeTargets validOn) {
+ m_attributeTarget = validOn;
+ }
+ internal AttributeUsageAttribute(AttributeTargets validOn, bool allowMultiple, bool inherited) {
+ m_attributeTarget = validOn;
+ m_allowMultiple = allowMultiple;
+ m_inherited = inherited;
+ }
+
+
+ //Properties
+ public AttributeTargets ValidOn
+ {
+ get{ return m_attributeTarget; }
+ }
+
+ public bool AllowMultiple
+ {
+ get { return m_allowMultiple; }
+ set { m_allowMultiple = value; }
+ }
+
+ public bool Inherited
+ {
+ get { return m_inherited; }
+ set { m_inherited = value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/BCLDebug.cs b/src/mscorlib/src/System/BCLDebug.cs
new file mode 100644
index 0000000000..9b2ade26fa
--- /dev/null
+++ b/src/mscorlib/src/System/BCLDebug.cs
@@ -0,0 +1,442 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Debugging Macros for use in the Base Class Libraries
+**
+**
+============================================================*/
+
+namespace System {
+
+ using System.IO;
+ using System.Text;
+ using System.Runtime.Remoting;
+ using System.Diagnostics;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal enum LogLevel {
+ Trace = 0,
+ Status = 20,
+ Warning= 40,
+ Error = 50,
+ Panic = 100,
+ }
+
+ internal struct SwitchStructure {
+ internal String name;
+ internal int value;
+
+ internal SwitchStructure (String n, int v) {
+ name = n;
+ value = v;
+ }
+ }
+
+
+ // Only statics, does not need to be marked with the serializable attribute
+ internal static class BCLDebug {
+ internal static volatile bool m_registryChecked=false;
+ internal static volatile bool m_loggingNotEnabled = false;
+ internal static bool m_perfWarnings;
+ internal static bool m_correctnessWarnings;
+ internal static bool m_safeHandleStackTraces;
+#if _DEBUG
+ internal static volatile bool m_domainUnloadAdded;
+#endif
+ internal static volatile PermissionSet m_MakeConsoleErrorLoggingWork;
+
+ static readonly SwitchStructure[] switches = {
+ new SwitchStructure("NLS", 0x00000001),
+ new SwitchStructure("SER", 0x00000002),
+ new SwitchStructure("DYNIL",0x00000004),
+ new SwitchStructure("REMOTE",0x00000008),
+ new SwitchStructure("BINARY",0x00000010), //Binary Formatter
+ new SwitchStructure("SOAP",0x00000020), // Soap Formatter
+ new SwitchStructure("REMOTINGCHANNELS",0x00000040),
+ new SwitchStructure("CACHE",0x00000080),
+ new SwitchStructure("RESMGRFILEFORMAT", 0x00000100), // .resources files
+ new SwitchStructure("PERF", 0x00000200),
+ new SwitchStructure("CORRECTNESS", 0x00000400),
+ new SwitchStructure("MEMORYFAILPOINT", 0x00000800),
+ new SwitchStructure("DATETIME", 0x00001000), // System.DateTime managed tracing
+ new SwitchStructure("INTEROP", 0x00002000), // Interop tracing
+ };
+
+ static readonly LogLevel[] levelConversions = {
+ LogLevel.Panic,
+ LogLevel.Error,
+ LogLevel.Error,
+ LogLevel.Warning,
+ LogLevel.Warning,
+ LogLevel.Status,
+ LogLevel.Status,
+ LogLevel.Trace,
+ LogLevel.Trace,
+ LogLevel.Trace,
+ LogLevel.Trace
+ };
+
+
+#if _DEBUG
+ internal static void WaitForFinalizers(Object sender, EventArgs e)
+ {
+ if (!m_registryChecked) {
+ CheckRegistry();
+ }
+ if (m_correctnessWarnings) {
+ GC.GetTotalMemory(true);
+ GC.WaitForPendingFinalizers();
+ }
+ }
+#endif
+ [Conditional("_DEBUG")]
+ static public void Assert(bool condition) {
+#if _DEBUG
+ Assert(condition, "Assert failed.");
+#endif
+ }
+
+ [Conditional("_DEBUG")]
+ static public void Assert(bool condition, String message) {
+#if _DEBUG
+ // Speed up debug builds marginally by avoiding the garbage from
+ // concatinating "BCL Assert: " and the message.
+ if (!condition)
+ System.Diagnostics.Assert.Check(condition, "BCL Assert", message);
+#endif
+ }
+
+ [Pure]
+ [Conditional("_LOGGING")]
+ [SecuritySafeCritical]
+ static public void Log(String message) {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ if (!m_registryChecked) {
+ CheckRegistry();
+ }
+ System.Diagnostics.Log.Trace(message);
+ System.Diagnostics.Log.Trace(Environment.NewLine);
+ }
+
+ [Pure]
+ [Conditional("_LOGGING")]
+ [SecuritySafeCritical]
+ static public void Log(String switchName, String message) {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ if (!m_registryChecked) {
+ CheckRegistry();
+ }
+ try {
+ LogSwitch ls;
+ ls = LogSwitch.GetSwitch(switchName);
+ if (ls!=null) {
+ System.Diagnostics.Log.Trace(ls,message);
+ System.Diagnostics.Log.Trace(ls,Environment.NewLine);
+ }
+ } catch {
+ System.Diagnostics.Log.Trace("Exception thrown in logging." + Environment.NewLine);
+ System.Diagnostics.Log.Trace("Switch was: " + ((switchName==null)?"<null>":switchName) + Environment.NewLine);
+ System.Diagnostics.Log.Trace("Message was: " + ((message==null)?"<null>":message) + Environment.NewLine);
+ }
+ }
+
+ //
+ // This code gets called during security startup, so we can't go through Marshal to get the values. This is
+ // just a small helper in native code instead of that.
+ //
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int GetRegistryLoggingValues(out bool loggingEnabled, out bool logToConsole, out int logLevel, out bool perfWarnings, out bool correctnessWarnings, out bool safeHandleStackTraces);
+
+ [SecuritySafeCritical]
+ private static void CheckRegistry() {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ if (m_registryChecked) {
+ return;
+ }
+
+ m_registryChecked = true;
+
+ bool loggingEnabled;
+ bool logToConsole;
+ int logLevel;
+ int facilityValue;
+ facilityValue = GetRegistryLoggingValues(out loggingEnabled, out logToConsole, out logLevel, out m_perfWarnings, out m_correctnessWarnings, out m_safeHandleStackTraces);
+
+ // Note we can get into some recursive situations where we call
+ // ourseves recursively through the .cctor. That's why we have the
+ // check for levelConversions == null.
+ if (!loggingEnabled) {
+ m_loggingNotEnabled = true;
+ }
+ if (loggingEnabled && levelConversions!=null) {
+ try {
+ //The values returned for the logging levels in the registry don't map nicely onto the
+ //values which we support internally (which are an approximation of the ones that
+ //the System.Diagnostics namespace uses) so we have a quick map.
+ Assert(logLevel>=0 && logLevel<=10, "logLevel>=0 && logLevel<=10");
+ logLevel = (int)levelConversions[logLevel];
+
+ if (facilityValue>0) {
+ for (int i=0; i<switches.Length; i++) {
+ if ((switches[i].value & facilityValue)!=0) {
+ LogSwitch L = new LogSwitch(switches[i].name, switches[i].name, System.Diagnostics.Log.GlobalSwitch);
+ L.MinimumLevel = (LoggingLevels)logLevel;
+ }
+ }
+ System.Diagnostics.Log.GlobalSwitch.MinimumLevel = (LoggingLevels)logLevel;
+ System.Diagnostics.Log.IsConsoleEnabled = logToConsole;
+ }
+
+ } catch {
+ //Silently eat any exceptions.
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal static bool CheckEnabled(String switchName) {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return false;
+ if (!m_registryChecked)
+ CheckRegistry();
+ LogSwitch logSwitch = LogSwitch.GetSwitch(switchName);
+ if (logSwitch==null) {
+ return false;
+ }
+ return ((int)logSwitch.MinimumLevel<=(int)LogLevel.Trace);
+ }
+
+ [SecuritySafeCritical]
+ private static bool CheckEnabled(String switchName, LogLevel level, out LogSwitch logSwitch) {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ {
+ logSwitch = null;
+ return false;
+ }
+ logSwitch = LogSwitch.GetSwitch(switchName);
+ if (logSwitch==null) {
+ return false;
+ }
+ return ((int)logSwitch.MinimumLevel<=(int)level);
+ }
+
+ [Pure]
+ [Conditional("_LOGGING")]
+ [SecuritySafeCritical]
+ public static void Log(String switchName, LogLevel level, params Object[]messages) {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ //Add code to check if logging is enabled in the registry.
+ LogSwitch logSwitch;
+
+ if (!m_registryChecked) {
+ CheckRegistry();
+ }
+
+ if (!CheckEnabled(switchName, level, out logSwitch)) {
+ return;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+
+ for (int i=0; i<messages.Length; i++) {
+ String s;
+ try {
+ if (messages[i]==null) {
+ s = "<null>";
+ } else {
+ s = messages[i].ToString();
+ }
+ } catch {
+ s = "<unable to convert>";
+ }
+ sb.Append(s);
+ }
+ System.Diagnostics.Log.LogMessage((LoggingLevels)((int)level), logSwitch, StringBuilderCache.GetStringAndRelease(sb));
+ }
+
+ // Note this overload doesn't take a format string. You probably don't
+ // want this one.
+ [Pure]
+ [Conditional("_LOGGING")]
+ public static void Trace(String switchName, params Object[]messages) {
+ if (m_loggingNotEnabled) {
+ return;
+ }
+
+ LogSwitch logSwitch;
+ if (!CheckEnabled(switchName, LogLevel.Trace, out logSwitch)) {
+ return;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+
+ for (int i=0; i<messages.Length; i++) {
+ String s;
+ try {
+ if (messages[i]==null) {
+ s = "<null>";
+ } else {
+ s = messages[i].ToString();
+ }
+ } catch {
+ s = "<unable to convert>";
+ }
+ sb.Append(s);
+ }
+
+ sb.Append(Environment.NewLine);
+ System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, StringBuilderCache.GetStringAndRelease(sb));
+ }
+
+ [Pure]
+ [Conditional("_LOGGING")]
+ public static void Trace(String switchName, String format, params Object[] messages) {
+ if (m_loggingNotEnabled) {
+ return;
+ }
+
+ LogSwitch logSwitch;
+ if (!CheckEnabled(switchName, LogLevel.Trace, out logSwitch)) {
+ return;
+ }
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ sb.AppendFormat(format, messages);
+ sb.Append(Environment.NewLine);
+
+ System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, StringBuilderCache.GetStringAndRelease(sb));
+ }
+
+ [Conditional("_LOGGING")]
+ public static void DumpStack(String switchName) {
+ LogSwitch logSwitch;
+
+ if (!m_registryChecked) {
+ CheckRegistry();
+ }
+
+ if (!CheckEnabled(switchName, LogLevel.Trace, out logSwitch)) {
+ return;
+ }
+
+ StackTrace trace = new StackTrace();
+ System.Diagnostics.Log.LogMessage(LoggingLevels.TraceLevel0, logSwitch, trace.ToString());
+ }
+
+ // For logging errors related to the console - we often can't expect to
+ // write to stdout if it doesn't exist.
+ [SecuritySafeCritical]
+ [Conditional("_DEBUG")]
+ internal static void ConsoleError(String msg)
+ {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+
+ if (m_MakeConsoleErrorLoggingWork == null) {
+ PermissionSet perms = new PermissionSet();
+ perms.AddPermission(new EnvironmentPermission(PermissionState.Unrestricted));
+ perms.AddPermission(new FileIOPermission(FileIOPermissionAccess.AllAccess, Path.GetFullPath(".")));
+ m_MakeConsoleErrorLoggingWork = perms;
+ }
+ m_MakeConsoleErrorLoggingWork.Assert();
+
+ using (TextWriter err = File.AppendText("ConsoleErrors.log"))
+ {
+ err.WriteLine(msg);
+ }
+ }
+
+ // For perf-related asserts. On a debug build, set the registry key
+ // BCLPerfWarnings to non-zero.
+ [Conditional("_DEBUG")]
+ [SecuritySafeCritical]
+ internal static void Perf(bool expr, String msg)
+ {
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ if (!m_registryChecked)
+ CheckRegistry();
+ if (!m_perfWarnings)
+ return;
+
+ if (!expr) {
+ Log("PERF", "BCL Perf Warning: "+msg);
+ }
+ System.Diagnostics.Assert.Check(expr, "BCL Perf Warning: Your perf may be less than perfect because...", msg);
+ }
+
+ // For correctness-related asserts. On a debug build, set the registry key
+ // BCLCorrectnessWarnings to non-zero.
+ [Conditional("_DEBUG")]
+#if _DEBUG
+ [SecuritySafeCritical]
+#endif
+ internal static void Correctness(bool expr, String msg)
+ {
+#if _DEBUG
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return;
+ if (!m_registryChecked)
+ CheckRegistry();
+ if (!m_correctnessWarnings)
+ return;
+
+ if (!m_domainUnloadAdded) {
+ m_domainUnloadAdded = true;
+ AppDomain.CurrentDomain.DomainUnload += new EventHandler(WaitForFinalizers);
+ }
+
+ if (!expr) {
+ Log("CORRECTNESS", "BCL Correctness Warning: "+msg);
+ }
+ System.Diagnostics.Assert.Check(expr, "BCL Correctness Warning: Your program may not work because...", msg);
+#endif
+ }
+
+#if !BIT64 // 32
+ [SecuritySafeCritical]
+#endif
+ internal static bool CorrectnessEnabled()
+ {
+#if BIT64
+ return false;
+#else // 32
+ if (AppDomain.CurrentDomain.IsUnloadingForcedFinalize())
+ return false;
+ if (!m_registryChecked)
+ CheckRegistry();
+ return m_correctnessWarnings;
+#endif // BIT64
+ }
+
+ // Whether SafeHandles include a stack trace showing where they
+ // were allocated. Only useful in checked & debug builds.
+ internal static bool SafeHandleStackTracesEnabled {
+ get {
+#if _DEBUG
+ if (!m_registryChecked)
+ CheckRegistry();
+ return m_safeHandleStackTraces;
+#else
+ return false;
+#endif
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/BadImageFormatException.cs b/src/mscorlib/src/System/BadImageFormatException.cs
new file mode 100644
index 0000000000..b71fcc3a49
--- /dev/null
+++ b/src/mscorlib/src/System/BadImageFormatException.cs
@@ -0,0 +1,158 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Exception to an invalid dll or executable format.
+**
+**
+===========================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ using FileLoadException = System.IO.FileLoadException;
+ using System.Security.Permissions;
+ using SecurityException = System.Security.SecurityException;
+ using System.Globalization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class BadImageFormatException : SystemException {
+
+ private String _fileName; // The name of the corrupt PE file.
+ private String _fusionLog; // fusion log (when applicable)
+
+ public BadImageFormatException()
+ : base(Environment.GetResourceString("Arg_BadImageFormatException")) {
+ SetErrorCode(__HResults.COR_E_BADIMAGEFORMAT);
+ }
+
+ public BadImageFormatException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_BADIMAGEFORMAT);
+ }
+
+ public BadImageFormatException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_BADIMAGEFORMAT);
+ }
+
+ public BadImageFormatException(String message, String fileName) : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_BADIMAGEFORMAT);
+ _fileName = fileName;
+ }
+
+ public BadImageFormatException(String message, String fileName, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_BADIMAGEFORMAT);
+ _fileName = fileName;
+ }
+
+ public override String Message
+ {
+ get {
+ SetMessageField();
+ return _message;
+ }
+ }
+
+ private void SetMessageField()
+ {
+ if (_message == null) {
+ if ((_fileName == null) &&
+ (HResult == System.__HResults.COR_E_EXCEPTION))
+ _message = Environment.GetResourceString("Arg_BadImageFormatException");
+
+ else
+ _message = FileLoadException.FormatFileLoadExceptionMessage(_fileName, HResult);
+ }
+ }
+
+ public String FileName {
+ get { return _fileName; }
+ }
+
+ public override String ToString()
+ {
+ String s = GetType().FullName + ": " + Message;
+
+ if (_fileName != null && _fileName.Length != 0)
+ s += Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", _fileName);
+
+ if (InnerException != null)
+ s = s + " ---> " + InnerException.ToString();
+
+ if (StackTrace != null)
+ s += Environment.NewLine + StackTrace;
+ try
+ {
+ if(FusionLog!=null)
+ {
+ if (s==null)
+ s=" ";
+ s+=Environment.NewLine;
+ s+=Environment.NewLine;
+ s+=FusionLog;
+ }
+ }
+ catch(SecurityException)
+ {
+
+ }
+ return s;
+ }
+
+ protected BadImageFormatException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ // Base class constructor will check info != null.
+
+ _fileName = info.GetString("BadImageFormat_FileName");
+ try
+ {
+ _fusionLog = info.GetString("BadImageFormat_FusionLog");
+ }
+ catch
+ {
+ _fusionLog = null;
+ }
+ }
+
+ private BadImageFormatException(String fileName, String fusionLog, int hResult)
+ : base(null)
+ {
+ SetErrorCode(hResult);
+ _fileName = fileName;
+ _fusionLog=fusionLog;
+ SetMessageField();
+ }
+
+ public String FusionLog {
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable CS0618 // Type or member is obsolete
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+#pragma warning restore CS0618 // Type or member is obsolete
+ get { return _fusionLog; }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ // Serialize data for our base classes. base will verify info != null.
+ base.GetObjectData(info, context);
+
+ // Serialize data for this class
+ info.AddValue("BadImageFormat_FileName", _fileName, typeof(String));
+ try
+ {
+ info.AddValue("BadImageFormat_FusionLog", FusionLog, typeof(String));
+ }
+ catch (SecurityException)
+ {
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/BitConverter.cs b/src/mscorlib/src/System/BitConverter.cs
new file mode 100644
index 0000000000..e4bb9ddc88
--- /dev/null
+++ b/src/mscorlib/src/System/BitConverter.cs
@@ -0,0 +1,451 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Allows developers to view the base data types as
+** an arbitrary array of bits.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+
+ // The BitConverter class contains methods for
+ // converting an array of bytes to one of the base data
+ // types, as well as for converting a base data type to an
+ // array of bytes.
+ //
+ // Only statics, does not need to be marked with the serializable attribute
+ public static class BitConverter {
+
+ // This field indicates the "endianess" of the architecture.
+ // The value is set to true if the architecture is
+ // little endian; false if it is big endian.
+#if BIGENDIAN
+ public static readonly bool IsLittleEndian /* = false */;
+#else
+ public static readonly bool IsLittleEndian = true;
+#endif
+
+ // Converts a byte into an array of bytes with length one.
+ public static byte[] GetBytes(bool value) {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 1);
+
+ byte[] r = new byte[1];
+ r[0] = (value ? (byte)Boolean.True : (byte)Boolean.False );
+ return r;
+ }
+
+ // Converts a char into an array of bytes with length two.
+ public static byte[] GetBytes(char value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 2);
+
+ return GetBytes((short)value);
+ }
+
+ // Converts a short into an array of bytes with length
+ // two.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static byte[] GetBytes(short value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 2);
+
+ byte[] bytes = new byte[2];
+ fixed(byte* b = bytes)
+ *((short*)b) = value;
+ return bytes;
+ }
+
+ // Converts an int into an array of bytes with length
+ // four.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static byte[] GetBytes(int value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 4);
+
+ byte[] bytes = new byte[4];
+ fixed(byte* b = bytes)
+ *((int*)b) = value;
+ return bytes;
+ }
+
+ // Converts a long into an array of bytes with length
+ // eight.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static byte[] GetBytes(long value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 8);
+
+ byte[] bytes = new byte[8];
+ fixed(byte* b = bytes)
+ *((long*)b) = value;
+ return bytes;
+ }
+
+ // Converts an ushort into an array of bytes with
+ // length two.
+ [CLSCompliant(false)]
+ public static byte[] GetBytes(ushort value) {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 2);
+
+ return GetBytes((short)value);
+ }
+
+ // Converts an uint into an array of bytes with
+ // length four.
+ [CLSCompliant(false)]
+ public static byte[] GetBytes(uint value) {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 4);
+
+ return GetBytes((int)value);
+ }
+
+ // Converts an unsigned long into an array of bytes with
+ // length eight.
+ [CLSCompliant(false)]
+ public static byte[] GetBytes(ulong value) {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 8);
+
+ return GetBytes((long)value);
+ }
+
+ // Converts a float into an array of bytes with length
+ // four.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static byte[] GetBytes(float value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 4);
+
+ return GetBytes(*(int*)&value);
+ }
+
+ // Converts a double into an array of bytes with length
+ // eight.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static byte[] GetBytes(double value)
+ {
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == 8);
+
+ return GetBytes(*(long*)&value);
+ }
+
+ // Converts an array of bytes into a char.
+ public static char ToChar(byte[] value, int startIndex)
+ {
+ if (value == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ }
+
+ if ((uint)startIndex >= value.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (startIndex > value.Length - 2) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+ Contract.EndContractBlock();
+
+ return (char)ToInt16(value, startIndex);
+ }
+
+ // Converts an array of bytes into a short.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static unsafe short ToInt16(byte[] value, int startIndex) {
+ if( value == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ }
+
+ if ((uint) startIndex >= value.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (startIndex > value.Length -2) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+ Contract.EndContractBlock();
+
+ fixed( byte * pbyte = &value[startIndex]) {
+ if( startIndex % 2 == 0) { // data is aligned
+ return *((short *) pbyte);
+ }
+ else {
+ if( IsLittleEndian) {
+ return (short)((*pbyte) | (*(pbyte + 1) << 8)) ;
+ }
+ else {
+ return (short)((*pbyte << 8) | (*(pbyte + 1)));
+ }
+ }
+ }
+
+ }
+
+ // Converts an array of bytes into an int.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static unsafe int ToInt32 (byte[] value, int startIndex) {
+ if( value == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ }
+
+ if ((uint) startIndex >= value.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (startIndex > value.Length -4) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+ Contract.EndContractBlock();
+
+ fixed( byte * pbyte = &value[startIndex]) {
+ if( startIndex % 4 == 0) { // data is aligned
+ return *((int *) pbyte);
+ }
+ else {
+ if( IsLittleEndian) {
+ return (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
+ }
+ else {
+ return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ }
+ }
+ }
+ }
+
+ // Converts an array of bytes into a long.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static unsafe long ToInt64 (byte[] value, int startIndex) {
+ if (value == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ }
+
+ if ((uint) startIndex >= value.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (startIndex > value.Length -8) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+ Contract.EndContractBlock();
+
+ fixed( byte * pbyte = &value[startIndex]) {
+ if( startIndex % 8 == 0) { // data is aligned
+ return *((long *) pbyte);
+ }
+ else {
+ if( IsLittleEndian) {
+ int i1 = (*pbyte) | (*(pbyte + 1) << 8) | (*(pbyte + 2) << 16) | (*(pbyte + 3) << 24);
+ int i2 = (*(pbyte+4)) | (*(pbyte + 5) << 8) | (*(pbyte + 6) << 16) | (*(pbyte + 7) << 24);
+ return (uint)i1 | ((long)i2 << 32);
+ }
+ else {
+ int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ int i2 = (*(pbyte+4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
+ return (uint)i2 | ((long)i1 << 32);
+ }
+ }
+ }
+ }
+
+
+ // Converts an array of bytes into an ushort.
+ //
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(byte[] value, int startIndex)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ if ((uint)startIndex >= value.Length)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (startIndex > value.Length - 2)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ Contract.EndContractBlock();
+
+ return (ushort)ToInt16(value, startIndex);
+ }
+
+ // Converts an array of bytes into an uint.
+ //
+ [CLSCompliant(false)]
+ public static uint ToUInt32(byte[] value, int startIndex)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ if ((uint)startIndex >= value.Length)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (startIndex > value.Length - 4)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ Contract.EndContractBlock();
+
+ return (uint)ToInt32(value, startIndex);
+ }
+
+ // Converts an array of bytes into an unsigned long.
+ //
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(byte[] value, int startIndex)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ if ((uint)startIndex >= value.Length)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (startIndex > value.Length - 8)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ Contract.EndContractBlock();
+
+ return (ulong)ToInt64(value, startIndex);
+ }
+
+ // Converts an array of bytes into a float.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public static float ToSingle (byte[] value, int startIndex)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ if ((uint)startIndex >= value.Length)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (startIndex > value.Length - 4)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ Contract.EndContractBlock();
+
+ int val = ToInt32(value, startIndex);
+ return *(float*)&val;
+ }
+
+ // Converts an array of bytes into a double.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public static double ToDouble (byte[] value, int startIndex)
+ {
+ if (value == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.value);
+ if ((uint)startIndex >= value.Length)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ if (startIndex > value.Length - 8)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ Contract.EndContractBlock();
+
+ long val = ToInt64(value, startIndex);
+ return *(double*)&val;
+ }
+
+ private static char GetHexValue(int i) {
+ Contract.Assert( i >=0 && i <16, "i is out of range.");
+ if (i<10) {
+ return (char)(i + '0');
+ }
+
+ return (char)(i - 10 + 'A');
+ }
+
+ // Converts an array of bytes into a String.
+ public static String ToString (byte[] value, int startIndex, int length) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if (startIndex < 0 || startIndex >= value.Length && startIndex > 0) { // Don't throw for a 0 length array.
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+
+ if (startIndex > value.Length - length) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ }
+ Contract.EndContractBlock();
+
+ if (length == 0) {
+ return string.Empty;
+ }
+
+ if (length > (Int32.MaxValue / 3)) {
+ // (Int32.MaxValue / 3) == 715,827,882 Bytes == 699 MB
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthTooLarge", (Int32.MaxValue / 3)));
+ }
+
+ int chArrayLength = length * 3;
+
+ char[] chArray = new char[chArrayLength];
+ int i = 0;
+ int index = startIndex;
+ for (i = 0; i < chArrayLength; i += 3) {
+ byte b = value[index++];
+ chArray[i]= GetHexValue(b/16);
+ chArray[i+1] = GetHexValue(b%16);
+ chArray[i+2] = '-';
+ }
+
+ // We don't need the last '-' character
+ return new String(chArray, 0, chArray.Length - 1);
+ }
+
+ // Converts an array of bytes into a String.
+ public static String ToString(byte [] value) {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return ToString(value, 0, value.Length);
+ }
+
+ // Converts an array of bytes into a String.
+ public static String ToString (byte [] value, int startIndex) {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return ToString(value, startIndex, value.Length - startIndex);
+ }
+
+ /*==================================ToBoolean===================================
+ **Action: Convert an array of bytes to a boolean value. We treat this array
+ ** as if the first 4 bytes were an Int4 an operate on this value.
+ **Returns: True if the Int4 value of the first 4 bytes is non-zero.
+ **Arguments: value -- The byte array
+ ** startIndex -- The position within the array.
+ **Exceptions: See ToInt4.
+ ==============================================================================*/
+ // Converts an array of bytes into a boolean.
+ public static bool ToBoolean(byte[] value, int startIndex) {
+ if (value==null)
+ throw new ArgumentNullException("value");
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (startIndex > value.Length - 1)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ return (value[startIndex]==0)?false:true;
+ }
+
+ [SecuritySafeCritical]
+ public static unsafe long DoubleToInt64Bits(double value) {
+ return *((long *)&value);
+ }
+
+ [SecuritySafeCritical]
+ public static unsafe double Int64BitsToDouble(long value) {
+ return *((double*)&value);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Boolean.cs b/src/mscorlib/src/System/Boolean.cs
new file mode 100644
index 0000000000..c5cd45a428
--- /dev/null
+++ b/src/mscorlib/src/System/Boolean.cs
@@ -0,0 +1,305 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The boolean class serves as a wrapper for the primitive
+** type boolean.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ // The Boolean class provides the
+ // object representation of the boolean primitive type.
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct Boolean : IComparable, IConvertible, IComparable<Boolean>, IEquatable<Boolean>
+ {
+
+ //
+ // Member Variables
+ //
+ private bool m_value;
+
+ // The true value.
+ //
+ internal const int True = 1;
+
+ // The false value.
+ //
+ internal const int False = 0;
+
+
+ //
+ // Internal Constants are real consts for performance.
+ //
+
+ // The internal string representation of true.
+ //
+ internal const String TrueLiteral = "True";
+
+ // The internal string representation of false.
+ //
+ internal const String FalseLiteral = "False";
+
+
+ //
+ // Public Constants
+ //
+
+ // The public string representation of true.
+ //
+ public static readonly String TrueString = TrueLiteral;
+
+ // The public string representation of false.
+ //
+ public static readonly String FalseString = FalseLiteral;
+
+ //
+ // Overriden Instance Methods
+ //
+ /*=================================GetHashCode==================================
+ **Args: None
+ **Returns: 1 or 0 depending on whether this instance represents true or false.
+ **Exceptions: None
+ **Overriden From: Value
+ ==============================================================================*/
+ // Provides a hash code for this instance.
+ public override int GetHashCode() {
+ return (m_value)?True:False;
+ }
+
+ /*===================================ToString===================================
+ **Args: None
+ **Returns: "True" or "False" depending on the state of the boolean.
+ **Exceptions: None.
+ ==============================================================================*/
+ // Converts the boolean value of this instance to a String.
+ public override String ToString() {
+ if (false == m_value) {
+ return FalseLiteral;
+ }
+ return TrueLiteral;
+ }
+
+ public String ToString(IFormatProvider provider) {
+ if (false == m_value) {
+ return FalseLiteral;
+ }
+ return TrueLiteral;
+ }
+
+ // Determines whether two Boolean objects are equal.
+ public override bool Equals (Object obj) {
+ //If it's not a boolean, we're definitely not equal
+ if (!(obj is Boolean)) {
+ return false;
+ }
+
+ return (m_value==((Boolean)obj).m_value);
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Boolean obj)
+ {
+ return m_value == obj;
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship. For booleans, false sorts before true.
+ // null is considered to be less than any instance.
+ // If object is not of type boolean, this method throws an ArgumentException.
+ //
+ // Returns a value less than zero if this object
+ //
+ public int CompareTo(Object obj) {
+ if (obj==null) {
+ return 1;
+ }
+ if (!(obj is Boolean)) {
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeBoolean"));
+ }
+
+ if (m_value==((Boolean)obj).m_value) {
+ return 0;
+ } else if (m_value==false) {
+ return -1;
+ }
+ return 1;
+ }
+
+ public int CompareTo(Boolean value) {
+ if (m_value==value) {
+ return 0;
+ } else if (m_value==false) {
+ return -1;
+ }
+ return 1;
+ }
+
+ //
+ // Static Methods
+ //
+
+ // Determines whether a String represents true or false.
+ //
+ public static Boolean Parse (String value) {
+ if (value==null) throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+ Boolean result = false;
+ if (!TryParse(value, out result)) {
+ throw new FormatException(Environment.GetResourceString("Format_BadBoolean"));
+ }
+ else {
+ return result;
+ }
+ }
+
+ // Determines whether a String represents true or false.
+ //
+ public static Boolean TryParse (String value, out Boolean result) {
+ result = false;
+ if (value==null) {
+ return false;
+ }
+ // For perf reasons, let's first see if they're equal, then do the
+ // trim to get rid of white space, and check again.
+ if (TrueLiteral.Equals(value, StringComparison.OrdinalIgnoreCase)) {
+ result = true;
+ return true;
+ }
+ if (FalseLiteral.Equals(value,StringComparison.OrdinalIgnoreCase)) {
+ result = false;
+ return true;
+ }
+
+ // Special case: Trim whitespace as well as null characters.
+ value = TrimWhiteSpaceAndNull(value);
+
+ if (TrueLiteral.Equals(value, StringComparison.OrdinalIgnoreCase)) {
+ result = true;
+ return true;
+ }
+
+ if (FalseLiteral.Equals(value,StringComparison.OrdinalIgnoreCase)) {
+ result = false;
+ return true;
+ }
+
+ return false;
+ }
+
+ private static String TrimWhiteSpaceAndNull(String value) {
+ int start = 0;
+ int end = value.Length-1;
+ char nullChar = (char) 0x0000;
+
+ while (start < value.Length) {
+ if (!Char.IsWhiteSpace(value[start]) && value[start] != nullChar) {
+ break;
+ }
+ start++;
+ }
+
+ while (end >= start) {
+ if (!Char.IsWhiteSpace(value[end]) && value[end] != nullChar) {
+ break;
+ }
+ end--;
+ }
+
+ return value.Substring(start, end - start + 1);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Boolean;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Boolean", "Char"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Boolean", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Buffer.cs b/src/mscorlib/src/System/Buffer.cs
new file mode 100644
index 0000000000..ea647f1e9a
--- /dev/null
+++ b/src/mscorlib/src/System/Buffer.cs
@@ -0,0 +1,645 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ //Only contains static methods. Does not require serialization
+
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+ using System.Runtime;
+
+#if BIT64
+ using nuint = System.UInt64;
+#else // BIT64
+ using nuint = System.UInt32;
+#endif // BIT64
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public static class Buffer
+ {
+ // Copies from one primitive array to another primitive array without
+ // respecting types. This calls memmove internally. The count and
+ // offset parameters here are in bytes. If you want to use traditional
+ // array element indices and counts, use Array.Copy.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void BlockCopy(Array src, int srcOffset,
+ Array dst, int dstOffset, int count);
+
+ // A very simple and efficient memmove that assumes all of the
+ // parameter validation has already been done. The count and offset
+ // parameters here are in bytes. If you want to use traditional
+ // array element indices and counts, use Array.Copy.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InternalBlockCopy(Array src, int srcOffsetBytes,
+ Array dst, int dstOffsetBytes, int byteCount);
+
+ // This is ported from the optimized CRT assembly in memchr.asm. The JIT generates
+ // pretty good code here and this ends up being within a couple % of the CRT asm.
+ // It is however cross platform as the CRT hasn't ported their fast version to 64-bit
+ // platforms.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static int IndexOfByte(byte* src, byte value, int index, int count)
+ {
+ Contract.Assert(src != null, "src should not be null");
+
+ byte* pByte = src + index;
+
+ // Align up the pointer to sizeof(int).
+ while (((int)pByte & 3) != 0)
+ {
+ if (count == 0)
+ return -1;
+ else if (*pByte == value)
+ return (int) (pByte - src);
+
+ count--;
+ pByte++;
+ }
+
+ // Fill comparer with value byte for comparisons
+ //
+ // comparer = 0/0/value/value
+ uint comparer = (((uint)value << 8) + (uint)value);
+ // comparer = value/value/value/value
+ comparer = (comparer << 16) + comparer;
+
+ // Run through buffer until we hit a 4-byte section which contains
+ // the byte we're looking for or until we exhaust the buffer.
+ while (count > 3)
+ {
+ // Test the buffer for presence of value. comparer contains the byte
+ // replicated 4 times.
+ uint t1 = *(uint*)pByte;
+ t1 = t1 ^ comparer;
+ uint t2 = 0x7efefeff + t1;
+ t1 = t1 ^ 0xffffffff;
+ t1 = t1 ^ t2;
+ t1 = t1 & 0x81010100;
+
+ // if t1 is zero then these 4-bytes don't contain a match
+ if (t1 != 0)
+ {
+ // We've found a match for value, figure out which position it's in.
+ int foundIndex = (int) (pByte - src);
+ if (pByte[0] == value)
+ return foundIndex;
+ else if (pByte[1] == value)
+ return foundIndex + 1;
+ else if (pByte[2] == value)
+ return foundIndex + 2;
+ else if (pByte[3] == value)
+ return foundIndex + 3;
+ }
+
+ count -= 4;
+ pByte += 4;
+
+ }
+
+ // Catch any bytes that might be left at the tail of the buffer
+ while (count > 0)
+ {
+ if (*pByte == value)
+ return (int) (pByte - src);
+
+ count--;
+ pByte++;
+ }
+
+ // If we don't have a match return -1;
+ return -1;
+ }
+
+ // Returns a bool to indicate if the array is of primitive data types
+ // or not.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool IsPrimitiveTypeArray(Array array);
+
+ // Gets a particular byte out of the array. The array must be an
+ // array of primitives.
+ //
+ // This essentially does the following:
+ // return ((byte*)array) + index.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern byte _GetByte(Array array, int index);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static byte GetByte(Array array, int index)
+ {
+ // Is the array present?
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ // Is it of primitive types?
+ if (!IsPrimitiveTypeArray(array))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array");
+
+ // Is the index in valid range of the array?
+ if (index < 0 || index >= _ByteLength(array))
+ throw new ArgumentOutOfRangeException("index");
+
+ return _GetByte(array, index);
+ }
+
+ // Sets a particular byte in an the array. The array must be an
+ // array of primitives.
+ //
+ // This essentially does the following:
+ // *(((byte*)array) + index) = value.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _SetByte(Array array, int index, byte value);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetByte(Array array, int index, byte value)
+ {
+ // Is the array present?
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ // Is it of primitive types?
+ if (!IsPrimitiveTypeArray(array))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array");
+
+ // Is the index in valid range of the array?
+ if (index < 0 || index >= _ByteLength(array))
+ throw new ArgumentOutOfRangeException("index");
+
+ // Make the FCall to do the work
+ _SetByte(array, index, value);
+ }
+
+
+ // Gets a particular byte out of the array. The array must be an
+ // array of primitives.
+ //
+ // This essentially does the following:
+ // return array.length * sizeof(array.UnderlyingElementType).
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int _ByteLength(Array array);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int ByteLength(Array array)
+ {
+ // Is the array present?
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ // Is it of primitive types?
+ if (!IsPrimitiveTypeArray(array))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePrimArray"), "array");
+
+ return _ByteLength(array);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static void ZeroMemory(byte* src, long len)
+ {
+ while(len-- > 0)
+ *(src + len) = 0;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe static void Memcpy(byte[] dest, int destIndex, byte* src, int srcIndex, int len) {
+ Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
+ Contract.Assert(dest.Length - destIndex >= len, "not enough bytes in dest");
+ // If dest has 0 elements, the fixed statement will throw an
+ // IndexOutOfRangeException. Special-case 0-byte copies.
+ if (len==0)
+ return;
+ fixed(byte* pDest = dest) {
+ Memcpy(pDest + destIndex, src + srcIndex, len);
+ }
+ }
+
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe static void Memcpy(byte* pDest, int destIndex, byte[] src, int srcIndex, int len)
+ {
+ Contract.Assert( (srcIndex >= 0) && (destIndex >= 0) && (len >= 0), "Index and length must be non-negative!");
+ Contract.Assert(src.Length - srcIndex >= len, "not enough bytes in src");
+ // If dest has 0 elements, the fixed statement will throw an
+ // IndexOutOfRangeException. Special-case 0-byte copies.
+ if (len==0)
+ return;
+ fixed(byte* pSrc = src) {
+ Memcpy(pDest + destIndex, pSrc + srcIndex, len);
+ }
+ }
+
+ // This is tricky to get right AND fast, so lets make it useful for the whole Fx.
+ // E.g. System.Runtime.WindowsRuntime!WindowsRuntimeBufferExtensions.MemCopy uses it.
+
+ // This method has a slightly different behavior on arm and other platforms.
+ // On arm this method behaves like memcpy and does not handle overlapping buffers.
+ // While on other platforms it behaves like memmove and handles overlapping buffers.
+ // This behavioral difference is unfortunate but intentional because
+ // 1. This method is given access to other internal dlls and this close to release we do not want to change it.
+ // 2. It is difficult to get this right for arm and again due to release dates we would like to visit it later.
+ [FriendAccessAllowed]
+ [System.Security.SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#if ARM
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe static extern void Memcpy(byte* dest, byte* src, int len);
+#else // ARM
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ internal unsafe static void Memcpy(byte* dest, byte* src, int len) {
+ Contract.Assert(len >= 0, "Negative length in memcopy!");
+ Memmove(dest, src, (uint)len);
+ }
+#endif // ARM
+
+ // This method has different signature for x64 and other platforms and is done for performance reasons.
+ [System.Security.SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe static void Memmove(byte* dest, byte* src, nuint len)
+ {
+ // P/Invoke into the native version when the buffers are overlapping and the copy needs to be performed backwards
+ // This check can produce false positives for lengths greater than Int32.MaxInt. It is fine because we want to use PInvoke path for the large lengths anyway.
+
+ if ((nuint)dest - (nuint)src < len) goto PInvoke;
+
+ // This is portable version of memcpy. It mirrors what the hand optimized assembly versions of memcpy typically do.
+ //
+ // Ideally, we would just use the cpblk IL instruction here. Unfortunately, cpblk IL instruction is not as efficient as
+ // possible yet and so we have this implementation here for now.
+
+ // Note: It's important that this switch handles lengths at least up to 22.
+ // See notes below near the main loop for why.
+
+ // The switch will be very fast since it can be implemented using a jump
+ // table in assembly. See http://stackoverflow.com/a/449297/4077294 for more info.
+
+ switch (len)
+ {
+ case 0:
+ return;
+ case 1:
+ *dest = *src;
+ return;
+ case 2:
+ *(short*)dest = *(short*)src;
+ return;
+ case 3:
+ *(short*)dest = *(short*)src;
+ *(dest + 2) = *(src + 2);
+ return;
+ case 4:
+ *(int*)dest = *(int*)src;
+ return;
+ case 5:
+ *(int*)dest = *(int*)src;
+ *(dest + 4) = *(src + 4);
+ return;
+ case 6:
+ *(int*)dest = *(int*)src;
+ *(short*)(dest + 4) = *(short*)(src + 4);
+ return;
+ case 7:
+ *(int*)dest = *(int*)src;
+ *(short*)(dest + 4) = *(short*)(src + 4);
+ *(dest + 6) = *(src + 6);
+ return;
+ case 8:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ return;
+ case 9:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(dest + 8) = *(src + 8);
+ return;
+ case 10:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(short*)(dest + 8) = *(short*)(src + 8);
+ return;
+ case 11:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(short*)(dest + 8) = *(short*)(src + 8);
+ *(dest + 10) = *(src + 10);
+ return;
+ case 12:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ return;
+ case 13:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(dest + 12) = *(src + 12);
+ return;
+ case 14:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(short*)(dest + 12) = *(short*)(src + 12);
+ return;
+ case 15:
+#if BIT64
+ *(long*)dest = *(long*)src;
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+#endif
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(short*)(dest + 12) = *(short*)(src + 12);
+ *(dest + 14) = *(src + 14);
+ return;
+ case 16:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ return;
+ case 17:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(dest + 16) = *(src + 16);
+ return;
+ case 18:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(short*)(dest + 16) = *(short*)(src + 16);
+ return;
+ case 19:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(short*)(dest + 16) = *(short*)(src + 16);
+ *(dest + 18) = *(src + 18);
+ return;
+ case 20:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(int*)(dest + 16) = *(int*)(src + 16);
+ return;
+ case 21:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(int*)(dest + 16) = *(int*)(src + 16);
+ *(dest + 20) = *(src + 20);
+ return;
+ case 22:
+#if BIT64
+ *(long*)dest = *(long*)src;
+ *(long*)(dest + 8) = *(long*)(src + 8);
+#else
+ *(int*)dest = *(int*)src;
+ *(int*)(dest + 4) = *(int*)(src + 4);
+ *(int*)(dest + 8) = *(int*)(src + 8);
+ *(int*)(dest + 12) = *(int*)(src + 12);
+#endif
+ *(int*)(dest + 16) = *(int*)(src + 16);
+ *(short*)(dest + 20) = *(short*)(src + 20);
+ return;
+ }
+
+ // P/Invoke into the native version for large lengths
+ if (len >= 512) goto PInvoke;
+
+ nuint i = 0; // byte offset at which we're copying
+
+ if (((int)dest & 3) != 0)
+ {
+ if (((int)dest & 1) != 0)
+ {
+ *(dest + i) = *(src + i);
+ i += 1;
+ if (((int)dest & 2) != 0)
+ goto IntAligned;
+ }
+ *(short*)(dest + i) = *(short*)(src + i);
+ i += 2;
+ }
+
+ IntAligned:
+
+#if BIT64
+ // On 64-bit IntPtr.Size == 8, so we want to advance to the next 8-aligned address. If
+ // (int)dest % 8 is 0, 5, 6, or 7, we will already have advanced by 0, 3, 2, or 1
+ // bytes to the next aligned address (respectively), so do nothing. On the other hand,
+ // if it is 1, 2, 3, or 4 we will want to copy-and-advance another 4 bytes until
+ // we're aligned.
+ // The thing 1, 2, 3, and 4 have in common that the others don't is that if you
+ // subtract one from them, their 3rd lsb will not be set. Hence, the below check.
+
+ if ((((int)dest - 1) & 4) == 0)
+ {
+ *(int*)(dest + i) = *(int*)(src + i);
+ i += 4;
+ }
+#endif // BIT64
+
+ nuint end = len - 16;
+ len -= i; // lower 4 bits of len represent how many bytes are left *after* the unrolled loop
+
+ // We know due to the above switch-case that this loop will always run 1 iteration; max
+ // bytes we copy before checking is 23 (7 to align the pointers, 16 for 1 iteration) so
+ // the switch handles lengths 0-22.
+ Contract.Assert(end >= 7 && i <= end);
+
+ // This is separated out into a different variable, so the i + 16 addition can be
+ // performed at the start of the pipeline and the loop condition does not have
+ // a dependency on the writes.
+ nuint counter;
+
+ do
+ {
+ counter = i + 16;
+
+ // This loop looks very costly since there appear to be a bunch of temporary values
+ // being created with the adds, but the jit (for x86 anyways) will convert each of
+ // these to use memory addressing operands.
+
+ // So the only cost is a bit of code size, which is made up for by the fact that
+ // we save on writes to dest/src.
+
+#if BIT64
+ *(long*)(dest + i) = *(long*)(src + i);
+ *(long*)(dest + i + 8) = *(long*)(src + i + 8);
+#else
+ *(int*)(dest + i) = *(int*)(src + i);
+ *(int*)(dest + i + 4) = *(int*)(src + i + 4);
+ *(int*)(dest + i + 8) = *(int*)(src + i + 8);
+ *(int*)(dest + i + 12) = *(int*)(src + i + 12);
+#endif
+
+ i = counter;
+
+ // See notes above for why this wasn't used instead
+ // i += 16;
+ }
+ while (counter <= end);
+
+ if ((len & 8) != 0)
+ {
+#if BIT64
+ *(long*)(dest + i) = *(long*)(src + i);
+#else
+ *(int*)(dest + i) = *(int*)(src + i);
+ *(int*)(dest + i + 4) = *(int*)(src + i + 4);
+#endif
+ i += 8;
+ }
+ if ((len & 4) != 0)
+ {
+ *(int*)(dest + i) = *(int*)(src + i);
+ i += 4;
+ }
+ if ((len & 2) != 0)
+ {
+ *(short*)(dest + i) = *(short*)(src + i);
+ i += 2;
+ }
+ if ((len & 1) != 0)
+ {
+ *(dest + i) = *(src + i);
+ // We're not using i after this, so not needed
+ // i += 1;
+ }
+
+ return;
+
+ PInvoke:
+ _Memmove(dest, src, len);
+
+ }
+
+ // Non-inlinable wrapper around the QCall that avoids poluting the fast path
+ // with P/Invoke prolog/epilog.
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ private unsafe static void _Memmove(byte* dest, byte* src, nuint len)
+ {
+ __Memmove(dest, src, len);
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ extern private unsafe static void __Memmove(byte* dest, byte* src, nuint len);
+
+ // The attributes on this method are chosen for best JIT performance.
+ // Please do not edit unless intentional.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static unsafe void MemoryCopy(void* source, void* destination, long destinationSizeInBytes, long sourceBytesToCopy)
+ {
+ if (sourceBytesToCopy > destinationSizeInBytes)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
+ }
+ Memmove((byte*)destination, (byte*)source, checked((nuint)sourceBytesToCopy));
+ }
+
+
+ // The attributes on this method are chosen for best JIT performance.
+ // Please do not edit unless intentional.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ [CLSCompliant(false)]
+ public static unsafe void MemoryCopy(void* source, void* destination, ulong destinationSizeInBytes, ulong sourceBytesToCopy)
+ {
+ if (sourceBytesToCopy > destinationSizeInBytes)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.sourceBytesToCopy);
+ }
+#if BIT64
+ Memmove((byte*)destination, (byte*)source, sourceBytesToCopy);
+#else // BIT64
+ Memmove((byte*)destination, (byte*)source, checked((uint)sourceBytesToCopy));
+#endif // BIT64
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Byte.cs b/src/mscorlib/src/System/Byte.cs
new file mode 100644
index 0000000000..2c24bf6d3b
--- /dev/null
+++ b/src/mscorlib/src/System/Byte.cs
@@ -0,0 +1,253 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a byte and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // The Byte class extends the Value class and
+ // provides object representation of the byte primitive type.
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ public struct Byte : IComparable, IFormattable, IConvertible
+ , IComparable<Byte>, IEquatable<Byte>
+ {
+ private byte m_value;
+
+ // The maximum value that a Byte may represent: 255.
+ public const byte MaxValue = (byte)0xFF;
+
+ // The minimum value that a Byte may represent: 0.
+ public const byte MinValue = 0;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type byte, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (!(value is Byte)) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeByte"));
+ }
+
+ return m_value - (((Byte)value).m_value);
+ }
+
+ public int CompareTo(Byte value) {
+ return m_value - value;
+ }
+
+ // Determines whether two Byte objects are equal.
+ public override bool Equals(Object obj) {
+ if (!(obj is Byte)) {
+ return false;
+ }
+ return m_value == ((Byte)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Byte obj)
+ {
+ return m_value == obj;
+ }
+
+ // Gets a hash code for this instance.
+ public override int GetHashCode() {
+ return m_value;
+ }
+
+ [Pure]
+ public static byte Parse(String s) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static byte Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static byte Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ // Parses an unsigned byte from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ [Pure]
+ public static byte Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static byte Parse(String s, NumberStyles style, NumberFormatInfo info) {
+ int i = 0;
+ try {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch(OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Byte"), e);
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Byte"));
+ return (byte)i;
+ }
+
+ public static bool TryParse(String s, out Byte result) {
+ return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Byte result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out Byte result) {
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i)) {
+ return false;
+ }
+ if (i < MinValue || i > MaxValue) {
+ return false;
+ }
+ result = (byte) i;
+ return true;
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ //
+ // IConvertible implementation
+ //
+ [Pure]
+ public TypeCode GetTypeCode() {
+ return TypeCode.Byte;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Byte", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/CLRConfig.cs b/src/mscorlib/src/System/CLRConfig.cs
new file mode 100644
index 0000000000..0831c4bb65
--- /dev/null
+++ b/src/mscorlib/src/System/CLRConfig.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System {
+
+/// <summary>
+/// For now, this class should be the central point to collect all managed declarations
+/// of native functions designed to expose config switches.
+/// In Dev11 M2.2 we will redesign this class to expose CLRConfig from within the CLR
+/// and refactor managed Fx code to access all compat switches through here.
+/// </summary>
+[FriendAccessAllowed]
+internal class CLRConfig {
+
+ [FriendAccessAllowed]
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern bool CheckLegacyManagedDeflateStream();
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern bool CheckThrowUnobservedTaskExceptions();
+
+} // internal class CLRConfig
+
+} // namespace System
+
+// file CLRConfig
diff --git a/src/mscorlib/src/System/CLSCompliantAttribute.cs b/src/mscorlib/src/System/CLSCompliantAttribute.cs
new file mode 100644
index 0000000000..e902049558
--- /dev/null
+++ b/src/mscorlib/src/System/CLSCompliantAttribute.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Container for assemblies.
+**
+**
+=============================================================================*/
+
+namespace System {
+[Serializable]
+ [AttributeUsage (AttributeTargets.All, Inherited=true, AllowMultiple=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class CLSCompliantAttribute : Attribute
+ {
+ private bool m_compliant;
+
+ public CLSCompliantAttribute (bool isCompliant)
+ {
+ m_compliant = isCompliant;
+ }
+ public bool IsCompliant
+ {
+ get
+ {
+ return m_compliant;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/CannotUnloadAppDomainException.cs b/src/mscorlib/src/System/CannotUnloadAppDomainException.cs
new file mode 100644
index 0000000000..6b07eae5e2
--- /dev/null
+++ b/src/mscorlib/src/System/CannotUnloadAppDomainException.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for failed attempt to unload an AppDomain.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class CannotUnloadAppDomainException : SystemException {
+ public CannotUnloadAppDomainException()
+ : base(Environment.GetResourceString("Arg_CannotUnloadAppDomainException")) {
+ SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN);
+ }
+
+ public CannotUnloadAppDomainException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN);
+ }
+
+ public CannotUnloadAppDomainException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_CANNOTUNLOADAPPDOMAIN);
+ }
+
+ //
+ //This constructor is required for serialization.
+ //
+ protected CannotUnloadAppDomainException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/CfgParser.cs b/src/mscorlib/src/System/CfgParser.cs
new file mode 100644
index 0000000000..ef368a9020
--- /dev/null
+++ b/src/mscorlib/src/System/CfgParser.cs
@@ -0,0 +1,574 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+ **
+ **
+ **
+ ** Purpose: XMLParser and Tree builder internal to BCL
+ **
+ **
+ ===========================================================*/
+
+namespace System
+{
+ using System.Runtime.InteropServices;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Security;
+ using System.Globalization;
+ using System.IO;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal enum ConfigEvents
+ {
+ StartDocument = 0,
+ StartDTD = StartDocument + 1,
+ EndDTD = StartDTD + 1,
+ StartDTDSubset = EndDTD + 1,
+ EndDTDSubset = StartDTDSubset + 1,
+ EndProlog = EndDTDSubset + 1,
+ StartEntity = EndProlog + 1,
+ EndEntity = StartEntity + 1,
+ EndDocument = EndEntity + 1,
+ DataAvailable = EndDocument + 1,
+ LastEvent = DataAvailable
+ }
+
+ [Serializable]
+ internal enum ConfigNodeType
+ {
+ Element = 1,
+ Attribute = Element + 1,
+ Pi = Attribute + 1,
+ XmlDecl = Pi + 1,
+ DocType = XmlDecl + 1,
+ DTDAttribute = DocType + 1,
+ EntityDecl = DTDAttribute + 1,
+ ElementDecl = EntityDecl + 1,
+ AttlistDecl = ElementDecl + 1,
+ Notation = AttlistDecl + 1,
+ Group = Notation + 1,
+ IncludeSect = Group + 1,
+ PCData = IncludeSect + 1,
+ CData = PCData + 1,
+ IgnoreSect = CData + 1,
+ Comment = IgnoreSect + 1,
+ EntityRef = Comment + 1,
+ Whitespace = EntityRef + 1,
+ Name = Whitespace + 1,
+ NMToken = Name + 1,
+ String = NMToken + 1,
+ Peref = String + 1,
+ Model = Peref + 1,
+ ATTDef = Model + 1,
+ ATTType = ATTDef + 1,
+ ATTPresence = ATTType + 1,
+ DTDSubset = ATTPresence + 1,
+ LastNodeType = DTDSubset + 1
+ }
+
+ [Serializable]
+ internal enum ConfigNodeSubType
+ {
+ Version = (int)ConfigNodeType.LastNodeType,
+ Encoding = Version + 1,
+ Standalone = Encoding + 1,
+ NS = Standalone + 1,
+ XMLSpace = NS + 1,
+ XMLLang = XMLSpace + 1,
+ System = XMLLang + 1,
+ Public = System + 1,
+ NData = Public + 1,
+ AtCData = NData + 1,
+ AtId = AtCData + 1,
+ AtIdref = AtId + 1,
+ AtIdrefs = AtIdref + 1,
+ AtEntity = AtIdrefs + 1,
+ AtEntities = AtEntity + 1,
+ AtNmToken = AtEntities + 1,
+ AtNmTokens = AtNmToken + 1,
+ AtNotation = AtNmTokens + 1,
+ AtRequired = AtNotation + 1,
+ AtImplied = AtRequired + 1,
+ AtFixed = AtImplied + 1,
+ PentityDecl = AtFixed + 1,
+ Empty = PentityDecl + 1,
+ Any = Empty + 1,
+ Mixed = Any + 1,
+ Sequence = Mixed + 1,
+ Choice = Sequence + 1,
+ Star = Choice + 1,
+ Plus = Star + 1,
+ Questionmark = Plus + 1,
+ LastSubNodeType = Questionmark + 1
+ }
+
+ internal abstract class BaseConfigHandler
+ {
+ // These delegates must be at the very start of the object
+ // This is necessary because unmanaged code takes a dependency on this layout
+ // Any changes made to this must be reflected in ConfigHelper.h in ConfigFactory class
+ protected Delegate[] eventCallbacks;
+ public BaseConfigHandler()
+ {
+ InitializeCallbacks();
+ }
+ private void InitializeCallbacks()
+ {
+ if (eventCallbacks == null)
+ {
+ eventCallbacks = new Delegate[6];
+ eventCallbacks[0] = new NotifyEventCallback(this.NotifyEvent);
+ eventCallbacks[1] = new BeginChildrenCallback(this.BeginChildren);
+ eventCallbacks[2] = new EndChildrenCallback(this.EndChildren);
+ eventCallbacks[3] = new ErrorCallback(this.Error);
+ eventCallbacks[4] = new CreateNodeCallback(this.CreateNode);
+ eventCallbacks[5] = new CreateAttributeCallback(this.CreateAttribute);
+ }
+ }
+
+ private delegate void NotifyEventCallback(ConfigEvents nEvent);
+ public abstract void NotifyEvent(ConfigEvents nEvent);
+
+ private delegate void BeginChildrenCallback(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength);
+ public abstract void BeginChildren(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength);
+
+ private delegate void EndChildrenCallback(int fEmpty,
+ int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength);
+ public abstract void EndChildren(int fEmpty,
+ int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength);
+
+ private delegate void ErrorCallback(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+ public abstract void Error(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+
+ private delegate void CreateNodeCallback(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+ public abstract void CreateNode(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+
+ private delegate void CreateAttributeCallback(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+ public abstract void CreateAttribute(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void RunParser(String fileName);
+ }
+
+ // Class used to build a DOM like tree of parsed XML
+ internal class ConfigTreeParser : BaseConfigHandler
+ {
+ ConfigNode rootNode = null;
+ ConfigNode currentNode = null;
+ String fileName = null;
+ int attributeEntry;
+ String key = null;
+ String [] treeRootPath = null; // element to start tree
+ bool parsing = false;
+ int depth = 0;
+ int pathDepth = 0;
+ int searchDepth = 0;
+ bool bNoSearchPath = false;
+
+ // Track state for error message formatting
+ String lastProcessed = null;
+ bool lastProcessedEndElement;
+
+
+ // NOTE: This parser takes a path eg. /configuration/system.runtime.remoting
+ // and will return a node which matches this.
+ internal ConfigNode Parse(String fileName, String configPath)
+ {
+ return Parse(fileName, configPath, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal ConfigNode Parse(String fileName, String configPath, bool skipSecurityStuff)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ Contract.EndContractBlock();
+ this.fileName = fileName;
+ if (configPath[0] == '/'){
+ treeRootPath = configPath.Substring(1).Split('/');
+ pathDepth = treeRootPath.Length - 1;
+ bNoSearchPath = false;
+ }
+ else{
+ treeRootPath = new String[1];
+ treeRootPath[0] = configPath;
+ bNoSearchPath = true;
+ }
+
+ if (!skipSecurityStuff) {
+ (new FileIOPermission( FileIOPermissionAccess.Read, System.IO.Path.GetFullPathInternal( fileName ) )).Demand();
+ }
+#pragma warning disable 618
+ (new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Assert();
+#pragma warning restore 618
+
+ try
+ {
+ RunParser(fileName);
+ }
+ catch(FileNotFoundException) {
+ throw; // Pass these through unadulterated.
+ }
+ catch(DirectoryNotFoundException) {
+ throw; // Pass these through unadulterated.
+ }
+ catch(UnauthorizedAccessException) {
+ throw;
+ }
+ catch(FileLoadException) {
+ throw;
+ }
+ catch(Exception inner) {
+ String message = GetInvalidSyntaxMessage();
+ // Neither Exception nor ApplicationException are the "right" exceptions here.
+ // Desktop throws ApplicationException for backwards compatibility.
+ // On Silverlight we don't have ApplicationException, so fall back to Exception.
+#if FEATURE_CORECLR
+ throw new Exception(message, inner);
+#else
+ throw new ApplicationException(message, inner);
+#endif
+ }
+ return rootNode;
+ }
+
+ public override void NotifyEvent(ConfigEvents nEvent)
+ {
+ BCLDebug.Trace("REMOTE", "NotifyEvent "+((Enum)nEvent).ToString()+"\n");
+ }
+
+ public override void BeginChildren(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength)
+ {
+ //Trace("BeginChildren",size,subType,nType,terminal,text,textLength,prefixLength,0);
+ if (!parsing &&
+ (!bNoSearchPath
+ && depth == (searchDepth + 1)
+ && String.Compare(text, treeRootPath[searchDepth], StringComparison.Ordinal) == 0))
+ {
+ searchDepth++;
+ }
+ }
+
+ public override void EndChildren(int fEmpty,
+ int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)] String text,
+ int textLength,
+ int prefixLength)
+ {
+ lastProcessed = text;
+ lastProcessedEndElement = true;
+ if (parsing)
+ {
+ //Trace("EndChildren",size,subType,nType,terminal,text,textLength,prefixLength,fEmpty);
+
+ if (currentNode == rootNode)
+ {
+ // End of section of tree which is parsed
+ parsing = false;
+ }
+
+ currentNode = currentNode.Parent;
+ }
+ else if (nType == ConfigNodeType.Element){
+ if(depth == searchDepth && String.Compare(text, treeRootPath[searchDepth - 1], StringComparison.Ordinal) == 0)
+ {
+ searchDepth--;
+ depth--;
+ }
+ else
+ depth--;
+ }
+ }
+
+ public override void Error(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength)
+ {
+ //Trace("Error",size,subType,nType,terminal,text,textLength,prefixLength,0);
+ }
+
+ public override void CreateNode(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength)
+ {
+ //Trace("CreateNode",size,subType,nType,terminal,text,textLength,prefixLength,0);
+
+ if (nType == ConfigNodeType.Element)
+ {
+ // New Node
+ lastProcessed = text;
+ lastProcessedEndElement = false;
+
+ if (parsing
+ || (bNoSearchPath &&
+ String.Compare(text, treeRootPath[0], StringComparison.OrdinalIgnoreCase) == 0)
+ || (depth == searchDepth && searchDepth == pathDepth &&
+ String.Compare(text, treeRootPath[pathDepth], StringComparison.OrdinalIgnoreCase) == 0 ))
+ {
+ parsing = true;
+
+ ConfigNode parentNode = currentNode;
+ currentNode = new ConfigNode(text, parentNode);
+ if (rootNode == null)
+ rootNode = currentNode;
+ else
+ parentNode.AddChild(currentNode);
+ }
+ else
+ depth++;
+ }
+ else if (nType == ConfigNodeType.PCData)
+ {
+ // Data node
+ if (currentNode != null)
+ {
+ currentNode.Value = text;
+ }
+ }
+ }
+
+ public override void CreateAttribute(int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength)
+ {
+ //Trace("CreateAttribute",size,subType,nType,terminal,text,textLength,prefixLength,0);
+ if (parsing)
+ {
+ // if the value of the attribute is null, the parser doesn't come back, so need to store the attribute when the
+ // attribute name is encountered
+ if (nType == ConfigNodeType.Attribute)
+ {
+ attributeEntry = currentNode.AddAttribute(text, "");
+ key = text;
+ }
+ else if (nType == ConfigNodeType.PCData)
+ {
+ currentNode.ReplaceAttribute(attributeEntry, key, text);
+ }
+ else
+ {
+ String message = GetInvalidSyntaxMessage();
+ // Neither Exception nor ApplicationException are the "right" exceptions here.
+ // Desktop throws ApplicationException for backwards compatibility.
+ // On Silverlight we don't have ApplicationException, so fall back to Exception.
+#if FEATURE_CORECLR
+ throw new Exception(message);
+#else
+ throw new ApplicationException(message);
+#endif
+ }
+ }
+ }
+
+#if _DEBUG
+ [System.Diagnostics.Conditional("_LOGGING")]
+ private void Trace(String name,
+ int size,
+ ConfigNodeSubType subType,
+ ConfigNodeType nType,
+ int terminal,
+ [MarshalAs(UnmanagedType.LPWStr)]String text,
+ int textLength,
+ int prefixLength, int fEmpty)
+ {
+
+ BCLDebug.Trace("REMOTE","Node "+name);
+ BCLDebug.Trace("REMOTE","text "+text);
+ BCLDebug.Trace("REMOTE","textLength "+textLength);
+ BCLDebug.Trace("REMOTE","size "+size);
+ BCLDebug.Trace("REMOTE","subType "+((Enum)subType).ToString());
+ BCLDebug.Trace("REMOTE","nType "+((Enum)nType).ToString());
+ BCLDebug.Trace("REMOTE","terminal "+terminal);
+ BCLDebug.Trace("REMOTE","prefixLength "+prefixLength);
+ BCLDebug.Trace("REMOTE","fEmpty "+fEmpty+"\n");
+ }
+#endif
+
+ private String GetInvalidSyntaxMessage()
+ {
+ String lastProcessedTag = null;
+
+ if (lastProcessed != null)
+ lastProcessedTag = (lastProcessedEndElement ? "</" : "<") + lastProcessed + ">";
+
+ return Environment.GetResourceString("XML_Syntax_InvalidSyntaxInFile", fileName, lastProcessedTag);
+ }
+ }
+
+ // Node in Tree produced by ConfigTreeParser
+ internal class ConfigNode
+ {
+ String m_name = null;
+ String m_value = null;
+ ConfigNode m_parent = null;
+ List<ConfigNode> m_children = new List<ConfigNode>(5);
+ List<DictionaryEntry> m_attributes = new List<DictionaryEntry>(5);
+
+ internal ConfigNode(String name, ConfigNode parent)
+ {
+ m_name = name;
+ m_parent = parent;
+ }
+
+ internal String Name
+ {
+ get {return m_name;}
+ }
+
+ internal String Value
+ {
+ get {return m_value;}
+ set {m_value = value;}
+ }
+
+ internal ConfigNode Parent
+ {
+ get {return m_parent;}
+ }
+
+ internal List<ConfigNode> Children
+ {
+ get {return m_children;}
+ }
+
+ internal List<DictionaryEntry> Attributes
+ {
+ get {return m_attributes;}
+ }
+
+ internal void AddChild(ConfigNode child)
+ {
+ child.m_parent = this;
+ m_children.Add(child);
+ }
+
+ internal int AddAttribute(String key, String value)
+ {
+ m_attributes.Add(new DictionaryEntry(key, value));
+ return m_attributes.Count-1;
+ }
+
+ internal void ReplaceAttribute(int index, String key, String value)
+ {
+ m_attributes[index] = new DictionaryEntry(key, value);
+ }
+
+#if _DEBUG
+ [System.Diagnostics.Conditional("_LOGGING")]
+ internal void Trace()
+ {
+ BCLDebug.Trace("REMOTE","************ConfigNode************");
+ BCLDebug.Trace("REMOTE","Name = "+m_name);
+ if (m_value != null)
+ BCLDebug.Trace("REMOTE","Value = "+m_value);
+ if (m_parent != null)
+ BCLDebug.Trace("REMOTE","Parent = "+m_parent.Name);
+ for (int i=0; i<m_attributes.Count; i++)
+ {
+ DictionaryEntry de = (DictionaryEntry)m_attributes[i];
+ BCLDebug.Trace("REMOTE","Key = "+de.Key+" Value = "+de.Value);
+ }
+
+ for (int i=0; i<m_children.Count; i++)
+ {
+ ((ConfigNode)m_children[i]).Trace();
+ }
+ }
+#endif
+ }
+}
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Char.cs b/src/mscorlib/src/System/Char.cs
new file mode 100644
index 0000000000..ff936c6618
--- /dev/null
+++ b/src/mscorlib/src/System/Char.cs
@@ -0,0 +1,1001 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This is the value class representing a Unicode character
+** Char methods until we create this functionality.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] public struct Char : IComparable, IConvertible
+ , IComparable<Char>, IEquatable<Char>
+ {
+ //
+ // Member Variables
+ //
+ internal char m_value;
+
+ //
+ // Public Constants
+ //
+ // The maximum character value.
+ public const char MaxValue = (char) 0xFFFF;
+ // The minimum character value.
+ public const char MinValue = (char) 0x00;
+
+ // Unicode category values from Unicode U+0000 ~ U+00FF. Store them in byte[] array to save space.
+ private readonly static byte[] categoryForLatin1 = {
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0000 - 0007
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0008 - 000F
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0010 - 0017
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0018 - 001F
+ (byte)UnicodeCategory.SpaceSeparator, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, // 0020 - 0027
+ (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.DashPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, // 0028 - 002F
+ (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, // 0030 - 0037
+ (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.DecimalDigitNumber, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherPunctuation, // 0038 - 003F
+ (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, // 0040 - 0047
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, // 0048 - 004F
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, // 0050 - 0057
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.ConnectorPunctuation, // 0058 - 005F
+ (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 0060 - 0067
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 0068 - 006F
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 0070 - 0077
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.OpenPunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.ClosePunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.Control, // 0078 - 007F
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0080 - 0087
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0088 - 008F
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0090 - 0097
+ (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, (byte)UnicodeCategory.Control, // 0098 - 009F
+ (byte)UnicodeCategory.SpaceSeparator, (byte)UnicodeCategory.OtherPunctuation, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.CurrencySymbol, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.OtherSymbol, // 00A0 - 00A7
+ (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.InitialQuotePunctuation, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.DashPunctuation, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.ModifierSymbol, // 00A8 - 00AF
+ (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.MathSymbol, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.OtherSymbol, (byte)UnicodeCategory.OtherPunctuation, // 00B0 - 00B7
+ (byte)UnicodeCategory.ModifierSymbol, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.FinalQuotePunctuation, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherNumber, (byte)UnicodeCategory.OtherPunctuation, // 00B8 - 00BF
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, // 00C0 - 00C7
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, // 00C8 - 00CF
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.MathSymbol, // 00D0 - 00D7
+ (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.UppercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 00D8 - 00DF
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 00E0 - 00E7
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 00E8 - 00EF
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.MathSymbol, // 00F0 - 00F7
+ (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, (byte)UnicodeCategory.LowercaseLetter, // 00F8 - 00FF
+ };
+
+ // Return true for all characters below or equal U+00ff, which is ASCII + Latin-1 Supplement.
+ private static bool IsLatin1(char ch) {
+ return (ch <= '\x00ff');
+ }
+
+ // Return true for all characters below or equal U+007f, which is ASCII.
+ private static bool IsAscii(char ch) {
+ return (ch <= '\x007f');
+ }
+
+ // Return the Unicode category for Unicode character <= 0x00ff.
+ private static UnicodeCategory GetLatin1UnicodeCategory(char ch) {
+ Contract.Assert(IsLatin1(ch), "Char.GetLatin1UnicodeCategory(): ch should be <= 007f");
+ return (UnicodeCategory)(categoryForLatin1[(int)ch]);
+ }
+
+ //
+ // Private Constants
+ //
+
+ //
+ // Overriden Instance Methods
+ //
+
+ // Calculate a hashcode for a 2 byte Unicode character.
+ public override int GetHashCode() {
+ return (int)m_value | ((int)m_value << 16);
+ }
+
+ // Used for comparing two boxed Char objects.
+ //
+ public override bool Equals(Object obj) {
+ if (!(obj is Char)) {
+ return false;
+ }
+ return (m_value==((Char)obj).m_value);
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Char obj)
+ {
+ return m_value == obj;
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Char, this method throws an ArgumentException.
+ //
+ [Pure]
+ public int CompareTo(Object value) {
+ if (value==null) {
+ return 1;
+ }
+ if (!(value is Char)) {
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeChar"));
+ }
+
+ return (m_value-((Char)value).m_value);
+ }
+
+ [Pure]
+ public int CompareTo(Char value) {
+ return (m_value-value);
+ }
+
+ // Overrides System.Object.ToString.
+ [Pure]
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Char.ToString(m_value);
+ }
+
+ [Pure]
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Char.ToString(m_value);
+ }
+
+ //
+ // Formatting Methods
+ //
+
+ /*===================================ToString===================================
+ **This static methods takes a character and returns the String representation of it.
+ ==============================================================================*/
+ // Provides a string representation of a character.
+ [Pure]
+ public static string ToString(char c) => string.CreateFromChar(c);
+
+ public static char Parse(String s) {
+ if (s==null) {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ if (s.Length!=1) {
+ throw new FormatException(Environment.GetResourceString("Format_NeedSingleChar"));
+ }
+ return s[0];
+ }
+
+ public static bool TryParse(String s, out Char result) {
+ result = '\0';
+ if (s == null) {
+ return false;
+ }
+ if (s.Length != 1) {
+ return false;
+ }
+ result = s[0];
+ return true;
+ }
+
+ //
+ // Static Methods
+ //
+ /*=================================ISDIGIT======================================
+ **A wrapper for Char. Returns a boolean indicating whether **
+ **character c is considered to be a digit. **
+ ==============================================================================*/
+ // Determines whether a character is a digit.
+ [Pure]
+ public static bool IsDigit(char c) {
+ if (IsLatin1(c)) {
+ return (c >= '0' && c <= '9');
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.DecimalDigitNumber);
+ }
+
+
+ /*=================================CheckLetter=====================================
+ ** Check if the specified UnicodeCategory belongs to the letter categories.
+ ==============================================================================*/
+ internal static bool CheckLetter(UnicodeCategory uc) {
+ switch(uc) {
+ case (UnicodeCategory.UppercaseLetter):
+ case (UnicodeCategory.LowercaseLetter):
+ case (UnicodeCategory.TitlecaseLetter):
+ case (UnicodeCategory.ModifierLetter):
+ case (UnicodeCategory.OtherLetter):
+ return (true);
+ }
+ return (false);
+ }
+
+ /*=================================ISLETTER=====================================
+ **A wrapper for Char. Returns a boolean indicating whether **
+ **character c is considered to be a letter. **
+ ==============================================================================*/
+ // Determines whether a character is a letter.
+ [Pure]
+ public static bool IsLetter(char c) {
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ c |=(char)0x20;
+ return ((c >= 'a' && c <= 'z'));
+ }
+ return (CheckLetter(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ private static bool IsWhiteSpaceLatin1(char c) {
+
+ // There are characters which belong to UnicodeCategory.Control but are considered as white spaces.
+ // We use code point comparisons for these characters here as a temporary fix.
+
+ // U+0009 = <control> HORIZONTAL TAB
+ // U+000a = <control> LINE FEED
+ // U+000b = <control> VERTICAL TAB
+ // U+000c = <contorl> FORM FEED
+ // U+000d = <control> CARRIAGE RETURN
+ // U+0085 = <control> NEXT LINE
+ // U+00a0 = NO-BREAK SPACE
+ if ((c == ' ') || (c >= '\x0009' && c <= '\x000d') || c == '\x00a0' || c == '\x0085') {
+ return (true);
+ }
+ return (false);
+ }
+
+ /*===============================ISWHITESPACE===================================
+ **A wrapper for Char. Returns a boolean indicating whether **
+ **character c is considered to be a whitespace character. **
+ ==============================================================================*/
+ // Determines whether a character is whitespace.
+ [Pure]
+ public static bool IsWhiteSpace(char c) {
+
+ if (IsLatin1(c)) {
+ return (IsWhiteSpaceLatin1(c));
+ }
+ return CharUnicodeInfo.IsWhiteSpace(c);
+ }
+
+
+ /*===================================IsUpper====================================
+ **Arguments: c -- the characater to be checked.
+ **Returns: True if c is an uppercase character.
+ ==============================================================================*/
+ // Determines whether a character is upper-case.
+ [Pure]
+ public static bool IsUpper(char c) {
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= 'A' && c <= 'Z');
+ }
+ return (GetLatin1UnicodeCategory(c)== UnicodeCategory.UppercaseLetter);
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.UppercaseLetter);
+ }
+
+ /*===================================IsLower====================================
+ **Arguments: c -- the characater to be checked.
+ **Returns: True if c is an lowercase character.
+ ==============================================================================*/
+ // Determines whether a character is lower-case.
+ [Pure]
+ public static bool IsLower(char c) {
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= 'a' && c <= 'z');
+ }
+ return (GetLatin1UnicodeCategory(c)== UnicodeCategory.LowercaseLetter);
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.LowercaseLetter);
+ }
+
+ internal static bool CheckPunctuation(UnicodeCategory uc)
+ {
+ switch (uc) {
+ case UnicodeCategory.ConnectorPunctuation:
+ case UnicodeCategory.DashPunctuation:
+ case UnicodeCategory.OpenPunctuation:
+ case UnicodeCategory.ClosePunctuation:
+ case UnicodeCategory.InitialQuotePunctuation:
+ case UnicodeCategory.FinalQuotePunctuation:
+ case UnicodeCategory.OtherPunctuation:
+ return (true);
+ }
+ return (false);
+ }
+
+
+ /*================================IsPunctuation=================================
+ **Arguments: c -- the characater to be checked.
+ **Returns: True if c is an punctuation mark
+ ==============================================================================*/
+ // Determines whether a character is a punctuation mark.
+ [Pure]
+ public static bool IsPunctuation(char c){
+ if (IsLatin1(c)) {
+ return (CheckPunctuation(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckPunctuation(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ /*=================================CheckLetterOrDigit=====================================
+ ** Check if the specified UnicodeCategory belongs to the letter or digit categories.
+ ==============================================================================*/
+ internal static bool CheckLetterOrDigit(UnicodeCategory uc) {
+ switch (uc) {
+ case UnicodeCategory.UppercaseLetter:
+ case UnicodeCategory.LowercaseLetter:
+ case UnicodeCategory.TitlecaseLetter:
+ case UnicodeCategory.ModifierLetter:
+ case UnicodeCategory.OtherLetter:
+ case UnicodeCategory.DecimalDigitNumber:
+ return (true);
+ }
+ return (false);
+ }
+
+ // Determines whether a character is a letter or a digit.
+ [Pure]
+ public static bool IsLetterOrDigit(char c) {
+ if (IsLatin1(c)) {
+ return (CheckLetterOrDigit(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ /*===================================ToUpper====================================
+ **
+ ==============================================================================*/
+ // Converts a character to upper-case for the specified culture.
+ // <;<;Not fully implemented>;>;
+ public static char ToUpper(char c, CultureInfo culture) {
+ if (culture==null)
+ throw new ArgumentNullException("culture");
+ Contract.EndContractBlock();
+ return culture.TextInfo.ToUpper(c);
+ }
+
+ /*=================================TOUPPER======================================
+ **A wrapper for Char.toUpperCase. Converts character c to its **
+ **uppercase equivalent. If c is already an uppercase character or is not an **
+ **alphabetic, nothing happens. **
+ ==============================================================================*/
+ // Converts a character to upper-case for the default culture.
+ //
+ public static char ToUpper(char c) {
+ return ToUpper(c, CultureInfo.CurrentCulture);
+ }
+
+
+ // Converts a character to upper-case for invariant culture.
+ public static char ToUpperInvariant(char c) {
+ return ToUpper(c, CultureInfo.InvariantCulture);
+ }
+
+ /*===================================ToLower====================================
+ **
+ ==============================================================================*/
+ // Converts a character to lower-case for the specified culture.
+ // <;<;Not fully implemented>;>;
+ public static char ToLower(char c, CultureInfo culture) {
+ if (culture==null)
+ throw new ArgumentNullException("culture");
+ Contract.EndContractBlock();
+ return culture.TextInfo.ToLower(c);
+ }
+
+ /*=================================TOLOWER======================================
+ **A wrapper for Char.toLowerCase. Converts character c to its **
+ **lowercase equivalent. If c is already a lowercase character or is not an **
+ **alphabetic, nothing happens. **
+ ==============================================================================*/
+ // Converts a character to lower-case for the default culture.
+ public static char ToLower(char c) {
+ return ToLower(c, CultureInfo.CurrentCulture);
+ }
+
+
+ // Converts a character to lower-case for invariant culture.
+ public static char ToLowerInvariant(char c) {
+ return ToLower(c, CultureInfo.InvariantCulture);
+ }
+
+ //
+ // IConvertible implementation
+ //
+ [Pure]
+ public TypeCode GetTypeCode() {
+ return TypeCode.Char;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Char", "Boolean"));
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Char", "Single"));
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Char", "Double"));
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Char", "Decimal"));
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Char", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+
+ public static bool IsControl(char c)
+ {
+ if (IsLatin1(c)) {
+ return (GetLatin1UnicodeCategory(c) == UnicodeCategory.Control);
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(c) == UnicodeCategory.Control);
+ }
+
+ public static bool IsControl(String s, int index) {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ return (GetLatin1UnicodeCategory(c) == UnicodeCategory.Control);
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.Control);
+ }
+
+
+ public static bool IsDigit(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ return (c >= '0' && c <= '9');
+ }
+ return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.DecimalDigitNumber);
+ }
+
+ public static bool IsLetter(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ c |=(char)0x20;
+ return ((c >= 'a' && c <= 'z'));
+ }
+ return (CheckLetter(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckLetter(CharUnicodeInfo.GetUnicodeCategory(s, index)));
+ }
+
+ public static bool IsLetterOrDigit(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ return CheckLetterOrDigit(GetLatin1UnicodeCategory(c));
+ }
+ return CheckLetterOrDigit(CharUnicodeInfo.GetUnicodeCategory(s, index));
+ }
+
+ public static bool IsLower(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= 'a' && c <= 'z');
+ }
+ return (GetLatin1UnicodeCategory(c)== UnicodeCategory.LowercaseLetter);
+ }
+
+ return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.LowercaseLetter);
+ }
+
+ /*=================================CheckNumber=====================================
+ ** Check if the specified UnicodeCategory belongs to the number categories.
+ ==============================================================================*/
+
+ internal static bool CheckNumber(UnicodeCategory uc) {
+ switch (uc) {
+ case (UnicodeCategory.DecimalDigitNumber):
+ case (UnicodeCategory.LetterNumber):
+ case (UnicodeCategory.OtherNumber):
+ return (true);
+ }
+ return (false);
+ }
+
+ public static bool IsNumber(char c)
+ {
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= '0' && c <= '9');
+ }
+ return (CheckNumber(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ public static bool IsNumber(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= '0' && c <= '9');
+ }
+ return (CheckNumber(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckNumber(CharUnicodeInfo.GetUnicodeCategory(s, index)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsPunctuation
+ //
+ // Determines if the given character is a punctuation character.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public static bool IsPunctuation (String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ return (CheckPunctuation(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckPunctuation(CharUnicodeInfo.GetUnicodeCategory(s, index)));
+ }
+
+
+ /*================================= CheckSeparator ============================
+ ** Check if the specified UnicodeCategory belongs to the seprator categories.
+ ==============================================================================*/
+
+ internal static bool CheckSeparator(UnicodeCategory uc)
+ {
+ switch (uc) {
+ case UnicodeCategory.SpaceSeparator:
+ case UnicodeCategory.LineSeparator:
+ case UnicodeCategory.ParagraphSeparator:
+ return (true);
+ }
+ return (false);
+ }
+
+ private static bool IsSeparatorLatin1(char c) {
+ // U+00a0 = NO-BREAK SPACE
+ // There is no LineSeparator or ParagraphSeparator in Latin 1 range.
+ return (c == '\x0020' || c == '\x00a0');
+ }
+
+ public static bool IsSeparator(char c)
+ {
+ if (IsLatin1(c)) {
+ return (IsSeparatorLatin1(c));
+ }
+ return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ public static bool IsSeparator(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ return (IsSeparatorLatin1(c));
+ }
+ return (CheckSeparator(CharUnicodeInfo.GetUnicodeCategory(s, index)));
+ }
+
+ [Pure]
+ public static bool IsSurrogate(char c)
+ {
+ return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END);
+ }
+
+ [Pure]
+ public static bool IsSurrogate(String s, int index)
+ {
+ if (s==null) {
+ throw new ArgumentNullException("s");
+ }
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return (IsSurrogate(s[index]));
+ }
+
+ /*================================= CheckSymbol ============================
+ ** Check if the specified UnicodeCategory belongs to the symbol categories.
+ ==============================================================================*/
+
+ internal static bool CheckSymbol(UnicodeCategory uc) {
+ switch (uc) {
+ case (UnicodeCategory.MathSymbol):
+ case (UnicodeCategory.CurrencySymbol):
+ case (UnicodeCategory.ModifierSymbol):
+ case (UnicodeCategory.OtherSymbol):
+ return (true);
+ }
+ return (false);
+ }
+
+ public static bool IsSymbol(char c)
+ {
+ if (IsLatin1(c)) {
+ return (CheckSymbol(GetLatin1UnicodeCategory(c)));
+ }
+ return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(c)));
+ }
+
+ public static bool IsSymbol(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ if (IsLatin1(s[index])) {
+ return (CheckSymbol(GetLatin1UnicodeCategory(s[index])));
+ }
+ return (CheckSymbol(CharUnicodeInfo.GetUnicodeCategory(s, index)));
+ }
+
+
+ public static bool IsUpper(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ char c = s[index];
+ if (IsLatin1(c)) {
+ if (IsAscii(c)) {
+ return (c >= 'A' && c <= 'Z');
+ }
+ return (GetLatin1UnicodeCategory(c)== UnicodeCategory.UppercaseLetter);
+ }
+
+ return (CharUnicodeInfo.GetUnicodeCategory(s, index) == UnicodeCategory.UppercaseLetter);
+ }
+
+ public static bool IsWhiteSpace(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+
+ if (IsLatin1(s[index])) {
+ return IsWhiteSpaceLatin1(s[index]);
+ }
+
+ return CharUnicodeInfo.IsWhiteSpace(s, index);
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(char c)
+ {
+ if (IsLatin1(c)) {
+ return (GetLatin1UnicodeCategory(c));
+ }
+ return CharUnicodeInfo.InternalGetUnicodeCategory(c);
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ if (IsLatin1(s[index])) {
+ return (GetLatin1UnicodeCategory(s[index]));
+ }
+ return CharUnicodeInfo.InternalGetUnicodeCategory(s, index);
+ }
+
+ public static double GetNumericValue(char c)
+ {
+ return CharUnicodeInfo.GetNumericValue(c);
+ }
+
+ public static double GetNumericValue(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return CharUnicodeInfo.GetNumericValue(s, index);
+ }
+
+
+ /*================================= IsHighSurrogate ============================
+ ** Check if a char is a high surrogate.
+ ==============================================================================*/
+ [Pure]
+ public static bool IsHighSurrogate(char c) {
+ return ((c >= CharUnicodeInfo.HIGH_SURROGATE_START) && (c <= CharUnicodeInfo.HIGH_SURROGATE_END));
+ }
+
+ [Pure]
+ public static bool IsHighSurrogate(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return (IsHighSurrogate(s[index]));
+ }
+
+ /*================================= IsLowSurrogate ============================
+ ** Check if a char is a low surrogate.
+ ==============================================================================*/
+ [Pure]
+ public static bool IsLowSurrogate(char c) {
+ return ((c >= CharUnicodeInfo.LOW_SURROGATE_START) && (c <= CharUnicodeInfo.LOW_SURROGATE_END));
+ }
+
+ [Pure]
+ public static bool IsLowSurrogate(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return (IsLowSurrogate(s[index]));
+ }
+
+ /*================================= IsSurrogatePair ============================
+ ** Check if the string specified by the index starts with a surrogate pair.
+ ==============================================================================*/
+ [Pure]
+ public static bool IsSurrogatePair(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ if (index + 1 < s.Length) {
+ return (IsSurrogatePair(s[index], s[index+1]));
+ }
+ return (false);
+ }
+
+ [Pure]
+ public static bool IsSurrogatePair(char highSurrogate, char lowSurrogate) {
+ return ((highSurrogate >= CharUnicodeInfo.HIGH_SURROGATE_START && highSurrogate <= CharUnicodeInfo.HIGH_SURROGATE_END) &&
+ (lowSurrogate >= CharUnicodeInfo.LOW_SURROGATE_START && lowSurrogate <= CharUnicodeInfo.LOW_SURROGATE_END));
+ }
+
+ internal const int UNICODE_PLANE00_END = 0x00ffff;
+ // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
+ internal const int UNICODE_PLANE01_START = 0x10000;
+ // The end codepoint for Unicode plane 16. This is the maximum code point value allowed for Unicode.
+ // Plane 16 contains 0x100000 ~ 0x10ffff.
+ internal const int UNICODE_PLANE16_END = 0x10ffff;
+
+ internal const int HIGH_SURROGATE_START = 0x00d800;
+ internal const int LOW_SURROGATE_END = 0x00dfff;
+
+
+
+ /*================================= ConvertFromUtf32 ============================
+ ** Convert an UTF32 value into a surrogate pair.
+ ==============================================================================*/
+
+ [System.Security.SecuritySafeCritical]
+ public static String ConvertFromUtf32(int utf32)
+ {
+ // For UTF32 values from U+00D800 ~ U+00DFFF, we should throw. They
+ // are considered as irregular code unit sequence, but they are not illegal.
+ if ((utf32 < 0 || utf32 > UNICODE_PLANE16_END) || (utf32 >= HIGH_SURROGATE_START && utf32 <= LOW_SURROGATE_END)) {
+ throw new ArgumentOutOfRangeException("utf32", Environment.GetResourceString("ArgumentOutOfRange_InvalidUTF32"));
+ }
+ Contract.EndContractBlock();
+
+ if (utf32 < UNICODE_PLANE01_START) {
+ // This is a BMP character.
+ return (Char.ToString((char)utf32));
+ }
+
+ unsafe
+ {
+ // This is a supplementary character. Convert it to a surrogate pair in UTF-16.
+ utf32 -= UNICODE_PLANE01_START;
+ uint surrogate = 0; // allocate 2 chars worth of stack space
+ char* address = (char*)&surrogate;
+ address[0] = (char)((utf32 / 0x400) + (int)CharUnicodeInfo.HIGH_SURROGATE_START);
+ address[1] = (char)((utf32 % 0x400) + (int)CharUnicodeInfo.LOW_SURROGATE_START);
+ return new string(address, 0, 2);
+ }
+ }
+
+
+ /*=============================ConvertToUtf32===================================
+ ** Convert a surrogate pair to UTF32 value
+ ==============================================================================*/
+
+ public static int ConvertToUtf32(char highSurrogate, char lowSurrogate) {
+ if (!IsHighSurrogate(highSurrogate)) {
+ throw new ArgumentOutOfRangeException("highSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidHighSurrogate"));
+ }
+ if (!IsLowSurrogate(lowSurrogate)) {
+ throw new ArgumentOutOfRangeException("lowSurrogate", Environment.GetResourceString("ArgumentOutOfRange_InvalidLowSurrogate"));
+ }
+ Contract.EndContractBlock();
+ return (((highSurrogate - CharUnicodeInfo.HIGH_SURROGATE_START) * 0x400) + (lowSurrogate - CharUnicodeInfo.LOW_SURROGATE_START) + UNICODE_PLANE01_START);
+ }
+
+ /*=============================ConvertToUtf32===================================
+ ** Convert a character or a surrogate pair starting at index of the specified string
+ ** to UTF32 value.
+ ** The char pointed by index should be a surrogate pair or a BMP character.
+ ** This method throws if a high-surrogate is not followed by a low surrogate.
+ ** This method throws if a low surrogate is seen without preceding a high-surrogate.
+ ==============================================================================*/
+
+ public static int ConvertToUtf32(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+ // Check if the character at index is a high surrogate.
+ int temp1 = (int)s[index] - CharUnicodeInfo.HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= 0x7ff) {
+ // Found a surrogate char.
+ if (temp1 <= 0x3ff) {
+ // Found a high surrogate.
+ if (index < s.Length - 1) {
+ int temp2 = (int)s[index+1] - CharUnicodeInfo.LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= 0x3ff) {
+ // Found a low surrogate.
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ } else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s");
+ }
+ } else {
+ // Found a high surrogate at the end of the string.
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHighSurrogate", index), "s");
+ }
+ } else {
+ // Find a low surrogate at the character pointed by index.
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidLowSurrogate", index), "s");
+ }
+ }
+ // Not a high-surrogate or low-surrogate. Genereate the UTF32 value for the BMP characters.
+ return ((int)s[index]);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/CharEnumerator.cs b/src/mscorlib/src/System/CharEnumerator.cs
new file mode 100644
index 0000000000..d25294c7e2
--- /dev/null
+++ b/src/mscorlib/src/System/CharEnumerator.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Enumerates the characters on a string. skips range
+** checks.
+**
+**
+============================================================*/
+namespace System {
+
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class CharEnumerator : IEnumerator, ICloneable, IEnumerator<char>, IDisposable {
+ private String str;
+ private int index;
+ private char currentElement;
+
+ internal CharEnumerator(String str) {
+ Contract.Requires(str != null);
+ this.str = str;
+ this.index = -1;
+ }
+
+ public Object Clone() {
+ return MemberwiseClone();
+ }
+
+ public bool MoveNext() {
+ if (index < (str.Length-1)) {
+ index++;
+ currentElement = str[index];
+ return true;
+ }
+ else
+ index = str.Length;
+ return false;
+
+ }
+
+ public void Dispose() {
+ if (str != null)
+ index = str.Length;
+ str = null;
+ }
+
+ /// <internalonly/>
+ Object IEnumerator.Current {
+ get { return Current; }
+ }
+
+ public char Current {
+ get {
+ if (index == -1)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (index >= str.Length)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ return currentElement;
+ }
+ }
+
+ public void Reset() {
+ currentElement = (char)0;
+ index = -1;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ArrayList.cs b/src/mscorlib/src/System/Collections/ArrayList.cs
new file mode 100644
index 0000000000..94f4dc74e8
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ArrayList.cs
@@ -0,0 +1,2635 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Implements a dynamically sized List as an array,
+** and provides many convenience methods for treating
+** an array as an IList.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Runtime;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ // Implements a variable-size List that uses an array of objects to store the
+ // elements. A ArrayList has a capacity, which is the allocated length
+ // of the internal array. As elements are added to a ArrayList, the capacity
+ // of the ArrayList is automatically increased as required by reallocating the
+ // internal array.
+ //
+#if FEATURE_CORECLR
+ [FriendAccessAllowed]
+#endif
+ [DebuggerTypeProxy(typeof(System.Collections.ArrayList.ArrayListDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ArrayList : IList, ICloneable
+ {
+ private Object[] _items;
+ [ContractPublicPropertyName("Count")]
+ private int _size;
+ private int _version;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ private const int _defaultCapacity = 4;
+ private static readonly Object[] emptyArray = EmptyArray<Object>.Value;
+
+ // Note: this constructor is a bogus constructor that does nothing
+ // and is for use only with SyncArrayList.
+ internal ArrayList( bool trash )
+ {
+ }
+
+ // Constructs a ArrayList. The list is initially empty and has a capacity
+ // of zero. Upon adding the first element to the list the capacity is
+ // increased to _defaultCapacity, and then increased in multiples of two as required.
+ public ArrayList() {
+ _items = emptyArray;
+ }
+
+ // Constructs a ArrayList with a given initial capacity. The list is
+ // initially empty, but will have room for the given number of elements
+ // before any reallocations are required.
+ //
+ public ArrayList(int capacity) {
+ if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "capacity"));
+ Contract.EndContractBlock();
+
+ if (capacity == 0)
+ _items = emptyArray;
+ else
+ _items = new Object[capacity];
+ }
+
+ // Constructs a ArrayList, copying the contents of the given collection. The
+ // size and capacity of the new list will both be equal to the size of the
+ // given collection.
+ //
+ public ArrayList(ICollection c) {
+ if (c==null)
+ throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection"));
+ Contract.EndContractBlock();
+
+ int count = c.Count;
+ if (count == 0)
+ {
+ _items = emptyArray;
+ }
+ else {
+ _items = new Object[count];
+ AddRange(c);
+ }
+ }
+
+ // Gets and sets the capacity of this list. The capacity is the size of
+ // the internal array used to hold items. When set, the internal
+ // array of the list is reallocated to the given capacity.
+ //
+ public virtual int Capacity {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= Count);
+ return _items.Length;
+ }
+ set {
+ if (value < _size) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ }
+ Contract.Ensures(Capacity >= 0);
+ Contract.EndContractBlock();
+ // We don't want to update the version number when we change the capacity.
+ // Some existing applications have dependency on this.
+ if (value != _items.Length) {
+ if (value > 0) {
+ Object[] newItems = new Object[value];
+ if (_size > 0) {
+ Array.Copy(_items, 0, newItems, 0, _size);
+ }
+ _items = newItems;
+ }
+ else {
+ _items = new Object[_defaultCapacity];
+ }
+ }
+ }
+ }
+
+ // Read-only property describing how many elements are in the List.
+ public virtual int Count {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return _size;
+ }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return false; }
+ }
+
+
+ // Is this ArrayList read-only?
+ public virtual bool IsReadOnly {
+ get { return false; }
+ }
+
+ // Is this ArrayList synchronized (thread-safe)?
+ public virtual bool IsSynchronized {
+ get { return false; }
+ }
+
+ // Synchronization root for this object.
+ public virtual Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Sets or Gets the element at the given index.
+ //
+ public virtual Object this[int index] {
+ get {
+ if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return _items[index];
+ }
+ set {
+ if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ _items[index] = value;
+ _version++;
+ }
+ }
+
+ // Creates a ArrayList wrapper for a particular IList. This does not
+ // copy the contents of the IList, but only wraps the ILIst. So any
+ // changes to the underlying list will affect the ArrayList. This would
+ // be useful if you want to Reverse a subrange of an IList, or want to
+ // use a generic BinarySearch or Sort method without implementing one yourself.
+ // However, since these methods are generic, the performance may not be
+ // nearly as good for some operations as they would be on the IList itself.
+ //
+ public static ArrayList Adapter(IList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+ return new IListWrapper(list);
+ }
+
+ // Adds the given object to the end of this list. The size of the list is
+ // increased by one. If required, the capacity of the list is doubled
+ // before adding the new element.
+ //
+ public virtual int Add(Object value) {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ if (_size == _items.Length) EnsureCapacity(_size + 1);
+ _items[_size] = value;
+ _version++;
+ return _size++;
+ }
+
+ // Adds the elements of the given collection to the end of this list. If
+ // required, the capacity of the list is increased to twice the previous
+ // capacity or the new size, whichever is larger.
+ //
+ public virtual void AddRange(ICollection c) {
+ InsertRange(_size, c);
+ }
+
+ // Searches a section of the list for a given element using a binary search
+ // algorithm. Elements of the list are compared to the search value using
+ // the given IComparer interface. If comparer is null, elements of
+ // the list are compared to the search value using the IComparable
+ // interface, which in that case must be implemented by all elements of the
+ // list and the given search value. This method assumes that the given
+ // section of the list is already sorted; if this is not the case, the
+ // result will be incorrect.
+ //
+ // The method returns the index of the given value in the list. If the
+ // list does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value. This is also the index at which
+ // the search value should be inserted into the list in order for the list
+ // to remain sorted.
+ //
+ // The method uses the Array.BinarySearch method to perform the
+ // search.
+ //
+ public virtual int BinarySearch(int index, int count, Object value, IComparer comparer) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.Ensures(Contract.Result<int>() < index + count);
+ Contract.EndContractBlock();
+
+ return Array.BinarySearch((Array)_items, index, count, value, comparer);
+ }
+
+ public virtual int BinarySearch(Object value)
+ {
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return BinarySearch(0, Count, value, null);
+ }
+
+ public virtual int BinarySearch(Object value, IComparer comparer)
+ {
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return BinarySearch(0, Count, value, comparer);
+ }
+
+
+ // Clears the contents of ArrayList.
+ public virtual void Clear() {
+ if (_size > 0)
+ {
+ Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ _size = 0;
+ }
+ _version++;
+ }
+
+ // Clones this ArrayList, doing a shallow copy. (A copy is made of all
+ // Object references in the ArrayList, but the Objects pointed to
+ // are not cloned).
+ public virtual Object Clone()
+ {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ ArrayList la = new ArrayList(_size);
+ la._size = _size;
+ la._version = _version;
+ Array.Copy(_items, 0, la._items, 0, _size);
+ return la;
+ }
+
+
+ // Contains returns true if the specified element is in the ArrayList.
+ // It does a linear, O(n) search. Equality is determined by calling
+ // item.Equals().
+ //
+ public virtual bool Contains(Object item) {
+ if (item==null) {
+ for(int i=0; i<_size; i++)
+ if (_items[i]==null)
+ return true;
+ return false;
+ }
+ else {
+ for(int i=0; i<_size; i++)
+ if ( (_items[i] != null) && (_items[i].Equals(item)) )
+ return true;
+ return false;
+ }
+ }
+
+ // Copies this ArrayList into array, which must be of a
+ // compatible array type.
+ //
+ public virtual void CopyTo(Array array) {
+ CopyTo(array, 0);
+ }
+
+ // Copies this ArrayList into array, which must be of a
+ // compatible array type.
+ //
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if ((array != null) && (array.Rank != 1))
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+ // Delegate rest of error checking to Array.Copy.
+ Array.Copy(_items, 0, array, arrayIndex, _size);
+ }
+
+ // Copies a section of this list to the given array at the given index.
+ //
+ // The method uses the Array.Copy method to copy the elements.
+ //
+ public virtual void CopyTo(int index, Array array, int arrayIndex, int count) {
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ if ((array != null) && (array.Rank != 1))
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+ // Delegate rest of error checking to Array.Copy.
+ Array.Copy(_items, index, array, arrayIndex, count);
+ }
+
+ // Ensures that the capacity of this list is at least the given minimum
+ // value. If the currect capacity of the list is less than min, the
+ // capacity is increased to twice the current capacity or to min,
+ // whichever is larger.
+ private void EnsureCapacity(int min) {
+ if (_items.Length < min) {
+ int newCapacity = _items.Length == 0? _defaultCapacity: _items.Length * 2;
+ // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
+ // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+ if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
+ if (newCapacity < min) newCapacity = min;
+ Capacity = newCapacity;
+ }
+ }
+
+ // Returns a list wrapper that is fixed at the current size. Operations
+ // that add or remove items will fail, however, replacing items is allowed.
+ //
+ public static IList FixedSize(IList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.EndContractBlock();
+ return new FixedSizeList(list);
+ }
+
+ // Returns a list wrapper that is fixed at the current size. Operations
+ // that add or remove items will fail, however, replacing items is allowed.
+ //
+ public static ArrayList FixedSize(ArrayList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+ return new FixedSizeArrayList(list);
+ }
+
+ // Returns an enumerator for this list with the given
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
+ // GetObject methods of the enumerator will throw an exception.
+ //
+ public virtual IEnumerator GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ return new ArrayListEnumeratorSimple(this);
+ }
+
+ // Returns an enumerator for a section of this list with the given
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
+ // GetObject methods of the enumerator will throw an exception.
+ //
+ public virtual IEnumerator GetEnumerator(int index, int count) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ Contract.EndContractBlock();
+
+ return new ArrayListEnumerator(this, index, count);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards from beginning to end.
+ // The elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public virtual int IndexOf(Object value) {
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return Array.IndexOf((Array)_items, value, 0, _size);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards, starting at index
+ // startIndex and ending at count number of elements. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public virtual int IndexOf(Object value, int startIndex) {
+ if (startIndex > _size)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+ return Array.IndexOf((Array)_items, value, startIndex, _size - startIndex);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards, starting at index
+ // startIndex and upto count number of elements. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public virtual int IndexOf(Object value, int startIndex, int count) {
+ if (startIndex > _size)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (count <0 || startIndex > _size - count) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+ return Array.IndexOf((Array)_items, value, startIndex, count);
+ }
+
+ // Inserts an element into this list at a given index. The size of the list
+ // is increased by one. If required, the capacity of the list is doubled
+ // before inserting the new element.
+ //
+ public virtual void Insert(int index, Object value) {
+ // Note that insertions at the end are legal.
+ if (index < 0 || index > _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_ArrayListInsert"));
+ //Contract.Ensures(Count == Contract.OldValue(Count) + 1);
+ Contract.EndContractBlock();
+
+ if (_size == _items.Length) EnsureCapacity(_size + 1);
+ if (index < _size) {
+ Array.Copy(_items, index, _items, index + 1, _size - index);
+ }
+ _items[index] = value;
+ _size++;
+ _version++;
+ }
+
+ // Inserts the elements of the given collection at a given index. If
+ // required, the capacity of the list is increased to twice the previous
+ // capacity or the new size, whichever is larger. Ranges may be added
+ // to the end of the list by setting index to the ArrayList's size.
+ //
+ public virtual void InsertRange(int index, ICollection c) {
+ if (c==null)
+ throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection"));
+ if (index < 0 || index > _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ //Contract.Ensures(Count == Contract.OldValue(Count) + c.Count);
+ Contract.EndContractBlock();
+
+ int count = c.Count;
+ if (count > 0) {
+ EnsureCapacity(_size + count);
+ // shift existing items
+ if (index < _size) {
+ Array.Copy(_items, index, _items, index + count, _size - index);
+ }
+
+ Object[] itemsToInsert = new Object[count];
+ c.CopyTo(itemsToInsert, 0);
+ itemsToInsert.CopyTo(_items, index);
+ _size += count;
+ _version++;
+ }
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at the end
+ // and ending at the first element in the list. The elements of the list
+ // are compared to the given value using the Object.Equals method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public virtual int LastIndexOf(Object value)
+ {
+ Contract.Ensures(Contract.Result<int>() < _size);
+ return LastIndexOf(value, _size - 1, _size);
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at index
+ // startIndex and ending at the first element in the list. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public virtual int LastIndexOf(Object value, int startIndex)
+ {
+ if (startIndex >= _size)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+ return LastIndexOf(value, startIndex, startIndex + 1);
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at index
+ // startIndex and upto count elements. The elements of
+ // the list are compared to the given value using the Object.Equals
+ // method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public virtual int LastIndexOf(Object value, int startIndex, int count) {
+ if (Count != 0 && (startIndex < 0 || count < 0))
+ throw new ArgumentOutOfRangeException((startIndex<0 ? "startIndex" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+
+ if (_size == 0) // Special case for an empty list
+ return -1;
+
+ if (startIndex >= _size || count > startIndex + 1)
+ throw new ArgumentOutOfRangeException((startIndex>=_size ? "startIndex" : "count"), Environment.GetResourceString("ArgumentOutOfRange_BiggerThanCollection"));
+
+ return Array.LastIndexOf((Array)_items, value, startIndex, count);
+ }
+
+ // Returns a read-only IList wrapper for the given IList.
+ //
+#if FEATURE_CORECLR
+ [FriendAccessAllowed]
+#endif
+ public static IList ReadOnly(IList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.EndContractBlock();
+ return new ReadOnlyList(list);
+ }
+
+ // Returns a read-only ArrayList wrapper for the given ArrayList.
+ //
+ public static ArrayList ReadOnly(ArrayList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+ return new ReadOnlyArrayList(list);
+ }
+
+ // Removes the element at the given index. The size of the list is
+ // decreased by one.
+ //
+ public virtual void Remove(Object obj) {
+ Contract.Ensures(Count >= 0);
+
+ int index = IndexOf(obj);
+ BCLDebug.Correctness(index >= 0 || !(obj is Int32), "You passed an Int32 to Remove that wasn't in the ArrayList." + Environment.NewLine + "Did you mean RemoveAt? int: "+obj+" Count: "+Count);
+ if (index >=0)
+ RemoveAt(index);
+ }
+
+ // Removes the element at the given index. The size of the list is
+ // decreased by one.
+ //
+ public virtual void RemoveAt(int index) {
+ if (index < 0 || index >= _size) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.Ensures(Count >= 0);
+ //Contract.Ensures(Count == Contract.OldValue(Count) - 1);
+ Contract.EndContractBlock();
+
+ _size--;
+ if (index < _size) {
+ Array.Copy(_items, index + 1, _items, index, _size - index);
+ }
+ _items[_size] = null;
+ _version++;
+ }
+
+ // Removes a range of elements from this list.
+ //
+ public virtual void RemoveRange(int index, int count) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Count >= 0);
+ //Contract.Ensures(Count == Contract.OldValue(Count) - count);
+ Contract.EndContractBlock();
+
+ if (count > 0) {
+ int i = _size;
+ _size -= count;
+ if (index < _size) {
+ Array.Copy(_items, index + count, _items, index, _size - index);
+ }
+ while (i > _size) _items[--i] = null;
+ _version++;
+ }
+ }
+
+ // Returns an IList that contains count copies of value.
+ //
+ public static ArrayList Repeat(Object value, int count) {
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+
+ ArrayList list = new ArrayList((count>_defaultCapacity)?count:_defaultCapacity);
+ for(int i=0; i<count; i++)
+ list.Add(value);
+ return list;
+ }
+
+ // Reverses the elements in this list.
+ public virtual void Reverse() {
+ Reverse(0, Count);
+ }
+
+ // Reverses the elements in a range of this list. Following a call to this
+ // method, an element in the range given by index and count
+ // which was previously located at index i will now be located at
+ // index index + (index + count - i - 1).
+ //
+ // This method uses the Array.Reverse method to reverse the
+ // elements.
+ //
+ public virtual void Reverse(int index, int count) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+ Array.Reverse(_items, index, count);
+ _version++;
+ }
+
+ // Sets the elements starting at the given index to the elements of the
+ // given collection.
+ //
+ public virtual void SetRange(int index, ICollection c) {
+ if (c==null) throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection"));
+ Contract.EndContractBlock();
+ int count = c.Count;
+ if (index < 0 || index > _size - count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count > 0) {
+ c.CopyTo(_items, index);
+ _version++;
+ }
+ }
+
+ public virtual ArrayList GetRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+ return new Range(this,index, count);
+ }
+
+ // Sorts the elements in this list. Uses the default comparer and
+ // Array.Sort.
+ public virtual void Sort()
+ {
+ Sort(0, Count, Comparer.Default);
+ }
+
+ // Sorts the elements in this list. Uses Array.Sort with the
+ // provided comparer.
+ public virtual void Sort(IComparer comparer)
+ {
+ Sort(0, Count, comparer);
+ }
+
+ // Sorts the elements in a section of this list. The sort compares the
+ // elements to each other using the given IComparer interface. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented by all
+ // elements of the list.
+ //
+ // This method uses the Array.Sort method to sort the elements.
+ //
+ public virtual void Sort(int index, int count, IComparer comparer) {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_size - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ Array.Sort(_items, index, count, comparer);
+ _version++;
+ }
+
+ // Returns a thread-safe wrapper around an IList.
+ //
+ [HostProtection(Synchronization=true)]
+ public static IList Synchronized(IList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<IList>() != null);
+ Contract.EndContractBlock();
+ return new SyncIList(list);
+ }
+
+ // Returns a thread-safe wrapper around a ArrayList.
+ //
+ [HostProtection(Synchronization=true)]
+ public static ArrayList Synchronized(ArrayList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.Ensures(Contract.Result<ArrayList>() != null);
+ Contract.EndContractBlock();
+ return new SyncArrayList(list);
+ }
+
+ // ToArray returns a new Object array containing the contents of the ArrayList.
+ // This requires copying the ArrayList, which is an O(n) operation.
+ public virtual Object[] ToArray() {
+ Contract.Ensures(Contract.Result<Object[]>() != null);
+
+ Object[] array = new Object[_size];
+ Array.Copy(_items, 0, array, 0, _size);
+ return array;
+ }
+
+ // ToArray returns a new array of a particular type containing the contents
+ // of the ArrayList. This requires copying the ArrayList and potentially
+ // downcasting all elements. This copy may fail and is an O(n) operation.
+ // Internally, this implementation calls Array.Copy.
+ //
+ [SecuritySafeCritical]
+ public virtual Array ToArray(Type type) {
+ if (type==null)
+ throw new ArgumentNullException("type");
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.EndContractBlock();
+ Array array = Array.UnsafeCreateInstance(type, _size);
+ Array.Copy(_items, 0, array, 0, _size);
+ return array;
+ }
+
+ // Sets the capacity of this list to the size of the list. This method can
+ // be used to minimize a list's memory overhead once it is known that no
+ // new elements will be added to the list. To completely clear a list and
+ // release all memory referenced by the list, execute the following
+ // statements:
+ //
+ // list.Clear();
+ // list.TrimToSize();
+ //
+ public virtual void TrimToSize() {
+ Capacity = _size;
+ }
+
+
+ // This class wraps an IList, exposing it as a ArrayList
+ // Note this requires reimplementing half of ArrayList...
+ [Serializable]
+ private class IListWrapper : ArrayList
+ {
+ private IList _list;
+
+ internal IListWrapper(IList list) {
+ _list = list;
+ _version = 0; // list doesn't not contain a version number
+ }
+
+ public override int Capacity {
+ get { return _list.Count; }
+ set {
+ if (value < Count) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ Contract.EndContractBlock();
+ }
+ }
+
+ public override int Count {
+ get { return _list.Count; }
+ }
+
+ public override bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _list.IsFixedSize; }
+ }
+
+
+ public override bool IsSynchronized {
+ get { return _list.IsSynchronized; }
+ }
+
+ public override Object this[int index] {
+ get {
+ return _list[index];
+ }
+ set {
+ _list[index] = value;
+ _version++;
+ }
+ }
+
+ public override Object SyncRoot {
+ get { return _list.SyncRoot; }
+ }
+
+ public override int Add(Object obj) {
+ int i = _list.Add(obj);
+ _version++;
+ return i;
+ }
+
+ public override void AddRange(ICollection c) {
+ InsertRange(Count, c);
+ }
+
+ // Other overloads with automatically work
+ public override int BinarySearch(int index, int count, Object value, IComparer comparer)
+ {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (this.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+ if (comparer == null)
+ comparer = Comparer.Default;
+
+ int lo = index;
+ int hi = index + count - 1;
+ int mid;
+ while (lo <= hi) {
+ mid = (lo+hi)/2;
+ int r = comparer.Compare(value, _list[mid]);
+ if (r == 0)
+ return mid;
+ if (r < 0)
+ hi = mid-1;
+ else
+ lo = mid+1;
+ }
+ // return bitwise complement of the first element greater than value.
+ // Since hi is less than lo now, ~lo is the correct item.
+ return ~lo;
+ }
+
+ public override void Clear() {
+ // If _list is an array, it will support Clear method.
+ // We shouldn't allow clear operation on a FixedSized ArrayList
+ if(_list.IsFixedSize) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ _list.Clear();
+ _version++;
+ }
+
+ public override Object Clone() {
+ // This does not do a shallow copy of _list into a ArrayList!
+ // This clones the IListWrapper, creating another wrapper class!
+ return new IListWrapper(_list);
+ }
+
+ public override bool Contains(Object obj) {
+ return _list.Contains(obj);
+ }
+
+ public override void CopyTo(Array array, int index) {
+ _list.CopyTo(array, index);
+ }
+
+ public override void CopyTo(int index, Array array, int arrayIndex, int count) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (index < 0 || arrayIndex < 0)
+ throw new ArgumentOutOfRangeException((index < 0) ? "index" : "arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if( count < 0)
+ throw new ArgumentOutOfRangeException( "count" , Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - arrayIndex < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ for(int i=index; i<index+count; i++)
+ array.SetValue(_list[i], arrayIndex++);
+ }
+
+ public override IEnumerator GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ public override IEnumerator GetEnumerator(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ return new IListWrapperEnumWrapper(this, index, count);
+ }
+
+ public override int IndexOf(Object value) {
+ return _list.IndexOf(value);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex) {
+ return IndexOf(value, startIndex, _list.Count - startIndex);
+ }
+
+ public override int IndexOf(Object value, int startIndex, int count) {
+ if (startIndex < 0 || startIndex > this.Count) throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (count < 0 || startIndex > this.Count - count) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ Contract.EndContractBlock();
+
+ int endIndex = startIndex + count;
+ if (value == null) {
+ for(int i=startIndex; i<endIndex; i++)
+ if (_list[i] == null)
+ return i;
+ return -1;
+ } else {
+ for(int i=startIndex; i<endIndex; i++)
+ if (_list[i] != null && _list[i].Equals(value))
+ return i;
+ return -1;
+ }
+ }
+
+ public override void Insert(int index, Object obj) {
+ _list.Insert(index, obj);
+ _version++;
+ }
+
+ public override void InsertRange(int index, ICollection c) {
+ if (c==null)
+ throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection"));
+ if (index < 0 || index > this.Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ if( c.Count > 0) {
+ ArrayList al = _list as ArrayList;
+ if( al != null) {
+ // We need to special case ArrayList.
+ // When c is a range of _list, we need to handle this in a special way.
+ // See ArrayList.InsertRange for details.
+ al.InsertRange(index, c);
+ }
+ else {
+ IEnumerator en = c.GetEnumerator();
+ while(en.MoveNext()) {
+ _list.Insert(index++, en.Current);
+ }
+ }
+ _version++;
+ }
+ }
+
+ public override int LastIndexOf(Object value) {
+ return LastIndexOf(value,_list.Count - 1, _list.Count);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex) {
+ return LastIndexOf(value, startIndex, startIndex + 1);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex, int count) {
+ if (_list.Count == 0)
+ return -1;
+
+ if (startIndex < 0 || startIndex >= _list.Count) throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (count < 0 || count > startIndex + 1) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ int endIndex = startIndex - count + 1;
+ if (value == null) {
+ for(int i=startIndex; i >= endIndex; i--)
+ if (_list[i] == null)
+ return i;
+ return -1;
+ } else {
+ for(int i=startIndex; i >= endIndex; i--)
+ if (_list[i] != null && _list[i].Equals(value))
+ return i;
+ return -1;
+ }
+ }
+
+ public override void Remove(Object value) {
+ int index = IndexOf(value);
+ if (index >=0)
+ RemoveAt(index);
+ }
+
+ public override void RemoveAt(int index) {
+ _list.RemoveAt(index);
+ _version++;
+ }
+
+ public override void RemoveRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ if( count > 0) // be consistent with ArrayList
+ _version++;
+
+ while(count > 0) {
+ _list.RemoveAt(index);
+ count--;
+ }
+ }
+
+ public override void Reverse(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ int i = index;
+ int j = index + count - 1;
+ while (i < j)
+ {
+ Object tmp = _list[i];
+ _list[i++] = _list[j];
+ _list[j--] = tmp;
+ }
+ _version++;
+ }
+
+ public override void SetRange(int index, ICollection c) {
+ if (c==null) {
+ throw new ArgumentNullException("c", Environment.GetResourceString("ArgumentNull_Collection"));
+ }
+ Contract.EndContractBlock();
+
+ if (index < 0 || index > _list.Count - c.Count) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if( c.Count > 0) {
+ IEnumerator en = c.GetEnumerator();
+ while(en.MoveNext()) {
+ _list[index++] = en.Current;
+ }
+ _version++;
+ }
+ }
+
+ public override ArrayList GetRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ return new Range(this,index, count);
+ }
+
+ public override void Sort(int index, int count, IComparer comparer) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_list.Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ Object [] array = new Object[count];
+ CopyTo(index, array, 0, count);
+ Array.Sort(array, 0, count, comparer);
+ for(int i=0; i<count; i++)
+ _list[i+index] = array[i];
+
+ _version++;
+ }
+
+
+ public override Object[] ToArray() {
+ Object[] array = new Object[Count];
+ _list.CopyTo(array, 0);
+ return array;
+ }
+
+ [SecuritySafeCritical]
+ public override Array ToArray(Type type)
+ {
+ if (type==null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ Array array = Array.UnsafeCreateInstance(type, _list.Count);
+ _list.CopyTo(array, 0);
+ return array;
+ }
+
+ public override void TrimToSize()
+ {
+ // Can't really do much here...
+ }
+
+ // This is the enumerator for an IList that's been wrapped in another
+ // class that implements all of ArrayList's methods.
+ [Serializable]
+ private sealed class IListWrapperEnumWrapper : IEnumerator, ICloneable
+ {
+ private IEnumerator _en;
+ private int _remaining;
+ private int _initialStartIndex; // for reset
+ private int _initialCount; // for reset
+ private bool _firstCall; // firstCall to MoveNext
+
+ private IListWrapperEnumWrapper()
+ {
+ }
+
+ internal IListWrapperEnumWrapper(IListWrapper listWrapper, int startIndex, int count)
+ {
+ _en = listWrapper.GetEnumerator();
+ _initialStartIndex = startIndex;
+ _initialCount = count;
+ while(startIndex-- > 0 && _en.MoveNext());
+ _remaining = count;
+ _firstCall = true;
+ }
+
+ public Object Clone() {
+ // We must clone the underlying enumerator, I think.
+ IListWrapperEnumWrapper clone = new IListWrapperEnumWrapper();
+ clone._en = (IEnumerator) ((ICloneable)_en).Clone();
+ clone._initialStartIndex = _initialStartIndex;
+ clone._initialCount = _initialCount;
+ clone._remaining = _remaining;
+ clone._firstCall = _firstCall;
+ return clone;
+ }
+
+ public bool MoveNext() {
+ if (_firstCall) {
+ _firstCall = false;
+ return _remaining-- > 0 && _en.MoveNext();
+ }
+ if (_remaining < 0)
+ return false;
+ bool r = _en.MoveNext();
+ return r && _remaining-- > 0;
+ }
+
+ public Object Current {
+ get {
+ if (_firstCall)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_remaining < 0)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ return _en.Current;
+ }
+ }
+
+ public void Reset() {
+ _en.Reset();
+ int startIndex = _initialStartIndex;
+ while(startIndex-- > 0 && _en.MoveNext());
+ _remaining = _initialCount;
+ _firstCall = true;
+ }
+ }
+ }
+
+
+ [Serializable]
+ private class SyncArrayList : ArrayList
+ {
+ private ArrayList _list;
+ private Object _root;
+
+ internal SyncArrayList(ArrayList list)
+ : base( false )
+ {
+ _list = list;
+ _root = list.SyncRoot;
+ }
+
+ public override int Capacity {
+ get {
+ lock(_root) {
+ return _list.Capacity;
+ }
+ }
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ set {
+ lock(_root) {
+ _list.Capacity = value;
+ }
+ }
+ }
+
+ public override int Count {
+ get { lock(_root) { return _list.Count; } }
+ }
+
+ public override bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _list.IsFixedSize; }
+ }
+
+
+ public override bool IsSynchronized {
+ get { return true; }
+ }
+
+ public override Object this[int index] {
+ get {
+ lock(_root) {
+ return _list[index];
+ }
+ }
+ set {
+ lock(_root) {
+ _list[index] = value;
+ }
+ }
+ }
+
+ public override Object SyncRoot {
+ get { return _root; }
+ }
+
+ public override int Add(Object value) {
+ lock(_root) {
+ return _list.Add(value);
+ }
+ }
+
+ public override void AddRange(ICollection c) {
+ lock(_root) {
+ _list.AddRange(c);
+ }
+ }
+
+ public override int BinarySearch(Object value) {
+ lock(_root) {
+ return _list.BinarySearch(value);
+ }
+ }
+
+ public override int BinarySearch(Object value, IComparer comparer) {
+ lock(_root) {
+ return _list.BinarySearch(value, comparer);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int BinarySearch(int index, int count, Object value, IComparer comparer) {
+ lock(_root) {
+ return _list.BinarySearch(index, count, value, comparer);
+ }
+ }
+
+ public override void Clear() {
+ lock(_root) {
+ _list.Clear();
+ }
+ }
+
+ public override Object Clone() {
+ lock(_root) {
+ return new SyncArrayList((ArrayList)_list.Clone());
+ }
+ }
+
+ public override bool Contains(Object item) {
+ lock(_root) {
+ return _list.Contains(item);
+ }
+ }
+
+ public override void CopyTo(Array array) {
+ lock(_root) {
+ _list.CopyTo(array);
+ }
+ }
+
+ public override void CopyTo(Array array, int index) {
+ lock(_root) {
+ _list.CopyTo(array, index);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void CopyTo(int index, Array array, int arrayIndex, int count) {
+ lock(_root) {
+ _list.CopyTo(index, array, arrayIndex, count);
+ }
+ }
+
+ public override IEnumerator GetEnumerator() {
+ lock(_root) {
+ return _list.GetEnumerator();
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override IEnumerator GetEnumerator(int index, int count) {
+ lock(_root) {
+ return _list.GetEnumerator(index, count);
+ }
+ }
+
+ public override int IndexOf(Object value) {
+ lock(_root) {
+ return _list.IndexOf(value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex) {
+ lock(_root) {
+ return _list.IndexOf(value, startIndex);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex, int count) {
+ lock(_root) {
+ return _list.IndexOf(value, startIndex, count);
+ }
+ }
+
+ public override void Insert(int index, Object value) {
+ lock(_root) {
+ _list.Insert(index, value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void InsertRange(int index, ICollection c) {
+ lock(_root) {
+ _list.InsertRange(index, c);
+ }
+ }
+
+ public override int LastIndexOf(Object value) {
+ lock(_root) {
+ return _list.LastIndexOf(value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex) {
+ lock(_root) {
+ return _list.LastIndexOf(value, startIndex);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex, int count) {
+ lock(_root) {
+ return _list.LastIndexOf(value, startIndex, count);
+ }
+ }
+
+ public override void Remove(Object value) {
+ lock(_root) {
+ _list.Remove(value);
+ }
+ }
+
+ public override void RemoveAt(int index) {
+ lock(_root) {
+ _list.RemoveAt(index);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void RemoveRange(int index, int count) {
+ lock(_root) {
+ _list.RemoveRange(index, count);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Reverse(int index, int count) {
+ lock(_root) {
+ _list.Reverse(index, count);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetRange(int index, ICollection c) {
+ lock(_root) {
+ _list.SetRange(index, c);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override ArrayList GetRange(int index, int count) {
+ lock(_root) {
+ return _list.GetRange(index, count);
+ }
+ }
+
+ public override void Sort() {
+ lock(_root) {
+ _list.Sort();
+ }
+ }
+
+ public override void Sort(IComparer comparer) {
+ lock(_root) {
+ _list.Sort(comparer);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Sort(int index, int count, IComparer comparer) {
+ lock(_root) {
+ _list.Sort(index, count, comparer);
+ }
+ }
+
+ public override Object[] ToArray() {
+ lock(_root) {
+ return _list.ToArray();
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Array ToArray(Type type) {
+ lock(_root) {
+ return _list.ToArray(type);
+ }
+ }
+
+ public override void TrimToSize() {
+ lock(_root) {
+ _list.TrimToSize();
+ }
+ }
+ }
+
+
+ [Serializable]
+ private class SyncIList : IList
+ {
+ private IList _list;
+ private Object _root;
+
+ internal SyncIList(IList list) {
+ _list = list;
+ _root = list.SyncRoot;
+ }
+
+ public virtual int Count {
+ get { lock(_root) { return _list.Count; } }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return _list.IsFixedSize; }
+ }
+
+
+ public virtual bool IsSynchronized {
+ get { return true; }
+ }
+
+ public virtual Object this[int index] {
+ get {
+ lock(_root) {
+ return _list[index];
+ }
+ }
+ set {
+ lock(_root) {
+ _list[index] = value;
+ }
+ }
+ }
+
+ public virtual Object SyncRoot {
+ get { return _root; }
+ }
+
+ public virtual int Add(Object value) {
+ lock(_root) {
+ return _list.Add(value);
+ }
+ }
+
+
+ public virtual void Clear() {
+ lock(_root) {
+ _list.Clear();
+ }
+ }
+
+ public virtual bool Contains(Object item) {
+ lock(_root) {
+ return _list.Contains(item);
+ }
+ }
+
+ public virtual void CopyTo(Array array, int index) {
+ lock(_root) {
+ _list.CopyTo(array, index);
+ }
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ lock(_root) {
+ return _list.GetEnumerator();
+ }
+ }
+
+ public virtual int IndexOf(Object value) {
+ lock(_root) {
+ return _list.IndexOf(value);
+ }
+ }
+
+ public virtual void Insert(int index, Object value) {
+ lock(_root) {
+ _list.Insert(index, value);
+ }
+ }
+
+ public virtual void Remove(Object value) {
+ lock(_root) {
+ _list.Remove(value);
+ }
+ }
+
+ public virtual void RemoveAt(int index) {
+ lock(_root) {
+ _list.RemoveAt(index);
+ }
+ }
+ }
+
+ [Serializable]
+ private class FixedSizeList : IList
+ {
+ private IList _list;
+
+ internal FixedSizeList(IList l) {
+ _list = l;
+ }
+
+ public virtual int Count {
+ get { return _list.Count; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return _list.IsSynchronized; }
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return _list[index];
+ }
+ set {
+ _list[index] = value;
+ }
+ }
+
+ public virtual Object SyncRoot {
+ get { return _list.SyncRoot; }
+ }
+
+ public virtual int Add(Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public virtual bool Contains(Object obj) {
+ return _list.Contains(obj);
+ }
+
+ public virtual void CopyTo(Array array, int index) {
+ _list.CopyTo(array, index);
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ public virtual int IndexOf(Object value) {
+ return _list.IndexOf(value);
+ }
+
+ public virtual void Insert(int index, Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public virtual void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+ }
+
+ [Serializable]
+ private class FixedSizeArrayList : ArrayList
+ {
+ private ArrayList _list;
+
+ internal FixedSizeArrayList(ArrayList l) {
+ _list = l;
+ _version = _list._version;
+ }
+
+ public override int Count {
+ get { return _list.Count; }
+ }
+
+ public override bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return true; }
+ }
+
+ public override bool IsSynchronized {
+ get { return _list.IsSynchronized; }
+ }
+
+ public override Object this[int index] {
+ get {
+ return _list[index];
+ }
+ set {
+ _list[index] = value;
+ _version = _list._version;
+ }
+ }
+
+ public override Object SyncRoot {
+ get { return _list.SyncRoot; }
+ }
+
+ public override int Add(Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public override void AddRange(ICollection c) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int BinarySearch(int index, int count, Object value, IComparer comparer) {
+ return _list.BinarySearch(index, count, value, comparer);
+ }
+
+ public override int Capacity {
+ get { return _list.Capacity; }
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ set { throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection")); }
+ }
+
+ public override void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public override Object Clone() {
+ FixedSizeArrayList arrayList = new FixedSizeArrayList(_list);
+ arrayList._list = (ArrayList)_list.Clone();
+ return arrayList;
+ }
+
+ public override bool Contains(Object obj) {
+ return _list.Contains(obj);
+ }
+
+ public override void CopyTo(Array array, int index) {
+ _list.CopyTo(array, index);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void CopyTo(int index, Array array, int arrayIndex, int count) {
+ _list.CopyTo(index, array, arrayIndex, count);
+ }
+
+ public override IEnumerator GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override IEnumerator GetEnumerator(int index, int count) {
+ return _list.GetEnumerator(index, count);
+ }
+
+ public override int IndexOf(Object value) {
+ return _list.IndexOf(value);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex) {
+ return _list.IndexOf(value, startIndex);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex, int count) {
+ return _list.IndexOf(value, startIndex, count);
+ }
+
+ public override void Insert(int index, Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void InsertRange(int index, ICollection c) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public override int LastIndexOf(Object value) {
+ return _list.LastIndexOf(value);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex) {
+ return _list.LastIndexOf(value, startIndex);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex, int count) {
+ return _list.LastIndexOf(value, startIndex, count);
+ }
+
+ public override void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ public override void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void RemoveRange(int index, int count) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetRange(int index, ICollection c) {
+ _list.SetRange(index, c);
+ _version = _list._version;
+ }
+
+ public override ArrayList GetRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ return new Range(this,index, count);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Reverse(int index, int count) {
+ _list.Reverse(index, count);
+ _version = _list._version;
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Sort(int index, int count, IComparer comparer) {
+ _list.Sort(index, count, comparer);
+ _version = _list._version;
+ }
+
+ public override Object[] ToArray() {
+ return _list.ToArray();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Array ToArray(Type type) {
+ return _list.ToArray(type);
+ }
+
+ public override void TrimToSize() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FixedSizeCollection"));
+ }
+ }
+
+ [Serializable]
+ private class ReadOnlyList : IList
+ {
+ private IList _list;
+
+ internal ReadOnlyList(IList l) {
+ _list = l;
+ }
+
+ public virtual int Count {
+ get { return _list.Count; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return true; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return _list.IsSynchronized; }
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return _list[index];
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+ }
+
+ public virtual Object SyncRoot {
+ get { return _list.SyncRoot; }
+ }
+
+ public virtual int Add(Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public virtual bool Contains(Object obj) {
+ return _list.Contains(obj);
+ }
+
+ public virtual void CopyTo(Array array, int index) {
+ _list.CopyTo(array, index);
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ public virtual int IndexOf(Object value) {
+ return _list.IndexOf(value);
+ }
+
+ public virtual void Insert(int index, Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public virtual void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+ }
+
+ [Serializable]
+ private class ReadOnlyArrayList : ArrayList
+ {
+ private ArrayList _list;
+
+ internal ReadOnlyArrayList(ArrayList l) {
+ _list = l;
+ }
+
+ public override int Count {
+ get { return _list.Count; }
+ }
+
+ public override bool IsReadOnly {
+ get { return true; }
+ }
+
+ public override bool IsFixedSize {
+ get { return true; }
+ }
+
+ public override bool IsSynchronized {
+ get { return _list.IsSynchronized; }
+ }
+
+ public override Object this[int index] {
+ get {
+ return _list[index];
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+ }
+
+ public override Object SyncRoot {
+ get { return _list.SyncRoot; }
+ }
+
+ public override int Add(Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override void AddRange(ICollection c) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int BinarySearch(int index, int count, Object value, IComparer comparer) {
+ return _list.BinarySearch(index, count, value, comparer);
+ }
+
+
+ public override int Capacity {
+ get { return _list.Capacity; }
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ set { throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection")); }
+ }
+
+ public override void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override Object Clone() {
+ ReadOnlyArrayList arrayList = new ReadOnlyArrayList(_list);
+ arrayList._list = (ArrayList)_list.Clone();
+ return arrayList;
+ }
+
+ public override bool Contains(Object obj) {
+ return _list.Contains(obj);
+ }
+
+ public override void CopyTo(Array array, int index) {
+ _list.CopyTo(array, index);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void CopyTo(int index, Array array, int arrayIndex, int count) {
+ _list.CopyTo(index, array, arrayIndex, count);
+ }
+
+ public override IEnumerator GetEnumerator() {
+ return _list.GetEnumerator();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override IEnumerator GetEnumerator(int index, int count) {
+ return _list.GetEnumerator(index, count);
+ }
+
+ public override int IndexOf(Object value) {
+ return _list.IndexOf(value);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex) {
+ return _list.IndexOf(value, startIndex);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOf(Object value, int startIndex, int count) {
+ return _list.IndexOf(value, startIndex, count);
+ }
+
+ public override void Insert(int index, Object obj) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void InsertRange(int index, ICollection c) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override int LastIndexOf(Object value) {
+ return _list.LastIndexOf(value);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex) {
+ return _list.LastIndexOf(value, startIndex);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex, int count) {
+ return _list.LastIndexOf(value, startIndex, count);
+ }
+
+ public override void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void RemoveRange(int index, int count) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetRange(int index, ICollection c) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override ArrayList GetRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (Count - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ return new Range(this,index, count);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Reverse(int index, int count) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Sort(int index, int count, IComparer comparer) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+
+ public override Object[] ToArray() {
+ return _list.ToArray();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Array ToArray(Type type) {
+ return _list.ToArray(type);
+ }
+
+ public override void TrimToSize() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ReadOnlyCollection"));
+ }
+ }
+
+
+ // Implements an enumerator for a ArrayList. The enumerator uses the
+ // internal version number of the list to ensure that no modifications are
+ // made to the list while an enumeration is in progress.
+ [Serializable]
+ private sealed class ArrayListEnumerator : IEnumerator, ICloneable
+ {
+ private ArrayList list;
+ private int index;
+ private int endIndex; // Where to stop.
+ private int version;
+ private Object currentElement;
+ private int startIndex; // Save this for Reset.
+
+ internal ArrayListEnumerator(ArrayList list, int index, int count) {
+ this.list = list;
+ startIndex = index;
+ this.index = index - 1;
+ endIndex = this.index + count; // last valid index
+ version = list._version;
+ currentElement = null;
+ }
+
+ public Object Clone() {
+ return MemberwiseClone();
+ }
+
+ public bool MoveNext() {
+ if (version != list._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ if (index < endIndex) {
+ currentElement = list[++index];
+ return true;
+ }
+ else {
+ index = endIndex + 1;
+ }
+
+ return false;
+ }
+
+ public Object Current {
+ get {
+ if (index < startIndex)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ else if (index > endIndex) {
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ }
+ return currentElement;
+ }
+ }
+
+ public void Reset() {
+ if (version != list._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ index = startIndex - 1;
+ }
+ }
+
+ // Implementation of a generic list subrange. An instance of this class
+ // is returned by the default implementation of List.GetRange.
+ [Serializable]
+ private class Range: ArrayList
+ {
+ private ArrayList _baseList;
+ private int _baseIndex;
+ [ContractPublicPropertyName("Count")]
+ private int _baseSize;
+ private int _baseVersion;
+
+ internal Range(ArrayList list, int index, int count) : base(false) {
+ _baseList = list;
+ _baseIndex = index;
+ _baseSize = count;
+ _baseVersion = list._version;
+ // we also need to update _version field to make Range of Range work
+ _version = list._version;
+ }
+
+ private void InternalUpdateRange()
+ {
+ if (_baseVersion != _baseList._version)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnderlyingArrayListChanged"));
+ }
+
+ private void InternalUpdateVersion() {
+ _baseVersion++;
+ _version++;
+ }
+
+ public override int Add(Object value) {
+ InternalUpdateRange();
+ _baseList.Insert(_baseIndex + _baseSize, value);
+ InternalUpdateVersion();
+ return _baseSize++;
+ }
+
+ public override void AddRange(ICollection c) {
+ if( c == null ) {
+ throw new ArgumentNullException("c");
+ }
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ int count = c.Count;
+ if( count > 0) {
+ _baseList.InsertRange(_baseIndex + _baseSize, c);
+ InternalUpdateVersion();
+ _baseSize += count;
+ }
+ }
+
+ // Other overloads with automatically work
+ public override int BinarySearch(int index, int count, Object value, IComparer comparer) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+ InternalUpdateRange();
+
+ int i = _baseList.BinarySearch(_baseIndex + index, count, value, comparer);
+ if (i >= 0) return i - _baseIndex;
+ return i + _baseIndex;
+ }
+
+ public override int Capacity {
+ get {
+ return _baseList.Capacity;
+ }
+
+ set {
+ if (value < Count) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ Contract.EndContractBlock();
+ }
+ }
+
+
+ public override void Clear() {
+ InternalUpdateRange();
+ if (_baseSize != 0)
+ {
+ _baseList.RemoveRange(_baseIndex, _baseSize);
+ InternalUpdateVersion();
+ _baseSize = 0;
+ }
+ }
+
+ public override Object Clone() {
+ InternalUpdateRange();
+ Range arrayList = new Range(_baseList,_baseIndex,_baseSize);
+ arrayList._baseList = (ArrayList)_baseList.Clone();
+ return arrayList;
+ }
+
+ public override bool Contains(Object item) {
+ InternalUpdateRange();
+ if (item==null) {
+ for(int i=0; i<_baseSize; i++)
+ if (_baseList[_baseIndex + i]==null)
+ return true;
+ return false;
+ }
+ else {
+ for(int i=0; i<_baseSize; i++)
+ if (_baseList[_baseIndex + i] != null && _baseList[_baseIndex + i].Equals(item))
+ return true;
+ return false;
+ }
+ }
+
+ public override void CopyTo(Array array, int index) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - index < _baseSize)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.CopyTo(_baseIndex, array, index, _baseSize);
+ }
+
+ public override void CopyTo(int index, Array array, int arrayIndex, int count) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - arrayIndex < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.CopyTo(_baseIndex + index, array, arrayIndex, count);
+ }
+
+ public override int Count {
+ get {
+ InternalUpdateRange();
+ return _baseSize;
+ }
+ }
+
+ public override bool IsReadOnly {
+ get { return _baseList.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _baseList.IsFixedSize; }
+ }
+
+ public override bool IsSynchronized {
+ get { return _baseList.IsSynchronized; }
+ }
+
+ public override IEnumerator GetEnumerator() {
+ return GetEnumerator(0,_baseSize);
+ }
+
+ public override IEnumerator GetEnumerator(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ return _baseList.GetEnumerator(_baseIndex + index, count);
+ }
+
+ public override ArrayList GetRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ return new Range(this, index, count);
+ }
+
+ public override Object SyncRoot {
+ get {
+ return _baseList.SyncRoot;
+ }
+ }
+
+
+ public override int IndexOf(Object value) {
+ InternalUpdateRange();
+ int i = _baseList.IndexOf(value, _baseIndex, _baseSize);
+ if (i >= 0) return i - _baseIndex;
+ return -1;
+ }
+
+ public override int IndexOf(Object value, int startIndex) {
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (startIndex > _baseSize)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ int i = _baseList.IndexOf(value, _baseIndex + startIndex, _baseSize - startIndex);
+ if (i >= 0) return i - _baseIndex;
+ return -1;
+ }
+
+ public override int IndexOf(Object value, int startIndex, int count) {
+ if (startIndex < 0 || startIndex > _baseSize)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count < 0 || (startIndex > _baseSize - count))
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ int i = _baseList.IndexOf(value, _baseIndex + startIndex, count);
+ if (i >= 0) return i - _baseIndex;
+ return -1;
+ }
+
+ public override void Insert(int index, Object value) {
+ if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.Insert(_baseIndex + index, value);
+ InternalUpdateVersion();
+ _baseSize++;
+ }
+
+ public override void InsertRange(int index, ICollection c) {
+ if (index < 0 || index > _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if( c == null) {
+ throw new ArgumentNullException("c");
+ }
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ int count = c.Count;
+ if( count > 0) {
+ _baseList.InsertRange(_baseIndex + index, c);
+ _baseSize += count;
+ InternalUpdateVersion();
+ }
+ }
+
+ public override int LastIndexOf(Object value) {
+ InternalUpdateRange();
+ int i = _baseList.LastIndexOf(value, _baseIndex + _baseSize - 1, _baseSize);
+ if (i >= 0) return i - _baseIndex;
+ return -1;
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex) {
+ return LastIndexOf(value, startIndex, startIndex + 1);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int LastIndexOf(Object value, int startIndex, int count) {
+ InternalUpdateRange();
+ if (_baseSize == 0)
+ return -1;
+
+ if (startIndex >= _baseSize)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ int i = _baseList.LastIndexOf(value, _baseIndex + startIndex, count);
+ if (i >= 0) return i - _baseIndex;
+ return -1;
+ }
+
+ // Don't need to override Remove
+
+ public override void RemoveAt(int index) {
+ if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.RemoveAt(_baseIndex + index);
+ InternalUpdateVersion();
+ _baseSize--;
+ }
+
+ public override void RemoveRange(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ // No need to call _bastList.RemoveRange if count is 0.
+ // In addition, _baseList won't change the vresion number if count is 0.
+ if( count > 0) {
+ _baseList.RemoveRange(_baseIndex + index, count);
+ InternalUpdateVersion();
+ _baseSize -= count;
+ }
+ }
+
+ public override void Reverse(int index, int count) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.Reverse(_baseIndex + index, count);
+ InternalUpdateVersion();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetRange(int index, ICollection c) {
+ InternalUpdateRange();
+ if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ _baseList.SetRange(_baseIndex + index, c);
+ if( c.Count > 0) {
+ InternalUpdateVersion();
+ }
+ }
+
+ public override void Sort(int index, int count, IComparer comparer) {
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (_baseSize - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ _baseList.Sort(_baseIndex + index, count, comparer);
+ InternalUpdateVersion();
+ }
+
+ public override Object this[int index] {
+ get {
+ InternalUpdateRange();
+ if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ return _baseList[_baseIndex + index];
+ }
+ set {
+ InternalUpdateRange();
+ if (index < 0 || index >= _baseSize) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ _baseList[_baseIndex + index] = value;
+ InternalUpdateVersion();
+ }
+ }
+
+ public override Object[] ToArray() {
+ InternalUpdateRange();
+ Object[] array = new Object[_baseSize];
+ Array.Copy(_baseList._items, _baseIndex, array, 0, _baseSize);
+ return array;
+ }
+
+ [SecuritySafeCritical]
+ public override Array ToArray(Type type) {
+ if (type==null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ InternalUpdateRange();
+ Array array = Array.UnsafeCreateInstance(type, _baseSize);
+ _baseList.CopyTo(_baseIndex, array, 0, _baseSize);
+ return array;
+ }
+
+ public override void TrimToSize() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RangeCollection"));
+ }
+ }
+
+ [Serializable]
+ private sealed class ArrayListEnumeratorSimple : IEnumerator, ICloneable {
+ private ArrayList list;
+ private int index;
+ private int version;
+ private Object currentElement;
+ [NonSerialized]
+ private bool isArrayList;
+ // this object is used to indicate enumeration has not started or has terminated
+ static Object dummyObject = new Object();
+
+ internal ArrayListEnumeratorSimple(ArrayList list) {
+ this.list = list;
+ this.index = -1;
+ version = list._version;
+ isArrayList = (list.GetType() == typeof(ArrayList));
+ currentElement = dummyObject;
+ }
+
+ public Object Clone() {
+ return MemberwiseClone();
+ }
+
+ public bool MoveNext() {
+ if (version != list._version) {
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ }
+
+ if( isArrayList) { // avoid calling virtual methods if we are operating on ArrayList to improve performance
+ if (index < list._size - 1) {
+ currentElement = list._items[++index];
+ return true;
+ }
+ else {
+ currentElement = dummyObject;
+ index =list._size;
+ return false;
+ }
+ }
+ else {
+ if (index < list.Count - 1) {
+ currentElement = list[++index];
+ return true;
+ }
+ else {
+ index = list.Count;
+ currentElement = dummyObject;
+ return false;
+ }
+ }
+ }
+
+ public Object Current {
+ get {
+ object temp = currentElement;
+ if(dummyObject == temp) { // check if enumeration has not started or has terminated
+ if (index == -1) {
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ }
+ else {
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ }
+ }
+
+ return temp;
+ }
+ }
+
+ public void Reset() {
+ if (version != list._version) {
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ }
+
+ currentElement = dummyObject;
+ index = -1;
+ }
+ }
+
+ internal class ArrayListDebugView {
+ private ArrayList arrayList;
+
+ public ArrayListDebugView( ArrayList arrayList) {
+ if( arrayList == null)
+ throw new ArgumentNullException("arrayList");
+
+ this.arrayList = arrayList;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public Object[] Items {
+ get {
+ return arrayList.ToArray();
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/BitArray.cs b/src/mscorlib/src/System/Collections/BitArray.cs
new file mode 100644
index 0000000000..2f565f83af
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/BitArray.cs
@@ -0,0 +1,524 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: The BitArray class manages a compact array of bit values.
+**
+**
+=============================================================================*/
+namespace System.Collections {
+
+ using System;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+ // A vector of bits. Use this to store bits efficiently, without having to do bit
+ // shifting yourself.
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable()] public sealed class BitArray : ICollection, ICloneable {
+ private BitArray() {
+ }
+
+ /*=========================================================================
+ ** Allocates space to hold length bit values. All of the values in the bit
+ ** array are set to false.
+ **
+ ** Exceptions: ArgumentException if length < 0.
+ =========================================================================*/
+ public BitArray(int length)
+ : this(length, false) {
+ }
+
+ /*=========================================================================
+ ** Allocates space to hold length bit values. All of the values in the bit
+ ** array are set to defaultValue.
+ **
+ ** Exceptions: ArgumentOutOfRangeException if length < 0.
+ =========================================================================*/
+ public BitArray(int length, bool defaultValue) {
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException(nameof(length), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ m_array = new int[GetArrayLength(length, BitsPerInt32)];
+ m_length = length;
+
+ int fillValue = defaultValue ? unchecked(((int)0xffffffff)) : 0;
+ for (int i = 0; i < m_array.Length; i++) {
+ m_array[i] = fillValue;
+ }
+
+ _version = 0;
+ }
+
+ /*=========================================================================
+ ** Allocates space to hold the bit values in bytes. bytes[0] represents
+ ** bits 0 - 7, bytes[1] represents bits 8 - 15, etc. The LSB of each byte
+ ** represents the lowest index value; bytes[0] & 1 represents bit 0,
+ ** bytes[0] & 2 represents bit 1, bytes[0] & 4 represents bit 2, etc.
+ **
+ ** Exceptions: ArgumentException if bytes == null.
+ =========================================================================*/
+ public BitArray(byte[] bytes) {
+ if (bytes == null) {
+ throw new ArgumentNullException(nameof(bytes));
+ }
+ Contract.EndContractBlock();
+ // this value is chosen to prevent overflow when computing m_length.
+ // m_length is of type int32 and is exposed as a property, so
+ // type of m_length can't be changed to accommodate.
+ if (bytes.Length > Int32.MaxValue / BitsPerByte) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArrayTooLarge", BitsPerByte), nameof(bytes));
+ }
+
+ m_array = new int[GetArrayLength(bytes.Length, BytesPerInt32)];
+ m_length = bytes.Length * BitsPerByte;
+
+ int i = 0;
+ int j = 0;
+ while (bytes.Length - j >= 4) {
+ m_array[i++] = (bytes[j] & 0xff) |
+ ((bytes[j + 1] & 0xff) << 8) |
+ ((bytes[j + 2] & 0xff) << 16) |
+ ((bytes[j + 3] & 0xff) << 24);
+ j += 4;
+ }
+
+ Contract.Assert(bytes.Length - j >= 0, "BitArray byteLength problem");
+ Contract.Assert(bytes.Length - j < 4, "BitArray byteLength problem #2");
+
+ switch (bytes.Length - j) {
+ case 3:
+ m_array[i] = ((bytes[j + 2] & 0xff) << 16);
+ goto case 2;
+ // fall through
+ case 2:
+ m_array[i] |= ((bytes[j + 1] & 0xff) << 8);
+ goto case 1;
+ // fall through
+ case 1:
+ m_array[i] |= (bytes[j] & 0xff);
+ break;
+ }
+
+ _version = 0;
+ }
+
+ public BitArray(bool[] values) {
+ if (values == null) {
+ throw new ArgumentNullException(nameof(values));
+ }
+ Contract.EndContractBlock();
+
+ m_array = new int[GetArrayLength(values.Length, BitsPerInt32)];
+ m_length = values.Length;
+
+ for (int i = 0;i<values.Length;i++) {
+ if (values[i])
+ m_array[i/32] |= (1 << (i%32));
+ }
+
+ _version = 0;
+
+ }
+
+ /*=========================================================================
+ ** Allocates space to hold the bit values in values. values[0] represents
+ ** bits 0 - 31, values[1] represents bits 32 - 63, etc. The LSB of each
+ ** integer represents the lowest index value; values[0] & 1 represents bit
+ ** 0, values[0] & 2 represents bit 1, values[0] & 4 represents bit 2, etc.
+ **
+ ** Exceptions: ArgumentException if values == null.
+ =========================================================================*/
+ public BitArray(int[] values) {
+ if (values == null) {
+ throw new ArgumentNullException(nameof(values));
+ }
+ Contract.EndContractBlock();
+ // this value is chosen to prevent overflow when computing m_length
+ if (values.Length > Int32.MaxValue / BitsPerInt32) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArrayTooLarge", BitsPerInt32), nameof(values));
+ }
+
+ m_array = new int[values.Length];
+ m_length = values.Length * BitsPerInt32;
+
+ Array.Copy(values, m_array, values.Length);
+
+ _version = 0;
+ }
+
+ /*=========================================================================
+ ** Allocates a new BitArray with the same length and bit values as bits.
+ **
+ ** Exceptions: ArgumentException if bits == null.
+ =========================================================================*/
+ public BitArray(BitArray bits) {
+ if (bits == null) {
+ throw new ArgumentNullException(nameof(bits));
+ }
+ Contract.EndContractBlock();
+
+ int arrayLength = GetArrayLength(bits.m_length, BitsPerInt32);
+ m_array = new int[arrayLength];
+ m_length = bits.m_length;
+
+ Array.Copy(bits.m_array, m_array, arrayLength);
+
+ _version = bits._version;
+ }
+
+ public bool this[int index] {
+ get {
+ return Get(index);
+ }
+ set {
+ Set(index,value);
+ }
+ }
+
+ /*=========================================================================
+ ** Returns the bit value at position index.
+ **
+ ** Exceptions: ArgumentOutOfRangeException if index < 0 or
+ ** index >= GetLength().
+ =========================================================================*/
+ public bool Get(int index) {
+ if (index < 0 || index >= Length) {
+ throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ return (m_array[index / 32] & (1 << (index % 32))) != 0;
+ }
+
+ /*=========================================================================
+ ** Sets the bit value at position index to value.
+ **
+ ** Exceptions: ArgumentOutOfRangeException if index < 0 or
+ ** index >= GetLength().
+ =========================================================================*/
+ public void Set(int index, bool value) {
+ if (index < 0 || index >= Length) {
+ throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ if (value) {
+ m_array[index / 32] |= (1 << (index % 32));
+ } else {
+ m_array[index / 32] &= ~(1 << (index % 32));
+ }
+
+ _version++;
+ }
+
+ /*=========================================================================
+ ** Sets all the bit values to value.
+ =========================================================================*/
+ public void SetAll(bool value) {
+ int fillValue = value ? unchecked(((int)0xffffffff)) : 0;
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ for (int i = 0; i < ints; i++) {
+ m_array[i] = fillValue;
+ }
+
+ _version++;
+ }
+
+ /*=========================================================================
+ ** Returns a reference to the current instance ANDed with value.
+ **
+ ** Exceptions: ArgumentException if value == null or
+ ** value.Length != this.Length.
+ =========================================================================*/
+ public BitArray And(BitArray value) {
+ if (value==null)
+ throw new ArgumentNullException(nameof(value));
+ if (Length != value.Length)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"));
+ Contract.EndContractBlock();
+
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ for (int i = 0; i < ints; i++) {
+ m_array[i] &= value.m_array[i];
+ }
+
+ _version++;
+ return this;
+ }
+
+ /*=========================================================================
+ ** Returns a reference to the current instance ORed with value.
+ **
+ ** Exceptions: ArgumentException if value == null or
+ ** value.Length != this.Length.
+ =========================================================================*/
+ public BitArray Or(BitArray value) {
+ if (value==null)
+ throw new ArgumentNullException(nameof(value));
+ if (Length != value.Length)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"));
+ Contract.EndContractBlock();
+
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ for (int i = 0; i < ints; i++) {
+ m_array[i] |= value.m_array[i];
+ }
+
+ _version++;
+ return this;
+ }
+
+ /*=========================================================================
+ ** Returns a reference to the current instance XORed with value.
+ **
+ ** Exceptions: ArgumentException if value == null or
+ ** value.Length != this.Length.
+ =========================================================================*/
+ public BitArray Xor(BitArray value) {
+ if (value==null)
+ throw new ArgumentNullException(nameof(value));
+ if (Length != value.Length)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"));
+ Contract.EndContractBlock();
+
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ for (int i = 0; i < ints; i++) {
+ m_array[i] ^= value.m_array[i];
+ }
+
+ _version++;
+ return this;
+ }
+
+ /*=========================================================================
+ ** Inverts all the bit values. On/true bit values are converted to
+ ** off/false. Off/false bit values are turned on/true. The current instance
+ ** is updated and returned.
+ =========================================================================*/
+ public BitArray Not() {
+ int ints = GetArrayLength(m_length, BitsPerInt32);
+ for (int i = 0; i < ints; i++) {
+ m_array[i] = ~m_array[i];
+ }
+
+ _version++;
+ return this;
+ }
+
+ public int Length {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return m_length;
+ }
+ set {
+ if (value < 0) {
+ throw new ArgumentOutOfRangeException(nameof(value), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ int newints = GetArrayLength(value, BitsPerInt32);
+ if (newints > m_array.Length || newints + _ShrinkThreshold < m_array.Length) {
+ // grow or shrink (if wasting more than _ShrinkThreshold ints)
+ int[] newarray = new int[newints];
+ Array.Copy(m_array, newarray, newints > m_array.Length ? m_array.Length : newints);
+ m_array = newarray;
+ }
+
+ if (value > m_length) {
+ // clear high bit values in the last int
+ int last = GetArrayLength(m_length, BitsPerInt32) - 1;
+ int bits = m_length % 32;
+ if (bits > 0) {
+ m_array[last] &= (1 << bits) - 1;
+ }
+
+ // clear remaining int values
+ Array.Clear(m_array, last + 1, newints - last - 1);
+ }
+
+ m_length = value;
+ _version++;
+ }
+ }
+
+ // ICollection implementation
+ public void CopyTo(Array array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException(nameof(array));
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"), nameof(array));
+
+ Contract.EndContractBlock();
+
+ if (array is int[])
+ {
+ Array.Copy(m_array, 0, array, index, GetArrayLength(m_length, BitsPerInt32));
+ }
+ else if (array is byte[])
+ {
+ int arrayLength = GetArrayLength(m_length, BitsPerByte);
+ if ((array.Length - index) < arrayLength)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ byte [] b = (byte[])array;
+ for (int i = 0; i < arrayLength; i++)
+ b[index + i] = (byte)((m_array[i/4] >> ((i%4)*8)) & 0x000000FF); // Shift to bring the required byte to LSB, then mask
+ }
+ else if (array is bool[])
+ {
+ if (array.Length - index < m_length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ bool [] b = (bool[])array;
+ for (int i = 0;i<m_length;i++)
+ b[index + i] = ((m_array[i/32] >> (i%32)) & 0x00000001) != 0;
+ }
+ else
+ throw new ArgumentException(Environment.GetResourceString("Arg_BitArrayTypeUnsupported"), nameof(array));
+ }
+
+ public int Count
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+
+ return m_length;
+ }
+ }
+
+ public Object Clone()
+ {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ Contract.Ensures(((BitArray)Contract.Result<Object>()).Length == this.Length);
+
+ return new BitArray(this);
+ }
+
+ public Object SyncRoot
+ {
+ get
+ {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ public bool IsReadOnly
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public bool IsSynchronized
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return new BitArrayEnumeratorSimple(this);
+ }
+
+ // XPerY=n means that n Xs can be stored in 1 Y.
+ private const int BitsPerInt32 = 32;
+ private const int BytesPerInt32 = 4;
+ private const int BitsPerByte = 8;
+
+ /// <summary>
+ /// Used for conversion between different representations of bit array.
+ /// Returns (n+(div-1))/div, rearranged to avoid arithmetic overflow.
+ /// For example, in the bit to int case, the straightforward calc would
+ /// be (n+31)/32, but that would cause overflow. So instead it's
+ /// rearranged to ((n-1)/32) + 1, with special casing for 0.
+ ///
+ /// Usage:
+ /// GetArrayLength(77, BitsPerInt32): returns how many ints must be
+ /// allocated to store 77 bits.
+ /// </summary>
+ /// <param name="n"></param>
+ /// <param name="div">use a conversion constant, e.g. BytesPerInt32 to get
+ /// how many ints are required to store n bytes</param>
+ /// <returns></returns>
+ private static int GetArrayLength(int n, int div) {
+ Contract.Assert(div > 0, "GetArrayLength: div arg must be greater than 0");
+ return n > 0 ? (((n - 1) / div) + 1) : 0;
+ }
+
+ [Serializable]
+ private class BitArrayEnumeratorSimple : IEnumerator, ICloneable
+ {
+ private BitArray bitarray;
+ private int index;
+ private int version;
+ private bool currentElement;
+
+ internal BitArrayEnumeratorSimple(BitArray bitarray) {
+ this.bitarray = bitarray;
+ this.index = -1;
+ version = bitarray._version;
+ }
+
+ public Object Clone() {
+ return MemberwiseClone();
+ }
+
+ public virtual bool MoveNext() {
+ if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ if (index < (bitarray.Count-1)) {
+ index++;
+ currentElement = bitarray.Get(index);
+ return true;
+ }
+ else
+ index = bitarray.Count;
+
+ return false;
+ }
+
+ public virtual Object Current {
+ get {
+ if (index == -1)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (index >= bitarray.Count)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ return currentElement;
+ }
+ }
+
+ public void Reset() {
+ if (version != bitarray._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ index = -1;
+ }
+ }
+
+ private int[] m_array;
+ private int m_length;
+ private int _version;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ private const int _ShrinkThreshold = 256;
+ }
+
+}
diff --git a/src/mscorlib/src/System/Collections/CollectionBase.cs b/src/mscorlib/src/System/Collections/CollectionBase.cs
new file mode 100644
index 0000000000..1bb08af27a
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/CollectionBase.cs
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//
+
+namespace System.Collections {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // Useful base class for typed read/write collections where items derive from object
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class CollectionBase : IList {
+ ArrayList list;
+
+ protected CollectionBase() {
+ list = new ArrayList();
+ }
+
+ protected CollectionBase(int capacity) {
+ list = new ArrayList(capacity);
+ }
+
+
+ protected ArrayList InnerList {
+ get {
+ if (list == null)
+ list = new ArrayList();
+ return list;
+ }
+ }
+
+ protected IList List {
+ get { return (IList)this; }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public int Capacity {
+ get {
+ return InnerList.Capacity;
+ }
+ set {
+ InnerList.Capacity = value;
+ }
+ }
+
+
+ public int Count {
+ get {
+ return list == null ? 0 : list.Count;
+ }
+ }
+
+ public void Clear() {
+ OnClear();
+ InnerList.Clear();
+ OnClearComplete();
+ }
+
+ public void RemoveAt(int index) {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ Object temp = InnerList[index];
+ OnValidate(temp);
+ OnRemove(index, temp);
+ InnerList.RemoveAt(index);
+ try {
+ OnRemoveComplete(index, temp);
+ }
+ catch {
+ InnerList.Insert(index, temp);
+ throw;
+ }
+
+ }
+
+ bool IList.IsReadOnly {
+ get { return InnerList.IsReadOnly; }
+ }
+
+ bool IList.IsFixedSize {
+ get { return InnerList.IsFixedSize; }
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return InnerList.IsSynchronized; }
+ }
+
+ Object ICollection.SyncRoot {
+ get { return InnerList.SyncRoot; }
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ InnerList.CopyTo(array, index);
+ }
+
+ Object IList.this[int index] {
+ get {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return InnerList[index];
+ }
+ set {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ OnValidate(value);
+ Object temp = InnerList[index];
+ OnSet(index, temp, value);
+ InnerList[index] = value;
+ try {
+ OnSetComplete(index, temp, value);
+ }
+ catch {
+ InnerList[index] = temp;
+ throw;
+ }
+ }
+ }
+
+ bool IList.Contains(Object value) {
+ return InnerList.Contains(value);
+ }
+
+ int IList.Add(Object value) {
+ OnValidate(value);
+ OnInsert(InnerList.Count, value);
+ int index = InnerList.Add(value);
+ try {
+ OnInsertComplete(index, value);
+ }
+ catch {
+ InnerList.RemoveAt(index);
+ throw;
+ }
+ return index;
+ }
+
+
+ void IList.Remove(Object value) {
+ OnValidate(value);
+ int index = InnerList.IndexOf(value);
+ if (index < 0) throw new ArgumentException(Environment.GetResourceString("Arg_RemoveArgNotFound"));
+ OnRemove(index, value);
+ InnerList.RemoveAt(index);
+ try{
+ OnRemoveComplete(index, value);
+ }
+ catch {
+ InnerList.Insert(index, value);
+ throw;
+ }
+ }
+
+ int IList.IndexOf(Object value) {
+ return InnerList.IndexOf(value);
+ }
+
+ void IList.Insert(int index, Object value) {
+ if (index < 0 || index > Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ OnValidate(value);
+ OnInsert(index, value);
+ InnerList.Insert(index, value);
+ try {
+ OnInsertComplete(index, value);
+ }
+ catch {
+ InnerList.RemoveAt(index);
+ throw;
+ }
+ }
+
+ public IEnumerator GetEnumerator() {
+ return InnerList.GetEnumerator();
+ }
+
+ protected virtual void OnSet(int index, Object oldValue, Object newValue) {
+ }
+
+ protected virtual void OnInsert(int index, Object value) {
+ }
+
+ protected virtual void OnClear() {
+ }
+
+ protected virtual void OnRemove(int index, Object value) {
+ }
+
+ protected virtual void OnValidate(Object value) {
+ if (value == null) throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+ }
+
+ protected virtual void OnSetComplete(int index, Object oldValue, Object newValue) {
+ }
+
+ protected virtual void OnInsertComplete(int index, Object value) {
+ }
+
+ protected virtual void OnClearComplete() {
+ }
+
+ protected virtual void OnRemoveComplete(int index, Object value) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Collections/Comparer.cs b/src/mscorlib/src/System/Collections/Comparer.cs
new file mode 100644
index 0000000000..11e26252a8
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Comparer.cs
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Default IComparer implementation.
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Comparer : IComparer , ISerializable
+ {
+ private CompareInfo m_compareInfo;
+ public static readonly Comparer Default = new Comparer(CultureInfo.CurrentCulture);
+ public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture);
+
+ private const String CompareInfoName = "CompareInfo";
+
+ private Comparer() {
+ m_compareInfo = null;
+ }
+
+ public Comparer(CultureInfo culture) {
+ if (culture==null) {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.EndContractBlock();
+ m_compareInfo = culture.CompareInfo;
+ }
+
+ private Comparer(SerializationInfo info, StreamingContext context) {
+ m_compareInfo = null;
+ SerializationInfoEnumerator enumerator = info.GetEnumerator();
+ while( enumerator.MoveNext()) {
+ switch( enumerator.Name) {
+ case CompareInfoName:
+ m_compareInfo = (CompareInfo) info.GetValue(CompareInfoName, typeof(CompareInfo));
+ break;
+ }
+ }
+ }
+
+ // Compares two Objects by calling CompareTo. If a ==
+ // b,0 is returned. If a implements
+ // IComparable, a.CompareTo(b) is returned. If a
+ // doesn't implement IComparable and b does,
+ // -(b.CompareTo(a)) is returned, otherwise an
+ // exception is thrown.
+ //
+ public int Compare(Object a, Object b) {
+ if (a == b) return 0;
+ if (a == null) return -1;
+ if (b == null) return 1;
+ if (m_compareInfo != null) {
+ String sa = a as String;
+ String sb = b as String;
+ if (sa != null && sb != null)
+ return m_compareInfo.Compare(sa, sb);
+ }
+
+ IComparable ia = a as IComparable;
+ if (ia != null)
+ return ia.CompareTo(b);
+
+ IComparable ib = b as IComparable;
+ if (ib != null)
+ return -ib.CompareTo(a);
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ if( m_compareInfo != null) {
+ info.AddValue(CompareInfoName, m_compareInfo);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/CompatibleComparer.cs b/src/mscorlib/src/System/Collections/CompatibleComparer.cs
new file mode 100644
index 0000000000..85e6c3f0f3
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/CompatibleComparer.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System.Diagnostics.Contracts;
+
+namespace System.Collections {
+
+ [Serializable]
+ internal class CompatibleComparer: IEqualityComparer {
+ IComparer _comparer;
+#pragma warning disable 618
+ IHashCodeProvider _hcp;
+
+ internal CompatibleComparer(IComparer comparer, IHashCodeProvider hashCodeProvider) {
+ _comparer = comparer;
+ _hcp = hashCodeProvider;
+ }
+#pragma warning restore 618
+
+ public int Compare(Object a, Object b) {
+ if (a == b) return 0;
+ if (a == null) return -1;
+ if (b == null) return 1;
+ if (_comparer != null)
+ return _comparer.Compare(a,b);
+ IComparable ia = a as IComparable;
+ if (ia != null)
+ return ia.CompareTo(b);
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
+ }
+
+ public new bool Equals(Object a, Object b) {
+ return Compare(a, b) == 0;
+ }
+
+ public int GetHashCode(Object obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ if (_hcp != null)
+ return _hcp.GetHashCode(obj);
+ return obj.GetHashCode();
+ }
+
+ // These are helpers for the Hashtable to query the IKeyComparer infrastructure.
+ internal IComparer Comparer {
+ get {
+ return _comparer;
+ }
+ }
+
+ // These are helpers for the Hashtable to query the IKeyComparer infrastructure.
+#pragma warning disable 618
+ internal IHashCodeProvider HashCodeProvider {
+ get {
+ return _hcp;
+ }
+ }
+#pragma warning restore 618
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs
new file mode 100644
index 0000000000..d805dc8be7
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentDictionary.cs
@@ -0,0 +1,2095 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: A scalable dictionary for concurrent access
+**
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading;
+using System.Security;
+using System.Security.Permissions;
+
+namespace System.Collections.Concurrent
+{
+
+ /// <summary>
+ /// Represents a thread-safe collection of keys and values.
+ /// </summary>
+ /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
+ /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
+ /// <remarks>
+ /// All public and protected members of <see cref="ConcurrentDictionary{TKey,TValue}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </remarks>
+#if !FEATURE_CORECLR
+ [Serializable]
+#endif
+ [ComVisible(false)]
+ [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class ConcurrentDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>
+ {
+ /// <summary>
+ /// Tables that hold the internal state of the ConcurrentDictionary
+ ///
+ /// Wrapping the three tables in a single object allows us to atomically
+ /// replace all tables at once.
+ /// </summary>
+ private class Tables
+ {
+ internal readonly Node[] m_buckets; // A singly-linked list for each bucket.
+ internal readonly object[] m_locks; // A set of locks, each guarding a section of the table.
+ internal volatile int[] m_countPerLock; // The number of elements guarded by each lock.
+ internal readonly IEqualityComparer<TKey> m_comparer; // Key equality comparer
+
+ internal Tables(Node[] buckets, object[] locks, int[] countPerLock, IEqualityComparer<TKey> comparer)
+ {
+ m_buckets = buckets;
+ m_locks = locks;
+ m_countPerLock = countPerLock;
+ m_comparer = comparer;
+ }
+ }
+#if !FEATURE_CORECLR
+ [NonSerialized]
+#endif
+ private volatile Tables m_tables; // Internal tables of the dictionary
+ // NOTE: this is only used for compat reasons to serialize the comparer.
+ // This should not be accessed from anywhere else outside of the serialization methods.
+ internal IEqualityComparer<TKey> m_comparer;
+#if !FEATURE_CORECLR
+ [NonSerialized]
+#endif
+ private readonly bool m_growLockArray; // Whether to dynamically increase the size of the striped lock
+
+ // How many times we resized becaused of collisions.
+ // This is used to make sure we don't resize the dictionary because of multi-threaded Add() calls
+ // that generate collisions. Whenever a GrowTable() should be the only place that changes this
+#if !FEATURE_CORECLR
+ // The field should be have been marked as NonSerialized but because we shipped it without that attribute in 4.5.1.
+ // we can't add it back without breaking compat. To maximize compat we are going to keep the OptionalField attribute
+ // This will prevent cases where the field was not serialized.
+ [OptionalField]
+#endif
+ private int m_keyRehashCount;
+
+#if !FEATURE_CORECLR
+ [NonSerialized]
+#endif
+ private int m_budget; // The maximum number of elements per lock before a resize operation is triggered
+
+#if !FEATURE_CORECLR // These fields are not used in CoreCLR
+ private KeyValuePair<TKey, TValue>[] m_serializationArray; // Used for custom serialization
+
+ private int m_serializationConcurrencyLevel; // used to save the concurrency level in serialization
+
+ private int m_serializationCapacity; // used to save the capacity in serialization
+#endif
+ // The default concurrency level is DEFAULT_CONCURRENCY_MULTIPLIER * #CPUs. The higher the
+ // DEFAULT_CONCURRENCY_MULTIPLIER, the more concurrent writes can take place without interference
+ // and blocking, but also the more expensive operations that require all locks become (e.g. table
+ // resizing, ToArray, Count, etc). According to brief benchmarks that we ran, 4 seems like a good
+ // compromise.
+ private const int DEFAULT_CONCURRENCY_MULTIPLIER = 4;
+
+ // The default capacity, i.e. the initial # of buckets. When choosing this value, we are making
+ // a trade-off between the size of a very small dictionary, and the number of resizes when
+ // constructing a large dictionary. Also, the capacity should not be divisible by a small prime.
+ private const int DEFAULT_CAPACITY = 31;
+
+ // The maximum size of the striped lock that will not be exceeded when locks are automatically
+ // added as the dictionary grows. However, the user is allowed to exceed this limit by passing
+ // a concurrency level larger than MAX_LOCK_NUMBER into the constructor.
+ private const int MAX_LOCK_NUMBER = 1024;
+
+ // Whether TValue is a type that can be written atomically (i.e., with no danger of torn reads)
+ private static readonly bool s_isValueWriteAtomic = IsValueWriteAtomic();
+
+
+ /// <summary>
+ /// Determines whether type TValue can be written atomically
+ /// </summary>
+ private static bool IsValueWriteAtomic()
+ {
+ Type valueType = typeof(TValue);
+
+ //
+ // Section 12.6.6 of ECMA CLI explains which types can be read and written atomically without
+ // the risk of tearing.
+ //
+ // See http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf
+ //
+ bool isAtomic =
+ (valueType.IsClass)
+ || valueType == typeof(Boolean)
+ || valueType == typeof(Char)
+ || valueType == typeof(Byte)
+ || valueType == typeof(SByte)
+ || valueType == typeof(Int16)
+ || valueType == typeof(UInt16)
+ || valueType == typeof(Int32)
+ || valueType == typeof(UInt32)
+ || valueType == typeof(Single);
+
+ if (!isAtomic && IntPtr.Size == 8)
+ {
+ isAtomic |= valueType == typeof(Double) || valueType == typeof(Int64);
+ }
+
+ return isAtomic;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that is empty, has the default concurrency level, has the default initial capacity, and
+ /// uses the default comparer for the key type.
+ /// </summary>
+ public ConcurrentDictionary() : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, EqualityComparer<TKey>.Default) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that is empty, has the specified concurrency level and capacity, and uses the default
+ /// comparer for the key type.
+ /// </summary>
+ /// <param name="concurrencyLevel">The estimated number of threads that will update the
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param>
+ /// <param name="capacity">The initial number of elements that the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// can contain.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="concurrencyLevel"/> is
+ /// less than 1.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> <paramref name="capacity"/> is less than
+ /// 0.</exception>
+ public ConcurrentDictionary(int concurrencyLevel, int capacity) : this(concurrencyLevel, capacity, false, EqualityComparer<TKey>.Default) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that contains elements copied from the specified <see
+ /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/>, has the default concurrency
+ /// level, has the default initial capacity, and uses the default comparer for the key type.
+ /// </summary>
+ /// <param name="collection">The <see
+ /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to
+ /// the new
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more
+ /// duplicate keys.</exception>
+ public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : this(collection, EqualityComparer<TKey>.Default) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that is empty, has the specified concurrency level and capacity, and uses the specified
+ /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>.
+ /// </summary>
+ /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>
+ /// implementation to use when comparing keys.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ public ConcurrentDictionary(IEqualityComparer<TKey> comparer) : this(DefaultConcurrencyLevel, DEFAULT_CAPACITY, true, comparer) { }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that contains elements copied from the specified <see
+ /// cref="T:System.Collections.IEnumerable"/>, has the default concurrency level, has the default
+ /// initial capacity, and uses the specified
+ /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>.
+ /// </summary>
+ /// <param name="collection">The <see
+ /// cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to
+ /// the new
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param>
+ /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>
+ /// implementation to use when comparing keys.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="collection"/> is a null reference
+ /// (Nothing in Visual Basic). -or-
+ /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ public ConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
+ : this(comparer)
+ {
+ if (collection == null) throw new ArgumentNullException("collection");
+
+ InitializeFromCollection(collection);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that contains elements copied from the specified <see cref="T:System.Collections.IEnumerable"/>,
+ /// has the specified concurrency level, has the specified initial capacity, and uses the specified
+ /// <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>.
+ /// </summary>
+ /// <param name="concurrencyLevel">The estimated number of threads that will update the
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param>
+ /// <param name="collection">The <see cref="T:System.Collections.IEnumerable{KeyValuePair{TKey,TValue}}"/> whose elements are copied to the new
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/>.</param>
+ /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/> implementation to use
+ /// when comparing keys.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="collection"/> is a null reference (Nothing in Visual Basic).
+ /// -or-
+ /// <paramref name="comparer"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="concurrencyLevel"/> is less than 1.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException"><paramref name="collection"/> contains one or more duplicate keys.</exception>
+ public ConcurrentDictionary(
+ int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer)
+ : this(concurrencyLevel, DEFAULT_CAPACITY, false, comparer)
+ {
+ if (collection == null) throw new ArgumentNullException("collection");
+ if (comparer == null) throw new ArgumentNullException("comparer");
+
+ InitializeFromCollection(collection);
+ }
+
+ private void InitializeFromCollection(IEnumerable<KeyValuePair<TKey, TValue>> collection)
+ {
+ TValue dummy;
+ foreach (KeyValuePair<TKey, TValue> pair in collection)
+ {
+ if (pair.Key == null) throw new ArgumentNullException("key");
+
+ if (!TryAddInternal(pair.Key, pair.Value, false, false, out dummy))
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_SourceContainsDuplicateKeys"));
+ }
+ }
+
+ if (m_budget == 0)
+ {
+ m_budget = m_tables.m_buckets.Length / m_tables.m_locks.Length;
+ }
+
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// class that is empty, has the specified concurrency level, has the specified initial capacity, and
+ /// uses the specified <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>.
+ /// </summary>
+ /// <param name="concurrencyLevel">The estimated number of threads that will update the
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/> concurrently.</param>
+ /// <param name="capacity">The initial number of elements that the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// can contain.</param>
+ /// <param name="comparer">The <see cref="T:System.Collections.Generic.IEqualityComparer{TKey}"/>
+ /// implementation to use when comparing keys.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="concurrencyLevel"/> is less than 1. -or-
+ /// <paramref name="capacity"/> is less than 0.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="comparer"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ public ConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer)
+ : this(concurrencyLevel, capacity, false, comparer)
+ {
+ }
+
+ internal ConcurrentDictionary(int concurrencyLevel, int capacity, bool growLockArray, IEqualityComparer<TKey> comparer)
+ {
+ if (concurrencyLevel < 1)
+ {
+ throw new ArgumentOutOfRangeException("concurrencyLevel", GetResource("ConcurrentDictionary_ConcurrencyLevelMustBePositive"));
+ }
+ if (capacity < 0)
+ {
+ throw new ArgumentOutOfRangeException("capacity", GetResource("ConcurrentDictionary_CapacityMustNotBeNegative"));
+ }
+ if (comparer == null) throw new ArgumentNullException("comparer");
+
+ // The capacity should be at least as large as the concurrency level. Otherwise, we would have locks that don't guard
+ // any buckets.
+ if (capacity < concurrencyLevel)
+ {
+ capacity = concurrencyLevel;
+ }
+
+ object[] locks = new object[concurrencyLevel];
+ for (int i = 0; i < locks.Length; i++)
+ {
+ locks[i] = new object();
+ }
+
+ int[] countPerLock = new int[locks.Length];
+ Node[] buckets = new Node[capacity];
+ m_tables = new Tables(buckets, locks, countPerLock, comparer);
+
+ m_growLockArray = growLockArray;
+ m_budget = buckets.Length / locks.Length;
+ }
+
+
+ /// <summary>
+ /// Attempts to add the specified key and value to the <see cref="ConcurrentDictionary{TKey,
+ /// TValue}"/>.
+ /// </summary>
+ /// <param name="key">The key of the element to add.</param>
+ /// <param name="value">The value of the element to add. The value can be a null reference (Nothing
+ /// in Visual Basic) for reference types.</param>
+ /// <returns>true if the key/value pair was added to the <see cref="ConcurrentDictionary{TKey,
+ /// TValue}"/>
+ /// successfully; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The <see cref="ConcurrentDictionary{TKey, TValue}"/>
+ /// contains too many elements.</exception>
+ public bool TryAdd(TKey key, TValue value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ TValue dummy;
+ return TryAddInternal(key, value, false, true, out dummy);
+ }
+
+ /// <summary>
+ /// Determines whether the <see cref="ConcurrentDictionary{TKey, TValue}"/> contains the specified
+ /// key.
+ /// </summary>
+ /// <param name="key">The key to locate in the <see cref="ConcurrentDictionary{TKey,
+ /// TValue}"/>.</param>
+ /// <returns>true if the <see cref="ConcurrentDictionary{TKey, TValue}"/> contains an element with
+ /// the specified key; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ public bool ContainsKey(TKey key)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ TValue throwAwayValue;
+ return TryGetValue(key, out throwAwayValue);
+ }
+
+ /// <summary>
+ /// Attempts to remove and return the the value with the specified key from the
+ /// <see cref="ConcurrentDictionary{TKey, TValue}"/>.
+ /// </summary>
+ /// <param name="key">The key of the element to remove and return.</param>
+ /// <param name="value">When this method returns, <paramref name="value"/> contains the object removed from the
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/> or the default value of <typeparamref
+ /// name="TValue"/>
+ /// if the operation failed.</param>
+ /// <returns>true if an object was removed successfully; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ public bool TryRemove(TKey key, out TValue value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ return TryRemoveInternal(key, out value, false, default(TValue));
+ }
+
+ /// <summary>
+ /// Removes the specified key from the dictionary if it exists and returns its associated value.
+ /// If matchValue flag is set, the key will be removed only if is associated with a particular
+ /// value.
+ /// </summary>
+ /// <param name="key">The key to search for and remove if it exists.</param>
+ /// <param name="value">The variable into which the removed value, if found, is stored.</param>
+ /// <param name="matchValue">Whether removal of the key is conditional on its value.</param>
+ /// <param name="oldValue">The conditional value to compare against if <paramref name="matchValue"/> is true</param>
+ /// <returns></returns>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ private bool TryRemoveInternal(TKey key, out TValue value, bool matchValue, TValue oldValue)
+ {
+ while (true)
+ {
+ Tables tables = m_tables;
+
+ IEqualityComparer<TKey> comparer = tables.m_comparer;
+
+ int bucketNo, lockNo;
+ GetBucketAndLockNo(comparer.GetHashCode(key), out bucketNo, out lockNo, tables.m_buckets.Length, tables.m_locks.Length);
+
+ lock (tables.m_locks[lockNo])
+ {
+ // If the table just got resized, we may not be holding the right lock, and must retry.
+ // This should be a rare occurence.
+ if (tables != m_tables)
+ {
+ continue;
+ }
+
+ Node prev = null;
+ for (Node curr = tables.m_buckets[bucketNo]; curr != null; curr = curr.m_next)
+ {
+ Assert((prev == null && curr == tables.m_buckets[bucketNo]) || prev.m_next == curr);
+
+ if (comparer.Equals(curr.m_key, key))
+ {
+ if (matchValue)
+ {
+ bool valuesMatch = EqualityComparer<TValue>.Default.Equals(oldValue, curr.m_value);
+ if (!valuesMatch)
+ {
+ value = default(TValue);
+ return false;
+ }
+ }
+
+ if (prev == null)
+ {
+ Volatile.Write<Node>(ref tables.m_buckets[bucketNo], curr.m_next);
+ }
+ else
+ {
+ prev.m_next = curr.m_next;
+ }
+
+ value = curr.m_value;
+ tables.m_countPerLock[lockNo]--;
+ return true;
+ }
+ prev = curr;
+ }
+ }
+
+ value = default(TValue);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Attempts to get the value associated with the specified key from the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <param name="key">The key of the value to get.</param>
+ /// <param name="value">When this method returns, <paramref name="value"/> contains the object from
+ /// the
+ /// <see cref="ConcurrentDictionary{TKey,TValue}"/> with the specified key or the default value of
+ /// <typeparamref name="TValue"/>, if the operation failed.</param>
+ /// <returns>true if the key was found in the <see cref="ConcurrentDictionary{TKey,TValue}"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ int bucketNo, lockNoUnused;
+
+ // We must capture the m_buckets field in a local variable. It is set to a new table on each table resize.
+ Tables tables = m_tables;
+ IEqualityComparer<TKey> comparer = tables.m_comparer;
+ GetBucketAndLockNo(comparer.GetHashCode(key), out bucketNo, out lockNoUnused, tables.m_buckets.Length, tables.m_locks.Length);
+
+ // We can get away w/out a lock here.
+ // The Volatile.Read ensures that the load of the fields of 'n' doesn't move before the load from buckets[i].
+ Node n = Volatile.Read<Node>(ref tables.m_buckets[bucketNo]);
+
+ while (n != null)
+ {
+ if (comparer.Equals(n.m_key, key))
+ {
+ value = n.m_value;
+ return true;
+ }
+ n = n.m_next;
+ }
+
+ value = default(TValue);
+ return false;
+ }
+
+ /// <summary>
+ /// Compares the existing value for the specified key with a specified value, and if they're equal,
+ /// updates the key with a third value.
+ /// </summary>
+ /// <param name="key">The key whose value is compared with <paramref name="comparisonValue"/> and
+ /// possibly replaced.</param>
+ /// <param name="newValue">The value that replaces the value of the element with <paramref
+ /// name="key"/> if the comparison results in equality.</param>
+ /// <param name="comparisonValue">The value that is compared to the value of the element with
+ /// <paramref name="key"/>.</param>
+ /// <returns>true if the value with <paramref name="key"/> was equal to <paramref
+ /// name="comparisonValue"/> and replaced with <paramref name="newValue"/>; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null
+ /// reference.</exception>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ IEqualityComparer<TValue> valueComparer = EqualityComparer<TValue>.Default;
+
+ while (true)
+ {
+ int bucketNo;
+ int lockNo;
+ int hashcode;
+
+ Tables tables = m_tables;
+ IEqualityComparer<TKey> comparer = tables.m_comparer;
+
+ hashcode = comparer.GetHashCode(key);
+ GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables.m_buckets.Length, tables.m_locks.Length);
+
+ lock (tables.m_locks[lockNo])
+ {
+ // If the table just got resized, we may not be holding the right lock, and must retry.
+ // This should be a rare occurence.
+ if (tables != m_tables)
+ {
+ continue;
+ }
+
+ // Try to find this key in the bucket
+ Node prev = null;
+ for (Node node = tables.m_buckets[bucketNo]; node != null; node = node.m_next)
+ {
+ Assert((prev == null && node == tables.m_buckets[bucketNo]) || prev.m_next == node);
+ if (comparer.Equals(node.m_key, key))
+ {
+ if (valueComparer.Equals(node.m_value, comparisonValue))
+ {
+ if (s_isValueWriteAtomic)
+ {
+ node.m_value = newValue;
+ }
+ else
+ {
+ Node newNode = new Node(node.m_key, newValue, hashcode, node.m_next);
+
+ if (prev == null)
+ {
+ tables.m_buckets[bucketNo] = newNode;
+ }
+ else
+ {
+ prev.m_next = newNode;
+ }
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ prev = node;
+ }
+
+ //didn't find the key
+ return false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Removes all keys and values from the <see cref="ConcurrentDictionary{TKey,TValue}"/>.
+ /// </summary>
+ public void Clear()
+ {
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+
+ Tables newTables = new Tables(new Node[DEFAULT_CAPACITY], m_tables.m_locks, new int[m_tables.m_countPerLock.Length], m_tables.m_comparer);
+ m_tables = newTables;
+ m_budget = Math.Max(1, newTables.m_buckets.Length / newTables.m_locks.Length);
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection"/> to an array of
+ /// type <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>, starting at the
+ /// specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional array of type <see
+ /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
+ /// that is the destination of the <see
+ /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/> elements copied from the <see
+ /// cref="T:System.Collections.ICollection"/>. The array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// 0.</exception>
+ /// <exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than
+ /// the length of the <paramref name="array"/>. -or- The number of elements in the source <see
+ /// cref="T:System.Collections.ICollection"/>
+ /// is greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>.</exception>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
+ {
+ if (array == null) throw new ArgumentNullException("array");
+ if (index < 0) throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative"));
+
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+
+ int count = 0;
+
+ for (int i = 0; i < m_tables.m_locks.Length && count >= 0; i++)
+ {
+ count += m_tables.m_countPerLock[i];
+ }
+
+ if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough"));
+ }
+
+ CopyToPairs(array, index);
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Copies the key and value pairs stored in the <see cref="ConcurrentDictionary{TKey,TValue}"/> to a
+ /// new array.
+ /// </summary>
+ /// <returns>A new array containing a snapshot of key and value pairs copied from the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ public KeyValuePair<TKey, TValue>[] ToArray()
+ {
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+ int count = 0;
+ checked
+ {
+ for (int i = 0; i < m_tables.m_locks.Length; i++)
+ {
+ count += m_tables.m_countPerLock[i];
+ }
+ }
+
+ KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[count];
+
+ CopyToPairs(array, 0);
+ return array;
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
+ ///
+ /// Important: the caller must hold all locks in m_locks before calling CopyToPairs.
+ /// </summary>
+ private void CopyToPairs(KeyValuePair<TKey, TValue>[] array, int index)
+ {
+ Node[] buckets = m_tables.m_buckets;
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ for (Node current = buckets[i]; current != null; current = current.m_next)
+ {
+ array[index] = new KeyValuePair<TKey, TValue>(current.m_key, current.m_value);
+ index++; //this should never flow, CopyToPairs is only called when there's no overflow risk
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
+ ///
+ /// Important: the caller must hold all locks in m_locks before calling CopyToEntries.
+ /// </summary>
+ private void CopyToEntries(DictionaryEntry[] array, int index)
+ {
+ Node[] buckets = m_tables.m_buckets;
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ for (Node current = buckets[i]; current != null; current = current.m_next)
+ {
+ array[index] = new DictionaryEntry(current.m_key, current.m_value);
+ index++; //this should never flow, CopyToEntries is only called when there's no overflow risk
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copy dictionary contents to an array - shared implementation between ToArray and CopyTo.
+ ///
+ /// Important: the caller must hold all locks in m_locks before calling CopyToObjects.
+ /// </summary>
+ private void CopyToObjects(object[] array, int index)
+ {
+ Node[] buckets = m_tables.m_buckets;
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ for (Node current = buckets[i]; current != null; current = current.m_next)
+ {
+ array[index] = new KeyValuePair<TKey, TValue>(current.m_key, current.m_value);
+ index++; //this should never flow, CopyToObjects is only called when there's no overflow risk
+ }
+ }
+ }
+
+ /// <summary>Returns an enumerator that iterates through the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.</summary>
+ /// <returns>An enumerator for the <see cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
+ /// <remarks>
+ /// The enumerator returned from the dictionary is safe to use concurrently with
+ /// reads and writes to the dictionary, however it does not represent a moment-in-time snapshot
+ /// of the dictionary. The contents exposed through the enumerator may contain modifications
+ /// made to the dictionary after <see cref="GetEnumerator"/> was called.
+ /// </remarks>
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+ {
+ Node[] buckets = m_tables.m_buckets;
+
+ for (int i = 0; i < buckets.Length; i++)
+ {
+ // The Volatile.Read ensures that the load of the fields of 'current' doesn't move before the load from buckets[i].
+ Node current = Volatile.Read<Node>(ref buckets[i]);
+
+ while (current != null)
+ {
+ yield return new KeyValuePair<TKey, TValue>(current.m_key, current.m_value);
+ current = current.m_next;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Shared internal implementation for inserts and updates.
+ /// If key exists, we always return false; and if updateIfExists == true we force update with value;
+ /// If key doesn't exist, we always add value and return true;
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
+ {
+ while (true)
+ {
+ int bucketNo, lockNo;
+ int hashcode;
+
+ Tables tables = m_tables;
+ IEqualityComparer<TKey> comparer = tables.m_comparer;
+ hashcode = comparer.GetHashCode(key);
+ GetBucketAndLockNo(hashcode, out bucketNo, out lockNo, tables.m_buckets.Length, tables.m_locks.Length);
+
+ bool resizeDesired = false;
+ bool lockTaken = false;
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ bool resizeDueToCollisions = false;
+#endif // !FEATURE_CORECLR
+#endif
+
+ try
+ {
+ if (acquireLock)
+ Monitor.Enter(tables.m_locks[lockNo], ref lockTaken);
+
+ // If the table just got resized, we may not be holding the right lock, and must retry.
+ // This should be a rare occurence.
+ if (tables != m_tables)
+ {
+ continue;
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ int collisionCount = 0;
+#endif // !FEATURE_CORECLR
+#endif
+
+ // Try to find this key in the bucket
+ Node prev = null;
+ for (Node node = tables.m_buckets[bucketNo]; node != null; node = node.m_next)
+ {
+ Assert((prev == null && node == tables.m_buckets[bucketNo]) || prev.m_next == node);
+ if (comparer.Equals(node.m_key, key))
+ {
+ // The key was found in the dictionary. If updates are allowed, update the value for that key.
+ // We need to create a new node for the update, in order to support TValue types that cannot
+ // be written atomically, since lock-free reads may be happening concurrently.
+ if (updateIfExists)
+ {
+ if (s_isValueWriteAtomic)
+ {
+ node.m_value = value;
+ }
+ else
+ {
+ Node newNode = new Node(node.m_key, value, hashcode, node.m_next);
+ if (prev == null)
+ {
+ tables.m_buckets[bucketNo] = newNode;
+ }
+ else
+ {
+ prev.m_next = newNode;
+ }
+ }
+ resultingValue = value;
+ }
+ else
+ {
+ resultingValue = node.m_value;
+ }
+ return false;
+ }
+ prev = node;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ collisionCount++;
+#endif // !FEATURE_CORECLR
+#endif
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer))
+ {
+ resizeDesired = true;
+ resizeDueToCollisions = true;
+ }
+#endif // !FEATURE_CORECLR
+#endif
+
+ // The key was not found in the bucket. Insert the key-value pair.
+ Volatile.Write<Node>(ref tables.m_buckets[bucketNo], new Node(key, value, hashcode, tables.m_buckets[bucketNo]));
+ checked
+ {
+ tables.m_countPerLock[lockNo]++;
+ }
+
+ //
+ // If the number of elements guarded by this lock has exceeded the budget, resize the bucket table.
+ // It is also possible that GrowTable will increase the budget but won't resize the bucket table.
+ // That happens if the bucket table is found to be poorly utilized due to a bad hash function.
+ //
+ if (tables.m_countPerLock[lockNo] > m_budget)
+ {
+ resizeDesired = true;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ Monitor.Exit(tables.m_locks[lockNo]);
+ }
+
+ //
+ // The fact that we got here means that we just performed an insertion. If necessary, we will grow the table.
+ //
+ // Concurrency notes:
+ // - Notice that we are not holding any locks at when calling GrowTable. This is necessary to prevent deadlocks.
+ // - As a result, it is possible that GrowTable will be called unnecessarily. But, GrowTable will obtain lock 0
+ // and then verify that the table we passed to it as the argument is still the current table.
+ //
+ if (resizeDesired)
+ {
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ if (resizeDueToCollisions)
+ {
+ GrowTable(tables, (IEqualityComparer<TKey>)HashHelpers.GetRandomizedEqualityComparer(comparer), true, m_keyRehashCount);
+ }
+ else
+#endif // !FEATURE_CORECLR
+ {
+ GrowTable(tables, tables.m_comparer, false, m_keyRehashCount);
+ }
+#else
+ GrowTable(tables, tables.m_comparer, false, m_keyRehashCount);
+#endif
+ }
+
+ resultingValue = value;
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the value associated with the specified key.
+ /// </summary>
+ /// <param name="key">The key of the value to get or set.</param>
+ /// <value>The value associated with the specified key. If the specified key is not found, a get
+ /// operation throws a
+ /// <see cref="T:Sytem.Collections.Generic.KeyNotFoundException"/>, and a set operation creates a new
+ /// element with the specified key.</value>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">The property is retrieved and
+ /// <paramref name="key"/>
+ /// does not exist in the collection.</exception>
+ public TValue this[TKey key]
+ {
+ get
+ {
+ TValue value;
+ if (!TryGetValue(key, out value))
+ {
+ throw new KeyNotFoundException();
+ }
+ return value;
+ }
+ set
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ TValue dummy;
+ TryAddInternal(key, value, true, true, out dummy);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of key/value pairs contained in the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <value>The number of key/value paris contained in the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.</value>
+ /// <remarks>Count has snapshot semantics and represents the number of items in the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// at the moment when Count was accessed.</remarks>
+ public int Count
+ {
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ get
+ {
+ int count = 0;
+
+ int acquiredLocks = 0;
+ try
+ {
+ // Acquire all locks
+ AcquireAllLocks(ref acquiredLocks);
+
+ // Compute the count, we allow overflow
+ for (int i = 0; i < m_tables.m_countPerLock.Length; i++)
+ {
+ count += m_tables.m_countPerLock[i];
+ }
+
+ }
+ finally
+ {
+ // Release locks that have been acquired earlier
+ ReleaseLocks(0, acquiredLocks);
+ }
+
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// if the key does not already exist.
+ /// </summary>
+ /// <param name="key">The key of the element to add.</param>
+ /// <param name="valueFactory">The function used to generate a value for the key</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="valueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The value for the key. This will be either the existing value for the key if the
+ /// key is already in the dictionary, or the new value for the key as returned by valueFactory
+ /// if the key was not in the dictionary.</returns>
+ public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ if (valueFactory == null) throw new ArgumentNullException("valueFactory");
+
+ TValue resultingValue;
+ if (TryGetValue(key, out resultingValue))
+ {
+ return resultingValue;
+ }
+ TryAddInternal(key, valueFactory(key), false, true, out resultingValue);
+ return resultingValue;
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/>
+ /// if the key does not already exist.
+ /// </summary>
+ /// <param name="key">The key of the element to add.</param>
+ /// <param name="value">the value to be added, if the key does not already exist</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The value for the key. This will be either the existing value for the key if the
+ /// key is already in the dictionary, or the new value if the key was not in the dictionary.</returns>
+ public TValue GetOrAdd(TKey key, TValue value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ TValue resultingValue;
+ TryAddInternal(key, value, false, true, out resultingValue);
+ return resultingValue;
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already
+ /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key
+ /// already exists.
+ /// </summary>
+ /// <param name="key">The key to be added or whose value should be updated</param>
+ /// <param name="addValueFactory">The function used to generate a value for an absent key</param>
+ /// <param name="updateValueFactory">The function used to generate a new value for an existing key
+ /// based on the key's existing value</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="addValueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was
+ /// absent) or the result of updateValueFactory (if the key was present).</returns>
+ public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ if (addValueFactory == null) throw new ArgumentNullException("addValueFactory");
+ if (updateValueFactory == null) throw new ArgumentNullException("updateValueFactory");
+
+ TValue newValue, resultingValue;
+ while (true)
+ {
+ TValue oldValue;
+ if (TryGetValue(key, out oldValue))
+ //key exists, try to update
+ {
+ newValue = updateValueFactory(key, oldValue);
+ if (TryUpdate(key, newValue, oldValue))
+ {
+ return newValue;
+ }
+ }
+ else //try add
+ {
+ newValue = addValueFactory(key);
+ if (TryAddInternal(key, newValue, false, true, out resultingValue))
+ {
+ return resultingValue;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Adds a key/value pair to the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key does not already
+ /// exist, or updates a key/value pair in the <see cref="ConcurrentDictionary{TKey,TValue}"/> if the key
+ /// already exists.
+ /// </summary>
+ /// <param name="key">The key to be added or whose value should be updated</param>
+ /// <param name="addValue">The value to be added for an absent key</param>
+ /// <param name="updateValueFactory">The function used to generate a new value for an existing key based on
+ /// the key's existing value</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="updateValueFactory"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <returns>The new value for the key. This will be either be the result of addValueFactory (if the key was
+ /// absent) or the result of updateValueFactory (if the key was present).</returns>
+ public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ if (updateValueFactory == null) throw new ArgumentNullException("updateValueFactory");
+ TValue newValue, resultingValue;
+ while (true)
+ {
+ TValue oldValue;
+ if (TryGetValue(key, out oldValue))
+ //key exists, try to update
+ {
+ newValue = updateValueFactory(key, oldValue);
+ if (TryUpdate(key, newValue, oldValue))
+ {
+ return newValue;
+ }
+ }
+ else //try add
+ {
+ if (TryAddInternal(key, addValue, false, true, out resultingValue))
+ {
+ return resultingValue;
+ }
+ }
+ }
+ }
+
+
+
+ /// <summary>
+ /// Gets a value that indicates whether the <see cref="ConcurrentDictionary{TKey,TValue}"/> is empty.
+ /// </summary>
+ /// <value>true if the <see cref="ConcurrentDictionary{TKey,TValue}"/> is empty; otherwise,
+ /// false.</value>
+ public bool IsEmpty
+ {
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ get
+ {
+ int acquiredLocks = 0;
+ try
+ {
+ // Acquire all locks
+ AcquireAllLocks(ref acquiredLocks);
+
+ for (int i = 0; i < m_tables.m_countPerLock.Length; i++)
+ {
+ if (m_tables.m_countPerLock[i] != 0)
+ {
+ return false;
+ }
+ }
+ }
+ finally
+ {
+ // Release locks that have been acquired earlier
+ ReleaseLocks(0, acquiredLocks);
+ }
+
+ return true;
+ }
+ }
+
+ #region IDictionary<TKey,TValue> members
+
+ /// <summary>
+ /// Adds the specified key and value to the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <param name="key">The object to use as the key of the element to add.</param>
+ /// <param name="value">The object to use as the value of the element to add.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// An element with the same key already exists in the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.</exception>
+ void IDictionary<TKey, TValue>.Add(TKey key, TValue value)
+ {
+ if (!TryAdd(key, value))
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_KeyAlreadyExisted"));
+ }
+ }
+
+ /// <summary>
+ /// Removes the element with the specified key from the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <param name="key">The key of the element to remove.</param>
+ /// <returns>true if the element is successfully remove; otherwise false. This method also returns
+ /// false if
+ /// <paramref name="key"/> was not found in the original <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ bool IDictionary<TKey, TValue>.Remove(TKey key)
+ {
+ TValue throwAwayValue;
+ return TryRemove(key, out throwAwayValue);
+ }
+
+ /// <summary>
+ /// Gets a collection containing the keys in the <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.Generic.ICollection{TKey}"/> containing the keys in the
+ /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</value>
+ public ICollection<TKey> Keys
+ {
+ get { return GetKeys(); }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="T:System.Collections.Generic.IEnumerable{TKey}"/> containing the keys of
+ /// the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.Generic.IEnumerable{TKey}"/> containing the keys of
+ /// the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.</value>
+ IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys
+ {
+ get { return GetKeys(); }
+ }
+
+ /// <summary>
+ /// Gets a collection containing the values in the <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.Generic.ICollection{TValue}"/> containing the values in
+ /// the
+ /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</value>
+ public ICollection<TValue> Values
+ {
+ get { return GetValues(); }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="T:System.Collections.Generic.IEnumerable{TValue}"/> containing the values
+ /// in the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.Generic.IEnumerable{TValue}"/> containing the
+ /// values in the <see cref="T:System.Collections.Generic.IReadOnlyDictionary{TKey,TValue}"/>.</value>
+ IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values
+ {
+ get { return GetValues(); }
+ }
+ #endregion
+
+ #region ICollection<KeyValuePair<TKey,TValue>> Members
+
+ /// <summary>
+ /// Adds the specified value to the <see cref="T:System.Collections.Generic.ICollection{TValue}"/>
+ /// with the specified key.
+ /// </summary>
+ /// <param name="keyValuePair">The <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
+ /// structure representing the key and value to add to the <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="keyValuePair"/> of <paramref
+ /// name="keyValuePair"/> is null.</exception>
+ /// <exception cref="T:System.OverflowException">The <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>
+ /// contains too many elements.</exception>
+ /// <exception cref="T:System.ArgumentException">An element with the same key already exists in the
+ /// <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/></exception>
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair)
+ {
+ ((IDictionary<TKey, TValue>)this).Add(keyValuePair.Key, keyValuePair.Value);
+ }
+
+ /// <summary>
+ /// Determines whether the <see cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/>
+ /// contains a specific key and value.
+ /// </summary>
+ /// <param name="keyValuePair">The <see cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
+ /// structure to locate in the <see
+ /// cref="T:System.Collections.Generic.ICollection{TValue}"/>.</param>
+ /// <returns>true if the <paramref name="keyValuePair"/> is found in the <see
+ /// cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/>; otherwise, false.</returns>
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair)
+ {
+ TValue value;
+ if (!TryGetValue(keyValuePair.Key, out value))
+ {
+ return false;
+ }
+ return EqualityComparer<TValue>.Default.Equals(value, keyValuePair.Value);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the dictionary is read-only.
+ /// </summary>
+ /// <value>true if the <see cref="T:System.Collections.Generic.ICollection{TKey,TValue}"/> is
+ /// read-only; otherwise, false. For <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>, this property always returns
+ /// false.</value>
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Removes a key and value from the dictionary.
+ /// </summary>
+ /// <param name="keyValuePair">The <see
+ /// cref="T:System.Collections.Generic.KeyValuePair{TKey,TValue}"/>
+ /// structure representing the key and value to remove from the <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.</param>
+ /// <returns>true if the key and value represented by <paramref name="keyValuePair"/> is successfully
+ /// found and removed; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The Key property of <paramref
+ /// name="keyValuePair"/> is a null reference (Nothing in Visual Basic).</exception>
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair)
+ {
+ if (keyValuePair.Key == null) throw new ArgumentNullException(GetResource("ConcurrentDictionary_ItemKeyIsNull"));
+
+ TValue throwAwayValue;
+ return TryRemoveInternal(keyValuePair.Key, out throwAwayValue, true, keyValuePair.Value);
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ /// <summary>Returns an enumerator that iterates through the <see
+ /// cref="ConcurrentDictionary{TKey,TValue}"/>.</summary>
+ /// <returns>An enumerator for the <see cref="ConcurrentDictionary{TKey,TValue}"/>.</returns>
+ /// <remarks>
+ /// The enumerator returned from the dictionary is safe to use concurrently with
+ /// reads and writes to the dictionary, however it does not represent a moment-in-time snapshot
+ /// of the dictionary. The contents exposed through the enumerator may contain modifications
+ /// made to the dictionary after <see cref="GetEnumerator"/> was called.
+ /// </remarks>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((ConcurrentDictionary<TKey, TValue>)this).GetEnumerator();
+ }
+
+ #endregion
+
+ #region IDictionary Members
+
+ /// <summary>
+ /// Adds the specified key and value to the dictionary.
+ /// </summary>
+ /// <param name="key">The object to use as the key.</param>
+ /// <param name="value">The object to use as the value.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.OverflowException">The dictionary contains too many
+ /// elements.</exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// <paramref name="key"/> is of a type that is not assignable to the key type <typeparamref
+ /// name="TKey"/> of the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>. -or-
+ /// <paramref name="value"/> is of a type that is not assignable to <typeparamref name="TValue"/>,
+ /// the type of values in the <see cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
+ /// -or- A value with the same key already exists in the <see
+ /// cref="T:System.Collections.Generic.Dictionary{TKey,TValue}"/>.
+ /// </exception>
+ void IDictionary.Add(object key, object value)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+ if (!(key is TKey)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect"));
+
+ TValue typedValue;
+ try
+ {
+ typedValue = (TValue)value;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));
+ }
+
+ ((IDictionary<TKey, TValue>)this).Add((TKey)key, typedValue);
+ }
+
+ /// <summary>
+ /// Gets whether the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> contains an
+ /// element with the specified key.
+ /// </summary>
+ /// <param name="key">The key to locate in the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</param>
+ /// <returns>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> contains
+ /// an element with the specified key; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentNullException"> <paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ bool IDictionary.Contains(object key)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ return (key is TKey) && ((ConcurrentDictionary<TKey, TValue>)this).ContainsKey((TKey)key);
+ }
+
+ /// <summary>Provides an <see cref="T:System.Collections.Generics.IDictionaryEnumerator"/> for the
+ /// <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</summary>
+ /// <returns>An <see cref="T:System.Collections.Generics.IDictionaryEnumerator"/> for the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</returns>
+ IDictionaryEnumerator IDictionary.GetEnumerator()
+ {
+ return new DictionaryEnumerator(this);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> has a fixed size.
+ /// </summary>
+ /// <value>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> has a
+ /// fixed size; otherwise, false. For <see
+ /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always
+ /// returns false.</value>
+ bool IDictionary.IsFixedSize
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> is read-only.
+ /// </summary>
+ /// <value>true if the <see cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/> is
+ /// read-only; otherwise, false. For <see
+ /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>, this property always
+ /// returns false.</value>
+ bool IDictionary.IsReadOnly
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="T:System.Collections.ICollection"/> containing the keys of the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.ICollection"/> containing the keys of the <see
+ /// cref="T:System.Collections.Generic.IDictionary{TKey,TValue}"/>.</value>
+ ICollection IDictionary.Keys
+ {
+ get { return GetKeys(); }
+ }
+
+ /// <summary>
+ /// Removes the element with the specified key from the <see
+ /// cref="T:System.Collections.IDictionary"/>.
+ /// </summary>
+ /// <param name="key">The key of the element to remove.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ void IDictionary.Remove(object key)
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ TValue throwAwayValue;
+ if (key is TKey)
+ {
+ this.TryRemove((TKey)key, out throwAwayValue);
+ }
+ }
+
+ /// <summary>
+ /// Gets an <see cref="T:System.Collections.ICollection"/> containing the values in the <see
+ /// cref="T:System.Collections.IDictionary"/>.
+ /// </summary>
+ /// <value>An <see cref="T:System.Collections.ICollection"/> containing the values in the <see
+ /// cref="T:System.Collections.IDictionary"/>.</value>
+ ICollection IDictionary.Values
+ {
+ get { return GetValues(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the value associated with the specified key.
+ /// </summary>
+ /// <param name="key">The key of the value to get or set.</param>
+ /// <value>The value associated with the specified key, or a null reference (Nothing in Visual Basic)
+ /// if <paramref name="key"/> is not in the dictionary or <paramref name="key"/> is of a type that is
+ /// not assignable to the key type <typeparamref name="TKey"/> of the <see
+ /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>.</value>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="key"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// A value is being assigned, and <paramref name="key"/> is of a type that is not assignable to the
+ /// key type <typeparamref name="TKey"/> of the <see
+ /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>. -or- A value is being
+ /// assigned, and <paramref name="key"/> is of a type that is not assignable to the value type
+ /// <typeparamref name="TValue"/> of the <see
+ /// cref="T:System.Collections.Generic.ConcurrentDictionary{TKey,TValue}"/>
+ /// </exception>
+ object IDictionary.this[object key]
+ {
+ get
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ TValue value;
+ if (key is TKey && this.TryGetValue((TKey)key, out value))
+ {
+ return value;
+ }
+
+ return null;
+ }
+ set
+ {
+ if (key == null) throw new ArgumentNullException("key");
+
+ if (!(key is TKey)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfKeyIncorrect"));
+ if (!(value is TValue)) throw new ArgumentException(GetResource("ConcurrentDictionary_TypeOfValueIncorrect"));
+
+ ((ConcurrentDictionary<TKey, TValue>)this)[(TKey)key] = (TValue)value;
+ }
+ }
+
+ #endregion
+
+ #region ICollection Members
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an array, starting
+ /// at the specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional array that is the destination of the elements copied from
+ /// the <see cref="T:System.Collections.ICollection"/>. The array must have zero-based
+ /// indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="array"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// 0.</exception>
+ /// <exception cref="T:System.ArgumentException"><paramref name="index"/> is equal to or greater than
+ /// the length of the <paramref name="array"/>. -or- The number of elements in the source <see
+ /// cref="T:System.Collections.ICollection"/>
+ /// is greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>.</exception>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ void ICollection.CopyTo(Array array, int index)
+ {
+ if (array == null) throw new ArgumentNullException("array");
+ if (index < 0) throw new ArgumentOutOfRangeException("index", GetResource("ConcurrentDictionary_IndexIsNegative"));
+
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+ Tables tables = m_tables;
+
+ int count = 0;
+
+ for (int i = 0; i < tables.m_locks.Length && count >= 0; i++)
+ {
+ count += tables.m_countPerLock[i];
+ }
+
+ if (array.Length - count < index || count < 0) //"count" itself or "count + index" can overflow
+ {
+ throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayNotLargeEnough"));
+ }
+
+ // To be consistent with the behavior of ICollection.CopyTo() in Dictionary<TKey,TValue>,
+ // we recognize three types of target arrays:
+ // - an array of KeyValuePair<TKey, TValue> structs
+ // - an array of DictionaryEntry structs
+ // - an array of objects
+
+ KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
+ if (pairs != null)
+ {
+ CopyToPairs(pairs, index);
+ return;
+ }
+
+ DictionaryEntry[] entries = array as DictionaryEntry[];
+ if (entries != null)
+ {
+ CopyToEntries(entries, index);
+ return;
+ }
+
+ object[] objects = array as object[];
+ if (objects != null)
+ {
+ CopyToObjects(objects, index);
+ return;
+ }
+
+ throw new ArgumentException(GetResource("ConcurrentDictionary_ArrayIncorrectType"), "array");
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is
+ /// synchronized with the SyncRoot.
+ /// </summary>
+ /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
+ /// (thread safe); otherwise, false. For <see
+ /// cref="T:System.Collections.Concurrent.ConcurrentDictionary{TKey,TValue}"/>, this property always
+ /// returns false.</value>
+ bool ICollection.IsSynchronized
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see
+ /// cref="T:System.Collections.ICollection"/>. This property is not supported.
+ /// </summary>
+ /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
+ }
+ }
+
+ #endregion
+
+ /// <summary>
+ /// Replaces the bucket table with a larger one. To prevent multiple threads from resizing the
+ /// table as a result of a race condition, the Tables instance that holds the table of buckets deemed too
+ /// small is passed in as an argument to GrowTable(). GrowTable() obtains a lock, and then checks
+ /// the Tables instance has been replaced in the meantime or not.
+ /// The <paramref name="rehashCount"/> will be used to ensure that we don't do two subsequent resizes
+ /// because of a collision
+ /// </summary>
+ private void GrowTable(Tables tables, IEqualityComparer<TKey> newComparer, bool regenerateHashKeys, int rehashCount)
+ {
+ int locksAcquired = 0;
+ try
+ {
+ // The thread that first obtains m_locks[0] will be the one doing the resize operation
+ AcquireLocks(0, 1, ref locksAcquired);
+
+ if (regenerateHashKeys && rehashCount == m_keyRehashCount)
+ {
+ // This method is called with regenerateHashKeys==true when we detected
+ // more than HashHelpers.HashCollisionThreshold collisions when adding a new element.
+ // In that case we are in the process of switching to another (randomized) comparer
+ // and we have to re-hash all the keys in the table.
+ // We are only going to do this if we did not just rehash the entire table while waiting for the lock
+ tables = m_tables;
+ }
+ else
+ {
+ // If we don't require a regeneration of hash keys we want to make sure we don't do work when
+ // we don't have to
+ if (tables != m_tables)
+ {
+ // We assume that since the table reference is different, it was already resized (or the budget
+ // was adjusted). If we ever decide to do table shrinking, or replace the table for other reasons,
+ // we will have to revisit this logic.
+ return;
+ }
+
+ // Compute the (approx.) total size. Use an Int64 accumulation variable to avoid an overflow.
+ long approxCount = 0;
+ for (int i = 0; i < tables.m_countPerLock.Length; i++)
+ {
+ approxCount += tables.m_countPerLock[i];
+ }
+
+ //
+ // If the bucket array is too empty, double the budget instead of resizing the table
+ //
+ if (approxCount < tables.m_buckets.Length / 4)
+ {
+ m_budget = 2 * m_budget;
+ if (m_budget < 0)
+ {
+ m_budget = int.MaxValue;
+ }
+
+ return;
+ }
+ }
+ // Compute the new table size. We find the smallest integer larger than twice the previous table size, and not divisible by
+ // 2,3,5 or 7. We can consider a different table-sizing policy in the future.
+ int newLength = 0;
+ bool maximizeTableSize = false;
+ try
+ {
+ checked
+ {
+ // Double the size of the buckets table and add one, so that we have an odd integer.
+ newLength = tables.m_buckets.Length * 2 + 1;
+
+ // Now, we only need to check odd integers, and find the first that is not divisible
+ // by 3, 5 or 7.
+ while (newLength % 3 == 0 || newLength % 5 == 0 || newLength % 7 == 0)
+ {
+ newLength += 2;
+ }
+
+ Assert(newLength % 2 != 0);
+
+ if (newLength > Array.MaxArrayLength)
+ {
+ maximizeTableSize = true;
+ }
+ }
+ }
+ catch (OverflowException)
+ {
+ maximizeTableSize = true;
+ }
+
+ if (maximizeTableSize)
+ {
+ newLength = Array.MaxArrayLength;
+
+ // We want to make sure that GrowTable will not be called again, since table is at the maximum size.
+ // To achieve that, we set the budget to int.MaxValue.
+ //
+ // (There is one special case that would allow GrowTable() to be called in the future:
+ // calling Clear() on the ConcurrentDictionary will shrink the table and lower the budget.)
+ m_budget = int.MaxValue;
+ }
+
+ // Now acquire all other locks for the table
+ AcquireLocks(1, tables.m_locks.Length, ref locksAcquired);
+
+ object[] newLocks = tables.m_locks;
+
+ // Add more locks
+ if (m_growLockArray && tables.m_locks.Length < MAX_LOCK_NUMBER)
+ {
+ newLocks = new object[tables.m_locks.Length * 2];
+ Array.Copy(tables.m_locks, newLocks, tables.m_locks.Length);
+
+ for (int i = tables.m_locks.Length; i < newLocks.Length; i++)
+ {
+ newLocks[i] = new object();
+ }
+ }
+
+ Node[] newBuckets = new Node[newLength];
+ int[] newCountPerLock = new int[newLocks.Length];
+
+ // Copy all data into a new table, creating new nodes for all elements
+ for (int i = 0; i < tables.m_buckets.Length; i++)
+ {
+ Node current = tables.m_buckets[i];
+ while (current != null)
+ {
+ Node next = current.m_next;
+ int newBucketNo, newLockNo;
+ int nodeHashCode = current.m_hashcode;
+
+ if (regenerateHashKeys)
+ {
+ // Recompute the hash from the key
+ nodeHashCode = newComparer.GetHashCode(current.m_key);
+ }
+
+ GetBucketAndLockNo(nodeHashCode, out newBucketNo, out newLockNo, newBuckets.Length, newLocks.Length);
+
+ newBuckets[newBucketNo] = new Node(current.m_key, current.m_value, nodeHashCode, newBuckets[newBucketNo]);
+
+ checked
+ {
+ newCountPerLock[newLockNo]++;
+ }
+
+ current = next;
+ }
+ }
+
+ // If this resize regenerated the hashkeys, increment the count
+ if (regenerateHashKeys)
+ {
+ // We use unchecked here because we don't want to throw an exception if
+ // an overflow happens
+ unchecked
+ {
+ m_keyRehashCount++;
+ }
+ }
+
+ // Adjust the budget
+ m_budget = Math.Max(1, newBuckets.Length / newLocks.Length);
+
+ // Replace tables with the new versions
+ m_tables = new Tables(newBuckets, newLocks, newCountPerLock, newComparer);
+ }
+ finally
+ {
+ // Release all locks that we took earlier
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Computes the bucket and lock number for a particular key.
+ /// </summary>
+ private void GetBucketAndLockNo(
+ int hashcode, out int bucketNo, out int lockNo, int bucketCount, int lockCount)
+ {
+ bucketNo = (hashcode & 0x7fffffff) % bucketCount;
+ lockNo = bucketNo % lockCount;
+
+ Assert(bucketNo >= 0 && bucketNo < bucketCount);
+ Assert(lockNo >= 0 && lockNo < lockCount);
+ }
+
+ /// <summary>
+ /// The number of concurrent writes for which to optimize by default.
+ /// </summary>
+ private static int DefaultConcurrencyLevel
+ {
+
+ get { return DEFAULT_CONCURRENCY_MULTIPLIER * PlatformHelper.ProcessorCount; }
+ }
+
+ /// <summary>
+ /// Acquires all locks for this hash table, and increments locksAcquired by the number
+ /// of locks that were successfully acquired. The locks are acquired in an increasing
+ /// order.
+ /// </summary>
+ private void AcquireAllLocks(ref int locksAcquired)
+ {
+#if !FEATURE_CORECLR
+ if (CDSCollectionETWBCLProvider.Log.IsEnabled())
+ {
+ CDSCollectionETWBCLProvider.Log.ConcurrentDictionary_AcquiringAllLocks(m_tables.m_buckets.Length);
+ }
+#endif //!FEATURE_CORECLR
+
+ // First, acquire lock 0
+ AcquireLocks(0, 1, ref locksAcquired);
+
+ // Now that we have lock 0, the m_locks array will not change (i.e., grow),
+ // and so we can safely read m_locks.Length.
+ AcquireLocks(1, m_tables.m_locks.Length, ref locksAcquired);
+ Assert(locksAcquired == m_tables.m_locks.Length);
+ }
+
+ /// <summary>
+ /// Acquires a contiguous range of locks for this hash table, and increments locksAcquired
+ /// by the number of locks that were successfully acquired. The locks are acquired in an
+ /// increasing order.
+ /// </summary>
+ private void AcquireLocks(int fromInclusive, int toExclusive, ref int locksAcquired)
+ {
+ Assert(fromInclusive <= toExclusive);
+ object[] locks = m_tables.m_locks;
+
+ for (int i = fromInclusive; i < toExclusive; i++)
+ {
+ bool lockTaken = false;
+ try
+ {
+ Monitor.Enter(locks[i], ref lockTaken);
+ }
+ finally
+ {
+ if (lockTaken)
+ {
+ locksAcquired++;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Releases a contiguous range of locks.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ private void ReleaseLocks(int fromInclusive, int toExclusive)
+ {
+ Assert(fromInclusive <= toExclusive);
+
+ for (int i = fromInclusive; i < toExclusive; i++)
+ {
+ Monitor.Exit(m_tables.m_locks[i]);
+ }
+ }
+
+ /// <summary>
+ /// Gets a collection containing the keys in the dictionary.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ private ReadOnlyCollection<TKey> GetKeys()
+ {
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+ List<TKey> keys = new List<TKey>();
+
+ for (int i = 0; i < m_tables.m_buckets.Length; i++)
+ {
+ Node current = m_tables.m_buckets[i];
+ while (current != null)
+ {
+ keys.Add(current.m_key);
+ current = current.m_next;
+ }
+ }
+
+ return new ReadOnlyCollection<TKey>(keys);
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// Gets a collection containing the values in the dictionary.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "ConcurrencyCop just doesn't know about these locks")]
+ private ReadOnlyCollection<TValue> GetValues()
+ {
+ int locksAcquired = 0;
+ try
+ {
+ AcquireAllLocks(ref locksAcquired);
+ List<TValue> values = new List<TValue>();
+
+ for (int i = 0; i < m_tables.m_buckets.Length; i++)
+ {
+ Node current = m_tables.m_buckets[i];
+ while (current != null)
+ {
+ values.Add(current.m_value);
+ current = current.m_next;
+ }
+ }
+
+ return new ReadOnlyCollection<TValue>(values);
+ }
+ finally
+ {
+ ReleaseLocks(0, locksAcquired);
+ }
+ }
+
+ /// <summary>
+ /// A helper method for asserts.
+ /// </summary>
+ [Conditional("DEBUG")]
+ private void Assert(bool condition)
+ {
+ Contract.Assert(condition);
+ }
+
+ /// <summary>
+ /// A helper function to obtain the string for a particular resource key.
+ /// </summary>
+ /// <param name="key"></param>
+ /// <returns></returns>
+ private string GetResource(string key)
+ {
+ Assert(key != null);
+
+ return Environment.GetResourceString(key);
+ }
+
+ /// <summary>
+ /// A node in a singly-linked list representing a particular hash table bucket.
+ /// </summary>
+ private class Node
+ {
+ internal TKey m_key;
+ internal TValue m_value;
+ internal volatile Node m_next;
+ internal int m_hashcode;
+
+ internal Node(TKey key, TValue value, int hashcode, Node next)
+ {
+ m_key = key;
+ m_value = value;
+ m_next = next;
+ m_hashcode = hashcode;
+ }
+ }
+
+ /// <summary>
+ /// A private class to represent enumeration over the dictionary that implements the
+ /// IDictionaryEnumerator interface.
+ /// </summary>
+ private class DictionaryEnumerator : IDictionaryEnumerator
+ {
+ IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator; // Enumerator over the dictionary.
+
+ internal DictionaryEnumerator(ConcurrentDictionary<TKey, TValue> dictionary)
+ {
+ m_enumerator = dictionary.GetEnumerator();
+ }
+
+ public DictionaryEntry Entry
+ {
+ get { return new DictionaryEntry(m_enumerator.Current.Key, m_enumerator.Current.Value); }
+ }
+
+ public object Key
+ {
+ get { return m_enumerator.Current.Key; }
+ }
+
+ public object Value
+ {
+ get { return m_enumerator.Current.Value; }
+ }
+
+ public object Current
+ {
+ get { return this.Entry; }
+ }
+
+ public bool MoveNext()
+ {
+ return m_enumerator.MoveNext();
+ }
+
+ public void Reset()
+ {
+ m_enumerator.Reset();
+ }
+ }
+
+#if !FEATURE_CORECLR
+ /// <summary>
+ /// Get the data array to be serialized
+ /// </summary>
+ [OnSerializing]
+ private void OnSerializing(StreamingContext context)
+ {
+ Tables tables = m_tables;
+
+ // save the data into the serialization array to be saved
+ m_serializationArray = ToArray();
+ m_serializationConcurrencyLevel = tables.m_locks.Length;
+ m_serializationCapacity = tables.m_buckets.Length;
+ m_comparer = (IEqualityComparer<TKey>)HashHelpers.GetEqualityComparerForSerialization(tables.m_comparer);
+ }
+
+ /// <summary>
+ /// Construct the dictionary from a previously serialized one
+ /// </summary>
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ KeyValuePair<TKey, TValue>[] array = m_serializationArray;
+
+ var buckets = new Node[m_serializationCapacity];
+ var countPerLock = new int[m_serializationConcurrencyLevel];
+
+ var locks = new object[m_serializationConcurrencyLevel];
+ for (int i = 0; i < locks.Length; i++)
+ {
+ locks[i] = new object();
+ }
+
+ m_tables = new Tables(buckets, locks, countPerLock, m_comparer);
+
+ InitializeFromCollection(array);
+ m_serializationArray = null;
+
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs
new file mode 100644
index 0000000000..9164eadad1
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentQueue.cs
@@ -0,0 +1,960 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A lock-free, concurrent queue primitive, and its associated debugger view type.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+
+ /// <summary>
+ /// Represents a thread-safe first-in, first-out collection of objects.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the queue.</typeparam>
+ /// <remarks>
+ /// All public and protected members of <see cref="ConcurrentQueue{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </remarks>
+ [ComVisible(false)]
+ [DebuggerDisplay("Count = {Count}")]
+ [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [Serializable]
+ public class ConcurrentQueue<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
+ {
+ //fields of ConcurrentQueue
+ [NonSerialized]
+ private volatile Segment m_head;
+
+ [NonSerialized]
+ private volatile Segment m_tail;
+
+ private T[] m_serializationArray; // Used for custom serialization.
+
+ private const int SEGMENT_SIZE = 32;
+
+ //number of snapshot takers, GetEnumerator(), ToList() and ToArray() operations take snapshot.
+ [NonSerialized]
+ internal volatile int m_numSnapshotTakers = 0;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/> class.
+ /// </summary>
+ public ConcurrentQueue()
+ {
+ m_head = m_tail = new Segment(0, this);
+ }
+
+ /// <summary>
+ /// Initializes the contents of the queue from an existing collection.
+ /// </summary>
+ /// <param name="collection">A collection from which to copy elements.</param>
+ private void InitializeFromCollection(IEnumerable<T> collection)
+ {
+ Segment localTail = new Segment(0, this);//use this local variable to avoid the extra volatile read/write. this is safe because it is only called from ctor
+ m_head = localTail;
+
+ int index = 0;
+ foreach (T element in collection)
+ {
+ Contract.Assert(index >= 0 && index < SEGMENT_SIZE);
+ localTail.UnsafeAdd(element);
+ index++;
+
+ if (index >= SEGMENT_SIZE)
+ {
+ localTail = localTail.UnsafeGrow();
+ index = 0;
+ }
+ }
+
+ m_tail = localTail;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentQueue{T}"/>
+ /// class that contains elements copied from the specified collection
+ /// </summary>
+ /// <param name="collection">The collection whose elements are copied to the new <see
+ /// cref="ConcurrentQueue{T}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is
+ /// null.</exception>
+ public ConcurrentQueue(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException("collection");
+ }
+
+ InitializeFromCollection(collection);
+ }
+
+ /// <summary>
+ /// Get the data array to be serialized
+ /// </summary>
+ [OnSerializing]
+ private void OnSerializing(StreamingContext context)
+ {
+ // save the data into the serialization array to be saved
+ m_serializationArray = ToArray();
+ }
+
+ /// <summary>
+ /// Construct the queue from a previously seiralized one
+ /// </summary>
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ Contract.Assert(m_serializationArray != null);
+ InitializeFromCollection(m_serializationArray);
+ m_serializationArray = null;
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see
+ /// cref="T:System.Array"/>, starting at a particular
+ /// <see cref="T:System.Array"/> index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the
+ /// destination of the elements copied from the
+ /// <see cref="T:System.Collections.Concurrent.ConcurrentBag"/>. The <see
+ /// cref="T:System.Array">Array</see> must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="array"/> is multidimensional. -or-
+ /// <paramref name="array"/> does not have zero-based indexing. -or-
+ /// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is
+ /// greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>. -or- The type of the source <see
+ /// cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the
+ /// destination <paramref name="array"/>.
+ /// </exception>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ // Validate arguments.
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+
+ // We must be careful not to corrupt the array, so we will first accumulate an
+ // internal list of elements that we will then copy to the array. This requires
+ // some extra allocation, but is necessary since we don't know up front whether
+ // the array is sufficiently large to hold the stack's contents.
+ ((ICollection)ToList()).CopyTo(array, index);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is
+ /// synchronized with the SyncRoot.
+ /// </summary>
+ /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
+ /// with the SyncRoot; otherwise, false. For <see cref="ConcurrentQueue{T}"/>, this property always
+ /// returns false.</value>
+ bool ICollection.IsSynchronized
+ {
+ // Gets a value indicating whether access to this collection is synchronized. Always returns
+ // false. The reason is subtle. While access is in face thread safe, it's not the case that
+ // locking on the SyncRoot would have prevented concurrent pushes and pops, as this property
+ // would typically indicate; that's because we internally use CAS operations vs. true locks.
+ get { return false; }
+ }
+
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see
+ /// cref="T:System.Collections.ICollection"/>. This property is not supported.
+ /// </summary>
+ /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported.</exception>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
+ }
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through a collection.
+ /// </summary>
+ /// <returns>An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through the collection.</returns>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<T>)this).GetEnumerator();
+ }
+
+ /// <summary>
+ /// Attempts to add an object to the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
+ /// reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will always add the object to the
+ /// end of the <see cref="ConcurrentQueue{T}"/>
+ /// and return true.</remarks>
+ bool IProducerConsumerCollection<T>.TryAdd(T item)
+ {
+ Enqueue(item);
+ return true;
+ }
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, <paramref name="item"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned succesfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentQueue{T}"/>, this operation will attempt to remove the object
+ /// from the beginning of the <see cref="ConcurrentQueue{T}"/>.
+ /// </remarks>
+ bool IProducerConsumerCollection<T>.TryTake(out T item)
+ {
+ return TryDequeue(out item);
+ }
+
+ /// <summary>
+ /// Gets a value that indicates whether the <see cref="ConcurrentQueue{T}"/> is empty.
+ /// </summary>
+ /// <value>true if the <see cref="ConcurrentQueue{T}"/> is empty; otherwise, false.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of this property is recommended
+ /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
+ /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case
+ /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating
+ /// the result.
+ /// </remarks>
+ public bool IsEmpty
+ {
+ get
+ {
+ Segment head = m_head;
+ if (!head.IsEmpty)
+ //fast route 1:
+ //if current head is not empty, then queue is not empty
+ return false;
+ else if (head.Next == null)
+ //fast route 2:
+ //if current head is empty and it's the last segment
+ //then queue is empty
+ return true;
+ else
+ //slow route:
+ //current head is empty and it is NOT the last segment,
+ //it means another thread is growing new segment
+ {
+ SpinWait spin = new SpinWait();
+ while (head.IsEmpty)
+ {
+ if (head.Next == null)
+ return true;
+
+ spin.SpinOnce();
+ head = m_head;
+ }
+ return false;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Copies the elements stored in the <see cref="ConcurrentQueue{T}"/> to a new array.
+ /// </summary>
+ /// <returns>A new array containing a snapshot of elements copied from the <see
+ /// cref="ConcurrentQueue{T}"/>.</returns>
+ public T[] ToArray()
+ {
+ return ToList().ToArray();
+ }
+
+ /// <summary>
+ /// Copies the <see cref="ConcurrentQueue{T}"/> elements to a new <see
+ /// cref="T:System.Collections.Generic.List{T}"/>.
+ /// </summary>
+ /// <returns>A new <see cref="T:System.Collections.Generic.List{T}"/> containing a snapshot of
+ /// elements copied from the <see cref="ConcurrentQueue{T}"/>.</returns>
+ private List<T> ToList()
+ {
+ // Increments the number of active snapshot takers. This increment must happen before the snapshot is
+ // taken. At the same time, Decrement must happen after list copying is over. Only in this way, can it
+ // eliminate race condition when Segment.TryRemove() checks whether m_numSnapshotTakers == 0.
+ Interlocked.Increment(ref m_numSnapshotTakers);
+
+ List<T> list = new List<T>();
+ try
+ {
+ //store head and tail positions in buffer,
+ Segment head, tail;
+ int headLow, tailHigh;
+ GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
+
+ if (head == tail)
+ {
+ head.AddToList(list, headLow, tailHigh);
+ }
+ else
+ {
+ head.AddToList(list, headLow, SEGMENT_SIZE - 1);
+ Segment curr = head.Next;
+ while (curr != tail)
+ {
+ curr.AddToList(list, 0, SEGMENT_SIZE - 1);
+ curr = curr.Next;
+ }
+ //Add tail segment
+ tail.AddToList(list, 0, tailHigh);
+ }
+ }
+ finally
+ {
+ // This Decrement must happen after copying is over.
+ Interlocked.Decrement(ref m_numSnapshotTakers);
+ }
+ return list;
+ }
+
+ /// <summary>
+ /// Store the position of the current head and tail positions.
+ /// </summary>
+ /// <param name="head">return the head segment</param>
+ /// <param name="tail">return the tail segment</param>
+ /// <param name="headLow">return the head offset, value range [0, SEGMENT_SIZE]</param>
+ /// <param name="tailHigh">return the tail offset, value range [-1, SEGMENT_SIZE-1]</param>
+ private void GetHeadTailPositions(out Segment head, out Segment tail,
+ out int headLow, out int tailHigh)
+ {
+ head = m_head;
+ tail = m_tail;
+ headLow = head.Low;
+ tailHigh = tail.High;
+ SpinWait spin = new SpinWait();
+
+ //we loop until the observed values are stable and sensible.
+ //This ensures that any update order by other methods can be tolerated.
+ while (
+ //if head and tail changed, retry
+ head != m_head || tail != m_tail
+ //if low and high pointers, retry
+ || headLow != head.Low || tailHigh != tail.High
+ //if head jumps ahead of tail because of concurrent grow and dequeue, retry
+ || head.m_index > tail.m_index)
+ {
+ spin.SpinOnce();
+ head = m_head;
+ tail = m_tail;
+ headLow = head.Low;
+ tailHigh = tail.High;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <value>The number of elements contained in the <see cref="ConcurrentQueue{T}"/>.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
+ /// property is recommended rather than retrieving the number of items from the <see cref="Count"/>
+ /// property and comparing it to 0.
+ /// </remarks>
+ public int Count
+ {
+ get
+ {
+ //store head and tail positions in buffer,
+ Segment head, tail;
+ int headLow, tailHigh;
+ GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
+
+ if (head == tail)
+ {
+ return tailHigh - headLow + 1;
+ }
+
+ //head segment
+ int count = SEGMENT_SIZE - headLow;
+
+ //middle segment(s), if any, are full.
+ //We don't deal with overflow to be consistent with the behavior of generic types in CLR.
+ count += SEGMENT_SIZE * ((int)(tail.m_index - head.m_index - 1));
+
+ //tail segment
+ count += tailHigh + 1;
+
+ return count;
+ }
+ }
+
+
+ /// <summary>
+ /// Copies the <see cref="ConcurrentQueue{T}"/> elements to an existing one-dimensional <see
+ /// cref="T:System.Array">Array</see>, starting at the specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array">Array</see> that is the
+ /// destination of the elements copied from the
+ /// <see cref="ConcurrentQueue{T}"/>. The <see cref="T:System.Array">Array</see> must have zero-based
+ /// indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ public void CopyTo(T[] array, int index)
+ {
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+
+ // We must be careful not to corrupt the array, so we will first accumulate an
+ // internal list of elements that we will then copy to the array. This requires
+ // some extra allocation, but is necessary since we don't know up front whether
+ // the array is sufficiently large to hold the stack's contents.
+ ToList().CopyTo(array, index);
+ }
+
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the <see
+ /// cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <returns>An enumerator for the contents of the <see
+ /// cref="ConcurrentQueue{T}"/>.</returns>
+ /// <remarks>
+ /// The enumeration represents a moment-in-time snapshot of the contents
+ /// of the queue. It does not reflect any updates to the collection after
+ /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
+ /// concurrently with reads from and writes to the queue.
+ /// </remarks>
+ public IEnumerator<T> GetEnumerator()
+ {
+ // Increments the number of active snapshot takers. This increment must happen before the snapshot is
+ // taken. At the same time, Decrement must happen after the enumeration is over. Only in this way, can it
+ // eliminate race condition when Segment.TryRemove() checks whether m_numSnapshotTakers == 0.
+ Interlocked.Increment(ref m_numSnapshotTakers);
+
+ // Takes a snapshot of the queue.
+ // A design flaw here: if a Thread.Abort() happens, we cannot decrement m_numSnapshotTakers. But we cannot
+ // wrap the following with a try/finally block, otherwise the decrement will happen before the yield return
+ // statements in the GetEnumerator (head, tail, headLow, tailHigh) method.
+ Segment head, tail;
+ int headLow, tailHigh;
+ GetHeadTailPositions(out head, out tail, out headLow, out tailHigh);
+
+ //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of
+ // the queue is not taken when GetEnumerator is initialized but when MoveNext() is first called.
+ // This is inconsistent with existing generic collections. In order to prevent it, we capture the
+ // value of m_head in a buffer and call out to a helper method.
+ //The old way of doing this was to return the ToList().GetEnumerator(), but ToList() was an
+ // unnecessary perfomance hit.
+ return GetEnumerator(head, tail, headLow, tailHigh);
+ }
+
+ /// <summary>
+ /// Helper method of GetEnumerator to seperate out yield return statement, and prevent lazy evaluation.
+ /// </summary>
+ private IEnumerator<T> GetEnumerator(Segment head, Segment tail, int headLow, int tailHigh)
+ {
+ try
+ {
+ SpinWait spin = new SpinWait();
+
+ if (head == tail)
+ {
+ for (int i = headLow; i <= tailHigh; i++)
+ {
+ // If the position is reserved by an Enqueue operation, but the value is not written into,
+ // spin until the value is available.
+ spin.Reset();
+ while (!head.m_state[i].m_value)
+ {
+ spin.SpinOnce();
+ }
+ yield return head.m_array[i];
+ }
+ }
+ else
+ {
+ //iterate on head segment
+ for (int i = headLow; i < SEGMENT_SIZE; i++)
+ {
+ // If the position is reserved by an Enqueue operation, but the value is not written into,
+ // spin until the value is available.
+ spin.Reset();
+ while (!head.m_state[i].m_value)
+ {
+ spin.SpinOnce();
+ }
+ yield return head.m_array[i];
+ }
+ //iterate on middle segments
+ Segment curr = head.Next;
+ while (curr != tail)
+ {
+ for (int i = 0; i < SEGMENT_SIZE; i++)
+ {
+ // If the position is reserved by an Enqueue operation, but the value is not written into,
+ // spin until the value is available.
+ spin.Reset();
+ while (!curr.m_state[i].m_value)
+ {
+ spin.SpinOnce();
+ }
+ yield return curr.m_array[i];
+ }
+ curr = curr.Next;
+ }
+
+ //iterate on tail segment
+ for (int i = 0; i <= tailHigh; i++)
+ {
+ // If the position is reserved by an Enqueue operation, but the value is not written into,
+ // spin until the value is available.
+ spin.Reset();
+ while (!tail.m_state[i].m_value)
+ {
+ spin.SpinOnce();
+ }
+ yield return tail.m_array[i];
+ }
+ }
+ }
+ finally
+ {
+ // This Decrement must happen after the enumeration is over.
+ Interlocked.Decrement(ref m_numSnapshotTakers);
+ }
+ }
+
+ /// <summary>
+ /// Adds an object to the end of the <see cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the end of the <see
+ /// cref="ConcurrentQueue{T}"/>. The value can be a null reference
+ /// (Nothing in Visual Basic) for reference types.
+ /// </param>
+ public void Enqueue(T item)
+ {
+ SpinWait spin = new SpinWait();
+ while (true)
+ {
+ Segment tail = m_tail;
+ if (tail.TryAppend(item))
+ return;
+ spin.SpinOnce();
+ }
+ }
+
+
+ /// <summary>
+ /// Attempts to remove and return the object at the beginning of the <see
+ /// cref="ConcurrentQueue{T}"/>.
+ /// </summary>
+ /// <param name="result">
+ /// When this method returns, if the operation was successful, <paramref name="result"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned from the beggining of the <see
+ /// cref="ConcurrentQueue{T}"/>
+ /// succesfully; otherwise, false.</returns>
+ public bool TryDequeue(out T result)
+ {
+ while (!IsEmpty)
+ {
+ Segment head = m_head;
+ if (head.TryRemove(out result))
+ return true;
+ //since method IsEmpty spins, we don't need to spin in the while loop
+ }
+ result = default(T);
+ return false;
+ }
+
+ /// <summary>
+ /// Attempts to return an object from the beginning of the <see cref="ConcurrentQueue{T}"/>
+ /// without removing it.
+ /// </summary>
+ /// <param name="result">When this method returns, <paramref name="result"/> contains an object from
+ /// the beginning of the <see cref="T:System.Collections.Concurrent.ConccurrentQueue{T}"/> or an
+ /// unspecified value if the operation failed.</param>
+ /// <returns>true if and object was returned successfully; otherwise, false.</returns>
+ public bool TryPeek(out T result)
+ {
+ Interlocked.Increment(ref m_numSnapshotTakers);
+
+ while (!IsEmpty)
+ {
+ Segment head = m_head;
+ if (head.TryPeek(out result))
+ {
+ Interlocked.Decrement(ref m_numSnapshotTakers);
+ return true;
+ }
+ //since method IsEmpty spins, we don't need to spin in the while loop
+ }
+ result = default(T);
+ Interlocked.Decrement(ref m_numSnapshotTakers);
+ return false;
+ }
+
+
+ /// <summary>
+ /// private class for ConcurrentQueue.
+ /// a queue is a linked list of small arrays, each node is called a segment.
+ /// A segment contains an array, a pointer to the next segment, and m_low, m_high indices recording
+ /// the first and last valid elements of the array.
+ /// </summary>
+ private class Segment
+ {
+ //we define two volatile arrays: m_array and m_state. Note that the accesses to the array items
+ //do not get volatile treatment. But we don't need to worry about loading adjacent elements or
+ //store/load on adjacent elements would suffer reordering.
+ // - Two stores: these are at risk, but CLRv2 memory model guarantees store-release hence we are safe.
+ // - Two loads: because one item from two volatile arrays are accessed, the loads of the array references
+ // are sufficient to prevent reordering of the loads of the elements.
+ internal volatile T[] m_array;
+
+ // For each entry in m_array, the corresponding entry in m_state indicates whether this position contains
+ // a valid value. m_state is initially all false.
+ internal volatile VolatileBool[] m_state;
+
+ //pointer to the next segment. null if the current segment is the last segment
+ private volatile Segment m_next;
+
+ //We use this zero based index to track how many segments have been created for the queue, and
+ //to compute how many active segments are there currently.
+ // * The number of currently active segments is : m_tail.m_index - m_head.m_index + 1;
+ // * m_index is incremented with every Segment.Grow operation. We use Int64 type, and we can safely
+ // assume that it never overflows. To overflow, we need to do 2^63 increments, even at a rate of 4
+ // billion (2^32) increments per second, it takes 2^31 seconds, which is about 64 years.
+ internal readonly long m_index;
+
+ //indices of where the first and last valid values
+ // - m_low points to the position of the next element to pop from this segment, range [0, infinity)
+ // m_low >= SEGMENT_SIZE implies the segment is disposable
+ // - m_high points to the position of the latest pushed element, range [-1, infinity)
+ // m_high == -1 implies the segment is new and empty
+ // m_high >= SEGMENT_SIZE-1 means this segment is ready to grow.
+ // and the thread who sets m_high to SEGMENT_SIZE-1 is responsible to grow the segment
+ // - Math.Min(m_low, SEGMENT_SIZE) > Math.Min(m_high, SEGMENT_SIZE-1) implies segment is empty
+ // - initially m_low =0 and m_high=-1;
+ private volatile int m_low;
+ private volatile int m_high;
+
+ private volatile ConcurrentQueue<T> m_source;
+
+ /// <summary>
+ /// Create and initialize a segment with the specified index.
+ /// </summary>
+ internal Segment(long index, ConcurrentQueue<T> source)
+ {
+ m_array = new T[SEGMENT_SIZE];
+ m_state = new VolatileBool[SEGMENT_SIZE]; //all initialized to false
+ m_high = -1;
+ Contract.Assert(index >= 0);
+ m_index = index;
+ m_source = source;
+ }
+
+ /// <summary>
+ /// return the next segment
+ /// </summary>
+ internal Segment Next
+ {
+ get { return m_next; }
+ }
+
+
+ /// <summary>
+ /// return true if the current segment is empty (doesn't have any element available to dequeue,
+ /// false otherwise
+ /// </summary>
+ internal bool IsEmpty
+ {
+ get { return (Low > High); }
+ }
+
+ /// <summary>
+ /// Add an element to the tail of the current segment
+ /// exclusively called by ConcurrentQueue.InitializedFromCollection
+ /// InitializeFromCollection is responsible to guaratee that there is no index overflow,
+ /// and there is no contention
+ /// </summary>
+ /// <param name="value"></param>
+ internal void UnsafeAdd(T value)
+ {
+ Contract.Assert(m_high < SEGMENT_SIZE - 1);
+ m_high++;
+ m_array[m_high] = value;
+ m_state[m_high].m_value = true;
+ }
+
+ /// <summary>
+ /// Create a new segment and append to the current one
+ /// Does not update the m_tail pointer
+ /// exclusively called by ConcurrentQueue.InitializedFromCollection
+ /// InitializeFromCollection is responsible to guaratee that there is no index overflow,
+ /// and there is no contention
+ /// </summary>
+ /// <returns>the reference to the new Segment</returns>
+ internal Segment UnsafeGrow()
+ {
+ Contract.Assert(m_high >= SEGMENT_SIZE - 1);
+ Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow
+ m_next = newSegment;
+ return newSegment;
+ }
+
+ /// <summary>
+ /// Create a new segment and append to the current one
+ /// Update the m_tail pointer
+ /// This method is called when there is no contention
+ /// </summary>
+ internal void Grow()
+ {
+ //no CAS is needed, since there is no contention (other threads are blocked, busy waiting)
+ Segment newSegment = new Segment(m_index + 1, m_source); //m_index is Int64, we don't need to worry about overflow
+ m_next = newSegment;
+ Contract.Assert(m_source.m_tail == this);
+ m_source.m_tail = m_next;
+ }
+
+
+ /// <summary>
+ /// Try to append an element at the end of this segment.
+ /// </summary>
+ /// <param name="value">the element to append</param>
+ /// <param name="tail">The tail.</param>
+ /// <returns>true if the element is appended, false if the current segment is full</returns>
+ /// <remarks>if appending the specified element succeeds, and after which the segment is full,
+ /// then grow the segment</remarks>
+ internal bool TryAppend(T value)
+ {
+ //quickly check if m_high is already over the boundary, if so, bail out
+ if (m_high >= SEGMENT_SIZE - 1)
+ {
+ return false;
+ }
+
+ //Now we will use a CAS to increment m_high, and store the result in newhigh.
+ //Depending on how many free spots left in this segment and how many threads are doing this Increment
+ //at this time, the returning "newhigh" can be
+ // 1) < SEGMENT_SIZE - 1 : we took a spot in this segment, and not the last one, just insert the value
+ // 2) == SEGMENT_SIZE - 1 : we took the last spot, insert the value AND grow the segment
+ // 3) > SEGMENT_SIZE - 1 : we failed to reserve a spot in this segment, we return false to
+ // Queue.Enqueue method, telling it to try again in the next segment.
+
+ int newhigh = SEGMENT_SIZE; //initial value set to be over the boundary
+
+ //We need do Interlocked.Increment and value/state update in a finally block to ensure that they run
+ //without interuption. This is to prevent anything from happening between them, and another dequeue
+ //thread maybe spinning forever to wait for m_state[] to be true;
+ try
+ { }
+ finally
+ {
+ newhigh = Interlocked.Increment(ref m_high);
+ if (newhigh <= SEGMENT_SIZE - 1)
+ {
+ m_array[newhigh] = value;
+ m_state[newhigh].m_value = true;
+ }
+
+ //if this thread takes up the last slot in the segment, then this thread is responsible
+ //to grow a new segment. Calling Grow must be in the finally block too for reliability reason:
+ //if thread abort during Grow, other threads will be left busy spinning forever.
+ if (newhigh == SEGMENT_SIZE - 1)
+ {
+ Grow();
+ }
+ }
+
+ //if newhigh <= SEGMENT_SIZE-1, it means the current thread successfully takes up a spot
+ return newhigh <= SEGMENT_SIZE - 1;
+ }
+
+
+ /// <summary>
+ /// try to remove an element from the head of current segment
+ /// </summary>
+ /// <param name="result">The result.</param>
+ /// <param name="head">The head.</param>
+ /// <returns>return false only if the current segment is empty</returns>
+ internal bool TryRemove(out T result)
+ {
+ SpinWait spin = new SpinWait();
+ int lowLocal = Low, highLocal = High;
+ while (lowLocal <= highLocal)
+ {
+ //try to update m_low
+ if (Interlocked.CompareExchange(ref m_low, lowLocal + 1, lowLocal) == lowLocal)
+ {
+ //if the specified value is not available (this spot is taken by a push operation,
+ // but the value is not written into yet), then spin
+ SpinWait spinLocal = new SpinWait();
+ while (!m_state[lowLocal].m_value)
+ {
+ spinLocal.SpinOnce();
+ }
+ result = m_array[lowLocal];
+
+ // If there is no other thread taking snapshot (GetEnumerator(), ToList(), etc), reset the deleted entry to null.
+ // It is ok if after this conditional check m_numSnapshotTakers becomes > 0, because new snapshots won't include
+ // the deleted entry at m_array[lowLocal].
+ if (m_source.m_numSnapshotTakers <= 0)
+ {
+ m_array[lowLocal] = default(T); //release the reference to the object.
+ }
+
+ //if the current thread sets m_low to SEGMENT_SIZE, which means the current segment becomes
+ //disposable, then this thread is responsible to dispose this segment, and reset m_head
+ if (lowLocal + 1 >= SEGMENT_SIZE)
+ {
+ // Invariant: we only dispose the current m_head, not any other segment
+ // In usual situation, disposing a segment is simply seting m_head to m_head.m_next
+ // But there is one special case, where m_head and m_tail points to the same and ONLY
+ //segment of the queue: Another thread A is doing Enqueue and finds that it needs to grow,
+ //while the *current* thread is doing *this* Dequeue operation, and finds that it needs to
+ //dispose the current (and ONLY) segment. Then we need to wait till thread A finishes its
+ //Grow operation, this is the reason of having the following while loop
+ spinLocal = new SpinWait();
+ while (m_next == null)
+ {
+ spinLocal.SpinOnce();
+ }
+ Contract.Assert(m_source.m_head == this);
+ m_source.m_head = m_next;
+ }
+ return true;
+ }
+ else
+ {
+ //CAS failed due to contention: spin briefly and retry
+ spin.SpinOnce();
+ lowLocal = Low; highLocal = High;
+ }
+ }//end of while
+ result = default(T);
+ return false;
+ }
+
+ /// <summary>
+ /// try to peek the current segment
+ /// </summary>
+ /// <param name="result">holds the return value of the element at the head position,
+ /// value set to default(T) if there is no such an element</param>
+ /// <returns>true if there are elements in the current segment, false otherwise</returns>
+ internal bool TryPeek(out T result)
+ {
+ result = default(T);
+ int lowLocal = Low;
+ if (lowLocal > High)
+ return false;
+ SpinWait spin = new SpinWait();
+ while (!m_state[lowLocal].m_value)
+ {
+ spin.SpinOnce();
+ }
+ result = m_array[lowLocal];
+ return true;
+ }
+
+ /// <summary>
+ /// Adds part or all of the current segment into a List.
+ /// </summary>
+ /// <param name="list">the list to which to add</param>
+ /// <param name="start">the start position</param>
+ /// <param name="end">the end position</param>
+ internal void AddToList(List<T> list, int start, int end)
+ {
+ for (int i = start; i <= end; i++)
+ {
+ SpinWait spin = new SpinWait();
+ while (!m_state[i].m_value)
+ {
+ spin.SpinOnce();
+ }
+ list.Add(m_array[i]);
+ }
+ }
+
+ /// <summary>
+ /// return the position of the head of the current segment
+ /// Value range [0, SEGMENT_SIZE], if it's SEGMENT_SIZE, it means this segment is exhausted and thus empty
+ /// </summary>
+ internal int Low
+ {
+ get
+ {
+ return Math.Min(m_low, SEGMENT_SIZE);
+ }
+ }
+
+ /// <summary>
+ /// return the logical position of the tail of the current segment
+ /// Value range [-1, SEGMENT_SIZE-1]. When it's -1, it means this is a new segment and has no elemnet yet
+ /// </summary>
+ internal int High
+ {
+ get
+ {
+ //if m_high > SEGMENT_SIZE, it means it's out of range, we should return
+ //SEGMENT_SIZE-1 as the logical position
+ return Math.Min(m_high, SEGMENT_SIZE - 1);
+ }
+ }
+
+ }
+ }//end of class Segment
+
+ /// <summary>
+ /// A wrapper struct for volatile bool, please note the copy of the struct it self will not be volatile
+ /// for example this statement will not include in volatilness operation volatileBool1 = volatileBool2 the jit will copy the struct and will ignore the volatile
+ /// </summary>
+ struct VolatileBool
+ {
+ public VolatileBool(bool value)
+ {
+ m_value = value;
+ }
+ public volatile bool m_value;
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
new file mode 100644
index 0000000000..15d4176cff
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/ConcurrentStack.cs
@@ -0,0 +1,840 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A lock-free, concurrent stack primitive, and its associated debugger view type.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Serialization;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+ // A stack that uses CAS operations internally to maintain thread-safety in a lock-free
+ // manner. Attempting to push or pop concurrently from the stack will not trigger waiting,
+ // although some optimistic concurrency and retry is used, possibly leading to lack of
+ // fairness and/or livelock. The stack uses spinning and backoff to add some randomization,
+ // in hopes of statistically decreasing the possibility of livelock.
+ //
+ // Note that we currently allocate a new node on every push. This avoids having to worry
+ // about potential ABA issues, since the CLR GC ensures that a memory address cannot be
+ // reused before all references to it have died.
+
+ /// <summary>
+ /// Represents a thread-safe last-in, first-out collection of objects.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the stack.</typeparam>
+ /// <remarks>
+ /// All public and protected members of <see cref="ConcurrentStack{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </remarks>
+ [DebuggerDisplay("Count = {Count}")]
+ [DebuggerTypeProxy(typeof(SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<>))]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+#if !FEATURE_CORECLR
+ [Serializable]
+#endif //!FEATURE_CORECLR
+ public class ConcurrentStack<T> : IProducerConsumerCollection<T>, IReadOnlyCollection<T>
+ {
+ /// <summary>
+ /// A simple (internal) node type used to store elements of concurrent stacks and queues.
+ /// </summary>
+ private class Node
+ {
+ internal readonly T m_value; // Value of the node.
+ internal Node m_next; // Next pointer.
+
+ /// <summary>
+ /// Constructs a new node with the specified value and no next node.
+ /// </summary>
+ /// <param name="value">The value of the node.</param>
+ internal Node(T value)
+ {
+ m_value = value;
+ m_next = null;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [NonSerialized]
+#endif //!FEATURE_CORECLR
+ private volatile Node m_head; // The stack is a singly linked list, and only remembers the head.
+
+#if !FEATURE_CORECLR
+ private T[] m_serializationArray; // Used for custom serialization.
+#endif //!FEATURE_CORECLR
+
+ private const int BACKOFF_MAX_YIELDS = 8; // Arbitrary number to cap backoff.
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentStack{T}"/>
+ /// class.
+ /// </summary>
+ public ConcurrentStack()
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ConcurrentStack{T}"/>
+ /// class that contains elements copied from the specified collection
+ /// </summary>
+ /// <param name="collection">The collection whose elements are copied to the new <see
+ /// cref="ConcurrentStack{T}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="collection"/> argument is
+ /// null.</exception>
+ public ConcurrentStack(IEnumerable<T> collection)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException("collection");
+ }
+ InitializeFromCollection(collection);
+ }
+
+ /// <summary>
+ /// Initializes the contents of the stack from an existing collection.
+ /// </summary>
+ /// <param name="collection">A collection from which to copy elements.</param>
+ private void InitializeFromCollection(IEnumerable<T> collection)
+ {
+ // We just copy the contents of the collection to our stack.
+ Node lastNode = null;
+ foreach (T element in collection)
+ {
+ Node newNode = new Node(element);
+ newNode.m_next = lastNode;
+ lastNode = newNode;
+ }
+
+ m_head = lastNode;
+ }
+
+#if !FEATURE_CORECLR
+ /// <summary>
+ /// Get the data array to be serialized
+ /// </summary>
+ [OnSerializing]
+ private void OnSerializing(StreamingContext context)
+ {
+ // save the data into the serialization array to be saved
+ m_serializationArray = ToArray();
+ }
+
+ /// <summary>
+ /// Construct the stack from a previously seiralized one
+ /// </summary>
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ Contract.Assert(m_serializationArray != null);
+ // Add the elements to our stack. We need to add them from head-to-tail, to
+ // preserve the original ordering of the stack before serialization.
+ Node prevNode = null;
+ Node head = null;
+ for (int i = 0; i < m_serializationArray.Length; i++)
+ {
+ Node currNode = new Node(m_serializationArray[i]);
+
+ if (prevNode == null)
+ {
+ head = currNode;
+ }
+ else
+ {
+ prevNode.m_next = currNode;
+ }
+
+ prevNode = currNode;
+ }
+
+ m_head = head;
+ m_serializationArray = null;
+ }
+#endif //!FEATURE_CORECLR
+
+
+ /// <summary>
+ /// Gets a value that indicates whether the <see cref="ConcurrentStack{T}"/> is empty.
+ /// </summary>
+ /// <value>true if the <see cref="ConcurrentStack{T}"/> is empty; otherwise, false.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of this property is recommended
+ /// rather than retrieving the number of items from the <see cref="Count"/> property and comparing it
+ /// to 0. However, as this collection is intended to be accessed concurrently, it may be the case
+ /// that another thread will modify the collection after <see cref="IsEmpty"/> returns, thus invalidating
+ /// the result.
+ /// </remarks>
+ public bool IsEmpty
+ {
+ // Checks whether the stack is empty. Clearly the answer may be out of date even prior to
+ // the function returning (i.e. if another thread concurrently adds to the stack). It does
+ // guarantee, however, that, if another thread does not mutate the stack, a subsequent call
+ // to TryPop will return true -- i.e. it will also read the stack as non-empty.
+ get { return m_head == null; }
+ }
+
+ /// <summary>
+ /// Gets the number of elements contained in the <see cref="ConcurrentStack{T}"/>.
+ /// </summary>
+ /// <value>The number of elements contained in the <see cref="ConcurrentStack{T}"/>.</value>
+ /// <remarks>
+ /// For determining whether the collection contains any items, use of the <see cref="IsEmpty"/>
+ /// property is recommended rather than retrieving the number of items from the <see cref="Count"/>
+ /// property and comparing it to 0.
+ /// </remarks>
+ public int Count
+ {
+ // Counts the number of entries in the stack. This is an O(n) operation. The answer may be out
+ // of date before returning, but guarantees to return a count that was once valid. Conceptually,
+ // the implementation snaps a copy of the list and then counts the entries, though physically
+ // this is not what actually happens.
+ get
+ {
+ int count = 0;
+
+ // Just whip through the list and tally up the number of nodes. We rely on the fact that
+ // node next pointers are immutable after being enqueued for the first time, even as
+ // they are being dequeued. If we ever changed this (e.g. to pool nodes somehow),
+ // we'd need to revisit this implementation.
+
+ for (Node curr = m_head; curr != null; curr = curr.m_next)
+ {
+ count++; //we don't handle overflow, to be consistent with existing generic collection types in CLR
+ }
+
+ return count;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"/> is
+ /// synchronized with the SyncRoot.
+ /// </summary>
+ /// <value>true if access to the <see cref="T:System.Collections.ICollection"/> is synchronized
+ /// with the SyncRoot; otherwise, false. For <see cref="ConcurrentStack{T}"/>, this property always
+ /// returns false.</value>
+ bool ICollection.IsSynchronized
+ {
+ // Gets a value indicating whether access to this collection is synchronized. Always returns
+ // false. The reason is subtle. While access is in face thread safe, it's not the case that
+ // locking on the SyncRoot would have prevented concurrent pushes and pops, as this property
+ // would typically indicate; that's because we internally use CAS operations vs. true locks.
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Gets an object that can be used to synchronize access to the <see
+ /// cref="T:System.Collections.ICollection"/>. This property is not supported.
+ /// </summary>
+ /// <exception cref="T:System.NotSupportedException">The SyncRoot property is not supported</exception>
+ object ICollection.SyncRoot
+ {
+ get
+ {
+ throw new NotSupportedException(Environment.GetResourceString("ConcurrentCollection_SyncRoot_NotSupported"));
+ }
+ }
+
+ /// <summary>
+ /// Removes all objects from the <see cref="ConcurrentStack{T}"/>.
+ /// </summary>
+ public void Clear()
+ {
+ // Clear the list by setting the head to null. We don't need to use an atomic
+ // operation for this: anybody who is mutating the head by pushing or popping
+ // will need to use an atomic operation to guarantee they serialize and don't
+ // overwrite our setting of the head to null.
+ m_head = null;
+ }
+
+ /// <summary>
+ /// Copies the elements of the <see cref="T:System.Collections.ICollection"/> to an <see
+ /// cref="T:System.Array"/>, starting at a particular
+ /// <see cref="T:System.Array"/> index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
+ /// the elements copied from the
+ /// <see cref="ConcurrentStack{T}"/>. The <see cref="T:System.Array"/> must
+ /// have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException">
+ /// <paramref name="array"/> is multidimensional. -or-
+ /// <paramref name="array"/> does not have zero-based indexing. -or-
+ /// <paramref name="index"/> is equal to or greater than the length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="T:System.Collections.ICollection"/> is
+ /// greater than the available space from <paramref name="index"/> to the end of the destination
+ /// <paramref name="array"/>. -or- The type of the source <see
+ /// cref="T:System.Collections.ICollection"/> cannot be cast automatically to the type of the
+ /// destination <paramref name="array"/>.
+ /// </exception>
+ void ICollection.CopyTo(Array array, int index)
+ {
+ // Validate arguments.
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+
+ // We must be careful not to corrupt the array, so we will first accumulate an
+ // internal list of elements that we will then copy to the array. This requires
+ // some extra allocation, but is necessary since we don't know up front whether
+ // the array is sufficiently large to hold the stack's contents.
+ ((ICollection)ToList()).CopyTo(array, index);
+ }
+
+ /// <summary>
+ /// Copies the <see cref="ConcurrentStack{T}"/> elements to an existing one-dimensional <see
+ /// cref="T:System.Array"/>, starting at the specified array index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
+ /// the elements copied from the
+ /// <see cref="ConcurrentStack{T}"/>. The <see cref="T:System.Array"/> must have zero-based
+ /// indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentStack{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ public void CopyTo(T[] array, int index)
+ {
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+
+ // We must be careful not to corrupt the array, so we will first accumulate an
+ // internal list of elements that we will then copy to the array. This requires
+ // some extra allocation, but is necessary since we don't know up front whether
+ // the array is sufficiently large to hold the stack's contents.
+ ToList().CopyTo(array, index);
+ }
+
+
+ /// <summary>
+ /// Inserts an object at the top of the <see cref="ConcurrentStack{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to push onto the <see cref="ConcurrentStack{T}"/>. The value can be
+ /// a null reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ public void Push(T item)
+ {
+ // Pushes a node onto the front of the stack thread-safely. Internally, this simply
+ // swaps the current head pointer using a (thread safe) CAS operation to accomplish
+ // lock freedom. If the CAS fails, we add some back off to statistically decrease
+ // contention at the head, and then go back around and retry.
+
+ Node newNode = new Node(item);
+ newNode.m_next = m_head;
+ if (Interlocked.CompareExchange(ref m_head, newNode, newNode.m_next) == newNode.m_next)
+ {
+ return;
+ }
+
+ // If we failed, go to the slow path and loop around until we succeed.
+ PushCore(newNode, newNode);
+ }
+
+ /// <summary>
+ /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically.
+ /// </summary>
+ /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <remarks>
+ /// When adding multiple items to the stack, using PushRange is a more efficient
+ /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange
+ /// guarantees that all of the elements will be added atomically, meaning that no other threads will
+ /// be able to inject elements between the elements being pushed. Items at lower indices in
+ /// the <paramref name="items"/> array will be pushed before items at higher indices.
+ /// </remarks>
+ public void PushRange(T[] items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException("items");
+ }
+ PushRange(items, 0, items.Length);
+ }
+
+ /// <summary>
+ /// Inserts multiple objects at the top of the <see cref="ConcurrentStack{T}"/> atomically.
+ /// </summary>
+ /// <param name="items">The objects to push onto the <see cref="ConcurrentStack{T}"/>.</param>
+ /// <param name="startIndex">The zero-based offset in <paramref name="items"/> at which to begin
+ /// inserting elements onto the top of the <see cref="ConcurrentStack{T}"/>.</param>
+ /// <param name="count">The number of elements to be inserted onto the top of the <see
+ /// cref="ConcurrentStack{T}"/>.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref
+ /// name="count"/> is negative. Or <paramref name="startIndex"/> is greater than or equal to the length
+ /// of <paramref name="items"/>.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> + <paramref name="count"/> is
+ /// greater than the length of <paramref name="items"/>.</exception>
+ /// <remarks>
+ /// When adding multiple items to the stack, using PushRange is a more efficient
+ /// mechanism than using <see cref="Push"/> one item at a time. Additionally, PushRange
+ /// guarantees that all of the elements will be added atomically, meaning that no other threads will
+ /// be able to inject elements between the elements being pushed. Items at lower indices in the
+ /// <paramref name="items"/> array will be pushed before items at higher indices.
+ /// </remarks>
+ public void PushRange(T[] items, int startIndex, int count)
+ {
+ ValidatePushPopRangeInput(items, startIndex, count);
+
+ // No op if the count is zero
+ if (count == 0)
+ return;
+
+
+ Node head, tail;
+ head = tail = new Node(items[startIndex]);
+ for (int i = startIndex + 1; i < startIndex + count; i++)
+ {
+ Node node = new Node(items[i]);
+ node.m_next = head;
+ head = node;
+ }
+
+ tail.m_next = m_head;
+ if (Interlocked.CompareExchange(ref m_head, head, tail.m_next) == tail.m_next)
+ {
+ return;
+ }
+
+ // If we failed, go to the slow path and loop around until we succeed.
+ PushCore(head, tail);
+
+ }
+
+
+ /// <summary>
+ /// Push one or many nodes into the stack, if head and tails are equal then push one node to the stack other wise push the list between head
+ /// and tail to the stack
+ /// </summary>
+ /// <param name="head">The head pointer to the new list</param>
+ /// <param name="tail">The tail pointer to the new list</param>
+ private void PushCore(Node head, Node tail)
+ {
+ SpinWait spin = new SpinWait();
+
+ // Keep trying to CAS the exising head with the new node until we succeed.
+ do
+ {
+ spin.SpinOnce();
+ // Reread the head and link our new node.
+ tail.m_next = m_head;
+ }
+ while (Interlocked.CompareExchange(
+ ref m_head, head, tail.m_next) != tail.m_next);
+
+#if !FEATURE_CORECLR
+ if (CDSCollectionETWBCLProvider.Log.IsEnabled())
+ {
+ CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPushFailed(spin.Count);
+ }
+#endif // !FEATURE_CORECLR
+ }
+
+ /// <summary>
+ /// Local helper function to validate the Pop Push range methods input
+ /// </summary>
+ private void ValidatePushPopRangeInput(T[] items, int startIndex, int count)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException("items");
+ }
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ConcurrentStack_PushPopRange_CountOutOfRange"));
+ }
+ int length = items.Length;
+ if (startIndex >= length || startIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ConcurrentStack_PushPopRange_StartOutOfRange"));
+ }
+ if (length - count < startIndex) //instead of (startIndex + count > items.Length) to prevent overflow
+ {
+ throw new ArgumentException(Environment.GetResourceString("ConcurrentStack_PushPopRange_InvalidCount"));
+ }
+ }
+
+ /// <summary>
+ /// Attempts to add an object to the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>. The value can be a null
+ /// reference (Nothing in Visual Basic) for reference types.
+ /// </param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentStack{T}"/>, this operation
+ /// will always insert the object onto the top of the <see cref="ConcurrentStack{T}"/>
+ /// and return true.</remarks>
+ bool IProducerConsumerCollection<T>.TryAdd(T item)
+ {
+ Push(item);
+ return true;
+ }
+
+ /// <summary>
+ /// Attempts to return an object from the top of the <see cref="ConcurrentStack{T}"/>
+ /// without removing it.
+ /// </summary>
+ /// <param name="result">When this method returns, <paramref name="result"/> contains an object from
+ /// the top of the <see cref="T:System.Collections.Concurrent.ConccurrentStack{T}"/> or an
+ /// unspecified value if the operation failed.</param>
+ /// <returns>true if and object was returned successfully; otherwise, false.</returns>
+ public bool TryPeek(out T result)
+ {
+ Node head = m_head;
+
+ // If the stack is empty, return false; else return the element and true.
+ if (head == null)
+ {
+ result = default(T);
+ return false;
+ }
+ else
+ {
+ result = head.m_value;
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Attempts to pop and return the object at the top of the <see cref="ConcurrentStack{T}"/>.
+ /// </summary>
+ /// <param name="result">
+ /// When this method returns, if the operation was successful, <paramref name="result"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned from the top of the <see
+ /// cref="ConcurrentStack{T}"/>
+ /// succesfully; otherwise, false.</returns>
+ public bool TryPop(out T result)
+ {
+ Node head = m_head;
+ //stack is empty
+ if (head == null)
+ {
+ result = default(T);
+ return false;
+ }
+ if (Interlocked.CompareExchange(ref m_head, head.m_next, head) == head)
+ {
+ result = head.m_value;
+ return true;
+ }
+
+ // Fall through to the slow path.
+ return TryPopCore(out result);
+ }
+
+ /// <summary>
+ /// Attempts to pop and return multiple objects from the top of the <see cref="ConcurrentStack{T}"/>
+ /// atomically.
+ /// </summary>
+ /// <param name="items">
+ /// The <see cref="T:System.Array"/> to which objects popped from the top of the <see
+ /// cref="ConcurrentStack{T}"/> will be added.
+ /// </param>
+ /// <returns>The number of objects successfully popped from the top of the <see
+ /// cref="ConcurrentStack{T}"/> and inserted in
+ /// <paramref name="items"/>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null argument (Nothing
+ /// in Visual Basic).</exception>
+ /// <remarks>
+ /// When popping multiple items, if there is little contention on the stack, using
+ /// TryPopRange can be more efficient than using <see cref="TryPop"/>
+ /// once per item to be removed. Nodes fill the <paramref name="items"/>
+ /// with the first node to be popped at the startIndex, the second node to be popped
+ /// at startIndex + 1, and so on.
+ /// </remarks>
+ public int TryPopRange(T[] items)
+ {
+ if (items == null)
+ {
+ throw new ArgumentNullException("items");
+ }
+
+ return TryPopRange(items, 0, items.Length);
+ }
+
+ /// <summary>
+ /// Attempts to pop and return multiple objects from the top of the <see cref="ConcurrentStack{T}"/>
+ /// atomically.
+ /// </summary>
+ /// <param name="items">
+ /// The <see cref="T:System.Array"/> to which objects popped from the top of the <see
+ /// cref="ConcurrentStack{T}"/> will be added.
+ /// </param>
+ /// <param name="startIndex">The zero-based offset in <paramref name="items"/> at which to begin
+ /// inserting elements from the top of the <see cref="ConcurrentStack{T}"/>.</param>
+ /// <param name="count">The number of elements to be popped from top of the <see
+ /// cref="ConcurrentStack{T}"/> and inserted into <paramref name="items"/>.</param>
+ /// <returns>The number of objects successfully popped from the top of
+ /// the <see cref="ConcurrentStack{T}"/> and inserted in <paramref name="items"/>.</returns>
+ /// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference
+ /// (Nothing in Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="startIndex"/> or <paramref
+ /// name="count"/> is negative. Or <paramref name="startIndex"/> is greater than or equal to the length
+ /// of <paramref name="items"/>.</exception>
+ /// <exception cref="ArgumentException"><paramref name="startIndex"/> + <paramref name="count"/> is
+ /// greater than the length of <paramref name="items"/>.</exception>
+ /// <remarks>
+ /// When popping multiple items, if there is little contention on the stack, using
+ /// TryPopRange can be more efficient than using <see cref="TryPop"/>
+ /// once per item to be removed. Nodes fill the <paramref name="items"/>
+ /// with the first node to be popped at the startIndex, the second node to be popped
+ /// at startIndex + 1, and so on.
+ /// </remarks>
+ public int TryPopRange(T[] items, int startIndex, int count)
+ {
+ ValidatePushPopRangeInput(items, startIndex, count);
+
+ // No op if the count is zero
+ if (count == 0)
+ return 0;
+
+ Node poppedHead;
+ int nodesCount = TryPopCore(count, out poppedHead);
+ if (nodesCount > 0)
+ {
+ CopyRemovedItems(poppedHead, items, startIndex, nodesCount);
+
+ }
+ return nodesCount;
+
+ }
+
+ /// <summary>
+ /// Local helper function to Pop an item from the stack, slow path
+ /// </summary>
+ /// <param name="result">The popped item</param>
+ /// <returns>True if succeeded, false otherwise</returns>
+ private bool TryPopCore(out T result)
+ {
+ Node poppedNode;
+
+ if (TryPopCore(1, out poppedNode) == 1)
+ {
+ result = poppedNode.m_value;
+ return true;
+ }
+
+ result = default(T);
+ return false;
+
+ }
+
+ /// <summary>
+ /// Slow path helper for TryPop. This method assumes an initial attempt to pop an element
+ /// has already occurred and failed, so it begins spinning right away.
+ /// </summary>
+ /// <param name="count">The number of items to pop.</param>
+ /// <param name="poppedHead">
+ /// When this method returns, if the pop succeeded, contains the removed object. If no object was
+ /// available to be removed, the value is unspecified. This parameter is passed uninitialized.
+ /// </param>
+ /// <returns>True if an element was removed and returned; otherwise, false.</returns>
+ private int TryPopCore(int count, out Node poppedHead)
+ {
+ SpinWait spin = new SpinWait();
+
+ // Try to CAS the head with its current next. We stop when we succeed or
+ // when we notice that the stack is empty, whichever comes first.
+ Node head;
+ Node next;
+ int backoff = 1;
+ Random r = new Random(Environment.TickCount & Int32.MaxValue); // avoid the case where TickCount could return Int32.MinValue
+ while (true)
+ {
+ head = m_head;
+ // Is the stack empty?
+ if (head == null)
+ {
+#if !FEATURE_CORECLR
+ if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
+ {
+ CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count);
+ }
+#endif //!FEATURE_CORECLR
+ poppedHead = null;
+ return 0;
+ }
+ next = head;
+ int nodesCount = 1;
+ for (; nodesCount < count && next.m_next != null; nodesCount++)
+ {
+ next = next.m_next;
+ }
+
+ // Try to swap the new head. If we succeed, break out of the loop.
+ if (Interlocked.CompareExchange(ref m_head, next.m_next, head) == head)
+ {
+#if !FEATURE_CORECLR
+ if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
+ {
+ CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spin.Count);
+ }
+#endif //!FEATURE_CORECLR
+ // Return the popped Node.
+ poppedHead = head;
+ return nodesCount;
+ }
+
+ // We failed to CAS the new head. Spin briefly and retry.
+ for (int i = 0; i < backoff; i++)
+ {
+ spin.SpinOnce();
+ }
+
+ backoff = spin.NextSpinWillYield ? r.Next(1, BACKOFF_MAX_YIELDS) : backoff * 2;
+ }
+ }
+
+
+ /// <summary>
+ /// Local helper function to copy the poped elements into a given collection
+ /// </summary>
+ /// <param name="head">The head of the list to be copied</param>
+ /// <param name="collection">The collection to place the popped items in</param>
+ /// <param name="startIndex">the beginning of index of where to place the popped items</param>
+ /// <param name="nodesCount">The number of nodes.</param>
+ private void CopyRemovedItems(Node head, T[] collection, int startIndex, int nodesCount)
+ {
+ Node current = head;
+ for (int i = startIndex; i < startIndex + nodesCount; i++)
+ {
+ collection[i] = current.m_value;
+ current = current.m_next;
+ }
+
+ }
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see
+ /// cref="T:System.Collections.Concurrent.IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the operation was successful, <paramref name="item"/> contains the
+ /// object removed. If no object was available to be removed, the value is unspecified.
+ /// </param>
+ /// <returns>true if an element was removed and returned succesfully; otherwise, false.</returns>
+ /// <remarks>For <see cref="ConcurrentStack{T}"/>, this operation will attempt to pope the object at
+ /// the top of the <see cref="ConcurrentStack{T}"/>.
+ /// </remarks>
+ bool IProducerConsumerCollection<T>.TryTake(out T item)
+ {
+ return TryPop(out item);
+ }
+
+ /// <summary>
+ /// Copies the items stored in the <see cref="ConcurrentStack{T}"/> to a new array.
+ /// </summary>
+ /// <returns>A new array containing a snapshot of elements copied from the <see
+ /// cref="ConcurrentStack{T}"/>.</returns>
+ public T[] ToArray()
+ {
+ return ToList().ToArray();
+ }
+
+ /// <summary>
+ /// Returns an array containing a snapshot of the list's contents, using
+ /// the target list node as the head of a region in the list.
+ /// </summary>
+ /// <returns>An array of the list's contents.</returns>
+ private List<T> ToList()
+ {
+ List<T> list = new List<T>();
+
+ Node curr = m_head;
+ while (curr != null)
+ {
+ list.Add(curr.m_value);
+ curr = curr.m_next;
+ }
+
+ return list;
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through the <see cref="ConcurrentStack{T}"/>.
+ /// </summary>
+ /// <returns>An enumerator for the <see cref="ConcurrentStack{T}"/>.</returns>
+ /// <remarks>
+ /// The enumeration represents a moment-in-time snapshot of the contents
+ /// of the stack. It does not reflect any updates to the collection after
+ /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use
+ /// concurrently with reads from and writes to the stack.
+ /// </remarks>
+ public IEnumerator<T> GetEnumerator()
+ {
+ // Returns an enumerator for the stack. This effectively takes a snapshot
+ // of the stack's contents at the time of the call, i.e. subsequent modifications
+ // (pushes or pops) will not be reflected in the enumerator's contents.
+
+ //If we put yield-return here, the iterator will be lazily evaluated. As a result a snapshot of
+ //the stack is not taken when GetEnumerator is initialized but when MoveNext() is first called.
+ //This is inconsistent with existing generic collections. In order to prevent it, we capture the
+ //value of m_head in a buffer and call out to a helper method
+ return GetEnumerator(m_head);
+ }
+
+ private IEnumerator<T> GetEnumerator(Node head)
+ {
+ Node current = head;
+ while (current != null)
+ {
+ yield return current.m_value;
+ current = current.m_next;
+ }
+ }
+
+ /// <summary>
+ /// Returns an enumerator that iterates through a collection.
+ /// </summary>
+ /// <returns>An <see cref="T:System.Collections.IEnumerator"/> that can be used to iterate through
+ /// the collection.</returns>
+ /// <remarks>
+ /// The enumeration represents a moment-in-time snapshot of the contents of the stack. It does not
+ /// reflect any updates to the collection after
+ /// <see cref="GetEnumerator"/> was called. The enumerator is safe to use concurrently with reads
+ /// from and writes to the stack.
+ /// </remarks>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<T>)this).GetEnumerator();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs
new file mode 100644
index 0000000000..a74f69069a
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A common interface for all concurrent collections.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Collections.Concurrent
+{
+
+ /// <summary>
+ /// Defines methods to manipulate thread-safe collections intended for producer/consumer usage.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of elements in the collection.</typeparam>
+ /// <remarks>
+ /// All implementations of this interface must enable all members of this interface
+ /// to be used concurrently from multiple threads.
+ /// </remarks>
+ public interface IProducerConsumerCollection<T> : IEnumerable<T>, ICollection
+ {
+
+ /// <summary>
+ /// Copies the elements of the <see cref="IProducerConsumerCollection{T}"/> to
+ /// an
+ /// <see cref="T:System.Array"/>, starting at a specified index.
+ /// </summary>
+ /// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of
+ /// the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// The array must have zero-based indexing.</param>
+ /// <param name="index">The zero-based index in <paramref name="array"/> at which copying
+ /// begins.</param>
+ /// <exception cref="ArgumentNullException"><paramref name="array"/> is a null reference (Nothing in
+ /// Visual Basic).</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is less than
+ /// zero.</exception>
+ /// <exception cref="ArgumentException"><paramref name="index"/> is equal to or greater than the
+ /// length of the <paramref name="array"/>
+ /// -or- The number of elements in the source <see cref="ConcurrentQueue{T}"/> is greater than the
+ /// available space from <paramref name="index"/> to the end of the destination <paramref
+ /// name="array"/>.
+ /// </exception>
+ void CopyTo(T[] array, int index);
+
+ /// <summary>
+ /// Attempts to add an object to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">The object to add to the <see
+ /// cref="IProducerConsumerCollection{T}"/>.</param>
+ /// <returns>true if the object was added successfully; otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentException">The <paramref name="item"/> was invalid for this collection.</exception>
+ bool TryAdd(T item);
+
+ /// <summary>
+ /// Attempts to remove and return an object from the <see cref="IProducerConsumerCollection{T}"/>.
+ /// </summary>
+ /// <param name="item">
+ /// When this method returns, if the object was removed and returned successfully, <paramref
+ /// name="item"/> contains the removed object. If no object was available to be removed, the value is
+ /// unspecified.
+ /// </param>
+ /// <returns>true if an object was removed and returned successfully; otherwise, false.</returns>
+ bool TryTake(out T item);
+
+ /// <summary>
+ /// Copies the elements contained in the <see cref="IProducerConsumerCollection{T}"/> to a new array.
+ /// </summary>
+ /// <returns>A new array containing the elements copied from the <see cref="IProducerConsumerCollection{T}"/>.</returns>
+ T[] ToArray();
+
+ }
+
+
+ /// <summary>
+ /// A debugger view of the IProducerConsumerCollection that makes it simple to browse the
+ /// collection's contents at a point in time.
+ /// </summary>
+ /// <typeparam name="T">The type of elements stored within.</typeparam>
+ internal sealed class SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView<T>
+ {
+ private IProducerConsumerCollection<T> m_collection; // The collection being viewed.
+
+ /// <summary>
+ /// Constructs a new debugger view object for the provided collection object.
+ /// </summary>
+ /// <param name="collection">A collection to browse in the debugger.</param>
+ public SystemCollectionsConcurrent_ProducerConsumerCollectionDebugView(IProducerConsumerCollection<T> collection)
+ {
+ if (collection == null)
+ {
+ throw new ArgumentNullException("collection");
+ }
+
+ m_collection = collection;
+ }
+
+ /// <summary>
+ /// Returns a snapshot of the underlying collection's elements.
+ /// </summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items
+ {
+ get { return m_collection.ToArray(); }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs b/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs
new file mode 100644
index 0000000000..02263b7f97
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/OrderablePartitioner.cs
@@ -0,0 +1,281 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+//
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+
+ /// <summary>
+ /// Represents a particular manner of splitting an orderable data source into multiple partitions.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in the collection.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// Each element in each partition has an integer index associated with it, which determines the relative
+ /// order of that element against elements in other partitions.
+ /// </para>
+ /// <para>
+ /// Inheritors of <see cref="OrderablePartitioner{TSource}"/> must adhere to the following rules:
+ /// <ol>
+ /// <li>All indices must be unique, such that there may not be duplicate indices. If all indices are not
+ /// unique, the output ordering may be scrambled.</li>
+ /// <li>All indices must be non-negative. If any indices are negative, consumers of the implementation
+ /// may throw exceptions.</li>
+ /// <li><see cref="GetPartitions"/> and <see cref="GetOrderablePartitions"/> should throw a
+ /// <see cref="T:System.ArgumentOutOfRangeException"/> if the requested partition count is less than or
+ /// equal to zero.</li>
+ /// <li><see cref="GetPartitions"/> and <see cref="GetOrderablePartitions"/> should always return a number
+ /// of enumerables equal to the requested partition count. If the partitioner runs out of data and cannot
+ /// create as many partitions as requested, an empty enumerator should be returned for each of the
+ /// remaining partitions. If this rule is not followed, consumers of the implementation may throw a <see
+ /// cref="T:System.InvalidOperationException"/>.</li>
+ /// <li><see cref="GetPartitions"/>, <see cref="GetOrderablePartitions"/>,
+ /// <see cref="GetDynamicPartitions"/>, and <see cref="GetOrderableDynamicPartitions"/>
+ /// should never return null. If null is returned, a consumer of the implementation may throw a
+ /// <see cref="T:System.InvalidOperationException"/>.</li>
+ /// <li><see cref="GetPartitions"/>, <see cref="GetOrderablePartitions"/>,
+ /// <see cref="GetDynamicPartitions"/>, and <see cref="GetOrderableDynamicPartitions"/>
+ /// should always return partitions that can fully and uniquely enumerate the input data source. All of
+ /// the data and only the data contained in the input source should be enumerated, with no duplication
+ /// that was not already in the input, unless specifically required by the particular partitioner's
+ /// design. If this is not followed, the output ordering may be scrambled.</li>
+ /// <li>If <see cref="KeysOrderedInEachPartition"/> returns true, each partition must return elements
+ /// with increasing key indices.</li>
+ /// <li>If <see cref="KeysOrderedAcrossPartitions"/> returns true, all the keys in partition numbered N
+ /// must be larger than all the keys in partition numbered N-1.</li>
+ /// <li>If <see cref="KeysNormalized"/> returns true, all indices must be monotonically increasing from
+ /// 0, though not necessarily within a single partition.</li>
+ /// </ol>
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public abstract class OrderablePartitioner<TSource> : Partitioner<TSource>
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="OrderablePartitioner{TSource}"/> class with the
+ /// specified constraints on the index keys.
+ /// </summary>
+ /// <param name="keysOrderedInEachPartition">
+ /// Indicates whether the elements in each partition are yielded in the order of
+ /// increasing keys.
+ /// </param>
+ /// <param name="keysOrderedAcrossPartitions">
+ /// Indicates whether elements in an earlier partition always come before
+ /// elements in a later partition. If true, each element in partition 0 has a smaller order key than
+ /// any element in partition 1, each element in partition 1 has a smaller order key than any element
+ /// in partition 2, and so on.
+ /// </param>
+ /// <param name="keysNormalized">
+ /// Indicates whether keys are normalized. If true, all order keys are distinct
+ /// integers in the range [0 .. numberOfElements-1]. If false, order keys must still be dictinct, but
+ /// only their relative order is considered, not their absolute values.
+ /// </param>
+ protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized)
+ {
+ KeysOrderedInEachPartition = keysOrderedInEachPartition;
+ KeysOrderedAcrossPartitions = keysOrderedAcrossPartitions;
+ KeysNormalized = keysNormalized;
+ }
+
+ /// <summary>
+ /// Partitions the underlying collection into the specified number of orderable partitions.
+ /// </summary>
+ /// <remarks>
+ /// Each partition is represented as an enumerator over key-value pairs.
+ /// The value of the pair is the element itself, and the key is an integer which determines
+ /// the relative ordering of this element against other elements in the data source.
+ /// </remarks>
+ /// <param name="partitionCount">The number of partitions to create.</param>
+ /// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
+ public abstract IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount);
+
+ /// <summary>
+ /// Creates an object that can partition the underlying collection into a variable number of
+ /// partitions.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The returned object implements the <see
+ /// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
+ /// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
+ /// object creates another partition over the sequence.
+ /// </para>
+ /// <para>
+ /// Each partition is represented as an enumerator over key-value pairs. The value in the pair is the element
+ /// itself, and the key is an integer which determines the relative ordering of this element against
+ /// other elements.
+ /// </para>
+ /// <para>
+ /// The <see cref="GetOrderableDynamicPartitions"/> method is only supported if the <see
+ /// cref="System.Collections.Concurrent.Partitioner{TSource}.SupportsDynamicPartitions">SupportsDynamicPartitions</see>
+ /// property returns true.
+ /// </para>
+ /// </remarks>
+ /// <returns>An object that can create partitions over the underlying data source.</returns>
+ /// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
+ /// partitioner.</exception>
+ public virtual IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
+ }
+
+ /// <summary>
+ /// Gets whether elements in each partition are yielded in the order of increasing keys.
+ /// </summary>
+ public bool KeysOrderedInEachPartition { get; private set; }
+
+ /// <summary>
+ /// Gets whether elements in an earlier partition always come before elements in a later partition.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="KeysOrderedAcrossPartitions"/> returns true, each element in partition 0 has a
+ /// smaller order key than any element in partition 1, each element in partition 1 has a smaller
+ /// order key than any element in partition 2, and so on.
+ /// </remarks>
+ public bool KeysOrderedAcrossPartitions { get; private set; }
+
+ /// <summary>
+ /// Gets whether order keys are normalized.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="KeysNormalized"/> returns true, all order keys are distinct integers in the range
+ /// [0 .. numberOfElements-1]. If the property returns false, order keys must still be dictinct, but
+ /// only their relative order is considered, not their absolute values.
+ /// </remarks>
+ public bool KeysNormalized { get; private set; }
+
+ /// <summary>
+ /// Partitions the underlying collection into the given number of ordered partitions.
+ /// </summary>
+ /// <remarks>
+ /// The default implementation provides the same behavior as <see cref="GetOrderablePartitions"/> except
+ /// that the returned set of partitions does not provide the keys for the elements.
+ /// </remarks>
+ /// <param name="partitionCount">The number of partitions to create.</param>
+ /// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
+ public override IList<IEnumerator<TSource>> GetPartitions(int partitionCount)
+ {
+ IList<IEnumerator<KeyValuePair<long, TSource>>> orderablePartitions = GetOrderablePartitions(partitionCount);
+
+ if (orderablePartitions.Count != partitionCount)
+ {
+ throw new InvalidOperationException("OrderablePartitioner_GetPartitions_WrongNumberOfPartitions");
+ }
+
+ IEnumerator<TSource>[] partitions = new IEnumerator<TSource>[partitionCount];
+ for (int i = 0; i < partitionCount; i++)
+ {
+ partitions[i] = new EnumeratorDropIndices(orderablePartitions[i]);
+ }
+ return partitions;
+ }
+
+ /// <summary>
+ /// Creates an object that can partition the underlying collection into a variable number of
+ /// partitions.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The returned object implements the <see
+ /// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
+ /// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
+ /// object creates another partition over the sequence.
+ /// </para>
+ /// <para>
+ /// The default implementation provides the same behavior as <see cref="GetOrderableDynamicPartitions"/> except
+ /// that the returned set of partitions does not provide the keys for the elements.
+ /// </para>
+ /// <para>
+ /// The <see cref="GetDynamicPartitions"/> method is only supported if the <see
+ /// cref="System.Collections.Concurrent.Partitioner{TSource}.SupportsDynamicPartitions"/>
+ /// property returns true.
+ /// </para>
+ /// </remarks>
+ /// <returns>An object that can create partitions over the underlying data source.</returns>
+ /// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
+ /// partitioner.</exception>
+ public override IEnumerable<TSource> GetDynamicPartitions()
+ {
+ IEnumerable<KeyValuePair<long, TSource>> orderablePartitions = GetOrderableDynamicPartitions();
+ return new EnumerableDropIndices(orderablePartitions);
+ }
+
+ /// <summary>
+ /// Converts an enumerable over key-value pairs to an enumerable over values.
+ /// </summary>
+ private class EnumerableDropIndices : IEnumerable<TSource>, IDisposable
+ {
+ private readonly IEnumerable<KeyValuePair<long, TSource>> m_source;
+ public EnumerableDropIndices(IEnumerable<KeyValuePair<long, TSource>> source)
+ {
+ m_source = source;
+ }
+ public IEnumerator<TSource> GetEnumerator()
+ {
+ return new EnumeratorDropIndices(m_source.GetEnumerator());
+ }
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((EnumerableDropIndices)this).GetEnumerator();
+ }
+ public void Dispose()
+ {
+ IDisposable d = m_source as IDisposable;
+ if (d != null)
+ {
+ d.Dispose();
+ }
+ }
+ }
+
+ private class EnumeratorDropIndices : IEnumerator<TSource>
+ {
+ private readonly IEnumerator<KeyValuePair<long, TSource>> m_source;
+ public EnumeratorDropIndices(IEnumerator<KeyValuePair<long, TSource>> source)
+ {
+ m_source = source;
+ }
+ public bool MoveNext()
+ {
+ return m_source.MoveNext();
+ }
+ public TSource Current
+ {
+ get
+ {
+ return m_source.Current.Value;
+ }
+ }
+ Object IEnumerator.Current
+ {
+ get
+ {
+ return ((EnumeratorDropIndices)this).Current;
+ }
+ }
+ public void Dispose()
+ {
+ m_source.Dispose();
+ }
+ public void Reset()
+ {
+ m_source.Reset();
+ }
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs b/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs
new file mode 100644
index 0000000000..3d54c1471b
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/Partitioner.cs
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Represents a particular way of splitting a collection into multiple partitions.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Threading;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// Represents a particular manner of splitting a data source into multiple partitions.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in the collection.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// Inheritors of <see cref="Partitioner{TSource}"/> must adhere to the following rules:
+ /// <ol>
+ /// <li><see cref="GetPartitions"/> should throw a
+ /// <see cref="T:System.ArgumentOutOfRangeException"/> if the requested partition count is less than or
+ /// equal to zero.</li>
+ /// <li><see cref="GetPartitions"/> should always return a number of enumerables equal to the requested
+ /// partition count. If the partitioner runs out of data and cannot create as many partitions as
+ /// requested, an empty enumerator should be returned for each of the remaining partitions. If this rule
+ /// is not followed, consumers of the implementation may throw a <see
+ /// cref="T:System.InvalidOperationException"/>.</li>
+ /// <li><see cref="GetPartitions"/> and <see cref="GetDynamicPartitions"/>
+ /// should never return null. If null is returned, a consumer of the implementation may throw a
+ /// <see cref="T:System.InvalidOperationException"/>.</li>
+ /// <li><see cref="GetPartitions"/> and <see cref="GetDynamicPartitions"/> should always return
+ /// partitions that can fully and uniquely enumerate the input data source. All of the data and only the
+ /// data contained in the input source should be enumerated, with no duplication that was not already in
+ /// the input, unless specifically required by the particular partitioner's design. If this is not
+ /// followed, the output ordering may be scrambled.</li>
+ /// </ol>
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public abstract class Partitioner<TSource>
+ {
+ /// <summary>
+ /// Partitions the underlying collection into the given number of partitions.
+ /// </summary>
+ /// <param name="partitionCount">The number of partitions to create.</param>
+ /// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
+ public abstract IList<IEnumerator<TSource>> GetPartitions(int partitionCount);
+
+ /// <summary>
+ /// Gets whether additional partitions can be created dynamically.
+ /// </summary>
+ /// <returns>
+ /// true if the <see cref="Partitioner{TSource}"/> can create partitions dynamically as they are
+ /// requested; false if the <see cref="Partitioner{TSource}"/> can only allocate
+ /// partitions statically.
+ /// </returns>
+ /// <remarks>
+ /// <para>
+ /// If a derived class does not override and implement <see cref="GetDynamicPartitions"/>,
+ /// <see cref="SupportsDynamicPartitions"/> should return false. The value of <see
+ /// cref="SupportsDynamicPartitions"/> should not vary over the lifetime of this instance.
+ /// </para>
+ /// </remarks>
+ public virtual bool SupportsDynamicPartitions
+ {
+ get { return false; }
+ }
+
+ /// <summary>
+ /// Creates an object that can partition the underlying collection into a variable number of
+ /// partitions.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The returned object implements the <see
+ /// cref="T:System.Collections.Generic.IEnumerable{TSource}"/> interface. Calling <see
+ /// cref="System.Collections.Generic.IEnumerable{TSource}.GetEnumerator">GetEnumerator</see> on the
+ /// object creates another partition over the sequence.
+ /// </para>
+ /// <para>
+ /// The <see cref="GetDynamicPartitions"/> method is only supported if the <see
+ /// cref="SupportsDynamicPartitions"/>
+ /// property returns true.
+ /// </para>
+ /// </remarks>
+ /// <returns>An object that can create partitions over the underlying data source.</returns>
+ /// <exception cref="NotSupportedException">Dynamic partitioning is not supported by this
+ /// partitioner.</exception>
+ public virtual IEnumerable<TSource> GetDynamicPartitions()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("Partitioner_DynamicPartitionsNotSupported"));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs b/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs
new file mode 100644
index 0000000000..2169c6dee7
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Concurrent/PartitionerStatic.cs
@@ -0,0 +1,1733 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A class of default partitioners for Partitioner<TSource>
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Threading;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+
+namespace System.Collections.Concurrent
+{
+ /// <summary>
+ /// Out-of-the-box partitioners are created with a set of default behaviors.
+ /// For example, by default, some form of buffering and chunking will be employed to achieve
+ /// optimal performance in the common scenario where an IEnumerable<> implementation is fast and
+ /// non-blocking. These behaviors can be overridden via this enumeration.
+ /// </summary>
+ [Flags]
+#if !FEATURE_CORECLR
+ [Serializable]
+#endif
+ public enum EnumerablePartitionerOptions
+ {
+ /// <summary>
+ /// Use the default behavior (i.e., use buffering to achieve optimal performance)
+ /// </summary>
+ None = 0x0,
+
+ /// <summary>
+ /// Creates a partitioner that will take items from the source enumerable one at a time
+ /// and will not use intermediate storage that can be accessed more efficiently by multiple threads.
+ /// This option provides support for low latency (items will be processed as soon as they are available from
+ /// the source) and partial support for dependencies between items (a thread cannot deadlock waiting for an item
+ /// that it, itself, is responsible for processing).
+ /// </summary>
+ NoBuffering = 0x1
+ }
+
+ // The static class Partitioners implements 3 default partitioning strategies:
+ // 1. dynamic load balance partitioning for indexable data source (IList and arrays)
+ // 2. static partitioning for indexable data source (IList and arrays)
+ // 3. dynamic load balance partitioning for enumerables. Enumerables have indexes, which are the natural order
+ // of elements, but enuemrators are not indexable
+ // - data source of type IList/arrays have both dynamic and static partitioning, as 1 and 3.
+ // We assume that the source data of IList/Array is not changing concurrently.
+ // - data source of type IEnumerable can only be partitioned dynamically (load-balance)
+ // - Dynamic partitioning methods 1 and 3 are same, both being dynamic and load-balance. But the
+ // implementation is different for data source of IList/Array vs. IEnumerable:
+ // * When the source collection is IList/Arrays, we use Interlocked on the shared index;
+ // * When the source collection is IEnumerable, we use Monitor to wrap around the access to the source
+ // enumerator.
+
+ /// <summary>
+ /// Provides common partitioning strategies for arrays, lists, and enumerables.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The static methods on <see cref="Partitioner"/> are all thread-safe and may be used concurrently
+ /// from multiple threads. However, while a created partitioner is in use, the underlying data source
+ /// should not be modified, whether from the same thread that's using a partitioner or from a separate
+ /// thread.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public static class Partitioner
+ {
+ /// <summary>
+ /// Creates an orderable partitioner from an <see cref="System.Collections.Generic.IList{T}"/>
+ /// instance.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in source list.</typeparam>
+ /// <param name="list">The list to be partitioned.</param>
+ /// <param name="loadBalance">
+ /// A Boolean value that indicates whether the created partitioner should dynamically
+ /// load balance between partitions rather than statically partition.
+ /// </param>
+ /// <returns>
+ /// An orderable partitioner based on the input list.
+ /// </returns>
+ public static OrderablePartitioner<TSource> Create<TSource>(IList<TSource> list, bool loadBalance)
+ {
+ if (list == null)
+ {
+ throw new ArgumentNullException("list");
+ }
+ if (loadBalance)
+ {
+ return (new DynamicPartitionerForIList<TSource>(list));
+ }
+ else
+ {
+ return (new StaticIndexRangePartitionerForIList<TSource>(list));
+ }
+ }
+
+ /// <summary>
+ /// Creates an orderable partitioner from a <see cref="System.Array"/> instance.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in source array.</typeparam>
+ /// <param name="array">The array to be partitioned.</param>
+ /// <param name="loadBalance">
+ /// A Boolean value that indicates whether the created partitioner should dynamically load balance
+ /// between partitions rather than statically partition.
+ /// </param>
+ /// <returns>
+ /// An orderable partitioner based on the input array.
+ /// </returns>
+ public static OrderablePartitioner<TSource> Create<TSource>(TSource[] array, bool loadBalance)
+ {
+ // This implementation uses 'ldelem' instructions for element retrieval, rather than using a
+ // method call.
+
+ if (array == null)
+ {
+ throw new ArgumentNullException("array");
+ }
+ if (loadBalance)
+ {
+ return (new DynamicPartitionerForArray<TSource>(array));
+ }
+ else
+ {
+ return (new StaticIndexRangePartitionerForArray<TSource>(array));
+ }
+ }
+
+ /// <summary>
+ /// Creates an orderable partitioner from a <see cref="System.Collections.Generic.IEnumerable{TSource}"/> instance.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in source enumerable.</typeparam>
+ /// <param name="source">The enumerable to be partitioned.</param>
+ /// <returns>
+ /// An orderable partitioner based on the input array.
+ /// </returns>
+ /// <remarks>
+ /// The ordering used in the created partitioner is determined by the natural order of the elements
+ /// as retrieved from the source enumerable.
+ /// </remarks>
+ public static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source)
+ {
+ return Create<TSource>(source, EnumerablePartitionerOptions.None);
+ }
+
+ /// <summary>
+ /// Creates an orderable partitioner from a <see cref="System.Collections.Generic.IEnumerable{TSource}"/> instance.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in source enumerable.</typeparam>
+ /// <param name="source">The enumerable to be partitioned.</param>
+ /// <param name="partitionerOptions">Options to control the buffering behavior of the partitioner.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="partitionerOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Collections.Concurrent.EnumerablePartitionerOptions"/>.
+ /// </exception>
+ /// <returns>
+ /// An orderable partitioner based on the input array.
+ /// </returns>
+ /// <remarks>
+ /// The ordering used in the created partitioner is determined by the natural order of the elements
+ /// as retrieved from the source enumerable.
+ /// </remarks>
+ public static OrderablePartitioner<TSource> Create<TSource>(IEnumerable<TSource> source, EnumerablePartitionerOptions partitionerOptions)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if ((partitionerOptions & (~EnumerablePartitionerOptions.NoBuffering)) != 0)
+ throw new ArgumentOutOfRangeException("partitionerOptions");
+
+ return (new DynamicPartitionerForIEnumerable<TSource>(source, partitionerOptions));
+ }
+
+ /// <summary>Creates a partitioner that chunks the user-specified range.</summary>
+ /// <param name="fromInclusive">The lower, inclusive bound of the range.</param>
+ /// <param name="toExclusive">The upper, exclusive bound of the range.</param>
+ /// <returns>A partitioner.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="toExclusive"/> argument is
+ /// less than or equal to the <paramref name="fromInclusive"/> argument.</exception>
+ public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive)
+ {
+ // How many chunks do we want to divide the range into? If this is 1, then the
+ // answer is "one chunk per core". Generally, though, you'll achieve better
+ // load balancing on a busy system if you make it higher than 1.
+ int coreOversubscriptionRate = 3;
+
+ if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
+ long rangeSize = (toExclusive - fromInclusive) /
+ (PlatformHelper.ProcessorCount * coreOversubscriptionRate);
+ if (rangeSize == 0) rangeSize = 1;
+ return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
+ }
+
+ /// <summary>Creates a partitioner that chunks the user-specified range.</summary>
+ /// <param name="fromInclusive">The lower, inclusive bound of the range.</param>
+ /// <param name="toExclusive">The upper, exclusive bound of the range.</param>
+ /// <param name="rangeSize">The size of each subrange.</param>
+ /// <returns>A partitioner.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="toExclusive"/> argument is
+ /// less than or equal to the <paramref name="fromInclusive"/> argument.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="rangeSize"/> argument is
+ /// less than or equal to 0.</exception>
+ public static OrderablePartitioner<Tuple<long, long>> Create(long fromInclusive, long toExclusive, long rangeSize)
+ {
+ if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
+ if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize");
+ return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
+ }
+
+ // Private method to parcel out range tuples.
+ private static IEnumerable<Tuple<long, long>> CreateRanges(long fromInclusive, long toExclusive, long rangeSize)
+ {
+ // Enumerate all of the ranges
+ long from, to;
+ bool shouldQuit = false;
+
+ for (long i = fromInclusive; (i < toExclusive) && !shouldQuit; i += rangeSize)
+ {
+ from = i;
+ try { checked { to = i + rangeSize; } }
+ catch (OverflowException)
+ {
+ to = toExclusive;
+ shouldQuit = true;
+ }
+ if (to > toExclusive) to = toExclusive;
+ yield return new Tuple<long, long>(from, to);
+ }
+ }
+
+ /// <summary>Creates a partitioner that chunks the user-specified range.</summary>
+ /// <param name="fromInclusive">The lower, inclusive bound of the range.</param>
+ /// <param name="toExclusive">The upper, exclusive bound of the range.</param>
+ /// <returns>A partitioner.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="toExclusive"/> argument is
+ /// less than or equal to the <paramref name="fromInclusive"/> argument.</exception>
+ public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive)
+ {
+ // How many chunks do we want to divide the range into? If this is 1, then the
+ // answer is "one chunk per core". Generally, though, you'll achieve better
+ // load balancing on a busy system if you make it higher than 1.
+ int coreOversubscriptionRate = 3;
+
+ if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
+ int rangeSize = (toExclusive - fromInclusive) /
+ (PlatformHelper.ProcessorCount * coreOversubscriptionRate);
+ if (rangeSize == 0) rangeSize = 1;
+ return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
+ }
+
+ /// <summary>Creates a partitioner that chunks the user-specified range.</summary>
+ /// <param name="fromInclusive">The lower, inclusive bound of the range.</param>
+ /// <param name="toExclusive">The upper, exclusive bound of the range.</param>
+ /// <param name="rangeSize">The size of each subrange.</param>
+ /// <returns>A partitioner.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="toExclusive"/> argument is
+ /// less than or equal to the <paramref name="fromInclusive"/> argument.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> The <paramref name="rangeSize"/> argument is
+ /// less than or equal to 0.</exception>
+ public static OrderablePartitioner<Tuple<int, int>> Create(int fromInclusive, int toExclusive, int rangeSize)
+ {
+ if (toExclusive <= fromInclusive) throw new ArgumentOutOfRangeException("toExclusive");
+ if (rangeSize <= 0) throw new ArgumentOutOfRangeException("rangeSize");
+ return Partitioner.Create(CreateRanges(fromInclusive, toExclusive, rangeSize), EnumerablePartitionerOptions.NoBuffering); // chunk one range at a time
+ }
+
+ // Private method to parcel out range tuples.
+ private static IEnumerable<Tuple<int, int>> CreateRanges(int fromInclusive, int toExclusive, int rangeSize)
+ {
+ // Enumerate all of the ranges
+ int from, to;
+ bool shouldQuit = false;
+
+ for (int i = fromInclusive; (i < toExclusive) && !shouldQuit; i += rangeSize)
+ {
+ from = i;
+ try { checked { to = i + rangeSize; } }
+ catch (OverflowException)
+ {
+ to = toExclusive;
+ shouldQuit = true;
+ }
+ if (to > toExclusive) to = toExclusive;
+ yield return new Tuple<int, int>(from, to);
+ }
+ }
+
+ #region DynamicPartitionEnumerator_Abstract class
+ /// <summary>
+ /// DynamicPartitionEnumerator_Abstract defines the enumerator for each partition for the dynamic load-balance
+ /// partitioning algorithm.
+ /// - Partition is an enumerator of KeyValuePairs, each corresponding to an item in the data source:
+ /// the key is the index in the source collection; the value is the item itself.
+ /// - a set of such partitions share a reader over data source. The type of the reader is specified by
+ /// TSourceReader.
+ /// - each partition requests a contiguous chunk of elements at a time from the source data. The chunk
+ /// size is initially 1, and doubles every time until it reaches the maximum chunk size.
+ /// The implementation for GrabNextChunk() method has two versions: one for data source of IndexRange
+ /// types (IList and the array), one for data source of IEnumerable.
+ /// - The method "Reset" is not supported for any partitioning algorithm.
+ /// - The implementation for MoveNext() method is same for all dynanmic partitioners, so we provide it
+ /// in this abstract class.
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in the data source</typeparam>
+ /// <typeparam name="TSourceReader">Type of the reader on the data source</typeparam>
+ //TSourceReader is
+ // - IList<TSource>, when source data is IList<TSource>, the shared reader is source data itself
+ // - TSource[], when source data is TSource[], the shared reader is source data itself
+ // - IEnumerator<TSource>, when source data is IEnumerable<TSource>, and the shared reader is an
+ // enumerator of the source data
+ private abstract class DynamicPartitionEnumerator_Abstract<TSource, TSourceReader> : IEnumerator<KeyValuePair<long, TSource>>
+ {
+ //----------------- common fields and constructor for all dynamic partitioners -----------------
+ //--- shared by all dervied class with souce data type: IList, Array, and IEnumerator
+ protected readonly TSourceReader m_sharedReader;
+
+ protected static int s_defaultMaxChunkSize = GetDefaultChunkSize<TSource>();
+
+ //deferred allocating in MoveNext() with initial value 0, to avoid false sharing
+ //we also use the fact that: (m_currentChunkSize==null) means MoveNext is never called on this enumerator
+ protected SharedInt m_currentChunkSize;
+
+ //deferring allocation in MoveNext() with initial value -1, to avoid false sharing
+ protected SharedInt m_localOffset;
+
+ private const int CHUNK_DOUBLING_RATE = 3; // Double the chunk size every this many grabs
+ private int m_doublingCountdown; // Number of grabs remaining until chunk size doubles
+ protected readonly int m_maxChunkSize; // s_defaultMaxChunkSize unless single-chunking is requested by the caller
+
+ // m_sharedIndex shared by this set of partitions, and particularly when m_sharedReader is IEnuerable
+ // it serves as tracking of the natual order of elements in m_sharedReader
+ // the value of this field is passed in from outside (already initialized) by the constructor,
+ protected readonly SharedLong m_sharedIndex;
+
+ protected DynamicPartitionEnumerator_Abstract(TSourceReader sharedReader, SharedLong sharedIndex)
+ : this(sharedReader, sharedIndex, false)
+ {
+ }
+
+ protected DynamicPartitionEnumerator_Abstract(TSourceReader sharedReader, SharedLong sharedIndex, bool useSingleChunking)
+ {
+ m_sharedReader = sharedReader;
+ m_sharedIndex = sharedIndex;
+ m_maxChunkSize = useSingleChunking ? 1 : s_defaultMaxChunkSize;
+ }
+
+ // ---------------- abstract method declarations --------------
+
+ /// <summary>
+ /// Abstract method to request a contiguous chunk of elements from the source collection
+ /// </summary>
+ /// <param name="requestedChunkSize">specified number of elements requested</param>
+ /// <returns>
+ /// true if we successfully reserved at least one element (up to #=requestedChunkSize)
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ //GrabNextChunk does the following:
+ // - grab # of requestedChunkSize elements from source data through shared reader,
+ // - at the time of function returns, m_currentChunkSize is updated with the number of
+ // elements actually got assigned (<=requestedChunkSize).
+ // - GrabNextChunk returns true if at least one element is assigned to this partition;
+ // false if the shared reader already hits the last element of the source data before
+ // we call GrabNextChunk
+ protected abstract bool GrabNextChunk(int requestedChunkSize);
+
+ /// <summary>
+ /// Abstract property, returns whether or not the shared reader has already read the last
+ /// element of the source data
+ /// </summary>
+ protected abstract bool HasNoElementsLeft { get; set; }
+
+ /// <summary>
+ /// Get the current element in the current partition. Property required by IEnumerator interface
+ /// This property is abstract because the implementation is different depending on the type
+ /// of the source data: IList, Array or IEnumerable
+ /// </summary>
+ public abstract KeyValuePair<long, TSource> Current { get; }
+
+ /// <summary>
+ /// Dispose is abstract, and depends on the type of the source data:
+ /// - For source data type IList and Array, the type of the shared reader is just the dataitself.
+ /// We don't do anything in Dispose method for IList and Array.
+ /// - For source data type IEnumerable, the type of the shared reader is an enumerator we created.
+ /// Thus we need to dispose this shared reader enumerator, when there is no more active partitions
+ /// left.
+ /// </summary>
+ public abstract void Dispose();
+
+ /// <summary>
+ /// Reset on partitions is not supported
+ /// </summary>
+ public void Reset()
+ {
+ throw new NotSupportedException();
+ }
+
+
+ /// <summary>
+ /// Get the current element in the current partition. Property required by IEnumerator interface
+ /// </summary>
+ Object IEnumerator.Current
+ {
+ get
+ {
+ return ((DynamicPartitionEnumerator_Abstract<TSource, TSourceReader>)this).Current;
+ }
+ }
+
+ /// <summary>
+ /// Moves to the next element if any.
+ /// Try current chunk first, if the current chunk do not have any elements left, then we
+ /// attempt to grab a chunk from the source collection.
+ /// </summary>
+ /// <returns>
+ /// true if successfully moving to the next position;
+ /// false otherwise, if and only if there is no more elements left in the current chunk
+ /// AND the source collection is exhausted.
+ /// </returns>
+ public bool MoveNext()
+ {
+ //perform deferred allocating of the local variables.
+ if (m_localOffset == null)
+ {
+ Contract.Assert(m_currentChunkSize == null);
+ m_localOffset = new SharedInt(-1);
+ m_currentChunkSize = new SharedInt(0);
+ m_doublingCountdown = CHUNK_DOUBLING_RATE;
+ }
+
+ if (m_localOffset.Value < m_currentChunkSize.Value - 1)
+ //attempt to grab the next element from the local chunk
+ {
+ m_localOffset.Value++;
+ return true;
+ }
+ else
+ //otherwise it means we exhausted the local chunk
+ //grab a new chunk from the source enumerator
+ {
+ // The second part of the || condition is necessary to handle the case when MoveNext() is called
+ // after a previous MoveNext call returned false.
+ Contract.Assert(m_localOffset.Value == m_currentChunkSize.Value - 1 || m_currentChunkSize.Value == 0);
+
+ //set the requested chunk size to a proper value
+ int requestedChunkSize;
+ if (m_currentChunkSize.Value == 0) //first time grabbing from source enumerator
+ {
+ requestedChunkSize = 1;
+ }
+ else if (m_doublingCountdown > 0)
+ {
+ requestedChunkSize = m_currentChunkSize.Value;
+ }
+ else
+ {
+ requestedChunkSize = Math.Min(m_currentChunkSize.Value * 2, m_maxChunkSize);
+ m_doublingCountdown = CHUNK_DOUBLING_RATE; // reset
+ }
+
+ // Decrement your doubling countdown
+ m_doublingCountdown--;
+
+ Contract.Assert(requestedChunkSize > 0 && requestedChunkSize <= m_maxChunkSize);
+ //GrabNextChunk will update the value of m_currentChunkSize
+ if (GrabNextChunk(requestedChunkSize))
+ {
+ Contract.Assert(m_currentChunkSize.Value <= requestedChunkSize && m_currentChunkSize.Value > 0);
+ m_localOffset.Value = 0;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Dynamic Partitioner for source data of IEnuemrable<> type
+ /// <summary>
+ /// Inherits from DynamicPartitioners
+ /// Provides customized implementation of GetOrderableDynamicPartitions_Factory method, to return an instance
+ /// of EnumerableOfPartitionsForIEnumerator defined internally
+ /// </summary>
+ /// <typeparam name="TSource">Type of elements in the source data</typeparam>
+ private class DynamicPartitionerForIEnumerable<TSource> : OrderablePartitioner<TSource>
+ {
+ IEnumerable<TSource> m_source;
+ readonly bool m_useSingleChunking;
+
+ //constructor
+ internal DynamicPartitionerForIEnumerable(IEnumerable<TSource> source, EnumerablePartitionerOptions partitionerOptions)
+ : base(true, false, true)
+ {
+ m_source = source;
+ m_useSingleChunking = ((partitionerOptions & EnumerablePartitionerOptions.NoBuffering) != 0);
+ }
+
+ /// <summary>
+ /// Overrides OrderablePartitioner.GetOrderablePartitions.
+ /// Partitions the underlying collection into the given number of orderable partitions.
+ /// </summary>
+ /// <param name="partitionCount">number of partitions requested</param>
+ /// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
+ override public IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
+ {
+ if (partitionCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("partitionCount");
+ }
+ IEnumerator<KeyValuePair<long, TSource>>[] partitions
+ = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
+
+ IEnumerable<KeyValuePair<long, TSource>> partitionEnumerable = new InternalPartitionEnumerable(m_source.GetEnumerator(), m_useSingleChunking, true);
+ for (int i = 0; i < partitionCount; i++)
+ {
+ partitions[i] = partitionEnumerable.GetEnumerator();
+ }
+ return partitions;
+ }
+
+ /// <summary>
+ /// Overrides OrderablePartitioner.GetOrderableDyanmicPartitions
+ /// </summary>
+ /// <returns>a enumerable collection of orderable partitions</returns>
+ override public IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
+ {
+ return new InternalPartitionEnumerable(m_source.GetEnumerator(), m_useSingleChunking, false);
+ }
+
+ /// <summary>
+ /// Whether additional partitions can be created dynamically.
+ /// </summary>
+ override public bool SupportsDynamicPartitions
+ {
+ get { return true; }
+ }
+
+ #region Internal classes: InternalPartitionEnumerable, InternalPartitionEnumerator
+ /// <summary>
+ /// Provides customized implementation for source data of IEnumerable
+ /// Different from the counterpart for IList/Array, this enumerable maintains several additional fields
+ /// shared by the partitions it owns, including a boolean "m_hasNoElementsLef", a shared lock, and a
+ /// shared count "m_activePartitionCount" used to track active partitions when they were created statically
+ /// </summary>
+ private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>, IDisposable
+ {
+ //reader through which we access the source data
+ private readonly IEnumerator<TSource> m_sharedReader;
+ private SharedLong m_sharedIndex;//initial value -1
+
+ private volatile KeyValuePair<long, TSource>[] m_FillBuffer; // intermediate buffer to reduce locking
+ private volatile int m_FillBufferSize; // actual number of elements in m_FillBuffer. Will start
+ // at m_FillBuffer.Length, and might be reduced during the last refill
+ private volatile int m_FillBufferCurrentPosition; //shared value to be accessed by Interlock.Increment only
+ private volatile int m_activeCopiers; //number of active copiers
+
+ //fields shared by all partitions that this Enumerable owns, their allocation is deferred
+ private SharedBool m_hasNoElementsLeft; // no elements left at all.
+ private SharedBool m_sourceDepleted; // no elements left in the enumerator, but there may be elements in the Fill Buffer
+
+ //shared synchronization lock, created by this Enumerable
+ private object m_sharedLock;//deferring allocation by enumerator
+
+ private bool m_disposed;
+
+ // If dynamic partitioning, then m_activePartitionCount == null
+ // If static partitioning, then it keeps track of active partition count
+ private SharedInt m_activePartitionCount;
+
+ // records whether or not the user has requested single-chunking behavior
+ private readonly bool m_useSingleChunking;
+
+ internal InternalPartitionEnumerable(IEnumerator<TSource> sharedReader, bool useSingleChunking, bool isStaticPartitioning)
+ {
+ m_sharedReader = sharedReader;
+ m_sharedIndex = new SharedLong(-1);
+ m_hasNoElementsLeft = new SharedBool(false);
+ m_sourceDepleted = new SharedBool(false);
+ m_sharedLock = new object();
+ m_useSingleChunking = useSingleChunking;
+
+ // Only allocate the fill-buffer if single-chunking is not in effect
+ if (!m_useSingleChunking)
+ {
+ // Time to allocate the fill buffer which is used to reduce the contention on the shared lock.
+ // First pick the buffer size multiplier. We use 4 for when there are more than 4 cores, and just 1 for below. This is based on empirical evidence.
+ int fillBufferMultiplier = (PlatformHelper.ProcessorCount > 4) ? 4 : 1;
+
+ // and allocate the fill buffer using these two numbers
+ m_FillBuffer = new KeyValuePair<long, TSource>[fillBufferMultiplier * Partitioner.GetDefaultChunkSize<TSource>()];
+ }
+
+ if (isStaticPartitioning)
+ {
+ // If this object is created for static partitioning (ie. via GetPartitions(int partitionCount),
+ // GetOrderablePartitions(int partitionCount)), we track the active partitions, in order to dispose
+ // this object when all the partitions have been disposed.
+ m_activePartitionCount = new SharedInt(0);
+ }
+ else
+ {
+ // Otherwise this object is created for dynamic partitioning (ie, via GetDynamicPartitions(),
+ // GetOrderableDynamicPartitions()), we do not need tracking. This object must be disposed
+ // explicitly
+ m_activePartitionCount = null;
+ }
+ }
+
+ public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
+ {
+ if (m_disposed)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("PartitionerStatic_CanNotCallGetEnumeratorAfterSourceHasBeenDisposed"));
+ }
+ else
+ {
+ return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex,
+ m_hasNoElementsLeft, m_sharedLock, m_activePartitionCount, this, m_useSingleChunking);
+ }
+ }
+
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((InternalPartitionEnumerable)this).GetEnumerator();
+ }
+
+
+ ///////////////////
+ //
+ // Used by GrabChunk_Buffered()
+ private void TryCopyFromFillBuffer(KeyValuePair<long, TSource>[] destArray,
+ int requestedChunkSize,
+ ref int actualNumElementsGrabbed)
+ {
+ actualNumElementsGrabbed = 0;
+
+
+ // making a local defensive copy of the fill buffer reference, just in case it gets nulled out
+ KeyValuePair<long, TSource>[] fillBufferLocalRef = m_FillBuffer;
+ if (fillBufferLocalRef == null) return;
+
+ // first do a quick check, and give up if the current position is at the end
+ // so that we don't do an unncessary pair of Interlocked.Increment / Decrement calls
+ if (m_FillBufferCurrentPosition >= m_FillBufferSize)
+ {
+ return; // no elements in the buffer to copy from
+ }
+
+ // We might have a chance to grab elements from the buffer. We will know for sure
+ // when we do the Interlocked.Add below.
+ // But first we must register as a potential copier in order to make sure
+ // the elements we're copying from don't get overwritten by another thread
+ // that starts refilling the buffer right after our Interlocked.Add.
+ Interlocked.Increment(ref m_activeCopiers);
+
+ int endPos = Interlocked.Add(ref m_FillBufferCurrentPosition, requestedChunkSize);
+ int beginPos = endPos - requestedChunkSize;
+
+ if (beginPos < m_FillBufferSize)
+ {
+ // adjust index and do the actual copy
+ actualNumElementsGrabbed = (endPos < m_FillBufferSize) ? endPos : m_FillBufferSize - beginPos;
+ Array.Copy(fillBufferLocalRef, beginPos, destArray, 0, actualNumElementsGrabbed);
+ }
+
+ // let the record show we are no longer accessing the buffer
+ Interlocked.Decrement(ref m_activeCopiers);
+ }
+
+ /// <summary>
+ /// This is the common entry point for consuming items from the source enumerable
+ /// </summary>
+ /// <returns>
+ /// true if we successfully reserved at least one element
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ internal bool GrabChunk(KeyValuePair<long, TSource>[] destArray, int requestedChunkSize, ref int actualNumElementsGrabbed)
+ {
+ actualNumElementsGrabbed = 0;
+
+ if (m_hasNoElementsLeft.Value)
+ {
+ return false;
+ }
+
+ if (m_useSingleChunking)
+ {
+ return GrabChunk_Single(destArray, requestedChunkSize, ref actualNumElementsGrabbed);
+ }
+ else
+ {
+ return GrabChunk_Buffered(destArray, requestedChunkSize, ref actualNumElementsGrabbed);
+ }
+ }
+
+ /// <summary>
+ /// Version of GrabChunk that grabs a single element at a time from the source enumerable
+ /// </summary>
+ /// <returns>
+ /// true if we successfully reserved an element
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ internal bool GrabChunk_Single(KeyValuePair<long,TSource>[] destArray, int requestedChunkSize, ref int actualNumElementsGrabbed)
+ {
+ Contract.Assert(m_useSingleChunking, "Expected m_useSingleChecking to be true");
+ Contract.Assert(requestedChunkSize == 1, "Got requested chunk size of " + requestedChunkSize + " when single-chunking was on");
+ Contract.Assert(actualNumElementsGrabbed == 0, "Expected actualNumElementsGrabbed == 0, instead it is " + actualNumElementsGrabbed);
+ Contract.Assert(destArray.Length == 1, "Expected destArray to be of length 1, instead its length is " + destArray.Length);
+
+ lock (m_sharedLock)
+ {
+ if (m_hasNoElementsLeft.Value) return false;
+
+ try
+ {
+ if (m_sharedReader.MoveNext())
+ {
+ m_sharedIndex.Value = checked(m_sharedIndex.Value + 1);
+ destArray[0]
+ = new KeyValuePair<long, TSource>(m_sharedIndex.Value,
+ m_sharedReader.Current);
+ actualNumElementsGrabbed = 1;
+ return true;
+ }
+ else
+ {
+ //if MoveNext() return false, we set the flag to inform other partitions
+ m_sourceDepleted.Value = true;
+ m_hasNoElementsLeft.Value = true;
+ return false;
+ }
+ }
+ catch
+ {
+ // On an exception, make sure that no additional items are hereafter enumerated
+ m_sourceDepleted.Value = true;
+ m_hasNoElementsLeft.Value = true;
+ throw;
+ }
+ }
+ }
+
+
+
+ /// <summary>
+ /// Version of GrabChunk that uses buffering scheme to grab items out of source enumerable
+ /// </summary>
+ /// <returns>
+ /// true if we successfully reserved at least one element (up to #=requestedChunkSize)
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ internal bool GrabChunk_Buffered(KeyValuePair<long,TSource>[] destArray, int requestedChunkSize, ref int actualNumElementsGrabbed)
+ {
+ Contract.Assert(requestedChunkSize > 0);
+ Contract.Assert(!m_useSingleChunking, "Did not expect to be in single-chunking mode");
+
+ TryCopyFromFillBuffer(destArray, requestedChunkSize, ref actualNumElementsGrabbed);
+
+ if (actualNumElementsGrabbed == requestedChunkSize)
+ {
+ // that was easy.
+ return true;
+ }
+ else if (m_sourceDepleted.Value)
+ {
+ // looks like we both reached the end of the fill buffer, and the source was depleted previously
+ // this means no more work to do for any other worker
+ m_hasNoElementsLeft.Value = true;
+ m_FillBuffer = null;
+ return (actualNumElementsGrabbed > 0);
+ }
+
+
+ //
+ // now's the time to take the shared lock and enumerate
+ //
+ lock (m_sharedLock)
+ {
+ if (m_sourceDepleted.Value)
+ {
+ return (actualNumElementsGrabbed > 0);
+ }
+
+ try
+ {
+ // we need to make sure all array copiers are finished
+ if (m_activeCopiers > 0)
+ {
+ SpinWait sw = new SpinWait();
+ while( m_activeCopiers > 0) sw.SpinOnce();
+ }
+
+ Contract.Assert(m_sharedIndex != null); //already been allocated in MoveNext() before calling GrabNextChunk
+
+ // Now's the time to actually enumerate the source
+
+ // We first fill up the requested # of elements in the caller's array
+ // continue from the where TryCopyFromFillBuffer() left off
+ for (; actualNumElementsGrabbed < requestedChunkSize; actualNumElementsGrabbed++)
+ {
+ if (m_sharedReader.MoveNext())
+ {
+ m_sharedIndex.Value = checked(m_sharedIndex.Value + 1);
+ destArray[actualNumElementsGrabbed]
+ = new KeyValuePair<long, TSource>(m_sharedIndex.Value,
+ m_sharedReader.Current);
+ }
+ else
+ {
+ //if MoveNext() return false, we set the flag to inform other partitions
+ m_sourceDepleted.Value = true;
+ break;
+ }
+ }
+
+ // taking a local snapshot of m_FillBuffer in case some other thread decides to null out m_FillBuffer
+ // in the entry of this method after observing m_sourceCompleted = true
+ var localFillBufferRef = m_FillBuffer;
+
+ // If the big buffer seems to be depleted, we will also fill that up while we are under the lock
+ // Note that this is the only place that m_FillBufferCurrentPosition can be reset
+ if (m_sourceDepleted.Value == false && localFillBufferRef != null &&
+ m_FillBufferCurrentPosition >= localFillBufferRef.Length)
+ {
+ for (int i = 0; i < localFillBufferRef.Length; i++)
+ {
+ if( m_sharedReader.MoveNext())
+ {
+ m_sharedIndex.Value = checked(m_sharedIndex.Value + 1);
+ localFillBufferRef[i]
+ = new KeyValuePair<long, TSource>(m_sharedIndex.Value,
+ m_sharedReader.Current);
+ }
+ else
+ {
+ // No more elements left in the enumerator.
+ // Record this, so that the next request can skip the lock
+ m_sourceDepleted.Value = true;
+
+ // also record the current count in m_FillBufferSize
+ m_FillBufferSize = i;
+
+ // and exit the for loop so that we don't keep incrementing m_FillBufferSize
+ break;
+ }
+
+ }
+
+ m_FillBufferCurrentPosition = 0;
+ }
+
+
+ }
+ catch
+ {
+ // If an exception occurs, don't let the other enumerators try to enumerate.
+ // NOTE: this could instead throw an InvalidOperationException, but that would be unexpected
+ // and not helpful to the end user. We know the root cause is being communicated already.)
+ m_sourceDepleted.Value = true;
+ m_hasNoElementsLeft.Value = true;
+ throw;
+ }
+ }
+
+ return (actualNumElementsGrabbed > 0);
+ }
+
+ public void Dispose()
+ {
+ if (!m_disposed)
+ {
+ m_disposed = true;
+ m_sharedReader.Dispose();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Inherits from DynamicPartitionEnumerator_Abstract directly
+ /// Provides customized implementation for: GrabNextChunk, HasNoElementsLeft, Current, Dispose
+ /// </summary>
+ private class InternalPartitionEnumerator : DynamicPartitionEnumerator_Abstract<TSource, IEnumerator<TSource>>
+ {
+ //---- fields ----
+ //cached local copy of the current chunk
+ private KeyValuePair<long, TSource>[] m_localList; //defer allocating to avoid false sharing
+
+ // the values of the following two fields are passed in from
+ // outside(already initialized) by the constructor,
+ private readonly SharedBool m_hasNoElementsLeft;
+ private readonly object m_sharedLock;
+ private readonly SharedInt m_activePartitionCount;
+ private InternalPartitionEnumerable m_enumerable;
+
+ //constructor
+ internal InternalPartitionEnumerator(
+ IEnumerator<TSource> sharedReader,
+ SharedLong sharedIndex,
+ SharedBool hasNoElementsLeft,
+ object sharedLock,
+ SharedInt activePartitionCount,
+ InternalPartitionEnumerable enumerable,
+ bool useSingleChunking)
+ : base(sharedReader, sharedIndex, useSingleChunking)
+ {
+ m_hasNoElementsLeft = hasNoElementsLeft;
+ m_sharedLock = sharedLock;
+ m_enumerable = enumerable;
+ m_activePartitionCount = activePartitionCount;
+
+ if (m_activePartitionCount != null)
+ {
+ // If static partitioning, we need to increase the active partition count.
+ Interlocked.Increment(ref m_activePartitionCount.Value);
+ }
+ }
+
+ //overriding methods
+
+ /// <summary>
+ /// Reserves a contiguous range of elements from source data
+ /// </summary>
+ /// <param name="requestedChunkSize">specified number of elements requested</param>
+ /// <returns>
+ /// true if we successfully reserved at least one element (up to #=requestedChunkSize)
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ override protected bool GrabNextChunk(int requestedChunkSize)
+ {
+ Contract.Assert(requestedChunkSize > 0);
+
+ if (HasNoElementsLeft)
+ {
+ return false;
+ }
+
+ // defer allocation to avoid false sharing
+ if (m_localList == null)
+ {
+ m_localList = new KeyValuePair<long, TSource>[m_maxChunkSize];
+ }
+
+ // make the actual call to the enumerable that grabs a chunk
+ return m_enumerable.GrabChunk(m_localList, requestedChunkSize, ref m_currentChunkSize.Value);
+ }
+
+ /// <summary>
+ /// Returns whether or not the shared reader has already read the last
+ /// element of the source data
+ /// </summary>
+ /// <remarks>
+ /// We cannot call m_sharedReader.MoveNext(), to see if it hits the last element
+ /// or not, because we can't undo MoveNext(). Thus we need to maintain a shared
+ /// boolean value m_hasNoElementsLeft across all partitions
+ /// </remarks>
+ override protected bool HasNoElementsLeft
+ {
+ get { return m_hasNoElementsLeft.Value; }
+ set
+ {
+ //we only set it from false to true once
+ //we should never set it back in any circumstances
+ Contract.Assert(value);
+ Contract.Assert(!m_hasNoElementsLeft.Value);
+ m_hasNoElementsLeft.Value = true;
+ }
+ }
+
+ override public KeyValuePair<long, TSource> Current
+ {
+ get
+ {
+ //verify that MoveNext is at least called once before Current is called
+ if (m_currentChunkSize == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
+ }
+ Contract.Assert(m_localList != null);
+ Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value);
+ return (m_localList[m_localOffset.Value]);
+ }
+ }
+
+ override public void Dispose()
+ {
+ // If this is static partitioning, ie. m_activePartitionCount != null, since the current partition
+ // is disposed, we decrement the number of active partitions for the shared reader.
+ if (m_activePartitionCount != null && Interlocked.Decrement(ref m_activePartitionCount.Value) == 0)
+ {
+ // If the number of active partitions becomes 0, we need to dispose the shared
+ // reader we created in the m_enumerable object.
+ m_enumerable.Dispose();
+ }
+ // If this is dynamic partitioning, ie. m_activePartitionCount != null, then m_enumerable needs to
+ // be disposed explicitly by the user, and we do not need to anything here
+ }
+ }
+ #endregion
+
+ }
+ #endregion
+
+ #region Dynamic Partitioner for source data of IndexRange types (IList<> and Array<>)
+ /// <summary>
+ /// Dynamic load-balance partitioner. This class is abstract and to be derived from by
+ /// the customized partitioner classes for IList, Array, and IEnumerable
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in the source data</typeparam>
+ /// <typeparam name="TCollection"> Type of the source data collection</typeparam>
+ private abstract class DynamicPartitionerForIndexRange_Abstract<TSource, TCollection> : OrderablePartitioner<TSource>
+ {
+ // TCollection can be: IList<TSource>, TSource[] and IEnumerable<TSource>
+ // Derived classes specify TCollection, and implement the abstract method GetOrderableDynamicPartitions_Factory accordingly
+ TCollection m_data;
+
+ /// <summary>
+ /// Constructs a new orderable partitioner
+ /// </summary>
+ /// <param name="data">source data collection</param>
+ protected DynamicPartitionerForIndexRange_Abstract(TCollection data)
+ : base(true, false, true)
+ {
+ m_data = data;
+ }
+
+ /// <summary>
+ /// Partition the source data and create an enumerable over the resulting partitions.
+ /// </summary>
+ /// <param name="data">the source data collection</param>
+ /// <returns>an enumerable of partitions of </returns>
+ protected abstract IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(TCollection data);
+
+ /// <summary>
+ /// Overrides OrderablePartitioner.GetOrderablePartitions.
+ /// Partitions the underlying collection into the given number of orderable partitions.
+ /// </summary>
+ /// <param name="partitionCount">number of partitions requested</param>
+ /// <returns>A list containing <paramref name="partitionCount"/> enumerators.</returns>
+ override public IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
+ {
+ if (partitionCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("partitionCount");
+ }
+ IEnumerator<KeyValuePair<long, TSource>>[] partitions
+ = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
+ IEnumerable<KeyValuePair<long, TSource>> partitionEnumerable = GetOrderableDynamicPartitions_Factory(m_data);
+ for (int i = 0; i < partitionCount; i++)
+ {
+ partitions[i] = partitionEnumerable.GetEnumerator();
+ }
+ return partitions;
+ }
+
+ /// <summary>
+ /// Overrides OrderablePartitioner.GetOrderableDyanmicPartitions
+ /// </summary>
+ /// <returns>a enumerable collection of orderable partitions</returns>
+ override public IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions()
+ {
+ return GetOrderableDynamicPartitions_Factory(m_data);
+ }
+
+ /// <summary>
+ /// Whether additional partitions can be created dynamically.
+ /// </summary>
+ override public bool SupportsDynamicPartitions
+ {
+ get { return true; }
+ }
+
+ }
+
+ /// <summary>
+ /// Defines dynamic partition for source data of IList and Array.
+ /// This class inherits DynamicPartitionEnumerator_Abstract
+ /// - implements GrabNextChunk, HasNoElementsLeft, and Dispose methods for IList and Array
+ /// - Current property still remains abstract, implementation is different for IList and Array
+ /// - introduces another abstract method SourceCount, which returns the number of elements in
+ /// the source data. Implementation differs for IList and Array
+ /// </summary>
+ /// <typeparam name="TSource">Type of the elements in the data source</typeparam>
+ /// <typeparam name="TSourceReader">Type of the reader on the source data</typeparam>
+ private abstract class DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, TSourceReader> : DynamicPartitionEnumerator_Abstract<TSource, TSourceReader>
+ {
+ //fields
+ protected int m_startIndex; //initially zero
+
+ //constructor
+ protected DynamicPartitionEnumeratorForIndexRange_Abstract(TSourceReader sharedReader, SharedLong sharedIndex)
+ : base(sharedReader, sharedIndex)
+ {
+ }
+
+ //abstract methods
+ //the Current property is still abstract, and will be implemented by derived classes
+ //we add another abstract method SourceCount to get the number of elements from the source reader
+
+ /// <summary>
+ /// Get the number of elements from the source reader.
+ /// It calls IList.Count or Array.Length
+ /// </summary>
+ protected abstract int SourceCount { get; }
+
+ //overriding methods
+
+ /// <summary>
+ /// Reserves a contiguous range of elements from source data
+ /// </summary>
+ /// <param name="requestedChunkSize">specified number of elements requested</param>
+ /// <returns>
+ /// true if we successfully reserved at least one element (up to #=requestedChunkSize)
+ /// false if all elements in the source collection have been reserved.
+ /// </returns>
+ override protected bool GrabNextChunk(int requestedChunkSize)
+ {
+ Contract.Assert(requestedChunkSize > 0);
+
+ while (!HasNoElementsLeft)
+ {
+ Contract.Assert(m_sharedIndex != null);
+ // use the new Volatile.Read method because it is cheaper than Interlocked.Read on AMD64 architecture
+ long oldSharedIndex = Volatile.Read(ref m_sharedIndex.Value);
+
+ if (HasNoElementsLeft)
+ {
+ //HasNoElementsLeft situation changed from false to true immediately
+ //and oldSharedIndex becomes stale
+ return false;
+ }
+
+ //there won't be overflow, because the index of IList/array is int, and we
+ //have casted it to long.
+ long newSharedIndex = Math.Min(SourceCount - 1, oldSharedIndex + requestedChunkSize);
+
+
+ //the following CAS, if successful, reserves a chunk of elements [oldSharedIndex+1, newSharedIndex]
+ //inclusive in the source collection
+ if (Interlocked.CompareExchange(ref m_sharedIndex.Value, newSharedIndex, oldSharedIndex)
+ == oldSharedIndex)
+ {
+ //set up local indexes.
+ //m_currentChunkSize is always set to requestedChunkSize when source data had
+ //enough elements of what we requested
+ m_currentChunkSize.Value = (int)(newSharedIndex - oldSharedIndex);
+ m_localOffset.Value = -1;
+ m_startIndex = (int)(oldSharedIndex + 1);
+ return true;
+ }
+ }
+ //didn't get any element, return false;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns whether or not the shared reader has already read the last
+ /// element of the source data
+ /// </summary>
+ override protected bool HasNoElementsLeft
+ {
+ get
+ {
+ Contract.Assert(m_sharedIndex != null);
+ // use the new Volatile.Read method because it is cheaper than Interlocked.Read on AMD64 architecture
+ return Volatile.Read(ref m_sharedIndex.Value) >= SourceCount - 1;
+ }
+ set
+ {
+ Contract.Assert(false);
+ }
+ }
+
+ /// <summary>
+ /// For source data type IList and Array, the type of the shared reader is just the data itself.
+ /// We don't do anything in Dispose method for IList and Array.
+ /// </summary>
+ override public void Dispose()
+ { }
+ }
+
+
+ /// <summary>
+ /// Inherits from DynamicPartitioners
+ /// Provides customized implementation of GetOrderableDynamicPartitions_Factory method, to return an instance
+ /// of EnumerableOfPartitionsForIList defined internally
+ /// </summary>
+ /// <typeparam name="TSource">Type of elements in the source data</typeparam>
+ private class DynamicPartitionerForIList<TSource> : DynamicPartitionerForIndexRange_Abstract<TSource, IList<TSource>>
+ {
+ //constructor
+ internal DynamicPartitionerForIList(IList<TSource> source)
+ : base(source)
+ { }
+
+ //override methods
+ override protected IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(IList<TSource> m_data)
+ {
+ //m_data itself serves as shared reader
+ return new InternalPartitionEnumerable(m_data);
+ }
+
+ /// <summary>
+ /// Inherits from PartitionList_Abstract
+ /// Provides customized implementation for source data of IList
+ /// </summary>
+ private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>
+ {
+ //reader through which we access the source data
+ private readonly IList<TSource> m_sharedReader;
+ private SharedLong m_sharedIndex;
+
+ internal InternalPartitionEnumerable(IList<TSource> sharedReader)
+ {
+ m_sharedReader = sharedReader;
+ m_sharedIndex = new SharedLong(-1);
+ }
+
+ public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
+ {
+ return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((InternalPartitionEnumerable)this).GetEnumerator();
+ }
+ }
+
+ /// <summary>
+ /// Inherits from DynamicPartitionEnumeratorForIndexRange_Abstract
+ /// Provides customized implementation of SourceCount property and Current property for IList
+ /// </summary>
+ private class InternalPartitionEnumerator : DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, IList<TSource>>
+ {
+ //constructor
+ internal InternalPartitionEnumerator(IList<TSource> sharedReader, SharedLong sharedIndex)
+ : base(sharedReader, sharedIndex)
+ { }
+
+ //overriding methods
+ override protected int SourceCount
+ {
+ get { return m_sharedReader.Count; }
+ }
+ /// <summary>
+ /// return a KeyValuePair of the current element and its key
+ /// </summary>
+ override public KeyValuePair<long, TSource> Current
+ {
+ get
+ {
+ //verify that MoveNext is at least called once before Current is called
+ if (m_currentChunkSize == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
+ }
+
+ Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value);
+ return new KeyValuePair<long, TSource>(m_startIndex + m_localOffset.Value,
+ m_sharedReader[m_startIndex + m_localOffset.Value]);
+ }
+ }
+ }
+ }
+
+
+
+ /// <summary>
+ /// Inherits from DynamicPartitioners
+ /// Provides customized implementation of GetOrderableDynamicPartitions_Factory method, to return an instance
+ /// of EnumerableOfPartitionsForArray defined internally
+ /// </summary>
+ /// <typeparam name="TSource">Type of elements in the source data</typeparam>
+ private class DynamicPartitionerForArray<TSource> : DynamicPartitionerForIndexRange_Abstract<TSource, TSource[]>
+ {
+ //constructor
+ internal DynamicPartitionerForArray(TSource[] source)
+ : base(source)
+ { }
+
+ //override methods
+ override protected IEnumerable<KeyValuePair<long, TSource>> GetOrderableDynamicPartitions_Factory(TSource[] m_data)
+ {
+ return new InternalPartitionEnumerable(m_data);
+ }
+
+ /// <summary>
+ /// Inherits from PartitionList_Abstract
+ /// Provides customized implementation for source data of Array
+ /// </summary>
+ private class InternalPartitionEnumerable : IEnumerable<KeyValuePair<long, TSource>>
+ {
+ //reader through which we access the source data
+ private readonly TSource[] m_sharedReader;
+ private SharedLong m_sharedIndex;
+
+ internal InternalPartitionEnumerable(TSource[] sharedReader)
+ {
+ m_sharedReader = sharedReader;
+ m_sharedIndex = new SharedLong(-1);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((InternalPartitionEnumerable)this).GetEnumerator();
+ }
+
+
+ public IEnumerator<KeyValuePair<long, TSource>> GetEnumerator()
+ {
+ return new InternalPartitionEnumerator(m_sharedReader, m_sharedIndex);
+ }
+ }
+
+ /// <summary>
+ /// Inherits from DynamicPartitionEnumeratorForIndexRange_Abstract
+ /// Provides customized implementation of SourceCount property and Current property for Array
+ /// </summary>
+ private class InternalPartitionEnumerator : DynamicPartitionEnumeratorForIndexRange_Abstract<TSource, TSource[]>
+ {
+ //constructor
+ internal InternalPartitionEnumerator(TSource[] sharedReader, SharedLong sharedIndex)
+ : base(sharedReader, sharedIndex)
+ { }
+
+ //overriding methods
+ override protected int SourceCount
+ {
+ get { return m_sharedReader.Length; }
+ }
+
+ override public KeyValuePair<long, TSource> Current
+ {
+ get
+ {
+ //verify that MoveNext is at least called once before Current is called
+ if (m_currentChunkSize == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
+ }
+
+ Contract.Assert(m_localOffset.Value >= 0 && m_localOffset.Value < m_currentChunkSize.Value);
+ return new KeyValuePair<long, TSource>(m_startIndex + m_localOffset.Value,
+ m_sharedReader[m_startIndex + m_localOffset.Value]);
+ }
+ }
+ }
+ }
+ #endregion
+
+
+ #region Static partitioning for IList and Array, abstract classes
+ /// <summary>
+ /// Static partitioning over IList.
+ /// - dynamic and load-balance
+ /// - Keys are ordered within each partition
+ /// - Keys are ordered across partitions
+ /// - Keys are normalized
+ /// - Number of partitions is fixed once specified, and the elements of the source data are
+ /// distributed to each partition as evenly as possible.
+ /// </summary>
+ /// <typeparam name="TSource">type of the elements</typeparam>
+ /// <typeparam name="TCollection">Type of the source data collection</typeparam>
+ private abstract class StaticIndexRangePartitioner<TSource, TCollection> : OrderablePartitioner<TSource>
+ {
+ protected StaticIndexRangePartitioner()
+ : base(true, true, true)
+ { }
+
+ /// <summary>
+ /// Abstract method to return the number of elements in the source data
+ /// </summary>
+ protected abstract int SourceCount { get; }
+
+ /// <summary>
+ /// Abstract method to create a partition that covers a range over source data,
+ /// starting from "startIndex", ending at "endIndex"
+ /// </summary>
+ /// <param name="startIndex">start index of the current partition on the source data</param>
+ /// <param name="endIndex">end index of the current partition on the source data</param>
+ /// <returns>a partition enumerator over the specified range</returns>
+ // The partitioning algorithm is implemented in GetOrderablePartitions method
+ // This method delegates according to source data type IList/Array
+ protected abstract IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex);
+
+ /// <summary>
+ /// Overrides OrderablePartitioner.GetOrderablePartitions
+ /// Return a list of partitions, each of which enumerate a fixed part of the source data
+ /// The elements of the source data are distributed to each partition as evenly as possible.
+ /// Specifically, if the total number of elements is N, and number of partitions is x, and N = a*x +b,
+ /// where a is the quotient, and b is the remainder. Then the first b partitions each has a + 1 elements,
+ /// and the last x-b partitions each has a elements.
+ /// For example, if N=10, x =3, then
+ /// partition 0 ranges [0,3],
+ /// partition 1 ranges [4,6],
+ /// partition 2 ranges [7,9].
+ /// This also takes care of the situation of (x&gt;N), the last x-N partitions are empty enumerators.
+ /// An empty enumerator is indicated by
+ /// (m_startIndex == list.Count &amp;&amp; m_endIndex == list.Count -1)
+ /// </summary>
+ /// <param name="partitionCount">specified number of partitions</param>
+ /// <returns>a list of partitions</returns>
+ override public IList<IEnumerator<KeyValuePair<long, TSource>>> GetOrderablePartitions(int partitionCount)
+ {
+ if (partitionCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("partitionCount");
+ }
+
+ int quotient, remainder;
+ quotient = Math.DivRem(SourceCount, partitionCount, out remainder);
+
+ IEnumerator<KeyValuePair<long, TSource>>[] partitions = new IEnumerator<KeyValuePair<long, TSource>>[partitionCount];
+ int lastEndIndex = -1;
+ for (int i = 0; i < partitionCount; i++)
+ {
+ int startIndex = lastEndIndex + 1;
+
+ if (i < remainder)
+ {
+ lastEndIndex = startIndex + quotient;
+ }
+ else
+ {
+ lastEndIndex = startIndex + quotient - 1;
+ }
+ partitions[i] = CreatePartition(startIndex, lastEndIndex);
+ }
+ return partitions;
+ }
+ }
+
+ /// <summary>
+ /// Static Partition for IList/Array.
+ /// This class implements all methods required by IEnumerator interface, except for the Current property.
+ /// Current Property is different for IList and Array. Arrays calls 'ldelem' instructions for faster element
+ /// retrieval.
+ /// </summary>
+ //We assume the source collection is not being updated concurrently. Otherwise it will break the
+ //static partitioning, since each partition operates on the source collection directly, it does
+ //not have a local cache of the elements assigned to them.
+ private abstract class StaticIndexRangePartition<TSource> : IEnumerator<KeyValuePair<long, TSource>>
+ {
+ //the start and end position in the source collection for the current partition
+ //the partition is empty if and only if
+ // (m_startIndex == m_data.Count && m_endIndex == m_data.Count-1)
+ protected readonly int m_startIndex;
+ protected readonly int m_endIndex;
+
+ //the current index of the current partition while enumerating on the source collection
+ protected volatile int m_offset;
+
+ /// <summary>
+ /// Constructs an instance of StaticIndexRangePartition
+ /// </summary>
+ /// <param name="startIndex">the start index in the source collection for the current partition </param>
+ /// <param name="endIndex">the end index in the source collection for the current partition</param>
+ protected StaticIndexRangePartition(int startIndex, int endIndex)
+ {
+ m_startIndex = startIndex;
+ m_endIndex = endIndex;
+ m_offset = startIndex - 1;
+ }
+
+ /// <summary>
+ /// Current Property is different for IList and Array. Arrays calls 'ldelem' instructions for faster
+ /// element retrieval.
+ /// </summary>
+ public abstract KeyValuePair<long, TSource> Current { get; }
+
+ /// <summary>
+ /// We don't dispose the source for IList and array
+ /// </summary>
+ public void Dispose()
+ { }
+
+ public void Reset()
+ {
+ throw new NotSupportedException();
+ }
+
+ /// <summary>
+ /// Moves to the next item
+ /// Before the first MoveNext is called: m_offset == m_startIndex-1;
+ /// </summary>
+ /// <returns>true if successful, false if there is no item left</returns>
+ public bool MoveNext()
+ {
+ if (m_offset < m_endIndex)
+ {
+ m_offset++;
+ return true;
+ }
+ else
+ {
+ //After we have enumerated over all elements, we set m_offset to m_endIndex +1.
+ //The reason we do this is, for an empty enumerator, we need to tell the Current
+ //property whether MoveNext has been called or not.
+ //For an empty enumerator, it starts with (m_offset == m_startIndex-1 == m_endIndex),
+ //and we don't set a new value to m_offset, then the above condition will always be
+ //true, and the Current property will mistakenly assume MoveNext is never called.
+ m_offset = m_endIndex + 1;
+ return false;
+ }
+ }
+
+ Object IEnumerator.Current
+ {
+ get
+ {
+ return ((StaticIndexRangePartition<TSource>)this).Current;
+ }
+ }
+ }
+ #endregion
+
+ #region Static partitioning for IList
+ /// <summary>
+ /// Inherits from StaticIndexRangePartitioner
+ /// Provides customized implementation of SourceCount and CreatePartition
+ /// </summary>
+ /// <typeparam name="TSource"></typeparam>
+ private class StaticIndexRangePartitionerForIList<TSource> : StaticIndexRangePartitioner<TSource, IList<TSource>>
+ {
+ IList<TSource> m_list;
+ internal StaticIndexRangePartitionerForIList(IList<TSource> list)
+ : base()
+ {
+ Contract.Assert(list != null);
+ m_list = list;
+ }
+ override protected int SourceCount
+ {
+ get { return m_list.Count; }
+ }
+ override protected IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex)
+ {
+ return new StaticIndexRangePartitionForIList<TSource>(m_list, startIndex, endIndex);
+ }
+ }
+
+ /// <summary>
+ /// Inherits from StaticIndexRangePartition
+ /// Provides customized implementation of Current property
+ /// </summary>
+ /// <typeparam name="TSource"></typeparam>
+ private class StaticIndexRangePartitionForIList<TSource> : StaticIndexRangePartition<TSource>
+ {
+ //the source collection shared by all partitions
+ private volatile IList<TSource> m_list;
+
+ internal StaticIndexRangePartitionForIList(IList<TSource> list, int startIndex, int endIndex)
+ : base(startIndex, endIndex)
+ {
+ Contract.Assert(startIndex >= 0 && endIndex <= list.Count - 1);
+ m_list = list;
+ }
+
+ override public KeyValuePair<long, TSource> Current
+ {
+ get
+ {
+ //verify that MoveNext is at least called once before Current is called
+ if (m_offset < m_startIndex)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
+ }
+
+ Contract.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex);
+ return (new KeyValuePair<long, TSource>(m_offset, m_list[m_offset]));
+ }
+ }
+ }
+ #endregion
+
+ #region static partitioning for Arrays
+ /// <summary>
+ /// Inherits from StaticIndexRangePartitioner
+ /// Provides customized implementation of SourceCount and CreatePartition for Array
+ /// </summary>
+ private class StaticIndexRangePartitionerForArray<TSource> : StaticIndexRangePartitioner<TSource, TSource[]>
+ {
+ TSource[] m_array;
+ internal StaticIndexRangePartitionerForArray(TSource[] array)
+ : base()
+ {
+ Contract.Assert(array != null);
+ m_array = array;
+ }
+ override protected int SourceCount
+ {
+ get { return m_array.Length; }
+ }
+ override protected IEnumerator<KeyValuePair<long, TSource>> CreatePartition(int startIndex, int endIndex)
+ {
+ return new StaticIndexRangePartitionForArray<TSource>(m_array, startIndex, endIndex);
+ }
+ }
+
+ /// <summary>
+ /// Inherits from StaticIndexRangePartitioner
+ /// Provides customized implementation of SourceCount and CreatePartition
+ /// </summary>
+ private class StaticIndexRangePartitionForArray<TSource> : StaticIndexRangePartition<TSource>
+ {
+ //the source collection shared by all partitions
+ private volatile TSource[] m_array;
+
+ internal StaticIndexRangePartitionForArray(TSource[] array, int startIndex, int endIndex)
+ : base(startIndex, endIndex)
+ {
+ Contract.Assert(startIndex >= 0 && endIndex <= array.Length - 1);
+ m_array = array;
+ }
+
+ override public KeyValuePair<long, TSource> Current
+ {
+ get
+ {
+ //verify that MoveNext is at least called once before Current is called
+ if (m_offset < m_startIndex)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("PartitionerStatic_CurrentCalledBeforeMoveNext"));
+ }
+
+ Contract.Assert(m_offset >= m_startIndex && m_offset <= m_endIndex);
+ return (new KeyValuePair<long, TSource>(m_offset, m_array[m_offset]));
+ }
+ }
+ }
+ #endregion
+
+
+ #region Utility functions
+ /// <summary>
+ /// A very simple primitive that allows us to share a value across multiple threads.
+ /// </summary>
+ /// <typeparam name="TSource"></typeparam>
+ private class SharedInt
+ {
+ internal volatile int Value;
+
+ internal SharedInt(int value)
+ {
+ this.Value = value;
+ }
+
+ }
+
+ /// <summary>
+ /// A very simple primitive that allows us to share a value across multiple threads.
+ /// </summary>
+ private class SharedBool
+ {
+ internal volatile bool Value;
+
+ internal SharedBool(bool value)
+ {
+ this.Value = value;
+ }
+
+ }
+
+ /// <summary>
+ /// A very simple primitive that allows us to share a value across multiple threads.
+ /// </summary>
+ private class SharedLong
+ {
+ internal long Value;
+ internal SharedLong(long value)
+ {
+ this.Value = value;
+ }
+
+ }
+
+ //--------------------
+ // The following part calculates the default chunk size. It is copied from System.Linq.Parallel.Scheduling,
+ // because mscorlib.dll cannot access System.Linq.Parallel.Scheduling
+ //--------------------
+
+ // The number of bytes we want "chunks" to be, when partitioning, etc. We choose 4 cache
+ // lines worth, assuming 128b cache line. Most (popular) architectures use 64b cache lines,
+ // but choosing 128b works for 64b too whereas a multiple of 64b isn't necessarily sufficient
+ // for 128b cache systems. So 128b it is.
+ private const int DEFAULT_BYTES_PER_CHUNK = 128 * 4;
+
+ private static int GetDefaultChunkSize<TSource>()
+ {
+ int chunkSize;
+
+ if (typeof(TSource).IsValueType)
+ {
+#if !FEATURE_CORECLR // Marshal.SizeOf is not supported in CoreCLR
+
+ if (typeof(TSource).StructLayoutAttribute.Value == LayoutKind.Explicit)
+ {
+ chunkSize = Math.Max(1, DEFAULT_BYTES_PER_CHUNK / Marshal.SizeOf(typeof(TSource)));
+ }
+ else
+ {
+ // We choose '128' because this ensures, no matter the actual size of the value type,
+ // the total bytes used will be a multiple of 128. This ensures it's cache aligned.
+ chunkSize = 128;
+ }
+#else
+ chunkSize = 128;
+#endif
+ }
+ else
+ {
+ Contract.Assert((DEFAULT_BYTES_PER_CHUNK % IntPtr.Size) == 0, "bytes per chunk should be a multiple of pointer size");
+ chunkSize = (DEFAULT_BYTES_PER_CHUNK / IntPtr.Size);
+ }
+ return chunkSize;
+ }
+ #endregion
+
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/DictionaryEntry.cs b/src/mscorlib/src/System/Collections/DictionaryEntry.cs
new file mode 100644
index 0000000000..fc1d57fe55
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/DictionaryEntry.cs
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: DictionaryEntry
+**
+**
+**
+**
+** Purpose: Return Value for IDictionaryEnumerator::GetEntry
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ // A DictionaryEntry holds a key and a value from a dictionary.
+ // It is returned by IDictionaryEnumerator::GetEntry().
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public struct DictionaryEntry
+ {
+ private Object _key;
+ private Object _value;
+
+ // Constructs a new DictionaryEnumerator by setting the Key
+ // and Value fields appropriately.
+ public DictionaryEntry(Object key, Object value) {
+ _key = key;
+ _value = value;
+ }
+
+ public Object Key {
+ get {
+ return _key;
+ }
+
+ set {
+ _key = value;
+ }
+ }
+
+ public Object Value {
+ get {
+ return _value;
+ }
+
+ set {
+ _value = value;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs b/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs
new file mode 100644
index 0000000000..6e28493ef8
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/EmptyReadOnlyDictionaryInternal.cs
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: List for exceptions.
+**
+**
+===========================================================*/
+
+using System.Diagnostics.Contracts;
+
+namespace System.Collections {
+ /// This is a simple implementation of IDictionary that is empty and readonly.
+ [Serializable]
+ internal sealed class EmptyReadOnlyDictionaryInternal: IDictionary {
+
+ // Note that this class must be agile with respect to AppDomains. See its usage in
+ // System.Exception to understand why this is the case.
+
+ public EmptyReadOnlyDictionaryInternal() {
+ }
+
+ // IEnumerable members
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new NodeEnumerator();
+ }
+
+ // ICollection members
+
+ public void CopyTo(Array array, int index) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if ( array.Length - index < this.Count )
+ throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
+ Contract.EndContractBlock();
+
+ // the actual copy is a NOP
+ }
+
+ public int Count {
+ get {
+ return 0;
+ }
+ }
+
+ public Object SyncRoot {
+ get {
+ return this;
+ }
+ }
+
+ public bool IsSynchronized {
+ get {
+ return false;
+ }
+ }
+
+ // IDictionary members
+
+ public Object this[Object key] {
+ get {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ return null;
+ }
+ set {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+
+ if (!key.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");
+
+ if( (value != null) && (!value.GetType().IsSerializable ) )
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
+ Contract.EndContractBlock();
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ }
+
+ public ICollection Keys {
+ get {
+ return EmptyArray<Object>.Value;
+ }
+ }
+
+ public ICollection Values {
+ get {
+ return EmptyArray<Object>.Value;
+ }
+ }
+
+ public bool Contains(Object key) {
+ return false;
+ }
+
+ public void Add(Object key, Object value) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+
+ if (!key.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key" );
+
+ if( (value != null) && (!value.GetType().IsSerializable) )
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
+ Contract.EndContractBlock();
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+
+ public void Clear() {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+
+ public bool IsReadOnly {
+ get {
+ return true;
+ }
+ }
+
+ public bool IsFixedSize {
+ get {
+ return true;
+ }
+ }
+
+ public IDictionaryEnumerator GetEnumerator() {
+ return new NodeEnumerator();
+ }
+
+ public void Remove(Object key) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+
+ private sealed class NodeEnumerator : IDictionaryEnumerator {
+
+ public NodeEnumerator() {
+ }
+
+ // IEnumerator members
+
+ public bool MoveNext() {
+ return false;
+ }
+
+ public Object Current {
+ get {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ }
+
+ public void Reset() {
+ }
+
+ // IDictionaryEnumerator members
+
+ public Object Key {
+ get {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ }
+
+ public Object Value {
+ get {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ }
+
+ public DictionaryEntry Entry {
+ get {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs b/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs
new file mode 100644
index 0000000000..b2fed9d78f
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/ArraySortHelper.cs
@@ -0,0 +1,1558 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: class to sort arrays
+**
+**
+===========================================================*/
+namespace System.Collections.Generic
+{
+ using System;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.Versioning;
+
+ #region ArraySortHelper for single arrays
+
+ internal interface IArraySortHelper<TKey>
+ {
+ void Sort(TKey[] keys, int index, int length, IComparer<TKey> comparer);
+ int BinarySearch(TKey[] keys, int index, int length, TKey value, IComparer<TKey> comparer);
+ }
+
+ internal static class IntrospectiveSortUtilities
+ {
+ // This is the threshold where Introspective sort switches to Insertion sort.
+ // Imperically, 16 seems to speed up most cases without slowing down others, at least for integers.
+ // Large value types may benefit from a smaller number.
+ internal const int IntrosortSizeThreshold = 16;
+
+ internal const int QuickSortDepthThreshold = 32;
+
+ internal static int FloorLog2(int n)
+ {
+ int result = 0;
+ while (n >= 1)
+ {
+ result++;
+ n = n / 2;
+ }
+ return result;
+ }
+
+ internal static void ThrowOrIgnoreBadComparer(Object comparer) {
+ // This is hit when an invarant of QuickSort is violated due to a bad IComparer implementation (for
+ // example, imagine an IComparer that returns 0 when items are equal but -1 all other times).
+ //
+ // We could have thrown this exception on v4, but due to changes in v4.5 around how we partition arrays
+ // there are different sets of input where we would throw this exception. In order to reduce overall risk from
+ // an app compat persective, we're changing to never throw on v4. Instead, we'll return with a partially
+ // sorted array.
+ if(BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_BogusIComparer", comparer));
+ }
+ }
+
+ }
+
+ [TypeDependencyAttribute("System.Collections.Generic.GenericArraySortHelper`1")]
+ internal class ArraySortHelper<T>
+ : IArraySortHelper<T>
+ {
+ static volatile IArraySortHelper<T> defaultArraySortHelper;
+
+ public static IArraySortHelper<T> Default
+ {
+ get
+ {
+ IArraySortHelper<T> sorter = defaultArraySortHelper;
+ if (sorter == null)
+ sorter = CreateArraySortHelper();
+
+ return sorter;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static IArraySortHelper<T> CreateArraySortHelper()
+ {
+ if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
+ {
+ defaultArraySortHelper = (IArraySortHelper<T>)RuntimeTypeHandle.Allocate(typeof(GenericArraySortHelper<string>).TypeHandle.Instantiate(new Type[] { typeof(T) }));
+ }
+ else
+ {
+ defaultArraySortHelper = new ArraySortHelper<T>();
+ }
+ return defaultArraySortHelper;
+ }
+
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Contract.Assert(keys != null, "Check the arguments in the caller!");
+ Contract.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(keys, index, length, comparer);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(keys, index, length, comparer);
+ }
+ else
+ {
+ DepthLimitedQuickSort(keys, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ try
+ {
+ if (comparer == null)
+ {
+ comparer = Comparer<T>.Default;
+ }
+
+ return InternalBinarySearch(array, index, length, value, comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ #endregion
+
+ internal static int InternalBinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Contract.Requires(array != null, "Check the arguments in the caller!");
+ Contract.Requires(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order = comparer.Compare(array[i], value);
+
+ if (order == 0) return i;
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreater(T[] keys, IComparer<T> comparer, int a, int b)
+ {
+ if (a != b)
+ {
+ if (comparer.Compare(keys[a], keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if(i != j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ internal static void DepthLimitedQuickSort(T[] keys, int left, int right, IComparer<T> comparer, int depthLimit)
+ {
+ do
+ {
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, left, right, comparer);
+ return;
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = i + ((j - i) >> 1);
+ SwapIfGreater(keys, comparer, i, middle); // swap the low with the mid point
+ SwapIfGreater(keys, comparer, i, j); // swap the low with the high
+ SwapIfGreater(keys, comparer, middle, j); // swap the middle with the high
+
+ T x = keys[middle];
+ do
+ {
+ while (comparer.Compare(keys[i], x) < 0) i++;
+ while (comparer.Compare(x, keys[j]) < 0) j--;
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ T key = keys[i];
+ keys[i] = keys[j];
+ keys[j] = key;
+ }
+ i++;
+ j--;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(keys, left, j, comparer, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(keys, i, right, comparer, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(left >= 0);
+ Contract.Requires(length >= 0);
+ Contract.Requires(length <= keys.Length);
+ Contract.Requires(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length), comparer);
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreater(keys, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreater(keys, comparer, lo, hi-1);
+ SwapIfGreater(keys, comparer, lo, hi);
+ SwapIfGreater(keys, comparer, hi-1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+ Contract.Ensures(Contract.Result<int>() >= lo && Contract.Result<int>() <= hi);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreater(keys, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreater(keys, comparer, lo, hi); // swap the low with the high
+ SwapIfGreater(keys, comparer, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys[++left], pivot) < 0) ;
+ while (comparer.Compare(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi, IComparer<T> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi >= lo);
+ Contract.Requires(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && comparer.Compare(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ [Serializable()]
+ internal class GenericArraySortHelper<T>
+ : IArraySortHelper<T>
+ where T : IComparable<T>
+ {
+ // Do not add a constructor to this class because ArraySortHelper<T>.CreateSortHelper will not execute it
+
+ #region IArraySortHelper<T> Members
+
+ public void Sort(T[] keys, int index, int length, IComparer<T> comparer)
+ {
+ Contract.Assert(keys != null, "Check the arguments in the caller!");
+ Contract.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default) {
+
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(keys, index, length);
+#else
+ // call the faster version of our sort algorithm if the user doesn't provide a comparer
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(keys, index, length);
+ }
+ else
+ {
+ DepthLimitedQuickSort(keys, index, length + index - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+ else
+ {
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ ArraySortHelper<T>.IntrospectiveSort(keys, index, length, comparer);
+ }
+ else
+ {
+ ArraySortHelper<T>.DepthLimitedQuickSort(keys, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ public int BinarySearch(T[] array, int index, int length, T value, IComparer<T> comparer)
+ {
+ Contract.Assert(array != null, "Check the arguments in the caller!");
+ Contract.Assert(index >= 0 && length >= 0 && (array.Length - index >= length), "Check the arguments in the caller!");
+
+ try
+ {
+ if (comparer == null || comparer == Comparer<T>.Default)
+ {
+ return BinarySearch(array, index, length, value);
+ }
+ else
+ {
+ return ArraySortHelper<T>.InternalBinarySearch(array, index, length, value, comparer);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ #endregion
+
+ // This function is called when the user doesn't specify any comparer.
+ // Since T is constrained here, we can call IComparable<T>.CompareTo here.
+ // We can avoid boxing for value type and casting for reference types.
+ private static int BinarySearch(T[] array, int index, int length, T value)
+ {
+ int lo = index;
+ int hi = index + length - 1;
+ while (lo <= hi)
+ {
+ int i = lo + ((hi - lo) >> 1);
+ int order;
+ if (array[i] == null)
+ {
+ order = (value == null) ? 0 : -1;
+ }
+ else
+ {
+ order = array[i].CompareTo(value);
+ }
+
+ if (order == 0)
+ {
+ return i;
+ }
+
+ if (order < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i - 1;
+ }
+ }
+
+ return ~lo;
+ }
+
+ private static void SwapIfGreaterWithItems(T[] keys, int a, int b)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(0 <= a && a < keys.Length);
+ Contract.Requires(0 <= b && b < keys.Length);
+
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ T key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ }
+ }
+ }
+
+ private static void Swap(T[] a, int i, int j)
+ {
+ if(i!=j)
+ {
+ T t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+ }
+
+ private static void DepthLimitedQuickSort(T[] keys, int left, int right, int depthLimit)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(0 <= left && left < keys.Length);
+ Contract.Requires(0 <= right && right < keys.Length);
+
+ // The code in this function looks very similar to QuickSort in ArraySortHelper<T> class.
+ // The difference is that T is constrainted to IComparable<T> here.
+ // So the IL code will be different. This function is faster than the one in ArraySortHelper<T>.
+
+ do
+ {
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, left, right);
+ return;
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = i + ((j - i) >> 1);
+ SwapIfGreaterWithItems(keys, i, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, i, j); // swap the low with the high
+ SwapIfGreaterWithItems(keys, middle, j); // swap the middle with the high
+
+ T x = keys[middle];
+ do
+ {
+ if (x == null)
+ {
+ // if x null, the loop to find two elements to be switched can be reduced.
+ while (keys[j] != null) j--;
+ }
+ else
+ {
+ while (x.CompareTo(keys[i]) > 0) i++;
+ while (x.CompareTo(keys[j]) < 0) j--;
+ }
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ T key = keys[i];
+ keys[i] = keys[j];
+ keys[j] = key;
+ }
+ i++;
+ j--;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(keys, left, j, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(keys, i, right, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ internal static void IntrospectiveSort(T[] keys, int left, int length)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(left >= 0);
+ Contract.Requires(length >= 0);
+ Contract.Requires(length <= keys.Length);
+ Contract.Requires(length + left <= keys.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
+ }
+
+ private static void IntroSort(T[] keys, int lo, int hi, int depthLimit)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, lo, hi-1);
+ SwapIfGreaterWithItems(keys, lo, hi);
+ SwapIfGreaterWithItems(keys, hi-1, hi);
+ return;
+ }
+
+ InsertionSort(keys, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(T[] keys, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+ Contract.Ensures(Contract.Result<int>() >= lo && Contract.Result<int>() <= hi);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, middle, hi); // swap the middle with the high
+
+ T pivot = keys[middle];
+ Swap(keys, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if (pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null) ;
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(T[] keys, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, lo, lo + i - 1);
+ DownHeap(keys, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(T[] keys, int i, int n, int lo)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(lo < keys.Length);
+
+ T d = keys[lo + i - 1];
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ }
+
+ private static void InsertionSort(T[] keys, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi >= lo);
+ Contract.Requires(hi <= keys.Length);
+
+ int i, j;
+ T t;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ }
+ }
+ }
+
+ #endregion
+
+ #region ArraySortHelper for paired key and value arrays
+
+ internal interface IArraySortHelper<TKey, TValue>
+ {
+ void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer);
+ }
+
+ [TypeDependencyAttribute("System.Collections.Generic.GenericArraySortHelper`2")]
+ internal class ArraySortHelper<TKey, TValue>
+ : IArraySortHelper<TKey, TValue>
+ {
+ static volatile IArraySortHelper<TKey, TValue> defaultArraySortHelper;
+
+ public static IArraySortHelper<TKey, TValue> Default
+ {
+ get
+ {
+ IArraySortHelper<TKey, TValue> sorter = defaultArraySortHelper;
+ if (sorter == null)
+ sorter = CreateArraySortHelper();
+
+ return sorter;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static IArraySortHelper<TKey, TValue> CreateArraySortHelper()
+ {
+ if (typeof(IComparable<TKey>).IsAssignableFrom(typeof(TKey)))
+ {
+ defaultArraySortHelper = (IArraySortHelper<TKey, TValue>)RuntimeTypeHandle.Allocate(typeof(GenericArraySortHelper<string, string>).TypeHandle.Instantiate(new Type[] { typeof(TKey), typeof(TValue) }));
+ }
+ else
+ {
+ defaultArraySortHelper = new ArraySortHelper<TKey, TValue>();
+ }
+ return defaultArraySortHelper;
+ }
+
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Contract.Assert(keys != null, "Check the arguments in the caller!"); // Precondition on interface method
+ Contract.Assert(index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+ comparer = Comparer<TKey>.Default;
+ }
+
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(keys, values, index, length, comparer);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ else
+ {
+ DepthLimitedQuickSort(keys, values, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, IComparer<TKey> comparer, int a, int b)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values == null || values.Length >= keys.Length);
+ Contract.Requires(comparer != null);
+ Contract.Requires(0 <= a && a < keys.Length);
+ Contract.Requires(0 <= b && b < keys.Length);
+
+ if (a != b)
+ {
+ if (comparer.Compare(keys[a], keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ if (values != null)
+ {
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if(i!=j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+ if(values != null)
+ {
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+ }
+
+ internal static void DepthLimitedQuickSort(TKey[] keys, TValue[] values, int left, int right, IComparer<TKey> comparer, int depthLimit)
+ {
+ do
+ {
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, left, right, comparer);
+ return;
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = i + ((j - i) >> 1);
+ SwapIfGreaterWithItems(keys, values, comparer, i, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, comparer, i, j); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, comparer, middle, j); // swap the middle with the high
+
+ TKey x = keys[middle];
+ do
+ {
+ while (comparer.Compare(keys[i], x) < 0) i++;
+ while (comparer.Compare(x, keys[j]) < 0) j--;
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ TKey key = keys[i];
+ keys[i] = keys[j];
+ keys[j] = key;
+ if (values != null)
+ {
+ TValue value = values[i];
+ values[i] = values[j];
+ values[j] = value;
+ }
+ }
+ i++;
+ j--;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(keys, values, left, j, comparer, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(keys, values, i, right, comparer, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(left >= 0);
+ Contract.Requires(length >= 0);
+ Contract.Requires(length <= keys.Length);
+ Contract.Requires(length + left <= keys.Length);
+ Contract.Requires(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length), comparer);
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi-1);
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi);
+ SwapIfGreaterWithItems(keys, values, comparer, hi-1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi, comparer);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi, comparer);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi, comparer);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit, comparer);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+ Contract.Ensures(Contract.Result<int>() >= lo && Contract.Result<int>() <= hi);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, comparer, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, comparer, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, comparer, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ while (comparer.Compare(keys[++left], pivot) < 0) ;
+ while (comparer.Compare(pivot, keys[--right]) < 0) ;
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo, comparer);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo, comparer);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = (values != null) ? values[lo + i - 1] : default(TValue);
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && comparer.Compare(keys[lo + child - 1], keys[lo + child]) < 0)
+ {
+ child++;
+ }
+ if (!(comparer.Compare(d, keys[lo + child - 1]) < 0))
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ if(values != null)
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ if(values != null)
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi, IComparer<TKey> comparer)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(comparer != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi >= lo);
+ Contract.Requires(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = (values != null) ? values[i + 1] : default(TValue);
+ while (j >= lo && comparer.Compare(t, keys[j]) < 0)
+ {
+ keys[j + 1] = keys[j];
+ if(values != null)
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ if(values != null)
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ internal class GenericArraySortHelper<TKey, TValue>
+ : IArraySortHelper<TKey, TValue>
+ where TKey : IComparable<TKey>
+ {
+ public void Sort(TKey[] keys, TValue[] values, int index, int length, IComparer<TKey> comparer)
+ {
+ Contract.Assert(keys != null, "Check the arguments in the caller!");
+ Contract.Assert( index >= 0 && length >= 0 && (keys.Length - index >= length), "Check the arguments in the caller!");
+
+ // Add a try block here to detect IComparers (or their
+ // underlying IComparables, etc) that are bogus.
+ try
+ {
+ if (comparer == null || comparer == Comparer<TKey>.Default)
+ {
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ IntrospectiveSort(keys, values, index, length);
+#else
+ // call the faster version of our sort algorithm if the user doesn't provide a comparer
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ IntrospectiveSort(keys, values, index, length);
+ }
+ else
+ {
+ DepthLimitedQuickSort(keys, values, index, length + index - 1, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+ else
+ {
+#if FEATURE_CORECLR
+ // Since QuickSort and IntrospectiveSort produce different sorting sequence for equal keys the upgrade
+ // to IntrospectiveSort was quirked. However since the phone builds always shipped with the new sort aka
+ // IntrospectiveSort and we would want to continue using this sort moving forward CoreCLR always uses the new sort.
+
+ ArraySortHelper<TKey, TValue>.IntrospectiveSort(keys, values, index, length, comparer);
+#else
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ ArraySortHelper<TKey, TValue>.IntrospectiveSort(keys, values, index, length, comparer);
+ }
+ else
+ {
+ ArraySortHelper<TKey, TValue>.DepthLimitedQuickSort(keys, values, index, length + index - 1, comparer, IntrospectiveSortUtilities.QuickSortDepthThreshold);
+ }
+#endif
+ }
+
+ }
+ catch (IndexOutOfRangeException)
+ {
+ IntrospectiveSortUtilities.ThrowOrIgnoreBadComparer(comparer);
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_IComparerFailed"), e);
+ }
+ }
+
+ private static void SwapIfGreaterWithItems(TKey[] keys, TValue[] values, int a, int b)
+ {
+ if (a != b)
+ {
+ if (keys[a] != null && keys[a].CompareTo(keys[b]) > 0)
+ {
+ TKey key = keys[a];
+ keys[a] = keys[b];
+ keys[b] = key;
+ if (values != null)
+ {
+ TValue value = values[a];
+ values[a] = values[b];
+ values[b] = value;
+ }
+ }
+ }
+ }
+
+ private static void Swap(TKey[] keys, TValue[] values, int i, int j)
+ {
+ if(i != j)
+ {
+ TKey k = keys[i];
+ keys[i] = keys[j];
+ keys[j] = k;
+ if(values != null)
+ {
+ TValue v = values[i];
+ values[i] = values[j];
+ values[j] = v;
+ }
+ }
+ }
+
+ private static void DepthLimitedQuickSort(TKey[] keys, TValue[] values, int left, int right, int depthLimit)
+ {
+ // The code in this function looks very similar to QuickSort in ArraySortHelper<T> class.
+ // The difference is that T is constrainted to IComparable<T> here.
+ // So the IL code will be different. This function is faster than the one in ArraySortHelper<T>.
+
+ do
+ {
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, left, right);
+ return;
+ }
+
+ int i = left;
+ int j = right;
+
+ // pre-sort the low, middle (pivot), and high values in place.
+ // this improves performance in the face of already sorted data, or
+ // data that is made up of multiple sorted runs appended together.
+ int middle = i + ((j - i) >> 1);
+ SwapIfGreaterWithItems(keys, values, i, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, i, j); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, middle, j); // swap the middle with the high
+
+ TKey x = keys[middle];
+ do
+ {
+ if (x == null)
+ {
+ // if x null, the loop to find two elements to be switched can be reduced.
+ while (keys[j] != null) j--;
+ }
+ else
+ {
+ while (x.CompareTo(keys[i]) > 0) i++;
+ while (x.CompareTo(keys[j]) < 0) j--;
+ }
+ Contract.Assert(i >= left && j <= right, "(i>=left && j<=right) Sort failed - Is your IComparer bogus?");
+ if (i > j) break;
+ if (i < j)
+ {
+ TKey key = keys[i];
+ keys[i] = keys[j];
+ keys[j] = key;
+ if (values != null)
+ {
+ TValue value = values[i];
+ values[i] = values[j];
+ values[j] = value;
+ }
+ }
+ i++;
+ j--;
+ } while (i <= j);
+
+ // The next iteration of the while loop is to "recursively" sort the larger half of the array and the
+ // following calls recursively sort the smaller half. So we subtract one from depthLimit here so
+ // both sorts see the new value.
+ depthLimit--;
+
+ if (j - left <= right - i)
+ {
+ if (left < j) DepthLimitedQuickSort(keys, values, left, j, depthLimit);
+ left = i;
+ }
+ else
+ {
+ if (i < right) DepthLimitedQuickSort(keys, values, i, right, depthLimit);
+ right = j;
+ }
+ } while (left < right);
+ }
+
+ internal static void IntrospectiveSort(TKey[] keys, TValue[] values, int left, int length)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(left >= 0);
+ Contract.Requires(length >= 0);
+ Contract.Requires(length <= keys.Length);
+ Contract.Requires(length + left <= keys.Length);
+ Contract.Requires(length + left <= values.Length);
+
+ if (length < 2)
+ return;
+
+ IntroSort(keys, values, left, length + left - 1, 2 * IntrospectiveSortUtilities.FloorLog2(keys.Length));
+ }
+
+ private static void IntroSort(TKey[] keys, TValue[] values, int lo, int hi, int depthLimit)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi < keys.Length);
+
+ while (hi > lo)
+ {
+ int partitionSize = hi - lo + 1;
+ if (partitionSize <= IntrospectiveSortUtilities.IntrosortSizeThreshold)
+ {
+ if (partitionSize == 1)
+ {
+ return;
+ }
+ if (partitionSize == 2)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ return;
+ }
+ if (partitionSize == 3)
+ {
+ SwapIfGreaterWithItems(keys, values, lo, hi-1);
+ SwapIfGreaterWithItems(keys, values, lo, hi);
+ SwapIfGreaterWithItems(keys, values, hi-1, hi);
+ return;
+ }
+
+ InsertionSort(keys, values, lo, hi);
+ return;
+ }
+
+ if (depthLimit == 0)
+ {
+ Heapsort(keys, values, lo, hi);
+ return;
+ }
+ depthLimit--;
+
+ int p = PickPivotAndPartition(keys, values, lo, hi);
+ // Note we've already partitioned around the pivot and do not have to move the pivot again.
+ IntroSort(keys, values, p + 1, hi, depthLimit);
+ hi = p - 1;
+ }
+ }
+
+ private static int PickPivotAndPartition(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+ Contract.Ensures(Contract.Result<int>() >= lo && Contract.Result<int>() <= hi);
+
+ // Compute median-of-three. But also partition them, since we've done the comparison.
+ int middle = lo + ((hi - lo) / 2);
+
+ // Sort lo, mid and hi appropriately, then pick mid as the pivot.
+ SwapIfGreaterWithItems(keys, values, lo, middle); // swap the low with the mid point
+ SwapIfGreaterWithItems(keys, values, lo, hi); // swap the low with the high
+ SwapIfGreaterWithItems(keys, values, middle, hi); // swap the middle with the high
+
+ TKey pivot = keys[middle];
+ Swap(keys, values, middle, hi - 1);
+ int left = lo, right = hi - 1; // We already partitioned lo and hi and put the pivot in hi - 1. And we pre-increment & decrement below.
+
+ while (left < right)
+ {
+ if(pivot == null)
+ {
+ while (left < (hi - 1) && keys[++left] == null) ;
+ while (right > lo && keys[--right] != null);
+ }
+ else
+ {
+ while (pivot.CompareTo(keys[++left]) > 0) ;
+ while (pivot.CompareTo(keys[--right]) < 0) ;
+ }
+
+ if (left >= right)
+ break;
+
+ Swap(keys, values, left, right);
+ }
+
+ // Put pivot in the right location.
+ Swap(keys, values, left, (hi - 1));
+ return left;
+ }
+
+ private static void Heapsort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi > lo);
+ Contract.Requires(hi < keys.Length);
+
+ int n = hi - lo + 1;
+ for (int i = n / 2; i >= 1; i = i - 1)
+ {
+ DownHeap(keys, values, i, n, lo);
+ }
+ for (int i = n; i > 1; i = i - 1)
+ {
+ Swap(keys, values, lo, lo + i - 1);
+ DownHeap(keys, values, 1, i - 1, lo);
+ }
+ }
+
+ private static void DownHeap(TKey[] keys, TValue[] values, int i, int n, int lo)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(lo < keys.Length);
+
+ TKey d = keys[lo + i - 1];
+ TValue dValue = (values != null) ? values[lo + i - 1] : default(TValue);
+ int child;
+ while (i <= n / 2)
+ {
+ child = 2 * i;
+ if (child < n && (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(keys[lo + child]) < 0))
+ {
+ child++;
+ }
+ if (keys[lo + child - 1] == null || keys[lo + child - 1].CompareTo(d) < 0)
+ break;
+ keys[lo + i - 1] = keys[lo + child - 1];
+ if(values != null)
+ values[lo + i - 1] = values[lo + child - 1];
+ i = child;
+ }
+ keys[lo + i - 1] = d;
+ if(values != null)
+ values[lo + i - 1] = dValue;
+ }
+
+ private static void InsertionSort(TKey[] keys, TValue[] values, int lo, int hi)
+ {
+ Contract.Requires(keys != null);
+ Contract.Requires(values != null);
+ Contract.Requires(lo >= 0);
+ Contract.Requires(hi >= lo);
+ Contract.Requires(hi <= keys.Length);
+
+ int i, j;
+ TKey t;
+ TValue tValue;
+ for (i = lo; i < hi; i++)
+ {
+ j = i;
+ t = keys[i + 1];
+ tValue = (values != null)? values[i + 1] : default(TValue);
+ while (j >= lo && (t == null || t.CompareTo(keys[j]) < 0))
+ {
+ keys[j + 1] = keys[j];
+ if(values != null)
+ values[j + 1] = values[j];
+ j--;
+ }
+ keys[j + 1] = t;
+ if(values != null)
+ values[j + 1] = tValue;
+ }
+ }
+ }
+
+ #endregion
+}
+
+
diff --git a/src/mscorlib/src/System/Collections/Generic/Comparer.cs b/src/mscorlib/src/System/Collections/Generic/Comparer.cs
new file mode 100644
index 0000000000..9f1a8bff6f
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/Comparer.cs
@@ -0,0 +1,325 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+//using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Runtime.Serialization;
+
+namespace System.Collections.Generic
+{
+ [Serializable]
+ [TypeDependencyAttribute("System.Collections.Generic.ObjectComparer`1")]
+ public abstract class Comparer<T> : IComparer, IComparer<T>
+ {
+ static readonly Comparer<T> defaultComparer = CreateComparer();
+
+ public static Comparer<T> Default {
+ get {
+ Contract.Ensures(Contract.Result<Comparer<T>>() != null);
+ return defaultComparer;
+ }
+ }
+
+ public static Comparer<T> Create(Comparison<T> comparison)
+ {
+ Contract.Ensures(Contract.Result<Comparer<T>>() != null);
+
+ if (comparison == null)
+ throw new ArgumentNullException("comparison");
+
+ return new ComparisonComparer<T>(comparison);
+ }
+
+ //
+ // Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen
+ // saves the right instantiations
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Comparer<T> CreateComparer()
+ {
+ object result = null;
+ RuntimeType t = (RuntimeType)typeof(T);
+
+ // If T implements IComparable<T> return a GenericComparer<T>
+ if (typeof(IComparable<T>).IsAssignableFrom(t))
+ {
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer<int>), t);
+ }
+ else if (default(T) == null)
+ {
+ // If T is a Nullable<U> where U implements IComparable<U> return a NullableComparer<U>
+ if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
+ RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
+ if (typeof(IComparable<>).MakeGenericType(u).IsAssignableFrom(u)) {
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer<int>), u);
+ }
+ }
+ }
+ else if (t.IsEnum)
+ {
+ // Explicitly call Enum.GetUnderlyingType here. Although GetTypeCode
+ // ends up doing this anyway, we end up avoiding an unnecessary P/Invoke
+ // and virtual method call.
+ TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));
+
+ // Depending on the enum type, we need to special case the comparers so that we avoid boxing
+ // Specialize differently for signed/unsigned types so we avoid problems with large numbers
+ switch (underlyingTypeCode)
+ {
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(Int32EnumComparer<int>), t);
+ break;
+ case TypeCode.Byte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(UInt32EnumComparer<uint>), t);
+ break;
+ // 64-bit enums: use UnsafeEnumCastLong
+ case TypeCode.Int64:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(Int64EnumComparer<long>), t);
+ break;
+ case TypeCode.UInt64:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(UInt64EnumComparer<ulong>), t);
+ break;
+ }
+ }
+
+ return result != null ?
+ (Comparer<T>)result :
+ new ObjectComparer<T>(); // Fallback to ObjectComparer, which uses boxing
+ }
+
+ public abstract int Compare(T x, T y);
+
+ int IComparer.Compare(object x, object y) {
+ if (x == null) return y == null ? 0 : -1;
+ if (y == null) return 1;
+ if (x is T && y is T) return Compare((T)x, (T)y);
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
+ return 0;
+ }
+ }
+
+ // Note: although there is a lot of shared code in the following
+ // comparers, we do not incorporate it into a base class for perf
+ // reasons. Adding another base class (even one with no fields)
+ // means another generic instantiation, which can be costly esp.
+ // for value types.
+
+ [Serializable]
+ internal sealed class GenericComparer<T> : Comparer<T> where T : IComparable<T>
+ {
+ public override int Compare(T x, T y) {
+ if (x != null) {
+ if (y != null) return x.CompareTo(y);
+ return 1;
+ }
+ if (y != null) return -1;
+ return 0;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+ }
+
+ [Serializable]
+ internal sealed class NullableComparer<T> : Comparer<T?> where T : struct, IComparable<T>
+ {
+ public override int Compare(Nullable<T> x, Nullable<T> y) {
+ if (x.HasValue) {
+ if (y.HasValue) return x.value.CompareTo(y.value);
+ return 1;
+ }
+ if (y.HasValue) return -1;
+ return 0;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+ }
+
+ [Serializable]
+ internal sealed class ObjectComparer<T> : Comparer<T>
+ {
+ public override int Compare(T x, T y) {
+ return System.Collections.Comparer.Default.Compare(x, y);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+ }
+
+ [Serializable]
+ internal sealed class ComparisonComparer<T> : Comparer<T>
+ {
+ private readonly Comparison<T> _comparison;
+
+ public ComparisonComparer(Comparison<T> comparison) {
+ _comparison = comparison;
+ }
+
+ public override int Compare(T x, T y) {
+ return _comparison(x, y);
+ }
+ }
+
+ // Enum comparers (specialized to avoid boxing)
+ // NOTE: Each of these needs to implement ISerializable
+ // and have a SerializationInfo/StreamingContext ctor,
+ // since we want to serialize as ObjectComparer for
+ // back-compat reasons (see below).
+
+ [Serializable]
+ internal sealed class Int32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
+ {
+ public Int32EnumComparer()
+ {
+ Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!");
+ }
+
+ // Used by the serialization engine.
+ private Int32EnumComparer(SerializationInfo info, StreamingContext context) { }
+
+ public override int Compare(T x, T y)
+ {
+ int ix = JitHelpers.UnsafeEnumCast(x);
+ int iy = JitHelpers.UnsafeEnumCast(y);
+ return ix.CompareTo(iy);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Previously Comparer<T> was not specialized for enums,
+ // and instead fell back to ObjectComparer which uses boxing.
+ // Set the type as ObjectComparer here so code that serializes
+ // Comparer for enums will not break.
+ info.SetType(typeof(ObjectComparer<T>));
+ }
+ }
+
+ [Serializable]
+ internal sealed class UInt32EnumComparer<T> : Comparer<T>, ISerializable where T : struct
+ {
+ public UInt32EnumComparer()
+ {
+ Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!");
+ }
+
+ // Used by the serialization engine.
+ private UInt32EnumComparer(SerializationInfo info, StreamingContext context) { }
+
+ public override int Compare(T x, T y)
+ {
+ uint ix = (uint)JitHelpers.UnsafeEnumCast(x);
+ uint iy = (uint)JitHelpers.UnsafeEnumCast(y);
+ return ix.CompareTo(iy);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(ObjectComparer<T>));
+ }
+ }
+
+ [Serializable]
+ internal sealed class Int64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
+ {
+ public Int64EnumComparer()
+ {
+ Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!");
+ }
+
+ // Used by the serialization engine.
+ private Int64EnumComparer(SerializationInfo info, StreamingContext context) { }
+
+ public override int Compare(T x, T y)
+ {
+ long lx = JitHelpers.UnsafeEnumCastLong(x);
+ long ly = JitHelpers.UnsafeEnumCastLong(y);
+ return lx.CompareTo(ly);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(ObjectComparer<T>));
+ }
+ }
+
+ [Serializable]
+ internal sealed class UInt64EnumComparer<T> : Comparer<T>, ISerializable where T : struct
+ {
+ public UInt64EnumComparer()
+ {
+ Contract.Assert(typeof(T).IsEnum, "This type is only intended to be used to compare enums!");
+ }
+
+ // Used by the serialization engine.
+ private UInt64EnumComparer(SerializationInfo info, StreamingContext context) { }
+
+ public override int Compare(T x, T y)
+ {
+ ulong lx = (ulong)JitHelpers.UnsafeEnumCastLong(x);
+ ulong ly = (ulong)JitHelpers.UnsafeEnumCastLong(y);
+ return lx.CompareTo(ly);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) =>
+ obj != null && GetType() == obj.GetType();
+
+ public override int GetHashCode() =>
+ GetType().GetHashCode();
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.SetType(typeof(ObjectComparer<T>));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/DebugView.cs b/src/mscorlib/src/System/Collections/Generic/DebugView.cs
new file mode 100644
index 0000000000..57b91eff51
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/DebugView.cs
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: DebugView class for generic collections
+**
+**
+**
+**
+=============================================================================*/
+
+namespace System.Collections.Generic {
+ using System;
+ using System.Collections.ObjectModel;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ //
+ // VS IDE can't differentiate between types with the same name from different
+ // assembly. So we need to use different names for collection debug view for
+ // collections in mscorlib.dll and system.dll.
+ //
+ internal sealed class Mscorlib_CollectionDebugView<T> {
+ private ICollection<T> collection;
+
+ public Mscorlib_CollectionDebugView(ICollection<T> collection) {
+ if (collection == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+
+ this.collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items {
+ get {
+ T[] items = new T[collection.Count];
+ collection.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ internal sealed class Mscorlib_DictionaryKeyCollectionDebugView<TKey, TValue> {
+ private ICollection<TKey> collection;
+
+ public Mscorlib_DictionaryKeyCollectionDebugView(ICollection<TKey> collection) {
+ if (collection == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+
+ this.collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public TKey[] Items {
+ get {
+ TKey[] items = new TKey[collection.Count];
+ collection.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ internal sealed class Mscorlib_DictionaryValueCollectionDebugView<TKey, TValue> {
+ private ICollection<TValue> collection;
+
+ public Mscorlib_DictionaryValueCollectionDebugView(ICollection<TValue> collection) {
+ if (collection == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+
+ this.collection = collection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public TValue[] Items {
+ get {
+ TValue[] items = new TValue[collection.Count];
+ collection.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ internal sealed class Mscorlib_DictionaryDebugView<K, V> {
+ private IDictionary<K, V> dict;
+
+ public Mscorlib_DictionaryDebugView(IDictionary<K, V> dictionary) {
+ if (dictionary == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
+
+ this.dict = dictionary;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePair<K, V>[] Items {
+ get {
+ KeyValuePair<K, V>[] items = new KeyValuePair<K, V>[dict.Count];
+ dict.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+
+ internal sealed class Mscorlib_KeyedCollectionDebugView<K, T> {
+ private KeyedCollection<K, T> kc;
+
+ public Mscorlib_KeyedCollectionDebugView(KeyedCollection<K, T> keyedCollection) {
+ if (keyedCollection == null) {
+ throw new ArgumentNullException("keyedCollection");
+ }
+ Contract.EndContractBlock();
+
+ kc = keyedCollection;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items {
+ get {
+ T[] items = new T[kc.Count];
+ kc.CopyTo(items, 0);
+ return items;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/Dictionary.cs b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs
new file mode 100644
index 0000000000..9cbfff5a57
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/Dictionary.cs
@@ -0,0 +1,1187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Generic hash table implementation
+**
+** #DictionaryVersusHashtableThreadSafety
+** Hashtable has multiple reader/single writer (MR/SW) thread safety built into
+** certain methods and properties, whereas Dictionary doesn't. If you're
+** converting framework code that formerly used Hashtable to Dictionary, it's
+** important to consider whether callers may have taken a dependence on MR/SW
+** thread safety. If a reader writer lock is available, then that may be used
+** with a Dictionary to get the same thread safety guarantee.
+**
+** Reader writer locks don't exist in silverlight, so we do the following as a
+** result of removing non-generic collections from silverlight:
+** 1. If the Hashtable was fully synchronized, then we replace it with a
+** Dictionary with full locks around reads/writes (same thread safety
+** guarantee).
+** 2. Otherwise, the Hashtable has the default MR/SW thread safety behavior,
+** so we do one of the following on a case-by-case basis:
+** a. If the race condition can be addressed by rearranging the code and using a temp
+** variable (for example, it's only populated immediately after created)
+** then we address the race condition this way and use Dictionary.
+** b. If there's concern about degrading performance with the increased
+** locking, we ifdef with FEATURE_NONGENERIC_COLLECTIONS so we can at
+** least use Hashtable in the desktop build, but Dictionary with full
+** locks in silverlight builds. Note that this is heavier locking than
+** MR/SW, but this is the only option without rewriting (or adding back)
+** the reader writer lock.
+** c. If there's no performance concern (e.g. debug-only code) we
+** consistently replace Hashtable with Dictionary plus full locks to
+** reduce complexity.
+** d. Most of serialization is dead code in silverlight. Instead of updating
+** those Hashtable occurences in serialization, we carved out references
+** to serialization such that this code doesn't need to build in
+** silverlight.
+===========================================================*/
+namespace System.Collections.Generic {
+
+ using System;
+ using System.Collections;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public class Dictionary<TKey,TValue>: IDictionary<TKey,TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>, ISerializable, IDeserializationCallback {
+
+ private struct Entry {
+ public int hashCode; // Lower 31 bits of hash code, -1 if unused
+ public int next; // Index of next entry, -1 if last
+ public TKey key; // Key of entry
+ public TValue value; // Value of entry
+ }
+
+ private int[] buckets;
+ private Entry[] entries;
+ private int count;
+ private int version;
+ private int freeList;
+ private int freeCount;
+ private IEqualityComparer<TKey> comparer;
+ private KeyCollection keys;
+ private ValueCollection values;
+ private Object _syncRoot;
+
+ // constants for serialization
+ private const String VersionName = "Version";
+ private const String HashSizeName = "HashSize"; // Must save buckets.Length
+ private const String KeyValuePairsName = "KeyValuePairs";
+ private const String ComparerName = "Comparer";
+
+ public Dictionary(): this(0, null) {}
+
+ public Dictionary(int capacity): this(capacity, null) {}
+
+ public Dictionary(IEqualityComparer<TKey> comparer): this(0, comparer) {}
+
+ public Dictionary(int capacity, IEqualityComparer<TKey> comparer) {
+ if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity);
+ if (capacity > 0) Initialize(capacity);
+ this.comparer = comparer ?? EqualityComparer<TKey>.Default;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING && FEATURE_CORECLR
+ if (HashHelpers.s_UseRandomizedStringHashing && comparer == EqualityComparer<string>.Default)
+ {
+ this.comparer = (IEqualityComparer<TKey>) NonRandomizedStringEqualityComparer.Default;
+ }
+#endif // FEATURE_RANDOMIZED_STRING_HASHING && FEATURE_CORECLR
+ }
+
+ public Dictionary(IDictionary<TKey,TValue> dictionary): this(dictionary, null) {}
+
+ public Dictionary(IDictionary<TKey,TValue> dictionary, IEqualityComparer<TKey> comparer):
+ this(dictionary != null? dictionary.Count: 0, comparer) {
+
+ if( dictionary == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
+ }
+
+ // It is likely that the passed-in dictionary is Dictionary<TKey,TValue>. When this is the case,
+ // avoid the enumerator allocation and overhead by looping through the entries array directly.
+ // We only do this when dictionary is Dictionary<TKey,TValue> and not a subclass, to maintain
+ // back-compat with subclasses that may have overridden the enumerator behavior.
+ if (dictionary.GetType() == typeof(Dictionary<TKey,TValue>)) {
+ Dictionary<TKey,TValue> d = (Dictionary<TKey,TValue>)dictionary;
+ int count = d.count;
+ Entry[] entries = d.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) {
+ Add(entries[i].key, entries[i].value);
+ }
+ }
+ return;
+ }
+
+ foreach (KeyValuePair<TKey,TValue> pair in dictionary) {
+ Add(pair.Key, pair.Value);
+ }
+ }
+
+ protected Dictionary(SerializationInfo info, StreamingContext context) {
+ //We can't do anything with the keys and values until the entire graph has been deserialized
+ //and we have a resonable estimate that GetHashCode is not going to fail. For the time being,
+ //we'll just cache this. The graph is not valid until OnDeserialization has been called.
+ HashHelpers.SerializationInfoTable.Add(this, info);
+ }
+
+ public IEqualityComparer<TKey> Comparer {
+ get {
+ return comparer;
+ }
+ }
+
+ public int Count {
+ get { return count - freeCount; }
+ }
+
+ public KeyCollection Keys {
+ get {
+ Contract.Ensures(Contract.Result<KeyCollection>() != null);
+ if (keys == null) keys = new KeyCollection(this);
+ return keys;
+ }
+ }
+
+ ICollection<TKey> IDictionary<TKey, TValue>.Keys {
+ get {
+ if (keys == null) keys = new KeyCollection(this);
+ return keys;
+ }
+ }
+
+ IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys {
+ get {
+ if (keys == null) keys = new KeyCollection(this);
+ return keys;
+ }
+ }
+
+ public ValueCollection Values {
+ get {
+ Contract.Ensures(Contract.Result<ValueCollection>() != null);
+ if (values == null) values = new ValueCollection(this);
+ return values;
+ }
+ }
+
+ ICollection<TValue> IDictionary<TKey, TValue>.Values {
+ get {
+ if (values == null) values = new ValueCollection(this);
+ return values;
+ }
+ }
+
+ IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values {
+ get {
+ if (values == null) values = new ValueCollection(this);
+ return values;
+ }
+ }
+
+ public TValue this[TKey key] {
+ get {
+ int i = FindEntry(key);
+ if (i >= 0) return entries[i].value;
+ ThrowHelper.ThrowKeyNotFoundException();
+ return default(TValue);
+ }
+ set {
+ Insert(key, value, false);
+ }
+ }
+
+ public void Add(TKey key, TValue value) {
+ Insert(key, value, true);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> keyValuePair) {
+ Add(keyValuePair.Key, keyValuePair.Value);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> keyValuePair) {
+ int i = FindEntry(keyValuePair.Key);
+ if( i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value)) {
+ return true;
+ }
+ return false;
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> keyValuePair) {
+ int i = FindEntry(keyValuePair.Key);
+ if( i >= 0 && EqualityComparer<TValue>.Default.Equals(entries[i].value, keyValuePair.Value)) {
+ Remove(keyValuePair.Key);
+ return true;
+ }
+ return false;
+ }
+
+ public void Clear() {
+ if (count > 0) {
+ for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
+ Array.Clear(entries, 0, count);
+ freeList = -1;
+ count = 0;
+ freeCount = 0;
+ version++;
+ }
+ }
+
+ public bool ContainsKey(TKey key) {
+ return FindEntry(key) >= 0;
+ }
+
+ public bool ContainsValue(TValue value) {
+ if (value == null) {
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0 && entries[i].value == null) return true;
+ }
+ }
+ else {
+ EqualityComparer<TValue> c = EqualityComparer<TValue>.Default;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0 && c.Equals(entries[i].value, value)) return true;
+ }
+ }
+ return false;
+ }
+
+ private void CopyTo(KeyValuePair<TKey,TValue>[] array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (index < 0 || index > array.Length ) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ int count = this.count;
+ Entry[] entries = this.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) {
+ array[index++] = new KeyValuePair<TKey,TValue>(entries[i].key, entries[i].value);
+ }
+ }
+ }
+
+ public Enumerator GetEnumerator() {
+ return new Enumerator(this, Enumerator.KeyValuePair);
+ }
+
+ IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator() {
+ return new Enumerator(this, Enumerator.KeyValuePair);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.info);
+ }
+ info.AddValue(VersionName, version);
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ info.AddValue(ComparerName, HashHelpers.GetEqualityComparerForSerialization(comparer), typeof(IEqualityComparer<TKey>));
+#else
+ info.AddValue(ComparerName, comparer, typeof(IEqualityComparer<TKey>));
+#endif
+
+ info.AddValue(HashSizeName, buckets == null ? 0 : buckets.Length); //This is the length of the bucket array.
+ if( buckets != null) {
+ KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[Count];
+ CopyTo(array, 0);
+ info.AddValue(KeyValuePairsName, array, typeof(KeyValuePair<TKey, TValue>[]));
+ }
+ }
+
+ private int FindEntry(TKey key) {
+ if( key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (buckets != null) {
+ int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
+ for (int i = buckets[hashCode % buckets.Length]; i >= 0; i = entries[i].next) {
+ if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) return i;
+ }
+ }
+ return -1;
+ }
+
+ private void Initialize(int capacity) {
+ int size = HashHelpers.GetPrime(capacity);
+ buckets = new int[size];
+ for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
+ entries = new Entry[size];
+ freeList = -1;
+ }
+
+ private void Insert(TKey key, TValue value, bool add) {
+
+ if( key == null ) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (buckets == null) Initialize(0);
+ int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
+ int targetBucket = hashCode % buckets.Length;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ int collisionCount = 0;
+#endif
+
+ for (int i = buckets[targetBucket]; i >= 0; i = entries[i].next) {
+ if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) {
+ if (add) {
+#if FEATURE_CORECLR
+ ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(key);
+#else
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
+#endif
+ }
+ entries[i].value = value;
+ version++;
+ return;
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ collisionCount++;
+#endif
+ }
+ int index;
+ if (freeCount > 0) {
+ index = freeList;
+ freeList = entries[index].next;
+ freeCount--;
+ }
+ else {
+ if (count == entries.Length)
+ {
+ Resize();
+ targetBucket = hashCode % buckets.Length;
+ }
+ index = count;
+ count++;
+ }
+
+ entries[index].hashCode = hashCode;
+ entries[index].next = buckets[targetBucket];
+ entries[index].key = key;
+ entries[index].value = value;
+ buckets[targetBucket] = index;
+ version++;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+
+#if FEATURE_CORECLR
+ // In case we hit the collision threshold we'll need to switch to the comparer which is using randomized string hashing
+ // in this case will be EqualityComparer<string>.Default.
+ // Note, randomized string hashing is turned on by default on coreclr so EqualityComparer<string>.Default will
+ // be using randomized string hashing
+
+ if (collisionCount > HashHelpers.HashCollisionThreshold && comparer == NonRandomizedStringEqualityComparer.Default)
+ {
+ comparer = (IEqualityComparer<TKey>) EqualityComparer<string>.Default;
+ Resize(entries.Length, true);
+ }
+#else
+ if(collisionCount > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(comparer))
+ {
+ comparer = (IEqualityComparer<TKey>) HashHelpers.GetRandomizedEqualityComparer(comparer);
+ Resize(entries.Length, true);
+ }
+#endif // FEATURE_CORECLR
+
+#endif
+
+ }
+
+ public virtual void OnDeserialization(Object sender) {
+ SerializationInfo siInfo;
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+
+ if (siInfo==null) {
+ // It might be necessary to call OnDeserialization from a container if the container object also implements
+ // OnDeserialization. However, remoting will call OnDeserialization again.
+ // We can return immediately if this function is called twice.
+ // Note we set remove the serialization info from the table at the end of this method.
+ return;
+ }
+
+ int realVersion = siInfo.GetInt32(VersionName);
+ int hashsize = siInfo.GetInt32(HashSizeName);
+ comparer = (IEqualityComparer<TKey>)siInfo.GetValue(ComparerName, typeof(IEqualityComparer<TKey>));
+
+ if( hashsize != 0) {
+ buckets = new int[hashsize];
+ for (int i = 0; i < buckets.Length; i++) buckets[i] = -1;
+ entries = new Entry[hashsize];
+ freeList = -1;
+
+ KeyValuePair<TKey, TValue>[] array = (KeyValuePair<TKey, TValue>[])
+ siInfo.GetValue(KeyValuePairsName, typeof(KeyValuePair<TKey, TValue>[]));
+
+ if (array==null) {
+ ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_MissingKeys);
+ }
+
+ for (int i=0; i<array.Length; i++) {
+ if ( array[i].Key == null) {
+ ThrowHelper.ThrowSerializationException(ExceptionResource.Serialization_NullKey);
+ }
+ Insert(array[i].Key, array[i].Value, true);
+ }
+ }
+ else {
+ buckets = null;
+ }
+
+ version = realVersion;
+ HashHelpers.SerializationInfoTable.Remove(this);
+ }
+
+ private void Resize() {
+ Resize(HashHelpers.ExpandPrime(count), false);
+ }
+
+ private void Resize(int newSize, bool forceNewHashCodes) {
+ Contract.Assert(newSize >= entries.Length);
+ int[] newBuckets = new int[newSize];
+ for (int i = 0; i < newBuckets.Length; i++) newBuckets[i] = -1;
+ Entry[] newEntries = new Entry[newSize];
+ Array.Copy(entries, 0, newEntries, 0, count);
+ if(forceNewHashCodes) {
+ for (int i = 0; i < count; i++) {
+ if(newEntries[i].hashCode != -1) {
+ newEntries[i].hashCode = (comparer.GetHashCode(newEntries[i].key) & 0x7FFFFFFF);
+ }
+ }
+ }
+ for (int i = 0; i < count; i++) {
+ if (newEntries[i].hashCode >= 0) {
+ int bucket = newEntries[i].hashCode % newSize;
+ newEntries[i].next = newBuckets[bucket];
+ newBuckets[bucket] = i;
+ }
+ }
+ buckets = newBuckets;
+ entries = newEntries;
+ }
+
+ public bool Remove(TKey key) {
+ if(key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (buckets != null) {
+ int hashCode = comparer.GetHashCode(key) & 0x7FFFFFFF;
+ int bucket = hashCode % buckets.Length;
+ int last = -1;
+ for (int i = buckets[bucket]; i >= 0; last = i, i = entries[i].next) {
+ if (entries[i].hashCode == hashCode && comparer.Equals(entries[i].key, key)) {
+ if (last < 0) {
+ buckets[bucket] = entries[i].next;
+ }
+ else {
+ entries[last].next = entries[i].next;
+ }
+ entries[i].hashCode = -1;
+ entries[i].next = freeList;
+ entries[i].key = default(TKey);
+ entries[i].value = default(TValue);
+ freeList = i;
+ freeCount++;
+ version++;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public bool TryGetValue(TKey key, out TValue value) {
+ int i = FindEntry(key);
+ if (i >= 0) {
+ value = entries[i].value;
+ return true;
+ }
+ value = default(TValue);
+ return false;
+ }
+
+ // This is a convenience method for the internal callers that were converted from using Hashtable.
+ // Many were combining key doesn't exist and key exists but null value (for non-value types) checks.
+ // This allows them to continue getting that behavior with minimal code delta. This is basically
+ // TryGetValue without the out param
+ internal TValue GetValueOrDefault(TKey key) {
+ int i = FindEntry(key);
+ if (i >= 0) {
+ return entries[i].value;
+ }
+ return default(TValue);
+ }
+
+ bool ICollection<KeyValuePair<TKey,TValue>>.IsReadOnly {
+ get { return false; }
+ }
+
+ void ICollection<KeyValuePair<TKey,TValue>>.CopyTo(KeyValuePair<TKey,TValue>[] array, int index) {
+ CopyTo(array, index);
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if( array.GetLowerBound(0) != 0 ) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ KeyValuePair<TKey,TValue>[] pairs = array as KeyValuePair<TKey,TValue>[];
+ if (pairs != null) {
+ CopyTo(pairs, index);
+ }
+ else if( array is DictionaryEntry[]) {
+ DictionaryEntry[] dictEntryArray = array as DictionaryEntry[];
+ Entry[] entries = this.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) {
+ dictEntryArray[index++] = new DictionaryEntry(entries[i].key, entries[i].value);
+ }
+ }
+ }
+ else {
+ object[] objects = array as object[];
+ if (objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ try {
+ int count = this.count;
+ Entry[] entries = this.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) {
+ objects[index++] = new KeyValuePair<TKey,TValue>(entries[i].key, entries[i].value);
+ }
+ }
+ }
+ catch(ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new Enumerator(this, Enumerator.KeyValuePair);
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ bool IDictionary.IsFixedSize {
+ get { return false; }
+ }
+
+ bool IDictionary.IsReadOnly {
+ get { return false; }
+ }
+
+ ICollection IDictionary.Keys {
+ get { return (ICollection)Keys; }
+ }
+
+ ICollection IDictionary.Values {
+ get { return (ICollection)Values; }
+ }
+
+ object IDictionary.this[object key] {
+ get {
+ if( IsCompatibleKey(key)) {
+ int i = FindEntry((TKey)key);
+ if (i >= 0) {
+ return entries[i].value;
+ }
+ }
+ return null;
+ }
+ set {
+ if (key == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
+
+ try {
+ TKey tempKey = (TKey)key;
+ try {
+ this[tempKey] = (TValue)value;
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
+ }
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
+ }
+ }
+ }
+
+ private static bool IsCompatibleKey(object key) {
+ if( key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+ return (key is TKey);
+ }
+
+ void IDictionary.Add(object key, object value) {
+ if (key == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<TValue>(value, ExceptionArgument.value);
+
+ try {
+ TKey tempKey = (TKey)key;
+
+ try {
+ Add(tempKey, (TValue)value);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(TValue));
+ }
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongKeyTypeArgumentException(key, typeof(TKey));
+ }
+ }
+
+ bool IDictionary.Contains(object key) {
+ if(IsCompatibleKey(key)) {
+ return ContainsKey((TKey)key);
+ }
+
+ return false;
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator() {
+ return new Enumerator(this, Enumerator.DictEntry);
+ }
+
+ void IDictionary.Remove(object key) {
+ if(IsCompatibleKey(key)) {
+ Remove((TKey)key);
+ }
+ }
+
+ [Serializable]
+ public struct Enumerator: IEnumerator<KeyValuePair<TKey,TValue>>,
+ IDictionaryEnumerator
+ {
+ private Dictionary<TKey,TValue> dictionary;
+ private int version;
+ private int index;
+ private KeyValuePair<TKey,TValue> current;
+ private int getEnumeratorRetType; // What should Enumerator.Current return?
+
+ internal const int DictEntry = 1;
+ internal const int KeyValuePair = 2;
+
+ internal Enumerator(Dictionary<TKey,TValue> dictionary, int getEnumeratorRetType) {
+ this.dictionary = dictionary;
+ version = dictionary.version;
+ index = 0;
+ this.getEnumeratorRetType = getEnumeratorRetType;
+ current = new KeyValuePair<TKey, TValue>();
+ }
+
+ public bool MoveNext() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ // Use unsigned comparison since we set index to dictionary.count+1 when the enumeration ends.
+ // dictionary.count+1 could be negative if dictionary.count is Int32.MaxValue
+ while ((uint)index < (uint)dictionary.count) {
+ if (dictionary.entries[index].hashCode >= 0) {
+ current = new KeyValuePair<TKey, TValue>(dictionary.entries[index].key, dictionary.entries[index].value);
+ index++;
+ return true;
+ }
+ index++;
+ }
+
+ index = dictionary.count + 1;
+ current = new KeyValuePair<TKey, TValue>();
+ return false;
+ }
+
+ public KeyValuePair<TKey,TValue> Current {
+ get { return current; }
+ }
+
+ public void Dispose() {
+ }
+
+ object IEnumerator.Current {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ if (getEnumeratorRetType == DictEntry) {
+ return new System.Collections.DictionaryEntry(current.Key, current.Value);
+ } else {
+ return new KeyValuePair<TKey, TValue>(current.Key, current.Value);
+ }
+ }
+ }
+
+ void IEnumerator.Reset() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ index = 0;
+ current = new KeyValuePair<TKey, TValue>();
+ }
+
+ DictionaryEntry IDictionaryEnumerator.Entry {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ return new DictionaryEntry(current.Key, current.Value);
+ }
+ }
+
+ object IDictionaryEnumerator.Key {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ return current.Key;
+ }
+ }
+
+ object IDictionaryEnumerator.Value {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ return current.Value;
+ }
+ }
+ }
+
+ [DebuggerTypeProxy(typeof(Mscorlib_DictionaryKeyCollectionDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ public sealed class KeyCollection: ICollection<TKey>, ICollection, IReadOnlyCollection<TKey>
+ {
+ private Dictionary<TKey,TValue> dictionary;
+
+ public KeyCollection(Dictionary<TKey,TValue> dictionary) {
+ if (dictionary == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
+ }
+ this.dictionary = dictionary;
+ }
+
+ public Enumerator GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ public void CopyTo(TKey[] array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < dictionary.Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ int count = dictionary.count;
+ Entry[] entries = dictionary.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) array[index++] = entries[i].key;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ bool ICollection<TKey>.IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<TKey>.Add(TKey item){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
+ }
+
+ void ICollection<TKey>.Clear(){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
+ }
+
+ bool ICollection<TKey>.Contains(TKey item){
+ return dictionary.ContainsKey(item);
+ }
+
+ bool ICollection<TKey>.Remove(TKey item){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_KeyCollectionSet);
+ return false;
+ }
+
+ IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if( array.GetLowerBound(0) != 0 ) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < dictionary.Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ TKey[] keys = array as TKey[];
+ if (keys != null) {
+ CopyTo(keys, index);
+ }
+ else {
+ object[] objects = array as object[];
+ if (objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ int count = dictionary.count;
+ Entry[] entries = dictionary.entries;
+ try {
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) objects[index++] = entries[i].key;
+ }
+ }
+ catch(ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ Object ICollection.SyncRoot {
+ get { return ((ICollection)dictionary).SyncRoot; }
+ }
+
+ [Serializable]
+ public struct Enumerator : IEnumerator<TKey>, System.Collections.IEnumerator
+ {
+ private Dictionary<TKey, TValue> dictionary;
+ private int index;
+ private int version;
+ private TKey currentKey;
+
+ internal Enumerator(Dictionary<TKey, TValue> dictionary) {
+ this.dictionary = dictionary;
+ version = dictionary.version;
+ index = 0;
+ currentKey = default(TKey);
+ }
+
+ public void Dispose() {
+ }
+
+ public bool MoveNext() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ while ((uint)index < (uint)dictionary.count) {
+ if (dictionary.entries[index].hashCode >= 0) {
+ currentKey = dictionary.entries[index].key;
+ index++;
+ return true;
+ }
+ index++;
+ }
+
+ index = dictionary.count + 1;
+ currentKey = default(TKey);
+ return false;
+ }
+
+ public TKey Current {
+ get {
+ return currentKey;
+ }
+ }
+
+ Object System.Collections.IEnumerator.Current {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ return currentKey;
+ }
+ }
+
+ void System.Collections.IEnumerator.Reset() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ index = 0;
+ currentKey = default(TKey);
+ }
+ }
+ }
+
+ [DebuggerTypeProxy(typeof(Mscorlib_DictionaryValueCollectionDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ public sealed class ValueCollection: ICollection<TValue>, ICollection, IReadOnlyCollection<TValue>
+ {
+ private Dictionary<TKey,TValue> dictionary;
+
+ public ValueCollection(Dictionary<TKey,TValue> dictionary) {
+ if (dictionary == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.dictionary);
+ }
+ this.dictionary = dictionary;
+ }
+
+ public Enumerator GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ public void CopyTo(TValue[] array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < dictionary.Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ int count = dictionary.count;
+ Entry[] entries = dictionary.entries;
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) array[index++] = entries[i].value;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ bool ICollection<TValue>.IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<TValue>.Add(TValue item){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
+ }
+
+ bool ICollection<TValue>.Remove(TValue item){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
+ return false;
+ }
+
+ void ICollection<TValue>.Clear(){
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ValueCollectionSet);
+ }
+
+ bool ICollection<TValue>.Contains(TValue item){
+ return dictionary.ContainsValue(item);
+ }
+
+ IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new Enumerator(dictionary);
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if( array.GetLowerBound(0) != 0 ) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < dictionary.Count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+
+ TValue[] values = array as TValue[];
+ if (values != null) {
+ CopyTo(values, index);
+ }
+ else {
+ object[] objects = array as object[];
+ if (objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ int count = dictionary.count;
+ Entry[] entries = dictionary.entries;
+ try {
+ for (int i = 0; i < count; i++) {
+ if (entries[i].hashCode >= 0) objects[index++] = entries[i].value;
+ }
+ }
+ catch(ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ Object ICollection.SyncRoot {
+ get { return ((ICollection)dictionary).SyncRoot; }
+ }
+
+ [Serializable]
+ public struct Enumerator : IEnumerator<TValue>, System.Collections.IEnumerator
+ {
+ private Dictionary<TKey, TValue> dictionary;
+ private int index;
+ private int version;
+ private TValue currentValue;
+
+ internal Enumerator(Dictionary<TKey, TValue> dictionary) {
+ this.dictionary = dictionary;
+ version = dictionary.version;
+ index = 0;
+ currentValue = default(TValue);
+ }
+
+ public void Dispose() {
+ }
+
+ public bool MoveNext() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ while ((uint)index < (uint)dictionary.count) {
+ if (dictionary.entries[index].hashCode >= 0) {
+ currentValue = dictionary.entries[index].value;
+ index++;
+ return true;
+ }
+ index++;
+ }
+ index = dictionary.count + 1;
+ currentValue = default(TValue);
+ return false;
+ }
+
+ public TValue Current {
+ get {
+ return currentValue;
+ }
+ }
+
+ Object System.Collections.IEnumerator.Current {
+ get {
+ if( index == 0 || (index == dictionary.count + 1)) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+
+ return currentValue;
+ }
+ }
+
+ void System.Collections.IEnumerator.Reset() {
+ if (version != dictionary.version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+ index = 0;
+ currentValue = default(TValue);
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
new file mode 100644
index 0000000000..b845d64fed
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/EqualityComparer.cs
@@ -0,0 +1,621 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Security;
+using System.Runtime.Serialization;
+
+namespace System.Collections.Generic
+{
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [TypeDependencyAttribute("System.Collections.Generic.ObjectEqualityComparer`1")]
+ public abstract class EqualityComparer<T> : IEqualityComparer, IEqualityComparer<T>
+ {
+ static readonly EqualityComparer<T> defaultComparer = CreateComparer();
+
+ public static EqualityComparer<T> Default {
+ get {
+ Contract.Ensures(Contract.Result<EqualityComparer<T>>() != null);
+ return defaultComparer;
+ }
+ }
+
+ //
+ // Note that logic in this method is replicated in vm\compile.cpp to ensure that NGen
+ // saves the right instantiations
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static EqualityComparer<T> CreateComparer()
+ {
+ Contract.Ensures(Contract.Result<EqualityComparer<T>>() != null);
+
+ object result = null;
+ RuntimeType t = (RuntimeType)typeof(T);
+
+ // Specialize type byte for performance reasons
+ if (t == typeof(byte)) {
+ result = new ByteEqualityComparer();
+ }
+ // If T implements IEquatable<T> return a GenericEqualityComparer<T>
+ else if (typeof(IEquatable<T>).IsAssignableFrom(t))
+ {
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericEqualityComparer<int>), t);
+ }
+ else if (default(T) == null) // Reference type/Nullable
+ {
+ // If T is a Nullable<U> where U implements IEquatable<U> return a NullableEqualityComparer<U>
+ if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) {
+ RuntimeType u = (RuntimeType)t.GetGenericArguments()[0];
+ if (typeof(IEquatable<>).MakeGenericType(u).IsAssignableFrom(u)) {
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableEqualityComparer<int>), u);
+ }
+ }
+ }
+ // See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
+ else if (t.IsEnum) {
+ TypeCode underlyingTypeCode = Type.GetTypeCode(Enum.GetUnderlyingType(t));
+
+ // Depending on the enum type, we need to special case the comparers so that we avoid boxing
+ // Note: We have different comparers for Short and SByte because for those types we need to make sure we call GetHashCode on the actual underlying type as the
+ // implementation of GetHashCode is more complex than for the other types.
+ switch (underlyingTypeCode) {
+ case TypeCode.Int16: // short
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(ShortEnumEqualityComparer<short>), t);
+ break;
+ case TypeCode.SByte:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(SByteEnumEqualityComparer<sbyte>), t);
+ break;
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Byte:
+ case TypeCode.UInt16: //ushort
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<int>), t);
+ break;
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(LongEnumEqualityComparer<long>), t);
+ break;
+ }
+ }
+
+ return result != null ?
+ (EqualityComparer<T>)result :
+ new ObjectEqualityComparer<T>(); // Fallback to ObjectEqualityComparer, which uses boxing
+ }
+
+ [Pure]
+ public abstract bool Equals(T x, T y);
+ [Pure]
+ public abstract int GetHashCode(T obj);
+
+ internal virtual int IndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex + count;
+ for (int i = startIndex; i < endIndex; i++) {
+ if (Equals(array[i], value)) return i;
+ }
+ return -1;
+ }
+
+ internal virtual int LastIndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex - count + 1;
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (Equals(array[i], value)) return i;
+ }
+ return -1;
+ }
+
+ int IEqualityComparer.GetHashCode(object obj) {
+ if (obj == null) return 0;
+ if (obj is T) return GetHashCode((T)obj);
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
+ return 0;
+ }
+
+ bool IEqualityComparer.Equals(object x, object y) {
+ if (x == y) return true;
+ if (x == null || y == null) return false;
+ if ((x is T) && (y is T)) return Equals((T)x, (T)y);
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
+ return false;
+ }
+ }
+
+ // The methods in this class look identical to the inherited methods, but the calls
+ // to Equal bind to IEquatable<T>.Equals(T) instead of Object.Equals(Object)
+ [Serializable]
+ internal class GenericEqualityComparer<T>: EqualityComparer<T> where T: IEquatable<T>
+ {
+ [Pure]
+ public override bool Equals(T x, T y) {
+ if (x != null) {
+ if (y != null) return x.Equals(y);
+ return false;
+ }
+ if (y != null) return false;
+ return true;
+ }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ if (obj == null) return 0;
+ return obj.GetHashCode();
+ }
+
+ internal override int IndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex + count;
+ if (value == null) {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (array[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (array[i] != null && array[i].Equals(value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ internal override int LastIndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex - count + 1;
+ if (value == null) {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i] != null && array[i].Equals(value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ GenericEqualityComparer<T> comparer = obj as GenericEqualityComparer<T>;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal class NullableEqualityComparer<T> : EqualityComparer<Nullable<T>> where T : struct, IEquatable<T>
+ {
+ [Pure]
+ public override bool Equals(Nullable<T> x, Nullable<T> y) {
+ if (x.HasValue) {
+ if (y.HasValue) return x.value.Equals(y.value);
+ return false;
+ }
+ if (y.HasValue) return false;
+ return true;
+ }
+
+ [Pure]
+ public override int GetHashCode(Nullable<T> obj) {
+ return obj.GetHashCode();
+ }
+
+ internal override int IndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count) {
+ int endIndex = startIndex + count;
+ if (!value.HasValue) {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (!array[i].HasValue) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (array[i].HasValue && array[i].value.Equals(value.value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ internal override int LastIndexOf(Nullable<T>[] array, Nullable<T> value, int startIndex, int count) {
+ int endIndex = startIndex - count + 1;
+ if (!value.HasValue) {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (!array[i].HasValue) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i].HasValue && array[i].value.Equals(value.value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ NullableEqualityComparer<T> comparer = obj as NullableEqualityComparer<T>;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal class ObjectEqualityComparer<T>: EqualityComparer<T>
+ {
+ [Pure]
+ public override bool Equals(T x, T y) {
+ if (x != null) {
+ if (y != null) return x.Equals(y);
+ return false;
+ }
+ if (y != null) return false;
+ return true;
+ }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ if (obj == null) return 0;
+ return obj.GetHashCode();
+ }
+
+ internal override int IndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex + count;
+ if (value == null) {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (array[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i < endIndex; i++) {
+ if (array[i] != null && array[i].Equals(value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ internal override int LastIndexOf(T[] array, T value, int startIndex, int count) {
+ int endIndex = startIndex - count + 1;
+ if (value == null) {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i] == null) return i;
+ }
+ }
+ else {
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i] != null && array[i].Equals(value)) return i;
+ }
+ }
+ return -1;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ ObjectEqualityComparer<T> comparer = obj as ObjectEqualityComparer<T>;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+ }
+
+#if FEATURE_CORECLR
+ // NonRandomizedStringEqualityComparer is the comparer used by default with the Dictionary<string,...>
+ // As the randomized string hashing is turned on by default on coreclr, we need to keep the performance not affected
+ // as much as possible in the main stream scenarios like Dictionary<string,>
+ // We use NonRandomizedStringEqualityComparer as default comparer as it doesnt use the randomized string hashing which
+ // keep the perofrmance not affected till we hit collision threshold and then we switch to the comparer which is using
+ // randomized string hashing GenericEqualityComparer<string>
+
+ internal class NonRandomizedStringEqualityComparer : GenericEqualityComparer<string> {
+ static IEqualityComparer<string> s_nonRandomizedComparer;
+
+ internal static new IEqualityComparer<string> Default {
+ get {
+ if (s_nonRandomizedComparer == null) {
+ s_nonRandomizedComparer = new NonRandomizedStringEqualityComparer();
+ }
+ return s_nonRandomizedComparer;
+ }
+ }
+
+ [Pure]
+ public override int GetHashCode(string obj) {
+ if (obj == null) return 0;
+ return obj.GetLegacyNonRandomizedHashCode();
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ // Performance of IndexOf on byte array is very important for some scenarios.
+ // We will call the C runtime function memchr, which is optimized.
+ [Serializable]
+ internal class ByteEqualityComparer: EqualityComparer<byte>
+ {
+ [Pure]
+ public override bool Equals(byte x, byte y) {
+ return x == y;
+ }
+
+ [Pure]
+ public override int GetHashCode(byte b) {
+ return b.GetHashCode();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe override int IndexOf(byte[] array, byte value, int startIndex, int count) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ if (count > array.Length - startIndex)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+ if (count == 0) return -1;
+ fixed (byte* pbytes = array) {
+ return Buffer.IndexOfByte(pbytes, value, startIndex, count);
+ }
+ }
+
+ internal override int LastIndexOf(byte[] array, byte value, int startIndex, int count) {
+ int endIndex = startIndex - count + 1;
+ for (int i = startIndex; i >= endIndex; i--) {
+ if (array[i] == value) return i;
+ }
+ return -1;
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ ByteEqualityComparer comparer = obj as ByteEqualityComparer;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal class EnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
+ {
+ [Pure]
+ public override bool Equals(T x, T y) {
+ int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(x);
+ int y_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(y);
+ return x_final == y_final;
+ }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
+ return x_final.GetHashCode();
+ }
+
+ public EnumEqualityComparer() { }
+
+ // This is used by the serialization engine.
+ protected EnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {
+ // For back-compat we need to serialize the comparers for enums with underlying types other than int as ObjectEqualityComparer
+ if (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(T))) != TypeCode.Int32) {
+ info.SetType(typeof(ObjectEqualityComparer<T>));
+ }
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ EnumEqualityComparer<T> comparer = obj as EnumEqualityComparer<T>;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal sealed class SByteEnumEqualityComparer<T> : EnumEqualityComparer<T>, ISerializable where T : struct
+ {
+ public SByteEnumEqualityComparer() { }
+
+ // This is used by the serialization engine.
+ public SByteEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
+ return ((sbyte)x_final).GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal sealed class ShortEnumEqualityComparer<T> : EnumEqualityComparer<T>, ISerializable where T : struct
+ {
+ public ShortEnumEqualityComparer() { }
+
+ // This is used by the serialization engine.
+ public ShortEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ int x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCast(obj);
+ return ((short)x_final).GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal sealed class LongEnumEqualityComparer<T> : EqualityComparer<T>, ISerializable where T : struct
+ {
+ [Pure]
+ public override bool Equals(T x, T y) {
+ long x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCastLong(x);
+ long y_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCastLong(y);
+ return x_final == y_final;
+ }
+
+ [Pure]
+ public override int GetHashCode(T obj) {
+ long x_final = System.Runtime.CompilerServices.JitHelpers.UnsafeEnumCastLong(obj);
+ return x_final.GetHashCode();
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ LongEnumEqualityComparer<T> comparer = obj as LongEnumEqualityComparer<T>;
+ return comparer != null;
+ }
+
+ public override int GetHashCode() {
+ return this.GetType().Name.GetHashCode();
+ }
+
+ public LongEnumEqualityComparer() { }
+
+ // This is used by the serialization engine.
+ public LongEnumEqualityComparer(SerializationInfo information, StreamingContext context) { }
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // The LongEnumEqualityComparer does not exist on 4.0 so we need to serialize this comparer as ObjectEqualityComparer
+ // to allow for roundtrip between 4.0 and 4.5.
+ info.SetType(typeof(ObjectEqualityComparer<T>));
+ }
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ // This type is not serializeable by design. It does not exist in previous versions and will be removed
+ // Once we move the framework to using secure hashing by default.
+ internal sealed class RandomizedStringEqualityComparer : IEqualityComparer<String>, IEqualityComparer, IWellKnownStringEqualityComparer
+ {
+ private long _entropy;
+
+ public RandomizedStringEqualityComparer() {
+ _entropy = HashHelpers.GetEntropy();
+ }
+
+ public new bool Equals(object x, object y) {
+ if (x == y) return true;
+ if (x == null || y == null) return false;
+ if ((x is string) && (y is string)) return Equals((string)x, (string)y);
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArgumentForComparison);
+ return false;
+ }
+
+ [Pure]
+ public bool Equals(string x, string y) {
+ if (x != null) {
+ if (y != null) return x.Equals(y);
+ return false;
+ }
+ if (y != null) return false;
+ return true;
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public int GetHashCode(String obj) {
+ if(obj == null) return 0;
+ return String.InternalMarvin32HashString(obj, obj.Length, _entropy);
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public int GetHashCode(Object obj) {
+ if(obj == null) return 0;
+
+ string sObj = obj as string;
+ if(sObj != null) return String.InternalMarvin32HashString(sObj, sObj.Length, _entropy);
+
+ return obj.GetHashCode();
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj) {
+ RandomizedStringEqualityComparer comparer = obj as RandomizedStringEqualityComparer;
+ return (comparer != null) && (this._entropy == comparer._entropy);
+ }
+
+ public override int GetHashCode() {
+ return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
+ }
+
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new RandomizedStringEqualityComparer();
+ }
+
+ // We want to serialize the old comparer.
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return EqualityComparer<string>.Default;
+ }
+ }
+
+ // This type is not serializeable by design. It does not exist in previous versions and will be removed
+ // Once we move the framework to using secure hashing by default.
+ internal sealed class RandomizedObjectEqualityComparer : IEqualityComparer, IWellKnownStringEqualityComparer
+ {
+ private long _entropy;
+
+ public RandomizedObjectEqualityComparer() {
+ _entropy = HashHelpers.GetEntropy();
+ }
+
+ [Pure]
+ public new bool Equals(Object x, Object y) {
+ if (x != null) {
+ if (y != null) return x.Equals(y);
+ return false;
+ }
+ if (y != null) return false;
+ return true;
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public int GetHashCode(Object obj) {
+ if(obj == null) return 0;
+
+ string sObj = obj as string;
+ if(sObj != null) return String.InternalMarvin32HashString(sObj, sObj.Length, _entropy);
+
+ return obj.GetHashCode();
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ RandomizedObjectEqualityComparer comparer = obj as RandomizedObjectEqualityComparer;
+ return (comparer != null) && (this._entropy == comparer._entropy);
+ }
+
+ public override int GetHashCode() {
+ return (this.GetType().Name.GetHashCode() ^ ((int) (_entropy & 0x7FFFFFFF)));
+ }
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new RandomizedObjectEqualityComparer();
+ }
+
+ // We want to serialize the old comparer, which in this case was null.
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return null;
+ }
+ }
+#endif
+}
+
diff --git a/src/mscorlib/src/System/Collections/Generic/ICollection.cs b/src/mscorlib/src/System/Collections/Generic/ICollection.cs
new file mode 100644
index 0000000000..741e8cc79b
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/ICollection.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ICollection
+**
+**
+**
+**
+** Purpose: Base interface for all generic collections.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // Base interface for all collections, defining enumerators, size, and
+ // synchronization methods.
+
+ // Note that T[] : IList<T>, and we want to ensure that if you use
+ // IList<YourValueType>, we ensure a YourValueType[] can be used
+ // without jitting. Hence the TypeDependencyAttribute on SZArrayHelper.
+ // This is a special workaround internally though - see VM\compile.cpp.
+ // The same attribute is on IEnumerable<T> and ICollection<T>.
+ [TypeDependencyAttribute("System.SZArrayHelper")]
+ public interface ICollection<T> : IEnumerable<T>
+ {
+ // Number of items in the collections.
+ int Count { get; }
+
+ bool IsReadOnly { get; }
+
+ void Add(T item);
+
+ void Clear();
+
+ bool Contains(T item);
+
+ // CopyTo copies a collection into an Array, starting at a particular
+ // index into the array.
+ //
+ void CopyTo(T[] array, int arrayIndex);
+
+ //void CopyTo(int sourceIndex, T[] destinationArray, int destinationIndex, int count);
+
+ bool Remove(T item);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IComparer.cs b/src/mscorlib/src/System/Collections/Generic/IComparer.cs
new file mode 100644
index 0000000000..7b9e97ff0e
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IComparer.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IComparer
+**
+**
+**
+**
+** Purpose: Interface for comparing two generic Objects.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+
+ using System;
+ // The generic IComparer interface implements a method that compares
+ // two objects. It is used in conjunction with the Sort and
+ // BinarySearch methods on the Array, List, and SortedList classes.
+ public interface IComparer<in T>
+ {
+ // Compares two objects. An implementation of this method must return a
+ // value less than zero if x is less than y, zero if x is equal to y, or a
+ // value greater than zero if x is greater than y.
+ //
+ int Compare(T x, T y);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IDictionary.cs b/src/mscorlib/src/System/Collections/Generic/IDictionary.cs
new file mode 100644
index 0000000000..2a2da944d3
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IDictionary.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IDictionary
+**
+**
+**
+**
+** Purpose: Base interface for all generic dictionaries.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // An IDictionary is a possibly unordered set of key-value pairs.
+ // Keys can be any non-null object. Values can be any object.
+ // You can look up a value in an IDictionary via the default indexed
+ // property, Items.
+ public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>
+ {
+ // Interfaces are not serializable
+ // The Item property provides methods to read and edit entries
+ // in the Dictionary.
+ TValue this[TKey key] {
+ get;
+ set;
+ }
+
+ // Returns a collections of the keys in this dictionary.
+ ICollection<TKey> Keys {
+ get;
+ }
+
+ // Returns a collections of the values in this dictionary.
+ ICollection<TValue> Values {
+ get;
+ }
+
+ // Returns whether this dictionary contains a particular key.
+ //
+ bool ContainsKey(TKey key);
+
+ // Adds a key-value pair to the dictionary.
+ //
+ void Add(TKey key, TValue value);
+
+ // Removes a particular key from the dictionary.
+ //
+ bool Remove(TKey key);
+
+ bool TryGetValue(TKey key, out TValue value);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IEnumerable.cs b/src/mscorlib/src/System/Collections/Generic/IEnumerable.cs
new file mode 100644
index 0000000000..67f35ce675
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IEnumerable.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IEnumerable
+**
+**
+**
+**
+** Purpose: Interface for providing generic IEnumerators
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+ using System;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // Implement this interface if you need to support foreach semantics.
+
+ // Note that T[] : IList<T>, and we want to ensure that if you use
+ // IList<YourValueType>, we ensure a YourValueType[] can be used
+ // without jitting. Hence the TypeDependencyAttribute on SZArrayHelper.
+ // This is a special workaround internally though - see VM\compile.cpp.
+ // The same attribute is on IList<T> and ICollection<T>.
+ [TypeDependencyAttribute("System.SZArrayHelper")]
+ public interface IEnumerable<out T> : IEnumerable
+ {
+ // Returns an IEnumerator for this enumerable Object. The enumerator provides
+ // a simple way to access all the contents of a collection.
+ /// <include file='doc\IEnumerable.uex' path='docs/doc[@for="IEnumerable.GetEnumerator"]/*' />
+ new IEnumerator<T> GetEnumerator();
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IEnumerator.cs b/src/mscorlib/src/System/Collections/Generic/IEnumerator.cs
new file mode 100644
index 0000000000..335616757b
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IEnumerator.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IEnumerator
+**
+**
+**
+**
+** Purpose: Base interface for all generic enumerators.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+ using System;
+ using System.Runtime.InteropServices;
+
+ // Base interface for all generic enumerators, providing a simple approach
+ // to iterating over a collection.
+ public interface IEnumerator<out T> : IDisposable, IEnumerator
+ {
+ // Returns the current element of the enumeration. The returned value is
+ // undefined before the first call to MoveNext and following a
+ // call to MoveNext that returned false. Multiple calls to
+ // GetCurrent with no intervening calls to MoveNext
+ // will return the same object.
+ //
+ /// <include file='doc\IEnumerator.uex' path='docs/doc[@for="IEnumerator.Current"]/*' />
+ new T Current {
+ get;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IEqualityComparer.cs b/src/mscorlib/src/System/Collections/Generic/IEqualityComparer.cs
new file mode 100644
index 0000000000..b6ac3be006
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IEqualityComparer.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Collections.Generic {
+ using System;
+
+ // The generic IEqualityComparer interface implements methods to if check two objects are equal
+ // and generate Hashcode for an object.
+ // It is use in Dictionary class.
+ public interface IEqualityComparer<in T>
+ {
+ bool Equals(T x, T y);
+ int GetHashCode(T obj);
+ }
+}
+
diff --git a/src/mscorlib/src/System/Collections/Generic/IList.cs b/src/mscorlib/src/System/Collections/Generic/IList.cs
new file mode 100644
index 0000000000..75ca0a9b00
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IList.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IList
+**
+**
+**
+**
+** Purpose: Base interface for all generic lists.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+
+ using System;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // An IList is an ordered collection of objects. The exact ordering
+ // is up to the implementation of the list, ranging from a sorted
+ // order to insertion order.
+
+ // Note that T[] : IList<T>, and we want to ensure that if you use
+ // IList<YourValueType>, we ensure a YourValueType[] can be used
+ // without jitting. Hence the TypeDependencyAttribute on SZArrayHelper.
+ // This is a special workaround internally though - see VM\compile.cpp.
+ // The same attribute is on IEnumerable<T> and ICollection<T>.
+ [TypeDependencyAttribute("System.SZArrayHelper")]
+ public interface IList<T> : ICollection<T>
+ {
+ // The Item property provides methods to read and edit entries in the List.
+ T this[int index] {
+ get;
+ set;
+ }
+
+ // Returns the index of a particular item, if it is in the list.
+ // Returns -1 if the item isn't in the list.
+ int IndexOf(T item);
+
+ // Inserts value into the list at position index.
+ // index must be non-negative and less than or equal to the
+ // number of elements in the list. If index equals the number
+ // of items in the list, then value is appended to the end.
+ void Insert(int index, T item);
+
+ // Removes the item at position index.
+ void RemoveAt(int index);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IReadOnlyCollection.cs b/src/mscorlib/src/System/Collections/Generic/IReadOnlyCollection.cs
new file mode 100644
index 0000000000..13bc718760
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IReadOnlyCollection.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IReadOnlyCollection<T>
+**
+**
+**
+** Purpose: Base interface for read-only generic lists.
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+
+ // Provides a read-only, covariant view of a generic list.
+
+ // Note that T[] : IReadOnlyList<T>, and we want to ensure that if you use
+ // IList<YourValueType>, we ensure a YourValueType[] can be used
+ // without jitting. Hence the TypeDependencyAttribute on SZArrayHelper.
+ // This is a special workaround internally though - see VM\compile.cpp.
+ // The same attribute is on IList<T>, IEnumerable<T>, ICollection<T>, and IReadOnlyList<T>.
+ [TypeDependencyAttribute("System.SZArrayHelper")]
+ // If we ever implement more interfaces on IReadOnlyCollection, we should also update RuntimeTypeCache.PopulateInterfaces() in rttype.cs
+ public interface IReadOnlyCollection<out T> : IEnumerable<T>
+ {
+ int Count { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IReadOnlyDictionary.cs b/src/mscorlib/src/System/Collections/Generic/IReadOnlyDictionary.cs
new file mode 100644
index 0000000000..3603b9a4ea
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IReadOnlyDictionary.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IReadOnlyDictionary<TKey, TValue>
+**
+**
+**
+** Purpose: Base interface for read-only generic dictionaries.
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Collections.Generic
+{
+ // Provides a read-only view of a generic dictionary.
+ public interface IReadOnlyDictionary<TKey, TValue> : IReadOnlyCollection<KeyValuePair<TKey, TValue>>
+ {
+ bool ContainsKey(TKey key);
+ bool TryGetValue(TKey key, out TValue value);
+
+ TValue this[TKey key] { get; }
+ IEnumerable<TKey> Keys { get; }
+ IEnumerable<TValue> Values { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/IReadOnlyList.cs b/src/mscorlib/src/System/Collections/Generic/IReadOnlyList.cs
new file mode 100644
index 0000000000..77366f0b2f
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/IReadOnlyList.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IReadOnlyList<T>
+**
+**
+**
+** Purpose: Base interface for read-only generic lists.
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+
+namespace System.Collections.Generic
+{
+
+ // Provides a read-only, covariant view of a generic list.
+
+ // Note that T[] : IReadOnlyList<T>, and we want to ensure that if you use
+ // IList<YourValueType>, we ensure a YourValueType[] can be used
+ // without jitting. Hence the TypeDependencyAttribute on SZArrayHelper.
+ // This is a special workaround internally though - see VM\compile.cpp.
+ // The same attribute is on IList<T>, IEnumerable<T>, ICollection<T> and IReadOnlyCollection<T>.
+ [TypeDependencyAttribute("System.SZArrayHelper")]
+ // If we ever implement more interfaces on IReadOnlyList, we should also update RuntimeTypeCache.PopulateInterfaces() in rttype.cs
+ public interface IReadOnlyList<out T> : IReadOnlyCollection<T>
+ {
+ T this[int index] { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/KeyNotFoundException.cs b/src/mscorlib/src/System/Collections/Generic/KeyNotFoundException.cs
new file mode 100644
index 0000000000..ffcd0405fd
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/KeyNotFoundException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: Exception class for Hashtable and Dictionary.
+**
+**
+=============================================================================*/
+
+namespace System.Collections.Generic {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class KeyNotFoundException : SystemException, ISerializable {
+
+ public KeyNotFoundException ()
+ : base(Environment.GetResourceString("Arg_KeyNotFound")) {
+ SetErrorCode(System.__HResults.COR_E_KEYNOTFOUND);
+ }
+
+ public KeyNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(System.__HResults.COR_E_KEYNOTFOUND);
+ }
+
+ public KeyNotFoundException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(System.__HResults.COR_E_KEYNOTFOUND);
+ }
+
+
+ protected KeyNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs b/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs
new file mode 100644
index 0000000000..17e1c531f1
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/KeyValuePair.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: KeyValuePair
+**
+**
+**
+**
+** Purpose: Generic key-value pair for dictionary enumerators.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+
+ using System;
+ using System.Text;
+
+ // A KeyValuePair holds a key and a value from a dictionary.
+ // It is used by the IEnumerable<T> implementation for both IDictionary<TKey, TValue>
+ // and IReadOnlyDictionary<TKey, TValue>.
+ [Serializable]
+ public struct KeyValuePair<TKey, TValue> {
+ private TKey key;
+ private TValue value;
+
+ public KeyValuePair(TKey key, TValue value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ public TKey Key {
+ get { return key; }
+ }
+
+ public TValue Value {
+ get { return value; }
+ }
+
+ public override string ToString() {
+ StringBuilder s = StringBuilderCache.Acquire();
+ s.Append('[');
+ if( Key != null) {
+ s.Append(Key.ToString());
+ }
+ s.Append(", ");
+ if( Value != null) {
+ s.Append(Value.ToString());
+ }
+ s.Append(']');
+ return StringBuilderCache.GetStringAndRelease(s);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Generic/List.cs b/src/mscorlib/src/System/Collections/Generic/List.cs
new file mode 100644
index 0000000000..ae3356d372
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Generic/List.cs
@@ -0,0 +1,1120 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Implements a generic, dynamically sized list as an
+** array.
+**
+**
+===========================================================*/
+namespace System.Collections.Generic {
+
+ using System;
+ using System.Runtime;
+ using System.Runtime.Versioning;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Collections.ObjectModel;
+ using System.Security.Permissions;
+
+ // Implements a variable-size List that uses an array of objects to store the
+ // elements. A List has a capacity, which is the allocated length
+ // of the internal array. As elements are added to a List, the capacity
+ // of the List is automatically increased as required by reallocating the
+ // internal array.
+ //
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T>
+ {
+ private const int _defaultCapacity = 4;
+
+ private T[] _items;
+ [ContractPublicPropertyName("Count")]
+ private int _size;
+ private int _version;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ static readonly T[] _emptyArray = new T[0];
+
+ // Constructs a List. The list is initially empty and has a capacity
+ // of zero. Upon adding the first element to the list the capacity is
+ // increased to _defaultCapacity, and then increased in multiples of two
+ // as required.
+ public List() {
+ _items = _emptyArray;
+ }
+
+ // Constructs a List with a given initial capacity. The list is
+ // initially empty, but will have room for the given number of elements
+ // before any reallocations are required.
+ //
+ public List(int capacity) {
+ if (capacity < 0) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.capacity, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ Contract.EndContractBlock();
+
+ if (capacity == 0)
+ _items = _emptyArray;
+ else
+ _items = new T[capacity];
+ }
+
+ // Constructs a List, copying the contents of the given collection. The
+ // size and capacity of the new list will both be equal to the size of the
+ // given collection.
+ //
+ public List(IEnumerable<T> collection) {
+ if (collection==null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+ Contract.EndContractBlock();
+
+ ICollection<T> c = collection as ICollection<T>;
+ if( c != null) {
+ int count = c.Count;
+ if (count == 0)
+ {
+ _items = _emptyArray;
+ }
+ else {
+ _items = new T[count];
+ c.CopyTo(_items, 0);
+ _size = count;
+ }
+ }
+ else {
+ _size = 0;
+ _items = _emptyArray;
+ // This enumerable could be empty. Let Add allocate a new array, if needed.
+ // Note it will also go to _defaultCapacity first, not 1, then 2, etc.
+
+ using(IEnumerator<T> en = collection.GetEnumerator()) {
+ while(en.MoveNext()) {
+ Add(en.Current);
+ }
+ }
+ }
+ }
+
+ // Gets and sets the capacity of this list. The capacity is the size of
+ // the internal array used to hold items. When set, the internal
+ // array of the list is reallocated to the given capacity.
+ //
+ public int Capacity {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return _items.Length;
+ }
+ set {
+ if (value < _size) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
+ }
+ Contract.EndContractBlock();
+
+ if (value != _items.Length) {
+ if (value > 0) {
+ T[] newItems = new T[value];
+ if (_size > 0) {
+ Array.Copy(_items, 0, newItems, 0, _size);
+ }
+ _items = newItems;
+ }
+ else {
+ _items = _emptyArray;
+ }
+ }
+ }
+ }
+
+ // Read-only property describing how many elements are in the List.
+ public int Count {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return _size;
+ }
+ }
+
+ bool System.Collections.IList.IsFixedSize {
+ get { return false; }
+ }
+
+
+ // Is this List read-only?
+ bool ICollection<T>.IsReadOnly {
+ get { return false; }
+ }
+
+ bool System.Collections.IList.IsReadOnly {
+ get { return false; }
+ }
+
+ // Is this List synchronized (thread-safe)?
+ bool System.Collections.ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ // Synchronization root for this object.
+ Object System.Collections.ICollection.SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+ // Sets or Gets the element at the given index.
+ //
+ public T this[int index] {
+ get {
+ // Following trick can reduce the range check by one
+ if ((uint) index >= (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+ Contract.EndContractBlock();
+ return _items[index];
+ }
+
+ set {
+ if ((uint) index >= (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+ Contract.EndContractBlock();
+ _items[index] = value;
+ _version++;
+ }
+ }
+
+ private static bool IsCompatibleObject(object value) {
+ // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ return ((value is T) || (value == null && default(T) == null));
+ }
+
+ Object System.Collections.IList.this[int index] {
+ get {
+ return this[index];
+ }
+ set {
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try {
+ this[index] = (T)value;
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+ }
+ }
+
+ // Adds the given object to the end of this list. The size of the list is
+ // increased by one. If required, the capacity of the list is doubled
+ // before adding the new element.
+ //
+ public void Add(T item) {
+ if (_size == _items.Length) EnsureCapacity(_size + 1);
+ _items[_size++] = item;
+ _version++;
+ }
+
+ int System.Collections.IList.Add(Object item)
+ {
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
+
+ try {
+ Add((T) item);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T));
+ }
+
+ return Count - 1;
+ }
+
+
+ // Adds the elements of the given collection to the end of this list. If
+ // required, the capacity of the list is increased to twice the previous
+ // capacity or the new size, whichever is larger.
+ //
+ public void AddRange(IEnumerable<T> collection) {
+ Contract.Ensures(Count >= Contract.OldValue(Count));
+
+ InsertRange(_size, collection);
+ }
+
+ public ReadOnlyCollection<T> AsReadOnly() {
+ Contract.Ensures(Contract.Result<ReadOnlyCollection<T>>() != null);
+ return new ReadOnlyCollection<T>(this);
+ }
+
+ // Searches a section of the list for a given element using a binary search
+ // algorithm. Elements of the list are compared to the search value using
+ // the given IComparer interface. If comparer is null, elements of
+ // the list are compared to the search value using the IComparable
+ // interface, which in that case must be implemented by all elements of the
+ // list and the given search value. This method assumes that the given
+ // section of the list is already sorted; if this is not the case, the
+ // result will be incorrect.
+ //
+ // The method returns the index of the given value in the list. If the
+ // list does not contain the given value, the method returns a negative
+ // integer. The bitwise complement operator (~) can be applied to a
+ // negative result to produce the index of the first element (if any) that
+ // is larger than the given search value. This is also the index at which
+ // the search value should be inserted into the list in order for the list
+ // to remain sorted.
+ //
+ // The method uses the Array.BinarySearch method to perform the
+ // search.
+ //
+ public int BinarySearch(int index, int count, T item, IComparer<T> comparer) {
+ if (index < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (count < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ if (_size - index < count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.Ensures(Contract.Result<int>() <= index + count);
+ Contract.EndContractBlock();
+
+ return Array.BinarySearch<T>(_items, index, count, item, comparer);
+ }
+
+ public int BinarySearch(T item)
+ {
+ Contract.Ensures(Contract.Result<int>() <= Count);
+ return BinarySearch(0, Count, item, null);
+ }
+
+ public int BinarySearch(T item, IComparer<T> comparer)
+ {
+ Contract.Ensures(Contract.Result<int>() <= Count);
+ return BinarySearch(0, Count, item, comparer);
+ }
+
+
+ // Clears the contents of List.
+ public void Clear() {
+ if (_size > 0)
+ {
+ Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ _size = 0;
+ }
+ _version++;
+ }
+
+ // Contains returns true if the specified element is in the List.
+ // It does a linear, O(n) search. Equality is determined by calling
+ // EqualityComparer<T>.Default.Equals().
+
+ public bool Contains(T item)
+ {
+ // PERF: IndexOf calls Array.IndexOf, which internally
+ // calls EqualityComparer<T>.Default.IndexOf, which
+ // is specialized for different types. This
+ // boosts performance since instead of making a
+ // virtual method call each iteration of the loop,
+ // via EqualityComparer<T>.Default.Equals, we
+ // only make one virtual call to EqualityComparer.IndexOf.
+
+ return _size != 0 && IndexOf(item) != -1;
+ }
+
+ bool System.Collections.IList.Contains(Object item)
+ {
+ if(IsCompatibleObject(item)) {
+ return Contains((T) item);
+ }
+ return false;
+ }
+
+ public List<TOutput> ConvertAll<TOutput>(Converter<T,TOutput> converter) {
+ if( converter == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.converter);
+ }
+
+ Contract.EndContractBlock();
+
+ List<TOutput> list = new List<TOutput>(_size);
+ for( int i = 0; i< _size; i++) {
+ list._items[i] = converter(_items[i]);
+ }
+ list._size = _size;
+ return list;
+ }
+
+ // Copies this List into array, which must be of a
+ // compatible array type.
+ //
+ public void CopyTo(T[] array) {
+ CopyTo(array, 0);
+ }
+
+ // Copies this List into array, which must be of a
+ // compatible array type.
+ //
+ void System.Collections.ICollection.CopyTo(Array array, int arrayIndex) {
+ if ((array != null) && (array.Rank != 1)) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+ Contract.EndContractBlock();
+
+ try {
+ // Array.Copy will check for NULL.
+ Array.Copy(_items, 0, array, arrayIndex, _size);
+ }
+ catch(ArrayTypeMismatchException){
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+
+ // Copies a section of this list to the given array at the given index.
+ //
+ // The method uses the Array.Copy method to copy the elements.
+ //
+ public void CopyTo(int index, T[] array, int arrayIndex, int count) {
+ if (_size - index < count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ }
+ Contract.EndContractBlock();
+
+ // Delegate rest of error checking to Array.Copy.
+ Array.Copy(_items, index, array, arrayIndex, count);
+ }
+
+ public void CopyTo(T[] array, int arrayIndex) {
+ // Delegate rest of error checking to Array.Copy.
+ Array.Copy(_items, 0, array, arrayIndex, _size);
+ }
+
+ // Ensures that the capacity of this list is at least the given minimum
+ // value. If the currect capacity of the list is less than min, the
+ // capacity is increased to twice the current capacity or to min,
+ // whichever is larger.
+ private void EnsureCapacity(int min) {
+ if (_items.Length < min) {
+ int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2;
+ // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
+ // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+ if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
+ if (newCapacity < min) newCapacity = min;
+ Capacity = newCapacity;
+ }
+ }
+
+ public bool Exists(Predicate<T> match) {
+ return FindIndex(match) != -1;
+ }
+
+ public T Find(Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0 ; i < _size; i++) {
+ if(match(_items[i])) {
+ return _items[i];
+ }
+ }
+ return default(T);
+ }
+
+ public List<T> FindAll(Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ List<T> list = new List<T>();
+ for(int i = 0 ; i < _size; i++) {
+ if(match(_items[i])) {
+ list.Add(_items[i]);
+ }
+ }
+ return list;
+ }
+
+ public int FindIndex(Predicate<T> match) {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return FindIndex(0, _size, match);
+ }
+
+ public int FindIndex(int startIndex, Predicate<T> match) {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < startIndex + Count);
+ return FindIndex(startIndex, _size - startIndex, match);
+ }
+
+ public int FindIndex(int startIndex, int count, Predicate<T> match) {
+ if( (uint)startIndex > (uint)_size ) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+
+ if (count < 0 || startIndex > _size - count) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < startIndex + count);
+ Contract.EndContractBlock();
+
+ int endIndex = startIndex + count;
+ for( int i = startIndex; i < endIndex; i++) {
+ if( match(_items[i])) return i;
+ }
+ return -1;
+ }
+
+ public T FindLast(Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = _size - 1 ; i >= 0; i--) {
+ if(match(_items[i])) {
+ return _items[i];
+ }
+ }
+ return default(T);
+ }
+
+ public int FindLastIndex(Predicate<T> match) {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return FindLastIndex(_size - 1, _size, match);
+ }
+
+ public int FindLastIndex(int startIndex, Predicate<T> match) {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() <= startIndex);
+ return FindLastIndex(startIndex, startIndex + 1, match);
+ }
+
+ public int FindLastIndex(int startIndex, int count, Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() <= startIndex);
+ Contract.EndContractBlock();
+
+ if(_size == 0) {
+ // Special case for 0 length List
+ if( startIndex != -1) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+ }
+ else {
+ // Make sure we're not out of range
+ if ( (uint)startIndex >= (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.startIndex, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+ }
+
+ // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ }
+
+ int endIndex = startIndex - count;
+ for( int i = startIndex; i > endIndex; i--) {
+ if( match(_items[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public void ForEach(Action<T> action) {
+ if( action == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
+ }
+ Contract.EndContractBlock();
+
+ int version = _version;
+
+ for(int i = 0 ; i < _size; i++) {
+ if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5) {
+ break;
+ }
+ action(_items[i]);
+ }
+
+ if (version != _version && BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ // Returns an enumerator for this list with the given
+ // permission for removal of elements. If modifications made to the list
+ // while an enumeration is in progress, the MoveNext and
+ // GetObject methods of the enumerator will throw an exception.
+ //
+ public Enumerator GetEnumerator() {
+ return new Enumerator(this);
+ }
+
+ /// <internalonly/>
+ IEnumerator<T> IEnumerable<T>.GetEnumerator() {
+ return new Enumerator(this);
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return new Enumerator(this);
+ }
+
+ public List<T> GetRange(int index, int count) {
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (count < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (_size - index < count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ }
+ Contract.Ensures(Contract.Result<List<T>>() != null);
+ Contract.EndContractBlock();
+
+ List<T> list = new List<T>(count);
+ Array.Copy(_items, index, list._items, 0, count);
+ list._size = count;
+ return list;
+ }
+
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards from beginning to end.
+ // The elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public int IndexOf(T item) {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ return Array.IndexOf(_items, item, 0, _size);
+ }
+
+ int System.Collections.IList.IndexOf(Object item)
+ {
+ if(IsCompatibleObject(item)) {
+ return IndexOf((T)item);
+ }
+ return -1;
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards, starting at index
+ // index and ending at count number of elements. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public int IndexOf(T item, int index) {
+ if (index > _size)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+ return Array.IndexOf(_items, item, index, _size - index);
+ }
+
+ // Returns the index of the first occurrence of a given value in a range of
+ // this list. The list is searched forwards, starting at index
+ // index and upto count number of elements. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.IndexOf method to perform the
+ // search.
+ //
+ public int IndexOf(T item, int index, int count) {
+ if (index > _size)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
+
+ if (count <0 || index > _size - count) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_Count);
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ Contract.EndContractBlock();
+
+ return Array.IndexOf(_items, item, index, count);
+ }
+
+ // Inserts an element into this list at a given index. The size of the list
+ // is increased by one. If required, the capacity of the list is doubled
+ // before inserting the new element.
+ //
+ public void Insert(int index, T item) {
+ // Note that insertions at the end are legal.
+ if ((uint) index > (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
+ }
+ Contract.EndContractBlock();
+ if (_size == _items.Length) EnsureCapacity(_size + 1);
+ if (index < _size) {
+ Array.Copy(_items, index, _items, index + 1, _size - index);
+ }
+ _items[index] = item;
+ _size++;
+ _version++;
+ }
+
+ void System.Collections.IList.Insert(int index, Object item)
+ {
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
+
+ try {
+ Insert(index, (T) item);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T));
+ }
+ }
+
+ // Inserts the elements of the given collection at a given index. If
+ // required, the capacity of the list is increased to twice the previous
+ // capacity or the new size, whichever is larger. Ranges may be added
+ // to the end of the list by setting index to the List's size.
+ //
+ public void InsertRange(int index, IEnumerable<T> collection) {
+ if (collection==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+ }
+
+ if ((uint)index > (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
+ }
+ Contract.EndContractBlock();
+
+ ICollection<T> c = collection as ICollection<T>;
+ if( c != null ) { // if collection is ICollection<T>
+ int count = c.Count;
+ if (count > 0) {
+ EnsureCapacity(_size + count);
+ if (index < _size) {
+ Array.Copy(_items, index, _items, index + count, _size - index);
+ }
+
+ // If we're inserting a List into itself, we want to be able to deal with that.
+ if (this == c) {
+ // Copy first part of _items to insert location
+ Array.Copy(_items, 0, _items, index, index);
+ // Copy last part of _items back to inserted location
+ Array.Copy(_items, index+count, _items, index*2, _size-index);
+ }
+ else {
+ T[] itemsToInsert = new T[count];
+ c.CopyTo(itemsToInsert, 0);
+ itemsToInsert.CopyTo(_items, index);
+ }
+ _size += count;
+ }
+ }
+ else {
+ using(IEnumerator<T> en = collection.GetEnumerator()) {
+ while(en.MoveNext()) {
+ Insert(index++, en.Current);
+ }
+ }
+ }
+ _version++;
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at the end
+ // and ending at the first element in the list. The elements of the list
+ // are compared to the given value using the Object.Equals method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public int LastIndexOf(T item)
+ {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < Count);
+ if (_size == 0) { // Special case for empty list
+ return -1;
+ }
+ else {
+ return LastIndexOf(item, _size - 1, _size);
+ }
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at index
+ // index and ending at the first element in the list. The
+ // elements of the list are compared to the given value using the
+ // Object.Equals method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public int LastIndexOf(T item, int index)
+ {
+ if (index >= _size)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_Index);
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(((Count == 0) && (Contract.Result<int>() == -1)) || ((Count > 0) && (Contract.Result<int>() <= index)));
+ Contract.EndContractBlock();
+ return LastIndexOf(item, index, index + 1);
+ }
+
+ // Returns the index of the last occurrence of a given value in a range of
+ // this list. The list is searched backwards, starting at index
+ // index and upto count elements. The elements of
+ // the list are compared to the given value using the Object.Equals
+ // method.
+ //
+ // This method uses the Array.LastIndexOf method to perform the
+ // search.
+ //
+ public int LastIndexOf(T item, int index, int count) {
+ if ((Count != 0) && (index < 0)) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if ((Count !=0) && (count < 0)) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(((Count == 0) && (Contract.Result<int>() == -1)) || ((Count > 0) && (Contract.Result<int>() <= index)));
+ Contract.EndContractBlock();
+
+ if (_size == 0) { // Special case for empty list
+ return -1;
+ }
+
+ if (index >= _size) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection);
+ }
+
+ if (count > index + 1) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_BiggerThanCollection);
+ }
+
+ return Array.LastIndexOf(_items, item, index, count);
+ }
+
+ // Removes the element at the given index. The size of the list is
+ // decreased by one.
+ //
+ public bool Remove(T item) {
+ int index = IndexOf(item);
+ if (index >= 0) {
+ RemoveAt(index);
+ return true;
+ }
+
+ return false;
+ }
+
+ void System.Collections.IList.Remove(Object item)
+ {
+ if(IsCompatibleObject(item)) {
+ Remove((T) item);
+ }
+ }
+
+ // This method removes all items which matches the predicate.
+ // The complexity is O(n).
+ public int RemoveAll(Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= Contract.OldValue(Count));
+ Contract.EndContractBlock();
+
+ int freeIndex = 0; // the first free slot in items array
+
+ // Find the first item which needs to be removed.
+ while( freeIndex < _size && !match(_items[freeIndex])) freeIndex++;
+ if( freeIndex >= _size) return 0;
+
+ int current = freeIndex + 1;
+ while( current < _size) {
+ // Find the first item which needs to be kept.
+ while( current < _size && match(_items[current])) current++;
+
+ if( current < _size) {
+ // copy item to the free slot.
+ _items[freeIndex++] = _items[current++];
+ }
+ }
+
+ Array.Clear(_items, freeIndex, _size - freeIndex);
+ int result = _size - freeIndex;
+ _size = freeIndex;
+ _version++;
+ return result;
+ }
+
+ // Removes the element at the given index. The size of the list is
+ // decreased by one.
+ //
+ public void RemoveAt(int index) {
+ if ((uint)index >= (uint)_size) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+ Contract.EndContractBlock();
+ _size--;
+ if (index < _size) {
+ Array.Copy(_items, index + 1, _items, index, _size - index);
+ }
+ _items[_size] = default(T);
+ _version++;
+ }
+
+ // Removes a range of elements from this list.
+ //
+ public void RemoveRange(int index, int count) {
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (count < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (_size - index < count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ if (count > 0) {
+ int i = _size;
+ _size -= count;
+ if (index < _size) {
+ Array.Copy(_items, index + count, _items, index, _size - index);
+ }
+ Array.Clear(_items, _size, count);
+ _version++;
+ }
+ }
+
+ // Reverses the elements in this list.
+ public void Reverse() {
+ Reverse(0, Count);
+ }
+
+ // Reverses the elements in a range of this list. Following a call to this
+ // method, an element in the range given by index and count
+ // which was previously located at index i will now be located at
+ // index index + (index + count - i - 1).
+ //
+ public void Reverse(int index, int count) {
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (count < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (_size - index < count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ // The non-generic Array.Reverse is not used because it does not perform
+ // well for non-primitive value types.
+ // If/when a generic Array.Reverse<T> becomes available, the below code
+ // can be deleted and replaced with a call to Array.Reverse<T>.
+ int i = index;
+ int j = index + count - 1;
+ T[] array = _items;
+ while (i < j)
+ {
+ T temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ i++;
+ j--;
+ }
+
+ _version++;
+ }
+
+ // Sorts the elements in this list. Uses the default comparer and
+ // Array.Sort.
+ public void Sort()
+ {
+ Sort(0, Count, null);
+ }
+
+ // Sorts the elements in this list. Uses Array.Sort with the
+ // provided comparer.
+ public void Sort(IComparer<T> comparer)
+ {
+ Sort(0, Count, comparer);
+ }
+
+ // Sorts the elements in a section of this list. The sort compares the
+ // elements to each other using the given IComparer interface. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented by all
+ // elements of the list.
+ //
+ // This method uses the Array.Sort method to sort the elements.
+ //
+ public void Sort(int index, int count, IComparer<T> comparer) {
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (count < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (_size - index < count)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+ Contract.EndContractBlock();
+
+ Array.Sort<T>(_items, index, count, comparer);
+ _version++;
+ }
+
+ public void Sort(Comparison<T> comparison) {
+ if( comparison == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.comparison);
+ }
+ Contract.EndContractBlock();
+
+ if( _size > 0) {
+ IComparer<T> comparer = Comparer<T>.Create(comparison);
+ Array.Sort(_items, 0, _size, comparer);
+ }
+ }
+
+ // ToArray returns an array containing the contents of the List.
+ // This requires copying the List, which is an O(n) operation.
+ public T[] ToArray() {
+ Contract.Ensures(Contract.Result<T[]>() != null);
+ Contract.Ensures(Contract.Result<T[]>().Length == Count);
+
+#if FEATURE_CORECLR
+ if (_size == 0)
+ {
+ return _emptyArray;
+ }
+#endif
+
+ T[] array = new T[_size];
+ Array.Copy(_items, 0, array, 0, _size);
+ return array;
+ }
+
+ // Sets the capacity of this list to the size of the list. This method can
+ // be used to minimize a list's memory overhead once it is known that no
+ // new elements will be added to the list. To completely clear a list and
+ // release all memory referenced by the list, execute the following
+ // statements:
+ //
+ // list.Clear();
+ // list.TrimExcess();
+ //
+ public void TrimExcess() {
+ int threshold = (int)(((double)_items.Length) * 0.9);
+ if( _size < threshold ) {
+ Capacity = _size;
+ }
+ }
+
+ public bool TrueForAll(Predicate<T> match) {
+ if( match == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0 ; i < _size; i++) {
+ if( !match(_items[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [Serializable]
+ public struct Enumerator : IEnumerator<T>, System.Collections.IEnumerator
+ {
+ private List<T> list;
+ private int index;
+ private int version;
+ private T current;
+
+ internal Enumerator(List<T> list) {
+ this.list = list;
+ index = 0;
+ version = list._version;
+ current = default(T);
+ }
+
+ public void Dispose() {
+ }
+
+ public bool MoveNext() {
+
+ List<T> localList = list;
+
+ if (version == localList._version && ((uint)index < (uint)localList._size))
+ {
+ current = localList._items[index];
+ index++;
+ return true;
+ }
+ return MoveNextRare();
+ }
+
+ private bool MoveNextRare()
+ {
+ if (version != list._version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ index = list._size + 1;
+ current = default(T);
+ return false;
+ }
+
+ public T Current {
+ get {
+ return current;
+ }
+ }
+
+ Object System.Collections.IEnumerator.Current {
+ get {
+ if( index == 0 || index == list._size + 1) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
+ }
+ return Current;
+ }
+ }
+
+ void System.Collections.IEnumerator.Reset() {
+ if (version != list._version) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+
+ index = 0;
+ current = default(T);
+ }
+
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Collections/Hashtable.cs b/src/mscorlib/src/System/Collections/Hashtable.cs
new file mode 100644
index 0000000000..262ccedea6
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Hashtable.cs
@@ -0,0 +1,1847 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Hash table implementation
+**
+**
+===========================================================*/
+
+namespace System.Collections {
+ using System;
+ using System.Runtime;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_CORECLR
+ using System.Security.Cryptography;
+#endif
+
+ // The Hashtable class represents a dictionary of associated keys and values
+ // with constant lookup time.
+ //
+ // Objects used as keys in a hashtable must implement the GetHashCode
+ // and Equals methods (or they can rely on the default implementations
+ // inherited from Object if key equality is simply reference
+ // equality). Furthermore, the GetHashCode and Equals methods of
+ // a key object must produce the same results given the same parameters for the
+ // entire time the key is present in the hashtable. In practical terms, this
+ // means that key objects should be immutable, at least for the time they are
+ // used as keys in a hashtable.
+ //
+ // When entries are added to a hashtable, they are placed into
+ // buckets based on the hashcode of their keys. Subsequent lookups of
+ // keys will use the hashcode of the keys to only search a particular bucket,
+ // thus substantially reducing the number of key comparisons required to find
+ // an entry. A hashtable's maximum load factor, which can be specified
+ // when the hashtable is instantiated, determines the maximum ratio of
+ // hashtable entries to hashtable buckets. Smaller load factors cause faster
+ // average lookup times at the cost of increased memory consumption. The
+ // default maximum load factor of 1.0 generally provides the best balance
+ // between speed and size. As entries are added to a hashtable, the hashtable's
+ // actual load factor increases, and when the actual load factor reaches the
+ // maximum load factor value, the number of buckets in the hashtable is
+ // automatically increased by approximately a factor of two (to be precise, the
+ // number of hashtable buckets is increased to the smallest prime number that
+ // is larger than twice the current number of hashtable buckets).
+ //
+ // Each object provides their own hash function, accessed by calling
+ // GetHashCode(). However, one can write their own object
+ // implementing IEqualityComparer and pass it to a constructor on
+ // the Hashtable. That hash function (and the equals method on the
+ // IEqualityComparer) would be used for all objects in the table.
+ //
+ // Changes since V1 during Whidbey:
+ // *) Deprecated IHashCodeProvider, use IEqualityComparer instead. This will
+ // allow better performance for objects where equality checking can be
+ // done much faster than establishing an ordering between two objects,
+ // such as an ordinal string equality check.
+ //
+ [DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable {
+ /*
+ Implementation Notes:
+ The generic Dictionary was copied from Hashtable's source - any bug
+ fixes here probably need to be made to the generic Dictionary as well.
+
+ This Hashtable uses double hashing. There are hashsize buckets in the
+ table, and each bucket can contain 0 or 1 element. We a bit to mark
+ whether there's been a collision when we inserted multiple elements
+ (ie, an inserted item was hashed at least a second time and we probed
+ this bucket, but it was already in use). Using the collision bit, we
+ can terminate lookups & removes for elements that aren't in the hash
+ table more quickly. We steal the most significant bit from the hash code
+ to store the collision bit.
+
+ Our hash function is of the following form:
+
+ h(key, n) = h1(key) + n*h2(key)
+
+ where n is the number of times we've hit a collided bucket and rehashed
+ (on this particular lookup). Here are our hash functions:
+
+ h1(key) = GetHash(key); // default implementation calls key.GetHashCode();
+ h2(key) = 1 + (((h1(key) >> 5) + 1) % (hashsize - 1));
+
+ The h1 can return any number. h2 must return a number between 1 and
+ hashsize - 1 that is relatively prime to hashsize (not a problem if
+ hashsize is prime). (Knuth's Art of Computer Programming, Vol. 3, p. 528-9)
+ If this is true, then we are guaranteed to visit every bucket in exactly
+ hashsize probes, since the least common multiple of hashsize and h2(key)
+ will be hashsize * h2(key). (This is the first number where adding h2 to
+ h1 mod hashsize will be 0 and we will search the same bucket twice).
+
+ We previously used a different h2(key, n) that was not constant. That is a
+ horrifically bad idea, unless you can prove that series will never produce
+ any identical numbers that overlap when you mod them by hashsize, for all
+ subranges from i to i+hashsize, for all i. It's not worth investigating,
+ since there was no clear benefit from using that hash function, and it was
+ broken.
+
+ For efficiency reasons, we've implemented this by storing h1 and h2 in a
+ temporary, and setting a variable called seed equal to h1. We do a probe,
+ and if we collided, we simply add h2 to seed each time through the loop.
+
+ A good test for h2() is to subclass Hashtable, provide your own implementation
+ of GetHash() that returns a constant, then add many items to the hash table.
+ Make sure Count equals the number of items you inserted.
+
+ Note that when we remove an item from the hash table, we set the key
+ equal to buckets, if there was a collision in this bucket. Otherwise
+ we'd either wipe out the collision bit, or we'd still have an item in
+ the hash table.
+
+ --
+ */
+
+ internal const Int32 HashPrime = 101;
+ private const Int32 InitialSize = 3;
+ private const String LoadFactorName = "LoadFactor";
+ private const String VersionName = "Version";
+ private const String ComparerName = "Comparer";
+ private const String HashCodeProviderName = "HashCodeProvider";
+ private const String HashSizeName = "HashSize"; // Must save buckets.Length
+ private const String KeysName = "Keys";
+ private const String ValuesName = "Values";
+ private const String KeyComparerName = "KeyComparer";
+
+ // Deleted entries have their key set to buckets
+
+ // The hash table data.
+ // This cannot be serialised
+ private struct bucket {
+ public Object key;
+ public Object val;
+ public int hash_coll; // Store hash code; sign bit means there was a collision.
+ }
+
+ private bucket[] buckets;
+
+ // The total number of entries in the hash table.
+ private int count;
+
+ // The total number of collision bits set in the hashtable
+ private int occupancy;
+
+ private int loadsize;
+ private float loadFactor;
+
+ private volatile int version;
+ private volatile bool isWriterInProgress;
+
+ private ICollection keys;
+ private ICollection values;
+
+ private IEqualityComparer _keycomparer;
+ private Object _syncRoot;
+
+ [Obsolete("Please use EqualityComparer property.")]
+ protected IHashCodeProvider hcp
+ {
+ get
+ {
+ if( _keycomparer is CompatibleComparer) {
+ return ((CompatibleComparer)_keycomparer).HashCodeProvider;
+ }
+ else if( _keycomparer == null) {
+ return null;
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer) {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(keyComparer.Comparer, value);
+ }
+ else if( _keycomparer == null) {
+ _keycomparer = new CompatibleComparer((IComparer)null, value);
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
+ }
+ }
+ }
+
+
+ [Obsolete("Please use KeyComparer properties.")]
+ protected IComparer comparer
+ {
+ get
+ {
+ if( _keycomparer is CompatibleComparer) {
+ return ((CompatibleComparer)_keycomparer).Comparer;
+ }
+ else if( _keycomparer == null) {
+ return null;
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
+ }
+ }
+ set
+ {
+ if (_keycomparer is CompatibleComparer) {
+ CompatibleComparer keyComparer = (CompatibleComparer)_keycomparer;
+ _keycomparer = new CompatibleComparer(value, keyComparer.HashCodeProvider);
+ }
+ else if( _keycomparer == null) {
+ _keycomparer = new CompatibleComparer(value, (IHashCodeProvider)null);
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Arg_CannotMixComparisonInfrastructure"));
+ }
+ }
+ }
+
+ protected IEqualityComparer EqualityComparer
+ {
+ get
+ {
+ return _keycomparer;
+ }
+ }
+
+ // Note: this constructor is a bogus constructor that does nothing
+ // and is for use only with SyncHashtable.
+ internal Hashtable( bool trash )
+ {
+ }
+
+ // Constructs a new hashtable. The hashtable is created with an initial
+ // capacity of zero and a load factor of 1.0.
+ public Hashtable() : this(0, 1.0f) {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and a load
+ // factor of 1.0. The capacity argument serves as an indication of
+ // the number of entries the hashtable will contain. When this number (or
+ // an approximation) is known, specifying it in the constructor can
+ // eliminate a number of resizing operations that would otherwise be
+ // performed when elements are added to the hashtable.
+ //
+ public Hashtable(int capacity) : this(capacity, 1.0f) {
+ }
+
+ // Constructs a new hashtable with the given initial capacity and load
+ // factor. The capacity argument serves as an indication of the
+ // number of entries the hashtable will contain. When this number (or an
+ // approximation) is known, specifying it in the constructor can eliminate
+ // a number of resizing operations that would otherwise be performed when
+ // elements are added to the hashtable. The loadFactor argument
+ // indicates the maximum ratio of hashtable entries to hashtable buckets.
+ // Smaller load factors cause faster average lookup times at the cost of
+ // increased memory consumption. A load factor of 1.0 generally provides
+ // the best balance between speed and size.
+ //
+ public Hashtable(int capacity, float loadFactor) {
+ if (capacity < 0)
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (!(loadFactor >= 0.1f && loadFactor <= 1.0f))
+ throw new ArgumentOutOfRangeException("loadFactor", Environment.GetResourceString("ArgumentOutOfRange_HashtableLoadFactor", .1, 1.0));
+ Contract.EndContractBlock();
+
+ // Based on perf work, .72 is the optimal load factor for this table.
+ this.loadFactor = 0.72f * loadFactor;
+
+ double rawsize = capacity / this.loadFactor;
+ if (rawsize > Int32.MaxValue)
+ throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
+
+ // Avoid awfully small sizes
+ int hashsize = (rawsize > InitialSize) ? HashHelpers.GetPrime((int)rawsize) : InitialSize;
+ buckets = new bucket[hashsize];
+
+ loadsize = (int)(this.loadFactor * hashsize);
+ isWriterInProgress = false;
+ // Based on the current algorithm, loadsize must be less than hashsize.
+ Contract.Assert( loadsize < hashsize, "Invalid hashtable loadsize!");
+ }
+
+ // Constructs a new hashtable with the given initial capacity and load
+ // factor. The capacity argument serves as an indication of the
+ // number of entries the hashtable will contain. When this number (or an
+ // approximation) is known, specifying it in the constructor can eliminate
+ // a number of resizing operations that would otherwise be performed when
+ // elements are added to the hashtable. The loadFactor argument
+ // indicates the maximum ratio of hashtable entries to hashtable buckets.
+ // Smaller load factors cause faster average lookup times at the cost of
+ // increased memory consumption. A load factor of 1.0 generally provides
+ // the best balance between speed and size. The hcp argument
+ // is used to specify an Object that will provide hash codes for all
+ // the Objects in the table. Using this, you can in effect override
+ // GetHashCode() on each Object using your own hash function. The
+ // comparer argument will let you specify a custom function for
+ // comparing keys. By specifying user-defined objects for hcp
+ // and comparer, users could make a hash table using strings
+ // as keys do case-insensitive lookups.
+ //
+ [Obsolete("Please use Hashtable(int, float, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, float loadFactor, IHashCodeProvider hcp, IComparer comparer) : this(capacity, loadFactor) {
+ if (hcp == null && comparer == null) {
+ this._keycomparer = null;
+ }
+ else {
+ this._keycomparer = new CompatibleComparer(comparer,hcp);
+ }
+ }
+
+ public Hashtable(int capacity, float loadFactor, IEqualityComparer equalityComparer) : this(capacity, loadFactor) {
+ this._keycomparer = equalityComparer;
+ }
+
+ // Constructs a new hashtable using a custom hash function
+ // and a custom comparison function for keys. This will enable scenarios
+ // such as doing lookups with case-insensitive strings.
+ //
+ [Obsolete("Please use Hashtable(IEqualityComparer) instead.")]
+ public Hashtable(IHashCodeProvider hcp, IComparer comparer) : this(0, 1.0f, hcp, comparer) {
+ }
+
+ public Hashtable(IEqualityComparer equalityComparer) : this(0, 1.0f, equalityComparer) {
+ }
+
+ // Constructs a new hashtable using a custom hash function
+ // and a custom comparison function for keys. This will enable scenarios
+ // such as doing lookups with case-insensitive strings.
+ //
+ [Obsolete("Please use Hashtable(int, IEqualityComparer) instead.")]
+ public Hashtable(int capacity, IHashCodeProvider hcp, IComparer comparer)
+ : this(capacity, 1.0f, hcp, comparer) {
+ }
+
+ public Hashtable(int capacity, IEqualityComparer equalityComparer)
+ : this(capacity, 1.0f, equalityComparer) {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with a load factor of 1.0.
+ //
+ public Hashtable(IDictionary d) : this(d, 1.0f) {
+ }
+
+ // Constructs a new hashtable containing a copy of the entries in the given
+ // dictionary. The hashtable is created with the given load factor.
+ //
+ public Hashtable(IDictionary d, float loadFactor)
+ : this(d, loadFactor, (IEqualityComparer)null) {
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, IHashCodeProvider hcp, IComparer comparer)
+ : this(d, 1.0f, hcp, comparer) {
+ }
+
+ public Hashtable(IDictionary d, IEqualityComparer equalityComparer)
+ : this(d, 1.0f, equalityComparer) {
+ }
+
+ [Obsolete("Please use Hashtable(IDictionary, float, IEqualityComparer) instead.")]
+ public Hashtable(IDictionary d, float loadFactor, IHashCodeProvider hcp, IComparer comparer)
+ : this((d != null ? d.Count : 0), loadFactor, hcp, comparer) {
+ if (d==null)
+ throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
+ Contract.EndContractBlock();
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext()) Add(e.Key, e.Value);
+ }
+
+ public Hashtable(IDictionary d, float loadFactor, IEqualityComparer equalityComparer)
+ : this((d != null ? d.Count : 0), loadFactor, equalityComparer) {
+ if (d==null)
+ throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
+ Contract.EndContractBlock();
+
+ IDictionaryEnumerator e = d.GetEnumerator();
+ while (e.MoveNext()) Add(e.Key, e.Value);
+ }
+
+ protected Hashtable(SerializationInfo info, StreamingContext context) {
+ //We can't do anything with the keys and values until the entire graph has been deserialized
+ //and we have a reasonable estimate that GetHashCode is not going to fail. For the time being,
+ //we'll just cache this. The graph is not valid until OnDeserialization has been called.
+ HashHelpers.SerializationInfoTable.Add(this, info);
+ }
+
+ // ‘InitHash’ is basically an implementation of classic DoubleHashing (see http://en.wikipedia.org/wiki/Double_hashing)
+ //
+ // 1) The only ‘correctness’ requirement is that the ‘increment’ used to probe
+ // a. Be non-zero
+ // b. Be relatively prime to the table size ‘hashSize’. (This is needed to insure you probe all entries in the table before you ‘wrap’ and visit entries already probed)
+ // 2) Because we choose table sizes to be primes, we just need to insure that the increment is 0 < incr < hashSize
+ //
+ // Thus this function would work: Incr = 1 + (seed % (hashSize-1))
+ //
+ // While this works well for ‘uniformly distributed’ keys, in practice, non-uniformity is common.
+ // In particular in practice we can see ‘mostly sequential’ where you get long clusters of keys that ‘pack’.
+ // To avoid bad behavior you want it to be the case that the increment is ‘large’ even for ‘small’ values (because small
+ // values tend to happen more in practice). Thus we multiply ‘seed’ by a number that will make these small values
+ // bigger (and not hurt large values). We picked HashPrime (101) because it was prime, and if ‘hashSize-1’ is not a multiple of HashPrime
+ // (enforced in GetPrime), then incr has the potential of being every value from 1 to hashSize-1. The choice was largely arbitrary.
+ //
+ // Computes the hash function: H(key, i) = h1(key) + i*h2(key, hashSize).
+ // The out parameter seed is h1(key), while the out parameter
+ // incr is h2(key, hashSize). Callers of this function should
+ // add incr each time through a loop.
+ private uint InitHash(Object key, int hashsize, out uint seed, out uint incr) {
+ // Hashcode must be positive. Also, we must not use the sign bit, since
+ // that is used for the collision bit.
+ uint hashcode = (uint) GetHash(key) & 0x7FFFFFFF;
+ seed = (uint) hashcode;
+ // Restriction: incr MUST be between 1 and hashsize - 1, inclusive for
+ // the modular arithmetic to work correctly. This guarantees you'll
+ // visit every bucket in the table exactly once within hashsize
+ // iterations. Violate this and it'll cause obscure bugs forever.
+ // If you change this calculation for h2(key), update putEntry too!
+ incr = (uint)(1 + ((seed * HashPrime) % ((uint)hashsize - 1)));
+ return hashcode;
+ }
+
+ // Adds an entry with the given key and value to this hashtable. An
+ // ArgumentException is thrown if the key is null or if the key is already
+ // present in the hashtable.
+ //
+ public virtual void Add(Object key, Object value) {
+ Insert(key, value, true);
+ }
+
+ // Removes all entries from this hashtable.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public virtual void Clear() {
+ Contract.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ if (count == 0 && occupancy == 0)
+ return;
+
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ for (int i = 0; i < buckets.Length; i++){
+ buckets[i].hash_coll = 0;
+ buckets[i].key = null;
+ buckets[i].val = null;
+ }
+
+ count = 0;
+ occupancy = 0;
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ }
+
+ // Clone returns a virtually identical copy of this hash table. This does
+ // a shallow copy - the Objects in the table aren't cloned, only the references
+ // to those Objects.
+ public virtual Object Clone()
+ {
+ bucket[] lbuckets = buckets;
+ Hashtable ht = new Hashtable(count,_keycomparer);
+ ht.version = version;
+ ht.loadFactor = loadFactor;
+ ht.count = 0;
+
+ int bucket = lbuckets.Length;
+ while (bucket > 0) {
+ bucket--;
+ Object keyv = lbuckets[bucket].key;
+ if ((keyv!= null) && (keyv != lbuckets)) {
+ ht[keyv] = lbuckets[bucket].val;
+ }
+ }
+
+ return ht;
+ }
+
+ // Checks if this hashtable contains the given key.
+ public virtual bool Contains(Object key) {
+ return ContainsKey(key);
+ }
+
+ // Checks if this hashtable contains an entry with the given key. This is
+ // an O(1) operation.
+ //
+ public virtual bool ContainsKey(Object key) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+
+ uint seed;
+ uint incr;
+ // Take a snapshot of buckets, in case another thread resizes table
+ bucket[] lbuckets = buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int) (seed % (uint)lbuckets.Length);
+ do {
+ b = lbuckets[bucketNumber];
+ if (b.key == null) {
+ return false;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals (b.key, key))
+ return true;
+ bucketNumber = (int) (((long)bucketNumber + incr)% (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return false;
+ }
+
+
+
+ // Checks if this hashtable contains an entry with the given value. The
+ // values of the entries of the hashtable are compared to the given value
+ // using the Object.Equals method. This method performs a linear
+ // search and is thus be substantially slower than the ContainsKey
+ // method.
+ //
+ public virtual bool ContainsValue(Object value) {
+
+ if (value == null) {
+ for (int i = buckets.Length; --i >= 0;) {
+ if (buckets[i].key != null && buckets[i].key != buckets && buckets[i].val == null)
+ return true;
+ }
+ }
+ else {
+ for (int i = buckets.Length; --i >= 0;) {
+ Object val = buckets[i].val;
+ if (val!=null && val.Equals(value)) return true;
+ }
+ }
+ return false;
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyKeys(Array array, int arrayIndex) {
+ Contract.Requires(array != null);
+ Contract.Requires(array.Rank == 1);
+
+ bucket[] lbuckets = buckets;
+ for (int i = lbuckets.Length; --i >= 0;) {
+ Object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != buckets)){
+ array.SetValue(keyv, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the keys of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the KeyCollection class.
+ private void CopyEntries(Array array, int arrayIndex) {
+ Contract.Requires(array != null);
+ Contract.Requires(array.Rank == 1);
+
+ bucket[] lbuckets = buckets;
+ for (int i = lbuckets.Length; --i >= 0;) {
+ Object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != buckets)){
+ DictionaryEntry entry = new DictionaryEntry(keyv,lbuckets[i].val);
+ array.SetValue(entry, arrayIndex++);
+ }
+ }
+ }
+
+ // Copies the values in this hash table to an array at
+ // a given index. Note that this only copies values, and not keys.
+ public virtual void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array"));
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - arrayIndex < Count)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ Contract.EndContractBlock();
+ CopyEntries(array, arrayIndex);
+ }
+
+ // Copies the values in this Hashtable to an KeyValuePairs array.
+ // KeyValuePairs is different from Dictionary Entry in that it has special
+ // debugger attributes on its fields.
+
+ internal virtual KeyValuePairs[] ToKeyValuePairsArray() {
+
+ KeyValuePairs[] array = new KeyValuePairs[count];
+ int index = 0;
+ bucket[] lbuckets = buckets;
+ for (int i = lbuckets.Length; --i >= 0;) {
+ Object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != buckets)){
+ array[index++] = new KeyValuePairs(keyv,lbuckets[i].val);
+ }
+ }
+
+ return array;
+ }
+
+
+ // Copies the values of this hashtable to a given array starting at a given
+ // index. This method is used by the implementation of the CopyTo method in
+ // the ValueCollection class.
+ private void CopyValues(Array array, int arrayIndex) {
+ Contract.Requires(array != null);
+ Contract.Requires(array.Rank == 1);
+
+ bucket[] lbuckets = buckets;
+ for (int i = lbuckets.Length; --i >= 0;) {
+ Object keyv = lbuckets[i].key;
+ if ((keyv != null) && (keyv != buckets)){
+ array.SetValue(lbuckets[i].val, arrayIndex++);
+ }
+ }
+ }
+
+ // Returns the value associated with the given key. If an entry with the
+ // given key is not found, the returned value is null.
+ //
+ public virtual Object this[Object key] {
+ get {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+
+ uint seed;
+ uint incr;
+
+
+ // Take a snapshot of buckets, in case another thread does a resize
+ bucket[] lbuckets = buckets;
+ uint hashcode = InitHash(key, lbuckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bucketNumber = (int) (seed % (uint)lbuckets.Length);
+ do
+ {
+ int currentversion;
+
+ // A read operation on hashtable has three steps:
+ // (1) calculate the hash and find the slot number.
+ // (2) compare the hashcode, if equal, go to step 3. Otherwise end.
+ // (3) compare the key, if equal, go to step 4. Otherwise end.
+ // (4) return the value contained in the bucket.
+ // After step 3 and before step 4. A writer can kick in a remove the old item and add a new one
+ // in the same bukcet. So in the reader we need to check if the hash table is modified during above steps.
+ //
+ // Writers (Insert, Remove, Clear) will set 'isWriterInProgress' flag before it starts modifying
+ // the hashtable and will ckear the flag when it is done. When the flag is cleared, the 'version'
+ // will be increased. We will repeat the reading if a writer is in progress or done with the modification
+ // during the read.
+ //
+ // Our memory model guarantee if we pick up the change in bucket from another processor,
+ // we will see the 'isWriterProgress' flag to be true or 'version' is changed in the reader.
+ //
+ int spinCount = 0;
+ do {
+ // this is violate read, following memory accesses can not be moved ahead of it.
+ currentversion = version;
+ b = lbuckets[bucketNumber];
+
+ // The contention between reader and writer shouldn't happen frequently.
+ // But just in case this will burn CPU, yield the control of CPU if we spinned a few times.
+ // 8 is just a random number I pick.
+ if( (++spinCount) % 8 == 0 ) {
+ Thread.Sleep(1); // 1 means we are yeilding control to all threads, including low-priority ones.
+ }
+ } while ( isWriterInProgress || (currentversion != version) );
+
+ if (b.key == null) {
+ return null;
+ }
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals (b.key, key))
+ return b.val;
+ bucketNumber = (int) (((long)bucketNumber + incr)% (uint)lbuckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < lbuckets.Length);
+ return null;
+ }
+
+ set {
+ Insert(key, value, false);
+ }
+ }
+
+ // Increases the bucket count of this hashtable. This method is called from
+ // the Insert method when the actual load factor of the hashtable reaches
+ // the upper limit specified when the hashtable was constructed. The number
+ // of buckets in the hashtable is increased to the smallest prime number
+ // that is larger than twice the current number of buckets, and the entries
+ // in the hashtable are redistributed into the new buckets using the cached
+ // hashcodes.
+ private void expand() {
+ int rawsize = HashHelpers.ExpandPrime(buckets.Length);
+ rehash(rawsize, false);
+ }
+
+ // We occationally need to rehash the table to clean up the collision bits.
+ private void rehash() {
+ rehash( buckets.Length, false );
+ }
+
+ private void UpdateVersion() {
+ // Version might become negative when version is Int32.MaxValue, but the oddity will be still be correct.
+ // So we don't need to special case this.
+ version++;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private void rehash( int newsize, bool forceNewHashCode ) {
+
+ // reset occupancy
+ occupancy=0;
+
+ // Don't replace any internal state until we've finished adding to the
+ // new bucket[]. This serves two purposes:
+ // 1) Allow concurrent readers to see valid hashtable contents
+ // at all times
+ // 2) Protect against an OutOfMemoryException while allocating this
+ // new bucket[].
+ bucket[] newBuckets = new bucket[newsize];
+
+ // rehash table into new buckets
+ int nb;
+ for (nb = 0; nb < buckets.Length; nb++){
+ bucket oldb = buckets[nb];
+ if ((oldb.key != null) && (oldb.key != buckets)) {
+ int hashcode = ((forceNewHashCode ? GetHash(oldb.key) : oldb.hash_coll) & 0x7FFFFFFF);
+ putEntry(newBuckets, oldb.key, oldb.val, hashcode);
+ }
+ }
+
+ // New bucket[] is good to go - replace buckets and other internal state.
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ buckets = newBuckets;
+ loadsize = (int)(loadFactor * newsize);
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ // minimun size of hashtable is 3 now and maximum loadFactor is 0.72 now.
+ Contract.Assert(loadsize < newsize, "Our current implementaion means this is not possible.");
+ return;
+ }
+
+ // Returns an enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Returns a dictionary enumerator for this hashtable.
+ // If modifications made to the hashtable while an enumeration is
+ // in progress, the MoveNext and Current methods of the
+ // enumerator will throw an exception.
+ //
+ public virtual IDictionaryEnumerator GetEnumerator() {
+ return new HashtableEnumerator(this, HashtableEnumerator.DictEntry);
+ }
+
+ // Internal method to get the hash code for an Object. This will call
+ // GetHashCode() on each object if you haven't provided an IHashCodeProvider
+ // instance. Otherwise, it calls hcp.GetHashCode(obj).
+ protected virtual int GetHash(Object key)
+ {
+ if (_keycomparer != null)
+ return _keycomparer.GetHashCode(key);
+ return key.GetHashCode();
+ }
+
+ // Is this Hashtable read-only?
+ public virtual bool IsReadOnly {
+ get { return false; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return false; }
+ }
+
+ // Is this Hashtable synchronized? See SyncRoot property
+ public virtual bool IsSynchronized {
+ get { return false; }
+ }
+
+ // Internal method to compare two keys. If you have provided an IComparer
+ // instance in the constructor, this method will call comparer.Compare(item, key).
+ // Otherwise, it will call item.Equals(key).
+ //
+ protected virtual bool KeyEquals(Object item, Object key)
+ {
+ Contract.Assert(key != null, "key can't be null here!");
+ if( Object.ReferenceEquals(buckets, item)) {
+ return false;
+ }
+
+ if (Object.ReferenceEquals(item,key))
+ return true;
+
+ if (_keycomparer != null)
+ return _keycomparer.Equals(item, key);
+ return item == null ? false : item.Equals(key);
+ }
+
+ // Returns a collection representing the keys of this hashtable. The order
+ // in which the returned collection represents the keys is unspecified, but
+ // it is guaranteed to be buckets = newBuckets; the same order in which a collection returned by
+ // GetValues represents the values of the hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Keys {
+ get {
+ if (keys == null) keys = new KeyCollection(this);
+ return keys;
+ }
+ }
+
+ // Returns a collection representing the values of this hashtable. The
+ // order in which the returned collection represents the values is
+ // unspecified, but it is guaranteed to be the same order in which a
+ // collection returned by GetKeys represents the keys of the
+ // hashtable.
+ //
+ // The returned collection is live in the sense that any changes
+ // to the hash table are reflected in this collection. It is not
+ // a static copy of all the keys in the hash table.
+ //
+ public virtual ICollection Values {
+ get {
+ if (values == null) values = new ValueCollection(this);
+ return values;
+ }
+ }
+
+ // Inserts an entry into this hashtable. This method is called from the Set
+ // and Add methods. If the add parameter is true and the given key already
+ // exists in the hashtable, an exception is thrown.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private void Insert (Object key, Object nvalue, bool add) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ if (count >= loadsize) {
+ expand();
+ }
+ else if(occupancy > loadsize && count > 100) {
+ rehash();
+ }
+
+ uint seed;
+ uint incr;
+ // Assume we only have one thread writing concurrently. Modify
+ // buckets to contain new data, as long as we insert in the right order.
+ uint hashcode = InitHash(key, buckets.Length, out seed, out incr);
+ int ntry = 0;
+ int emptySlotNumber = -1; // We use the empty slot number to cache the first empty slot. We chose to reuse slots
+ // create by remove that have the collision bit set over using up new slots.
+ int bucketNumber = (int) (seed % (uint)buckets.Length);
+ do {
+
+ // Set emptySlot number to current bucket if it is the first available bucket that we have seen
+ // that once contained an entry and also has had a collision.
+ // We need to search this entire collision chain because we have to ensure that there are no
+ // duplicate entries in the table.
+ if (emptySlotNumber == -1 && (buckets[bucketNumber].key == buckets) && (buckets[bucketNumber].hash_coll < 0))//(((buckets[bucketNumber].hash_coll & unchecked(0x80000000))!=0)))
+ emptySlotNumber = bucketNumber;
+
+ // Insert the key/value pair into this bucket if this bucket is empty and has never contained an entry
+ // OR
+ // This bucket once contained an entry but there has never been a collision
+ if ((buckets[bucketNumber].key == null) ||
+ (buckets[bucketNumber].key == buckets && ((buckets[bucketNumber].hash_coll & unchecked(0x80000000))==0))) {
+
+ // If we have found an available bucket that has never had a collision, but we've seen an available
+ // bucket in the past that has the collision bit set, use the previous bucket instead
+ if (emptySlotNumber != -1) // Reuse slot
+ bucketNumber = emptySlotNumber;
+
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ buckets[bucketNumber].val = nvalue;
+ buckets[bucketNumber].key = key;
+ buckets[bucketNumber].hash_coll |= (int) hashcode;
+ count++;
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ // coreclr has the randomized string hashing on by default so we don't need to resize at this point
+
+ if(ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
+ {
+ // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
+ // cases there may not be any strings in the hashtable and we wouldn't get any mixing.
+ if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
+ {
+ _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
+ rehash(buckets.Length, true);
+ }
+ }
+#endif // !FEATURE_CORECLR
+#endif // FEATURE_RANDOMIZED_STRING_HASHING
+ return;
+ }
+
+ // The current bucket is in use
+ // OR
+ // it is available, but has had the collision bit set and we have already found an available bucket
+ if (((buckets[bucketNumber].hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals (buckets[bucketNumber].key, key)) {
+ if (add) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", buckets[bucketNumber].key, key));
+ }
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ buckets[bucketNumber].val = nvalue;
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ if(ntry > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
+ {
+ // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
+ // cases there may not be any strings in the hashtable and we wouldn't get any mixing.
+ if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
+ {
+ _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
+ rehash(buckets.Length, true);
+ }
+ }
+#endif // !FEATURE_CORECLR
+#endif
+ return;
+ }
+
+ // The current bucket is full, and we have therefore collided. We need to set the collision bit
+ // UNLESS
+ // we have remembered an available slot previously.
+ if (emptySlotNumber == -1) {// We don't need to set the collision bit here since we already have an empty slot
+ if( buckets[bucketNumber].hash_coll >= 0 ) {
+ buckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ occupancy++;
+ }
+ }
+
+ bucketNumber = (int) (((long)bucketNumber + incr)% (uint)buckets.Length);
+ } while (++ntry < buckets.Length);
+
+ // This code is here if and only if there were no buckets without a collision bit set in the entire table
+ if (emptySlotNumber != -1)
+ {
+ // We pretty much have to insert in this order. Don't set hash
+ // code until the value & key are set appropriately.
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ buckets[emptySlotNumber].val = nvalue;
+ buckets[emptySlotNumber].key = key;
+ buckets[emptySlotNumber].hash_coll |= (int) hashcode;
+ count++;
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+#if !FEATURE_CORECLR
+ if(buckets.Length > HashHelpers.HashCollisionThreshold && HashHelpers.IsWellKnownEqualityComparer(_keycomparer))
+ {
+ // PERF: We don't want to rehash if _keycomparer is already a RandomizedObjectEqualityComparer since in some
+ // cases there may not be any strings in the hashtable and we wouldn't get any mixing.
+ if(_keycomparer == null || !(_keycomparer is System.Collections.Generic.RandomizedObjectEqualityComparer))
+ {
+ _keycomparer = HashHelpers.GetRandomizedEqualityComparer(_keycomparer);
+ rehash(buckets.Length, true);
+ }
+ }
+#endif // !FEATURE_CORECLR
+#endif
+ return;
+ }
+
+ // If you see this assert, make sure load factor & count are reasonable.
+ // Then verify that our double hash function (h2, described at top of file)
+ // meets the requirements described above. You should never see this assert.
+ Contract.Assert(false, "hash table insert failed! Load factor too high, or our double hashing function is incorrect.");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HashInsertFailed"));
+ }
+
+ private void putEntry (bucket[] newBuckets, Object key, Object nvalue, int hashcode)
+ {
+ Contract.Assert(hashcode >= 0, "hashcode >= 0"); // make sure collision bit (sign bit) wasn't set.
+
+ uint seed = (uint) hashcode;
+ uint incr = (uint)(1 + ((seed * HashPrime) % ((uint)newBuckets.Length - 1)));
+ int bucketNumber = (int) (seed % (uint)newBuckets.Length);
+ do {
+
+ if ((newBuckets[bucketNumber].key == null) || (newBuckets[bucketNumber].key == buckets)) {
+ newBuckets[bucketNumber].val = nvalue;
+ newBuckets[bucketNumber].key = key;
+ newBuckets[bucketNumber].hash_coll |= hashcode;
+ return;
+ }
+
+ if( newBuckets[bucketNumber].hash_coll >= 0 ) {
+ newBuckets[bucketNumber].hash_coll |= unchecked((int)0x80000000);
+ occupancy++;
+ }
+ bucketNumber = (int) (((long)bucketNumber + incr)% (uint)newBuckets.Length);
+ } while (true);
+ }
+
+ // Removes an entry from this hashtable. If an entry with the specified
+ // key exists in the hashtable, it is removed. An ArgumentException is
+ // thrown if the key is null.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public virtual void Remove(Object key) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ Contract.Assert(!isWriterInProgress, "Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized.");
+
+ uint seed;
+ uint incr;
+ // Assuming only one concurrent writer, write directly into buckets.
+ uint hashcode = InitHash(key, buckets.Length, out seed, out incr);
+ int ntry = 0;
+
+ bucket b;
+ int bn = (int) (seed % (uint)buckets.Length); // bucketNumber
+ do {
+ b = buckets[bn];
+ if (((b.hash_coll & 0x7FFFFFFF) == hashcode) &&
+ KeyEquals (b.key, key)) {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ isWriterInProgress = true;
+ // Clear hash_coll field, then key, then value
+ buckets[bn].hash_coll &= unchecked((int)0x80000000);
+ if (buckets[bn].hash_coll != 0) {
+ buckets[bn].key = buckets;
+ }
+ else {
+ buckets[bn].key = null;
+ }
+ buckets[bn].val = null; // Free object references sooner & simplify ContainsValue.
+ count--;
+ UpdateVersion();
+ isWriterInProgress = false;
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ return;
+ }
+ bn = (int) (((long)bn + incr)% (uint)buckets.Length);
+ } while (b.hash_coll < 0 && ++ntry < buckets.Length);
+
+ //throw new ArgumentException(Environment.GetResourceString("Arg_RemoveArgNotFound"));
+ }
+
+ // Returns the object to synchronize on for this hash table.
+ public virtual Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Returns the number of associations in this hashtable.
+ //
+ public virtual int Count {
+ get { return count; }
+ }
+
+ // Returns a thread-safe wrapper for a Hashtable.
+ //
+ [HostProtection(Synchronization=true)]
+ public static Hashtable Synchronized(Hashtable table) {
+ if (table==null)
+ throw new ArgumentNullException("table");
+ Contract.EndContractBlock();
+ return new SyncHashtable(table);
+ }
+
+ //
+ // The ISerializable Implementation
+ //
+
+ [System.Security.SecurityCritical]
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ // This is imperfect - it only works well if all other writes are
+ // also using our synchronized wrapper. But it's still a good idea.
+ lock (SyncRoot) {
+ // This method hasn't been fully tweaked to be safe for a concurrent writer.
+ int oldVersion = version;
+ info.AddValue(LoadFactorName, loadFactor);
+ info.AddValue(VersionName, version);
+
+ //
+ // We need to maintain serialization compatibility with Everett and RTM.
+ // If the comparer is null or a compatible comparer, serialize Hashtable
+ // in a format that can be deserialized on Everett and RTM.
+ //
+ // Also, if the Hashtable is using randomized hashing, serialize the old
+ // view of the _keycomparer so perevious frameworks don't see the new types
+#pragma warning disable 618
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ IEqualityComparer keyComparerForSerilization = (IEqualityComparer) HashHelpers.GetEqualityComparerForSerialization(_keycomparer);
+#else
+ IEqualityComparer keyComparerForSerilization = _keycomparer;
+#endif
+
+ if( keyComparerForSerilization == null) {
+ info.AddValue(ComparerName, null,typeof(IComparer));
+ info.AddValue(HashCodeProviderName, null, typeof(IHashCodeProvider));
+ }
+ else if(keyComparerForSerilization is CompatibleComparer) {
+ CompatibleComparer c = keyComparerForSerilization as CompatibleComparer;
+ info.AddValue(ComparerName, c.Comparer, typeof(IComparer));
+ info.AddValue(HashCodeProviderName, c.HashCodeProvider, typeof(IHashCodeProvider));
+ }
+ else {
+ info.AddValue(KeyComparerName, keyComparerForSerilization, typeof(IEqualityComparer));
+ }
+#pragma warning restore 618
+
+ info.AddValue(HashSizeName, buckets.Length); //This is the length of the bucket array.
+ Object [] serKeys = new Object[count];
+ Object [] serValues = new Object[count];
+ CopyKeys(serKeys, 0);
+ CopyValues(serValues,0);
+ info.AddValue(KeysName, serKeys, typeof(Object[]));
+ info.AddValue(ValuesName, serValues, typeof(Object[]));
+
+ // Explicitly check to see if anyone changed the Hashtable while we
+ // were serializing it. That's a race condition in their code.
+ if (version != oldVersion)
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ }
+ }
+
+ //
+ // DeserializationEvent Listener
+ //
+ public virtual void OnDeserialization(Object sender) {
+ if (buckets!=null) {
+ // Somebody had a dependency on this hashtable and fixed us up before the ObjectManager got to it.
+ return;
+ }
+
+ SerializationInfo siInfo;
+ HashHelpers.SerializationInfoTable.TryGetValue(this, out siInfo);
+
+ if (siInfo==null) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidOnDeser"));
+ }
+
+ int hashsize = 0;
+ IComparer c = null;
+
+#pragma warning disable 618
+ IHashCodeProvider hcp = null;
+#pragma warning restore 618
+
+ Object [] serKeys = null;
+ Object [] serValues = null;
+
+ SerializationInfoEnumerator enumerator = siInfo.GetEnumerator();
+
+ while( enumerator.MoveNext())
+ {
+ switch( enumerator.Name)
+ {
+ case LoadFactorName:
+ loadFactor = siInfo.GetSingle(LoadFactorName);
+ break;
+ case HashSizeName:
+ hashsize = siInfo.GetInt32(HashSizeName);
+ break;
+ case KeyComparerName:
+ _keycomparer = (IEqualityComparer)siInfo.GetValue(KeyComparerName, typeof(IEqualityComparer));
+ break;
+ case ComparerName:
+ c = (IComparer)siInfo.GetValue(ComparerName, typeof(IComparer));
+ break;
+ case HashCodeProviderName:
+#pragma warning disable 618
+ hcp = (IHashCodeProvider)siInfo.GetValue(HashCodeProviderName, typeof(IHashCodeProvider));
+#pragma warning restore 618
+ break;
+ case KeysName:
+ serKeys = (Object[])siInfo.GetValue(KeysName, typeof(Object[]));
+ break;
+ case ValuesName:
+ serValues = (Object[])siInfo.GetValue(ValuesName, typeof(Object[]));
+ break;
+ }
+ }
+
+ loadsize = (int)(loadFactor*hashsize);
+
+ // V1 object doesn't has _keycomparer field.
+ if ( (_keycomparer == null) && ( (c != null) || (hcp != null) ) ){
+ _keycomparer = new CompatibleComparer(c,hcp);
+ }
+
+ buckets = new bucket[hashsize];
+
+ if (serKeys==null) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_MissingKeys"));
+ }
+ if (serValues==null) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_MissingValues"));
+ }
+ if (serKeys.Length!=serValues.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_KeyValueDifferentSizes"));
+ }
+ for (int i=0; i<serKeys.Length; i++) {
+ if (serKeys[i]==null) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_NullKey"));
+ }
+ Insert(serKeys[i], serValues[i], true);
+ }
+
+ version = siInfo.GetInt32(VersionName);
+
+ HashHelpers.SerializationInfoTable.Remove(this);
+ }
+
+
+ // Implements a Collection for the keys of a hashtable. An instance of this
+ // class is created by the GetKeys method of a hashtable.
+ [Serializable]
+ private class KeyCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal KeyCollection(Hashtable hashtable) {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (array.Length - arrayIndex < _hashtable.count)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ _hashtable.CopyKeys(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Keys);
+ }
+
+ public virtual bool IsSynchronized {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count {
+ get { return _hashtable.count; }
+ }
+ }
+
+ // Implements a Collection for the values of a hashtable. An instance of
+ // this class is created by the GetValues method of a hashtable.
+ [Serializable]
+ private class ValueCollection : ICollection
+ {
+ private Hashtable _hashtable;
+
+ internal ValueCollection(Hashtable hashtable) {
+ _hashtable = hashtable;
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (array.Length - arrayIndex < _hashtable.count)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ _hashtable.CopyValues(array, arrayIndex);
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new HashtableEnumerator(_hashtable, HashtableEnumerator.Values);
+ }
+
+ public virtual bool IsSynchronized {
+ get { return _hashtable.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return _hashtable.SyncRoot; }
+ }
+
+ public virtual int Count {
+ get { return _hashtable.count; }
+ }
+ }
+
+ // Synchronized wrapper for hashtable
+ [Serializable]
+ private class SyncHashtable : Hashtable, IEnumerable
+ {
+ protected Hashtable _table;
+
+ internal SyncHashtable(Hashtable table) : base(false) {
+ _table = table;
+ }
+
+ internal SyncHashtable(SerializationInfo info, StreamingContext context) : base (info, context) {
+ _table = (Hashtable)info.GetValue("ParentTable", typeof(Hashtable));
+ if (_table==null) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+ }
+
+
+ /*================================GetObjectData=================================
+ **Action: Return a serialization info containing a reference to _table. We need
+ ** to implement this because our parent HT does and we don't want to actually
+ ** serialize all of it's values (just a reference to the table, which will then
+ ** be serialized separately.)
+ **Returns: void
+ **Arguments: info -- the SerializationInfo into which to store the data.
+ ** context -- the StreamingContext for the current serialization (ignored)
+ **Exceptions: ArgumentNullException if info is null.
+ ==============================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ // Our serialization code hasn't been fully tweaked to be safe
+ // for a concurrent writer.
+ lock (_table.SyncRoot) {
+ info.AddValue("ParentTable", _table, typeof(Hashtable));
+ }
+ }
+
+ public override int Count {
+ get { return _table.Count; }
+ }
+
+ public override bool IsReadOnly {
+ get { return _table.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _table.IsFixedSize; }
+ }
+
+ public override bool IsSynchronized {
+ get { return true; }
+ }
+
+ public override Object this[Object key] {
+ get {
+ return _table[key];
+ }
+ set {
+ lock(_table.SyncRoot) {
+ _table[key] = value;
+ }
+ }
+ }
+
+ public override Object SyncRoot {
+ get { return _table.SyncRoot; }
+ }
+
+ public override void Add(Object key, Object value) {
+ lock(_table.SyncRoot) {
+ _table.Add(key, value);
+ }
+ }
+
+ public override void Clear() {
+ lock(_table.SyncRoot) {
+ _table.Clear();
+ }
+ }
+
+ public override bool Contains(Object key) {
+ return _table.Contains(key);
+ }
+
+ public override bool ContainsKey(Object key) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ return _table.ContainsKey(key);
+ }
+
+ public override bool ContainsValue(Object key) {
+ lock(_table.SyncRoot) {
+ return _table.ContainsValue(key);
+ }
+ }
+
+ public override void CopyTo(Array array, int arrayIndex) {
+ lock (_table.SyncRoot) {
+ _table.CopyTo(array, arrayIndex);
+ }
+ }
+
+ public override Object Clone() {
+ lock (_table.SyncRoot) {
+ return Hashtable.Synchronized((Hashtable)_table.Clone());
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return _table.GetEnumerator();
+ }
+
+ public override IDictionaryEnumerator GetEnumerator() {
+ return _table.GetEnumerator();
+ }
+
+ public override ICollection Keys {
+ get {
+ lock(_table.SyncRoot) {
+ return _table.Keys;
+ }
+ }
+ }
+
+ public override ICollection Values {
+ get {
+ lock(_table.SyncRoot) {
+ return _table.Values;
+ }
+ }
+ }
+
+ public override void Remove(Object key) {
+ lock(_table.SyncRoot) {
+ _table.Remove(key);
+ }
+ }
+
+ /*==============================OnDeserialization===============================
+ **Action: Does nothing. We have to implement this because our parent HT implements it,
+ ** but it doesn't do anything meaningful. The real work will be done when we
+ ** call OnDeserialization on our parent table.
+ **Returns: void
+ **Arguments: None
+ **Exceptions: None
+ ==============================================================================*/
+ public override void OnDeserialization(Object sender) {
+ return;
+ }
+
+ internal override KeyValuePairs[] ToKeyValuePairsArray() {
+ return _table.ToKeyValuePairsArray();
+ }
+
+ }
+
+
+ // Implements an enumerator for a hashtable. The enumerator uses the
+ // internal version number of the hashtabke to ensure that no modifications
+ // are made to the hashtable while an enumeration is in progress.
+ [Serializable]
+ private class HashtableEnumerator : IDictionaryEnumerator, ICloneable
+ {
+ private Hashtable hashtable;
+ private int bucket;
+ private int version;
+ private bool current;
+ private int getObjectRetType; // What should GetObject return?
+ private Object currentKey;
+ private Object currentValue;
+
+ internal const int Keys = 1;
+ internal const int Values = 2;
+ internal const int DictEntry = 3;
+
+ internal HashtableEnumerator(Hashtable hashtable, int getObjRetType) {
+ this.hashtable = hashtable;
+ bucket = hashtable.buckets.Length;
+ version = hashtable.version;
+ current = false;
+ getObjectRetType = getObjRetType;
+ }
+
+ public Object Clone() {
+ return MemberwiseClone();
+ }
+
+ public virtual Object Key {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ return currentKey;
+ }
+ }
+
+ public virtual bool MoveNext() {
+ if (version != hashtable.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ while (bucket > 0) {
+ bucket--;
+ Object keyv = hashtable.buckets[bucket].key;
+ if ((keyv!= null) && (keyv != hashtable.buckets)) {
+ currentKey = keyv;
+ currentValue = hashtable.buckets[bucket].val;
+ current = true;
+ return true;
+ }
+ }
+ current = false;
+ return false;
+ }
+
+ public virtual DictionaryEntry Entry {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumOpCantHappen));
+ return new DictionaryEntry(currentKey, currentValue);
+ }
+ }
+
+
+ public virtual Object Current {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumOpCantHappen));
+
+ if (getObjectRetType==Keys)
+ return currentKey;
+ else if (getObjectRetType==Values)
+ return currentValue;
+ else
+ return new DictionaryEntry(currentKey, currentValue);
+ }
+ }
+
+ public virtual Object Value {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumOpCantHappen));
+ return currentValue;
+ }
+ }
+
+ public virtual void Reset() {
+ if (version != hashtable.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ current = false;
+ bucket = hashtable.buckets.Length;
+ currentKey = null;
+ currentValue = null;
+ }
+ }
+
+ // internal debug view class for hashtable
+ internal class HashtableDebugView {
+ private Hashtable hashtable;
+
+ public HashtableDebugView( Hashtable hashtable) {
+ if( hashtable == null) {
+ throw new ArgumentNullException( "hashtable");
+ }
+ Contract.EndContractBlock();
+
+ this.hashtable = hashtable;
+ }
+
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePairs[] Items {
+ get {
+ return hashtable.ToKeyValuePairsArray();
+ }
+ }
+ }
+ }
+
+ [FriendAccessAllowed]
+ internal static class HashHelpers
+ {
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ public const int HashCollisionThreshold = 100;
+ public static bool s_UseRandomizedStringHashing = String.UseRandomizedHashing();
+#endif
+
+ // Table of prime numbers to use as hash table sizes.
+ // A typical resize algorithm would pick the smallest prime number in this array
+ // that is larger than twice the previous capacity.
+ // Suppose our Hashtable currently has capacity x and enough elements are added
+ // such that a resize needs to occur. Resizing first computes 2x then finds the
+ // first prime in the table greater than 2x, i.e. if primes are ordered
+ // p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
+ // Doubling is important for preserving the asymptotic complexity of the
+ // hashtable operations such as add. Having a prime guarantees that double
+ // hashing does not lead to infinite loops. IE, your hash function will be
+ // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
+ public static readonly int[] primes = {
+ 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
+ 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
+ 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
+ 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
+ 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
+
+ // Used by Hashtable and Dictionary's SeralizationInfo .ctor's to store the SeralizationInfo
+ // object until OnDeserialization is called.
+ private static ConditionalWeakTable<object, SerializationInfo> s_SerializationInfoTable;
+
+ internal static ConditionalWeakTable<object, SerializationInfo> SerializationInfoTable
+ {
+ get
+ {
+ if(s_SerializationInfoTable == null)
+ {
+ ConditionalWeakTable<object, SerializationInfo> newTable = new ConditionalWeakTable<object, SerializationInfo>();
+ Interlocked.CompareExchange(ref s_SerializationInfoTable, newTable, null);
+ }
+
+ return s_SerializationInfoTable;
+ }
+
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static bool IsPrime(int candidate)
+ {
+ if ((candidate & 1) != 0)
+ {
+ int limit = (int)Math.Sqrt (candidate);
+ for (int divisor = 3; divisor <= limit; divisor+=2)
+ {
+ if ((candidate % divisor) == 0)
+ return false;
+ }
+ return true;
+ }
+ return (candidate == 2);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int GetPrime(int min)
+ {
+ if (min < 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_HTCapacityOverflow"));
+ Contract.EndContractBlock();
+
+ for (int i = 0; i < primes.Length; i++)
+ {
+ int prime = primes[i];
+ if (prime >= min) return prime;
+ }
+
+ //outside of our predefined table.
+ //compute the hard way.
+ for (int i = (min | 1); i < Int32.MaxValue;i+=2)
+ {
+ if (IsPrime(i) && ((i - 1) % Hashtable.HashPrime != 0))
+ return i;
+ }
+ return min;
+ }
+
+ public static int GetMinPrime()
+ {
+ return primes[0];
+ }
+
+ // Returns size of hashtable to grow to.
+ public static int ExpandPrime(int oldSize)
+ {
+ int newSize = 2 * oldSize;
+
+ // Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
+ // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+ if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
+ {
+ Contract.Assert( MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
+ return MaxPrimeArrayLength;
+ }
+
+ return GetPrime(newSize);
+ }
+
+
+ // This is the maximum prime smaller than Array.MaxArrayLength
+ public const int MaxPrimeArrayLength = 0x7FEFFFFD;
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ public static bool IsWellKnownEqualityComparer(object comparer)
+ {
+ return (comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);
+ }
+
+ public static IEqualityComparer GetRandomizedEqualityComparer(object comparer)
+ {
+ Contract.Assert(comparer == null || comparer == System.Collections.Generic.EqualityComparer<string>.Default || comparer is IWellKnownStringEqualityComparer);
+
+ if(comparer == null) {
+ return new System.Collections.Generic.RandomizedObjectEqualityComparer();
+ }
+
+ if(comparer == System.Collections.Generic.EqualityComparer<string>.Default) {
+ return new System.Collections.Generic.RandomizedStringEqualityComparer();
+ }
+
+ IWellKnownStringEqualityComparer cmp = comparer as IWellKnownStringEqualityComparer;
+
+ if(cmp != null) {
+ return cmp.GetRandomizedEqualityComparer();
+ }
+
+ Contract.Assert(false, "Missing case in GetRandomizedEqualityComparer!");
+
+ return null;
+ }
+
+ public static object GetEqualityComparerForSerialization(object comparer)
+ {
+ if(comparer == null)
+ {
+ return null;
+ }
+
+ IWellKnownStringEqualityComparer cmp = comparer as IWellKnownStringEqualityComparer;
+
+ if(cmp != null)
+ {
+ return cmp.GetEqualityComparerForSerialization();
+ }
+
+ return comparer;
+ }
+
+ private const int bufferSize = 1024;
+#if !FEATURE_CORECLR
+ private static RandomNumberGenerator rng;
+#endif
+ private static byte[] data;
+ private static int currentIndex = bufferSize;
+ private static readonly object lockObj = new Object();
+
+ internal static long GetEntropy()
+ {
+ lock(lockObj) {
+ long ret;
+
+ if(currentIndex == bufferSize)
+ {
+ if(data == null)
+ {
+ data = new byte[bufferSize];
+ Contract.Assert(bufferSize % 8 == 0, "We increment our current index by 8, so our buffer size must be a multiple of 8");
+#if !FEATURE_CORECLR
+ rng = RandomNumberGenerator.Create();
+#endif
+
+ }
+
+#if FEATURE_CORECLR
+ Microsoft.Win32.Win32Native.Random(true, data, data.Length);
+#else
+ rng.GetBytes(data);
+#endif
+ currentIndex = 0;
+ }
+
+ ret = BitConverter.ToInt64(data, currentIndex);
+ currentIndex += 8;
+
+ return ret;
+ }
+ }
+#endif // FEATURE_RANDOMIZED_STRING_HASHING
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ICollection.cs b/src/mscorlib/src/System/Collections/ICollection.cs
new file mode 100644
index 0000000000..6d4d6e1a93
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ICollection.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ICollection
+**
+**
+**
+**
+** Purpose: Base interface for all collections.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // Base interface for all collections, defining enumerators, size, and
+ // synchronization methods.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICollection : IEnumerable
+ {
+ // Interfaces are not serialable
+ // CopyTo copies a collection into an Array, starting at a particular
+ // index into the array.
+ //
+ void CopyTo(Array array, int index);
+
+ // Number of items in the collections.
+ int Count
+ { get; }
+
+
+ // SyncRoot will return an Object to use for synchronization
+ // (thread safety). You can use this object in your code to take a
+ // lock on the collection, even if this collection is a wrapper around
+ // another collection. The intent is to tunnel through to a real
+ // implementation of a collection, and use one of the internal objects
+ // found in that code.
+ //
+ // In the absense of a static Synchronized method on a collection,
+ // the expected usage for SyncRoot would look like this:
+ //
+ // ICollection col = ...
+ // lock (col.SyncRoot) {
+ // // Some operation on the collection, which is now thread safe.
+ // // This may include multiple operations.
+ // }
+ //
+ //
+ // The system-provided collections have a static method called
+ // Synchronized which will create a thread-safe wrapper around the
+ // collection. All access to the collection that you want to be
+ // thread-safe should go through that wrapper collection. However, if
+ // you need to do multiple calls on that collection (such as retrieving
+ // two items, or checking the count then doing something), you should
+ // NOT use our thread-safe wrapper since it only takes a lock for the
+ // duration of a single method call. Instead, use Monitor.Enter/Exit
+ // or your language's equivalent to the C# lock keyword as mentioned
+ // above.
+ //
+ // For collections with no publically available underlying store, the
+ // expected implementation is to simply return the this pointer. Note
+ // that the this pointer may not be sufficient for collections that
+ // wrap other collections; those should return the underlying
+ // collection's SyncRoot property.
+ Object SyncRoot
+ { get; }
+
+ // Is this collection synchronized (i.e., thread-safe)? If you want a
+ // thread-safe collection, you can use SyncRoot as an object to
+ // synchronize your collection with. If you're using one of the
+ // collections in System.Collections, you could call the static
+ // Synchronized method to get a thread-safe wrapper around the
+ // underlying collection.
+ bool IsSynchronized
+ { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IComparer.cs b/src/mscorlib/src/System/Collections/IComparer.cs
new file mode 100644
index 0000000000..d5a3448934
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IComparer.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IComparer
+**
+**
+**
+**
+** Purpose: Interface for comparing two Objects.
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ // The IComparer interface implements a method that compares two objects. It is
+ // used in conjunction with the Sort and BinarySearch methods on
+ // the Array and List classes.
+ //
+ // Interfaces are not serializable
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IComparer {
+ // Compares two objects. An implementation of this method must return a
+ // value less than zero if x is less than y, zero if x is equal to y, or a
+ // value greater than zero if x is greater than y.
+ //
+ int Compare(Object x, Object y);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IDictionary.cs b/src/mscorlib/src/System/Collections/IDictionary.cs
new file mode 100644
index 0000000000..4da89d6983
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IDictionary.cs
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IDictionary
+**
+**
+**
+**
+** Purpose: Base interface for all dictionaries.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // An IDictionary is a possibly unordered set of key-value pairs.
+ // Keys can be any non-null object. Values can be any object.
+ // You can look up a value in an IDictionary via the default indexed
+ // property, Items.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IDictionary : ICollection
+ {
+ // Interfaces are not serializable
+ // The Item property provides methods to read and edit entries
+ // in the Dictionary.
+ Object this[Object key] {
+ get;
+ set;
+ }
+
+ // Returns a collections of the keys in this dictionary.
+ ICollection Keys {
+ get;
+ }
+
+ // Returns a collections of the values in this dictionary.
+ ICollection Values {
+ get;
+ }
+
+ // Returns whether this dictionary contains a particular key.
+ //
+ bool Contains(Object key);
+
+ // Adds a key-value pair to the dictionary.
+ //
+ void Add(Object key, Object value);
+
+ // Removes all pairs from the dictionary.
+ void Clear();
+
+ bool IsReadOnly
+ { get; }
+
+ bool IsFixedSize
+ { get; }
+
+ // Returns an IDictionaryEnumerator for this dictionary.
+ new IDictionaryEnumerator GetEnumerator();
+
+ // Removes a particular key from the dictionary.
+ //
+ void Remove(Object key);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IDictionaryEnumerator.cs b/src/mscorlib/src/System/Collections/IDictionaryEnumerator.cs
new file mode 100644
index 0000000000..b995a04a0e
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IDictionaryEnumerator.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IDictionaryEnumerator
+**
+**
+**
+**
+** Purpose: Base interface for dictionary enumerators.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ // Interfaces are not serializable
+
+ using System;
+ // This interface represents an enumerator that allows sequential access to the
+ // elements of a dictionary. Upon creation, an enumerator is conceptually
+ // positioned before the first element of the enumeration. The first call to the
+ // MoveNext method brings the first element of the enumeration into view,
+ // and each successive call to MoveNext brings the next element into
+ // view until MoveNext returns false, indicating that there are no more
+ // elements to enumerate. Following each call to MoveNext, the
+ // Key and Value methods are used to obtain the key and
+ // value of the element currently in view. The values returned by calls to
+ // Key and Value are undefined before the first call to
+ // MoveNext and following a call to MoveNext that returned false.
+ // Enumerators are typically used in while loops of the form
+ //
+ // IDictionaryEnumerator e = ...;
+ // while (e.MoveNext()) {
+ // Object key = e.Key;
+ // Object value = e.Value;
+ // ...
+ // }
+ //
+ // The IDictionaryEnumerator interface extends the IEnumerator
+ // inerface and can thus be used as a regular enumerator. The Current
+ // method of an IDictionaryEnumerator returns a DictionaryEntry containing
+ // the current key and value pair. However, the GetEntry method will
+ // return the same DictionaryEntry and avoids boxing the DictionaryEntry (boxing
+ // is somewhat expensive).
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IDictionaryEnumerator : IEnumerator
+ {
+ // Returns the key of the current element of the enumeration. The returned
+ // value is undefined before the first call to GetNext and following
+ // a call to GetNext that returned false. Multiple calls to
+ // GetKey with no intervening calls to GetNext will return
+ // the same object.
+ //
+ Object Key {
+ get;
+ }
+
+ // Returns the value of the current element of the enumeration. The
+ // returned value is undefined before the first call to GetNext and
+ // following a call to GetNext that returned false. Multiple calls
+ // to GetValue with no intervening calls to GetNext will
+ // return the same object.
+ //
+ Object Value {
+ get;
+ }
+
+ // GetBlock will copy dictionary values into the given Array. It will either
+ // fill up the array, or if there aren't enough elements, it will
+ // copy as much as possible into the Array. The number of elements
+ // copied is returned.
+ //
+ DictionaryEntry Entry {
+ get;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IEnumerable.cs b/src/mscorlib/src/System/Collections/IEnumerable.cs
new file mode 100644
index 0000000000..5fa63f15d0
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IEnumerable.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IEnumerable
+**
+**
+**
+**
+** Purpose: Interface for classes providing IEnumerators
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices;
+
+ // Implement this interface if you need to support VB's foreach semantics.
+ // Also, COM classes that support an enumerator will also implement this interface.
+ [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IEnumerable
+ {
+ // Interfaces are not serializable
+ // Returns an IEnumerator for this enumerable Object. The enumerator provides
+ // a simple way to access all the contents of a collection.
+ [Pure]
+ [DispId(-4)]
+ IEnumerator GetEnumerator();
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IEnumerator.cs b/src/mscorlib/src/System/Collections/IEnumerator.cs
new file mode 100644
index 0000000000..99509d15ea
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IEnumerator.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IEnumerator
+**
+**
+**
+**
+** Purpose: Base interface for all enumerators.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Runtime.InteropServices;
+
+ // Base interface for all enumerators, providing a simple approach
+ // to iterating over a collection.
+ [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IEnumerator
+ {
+ // Interfaces are not serializable
+ // Advances the enumerator to the next element of the enumeration and
+ // returns a boolean indicating whether an element is available. Upon
+ // creation, an enumerator is conceptually positioned before the first
+ // element of the enumeration, and the first call to MoveNext
+ // brings the first element of the enumeration into view.
+ //
+ bool MoveNext();
+
+ // Returns the current element of the enumeration. The returned value is
+ // undefined before the first call to MoveNext and following a
+ // call to MoveNext that returned false. Multiple calls to
+ // GetCurrent with no intervening calls to MoveNext
+ // will return the same object.
+ //
+ Object Current {
+ get;
+ }
+
+ // Resets the enumerator to the beginning of the enumeration, starting over.
+ // The preferred behavior for Reset is to return the exact same enumeration.
+ // This means if you modify the underlying collection then call Reset, your
+ // IEnumerator will be invalid, just as it would have been if you had called
+ // MoveNext or Current.
+ //
+ void Reset();
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IEqualityComparer.cs b/src/mscorlib/src/System/Collections/IEqualityComparer.cs
new file mode 100644
index 0000000000..50c732f47c
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IEqualityComparer.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IEqualityComparer
+**
+**
+**
+**
+** Purpose: A mechanism to expose a simplified infrastructure for
+** Comparing objects in collections.
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ // An IEqualityComparer is a mechanism to consume custom performant comparison infrastructure
+ // that can be consumed by some of the common collections.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IEqualityComparer {
+ bool Equals(Object x, Object y);
+ int GetHashCode(Object obj);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IHashCodeProvider.cs b/src/mscorlib/src/System/Collections/IHashCodeProvider.cs
new file mode 100644
index 0000000000..aefa15e1e5
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IHashCodeProvider.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IHashCodeProvider
+**
+**
+**
+**
+** Purpose: A bunch of strings.
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ // Provides a mechanism for a hash table user to override the default
+ // GetHashCode() function on Objects, providing their own hash function.
+ [Obsolete("Please use IEqualityComparer instead.")]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IHashCodeProvider
+ {
+ // Interfaces are not serializable
+ // Returns a hash code for the given object.
+ //
+ int GetHashCode (Object obj);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IList.cs b/src/mscorlib/src/System/Collections/IList.cs
new file mode 100644
index 0000000000..8bdfe4c1d0
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IList.cs
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IList
+**
+**
+**
+**
+** Purpose: Base interface for all Lists.
+**
+**
+===========================================================*/
+namespace System.Collections {
+
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // An IList is an ordered collection of objects. The exact ordering
+ // is up to the implementation of the list, ranging from a sorted
+ // order to insertion order.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IList : ICollection
+ {
+ // The Item property provides methods to read and edit entries in the List.
+ Object this[int index] {
+ get;
+ set;
+ }
+
+ // Adds an item to the list. The exact position in the list is
+ // implementation-dependent, so while ArrayList may always insert
+ // in the last available location, a SortedList most likely would not.
+ // The return value is the position the new element was inserted in.
+ int Add(Object value);
+
+ // Returns whether the list contains a particular item.
+ bool Contains(Object value);
+
+ // Removes all items from the list.
+ void Clear();
+
+ bool IsReadOnly
+ { get; }
+
+
+ bool IsFixedSize
+ {
+ get;
+ }
+
+
+ // Returns the index of a particular item, if it is in the list.
+ // Returns -1 if the item isn't in the list.
+ int IndexOf(Object value);
+
+ // Inserts value into the list at position index.
+ // index must be non-negative and less than or equal to the
+ // number of elements in the list. If index equals the number
+ // of items in the list, then value is appended to the end.
+ void Insert(int index, Object value);
+
+ // Removes an item from the list.
+ void Remove(Object value);
+
+ // Removes the item at position index.
+ void RemoveAt(int index);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IStructuralComparable.cs b/src/mscorlib/src/System/Collections/IStructuralComparable.cs
new file mode 100644
index 0000000000..1b6f3aff7a
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IStructuralComparable.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+
+namespace System.Collections {
+
+ public interface IStructuralComparable {
+ Int32 CompareTo(Object other, IComparer comparer);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/IStructuralEquatable.cs b/src/mscorlib/src/System/Collections/IStructuralEquatable.cs
new file mode 100644
index 0000000000..5a5295fc38
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/IStructuralEquatable.cs
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace System.Collections {
+
+ public interface IStructuralEquatable {
+ Boolean Equals(Object other, IEqualityComparer comparer);
+ int GetHashCode(IEqualityComparer comparer);
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/KeyValuePairs.cs b/src/mscorlib/src/System/Collections/KeyValuePairs.cs
new file mode 100644
index 0000000000..22bf92c456
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/KeyValuePairs.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: KeyValuePairs to display items in collection class under debugger
+**
+**
+===========================================================*/
+
+namespace System.Collections {
+ using System.Diagnostics;
+
+ [DebuggerDisplay("{value}", Name = "[{key}]", Type = "" )]
+ internal class KeyValuePairs {
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object key;
+
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ private object value;
+
+ public KeyValuePairs(object key, object value) {
+ this.value = value;
+ this.key = key;
+ }
+
+ public object Key {
+ get { return key; }
+ }
+
+ public object Value {
+ get { return value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs
new file mode 100644
index 0000000000..944523c475
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ListDictionaryInternal.cs
@@ -0,0 +1,429 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: List for exceptions.
+**
+**
+===========================================================*/
+using System.Diagnostics.Contracts;
+namespace System.Collections {
+ /// This is a simple implementation of IDictionary using a singly linked list. This
+ /// will be smaller and faster than a Hashtable if the number of elements is 10 or less.
+ /// This should not be used if performance is important for large numbers of elements.
+ [Serializable]
+ internal class ListDictionaryInternal: IDictionary {
+ DictionaryNode head;
+ int version;
+ int count;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public ListDictionaryInternal() {
+ }
+
+ public Object this[Object key] {
+ get {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ DictionaryNode node = head;
+
+ while (node != null) {
+ if ( node.key.Equals(key) ) {
+ return node.value;
+ }
+ node = node.next;
+ }
+ return null;
+ }
+ set {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+
+#if FEATURE_SERIALIZATION
+ if (!key.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key");
+
+ if( (value != null) && (!value.GetType().IsSerializable ) )
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
+#endif
+
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next) {
+ if( node.key.Equals(key) ) {
+ break;
+ }
+ last = node;
+ }
+ if (node != null) {
+ // Found it
+ node.value = value;
+ return;
+ }
+ // Not found, so add a new one
+ DictionaryNode newNode = new DictionaryNode();
+ newNode.key = key;
+ newNode.value = value;
+ if (last != null) {
+ last.next = newNode;
+ }
+ else {
+ head = newNode;
+ }
+ count++;
+ }
+ }
+
+ public int Count {
+ get {
+ return count;
+ }
+ }
+
+ public ICollection Keys {
+ get {
+ return new NodeKeyValueCollection(this, true);
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return false;
+ }
+ }
+
+ public bool IsFixedSize {
+ get {
+ return false;
+ }
+ }
+
+ public bool IsSynchronized {
+ get {
+ return false;
+ }
+ }
+
+ public Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ public ICollection Values {
+ get {
+ return new NodeKeyValueCollection(this, false);
+ }
+ }
+
+ public void Add(Object key, Object value) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+
+#if FEATURE_SERIALIZATION
+ if (!key.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "key" );
+
+ if( (value != null) && (!value.GetType().IsSerializable) )
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSerializable"), "value");
+#endif
+
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next) {
+ if (node.key.Equals(key)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", node.key, key));
+ }
+ last = node;
+ }
+ if (node != null) {
+ // Found it
+ node.value = value;
+ return;
+ }
+ // Not found, so add a new one
+ DictionaryNode newNode = new DictionaryNode();
+ newNode.key = key;
+ newNode.value = value;
+ if (last != null) {
+ last.next = newNode;
+ }
+ else {
+ head = newNode;
+ }
+ count++;
+ }
+
+ public void Clear() {
+ count = 0;
+ head = null;
+ version++;
+ }
+
+ public bool Contains(Object key) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ for (DictionaryNode node = head; node != null; node = node.next) {
+ if (node.key.Equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void CopyTo(Array array, int index) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if ( array.Length - index < this.Count )
+ throw new ArgumentException( Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
+ Contract.EndContractBlock();
+
+ for (DictionaryNode node = head; node != null; node = node.next) {
+ array.SetValue(new DictionaryEntry(node.key, node.value), index);
+ index++;
+ }
+ }
+
+ public IDictionaryEnumerator GetEnumerator() {
+ return new NodeEnumerator(this);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new NodeEnumerator(this);
+ }
+
+ public void Remove(Object key) {
+ if (key == null) {
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ }
+ Contract.EndContractBlock();
+ version++;
+ DictionaryNode last = null;
+ DictionaryNode node;
+ for (node = head; node != null; node = node.next) {
+ if (node.key.Equals(key)) {
+ break;
+ }
+ last = node;
+ }
+ if (node == null) {
+ return;
+ }
+ if (node == head) {
+ head = node.next;
+ } else {
+ last.next = node.next;
+ }
+ count--;
+ }
+
+ private class NodeEnumerator : IDictionaryEnumerator {
+ ListDictionaryInternal list;
+ DictionaryNode current;
+ int version;
+ bool start;
+
+
+ public NodeEnumerator(ListDictionaryInternal list) {
+ this.list = list;
+ version = list.version;
+ start = true;
+ current = null;
+ }
+
+ public Object Current {
+ get {
+ return Entry;
+ }
+ }
+
+ public DictionaryEntry Entry {
+ get {
+ if (current == null) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return new DictionaryEntry(current.key, current.value);
+ }
+ }
+
+ public Object Key {
+ get {
+ if (current == null) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return current.key;
+ }
+ }
+
+ public Object Value {
+ get {
+ if (current == null) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return current.value;
+ }
+ }
+
+ public bool MoveNext() {
+ if (version != list.version) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ }
+ if (start) {
+ current = list.head;
+ start = false;
+ }
+ else {
+ if( current != null ) {
+ current = current.next;
+ }
+ }
+ return (current != null);
+ }
+
+ public void Reset() {
+ if (version != list.version) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ }
+ start = true;
+ current = null;
+ }
+
+ }
+
+
+ private class NodeKeyValueCollection : ICollection {
+ ListDictionaryInternal list;
+ bool isKeys;
+
+ public NodeKeyValueCollection(ListDictionaryInternal list, bool isKeys) {
+ this.list = list;
+ this.isKeys = isKeys;
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (array.Length - index < list.Count)
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Index"), "index");
+ for (DictionaryNode node = list.head; node != null; node = node.next) {
+ array.SetValue(isKeys ? node.key : node.value, index);
+ index++;
+ }
+ }
+
+ int ICollection.Count {
+ get {
+ int count = 0;
+ for (DictionaryNode node = list.head; node != null; node = node.next) {
+ count++;
+ }
+ return count;
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get {
+ return false;
+ }
+ }
+
+ Object ICollection.SyncRoot {
+ get {
+ return list.SyncRoot;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new NodeKeyValueEnumerator(list, isKeys);
+ }
+
+
+ private class NodeKeyValueEnumerator: IEnumerator {
+ ListDictionaryInternal list;
+ DictionaryNode current;
+ int version;
+ bool isKeys;
+ bool start;
+
+ public NodeKeyValueEnumerator(ListDictionaryInternal list, bool isKeys) {
+ this.list = list;
+ this.isKeys = isKeys;
+ this.version = list.version;
+ this.start = true;
+ this.current = null;
+ }
+
+ public Object Current {
+ get {
+ if (current == null) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return isKeys ? current.key : current.value;
+ }
+ }
+
+ public bool MoveNext() {
+ if (version != list.version) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ }
+ if (start) {
+ current = list.head;
+ start = false;
+ }
+ else {
+ if( current != null) {
+ current = current.next;
+ }
+ }
+ return (current != null);
+ }
+
+ public void Reset() {
+ if (version != list.version) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ }
+ start = true;
+ current = null;
+ }
+ }
+ }
+
+ [Serializable]
+ private class DictionaryNode {
+ public Object key;
+ public Object value;
+ public DictionaryNode next;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs
new file mode 100644
index 0000000000..54aa7bb09d
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ObjectModel/Collection.cs
@@ -0,0 +1,328 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Collections.ObjectModel
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Runtime;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ public class Collection<T>: IList<T>, IList, IReadOnlyList<T>
+ {
+ IList<T> items;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public Collection() {
+ items = new List<T>();
+ }
+
+ public Collection(IList<T> list) {
+ if (list == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
+ }
+ items = list;
+ }
+
+ public int Count {
+ get { return items.Count; }
+ }
+
+ protected IList<T> Items {
+ get { return items; }
+ }
+
+ public T this[int index] {
+ get { return items[index]; }
+ set {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index >= items.Count) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ SetItem(index, value);
+ }
+ }
+
+ public void Add(T item) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ int index = items.Count;
+ InsertItem(index, item);
+ }
+
+ public void Clear() {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ ClearItems();
+ }
+
+ public void CopyTo(T[] array, int index) {
+ items.CopyTo(array, index);
+ }
+
+ public bool Contains(T item) {
+ return items.Contains(item);
+ }
+
+ public IEnumerator<T> GetEnumerator() {
+ return items.GetEnumerator();
+ }
+
+ public int IndexOf(T item) {
+ return items.IndexOf(item);
+ }
+
+ public void Insert(int index, T item) {
+ if (items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index > items.Count) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_ListInsert);
+ }
+
+ InsertItem(index, item);
+ }
+
+ public bool Remove(T item) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ int index = items.IndexOf(item);
+ if (index < 0) return false;
+ RemoveItem(index);
+ return true;
+ }
+
+ public void RemoveAt(int index) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if (index < 0 || index >= items.Count) {
+ ThrowHelper.ThrowArgumentOutOfRange_IndexException();
+ }
+
+ RemoveItem(index);
+ }
+
+ protected virtual void ClearItems() {
+ items.Clear();
+ }
+
+ protected virtual void InsertItem(int index, T item) {
+ items.Insert(index, item);
+ }
+
+ protected virtual void RemoveItem(int index) {
+ items.RemoveAt(index);
+ }
+
+ protected virtual void SetItem(int index, T item) {
+ items[index] = item;
+ }
+
+ bool ICollection<T>.IsReadOnly {
+ get {
+ return items.IsReadOnly;
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return ((IEnumerable)items).GetEnumerator();
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ ICollection c = items as ICollection;
+ if( c != null) {
+ _syncRoot = c.SyncRoot;
+ }
+ else {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ }
+ return _syncRoot;
+ }
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if( array.GetLowerBound(0) != 0 ) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0 ) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ T[] tArray = array as T[];
+ if (tArray != null) {
+ items.CopyTo(tArray , index);
+ }
+ else {
+ //
+ // Catch the obvious case assignment will fail.
+ // We can found all possible problems by doing the check though.
+ // For example, if the element type of the Array is derived from T,
+ // we can't figure out if we can successfully copy the element beforehand.
+ //
+ Type targetType = array.GetType().GetElementType();
+ Type sourceType = typeof(T);
+ if(!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ //
+ // We can't cast array of value type to object[], so we don't support
+ // widening of primitive types here.
+ //
+ object[] objects = array as object[];
+ if( objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ int count = items.Count;
+ try {
+ for (int i = 0; i < count; i++) {
+ objects[index++] = items[i];
+ }
+ }
+ catch(ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ object IList.this[int index] {
+ get { return items[index]; }
+ set {
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try {
+ this[index] = (T)value;
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+
+ }
+ }
+
+ bool IList.IsReadOnly {
+ get {
+ return items.IsReadOnly;
+ }
+ }
+
+ bool IList.IsFixedSize {
+ get {
+ // There is no IList<T>.IsFixedSize, so we must assume that only
+ // readonly collections are fixed size, if our internal item
+ // collection does not implement IList. Note that Array implements
+ // IList, and therefore T[] and U[] will be fixed-size.
+ IList list = items as IList;
+ if(list != null)
+ {
+ return list.IsFixedSize;
+ }
+ return items.IsReadOnly;
+ }
+ }
+
+ int IList.Add(object value) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try {
+ Add((T)value);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+
+ return this.Count - 1;
+ }
+
+ bool IList.Contains(object value) {
+ if(IsCompatibleObject(value)) {
+ return Contains((T) value);
+ }
+ return false;
+ }
+
+ int IList.IndexOf(object value) {
+ if(IsCompatibleObject(value)) {
+ return IndexOf((T)value);
+ }
+ return -1;
+ }
+
+ void IList.Insert(int index, object value) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ try {
+ Insert(index, (T)value);
+ }
+ catch (InvalidCastException) {
+ ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
+ }
+
+ }
+
+ void IList.Remove(object value) {
+ if( items.IsReadOnly) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ if(IsCompatibleObject(value)) {
+ Remove((T) value);
+ }
+ }
+
+ private static bool IsCompatibleObject(object value) {
+ // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ return ((value is T) || (value == null && default(T) == null));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs b/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs
new file mode 100644
index 0000000000..7313d71950
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ObjectModel/KeyedCollection.cs
@@ -0,0 +1,245 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Collections.ObjectModel
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [DebuggerTypeProxy(typeof(Mscorlib_KeyedCollectionDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ public abstract class KeyedCollection<TKey,TItem>: Collection<TItem>
+ {
+ const int defaultThreshold = 0;
+
+ IEqualityComparer<TKey> comparer;
+ Dictionary<TKey,TItem> dict;
+ int keyCount;
+ int threshold;
+
+ protected KeyedCollection(): this(null, defaultThreshold) {}
+
+ protected KeyedCollection(IEqualityComparer<TKey> comparer): this(comparer, defaultThreshold) {}
+
+
+ protected KeyedCollection(IEqualityComparer<TKey> comparer, int dictionaryCreationThreshold)
+ : base(new List<TItem>()) { // Be explicit about the use of List<T> so we can foreach over
+ // Items internally without enumerator allocations.
+ if (comparer == null) {
+ comparer = EqualityComparer<TKey>.Default;
+ }
+
+ if (dictionaryCreationThreshold == -1) {
+ dictionaryCreationThreshold = int.MaxValue;
+ }
+
+ if( dictionaryCreationThreshold < -1) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.dictionaryCreationThreshold, ExceptionResource.ArgumentOutOfRange_InvalidThreshold);
+ }
+
+ this.comparer = comparer;
+ this.threshold = dictionaryCreationThreshold;
+ }
+
+ /// <summary>
+ /// Enables the use of foreach internally without allocations using <see cref="List{T}"/>'s struct enumerator.
+ /// </summary>
+ new private List<TItem> Items {
+ get {
+ Contract.Assert(base.Items is List<TItem>);
+
+ return (List<TItem>)base.Items;
+ }
+ }
+
+ public IEqualityComparer<TKey> Comparer {
+ get {
+ return comparer;
+ }
+ }
+
+ public TItem this[TKey key] {
+ get {
+ if( key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (dict != null) {
+ return dict[key];
+ }
+
+ foreach (TItem item in Items) {
+ if (comparer.Equals(GetKeyForItem(item), key)) return item;
+ }
+
+ ThrowHelper.ThrowKeyNotFoundException();
+ return default(TItem);
+ }
+ }
+
+ public bool Contains(TKey key) {
+ if( key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (dict != null) {
+ return dict.ContainsKey(key);
+ }
+
+ foreach (TItem item in Items) {
+ if (comparer.Equals(GetKeyForItem(item), key)) return true;
+ }
+ return false;
+ }
+
+ private bool ContainsItem(TItem item) {
+ TKey key;
+ if( (dict == null) || ((key = GetKeyForItem(item)) == null)) {
+ return Items.Contains(item);
+ }
+
+ TItem itemInDict;
+ bool exist = dict.TryGetValue(key, out itemInDict);
+ if( exist) {
+ return EqualityComparer<TItem>.Default.Equals(itemInDict, item);
+ }
+ return false;
+ }
+
+ public bool Remove(TKey key) {
+ if( key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ if (dict != null) {
+ if (dict.ContainsKey(key)) {
+ return Remove(dict[key]);
+ }
+
+ return false;
+ }
+
+ for (int i = 0; i < Items.Count; i++) {
+ if (comparer.Equals(GetKeyForItem(Items[i]), key)) {
+ RemoveItem(i);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected IDictionary<TKey,TItem> Dictionary {
+ get { return dict; }
+ }
+
+ protected void ChangeItemKey(TItem item, TKey newKey) {
+ // check if the item exists in the collection
+ if( !ContainsItem(item)) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_ItemNotExist);
+ }
+
+ TKey oldKey = GetKeyForItem(item);
+ if (!comparer.Equals(oldKey, newKey)) {
+ if (newKey != null) {
+ AddKey(newKey, item);
+ }
+
+ if (oldKey != null) {
+ RemoveKey(oldKey);
+ }
+ }
+ }
+
+ protected override void ClearItems() {
+ base.ClearItems();
+ if (dict != null) {
+ dict.Clear();
+ }
+
+ keyCount = 0;
+ }
+
+ protected abstract TKey GetKeyForItem(TItem item);
+
+ protected override void InsertItem(int index, TItem item) {
+ TKey key = GetKeyForItem(item);
+ if (key != null) {
+ AddKey(key, item);
+ }
+ base.InsertItem(index, item);
+ }
+
+ protected override void RemoveItem(int index) {
+ TKey key = GetKeyForItem(Items[index]);
+ if (key != null) {
+ RemoveKey(key);
+ }
+ base.RemoveItem(index);
+ }
+
+ protected override void SetItem(int index, TItem item) {
+ TKey newKey = GetKeyForItem(item);
+ TKey oldKey = GetKeyForItem(Items[index]);
+
+ if (comparer.Equals(oldKey, newKey)) {
+ if (newKey != null && dict != null) {
+ dict[newKey] = item;
+ }
+ }
+ else {
+ if (newKey != null) {
+ AddKey(newKey, item);
+ }
+
+ if (oldKey != null) {
+ RemoveKey(oldKey);
+ }
+ }
+ base.SetItem(index, item);
+ }
+
+ private void AddKey(TKey key, TItem item) {
+ if (dict != null) {
+ dict.Add(key, item);
+ }
+ else if (keyCount == threshold) {
+ CreateDictionary();
+ dict.Add(key, item);
+ }
+ else {
+ if (Contains(key)) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
+ }
+
+ keyCount++;
+ }
+ }
+
+ private void CreateDictionary() {
+ dict = new Dictionary<TKey,TItem>(comparer);
+ foreach (TItem item in Items) {
+ TKey key = GetKeyForItem(item);
+ if (key != null) {
+ dict.Add(key, item);
+ }
+ }
+ }
+
+ private void RemoveKey(TKey key) {
+ Contract.Assert(key != null, "key shouldn't be null!");
+ if (dict != null) {
+ dict.Remove(key);
+ }
+ else {
+ keyCount--;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
new file mode 100644
index 0000000000..ec7149e4f5
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs
@@ -0,0 +1,232 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Collections.ObjectModel
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Runtime;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ public class ReadOnlyCollection<T>: IList<T>, IList, IReadOnlyList<T>
+ {
+ IList<T> list;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ public ReadOnlyCollection(IList<T> list) {
+ if (list == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.list);
+ }
+ this.list = list;
+ }
+
+ public int Count {
+ get { return list.Count; }
+ }
+
+ public T this[int index] {
+ get { return list[index]; }
+ }
+
+ public bool Contains(T value) {
+ return list.Contains(value);
+ }
+
+ public void CopyTo(T[] array, int index) {
+ list.CopyTo(array, index);
+ }
+
+ public IEnumerator<T> GetEnumerator() {
+ return list.GetEnumerator();
+ }
+
+ public int IndexOf(T value) {
+ return list.IndexOf(value);
+ }
+
+ protected IList<T> Items {
+ get {
+ return list;
+ }
+ }
+
+ bool ICollection<T>.IsReadOnly {
+ get { return true; }
+ }
+
+ T IList<T>.this[int index] {
+ get { return list[index]; }
+ set {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ void ICollection<T>.Add(T value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void ICollection<T>.Clear() {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList<T>.Insert(int index, T value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool ICollection<T>.Remove(T value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ void IList<T>.RemoveAt(int index) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ IEnumerator IEnumerable.GetEnumerator() {
+ return ((IEnumerable)list).GetEnumerator();
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ ICollection c = list as ICollection;
+ if( c != null) {
+ _syncRoot = c.SyncRoot;
+ }
+ else {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ }
+ return _syncRoot;
+ }
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array==null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if( array.GetLowerBound(0) != 0 ) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ T[] items = array as T[];
+ if (items != null) {
+ list.CopyTo(items, index);
+ }
+ else {
+ //
+ // Catch the obvious case assignment will fail.
+ // We can found all possible problems by doing the check though.
+ // For example, if the element type of the Array is derived from T,
+ // we can't figure out if we can successfully copy the element beforehand.
+ //
+ Type targetType = array.GetType().GetElementType();
+ Type sourceType = typeof(T);
+ if(!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ //
+ // We can't cast array of value type to object[], so we don't support
+ // widening of primitive types here.
+ //
+ object[] objects = array as object[];
+ if( objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ int count = list.Count;
+ try {
+ for (int i = 0; i < count; i++) {
+ objects[index++] = list[i];
+ }
+ }
+ catch(ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ bool IList.IsFixedSize {
+ get { return true; }
+ }
+
+ bool IList.IsReadOnly {
+ get { return true; }
+ }
+
+ object IList.this[int index] {
+ get { return list[index]; }
+ set {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ int IList.Add(object value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return -1;
+ }
+
+ void IList.Clear() {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ private static bool IsCompatibleObject(object value) {
+ // Non-null values are fine. Only accept nulls if T is a class or Nullable<U>.
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ return ((value is T) || (value == null && default(T) == null));
+ }
+
+ bool IList.Contains(object value) {
+ if(IsCompatibleObject(value)) {
+ return Contains((T) value);
+ }
+ return false;
+ }
+
+ int IList.IndexOf(object value) {
+ if(IsCompatibleObject(value)) {
+ return IndexOf((T)value);
+ }
+ return -1;
+ }
+
+ void IList.Insert(int index, object value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList.Remove(object value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IList.RemoveAt(int index) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs
new file mode 100644
index 0000000000..11833c2c1b
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs
@@ -0,0 +1,625 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Read-only wrapper for another generic dictionary.
+**
+===========================================================*/
+
+namespace System.Collections.ObjectModel
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [DebuggerTypeProxy(typeof(Mscorlib_DictionaryDebugView<,>))]
+ [DebuggerDisplay("Count = {Count}")]
+ public class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, IReadOnlyDictionary<TKey, TValue>
+ {
+ private readonly IDictionary<TKey, TValue> m_dictionary;
+ [NonSerialized]
+ private Object m_syncRoot;
+ [NonSerialized]
+ private KeyCollection m_keys;
+ [NonSerialized]
+ private ValueCollection m_values;
+
+ public ReadOnlyDictionary(IDictionary<TKey, TValue> dictionary) {
+ if (dictionary == null) {
+ throw new ArgumentNullException("dictionary");
+ }
+ Contract.EndContractBlock();
+ m_dictionary = dictionary;
+ }
+
+ protected IDictionary<TKey, TValue> Dictionary {
+ get { return m_dictionary; }
+ }
+
+ public KeyCollection Keys {
+ get {
+ Contract.Ensures(Contract.Result<KeyCollection>() != null);
+ if (m_keys == null) {
+ m_keys = new KeyCollection(m_dictionary.Keys);
+ }
+ return m_keys;
+ }
+ }
+
+ public ValueCollection Values {
+ get {
+ Contract.Ensures(Contract.Result<ValueCollection>() != null);
+ if (m_values == null) {
+ m_values = new ValueCollection(m_dictionary.Values);
+ }
+ return m_values;
+ }
+ }
+
+ #region IDictionary<TKey, TValue> Members
+
+ public bool ContainsKey(TKey key) {
+ return m_dictionary.ContainsKey(key);
+ }
+
+ ICollection<TKey> IDictionary<TKey, TValue>.Keys {
+ get {
+ return Keys;
+ }
+ }
+
+ public bool TryGetValue(TKey key, out TValue value) {
+ return m_dictionary.TryGetValue(key, out value);
+ }
+
+ ICollection<TValue> IDictionary<TKey, TValue>.Values {
+ get {
+ return Values;
+ }
+ }
+
+ public TValue this[TKey key] {
+ get {
+ return m_dictionary[key];
+ }
+ }
+
+ void IDictionary<TKey, TValue>.Add(TKey key, TValue value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool IDictionary<TKey, TValue>.Remove(TKey key) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ TValue IDictionary<TKey, TValue>.this[TKey key] {
+ get {
+ return m_dictionary[key];
+ }
+ set {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ #endregion
+
+ #region ICollection<KeyValuePair<TKey, TValue>> Members
+
+ public int Count {
+ get { return m_dictionary.Count; }
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) {
+ return m_dictionary.Contains(item);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
+ m_dictionary.CopyTo(array, arrayIndex);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void ICollection<KeyValuePair<TKey, TValue>>.Clear() {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ #endregion
+
+ #region IEnumerable<KeyValuePair<TKey, TValue>> Members
+
+ public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() {
+ return m_dictionary.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return ((IEnumerable)m_dictionary).GetEnumerator();
+ }
+
+ #endregion
+
+ #region IDictionary Members
+
+ private static bool IsCompatibleKey(object key) {
+ if (key == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+ return key is TKey;
+ }
+
+ void IDictionary.Add(object key, object value) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void IDictionary.Clear() {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool IDictionary.Contains(object key) {
+ return IsCompatibleKey(key) && ContainsKey((TKey)key);
+ }
+
+ IDictionaryEnumerator IDictionary.GetEnumerator() {
+ IDictionary d = m_dictionary as IDictionary;
+ if (d != null) {
+ return d.GetEnumerator();
+ }
+ return new DictionaryEnumerator(m_dictionary);
+ }
+
+ bool IDictionary.IsFixedSize {
+ get { return true; }
+ }
+
+ bool IDictionary.IsReadOnly {
+ get { return true; }
+ }
+
+ ICollection IDictionary.Keys {
+ get {
+ return Keys;
+ }
+ }
+
+ void IDictionary.Remove(object key) {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ ICollection IDictionary.Values {
+ get {
+ return Values;
+ }
+ }
+
+ object IDictionary.this[object key] {
+ get {
+ if (IsCompatibleKey(key)) {
+ return this[(TKey)key];
+ }
+ return null;
+ }
+ set {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+ }
+
+ void ICollection.CopyTo(Array array, int index) {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if (array.GetLowerBound(0) != 0) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0 || index > array.Length) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ KeyValuePair<TKey, TValue>[] pairs = array as KeyValuePair<TKey, TValue>[];
+ if (pairs != null) {
+ m_dictionary.CopyTo(pairs, index);
+ }
+ else {
+ DictionaryEntry[] dictEntryArray = array as DictionaryEntry[];
+ if (dictEntryArray != null) {
+ foreach (var item in m_dictionary) {
+ dictEntryArray[index++] = new DictionaryEntry(item.Key, item.Value);
+ }
+ }
+ else {
+ object[] objects = array as object[];
+ if (objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ try {
+ foreach (var item in m_dictionary) {
+ objects[index++] = new KeyValuePair<TKey, TValue>(item.Key, item.Value);
+ }
+ }
+ catch (ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if (m_syncRoot == null) {
+ ICollection c = m_dictionary as ICollection;
+ if (c != null) {
+ m_syncRoot = c.SyncRoot;
+ }
+ else {
+ System.Threading.Interlocked.CompareExchange<Object>(ref m_syncRoot, new Object(), null);
+ }
+ }
+ return m_syncRoot;
+ }
+ }
+
+ [Serializable]
+ private struct DictionaryEnumerator : IDictionaryEnumerator {
+ private readonly IDictionary<TKey, TValue> m_dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> m_enumerator;
+
+ public DictionaryEnumerator(IDictionary<TKey, TValue> dictionary) {
+ m_dictionary = dictionary;
+ m_enumerator = m_dictionary.GetEnumerator();
+ }
+
+ public DictionaryEntry Entry {
+ get { return new DictionaryEntry(m_enumerator.Current.Key, m_enumerator.Current.Value); }
+ }
+
+ public object Key {
+ get { return m_enumerator.Current.Key; }
+ }
+
+ public object Value {
+ get { return m_enumerator.Current.Value; }
+ }
+
+ public object Current {
+ get { return Entry; }
+ }
+
+ public bool MoveNext() {
+ return m_enumerator.MoveNext();
+ }
+
+ public void Reset() {
+ m_enumerator.Reset();
+ }
+ }
+
+ #endregion
+
+ #region IReadOnlyDictionary members
+
+ IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys {
+ get {
+ return Keys;
+ }
+ }
+
+ IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values {
+ get {
+ return Values;
+ }
+ }
+
+ #endregion IReadOnlyDictionary members
+
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ public sealed class KeyCollection : ICollection<TKey>, ICollection, IReadOnlyCollection<TKey> {
+ private readonly ICollection<TKey> m_collection;
+ [NonSerialized]
+ private Object m_syncRoot;
+
+ internal KeyCollection(ICollection<TKey> collection)
+ {
+ if (collection == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+ }
+ m_collection = collection;
+ }
+
+ #region ICollection<T> Members
+
+ void ICollection<TKey>.Add(TKey item)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void ICollection<TKey>.Clear()
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool ICollection<TKey>.Contains(TKey item)
+ {
+ return m_collection.Contains(item);
+ }
+
+ public void CopyTo(TKey[] array, int arrayIndex)
+ {
+ m_collection.CopyTo(array, arrayIndex);
+ }
+
+ public int Count {
+ get { return m_collection.Count; }
+ }
+
+ bool ICollection<TKey>.IsReadOnly {
+ get { return true; }
+ }
+
+ bool ICollection<TKey>.Remove(TKey item)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ #endregion
+
+ #region IEnumerable<T> Members
+
+ public IEnumerator<TKey> GetEnumerator()
+ {
+ return m_collection.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return ((IEnumerable)m_collection).GetEnumerator();
+ }
+
+ #endregion
+
+ #region ICollection Members
+
+ void ICollection.CopyTo(Array array, int index) {
+ ReadOnlyDictionaryHelpers.CopyToNonGenericICollectionHelper<TKey>(m_collection, array, index);
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if (m_syncRoot == null) {
+ ICollection c = m_collection as ICollection;
+ if (c != null) {
+ m_syncRoot = c.SyncRoot;
+ }
+ else {
+ System.Threading.Interlocked.CompareExchange<Object>(ref m_syncRoot, new Object(), null);
+ }
+ }
+ return m_syncRoot;
+ }
+ }
+
+ #endregion
+ }
+
+ [DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))]
+ [DebuggerDisplay("Count = {Count}")]
+ [Serializable]
+ public sealed class ValueCollection : ICollection<TValue>, ICollection, IReadOnlyCollection<TValue> {
+ private readonly ICollection<TValue> m_collection;
+ [NonSerialized]
+ private Object m_syncRoot;
+
+ internal ValueCollection(ICollection<TValue> collection)
+ {
+ if (collection == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
+ }
+ m_collection = collection;
+ }
+
+ #region ICollection<T> Members
+
+ void ICollection<TValue>.Add(TValue item)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ void ICollection<TValue>.Clear()
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ }
+
+ bool ICollection<TValue>.Contains(TValue item)
+ {
+ return m_collection.Contains(item);
+ }
+
+ public void CopyTo(TValue[] array, int arrayIndex)
+ {
+ m_collection.CopyTo(array, arrayIndex);
+ }
+
+ public int Count {
+ get { return m_collection.Count; }
+ }
+
+ bool ICollection<TValue>.IsReadOnly {
+ get { return true; }
+ }
+
+ bool ICollection<TValue>.Remove(TValue item)
+ {
+ ThrowHelper.ThrowNotSupportedException(ExceptionResource.NotSupported_ReadOnlyCollection);
+ return false;
+ }
+
+ #endregion
+
+ #region IEnumerable<T> Members
+
+ public IEnumerator<TValue> GetEnumerator()
+ {
+ return m_collection.GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return ((IEnumerable)m_collection).GetEnumerator();
+ }
+
+ #endregion
+
+ #region ICollection Members
+
+ void ICollection.CopyTo(Array array, int index) {
+ ReadOnlyDictionaryHelpers.CopyToNonGenericICollectionHelper<TValue>(m_collection, array, index);
+ }
+
+ bool ICollection.IsSynchronized {
+ get { return false; }
+ }
+
+ object ICollection.SyncRoot {
+ get {
+ if (m_syncRoot == null) {
+ ICollection c = m_collection as ICollection;
+ if (c != null) {
+ m_syncRoot = c.SyncRoot;
+ }
+ else {
+ System.Threading.Interlocked.CompareExchange<Object>(ref m_syncRoot, new Object(), null);
+ }
+ }
+ return m_syncRoot;
+ }
+ }
+
+ #endregion ICollection Members
+ }
+ }
+
+ // To share code when possible, use a non-generic class to get rid of irrelevant type parameters.
+ internal static class ReadOnlyDictionaryHelpers
+ {
+ #region Helper method for our KeyCollection and ValueCollection
+
+ // Abstracted away to avoid redundant implementations.
+ internal static void CopyToNonGenericICollectionHelper<T>(ICollection<T> collection, Array array, int index)
+ {
+ if (array == null) {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
+ }
+
+ if (array.Rank != 1) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported);
+ }
+
+ if (array.GetLowerBound(0) != 0) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_NonZeroLowerBound);
+ }
+
+ if (index < 0) {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.arrayIndex, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+ }
+
+ if (array.Length - index < collection.Count) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
+ }
+
+ // Easy out if the ICollection<T> implements the non-generic ICollection
+ ICollection nonGenericCollection = collection as ICollection;
+ if (nonGenericCollection != null) {
+ nonGenericCollection.CopyTo(array, index);
+ return;
+ }
+
+ T[] items = array as T[];
+ if (items != null) {
+ collection.CopyTo(items, index);
+ }
+ else {
+ //
+ // Catch the obvious case assignment will fail.
+ // We can found all possible problems by doing the check though.
+ // For example, if the element type of the Array is derived from T,
+ // we can't figure out if we can successfully copy the element beforehand.
+ //
+ Type targetType = array.GetType().GetElementType();
+ Type sourceType = typeof(T);
+ if (!(targetType.IsAssignableFrom(sourceType) || sourceType.IsAssignableFrom(targetType))) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ //
+ // We can't cast array of value type to object[], so we don't support
+ // widening of primitive types here.
+ //
+ object[] objects = array as object[];
+ if (objects == null) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+
+ try {
+ foreach (var item in collection) {
+ objects[index++] = item;
+ }
+ }
+ catch (ArrayTypeMismatchException) {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidArrayType);
+ }
+ }
+ }
+
+ #endregion Helper method for our KeyCollection and ValueCollection
+ }
+}
+
diff --git a/src/mscorlib/src/System/Collections/SortedList.cs b/src/mscorlib/src/System/Collections/SortedList.cs
new file mode 100644
index 0000000000..8e3926af01
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/SortedList.cs
@@ -0,0 +1,1011 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: A sorted dictionary.
+**
+**
+===========================================================*/
+namespace System.Collections {
+ using System;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+
+ // The SortedList class implements a sorted list of keys and values. Entries in
+ // a sorted list are sorted by their keys and are accessible both by key and by
+ // index. The keys of a sorted list can be ordered either according to a
+ // specific IComparer implementation given when the sorted list is
+ // instantiated, or according to the IComparable implementation provided
+ // by the keys themselves. In either case, a sorted list does not allow entries
+ // with duplicate keys.
+ //
+ // A sorted list internally maintains two arrays that store the keys and
+ // values of the entries. The capacity of a sorted list is the allocated
+ // length of these internal arrays. As elements are added to a sorted list, the
+ // capacity of the sorted list is automatically increased as required by
+ // reallocating the internal arrays. The capacity is never automatically
+ // decreased, but users can call either TrimToSize or
+ // Capacity explicitly.
+ //
+ // The GetKeyList and GetValueList methods of a sorted list
+ // provides access to the keys and values of the sorted list in the form of
+ // List implementations. The List objects returned by these
+ // methods are aliases for the underlying sorted list, so modifications
+ // made to those lists are directly reflected in the sorted list, and vice
+ // versa.
+ //
+ // The SortedList class provides a convenient way to create a sorted
+ // copy of another dictionary, such as a Hashtable. For example:
+ //
+ // Hashtable h = new Hashtable();
+ // h.Add(...);
+ // h.Add(...);
+ // ...
+ // SortedList s = new SortedList(h);
+ //
+ // The last line above creates a sorted list that contains a copy of the keys
+ // and values stored in the hashtable. In this particular example, the keys
+ // will be ordered according to the IComparable interface, which they
+ // all must implement. To impose a different ordering, SortedList also
+ // has a constructor that allows a specific IComparer implementation to
+ // be specified.
+ //
+ [DebuggerTypeProxy(typeof(System.Collections.SortedList.SortedListDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ [Obsolete("Non-generic collections have been deprecated. Please use collections in System.Collections.Generic.")]
+#endif
+ [Serializable]
+ public class SortedList : IDictionary, ICloneable
+ {
+ private Object[] keys;
+ private Object[] values;
+ private int _size;
+ private int version;
+ private IComparer comparer;
+ private KeyList keyList;
+ private ValueList valueList;
+ [NonSerialized]
+ private Object _syncRoot;
+
+ private const int _defaultCapacity = 16;
+
+ private static Object[] emptyArray = EmptyArray<Object>.Value;
+
+ // Constructs a new sorted list. The sorted list is initially empty and has
+ // a capacity of zero. Upon adding the first element to the sorted list the
+ // capacity is increased to 16, and then increased in multiples of two as
+ // required. The elements of the sorted list are ordered according to the
+ // IComparable interface, which must be implemented by the keys of
+ // all entries added to the sorted list.
+ public SortedList() {
+ Init();
+ }
+ private void Init()
+ {
+ keys = emptyArray;
+ values = emptyArray;
+ _size = 0;
+ comparer = new Comparer(CultureInfo.CurrentCulture);
+ }
+
+ // Constructs a new sorted list. The sorted list is initially empty and has
+ // a capacity of zero. Upon adding the first element to the sorted list the
+ // capacity is increased to 16, and then increased in multiples of two as
+ // required. The elements of the sorted list are ordered according to the
+ // IComparable interface, which must be implemented by the keys of
+ // all entries added to the sorted list.
+ //
+ public SortedList(int initialCapacity) {
+ if (initialCapacity < 0)
+ throw new ArgumentOutOfRangeException("initialCapacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ keys = new Object[initialCapacity];
+ values = new Object[initialCapacity];
+ comparer = new Comparer(CultureInfo.CurrentCulture);
+ }
+
+ // Constructs a new sorted list with a given IComparer
+ // implementation. The sorted list is initially empty and has a capacity of
+ // zero. Upon adding the first element to the sorted list the capacity is
+ // increased to 16, and then increased in multiples of two as required. The
+ // elements of the sorted list are ordered according to the given
+ // IComparer implementation. If comparer is null, the
+ // elements are compared to each other using the IComparable
+ // interface, which in that case must be implemented by the keys of all
+ // entries added to the sorted list.
+ //
+ public SortedList(IComparer comparer)
+ : this() {
+ if (comparer != null) this.comparer = comparer;
+ }
+
+ // Constructs a new sorted list with a given IComparer
+ // implementation and a given initial capacity. The sorted list is
+ // initially empty, but will have room for the given number of elements
+ // before any reallocations are required. The elements of the sorted list
+ // are ordered according to the given IComparer implementation. If
+ // comparer is null, the elements are compared to each other using
+ // the IComparable interface, which in that case must be implemented
+ // by the keys of all entries added to the sorted list.
+ //
+ public SortedList(IComparer comparer, int capacity)
+ : this(comparer) {
+ Capacity = capacity;
+ }
+
+ // Constructs a new sorted list containing a copy of the entries in the
+ // given dictionary. The elements of the sorted list are ordered according
+ // to the IComparable interface, which must be implemented by the
+ // keys of all entries in the the given dictionary as well as keys
+ // subsequently added to the sorted list.
+ //
+ public SortedList(IDictionary d)
+ : this(d, null) {
+ }
+
+ // Constructs a new sorted list containing a copy of the entries in the
+ // given dictionary. The elements of the sorted list are ordered according
+ // to the given IComparer implementation. If comparer is
+ // null, the elements are compared to each other using the
+ // IComparable interface, which in that case must be implemented
+ // by the keys of all entries in the the given dictionary as well as keys
+ // subsequently added to the sorted list.
+ //
+ public SortedList(IDictionary d, IComparer comparer)
+ : this(comparer, (d != null ? d.Count : 0)) {
+ if (d==null)
+ throw new ArgumentNullException("d", Environment.GetResourceString("ArgumentNull_Dictionary"));
+ Contract.EndContractBlock();
+ d.Keys.CopyTo(keys, 0);
+ d.Values.CopyTo(values, 0);
+ Array.Sort(keys, values, comparer);
+ _size = d.Count;
+ }
+
+ // Adds an entry with the given key and value to this sorted list. An
+ // ArgumentException is thrown if the key is already present in the sorted list.
+ //
+ public virtual void Add(Object key, Object value) {
+ if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int i = Array.BinarySearch(keys, 0, _size, key, comparer);
+ if (i >= 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate__", GetKey(i), key));
+ Insert(~i, key, value);
+ }
+
+ // Returns the capacity of this sorted list. The capacity of a sorted list
+ // represents the allocated length of the internal arrays used to store the
+ // keys and values of the list, and thus also indicates the maximum number
+ // of entries the list can contain before a reallocation of the internal
+ // arrays is required.
+ //
+ public virtual int Capacity {
+ get {
+ return keys.Length;
+ }
+ set {
+ if (value < Count) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ if (value != keys.Length) {
+ if (value > 0) {
+ Object[] newKeys = new Object[value];
+ Object[] newValues = new Object[value];
+ if (_size > 0) {
+ Array.Copy(keys, 0, newKeys, 0, _size);
+ Array.Copy(values, 0, newValues, 0, _size);
+ }
+ keys = newKeys;
+ values = newValues;
+ }
+ else {
+ // size can only be zero here.
+ Contract.Assert( _size == 0, "Size is not zero");
+ keys = emptyArray;
+ values = emptyArray;
+ }
+ }
+ }
+ }
+
+ // Returns the number of entries in this sorted list.
+ //
+ public virtual int Count {
+ get {
+ return _size;
+ }
+ }
+
+ // Returns a collection representing the keys of this sorted list. This
+ // method returns the same object as GetKeyList, but typed as an
+ // ICollection instead of an IList.
+ //
+ public virtual ICollection Keys {
+ get {
+ return GetKeyList();
+ }
+ }
+
+ // Returns a collection representing the values of this sorted list. This
+ // method returns the same object as GetValueList, but typed as an
+ // ICollection instead of an IList.
+ //
+ public virtual ICollection Values {
+ get {
+ return GetValueList();
+ }
+ }
+
+ // Is this SortedList read-only?
+ public virtual bool IsReadOnly {
+ get { return false; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return false; }
+ }
+
+ // Is this SortedList synchronized (thread-safe)?
+ public virtual bool IsSynchronized {
+ get { return false; }
+ }
+
+ // Synchronization root for this object.
+ public virtual Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Removes all entries from this sorted list.
+ public virtual void Clear() {
+ // clear does not change the capacity
+ version++;
+ Array.Clear(keys, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ Array.Clear(values, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ _size = 0;
+
+ }
+
+ // Makes a virtually identical copy of this SortedList. This is a shallow
+ // copy. IE, the Objects in the SortedList are not cloned - we copy the
+ // references to those objects.
+ public virtual Object Clone()
+ {
+ SortedList sl = new SortedList(_size);
+ Array.Copy(keys, 0, sl.keys, 0, _size);
+ Array.Copy(values, 0, sl.values, 0, _size);
+ sl._size = _size;
+ sl.version = version;
+ sl.comparer = comparer;
+ // Don't copy keyList nor valueList.
+ return sl;
+ }
+
+
+ // Checks if this sorted list contains an entry with the given key.
+ //
+ public virtual bool Contains(Object key) {
+ return IndexOfKey(key) >= 0;
+ }
+
+ // Checks if this sorted list contains an entry with the given key.
+ //
+ public virtual bool ContainsKey(Object key) {
+ // Yes, this is a SPEC'ed duplicate of Contains().
+ return IndexOfKey(key) >= 0;
+ }
+
+ // Checks if this sorted list contains an entry with the given value. The
+ // values of the entries of the sorted list are compared to the given value
+ // using the Object.Equals method. This method performs a linear
+ // search and is substantially slower than the Contains
+ // method.
+ //
+ public virtual bool ContainsValue(Object value) {
+ return IndexOfValue(value) >= 0;
+ }
+
+ // Copies the values in this SortedList to an array.
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Array"));
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - arrayIndex < Count)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayPlusOffTooSmall"));
+ Contract.EndContractBlock();
+ for (int i = 0; i<Count; i++) {
+ DictionaryEntry entry = new DictionaryEntry(keys[i],values[i]);
+ array.SetValue(entry, i + arrayIndex);
+ }
+ }
+
+ // Copies the values in this SortedList to an KeyValuePairs array.
+ // KeyValuePairs is different from Dictionary Entry in that it has special
+ // debugger attributes on its fields.
+
+ internal virtual KeyValuePairs[] ToKeyValuePairsArray() {
+ KeyValuePairs[] array = new KeyValuePairs[Count];
+ for (int i = 0; i < Count; i++) {
+ array[i] = new KeyValuePairs(keys[i],values[i]);
+ }
+ return array;
+ }
+
+ // Ensures that the capacity of this sorted list is at least the given
+ // minimum value. If the currect capacity of the list is less than
+ // min, the capacity is increased to twice the current capacity or
+ // to min, whichever is larger.
+ private void EnsureCapacity(int min) {
+ int newCapacity = keys.Length == 0? 16: keys.Length * 2;
+ // Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow.
+ // Note that this check works even when _items.Length overflowed thanks to the (uint) cast
+ if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength;
+ if (newCapacity < min) newCapacity = min;
+ Capacity = newCapacity;
+ }
+
+ // Returns the value of the entry at the given index.
+ //
+ public virtual Object GetByIndex(int index) {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return values[index];
+ }
+
+ // Returns an IEnumerator for this sorted list. If modifications
+ // made to the sorted list while an enumeration is in progress,
+ // the MoveNext and Remove methods
+ // of the enumerator will throw an exception.
+ //
+ IEnumerator IEnumerable.GetEnumerator() {
+ return new SortedListEnumerator(this, 0, _size, SortedListEnumerator.DictEntry);
+ }
+
+ // Returns an IDictionaryEnumerator for this sorted list. If modifications
+ // made to the sorted list while an enumeration is in progress,
+ // the MoveNext and Remove methods
+ // of the enumerator will throw an exception.
+ //
+ public virtual IDictionaryEnumerator GetEnumerator() {
+ return new SortedListEnumerator(this, 0, _size, SortedListEnumerator.DictEntry);
+ }
+
+ // Returns the key of the entry at the given index.
+ //
+ public virtual Object GetKey(int index) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ return keys[index];
+ }
+
+ // Returns an IList representing the keys of this sorted list. The
+ // returned list is an alias for the keys of this sorted list, so
+ // modifications made to the returned list are directly reflected in the
+ // underlying sorted list, and vice versa. The elements of the returned
+ // list are ordered in the same way as the elements of the sorted list. The
+ // returned list does not support adding, inserting, or modifying elements
+ // (the Add, AddRange, Insert, InsertRange,
+ // Reverse, Set, SetRange, and Sort methods
+ // throw exceptions), but it does allow removal of elements (through the
+ // Remove and RemoveRange methods or through an enumerator).
+ // Null is an invalid key value.
+ //
+ public virtual IList GetKeyList() {
+ if (keyList == null) keyList = new KeyList(this);
+ return keyList;
+ }
+
+ // Returns an IList representing the values of this sorted list. The
+ // returned list is an alias for the values of this sorted list, so
+ // modifications made to the returned list are directly reflected in the
+ // underlying sorted list, and vice versa. The elements of the returned
+ // list are ordered in the same way as the elements of the sorted list. The
+ // returned list does not support adding or inserting elements (the
+ // Add, AddRange, Insert and InsertRange
+ // methods throw exceptions), but it does allow modification and removal of
+ // elements (through the Remove, RemoveRange, Set and
+ // SetRange methods or through an enumerator).
+ //
+ public virtual IList GetValueList() {
+ if (valueList == null) valueList = new ValueList(this);
+ return valueList;
+ }
+
+ // Returns the value associated with the given key. If an entry with the
+ // given key is not found, the returned value is null.
+ //
+ public virtual Object this[Object key] {
+ get {
+ int i = IndexOfKey(key);
+ if (i >= 0) return values[i];
+ return null;
+ }
+ set {
+ if (key == null) throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int i = Array.BinarySearch(keys, 0, _size, key, comparer);
+ if (i >= 0) {
+ values[i] = value;
+ version++;
+ return;
+ }
+ Insert(~i, key, value);
+ }
+ }
+
+ // Returns the index of the entry with a given key in this sorted list. The
+ // key is located through a binary search, and thus the average execution
+ // time of this method is proportional to Log2(size), where
+ // size is the size of this sorted list. The returned value is -1 if
+ // the given key does not occur in this sorted list. Null is an invalid
+ // key value.
+ //
+ public virtual int IndexOfKey(Object key) {
+ if (key == null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+ int ret = Array.BinarySearch(keys, 0, _size, key, comparer);
+ return ret >=0 ? ret : -1;
+ }
+
+ // Returns the index of the first occurrence of an entry with a given value
+ // in this sorted list. The entry is located through a linear search, and
+ // thus the average execution time of this method is proportional to the
+ // size of this sorted list. The elements of the list are compared to the
+ // given value using the Object.Equals method.
+ //
+ public virtual int IndexOfValue(Object value) {
+ return Array.IndexOf(values, value, 0, _size);
+ }
+
+ // Inserts an entry with a given key and value at a given index.
+ private void Insert(int index, Object key, Object value) {
+ if (_size == keys.Length) EnsureCapacity(_size + 1);
+ if (index < _size) {
+ Array.Copy(keys, index, keys, index + 1, _size - index);
+ Array.Copy(values, index, values, index + 1, _size - index);
+ }
+ keys[index] = key;
+ values[index] = value;
+ _size++;
+ version++;
+ }
+
+ // Removes the entry at the given index. The size of the sorted list is
+ // decreased by one.
+ //
+ public virtual void RemoveAt(int index) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ _size--;
+ if (index < _size) {
+ Array.Copy(keys, index + 1, keys, index, _size - index);
+ Array.Copy(values, index + 1, values, index, _size - index);
+ }
+ keys[_size] = null;
+ values[_size] = null;
+ version++;
+ }
+
+ // Removes an entry from this sorted list. If an entry with the specified
+ // key exists in the sorted list, it is removed. An ArgumentException is
+ // thrown if the key is null.
+ //
+ public virtual void Remove(Object key) {
+ int i = IndexOfKey(key);
+ if (i >= 0)
+ RemoveAt(i);
+ }
+
+ // Sets the value at an index to a given value. The previous value of
+ // the given entry is overwritten.
+ //
+ public virtual void SetByIndex(int index, Object value) {
+ if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+ values[index] = value;
+ version++;
+ }
+
+ // Returns a thread-safe SortedList.
+ //
+ [HostProtection(Synchronization=true)]
+ public static SortedList Synchronized(SortedList list) {
+ if (list==null)
+ throw new ArgumentNullException("list");
+ Contract.EndContractBlock();
+ return new SyncSortedList(list);
+ }
+
+ // Sets the capacity of this sorted list to the size of the sorted list.
+ // This method can be used to minimize a sorted list's memory overhead once
+ // it is known that no new elements will be added to the sorted list. To
+ // completely clear a sorted list and release all memory referenced by the
+ // sorted list, execute the following statements:
+ //
+ // sortedList.Clear();
+ // sortedList.TrimToSize();
+ //
+ public virtual void TrimToSize() {
+ Capacity = _size;
+ }
+
+ [Serializable]
+ private class SyncSortedList : SortedList
+ {
+ private SortedList _list;
+ private Object _root;
+
+
+ internal SyncSortedList(SortedList list) {
+ _list = list;
+ _root = list.SyncRoot;
+ }
+
+ public override int Count {
+ get { lock(_root) { return _list.Count; } }
+ }
+
+ public override Object SyncRoot {
+ get { return _root; }
+ }
+
+ public override bool IsReadOnly {
+ get { return _list.IsReadOnly; }
+ }
+
+ public override bool IsFixedSize {
+ get { return _list.IsFixedSize; }
+ }
+
+
+ public override bool IsSynchronized {
+ get { return true; }
+ }
+
+ public override Object this[Object key] {
+ get {
+ lock(_root) {
+ return _list[key];
+ }
+ }
+ set {
+ lock(_root) {
+ _list[key] = value;
+ }
+ }
+ }
+
+ public override void Add(Object key, Object value) {
+ lock(_root) {
+ _list.Add(key, value);
+ }
+ }
+
+ public override int Capacity {
+ get{ lock(_root) { return _list.Capacity; } }
+ }
+
+ public override void Clear() {
+ lock(_root) {
+ _list.Clear();
+ }
+ }
+
+ public override Object Clone() {
+ lock(_root) {
+ return _list.Clone();
+ }
+ }
+
+ public override bool Contains(Object key) {
+ lock(_root) {
+ return _list.Contains(key);
+ }
+ }
+
+ public override bool ContainsKey(Object key) {
+ lock(_root) {
+ return _list.ContainsKey(key);
+ }
+ }
+
+ public override bool ContainsValue(Object key) {
+ lock(_root) {
+ return _list.ContainsValue(key);
+ }
+ }
+
+ public override void CopyTo(Array array, int index) {
+ lock(_root) {
+ _list.CopyTo(array, index);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Object GetByIndex(int index) {
+ lock(_root) {
+ return _list.GetByIndex(index);
+ }
+ }
+
+ public override IDictionaryEnumerator GetEnumerator() {
+ lock(_root) {
+ return _list.GetEnumerator();
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override Object GetKey(int index) {
+ lock(_root) {
+ return _list.GetKey(index);
+ }
+ }
+
+ public override IList GetKeyList() {
+ lock(_root) {
+ return _list.GetKeyList();
+ }
+ }
+
+ public override IList GetValueList() {
+ lock(_root) {
+ return _list.GetValueList();
+ }
+ }
+
+ public override int IndexOfKey(Object key) {
+ if (key == null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+
+ lock(_root) {
+ return _list.IndexOfKey(key);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int IndexOfValue(Object value) {
+ lock(_root) {
+ return _list.IndexOfValue(value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void RemoveAt(int index) {
+ lock(_root) {
+ _list.RemoveAt(index);
+ }
+ }
+
+ public override void Remove(Object key) {
+ lock(_root) {
+ _list.Remove(key);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void SetByIndex(int index, Object value) {
+ lock(_root) {
+ _list.SetByIndex(index, value);
+ }
+ }
+
+ internal override KeyValuePairs[] ToKeyValuePairsArray() {
+ return _list.ToKeyValuePairsArray();
+ }
+
+ public override void TrimToSize() {
+ lock(_root) {
+ _list.TrimToSize();
+ }
+ }
+ }
+
+
+ [Serializable]
+ private class SortedListEnumerator : IDictionaryEnumerator, ICloneable
+ {
+ private SortedList sortedList;
+ private Object key;
+ private Object value;
+ private int index;
+ private int startIndex; // Store for Reset.
+ private int endIndex;
+ private int version;
+ private bool current; // Is the current element valid?
+ private int getObjectRetType; // What should GetObject return?
+
+ internal const int Keys = 1;
+ internal const int Values = 2;
+ internal const int DictEntry = 3;
+
+ internal SortedListEnumerator(SortedList sortedList, int index, int count,
+ int getObjRetType) {
+ this.sortedList = sortedList;
+ this.index = index;
+ startIndex = index;
+ endIndex = index + count;
+ version = sortedList.version;
+ getObjectRetType = getObjRetType;
+ current = false;
+ }
+
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ public virtual Object Key {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return key;
+ }
+ }
+
+ public virtual bool MoveNext() {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (index < endIndex) {
+ key = sortedList.keys[index];
+ value = sortedList.values[index];
+ index++;
+ current = true;
+ return true;
+ }
+ key = null;
+ value = null;
+ current = false;
+ return false;
+ }
+
+ public virtual DictionaryEntry Entry {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public virtual Object Current {
+ get {
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+
+ if (getObjectRetType==Keys)
+ return key;
+ else if (getObjectRetType==Values)
+ return value;
+ else
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public virtual Object Value {
+ get {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ if (current == false) throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ return value;
+ }
+ }
+
+ public virtual void Reset() {
+ if (version != sortedList.version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ index = startIndex;
+ current = false;
+ key = null;
+ value = null;
+ }
+ }
+
+ [Serializable]
+ private class KeyList : IList
+ {
+ private SortedList sortedList;
+
+ internal KeyList(SortedList sortedList) {
+ this.sortedList = sortedList;
+ }
+
+ public virtual int Count {
+ get { return sortedList._size; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return true; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return sortedList.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return sortedList.SyncRoot; }
+ }
+
+ public virtual int Add(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ // return 0; // suppress compiler warning
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual bool Contains(Object key) {
+ return sortedList.Contains(key);
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array != null && array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+
+ // defer error checking to Array.Copy
+ Array.Copy(sortedList.keys, 0, array, arrayIndex, sortedList.Count);
+ }
+
+ public virtual void Insert(int index, Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return sortedList.GetKey(index);
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_KeyCollectionSet"));
+ }
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new SortedListEnumerator(sortedList, 0, sortedList.Count, SortedListEnumerator.Keys);
+ }
+
+ public virtual int IndexOf(Object key) {
+ if (key==null)
+ throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ Contract.EndContractBlock();
+
+ int i = Array.BinarySearch(sortedList.keys, 0,
+ sortedList.Count, key, sortedList.comparer);
+ if (i >= 0) return i;
+ return -1;
+ }
+
+ public virtual void Remove(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+ }
+
+ [Serializable]
+ private class ValueList : IList
+ {
+ private SortedList sortedList;
+
+ internal ValueList(SortedList sortedList) {
+ this.sortedList = sortedList;
+ }
+
+ public virtual int Count {
+ get { return sortedList._size; }
+ }
+
+ public virtual bool IsReadOnly {
+ get { return true; }
+ }
+
+ public virtual bool IsFixedSize {
+ get { return true; }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return sortedList.IsSynchronized; }
+ }
+
+ public virtual Object SyncRoot {
+ get { return sortedList.SyncRoot; }
+ }
+
+ public virtual int Add(Object key) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void Clear() {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual bool Contains(Object value) {
+ return sortedList.ContainsValue(value);
+ }
+
+ public virtual void CopyTo(Array array, int arrayIndex) {
+ if (array != null && array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ Contract.EndContractBlock();
+
+ // defer error checking to Array.Copy
+ Array.Copy(sortedList.values, 0, array, arrayIndex, sortedList.Count);
+ }
+
+ public virtual void Insert(int index, Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual Object this[int index] {
+ get {
+ return sortedList.GetByIndex(index);
+ }
+ set {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+ }
+
+ public virtual IEnumerator GetEnumerator() {
+ return new SortedListEnumerator(sortedList, 0, sortedList.Count, SortedListEnumerator.Values);
+ }
+
+ public virtual int IndexOf(Object value) {
+ return Array.IndexOf(sortedList.values, value, 0, sortedList.Count);
+ }
+
+ public virtual void Remove(Object value) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ public virtual void RemoveAt(int index) {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_SortedListNestedWrite));
+ }
+
+ }
+
+ // internal debug view class for sorted list
+ internal class SortedListDebugView {
+ private SortedList sortedList;
+
+ public SortedListDebugView( SortedList sortedList) {
+ if( sortedList == null) {
+ throw new ArgumentNullException("sortedList");
+ }
+ Contract.EndContractBlock();
+
+ this.sortedList = sortedList;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public KeyValuePairs[] Items {
+ get {
+ return sortedList.ToKeyValuePairsArray();
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/Stack.cs b/src/mscorlib/src/System/Collections/Stack.cs
new file mode 100644
index 0000000000..0384a4ee81
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/Stack.cs
@@ -0,0 +1,380 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+** Purpose: An array implementation of a stack.
+**
+**
+=============================================================================*/
+namespace System.Collections {
+ using System;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ // A simple stack of objects. Internally it is implemented as an array,
+ // so Push can be O(n). Pop is O(1).
+ [DebuggerTypeProxy(typeof(System.Collections.Stack.StackDebugView))]
+ [DebuggerDisplay("Count = {Count}")]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class Stack : ICollection, ICloneable {
+ private Object[] _array; // Storage for stack elements
+ [ContractPublicPropertyName("Count")]
+ private int _size; // Number of items in the stack.
+ private int _version; // Used to keep enumerator in sync w/ collection.
+ [NonSerialized]
+ private Object _syncRoot;
+
+ private const int _defaultCapacity = 10;
+
+ public Stack() {
+ _array = new Object[_defaultCapacity];
+ _size = 0;
+ _version = 0;
+ }
+
+ // Create a stack with a specific initial capacity. The initial capacity
+ // must be a non-negative number.
+ public Stack(int initialCapacity) {
+ if (initialCapacity < 0)
+ throw new ArgumentOutOfRangeException("initialCapacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (initialCapacity < _defaultCapacity)
+ initialCapacity = _defaultCapacity; // Simplify doubling logic in Push.
+ _array = new Object[initialCapacity];
+ _size = 0;
+ _version = 0;
+ }
+
+ // Fills a Stack with the contents of a particular collection. The items are
+ // pushed onto the stack in the same order they are read by the enumerator.
+ //
+ public Stack(ICollection col) : this((col==null ? 32 : col.Count))
+ {
+ if (col==null)
+ throw new ArgumentNullException("col");
+ Contract.EndContractBlock();
+ IEnumerator en = col.GetEnumerator();
+ while(en.MoveNext())
+ Push(en.Current);
+ }
+
+ public virtual int Count {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return _size;
+ }
+ }
+
+ public virtual bool IsSynchronized {
+ get { return false; }
+ }
+
+ public virtual Object SyncRoot {
+ get {
+ if( _syncRoot == null) {
+ System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null);
+ }
+ return _syncRoot;
+ }
+ }
+
+ // Removes all Objects from the Stack.
+ public virtual void Clear() {
+ Array.Clear(_array, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
+ _size = 0;
+ _version++;
+ }
+
+ public virtual Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ Stack s = new Stack(_size);
+ s._size = _size;
+ Array.Copy(_array, 0, s._array, 0, _size);
+ s._version = _version;
+ return s;
+ }
+
+ public virtual bool Contains(Object obj) {
+ int count = _size;
+
+ while (count-- > 0) {
+ if (obj == null) {
+ if (_array[count] == null)
+ return true;
+ }
+ else if (_array[count] != null && _array[count].Equals(obj)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Copies the stack into an array.
+ public virtual void CopyTo(Array array, int index) {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - index < _size)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ int i = 0;
+ if (array is Object[]) {
+ Object[] objArray = (Object[]) array;
+ while(i < _size) {
+ objArray[i+index] = _array[_size-i-1];
+ i++;
+ }
+ }
+ else {
+ while(i < _size) {
+ array.SetValue(_array[_size-i-1], i+index);
+ i++;
+ }
+ }
+ }
+
+ // Returns an IEnumerator for this Stack.
+ public virtual IEnumerator GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ return new StackEnumerator(this);
+ }
+
+ // Returns the top object on the stack without removing it. If the stack
+ // is empty, Peek throws an InvalidOperationException.
+ public virtual Object Peek() {
+ if (_size==0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
+ Contract.EndContractBlock();
+ return _array[_size-1];
+ }
+
+ // Pops an item from the top of the stack. If the stack is empty, Pop
+ // throws an InvalidOperationException.
+ public virtual Object Pop() {
+ if (_size == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
+ //Contract.Ensures(Count == Contract.OldValue(Count) - 1);
+ Contract.EndContractBlock();
+ _version++;
+ Object obj = _array[--_size];
+ _array[_size] = null; // Free memory quicker.
+ return obj;
+ }
+
+ // Pushes an item to the top of the stack.
+ //
+ public virtual void Push(Object obj) {
+ //Contract.Ensures(Count == Contract.OldValue(Count) + 1);
+ if (_size == _array.Length) {
+ Object[] newArray = new Object[2*_array.Length];
+ Array.Copy(_array, 0, newArray, 0, _size);
+ _array = newArray;
+ }
+ _array[_size++] = obj;
+ _version++;
+ }
+
+ // Returns a synchronized Stack.
+ //
+ [HostProtection(Synchronization=true)]
+ public static Stack Synchronized(Stack stack) {
+ if (stack==null)
+ throw new ArgumentNullException("stack");
+ Contract.Ensures(Contract.Result<Stack>() != null);
+ Contract.EndContractBlock();
+ return new SyncStack(stack);
+ }
+
+
+ // Copies the Stack to an array, in the same order Pop would return the items.
+ public virtual Object[] ToArray()
+ {
+ Contract.Ensures(Contract.Result<Object[]>() != null);
+
+ Object[] objArray = new Object[_size];
+ int i = 0;
+ while(i < _size) {
+ objArray[i] = _array[_size-i-1];
+ i++;
+ }
+ return objArray;
+ }
+
+ [Serializable]
+ private class SyncStack : Stack
+ {
+ private Stack _s;
+ private Object _root;
+
+ internal SyncStack(Stack stack) {
+ _s = stack;
+ _root = stack.SyncRoot;
+ }
+
+ public override bool IsSynchronized {
+ get { return true; }
+ }
+
+ public override Object SyncRoot {
+ get {
+ return _root;
+ }
+ }
+
+ public override int Count {
+ get {
+ lock (_root) {
+ return _s.Count;
+ }
+ }
+ }
+
+ public override bool Contains(Object obj) {
+ lock (_root) {
+ return _s.Contains(obj);
+ }
+ }
+
+ public override Object Clone()
+ {
+ lock (_root) {
+ return new SyncStack((Stack)_s.Clone());
+ }
+ }
+
+ public override void Clear() {
+ lock (_root) {
+ _s.Clear();
+ }
+ }
+
+ public override void CopyTo(Array array, int arrayIndex) {
+ lock (_root) {
+ _s.CopyTo(array, arrayIndex);
+ }
+ }
+
+ public override void Push(Object value) {
+ lock (_root) {
+ _s.Push(value);
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Thread safety problems with precondition - can't express the precondition as of Dev10.
+ public override Object Pop() {
+ lock (_root) {
+ return _s.Pop();
+ }
+ }
+
+ public override IEnumerator GetEnumerator() {
+ lock (_root) {
+ return _s.GetEnumerator();
+ }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Thread safety problems with precondition - can't express the precondition as of Dev10.
+ public override Object Peek() {
+ lock (_root) {
+ return _s.Peek();
+ }
+ }
+
+ public override Object[] ToArray() {
+ lock (_root) {
+ return _s.ToArray();
+ }
+ }
+ }
+
+
+ [Serializable]
+ private class StackEnumerator : IEnumerator, ICloneable
+ {
+ private Stack _stack;
+ private int _index;
+ private int _version;
+ private Object currentElement;
+
+ internal StackEnumerator(Stack stack) {
+ _stack = stack;
+ _version = _stack._version;
+ _index = -2;
+ currentElement = null;
+ }
+
+ public Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ public virtual bool MoveNext() {
+ bool retval;
+ if (_version != _stack._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ if (_index == -2) { // First call to enumerator.
+ _index = _stack._size-1;
+ retval = ( _index >= 0);
+ if (retval)
+ currentElement = _stack._array[_index];
+ return retval;
+ }
+ if (_index == -1) { // End of enumeration.
+ return false;
+ }
+
+ retval = (--_index >= 0);
+ if (retval)
+ currentElement = _stack._array[_index];
+ else
+ currentElement = null;
+ return retval;
+ }
+
+ public virtual Object Current {
+ get {
+ if (_index == -2) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_index == -1) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ return currentElement;
+ }
+ }
+
+ public virtual void Reset() {
+ if (_version != _stack._version) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumFailedVersion));
+ _index = -2;
+ currentElement = null;
+ }
+ }
+
+ internal class StackDebugView {
+ private Stack stack;
+
+ public StackDebugView( Stack stack) {
+ if( stack == null)
+ throw new ArgumentNullException("stack");
+ Contract.EndContractBlock();
+
+ this.stack = stack;
+ }
+
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public Object[] Items {
+ get {
+ return stack.ToArray();
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Collections/StructuralComparisons.cs b/src/mscorlib/src/System/Collections/StructuralComparisons.cs
new file mode 100644
index 0000000000..685af59c4b
--- /dev/null
+++ b/src/mscorlib/src/System/Collections/StructuralComparisons.cs
@@ -0,0 +1,89 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Collections {
+ public static class StructuralComparisons {
+
+ private static volatile IComparer s_StructuralComparer;
+ private static volatile IEqualityComparer s_StructuralEqualityComparer;
+
+ public static IComparer StructuralComparer {
+ get {
+ IComparer comparer = s_StructuralComparer;
+ if (comparer == null) {
+ comparer = new StructuralComparer();
+ s_StructuralComparer = comparer;
+ }
+ return comparer;
+ }
+ }
+
+ public static IEqualityComparer StructuralEqualityComparer {
+ get {
+ IEqualityComparer comparer = s_StructuralEqualityComparer;
+ if (comparer == null) {
+ comparer = new StructuralEqualityComparer();
+ s_StructuralEqualityComparer = comparer;
+ }
+ return comparer;
+ }
+ }
+ }
+
+ [Serializable]
+ internal class StructuralEqualityComparer : IEqualityComparer {
+ public new bool Equals(Object x, Object y) {
+ if (x != null) {
+
+ IStructuralEquatable seObj = x as IStructuralEquatable;
+
+ if (seObj != null){
+ return seObj.Equals(y, this);
+ }
+
+ if (y != null) {
+ return x.Equals(y);
+ } else {
+ return false;
+ }
+ }
+ if (y != null) return false;
+ return true;
+ }
+
+ public int GetHashCode(Object obj) {
+ if (obj == null) return 0;
+
+ IStructuralEquatable seObj = obj as IStructuralEquatable;
+
+ if (seObj != null) {
+ return seObj.GetHashCode(this);
+ }
+
+ return obj.GetHashCode();
+ }
+ }
+
+ [Serializable]
+ internal class StructuralComparer : IComparer {
+ public int Compare(Object x, Object y) {
+
+ if (x == null) return y == null ? 0 : -1;
+ if (y == null) return 1;
+
+ IStructuralComparable scX = x as IStructuralComparable;
+
+ if (scX != null) {
+ return scX.CompareTo(y, this);
+ }
+
+ return Comparer.Default.Compare(x, y);
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/CompatibilitySwitches.cs b/src/mscorlib/src/System/CompatibilitySwitches.cs
new file mode 100644
index 0000000000..7facf85df3
--- /dev/null
+++ b/src/mscorlib/src/System/CompatibilitySwitches.cs
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Runtime;
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ [FriendAccessAllowed]
+ internal static class CompatibilitySwitches
+ {
+ private static bool s_AreSwitchesSet;
+
+#if FEATURE_CORECLR
+ private static bool s_useLatestBehaviorWhenTFMNotSpecified; // Which behavior to use when the TFM is not specified.
+#endif //FEATURE_CORECLR
+
+#if !FEATURE_CORECLR
+ private static bool s_isNetFx40TimeSpanLegacyFormatMode;
+ private static bool s_isNetFx40LegacySecurityPolicy;
+ private static bool s_isNetFx45LegacyManagedDeflateStream;
+#endif //!FEATURE_CORECLR
+
+ public static bool IsCompatibilityBehaviorDefined
+ {
+ get
+ {
+ return s_AreSwitchesSet;
+ }
+ }
+
+ private static bool IsCompatibilitySwitchSet(string compatibilitySwitch)
+ {
+ bool? result = AppDomain.CurrentDomain.IsCompatibilitySwitchSet(compatibilitySwitch);
+ return (result.HasValue && result.Value);
+ }
+
+ internal static void InitializeSwitches()
+ {
+#if FEATURE_CORECLR
+ s_useLatestBehaviorWhenTFMNotSpecified = IsCompatibilitySwitchSet("UseLatestBehaviorWhenTFMNotSpecified");
+#endif //FEATURE_CORECLR
+
+#if !FEATURE_CORECLR
+ s_isNetFx40TimeSpanLegacyFormatMode = IsCompatibilitySwitchSet("NetFx40_TimeSpanLegacyFormatMode");
+ s_isNetFx40LegacySecurityPolicy = IsCompatibilitySwitchSet("NetFx40_LegacySecurityPolicy");
+ s_isNetFx45LegacyManagedDeflateStream = IsCompatibilitySwitchSet("NetFx45_LegacyManagedDeflateStream");
+#endif //FEATURE_CORECLR
+
+ s_AreSwitchesSet = true;
+ }
+
+#if FEATURE_CORECLR
+ /// <summary>
+ /// This property returns whether to give the latest behavior when the TFM is missing
+ /// </summary>
+ internal static bool UseLatestBehaviorWhenTFMNotSpecified
+ {
+ get
+ {
+ return s_useLatestBehaviorWhenTFMNotSpecified;
+ }
+ }
+#else //FEATURE_CORECLR
+
+ public static bool IsAppEarlierThanSilverlight4
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public static bool IsAppEarlierThanWindowsPhone8
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public static bool IsAppEarlierThanWindowsPhoneMango
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+#endif //FEATURE_CORECLR
+
+ public static bool IsNetFx40TimeSpanLegacyFormatMode
+ {
+ get
+ {
+#if !FEATURE_CORECLR
+ return s_isNetFx40TimeSpanLegacyFormatMode;
+#else
+ return false;
+#endif //!FEATURE_CORECLR
+ }
+ }
+
+ public static bool IsNetFx40LegacySecurityPolicy
+ {
+ get
+ {
+#if !FEATURE_CORECLR
+ return s_isNetFx40LegacySecurityPolicy;
+#else
+ return false;
+#endif //!FEATURE_CORECLR
+ }
+ }
+
+ public static bool IsNetFx45LegacyManagedDeflateStream
+ {
+ get
+ {
+#if !FEATURE_CORECLR
+ return s_isNetFx45LegacyManagedDeflateStream;
+#else
+ return false;
+#endif //!FEATURE_CORECLR
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHash.cs b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHash.cs
new file mode 100644
index 0000000000..a7b0e70266
--- /dev/null
+++ b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHash.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+namespace System.Configuration.Assemblies {
+ using System;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public struct AssemblyHash : ICloneable
+ {
+ private AssemblyHashAlgorithm _Algorithm;
+ private byte[] _Value;
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public static readonly AssemblyHash Empty = new AssemblyHash(AssemblyHashAlgorithm.None, null);
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public AssemblyHash(byte[] value) {
+ _Algorithm = AssemblyHashAlgorithm.SHA1;
+ _Value = null;
+
+ if (value != null) {
+ int length = value.Length;
+ _Value = new byte[length];
+ Array.Copy(value, _Value, length);
+ }
+ }
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public AssemblyHash(AssemblyHashAlgorithm algorithm, byte[] value) {
+ _Algorithm = algorithm;
+ _Value = null;
+
+ if (value != null) {
+ int length = value.Length;
+ _Value = new byte[length];
+ Array.Copy(value, _Value, length);
+ }
+ }
+
+ // Hash is made up of a byte array and a value from a class of supported
+ // algorithm types.
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public AssemblyHashAlgorithm Algorithm {
+ get { return _Algorithm; }
+ set { _Algorithm = value; }
+ }
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public byte[] GetValue() {
+ return _Value;
+ }
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetValue(byte[] value) {
+ _Value = value;
+ }
+
+ [Obsolete("The AssemblyHash class has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public Object Clone() {
+ return new AssemblyHash(_Algorithm, _Value);
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHashAlgorithm.cs b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHashAlgorithm.cs
new file mode 100644
index 0000000000..6c4fb3febf
--- /dev/null
+++ b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyHashAlgorithm.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+using System.Runtime.InteropServices;
+
+namespace System.Configuration.Assemblies {
+
+ using System;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum AssemblyHashAlgorithm
+ {
+ None = 0,
+ MD5 = 0x8003,
+ SHA1 = 0x8004,
+ [ComVisible(false)]
+ SHA256 = 0x800c,
+ [ComVisible(false)]
+ SHA384 = 0x800d,
+ [ComVisible(false)]
+ SHA512 = 0x800e,
+ }
+}
diff --git a/src/mscorlib/src/System/Configuration/Assemblies/AssemblyVersionCompatibility.cs b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyVersionCompatibility.cs
new file mode 100644
index 0000000000..4b0f1e4236
--- /dev/null
+++ b/src/mscorlib/src/System/Configuration/Assemblies/AssemblyVersionCompatibility.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: defining the different flavor's assembly version compatibility
+**
+**
+===========================================================*/
+namespace System.Configuration.Assemblies {
+
+ using System;
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum AssemblyVersionCompatibility
+ {
+ SameMachine = 1,
+ SameProcess = 2,
+ SameDomain = 3,
+ }
+}
diff --git a/src/mscorlib/src/System/ContextBoundObject.cs b/src/mscorlib/src/System/ContextBoundObject.cs
new file mode 100644
index 0000000000..01929dabe3
--- /dev/null
+++ b/src/mscorlib/src/System/ContextBoundObject.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: Defines the root type for all context bound types
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Security.Permissions;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class ContextBoundObject : MarshalByRefObject {
+#else // FEATURE_REMOTING
+ public abstract class ContextBoundObject {
+#endif // FEATURE_REMOTING
+ }
+}
diff --git a/src/mscorlib/src/System/ContextMarshalException.cs b/src/mscorlib/src/System/ContextMarshalException.cs
new file mode 100644
index 0000000000..f74a62b991
--- /dev/null
+++ b/src/mscorlib/src/System/ContextMarshalException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for attempting to pass an instance through a context
+** boundary, when the formal type and the instance's marshal style are
+** incompatible or cannot be marshaled.
+**
+** This is thrown by the VM when attempts to marshal the exception
+** object at the AppDomain transition boundary fails.
+=============================================================================*/
+
+namespace System {
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ContextMarshalException : SystemException {
+ public ContextMarshalException()
+ : base(Environment.GetResourceString("Arg_ContextMarshalException")) {
+ SetErrorCode(__HResults.COR_E_CONTEXTMARSHAL);
+ }
+
+ public ContextMarshalException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_CONTEXTMARSHAL);
+ }
+
+ public ContextMarshalException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_CONTEXTMARSHAL);
+ }
+
+ protected ContextMarshalException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/ContextStaticAttribute.cs b/src/mscorlib/src/System/ContextStaticAttribute.cs
new file mode 100644
index 0000000000..b875aa33f5
--- /dev/null
+++ b/src/mscorlib/src/System/ContextStaticAttribute.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Custom attribute to indicate that the field should be treated
+** as a static relative to a context.
+**
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+[Serializable]
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ [Obsolete("ContextStaticAttribute is not supported in this release. It has been left in so that legacy tools can be used with this release, but it cannot be used in your code.", true)]
+#endif // FEATURE_CORECLR
+ public class ContextStaticAttribute : Attribute
+ {
+ public ContextStaticAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Convert.cs b/src/mscorlib/src/System/Convert.cs
new file mode 100644
index 0000000000..d1468314f2
--- /dev/null
+++ b/src/mscorlib/src/System/Convert.cs
@@ -0,0 +1,2718 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Home for static conversion methods.
+**
+**
+===========================================================*/
+
+using System;
+using System.Globalization;
+using System.Threading;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Security;
+using System.Diagnostics.Contracts;
+
+
+namespace System {
+
+ [Flags]
+ public enum Base64FormattingOptions {
+ None = 0,
+ InsertLineBreaks = 1
+ }
+
+ // Returns the type code of this object. An implementation of this method
+ // must not return TypeCode.Empty (which represents a null reference) or
+ // TypeCode.Object (which represents an object that doesn't implement the
+ // IConvertible interface). An implementation of this method should return
+ // TypeCode.DBNull if the value of this object is a database null. For
+ // example, a nullable integer type should return TypeCode.DBNull if the
+ // value of the object is the database null. Otherwise, an implementation
+ // of this method should return the TypeCode that best describes the
+ // internal representation of the object.
+ // The Value class provides conversion and querying methods for values. The
+ // Value class contains static members only, and it is not possible to create
+ // instances of the class.
+ //
+ // The statically typed conversion methods provided by the Value class are all
+ // of the form:
+ //
+ // public static XXX ToXXX(YYY value)
+ //
+ // where XXX is the target type and YYY is the source type. The matrix below
+ // shows the set of supported conversions. The set of conversions is symmetric
+ // such that for every ToXXX(YYY) there is also a ToYYY(XXX).
+ //
+ // From: To: Bol Chr SBy Byt I16 U16 I32 U32 I64 U64 Sgl Dbl Dec Dat Str
+ // ----------------------------------------------------------------------
+ // Boolean x x x x x x x x x x x x x
+ // Char x x x x x x x x x x
+ // SByte x x x x x x x x x x x x x x
+ // Byte x x x x x x x x x x x x x x
+ // Int16 x x x x x x x x x x x x x x
+ // UInt16 x x x x x x x x x x x x x x
+ // Int32 x x x x x x x x x x x x x x
+ // UInt32 x x x x x x x x x x x x x x
+ // Int64 x x x x x x x x x x x x x x
+ // UInt64 x x x x x x x x x x x x x x
+ // Single x x x x x x x x x x x x x
+ // Double x x x x x x x x x x x x x
+ // Decimal x x x x x x x x x x x x x
+ // DateTime x x
+ // String x x x x x x x x x x x x x x x
+ // ----------------------------------------------------------------------
+ //
+ // For dynamic conversions, the Value class provides a set of methods of the
+ // form:
+ //
+ // public static XXX ToXXX(object value)
+ //
+ // where XXX is the target type (Boolean, Char, SByte, Byte, Int16, UInt16,
+ // Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime,
+ // or String). The implementations of these methods all take the form:
+ //
+ // public static XXX toXXX(object value) {
+ // return value == null? XXX.Default: ((IConvertible)value).ToXXX();
+ // }
+ //
+ // The code first checks if the given value is a null reference (which is the
+ // same as Value.Empty), in which case it returns the default value for type
+ // XXX. Otherwise, a cast to IConvertible is performed, and the appropriate ToXXX()
+ // method is invoked on the object. An InvalidCastException is thrown if the
+ // cast to IConvertible fails, and that exception is simply allowed to propagate out
+ // of the conversion method.
+
+ // Constant representing the database null value. This value is used in
+ // database applications to indicate the absense of a known value. Note
+ // that Value.DBNull is NOT the same as a null object reference, which is
+ // represented by Value.Empty.
+ //
+ // The Equals() method of DBNull always returns false, even when the
+ // argument is itself DBNull.
+ //
+ // When passed Value.DBNull, the Value.GetTypeCode() method returns
+ // TypeCode.DBNull.
+ //
+ // When passed Value.DBNull, the Value.ToXXX() methods all throw an
+ // InvalidCastException.
+
+ public static class Convert {
+
+ //A typeof operation is fairly expensive (does a system call), so we'll cache these here
+ //statically. These are exactly lined up with the TypeCode, eg. ConvertType[TypeCode.Int16]
+ //will give you the type of an Int16.
+ internal static readonly RuntimeType[] ConvertTypes = {
+ (RuntimeType)typeof(System.Empty),
+ (RuntimeType)typeof(Object),
+ (RuntimeType)typeof(System.DBNull),
+ (RuntimeType)typeof(Boolean),
+ (RuntimeType)typeof(Char),
+ (RuntimeType)typeof(SByte),
+ (RuntimeType)typeof(Byte),
+ (RuntimeType)typeof(Int16),
+ (RuntimeType)typeof(UInt16),
+ (RuntimeType)typeof(Int32),
+ (RuntimeType)typeof(UInt32),
+ (RuntimeType)typeof(Int64),
+ (RuntimeType)typeof(UInt64),
+ (RuntimeType)typeof(Single),
+ (RuntimeType)typeof(Double),
+ (RuntimeType)typeof(Decimal),
+ (RuntimeType)typeof(DateTime),
+ (RuntimeType)typeof(Object), //TypeCode is discontinuous so we need a placeholder.
+ (RuntimeType)typeof(String)
+ };
+
+ // Need to special case Enum because typecode will be underlying type, e.g. Int32
+ private static readonly RuntimeType EnumType = (RuntimeType)typeof(Enum);
+
+ internal static readonly char[] base64Table = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
+ 'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d',
+ 'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s',
+ 't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
+ '8','9','+','/','=' };
+
+ private const Int32 base64LineBreakPosition = 76;
+
+#if _DEBUG
+ private static bool TriggerAsserts = DoAsserts();
+ private static bool DoAsserts() {
+ Contract.Assert(ConvertTypes!=null, "[Convert.cctor]ConvertTypes!=null");
+ Contract.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)");
+ Contract.Assert(ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty),
+ "[Convert.cctor]ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty)");
+ Contract.Assert(ConvertTypes[(int)TypeCode.String]==typeof(String),
+ "[Convert.cctor]ConvertTypes[(int)TypeCode.String]==typeof(System.String)");
+ Contract.Assert(ConvertTypes[(int)TypeCode.Int32]==typeof(int),
+ "[Convert.cctor]ConvertTypes[(int)TypeCode.Int32]==typeof(int)");
+ return true;
+ }
+#endif
+
+ public static readonly Object DBNull = System.DBNull.Value;
+
+ // Returns the type code for the given object. If the argument is null,
+ // the result is TypeCode.Empty. If the argument is not a value (i.e. if
+ // the object does not implement IConvertible), the result is TypeCode.Object.
+ // Otherwise, the result is the type code of the object, as determined by
+ // the object's implementation of IConvertible.
+ [Pure]
+ public static TypeCode GetTypeCode(object value) {
+ if (value == null) return TypeCode.Empty;
+ IConvertible temp = value as IConvertible;
+ if (temp != null)
+ {
+ return temp.GetTypeCode();
+ }
+ return TypeCode.Object;
+ }
+
+ // Returns true if the given object is a database null. This operation
+ // corresponds to "value.GetTypeCode() == TypeCode.DBNull".
+ [Pure]
+ public static bool IsDBNull(object value) {
+ if (value == System.DBNull.Value) return true;
+ IConvertible convertible = value as IConvertible;
+ return convertible != null? convertible.GetTypeCode() == TypeCode.DBNull: false;
+ }
+
+ // Converts the given object to the given type. In general, this method is
+ // equivalent to calling the Value.ToXXX(value) method for the given
+ // typeCode and boxing the result.
+ //
+ // The method first checks if the given object implements IConvertible. If not,
+ // the only permitted conversion is from a null to TypeCode.Empty, the
+ // result of which is null.
+ //
+ // If the object does implement IConvertible, a check is made to see if the
+ // object already has the given type code, in which case the object is
+ // simply returned. Otherwise, the appropriate ToXXX() is invoked on the
+ // object's implementation of IConvertible.
+ public static Object ChangeType(Object value, TypeCode typeCode) {
+ return ChangeType(value, typeCode, Thread.CurrentThread.CurrentCulture);
+ }
+
+ public static Object ChangeType(Object value, TypeCode typeCode, IFormatProvider provider) {
+ if (value == null && (typeCode == TypeCode.Empty || typeCode == TypeCode.String || typeCode == TypeCode.Object)) {
+ return null;
+ }
+
+ IConvertible v = value as IConvertible;
+ if (v == null) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_IConvertible"));
+ }
+
+ // This line is invalid for things like Enums that return a TypeCode
+ // of Int32, but the object can't actually be cast to an Int32.
+ // if (v.GetTypeCode() == typeCode) return value;
+ switch (typeCode) {
+ case TypeCode.Boolean:
+ return v.ToBoolean(provider);
+ case TypeCode.Char:
+ return v.ToChar(provider);
+ case TypeCode.SByte:
+ return v.ToSByte(provider);
+ case TypeCode.Byte:
+ return v.ToByte(provider);
+ case TypeCode.Int16:
+ return v.ToInt16(provider);
+ case TypeCode.UInt16:
+ return v.ToUInt16(provider);
+ case TypeCode.Int32:
+ return v.ToInt32(provider);
+ case TypeCode.UInt32:
+ return v.ToUInt32(provider);
+ case TypeCode.Int64:
+ return v.ToInt64(provider);
+ case TypeCode.UInt64:
+ return v.ToUInt64(provider);
+ case TypeCode.Single:
+ return v.ToSingle(provider);
+ case TypeCode.Double:
+ return v.ToDouble(provider);
+ case TypeCode.Decimal:
+ return v.ToDecimal(provider);
+ case TypeCode.DateTime:
+ return v.ToDateTime(provider);
+ case TypeCode.String:
+ return v.ToString(provider);
+ case TypeCode.Object:
+ return value;
+ case TypeCode.DBNull:
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_DBNull"));
+ case TypeCode.Empty:
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_Empty"));
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Arg_UnknownTypeCode"));
+ }
+ }
+
+ internal static Object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider) {
+ Contract.Requires(value != null, "[Convert.DefaultToType]value!=null");
+ if (targetType==null) {
+ throw new ArgumentNullException("targetType");
+ }
+ Contract.EndContractBlock();
+
+ RuntimeType rtTargetType = targetType as RuntimeType;
+
+ if (rtTargetType != null)
+ {
+ if (value.GetType() == targetType)
+ {
+ return value;
+ }
+
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Boolean])
+ return value.ToBoolean(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Char])
+ return value.ToChar(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.SByte])
+ return value.ToSByte(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Byte])
+ return value.ToByte(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Int16])
+ return value.ToInt16(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.UInt16])
+ return value.ToUInt16(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Int32])
+ return value.ToInt32(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.UInt32])
+ return value.ToUInt32(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Int64])
+ return value.ToInt64(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.UInt64])
+ return value.ToUInt64(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Single])
+ return value.ToSingle(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Double])
+ return value.ToDouble(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Decimal])
+ return value.ToDecimal(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.DateTime])
+ return value.ToDateTime(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.String])
+ return value.ToString(provider);
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Object])
+ return (Object)value;
+ // Need to special case Enum because typecode will be underlying type, e.g. Int32
+ if (rtTargetType == EnumType)
+ return (Enum)value;
+ if (rtTargetType == ConvertTypes[(int)TypeCode.DBNull])
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_DBNull"));
+ if (rtTargetType == ConvertTypes[(int)TypeCode.Empty])
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_Empty"));
+ }
+
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", value.GetType().FullName, targetType.FullName));
+ }
+
+ public static Object ChangeType(Object value, Type conversionType) {
+ return ChangeType(value, conversionType, Thread.CurrentThread.CurrentCulture);
+ }
+
+ public static Object ChangeType(Object value, Type conversionType, IFormatProvider provider) {
+ if( conversionType == null) {
+ throw new ArgumentNullException("conversionType");
+ }
+ Contract.EndContractBlock();
+
+ if( value == null ) {
+ if(conversionType.IsValueType) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCastNullToValueType"));
+ }
+ return null;
+ }
+
+ IConvertible ic = value as IConvertible;
+ if (ic == null) {
+ if ( value.GetType() == conversionType) {
+ return value;
+ }
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_IConvertible"));
+ }
+
+ RuntimeType rtConversionType = conversionType as RuntimeType;
+
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Boolean])
+ return ic.ToBoolean(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Char])
+ return ic.ToChar(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.SByte])
+ return ic.ToSByte(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Byte])
+ return ic.ToByte(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Int16])
+ return ic.ToInt16(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.UInt16])
+ return ic.ToUInt16(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Int32])
+ return ic.ToInt32(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.UInt32])
+ return ic.ToUInt32(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Int64])
+ return ic.ToInt64(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.UInt64])
+ return ic.ToUInt64(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Single])
+ return ic.ToSingle(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Double])
+ return ic.ToDouble(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Decimal])
+ return ic.ToDecimal(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.DateTime])
+ return ic.ToDateTime(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.String])
+ return ic.ToString(provider);
+ if (rtConversionType==ConvertTypes[(int)TypeCode.Object])
+ return (Object)value;
+
+ return ic.ToType(conversionType, provider);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowCharOverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_Char")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowByteOverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_Byte")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowSByteOverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_SByte")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowInt16OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_Int16")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowUInt16OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_UInt16")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowInt32OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowUInt32OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_UInt32")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowInt64OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_Int64")); }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static void ThrowUInt64OverflowException() { throw new OverflowException(Environment.GetResourceString("Overflow_UInt64")); }
+
+ // Conversions to Boolean
+ public static bool ToBoolean(Object value) {
+ return value == null? false: ((IConvertible)value).ToBoolean(null);
+ }
+
+ public static bool ToBoolean(Object value, IFormatProvider provider) {
+ return value == null? false: ((IConvertible)value).ToBoolean(provider);
+ }
+
+
+ public static bool ToBoolean(bool value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static bool ToBoolean(sbyte value) {
+ return value != 0;
+ }
+
+ // To be consistent with IConvertible in the base data types else we get different semantics
+ // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
+ public static bool ToBoolean(char value) {
+ return ((IConvertible)value).ToBoolean(null);
+ }
+
+ public static bool ToBoolean(byte value) {
+ return value != 0;
+ }
+
+
+ public static bool ToBoolean(short value) {
+ return value != 0;
+ }
+
+ [CLSCompliant(false)]
+ public static bool ToBoolean(ushort value) {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(int value) {
+ return value != 0;
+ }
+
+ [CLSCompliant(false)]
+ public static bool ToBoolean(uint value) {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(long value) {
+ return value != 0;
+ }
+
+ [CLSCompliant(false)]
+ public static bool ToBoolean(ulong value) {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(String value) {
+ if (value == null)
+ return false;
+ return Boolean.Parse(value);
+ }
+
+ public static bool ToBoolean(String value, IFormatProvider provider) {
+ if (value == null)
+ return false;
+ return Boolean.Parse(value);
+ }
+
+ public static bool ToBoolean(float value)
+ {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(double value)
+ {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(decimal value)
+ {
+ return value != 0;
+ }
+
+ public static bool ToBoolean(DateTime value)
+ {
+ return ((IConvertible)value).ToBoolean(null);
+ }
+
+ // Disallowed conversions to Boolean
+ // public static bool ToBoolean(TimeSpan value)
+
+ // Conversions to Char
+
+
+ public static char ToChar(object value) {
+ return value == null? (char)0: ((IConvertible)value).ToChar(null);
+ }
+
+ public static char ToChar(object value, IFormatProvider provider) {
+ return value == null? (char)0: ((IConvertible)value).ToChar(provider);
+ }
+
+ public static char ToChar(bool value) {
+ return ((IConvertible)value).ToChar(null);
+ }
+
+ public static char ToChar(char value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static char ToChar(sbyte value) {
+ if (value < 0) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ public static char ToChar(byte value) {
+ return (char)value;
+ }
+
+ public static char ToChar(short value) {
+ if (value < 0) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ [CLSCompliant(false)]
+ public static char ToChar(ushort value) {
+ return (char)value;
+ }
+
+ public static char ToChar(int value) {
+ if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ [CLSCompliant(false)]
+ public static char ToChar(uint value) {
+ if (value > Char.MaxValue) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ public static char ToChar(long value) {
+ if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ [CLSCompliant(false)]
+ public static char ToChar(ulong value) {
+ if (value > Char.MaxValue) ThrowCharOverflowException();
+ Contract.EndContractBlock();
+ return (char)value;
+ }
+
+ //
+ // @VariantSwitch
+ // Remove FormatExceptions;
+ //
+ public static char ToChar(String value) {
+ return ToChar(value, null);
+ }
+
+ public static char ToChar(String value, IFormatProvider provider) {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ if (value.Length != 1)
+ throw new FormatException(Environment.GetResourceString(ResId.Format_NeedSingleChar));
+
+ return value[0];
+ }
+
+ // To be consistent with IConvertible in the base data types else we get different semantics
+ // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
+ public static char ToChar(float value)
+ {
+ return ((IConvertible)value).ToChar(null);
+ }
+
+ // To be consistent with IConvertible in the base data types else we get different semantics
+ // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
+ public static char ToChar(double value)
+ {
+ return ((IConvertible)value).ToChar(null);
+ }
+
+ // To be consistent with IConvertible in the base data types else we get different semantics
+ // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
+ public static char ToChar(decimal value)
+ {
+ return ((IConvertible)value).ToChar(null);
+ }
+
+ public static char ToChar(DateTime value)
+ {
+ return ((IConvertible)value).ToChar(null);
+ }
+
+
+ // Disallowed conversions to Char
+ // public static char ToChar(TimeSpan value)
+
+ // Conversions to SByte
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(object value) {
+ return value == null? (sbyte)0: ((IConvertible)value).ToSByte(null);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(object value, IFormatProvider provider) {
+ return value == null? (sbyte)0: ((IConvertible)value).ToSByte(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(bool value) {
+ return value? (sbyte)Boolean.True: (sbyte)Boolean.False;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(sbyte value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(char value) {
+ if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(byte value) {
+ if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(short value) {
+ if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(ushort value) {
+ if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(int value) {
+ if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(uint value) {
+ if (value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(long value) {
+ if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(ulong value) {
+ if (value > (ulong)SByte.MaxValue) ThrowSByteOverflowException();
+ Contract.EndContractBlock();
+ return (sbyte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(float value) {
+ return ToSByte((double)value);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(double value) {
+ return ToSByte(ToInt32(value));
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(decimal value) {
+ return Decimal.ToSByte(Decimal.Round(value, 0));
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(String value) {
+ if (value == null)
+ return 0;
+ return SByte.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(String value, IFormatProvider provider) {
+ return SByte.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(DateTime value)
+ {
+ return ((IConvertible)value).ToSByte(null);
+ }
+
+ // Disallowed conversions to SByte
+ // public static sbyte ToSByte(TimeSpan value)
+
+ // Conversions to Byte
+
+ public static byte ToByte(object value) {
+ return value == null? (byte)0: ((IConvertible)value).ToByte(null);
+ }
+
+ public static byte ToByte(object value, IFormatProvider provider) {
+ return value == null? (byte)0: ((IConvertible)value).ToByte(provider);
+ }
+
+ public static byte ToByte(bool value) {
+ return value? (byte)Boolean.True: (byte)Boolean.False;
+ }
+
+ public static byte ToByte(byte value) {
+ return value;
+ }
+
+ public static byte ToByte(char value) {
+ if (value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static byte ToByte(sbyte value) {
+ if (value < Byte.MinValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ public static byte ToByte(short value) {
+ if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static byte ToByte(ushort value) {
+ if (value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ public static byte ToByte(int value) {
+ if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static byte ToByte(uint value) {
+ if (value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ public static byte ToByte(long value) {
+ if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ [CLSCompliant(false)]
+ public static byte ToByte(ulong value) {
+ if (value > Byte.MaxValue) ThrowByteOverflowException();
+ Contract.EndContractBlock();
+ return (byte)value;
+ }
+
+ public static byte ToByte(float value) {
+ return ToByte((double)value);
+ }
+
+ public static byte ToByte(double value) {
+ return ToByte(ToInt32(value));
+ }
+
+ public static byte ToByte(decimal value) {
+ return Decimal.ToByte(Decimal.Round(value, 0));
+ }
+
+ public static byte ToByte(String value) {
+ if (value == null)
+ return 0;
+ return Byte.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static byte ToByte(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Byte.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ public static byte ToByte(DateTime value)
+ {
+ return ((IConvertible)value).ToByte(null);
+ }
+
+
+ // Disallowed conversions to Byte
+ // public static byte ToByte(TimeSpan value)
+
+ // Conversions to Int16
+
+ public static short ToInt16(object value) {
+ return value == null? (short)0: ((IConvertible)value).ToInt16(null);
+ }
+
+ public static short ToInt16(object value, IFormatProvider provider) {
+ return value == null? (short)0: ((IConvertible)value).ToInt16(provider);
+ }
+
+ public static short ToInt16(bool value) {
+ return value? (short)Boolean.True: (short)Boolean.False;
+ }
+
+ public static short ToInt16(char value) {
+ if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ [CLSCompliant(false)]
+ public static short ToInt16(sbyte value) {
+ return value;
+ }
+
+ public static short ToInt16(byte value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static short ToInt16(ushort value) {
+ if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ public static short ToInt16(int value) {
+ if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ [CLSCompliant(false)]
+ public static short ToInt16(uint value) {
+ if (value > Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ public static short ToInt16(short value) {
+ return value;
+ }
+
+ public static short ToInt16(long value) {
+ if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ [CLSCompliant(false)]
+ public static short ToInt16(ulong value) {
+ if (value > (ulong)Int16.MaxValue) ThrowInt16OverflowException();
+ Contract.EndContractBlock();
+ return (short)value;
+ }
+
+ public static short ToInt16(float value) {
+ return ToInt16((double)value);
+ }
+
+ public static short ToInt16(double value) {
+ return ToInt16(ToInt32(value));
+ }
+
+ public static short ToInt16(decimal value) {
+ return Decimal.ToInt16(Decimal.Round(value, 0));
+ }
+
+ public static short ToInt16(String value) {
+ if (value == null)
+ return 0;
+ return Int16.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static short ToInt16(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Int16.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ public static short ToInt16(DateTime value)
+ {
+ return ((IConvertible)value).ToInt16(null);
+ }
+
+
+ // Disallowed conversions to Int16
+ // public static short ToInt16(TimeSpan value)
+
+ // Conversions to UInt16
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(object value) {
+ return value == null? (ushort)0: ((IConvertible)value).ToUInt16(null);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(object value, IFormatProvider provider) {
+ return value == null? (ushort)0: ((IConvertible)value).ToUInt16(provider);
+ }
+
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(bool value) {
+ return value? (ushort)Boolean.True: (ushort)Boolean.False;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(char value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(sbyte value) {
+ if (value < 0) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(byte value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(short value) {
+ if (value < 0) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(int value) {
+ if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(ushort value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(uint value) {
+ if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(long value) {
+ if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(ulong value) {
+ if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
+ Contract.EndContractBlock();
+ return (ushort)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(float value) {
+ return ToUInt16((double)value);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(double value) {
+ return ToUInt16(ToInt32(value));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(decimal value) {
+ return Decimal.ToUInt16(Decimal.Round(value, 0));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(String value) {
+ if (value == null)
+ return 0;
+ return UInt16.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return UInt16.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(DateTime value)
+ {
+ return ((IConvertible)value).ToUInt16(null);
+ }
+
+ // Disallowed conversions to UInt16
+ // public static ushort ToUInt16(TimeSpan value)
+
+ // Conversions to Int32
+
+ public static int ToInt32(object value) {
+ return value == null? 0: ((IConvertible)value).ToInt32(null);
+ }
+
+ public static int ToInt32(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToInt32(provider);
+ }
+
+
+ public static int ToInt32(bool value) {
+ return value? Boolean.True: Boolean.False;
+ }
+
+ public static int ToInt32(char value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static int ToInt32(sbyte value) {
+ return value;
+ }
+
+ public static int ToInt32(byte value) {
+ return value;
+ }
+
+ public static int ToInt32(short value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static int ToInt32(ushort value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static int ToInt32(uint value) {
+ if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ Contract.EndContractBlock();
+ return (int)value;
+ }
+
+ public static int ToInt32(int value) {
+ return value;
+ }
+
+ public static int ToInt32(long value) {
+ if (value < Int32.MinValue || value > Int32.MaxValue) ThrowInt32OverflowException();
+ Contract.EndContractBlock();
+ return (int)value;
+ }
+
+ [CLSCompliant(false)]
+ public static int ToInt32(ulong value) {
+ if (value > Int32.MaxValue) ThrowInt32OverflowException();
+ Contract.EndContractBlock();
+ return (int)value;
+ }
+
+ public static int ToInt32(float value) {
+ return ToInt32((double)value);
+ }
+
+ public static int ToInt32(double value) {
+ if (value >= 0) {
+ if (value < 2147483647.5) {
+ int result = (int)value;
+ double dif = value - result;
+ if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++;
+ return result;
+ }
+ }
+ else {
+ if (value >= -2147483648.5) {
+ int result = (int)value;
+ double dif = value - result;
+ if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--;
+ return result;
+ }
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int ToInt32(decimal value) {
+ return Decimal.FCallToInt32(value);
+ }
+
+ public static int ToInt32(String value) {
+ if (value == null)
+ return 0;
+ return Int32.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static int ToInt32(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Int32.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ public static int ToInt32(DateTime value)
+ {
+ return ((IConvertible)value).ToInt32(null);
+ }
+
+
+ // Disallowed conversions to Int32
+ // public static int ToInt32(TimeSpan value)
+
+ // Conversions to UInt32
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(object value) {
+ return value == null? 0: ((IConvertible)value).ToUInt32(null);
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToUInt32(provider);
+ }
+
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(bool value) {
+ return value? (uint)Boolean.True: (uint)Boolean.False;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(char value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(sbyte value) {
+ if (value < 0) ThrowUInt32OverflowException();
+ Contract.EndContractBlock();
+ return (uint)value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(byte value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(short value) {
+ if (value < 0) ThrowUInt32OverflowException();
+ Contract.EndContractBlock();
+ return (uint)value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(ushort value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(int value) {
+ if (value < 0) ThrowUInt32OverflowException();
+ Contract.EndContractBlock();
+ return (uint)value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(uint value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(long value) {
+ if (value < 0 || value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ Contract.EndContractBlock();
+ return (uint)value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(ulong value) {
+ if (value > UInt32.MaxValue) ThrowUInt32OverflowException();
+ Contract.EndContractBlock();
+ return (uint)value;
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(float value) {
+ return ToUInt32((double)value);
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(double value) {
+ if (value >= -0.5 && value < 4294967295.5) {
+ uint result = (uint)value;
+ double dif = value - result;
+ if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++;
+ return result;
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt32"));
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(decimal value) {
+ return Decimal.ToUInt32(Decimal.Round(value, 0));
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(String value) {
+ if (value == null)
+ return 0;
+ return UInt32.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return UInt32.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ [CLSCompliant(false)]
+ public static uint ToUInt32(DateTime value)
+ {
+ return ((IConvertible)value).ToUInt32(null);
+ }
+
+ // Disallowed conversions to UInt32
+ // public static uint ToUInt32(TimeSpan value)
+
+ // Conversions to Int64
+
+ public static long ToInt64(object value) {
+ return value == null? 0: ((IConvertible)value).ToInt64(null);
+ }
+
+ public static long ToInt64(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToInt64(provider);
+ }
+
+
+ public static long ToInt64(bool value) {
+ return value? Boolean.True: Boolean.False;
+ }
+
+ public static long ToInt64(char value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static long ToInt64(sbyte value) {
+ return value;
+ }
+
+ public static long ToInt64(byte value) {
+ return value;
+ }
+
+ public static long ToInt64(short value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static long ToInt64(ushort value) {
+ return value;
+ }
+
+ public static long ToInt64(int value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static long ToInt64(uint value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static long ToInt64(ulong value) {
+ if (value > Int64.MaxValue) ThrowInt64OverflowException();
+ Contract.EndContractBlock();
+ return (long)value;
+ }
+
+ public static long ToInt64(long value) {
+ return value;
+ }
+
+
+ public static long ToInt64(float value) {
+ return ToInt64((double)value);
+ }
+
+ public static long ToInt64(double value) {
+ return checked((long)Math.Round(value));
+ }
+
+ public static long ToInt64(decimal value) {
+ return Decimal.ToInt64(Decimal.Round(value, 0));
+ }
+
+ public static long ToInt64(string value) {
+ if (value == null)
+ return 0;
+ return Int64.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static long ToInt64(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Int64.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ public static long ToInt64(DateTime value)
+ {
+ return ((IConvertible)value).ToInt64(null);
+ }
+
+ // Disallowed conversions to Int64
+ // public static long ToInt64(TimeSpan value)
+
+ // Conversions to UInt64
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(object value) {
+ return value == null? 0: ((IConvertible)value).ToUInt64(null);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToUInt64(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(bool value) {
+ return value? (ulong)Boolean.True: (ulong)Boolean.False;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(char value) {
+ return value;
+ }
+
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(sbyte value) {
+ if (value < 0) ThrowUInt64OverflowException();
+ Contract.EndContractBlock();
+ return (ulong)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(byte value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(short value) {
+ if (value < 0) ThrowUInt64OverflowException();
+ Contract.EndContractBlock();
+ return (ulong)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(ushort value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(int value) {
+ if (value < 0) ThrowUInt64OverflowException();
+ Contract.EndContractBlock();
+ return (ulong)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(uint value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(long value) {
+ if (value < 0) ThrowUInt64OverflowException();
+ Contract.EndContractBlock();
+ return (ulong)value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(UInt64 value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(float value) {
+ return ToUInt64((double)value);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(double value) {
+ return checked((ulong)Math.Round(value));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(decimal value) {
+ return Decimal.ToUInt64(Decimal.Round(value, 0));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(String value) {
+ if (value == null)
+ return 0;
+ return UInt64.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return UInt64.Parse(value, NumberStyles.Integer, provider);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(DateTime value)
+ {
+ return ((IConvertible)value).ToUInt64(null);
+ }
+
+ // Disallowed conversions to UInt64
+ // public static ulong ToUInt64(TimeSpan value)
+
+ // Conversions to Single
+
+ public static float ToSingle(object value) {
+ return value == null? 0: ((IConvertible)value).ToSingle(null);
+ }
+
+ public static float ToSingle(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToSingle(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static float ToSingle(sbyte value) {
+ return value;
+ }
+
+ public static float ToSingle(byte value) {
+ return value;
+ }
+
+ public static float ToSingle(char value) {
+ return ((IConvertible)value).ToSingle(null);
+ }
+
+ public static float ToSingle(short value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static float ToSingle(ushort value) {
+ return value;
+ }
+
+ public static float ToSingle(int value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static float ToSingle(uint value) {
+ return value;
+ }
+
+ public static float ToSingle(long value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static float ToSingle(ulong value) {
+ return value;
+ }
+
+ public static float ToSingle(float value) {
+ return value;
+ }
+
+ public static float ToSingle(double value) {
+ return (float)value;
+ }
+
+ public static float ToSingle(decimal value) {
+ return (float)value;
+ }
+
+ public static float ToSingle(String value) {
+ if (value == null)
+ return 0;
+ return Single.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static float ToSingle(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Single.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ }
+
+
+ public static float ToSingle(bool value)
+ {
+ return value? Boolean.True: Boolean.False;
+ }
+
+ public static float ToSingle(DateTime value)
+ {
+ return ((IConvertible)value).ToSingle(null);
+ }
+
+ // Disallowed conversions to Single
+ // public static float ToSingle(TimeSpan value)
+
+ // Conversions to Double
+
+ public static double ToDouble(object value) {
+ return value == null? 0: ((IConvertible)value).ToDouble(null);
+ }
+
+ public static double ToDouble(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToDouble(provider);
+ }
+
+
+ [CLSCompliant(false)]
+ public static double ToDouble(sbyte value) {
+ return value;
+ }
+
+ public static double ToDouble(byte value) {
+ return value;
+ }
+
+ public static double ToDouble(short value) {
+ return value;
+ }
+
+ public static double ToDouble(char value) {
+ return ((IConvertible)value).ToDouble(null);
+ }
+
+ [CLSCompliant(false)]
+ public static double ToDouble(ushort value) {
+ return value;
+ }
+
+ public static double ToDouble(int value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static double ToDouble(uint value) {
+ return value;
+ }
+
+ public static double ToDouble(long value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static double ToDouble(ulong value) {
+ return value;
+ }
+
+ public static double ToDouble(float value) {
+ return value;
+ }
+
+ public static double ToDouble(double value) {
+ return value;
+ }
+
+ public static double ToDouble(decimal value) {
+ return (double)value;
+ }
+
+ public static double ToDouble(String value) {
+ if (value == null)
+ return 0;
+ return Double.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static double ToDouble(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0;
+ return Double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
+ }
+
+ public static double ToDouble(bool value) {
+ return value? Boolean.True: Boolean.False;
+ }
+
+ public static double ToDouble(DateTime value)
+ {
+ return ((IConvertible)value).ToDouble(null);
+ }
+
+ // Disallowed conversions to Double
+ // public static double ToDouble(TimeSpan value)
+
+ // Conversions to Decimal
+
+ public static decimal ToDecimal(object value) {
+ return value == null? 0: ((IConvertible)value).ToDecimal(null);
+ }
+
+ public static decimal ToDecimal(object value, IFormatProvider provider) {
+ return value == null? 0: ((IConvertible)value).ToDecimal(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static decimal ToDecimal(sbyte value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(byte value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(char value) {
+ return ((IConvertible)value).ToDecimal(null);
+ }
+
+ public static decimal ToDecimal(short value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static decimal ToDecimal(ushort value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(int value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static decimal ToDecimal(uint value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(long value) {
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ public static decimal ToDecimal(ulong value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(float value) {
+ return (decimal)value;
+ }
+
+ public static decimal ToDecimal(double value) {
+ return (decimal)value;
+ }
+
+ public static decimal ToDecimal(String value) {
+ if (value == null)
+ return 0m;
+ return Decimal.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static Decimal ToDecimal(String value, IFormatProvider provider) {
+ if (value == null)
+ return 0m;
+ return Decimal.Parse(value, NumberStyles.Number, provider);
+ }
+
+ public static decimal ToDecimal(decimal value) {
+ return value;
+ }
+
+ public static decimal ToDecimal(bool value) {
+ return value? Boolean.True: Boolean.False;
+ }
+
+ public static decimal ToDecimal(DateTime value)
+ {
+ return ((IConvertible)value).ToDecimal(null);
+ }
+
+ // Disallowed conversions to Decimal
+ // public static decimal ToDecimal(TimeSpan value)
+
+ // Conversions to DateTime
+
+ public static DateTime ToDateTime(DateTime value) {
+ return value;
+ }
+
+ public static DateTime ToDateTime(object value) {
+ return value == null? DateTime.MinValue: ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(object value, IFormatProvider provider) {
+ return value == null? DateTime.MinValue: ((IConvertible)value).ToDateTime(provider);
+ }
+
+ public static DateTime ToDateTime(String value) {
+ if (value == null)
+ return new DateTime(0);
+ return DateTime.Parse(value, CultureInfo.CurrentCulture);
+ }
+
+ public static DateTime ToDateTime(String value, IFormatProvider provider) {
+ if (value == null)
+ return new DateTime(0);
+ return DateTime.Parse(value, provider);
+ }
+
+ [CLSCompliant(false)]
+ public static DateTime ToDateTime(sbyte value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(byte value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(short value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ [CLSCompliant(false)]
+ public static DateTime ToDateTime(ushort value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(int value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ [CLSCompliant(false)]
+ public static DateTime ToDateTime(uint value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(long value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ [CLSCompliant(false)]
+ public static DateTime ToDateTime(ulong value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(bool value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(char value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(float value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(double value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ public static DateTime ToDateTime(decimal value) {
+ return ((IConvertible)value).ToDateTime(null);
+ }
+
+ // Disallowed conversions to DateTime
+ // public static DateTime ToDateTime(TimeSpan value)
+
+ // Conversions to String
+
+ public static string ToString(Object value) {
+ return ToString(value,null);
+ }
+
+ public static string ToString(Object value, IFormatProvider provider) {
+ IConvertible ic = value as IConvertible;
+ if (ic != null)
+ return ic.ToString(provider);
+ IFormattable formattable = value as IFormattable;
+ if (formattable != null)
+ return formattable.ToString(null, provider);
+ return value == null? String.Empty: value.ToString();
+ }
+
+ public static string ToString(bool value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString();
+ }
+
+ public static string ToString(bool value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(char value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return Char.ToString(value);
+ }
+
+ public static string ToString(char value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(sbyte value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(sbyte value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(byte value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(byte value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(short value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(short value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(ushort value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(ushort value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(int value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(int value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(uint value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(uint value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(long value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(long value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(ulong value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ [CLSCompliant(false)]
+ public static string ToString(ulong value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(float value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(float value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(double value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(double value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(decimal value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(CultureInfo.CurrentCulture);
+ }
+
+ public static string ToString(Decimal value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static string ToString(DateTime value) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString();
+ }
+
+ public static string ToString(DateTime value, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() != null);
+ return value.ToString(provider);
+ }
+
+ public static String ToString(String value) {
+ Contract.Ensures(Contract.Result<string>() == value); // We were always skipping the null check here.
+ return value;
+ }
+
+ public static String ToString(String value,IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<string>() == value); // We were always skipping the null check here.
+ return value; // avoid the null check
+ }
+
+
+ //
+ // Conversions which understand Base XXX numbers.
+ //
+ // Parses value in base base. base can only
+ // be 2, 8, 10, or 16. If base is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ public static byte ToByte (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ int r = ParseNumbers.StringToInt(value,fromBase,ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
+ if (r < Byte.MinValue || r > Byte.MaxValue)
+ ThrowByteOverflowException();
+ return (byte) r;
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ [CLSCompliant(false)]
+ public static sbyte ToSByte (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ int r = ParseNumbers.StringToInt(value,fromBase,ParseNumbers.IsTight | ParseNumbers.TreatAsI1);
+ if (fromBase != 10 && r <= Byte.MaxValue)
+ return (sbyte)r;
+
+ if (r < SByte.MinValue || r > SByte.MaxValue)
+ ThrowSByteOverflowException();
+ return (sbyte) r;
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ public static short ToInt16 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ int r = ParseNumbers.StringToInt(value,fromBase,ParseNumbers.IsTight | ParseNumbers.TreatAsI2);
+ if (fromBase != 10 && r <= UInt16.MaxValue)
+ return (short)r;
+
+ if (r < Int16.MinValue || r > Int16.MaxValue)
+ ThrowInt16OverflowException();
+ return (short) r;
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ [CLSCompliant(false)]
+ public static ushort ToUInt16 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ int r = ParseNumbers.StringToInt(value,fromBase,ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
+ if (r < UInt16.MinValue || r > UInt16.MaxValue)
+ ThrowUInt16OverflowException();
+ return (ushort) r;
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ public static int ToInt32 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.StringToInt(value,fromBase,ParseNumbers.IsTight);
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ [CLSCompliant(false)]
+ public static uint ToUInt32 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return (uint) ParseNumbers.StringToInt(value,fromBase, ParseNumbers.TreatAsUnsigned | ParseNumbers.IsTight);
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ public static long ToInt64 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.StringToLong(value,fromBase,ParseNumbers.IsTight);
+ }
+
+ // Parses value in base fromBase. fromBase can only
+ // be 2, 8, 10, or 16. If fromBase is 16, the number may be preceded
+ // by 0x; any other leading or trailing characters cause an error.
+ //
+ [CLSCompliant(false)]
+ public static ulong ToUInt64 (String value, int fromBase) {
+ if (fromBase!=2 && fromBase!=8 && fromBase!=10 && fromBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return (ulong) ParseNumbers.StringToLong(value,fromBase, ParseNumbers.TreatAsUnsigned | ParseNumbers.IsTight);
+ }
+
+ // Convert the byte value to a string in base fromBase
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ToString (byte value, int toBase) {
+ if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.IntToString((int)value, toBase, -1, ' ', ParseNumbers.PrintAsI1);
+ }
+
+ // Convert the Int16 value to a string in base fromBase
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ToString (short value, int toBase) {
+ if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.IntToString((int)value, toBase, -1, ' ', ParseNumbers.PrintAsI2);
+ }
+
+ // Convert the Int32 value to a string in base toBase
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ToString (int value, int toBase) {
+ if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.IntToString(value, toBase, -1, ' ', 0);
+ }
+
+ // Convert the Int64 value to a string in base toBase
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ToString (long value, int toBase) {
+ if (toBase!=2 && toBase!=8 && toBase!=10 && toBase!=16) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidBase"));
+ }
+ Contract.EndContractBlock();
+ return ParseNumbers.LongToString(value, toBase, -1, ' ', 0);
+ }
+
+ public static String ToBase64String(byte[] inArray) {
+ if (inArray==null) {
+ throw new ArgumentNullException("inArray");
+ }
+ Contract.Ensures(Contract.Result<string>() != null);
+ Contract.EndContractBlock();
+ return ToBase64String(inArray, 0, inArray.Length, Base64FormattingOptions.None);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static String ToBase64String(byte[] inArray, Base64FormattingOptions options) {
+ if (inArray==null) {
+ throw new ArgumentNullException("inArray");
+ }
+ Contract.Ensures(Contract.Result<string>() != null);
+ Contract.EndContractBlock();
+ return ToBase64String(inArray, 0, inArray.Length, options);
+ }
+
+ public static String ToBase64String(byte[] inArray, int offset, int length) {
+ return ToBase64String(inArray, offset, length, Base64FormattingOptions.None);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static unsafe String ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options) {
+ //Do data verfication
+ if (inArray==null)
+ throw new ArgumentNullException("inArray");
+ if (length<0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (offset<0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ if (options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options));
+ Contract.Ensures(Contract.Result<string>() != null);
+ Contract.EndContractBlock();
+
+ int inArrayLength;
+ int stringLength;
+
+ inArrayLength = inArray.Length;
+ if (offset > (inArrayLength - length))
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"));
+
+ if (inArrayLength == 0)
+ return String.Empty;
+
+ bool insertLineBreaks = (options == Base64FormattingOptions.InsertLineBreaks);
+ //Create the new string. This is the maximally required length.
+ stringLength = ToBase64_CalculateAndValidateOutputLength(length, insertLineBreaks);
+
+ string returnString = string.FastAllocateString(stringLength);
+ fixed (char* outChars = returnString){
+ fixed (byte* inData = inArray) {
+ int j = ConvertToBase64Array(outChars,inData,offset,length, insertLineBreaks);
+ BCLDebug.Assert(returnString.Length == j, "returnString.Length == j");
+ return returnString;
+ }
+ }
+ }
+
+ public static int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut) {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= outArray.Length);
+ Contract.EndContractBlock();
+
+ return ToBase64CharArray(inArray, offsetIn, length, outArray, offsetOut, Base64FormattingOptions.None);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static unsafe int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, Base64FormattingOptions options) {
+ //Do data verfication
+ if (inArray==null)
+ throw new ArgumentNullException("inArray");
+ if (outArray==null)
+ throw new ArgumentNullException("outArray");
+ if (length<0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (offsetIn<0)
+ throw new ArgumentOutOfRangeException("offsetIn", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ if (offsetOut<0)
+ throw new ArgumentOutOfRangeException("offsetOut", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+
+ if( options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options));
+ }
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= outArray.Length);
+ Contract.EndContractBlock();
+
+
+ int retVal;
+
+ int inArrayLength;
+ int outArrayLength;
+ int numElementsToCopy;
+
+ inArrayLength = inArray.Length;
+
+ if (offsetIn > (int)(inArrayLength - length))
+ throw new ArgumentOutOfRangeException("offsetIn", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"));
+
+ if (inArrayLength == 0)
+ return 0;
+
+ bool insertLineBreaks = (options == Base64FormattingOptions.InsertLineBreaks);
+ //This is the maximally required length that must be available in the char array
+ outArrayLength = outArray.Length;
+
+ // Length of the char buffer required
+ numElementsToCopy = ToBase64_CalculateAndValidateOutputLength(length, insertLineBreaks);
+
+ if (offsetOut > (int)(outArrayLength - numElementsToCopy))
+ throw new ArgumentOutOfRangeException("offsetOut", Environment.GetResourceString("ArgumentOutOfRange_OffsetOut"));
+
+ fixed (char* outChars = &outArray[offsetOut]) {
+ fixed (byte* inData = inArray) {
+ retVal = ConvertToBase64Array(outChars,inData,offsetIn,length, insertLineBreaks);
+ }
+ }
+
+ return retVal;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int offset, int length, bool insertLineBreaks) {
+ int lengthmod3 = length%3;
+ int calcLength = offset + (length - lengthmod3);
+ int j=0;
+ int charcount = 0;
+ //Convert three bytes at a time to base64 notation. This will consume 4 chars.
+ int i;
+
+ // get a pointer to the base64Table to avoid unnecessary range checking
+ fixed(char* base64 = base64Table) {
+ for (i=offset; i<calcLength; i+=3)
+ {
+ if (insertLineBreaks) {
+ if (charcount == base64LineBreakPosition) {
+ outChars[j++] = '\r';
+ outChars[j++] = '\n';
+ charcount = 0;
+ }
+ charcount += 4;
+ }
+ outChars[j] = base64[(inData[i]&0xfc)>>2];
+ outChars[j+1] = base64[((inData[i]&0x03)<<4) | ((inData[i+1]&0xf0)>>4)];
+ outChars[j+2] = base64[((inData[i+1]&0x0f)<<2) | ((inData[i+2]&0xc0)>>6)];
+ outChars[j+3] = base64[(inData[i+2]&0x3f)];
+ j += 4;
+ }
+
+ //Where we left off before
+ i = calcLength;
+
+ if (insertLineBreaks && (lengthmod3 !=0) && (charcount == base64LineBreakPosition)) {
+ outChars[j++] = '\r';
+ outChars[j++] = '\n';
+ }
+
+ switch(lengthmod3)
+ {
+ case 2: //One character padding needed
+ outChars[j] = base64[(inData[i]&0xfc)>>2];
+ outChars[j+1] = base64[((inData[i]&0x03)<<4)|((inData[i+1]&0xf0)>>4)];
+ outChars[j+2] = base64[(inData[i+1]&0x0f)<<2];
+ outChars[j+3] = base64[64]; //Pad
+ j+=4;
+ break;
+ case 1: // Two character padding needed
+ outChars[j] = base64[(inData[i]&0xfc)>>2];
+ outChars[j+1] = base64[(inData[i]&0x03)<<4];
+ outChars[j+2] = base64[64]; //Pad
+ outChars[j+3] = base64[64]; //Pad
+ j+=4;
+ break;
+ }
+ }
+
+ return j;
+ }
+
+ private static int ToBase64_CalculateAndValidateOutputLength(int inputLength, bool insertLineBreaks) {
+ long outlen = ((long)inputLength) / 3 * 4; // the base length - we want integer division here.
+ outlen += ((inputLength % 3) != 0) ? 4 : 0; // at most 4 more chars for the remainder
+
+ if (outlen == 0)
+ return 0;
+
+ if (insertLineBreaks) {
+ long newLines = outlen / base64LineBreakPosition;
+ if ((outlen % base64LineBreakPosition) == 0) {
+ --newLines;
+ }
+ outlen += newLines * 2; // the number of line break chars we'll add, "\r\n"
+ }
+
+ // If we overflow an int then we cannot allocate enough
+ // memory to output the value so throw
+ if (outlen > int.MaxValue)
+ throw new OutOfMemoryException();
+
+ return (int)outlen;
+ }
+
+
+ /// <summary>
+ /// Converts the specified string, which encodes binary data as Base64 digits, to the equivalent byte array.
+ /// </summary>
+ /// <param name="s">The string to convert</param>
+ /// <returns>The array of bytes represented by the specifed Base64 string.</returns>
+ [SecuritySafeCritical]
+ public static Byte[] FromBase64String(String s) {
+
+ // "s" is an unfortunate parameter name, but we need to keep it for backward compat.
+
+ if (s == null)
+ throw new ArgumentNullException("s");
+
+ Contract.EndContractBlock();
+
+ unsafe {
+ fixed (Char* sPtr = s) {
+
+ return FromBase64CharPtr(sPtr, s.Length);
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.
+ /// </summary>
+ /// <param name="inArray">Chars representing Base64 encoding characters</param>
+ /// <param name="offset">A position within the input array.</param>
+ /// <param name="length">Number of element to convert.</param>
+ /// <returns>The array of bytes represented by the specified Base64 encoding characters.</returns>
+ [SecuritySafeCritical]
+ public static Byte[] FromBase64CharArray(Char[] inArray, Int32 offset, Int32 length) {
+
+ if (inArray == null)
+ throw new ArgumentNullException("inArray");
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+
+ if (offset > inArray.Length - length)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"));
+
+ Contract.EndContractBlock();
+
+ unsafe {
+ fixed (Char* inArrayPtr = inArray) {
+
+ return FromBase64CharPtr(inArrayPtr + offset, length);
+ }
+ }
+ }
+
+
+
+ /// <summary>
+ /// Convert Base64 encoding characters to bytes:
+ /// - Compute result length exactly by actually walking the input;
+ /// - Allocate new result array based on computation;
+ /// - Decode input into the new array;
+ /// </summary>
+ /// <param name="inputPtr">Pointer to the first input char</param>
+ /// <param name="inputLength">Number of input chars</param>
+ /// <returns></returns>
+ [SecurityCritical]
+ private static unsafe Byte[] FromBase64CharPtr(Char* inputPtr, Int32 inputLength) {
+
+ // The validity of parameters much be checked by callers, thus we are Critical here.
+
+ Contract.Assert(0 <= inputLength);
+
+ // We need to get rid of any trailing white spaces.
+ // Otherwise we would be rejecting input such as "abc= ":
+ while (inputLength > 0)
+ {
+ Int32 lastChar = inputPtr[inputLength - 1];
+ if (lastChar != (Int32) ' ' && lastChar != (Int32) '\n' && lastChar != (Int32) '\r' && lastChar != (Int32) '\t')
+ break;
+ inputLength--;
+ }
+
+ // Compute the output length:
+ Int32 resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
+
+ Contract.Assert(0 <= resultLength);
+
+ // resultLength can be zero. We will still enter FromBase64_Decode and process the input.
+ // It may either simply write no bytes (e.g. input = " ") or throw (e.g. input = "ab").
+
+ // Create result byte blob:
+ Byte[] decodedBytes = new Byte[resultLength];
+
+ // Convert Base64 chars into bytes:
+ Int32 actualResultLength;
+ fixed (Byte* decodedBytesPtr = decodedBytes)
+ actualResultLength = FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
+
+ // Note that actualResultLength can differ from resultLength if the caller is modifying the array
+ // as it is being converted. Silently ignore the failure.
+ // Consider throwing exception in an non in-place release.
+
+ // We are done:
+ return decodedBytes;
+ }
+
+
+ /// <summary>
+ /// Decode characters representing a Base64 encoding into bytes:
+ /// Walk the input. Every time 4 chars are read, convert them to the 3 corresponding output bytes.
+ /// This method is a bit lengthy on purpose. We are trying to avoid jumps to helpers in the loop
+ /// to aid performance.
+ /// </summary>
+ /// <param name="inputPtr">Pointer to first input char</param>
+ /// <param name="inputLength">Number of input chars</param>
+ /// <param name="destPtr">Pointer to location for the first result byte</param>
+ /// <param name="destLength">Max length of the preallocated result buffer</param>
+ /// <returns>If the result buffer was not large enough to write all result bytes, return -1;
+ /// Otherwise return the number of result bytes actually produced.</returns>
+ [SecurityCritical]
+ private static unsafe Int32 FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength) {
+
+ // You may find this method weird to look at. It’s written for performance, not aesthetics.
+ // You will find unrolled loops label jumps and bit manipulations.
+
+ const UInt32 intA = (UInt32) 'A';
+ const UInt32 inta = (UInt32) 'a';
+ const UInt32 int0 = (UInt32) '0';
+ const UInt32 intEq = (UInt32) '=';
+ const UInt32 intPlus = (UInt32) '+';
+ const UInt32 intSlash = (UInt32) '/';
+ const UInt32 intSpace = (UInt32) ' ';
+ const UInt32 intTab = (UInt32) '\t';
+ const UInt32 intNLn = (UInt32) '\n';
+ const UInt32 intCRt = (UInt32) '\r';
+ const UInt32 intAtoZ = (UInt32) ('Z' - 'A'); // = ('z' - 'a')
+ const UInt32 int0to9 = (UInt32) ('9' - '0');
+
+ Char* inputPtr = startInputPtr;
+ Byte* destPtr = startDestPtr;
+
+ // Pointers to the end of input and output:
+ Char* endInputPtr = inputPtr + inputLength;
+ Byte* endDestPtr = destPtr + destLength;
+
+ // Current char code/value:
+ UInt32 currCode;
+
+ // This 4-byte integer will contain the 4 codes of the current 4-char group.
+ // Eeach char codes for 6 bits = 24 bits.
+ // The remaining byte will be FF, we use it as a marker when 4 chars have been processed.
+ UInt32 currBlockCodes = 0x000000FFu;
+
+ unchecked { while (true) {
+
+ // break when done:
+ if (inputPtr >= endInputPtr)
+ goto _AllInputConsumed;
+
+ // Get current char:
+ currCode = (UInt32) (*inputPtr);
+ inputPtr++;
+
+ // Determine current char code:
+
+ if (currCode - intA <= intAtoZ)
+ currCode -= intA;
+
+ else if (currCode - inta <= intAtoZ)
+ currCode -= (inta - 26u);
+
+ else if (currCode - int0 <= int0to9)
+ currCode -= (int0 - 52u);
+
+ else {
+ // Use the slower switch for less common cases:
+ switch(currCode) {
+
+ // Significant chars:
+ case intPlus: currCode = 62u;
+ break;
+
+ case intSlash: currCode = 63u;
+ break;
+
+ // Legal no-value chars (we ignore these):
+ case intCRt: case intNLn: case intSpace: case intTab:
+ continue;
+
+ // The equality char is only legal at the end of the input.
+ // Jump after the loop to make it easier for the JIT register predictor to do a good job for the loop itself:
+ case intEq:
+ goto _EqualityCharEncountered;
+
+ // Other chars are illegal:
+ default:
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64Char"));
+ }
+ }
+
+ // Ok, we got the code. Save it:
+ currBlockCodes = (currBlockCodes << 6) | currCode;
+
+ // Last bit in currBlockCodes will be on after in shifted right 4 times:
+ if ((currBlockCodes & 0x80000000u) != 0u) {
+
+ if ((Int32) (endDestPtr - destPtr) < 3)
+ return -1;
+
+ *(destPtr) = (Byte) (currBlockCodes >> 16);
+ *(destPtr + 1) = (Byte) (currBlockCodes >> 8);
+ *(destPtr + 2) = (Byte) (currBlockCodes);
+ destPtr += 3;
+
+ currBlockCodes = 0x000000FFu;
+ }
+
+ }} // unchecked while
+
+ // 'd be nice to have an assert that we never get here, but CS0162: Unreachable code detected.
+ // Contract.Assert(false, "We only leave the above loop by jumping; should never get here.");
+
+ // We jump here out of the loop if we hit an '=':
+ _EqualityCharEncountered:
+
+ Contract.Assert(currCode == intEq);
+
+ // Recall that inputPtr is now one position past where '=' was read.
+ // '=' can only be at the last input pos:
+ if (inputPtr == endInputPtr) {
+
+ // Code is zero for trailing '=':
+ currBlockCodes <<= 6;
+
+ // The '=' did not complete a 4-group. The input must be bad:
+ if ((currBlockCodes & 0x80000000u) == 0u)
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64CharArrayLength"));
+
+ if ((int)(endDestPtr - destPtr) < 2) // Autch! We underestimated the output length!
+ return -1;
+
+ // We are good, store bytes form this past group. We had a single "=", so we take two bytes:
+ *(destPtr++) = (Byte) (currBlockCodes >> 16);
+ *(destPtr++) = (Byte) (currBlockCodes >> 8);
+
+ currBlockCodes = 0x000000FFu;
+
+ } else { // '=' can also be at the pre-last position iff the last is also a '=' excluding the white spaces:
+
+ // We need to get rid of any intermediate white spaces.
+ // Otherwise we would be rejecting input such as "abc= =":
+ while (inputPtr < (endInputPtr - 1))
+ {
+ Int32 lastChar = *(inputPtr);
+ if (lastChar != (Int32) ' ' && lastChar != (Int32) '\n' && lastChar != (Int32) '\r' && lastChar != (Int32) '\t')
+ break;
+ inputPtr++;
+ }
+
+ if (inputPtr == (endInputPtr - 1) && *(inputPtr) == '=') {
+
+ // Code is zero for each of the two '=':
+ currBlockCodes <<= 12;
+
+ // The '=' did not complete a 4-group. The input must be bad:
+ if ((currBlockCodes & 0x80000000u) == 0u)
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64CharArrayLength"));
+
+ if ((Int32) (endDestPtr - destPtr) < 1) // Autch! We underestimated the output length!
+ return -1;
+
+ // We are good, store bytes form this past group. We had a "==", so we take only one byte:
+ *(destPtr++) = (Byte) (currBlockCodes >> 16);
+
+ currBlockCodes = 0x000000FFu;
+
+ } else // '=' is not ok at places other than the end:
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64Char"));
+
+ }
+
+ // We get here either from above or by jumping out of the loop:
+ _AllInputConsumed:
+
+ // The last block of chars has less than 4 items
+ if (currBlockCodes != 0x000000FFu)
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64CharArrayLength"));
+
+ // Return how many bytes were actually recovered:
+ return (Int32) (destPtr - startDestPtr);
+
+ } // Int32 FromBase64_Decode(...)
+
+
+ /// <summary>
+ /// Compute the number of bytes encoded in the specified Base 64 char array:
+ /// Walk the entire input counting white spaces and padding chars, then compute result length
+ /// based on 3 bytes per 4 chars.
+ /// </summary>
+ [SecurityCritical]
+ private static unsafe Int32 FromBase64_ComputeResultLength(Char* inputPtr, Int32 inputLength) {
+
+ const UInt32 intEq = (UInt32) '=';
+ const UInt32 intSpace = (UInt32) ' ';
+
+ Contract.Assert(0 <= inputLength);
+
+ Char* inputEndPtr = inputPtr + inputLength;
+ Int32 usefulInputLength = inputLength;
+ Int32 padding = 0;
+
+ while (inputPtr < inputEndPtr) {
+
+ UInt32 c = (UInt32) (*inputPtr);
+ inputPtr++;
+
+ // We want to be as fast as possible and filter out spaces with as few comparisons as possible.
+ // We end up accepting a number of illegal chars as legal white-space chars.
+ // This is ok: as soon as we hit them during actual decode we will recognise them as illegal and throw.
+ if (c <= intSpace)
+ usefulInputLength--;
+
+ else if (c == intEq) {
+ usefulInputLength--;
+ padding++;
+ }
+ }
+
+ Contract.Assert(0 <= usefulInputLength);
+
+ // For legal input, we can assume that 0 <= padding < 3. But it may be more for illegal input.
+ // We will notice it at decode when we see a '=' at the wrong place.
+ Contract.Assert(0 <= padding);
+
+ // Perf: reuse the variable that stored the number of '=' to store the number of bytes encoded by the
+ // last group that contains the '=':
+ if (padding != 0) {
+
+ if (padding == 1)
+ padding = 2;
+ else if (padding == 2)
+ padding = 1;
+ else
+ throw new FormatException(Environment.GetResourceString("Format_BadBase64Char"));
+ }
+
+ // Done:
+ return (usefulInputLength / 4) * 3 + padding;
+ }
+
+ } // class Convert
+} // namespace
+
diff --git a/src/mscorlib/src/System/Currency.cs b/src/mscorlib/src/System/Currency.cs
new file mode 100644
index 0000000000..d29ad2452c
--- /dev/null
+++ b/src/mscorlib/src/System/Currency.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ [Serializable]
+ internal struct Currency
+ {
+ internal long m_value;
+
+ // Constructs a Currency from a Decimal value.
+ //
+ public Currency(Decimal value) {
+ m_value = Decimal.ToCurrency(value).m_value;
+ }
+
+ // Constructs a Currency from a long value without scaling. The
+ // ignored parameter exists only to distinguish this constructor
+ // from the constructor that takes a long. Used only in the System
+ // package, especially in Variant.
+ internal Currency(long value, int ignored) {
+ m_value = value;
+ }
+
+ // Creates a Currency from an OLE Automation Currency. This method
+ // applies no scaling to the Currency value, essentially doing a bitwise
+ // copy.
+ //
+ public static Currency FromOACurrency(long cy){
+ return new Currency(cy, 0);
+ }
+
+ //Creates an OLE Automation Currency from a Currency instance. This
+ // method applies no scaling to the Currency value, essentially doing
+ // a bitwise copy.
+ //
+ public long ToOACurrency() {
+ return m_value;
+ }
+
+ // Converts a Currency to a Decimal.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal ToDecimal(Currency c)
+ {
+ Decimal result = new Decimal ();
+ FCallToDecimal (ref result, c);
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallToDecimal(ref Decimal result,Currency c);
+ }
+}
diff --git a/src/mscorlib/src/System/CurrentTimeZone.cs b/src/mscorlib/src/System/CurrentTimeZone.cs
new file mode 100644
index 0000000000..f015c05b33
--- /dev/null
+++ b/src/mscorlib/src/System/CurrentTimeZone.cs
@@ -0,0 +1,310 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: CurrentTimeZone
+**
+**
+** Purpose:
+** This class represents the current system timezone. It is
+** the only meaningful implementation of the TimeZone class
+** available in this version.
+**
+** The only TimeZone that we support in version 1 is the
+** CurrentTimeZone as determined by the system timezone.
+**
+**
+============================================================*/
+namespace System {
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using System.Threading;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ //
+ // Currently, this is the only supported timezone.
+ // The values of the timezone is from the current system timezone setting in the
+ // control panel.
+ //
+#if FEATURE_CORECLR
+ [Obsolete("System.CurrentSystemTimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo.Local instead.")]
+#endif
+ [Serializable]
+ internal class CurrentSystemTimeZone : TimeZone {
+ // <BUGBUG>BUGBUG :
+ // One problem is when user changes the current timezone. We
+ // are not able to update currentStandardName/currentDaylightName/
+ // currentDaylightChanges.
+ // We need WM_TIMECHANGE to do this or use
+ // RegNotifyChangeKeyValue() to monitor </BUGBUG>
+ //
+ private const long TicksPerMillisecond = 10000;
+ private const long TicksPerSecond = TicksPerMillisecond * 1000;
+ private const long TicksPerMinute = TicksPerSecond * 60;
+
+ // The per-year information is cached in in this instance value. As a result it can
+ // be cleaned up by CultureInfo.ClearCachedData, which will clear the instance of this object
+ private Hashtable m_CachedDaylightChanges = new Hashtable();
+
+ // Standard offset in ticks to the Universal time if
+ // no daylight saving is in used.
+ // E.g. the offset for PST (Pacific Standard time) should be -8 * 60 * 60 * 1000 * 10000.
+ // (1 millisecond = 10000 ticks)
+ private long m_ticksOffset;
+ private String m_standardName;
+ private String m_daylightName;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal CurrentSystemTimeZone() {
+ m_ticksOffset = nativeGetTimeZoneMinuteOffset() * TicksPerMinute;
+ m_standardName = null;
+ m_daylightName = null;
+ }
+
+ public override String StandardName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_standardName == null) {
+ m_standardName = nativeGetStandardName();
+ }
+ return (m_standardName);
+ }
+ }
+
+ public override String DaylightName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_daylightName == null) {
+ m_daylightName = nativeGetDaylightName();
+ if (m_daylightName == null) {
+ m_daylightName = this.StandardName;
+ }
+ }
+ return (m_daylightName);
+ }
+ }
+
+ internal long GetUtcOffsetFromUniversalTime(DateTime time, ref Boolean isAmbiguousLocalDst) {
+ // Get the daylight changes for the year of the specified time.
+ TimeSpan offset = new TimeSpan(m_ticksOffset);
+ DaylightTime daylightTime = GetDaylightChanges(time.Year);
+ isAmbiguousLocalDst= false;
+
+ if (daylightTime == null || daylightTime.Delta.Ticks == 0) {
+ return offset.Ticks;
+ }
+
+ // The start and end times represent the range of universal times that are in DST for that year.
+ // Within that there is an ambiguous hour, usually right at the end, but at the beginning in
+ // the unusual case of a negative daylight savings delta.
+ DateTime startTime = daylightTime.Start - offset;
+ DateTime endTime = daylightTime.End - offset - daylightTime.Delta;
+ DateTime ambiguousStart;
+ DateTime ambiguousEnd;
+ if (daylightTime.Delta.Ticks > 0) {
+ ambiguousStart = endTime - daylightTime.Delta;
+ ambiguousEnd = endTime;
+ } else {
+ ambiguousStart = startTime;
+ ambiguousEnd = startTime - daylightTime.Delta;
+ }
+
+ Boolean isDst = false;
+ if (startTime > endTime) {
+ // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
+ // Note, the summer in the southern hemisphere begins late in the year.
+ isDst = (time < endTime || time >= startTime);
+ }
+ else {
+ // In northern hemisphere, the daylight saving time starts in the middle of the year.
+ isDst = (time>=startTime && time<endTime);
+ }
+ if (isDst) {
+ offset += daylightTime.Delta;
+
+ // See if the resulting local time becomes ambiguous. This must be captured here or the
+ // DateTime will not be able to round-trip back to UTC accurately.
+ if (time >= ambiguousStart && time < ambiguousEnd ) {
+ isAmbiguousLocalDst = true;
+ }
+ }
+ return offset.Ticks;
+ }
+
+ public override DateTime ToLocalTime(DateTime time) {
+ if (time.Kind == DateTimeKind.Local) {
+ return time;
+ }
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offset = GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ long tick = time.Ticks + offset;
+ if (tick>DateTime.MaxTicks) {
+ return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
+ }
+ if (tick<DateTime.MinTicks) {
+ return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
+ }
+ return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject {
+ get {
+ if (s_InternalSyncObject == null) {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override DaylightTime GetDaylightChanges(int year) {
+ if (year < 1 || year > 9999) {
+ throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 9999));
+ }
+ Contract.EndContractBlock();
+
+ Object objYear = (Object)year;
+
+ if (!m_CachedDaylightChanges.Contains(objYear)) {
+ lock (InternalSyncObject) {
+
+ if (!m_CachedDaylightChanges.Contains(objYear)) {
+
+ //
+ // rawData is an array of 17 short (16 bit) numbers.
+ // The first 8 numbers contains the
+ // year/month/day/dayOfWeek/hour/minute/second/millisecond for the starting time of daylight saving time.
+ // The next 8 numbers contains the
+ // year/month/day/dayOfWeek/hour/minute/second/millisecond for the ending time of daylight saving time.
+ // The last short number is the delta to the standard offset in minutes.
+ //
+ short[] rawData = nativeGetDaylightChanges(year);
+
+ if (rawData == null) {
+ //
+ // If rawData is null, it means that daylight saving time is not used
+ // in this timezone. So keep currentDaylightChanges as the empty array.
+ //
+ m_CachedDaylightChanges.Add(objYear, new DaylightTime(DateTime.MinValue, DateTime.MinValue, TimeSpan.Zero));
+ } else {
+ DateTime start;
+ DateTime end;
+ TimeSpan delta;
+
+ //
+ // Store the start of daylight saving time.
+ //
+
+ start = GetDayOfWeek(year, (rawData[0] != 0), rawData[1], rawData[2],
+ rawData[3],
+ rawData[4], rawData[5], rawData[6], rawData[7]);
+
+ //
+ // Store the end of daylight saving time.
+ //
+ end = GetDayOfWeek(year, (rawData[8] != 0), rawData[9], rawData[10],
+ rawData[11],
+ rawData[12], rawData[13], rawData[14], rawData[15]);
+
+ delta = new TimeSpan(rawData[16] * TicksPerMinute);
+ DaylightTime currentDaylightChanges = new DaylightTime(start, end, delta);
+ m_CachedDaylightChanges.Add(objYear, currentDaylightChanges);
+ }
+ }
+ }
+ }
+
+ DaylightTime result = (DaylightTime)m_CachedDaylightChanges[objYear];
+
+ return result;
+ }
+
+ public override TimeSpan GetUtcOffset(DateTime time) {
+ if (time.Kind == DateTimeKind.Utc) {
+ return TimeSpan.Zero;
+ }
+ else {
+ return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset);
+ }
+ }
+
+ //
+ // Return the (numberOfSunday)th day of week in a particular year/month.
+ //
+ private static DateTime GetDayOfWeek(int year, bool fixedDate, int month, int targetDayOfWeek, int numberOfSunday, int hour, int minute, int second, int millisecond) {
+ DateTime time;
+
+ if (fixedDate) {
+ //
+ // Create a Fixed-Date transition time based on the supplied parameters
+ // For Fixed-Dated transition times, the 'numberOfSunday' parameter actually
+ // represents the day of the month.
+ //
+
+ // if the day is out of range for the month then use the last day of the month
+ int day = DateTime.DaysInMonth(year, month);
+
+ time = new DateTime(year, month, (day < numberOfSunday) ? day : numberOfSunday,
+ hour, minute, second, millisecond, DateTimeKind.Local);
+ }
+ else if (numberOfSunday <= 4) {
+ //
+ // Get the (numberOfSunday)th Sunday.
+ //
+
+ time = new DateTime(year, month, 1, hour, minute, second, millisecond, DateTimeKind.Local);
+
+ int dayOfWeek = (int)time.DayOfWeek;
+ int delta = targetDayOfWeek - dayOfWeek;
+ if (delta < 0) {
+ delta += 7;
+ }
+ delta += 7 * (numberOfSunday - 1);
+
+ if (delta > 0) {
+ time = time.AddDays(delta);
+ }
+ } else {
+ //
+ // If numberOfSunday is greater than 4, we will get the last sunday.
+ //
+ Calendar cal = GregorianCalendar.GetDefaultInstance();
+ time = new DateTime(year, month, cal.GetDaysInMonth(year, month), hour, minute, second, millisecond, DateTimeKind.Local);
+ // This is the day of week for the last day of the month.
+ int dayOfWeek = (int)time.DayOfWeek;
+ int delta = dayOfWeek - targetDayOfWeek;
+ if (delta < 0) {
+ delta += 7;
+ }
+
+ if (delta > 0) {
+ time = time.AddDays(-delta);
+ }
+ }
+ return (time);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int nativeGetTimeZoneMinuteOffset();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static String nativeGetDaylightName();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static String nativeGetStandardName();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static short[] nativeGetDaylightChanges(int year);
+ } // class CurrentSystemTimeZone
+}
diff --git a/src/mscorlib/src/System/DBNull.cs b/src/mscorlib/src/System/DBNull.cs
new file mode 100644
index 0000000000..130366d86d
--- /dev/null
+++ b/src/mscorlib/src/System/DBNull.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+// Void
+// This class represents a Missing Variant
+////////////////////////////////////////////////////////////////////////////////
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class DBNull : ISerializable, IConvertible {
+
+ //Package private constructor
+ private DBNull(){
+ }
+
+ private DBNull(SerializationInfo info, StreamingContext context) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DBNullSerial"));
+ }
+
+ public static readonly DBNull Value = new DBNull();
+
+ [System.Security.SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {
+ UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.NullUnity, null, null);
+ }
+
+ public override String ToString() {
+ return String.Empty;
+ }
+
+ public String ToString(IFormatProvider provider) {
+ return String.Empty;
+ }
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.DBNull;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromDBNull"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/DataMisalignedException.cs b/src/mscorlib/src/System/DataMisalignedException.cs
new file mode 100644
index 0000000000..e5332bb9b7
--- /dev/null
+++ b/src/mscorlib/src/System/DataMisalignedException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: The exception class for a misaligned access exception
+**
+=============================================================================*/
+
+namespace System
+{
+ using System;
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DataMisalignedException : SystemException
+ {
+ public DataMisalignedException()
+ : base(Environment.GetResourceString("Arg_DataMisalignedException"))
+ {
+ SetErrorCode(__HResults.COR_E_DATAMISALIGNED);
+ }
+
+ public DataMisalignedException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_DATAMISALIGNED);
+ }
+
+ public DataMisalignedException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ SetErrorCode(__HResults.COR_E_DATAMISALIGNED);
+ }
+
+ internal DataMisalignedException(SerializationInfo info, StreamingContext context)
+ : base (info, context)
+ {
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/DateTime.cs b/src/mscorlib/src/System/DateTime.cs
new file mode 100644
index 0000000000..c464549333
--- /dev/null
+++ b/src/mscorlib/src/System/DateTime.cs
@@ -0,0 +1,1379 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Threading;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using Calendar = System.Globalization.Calendar;
+
+ // This value type represents a date and time. Every DateTime
+ // object has a private field (Ticks) of type Int64 that stores the
+ // date and time as the number of 100 nanosecond intervals since
+ // 12:00 AM January 1, year 1 A.D. in the proleptic Gregorian Calendar.
+ //
+ // Starting from V2.0, DateTime also stored some context about its time
+ // zone in the form of a 3-state value representing Unspecified, Utc or
+ // Local. This is stored in the two top bits of the 64-bit numeric value
+ // with the remainder of the bits storing the tick count. This information
+ // is only used during time zone conversions and is not part of the
+ // identity of the DateTime. Thus, operations like Compare and Equals
+ // ignore this state. This is to stay compatible with earlier behavior
+ // and performance characteristics and to avoid forcing people into dealing
+ // with the effects of daylight savings. Note, that this has little effect
+ // on how the DateTime works except in a context where its specific time
+ // zone is needed, such as during conversions and some parsing and formatting
+ // cases.
+ //
+ // There is also 4th state stored that is a special type of Local value that
+ // is used to avoid data loss when round-tripping between local and UTC time.
+ // See below for more information on this 4th state, although it is
+ // effectively hidden from most users, who just see the 3-state DateTimeKind
+ // enumeration.
+ //
+ // For compatibility, DateTime does not serialize the Kind data when used in
+ // binary serialization.
+ //
+ // For a description of various calendar issues, look at
+ //
+ // Calendar Studies web site, at
+ // http://serendipity.nofadz.com/hermetic/cal_stud.htm.
+ //
+ //
+ [StructLayout(LayoutKind.Auto)]
+ [Serializable]
+ public struct DateTime : IComparable, IFormattable, IConvertible, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
+ {
+
+ // Number of 100ns ticks per time unit
+ private const long TicksPerMillisecond = 10000;
+ private const long TicksPerSecond = TicksPerMillisecond * 1000;
+ private const long TicksPerMinute = TicksPerSecond * 60;
+ private const long TicksPerHour = TicksPerMinute * 60;
+ private const long TicksPerDay = TicksPerHour * 24;
+
+ // Number of milliseconds per time unit
+ private const int MillisPerSecond = 1000;
+ private const int MillisPerMinute = MillisPerSecond * 60;
+ private const int MillisPerHour = MillisPerMinute * 60;
+ private const int MillisPerDay = MillisPerHour * 24;
+
+ // Number of days in a non-leap year
+ private const int DaysPerYear = 365;
+ // Number of days in 4 years
+ private const int DaysPer4Years = DaysPerYear * 4 + 1; // 1461
+ // Number of days in 100 years
+ private const int DaysPer100Years = DaysPer4Years * 25 - 1; // 36524
+ // Number of days in 400 years
+ private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
+
+ // Number of days from 1/1/0001 to 12/31/1600
+ private const int DaysTo1601 = DaysPer400Years * 4; // 584388
+ // Number of days from 1/1/0001 to 12/30/1899
+ private const int DaysTo1899 = DaysPer400Years * 4 + DaysPer100Years * 3 - 367;
+ // Number of days from 1/1/0001 to 12/31/1969
+ internal const int DaysTo1970 = DaysPer400Years * 4 + DaysPer100Years * 3 + DaysPer4Years * 17 + DaysPerYear; // 719,162
+ // Number of days from 1/1/0001 to 12/31/9999
+ private const int DaysTo10000 = DaysPer400Years * 25 - 366; // 3652059
+
+ internal const long MinTicks = 0;
+ internal const long MaxTicks = DaysTo10000 * TicksPerDay - 1;
+ private const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
+
+ private const long FileTimeOffset = DaysTo1601 * TicksPerDay;
+ private const long DoubleDateOffset = DaysTo1899 * TicksPerDay;
+ // The minimum OA date is 0100/01/01 (Note it's year 100).
+ // The maximum OA date is 9999/12/31
+ private const long OADateMinAsTicks = (DaysPer100Years - DaysPerYear) * TicksPerDay;
+ // All OA dates must be greater than (not >=) OADateMinAsDouble
+ private const double OADateMinAsDouble = -657435.0;
+ // All OA dates must be less than (not <=) OADateMaxAsDouble
+ private const double OADateMaxAsDouble = 2958466.0;
+
+ private const int DatePartYear = 0;
+ private const int DatePartDayOfYear = 1;
+ private const int DatePartMonth = 2;
+ private const int DatePartDay = 3;
+
+ private static readonly int[] DaysToMonth365 = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
+ private static readonly int[] DaysToMonth366 = {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
+
+ public static readonly DateTime MinValue = new DateTime(MinTicks, DateTimeKind.Unspecified);
+ public static readonly DateTime MaxValue = new DateTime(MaxTicks, DateTimeKind.Unspecified);
+
+ private const UInt64 TicksMask = 0x3FFFFFFFFFFFFFFF;
+ private const UInt64 FlagsMask = 0xC000000000000000;
+ private const UInt64 LocalMask = 0x8000000000000000;
+ private const Int64 TicksCeiling = 0x4000000000000000;
+ private const UInt64 KindUnspecified = 0x0000000000000000;
+ private const UInt64 KindUtc = 0x4000000000000000;
+ private const UInt64 KindLocal = 0x8000000000000000;
+ private const UInt64 KindLocalAmbiguousDst = 0xC000000000000000;
+ private const Int32 KindShift = 62;
+
+ private const String TicksField = "ticks";
+ private const String DateDataField = "dateData";
+
+ // The data is stored as an unsigned 64-bit integeter
+ // Bits 01-62: The value of 100-nanosecond ticks where 0 represents 1/1/0001 12:00am, up until the value
+ // 12/31/9999 23:59:59.9999999
+ // Bits 63-64: A four-state value that describes the DateTimeKind value of the date time, with a 2nd
+ // value for the rare case where the date time is local, but is in an overlapped daylight
+ // savings time hour and it is in daylight savings time. This allows distinction of these
+ // otherwise ambiguous local times and prevents data loss when round tripping from Local to
+ // UTC time.
+ private UInt64 dateData;
+
+ // Constructs a DateTime from a tick count. The ticks
+ // argument specifies the date as the number of 100-nanosecond intervals
+ // that have elapsed since 1/1/0001 12:00am.
+ //
+ public DateTime(long ticks) {
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks"));
+ Contract.EndContractBlock();
+ dateData = (UInt64)ticks;
+ }
+
+ private DateTime(UInt64 dateData) {
+ this.dateData = dateData;
+ }
+
+ public DateTime(long ticks, DateTimeKind kind) {
+ if (ticks < MinTicks || ticks > MaxTicks) {
+ throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks"));
+ }
+ if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind");
+ }
+ Contract.EndContractBlock();
+ this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ }
+
+ internal DateTime(long ticks, DateTimeKind kind, Boolean isAmbiguousDst) {
+ if (ticks < MinTicks || ticks > MaxTicks) {
+ throw new ArgumentOutOfRangeException("ticks", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadTicks"));
+ }
+ Contract.Requires(kind == DateTimeKind.Local, "Internal Constructor is for local times only");
+ Contract.EndContractBlock();
+ dateData = ((UInt64)ticks | (isAmbiguousDst ? KindLocalAmbiguousDst : KindLocal));
+ }
+
+ // Constructs a DateTime from a given year, month, and day. The
+ // time-of-day of the resulting DateTime is always midnight.
+ //
+ public DateTime(int year, int month, int day) {
+ this.dateData = (UInt64) DateToTicks(year, month, day);
+ }
+
+ // Constructs a DateTime from a given year, month, and day for
+ // the specified calendar. The
+ // time-of-day of the resulting DateTime is always midnight.
+ //
+ public DateTime(int year, int month, int day, Calendar calendar)
+ : this(year, month, day, 0, 0, 0, calendar) {
+ }
+
+ // Constructs a DateTime from a given year, month, day, hour,
+ // minute, and second.
+ //
+ public DateTime(int year, int month, int day, int hour, int minute, int second) {
+ this.dateData = (UInt64)(DateToTicks(year, month, day) + TimeToTicks(hour, minute, second));
+ }
+
+ public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind) {
+ if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind");
+ }
+ Contract.EndContractBlock();
+ Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ }
+
+ // Constructs a DateTime from a given year, month, day, hour,
+ // minute, and second for the specified calendar.
+ //
+ public DateTime(int year, int month, int day, int hour, int minute, int second, Calendar calendar) {
+ if (calendar == null)
+ throw new ArgumentNullException("calendar");
+ Contract.EndContractBlock();
+ this.dateData = (UInt64)calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ }
+
+ // Constructs a DateTime from a given year, month, day, hour,
+ // minute, and second.
+ //
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond) {
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1));
+ }
+ Contract.EndContractBlock();
+ Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ ticks += millisecond * TicksPerMillisecond;
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DateTimeRange"));
+ this.dateData = (UInt64)ticks;
+ }
+
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind) {
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1));
+ }
+ if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind");
+ }
+ Contract.EndContractBlock();
+ Int64 ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+ ticks += millisecond * TicksPerMillisecond;
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DateTimeRange"));
+ this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ }
+
+ // Constructs a DateTime from a given year, month, day, hour,
+ // minute, and second for the specified calendar.
+ //
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar) {
+ if (calendar == null)
+ throw new ArgumentNullException("calendar");
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1));
+ }
+ Contract.EndContractBlock();
+ Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ ticks += millisecond * TicksPerMillisecond;
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DateTimeRange"));
+ this.dateData = (UInt64)ticks;
+ }
+
+ public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind) {
+ if (calendar == null)
+ throw new ArgumentNullException("calendar");
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException("millisecond", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, MillisPerSecond - 1));
+ }
+ if (kind < DateTimeKind.Unspecified || kind > DateTimeKind.Local) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeKind"), "kind");
+ }
+ Contract.EndContractBlock();
+ Int64 ticks = calendar.ToDateTime(year, month, day, hour, minute, second, 0).Ticks;
+ ticks += millisecond * TicksPerMillisecond;
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DateTimeRange"));
+ this.dateData = ((UInt64)ticks | ((UInt64)kind << KindShift));
+ }
+
+ private DateTime(SerializationInfo info, StreamingContext context) {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ Boolean foundTicks = false;
+ Boolean foundDateData = false;
+ Int64 serializedTicks = 0;
+ UInt64 serializedDateData = 0;
+
+
+ // Get the data
+ SerializationInfoEnumerator enumerator = info.GetEnumerator();
+ while( enumerator.MoveNext()) {
+ switch( enumerator.Name) {
+ case TicksField:
+ serializedTicks = Convert.ToInt64(enumerator.Value, CultureInfo.InvariantCulture);
+ foundTicks = true;
+ break;
+ case DateDataField:
+ serializedDateData = Convert.ToUInt64(enumerator.Value, CultureInfo.InvariantCulture);
+ foundDateData = true;
+ break;
+ default:
+ // Ignore other fields for forward compatibility.
+ break;
+ }
+ }
+ if (foundDateData) {
+ this.dateData = serializedDateData;
+ }
+ else if (foundTicks) {
+ this.dateData = (UInt64)serializedTicks;
+ }
+ else {
+ throw new SerializationException(Environment.GetResourceString("Serialization_MissingDateTimeData"));
+ }
+ Int64 ticks = InternalTicks;
+ if (ticks < MinTicks || ticks > MaxTicks) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_DateTimeTicksOutOfRange"));
+ }
+ }
+
+
+
+ internal Int64 InternalTicks {
+ get {
+ return (Int64)(dateData & TicksMask);
+ }
+ }
+
+ private UInt64 InternalKind {
+ get {
+ return (dateData & FlagsMask);
+ }
+ }
+
+ // Returns the DateTime resulting from adding the given
+ // TimeSpan to this DateTime.
+ //
+ public DateTime Add(TimeSpan value) {
+ return AddTicks(value._ticks);
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // time units to this DateTime.
+ private DateTime Add(double value, int scale) {
+ long millis = (long)(value * scale + (value >= 0? 0.5: -0.5));
+ if (millis <= -MaxMillis || millis >= MaxMillis)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
+ return AddTicks(millis * TicksPerMillisecond);
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // days to this DateTime. The result is computed by rounding the
+ // fractional number of days given by value to the nearest
+ // millisecond, and adding that interval to this DateTime. The
+ // value argument is permitted to be negative.
+ //
+ public DateTime AddDays(double value) {
+ return Add(value, MillisPerDay);
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // hours to this DateTime. The result is computed by rounding the
+ // fractional number of hours given by value to the nearest
+ // millisecond, and adding that interval to this DateTime. The
+ // value argument is permitted to be negative.
+ //
+ public DateTime AddHours(double value) {
+ return Add(value, MillisPerHour);
+ }
+
+ // Returns the DateTime resulting from the given number of
+ // milliseconds to this DateTime. The result is computed by rounding
+ // the number of milliseconds given by value to the nearest integer,
+ // and adding that interval to this DateTime. The value
+ // argument is permitted to be negative.
+ //
+ public DateTime AddMilliseconds(double value) {
+ return Add(value, 1);
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // minutes to this DateTime. The result is computed by rounding the
+ // fractional number of minutes given by value to the nearest
+ // millisecond, and adding that interval to this DateTime. The
+ // value argument is permitted to be negative.
+ //
+ public DateTime AddMinutes(double value) {
+ return Add(value, MillisPerMinute);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to this DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of this DateTime by
+ // months months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of this DateTime.
+ //
+ // In more precise terms, considering this DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding months months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+ public DateTime AddMonths(int months) {
+ if (months < -120000 || months > 120000) throw new ArgumentOutOfRangeException("months", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadMonths"));
+ Contract.EndContractBlock();
+ int y = GetDatePart(DatePartYear);
+ int m = GetDatePart(DatePartMonth);
+ int d = GetDatePart(DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0) {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ if (y < 1 || y > 9999) {
+ throw new ArgumentOutOfRangeException("months", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));
+ }
+ int days = DaysInMonth(y, m);
+ if (d > days) d = days;
+ return new DateTime((UInt64)(DateToTicks(y, m, d) + InternalTicks % TicksPerDay) | InternalKind);
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // seconds to this DateTime. The result is computed by rounding the
+ // fractional number of seconds given by value to the nearest
+ // millisecond, and adding that interval to this DateTime. The
+ // value argument is permitted to be negative.
+ //
+ public DateTime AddSeconds(double value) {
+ return Add(value, MillisPerSecond);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // 100-nanosecond ticks to this DateTime. The value argument
+ // is permitted to be negative.
+ //
+ public DateTime AddTicks(long value) {
+ long ticks = InternalTicks;
+ if (value > MaxTicks - ticks || value < MinTicks - ticks) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));
+ }
+ return new DateTime((UInt64)(ticks + value) | InternalKind);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to this DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of this DateTime by value
+ // years. If the month and day of this DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of this DateTime.
+ //
+ public DateTime AddYears(int value) {
+ if (value < -10000 || value > 10000) throw new ArgumentOutOfRangeException("years", Environment.GetResourceString("ArgumentOutOfRange_DateTimeBadYears"));
+ Contract.EndContractBlock();
+ return AddMonths(value * 12);
+ }
+
+ // Compares two DateTime values, returning an integer that indicates
+ // their relationship.
+ //
+ public static int Compare(DateTime t1, DateTime t2) {
+ Int64 ticks1 = t1.InternalTicks;
+ Int64 ticks2 = t2.InternalTicks;
+ if (ticks1 > ticks2) return 1;
+ if (ticks1 < ticks2) return -1;
+ return 0;
+ }
+
+ // Compares this DateTime to a given object. This method provides an
+ // implementation of the IComparable interface. The object
+ // argument must be another DateTime, or otherwise an exception
+ // occurs. Null is considered less than any instance.
+ //
+ // Returns a value less than zero if this object
+ public int CompareTo(Object value) {
+ if (value == null) return 1;
+ if (!(value is DateTime)) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDateTime"));
+ }
+
+ return Compare(this, (DateTime)value);
+ }
+
+ public int CompareTo(DateTime value) {
+ return Compare(this, value);
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ // Will check the if the parameters are valid.
+ private static long DateToTicks(int year, int month, int day) {
+ if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) {
+ int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365;
+ if (day >= 1 && day <= days[month] - days[month - 1]) {
+ int y = year - 1;
+ int n = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
+ return n * TicksPerDay;
+ }
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+
+ // Return the tick count corresponding to the given hour, minute, second.
+ // Will check the if the parameters are valid.
+ private static long TimeToTicks(int hour, int minute, int second)
+ {
+ //TimeSpan.TimeToTicks is a family access function which does no error checking, so
+ //we need to put some error checking out here.
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
+ {
+ return (TimeSpan.TimeToTicks(hour, minute, second));
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+ public static int DaysInMonth(int year, int month) {
+ if (month < 1 || month > 12) throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ Contract.EndContractBlock();
+ // IsLeapYear checks the year argument
+ int[] days = IsLeapYear(year)? DaysToMonth366: DaysToMonth365;
+ return days[month] - days[month - 1];
+ }
+
+ // Converts an OLE Date to a tick count.
+ // This function is duplicated in COMDateTime.cpp
+ internal static long DoubleDateToTicks(double value) {
+ // The check done this way will take care of NaN
+ if (!(value < OADateMaxAsDouble) || !(value > OADateMinAsDouble))
+ throw new ArgumentException(Environment.GetResourceString("Arg_OleAutDateInvalid"));
+
+ // Conversion to long will not cause an overflow here, as at this point the "value" is in between OADateMinAsDouble and OADateMaxAsDouble
+ long millis = (long)(value * MillisPerDay + (value >= 0? 0.5: -0.5));
+ // The interesting thing here is when you have a value like 12.5 it all positive 12 days and 12 hours from 01/01/1899
+ // However if you a value of -12.25 it is minus 12 days but still positive 6 hours, almost as though you meant -11.75 all negative
+ // This line below fixes up the millis in the negative case
+ if (millis < 0) {
+ millis -= (millis % MillisPerDay) * 2;
+ }
+
+ millis += DoubleDateOffset / TicksPerMillisecond;
+
+ if (millis < 0 || millis >= MaxMillis) throw new ArgumentException(Environment.GetResourceString("Arg_OleAutDateScale"));
+ return millis * TicksPerMillisecond;
+ }
+
+#if !FEATURE_CORECLR
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool LegacyParseMode();
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool EnableAmPmParseAdjustment();
+#endif
+
+ // Checks if this DateTime is equal to a given object. Returns
+ // true if the given object is a boxed DateTime and its value
+ // is equal to the value of this DateTime. Returns false
+ // otherwise.
+ //
+ public override bool Equals(Object value) {
+ if (value is DateTime) {
+ return InternalTicks == ((DateTime)value).InternalTicks;
+ }
+ return false;
+ }
+
+ public bool Equals(DateTime value) {
+ return InternalTicks == value.InternalTicks;
+ }
+
+ // Compares two DateTime values for equality. Returns true if
+ // the two DateTime values are equal, or false if they are
+ // not equal.
+ //
+ public static bool Equals(DateTime t1, DateTime t2) {
+ return t1.InternalTicks == t2.InternalTicks;
+ }
+
+ public static DateTime FromBinary(Int64 dateData) {
+ if ((dateData & (unchecked( (Int64) LocalMask))) != 0) {
+ // Local times need to be adjusted as you move from one time zone to another,
+ // just as they are when serializing in text. As such the format for local times
+ // changes to store the ticks of the UTC time, but with flags that look like a
+ // local date.
+ Int64 ticks = dateData & (unchecked((Int64)TicksMask));
+ // Negative ticks are stored in the top part of the range and should be converted back into a negative number
+ if (ticks > TicksCeiling - TicksPerDay) {
+ ticks = ticks - TicksCeiling;
+ }
+ // Convert the ticks back to local. If the UTC ticks are out of range, we need to default to
+ // the UTC offset from MinValue and MaxValue to be consistent with Parse.
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offsetTicks;
+ if (ticks < MinTicks) {
+ offsetTicks = TimeZoneInfo.GetLocalUtcOffset(DateTime.MinValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
+ }
+ else if (ticks > MaxTicks) {
+ offsetTicks = TimeZoneInfo.GetLocalUtcOffset(DateTime.MaxValue, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
+ }
+ else {
+ // Because the ticks conversion between UTC and local is lossy, we need to capture whether the
+ // time is in a repeated hour so that it can be passed to the DateTime constructor.
+ DateTime utcDt = new DateTime(ticks, DateTimeKind.Utc);
+ Boolean isDaylightSavings = false;
+ offsetTicks = TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
+ }
+ ticks += offsetTicks;
+ // Another behaviour of parsing is to cause small times to wrap around, so that they can be used
+ // to compare times of day
+ if (ticks < 0) {
+ ticks += TicksPerDay;
+ }
+ if (ticks < MinTicks || ticks > MaxTicks) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), "dateData");
+ }
+ return new DateTime(ticks, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+ else {
+ return DateTime.FromBinaryRaw(dateData);
+ }
+ }
+
+ // A version of ToBinary that uses the real representation and does not adjust local times. This is needed for
+ // scenarios where the serialized data must maintain compatibility
+ internal static DateTime FromBinaryRaw(Int64 dateData) {
+ Int64 ticks = dateData & (Int64)TicksMask;
+ if (ticks < MinTicks || ticks > MaxTicks)
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeBadBinaryData"), "dateData");
+ return new DateTime((UInt64)dateData);
+ }
+
+ // Creates a DateTime from a Windows filetime. A Windows filetime is
+ // a long representing the date and time as the number of
+ // 100-nanosecond intervals that have elapsed since 1/1/1601 12:00am.
+ //
+ public static DateTime FromFileTime(long fileTime) {
+ return FromFileTimeUtc(fileTime).ToLocalTime();
+ }
+
+ public static DateTime FromFileTimeUtc(long fileTime) {
+ if (fileTime < 0 || fileTime > MaxTicks - FileTimeOffset) {
+ throw new ArgumentOutOfRangeException("fileTime", Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid"));
+ }
+ Contract.EndContractBlock();
+
+ // This is the ticks in Universal time for this fileTime.
+ long universalTicks = fileTime + FileTimeOffset;
+ return new DateTime(universalTicks, DateTimeKind.Utc);
+ }
+
+ // Creates a DateTime from an OLE Automation Date.
+ //
+ public static DateTime FromOADate(double d) {
+ return new DateTime(DoubleDateToTicks(d), DateTimeKind.Unspecified);
+ }
+
+ [System.Security.SecurityCritical /*auto-generated_required*/]
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ // Serialize both the old and the new format
+ info.AddValue(TicksField, InternalTicks);
+ info.AddValue(DateDataField, dateData);
+ }
+
+ public Boolean IsDaylightSavingTime() {
+ if (Kind == DateTimeKind.Utc) {
+ return false;
+ }
+ return TimeZoneInfo.Local.IsDaylightSavingTime(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+
+ public static DateTime SpecifyKind(DateTime value, DateTimeKind kind) {
+ return new DateTime(value.InternalTicks, kind);
+ }
+
+ public Int64 ToBinary() {
+ if (Kind == DateTimeKind.Local) {
+ // Local times need to be adjusted as you move from one time zone to another,
+ // just as they are when serializing in text. As such the format for local times
+ // changes to store the ticks of the UTC time, but with flags that look like a
+ // local date.
+
+ // To match serialization in text we need to be able to handle cases where
+ // the UTC value would be out of range. Unused parts of the ticks range are
+ // used for this, so that values just past max value are stored just past the
+ // end of the maximum range, and values just below minimum value are stored
+ // at the end of the ticks area, just below 2^62.
+ TimeSpan offset = TimeZoneInfo.GetLocalUtcOffset(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ Int64 ticks = Ticks;
+ Int64 storedTicks = ticks - offset.Ticks;
+ if (storedTicks < 0) {
+ storedTicks = TicksCeiling + storedTicks;
+ }
+ return storedTicks | (unchecked((Int64) LocalMask));
+ }
+ else {
+ return (Int64)dateData;
+ }
+ }
+
+ // Return the underlying data, without adjust local times to the right time zone. Needed if performance
+ // or compatibility are important.
+ internal Int64 ToBinaryRaw() {
+ return (Int64)dateData;
+ }
+
+ // Returns the date part of this DateTime. The resulting value
+ // corresponds to this DateTime with the time-of-day part set to
+ // zero (midnight).
+ //
+ public DateTime Date {
+ get {
+ Int64 ticks = InternalTicks;
+ return new DateTime((UInt64)(ticks - ticks % TicksPerDay) | InternalKind);
+ }
+ }
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ private int GetDatePart(int part) {
+ Int64 ticks = InternalTicks;
+ // n = number of days since 1/1/0001
+ int n = (int)(ticks / TicksPerDay);
+ // y400 = number of whole 400-year periods since 1/1/0001
+ int y400 = n / DaysPer400Years;
+ // n = day number within 400-year period
+ n -= y400 * DaysPer400Years;
+ // y100 = number of whole 100-year periods within 400-year period
+ int y100 = n / DaysPer100Years;
+ // Last 100-year period has an extra day, so decrement result if 4
+ if (y100 == 4) y100 = 3;
+ // n = day number within 100-year period
+ n -= y100 * DaysPer100Years;
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / DaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * DaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / DaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear) {
+ return y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1;
+ }
+ // n = day number within year
+ n -= y1 * DaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear) return n + 1;
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = y1 == 3 && (y4 != 24 || y100 == 3);
+ int[] days = leapYear? DaysToMonth366: DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return m;
+ // Return 1-based day-of-month
+ return n - days[m - 1] + 1;
+ }
+
+ // Returns the day-of-month part of this DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+ public int Day {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ Contract.Ensures(Contract.Result<int>() <= 31);
+ return GetDatePart(DatePartDay);
+ }
+ }
+
+ // Returns the day-of-week part of this DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+ public DayOfWeek DayOfWeek {
+ get {
+ Contract.Ensures(Contract.Result<DayOfWeek>() >= DayOfWeek.Sunday);
+ Contract.Ensures(Contract.Result<DayOfWeek>() <= DayOfWeek.Saturday);
+ return (DayOfWeek)((InternalTicks / TicksPerDay + 1) % 7);
+ }
+ }
+
+ // Returns the day-of-year part of this DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+ public int DayOfYear {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ Contract.Ensures(Contract.Result<int>() <= 366); // leap year
+ return GetDatePart(DatePartDayOfYear);
+ }
+ }
+
+ // Returns the hash code for this DateTime.
+ //
+ public override int GetHashCode() {
+ Int64 ticks = InternalTicks;
+ return unchecked((int)ticks) ^ (int)(ticks >> 32);
+ }
+
+ // Returns the hour part of this DateTime. The returned value is an
+ // integer between 0 and 23.
+ //
+ public int Hour {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 24);
+ return (int)((InternalTicks / TicksPerHour) % 24);
+ }
+ }
+
+ internal Boolean IsAmbiguousDaylightSavingTime() {
+ return (InternalKind == KindLocalAmbiguousDst);
+ }
+
+ [Pure]
+ public DateTimeKind Kind {
+ get {
+ switch (InternalKind) {
+ case KindUnspecified:
+ return DateTimeKind.Unspecified;
+ case KindUtc:
+ return DateTimeKind.Utc;
+ default:
+ return DateTimeKind.Local;
+ }
+ }
+ }
+
+ // Returns the millisecond part of this DateTime. The returned value
+ // is an integer between 0 and 999.
+ //
+ public int Millisecond {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 1000);
+ return (int)((InternalTicks/ TicksPerMillisecond) % 1000);
+ }
+ }
+
+ // Returns the minute part of this DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+ public int Minute {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 60);
+ return (int)((InternalTicks / TicksPerMinute) % 60);
+ }
+ }
+
+ // Returns the month part of this DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+ public int Month {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ return GetDatePart(DatePartMonth);
+ }
+ }
+
+ // Returns a DateTime representing the current date and time. The
+ // resolution of the returned value depends on the system timer. For
+ // Windows NT 3.5 and later the timer resolution is approximately 10ms,
+ // for Windows NT 3.1 it is approximately 16ms, and for Windows 95 and 98
+ // it is approximately 55ms.
+ //
+ public static DateTime Now {
+ get {
+ Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Local);
+
+ DateTime utc = UtcNow;
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offset = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utc, out isAmbiguousLocalDst).Ticks;
+ long tick = utc.Ticks + offset;
+ if (tick>DateTime.MaxTicks) {
+ return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
+ }
+ if (tick<DateTime.MinTicks) {
+ return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
+ }
+ return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+ }
+
+ public static DateTime UtcNow {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Utc);
+ // following code is tuned for speed. Don't change it without running benchmark.
+ long ticks = 0;
+ ticks = GetSystemTimeAsFileTime();
+
+ return new DateTime( ((UInt64)(ticks + FileTimeOffset)) | KindUtc);
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern long GetSystemTimeAsFileTime();
+
+
+
+ // Returns the second part of this DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+ public int Second {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 60);
+ return (int)((InternalTicks / TicksPerSecond) % 60);
+ }
+ }
+
+ // Returns the tick count for this DateTime. The returned value is
+ // the number of 100-nanosecond intervals that have elapsed since 1/1/0001
+ // 12:00am.
+ //
+ public long Ticks {
+ get {
+ return InternalTicks;
+ }
+ }
+
+ // Returns the time-of-day part of this DateTime. The returned value
+ // is a TimeSpan that indicates the time elapsed since midnight.
+ //
+ public TimeSpan TimeOfDay {
+ get {
+ return new TimeSpan(InternalTicks % TicksPerDay);
+ }
+ }
+
+ // Returns a DateTime representing the current date. The date part
+ // of the returned value is the current date, and the time-of-day part of
+ // the returned value is zero (midnight).
+ //
+ public static DateTime Today {
+ get {
+ return DateTime.Now.Date;
+ }
+ }
+
+ // Returns the year part of this DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int Year {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1 && Contract.Result<int>() <= 9999);
+ return GetDatePart(DatePartYear);
+ }
+ }
+
+ // Checks whether a given year is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+ public static bool IsLeapYear(int year) {
+ if (year < 1 || year > 9999) {
+ throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Year"));
+ }
+ Contract.EndContractBlock();
+ return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
+ }
+
+ // Constructs a DateTime from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTime Parse(String s) {
+ return (DateTimeParse.Parse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None));
+ }
+
+ // Constructs a DateTime from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTime Parse(String s, IFormatProvider provider) {
+ return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), DateTimeStyles.None));
+ }
+
+ public static DateTime Parse(String s, IFormatProvider provider, DateTimeStyles styles) {
+ DateTimeFormatInfo.ValidateStyles(styles, "styles");
+ return (DateTimeParse.Parse(s, DateTimeFormatInfo.GetInstance(provider), styles));
+ }
+
+ // Constructs a DateTime from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTime ParseExact(String s, String format, IFormatProvider provider) {
+ return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), DateTimeStyles.None));
+ }
+
+ // Constructs a DateTime from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTime ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style) {
+ DateTimeFormatInfo.ValidateStyles(style, "style");
+ return (DateTimeParse.ParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style));
+ }
+
+ public static DateTime ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style) {
+ DateTimeFormatInfo.ValidateStyles(style, "style");
+ return DateTimeParse.ParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style);
+ }
+
+ public TimeSpan Subtract(DateTime value) {
+ return new TimeSpan(InternalTicks - value.InternalTicks);
+ }
+
+ public DateTime Subtract(TimeSpan value) {
+ long ticks = InternalTicks;
+ long valueTicks = value._ticks;
+ if (ticks - MinTicks < valueTicks || ticks - MaxTicks > valueTicks) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));
+ }
+ return new DateTime((UInt64)(ticks - valueTicks) | InternalKind);
+ }
+
+ // This function is duplicated in COMDateTime.cpp
+ private static double TicksToOADate(long value) {
+ if (value == 0)
+ return 0.0; // Returns OleAut's zero'ed date value.
+ if (value < TicksPerDay) // This is a fix for VB. They want the default day to be 1/1/0001 rathar then 12/30/1899.
+ value += DoubleDateOffset; // We could have moved this fix down but we would like to keep the bounds check.
+ if (value < OADateMinAsTicks)
+ throw new OverflowException(Environment.GetResourceString("Arg_OleAutDateInvalid"));
+ // Currently, our max date == OA's max date (12/31/9999), so we don't
+ // need an overflow check in that direction.
+ long millis = (value - DoubleDateOffset) / TicksPerMillisecond;
+ if (millis < 0) {
+ long frac = millis % MillisPerDay;
+ if (frac != 0) millis -= (MillisPerDay + frac) * 2;
+ }
+ return (double)millis / MillisPerDay;
+ }
+
+ // Converts the DateTime instance into an OLE Automation compatible
+ // double date.
+ public double ToOADate() {
+ return TicksToOADate(InternalTicks);
+ }
+
+ public long ToFileTime() {
+ // Treats the input as local if it is not specified
+ return ToUniversalTime().ToFileTimeUtc();
+ }
+
+ public long ToFileTimeUtc() {
+ // Treats the input as universal if it is not specified
+ long ticks = ((InternalKind & LocalMask) != 0) ? ToUniversalTime().InternalTicks : this.InternalTicks;
+ ticks -= FileTimeOffset;
+ if (ticks < 0) {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_FileTimeInvalid"));
+ }
+ return ticks;
+ }
+
+ public DateTime ToLocalTime()
+ {
+ return ToLocalTime(false);
+ }
+
+ internal DateTime ToLocalTime(bool throwOnOverflow)
+ {
+ if (Kind == DateTimeKind.Local) {
+ return this;
+ }
+ Boolean isDaylightSavings = false;
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offset = TimeZoneInfo.GetUtcOffsetFromUtc(this, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
+ long tick = Ticks + offset;
+ if (tick > DateTime.MaxTicks)
+ {
+ if (throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArgumentOutOfRangeException"));
+ else
+ return new DateTime(DateTime.MaxTicks, DateTimeKind.Local);
+ }
+ if (tick < DateTime.MinTicks)
+ {
+ if (throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArgumentOutOfRangeException"));
+ else
+ return new DateTime(DateTime.MinTicks, DateTimeKind.Local);
+ }
+ return new DateTime(tick, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+
+ public String ToLongDateString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, "D", DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public String ToLongTimeString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, "T", DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public String ToShortDateString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, "d", DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public String ToShortTimeString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, "t", DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, null, DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, format, DateTimeFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, null, DateTimeFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(this, format, DateTimeFormatInfo.GetInstance(provider));
+ }
+
+ public DateTime ToUniversalTime() {
+ return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+
+ public static Boolean TryParse(String s, out DateTime result) {
+ return DateTimeParse.TryParse(s, DateTimeFormatInfo.CurrentInfo, DateTimeStyles.None, out result);
+ }
+
+ public static Boolean TryParse(String s, IFormatProvider provider, DateTimeStyles styles, out DateTime result) {
+ DateTimeFormatInfo.ValidateStyles(styles, "styles");
+ return DateTimeParse.TryParse(s, DateTimeFormatInfo.GetInstance(provider), styles, out result);
+ }
+
+ public static Boolean TryParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
+ DateTimeFormatInfo.ValidateStyles(style, "style");
+ return DateTimeParse.TryParseExact(s, format, DateTimeFormatInfo.GetInstance(provider), style, out result);
+ }
+
+ public static Boolean TryParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result) {
+ DateTimeFormatInfo.ValidateStyles(style, "style");
+ return DateTimeParse.TryParseExactMultiple(s, formats, DateTimeFormatInfo.GetInstance(provider), style, out result);
+ }
+
+ public static DateTime operator +(DateTime d, TimeSpan t) {
+ long ticks = d.InternalTicks;
+ long valueTicks = t._ticks;
+ if (valueTicks > MaxTicks - ticks || valueTicks < MinTicks - ticks) {
+ throw new ArgumentOutOfRangeException("t", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));
+ }
+ return new DateTime((UInt64)(ticks + valueTicks) | d.InternalKind);
+ }
+
+ public static DateTime operator -(DateTime d, TimeSpan t) {
+ long ticks = d.InternalTicks;
+ long valueTicks = t._ticks;
+ if (ticks - MinTicks < valueTicks || ticks - MaxTicks > valueTicks) {
+ throw new ArgumentOutOfRangeException("t", Environment.GetResourceString("ArgumentOutOfRange_DateArithmetic"));
+ }
+ return new DateTime((UInt64)(ticks - valueTicks) | d.InternalKind);
+ }
+
+ public static TimeSpan operator -(DateTime d1, DateTime d2) {
+ return new TimeSpan(d1.InternalTicks - d2.InternalTicks);
+ }
+
+ public static bool operator ==(DateTime d1, DateTime d2) {
+ return d1.InternalTicks == d2.InternalTicks;
+ }
+
+ public static bool operator !=(DateTime d1, DateTime d2) {
+ return d1.InternalTicks != d2.InternalTicks;
+ }
+
+ public static bool operator <(DateTime t1, DateTime t2) {
+ return t1.InternalTicks < t2.InternalTicks;
+ }
+
+ public static bool operator <=(DateTime t1, DateTime t2) {
+ return t1.InternalTicks <= t2.InternalTicks;
+ }
+
+ public static bool operator >(DateTime t1, DateTime t2) {
+ return t1.InternalTicks > t2.InternalTicks;
+ }
+
+ public static bool operator >=(DateTime t1, DateTime t2) {
+ return t1.InternalTicks >= t2.InternalTicks;
+ }
+
+
+ // Returns a string array containing all of the known date and time options for the
+ // current culture. The strings returned are properly formatted date and
+ // time strings for the current instance of DateTime.
+ public String[] GetDateTimeFormats()
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return (GetDateTimeFormats(CultureInfo.CurrentCulture));
+ }
+
+ // Returns a string array containing all of the known date and time options for the
+ // using the information provided by IFormatProvider. The strings returned are properly formatted date and
+ // time strings for the current instance of DateTime.
+ public String[] GetDateTimeFormats(IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return (DateTimeFormat.GetAllDateTimes(this, DateTimeFormatInfo.GetInstance(provider)));
+ }
+
+
+ // Returns a string array containing all of the date and time options for the
+ // given format format and current culture. The strings returned are properly formatted date and
+ // time strings for the current instance of DateTime.
+ public String[] GetDateTimeFormats(char format)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return (GetDateTimeFormats(format, CultureInfo.CurrentCulture));
+ }
+
+ // Returns a string array containing all of the date and time options for the
+ // given format format and given culture. The strings returned are properly formatted date and
+ // time strings for the current instance of DateTime.
+ public String[] GetDateTimeFormats(char format, IFormatProvider provider)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return (DateTimeFormat.GetAllDateTimes(this, format, DateTimeFormatInfo.GetInstance(provider)));
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.DateTime;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Boolean"));
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Char"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "SByte"));
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Byte"));
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Int16"));
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "UInt16"));
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Int32"));
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "UInt32"));
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Int64"));
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "UInt64"));
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Single"));
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Double"));
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "DateTime", "Decimal"));
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ return this;
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+
+ // Tries to construct a DateTime from a given year, month, day, hour,
+ // minute, second and millisecond.
+ //
+ internal static Boolean TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result) {
+ result = DateTime.MinValue;
+ if (year < 1 || year > 9999 || month < 1 || month > 12) {
+ return false;
+ }
+ int[] days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
+ if (day < 1 || day > days[month] - days[month - 1]) {
+ return false;
+ }
+ if (hour < 0 || hour >= 24 || minute < 0 || minute >= 60 || second < 0 || second >= 60) {
+ return false;
+ }
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ return false;
+ }
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second);
+
+ ticks += millisecond * TicksPerMillisecond;
+ if (ticks < MinTicks || ticks > MaxTicks) {
+ return false;
+ }
+ result = new DateTime(ticks, DateTimeKind.Unspecified);
+ return true;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/DateTimeKind.cs b/src/mscorlib/src/System/DateTimeKind.cs
new file mode 100644
index 0000000000..1a8a4ff6b4
--- /dev/null
+++ b/src/mscorlib/src/System/DateTimeKind.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System {
+
+ // This enum is used to indentify DateTime instances in cases when they are known to be in local time,
+ // UTC time or if this information has not been specified or is not applicable.
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum DateTimeKind
+ {
+ Unspecified = 0,
+ Utc = 1,
+ Local = 2,
+ }
+}
diff --git a/src/mscorlib/src/System/DateTimeOffset.cs b/src/mscorlib/src/System/DateTimeOffset.cs
new file mode 100644
index 0000000000..3e63c76124
--- /dev/null
+++ b/src/mscorlib/src/System/DateTimeOffset.cs
@@ -0,0 +1,831 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Threading;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // DateTimeOffset is a value type that consists of a DateTime and a time zone offset,
+ // ie. how far away the time is from GMT. The DateTime is stored whole, and the offset
+ // is stored as an Int16 internally to save space, but presented as a TimeSpan.
+ //
+ // The range is constrained so that both the represented clock time and the represented
+ // UTC time fit within the boundaries of MaxValue. This gives it the same range as DateTime
+ // for actual UTC times, and a slightly constrained range on one end when an offset is
+ // present.
+ //
+ // This class should be substitutable for date time in most cases; so most operations
+ // effectively work on the clock time. However, the underlying UTC time is what counts
+ // for the purposes of identity, sorting and subtracting two instances.
+ //
+ //
+ // There are theoretically two date times stored, the UTC and the relative local representation
+ // or the 'clock' time. It actually does not matter which is stored in m_dateTime, so it is desirable
+ // for most methods to go through the helpers UtcDateTime and ClockDateTime both to abstract this
+ // out and for internal readability.
+
+ [StructLayout(LayoutKind.Auto)]
+ [Serializable]
+ public struct DateTimeOffset : IComparable, IFormattable,
+ IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>, ISerializable, IDeserializationCallback
+ {
+ // Constants
+ internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
+ internal const Int64 MinOffset = -MaxOffset;
+
+ private const long UnixEpochTicks = TimeSpan.TicksPerDay * DateTime.DaysTo1970; // 621,355,968,000,000,000
+ private const long UnixEpochSeconds = UnixEpochTicks / TimeSpan.TicksPerSecond; // 62,135,596,800
+ private const long UnixEpochMilliseconds = UnixEpochTicks / TimeSpan.TicksPerMillisecond; // 62,135,596,800,000
+
+ internal const long UnixMinSeconds = DateTime.MinTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
+ internal const long UnixMaxSeconds = DateTime.MaxTicks / TimeSpan.TicksPerSecond - UnixEpochSeconds;
+
+ // Static Fields
+ public static readonly DateTimeOffset MinValue = new DateTimeOffset(DateTime.MinTicks, TimeSpan.Zero);
+ public static readonly DateTimeOffset MaxValue = new DateTimeOffset(DateTime.MaxTicks, TimeSpan.Zero);
+
+ // Instance Fields
+ private DateTime m_dateTime;
+ private Int16 m_offsetMinutes;
+
+ // Constructors
+
+ // Constructs a DateTimeOffset from a tick count and offset
+ public DateTimeOffset(long ticks, TimeSpan offset) {
+ m_offsetMinutes = ValidateOffset(offset);
+ // Let the DateTime constructor do the range checks
+ DateTime dateTime = new DateTime(ticks);
+ m_dateTime = ValidateDate(dateTime, offset);
+ }
+
+ // Constructs a DateTimeOffset from a DateTime. For Local and Unspecified kinds,
+ // extracts the local offset. For UTC, creates a UTC instance with a zero offset.
+ public DateTimeOffset(DateTime dateTime) {
+ TimeSpan offset;
+ if (dateTime.Kind != DateTimeKind.Utc) {
+ // Local and Unspecified are both treated as Local
+ offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+ else {
+ offset = new TimeSpan(0);
+ }
+ m_offsetMinutes = ValidateOffset(offset);
+ m_dateTime = ValidateDate(dateTime, offset);
+ }
+
+ // Constructs a DateTimeOffset from a DateTime. And an offset. Always makes the clock time
+ // consistent with the DateTime. For Utc ensures the offset is zero. For local, ensures that
+ // the offset corresponds to the local.
+ public DateTimeOffset(DateTime dateTime, TimeSpan offset) {
+ if (dateTime.Kind == DateTimeKind.Local) {
+ if (offset != TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetLocalMismatch"), "offset");
+ }
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc) {
+ if (offset != TimeSpan.Zero) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetUtcMismatch"), "offset");
+ }
+ }
+ m_offsetMinutes = ValidateOffset(offset);
+ m_dateTime = ValidateDate(dateTime, offset);
+ }
+
+ // Constructs a DateTimeOffset from a given year, month, day, hour,
+ // minute, second and offset.
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, TimeSpan offset) {
+ m_offsetMinutes = ValidateOffset(offset);
+ m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second), offset);
+ }
+
+ // Constructs a DateTimeOffset from a given year, month, day, hour,
+ // minute, second, millsecond and offset
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, TimeSpan offset) {
+ m_offsetMinutes = ValidateOffset(offset);
+ m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second, millisecond), offset);
+ }
+
+
+ // Constructs a DateTimeOffset from a given year, month, day, hour,
+ // minute, second, millsecond, Calendar and offset.
+ public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, TimeSpan offset) {
+ m_offsetMinutes = ValidateOffset(offset);
+ m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second, millisecond, calendar), offset);
+ }
+
+ // Returns a DateTimeOffset representing the current date and time. The
+ // resolution of the returned value depends on the system timer. For
+ // Windows NT 3.5 and later the timer resolution is approximately 10ms,
+ // for Windows NT 3.1 it is approximately 16ms, and for Windows 95 and 98
+ // it is approximately 55ms.
+ //
+ public static DateTimeOffset Now {
+ get {
+ return new DateTimeOffset(DateTime.Now);
+ }
+ }
+
+ public static DateTimeOffset UtcNow {
+ get {
+ return new DateTimeOffset(DateTime.UtcNow);
+ }
+ }
+
+ public DateTime DateTime {
+ get {
+ return ClockDateTime;
+ }
+ }
+
+ public DateTime UtcDateTime {
+ [Pure]
+ get {
+ Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Utc);
+ return DateTime.SpecifyKind(m_dateTime, DateTimeKind.Utc);
+ }
+ }
+
+ public DateTime LocalDateTime {
+ [Pure]
+ get {
+ Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Local);
+ return UtcDateTime.ToLocalTime();
+ }
+ }
+
+ // Adjust to a given offset with the same UTC time. Can throw ArgumentException
+ //
+ public DateTimeOffset ToOffset(TimeSpan offset) {
+ return new DateTimeOffset((m_dateTime + offset).Ticks, offset);
+ }
+
+
+ // Instance Properties
+
+ // The clock or visible time represented. This is just a wrapper around the internal date because this is
+ // the chosen storage mechanism. Going through this helper is good for readability and maintainability.
+ // This should be used for display but not identity.
+ private DateTime ClockDateTime {
+ get {
+ return new DateTime((m_dateTime + Offset).Ticks, DateTimeKind.Unspecified);
+ }
+ }
+
+ // Returns the date part of this DateTimeOffset. The resulting value
+ // corresponds to this DateTimeOffset with the time-of-day part set to
+ // zero (midnight).
+ //
+ public DateTime Date {
+ get {
+ return ClockDateTime.Date;
+ }
+ }
+
+ // Returns the day-of-month part of this DateTimeOffset. The returned
+ // value is an integer between 1 and 31.
+ //
+ public int Day {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ Contract.Ensures(Contract.Result<int>() <= 31);
+ return ClockDateTime.Day;
+ }
+ }
+
+ // Returns the day-of-week part of this DateTimeOffset. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+ public DayOfWeek DayOfWeek {
+ get {
+ Contract.Ensures(Contract.Result<DayOfWeek>() >= DayOfWeek.Sunday);
+ Contract.Ensures(Contract.Result<DayOfWeek>() <= DayOfWeek.Saturday);
+ return ClockDateTime.DayOfWeek;
+ }
+ }
+
+ // Returns the day-of-year part of this DateTimeOffset. The returned value
+ // is an integer between 1 and 366.
+ //
+ public int DayOfYear {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ Contract.Ensures(Contract.Result<int>() <= 366); // leap year
+ return ClockDateTime.DayOfYear;
+ }
+ }
+
+ // Returns the hour part of this DateTimeOffset. The returned value is an
+ // integer between 0 and 23.
+ //
+ public int Hour {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 24);
+ return ClockDateTime.Hour;
+ }
+ }
+
+
+ // Returns the millisecond part of this DateTimeOffset. The returned value
+ // is an integer between 0 and 999.
+ //
+ public int Millisecond {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 1000);
+ return ClockDateTime.Millisecond;
+ }
+ }
+
+ // Returns the minute part of this DateTimeOffset. The returned value is
+ // an integer between 0 and 59.
+ //
+ public int Minute {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 60);
+ return ClockDateTime.Minute;
+ }
+ }
+
+ // Returns the month part of this DateTimeOffset. The returned value is an
+ // integer between 1 and 12.
+ //
+ public int Month {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1);
+ return ClockDateTime.Month;
+ }
+ }
+
+ public TimeSpan Offset {
+ get {
+ return new TimeSpan(0, m_offsetMinutes, 0);
+ }
+ }
+
+ // Returns the second part of this DateTimeOffset. The returned value is
+ // an integer between 0 and 59.
+ //
+ public int Second {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() < 60);
+ return ClockDateTime.Second;
+ }
+ }
+
+ // Returns the tick count for this DateTimeOffset. The returned value is
+ // the number of 100-nanosecond intervals that have elapsed since 1/1/0001
+ // 12:00am.
+ //
+ public long Ticks {
+ get {
+ return ClockDateTime.Ticks;
+ }
+ }
+
+ public long UtcTicks {
+ get {
+ return UtcDateTime.Ticks;
+ }
+ }
+
+ // Returns the time-of-day part of this DateTimeOffset. The returned value
+ // is a TimeSpan that indicates the time elapsed since midnight.
+ //
+ public TimeSpan TimeOfDay {
+ get {
+ return ClockDateTime.TimeOfDay;
+ }
+ }
+
+ // Returns the year part of this DateTimeOffset. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int Year {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 1 && Contract.Result<int>() <= 9999);
+ return ClockDateTime.Year;
+ }
+ }
+
+ // Returns the DateTimeOffset resulting from adding the given
+ // TimeSpan to this DateTimeOffset.
+ //
+ public DateTimeOffset Add(TimeSpan timeSpan) {
+ return new DateTimeOffset(ClockDateTime.Add(timeSpan), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding a fractional number of
+ // days to this DateTimeOffset. The result is computed by rounding the
+ // fractional number of days given by value to the nearest
+ // millisecond, and adding that interval to this DateTimeOffset. The
+ // value argument is permitted to be negative.
+ //
+ public DateTimeOffset AddDays(double days) {
+ return new DateTimeOffset(ClockDateTime.AddDays(days), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding a fractional number of
+ // hours to this DateTimeOffset. The result is computed by rounding the
+ // fractional number of hours given by value to the nearest
+ // millisecond, and adding that interval to this DateTimeOffset. The
+ // value argument is permitted to be negative.
+ //
+ public DateTimeOffset AddHours(double hours) {
+ return new DateTimeOffset(ClockDateTime.AddHours(hours), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from the given number of
+ // milliseconds to this DateTimeOffset. The result is computed by rounding
+ // the number of milliseconds given by value to the nearest integer,
+ // and adding that interval to this DateTimeOffset. The value
+ // argument is permitted to be negative.
+ //
+ public DateTimeOffset AddMilliseconds(double milliseconds) {
+ return new DateTimeOffset(ClockDateTime.AddMilliseconds(milliseconds), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding a fractional number of
+ // minutes to this DateTimeOffset. The result is computed by rounding the
+ // fractional number of minutes given by value to the nearest
+ // millisecond, and adding that interval to this DateTimeOffset. The
+ // value argument is permitted to be negative.
+ //
+ public DateTimeOffset AddMinutes(double minutes) {
+ return new DateTimeOffset(ClockDateTime.AddMinutes(minutes), Offset);
+ }
+
+ public DateTimeOffset AddMonths(int months) {
+ return new DateTimeOffset(ClockDateTime.AddMonths(months), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding a fractional number of
+ // seconds to this DateTimeOffset. The result is computed by rounding the
+ // fractional number of seconds given by value to the nearest
+ // millisecond, and adding that interval to this DateTimeOffset. The
+ // value argument is permitted to be negative.
+ //
+ public DateTimeOffset AddSeconds(double seconds) {
+ return new DateTimeOffset(ClockDateTime.AddSeconds(seconds), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding the given number of
+ // 100-nanosecond ticks to this DateTimeOffset. The value argument
+ // is permitted to be negative.
+ //
+ public DateTimeOffset AddTicks(long ticks) {
+ return new DateTimeOffset(ClockDateTime.AddTicks(ticks), Offset);
+ }
+
+ // Returns the DateTimeOffset resulting from adding the given number of
+ // years to this DateTimeOffset. The result is computed by incrementing
+ // (or decrementing) the year part of this DateTimeOffset by value
+ // years. If the month and day of this DateTimeOffset is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTimeOffset becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of this DateTimeOffset.
+ //
+ public DateTimeOffset AddYears(int years) {
+ return new DateTimeOffset(ClockDateTime.AddYears(years), Offset);
+ }
+
+ // Compares two DateTimeOffset values, returning an integer that indicates
+ // their relationship.
+ //
+ public static int Compare(DateTimeOffset first, DateTimeOffset second) {
+ return DateTime.Compare(first.UtcDateTime, second.UtcDateTime);
+ }
+
+ // Compares this DateTimeOffset to a given object. This method provides an
+ // implementation of the IComparable interface. The object
+ // argument must be another DateTimeOffset, or otherwise an exception
+ // occurs. Null is considered less than any instance.
+ //
+ int IComparable.CompareTo(Object obj) {
+ if (obj == null) return 1;
+ if (!(obj is DateTimeOffset)) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDateTimeOffset"));
+ }
+
+ DateTime objUtc = ((DateTimeOffset)obj).UtcDateTime;
+ DateTime utc = UtcDateTime;
+ if (utc > objUtc) return 1;
+ if (utc < objUtc) return -1;
+ return 0;
+ }
+
+ public int CompareTo(DateTimeOffset other) {
+ DateTime otherUtc = other.UtcDateTime;
+ DateTime utc = UtcDateTime;
+ if (utc > otherUtc) return 1;
+ if (utc < otherUtc) return -1;
+ return 0;
+ }
+
+
+ // Checks if this DateTimeOffset is equal to a given object. Returns
+ // true if the given object is a boxed DateTimeOffset and its value
+ // is equal to the value of this DateTimeOffset. Returns false
+ // otherwise.
+ //
+ public override bool Equals(Object obj) {
+ if (obj is DateTimeOffset) {
+ return UtcDateTime.Equals(((DateTimeOffset)obj).UtcDateTime);
+ }
+ return false;
+ }
+
+ public bool Equals(DateTimeOffset other) {
+ return UtcDateTime.Equals(other.UtcDateTime);
+ }
+
+ public bool EqualsExact(DateTimeOffset other) {
+ //
+ // returns true when the ClockDateTime, Kind, and Offset match
+ //
+ // currently the Kind should always be Unspecified, but there is always the possibility that a future version
+ // of DateTimeOffset overloads the Kind field
+ //
+ return (ClockDateTime == other.ClockDateTime && Offset == other.Offset && ClockDateTime.Kind == other.ClockDateTime.Kind);
+ }
+
+ // Compares two DateTimeOffset values for equality. Returns true if
+ // the two DateTimeOffset values are equal, or false if they are
+ // not equal.
+ //
+ public static bool Equals(DateTimeOffset first, DateTimeOffset second) {
+ return DateTime.Equals(first.UtcDateTime, second.UtcDateTime);
+ }
+
+ // Creates a DateTimeOffset from a Windows filetime. A Windows filetime is
+ // a long representing the date and time as the number of
+ // 100-nanosecond intervals that have elapsed since 1/1/1601 12:00am.
+ //
+ public static DateTimeOffset FromFileTime(long fileTime) {
+ return new DateTimeOffset(DateTime.FromFileTime(fileTime));
+ }
+
+ public static DateTimeOffset FromUnixTimeSeconds(long seconds) {
+ if (seconds < UnixMinSeconds || seconds > UnixMaxSeconds) {
+ throw new ArgumentOutOfRangeException("seconds",
+ string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), UnixMinSeconds, UnixMaxSeconds));
+ }
+
+ long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks;
+ return new DateTimeOffset(ticks, TimeSpan.Zero);
+ }
+
+ public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds) {
+ const long MinMilliseconds = DateTime.MinTicks / TimeSpan.TicksPerMillisecond - UnixEpochMilliseconds;
+ const long MaxMilliseconds = DateTime.MaxTicks / TimeSpan.TicksPerMillisecond - UnixEpochMilliseconds;
+
+ if (milliseconds < MinMilliseconds || milliseconds > MaxMilliseconds) {
+ throw new ArgumentOutOfRangeException("milliseconds",
+ string.Format(Environment.GetResourceString("ArgumentOutOfRange_Range"), MinMilliseconds, MaxMilliseconds));
+ }
+
+ long ticks = milliseconds * TimeSpan.TicksPerMillisecond + UnixEpochTicks;
+ return new DateTimeOffset(ticks, TimeSpan.Zero);
+ }
+
+ // ----- SECTION: private serialization instance methods ----------------*
+
+ void IDeserializationCallback.OnDeserialization(Object sender) {
+ try {
+ m_offsetMinutes = ValidateOffset(Offset);
+ m_dateTime = ValidateDate(ClockDateTime, Offset);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+
+ Contract.EndContractBlock();
+
+ info.AddValue("DateTime", m_dateTime);
+ info.AddValue("OffsetMinutes", m_offsetMinutes);
+ }
+
+
+ DateTimeOffset(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+
+ m_dateTime = (DateTime)info.GetValue("DateTime", typeof(DateTime));
+ m_offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16));
+ }
+
+ // Returns the hash code for this DateTimeOffset.
+ //
+ public override int GetHashCode() {
+ return UtcDateTime.GetHashCode();
+ }
+
+ // Constructs a DateTimeOffset from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTimeOffset Parse(String input) {
+ TimeSpan offset;
+ DateTime dateResult = DateTimeParse.Parse(input,
+ DateTimeFormatInfo.CurrentInfo,
+ DateTimeStyles.None,
+ out offset);
+ return new DateTimeOffset(dateResult.Ticks, offset);
+ }
+
+ // Constructs a DateTimeOffset from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTimeOffset Parse(String input, IFormatProvider formatProvider) {
+ return Parse(input, formatProvider, DateTimeStyles.None);
+ }
+
+ public static DateTimeOffset Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult = DateTimeParse.Parse(input,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out offset);
+ return new DateTimeOffset(dateResult.Ticks, offset);
+ }
+
+ // Constructs a DateTimeOffset from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider) {
+ return ParseExact(input, format, formatProvider, DateTimeStyles.None);
+ }
+
+ // Constructs a DateTimeOffset from a string. The string must specify a
+ // date and optionally a time in a culture-specific or universal format.
+ // Leading and trailing whitespace characters are allowed.
+ //
+ public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult = DateTimeParse.ParseExact(input,
+ format,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out offset);
+ return new DateTimeOffset(dateResult.Ticks, offset);
+ }
+
+ public static DateTimeOffset ParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult = DateTimeParse.ParseExactMultiple(input,
+ formats,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out offset);
+ return new DateTimeOffset(dateResult.Ticks, offset);
+ }
+
+ public TimeSpan Subtract(DateTimeOffset value) {
+ return UtcDateTime.Subtract(value.UtcDateTime);
+ }
+
+ public DateTimeOffset Subtract(TimeSpan value) {
+ return new DateTimeOffset(ClockDateTime.Subtract(value), Offset);
+ }
+
+
+ public long ToFileTime() {
+ return UtcDateTime.ToFileTime();
+ }
+
+ public long ToUnixTimeSeconds() {
+ // Truncate sub-second precision before offsetting by the Unix Epoch to avoid
+ // the last digit being off by one for dates that result in negative Unix times.
+ //
+ // For example, consider the DateTimeOffset 12/31/1969 12:59:59.001 +0
+ // ticks = 621355967990010000
+ // ticksFromEpoch = ticks - UnixEpochTicks = -9990000
+ // secondsFromEpoch = ticksFromEpoch / TimeSpan.TicksPerSecond = 0
+ //
+ // Notice that secondsFromEpoch is rounded *up* by the truncation induced by integer division,
+ // whereas we actually always want to round *down* when converting to Unix time. This happens
+ // automatically for positive Unix time values. Now the example becomes:
+ // seconds = ticks / TimeSpan.TicksPerSecond = 62135596799
+ // secondsFromEpoch = seconds - UnixEpochSeconds = -1
+ //
+ // In other words, we want to consistently round toward the time 1/1/0001 00:00:00,
+ // rather than toward the Unix Epoch (1/1/1970 00:00:00).
+ long seconds = UtcDateTime.Ticks / TimeSpan.TicksPerSecond;
+ return seconds - UnixEpochSeconds;
+ }
+
+ public long ToUnixTimeMilliseconds() {
+ // Truncate sub-millisecond precision before offsetting by the Unix Epoch to avoid
+ // the last digit being off by one for dates that result in negative Unix times
+ long milliseconds = UtcDateTime.Ticks / TimeSpan.TicksPerMillisecond;
+ return milliseconds - UnixEpochMilliseconds;
+ }
+
+ public DateTimeOffset ToLocalTime() {
+ return ToLocalTime(false);
+ }
+
+ internal DateTimeOffset ToLocalTime(bool throwOnOverflow)
+ {
+ return new DateTimeOffset(UtcDateTime.ToLocalTime(throwOnOverflow));
+ }
+
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.CurrentInfo, Offset);
+ }
+
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.CurrentInfo, Offset);
+ }
+
+ public String ToString(IFormatProvider formatProvider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ }
+
+ public String ToString(String format, IFormatProvider formatProvider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
+ }
+
+ public DateTimeOffset ToUniversalTime() {
+ return new DateTimeOffset(UtcDateTime);
+ }
+
+ public static Boolean TryParse(String input, out DateTimeOffset result) {
+ TimeSpan offset;
+ DateTime dateResult;
+ Boolean parsed = DateTimeParse.TryParse(input,
+ DateTimeFormatInfo.CurrentInfo,
+ DateTimeStyles.None,
+ out dateResult,
+ out offset);
+ result = new DateTimeOffset(dateResult.Ticks, offset);
+ return parsed;
+ }
+
+ public static Boolean TryParse(String input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult;
+ Boolean parsed = DateTimeParse.TryParse(input,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out dateResult,
+ out offset);
+ result = new DateTimeOffset(dateResult.Ticks, offset);
+ return parsed;
+ }
+
+ public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles,
+ out DateTimeOffset result) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult;
+ Boolean parsed = DateTimeParse.TryParseExact(input,
+ format,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out dateResult,
+ out offset);
+ result = new DateTimeOffset(dateResult.Ticks, offset);
+ return parsed;
+ }
+
+ public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
+ out DateTimeOffset result) {
+ styles = ValidateStyles(styles, "styles");
+ TimeSpan offset;
+ DateTime dateResult;
+ Boolean parsed = DateTimeParse.TryParseExactMultiple(input,
+ formats,
+ DateTimeFormatInfo.GetInstance(formatProvider),
+ styles,
+ out dateResult,
+ out offset);
+ result = new DateTimeOffset(dateResult.Ticks, offset);
+ return parsed;
+ }
+
+ // Ensures the TimeSpan is valid to go in a DateTimeOffset.
+ private static Int16 ValidateOffset(TimeSpan offset) {
+ Int64 ticks = offset.Ticks;
+ if (ticks % TimeSpan.TicksPerMinute != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetPrecision"), "offset");
+ }
+ if (ticks < MinOffset || ticks > MaxOffset) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_OffsetOutOfRange"));
+ }
+ return (Int16)(offset.Ticks / TimeSpan.TicksPerMinute);
+ }
+
+ // Ensures that the time and offset are in range.
+ private static DateTime ValidateDate(DateTime dateTime, TimeSpan offset) {
+ // The key validation is that both the UTC and clock times fit. The clock time is validated
+ // by the DateTime constructor.
+ Contract.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated.");
+ // This operation cannot overflow because offset should have already been validated to be within
+ // 14 hours and the DateTime instance is more than that distance from the boundaries of Int64.
+ Int64 utcTicks = dateTime.Ticks - offset.Ticks;
+ if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_UTCOutOfRange"));
+ }
+ // make sure the Kind is set to Unspecified
+ //
+ return new DateTime(utcTicks, DateTimeKind.Unspecified);
+ }
+
+ private static DateTimeStyles ValidateStyles(DateTimeStyles style, String parameterName) {
+ if ((style & DateTimeFormatInfo.InvalidDateTimeStyles) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeStyles"), parameterName);
+ }
+ if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeStyles"), parameterName);
+ }
+ if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetInvalidDateTimeStyles"), parameterName);
+ }
+
+ Contract.EndContractBlock();
+ // RoundtripKind does not make sense for DateTimeOffset; ignore this flag for backward compatibility with DateTime
+ style &= ~DateTimeStyles.RoundtripKind;
+
+ // AssumeLocal is also ignored as that is what we do by default with DateTimeOffset.Parse
+ style &= ~DateTimeStyles.AssumeLocal;
+
+ return style;
+ }
+
+ // Operators
+
+ public static implicit operator DateTimeOffset (DateTime dateTime) {
+ return new DateTimeOffset(dateTime);
+ }
+
+ public static DateTimeOffset operator +(DateTimeOffset dateTimeOffset, TimeSpan timeSpan) {
+ return new DateTimeOffset(dateTimeOffset.ClockDateTime + timeSpan, dateTimeOffset.Offset);
+ }
+
+
+ public static DateTimeOffset operator -(DateTimeOffset dateTimeOffset, TimeSpan timeSpan) {
+ return new DateTimeOffset(dateTimeOffset.ClockDateTime - timeSpan, dateTimeOffset.Offset);
+ }
+
+ public static TimeSpan operator -(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime - right.UtcDateTime;
+ }
+
+ public static bool operator ==(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime == right.UtcDateTime;
+ }
+
+ public static bool operator !=(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime != right.UtcDateTime;
+ }
+
+ public static bool operator <(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime < right.UtcDateTime;
+ }
+
+ public static bool operator <=(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime <= right.UtcDateTime;
+ }
+
+ public static bool operator >(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime > right.UtcDateTime;
+ }
+
+ public static bool operator >=(DateTimeOffset left, DateTimeOffset right) {
+ return left.UtcDateTime >= right.UtcDateTime;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/DayOfWeek.cs b/src/mscorlib/src/System/DayOfWeek.cs
new file mode 100644
index 0000000000..37b8f8975d
--- /dev/null
+++ b/src/mscorlib/src/System/DayOfWeek.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Enum for the day of the week.
+**
+**
+============================================================*/
+namespace System {
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum DayOfWeek {
+ Sunday = 0,
+ Monday = 1,
+ Tuesday = 2,
+ Wednesday = 3,
+ Thursday = 4,
+ Friday = 5,
+ Saturday = 6,
+ }
+}
diff --git a/src/mscorlib/src/System/Decimal.cs b/src/mscorlib/src/System/Decimal.cs
new file mode 100644
index 0000000000..8a2c30ffa8
--- /dev/null
+++ b/src/mscorlib/src/System/Decimal.cs
@@ -0,0 +1,1244 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ // Implements the Decimal data type. The Decimal data type can
+ // represent values ranging from -79,228,162,514,264,337,593,543,950,335 to
+ // 79,228,162,514,264,337,593,543,950,335 with 28 significant digits. The
+ // Decimal data type is ideally suited to financial calculations that
+ // require a large number of significant digits and no round-off errors.
+ //
+ // The finite set of values of type Decimal are of the form m
+ // / 10e, where m is an integer such that
+ // -296 <; m <; 296, and e is an integer
+ // between 0 and 28 inclusive.
+ //
+ // Contrary to the float and double data types, decimal
+ // fractional numbers such as 0.1 can be represented exactly in the
+ // Decimal representation. In the float and double
+ // representations, such numbers are often infinite fractions, making those
+ // representations more prone to round-off errors.
+ //
+ // The Decimal class implements widening conversions from the
+ // ubyte, char, short, int, and long types
+ // to Decimal. These widening conversions never loose any information
+ // and never throw exceptions. The Decimal class also implements
+ // narrowing conversions from Decimal to ubyte, char,
+ // short, int, and long. These narrowing conversions round
+ // the Decimal value towards zero to the nearest integer, and then
+ // converts that integer to the destination type. An OverflowException
+ // is thrown if the result is not within the range of the destination type.
+ //
+ // The Decimal class provides a widening conversion from
+ // Currency to Decimal. This widening conversion never loses any
+ // information and never throws exceptions. The Currency class provides
+ // a narrowing conversion from Decimal to Currency. This
+ // narrowing conversion rounds the Decimal to four decimals and then
+ // converts that number to a Currency. An OverflowException
+ // is thrown if the result is not within the range of the Currency type.
+ //
+ // The Decimal class provides narrowing conversions to and from the
+ // float and double types. A conversion from Decimal to
+ // float or double may loose precision, but will not loose
+ // information about the overall magnitude of the numeric value, and will never
+ // throw an exception. A conversion from float or double to
+ // Decimal throws an OverflowException if the value is not within
+ // the range of the Decimal type.
+ [StructLayout(LayoutKind.Sequential)]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ public struct Decimal : IFormattable, IComparable, IConvertible, IComparable<Decimal>, IEquatable<Decimal>, IDeserializationCallback
+ {
+
+ // Sign mask for the flags field. A value of zero in this bit indicates a
+ // positive Decimal value, and a value of one in this bit indicates a
+ // negative Decimal value.
+ //
+ // Look at OleAut's DECIMAL_NEG constant to check for negative values
+ // in native code.
+ private const int SignMask = unchecked((int)0x80000000);
+ private const byte DECIMAL_NEG = 0x80;
+ private const byte DECIMAL_ADD = 0x00;
+
+ // Scale mask for the flags field. This byte in the flags field contains
+ // the power of 10 to divide the Decimal value by. The scale byte must
+ // contain a value between 0 and 28 inclusive.
+ private const int ScaleMask = 0x00FF0000;
+
+ // Number of bits scale is shifted by.
+ private const int ScaleShift = 16;
+
+ // The maximum power of 10 that a 32 bit integer can store
+ private const Int32 MaxInt32Scale = 9;
+
+ // Fast access for 10^n where n is 0-9
+ private static UInt32[] Powers10 = new UInt32[] {
+ 1,
+ 10,
+ 100,
+ 1000,
+ 10000,
+ 100000,
+ 1000000,
+ 10000000,
+ 100000000,
+ 1000000000
+ };
+
+ // Constant representing the Decimal value 0.
+ public const Decimal Zero = 0m;
+
+ // Constant representing the Decimal value 1.
+ public const Decimal One = 1m;
+
+ // Constant representing the Decimal value -1.
+ public const Decimal MinusOne = -1m;
+
+ // Constant representing the largest possible Decimal value. The value of
+ // this constant is 79,228,162,514,264,337,593,543,950,335.
+ public const Decimal MaxValue = 79228162514264337593543950335m;
+
+ // Constant representing the smallest possible Decimal value. The value of
+ // this constant is -79,228,162,514,264,337,593,543,950,335.
+ public const Decimal MinValue = -79228162514264337593543950335m;
+
+
+ // Constant representing the negative number that is the closest possible
+ // Decimal value to -0m.
+ private const Decimal NearNegativeZero = -0.000000000000000000000000001m;
+
+ // Constant representing the positive number that is the closest possible
+ // Decimal value to +0m.
+ private const Decimal NearPositiveZero = +0.000000000000000000000000001m;
+
+ // The lo, mid, hi, and flags fields contain the representation of the
+ // Decimal value. The lo, mid, and hi fields contain the 96-bit integer
+ // part of the Decimal. Bits 0-15 (the lower word) of the flags field are
+ // unused and must be zero; bits 16-23 contain must contain a value between
+ // 0 and 28, indicating the power of 10 to divide the 96-bit integer part
+ // by to produce the Decimal value; bits 24-30 are unused and must be zero;
+ // and finally bit 31 indicates the sign of the Decimal value, 0 meaning
+ // positive and 1 meaning negative.
+ //
+ // NOTE: Do not change the order in which these fields are declared. The
+ // native methods in this class rely on this particular order.
+ private int flags;
+ private int hi;
+ private int lo;
+ private int mid;
+
+
+ // Constructs a zero Decimal.
+ //public Decimal() {
+ // lo = 0;
+ // mid = 0;
+ // hi = 0;
+ // flags = 0;
+ //}
+
+ // Constructs a Decimal from an integer value.
+ //
+ public Decimal(int value) {
+ // JIT today can't inline methods that contains "starg" opcode.
+ // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg".
+ int value_copy = value;
+ if (value_copy >= 0) {
+ flags = 0;
+ }
+ else {
+ flags = SignMask;
+ value_copy = -value_copy;
+ }
+ lo = value_copy;
+ mid = 0;
+ hi = 0;
+ }
+
+ // Constructs a Decimal from an unsigned integer value.
+ //
+ [CLSCompliant(false)]
+ public Decimal(uint value) {
+ flags = 0;
+ lo = (int) value;
+ mid = 0;
+ hi = 0;
+ }
+
+ // Constructs a Decimal from a long value.
+ //
+ public Decimal(long value) {
+ // JIT today can't inline methods that contains "starg" opcode.
+ // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg".
+ long value_copy = value;
+ if (value_copy >= 0) {
+ flags = 0;
+ }
+ else {
+ flags = SignMask;
+ value_copy = -value_copy;
+ }
+ lo = (int)value_copy;
+ mid = (int)(value_copy >> 32);
+ hi = 0;
+ }
+
+ // Constructs a Decimal from an unsigned long value.
+ //
+ [CLSCompliant(false)]
+ public Decimal(ulong value) {
+ flags = 0;
+ lo = (int)value;
+ mid = (int)(value >> 32);
+ hi = 0;
+ }
+
+ // Constructs a Decimal from a float value.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern Decimal(float value);
+
+ // Constructs a Decimal from a double value.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern Decimal(double value);
+
+ // Constructs a Decimal from a Currency value.
+ //
+ internal Decimal(Currency value) {
+ this = Currency.ToDecimal(value);
+ }
+
+ // Don't remove these 2 methods below. They are required by the fx when the are dealing with Currency in their
+ // databases
+ public static long ToOACurrency(Decimal value)
+ {
+ return new Currency(value).ToOACurrency();
+ }
+
+ public static Decimal FromOACurrency(long cy)
+ {
+ return Currency.ToDecimal(Currency.FromOACurrency(cy));
+ }
+
+
+ // Constructs a Decimal from an integer array containing a binary
+ // representation. The bits argument must be a non-null integer
+ // array with four elements. bits[0], bits[1], and
+ // bits[2] contain the low, middle, and high 32 bits of the 96-bit
+ // integer part of the Decimal. bits[3] contains the scale factor
+ // and sign of the Decimal: bits 0-15 (the lower word) are unused and must
+ // be zero; bits 16-23 must contain a value between 0 and 28, indicating
+ // the power of 10 to divide the 96-bit integer part by to produce the
+ // Decimal value; bits 24-30 are unused and must be zero; and finally bit
+ // 31 indicates the sign of the Decimal value, 0 meaning positive and 1
+ // meaning negative.
+ //
+ // Note that there are several possible binary representations for the
+ // same numeric value. For example, the value 1 can be represented as {1,
+ // 0, 0, 0} (integer value 1 with a scale factor of 0) and equally well as
+ // {1000, 0, 0, 0x30000} (integer value 1000 with a scale factor of 3).
+ // The possible binary representations of a particular value are all
+ // equally valid, and all are numerically equivalent.
+ //
+ public Decimal(int[] bits) {
+ this.lo = 0;
+ this.mid = 0;
+ this.hi = 0;
+ this.flags = 0;
+ SetBits(bits);
+ }
+
+ private void SetBits(int[] bits) {
+ if (bits==null)
+ throw new ArgumentNullException("bits");
+ Contract.EndContractBlock();
+ if (bits.Length == 4) {
+ int f = bits[3];
+ if ((f & ~(SignMask | ScaleMask)) == 0 && (f & ScaleMask) <= (28 << 16)) {
+ lo = bits[0];
+ mid = bits[1];
+ hi = bits[2];
+ flags = f;
+ return;
+ }
+ }
+ throw new ArgumentException(Environment.GetResourceString("Arg_DecBitCtor"));
+ }
+
+ // Constructs a Decimal from its constituent parts.
+ //
+ public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) {
+ if (scale > 28)
+ throw new ArgumentOutOfRangeException("scale", Environment.GetResourceString("ArgumentOutOfRange_DecimalScale"));
+ Contract.EndContractBlock();
+ this.lo = lo;
+ this.mid = mid;
+ this.hi = hi;
+ this.flags = ((int)scale) << 16;
+ if (isNegative)
+ this.flags |= SignMask;
+ }
+
+ [OnSerializing]
+ void OnSerializing(StreamingContext ctx) {
+ // OnSerializing is called before serialization of an object
+ try {
+ SetBits( GetBits(this) );
+ } catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Overflow_Decimal"), e);
+ }
+ }
+
+ void IDeserializationCallback.OnDeserialization(Object sender) {
+ // OnDeserialization is called after each instance of this class is deserialized.
+ // This callback method performs decimal validation after being deserialized.
+ try {
+ SetBits( GetBits(this) );
+ } catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Overflow_Decimal"), e);
+ }
+ }
+
+ // Constructs a Decimal from its constituent parts.
+ private Decimal(int lo, int mid, int hi, int flags) {
+ if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) {
+ this.lo = lo;
+ this.mid = mid;
+ this.hi = hi;
+ this.flags = flags;
+ return;
+ }
+ throw new ArgumentException(Environment.GetResourceString("Arg_DecBitCtor"));
+ }
+
+ // Returns the absolute value of the given Decimal. If d is
+ // positive, the result is d. If d is negative, the result
+ // is -d.
+ //
+ internal static Decimal Abs(Decimal d) {
+ return new Decimal(d.lo, d.mid, d.hi, d.flags & ~SignMask);
+ }
+
+ // Adds two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Add(Decimal d1, Decimal d2)
+ {
+ FCallAddSub (ref d1, ref d2, DECIMAL_ADD);
+ return d1;
+ }
+
+ // FCallAddSub adds or subtracts two decimal values. On return, d1 contains the result
+ // of the operation. Passing in DECIMAL_ADD or DECIMAL_NEG for bSign indicates
+ // addition or subtraction, respectively.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallAddSub(ref Decimal d1, ref Decimal d2, byte bSign);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallAddSubOverflowed(ref Decimal d1, ref Decimal d2, byte bSign, ref bool overflowed);
+
+ // Rounds a Decimal to an integer value. The Decimal argument is rounded
+ // towards positive infinity.
+ public static Decimal Ceiling(Decimal d) {
+ return (-(Decimal.Floor(-d)));
+ }
+
+ // Compares two Decimal values, returning an integer that indicates their
+ // relationship.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int Compare(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern int FCallCompare(ref Decimal d1, ref Decimal d2);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Decimal, this method throws an ArgumentException.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ return 1;
+ if (!(value is Decimal))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal"));
+
+ Decimal other = (Decimal)value;
+ return FCallCompare(ref this, ref other);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int CompareTo(Decimal value)
+ {
+ return FCallCompare(ref this, ref value);
+ }
+
+ // Divides two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Divide(Decimal d1, Decimal d2)
+ {
+ FCallDivide (ref d1, ref d2);
+ return d1;
+ }
+
+ // FCallDivide divides two decimal values. On return, d1 contains the result
+ // of the operation.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallDivide(ref Decimal d1, ref Decimal d2);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallDivideOverflowed(ref Decimal d1, ref Decimal d2, ref bool overflowed);
+
+
+ // Checks if this Decimal is equal to a given object. Returns true
+ // if the given object is a boxed Decimal and its value is equal to the
+ // value of this Decimal. Returns false otherwise.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool Equals(Object value) {
+ if (value is Decimal) {
+ Decimal other = (Decimal)value;
+ return FCallCompare(ref this, ref other) == 0;
+ }
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool Equals(Decimal value)
+ {
+ return FCallCompare(ref this, ref value) == 0;
+ }
+
+ // Returns the hash code for this Decimal.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern override int GetHashCode();
+
+ // Compares two Decimal values for equality. Returns true if the two
+ // Decimal values are equal, or false if they are not equal.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool Equals(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) == 0;
+ }
+
+ // Rounds a Decimal to an integer value. The Decimal argument is rounded
+ // towards negative infinity.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Floor(Decimal d)
+ {
+ FCallFloor (ref d);
+ return d;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallFloor(ref Decimal d);
+
+ // Converts this Decimal to a string. The resulting string consists of an
+ // optional minus sign ("-") followed to a sequence of digits ("0" - "9"),
+ // optionally followed by a decimal point (".") and another sequence of
+ // digits.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ // Converts a string to a Decimal. The string must consist of an optional
+ // minus sign ("-") followed by a sequence of digits ("0" - "9"). The
+ // sequence of digits may optionally contain a single decimal point (".")
+ // character. Leading and trailing whitespace characters are allowed.
+ // Parse also allows a currency symbol, a trailing negative sign, and
+ // parentheses in the number.
+ //
+ public static Decimal Parse(String s) {
+ return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static Decimal Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimal(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static Decimal Parse(String s, IFormatProvider provider) {
+ return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static Decimal Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static Boolean TryParse(String s, out Decimal result) {
+ return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Decimal result) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ // Returns a binary representation of a Decimal. The return value is an
+ // integer array with four elements. Elements 0, 1, and 2 contain the low,
+ // middle, and high 32 bits of the 96-bit integer part of the Decimal.
+ // Element 3 contains the scale factor and sign of the Decimal: bits 0-15
+ // (the lower word) are unused; bits 16-23 contain a value between 0 and
+ // 28, indicating the power of 10 to divide the 96-bit integer part by to
+ // produce the Decimal value; bits 24-30 are unused; and finally bit 31
+ // indicates the sign of the Decimal value, 0 meaning positive and 1
+ // meaning negative.
+ //
+ public static int[] GetBits(Decimal d) {
+ return new int[] {d.lo, d.mid, d.hi, d.flags};
+ }
+
+ internal static void GetBytes(Decimal d, byte [] buffer) {
+ Contract.Requires((buffer != null && buffer.Length >= 16), "[GetBytes]buffer != null && buffer.Length >= 16");
+ buffer[0] = (byte) d.lo;
+ buffer[1] = (byte) (d.lo >> 8);
+ buffer[2] = (byte) (d.lo >> 16);
+ buffer[3] = (byte) (d.lo >> 24);
+
+ buffer[4] = (byte) d.mid;
+ buffer[5] = (byte) (d.mid >> 8);
+ buffer[6] = (byte) (d.mid >> 16);
+ buffer[7] = (byte) (d.mid >> 24);
+
+ buffer[8] = (byte) d.hi;
+ buffer[9] = (byte) (d.hi >> 8);
+ buffer[10] = (byte) (d.hi >> 16);
+ buffer[11] = (byte) (d.hi >> 24);
+
+ buffer[12] = (byte) d.flags;
+ buffer[13] = (byte) (d.flags >> 8);
+ buffer[14] = (byte) (d.flags >> 16);
+ buffer[15] = (byte) (d.flags >> 24);
+ }
+
+ internal static decimal ToDecimal(byte [] buffer) {
+ Contract.Requires((buffer != null && buffer.Length >= 16), "[ToDecimal]buffer != null && buffer.Length >= 16");
+ int lo = ((int)buffer[0]) | ((int)buffer[1] << 8) | ((int)buffer[2] << 16) | ((int)buffer[3] << 24);
+ int mid = ((int)buffer[4]) | ((int)buffer[5] << 8) | ((int)buffer[6] << 16) | ((int)buffer[7] << 24);
+ int hi = ((int)buffer[8]) | ((int)buffer[9] << 8) | ((int)buffer[10] << 16) | ((int)buffer[11] << 24);
+ int flags = ((int)buffer[12]) | ((int)buffer[13] << 8) | ((int)buffer[14] << 16) | ((int)buffer[15] << 24);
+ return new Decimal(lo,mid,hi,flags);
+ }
+
+ // This method does a 'raw' and 'unchecked' addition of a UInt32 to a Decimal in place.
+ // 'raw' means that it operates on the internal 96-bit unsigned integer value and
+ // ingores the sign and scale. This means that it is not equivalent to just adding
+ // that number, as the sign and scale are effectively applied to the UInt32 value also.
+ // 'unchecked' means that it does not fail if you overflow the 96 bit value.
+ private static void InternalAddUInt32RawUnchecked(ref Decimal value, UInt32 i) {
+ UInt32 v;
+ UInt32 sum;
+ v = (UInt32)value.lo;
+ sum = v + i;
+ value.lo = (Int32)sum;
+ if (sum < v || sum < i) {
+ v = (UInt32)value.mid;
+ sum = v + 1;
+ value.mid = (Int32)sum;
+ if (sum < v || sum < 1) {
+ value.hi = (Int32) ((UInt32)value.hi + 1);
+ }
+ }
+ }
+
+ // This method does an in-place division of a decimal by a UInt32, returning the remainder.
+ // Although it does not operate on the sign or scale, this does not result in any
+ // caveat for the result. It is equivalent to dividing by that number.
+ private static UInt32 InternalDivRemUInt32(ref Decimal value, UInt32 divisor) {
+ UInt32 remainder = 0;
+ UInt64 n;
+ if (value.hi != 0) {
+ n = ((UInt32) value.hi);
+ value.hi = (Int32)((UInt32)(n / divisor));
+ remainder = (UInt32)(n % divisor);
+ }
+ if (value.mid != 0 || remainder != 0) {
+ n = ((UInt64)remainder << 32) | (UInt32) value.mid;
+ value.mid = (Int32)((UInt32)(n / divisor));
+ remainder = (UInt32)(n % divisor);
+ }
+ if (value.lo != 0 || remainder != 0) {
+ n = ((UInt64)remainder << 32) | (UInt32) value.lo;
+ value.lo = (Int32)((UInt32)(n / divisor));
+ remainder = (UInt32)(n % divisor);
+ }
+ return remainder;
+ }
+
+ // Does an in-place round the specified number of digits, rounding mid-point values
+ // away from zero
+ private static void InternalRoundFromZero(ref Decimal d, int decimalCount) {
+ Int32 scale = (d.flags & ScaleMask) >> ScaleShift;
+ Int32 scaleDifference = scale - decimalCount;
+ if (scaleDifference <= 0) {
+ return;
+ }
+ // Divide the value by 10^scaleDifference
+ UInt32 lastRemainder;
+ UInt32 lastDivisor;
+ do {
+ Int32 diffChunk = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference;
+ lastDivisor = Powers10[diffChunk];
+ lastRemainder = InternalDivRemUInt32(ref d, lastDivisor);
+ scaleDifference -= diffChunk;
+ } while (scaleDifference > 0);
+
+ // Round away from zero at the mid point
+ if (lastRemainder >= (lastDivisor >> 1)) {
+ InternalAddUInt32RawUnchecked(ref d, 1);
+ }
+
+ // the scale becomes the desired decimal count
+ d.flags = ((decimalCount << ScaleShift) & ScaleMask) | (d.flags & SignMask);
+ }
+
+ // Returns the larger of two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static Decimal Max(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) >= 0? d1: d2;
+ }
+
+ // Returns the smaller of two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static Decimal Min(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) < 0? d1: d2;
+ }
+
+ public static Decimal Remainder(Decimal d1, Decimal d2) {
+ // OleAut doesn't provide a VarDecMod.
+
+ // In the operation x % y the sign of y does not matter. Result will have the sign of x.
+ d2.flags = (d2.flags & ~SignMask) | (d1.flags & SignMask);
+
+
+ // This piece of code is to work around the fact that Dividing a decimal with 28 digits number by decimal which causes
+ // causes the result to be 28 digits, can cause to be incorrectly rounded up.
+ // eg. Decimal.MaxValue / 2 * Decimal.MaxValue will overflow since the division by 2 was rounded instead of being truncked.
+ if (Abs(d1) < Abs(d2)) {
+ return d1;
+ }
+ d1 -= d2;
+
+ if (d1 == 0) {
+ // The sign of D1 will be wrong here. Fall through so that we still get a DivideByZeroException
+ d1.flags = (d1.flags & ~SignMask) | (d2.flags & SignMask);
+ }
+
+ // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2)
+ Decimal dividedResult = Truncate(d1/d2);
+ Decimal multipliedResult = dividedResult * d2;
+ Decimal result = d1 - multipliedResult;
+ // See if the result has crossed 0
+ if ((d1.flags & SignMask) != (result.flags & SignMask)) {
+
+ if (NearNegativeZero <= result && result <= NearPositiveZero) {
+ // Certain Remainder operations on decimals with 28 significant digits round
+ // to [+-]0.000000000000000000000000001m instead of [+-]0m during the intermediate calculations.
+ // 'zero' results just need their sign corrected.
+ result.flags = (result.flags & ~SignMask) | (d1.flags & SignMask);
+ }
+ else {
+ // If the division rounds up because it runs out of digits, the multiplied result can end up with a larger
+ // absolute value and the result of the formula crosses 0. To correct it can add the divisor back.
+ result += d2;
+ }
+ }
+
+ return result;
+ }
+
+ // Multiplies two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Multiply(Decimal d1, Decimal d2)
+ {
+ FCallMultiply (ref d1, ref d2);
+ return d1;
+ }
+
+ // FCallMultiply multiples two decimal values. On return, d1 contains the result
+ // of the operation.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallMultiply(ref Decimal d1, ref Decimal d2);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallMultiplyOverflowed(ref Decimal d1, ref Decimal d2, ref bool overflowed);
+
+ // Returns the negated value of the given Decimal. If d is non-zero,
+ // the result is -d. If d is zero, the result is zero.
+ //
+ public static Decimal Negate(Decimal d) {
+ return new Decimal(d.lo, d.mid, d.hi, d.flags ^ SignMask);
+ }
+
+ // Rounds a Decimal value to a given number of decimal places. The value
+ // given by d is rounded to the number of decimal places given by
+ // decimals. The decimals argument must be an integer between
+ // 0 and 28 inclusive.
+ //
+ // By default a mid-point value is rounded to the nearest even number. If the mode is
+ // passed in, it can also round away from zero.
+
+ public static Decimal Round(Decimal d) {
+ return Round(d, 0);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Round(Decimal d, int decimals)
+ {
+ FCallRound (ref d, decimals);
+ return d;
+ }
+
+ public static Decimal Round(Decimal d, MidpointRounding mode) {
+ return Round(d, 0, mode);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) {
+ if ((decimals < 0) || (decimals > 28))
+ throw new ArgumentOutOfRangeException("decimals", Environment.GetResourceString("ArgumentOutOfRange_DecimalRound"));
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");
+ }
+ Contract.EndContractBlock();
+
+ if (mode == MidpointRounding.ToEven) {
+ FCallRound (ref d, decimals);
+ }
+ else {
+ InternalRoundFromZero(ref d, decimals);
+ }
+ return d;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallRound(ref Decimal d, int decimals);
+
+ // Subtracts two Decimal values.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Subtract(Decimal d1, Decimal d2)
+ {
+ FCallAddSub(ref d1, ref d2, DECIMAL_NEG);
+ return d1;
+ }
+
+ // Converts a Decimal to an unsigned byte. The Decimal value is rounded
+ // towards zero to the nearest integer value, and the result of this
+ // operation is returned as a byte.
+ //
+ public static byte ToByte(Decimal value) {
+ uint temp;
+ try {
+ temp = ToUInt32(value);
+ }
+ catch (OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Byte"), e);
+ }
+ if (temp < Byte.MinValue || temp > Byte.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Byte"));
+ return (byte)temp;
+
+ }
+
+ // Converts a Decimal to a signed byte. The Decimal value is rounded
+ // towards zero to the nearest integer value, and the result of this
+ // operation is returned as a byte.
+ //
+ [CLSCompliant(false)]
+ public static sbyte ToSByte(Decimal value) {
+ int temp;
+ try {
+ temp = ToInt32(value);
+ }
+ catch (OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_SByte"), e);
+ }
+ if (temp < SByte.MinValue || temp > SByte.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_SByte"));
+ return (sbyte)temp;
+ }
+
+ // Converts a Decimal to a short. The Decimal value is
+ // rounded towards zero to the nearest integer value, and the result of
+ // this operation is returned as a short.
+ //
+ public static short ToInt16(Decimal value) {
+ int temp;
+ try {
+ temp = ToInt32(value);
+ }
+ catch (OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int16"), e);
+ }
+ if (temp < Int16.MinValue || temp > Int16.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Int16"));
+ return (short)temp;
+ }
+
+
+ // Converts a Decimal to a Currency. Since a Currency
+ // has fewer significant digits than a Decimal, this operation may
+ // produce round-off errors.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Currency ToCurrency(Decimal d)
+ {
+ Currency result = new Currency ();
+ FCallToCurrency (ref result, d);
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallToCurrency(ref Currency result, Decimal d);
+
+ // Converts a Decimal to a double. Since a double has fewer significant
+ // digits than a Decimal, this operation may produce round-off errors.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double ToDouble(Decimal d);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int FCallToInt32(Decimal d);
+
+ // Converts a Decimal to an integer. The Decimal value is rounded towards
+ // zero to the nearest integer value, and the result of this operation is
+ // returned as an integer.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int ToInt32(Decimal d) {
+ if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d);
+ if (d.hi == 0 && d.mid == 0) {
+ int i = d.lo;
+ if (d.flags >= 0) {
+ if (i >= 0) return i;
+ }
+ else {
+ i = -i;
+ if (i <= 0) return i;
+ }
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
+ }
+
+ // Converts a Decimal to a long. The Decimal value is rounded towards zero
+ // to the nearest integer value, and the result of this operation is
+ // returned as a long.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static long ToInt64(Decimal d) {
+ if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d);
+ if (d.hi == 0) {
+ long l = d.lo & 0xFFFFFFFFL | (long)d.mid << 32;
+ if (d.flags >= 0) {
+ if (l >= 0) return l;
+ }
+ else {
+ l = -l;
+ if (l <= 0) return l;
+ }
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
+ }
+
+ // Converts a Decimal to an ushort. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as an ushort.
+ //
+ [CLSCompliant(false)]
+ public static ushort ToUInt16(Decimal value) {
+ uint temp;
+ try {
+ temp = ToUInt32(value);
+ }
+ catch (OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt16"), e);
+ }
+ if (temp < UInt16.MinValue || temp > UInt16.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_UInt16"));
+ return (ushort)temp;
+ }
+
+ // Converts a Decimal to an unsigned integer. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as an unsigned integer.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public static uint ToUInt32(Decimal d) {
+ if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d);
+ if (d.hi == 0 && d.mid == 0) {
+ uint i = (uint) d.lo;
+ if (d.flags >= 0 || i == 0)
+ return i;
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt32"));
+ }
+
+ // Converts a Decimal to an unsigned long. The Decimal
+ // value is rounded towards zero to the nearest integer value, and the
+ // result of this operation is returned as a long.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public static ulong ToUInt64(Decimal d) {
+ if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d);
+ if (d.hi == 0) {
+ ulong l = ((ulong)(uint)d.lo) | ((ulong)(uint)d.mid << 32);
+ if (d.flags >= 0 || l == 0)
+ return l;
+ }
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt64"));
+ }
+
+ // Converts a Decimal to a float. Since a float has fewer significant
+ // digits than a Decimal, this operation may produce round-off errors.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern float ToSingle(Decimal d);
+
+ // Truncates a Decimal to an integer value. The Decimal argument is rounded
+ // towards zero to the nearest integer value, corresponding to removing all
+ // digits after the decimal point.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal Truncate(Decimal d)
+ {
+ FCallTruncate (ref d);
+ return d;
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallTruncate(ref Decimal d);
+
+
+ public static implicit operator Decimal(byte value) {
+ return new Decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Decimal(sbyte value) {
+ return new Decimal(value);
+ }
+
+ public static implicit operator Decimal(short value) {
+ return new Decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Decimal(ushort value) {
+ return new Decimal(value);
+ }
+
+ public static implicit operator Decimal(char value) {
+ return new Decimal(value);
+ }
+
+ public static implicit operator Decimal(int value) {
+ return new Decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Decimal(uint value) {
+ return new Decimal(value);
+ }
+
+ public static implicit operator Decimal(long value) {
+ return new Decimal(value);
+ }
+
+ [CLSCompliant(false)]
+ public static implicit operator Decimal(ulong value) {
+ return new Decimal(value);
+ }
+
+
+ public static explicit operator Decimal(float value) {
+ return new Decimal(value);
+ }
+
+ public static explicit operator Decimal(double value) {
+ return new Decimal(value);
+ }
+
+ public static explicit operator byte(Decimal value) {
+ return ToByte(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator sbyte(Decimal value) {
+ return ToSByte(value);
+ }
+
+ public static explicit operator char(Decimal value) {
+ UInt16 temp;
+ try {
+ temp = ToUInt16(value);
+ }
+ catch (OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Char"), e);
+ }
+ return (char)temp;
+ }
+
+ public static explicit operator short(Decimal value) {
+ return ToInt16(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator ushort(Decimal value) {
+ return ToUInt16(value);
+ }
+
+ public static explicit operator int(Decimal value) {
+ return ToInt32(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator uint(Decimal value) {
+ return ToUInt32(value);
+ }
+
+ public static explicit operator long(Decimal value) {
+ return ToInt64(value);
+ }
+
+ [CLSCompliant(false)]
+ public static explicit operator ulong(Decimal value) {
+ return ToUInt64(value);
+ }
+
+ public static explicit operator float(Decimal value) {
+ return ToSingle(value);
+ }
+
+ public static explicit operator double(Decimal value) {
+ return ToDouble(value);
+ }
+
+ public static Decimal operator +(Decimal d) {
+ return d;
+ }
+
+ public static Decimal operator -(Decimal d) {
+ return Negate(d);
+ }
+
+ public static Decimal operator ++(Decimal d) {
+ return Add(d, One);
+ }
+
+ public static Decimal operator --(Decimal d) {
+ return Subtract(d, One);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal operator +(Decimal d1, Decimal d2) {
+ FCallAddSub(ref d1, ref d2, DECIMAL_ADD);
+ return d1;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal operator -(Decimal d1, Decimal d2) {
+ FCallAddSub(ref d1, ref d2, DECIMAL_NEG);
+ return d1;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal operator *(Decimal d1, Decimal d2) {
+ FCallMultiply (ref d1, ref d2);
+ return d1;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Decimal operator /(Decimal d1, Decimal d2) {
+ FCallDivide (ref d1, ref d2);
+ return d1;
+ }
+
+ public static Decimal operator %(Decimal d1, Decimal d2) {
+ return Remainder(d1, d2);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator ==(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) == 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator !=(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) != 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator <(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) < 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator <=(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) <= 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator >(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) > 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool operator >=(Decimal d1, Decimal d2) {
+ return FCallCompare(ref d1, ref d2) >= 0;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Decimal;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(this);
+ }
+
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Decimal", "Char"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(this);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(this);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(this);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(this);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(this);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(this);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(this);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(this);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(this);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(this);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return this;
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Decimal", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/DefaultBinder.cs b/src/mscorlib/src/System/DefaultBinder.cs
new file mode 100644
index 0000000000..405055e844
--- /dev/null
+++ b/src/mscorlib/src/System/DefaultBinder.cs
@@ -0,0 +1,1168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// This class represents the Default COM+ binder.
+//
+//
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+ //Marked serializable even though it has no state.
+ [Serializable]
+ internal class DefaultBinder : Binder
+ {
+ // This method is passed a set of methods and must choose the best
+ // fit. The methods all have the same number of arguments and the object
+ // array args. On exit, this method will choice the best fit method
+ // and coerce the args to match that method. By match, we mean all primitive
+ // arguments are exact matchs and all object arguments are exact or subclasses
+ // of the target. If the target OR is an interface, the object must implement
+ // that interface. There are a couple of exceptions
+ // thrown when a method cannot be returned. If no method matchs the args and
+ // ArgumentException is thrown. If multiple methods match the args then
+ // an AmbiguousMatchException is thrown.
+ //
+ // The most specific match will be selected.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MethodBase BindToMethod(
+ BindingFlags bindingAttr, MethodBase[] match, ref Object[] args,
+ ParameterModifier[] modifiers, CultureInfo cultureInfo, String[] names, out Object state)
+ {
+ if (match == null || match.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match");
+ Contract.EndContractBlock();
+
+ MethodBase[] candidates = (MethodBase[]) match.Clone();
+
+ int i;
+ int j;
+
+ state = null;
+
+ #region Map named parameters to candidate parameter postions
+ // We are creating an paramOrder array to act as a mapping
+ // between the order of the args and the actual order of the
+ // parameters in the method. This order may differ because
+ // named parameters (names) may change the order. If names
+ // is not provided, then we assume the default mapping (0,1,...)
+ int[][] paramOrder = new int[candidates.Length][];
+
+ for (i = 0; i < candidates.Length; i++)
+ {
+ ParameterInfo[] par = candidates[i].GetParametersNoCopy();
+
+ // args.Length + 1 takes into account the possibility of a last paramArray that can be omitted
+ paramOrder[i] = new int[(par.Length > args.Length) ? par.Length : args.Length];
+
+ if (names == null)
+ {
+ // Default mapping
+ for (j = 0; j < args.Length; j++)
+ paramOrder[i][j] = j;
+ }
+ else
+ {
+ // Named parameters, reorder the mapping. If CreateParamOrder fails, it means that the method
+ // doesn't have a name that matchs one of the named parameters so we don't consider it any further.
+ if (!CreateParamOrder(paramOrder[i], par, names))
+ candidates[i] = null;
+ }
+ }
+ #endregion
+
+ Type[] paramArrayTypes = new Type[candidates.Length];
+
+ Type[] argTypes = new Type[args.Length];
+
+ #region Cache the type of the provided arguments
+ // object that contain a null are treated as if they were typeless (but match either object
+ // references or value classes). We mark this condition by placing a null in the argTypes array.
+ for (i = 0; i < args.Length; i++)
+ {
+ if (args[i] != null)
+ {
+ argTypes[i] = args[i].GetType();
+ }
+ }
+ #endregion
+
+
+ // Find the method that matches...
+ int CurIdx = 0;
+ bool defaultValueBinding = ((bindingAttr & BindingFlags.OptionalParamBinding) != 0);
+
+ Type paramArrayType = null;
+
+ #region Filter methods by parameter count and type
+ for (i = 0; i < candidates.Length; i++)
+ {
+ paramArrayType = null;
+
+ // If we have named parameters then we may have a hole in the candidates array.
+ if (candidates[i] == null)
+ continue;
+
+ // Validate the parameters.
+ ParameterInfo[] par = candidates[i].GetParametersNoCopy();
+
+ #region Match method by parameter count
+ if (par.Length == 0)
+ {
+ #region No formal parameters
+ if (args.Length != 0)
+ {
+ if ((candidates[i].CallingConvention & CallingConventions.VarArgs) == 0)
+ continue;
+ }
+
+ // This is a valid routine so we move it up the candidates list.
+ paramOrder[CurIdx] = paramOrder[i];
+ candidates[CurIdx++] = candidates[i];
+
+ continue;
+ #endregion
+ }
+ else if (par.Length > args.Length)
+ {
+ #region Shortage of provided parameters
+ // If the number of parameters is greater than the number of args then
+ // we are in the situation were we may be using default values.
+ for (j = args.Length; j < par.Length - 1; j++)
+ {
+ if (par[j].DefaultValue == System.DBNull.Value)
+ break;
+ }
+
+ if (j != par.Length - 1)
+ continue;
+
+ if (par[j].DefaultValue == System.DBNull.Value)
+ {
+ if (!par[j].ParameterType.IsArray)
+ continue;
+
+ if (!par[j].IsDefined(typeof(ParamArrayAttribute), true))
+ continue;
+
+ paramArrayType = par[j].ParameterType.GetElementType();
+ }
+ #endregion
+ }
+ else if (par.Length < args.Length)
+ {
+ #region Excess provided parameters
+ // test for the ParamArray case
+ int lastArgPos = par.Length - 1;
+
+ if (!par[lastArgPos].ParameterType.IsArray)
+ continue;
+
+ if (!par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true))
+ continue;
+
+ if (paramOrder[i][lastArgPos] != lastArgPos)
+ continue;
+
+ paramArrayType = par[lastArgPos].ParameterType.GetElementType();
+ #endregion
+ }
+ else
+ {
+ #region Test for paramArray, save paramArray type
+ int lastArgPos = par.Length - 1;
+
+ if (par[lastArgPos].ParameterType.IsArray
+ && par[lastArgPos].IsDefined(typeof(ParamArrayAttribute), true)
+ && paramOrder[i][lastArgPos] == lastArgPos)
+ {
+ if (!par[lastArgPos].ParameterType.IsAssignableFrom(argTypes[lastArgPos]))
+ paramArrayType = par[lastArgPos].ParameterType.GetElementType();
+ }
+ #endregion
+ }
+ #endregion
+
+ Type pCls = null;
+ int argsToCheck = (paramArrayType != null) ? par.Length - 1 : args.Length;
+
+ #region Match method by parameter type
+ for (j = 0; j < argsToCheck; j++)
+ {
+ #region Classic argument coersion checks
+ // get the formal type
+ pCls = par[j].ParameterType;
+
+ if (pCls.IsByRef)
+ pCls = pCls.GetElementType();
+
+ // the type is the same
+ if (pCls == argTypes[paramOrder[i][j]])
+ continue;
+
+ // a default value is available
+ if (defaultValueBinding && args[paramOrder[i][j]] == Type.Missing)
+ continue;
+
+ // the argument was null, so it matches with everything
+ if (args[paramOrder[i][j]] == null)
+ continue;
+
+ // the type is Object, so it will match everything
+ if (pCls == typeof(Object))
+ continue;
+
+ // now do a "classic" type check
+ if (pCls.IsPrimitive)
+ {
+ if (argTypes[paramOrder[i][j]] == null || !CanConvertPrimitiveObjectToType(args[paramOrder[i][j]],(RuntimeType)pCls))
+ {
+ break;
+ }
+ }
+ else
+ {
+ if (argTypes[paramOrder[i][j]] == null)
+ continue;
+
+ if (!pCls.IsAssignableFrom(argTypes[paramOrder[i][j]]))
+ {
+ if (argTypes[paramOrder[i][j]].IsCOMObject)
+ {
+ if (pCls.IsInstanceOfType(args[paramOrder[i][j]]))
+ continue;
+ }
+ break;
+ }
+ }
+ #endregion
+ }
+
+ if (paramArrayType != null && j == par.Length - 1)
+ {
+ #region Check that excess arguments can be placed in the param array
+ for (; j < args.Length; j++)
+ {
+ if (paramArrayType.IsPrimitive)
+ {
+ if (argTypes[j] == null || !CanConvertPrimitiveObjectToType(args[j], (RuntimeType)paramArrayType))
+ break;
+ }
+ else
+ {
+ if (argTypes[j] == null)
+ continue;
+
+ if (!paramArrayType.IsAssignableFrom(argTypes[j]))
+ {
+ if (argTypes[j].IsCOMObject)
+ {
+ if (paramArrayType.IsInstanceOfType(args[j]))
+ continue;
+ }
+
+ break;
+ }
+ }
+ }
+ #endregion
+ }
+ #endregion
+
+ if (j == args.Length)
+ {
+ #region This is a valid routine so we move it up the candidates list
+ paramOrder[CurIdx] = paramOrder[i];
+ paramArrayTypes[CurIdx] = paramArrayType;
+ candidates[CurIdx++] = candidates[i];
+ #endregion
+ }
+ }
+ #endregion
+
+ // If we didn't find a method
+ if (CurIdx == 0)
+ throw new MissingMethodException(Environment.GetResourceString("MissingMember"));
+
+ if (CurIdx == 1)
+ {
+ #region Found only one method
+ if (names != null)
+ {
+ state = new BinderState((int[])paramOrder[0].Clone(), args.Length, paramArrayTypes[0] != null);
+ ReorderParams(paramOrder[0],args);
+ }
+
+ // If the parameters and the args are not the same length or there is a paramArray
+ // then we need to create a argument array.
+ ParameterInfo[] parms = candidates[0].GetParametersNoCopy();
+
+ if (parms.Length == args.Length)
+ {
+ if (paramArrayTypes[0] != null)
+ {
+ Object[] objs = new Object[parms.Length];
+ int lastPos = parms.Length - 1;
+ Array.Copy(args, 0, objs, 0, lastPos);
+ objs[lastPos] = Array.UnsafeCreateInstance(paramArrayTypes[0], 1);
+ ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
+ args = objs;
+ }
+ }
+ else if (parms.Length > args.Length)
+ {
+ Object[] objs = new Object[parms.Length];
+
+ for (i=0;i<args.Length;i++)
+ objs[i] = args[i];
+
+ for (;i<parms.Length - 1;i++)
+ objs[i] = parms[i].DefaultValue;
+
+ if (paramArrayTypes[0] != null)
+ objs[i] = Array.UnsafeCreateInstance(paramArrayTypes[0], 0); // create an empty array for the
+
+ else
+ objs[i] = parms[i].DefaultValue;
+
+ args = objs;
+ }
+ else
+ {
+ if ((candidates[0].CallingConvention & CallingConventions.VarArgs) == 0)
+ {
+ Object[] objs = new Object[parms.Length];
+ int paramArrayPos = parms.Length - 1;
+ Array.Copy(args, 0, objs, 0, paramArrayPos);
+ objs[paramArrayPos] = Array.UnsafeCreateInstance(paramArrayTypes[0], args.Length - paramArrayPos);
+ Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
+ args = objs;
+ }
+ }
+ #endregion
+
+ return candidates[0];
+ }
+
+ int currentMin = 0;
+ bool ambig = false;
+ for (i = 1; i < CurIdx; i++)
+ {
+ #region Walk all of the methods looking the most specific method to invoke
+ int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder[currentMin], paramArrayTypes[currentMin],
+ candidates[i], paramOrder[i], paramArrayTypes[i], argTypes, args);
+
+ if (newMin == 0)
+ {
+ ambig = true;
+ }
+ else if (newMin == 2)
+ {
+ currentMin = i;
+ ambig = false;
+ }
+ #endregion
+ }
+
+ if (ambig)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ // Reorder (if needed)
+ if (names != null) {
+ state = new BinderState((int[])paramOrder[currentMin].Clone(), args.Length, paramArrayTypes[currentMin] != null);
+ ReorderParams(paramOrder[currentMin], args);
+ }
+
+ // If the parameters and the args are not the same length or there is a paramArray
+ // then we need to create a argument array.
+ ParameterInfo[] parameters = candidates[currentMin].GetParametersNoCopy();
+ if (parameters.Length == args.Length)
+ {
+ if (paramArrayTypes[currentMin] != null)
+ {
+ Object[] objs = new Object[parameters.Length];
+ int lastPos = parameters.Length - 1;
+ Array.Copy(args, 0, objs, 0, lastPos);
+ objs[lastPos] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], 1);
+ ((Array)objs[lastPos]).SetValue(args[lastPos], 0);
+ args = objs;
+ }
+ }
+ else if (parameters.Length > args.Length)
+ {
+ Object[] objs = new Object[parameters.Length];
+
+ for (i=0;i<args.Length;i++)
+ objs[i] = args[i];
+
+ for (;i<parameters.Length - 1;i++)
+ objs[i] = parameters[i].DefaultValue;
+
+ if (paramArrayTypes[currentMin] != null)
+ {
+ objs[i] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], 0);
+ }
+ else
+ {
+ objs[i] = parameters[i].DefaultValue;
+ }
+
+ args = objs;
+ }
+ else
+ {
+ if ((candidates[currentMin].CallingConvention & CallingConventions.VarArgs) == 0)
+ {
+ Object[] objs = new Object[parameters.Length];
+ int paramArrayPos = parameters.Length - 1;
+ Array.Copy(args, 0, objs, 0, paramArrayPos);
+ objs[paramArrayPos] = Array.UnsafeCreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos);
+ Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos);
+ args = objs;
+ }
+ }
+
+ return candidates[currentMin];
+ }
+
+
+ // Given a set of fields that match the base criteria, select a field.
+ // if value is null then we have no way to select a field
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override FieldInfo BindToField(BindingFlags bindingAttr,FieldInfo[] match, Object value,CultureInfo cultureInfo)
+ {
+ if (match == null) {
+ throw new ArgumentNullException("match");
+ }
+
+ int i;
+ // Find the method that match...
+ int CurIdx = 0;
+
+ Type valueType = null;
+
+ FieldInfo[] candidates = (FieldInfo[]) match.Clone();
+
+ // If we are a FieldSet, then use the value's type to disambiguate
+ if ((bindingAttr & BindingFlags.SetField) != 0) {
+ valueType = value.GetType();
+
+ for (i=0;i<candidates.Length;i++) {
+ Type pCls = candidates[i].FieldType;
+ if (pCls == valueType) {
+ candidates[CurIdx++] = candidates[i];
+ continue;
+ }
+ if (value == Empty.Value) {
+ // the object passed in was null which would match any non primitive non value type
+ if (pCls.IsClass) {
+ candidates[CurIdx++] = candidates[i];
+ continue;
+ }
+ }
+ if (pCls == typeof(Object)) {
+ candidates[CurIdx++] = candidates[i];
+ continue;
+ }
+ if (pCls.IsPrimitive) {
+ if (CanConvertPrimitiveObjectToType(value,(RuntimeType)pCls)) {
+ candidates[CurIdx++] = candidates[i];
+ continue;
+ }
+ }
+ else {
+ if (pCls.IsAssignableFrom(valueType)) {
+ candidates[CurIdx++] = candidates[i];
+ continue;
+ }
+ }
+ }
+ if (CurIdx == 0)
+ throw new MissingFieldException(Environment.GetResourceString("MissingField"));
+ if (CurIdx == 1)
+ return candidates[0];
+ }
+
+ // Walk all of the methods looking the most specific method to invoke
+ int currentMin = 0;
+ bool ambig = false;
+ for (i=1;i<CurIdx;i++) {
+ int newMin = FindMostSpecificField(candidates[currentMin], candidates[i]);
+ if (newMin == 0)
+ ambig = true;
+ else {
+ if (newMin == 2) {
+ currentMin = i;
+ ambig = false;
+ }
+ }
+ }
+ if (ambig)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ return candidates[currentMin];
+ }
+
+ // Given a set of methods that match the base criteria, select a method based
+ // upon an array of types. This method should return null if no method matchs
+ // the criteria.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MethodBase SelectMethod(BindingFlags bindingAttr,MethodBase[] match,Type[] types,ParameterModifier[] modifiers)
+ {
+ int i;
+ int j;
+
+ Type[] realTypes = new Type[types.Length];
+ for (i=0;i<types.Length;i++) {
+ realTypes[i] = types[i].UnderlyingSystemType;
+ if (!(realTypes[i] is RuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"types");
+ }
+ types = realTypes;
+
+ // We don't automatically jump out on exact match.
+ if (match == null || match.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match");
+
+ MethodBase[] candidates = (MethodBase[]) match.Clone();
+
+ // Find all the methods that can be described by the types parameter.
+ // Remove all of them that cannot.
+ int CurIdx = 0;
+ for (i=0;i<candidates.Length;i++) {
+ ParameterInfo[] par = candidates[i].GetParametersNoCopy();
+ if (par.Length != types.Length)
+ continue;
+ for (j=0;j<types.Length;j++) {
+ Type pCls = par[j].ParameterType;
+ if (pCls == types[j])
+ continue;
+ if (pCls == typeof(Object))
+ continue;
+ if (pCls.IsPrimitive) {
+ if (!(types[j].UnderlyingSystemType is RuntimeType) ||
+ !CanConvertPrimitive((RuntimeType)types[j].UnderlyingSystemType,(RuntimeType)pCls.UnderlyingSystemType))
+ break;
+ }
+ else {
+ if (!pCls.IsAssignableFrom(types[j]))
+ break;
+ }
+ }
+ if (j == types.Length)
+ candidates[CurIdx++] = candidates[i];
+ }
+ if (CurIdx == 0)
+ return null;
+ if (CurIdx == 1)
+ return candidates[0];
+
+ // Walk all of the methods looking the most specific method to invoke
+ int currentMin = 0;
+ bool ambig = false;
+ int[] paramOrder = new int[types.Length];
+ for (i=0;i<types.Length;i++)
+ paramOrder[i] = i;
+ for (i=1;i<CurIdx;i++) {
+ int newMin = FindMostSpecificMethod(candidates[currentMin], paramOrder, null, candidates[i], paramOrder, null, types, null);
+ if (newMin == 0)
+ ambig = true;
+ else {
+ if (newMin == 2) {
+ currentMin = i;
+ ambig = false;
+ currentMin = i;
+ }
+ }
+ }
+ if (ambig)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ return candidates[currentMin];
+ }
+
+ // Given a set of properties that match the base criteria, select one.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override PropertyInfo SelectProperty(BindingFlags bindingAttr,PropertyInfo[] match,Type returnType,
+ Type[] indexes,ParameterModifier[] modifiers)
+ {
+ // Allow a null indexes array. But if it is not null, every element must be non-null as well.
+ if (indexes != null && !Contract.ForAll(indexes, delegate(Type t) { return t != null; }))
+ {
+ throw new ArgumentNullException("indexes");
+ }
+ if (match == null || match.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "match");
+ Contract.EndContractBlock();
+
+ PropertyInfo[] candidates = (PropertyInfo[]) match.Clone();
+
+ int i,j = 0;
+
+ // Find all the properties that can be described by type indexes parameter
+ int CurIdx = 0;
+ int indexesLength = (indexes != null) ? indexes.Length : 0;
+ for (i=0;i<candidates.Length;i++) {
+
+ if (indexes != null)
+ {
+ ParameterInfo[] par = candidates[i].GetIndexParameters();
+ if (par.Length != indexesLength)
+ continue;
+
+ for (j=0;j<indexesLength;j++) {
+ Type pCls = par[j]. ParameterType;
+
+ // If the classes exactly match continue
+ if (pCls == indexes[j])
+ continue;
+ if (pCls == typeof(Object))
+ continue;
+
+ if (pCls.IsPrimitive) {
+ if (!(indexes[j].UnderlyingSystemType is RuntimeType) ||
+ !CanConvertPrimitive((RuntimeType)indexes[j].UnderlyingSystemType,(RuntimeType)pCls.UnderlyingSystemType))
+ break;
+ }
+ else {
+ if (!pCls.IsAssignableFrom(indexes[j]))
+ break;
+ }
+ }
+ }
+
+ if (j == indexesLength) {
+ if (returnType != null) {
+ if (candidates[i].PropertyType.IsPrimitive) {
+ if (!(returnType.UnderlyingSystemType is RuntimeType) ||
+ !CanConvertPrimitive((RuntimeType)returnType.UnderlyingSystemType,(RuntimeType)candidates[i].PropertyType.UnderlyingSystemType))
+ continue;
+ }
+ else {
+ if (!candidates[i].PropertyType.IsAssignableFrom(returnType))
+ continue;
+ }
+ }
+ candidates[CurIdx++] = candidates[i];
+ }
+ }
+ if (CurIdx == 0)
+ return null;
+ if (CurIdx == 1)
+ return candidates[0];
+
+ // Walk all of the properties looking the most specific method to invoke
+ int currentMin = 0;
+ bool ambig = false;
+ int[] paramOrder = new int[indexesLength];
+ for (i=0;i<indexesLength;i++)
+ paramOrder[i] = i;
+ for (i=1;i<CurIdx;i++) {
+ int newMin = FindMostSpecificType(candidates[currentMin].PropertyType, candidates[i].PropertyType,returnType);
+ if (newMin == 0 && indexes != null)
+ newMin = FindMostSpecific(candidates[currentMin].GetIndexParameters(),
+ paramOrder,
+ null,
+ candidates[i].GetIndexParameters(),
+ paramOrder,
+ null,
+ indexes,
+ null);
+ if (newMin == 0)
+ {
+ newMin = FindMostSpecificProperty(candidates[currentMin], candidates[i]);
+ if (newMin == 0)
+ ambig = true;
+ }
+ if (newMin == 2) {
+ ambig = false;
+ currentMin = i;
+ }
+ }
+
+ if (ambig)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ return candidates[currentMin];
+ }
+
+ // ChangeType
+ // The default binder doesn't support any change type functionality.
+ // This is because the default is built into the low level invoke code.
+ public override Object ChangeType(Object value,Type type,CultureInfo cultureInfo)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ChangeType"));
+ }
+
+ public override void ReorderArgumentArray(ref Object[] args, Object state)
+ {
+ BinderState binderState = (BinderState)state;
+ ReorderParams(binderState.m_argsMap, args);
+ if (binderState.m_isParamArray) {
+ int paramArrayPos = args.Length - 1;
+ if (args.Length == binderState.m_originalSize)
+ args[paramArrayPos] = ((Object[])args[paramArrayPos])[0];
+ else {
+ // must be args.Length < state.originalSize
+ Object[] newArgs = new Object[args.Length];
+ Array.Copy(args, 0, newArgs, 0, paramArrayPos);
+ for (int i = paramArrayPos, j = 0; i < newArgs.Length; i++, j++) {
+ newArgs[i] = ((Object[])args[paramArrayPos])[j];
+ }
+ args = newArgs;
+ }
+ }
+ else {
+ if (args.Length > binderState.m_originalSize) {
+ Object[] newArgs = new Object[binderState.m_originalSize];
+ Array.Copy(args, 0, newArgs, 0, binderState.m_originalSize);
+ args = newArgs;
+ }
+ }
+ }
+
+ // Return any exact bindings that may exist. (This method is not defined on the
+ // Binder and is used by RuntimeType.)
+ public static MethodBase ExactBinding(MethodBase[] match,Type[] types,ParameterModifier[] modifiers)
+ {
+ if (match==null)
+ throw new ArgumentNullException("match");
+ Contract.EndContractBlock();
+ MethodBase[] aExactMatches = new MethodBase[match.Length];
+ int cExactMatches = 0;
+
+ for (int i=0;i<match.Length;i++) {
+ ParameterInfo[] par = match[i].GetParametersNoCopy();
+ if (par.Length == 0) {
+ continue;
+ }
+ int j;
+ for (j=0;j<types.Length;j++) {
+ Type pCls = par[j]. ParameterType;
+
+ // If the classes exactly match continue
+ if (!pCls.Equals(types[j]))
+ break;
+ }
+ if (j < types.Length)
+ continue;
+
+ // Add the exact match to the array of exact matches.
+ aExactMatches[cExactMatches] = match[i];
+ cExactMatches++;
+ }
+
+ if (cExactMatches == 0)
+ return null;
+
+ if (cExactMatches == 1)
+ return aExactMatches[0];
+
+ return FindMostDerivedNewSlotMeth(aExactMatches, cExactMatches);
+ }
+
+ // Return any exact bindings that may exist. (This method is not defined on the
+ // Binder and is used by RuntimeType.)
+ public static PropertyInfo ExactPropertyBinding(PropertyInfo[] match,Type returnType,Type[] types,ParameterModifier[] modifiers)
+ {
+ if (match==null)
+ throw new ArgumentNullException("match");
+ Contract.EndContractBlock();
+
+ PropertyInfo bestMatch = null;
+ int typesLength = (types != null) ? types.Length : 0;
+ for (int i=0;i<match.Length;i++) {
+ ParameterInfo[] par = match[i].GetIndexParameters();
+ int j;
+ for (j=0;j<typesLength;j++) {
+ Type pCls = par[j].ParameterType;
+
+ // If the classes exactly match continue
+ if (pCls != types[j])
+ break;
+ }
+ if (j < typesLength)
+ continue;
+ if (returnType != null && returnType != match[i].PropertyType)
+ continue;
+
+ if (bestMatch != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ bestMatch = match[i];
+ }
+ return bestMatch;
+ }
+
+ private static int FindMostSpecific(ParameterInfo[] p1, int[] paramOrder1, Type paramArrayType1,
+ ParameterInfo[] p2, int[] paramOrder2, Type paramArrayType2,
+ Type[] types, Object[] args)
+ {
+ // A method using params is always less specific than one not using params
+ if (paramArrayType1 != null && paramArrayType2 == null) return 2;
+ if (paramArrayType2 != null && paramArrayType1 == null) return 1;
+
+ // now either p1 and p2 both use params or neither does.
+
+ bool p1Less = false;
+ bool p2Less = false;
+
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (args != null && args[i] == Type.Missing)
+ continue;
+
+ Type c1, c2;
+
+ // If a param array is present, then either
+ // the user re-ordered the parameters in which case
+ // the argument to the param array is either an array
+ // in which case the params is conceptually ignored and so paramArrayType1 == null
+ // or the argument to the param array is a single element
+ // in which case paramOrder[i] == p1.Length - 1 for that element
+ // or the user did not re-order the parameters in which case
+ // the paramOrder array could contain indexes larger than p.Length - 1 (see VSW 577286)
+ // so any index >= p.Length - 1 is being put in the param array
+
+ if (paramArrayType1 != null && paramOrder1[i] >= p1.Length - 1)
+ c1 = paramArrayType1;
+ else
+ c1 = p1[paramOrder1[i]].ParameterType;
+
+ if (paramArrayType2 != null && paramOrder2[i] >= p2.Length - 1)
+ c2 = paramArrayType2;
+ else
+ c2 = p2[paramOrder2[i]].ParameterType;
+
+ if (c1 == c2) continue;
+
+ switch (FindMostSpecificType(c1, c2, types[i])) {
+ case 0: return 0;
+ case 1: p1Less = true; break;
+ case 2: p2Less = true; break;
+ }
+ }
+
+ // Two way p1Less and p2Less can be equal. All the arguments are the
+ // same they both equal false, otherwise there were things that both
+ // were the most specific type on....
+ if (p1Less == p2Less)
+ {
+ // if we cannot tell which is a better match based on parameter types (p1Less == p2Less),
+ // let's see which one has the most matches without using the params array (the longer one wins).
+ if (!p1Less && args != null)
+ {
+ if (p1.Length > p2.Length)
+ {
+ return 1;
+ }
+ else if (p2.Length > p1.Length)
+ {
+ return 2;
+ }
+ }
+
+ return 0;
+ }
+ else
+ {
+ return (p1Less == true) ? 1 : 2;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static int FindMostSpecificType(Type c1, Type c2, Type t)
+ {
+ // If the two types are exact move on...
+ if (c1 == c2)
+ return 0;
+
+ if (c1 == t)
+ return 1;
+
+ if (c2 == t)
+ return 2;
+
+ bool c1FromC2;
+ bool c2FromC1;
+
+ if (c1.IsByRef || c2.IsByRef)
+ {
+ if (c1.IsByRef && c2.IsByRef)
+ {
+ c1 = c1.GetElementType();
+ c2 = c2.GetElementType();
+ }
+ else if (c1.IsByRef)
+ {
+ if (c1.GetElementType() == c2)
+ return 2;
+
+ c1 = c1.GetElementType();
+ }
+ else
+ {
+ if (c2.GetElementType() == c1)
+ return 1;
+
+ c2 = c2.GetElementType();
+ }
+ }
+
+
+ if (c1.IsPrimitive && c2.IsPrimitive)
+ {
+ c1FromC2 = CanConvertPrimitive((RuntimeType)c2, (RuntimeType)c1);
+ c2FromC1 = CanConvertPrimitive((RuntimeType)c1, (RuntimeType)c2);
+ }
+ else
+ {
+ c1FromC2 = c1.IsAssignableFrom(c2);
+ c2FromC1 = c2.IsAssignableFrom(c1);
+ }
+
+ if (c1FromC2 == c2FromC1)
+ return 0;
+
+ if (c1FromC2)
+ {
+ return 2;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ private static int FindMostSpecificMethod(MethodBase m1, int[] paramOrder1, Type paramArrayType1,
+ MethodBase m2, int[] paramOrder2, Type paramArrayType2,
+ Type[] types, Object[] args)
+ {
+ // Find the most specific method based on the parameters.
+ int res = FindMostSpecific(m1.GetParametersNoCopy(), paramOrder1, paramArrayType1,
+ m2.GetParametersNoCopy(), paramOrder2, paramArrayType2, types, args);
+
+ // If the match was not ambigous then return the result.
+ if (res != 0)
+ return res;
+
+ // Check to see if the methods have the exact same name and signature.
+ if (CompareMethodSigAndName(m1, m2))
+ {
+ // Determine the depth of the declaring types for both methods.
+ int hierarchyDepth1 = GetHierarchyDepth(m1.DeclaringType);
+ int hierarchyDepth2 = GetHierarchyDepth(m2.DeclaringType);
+
+ // The most derived method is the most specific one.
+ if (hierarchyDepth1 == hierarchyDepth2)
+ {
+ return 0;
+ }
+ else if (hierarchyDepth1 < hierarchyDepth2)
+ {
+ return 2;
+ }
+ else
+ {
+ return 1;
+ }
+ }
+
+ // The match is ambigous.
+ return 0;
+ }
+
+ private static int FindMostSpecificField(FieldInfo cur1,FieldInfo cur2)
+ {
+ // Check to see if the fields have the same name.
+ if (cur1.Name == cur2.Name)
+ {
+ int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType);
+ int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType);
+
+ if (hierarchyDepth1 == hierarchyDepth2) {
+ Contract.Assert(cur1.IsStatic != cur2.IsStatic, "hierarchyDepth1 == hierarchyDepth2");
+ return 0;
+ }
+ else if (hierarchyDepth1 < hierarchyDepth2)
+ return 2;
+ else
+ return 1;
+ }
+
+ // The match is ambigous.
+ return 0;
+ }
+
+ private static int FindMostSpecificProperty(PropertyInfo cur1,PropertyInfo cur2)
+ {
+ // Check to see if the fields have the same name.
+ if (cur1.Name == cur2.Name)
+ {
+ int hierarchyDepth1 = GetHierarchyDepth(cur1.DeclaringType);
+ int hierarchyDepth2 = GetHierarchyDepth(cur2.DeclaringType);
+
+ if (hierarchyDepth1 == hierarchyDepth2) {
+ return 0;
+ }
+ else if (hierarchyDepth1 < hierarchyDepth2)
+ return 2;
+ else
+ return 1;
+ }
+
+ // The match is ambigous.
+ return 0;
+ }
+
+ internal static bool CompareMethodSigAndName(MethodBase m1, MethodBase m2)
+ {
+ ParameterInfo[] params1 = m1.GetParametersNoCopy();
+ ParameterInfo[] params2 = m2.GetParametersNoCopy();
+
+ if (params1.Length != params2.Length)
+ return false;
+
+ int numParams = params1.Length;
+ for (int i = 0; i < numParams; i++)
+ {
+ if (params1[i].ParameterType != params2[i].ParameterType)
+ return false;
+ }
+
+ return true;
+ }
+
+ internal static int GetHierarchyDepth(Type t)
+ {
+ int depth = 0;
+
+ Type currentType = t;
+ do
+ {
+ depth++;
+ currentType = currentType.BaseType;
+ } while (currentType != null);
+
+ return depth;
+ }
+
+ internal static MethodBase FindMostDerivedNewSlotMeth(MethodBase[] match, int cMatches)
+ {
+ int deepestHierarchy = 0;
+ MethodBase methWithDeepestHierarchy = null;
+
+ for (int i = 0; i < cMatches; i++)
+ {
+ // Calculate the depth of the hierarchy of the declaring type of the
+ // current method.
+ int currentHierarchyDepth = GetHierarchyDepth(match[i].DeclaringType);
+
+ // The two methods have the same name, signature, and hierarchy depth.
+ // This can only happen if at least one is vararg or generic.
+ if (currentHierarchyDepth == deepestHierarchy)
+ {
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ }
+
+ // Check to see if this method is on the most derived class.
+ if (currentHierarchyDepth > deepestHierarchy)
+ {
+ deepestHierarchy = currentHierarchyDepth;
+ methWithDeepestHierarchy = match[i];
+ }
+ }
+
+ return methWithDeepestHierarchy;
+ }
+
+ // CanConvertPrimitive
+ // This will determine if the source can be converted to the target type
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool CanConvertPrimitive(RuntimeType source,RuntimeType target);
+
+ // CanConvertPrimitiveObjectToType
+ // This method will determine if the primitive object can be converted
+ // to a type.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern bool CanConvertPrimitiveObjectToType(Object source,RuntimeType type);
+
+ // This method will sort the vars array into the mapping order stored
+ // in the paramOrder array.
+ private static void ReorderParams(int[] paramOrder,Object[] vars)
+ {
+ object[] varsCopy = new object[vars.Length];
+ for (int i = 0; i < vars.Length; i ++)
+ varsCopy[i] = vars[i];
+
+ for (int i = 0; i < vars.Length; i ++)
+ vars[i] = varsCopy[paramOrder[i]];
+ }
+
+ // This method will create the mapping between the Parameters and the underlying
+ // data based upon the names array. The names array is stored in the same order
+ // as the values and maps to the parameters of the method. We store the mapping
+ // from the parameters to the names in the paramOrder array. All parameters that
+ // don't have matching names are then stored in the array in order.
+ private static bool CreateParamOrder(int[] paramOrder,ParameterInfo[] pars,String[] names)
+ {
+ bool[] used = new bool[pars.Length];
+
+ // Mark which parameters have not been found in the names list
+ for (int i=0;i<pars.Length;i++)
+ paramOrder[i] = -1;
+ // Find the parameters with names.
+ for (int i=0;i<names.Length;i++) {
+ int j;
+ for (j=0;j<pars.Length;j++) {
+ if (names[i].Equals(pars[j].Name)) {
+ paramOrder[j] = i;
+ used[i] = true;
+ break;
+ }
+ }
+ // This is an error condition. The name was not found. This
+ // method must not match what we sent.
+ if (j == pars.Length)
+ return false;
+ }
+
+ // Now we fill in the holes with the parameters that are unused.
+ int pos = 0;
+ for (int i=0;i<pars.Length;i++) {
+ if (paramOrder[i] == -1) {
+ for (;pos<pars.Length;pos++) {
+ if (!used[pos]) {
+ paramOrder[i] = pos;
+ pos++;
+ break;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ internal class BinderState {
+ internal int[] m_argsMap;
+ internal int m_originalSize;
+ internal bool m_isParamArray;
+
+ internal BinderState(int[] argsMap, int originalSize, bool isParamArray) {
+ m_argsMap = argsMap;
+ m_originalSize = originalSize;
+ m_isParamArray = isParamArray;
+ }
+
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Delegate.cs b/src/mscorlib/src/System/Delegate.cs
new file mode 100644
index 0000000000..110555423c
--- /dev/null
+++ b/src/mscorlib/src/System/Delegate.cs
@@ -0,0 +1,754 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Runtime;
+ using System.Threading;
+ using System.Runtime.Serialization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Delegate : ICloneable, ISerializable
+ {
+ // _target is the object we will invoke on
+ [System.Security.SecurityCritical]
+ internal Object _target;
+
+ // MethodBase, either cached after first request or assigned from a DynamicMethod
+ // For open delegates to collectible types, this may be a LoaderAllocator object
+ [System.Security.SecurityCritical]
+ internal Object _methodBase;
+
+ // _methodPtr is a pointer to the method we will invoke
+ // It could be a small thunk if this is a static or UM call
+ [System.Security.SecurityCritical]
+ internal IntPtr _methodPtr;
+
+ // In the case of a static method passed to a delegate, this field stores
+ // whatever _methodPtr would have stored: and _methodPtr points to a
+ // small thunk which removes the "this" pointer before going on
+ // to _methodPtrAux.
+ [System.Security.SecurityCritical]
+ internal IntPtr _methodPtrAux;
+
+ // This constructor is called from the class generated by the
+ // compiler generated code
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected Delegate(Object target,String method)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ // This API existed in v1/v1.1 and only expected to create closed
+ // instance delegates. Constrain the call to BindToMethodName to
+ // such and don't allow relaxed signature matching (which could make
+ // the choice of target method ambiguous) for backwards
+ // compatibility. The name matching was case sensitive and we
+ // preserve that as well.
+ if (!BindToMethodName(target, (RuntimeType)target.GetType(), method,
+ DelegateBindingFlags.InstanceMethodOnly |
+ DelegateBindingFlags.ClosedDelegateOnly))
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+ }
+
+ // This constructor is called from a class to generate a
+ // delegate based upon a static method name and the Type object
+ // for the class defining the method.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected unsafe Delegate(Type target,String method)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+
+ if (target.IsGenericType && target.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
+
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ RuntimeType rtTarget = target as RuntimeType;
+ if (rtTarget == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
+
+ // This API existed in v1/v1.1 and only expected to create open
+ // static delegates. Constrain the call to BindToMethodName to such
+ // and don't allow relaxed signature matching (which could make the
+ // choice of target method ambiguous) for backwards compatibility.
+ // The name matching was case insensitive (no idea why this is
+ // different from the constructor above) and we preserve that as
+ // well.
+ BindToMethodName(null, rtTarget, method,
+ DelegateBindingFlags.StaticMethodOnly |
+ DelegateBindingFlags.OpenDelegateOnly |
+ DelegateBindingFlags.CaselessMatching);
+ }
+
+ // Protect the default constructor so you can't build a delegate
+ private Delegate()
+ {
+ }
+
+ public Object DynamicInvoke(params Object[] args)
+ {
+ // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
+ // But to maintain backward compatibility we can't switch to calling an
+ // internal overload of DynamicInvokeImpl that takes a stack mark.
+ // Fortunately the stack walker skips all the reflection invocation frames including this one.
+ // So this method will never be returned by the stack walker as the caller.
+ // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
+ return DynamicInvokeImpl(args);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected virtual object DynamicInvokeImpl(object[] args)
+ {
+ RuntimeMethodHandleInternal method = new RuntimeMethodHandleInternal(GetInvokeMethod());
+ RuntimeMethodInfo invoke = (RuntimeMethodInfo)RuntimeType.GetMethodBase((RuntimeType)this.GetType(), method);
+
+ return invoke.UnsafeInvoke(this, BindingFlags.Default, null, args, null);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool Equals(Object obj)
+ {
+ if (obj == null || !InternalEqualTypes(this, obj))
+ return false;
+
+ Delegate d = (Delegate) obj;
+
+ // do an optimistic check first. This is hopefully cheap enough to be worth
+ if (_target == d._target && _methodPtr == d._methodPtr && _methodPtrAux == d._methodPtrAux)
+ return true;
+
+ // even though the fields were not all equals the delegates may still match
+ // When target carries the delegate itself the 2 targets (delegates) may be different instances
+ // but the delegates are logically the same
+ // It may also happen that the method pointer was not jitted when creating one delegate and jitted in the other
+ // if that's the case the delegates may still be equals but we need to make a more complicated check
+
+ if (_methodPtrAux.IsNull())
+ {
+ if (!d._methodPtrAux.IsNull())
+ return false; // different delegate kind
+ // they are both closed over the first arg
+ if (_target != d._target)
+ return false;
+ // fall through method handle check
+ }
+ else
+ {
+ if (d._methodPtrAux.IsNull())
+ return false; // different delegate kind
+
+ // Ignore the target as it will be the delegate instance, though it may be a different one
+ /*
+ if (_methodPtr != d._methodPtr)
+ return false;
+ */
+
+ if (_methodPtrAux == d._methodPtrAux)
+ return true;
+ // fall through method handle check
+ }
+
+ // method ptrs don't match, go down long path
+ //
+ if (_methodBase == null || d._methodBase == null || !(_methodBase is MethodInfo) || !(d._methodBase is MethodInfo))
+ return Delegate.InternalEqualMethodHandles(this, d);
+ else
+ return _methodBase.Equals(d._methodBase);
+
+ }
+
+ public override int GetHashCode()
+ {
+ //
+ // this is not right in the face of a method being jitted in one delegate and not in another
+ // in that case the delegate is the same and Equals will return true but GetHashCode returns a
+ // different hashcode which is not true.
+ /*
+ if (_methodPtrAux.IsNull())
+ return unchecked((int)((long)this._methodPtr));
+ else
+ return unchecked((int)((long)this._methodPtrAux));
+ */
+ return GetType().GetHashCode();
+ }
+
+ public static Delegate Combine(Delegate a, Delegate b)
+ {
+ if ((Object)a == null) // cast to object for a more efficient test
+ return b;
+
+ return a.CombineImpl(b);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Delegate Combine(params Delegate[] delegates)
+ {
+ if (delegates == null || delegates.Length == 0)
+ return null;
+
+ Delegate d = delegates[0];
+ for (int i = 1; i < delegates.Length; i++)
+ d = Combine(d,delegates[i]);
+
+ return d;
+ }
+
+ public virtual Delegate[] GetInvocationList()
+ {
+ Delegate[] d = new Delegate[1];
+ d[0] = this;
+ return d;
+ }
+
+ // This routine will return the method
+ public MethodInfo Method
+ {
+ get
+ {
+ return GetMethodImpl();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected virtual MethodInfo GetMethodImpl()
+ {
+ if ((_methodBase == null) || !(_methodBase is MethodInfo))
+ {
+ IRuntimeMethodInfo method = FindMethodHandle();
+ RuntimeType declaringType = RuntimeMethodHandle.GetDeclaringType(method);
+ // need a proper declaring type instance method on a generic type
+ if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType))
+ {
+ bool isStatic = (RuntimeMethodHandle.GetAttributes(method) & MethodAttributes.Static) != (MethodAttributes)0;
+ if (!isStatic)
+ {
+ if (_methodPtrAux == (IntPtr)0)
+ {
+ // The target may be of a derived type that doesn't have visibility onto the
+ // target method. We don't want to call RuntimeType.GetMethodBase below with that
+ // or reflection can end up generating a MethodInfo where the ReflectedType cannot
+ // see the MethodInfo itself and that breaks an important invariant. But the
+ // target type could include important generic type information we need in order
+ // to work out what the exact instantiation of the method's declaring type is. So
+ // we'll walk up the inheritance chain (which will yield exactly instantiated
+ // types at each step) until we find the declaring type. Since the declaring type
+ // we get from the method is probably shared and those in the hierarchy we're
+ // walking won't be we compare using the generic type definition forms instead.
+ Type currentType = _target.GetType();
+ Type targetType = declaringType.GetGenericTypeDefinition();
+ while (currentType != null)
+ {
+ if (currentType.IsGenericType &&
+ currentType.GetGenericTypeDefinition() == targetType)
+ {
+ declaringType = currentType as RuntimeType;
+ break;
+ }
+ currentType = currentType.BaseType;
+ }
+
+ // RCWs don't need to be "strongly-typed" in which case we don't find a base type
+ // that matches the declaring type of the method. This is fine because interop needs
+ // to work with exact methods anyway so declaringType is never shared at this point.
+ BCLDebug.Assert(currentType != null || _target.GetType().IsCOMObject, "The class hierarchy should declare the method");
+ }
+ else
+ {
+ // it's an open one, need to fetch the first arg of the instantiation
+ MethodInfo invoke = this.GetType().GetMethod("Invoke");
+ declaringType = (RuntimeType)invoke.GetParameters()[0].ParameterType;
+ }
+ }
+ }
+ _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method);
+ }
+ return (MethodInfo)_methodBase;
+ }
+
+ public Object Target
+ {
+ get
+ {
+ return GetTarget();
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Delegate Remove(Delegate source, Delegate value)
+ {
+ if (source == null)
+ return null;
+
+ if (value == null)
+ return source;
+
+ if (!InternalEqualTypes(source, value))
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
+
+ return source.RemoveImpl(value);
+ }
+
+ public static Delegate RemoveAll(Delegate source, Delegate value)
+ {
+ Delegate newDelegate = null;
+
+ do
+ {
+ newDelegate = source;
+ source = Remove(source, value);
+ }
+ while (newDelegate != source);
+
+ return newDelegate;
+ }
+
+ protected virtual Delegate CombineImpl(Delegate d)
+ {
+ throw new MulticastNotSupportedException(Environment.GetResourceString("Multicast_Combine"));
+ }
+
+ protected virtual Delegate RemoveImpl(Delegate d)
+ {
+ return (d.Equals(this)) ? null : this;
+ }
+
+
+ public virtual Object Clone()
+ {
+ return MemberwiseClone();
+ }
+
+ // V1 API.
+ public static Delegate CreateDelegate(Type type, Object target, String method)
+ {
+ return CreateDelegate(type, target, method, false, true);
+ }
+
+ // V1 API.
+ public static Delegate CreateDelegate(Type type, Object target, String method, bool ignoreCase)
+ {
+ return CreateDelegate(type, target, method, ignoreCase, true);
+ }
+
+ // V1 API.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Delegate CreateDelegate(Type type, Object target, String method, bool ignoreCase, bool throwOnBindFailure)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");
+
+ Delegate d = InternalAlloc(rtType);
+ // This API existed in v1/v1.1 and only expected to create closed
+ // instance delegates. Constrain the call to BindToMethodName to such
+ // and don't allow relaxed signature matching (which could make the
+ // choice of target method ambiguous) for backwards compatibility.
+ // We never generate a closed over null delegate and this is
+ // actually enforced via the check on target above, but we pass
+ // NeverCloseOverNull anyway just for clarity.
+ if (!d.BindToMethodName(target, (RuntimeType)target.GetType(), method,
+ DelegateBindingFlags.InstanceMethodOnly |
+ DelegateBindingFlags.ClosedDelegateOnly |
+ DelegateBindingFlags.NeverCloseOverNull |
+ (ignoreCase ? DelegateBindingFlags.CaselessMatching : 0)))
+ {
+ if (throwOnBindFailure)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+ d = null;
+ }
+
+ return d;
+ }
+
+ // V1 API.
+ public static Delegate CreateDelegate(Type type, Type target, String method)
+ {
+ return CreateDelegate(type, target, method, false, true);
+ }
+
+ // V1 API.
+ public static Delegate CreateDelegate(Type type, Type target, String method, bool ignoreCase)
+ {
+ return CreateDelegate(type, target, method, ignoreCase, true);
+ }
+
+ // V1 API.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Delegate CreateDelegate(Type type, Type target, String method, bool ignoreCase, bool throwOnBindFailure)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (target.IsGenericType && target.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Arg_UnboundGenParam"), "target");
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = type as RuntimeType;
+ RuntimeType rtTarget = target as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
+ if (rtTarget == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "target");
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");
+
+ Delegate d = InternalAlloc(rtType);
+ // This API existed in v1/v1.1 and only expected to create open
+ // static delegates. Constrain the call to BindToMethodName to such
+ // and don't allow relaxed signature matching (which could make the
+ // choice of target method ambiguous) for backwards compatibility.
+ if (!d.BindToMethodName(null, rtTarget, method,
+ DelegateBindingFlags.StaticMethodOnly |
+ DelegateBindingFlags.OpenDelegateOnly |
+ (ignoreCase ? DelegateBindingFlags.CaselessMatching : 0)))
+ {
+ if (throwOnBindFailure)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+ d = null;
+ }
+
+ return d;
+ }
+
+ // V1 API.
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Delegate CreateDelegate(Type type, MethodInfo method, bool throwOnBindFailure)
+ {
+ // Validate the parameters.
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
+
+ RuntimeMethodInfo rmi = method as RuntimeMethodInfo;
+ if (rmi == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
+
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
+
+ // This API existed in v1/v1.1 and only expected to create closed
+ // instance delegates. Constrain the call to BindToMethodInfo to
+ // open delegates only for backwards compatibility. But we'll allow
+ // relaxed signature checking and open static delegates because
+ // there's no ambiguity there (the caller would have to explicitly
+ // pass us a static method or a method with a non-exact signature
+ // and the only change in behavior from v1.1 there is that we won't
+ // fail the call).
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Delegate d = CreateDelegateInternal(
+ rtType,
+ rmi,
+ null,
+ DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.RelaxedSignature,
+ ref stackMark);
+
+ if (d == null && throwOnBindFailure)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+
+ return d;
+ }
+
+ // V2 API.
+ public static Delegate CreateDelegate(Type type, Object firstArgument, MethodInfo method)
+ {
+ return CreateDelegate(type, firstArgument, method, true);
+ }
+
+ // V2 API.
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Delegate CreateDelegate(Type type, Object firstArgument, MethodInfo method, bool throwOnBindFailure)
+ {
+ // Validate the parameters.
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
+
+ RuntimeMethodInfo rmi = method as RuntimeMethodInfo;
+ if (rmi == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
+
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "type");
+
+ // This API is new in Whidbey and allows the full range of delegate
+ // flexability (open or closed delegates binding to static or
+ // instance methods with relaxed signature checking. The delegate
+ // can also be closed over null. There's no ambiguity with all these
+ // options since the caller is providing us a specific MethodInfo.
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Delegate d = CreateDelegateInternal(
+ rtType,
+ rmi,
+ firstArgument,
+ DelegateBindingFlags.RelaxedSignature,
+ ref stackMark);
+
+ if (d == null && throwOnBindFailure)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+
+ return d;
+ }
+
+ public static bool operator ==(Delegate d1, Delegate d2)
+ {
+ if ((Object)d1 == null)
+ return (Object)d2 == null;
+
+ return d1.Equals(d2);
+ }
+
+ public static bool operator != (Delegate d1, Delegate d2)
+ {
+ if ((Object)d1 == null)
+ return (Object)d2 != null;
+
+ return !d1.Equals(d2);
+ }
+
+ //
+ // Implementation of ISerializable
+ //
+
+ [System.Security.SecurityCritical]
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException();
+ }
+ //
+ // internal implementation details (FCALLS and utilities)
+ //
+
+ // V2 internal API.
+ // This is Critical because it skips the security check when creating the delegate.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static Delegate CreateDelegateNoSecurityCheck(Type type, Object target, RuntimeMethodHandle method)
+ {
+ // Validate the parameters.
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ if (method.IsNullHandle())
+ throw new ArgumentNullException("method");
+
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "type");
+
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");
+
+ // Initialize the method...
+ Delegate d = InternalAlloc(rtType);
+ // This is a new internal API added in Whidbey. Currently it's only
+ // used by the dynamic method code to generate a wrapper delegate.
+ // Allow flexible binding options since the target method is
+ // unambiguously provided to us.
+
+ if (!d.BindToMethodInfo(target,
+ method.GetMethodInfo(),
+ RuntimeMethodHandle.GetDeclaringType(method.GetMethodInfo()),
+ DelegateBindingFlags.RelaxedSignature | DelegateBindingFlags.SkipSecurityChecks))
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+ return d;
+ }
+
+ // Caution: this method is intended for deserialization only, no security checks are performed.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Delegate CreateDelegateNoSecurityCheck(RuntimeType type, Object firstArgument, MethodInfo method)
+ {
+ // Validate the parameters.
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (method == null)
+ throw new ArgumentNullException("method");
+
+ Contract.EndContractBlock();
+
+ RuntimeMethodInfo rtMethod = method as RuntimeMethodInfo;
+ if (rtMethod == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "method");
+
+ if (!type.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");
+
+ // This API is used by the formatters when deserializing a delegate.
+ // They pass us the specific target method (that was already the
+ // target in a valid delegate) so we should bind with the most
+ // relaxed rules available (the result will never be ambiguous, it
+ // just increases the chance of success with minor (compatible)
+ // signature changes). We explicitly skip security checks here --
+ // we're not really constructing a delegate, we're cloning an
+ // existing instance which already passed its checks.
+ Delegate d = UnsafeCreateDelegate(type, rtMethod, firstArgument,
+ DelegateBindingFlags.SkipSecurityChecks |
+ DelegateBindingFlags.RelaxedSignature);
+
+ if (d == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+
+ return d;
+ }
+
+ // V1 API.
+ public static Delegate CreateDelegate(Type type, MethodInfo method)
+ {
+ return CreateDelegate(type, method, true);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static Delegate CreateDelegateInternal(RuntimeType rtType, RuntimeMethodInfo rtMethod, Object firstArgument, DelegateBindingFlags flags, ref StackCrawlMark stackMark)
+ {
+ Contract.Assert((flags & DelegateBindingFlags.SkipSecurityChecks) == 0);
+
+#if FEATURE_APPX
+ bool nonW8PMethod = (rtMethod.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0;
+ bool nonW8PType = (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0;
+ if (nonW8PMethod || nonW8PType)
+ {
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(
+ Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext",
+ nonW8PMethod ? rtMethod.FullName : rtType.FullName));
+ }
+#endif
+
+ return UnsafeCreateDelegate(rtType, rtMethod, firstArgument, flags);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static Delegate UnsafeCreateDelegate(RuntimeType rtType, RuntimeMethodInfo rtMethod, Object firstArgument, DelegateBindingFlags flags)
+ {
+ Delegate d = InternalAlloc(rtType);
+
+ if (d.BindToMethodInfo(firstArgument, rtMethod, rtMethod.GetDeclaringTypeInternal(), flags))
+ return d;
+ else
+ return null;
+ }
+
+ //
+ // internal implementation details (FCALLS and utilities)
+ //
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool BindToMethodName(Object target, RuntimeType methodType, String method, DelegateBindingFlags flags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool BindToMethodInfo(Object target, IRuntimeMethodInfo method, RuntimeType methodType, DelegateBindingFlags flags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static MulticastDelegate InternalAlloc(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static MulticastDelegate InternalAllocLike(Delegate d);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool InternalEqualTypes(object a, object b);
+
+ // Used by the ctor. Do not call directly.
+ // The name of this function will appear in managed stacktraces as delegate constructor.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void DelegateConstruct(Object target, IntPtr slot);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetMulticastInvoke();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetInvokeMethod();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IRuntimeMethodInfo FindMethodHandle();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool InternalEqualMethodHandles(Delegate left, Delegate right);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr AdjustTarget(Object target, IntPtr methodPtr);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetCallStub(IntPtr methodPtr);
+
+ [System.Security.SecuritySafeCritical]
+ internal virtual Object GetTarget()
+ {
+ return (_methodPtrAux.IsNull()) ? _target : null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool CompareUnmanagedFunctionPtrs (Delegate d1, Delegate d2);
+ }
+
+ // These flags effect the way BindToMethodInfo and BindToMethodName are allowed to bind a delegate to a target method. Their
+ // values must be kept in sync with the definition in vm\comdelegate.h.
+ internal enum DelegateBindingFlags
+ {
+ StaticMethodOnly = 0x00000001, // Can only bind to static target methods
+ InstanceMethodOnly = 0x00000002, // Can only bind to instance (including virtual) methods
+ OpenDelegateOnly = 0x00000004, // Only allow the creation of delegates open over the 1st argument
+ ClosedDelegateOnly = 0x00000008, // Only allow the creation of delegates closed over the 1st argument
+ NeverCloseOverNull = 0x00000010, // A null target will never been considered as a possible null 1st argument
+ CaselessMatching = 0x00000020, // Use case insensitive lookup for methods matched by name
+ SkipSecurityChecks = 0x00000040, // Skip security checks (visibility, link demand etc.)
+ RelaxedSignature = 0x00000080, // Allow relaxed signature matching (co/contra variance)
+ }
+}
diff --git a/src/mscorlib/src/System/DelegateSerializationHolder.cs b/src/mscorlib/src/System/DelegateSerializationHolder.cs
new file mode 100644
index 0000000000..a6280333db
--- /dev/null
+++ b/src/mscorlib/src/System/DelegateSerializationHolder.cs
@@ -0,0 +1,299 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Reflection;
+using System.Runtime.Remoting;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ [Serializable]
+ internal sealed class DelegateSerializationHolder : IObjectReference, ISerializable
+ {
+ #region Static Members
+ [System.Security.SecurityCritical] // auto-generated
+ internal static DelegateEntry GetDelegateSerializationInfo(
+ SerializationInfo info, Type delegateType, Object target, MethodInfo method, int targetIndex)
+ {
+ // Used for MulticastDelegate
+
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ if (!method.IsPublic || (method.DeclaringType != null && !method.DeclaringType.IsVisible))
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+
+ Type c = delegateType.BaseType;
+
+ if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"),"type");
+
+ if (method.DeclaringType == null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalMethodSerialization"));
+
+ DelegateEntry de = new DelegateEntry(delegateType.FullName, delegateType.Module.Assembly.FullName, target,
+ method.ReflectedType.Module.Assembly.FullName, method.ReflectedType.FullName, method.Name);
+
+ if (info.MemberCount == 0)
+ {
+ info.SetType(typeof(DelegateSerializationHolder));
+ info.AddValue("Delegate",de,typeof(DelegateEntry));
+ }
+
+ // target can be an object so it needs to be added to the info, or else a fixup is needed
+ // when deserializing, and the fixup will occur too late. If it is added directly to the
+ // info then the rules of deserialization will guarantee that it will be available when
+ // needed
+
+ if (target != null)
+ {
+ String targetName = "target" + targetIndex;
+ info.AddValue(targetName, de.target);
+ de.target = targetName;
+ }
+
+ // Due to a number of additions (delegate signature binding relaxation, delegates with open this or closed over the
+ // first parameter and delegates over generic methods) we need to send a deal more information than previously. We can
+ // get this by serializing the target MethodInfo. We still need to send the same information as before though (the
+ // DelegateEntry above) for backwards compatibility. And we want to send the MethodInfo (which is serialized via an
+ // ISerializable holder) as a top-level child of the info for the same reason as the target above -- we wouldn't have an
+ // order of deserialization guarantee otherwise.
+ String methodInfoName = "method" + targetIndex;
+ info.AddValue(methodInfoName, method);
+
+ return de;
+ }
+ #endregion
+
+ #region Definitions
+ [Serializable]
+ internal class DelegateEntry
+ {
+ #region Internal Data Members
+ internal String type;
+ internal String assembly;
+ internal Object target;
+ internal String targetTypeAssembly;
+ internal String targetTypeName;
+ internal String methodName;
+ internal DelegateEntry delegateEntry;
+ #endregion
+
+ #region Constructor
+ internal DelegateEntry(
+ String type, String assembly, Object target, String targetTypeAssembly, String targetTypeName, String methodName)
+ {
+ this.type = type;
+ this.assembly = assembly;
+ this.target = target;
+ this.targetTypeAssembly = targetTypeAssembly;
+ this.targetTypeName = targetTypeName;
+ this.methodName = methodName;
+ }
+ #endregion
+
+ #region Internal Members
+ internal DelegateEntry Entry
+ {
+ get { return delegateEntry; }
+ set { delegateEntry = value; }
+ }
+ #endregion
+ }
+
+ #endregion
+
+ #region Private Data Members
+ private DelegateEntry m_delegateEntry;
+ private MethodInfo[] m_methods;
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ private DelegateSerializationHolder(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ bool bNewWire = true;
+
+ try
+ {
+ m_delegateEntry = (DelegateEntry)info.GetValue("Delegate", typeof(DelegateEntry));
+ }
+ catch
+ {
+ // Old wire format
+ m_delegateEntry = OldDelegateWireFormat(info, context);
+ bNewWire = false;
+ }
+
+ if (bNewWire)
+ {
+ // retrieve the targets
+ DelegateEntry deiter = m_delegateEntry;
+ int count = 0;
+ while (deiter != null)
+ {
+ if (deiter.target != null)
+ {
+ string stringTarget = deiter.target as string; //need test to pass older wire format
+ if (stringTarget != null)
+ deiter.target = info.GetValue(stringTarget, typeof(Object));
+ }
+ count++;
+ deiter = deiter.delegateEntry;
+ }
+
+ // If the sender is as recent as us they'll have provided MethodInfos for each delegate. Look for these and pack
+ // them into an ordered array if present.
+ MethodInfo[] methods = new MethodInfo[count];
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ String methodInfoName = "method" + i;
+ methods[i] = (MethodInfo)info.GetValueNoThrow(methodInfoName, typeof(MethodInfo));
+ if (methods[i] == null)
+ break;
+ }
+
+ // If we got the info then make the array available for deserialization.
+ if (i == count)
+ m_methods = methods;
+ }
+ }
+ #endregion
+
+ #region Private Members
+ private void ThrowInsufficientState(string field)
+ {
+ throw new SerializationException(
+ Environment.GetResourceString("Serialization_InsufficientDeserializationState", field));
+ }
+
+ private DelegateEntry OldDelegateWireFormat(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ String delegateType = info.GetString("DelegateType");
+ String delegateAssembly = info.GetString("DelegateAssembly");
+ Object target = info.GetValue("Target", typeof(Object));
+ String targetTypeAssembly = info.GetString("TargetTypeAssembly");
+ String targetTypeName = info.GetString("TargetTypeName");
+ String methodName = info.GetString("MethodName");
+
+ return new DelegateEntry(delegateType, delegateAssembly, target, targetTypeAssembly, targetTypeName, methodName);
+ }
+
+ [System.Security.SecurityCritical]
+ private Delegate GetDelegate(DelegateEntry de, int index)
+ {
+ Delegate d;
+
+ try
+ {
+ if (de.methodName == null || de.methodName.Length == 0)
+ ThrowInsufficientState("MethodName");
+
+ if (de.assembly == null || de.assembly.Length == 0)
+ ThrowInsufficientState("DelegateAssembly");
+
+ if (de.targetTypeName == null || de.targetTypeName.Length == 0)
+ ThrowInsufficientState("TargetTypeName");
+
+ // We cannot use Type.GetType directly, because of AppCompat - assembly names starting with '[' would fail to load.
+ RuntimeType type = (RuntimeType)Assembly.GetType_Compat(de.assembly, de.type);
+ RuntimeType targetType = (RuntimeType)Assembly.GetType_Compat(de.targetTypeAssembly, de.targetTypeName);
+
+ // If we received the new style delegate encoding we already have the target MethodInfo in hand.
+ if (m_methods != null)
+ {
+#if FEATURE_REMOTING
+ Object target = de.target != null ? RemotingServices.CheckCast(de.target, targetType) : null;
+#else
+ if(de.target != null && !targetType.IsInstanceOfType(de.target))
+ throw new InvalidCastException();
+ Object target=de.target;
+#endif
+ d = Delegate.CreateDelegateNoSecurityCheck(type, target, m_methods[index]);
+ }
+ else
+ {
+ if (de.target != null)
+#if FEATURE_REMOTING
+ d = Delegate.CreateDelegate(type, RemotingServices.CheckCast(de.target, targetType), de.methodName);
+#else
+ {
+ if(!targetType.IsInstanceOfType(de.target))
+ throw new InvalidCastException();
+ d = Delegate.CreateDelegate(type, de.target, de.methodName);
+ }
+#endif
+ else
+ d = Delegate.CreateDelegate(type, targetType, de.methodName);
+ }
+
+ if ((d.Method != null && !d.Method.IsPublic) || (d.Method.DeclaringType != null && !d.Method.DeclaringType.IsVisible))
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+ }
+ catch (Exception e)
+ {
+ if (e is SerializationException)
+ throw e;
+
+ throw new SerializationException(e.Message, e);
+ }
+
+ return d;
+ }
+ #endregion
+
+ #region IObjectReference
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ int count = 0;
+ for (DelegateEntry de = m_delegateEntry; de != null; de = de.Entry)
+ count++;
+
+ int maxindex = count - 1;
+
+ if (count == 1)
+ {
+ return GetDelegate(m_delegateEntry, 0);
+ }
+ else
+ {
+ object[] invocationList = new object[count];
+
+ for (DelegateEntry de = m_delegateEntry; de != null; de = de.Entry)
+ {
+ // Be careful to match the index we pass to GetDelegate (used to look up extra information for each delegate) to
+ // the order we process the entries: we're actually looking at them in reverse order.
+ --count;
+ invocationList[count] = GetDelegate(de, maxindex - count);
+ }
+ return ((MulticastDelegate)invocationList[0]).NewMulticastDelegate(invocationList, invocationList.Length);
+ }
+ }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DelegateSerHolderSerial"));
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Assert.cs b/src/mscorlib/src/System/Diagnostics/Assert.cs
new file mode 100644
index 0000000000..40efe753af
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Assert.cs
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+ using System;
+ using System.Security.Permissions;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+ // Class which handles code asserts. Asserts are used to explicitly protect
+ // assumptions made in the code. In general if an assert fails, it indicates
+ // a program bug so is immediately called to the attention of the user.
+ // Only static data members, does not need to be marked with the serializable attribute
+ internal static class Assert
+ {
+ internal const int COR_E_FAILFAST = unchecked((int) 0x80131623);
+ private static AssertFilter Filter;
+
+ static Assert()
+ {
+ Filter = new DefaultFilter();
+ }
+
+ // Called when an assertion is being made.
+ //
+ internal static void Check(bool condition, String conditionString, String message)
+ {
+ if (!condition)
+ {
+ Fail (conditionString, message, null, COR_E_FAILFAST);
+ }
+ }
+
+ internal static void Check(bool condition, String conditionString, String message, int exitCode)
+ {
+ if (!condition)
+ {
+ Fail(conditionString, message, null, exitCode);
+ }
+ }
+
+ internal static void Fail(String conditionString, String message)
+ {
+ Fail(conditionString, message, null, COR_E_FAILFAST);
+ }
+
+ internal static void Fail(String conditionString, String message, String windowTitle, int exitCode)
+ {
+ Fail(conditionString, message, windowTitle, exitCode, StackTrace.TraceFormat.Normal, 0);
+ }
+
+ internal static void Fail(String conditionString, String message, int exitCode, StackTrace.TraceFormat stackTraceFormat)
+ {
+ Fail(conditionString, message, null, exitCode, stackTraceFormat, 0);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void Fail(String conditionString, String message, String windowTitle, int exitCode, StackTrace.TraceFormat stackTraceFormat, int numStackFramesToSkip)
+ {
+ // get the stacktrace
+ StackTrace st = new StackTrace(numStackFramesToSkip, true);
+
+ AssertFilters iResult = Filter.AssertFailure (conditionString, message, st, stackTraceFormat, windowTitle);
+
+ if (iResult == AssertFilters.FailDebug)
+ {
+ if (Debugger.IsAttached == true)
+ Debugger.Break();
+ else
+ {
+ if (Debugger.Launch() == false)
+ {
+ throw new InvalidOperationException(
+ Environment.GetResourceString("InvalidOperation_DebuggerLaunchFailed"));
+ }
+ }
+ }
+ else if (iResult == AssertFilters.FailTerminate)
+ {
+#if FEATURE_CORECLR
+ // We want to exit the Silverlight application, after displaying a message.
+ // Our best known way to emulate this is to exit the process with a known
+ // error code. Jolt may not be prepared for an appdomain to be unloaded.
+ Environment._Exit(exitCode);
+#else
+ // This assert dialog will be common for code contract failures. If a code contract failure
+ // occurs on an end user machine, we believe the right experience is to do a FailFast, which
+ // will report this error via Watson, so someone could theoretically fix the bug.
+ // However, in CLR v4, Environment.FailFast when a debugger is attached gives you an MDA
+ // saying you've hit a bug in the runtime or unsafe managed code, and this is most likely caused
+ // by heap corruption or a stack imbalance from COM Interop or P/Invoke. That extremely
+ // misleading error isn't right, and we can temporarily work around this by using Environment.Exit
+ // if a debugger is attached. The right fix is to plumb FailFast correctly through our native
+ // Watson code, adding in a TypeOfReportedError for fatal managed errors.
+ if (Debugger.IsAttached)
+ Environment._Exit(exitCode);
+ else
+ Environment.FailFast(message, unchecked((uint) exitCode));
+#endif
+ }
+ }
+
+ // Called when an assert happens.
+ // windowTitle can be null.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int ShowDefaultAssertDialog(String conditionString, String message, String stackTrace, String windowTitle);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/AssertFilter.cs b/src/mscorlib/src/System/Diagnostics/AssertFilter.cs
new file mode 100644
index 0000000000..b441fc326b
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/AssertFilter.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+
+
+ using System;
+ using System.Runtime.Versioning;
+ // A Filter is used to decide whether an assert failure
+ // should terminate the program (or invoke the debugger).
+ // Typically this is done by popping up a dialog & asking the user.
+ //
+ // The default filter brings up a simple Win32 dialog with 3 buttons.
+
+ [Serializable]
+ abstract internal class AssertFilter
+ {
+
+ // Called when an assert fails. This should be overridden with logic which
+ // determines whether the program should terminate or not. Typically this
+ // is done by asking the user.
+ //
+ // The windowTitle can be null.
+ abstract public AssertFilters AssertFailure(String condition, String message,
+ StackTrace location, StackTrace.TraceFormat stackTraceFormat, String windowTitle);
+
+ }
+ // No data, does not need to be marked with the serializable attribute
+ internal class DefaultFilter : AssertFilter
+ {
+ internal DefaultFilter()
+ {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override AssertFilters AssertFailure(String condition, String message,
+ StackTrace location, StackTrace.TraceFormat stackTraceFormat,
+ String windowTitle)
+
+ {
+ return (AssertFilters) Assert.ShowDefaultAssertDialog (condition, message, location.ToString(stackTraceFormat), windowTitle);
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/AssertFilters.cs b/src/mscorlib/src/System/Diagnostics/AssertFilters.cs
new file mode 100644
index 0000000000..13131d4819
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/AssertFilters.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+
+ /*
+ * FailDebug indicates the debugger should be invoked
+ * FailIgnore indicates the failure should be ignored & the
+ * program continued
+ * FailTerminate indicates that the program should be terminated
+ * FailContinue indicates that no decision is made -
+ * the previous Filter should be invoked
+ */
+ using System;
+ [Serializable]
+ internal enum AssertFilters
+ {
+ FailDebug = 0,
+ FailIgnore = 1,
+ FailTerminate = 2,
+ FailContinueFilter = 3,
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs b/src/mscorlib/src/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs
new file mode 100644
index 0000000000..fb26fcc4ab
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/CodeAnalysis/SuppressMessageAttribute.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** An attribute to suppress violation messages/warnings
+** by static code analysis tools.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.Diagnostics.CodeAnalysis
+{
+
+ [AttributeUsage(
+ AttributeTargets.All,
+ Inherited = false,
+ AllowMultiple = true
+ )
+ ]
+ [Conditional("CODE_ANALYSIS")]
+ public sealed class SuppressMessageAttribute : Attribute
+ {
+ private string category;
+ private string justification;
+ private string checkId;
+ private string scope;
+ private string target;
+ private string messageId;
+
+ public SuppressMessageAttribute(string category, string checkId)
+ {
+ this.category = category;
+ this.checkId = checkId;
+ }
+
+ public string Category
+ {
+ get { return category; }
+ }
+
+ public string CheckId
+ {
+ get { return checkId; }
+ }
+
+ public string Scope
+ {
+ get { return scope; }
+ set { scope = value; }
+ }
+
+ public string Target
+ {
+ get { return target; }
+ set { target = value; }
+ }
+
+ public string MessageId
+ {
+ get { return messageId; }
+ set { messageId = value; }
+ }
+
+ public string Justification
+ {
+ get { return justification; }
+ set { justification = value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/ConditionalAttribute.cs b/src/mscorlib/src/System/Diagnostics/ConditionalAttribute.cs
new file mode 100644
index 0000000000..b20931f9c3
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/ConditionalAttribute.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Diagnostics {
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple=true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ConditionalAttribute : Attribute
+ {
+ public ConditionalAttribute(String conditionString)
+ {
+ m_conditionString = conditionString;
+ }
+
+ public String ConditionString {
+ get {
+ return m_conditionString;
+ }
+ }
+
+ private String m_conditionString;
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Contracts/Contracts.cs b/src/mscorlib/src/System/Diagnostics/Contracts/Contracts.cs
new file mode 100644
index 0000000000..e002e6a5c1
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Contracts/Contracts.cs
@@ -0,0 +1,1017 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The contract class allows for expressing preconditions,
+** postconditions, and object invariants about methods in source
+** code for runtime checking & static analysis.
+**
+** Two classes (Contract and ContractHelper) are split into partial classes
+** in order to share the public front for multiple platforms (this file)
+** while providing separate implementation details for each platform.
+**
+===========================================================*/
+#define DEBUG // The behavior of this contract library should be consistent regardless of build type.
+
+#if SILVERLIGHT
+#define FEATURE_UNTRUSTED_CALLERS
+
+#elif REDHAWK_RUNTIME
+
+#elif BARTOK_RUNTIME
+
+#else // CLR
+#define FEATURE_UNTRUSTED_CALLERS
+#define FEATURE_RELIABILITY_CONTRACTS
+#define FEATURE_SERIALIZATION
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+
+#if FEATURE_RELIABILITY_CONTRACTS
+using System.Runtime.ConstrainedExecution;
+#endif
+#if FEATURE_UNTRUSTED_CALLERS
+using System.Security;
+using System.Security.Permissions;
+#endif
+
+namespace System.Diagnostics.Contracts {
+
+ #region Attributes
+
+ /// <summary>
+ /// Methods and classes marked with this attribute can be used within calls to Contract methods. Such methods not make any visible state changes.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Delegate | AttributeTargets.Class | AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public sealed class PureAttribute : Attribute
+ {
+ }
+
+ /// <summary>
+ /// Types marked with this attribute specify that a separate type contains the contracts for this type.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [Conditional("DEBUG")]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
+ public sealed class ContractClassAttribute : Attribute
+ {
+ private Type _typeWithContracts;
+
+ public ContractClassAttribute(Type typeContainingContracts)
+ {
+ _typeWithContracts = typeContainingContracts;
+ }
+
+ public Type TypeContainingContracts {
+ get { return _typeWithContracts; }
+ }
+ }
+
+ /// <summary>
+ /// Types marked with this attribute specify that they are a contract for the type that is the argument of the constructor.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+ public sealed class ContractClassForAttribute : Attribute
+ {
+ private Type _typeIAmAContractFor;
+
+ public ContractClassForAttribute(Type typeContractsAreFor)
+ {
+ _typeIAmAContractFor = typeContractsAreFor;
+ }
+
+ public Type TypeContractsAreFor {
+ get { return _typeIAmAContractFor; }
+ }
+ }
+
+ /// <summary>
+ /// This attribute is used to mark a method as being the invariant
+ /// method for a class. The method can have any name, but it must
+ /// return "void" and take no parameters. The body of the method
+ /// must consist solely of one or more calls to the method
+ /// Contract.Invariant. A suggested name for the method is
+ /// "ObjectInvariant".
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ public sealed class ContractInvariantMethodAttribute : Attribute
+ {
+ }
+
+ /// <summary>
+ /// Attribute that specifies that an assembly is a reference assembly with contracts.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public sealed class ContractReferenceAssemblyAttribute : Attribute
+ {
+ }
+
+ /// <summary>
+ /// Methods (and properties) marked with this attribute can be used within calls to Contract methods, but have no runtime behavior associated with them.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
+ public sealed class ContractRuntimeIgnoredAttribute : Attribute
+ {
+ }
+
+ /*
+ [Serializable]
+ internal enum Mutability
+ {
+ Immutable, // read-only after construction, except for lazy initialization & caches
+ // Do we need a "deeply immutable" value?
+ Mutable,
+ HasInitializationPhase, // read-only after some point.
+ // Do we need a value for mutable types with read-only wrapper subclasses?
+ }
+
+ // Note: This hasn't been thought through in any depth yet. Consider it experimental.
+ // We should replace this with Joe's concepts.
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
+ [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "Thank you very much, but we like the names we've defined for the accessors")]
+ internal sealed class MutabilityAttribute : Attribute
+ {
+ private Mutability _mutabilityMarker;
+
+ public MutabilityAttribute(Mutability mutabilityMarker)
+ {
+ _mutabilityMarker = mutabilityMarker;
+ }
+
+ public Mutability Mutability {
+ get { return _mutabilityMarker; }
+ }
+ }
+ */
+
+ /// <summary>
+ /// Instructs downstream tools whether to assume the correctness of this assembly, type or member without performing any verification or not.
+ /// Can use [ContractVerification(false)] to explicitly mark assembly, type or member as one to *not* have verification performed on it.
+ /// Most specific element found (member, type, then assembly) takes precedence.
+ /// (That is useful if downstream tools allow a user to decide which polarity is the default, unmarked case.)
+ /// </summary>
+ /// <remarks>
+ /// Apply this attribute to a type to apply to all members of the type, including nested types.
+ /// Apply this attribute to an assembly to apply to all types and members of the assembly.
+ /// Apply this attribute to a property to apply to both the getter and setter.
+ /// </remarks>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property)]
+ public sealed class ContractVerificationAttribute : Attribute
+ {
+ private bool _value;
+
+ public ContractVerificationAttribute(bool value) { _value = value; }
+
+ public bool Value {
+ get { return _value; }
+ }
+ }
+
+ /// <summary>
+ /// Allows a field f to be used in the method contracts for a method m when f has less visibility than m.
+ /// For instance, if the method is public, but the field is private.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+ [AttributeUsage(AttributeTargets.Field)]
+ [SuppressMessage("Microsoft.Design", "CA1019:DefineAccessorsForAttributeArguments", Justification = "Thank you very much, but we like the names we've defined for the accessors")]
+ public sealed class ContractPublicPropertyNameAttribute : Attribute
+ {
+ private String _publicName;
+
+ public ContractPublicPropertyNameAttribute(String name)
+ {
+ _publicName = name;
+ }
+
+ public String Name {
+ get { return _publicName; }
+ }
+ }
+
+ /// <summary>
+ /// Enables factoring legacy if-then-throw into separate methods for reuse and full control over
+ /// thrown exception and arguments
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+ [Conditional("CONTRACTS_FULL")]
+ public sealed class ContractArgumentValidatorAttribute : Attribute
+ {
+ }
+
+ /// <summary>
+ /// Enables writing abbreviations for contracts that get copied to other methods
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
+ [Conditional("CONTRACTS_FULL")]
+ public sealed class ContractAbbreviatorAttribute : Attribute
+ {
+ }
+
+ /// <summary>
+ /// Allows setting contract and tool options at assembly, type, or method granularity.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)]
+ [Conditional("CONTRACTS_FULL")]
+ public sealed class ContractOptionAttribute : Attribute
+ {
+ private String _category;
+ private String _setting;
+ private bool _enabled;
+ private String _value;
+
+ public ContractOptionAttribute(String category, String setting, bool enabled)
+ {
+ _category = category;
+ _setting = setting;
+ _enabled = enabled;
+ }
+
+ public ContractOptionAttribute(String category, String setting, String value)
+ {
+ _category = category;
+ _setting = setting;
+ _value = value;
+ }
+
+ public String Category {
+ get { return _category; }
+ }
+
+ public String Setting {
+ get { return _setting; }
+ }
+
+ public bool Enabled {
+ get { return _enabled; }
+ }
+
+ public String Value {
+ get { return _value; }
+ }
+ }
+
+ #endregion Attributes
+
+ /// <summary>
+ /// Contains static methods for representing program contracts such as preconditions, postconditions, and invariants.
+ /// </summary>
+ /// <remarks>
+ /// WARNING: A binary rewriter must be used to insert runtime enforcement of these contracts.
+ /// Otherwise some contracts like Ensures can only be checked statically and will not throw exceptions during runtime when contracts are violated.
+ /// Please note this class uses conditional compilation to help avoid easy mistakes. Defining the preprocessor
+ /// symbol CONTRACTS_PRECONDITIONS will include all preconditions expressed using Contract.Requires in your
+ /// build. The symbol CONTRACTS_FULL will include postconditions and object invariants, and requires the binary rewriter.
+ /// </remarks>
+ public static partial class Contract
+ {
+ #region User Methods
+
+ #region Assume
+
+ /// <summary>
+ /// Instructs code analysis tools to assume the expression <paramref name="condition"/> is true even if it can not be statically proven to always be true.
+ /// </summary>
+ /// <param name="condition">Expression to assume will always be true.</param>
+ /// <remarks>
+ /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
+ /// </remarks>
+ [Pure]
+ [Conditional("DEBUG")]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Assume(bool condition)
+ {
+ if (!condition) {
+ ReportFailure(ContractFailureKind.Assume, null, null, null);
+ }
+ }
+
+ /// <summary>
+ /// Instructs code analysis tools to assume the expression <paramref name="condition"/> is true even if it can not be statically proven to always be true.
+ /// </summary>
+ /// <param name="condition">Expression to assume will always be true.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// At runtime this is equivalent to an <seealso cref="System.Diagnostics.Contracts.Contract.Assert(bool)"/>.
+ /// </remarks>
+ [Pure]
+ [Conditional("DEBUG")]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Assume(bool condition, String userMessage)
+ {
+ if (!condition) {
+ ReportFailure(ContractFailureKind.Assume, userMessage, null, null);
+ }
+ }
+
+ #endregion Assume
+
+ #region Assert
+
+ /// <summary>
+ /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
+ /// </summary>
+ /// <param name="condition">Expression to check to always be true.</param>
+ [Pure]
+ [Conditional("DEBUG")]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Assert(bool condition)
+ {
+ if (!condition)
+ ReportFailure(ContractFailureKind.Assert, null, null, null);
+ }
+
+ /// <summary>
+ /// In debug builds, perform a runtime check that <paramref name="condition"/> is true.
+ /// </summary>
+ /// <param name="condition">Expression to check to always be true.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ [Pure]
+ [Conditional("DEBUG")]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Assert(bool condition, String userMessage)
+ {
+ if (!condition)
+ ReportFailure(ContractFailureKind.Assert, userMessage, null, null);
+ }
+
+ #endregion Assert
+
+ #region Requires
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// Use this form when backward compatibility does not force you to throw a particular exception.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Requires(bool condition)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// Use this form when backward compatibility does not force you to throw a particular exception.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Requires(bool condition, String userMessage)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// Use this form when you want to throw a particular exception.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "condition")]
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Requires<TException>(bool condition) where TException : Exception
+ {
+ AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> must be true before the enclosing method or property is invoked.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// Use this form when you want to throw a particular exception.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "userMessage")]
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "condition")]
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Requires<TException>(bool condition, String userMessage) where TException : Exception
+ {
+ AssertMustUseRewriter(ContractFailureKind.Precondition, "Requires<TException>");
+ }
+
+ #endregion Requires
+
+ #region Ensures
+
+ /// <summary>
+ /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this postcondition.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Ensures(bool condition)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
+ }
+
+ /// <summary>
+ /// Specifies a public contract such that the expression <paramref name="condition"/> will be true when the enclosing method or property returns normally.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference members at least as visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this postcondition.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Ensures(bool condition, String userMessage)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Postcondition, "Ensures");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that if an exception of type <typeparamref name="TException"/> is thrown then the expression <paramref name="condition"/> will be true when the enclosing method or property terminates abnormally.
+ /// </summary>
+ /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
+ /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this postcondition.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Exception type used in tools.")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void EnsuresOnThrow<TException>(bool condition) where TException : Exception
+ {
+ AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that if an exception of type <typeparamref name="TException"/> is thrown then the expression <paramref name="condition"/> will be true when the enclosing method or property terminates abnormally.
+ /// </summary>
+ /// <typeparam name="TException">Type of exception related to this postcondition.</typeparam>
+ /// <param name="condition">Boolean expression representing the contract. May include <seealso cref="OldValue"/> and <seealso cref="Result"/>.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// This call must happen at the beginning of a method or property before any other code.
+ /// This contract is exposed to clients so must only reference types and members at least as visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this postcondition.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Exception type used in tools.")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void EnsuresOnThrow<TException>(bool condition, String userMessage) where TException : Exception
+ {
+ AssertMustUseRewriter(ContractFailureKind.PostconditionOnException, "EnsuresOnThrow");
+ }
+
+ #region Old, Result, and Out Parameters
+
+ /// <summary>
+ /// Represents the result (a.k.a. return value) of a method or property.
+ /// </summary>
+ /// <typeparam name="T">Type of return value of the enclosing method or property.</typeparam>
+ /// <returns>Return value of the enclosing method or property.</returns>
+ /// <remarks>
+ /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Not intended to be called at runtime.")]
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static T Result<T>() { return default(T); }
+
+ /// <summary>
+ /// Represents the final (output) value of an out parameter when returning from a method.
+ /// </summary>
+ /// <typeparam name="T">Type of the out parameter.</typeparam>
+ /// <param name="value">The out parameter.</param>
+ /// <returns>The output value of the out parameter.</returns>
+ /// <remarks>
+ /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#", Justification = "Not intended to be called at runtime.")]
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static T ValueAtReturn<T>(out T value) { value = default(T); return value; }
+
+ /// <summary>
+ /// Represents the value of <paramref name="value"/> as it was at the start of the method or property.
+ /// </summary>
+ /// <typeparam name="T">Type of <paramref name="value"/>. This can be inferred.</typeparam>
+ /// <param name="value">Value to represent. This must be a field or parameter.</param>
+ /// <returns>Value of <paramref name="value"/> at the start of the method or property.</returns>
+ /// <remarks>
+ /// This method can only be used within the argument to the <seealso cref="Ensures(bool)"/> contract.
+ /// </remarks>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "value")]
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static T OldValue<T>(T value) { return default(T); }
+
+ #endregion Old, Result, and Out Parameters
+
+ #endregion Ensures
+
+ #region Invariant
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <remarks>
+ /// This contact can only be specified in a dedicated invariant method declared on a class.
+ /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this invariant.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Invariant(bool condition)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
+ }
+
+ /// <summary>
+ /// Specifies a contract such that the expression <paramref name="condition"/> will be true after every method or property on the enclosing class.
+ /// </summary>
+ /// <param name="condition">Boolean expression representing the contract.</param>
+ /// <param name="userMessage">If it is not a constant string literal, then the contract may not be understood by tools.</param>
+ /// <remarks>
+ /// This contact can only be specified in a dedicated invariant method declared on a class.
+ /// This contract is not exposed to clients so may reference members less visible as the enclosing method.
+ /// The contract rewriter must be used for runtime enforcement of this invariant.
+ /// </remarks>
+ [Pure]
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static void Invariant(bool condition, String userMessage)
+ {
+ AssertMustUseRewriter(ContractFailureKind.Invariant, "Invariant");
+ }
+
+ #endregion Invariant
+
+ #region Quantifiers
+
+ #region ForAll
+
+ /// <summary>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// for all integers starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
+ /// </summary>
+ /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
+ /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
+ /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
+ /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for all integers
+ /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
+ /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
+#endif
+ public static bool ForAll(int fromInclusive, int toExclusive, Predicate<int> predicate)
+ {
+ if (fromInclusive > toExclusive)
+#if INSIDE_CLR
+ throw new ArgumentException(Environment.GetResourceString("Argument_ToExclusiveLessThanFromExclusive"));
+#else
+ throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
+#endif
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+ Contract.EndContractBlock();
+
+ for (int i = fromInclusive; i < toExclusive; i++)
+ if (!predicate(i)) return false;
+ return true;
+ }
+
+
+ /// <summary>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// for all elements in the <paramref name="collection"/>.
+ /// </summary>
+ /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
+ /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
+ /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for all elements in
+ /// <paramref name="collection"/>.</returns>
+ /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.TrueForAll"/>
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
+#endif
+ public static bool ForAll<T>(IEnumerable<T> collection, Predicate<T> predicate)
+ {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+ Contract.EndContractBlock();
+
+ foreach (T t in collection)
+ if (!predicate(t)) return false;
+ return true;
+ }
+
+ #endregion ForAll
+
+ #region Exists
+
+ /// <summary>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// for any integer starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.
+ /// </summary>
+ /// <param name="fromInclusive">First integer to pass to <paramref name="predicate"/>.</param>
+ /// <param name="toExclusive">One greater than the last integer to pass to <paramref name="predicate"/>.</param>
+ /// <param name="predicate">Function that is evaluated from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</param>
+ /// <returns><c>true</c> if <paramref name="predicate"/> returns <c>true</c> for any integer
+ /// starting from <paramref name="fromInclusive"/> to <paramref name="toExclusive"/> - 1.</returns>
+ /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate obeys CER rules.
+#endif
+ public static bool Exists(int fromInclusive, int toExclusive, Predicate<int> predicate)
+ {
+ if (fromInclusive > toExclusive)
+#if INSIDE_CLR
+ throw new ArgumentException(Environment.GetResourceString("Argument_ToExclusiveLessThanFromExclusive"));
+#else
+ throw new ArgumentException("fromInclusive must be less than or equal to toExclusive.");
+#endif
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+ Contract.EndContractBlock();
+
+ for (int i = fromInclusive; i < toExclusive; i++)
+ if (predicate(i)) return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns whether the <paramref name="predicate"/> returns <c>true</c>
+ /// for any element in the <paramref name="collection"/>.
+ /// </summary>
+ /// <param name="collection">The collection from which elements will be drawn from to pass to <paramref name="predicate"/>.</param>
+ /// <param name="predicate">Function that is evaluated on elements from <paramref name="collection"/>.</param>
+ /// <returns><c>true</c> if and only if <paramref name="predicate"/> returns <c>true</c> for an element in
+ /// <paramref name="collection"/>.</returns>
+ /// <seealso cref="System.Collections.Generic.List&lt;T&gt;.Exists"/>
+ [Pure]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] // Assumes predicate & collection enumerator obey CER rules.
+#endif
+ public static bool Exists<T>(IEnumerable<T> collection, Predicate<T> predicate)
+ {
+ if (collection == null)
+ throw new ArgumentNullException("collection");
+ if (predicate == null)
+ throw new ArgumentNullException("predicate");
+ Contract.EndContractBlock();
+
+ foreach (T t in collection)
+ if (predicate(t)) return true;
+ return false;
+ }
+
+ #endregion Exists
+
+ #endregion Quantifiers
+
+ #region Pointers
+#if FEATURE_UNSAFE_CONTRACTS
+ /// <summary>
+ /// Runtime checking for pointer bounds is not currently feasible. Thus, at runtime, we just return
+ /// a very long extent for each pointer that is writable. As long as assertions are of the form
+ /// WritableBytes(ptr) >= ..., the runtime assertions will not fail.
+ /// The runtime value is 2^64 - 1 or 2^32 - 1.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1802", Justification = "FxCop is confused")]
+ static readonly ulong MaxWritableExtent = (UIntPtr.Size == 4) ? UInt32.MaxValue : UInt64.MaxValue;
+
+ /// <summary>
+ /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static ulong WritableBytes(UIntPtr startAddress) { return MaxWritableExtent - startAddress.ToUInt64(); }
+
+ /// <summary>
+ /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static ulong WritableBytes(IntPtr startAddress) { return MaxWritableExtent - (ulong)startAddress; }
+
+ /// <summary>
+ /// Allows specifying a writable extent for a UIntPtr, similar to SAL's writable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes writable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+ [SecurityCritical]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+
+ unsafe public static ulong WritableBytes(void* startAddress) { return MaxWritableExtent - (ulong)startAddress; }
+
+ /// <summary>
+ /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static ulong ReadableBytes(UIntPtr startAddress) { return MaxWritableExtent - startAddress.ToUInt64(); }
+
+ /// <summary>
+ /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static ulong ReadableBytes(IntPtr startAddress) { return MaxWritableExtent - (ulong)startAddress; }
+
+ /// <summary>
+ /// Allows specifying a readable extent for a UIntPtr, similar to SAL's readable extent.
+ /// NOTE: this is for static checking only. No useful runtime code can be generated for this
+ /// at the moment.
+ /// </summary>
+ /// <param name="startAddress">Start of memory region</param>
+ /// <returns>The result is the number of bytes readable starting at <paramref name="startAddress"/></returns>
+ [CLSCompliant(false)]
+ [Pure]
+ [ContractRuntimeIgnored]
+ [SecurityCritical]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ unsafe public static ulong ReadableBytes(void* startAddress) { return MaxWritableExtent - (ulong)startAddress; }
+#endif // FEATURE_UNSAFE_CONTRACTS
+ #endregion
+
+ #region Misc.
+
+ /// <summary>
+ /// Marker to indicate the end of the contract section of a method.
+ /// </summary>
+ [Conditional("CONTRACTS_FULL")]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static void EndContractBlock() { }
+
+ #endregion
+
+ #endregion User Methods
+
+ #region Failure Behavior
+
+ /// <summary>
+ /// Without contract rewriting, failing Assert/Assumes end up calling this method.
+ /// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call
+ /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
+ /// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
+ /// </summary>
+ static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException);
+
+ /// <summary>
+ /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
+ /// It is NEVER used to indicate failure of actual contracts at runtime.
+ /// </summary>
+ static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind);
+
+ #endregion
+ }
+
+ public enum ContractFailureKind {
+ Precondition,
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
+ Postcondition,
+ [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Postcondition")]
+ PostconditionOnException,
+ Invariant,
+ Assert,
+ Assume,
+ }
+
+
+}
+
+// Note: In .NET FX 4.5, we duplicated the ContractHelper class in the System.Runtime.CompilerServices
+// namespace to remove an ugly wart of a namespace from the Windows 8 profile. But we still need the
+// old locations left around, so we can support rewritten .NET FX 4.0 libraries. Consider removing
+// these from our reference assembly in a future version.
+namespace System.Diagnostics.Contracts.Internal
+{
+ [Obsolete("Use the ContractHelper class in the System.Runtime.CompilerServices namespace instead.")]
+ public static class ContractHelper
+ {
+ #region Rewriter Failure Hooks
+
+ /// <summary>
+ /// Rewriter will call this method on a contract failure to allow listeners to be notified.
+ /// The method should not perform any failure (assert/throw) itself.
+ /// </summary>
+ /// <returns>null if the event was handled and should not trigger a failure.
+ /// Otherwise, returns the localized failure message</returns>
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static string RaiseContractFailedEvent(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
+ {
+ return System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
+ }
+
+ /// <summary>
+ /// Rewriter calls this method to get the default failure behavior.
+ /// </summary>
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static void TriggerFailure(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ {
+ System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, displayMessage, userMessage, conditionText, innerException);
+ }
+
+ #endregion Rewriter Failure Hooks
+ }
+} // namespace System.Diagnostics.Contracts.Internal
+
+
+namespace System.Runtime.CompilerServices
+{
+ public static partial class ContractHelper
+ {
+ #region Rewriter Failure Hooks
+
+ /// <summary>
+ /// Rewriter will call this method on a contract failure to allow listeners to be notified.
+ /// The method should not perform any failure (assert/throw) itself.
+ /// </summary>
+ /// <returns>null if the event was handled and should not trigger a failure.
+ /// Otherwise, returns the localized failure message</returns>
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public static string RaiseContractFailedEvent(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
+ {
+ var resultFailureMessage = "Contract failed"; // default in case implementation does not assign anything.
+ RaiseContractFailedEventImplementation(failureKind, userMessage, conditionText, innerException, ref resultFailureMessage);
+ return resultFailureMessage;
+ }
+
+
+ /// <summary>
+ /// Rewriter calls this method to get the default failure behavior.
+ /// </summary>
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+#endif
+ public static void TriggerFailure(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ {
+ TriggerFailureImplementation(kind, displayMessage, userMessage, conditionText, innerException);
+ }
+
+ #endregion Rewriter Failure Hooks
+
+ #region Implementation Stubs
+
+ /// <summary>
+ /// Rewriter will call this method on a contract failure to allow listeners to be notified.
+ /// The method should not perform any failure (assert/throw) itself.
+ /// This method has 3 functions:
+ /// 1. Call any contract hooks (such as listeners to Contract failed events)
+ /// 2. Determine if the listeneres deem the failure as handled (then resultFailureMessage should be set to null)
+ /// 3. Produce a localized resultFailureMessage used in advertising the failure subsequently.
+ /// </summary>
+ /// <param name="resultFailureMessage">Should really be out (or the return value), but partial methods are not flexible enough.
+ /// On exit: null if the event was handled and should not trigger a failure.
+ /// Otherwise, returns the localized failure message</param>
+ static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage);
+
+ /// <summary>
+ /// Implements the default failure behavior of the platform. Under the BCL, it triggers an Assert box.
+ /// </summary>
+ static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException);
+
+ #endregion Implementation Stubs
+ }
+} // namespace System.Runtime.CompilerServices
+
diff --git a/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs b/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs
new file mode 100644
index 0000000000..804318e702
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Contracts/ContractsBCL.cs
@@ -0,0 +1,521 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Implementation details of CLR Contracts.
+**
+===========================================================*/
+#define DEBUG // The behavior of this contract library should be consistent regardless of build type.
+
+#if SILVERLIGHT
+#define FEATURE_UNTRUSTED_CALLERS
+#elif REDHAWK_RUNTIME
+
+#elif BARTOK_RUNTIME
+
+#else // CLR
+#define FEATURE_UNTRUSTED_CALLERS
+#define FEATURE_RELIABILITY_CONTRACTS
+#define FEATURE_SERIALIZATION
+#endif
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Reflection;
+
+#if FEATURE_RELIABILITY_CONTRACTS
+using System.Runtime.ConstrainedExecution;
+#endif
+#if FEATURE_UNTRUSTED_CALLERS
+using System.Security;
+using System.Security.Permissions;
+#endif
+
+namespace System.Diagnostics.Contracts {
+
+ public static partial class Contract
+ {
+ #region Private Methods
+
+ [ThreadStatic]
+ private static bool _assertingMustUseRewriter;
+
+ /// <summary>
+ /// This method is used internally to trigger a failure indicating to the "programmer" that he is using the interface incorrectly.
+ /// It is NEVER used to indicate failure of actual contracts at runtime.
+ /// </summary>
+ [SecuritySafeCritical]
+ static partial void AssertMustUseRewriter(ContractFailureKind kind, String contractKind)
+ {
+ if (_assertingMustUseRewriter)
+ System.Diagnostics.Assert.Fail("Asserting that we must use the rewriter went reentrant.", "Didn't rewrite this mscorlib?");
+ _assertingMustUseRewriter = true;
+
+ // For better diagnostics, report which assembly is at fault. Walk up stack and
+ // find the first non-mscorlib assembly.
+ Assembly thisAssembly = typeof(Contract).Assembly; // In case we refactor mscorlib, use Contract class instead of Object.
+ StackTrace stack = new StackTrace();
+ Assembly probablyNotRewritten = null;
+ for (int i = 0; i < stack.FrameCount; i++)
+ {
+ Assembly caller = stack.GetFrame(i).GetMethod().DeclaringType.Assembly;
+ if (caller != thisAssembly)
+ {
+ probablyNotRewritten = caller;
+ break;
+ }
+ }
+
+ if (probablyNotRewritten == null)
+ probablyNotRewritten = thisAssembly;
+ String simpleName = probablyNotRewritten.GetName().Name;
+ System.Runtime.CompilerServices.ContractHelper.TriggerFailure(kind, Environment.GetResourceString("MustUseCCRewrite", contractKind, simpleName), null, null, null);
+
+ _assertingMustUseRewriter = false;
+ }
+
+ #endregion Private Methods
+
+ #region Failure Behavior
+
+ /// <summary>
+ /// Without contract rewriting, failing Assert/Assumes end up calling this method.
+ /// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call
+ /// System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent, followed by
+ /// System.Runtime.CompilerServices.ContractHelper.TriggerFailure.
+ /// </summary>
+ [SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Security.SecuritySafeCriticalAttribute")]
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ static partial void ReportFailure(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException)
+ {
+ if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), "failureKind");
+ Contract.EndContractBlock();
+
+ // displayMessage == null means: yes we handled it. Otherwise it is the localized failure message
+ var displayMessage = System.Runtime.CompilerServices.ContractHelper.RaiseContractFailedEvent(failureKind, userMessage, conditionText, innerException);
+
+ if (displayMessage == null) return;
+
+ System.Runtime.CompilerServices.ContractHelper.TriggerFailure(failureKind, displayMessage, userMessage, conditionText, innerException);
+ }
+
+ /// <summary>
+ /// Allows a managed application environment such as an interactive interpreter (IronPython)
+ /// to be notified of contract failures and
+ /// potentially "handle" them, either by throwing a particular exception type, etc. If any of the
+ /// event handlers sets the Cancel flag in the ContractFailedEventArgs, then the Contract class will
+ /// not pop up an assert dialog box or trigger escalation policy. Hooking this event requires
+ /// full trust, because it will inform you of bugs in the appdomain and because the event handler
+ /// could allow you to continue execution.
+ /// </summary>
+ public static event EventHandler<ContractFailedEventArgs> ContractFailed {
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#if FEATURE_LINK_DEMAND
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+#endif
+ add {
+ System.Runtime.CompilerServices.ContractHelper.InternalContractFailed += value;
+ }
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#if FEATURE_LINK_DEMAND
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+#endif
+ remove {
+ System.Runtime.CompilerServices.ContractHelper.InternalContractFailed -= value;
+ }
+ }
+ #endregion FailureBehavior
+ }
+
+ public sealed class ContractFailedEventArgs : EventArgs
+ {
+ private ContractFailureKind _failureKind;
+ private String _message;
+ private String _condition;
+ private Exception _originalException;
+ private bool _handled;
+ private bool _unwind;
+
+ internal Exception thrownDuringHandler;
+
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ public ContractFailedEventArgs(ContractFailureKind failureKind, String message, String condition, Exception originalException)
+ {
+ Contract.Requires(originalException == null || failureKind == ContractFailureKind.PostconditionOnException);
+ _failureKind = failureKind;
+ _message = message;
+ _condition = condition;
+ _originalException = originalException;
+ }
+
+ public String Message { get { return _message; } }
+ public String Condition { get { return _condition; } }
+ public ContractFailureKind FailureKind { get { return _failureKind; } }
+ public Exception OriginalException { get { return _originalException; } }
+
+ // Whether the event handler "handles" this contract failure, or to fail via escalation policy.
+ public bool Handled {
+ get { return _handled; }
+ }
+
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#if FEATURE_LINK_DEMAND
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+#endif
+ public void SetHandled()
+ {
+ _handled = true;
+ }
+
+ public bool Unwind {
+ get { return _unwind; }
+ }
+
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#if FEATURE_LINK_DEMAND
+ [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
+#endif
+#endif
+ public void SetUnwind()
+ {
+ _unwind = true;
+ }
+ }
+
+ [Serializable]
+ [SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic")]
+ internal sealed class ContractException : Exception
+ {
+ readonly ContractFailureKind _Kind;
+ readonly string _UserMessage;
+ readonly string _Condition;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public ContractFailureKind Kind { get { return _Kind; } }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public string Failure { get { return this.Message; } }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public string UserMessage { get { return _UserMessage; } }
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ public string Condition { get { return _Condition; } }
+
+ // Called by COM Interop, if we see COR_E_CODECONTRACTFAILED as an HRESULT.
+ private ContractException()
+ {
+ HResult = System.Runtime.CompilerServices.ContractHelper.COR_E_CODECONTRACTFAILED;
+ }
+
+ public ContractException(ContractFailureKind kind, string failure, string userMessage, string condition, Exception innerException)
+ : base(failure, innerException)
+ {
+ HResult = System.Runtime.CompilerServices.ContractHelper.COR_E_CODECONTRACTFAILED;
+ this._Kind = kind;
+ this._UserMessage = userMessage;
+ this._Condition = condition;
+ }
+
+ private ContractException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+ : base(info, context)
+ {
+ _Kind = (ContractFailureKind)info.GetInt32("Kind");
+ _UserMessage = info.GetString("UserMessage");
+ _Condition = info.GetString("Condition");
+ }
+
+#if FEATURE_UNTRUSTED_CALLERS && FEATURE_SERIALIZATION
+ [SecurityCritical]
+#if FEATURE_LINK_DEMAND && FEATURE_SERIALIZATION
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
+#endif // FEATURE_LINK_DEMAND
+#endif // FEATURE_UNTRUSTED_CALLERS
+ public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+ {
+ base.GetObjectData(info, context);
+
+ info.AddValue("Kind", _Kind);
+ info.AddValue("UserMessage", _UserMessage);
+ info.AddValue("Condition", _Condition);
+ }
+ }
+}
+
+
+namespace System.Runtime.CompilerServices
+{
+ public static partial class ContractHelper
+ {
+ #region Private fields
+
+ private static volatile EventHandler<ContractFailedEventArgs> contractFailedEvent;
+ private static readonly Object lockObject = new Object();
+
+ internal const int COR_E_CODECONTRACTFAILED = unchecked((int)0x80131542);
+
+ #endregion
+
+ /// <summary>
+ /// Allows a managed application environment such as an interactive interpreter (IronPython) or a
+ /// web browser host (Jolt hosting Silverlight in IE) to be notified of contract failures and
+ /// potentially "handle" them, either by throwing a particular exception type, etc. If any of the
+ /// event handlers sets the Cancel flag in the ContractFailedEventArgs, then the Contract class will
+ /// not pop up an assert dialog box or trigger escalation policy. Hooking this event requires
+ /// full trust.
+ /// </summary>
+ internal static event EventHandler<ContractFailedEventArgs> InternalContractFailed
+ {
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#endif
+ add {
+ // Eagerly prepare each event handler _marked with a reliability contract_, to
+ // attempt to reduce out of memory exceptions while reporting contract violations.
+ // This only works if the new handler obeys the constraints placed on
+ // constrained execution regions. Eagerly preparing non-reliable event handlers
+ // would be a perf hit and wouldn't significantly improve reliability.
+ // UE: Please mention reliable event handlers should also be marked with the
+ // PrePrepareMethodAttribute to avoid CER eager preparation work when ngen'ed.
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareContractedDelegate(value);
+ lock (lockObject)
+ {
+ contractFailedEvent += value;
+ }
+ }
+#if FEATURE_UNTRUSTED_CALLERS
+ [SecurityCritical]
+#endif
+ remove {
+ lock (lockObject)
+ {
+ contractFailedEvent -= value;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Rewriter will call this method on a contract failure to allow listeners to be notified.
+ /// The method should not perform any failure (assert/throw) itself.
+ /// This method has 3 functions:
+ /// 1. Call any contract hooks (such as listeners to Contract failed events)
+ /// 2. Determine if the listeneres deem the failure as handled (then resultFailureMessage should be set to null)
+ /// 3. Produce a localized resultFailureMessage used in advertising the failure subsequently.
+ /// </summary>
+ /// <param name="resultFailureMessage">Should really be out (or the return value), but partial methods are not flexible enough.
+ /// On exit: null if the event was handled and should not trigger a failure.
+ /// Otherwise, returns the localized failure message</param>
+ [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate")]
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_RELIABILITY_CONTRACTS
+ [SecuritySafeCritical]
+#endif
+ static partial void RaiseContractFailedEventImplementation(ContractFailureKind failureKind, String userMessage, String conditionText, Exception innerException, ref string resultFailureMessage)
+ {
+ if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", failureKind), "failureKind");
+ Contract.EndContractBlock();
+
+ string returnValue;
+ String displayMessage = "contract failed."; // Incomplete, but in case of OOM during resource lookup...
+ ContractFailedEventArgs eventArgs = null; // In case of OOM.
+#if FEATURE_RELIABILITY_CONTRACTS
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
+#endif
+ try
+ {
+ displayMessage = GetDisplayMessage(failureKind, userMessage, conditionText);
+ EventHandler<ContractFailedEventArgs> contractFailedEventLocal = contractFailedEvent;
+ if (contractFailedEventLocal != null)
+ {
+ eventArgs = new ContractFailedEventArgs(failureKind, displayMessage, conditionText, innerException);
+ foreach (EventHandler<ContractFailedEventArgs> handler in contractFailedEventLocal.GetInvocationList())
+ {
+ try
+ {
+ handler(null, eventArgs);
+ }
+ catch (Exception e)
+ {
+ eventArgs.thrownDuringHandler = e;
+ eventArgs.SetUnwind();
+ }
+ }
+ if (eventArgs.Unwind)
+ {
+#if !FEATURE_CORECLR
+ if (Environment.IsCLRHosted)
+ TriggerCodeContractEscalationPolicy(failureKind, displayMessage, conditionText, innerException);
+#endif
+ // unwind
+ if (innerException == null) { innerException = eventArgs.thrownDuringHandler; }
+ throw new ContractException(failureKind, displayMessage, userMessage, conditionText, innerException);
+ }
+ }
+ }
+ finally
+ {
+ if (eventArgs != null && eventArgs.Handled)
+ {
+ returnValue = null; // handled
+ }
+ else
+ {
+ returnValue = displayMessage;
+ }
+ }
+ resultFailureMessage = returnValue;
+ }
+
+ /// <summary>
+ /// Rewriter calls this method to get the default failure behavior.
+ /// </summary>
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "conditionText")]
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "userMessage")]
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "kind")]
+ [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "innerException")]
+ [System.Diagnostics.DebuggerNonUserCode]
+#if FEATURE_UNTRUSTED_CALLERS && !FEATURE_CORECLR
+ [SecuritySafeCritical]
+#endif
+ static partial void TriggerFailureImplementation(ContractFailureKind kind, String displayMessage, String userMessage, String conditionText, Exception innerException)
+ {
+ // If we're here, our intent is to pop up a dialog box (if we can). For developers
+ // interacting live with a debugger, this is a good experience. For Silverlight
+ // hosted in Internet Explorer, the assert window is great. If we cannot
+ // pop up a dialog box, throw an exception (consider a library compiled with
+ // "Assert On Failure" but used in a process that can't pop up asserts, like an
+ // NT Service). For the CLR hosted by server apps like SQL or Exchange, we should
+ // trigger escalation policy.
+#if !FEATURE_CORECLR
+ if (Environment.IsCLRHosted)
+ {
+ TriggerCodeContractEscalationPolicy(kind, displayMessage, conditionText, innerException);
+ // Hosts like SQL may choose to abort the thread, so we will not get here in all cases.
+ // But if the host's chosen action was to throw an exception, we should throw an exception
+ // here (which is easier to do in managed code with the right parameters).
+ throw new ContractException(kind, displayMessage, userMessage, conditionText, innerException);
+ }
+#endif // !FEATURE_CORECLR
+ if (!Environment.UserInteractive) {
+ throw new ContractException(kind, displayMessage, userMessage, conditionText, innerException);
+ }
+ // May need to rethink Assert.Fail w/ TaskDialogIndirect as a model. Window title. Main instruction. Content. Expanded info.
+ // Optional info like string for collapsed text vs. expanded text.
+ String windowTitle = Environment.GetResourceString(GetResourceNameForFailure(kind));
+ const int numStackFramesToSkip = 2; // To make stack traces easier to read
+ System.Diagnostics.Assert.Fail(conditionText, displayMessage, windowTitle, COR_E_CODECONTRACTFAILED, StackTrace.TraceFormat.Normal, numStackFramesToSkip);
+ // If we got here, the user selected Ignore. Continue.
+ }
+
+ private static String GetResourceNameForFailure(ContractFailureKind failureKind)
+ {
+ String resourceName = null;
+ switch (failureKind)
+ {
+ case ContractFailureKind.Assert:
+ resourceName = "AssertionFailed";
+ break;
+
+ case ContractFailureKind.Assume:
+ resourceName = "AssumptionFailed";
+ break;
+
+ case ContractFailureKind.Precondition:
+ resourceName = "PreconditionFailed";
+ break;
+
+ case ContractFailureKind.Postcondition:
+ resourceName = "PostconditionFailed";
+ break;
+
+ case ContractFailureKind.Invariant:
+ resourceName = "InvariantFailed";
+ break;
+
+ case ContractFailureKind.PostconditionOnException:
+ resourceName = "PostconditionOnExceptionFailed";
+ break;
+
+ default:
+ Contract.Assume(false, "Unreachable code");
+ resourceName = "AssumptionFailed";
+ break;
+ }
+ return resourceName;
+ }
+
+#if FEATURE_RELIABILITY_CONTRACTS
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#endif
+ private static String GetDisplayMessage(ContractFailureKind failureKind, String userMessage, String conditionText)
+ {
+ String resourceName = GetResourceNameForFailure(failureKind);
+ // Well-formatted English messages will take one of four forms. A sentence ending in
+ // either a period or a colon, the condition string, then the message tacked
+ // on to the end with two spaces in front.
+ // Note that both the conditionText and userMessage may be null. Also,
+ // on Silverlight we may not be able to look up a friendly string for the
+ // error message. Let's leverage Silverlight's default error message there.
+ String failureMessage;
+ if (!String.IsNullOrEmpty(conditionText)) {
+ resourceName += "_Cnd";
+ failureMessage = Environment.GetResourceString(resourceName, conditionText);
+ }
+ else {
+ failureMessage = Environment.GetResourceString(resourceName);
+ }
+
+ // Now add in the user message, if present.
+ if (!String.IsNullOrEmpty(userMessage))
+ {
+ return failureMessage + " " + userMessage;
+ }
+ else
+ {
+ return failureMessage;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ // Will trigger escalation policy, if hosted and the host requested us to do something (such as
+ // abort the thread or exit the process). Starting in Dev11, for hosted apps the default behavior
+ // is to throw an exception.
+ // Implementation notes:
+ // We implement our default behavior of throwing an exception by simply returning from our native
+ // method inside the runtime and falling through to throw an exception.
+ // We must call through this method before calling the method on the Environment class
+ // because our security team does not yet support SecuritySafeCritical on P/Invoke methods.
+ // Note this can be called in the context of throwing another exception (EnsuresOnThrow).
+ [SecuritySafeCritical]
+ [DebuggerNonUserCode]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static void TriggerCodeContractEscalationPolicy(ContractFailureKind failureKind, String message, String conditionText, Exception innerException)
+ {
+ String exceptionAsString = null;
+ if (innerException != null)
+ exceptionAsString = innerException.ToString();
+ Environment.TriggerCodeContractFailure(failureKind, message, conditionText, exceptionAsString);
+ }
+#endif // !FEATURE_CORECLR
+ }
+} // namespace System.Runtime.CompilerServices
+
diff --git a/src/mscorlib/src/System/Diagnostics/Debugger.cs b/src/mscorlib/src/System/Diagnostics/Debugger.cs
new file mode 100644
index 0000000000..339c89eecf
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Debugger.cs
@@ -0,0 +1,195 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// The Debugger class is a part of the System.Diagnostics package
+// and is used for communicating with a debugger.
+
+namespace System.Diagnostics
+{
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.Versioning;
+
+ // No data, does not need to be marked with the serializable attribute
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Debugger
+ {
+ // This should have been a static class, but wasn't as of v3.5. Clearly, this is
+ // broken. We'll keep this in V4 for binary compat, but marked obsolete as error
+ // so migrated source code gets fixed.
+ [Obsolete("Do not create instances of the Debugger class. Call the static methods directly on this type instead", true)]
+ public Debugger()
+ {
+ // Should not have been instantiable - here for binary compatibility in V4.
+ }
+
+ // Break causes a breakpoint to be signalled to an attached debugger. If no debugger
+ // is attached, the user is asked if he wants to attach a debugger. If yes, then the
+ // debugger is launched.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Break()
+ {
+ if (!Debugger.IsAttached)
+ {
+ // Try and demand UnmanagedCodePermission. This is done in a try block because if this
+ // fails we want to be able to silently eat the exception and just return so
+ // that the call to Break does not possibly cause an unhandled exception.
+ // The idea here is that partially trusted code shouldn't be able to launch a debugger
+ // without the user going through Watson.
+ try
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ // If we enter this block, we do not have permission to break into the debugger
+ // and so we just return.
+ catch (SecurityException)
+ {
+ return;
+ }
+ }
+
+ // Causing a break is now allowed.
+ BreakInternal();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static void BreakCanThrow()
+ {
+ if (!Debugger.IsAttached)
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ // Causing a break is now allowed.
+ BreakInternal();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void BreakInternal();
+
+ // Launch launches & attaches a debugger to the process. If a debugger is already attached,
+ // nothing happens.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool Launch()
+ {
+ if (Debugger.IsAttached)
+ return (true);
+
+ // Try and demand UnmanagedCodePermission. This is done in a try block because if this
+ // fails we want to be able to silently eat the exception and just return so
+ // that the call to Break does not possibly cause an unhandled exception.
+ // The idea here is that partially trusted code shouldn't be able to launch a debugger
+ // without the user going through Watson.
+ try
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ // If we enter this block, we do not have permission to break into the debugger
+ // and so we just return.
+ catch (SecurityException)
+ {
+ return (false);
+ }
+
+ // Causing the debugger to launch is now allowed.
+ return (LaunchInternal());
+ }
+
+ // This class implements code:ICustomDebuggerNotification and provides a type to be used to notify
+ // the debugger that execution is about to enter a path that involves a cross-thread dependency.
+ // See code:NotifyOfCrossThreadDependency for more details.
+ private class CrossThreadDependencyNotification : ICustomDebuggerNotification
+ {
+ // constructor
+ public CrossThreadDependencyNotification()
+ {
+ }
+ }
+
+ // Do not inline the slow path
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ private static void NotifyOfCrossThreadDependencySlow()
+ {
+ CrossThreadDependencyNotification notification = new CrossThreadDependencyNotification();
+ CustomNotification(notification);
+ }
+
+ // Sends a notification to the debugger to indicate that execution is about to enter a path
+ // involving a cross thread dependency. A debugger that has opted into this type of notification
+ // can take appropriate action on receipt. For example, performing a funceval normally requires
+ // freezing all threads but the one performing the funceval. If the funceval requires execution on
+ // more than one thread, as might occur in remoting scenarios, the funceval will block. This
+ // notification will apprise the debugger that it will need to slip a thread or abort the funceval
+ // in such a situation. The notification is subject to collection after this function returns.
+ //
+ [method:System.Runtime.InteropServices.ComVisible(false)]
+ public static void NotifyOfCrossThreadDependency()
+ {
+ if (Debugger.IsAttached)
+ {
+ NotifyOfCrossThreadDependencySlow();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool LaunchInternal();
+
+ // Returns whether or not a debugger is attached to the process.
+ //
+ public static extern bool IsAttached
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ // Constants representing the importance level of messages to be logged.
+ //
+ // An attached debugger can enable or disable which messages will
+ // actually be reported to the user through the COM+ debugger
+ // services API. This info is communicated to the runtime so only
+ // desired events are actually reported to the debugger.
+ //
+ // Constant representing the default category
+ public static readonly String DefaultCategory = null;
+
+ // Posts a message for the attached debugger. If there is no
+ // debugger attached, has no effect. The debugger may or may not
+ // report the message depending on its settings.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void Log(int level, String category, String message);
+
+ // Checks to see if an attached debugger has logging enabled
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool IsLogging();
+
+ // Posts a custom notification for the attached debugger. If there is no
+ // debugger attached, has no effect. The debugger may or may not
+ // report the notification depending on its settings.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void CustomNotification(ICustomDebuggerNotification data);
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs b/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs
new file mode 100644
index 0000000000..6adcf34eda
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/DebuggerAttributes.cs
@@ -0,0 +1,378 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Attributes for debugger
+**
+**
+===========================================================*/
+
+
+namespace System.Diagnostics {
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
+ [ComVisible(true)]
+ public sealed class DebuggerStepThroughAttribute : Attribute
+ {
+ public DebuggerStepThroughAttribute () {}
+ }
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
+ [ComVisible(true)]
+ public sealed class DebuggerStepperBoundaryAttribute : Attribute
+ {
+ public DebuggerStepperBoundaryAttribute () {}
+ }
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)]
+ [ComVisible(true)]
+ public sealed class DebuggerHiddenAttribute : Attribute
+ {
+ public DebuggerHiddenAttribute () {}
+ }
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor |AttributeTargets.Struct, Inherited = false)]
+ [ComVisible(true)]
+ public sealed class DebuggerNonUserCodeAttribute : Attribute
+ {
+ public DebuggerNonUserCodeAttribute () {}
+ }
+
+ // Attribute class used by the compiler to mark modules.
+ // If present, then debugging information for everything in the
+ // assembly was generated by the compiler, and will be preserved
+ // by the Runtime so that the debugger can provide full functionality
+ // in the case of JIT attach. If not present, then the compiler may
+ // or may not have included debugging information, and the Runtime
+ // won't preserve the debugging info, which will make debugging after
+ // a JIT attach difficult.
+ [AttributeUsage(AttributeTargets.Assembly|AttributeTargets.Module, AllowMultiple = false)]
+ [ComVisible(true)]
+ public sealed class DebuggableAttribute : Attribute
+ {
+ [Flags]
+ [ComVisible(true)]
+ public enum DebuggingModes
+ {
+ None = 0x0,
+ Default = 0x1,
+ DisableOptimizations = 0x100,
+ IgnoreSymbolStoreSequencePoints = 0x2,
+ EnableEditAndContinue = 0x4
+ }
+
+ private DebuggingModes m_debuggingModes;
+
+ public DebuggableAttribute(bool isJITTrackingEnabled,
+ bool isJITOptimizerDisabled)
+ {
+ m_debuggingModes = 0;
+
+ if (isJITTrackingEnabled)
+ {
+ m_debuggingModes |= DebuggingModes.Default;
+ }
+
+ if (isJITOptimizerDisabled)
+ {
+ m_debuggingModes |= DebuggingModes.DisableOptimizations;
+ }
+ }
+
+ public DebuggableAttribute(DebuggingModes modes)
+ {
+ m_debuggingModes = modes;
+ }
+
+ public bool IsJITTrackingEnabled
+ {
+ get { return ((m_debuggingModes & DebuggingModes.Default) != 0); }
+ }
+
+ public bool IsJITOptimizerDisabled
+ {
+ get { return ((m_debuggingModes & DebuggingModes.DisableOptimizations) != 0); }
+ }
+
+ public DebuggingModes DebuggingFlags
+ {
+ get { return m_debuggingModes; }
+ }
+ }
+
+ // DebuggerBrowsableState states are defined as follows:
+ // Never never show this element
+ // Expanded expansion of the class is done, so that all visible internal members are shown
+ // Collapsed expansion of the class is not performed. Internal visible members are hidden
+ // RootHidden The target element itself should not be shown, but should instead be
+ // automatically expanded to have its members displayed.
+ // Default value is collapsed
+
+ // Please also change the code which validates DebuggerBrowsableState variable (in this file)
+ // if you change this enum.
+ [ComVisible(true)]
+ public enum DebuggerBrowsableState
+ {
+ Never = 0,
+ //Expanded is not supported in this release
+ //Expanded = 1,
+ Collapsed = 2,
+ RootHidden = 3
+ }
+
+
+ // the one currently supported with the csee.dat
+ // (mcee.dat, autoexp.dat) file.
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+ [ComVisible(true)]
+ public sealed class DebuggerBrowsableAttribute: Attribute
+ {
+ private DebuggerBrowsableState state;
+ public DebuggerBrowsableAttribute(DebuggerBrowsableState state)
+ {
+ if( state < DebuggerBrowsableState.Never || state > DebuggerBrowsableState.RootHidden)
+ throw new ArgumentOutOfRangeException("state");
+ Contract.EndContractBlock();
+
+ this.state = state;
+ }
+ public DebuggerBrowsableState State
+ {
+ get { return state; }
+ }
+ }
+
+
+ // DebuggerTypeProxyAttribute
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)]
+ [ComVisible(true)]
+ public sealed class DebuggerTypeProxyAttribute: Attribute
+ {
+ private string typeName;
+ private string targetName;
+ private Type target;
+
+ public DebuggerTypeProxyAttribute(Type type)
+ {
+ if (type == null) {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ this.typeName = type.AssemblyQualifiedName;
+ }
+
+ public DebuggerTypeProxyAttribute(string typeName)
+ {
+ this.typeName = typeName;
+ }
+ public string ProxyTypeName
+ {
+ get { return typeName; }
+ }
+
+ public Type Target
+ {
+ set {
+ if( value == null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ targetName = value.AssemblyQualifiedName;
+ target = value;
+ }
+
+ get { return target; }
+ }
+
+ public string TargetTypeName
+ {
+ get { return targetName; }
+ set { targetName = value; }
+
+ }
+ }
+
+ // This attribute is used to control what is displayed for the given class or field
+ // in the data windows in the debugger. The single argument to this attribute is
+ // the string that will be displayed in the value column for instances of the type.
+ // This string can include text between { and } which can be either a field,
+ // property or method (as will be documented in mscorlib). In the C# case,
+ // a general expression will be allowed which only has implicit access to the this pointer
+ // for the current instance of the target type. The expression will be limited,
+ // however: there is no access to aliases, locals, or pointers.
+ // In addition, attributes on properties referenced in the expression are not processed.
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Assembly, AllowMultiple = true)]
+ [ComVisible(true)]
+ public sealed class DebuggerDisplayAttribute : Attribute
+ {
+ private string name;
+ private string value;
+ private string type;
+ private string targetName;
+ private Type target;
+
+ public DebuggerDisplayAttribute(string value)
+ {
+ if( value == null ) {
+ this.value = "";
+ }
+ else {
+ this.value = value;
+ }
+ name = "";
+ type = "";
+ }
+
+ public string Value
+ {
+ get { return this.value; }
+ }
+
+ public string Name
+ {
+ get { return name; }
+ set { name = value; }
+ }
+
+ public string Type
+ {
+ get { return type; }
+ set { type = value; }
+ }
+
+ public Type Target
+ {
+ set {
+ if( value == null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ targetName = value.AssemblyQualifiedName;
+ target = value;
+ }
+ get { return target; }
+ }
+
+ public string TargetTypeName
+ {
+ get { return targetName; }
+ set { targetName = value; }
+
+ }
+ }
+
+
+ /// <summary>
+ /// Signifies that the attributed type has a visualizer which is pointed
+ /// to by the parameter type name strings.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)]
+ [ComVisible(true)]
+ public sealed class DebuggerVisualizerAttribute: Attribute
+ {
+ private string visualizerObjectSourceName;
+ private string visualizerName;
+ private string description;
+ private string targetName;
+ private Type target;
+
+ public DebuggerVisualizerAttribute(string visualizerTypeName)
+ {
+ this.visualizerName = visualizerTypeName;
+ }
+ public DebuggerVisualizerAttribute(string visualizerTypeName, string visualizerObjectSourceTypeName)
+ {
+ this.visualizerName = visualizerTypeName;
+ this.visualizerObjectSourceName = visualizerObjectSourceTypeName;
+ }
+ public DebuggerVisualizerAttribute(string visualizerTypeName, Type visualizerObjectSource)
+ {
+ if (visualizerObjectSource == null) {
+ throw new ArgumentNullException("visualizerObjectSource");
+ }
+ Contract.EndContractBlock();
+ this.visualizerName = visualizerTypeName;
+ this.visualizerObjectSourceName = visualizerObjectSource.AssemblyQualifiedName;
+ }
+ public DebuggerVisualizerAttribute(Type visualizer)
+ {
+ if (visualizer == null) {
+ throw new ArgumentNullException("visualizer");
+ }
+ Contract.EndContractBlock();
+ this.visualizerName = visualizer.AssemblyQualifiedName;
+ }
+ public DebuggerVisualizerAttribute(Type visualizer, Type visualizerObjectSource)
+ {
+ if (visualizer == null) {
+ throw new ArgumentNullException("visualizer");
+ }
+ if (visualizerObjectSource == null) {
+ throw new ArgumentNullException("visualizerObjectSource");
+ }
+ Contract.EndContractBlock();
+ this.visualizerName = visualizer.AssemblyQualifiedName;
+ this.visualizerObjectSourceName = visualizerObjectSource.AssemblyQualifiedName;
+ }
+ public DebuggerVisualizerAttribute(Type visualizer, string visualizerObjectSourceTypeName)
+ {
+ if (visualizer == null) {
+ throw new ArgumentNullException("visualizer");
+ }
+ Contract.EndContractBlock();
+ this.visualizerName = visualizer.AssemblyQualifiedName;
+ this.visualizerObjectSourceName = visualizerObjectSourceTypeName;
+ }
+
+ public string VisualizerObjectSourceTypeName
+ {
+ get { return visualizerObjectSourceName; }
+ }
+ public string VisualizerTypeName
+ {
+ get { return visualizerName; }
+ }
+ public string Description
+ {
+ get { return description; }
+ set { description = value; }
+ }
+
+ public Type Target
+ {
+ set {
+ if( value == null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ targetName = value.AssemblyQualifiedName;
+ target = value;
+ }
+
+ get { return target; }
+ }
+
+ public string TargetTypeName
+ {
+ set { targetName = value; }
+ get { return targetName; }
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Diagnostics/EditAndContinueHelper.cs b/src/mscorlib/src/System/Diagnostics/EditAndContinueHelper.cs
new file mode 100644
index 0000000000..32d7a98a50
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/EditAndContinueHelper.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Helper for EditAndContinue
+**
+**
+=============================================================================*/
+
+namespace System.Diagnostics {
+
+ using System;
+
+ [Serializable]
+ internal sealed class EditAndContinueHelper
+ {
+#pragma warning disable 169
+#pragma warning disable 414 // Field is not used from managed.
+ private Object _objectReference;
+#pragma warning restore 414
+#pragma warning restore 169
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs b/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs
new file mode 100644
index 0000000000..a7124a26ff
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/ActivityTracker.cs
@@ -0,0 +1,670 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics;
+using System.Threading;
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+using System.Threading.Tasks;
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// 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 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)
+ ///
+ /// On every start event call OnStart
+ ///
+ /// Guid activityID;
+ /// Guid relatedActivityID;
+ /// if (OnStart(activityName, out activityID, out relatedActivityID, ForceStop, options))
+ /// // Log Start event with activityID and relatedActivityID
+ ///
+ /// On every stop event call OnStop
+ ///
+ /// Guid activityID;
+ /// if (OnStop(activityName, ref activityID ForceStop))
+ /// // Stop event with activityID
+ ///
+ /// 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.
+ /// It updates CurrentActivityId to track.
+ ///
+ /// It returns true if the Start should be logged, otherwise (if it is illegal recursion) it return false.
+ ///
+ /// The start event should use as its activity ID the CurrentActivityId AFTER calling this routine and its
+ /// RelatedActivityID the CurrentActivityId BEFORE calling this routine (the creator).
+ ///
+ /// If activity tracing is not on, then activityId and relatedActivityId are not set
+ /// </summary>
+ 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
+ {
+ // 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 (TplEtwProvider.Log.IsEnabled(EventLevel.Informational, TplEtwProvider.Keywords.TasksFlowActivityIds))
+ Enable();
+ 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)
+ {
+ etwLog.DebugFacilityMessage("OnStartEnter", fullActivityName);
+ etwLog.DebugFacilityMessage("OnStartEnterActivityState", ActivityInfo.LiveActivities(currentActivity));
+ }
+
+ if (currentActivity != null)
+ {
+ // Stop activity tracking if we reached the maximum allowed depth
+ if (currentActivity.m_level >= MAX_ACTIVITY_DEPTH)
+ {
+ activityId = Guid.Empty;
+ relatedActivityId = Guid.Empty;
+ if (etwLog.Debug)
+ etwLog.DebugFacilityMessage("OnStartRET", "Fail");
+ return;
+ }
+ // Check for recursion, and force-stop any activities if the activity already started.
+ if ((options & EventActivityOptions.Recursive) == 0)
+ {
+ ActivityInfo existingActivity = FindActiveActivity(fullActivityName, currentActivity);
+ if (existingActivity != null)
+ {
+ OnStop(providerName, activityName, task, ref activityId);
+ currentActivity = m_current.Value;
+ }
+ }
+ }
+
+ // Get a unique ID for this activity.
+ long id;
+ if (currentActivity == null)
+ id = Interlocked.Increment(ref m_nextId);
+ else
+ id = Interlocked.Increment(ref currentActivity.m_lastChildID);
+
+ // 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, relatedActivityId, options);
+ m_current.Value = newActivity;
+
+ // Remember the current ID so we can log it
+ activityId = newActivity.ActivityId;
+
+ if (etwLog.Debug)
+ {
+ etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
+ etwLog.DebugFacilityMessage1("OnStartRet", activityId.ToString(), relatedActivityId.ToString());
+ }
+ }
+
+ /// <summary>
+ /// Called when a work item stops. The activity name = providerName + activityName without 'Stop' suffix.
+ /// 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>
+ public void OnStop(string providerName, string activityName, int task, ref Guid activityId)
+ {
+ if (m_current == null) // We are not enabled
+ return;
+
+ var fullActivityName = NormalizeActivityName(providerName, activityName, task);
+
+ var etwLog = TplEtwProvider.Log;
+ if (etwLog.Debug)
+ {
+ etwLog.DebugFacilityMessage("OnStopEnter", fullActivityName);
+ etwLog.DebugFacilityMessage("OnStopEnterActivityState", ActivityInfo.LiveActivities(m_current.Value));
+ }
+
+ 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.
+
+ // Search to find the activity to stop in one pass. This insures that we don't let one mistake
+ // (stopping something that was not started) cause all active starts to be stopped
+ // By first finding the target start to stop we are more robust.
+ ActivityInfo activityToStop = FindActiveActivity(fullActivityName, currentActivity);
+
+ // ignore stops where we can't find a start because we may have popped them previously.
+ if (activityToStop == null)
+ {
+ activityId = Guid.Empty;
+ // TODO add some logging about this. Basically could not find matching start.
+ if (etwLog.Debug)
+ etwLog.DebugFacilityMessage("OnStopRET", "Fail");
+ return;
+ }
+
+ activityId = activityToStop.ActivityId;
+
+ // See if there are any orphans that need to be stopped.
+ ActivityInfo orphan = currentActivity;
+ while (orphan != activityToStop && orphan != null)
+ {
+ if (orphan.m_stopped != 0) // Skip dead activities.
+ {
+ orphan = orphan.m_creator;
+ continue;
+ }
+ if (orphan.CanBeOrphan())
+ {
+ // We can't pop anything after we see a valid orphan, remember this for later when we update m_current.
+ if (newCurrentActivity == null)
+ newCurrentActivity = orphan;
+ }
+ else
+ {
+ orphan.m_stopped = 1;
+ Contract.Assert(orphan.m_stopped != 0);
+ }
+ orphan = orphan.m_creator;
+ }
+
+ // try to Stop the activity atomically. Other threads may be trying to do this as well.
+ if (Interlocked.CompareExchange(ref activityToStop.m_stopped, 1, 0) == 0)
+ {
+ // I succeeded stopping this activity. Now we update our m_current pointer
+
+ // If I haven't yet determined the new current activity, it is my creator.
+ if (newCurrentActivity == null)
+ newCurrentActivity = activityToStop.m_creator;
+
+ m_current.Value = newCurrentActivity;
+
+ if (etwLog.Debug)
+ {
+ etwLog.DebugFacilityMessage("OnStopRetActivityState", ActivityInfo.LiveActivities(newCurrentActivity));
+ etwLog.DebugFacilityMessage("OnStopRet", activityId.ToString());
+ }
+ return;
+ }
+ // We failed to stop it. We must have hit a race to stop it. Just start over and try again.
+ }
+ }
+
+ /// <summary>
+ /// Turns on activity tracking. It is sticky, once on it stays on (race issues otherwise)
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public void Enable()
+ {
+ if (m_current == null)
+ {
+ // Catch the not Implemented
+ try
+ {
+ m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
+ }
+ catch (NotImplementedException) {
+#if (!ES_BUILD_PCL && ! PROJECTN)
+ // send message to debugger without delay
+ System.Diagnostics.Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable");
+#endif
+ }
+ }
+ }
+
+ /// <summary>
+ /// An activity tracker is a singleton, this is how you get the one and only instance.
+ /// </summary>
+ public static ActivityTracker Instance { get { return s_activityTrackerInstance; } }
+
+
+ #region private
+
+ /// <summary>
+ /// The current activity ID. Use this to log normal events.
+ /// </summary>
+ private Guid CurrentActivityId { get { return m_current.Value.ActivityId; } }
+
+ /// <summary>
+ /// Searched for a active (nonstopped) activity with the given name. Returns null if not found.
+ /// </summary>
+ private ActivityInfo FindActiveActivity(string name, ActivityInfo startLocation)
+ {
+ var activity = startLocation;
+ while (activity != null)
+ {
+ if (name == activity.m_name && activity.m_stopped == 0)
+ return activity;
+ activity = activity.m_creator;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Strip out "Start" or "End" suffix from activity name and add providerName prefix.
+ /// If 'task' it does not end in Start or Stop and Task is non-zero use that as the name of the activity
+ /// </summary>
+ private string NormalizeActivityName(string providerName, string activityName, int task)
+ {
+ if (activityName.EndsWith(EventSource.s_ActivityStartSuffix, StringComparison.Ordinal))
+ activityName = activityName.Substring(0, activityName.Length - EventSource.s_ActivityStartSuffix.Length);
+ else if (activityName.EndsWith(EventSource.s_ActivityStopSuffix, StringComparison.Ordinal))
+ activityName = activityName.Substring(0, activityName.Length - EventSource.s_ActivityStopSuffix.Length);
+ else if (task != 0)
+ activityName = "task" + task.ToString();
+
+ // We use provider name to distinguish between activities from different providers.
+ return providerName + activityName;
+ }
+
+ // *******************************************************************************
+ /// <summary>
+ /// 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
+ /// '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, 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);
+ }
+
+ public Guid ActivityId
+ {
+ get
+ {
+ return m_guid;
+ }
+ }
+
+ public static string Path(ActivityInfo activityInfo)
+ {
+ if (activityInfo == null)
+ return ("");
+ return Path(activityInfo.m_creator) + "/" + activityInfo.m_uniqueId.ToString();
+ }
+
+ public override string ToString()
+ {
+ return m_name + "(" + Path(this) + (m_stopped != 0 ? ",DEAD)" : ")");
+ }
+
+ public static string LiveActivities(ActivityInfo list)
+ {
+ if (list == null)
+ return "";
+ return list.ToString() + ";" + LiveActivities(list.m_creator);
+ }
+
+ public bool CanBeOrphan()
+ {
+ if ((m_eventOptions & EventActivityOptions.Detachable) != 0)
+ return true;
+ return false;
+ }
+
+ #region private
+
+ #region CreateActivityPathGuid
+ /// <summary>
+ /// Logically every activity Path (see Path()) that describes the activities that caused this
+ /// (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 advantage of this in the encoding to output as long
+ /// a path in the GUID as possible.
+ ///
+ /// 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.
+ ///
+ /// It returns both the GUID which has the path as well as the offset that points just beyond
+ /// the end of the activity (so it can be appended to). Note that if the end is in a nibble
+ /// (it uses nibbles instead of bytes as the unit of encoding, then it will point at the unfinished
+ /// byte (since the top nibble can't be zero you can determine if this is true by seeing if
+ /// this byte is nonZero. This offset is needed to efficiently create the ID for child activities.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathGuidOffset)
+ {
+ fixed (Guid* outPtr = &idRet)
+ {
+ int activityPathGuidOffsetStart = 0;
+ if (m_creator != null)
+ {
+ activityPathGuidOffsetStart = m_creator.m_activityPathGuidOffset;
+ idRet = m_creator.m_guid;
+ }
+ else
+ {
+ // TODO FIXME - differentiate between AD inside PCL
+ int appDomainID = 0;
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ 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);
+
+
+ // If the path does not fit, Make a GUID by incrementing rather than as a path, keeping as much of the path as possible
+ if (12 < activityPathGuidOffset)
+ CreateOverflowGuid(outPtr);
+ }
+ }
+
+ /// <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 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)
+ {
+ // 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 = 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);
+
+ // Does it fit?
+ if (endId <= 12)
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ enum NumberListCodes : byte
+ {
+ End = 0x0, // ends the list. No valid value has this prefix.
+ 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 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 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 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
+ /// special (longer prefix) that indicates that this ID is allocated differently
+ [System.Security.SecurityCritical]
+ private static unsafe int AddIdToGuid(Guid* outPtr, int whereToAddId, uint id, bool overflow = false)
+ {
+ byte* ptr = (byte*)outPtr;
+ byte* endPtr = ptr + 12;
+ ptr += whereToAddId;
+ if (endPtr <= ptr)
+ return 13; // 12 means we might exactly fit, 13 means we definately did not fit
+
+ if (0 < id && id <= (uint)NumberListCodes.LastImmediateValue && !overflow)
+ WriteNibble(ref ptr, endPtr, id);
+ else
+ {
+ uint len = 4;
+ if (id <= 0xFF)
+ len = 1;
+ else if (id <= 0xFFFF)
+ len = 2;
+ else if (id <= 0xFFFFFF)
+ len = 3;
+
+ if (overflow)
+ {
+ 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);
+ }
+ // The rest is the same for overflow and non-overflow case
+ WriteNibble(ref ptr, endPtr, (uint)NumberListCodes.MultiByte1 + (len - 1));
+
+ // 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 outputting as padding.
+ if (id < 4096)
+ {
+ // Indicate this is a 1 byte multicode with 4 high order bits in the lower nibble.
+ *ptr = (byte)(((uint)NumberListCodes.MultiByte1 << 4) + (id >> 8));
+ id &= 0xFF; // Now we only want the low order bits.
+ }
+ ptr++;
+ }
+
+ // Write out the bytes.
+ while (0 < len)
+ {
+ if (endPtr <= ptr)
+ {
+ ptr++; // Indicate that we have overflowed
+ break;
+ }
+ *ptr++ = (byte)id;
+ id = (id >> 8);
+ --len;
+ }
+ }
+
+ // Compute the checksum
+ uint* sumPtr = (uint*)outPtr;
+ // We set the last DWORD the sum of the first 3 DWORDS in the GUID. This
+ sumPtr[3] = sumPtr[0] + sumPtr[1] + sumPtr[2] + 0x599D99AD; // This last number is a random number (it identifies us as us)
+
+ return (int)(ptr - ((byte*)outPtr));
+ }
+
+ /// <summary>
+ /// Write a single Nible 'value' (must be 0-15) to the byte buffer represented by *ptr.
+ /// Will not go past 'endPtr'. Also it assumes that we never write 0 so we can detect
+ /// whether a nibble has already been written to ptr because it will be nonzero.
+ /// Thus if it is non-zero it adds to the current byte, otherwise it advances and writes
+ /// the new byte (in the high bits) of the next byte.
+ /// </summary>
+ [System.Security.SecurityCritical]
+ private static unsafe void WriteNibble(ref byte* ptr, byte* endPtr, uint value)
+ {
+ Contract.Assert(0 <= value && value < 16);
+ Contract.Assert(ptr < endPtr);
+
+ if (*ptr != 0)
+ *ptr++ |= (byte)value;
+ else
+ *ptr = (byte)(value << 4);
+ }
+
+ #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 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
+ }
+
+ // This callback is used to initialize the m_current AsyncLocal Variable.
+ // Its job is to keep the ETW Activity ID (part of thread local storage) in sync
+ // with m_current.ActivityID
+ void ActivityChanging(AsyncLocalValueChangedArgs<ActivityInfo> args)
+ {
+ ActivityInfo cur = args.CurrentValue;
+ ActivityInfo prev = args.PreviousValue;
+
+ // 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)
+ {
+ // 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;
+ }
+ }
+
+ // 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 property 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();
+
+ // 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.
+
+ #endregion
+ }
+
+#if ES_BUILD_STANDALONE || PROJECTN
+ /******************************** 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 races.
+ /// </summary>
+ ///
+#if ES_BUILD_STANDALONE
+ [EventSource(Name = "Microsoft.Tasks.Nuget")]
+#else
+ [EventSource(Name = "System.Diagnostics.Tracing.TplEtwProvider")]
+#endif
+ internal class TplEtwProvider : EventSource
+ {
+ public class Keywords
+ {
+ public const EventKeywords TasksFlowActivityIds = (EventKeywords)0x80;
+ public const EventKeywords Debug = (EventKeywords)0x20000;
+ }
+
+ 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
+ // In these cases we don't have any Async local support. Do nothing.
+ internal sealed class AsyncLocalValueChangedArgs<T>
+ {
+ public T PreviousValue { get { return default(T); } }
+ public T CurrentValue { get { return default(T); } }
+
+ }
+
+ internal sealed class AsyncLocal<T>
+ {
+ public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler) {
+ throw new NotImplementedException("AsyncLocal only available on V4.6 and above");
+ }
+ public T Value
+ {
+ get { return default(T); }
+ set { }
+ }
+ }
+#endif
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventActivityOptions.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventActivityOptions.cs
new file mode 100644
index 0000000000..782afbf869
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventActivityOptions.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// EventActivityOptions flags allow to specify different activity related characteristics.
+ /// </summary>
+ [Flags]
+ public enum EventActivityOptions
+ {
+ /// <summary>
+ /// No special options are added to the event.
+ /// </summary>
+ None = 0,
+
+ /// <summary>
+ /// Disable Implicit Activity Tracking
+ /// </summary>
+ Disable = 0x2,
+
+ /// <summary>
+ /// Allow activity event to call itself (directly or indirectly)
+ /// </summary>
+ Recursive = 0x4,
+
+ /// <summary>
+ /// Allows event activity to live beyond its parent.
+ /// </summary>
+ Detachable = 0x8
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs
new file mode 100644
index 0000000000..b1f946464e
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventCounter.cs
@@ -0,0 +1,436 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+#if ES_BUILD_PCL
+ using System.Threading.Tasks;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Provides the ability to collect statistics through EventSource
+ /// </summary>
+ public class EventCounter
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EventCounter"/> class.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <param name="eventSource">The event source.</param>
+ public EventCounter(string name, EventSource eventSource)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(nameof(name));
+ }
+
+ if (eventSource == null)
+ {
+ throw new ArgumentNullException(nameof(eventSource));
+ }
+
+ InitializeBuffer();
+ _name = name;
+ EventCounterGroup.AddEventCounter(eventSource, this);
+ }
+
+ /// <summary>
+ /// Writes the metric.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ public void WriteMetric(float value)
+ {
+ Enqueue(value);
+ }
+
+ #region private implementation
+
+ private readonly string _name;
+
+ #region Buffer Management
+
+ // Values buffering
+ private const int BufferedSize = 10;
+ private const float UnusedBufferSlotValue = float.NegativeInfinity;
+ private const int UnsetIndex = -1;
+ private volatile float[] _bufferedValues;
+ private volatile int _bufferedValuesIndex;
+
+ private void InitializeBuffer()
+ {
+ _bufferedValues = new float[BufferedSize];
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ _bufferedValues[i] = UnusedBufferSlotValue;
+ }
+ }
+
+ private void Enqueue(float value)
+ {
+ // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
+ int i = _bufferedValuesIndex;
+ while (true)
+ {
+ float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+ i++;
+ if (_bufferedValues.Length <= i)
+ {
+ // It is possible that two threads both think the buffer is full, but only one get to actually flush it, the other
+ // will eventually enter this code path and potentially calling Flushing on a buffer that is not full, and that's okay too.
+ lock (_bufferedValues)
+ {
+ Flush();
+ }
+ i = 0;
+ }
+
+ if (result == UnusedBufferSlotValue)
+ {
+ // CompareExchange succeeded
+ _bufferedValuesIndex = i;
+ return;
+ }
+ }
+ }
+
+ private void Flush()
+ {
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ var value = Interlocked.Exchange(ref _bufferedValues[i], UnusedBufferSlotValue);
+ if (value != UnusedBufferSlotValue)
+ {
+ OnMetricWritten(value);
+ }
+ }
+
+ _bufferedValuesIndex = 0;
+ }
+
+ #endregion // Buffer Management
+
+ #region Statistics Calculation
+
+ // Statistics
+ private int _count;
+ private float _sum;
+ private float _sumSquared;
+ private float _min;
+ private float _max;
+
+ private void OnMetricWritten(float value)
+ {
+ _sum += value;
+ _sumSquared += value * value;
+ if (_count == 0 || value > _max)
+ {
+ _max = value;
+ }
+
+ if (_count == 0 || value < _min)
+ {
+ _min = value;
+ }
+
+ _count++;
+ }
+
+ internal EventCounterPayload GetEventCounterPayload()
+ {
+ lock (_bufferedValues)
+ {
+ Flush();
+ EventCounterPayload result = new EventCounterPayload();
+ result.Name = _name;
+ result.Count = _count;
+ result.Mean = _sum / _count;
+ result.StandardDerivation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+ result.Min = _min;
+ result.Max = _max;
+ ResetStatistics();
+ return result;
+ }
+ }
+
+ private void ResetStatistics()
+ {
+ _count = 0;
+ _sum = 0;
+ _sumSquared = 0;
+ _min = 0;
+ _max = 0;
+ }
+
+ #endregion // Statistics Calculation
+
+ #endregion // private implementation
+ }
+
+ #region internal supporting classes
+
+ [EventData]
+ internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>>
+ {
+ public string Name { get; set; }
+
+ public float Mean { get; set; }
+
+ public float StandardDerivation { get; set; }
+
+ public int Count { get; set; }
+
+ public float Min { get; set; }
+
+ public float Max { get; set; }
+
+ public float IntervalSec { get; internal set; }
+
+ #region Implementation of the IEnumerable interface
+
+ public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ private IEnumerable<KeyValuePair<string, object>> ForEnumeration
+ {
+ get
+ {
+ yield return new KeyValuePair<string, object>("Name", Name);
+ yield return new KeyValuePair<string, object>("Mean", Mean);
+ yield return new KeyValuePair<string, object>("StandardDerivation", StandardDerivation);
+ yield return new KeyValuePair<string, object>("Count", Count);
+ yield return new KeyValuePair<string, object>("Min", Min);
+ yield return new KeyValuePair<string, object>("Max", Max);
+ }
+ }
+
+ #endregion // Implementation of the IEnumerable interface
+ }
+
+ internal class EventCounterGroup : IDisposable
+ {
+ private readonly EventSource _eventSource;
+ private readonly int _eventSourceIndex;
+ private readonly List<EventCounter> _eventCounters;
+
+ internal EventCounterGroup(EventSource eventSource, int eventSourceIndex)
+ {
+ _eventSource = eventSource;
+ _eventSourceIndex = eventSourceIndex;
+ _eventCounters = new List<EventCounter>();
+ RegisterCommandCallback();
+ }
+
+ private void Add(EventCounter eventCounter)
+ {
+ _eventCounters.Add(eventCounter);
+ }
+
+ #region EventSource Command Processing
+
+ private void RegisterCommandCallback()
+ {
+ _eventSource.EventCommandExecuted += OnEventSourceCommand;
+ }
+
+ private void OnEventSourceCommand(object sender, EventCommandEventArgs e)
+ {
+ if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update)
+ {
+ string valueStr;
+ float value;
+ if (e.Arguments.TryGetValue("EventCounterIntervalSec", out valueStr) && float.TryParse(valueStr, out value))
+ {
+ EnableTimer(value);
+ }
+ }
+ }
+
+ #endregion // EventSource Command Processing
+
+ #region Global EventCounterGroup Array management
+
+ private static EventCounterGroup[] s_eventCounterGroups;
+
+ internal static void AddEventCounter(EventSource eventSource, EventCounter eventCounter)
+ {
+ int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+
+ EventCounterGroup.EnsureEventSourceIndexAvailable(eventSourceIndex);
+ EventCounterGroup eventCounterGroup = GetEventCounterGroup(eventSource);
+ eventCounterGroup.Add(eventCounter);
+ }
+
+ private static void EnsureEventSourceIndexAvailable(int eventSourceIndex)
+ {
+ if (EventCounterGroup.s_eventCounterGroups == null)
+ {
+ EventCounterGroup.s_eventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+ }
+ else if (eventSourceIndex >= EventCounterGroup.s_eventCounterGroups.Length)
+ {
+ EventCounterGroup[] newEventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+ Array.Copy(EventCounterGroup.s_eventCounterGroups, 0, newEventCounterGroups, 0, EventCounterGroup.s_eventCounterGroups.Length);
+ EventCounterGroup.s_eventCounterGroups = newEventCounterGroups;
+ }
+ }
+
+ private static EventCounterGroup GetEventCounterGroup(EventSource eventSource)
+ {
+ int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+ EventCounterGroup result = EventCounterGroup.s_eventCounterGroups[eventSourceIndex];
+ if (result == null)
+ {
+ result = new EventCounterGroup(eventSource, eventSourceIndex);
+ EventCounterGroup.s_eventCounterGroups[eventSourceIndex] = result;
+ }
+
+ return result;
+ }
+
+ #endregion // Global EventCounterGroup Array management
+
+ #region Timer Processing
+
+ private DateTime _timeStampSinceCollectionStarted;
+ private int _pollingIntervalInMilliseconds;
+ private Timer _pollingTimer;
+
+ private void EnableTimer(float pollingIntervalInSeconds)
+ {
+ if (pollingIntervalInSeconds == 0)
+ {
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+
+ _pollingIntervalInMilliseconds = 0;
+ }
+ else if (_pollingIntervalInMilliseconds == 0 || pollingIntervalInSeconds < _pollingIntervalInMilliseconds)
+ {
+ _pollingIntervalInMilliseconds = (int)(pollingIntervalInSeconds * 1000);
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+
+ _timeStampSinceCollectionStarted = DateTime.Now;
+ _pollingTimer = new Timer(OnTimer, null, _pollingIntervalInMilliseconds, _pollingIntervalInMilliseconds);
+ }
+ }
+
+ private void OnTimer(object state)
+ {
+ if (_eventSource.IsEnabled())
+ {
+ DateTime now = DateTime.Now;
+ TimeSpan elapsed = now - _timeStampSinceCollectionStarted;
+ lock (_pollingTimer)
+ {
+ foreach (var eventCounter in _eventCounters)
+ {
+ EventCounterPayload payload = eventCounter.GetEventCounterPayload();
+ payload.IntervalSec = (float)elapsed.TotalSeconds;
+ _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new { Payload = payload });
+ }
+
+
+ _timeStampSinceCollectionStarted = now;
+ }
+ }
+ else
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ EventCounterGroup.s_eventCounterGroups[_eventSourceIndex] = null;
+ }
+ }
+
+ #region PCL timer hack
+
+#if ES_BUILD_PCL
+ internal delegate void TimerCallback(object state);
+
+ internal sealed class Timer : CancellationTokenSource, IDisposable
+ {
+ private int _period;
+ private TimerCallback _callback;
+ private object _state;
+
+ internal Timer(TimerCallback callback, object state, int dueTime, int period)
+ {
+ _callback = callback;
+ _state = state;
+ _period = period;
+ Schedule(dueTime);
+ }
+
+ private void Schedule(int dueTime)
+ {
+ Task.Delay(dueTime, Token).ContinueWith(OnTimer, null, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
+ }
+
+ private void OnTimer(Task t, object s)
+ {
+ Schedule(_period);
+ _callback(_state);
+ }
+
+ public new void Dispose() { base.Cancel(); }
+ }
+#endif
+ #endregion // PCL timer hack
+
+ #endregion // Timer Processing
+
+ #region Implementation of the IDisposable interface
+
+ private bool _disposed = false;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+ }
+
+ _disposed = true;
+ }
+
+ #endregion // Implementation of the IDisposable interface
+ }
+
+ #endregion // internal supporting classes
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventDescriptor.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventDescriptor.cs
new file mode 100644
index 0000000000..11b6e6bac2
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventDescriptor.cs
@@ -0,0 +1,193 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+#endif
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ [StructLayout(LayoutKind.Explicit, Size = 16)]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+ internal struct EventDescriptor
+ {
+ # region private
+ [FieldOffset(0)]
+ private int m_traceloggingId;
+ [FieldOffset(0)]
+ private ushort m_id;
+ [FieldOffset(2)]
+ private byte m_version;
+ [FieldOffset(3)]
+ private byte m_channel;
+ [FieldOffset(4)]
+ private byte m_level;
+ [FieldOffset(5)]
+ private byte m_opcode;
+ [FieldOffset(6)]
+ private ushort m_task;
+ [FieldOffset(8)]
+ private long m_keywords;
+ #endregion
+
+ public EventDescriptor(
+ int traceloggingId,
+ byte level,
+ byte opcode,
+ long keywords
+ )
+ {
+ this.m_id = 0;
+ this.m_version = 0;
+ this.m_channel = 0;
+ this.m_traceloggingId = traceloggingId;
+ this.m_level = level;
+ this.m_opcode = opcode;
+ this.m_task = 0;
+ this.m_keywords = keywords;
+ }
+
+ public EventDescriptor(
+ int id,
+ byte version,
+ byte channel,
+ byte level,
+ byte opcode,
+ int task,
+ long keywords
+ )
+ {
+ if (id < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(id), Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (id > ushort.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(id), Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+ }
+
+ m_traceloggingId = 0;
+ m_id = (ushort)id;
+ m_version = version;
+ m_channel = channel;
+ m_level = level;
+ m_opcode = opcode;
+ m_keywords = keywords;
+
+ if (task < 0)
+ {
+ throw new ArgumentOutOfRangeException(nameof(task), Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (task > ushort.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(nameof(task), Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+ }
+
+ m_task = (ushort)task;
+ }
+
+ public int EventId
+ {
+ get
+ {
+ return m_id;
+ }
+ }
+ public byte Version
+ {
+ get
+ {
+ return m_version;
+ }
+ }
+ public byte Channel
+ {
+ get
+ {
+ return m_channel;
+ }
+ }
+ public byte Level
+ {
+ get
+ {
+ return m_level;
+ }
+ }
+ public byte Opcode
+ {
+ get
+ {
+ return m_opcode;
+ }
+ }
+ public int Task
+ {
+ get
+ {
+ return m_task;
+ }
+ }
+ public long Keywords
+ {
+ get
+ {
+ return m_keywords;
+ }
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is EventDescriptor))
+ return false;
+
+ return Equals((EventDescriptor) obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return m_id ^ m_version ^ m_channel ^ m_level ^ m_opcode ^ m_task ^ (int)m_keywords;
+ }
+
+ public bool Equals(EventDescriptor other)
+ {
+ if ((m_id != other.m_id) ||
+ (m_version != other.m_version) ||
+ (m_channel != other.m_channel) ||
+ (m_level != other.m_level) ||
+ (m_opcode != other.m_opcode) ||
+ (m_task != other.m_task) ||
+ (m_keywords != other.m_keywords))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ public static bool operator ==(EventDescriptor event1, EventDescriptor event2)
+ {
+ return event1.Equals(event2);
+ }
+
+ public static bool operator !=(EventDescriptor event1, EventDescriptor event2)
+ {
+ return !event1.Equals(event2);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs
new file mode 100644
index 0000000000..6ea8d98d92
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventProvider.cs
@@ -0,0 +1,1220 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using Microsoft.Win32;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+using System;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_AGAINST_DOTNET_V35
+using Microsoft.Internal; // for Tuple (can't define alias for open generic types so we "use" the whole namespace)
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ // New in CLR4.0
+ internal enum ControllerCommand
+ {
+ // Strictly Positive numbers are for provider-specific commands, negative number are for 'shared' commands. 256
+ // The first 256 negative numbers are reserved for the framework.
+ Update = 0, // Not used by EventPrividerBase.
+ SendManifest = -1,
+ Enable = -2,
+ Disable = -3,
+ };
+
+ /// <summary>
+ /// Only here because System.Diagnostics.EventProvider needs one more extensibility hook (when it gets a
+ /// controller callback)
+ /// </summary>
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+ internal partial class EventProvider : IDisposable
+ {
+ // This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
+ // subclasses of EventProvider use when creating efficient (but unsafe) version of
+ // EventWrite. We do make it a nested type because we really don't expect anyone to use
+ // it except subclasses (and then only rarely).
+ public struct EventData
+ {
+ internal unsafe ulong Ptr;
+ internal uint Size;
+ internal uint Reserved;
+ }
+
+ /// <summary>
+ /// A struct characterizing ETW sessions (identified by the etwSessionId) as
+ /// activity-tracing-aware or legacy. A session that's activity-tracing-aware
+ /// has specified one non-zero bit in the reserved range 44-47 in the
+ /// 'allKeywords' value it passed in for a specific EventProvider.
+ /// </summary>
+ public struct SessionInfo
+ {
+ internal int sessionIdBit; // the index of the bit used for tracing in the "reserved" field of AllKeywords
+ internal int etwSessionId; // the machine-wide ETW session ID
+
+ internal SessionInfo(int sessionIdBit_, int etwSessionId_)
+ { sessionIdBit = sessionIdBit_; etwSessionId = etwSessionId_; }
+ }
+
+ private static bool m_setInformationMissing;
+
+ [SecurityCritical]
+ UnsafeNativeMethods.ManifestEtw.EtwEnableCallback m_etwCallback; // Trace Callback function
+ private long m_regHandle; // Trace Registration Handle
+ private byte m_level; // Tracing Level
+ private long m_anyKeywordMask; // Trace Enable Flags
+ private long m_allKeywordMask; // Match all keyword
+ private List<SessionInfo> m_liveSessions; // current live sessions (Tuple<sessionIdBit, etwSessionId>)
+ private bool m_enabled; // Enabled flag from Trace callback
+ private Guid m_providerId; // Control Guid
+ internal bool m_disposed; // when true provider has unregistered
+
+ [ThreadStatic]
+ private static WriteEventErrorCode s_returnCode; // The last return code
+
+ private const int s_basicTypeAllocationBufferSize = 16;
+ private const int s_etwMaxNumberArguments = 128;
+ private const int s_etwAPIMaxRefObjCount = 8;
+ private const int s_maxEventDataDescriptors = 128;
+ private const int s_traceEventMaximumSize = 65482;
+ private const int s_traceEventMaximumStringSize = 32724;
+
+ [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
+ public enum WriteEventErrorCode : int
+ {
+ //check mapping to runtime codes
+ NoError = 0,
+ NoFreeBuffers = 1,
+ EventTooBig = 2,
+ NullInput = 3,
+ TooManyArgs = 4,
+ Other = 5,
+ };
+
+ // Because callbacks happen on registration, and we need the callbacks for those setup
+ // we can't call Register in the constructor.
+ //
+ // Note that EventProvider should ONLY be used by EventSource. In particular because
+ // it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
+ // you may get native callbacks during shutdown when we have destroyed the delegate.
+ // EventSource has special logic to do this, no one else should be calling EventProvider.
+ internal EventProvider()
+ {
+ }
+
+ /// <summary>
+ /// This method registers the controlGuid of this class with ETW. We need to be running on
+ /// Vista or above. If not a PlatformNotSupported exception will be thrown. If for some
+ /// reason the ETW Register call failed a NotSupported exception will be thrown.
+ /// </summary>
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventRegister(System.Guid&,Microsoft.Win32.UnsafeNativeMethods.ManifestEtw+EtwEnableCallback,System.Void*,System.Int64&):System.UInt32" />
+ // <SatisfiesLinkDemand Name="Win32Exception..ctor(System.Int32)" />
+ // <ReferencesCritical Name="Method: EtwEnableCallBack(Guid&, Int32, Byte, Int64, Int64, Void*, Void*):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ internal unsafe void Register(Guid providerGuid)
+ {
+ m_providerId = providerGuid;
+ uint status;
+ m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
+
+ status = EventRegister(ref m_providerId, m_etwCallback);
+ if (status != 0)
+ {
+ throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
+ }
+ }
+
+ //
+ // implement Dispose Pattern to early deregister from ETW insted of waiting for
+ // the finalizer to call deregistration.
+ // Once the user is done with the provider it needs to call Close() or Dispose()
+ // If neither are called the finalizer will unregister the provider anyway
+ //
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ // <SecurityKernel Critical="True" TreatAsSafe="Does not expose critical resource" Ring="1">
+ // <ReferencesCritical Name="Method: Deregister():Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ protected virtual void Dispose(bool disposing)
+ {
+ //
+ // explicit cleanup is done by calling Dispose with true from
+ // Dispose() or Close(). The disposing arguement is ignored because there
+ // are no unmanaged resources.
+ // The finalizer calls Dispose with false.
+ //
+
+ //
+ // check if the object has been allready disposed
+ //
+ if (m_disposed) return;
+
+ // Disable the provider.
+ m_enabled = false;
+
+ // Do most of the work under a lock to avoid shutdown race.
+ lock (EventListener.EventListenersLock)
+ {
+ // Double check
+ if (m_disposed)
+ return;
+
+ Deregister();
+ m_disposed = true;
+ }
+ }
+
+ /// <summary>
+ /// This method deregisters the controlGuid of this class with ETW.
+ ///
+ /// </summary>
+ public virtual void Close()
+ {
+ Dispose();
+ }
+
+ ~EventProvider()
+ {
+ Dispose(false);
+ }
+
+ /// <summary>
+ /// This method un-registers from ETW.
+ /// </summary>
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventUnregister(System.Int64):System.Int32" />
+ // </SecurityKernel>
+ // TODO Check return code from UnsafeNativeMethods.ManifestEtw.EventUnregister
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1806:DoNotIgnoreMethodResults", MessageId = "Microsoft.Win32.UnsafeNativeMethods.ManifestEtw.EventUnregister(System.Int64)"), System.Security.SecurityCritical]
+ private unsafe void Deregister()
+ {
+ //
+ // Unregister from ETW using the RegHandle saved from
+ // the register call.
+ //
+
+ if (m_regHandle != 0)
+ {
+ EventUnregister();
+ m_regHandle = 0;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <UsesUnsafeCode Name="Parameter filterData of type: Void*" />
+ // <UsesUnsafeCode Name="Parameter callbackContext of type: Void*" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ unsafe void EtwEnableCallBack(
+ [In] ref System.Guid sourceId,
+ [In] int controlCode,
+ [In] byte setLevel,
+ [In] long anyKeyword,
+ [In] long allKeyword,
+ [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+ [In] void* callbackContext
+ )
+ {
+ // This is an optional callback API. We will therefore ignore any failures that happen as a
+ // result of turning on this provider as to not crash the app.
+ // EventSource has code to validate whether initialization it expected to occur actually occurred
+ try
+ {
+ ControllerCommand command = ControllerCommand.Update;
+ IDictionary<string, string> args = null;
+ bool skipFinalOnControllerCommand = false;
+ if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
+ {
+ m_enabled = true;
+ m_level = setLevel;
+ m_anyKeywordMask = anyKeyword;
+ m_allKeywordMask = allKeyword;
+
+ // ES_SESSION_INFO is a marker for additional places we #ifdeffed out to remove
+ // references to EnumerateTraceGuidsEx. This symbol is actually not used because
+ // today we use FEATURE_ACTIVITYSAMPLING to determine if this code is there or not.
+ // However we put it in the #if so that we don't lose the fact that this feature
+ // switch is at least partially independent of FEATURE_ACTIVITYSAMPLING
+
+ List<Tuple<SessionInfo, bool>> sessionsChanged = GetSessions();
+ foreach (var session in sessionsChanged)
+ {
+ int sessionChanged = session.Item1.sessionIdBit;
+ int etwSessionId = session.Item1.etwSessionId;
+ bool bEnabling = session.Item2;
+
+ skipFinalOnControllerCommand = true;
+ args = null; // reinitialize args for every session...
+
+ // if we get more than one session changed we have no way
+ // of knowing which one "filterData" belongs to
+ if (sessionsChanged.Count > 1)
+ filterData = null;
+
+ // read filter data only when a session is being *added*
+ byte[] data;
+ int keyIndex;
+ if (bEnabling &&
+ GetDataFromController(etwSessionId, filterData, out command, out data, out keyIndex))
+ {
+ args = new Dictionary<string, string>(4);
+ while (keyIndex < data.Length)
+ {
+ int keyEnd = FindNull(data, keyIndex);
+ int valueIdx = keyEnd + 1;
+ int valueEnd = FindNull(data, valueIdx);
+ if (valueEnd < data.Length)
+ {
+ string key = System.Text.Encoding.UTF8.GetString(data, keyIndex, keyEnd - keyIndex);
+ string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx);
+ args[key] = value;
+ }
+ keyIndex = valueEnd + 1;
+ }
+ }
+
+ // execute OnControllerCommand once for every session that has changed.
+ OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId);
+ }
+ }
+ else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
+ {
+ m_enabled = false;
+ m_level = 0;
+ m_anyKeywordMask = 0;
+ m_allKeywordMask = 0;
+ m_liveSessions = null;
+ }
+ else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE)
+ {
+ command = ControllerCommand.SendManifest;
+ }
+ else
+ return; // per spec you ignore commands you don't recognize.
+
+ if (!skipFinalOnControllerCommand)
+ OnControllerCommand(command, args, 0, 0);
+ }
+ catch (Exception)
+ {
+ // We want to ignore any failures that happen as a result of turning on this provider as to
+ // not crash the app.
+ }
+ }
+
+ // New in CLR4.0
+ protected virtual void OnControllerCommand(ControllerCommand command, IDictionary<string, string> arguments, int sessionId, int etwSessionId) { }
+ protected EventLevel Level { get { return (EventLevel)m_level; } set { m_level = (byte)value; } }
+ protected EventKeywords MatchAnyKeyword { get { return (EventKeywords)m_anyKeywordMask; } set { m_anyKeywordMask = unchecked((long)value); } }
+ protected EventKeywords MatchAllKeyword { get { return (EventKeywords)m_allKeywordMask; } set { m_allKeywordMask = unchecked((long)value); } }
+
+ static private int FindNull(byte[] buffer, int idx)
+ {
+ while (idx < buffer.Length && buffer[idx] != 0)
+ idx++;
+ return idx;
+ }
+
+ /// <summary>
+ /// Determines the ETW sessions that have been added and/or removed to the set of
+ /// sessions interested in the current provider. It does so by (1) enumerating over all
+ /// ETW sessions that enabled 'this.m_Guid' for the current process ID, and (2)
+ /// comparing the current list with a list it cached on the previous invocation.
+ ///
+ /// The return value is a list of tuples, where the SessionInfo specifies the
+ /// ETW session that was added or remove, and the bool specifies whether the
+ /// session was added or whether it was removed from the set.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ private List<Tuple<SessionInfo, bool>> GetSessions()
+ {
+ List<SessionInfo> liveSessionList = null;
+
+ GetSessionInfo((Action<int, long>)
+ ((etwSessionId, matchAllKeywords) =>
+ GetSessionInfoCallback(etwSessionId, matchAllKeywords, ref liveSessionList)));
+
+ List<Tuple<SessionInfo, bool>> changedSessionList = new List<Tuple<SessionInfo, bool>>();
+
+ // first look for sessions that have gone away (or have changed)
+ // (present in the m_liveSessions but not in the new liveSessionList)
+ if (m_liveSessions != null)
+ {
+ foreach (SessionInfo s in m_liveSessions)
+ {
+ int idx;
+ if ((idx = IndexOfSessionInList(liveSessionList, s.etwSessionId)) < 0 ||
+ (liveSessionList[idx].sessionIdBit != s.sessionIdBit))
+ changedSessionList.Add(Tuple.Create(s, false));
+
+ }
+ }
+ // next look for sessions that were created since the last callback (or have changed)
+ // (present in the new liveSessionList but not in m_liveSessions)
+ if (liveSessionList != null)
+ {
+ foreach (SessionInfo s in liveSessionList)
+ {
+ int idx;
+ if ((idx = IndexOfSessionInList(m_liveSessions, s.etwSessionId)) < 0 ||
+ (m_liveSessions[idx].sessionIdBit != s.sessionIdBit))
+ changedSessionList.Add(Tuple.Create(s, true));
+ }
+ }
+
+ m_liveSessions = liveSessionList;
+ return changedSessionList;
+ }
+
+
+ /// <summary>
+ /// This method is the callback used by GetSessions() when it calls into GetSessionInfo().
+ /// It updates a List{SessionInfo} based on the etwSessionId and matchAllKeywords that
+ /// GetSessionInfo() passes in.
+ /// </summary>
+ private static void GetSessionInfoCallback(int etwSessionId, long matchAllKeywords,
+ ref List<SessionInfo> sessionList)
+ {
+ uint sessionIdBitMask = (uint)SessionMask.FromEventKeywords(unchecked((ulong)matchAllKeywords));
+ // an ETW controller that specifies more than the mandated bit for our EventSource
+ // will be ignored...
+ if (bitcount(sessionIdBitMask) > 1)
+ return;
+
+ if (sessionList == null)
+ sessionList = new List<SessionInfo>(8);
+
+ if (bitcount(sessionIdBitMask) == 1)
+ {
+ // activity-tracing-aware etw session
+ sessionList.Add(new SessionInfo(bitindex(sessionIdBitMask) + 1, etwSessionId));
+ }
+ else
+ {
+ // legacy etw session
+ sessionList.Add(new SessionInfo(bitcount((uint)SessionMask.All) + 1, etwSessionId));
+ }
+ }
+
+ /// <summary>
+ /// This method enumerates over all active ETW sessions that have enabled 'this.m_Guid'
+ /// for the current process ID, calling 'action' for each session, and passing it the
+ /// ETW session and the 'AllKeywords' the session enabled for the current provider.
+ /// </summary>
+ [System.Security.SecurityCritical]
+ private unsafe void GetSessionInfo(Action<int, long> action)
+ {
+ // We wish the EventSource package to be legal for Windows Store applications.
+ // Currently EnumerateTraceGuidsEx is not an allowed API, so we avoid its use here
+ // and use the information in the registry instead. This means that ETW controllers
+ // that do not publish their intent to the registry (basically all controllers EXCEPT
+ // TraceEventSesion) will not work properly
+
+ // However the framework version of EventSource DOES have ES_SESSION_INFO defined and thus
+ // does not have this issue.
+#if ES_SESSION_INFO || !ES_BUILD_STANDALONE
+ int buffSize = 256; // An initial guess that probably works most of the time.
+ byte* buffer;
+ for (; ; )
+ {
+ var space = stackalloc byte[buffSize];
+ buffer = space;
+ var hr = 0;
+
+ fixed (Guid* provider = &m_providerId)
+ {
+ hr = UnsafeNativeMethods.ManifestEtw.EnumerateTraceGuidsEx(UnsafeNativeMethods.ManifestEtw.TRACE_QUERY_INFO_CLASS.TraceGuidQueryInfo,
+ provider, sizeof(Guid), buffer, buffSize, ref buffSize);
+ }
+ if (hr == 0)
+ break;
+ if (hr != 122 /* ERROR_INSUFFICIENT_BUFFER */)
+ return;
+ }
+
+ var providerInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_GUID_INFO*)buffer;
+ var providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&providerInfos[1];
+ int processId = unchecked((int)Win32Native.GetCurrentProcessId());
+ // iterate over the instances of the EventProvider in all processes
+ for (int i = 0; i < providerInfos->InstanceCount; i++)
+ {
+ if (providerInstance->Pid == processId)
+ {
+ var enabledInfos = (UnsafeNativeMethods.ManifestEtw.TRACE_ENABLE_INFO*)&providerInstance[1];
+ // iterate over the list of active ETW sessions "listening" to the current provider
+ for (int j = 0; j < providerInstance->EnableCount; j++)
+ action(enabledInfos[j].LoggerId, enabledInfos[j].MatchAllKeyword);
+ }
+ if (providerInstance->NextOffset == 0)
+ break;
+ Contract.Assert(0 <= providerInstance->NextOffset && providerInstance->NextOffset < buffSize);
+ var structBase = (byte*)providerInstance;
+ providerInstance = (UnsafeNativeMethods.ManifestEtw.TRACE_PROVIDER_INSTANCE_INFO*)&structBase[providerInstance->NextOffset];
+ }
+#else
+#if !ES_BUILD_PCL && !FEATURE_PAL // TODO command arguments don't work on PCL builds...
+ // This code is only used in the Nuget Package Version of EventSource. because
+ // the code above is using APIs baned from UWP apps.
+ //
+ // TODO: In addition to only working when TraceEventSession enables the provider, this code
+ // also has a problem because TraceEvent does not clean up if the registry is stale
+ // It is unclear if it is worth keeping, but for now we leave it as it does work
+ // at least some of the time.
+
+ // Determine our session from what is in the registry.
+ string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
+ if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
+ regKey = @"Software" + @"\Wow6432Node" + regKey;
+ else
+ regKey = @"Software" + regKey;
+
+ var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(regKey);
+ if (key != null)
+ {
+ foreach (string valueName in key.GetValueNames())
+ {
+ if (valueName.StartsWith("ControllerData_Session_", StringComparison.Ordinal))
+ {
+ string strId = valueName.Substring(23); // strip of the ControllerData_Session_
+ int etwSessionId;
+ if (int.TryParse(strId, out etwSessionId))
+ {
+ // we need to assert this permission for partial trust scenarios
+ (new RegistryPermission(RegistryPermissionAccess.Read, regKey)).Assert();
+ var data = key.GetValue(valueName) as byte[];
+ if (data != null)
+ {
+ var dataAsString = System.Text.Encoding.UTF8.GetString(data);
+ int keywordIdx = dataAsString.IndexOf("EtwSessionKeyword", StringComparison.Ordinal);
+ if (0 <= keywordIdx)
+ {
+ int startIdx = keywordIdx + 18;
+ int endIdx = dataAsString.IndexOf('\0', startIdx);
+ string keywordBitString = dataAsString.Substring(startIdx, endIdx-startIdx);
+ int keywordBit;
+ if (0 < endIdx && int.TryParse(keywordBitString, out keywordBit))
+ action(etwSessionId, 1L << keywordBit);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+#endif
+ }
+
+ /// <summary>
+ /// Returns the index of the SesisonInfo from 'sessions' that has the specified 'etwSessionId'
+ /// or -1 if the value is not present.
+ /// </summary>
+ private static int IndexOfSessionInList(List<SessionInfo> sessions, int etwSessionId)
+ {
+ if (sessions == null)
+ return -1;
+ // for non-coreclr code we could use List<T>.FindIndex(Predicate<T>), but we need this to compile
+ // on coreclr as well
+ for (int i = 0; i < sessions.Count; ++i)
+ if (sessions[i].etwSessionId == etwSessionId)
+ return i;
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Gets any data to be passed from the controller to the provider. It starts with what is passed
+ /// into the callback, but unfortunately this data is only present for when the provider is active
+ /// at the time the controller issues the command. To allow for providers to activate after the
+ /// controller issued a command, we also check the registry and use that to get the data. The function
+ /// returns an array of bytes representing the data, the index into that byte array where the data
+ /// starts, and the command being issued associated with that data.
+ /// </summary>
+ [System.Security.SecurityCritical]
+ private unsafe bool GetDataFromController(int etwSessionId,
+ UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
+ {
+ data = null;
+ dataStart = 0;
+ if (filterData == null)
+ {
+#if (!ES_BUILD_PCL && !PROJECTN && !FEATURE_PAL)
+ string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
+ if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
+ regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
+ else
+ regKey = @"HKEY_LOCAL_MACHINE\Software" + regKey;
+
+ string valueName = "ControllerData_Session_" + etwSessionId.ToString(CultureInfo.InvariantCulture);
+
+ // we need to assert this permission for partial trust scenarios
+ (new RegistryPermission(RegistryPermissionAccess.Read, regKey)).Assert();
+ data = Microsoft.Win32.Registry.GetValue(regKey, valueName, null) as byte[];
+ if (data != null)
+ {
+ // We only used the persisted data from the registry for updates.
+ command = ControllerCommand.Update;
+ return true;
+ }
+#endif
+ }
+ else
+ {
+ if (filterData->Ptr != 0 && 0 < filterData->Size && filterData->Size <= 1024)
+ {
+ data = new byte[filterData->Size];
+ Marshal.Copy((IntPtr)filterData->Ptr, data, 0, data.Length);
+ }
+ command = (ControllerCommand)filterData->Type;
+ return true;
+ }
+
+ command = ControllerCommand.Update;
+ return false;
+ }
+
+ /// <summary>
+ /// IsEnabled, method used to test if provider is enabled
+ /// </summary>
+ public bool IsEnabled()
+ {
+ return m_enabled;
+ }
+
+ /// <summary>
+ /// IsEnabled, method used to test if event is enabled
+ /// </summary>
+ /// <param name="level">
+ /// Level to test
+ /// </param>
+ /// <param name="keywords">
+ /// Keyword to test
+ /// </param>
+ public bool IsEnabled(byte level, long keywords)
+ {
+ //
+ // If not enabled at all, return false.
+ //
+ if (!m_enabled)
+ {
+ return false;
+ }
+
+ // This also covers the case of Level == 0.
+ if ((level <= m_level) ||
+ (m_level == 0))
+ {
+
+ //
+ // Check if Keyword is enabled
+ //
+
+ if ((keywords == 0) ||
+ (((keywords & m_anyKeywordMask) != 0) &&
+ ((keywords & m_allKeywordMask) == m_allKeywordMask)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public static WriteEventErrorCode GetLastWriteEventError()
+ {
+ return s_returnCode;
+ }
+
+ //
+ // Helper function to set the last error on the thread
+ //
+ private static void SetLastError(int error)
+ {
+ switch (error)
+ {
+ case UnsafeNativeMethods.ManifestEtw.ERROR_ARITHMETIC_OVERFLOW:
+ case UnsafeNativeMethods.ManifestEtw.ERROR_MORE_DATA:
+ s_returnCode = WriteEventErrorCode.EventTooBig;
+ break;
+ case UnsafeNativeMethods.ManifestEtw.ERROR_NOT_ENOUGH_MEMORY:
+ s_returnCode = WriteEventErrorCode.NoFreeBuffers;
+ break;
+ }
+ }
+
+ // <SecurityKernel Critical="True" Ring="0">
+ // <UsesUnsafeCode Name="Local intptrPtr of type: IntPtr*" />
+ // <UsesUnsafeCode Name="Local intptrPtr of type: Int32*" />
+ // <UsesUnsafeCode Name="Local longptr of type: Int64*" />
+ // <UsesUnsafeCode Name="Local uintptr of type: UInt32*" />
+ // <UsesUnsafeCode Name="Local ulongptr of type: UInt64*" />
+ // <UsesUnsafeCode Name="Local charptr of type: Char*" />
+ // <UsesUnsafeCode Name="Local byteptr of type: Byte*" />
+ // <UsesUnsafeCode Name="Local shortptr of type: Int16*" />
+ // <UsesUnsafeCode Name="Local sbyteptr of type: SByte*" />
+ // <UsesUnsafeCode Name="Local ushortptr of type: UInt16*" />
+ // <UsesUnsafeCode Name="Local floatptr of type: Single*" />
+ // <UsesUnsafeCode Name="Local doubleptr of type: Double*" />
+ // <UsesUnsafeCode Name="Local boolptr of type: Boolean*" />
+ // <UsesUnsafeCode Name="Local guidptr of type: Guid*" />
+ // <UsesUnsafeCode Name="Local decimalptr of type: Decimal*" />
+ // <UsesUnsafeCode Name="Local booleanptr of type: Boolean*" />
+ // <UsesUnsafeCode Name="Parameter dataDescriptor of type: EventData*" />
+ // <UsesUnsafeCode Name="Parameter dataBuffer of type: Byte*" />
+ // </SecurityKernel>
+ [System.Security.SecurityCritical]
+ private static unsafe object EncodeObject(ref object data, ref EventData* dataDescriptor, ref byte* dataBuffer, ref uint totalEventSize)
+ /*++
+
+ Routine Description:
+
+ This routine is used by WriteEvent to unbox the object type and
+ to fill the passed in ETW data descriptor.
+
+ Arguments:
+
+ data - argument to be decoded
+
+ dataDescriptor - pointer to the descriptor to be filled (updated to point to the next empty entry)
+
+ dataBuffer - storage buffer for storing user data, needed because cant get the address of the object
+ (updated to point to the next empty entry)
+
+ Return Value:
+
+ null if the object is a basic type other than string or byte[]. String otherwise
+
+ --*/
+ {
+ Again:
+ dataDescriptor->Reserved = 0;
+
+ string sRet = data as string;
+ byte[] blobRet = null;
+
+ if (sRet != null)
+ {
+ dataDescriptor->Size = ((uint)sRet.Length + 1) * 2;
+ }
+ else if ((blobRet = data as byte[]) != null)
+ {
+ // first store array length
+ *(int*)dataBuffer = blobRet.Length;
+ dataDescriptor->Ptr = (ulong)dataBuffer;
+ dataDescriptor->Size = 4;
+ totalEventSize += dataDescriptor->Size;
+
+ // then the array parameters
+ dataDescriptor++;
+ dataBuffer += s_basicTypeAllocationBufferSize;
+ dataDescriptor->Size = (uint)blobRet.Length;
+ }
+ else if (data is IntPtr)
+ {
+ dataDescriptor->Size = (uint)sizeof(IntPtr);
+ IntPtr* intptrPtr = (IntPtr*)dataBuffer;
+ *intptrPtr = (IntPtr)data;
+ dataDescriptor->Ptr = (ulong)intptrPtr;
+ }
+ else if (data is int)
+ {
+ dataDescriptor->Size = (uint)sizeof(int);
+ int* intptr = (int*)dataBuffer;
+ *intptr = (int)data;
+ dataDescriptor->Ptr = (ulong)intptr;
+ }
+ else if (data is long)
+ {
+ dataDescriptor->Size = (uint)sizeof(long);
+ long* longptr = (long*)dataBuffer;
+ *longptr = (long)data;
+ dataDescriptor->Ptr = (ulong)longptr;
+ }
+ else if (data is uint)
+ {
+ dataDescriptor->Size = (uint)sizeof(uint);
+ uint* uintptr = (uint*)dataBuffer;
+ *uintptr = (uint)data;
+ dataDescriptor->Ptr = (ulong)uintptr;
+ }
+ else if (data is UInt64)
+ {
+ dataDescriptor->Size = (uint)sizeof(ulong);
+ UInt64* ulongptr = (ulong*)dataBuffer;
+ *ulongptr = (ulong)data;
+ dataDescriptor->Ptr = (ulong)ulongptr;
+ }
+ else if (data is char)
+ {
+ dataDescriptor->Size = (uint)sizeof(char);
+ char* charptr = (char*)dataBuffer;
+ *charptr = (char)data;
+ dataDescriptor->Ptr = (ulong)charptr;
+ }
+ else if (data is byte)
+ {
+ dataDescriptor->Size = (uint)sizeof(byte);
+ byte* byteptr = (byte*)dataBuffer;
+ *byteptr = (byte)data;
+ dataDescriptor->Ptr = (ulong)byteptr;
+ }
+ else if (data is short)
+ {
+ dataDescriptor->Size = (uint)sizeof(short);
+ short* shortptr = (short*)dataBuffer;
+ *shortptr = (short)data;
+ dataDescriptor->Ptr = (ulong)shortptr;
+ }
+ else if (data is sbyte)
+ {
+ dataDescriptor->Size = (uint)sizeof(sbyte);
+ sbyte* sbyteptr = (sbyte*)dataBuffer;
+ *sbyteptr = (sbyte)data;
+ dataDescriptor->Ptr = (ulong)sbyteptr;
+ }
+ else if (data is ushort)
+ {
+ dataDescriptor->Size = (uint)sizeof(ushort);
+ ushort* ushortptr = (ushort*)dataBuffer;
+ *ushortptr = (ushort)data;
+ dataDescriptor->Ptr = (ulong)ushortptr;
+ }
+ else if (data is float)
+ {
+ dataDescriptor->Size = (uint)sizeof(float);
+ float* floatptr = (float*)dataBuffer;
+ *floatptr = (float)data;
+ dataDescriptor->Ptr = (ulong)floatptr;
+ }
+ else if (data is double)
+ {
+ dataDescriptor->Size = (uint)sizeof(double);
+ double* doubleptr = (double*)dataBuffer;
+ *doubleptr = (double)data;
+ dataDescriptor->Ptr = (ulong)doubleptr;
+ }
+ else if (data is bool)
+ {
+ // WIN32 Bool is 4 bytes
+ dataDescriptor->Size = 4;
+ int* intptr = (int*)dataBuffer;
+ if (((bool)data))
+ {
+ *intptr = 1;
+ }
+ else
+ {
+ *intptr = 0;
+ }
+ dataDescriptor->Ptr = (ulong)intptr;
+ }
+ else if (data is Guid)
+ {
+ dataDescriptor->Size = (uint)sizeof(Guid);
+ Guid* guidptr = (Guid*)dataBuffer;
+ *guidptr = (Guid)data;
+ dataDescriptor->Ptr = (ulong)guidptr;
+ }
+ else if (data is decimal)
+ {
+ dataDescriptor->Size = (uint)sizeof(decimal);
+ decimal* decimalptr = (decimal*)dataBuffer;
+ *decimalptr = (decimal)data;
+ dataDescriptor->Ptr = (ulong)decimalptr;
+ }
+ else if (data is DateTime)
+ {
+ const long UTCMinTicks = 504911232000000000;
+ long dateTimeTicks = 0;
+ // We cannot translate dates sooner than 1/1/1601 in UTC.
+ // To avoid getting an ArgumentOutOfRangeException we compare with 1/1/1601 DateTime ticks
+ if (((DateTime)data).Ticks > UTCMinTicks)
+ dateTimeTicks = ((DateTime)data).ToFileTimeUtc();
+ dataDescriptor->Size = (uint)sizeof(long);
+ long* longptr = (long*)dataBuffer;
+ *longptr = dateTimeTicks;
+ dataDescriptor->Ptr = (ulong)longptr;
+ }
+ else
+ {
+ if (data is System.Enum)
+ {
+ Type underlyingType = Enum.GetUnderlyingType(data.GetType());
+ if (underlyingType == typeof(int))
+ {
+#if !ES_BUILD_PCL
+ data = ((IConvertible)data).ToInt32(null);
+#else
+ data = (int)data;
+#endif
+ goto Again;
+ }
+ else if (underlyingType == typeof(long))
+ {
+#if !ES_BUILD_PCL
+ data = ((IConvertible)data).ToInt64(null);
+#else
+ data = (long)data;
+#endif
+ goto Again;
+ }
+ }
+
+ // To our eyes, everything else is a just a string
+ if (data == null)
+ sRet = "";
+ else
+ sRet = data.ToString();
+ dataDescriptor->Size = ((uint)sRet.Length + 1) * 2;
+ }
+
+ totalEventSize += dataDescriptor->Size;
+
+ // advance buffers
+ dataDescriptor++;
+ dataBuffer += s_basicTypeAllocationBufferSize;
+
+ return (object)sRet ?? (object)blobRet;
+ }
+
+ /// <summary>
+ /// WriteEvent, method to write a parameters with event schema properties
+ /// </summary>
+ /// <param name="eventDescriptor">
+ /// Event Descriptor for this event.
+ /// </param>
+ /// <param name="activityID">
+ /// A pointer to the activity ID GUID to log
+ /// </param>
+ /// <param name="childActivityID">
+ /// childActivityID is marked as 'related' to the current activity ID.
+ /// </param>
+ /// <param name="eventPayload">
+ /// Payload for the ETW event.
+ /// </param>
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
+ // <UsesUnsafeCode Name="Local dataBuffer of type: Byte*" />
+ // <UsesUnsafeCode Name="Local pdata of type: Char*" />
+ // <UsesUnsafeCode Name="Local userData of type: EventData*" />
+ // <UsesUnsafeCode Name="Local userDataPtr of type: EventData*" />
+ // <UsesUnsafeCode Name="Local currentBuffer of type: Byte*" />
+ // <UsesUnsafeCode Name="Local v0 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v1 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v2 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v3 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v4 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v5 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v6 of type: Char*" />
+ // <UsesUnsafeCode Name="Local v7 of type: Char*" />
+ // <ReferencesCritical Name="Method: EncodeObject(Object&, EventData*, Byte*):String" Ring="1" />
+ // </SecurityKernel>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Performance-critical code")]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ [System.Security.SecurityCritical]
+ internal unsafe bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, params object[] eventPayload)
+ {
+ int status = 0;
+
+ if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
+ {
+ int argCount = 0;
+ unsafe
+ {
+ argCount = eventPayload.Length;
+
+ if (argCount > s_etwMaxNumberArguments)
+ {
+ s_returnCode = WriteEventErrorCode.TooManyArgs;
+ return false;
+ }
+
+ uint totalEventSize = 0;
+ int index;
+ int refObjIndex = 0;
+ List<int> refObjPosition = new List<int>(s_etwAPIMaxRefObjCount);
+ List<object> dataRefObj = new List<object>(s_etwAPIMaxRefObjCount);
+ EventData* userData = stackalloc EventData[2 * argCount];
+ EventData* userDataPtr = (EventData*)userData;
+ byte* dataBuffer = stackalloc byte[s_basicTypeAllocationBufferSize * 2 * argCount]; // Assume 16 chars for non-string argument
+ byte* currentBuffer = dataBuffer;
+
+ //
+ // The loop below goes through all the arguments and fills in the data
+ // descriptors. For strings save the location in the dataString array.
+ // Calculates the total size of the event by adding the data descriptor
+ // size value set in EncodeObject method.
+ //
+ bool hasNonStringRefArgs = false;
+ for (index = 0; index < eventPayload.Length; index++)
+ {
+ if (eventPayload[index] != null)
+ {
+ object supportedRefObj;
+ supportedRefObj = EncodeObject(ref eventPayload[index], ref userDataPtr, ref currentBuffer, ref totalEventSize);
+
+ if (supportedRefObj != null)
+ {
+ // EncodeObject advanced userDataPtr to the next empty slot
+ int idx = (int)(userDataPtr - userData - 1);
+ if (!(supportedRefObj is string))
+ {
+ if (eventPayload.Length + idx + 1 - index > s_etwMaxNumberArguments)
+ {
+ s_returnCode = WriteEventErrorCode.TooManyArgs;
+ return false;
+ }
+ hasNonStringRefArgs = true;
+ }
+ dataRefObj.Add(supportedRefObj);
+ refObjPosition.Add(idx);
+ refObjIndex++;
+ }
+ }
+ else
+ {
+ s_returnCode = WriteEventErrorCode.NullInput;
+ return false;
+ }
+ }
+
+ // update argCount based on actual number of arguments written to 'userData'
+ argCount = (int)(userDataPtr - userData);
+
+ if (totalEventSize > s_traceEventMaximumSize)
+ {
+ s_returnCode = WriteEventErrorCode.EventTooBig;
+ return false;
+ }
+
+ // the optimized path (using "fixed" instead of allocating pinned GCHandles
+ if (!hasNonStringRefArgs && (refObjIndex < s_etwAPIMaxRefObjCount))
+ {
+ // Fast path: at most 8 string arguments
+
+ // ensure we have at least s_etwAPIMaxStringCount in dataString, so that
+ // the "fixed" statement below works
+ while (refObjIndex < s_etwAPIMaxRefObjCount)
+ {
+ dataRefObj.Add(null);
+ ++refObjIndex;
+ }
+
+ //
+ // now fix any string arguments and set the pointer on the data descriptor
+ //
+ fixed (char* v0 = (string)dataRefObj[0], v1 = (string)dataRefObj[1], v2 = (string)dataRefObj[2], v3 = (string)dataRefObj[3],
+ v4 = (string)dataRefObj[4], v5 = (string)dataRefObj[5], v6 = (string)dataRefObj[6], v7 = (string)dataRefObj[7])
+ {
+ userDataPtr = (EventData*)userData;
+ if (dataRefObj[0] != null)
+ {
+ userDataPtr[refObjPosition[0]].Ptr = (ulong)v0;
+ }
+ if (dataRefObj[1] != null)
+ {
+ userDataPtr[refObjPosition[1]].Ptr = (ulong)v1;
+ }
+ if (dataRefObj[2] != null)
+ {
+ userDataPtr[refObjPosition[2]].Ptr = (ulong)v2;
+ }
+ if (dataRefObj[3] != null)
+ {
+ userDataPtr[refObjPosition[3]].Ptr = (ulong)v3;
+ }
+ if (dataRefObj[4] != null)
+ {
+ userDataPtr[refObjPosition[4]].Ptr = (ulong)v4;
+ }
+ if (dataRefObj[5] != null)
+ {
+ userDataPtr[refObjPosition[5]].Ptr = (ulong)v5;
+ }
+ if (dataRefObj[6] != null)
+ {
+ userDataPtr[refObjPosition[6]].Ptr = (ulong)v6;
+ }
+ if (dataRefObj[7] != null)
+ {
+ userDataPtr[refObjPosition[7]].Ptr = (ulong)v7;
+ }
+
+ status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+ }
+ }
+ else
+ {
+ // Slow path: use pinned handles
+ userDataPtr = (EventData*)userData;
+
+ GCHandle[] rgGCHandle = new GCHandle[refObjIndex];
+ for (int i = 0; i < refObjIndex; ++i)
+ {
+ // below we still use "fixed" to avoid taking dependency on the offset of the first field
+ // in the object (the way we would need to if we used GCHandle.AddrOfPinnedObject)
+ rgGCHandle[i] = GCHandle.Alloc(dataRefObj[i], GCHandleType.Pinned);
+ if (dataRefObj[i] is string)
+ {
+ fixed (char* p = (string)dataRefObj[i])
+ userDataPtr[refObjPosition[i]].Ptr = (ulong)p;
+ }
+ else
+ {
+ fixed (byte* p = (byte[])dataRefObj[i])
+ userDataPtr[refObjPosition[i]].Ptr = (ulong)p;
+ }
+ }
+
+ status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, argCount, userData);
+
+ for (int i = 0; i < refObjIndex; ++i)
+ {
+ rgGCHandle[i].Free();
+ }
+ }
+ }
+ }
+
+ if (status != 0)
+ {
+ SetLastError((int)status);
+ return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// WriteEvent, method to be used by generated code on a derived class
+ /// </summary>
+ /// <param name="eventDescriptor">
+ /// Event Descriptor for this event.
+ /// </param>
+ /// <param name="activityID">
+ /// A pointer to the activity ID to log
+ /// </param>
+ /// <param name="childActivityID">
+ /// If this event is generating a child activity (WriteEventTransfer related activity) this is child activity
+ /// This can be null for events that do not generate a child activity.
+ /// </param>
+ /// <param name="dataCount">
+ /// number of event descriptors
+ /// </param>
+ /// <param name="data">
+ /// pointer do the event data
+ /// </param>
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.ManifestEtw.EventWrite(System.Int64,EventDescriptor&,System.UInt32,System.Void*):System.UInt32" />
+ // </SecurityKernel>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ [System.Security.SecurityCritical]
+ internal unsafe protected bool WriteEvent(ref EventDescriptor eventDescriptor, Guid* activityID, Guid* childActivityID, int dataCount, IntPtr data)
+ {
+ if (childActivityID != null)
+ {
+ // activity transfers are supported only for events that specify the Send or Receive opcode
+ Contract.Assert((EventOpcode)eventDescriptor.Opcode == EventOpcode.Send ||
+ (EventOpcode)eventDescriptor.Opcode == EventOpcode.Receive ||
+ (EventOpcode)eventDescriptor.Opcode == EventOpcode.Start ||
+ (EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
+ }
+
+ int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
+
+ if (status != 0)
+ {
+ SetLastError(status);
+ return false;
+ }
+ return true;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
+ [System.Security.SecurityCritical]
+ internal unsafe bool WriteEventRaw(
+ ref EventDescriptor eventDescriptor,
+ Guid* activityID,
+ Guid* relatedActivityID,
+ int dataCount,
+ IntPtr data)
+ {
+ int status;
+
+ status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ m_regHandle,
+ ref eventDescriptor,
+ activityID,
+ relatedActivityID,
+ dataCount,
+ (EventData*)data);
+
+ if (status != 0)
+ {
+ SetLastError(status);
+ return false;
+ }
+ return true;
+ }
+
+
+ // These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
+ // either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
+ [SecurityCritical]
+ private unsafe uint EventRegister(ref Guid providerId, UnsafeNativeMethods.ManifestEtw.EtwEnableCallback enableCallback)
+ {
+ m_providerId = providerId;
+ m_etwCallback = enableCallback;
+ return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
+ }
+
+ [SecurityCritical]
+ private uint EventUnregister()
+ {
+ uint status = UnsafeNativeMethods.ManifestEtw.EventUnregister(m_regHandle);
+ m_regHandle = 0;
+ return status;
+ }
+
+ static int[] nibblebits = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ private static int bitcount(uint n)
+ {
+ int count = 0;
+ for (; n != 0; n = n >> 4)
+ count += nibblebits[n & 0x0f];
+ return count;
+ }
+ private static int bitindex(uint n)
+ {
+ Contract.Assert(bitcount(n) == 1);
+ int idx = 0;
+ while ((n & (1 << idx)) == 0)
+ idx++;
+ return idx;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs
new file mode 100644
index 0000000000..8c2edfdec2
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs
@@ -0,0 +1,6962 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
+// It is available from http://www.codeplex.com/hyperAddin
+#if !PLATFORM_UNIX
+
+#define FEATURE_MANAGED_ETW
+
+#if !ES_BUILD_STANDALONE && !CORECLR && !PROJECTN
+#define FEATURE_ACTIVITYSAMPLING
+#endif // !ES_BUILD_STANDALONE
+
+#endif // !PLATFORM_UNIX
+
+#if ES_BUILD_STANDALONE
+#define FEATURE_MANAGED_ETW_CHANNELS
+// #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+#endif
+
+/* 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.
+//
+// Basic Model
+//
+// PRINCIPLE: EventSource - ETW decoupling
+//
+// Conceptually and EventSouce is something takes event logging data from the source methods
+// To the EventListener that can subscribe them. Note that CONCEPTUALLY EVENTSOURCES DON'T
+// KNOW ABOUT ETW!. The MODEL of the system is that there is a special EventListern Which
+// we will call the EtwEventListener, that forwards commands from ETW to EventSources and
+// listeners to the EventSources and forwards on those events to ETW. THus the model should
+// be that you DON'T NEED ETW.
+//
+// Now in actual practice, EventSouce have rather intimate knowledge of ETW and send events
+// to it directly, but this can be VIEWED AS AN OPTIMIATION.
+//
+// Basic Event Data Flow:
+//
+// There are two ways for event Data to enter the system
+// 1) WriteEvent* and friends. This is called the 'contract' based approach because
+// you write a method per event which forms a contract that is know at compile time.
+// In this scheme each event is given an EVENTID (small integer). which is its identity
+// 2) Write<T> methods. This is called the 'dynamic' approach because new events
+// can be created on the fly. Event identity is determined by the event NAME, and these
+// are not quite as efficient at runtime since you have at least a hash table lookup
+// on every event write.
+//
+// EventSource-EventListener transfer fully support both ways of writing events (either contract
+// based (WriteEvent*) or dynamic (Write<T>). Both way fully support the same set of data
+// types. It is suggested, however, that you use the contract based approach when the event scheme
+// is known at compile time (that is whenever possible). It is more efficient, but more importantly
+// it makes the contract very explicit, and centralizes all policy about logging. These are good
+// things. The Write<T> API is really meant for more ad-hoc
+//
+// Allowed Data.
+//
+// Note that EventSource-EventListeners have a conceptual serialization-deserialization that happens
+// during the transfer. In particular object identity is not preserved, some objects are morphed,
+// and not all data types are supported. In particular you can pass
+//
+// A Valid type to log to an EventSource include
+// * Primitive data types
+// * IEnumerable<T> of valid types T (this include arrays) (* New for V4.6)
+// * Explicitly Opted in class or struct with public property Getters over Valid types. (* New for V4.6)
+//
+// This set of types is roughly a generalization of JSON support (Basically primitives, bags, and arrays).
+//
+// Explicitly allowed structs include (* New for V4.6)
+// * Marked with the EventData attribute
+// * implicitly defined (e.g the C# new {x = 3, y = 5} syntax)
+// * KeyValuePair<K,V> (thus dictionaries can be passed since they are an IEnumerable of KeyValuePair)
+//
+// When classes are returned in an EventListener, what is returned is something that implements
+// IDictionary<string, T>. Thus when objects are passed to an EventSource they are transformed
+// into a key-value bag (the IDictionary<string, T>) for consumption in the listener. These
+// are obvious NOT the original objects.
+//
+// ETWserialization formats:
+//
+// As mentioned conceptually EventSource's send data to EventListeners and there is a conceptual
+// copy/morph of that data as described above. In addition the .NET framework supports a conceptual
+// ETWListener that will send the data to then ETW stream. If you use this feature, the data needs
+// to be serialized in a way that ETW supports. ETW supports the following serialization formats
+//
+// 1) Manifest Based serialization.
+// 2) SelfDescribing serialization (TraceLogging style in the TraceLogging directory)
+//
+// A key factor is that the Write<T> method, which support on the fly definition of events, can't
+// support the manifest based serialization because the manifest needs the schema of all events
+// to be known before any events are emitted. This implies the following
+//
+// If you use Write<T> and the output goes to ETW it will use the SelfDescribing format.
+// If you use the EventSource(string) constructor for an eventSource (in which you don't
+// create a subclass), the default is also to use Self-Describing serialization. In addition
+// you can use the EventSoruce(EventSourceSettings) constructor to also explicitly specify
+// Self-Describing serialization format. These effect the WriteEvent* APIs going to ETW.
+//
+// Note that none of this ETW serialization logic affects EventListeners. Only the ETW listener.
+//
+// *************************************************************************************
+// *** INTERNALS: Event Propagation
+//
+// Data enters the system either though
+//
+// 1) A user defined method in the user defined subclass of EventSource which calls
+// A) A typesafe type specific overload of WriteEvent(ID, ...) e.g. WriteEvent(ID, string, string)
+// * which calls into the unsafe WriteEventCore(ID COUNT EventData*) WriteEventWithRelatedActivityIdCore()
+// B) The typesafe overload WriteEvent(ID, object[]) which calls the private helper WriteEventVarargs(ID, Guid* object[])
+// C) Directly into the unsafe WriteEventCore(ID, COUNT EventData*) or WriteEventWithRelatedActivityIdCore()
+//
+// All event data eventually flows to one of
+// * WriteEventWithRelatedActivityIdCore(ID, Guid*, COUNT, EventData*)
+// * WriteEventVarargs(ID, Guid*, object[])
+//
+// 2) A call to one of the overloads of Write<T>. All these overloads end up in
+// * WriteImpl<T>(EventName, Options, Data, Guid*, Guid*)
+//
+// On output there are the following routines
+// Writing to all listeners that are NOT ETW, we have the following routines
+// * WriteToAllListeners(ID, Guid*, COUNT, EventData*)
+// * WriteToAllListeners(ID, Guid*, object[])
+// * WriteToAllListeners(NAME, Guid*, EventPayload)
+//
+// EventPayload is the internal type that implements the IDictionary<string, object> interface
+// The EventListeners will pass back for serialized classes for nested object, but
+// WriteToAllListeners(NAME, Guid*, EventPayload) unpacks this uses the fields as if they
+// were parameters to a method.
+//
+// The first two are used for the WriteEvent* case, and the later is used for the Write<T> case.
+//
+// Writing to ETW, Manifest Based
+// EventProvider.WriteEvent(EventDescriptor, Guid*, COUNT, EventData*)
+// EventProvider.WriteEvent(EventDescriptor, Guid*, object[])
+// Writing to ETW, Self-Describing format
+// WriteMultiMerge(NAME, Options, Types, EventData*)
+// WriteMultiMerge(NAME, Options, Types, object[])
+// WriteImpl<T> has logic that knows how to serialize (like WriteMultiMerge) but also knows
+// will write it to
+//
+// All ETW writes eventually call
+// EventWriteTransfer (native PINVOKE wrapper)
+// EventWriteTransferWrapper (fixes compat problem if you pass null as the related activityID)
+// EventProvider.WriteEventRaw - sets last error
+// EventSource.WriteEventRaw - Does EventSource exception handling logic
+// WriteMultiMerge
+// WriteImpl<T>
+// EventProvider.WriteEvent(EventDescriptor, Guid*, COUNT, EventData*)
+// EventProvider.WriteEvent(EventDescriptor, Guid*, object[])
+//
+// Serialization: We have a bit of a hodge-podge of serializers right now. Only the one for ETW knows
+// how to deal with nested classes or arrays. I will call this serializer the 'TypeInfo' serializer
+// since it is the TraceLoggingTypeInfo structure that knows how to do this. Effectively for a type you
+// can call one of these
+// WriteMetadata - transforms the type T into serialization meta data blob for that type
+// WriteObjectData - transforms an object of T into serialization meta data blob for that type
+// GetData - transforms an object of T into its deserialized form suitable for passing to EventListener.
+// The first two are used to serialize something for ETW. The second one is used to transform the object
+// for use by the EventListener. We also have a 'DecodeObject' method that will take a EventData* and
+// deserialize to pass to an EventListener, but it only works on primitive types (types supported in version V4.5).
+//
+// It is an important observation that while EventSource does support users directly calling with EventData*
+// blobs, we ONLY support that for the primitive types (V4.5 level support). Thus while there is a EventData*
+// path through the system it is only for some types. The object[] path is the more general (but less efficient) path.
+//
+// TODO There is cleanup needed There should be no divergence until WriteEventRaw.
+//
+// TODO: We should have a single choke point (right now we always have this parallel EventData* and object[] path. This
+// was historical (at one point we tried to pass object directly from EventSoruce to EventListener. That was always
+// fragile and a compatibility headache, but we have finally been forced into the idea that there is always a transformation.
+// This allows us to use the EventData* form to be the canonical data format in the low level APIs. This also gives us the
+// opportunity to expose this format to EventListeners in the future.
+//
+using System;
+using System.Runtime.CompilerServices;
+#if FEATURE_ACTIVITYSAMPLING
+using System.Collections.Concurrent;
+#endif
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Reflection;
+using System.Resources;
+using System.Security;
+using System.Security.Permissions;
+
+using System.Text;
+using System.Threading;
+using Microsoft.Win32;
+
+#if ES_BUILD_STANDALONE
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
+#else
+using System.Threading.Tasks;
+#endif
+
+using Microsoft.Reflection;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// This class is meant to be inherited by a user-defined event source in order to define a managed
+ /// ETW provider. Please See DESIGN NOTES above for the internal architecture.
+ /// The minimal definition of an EventSource simply specifies a number of ETW event methods that
+ /// call one of the EventSource.WriteEvent overloads, <see cref="EventSource.WriteEventCore"/>,
+ /// or <see cref="EventSource.WriteEventWithRelatedActivityIdCore"/> to log them. This functionality
+ /// is sufficient for many users.
+ /// <para>
+ /// To achieve more control over the ETW provider manifest exposed by the event source type, the
+ /// [<see cref="EventAttribute"/>] attributes can be specified for the ETW event methods.
+ /// </para><para>
+ /// For very advanced EventSources, it is possible to intercept the commands being given to the
+ /// eventSource and change what filtering is done (see EventListener.EnableEvents and
+ /// <see cref="EventListener.DisableEvents"/>) or cause actions to be performed by the eventSource,
+ /// e.g. dumping a data structure (see EventSource.SendCommand and
+ /// <see cref="EventSource.OnEventCommand"/>).
+ /// </para><para>
+ /// The eventSources can be turned on with Windows ETW controllers (e.g. logman), immediately.
+ /// It is also possible to control and intercept the data dispatcher programmatically. See
+ /// <see cref="EventListener"/> for more.
+ /// </para>
+ /// </summary>
+ /// <remarks>
+ /// This is a minimal definition for a custom event source:
+ /// <code>
+ /// [EventSource(Name="Samples-Demos-Minimal")]
+ /// sealed class MinimalEventSource : EventSource
+ /// {
+ /// public static MinimalEventSource Log = new MinimalEventSource();
+ /// public void Load(long ImageBase, string Name) { WriteEvent(1, ImageBase, Name); }
+ /// public void Unload(long ImageBase) { WriteEvent(2, ImageBase); }
+ /// private MinimalEventSource() {}
+ /// }
+ /// </code>
+ /// </remarks>
+ public partial class EventSource : IDisposable
+ {
+
+#if FEATURE_EVENTSOURCE_XPLAT
+ private static readonly EventListener persistent_Xplat_Listener = XplatEventLogger.InitializePersistentListener();
+#endif //FEATURE_EVENTSOURCE_XPLAT
+
+ /// <summary>
+ /// The human-friendly name of the eventSource. It defaults to the simple name of the class
+ /// </summary>
+ public string Name { get { return m_name; } }
+ /// <summary>
+ /// Every eventSource is assigned a GUID to uniquely identify it to the system.
+ /// </summary>
+ public Guid Guid { get { return m_guid; } }
+
+ /// <summary>
+ /// Returns true if the eventSource has been enabled at all. This is the prefered test
+ /// to be performed before a relatively expensive EventSource operation.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ public bool IsEnabled()
+ {
+ return m_eventSourceEnabled;
+ }
+
+ /// <summary>
+ /// Returns true if events with greater than or equal 'level' and have one of 'keywords' set are enabled.
+ ///
+ /// Note that the result of this function is only an approximation on whether a particular
+ /// event is active or not. It is only meant to be used as way of avoiding expensive
+ /// computation for logging when logging is not on, therefore it sometimes returns false
+ /// positives (but is always accurate when returning false). EventSources are free to
+ /// have additional filtering.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ public bool IsEnabled(EventLevel level, EventKeywords keywords)
+ {
+ return IsEnabled(level, keywords, EventChannel.None);
+ }
+
+ /// <summary>
+ /// Returns true if events with greater than or equal 'level' and have one of 'keywords' set are enabled, or
+ /// if 'keywords' specifies a channel bit for a channel that is enabled.
+ ///
+ /// Note that the result of this function only an approximation on whether a particular
+ /// event is active or not. It is only meant to be used as way of avoiding expensive
+ /// computation for logging when logging is not on, therefore it sometimes returns false
+ /// positives (but is always accurate when returning false). EventSources are free to
+ /// have additional filtering.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ public bool IsEnabled(EventLevel level, EventKeywords keywords, EventChannel channel)
+ {
+ if (!m_eventSourceEnabled)
+ return false;
+
+ if (!IsEnabledCommon(m_eventSourceEnabled, m_level, m_matchAnyKeyword, level, keywords, channel))
+ return false;
+
+#if !FEATURE_ACTIVITYSAMPLING
+
+ return true;
+
+#else // FEATURE_ACTIVITYSAMPLING
+
+ return true;
+
+#if OPTIMIZE_IS_ENABLED
+ //================================================================================
+ // 2013/03/06 - The code below is a possible optimization for IsEnabled(level, kwd)
+ // in case activity tracing/sampling is enabled. The added complexity of this
+ // code however weighs against having it "on" until we know it's really needed.
+ // For now we'll have this #ifdef-ed out in case we see evidence this is needed.
+ //================================================================================
+
+ // At this point we believe the event is enabled, however we now need to check
+ // if we filter because of activity
+
+ // Optimization, all activity filters also register a delegate here, so if there
+ // is no delegate, we know there are no activity filters, which means that there
+ // is no additional filtering, which means that we can return true immediately.
+ if (s_activityDying == null)
+ return true;
+
+ // if there's at least one legacy ETW listener we can't filter this
+ if (m_legacySessions != null && m_legacySessions.Count > 0)
+ return true;
+
+ // if any event ID that triggers a new activity, or "transfers" activities
+ // is covered by 'keywords' we can't filter this
+ if (unchecked(((long)keywords & m_keywordTriggers)) != 0)
+ return true;
+
+ // See if all listeners have activity filters that would block the event.
+ for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId)
+ {
+ EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId];
+ if (etwSession == null)
+ continue;
+
+ ActivityFilter activityFilter = etwSession.m_activityFilter;
+ if (activityFilter == null ||
+ ActivityFilter.GetFilter(activityFilter, this) == null)
+ {
+ // No activity filter for ETW, if event is active for ETW, we can't filter.
+ for (int i = 0; i < m_eventData.Length; i++)
+ if (m_eventData[i].EnabledForETW)
+ return true;
+ }
+ else if (ActivityFilter.IsCurrentActivityActive(activityFilter))
+ return true;
+ }
+
+ // for regular event listeners
+ var curDispatcher = m_Dispatchers;
+ while (curDispatcher != null)
+ {
+ ActivityFilter activityFilter = curDispatcher.m_Listener.m_activityFilter;
+ if (activityFilter == null)
+ {
+ // See if any event is enabled.
+ for (int i = 0; i < curDispatcher.m_EventEnabled.Length; i++)
+ if (curDispatcher.m_EventEnabled[i])
+ return true;
+ }
+ else if (ActivityFilter.IsCurrentActivityActive(activityFilter))
+ return true;
+ curDispatcher = curDispatcher.m_Next;
+ }
+
+ // Every listener has an activity filter that is blocking writing the event,
+ // thus the event is not enabled.
+ return false;
+#endif // OPTIMIZE_IS_ENABLED
+
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+
+ /// <summary>
+ /// Returns the settings for the event source instance
+ /// </summary>
+ public EventSourceSettings Settings
+ {
+ get { return m_config; }
+ }
+
+ // Manifest support
+ /// <summary>
+ /// Returns the GUID that uniquely identifies the eventSource defined by 'eventSourceType'.
+ /// This API allows you to compute this without actually creating an instance of the EventSource.
+ /// It only needs to reflect over the type.
+ /// </summary>
+ public static Guid GetGuid(Type eventSourceType)
+ {
+ if (eventSourceType == null)
+ throw new ArgumentNullException(nameof(eventSourceType));
+ Contract.EndContractBlock();
+
+ EventSourceAttribute attrib = (EventSourceAttribute)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute));
+ string name = eventSourceType.Name;
+ if (attrib != null)
+ {
+ if (attrib.Guid != null)
+ {
+ Guid g = Guid.Empty;
+#if !ES_BUILD_AGAINST_DOTNET_V35
+ if (Guid.TryParse(attrib.Guid, out g))
+ return g;
+#else
+ try { return new Guid(attrib.Guid); }
+ catch (Exception) { }
+#endif
+ }
+
+ if (attrib.Name != null)
+ name = attrib.Name;
+ }
+
+ if (name == null)
+ {
+ throw new ArgumentException(Resources.GetResourceString("Argument_InvalidTypeName"), nameof(eventSourceType));
+ }
+ return GenerateGuidFromName(name.ToUpperInvariant()); // Make it case insensitive.
+ }
+ /// <summary>
+ /// Returns the official ETW Provider name for the eventSource defined by 'eventSourceType'.
+ /// This API allows you to compute this without actually creating an instance of the EventSource.
+ /// It only needs to reflect over the type.
+ /// </summary>
+ public static string GetName(Type eventSourceType)
+ {
+ return GetName(eventSourceType, EventManifestOptions.None);
+ }
+
+ /// <summary>
+ /// Returns a string of the XML manifest associated with the eventSourceType. The scheme for this XML is
+ /// documented at in EventManifest Schema http://msdn.microsoft.com/en-us/library/aa384043(VS.85).aspx.
+ /// This is the preferred way of generating a manifest to be embedded in the ETW stream as it is fast and
+ /// the fact that it only includes localized entries for the current UI culture is an acceptable tradeoff.
+ /// </summary>
+ /// <param name="eventSourceType">The type of the event source class for which the manifest is generated</param>
+ /// <param name="assemblyPathToIncludeInManifest">The manifest XML fragment contains the string name of the DLL name in
+ /// which it is embedded. This parameter specifies what name will be used</param>
+ /// <returns>The XML data string</returns>
+ public static string GenerateManifest(Type eventSourceType, string assemblyPathToIncludeInManifest)
+ {
+ return GenerateManifest(eventSourceType, assemblyPathToIncludeInManifest, EventManifestOptions.None);
+ }
+ /// <summary>
+ /// Returns a string of the XML manifest associated with the eventSourceType. The scheme for this XML is
+ /// documented at in EventManifest Schema http://msdn.microsoft.com/en-us/library/aa384043(VS.85).aspx.
+ /// Pass EventManifestOptions.AllCultures when generating a manifest to be registered on the machine. This
+ /// ensures that the entries in the event log will be "optimally" localized.
+ /// </summary>
+ /// <param name="eventSourceType">The type of the event source class for which the manifest is generated</param>
+ /// <param name="assemblyPathToIncludeInManifest">The manifest XML fragment contains the string name of the DLL name in
+ /// which it is embedded. This parameter specifies what name will be used</param>
+ /// <param name="flags">The flags to customize manifest generation. If flags has bit OnlyIfNeededForRegistration specified
+ /// this returns null when the eventSourceType does not require explicit registration</param>
+ /// <returns>The XML data string or null</returns>
+ public static string GenerateManifest(Type eventSourceType, string assemblyPathToIncludeInManifest, EventManifestOptions flags)
+ {
+ if (eventSourceType == null)
+ throw new ArgumentNullException(nameof(eventSourceType));
+ Contract.EndContractBlock();
+
+ byte[] manifestBytes = EventSource.CreateManifestAndDescriptors(eventSourceType, assemblyPathToIncludeInManifest, null, flags);
+ return (manifestBytes == null) ? null : Encoding.UTF8.GetString(manifestBytes, 0, manifestBytes.Length);
+ }
+
+ // EventListener support
+ /// <summary>
+ /// returns a list (IEnumerable) of all sources in the appdomain). EventListeners typically need this.
+ /// </summary>
+ /// <returns></returns>
+ public static IEnumerable<EventSource> GetSources()
+ {
+ var ret = new List<EventSource>();
+ lock (EventListener.EventListenersLock)
+ {
+ foreach (WeakReference eventSourceRef in EventListener.s_EventSources)
+ {
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource != null && !eventSource.IsDisposed)
+ ret.Add(eventSource);
+ }
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Send a command to a particular EventSource identified by 'eventSource'.
+ /// Calling this routine simply forwards the command to the EventSource.OnEventCommand
+ /// callback. What the EventSource does with the command and its arguments are from
+ /// that point EventSource-specific.
+ /// </summary>
+ /// <param name="eventSource">The instance of EventSource to send the command to</param>
+ /// <param name="command">A positive user-defined EventCommand, or EventCommand.SendManifest</param>
+ /// <param name="commandArguments">A set of (name-argument, value-argument) pairs associated with the command</param>
+ public static void SendCommand(EventSource eventSource, EventCommand command, IDictionary<string, string> commandArguments)
+ {
+ if (eventSource == null)
+ throw new ArgumentNullException(nameof(eventSource));
+
+ // User-defined EventCommands should not conflict with the reserved commands.
+ if ((int)command <= (int)EventCommand.Update && (int)command != (int)EventCommand.SendManifest)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidCommand"), nameof(command));
+ }
+
+ eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
+ }
+
+#if !ES_BUILD_STANDALONE
+ /// <summary>
+ /// This property allows EventSource code to appropriately handle as "different"
+ /// activities started on different threads that have not had an activity created on them.
+ /// </summary>
+ internal static Guid InternalCurrentThreadActivityId
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+ Guid retval = CurrentThreadActivityId;
+ if (retval == Guid.Empty)
+ {
+ retval = FallbackActivityId;
+ }
+ return retval;
+ }
+ }
+
+ internal static Guid FallbackActivityId
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+#pragma warning disable 612, 618
+ int threadID = AppDomain.GetCurrentThreadId();
+
+ // Managed thread IDs are more aggressively re-used than native thread IDs,
+ // so we'll use the latter...
+ return new Guid(unchecked((uint)threadID),
+ unchecked((ushort)s_currentPid), unchecked((ushort)(s_currentPid >> 16)),
+ 0x94, 0x1b, 0x87, 0xd5, 0xa6, 0x5c, 0x36, 0x64);
+#pragma warning restore 612, 618
+ }
+ }
+#endif // !ES_BUILD_STANDALONE
+
+ // Error APIs. (We don't throw by default, but you can probe for status)
+ /// <summary>
+ /// Because
+ ///
+ /// 1) Logging is often optional and thus should not generate fatal errors (exceptions)
+ /// 2) EventSources are often initialized in class constructors (which propagate exceptions poorly)
+ ///
+ /// The event source constructor does not throw exceptions. Instead we remember any exception that
+ /// was generated (it is also logged to Trace.WriteLine).
+ /// </summary>
+ public Exception ConstructionException { get { return m_constructionException; } }
+
+ /// <summary>
+ /// EventSources can have arbitrary string key-value pairs associated with them called Traits.
+ /// These traits are not interpreted by the EventSource but may be interpreted by EventListeners
+ /// (e.g. like the built in ETW listener). These traits are specififed at EventSource
+ /// construction time and can be retrieved by using this GetTrait API.
+ /// </summary>
+ /// <param name="key">The key to look up in the set of key-value pairs passed to the EventSource constructor</param>
+ /// <returns>The value string associated iwth key. Will return null if there is no such key.</returns>
+ public string GetTrait(string key)
+ {
+ if (m_traits != null)
+ {
+ for (int i = 0; i < m_traits.Length - 1; i += 2)
+ {
+ if (m_traits[i] == key)
+ return m_traits[i + 1];
+ }
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Displays the name and GUID for the eventSource for debugging purposes.
+ /// </summary>
+ public override string ToString()
+ {
+ return Resources.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
+ /// no parameters. The ETW provider name and GUID of the EventSource are determined by the EventSource
+ /// custom attribute (so you can determine these things declaratively). If the GUID for the eventSource
+ /// is not specified in the EventSourceAttribute (recommended), it is Generated by hashing the name.
+ /// If the ETW provider name of the EventSource is not given, the name of the EventSource class is used as
+ /// the ETW provider name.
+ /// </summary>
+ protected EventSource()
+ : this(EventSourceSettings.EtwManifestEventFormat)
+ {
+ }
+
+ /// <summary>
+ /// By default calling the 'WriteEvent' methods do NOT throw on errors (they silently discard the event).
+ /// This is because in most cases users assume logging is not 'precious' and do NOT wish to have logging failures
+ /// crash the program. However for those applications where logging is 'precious' and if it fails the caller
+ /// wishes to react, setting 'throwOnEventWriteErrors' will cause an exception to be thrown if WriteEvent
+ /// fails. Note the fact that EventWrite succeeds does not necessarily mean that the event reached its destination
+ /// only that operation of writing it did not fail. These EventSources will not generate self-describing ETW events.
+ ///
+ /// For compatibility only use the EventSourceSettings.ThrowOnEventWriteErrors flag instead.
+ /// </summary>
+ // [Obsolete("Use the EventSource(EventSourceSettings) overload")]
+ protected EventSource(bool throwOnEventWriteErrors)
+ : this(EventSourceSettings.EtwManifestEventFormat | (throwOnEventWriteErrors ? EventSourceSettings.ThrowOnEventWriteErrors : 0))
+ { }
+
+ /// <summary>
+ /// Construct an EventSource with additional non-default settings (see EventSourceSettings for more)
+ /// </summary>
+ protected EventSource(EventSourceSettings settings) : this(settings, null) { }
+
+ /// <summary>
+ /// Construct an EventSource with additional non-default settings.
+ ///
+ /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
+ /// The first string is the key and the second is the value. These are not interpreted by EventSource
+ /// itself but may be interprated the listeners. Can be fetched with GetTrait(string).
+ /// </summary>
+ /// <param name="settings">See EventSourceSettings for more.</param>
+ /// <param name="traits">A collection of key-value strings (must be an even number).</param>
+ protected EventSource(EventSourceSettings settings, params string[] traits)
+ {
+ m_config = ValidateSettings(settings);
+
+ Guid eventSourceGuid;
+ string eventSourceName;
+
+ EventMetadata[] eventDescriptors;
+ byte[] manifest;
+ GetMetadata(out eventSourceGuid, out eventSourceName, out eventDescriptors, out manifest);
+
+ if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null)
+ {
+ var myType = this.GetType();
+ eventSourceGuid = GetGuid(myType);
+ eventSourceName = GetName(myType);
+ }
+
+ Initialize(eventSourceGuid, eventSourceName, traits);
+ }
+
+ internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
+ {
+ //
+ // In ProjectN subclasses need to override this method, and return the data from their EventSourceAttribute and EventAttribute annotations.
+ // On other architectures it is a no-op.
+ //
+ // eventDescriptors needs to contain one EventDescriptor for each event; the event's ID should be the same as its index in this array.
+ // manifestBytes is a UTF-8 encoding of the ETW manifest for the type.
+ //
+ // This will be implemented by an IL rewriter, so we can't make this method abstract or the initial build of the subclass would fail.
+ //
+ eventSourceGuid = Guid.Empty;
+ eventSourceName = null;
+ eventData = null;
+ manifestBytes = null;
+
+ return;
+ }
+
+ /// <summary>
+ /// This method is called when the eventSource is updated by the controller.
+ /// </summary>
+ protected virtual void OnEventCommand(EventCommandEventArgs command) { }
+
+#pragma warning disable 1591
+ // optimized for common signatures (no args)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId)
+ {
+ WriteEventCore(eventId, 0, null);
+ }
+
+ // optimized for common signatures (ints)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, int arg1)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[1];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 4;
+ WriteEventCore(eventId, 1, descrs);
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, int arg1, int arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 4;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 4;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 4;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+
+ // optimized for common signatures (longs)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, long arg1)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[1];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ WriteEventCore(eventId, 1, descrs);
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, long arg1, long arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 8;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, long arg1, long arg2, long arg3)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 8;
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 8;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+
+ // optimized for common signatures (strings)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ fixed (char* string1Bytes = arg1)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[1];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ WriteEventCore(eventId, 1, descrs);
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1, string arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ if (arg2 == null) arg2 = "";
+ fixed (char* string1Bytes = arg1)
+ fixed (char* string2Bytes = arg2)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ descrs[1].DataPointer = (IntPtr)string2Bytes;
+ descrs[1].Size = ((arg2.Length + 1) * 2);
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1, string arg2, string arg3)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ if (arg2 == null) arg2 = "";
+ if (arg3 == null) arg3 = "";
+ fixed (char* string1Bytes = arg1)
+ fixed (char* string2Bytes = arg2)
+ fixed (char* string3Bytes = arg3)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ descrs[1].DataPointer = (IntPtr)string2Bytes;
+ descrs[1].Size = ((arg2.Length + 1) * 2);
+ descrs[2].DataPointer = (IntPtr)string3Bytes;
+ descrs[2].Size = ((arg3.Length + 1) * 2);
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (string and ints)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1, int arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ fixed (char* string1Bytes = arg1)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1, int arg2, int arg3)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ fixed (char* string1Bytes = arg1)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 4;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (string and longs)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, string arg1, long arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg1 == null) arg1 = "";
+ fixed (char* string1Bytes = arg1)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)string1Bytes;
+ descrs[0].Size = ((arg1.Length + 1) * 2);
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 8;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (long and string)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, long arg1, string arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg2 == null) arg2 = "";
+ fixed (char* string2Bytes = arg2)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)string2Bytes;
+ descrs[1].Size = ((arg2.Length + 1) * 2);
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (int and string)
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, int arg1, string arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ if (arg2 == null) arg2 = "";
+ fixed (char* string2Bytes = arg2)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 4;
+ descrs[1].DataPointer = (IntPtr)string2Bytes;
+ descrs[1].Size = ((arg2.Length + 1) * 2);
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, byte[] arg1)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ if (arg1 == null || arg1.Length == 0)
+ {
+ int blobSize = 0;
+ descrs[0].DataPointer = (IntPtr)(&blobSize);
+ descrs[0].Size = 4;
+ descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content
+ descrs[1].Size = 0;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ else
+ {
+ int blobSize = arg1.Length;
+ fixed (byte* blob = &arg1[0])
+ {
+ descrs[0].DataPointer = (IntPtr)(&blobSize);
+ descrs[0].Size = 4;
+ descrs[1].DataPointer = (IntPtr)blob;
+ descrs[1].Size = blobSize;
+ WriteEventCore(eventId, 2, descrs);
+ }
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, long arg1, byte[] arg2)
+ {
+ if (m_eventSourceEnabled)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ if (arg2 == null || arg2.Length == 0)
+ {
+ int blobSize = 0;
+ descrs[1].DataPointer = (IntPtr)(&blobSize);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents
+ descrs[2].Size = 0;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ else
+ {
+ int blobSize = arg2.Length;
+ fixed (byte* blob = &arg2[0])
+ {
+ descrs[1].DataPointer = (IntPtr)(&blobSize);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)blob;
+ descrs[2].Size = blobSize;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+ }
+ }
+
+#pragma warning restore 1591
+
+ /// <summary>
+ /// Used to construct the data structure to be passed to the native ETW APIs - EventWrite and EventWriteTransfer.
+ /// </summary>
+ protected internal struct EventData
+ {
+ /// <summary>
+ /// Address where the one argument lives (if this points to managed memory you must ensure the
+ /// managed object is pinned.
+ /// </summary>
+ public IntPtr DataPointer { get { return (IntPtr)m_Ptr; } set { m_Ptr = unchecked((long)value); } }
+ /// <summary>
+ /// Size of the argument referenced by DataPointer
+ /// </summary>
+ public int Size { get { return m_Size; } set { m_Size = value; } }
+
+ #region private
+ /// <summary>
+ /// Initializes the members of this EventData object to point at a previously-pinned
+ /// tracelogging-compatible metadata blob.
+ /// </summary>
+ /// <param name="pointer">Pinned tracelogging-compatible metadata blob.</param>
+ /// <param name="size">The size of the metadata blob.</param>
+ /// <param name="reserved">Value for reserved: 2 for per-provider metadata, 1 for per-event metadata</param>
+ [SecurityCritical]
+ internal unsafe void SetMetadata(byte* pointer, int size, int reserved)
+ {
+ this.m_Ptr = (long)(ulong)(UIntPtr)pointer;
+ this.m_Size = size;
+ this.m_Reserved = reserved; // Mark this descriptor as containing tracelogging-compatible metadata.
+ }
+
+ //Important, we pass this structure directly to the Win32 EventWrite API, so this structure must be layed out exactly
+ // the way EventWrite wants it.
+ internal long m_Ptr;
+ internal int m_Size;
+#pragma warning disable 0649
+ internal int m_Reserved; // Used to pad the size to match the Win32 API
+#pragma warning restore 0649
+ #endregion
+ }
+
+ /// <summary>
+ /// This routine allows you to create efficient WriteEvent helpers, however the code that you use to
+ /// do this, while straightforward, is unsafe.
+ /// </summary>
+ /// <remarks>
+ /// <code>
+ /// protected unsafe void WriteEvent(int eventId, string arg1, long arg2)
+ /// {
+ /// if (IsEnabled())
+ /// {
+ /// if (arg2 == null) arg2 = "";
+ /// fixed (char* string2Bytes = arg2)
+ /// {
+ /// EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ /// descrs[0].DataPointer = (IntPtr)(&amp;arg1);
+ /// descrs[0].Size = 8;
+ /// descrs[1].DataPointer = (IntPtr)string2Bytes;
+ /// descrs[1].Size = ((arg2.Length + 1) * 2);
+ /// WriteEventCore(eventId, 2, descrs);
+ /// }
+ /// }
+ /// }
+ /// </code>
+ /// </remarks>
+ [SecurityCritical]
+ [CLSCompliant(false)]
+ protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSource.EventData* data)
+ {
+ WriteEventWithRelatedActivityIdCore(eventId, null, eventDataCount, data);
+ }
+
+ /// <summary>
+ /// This routine allows you to create efficient WriteEventWithRelatedActivityId helpers, however the code
+ /// that you use to do this, while straightforward, is unsafe. The only difference from
+ /// <see cref="WriteEventCore"/> is that you pass the relatedActivityId from caller through to this API
+ /// </summary>
+ /// <remarks>
+ /// <code>
+ /// protected unsafe void WriteEventWithRelatedActivityId(int eventId, Guid relatedActivityId, string arg1, long arg2)
+ /// {
+ /// if (IsEnabled())
+ /// {
+ /// if (arg2 == null) arg2 = "";
+ /// fixed (char* string2Bytes = arg2)
+ /// {
+ /// EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+ /// descrs[0].DataPointer = (IntPtr)(&amp;arg1);
+ /// descrs[0].Size = 8;
+ /// descrs[1].DataPointer = (IntPtr)string2Bytes;
+ /// descrs[1].Size = ((arg2.Length + 1) * 2);
+ /// WriteEventWithRelatedActivityIdCore(eventId, relatedActivityId, 2, descrs);
+ /// }
+ /// }
+ /// }
+ /// </code>
+ /// </remarks>
+ [SecurityCritical]
+ [CLSCompliant(false)]
+ protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data)
+ {
+ if (m_eventSourceEnabled)
+ {
+ try
+ {
+ Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
+ if (relatedActivityId != null)
+ ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
+
+#if FEATURE_MANAGED_ETW
+ if (m_eventData[eventId].EnabledForETW)
+ {
+ EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode;
+ EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions;
+ Guid* pActivityId = null;
+ Guid activityId = Guid.Empty;
+ Guid relActivityId = Guid.Empty;
+
+ if (opcode != EventOpcode.Info && relatedActivityId == null &&
+ ((activityOptions & EventActivityOptions.Disable) == 0))
+ {
+ if (opcode == EventOpcode.Start)
+ {
+ m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relActivityId, m_eventData[eventId].ActivityOptions);
+ }
+ else if (opcode == EventOpcode.Stop)
+ {
+ m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId);
+ }
+
+ if (activityId != Guid.Empty)
+ pActivityId = &activityId;
+ if (relActivityId != Guid.Empty)
+ relatedActivityId = &relActivityId;
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+ // this code should be kept in sync with WriteEventVarargs().
+ SessionMask etwSessions = SessionMask.All;
+ // only compute etwSessions if there are *any* ETW filters enabled...
+ if ((ulong)m_curLiveSessions != 0)
+ etwSessions = GetEtwSessionMask(eventId, relatedActivityId);
+ // OutputDebugString(string.Format("{0}.WriteEvent(id {1}) -> to sessions {2:x}",
+ // m_name, m_eventData[eventId].Name, (ulong) etwSessions));
+
+ if ((ulong)etwSessions != 0 || m_legacySessions != null && m_legacySessions.Count > 0)
+ {
+ if (!SelfDescribingEvents)
+ {
+ if (etwSessions.IsEqualOrSupersetOf(m_curLiveSessions))
+ {
+ // OutputDebugString(string.Format(" (1) id {0}, kwd {1:x}",
+ // m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Keywords));
+ // by default the Descriptor.Keyword will have the perEventSourceSessionId bit
+ // 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(m_eventData[eventId].Name);
+ }
+ else
+ {
+ long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords())));
+ // OutputDebugString(string.Format(" (2) id {0}, kwd {1:x}",
+ // m_eventData[eventId].Name, etwSessions.ToEventKeywords() | (ulong) origKwd));
+ // only some of the ETW sessions will receive this event. Synthesize a new
+ // Descriptor whose Keywords field will have the appropriate bits set.
+ // etwSessions might be 0, if there are legacy ETW listeners that want this event
+ var desc = new EventDescriptor(
+ m_eventData[eventId].Descriptor.EventId,
+ m_eventData[eventId].Descriptor.Version,
+ m_eventData[eventId].Descriptor.Channel,
+ m_eventData[eventId].Descriptor.Level,
+ m_eventData[eventId].Descriptor.Opcode,
+ m_eventData[eventId].Descriptor.Task,
+ unchecked((long)etwSessions.ToEventKeywords() | origKwd));
+
+ if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+ }
+ }
+ else
+ {
+ TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes;
+ if (tlet == null)
+ {
+ tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name,
+ EventTags.None,
+ m_eventData[eventId].Parameters);
+ Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null);
+
+ }
+ long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords())));
+ // TODO: activity ID support
+ EventSourceOptions opt = new EventSourceOptions
+ {
+ Keywords = (EventKeywords)unchecked((long)etwSessions.ToEventKeywords() | origKwd),
+ Level = (EventLevel)m_eventData[eventId].Descriptor.Level,
+ Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode
+ };
+
+ WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, relatedActivityId, data);
+ }
+ }
+#else
+ if (!SelfDescribingEvents)
+ {
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+ }
+ else
+ {
+ TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes;
+ if (tlet == null)
+ {
+ tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name,
+ m_eventData[eventId].Tags,
+ m_eventData[eventId].Parameters);
+ Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null);
+
+ }
+ EventSourceOptions opt = new EventSourceOptions
+ {
+ Keywords = (EventKeywords)m_eventData[eventId].Descriptor.Keywords,
+ Level = (EventLevel)m_eventData[eventId].Descriptor.Level,
+ Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode
+ };
+
+ WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, relatedActivityId, data);
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+#endif // FEATURE_MANAGED_ETW
+
+ if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
+ WriteToAllListeners(eventId, relatedActivityId, eventDataCount, data);
+ }
+ catch (Exception ex)
+ {
+ if (ex is EventSourceException)
+ throw;
+ else
+ ThrowEventSourceException(m_eventData[eventId].Name, ex);
+ }
+ }
+ }
+
+ // fallback varags helpers.
+ /// <summary>
+ /// This is the varargs helper for writing an event. It does create an array and box all the arguments so it is
+ /// relatively inefficient and should only be used for relatively rare events (e.g. less than 100 / sec). If your
+ /// rates are faster than that you should use <see cref="WriteEventCore"/> to create fast helpers for your particular
+ /// method signature. Even if you use this for rare events, this call should be guarded by an <see cref="IsEnabled()"/>
+ /// check so that the varargs call is not made when the EventSource is not active.
+ /// </summary>
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ protected unsafe void WriteEvent(int eventId, params object[] args)
+ {
+ WriteEventVarargs(eventId, null, args);
+ }
+
+ /// <summary>
+ /// This is the varargs helper for writing an event which also specifies a related activity. It is completely analogous
+ /// to corresponding WriteEvent (they share implementation). It does create an array and box all the arguments so it is
+ /// relatively inefficient and should only be used for relatively rare events (e.g. less than 100 / sec). If your
+ /// rates are faster than that you should use <see cref="WriteEventWithRelatedActivityIdCore"/> to create fast helpers for your
+ /// particular method signature. Even if you use this for rare events, this call should be guarded by an <see cref="IsEnabled()"/>
+ /// check so that the varargs call is not made when the EventSource is not active.
+ /// </summary>
+ [SecuritySafeCritical]
+ protected unsafe void WriteEventWithRelatedActivityId(int eventId, Guid relatedActivityId, params object[] args)
+ {
+ WriteEventVarargs(eventId, &relatedActivityId, args);
+ }
+
+ #endregion
+
+ #region IDisposable Members
+ /// <summary>
+ /// Disposes of an EventSource.
+ /// </summary>
+ public void Dispose()
+ {
+ this.Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ /// <summary>
+ /// Disposes of an EventSource.
+ /// </summary>
+ /// <remarks>
+ /// Called from Dispose() with disposing=true, and from the finalizer (~EventSource) with disposing=false.
+ /// Guidelines:
+ /// 1. We may be called more than once: do nothing after the first call.
+ /// 2. Avoid throwing exceptions if disposing is false, i.e. if we're being finalized.
+ /// </remarks>
+ /// <param name="disposing">True if called from Dispose(), false if called from the finalizer.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+#if FEATURE_MANAGED_ETW
+ // Send the manifest one more time to ensure circular buffers have a chance to get to this information
+ // even in scenarios with a high volume of ETW events.
+ if (m_eventSourceEnabled)
+ {
+ try
+ {
+ SendManifest(m_rawManifest);
+ }
+ catch (Exception)
+ { } // If it fails, simply give up.
+ m_eventSourceEnabled = false;
+ }
+ if (m_provider != null)
+ {
+ m_provider.Dispose();
+ m_provider = null;
+ }
+#endif
+ }
+ m_eventSourceEnabled = false;
+ m_eventSourceDisposed = true;
+ }
+ /// <summary>
+ /// Finalizer for EventSource
+ /// </summary>
+ ~EventSource()
+ {
+ this.Dispose(false);
+ }
+ #endregion
+
+ #region private
+#if FEATURE_ACTIVITYSAMPLING
+ internal void WriteStringToListener(EventListener listener, string msg, SessionMask m)
+ {
+ Contract.Assert(listener == null || (uint)m == (uint)SessionMask.FromId(0));
+
+ if (m_eventSourceEnabled)
+ {
+ if (listener == null)
+ {
+ WriteEventString(0, unchecked((long)m.ToEventKeywords()), msg);
+ }
+ else
+ {
+ List<object> arg = new List<object>();
+ arg.Add(msg);
+ EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
+ eventCallbackArgs.EventId = 0;
+ eventCallbackArgs.Payload = new ReadOnlyCollection<object>(arg);
+ listener.OnEventWritten(eventCallbackArgs);
+ }
+ }
+ }
+#endif
+
+ [SecurityCritical]
+ private unsafe void WriteEventRaw(
+ string eventName,
+ ref EventDescriptor eventDescriptor,
+ Guid* activityID,
+ Guid* relatedActivityID,
+ int dataCount,
+ IntPtr data)
+ {
+#if FEATURE_MANAGED_ETW
+ if (m_provider == null)
+ {
+ ThrowEventSourceException(eventName);
+ }
+ else
+ {
+ if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
+ ThrowEventSourceException(eventName);
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ // FrameworkEventSource is on the startup path for the framework, so we have this internal overload that it can use
+ // to prevent the working set hit from looking at the custom attributes on the type to get the Guid.
+ internal EventSource(Guid eventSourceGuid, string eventSourceName)
+ : this(eventSourceGuid, eventSourceName, EventSourceSettings.EtwManifestEventFormat)
+ { }
+
+ // Used by the internal FrameworkEventSource constructor and the TraceLogging-style event source constructor
+ internal EventSource(Guid eventSourceGuid, string eventSourceName, EventSourceSettings settings, string[] traits = null)
+ {
+ m_config = ValidateSettings(settings);
+ Initialize(eventSourceGuid, eventSourceName, traits);
+ }
+
+ /// <summary>
+ /// This method is responsible for the common initialization path from our constructors. It must
+ /// not leak any exceptions (otherwise, since most EventSource classes define a static member,
+ /// "Log", such an exception would become a cached exception for the initialization of the static
+ /// member, and any future access to the "Log" would throw the cached exception).
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "guid")]
+ [SecuritySafeCritical]
+ private unsafe void Initialize(Guid eventSourceGuid, string eventSourceName, string[] traits)
+ {
+ try
+ {
+ m_traits = traits;
+ if (m_traits != null && m_traits.Length % 2 != 0)
+ {
+ throw new ArgumentException(Resources.GetResourceString("TraitEven"), nameof(traits));
+ }
+
+ if (eventSourceGuid == Guid.Empty)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NeedGuid"));
+ }
+
+ if (eventSourceName == null)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NeedName"));
+ }
+
+ m_name = eventSourceName;
+ m_guid = eventSourceGuid;
+#if FEATURE_ACTIVITYSAMPLING
+ m_curLiveSessions = new SessionMask(0);
+ m_etwSessionIdMap = new EtwSession[SessionMask.MAX];
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ //Enable Implicit Activity tracker
+ m_activityTracker = ActivityTracker.Instance;
+
+#if FEATURE_MANAGED_ETW
+ // Create and register our provider traits. We do this early because it is needed to log errors
+ // In the self-describing event case.
+ this.InitializeProviderMetadata();
+
+ // Register the provider with ETW
+ var provider = new OverideEventProvider(this);
+ provider.Register(eventSourceGuid);
+#endif
+ // Add the eventSource to the global (weak) list.
+ // This also sets m_id, which is the index in the list.
+ EventListener.AddEventSource(this);
+
+#if FEATURE_MANAGED_ETW
+ // OK if we get this far without an exception, then we can at least write out error messages.
+ // Set m_provider, which allows this.
+ m_provider = provider;
+
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ // API available on OS >= Win 8 and patched Win 7.
+ // Disable only for FrameworkEventSource to avoid recursion inside exception handling.
+ var osVer = Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor;
+ if (this.Name != "System.Diagnostics.Eventing.FrameworkEventSource" || osVer >= 62)
+#endif
+ {
+ int setInformationResult;
+ System.Runtime.InteropServices.GCHandle metadataHandle =
+ System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned);
+ IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
+
+ setInformationResult = m_provider.SetInformation(
+ UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
+ providerMetadata,
+ (uint)this.providerMetadata.Length);
+
+ metadataHandle.Free();
+ }
+#endif // FEATURE_MANAGED_ETW
+
+ Contract.Assert(!m_eventSourceEnabled); // We can't be enabled until we are completely initted.
+ // We are logically completely initialized at this point.
+ m_completelyInited = true;
+ }
+ catch (Exception e)
+ {
+ if (m_constructionException == null)
+ m_constructionException = e;
+ ReportOutOfBandMessage("ERROR: Exception during construction of EventSource " + Name + ": " + e.Message, true);
+ }
+
+ // Once m_completelyInited is set, you can have concurrency, so all work is under the lock.
+ lock (EventListener.EventListenersLock)
+ {
+ // If there are any deferred commands, we can do them now.
+ // This is the most likely place for exceptions to happen.
+ // 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(deferredCommands); // This can never throw, it catches them and reports the errors.
+ deferredCommands = deferredCommands.nextCommand;
+ }
+ }
+ }
+
+ private static string GetName(Type eventSourceType, EventManifestOptions flags)
+ {
+ if (eventSourceType == null)
+ throw new ArgumentNullException(nameof(eventSourceType));
+ Contract.EndContractBlock();
+
+ EventSourceAttribute attrib = (EventSourceAttribute)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute), flags);
+ if (attrib != null && attrib.Name != null)
+ return attrib.Name;
+
+ return eventSourceType.Name;
+ }
+
+ /// <summary>
+ /// Implements the SHA1 hashing algorithm. Note that this
+ /// implementation is for hashing public information. Do not
+ /// use this code to hash private data, as this implementation does
+ /// not take any steps to avoid information disclosure.
+ /// </summary>
+ private struct Sha1ForNonSecretPurposes
+ {
+ private long length; // Total message length in bits
+ private uint[] w; // Workspace
+ private int pos; // Length of current chunk in bytes
+
+ /// <summary>
+ /// Call Start() to initialize the hash object.
+ /// </summary>
+ public void Start()
+ {
+ if (this.w == null)
+ {
+ this.w = new uint[85];
+ }
+
+ this.length = 0;
+ this.pos = 0;
+ this.w[80] = 0x67452301;
+ this.w[81] = 0xEFCDAB89;
+ this.w[82] = 0x98BADCFE;
+ this.w[83] = 0x10325476;
+ this.w[84] = 0xC3D2E1F0;
+ }
+
+ /// <summary>
+ /// Adds an input byte to the hash.
+ /// </summary>
+ /// <param name="input">Data to include in the hash.</param>
+ public void Append(byte input)
+ {
+ this.w[this.pos / 4] = (this.w[this.pos / 4] << 8) | input;
+ if (64 == ++this.pos)
+ {
+ this.Drain();
+ }
+ }
+
+ /// <summary>
+ /// Adds input bytes to the hash.
+ /// </summary>
+ /// <param name="input">
+ /// Data to include in the hash. Must not be null.
+ /// </param>
+ public void Append(byte[] input)
+ {
+ foreach (var b in input)
+ {
+ this.Append(b);
+ }
+ }
+
+ /// <summary>
+ /// Retrieves the hash value.
+ /// Note that after calling this function, the hash object should
+ /// be considered uninitialized. Subsequent calls to Append or
+ /// Finish will produce useless results. Call Start() to
+ /// reinitialize.
+ /// </summary>
+ /// <param name="output">
+ /// Buffer to receive the hash value. Must not be null.
+ /// Up to 20 bytes of hash will be written to the output buffer.
+ /// If the buffer is smaller than 20 bytes, the remaining hash
+ /// bytes will be lost. If the buffer is larger than 20 bytes, the
+ /// rest of the buffer is left unmodified.
+ /// </param>
+ public void Finish(byte[] output)
+ {
+ long l = this.length + 8 * this.pos;
+ this.Append(0x80);
+ while (this.pos != 56)
+ {
+ this.Append(0x00);
+ }
+
+ unchecked
+ {
+ this.Append((byte)(l >> 56));
+ this.Append((byte)(l >> 48));
+ this.Append((byte)(l >> 40));
+ this.Append((byte)(l >> 32));
+ this.Append((byte)(l >> 24));
+ this.Append((byte)(l >> 16));
+ this.Append((byte)(l >> 8));
+ this.Append((byte)l);
+
+ int end = output.Length < 20 ? output.Length : 20;
+ for (int i = 0; i != end; i++)
+ {
+ uint temp = this.w[80 + i / 4];
+ output[i] = (byte)(temp >> 24);
+ this.w[80 + i / 4] = temp << 8;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Called when this.pos reaches 64.
+ /// </summary>
+ private void Drain()
+ {
+ for (int i = 16; i != 80; i++)
+ {
+ this.w[i] = Rol1((this.w[i - 3] ^ this.w[i - 8] ^ this.w[i - 14] ^ this.w[i - 16]));
+ }
+
+ unchecked
+ {
+ uint a = this.w[80];
+ uint b = this.w[81];
+ uint c = this.w[82];
+ uint d = this.w[83];
+ uint e = this.w[84];
+
+ for (int i = 0; i != 20; i++)
+ {
+ const uint k = 0x5A827999;
+ uint f = (b & c) | ((~b) & d);
+ uint temp = Rol5(a) + f + e + k + this.w[i]; e = d; d = c; c = Rol30(b); b = a; a = temp;
+ }
+
+ for (int i = 20; i != 40; i++)
+ {
+ uint f = b ^ c ^ d;
+ const uint k = 0x6ED9EBA1;
+ uint temp = Rol5(a) + f + e + k + this.w[i]; e = d; d = c; c = Rol30(b); b = a; a = temp;
+ }
+
+ for (int i = 40; i != 60; i++)
+ {
+ uint f = (b & c) | (b & d) | (c & d);
+ const uint k = 0x8F1BBCDC;
+ uint temp = Rol5(a) + f + e + k + this.w[i]; e = d; d = c; c = Rol30(b); b = a; a = temp;
+ }
+
+ for (int i = 60; i != 80; i++)
+ {
+ uint f = b ^ c ^ d;
+ const uint k = 0xCA62C1D6;
+ uint temp = Rol5(a) + f + e + k + this.w[i]; e = d; d = c; c = Rol30(b); b = a; a = temp;
+ }
+
+ this.w[80] += a;
+ this.w[81] += b;
+ this.w[82] += c;
+ this.w[83] += d;
+ this.w[84] += e;
+ }
+
+ this.length += 512; // 64 bytes == 512 bits
+ this.pos = 0;
+ }
+
+ private static uint Rol1(uint input)
+ {
+ return (input << 1) | (input >> 31);
+ }
+
+ private static uint Rol5(uint input)
+ {
+ return (input << 5) | (input >> 27);
+ }
+
+ private static uint Rol30(uint input)
+ {
+ return (input << 30) | (input >> 2);
+ }
+ }
+
+ private static Guid GenerateGuidFromName(string name)
+ {
+ byte[] bytes = Encoding.BigEndianUnicode.GetBytes(name);
+ var hash = new Sha1ForNonSecretPurposes();
+ hash.Start();
+ hash.Append(namespaceBytes);
+ hash.Append(bytes);
+ Array.Resize(ref bytes, 16);
+ hash.Finish(bytes);
+
+ bytes[7] = unchecked((byte)((bytes[7] & 0x0F) | 0x50)); // Set high 4 bits of octet 7 to 5, as per RFC 4122
+ return new Guid(bytes);
+ }
+
+ [SecurityCritical]
+ private unsafe object DecodeObject(int eventId, int parameterId, ref EventSource.EventData* data)
+ {
+ // TODO FIX : We use reflection which in turn uses EventSource, right now we carefully avoid
+ // the recursion, but can we do this in a robust way?
+
+ IntPtr dataPointer = data->DataPointer;
+ // advance to next EventData in array
+ ++data;
+
+ Type dataType = GetDataType(m_eventData[eventId], parameterId);
+
+ Again:
+ if (dataType == typeof(IntPtr))
+ {
+ return *((IntPtr*)dataPointer);
+ }
+ else if (dataType == typeof(int))
+ {
+ return *((int*)dataPointer);
+ }
+ else if (dataType == typeof(uint))
+ {
+ return *((uint*)dataPointer);
+ }
+ else if (dataType == typeof(long))
+ {
+ return *((long*)dataPointer);
+ }
+ else if (dataType == typeof(ulong))
+ {
+ return *((ulong*)dataPointer);
+ }
+ else if (dataType == typeof(byte))
+ {
+ return *((byte*)dataPointer);
+ }
+ else if (dataType == typeof(sbyte))
+ {
+ return *((sbyte*)dataPointer);
+ }
+ else if (dataType == typeof(short))
+ {
+ return *((short*)dataPointer);
+ }
+ else if (dataType == typeof(ushort))
+ {
+ return *((ushort*)dataPointer);
+ }
+ else if (dataType == typeof(float))
+ {
+ return *((float*)dataPointer);
+ }
+ else if (dataType == typeof(double))
+ {
+ return *((double*)dataPointer);
+ }
+ else if (dataType == typeof(decimal))
+ {
+ return *((decimal*)dataPointer);
+ }
+ else if (dataType == typeof(bool))
+ {
+ // The manifest defines a bool as a 32bit type (WIN32 BOOL), not 1 bit as CLR Does.
+ if (*((int*)dataPointer) == 1)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (dataType == typeof(Guid))
+ {
+ return *((Guid*)dataPointer);
+ }
+ else if (dataType == typeof(char))
+ {
+ return *((char*)dataPointer);
+ }
+ else if (dataType == typeof(DateTime))
+ {
+ long dateTimeTicks = *((long*)dataPointer);
+ return DateTime.FromFileTimeUtc(dateTimeTicks);
+ }
+ else if (dataType == typeof(byte[]))
+ {
+ // byte[] are written to EventData* as an int followed by a blob
+ int cbSize = *((int*)dataPointer);
+ byte[] blob = new byte[cbSize];
+ dataPointer = data->DataPointer;
+ data++;
+ for (int i = 0; i < cbSize; ++i)
+ blob[i] = *((byte*)(dataPointer + i));
+ return blob;
+ }
+ else if (dataType == typeof(byte*))
+ {
+ // TODO: how do we want to handle this? For now we ignore it...
+ return null;
+ }
+ else
+ {
+ if (m_EventSourcePreventRecursion && m_EventSourceInDecodeObject)
+ {
+ return null;
+ }
+
+ try
+ {
+ m_EventSourceInDecodeObject = true;
+
+ if (dataType.IsEnum())
+ {
+ dataType = Enum.GetUnderlyingType(dataType);
+ goto Again;
+ }
+
+
+ // Everything else is marshaled as a string.
+ // ETW strings are NULL-terminated, so marshal everything up to the first
+ // null in the string.
+ return System.Runtime.InteropServices.Marshal.PtrToStringUni(dataPointer);
+
+ }
+ finally
+ {
+ m_EventSourceInDecodeObject = false;
+ }
+ }
+ }
+
+ // Finds the Dispatcher (which holds the filtering state), for a given dispatcher for the current
+ // eventSource).
+ private EventDispatcher GetDispatcher(EventListener listener)
+ {
+ EventDispatcher dispatcher = m_Dispatchers;
+ while (dispatcher != null)
+ {
+ if (dispatcher.m_Listener == listener)
+ return dispatcher;
+ dispatcher = dispatcher.m_Next;
+ }
+ return dispatcher;
+ }
+
+ [SecurityCritical]
+ private unsafe void WriteEventVarargs(int eventId, Guid* childActivityID, object[] args)
+ {
+ if (m_eventSourceEnabled)
+ {
+ try
+ {
+ Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
+ if (childActivityID != null)
+ {
+ 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(Resources.GetResourceString("EventSource_NoRelatedActivityId"));
+ }
+ }
+
+ LogEventArgsMismatches(m_eventData[eventId].Parameters, args);
+#if FEATURE_MANAGED_ETW
+ if (m_eventData[eventId].EnabledForETW)
+ {
+ Guid* pActivityId = null;
+ Guid activityId = Guid.Empty;
+ Guid relatedActivityId = Guid.Empty;
+ EventOpcode opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode;
+ EventActivityOptions activityOptions = m_eventData[eventId].ActivityOptions;
+
+ if (childActivityID == null &&
+ ((activityOptions & EventActivityOptions.Disable) == 0))
+ {
+ if (opcode == EventOpcode.Start)
+ {
+ m_activityTracker.OnStart(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId, ref relatedActivityId, m_eventData[eventId].ActivityOptions);
+ }
+ else if (opcode == EventOpcode.Stop)
+ {
+ m_activityTracker.OnStop(m_name, m_eventData[eventId].Name, m_eventData[eventId].Descriptor.Task, ref activityId);
+ }
+
+ if (activityId != Guid.Empty)
+ pActivityId = &activityId;
+ if (relatedActivityId != Guid.Empty)
+ childActivityID = &relatedActivityId;
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+ // this code should be kept in sync with WriteEventWithRelatedActivityIdCore().
+ SessionMask etwSessions = SessionMask.All;
+ // only compute etwSessions if there are *any* ETW filters enabled...
+ if ((ulong)m_curLiveSessions != 0)
+ etwSessions = GetEtwSessionMask(eventId, childActivityID);
+
+ if ((ulong)etwSessions != 0 || m_legacySessions != null && m_legacySessions.Count > 0)
+ {
+ if (!SelfDescribingEvents)
+ {
+ if (etwSessions.IsEqualOrSupersetOf(m_curLiveSessions))
+ {
+ // by default the Descriptor.Keyword will have the perEventSourceSessionId bit
+ // 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(m_eventData[eventId].Name);
+ }
+ else
+ {
+ long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords())));
+ // only some of the ETW sessions will receive this event. Synthesize a new
+ // Descriptor whose Keywords field will have the appropriate bits set.
+ var desc = new EventDescriptor(
+ m_eventData[eventId].Descriptor.EventId,
+ m_eventData[eventId].Descriptor.Version,
+ m_eventData[eventId].Descriptor.Channel,
+ m_eventData[eventId].Descriptor.Level,
+ m_eventData[eventId].Descriptor.Opcode,
+ m_eventData[eventId].Descriptor.Task,
+ unchecked((long)etwSessions.ToEventKeywords() | origKwd));
+
+ if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+ }
+ }
+ else
+ {
+ TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes;
+ if (tlet == null)
+ {
+ tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name,
+ EventTags.None,
+ m_eventData[eventId].Parameters);
+ Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null);
+
+ }
+ long origKwd = unchecked((long)((ulong)m_eventData[eventId].Descriptor.Keywords & ~(SessionMask.All.ToEventKeywords())));
+ // TODO: activity ID support
+ EventSourceOptions opt = new EventSourceOptions
+ {
+ Keywords = (EventKeywords)unchecked((long)etwSessions.ToEventKeywords() | origKwd),
+ Level = (EventLevel)m_eventData[eventId].Descriptor.Level,
+ Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode
+ };
+
+ WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, childActivityID, args);
+ }
+ }
+#else
+ if (!SelfDescribingEvents)
+ {
+ if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
+ ThrowEventSourceException(m_eventData[eventId].Name);
+ }
+ else
+ {
+ TraceLoggingEventTypes tlet = m_eventData[eventId].TraceLoggingEventTypes;
+ if (tlet == null)
+ {
+ tlet = new TraceLoggingEventTypes(m_eventData[eventId].Name,
+ EventTags.None,
+ m_eventData[eventId].Parameters);
+ Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, tlet, null);
+
+ }
+ // TODO: activity ID support
+ EventSourceOptions opt = new EventSourceOptions
+ {
+ Keywords = (EventKeywords)m_eventData[eventId].Descriptor.Keywords,
+ Level = (EventLevel)m_eventData[eventId].Descriptor.Level,
+ Opcode = (EventOpcode)m_eventData[eventId].Descriptor.Opcode
+ };
+
+ WriteMultiMerge(m_eventData[eventId].Name, ref opt, tlet, pActivityId, childActivityID, args);
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+#endif // FEATURE_MANAGED_ETW
+ if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
+ {
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ // Maintain old behavior - object identity is preserved
+ if (AppContextSwitches.PreserveEventListnerObjectIdentity)
+ {
+ WriteToAllListeners(eventId, childActivityID, args);
+ }
+ else
+#endif // !ES_BUILD_STANDALONE
+ {
+ object[] serializedArgs = SerializeEventArgs(eventId, args);
+ WriteToAllListeners(eventId, childActivityID, serializedArgs);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ if (ex is EventSourceException)
+ throw;
+ else
+ ThrowEventSourceException(m_eventData[eventId].Name, ex);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ unsafe private object[] SerializeEventArgs(int eventId, object[] args)
+ {
+ TraceLoggingEventTypes eventTypes = m_eventData[eventId].TraceLoggingEventTypes;
+ if (eventTypes == null)
+ {
+ eventTypes = new TraceLoggingEventTypes(m_eventData[eventId].Name,
+ EventTags.None,
+ m_eventData[eventId].Parameters);
+ Interlocked.CompareExchange(ref m_eventData[eventId].TraceLoggingEventTypes, eventTypes, null);
+ }
+ var eventData = new object[eventTypes.typeInfos.Length];
+ for (int i = 0; i < eventTypes.typeInfos.Length; i++)
+ {
+ eventData[i] = eventTypes.typeInfos[i].GetData(args[i]);
+ }
+ 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)
+ {
+#if (!ES_BUILD_PCL && !PROJECTN)
+ // 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, Resources.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
+ }
+#endif //!ES_BUILD_PCL
+ }
+
+ private int GetParamLenghtIncludingByteArray(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;
+ int modifiedParamCount = GetParamLenghtIncludingByteArray(m_eventData[eventId].Parameters);
+ if (eventDataCount != modifiedParamCount)
+ {
+ ReportOutOfBandMessage(Resources.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
+ paramCount = Math.Min(paramCount, eventDataCount);
+ }
+
+ object[] args = new object[paramCount];
+
+ EventSource.EventData* dataPtr = data;
+ for (int i = 0; i < paramCount; i++)
+ args[i] = DecodeObject(eventId, i, ref dataPtr);
+ WriteToAllListeners(eventId, childActivityID, args);
+ }
+
+ // helper for writing to all EventListeners attached the current eventSource.
+ [SecurityCritical]
+ unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, params object[] args)
+ {
+ EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
+ eventCallbackArgs.EventId = eventId;
+ if (childActivityID != null)
+ eventCallbackArgs.RelatedActivityId = *childActivityID;
+ eventCallbackArgs.EventName = m_eventData[eventId].Name;
+ eventCallbackArgs.Message = m_eventData[eventId].Message;
+ eventCallbackArgs.Payload = new ReadOnlyCollection<object>(args);
+
+ DispatchToAllListeners(eventId, childActivityID, eventCallbackArgs);
+ }
+
+ [SecurityCritical]
+ private unsafe void DispatchToAllListeners(int eventId, Guid* childActivityID, EventWrittenEventArgs eventCallbackArgs)
+ {
+ Exception lastThrownException = null;
+ for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next)
+ {
+ Contract.Assert(dispatcher.m_EventEnabled != null);
+ if (eventId == -1 || dispatcher.m_EventEnabled[eventId])
+ {
+#if FEATURE_ACTIVITYSAMPLING
+ var activityFilter = dispatcher.m_Listener.m_activityFilter;
+ // order below is important as PassesActivityFilter will "flow" active activities
+ // even when the current EventSource doesn't have filtering enabled. This allows
+ // interesting activities to be updated so that sources that do sample can get
+ // accurate data
+ if (activityFilter == null ||
+ ActivityFilter.PassesActivityFilter(activityFilter, childActivityID,
+ m_eventData[eventId].TriggersActivityTracking > 0,
+ this, eventId) ||
+ !dispatcher.m_activityFilteringEnabled)
+#endif // FEATURE_ACTIVITYSAMPLING
+ {
+ try
+ {
+ dispatcher.m_Listener.OnEventWritten(eventCallbackArgs);
+ }
+ catch (Exception e)
+ {
+ ReportOutOfBandMessage("ERROR: Exception during EventSource.OnEventWritten: "
+ + e.Message, false);
+ lastThrownException = e;
+ }
+ }
+ }
+ }
+
+ if (lastThrownException != null)
+ {
+ throw new EventSourceException(lastThrownException);
+ }
+ }
+
+ [SecuritySafeCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
+ {
+#if FEATURE_MANAGED_ETW
+ if (m_provider != null)
+ {
+ string eventName = "EventSourceMessage";
+ if (SelfDescribingEvents)
+ {
+ EventSourceOptions opt = new EventSourceOptions
+ {
+ Keywords = (EventKeywords)unchecked(keywords),
+ Level = level
+ };
+ var msg = new { message = msgString };
+ var tlet = new TraceLoggingEventTypes(eventName, EventTags.None, new Type[] { msg.GetType() });
+ WriteMultiMergeInner(eventName, ref opt, tlet, null, null, msg);
+ }
+ else
+ {
+ // We want the name of the provider to show up so if we don't have a manifest we create
+ // on that at least has the provider name (I don't define any events).
+ if (m_rawManifest == null && m_outOfBandMessageCount == 1)
+ {
+ ManifestBuilder manifestBuilder = new ManifestBuilder(Name, Guid, Name, null, EventManifestOptions.None);
+ manifestBuilder.StartEvent(eventName, new EventAttribute(0) { Level = EventLevel.LogAlways, Task = (EventTask)0xFFFE });
+ manifestBuilder.AddEventParameter(typeof(string), "message");
+ manifestBuilder.EndEvent();
+ SendManifest(manifestBuilder.CreateManifest());
+ }
+
+ // We use this low level routine to to bypass the enabled checking, since the eventSource itself is only partially inited.
+ fixed (char* msgStringPtr = msgString)
+ {
+ EventDescriptor descr = new EventDescriptor(0, 0, 0, (byte)level, 0, 0, keywords);
+ EventProvider.EventData data = new EventProvider.EventData();
+ data.Ptr = (ulong)msgStringPtr;
+ data.Size = (uint)(2 * (msgString.Length + 1));
+ data.Reserved = 0;
+ m_provider.WriteEvent(ref descr, null, null, 1, (IntPtr)((void*)&data));
+ }
+ }
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ /// <summary>
+ /// Since this is a means of reporting errors (see ReportoutOfBandMessage) any failure encountered
+ /// while writing the message to any one of the listeners will be silently ignored.
+ /// </summary>
+ private void WriteStringToAllListeners(string eventName, string msg)
+ {
+ EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
+ eventCallbackArgs.EventId = 0;
+ eventCallbackArgs.Message = msg;
+ eventCallbackArgs.Payload = new ReadOnlyCollection<object>(new List<object>() { msg });
+ eventCallbackArgs.PayloadNames = new ReadOnlyCollection<string>(new List<string> { "message" });
+ eventCallbackArgs.EventName = eventName;
+
+ for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next)
+ {
+ bool dispatcherEnabled = false;
+ if (dispatcher.m_EventEnabled == null)
+ {
+ // if the listeners that weren't correctly initialized, we will send to it
+ // since this is an error message and we want to see it go out.
+ dispatcherEnabled = true;
+ }
+ else
+ {
+ // if there's *any* enabled event on the dispatcher we'll write out the string
+ // otherwise we'll treat the listener as disabled and skip it
+ for (int evtId = 0; evtId < dispatcher.m_EventEnabled.Length; ++evtId)
+ {
+ if (dispatcher.m_EventEnabled[evtId])
+ {
+ dispatcherEnabled = true;
+ break;
+ }
+ }
+ }
+ try
+ {
+ if (dispatcherEnabled)
+ dispatcher.m_Listener.OnEventWritten(eventCallbackArgs);
+ }
+ catch
+ {
+ // ignore any exceptions thrown by listeners' OnEventWritten
+ }
+ }
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+ [SecurityCritical]
+ unsafe private SessionMask GetEtwSessionMask(int eventId, Guid* childActivityID)
+ {
+ SessionMask etwSessions = new SessionMask();
+
+ for (int i = 0; i < SessionMask.MAX; ++i)
+ {
+ EtwSession etwSession = m_etwSessionIdMap[i];
+ if (etwSession != null)
+ {
+ ActivityFilter activityFilter = etwSession.m_activityFilter;
+ // PassesActivityFilter() will flow "interesting" activities, so make sure
+ // to perform this test first, before ORing with ~m_activityFilteringForETWEnabled
+ // (note: the first test for !m_activityFilteringForETWEnabled[i] ensures we
+ // do not fire events indiscriminately, when no filters are specified, but only
+ // if, in addition, the session did not also enable ActivitySampling)
+ if (activityFilter == null && !m_activityFilteringForETWEnabled[i] ||
+ activityFilter != null &&
+ ActivityFilter.PassesActivityFilter(activityFilter, childActivityID,
+ m_eventData[eventId].TriggersActivityTracking > 0, this, eventId) ||
+ !m_activityFilteringForETWEnabled[i])
+ {
+ etwSessions[i] = true;
+ }
+ }
+ }
+ // flow "interesting" activities for all legacy sessions in which there's some
+ // level of activity tracing enabled (even other EventSources)
+ if (m_legacySessions != null && m_legacySessions.Count > 0 &&
+ (EventOpcode)m_eventData[eventId].Descriptor.Opcode == EventOpcode.Send)
+ {
+ // only calculate InternalCurrentThreadActivityId once
+ Guid* pCurrentActivityId = null;
+ Guid currentActivityId;
+ foreach (var legacyEtwSession in m_legacySessions)
+ {
+ if (legacyEtwSession == null)
+ continue;
+
+ ActivityFilter activityFilter = legacyEtwSession.m_activityFilter;
+ if (activityFilter != null)
+ {
+ if (pCurrentActivityId == null)
+ {
+ currentActivityId = InternalCurrentThreadActivityId;
+ pCurrentActivityId = &currentActivityId;
+ }
+ ActivityFilter.FlowActivityIfNeeded(activityFilter, pCurrentActivityId, childActivityID);
+ }
+ }
+ }
+
+ return etwSessions;
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ /// <summary>
+ /// Returns true if 'eventNum' is enabled if you only consider the level and matchAnyKeyword filters.
+ /// It is possible that eventSources turn off the event based on additional filtering criteria.
+ /// </summary>
+ private bool IsEnabledByDefault(int eventNum, bool enable, EventLevel currentLevel, EventKeywords currentMatchAnyKeyword)
+ {
+ if (!enable)
+ return false;
+
+ EventLevel eventLevel = (EventLevel)m_eventData[eventNum].Descriptor.Level;
+ EventKeywords eventKeywords = unchecked((EventKeywords)((ulong)m_eventData[eventNum].Descriptor.Keywords & (~(SessionMask.All.ToEventKeywords()))));
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ EventChannel channel = unchecked((EventChannel)m_eventData[eventNum].Descriptor.Channel);
+#else
+ EventChannel channel = EventChannel.None;
+#endif
+
+ return IsEnabledCommon(enable, currentLevel, currentMatchAnyKeyword, eventLevel, eventKeywords, channel);
+ }
+
+ private bool IsEnabledCommon(bool enabled, EventLevel currentLevel, EventKeywords currentMatchAnyKeyword,
+ EventLevel eventLevel, EventKeywords eventKeywords, EventChannel eventChannel)
+ {
+ if (!enabled)
+ return false;
+
+ // does is pass the level test?
+ if ((currentLevel != 0) && (currentLevel < eventLevel))
+ return false;
+
+ // if yes, does it pass the keywords test?
+ if (currentMatchAnyKeyword != 0 && eventKeywords != 0)
+ {
+#if FEATURE_MANAGED_ETW_CHANNELS
+ // is there a channel with keywords that match currentMatchAnyKeyword?
+ if (eventChannel != EventChannel.None && this.m_channelData != null && this.m_channelData.Length > (int)eventChannel)
+ {
+ EventKeywords channel_keywords = unchecked((EventKeywords)(m_channelData[(int)eventChannel] | (ulong)eventKeywords));
+ if (channel_keywords != 0 && (channel_keywords & currentMatchAnyKeyword) == 0)
+ return false;
+ }
+ else
+#endif
+ {
+ if ((unchecked((ulong)eventKeywords & (ulong)currentMatchAnyKeyword)) == 0)
+ return false;
+ }
+ }
+ return true;
+
+ }
+ [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
+ private void ThrowEventSourceException(string eventName, Exception innerEx = null)
+ {
+ // 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)
+ return;
+ try
+ {
+ m_EventSourceExceptionRecurenceCount++;
+
+ string errorPrefix = "EventSourceException";
+ if(eventName != null)
+ {
+ errorPrefix += " while processing event \"" + eventName + "\"";
+ }
+
+ // TODO Create variations of EventSourceException that indicate more information using the error code.
+ switch (EventProvider.GetLastWriteEventError())
+ {
+ case EventProvider.WriteEventErrorCode.EventTooBig:
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_EventTooBig"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_EventTooBig"), innerEx);
+ break;
+ case EventProvider.WriteEventErrorCode.NoFreeBuffers:
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NoFreeBuffers"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
+ break;
+ case EventProvider.WriteEventErrorCode.NullInput:
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NullInput"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NullInput"), innerEx);
+ break;
+ case EventProvider.WriteEventErrorCode.TooManyArgs:
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_TooManyArgs"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_TooManyArgs"), innerEx);
+ break;
+ default:
+ if (innerEx != null)
+ ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
+ else
+ ReportOutOfBandMessage(errorPrefix, true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
+ break;
+ }
+ }
+ finally
+ {
+ m_EventSourceExceptionRecurenceCount--;
+ }
+ }
+
+ 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.Start)
+ {
+ ThrowEventSourceException(eventName);
+ }
+ }
+
+ internal static EventOpcode GetOpcodeWithDefault(EventOpcode opcode, string eventName)
+ {
+ if (opcode == EventOpcode.Info && eventName != null)
+ {
+ if (eventName.EndsWith(s_ActivityStartSuffix, StringComparison.Ordinal))
+ {
+ return EventOpcode.Start;
+ }
+ else if (eventName.EndsWith(s_ActivityStopSuffix, StringComparison.Ordinal))
+ {
+ return EventOpcode.Stop;
+ }
+ }
+
+ return opcode;
+ }
+
+#if FEATURE_MANAGED_ETW
+ /// <summary>
+ /// This class lets us hook the 'OnEventCommand' from the eventSource.
+ /// </summary>
+ private class OverideEventProvider : EventProvider
+ {
+ public OverideEventProvider(EventSource eventSource)
+ {
+ this.m_eventSource = eventSource;
+ }
+ protected override void OnControllerCommand(ControllerCommand command, IDictionary<string, string> arguments,
+ int perEventSourceSessionId, int etwSessionId)
+ {
+ // We use null to represent the ETW EventListener.
+ EventListener listener = null;
+ m_eventSource.SendCommand(listener, perEventSourceSessionId, etwSessionId,
+ (EventCommand)command, IsEnabled(), Level, MatchAnyKeyword, arguments);
+ }
+ private EventSource m_eventSource;
+ }
+#endif
+
+ /// <summary>
+ /// Used to hold all the static information about an event. This includes everything in the event
+ /// descriptor as well as some stuff we added specifically for EventSource. see the
+ /// code:m_eventData for where we use this.
+ /// </summary>
+ internal partial struct EventMetadata
+ {
+ public EventDescriptor Descriptor;
+ 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
+ public byte TriggersActivityTracking; // count of listeners that marked this event as trigger for start of activity logging.
+#if !FEATURE_ACTIVITYSAMPLING
+#pragma warning restore 0649
+#endif
+ public string Name; // the name of the event
+ public string Message; // If the event has a message associated with it, this is it.
+ public ParameterInfo[] Parameters; // TODO can we remove?
+
+ public TraceLoggingEventTypes TraceLoggingEventTypes;
+ public EventActivityOptions ActivityOptions;
+
+#if PROJECTN
+ public EventParameterType[] ParameterTypes;
+#endif
+ };
+
+ // This is the internal entry point that code:EventListeners call when wanting to send a command to a
+ // eventSource. The logic is as follows
+ //
+ // * if Command == Update
+ // * perEventSourceSessionId specifies the per-provider ETW session ID that the command applies
+ // to (if listener != null)
+ // perEventSourceSessionId = 0 - reserved for EventListeners
+ // perEventSourceSessionId = 1..SessionMask.MAX - reserved for activity tracing aware ETW sessions
+ // perEventSourceSessionId-1 represents the bit in the reserved field (bits 44..47) in
+ // Keywords that identifies the session
+ // perEventSourceSessionId = SessionMask.MAX+1 - reserved for legacy ETW sessions; these are
+ // discriminated by etwSessionId
+ // * etwSessionId specifies a machine-wide ETW session ID; this allows correlation of
+ // activity tracing across different providers (which might have different sessionIds
+ // for the same ETW session)
+ // * enable, level, matchAnyKeywords are used to set a default for all events for the
+ // eventSource. In particular, if 'enabled' is false, 'level' and
+ // 'matchAnyKeywords' are not used.
+ // * OnEventCommand is invoked, which may cause calls to
+ // code:EventSource.EnableEventForDispatcher which may cause changes in the filtering
+ // depending on the logic in that routine.
+ // * else (command != Update)
+ // * Simply call OnEventCommand. The expectation is that filtering is NOT changed.
+ // * The 'enabled' 'level', matchAnyKeyword' arguments are ignored (must be true, 0, 0).
+ //
+ // dispatcher == null has special meaning. It is the 'ETW' dispatcher.
+ internal void SendCommand(EventListener listener, int perEventSourceSessionId, int etwSessionId,
+ EventCommand command, bool enable,
+ EventLevel level, EventKeywords matchAnyKeyword,
+ IDictionary<string, string> commandArguments)
+ {
+ var commandArgs = new EventCommandEventArgs(command, commandArguments, this, listener, perEventSourceSessionId, etwSessionId, enable, level, matchAnyKeyword);
+ lock (EventListener.EventListenersLock)
+ {
+ 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.
+ commandArgs.nextCommand = m_deferredCommands;
+ m_deferredCommands = commandArgs;
+ }
+ }
+ }
+
+ /// <summary>
+ /// We want the eventSource to be fully initialized when we do commands because that way we can send
+ /// error messages and other logging directly to the event stream. Unfortunately we can get callbacks
+ /// when we are not fully initialized. In that case we store them in 'commandArgs' and do them later.
+ /// This helper actually does all actual command logic.
+ /// </summary>
+ internal void DoCommand(EventCommandEventArgs commandArgs)
+ {
+ // PRECONDITION: We should be holding the EventListener.EventListenersLock
+ // We defer commands until we are completely inited. This allows error messages to be sent.
+ Contract.Assert(m_completelyInited);
+
+#if FEATURE_MANAGED_ETW
+ if (m_provider == null) // If we failed to construct
+ return;
+#endif // FEATURE_MANAGED_ETW
+
+ m_outOfBandMessageCount = 0;
+ bool shouldReport = (commandArgs.perEventSourceSessionId > 0) && (commandArgs.perEventSourceSessionId <= SessionMask.MAX);
+ try
+ {
+ EnsureDescriptorsInitialized();
+ Contract.Assert(m_eventData != null);
+
+ // Find the per-EventSource dispatcher corresponding to registered dispatcher
+ commandArgs.dispatcher = GetDispatcher(commandArgs.listener);
+ if (commandArgs.dispatcher == null && commandArgs.listener != null) // dispatcher == null means ETW dispatcher
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_ListenerNotFound"));
+ }
+
+ if (commandArgs.Arguments == null)
+ commandArgs.Arguments = new Dictionary<string, string>();
+
+ if (commandArgs.Command == EventCommand.Update)
+ {
+ // Set it up using the 'standard' filtering bitfields (use the "global" enable, not session specific one)
+ for (int i = 0; i < m_eventData.Length; i++)
+ EnableEventForDispatcher(commandArgs.dispatcher, i, IsEnabledByDefault(i, commandArgs.enable, commandArgs.level, commandArgs.matchAnyKeyword));
+
+ if (commandArgs.enable)
+ {
+ if (!m_eventSourceEnabled)
+ {
+ // EventSource turned on for the first time, simply copy the bits.
+ m_level = commandArgs.level;
+ m_matchAnyKeyword = commandArgs.matchAnyKeyword;
+ }
+ else
+ {
+ // Already enabled, make it the most verbose of the existing and new filter
+ if (commandArgs.level > m_level)
+ m_level = commandArgs.level;
+ if (commandArgs.matchAnyKeyword == 0)
+ m_matchAnyKeyword = 0;
+ else if (m_matchAnyKeyword != 0)
+ m_matchAnyKeyword = unchecked(m_matchAnyKeyword | commandArgs.matchAnyKeyword);
+ }
+ }
+
+ // interpret perEventSourceSessionId's sign, and adjust perEventSourceSessionId to
+ // represent 0-based positive values
+ bool bSessionEnable = (commandArgs.perEventSourceSessionId >= 0);
+ if (commandArgs.perEventSourceSessionId == 0 && commandArgs.enable == false)
+ bSessionEnable = false;
+
+ if (commandArgs.listener == null)
+ {
+ if (!bSessionEnable)
+ commandArgs.perEventSourceSessionId = -commandArgs.perEventSourceSessionId;
+ // for "global" enable/disable (passed in with listener == null and
+ // perEventSourceSessionId == 0) perEventSourceSessionId becomes -1
+ --commandArgs.perEventSourceSessionId;
+ }
+
+ commandArgs.Command = bSessionEnable ? EventCommand.Enable : EventCommand.Disable;
+
+ // perEventSourceSessionId = -1 when ETW sent a notification, but the set of active sessions
+ // hasn't changed.
+ // sesisonId = SessionMask.MAX when one of the legacy ETW sessions changed
+ // 0 <= perEventSourceSessionId < SessionMask.MAX for activity-tracing aware sessions
+ Contract.Assert(commandArgs.perEventSourceSessionId >= -1 && commandArgs.perEventSourceSessionId <= SessionMask.MAX);
+
+ // Send the manifest if we are enabling an ETW session
+ if (bSessionEnable && commandArgs.dispatcher == null)
+ {
+ // eventSourceDispatcher == null means this is the ETW manifest
+
+ // Note that we unconditionally send the manifest whenever we are enabled, even if
+ // we were already enabled. This is because there may be multiple sessions active
+ // and we can't know that all the sessions have seen the manifest.
+ if (!SelfDescribingEvents)
+ SendManifest(m_rawManifest);
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+ if (bSessionEnable && commandArgs.perEventSourceSessionId != -1)
+ {
+ bool participateInSampling = false;
+ string activityFilters;
+ int sessionIdBit;
+
+ ParseCommandArgs(commandArgs.Arguments, out participateInSampling,
+ out activityFilters, out sessionIdBit);
+
+ if (commandArgs.listener == null && commandArgs.Arguments.Count > 0 && commandArgs.perEventSourceSessionId != sessionIdBit)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_SessionIdError",
+ commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD,
+ sessionIdBit + SessionMask.SHIFT_SESSION_TO_KEYWORD));
+ }
+
+ if (commandArgs.listener == null)
+ {
+ UpdateEtwSession(commandArgs.perEventSourceSessionId, commandArgs.etwSessionId, true, activityFilters, participateInSampling);
+ }
+ else
+ {
+ ActivityFilter.UpdateFilter(ref commandArgs.listener.m_activityFilter, this, 0, activityFilters);
+ commandArgs.dispatcher.m_activityFilteringEnabled = participateInSampling;
+ }
+ }
+ else if (!bSessionEnable && commandArgs.listener == null)
+ {
+ // if we disable an ETW session, indicate that in a synthesized command argument
+ if (commandArgs.perEventSourceSessionId >= 0 && commandArgs.perEventSourceSessionId < SessionMask.MAX)
+ {
+ commandArgs.Arguments["EtwSessionKeyword"] = (commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD).ToString(CultureInfo.InvariantCulture);
+ }
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // Turn on the enable bit before making the OnEventCommand callback This allows you to do useful
+ // things like log messages, or test if keywords are enabled in the callback.
+ if (commandArgs.enable)
+ {
+ 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)
+ {
+ // if we disable an ETW session, complete disabling it
+ UpdateEtwSession(commandArgs.perEventSourceSessionId, commandArgs.etwSessionId, false, null, false);
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ if (!commandArgs.enable)
+ {
+ // If we are disabling, maybe we can turn on 'quick checks' to filter
+ // quickly. These are all just optimizations (since later checks will still filter)
+
+#if FEATURE_ACTIVITYSAMPLING
+ // Turn off (and forget) any information about Activity Tracing.
+ if (commandArgs.listener == null)
+ {
+ // reset all filtering information for activity-tracing-aware sessions
+ for (int i = 0; i < SessionMask.MAX; ++i)
+ {
+ EtwSession etwSession = m_etwSessionIdMap[i];
+ if (etwSession != null)
+ ActivityFilter.DisableFilter(ref etwSession.m_activityFilter, this);
+ }
+ m_activityFilteringForETWEnabled = new SessionMask(0);
+ m_curLiveSessions = new SessionMask(0);
+ // reset activity-tracing-aware sessions
+ if (m_etwSessionIdMap != null)
+ for (int i = 0; i < SessionMask.MAX; ++i)
+ m_etwSessionIdMap[i] = null;
+ // reset legacy sessions
+ if (m_legacySessions != null)
+ m_legacySessions.Clear();
+ }
+ else
+ {
+ ActivityFilter.DisableFilter(ref commandArgs.listener.m_activityFilter, this);
+ commandArgs.dispatcher.m_activityFilteringEnabled = false;
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // There is a good chance EnabledForAnyListener are not as accurate as
+ // they could be, go ahead and get a better estimate.
+ for (int i = 0; i < m_eventData.Length; i++)
+ {
+ bool isEnabledForAnyListener = false;
+ for (EventDispatcher dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next)
+ {
+ if (dispatcher.m_EventEnabled[i])
+ {
+ isEnabledForAnyListener = true;
+ break;
+ }
+ }
+ m_eventData[i].EnabledForAnyListener = isEnabledForAnyListener;
+ }
+
+ // If no events are enabled, disable the global enabled bit.
+ if (!AnyEventEnabled())
+ {
+ m_level = 0;
+ m_matchAnyKeyword = 0;
+ m_eventSourceEnabled = false;
+ }
+ }
+#if FEATURE_ACTIVITYSAMPLING
+ UpdateKwdTriggers(commandArgs.enable);
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+ else
+ {
+ if (commandArgs.Command == EventCommand.SendManifest)
+ {
+ // TODO: should we generate the manifest here if we hadn't already?
+ if (m_rawManifest != null)
+ SendManifest(m_rawManifest);
+ }
+
+ // These are not used for non-update commands and thus should always be 'default' values
+ // 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
+ if (m_completelyInited && (commandArgs.listener != null || shouldReport))
+ {
+ SessionMask m = SessionMask.FromId(commandArgs.perEventSourceSessionId);
+ ReportActivitySamplingInfo(commandArgs.listener, m);
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+ catch (Exception e)
+ {
+ // When the ETW session is created after the EventSource has registered with the ETW system
+ // we can send any error messages here.
+ ReportOutOfBandMessage("ERROR: Exception in Command Processing for EventSource " + Name + ": " + e.Message, true);
+ // We never throw when doing a command.
+ }
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+
+ internal void UpdateEtwSession(
+ int sessionIdBit,
+ int etwSessionId,
+ bool bEnable,
+ string activityFilters,
+ bool participateInSampling)
+ {
+ if (sessionIdBit < SessionMask.MAX)
+ {
+ // activity-tracing-aware etw session
+ if (bEnable)
+ {
+ var etwSession = EtwSession.GetEtwSession(etwSessionId, true);
+ ActivityFilter.UpdateFilter(ref etwSession.m_activityFilter, this, sessionIdBit, activityFilters);
+ m_etwSessionIdMap[sessionIdBit] = etwSession;
+ m_activityFilteringForETWEnabled[sessionIdBit] = participateInSampling;
+ }
+ else
+ {
+ var etwSession = EtwSession.GetEtwSession(etwSessionId);
+ m_etwSessionIdMap[sessionIdBit] = null;
+ m_activityFilteringForETWEnabled[sessionIdBit] = false;
+ if (etwSession != null)
+ {
+ ActivityFilter.DisableFilter(ref etwSession.m_activityFilter, this);
+ // the ETW session is going away; remove it from the global list
+ EtwSession.RemoveEtwSession(etwSession);
+ }
+ }
+ m_curLiveSessions[sessionIdBit] = bEnable;
+ }
+ else
+ {
+ // legacy etw session
+ if (bEnable)
+ {
+ if (m_legacySessions == null)
+ m_legacySessions = new List<EtwSession>(8);
+ var etwSession = EtwSession.GetEtwSession(etwSessionId, true);
+ if (!m_legacySessions.Contains(etwSession))
+ m_legacySessions.Add(etwSession);
+ }
+ else
+ {
+ var etwSession = EtwSession.GetEtwSession(etwSessionId);
+ if (etwSession != null)
+ {
+ if (m_legacySessions != null)
+ m_legacySessions.Remove(etwSession);
+ // the ETW session is going away; remove it from the global list
+ EtwSession.RemoveEtwSession(etwSession);
+ }
+ }
+ }
+ }
+
+ internal static bool ParseCommandArgs(
+ IDictionary<string, string> commandArguments,
+ out bool participateInSampling,
+ out string activityFilters,
+ out int sessionIdBit)
+ {
+ bool res = true;
+ participateInSampling = false;
+ string activityFilterString;
+ if (commandArguments.TryGetValue("ActivitySamplingStartEvent", out activityFilters))
+ {
+ // if a start event is specified default the event source to participate in sampling
+ participateInSampling = true;
+ }
+
+ if (commandArguments.TryGetValue("ActivitySampling", out activityFilterString))
+ {
+ if (string.Compare(activityFilterString, "false", StringComparison.OrdinalIgnoreCase) == 0 ||
+ activityFilterString == "0")
+ participateInSampling = false;
+ else
+ participateInSampling = true;
+ }
+
+ string sSessionKwd;
+ int sessionKwd = -1;
+ if (!commandArguments.TryGetValue("EtwSessionKeyword", out sSessionKwd) ||
+ !int.TryParse(sSessionKwd, out sessionKwd) ||
+ sessionKwd < SessionMask.SHIFT_SESSION_TO_KEYWORD ||
+ sessionKwd >= SessionMask.SHIFT_SESSION_TO_KEYWORD + SessionMask.MAX)
+ {
+ sessionIdBit = -1;
+ res = false;
+ }
+ else
+ {
+ sessionIdBit = sessionKwd - SessionMask.SHIFT_SESSION_TO_KEYWORD;
+ }
+ return res;
+ }
+
+ internal void UpdateKwdTriggers(bool enable)
+ {
+ if (enable)
+ {
+ // recompute m_keywordTriggers
+ ulong gKeywords = unchecked((ulong)m_matchAnyKeyword);
+ if (gKeywords == 0)
+ gKeywords = 0xFFFFffffFFFFffff;
+
+ m_keywordTriggers = 0;
+ for (int sessId = 0; sessId < SessionMask.MAX; ++sessId)
+ {
+ EtwSession etwSession = m_etwSessionIdMap[sessId];
+ if (etwSession == null)
+ continue;
+
+ ActivityFilter activityFilter = etwSession.m_activityFilter;
+ ActivityFilter.UpdateKwdTriggers(activityFilter, m_guid, this, unchecked((EventKeywords)gKeywords));
+ }
+ }
+ else
+ {
+ m_keywordTriggers = 0;
+ }
+ }
+
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ /// <summary>
+ /// If 'value is 'true' then set the eventSource so that 'dispatcher' will receive event with the eventId
+ /// of 'eventId. If value is 'false' disable the event for that dispatcher. If 'eventId' is out of
+ /// range return false, otherwise true.
+ /// </summary>
+ internal bool EnableEventForDispatcher(EventDispatcher dispatcher, int eventId, bool value)
+ {
+ if (dispatcher == null)
+ {
+ if (eventId >= m_eventData.Length)
+ return false;
+#if FEATURE_MANAGED_ETW
+ if (m_provider != null)
+ m_eventData[eventId].EnabledForETW = value;
+#endif
+ }
+ else
+ {
+ if (eventId >= dispatcher.m_EventEnabled.Length)
+ return false;
+ dispatcher.m_EventEnabled[eventId] = value;
+ if (value)
+ m_eventData[eventId].EnabledForAnyListener = true;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if any event at all is on.
+ /// </summary>
+ private bool AnyEventEnabled()
+ {
+ for (int i = 0; i < m_eventData.Length; i++)
+ if (m_eventData[i].EnabledForETW || m_eventData[i].EnabledForAnyListener)
+ return true;
+ return false;
+ }
+
+ private bool IsDisposed
+ {
+ get { return m_eventSourceDisposed; }
+ }
+
+ [SecuritySafeCritical]
+ private void EnsureDescriptorsInitialized()
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
+ if (m_eventData == null)
+ {
+ Guid eventSourceGuid = Guid.Empty;
+ string eventSourceName = null;
+ EventMetadata[] eventData = null;
+ byte[] manifest = null;
+
+ // Try the GetMetadata provided by the ILTransform in ProjectN. The default sets all to null, and in that case we fall back
+ // to the reflection approach.
+ GetMetadata(out eventSourceGuid, out eventSourceName, out eventData, out manifest);
+
+ if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null || eventData == null || manifest == null)
+ {
+ // GetMetadata failed, so we have to set it via reflection.
+ Contract.Assert(m_rawManifest == null);
+ m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
+ Contract.Assert(m_eventData != null);
+
+ }
+ else
+ {
+ // GetMetadata worked, so set the fields as appropriate.
+ m_name = eventSourceName;
+ m_guid = eventSourceGuid;
+ m_eventData = eventData;
+ m_rawManifest = manifest;
+ }
+ // TODO Enforce singleton pattern
+ foreach (WeakReference eventSourceRef in EventListener.s_EventSources)
+ {
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource != null && eventSource.Guid == m_guid && !eventSource.IsDisposed)
+ {
+ if (eventSource != this)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_EventSourceGuidInUse", m_guid));
+ }
+ }
+ }
+
+ // Make certain all dispatchers also have their arrays initialized
+ EventDispatcher dispatcher = m_Dispatchers;
+ while (dispatcher != null)
+ {
+ if (dispatcher.m_EventEnabled == null)
+ dispatcher.m_EventEnabled = new bool[m_eventData.Length];
+ dispatcher = dispatcher.m_Next;
+ }
+ }
+ if (s_currentPid == 0)
+ {
+#if ES_BUILD_STANDALONE && !ES_BUILD_PCL
+ // for non-BCL EventSource we must assert SecurityPermission
+ new SecurityPermission(PermissionState.Unrestricted).Assert();
+#endif
+ s_currentPid = Win32Native.GetCurrentProcessId();
+ }
+ }
+
+ // Send out the ETW manifest XML out to ETW
+ // Today, we only send the manifest to ETW, custom listeners don't get it.
+ [SecuritySafeCritical]
+ private unsafe bool SendManifest(byte[] rawManifest)
+ {
+ bool success = true;
+
+ if (rawManifest == null)
+ return false;
+
+ Contract.Assert(!SelfDescribingEvents);
+
+#if FEATURE_MANAGED_ETW
+ fixed (byte* dataPtr = rawManifest)
+ {
+ // we don't want the manifest to show up in the event log channels so we specify as keywords
+ // everything but the first 8 bits (reserved for the 8 channels)
+ var manifestDescr = new EventDescriptor(0xFFFE, 1, 0, 0, 0xFE, 0xFFFE, 0x00ffFFFFffffFFFF);
+ ManifestEnvelope envelope = new ManifestEnvelope();
+
+ envelope.Format = ManifestEnvelope.ManifestFormats.SimpleXmlFormat;
+ envelope.MajorVersion = 1;
+ envelope.MinorVersion = 0;
+ envelope.Magic = 0x5B; // An unusual number that can be checked for consistency.
+ int dataLeft = rawManifest.Length;
+ envelope.ChunkNumber = 0;
+
+ EventProvider.EventData* dataDescrs = stackalloc EventProvider.EventData[2];
+
+ dataDescrs[0].Ptr = (ulong)&envelope;
+ dataDescrs[0].Size = (uint)sizeof(ManifestEnvelope);
+ dataDescrs[0].Reserved = 0;
+
+ dataDescrs[1].Ptr = (ulong)dataPtr;
+ dataDescrs[1].Reserved = 0;
+
+ int chunkSize = ManifestEnvelope.MaxChunkSize;
+ TRY_AGAIN_WITH_SMALLER_CHUNK_SIZE:
+ envelope.TotalChunks = (ushort)((dataLeft + (chunkSize - 1)) / chunkSize);
+ while (dataLeft > 0)
+ {
+ dataDescrs[1].Size = (uint)Math.Min(dataLeft, chunkSize);
+ if (m_provider != null)
+ {
+ if (!m_provider.WriteEvent(ref manifestDescr, null, null, 2, (IntPtr)dataDescrs))
+ {
+ // Turns out that if users set the BufferSize to something less than 64K then WriteEvent
+ // can fail. If we get this failure on the first chunk try again with something smaller
+ // The smallest BufferSize is 1K so if we get to 256 (to account for envelope overhead), we can give up making it smaller.
+ if (EventProvider.GetLastWriteEventError() == EventProvider.WriteEventErrorCode.EventTooBig)
+ {
+ if (envelope.ChunkNumber == 0 && chunkSize > 256)
+ {
+ chunkSize = chunkSize / 2;
+ goto TRY_AGAIN_WITH_SMALLER_CHUNK_SIZE;
+ }
+ }
+ success = false;
+ if (ThrowOnEventWriteErrors)
+ ThrowEventSourceException("SendManifest");
+ break;
+ }
+ }
+ dataLeft -= chunkSize;
+ dataDescrs[1].Ptr += (uint)chunkSize;
+ envelope.ChunkNumber++;
+
+ // For large manifests we want to not overflow any receiver's buffer. Most manifests will fit within
+ // 5 chunks, so only the largest manifests will hit the pause.
+ if((envelope.ChunkNumber % 5) == 0)
+ Thread.Sleep(15);
+ }
+ }
+#endif // FEATURE_MANAGED_ETW
+ return success;
+ }
+
+#if (ES_BUILD_PCL || PROJECTN)
+ internal static Attribute GetCustomAttributeHelper(Type type, Type attributeType, EventManifestOptions flags = EventManifestOptions.None)
+ {
+ return GetCustomAttributeHelper(type.GetTypeInfo(), attributeType, flags);
+ }
+#endif
+
+ // Helper to deal with the fact that the type we are reflecting over might be loaded in the ReflectionOnly context.
+ // When that is the case, we have the build the custom assemblies on a member by hand.
+ internal static Attribute GetCustomAttributeHelper(MemberInfo member, Type attributeType, EventManifestOptions flags = EventManifestOptions.None)
+ {
+ if (!member.Module.Assembly.ReflectionOnly() && (flags & EventManifestOptions.AllowEventSourceOverride) == 0)
+ {
+ // Let the runtime to the work for us, since we can execute code in this context.
+ Attribute firstAttribute = null;
+ foreach (var attribute in member.GetCustomAttributes(attributeType, false))
+ {
+ firstAttribute = (Attribute)attribute;
+ break;
+ }
+ return firstAttribute;
+ }
+
+#if (!ES_BUILD_PCL && !PROJECTN)
+ // In the reflection only context, we have to do things by hand.
+ string fullTypeNameToFind = attributeType.FullName;
+
+#if EVENT_SOURCE_LEGACY_NAMESPACE_SUPPORT
+ fullTypeNameToFind = fullTypeNameToFind.Replace("System.Diagnostics.Eventing", "System.Diagnostics.Tracing");
+#endif
+
+ foreach (CustomAttributeData data in CustomAttributeData.GetCustomAttributes(member))
+ {
+ if (AttributeTypeNamesMatch(attributeType, data.Constructor.ReflectedType))
+ {
+ Attribute attr = null;
+
+ Contract.Assert(data.ConstructorArguments.Count <= 1);
+
+ if (data.ConstructorArguments.Count == 1)
+ {
+ attr = (Attribute)Activator.CreateInstance(attributeType, new object[] { data.ConstructorArguments[0].Value });
+ }
+ else if (data.ConstructorArguments.Count == 0)
+ {
+ attr = (Attribute)Activator.CreateInstance(attributeType);
+ }
+
+ if (attr != null)
+ {
+ Type t = attr.GetType();
+
+ foreach (CustomAttributeNamedArgument namedArgument in data.NamedArguments)
+ {
+ PropertyInfo p = t.GetProperty(namedArgument.MemberInfo.Name, BindingFlags.Public | BindingFlags.Instance);
+ object value = namedArgument.TypedValue.Value;
+
+ if (p.PropertyType.IsEnum)
+ {
+ value = Enum.Parse(p.PropertyType, value.ToString());
+ }
+
+ p.SetValue(attr, value, null);
+ }
+
+ return attr;
+ }
+ }
+ }
+
+ return null;
+#else // ES_BUILD_PCL && PROJECTN
+ throw new ArgumentException(Resources.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection"));
+#endif
+ }
+
+ /// <summary>
+ /// Evaluates if two related "EventSource"-domain types should be considered the same
+ /// </summary>
+ /// <param name="attributeType">The attribute type in the load context - it's associated with the running
+ /// EventSource type. This type may be different fromt he base type of the user-defined EventSource.</param>
+ /// <param name="reflectedAttributeType">The attribute type in the reflection context - it's associated with
+ /// the user-defined EventSource, and is in the same assembly as the eventSourceType passed to
+ /// </param>
+ /// <returns>True - if the types should be considered equivalent, False - otherwise</returns>
+ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAttributeType)
+ {
+ return
+ // are these the same type?
+ attributeType == reflectedAttributeType ||
+ // are the full typenames equal?
+ string.Equals(attributeType.FullName, reflectedAttributeType.FullName, StringComparison.Ordinal) ||
+ // are the typenames equal and the namespaces under "Diagnostics.Tracing" (typically
+ // either Microsoft.Diagnostics.Tracing or System.Diagnostics.Tracing)?
+ string.Equals(attributeType.Name, reflectedAttributeType.Name, StringComparison.Ordinal) &&
+ attributeType.Namespace.EndsWith("Diagnostics.Tracing", StringComparison.Ordinal) &&
+ (reflectedAttributeType.Namespace.EndsWith("Diagnostics.Tracing", StringComparison.Ordinal)
+#if EVENT_SOURCE_LEGACY_NAMESPACE_SUPPORT
+ || reflectedAttributeType.Namespace.EndsWith("Diagnostics.Eventing", StringComparison.Ordinal)
+#endif
+);
+ }
+
+ private static Type GetEventSourceBaseType(Type eventSourceType, bool allowEventSourceOverride, bool reflectionOnly)
+ {
+ // return false for "object" and interfaces
+ if (eventSourceType.BaseType() == null)
+ return null;
+
+ // now go up the inheritance chain until hitting a concrete type ("object" at worse)
+ do
+ {
+ eventSourceType = eventSourceType.BaseType();
+ }
+ while (eventSourceType != null && eventSourceType.IsAbstract());
+
+ if (eventSourceType != null)
+ {
+ if (!allowEventSourceOverride)
+ {
+ if (reflectionOnly && eventSourceType.FullName != typeof(EventSource).FullName ||
+ !reflectionOnly && eventSourceType != typeof(EventSource))
+ return null;
+ }
+ else
+ {
+ if (eventSourceType.Name != "EventSource")
+ return null;
+ }
+ }
+ return eventSourceType;
+ }
+
+ // Use reflection to look at the attributes of a class, and generate a manifest for it (as UTF8) and
+ // return the UTF8 bytes. It also sets up the code:EventData structures needed to dispatch events
+ // at run time. 'source' is the event source to place the descriptors. If it is null,
+ // then the descriptors are not creaed, and just the manifest is generated.
+ private static byte[] CreateManifestAndDescriptors(Type eventSourceType, string eventSourceDllName, EventSource source,
+ EventManifestOptions flags = EventManifestOptions.None)
+ {
+ ManifestBuilder manifest = null;
+ bool bNeedsManifest = source != null ? !source.SelfDescribingEvents : true;
+ Exception exception = null; // exception that might get raised during validation b/c we couldn't/didn't recover from a previous error
+ byte[] res = null;
+
+ if (eventSourceType.IsAbstract() && (flags & EventManifestOptions.Strict) == 0)
+ return null;
+
+#if DEBUG && ES_BUILD_STANDALONE
+ TestSupport.TestHooks.MaybeThrow(eventSourceType,
+ TestSupport.Category.ManifestError,
+ "EventSource_CreateManifestAndDescriptors",
+ new ArgumentException("EventSource_CreateManifestAndDescriptors"));
+#endif
+
+ try
+ {
+ MethodInfo[] methods = eventSourceType.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+ EventAttribute defaultEventAttribute;
+ int eventId = 1; // The number given to an event that does not have a explicitly given ID.
+ EventMetadata[] eventData = null;
+ Dictionary<string, string> eventsByName = null;
+ if (source != null || (flags & EventManifestOptions.Strict) != 0)
+ {
+ eventData = new EventMetadata[methods.Length + 1];
+ eventData[0].Name = ""; // Event 0 is the 'write messages string' event, and has an empty name.
+ }
+
+ // See if we have localization information.
+ ResourceManager resources = null;
+ EventSourceAttribute eventSourceAttrib = (EventSourceAttribute)GetCustomAttributeHelper(eventSourceType, typeof(EventSourceAttribute), flags);
+ if (eventSourceAttrib != null && eventSourceAttrib.LocalizationResources != null)
+ resources = new ResourceManager(eventSourceAttrib.LocalizationResources, eventSourceType.Assembly());
+
+ manifest = new ManifestBuilder(GetName(eventSourceType, flags), GetGuid(eventSourceType), eventSourceDllName,
+ resources, flags);
+
+ // Add an entry unconditionally for event ID 0 which will be for a string message.
+ manifest.StartEvent("EventSourceMessage", new EventAttribute(0) { Level = EventLevel.LogAlways, Task = (EventTask)0xFFFE });
+ manifest.AddEventParameter(typeof(string), "message");
+ manifest.EndEvent();
+
+ // eventSourceType must be sealed and must derive from this EventSource
+ if ((flags & EventManifestOptions.Strict) != 0)
+ {
+ bool typeMatch = GetEventSourceBaseType(eventSourceType, (flags & EventManifestOptions.AllowEventSourceOverride) != 0, eventSourceType.Assembly().ReflectionOnly()) != null;
+
+ if (!typeMatch)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustDeriveFromEventSource"));
+ }
+ if (!eventSourceType.IsAbstract() && !eventSourceType.IsSealed())
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustBeSealedOrAbstract"));
+ }
+ }
+
+ // Collect task, opcode, keyword and channel information
+#if FEATURE_MANAGED_ETW_CHANNELS && FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes", "Channels" })
+#else
+ foreach (var providerEnumKind in new string[] { "Keywords", "Tasks", "Opcodes" })
+#endif
+ {
+ Type nestedType = eventSourceType.GetNestedType(providerEnumKind);
+ if (nestedType != null)
+ {
+ if (eventSourceType.IsAbstract())
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareKTOC", nestedType.Name));
+ }
+ else
+ {
+ foreach (FieldInfo staticField in nestedType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static))
+ {
+ AddProviderEnumKind(manifest, staticField, providerEnumKind);
+ }
+ }
+ }
+ }
+ // ensure we have keywords for the session-filtering reserved bits
+ {
+ manifest.AddKeyword("Session3", (long)0x1000 << 32);
+ manifest.AddKeyword("Session2", (long)0x2000 << 32);
+ manifest.AddKeyword("Session1", (long)0x4000 << 32);
+ manifest.AddKeyword("Session0", (long)0x8000 << 32);
+ }
+
+ if (eventSourceType != typeof(EventSource))
+ {
+ for (int i = 0; i < methods.Length; i++)
+ {
+ MethodInfo method = methods[i];
+ ParameterInfo[] args = method.GetParameters();
+
+ // Get the EventDescriptor (from the Custom attributes)
+ EventAttribute eventAttribute = (EventAttribute)GetCustomAttributeHelper(method, typeof(EventAttribute), flags);
+
+ // 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
+ // design of having event sources implement specific interfaces. To fix this in a compatible way
+ // we will now allow both non-void returning and virtual methods to be Event methods, as long
+ // as they are marked with the [Event] attribute
+ if (/* method.IsVirtual || */ method.IsStatic)
+ {
+ continue;
+ }
+
+ if (eventSourceType.IsAbstract())
+ {
+ if (eventAttribute != null)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareEventMethods", method.Name, eventAttribute.EventId));
+ }
+ continue;
+ }
+ else if (eventAttribute == null)
+ {
+ // Methods that don't return void can't be events, if they're NOT marked with [Event].
+ // (see Compat comment above)
+ if (method.ReturnType != typeof(void))
+ {
+ continue;
+ }
+
+ // Continue to ignore virtual methods if they do NOT have the [Event] attribute
+ // (see Compat comment above)
+ if (method.IsVirtual)
+ {
+ continue;
+ }
+
+ // If we explicitly mark the method as not being an event, then honor that.
+ if (GetCustomAttributeHelper(method, typeof(NonEventAttribute), flags) != null)
+ continue;
+
+ defaultEventAttribute = new EventAttribute(eventId);
+ eventAttribute = defaultEventAttribute;
+ }
+ else if (eventAttribute.EventId <= 0)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_NeedPositiveId", method.Name), true);
+ continue; // don't validate anything else for this event
+ }
+ if (method.Name.LastIndexOf('.') >= 0)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventMustNotBeExplicitImplementation", method.Name, eventAttribute.EventId));
+ }
+
+ eventId++;
+ string eventName = method.Name;
+
+ 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 (noTask)
+ eventAttribute.Task = (EventTask)(0xFFFE - eventAttribute.EventId);
+
+ // 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)
+ {
+ if (eventAttribute.Opcode == EventOpcode.Start)
+ {
+ string taskName = eventName.Substring(0, eventName.Length - s_ActivityStartSuffix.Length); // Remove the Stop suffix to get the task name
+ if (string.Compare(eventName, 0, taskName, 0, taskName.Length) == 0 &&
+ string.Compare(eventName, taskName.Length, s_ActivityStartSuffix, 0, Math.Max(eventName.Length - taskName.Length, s_ActivityStartSuffix.Length)) == 0)
+ {
+ // Add a task that is just the task name for the start event. This suppress the auto-task generation
+ // That would otherwise happen (and create 'TaskName'Start as task name rather than just 'TaskName'
+ manifest.AddTask(taskName, (int)eventAttribute.Task);
+ }
+ }
+ else if (eventAttribute.Opcode == EventOpcode.Stop)
+ {
+ // Find the start associated with this stop event. We require start to be immediately before the stop
+ int startEventId = eventAttribute.EventId - 1;
+ if (eventData != null && startEventId < eventData.Length)
+ {
+ Contract.Assert(0 <= startEventId); // Since we reserve id 0, we know that id-1 is <= 0
+ EventMetadata startEventMetadata = eventData[startEventId];
+
+ // If you remove the Stop and add a Start does that name match the Start Event's Name?
+ // Ideally we would throw an error
+ string taskName = eventName.Substring(0, eventName.Length - s_ActivityStopSuffix.Length); // Remove the Stop suffix to get the task name
+ if (startEventMetadata.Descriptor.Opcode == (byte)EventOpcode.Start &&
+ string.Compare(startEventMetadata.Name, 0, taskName, 0, taskName.Length) == 0 &&
+ string.Compare(startEventMetadata.Name, taskName.Length, s_ActivityStartSuffix, 0, Math.Max(startEventMetadata.Name.Length - taskName.Length, s_ActivityStartSuffix.Length)) == 0)
+ {
+
+ // Make the stop event match the start event
+ eventAttribute.Task = (EventTask)startEventMetadata.Descriptor.Task;
+ noTask = false;
+ }
+ }
+ if (noTask && (flags & EventManifestOptions.Strict) != 0) // Throw an error if we can compatibly.
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_StopsFollowStarts"));
+ }
+ }
+ }
+ }
+
+ bool hasRelatedActivityID = RemoveFirstArgIfRelatedActivityId(ref args);
+ if (!(source != null && source.SelfDescribingEvents))
+ {
+ manifest.StartEvent(eventName, eventAttribute);
+ for (int fieldIdx = 0; fieldIdx < args.Length; fieldIdx++)
+ {
+ manifest.AddEventParameter(args[fieldIdx].ParameterType, args[fieldIdx].Name);
+ }
+ manifest.EndEvent();
+ }
+
+ 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, flags);
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ // add the channel keyword for Event Viewer channel based filters. This is added for creating the EventDescriptors only
+ // and is not required for the manifest
+ if (eventAttribute.Channel != EventChannel.None)
+ {
+ unchecked
+ {
+ eventAttribute.Keywords |= (EventKeywords)manifest.GetChannelKeyword(eventAttribute.Channel, (ulong) eventAttribute.Keywords);
+ }
+ }
+#endif
+ string eventKey = "event_" + eventName;
+ string msg = manifest.GetLocalizedMessage(eventKey, CultureInfo.CurrentUICulture, etwFormat: false);
+ // overwrite inline message with the localized message
+ if (msg != null) eventAttribute.Message = msg;
+
+ AddEventDescriptor(ref eventData, eventName, eventAttribute, args, hasRelatedActivityID);
+ }
+ }
+ }
+
+ // Tell the TraceLogging stuff where to start allocating its own IDs.
+ NameInfo.ReserveEventIDsBelow(eventId);
+
+ if (source != null)
+ {
+ TrimEventDescriptors(ref eventData);
+ source.m_eventData = eventData; // officially initialize it. We do this at most once (it is racy otherwise).
+#if FEATURE_MANAGED_ETW_CHANNELS
+ source.m_channelData = manifest.GetChannelData();
+#endif
+ }
+
+ // if this is an abstract event source we've already performed all the validation we can
+ if (!eventSourceType.IsAbstract() && (source == null || !source.SelfDescribingEvents))
+ {
+ bNeedsManifest = (flags & EventManifestOptions.OnlyIfNeededForRegistration) == 0
+#if FEATURE_MANAGED_ETW_CHANNELS
+ || manifest.GetChannelData().Length > 0
+#endif
+;
+
+ // if the manifest is not needed and we're not requested to validate the event source return early
+ if (!bNeedsManifest && (flags & EventManifestOptions.Strict) == 0)
+ return null;
+
+ res = manifest.CreateManifest();
+ }
+ }
+ catch (Exception e)
+ {
+ // if this is a runtime manifest generation let the exception propagate
+ if ((flags & EventManifestOptions.Strict) == 0)
+ throw;
+ // else store it to include it in the Argument exception we raise below
+ exception = e;
+ }
+
+ if ((flags & EventManifestOptions.Strict) != 0 && (manifest.Errors.Count > 0 || exception != null))
+ {
+ string msg = String.Empty;
+ if (manifest.Errors.Count > 0)
+ {
+ bool firstError = true;
+ foreach (string error in manifest.Errors)
+ {
+ if (!firstError)
+ msg += Environment.NewLine;
+ firstError = false;
+ msg += error;
+ }
+ }
+ else
+ msg = "Unexpected error: " + exception.Message;
+
+ throw new ArgumentException(msg, exception);
+ }
+
+ return bNeedsManifest ? res : null;
+ }
+
+ 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) &&
+ string.Compare(args[0].Name, "relatedActivityId", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ 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'
+ // to the manifest.
+ private static void AddProviderEnumKind(ManifestBuilder manifest, FieldInfo staticField, string providerEnumKind)
+ {
+ bool reflectionOnly = staticField.Module.Assembly.ReflectionOnly();
+ Type staticFieldType = staticField.FieldType;
+ if (!reflectionOnly && (staticFieldType == typeof(EventOpcode)) || AttributeTypeNamesMatch(staticFieldType, typeof(EventOpcode)))
+ {
+ if (providerEnumKind != "Opcodes") goto Error;
+ int value = (int)staticField.GetRawConstantValue();
+ manifest.AddOpcode(staticField.Name, value);
+ }
+ else if (!reflectionOnly && (staticFieldType == typeof(EventTask)) || AttributeTypeNamesMatch(staticFieldType, typeof(EventTask)))
+ {
+ if (providerEnumKind != "Tasks") goto Error;
+ int value = (int)staticField.GetRawConstantValue();
+ manifest.AddTask(staticField.Name, value);
+ }
+ else if (!reflectionOnly && (staticFieldType == typeof(EventKeywords)) || AttributeTypeNamesMatch(staticFieldType, typeof(EventKeywords)))
+ {
+ if (providerEnumKind != "Keywords") goto Error;
+ ulong value = unchecked((ulong)(long)staticField.GetRawConstantValue());
+ manifest.AddKeyword(staticField.Name, value);
+ }
+#if FEATURE_MANAGED_ETW_CHANNELS && FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ else if (!reflectionOnly && (staticFieldType == typeof(EventChannel)) || AttributeTypeNamesMatch(staticFieldType, typeof(EventChannel)))
+ {
+ if (providerEnumKind != "Channels") goto Error;
+ var channelAttribute = (EventChannelAttribute)GetCustomAttributeHelper(staticField, typeof(EventChannelAttribute));
+ manifest.AddChannel(staticField.Name, (byte)staticField.GetRawConstantValue(), channelAttribute);
+ }
+#endif
+ return;
+ Error:
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind));
+ }
+
+ // Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method
+ // 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,
+ bool hasRelatedActivityID)
+ {
+ if (eventData == null || eventData.Length <= eventAttribute.EventId)
+ {
+ EventMetadata[] newValues = new EventMetadata[Math.Max(eventData.Length + 16, eventAttribute.EventId + 1)];
+ Array.Copy(eventData, 0, newValues, 0, eventData.Length);
+ eventData = newValues;
+ }
+
+ eventData[eventAttribute.EventId].Descriptor = new EventDescriptor(
+ eventAttribute.EventId,
+ eventAttribute.Version,
+#if FEATURE_MANAGED_ETW_CHANNELS
+ (byte)eventAttribute.Channel,
+#else
+ (byte)0,
+#endif
+ (byte)eventAttribute.Level,
+ (byte)eventAttribute.Opcode,
+ (int)eventAttribute.Task,
+ unchecked((long)((ulong)eventAttribute.Keywords | SessionMask.All.ToEventKeywords())));
+
+ eventData[eventAttribute.EventId].Tags = eventAttribute.Tags;
+ eventData[eventAttribute.EventId].Name = eventName;
+ 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
+ // size after all event descriptors have been added.
+ private static void TrimEventDescriptors(ref EventMetadata[] eventData)
+ {
+ int idx = eventData.Length;
+ while (0 < idx)
+ {
+ --idx;
+ if (eventData[idx].Descriptor.EventId != 0)
+ break;
+ }
+ if (eventData.Length - idx > 2) // allow one wasted slot.
+ {
+ EventMetadata[] newValues = new EventMetadata[idx + 1];
+ Array.Copy(eventData, 0, newValues, 0, newValues.Length);
+ eventData = newValues;
+ }
+ }
+
+ // Helper used by code:EventListener.AddEventSource and code:EventListener.EventListener
+ // when a listener gets attached to a eventSource
+ internal void AddListener(EventListener listener)
+ {
+ lock (EventListener.EventListenersLock)
+ {
+ bool[] enabledArray = null;
+ if (m_eventData != null)
+ enabledArray = new bool[m_eventData.Length];
+ m_Dispatchers = new EventDispatcher(m_Dispatchers, enabledArray, listener);
+ listener.OnEventSourceCreated(this);
+ }
+ }
+
+ // Helper used by code:CreateManifestAndDescriptors to find user mistakes like reusing an event
+ // 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, EventManifestOptions options)
+ {
+ int evtId = eventAttribute.EventId;
+ string evtName = method.Name;
+ int eventArg = GetHelperCallFirstArg(method);
+ if (eventArg >= 0 && evtId != eventArg)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_MismatchIdToWriteEvent", evtName, evtId, eventArg), true);
+ }
+
+ if (evtId < eventData.Length && eventData[evtId].Descriptor.EventId != 0)
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventIdReused", evtName, evtId, eventData[evtId].Name), true);
+ }
+
+ // We give a task to things if they don't have one.
+ // TODO this is moderately expensive (N*N). We probably should not even bother....
+ Contract.Assert(eventAttribute.Task != EventTask.None || eventAttribute.Opcode != EventOpcode.Info);
+ for (int idx = 0; idx < eventData.Length; ++idx)
+ {
+ // skip unused Event IDs.
+ if (eventData[idx].Name == null)
+ continue;
+
+ if (eventData[idx].Descriptor.Task == (int)eventAttribute.Task && eventData[idx].Descriptor.Opcode == (int)eventAttribute.Opcode)
+ {
+ manifest.ManifestError(Resources.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)
+ {
+ 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(Resources.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+ }
+ }
+
+ // If we ever want to enforce the rule: MethodName = TaskName + OpcodeName here's how:
+ // (the reason we don't is backwards compat and the need for handling this as a non-fatal error
+ // by eventRegister.exe)
+ // taskName & opcodeName could be passed in by the caller which has opTab & taskTab handy
+ // if (!(((int)eventAttribute.Opcode == 0 && evtName == taskName) || (evtName == taskName+opcodeName)))
+ // {
+ // throw new WarningException(Resources.GetResourceString("EventSource_EventNameDoesNotEqualTaskPlusOpcode"));
+ // }
+
+ if (eventsByName == null)
+ eventsByName = new Dictionary<string, string>();
+
+ if (eventsByName.ContainsKey(evtName))
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventNameReused", evtName), true);
+ }
+
+ eventsByName[evtName] = evtName;
+ }
+
+ /// <summary>
+ /// This method looks at the IL and tries to pattern match against the standard
+ /// 'boilerplate' event body
+ /// <code>
+ /// { if (Enabled()) WriteEvent(#, ...) }
+ /// </code>
+ /// If the pattern matches, it returns the literal number passed as the first parameter to
+ /// the WriteEvent. This is used to find common user errors (mismatching this
+ /// number with the EventAttribute ID). It is only used for validation.
+ /// </summary>
+ /// <param name="method">The method to probe.</param>
+ /// <returns>The literal value or -1 if the value could not be determined. </returns>
+ [SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
+ static private int GetHelperCallFirstArg(MethodInfo method)
+ {
+#if (!ES_BUILD_PCL && !PROJECTN)
+ // Currently searches for the following pattern
+ //
+ // ... // CAN ONLY BE THE INSTRUCTIONS BELOW
+ // LDARG0
+ // LDC.I4 XXX
+ // ... // CAN ONLY BE THE INSTRUCTIONS BELOW CAN'T BE A BRANCH OR A CALL
+ // CALL
+ // NOP // 0 or more times
+ // RET
+ //
+ // If we find this pattern we return the XXX. Otherwise we return -1.
+ (new ReflectionPermission(ReflectionPermissionFlag.MemberAccess)).Assert();
+ byte[] instrs = method.GetMethodBody().GetILAsByteArray();
+ int retVal = -1;
+ for (int idx = 0; idx < instrs.Length; )
+ {
+ switch (instrs[idx])
+ {
+ case 0: // NOP
+ case 1: // BREAK
+ case 2: // LDARG_0
+ case 3: // LDARG_1
+ case 4: // LDARG_2
+ case 5: // LDARG_3
+ case 6: // LDLOC_0
+ case 7: // LDLOC_1
+ case 8: // LDLOC_2
+ case 9: // LDLOC_3
+ case 10: // STLOC_0
+ case 11: // STLOC_1
+ case 12: // STLOC_2
+ case 13: // STLOC_3
+ break;
+ case 14: // LDARG_S
+ case 16: // STARG_S
+ idx++;
+ break;
+ case 20: // LDNULL
+ break;
+ case 21: // LDC_I4_M1
+ case 22: // LDC_I4_0
+ case 23: // LDC_I4_1
+ case 24: // LDC_I4_2
+ case 25: // LDC_I4_3
+ case 26: // LDC_I4_4
+ case 27: // LDC_I4_5
+ case 28: // LDC_I4_6
+ case 29: // LDC_I4_7
+ case 30: // LDC_I4_8
+ if (idx > 0 && instrs[idx - 1] == 2) // preceeded by LDARG0
+ retVal = instrs[idx] - 22;
+ break;
+ case 31: // LDC_I4_S
+ if (idx > 0 && instrs[idx - 1] == 2) // preceeded by LDARG0
+ retVal = instrs[idx + 1];
+ idx++;
+ break;
+ case 32: // LDC_I4
+ idx += 4;
+ break;
+ case 37: // DUP
+ break;
+ case 40: // CALL
+ idx += 4;
+
+ if (retVal >= 0)
+ {
+ // Is this call just before return?
+ for (int search = idx + 1; search < instrs.Length; search++)
+ {
+ if (instrs[search] == 42) // RET
+ return retVal;
+ if (instrs[search] != 0) // NOP
+ break;
+ }
+ }
+ retVal = -1;
+ break;
+ case 44: // BRFALSE_S
+ case 45: // BRTRUE_S
+ retVal = -1;
+ idx++;
+ break;
+ case 57: // BRFALSE
+ case 58: // BRTRUE
+ retVal = -1;
+ idx += 4;
+ break;
+ case 103: // CONV_I1
+ case 104: // CONV_I2
+ case 105: // CONV_I4
+ case 106: // CONV_I8
+ case 109: // CONV_U4
+ case 110: // CONV_U8
+ break;
+ case 140: // BOX
+ case 141: // NEWARR
+ idx += 4;
+ break;
+ case 162: // STELEM_REF
+ break;
+ case 254: // PREFIX
+ idx++;
+ // Covers the CEQ instructions used in debug code for some reason.
+ if (idx >= instrs.Length || instrs[idx] >= 6)
+ goto default;
+ break;
+ default:
+ /* Contract.Assert(false, "Warning: User validation code sub-optimial: Unsuported opcode " + instrs[idx] +
+ " at " + idx + " in method " + method.Name); */
+ return -1;
+ }
+ idx++;
+ }
+#endif
+ return -1;
+ }
+
+#if false // This routine is not needed at all, it was used for unit test debugging.
+ [Conditional("DEBUG")]
+ private static void OutputDebugString(string msg)
+ {
+#if !ES_BUILD_PCL
+ msg = msg.TrimEnd('\r', '\n') +
+ string.Format(CultureInfo.InvariantCulture, ", Thrd({0})" + Environment.NewLine, Thread.CurrentThread.ManagedThreadId);
+ System.Diagnostics.Debugger.Log(0, null, msg);
+#endif
+ }
+#endif
+
+ /// <summary>
+ /// Sends an error message to the debugger (outputDebugString), as well as the EventListeners
+ /// It will do this even if the EventSource is not enabled.
+ /// TODO remove flush parameter it is not used.
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ internal void ReportOutOfBandMessage(string msg, bool flush)
+ {
+ try
+ {
+#if (!ES_BUILD_PCL && !PROJECTN)
+ // send message to debugger without delay
+ System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg , Environment.NewLine));
+#endif
+
+ // Send it to all listeners.
+ if (m_outOfBandMessageCount < 16 - 1) // Note this is only if size byte
+ m_outOfBandMessageCount++;
+ else
+ {
+ if (m_outOfBandMessageCount == 16)
+ return;
+ 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.";
+ }
+
+ WriteEventString(EventLevel.LogAlways, -1, msg);
+ WriteStringToAllListeners("EventSourceMessage", msg);
+ }
+ catch (Exception) { } // If we fail during last chance logging, well, we have to give up....
+ }
+
+ private EventSourceSettings ValidateSettings(EventSourceSettings settings)
+ {
+ var evtFormatMask = EventSourceSettings.EtwManifestEventFormat |
+ EventSourceSettings.EtwSelfDescribingEventFormat;
+ if ((settings & evtFormatMask) == evtFormatMask)
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidEventFormat"), nameof(settings));
+ }
+
+ // If you did not explicitly ask for manifest, you get self-describing.
+ if ((settings & evtFormatMask) == 0)
+ settings |= EventSourceSettings.EtwSelfDescribingEventFormat;
+ return settings;
+ }
+
+ private bool ThrowOnEventWriteErrors
+ {
+ get { return (m_config & EventSourceSettings.ThrowOnEventWriteErrors) != 0; }
+ set
+ {
+ if (value) m_config |= EventSourceSettings.ThrowOnEventWriteErrors;
+ else m_config &= ~EventSourceSettings.ThrowOnEventWriteErrors;
+ }
+ }
+
+ private bool SelfDescribingEvents
+ {
+ get
+ {
+ Contract.Assert(((m_config & EventSourceSettings.EtwManifestEventFormat) != 0) !=
+ ((m_config & EventSourceSettings.EtwSelfDescribingEventFormat) != 0));
+ return (m_config & EventSourceSettings.EtwSelfDescribingEventFormat) != 0;
+ }
+ set
+ {
+ if (!value)
+ {
+ m_config |= EventSourceSettings.EtwManifestEventFormat;
+ m_config &= ~EventSourceSettings.EtwSelfDescribingEventFormat;
+ }
+ else
+ {
+ m_config |= EventSourceSettings.EtwSelfDescribingEventFormat;
+ m_config &= ~EventSourceSettings.EtwManifestEventFormat;
+ }
+ }
+ }
+
+#if FEATURE_ACTIVITYSAMPLING
+ private void ReportActivitySamplingInfo(EventListener listener, SessionMask sessions)
+ {
+ Contract.Assert(listener == null || (uint)sessions == (uint)SessionMask.FromId(0));
+
+ for (int perEventSourceSessionId = 0; perEventSourceSessionId < SessionMask.MAX; ++perEventSourceSessionId)
+ {
+ if (!sessions[perEventSourceSessionId])
+ continue;
+
+ ActivityFilter af;
+ if (listener == null)
+ {
+ EtwSession etwSession = m_etwSessionIdMap[perEventSourceSessionId];
+ Contract.Assert(etwSession != null);
+ af = etwSession.m_activityFilter;
+ }
+ else
+ {
+ af = listener.m_activityFilter;
+ }
+
+ if (af == null)
+ continue;
+
+ SessionMask m = new SessionMask();
+ m[perEventSourceSessionId] = true;
+
+ foreach (var t in af.GetFilterAsTuple(m_guid))
+ {
+ WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: {1} = {2}", perEventSourceSessionId, t.Item1, t.Item2), m);
+ }
+
+ bool participateInSampling = (listener == null) ?
+ m_activityFilteringForETWEnabled[perEventSourceSessionId] :
+ GetDispatcher(listener).m_activityFilteringEnabled;
+ WriteStringToListener(listener, string.Format(CultureInfo.InvariantCulture, "Session {0}: Activity Sampling support: {1}",
+ perEventSourceSessionId, participateInSampling ? "enabled" : "disabled"), m);
+ }
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // private instance state
+ private string m_name; // My friendly name (privided in ctor)
+ internal int m_id; // A small integer that is unique to this instance.
+ private Guid m_guid; // GUID representing the ETW eventSource to the OS.
+ 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
+
+ private bool m_eventSourceDisposed; // has Dispose been called.
+
+ // Enabling bits
+ private bool m_eventSourceEnabled; // am I enabled (any of my events are enabled for any dispatcher)
+ internal EventLevel m_level; // highest level enabled by any output dispatcher
+ internal EventKeywords m_matchAnyKeyword; // the logical OR of all levels enabled by any output dispatcher (zero is a special case) meaning 'all keywords'
+
+ // Dispatching state
+ internal volatile EventDispatcher m_Dispatchers; // Linked list of code:EventDispatchers we write the data to (we also do ETW specially)
+#if FEATURE_MANAGED_ETW
+ private volatile OverideEventProvider m_provider; // This hooks up ETW commands to our 'OnEventCommand' callback
+#endif
+ private bool m_completelyInited; // The EventSource constructor has returned without exception.
+ private Exception m_constructionException; // If there was an exception construction, this is it
+ private byte m_outOfBandMessageCount; // The number of out of band messages sent (we throttle them
+ private EventCommandEventArgs m_deferredCommands;// If we get commands before we are fully we store them here and run the when we are fully inited.
+
+ private string[] m_traits; // Used to implement GetTraits
+
+ internal static uint s_currentPid; // current process id, used in synthesizing quasi-GUIDs
+ [ThreadStatic]
+ private static byte m_EventSourceExceptionRecurenceCount = 0; // current recursion count inside ThrowEventSourceException
+
+ [ThreadStatic]
+ private static bool m_EventSourceInDecodeObject = false;
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ internal volatile ulong[] m_channelData;
+#endif
+
+#if FEATURE_ACTIVITYSAMPLING
+ private SessionMask m_curLiveSessions; // the activity-tracing aware sessions' bits
+ private EtwSession[] m_etwSessionIdMap; // the activity-tracing aware sessions
+ private List<EtwSession> m_legacySessions; // the legacy ETW sessions listening to this source
+ internal long m_keywordTriggers; // a bit is set if it corresponds to a keyword that's part of an enabled triggering event
+ internal SessionMask m_activityFilteringForETWEnabled; // does THIS EventSource have activity filtering turned on for each ETW session
+ static internal Action<Guid> s_activityDying; // Fires when something calls SetCurrentThreadToActivity()
+ // Also used to mark that activity tracing is on for some case
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // We use a single instance of ActivityTracker for all EventSources instances to allow correlation between multiple event providers.
+ // We have m_activityTracker field simply because instance field is more efficient than static field fetch.
+ ActivityTracker m_activityTracker;
+ internal const string s_ActivityStartSuffix = "Start";
+ internal const string s_ActivityStopSuffix = "Stop";
+
+ // used for generating GUID from eventsource name
+ private static readonly byte[] namespaceBytes = new byte[] {
+ 0x48, 0x2C, 0x2D, 0xB2, 0xC3, 0x90, 0x47, 0xC8,
+ 0x87, 0xF8, 0x1A, 0x15, 0xBF, 0xC1, 0x30, 0xFB,
+ };
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Enables specifying event source configuration options to be used in the EventSource constructor.
+ /// </summary>
+ [Flags]
+ public enum EventSourceSettings
+ {
+ /// <summary>
+ /// This specifies none of the special configuration options should be enabled.
+ /// </summary>
+ Default = 0,
+ /// <summary>
+ /// Normally an EventSource NEVER throws; setting this option will tell it to throw when it encounters errors.
+ /// </summary>
+ ThrowOnEventWriteErrors = 1,
+ /// <summary>
+ /// Setting this option is a directive to the ETW listener should use manifest-based format when
+ /// firing events. This is the default option when defining a type derived from EventSource
+ /// (using the protected EventSource constructors).
+ /// Only one of EtwManifestEventFormat or EtwSelfDescribingEventFormat should be specified
+ /// </summary>
+ EtwManifestEventFormat = 4,
+ /// <summary>
+ /// Setting this option is a directive to the ETW listener should use self-describing event format
+ /// when firing events. This is the default option when creating a new instance of the EventSource
+ /// type (using the public EventSource constructors).
+ /// Only one of EtwManifestEventFormat or EtwSelfDescribingEventFormat should be specified
+ /// </summary>
+ EtwSelfDescribingEventFormat = 8,
+ }
+
+ /// <summary>
+ /// An EventListener represents a target for the events generated by EventSources (that is subclasses
+ /// of <see cref="EventSource"/>), in the current appdomain. When a new EventListener is created
+ /// it is logically attached to all eventSources in that appdomain. When the EventListener is Disposed, then
+ /// it is disconnected from the event eventSources. Note that there is a internal list of STRONG references
+ /// to EventListeners, which means that relying on the lack of references to EventListeners to clean up
+ /// EventListeners will NOT work. You must call EventListener.Dispose explicitly when a dispatcher is no
+ /// longer needed.
+ /// <para>
+ /// Once created, EventListeners can enable or disable on a per-eventSource basis using verbosity levels
+ /// (<see cref="EventLevel"/>) and bitfields (<see cref="EventKeywords"/>) to further restrict the set of
+ /// events to be sent to the dispatcher. The dispatcher can also send arbitrary commands to a particular
+ /// eventSource using the 'SendCommand' method. The meaning of the commands are eventSource specific.
+ /// </para><para>
+ /// The Null Guid (that is (new Guid()) has special meaning as a wildcard for 'all current eventSources in
+ /// the appdomain'. Thus it is relatively easy to turn on all events in the appdomain if desired.
+ /// </para><para>
+ /// It is possible for there to be many EventListener's defined in a single appdomain. Each dispatcher is
+ /// logically independent of the other listeners. Thus when one dispatcher enables or disables events, it
+ /// affects only that dispatcher (other listeners get the events they asked for). It is possible that
+ /// commands sent with 'SendCommand' would do a semantic operation that would affect the other listeners
+ /// (like doing a GC, or flushing data ...), but this is the exception rather than the rule.
+ /// </para><para>
+ /// Thus the model is that each EventSource keeps a list of EventListeners that it is sending events
+ /// to. Associated with each EventSource-dispatcher pair is a set of filtering criteria that determine for
+ /// that eventSource what events that dispatcher will receive.
+ /// </para><para>
+ /// Listeners receive the events on their 'OnEventWritten' method. Thus subclasses of EventListener must
+ /// override this method to do something useful with the data.
+ /// </para><para>
+ /// In addition, when new eventSources are created, the 'OnEventSourceCreate' method is called. The
+ /// invariant associated with this callback is that every eventSource gets exactly one
+ /// 'OnEventSourceCreate' call for ever eventSource that can potentially send it log messages. In
+ /// particular when a EventListener is created, typically a series of OnEventSourceCreate' calls are
+ /// made to notify the new dispatcher of all the eventSources that existed before the EventListener was
+ /// created.
+ /// </para>
+ /// </summary>
+ public class EventListener : IDisposable
+ {
+ private event EventHandler<EventSourceCreatedEventArgs> _EventSourceCreated;
+
+ /// <summary>
+ /// 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>
+ public event EventHandler<EventSourceCreatedEventArgs> EventSourceCreated
+ {
+ add
+ {
+ CallBackForExistingEventSources(false, value);
+
+ this._EventSourceCreated = (EventHandler<EventSourceCreatedEventArgs>)Delegate.Combine(_EventSourceCreated, value);
+ }
+ remove
+ {
+ 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
+ /// is the only way to actually make the listen die. Thus it is important that users of EventListener
+ /// call Dispose when they are done with their logging.
+ /// </summary>
+#if ES_BUILD_STANDALONE
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
+#endif
+ public virtual void Dispose()
+ {
+ lock (EventListenersLock)
+ {
+ if (s_Listeners != null)
+ {
+ if (this == s_Listeners)
+ {
+ EventListener cur = s_Listeners;
+ s_Listeners = this.m_Next;
+ RemoveReferencesToListenerInEventSources(cur);
+ }
+ else
+ {
+ // Find 'this' from the s_Listeners linked list.
+ EventListener prev = s_Listeners;
+ for (; ; )
+ {
+ EventListener cur = prev.m_Next;
+ if (cur == null)
+ break;
+ if (cur == this)
+ {
+ // Found our Listener, remove references to to it in the eventSources
+ prev.m_Next = cur.m_Next; // Remove entry.
+ RemoveReferencesToListenerInEventSources(cur);
+ break;
+ }
+ prev = cur;
+ }
+ }
+ }
+ Validate();
+ }
+ }
+ // We don't expose a Dispose(bool), because the contract is that you don't have any non-syncronous
+ // 'cleanup' associated with this object
+
+ /// <summary>
+ /// Enable all events from the eventSource identified by 'eventSource' to the current
+ /// dispatcher that have a verbosity level of 'level' or lower.
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
+ /// dispatcher if 'level' indicates a less verbose level than was previously enabled.
+ ///
+ /// This call never has an effect on other EventListeners.
+ ///
+ /// </summary>
+ public void EnableEvents(EventSource eventSource, EventLevel level)
+ {
+ EnableEvents(eventSource, level, EventKeywords.None);
+ }
+ /// <summary>
+ /// Enable all events from the eventSource identified by 'eventSource' to the current
+ /// dispatcher that have a verbosity level of 'level' or lower and have a event keyword
+ /// matching any of the bits in 'matchAnyKeyword'.
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
+ /// dispatcher if 'level' indicates a less verbose level than was previously enabled or
+ /// if 'matchAnyKeyword' has fewer keywords set than where previously set.
+ ///
+ /// This call never has an effect on other EventListeners.
+ /// </summary>
+ public void EnableEvents(EventSource eventSource, EventLevel level, EventKeywords matchAnyKeyword)
+ {
+ EnableEvents(eventSource, level, matchAnyKeyword, null);
+ }
+ /// <summary>
+ /// Enable all events from the eventSource identified by 'eventSource' to the current
+ /// dispatcher that have a verbosity level of 'level' or lower and have a event keyword
+ /// matching any of the bits in 'matchAnyKeyword' as well as any (eventSource specific)
+ /// effect passing additional 'key-value' arguments 'arguments' might have.
+ ///
+ /// This call can have the effect of REDUCING the number of events sent to the
+ /// dispatcher if 'level' indicates a less verbose level than was previously enabled or
+ /// if 'matchAnyKeyword' has fewer keywords set than where previously set.
+ ///
+ /// This call never has an effect on other EventListeners.
+ /// </summary>
+ public void EnableEvents(EventSource eventSource, EventLevel level, EventKeywords matchAnyKeyword, IDictionary<string, string> arguments)
+ {
+ if (eventSource == null)
+ {
+ throw new ArgumentNullException(nameof(eventSource));
+ }
+ Contract.EndContractBlock();
+
+ eventSource.SendCommand(this, 0, 0, EventCommand.Update, true, level, matchAnyKeyword, arguments);
+ }
+ /// <summary>
+ /// Disables all events coming from eventSource identified by 'eventSource'.
+ ///
+ /// This call never has an effect on other EventListeners.
+ /// </summary>
+ public void DisableEvents(EventSource eventSource)
+ {
+ if (eventSource == null)
+ {
+ throw new ArgumentNullException(nameof(eventSource));
+ }
+ Contract.EndContractBlock();
+
+ eventSource.SendCommand(this, 0, 0, EventCommand.Update, false, EventLevel.LogAlways, EventKeywords.None, null);
+ }
+
+ /// <summary>
+ /// EventSourceIndex is small non-negative integer (suitable for indexing in an array)
+ /// identifying EventSource. It is unique per-appdomain. Some EventListeners might find
+ /// it useful to store additional information about each eventSource connected to it,
+ /// and EventSourceIndex allows this extra information to be efficiently stored in a
+ /// (growable) array (eg List(T)).
+ /// </summary>
+ public static int EventSourceIndex(EventSource eventSource) { return eventSource.m_id; }
+
+ /// <summary>
+ /// This method is called 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 'OnEventWritten' callbacks
+ /// for a particular eventSource to occur BEFORE the OnEventSourceCreated is issued.
+ /// </summary>
+ /// <param name="eventSource"></param>
+ 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>
+ /// <param name="eventData"></param>
+ internal protected virtual void OnEventWritten(EventWrittenEventArgs eventData)
+ {
+ EventHandler<EventWrittenEventArgs> callBack = this.EventWritten;
+ if (callBack != null)
+ {
+ callBack(this, eventData);
+ }
+ }
+
+
+ #region private
+ /// <summary>
+ /// This routine adds newEventSource to the global list of eventSources, it also assigns the
+ /// ID to the eventSource (which is simply the ordinal in the global list).
+ ///
+ /// EventSources currently do not pro-actively remove themselves from this list. Instead
+ /// when eventSources's are GCed, the weak handle in this list naturally gets nulled, and
+ /// we will reuse the slot. Today this list never shrinks (but we do reuse entries
+ /// that are in the list). This seems OK since the expectation is that EventSources
+ /// tend to live for the lifetime of the appdomain anyway (they tend to be used in
+ /// global variables).
+ /// </summary>
+ /// <param name="newEventSource"></param>
+ internal static void AddEventSource(EventSource newEventSource)
+ {
+ lock (EventListenersLock)
+ {
+ if (s_EventSources == null)
+ s_EventSources = new List<WeakReference>(2);
+
+ if (!s_EventSourceShutdownRegistered)
+ {
+ s_EventSourceShutdownRegistered = true;
+#if (!ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN)
+ AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown;
+ AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown;
+#endif
+ }
+
+
+ // Periodically search the list for existing entries to reuse, this avoids
+ // unbounded memory use if we keep recycling eventSources (an unlikely thing).
+ int newIndex = -1;
+ if (s_EventSources.Count % 64 == 63) // on every block of 64, fill up the block before continuing
+ {
+ int i = s_EventSources.Count; // Work from the top down.
+ while (0 < i)
+ {
+ --i;
+ WeakReference weakRef = s_EventSources[i];
+ if (!weakRef.IsAlive)
+ {
+ newIndex = i;
+ weakRef.Target = newEventSource;
+ break;
+ }
+ }
+ }
+ if (newIndex < 0)
+ {
+ newIndex = s_EventSources.Count;
+ s_EventSources.Add(new WeakReference(newEventSource));
+ }
+ newEventSource.m_id = newIndex;
+
+ // Add every existing dispatcher to the new EventSource
+ for (EventListener listener = s_Listeners; listener != null; listener = listener.m_Next)
+ newEventSource.AddListener(listener);
+
+ Validate();
+ }
+ }
+
+ // Whenver we have async callbacks from native code, there is an ugly issue where
+ // during .NET shutdown native code could be calling the callback, but the CLR
+ // has already prohibited callbacks to managed code in the appdomain, causing the CLR
+ // to throw a COMPLUS_BOOT_EXCEPTION. The guideline we give is that you must unregister
+ // such callbacks on process shutdown or appdomain so that unmanaged code will never
+ // do this. This is what this callback is for.
+ // See bug 724140 for more
+ private static void DisposeOnShutdown(object sender, EventArgs e)
+ {
+ lock(EventListenersLock)
+ {
+ foreach (var esRef in s_EventSources)
+ {
+ EventSource es = esRef.Target as EventSource;
+ if (es != null)
+ es.Dispose();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Helper used in code:Dispose that removes any references to 'listenerToRemove' in any of the
+ /// eventSources in the appdomain.
+ ///
+ /// The EventListenersLock must be held before calling this routine.
+ /// </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)
+ {
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource != null)
+ {
+ // Is the first output dispatcher the dispatcher we are removing?
+ if (eventSource.m_Dispatchers.m_Listener == listenerToRemove)
+ eventSource.m_Dispatchers = eventSource.m_Dispatchers.m_Next;
+ else
+ {
+ // Remove 'listenerToRemove' from the eventSource.m_Dispatchers linked list.
+ EventDispatcher prev = eventSource.m_Dispatchers;
+ for (; ; )
+ {
+ EventDispatcher cur = prev.m_Next;
+ if (cur == null)
+ {
+ Contract.Assert(false, "EventSource did not have a registered EventListener!");
+ break;
+ }
+ if (cur.m_Listener == listenerToRemove)
+ {
+ prev.m_Next = cur.m_Next; // Remove entry.
+ break;
+ }
+ prev = cur;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Checks internal consistency of EventSources/Listeners.
+ /// </summary>
+ [Conditional("DEBUG")]
+ internal static void Validate()
+ {
+ lock (EventListenersLock)
+ {
+ // Get all listeners
+ Dictionary<EventListener, bool> allListeners = new Dictionary<EventListener, bool>();
+ EventListener cur = s_Listeners;
+ while (cur != null)
+ {
+ allListeners.Add(cur, true);
+ cur = cur.m_Next;
+ }
+
+ // For all eventSources
+ int id = -1;
+ foreach (WeakReference eventSourceRef in s_EventSources)
+ {
+ id++;
+ EventSource eventSource = eventSourceRef.Target as EventSource;
+ if (eventSource == null)
+ continue;
+ Contract.Assert(eventSource.m_id == id, "Unexpected event source ID.");
+
+ // None listeners on eventSources exist in the dispatcher list.
+ EventDispatcher dispatcher = eventSource.m_Dispatchers;
+ while (dispatcher != null)
+ {
+ Contract.Assert(allListeners.ContainsKey(dispatcher.m_Listener), "EventSource has a listener not on the global list.");
+ dispatcher = dispatcher.m_Next;
+ }
+
+ // Every dispatcher is on Dispatcher List of every eventSource.
+ foreach (EventListener listener in allListeners.Keys)
+ {
+ dispatcher = eventSource.m_Dispatchers;
+ for (; ; )
+ {
+ Contract.Assert(dispatcher != null, "Listener is not on all eventSources.");
+ if (dispatcher.m_Listener == listener)
+ break;
+ dispatcher = dispatcher.m_Next;
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets a global lock that is intended to protect the code:s_Listeners linked list and the
+ /// code:s_EventSources WeakReference list. (We happen to use the s_EventSources list as
+ /// the lock object)
+ /// </summary>
+ internal static object EventListenersLock
+ {
+ get
+ {
+ if (s_EventSources == null)
+ Interlocked.CompareExchange(ref s_EventSources, new List<WeakReference>(2), null);
+ return s_EventSources;
+ }
+ }
+
+ private void CallBackForExistingEventSources(bool addToListenersList, EventHandler<EventSourceCreatedEventArgs> callback)
+ {
+ lock (EventListenersLock)
+ {
+ // Disallow creating EventListener reentrancy.
+ if (s_CreatingListener)
+ {
+ throw new InvalidOperationException(Resources.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
+#if FEATURE_ACTIVITYSAMPLING
+ internal ActivityFilter m_activityFilter; // If we are filtering by activity on this Listener, this keeps track of it.
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // static fields
+
+ /// <summary>
+ /// The list of all listeners in the appdomain. Listeners must be explicitly disposed to remove themselves
+ /// from this list. Note that EventSources point to their listener but NOT the reverse.
+ /// </summary>
+ internal static EventListener s_Listeners;
+ /// <summary>
+ /// The list of all active eventSources in the appdomain. Note that eventSources do NOT
+ /// remove themselves from this list this is a weak list and the GC that removes them may
+ /// not have happened yet. Thus it can contain event sources that are dead (thus you have
+ /// to filter those out.
+ /// </summary>
+ internal static List<WeakReference> s_EventSources;
+
+ /// <summary>
+ /// Used to disallow reentrancy.
+ /// </summary>
+ private static bool s_CreatingListener = false;
+
+ /// <summary>
+ /// Used to register AD/Process shutdown callbacks.
+ /// </summary>
+ private static bool s_EventSourceShutdownRegistered = false;
+ #endregion
+ }
+
+ /// <summary>
+ /// Passed to the code:EventSource.OnEventCommand callback
+ /// </summary>
+ public class EventCommandEventArgs : EventArgs
+ {
+ /// <summary>
+ /// Gets the command for the callback.
+ /// </summary>
+ public EventCommand Command { get; internal set; }
+
+ /// <summary>
+ /// Gets the arguments for the callback.
+ /// </summary>
+ public IDictionary<String, String> Arguments { get; internal set; }
+
+ /// <summary>
+ /// Enables the event that has the specified identifier.
+ /// </summary>
+ /// <param name="eventId">Event ID of event to be enabled</param>
+ /// <returns>true if eventId is in range</returns>
+ public bool EnableEvent(int eventId)
+ {
+ if (Command != EventCommand.Enable && Command != EventCommand.Disable)
+ throw new InvalidOperationException();
+ return eventSource.EnableEventForDispatcher(dispatcher, eventId, true);
+ }
+
+ /// <summary>
+ /// Disables the event that have the specified identifier.
+ /// </summary>
+ /// <param name="eventId">Event ID of event to be disabled</param>
+ /// <returns>true if eventId is in range</returns>
+ public bool DisableEvent(int eventId)
+ {
+ if (Command != EventCommand.Enable && Command != EventCommand.Disable)
+ throw new InvalidOperationException();
+ return eventSource.EnableEventForDispatcher(dispatcher, eventId, false);
+ }
+
+ #region private
+
+ internal EventCommandEventArgs(EventCommand command, IDictionary<string, string> arguments, EventSource eventSource,
+ EventListener listener, int perEventSourceSessionId, int etwSessionId, bool enable, EventLevel level, EventKeywords matchAnyKeyword)
+ {
+ this.Command = command;
+ this.Arguments = arguments;
+ this.eventSource = eventSource;
+ this.listener = listener;
+ this.perEventSourceSessionId = perEventSourceSessionId;
+ this.etwSessionId = etwSessionId;
+ this.enable = enable;
+ this.level = level;
+ this.matchAnyKeyword = matchAnyKeyword;
+ }
+
+ internal EventSource eventSource;
+ internal EventDispatcher dispatcher;
+
+ // These are the arguments of sendCommand and are only used for deferring commands until after we are fully initialized.
+ internal EventListener listener;
+ internal int perEventSourceSessionId;
+ internal int etwSessionId;
+ internal bool enable;
+ internal EventLevel level;
+ internal EventKeywords matchAnyKeyword;
+ internal EventCommandEventArgs nextCommand; // We form a linked list of these deferred commands.
+
+ #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.
+ /// </summary>
+ public class EventWrittenEventArgs : EventArgs
+ {
+ /// <summary>
+ /// The name of the event.
+ /// </summary>
+ public string EventName
+ {
+ get
+ {
+ if (m_eventName != null || EventId < 0) // TraceLogging convention EventID == -1
+ {
+ return m_eventName;
+ }
+ else
+ return m_eventSource.m_eventData[EventId].Name;
+ }
+ internal set
+ {
+ m_eventName = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the event ID for the event that was written.
+ /// </summary>
+ public int EventId { get; internal set; }
+
+ /// <summary>
+ /// Gets the activity ID for the thread on which the event was written.
+ /// </summary>
+ public Guid ActivityId
+ {
+ [System.Security.SecurityCritical]
+ get { return EventSource.CurrentThreadActivityId; }
+ }
+
+ /// <summary>
+ /// Gets the related activity ID if one was specified when the event was written.
+ /// </summary>
+ public Guid RelatedActivityId
+ {
+ [System.Security.SecurityCritical]
+ get;
+ internal set;
+ }
+
+ /// <summary>
+ /// Gets the payload for the event.
+ /// </summary>
+ public ReadOnlyCollection<Object> Payload { get; internal set; }
+
+ /// <summary>
+ /// Gets the payload argument names.
+ /// </summary>
+ public ReadOnlyCollection<string> PayloadNames
+ {
+ get
+ {
+ // For contract based events we create the list lazily.
+ if (m_payloadNames == null)
+ {
+ // Self described events are identified by id -1.
+ Contract.Assert(EventId != -1);
+
+ var names = new List<string>();
+ foreach (var parameter in m_eventSource.m_eventData[EventId].Parameters)
+ {
+ names.Add(parameter.Name);
+ }
+ m_payloadNames = new ReadOnlyCollection<string>(names);
+ }
+
+ return m_payloadNames;
+ }
+
+ internal set
+ {
+ m_payloadNames = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets the event source object.
+ /// </summary>
+ public EventSource EventSource { get { return m_eventSource; } }
+
+ /// <summary>
+ /// Gets the keywords for the event.
+ /// </summary>
+ public EventKeywords Keywords
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return m_keywords;
+
+ return (EventKeywords)m_eventSource.m_eventData[EventId].Descriptor.Keywords;
+ }
+ }
+
+ /// <summary>
+ /// Gets the operation code for the event.
+ /// </summary>
+ public EventOpcode Opcode
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return m_opcode;
+ return (EventOpcode)m_eventSource.m_eventData[EventId].Descriptor.Opcode;
+ }
+ }
+
+ /// <summary>
+ /// Gets the task for the event.
+ /// </summary>
+ public EventTask Task
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return EventTask.None;
+
+ return (EventTask)m_eventSource.m_eventData[EventId].Descriptor.Task;
+ }
+ }
+
+ /// <summary>
+ /// Any provider/user defined options associated with the event.
+ /// </summary>
+ public EventTags Tags
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return m_tags;
+ return m_eventSource.m_eventData[EventId].Tags;
+ }
+ }
+
+ /// <summary>
+ /// Gets the message for the event.
+ /// </summary>
+ public string Message
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return m_message;
+ else
+ return m_eventSource.m_eventData[EventId].Message;
+ }
+ internal set
+ {
+ m_message = value;
+ }
+ }
+
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ /// <summary>
+ /// Gets the channel for the event.
+ /// </summary>
+ public EventChannel Channel
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return EventChannel.None;
+ return (EventChannel)m_eventSource.m_eventData[EventId].Descriptor.Channel;
+ }
+ }
+#endif
+
+ /// <summary>
+ /// Gets the version of the event.
+ /// </summary>
+ public byte Version
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return 0;
+ return m_eventSource.m_eventData[EventId].Descriptor.Version;
+ }
+ }
+
+ /// <summary>
+ /// Gets the level for the event.
+ /// </summary>
+ public EventLevel Level
+ {
+ get
+ {
+ if (EventId < 0) // TraceLogging convention EventID == -1
+ return m_level;
+ return (EventLevel)m_eventSource.m_eventData[EventId].Descriptor.Level;
+ }
+ }
+
+ #region private
+ internal EventWrittenEventArgs(EventSource eventSource)
+ {
+ m_eventSource = eventSource;
+ }
+ private string m_message;
+ private string m_eventName;
+ private EventSource m_eventSource;
+ private ReadOnlyCollection<string> m_payloadNames;
+ internal EventTags m_tags;
+ internal EventOpcode m_opcode;
+ internal EventLevel m_level;
+ internal EventKeywords m_keywords;
+ #endregion
+ }
+
+ /// <summary>
+ /// Allows customizing defaults and specifying localization support for the event source class to which it is applied.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class)]
+ public sealed class EventSourceAttribute : Attribute
+ {
+ /// <summary>
+ /// Overrides the ETW name of the event source (which defaults to the class name)
+ /// </summary>
+ public string Name { get; set; }
+
+ /// <summary>
+ /// Overrides the default (calculated) Guid of an EventSource type. Explicitly defining a GUID is discouraged,
+ /// except when upgrading existing ETW providers to using event sources.
+ /// </summary>
+ public string Guid { get; set; }
+
+ /// <summary>
+ /// <para>
+ /// EventSources support localization of events. The names used for events, opcodes, tasks, keywords and maps
+ /// can be localized to several languages if desired. This works by creating a ResX style string table
+ /// (by simply adding a 'Resource File' to your project). This resource file is given a name e.g.
+ /// 'DefaultNameSpace.ResourceFileName' which can be passed to the ResourceManager constructor to read the
+ /// resources. This name is the value of the LocalizationResources property.
+ /// </para><para>
+ /// If LocalizationResources property is non-null, then EventSource will look up the localized strings for events by
+ /// using the following resource naming scheme
+ /// </para>
+ /// <para>* event_EVENTNAME</para>
+ /// <para>* task_TASKNAME</para>
+ /// <para>* keyword_KEYWORDNAME</para>
+ /// <para>* map_MAPNAME</para>
+ /// <para>
+ /// where the capitalized name is the name of the event, task, keyword, or map value that should be localized.
+ /// Note that the localized string for an event corresponds to the Message string, and can have {0} values
+ /// which represent the payload values.
+ /// </para>
+ /// </summary>
+ public string LocalizationResources { get; set; }
+ }
+
+ /// <summary>
+ /// Any instance methods in a class that subclasses <see cref="EventSource"/> and that return void are
+ /// assumed by default to be methods that generate an ETW event. Enough information can be deduced from the
+ /// name of the method and its signature to generate basic schema information for the event. The
+ /// <see cref="EventAttribute"/> class allows you to specify additional event schema information for an event if
+ /// desired.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class EventAttribute : Attribute
+ {
+ /// <summary>Construct an EventAttribute with specified eventId</summary>
+ /// <param name="eventId">ID of the ETW event (an integer between 1 and 65535)</param>
+ public EventAttribute(int eventId) { this.EventId = eventId; Level = EventLevel.Informational; this.m_opcodeSet = false; }
+ /// <summary>Event's ID</summary>
+ public int EventId { get; private set; }
+ /// <summary>Event's severity level: indicates the severity or verbosity of the event</summary>
+ public EventLevel Level { get; set; }
+ /// <summary>Event's keywords: allows classification of events by "categories"</summary>
+ public EventKeywords Keywords { get; set; }
+ /// <summary>Event's operation code: allows defining operations, generally used with Tasks</summary>
+ public EventOpcode Opcode
+ {
+ get
+ {
+ return m_opcode;
+ }
+ set
+ {
+ this.m_opcode = value;
+ this.m_opcodeSet = true;
+ }
+ }
+
+ internal bool IsOpcodeSet
+ {
+ get
+ {
+ return m_opcodeSet;
+ }
+ }
+
+ /// <summary>Event's task: allows logical grouping of events</summary>
+ public EventTask Task { get; set; }
+#if FEATURE_MANAGED_ETW_CHANNELS
+ /// <summary>Event's channel: defines an event log as an additional destination for the event</summary>
+ public EventChannel Channel { get; set; }
+#endif
+ /// <summary>Event's version</summary>
+ public byte Version { get; set; }
+
+ /// <summary>
+ /// This can be specified to enable formatting and localization of the event's payload. You can
+ /// use standard .NET substitution operators (eg {1}) in the string and they will be replaced
+ /// with the 'ToString()' of the corresponding part of the event payload.
+ /// </summary>
+ public string Message { get; set; }
+
+ /// <summary>
+ /// User defined options associated with the event. These do not have meaning to the EventSource but
+ /// are passed through to listeners which given them semantics.
+ /// </summary>
+ public EventTags Tags { get; set; }
+
+ /// <summary>
+ /// Allows fine control over the Activity IDs generated by start and stop events
+ /// </summary>
+ public EventActivityOptions ActivityOptions { get; set; }
+
+ #region private
+ EventOpcode m_opcode;
+ private bool m_opcodeSet;
+ #endregion
+ }
+
+ /// <summary>
+ /// By default all instance methods in a class that subclasses code:EventSource that and return
+ /// void are assumed to be methods that generate an event. This default can be overridden by specifying
+ /// the code:NonEventAttribute
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class NonEventAttribute : Attribute
+ {
+ /// <summary>
+ /// Constructs a default NonEventAttribute
+ /// </summary>
+ public NonEventAttribute() { }
+ }
+
+ // FUTURE we may want to expose this at some point once we have a partner that can help us validate the design.
+#if FEATURE_MANAGED_ETW_CHANNELS
+ /// <summary>
+ /// EventChannelAttribute allows customizing channels supported by an EventSource. This attribute must be
+ /// applied to an member of type EventChannel defined in a Channels class nested in the EventSource class:
+ /// <code>
+ /// public static class Channels
+ /// {
+ /// [Channel(Enabled = true, EventChannelType = EventChannelType.Admin)]
+ /// public const EventChannel Admin = (EventChannel)16;
+ ///
+ /// [Channel(Enabled = false, EventChannelType = EventChannelType.Operational)]
+ /// public const EventChannel Operational = (EventChannel)17;
+ /// }
+ /// </code>
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Field)]
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ public
+#endif
+ class EventChannelAttribute : Attribute
+ {
+ /// <summary>
+ /// Specified whether the channel is enabled by default
+ /// </summary>
+ public bool Enabled { get; set; }
+
+ /// <summary>
+ /// Legal values are in EventChannelType
+ /// </summary>
+ public EventChannelType EventChannelType { get; set; }
+
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ /// <summary>
+ /// Specifies the isolation for the channel
+ /// </summary>
+ public EventChannelIsolation Isolation { get; set; }
+
+ /// <summary>
+ /// Specifies an SDDL access descriptor that controls access to the log file that backs the channel.
+ /// See MSDN ((http://msdn.microsoft.com/en-us/library/windows/desktop/aa382741.aspx) for details.
+ /// </summary>
+ public string Access { get; set; }
+
+ /// <summary>
+ /// Allows importing channels defined in external manifests
+ /// </summary>
+ public string ImportChannel { get; set; }
+#endif
+
+ // TODO: there is a convention that the name is the Provider/Type Should we provide an override?
+ // public string Name { get; set; }
+ }
+
+ /// <summary>
+ /// Allowed channel types
+ /// </summary>
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ public
+#endif
+ enum EventChannelType
+ {
+ /// <summary>The admin channel</summary>
+ Admin = 1,
+ /// <summary>The operational channel</summary>
+ Operational,
+ /// <summary>The Analytic channel</summary>
+ Analytic,
+ /// <summary>The debug channel</summary>
+ Debug,
+ }
+
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ /// <summary>
+ /// Allowed isolation levels. See MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/aa382741.aspx)
+ /// for the default permissions associated with each level. EventChannelIsolation and Access allows control over the
+ /// access permissions for the channel and backing file.
+ /// </summary>
+ public
+ enum EventChannelIsolation
+ {
+ /// <summary>
+ /// This is the default isolation level. All channels that specify Application isolation use the same ETW session
+ /// </summary>
+ Application = 1,
+ /// <summary>
+ /// All channels that specify System isolation use the same ETW session
+ /// </summary>
+ System,
+ /// <summary>
+ /// Use sparingly! When specifying Custom isolation, a separate ETW session is created for the channel.
+ /// Using Custom isolation lets you control the access permissions for the channel and backing file.
+ /// Because there are only 64 ETW sessions available, you should limit your use of Custom isolation.
+ /// </summary>
+ Custom,
+ }
+#endif
+#endif
+
+ /// <summary>
+ /// Describes the pre-defined command (EventCommandEventArgs.Command property) that is passed to the OnEventCommand callback.
+ /// </summary>
+ public enum EventCommand
+ {
+ /// <summary>
+ /// Update EventSource state
+ /// </summary>
+ Update = 0,
+ /// <summary>
+ /// Request EventSource to generate and send its manifest
+ /// </summary>
+ SendManifest = -1,
+ /// <summary>
+ /// Enable event
+ /// </summary>
+ Enable = -2,
+ /// <summary>
+ /// Disable event
+ /// </summary>
+ Disable = -3
+ };
+
+
+ #region private classes
+
+#if FEATURE_ACTIVITYSAMPLING
+
+ /// <summary>
+ /// ActivityFilter is a helper structure that is used to keep track of run-time state
+ /// associated with activity filtering. It is 1-1 with EventListeners (logically
+ /// every listener has one of these, however we actually allocate them lazily), as well
+ /// as 1-to-1 with tracing-aware EtwSessions.
+ ///
+ /// This structure also keeps track of the sampling counts associated with 'trigger'
+ /// events. Because these trigger events are rare, and you typically only have one of
+ /// them, we store them here as a linked list.
+ /// </summary>
+ internal sealed class ActivityFilter : IDisposable
+ {
+ /// <summary>
+ /// Disable all activity filtering for the listener associated with 'filterList',
+ /// (in the session associated with it) that is triggered by any event in 'source'.
+ /// </summary>
+ public static void DisableFilter(ref ActivityFilter filterList, EventSource source)
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
+
+ if (filterList == null)
+ return;
+
+ ActivityFilter cur;
+ // Remove it from anywhere in the list (except the first element, which has to
+ // be treated specially)
+ ActivityFilter prev = filterList;
+ cur = prev.m_next;
+ while (cur != null)
+ {
+ if (cur.m_providerGuid == source.Guid)
+ {
+ // update TriggersActivityTracking bit
+ if (cur.m_eventId >= 0 && cur.m_eventId < source.m_eventData.Length)
+ --source.m_eventData[cur.m_eventId].TriggersActivityTracking;
+
+ // Remove it from the linked list.
+ prev.m_next = cur.m_next;
+ // dispose of the removed node
+ cur.Dispose();
+ // update cursor
+ cur = prev.m_next;
+ }
+ else
+ {
+ // update cursors
+ prev = cur;
+ cur = prev.m_next;
+ }
+ }
+
+ // Sadly we have to treat the first element specially in linked list removal in C#
+ if (filterList.m_providerGuid == source.Guid)
+ {
+ // update TriggersActivityTracking bit
+ if (filterList.m_eventId >= 0 && filterList.m_eventId < source.m_eventData.Length)
+ --source.m_eventData[filterList.m_eventId].TriggersActivityTracking;
+
+ // We are the first element in the list.
+ var first = filterList;
+ filterList = first.m_next;
+ // dispose of the removed node
+ first.Dispose();
+ }
+ // the above might have removed the one ActivityFilter in the session that contains the
+ // cleanup delegate; re-create the delegate if needed
+ if (filterList != null)
+ {
+ EnsureActivityCleanupDelegate(filterList);
+ }
+ }
+
+ /// <summary>
+ /// Currently this has "override" semantics. We first disable all filters
+ /// associated with 'source', and next we add new filters for each entry in the
+ /// string 'startEvents'. participateInSampling specifies whether non-startEvents
+ /// always trigger or only trigger when current activity is 'active'.
+ /// </summary>
+ public static void UpdateFilter(
+ ref ActivityFilter filterList,
+ EventSource source,
+ int perEventSourceSessionId,
+ string startEvents)
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
+
+ // first remove all filters associated with 'source'
+ DisableFilter(ref filterList, source);
+
+ if (!string.IsNullOrEmpty(startEvents))
+ {
+ // ActivitySamplingStartEvents is a space-separated list of Event:Frequency pairs.
+ // The Event may be specified by name or by ID. Errors in parsing such a pair
+ // result in the error being reported to the listeners, and the pair being ignored.
+ // E.g. "CustomActivityStart:1000 12:10" specifies that for event CustomActivityStart
+ // we should initiate activity tracing once every 1000 events, *and* for event ID 12
+ // we should initiate activity tracing once every 10 events.
+ string[] activityFilterStrings = startEvents.Split(' ');
+
+ for (int i = 0; i < activityFilterStrings.Length; ++i)
+ {
+ string activityFilterString = activityFilterStrings[i];
+ int sampleFreq = 1;
+ int eventId = -1;
+ int colonIdx = activityFilterString.IndexOf(':');
+ if (colonIdx < 0)
+ {
+ source.ReportOutOfBandMessage("ERROR: Invalid ActivitySamplingStartEvent specification: " +
+ activityFilterString, false);
+ // ignore failure...
+ continue;
+ }
+ string sFreq = activityFilterString.Substring(colonIdx + 1);
+ if (!int.TryParse(sFreq, out sampleFreq))
+ {
+ source.ReportOutOfBandMessage("ERROR: Invalid sampling frequency specification: " + sFreq, false);
+ continue;
+ }
+ activityFilterString = activityFilterString.Substring(0, colonIdx);
+ if (!int.TryParse(activityFilterString, out eventId))
+ {
+ // reset eventId
+ eventId = -1;
+ // see if it's an event name
+ for (int j = 0; j < source.m_eventData.Length; j++)
+ {
+ EventSource.EventMetadata[] ed = source.m_eventData;
+ if (ed[j].Name != null && ed[j].Name.Length == activityFilterString.Length &&
+ string.Compare(ed[j].Name, activityFilterString, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ eventId = ed[j].Descriptor.EventId;
+ break;
+ }
+ }
+ }
+ if (eventId < 0 || eventId >= source.m_eventData.Length)
+ {
+ source.ReportOutOfBandMessage("ERROR: Invalid eventId specification: " + activityFilterString, false);
+ continue;
+ }
+ EnableFilter(ref filterList, source, perEventSourceSessionId, eventId, sampleFreq);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns the first ActivityFilter from 'filterList' corresponding to 'source'.
+ /// </summary>
+ public static ActivityFilter GetFilter(ActivityFilter filterList, EventSource source)
+ {
+ for (var af = filterList; af != null; af = af.m_next)
+ {
+ if (af.m_providerGuid == source.Guid && af.m_samplingFreq != -1)
+ return af;
+ }
+ return null;
+ }
+
+ /// <summary>
+ /// Returns a session mask representing all sessions in which the activity
+ /// associated with the current thread is allowed through the activity filter.
+ /// If 'triggeringEvent' is true the event MAY be a triggering event. Ideally
+ /// most of the time this is false as you can guarentee this event is NOT a
+ /// triggering event. If 'triggeringEvent' is true, then it checks the
+ /// 'EventSource' and 'eventID' of the event being logged to see if it is actually
+ /// a trigger. If so it activates the current activity.
+ ///
+ /// If 'childActivityID' is present, it will be added to the active set if the
+ /// current activity is active.
+ /// </summary>
+ [SecurityCritical]
+ unsafe public static bool PassesActivityFilter(
+ ActivityFilter filterList,
+ Guid* childActivityID,
+ bool triggeringEvent,
+ EventSource source,
+ int eventId)
+ {
+ Contract.Assert(filterList != null && filterList.m_activeActivities != null);
+ bool shouldBeLogged = false;
+ if (triggeringEvent)
+ {
+ for (ActivityFilter af = filterList; af != null; af = af.m_next)
+ {
+ if (eventId == af.m_eventId && source.Guid == af.m_providerGuid)
+ {
+ // Update the sampling count with wrap-around
+ int curSampleCount, newSampleCount;
+ do
+ {
+ curSampleCount = af.m_curSampleCount;
+ if (curSampleCount <= 1)
+ newSampleCount = af.m_samplingFreq; // Wrap around, counting down to 1
+ else
+ newSampleCount = curSampleCount - 1;
+ }
+ while (Interlocked.CompareExchange(ref af.m_curSampleCount, newSampleCount, curSampleCount) != curSampleCount);
+ // If we hit zero, then start tracking the activity.
+ if (curSampleCount <= 1)
+ {
+ Guid currentActivityId = EventSource.InternalCurrentThreadActivityId;
+ Tuple<Guid, int> startId;
+ // only add current activity if it's not already a root activity
+ if (!af.m_rootActiveActivities.TryGetValue(currentActivityId, out startId))
+ {
+ // EventSource.OutputDebugString(string.Format(" PassesAF - Triggering(session {0}, evt {1})", af.m_perEventSourceSessionId, eventId));
+ shouldBeLogged = true;
+ af.m_activeActivities[currentActivityId] = Environment.TickCount;
+ af.m_rootActiveActivities[currentActivityId] = Tuple.Create(source.Guid, eventId);
+ }
+ }
+ else
+ {
+ // a start event following a triggering start event
+ Guid currentActivityId = EventSource.InternalCurrentThreadActivityId;
+ Tuple<Guid, int> startId;
+ // only remove current activity if we added it
+ if (af.m_rootActiveActivities.TryGetValue(currentActivityId, out startId) &&
+ startId.Item1 == source.Guid && startId.Item2 == eventId)
+ {
+ // EventSource.OutputDebugString(string.Format("Activity dying: {0} -> StartEvent({1})", currentActivityId, eventId));
+ // remove activity only from current logging scope (af)
+ int dummy;
+ af.m_activeActivities.TryRemove(currentActivityId, out dummy);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ var activeActivities = GetActiveActivities(filterList);
+ if (activeActivities != null)
+ {
+ // if we hadn't already determined this should be logged, test further
+ if (!shouldBeLogged)
+ {
+ shouldBeLogged = !activeActivities.IsEmpty &&
+ activeActivities.ContainsKey(EventSource.InternalCurrentThreadActivityId);
+ }
+ if (shouldBeLogged && childActivityID != null &&
+ ((EventOpcode)source.m_eventData[eventId].Descriptor.Opcode == EventOpcode.Send))
+ {
+ FlowActivityIfNeeded(filterList, null, childActivityID);
+ // EventSource.OutputDebugString(string.Format(" PassesAF - activity {0}", *childActivityID));
+ }
+ }
+ // EventSource.OutputDebugString(string.Format(" PassesAF - shouldBeLogged(evt {0}) = {1:x}", eventId, shouldBeLogged));
+ return shouldBeLogged;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static bool IsCurrentActivityActive(ActivityFilter filterList)
+ {
+ var activeActivities = GetActiveActivities(filterList);
+ if (activeActivities != null &&
+ activeActivities.ContainsKey(EventSource.InternalCurrentThreadActivityId))
+ return true;
+
+ return false;
+ }
+
+ /// <summary>
+ /// For the EventListener/EtwSession associated with 'filterList', add 'childActivityid'
+ /// to list of active activities IF 'currentActivityId' is also active. Passing in a null
+ /// value for 'currentActivityid' is an indication tha caller has already verified
+ /// that the current activity is active.
+ /// </summary>
+ [SecurityCritical]
+ unsafe public static void FlowActivityIfNeeded(ActivityFilter filterList, Guid* currentActivityId, Guid* childActivityID)
+ {
+ Contract.Assert(childActivityID != null);
+
+ var activeActivities = GetActiveActivities(filterList);
+ Contract.Assert(activeActivities != null);
+
+ // take currentActivityId == null to mean we *know* the current activity is "active"
+ if (currentActivityId != null && !activeActivities.ContainsKey(*currentActivityId))
+ return;
+
+ if (activeActivities.Count > MaxActivityTrackCount)
+ {
+ TrimActiveActivityStore(activeActivities);
+ // make sure current activity is still in the set:
+ activeActivities[EventSource.InternalCurrentThreadActivityId] = Environment.TickCount;
+ }
+ // add child activity to list of actives
+ activeActivities[*childActivityID] = Environment.TickCount;
+
+ }
+
+ /// <summary>
+ /// </summary>
+ public static void UpdateKwdTriggers(ActivityFilter activityFilter, Guid sourceGuid, EventSource source, EventKeywords sessKeywords)
+ {
+ for (var af = activityFilter; af != null; af = af.m_next)
+ {
+ if ((sourceGuid == af.m_providerGuid) &&
+ (source.m_eventData[af.m_eventId].TriggersActivityTracking > 0 ||
+ ((EventOpcode)source.m_eventData[af.m_eventId].Descriptor.Opcode == EventOpcode.Send)))
+ {
+ // we could be more precise here, if we tracked 'anykeywords' per session
+ unchecked
+ {
+ source.m_keywordTriggers |= (source.m_eventData[af.m_eventId].Descriptor.Keywords & (long)sessKeywords);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// For the EventSource specified by 'sourceGuid' and the EventListener/EtwSession
+ /// associated with 'this' ActivityFilter list, return configured sequence of
+ /// [eventId, sampleFreq] pairs that defines the sampling policy.
+ /// </summary>
+ public IEnumerable<Tuple<int, int>> GetFilterAsTuple(Guid sourceGuid)
+ {
+ for (ActivityFilter af = this; af != null; af = af.m_next)
+ {
+ if (af.m_providerGuid == sourceGuid)
+ yield return Tuple.Create(af.m_eventId, af.m_samplingFreq);
+ }
+ }
+
+ /// <summary>
+ /// The cleanup being performed consists of removing the m_myActivityDelegate from
+ /// the static s_activityDying, therefore allowing the ActivityFilter to be reclaimed.
+ /// </summary>
+ public void Dispose()
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
+ // m_myActivityDelegate is still alive (held by the static EventSource.s_activityDying).
+ // Therefore we are ok to take a dependency on m_myActivityDelegate being valid even
+ // during the finalization of the ActivityFilter
+ if (m_myActivityDelegate != null)
+ {
+ EventSource.s_activityDying = (Action<Guid>)Delegate.Remove(EventSource.s_activityDying, m_myActivityDelegate);
+ m_myActivityDelegate = null;
+ }
+ }
+
+ #region private
+
+ /// <summary>
+ /// Creates a new ActivityFilter that is triggered by 'eventId' from 'source' ever
+ /// 'samplingFreq' times the event fires. You can have several of these forming a
+ /// linked list.
+ /// </summary>
+ private ActivityFilter(EventSource source, int perEventSourceSessionId, int eventId, int samplingFreq, ActivityFilter existingFilter = null)
+ {
+ m_providerGuid = source.Guid;
+ m_perEventSourceSessionId = perEventSourceSessionId;
+ m_eventId = eventId;
+ m_samplingFreq = samplingFreq;
+ m_next = existingFilter;
+
+ Contract.Assert(existingFilter == null ||
+ (existingFilter.m_activeActivities == null) == (existingFilter.m_rootActiveActivities == null));
+
+ // if this is the first filter we add for this session, we need to create a new
+ // table of activities. m_activeActivities is common across EventSources in the same
+ // session
+ ConcurrentDictionary<Guid, int> activeActivities = null;
+ if (existingFilter == null ||
+ (activeActivities = GetActiveActivities(existingFilter)) == null)
+ {
+ m_activeActivities = new ConcurrentDictionary<Guid, int>();
+ m_rootActiveActivities = new ConcurrentDictionary<Guid, Tuple<Guid, int>>();
+
+ // Add a delegate to the 'SetCurrentThreadToActivity callback so that I remove 'dead' activities
+ m_myActivityDelegate = GetActivityDyingDelegate(this);
+ EventSource.s_activityDying = (Action<Guid>)Delegate.Combine(EventSource.s_activityDying, m_myActivityDelegate);
+ }
+ else
+ {
+ m_activeActivities = activeActivities;
+ m_rootActiveActivities = existingFilter.m_rootActiveActivities;
+ }
+
+ }
+
+ /// <summary>
+ /// Ensure there's at least one ActivityFilter in the 'filterList' that contains an
+ /// activity-removing delegate for the listener/session associated with 'filterList'.
+ /// </summary>
+ private static void EnsureActivityCleanupDelegate(ActivityFilter filterList)
+ {
+ if (filterList == null)
+ return;
+
+ for (ActivityFilter af = filterList; af != null; af = af.m_next)
+ {
+ if (af.m_myActivityDelegate != null)
+ return;
+ }
+
+ // we didn't find a delegate
+ filterList.m_myActivityDelegate = GetActivityDyingDelegate(filterList);
+ EventSource.s_activityDying = (Action<Guid>)Delegate.Combine(EventSource.s_activityDying, filterList.m_myActivityDelegate);
+ }
+
+ /// <summary>
+ /// Builds the delegate to be called when an activity is dying. This is responsible
+ /// for performing whatever cleanup is needed for the ActivityFilter list passed in.
+ /// This gets "added" to EventSource.s_activityDying and ends up being called from
+ /// EventSource.SetCurrentThreadActivityId and ActivityFilter.PassesActivityFilter.
+ /// </summary>
+ /// <returns>The delegate to be called when an activity is dying</returns>
+ private static Action<Guid> GetActivityDyingDelegate(ActivityFilter filterList)
+ {
+ return (Guid oldActivity) =>
+ {
+ int dummy;
+ filterList.m_activeActivities.TryRemove(oldActivity, out dummy);
+ Tuple<Guid, int> dummyTuple;
+ filterList.m_rootActiveActivities.TryRemove(oldActivity, out dummyTuple);
+ };
+ }
+
+ /// <summary>
+ /// Enables activity filtering for the listener associated with 'filterList', triggering on
+ /// the event 'eventID' from 'source' with a sampling frequency of 'samplingFreq'
+ ///
+ /// if 'eventID' is out of range (e.g. negative), it means we are not triggering (but we are
+ /// activitySampling if something else triggered).
+ /// </summary>
+ /// <returns>true if activity sampling is enabled the samplingFreq is non-zero </returns>
+ private static bool EnableFilter(ref ActivityFilter filterList, EventSource source, int perEventSourceSessionId, int eventId, int samplingFreq)
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(Monitor.IsEntered(EventListener.EventListenersLock));
+#endif
+ Contract.Assert(samplingFreq > 0);
+ Contract.Assert(eventId >= 0);
+
+ filterList = new ActivityFilter(source, perEventSourceSessionId, eventId, samplingFreq, filterList);
+
+ // Mark the 'quick Check' that indicates this is a trigger event.
+ // If eventId is out of range then this mark is not done which has the effect of ignoring
+ // the trigger.
+ if (0 <= eventId && eventId < source.m_eventData.Length)
+ ++source.m_eventData[eventId].TriggersActivityTracking;
+
+ return true;
+ }
+
+ /// <summary>
+ /// Normally this code never runs, it is here just to prevent run-away resource usage.
+ /// </summary>
+ private static void TrimActiveActivityStore(ConcurrentDictionary<Guid, int> activities)
+ {
+ if (activities.Count > MaxActivityTrackCount)
+ {
+ // Remove half of the oldest activity ids.
+ var keyValues = activities.ToArray();
+ var tickNow = Environment.TickCount;
+
+ // Sort by age, taking into account wrap-around. As long as x and y are within
+ // 23 days of now then (0x7FFFFFFF & (tickNow - x.Value)) is the delta (even if
+ // TickCount wraps). I then sort by DESCENDING age. (that is oldest value first)
+ Array.Sort(keyValues, (x, y) => (0x7FFFFFFF & (tickNow - y.Value)) - (0x7FFFFFFF & (tickNow - x.Value)));
+ for (int i = 0; i < keyValues.Length / 2; i++)
+ {
+ int dummy;
+ activities.TryRemove(keyValues[i].Key, out dummy);
+ }
+ }
+ }
+
+ private static ConcurrentDictionary<Guid, int> GetActiveActivities(
+ ActivityFilter filterList)
+ {
+ for (ActivityFilter af = filterList; af != null; af = af.m_next)
+ {
+ if (af.m_activeActivities != null)
+ return af.m_activeActivities;
+ }
+ return null;
+ }
+
+ // m_activeActivities always points to the sample dictionary for EVERY ActivityFilter
+ // in the m_next list. The 'int' value in the m_activities set is a timestamp
+ // (Environment.TickCount) of when the entry was put in the system and is used to
+ // remove 'old' entries that if the set gets too big.
+ ConcurrentDictionary<Guid, int> m_activeActivities;
+
+ // m_rootActiveActivities holds the "root" active activities, i.e. the activities
+ // that were marked as active because a Start event fired on them. We need to keep
+ // track of these to enable sampling in the scenario of an app's main thread that
+ // never explicitly sets distinct activity IDs as it executes. To handle these
+ // situations we manufacture a Guid from the thread's ID, and:
+ // (a) we consider the firing of a start event when the sampling counter reaches
+ // zero to mark the beginning of an interesting activity, and
+ // (b) we consider the very next firing of the same start event to mark the
+ // ending of that activity.
+ // We use a ConcurrentDictionary to avoid taking explicit locks.
+ // The key (a guid) represents the activity ID of the root active activity
+ // The value is made up of the Guid of the event provider and the eventId of
+ // the start event.
+ ConcurrentDictionary<Guid, Tuple<Guid, int>> m_rootActiveActivities;
+ Guid m_providerGuid; // We use the GUID rather than object identity because we don't want to keep the eventSource alive
+ int m_eventId; // triggering event
+ int m_samplingFreq; // Counter reset to this when it hits 0
+ int m_curSampleCount; // We count down to 0 and then activate the activity.
+ int m_perEventSourceSessionId; // session ID bit for ETW, 0 for EventListeners
+
+ const int MaxActivityTrackCount = 100000; // maximum number of tracked activities
+
+ ActivityFilter m_next; // We create a linked list of these
+ Action<Guid> m_myActivityDelegate;
+ #endregion
+ };
+
+
+ /// <summary>
+ /// An EtwSession instance represents an activity-tracing-aware ETW session. Since these
+ /// are limited to 8 concurrent sessions per machine (currently) we're going to store
+ /// the active ones in a singly linked list.
+ /// </summary>
+ internal class EtwSession
+ {
+ public static EtwSession GetEtwSession(int etwSessionId, bool bCreateIfNeeded = false)
+ {
+ if (etwSessionId < 0)
+ return null;
+
+ EtwSession etwSession;
+ foreach (var wrEtwSession in s_etwSessions)
+ {
+#if ES_BUILD_STANDALONE
+ if ((etwSession = (EtwSession) wrEtwSession.Target) != null && etwSession.m_etwSessionId == etwSessionId)
+ return etwSession;
+#else
+ if (wrEtwSession.TryGetTarget(out etwSession) && etwSession.m_etwSessionId == etwSessionId)
+ return etwSession;
+#endif
+ }
+
+ if (!bCreateIfNeeded)
+ return null;
+
+#if ES_BUILD_STANDALONE
+ if (s_etwSessions == null)
+ s_etwSessions = new List<WeakReference>();
+
+ etwSession = new EtwSession(etwSessionId);
+ s_etwSessions.Add(new WeakReference(etwSession));
+#else
+ if (s_etwSessions == null)
+ s_etwSessions = new List<WeakReference<EtwSession>>();
+
+ etwSession = new EtwSession(etwSessionId);
+ s_etwSessions.Add(new WeakReference<EtwSession>(etwSession));
+#endif
+
+ if (s_etwSessions.Count > s_thrSessionCount)
+ TrimGlobalList();
+
+ return etwSession;
+
+ }
+
+ public static void RemoveEtwSession(EtwSession etwSession)
+ {
+ Contract.Assert(etwSession != null);
+ if (s_etwSessions == null || etwSession == null)
+ return;
+
+ s_etwSessions.RemoveAll((wrEtwSession) =>
+ {
+ EtwSession session;
+#if ES_BUILD_STANDALONE
+ return (session = (EtwSession) wrEtwSession.Target) != null &&
+ (session.m_etwSessionId == etwSession.m_etwSessionId);
+#else
+ return wrEtwSession.TryGetTarget(out session) &&
+ (session.m_etwSessionId == etwSession.m_etwSessionId);
+#endif
+ });
+
+ if (s_etwSessions.Count > s_thrSessionCount)
+ TrimGlobalList();
+ }
+
+ private static void TrimGlobalList()
+ {
+ if (s_etwSessions == null)
+ return;
+
+ s_etwSessions.RemoveAll((wrEtwSession) =>
+ {
+#if ES_BUILD_STANDALONE
+ return wrEtwSession.Target == null;
+#else
+ EtwSession session;
+ return !wrEtwSession.TryGetTarget(out session);
+#endif
+ });
+ }
+
+ private EtwSession(int etwSessionId)
+ {
+ m_etwSessionId = etwSessionId;
+ }
+
+ public readonly int m_etwSessionId; // ETW session ID (as retrieved by EventProvider)
+ public ActivityFilter m_activityFilter; // all filters enabled for this session
+
+#if ES_BUILD_STANDALONE
+ private static List<WeakReference> s_etwSessions = new List<WeakReference>();
+#else
+ private static List<WeakReference<EtwSession>> s_etwSessions = new List<WeakReference<EtwSession>>();
+#endif
+ private const int s_thrSessionCount = 16;
+ }
+
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // holds a bitfield representing a session mask
+ /// <summary>
+ /// A SessionMask represents a set of (at most MAX) sessions as a bit mask. The perEventSourceSessionId
+ /// is the index in the SessionMask of the bit that will be set. These can translate to
+ /// EventSource's reserved keywords bits using the provided ToEventKeywords() and
+ /// FromEventKeywords() methods.
+ /// </summary>
+ internal struct SessionMask
+ {
+ public SessionMask(SessionMask m)
+ { m_mask = m.m_mask; }
+
+ public SessionMask(uint mask = 0)
+ { m_mask = mask & MASK; }
+
+ public bool IsEqualOrSupersetOf(SessionMask m)
+ {
+ return (this.m_mask | m.m_mask) == this.m_mask;
+ }
+
+ public static SessionMask All
+ {
+ get { return new SessionMask(MASK); }
+ }
+
+ public static SessionMask FromId(int perEventSourceSessionId)
+ {
+ Contract.Assert(perEventSourceSessionId < MAX);
+ return new SessionMask((uint)1 << perEventSourceSessionId);
+ }
+
+ public ulong ToEventKeywords()
+ {
+ return (ulong)m_mask << SHIFT_SESSION_TO_KEYWORD;
+ }
+
+ public static SessionMask FromEventKeywords(ulong m)
+ {
+ return new SessionMask((uint)(m >> SHIFT_SESSION_TO_KEYWORD));
+ }
+
+ public bool this[int perEventSourceSessionId]
+ {
+ get
+ {
+ Contract.Assert(perEventSourceSessionId < MAX);
+ return (m_mask & (1 << perEventSourceSessionId)) != 0;
+ }
+ set
+ {
+ Contract.Assert(perEventSourceSessionId < MAX);
+ if (value) m_mask |= ((uint)1 << perEventSourceSessionId);
+ else m_mask &= ~((uint)1 << perEventSourceSessionId);
+ }
+ }
+
+ public static SessionMask operator |(SessionMask m1, SessionMask m2)
+ {
+ return new SessionMask(m1.m_mask | m2.m_mask);
+ }
+
+ public static SessionMask operator &(SessionMask m1, SessionMask m2)
+ {
+ return new SessionMask(m1.m_mask & m2.m_mask);
+ }
+
+ public static SessionMask operator ^(SessionMask m1, SessionMask m2)
+ {
+ return new SessionMask(m1.m_mask ^ m2.m_mask);
+ }
+
+ public static SessionMask operator ~(SessionMask m)
+ {
+ return new SessionMask(MASK & ~(m.m_mask));
+ }
+
+ public static explicit operator ulong(SessionMask m)
+ { return m.m_mask; }
+
+ public static explicit operator uint(SessionMask m)
+ { return m.m_mask; }
+
+ private uint m_mask;
+
+ internal const int SHIFT_SESSION_TO_KEYWORD = 44; // bits 44-47 inclusive are reserved
+ internal const uint MASK = 0x0fU; // the mask of 4 reserved bits
+ internal const uint MAX = 4; // maximum number of simultaneous ETW sessions supported
+ }
+
+ /// <summary>
+ /// code:EventDispatchers are a simple 'helper' structure that holds the filtering state
+ /// (m_EventEnabled) for a particular EventSource X EventListener tuple
+ ///
+ /// Thus a single EventListener may have many EventDispatchers (one for every EventSource
+ /// that that EventListener has activate) and a Single EventSource may also have many
+ /// event Dispatchers (one for every EventListener that has activated it).
+ ///
+ /// Logically a particular EventDispatcher belongs to exactly one EventSource and exactly
+ /// one EventListener (alhtough EventDispatcher does not 'remember' the EventSource it is
+ /// associated with.
+ /// </summary>
+ internal class EventDispatcher
+ {
+ internal EventDispatcher(EventDispatcher next, bool[] eventEnabled, EventListener listener)
+ {
+ m_Next = next;
+ m_EventEnabled = eventEnabled;
+ m_Listener = listener;
+ }
+
+ // Instance fields
+ readonly internal EventListener m_Listener; // The dispatcher this entry is for
+ internal bool[] m_EventEnabled; // For every event in a the eventSource, is it enabled?
+#if FEATURE_ACTIVITYSAMPLING
+ internal bool m_activityFilteringEnabled; // does THIS EventSource have activity filtering turned on for this listener?
+#endif // FEATURE_ACTIVITYSAMPLING
+
+ // Only guaranteed to exist after a InsureInit()
+ internal EventDispatcher m_Next; // These form a linked list in code:EventSource.m_Dispatchers
+ // Of all listeners for that eventSource.
+ }
+
+ /// <summary>
+ /// Flags that can be used with EventSource.GenerateManifest to control how the ETW manifest for the EventSource is
+ /// generated.
+ /// </summary>
+ [Flags]
+ public enum EventManifestOptions
+ {
+ /// <summary>
+ /// Only the resources associated with current UI culture are included in the manifest
+ /// </summary>
+ None = 0x0,
+ /// <summary>
+ /// Throw exceptions for any inconsistency encountered
+ /// </summary>
+ Strict = 0x1,
+ /// <summary>
+ /// Generate a "resources" node under "localization" for every satellite assembly provided
+ /// </summary>
+ AllCultures = 0x2,
+ /// <summary>
+ /// Generate the manifest only if the event source needs to be registered on the machine,
+ /// otherwise return null (but still perform validation if Strict is specified)
+ /// </summary>
+ OnlyIfNeededForRegistration = 0x4,
+ /// <summary>
+ /// When generating the manifest do *not* enforce the rule that the current EventSource class
+ /// must be the base class for the user-defined type passed in. This allows validation of .net
+ /// event sources using the new validation code
+ /// </summary>
+ AllowEventSourceOverride = 0x8,
+ }
+
+ /// <summary>
+ /// ManifestBuilder is designed to isolate the details of the message of the event from the
+ /// rest of EventSource. This one happens to create XML.
+ /// </summary>
+ internal partial class ManifestBuilder
+ {
+ /// <summary>
+ /// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
+ /// 'resources, is a resource manager. If specified all messages are localized using that manager.
+ /// </summary>
+ public ManifestBuilder(string providerName, Guid providerGuid, string dllName, ResourceManager resources,
+ EventManifestOptions flags)
+ {
+#if FEATURE_MANAGED_ETW_CHANNELS
+ this.providerName = providerName;
+#endif
+ this.flags = flags;
+
+ this.resources = resources;
+ sb = new StringBuilder();
+ events = new StringBuilder();
+ templates = new StringBuilder();
+ opcodeTab = new Dictionary<int, string>();
+ stringTab = new Dictionary<string, string>();
+ errors = new List<string>();
+ perEventByteArrayArgIndices = new Dictionary<string, List<int>>();
+
+ sb.AppendLine("<instrumentationManifest xmlns=\"http://schemas.microsoft.com/win/2004/08/events\">");
+ sb.AppendLine(" <instrumentation xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:win=\"http://manifests.microsoft.com/win/2004/08/windows/events\">");
+ sb.AppendLine(" <events xmlns=\"http://schemas.microsoft.com/win/2004/08/events\">");
+ sb.Append("<provider name=\"").Append(providerName).
+ Append("\" guid=\"{").Append(providerGuid.ToString()).Append("}");
+ if (dllName != null)
+ sb.Append("\" resourceFileName=\"").Append(dllName).Append("\" messageFileName=\"").Append(dllName);
+
+ var symbolsName = providerName.Replace("-", "").Replace(".", "_"); // Period and - are illegal replace them.
+ sb.Append("\" symbol=\"").Append(symbolsName);
+ sb.Append("\">").AppendLine();
+ }
+
+ public void AddOpcode(string name, int value)
+ {
+ if ((flags & EventManifestOptions.Strict) != 0)
+ {
+ if (value <= 10 || value >= 239)
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalOpcodeValue", name, value));
+ }
+ string prevName;
+ if (opcodeTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_OpcodeCollision", name, prevName, value));
+ }
+ }
+ opcodeTab[value] = name;
+ }
+ public void AddTask(string name, int value)
+ {
+ if ((flags & EventManifestOptions.Strict) != 0)
+ {
+ if (value <= 0 || value >= 65535)
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalTaskValue", name, value));
+ }
+ string prevName;
+ if (taskTab != null && taskTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_TaskCollision", name, prevName, value));
+ }
+ }
+ if (taskTab == null)
+ taskTab = new Dictionary<int, string>();
+ taskTab[value] = name;
+ }
+ public void AddKeyword(string name, ulong value)
+ {
+ if ((value & (value - 1)) != 0) // Is it a power of 2?
+ {
+ ManifestError(Resources.GetResourceString("EventSource_KeywordNeedPowerOfTwo", "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
+ }
+ if ((flags & EventManifestOptions.Strict) != 0)
+ {
+ if (value >= 0x0000100000000000UL && !name.StartsWith("Session", StringComparison.Ordinal))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalKeywordsValue", name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ }
+ string prevName;
+ if (keywordTab != null && keywordTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_KeywordCollision", name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ }
+ }
+ if (keywordTab == null)
+ keywordTab = new Dictionary<ulong, string>();
+ keywordTab[value] = name;
+ }
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ /// <summary>
+ /// Add a channel. channelAttribute can be null
+ /// </summary>
+ public void AddChannel(string name, int value, EventChannelAttribute channelAttribute)
+ {
+ EventChannel chValue = (EventChannel)value;
+ if (value < (int)EventChannel.Admin || value > 255)
+ ManifestError(Resources.GetResourceString("EventSource_EventChannelOutOfRange", name, value));
+ else if (chValue >= EventChannel.Admin && chValue <= EventChannel.Debug &&
+ channelAttribute != null && EventChannelToChannelType(chValue) != channelAttribute.EventChannelType)
+ {
+ // we want to ensure developers do not define EventChannels that conflict with the builtin ones,
+ // but we want to allow them to override the default ones...
+ ManifestError(Resources.GetResourceString("EventSource_ChannelTypeDoesNotMatchEventChannelValue",
+ name, ((EventChannel)value).ToString()));
+ }
+
+ // TODO: validate there are no conflicting manifest exposed names (generally following the format "provider/type")
+
+ ulong kwd = GetChannelKeyword(chValue);
+
+ if (channelTab == null)
+ channelTab = new Dictionary<int, ChannelInfo>(4);
+ channelTab[value] = new ChannelInfo { Name = name, Keywords = kwd, Attribs = channelAttribute };
+ }
+
+ private EventChannelType EventChannelToChannelType(EventChannel channel)
+ {
+#if !ES_BUILD_STANDALONE
+ Contract.Assert(channel >= EventChannel.Admin && channel <= EventChannel.Debug);
+#endif
+ return (EventChannelType)((int)channel - (int)EventChannel.Admin + (int)EventChannelType.Admin);
+ }
+ private EventChannelAttribute GetDefaultChannelAttribute(EventChannel channel)
+ {
+ EventChannelAttribute attrib = new EventChannelAttribute();
+ attrib.EventChannelType = EventChannelToChannelType(channel);
+ if (attrib.EventChannelType <= EventChannelType.Operational)
+ attrib.Enabled = true;
+ return attrib;
+ }
+
+ public ulong[] GetChannelData()
+ {
+ if (this.channelTab == null)
+ {
+ return new ulong[0];
+ }
+
+ // We create an array indexed by the channel id for fast look up.
+ // E.g. channelMask[Admin] will give you the bit mask for Admin channel.
+ int maxkey = -1;
+ foreach (var item in this.channelTab.Keys)
+ {
+ if (item > maxkey)
+ {
+ maxkey = item;
+ }
+ }
+
+ ulong[] channelMask = new ulong[maxkey + 1];
+ foreach (var item in this.channelTab)
+ {
+ channelMask[item.Key] = item.Value.Keywords;
+ }
+
+ return channelMask;
+ }
+
+#endif
+ public void StartEvent(string eventName, EventAttribute eventAttribute)
+ {
+ Contract.Assert(numParams == 0);
+ Contract.Assert(this.eventName == null);
+ this.eventName = eventName;
+ numParams = 0;
+ byteArrArgIndices = null;
+
+ events.Append(" <event").
+ Append(" value=\"").Append(eventAttribute.EventId).Append("\"").
+ Append(" version=\"").Append(eventAttribute.Version).Append("\"").
+ Append(" level=\"").Append(GetLevelName(eventAttribute.Level)).Append("\"").
+ Append(" symbol=\"").Append(eventName).Append("\"");
+
+ // at this point we add to the manifest's stringTab a message that is as-of-yet
+ // "untranslated to manifest convention", b/c we don't have the number or position
+ // of any byte[] args (which require string format index updates)
+ WriteMessageAttrib(events, "event", eventName, eventAttribute.Message);
+
+ if (eventAttribute.Keywords != 0)
+ events.Append(" keywords=\"").Append(GetKeywords((ulong)eventAttribute.Keywords, eventName)).Append("\"");
+ if (eventAttribute.Opcode != 0)
+ events.Append(" opcode=\"").Append(GetOpcodeName(eventAttribute.Opcode, eventName)).Append("\"");
+ if (eventAttribute.Task != 0)
+ events.Append(" task=\"").Append(GetTaskName(eventAttribute.Task, eventName)).Append("\"");
+#if FEATURE_MANAGED_ETW_CHANNELS
+ if (eventAttribute.Channel != 0)
+ {
+ events.Append(" channel=\"").Append(GetChannelName(eventAttribute.Channel, eventName, eventAttribute.Message)).Append("\"");
+ }
+#endif
+ }
+
+ public void AddEventParameter(Type type, string name)
+ {
+ if (numParams == 0)
+ templates.Append(" <template tid=\"").Append(eventName).Append("Args\">").AppendLine();
+ if (type == typeof(byte[]))
+ {
+ // mark this index as "extraneous" (it has no parallel in the managed signature)
+ // we use these values in TranslateToManifestConvention()
+ if (byteArrArgIndices == null)
+ byteArrArgIndices = new List<int>(4);
+ byteArrArgIndices.Add(numParams);
+
+ // add an extra field to the template representing the length of the binary blob
+ numParams++;
+ templates.Append(" <data name=\"").Append(name).Append("Size\" inType=\"win:UInt32\"/>").AppendLine();
+ }
+ numParams++;
+ templates.Append(" <data name=\"").Append(name).Append("\" inType=\"").Append(GetTypeName(type)).Append("\"");
+ // TODO: for 'byte*' types it assumes the user provided length is named using the same naming convention
+ // as for 'byte[]' args (blob_arg_name + "Size")
+ if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+ {
+ // add "length" attribute to the "blob" field in the template (referencing the field added above)
+ templates.Append(" length=\"").Append(name).Append("Size\"");
+ }
+ // ETW does not support 64-bit value maps, so we don't specify these as ETW maps
+ if (type.IsEnum() && Enum.GetUnderlyingType(type) != typeof(UInt64) && Enum.GetUnderlyingType(type) != typeof(Int64))
+ {
+ templates.Append(" map=\"").Append(type.Name).Append("\"");
+ if (mapsTab == null)
+ mapsTab = new Dictionary<string, Type>();
+ if (!mapsTab.ContainsKey(type.Name))
+ mapsTab.Add(type.Name, type); // Remember that we need to dump the type enumeration
+ }
+
+ templates.Append("/>").AppendLine();
+ }
+ public void EndEvent()
+ {
+ if (numParams > 0)
+ {
+ templates.Append(" </template>").AppendLine();
+ events.Append(" template=\"").Append(eventName).Append("Args\"");
+ }
+ events.Append("/>").AppendLine();
+
+ if (byteArrArgIndices != null)
+ perEventByteArrayArgIndices[eventName] = byteArrArgIndices;
+
+ // at this point we have all the information we need to translate the C# Message
+ // to the manifest string we'll put in the stringTab
+ string msg;
+ if (stringTab.TryGetValue("event_" + eventName, out msg))
+ {
+ msg = TranslateToManifestConvention(msg, eventName);
+ stringTab["event_" + eventName] = msg;
+ }
+
+ eventName = null;
+ numParams = 0;
+ byteArrArgIndices = null;
+ }
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ // Channel keywords are generated one per channel to allow channel based filtering in event viewer. These keywords are autogenerated
+ // by mc.exe for compiling a manifest and are based on the order of the channels (fields) in the Channels inner class (when advanced
+ // channel support is enabled), or based on the order the predefined channels appear in the EventAttribute properties (for simple
+ // support). The manifest generated *MUST* have the channels specified in the same order (that's how our computed keywords are mapped
+ // to channels by the OS infrastructure).
+ // If channelKeyworkds is present, and has keywords bits in the ValidPredefinedChannelKeywords then it is
+ // assumed that that the keyword for that channel should be that bit.
+ // otherwise we allocate a channel bit for the channel.
+ // explicit channel bits are only used by WCF to mimic an existing manifest,
+ // so we don't dont do error checking.
+ public ulong GetChannelKeyword(EventChannel channel, ulong channelKeyword=0)
+ {
+ // strip off any non-channel keywords, since we are only interested in channels here.
+ channelKeyword &= ValidPredefinedChannelKeywords;
+ if (channelTab == null)
+ {
+ channelTab = new Dictionary<int, ChannelInfo>(4);
+ }
+
+ if (channelTab.Count == MaxCountChannels)
+ ManifestError(Resources.GetResourceString("EventSource_MaxChannelExceeded"));
+
+ ChannelInfo info;
+ if (!channelTab.TryGetValue((int)channel, out info))
+ {
+ // If we were not given an explicit channel, allocate one.
+ if (channelKeyword != 0)
+ {
+ channelKeyword = nextChannelKeywordBit;
+ nextChannelKeywordBit >>= 1;
+ }
+ }
+ else
+ {
+ channelKeyword = info.Keywords;
+ }
+
+ return channelKeyword;
+ }
+#endif
+
+ public byte[] CreateManifest()
+ {
+ string str = CreateManifestString();
+ return Encoding.UTF8.GetBytes(str);
+ }
+
+ public IList<string> Errors { get { return errors; } }
+
+ /// <summary>
+ /// When validating an event source it adds the error to the error collection.
+ /// When not validating it throws an exception if runtimeCritical is "true".
+ /// Otherwise the error is ignored.
+ /// </summary>
+ /// <param name="msg"></param>
+ /// <param name="runtimeCritical"></param>
+ public void ManifestError(string msg, bool runtimeCritical = false)
+ {
+ if ((flags & EventManifestOptions.Strict) != 0)
+ errors.Add(msg);
+ else if (runtimeCritical)
+ throw new ArgumentException(msg);
+ }
+
+ private string CreateManifestString()
+ {
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ // Write out the channels
+ if (channelTab != null)
+ {
+ sb.Append(" <channels>").AppendLine();
+ var sortedChannels = new List<KeyValuePair<int, ChannelInfo>>();
+ foreach (KeyValuePair<int, ChannelInfo> p in channelTab) { sortedChannels.Add(p); }
+ sortedChannels.Sort((p1, p2) => -Comparer<ulong>.Default.Compare(p1.Value.Keywords, p2.Value.Keywords));
+ foreach (var kvpair in sortedChannels)
+ {
+ int channel = kvpair.Key;
+ ChannelInfo channelInfo = kvpair.Value;
+
+ string channelType = null;
+ string elementName = "channel";
+ bool enabled = false;
+ string fullName = null;
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ string isolation = null;
+ string access = null;
+#endif
+ if (channelInfo.Attribs != null)
+ {
+ var attribs = channelInfo.Attribs;
+ if (Enum.IsDefined(typeof(EventChannelType), attribs.EventChannelType))
+ channelType = attribs.EventChannelType.ToString();
+ enabled = attribs.Enabled;
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ if (attribs.ImportChannel != null)
+ {
+ fullName = attribs.ImportChannel;
+ elementName = "importChannel";
+ }
+ if (Enum.IsDefined(typeof(EventChannelIsolation), attribs.Isolation))
+ isolation = attribs.Isolation.ToString();
+ access = attribs.Access;
+#endif
+ }
+ if (fullName == null)
+ fullName = providerName + "/" + channelInfo.Name;
+
+ sb.Append(" <").Append(elementName);
+ sb.Append(" chid=\"").Append(channelInfo.Name).Append("\"");
+ sb.Append(" name=\"").Append(fullName).Append("\"");
+ if (elementName == "channel") // not applicable to importChannels.
+ {
+ WriteMessageAttrib(sb, "channel", channelInfo.Name, null);
+ sb.Append(" value=\"").Append(channel).Append("\"");
+ if (channelType != null)
+ sb.Append(" type=\"").Append(channelType).Append("\"");
+ sb.Append(" enabled=\"").Append(enabled.ToString().ToLower()).Append("\"");
+#if FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+ if (access != null)
+ sb.Append(" access=\"").Append(access).Append("\"");
+ if (isolation != null)
+ sb.Append(" isolation=\"").Append(isolation).Append("\"");
+#endif
+ }
+ sb.Append("/>").AppendLine();
+ }
+ sb.Append(" </channels>").AppendLine();
+ }
+#endif
+
+ // Write out the tasks
+ if (taskTab != null)
+ {
+
+ sb.Append(" <tasks>").AppendLine();
+ var sortedTasks = new List<int>(taskTab.Keys);
+ sortedTasks.Sort();
+ foreach (int task in sortedTasks)
+ {
+ sb.Append(" <task");
+ WriteNameAndMessageAttribs(sb, "task", taskTab[task]);
+ sb.Append(" value=\"").Append(task).Append("\"/>").AppendLine();
+ }
+ sb.Append(" </tasks>").AppendLine();
+ }
+
+ // Write out the maps
+ if (mapsTab != null)
+ {
+ sb.Append(" <maps>").AppendLine();
+ foreach (Type enumType in mapsTab.Values)
+ {
+ bool isbitmap = EventSource.GetCustomAttributeHelper(enumType, typeof(FlagsAttribute), flags) != null;
+ string mapKind = isbitmap ? "bitMap" : "valueMap";
+ sb.Append(" <").Append(mapKind).Append(" name=\"").Append(enumType.Name).Append("\">").AppendLine();
+
+ // write out each enum value
+ FieldInfo[] staticFields = enumType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Static);
+ foreach (FieldInfo staticField in staticFields)
+ {
+ object constantValObj = staticField.GetRawConstantValue();
+ if (constantValObj != null)
+ {
+ long hexValue;
+ if (constantValObj is int)
+ hexValue = ((int)constantValObj);
+ else if (constantValObj is long)
+ hexValue = ((long)constantValObj);
+ else
+ continue;
+
+ // ETW requires all bitmap values to be powers of 2. Skip the ones that are not.
+ // TODO: Warn people about the dropping of values.
+ if (isbitmap && ((hexValue & (hexValue - 1)) != 0 || hexValue == 0))
+ continue;
+
+ sb.Append(" <map value=\"0x").Append(hexValue.ToString("x", CultureInfo.InvariantCulture)).Append("\"");
+ WriteMessageAttrib(sb, "map", enumType.Name + "." + staticField.Name, staticField.Name);
+ sb.Append("/>").AppendLine();
+ }
+ }
+ sb.Append(" </").Append(mapKind).Append(">").AppendLine();
+ }
+ sb.Append(" </maps>").AppendLine();
+ }
+
+ // Write out the opcodes
+ sb.Append(" <opcodes>").AppendLine();
+ var sortedOpcodes = new List<int>(opcodeTab.Keys);
+ sortedOpcodes.Sort();
+ foreach (int opcode in sortedOpcodes)
+ {
+ sb.Append(" <opcode");
+ WriteNameAndMessageAttribs(sb, "opcode", opcodeTab[opcode]);
+ sb.Append(" value=\"").Append(opcode).Append("\"/>").AppendLine();
+ }
+ sb.Append(" </opcodes>").AppendLine();
+
+ // Write out the keywords
+ if (keywordTab != null)
+ {
+ sb.Append(" <keywords>").AppendLine();
+ var sortedKeywords = new List<ulong>(keywordTab.Keys);
+ sortedKeywords.Sort();
+ foreach (ulong keyword in sortedKeywords)
+ {
+ sb.Append(" <keyword");
+ WriteNameAndMessageAttribs(sb, "keyword", keywordTab[keyword]);
+ sb.Append(" mask=\"0x").Append(keyword.ToString("x", CultureInfo.InvariantCulture)).Append("\"/>").AppendLine();
+ }
+ sb.Append(" </keywords>").AppendLine();
+ }
+
+ sb.Append(" <events>").AppendLine();
+ sb.Append(events);
+ sb.Append(" </events>").AppendLine();
+
+ sb.Append(" <templates>").AppendLine();
+ if (templates.Length > 0)
+ {
+ sb.Append(templates);
+ }
+ else
+ {
+ // Work around a cornercase ETW issue where a manifest with no templates causes
+ // ETW events to not get sent to their associated channel.
+ sb.Append(" <template tid=\"_empty\"></template>").AppendLine();
+ }
+ sb.Append(" </templates>").AppendLine();
+
+ sb.Append("</provider>").AppendLine();
+ sb.Append("</events>").AppendLine();
+ sb.Append("</instrumentation>").AppendLine();
+
+ // Output the localization information.
+ sb.Append("<localization>").AppendLine();
+
+ List<CultureInfo> cultures = null;
+ if (resources != null && (flags & EventManifestOptions.AllCultures) != 0)
+ {
+ cultures = GetSupportedCultures(resources);
+ }
+ else
+ {
+ cultures = new List<CultureInfo>();
+ cultures.Add(CultureInfo.CurrentUICulture);
+ }
+#if ES_BUILD_STANDALONE || PROJECTN
+ var sortedStrings = new List<string>(stringTab.Keys);
+ sortedStrings.Sort();
+#else
+ // DD 947936
+ var sortedStrings = new string[stringTab.Keys.Count];
+ stringTab.Keys.CopyTo(sortedStrings, 0);
+ // Avoid using public Array.Sort as that attempts to access BinaryCompatibility. Unfortunately FrameworkEventSource gets called
+ // very early in the app domain creation, when _FusionStore is not set up yet, resulting in a failure to run the static constructory
+ // for BinaryCompatibility. This failure is then cached and a TypeInitializationException is thrown every time some code attampts to
+ // access BinaryCompatibility.
+ ArraySortHelper<string>.IntrospectiveSort(sortedStrings, 0, sortedStrings.Length, Comparer<string>.Default);
+#endif
+ foreach (var ci in cultures)
+ {
+ sb.Append(" <resources culture=\"").Append(ci.Name).Append("\">").AppendLine();
+ sb.Append(" <stringTable>").AppendLine();
+
+ foreach (var stringKey in sortedStrings)
+ {
+ string val = GetLocalizedMessage(stringKey, ci, etwFormat: true);
+ sb.Append(" <string id=\"").Append(stringKey).Append("\" value=\"").Append(val).Append("\"/>").AppendLine();
+ }
+ sb.Append(" </stringTable>").AppendLine();
+ sb.Append(" </resources>").AppendLine();
+ }
+ sb.Append("</localization>").AppendLine();
+ sb.AppendLine("</instrumentationManifest>");
+ return sb.ToString();
+ }
+
+ #region private
+ private void WriteNameAndMessageAttribs(StringBuilder stringBuilder, string elementName, string name)
+ {
+ stringBuilder.Append(" name=\"").Append(name).Append("\"");
+ WriteMessageAttrib(sb, elementName, name, name);
+ }
+ private void WriteMessageAttrib(StringBuilder stringBuilder, string elementName, string name, string value)
+ {
+ string key = elementName + "_" + name;
+ // See if the user wants things localized.
+ if (resources != null)
+ {
+ // resource fallback: strings in the neutral culture will take precedence over inline strings
+ string localizedString = resources.GetString(key, CultureInfo.InvariantCulture);
+ if (localizedString != null)
+ value = localizedString;
+ }
+ if (value == null)
+ return;
+
+ stringBuilder.Append(" message=\"$(string.").Append(key).Append(")\"");
+ string prevValue;
+ if (stringTab.TryGetValue(key, out prevValue) && !prevValue.Equals(value))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_DuplicateStringKey", key), true);
+ return;
+ }
+
+ stringTab[key] = value;
+ }
+ internal string GetLocalizedMessage(string key, CultureInfo ci, bool etwFormat)
+ {
+ string value = null;
+ if (resources != null)
+ {
+ string localizedString = resources.GetString(key, ci);
+ if (localizedString != null)
+ {
+ value = localizedString;
+ if (etwFormat && key.StartsWith("event_", StringComparison.Ordinal))
+ {
+ var evtName = key.Substring("event_".Length);
+ value = TranslateToManifestConvention(value, evtName);
+ }
+ }
+ }
+ if (etwFormat && value == null)
+ stringTab.TryGetValue(key, out value);
+
+ return value;
+ }
+
+ /// <summary>
+ /// There's no API to enumerate all languages an assembly is localized into, so instead
+ /// we enumerate through all the "known" cultures and attempt to load a corresponding satellite
+ /// assembly
+ /// </summary>
+ /// <param name="resources"></param>
+ /// <returns></returns>
+ private static List<CultureInfo> GetSupportedCultures(ResourceManager resources)
+ {
+ var cultures = new List<CultureInfo>();
+#if !ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN
+ foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures /*| CultureTypes.NeutralCultures*/))
+ {
+ if (resources.GetResourceSet(ci, true, false) != null)
+ cultures.Add(ci);
+ }
+#endif // !ES_BUILD_PCL && !FEATURE_CORECLR
+ if (!cultures.Contains(CultureInfo.CurrentUICulture))
+ cultures.Insert(0, CultureInfo.CurrentUICulture);
+ return cultures;
+ }
+
+ private static string GetLevelName(EventLevel level)
+ {
+ return (((int)level >= 16) ? "" : "win:") + level.ToString();
+ }
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ private string GetChannelName(EventChannel channel, string eventName, string eventMessage)
+ {
+ ChannelInfo info = null;
+ if (channelTab == null || !channelTab.TryGetValue((int)channel, out info))
+ {
+ if (channel < EventChannel.Admin) // || channel > EventChannel.Debug)
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+
+ // allow channels to be auto-defined. The well known ones get their well known names, and the
+ // 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.
+
+ AddChannel(channelName, (int)channel, GetDefaultChannelAttribute(channel));
+ if (!channelTab.TryGetValue((int)channel, out info))
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+ }
+ // events that specify admin channels *must* have non-null "Message" attributes
+ if (resources != null && eventMessage == null)
+ eventMessage = resources.GetString("event_" + eventName, CultureInfo.InvariantCulture);
+ if (info.Attribs.EventChannelType == EventChannelType.Admin && eventMessage == null)
+ ManifestError(Resources.GetResourceString("EventSource_EventWithAdminChannelMustHaveMessage", eventName, info.Name));
+ return info.Name;
+ }
+#endif
+ private string GetTaskName(EventTask task, string eventName)
+ {
+ if (task == EventTask.None)
+ return "";
+
+ string ret;
+ if (taskTab == null)
+ taskTab = new Dictionary<int, string>();
+ if (!taskTab.TryGetValue((int)task, out ret))
+ ret = taskTab[(int)task] = eventName;
+ return ret;
+ }
+
+ private string GetOpcodeName(EventOpcode opcode, string eventName)
+ {
+ switch (opcode)
+ {
+ case EventOpcode.Info:
+ return "win:Info";
+ case EventOpcode.Start:
+ return "win:Start";
+ case EventOpcode.Stop:
+ return "win:Stop";
+ case EventOpcode.DataCollectionStart:
+ return "win:DC_Start";
+ case EventOpcode.DataCollectionStop:
+ return "win:DC_Stop";
+ case EventOpcode.Extension:
+ return "win:Extension";
+ case EventOpcode.Reply:
+ return "win:Reply";
+ case EventOpcode.Resume:
+ return "win:Resume";
+ case EventOpcode.Suspend:
+ return "win:Suspend";
+ case EventOpcode.Send:
+ return "win:Send";
+ case EventOpcode.Receive:
+ return "win:Receive";
+ }
+
+ string ret;
+ if (opcodeTab == null || !opcodeTab.TryGetValue((int)opcode, out ret))
+ {
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedOpcode", opcode, eventName), true);
+ ret = null;
+ }
+ return ret;
+ }
+
+ private string GetKeywords(ulong keywords, string eventName)
+ {
+ // ignore keywords associate with channels
+ // See ValidPredefinedChannelKeywords def for more.
+ keywords &= ~ValidPredefinedChannelKeywords;
+
+ string ret = "";
+ for (ulong bit = 1; bit != 0; bit <<= 1)
+ {
+ if ((keywords & bit) != 0)
+ {
+ string keyword = null;
+ if ((keywordTab == null || !keywordTab.TryGetValue(bit, out keyword)) &&
+ (bit >= (ulong)0x1000000000000))
+ {
+ // do not report Windows reserved keywords in the manifest (this allows the code
+ // to be resilient to potential renaming of these keywords)
+ keyword = string.Empty;
+ }
+ if (keyword == null)
+ {
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedKeyword", "0x" + bit.ToString("x", CultureInfo.CurrentCulture), eventName), true);
+ keyword = string.Empty;
+ }
+ if (ret.Length != 0 && keyword.Length != 0)
+ ret = ret + " ";
+ ret = ret + keyword;
+ }
+ }
+ return ret;
+ }
+
+ private string GetTypeName(Type type)
+ {
+ if (type.IsEnum())
+ {
+ FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+ var typeName = GetTypeName(fields[0].FieldType);
+ return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
+ }
+
+ return GetTypeNameHelper(type);
+ }
+
+ private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count)
+ {
+ if (stringBuilder == null)
+ stringBuilder = new StringBuilder();
+ stringBuilder.Append(eventMessage, startIndex, count);
+ }
+
+ // Manifest messages use %N conventions for their message substitutions. Translate from
+ // .NET conventions. We can't use RegEx for this (we are in mscorlib), so we do it 'by hand'
+ private string TranslateToManifestConvention(string eventMessage, string evtName)
+ {
+ StringBuilder stringBuilder = null; // We lazily create this
+ int writtenSoFar = 0;
+ int chIdx = -1;
+ for (int i = 0; ; )
+ {
+ if (i >= eventMessage.Length)
+ {
+ if (stringBuilder == null)
+ return eventMessage;
+ UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
+ return stringBuilder.ToString();
+ }
+
+ if (eventMessage[i] == '%')
+ {
+ // handle format message escaping character '%' by escaping it
+ UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
+ stringBuilder.Append("%%");
+ i++;
+ writtenSoFar = i;
+ }
+ else if (i < eventMessage.Length - 1 &&
+ (eventMessage[i] == '{' && eventMessage[i + 1] == '{' || eventMessage[i] == '}' && eventMessage[i + 1] == '}'))
+ {
+ // handle C# escaped '{" and '}'
+ UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
+ stringBuilder.Append(eventMessage[i]);
+ i++; i++;
+ writtenSoFar = i;
+ }
+ else if (eventMessage[i] == '{')
+ {
+ int leftBracket = i;
+ i++;
+ int argNum = 0;
+ while (i < eventMessage.Length && Char.IsDigit(eventMessage[i]))
+ {
+ argNum = argNum * 10 + eventMessage[i] - '0';
+ i++;
+ }
+ if (i < eventMessage.Length && eventMessage[i] == '}')
+ {
+ i++;
+ UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, leftBracket - writtenSoFar);
+ int manIndex = TranslateIndexToManifestConvention(argNum, evtName);
+ stringBuilder.Append('%').Append(manIndex);
+ // An '!' after the insert specifier {n} will be interpreted as a literal.
+ // We'll escape it so that mc.exe does not attempt to consider it the
+ // beginning of a format string.
+ if (i < eventMessage.Length && eventMessage[i] == '!')
+ {
+ i++;
+ stringBuilder.Append("%!");
+ }
+ writtenSoFar = i;
+ }
+ else
+ {
+ ManifestError(Resources.GetResourceString("EventSource_UnsupportedMessageProperty", evtName, eventMessage));
+ }
+ }
+ else if ((chIdx = "&<>'\"\r\n\t".IndexOf(eventMessage[i])) >= 0)
+ {
+ string[] escapes = { "&amp;", "&lt;", "&gt;", "&apos;", "&quot;", "%r", "%n", "%t" };
+ var update = new Action<char, string>(
+ (ch, escape) =>
+ {
+ UpdateStringBuilder(ref stringBuilder, eventMessage, writtenSoFar, i - writtenSoFar);
+ i++;
+ stringBuilder.Append(escape);
+ writtenSoFar = i;
+ });
+ update(eventMessage[i], escapes[chIdx]);
+ }
+ else
+ i++;
+ }
+ }
+
+ private int TranslateIndexToManifestConvention(int idx, string evtName)
+ {
+ List<int> byteArrArgIndices;
+ if (perEventByteArrayArgIndices.TryGetValue(evtName, out byteArrArgIndices))
+ {
+ foreach (var byArrIdx in byteArrArgIndices)
+ {
+ if (idx >= byArrIdx)
+ ++idx;
+ else
+ break;
+ }
+ }
+ return idx + 1;
+ }
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ class ChannelInfo
+ {
+ public string Name;
+ public ulong Keywords;
+ public EventChannelAttribute Attribs;
+ }
+#endif
+
+ Dictionary<int, string> opcodeTab;
+ Dictionary<int, string> taskTab;
+#if FEATURE_MANAGED_ETW_CHANNELS
+ Dictionary<int, ChannelInfo> channelTab;
+#endif
+ Dictionary<ulong, string> keywordTab;
+ Dictionary<string, Type> mapsTab;
+
+ Dictionary<string, string> stringTab; // Maps unlocalized strings to localized ones
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ // WCF used EventSource to mimic a existing ETW manifest. To support this
+ // in just their case, we allowed them to specify the keywords associated
+ // with their channels explicitly. ValidPredefinedChannelKeywords is
+ // this set of channel keywords that we allow to be explicitly set. You
+ // can ignore these bits otherwise.
+ internal const ulong ValidPredefinedChannelKeywords = 0xF000000000000000;
+ ulong nextChannelKeywordBit = 0x8000000000000000; // available Keyword bit to be used for next channel definition, grows down
+ const int MaxCountChannels = 8; // a manifest can defined at most 8 ETW channels
+#endif
+
+ StringBuilder sb; // Holds the provider information.
+ StringBuilder events; // Holds the events.
+ StringBuilder templates;
+
+#if FEATURE_MANAGED_ETW_CHANNELS
+ string providerName;
+#endif
+ ResourceManager resources; // Look up localized strings here.
+ EventManifestOptions flags;
+ IList<string> errors; // list of currently encountered errors
+ Dictionary<string, List<int>> perEventByteArrayArgIndices; // "event_name" -> List_of_Indices_of_Byte[]_Arg
+
+ // State we track between StartEvent and EndEvent.
+ string eventName; // Name of the event currently being processed.
+ int numParams; // keeps track of the number of args the event has.
+ List<int> byteArrArgIndices; // keeps track of the index of each byte[] argument
+ #endregion
+ }
+
+ /// <summary>
+ /// Used to send the m_rawManifest into the event dispatcher as a series of events.
+ /// </summary>
+ internal struct ManifestEnvelope
+ {
+ public const int MaxChunkSize = 0xFF00;
+ public enum ManifestFormats : byte
+ {
+ SimpleXmlFormat = 1, // simply dump the XML manifest as UTF8
+ }
+
+ public ManifestFormats Format;
+ public byte MajorVersion;
+ public byte MinorVersion;
+ public byte Magic;
+ public ushort TotalChunks;
+ public ushort ChunkNumber;
+ };
+
+ #endregion
+}
+
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSourceException.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSourceException.cs
new file mode 100644
index 0000000000..3fc9d545b8
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSourceException.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.Serialization;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Exception that is thrown when an error occurs during EventSource operation.
+ /// </summary>
+#if (!ES_BUILD_PCL && !PROJECTN)
+ [Serializable]
+#endif
+ public class EventSourceException : Exception
+ {
+ /// <summary>
+ /// Initializes a new instance of the EventSourceException class.
+ /// </summary>
+ public EventSourceException() :
+ base(Resources.GetResourceString("EventSource_ListenerWriteFailure")) { }
+
+ /// <summary>
+ /// Initializes a new instance of the EventSourceException class with a specified error message.
+ /// </summary>
+ public EventSourceException(string message) : base(message) { }
+
+ /// <summary>
+ /// Initializes a new instance of the EventSourceException class with a specified error message
+ /// and a reference to the inner exception that is the cause of this exception.
+ /// </summary>
+ public EventSourceException(string message, Exception innerException) : base(message, innerException) { }
+
+#if (!ES_BUILD_PCL && !PROJECTN)
+ /// <summary>
+ /// Initializes a new instance of the EventSourceException class with serialized data.
+ /// </summary>
+ protected EventSourceException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+#endif
+
+ internal EventSourceException(Exception innerException) :
+ base(Resources.GetResourceString("EventSource_ListenerWriteFailure"), innerException) { }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs
new file mode 100644
index 0000000000..00bd0b7caa
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/EventSource_CoreCLR.cs
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.Reflection;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Tracing
+{
+ public partial class EventSource
+ {
+ // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. This API
+ /// should be used when the caller knows the thread's current activity (the one being
+ /// overwritten) has completed. Otherwise, callers should prefer the overload that
+ /// return the oldActivityThatWillContinue (below).
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ [System.Security.SecuritySafeCritical]
+ public static void SetCurrentThreadActivityId(Guid activityId)
+ {
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
+#if FEATURE_MANAGED_ETW
+#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(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref activityId) == 0)
+ {
+#if FEATURE_ACTIVITYSAMPLING
+ var activityDying = s_activityDying;
+ if (activityDying != null && newId != activityId)
+ {
+ if (activityId == Guid.Empty)
+ {
+ activityId = FallbackActivityId;
+ }
+ // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
+ activityDying(activityId); // This is actually the OLD activity ID.
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. It returns
+ /// whatever activity the thread was previously marked with. There is a convention that
+ /// callers can assume that callees restore this activity mark before the callee returns.
+ /// To encourage this this API returns the old activity, so that it can be restored later.
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
+ /// which will continue at some point in the future, on the current thread</param>
+ [System.Security.SecuritySafeCritical]
+ public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
+ {
+ oldActivityThatWillContinue = activityId;
+#if FEATURE_MANAGED_ETW
+ // 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.
+
+ UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // FEATURE_MANAGED_ETW
+
+ // We don't call the activityDying callback here because the caller has declared that
+ // it is not dying.
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
+ }
+
+ /// <summary>
+ /// Retrieves the ETW activity ID associated with the current thread.
+ /// </summary>
+ public static Guid CurrentThreadActivityId
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ // 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.
+ Guid retVal = new Guid();
+#if FEATURE_MANAGED_ETW
+ UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#endif // FEATURE_MANAGED_ETW
+ return retVal;
+ }
+ }
+
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ return eventData.Parameters.Length;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ return eventData.Parameters[parameterId].ParameterType;
+ }
+
+ private static string GetResourceString(string key, params object[] args)
+ {
+ return Environment.GetResourceString(key, args);
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = false;
+ }
+
+ internal partial class ManifestBuilder
+ {
+ private string GetTypeNameHelper(Type type)
+ {
+ switch (type.GetTypeCode())
+ {
+ case TypeCode.Boolean:
+ return "win:Boolean";
+ case TypeCode.Byte:
+ return "win:UInt8";
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ return "win:UInt16";
+ case TypeCode.UInt32:
+ return "win:UInt32";
+ case TypeCode.UInt64:
+ return "win:UInt64";
+ case TypeCode.SByte:
+ return "win:Int8";
+ case TypeCode.Int16:
+ return "win:Int16";
+ case TypeCode.Int32:
+ return "win:Int32";
+ case TypeCode.Int64:
+ return "win:Int64";
+ case TypeCode.String:
+ return "win:UnicodeString";
+ case TypeCode.Single:
+ return "win:Float";
+ case TypeCode.Double:
+ return "win:Double";
+ case TypeCode.DateTime:
+ return "win:FILETIME";
+ default:
+ if (type == typeof(Guid))
+ return "win:GUID";
+ else if (type == typeof(IntPtr))
+ return "win:Pointer";
+ else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+ return "win:Binary";
+
+ ManifestError(Resources.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
+ return string.Empty;
+ }
+ }
+ }
+
+ internal partial class EventProvider
+ {
+ [System.Security.SecurityCritical]
+ internal unsafe int SetInformation(
+ UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
+ IntPtr data,
+ uint dataSize)
+ {
+ int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
+
+ if (!m_setInformationMissing)
+ {
+ try
+ {
+ status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
+ m_regHandle,
+ eventInfoClass,
+ (void *)data,
+ (int)dataSize);
+ }
+ catch (TypeLoadException)
+ {
+ m_setInformationMissing = true;
+ }
+ }
+
+ return status;
+ }
+ }
+
+ internal static class Resources
+ {
+ internal static string GetResourceString(string key, params object[] args)
+ {
+ return Environment.GetResourceString(key, args);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/FrameworkEventSource.cs b/src/mscorlib/src/System/Diagnostics/Eventing/FrameworkEventSource.cs
new file mode 100644
index 0000000000..6d3e28fcab
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/FrameworkEventSource.cs
@@ -0,0 +1,620 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// ResourcesEtwProvider.cs
+//
+//
+// Managed event source for things that can version with MSCORLIB.
+//
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Text;
+using System.Runtime.CompilerServices;
+
+namespace System.Diagnostics.Tracing {
+
+ // To use the framework provider
+ //
+ // \\clrmain\tools\Perfmonitor /nokernel /noclr /provider:8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1 start
+ // Run run your app
+ // \\clrmain\tools\Perfmonitor stop
+ // \\clrmain\tools\Perfmonitor print
+ //
+ // This will produce an XML file, where each event is pretty-printed with all its arguments nicely parsed.
+ //
+ [FriendAccessAllowed]
+ [EventSource(Guid = "8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1", Name = "System.Diagnostics.Eventing.FrameworkEventSource")]
+ sealed internal class FrameworkEventSource : EventSource {
+ // Defines the singleton instance for the Resources ETW provider
+ public static readonly FrameworkEventSource Log = new FrameworkEventSource();
+
+ // Keyword definitions. These represent logical groups of events that can be turned on and off independently
+ // Often each task has a keyword, but where tasks are determined by subsystem, keywords are determined by
+ // usefulness to end users to filter. Generally users don't mind extra events if they are not high volume
+ // so grouping low volume events together in a single keywords is OK (users can post-filter by task if desired)
+ public static class Keywords {
+ public const EventKeywords Loader = (EventKeywords)0x0001; // This is bit 0
+ public const EventKeywords ThreadPool = (EventKeywords)0x0002;
+ public const EventKeywords NetClient = (EventKeywords)0x0004;
+ //
+ // This is a private event we do not want to expose to customers. It is to be used for profiling
+ // uses of dynamic type loading by ProjectN applications running on the desktop CLR
+ //
+ public const EventKeywords DynamicTypeUsage = (EventKeywords)0x0008;
+ public const EventKeywords ThreadTransfer = (EventKeywords)0x0010;
+ }
+
+ /// <summary>ETW tasks that have start/stop events.</summary>
+ [FriendAccessAllowed]
+ public static class Tasks // this name is important for EventSource
+ {
+ /// <summary>Begin / End - GetResponse.</summary>
+ public const EventTask GetResponse = (EventTask)1;
+ /// <summary>Begin / End - GetRequestStream</summary>
+ public const EventTask GetRequestStream = (EventTask)2;
+ /// <summary>Send / Receive - begin transfer/end transfer</summary>
+ public const EventTask ThreadTransfer = (EventTask)3;
+ }
+
+ [FriendAccessAllowed]
+ public static class Opcodes
+ {
+ public const EventOpcode ReceiveHandled = (EventOpcode)11;
+ }
+
+ // This predicate is used by consumers of this class to deteremine if the class has actually been initialized,
+ // and therefore if the public statics are available for use. This is typically not a problem... if the static
+ // class constructor fails, then attempts to access the statics (or even this property) will result in a
+ // TypeInitializationException. However, that is not the case while the class loader is actually trying to construct
+ // the TypeInitializationException instance to represent that failure, and some consumers of this class are on
+ // that code path, specifically the resource manager.
+ public static bool IsInitialized
+ {
+ get
+ {
+ return Log != null;
+ }
+ }
+
+ // The FrameworkEventSource GUID is {8E9F5090-2D75-4d03-8A81-E5AFBF85DAF1}
+ private FrameworkEventSource() : base(new Guid(0x8e9f5090, 0x2d75, 0x4d03, 0x8a, 0x81, 0xe5, 0xaf, 0xbf, 0x85, 0xda, 0xf1), "System.Diagnostics.Eventing.FrameworkEventSource") { }
+
+ // WriteEvent overloads (to avoid the "params" EventSource.WriteEvent
+
+ // optimized for common signatures (used by the ThreadTransferSend/Receive events)
+ [NonEvent, System.Security.SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEvent(int eventId, long arg1, int arg2, string arg3, bool arg4)
+ {
+ if (IsEnabled())
+ {
+ if (arg3 == null) arg3 = "";
+ fixed (char* string3Bytes = arg3)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)string3Bytes;
+ descrs[2].Size = ((arg3.Length + 1) * 2);
+ descrs[3].DataPointer = (IntPtr)(&arg4);
+ descrs[3].Size = 4;
+ WriteEventCore(eventId, 4, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (used by the ThreadTransferSend/Receive events)
+ [NonEvent, System.Security.SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEvent(int eventId, long arg1, int arg2, string arg3)
+ {
+ if (IsEnabled())
+ {
+ if (arg3 == null) arg3 = "";
+ fixed (char* string3Bytes = arg3)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)string3Bytes;
+ descrs[2].Size = ((arg3.Length + 1) * 2);
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (used by the BeginGetResponse/BeginGetRequestStream events)
+ [NonEvent, System.Security.SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEvent(int eventId, long arg1, string arg2, bool arg3, bool arg4)
+ {
+ if (IsEnabled())
+ {
+ if (arg2 == null) arg2 = "";
+ fixed (char* string2Bytes = arg2)
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)string2Bytes;
+ descrs[1].Size = ((arg2.Length + 1) * 2);
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 4;
+ descrs[3].DataPointer = (IntPtr)(&arg4);
+ descrs[3].Size = 4;
+ WriteEventCore(eventId, 4, descrs);
+ }
+ }
+ }
+
+ // optimized for common signatures (used by the EndGetRequestStream event)
+ [NonEvent, System.Security.SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEvent(int eventId, long arg1, bool arg2, bool arg3)
+ {
+ if (IsEnabled())
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 4;
+ WriteEventCore(eventId, 3, descrs);
+ }
+ }
+
+ // optimized for common signatures (used by the EndGetResponse event)
+ [NonEvent, System.Security.SecuritySafeCritical]
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
+ private unsafe void WriteEvent(int eventId, long arg1, bool arg2, bool arg3, int arg4)
+ {
+ if (IsEnabled())
+ {
+ EventSource.EventData* descrs = stackalloc EventSource.EventData[4];
+ descrs[0].DataPointer = (IntPtr)(&arg1);
+ descrs[0].Size = 8;
+ descrs[1].DataPointer = (IntPtr)(&arg2);
+ descrs[1].Size = 4;
+ descrs[2].DataPointer = (IntPtr)(&arg3);
+ descrs[2].Size = 4;
+ descrs[3].DataPointer = (IntPtr)(&arg4);
+ descrs[3].Size = 4;
+ WriteEventCore(eventId, 4, descrs);
+ }
+ }
+
+ // ResourceManager Event Definitions
+
+ [Event(1, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerLookupStarted(String baseName, String mainAssemblyName, String cultureName) {
+ WriteEvent(1, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(2, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerLookingForResourceSet(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(2, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(3, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerFoundResourceSetInCache(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(3, baseName, mainAssemblyName, cultureName);
+ }
+
+ // After loading a satellite assembly, we already have the ResourceSet for this culture in
+ // the cache. This can happen if you have an assembly load callback that called into this
+ // instance of the ResourceManager.
+ [Event(4, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerFoundResourceSetInCacheUnexpected(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(4, baseName, mainAssemblyName, cultureName);
+ }
+
+ // manifest resource stream lookup succeeded
+ [Event(5, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerStreamFound(String baseName, String mainAssemblyName, String cultureName, String loadedAssemblyName, String resourceFileName) {
+ if (IsEnabled())
+ WriteEvent(5, baseName, mainAssemblyName, cultureName, loadedAssemblyName, resourceFileName);
+ }
+
+ // manifest resource stream lookup failed
+ [Event(6, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerStreamNotFound(String baseName, String mainAssemblyName, String cultureName, String loadedAssemblyName, String resourceFileName) {
+ if (IsEnabled())
+ WriteEvent(6, baseName, mainAssemblyName, cultureName, loadedAssemblyName, resourceFileName);
+ }
+
+ [Event(7, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerGetSatelliteAssemblySucceeded(String baseName, String mainAssemblyName, String cultureName, String assemblyName) {
+ if (IsEnabled())
+ WriteEvent(7, baseName, mainAssemblyName, cultureName, assemblyName);
+ }
+
+ [Event(8, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerGetSatelliteAssemblyFailed(String baseName, String mainAssemblyName, String cultureName, String assemblyName) {
+ if (IsEnabled())
+ WriteEvent(8, baseName, mainAssemblyName, cultureName, assemblyName);
+ }
+
+ [Event(9, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(String baseName, String mainAssemblyName, String assemblyName, String resourceFileName) {
+ if (IsEnabled())
+ WriteEvent(9, baseName, mainAssemblyName, assemblyName, resourceFileName);
+ }
+
+ [Event(10, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerCaseInsensitiveResourceStreamLookupFailed(String baseName, String mainAssemblyName, String assemblyName, String resourceFileName) {
+ if (IsEnabled())
+ WriteEvent(10, baseName, mainAssemblyName, assemblyName, resourceFileName);
+ }
+
+ // Could not access the manifest resource the assembly
+ [Event(11, Level = EventLevel.Error, Keywords = Keywords.Loader)]
+ public void ResourceManagerManifestResourceAccessDenied(String baseName, String mainAssemblyName, String assemblyName, String canonicalName) {
+ if (IsEnabled())
+ WriteEvent(11, baseName, mainAssemblyName, assemblyName, canonicalName);
+ }
+
+ // Neutral resources are sufficient for this culture. Skipping satellites
+ [Event(12, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerNeutralResourcesSufficient(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(12, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(13, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerNeutralResourceAttributeMissing(String mainAssemblyName) {
+ if (IsEnabled())
+ WriteEvent(13, mainAssemblyName);
+ }
+
+ [Event(14, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerCreatingResourceSet(String baseName, String mainAssemblyName, String cultureName, String fileName) {
+ if (IsEnabled())
+ WriteEvent(14, baseName, mainAssemblyName, cultureName, fileName);
+ }
+
+ [Event(15, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerNotCreatingResourceSet(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(15, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(16, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerLookupFailed(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(16, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(17, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerReleasingResources(String baseName, String mainAssemblyName) {
+ if (IsEnabled())
+ WriteEvent(17, baseName, mainAssemblyName);
+ }
+
+ [Event(18, Level = EventLevel.Warning, Keywords = Keywords.Loader)]
+ public void ResourceManagerNeutralResourcesNotFound(String baseName, String mainAssemblyName, String resName) {
+ if (IsEnabled())
+ WriteEvent(18, baseName, mainAssemblyName, resName);
+ }
+
+ [Event(19, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerNeutralResourcesFound(String baseName, String mainAssemblyName, String resName) {
+ if (IsEnabled())
+ WriteEvent(19, baseName, mainAssemblyName, resName);
+ }
+
+ [Event(20, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerAddingCultureFromConfigFile(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(20, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(21, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerCultureNotFoundInConfigFile(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(21, baseName, mainAssemblyName, cultureName);
+ }
+
+ [Event(22, Level = EventLevel.Informational, Keywords = Keywords.Loader)]
+ public void ResourceManagerCultureFoundInConfigFile(String baseName, String mainAssemblyName, String cultureName) {
+ if (IsEnabled())
+ WriteEvent(22, baseName, mainAssemblyName, cultureName);
+ }
+
+
+ // ResourceManager Event Wrappers
+
+ [NonEvent]
+ public void ResourceManagerLookupStarted(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerLookupStarted(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerLookingForResourceSet(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerLookingForResourceSet(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerFoundResourceSetInCache(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerFoundResourceSetInCache(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerFoundResourceSetInCacheUnexpected(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerFoundResourceSetInCacheUnexpected(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerStreamFound(String baseName, Assembly mainAssembly, String cultureName, Assembly loadedAssembly, String resourceFileName) {
+ if (IsEnabled())
+ ResourceManagerStreamFound(baseName, GetName(mainAssembly), cultureName, GetName(loadedAssembly), resourceFileName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerStreamNotFound(String baseName, Assembly mainAssembly, String cultureName, Assembly loadedAssembly, String resourceFileName) {
+ if (IsEnabled())
+ ResourceManagerStreamNotFound(baseName, GetName(mainAssembly), cultureName, GetName(loadedAssembly), resourceFileName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerGetSatelliteAssemblySucceeded(String baseName, Assembly mainAssembly, String cultureName, String assemblyName) {
+ if (IsEnabled())
+ ResourceManagerGetSatelliteAssemblySucceeded(baseName, GetName(mainAssembly), cultureName, assemblyName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerGetSatelliteAssemblyFailed(String baseName, Assembly mainAssembly, String cultureName, String assemblyName) {
+ if (IsEnabled())
+ ResourceManagerGetSatelliteAssemblyFailed(baseName, GetName(mainAssembly), cultureName, assemblyName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(String baseName, Assembly mainAssembly, String assemblyName, String resourceFileName) {
+ if (IsEnabled())
+ ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(baseName, GetName(mainAssembly), assemblyName, resourceFileName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerCaseInsensitiveResourceStreamLookupFailed(String baseName, Assembly mainAssembly, String assemblyName, String resourceFileName) {
+ if (IsEnabled())
+ ResourceManagerCaseInsensitiveResourceStreamLookupFailed(baseName, GetName(mainAssembly), assemblyName, resourceFileName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerManifestResourceAccessDenied(String baseName, Assembly mainAssembly, String assemblyName, String canonicalName) {
+ if (IsEnabled())
+ ResourceManagerManifestResourceAccessDenied(baseName, GetName(mainAssembly), assemblyName, canonicalName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerNeutralResourcesSufficient(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerNeutralResourcesSufficient(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerNeutralResourceAttributeMissing(Assembly mainAssembly) {
+ if (IsEnabled())
+ ResourceManagerNeutralResourceAttributeMissing(GetName(mainAssembly));
+ }
+
+ [NonEvent]
+ public void ResourceManagerCreatingResourceSet(String baseName, Assembly mainAssembly, String cultureName, String fileName) {
+ if (IsEnabled())
+ ResourceManagerCreatingResourceSet(baseName, GetName(mainAssembly), cultureName, fileName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerNotCreatingResourceSet(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerNotCreatingResourceSet(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerLookupFailed(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerLookupFailed(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerReleasingResources(String baseName, Assembly mainAssembly) {
+ if (IsEnabled())
+ ResourceManagerReleasingResources(baseName, GetName(mainAssembly));
+ }
+
+ [NonEvent]
+ public void ResourceManagerNeutralResourcesNotFound(String baseName, Assembly mainAssembly, String resName) {
+ if (IsEnabled())
+ ResourceManagerNeutralResourcesNotFound(baseName, GetName(mainAssembly), resName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerNeutralResourcesFound(String baseName, Assembly mainAssembly, String resName) {
+ if (IsEnabled())
+ ResourceManagerNeutralResourcesFound(baseName, GetName(mainAssembly), resName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerAddingCultureFromConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerAddingCultureFromConfigFile(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerCultureNotFoundInConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerCultureNotFoundInConfigFile(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ [NonEvent]
+ public void ResourceManagerCultureFoundInConfigFile(String baseName, Assembly mainAssembly, String cultureName) {
+ if (IsEnabled())
+ ResourceManagerCultureFoundInConfigFile(baseName, GetName(mainAssembly), cultureName);
+ }
+
+ private static string GetName(Assembly assembly) {
+ if (assembly == null)
+ return "<<NULL>>";
+ else
+ return assembly.FullName;
+ }
+
+ [Event(30, Level = EventLevel.Verbose, Keywords = Keywords.ThreadPool|Keywords.ThreadTransfer)]
+ public void ThreadPoolEnqueueWork(long workID) {
+ WriteEvent(30, workID);
+ }
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void ThreadPoolEnqueueWorkObject(object workID) {
+ // convert the Object Id to a long
+ ThreadPoolEnqueueWork((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref workID)));
+ }
+
+ [Event(31, Level = EventLevel.Verbose, Keywords = Keywords.ThreadPool|Keywords.ThreadTransfer)]
+ public void ThreadPoolDequeueWork(long workID) {
+ WriteEvent(31, workID);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void ThreadPoolDequeueWorkObject(object workID) {
+ // convert the Object Id to a long
+ ThreadPoolDequeueWork((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref workID)));
+ }
+
+ // In the desktop runtime they don't use Tasks for the point at which the response happens, which means that the
+ // Activity ID created by start using implicit activity IDs does not match. Thus disable implicit activities (until we fix that)
+ [Event(140, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
+ Task = Tasks.GetResponse, Opcode = EventOpcode.Start, Version = 1)]
+ private void GetResponseStart(long id, string uri, bool success, bool synchronous) {
+ WriteEvent(140, id, uri, success, synchronous);
+ }
+
+ [Event(141, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
+ Task = Tasks.GetResponse, Opcode = EventOpcode.Stop, Version = 1)]
+ private void GetResponseStop(long id, bool success, bool synchronous, int statusCode) {
+ WriteEvent(141, id, success, synchronous, statusCode);
+ }
+
+ // In the desktop runtime they don't use Tasks for the point at which the response happens, which means that the
+ // Activity ID created by start using implicit activity IDs does not match. Thus disable implicit activities (until we fix that)
+ [Event(142, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
+ Task = Tasks.GetRequestStream, Opcode = EventOpcode.Start, Version = 1)]
+ private void GetRequestStreamStart(long id, string uri, bool success, bool synchronous) {
+ WriteEvent(142, id, uri, success, synchronous);
+ }
+
+ [Event(143, Level = EventLevel.Informational, Keywords = Keywords.NetClient, ActivityOptions=EventActivityOptions.Disable,
+ Task = Tasks.GetRequestStream, Opcode = EventOpcode.Stop, Version = 1)]
+ private void GetRequestStreamStop(long id, bool success, bool synchronous) {
+ WriteEvent(143, id, success, synchronous);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void BeginGetResponse(object id, string uri, bool success, bool synchronous) {
+ if (IsEnabled())
+ GetResponseStart(IdForObject(id), uri, success, synchronous);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void EndGetResponse(object id, bool success, bool synchronous, int statusCode) {
+ if (IsEnabled())
+ GetResponseStop(IdForObject(id), success, synchronous, statusCode);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void BeginGetRequestStream(object id, string uri, bool success, bool synchronous) {
+ if (IsEnabled())
+ GetRequestStreamStart(IdForObject(id), uri, success, synchronous);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void EndGetRequestStream(object id, bool success, bool synchronous) {
+ if (IsEnabled())
+ GetRequestStreamStop(IdForObject(id), success, synchronous);
+ }
+
+ // id - represents a correlation ID that allows correlation of two activities, one stamped by
+ // ThreadTransferSend, the other by ThreadTransferReceive
+ // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
+ // 1 - managed Timers ("roaming" ID)
+ // 2 - managed async IO operations (FileStream, PipeStream, a.o.)
+ // 3 - WinRT dispatch operations
+ // info - any additional information user code might consider interesting
+ [Event(150, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = EventOpcode.Send)]
+ public void ThreadTransferSend(long id, int kind, string info, bool multiDequeues) {
+ if (IsEnabled())
+ WriteEvent(150, id, kind, info, multiDequeues);
+ }
+ // id - is a managed object. it gets translated to the object's address. ETW listeners must
+ // keep track of GC movements in order to correlate the value passed to XyzSend with the
+ // (possibly changed) value passed to XyzReceive
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void ThreadTransferSendObj(object id, int kind, string info, bool multiDequeues) {
+ ThreadTransferSend((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info, multiDequeues);
+ }
+
+ // id - represents a correlation ID that allows correlation of two activities, one stamped by
+ // ThreadTransferSend, the other by ThreadTransferReceive
+ // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
+ // 1 - managed Timers ("roaming" ID)
+ // 2 - managed async IO operations (FileStream, PipeStream, a.o.)
+ // 3 - WinRT dispatch operations
+ // info - any additional information user code might consider interesting
+ [Event(151, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = EventOpcode.Receive)]
+ public void ThreadTransferReceive(long id, int kind, string info) {
+ if (IsEnabled())
+ WriteEvent(151, id, kind, info);
+ }
+ // id - is a managed object. it gets translated to the object's address. ETW listeners must
+ // keep track of GC movements in order to correlate the value passed to XyzSend with the
+ // (possibly changed) value passed to XyzReceive
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void ThreadTransferReceiveObj(object id, int kind, string info) {
+ ThreadTransferReceive((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info);
+ }
+
+ // id - represents a correlation ID that allows correlation of two activities, one stamped by
+ // ThreadTransferSend, the other by ThreadTransferReceive
+ // kind - identifies the transfer: values below 64 are reserved for the runtime. Currently used values:
+ // 1 - managed Timers ("roaming" ID)
+ // 2 - managed async IO operations (FileStream, PipeStream, a.o.)
+ // 3 - WinRT dispatch operations
+ // info - any additional information user code might consider interesting
+ [Event(152, Level = EventLevel.Informational, Keywords = Keywords.ThreadTransfer, Task = Tasks.ThreadTransfer, Opcode = Opcodes.ReceiveHandled)]
+ public void ThreadTransferReceiveHandled(long id, int kind, string info) {
+ if (IsEnabled())
+ WriteEvent(152, id, kind, info);
+ }
+ // id - is a managed object. it gets translated to the object's address. ETW listeners must
+ // keep track of GC movements in order to correlate the value passed to XyzSend with the
+ // (possibly changed) value passed to XyzReceive
+ [NonEvent, System.Security.SecuritySafeCritical]
+ public unsafe void ThreadTransferReceiveHandledObj(object id, int kind, string info) {
+ ThreadTransferReceive((long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref id)), kind, info);
+ }
+
+ // return a stable ID for a an object. We use the hash code which is not truely unique but is
+ // close enough for now at least. we add to it 0x7FFFFFFF00000000 to make it distinguishable
+ // from the style of ID that simply casts the object reference to a long (since old versions of the
+ // runtime will emit IDs of that form).
+ private static long IdForObject(object obj) {
+ return obj.GetHashCode() + 0x7FFFFFFF00000000;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/StubEnvironment.cs b/src/mscorlib/src/System/Diagnostics/Eventing/StubEnvironment.cs
new file mode 100644
index 0000000000..e090c4f106
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/StubEnvironment.cs
@@ -0,0 +1,373 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing.Internal
+#else
+namespace System.Diagnostics.Tracing.Internal
+#endif
+{
+#if ES_BUILD_AGAINST_DOTNET_V35
+ using Microsoft.Internal;
+#endif
+ using Microsoft.Reflection;
+ using System.Reflection;
+
+ internal static class Environment
+ {
+ public static readonly string NewLine = System.Environment.NewLine;
+
+ public static int TickCount
+ { get { return System.Environment.TickCount; } }
+
+ public static string GetResourceString(string key, params object[] args)
+ {
+ string fmt = rm.GetString(key);
+ if (fmt != null)
+ return string.Format(fmt, args);
+
+ string sargs = String.Empty;
+ foreach(var arg in args)
+ {
+ if (sargs != String.Empty)
+ sargs += ", ";
+ sargs += arg.ToString();
+ }
+
+ return key + " (" + sargs + ")";
+ }
+
+ public static string GetRuntimeResourceString(string key, params object[] args)
+ {
+ return GetResourceString(key, args);
+ }
+
+ private static System.Resources.ResourceManager rm = new System.Resources.ResourceManager("Microsoft.Diagnostics.Tracing.Messages", typeof(Environment).Assembly());
+ }
+}
+
+#if ES_BUILD_AGAINST_DOTNET_V35
+
+namespace Microsoft.Diagnostics.Contracts.Internal
+{
+ internal class Contract
+ {
+ public static void Assert(bool invariant)
+ {
+ Assert(invariant, string.Empty);
+ }
+ public static void Assert(bool invariant, string message)
+ {
+ if (!invariant)
+ {
+ if (System.Diagnostics.Debugger.IsAttached)
+ System.Diagnostics.Debugger.Break();
+ throw new Exception("Assertion failed: " + message);
+ }
+ }
+ public static void EndContractBlock()
+ { }
+ }
+}
+
+
+namespace Microsoft.Internal
+{
+ using System.Text;
+
+ internal static class Tuple
+ {
+ public static Tuple<T1> Create<T1>(T1 item1)
+ {
+ return new Tuple<T1>(item1);
+ }
+
+ public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
+ {
+ return new Tuple<T1, T2>(item1, item2);
+ }
+ }
+
+ [Serializable]
+ internal class Tuple<T1>
+ {
+ private readonly T1 m_Item1;
+
+ public T1 Item1 { get { return m_Item1; } }
+
+ public Tuple(T1 item1)
+ {
+ m_Item1 = item1;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ sb.Append(m_Item1);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int Size
+ {
+ get
+ {
+ return 1;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2>
+ {
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+
+ public Tuple(T1 item1, T2 item2)
+ {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ }
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int Size
+ {
+ get
+ {
+ return 2;
+ }
+ }
+ }
+}
+
+#endif
+
+namespace Microsoft.Reflection
+{
+ using System.Reflection;
+
+#if (ES_BUILD_PCL || PROJECTN)
+ [Flags]
+ public enum BindingFlags
+ {
+ DeclaredOnly = 0x02, // Only look at the members declared on the Type
+ Instance = 0x04, // Include Instance members in search
+ Static = 0x08, // Include Static members in search
+ Public = 0x10, // Include Public members in search
+ NonPublic = 0x20, // Include Non-Public members in search
+ }
+
+ public enum TypeCode {
+ Empty = 0, // Null reference
+ Object = 1, // Instance that isn't a value
+ DBNull = 2, // Database null value
+ Boolean = 3, // Boolean
+ Char = 4, // Unicode character
+ SByte = 5, // Signed 8-bit integer
+ Byte = 6, // Unsigned 8-bit integer
+ Int16 = 7, // Signed 16-bit integer
+ UInt16 = 8, // Unsigned 16-bit integer
+ Int32 = 9, // Signed 32-bit integer
+ UInt32 = 10, // Unsigned 32-bit integer
+ Int64 = 11, // Signed 64-bit integer
+ UInt64 = 12, // Unsigned 64-bit integer
+ Single = 13, // IEEE 32-bit float
+ Double = 14, // IEEE 64-bit double
+ Decimal = 15, // Decimal
+ DateTime = 16, // DateTime
+ String = 18, // Unicode character string
+ }
+#endif
+ static class ReflectionExtensions
+ {
+#if (!ES_BUILD_PCL && !PROJECTN)
+
+ //
+ // Type extension methods
+ //
+ public static bool IsEnum(this Type type) { return type.IsEnum; }
+ public static bool IsAbstract(this Type type) { return type.IsAbstract; }
+ public static bool IsSealed(this Type type) { return type.IsSealed; }
+ public static bool IsValueType(this Type type) { return type.IsValueType; }
+ public static bool IsGenericType(this Type type) { return type.IsGenericType; }
+ public static Type BaseType(this Type type) { return type.BaseType; }
+ public static Assembly Assembly(this Type type) { return type.Assembly; }
+ public static TypeCode GetTypeCode(this Type type) { return Type.GetTypeCode(type); }
+
+ public static bool ReflectionOnly(this Assembly assm) { return assm.ReflectionOnly; }
+
+#else // ES_BUILD_PCL
+
+ //
+ // Type extension methods
+ //
+ public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; }
+ public static bool IsAbstract(this Type type) { return type.GetTypeInfo().IsAbstract; }
+ public static bool IsSealed(this Type type) { return type.GetTypeInfo().IsSealed; }
+ public static bool IsValueType(this Type type) { return type.GetTypeInfo().IsValueType; }
+ public static bool IsGenericType(this Type type) { return type.IsConstructedGenericType; }
+ public static Type BaseType(this Type type) { return type.GetTypeInfo().BaseType; }
+ public static Assembly Assembly(this Type type) { return type.GetTypeInfo().Assembly; }
+ public static IEnumerable<PropertyInfo> GetProperties(this Type type) { return type.GetRuntimeProperties(); }
+ public static MethodInfo GetGetMethod(this PropertyInfo propInfo) { return propInfo.GetMethod; }
+ public static Type[] GetGenericArguments(this Type type) { return type.GenericTypeArguments; }
+
+ public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
+ {
+ // Minimal implementation to cover only the cases we need
+ System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
+ System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic)) == 0);
+ Func<MethodInfo, bool> visFilter;
+ Func<MethodInfo, bool> instFilter;
+ switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
+ {
+ case 0: visFilter = mi => false; break;
+ case BindingFlags.Public: visFilter = mi => mi.IsPublic; break;
+ case BindingFlags.NonPublic: visFilter = mi => !mi.IsPublic; break;
+ default: visFilter = mi => true; break;
+ }
+ switch (flags & (BindingFlags.Instance | BindingFlags.Static))
+ {
+ case 0: instFilter = mi => false; break;
+ case BindingFlags.Instance: instFilter = mi => !mi.IsStatic; break;
+ case BindingFlags.Static: instFilter = mi => mi.IsStatic; break;
+ default: instFilter = mi => true; break;
+ }
+ List<MethodInfo> methodInfos = new List<MethodInfo>();
+ foreach (var declaredMethod in type.GetTypeInfo().DeclaredMethods)
+ {
+ if (visFilter(declaredMethod) && instFilter(declaredMethod))
+ methodInfos.Add(declaredMethod);
+ }
+ return methodInfos.ToArray();
+ }
+ public static FieldInfo[] GetFields(this Type type, BindingFlags flags)
+ {
+ // Minimal implementation to cover only the cases we need
+ System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
+ System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) == 0);
+ Func<FieldInfo, bool> visFilter;
+ Func<FieldInfo, bool> instFilter;
+ switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
+ {
+ case 0: visFilter = fi => false; break;
+ case BindingFlags.Public: visFilter = fi => fi.IsPublic; break;
+ case BindingFlags.NonPublic: visFilter = fi => !fi.IsPublic; break;
+ default: visFilter = fi => true; break;
+ }
+ switch (flags & (BindingFlags.Instance | BindingFlags.Static))
+ {
+ case 0: instFilter = fi => false; break;
+ case BindingFlags.Instance: instFilter = fi => !fi.IsStatic; break;
+ case BindingFlags.Static: instFilter = fi => fi.IsStatic; break;
+ default: instFilter = fi => true; break;
+ }
+ List<FieldInfo> fieldInfos = new List<FieldInfo>();
+ foreach (var declaredField in type.GetTypeInfo().DeclaredFields)
+ {
+ if (visFilter(declaredField) && instFilter(declaredField))
+ fieldInfos.Add(declaredField);
+ }
+ return fieldInfos.ToArray();
+ }
+ public static Type GetNestedType(this Type type, string nestedTypeName)
+ {
+ TypeInfo ti = null;
+ foreach(var nt in type.GetTypeInfo().DeclaredNestedTypes)
+ {
+ if (nt.Name == nestedTypeName)
+ {
+ ti = nt;
+ break;
+ }
+ }
+ return ti == null ? null : ti.AsType();
+ }
+ public static TypeCode GetTypeCode(this Type type)
+ {
+ if (type == typeof(bool)) return TypeCode.Boolean;
+ else if (type == typeof(byte)) return TypeCode.Byte;
+ else if (type == typeof(char)) return TypeCode.Char;
+ else if (type == typeof(ushort)) return TypeCode.UInt16;
+ else if (type == typeof(uint)) return TypeCode.UInt32;
+ else if (type == typeof(ulong)) return TypeCode.UInt64;
+ else if (type == typeof(sbyte)) return TypeCode.SByte;
+ else if (type == typeof(short)) return TypeCode.Int16;
+ else if (type == typeof(int)) return TypeCode.Int32;
+ else if (type == typeof(long)) return TypeCode.Int64;
+ else if (type == typeof(string)) return TypeCode.String;
+ else if (type == typeof(float)) return TypeCode.Single;
+ else if (type == typeof(double)) return TypeCode.Double;
+ else if (type == typeof(DateTime)) return TypeCode.DateTime;
+ else if (type == (typeof(Decimal))) return TypeCode.Decimal;
+ else return TypeCode.Object;
+ }
+
+ //
+ // FieldInfo extension methods
+ //
+ public static object GetRawConstantValue(this FieldInfo fi)
+ { return fi.GetValue(null); }
+
+ //
+ // Assembly extension methods
+ //
+ public static bool ReflectionOnly(this Assembly assm)
+ {
+ // In PCL we can't load in reflection-only context
+ return false;
+ }
+
+#endif
+ }
+}
+
+// Defining some no-ops in PCL builds
+#if ES_BUILD_PCL || PROJECTN
+namespace System.Security
+{
+ class SuppressUnmanagedCodeSecurityAttribute : Attribute { }
+
+ enum SecurityAction { Demand }
+}
+namespace System.Security.Permissions
+{
+ class HostProtectionAttribute : Attribute { public bool MayLeakOnAbort { get; set; } }
+ class PermissionSetAttribute : Attribute
+ {
+ public PermissionSetAttribute(System.Security.SecurityAction action) { }
+ public bool Unrestricted { get; set; }
+ }
+}
+#endif
+
+#if PROJECTN
+namespace System
+{
+ public static class AppDomain
+ {
+ public static int GetCurrentThreadId()
+ {
+ return (int)Interop.mincore.GetCurrentThreadId();
+ }
+ }
+}
+#endif
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ArrayTypeInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ArrayTypeInfo.cs
new file mode 100644
index 0000000000..5771354f67
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ArrayTypeInfo.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ internal sealed class ArrayTypeInfo : TraceLoggingTypeInfo
+ {
+ private readonly TraceLoggingTypeInfo elementInfo;
+
+ public ArrayTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+ : base(type)
+ {
+ this.elementInfo = elementInfo;
+ }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.BeginBufferedArray();
+ this.elementInfo.WriteMetadata(collector, name, format);
+ collector.EndBufferedArray();
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ var bookmark = collector.BeginBufferedArray();
+
+ var count = 0;
+ Array array = (Array)value.ReferenceValue;
+ if (array != null)
+ {
+ count = array.Length;
+ for (int i = 0; i < array.Length; i++)
+ {
+ this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(array.GetValue(i)));
+ }
+ }
+
+ collector.EndBufferedArray(bookmark, count);
+ }
+
+ public override object GetData(object value)
+ {
+ var array = (Array)value;
+ var serializedArray = new object[array.Length];
+ for (int i = 0; i < array.Length; i++)
+ {
+ serializedArray[i] = this.elementInfo.GetData(array.GetValue(i));
+ }
+ return serializedArray;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSet.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSet.cs
new file mode 100644
index 0000000000..76c01c6c06
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSet.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Interlocked = System.Threading.Interlocked;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: A very simple lock-free add-only dictionary.
+ /// Warning: this is a copy-by-value type. Copying performs a snapshot.
+ /// Accessing a readonly field always makes a copy of the field, so the
+ /// GetOrAdd method will not work as expected if called on a readonly field.
+ /// </summary>
+ /// <typeparam name="KeyType">
+ /// The type of the key, used for TryGet.
+ /// </typeparam>
+ /// <typeparam name="ItemType">
+ /// The type of the item, used for GetOrAdd.
+ /// </typeparam>
+ internal struct ConcurrentSet<KeyType, ItemType>
+ where ItemType : ConcurrentSetItem<KeyType, ItemType>
+ {
+ private ItemType[] items;
+
+ public ItemType TryGet(KeyType key)
+ {
+ ItemType item;
+ var oldItems = this.items;
+
+ if (oldItems != null)
+ {
+ var lo = 0;
+ var hi = oldItems.Length;
+ do
+ {
+ int i = (lo + hi) / 2;
+ item = oldItems[i];
+
+ int cmp = item.Compare(key);
+ if (cmp == 0)
+ {
+ goto Done;
+ }
+ else if (cmp < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i;
+ }
+ }
+ while (lo != hi);
+ }
+
+ item = null;
+
+ Done:
+
+ return item;
+ }
+
+ public ItemType GetOrAdd(ItemType newItem)
+ {
+ ItemType item;
+ var oldItems = this.items;
+ ItemType[] newItems;
+
+ Retry:
+
+ if (oldItems == null)
+ {
+ newItems = new ItemType[] { newItem };
+ }
+ else
+ {
+ var lo = 0;
+ var hi = oldItems.Length;
+ do
+ {
+ int i = (lo + hi) / 2;
+ item = oldItems[i];
+
+ int cmp = item.Compare(newItem);
+ if (cmp == 0)
+ {
+ goto Done;
+ }
+ else if (cmp < 0)
+ {
+ lo = i + 1;
+ }
+ else
+ {
+ hi = i;
+ }
+ }
+ while (lo != hi);
+
+ int oldLength = oldItems.Length;
+ newItems = new ItemType[oldLength + 1];
+ Array.Copy(oldItems, 0, newItems, 0, lo);
+ newItems[lo] = newItem;
+ Array.Copy(oldItems, lo, newItems, lo + 1, oldLength - lo);
+ }
+
+ newItems = Interlocked.CompareExchange(ref this.items, newItems, oldItems);
+ if (oldItems != newItems)
+ {
+ oldItems = newItems;
+ goto Retry;
+ }
+
+ item = newItem;
+
+ Done:
+
+ return item;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSetItem.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSetItem.cs
new file mode 100644
index 0000000000..558dbf670b
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/ConcurrentSetItem.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Abstract base class that must be inherited by items in a
+ /// ConcurrentSet.
+ /// </summary>
+ /// <typeparam name="KeyType">Type of the set's key.</typeparam>
+ /// <typeparam name="ItemType">Type of the derived class.</typeparam>
+ internal abstract class ConcurrentSetItem<KeyType, ItemType>
+ where ItemType : ConcurrentSetItem<KeyType, ItemType>
+ {
+ public abstract int Compare(ItemType other);
+ public abstract int Compare(KeyType key);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs
new file mode 100644
index 0000000000..d0d687e8d8
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/DataCollector.cs
@@ -0,0 +1,319 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: This is the implementation of the DataCollector
+ /// functionality. To enable safe access to the DataCollector from
+ /// untrusted code, there is one thread-local instance of this structure
+ /// per thread. The instance must be Enabled before any data is written to
+ /// it. The instance must be Finished before the data is passed to
+ /// EventWrite. The instance must be Disabled before the arrays referenced
+ /// by the pointers are freed or unpinned.
+ /// </summary>
+ [SecurityCritical]
+ internal unsafe struct DataCollector
+ {
+ [ThreadStatic]
+ internal static DataCollector ThreadInstance;
+
+ private byte* scratchEnd;
+ private EventSource.EventData* datasEnd;
+ private GCHandle* pinsEnd;
+ private EventSource.EventData* datasStart;
+ private byte* scratch;
+ private EventSource.EventData* datas;
+ private GCHandle* pins;
+ private byte[] buffer;
+ private int bufferPos;
+ private int bufferNesting; // We may merge many fields int a single blob. If we are doing this we increment this.
+ private bool writingScalars;
+
+ internal void Enable(
+ byte* scratch,
+ int scratchSize,
+ EventSource.EventData* datas,
+ int dataCount,
+ GCHandle* pins,
+ int pinCount)
+ {
+ this.datasStart = datas;
+ this.scratchEnd = scratch + scratchSize;
+ this.datasEnd = datas + dataCount;
+ this.pinsEnd = pins + pinCount;
+ this.scratch = scratch;
+ this.datas = datas;
+ this.pins = pins;
+ this.writingScalars = false;
+ }
+
+ internal void Disable()
+ {
+ this = new DataCollector();
+ }
+
+ /// <summary>
+ /// Completes the list of scalars. Finish must be called before the data
+ /// descriptor array is passed to EventWrite.
+ /// </summary>
+ /// <returns>
+ /// A pointer to the next unused data descriptor, or datasEnd if they were
+ /// all used. (Descriptors may be unused if a string or array was null.)
+ /// </returns>
+ internal EventSource.EventData* Finish()
+ {
+ this.ScalarsEnd();
+ return this.datas;
+ }
+
+ internal void AddScalar(void* value, int size)
+ {
+ var pb = (byte*)value;
+ if (this.bufferNesting == 0)
+ {
+ var scratchOld = this.scratch;
+ var scratchNew = scratchOld + size;
+ if (this.scratchEnd < scratchNew)
+ {
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_AddScalarOutOfRange"));
+ }
+
+ this.ScalarsBegin();
+ this.scratch = scratchNew;
+
+ for (int i = 0; i != size; i++)
+ {
+ scratchOld[i] = pb[i];
+ }
+ }
+ else
+ {
+ var oldPos = this.bufferPos;
+ this.bufferPos = checked(this.bufferPos + size);
+ this.EnsureBuffer();
+ for (int i = 0; i != size; i++, oldPos++)
+ {
+ this.buffer[oldPos] = pb[i];
+ }
+ }
+ }
+
+ internal void AddBinary(string value, int size)
+ {
+ if (size > ushort.MaxValue)
+ {
+ size = ushort.MaxValue - 1;
+ }
+
+ if (this.bufferNesting != 0)
+ {
+ this.EnsureBuffer(size + 2);
+ }
+
+ this.AddScalar(&size, 2);
+
+ if (size != 0)
+ {
+ if (this.bufferNesting == 0)
+ {
+ this.ScalarsEnd();
+ this.PinArray(value, size);
+ }
+ else
+ {
+ var oldPos = this.bufferPos;
+ this.bufferPos = checked(this.bufferPos + size);
+ this.EnsureBuffer();
+ fixed (void* p = value)
+ {
+ Marshal.Copy((IntPtr)p, this.buffer, oldPos, size);
+ }
+ }
+ }
+ }
+
+ internal void AddBinary(Array value, int size)
+ {
+ this.AddArray(value, size, 1);
+ }
+
+ internal void AddArray(Array value, int length, int itemSize)
+ {
+ if (length > ushort.MaxValue)
+ {
+ length = ushort.MaxValue;
+ }
+
+ var size = length * itemSize;
+ if (this.bufferNesting != 0)
+ {
+ this.EnsureBuffer(size + 2);
+ }
+
+ this.AddScalar(&length, 2);
+
+ if (length != 0)
+ {
+ if (this.bufferNesting == 0)
+ {
+ this.ScalarsEnd();
+ this.PinArray(value, size);
+ }
+ else
+ {
+ var oldPos = this.bufferPos;
+ this.bufferPos = checked(this.bufferPos + size);
+ this.EnsureBuffer();
+ Buffer.BlockCopy(value, 0, this.buffer, oldPos, size);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Marks the start of a non-blittable array or enumerable.
+ /// </summary>
+ /// <returns>Bookmark to be passed to EndBufferedArray.</returns>
+ internal int BeginBufferedArray()
+ {
+ this.BeginBuffered();
+ this.bufferPos += 2; // Reserve space for the array length (filled in by EndEnumerable)
+ return this.bufferPos;
+ }
+
+ /// <summary>
+ /// Marks the end of a non-blittable array or enumerable.
+ /// </summary>
+ /// <param name="bookmark">The value returned by BeginBufferedArray.</param>
+ /// <param name="count">The number of items in the array.</param>
+ internal void EndBufferedArray(int bookmark, int count)
+ {
+ this.EnsureBuffer();
+ this.buffer[bookmark - 2] = unchecked((byte)count);
+ this.buffer[bookmark - 1] = unchecked((byte)(count >> 8));
+ this.EndBuffered();
+ }
+
+ /// <summary>
+ /// Marks the start of dynamically-buffered data.
+ /// </summary>
+ internal void BeginBuffered()
+ {
+ this.ScalarsEnd();
+ this.bufferNesting += 1;
+ }
+
+ /// <summary>
+ /// Marks the end of dynamically-buffered data.
+ /// </summary>
+ internal void EndBuffered()
+ {
+ this.bufferNesting -= 1;
+
+ if (this.bufferNesting == 0)
+ {
+ /*
+ TODO (perf): consider coalescing adjacent buffered regions into a
+ single buffer, similar to what we're already doing for adjacent
+ scalars. In addition, if a type contains a buffered region adjacent
+ to a blittable array, and the blittable array is small, it would be
+ more efficient to buffer the array instead of pinning it.
+ */
+
+ this.EnsureBuffer();
+ this.PinArray(this.buffer, this.bufferPos);
+ this.buffer = null;
+ this.bufferPos = 0;
+ }
+ }
+
+ private void EnsureBuffer()
+ {
+ var required = this.bufferPos;
+ if (this.buffer == null || this.buffer.Length < required)
+ {
+ this.GrowBuffer(required);
+ }
+ }
+
+ private void EnsureBuffer(int additionalSize)
+ {
+ var required = this.bufferPos + additionalSize;
+ if (this.buffer == null || this.buffer.Length < required)
+ {
+ this.GrowBuffer(required);
+ }
+ }
+
+ private void GrowBuffer(int required)
+ {
+ var newSize = this.buffer == null ? 64 : this.buffer.Length;
+
+ do
+ {
+ newSize *= 2;
+ }
+ while (newSize < required);
+
+ Array.Resize(ref this.buffer, newSize);
+ }
+
+ private void PinArray(object value, int size)
+ {
+ var pinsTemp = this.pins;
+ if (this.pinsEnd <= pinsTemp)
+ {
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_PinArrayOutOfRange"));
+ }
+
+ var datasTemp = this.datas;
+ if (this.datasEnd <= datasTemp)
+ {
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+ }
+
+ this.pins = pinsTemp + 1;
+ this.datas = datasTemp + 1;
+
+ *pinsTemp = GCHandle.Alloc(value, GCHandleType.Pinned);
+ datasTemp->m_Ptr = (long)(ulong)(UIntPtr)(void*)pinsTemp->AddrOfPinnedObject();
+ datasTemp->m_Size = size;
+ }
+
+ private void ScalarsBegin()
+ {
+ if (!this.writingScalars)
+ {
+ var datasTemp = this.datas;
+ if (this.datasEnd <= datasTemp)
+ {
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+ }
+
+ datasTemp->m_Ptr = (long)(ulong)(UIntPtr)this.scratch;
+ this.writingScalars = true;
+ }
+ }
+
+ private void ScalarsEnd()
+ {
+ if (this.writingScalars)
+ {
+ var datasTemp = this.datas;
+ datasTemp->m_Size = checked((int)(this.scratch - (byte*)datasTemp->m_Ptr));
+ this.datas = datasTemp + 1;
+ this.writingScalars = false;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EmptyStruct.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EmptyStruct.cs
new file mode 100644
index 0000000000..bc7fb8c346
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EmptyStruct.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Empty struct indicating no payload data.
+ /// </summary>
+ internal struct EmptyStruct
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumHelper.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumHelper.cs
new file mode 100644
index 0000000000..7a23378bb1
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumHelper.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#if EVENTSOURCE_GENERICS
+?using System;
+using System.Reflection;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Provides support for casting enums to their underlying type
+ /// from within generic context.
+ /// </summary>
+ /// <typeparam name="UnderlyingType">
+ /// The underlying type of the enum.
+ /// </typeparam>
+ internal static class EnumHelper<UnderlyingType>
+ {
+ public static UnderlyingType Cast<ValueType>(ValueType value)
+ {
+ return (UnderlyingType)(object)value;
+ }
+ }
+
+}
+#endif
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumerableTypeInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumerableTypeInfo.cs
new file mode 100644
index 0000000000..74a3fa27b2
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EnumerableTypeInfo.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ internal sealed class EnumerableTypeInfo : TraceLoggingTypeInfo
+ {
+ private readonly TraceLoggingTypeInfo elementInfo;
+
+ public EnumerableTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+ : base(type)
+ {
+ this.elementInfo = elementInfo;
+ }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.BeginBufferedArray();
+ this.elementInfo.WriteMetadata(collector, name, format);
+ collector.EndBufferedArray();
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ var bookmark = collector.BeginBufferedArray();
+
+ var count = 0;
+ IEnumerable enumerable = (IEnumerable)value.ReferenceValue;
+ if (enumerable != null)
+ {
+ foreach (var element in enumerable)
+ {
+ this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(element));
+ count++;
+ }
+ }
+
+ collector.EndBufferedArray(bookmark, count);
+ }
+
+ public override object GetData(object value)
+ {
+ var iterType = (IEnumerable)value;
+ List<object> serializedEnumerable = new List<object>();
+ foreach (var element in iterType)
+ {
+ serializedEnumerable.Add(elementInfo.GetData(element));
+ }
+ return serializedEnumerable.ToArray();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventDataAttribute.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventDataAttribute.cs
new file mode 100644
index 0000000000..cdedf13c64
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventDataAttribute.cs
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Used when authoring types that will be passed to EventSource.Write.
+ /// EventSource.Write&lt;T> only works when T is either an anonymous type
+ /// or a type with an [EventData] attribute. In addition, the properties
+ /// of T must be supported property types. Supported property types include
+ /// simple built-in types (int, string, Guid, DateTime, DateTimeOffset,
+ /// KeyValuePair, etc.), anonymous types that only contain supported types,
+ /// types with an [EventData] attribute, arrays of the above, and IEnumerable
+ /// of the above.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+ public class EventDataAttribute
+ : Attribute
+ {
+ private EventLevel level = (EventLevel)(-1);
+ private EventOpcode opcode = (EventOpcode)(-1);
+
+ /// <summary>
+ /// Gets or sets the name to use if this type is used for an
+ /// implicitly-named event or an implicitly-named property.
+ ///
+ /// Example 1:
+ ///
+ /// EventSource.Write(null, new T()); // implicitly-named event
+ ///
+ /// The name of the event will be determined as follows:
+ ///
+ /// if (T has an EventData attribute and attribute.Name != null)
+ /// eventName = attribute.Name;
+ /// else
+ /// eventName = typeof(T).Name;
+ ///
+ /// Example 2:
+ ///
+ /// EventSource.Write(name, new { _1 = new T() }); // implicitly-named field
+ ///
+ /// The name of the field will be determined as follows:
+ ///
+ /// if (T has an EventData attribute and attribute.Name != null)
+ /// fieldName = attribute.Name;
+ /// else
+ /// fieldName = typeof(T).Name;
+ /// </summary>
+ public string Name
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the level to use for the event.
+ /// Invalid levels (outside the range 0..255) are treated as unset.
+ /// Note that the Level attribute can bubble-up, i.e. if a type contains
+ /// a sub-object (a field or property), and the sub-object's type has a
+ /// TraceLoggingEvent attribute, the Level from the sub-object's attribute
+ /// can affect the event's level.
+ ///
+ /// Example: for EventSource.Write(name, options, data), the level of the
+ /// event will be determined as follows:
+ ///
+ /// if (options.Level has been set)
+ /// eventLevel = options.Level;
+ /// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Level has been set)
+ /// eventLevel = attribute.Level;
+ /// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Level has been set)
+ /// eventLevel = attribute.Level;
+ /// else
+ /// eventLevel = EventLevel.LogAlways;
+ /// </summary>
+ internal EventLevel Level
+ {
+ get { return this.level; }
+ set { this.level = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the opcode to use for the event.
+ /// Invalid opcodes (outside the range 0..255) are treated as unset.
+ /// Note that the Opcode attribute can bubble-up, i.e. if a type contains
+ /// a sub-object (a field or property), and the sub-object's type has a
+ /// TraceLoggingEvent attribute, the Opcode from the sub-object's attribute
+ /// can affect the event's opcode.
+ ///
+ /// Example: for EventSource.Write(name, options, data), the opcode of the
+ /// event will be determined as follows:
+ ///
+ /// if (options.Opcode has been set)
+ /// eventOpcode = options.Opcode;
+ /// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Opcode has been set)
+ /// eventOpcode = attribute.Opcode;
+ /// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Opcode has been set)
+ /// eventOpcode = attribute.Opcode;
+ /// else
+ /// eventOpcode = EventOpcode.Info;
+ /// </summary>
+ internal EventOpcode Opcode
+ {
+ get { return this.opcode; }
+ set { this.opcode = value; }
+ }
+
+ /// <summary>
+ /// Gets or sets the keywords to use for the event.
+ /// Note that the Keywords attribute can bubble-up, i.e. if a type contains
+ /// a sub-object (a field or property), and the sub-object's type has a
+ /// TraceLoggingEvent attribute, the Keywords from the sub-object's attribute
+ /// can affect the event's keywords.
+ ///
+ /// Example: for EventSource.Write(name, options, data), the keywords of the
+ /// event will be determined as follows:
+ ///
+ /// eventKeywords = options.Keywords;
+ /// if (data.GetType() has a TraceLoggingEvent attribute)
+ /// eventKeywords |= attribute.Keywords;
+ /// if (a field/property contained in data has a TraceLoggingEvent attribute)
+ /// eventKeywords |= attribute.Keywords;
+ /// </summary>
+ internal EventKeywords Keywords
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the flags for an event. These flags are ignored by ETW,
+ /// but can have meaning to the event consumer.
+ /// </summary>
+ internal EventTags Tags
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldAttribute.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldAttribute.cs
new file mode 100644
index 0000000000..1a298c2851
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldAttribute.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Tags are flags that are not interpreted by EventSource but are passed along
+ /// to the EventListener. The EventListener determines the semantics of the flags.
+ /// </summary>
+ [Flags]
+ public enum EventFieldTags
+ {
+ /// <summary>
+ /// No special traits are added to the field.
+ /// </summary>
+ None = 0,
+
+ /* Bits below 0x10000 are available for any use by the provider. */
+ /* Bits at or above 0x10000 are reserved for definition by Microsoft. */
+ }
+
+ /// <summary>
+ /// TraceLogging: used when authoring types that will be passed to EventSource.Write.
+ /// Controls how a field or property is handled when it is written as a
+ /// field in a TraceLogging event. Apply this attribute to a field or
+ /// property if the default handling is not correct. (Apply the
+ /// TraceLoggingIgnore attribute if the property should not be
+ /// included as a field in the event.)
+ /// The default for Name is null, which means that the name of the
+ /// underlying field or property will be used as the event field's name.
+ /// The default for PiiTag is 0, which means that the event field does not
+ /// contain personally-identifiable information.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property)]
+ public class EventFieldAttribute
+ : Attribute
+ {
+ /// <summary>
+ /// User defined options for the field. These are not interpreted by the EventSource
+ /// but are available to the Listener. See EventFieldSettings for details
+ /// </summary>
+ public EventFieldTags Tags
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets the name to use for the field. This defaults to null.
+ /// If null, the name of the corresponding property will be used
+ /// as the event field's name.
+ /// TODO REMOVE
+ /// </summary>
+ internal string Name
+ {
+ get;
+ set;
+ }
+
+ /// <summary>
+ /// Gets or sets a field formatting hint.
+ /// </summary>
+ public EventFieldFormat Format
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldFormat.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldFormat.cs
new file mode 100644
index 0000000000..fd77b07965
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventFieldFormat.cs
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Provides a hint that may be used by an event listener when formatting
+ /// an event field for display. Note that the event listener may ignore the
+ /// hint if it does not recognize a particular combination of type and format.
+ /// Similar to TDH_OUTTYPE.
+ /// </summary>
+ public enum EventFieldFormat
+ {
+ /// <summary>
+ /// Field receives default formatting based on the field's underlying type.
+ /// </summary>
+ Default = 0,
+#if false
+ /// <summary>
+ /// Field should not be displayed.
+ /// </summary>
+ NoPrint = 1,
+#endif
+ /// <summary>
+ /// Field should be formatted as character or string data.
+ /// Typically applied to 8-bit or 16-bit integers.
+ /// This is the default format for String and Char types.
+ /// </summary>
+ String = 2,
+
+ /// <summary>
+ /// Field should be formatted as boolean data. Typically applied to 8-bit
+ /// or 32-bit integers. This is the default format for the Boolean type.
+ /// </summary>
+ Boolean = 3,
+
+ /// <summary>
+ /// Field should be formatted as hexadecimal data. Typically applied to
+ /// integer types.
+ /// </summary>
+ Hexadecimal = 4,
+
+#if false
+ /// <summary>
+ /// Field should be formatted as a process identifier. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ ProcessId = 5,
+
+ /// <summary>
+ /// Field should be formatted as a thread identifier. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ ThreadId = 6,
+
+ /// <summary>
+ /// Field should be formatted as an Internet port. Typically applied to 16-bit integer
+ /// types.
+ /// </summary>
+ Port = 7,
+ /// <summary>
+ /// Field should be formatted as an Internet Protocol v4 address. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ Ipv4Address = 8,
+
+ /// <summary>
+ /// Field should be formatted as an Internet Protocol v6 address. Typically applied to
+ /// byte[] types.
+ /// </summary>
+ Ipv6Address = 9,
+ /// <summary>
+ /// Field should be formatted as a SOCKADDR. Typically applied to byte[] types.
+ /// </summary>
+ SocketAddress = 10,
+#endif
+ /// <summary>
+ /// Field should be formatted as XML string data. Typically applied to
+ /// strings or arrays of 8-bit or 16-bit integers.
+ /// </summary>
+ Xml = 11,
+
+ /// <summary>
+ /// Field should be formatted as JSON string data. Typically applied to
+ /// strings or arrays of 8-bit or 16-bit integers.
+ /// </summary>
+ Json = 12,
+#if false
+ /// <summary>
+ /// Field should be formatted as a Win32 error code. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ Win32Error = 13,
+
+ /// <summary>
+ /// Field should be formatted as an NTSTATUS code. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ NTStatus = 14,
+#endif
+ /// <summary>
+ /// Field should be formatted as an HRESULT code. Typically applied to
+ /// 32-bit integer types.
+ /// </summary>
+ HResult = 15,
+#if false
+ /// <summary>
+ /// Field should be formatted as a FILETIME. Typically applied to 64-bit
+ /// integer types. This is the default format for DateTime types.
+ /// </summary>
+ FileTime = 16,
+ /// <summary>
+ /// When applied to a numeric type, indicates that the type should be formatted
+ /// as a signed integer. This is the default format for signed integer types.
+ /// </summary>
+ Signed = 17,
+
+ /// <summary>
+ /// When applied to a numeric type, indicates that the type should be formatted
+ /// as an unsigned integer. This is the default format for unsigned integer types.
+ /// </summary>
+ Unsigned = 18,
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventIgnoreAttribute.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventIgnoreAttribute.cs
new file mode 100644
index 0000000000..769345f78e
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventIgnoreAttribute.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Used when authoring types that will be passed to EventSource.Write.
+ /// By default, EventSource.Write will write all of an object's public
+ /// properties to the event payload. Apply [EventIgnore] to a public
+ /// property to prevent EventSource.Write from including the property in
+ /// the event.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Property)]
+ public class EventIgnoreAttribute
+ : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs
new file mode 100644
index 0000000000..be97447301
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventPayload.cs
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Collections;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// EventPayload class holds the list of parameters and their corresponding values for user defined types passed to
+ /// EventSource APIs.
+ /// Preserving the order of the elements as they were found inside user defined types is the most important characteristic of this class.
+ /// </summary>
+ internal class EventPayload : IDictionary<string, object>
+ {
+ internal EventPayload(List<string> payloadNames, List<object> payloadValues)
+ {
+ Contract.Assert(payloadNames.Count == payloadValues.Count);
+
+ m_names = payloadNames;
+ m_values = payloadValues;
+ }
+
+ public ICollection<string> Keys { get { return m_names; } }
+ public ICollection<object> Values { get { return m_values; } }
+
+ public object this[string key]
+ {
+ get
+ {
+ if (key == null)
+ throw new System.ArgumentNullException("key");
+
+ int position = 0;
+ foreach(var name in m_names)
+ {
+ if (name == key)
+ {
+ return m_values[position];
+ }
+ position++;
+ }
+
+ throw new System.Collections.Generic.KeyNotFoundException();
+ }
+ set
+ {
+ throw new System.NotSupportedException();
+ }
+ }
+
+ public void Add(string key, object value)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public void Add(KeyValuePair<string, object> payloadEntry)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public void Clear()
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public bool Contains(KeyValuePair<string, object> entry)
+ {
+ return ContainsKey(entry.Key);
+ }
+
+ public bool ContainsKey(string key)
+ {
+ if (key == null)
+ throw new System.ArgumentNullException("key");
+
+ foreach (var item in m_names)
+ {
+ if (item == key)
+ return true;
+ }
+ return false;
+ }
+
+ public int Count { get { return m_names.Count; } }
+
+ public bool IsReadOnly { get { return true; } }
+
+ public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+ {
+ for (int i = 0; i < Keys.Count; i++)
+ {
+ yield return new KeyValuePair<string, object>(this.m_names[i], this.m_values[i]);
+ }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ var instance = this as IEnumerable<KeyValuePair<string, object>>;
+ return instance.GetEnumerator();
+ }
+
+ public void CopyTo(KeyValuePair<string, object>[] payloadEntries, int count)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public bool Remove(string key)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public bool Remove(KeyValuePair<string, object> entry)
+ {
+ throw new System.NotSupportedException();
+ }
+
+ public bool TryGetValue(string key, out object value)
+ {
+ if (key == null)
+ throw new System.ArgumentNullException("key");
+
+ int position = 0;
+ foreach (var name in m_names)
+ {
+ if (name == key)
+ {
+ value = m_values[position];
+ return true;
+ }
+ position++;
+ }
+
+ value = default(object);
+ return false;
+ }
+
+ #region private
+ private List<string> m_names;
+ private List<object> m_values;
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs
new file mode 100644
index 0000000000..fccfd48721
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceActivity.cs
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Provides support for EventSource activities by marking the start and
+ /// end of a particular operation.
+ /// </summary>
+ internal sealed class EventSourceActivity
+ : IDisposable
+ {
+ /// <summary>
+ /// Initializes a new instance of the EventSourceActivity class that
+ /// is attached to the specified event source. The new activity will
+ /// not be attached to any related (parent) activity.
+ /// The activity is created in the Initialized state.
+ /// </summary>
+ /// <param name="eventSource">
+ /// The event source to which the activity information is written.
+ /// </param>
+ public EventSourceActivity(EventSource eventSource)
+ {
+ if (eventSource == null)
+ throw new ArgumentNullException("eventSource");
+ Contract.EndContractBlock();
+
+ this.eventSource = eventSource;
+ }
+
+ /// <summary>
+ /// You can make an activity out of just an EventSource.
+ /// </summary>
+ public static implicit operator EventSourceActivity(EventSource eventSource) { return new EventSourceActivity(eventSource); }
+
+ /* Properties */
+ /// <summary>
+ /// Gets the event source to which this activity writes events.
+ /// </summary>
+ public EventSource EventSource
+ {
+ get { return this.eventSource; }
+ }
+
+ /// <summary>
+ /// Gets this activity's unique identifier, or the default Guid if the
+ /// event source was disabled when the activity was initialized.
+ /// </summary>
+ public Guid Id
+ {
+ get { return this.activityId; }
+ }
+
+#if false // don't expose RelatedActivityId unless there is a need.
+ /// <summary>
+ /// Gets the unique identifier of this activity's related (parent)
+ /// activity.
+ /// </summary>
+ public Guid RelatedId
+ {
+ get { return this.relatedActivityId; }
+ }
+#endif
+
+ /// <summary>
+ /// Writes a Start event with the specified name and data. If the start event is not active (because the provider
+ /// is not on or keyword-level indiates the event is off, then the returned activity is simply the 'this' poitner
+ /// and it is effectively like the Start d
+ ///
+ /// A new activityID GUID is generated and the returned
+ /// EventSourceActivity remembers this activity and will mark every event (including the start stop and any writes)
+ /// with this activityID. In addition the Start activity will log a 'relatedActivityID' that was the activity
+ /// ID before the start event. This way event processors can form a linked list of all the activities that
+ /// caused this one (directly or indirectly).
+ /// </summary>
+ /// <param name="eventName">
+ /// The name to use for the event. It is strongly suggested that this name end in 'Start' (e.g. DownloadStart).
+ /// If you do this, then the Stop() method will automatically replace the 'Start' suffix with a 'Stop' suffix.
+ /// </param>
+ /// <param name="options">Allow options (keywords, level) to be set for the write associated with this start
+ /// These will also be used for the stop event.</param>
+ /// <param name="data">The data to include in the event.</param>
+ public EventSourceActivity Start<T>(string eventName, EventSourceOptions options, T data)
+ {
+ return this.Start(eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
+ /// and level==Info) Data payload is empty.
+ /// </summary>
+ public EventSourceActivity Start(string eventName)
+ {
+ var options = new EventSourceOptions();
+ var data = new EmptyStruct();
+ return this.Start(eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data). Data payload is empty.
+ /// </summary>
+ public EventSourceActivity Start(string eventName, EventSourceOptions options)
+ {
+ var data = new EmptyStruct();
+ return this.Start(eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
+ /// and level==Info)
+ /// </summary>
+ public EventSourceActivity Start<T>(string eventName, T data)
+ {
+ var options = new EventSourceOptions();
+ return this.Start(eventName, ref options, ref data);
+ }
+
+ /// <summary>
+ /// Writes a Stop event with the specified data, and sets the activity
+ /// to the Stopped state. The name is determined by the eventName used in Start.
+ /// If that Start event name is suffixed with 'Start' that is removed, and regardless
+ /// 'Stop' is appended to the result to form the Stop event name.
+ /// May only be called when the activity is in the Started state.
+ /// </summary>
+ /// <param name="data">The data to include in the event.</param>
+ public void Stop<T>(T data)
+ {
+ this.Stop(null, ref data);
+ }
+ /// <summary>
+ /// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
+ /// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
+ /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
+ /// </summary>
+ public void Stop<T>(string eventName)
+ {
+ var data = new EmptyStruct();
+ this.Stop(eventName, ref data);
+ }
+ /// <summary>
+ /// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
+ /// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
+ /// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
+ /// </summary>
+ public void Stop<T>(string eventName, T data)
+ {
+ this.Stop(eventName, ref data);
+ }
+
+ /// <summary>
+ /// Writes an event associated with this activity to the eventSource associted with this activity.
+ /// May only be called when the activity is in the Started state.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name to use for the event. If null, the name is determined from
+ /// data's type.
+ /// </param>
+ /// <param name="options">
+ /// The options to use for the event.
+ /// </param>
+ /// <param name="data">The data to include in the event.</param>
+ public void Write<T>(string eventName, EventSourceOptions options, T data)
+ {
+ this.Write(this.eventSource, eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Writes an event associated with this activity.
+ /// May only be called when the activity is in the Started state.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name to use for the event. If null, the name is determined from
+ /// data's type.
+ /// </param>
+ /// <param name="data">The data to include in the event.</param>
+ public void Write<T>(string eventName, T data)
+ {
+ var options = new EventSourceOptions();
+ this.Write(this.eventSource, eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Writes a trivial event associated with this activity.
+ /// May only be called when the activity is in the Started state.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name to use for the event. Must not be null.
+ /// </param>
+ /// <param name="options">
+ /// The options to use for the event.
+ /// </param>
+ public void Write(string eventName, EventSourceOptions options)
+ {
+ var data = new EmptyStruct();
+ this.Write(this.eventSource, eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Writes a trivial event associated with this activity.
+ /// May only be called when the activity is in the Started state.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name to use for the event. Must not be null.
+ /// </param>
+ public void Write(string eventName)
+ {
+ var options = new EventSourceOptions();
+ var data = new EmptyStruct();
+ this.Write(this.eventSource, eventName, ref options, ref data);
+ }
+ /// <summary>
+ /// Writes an event to a arbitrary eventSource stamped with the activity ID of this activity.
+ /// </summary>
+ public void Write<T>(EventSource source, string eventName, EventSourceOptions options, T data)
+ {
+ this.Write(source, eventName, ref options, ref data);
+ }
+
+ /// <summary>
+ /// Releases any unmanaged resources associated with this object.
+ /// If the activity is in the Started state, calls Stop().
+ /// </summary>
+ public void Dispose()
+ {
+ if (this.state == State.Started)
+ {
+ var data = new EmptyStruct();
+ this.Stop(null, ref data);
+ }
+ }
+
+ #region private
+ private EventSourceActivity Start<T>(string eventName, ref EventSourceOptions options, ref T data)
+ {
+ if (this.state != State.Started)
+ throw new InvalidOperationException();
+
+ // If the source is not on at all, then we don't need to do anything and we can simply return ourselves.
+ if (!this.eventSource.IsEnabled())
+ return this;
+
+ var newActivity = new EventSourceActivity(eventSource);
+ if (!this.eventSource.IsEnabled(options.Level, options.Keywords))
+ {
+ // newActivity.relatedActivityId = this.Id;
+ Guid relatedActivityId = this.Id;
+ newActivity.activityId = Guid.NewGuid();
+ newActivity.startStopOptions = options;
+ newActivity.eventName = eventName;
+ newActivity.startStopOptions.Opcode = EventOpcode.Start;
+ this.eventSource.Write(eventName, ref newActivity.startStopOptions, ref newActivity.activityId, ref relatedActivityId, ref data);
+ }
+ else
+ {
+ // If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.
+ newActivity.activityId = this.Id;
+ }
+
+ return newActivity;
+ }
+
+ private void Write<T>(EventSource eventSource, string eventName, ref EventSourceOptions options, ref T data)
+ {
+ if (this.state != State.Started)
+ throw new InvalidOperationException(); // Write after stop.
+ if (eventName == null)
+ throw new ArgumentNullException();
+
+ eventSource.Write(eventName, ref options, ref this.activityId, ref s_empty, ref data);
+ }
+
+ private void Stop<T>(string eventName, ref T data)
+ {
+ if (this.state != State.Started)
+ throw new InvalidOperationException();
+
+ // If start was not fired, then stop isn't as well.
+ if (!StartEventWasFired)
+ return;
+
+ this.state = State.Stopped;
+ if (eventName == null)
+ {
+ eventName = this.eventName;
+ if (eventName.EndsWith("Start"))
+ eventName = eventName.Substring(0, eventName.Length - 5);
+ eventName = eventName + "Stop";
+ }
+ this.startStopOptions.Opcode = EventOpcode.Stop;
+ this.eventSource.Write(eventName, ref this.startStopOptions, ref this.activityId, ref s_empty, ref data);
+ }
+
+ private enum State
+ {
+ Started,
+ Stopped
+ }
+
+ /// <summary>
+ /// If eventName is non-null then we logged a start event
+ /// </summary>
+ private bool StartEventWasFired { get { return eventName != null; } }
+
+ private readonly EventSource eventSource;
+ private EventSourceOptions startStopOptions;
+ internal Guid activityId;
+ // internal Guid relatedActivityId;
+ private State state;
+ private string eventName;
+
+ static internal Guid s_empty;
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceOptions.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceOptions.cs
new file mode 100644
index 0000000000..26305a5708
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/EventSourceOptions.cs
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Used when calling EventSource.Write.
+ /// Optional overrides for event settings such as Level, Keywords, or Opcode.
+ /// If overrides are not provided for a setting, default values will be used.
+ /// </summary>
+ public struct EventSourceOptions
+ {
+ internal EventKeywords keywords;
+ internal EventTags tags;
+ internal EventActivityOptions activityOptions;
+ internal byte level;
+ internal byte opcode;
+ internal byte valuesSet;
+
+ internal const byte keywordsSet = 0x1;
+ internal const byte tagsSet = 0x2;
+ internal const byte levelSet = 0x4;
+ internal const byte opcodeSet = 0x8;
+ internal const byte activityOptionsSet = 0x10;
+
+ /// <summary>
+ /// Gets or sets the level to use for the specified event. If this property
+ /// is unset, the event's level will be 5 (Verbose).
+ /// </summary>
+ public EventLevel Level
+ {
+ get
+ {
+ return (EventLevel)this.level;
+ }
+
+ set
+ {
+ this.level = checked((byte)value);
+ this.valuesSet |= levelSet;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the opcode to use for the specified event. If this property
+ /// is unset, the event's opcode will 0 (Info).
+ /// </summary>
+ public EventOpcode Opcode
+ {
+ get
+ {
+ return (EventOpcode)this.opcode;
+ }
+
+ set
+ {
+ this.opcode = checked((byte)value);
+ this.valuesSet |= opcodeSet;
+ }
+ }
+
+ internal bool IsOpcodeSet
+ {
+ get
+ {
+ return (this.valuesSet & opcodeSet) != 0;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the keywords to use for the specified event. If this
+ /// property is unset, the event's keywords will be 0.
+ /// </summary>
+ public EventKeywords Keywords
+ {
+ get
+ {
+ return this.keywords;
+ }
+
+ set
+ {
+ this.keywords = value;
+ this.valuesSet |= keywordsSet;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the tags to use for the specified event. If this property is
+ /// unset, the event's tags will be 0.
+ /// </summary>
+ public EventTags Tags
+ {
+ get
+ {
+ return this.tags;
+ }
+
+ set
+ {
+ this.tags = value;
+ this.valuesSet |= tagsSet;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the activity options for this specified events. If this property is
+ /// unset, the event's activity options will be 0.
+ /// </summary>
+ public EventActivityOptions ActivityOptions
+ {
+ get
+ {
+ return this.activityOptions;
+ }
+ set
+ {
+ this.activityOptions = value;
+ this.valuesSet |= activityOptionsSet;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs
new file mode 100644
index 0000000000..45673f7ab5
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/FieldMetadata.cs
@@ -0,0 +1,231 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Encoding = System.Text.Encoding;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Contains the information needed to generate tracelogging
+ /// metadata for an event field.
+ /// </summary>
+ internal class FieldMetadata
+ {
+ /// <summary>
+ /// Name of the field
+ /// </summary>
+ private readonly string name;
+
+ /// <summary>
+ /// The number of bytes in the UTF8 Encoding of 'name' INCLUDING a null terminator.
+ /// </summary>
+ private readonly int nameSize;
+ private readonly EventFieldTags tags;
+ private readonly byte[] custom;
+
+ /// <summary>
+ /// ETW supports fixed sized arrays. If inType has the InTypeFixedCountFlag then this is the
+ /// statically known count for the array. It is also used to encode the number of bytes of
+ /// custom meta-data if InTypeCustomCountFlag set.
+ /// </summary>
+ private readonly ushort fixedCount;
+
+ private byte inType;
+ private byte outType;
+
+ /// <summary>
+ /// Scalar or variable-length array.
+ /// </summary>
+ public FieldMetadata(
+ string name,
+ TraceLoggingDataType type,
+ EventFieldTags tags,
+ bool variableCount)
+ : this(
+ name,
+ type,
+ tags,
+ variableCount ? Statics.InTypeVariableCountFlag : (byte)0,
+ 0,
+ null)
+ {
+ return;
+ }
+
+ /// <summary>
+ /// Fixed-length array.
+ /// </summary>
+ public FieldMetadata(
+ string name,
+ TraceLoggingDataType type,
+ EventFieldTags tags,
+ ushort fixedCount)
+ : this(
+ name,
+ type,
+ tags,
+ Statics.InTypeFixedCountFlag,
+ fixedCount,
+ null)
+ {
+ return;
+ }
+
+ /// <summary>
+ /// Custom serializer
+ /// </summary>
+ public FieldMetadata(
+ string name,
+ TraceLoggingDataType type,
+ EventFieldTags tags,
+ byte[] custom)
+ : this(
+ name,
+ type,
+ tags,
+ Statics.InTypeCustomCountFlag,
+ checked((ushort)(custom == null ? 0 : custom.Length)),
+ custom)
+ {
+ return;
+ }
+
+ private FieldMetadata(
+ string name,
+ TraceLoggingDataType dataType,
+ EventFieldTags tags,
+ byte countFlags,
+ ushort fixedCount = 0,
+ byte[] custom = null)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException(
+ "name",
+ "This usually means that the object passed to Write is of a type that"
+ + " does not support being used as the top-level object in an event,"
+ + " e.g. a primitive or built-in type.");
+ }
+
+ Statics.CheckName(name);
+ var coreType = (int)dataType & Statics.InTypeMask;
+ this.name = name;
+ this.nameSize = Encoding.UTF8.GetByteCount(this.name) + 1;
+ this.inType = (byte)(coreType | countFlags);
+ this.outType = (byte)(((int)dataType >> 8) & Statics.OutTypeMask);
+ this.tags = tags;
+ this.fixedCount = fixedCount;
+ this.custom = custom;
+
+ if (countFlags != 0)
+ {
+ if (coreType == (int)TraceLoggingDataType.Nil)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNil"));
+ }
+ if (coreType == (int)TraceLoggingDataType.Binary)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
+ }
+#if !BROKEN_UNTIL_M3
+ if (coreType == (int)TraceLoggingDataType.Utf16String ||
+ coreType == (int)TraceLoggingDataType.MbcsString)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
+ }
+#endif
+ }
+
+ if (((int)this.tags & 0xfffffff) != 0)
+ {
+ this.outType |= Statics.OutTypeChainFlag;
+ }
+
+ if (this.outType != 0)
+ {
+ this.inType |= Statics.InTypeChainFlag;
+ }
+ }
+
+ public void IncrementStructFieldCount()
+ {
+ this.inType |= Statics.InTypeChainFlag;
+ this.outType++;
+ if ((this.outType & Statics.OutTypeMask) == 0)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_TooManyFields"));
+ }
+ }
+
+ /// <summary>
+ /// This is the main routine for FieldMetaData. Basically it will serialize the data in
+ /// this structure as TraceLogging style meta-data into the array 'metaArray' starting at
+ /// 'pos' (pos is updated to reflect the bytes written).
+ ///
+ /// Note that 'metaData' can be null, in which case it only updates 'pos'. This is useful
+ /// for a 'two pass' approach where you figure out how big to make the array, and then you
+ /// fill it in.
+ /// </summary>
+ public void Encode(ref int pos, byte[] metadata)
+ {
+ // Write out the null terminated UTF8 encoded name
+ if (metadata != null)
+ {
+ Encoding.UTF8.GetBytes(this.name, 0, this.name.Length, metadata, pos);
+ }
+ pos += this.nameSize;
+
+ // Write 1 byte for inType
+ if (metadata != null)
+ {
+ metadata[pos] = this.inType;
+ }
+ pos += 1;
+
+ // If InTypeChainFlag set, then write out the outType
+ if (0 != (this.inType & Statics.InTypeChainFlag))
+ {
+ if (metadata != null)
+ {
+ metadata[pos] = this.outType;
+ }
+ pos += 1;
+
+ // If OutTypeChainFlag set, then write out tags
+ if (0 != (this.outType & Statics.OutTypeChainFlag))
+ {
+ Statics.EncodeTags((int)this.tags, ref pos, metadata);
+ }
+ }
+
+ // If InTypeFixedCountFlag set, write out the fixedCount (2 bytes little endian)
+ if (0 != (this.inType & Statics.InTypeFixedCountFlag))
+ {
+ if (metadata != null)
+ {
+ metadata[pos + 0] = unchecked((byte)this.fixedCount);
+ metadata[pos + 1] = (byte)(this.fixedCount >> 8);
+ }
+ pos += 2;
+
+ // If InTypeCustomCountFlag set, write out the blob of custom meta-data.
+ if (Statics.InTypeCustomCountFlag == (this.inType & Statics.InTypeCountMask) &&
+ this.fixedCount != 0)
+ {
+ if (metadata != null)
+ {
+ Buffer.BlockCopy(this.custom, 0, metadata, pos, this.fixedCount);
+ }
+ pos += this.fixedCount;
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/InvokeTypeInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/InvokeTypeInfo.cs
new file mode 100644
index 0000000000..3e5997bc9b
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/InvokeTypeInfo.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: An implementation of TraceLoggingTypeInfo that works
+ /// for arbitrary types. It writes all public instance properties of
+ /// the type.
+ /// </summary>
+ /// <typeparam name="ContainerType">
+ /// Type from which to read values.
+ /// </typeparam>
+ internal sealed class InvokeTypeInfo : TraceLoggingTypeInfo
+ {
+ private readonly PropertyAnalysis[] properties;
+
+ public InvokeTypeInfo(
+ Type type,
+ TypeAnalysis typeAnalysis)
+ : base(
+ type,
+ typeAnalysis.name,
+ typeAnalysis.level,
+ typeAnalysis.opcode,
+ typeAnalysis.keywords,
+ typeAnalysis.tags)
+ {
+ if (typeAnalysis.properties.Length != 0)
+ this.properties = typeAnalysis.properties;
+ }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ var groupCollector = collector.AddGroup(name);
+ if (this.properties != null)
+ {
+ foreach (var property in this.properties)
+ {
+ var propertyFormat = EventFieldFormat.Default;
+ var propertyAttribute = property.fieldAttribute;
+ if (propertyAttribute != null)
+ {
+ groupCollector.Tags = propertyAttribute.Tags;
+ propertyFormat = propertyAttribute.Format;
+ }
+
+ property.typeInfo.WriteMetadata(
+ groupCollector,
+ property.name,
+ propertyFormat);
+ }
+ }
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ if (this.properties != null)
+ {
+ foreach (var property in this.properties)
+ {
+ property.typeInfo.WriteData(collector, property.getter(value));
+ }
+ }
+ }
+
+ public override object GetData(object value)
+ {
+ if (this.properties != null)
+ {
+ var membersNames = new List<string>();
+ var memebersValues = new List<object>();
+ for (int i = 0; i < this.properties.Length; i++)
+ {
+ var propertyValue = properties[i].propertyInfo.GetValue(value);
+ membersNames.Add(properties[i].name);
+ memebersValues.Add(properties[i].typeInfo.GetData(propertyValue));
+ }
+ return new EventPayload(membersNames, memebersValues);
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/NameInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/NameInfo.cs
new file mode 100644
index 0000000000..668043ae68
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/NameInfo.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Interlocked = System.Threading.Interlocked;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Stores the metadata and event identifier corresponding
+ /// to a tracelogging event type+name+tags combination.
+ /// </summary>
+ internal sealed class NameInfo
+ : ConcurrentSetItem<KeyValuePair<string, EventTags>, NameInfo>
+ {
+ /// <summary>
+ /// Insure that eventIds strictly less than 'eventId' will not be
+ /// used by the SelfDescribing events.
+ /// </summary>
+ internal static void ReserveEventIDsBelow(int eventId)
+ {
+ for(;;)
+ {
+ int snapshot = lastIdentity;
+ int newIdentity = (lastIdentity & ~0xFFFFFF) + eventId;
+ newIdentity = Math.Max(newIdentity, snapshot); // Should be redundant. as we only create descriptors once.
+ if (Interlocked.CompareExchange(ref lastIdentity, newIdentity, snapshot) == snapshot)
+ break;
+ }
+ }
+
+ private static int lastIdentity = Statics.TraceLoggingChannel << 24;
+ internal readonly string name;
+ internal readonly EventTags tags;
+ internal readonly int identity;
+ internal readonly byte[] nameMetadata;
+
+ public NameInfo(string name, EventTags tags, int typeMetadataSize)
+ {
+ this.name = name;
+ this.tags = tags & Statics.EventTagsMask;
+ this.identity = Interlocked.Increment(ref lastIdentity);
+
+ int tagsPos = 0;
+ Statics.EncodeTags((int)this.tags, ref tagsPos, null);
+
+ this.nameMetadata = Statics.MetadataForString(name, tagsPos, 0, typeMetadataSize);
+
+ tagsPos = 2;
+ Statics.EncodeTags((int)this.tags, ref tagsPos, this.nameMetadata);
+ }
+
+ public override int Compare(NameInfo other)
+ {
+ return this.Compare(other.name, other.tags);
+ }
+
+ public override int Compare(KeyValuePair<string, EventTags> key)
+ {
+ return this.Compare(key.Key, key.Value & Statics.EventTagsMask);
+ }
+
+ private int Compare(string otherName, EventTags otherTags)
+ {
+ int result = StringComparer.Ordinal.Compare(this.name, otherName);
+ if (result == 0 && this.tags != otherTags)
+ {
+ result = this.tags < otherTags ? -1 : 1;
+ }
+ return result;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAnalysis.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAnalysis.cs
new file mode 100644
index 0000000000..1f07539b52
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyAnalysis.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Reflection;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: stores the per-property information obtained by
+ /// reflecting over a type.
+ /// </summary>
+ internal sealed class PropertyAnalysis
+ {
+ internal readonly string name;
+ internal readonly PropertyInfo propertyInfo;
+ internal readonly Func<PropertyValue, PropertyValue> getter;
+ internal readonly TraceLoggingTypeInfo typeInfo;
+ internal readonly EventFieldAttribute fieldAttribute;
+
+ public PropertyAnalysis(
+ string name,
+ PropertyInfo propertyInfo,
+ TraceLoggingTypeInfo typeInfo,
+ EventFieldAttribute fieldAttribute)
+ {
+ this.name = name;
+ this.propertyInfo = propertyInfo;
+ this.getter = PropertyValue.GetPropertyGetter(propertyInfo);
+ this.typeInfo = typeInfo;
+ this.fieldAttribute = fieldAttribute;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs
new file mode 100644
index 0000000000..0f34d95648
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/PropertyValue.cs
@@ -0,0 +1,251 @@
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+namespace System.Diagnostics.Tracing
+{
+ /// <summary>
+ /// Holds property values of any type. For common value types, we have inline storage so that we don't need
+ /// to box the values. For all other types, we store the value in a single object reference field.
+ ///
+ /// To get the value of a property quickly, use a delegate produced by <see cref="PropertyValue.GetPropertyGetter(PropertyInfo)"/>.
+ /// </summary>
+ internal unsafe struct PropertyValue
+ {
+ /// <summary>
+ /// Union of well-known value types, to avoid boxing those types.
+ /// </summary>
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Scalar
+ {
+ [FieldOffset(0)]
+ public Boolean AsBoolean;
+ [FieldOffset(0)]
+ public Byte AsByte;
+ [FieldOffset(0)]
+ public SByte AsSByte;
+ [FieldOffset(0)]
+ public Char AsChar;
+ [FieldOffset(0)]
+ public Int16 AsInt16;
+ [FieldOffset(0)]
+ public UInt16 AsUInt16;
+ [FieldOffset(0)]
+ public Int32 AsInt32;
+ [FieldOffset(0)]
+ public UInt32 AsUInt32;
+ [FieldOffset(0)]
+ public Int64 AsInt64;
+ [FieldOffset(0)]
+ public UInt64 AsUInt64;
+ [FieldOffset(0)]
+ public IntPtr AsIntPtr;
+ [FieldOffset(0)]
+ public UIntPtr AsUIntPtr;
+ [FieldOffset(0)]
+ public Single AsSingle;
+ [FieldOffset(0)]
+ public Double AsDouble;
+ [FieldOffset(0)]
+ public Guid AsGuid;
+ [FieldOffset(0)]
+ public DateTime AsDateTime;
+ [FieldOffset(0)]
+ public DateTimeOffset AsDateTimeOffset;
+ [FieldOffset(0)]
+ public TimeSpan AsTimeSpan;
+ [FieldOffset(0)]
+ public Decimal AsDecimal;
+ }
+
+ // Anything not covered by the Scalar union gets stored in this reference.
+ readonly object _reference;
+ readonly Scalar _scalar;
+ readonly int _scalarLength;
+
+ private PropertyValue(object value)
+ {
+ _reference = value;
+ _scalar = default(Scalar);
+ _scalarLength = 0;
+ }
+
+ private PropertyValue(Scalar scalar, int scalarLength)
+ {
+ _reference = null;
+ _scalar = scalar;
+ _scalarLength = scalarLength;
+ }
+
+ private PropertyValue(Boolean value) : this(new Scalar() { AsBoolean = value }, sizeof(Boolean)) { }
+ private PropertyValue(Byte value) : this(new Scalar() { AsByte = value }, sizeof(Byte)) { }
+ private PropertyValue(SByte value) : this(new Scalar() { AsSByte = value }, sizeof(SByte)) { }
+ private PropertyValue(Char value) : this(new Scalar() { AsChar = value }, sizeof(Char)) { }
+ private PropertyValue(Int16 value) : this(new Scalar() { AsInt16 = value }, sizeof(Int16)) { }
+ private PropertyValue(UInt16 value) : this(new Scalar() { AsUInt16 = value }, sizeof(UInt16)) { }
+ private PropertyValue(Int32 value) : this(new Scalar() { AsInt32 = value }, sizeof(Int32)) { }
+ private PropertyValue(UInt32 value) : this(new Scalar() { AsUInt32 = value }, sizeof(UInt32)) { }
+ private PropertyValue(Int64 value) : this(new Scalar() { AsInt64 = value }, sizeof(Int64)) { }
+ private PropertyValue(UInt64 value) : this(new Scalar() { AsUInt64 = value }, sizeof(UInt64)) { }
+ private PropertyValue(IntPtr value) : this(new Scalar() { AsIntPtr = value }, sizeof(IntPtr)) { }
+ private PropertyValue(UIntPtr value) : this(new Scalar() { AsUIntPtr = value }, sizeof(UIntPtr)) { }
+ private PropertyValue(Single value) : this(new Scalar() { AsSingle = value }, sizeof(Single)) { }
+ private PropertyValue(Double value) : this(new Scalar() { AsDouble = value }, sizeof(Double)) { }
+ private PropertyValue(Guid value) : this(new Scalar() { AsGuid = value }, sizeof(Guid)) { }
+ private PropertyValue(DateTime value) : this(new Scalar() { AsDateTime = value }, sizeof(DateTime)) { }
+ private PropertyValue(DateTimeOffset value) : this(new Scalar() { AsDateTimeOffset = value }, sizeof(DateTimeOffset)) { }
+ private PropertyValue(TimeSpan value) : this(new Scalar() { AsTimeSpan = value }, sizeof(TimeSpan)) { }
+ private PropertyValue(Decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(Decimal)) { }
+
+ public static Func<object, PropertyValue> GetFactory(Type type)
+ {
+ if (type == typeof(Boolean)) return value => new PropertyValue((Boolean)value);
+ if (type == typeof(Byte)) return value => new PropertyValue((Byte)value);
+ if (type == typeof(SByte)) return value => new PropertyValue((SByte)value);
+ if (type == typeof(Char)) return value => new PropertyValue((Char)value);
+ if (type == typeof(Int16)) return value => new PropertyValue((Int16)value);
+ if (type == typeof(UInt16)) return value => new PropertyValue((UInt16)value);
+ if (type == typeof(Int32)) return value => new PropertyValue((Int32)value);
+ if (type == typeof(UInt32)) return value => new PropertyValue((UInt32)value);
+ if (type == typeof(Int64)) return value => new PropertyValue((Int64)value);
+ if (type == typeof(UInt64)) return value => new PropertyValue((UInt64)value);
+ if (type == typeof(IntPtr)) return value => new PropertyValue((IntPtr)value);
+ if (type == typeof(UIntPtr)) return value => new PropertyValue((UIntPtr)value);
+ if (type == typeof(Single)) return value => new PropertyValue((Single)value);
+ if (type == typeof(Double)) return value => new PropertyValue((Double)value);
+ if (type == typeof(Guid)) return value => new PropertyValue((Guid)value);
+ if (type == typeof(DateTime)) return value => new PropertyValue((DateTime)value);
+ if (type == typeof(DateTimeOffset)) return value => new PropertyValue((DateTimeOffset)value);
+ if (type == typeof(TimeSpan)) return value => new PropertyValue((TimeSpan)value);
+ if (type == typeof(Decimal)) return value => new PropertyValue((Decimal)value);
+
+ return value => new PropertyValue(value);
+ }
+
+
+ public object ReferenceValue
+ {
+ get
+ {
+ Contract.Assert(_scalarLength == 0, "This ReflectedValue refers to an unboxed value type, not a reference type or boxed value type.");
+ return _reference;
+ }
+ }
+
+ public Scalar ScalarValue
+ {
+ get
+ {
+ Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+ return _scalar;
+ }
+ }
+
+ public int ScalarLength
+ {
+ get
+ {
+ Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+ return _scalarLength;
+ }
+ }
+
+ /// <summary>
+ /// Gets a delegate that gets the value of a given property.
+ /// </summary>
+ public static Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+ {
+ if (property.DeclaringType.GetTypeInfo().IsValueType)
+ return GetBoxedValueTypePropertyGetter(property);
+ else
+ return GetReferenceTypePropertyGetter(property);
+ }
+
+ /// <summary>
+ /// Gets a delegate that gets the value of a property of a value type. We unfortunately cannot avoid boxing the value type,
+ /// without making this generic over the value type. That would result in a large number of generic instantiations, and furthermore
+ /// does not work correctly on .Net Native (we cannot express the needed instantiations in an rd.xml file). We expect that user-defined
+ /// value types will be rare, and in any case the boxing only happens for events that are actually enabled.
+ /// </summary>
+ private static Func<PropertyValue, PropertyValue> GetBoxedValueTypePropertyGetter(PropertyInfo property)
+ {
+ var type = property.PropertyType;
+
+ if (type.GetTypeInfo().IsEnum)
+ type = Enum.GetUnderlyingType(type);
+
+ var factory = GetFactory(type);
+
+ return container => factory(property.GetValue(container.ReferenceValue));
+ }
+
+ /// <summary>
+ /// For properties of reference types, we use a generic helper class to get the value. This enables us to use MethodInfo.CreateDelegate
+ /// to build a fast getter. We can get away with this on .Net Native, because we really only need one runtime instantiation of the
+ /// generic type, since it's only instantiated over reference types (and thus all instances are shared).
+ /// </summary>
+ /// <param name="property"></param>
+ /// <returns></returns>
+ private static Func<PropertyValue, PropertyValue> GetReferenceTypePropertyGetter(PropertyInfo property)
+ {
+ var helper = (TypeHelper)Activator.CreateInstance(typeof(ReferenceTypeHelper<>).MakeGenericType(property.DeclaringType));
+ return helper.GetPropertyGetter(property);
+ }
+
+ private abstract class TypeHelper
+ {
+ public abstract Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property);
+
+ protected Delegate GetGetMethod(PropertyInfo property, Type propertyType)
+ {
+ return property.GetMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(property.DeclaringType, propertyType));
+ }
+ }
+
+ private sealed class ReferenceTypeHelper<TContainer> : TypeHelper where TContainer : class
+ {
+ public override Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+ {
+ var type = property.PropertyType;
+
+ if (!Statics.IsValueType(type))
+ {
+ var getter = (Func<TContainer, object>)GetGetMethod(property, type);
+ return container => new PropertyValue(getter((TContainer)container.ReferenceValue));
+ }
+ else
+ {
+ if (type.GetTypeInfo().IsEnum)
+ type = Enum.GetUnderlyingType(type);
+
+ if (type == typeof(Boolean)) { var f = (Func<TContainer, Boolean>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Byte)) { var f = (Func<TContainer, Byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(SByte)) { var f = (Func<TContainer, SByte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Char)) { var f = (Func<TContainer, Char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int16)) { var f = (Func<TContainer, Int16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt16)) { var f = (Func<TContainer, UInt16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int32)) { var f = (Func<TContainer, Int32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt32)) { var f = (Func<TContainer, UInt32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int64)) { var f = (Func<TContainer, Int64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt64)) { var f = (Func<TContainer, UInt64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Single)) { var f = (Func<TContainer, Single>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Double)) { var f = (Func<TContainer, Double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Decimal)) { var f = (Func<TContainer, Decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+
+ return container => new PropertyValue(property.GetValue(container.ReferenceValue));
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleEventTypes.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleEventTypes.cs
new file mode 100644
index 0000000000..cdced968f0
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleEventTypes.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using Interlocked = System.Threading.Interlocked;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Contains the metadata needed to emit an event, optimized
+ /// for events with one top-level compile-time-typed payload object.
+ /// </summary>
+ /// <typeparam name="T">
+ /// Type of the top-level payload object. Should be EmptyStruct if the
+ /// event has no payload.
+ /// </typeparam>
+ internal static class SimpleEventTypes<T>
+ {
+ private static TraceLoggingEventTypes instance;
+
+ public static TraceLoggingEventTypes Instance
+ {
+ get { return instance ?? InitInstance(); }
+ }
+
+ private static TraceLoggingEventTypes InitInstance()
+ {
+ var info = TraceLoggingTypeInfo.GetInstance(typeof(T), null);
+ var newInstance = new TraceLoggingEventTypes(info.Name, info.Tags, new TraceLoggingTypeInfo[] { info });
+ Interlocked.CompareExchange(ref instance, newInstance, null);
+ return instance;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs
new file mode 100644
index 0000000000..e51aff0380
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/SimpleTypeInfos.cs
@@ -0,0 +1,296 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Type handler for empty or unsupported types.
+ /// </summary>
+ internal sealed class NullTypeInfo : TraceLoggingTypeInfo
+ {
+ public NullTypeInfo() : base(typeof(EmptyStruct)) { }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.AddGroup(name);
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ return;
+ }
+
+ public override object GetData(object value)
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Type handler for simple scalar types.
+ /// </summary>
+ sealed class ScalarTypeInfo : TraceLoggingTypeInfo
+ {
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+ TraceLoggingDataType nativeFormat;
+
+ private ScalarTypeInfo(
+ Type type,
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+ TraceLoggingDataType nativeFormat)
+ : base(type)
+ {
+ this.formatFunc = formatFunc;
+ this.nativeFormat = nativeFormat;
+ }
+
+ public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
+ {
+ collector.AddScalar(name, formatFunc(format, nativeFormat));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ collector.AddScalar(value);
+ }
+
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(Boolean), Statics.Format8, TraceLoggingDataType.Boolean8); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(Byte), Statics.Format8, TraceLoggingDataType.UInt8); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(SByte), Statics.Format8, TraceLoggingDataType.Int8); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(Char), Statics.Format16, TraceLoggingDataType.Char16); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(Int16), Statics.Format16, TraceLoggingDataType.Int16); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(UInt16), Statics.Format16, TraceLoggingDataType.UInt16); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(Int32), Statics.Format32, TraceLoggingDataType.Int32); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(UInt32), Statics.Format32, TraceLoggingDataType.UInt32); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(Int64), Statics.Format64, TraceLoggingDataType.Int64); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(UInt64), Statics.Format64, TraceLoggingDataType.UInt64); }
+ public static TraceLoggingTypeInfo IntPtr() { return new ScalarTypeInfo(typeof(IntPtr), Statics.FormatPtr, Statics.IntPtrType); }
+ public static TraceLoggingTypeInfo UIntPtr() { return new ScalarTypeInfo(typeof(UIntPtr), Statics.FormatPtr, Statics.UIntPtrType); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(Single), Statics.Format32, TraceLoggingDataType.Float); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(Double), Statics.Format64, TraceLoggingDataType.Double); }
+ public static TraceLoggingTypeInfo Guid() { return new ScalarTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid); }
+ }
+
+
+ /// <summary>
+ /// Type handler for arrays of scalars
+ /// </summary>
+ internal sealed class ScalarArrayTypeInfo : TraceLoggingTypeInfo
+ {
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+ TraceLoggingDataType nativeFormat;
+ int elementSize;
+
+ private ScalarArrayTypeInfo(
+ Type type,
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+ TraceLoggingDataType nativeFormat,
+ int elementSize)
+ : base(type)
+ {
+ this.formatFunc = formatFunc;
+ this.nativeFormat = nativeFormat;
+ this.elementSize = elementSize;
+ }
+
+ public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
+ {
+ collector.AddArray(name, formatFunc(format, nativeFormat));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ collector.AddArray(value, elementSize);
+ }
+
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(Boolean[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(Boolean)); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(Byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(Byte)); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(SByte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(SByte)); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(Char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(Char)); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(Int16[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(Int16)); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(UInt16[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(UInt16)); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(Int32[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(Int32)); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(UInt32[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(UInt32)); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(Int64[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(Int64)); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(UInt64[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(UInt64)); }
+ public static TraceLoggingTypeInfo IntPtr() { return new ScalarArrayTypeInfo(typeof(IntPtr[]), Statics.FormatPtr, Statics.IntPtrType, System.IntPtr.Size); }
+ public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
+ public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for String.
+ /// </summary>
+ internal sealed class StringTypeInfo : TraceLoggingTypeInfo
+ {
+ public StringTypeInfo() : base(typeof(string)) { }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.CountedUtf16String, format));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ collector.AddBinary((string)value.ReferenceValue);
+ }
+
+ public override object GetData(object value)
+ {
+ if(value == null)
+ {
+ return "";
+ }
+
+ return value;
+ }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for DateTime.
+ /// </summary>
+ internal sealed class DateTimeTypeInfo : TraceLoggingTypeInfo
+ {
+ public DateTimeTypeInfo() : base(typeof(DateTime)) { }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.FileTime, format));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ var ticks = value.ScalarValue.AsDateTime.Ticks;
+ collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
+ }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for DateTimeOffset.
+ /// </summary>
+ internal sealed class DateTimeOffsetTypeInfo : TraceLoggingTypeInfo
+ {
+ public DateTimeOffsetTypeInfo() : base(typeof(DateTimeOffset)) { }
+
+ public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
+ {
+ var group = collector.AddGroup(name);
+ group.AddScalar("Ticks", Statics.MakeDataType(TraceLoggingDataType.FileTime, format));
+ group.AddScalar("Offset", TraceLoggingDataType.Int64);
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ var dateTimeOffset = value.ScalarValue.AsDateTimeOffset;
+ var ticks = dateTimeOffset.Ticks;
+ collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
+ collector.AddScalar(dateTimeOffset.Offset.Ticks);
+ }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for TimeSpan.
+ /// </summary>
+ internal sealed class TimeSpanTypeInfo : TraceLoggingTypeInfo
+ {
+ public TimeSpanTypeInfo() : base(typeof(TimeSpan)) { }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Int64, format));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ collector.AddScalar(value.ScalarValue.AsTimeSpan.Ticks);
+ }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for Decimal. (Note: not full-fidelity, exposed as Double.)
+ /// </summary>
+ internal sealed class DecimalTypeInfo : TraceLoggingTypeInfo
+ {
+ public DecimalTypeInfo() : base(typeof(Decimal)) { }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Double, format));
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ collector.AddScalar((double)value.ScalarValue.AsDecimal);
+ }
+ }
+
+ /// <summary>
+ /// TraceLogging: Type handler for Nullable.
+ /// </summary>
+ internal sealed class NullableTypeInfo : TraceLoggingTypeInfo
+ {
+ private readonly TraceLoggingTypeInfo valueInfo;
+ private readonly Func<PropertyValue, PropertyValue> hasValueGetter;
+ private readonly Func<PropertyValue, PropertyValue> valueGetter;
+
+ public NullableTypeInfo(Type type, List<Type> recursionCheck)
+ : base(type)
+ {
+ var typeArgs = type.GenericTypeArguments;
+ Contract.Assert(typeArgs.Length == 1);
+ this.valueInfo = TraceLoggingTypeInfo.GetInstance(typeArgs[0], recursionCheck);
+ this.hasValueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("HasValue"));
+ this.valueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("Value"));
+ }
+
+ public override void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format)
+ {
+ var group = collector.AddGroup(name);
+ group.AddScalar("HasValue", TraceLoggingDataType.Boolean8);
+ this.valueInfo.WriteMetadata(group, "Value", format);
+ }
+
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
+ {
+ var hasValue = hasValueGetter(value);
+ collector.AddScalar(hasValue);
+ var val = hasValue.ScalarValue.AsBoolean ? valueGetter(value) : valueInfo.PropertyValueFactory(Activator.CreateInstance(valueInfo.DataType));
+ this.valueInfo.WriteData(collector, val);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs
new file mode 100644
index 0000000000..fa0f79f58f
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/Statics.cs
@@ -0,0 +1,727 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Encoding = System.Text.Encoding;
+
+using Microsoft.Reflection;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Constants and utility functions.
+ /// </summary>
+ internal static class Statics
+ {
+ #region Constants
+
+ public const byte DefaultLevel = 5;
+ public const byte TraceLoggingChannel = 0xb;
+ public const byte InTypeMask = 31;
+ public const byte InTypeFixedCountFlag = 32;
+ public const byte InTypeVariableCountFlag = 64;
+ public const byte InTypeCustomCountFlag = 96;
+ public const byte InTypeCountMask = 96;
+ public const byte InTypeChainFlag = 128;
+ public const byte OutTypeMask = 127;
+ public const byte OutTypeChainFlag = 128;
+ public const EventTags EventTagsMask = (EventTags)0xfffffff;
+
+ public static readonly TraceLoggingDataType IntPtrType = IntPtr.Size == 8
+ ? TraceLoggingDataType.Int64
+ : TraceLoggingDataType.Int32;
+ public static readonly TraceLoggingDataType UIntPtrType = IntPtr.Size == 8
+ ? TraceLoggingDataType.UInt64
+ : TraceLoggingDataType.UInt32;
+ public static readonly TraceLoggingDataType HexIntPtrType = IntPtr.Size == 8
+ ? TraceLoggingDataType.HexInt64
+ : TraceLoggingDataType.HexInt32;
+
+ #endregion
+
+ #region Metadata helpers
+
+ /// <summary>
+ /// A complete metadata chunk can be expressed as:
+ /// length16 + prefix + null-terminated-utf8-name + suffix + additionalData.
+ /// We assume that excludedData will be provided by some other means,
+ /// but that its size is known. This function returns a blob containing
+ /// length16 + prefix + name + suffix, with prefix and suffix initialized
+ /// to 0's. The length16 value is initialized to the length of the returned
+ /// blob plus additionalSize, so that the concatenation of the returned blob
+ /// plus a blob of size additionalSize constitutes a valid metadata blob.
+ /// </summary>
+ /// <param name="name">
+ /// The name to include in the blob.
+ /// </param>
+ /// <param name="prefixSize">
+ /// Amount of space to reserve before name. For provider or field blobs, this
+ /// should be 0. For event blobs, this is used for the tags field and will vary
+ /// from 1 to 4, depending on how large the tags field needs to be.
+ /// </param>
+ /// <param name="suffixSize">
+ /// Amount of space to reserve after name. For example, a provider blob with no
+ /// traits would reserve 0 extra bytes, but a provider blob with a single GroupId
+ /// field would reserve 19 extra bytes.
+ /// </param>
+ /// <param name="additionalSize">
+ /// Amount of additional data in another blob. This value will be counted in the
+ /// blob's length field, but will not be included in the returned byte[] object.
+ /// The complete blob would then be the concatenation of the returned byte[] object
+ /// with another byte[] object of length additionalSize.
+ /// </param>
+ /// <returns>
+ /// A byte[] object with the length and name fields set, with room reserved for
+ /// prefix and suffix. If additionalSize was 0, the byte[] object is a complete
+ /// blob. Otherwise, another byte[] of size additionalSize must be concatenated
+ /// with this one to form a complete blob.
+ /// </returns>
+ public static byte[] MetadataForString(
+ string name,
+ int prefixSize,
+ int suffixSize,
+ int additionalSize)
+ {
+ Statics.CheckName(name);
+ int metadataSize = Encoding.UTF8.GetByteCount(name) + 3 + prefixSize + suffixSize;
+ var metadata = new byte[metadataSize];
+ ushort totalSize = checked((ushort)(metadataSize + additionalSize));
+ metadata[0] = unchecked((byte)totalSize);
+ metadata[1] = unchecked((byte)(totalSize >> 8));
+ Encoding.UTF8.GetBytes(name, 0, name.Length, metadata, 2 + prefixSize);
+ return metadata;
+ }
+
+ /// <summary>
+ /// Serialize the low 28 bits of the tags value into the metadata stream,
+ /// starting at the index given by pos. Updates pos. Writes 1 to 4 bytes,
+ /// depending on the value of the tags variable. Usable for event tags and
+ /// field tags.
+ ///
+ /// Note that 'metadata' can be null, in which case it only updates 'pos'.
+ /// This is useful for a two pass approach where you figure out how big to
+ /// make the array, and then you fill it in.
+ /// </summary>
+ public static void EncodeTags(int tags, ref int pos, byte[] metadata)
+ {
+ // We transmit the low 28 bits of tags, high bits first, 7 bits at a time.
+ var tagsLeft = tags & 0xfffffff;
+ bool more;
+ do
+ {
+ byte current = (byte)((tagsLeft >> 21) & 0x7f);
+ more = (tagsLeft & 0x1fffff) != 0;
+ current |= (byte)(more ? 0x80 : 0x00);
+ tagsLeft = tagsLeft << 7;
+
+ if (metadata != null)
+ {
+ metadata[pos] = current;
+ }
+ pos += 1;
+ }
+ while (more);
+ }
+
+ public static byte Combine(
+ int settingValue,
+ byte defaultValue)
+ {
+ unchecked
+ {
+ return (byte)settingValue == settingValue
+ ? (byte)settingValue
+ : defaultValue;
+ }
+ }
+
+ public static byte Combine(
+ int settingValue1,
+ int settingValue2,
+ byte defaultValue)
+ {
+ unchecked
+ {
+ return (byte)settingValue1 == settingValue1
+ ? (byte)settingValue1
+ : (byte)settingValue2 == settingValue2
+ ? (byte)settingValue2
+ : defaultValue;
+ }
+ }
+
+ public static int Combine(
+ int settingValue1,
+ int settingValue2)
+ {
+ unchecked
+ {
+ return (byte)settingValue1 == settingValue1
+ ? settingValue1
+ : settingValue2;
+ }
+ }
+
+ public static void CheckName(string name)
+ {
+ if (name != null && 0 <= name.IndexOf('\0'))
+ {
+ throw new ArgumentOutOfRangeException("name");
+ }
+ }
+
+ public static bool ShouldOverrideFieldName(string fieldName)
+ {
+ return (fieldName.Length <= 2 && fieldName[0] == '_');
+ }
+
+ public static TraceLoggingDataType MakeDataType(
+ TraceLoggingDataType baseType,
+ EventFieldFormat format)
+ {
+ return (TraceLoggingDataType)(((int)baseType & 0x1f) | ((int)format << 8));
+ }
+
+ /// <summary>
+ /// Adjusts the native type based on format.
+ /// - If format is default, return native.
+ /// - If format is recognized, return the canonical type for that format.
+ /// - Otherwise remove existing format from native and apply the requested format.
+ /// </summary>
+ public static TraceLoggingDataType Format8(
+ EventFieldFormat format,
+ TraceLoggingDataType native)
+ {
+ switch (format)
+ {
+ case EventFieldFormat.Default:
+ return native;
+ case EventFieldFormat.String:
+ return TraceLoggingDataType.Char8;
+ case EventFieldFormat.Boolean:
+ return TraceLoggingDataType.Boolean8;
+ case EventFieldFormat.Hexadecimal:
+ return TraceLoggingDataType.HexInt8;
+#if false
+ case EventSourceFieldFormat.Signed:
+ return TraceLoggingDataType.Int8;
+ case EventSourceFieldFormat.Unsigned:
+ return TraceLoggingDataType.UInt8;
+#endif
+ default:
+ return MakeDataType(native, format);
+ }
+ }
+
+ /// <summary>
+ /// Adjusts the native type based on format.
+ /// - If format is default, return native.
+ /// - If format is recognized, return the canonical type for that format.
+ /// - Otherwise remove existing format from native and apply the requested format.
+ /// </summary>
+ public static TraceLoggingDataType Format16(
+ EventFieldFormat format,
+ TraceLoggingDataType native)
+ {
+ switch (format)
+ {
+ case EventFieldFormat.Default:
+ return native;
+ case EventFieldFormat.String:
+ return TraceLoggingDataType.Char16;
+ case EventFieldFormat.Hexadecimal:
+ return TraceLoggingDataType.HexInt16;
+#if false
+ case EventSourceFieldFormat.Port:
+ return TraceLoggingDataType.Port;
+ case EventSourceFieldFormat.Signed:
+ return TraceLoggingDataType.Int16;
+ case EventSourceFieldFormat.Unsigned:
+ return TraceLoggingDataType.UInt16;
+#endif
+ default:
+ return MakeDataType(native, format);
+ }
+ }
+
+ /// <summary>
+ /// Adjusts the native type based on format.
+ /// - If format is default, return native.
+ /// - If format is recognized, return the canonical type for that format.
+ /// - Otherwise remove existing format from native and apply the requested format.
+ /// </summary>
+ public static TraceLoggingDataType Format32(
+ EventFieldFormat format,
+ TraceLoggingDataType native)
+ {
+ switch (format)
+ {
+ case EventFieldFormat.Default:
+ return native;
+ case EventFieldFormat.Boolean:
+ return TraceLoggingDataType.Boolean32;
+ case EventFieldFormat.Hexadecimal:
+ return TraceLoggingDataType.HexInt32;
+#if false
+ case EventSourceFieldFormat.Ipv4Address:
+ return TraceLoggingDataType.Ipv4Address;
+ case EventSourceFieldFormat.ProcessId:
+ return TraceLoggingDataType.ProcessId;
+ case EventSourceFieldFormat.ThreadId:
+ return TraceLoggingDataType.ThreadId;
+ case EventSourceFieldFormat.Win32Error:
+ return TraceLoggingDataType.Win32Error;
+ case EventSourceFieldFormat.NTStatus:
+ return TraceLoggingDataType.NTStatus;
+#endif
+ case EventFieldFormat.HResult:
+ return TraceLoggingDataType.HResult;
+#if false
+ case EventSourceFieldFormat.Signed:
+ return TraceLoggingDataType.Int32;
+ case EventSourceFieldFormat.Unsigned:
+ return TraceLoggingDataType.UInt32;
+#endif
+ default:
+ return MakeDataType(native, format);
+ }
+ }
+
+ /// <summary>
+ /// Adjusts the native type based on format.
+ /// - If format is default, return native.
+ /// - If format is recognized, return the canonical type for that format.
+ /// - Otherwise remove existing format from native and apply the requested format.
+ /// </summary>
+ public static TraceLoggingDataType Format64(
+ EventFieldFormat format,
+ TraceLoggingDataType native)
+ {
+ switch (format)
+ {
+ case EventFieldFormat.Default:
+ return native;
+ case EventFieldFormat.Hexadecimal:
+ return TraceLoggingDataType.HexInt64;
+#if false
+ case EventSourceFieldFormat.FileTime:
+ return TraceLoggingDataType.FileTime;
+ case EventSourceFieldFormat.Signed:
+ return TraceLoggingDataType.Int64;
+ case EventSourceFieldFormat.Unsigned:
+ return TraceLoggingDataType.UInt64;
+#endif
+ default:
+ return MakeDataType(native, format);
+ }
+ }
+
+ /// <summary>
+ /// Adjusts the native type based on format.
+ /// - If format is default, return native.
+ /// - If format is recognized, return the canonical type for that format.
+ /// - Otherwise remove existing format from native and apply the requested format.
+ /// </summary>
+ public static TraceLoggingDataType FormatPtr(
+ EventFieldFormat format,
+ TraceLoggingDataType native)
+ {
+ switch (format)
+ {
+ case EventFieldFormat.Default:
+ return native;
+ case EventFieldFormat.Hexadecimal:
+ return HexIntPtrType;
+#if false
+ case EventSourceFieldFormat.Signed:
+ return IntPtrType;
+ case EventSourceFieldFormat.Unsigned:
+ return UIntPtrType;
+#endif
+ default:
+ return MakeDataType(native, format);
+ }
+ }
+
+ #endregion
+
+ #region Reflection helpers
+
+ /*
+ All TraceLogging use of reflection APIs should go through wrappers here.
+ This helps with portability, and it also makes it easier to audit what
+ kinds of reflection operations are being done.
+ */
+
+ public static object CreateInstance(Type type, params object[] parameters)
+ {
+ return Activator.CreateInstance(type, parameters);
+ }
+
+ public static bool IsValueType(Type type)
+ {
+ bool result = type.IsValueType();
+ return result;
+ }
+
+ public static bool IsEnum(Type type)
+ {
+ bool result = type.IsEnum();
+ return result;
+ }
+
+ public static IEnumerable<PropertyInfo> GetProperties(Type type)
+ {
+ IEnumerable<PropertyInfo> result = type.GetProperties();
+ return result;
+ }
+
+ public static MethodInfo GetGetMethod(PropertyInfo propInfo)
+ {
+ MethodInfo result = propInfo.GetGetMethod();
+ return result;
+ }
+
+ public static MethodInfo GetDeclaredStaticMethod(Type declaringType, string name)
+ {
+ MethodInfo result;
+#if (ES_BUILD_PCL || PROJECTN)
+ result = declaringType.GetTypeInfo().GetDeclaredMethod(name);
+#else
+ result = declaringType.GetMethod(
+ name,
+ BindingFlags.DeclaredOnly | BindingFlags.Static | BindingFlags.NonPublic);
+#endif
+ return result;
+ }
+
+ public static bool HasCustomAttribute(
+ PropertyInfo propInfo,
+ Type attributeType)
+ {
+ bool result;
+#if (ES_BUILD_PCL || PROJECTN)
+ result = propInfo.IsDefined(attributeType);
+#else
+ var attributes = propInfo.GetCustomAttributes(
+ attributeType,
+ false);
+ result = attributes.Length != 0;
+#endif
+ return result;
+ }
+
+ public static AttributeType GetCustomAttribute<AttributeType>(PropertyInfo propInfo)
+ where AttributeType : Attribute
+ {
+ AttributeType result = null;
+#if (ES_BUILD_PCL || PROJECTN)
+ foreach (var attrib in propInfo.GetCustomAttributes<AttributeType>(false))
+ {
+ result = attrib;
+ break;
+ }
+#else
+ var attributes = propInfo.GetCustomAttributes(typeof(AttributeType), false);
+ if (attributes.Length != 0)
+ {
+ result = (AttributeType)attributes[0];
+ }
+#endif
+ return result;
+ }
+
+ public static AttributeType GetCustomAttribute<AttributeType>(Type type)
+ where AttributeType : Attribute
+ {
+ AttributeType result = null;
+#if (ES_BUILD_PCL || PROJECTN)
+ foreach (var attrib in type.GetTypeInfo().GetCustomAttributes<AttributeType>(false))
+ {
+ result = attrib;
+ break;
+ }
+#else
+ var attributes = type.GetCustomAttributes(typeof(AttributeType), false);
+ if (attributes.Length != 0)
+ {
+ result = (AttributeType)attributes[0];
+ }
+#endif
+ return result;
+ }
+
+ public static Type[] GetGenericArguments(Type type)
+ {
+ return type.GetGenericArguments();
+ }
+
+ public static Type FindEnumerableElementType(Type type)
+ {
+ Type elementType = null;
+
+ if (IsGenericMatch(type, typeof(IEnumerable<>)))
+ {
+ elementType = GetGenericArguments(type)[0];
+ }
+ else
+ {
+#if (ES_BUILD_PCL || PROJECTN)
+ var ifaceTypes = type.GetTypeInfo().ImplementedInterfaces;
+#else
+ var ifaceTypes = type.FindInterfaces(IsGenericMatch, typeof(IEnumerable<>));
+#endif
+
+ foreach (var ifaceType in ifaceTypes)
+ {
+#if (ES_BUILD_PCL || PROJECTN)
+ if (!IsGenericMatch(ifaceType, typeof(IEnumerable<>)))
+ {
+ continue;
+ }
+#endif
+
+ if (elementType != null)
+ {
+ // ambiguous match. report no match at all.
+ elementType = null;
+ break;
+ }
+
+ elementType = GetGenericArguments(ifaceType)[0];
+ }
+ }
+
+ return elementType;
+ }
+
+ public static bool IsGenericMatch(Type type, object openType)
+ {
+ return type.IsGenericType() && type.GetGenericTypeDefinition() == (Type)openType;
+ }
+
+ public static Delegate CreateDelegate(Type delegateType, MethodInfo methodInfo)
+ {
+ Delegate result;
+#if (ES_BUILD_PCL || PROJECTN)
+ result = methodInfo.CreateDelegate(
+ delegateType);
+#else
+ result = Delegate.CreateDelegate(
+ delegateType,
+ methodInfo);
+#endif
+ return result;
+ }
+
+ public static TraceLoggingTypeInfo CreateDefaultTypeInfo(
+ Type dataType,
+ List<Type> recursionCheck)
+ {
+ TraceLoggingTypeInfo result;
+
+ if (recursionCheck.Contains(dataType))
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_RecursiveTypeDefinition"));
+ }
+
+ recursionCheck.Add(dataType);
+
+ var eventAttrib = Statics.GetCustomAttribute<EventDataAttribute>(dataType);
+ if (eventAttrib != null ||
+ Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null ||
+ IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
+ {
+ var analysis = new TypeAnalysis(dataType, eventAttrib, recursionCheck);
+ result = new InvokeTypeInfo(dataType, analysis);
+ }
+ else if (dataType.IsArray)
+ {
+ var elementType = dataType.GetElementType();
+ if (elementType == typeof(Boolean))
+ {
+ result = ScalarArrayTypeInfo.Boolean();
+ }
+ else if (elementType == typeof(Byte))
+ {
+ result = ScalarArrayTypeInfo.Byte();
+ }
+ else if (elementType == typeof(SByte))
+ {
+ result = ScalarArrayTypeInfo.SByte();
+ }
+ else if (elementType == typeof(Int16))
+ {
+ result = ScalarArrayTypeInfo.Int16();
+ }
+ else if (elementType == typeof(UInt16))
+ {
+ result = ScalarArrayTypeInfo.UInt16();
+ }
+ else if (elementType == typeof(Int32))
+ {
+ result = ScalarArrayTypeInfo.Int32();
+ }
+ else if (elementType == typeof(UInt32))
+ {
+ result = ScalarArrayTypeInfo.UInt32();
+ }
+ else if (elementType == typeof(Int64))
+ {
+ result = ScalarArrayTypeInfo.Int64();
+ }
+ else if (elementType == typeof(UInt64))
+ {
+ result = ScalarArrayTypeInfo.UInt64();
+ }
+ else if (elementType == typeof(Char))
+ {
+ result = ScalarArrayTypeInfo.Char();
+ }
+ else if (elementType == typeof(Double))
+ {
+ result = ScalarArrayTypeInfo.Double();
+ }
+ else if (elementType == typeof(Single))
+ {
+ result = ScalarArrayTypeInfo.Single();
+ }
+ else if (elementType == typeof(IntPtr))
+ {
+ result = ScalarArrayTypeInfo.IntPtr();
+ }
+ else if (elementType == typeof(UIntPtr))
+ {
+ result = ScalarArrayTypeInfo.UIntPtr();
+ }
+ else if (elementType == typeof(Guid))
+ {
+ result = ScalarArrayTypeInfo.Guid();
+ }
+ else
+ {
+ result = new ArrayTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
+ }
+ }
+ else
+ {
+ if (Statics.IsEnum(dataType))
+ dataType = Enum.GetUnderlyingType(dataType);
+
+ if (dataType == typeof(String))
+ {
+ result = new StringTypeInfo();
+ }
+ else if (dataType == typeof(Boolean))
+ {
+ result = ScalarTypeInfo.Boolean();
+ }
+ else if (dataType == typeof(Byte))
+ {
+ result = ScalarTypeInfo.Byte();
+ }
+ else if (dataType == typeof(SByte))
+ {
+ result = ScalarTypeInfo.SByte();
+ }
+ else if (dataType == typeof(Int16))
+ {
+ result = ScalarTypeInfo.Int16();
+ }
+ else if (dataType == typeof(UInt16))
+ {
+ result = ScalarTypeInfo.UInt16();
+ }
+ else if (dataType == typeof(Int32))
+ {
+ result = ScalarTypeInfo.Int32();
+ }
+ else if (dataType == typeof(UInt32))
+ {
+ result = ScalarTypeInfo.UInt32();
+ }
+ else if (dataType == typeof(Int64))
+ {
+ result = ScalarTypeInfo.Int64();
+ }
+ else if (dataType == typeof(UInt64))
+ {
+ result = ScalarTypeInfo.UInt64();
+ }
+ else if (dataType == typeof(Char))
+ {
+ result = ScalarTypeInfo.Char();
+ }
+ else if (dataType == typeof(Double))
+ {
+ result = ScalarTypeInfo.Double();
+ }
+ else if (dataType == typeof(Single))
+ {
+ result = ScalarTypeInfo.Single();
+ }
+ else if (dataType == typeof(DateTime))
+ {
+ result = new DateTimeTypeInfo();
+ }
+ else if (dataType == typeof(Decimal))
+ {
+ result = new DecimalTypeInfo();
+ }
+ else if (dataType == typeof(IntPtr))
+ {
+ result = ScalarTypeInfo.IntPtr();
+ }
+ else if (dataType == typeof(UIntPtr))
+ {
+ result = ScalarTypeInfo.UIntPtr();
+ }
+ else if (dataType == typeof(Guid))
+ {
+ result = ScalarTypeInfo.Guid();
+ }
+ else if (dataType == typeof(TimeSpan))
+ {
+ result = new TimeSpanTypeInfo();
+ }
+ else if (dataType == typeof(DateTimeOffset))
+ {
+ result = new DateTimeOffsetTypeInfo();
+ }
+ else if (dataType == typeof(EmptyStruct))
+ {
+ result = new NullTypeInfo();
+ }
+ else if (IsGenericMatch(dataType, typeof(Nullable<>)))
+ {
+ result = new NullableTypeInfo(dataType, recursionCheck);
+ }
+ else
+ {
+ var elementType = FindEnumerableElementType(dataType);
+ if (elementType != null)
+ {
+ result = new EnumerableTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
+ }
+ else
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NonCompliantTypeError", dataType.Name));
+ }
+ }
+ }
+
+ return result;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs
new file mode 100644
index 0000000000..4b6e633487
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataCollector.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Security;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Used when implementing a custom TraceLoggingTypeInfo.
+ /// The instance of this type is provided to the TypeInfo.WriteData method.
+ /// All operations are forwarded to the current thread's DataCollector.
+ /// Note that this abstraction would allow us to expose the custom
+ /// serialization system to partially-trusted code. If we end up not
+ /// making custom serialization public, or if we only expose it to
+ /// full-trust code, this abstraction is unnecessary (though it probably
+ /// doesn't hurt anything).
+ /// </summary>
+ [SecuritySafeCritical]
+ internal unsafe class TraceLoggingDataCollector
+ {
+ internal static readonly TraceLoggingDataCollector Instance = new TraceLoggingDataCollector();
+
+ private TraceLoggingDataCollector()
+ {
+ return;
+ }
+
+ /// <summary>
+ /// Marks the start of a non-blittable array or enumerable.
+ /// </summary>
+ /// <returns>Bookmark to be passed to EndBufferedArray.</returns>
+ public int BeginBufferedArray()
+ {
+ return DataCollector.ThreadInstance.BeginBufferedArray();
+ }
+
+ /// <summary>
+ /// Marks the end of a non-blittable array or enumerable.
+ /// </summary>
+ /// <param name="bookmark">The value returned by BeginBufferedArray.</param>
+ /// <param name="count">The number of items in the array.</param>
+ public void EndBufferedArray(int bookmark, int count)
+ {
+ DataCollector.ThreadInstance.EndBufferedArray(bookmark, count);
+ }
+
+ /// <summary>
+ /// Adds the start of a group to the event.
+ /// This has no effect on the event payload, but is provided to allow
+ /// WriteMetadata and WriteData implementations to have similar
+ /// sequences of calls, allowing for easier verification of correctness.
+ /// </summary>
+ public TraceLoggingDataCollector AddGroup()
+ {
+ return this;
+ }
+
+ public void AddScalar(PropertyValue value)
+ {
+ var scalar = value.ScalarValue;
+ DataCollector.ThreadInstance.AddScalar(&scalar, value.ScalarLength);
+ }
+
+ /// <summary>
+ /// Adds an Int64 value to the event payload.
+ /// </summary>
+ /// <param name="value">Value to be added.</param>
+ public void AddScalar(long value)
+ {
+ DataCollector.ThreadInstance.AddScalar(&value, sizeof(long));
+ }
+
+ /// <summary>
+ /// Adds a Double value to the event payload.
+ /// </summary>
+ /// <param name="value">Value to be added.</param>
+ public void AddScalar(double value)
+ {
+ DataCollector.ThreadInstance.AddScalar(&value, sizeof(double));
+ }
+
+ /// <summary>
+ /// Adds a counted String value to the event payload.
+ /// </summary>
+ /// <param name="value">
+ /// Value to be added. A null value is treated as a zero-length string.
+ /// </param>
+ public void AddBinary(string value)
+ {
+ DataCollector.ThreadInstance.AddBinary(value, value == null ? 0 : value.Length * 2);
+ }
+
+ public void AddArray(PropertyValue value, int elementSize)
+ {
+ Array array = (Array)value.ReferenceValue;
+ DataCollector.ThreadInstance.AddArray(array, array == null ? 0 : array.Length, elementSize);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataType.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataType.cs
new file mode 100644
index 0000000000..529948daf8
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingDataType.cs
@@ -0,0 +1,349 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Used when implementing a custom TraceLoggingTypeInfo.
+ /// These are passed to metadataCollector.Add to specify the low-level
+ /// type of a field in the event payload. Note that a "formatted"
+ /// TraceLoggingDataType consists of a core TraceLoggingDataType value
+ /// (a TraceLoggingDataType with a value less than 32) plus an OutType.
+ /// Any combination of TraceLoggingDataType + OutType is valid, but not
+ /// all are useful. In particular, combinations not explicitly listed
+ /// below are unlikely to be recognized by decoders, and will typically
+ /// be decoded as the corresponding core type (i.e. the decoder will
+ /// mask off any unrecognized OutType value).
+ /// </summary>
+ internal enum TraceLoggingDataType
+ {
+ /// <summary>
+ /// Core type.
+ /// Data type with no value (0-length payload).
+ /// NOTE: arrays of Nil are illegal.
+ /// NOTE: a fixed-length array of Nil is interpreted by the decoder as
+ /// a struct (obsolete but retained for backwards-compatibility).
+ /// </summary>
+ Nil = 0,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes null-terminated Char16 string.
+ /// Decoding treats as UTF-16LE string.
+ /// </summary>
+ Utf16String = 1,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes null-terminated Char8 string.
+ /// Decoding treats as MBCS string.
+ /// </summary>
+ MbcsString = 2,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 8-bit value.
+ /// Decoding treats as signed integer.
+ /// </summary>
+ Int8 = 3,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 8-bit value.
+ /// Decoding treats as unsigned integer.
+ /// </summary>
+ UInt8 = 4,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-bit value.
+ /// Decoding treats as signed integer.
+ /// </summary>
+ Int16 = 5,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-bit value.
+ /// Decoding treats as unsigned integer.
+ /// </summary>
+ UInt16 = 6,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as signed integer.
+ /// </summary>
+ Int32 = 7,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as unsigned integer.
+ /// </summary>
+ UInt32 = 8,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 64-bit value.
+ /// Decoding treats as signed integer.
+ /// </summary>
+ Int64 = 9,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 64-bit value.
+ /// Decoding treats as unsigned integer.
+ /// </summary>
+ UInt64 = 10,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as Float.
+ /// </summary>
+ Float = 11,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 64-bit value.
+ /// Decoding treats as Double.
+ /// </summary>
+ Double = 12,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as Boolean.
+ /// </summary>
+ Boolean32 = 13,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-bit bytecount followed by binary data.
+ /// Decoding treats as binary data.
+ /// </summary>
+ Binary = 14,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-byte value.
+ /// Decoding treats as GUID.
+ /// </summary>
+ Guid = 15,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 64-bit value.
+ /// Decoding treats as FILETIME.
+ /// </summary>
+ FileTime = 17,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-byte value.
+ /// Decoding treats as SYSTEMTIME.
+ /// </summary>
+ SystemTime = 18,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as hexadecimal unsigned integer.
+ /// </summary>
+ HexInt32 = 20,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 64-bit value.
+ /// Decoding treats as hexadecimal unsigned integer.
+ /// </summary>
+ HexInt64 = 21,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-bit bytecount followed by Char16 data.
+ /// Decoding treats as UTF-16LE string.
+ /// </summary>
+ CountedUtf16String = 22,
+
+ /// <summary>
+ /// Core type.
+ /// Encoding assumes 16-bit bytecount followed by Char8 data.
+ /// Decoding treats as MBCS string.
+ /// </summary>
+ CountedMbcsString = 23,
+
+ /// <summary>
+ /// Core type.
+ /// Special case: Struct indicates that this field plus the the
+ /// subsequent N logical fields are to be considered as one logical
+ /// field (i.e. a nested structure). The OutType is used to encode N.
+ /// The maximum value for N is 127. This field has no payload by
+ /// itself, but logically contains the payload of the following N
+ /// fields. It is legal to have an array of Struct.
+ /// </summary>
+ Struct = 24,
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit value.
+ /// Decoding treats as UTF-16LE character.
+ /// </summary>
+ Char16 = UInt16 + (EventFieldFormat.String << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 8-bit value.
+ /// Decoding treats as character.
+ /// </summary>
+ Char8 = UInt8 + (EventFieldFormat.String << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 8-bit value.
+ /// Decoding treats as Boolean.
+ /// </summary>
+ Boolean8 = UInt8 + (EventFieldFormat.Boolean << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 8-bit value.
+ /// Decoding treats as hexadecimal unsigned integer.
+ /// </summary>
+ HexInt8 = UInt8 + (EventFieldFormat.Hexadecimal << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit value.
+ /// Decoding treats as hexadecimal unsigned integer.
+ /// </summary>
+ HexInt16 = UInt16 + (EventFieldFormat.Hexadecimal << 8),
+
+#if false
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as process identifier.
+ /// </summary>
+ ProcessId = UInt32 + (EventSourceFieldFormat.ProcessId << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as thread identifier.
+ /// </summary>
+ ThreadId = UInt32 + (EventSourceFieldFormat.ThreadId << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit value.
+ /// Decoding treats as IP port.
+ /// </summary>
+ Port = UInt16 + (EventSourceFieldFormat.Port << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as IPv4 address.
+ /// </summary>
+ Ipv4Address = UInt32 + (EventSourceFieldFormat.Ipv4Address << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by binary data.
+ /// Decoding treats as IPv6 address.
+ /// </summary>
+ Ipv6Address = Binary + (EventSourceFieldFormat.Ipv6Address << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by binary data.
+ /// Decoding treats as SOCKADDR.
+ /// </summary>
+ SocketAddress = Binary + (EventSourceFieldFormat.SocketAddress << 8),
+#endif
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes null-terminated Char16 string.
+ /// Decoding treats as UTF-16LE XML string.
+ /// </summary>
+ Utf16Xml = Utf16String + (EventFieldFormat.Xml << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes null-terminated Char8 string.
+ /// Decoding treats as MBCS XML string.
+ /// </summary>
+ MbcsXml = MbcsString + (EventFieldFormat.Xml << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by Char16 data.
+ /// Decoding treats as UTF-16LE XML.
+ /// </summary>
+ CountedUtf16Xml = CountedUtf16String + (EventFieldFormat.Xml << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by Char8 data.
+ /// Decoding treats as MBCS XML.
+ /// </summary>
+ CountedMbcsXml = CountedMbcsString + (EventFieldFormat.Xml << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes null-terminated Char16 string.
+ /// Decoding treats as UTF-16LE JSON string.
+ /// </summary>
+ Utf16Json = Utf16String + (EventFieldFormat.Json << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes null-terminated Char8 string.
+ /// Decoding treats as MBCS JSON string.
+ /// </summary>
+ MbcsJson = MbcsString + (EventFieldFormat.Json << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by Char16 data.
+ /// Decoding treats as UTF-16LE JSON.
+ /// </summary>
+ CountedUtf16Json = CountedUtf16String + (EventFieldFormat.Json << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 16-bit bytecount followed by Char8 data.
+ /// Decoding treats as MBCS JSON.
+ /// </summary>
+ CountedMbcsJson = CountedMbcsString + (EventFieldFormat.Json << 8),
+#if false
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as Win32 error.
+ /// </summary>
+ Win32Error = UInt32 + (EventSourceFieldFormat.Win32Error << 8),
+
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as NTSTATUS.
+ /// </summary>
+ NTStatus = UInt32 + (EventSourceFieldFormat.NTStatus << 8),
+#endif
+ /// <summary>
+ /// Formatted type.
+ /// Encoding assumes 32-bit value.
+ /// Decoding treats as HRESULT.
+ /// </summary>
+ HResult = Int32 + (EventFieldFormat.HResult << 8)
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs
new file mode 100644
index 0000000000..963c492419
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventSource.cs
@@ -0,0 +1,902 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// This program uses code hyperlinks available as part of the HyperAddin Visual Studio plug-in.
+// It is available from http://www.codeplex.com/hyperAddin
+
+#if !PLATFORM_UNIX
+#define FEATURE_MANAGED_ETW
+
+#if !ES_BUILD_STANDALONE
+#define FEATURE_ACTIVITYSAMPLING
+#endif
+#endif // PLATFORM_UNIX
+
+#if ES_BUILD_STANDALONE
+#define FEATURE_MANAGED_ETW_CHANNELS
+// #define FEATURE_ADVANCED_MANAGED_ETW_CHANNELS
+#endif
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
+#endif
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Collections.ObjectModel;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+using System.Collections.Generic;
+using System.Text;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+using System.Collections.Generic;
+using System.Text;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ public partial class EventSource
+ {
+#if FEATURE_MANAGED_ETW
+ private byte[] providerMetadata;
+#endif
+
+ /// <summary>
+ /// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
+ /// </summary>
+ /// <param name="eventSourceName">
+ /// The name of the event source. Must not be null.
+ /// </param>
+ public EventSource(
+ string eventSourceName)
+ : this(eventSourceName, EventSourceSettings.EtwSelfDescribingEventFormat)
+ { }
+
+ /// <summary>
+ /// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
+ /// </summary>
+ /// <param name="eventSourceName">
+ /// The name of the event source. Must not be null.
+ /// </param>
+ /// <param name="config">
+ /// Configuration options for the EventSource as a whole.
+ /// </param>
+ public EventSource(
+ string eventSourceName,
+ EventSourceSettings config)
+ : this(eventSourceName, config, null) { }
+
+ /// <summary>
+ /// Construct an EventSource with a given name for non-contract based events (e.g. those using the Write() API).
+ ///
+ /// Also specify a list of key-value pairs called traits (you must pass an even number of strings).
+ /// The first string is the key and the second is the value. These are not interpreted by EventSource
+ /// itself but may be interprated the listeners. Can be fetched with GetTrait(string).
+ /// </summary>
+ /// <param name="eventSourceName">
+ /// The name of the event source. Must not be null.
+ /// </param>
+ /// <param name="config">
+ /// Configuration options for the EventSource as a whole.
+ /// </param>
+ /// <param name="traits">A collection of key-value strings (must be an even number).</param>
+ public EventSource(
+ string eventSourceName,
+ EventSourceSettings config,
+ params string[] traits)
+ : this(
+ eventSourceName == null ? new Guid() : GenerateGuidFromName(eventSourceName.ToUpperInvariant()),
+ eventSourceName,
+ config, traits)
+ {
+ if (eventSourceName == null)
+ {
+ throw new ArgumentNullException("eventSourceName");
+ }
+ Contract.EndContractBlock();
+ }
+
+ /// <summary>
+ /// Writes an event with no fields and default options.
+ /// (Native API: EventWriteTransfer)
+ /// </summary>
+ /// <param name="eventName">The name of the event. Must not be null.</param>
+ [SecuritySafeCritical]
+ public unsafe void Write(string eventName)
+ {
+ if (eventName == null)
+ {
+ throw new ArgumentNullException("eventName");
+ }
+
+ Contract.EndContractBlock();
+
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ var options = new EventSourceOptions();
+ this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
+ }
+
+ /// <summary>
+ /// Writes an event with no fields.
+ /// (Native API: EventWriteTransfer)
+ /// </summary>
+ /// <param name="eventName">The name of the event. Must not be null.</param>
+ /// <param name="options">
+ /// Options for the event, such as the level, keywords, and opcode. Unset
+ /// options will be set to default values.
+ /// </param>
+ [SecuritySafeCritical]
+ public unsafe void Write(string eventName, EventSourceOptions options)
+ {
+ if (eventName == null)
+ {
+ throw new ArgumentNullException("eventName");
+ }
+
+ Contract.EndContractBlock();
+
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
+ }
+
+ /// <summary>
+ /// Writes an event.
+ /// (Native API: EventWriteTransfer)
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type that defines the event and its payload. This must be an
+ /// anonymous type or a type with an [EventData] attribute.
+ /// </typeparam>
+ /// <param name="eventName">
+ /// The name for the event. If null, the event name is automatically
+ /// determined based on T, either from the Name property of T's EventData
+ /// attribute or from typeof(T).Name.
+ /// </param>
+ /// <param name="data">
+ /// The object containing the event payload data. The type T must be
+ /// an anonymous type or a type with an [EventData] attribute. The
+ /// public instance properties of data will be written recursively to
+ /// create the fields of the event.
+ /// </param>
+ [SecuritySafeCritical]
+ public unsafe void Write<T>(
+ string eventName,
+ T data)
+ {
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ var options = new EventSourceOptions();
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
+ }
+
+ /// <summary>
+ /// Writes an event.
+ /// (Native API: EventWriteTransfer)
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type that defines the event and its payload. This must be an
+ /// anonymous type or a type with an [EventData] attribute.
+ /// </typeparam>
+ /// <param name="eventName">
+ /// The name for the event. If null, the event name is automatically
+ /// determined based on T, either from the Name property of T's EventData
+ /// attribute or from typeof(T).Name.
+ /// </param>
+ /// <param name="options">
+ /// Options for the event, such as the level, keywords, and opcode. Unset
+ /// options will be set to default values.
+ /// </param>
+ /// <param name="data">
+ /// The object containing the event payload data. The type T must be
+ /// an anonymous type or a type with an [EventData] attribute. The
+ /// public instance properties of data will be written recursively to
+ /// create the fields of the event.
+ /// </param>
+ [SecuritySafeCritical]
+ public unsafe void Write<T>(
+ string eventName,
+ EventSourceOptions options,
+ T data)
+ {
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
+ }
+
+ /// <summary>
+ /// Writes an event.
+ /// This overload is for use with extension methods that wish to efficiently
+ /// forward the options or data parameter without performing an extra copy.
+ /// (Native API: EventWriteTransfer)
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type that defines the event and its payload. This must be an
+ /// anonymous type or a type with an [EventData] attribute.
+ /// </typeparam>
+ /// <param name="eventName">
+ /// The name for the event. If null, the event name is automatically
+ /// determined based on T, either from the Name property of T's EventData
+ /// attribute or from typeof(T).Name.
+ /// </param>
+ /// <param name="options">
+ /// Options for the event, such as the level, keywords, and opcode. Unset
+ /// options will be set to default values.
+ /// </param>
+ /// <param name="data">
+ /// The object containing the event payload data. The type T must be
+ /// an anonymous type or a type with an [EventData] attribute. The
+ /// public instance properties of data will be written recursively to
+ /// create the fields of the event.
+ /// </param>
+ [SecuritySafeCritical]
+ public unsafe void Write<T>(
+ string eventName,
+ ref EventSourceOptions options,
+ ref T data)
+ {
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
+ }
+
+ /// <summary>
+ /// Writes an event.
+ /// This overload is meant for clients that need to manipuate the activityId
+ /// and related ActivityId for the event.
+ /// </summary>
+ /// <typeparam name="T">
+ /// The type that defines the event and its payload. This must be an
+ /// anonymous type or a type with an [EventData] attribute.
+ /// </typeparam>
+ /// <param name="eventName">
+ /// The name for the event. If null, the event name is automatically
+ /// determined based on T, either from the Name property of T's EventData
+ /// attribute or from typeof(T).Name.
+ /// </param>
+ /// <param name="options">
+ /// Options for the event, such as the level, keywords, and opcode. Unset
+ /// options will be set to default values.
+ /// </param>
+ /// <param name="activityId">
+ /// The GUID of the activity associated with this event.
+ /// </param>
+ /// <param name="relatedActivityId">
+ /// The GUID of another activity that is related to this activity, or Guid.Empty
+ /// if there is no related activity. Most commonly, the Start operation of a
+ /// new activity specifies a parent activity as its related activity.
+ /// </param>
+ /// <param name="data">
+ /// The object containing the event payload data. The type T must be
+ /// an anonymous type or a type with an [EventData] attribute. The
+ /// public instance properties of data will be written recursively to
+ /// create the fields of the event.
+ /// </param>
+ [SecuritySafeCritical]
+ public unsafe void Write<T>(
+ string eventName,
+ ref EventSourceOptions options,
+ ref Guid activityId,
+ ref Guid relatedActivityId,
+ ref T data)
+ {
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ fixed (Guid* pActivity = &activityId, pRelated = &relatedActivityId)
+ {
+ this.WriteImpl(
+ eventName,
+ ref options,
+ data,
+ pActivity,
+ relatedActivityId == Guid.Empty ? null : pRelated,
+ SimpleEventTypes<T>.Instance);
+ }
+ }
+
+ /// <summary>
+ /// Writes an extended event, where the values of the event are the
+ /// combined properties of any number of values. This method is
+ /// intended for use in advanced logging scenarios that support a
+ /// dynamic set of event context providers.
+ /// This method does a quick check on whether this event is enabled.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name for the event. If null, the name from eventTypes is used.
+ /// (Note that providing the event name via the name parameter is slightly
+ /// less efficient than using the name from eventTypes.)
+ /// </param>
+ /// <param name="options">
+ /// Optional overrides for the event, such as the level, keyword, opcode,
+ /// activityId, and relatedActivityId. Any settings not specified by options
+ /// are obtained from eventTypes.
+ /// </param>
+ /// <param name="eventTypes">
+ /// Information about the event and the types of the values in the event.
+ /// Must not be null. Note that the eventTypes object should be created once and
+ /// saved. It should not be recreated for each event.
+ /// </param>
+ /// <param name="activityID">
+ /// A pointer to the activity ID GUID to log
+ /// </param>
+ /// <param name="childActivityID">
+ /// A pointer to the child activity ID to log (can be null) </param>
+ /// <param name="values">
+ /// The values to include in the event. Must not be null. The number and types of
+ /// the values must match the number and types of the fields described by the
+ /// eventTypes parameter.
+ /// </param>
+ [SecuritySafeCritical]
+ private unsafe void WriteMultiMerge(
+ string eventName,
+ ref EventSourceOptions options,
+ TraceLoggingEventTypes eventTypes,
+ Guid* activityID,
+ Guid* childActivityID,
+ params object[] values)
+ {
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+ byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0
+ ? options.level
+ : eventTypes.level;
+ EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0
+ ? options.keywords
+ : eventTypes.keywords;
+
+ if (this.IsEnabled((EventLevel)level, keywords))
+ {
+ WriteMultiMergeInner(eventName, ref options, eventTypes, activityID, childActivityID, values);
+ }
+ }
+
+ /// <summary>
+ /// Writes an extended event, where the values of the event are the
+ /// combined properties of any number of values. This method is
+ /// intended for use in advanced logging scenarios that support a
+ /// dynamic set of event context providers.
+ /// Attention: This API does not check whether the event is enabled or not.
+ /// Please use WriteMultiMerge to avoid spending CPU cycles for events that are
+ /// not enabled.
+ /// </summary>
+ /// <param name="eventName">
+ /// The name for the event. If null, the name from eventTypes is used.
+ /// (Note that providing the event name via the name parameter is slightly
+ /// less efficient than using the name from eventTypes.)
+ /// </param>
+ /// <param name="options">
+ /// Optional overrides for the event, such as the level, keyword, opcode,
+ /// activityId, and relatedActivityId. Any settings not specified by options
+ /// are obtained from eventTypes.
+ /// </param>
+ /// <param name="eventTypes">
+ /// Information about the event and the types of the values in the event.
+ /// Must not be null. Note that the eventTypes object should be created once and
+ /// saved. It should not be recreated for each event.
+ /// </param>
+ /// <param name="activityID">
+ /// A pointer to the activity ID GUID to log
+ /// </param>
+ /// <param name="childActivityID">
+ /// A pointer to the child activity ID to log (can be null)
+ /// </param>
+ /// <param name="values">
+ /// The values to include in the event. Must not be null. The number and types of
+ /// the values must match the number and types of the fields described by the
+ /// eventTypes parameter.
+ /// </param>
+ [SecuritySafeCritical]
+ private unsafe void WriteMultiMergeInner(
+ string eventName,
+ ref EventSourceOptions options,
+ TraceLoggingEventTypes eventTypes,
+ Guid* activityID,
+ Guid* childActivityID,
+ params object[] values)
+ {
+#if FEATURE_MANAGED_ETW
+ int identity = 0;
+ byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0
+ ? options.level
+ : eventTypes.level;
+ byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0
+ ? options.opcode
+ : eventTypes.opcode;
+ EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0
+ ? options.tags
+ : eventTypes.Tags;
+ EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0
+ ? options.keywords
+ : eventTypes.keywords;
+
+ var nameInfo = eventTypes.GetNameInfo(eventName ?? eventTypes.Name, tags);
+ if (nameInfo == null)
+ {
+ return;
+ }
+ identity = nameInfo.identity;
+ EventDescriptor descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
+
+ var pinCount = eventTypes.pinCount;
+ var scratch = stackalloc byte[eventTypes.scratchSize];
+ var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
+ var pins = stackalloc GCHandle[pinCount];
+
+ fixed (byte*
+ pMetadata0 = this.providerMetadata,
+ pMetadata1 = nameInfo.nameMetadata,
+ pMetadata2 = eventTypes.typeMetadata)
+ {
+ descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2);
+ descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
+ descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
+
+#if (!ES_BUILD_PCL && !PROJECTN)
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
+#endif
+ try
+ {
+ DataCollector.ThreadInstance.Enable(
+ scratch,
+ eventTypes.scratchSize,
+ descriptors + 3,
+ eventTypes.dataCount,
+ pins,
+ pinCount);
+
+ for (int i = 0; i < eventTypes.typeInfos.Length; i++)
+ {
+ var info = eventTypes.typeInfos[i];
+ info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(values[i]));
+ }
+
+ this.WriteEventRaw(
+ eventName,
+ ref descriptor,
+ activityID,
+ childActivityID,
+ (int)(DataCollector.ThreadInstance.Finish() - descriptors),
+ (IntPtr)descriptors);
+ }
+ finally
+ {
+ this.WriteCleanup(pins, pinCount);
+ }
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ /// <summary>
+ /// Writes an extended event, where the values of the event have already
+ /// been serialized in "data".
+ /// </summary>
+ /// <param name="eventName">
+ /// The name for the event. If null, the name from eventTypes is used.
+ /// (Note that providing the event name via the name parameter is slightly
+ /// less efficient than using the name from eventTypes.)
+ /// </param>
+ /// <param name="options">
+ /// Optional overrides for the event, such as the level, keyword, opcode,
+ /// activityId, and relatedActivityId. Any settings not specified by options
+ /// are obtained from eventTypes.
+ /// </param>
+ /// <param name="eventTypes">
+ /// Information about the event and the types of the values in the event.
+ /// Must not be null. Note that the eventTypes object should be created once and
+ /// saved. It should not be recreated for each event.
+ /// </param>
+ /// <param name="activityID">
+ /// A pointer to the activity ID GUID to log
+ /// </param>
+ /// <param name="childActivityID">
+ /// A pointer to the child activity ID to log (can be null)
+ /// </param>
+ /// <param name="data">
+ /// The previously serialized values to include in the event. Must not be null.
+ /// The number and types of the values must match the number and types of the
+ /// fields described by the eventTypes parameter.
+ /// </param>
+ [SecuritySafeCritical]
+ internal unsafe void WriteMultiMerge(
+ string eventName,
+ ref EventSourceOptions options,
+ TraceLoggingEventTypes eventTypes,
+ Guid* activityID,
+ Guid* childActivityID,
+ EventData* data)
+ {
+#if FEATURE_MANAGED_ETW
+ if (!this.IsEnabled())
+ {
+ return;
+ }
+
+ fixed (EventSourceOptions* pOptions = &options)
+ {
+ EventDescriptor descriptor;
+ var nameInfo = this.UpdateDescriptor(eventName, eventTypes, ref options, out descriptor);
+ if (nameInfo == null)
+ {
+ return;
+ }
+
+ // We make a descriptor for each EventData, and because we morph strings to counted strings
+ // we may have 2 for each arg, so we allocate enough for this.
+ var descriptors = stackalloc EventData[eventTypes.dataCount + eventTypes.typeInfos.Length * 2 + 3];
+
+ fixed (byte*
+ pMetadata0 = this.providerMetadata,
+ pMetadata1 = nameInfo.nameMetadata,
+ pMetadata2 = eventTypes.typeMetadata)
+ {
+ descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2);
+ descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
+ descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
+ int numDescrs = 3;
+
+ for (int i = 0; i < eventTypes.typeInfos.Length; i++)
+ {
+ // Until M3, we need to morph strings to a counted representation
+ // When TDH supports null terminated strings, we can remove this.
+ if (eventTypes.typeInfos[i].DataType == typeof(string))
+ {
+ // Write out the size of the string
+ descriptors[numDescrs].m_Ptr = (long)&descriptors[numDescrs + 1].m_Size;
+ descriptors[numDescrs].m_Size = 2;
+ numDescrs++;
+
+ descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
+ descriptors[numDescrs].m_Size = data[i].m_Size - 2; // Remove the null terminator
+ numDescrs++;
+ }
+ else
+ {
+ descriptors[numDescrs].m_Ptr = data[i].m_Ptr;
+ descriptors[numDescrs].m_Size = data[i].m_Size;
+
+ // old conventions for bool is 4 bytes, but meta-data assumes 1.
+ if (data[i].m_Size == 4 && eventTypes.typeInfos[i].DataType == typeof(bool))
+ descriptors[numDescrs].m_Size = 1;
+
+ numDescrs++;
+ }
+ }
+
+ this.WriteEventRaw(
+ eventName,
+ ref descriptor,
+ activityID,
+ childActivityID,
+ numDescrs,
+ (IntPtr)descriptors);
+ }
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ [SecuritySafeCritical]
+ private unsafe void WriteImpl(
+ string eventName,
+ ref EventSourceOptions options,
+ object data,
+ Guid* pActivityId,
+ Guid* pRelatedActivityId,
+ TraceLoggingEventTypes eventTypes)
+ {
+ try
+ {
+ fixed (EventSourceOptions* pOptions = &options)
+ {
+ EventDescriptor descriptor;
+ options.Opcode = options.IsOpcodeSet ? options.Opcode : GetOpcodeWithDefault(options.Opcode, eventName);
+ var nameInfo = this.UpdateDescriptor(eventName, eventTypes, ref options, out descriptor);
+ if (nameInfo == null)
+ {
+ return;
+ }
+
+#if FEATURE_MANAGED_ETW
+ var pinCount = eventTypes.pinCount;
+ var scratch = stackalloc byte[eventTypes.scratchSize];
+ var descriptors = stackalloc EventData[eventTypes.dataCount + 3];
+ var pins = stackalloc GCHandle[pinCount];
+
+ fixed (byte*
+ pMetadata0 = this.providerMetadata,
+ pMetadata1 = nameInfo.nameMetadata,
+ pMetadata2 = eventTypes.typeMetadata)
+ {
+ descriptors[0].SetMetadata(pMetadata0, this.providerMetadata.Length, 2);
+ descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
+ descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
+#endif // FEATURE_MANAGED_ETW
+
+#if (!ES_BUILD_PCL && !PROJECTN)
+ System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
+#endif
+ EventOpcode opcode = (EventOpcode)descriptor.Opcode;
+
+ Guid activityId = Guid.Empty;
+ Guid relatedActivityId = Guid.Empty;
+ if (pActivityId == null && pRelatedActivityId == null &&
+ ((options.ActivityOptions & EventActivityOptions.Disable) == 0))
+ {
+ if (opcode == EventOpcode.Start)
+ {
+ m_activityTracker.OnStart(m_name, eventName, 0, ref activityId, ref relatedActivityId, options.ActivityOptions);
+ }
+ else if (opcode == EventOpcode.Stop)
+ {
+ m_activityTracker.OnStop(m_name, eventName, 0, ref activityId);
+ }
+ if (activityId != Guid.Empty)
+ pActivityId = &activityId;
+ if (relatedActivityId != Guid.Empty)
+ pRelatedActivityId = &relatedActivityId;
+ }
+
+ try
+ {
+#if FEATURE_MANAGED_ETW
+ DataCollector.ThreadInstance.Enable(
+ scratch,
+ eventTypes.scratchSize,
+ descriptors + 3,
+ eventTypes.dataCount,
+ pins,
+ pinCount);
+
+ var info = eventTypes.typeInfos[0];
+ info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(data));
+
+ this.WriteEventRaw(
+ eventName,
+ ref descriptor,
+ pActivityId,
+ pRelatedActivityId,
+ (int)(DataCollector.ThreadInstance.Finish() - descriptors),
+ (IntPtr)descriptors);
+#endif // FEATURE_MANAGED_ETW
+
+ // TODO enable filtering for listeners.
+ if (m_Dispatchers != null)
+ {
+ var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data));
+ WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData);
+ }
+
+ }
+ catch (Exception ex)
+ {
+ if (ex is EventSourceException)
+ throw;
+ else
+ ThrowEventSourceException(eventName, ex);
+ }
+#if FEATURE_MANAGED_ETW
+ finally
+ {
+ this.WriteCleanup(pins, pinCount);
+ }
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+ }
+ catch (Exception ex)
+ {
+ if (ex is EventSourceException)
+ throw;
+ else
+ ThrowEventSourceException(eventName, ex);
+ }
+ }
+
+ [SecurityCritical]
+ private unsafe void WriteToAllListeners(string eventName, ref EventDescriptor eventDescriptor, EventTags tags, Guid* pActivityId, EventPayload payload)
+ {
+ EventWrittenEventArgs eventCallbackArgs = new EventWrittenEventArgs(this);
+ eventCallbackArgs.EventName = eventName;
+ eventCallbackArgs.m_level = (EventLevel) eventDescriptor.Level;
+ eventCallbackArgs.m_keywords = (EventKeywords) eventDescriptor.Keywords;
+ eventCallbackArgs.m_opcode = (EventOpcode) eventDescriptor.Opcode;
+ eventCallbackArgs.m_tags = tags;
+
+ // Self described events do not have an id attached. We mark it internally with -1.
+ eventCallbackArgs.EventId = -1;
+ if (pActivityId != null)
+ eventCallbackArgs.RelatedActivityId = *pActivityId;
+
+ if (payload != null)
+ {
+ eventCallbackArgs.Payload = new ReadOnlyCollection<object>((IList<object>)payload.Values);
+ eventCallbackArgs.PayloadNames = new ReadOnlyCollection<string>((IList<string>)payload.Keys);
+ }
+
+ DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
+ }
+
+#if (!ES_BUILD_PCL && !PROJECTN)
+ [System.Runtime.ConstrainedExecution.ReliabilityContract(
+ System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState,
+ System.Runtime.ConstrainedExecution.Cer.Success)]
+#endif
+ [SecurityCritical]
+ [NonEvent]
+ private unsafe void WriteCleanup(GCHandle* pPins, int cPins)
+ {
+ DataCollector.ThreadInstance.Disable();
+
+ for (int i = 0; i != cPins; i++)
+ {
+ if (IntPtr.Zero != (IntPtr)pPins[i])
+ {
+ pPins[i].Free();
+ }
+ }
+ }
+
+ private void InitializeProviderMetadata()
+ {
+#if FEATURE_MANAGED_ETW
+ if (m_traits != null)
+ {
+ List<byte> traitMetaData = new List<byte>(100);
+ for (int i = 0; i < m_traits.Length - 1; i += 2)
+ {
+ if (m_traits[i].StartsWith("ETW_", StringComparison.Ordinal))
+ {
+ string etwTrait = m_traits[i].Substring(4);
+ byte traitNum;
+ if (!byte.TryParse(etwTrait, out traitNum))
+ {
+ if (etwTrait == "GROUP")
+ {
+ traitNum = 1;
+ }
+ else
+ {
+ throw new ArgumentException(Resources.GetResourceString("UnknownEtwTrait", etwTrait), "traits");
+ }
+ }
+ string value = m_traits[i + 1];
+ int lenPos = traitMetaData.Count;
+ traitMetaData.Add(0); // Emit size (to be filled in later)
+ traitMetaData.Add(0);
+ traitMetaData.Add(traitNum); // Emit Trait number
+ var valueLen = AddValueToMetaData(traitMetaData, value) + 3; // Emit the value bytes +3 accounts for 3 bytes we emited above.
+ traitMetaData[lenPos] = unchecked((byte)valueLen); // Fill in size
+ traitMetaData[lenPos + 1] = unchecked((byte)(valueLen >> 8));
+ }
+ }
+ providerMetadata = Statics.MetadataForString(this.Name, 0, traitMetaData.Count, 0);
+ int startPos = providerMetadata.Length - traitMetaData.Count;
+ foreach (var b in traitMetaData)
+ providerMetadata[startPos++] = b;
+ }
+ else
+ providerMetadata = Statics.MetadataForString(this.Name, 0, 0, 0);
+#endif //FEATURE_MANAGED_ETW
+ }
+
+ private static int AddValueToMetaData(List<byte> metaData, string value)
+ {
+ if (value.Length == 0)
+ return 0;
+
+ int startPos = metaData.Count;
+ char firstChar = value[0];
+
+ if (firstChar == '@')
+ metaData.AddRange(Encoding.UTF8.GetBytes(value.Substring(1)));
+ else if (firstChar == '{')
+ metaData.AddRange(new Guid(value).ToByteArray());
+ else if (firstChar == '#')
+ {
+ for (int i = 1; i < value.Length; i++)
+ {
+ if (value[i] != ' ') // Skip spaces between bytes.
+ {
+ if (!(i + 1 < value.Length))
+ {
+ throw new ArgumentException(Resources.GetResourceString("EvenHexDigits"), "traits");
+ }
+ metaData.Add((byte)(HexDigit(value[i]) * 16 + HexDigit(value[i + 1])));
+ i++;
+ }
+ }
+ }
+ else if ('A' <= firstChar || ' ' == firstChar) // Is it alphabetic or space (excludes digits and most punctuation).
+ {
+ metaData.AddRange(Encoding.UTF8.GetBytes(value));
+ }
+ else
+ {
+ throw new ArgumentException(Resources.GetResourceString("IllegalValue", value), "traits");
+ }
+
+ return metaData.Count - startPos;
+ }
+
+ /// <summary>
+ /// Returns a value 0-15 if 'c' is a hexadecimal digit. If it throws an argument exception.
+ /// </summary>
+ private static int HexDigit(char c)
+ {
+ if ('0' <= c && c <= '9')
+ {
+ return (c - '0');
+ }
+ if ('a' <= c)
+ {
+ c = unchecked((char)(c - ('a' - 'A'))); // Convert to lower case
+ }
+ if ('A' <= c && c <= 'F')
+ {
+ return (c - 'A' + 10);
+ }
+
+ throw new ArgumentException(Resources.GetResourceString("BadHexDigit", c), "traits");
+ }
+
+ private NameInfo UpdateDescriptor(
+ string name,
+ TraceLoggingEventTypes eventInfo,
+ ref EventSourceOptions options,
+ out EventDescriptor descriptor)
+ {
+ NameInfo nameInfo = null;
+ int identity = 0;
+ byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0
+ ? options.level
+ : eventInfo.level;
+ byte opcode = (options.valuesSet & EventSourceOptions.opcodeSet) != 0
+ ? options.opcode
+ : eventInfo.opcode;
+ EventTags tags = (options.valuesSet & EventSourceOptions.tagsSet) != 0
+ ? options.tags
+ : eventInfo.Tags;
+ EventKeywords keywords = (options.valuesSet & EventSourceOptions.keywordsSet) != 0
+ ? options.keywords
+ : eventInfo.keywords;
+
+ if (this.IsEnabled((EventLevel)level, keywords))
+ {
+ nameInfo = eventInfo.GetNameInfo(name ?? eventInfo.Name, tags);
+ identity = nameInfo.identity;
+ }
+
+ descriptor = new EventDescriptor(identity, level, opcode, (long)keywords);
+ return nameInfo;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTraits.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTraits.cs
new file mode 100644
index 0000000000..e808a8823c
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTraits.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Tags are flags that are not interpreted by EventSource but are passed along
+ /// to the EventListener. The EventListener determines the semantics of the flags.
+ /// </summary>
+ [Flags]
+ public enum EventTags
+ {
+ /// <summary>
+ /// No special traits are added to the event.
+ /// </summary>
+ None = 0,
+
+ /* Bits below 0x10000 are available for any use by the provider. */
+ /* Bits at or above 0x10000 are reserved for definition by Microsoft. */
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs
new file mode 100644
index 0000000000..4e33e58a82
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingEventTypes.cs
@@ -0,0 +1,262 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using Interlocked = System.Threading.Interlocked;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: Used when calling EventSource.WriteMultiMerge.
+ /// Stores the type information to use when writing the event fields.
+ /// </summary>
+ public class TraceLoggingEventTypes
+ {
+ internal readonly TraceLoggingTypeInfo[] typeInfos;
+ internal readonly string name;
+ internal readonly EventTags tags;
+ internal readonly byte level;
+ internal readonly byte opcode;
+ internal readonly EventKeywords keywords;
+ internal readonly byte[] typeMetadata;
+ internal readonly int scratchSize;
+ internal readonly int dataCount;
+ internal readonly int pinCount;
+ private ConcurrentSet<KeyValuePair<string, EventTags>, NameInfo> nameInfos;
+
+ /// <summary>
+ /// Initializes a new instance of TraceLoggingEventTypes corresponding
+ /// to the name, flags, and types provided. Always uses the default
+ /// TypeInfo for each Type.
+ /// </summary>
+ /// <param name="name">
+ /// The name to use when the name parameter passed to
+ /// EventSource.Write is null. This value must not be null.
+ /// </param>
+ /// <param name="tags">
+ /// Tags to add to the event if the tags are not set via options.
+ /// </param>
+ /// <param name="types">
+ /// The types of the fields in the event. This value must not be null.
+ /// </param>
+ internal TraceLoggingEventTypes(
+ string name,
+ EventTags tags,
+ params Type[] types)
+ : this(tags, name, MakeArray(types))
+ {
+ return;
+ }
+
+ /// <summary>
+ /// Returns a new instance of TraceLoggingEventInfo corresponding to the name,
+ /// flags, and typeInfos provided.
+ /// </summary>
+ /// <param name="name">
+ /// The name to use when the name parameter passed to
+ /// EventSource.Write is null. This value must not be null.
+ /// </param>
+ /// <param name="tags">
+ /// Tags to add to the event if the tags are not set via options.
+ /// </param>
+ /// <param name="typeInfos">
+ /// The types of the fields in the event. This value must not be null.
+ /// </param>
+ /// <returns>
+ /// An instance of TraceLoggingEventInfo with DefaultName set to the specified name
+ /// and with the specified typeInfos.
+ /// </returns>
+ internal TraceLoggingEventTypes(
+ string name,
+ EventTags tags,
+ params TraceLoggingTypeInfo[] typeInfos)
+ : this(tags, name, MakeArray(typeInfos))
+ {
+ return;
+ }
+
+ internal TraceLoggingEventTypes(
+ string name,
+ EventTags tags,
+ System.Reflection.ParameterInfo[] paramInfos)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ Contract.EndContractBlock();
+
+ this.typeInfos = MakeArray(paramInfos);
+ this.name = name;
+ this.tags = tags;
+ this.level = Statics.DefaultLevel;
+
+ var collector = new TraceLoggingMetadataCollector();
+ for (int i = 0; i < typeInfos.Length; ++i)
+ {
+ var typeInfo = typeInfos[i];
+ this.level = Statics.Combine((int)typeInfo.Level, this.level);
+ this.opcode = Statics.Combine((int)typeInfo.Opcode, this.opcode);
+ this.keywords |= typeInfo.Keywords;
+ var paramName = paramInfos[i].Name;
+ if (Statics.ShouldOverrideFieldName(paramName))
+ {
+ paramName = typeInfo.Name;
+ }
+ typeInfo.WriteMetadata(collector, paramName, EventFieldFormat.Default);
+ }
+
+ this.typeMetadata = collector.GetMetadata();
+ this.scratchSize = collector.ScratchSize;
+ this.dataCount = collector.DataCount;
+ this.pinCount = collector.PinCount;
+ }
+
+ private TraceLoggingEventTypes(
+ EventTags tags,
+ string defaultName,
+ TraceLoggingTypeInfo[] typeInfos)
+ {
+ if (defaultName == null)
+ {
+ throw new ArgumentNullException("defaultName");
+ }
+
+ Contract.EndContractBlock();
+
+ this.typeInfos = typeInfos;
+ this.name = defaultName;
+ this.tags = tags;
+ this.level = Statics.DefaultLevel;
+
+ var collector = new TraceLoggingMetadataCollector();
+ foreach (var typeInfo in typeInfos)
+ {
+ this.level = Statics.Combine((int)typeInfo.Level, this.level);
+ this.opcode = Statics.Combine((int)typeInfo.Opcode, this.opcode);
+ this.keywords |= typeInfo.Keywords;
+ typeInfo.WriteMetadata(collector, null, EventFieldFormat.Default);
+ }
+
+ this.typeMetadata = collector.GetMetadata();
+ this.scratchSize = collector.ScratchSize;
+ this.dataCount = collector.DataCount;
+ this.pinCount = collector.PinCount;
+ }
+
+ /// <summary>
+ /// Gets the default name that will be used for events with this descriptor.
+ /// </summary>
+ internal string Name
+ {
+ get { return this.name; }
+ }
+
+ /// <summary>
+ /// Gets the default level that will be used for events with this descriptor.
+ /// </summary>
+ internal EventLevel Level
+ {
+ get { return (EventLevel)this.level; }
+ }
+
+ /// <summary>
+ /// Gets the default opcode that will be used for events with this descriptor.
+ /// </summary>
+ internal EventOpcode Opcode
+ {
+ get { return (EventOpcode)this.opcode; }
+ }
+
+ /// <summary>
+ /// Gets the default set of keywords that will added to events with this descriptor.
+ /// </summary>
+ internal EventKeywords Keywords
+ {
+ get { return (EventKeywords)this.keywords; }
+ }
+
+ /// <summary>
+ /// Gets the default tags that will be added events with this descriptor.
+ /// </summary>
+ internal EventTags Tags
+ {
+ get { return this.tags; }
+ }
+
+ internal NameInfo GetNameInfo(string name, EventTags tags)
+ {
+ var ret = this.nameInfos.TryGet(new KeyValuePair<string, EventTags>(name, tags));
+ if (ret == null)
+ {
+ ret = this.nameInfos.GetOrAdd(new NameInfo(name, tags, this.typeMetadata.Length));
+ }
+
+ return ret;
+ }
+
+ private TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[] paramInfos)
+ {
+ if (paramInfos == null)
+ {
+ throw new ArgumentNullException("paramInfos");
+ }
+
+ Contract.EndContractBlock();
+
+ var recursionCheck = new List<Type>(paramInfos.Length);
+ var result = new TraceLoggingTypeInfo[paramInfos.Length];
+ for (int i = 0; i < paramInfos.Length; ++i)
+ {
+ result[i] = TraceLoggingTypeInfo.GetInstance(paramInfos[i].ParameterType, recursionCheck);
+ }
+
+ return result;
+ }
+
+ private static TraceLoggingTypeInfo[] MakeArray(Type[] types)
+ {
+ if (types == null)
+ {
+ throw new ArgumentNullException("types");
+ }
+
+ Contract.EndContractBlock();
+
+ var recursionCheck = new List<Type>(types.Length);
+ var result = new TraceLoggingTypeInfo[types.Length];
+ for (int i = 0; i < types.Length; i++)
+ {
+ result[i] = TraceLoggingTypeInfo.GetInstance(types[i], recursionCheck);
+ }
+
+ return result;
+ }
+
+ private static TraceLoggingTypeInfo[] MakeArray(
+ TraceLoggingTypeInfo[] typeInfos)
+ {
+ if (typeInfos == null)
+ {
+ throw new ArgumentNullException("typeInfos");
+ }
+
+ Contract.EndContractBlock();
+
+ return (TraceLoggingTypeInfo[])typeInfos.Clone(); ;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs
new file mode 100644
index 0000000000..0467ec43e5
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingMetadataCollector.cs
@@ -0,0 +1,370 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: used when implementing a custom TraceLoggingTypeInfo.
+ /// An instance of this type is provided to the TypeInfo.WriteMetadata method.
+ /// </summary>
+ internal class TraceLoggingMetadataCollector
+ {
+ private readonly Impl impl;
+ private readonly FieldMetadata currentGroup;
+ private int bufferedArrayFieldCount = int.MinValue;
+
+ /// <summary>
+ /// Creates a root-level collector.
+ /// </summary>
+ internal TraceLoggingMetadataCollector()
+ {
+ this.impl = new Impl();
+ }
+
+ /// <summary>
+ /// Creates a collector for a group.
+ /// </summary>
+ /// <param name="other">Parent collector</param>
+ /// <param name="group">The field that starts the group</param>
+ private TraceLoggingMetadataCollector(
+ TraceLoggingMetadataCollector other,
+ FieldMetadata group)
+ {
+ this.impl = other.impl;
+ this.currentGroup = group;
+ }
+
+ /// <summary>
+ /// The field tags to be used for the next field.
+ /// This will be reset to None each time a field is written.
+ /// </summary>
+ internal EventFieldTags Tags
+ {
+ get;
+ set;
+ }
+
+ internal int ScratchSize
+ {
+ get { return this.impl.scratchSize; }
+ }
+
+ internal int DataCount
+ {
+ get { return this.impl.dataCount; }
+ }
+
+ internal int PinCount
+ {
+ get { return this.impl.pinCount; }
+ }
+
+ private bool BeginningBufferedArray
+ {
+ get { return this.bufferedArrayFieldCount == 0; }
+ }
+
+ /// <summary>
+ /// Call this method to add a group to the event and to return
+ /// a new metadata collector that can be used to add fields to the
+ /// group. After all of the fields in the group have been written,
+ /// switch back to the original metadata collector to add fields
+ /// outside of the group.
+ /// Special-case: if name is null, no group is created, and AddGroup
+ /// returns the original metadata collector. This is useful when
+ /// adding the top-level group for an event.
+ /// Note: do not use the original metadata collector while the group's
+ /// metadata collector is in use, and do not use the group's metadata
+ /// collector after switching back to the original.
+ /// </summary>
+ /// <param name="name">
+ /// The name of the group. If name is null, the call to AddGroup is a
+ /// no-op (collector.AddGroup(null) returns collector).
+ /// </param>
+ /// <returns>
+ /// A new metadata collector that can be used to add fields to the group.
+ /// </returns>
+ public TraceLoggingMetadataCollector AddGroup(string name)
+ {
+ TraceLoggingMetadataCollector result = this;
+
+ if (name != null || // Normal.
+ this.BeginningBufferedArray) // Error, FieldMetadata's constructor will throw the appropriate exception.
+ {
+ var newGroup = new FieldMetadata(
+ name,
+ TraceLoggingDataType.Struct,
+ this.Tags,
+ this.BeginningBufferedArray);
+ this.AddField(newGroup);
+ result = new TraceLoggingMetadataCollector(this, newGroup);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Adds a scalar field to an event.
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">
+ /// The type code for the added field. This must be a fixed-size type
+ /// (e.g. string types are not supported).
+ /// </param>
+ public void AddScalar(string name, TraceLoggingDataType type)
+ {
+ int size;
+ switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
+ {
+ case TraceLoggingDataType.Int8:
+ case TraceLoggingDataType.UInt8:
+ case TraceLoggingDataType.Char8:
+ size = 1;
+ break;
+ case TraceLoggingDataType.Int16:
+ case TraceLoggingDataType.UInt16:
+ case TraceLoggingDataType.Char16:
+ size = 2;
+ break;
+ case TraceLoggingDataType.Int32:
+ case TraceLoggingDataType.UInt32:
+ case TraceLoggingDataType.HexInt32:
+ case TraceLoggingDataType.Float:
+ case TraceLoggingDataType.Boolean32:
+ size = 4;
+ break;
+ case TraceLoggingDataType.Int64:
+ case TraceLoggingDataType.UInt64:
+ case TraceLoggingDataType.HexInt64:
+ case TraceLoggingDataType.Double:
+ case TraceLoggingDataType.FileTime:
+ size = 8;
+ break;
+ case TraceLoggingDataType.Guid:
+ case TraceLoggingDataType.SystemTime:
+ size = 16;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("type");
+ }
+
+ this.impl.AddScalar(size);
+ this.AddField(new FieldMetadata(name, type, this.Tags, this.BeginningBufferedArray));
+ }
+
+ /// <summary>
+ /// Adds a binary-format field to an event.
+ /// Compatible with core types: Binary, CountedUtf16String, CountedMbcsString.
+ /// Compatible with dataCollector methods: AddBinary(string), AddArray(Any8bitType[]).
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">
+ /// The type code for the added field. This must be a Binary or CountedString type.
+ /// </param>
+ public void AddBinary(string name, TraceLoggingDataType type)
+ {
+ switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
+ {
+ case TraceLoggingDataType.Binary:
+ case TraceLoggingDataType.CountedMbcsString:
+ case TraceLoggingDataType.CountedUtf16String:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("type");
+ }
+
+ this.impl.AddScalar(2);
+ this.impl.AddNonscalar();
+ this.AddField(new FieldMetadata(name, type, this.Tags, this.BeginningBufferedArray));
+ }
+
+ /// <summary>
+ /// Adds an array field to an event.
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">
+ /// The type code for the added field. This must be a fixed-size type
+ /// or a string type. In the case of a string type, this adds an array
+ /// of characters, not an array of strings.
+ /// </param>
+ public void AddArray(string name, TraceLoggingDataType type)
+ {
+ switch ((TraceLoggingDataType)((int)type & Statics.InTypeMask))
+ {
+ case TraceLoggingDataType.Utf16String:
+ case TraceLoggingDataType.MbcsString:
+ case TraceLoggingDataType.Int8:
+ case TraceLoggingDataType.UInt8:
+ case TraceLoggingDataType.Int16:
+ case TraceLoggingDataType.UInt16:
+ case TraceLoggingDataType.Int32:
+ case TraceLoggingDataType.UInt32:
+ case TraceLoggingDataType.Int64:
+ case TraceLoggingDataType.UInt64:
+ case TraceLoggingDataType.Float:
+ case TraceLoggingDataType.Double:
+ case TraceLoggingDataType.Boolean32:
+ case TraceLoggingDataType.Guid:
+ case TraceLoggingDataType.FileTime:
+ case TraceLoggingDataType.HexInt32:
+ case TraceLoggingDataType.HexInt64:
+ case TraceLoggingDataType.Char16:
+ case TraceLoggingDataType.Char8:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException("type");
+ }
+
+ if (this.BeginningBufferedArray)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+ }
+
+ this.impl.AddScalar(2);
+ this.impl.AddNonscalar();
+ this.AddField(new FieldMetadata(name, type, this.Tags, true));
+ }
+
+ public void BeginBufferedArray()
+ {
+ if (this.bufferedArrayFieldCount >= 0)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+ }
+
+ this.bufferedArrayFieldCount = 0;
+ this.impl.BeginBuffered();
+ }
+
+ public void EndBufferedArray()
+ {
+ if (this.bufferedArrayFieldCount != 1)
+ {
+ throw new InvalidOperationException(Resources.GetResourceString("EventSource_IncorrentlyAuthoredTypeInfo"));
+ }
+
+ this.bufferedArrayFieldCount = int.MinValue;
+ this.impl.EndBuffered();
+ }
+
+ /// <summary>
+ /// Adds a custom-serialized field to an event.
+ /// </summary>
+ /// <param name="name">
+ /// The name to use for the added field. This value must not be null.
+ /// </param>
+ /// <param name="type">The encoding type for the field.</param>
+ /// <param name="metadata">Additional information needed to decode the field, if any.</param>
+ public void AddCustom(string name, TraceLoggingDataType type, byte[] metadata)
+ {
+ if (this.BeginningBufferedArray)
+ {
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedCustomSerializedData"));
+ }
+
+ this.impl.AddScalar(2);
+ this.impl.AddNonscalar();
+ this.AddField(new FieldMetadata(
+ name,
+ type,
+ this.Tags,
+ metadata));
+ }
+
+ internal byte[] GetMetadata()
+ {
+ var size = this.impl.Encode(null);
+ var metadata = new byte[size];
+ this.impl.Encode(metadata);
+ return metadata;
+ }
+
+ private void AddField(FieldMetadata fieldMetadata)
+ {
+ this.Tags = EventFieldTags.None;
+ this.bufferedArrayFieldCount++;
+ this.impl.fields.Add(fieldMetadata);
+
+ if (this.currentGroup != null)
+ {
+ this.currentGroup.IncrementStructFieldCount();
+ }
+ }
+
+ private class Impl
+ {
+ internal readonly List<FieldMetadata> fields = new List<FieldMetadata>();
+ internal short scratchSize;
+ internal sbyte dataCount;
+ internal sbyte pinCount;
+ private int bufferNesting;
+ private bool scalar;
+
+ public void AddScalar(int size)
+ {
+ if (this.bufferNesting == 0)
+ {
+ if (!this.scalar)
+ {
+ this.dataCount = checked((sbyte)(this.dataCount + 1));
+ }
+
+ this.scalar = true;
+ this.scratchSize = checked((short)(this.scratchSize + size));
+ }
+ }
+
+ public void AddNonscalar()
+ {
+ if (this.bufferNesting == 0)
+ {
+ this.scalar = false;
+ this.pinCount = checked((sbyte)(this.pinCount + 1));
+ this.dataCount = checked((sbyte)(this.dataCount + 1));
+ }
+ }
+
+ public void BeginBuffered()
+ {
+ if (this.bufferNesting == 0)
+ {
+ this.AddNonscalar();
+ }
+
+ this.bufferNesting++;
+ }
+
+ public void EndBuffered()
+ {
+ this.bufferNesting--;
+ }
+
+ public int Encode(byte[] metadata)
+ {
+ int size = 0;
+
+ foreach (var field in this.fields)
+ {
+ field.Encode(ref size, metadata);
+ }
+
+ return size;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs
new file mode 100644
index 0000000000..5815d12fb0
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TraceLoggingTypeInfo.cs
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: used when implementing a custom TraceLoggingTypeInfo.
+ /// Non-generic base class for TraceLoggingTypeInfo&lt;DataType>. Do not derive
+ /// from this class. Instead, derive from TraceLoggingTypeInfo&lt;DataType>.
+ /// </summary>
+ internal abstract class TraceLoggingTypeInfo
+ {
+ private readonly string name;
+ private readonly EventKeywords keywords;
+ private readonly EventLevel level = (EventLevel)(-1);
+ private readonly EventOpcode opcode = (EventOpcode)(-1);
+ private readonly EventTags tags;
+ private readonly Type dataType;
+ private readonly Func<object, PropertyValue> propertyValueFactory;
+
+ internal TraceLoggingTypeInfo(Type dataType)
+ {
+ if (dataType == null)
+ {
+ throw new ArgumentNullException("dataType");
+ }
+
+ Contract.EndContractBlock();
+
+ this.name = dataType.Name;
+ this.dataType = dataType;
+ this.propertyValueFactory = PropertyValue.GetFactory(dataType);
+ }
+
+ internal TraceLoggingTypeInfo(
+ Type dataType,
+ string name,
+ EventLevel level,
+ EventOpcode opcode,
+ EventKeywords keywords,
+ EventTags tags)
+ {
+ if (dataType == null)
+ {
+ throw new ArgumentNullException("dataType");
+ }
+
+ if (name == null)
+ {
+ throw new ArgumentNullException("eventName");
+ }
+
+ Contract.EndContractBlock();
+
+ Statics.CheckName(name);
+
+ this.name = name;
+ this.keywords = keywords;
+ this.level = level;
+ this.opcode = opcode;
+ this.tags = tags;
+ this.dataType = dataType;
+ this.propertyValueFactory = PropertyValue.GetFactory(dataType);
+ }
+
+ /// <summary>
+ /// Gets the name to use for the event if this type is the top-level type,
+ /// or the name to use for an implicitly-named field.
+ /// Never null.
+ /// </summary>
+ public string Name
+ {
+ get { return this.name; }
+ }
+
+ /// <summary>
+ /// Gets the event level associated with this type. Any value in the range 0..255
+ /// is an associated event level. Any value outside the range 0..255 is invalid and
+ /// indicates that this type has no associated event level.
+ /// </summary>
+ public EventLevel Level
+ {
+ get { return this.level; }
+ }
+
+ /// <summary>
+ /// Gets the event opcode associated with this type. Any value in the range 0..255
+ /// is an associated event opcode. Any value outside the range 0..255 is invalid and
+ /// indicates that this type has no associated event opcode.
+ /// </summary>
+ public EventOpcode Opcode
+ {
+ get { return this.opcode; }
+ }
+
+ /// <summary>
+ /// Gets the keyword(s) associated with this type.
+ /// </summary>
+ public EventKeywords Keywords
+ {
+ get { return this.keywords; }
+ }
+
+ /// <summary>
+ /// Gets the event tags associated with this type.
+ /// </summary>
+ public EventTags Tags
+ {
+ get { return this.tags; }
+ }
+
+ internal Type DataType
+ {
+ get { return this.dataType; }
+ }
+
+ internal Func<object, PropertyValue> PropertyValueFactory
+ {
+ get { return this.propertyValueFactory; }
+ }
+
+ /// <summary>
+ /// When overridden by a derived class, writes the metadata (schema) for
+ /// this type. Note that the sequence of operations in WriteMetadata should be
+ /// essentially identical to the sequence of operations in
+ /// WriteData/WriteObjectData. Otherwise, the metadata and data will not match,
+ /// which may cause trouble when decoding the event.
+ /// </summary>
+ /// <param name="collector">
+ /// The object that collects metadata for this object's type. Metadata is written
+ /// by calling methods on the collector object. Note that if the type contains
+ /// sub-objects, the implementation of this method may need to call the
+ /// WriteMetadata method for the type of the sub-object, e.g. by calling
+ /// TraceLoggingTypeInfo&lt;SubType&gt;.Instance.WriteMetadata(...).
+ /// </param>
+ /// <param name="name">
+ /// The name of the property that contains an object of this type, or null if this
+ /// object is being written as a top-level object of an event. Typical usage
+ /// is to pass this value to collector.AddGroup.
+ /// </param>
+ /// <param name="format">
+ /// The format attribute for the field that contains an object of this type.
+ /// </param>
+ public abstract void WriteMetadata(
+ TraceLoggingMetadataCollector collector,
+ string name,
+ EventFieldFormat format);
+
+ /// <summary>
+ /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
+ /// method.
+ /// </summary>
+ /// <param name="collector">
+ /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
+ /// method.
+ /// </param>
+ /// <param name="value">
+ /// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
+ /// method.
+ /// </param>
+ public abstract void WriteData(
+ TraceLoggingDataCollector collector,
+ PropertyValue value);
+
+ /// <summary>
+ /// Fetches the event parameter data for internal serialization.
+ /// </summary>
+ /// <param name="value"></param>
+ /// <returns></returns>
+ public virtual object GetData(object value)
+ {
+ return value;
+ }
+
+ [ThreadStatic] // per-thread cache to avoid synchronization
+ private static Dictionary<Type, TraceLoggingTypeInfo> threadCache;
+
+ public static TraceLoggingTypeInfo GetInstance(Type type, List<Type> recursionCheck)
+ {
+ var cache = threadCache ?? (threadCache = new Dictionary<Type, TraceLoggingTypeInfo>());
+
+ TraceLoggingTypeInfo instance;
+ if (!cache.TryGetValue(type, out instance))
+ {
+ if (recursionCheck == null)
+ recursionCheck = new List<Type>();
+ var recursionCheckCount = recursionCheck.Count;
+ instance = Statics.CreateDefaultTypeInfo(type, recursionCheck);
+ cache[type] = instance;
+ recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
+ }
+ return instance;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TypeAnalysis.cs b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TypeAnalysis.cs
new file mode 100644
index 0000000000..42cdde5f6a
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/TraceLogging/TypeAnalysis.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// TraceLogging: stores the per-type information obtained by reflecting over a type.
+ /// </summary>
+ internal sealed class TypeAnalysis
+ {
+ internal readonly PropertyAnalysis[] properties;
+ internal readonly string name;
+ internal readonly EventKeywords keywords;
+ internal readonly EventLevel level = (EventLevel)(-1);
+ internal readonly EventOpcode opcode = (EventOpcode)(-1);
+ internal readonly EventTags tags;
+
+ public TypeAnalysis(
+ Type dataType,
+ EventDataAttribute eventAttrib,
+ List<Type> recursionCheck)
+ {
+ var propertyInfos = Statics.GetProperties(dataType);
+ var propertyList = new List<PropertyAnalysis>();
+
+ foreach (var propertyInfo in propertyInfos)
+ {
+ if (Statics.HasCustomAttribute(propertyInfo, typeof(EventIgnoreAttribute)))
+ {
+ continue;
+ }
+
+ if (!propertyInfo.CanRead ||
+ propertyInfo.GetIndexParameters().Length != 0)
+ {
+ continue;
+ }
+
+ MethodInfo getterInfo = Statics.GetGetMethod(propertyInfo);
+ if (getterInfo == null)
+ {
+ continue;
+ }
+
+ if (getterInfo.IsStatic || !getterInfo.IsPublic)
+ {
+ continue;
+ }
+
+ var propertyType = propertyInfo.PropertyType;
+ var propertyTypeInfo = TraceLoggingTypeInfo.GetInstance(propertyType, recursionCheck);
+ var fieldAttribute = Statics.GetCustomAttribute<EventFieldAttribute>(propertyInfo);
+
+ string propertyName =
+ fieldAttribute != null && fieldAttribute.Name != null
+ ? fieldAttribute.Name
+ : Statics.ShouldOverrideFieldName(propertyInfo.Name)
+ ? propertyTypeInfo.Name
+ : propertyInfo.Name;
+ propertyList.Add(new PropertyAnalysis(
+ propertyName,
+ propertyInfo,
+ propertyTypeInfo,
+ fieldAttribute));
+ }
+
+ this.properties = propertyList.ToArray();
+
+ foreach (var property in this.properties)
+ {
+ var typeInfo = property.typeInfo;
+ this.level = (EventLevel)Statics.Combine((int)typeInfo.Level, (int)this.level);
+ this.opcode = (EventOpcode)Statics.Combine((int)typeInfo.Opcode, (int)this.opcode);
+ this.keywords |= typeInfo.Keywords;
+ this.tags |= typeInfo.Tags;
+ }
+
+ if (eventAttrib != null)
+ {
+ this.level = (EventLevel)Statics.Combine((int)eventAttrib.Level, (int)this.level);
+ this.opcode = (EventOpcode)Statics.Combine((int)eventAttrib.Opcode, (int)this.opcode);
+ this.keywords |= eventAttrib.Keywords;
+ this.tags |= eventAttrib.Tags;
+ this.name = eventAttrib.Name;
+ }
+
+ if (this.name == null)
+ {
+ this.name = dataType.Name;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/Winmeta.cs b/src/mscorlib/src/System/Diagnostics/Eventing/Winmeta.cs
new file mode 100644
index 0000000000..c93e745173
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/Winmeta.cs
@@ -0,0 +1,196 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose:
+** Contains eventing constants defined by the Windows
+** environment.
+**
+============================================================*/
+#if ES_BUILD_STANDALONE
+#define FEATURE_MANAGED_ETW_CHANNELS
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ using System;
+
+ /// <summary>
+ /// WindowsEventLevel. Custom values must be in the range from 16 through 255
+ /// </summary>
+ public enum EventLevel
+ {
+ /// <summary>
+ /// Log always
+ /// </summary>
+ LogAlways = 0,
+ /// <summary>
+ /// Only critical errors
+ /// </summary>
+ Critical,
+ /// <summary>
+ /// All errors, including previous levels
+ /// </summary>
+ Error,
+ /// <summary>
+ /// All warnings, including previous levels
+ /// </summary>
+ Warning,
+ /// <summary>
+ /// All informational events, including previous levels
+ /// </summary>
+ Informational,
+ /// <summary>
+ /// All events, including previous levels
+ /// </summary>
+ Verbose
+ }
+ /// <summary>
+ /// WindowsEventTask. Custom values must be in the range from 1 through 65534
+ /// </summary>
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+#endif
+ public enum EventTask
+ {
+ /// <summary>
+ /// Undefined task
+ /// </summary>
+ None = 0
+ }
+ /// <summary>
+ /// EventOpcode. Custom values must be in the range from 11 through 239
+ /// </summary>
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+#endif
+ public enum EventOpcode
+ {
+ /// <summary>
+ /// An informational event
+ /// </summary>
+ Info = 0,
+ /// <summary>
+ /// An activity start event
+ /// </summary>
+ Start,
+ /// <summary>
+ /// An activity end event
+ /// </summary>
+ Stop,
+ /// <summary>
+ /// A trace collection start event
+ /// </summary>
+ DataCollectionStart,
+ /// <summary>
+ /// A trace collection end event
+ /// </summary>
+ DataCollectionStop,
+ /// <summary>
+ /// An extensional event
+ /// </summary>
+ Extension,
+ /// <summary>
+ /// A reply event
+ /// </summary>
+ Reply,
+ /// <summary>
+ /// An event representing the activity resuming from the suspension
+ /// </summary>
+ Resume,
+ /// <summary>
+ /// An event representing the activity is suspended, pending another activity's completion
+ /// </summary>
+ Suspend,
+ /// <summary>
+ /// An event representing the activity is transferred to another component, and can continue to work
+ /// </summary>
+ Send,
+ /// <summary>
+ /// An event representing receiving an activity transfer from another component
+ /// </summary>
+ Receive = 240
+ }
+
+ // Added for CLR V4
+ /// <summary>
+ /// EventChannel. Custom values must be in the range from 16 through 255. Currently only predefined values allowed.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Backwards compatibility")]
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+#endif
+ public enum EventChannel : byte
+ {
+ /// <summary>
+ /// No channel
+ /// </summary>
+ None = 0,
+ // Channels 1 - 15 are reserved...
+ /// <summary>The admin channel</summary>
+ Admin = 16,
+ /// <summary>The operational channel</summary>
+ Operational = 17,
+ /// <summary>The analytic channel</summary>
+ Analytic = 18,
+ /// <summary>The debug channel</summary>
+ Debug = 19,
+
+ };
+
+ /// <summary>
+ /// EventOpcode
+ /// </summary>
+ [Flags]
+ public enum EventKeywords : long
+ {
+ /// <summary>
+ /// No events.
+ /// </summary>
+ None = 0x0,
+ /// <summary>
+ /// All Events
+ /// </summary>
+ All = ~0,
+ /// <summary>
+ /// Telemetry events
+ /// </summary>
+ MicrosoftTelemetry = 0x02000000000000,
+ /// <summary>
+ /// WDI context events
+ /// </summary>
+ WdiContext = 0x02000000000000,
+ /// <summary>
+ /// WDI diagnostic events
+ /// </summary>
+ WdiDiagnostic = 0x04000000000000,
+ /// <summary>
+ /// SQM events
+ /// </summary>
+ Sqm = 0x08000000000000,
+ /// <summary>
+ /// Failed security audits
+ /// </summary>
+ AuditFailure = 0x10000000000000,
+ /// <summary>
+ /// Successful security audits
+ /// </summary>
+ AuditSuccess = 0x20000000000000,
+ /// <summary>
+ /// Transfer events where the related Activity ID is a computed value and not a GUID
+ /// N.B. The correct value for this field is 0x40000000000000.
+ /// </summary>
+ CorrelationHint = 0x10000000000000,
+ /// <summary>
+ /// Events raised using classic eventlog API
+ /// </summary>
+ EventLogClassic = 0x80000000000000
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs b/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs
new file mode 100644
index 0000000000..d7112fc81b
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Eventing/XplatEventLogger.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Collections.ObjectModel;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+using Contract = System.Diagnostics.Contracts.Contract;
+
+#if FEATURE_EVENTSOURCE_XPLAT
+
+namespace System.Diagnostics.Tracing
+{
+
+ internal class XplatEventLogger : EventListener
+ {
+ private static Lazy<string> eventSourceNameFilter = new Lazy<string>(() => CompatibilitySwitch.GetValueInternal("EventSourceFilter"));
+ private static Lazy<string> eventSourceEventFilter = new Lazy<string>(() => CompatibilitySwitch.GetValueInternal("EventNameFilter"));
+
+ public XplatEventLogger() {}
+
+ private static bool initializedPersistentListener = false;
+
+ [System.Security.SecuritySafeCritical]
+ public static EventListener InitializePersistentListener()
+ {
+ try{
+
+ if (!initializedPersistentListener && XplatEventLogger.IsEventSourceLoggingEnabled())
+ {
+ initializedPersistentListener = true;
+ return new XplatEventLogger();
+ }
+ }
+ catch(Exception){}
+
+ return null;
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern bool IsEventSourceLoggingEnabled();
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void LogEventSource(int eventID, string eventName, string eventSourceName, string payload);
+
+ static List<char> escape_seq = new List<char> { '\b', '\f', '\n', '\r', '\t', '\"', '\\' };
+ static Dictionary<char, string> seq_mapping = new Dictionary<char, string>()
+ {
+ {'\b', "b"},
+ {'\f', "f"},
+ {'\n', "n"},
+ {'\r', "r"},
+ {'\t', "t"},
+ {'\"', "\\\""},
+ {'\\', "\\\\"}
+ };
+
+ private static void minimalJsonserializer(string payload, StringBuilder sb)
+ {
+ foreach( var elem in payload)
+ {
+ if (escape_seq.Contains(elem))
+ {
+ sb.Append("\\\\");
+ sb.Append(seq_mapping[elem]);
+ }
+ else
+ {
+ sb.Append(elem);
+ }
+ }
+ }
+
+ private static string Serialize(ReadOnlyCollection<string> payloadName, ReadOnlyCollection<object> payload, string sep = ", ")
+ {
+
+ if (payloadName == null || payload == null )
+ return String.Empty;
+
+ if (payloadName.Count == 0 || payload.Count == 0)
+ return String.Empty;
+
+ int eventDataCount = payloadName.Count;
+
+ if(payloadName.Count != payload.Count)
+ {
+ eventDataCount = Math.Min(payloadName.Count, payload.Count);
+ }
+
+ var sb = StringBuilderCache.Acquire();
+
+ sb.Append('{');
+ for (int i = 0; i < eventDataCount; i++)
+ {
+ var fieldstr = payloadName[i].ToString();
+
+ sb.Append("\\\"");
+ sb.Append(fieldstr);
+ sb.Append("\\\"");
+ sb.Append(':');
+
+ var valuestr = payload[i] as string;
+
+ if( valuestr != null)
+ {
+ sb.Append("\\\"");
+ minimalJsonserializer(valuestr,sb);
+ sb.Append("\\\"");
+ }
+ else
+ {
+ sb.Append(payload[i].ToString());
+ }
+
+ sb.Append(sep);
+
+ }
+
+ sb.Length -= sep.Length;
+ sb.Append('}');
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ internal protected override void OnEventSourceCreated(EventSource eventSource)
+ {
+ string eventSourceFilter = eventSourceNameFilter.Value;
+ if (String.IsNullOrEmpty(eventSourceFilter) || (eventSource.Name.IndexOf(eventSourceFilter, StringComparison.OrdinalIgnoreCase) >= 0))
+ {
+ EnableEvents(eventSource, EventLevel.LogAlways, EventKeywords.All, null);
+ }
+ }
+
+ internal protected override void OnEventWritten(EventWrittenEventArgs eventData)
+ {
+ string eventFilter = eventSourceEventFilter.Value;
+ if (String.IsNullOrEmpty(eventFilter) || (eventData.EventName.IndexOf(eventFilter, StringComparison.OrdinalIgnoreCase) >= 0))
+ {
+ LogOnEventWritten(eventData);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void LogOnEventWritten(EventWrittenEventArgs eventData)
+ {
+ string payload = "";
+ if (eventData.Payload != null)
+ {
+ try{
+ payload = Serialize(eventData.PayloadNames, eventData.Payload);
+ }
+ catch (Exception ex)
+ {
+ payload = "XplatEventLogger failed with Exception " + ex.ToString();
+ }
+ }
+
+ LogEventSource( eventData.EventId, eventData.EventName,eventData.EventSource.Name,payload);
+ }
+ }
+}
+#endif //FEATURE_EVENTSOURCE_XPLAT
diff --git a/src/mscorlib/src/System/Diagnostics/ICustomDebuggerNotification.cs b/src/mscorlib/src/System/Diagnostics/ICustomDebuggerNotification.cs
new file mode 100644
index 0000000000..29323cea2d
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/ICustomDebuggerNotification.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** This interface is implemented by classes that support custom debugger notifications.
+**
+===========================================================*/
+namespace System.Diagnostics {
+
+ using System;
+ // Defines an interface indicating that a custom debugger notification is requested under specific
+ // conditions. Users should implement this interface to be used as an argument to
+ // System.Diagnostics.Debugger.CustomNotification.
+ internal interface ICustomDebuggerNotification
+ {
+ // Interface does not need to be marked with the serializable attribute
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/LogSwitch.cs b/src/mscorlib/src/System/Diagnostics/LogSwitch.cs
new file mode 100644
index 0000000000..e3e2b867c4
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/LogSwitch.cs
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+ [Serializable]
+ internal class LogSwitch
+ {
+ // ! WARNING !
+ // If any fields are added/deleted/modified, perform the
+ // same in the EE code (debugdebugger.cpp/debugdebugger.h)
+ internal String strName;
+ internal String strDescription;
+ private LogSwitch ParentSwitch;
+ internal volatile LoggingLevels iLevel;
+ internal volatile LoggingLevels iOldLevel;
+
+ // ! END WARNING !
+
+
+ private LogSwitch ()
+ {
+ }
+
+ // Constructs a LogSwitch. A LogSwitch is used to categorize log messages.
+ //
+ // All switches (except for the global LogSwitch) have a parent LogSwitch.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LogSwitch(String name, String description, LogSwitch parent)
+ {
+ if (name != null && name.Length == 0)
+ throw new ArgumentOutOfRangeException("Name", Environment.GetResourceString("Argument_StringZeroLength"));
+ Contract.EndContractBlock();
+
+ if ((name != null) && (parent != null))
+ {
+ strName = name;
+ strDescription = description;
+ iLevel = LoggingLevels.ErrorLevel;
+ iOldLevel = iLevel;
+ ParentSwitch = parent;
+
+ Log.m_Hashtable.Add (strName, this);
+
+ // Call into the EE to let it know about the creation of
+ // this switch
+ Log.AddLogSwitch (this);
+ }
+ else
+ throw new ArgumentNullException ((name==null ? "name" : "parent"));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal LogSwitch(String name, String description)
+ {
+ strName = name;
+ strDescription = description;
+ iLevel = LoggingLevels.ErrorLevel;
+ iOldLevel = iLevel;
+ ParentSwitch = null;
+
+ Log.m_Hashtable.Add (strName, this);
+
+ // Call into the EE to let it know about the creation of
+ // this switch
+ Log.AddLogSwitch (this);
+ }
+
+
+ // Get property returns the name of the switch
+ public virtual String Name
+ {
+ get { return strName;}
+ }
+
+ // Get property returns the description of the switch
+ public virtual String Description
+ {
+ get {return strDescription;}
+ }
+
+
+ // Get property returns the parent of the switch
+ public virtual LogSwitch Parent
+ {
+ get { return ParentSwitch; }
+ }
+
+
+ // Property to Get/Set the level of log messages which are "on" for the switch.
+ //
+ public virtual LoggingLevels MinimumLevel
+ {
+ get { return iLevel; }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ set
+ {
+ iLevel = value;
+ iOldLevel = value;
+ String strParentName = ParentSwitch!=null ? ParentSwitch.Name : "";
+ if (Debugger.IsAttached)
+ Log.ModifyLogSwitch ((int)iLevel, strName, strParentName);
+
+ Log.InvokeLogSwitchLevelHandlers (this, iLevel);
+ }
+ }
+
+
+ // Checks if the given level is "on" for this switch or one of its parents.
+ //
+ public virtual bool CheckLevel(LoggingLevels level)
+ {
+ if (iLevel > level)
+ {
+ // recurse through the list till parent is hit.
+ if (this.ParentSwitch == null)
+ return false;
+ else
+ return this.ParentSwitch.CheckLevel (level);
+ }
+ else
+ return true;
+ }
+
+
+ // Returns a switch with the particular name, if any. Returns null if no
+ // such switch exists.
+ public static LogSwitch GetSwitch(String name)
+ {
+ return (LogSwitch)Log.m_Hashtable[name];
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/LoggingLevels.cs b/src/mscorlib/src/System/Diagnostics/LoggingLevels.cs
new file mode 100644
index 0000000000..0eea0507ec
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/LoggingLevels.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+
+ using System;
+ // Constants representing the importance level of messages to be logged.
+ // This level can be used to organize messages, and also to filter which
+ // messages are displayed.
+ //
+ // An attached debugger can enable or disable which messages will
+ // actually be reported to the user through the COM+ debugger
+ // services API. This info is communicated to the runtime so only
+ // desired events are actually reported to the debugger.
+ // NOTE: The following constants mirror the constants
+ // declared in the EE code (DebugDebugger.h). Any changes here will also
+ // need to be made there.
+ // Constants representing the importance level of messages to be logged.
+ // This level can be used to organize messages, and also to filter which
+ // messages are displayed.
+ [Serializable]
+ internal enum LoggingLevels
+ {
+ TraceLevel0 = 0,
+ TraceLevel1 = 1,
+ TraceLevel2 = 2,
+ TraceLevel3 = 3,
+ TraceLevel4 = 4,
+
+ StatusLevel0 = 20,
+ StatusLevel1 = 21,
+ StatusLevel2 = 22,
+ StatusLevel3 = 23,
+ StatusLevel4 = 24,
+
+
+ WarningLevel = 40,
+
+ ErrorLevel = 50,
+
+ PanicLevel = 100,
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Stackframe.cs b/src/mscorlib/src/System/Diagnostics/Stackframe.cs
new file mode 100644
index 0000000000..397c3e12e6
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Stackframe.cs
@@ -0,0 +1,348 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+
+ using System.Text;
+ using System;
+ using System.IO;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // There is no good reason for the methods of this class to be virtual.
+ // In order to ensure trusted code can trust the data it gets from a
+ // StackTrace, we use an InheritanceDemand to prevent partially-trusted
+ // subclasses.
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class StackFrame
+ {
+ private MethodBase method;
+ private int offset;
+ private int ILOffset;
+ private String strFileName;
+ private int iLineNumber;
+ private int iColumnNumber;
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ [System.Runtime.Serialization.OptionalField]
+ private bool fIsLastFrameFromForeignExceptionStackTrace;
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ internal void InitMembers()
+ {
+ method = null;
+ offset = OFFSET_UNKNOWN;
+ ILOffset = OFFSET_UNKNOWN;
+ strFileName = null;
+ iLineNumber = 0;
+ iColumnNumber = 0;
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ fIsLastFrameFromForeignExceptionStackTrace = false;
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ }
+
+ // Constructs a StackFrame corresponding to the active stack frame.
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public StackFrame()
+ {
+ InitMembers();
+ BuildStackFrame (0 + StackTrace.METHODS_TO_SKIP, false);// iSkipFrames=0
+ }
+
+ // Constructs a StackFrame corresponding to the active stack frame.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public StackFrame(bool fNeedFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame (0 + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);// iSkipFrames=0
+ }
+
+ // Constructs a StackFrame corresponding to a calling stack frame.
+ //
+ public StackFrame(int skipFrames)
+ {
+ InitMembers();
+ BuildStackFrame (skipFrames + StackTrace.METHODS_TO_SKIP, false);
+ }
+
+ // Constructs a StackFrame corresponding to a calling stack frame.
+ //
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public StackFrame(int skipFrames, bool fNeedFileInfo)
+ {
+ InitMembers();
+ BuildStackFrame (skipFrames + StackTrace.METHODS_TO_SKIP, fNeedFileInfo);
+ }
+
+
+ // Called from the class "StackTrace"
+ //
+ internal StackFrame(bool DummyFlag1, bool DummyFlag2)
+ {
+ InitMembers();
+ }
+
+ // Constructs a "fake" stack frame, just containing the given file
+ // name and line number. Use when you don't want to use the
+ // debugger's line mapping logic.
+ //
+ public StackFrame(String fileName, int lineNumber)
+ {
+ InitMembers();
+ BuildStackFrame (StackTrace.METHODS_TO_SKIP, false);
+ strFileName = fileName;
+ iLineNumber = lineNumber;
+ iColumnNumber = 0;
+ }
+
+
+ // Constructs a "fake" stack frame, just containing the given file
+ // name, line number and column number. Use when you don't want to
+ // use the debugger's line mapping logic.
+ //
+ public StackFrame(String fileName, int lineNumber, int colNumber)
+ {
+ InitMembers();
+ BuildStackFrame (StackTrace.METHODS_TO_SKIP, false);
+ strFileName = fileName;
+ iLineNumber = lineNumber;
+ iColumnNumber = colNumber;
+ }
+
+
+ // Constant returned when the native or IL offset is unknown
+ public const int OFFSET_UNKNOWN = -1;
+
+
+ internal virtual void SetMethodBase (MethodBase mb)
+ {
+ method = mb;
+ }
+
+ internal virtual void SetOffset (int iOffset)
+ {
+ offset = iOffset;
+ }
+
+ internal virtual void SetILOffset (int iOffset)
+ {
+ ILOffset = iOffset;
+ }
+
+ internal virtual void SetFileName (String strFName)
+ {
+ strFileName = strFName;
+ }
+
+ internal virtual void SetLineNumber (int iLine)
+ {
+ iLineNumber = iLine;
+ }
+
+ internal virtual void SetColumnNumber (int iCol)
+ {
+ iColumnNumber = iCol;
+ }
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ internal virtual void SetIsLastFrameFromForeignExceptionStackTrace (bool fIsLastFrame)
+ {
+ fIsLastFrameFromForeignExceptionStackTrace = fIsLastFrame;
+ }
+
+ internal virtual bool GetIsLastFrameFromForeignExceptionStackTrace()
+ {
+ return fIsLastFrameFromForeignExceptionStackTrace;
+ }
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ // Returns the method the frame is executing
+ //
+ public virtual MethodBase GetMethod ()
+ {
+ Contract.Ensures(Contract.Result<MethodBase>() != null);
+
+ return method;
+ }
+
+ // Returns the offset from the start of the native (jitted) code for the
+ // method being executed
+ //
+ public virtual int GetNativeOffset ()
+ {
+ return offset;
+ }
+
+
+ // Returns the offset from the start of the IL code for the
+ // method being executed. This offset may be approximate depending
+ // on whether the jitter is generating debuggable code or not.
+ //
+ public virtual int GetILOffset()
+ {
+ return ILOffset;
+ }
+
+ // Returns the file name containing the code being executed. This
+ // information is normally extracted from the debugging symbols
+ // for the executable.
+ //
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public virtual String GetFileName()
+ {
+ if (strFileName != null)
+ {
+ // This isn't really correct, but we don't have
+ // a permission that protects discovery of potentially
+ // local urls so we'll use this.
+
+ FileIOPermission perm = new FileIOPermission( PermissionState.None );
+ perm.AllFiles = FileIOPermissionAccess.PathDiscovery;
+ perm.Demand();
+ }
+
+ return strFileName;
+ }
+
+ // Returns the line number in the file containing the code being executed.
+ // This information is normally extracted from the debugging symbols
+ // for the executable.
+ //
+ public virtual int GetFileLineNumber()
+ {
+ return iLineNumber;
+ }
+
+ // Returns the column number in the line containing the code being executed.
+ // This information is normally extracted from the debugging symbols
+ // for the executable.
+ //
+ public virtual int GetFileColumnNumber()
+ {
+ return iColumnNumber;
+ }
+
+
+ // Builds a readable representation of the stack frame
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder(255);
+
+ if (method != null)
+ {
+ sb.Append(method.Name);
+
+ // deal with the generic portion of the method
+ if (method is MethodInfo && ((MethodInfo)method).IsGenericMethod)
+ {
+ Type[] typars = ((MethodInfo)method).GetGenericArguments();
+
+ sb.Append('<');
+ int k = 0;
+ bool fFirstTyParam = true;
+ while (k < typars.Length)
+ {
+ if (fFirstTyParam == false)
+ sb.Append(',');
+ else
+ fFirstTyParam = false;
+
+ sb.Append(typars[k].Name);
+ k++;
+ }
+
+ sb.Append('>');
+ }
+
+ sb.Append(" at offset ");
+ if (offset == OFFSET_UNKNOWN)
+ sb.Append("<offset unknown>");
+ else
+ sb.Append(offset);
+
+ sb.Append(" in file:line:column ");
+
+ bool useFileName = (strFileName != null);
+
+ if (useFileName)
+ {
+ try
+ {
+ // This isn't really correct, but we don't have
+ // a permission that protects discovery of potentially
+ // local urls so we'll use this.
+
+ FileIOPermission perm = new FileIOPermission(PermissionState.None);
+ perm.AllFiles = FileIOPermissionAccess.PathDiscovery;
+ perm.Demand();
+ }
+ catch (System.Security.SecurityException)
+ {
+ useFileName = false;
+ }
+ }
+
+ if (!useFileName)
+ sb.Append("<filename unknown>");
+ else
+ sb.Append(strFileName);
+ sb.Append(':');
+ sb.Append(iLineNumber);
+ sb.Append(':');
+ sb.Append(iColumnNumber);
+ }
+ else
+ {
+ sb.Append("<null>");
+ }
+ sb.Append(Environment.NewLine);
+
+ return sb.ToString();
+ }
+
+
+ private void BuildStackFrame(int skipFrames, bool fNeedFileInfo)
+ {
+ using (StackFrameHelper StackF = new StackFrameHelper(null))
+ {
+ StackF.InitializeSourceInfo(0, fNeedFileInfo, null);
+
+ int iNumOfFrames = StackF.GetNumberOfFrames();
+
+ skipFrames += StackTrace.CalculateFramesToSkip(StackF, iNumOfFrames);
+
+ if ((iNumOfFrames - skipFrames) > 0)
+ {
+ method = StackF.GetMethodBase(skipFrames);
+ offset = StackF.GetOffset(skipFrames);
+ ILOffset = StackF.GetILOffset(skipFrames);
+ if (fNeedFileInfo)
+ {
+ strFileName = StackF.GetFilename(skipFrames);
+ iLineNumber = StackF.GetLineNumber(skipFrames);
+ iColumnNumber = StackF.GetColumnNumber(skipFrames);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/Stacktrace.cs b/src/mscorlib/src/System/Diagnostics/Stacktrace.cs
new file mode 100644
index 0000000000..047a60f328
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/Stacktrace.cs
@@ -0,0 +1,770 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+ using System;
+ using System.Collections;
+ using System.Text;
+ using System.Threading;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // READ ME:
+ // Modifying the order or fields of this object may require other changes
+ // to the unmanaged definition of the StackFrameHelper class, in
+ // VM\DebugDebugger.h. The binder will catch some of these layout problems.
+ [Serializable]
+ internal class StackFrameHelper : IDisposable
+ {
+ [NonSerialized]
+ private Thread targetThread;
+ private int[] rgiOffset;
+ private int[] rgiILOffset;
+ // this field is here only for backwards compatibility of serialization format
+ private MethodBase[] rgMethodBase;
+
+#pragma warning disable 414
+ // dynamicMethods is an array of System.Resolver objects, used to keep
+ // DynamicMethodDescs alive for the lifetime of StackFrameHelper.
+ private Object dynamicMethods; // Field is not used from managed.
+
+ [NonSerialized]
+ private IntPtr[] rgMethodHandle;
+ private String[] rgAssemblyPath;
+ private IntPtr[] rgLoadedPeAddress;
+ private int[] rgiLoadedPeSize;
+ private IntPtr[] rgInMemoryPdbAddress;
+ private int[] rgiInMemoryPdbSize;
+ // if rgiMethodToken[i] == 0, then don't attempt to get the portable PDB source/info
+ private int[] rgiMethodToken;
+ private String[] rgFilename;
+ private int[] rgiLineNumber;
+ private int[] rgiColumnNumber;
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ [OptionalField]
+ private bool[] rgiLastFrameFromForeignExceptionStackTrace;
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+ private GetSourceLineInfoDelegate getSourceLineInfo;
+ private int iFrameCount;
+#pragma warning restore 414
+
+ private delegate void GetSourceLineInfoDelegate(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize,
+ IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset,
+ out string sourceFile, out int sourceLine, out int sourceColumn);
+
+#if FEATURE_CORECLR
+ private static Type s_symbolsType = null;
+ private static MethodInfo s_symbolsMethodInfo = null;
+
+ [ThreadStatic]
+ private static int t_reentrancy = 0;
+#endif
+
+ public StackFrameHelper(Thread target)
+ {
+ targetThread = target;
+ rgMethodBase = null;
+ rgMethodHandle = null;
+ rgiMethodToken = null;
+ rgiOffset = null;
+ rgiILOffset = null;
+ rgAssemblyPath = null;
+ rgLoadedPeAddress = null;
+ rgiLoadedPeSize = null;
+ rgInMemoryPdbAddress = null;
+ rgiInMemoryPdbSize = null;
+ dynamicMethods = null;
+ rgFilename = null;
+ rgiLineNumber = null;
+ rgiColumnNumber = null;
+ getSourceLineInfo = null;
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ rgiLastFrameFromForeignExceptionStackTrace = null;
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ // 0 means capture all frames. For StackTraces from an Exception, the EE always
+ // captures all frames. For other uses of StackTraces, we can abort stack walking after
+ // some limit if we want to by setting this to a non-zero value. In Whidbey this was
+ // hard-coded to 512, but some customers complained. There shouldn't be any need to limit
+ // this as memory/CPU is no longer allocated up front. If there is some reason to provide a
+ // limit in the future, then we should expose it in the managed API so applications can
+ // override it.
+ iFrameCount = 0;
+ }
+
+ //
+ // Initializes the stack trace helper. If fNeedFileInfo is true, initializes rgFilename,
+ // rgiLineNumber and rgiColumnNumber fields using the portable PDB reader if not already
+ // done by GetStackFramesInternal (on Windows for old PDB format).
+ //
+ internal void InitializeSourceInfo(int iSkip, bool fNeedFileInfo, Exception exception)
+ {
+ StackTrace.GetStackFramesInternal(this, iSkip, fNeedFileInfo, exception);
+
+#if FEATURE_CORECLR
+ if (!fNeedFileInfo)
+ return;
+
+ // Check if this function is being reentered because of an exception in the code below
+ if (t_reentrancy > 0)
+ return;
+
+ t_reentrancy++;
+ try
+ {
+ if (s_symbolsMethodInfo == null)
+ {
+ s_symbolsType = Type.GetType(
+ "System.Diagnostics.StackTraceSymbols, System.Diagnostics.StackTrace, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a",
+ throwOnError: false);
+
+ if (s_symbolsType == null)
+ return;
+
+ s_symbolsMethodInfo = s_symbolsType.GetMethod("GetSourceLineInfo", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+ if (s_symbolsMethodInfo == null)
+ return;
+ }
+
+ if (getSourceLineInfo == null)
+ {
+ // Create an instance of System.Diagnostics.Stacktrace.Symbols
+ object target = Activator.CreateInstance(s_symbolsType);
+
+ // Create an instance delegate for the GetSourceLineInfo method
+ getSourceLineInfo = (GetSourceLineInfoDelegate)s_symbolsMethodInfo.CreateDelegate(typeof(GetSourceLineInfoDelegate), target);
+ }
+
+ for (int index = 0; index < iFrameCount; index++)
+ {
+ // If there was some reason not to try get the symbols from the portable PDB reader like the module was
+ // ENC or the source/line info was already retrieved, the method token is 0.
+ if (rgiMethodToken[index] != 0)
+ {
+ getSourceLineInfo(rgAssemblyPath[index], rgLoadedPeAddress[index], rgiLoadedPeSize[index],
+ rgInMemoryPdbAddress[index], rgiInMemoryPdbSize[index], rgiMethodToken[index],
+ rgiILOffset[index], out rgFilename[index], out rgiLineNumber[index], out rgiColumnNumber[index]);
+ }
+ }
+ }
+ catch
+ {
+ }
+ finally
+ {
+ t_reentrancy--;
+ }
+#endif
+ }
+
+ void IDisposable.Dispose()
+ {
+#if FEATURE_CORECLR
+ if (getSourceLineInfo != null)
+ {
+ IDisposable disposable = getSourceLineInfo.Target as IDisposable;
+ if (disposable != null)
+ {
+ disposable.Dispose();
+ }
+ }
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public virtual MethodBase GetMethodBase(int i)
+ {
+ // There may be a better way to do this.
+ // we got RuntimeMethodHandles here and we need to go to MethodBase
+ // but we don't know whether the reflection info has been initialized
+ // or not. So we call GetMethods and GetConstructors on the type
+ // and then we fetch the proper MethodBase!!
+ IntPtr mh = rgMethodHandle[i];
+
+ if (mh.IsNull())
+ return null;
+
+ IRuntimeMethodInfo mhReal = RuntimeMethodHandle.GetTypicalMethodDefinition(new RuntimeMethodInfoStub(mh, this));
+
+ return RuntimeType.GetMethodBase(mhReal);
+ }
+
+ public virtual int GetOffset(int i) { return rgiOffset[i];}
+ public virtual int GetILOffset(int i) { return rgiILOffset[i];}
+ public virtual String GetFilename(int i) { return rgFilename == null ? null : rgFilename[i];}
+ public virtual int GetLineNumber(int i) { return rgiLineNumber == null ? 0 : rgiLineNumber[i];}
+ public virtual int GetColumnNumber(int i) { return rgiColumnNumber == null ? 0 : rgiColumnNumber[i];}
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ public virtual bool IsLastFrameFromForeignExceptionStackTrace(int i)
+ {
+ return (rgiLastFrameFromForeignExceptionStackTrace == null)?false:rgiLastFrameFromForeignExceptionStackTrace[i];
+ }
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ public virtual int GetNumberOfFrames() { return iFrameCount;}
+ public virtual void SetNumberOfFrames(int i) { iFrameCount = i;}
+
+ //
+ // serialization implementation
+ //
+ [OnSerializing]
+ [SecuritySafeCritical]
+ void OnSerializing(StreamingContext context)
+ {
+ // this is called in the process of serializing this object.
+ // For compatibility with Everett we need to assign the rgMethodBase field as that is the field
+ // that will be serialized
+ rgMethodBase = (rgMethodHandle == null) ? null : new MethodBase[rgMethodHandle.Length];
+ if (rgMethodHandle != null)
+ {
+ for (int i = 0; i < rgMethodHandle.Length; i++)
+ {
+ if (!rgMethodHandle[i].IsNull())
+ rgMethodBase[i] = RuntimeType.GetMethodBase(new RuntimeMethodInfoStub(rgMethodHandle[i], this));
+ }
+ }
+ }
+
+ [OnSerialized]
+ void OnSerialized(StreamingContext context)
+ {
+ // after we are done serializing null the rgMethodBase field
+ rgMethodBase = null;
+ }
+
+ [OnDeserialized]
+ [SecuritySafeCritical]
+ void OnDeserialized(StreamingContext context)
+ {
+ // after we are done deserializing we need to transform the rgMethodBase in rgMethodHandle
+ rgMethodHandle = (rgMethodBase == null) ? null : new IntPtr[rgMethodBase.Length];
+ if (rgMethodBase != null)
+ {
+ for (int i = 0; i < rgMethodBase.Length; i++)
+ {
+ if (rgMethodBase[i] != null)
+ rgMethodHandle[i] = rgMethodBase[i].MethodHandle.Value;
+ }
+ }
+ rgMethodBase = null;
+ }
+ }
+
+
+ // Class which represents a description of a stack trace
+ // There is no good reason for the methods of this class to be virtual.
+ // In order to ensure trusted code can trust the data it gets from a
+ // StackTrace, we use an InheritanceDemand to prevent partially-trusted
+ // subclasses.
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class StackTrace
+ {
+ private StackFrame[] frames;
+ private int m_iNumOfFrames;
+ public const int METHODS_TO_SKIP = 0;
+ private int m_iMethodsToSkip;
+
+ // Constructs a stack trace from the current location.
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public StackTrace()
+ {
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+ CaptureStackTrace(METHODS_TO_SKIP, false, null, null);
+ }
+
+ // Constructs a stack trace from the current location.
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(bool fNeedFileInfo)
+ {
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+ CaptureStackTrace(METHODS_TO_SKIP, fNeedFileInfo, null, null);
+ }
+
+ // Constructs a stack trace from the current location, in a caller's
+ // frame
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(int skipFrames)
+ {
+
+ if (skipFrames < 0)
+ throw new ArgumentOutOfRangeException("skipFrames",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+
+ CaptureStackTrace(skipFrames+METHODS_TO_SKIP, false, null, null);
+ }
+
+ // Constructs a stack trace from the current location, in a caller's
+ // frame
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(int skipFrames, bool fNeedFileInfo)
+ {
+
+ if (skipFrames < 0)
+ throw new ArgumentOutOfRangeException("skipFrames",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+
+ CaptureStackTrace(skipFrames+METHODS_TO_SKIP, fNeedFileInfo, null, null);
+ }
+
+
+ // Constructs a stack trace from the current location.
+ public StackTrace(Exception e)
+ {
+ if (e == null)
+ throw new ArgumentNullException("e");
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+ CaptureStackTrace(METHODS_TO_SKIP, false, null, e);
+ }
+
+ // Constructs a stack trace from the current location.
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(Exception e, bool fNeedFileInfo)
+ {
+ if (e == null)
+ throw new ArgumentNullException("e");
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+ CaptureStackTrace(METHODS_TO_SKIP, fNeedFileInfo, null, e);
+ }
+
+ // Constructs a stack trace from the current location, in a caller's
+ // frame
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(Exception e, int skipFrames)
+ {
+ if (e == null)
+ throw new ArgumentNullException("e");
+
+ if (skipFrames < 0)
+ throw new ArgumentOutOfRangeException("skipFrames",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+
+ CaptureStackTrace(skipFrames+METHODS_TO_SKIP, false, null, e);
+ }
+
+ // Constructs a stack trace from the current location, in a caller's
+ // frame
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public StackTrace(Exception e, int skipFrames, bool fNeedFileInfo)
+ {
+ if (e == null)
+ throw new ArgumentNullException("e");
+
+ if (skipFrames < 0)
+ throw new ArgumentOutOfRangeException("skipFrames",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+
+ CaptureStackTrace(skipFrames+METHODS_TO_SKIP, fNeedFileInfo, null, e);
+ }
+
+
+ // Constructs a "fake" stack trace, just containing a single frame.
+ // Does not have the overhead of a full stack trace.
+ //
+ public StackTrace(StackFrame frame)
+ {
+ frames = new StackFrame[1];
+ frames[0] = frame;
+ m_iMethodsToSkip = 0;
+ m_iNumOfFrames = 1;
+ }
+
+
+ // Constructs a stack trace for the given thread
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ [Obsolete("This constructor has been deprecated. Please use a constructor that does not require a Thread parameter. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public StackTrace(Thread targetThread, bool needFileInfo)
+ {
+ m_iNumOfFrames = 0;
+ m_iMethodsToSkip = 0;
+
+ CaptureStackTrace(METHODS_TO_SKIP, needFileInfo, targetThread, null);
+
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void GetStackFramesInternal(StackFrameHelper sfh, int iSkip, bool fNeedFileInfo, Exception e);
+
+ internal static int CalculateFramesToSkip(StackFrameHelper StackF, int iNumFrames)
+ {
+ int iRetVal = 0;
+ String PackageName = "System.Diagnostics";
+
+ // Check if this method is part of the System.Diagnostics
+ // package. If so, increment counter keeping track of
+ // System.Diagnostics functions
+ for (int i = 0; i < iNumFrames; i++)
+ {
+ MethodBase mb = StackF.GetMethodBase(i);
+ if (mb != null)
+ {
+ Type t = mb.DeclaringType;
+ if (t == null)
+ break;
+ String ns = t.Namespace;
+ if (ns == null)
+ break;
+ if (String.Compare(ns, PackageName, StringComparison.Ordinal) != 0)
+ break;
+ }
+ iRetVal++;
+ }
+
+ return iRetVal;
+ }
+
+ // Retrieves an object with stack trace information encoded.
+ // It leaves out the first "iSkip" lines of the stacktrace.
+ //
+ private void CaptureStackTrace(int iSkip, bool fNeedFileInfo, Thread targetThread, Exception e)
+ {
+ m_iMethodsToSkip += iSkip;
+
+ using (StackFrameHelper StackF = new StackFrameHelper(targetThread))
+ {
+ StackF.InitializeSourceInfo(0, fNeedFileInfo, e);
+
+ m_iNumOfFrames = StackF.GetNumberOfFrames();
+
+ if (m_iMethodsToSkip > m_iNumOfFrames)
+ m_iMethodsToSkip = m_iNumOfFrames;
+
+ if (m_iNumOfFrames != 0)
+ {
+ frames = new StackFrame[m_iNumOfFrames];
+
+ for (int i = 0; i < m_iNumOfFrames; i++)
+ {
+ bool fDummy1 = true;
+ bool fDummy2 = true;
+ StackFrame sfTemp = new StackFrame(fDummy1, fDummy2);
+
+ sfTemp.SetMethodBase(StackF.GetMethodBase(i));
+ sfTemp.SetOffset(StackF.GetOffset(i));
+ sfTemp.SetILOffset(StackF.GetILOffset(i));
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ sfTemp.SetIsLastFrameFromForeignExceptionStackTrace(StackF.IsLastFrameFromForeignExceptionStackTrace(i));
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ if (fNeedFileInfo)
+ {
+ sfTemp.SetFileName(StackF.GetFilename(i));
+ sfTemp.SetLineNumber(StackF.GetLineNumber(i));
+ sfTemp.SetColumnNumber(StackF.GetColumnNumber(i));
+ }
+
+ frames[i] = sfTemp;
+ }
+
+ // CalculateFramesToSkip skips all frames in the System.Diagnostics namespace,
+ // but this is not desired if building a stack trace from an exception.
+ if (e == null)
+ m_iMethodsToSkip += CalculateFramesToSkip(StackF, m_iNumOfFrames);
+
+ m_iNumOfFrames -= m_iMethodsToSkip;
+ if (m_iNumOfFrames < 0)
+ {
+ m_iNumOfFrames = 0;
+ }
+ }
+
+ // In case this is the same object being re-used, set frames to null
+ else
+ frames = null;
+ }
+ }
+
+ // Property to get the number of frames in the stack trace
+ //
+ public virtual int FrameCount
+ {
+ get { return m_iNumOfFrames;}
+ }
+
+
+ // Returns a given stack frame. Stack frames are numbered starting at
+ // zero, which is the last stack frame pushed.
+ //
+ public virtual StackFrame GetFrame(int index)
+ {
+ if ((frames != null) && (index < m_iNumOfFrames) && (index >= 0))
+ return frames[index+m_iMethodsToSkip];
+
+ return null;
+ }
+
+ // Returns an array of all stack frames for this stacktrace.
+ // The array is ordered and sized such that GetFrames()[i] == GetFrame(i)
+ // The nth element of this array is the same as GetFrame(n).
+ // The length of the array is the same as FrameCount.
+ //
+ [ComVisible(false)]
+ public virtual StackFrame [] GetFrames()
+ {
+ if (frames == null || m_iNumOfFrames <= 0)
+ return null;
+
+ // We have to return a subset of the array. Unfortunately this
+ // means we have to allocate a new array and copy over.
+ StackFrame [] array = new StackFrame[m_iNumOfFrames];
+ Array.Copy(frames, m_iMethodsToSkip, array, 0, m_iNumOfFrames);
+ return array;
+ }
+
+ // Builds a readable representation of the stack trace
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override String ToString()
+ {
+ // Include a trailing newline for backwards compatibility
+ return ToString(TraceFormat.TrailingNewLine);
+ }
+
+ // TraceFormat is Used to specify options for how the
+ // string-representation of a StackTrace should be generated.
+ internal enum TraceFormat
+ {
+ Normal,
+ TrailingNewLine, // include a trailing new line character
+ NoResourceLookup // to prevent infinite resource recusion
+ }
+
+ // Builds a readable representation of the stack trace, specifying
+ // the format for backwards compatibility.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ internal String ToString(TraceFormat traceFormat)
+ {
+ bool displayFilenames = true; // we'll try, but demand may fail
+ String word_At = "at";
+ String inFileLineNum = "in {0}:line {1}";
+
+ if(traceFormat != TraceFormat.NoResourceLookup)
+ {
+ word_At = Environment.GetResourceString("Word_At");
+ inFileLineNum = Environment.GetResourceString("StackTrace_InFileLineNumber");
+ }
+
+ bool fFirstFrame = true;
+ StringBuilder sb = new StringBuilder(255);
+ for (int iFrameIndex = 0; iFrameIndex < m_iNumOfFrames; iFrameIndex++)
+ {
+ StackFrame sf = GetFrame(iFrameIndex);
+ MethodBase mb = sf.GetMethod();
+ if (mb != null)
+ {
+ // We want a newline at the end of every line except for the last
+ if (fFirstFrame)
+ fFirstFrame = false;
+ else
+ sb.Append(Environment.NewLine);
+
+ sb.AppendFormat(CultureInfo.InvariantCulture, " {0} ", word_At);
+
+ Type t = mb.DeclaringType;
+ // if there is a type (non global method) print it
+ if (t != null)
+ {
+ // Append t.FullName, replacing '+' with '.'
+ string fullName = t.FullName;
+ for (int i = 0; i < fullName.Length; i++)
+ {
+ char ch = fullName[i];
+ sb.Append(ch == '+' ? '.' : ch);
+ }
+ sb.Append('.');
+ }
+ sb.Append(mb.Name);
+
+ // deal with the generic portion of the method
+ if (mb is MethodInfo && ((MethodInfo)mb).IsGenericMethod)
+ {
+ Type[] typars = ((MethodInfo)mb).GetGenericArguments();
+ sb.Append('[');
+ int k=0;
+ bool fFirstTyParam = true;
+ while (k < typars.Length)
+ {
+ if (fFirstTyParam == false)
+ sb.Append(',');
+ else
+ fFirstTyParam = false;
+
+ sb.Append(typars[k].Name);
+ k++;
+ }
+ sb.Append(']');
+ }
+
+ ParameterInfo[] pi = null;
+#if FEATURE_CORECLR
+ try
+ {
+#endif
+ pi = mb.GetParameters();
+#if FEATURE_CORECLR
+ }
+ catch
+ {
+ // The parameter info cannot be loaded, so we don't
+ // append the parameter list.
+ }
+#endif
+ if (pi != null)
+ {
+ // arguments printing
+ sb.Append('(');
+ bool fFirstParam = true;
+ for (int j = 0; j < pi.Length; j++)
+ {
+ if (fFirstParam == false)
+ sb.Append(", ");
+ else
+ fFirstParam = false;
+
+ String typeName = "<UnknownType>";
+ if (pi[j].ParameterType != null)
+ typeName = pi[j].ParameterType.Name;
+ sb.Append(typeName);
+ sb.Append(' ');
+ sb.Append(pi[j].Name);
+ }
+ sb.Append(')');
+ }
+
+ // source location printing
+ if (displayFilenames && (sf.GetILOffset() != -1))
+ {
+ // If we don't have a PDB or PDB-reading is disabled for the module,
+ // then the file name will be null.
+ String fileName = null;
+
+ // Getting the filename from a StackFrame is a privileged operation - we won't want
+ // to disclose full path names to arbitrarily untrusted code. Rather than just omit
+ // this we could probably trim to just the filename so it's still mostly usefull.
+ try
+ {
+ fileName = sf.GetFileName();
+ }
+#if FEATURE_CAS_POLICY
+ catch (NotSupportedException)
+ {
+ // Having a deprecated stack modifier on the callstack (such as Deny) will cause
+ // a NotSupportedException to be thrown. Since we don't know if the app can
+ // access the file names, we'll conservatively hide them.
+ displayFilenames = false;
+ }
+#endif // FEATURE_CAS_POLICY
+ catch (SecurityException)
+ {
+ // If the demand for displaying filenames fails, then it won't
+ // succeed later in the loop. Avoid repeated exceptions by not trying again.
+ displayFilenames = false;
+ }
+
+ if (fileName != null)
+ {
+ // tack on " in c:\tmp\MyFile.cs:line 5"
+ sb.Append(' ');
+ sb.AppendFormat(CultureInfo.InvariantCulture, inFileLineNum, fileName, sf.GetFileLineNumber());
+ }
+ }
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+ if (sf.GetIsLastFrameFromForeignExceptionStackTrace())
+ {
+ sb.Append(Environment.NewLine);
+ sb.Append(Environment.GetResourceString("Exception_EndStackTraceFromPreviousThrow"));
+ }
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+ }
+ }
+
+ if(traceFormat == TraceFormat.TrailingNewLine)
+ sb.Append(Environment.NewLine);
+
+ return sb.ToString();
+ }
+
+ // This helper is called from within the EE to construct a string representation
+ // of the current stack trace.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private static String GetManagedStackTraceStringHelper(bool fNeedFileInfo)
+ {
+ // Note all the frames in System.Diagnostics will be skipped when capturing
+ // a normal stack trace (not from an exception) so we don't need to explicitly
+ // skip the GetManagedStackTraceStringHelper frame.
+ StackTrace st = new StackTrace(0, fNeedFileInfo);
+ return st.ToString();
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymBinder.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymBinder.cs
new file mode 100644
index 0000000000..1ce870f983
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymBinder.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+**
+** Represents a symbol binder for managed code.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+ using System.Text;
+ using System.Runtime.InteropServices;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolBinder
+ {
+ // The importer parameter should be an IntPtr, not an int. This interface can not be modified without
+ // a breaking change, and so ISymbolBinderEx.GetReader() has been added with the correct marshalling layout.
+ [Obsolete("The recommended alternative is ISymbolBinder1.GetReader. ISymbolBinder1.GetReader takes the importer interface pointer as an IntPtr instead of an Int32, and thus works on both 32-bit and 64-bit architectures. http://go.microsoft.com/fwlink/?linkid=14202=14202")]
+ ISymbolReader GetReader(int importer, String filename,
+ String searchPath);
+ }
+
+ // This interface has a revised ISymbolBinder.GetReader() with the proper signature.
+ // It is not called ISymbolBinder2 because it maps to the IUnmanagedSymbolBinder interfaces, and
+ // does not wrap the IUnmanagedSymbolBinder2 interfaces declared in CorSym.idl.
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolBinder1
+ {
+
+ ISymbolReader GetReader(IntPtr importer, String filename,
+ String searchPath);
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocument.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocument.cs
new file mode 100644
index 0000000000..c458b8e8a9
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocument.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a document referenced by a symbol store. A document is
+** defined by a URL and a document type GUID. Using the document type
+** GUID and the URL, one can locate the document however it is
+** stored. Document source can optionally be stored in the symbol
+** store. This interface also provides access to that source if it is
+** present.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolDocument
+ {
+ // Properties of the document.
+ String URL { get; }
+ Guid DocumentType { get; }
+
+ // Language of the document.
+ Guid Language { get; }
+ Guid LanguageVendor { get; }
+
+ // Check sum information.
+ Guid CheckSumAlgorithmId { get; }
+ byte[] GetCheckSum();
+
+ // Given a line in this document that may or may not be a sequence
+ // point, return the closest line that is a sequence point.
+ int FindClosestLine(int line);
+
+ // Access to embedded source.
+ bool HasEmbeddedSource { get; }
+ int SourceLength { get; }
+ byte[] GetSourceRange(int startLine, int startColumn,
+ int endLine, int endColumn);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocumentWriter.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocumentWriter.cs
new file mode 100644
index 0000000000..2b7b078dbc
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymDocumentWriter.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a document referenced by a symbol store. A document is
+** defined by a URL and a document type GUID. Document source can
+** optionally be stored in the symbol store.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolDocumentWriter
+ {
+ // SetSource will store the raw source for a document into the
+ // symbol store. An array of unsigned bytes is used instead of
+ // character data to accommodate a wider variety of "source".
+ void SetSource(byte[] source);
+
+ // Check sum support.
+ void SetCheckSum(Guid algorithmId, byte[] checkSum);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymMethod.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymMethod.cs
new file mode 100644
index 0000000000..5edabb1194
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymMethod.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a method within a symbol reader. This provides access to
+** only the symbol-related attributes of a method, such as sequence
+** points, lexical scopes, and parameter information. Use it in
+** conjucntion with other means to read the type-related attrbiutes of
+** a method, such as Reflections.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ using System.Runtime.InteropServices;
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolMethod
+ {
+ // Get the token for this method.
+ SymbolToken Token { get; }
+
+ // Get the count of sequence points.
+ int SequencePointCount { get; }
+
+ // Get the sequence points for this method. The sequence points
+ // are sorted by offset and are for all documents in the
+ // method. Use GetSequencePointCount to retrieve the count of all
+ // sequence points and create arrays of the proper size.
+ // GetSequencePoints will verify the size of each array and place
+ // the sequence point information into each. If any array is NULL,
+ // then the data for that array is simply not returned.
+ void GetSequencePoints(int[] offsets,
+ ISymbolDocument[] documents,
+ int[] lines,
+ int[] columns,
+ int[] endLines,
+ int[] endColumns);
+
+ // Get the root lexical scope for this method. This scope encloses
+ // the entire method.
+ ISymbolScope RootScope { get; }
+
+ // Given an offset within the method, returns the most enclosing
+ // lexical scope. This can be used to start local variable
+ // searches.
+ ISymbolScope GetScope(int offset);
+
+ // Given a position in a document, return the offset within the
+ // method that corresponds to the position.
+ int GetOffset(ISymbolDocument document,
+ int line,
+ int column);
+
+ // Given a position in a document, return an array of start/end
+ // offset paris that correspond to the ranges of IL that the
+ // position covers within this method. The array is an array of
+ // integers and is [start,end,start,end]. The number of range
+ // pairs is the length of the array / 2.
+ int[] GetRanges(ISymbolDocument document,
+ int line,
+ int column);
+
+ // Get the parameters for this method. The paraemeters are
+ // returned in the order they are defined within the method's
+ // signature.
+ ISymbolVariable[] GetParameters();
+
+ // Get the namespace that this method is defined within.
+ ISymbolNamespace GetNamespace();
+
+ // Get the start/end document positions for the source of this
+ // method. The first array position is the start while the second
+ // is the end. Returns true if positions were defined, false
+ // otherwise.
+ bool GetSourceStartEnd(ISymbolDocument[] docs,
+ int[] lines,
+ int[] columns);
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymNamespace.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymNamespace.cs
new file mode 100644
index 0000000000..1dee13ef69
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymNamespace.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a namespace within a symbol reader.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolNamespace
+ {
+ // Get the name of this namespace
+ String Name { get; }
+
+ // Get the children of this namespace
+ ISymbolNamespace[] GetNamespaces();
+
+ // Get the variables in this namespace
+ ISymbolVariable[] GetVariables();
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymReader.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymReader.cs
new file mode 100644
index 0000000000..8bc75e5aba
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymReader.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a symbol reader for managed code. Provides access to
+** documents, methods, and variables.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Interface does not need to be marked with the serializable attribute
+ using System;
+ using System.Runtime.InteropServices;
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolReader
+ {
+ // Find a document. Language, vendor, and document type are
+ // optional.
+ ISymbolDocument GetDocument(String url,
+ Guid language,
+ Guid languageVendor,
+ Guid documentType);
+
+ // Return an array of all of the documents defined in the symbol
+ // store.
+ ISymbolDocument[] GetDocuments();
+
+ // Return the method that was specified as the user entry point
+ // for the module, if any. This would be, perhaps, the user's main
+ // method rather than compiler generated stubs before main.
+ SymbolToken UserEntryPoint { get; }
+
+ // Get a symbol reader method given the id of a method.
+ ISymbolMethod GetMethod(SymbolToken method);
+
+ // Get a symbol reader method given the id of a method and an E&C
+ // version number. Version numbers start a 1 and are incremented
+ // each time the method is changed due to an E&C operation.
+ ISymbolMethod GetMethod(SymbolToken method, int version);
+
+ // Return a non-local variable given its parent and name.
+ ISymbolVariable[] GetVariables(SymbolToken parent);
+
+ // Return a non-local variable given its parent and name.
+ ISymbolVariable[] GetGlobalVariables();
+
+ // Given a position in a document, return the ISymbolMethod that
+ // contains that position.
+ ISymbolMethod GetMethodFromDocumentPosition(ISymbolDocument document,
+ int line,
+ int column);
+
+ // Gets a custom attribute based upon its name. Not to be
+ // confused with Metadata custom attributes, these attributes are
+ // held in the symbol store.
+ byte[] GetSymAttribute(SymbolToken parent, String name);
+
+ // Get the namespaces defined at global scope within this symbol store.
+ ISymbolNamespace[] GetNamespaces();
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymScope.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymScope.cs
new file mode 100644
index 0000000000..859d7d42c8
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymScope.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a lexical scope within a ISymbolMethod. Provides access to
+** the start and end offsets of the scope, as well as its child and
+** parent scopes. Also provides access to all the locals defined
+** within this scope.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Interface does not need to be marked with the serializable attribute
+ using System;
+ using System.Text;
+ using System.Runtime.InteropServices;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolScope
+ {
+ // Get the method that contains this scope.
+ ISymbolMethod Method { get; }
+
+ // Get the parent scope of this scope.
+ ISymbolScope Parent { get; }
+
+ // Get any child scopes of this scope.
+ ISymbolScope[] GetChildren();
+
+ // Get the start and end offsets for this scope.
+ int StartOffset { get; }
+ int EndOffset { get; }
+
+ // Get the locals within this scope. They are returned in no
+ // particular order. Note: if a local variable changes its address
+ // within this scope then that variable will be returned multiple
+ // times, each with a different offset range.
+ ISymbolVariable[] GetLocals();
+
+ // Get the namespaces that are being "used" within this scope.
+ ISymbolNamespace[] GetNamespaces();
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymVariable.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymVariable.cs
new file mode 100644
index 0000000000..857d24b2b6
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymVariable.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a variable within a symbol store. This could be a
+** parameter, local variable, or some other non-local variable.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Interface does not need to be marked with the serializable attribute
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolVariable
+ {
+ // Get the name of this variable.
+ String Name { get; }
+
+ // Get the attributes of this variable.
+ Object Attributes { get; }
+
+ // Get the signature of this variable.
+ byte[] GetSignature();
+
+ SymAddressKind AddressKind { get; }
+ int AddressField1 { get; }
+ int AddressField2 { get; }
+ int AddressField3 { get; }
+
+ // Get the start/end offsets of this variable within its
+ // parent. If this is a local variable within a scope, these will
+ // fall within the offsets defined for the scope.
+ int StartOffset { get; }
+ int EndOffset { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs
new file mode 100644
index 0000000000..b6177be2aa
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/ISymWriter.cs
@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents a symbol writer for managed code. Provides methods to
+** define documents, sequence points, lexical scopes, and variables.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+ using System.Text;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISymbolWriter
+ {
+ // Set the IMetadataEmitter that this symbol writer is associated
+ // with. This must be done only once before any other ISymbolWriter
+ // methods are called.
+ void Initialize(IntPtr emitter, String filename, bool fFullBuild);
+
+ // Define a source document. Guid's will be provided for the
+ // languages, vendors, and document types that we currently know
+ // about.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ ISymbolDocumentWriter DefineDocument(String url,
+ Guid language,
+ Guid languageVendor,
+ Guid documentType);
+
+ // Define the method that the user has defined as their entrypoint
+ // for this module. This would be, perhaps, the user's main method
+ // rather than compiler generated stubs before main.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void SetUserEntryPoint(SymbolToken entryMethod);
+
+ // Open a method to emit symbol information into. The given method
+ // becomes the current method for calls do define sequence points,
+ // parameters and lexical scopes. There is an implicit lexical
+ // scope around the entire method. Re-opening a method that has
+ // been previously closed effectivley erases any previously
+ // defined symbols for that method.
+ //
+ // There can be only one open method at a time.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void OpenMethod(SymbolToken method);
+
+ // Close the current method. Once a method is closed, no more
+ // symbols can be defined within it.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void CloseMethod();
+
+ // Define a group of sequence points within the current method.
+ // Each line/column defines the start of a statement within a
+ // method. The arrays should be sorted by offset. The offset is
+ // always the offset from the start of the method, in bytes.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void DefineSequencePoints(ISymbolDocumentWriter document,
+ int[] offsets,
+ int[] lines,
+ int[] columns,
+ int[] endLines,
+ int[] endColumns);
+
+ // Open a new lexical scope in the current method. The scope
+ // becomes the new current scope and is effectivley pushed onto a
+ // stack of scopes. startOffset is the offset, in bytes from the
+ // beginning of the method, of the first instruction in the
+ // lexical scope. Scopes must form a hierarchy. Siblings are not
+ // allowed to overlap.
+ //
+ // OpenScope returns an opaque scope id that can be used with
+ // SetScopeRange to define a scope's start/end offset at a later
+ // time. In this case, the offsets passed to OpenScope and
+ // CloseScope are ignored.
+ //
+ // Note: scope id's are only valid in the current method.
+ //
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ int OpenScope(int startOffset);
+
+ // Close the current lexical scope. Once a scope is closed no more
+ // variables can be defined within it. endOffset points past the
+ // last instruction in the scope.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void CloseScope(int endOffset);
+
+ // Define the offset range for a given lexical scope.
+ void SetScopeRange(int scopeID, int startOffset, int endOffset);
+
+ // Define a single variable in the current lexical
+ // scope. startOffset and endOffset are optional. If 0, then they
+ // are ignored and the variable is defined over the entire
+ // scope. If non-zero, then they must fall within the offsets of
+ // the current scope. This can be called multiple times for a
+ // variable of the same name that has multiple homes throughout a
+ // scope. (Note: start/end offsets must not overlap in such a
+ // case.)
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void DefineLocalVariable(String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3,
+ int startOffset,
+ int endOffset);
+
+ // Define a single parameter in the current method. The type of
+ // each parameter is taken from its position (sequence) within the
+ // method's signature.
+ //
+ // Note: if parameters are defined in the metadata for a given
+ // method, then clearly one would not have to define them again
+ // with calls to this method. The symbol readers will have to be
+ // smart enough to check the normal metadata for these first then
+ // fall back to the symbol store.
+ void DefineParameter(String name,
+ ParameterAttributes attributes,
+ int sequence,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3);
+
+ // Define a single variable not within a method. This is used for
+ // certian fields in classes, bitfields, etc.
+ void DefineField(SymbolToken parent,
+ String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3);
+
+ // Define a single global variable.
+ void DefineGlobalVariable(String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3);
+
+ // Close will close the ISymbolWriter and commit the symbols
+ // to the symbol store. The ISymbolWriter becomes invalid
+ // after this call for further updates.
+ void Close();
+
+ // Defines a custom attribute based upon its name. Not to be
+ // confused with Metadata custom attributes, these attributes are
+ // held in the symbol store.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void SetSymAttribute(SymbolToken parent, String name, byte[] data);
+
+ // Opens a new namespace. Call this before defining methods or
+ // variables that live within a namespace. Namespaces can be nested.
+ void OpenNamespace(String name);
+
+ // Close the most recently opened namespace.
+ void CloseNamespace();
+
+ // Specifies that the given, fully qualified namespace name is
+ // being used within the currently open lexical scope. Closing the
+ // current scope will also stop using the namespace, and the
+ // namespace will be in use in all scopes that inherit from the
+ // currently open scope.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void UsingNamespace(String fullName);
+
+ // Specifies the true start and end of a method within a source
+ // file. Use this to specify the extent of a method independently
+ // of what sequence points exist within the method.
+ void SetMethodSourceRange(ISymbolDocumentWriter startDoc,
+ int startLine,
+ int startColumn,
+ ISymbolDocumentWriter endDoc,
+ int endLine,
+ int endColumn);
+
+ // Used to set the underlying ISymUnmanagedWriter that a
+ // managed ISymbolWriter may use to emit symbols with.
+ void SetUnderlyingWriter(IntPtr underlyingWriter);
+ }
+
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs
new file mode 100644
index 0000000000..a7f866f2ec
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymAddressKind.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Represents address Kinds used with local variables, parameters, and
+** fields.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Only statics, does not need to be marked with the serializable attribute
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum SymAddressKind
+ {
+ // ILOffset: addr1 = IL local var or param index.
+ ILOffset = 1,
+
+ // NativeRVA: addr1 = RVA into module.
+ NativeRVA = 2,
+
+ // NativeRegister: addr1 = register the var is stored in.
+ NativeRegister = 3,
+
+ // NativeRegisterRelative: addr1 = register, addr2 = offset.
+ NativeRegisterRelative = 4,
+
+ // NativeOffset: addr1 = offset from start of parent.
+ NativeOffset = 5,
+
+ // NativeRegisterRegister: addr1 = reg low, addr2 = reg high.
+ NativeRegisterRegister = 6,
+
+ // NativeRegisterStack: addr1 = reg low, addr2 = reg stk, addr3 = offset.
+ NativeRegisterStack = 7,
+
+ // NativeStackRegister: addr1 = reg stk, addr2 = offset, addr3 = reg high.
+ NativeStackRegister = 8,
+
+ // BitField: addr1 = field start, addr = field length.
+ BitField = 9,
+
+ // NativeSectionOffset: addr1 = section, addr = offset
+ NativeSectionOffset = 10,
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/SymDocumentType.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymDocumentType.cs
new file mode 100644
index 0000000000..f7c7fea867
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymDocumentType.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+[System.Runtime.InteropServices.ComVisible(true)]
+** A class to hold public guids for document types to be used with the
+** symbol store.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Only statics does not need to be marked with the serializable attribute
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class SymDocumentType
+ {
+ public static readonly Guid Text = new Guid(0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageType.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageType.cs
new file mode 100644
index 0000000000..a67ba297af
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageType.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+[System.Runtime.InteropServices.ComVisible(true)]
+** A class to hold public guids for languages types.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Only statics, does not need to be marked with the serializable attribute
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class SymLanguageType
+ {
+ public static readonly Guid C = new Guid(0x63a08714, unchecked((short) 0xfc37), 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);
+ public static readonly Guid CPlusPlus = new Guid(0x3a12d0b7, unchecked((short)0xc26c), 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);
+
+ public static readonly Guid CSharp = new Guid(0x3f5162f8, unchecked((short)0x07c6), 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);
+
+ public static readonly Guid Basic = new Guid(0x3a12d0b8, unchecked((short)0xc26c), 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);
+
+ public static readonly Guid Java = new Guid(0x3a12d0b4, unchecked((short)0xc26c), 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);
+
+ public static readonly Guid Cobol = new Guid(unchecked((int)0xaf046cd1), unchecked((short)0xd0e1), 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);
+
+ public static readonly Guid Pascal = new Guid(unchecked((int)0xaf046cd2), unchecked((short) 0xd0e1), 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);
+
+ public static readonly Guid ILAssembly = new Guid(unchecked((int)0xaf046cd3), unchecked((short)0xd0e1), 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);
+
+ public static readonly Guid JScript = new Guid(0x3a12d0b6, unchecked((short)0xc26c), 0x11d0, 0xb4, 0x42, 0x00, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);
+
+ public static readonly Guid SMC = new Guid(unchecked((int)0xd9b9f7b), 0x6611, unchecked((short)0x11d3), 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);
+
+ public static readonly Guid MCPlusPlus = new Guid(0x4b35fde8, unchecked((short)0x07c6), 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageVendor.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageVendor.cs
new file mode 100644
index 0000000000..8bef10bdad
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/SymLanguageVendor.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+[System.Runtime.InteropServices.ComVisible(true)]
+** A class to hold public guids for language vendors.
+**
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+ // Only statics, does not need to be marked with the serializable attribute
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class SymLanguageVendor
+ {
+ public static readonly Guid Microsoft = new Guid(unchecked((int)0x994b45c4), unchecked((short) 0xe6e9), 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/SymbolStore/Token.cs b/src/mscorlib/src/System/Diagnostics/SymbolStore/Token.cs
new file mode 100644
index 0000000000..a8a6675a2f
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/SymbolStore/Token.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Small value class used by the SymbolStore package for passing
+** around metadata tokens.
+**
+===========================================================*/
+namespace System.Diagnostics.SymbolStore {
+
+ using System;
+ using System.Runtime.InteropServices;
+
+ [ComVisible(true)]
+ public struct SymbolToken
+ {
+ internal int m_token;
+
+ public SymbolToken(int val) {m_token=val;}
+
+ public int GetToken() {return m_token;}
+
+ public override int GetHashCode() {return m_token;}
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is SymbolToken)
+ return Equals((SymbolToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(SymbolToken obj)
+ {
+ return obj.m_token == m_token;
+ }
+
+ public static bool operator ==(SymbolToken a, SymbolToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(SymbolToken a, SymbolToken b)
+ {
+ return !(a == b);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Diagnostics/log.cs b/src/mscorlib/src/System/Diagnostics/log.cs
new file mode 100644
index 0000000000..1c68aad161
--- /dev/null
+++ b/src/mscorlib/src/System/Diagnostics/log.cs
@@ -0,0 +1,251 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics {
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Permissions;
+ using System.IO;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using Encoding = System.Text.Encoding;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+ // LogMessageEventHandlers are triggered when a message is generated which is
+ // "on" per its switch.
+ //
+ // By default, the debugger (if attached) is the only event handler.
+ // There is also a "built-in" console device which can be enabled
+ // programatically, by registry (specifics....) or environment
+ // variables.
+ [Serializable]
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ internal delegate void LogMessageEventHandler(LoggingLevels level, LogSwitch category,
+ String message,
+ StackTrace location);
+
+
+ // LogSwitchLevelHandlers are triggered when the level of a LogSwitch is modified
+ // NOTE: These are NOT triggered when the log switch setting is changed from the
+ // attached debugger.
+ //
+ [Serializable]
+ internal delegate void LogSwitchLevelHandler(LogSwitch ls, LoggingLevels newLevel);
+
+
+ internal static class Log
+ {
+
+ // Switches allow relatively fine level control of which messages are
+ // actually shown. Normally most debugging messages are not shown - the
+ // user will typically enable those which are relevant to what is being
+ // investigated.
+ //
+ // An attached debugger can enable or disable which messages will
+ // actually be reported to the user through the COM+ debugger
+ // services API. This info is communicated to the runtime so only
+ // desired events are actually reported to the debugger.
+ internal static Hashtable m_Hashtable;
+ private static volatile bool m_fConsoleDeviceEnabled;
+ private static LogMessageEventHandler _LogMessageEventHandler;
+ private static volatile LogSwitchLevelHandler _LogSwitchLevelHandler;
+ private static Object locker;
+
+ // Constant representing the global switch
+ public static readonly LogSwitch GlobalSwitch;
+
+
+ static Log()
+ {
+ m_Hashtable = new Hashtable();
+ m_fConsoleDeviceEnabled = false;
+ //pConsole = null;
+ //iNumOfMsgHandlers = 0;
+ //iMsgHandlerArraySize = 0;
+ locker = new Object();
+
+ // allocate the GlobalSwitch object
+ GlobalSwitch = new LogSwitch ("Global", "Global Switch for this log");
+
+ GlobalSwitch.MinimumLevel = LoggingLevels.ErrorLevel;
+ }
+
+ public static void AddOnLogMessage(LogMessageEventHandler handler)
+ {
+ lock (locker)
+ _LogMessageEventHandler =
+ (LogMessageEventHandler) MulticastDelegate.Combine(_LogMessageEventHandler, handler);
+ }
+
+ public static void RemoveOnLogMessage(LogMessageEventHandler handler)
+ {
+
+ lock (locker)
+ _LogMessageEventHandler =
+ (LogMessageEventHandler) MulticastDelegate.Remove(_LogMessageEventHandler, handler);
+ }
+
+ public static void AddOnLogSwitchLevel(LogSwitchLevelHandler handler)
+ {
+ lock (locker)
+ _LogSwitchLevelHandler =
+ (LogSwitchLevelHandler) MulticastDelegate.Combine(_LogSwitchLevelHandler, handler);
+ }
+
+ public static void RemoveOnLogSwitchLevel(LogSwitchLevelHandler handler)
+ {
+ lock (locker)
+ _LogSwitchLevelHandler =
+ (LogSwitchLevelHandler) MulticastDelegate.Remove(_LogSwitchLevelHandler, handler);
+ }
+
+ internal static void InvokeLogSwitchLevelHandlers (LogSwitch ls, LoggingLevels newLevel)
+ {
+ LogSwitchLevelHandler handler = _LogSwitchLevelHandler;
+ if (handler != null)
+ handler(ls, newLevel);
+ }
+
+
+ // Property to Enable/Disable ConsoleDevice. Enabling the console device
+ // adds the console device as a log output, causing any
+ // log messages which make it through filters to be written to the
+ // application console. The console device is enabled by default if the
+ // ??? registry entry or ??? environment variable is set.
+ public static bool IsConsoleEnabled
+ {
+ get { return m_fConsoleDeviceEnabled; }
+ set { m_fConsoleDeviceEnabled = value; }
+ }
+
+ // Generates a log message. If its switch (or a parent switch) allows the
+ // level for the message, it is "broadcast" to all of the log
+ // devices.
+ //
+ public static void LogMessage(LoggingLevels level, String message)
+ {
+ LogMessage (level, GlobalSwitch, message);
+ }
+
+ // Generates a log message. If its switch (or a parent switch) allows the
+ // level for the message, it is "broadcast" to all of the log
+ // devices.
+ //
+ public static void LogMessage(LoggingLevels level, LogSwitch logswitch, String message)
+ {
+ if (logswitch == null)
+ throw new ArgumentNullException ("LogSwitch");
+
+ if (level < 0)
+ throw new ArgumentOutOfRangeException("level", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Is logging for this level for this switch enabled?
+ if (logswitch.CheckLevel (level) == true)
+ {
+ // Send message for logging
+
+ // first send it to the debugger
+ Debugger.Log ((int) level, logswitch.strName, message);
+
+ // Send to the console device
+ if (m_fConsoleDeviceEnabled)
+ {
+ Console.Write(message);
+ }
+ }
+ }
+
+ /*
+ * Following are convenience entry points; all go through Log()
+ * Note that the (Switch switch, String message) variations
+ * are preferred.
+ */
+ public static void Trace(LogSwitch logswitch, String message)
+ {
+ LogMessage (LoggingLevels.TraceLevel0, logswitch, message);
+ }
+
+ public static void Trace(String switchname, String message)
+ {
+ LogSwitch ls;
+ ls = LogSwitch.GetSwitch (switchname);
+ LogMessage (LoggingLevels.TraceLevel0, ls, message);
+ }
+
+ public static void Trace(String message)
+ {
+ LogMessage (LoggingLevels.TraceLevel0, GlobalSwitch, message);
+ }
+
+ public static void Status(LogSwitch logswitch, String message)
+ {
+ LogMessage (LoggingLevels.StatusLevel0, logswitch, message);
+ }
+
+ public static void Status(String switchname, String message)
+ {
+ LogSwitch ls;
+ ls = LogSwitch.GetSwitch (switchname);
+ LogMessage (LoggingLevels.StatusLevel0, ls, message);
+ }
+
+ public static void Status(String message)
+ {
+ LogMessage (LoggingLevels.StatusLevel0, GlobalSwitch, message);
+ }
+
+ public static void Warning(LogSwitch logswitch, String message)
+ {
+ LogMessage (LoggingLevels.WarningLevel, logswitch, message);
+ }
+
+ public static void Warning(String switchname, String message)
+ {
+ LogSwitch ls;
+ ls = LogSwitch.GetSwitch (switchname);
+ LogMessage (LoggingLevels.WarningLevel, ls, message);
+ }
+
+ public static void Warning(String message)
+ {
+ LogMessage (LoggingLevels.WarningLevel, GlobalSwitch, message);
+ }
+
+ public static void Error(LogSwitch logswitch, String message)
+ {
+ LogMessage (LoggingLevels.ErrorLevel, logswitch, message);
+ }
+
+ public static void Error(String switchname, String message)
+ {
+ LogSwitch ls;
+ ls = LogSwitch.GetSwitch (switchname);
+ LogMessage (LoggingLevels.ErrorLevel, ls, message);
+
+ }
+
+ public static void Error(String message)
+ {
+ LogMessage (LoggingLevels.ErrorLevel, GlobalSwitch, message);
+ }
+
+ public static void Panic(String message)
+ {
+ LogMessage (LoggingLevels.PanicLevel, GlobalSwitch, message);
+ }
+
+
+ // Native method to inform the EE about the creation of a new LogSwitch
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void AddLogSwitch(LogSwitch logSwitch);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ModifyLogSwitch (int iNewLevel, String strSwitchName, String strParentName);
+ }
+
+}
diff --git a/src/mscorlib/src/System/DivideByZeroException.cs b/src/mscorlib/src/System/DivideByZeroException.cs
new file mode 100644
index 0000000000..b975e81df6
--- /dev/null
+++ b/src/mscorlib/src/System/DivideByZeroException.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for bad arithmetic conditions!
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class DivideByZeroException : ArithmeticException {
+ public DivideByZeroException()
+ : base(Environment.GetResourceString("Arg_DivideByZero")) {
+ SetErrorCode(__HResults.COR_E_DIVIDEBYZERO);
+ }
+
+ public DivideByZeroException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_DIVIDEBYZERO);
+ }
+
+ public DivideByZeroException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_DIVIDEBYZERO);
+ }
+
+ protected DivideByZeroException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/DllNotFoundException.cs b/src/mscorlib/src/System/DllNotFoundException.cs
new file mode 100644
index 0000000000..f860904f3f
--- /dev/null
+++ b/src/mscorlib/src/System/DllNotFoundException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for some failed P/Invoke calls.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class DllNotFoundException : TypeLoadException {
+ public DllNotFoundException()
+ : base(Environment.GetResourceString("Arg_DllNotFoundException")) {
+ SetErrorCode(__HResults.COR_E_DLLNOTFOUND);
+ }
+
+ public DllNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_DLLNOTFOUND);
+ }
+
+ public DllNotFoundException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_DLLNOTFOUND);
+ }
+
+ protected DllNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Double.cs b/src/mscorlib/src/System/Double.cs
new file mode 100644
index 0000000000..b2d509af8d
--- /dev/null
+++ b/src/mscorlib/src/System/Double.cs
@@ -0,0 +1,367 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A representation of an IEEE double precision
+** floating point number.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct Double : IComparable, IFormattable, IConvertible
+ , IComparable<Double>, IEquatable<Double>
+ {
+ internal double m_value;
+
+ //
+ // Public Constants
+ //
+ public const double MinValue = -1.7976931348623157E+308;
+ public const double MaxValue = 1.7976931348623157E+308;
+
+ // Note Epsilon should be a double whose hex representation is 0x1
+ // on little endian machines.
+ public const double Epsilon = 4.9406564584124654E-324;
+ public const double NegativeInfinity = (double)-1.0 / (double)(0.0);
+ public const double PositiveInfinity = (double)1.0 / (double)(0.0);
+ public const double NaN = (double)0.0 / (double)0.0;
+
+ internal static double NegativeZero = BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000));
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsInfinity(double d) {
+ return (*(long*)(&d) & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000;
+ }
+
+ [Pure]
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool IsPositiveInfinity(double d) {
+ //Jit will generate inlineable code with this
+ if (d == double.PositiveInfinity)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ [Pure]
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool IsNegativeInfinity(double d) {
+ //Jit will generate inlineable code with this
+ if (d == double.NegativeInfinity)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static bool IsNegative(double d) {
+ return (*(UInt64*)(&d) & 0x8000000000000000) == 0x8000000000000000;
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsNaN(double d)
+ {
+ return (*(UInt64*)(&d) & 0x7FFFFFFFFFFFFFFFL) > 0x7FF0000000000000L;
+ }
+
+
+ // Compares this object to another object, returning an instance of System.Relation.
+ // Null is considered less than any instance.
+ //
+ // If object is not of type Double, this method throws an ArgumentException.
+ //
+ // Returns a value less than zero if this object
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is Double) {
+ double d = (double)value;
+ if (m_value < d) return -1;
+ if (m_value > d) return 1;
+ if (m_value == d) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(d) ? 0 : -1);
+ else
+ return 1;
+ }
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDouble"));
+ }
+
+ public int CompareTo(Double value) {
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ if (m_value == value) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(value) ? 0 : -1);
+ else
+ return 1;
+ }
+
+ // True if obj is another Double with the same value as the current instance. This is
+ // a method of object equality, that only returns true if obj is also a double.
+ public override bool Equals(Object obj) {
+ if (!(obj is Double)) {
+ return false;
+ }
+ double temp = ((Double)obj).m_value;
+ // This code below is written this way for performance reasons i.e the != and == check is intentional.
+ if (temp == m_value) {
+ return true;
+ }
+ return IsNaN(temp) && IsNaN(m_value);
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator ==(Double left, Double right) {
+ return left == right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator !=(Double left, Double right) {
+ return left != right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator <(Double left, Double right) {
+ return left < right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator >(Double left, Double right) {
+ return left > right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator <=(Double left, Double right) {
+ return left <= right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator >=(Double left, Double right) {
+ return left >= right;
+ }
+
+ public bool Equals(Double obj)
+ {
+ if (obj == m_value) {
+ return true;
+ }
+ return IsNaN(obj) && IsNaN(m_value);
+ }
+
+ //The hashcode for a double is the absolute value of the integer representation
+ //of that double.
+ //
+ [System.Security.SecuritySafeCritical]
+ public unsafe override int GetHashCode() {
+ double d = m_value;
+ if (d == 0) {
+ // Ensure that 0 and -0 have the same hash code
+ return 0;
+ }
+ long value = *(long*)(&d);
+ return unchecked((int)value) ^ ((int)(value >> 32));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static double Parse(String s) {
+ return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static double Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static double Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static double Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a double from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ // This method will not throw an OverflowException, but will return
+ // PositiveInfinity or NegativeInfinity for a number that is too
+ // large or too small.
+ //
+ private static double Parse(String s, NumberStyles style, NumberFormatInfo info) {
+ return Number.ParseDouble(s, style, info);
+ }
+
+ public static bool TryParse(String s, out double result) {
+ return TryParse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out double result) {
+ if (s == null) {
+ result = 0;
+ return false;
+ }
+ bool success = Number.TryParseDouble(s, style, info, out result);
+ if (!success) {
+ String sTrim = s.Trim();
+ if (sTrim.Equals(info.PositiveInfinitySymbol)) {
+ result = PositiveInfinity;
+ } else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
+ result = NegativeInfinity;
+ } else if (sTrim.Equals(info.NaNSymbol)) {
+ result = NaN;
+ } else
+ return false; // We really failed
+ }
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Double;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "Char"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/DuplicateWaitObjectException.cs b/src/mscorlib/src/System/DuplicateWaitObjectException.cs
new file mode 100644
index 0000000000..d358d964c2
--- /dev/null
+++ b/src/mscorlib/src/System/DuplicateWaitObjectException.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for duplicate objects in WaitAll/WaitAny.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+
+ // The DuplicateWaitObjectException is thrown when an object
+ // appears more than once in the list of objects to WaitAll or WaitAny.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class DuplicateWaitObjectException : ArgumentException {
+
+ private static volatile String _duplicateWaitObjectMessage = null;
+
+ private static String DuplicateWaitObjectMessage {
+ get {
+ if (_duplicateWaitObjectMessage == null)
+ _duplicateWaitObjectMessage = Environment.GetResourceString("Arg_DuplicateWaitObjectException");
+ return _duplicateWaitObjectMessage;
+ }
+ }
+
+ // Creates a new DuplicateWaitObjectException with its message
+ // string set to a default message.
+ public DuplicateWaitObjectException()
+ : base(DuplicateWaitObjectMessage) {
+ SetErrorCode(__HResults.COR_E_DUPLICATEWAITOBJECT);
+ }
+
+ public DuplicateWaitObjectException(String parameterName)
+ : base(DuplicateWaitObjectMessage, parameterName) {
+ SetErrorCode(__HResults.COR_E_DUPLICATEWAITOBJECT);
+ }
+
+ public DuplicateWaitObjectException(String parameterName, String message)
+ : base(message, parameterName) {
+ SetErrorCode(__HResults.COR_E_DUPLICATEWAITOBJECT);
+ }
+
+ public DuplicateWaitObjectException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_DUPLICATEWAITOBJECT);
+ }
+
+ // This constructor is required for serialization
+ protected DuplicateWaitObjectException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Empty.cs b/src/mscorlib/src/System/Empty.cs
new file mode 100644
index 0000000000..f7e7486014
--- /dev/null
+++ b/src/mscorlib/src/System/Empty.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+////////////////////////////////////////////////////////////////////////////////
+// Empty
+// This class represents an empty variant
+////////////////////////////////////////////////////////////////////////////////
+using System.Diagnostics.Contracts;
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ internal sealed class Empty : ISerializable
+ {
+ private Empty() {
+ }
+
+ public static readonly Empty Value = new Empty();
+
+ public override String ToString()
+ {
+ return String.Empty;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.EmptyUnity, null, null);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/EntryPointNotFoundException.cs b/src/mscorlib/src/System/EntryPointNotFoundException.cs
new file mode 100644
index 0000000000..a65d80058e
--- /dev/null
+++ b/src/mscorlib/src/System/EntryPointNotFoundException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for some failed P/Invoke calls.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class EntryPointNotFoundException : TypeLoadException {
+ public EntryPointNotFoundException()
+ : base(Environment.GetResourceString("Arg_EntryPointNotFoundException")) {
+ SetErrorCode(__HResults.COR_E_ENTRYPOINTNOTFOUND);
+ }
+
+ public EntryPointNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ENTRYPOINTNOTFOUND);
+ }
+
+ public EntryPointNotFoundException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_ENTRYPOINTNOTFOUND);
+ }
+
+ protected EntryPointNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Enum.cs b/src/mscorlib/src/System/Enum.cs
new file mode 100644
index 0000000000..a8104556e4
--- /dev/null
+++ b/src/mscorlib/src/System/Enum.cs
@@ -0,0 +1,1265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using System.Text;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Enum : ValueType, IComparable, IFormattable, IConvertible
+ {
+ #region Private Constants
+ private const char enumSeparatorChar = ',';
+ private const String enumSeparatorString = ", ";
+ #endregion
+
+ #region Private Static Methods
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static TypeValuesAndNames GetCachedValuesAndNames(RuntimeType enumType, bool getNames)
+ {
+ TypeValuesAndNames entry = enumType.GenericCache as TypeValuesAndNames;
+
+ if (entry == null || (getNames && entry.Names == null))
+ {
+ ulong[] values = null;
+ String[] names = null;
+ bool isFlags = enumType.IsDefined(typeof(System.FlagsAttribute), false);
+
+ GetEnumValuesAndNames(
+ enumType.GetTypeHandleInternal(),
+ JitHelpers.GetObjectHandleOnStack(ref values),
+ JitHelpers.GetObjectHandleOnStack(ref names),
+ getNames);
+
+ entry = new TypeValuesAndNames(isFlags, values, names);
+ enumType.GenericCache = entry;
+ }
+
+ return entry;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe String InternalFormattedHexString()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ case CorElementType.U1:
+ return (*(byte*)pValue).ToString("X2", null);
+ case CorElementType.Boolean:
+ // direct cast from bool to byte is not allowed
+ return Convert.ToByte(*(bool*)pValue).ToString("X2", null);
+ case CorElementType.I2:
+ case CorElementType.U2:
+ case CorElementType.Char:
+ return (*(ushort*)pValue).ToString("X4", null);
+ case CorElementType.I4:
+ case CorElementType.U4:
+ return (*(uint*)pValue).ToString("X8", null);
+ case CorElementType.I8:
+ case CorElementType.U8:
+ return (*(ulong*)pValue).ToString("X16", null);
+ default:
+ Contract.Assert(false, "Invalid Object type in Format");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+ }
+
+ private static String InternalFormattedHexString(object value)
+ {
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ switch (typeCode)
+ {
+ case TypeCode.SByte:
+ return ((byte)(sbyte)value).ToString("X2", null);
+ case TypeCode.Byte:
+ return ((byte)value).ToString("X2", null);
+ case TypeCode.Boolean:
+ // direct cast from bool to byte is not allowed
+ return Convert.ToByte((bool)value).ToString("X2", null);
+ case TypeCode.Int16:
+ return ((UInt16)(Int16)value).ToString("X4", null);
+ case TypeCode.UInt16:
+ return ((UInt16)value).ToString("X4", null);
+ case TypeCode.Char:
+ return ((UInt16)(Char)value).ToString("X4", null);
+ case TypeCode.UInt32:
+ return ((UInt32)value).ToString("X8", null);
+ case TypeCode.Int32:
+ return ((UInt32)(Int32)value).ToString("X8", null);
+ case TypeCode.UInt64:
+ return ((UInt64)value).ToString("X16", null);
+ case TypeCode.Int64:
+ return ((UInt64)(Int64)value).ToString("X16", null);
+ // All unsigned types will be directly cast
+ default:
+ Contract.Assert(false, "Invalid Object type in Format");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+
+ internal static String GetEnumName(RuntimeType eT, ulong ulValue)
+ {
+ Contract.Requires(eT != null);
+ ulong[] ulValues = Enum.InternalGetValues(eT);
+ int index = Array.BinarySearch(ulValues, ulValue);
+
+ if (index >= 0)
+ {
+ string[] names = Enum.InternalGetNames(eT);
+ return names[index];
+ }
+
+ return null; // return null so the caller knows to .ToString() the input
+ }
+
+ private static String InternalFormat(RuntimeType eT, ulong value)
+ {
+ Contract.Requires(eT != null);
+
+ // These values are sorted by value. Don't change this
+ TypeValuesAndNames entry = GetCachedValuesAndNames(eT, true);
+
+ if (!entry.IsFlag) // Not marked with Flags attribute
+ {
+ return Enum.GetEnumName(eT, value);
+ }
+ else // These are flags OR'ed together (We treat everything as unsigned types)
+ {
+ return InternalFlagsFormat(eT, entry, value);
+ }
+ }
+
+ private static String InternalFlagsFormat(RuntimeType eT,ulong result)
+ {
+ // These values are sorted by value. Don't change this
+ TypeValuesAndNames entry = GetCachedValuesAndNames(eT, true);
+
+ return InternalFlagsFormat(eT, entry, result);
+ }
+
+ private static String InternalFlagsFormat(RuntimeType eT, TypeValuesAndNames entry, ulong result)
+ {
+ Contract.Requires(eT != null);
+
+ String[] names = entry.Names;
+ ulong[] values = entry.Values;
+ Contract.Assert(names.Length == values.Length);
+
+ int index = values.Length - 1;
+ StringBuilder retval = new StringBuilder();
+ bool firstTime = true;
+ ulong saveResult = result;
+
+ // We will not optimize this code further to keep it maintainable. There are some boundary checks that can be applied
+ // to minimize the comparsions required. This code works the same for the best/worst case. In general the number of
+ // items in an enum are sufficiently small and not worth the optimization.
+ while (index >= 0)
+ {
+ if ((index == 0) && (values[index] == 0))
+ break;
+
+ if ((result & values[index]) == values[index])
+ {
+ result -= values[index];
+ if (!firstTime)
+ retval.Insert(0, enumSeparatorString);
+
+ retval.Insert(0, names[index]);
+ firstTime = false;
+ }
+
+ index--;
+ }
+
+ // We were unable to represent this number as a bitwise or of valid flags
+ if (result != 0)
+ return null; // return null so the caller knows to .ToString() the input
+
+ // For the case when we have zero
+ if (saveResult == 0)
+ {
+ if (values.Length > 0 && values[0] == 0)
+ return names[0]; // Zero was one of the enum values.
+ else
+ return "0";
+ }
+ else
+ {
+ return retval.ToString(); // Return the string representation
+ }
+ }
+
+ internal static ulong ToUInt64(Object value)
+ {
+ // Helper function to silently convert the value to UInt64 from the other base types for enum without throwing an exception.
+ // This is need since the Convert functions do overflow checks.
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ ulong result;
+ switch (typeCode)
+ {
+ case TypeCode.SByte:
+ result = (ulong)(sbyte)value;
+ break;
+ case TypeCode.Byte:
+ result = (byte)value;
+ break;
+ case TypeCode.Boolean:
+ // direct cast from bool to byte is not allowed
+ result = Convert.ToByte((bool)value);
+ break;
+ case TypeCode.Int16:
+ result = (ulong)(Int16)value;
+ break;
+ case TypeCode.UInt16:
+ result = (UInt16)value;
+ break;
+ case TypeCode.Char:
+ result = (UInt16)(Char)value;
+ break;
+ case TypeCode.UInt32:
+ result = (UInt32)value;
+ break;
+ case TypeCode.Int32:
+ result = (ulong)(int)value;
+ break;
+ case TypeCode.UInt64:
+ result = (ulong)value;
+ break;
+ case TypeCode.Int64:
+ result = (ulong)(Int64)value;
+ break;
+ // All unsigned types will be directly cast
+ default:
+ Contract.Assert(false, "Invalid Object type in ToUInt64");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int InternalCompareTo(Object o1, Object o2);
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeType InternalGetUnderlyingType(RuntimeType enumType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [System.Security.SuppressUnmanagedCodeSecurity]
+ private static extern void GetEnumValuesAndNames(RuntimeTypeHandle enumType, ObjectHandleOnStack values, ObjectHandleOnStack names, bool getNames);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object InternalBoxEnum(RuntimeType enumType, long value);
+ #endregion
+
+ #region Public Static Methods
+ private enum ParseFailureKind
+ {
+ None = 0,
+ Argument = 1,
+ ArgumentNull = 2,
+ ArgumentWithParameter = 3,
+ UnhandledException = 4
+ }
+
+ // This will store the result of the parsing.
+ private struct EnumResult
+ {
+ internal object parsedEnum;
+ internal bool canThrow;
+ internal ParseFailureKind m_failure;
+ internal string m_failureMessageID;
+ internal string m_failureParameter;
+ internal object m_failureMessageFormatArgument;
+ internal Exception m_innerException;
+
+ internal void SetFailure(Exception unhandledException)
+ {
+ m_failure = ParseFailureKind.UnhandledException;
+ m_innerException = unhandledException;
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureParameter)
+ {
+ m_failure = failure;
+ m_failureParameter = failureParameter;
+ if (canThrow)
+ throw GetEnumParseException();
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument)
+ {
+ m_failure = failure;
+ m_failureMessageID = failureMessageID;
+ m_failureMessageFormatArgument = failureMessageFormatArgument;
+ if (canThrow)
+ throw GetEnumParseException();
+ }
+ internal Exception GetEnumParseException()
+ {
+ switch (m_failure)
+ {
+ case ParseFailureKind.Argument:
+ return new ArgumentException(Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(m_failureParameter);
+
+ case ParseFailureKind.ArgumentWithParameter:
+ return new ArgumentException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument));
+
+ case ParseFailureKind.UnhandledException:
+ return m_innerException;
+
+ default:
+ Contract.Assert(false, "Unknown EnumParseFailure: " + m_failure);
+ return new ArgumentException(Environment.GetResourceString("Arg_EnumValueNotFound"));
+ }
+ }
+ }
+
+ public static bool TryParse<TEnum>(String value, out TEnum result) where TEnum : struct
+ {
+ return TryParse(value, false, out result);
+ }
+
+ public static bool TryParse<TEnum>(String value, bool ignoreCase, out TEnum result) where TEnum : struct
+ {
+ result = default(TEnum);
+ EnumResult parseResult = new EnumResult();
+ bool retValue;
+
+ if (retValue = TryParseEnum(typeof(TEnum), value, ignoreCase, ref parseResult))
+ result = (TEnum)parseResult.parsedEnum;
+ return retValue;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object Parse(Type enumType, String value)
+ {
+ return Parse(enumType, value, false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object Parse(Type enumType, String value, bool ignoreCase)
+ {
+ EnumResult parseResult = new EnumResult() { canThrow = true };
+ if (TryParseEnum(enumType, value, ignoreCase, ref parseResult))
+ return parseResult.parsedEnum;
+ else
+ throw parseResult.GetEnumParseException();
+ }
+
+ private static bool TryParseEnum(Type enumType, String value, bool ignoreCase, ref EnumResult parseResult)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+
+ if (value == null) {
+ parseResult.SetFailure(ParseFailureKind.ArgumentNull, "value");
+ return false;
+ }
+
+ int firstNonWhitespaceIndex = -1;
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (!Char.IsWhiteSpace(value[i]))
+ {
+ firstNonWhitespaceIndex = i;
+ break;
+ }
+ }
+ if (firstNonWhitespaceIndex == -1) {
+ parseResult.SetFailure(ParseFailureKind.Argument, "Arg_MustContainEnumInfo", null);
+ return false;
+ }
+
+ // We have 2 code paths here. One if they are values else if they are Strings.
+ // values will have the first character as as number or a sign.
+ ulong result = 0;
+
+ char firstNonWhitespaceChar = value[firstNonWhitespaceIndex];
+ if (Char.IsDigit(firstNonWhitespaceChar) || firstNonWhitespaceChar == '-' || firstNonWhitespaceChar == '+')
+ {
+ Type underlyingType = GetUnderlyingType(enumType);
+ Object temp;
+
+ try
+ {
+ value = value.Trim();
+ temp = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture);
+ parseResult.parsedEnum = ToObject(enumType, temp);
+ return true;
+ }
+ catch (FormatException)
+ { // We need to Parse this as a String instead. There are cases
+ // when you tlbimp enums that can have values of the form "3D".
+ // Don't fix this code.
+ }
+ catch (Exception ex)
+ {
+ if (parseResult.canThrow)
+ throw;
+ else
+ {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ }
+
+ // Find the field. Let's assume that these are always static classes
+ // because the class is an enum.
+ TypeValuesAndNames entry = GetCachedValuesAndNames(rtType, true);
+ String[] enumNames = entry.Names;
+ ulong[] enumValues = entry.Values;
+
+ StringComparison comparison = ignoreCase ?
+ StringComparison.OrdinalIgnoreCase :
+ StringComparison.Ordinal;
+
+ int valueIndex = firstNonWhitespaceIndex;
+ while (valueIndex <= value.Length) // '=' is to handle invalid case of an ending comma
+ {
+ // Find the next separator, if there is one, otherwise the end of the string.
+ int endIndex = value.IndexOf(enumSeparatorChar, valueIndex);
+ if (endIndex == -1)
+ {
+ endIndex = value.Length;
+ }
+
+ // Shift the starting and ending indices to eliminate whitespace
+ int endIndexNoWhitespace = endIndex;
+ while (valueIndex < endIndex && Char.IsWhiteSpace(value[valueIndex])) valueIndex++;
+ while (endIndexNoWhitespace > valueIndex && Char.IsWhiteSpace(value[endIndexNoWhitespace - 1])) endIndexNoWhitespace--;
+ int valueSubstringLength = endIndexNoWhitespace - valueIndex;
+
+ // Try to match this substring against each enum name
+ bool success = false;
+ for (int i = 0; i < enumNames.Length; i++)
+ {
+ if (enumNames[i].Length == valueSubstringLength &&
+ string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0)
+ {
+ result |= enumValues[i];
+ success = true;
+ break;
+ }
+ }
+
+ // If we couldn't find a match, throw an argument exception.
+ if (!success)
+ {
+ // Not found, throw an argument exception.
+ parseResult.SetFailure(ParseFailureKind.ArgumentWithParameter, "Arg_EnumValueNotFound", value);
+ return false;
+ }
+
+ // Move our pointer to the ending index to go again.
+ valueIndex = endIndex + 1;
+ }
+
+ try
+ {
+ parseResult.parsedEnum = ToObject(enumType, result);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ if (parseResult.canThrow)
+ throw;
+ else
+ {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Type GetUnderlyingType(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<Type>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumUnderlyingType();
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Array GetValues(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<Array>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumValues();
+ }
+
+ internal static ulong[] InternalGetValues(RuntimeType enumType)
+ {
+ // Get all of the values
+ return GetCachedValuesAndNames(enumType, false).Values;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String GetName(Type enumType, Object value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumName(value);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String[] GetNames(Type enumType)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return enumType.GetEnumNames();
+ }
+
+ internal static String[] InternalGetNames(RuntimeType enumType)
+ {
+ // Get all of the names
+ return GetCachedValuesAndNames(enumType, true).Names;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, Object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Delegate rest of error checking to the other functions
+ TypeCode typeCode = Convert.GetTypeCode(value);
+
+ switch (typeCode)
+ {
+ case TypeCode.Int32 :
+ return ToObject(enumType, (int)value);
+
+ case TypeCode.SByte :
+ return ToObject(enumType, (sbyte)value);
+
+ case TypeCode.Int16 :
+ return ToObject(enumType, (short)value);
+
+ case TypeCode.Int64 :
+ return ToObject(enumType, (long)value);
+
+ case TypeCode.UInt32 :
+ return ToObject(enumType, (uint)value);
+
+ case TypeCode.Byte :
+ return ToObject(enumType, (byte)value);
+
+ case TypeCode.UInt16 :
+ return ToObject(enumType, (ushort)value);
+
+ case TypeCode.UInt64 :
+ return ToObject(enumType, (ulong)value);
+
+ case TypeCode.Char:
+ return ToObject(enumType, (char)value);
+
+ case TypeCode.Boolean:
+ return ToObject(enumType, (bool)value);
+
+ default:
+ // All unsigned types will be directly cast
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+ }
+ }
+
+ [Pure]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static bool IsDefined(Type enumType, Object value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ Contract.EndContractBlock();
+
+ return enumType.IsEnumDefined(value);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static String Format(Type enumType, Object value, String format)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+
+ // Check if both of them are of the same type
+ Type valueType = value.GetType();
+
+ Type underlyingType = GetUnderlyingType(enumType);
+
+ // If the value is an Enum then we need to extract the underlying value from it
+ if (valueType.IsEnum) {
+
+ if (!valueType.IsEquivalentTo(enumType))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), enumType.ToString()));
+
+ if (format.Length != 1)
+ {
+ // all acceptable format string are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+ return ((Enum)value).ToString(format);
+ }
+ // The value must be of the same type as the Underlying type of the Enum
+ else if (valueType != underlyingType) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+ }
+ if (format.Length != 1)
+ {
+ // all acceptable format string are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ char formatCh = format[0];
+ if (formatCh == 'G' || formatCh == 'g')
+ return GetEnumName(rtType, ToUInt64(value));
+
+ if (formatCh == 'D' || formatCh == 'd')
+ return value.ToString();
+
+ if (formatCh == 'X' || formatCh == 'x')
+ return InternalFormattedHexString(value);
+
+ if (formatCh == 'F' || formatCh == 'f')
+ return Enum.InternalFlagsFormat(rtType, ToUInt64(value)) ?? value.ToString();
+
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ #endregion
+
+ #region Definitions
+ private class TypeValuesAndNames
+ {
+ // Each entry contains a list of sorted pair of enum field names and values, sorted by values
+ public TypeValuesAndNames(bool isFlag, ulong[] values, String[] names)
+ {
+ this.IsFlag = isFlag;
+ this.Values = values;
+ this.Names = names;
+ }
+
+ public bool IsFlag;
+ public ulong[] Values;
+ public String[] Names;
+ }
+ #endregion
+
+ #region Private Methods
+ [System.Security.SecuritySafeCritical]
+ internal unsafe Object GetValue()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return *(sbyte*)pValue;
+ case CorElementType.U1:
+ return *(byte*)pValue;
+ case CorElementType.Boolean:
+ return *(bool*)pValue;
+ case CorElementType.I2:
+ return *(short*)pValue;
+ case CorElementType.U2:
+ return *(ushort*)pValue;
+ case CorElementType.Char:
+ return *(char*)pValue;
+ case CorElementType.I4:
+ return *(int*)pValue;
+ case CorElementType.U4:
+ return *(uint*)pValue;
+ case CorElementType.R4:
+ return *(float*)pValue;
+ case CorElementType.I8:
+ return *(long*)pValue;
+ case CorElementType.U8:
+ return *(ulong*)pValue;
+ case CorElementType.R8:
+ return *(double*)pValue;
+ case CorElementType.I:
+ return *(IntPtr*)pValue;
+ case CorElementType.U:
+ return *(UIntPtr*)pValue;
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return null;
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe ulong ToUInt64()
+ {
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return (ulong)*(sbyte*)pValue;
+ case CorElementType.U1:
+ return *(byte*)pValue;
+ case CorElementType.Boolean:
+ return Convert.ToUInt64(*(bool*)pValue, CultureInfo.InvariantCulture);
+ case CorElementType.I2:
+ return (ulong)*(short*)pValue;
+ case CorElementType.U2:
+ case CorElementType.Char:
+ return *(ushort*)pValue;
+ case CorElementType.I4:
+ return (ulong)*(int*)pValue;
+ case CorElementType.U4:
+ case CorElementType.R4:
+ return *(uint*)pValue;
+ case CorElementType.I8:
+ return (ulong)*(long*)pValue;
+ case CorElementType.U8:
+ case CorElementType.R8:
+ return *(ulong*)pValue;
+ case CorElementType.I:
+ if (IntPtr.Size == 8)
+ {
+ return *(ulong*)pValue;
+ }
+ else
+ {
+ return (ulong)*(int*)pValue;
+ }
+ case CorElementType.U:
+ if (IntPtr.Size == 8)
+ {
+ return *(ulong*)pValue;
+ }
+ else
+ {
+ return *(uint*)pValue;
+ }
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return 0;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool InternalHasFlag(Enum flags);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern CorElementType InternalGetCorElementType();
+
+ #endregion
+
+ #region Object Overrides
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern override bool Equals(Object obj);
+
+ [System.Security.SecuritySafeCritical]
+ public override unsafe int GetHashCode()
+ {
+ // Avoid boxing by inlining GetValue()
+ // return GetValue().GetHashCode();
+
+ fixed (void* pValue = &JitHelpers.GetPinningHelper(this).m_data)
+ {
+ switch (InternalGetCorElementType())
+ {
+ case CorElementType.I1:
+ return (*(sbyte*)pValue).GetHashCode();
+ case CorElementType.U1:
+ return (*(byte*)pValue).GetHashCode();
+ case CorElementType.Boolean:
+ return (*(bool*)pValue).GetHashCode();
+ case CorElementType.I2:
+ return (*(short*)pValue).GetHashCode();
+ case CorElementType.U2:
+ return (*(ushort*)pValue).GetHashCode();
+ case CorElementType.Char:
+ return (*(char*)pValue).GetHashCode();
+ case CorElementType.I4:
+ return (*(int*)pValue).GetHashCode();
+ case CorElementType.U4:
+ return (*(uint*)pValue).GetHashCode();
+ case CorElementType.R4:
+ return (*(float*)pValue).GetHashCode();
+ case CorElementType.I8:
+ return (*(long*)pValue).GetHashCode();
+ case CorElementType.U8:
+ return (*(ulong*)pValue).GetHashCode();
+ case CorElementType.R8:
+ return (*(double*)pValue).GetHashCode();
+ case CorElementType.I:
+ return (*(IntPtr*)pValue).GetHashCode();
+ case CorElementType.U:
+ return (*(UIntPtr*)pValue).GetHashCode();
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ return 0;
+ }
+ }
+ }
+
+ public override String ToString()
+ {
+ // Returns the value in a human readable format. For PASCAL style enums who's value maps directly the name of the field is returned.
+ // For PASCAL style enums who's values do not map directly the decimal value of the field is returned.
+ // For BitFlags (indicated by the Flags custom attribute): If for each bit that is set in the value there is a corresponding constant
+ //(a pure power of 2), then the OR string (ie "Red | Yellow") is returned. Otherwise, if the value is zero or if you can't create a string that consists of
+ // pure powers of 2 OR-ed together, you return a hex value
+
+
+ // Try to see if its one of the enum values, then we return a String back else the value
+ return Enum.InternalFormat((RuntimeType)GetType(), ToUInt64()) ?? GetValue().ToString();
+ }
+ #endregion
+
+ #region IFormattable
+ [Obsolete("The provider argument is not used. Please use ToString(String).")]
+ public String ToString(String format, IFormatProvider provider)
+ {
+ return ToString(format);
+ }
+ #endregion
+
+ #region IComparable
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int CompareTo(Object target)
+ {
+ const int retIncompatibleMethodTables = 2; // indicates that the method tables did not match
+ const int retInvalidEnumType = 3; // indicates that the enum was of an unknown/unsupported unerlying type
+
+ if (this == null)
+ throw new NullReferenceException();
+ Contract.EndContractBlock();
+
+ int ret = InternalCompareTo(this, target);
+
+ if (ret < retIncompatibleMethodTables)
+ {
+ // -1, 0 and 1 are the normal return codes
+ return ret;
+ }
+ else if (ret == retIncompatibleMethodTables)
+ {
+ Type thisType = this.GetType();
+ Type targetType = target.GetType();
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType",
+ targetType.ToString(), thisType.ToString()));
+ }
+ else
+ {
+ // assert valid return code (3)
+ Contract.Assert(ret == retInvalidEnumType, "Enum.InternalCompareTo return code was invalid");
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+ #endregion
+
+ #region Public Methods
+ public String ToString(String format) {
+ char formatCh;
+ if (format == null || format.Length == 0)
+ formatCh = 'G';
+ else if (format.Length != 1)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ else
+ formatCh = format[0];
+
+ if (formatCh == 'G' || formatCh == 'g')
+ return ToString();
+
+ if (formatCh == 'D' || formatCh == 'd')
+ return GetValue().ToString();
+
+ if (formatCh == 'X' || formatCh == 'x')
+ return InternalFormattedHexString();
+
+ if (formatCh == 'F' || formatCh == 'f')
+ return InternalFlagsFormat((RuntimeType)GetType(), ToUInt64()) ?? GetValue().ToString();
+
+ throw new FormatException(Environment.GetResourceString("Format_InvalidEnumFormatSpecification"));
+ }
+
+ [Obsolete("The provider argument is not used. Please use ToString().")]
+ public String ToString(IFormatProvider provider)
+ {
+ return ToString();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public Boolean HasFlag(Enum flag) {
+ if (flag == null)
+ throw new ArgumentNullException("flag");
+ Contract.EndContractBlock();
+
+ if (!this.GetType().IsEquivalentTo(flag.GetType())) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EnumTypeDoesNotMatch", flag.GetType(), this.GetType()));
+ }
+
+ return InternalHasFlag(flag);
+ }
+
+ #endregion
+
+ #region IConvertable
+ public TypeCode GetTypeCode()
+ {
+ Type enumType = this.GetType();
+ Type underlyingType = GetUnderlyingType(enumType);
+
+ if (underlyingType == typeof(Int32))
+ {
+ return TypeCode.Int32;
+ }
+
+ if (underlyingType == typeof(sbyte))
+ {
+ return TypeCode.SByte;
+ }
+
+ if (underlyingType == typeof(Int16))
+ {
+ return TypeCode.Int16;
+ }
+
+ if (underlyingType == typeof(Int64))
+ {
+ return TypeCode.Int64;
+ }
+
+ if (underlyingType == typeof(UInt32))
+ {
+ return TypeCode.UInt32;
+ }
+
+ if (underlyingType == typeof(byte))
+ {
+ return TypeCode.Byte;
+ }
+
+ if (underlyingType == typeof(UInt16))
+ {
+ return TypeCode.UInt16;
+ }
+
+ if (underlyingType == typeof(UInt64))
+ {
+ return TypeCode.UInt64;
+ }
+
+ if (underlyingType == typeof(Boolean))
+ {
+ return TypeCode.Boolean;
+ }
+
+ if (underlyingType == typeof(Char))
+ {
+ return TypeCode.Char;
+ }
+
+ Contract.Assert(false, "Unknown underlying type.");
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider)
+ {
+ return Convert.ToBoolean(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider)
+ {
+ return Convert.ToChar(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider)
+ {
+ return Convert.ToSByte(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider)
+ {
+ return Convert.ToByte(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider)
+ {
+ return Convert.ToInt16(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider)
+ {
+ return Convert.ToUInt16(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider)
+ {
+ return Convert.ToInt32(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider)
+ {
+ return Convert.ToUInt32(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider)
+ {
+ return Convert.ToInt64(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider)
+ {
+ return Convert.ToUInt64(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider)
+ {
+ return Convert.ToSingle(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider)
+ {
+ return Convert.ToDouble(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider)
+ {
+ return Convert.ToDecimal(GetValue(), CultureInfo.CurrentCulture);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider)
+ {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Enum", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider)
+ {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ #endregion
+
+ #region ToObject
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, sbyte value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, short value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, int value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, byte value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, ushort value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, uint value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, long value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static Object ToObject(Type enumType, ulong value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, unchecked((long)value));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Object ToObject(Type enumType, char value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Object ToObject(Type enumType, bool value)
+ {
+ if (enumType == null)
+ throw new ArgumentNullException("enumType");
+ if (!enumType.IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+ RuntimeType rtType = enumType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "enumType");
+ return InternalBoxEnum(rtType, value ? 1 : 0);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Environment.cs b/src/mscorlib/src/System/Environment.cs
new file mode 100644
index 0000000000..5ee30bb9ba
--- /dev/null
+++ b/src/mscorlib/src/System/Environment.cs
@@ -0,0 +1,1768 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Provides some basic access to some environment
+** functionality.
+**
+**
+============================================================*/
+namespace System {
+ using System.IO;
+ using System.Security;
+ using System.Resources;
+ using System.Globalization;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Configuration.Assemblies;
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using System.Diagnostics;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Threading;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [ComVisible(true)]
+ public enum EnvironmentVariableTarget {
+ Process = 0,
+#if FEATURE_WIN32_REGISTRY
+ User = 1,
+ Machine = 2,
+#endif
+ }
+
+ [ComVisible(true)]
+ public static class Environment {
+
+ // Assume the following constants include the terminating '\0' - use <, not <=
+ const int MaxEnvVariableValueLength = 32767; // maximum length for environment variable name and value
+ // System environment variables are stored in the registry, and have
+ // a size restriction that is separate from both normal environment
+ // variables and registry value name lengths, according to MSDN.
+ // MSDN doesn't detail whether the name is limited to 1024, or whether
+ // that includes the contents of the environment variable.
+ const int MaxSystemEnvVariableLength = 1024;
+ const int MaxUserEnvVariableLength = 255;
+
+ internal sealed class ResourceHelper
+ {
+ internal ResourceHelper(String name) {
+ m_name = name;
+ }
+
+ private String m_name;
+ private ResourceManager SystemResMgr;
+
+ // To avoid infinite loops when calling GetResourceString. See comments
+ // in GetResourceString for this field.
+ private List<string> currentlyLoading;
+
+ // process-wide state (since this is only used in one domain),
+ // used to avoid the TypeInitialization infinite recusion
+ // in GetResourceStringCode
+ internal bool resourceManagerInited = false;
+
+ // Is this thread currently doing infinite resource lookups?
+ private int infinitelyRecursingCount;
+
+ // Data representing one individual resource lookup on a thread.
+ internal class GetResourceStringUserData
+ {
+ public ResourceHelper m_resourceHelper;
+ public String m_key;
+ public String m_retVal;
+ public bool m_lockWasTaken;
+
+ public GetResourceStringUserData(ResourceHelper resourceHelper, String key)
+ {
+ m_resourceHelper = resourceHelper;
+ m_key = key;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal String GetResourceString(String key) {
+ if (key == null || key.Length == 0) {
+ Contract.Assert(false, "Environment::GetResourceString with null or empty key. Bug in caller, or weird recursive loading problem?");
+ return "[Resource lookup failed - null or empty resource name]";
+ }
+
+ // We have a somewhat common potential for infinite
+ // loops with mscorlib's ResourceManager. If "potentially dangerous"
+ // code throws an exception, we will get into an infinite loop
+ // inside the ResourceManager and this "potentially dangerous" code.
+ // Potentially dangerous code includes the IO package, CultureInfo,
+ // parts of the loader, some parts of Reflection, Security (including
+ // custom user-written permissions that may parse an XML file at
+ // class load time), assembly load event handlers, etc. Essentially,
+ // this is not a bounded set of code, and we need to fix the problem.
+ // Fortunately, this is limited to mscorlib's error lookups and is NOT
+ // a general problem for all user code using the ResourceManager.
+
+ // The solution is to make sure only one thread at a time can call
+ // GetResourceString. Also, since resource lookups can be
+ // reentrant, if the same thread comes into GetResourceString
+ // twice looking for the exact same resource name before
+ // returning, we're going into an infinite loop and we should
+ // return a bogus string.
+
+ GetResourceStringUserData userData = new GetResourceStringUserData(this, key);
+
+ RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(GetResourceStringCode);
+ RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(GetResourceStringBackoutCode);
+
+ RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData);
+ return userData.m_retVal;
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ private void GetResourceStringCode(Object userDataIn)
+ {
+ GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
+ ResourceHelper rh = userData.m_resourceHelper;
+ String key = userData.m_key;
+
+ Monitor.Enter(rh, ref userData.m_lockWasTaken);
+
+ // Are we recursively looking up the same resource? Note - our backout code will set
+ // the ResourceHelper's currentlyLoading stack to null if an exception occurs.
+ if (rh.currentlyLoading != null && rh.currentlyLoading.Count > 0 && rh.currentlyLoading.LastIndexOf(key) != -1) {
+ // We can start infinitely recursing for one resource lookup,
+ // then during our failure reporting, start infinitely recursing again.
+ // avoid that.
+ if (rh.infinitelyRecursingCount > 0) {
+ userData.m_retVal = "[Resource lookup failed - infinite recursion or critical failure detected.]";
+ return;
+ }
+ rh.infinitelyRecursingCount++;
+
+ // Note: our infrastructure for reporting this exception will again cause resource lookup.
+ // This is the most direct way of dealing with that problem.
+ String message = "Infinite recursion during resource lookup within "+System.CoreLib.Name+". This may be a bug in "+System.CoreLib.Name+", or potentially in certain extensibility points such as assembly resolve events or CultureInfo names. Resource name: " + key;
+ Assert.Fail("[Recursive resource lookup bug]", message, Assert.COR_E_FAILFAST, System.Diagnostics.StackTrace.TraceFormat.NoResourceLookup);
+ Environment.FailFast(message);
+ }
+ if (rh.currentlyLoading == null)
+ rh.currentlyLoading = new List<string>();
+
+ // Call class constructors preemptively, so that we cannot get into an infinite
+ // loop constructing a TypeInitializationException. If this were omitted,
+ // we could get the Infinite recursion assert above by failing type initialization
+ // between the Push and Pop calls below.
+
+ if (!rh.resourceManagerInited)
+ {
+ // process-critical code here. No ThreadAbortExceptions
+ // can be thrown here. Other exceptions percolate as normal.
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ RuntimeHelpers.RunClassConstructor(typeof(ResourceManager).TypeHandle);
+ RuntimeHelpers.RunClassConstructor(typeof(ResourceReader).TypeHandle);
+ RuntimeHelpers.RunClassConstructor(typeof(RuntimeResourceSet).TypeHandle);
+ RuntimeHelpers.RunClassConstructor(typeof(BinaryReader).TypeHandle);
+ rh.resourceManagerInited = true;
+ }
+
+ }
+
+ rh.currentlyLoading.Add(key); // Push
+
+ if (rh.SystemResMgr == null) {
+ rh.SystemResMgr = new ResourceManager(m_name, typeof(Object).Assembly);
+ }
+ String s = rh.SystemResMgr.GetString(key, null);
+ rh.currentlyLoading.RemoveAt(rh.currentlyLoading.Count - 1); // Pop
+
+ Contract.Assert(s!=null, "Managed resource string lookup failed. Was your resource name misspelled? Did you rebuild mscorlib after adding a resource to resources.txt? Debug this w/ cordbg and bug whoever owns the code that called Environment.GetResourceString. Resource name was: \""+key+"\"");
+
+ userData.m_retVal = s;
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ [PrePrepareMethod]
+ private void GetResourceStringBackoutCode(Object userDataIn, bool exceptionThrown)
+ {
+ GetResourceStringUserData userData = (GetResourceStringUserData) userDataIn;
+ ResourceHelper rh = userData.m_resourceHelper;
+
+ if (exceptionThrown)
+ {
+ if (userData.m_lockWasTaken)
+ {
+ // Backout code - throw away potentially corrupt state
+ rh.SystemResMgr = null;
+ rh.currentlyLoading = null;
+ }
+ }
+ // Release the lock, if we took it.
+ if (userData.m_lockWasTaken)
+ {
+ Monitor.Exit(rh);
+ }
+ }
+
+ }
+
+ private static volatile ResourceHelper m_resHelper; // Doesn't need to be initialized as they're zero-init.
+
+ private const int MaxMachineNameLength = 256;
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ get {
+ if (s_InternalSyncObject == null) {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+
+ private static volatile OperatingSystem m_os; // Cached OperatingSystem value
+
+ /*==================================TickCount===================================
+ **Action: Gets the number of ticks since the system was started.
+ **Returns: The number of ticks since the system was started.
+ **Arguments: None
+ **Exceptions: None
+ ==============================================================================*/
+ public static extern int TickCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ // Terminates this process with the given exit code.
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void _Exit(int exitCode);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public static void Exit(int exitCode) {
+ _Exit(exitCode);
+ }
+
+
+ public static extern int ExitCode {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ set;
+ }
+
+ // Note: The CLR's Watson bucketization code looks at the caller of the FCALL method
+ // to assign blame for crashes. Don't mess with this, such as by making it call
+ // another managed helper method, unless you consult with some CLR Watson experts.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void FailFast(String message);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void FailFast(String message, uint exitCode);
+
+ // This overload of FailFast will allow you to specify the exception object
+ // whose bucket details *could* be used when undergoing the failfast process.
+ // To be specific:
+ //
+ // 1) When invoked from within a managed EH clause (fault/finally/catch),
+ // if the exception object is preallocated, the runtime will try to find its buckets
+ // and use them. If the exception object is not preallocated, it will use the bucket
+ // details contained in the object (if any).
+ //
+ // 2) When invoked from outside the managed EH clauses (fault/finally/catch),
+ // if the exception object is preallocated, the runtime will use the callsite's
+ // IP for bucketing. If the exception object is not preallocated, it will use the bucket
+ // details contained in the object (if any).
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void FailFast(String message, Exception exception);
+
+#if !FEATURE_CORECLR
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods.
+ [SuppressUnmanagedCodeSecurity]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static extern void TriggerCodeContractFailure(ContractFailureKind failureKind, String message, String condition, String exceptionAsString);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods.
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool GetIsCLRHosted();
+
+ internal static bool IsCLRHosted {
+ [SecuritySafeCritical]
+ get { return GetIsCLRHosted(); }
+ }
+
+ public static String CommandLine {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
+
+ String commandLine = null;
+ GetCommandLine(JitHelpers.GetStringHandleOnStack(ref commandLine));
+ return commandLine;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void GetCommandLine(StringHandleOnStack retString);
+#endif // !FEATURE_CORECLR
+
+ /*===============================CurrentDirectory===============================
+ **Action: Provides a getter and setter for the current directory. The original
+ ** current directory is the one from which the process was started.
+ **Returns: The current directory (from the getter). Void from the setter.
+ **Arguments: The current directory to which to switch to the setter.
+ **Exceptions:
+ ==============================================================================*/
+ public static String CurrentDirectory
+ {
+ get{
+ return Directory.GetCurrentDirectory();
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ set {
+ Directory.SetCurrentDirectory(value);
+ }
+ }
+
+ // Returns the system directory (ie, C:\WinNT\System32).
+ public static String SystemDirectory {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+#else
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ get {
+ StringBuilder sb = new StringBuilder(Path.MaxPath);
+ int r = Win32Native.GetSystemDirectory(sb, Path.MaxPath);
+ Contract.Assert(r < Path.MaxPath, "r < Path.MaxPath");
+ if (r==0) __Error.WinIOError();
+ String path = sb.ToString();
+
+#if !FEATURE_CORECLR
+ // Do security check
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
+#endif
+
+ return path;
+ }
+ }
+
+ // Returns the windows directory (ie, C:\WinNT).
+ // Used by NLS+ custom culures only at the moment.
+ internal static String InternalWindowsDirectory {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ StringBuilder sb = new StringBuilder(Path.MaxPath);
+ int r = Win32Native.GetWindowsDirectory(sb, Path.MaxPath);
+ Contract.Assert(r < Path.MaxPath, "r < Path.MaxPath");
+ if (r==0) __Error.WinIOError();
+ String path = sb.ToString();
+
+ return path;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ExpandEnvironmentVariables(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ if (name.Length == 0) {
+ return name;
+ }
+
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
+ // Environment variable accessors are not approved modern API.
+ // Behave as if no variables are defined in this case.
+ return name;
+ }
+
+ int currentSize = 100;
+ StringBuilder blob = new StringBuilder(currentSize); // A somewhat reasonable default size
+
+#if PLATFORM_UNIX // Win32Native.ExpandEnvironmentStrings isn't available
+ int lastPos = 0, pos;
+ while (lastPos < name.Length && (pos = name.IndexOf('%', lastPos + 1)) >= 0)
+ {
+ if (name[lastPos] == '%')
+ {
+ string key = name.Substring(lastPos + 1, pos - lastPos - 1);
+ string value = Environment.GetEnvironmentVariable(key);
+ if (value != null)
+ {
+ blob.Append(value);
+ lastPos = pos + 1;
+ continue;
+ }
+ }
+ blob.Append(name.Substring(lastPos, pos - lastPos));
+ lastPos = pos;
+ }
+ blob.Append(name.Substring(lastPos));
+#else
+
+ int size;
+
+#if !FEATURE_CORECLR
+ bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
+
+ // Do a security check to guarantee we can read each of the
+ // individual environment variables requested here.
+ String[] varArray = name.Split(new char[] {'%'});
+ StringBuilder vars = isFullTrust ? null : new StringBuilder();
+
+ bool fJustExpanded = false; // to accommodate expansion alg.
+
+ for(int i=1; i<varArray.Length-1; i++) { // Skip first and last tokens
+ // ExpandEnvironmentStrings' greedy algorithm expands every
+ // non-boundary %-delimited substring, provided the previous
+ // has not been expanded.
+ // if "foo" is not expandable, and "PATH" is, then both
+ // %foo%PATH% and %foo%foo%PATH% will expand PATH, but
+ // %PATH%PATH% will expand only once.
+ // Therefore, if we've just expanded, skip this substring.
+ if (varArray[i].Length == 0 || fJustExpanded == true)
+ {
+ fJustExpanded = false;
+ continue; // Nothing to expand
+ }
+ // Guess a somewhat reasonable initial size, call the method, then if
+ // it fails (ie, the return value is larger than our buffer size),
+ // make a new buffer & try again.
+ blob.Length = 0;
+ String envVar = "%" + varArray[i] + "%";
+ size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
+ if (size == 0)
+ Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+
+ // some environment variable might be changed while this function is called
+ while (size > currentSize) {
+ currentSize = size;
+ blob.Capacity = currentSize;
+ blob.Length = 0;
+ size = Win32Native.ExpandEnvironmentStrings(envVar, blob, currentSize);
+ if (size == 0)
+ Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+ }
+
+ if (!isFullTrust) {
+ String temp = blob.ToString();
+ fJustExpanded = (temp != envVar);
+ if (fJustExpanded) { // We expanded successfully, we need to do String comparison here
+ // since %FOO% can become %FOOD
+ vars.Append(varArray[i]);
+ vars.Append(';');
+ }
+ }
+ }
+
+ if (!isFullTrust)
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
+#endif // !FEATURE_CORECLR
+
+ blob.Length = 0;
+ size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
+ if (size == 0)
+ Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+
+ while (size > currentSize) {
+ currentSize = size;
+ blob.Capacity = currentSize;
+ blob.Length = 0;
+
+ size = Win32Native.ExpandEnvironmentStrings(name, blob, currentSize);
+ if (size == 0)
+ Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
+ }
+#endif // PLATFORM_UNIX
+
+ return blob.ToString();
+ }
+
+ public static String MachineName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+
+ // UWP Debug scenarios
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode())
+ {
+ // Getting Computer Name is not a supported scenario on Store apps.
+ throw new PlatformNotSupportedException();
+ }
+
+ // In future release of operating systems, you might be able to rename a machine without
+ // rebooting. Therefore, don't cache this machine name.
+#if !FEATURE_CORECLR
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read, "COMPUTERNAME").Demand();
+#endif
+ StringBuilder buf = new StringBuilder(MaxMachineNameLength);
+ int len = MaxMachineNameLength;
+ if (Win32Native.GetComputerName(buf, ref len) == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ComputerName"));
+ return buf.ToString();
+ }
+ }
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern Int32 GetProcessorCount();
+
+ public static int ProcessorCount {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return GetProcessorCount();
+ }
+ }
+
+ public static int SystemPageSize {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
+ Win32Native.SYSTEM_INFO info = new Win32Native.SYSTEM_INFO();
+ Win32Native.GetSystemInfo(ref info);
+ return info.dwPageSize;
+ }
+ }
+
+ /*==============================GetCommandLineArgs==============================
+ **Action: Gets the command line and splits it appropriately to deal with whitespace,
+ ** quotes, and escape characters.
+ **Returns: A string array containing your command line arguments.
+ **Arguments: None
+ **Exceptions: None.
+ ==============================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String[] GetCommandLineArgs()
+ {
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read, "Path").Demand();
+#if FEATURE_CORECLR
+ /*
+ * There are multiple entry points to a hosted app.
+ * The host could use ::ExecuteAssembly() or ::CreateDelegate option
+ * ::ExecuteAssembly() -> In this particular case, the runtime invokes the main
+ method based on the arguments set by the host, and we return those arguments
+ *
+ * ::CreateDelegate() -> In this particular case, the host is asked to create a
+ * delegate based on the appDomain, assembly and methodDesc passed to it.
+ * which the caller uses to invoke the method. In this particular case we do not have
+ * any information on what arguments would be passed to the delegate.
+ * So our best bet is to simply use the commandLine that was used to invoke the process.
+ * in case it is present.
+ */
+ if(s_CommandLineArgs != null)
+ return (string[])s_CommandLineArgs.Clone();
+#endif
+ return GetCommandLineArgsNative();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern String[] GetCommandLineArgsNative();
+
+#if !FEATURE_CORECLR
+ // We need to keep this Fcall since it is used in AppDomain.cs.
+ // If we call GetEnvironmentVariable from AppDomain.cs, we will use StringBuilder class.
+ // That has side effect to change the ApartmentState of the calling Thread to MTA.
+ // So runtime can't change the ApartmentState of calling thread any more.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String nativeGetEnvironmentVariable(String variable);
+#endif //!FEATURE_CORECLR
+
+#if FEATURE_CORECLR
+ private static string[] s_CommandLineArgs = null;
+ private static void SetCommandLineArgs(string[] cmdLineArgs)
+ {
+ s_CommandLineArgs = cmdLineArgs;
+ }
+#endif
+
+ /*============================GetEnvironmentVariable============================
+ **Action:
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String GetEnvironmentVariable(String variable)
+ {
+ if (variable == null)
+ throw new ArgumentNullException("variable");
+ Contract.EndContractBlock();
+
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
+ // Environment variable accessors are not approved modern API.
+ // Behave as if the variable was not found in this case.
+ return null;
+ }
+
+#if !FEATURE_CORECLR
+ (new EnvironmentPermission(EnvironmentPermissionAccess.Read, variable)).Demand();
+#endif //!FEATURE_CORECLR
+
+ StringBuilder blob = StringBuilderCache.Acquire(128); // A somewhat reasonable default size
+ int requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
+
+ if (requiredSize == 0) { // GetEnvironmentVariable failed
+ if (Marshal.GetLastWin32Error() == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
+ StringBuilderCache.Release(blob);
+ return null;
+ }
+ }
+
+ while (requiredSize > blob.Capacity) { // need to retry since the environment variable might be changed
+ blob.Capacity = requiredSize;
+ blob.Length = 0;
+ requiredSize = Win32Native.GetEnvironmentVariable(variable, blob, blob.Capacity);
+ }
+ return StringBuilderCache.GetStringAndRelease(blob);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static string GetEnvironmentVariable( string variable, EnvironmentVariableTarget target)
+ {
+ if (variable == null)
+ {
+ throw new ArgumentNullException("variable");
+ }
+ Contract.EndContractBlock();
+
+ if (target == EnvironmentVariableTarget.Process)
+ {
+ return GetEnvironmentVariable(variable);
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
+
+ if( target == EnvironmentVariableTarget.Machine) {
+ using (RegistryKey environmentKey =
+ Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
+
+ Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
+ if (environmentKey == null) {
+ return null;
+ }
+
+ string value = environmentKey.GetValue(variable) as string;
+ return value;
+ }
+ }
+ else if( target == EnvironmentVariableTarget.User) {
+ using (RegistryKey environmentKey =
+ Registry.CurrentUser.OpenSubKey("Environment", false)) {
+
+ Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
+ if (environmentKey == null) {
+ return null;
+ }
+
+ string value = environmentKey.GetValue(variable) as string;
+ return value;
+ }
+ }
+ else
+#endif // FEATURE_WIN32_REGISTRY
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
+ }
+ }
+
+ /*===========================GetEnvironmentVariables============================
+ **Action: Returns an IDictionary containing all enviroment variables and their values.
+ **Returns: An IDictionary containing all environment variables and their values.
+ **Arguments: None.
+ **Exceptions: None.
+ ==============================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static char[] GetEnvironmentCharArray()
+ {
+ char[] block = null;
+
+ // Make sure pStrings is not leaked with async exceptions
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ char * pStrings = null;
+
+ try
+ {
+ pStrings = Win32Native.GetEnvironmentStrings();
+ if (pStrings == null) {
+ throw new OutOfMemoryException();
+ }
+
+ // Format for GetEnvironmentStrings is:
+ // [=HiddenVar=value\0]* [Variable=value\0]* \0
+ // See the description of Environment Blocks in MSDN's
+ // CreateProcess page (null-terminated array of null-terminated strings).
+
+ // Search for terminating \0\0 (two unicode \0's).
+ char * p = pStrings;
+ while (!(*p == '\0' && *(p + 1) == '\0'))
+ p++;
+
+ int len = (int)(p - pStrings + 1);
+ block = new char[len];
+
+ fixed (char* pBlock = block)
+ String.wstrcpy(pBlock, pStrings, len);
+ }
+ finally
+ {
+ if (pStrings != null)
+ Win32Native.FreeEnvironmentStrings(pStrings);
+ }
+ }
+
+ return block;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static IDictionary GetEnvironmentVariables()
+ {
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
+ // Environment variable accessors are not approved modern API.
+ // Behave as if no environment variables are defined in this case.
+ return new Hashtable(0);
+ }
+
+#if !FEATURE_CORECLR
+ bool isFullTrust = CodeAccessSecurityEngine.QuickCheckForAllDemands();
+ StringBuilder vars = isFullTrust ? null : new StringBuilder();
+ bool first = true;
+#endif
+
+ char[] block = GetEnvironmentCharArray();
+
+ Hashtable table = new Hashtable(20);
+
+ // Copy strings out, parsing into pairs and inserting into the table.
+ // The first few environment variable entries start with an '='!
+ // The current working directory of every drive (except for those drives
+ // you haven't cd'ed into in your DOS window) are stored in the
+ // environment block (as =C:=pwd) and the program's exit code is
+ // as well (=ExitCode=00000000) Skip all that start with =.
+ // Read docs about Environment Blocks on MSDN's CreateProcess page.
+
+ // Format for GetEnvironmentStrings is:
+ // (=HiddenVar=value\0 | Variable=value\0)* \0
+ // See the description of Environment Blocks in MSDN's
+ // CreateProcess page (null-terminated array of null-terminated strings).
+ // Note the =HiddenVar's aren't always at the beginning.
+
+ for(int i=0; i<block.Length; i++) {
+ int startKey = i;
+ // Skip to key
+ // On some old OS, the environment block can be corrupted.
+ // Someline will not have '=', so we need to check for '\0'.
+ while(block[i]!='=' && block[i] != '\0') {
+ i++;
+ }
+
+ if(block[i] == '\0') {
+ continue;
+ }
+
+ // Skip over environment variables starting with '='
+ if (i-startKey==0) {
+ while(block[i]!=0) {
+ i++;
+ }
+ continue;
+ }
+ String key = new String(block, startKey, i-startKey);
+ i++; // skip over '='
+ int startValue = i;
+ while(block[i]!=0) {
+ // Read to end of this entry
+ i++;
+ }
+
+ String value = new String(block, startValue, i-startValue);
+ // skip over 0 handled by for loop's i++
+ table[key]=value;
+
+#if !FEATURE_CORECLR
+ if (!isFullTrust) {
+ if( first) {
+ first = false;
+ }
+ else {
+ vars.Append(';');
+ }
+ vars.Append(key);
+ }
+#endif
+ }
+
+#if !FEATURE_CORECLR
+ if (!isFullTrust)
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read, vars.ToString()).Demand();
+#endif
+ return table;
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ internal static IDictionary GetRegistryKeyNameValuePairs(RegistryKey registryKey) {
+ Hashtable table = new Hashtable(20);
+
+ if (registryKey != null) {
+ string[] names = registryKey.GetValueNames();
+ foreach( string name in names) {
+ string value = registryKey.GetValue(name, "").ToString();
+ table.Add(name, value);
+ }
+ }
+ return table;
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static IDictionary GetEnvironmentVariables( EnvironmentVariableTarget target) {
+ if( target == EnvironmentVariableTarget.Process) {
+ return GetEnvironmentVariables();
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ (new EnvironmentPermission(PermissionState.Unrestricted)).Demand();
+
+ if( target == EnvironmentVariableTarget.Machine) {
+ using (RegistryKey environmentKey =
+ Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", false)) {
+
+ return GetRegistryKeyNameValuePairs(environmentKey);
+ }
+ }
+ else if( target == EnvironmentVariableTarget.User) {
+ using (RegistryKey environmentKey =
+ Registry.CurrentUser.OpenSubKey("Environment", false)) {
+ return GetRegistryKeyNameValuePairs(environmentKey);
+ }
+ }
+ else
+#endif // FEATURE_WIN32_REGISTRY
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetEnvironmentVariable(string variable, string value) {
+ CheckEnvironmentVariableName(variable);
+
+#if !FEATURE_CORECLR
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+#endif
+ // explicitly null out value if is the empty string.
+ if (String.IsNullOrEmpty(value) || value[0] == '\0') {
+ value = null;
+ }
+ else {
+ if( value.Length >= MaxEnvVariableValueLength) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
+ }
+ }
+
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXDesignMode()) {
+ // Environment variable accessors are not approved modern API.
+ // so we throw PlatformNotSupportedException.
+ throw new PlatformNotSupportedException();
+ }
+
+ if(!Win32Native.SetEnvironmentVariable(variable, value)) {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ // Allow user to try to clear a environment variable
+ if( errorCode == Win32Native.ERROR_ENVVAR_NOT_FOUND) {
+ return;
+ }
+
+ // The error message from Win32 is "The filename or extension is too long",
+ // which is not accurate.
+ if( errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
+ }
+
+ throw new ArgumentException(Win32Native.GetMessage(errorCode));
+ }
+ }
+
+ private static void CheckEnvironmentVariableName(string variable) {
+ if (variable == null) {
+ throw new ArgumentNullException("variable");
+ }
+
+ if( variable.Length == 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "variable");
+ }
+
+ if( variable[0] == '\0') {
+ throw new ArgumentException(Environment.GetResourceString("Argument_StringFirstCharIsZero"), "variable");
+ }
+
+ // Make sure the environment variable name isn't longer than the
+ // max limit on environment variable values. (MSDN is ambiguous
+ // on whether this check is necessary.)
+ if( variable.Length >= MaxEnvVariableValueLength ) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
+ }
+
+ if( variable.IndexOf('=') != -1) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalEnvVarName"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetEnvironmentVariable(string variable, string value, EnvironmentVariableTarget target) {
+ if( target == EnvironmentVariableTarget.Process) {
+ SetEnvironmentVariable(variable, value);
+ return;
+ }
+
+ CheckEnvironmentVariableName(variable);
+
+ // System-wide environment variables stored in the registry are
+ // limited to 1024 chars for the environment variable name.
+ if (variable.Length >= MaxSystemEnvVariableLength) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarName"));
+ }
+
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+ // explicitly null out value if is the empty string.
+ if (String.IsNullOrEmpty(value) || value[0] == '\0') {
+ value = null;
+ }
+#if FEATURE_WIN32_REGISTRY
+ if( target == EnvironmentVariableTarget.Machine) {
+ using (RegistryKey environmentKey =
+ Registry.LocalMachine.OpenSubKey(@"System\CurrentControlSet\Control\Session Manager\Environment", true)) {
+
+ Contract.Assert(environmentKey != null, @"HKLM\System\CurrentControlSet\Control\Session Manager\Environment is missing!");
+ if (environmentKey != null) {
+ if (value == null)
+ environmentKey.DeleteValue(variable, false);
+ else
+ environmentKey.SetValue(variable, value);
+ }
+ }
+ }
+ else if( target == EnvironmentVariableTarget.User) {
+ // User-wide environment variables stored in the registry are
+ // limited to 255 chars for the environment variable name.
+ if (variable.Length >= MaxUserEnvVariableLength) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LongEnvVarValue"));
+ }
+ using (RegistryKey environmentKey =
+ Registry.CurrentUser.OpenSubKey("Environment", true)) {
+ Contract.Assert(environmentKey != null, @"HKCU\Environment is missing!");
+ if (environmentKey != null) {
+ if (value == null)
+ environmentKey.DeleteValue(variable, false);
+ else
+ environmentKey.SetValue(variable, value);
+ }
+ }
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
+ }
+ // send a WM_SETTINGCHANGE message to all windows
+ IntPtr r = Win32Native.SendMessageTimeout(new IntPtr(Win32Native.HWND_BROADCAST), Win32Native.WM_SETTINGCHANGE, IntPtr.Zero, "Environment", 0, 1000, IntPtr.Zero);
+
+ if (r == IntPtr.Zero) BCLDebug.Assert(false, "SetEnvironmentVariable failed: " + Marshal.GetLastWin32Error());
+
+#else // FEATURE_WIN32_REGISTRY
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)target));
+#endif
+ }
+
+
+ /*===============================GetLogicalDrives===============================
+ **Action: Retrieves the names of the logical drives on this machine in the form "C:\".
+ **Arguments: None.
+ **Exceptions: IOException.
+ **Permissions: SystemInfo Permission.
+ ==============================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String[] GetLogicalDrives() {
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+
+ int drives = Win32Native.GetLogicalDrives();
+ if (drives==0)
+ __Error.WinIOError();
+ uint d = (uint)drives;
+ int count = 0;
+ while (d != 0) {
+ if (((int)d & 1) != 0) count++;
+ d >>= 1;
+ }
+ String[] result = new String[count];
+ char[] root = new char[] {'A', ':', '\\'};
+ d = (uint)drives;
+ count = 0;
+ while (d != 0) {
+ if (((int)d & 1) != 0) {
+ result[count++] = new String(root);
+ }
+ d >>= 1;
+ root[0]++;
+ }
+ return result;
+ }
+
+ /*===================================NewLine====================================
+ **Action: A property which returns the appropriate newline string for the given
+ ** platform.
+ **Returns: \r\n on Win32.
+ **Arguments: None.
+ **Exceptions: None.
+ ==============================================================================*/
+ public static String NewLine {
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+#if !PLATFORM_UNIX
+ return "\r\n";
+#else
+ return "\n";
+#endif // !PLATFORM_UNIX
+ }
+ }
+
+
+ /*===================================Version====================================
+ **Action: Returns the COM+ version struct, describing the build number.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ public static Version Version {
+ get {
+
+ // Previously this represented the File version of mscorlib.dll. Many other libraries in the framework and outside took dependencies on the first three parts of this version
+ // remaining constant throughout 4.x. From 4.0 to 4.5.2 this was fine since the file version only incremented the last part.Starting with 4.6 we switched to a file versioning
+ // scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded.
+
+ return new Version(4,0,30319,42000);
+ }
+ }
+
+
+ /*==================================WorkingSet==================================
+ **Action:
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern long GetWorkingSet();
+
+ public static long WorkingSet {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+ return GetWorkingSet();
+ }
+ }
+
+
+ /*==================================OSVersion===================================
+ **Action:
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ public static OperatingSystem OSVersion {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<OperatingSystem>() != null);
+
+ if (m_os==null) { // We avoid the lock since we don't care if two threads will set this at the same time.
+
+ Microsoft.Win32.Win32Native.OSVERSIONINFO osvi = new Microsoft.Win32.Win32Native.OSVERSIONINFO();
+ if (!GetVersion(osvi)) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
+ }
+
+ Microsoft.Win32.Win32Native.OSVERSIONINFOEX osviEx = new Microsoft.Win32.Win32Native.OSVERSIONINFOEX();
+ if (!GetVersionEx(osviEx))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GetVersion"));
+
+#if PLATFORM_UNIX
+ PlatformID id = PlatformID.Unix;
+#else
+ PlatformID id = PlatformID.Win32NT;
+#endif // PLATFORM_UNIX
+
+ Version v = new Version(osvi.MajorVersion, osvi.MinorVersion, osvi.BuildNumber, (osviEx.ServicePackMajor << 16) |osviEx.ServicePackMinor);
+ m_os = new OperatingSystem(id, v, osvi.CSDVersion);
+ }
+ Contract.Assert(m_os != null, "m_os != null");
+ return m_os;
+ }
+ }
+
+#if FEATURE_CORESYSTEM
+
+ internal static bool IsWindows8OrAbove {
+ get {
+ return true;
+ }
+ }
+
+#if FEATURE_COMINTEROP
+ internal static bool IsWinRTSupported {
+ get {
+ return true;
+ }
+ }
+#endif // FEATURE_COMINTEROP
+
+#else // FEATURE_CORESYSTEM
+
+ private static volatile bool s_IsWindows8OrAbove;
+ private static volatile bool s_CheckedOSWin8OrAbove;
+
+ // Windows 8 version is 6.2
+ internal static bool IsWindows8OrAbove {
+ get {
+ if (!s_CheckedOSWin8OrAbove) {
+ OperatingSystem OS = Environment.OSVersion;
+ s_IsWindows8OrAbove = (OS.Platform == PlatformID.Win32NT &&
+ ((OS.Version.Major == 6 && OS.Version.Minor >= 2) || (OS.Version.Major > 6)));
+ s_CheckedOSWin8OrAbove = true;
+ }
+ return s_IsWindows8OrAbove;
+ }
+ }
+
+#if FEATURE_COMINTEROP
+ private static volatile bool s_WinRTSupported;
+ private static volatile bool s_CheckedWinRT;
+
+ // Does the current version of Windows have Windows Runtime suppport?
+ internal static bool IsWinRTSupported {
+ [SecuritySafeCritical]
+ get {
+ if (!s_CheckedWinRT) {
+ s_WinRTSupported = WinRTSupported();
+ s_CheckedWinRT = true;
+ }
+
+ return s_WinRTSupported;
+ }
+ }
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool WinRTSupported();
+#endif // FEATURE_COMINTEROP
+
+#endif // FEATURE_CORESYSTEM
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool GetVersion(Microsoft.Win32.Win32Native.OSVERSIONINFO osVer);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool GetVersionEx(Microsoft.Win32.Win32Native.OSVERSIONINFOEX osVer);
+
+
+ /*==================================StackTrace==================================
+ **Action:
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ public static String StackTrace {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+ return GetStackTrace(null, true);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ internal static String GetStackTrace(Exception e, bool needFileInfo)
+ {
+ // Note: Setting needFileInfo to true will start up COM and set our
+ // apartment state. Try to not call this when passing "true"
+ // before the EE's ExecuteMainMethod has had a chance to set up the
+ // apartment state. --
+ StackTrace st;
+ if (e == null)
+ st = new StackTrace(needFileInfo);
+ else
+ st = new StackTrace(e, needFileInfo);
+
+ // Do no include a trailing newline for backwards compatibility
+ return st.ToString( System.Diagnostics.StackTrace.TraceFormat.Normal );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static void InitResourceHelper() {
+ // Only the default AppDomain should have a ResourceHelper. All calls to
+ // GetResourceString from any AppDomain delegate to GetResourceStringLocal
+ // in the default AppDomain via the fcall GetResourceFromDefault.
+
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+
+ Monitor.Enter(Environment.InternalSyncObject, ref tookLock);
+
+ if (m_resHelper == null) {
+ ResourceHelper rh = new ResourceHelper(System.CoreLib.Name);
+
+ System.Threading.Thread.MemoryBarrier();
+ m_resHelper =rh;
+ }
+ }
+ finally {
+ if (tookLock)
+ Monitor.Exit(Environment.InternalSyncObject);
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static String GetResourceFromDefault(String key);
+#endif
+
+ // Looks up the resource string value for key.
+ //
+ // if you change this method's signature then you must change the code that calls it
+ // in excep.cpp and probably you will have to visit mscorlib.h to add the new signature
+ // as well as metasig.h to create the new signature type
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ internal static String GetResourceStringLocal(String key) {
+ if (m_resHelper == null)
+ InitResourceHelper();
+
+ return m_resHelper.GetResourceString(key);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static String GetResourceString(String key) {
+#if FEATURE_CORECLR
+ return GetResourceStringLocal(key);
+#else
+ return GetResourceFromDefault(key);
+#endif //FEATURE_CORECLR
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static String GetResourceString(String key, params Object[] values) {
+ String s = GetResourceString(key);
+ return String.Format(CultureInfo.CurrentCulture, s, values);
+ }
+
+ //The following two internal methods are not used anywhere within the framework,
+ // but are being kept around as external platforms built on top of us have taken
+ // dependency by using private reflection on them for getting system resource strings
+ internal static String GetRuntimeResourceString(String key) {
+ return GetResourceString(key);
+ }
+
+ internal static String GetRuntimeResourceString(String key, params Object[] values) {
+ return GetResourceString(key,values);
+ }
+
+ public static bool Is64BitProcess {
+ get {
+#if BIT64
+ return true;
+#else // 32
+ return false;
+#endif
+ }
+ }
+
+ public static bool Is64BitOperatingSystem {
+ [System.Security.SecuritySafeCritical]
+ get {
+#if BIT64
+ // 64-bit programs run only on 64-bit
+ return true;
+#else // 32
+ bool isWow64; // WinXP SP2+ and Win2k3 SP1+
+ return Win32Native.DoesWin32MethodExist(Win32Native.KERNEL32, "IsWow64Process")
+ && Win32Native.IsWow64Process(Win32Native.GetCurrentProcess(), out isWow64)
+ && isWow64;
+#endif
+ }
+ }
+
+ public static extern bool HasShutdownStarted {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+#if !FEATURE_CORECLR
+ // This is the temporary Whidbey stub for compatibility flags
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecurityCritical]
+ internal static extern bool GetCompatibilityFlag(CompatibilityFlag flag);
+#endif //!FEATURE_CORECLR
+
+ public static string UserName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserName").Demand();
+
+ StringBuilder sb = new StringBuilder(256);
+ int size = sb.Capacity;
+ if (Win32Native.GetUserName(sb, ref size))
+ {
+ return sb.ToString();
+ }
+ return String.Empty;
+ }
+ }
+
+ // Note that this is a handle to a process window station, but it does
+ // not need to be closed. CloseWindowStation would ignore this handle.
+ // We also do handle equality checking as well. This isn't a great fit
+ // for SafeHandle. We don't gain anything by using SafeHandle here.
+#if !FEATURE_CORECLR
+ private static volatile IntPtr processWinStation; // Doesn't need to be initialized as they're zero-init.
+ private static volatile bool isUserNonInteractive;
+#endif
+
+ public static bool UserInteractive {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+#if !FEATURE_CORECLR
+ IntPtr hwinsta = Win32Native.GetProcessWindowStation();
+ if (hwinsta != IntPtr.Zero && processWinStation != hwinsta) {
+ int lengthNeeded = 0;
+ Win32Native.USEROBJECTFLAGS flags = new Win32Native.USEROBJECTFLAGS();
+ if (Win32Native.GetUserObjectInformation(hwinsta, Win32Native.UOI_FLAGS, flags, Marshal.SizeOf(flags),ref lengthNeeded)) {
+ if ((flags.dwFlags & Win32Native.WSF_VISIBLE) == 0) {
+ isUserNonInteractive = true;
+ }
+ }
+ processWinStation = hwinsta;
+ }
+
+ // The logic is reversed to avoid static initialization to true
+ return !isUserNonInteractive;
+#else
+ return true;
+#endif
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static string GetFolderPath(SpecialFolder folder) {
+ if (!Enum.IsDefined(typeof(SpecialFolder), folder))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder));
+ Contract.EndContractBlock();
+
+ return InternalGetFolderPath(folder, SpecialFolderOption.None);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static string GetFolderPath(SpecialFolder folder, SpecialFolderOption option) {
+ if (!Enum.IsDefined(typeof(SpecialFolder),folder))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)folder));
+ if (!Enum.IsDefined(typeof(SpecialFolderOption),option))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)option));
+ Contract.EndContractBlock();
+
+ return InternalGetFolderPath(folder, option);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static string UnsafeGetFolderPath(SpecialFolder folder)
+ {
+ return InternalGetFolderPath(folder, SpecialFolderOption.None, suppressSecurityChecks: true);
+ }
+
+ [System.Security.SecurityCritical]
+ private static string InternalGetFolderPath(SpecialFolder folder, SpecialFolderOption option, bool suppressSecurityChecks = false)
+ {
+#if FEATURE_CORESYSTEM
+ // This is currently customized for Windows Phone since CoreSystem doesn't support
+ // SHGetFolderPath. The allowed folder values are based on the version of .NET CF WP7 was using.
+ switch (folder)
+ {
+ case SpecialFolder.System:
+ return SystemDirectory;
+ case SpecialFolder.ApplicationData:
+ case SpecialFolder.Favorites:
+ case SpecialFolder.Programs:
+ case SpecialFolder.StartMenu:
+ case SpecialFolder.Startup:
+ case SpecialFolder.Personal:
+ throw new PlatformNotSupportedException();
+ default:
+ throw new PlatformNotSupportedException();
+ }
+#else // FEATURE_CORESYSTEM
+#if !FEATURE_CORECLR
+ if (option == SpecialFolderOption.Create && !suppressSecurityChecks) {
+ FileIOPermission createPermission = new FileIOPermission(PermissionState.None);
+ createPermission.AllFiles = FileIOPermissionAccess.Write;
+ createPermission.Demand();
+ }
+#endif
+
+ StringBuilder sb = new StringBuilder(Path.MaxPath);
+ int hresult = Win32Native.SHGetFolderPath(IntPtr.Zero, /* hwndOwner: [in] Reserved */
+ ((int)folder | (int)option), /* nFolder: [in] CSIDL */
+ IntPtr.Zero, /* hToken: [in] access token */
+ Win32Native.SHGFP_TYPE_CURRENT, /* dwFlags: [in] retrieve current path */
+ sb); /* pszPath: [out]resultant path */
+ String s;
+ if (hresult < 0)
+ {
+ switch (hresult)
+ {
+ default:
+ // The previous incarnation threw away all errors. In order to limit
+ // breaking changes, we will be permissive about these errors
+ // instead of calling ThowExceptionForHR.
+ //Runtime.InteropServices.Marshal.ThrowExceptionForHR(hresult);
+ break;
+ case __HResults.COR_E_PLATFORMNOTSUPPORTED:
+ // This one error is the one we do want to throw.
+
+ throw new PlatformNotSupportedException();
+ }
+
+ // SHGetFolderPath does not initialize the output buffer on error
+ s = String.Empty;
+ }
+ else
+ {
+ s = sb.ToString();
+ }
+
+ if (!suppressSecurityChecks)
+ {
+ // On CoreCLR we can check with the host if we're not trying to use any special options.
+ // Otherwise, we need to do a full demand since hosts aren't expecting to handle requests to
+ // create special folders.
+#if FEATURE_CORECLR
+ if (option == SpecialFolderOption.None)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, s);
+ state.EnsureState();
+ }
+ else
+#endif // FEATURE_CORECLR
+ {
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, s).Demand();
+ }
+ }
+ return s;
+#endif // FEATURE_CORESYSTEM
+ }
+
+ public static string UserDomainName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ new EnvironmentPermission(EnvironmentPermissionAccess.Read,"UserDomain").Demand();
+
+ byte[] sid = new byte[1024];
+ int sidLen = sid.Length;
+ StringBuilder domainName = new StringBuilder(1024);
+ uint domainNameLen = (uint) domainName.Capacity;
+ int peUse;
+
+ byte ret = Win32Native.GetUserNameEx(Win32Native.NameSamCompatible, domainName, ref domainNameLen);
+ if (ret == 1) {
+ string samName = domainName.ToString();
+ int index = samName.IndexOf('\\');
+ if( index != -1) {
+ return samName.Substring(0, index);
+ }
+ }
+ domainNameLen = (uint) domainName.Capacity;
+
+ bool success = Win32Native.LookupAccountName(null, UserName, sid, ref sidLen, domainName, ref domainNameLen, out peUse);
+ if (!success) {
+ int errorCode = Marshal.GetLastWin32Error();
+ throw new InvalidOperationException(Win32Native.GetMessage(errorCode));
+ }
+
+ return domainName.ToString();
+ }
+ }
+
+ public enum SpecialFolderOption {
+ None = 0,
+ Create = Win32Native.CSIDL_FLAG_CREATE,
+ DoNotVerify = Win32Native.CSIDL_FLAG_DONT_VERIFY,
+ }
+
+//////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!////////
+//////!!!!!! Keep the following locations synchronized !!!!!!////////
+//////!!!!!! 1) ndp\clr\src\BCL\Microsoft\Win32\Win32Native.cs !!!!!!////////
+//////!!!!!! 2) ndp\clr\src\BCL\System\Environment.cs !!!!!!////////
+//////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!////////
+ [ComVisible(true)]
+ public enum SpecialFolder {
+ //
+ // Represents the file system directory that serves as a common repository for
+ // application-specific data for the current, roaming user.
+ // A roaming user works on more than one computer on a network. A roaming user's
+ // profile is kept on a server on the network and is loaded onto a system when the
+ // user logs on.
+ //
+ ApplicationData = Win32Native.CSIDL_APPDATA,
+ //
+ // Represents the file system directory that serves as a common repository for application-specific data that
+ // is used by all users.
+ //
+ CommonApplicationData = Win32Native.CSIDL_COMMON_APPDATA,
+ //
+ // Represents the file system directory that serves as a common repository for application specific data that
+ // is used by the current, non-roaming user.
+ //
+ LocalApplicationData = Win32Native.CSIDL_LOCAL_APPDATA,
+ //
+ // Represents the file system directory that serves as a common repository for Internet
+ // cookies.
+ //
+ Cookies = Win32Native.CSIDL_COOKIES,
+ Desktop = Win32Native.CSIDL_DESKTOP,
+ //
+ // Represents the file system directory that serves as a common repository for the user's
+ // favorite items.
+ //
+ Favorites = Win32Native.CSIDL_FAVORITES,
+ //
+ // Represents the file system directory that serves as a common repository for Internet
+ // history items.
+ //
+ History = Win32Native.CSIDL_HISTORY,
+ //
+ // Represents the file system directory that serves as a common repository for temporary
+ // Internet files.
+ //
+ InternetCache = Win32Native.CSIDL_INTERNET_CACHE,
+ //
+ // Represents the file system directory that contains
+ // the user's program groups.
+ //
+ Programs = Win32Native.CSIDL_PROGRAMS,
+ MyComputer = Win32Native.CSIDL_DRIVES,
+ MyMusic = Win32Native.CSIDL_MYMUSIC,
+ MyPictures = Win32Native.CSIDL_MYPICTURES,
+ // "My Videos" folder
+ MyVideos = Win32Native.CSIDL_MYVIDEO,
+ //
+ // Represents the file system directory that contains the user's most recently used
+ // documents.
+ //
+ Recent = Win32Native.CSIDL_RECENT,
+ //
+ // Represents the file system directory that contains Send To menu items.
+ //
+ SendTo = Win32Native.CSIDL_SENDTO,
+ //
+ // Represents the file system directory that contains the Start menu items.
+ //
+ StartMenu = Win32Native.CSIDL_STARTMENU,
+ //
+ // Represents the file system directory that corresponds to the user's Startup program group. The system
+ // starts these programs whenever any user logs on to Windows NT, or
+ // starts Windows 95 or Windows 98.
+ //
+ Startup = Win32Native.CSIDL_STARTUP,
+ //
+ // System directory.
+ //
+ System = Win32Native.CSIDL_SYSTEM,
+ //
+ // Represents the file system directory that serves as a common repository for document
+ // templates.
+ //
+ Templates = Win32Native.CSIDL_TEMPLATES,
+ //
+ // Represents the file system directory used to physically store file objects on the desktop.
+ // This should not be confused with the desktop folder itself, which is
+ // a virtual folder.
+ //
+ DesktopDirectory = Win32Native.CSIDL_DESKTOPDIRECTORY,
+ //
+ // Represents the file system directory that serves as a common repository for documents.
+ //
+ Personal = Win32Native.CSIDL_PERSONAL,
+ //
+ // "MyDocuments" is a better name than "Personal"
+ //
+ MyDocuments = Win32Native.CSIDL_PERSONAL,
+ //
+ // Represents the program files folder.
+ //
+ ProgramFiles = Win32Native.CSIDL_PROGRAM_FILES,
+ //
+ // Represents the folder for components that are shared across applications.
+ //
+ CommonProgramFiles = Win32Native.CSIDL_PROGRAM_FILES_COMMON,
+#if !FEATURE_CORECLR
+ //
+ // <user name>\Start Menu\Programs\Administrative Tools
+ //
+ AdminTools = Win32Native.CSIDL_ADMINTOOLS,
+ //
+ // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
+ //
+ CDBurning = Win32Native.CSIDL_CDBURN_AREA,
+ //
+ // All Users\Start Menu\Programs\Administrative Tools
+ //
+ CommonAdminTools = Win32Native.CSIDL_COMMON_ADMINTOOLS,
+ //
+ // All Users\Documents
+ //
+ CommonDocuments = Win32Native.CSIDL_COMMON_DOCUMENTS,
+ //
+ // All Users\My Music
+ //
+ CommonMusic = Win32Native.CSIDL_COMMON_MUSIC,
+ //
+ // Links to All Users OEM specific apps
+ //
+ CommonOemLinks = Win32Native.CSIDL_COMMON_OEM_LINKS,
+ //
+ // All Users\My Pictures
+ //
+ CommonPictures = Win32Native.CSIDL_COMMON_PICTURES,
+ //
+ // All Users\Start Menu
+ //
+ CommonStartMenu = Win32Native.CSIDL_COMMON_STARTMENU,
+ //
+ // All Users\Start Menu\Programs
+ //
+ CommonPrograms = Win32Native.CSIDL_COMMON_PROGRAMS,
+ //
+ // All Users\Startup
+ //
+ CommonStartup = Win32Native.CSIDL_COMMON_STARTUP,
+ //
+ // All Users\Desktop
+ //
+ CommonDesktopDirectory = Win32Native.CSIDL_COMMON_DESKTOPDIRECTORY,
+ //
+ // All Users\Templates
+ //
+ CommonTemplates = Win32Native.CSIDL_COMMON_TEMPLATES,
+ //
+ // All Users\My Video
+ //
+ CommonVideos = Win32Native.CSIDL_COMMON_VIDEO,
+ //
+ // windows\fonts
+ //
+ Fonts = Win32Native.CSIDL_FONTS,
+ //
+ // %APPDATA%\Microsoft\Windows\Network Shortcuts
+ //
+ NetworkShortcuts = Win32Native.CSIDL_NETHOOD,
+ //
+ // %APPDATA%\Microsoft\Windows\Printer Shortcuts
+ //
+ PrinterShortcuts = Win32Native.CSIDL_PRINTHOOD,
+ //
+ // USERPROFILE
+ //
+ UserProfile = Win32Native.CSIDL_PROFILE,
+ //
+ // x86 Program Files\Common on RISC
+ //
+ CommonProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILES_COMMONX86,
+ //
+ // x86 C:\Program Files on RISC
+ //
+ ProgramFilesX86 = Win32Native.CSIDL_PROGRAM_FILESX86,
+ //
+ // Resource Directory
+ //
+ Resources = Win32Native.CSIDL_RESOURCES,
+ //
+ // Localized Resource Directory
+ //
+ LocalizedResources = Win32Native.CSIDL_RESOURCES_LOCALIZED,
+ //
+ // %windir%\System32 or %windir%\syswow64
+ //
+ SystemX86 = Win32Native.CSIDL_SYSTEMX86,
+ //
+ // GetWindowsDirectory()
+ //
+ Windows = Win32Native.CSIDL_WINDOWS,
+#endif // !FEATURE_CORECLR
+ }
+
+ public static int CurrentManagedThreadId
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return Thread.CurrentThread.ManagedThreadId;
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/EventArgs.cs b/src/mscorlib/src/System/EventArgs.cs
new file mode 100644
index 0000000000..349de857d8
--- /dev/null
+++ b/src/mscorlib/src/System/EventArgs.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ // The base class for all event classes.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class EventArgs {
+ public static readonly EventArgs Empty = new EventArgs();
+
+ public EventArgs()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/EventHandler.cs b/src/mscorlib/src/System/EventHandler.cs
new file mode 100644
index 0000000000..517e1f7c26
--- /dev/null
+++ b/src/mscorlib/src/System/EventHandler.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void EventHandler(Object sender, EventArgs e);
+
+ [Serializable]
+ public delegate void EventHandler<TEventArgs>(Object sender, TEventArgs e); // Removed TEventArgs constraint post-.NET 4
+}
diff --git a/src/mscorlib/src/System/Exception.cs b/src/mscorlib/src/System/Exception.cs
new file mode 100644
index 0000000000..12799e7875
--- /dev/null
+++ b/src/mscorlib/src/System/Exception.cs
@@ -0,0 +1,1006 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The base class for all exceptional conditions.
+**
+**
+=============================================================================*/
+
+namespace System {
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+ using System.Security;
+ using System.IO;
+ using System.Text;
+ using System.Reflection;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Exception))]
+ [Serializable]
+ [ComVisible(true)]
+ public class Exception : ISerializable, _Exception
+ {
+ private void Init()
+ {
+ _message = null;
+ _stackTrace = null;
+ _dynamicMethods = null;
+ HResult = __HResults.COR_E_EXCEPTION;
+ _xcode = _COMPlusExceptionCode;
+ _xptrs = (IntPtr) 0;
+
+ // Initialize the WatsonBuckets to be null
+ _watsonBuckets = null;
+
+ // Initialize the watson bucketing IP
+ _ipForWatsonBuckets = UIntPtr.Zero;
+
+#if FEATURE_SERIALIZATION
+ _safeSerializationManager = new SafeSerializationManager();
+#endif // FEATURE_SERIALIZATION
+ }
+
+ public Exception() {
+ Init();
+ }
+
+ public Exception(String message) {
+ Init();
+ _message = message;
+ }
+
+ // Creates a new Exception. All derived classes should
+ // provide this constructor.
+ // Note: the stack trace is not started until the exception
+ // is thrown
+ //
+ public Exception (String message, Exception innerException) {
+ Init();
+ _message = message;
+ _innerException = innerException;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected Exception(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ _className = info.GetString("ClassName");
+ _message = info.GetString("Message");
+ _data = (IDictionary)(info.GetValueNoThrow("Data",typeof(IDictionary)));
+ _innerException = (Exception)(info.GetValue("InnerException",typeof(Exception)));
+ _helpURL = info.GetString("HelpURL");
+ _stackTraceString = info.GetString("StackTraceString");
+ _remoteStackTraceString = info.GetString("RemoteStackTraceString");
+ _remoteStackIndex = info.GetInt32("RemoteStackIndex");
+
+ _exceptionMethodString = (String)(info.GetValue("ExceptionMethod",typeof(String)));
+ HResult = info.GetInt32("HResult");
+ _source = info.GetString("Source");
+
+ // Get the WatsonBuckets that were serialized - this is particularly
+ // done to support exceptions going across AD transitions.
+ //
+ // We use the no throw version since we could be deserializing a pre-V4
+ // exception object that may not have this entry. In such a case, we would
+ // get null.
+ _watsonBuckets = (Object)info.GetValueNoThrow("WatsonBuckets", typeof(byte[]));
+
+#if FEATURE_SERIALIZATION
+ _safeSerializationManager = info.GetValueNoThrow("SafeSerializationManager", typeof(SafeSerializationManager)) as SafeSerializationManager;
+#endif // FEATURE_SERIALIZATION
+
+ if (_className == null || HResult==0)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+
+ // If we are constructing a new exception after a cross-appdomain call...
+ if (context.State == StreamingContextStates.CrossAppDomain)
+ {
+ // ...this new exception may get thrown. It is logically a re-throw, but
+ // physically a brand-new exception. Since the stack trace is cleared
+ // on a new exception, the "_remoteStackTraceString" is provided to
+ // effectively import a stack trace from a "remote" exception. So,
+ // move the _stackTraceString into the _remoteStackTraceString. Note
+ // that if there is an existing _remoteStackTraceString, it will be
+ // preserved at the head of the new string, so everything works as
+ // expected.
+ // Even if this exception is NOT thrown, things will still work as expected
+ // because the StackTrace property returns the concatenation of the
+ // _remoteStackTraceString and the _stackTraceString.
+ _remoteStackTraceString = _remoteStackTraceString + _stackTraceString;
+ _stackTraceString = null;
+ }
+ }
+
+
+ public virtual String Message {
+ get {
+ if (_message == null) {
+ if (_className==null) {
+ _className = GetClassName();
+ }
+ return Environment.GetResourceString("Exception_WasThrown", _className);
+
+ } else {
+ return _message;
+ }
+ }
+ }
+
+ public virtual IDictionary Data {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_data == null)
+ if (IsImmutableAgileException(this))
+ _data = new EmptyReadOnlyDictionaryInternal();
+ else
+ _data = new ListDictionaryInternal();
+
+ return _data;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool IsImmutableAgileException(Exception e);
+
+#if FEATURE_COMINTEROP
+ //
+ // Exception requires anything to be added into Data dictionary is serializable
+ // This wrapper is made serializable to satisfy this requirement but does NOT serialize
+ // the object and simply ignores it during serialization, because we only need
+ // the exception instance in the app to hold the error object alive.
+ // Once the exception is serialized to debugger, debugger only needs the error reference string
+ //
+ [Serializable]
+ internal class __RestrictedErrorObject
+ {
+ // Hold the error object instance but don't serialize/deserialize it
+ [NonSerialized]
+ private object _realErrorObject;
+
+ internal __RestrictedErrorObject(object errorObject)
+ {
+ _realErrorObject = errorObject;
+ }
+
+ public object RealErrorObject
+ {
+ get
+ {
+ return _realErrorObject;
+ }
+ }
+ }
+
+ [FriendAccessAllowed]
+ internal void AddExceptionDataForRestrictedErrorInfo(
+ string restrictedError,
+ string restrictedErrorReference,
+ string restrictedCapabilitySid,
+ object restrictedErrorObject,
+ bool hasrestrictedLanguageErrorObject = false)
+ {
+ IDictionary dict = Data;
+ if (dict != null)
+ {
+ dict.Add("RestrictedDescription", restrictedError);
+ dict.Add("RestrictedErrorReference", restrictedErrorReference);
+ dict.Add("RestrictedCapabilitySid", restrictedCapabilitySid);
+
+ // Keep the error object alive so that user could retrieve error information
+ // using Data["RestrictedErrorReference"]
+ dict.Add("__RestrictedErrorObject", (restrictedErrorObject == null ? null : new __RestrictedErrorObject(restrictedErrorObject)));
+ dict.Add("__HasRestrictedLanguageErrorObject", hasrestrictedLanguageErrorObject);
+ }
+ }
+
+ internal bool TryGetRestrictedLanguageErrorObject(out object restrictedErrorObject)
+ {
+ restrictedErrorObject = null;
+ if (Data != null && Data.Contains("__HasRestrictedLanguageErrorObject"))
+ {
+ if (Data.Contains("__RestrictedErrorObject"))
+ {
+ __RestrictedErrorObject restrictedObject = Data["__RestrictedErrorObject"] as __RestrictedErrorObject;
+ if (restrictedObject != null)
+ restrictedErrorObject = restrictedObject.RealErrorObject;
+ }
+ return (bool)Data["__HasRestrictedLanguageErrorObject"];
+ }
+
+ return false;
+ }
+#endif // FEATURE_COMINTEROP
+
+ private string GetClassName()
+ {
+ // Will include namespace but not full instantiation and assembly name.
+ if (_className == null)
+ _className = GetType().ToString();
+
+ return _className;
+ }
+
+ // Retrieves the lowest exception (inner most) for the given Exception.
+ // This will traverse exceptions using the innerException property.
+ //
+ public virtual Exception GetBaseException()
+ {
+ Exception inner = InnerException;
+ Exception back = this;
+
+ while (inner != null) {
+ back = inner;
+ inner = inner.InnerException;
+ }
+
+ return back;
+ }
+
+ // Returns the inner exception contained in this exception
+ //
+ public Exception InnerException {
+ get { return _innerException; }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern private IRuntimeMethodInfo GetMethodFromStackTrace(Object stackTrace);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private MethodBase GetExceptionMethodFromStackTrace()
+ {
+ IRuntimeMethodInfo method = GetMethodFromStackTrace(_stackTrace);
+
+ // Under certain race conditions when exceptions are re-used, this can be null
+ if (method == null)
+ return null;
+
+ return RuntimeType.GetMethodBase(method);
+ }
+
+ public MethodBase TargetSite {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return GetTargetSiteInternal();
+ }
+ }
+
+
+ // this function is provided as a private helper to avoid the security demand
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodBase GetTargetSiteInternal() {
+ if (_exceptionMethod!=null) {
+ return _exceptionMethod;
+ }
+ if (_stackTrace==null) {
+ return null;
+ }
+
+ if (_exceptionMethodString!=null) {
+ _exceptionMethod = GetExceptionMethodFromString();
+ } else {
+ _exceptionMethod = GetExceptionMethodFromStackTrace();
+ }
+ return _exceptionMethod;
+ }
+
+ // Returns the stack trace as a string. If no stack trace is
+ // available, null is returned.
+ public virtual String StackTrace
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ get
+ {
+ // By default attempt to include file and line number info
+ return GetStackTrace(true);
+ }
+ }
+
+ // Computes and returns the stack trace as a string
+ // Attempts to get source file and line number information if needFileInfo
+ // is true. Note that this requires FileIOPermission(PathDiscovery), and so
+ // will usually fail in CoreCLR. To avoid the demand and resulting
+ // SecurityException we can explicitly not even try to get fileinfo.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private string GetStackTrace(bool needFileInfo)
+ {
+ string stackTraceString = _stackTraceString;
+ string remoteStackTraceString = _remoteStackTraceString;
+
+#if !FEATURE_CORECLR
+ if (!needFileInfo)
+ {
+ // Filter out file names/paths and line numbers from _stackTraceString and _remoteStackTraceString.
+ // This is used only when generating stack trace for Watson where the strings must be PII-free.
+ stackTraceString = StripFileInfo(stackTraceString, false);
+ remoteStackTraceString = StripFileInfo(remoteStackTraceString, true);
+ }
+#endif // !FEATURE_CORECLR
+
+ // if no stack trace, try to get one
+ if (stackTraceString != null)
+ {
+ return remoteStackTraceString + stackTraceString;
+ }
+ if (_stackTrace == null)
+ {
+ return remoteStackTraceString;
+ }
+
+ // Obtain the stack trace string. Note that since Environment.GetStackTrace
+ // will add the path to the source file if the PDB is present and a demand
+ // for FileIOPermission(PathDiscovery) succeeds, we need to make sure we
+ // don't store the stack trace string in the _stackTraceString member variable.
+ String tempStackTraceString = Environment.GetStackTrace(this, needFileInfo);
+ return remoteStackTraceString + tempStackTraceString;
+ }
+
+ [FriendAccessAllowed]
+ internal void SetErrorCode(int hr)
+ {
+ HResult = hr;
+ }
+
+ // Sets the help link for this exception.
+ // This should be in a URL/URN form, such as:
+ // "file:///C:/Applications/Bazzal/help.html#ErrorNum42"
+ // Changed to be a read-write String and not return an exception
+ public virtual String HelpLink
+ {
+ get
+ {
+ return _helpURL;
+ }
+ set
+ {
+ _helpURL = value;
+ }
+ }
+
+ public virtual String Source {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ get {
+ if (_source == null)
+ {
+ StackTrace st = new StackTrace(this,true);
+ if (st.FrameCount>0)
+ {
+ StackFrame sf = st.GetFrame(0);
+ MethodBase method = sf.GetMethod();
+
+ Module module = method.Module;
+
+ RuntimeModule rtModule = module as RuntimeModule;
+
+ if (rtModule == null)
+ {
+ System.Reflection.Emit.ModuleBuilder moduleBuilder = module as System.Reflection.Emit.ModuleBuilder;
+ if (moduleBuilder != null)
+ rtModule = moduleBuilder.InternalModule;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeReflectionObject"));
+ }
+
+ _source = rtModule.GetRuntimeAssembly().GetSimpleName();
+ }
+ }
+
+ return _source;
+ }
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ set { _source = value; }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override String ToString()
+ {
+ return ToString(true, true);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private String ToString(bool needFileLineInfo, bool needMessage) {
+ String message = (needMessage ? Message : null);
+ String s;
+
+ if (message == null || message.Length <= 0) {
+ s = GetClassName();
+ }
+ else {
+ s = GetClassName() + ": " + message;
+ }
+
+ if (_innerException!=null) {
+ s = s + " ---> " + _innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine +
+ " " + Environment.GetResourceString("Exception_EndOfInnerExceptionStack");
+
+ }
+
+ string stackTrace = GetStackTrace(needFileLineInfo);
+ if (stackTrace != null)
+ {
+ s += Environment.NewLine + stackTrace;
+ }
+
+ return s;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private String GetExceptionMethodString() {
+ MethodBase methBase = GetTargetSiteInternal();
+ if (methBase==null) {
+ return null;
+ }
+ if (methBase is System.Reflection.Emit.DynamicMethod.RTDynamicMethod)
+ {
+ // DynamicMethods cannot be serialized
+ return null;
+ }
+
+ // Note that the newline separator is only a separator, chosen such that
+ // it won't (generally) occur in a method name. This string is used
+ // only for serialization of the Exception Method.
+ char separator = '\n';
+ StringBuilder result = new StringBuilder();
+ if (methBase is ConstructorInfo) {
+ RuntimeConstructorInfo rci = (RuntimeConstructorInfo)methBase;
+ Type t = rci.ReflectedType;
+ result.Append((int)MemberTypes.Constructor);
+ result.Append(separator);
+ result.Append(rci.Name);
+ if (t!=null)
+ {
+ result.Append(separator);
+ result.Append(t.Assembly.FullName);
+ result.Append(separator);
+ result.Append(t.FullName);
+ }
+ result.Append(separator);
+ result.Append(rci.ToString());
+ } else {
+ Contract.Assert(methBase is MethodInfo, "[Exception.GetExceptionMethodString]methBase is MethodInfo");
+ RuntimeMethodInfo rmi = (RuntimeMethodInfo)methBase;
+ Type t = rmi.DeclaringType;
+ result.Append((int)MemberTypes.Method);
+ result.Append(separator);
+ result.Append(rmi.Name);
+ result.Append(separator);
+ result.Append(rmi.Module.Assembly.FullName);
+ result.Append(separator);
+ if (t != null)
+ {
+ result.Append(t.FullName);
+ result.Append(separator);
+ }
+ result.Append(rmi.ToString());
+ }
+
+ return result.ToString();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodBase GetExceptionMethodFromString() {
+ Contract.Assert(_exceptionMethodString != null, "Method string cannot be NULL!");
+ String[] args = _exceptionMethodString.Split(new char[]{'\0', '\n'});
+ if (args.Length!=5) {
+ throw new SerializationException();
+ }
+ SerializationInfo si = new SerializationInfo(typeof(MemberInfoSerializationHolder), new FormatterConverter());
+ si.AddValue("MemberType", (int)Int32.Parse(args[0], CultureInfo.InvariantCulture), typeof(Int32));
+ si.AddValue("Name", args[1], typeof(String));
+ si.AddValue("AssemblyName", args[2], typeof(String));
+ si.AddValue("ClassName", args[3]);
+ si.AddValue("Signature", args[4]);
+ MethodBase result;
+ StreamingContext sc = new StreamingContext(StreamingContextStates.All);
+ try {
+ result = (MethodBase)new MemberInfoSerializationHolder(si, sc).GetRealObject(sc);
+ } catch (SerializationException) {
+ result = null;
+ }
+ return result;
+ }
+
+#if FEATURE_SERIALIZATION
+ protected event EventHandler<SafeSerializationEventArgs> SerializeObjectState
+ {
+ add { _safeSerializationManager.SerializeObjectState += value; }
+ remove { _safeSerializationManager.SerializeObjectState -= value; }
+ }
+#endif // FEATURE_SERIALIZATION
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ String tempStackTraceString = _stackTraceString;
+
+ if (_stackTrace!=null)
+ {
+ if (tempStackTraceString==null)
+ {
+ tempStackTraceString = Environment.GetStackTrace(this, true);
+ }
+ if (_exceptionMethod==null)
+ {
+ _exceptionMethod = GetExceptionMethodFromStackTrace();
+ }
+ }
+
+ if (_source == null)
+ {
+ _source = Source; // Set the Source information correctly before serialization
+ }
+
+ info.AddValue("ClassName", GetClassName(), typeof(String));
+ info.AddValue("Message", _message, typeof(String));
+ info.AddValue("Data", _data, typeof(IDictionary));
+ info.AddValue("InnerException", _innerException, typeof(Exception));
+ info.AddValue("HelpURL", _helpURL, typeof(String));
+ info.AddValue("StackTraceString", tempStackTraceString, typeof(String));
+ info.AddValue("RemoteStackTraceString", _remoteStackTraceString, typeof(String));
+ info.AddValue("RemoteStackIndex", _remoteStackIndex, typeof(Int32));
+ info.AddValue("ExceptionMethod", GetExceptionMethodString(), typeof(String));
+ info.AddValue("HResult", HResult);
+ info.AddValue("Source", _source, typeof(String));
+
+ // Serialize the Watson bucket details as well
+ info.AddValue("WatsonBuckets", _watsonBuckets, typeof(byte[]));
+
+#if FEATURE_SERIALIZATION
+ if (_safeSerializationManager != null && _safeSerializationManager.IsActive)
+ {
+ info.AddValue("SafeSerializationManager", _safeSerializationManager, typeof(SafeSerializationManager));
+
+ // User classes derived from Exception must have a valid _safeSerializationManager.
+ // Exceptions defined in mscorlib don't use this field might not have it initalized (since they are
+ // often created in the VM with AllocateObject instead if the managed construtor)
+ // If you are adding code to use a SafeSerializationManager from an mscorlib exception, update
+ // this assert to ensure that it fails when that exception's _safeSerializationManager is NULL
+ Contract.Assert(((_safeSerializationManager != null) || (this.GetType().Assembly == typeof(object).Assembly)),
+ "User defined exceptions must have a valid _safeSerializationManager");
+
+ // Handle serializing any transparent or partial trust subclass data
+ _safeSerializationManager.CompleteSerialization(this, info, context);
+ }
+#endif // FEATURE_SERIALIZATION
+ }
+
+ // This is used by remoting to preserve the server side stack trace
+ // by appending it to the message ... before the exception is rethrown
+ // at the client call site.
+ internal Exception PrepForRemoting()
+ {
+ String tmp = null;
+
+ if (_remoteStackIndex == 0)
+ {
+ tmp = Environment.NewLine+ "Server stack trace: " + Environment.NewLine
+ + StackTrace
+ + Environment.NewLine + Environment.NewLine
+ + "Exception rethrown at ["+_remoteStackIndex+"]: " + Environment.NewLine;
+ }
+ else
+ {
+ tmp = StackTrace
+ + Environment.NewLine + Environment.NewLine
+ + "Exception rethrown at ["+_remoteStackIndex+"]: " + Environment.NewLine;
+ }
+
+ _remoteStackTraceString = tmp;
+ _remoteStackIndex++;
+
+ return this;
+ }
+
+ // This method will clear the _stackTrace of the exception object upon deserialization
+ // to ensure that references from another AD/Process dont get accidently used.
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ _stackTrace = null;
+
+ // We wont serialize or deserialize the IP for Watson bucketing since
+ // we dont know where the deserialized object will be used in.
+ // Using it across process or an AppDomain could be invalid and result
+ // in AV in the runtime.
+ //
+ // Hence, we set it to zero when deserialization takes place.
+ _ipForWatsonBuckets = UIntPtr.Zero;
+
+#if FEATURE_SERIALIZATION
+ if (_safeSerializationManager == null)
+ {
+ _safeSerializationManager = new SafeSerializationManager();
+ }
+ else
+ {
+ _safeSerializationManager.CompleteDeserialization(this);
+ }
+#endif // FEATURE_SERIALIZATION
+ }
+
+ // This is used by the runtime when re-throwing a managed exception. It will
+ // copy the stack trace to _remoteStackTraceString.
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ internal void InternalPreserveStackTrace()
+ {
+ string tmpStackTraceString;
+
+#if FEATURE_APPX
+ if (AppDomain.IsAppXModel())
+ {
+ // Call our internal GetStackTrace in AppX so we can parse the result should
+ // we need to strip file/line info from it to make it PII-free. Calling the
+ // public and overridable StackTrace getter here was probably not intended.
+ tmpStackTraceString = GetStackTrace(true);
+
+ // Make sure that the _source field is initialized if Source is not overriden.
+ // We want it to contain the original faulting point.
+ string source = Source;
+ }
+ else
+#else // FEATURE_APPX
+#if FEATURE_CORESYSTEM
+ // Preinitialize _source on CoreSystem as well. The legacy behavior is not ideal and
+ // we keep it for back compat but we can afford to make the change on the Phone.
+ string source = Source;
+#endif // FEATURE_CORESYSTEM
+#endif // FEATURE_APPX
+ {
+ // Call the StackTrace getter in classic for compat.
+ tmpStackTraceString = StackTrace;
+ }
+
+ if (tmpStackTraceString != null && tmpStackTraceString.Length > 0)
+ {
+ _remoteStackTraceString = tmpStackTraceString + Environment.NewLine;
+ }
+
+ _stackTrace = null;
+ _stackTraceString = null;
+ }
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+
+ // This is the object against which a lock will be taken
+ // when attempt to restore the EDI. Since its static, its possible
+ // that unrelated exception object restorations could get blocked
+ // for a small duration but that sounds reasonable considering
+ // such scenarios are going to be extremely rare, where timing
+ // matches precisely.
+ [OptionalField]
+ private static object s_EDILock = new object();
+
+ internal UIntPtr IPForWatsonBuckets
+ {
+ get {
+ return _ipForWatsonBuckets;
+ }
+ }
+
+ internal object WatsonBuckets
+ {
+ get
+ {
+ return _watsonBuckets;
+ }
+ }
+
+ internal string RemoteStackTrace
+ {
+ get
+ {
+ return _remoteStackTraceString;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void PrepareForForeignExceptionRaise();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetStackTracesDeepCopy(Exception exception, out object currentStackTrace, out object dynamicMethodArray);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void SaveStackTracesFromDeepCopy(Exception exception, object currentStackTrace, object dynamicMethodArray);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern object CopyStackTrace(object currentStackTrace);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern object CopyDynamicMethods(object currentDynamicMethods);
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern string StripFileInfo(string stackTrace, bool isRemoteStackTrace);
+#endif // !FEATURE_CORECLR
+
+ [SecuritySafeCritical]
+ internal object DeepCopyStackTrace(object currentStackTrace)
+ {
+ if (currentStackTrace != null)
+ {
+ return CopyStackTrace(currentStackTrace);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal object DeepCopyDynamicMethods(object currentDynamicMethods)
+ {
+ if (currentDynamicMethods != null)
+ {
+ return CopyDynamicMethods(currentDynamicMethods);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal void GetStackTracesDeepCopy(out object currentStackTrace, out object dynamicMethodArray)
+ {
+ GetStackTracesDeepCopy(this, out currentStackTrace, out dynamicMethodArray);
+ }
+
+ // This is invoked by ExceptionDispatchInfo.Throw to restore the exception stack trace, corresponding to the original throw of the
+ // exception, just before the exception is "rethrown".
+ [SecuritySafeCritical]
+ internal void RestoreExceptionDispatchInfo(System.Runtime.ExceptionServices.ExceptionDispatchInfo exceptionDispatchInfo)
+ {
+ bool fCanProcessException = !(IsImmutableAgileException(this));
+ // Restore only for non-preallocated exceptions
+ if (fCanProcessException)
+ {
+ // Take a lock to ensure only one thread can restore the details
+ // at a time against this exception object that could have
+ // multiple ExceptionDispatchInfo instances associated with it.
+ //
+ // We do this inside a finally clause to ensure ThreadAbort cannot
+ // be injected while we have taken the lock. This is to prevent
+ // unrelated exception restorations from getting blocked due to TAE.
+ try{}
+ finally
+ {
+ // When restoring back the fields, we again create a copy and set reference to them
+ // in the exception object. This will ensure that when this exception is thrown and these
+ // fields are modified, then EDI's references remain intact.
+ //
+ // Since deep copying can throw on OOM, try to get the copies
+ // outside the lock.
+ object _stackTraceCopy = (exceptionDispatchInfo.BinaryStackTraceArray == null)?null:DeepCopyStackTrace(exceptionDispatchInfo.BinaryStackTraceArray);
+ object _dynamicMethodsCopy = (exceptionDispatchInfo.DynamicMethodArray == null)?null:DeepCopyDynamicMethods(exceptionDispatchInfo.DynamicMethodArray);
+
+ // Finally, restore the information.
+ //
+ // Since EDI can be created at various points during exception dispatch (e.g. at various frames on the stack) for the same exception instance,
+ // they can have different data to be restored. Thus, to ensure atomicity of restoration from each EDI, perform the restore under a lock.
+ lock(Exception.s_EDILock)
+ {
+ _watsonBuckets = exceptionDispatchInfo.WatsonBuckets;
+ _ipForWatsonBuckets = exceptionDispatchInfo.IPForWatsonBuckets;
+ _remoteStackTraceString = exceptionDispatchInfo.RemoteStackTrace;
+ SaveStackTracesFromDeepCopy(this, _stackTraceCopy, _dynamicMethodsCopy);
+ }
+ _stackTraceString = null;
+
+ // Marks the TES state to indicate we have restored foreign exception
+ // dispatch information.
+ Exception.PrepareForForeignExceptionRaise();
+ }
+ }
+ }
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
+
+ private String _className; //Needed for serialization.
+ private MethodBase _exceptionMethod; //Needed for serialization.
+ private String _exceptionMethodString; //Needed for serialization.
+ internal String _message;
+ private IDictionary _data;
+ private Exception _innerException;
+ private String _helpURL;
+ private Object _stackTrace;
+ [OptionalField] // This isnt present in pre-V4 exception objects that would be serialized.
+ private Object _watsonBuckets;
+ private String _stackTraceString; //Needed for serialization.
+ private String _remoteStackTraceString;
+ private int _remoteStackIndex;
+#pragma warning disable 414 // Field is not used from managed.
+ // _dynamicMethods is an array of System.Resolver objects, used to keep
+ // DynamicMethodDescs alive for the lifetime of the exception. We do this because
+ // the _stackTrace field holds MethodDescs, and a DynamicMethodDesc can be destroyed
+ // unless a System.Resolver object roots it.
+ private Object _dynamicMethods;
+#pragma warning restore 414
+
+ // @MANAGED: HResult is used from within the EE! Rename with care - check VM directory
+ internal int _HResult; // HResult
+
+ public int HResult
+ {
+ get
+ {
+ return _HResult;
+ }
+ protected set
+ {
+ _HResult = value;
+ }
+ }
+
+ private String _source; // Mainly used by VB.
+ // WARNING: Don't delete/rename _xptrs and _xcode - used by functions
+ // on Marshal class. Native functions are in COMUtilNative.cpp & AppDomain
+ private IntPtr _xptrs; // Internal EE stuff
+#pragma warning disable 414 // Field is not used from managed.
+ private int _xcode; // Internal EE stuff
+#pragma warning restore 414
+ [OptionalField]
+ private UIntPtr _ipForWatsonBuckets; // Used to persist the IP for Watson Bucketing
+
+#if FEATURE_SERIALIZATION
+ [OptionalField(VersionAdded = 4)]
+ private SafeSerializationManager _safeSerializationManager;
+#endif // FEATURE_SERIALIZATION
+
+ // See src\inc\corexcep.h's EXCEPTION_COMPLUS definition:
+ private const int _COMPlusExceptionCode = unchecked((int)0xe0434352); // Win32 exception code for COM+ exceptions
+
+ // InternalToString is called by the runtime to get the exception text
+ // and create a corresponding CrossAppDomainMarshaledException
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual String InternalToString()
+ {
+ try
+ {
+#pragma warning disable 618
+ SecurityPermission sp= new SecurityPermission(SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy);
+#pragma warning restore 618
+ sp.Assert();
+ }
+ catch
+ {
+ //under normal conditions there should be no exceptions
+ //however if something wrong happens we still can call the usual ToString
+ }
+
+ // Get the current stack trace string.
+ return ToString(true, true);
+ }
+
+ // this method is required so Object.GetType is not made virtual by the compiler
+ // _Exception.GetType()
+ public new Type GetType()
+ {
+ return base.GetType();
+ }
+
+ internal bool IsTransient
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return nIsTransient(_HResult);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static bool nIsTransient(int hr);
+
+
+ // This piece of infrastructure exists to help avoid deadlocks
+ // between parts of mscorlib that might throw an exception while
+ // holding a lock that are also used by mscorlib's ResourceManager
+ // instance. As a special case of code that may throw while holding
+ // a lock, we also need to fix our asynchronous exceptions to use
+ // Win32 resources as well (assuming we ever call a managed
+ // constructor on instances of them). We should grow this set of
+ // exception messages as we discover problems, then move the resources
+ // involved to native code.
+ internal enum ExceptionMessageKind
+ {
+ ThreadAbort = 1,
+ ThreadInterrupted = 2,
+ OutOfMemory = 3
+ }
+
+ // See comment on ExceptionMessageKind
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static String GetMessageFromNativeResources(ExceptionMessageKind kind)
+ {
+ string retMesg = null;
+ GetMessageFromNativeResources(kind, JitHelpers.GetStringHandleOnStack(ref retMesg));
+ return retMesg;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetMessageFromNativeResources(ExceptionMessageKind kind, StringHandleOnStack retMesg);
+ }
+
+
+
+#if FEATURE_CORECLR
+
+ //--------------------------------------------------------------------------
+ // Telesto: Telesto doesn't support appdomain marshaling of objects so
+ // managed exceptions that leak across appdomain boundaries are flatted to
+ // its ToString() output and rethrown as an CrossAppDomainMarshaledException.
+ // The Message field is set to the ToString() output of the original exception.
+ //--------------------------------------------------------------------------
+
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ internal sealed class CrossAppDomainMarshaledException : SystemException
+ {
+ public CrossAppDomainMarshaledException(String message, int errorCode)
+ : base(message)
+ {
+ SetErrorCode(errorCode);
+ }
+
+ // Normally, only Telesto's UEF will see these exceptions.
+ // This override prints out the original Exception's ToString()
+ // output and hides the fact that it is wrapped inside another excepton.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ internal override String InternalToString()
+ {
+ return Message;
+ }
+
+ }
+#endif
+
+
+}
+
diff --git a/src/mscorlib/src/System/ExecutionEngineException.cs b/src/mscorlib/src/System/ExecutionEngineException.cs
new file mode 100644
index 0000000000..5b2592cca9
--- /dev/null
+++ b/src/mscorlib/src/System/ExecutionEngineException.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for misc execution engine exceptions.
+** Currently, its only used as a placeholder type when the EE
+** does a FailFast.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [Obsolete("This type previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete.")]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class ExecutionEngineException : SystemException {
+ public ExecutionEngineException()
+ : base(Environment.GetResourceString("Arg_ExecutionEngineException")) {
+ SetErrorCode(__HResults.COR_E_EXECUTIONENGINE);
+ }
+
+ public ExecutionEngineException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_EXECUTIONENGINE);
+ }
+
+ public ExecutionEngineException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_EXECUTIONENGINE);
+ }
+
+ internal ExecutionEngineException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/FieldAccessException.cs b/src/mscorlib/src/System/FieldAccessException.cs
new file mode 100644
index 0000000000..fbc3b1f592
--- /dev/null
+++ b/src/mscorlib/src/System/FieldAccessException.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: The exception class for class loading failures.
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class FieldAccessException : MemberAccessException {
+ public FieldAccessException()
+ : base(Environment.GetResourceString("Arg_FieldAccessException")) {
+ SetErrorCode(__HResults.COR_E_FIELDACCESS);
+ }
+
+ public FieldAccessException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_FIELDACCESS);
+ }
+
+ public FieldAccessException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_FIELDACCESS);
+ }
+
+ protected FieldAccessException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/FlagsAttribute.cs b/src/mscorlib/src/System/FlagsAttribute.cs
new file mode 100644
index 0000000000..cb955cf3a1
--- /dev/null
+++ b/src/mscorlib/src/System/FlagsAttribute.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System {
+
+ using System;
+ // Custom attribute to indicate that the enum
+ // should be treated as a bitfield (or set of flags).
+ // An IDE may use this information to provide a richer
+ // development experience.
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Enum, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class FlagsAttribute : Attribute
+ {
+ public FlagsAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/FormatException.cs b/src/mscorlib/src/System/FormatException.cs
new file mode 100644
index 0000000000..2e1c8a9cd4
--- /dev/null
+++ b/src/mscorlib/src/System/FormatException.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Exception to designate an illegal argument to FormatMessage.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class FormatException : SystemException {
+ public FormatException()
+ : base(Environment.GetResourceString("Arg_FormatException")) {
+ SetErrorCode(__HResults.COR_E_FORMAT);
+ }
+
+ public FormatException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_FORMAT);
+ }
+
+ public FormatException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_FORMAT);
+ }
+
+ protected FormatException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/FormattableString.cs b/src/mscorlib/src/System/FormattableString.cs
new file mode 100644
index 0000000000..ef56bcf3e0
--- /dev/null
+++ b/src/mscorlib/src/System/FormattableString.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: FormattableString
+**
+**
+** Purpose: implementation of the FormattableString
+** class.
+**
+===========================================================*/
+namespace System
+{
+ /// <summary>
+ /// A composite format string along with the arguments to be formatted. An instance of this
+ /// type may result from the use of the C# or VB language primitive "interpolated string".
+ /// </summary>
+ public abstract class FormattableString : IFormattable
+ {
+ /// <summary>
+ /// The composite format string.
+ /// </summary>
+ public abstract string Format { get; }
+
+ /// <summary>
+ /// Returns an object array that contains zero or more objects to format. Clients should not
+ /// mutate the contents of the array.
+ /// </summary>
+ public abstract object[] GetArguments();
+
+ /// <summary>
+ /// The number of arguments to be formatted.
+ /// </summary>
+ public abstract int ArgumentCount { get; }
+
+ /// <summary>
+ /// Returns one argument to be formatted from argument position <paramref name="index"/>.
+ /// </summary>
+ public abstract object GetArgument(int index);
+
+ /// <summary>
+ /// Format to a string using the given culture.
+ /// </summary>
+ public abstract string ToString(IFormatProvider formatProvider);
+
+ string IFormattable.ToString(string ignored, IFormatProvider formatProvider)
+ {
+ return ToString(formatProvider);
+ }
+
+ /// <summary>
+ /// Format the given object in the invariant culture. This static method may be
+ /// imported in C# by
+ /// <code>
+ /// using static System.FormattableString;
+ /// </code>.
+ /// Within the scope
+ /// of that import directive an interpolated string may be formatted in the
+ /// invariant culture by writing, for example,
+ /// <code>
+ /// Invariant($"{{ lat = {latitude}; lon = {longitude} }}")
+ /// </code>
+ /// </summary>
+ public static string Invariant(FormattableString formattable)
+ {
+ if (formattable == null)
+ {
+ throw new ArgumentNullException("formattable");
+ }
+
+ return formattable.ToString(Globalization.CultureInfo.InvariantCulture);
+ }
+
+ public override string ToString()
+ {
+ return ToString(Globalization.CultureInfo.CurrentCulture);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/GC.cs b/src/mscorlib/src/System/GC.cs
new file mode 100644
index 0000000000..73c676df7d
--- /dev/null
+++ b/src/mscorlib/src/System/GC.cs
@@ -0,0 +1,641 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Exposes features of the Garbage Collector through
+** the class libraries. This is a class which cannot be
+** instantiated.
+**
+**
+===========================================================*/
+namespace System {
+ //This class only static members and doesn't require the serializable keyword.
+
+ using System;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using System.Security;
+ using System.Threading;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public enum GCCollectionMode
+ {
+ Default = 0,
+ Forced = 1,
+ Optimized = 2
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!
+ // make sure you change the def in vm\gc.h
+ // if you change this!
+ [Serializable]
+ internal enum InternalGCCollectionMode
+ {
+ NonBlocking = 0x00000001,
+ Blocking = 0x00000002,
+ Optimized = 0x00000004,
+ Compacting = 0x00000008,
+ }
+
+ // !!!!!!!!!!!!!!!!!!!!!!!
+ // make sure you change the def in vm\gc.h
+ // if you change this!
+ [Serializable]
+ public enum GCNotificationStatus
+ {
+ Succeeded = 0,
+ Failed = 1,
+ Canceled = 2,
+ Timeout = 3,
+ NotApplicable = 4
+ }
+
+ public static class GC
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetGCLatencyMode();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int SetGCLatencyMode(int newLatencyMode);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int _StartNoGCRegion(long totalSize, bool lohSizeKnown, long lohSize, bool disallowFullBlockingGC);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int _EndNoGCRegion();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetLOHCompactionMode();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void SetLOHCompactionMode(int newLOHCompactionMode);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int GetGenerationWR(IntPtr handle);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern long GetTotalMemory();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _Collect(int generation, int mode);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int GetMaxGeneration();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern int _CollectionCount (int generation, int getSpecialGCCount);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsServerGC();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void _AddMemoryPressure(UInt64 bytesAllocated);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void _RemoveMemoryPressure(UInt64 bytesAllocated);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void AddMemoryPressure (long bytesAllocated) {
+ if( bytesAllocated <= 0) {
+ throw new ArgumentOutOfRangeException("bytesAllocated",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+
+ if( (4 == IntPtr.Size) && (bytesAllocated > Int32.MaxValue) ) {
+ throw new ArgumentOutOfRangeException("pressure",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegInt32"));
+ }
+ Contract.EndContractBlock();
+
+ _AddMemoryPressure((ulong)bytesAllocated);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void RemoveMemoryPressure (long bytesAllocated) {
+ if( bytesAllocated <= 0) {
+ throw new ArgumentOutOfRangeException("bytesAllocated",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+
+ if( (4 == IntPtr.Size) && (bytesAllocated > Int32.MaxValue) ) {
+ throw new ArgumentOutOfRangeException("bytesAllocated",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegInt32"));
+ }
+ Contract.EndContractBlock();
+
+ _RemoveMemoryPressure((ulong) bytesAllocated);
+ }
+
+
+ // Returns the generation that obj is currently in.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetGeneration(Object obj);
+
+
+ // Forces a collection of all generations from 0 through Generation.
+ //
+ public static void Collect(int generation) {
+ Collect(generation, GCCollectionMode.Default);
+ }
+
+ // Garbage Collect all generations.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Collect() {
+ //-1 says to GC all generations.
+ _Collect(-1, (int)InternalGCCollectionMode.Blocking);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Collect(int generation, GCCollectionMode mode)
+ {
+ Collect(generation, mode, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Collect(int generation, GCCollectionMode mode, bool blocking)
+ {
+ Collect(generation, mode, blocking, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Collect(int generation, GCCollectionMode mode, bool blocking, bool compacting)
+ {
+ if (generation<0)
+ {
+ throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+
+ if ((mode < GCCollectionMode.Default) || (mode > GCCollectionMode.Optimized))
+ {
+ throw new ArgumentOutOfRangeException("mode", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ }
+
+ Contract.EndContractBlock();
+
+ int iInternalModes = 0;
+
+ if (mode == GCCollectionMode.Optimized)
+ {
+ iInternalModes |= (int)InternalGCCollectionMode.Optimized;
+ }
+
+ if (compacting)
+ iInternalModes |= (int)InternalGCCollectionMode.Compacting;
+
+ if (blocking)
+ {
+ iInternalModes |= (int)InternalGCCollectionMode.Blocking;
+ }
+ else if (!compacting)
+ {
+ iInternalModes |= (int)InternalGCCollectionMode.NonBlocking;
+ }
+
+ _Collect(generation, iInternalModes);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int CollectionCount (int generation)
+ {
+ if (generation<0)
+ {
+ throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+ Contract.EndContractBlock();
+ return _CollectionCount(generation, 0);
+ }
+
+ // pass in true to get the BGC or FGC count.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static int CollectionCount (int generation, bool getSpecialGCCount)
+ {
+ if (generation<0)
+ {
+ throw new ArgumentOutOfRangeException("generation", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+ Contract.EndContractBlock();
+ return _CollectionCount(generation, (getSpecialGCCount ? 1 : 0));
+ }
+
+ // This method DOES NOT DO ANYTHING in and of itself. It's used to
+ // prevent a finalizable object from losing any outstanding references
+ // a touch too early. The JIT is very aggressive about keeping an
+ // object's lifetime to as small a window as possible, to the point
+ // where a 'this' pointer isn't considered live in an instance method
+ // unless you read a value from the instance. So for finalizable
+ // objects that store a handle or pointer and provide a finalizer that
+ // cleans them up, this can cause subtle race conditions with the finalizer
+ // thread. This isn't just about handles - it can happen with just
+ // about any finalizable resource.
+ //
+ // Users should insert a call to this method right after the last line
+ // of their code where their code still needs the object to be kept alive.
+ // The object which reference is passed into this method will not
+ // be eligible for collection until the call to this method happens.
+ // Once the call to this method has happened the object may immediately
+ // become eligible for collection. Here is an example:
+ //
+ // "...all you really need is one object with a Finalize method, and a
+ // second object with a Close/Dispose/Done method. Such as the following
+ // contrived example:
+ //
+ // class Foo {
+ // Stream stream = ...;
+ // protected void Finalize() { stream.Close(); }
+ // void Problem() { stream.MethodThatSpansGCs(); }
+ // static void Main() { new Foo().Problem(); }
+ // }
+ //
+ //
+ // In this code, Foo will be finalized in the middle of
+ // stream.MethodThatSpansGCs, thus closing a stream still in use."
+ //
+ // If we insert a call to GC.KeepAlive(this) at the end of Problem(), then
+ // Foo doesn't get finalized and the stream stays open.
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void KeepAlive(Object obj)
+ {
+ }
+
+ // Returns the generation in which wo currently resides.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int GetGeneration(WeakReference wo) {
+ int result = GetGenerationWR(wo.m_handle);
+ KeepAlive(wo);
+ return result;
+ }
+
+ // Returns the maximum GC generation. Currently assumes only 1 heap.
+ //
+ public static int MaxGeneration {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return GetMaxGeneration(); }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _WaitForPendingFinalizers();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void WaitForPendingFinalizers() {
+ // QCalls can not be exposed from mscorlib directly, need to wrap it.
+ _WaitForPendingFinalizers();
+ }
+
+ // Indicates that the system should not call the Finalize() method on
+ // an object that would normally require this call.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern void _SuppressFinalize(Object o);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void SuppressFinalize(Object obj) {
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+ Contract.EndContractBlock();
+ _SuppressFinalize(obj);
+ }
+
+ // Indicates that the system should call the Finalize() method on an object
+ // for which SuppressFinalize has already been called. The other situation
+ // where calling ReRegisterForFinalize is useful is inside a finalizer that
+ // needs to resurrect itself or an object that it references.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _ReRegisterForFinalize(Object o);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void ReRegisterForFinalize(Object obj) {
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+ Contract.EndContractBlock();
+ _ReRegisterForFinalize(obj);
+ }
+
+ // Returns the total number of bytes currently in use by live objects in
+ // the GC heap. This does not return the total size of the GC heap, but
+ // only the live objects in the GC heap.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static long GetTotalMemory(bool forceFullCollection) {
+ long size = GetTotalMemory();
+ if (!forceFullCollection)
+ return size;
+ // If we force a full collection, we will run the finalizers on all
+ // existing objects and do a collection until the value stabilizes.
+ // The value is "stable" when either the value is within 5% of the
+ // previous call to GetTotalMemory, or if we have been sitting
+ // here for more than x times (we don't want to loop forever here).
+ int reps = 20; // Number of iterations
+ long newSize = size;
+ float diff;
+ do {
+ GC.WaitForPendingFinalizers();
+ GC.Collect();
+ size = newSize;
+ newSize = GetTotalMemory();
+ diff = ((float)(newSize - size)) / size;
+ } while (reps-- > 0 && !(-.05 < diff && diff < .05));
+ return newSize;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern long _GetAllocatedBytesForCurrentThread();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static long GetAllocatedBytesForCurrentThread() {
+ return _GetAllocatedBytesForCurrentThread();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool _RegisterForFullGCNotification(int maxGenerationPercentage, int largeObjectHeapPercentage);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool _CancelFullGCNotification();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int _WaitForFullGCApproach(int millisecondsTimeout);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int _WaitForFullGCComplete(int millisecondsTimeout);
+
+ [SecurityCritical]
+ public static void RegisterForFullGCNotification(int maxGenerationThreshold, int largeObjectHeapThreshold)
+ {
+ if ((maxGenerationThreshold <= 0) || (maxGenerationThreshold >= 100))
+ {
+ throw new ArgumentOutOfRangeException("maxGenerationThreshold",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"),
+ 1,
+ 99));
+ }
+
+ if ((largeObjectHeapThreshold <= 0) || (largeObjectHeapThreshold >= 100))
+ {
+ throw new ArgumentOutOfRangeException("largeObjectHeapThreshold",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"),
+ 1,
+ 99));
+}
+
+ if (!_RegisterForFullGCNotification(maxGenerationThreshold, largeObjectHeapThreshold))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotWithConcurrentGC"));
+ }
+ }
+
+ [SecurityCritical]
+ public static void CancelFullGCNotification()
+ {
+ if (!_CancelFullGCNotification())
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotWithConcurrentGC"));
+ }
+ }
+
+ [SecurityCritical]
+ public static GCNotificationStatus WaitForFullGCApproach()
+ {
+ return (GCNotificationStatus)_WaitForFullGCApproach(-1);
+ }
+
+ [SecurityCritical]
+ public static GCNotificationStatus WaitForFullGCApproach(int millisecondsTimeout)
+ {
+ if (millisecondsTimeout < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+
+ return (GCNotificationStatus)_WaitForFullGCApproach(millisecondsTimeout);
+ }
+
+ [SecurityCritical]
+ public static GCNotificationStatus WaitForFullGCComplete()
+ {
+ return (GCNotificationStatus)_WaitForFullGCComplete(-1);
+ }
+
+ [SecurityCritical]
+ public static GCNotificationStatus WaitForFullGCComplete(int millisecondsTimeout)
+ {
+ if (millisecondsTimeout < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ return (GCNotificationStatus)_WaitForFullGCComplete(millisecondsTimeout);
+ }
+
+ enum StartNoGCRegionStatus
+ {
+ Succeeded = 0,
+ NotEnoughMemory = 1,
+ AmountTooLarge = 2,
+ AlreadyInProgress = 3
+ }
+
+ enum EndNoGCRegionStatus
+ {
+ Succeeded = 0,
+ NotInProgress = 1,
+ GCInduced = 2,
+ AllocationExceeded = 3
+ }
+
+ [SecurityCritical]
+ static bool StartNoGCRegionWorker(long totalSize, bool hasLohSize, long lohSize, bool disallowFullBlockingGC)
+ {
+ StartNoGCRegionStatus status = (StartNoGCRegionStatus)_StartNoGCRegion(totalSize, hasLohSize, lohSize, disallowFullBlockingGC);
+ if (status == StartNoGCRegionStatus.AmountTooLarge)
+ throw new ArgumentOutOfRangeException("totalSize",
+ "totalSize is too large. For more information about setting the maximum size, see \"Latency Modes\" in http://go.microsoft.com/fwlink/?LinkId=522706");
+ else if (status == StartNoGCRegionStatus.AlreadyInProgress)
+ throw new InvalidOperationException("The NoGCRegion mode was already in progress");
+ else if (status == StartNoGCRegionStatus.NotEnoughMemory)
+ return false;
+ return true;
+ }
+
+ [SecurityCritical]
+ public static bool TryStartNoGCRegion(long totalSize)
+ {
+ return StartNoGCRegionWorker(totalSize, false, 0, false);
+ }
+
+ [SecurityCritical]
+ public static bool TryStartNoGCRegion(long totalSize, long lohSize)
+ {
+ return StartNoGCRegionWorker(totalSize, true, lohSize, false);
+ }
+
+ [SecurityCritical]
+ public static bool TryStartNoGCRegion(long totalSize, bool disallowFullBlockingGC)
+ {
+ return StartNoGCRegionWorker(totalSize, false, 0, disallowFullBlockingGC);
+ }
+
+ [SecurityCritical]
+ public static bool TryStartNoGCRegion(long totalSize, long lohSize, bool disallowFullBlockingGC)
+ {
+ return StartNoGCRegionWorker(totalSize, true, lohSize, disallowFullBlockingGC);
+ }
+
+ [SecurityCritical]
+ static EndNoGCRegionStatus EndNoGCRegionWorker()
+ {
+ EndNoGCRegionStatus status = (EndNoGCRegionStatus)_EndNoGCRegion();
+ if (status == EndNoGCRegionStatus.NotInProgress)
+ throw new InvalidOperationException("NoGCRegion mode must be set");
+ else if (status == EndNoGCRegionStatus.GCInduced)
+ throw new InvalidOperationException("Garbage collection was induced in NoGCRegion mode");
+ else if (status == EndNoGCRegionStatus.AllocationExceeded)
+ throw new InvalidOperationException("Allocated memory exceeds specified memory for NoGCRegion mode");
+
+ return EndNoGCRegionStatus.Succeeded;
+ }
+
+ [SecurityCritical]
+ public static void EndNoGCRegion()
+ {
+ EndNoGCRegionWorker();
+ }
+ }
+
+#if !FEATURE_CORECLR
+ internal class SizedReference : IDisposable
+ {
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr CreateSizedRef(Object o);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FreeSizedRef(IntPtr h);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object GetTargetOfSizedRef(IntPtr h);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Int64 GetApproximateSizeOfSizedRef(IntPtr h);
+
+ #pragma warning disable 420
+ [System.Security.SecuritySafeCritical]
+ private void Free()
+ {
+ IntPtr temp = _handle;
+ if (temp != IntPtr.Zero &&
+ (Interlocked.CompareExchange(ref _handle, IntPtr.Zero, temp) == temp))
+ {
+ FreeSizedRef(temp);
+ }
+ }
+
+ internal volatile IntPtr _handle;
+
+ [System.Security.SecuritySafeCritical]
+ public SizedReference(Object target)
+ {
+ IntPtr temp = IntPtr.Zero;
+ temp = CreateSizedRef(target);
+ _handle = temp;
+ }
+
+ ~SizedReference()
+ {
+ Free();
+ }
+
+ public Object Target
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ IntPtr temp = _handle;
+ if (temp == IntPtr.Zero)
+ {
+ return null;
+ }
+
+ Object o = GetTargetOfSizedRef(temp);
+
+ return (_handle == IntPtr.Zero) ? null : o;
+ }
+ }
+
+ public Int64 ApproximateSize
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ IntPtr temp = _handle;
+
+ if (temp == IntPtr.Zero)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+ }
+
+ Int64 size = GetApproximateSizeOfSizedRef(temp);
+
+ if (_handle == IntPtr.Zero)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+ }
+ else
+ {
+ return size;
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ Free();
+ GC.SuppressFinalize(this);
+ }
+ }
+#endif
+}
diff --git a/src/mscorlib/src/System/Globalization/BidiCategory.cs b/src/mscorlib/src/System/Globalization/BidiCategory.cs
new file mode 100644
index 0000000000..1041776424
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/BidiCategory.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose:
+**
+**
+============================================================*/
+namespace System.Globalization {
+ [Serializable]
+ internal enum BidiCategory {
+ LeftToRight = 0,
+ LeftToRightEmbedding = 1,
+ LeftToRightOverride = 2,
+ RightToLeft = 3,
+ RightToLeftArabic = 4,
+ RightToLeftEmbedding = 5,
+ RightToLeftOverride = 6,
+ PopDirectionalFormat = 7,
+ EuropeanNumber = 8,
+ EuropeanNumberSeparator = 9,
+ EuropeanNumberTerminator = 10,
+ ArabicNumber = 11,
+ CommonNumberSeparator = 12,
+ NonSpacingMark = 13,
+ BoundaryNeutral = 14,
+ ParagraphSeparator = 15,
+ SegmentSeparator = 16,
+ Whitespace = 17,
+ OtherNeutrals = 18,
+ LeftToRightIsolate = 19,
+ RightToLeftIsolate = 20,
+ FirstStrongIsolate = 21,
+ PopDirectionIsolate = 22,
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/Calendar.cs b/src/mscorlib/src/System/Globalization/Calendar.cs
new file mode 100644
index 0000000000..d6dfdc9f4b
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/Calendar.cs
@@ -0,0 +1,861 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // This abstract class represents a calendar. A calendar reckons time in
+ // divisions such as weeks, months and years. The number, length and start of
+ // the divisions vary in each calendar.
+ //
+ // Any instant in time can be represented as an n-tuple of numeric values using
+ // a particular calendar. For example, the next vernal equinox occurs at (0.0, 0
+ // , 46, 8, 20, 3, 1999) in the Gregorian calendar. An implementation of
+ // Calendar can map any DateTime value to such an n-tuple and vice versa. The
+ // DateTimeFormat class can map between such n-tuples and a textual
+ // representation such as "8:46 AM March 20th 1999 AD".
+ //
+ // Most calendars identify a year which begins the current era. There may be any
+ // number of previous eras. The Calendar class identifies the eras as enumerated
+ // integers where the current era (CurrentEra) has the value zero.
+ //
+ // For consistency, the first unit in each interval, e.g. the first month, is
+ // assigned the value one.
+ // The calculation of hour/minute/second is moved to Calendar from GregorianCalendar,
+ // since most of the calendars (or all?) have the same way of calcuating hour/minute/second.
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Calendar : ICloneable
+ {
+
+ // Number of 100ns (10E-7 second) ticks per time unit
+ internal const long TicksPerMillisecond = 10000;
+ internal const long TicksPerSecond = TicksPerMillisecond * 1000;
+ internal const long TicksPerMinute = TicksPerSecond * 60;
+ internal const long TicksPerHour = TicksPerMinute * 60;
+ internal const long TicksPerDay = TicksPerHour * 24;
+
+ // Number of milliseconds per time unit
+ internal const int MillisPerSecond = 1000;
+ internal const int MillisPerMinute = MillisPerSecond * 60;
+ internal const int MillisPerHour = MillisPerMinute * 60;
+ internal const int MillisPerDay = MillisPerHour * 24;
+
+ // Number of days in a non-leap year
+ internal const int DaysPerYear = 365;
+ // Number of days in 4 years
+ internal const int DaysPer4Years = DaysPerYear * 4 + 1;
+ // Number of days in 100 years
+ internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
+ // Number of days in 400 years
+ internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
+
+ // Number of days from 1/1/0001 to 1/1/10000
+ internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
+
+ internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
+
+ //
+ // Calendar ID Values. This is used to get data from calendar.nlp.
+ // The order of calendar ID means the order of data items in the table.
+ //
+
+ internal const int CAL_GREGORIAN = 1 ; // Gregorian (localized) calendar
+ internal const int CAL_GREGORIAN_US = 2 ; // Gregorian (U.S.) calendar
+ internal const int CAL_JAPAN = 3 ; // Japanese Emperor Era calendar
+ internal const int CAL_TAIWAN = 4 ; // Taiwan Era calendar
+ internal const int CAL_KOREA = 5 ; // Korean Tangun Era calendar
+ internal const int CAL_HIJRI = 6 ; // Hijri (Arabic Lunar) calendar
+ internal const int CAL_THAI = 7 ; // Thai calendar
+ internal const int CAL_HEBREW = 8 ; // Hebrew (Lunar) calendar
+ internal const int CAL_GREGORIAN_ME_FRENCH = 9 ; // Gregorian Middle East French calendar
+ internal const int CAL_GREGORIAN_ARABIC = 10; // Gregorian Arabic calendar
+ internal const int CAL_GREGORIAN_XLIT_ENGLISH = 11; // Gregorian Transliterated English calendar
+ internal const int CAL_GREGORIAN_XLIT_FRENCH = 12;
+ internal const int CAL_JULIAN = 13;
+ internal const int CAL_JAPANESELUNISOLAR = 14;
+ internal const int CAL_CHINESELUNISOLAR = 15;
+ internal const int CAL_SAKA = 16; // reserved to match Office but not implemented in our code
+ internal const int CAL_LUNAR_ETO_CHN = 17; // reserved to match Office but not implemented in our code
+ internal const int CAL_LUNAR_ETO_KOR = 18; // reserved to match Office but not implemented in our code
+ internal const int CAL_LUNAR_ETO_ROKUYOU = 19; // reserved to match Office but not implemented in our code
+ internal const int CAL_KOREANLUNISOLAR = 20;
+ internal const int CAL_TAIWANLUNISOLAR = 21;
+ internal const int CAL_PERSIAN = 22;
+ internal const int CAL_UMALQURA = 23;
+
+ internal int m_currentEraValue = -1;
+
+ [System.Runtime.Serialization.OptionalField(VersionAdded = 2)]
+ private bool m_isReadOnly = false;
+
+ // The minimum supported DateTime range for the calendar.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ // The maximum supported DateTime range for the calendar.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+
+
+
+ protected Calendar() {
+ //Do-nothing constructor.
+ }
+
+ ///
+ // This can not be abstract, otherwise no one can create a subclass of Calendar.
+ //
+ internal virtual int ID {
+ get {
+ return (-1);
+ }
+ }
+
+ ///
+ // Return the Base calendar ID for calendars that didn't have defined data in calendarData
+ //
+
+ internal virtual int BaseCalendarID
+ {
+ get { return ID; }
+ }
+
+ // Returns the type of the calendar.
+ //
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.Unknown;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsReadOnly
+ //
+ // Detect if the object is readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsReadOnly
+ {
+ get { return (m_isReadOnly); }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Clone
+ //
+ // Is the implementation of ICloneable.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual Object Clone()
+ {
+ object o = MemberwiseClone();
+ ((Calendar) o).SetReadOnlyState(false);
+ return (o);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ReadOnly
+ //
+ // Create a cloned readonly instance or return the input one if it is
+ // readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static Calendar ReadOnly(Calendar calendar)
+ {
+ if (calendar == null) { throw new ArgumentNullException("calendar"); }
+ Contract.EndContractBlock();
+ if (calendar.IsReadOnly) { return (calendar); }
+
+ Calendar clonedCalendar = (Calendar)(calendar.MemberwiseClone());
+ clonedCalendar.SetReadOnlyState(true);
+
+ return (clonedCalendar);
+ }
+
+ internal void VerifyWritable()
+ {
+ if (m_isReadOnly)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ }
+
+ internal void SetReadOnlyState(bool readOnly)
+ {
+ m_isReadOnly = readOnly;
+ }
+
+
+ /*=================================CurrentEraValue==========================
+ **Action: This is used to convert CurretEra(0) to an appropriate era value.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ **Notes:
+ ** The value is from calendar.nlp.
+ ============================================================================*/
+
+ internal virtual int CurrentEraValue {
+ get {
+ // The following code assumes that the current era value can not be -1.
+ if (m_currentEraValue == -1) {
+ Contract.Assert(BaseCalendarID > 0, "[Calendar.CurrentEraValue] Expected ID > 0");
+ m_currentEraValue = CalendarData.GetCalendarData(BaseCalendarID).iCurrentEra;
+ }
+ return (m_currentEraValue);
+ }
+ }
+
+ // The current era for a calendar.
+
+ public const int CurrentEra = 0;
+
+ internal int twoDigitYearMax = -1;
+
+ internal static void CheckAddResult(long ticks, DateTime minValue, DateTime maxValue) {
+ if (ticks < minValue.Ticks || ticks > maxValue.Ticks) {
+ throw new ArgumentException(
+ String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Argument_ResultCalendarRange"),
+ minValue, maxValue));
+ }
+ Contract.EndContractBlock();
+ }
+
+ internal DateTime Add(DateTime time, double value, int scale) {
+ // From ECMA CLI spec, Partition III, section 3.27:
+ //
+ // If overflow occurs converting a floating-point type to an integer, or if the floating-point value
+ // being converted to an integer is a NaN, the value returned is unspecified.
+ //
+ // Based upon this, this method should be performing the comparison against the double
+ // before attempting a cast. Otherwise, the result is undefined.
+ double tempMillis = (value * scale + (value >= 0 ? 0.5 : -0.5));
+ if (!((tempMillis > -(double)MaxMillis) && (tempMillis < (double)MaxMillis)))
+ {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_AddValue"));
+ }
+
+ long millis = (long)tempMillis;
+ long ticks = time.Ticks + millis * TicksPerMillisecond;
+ CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // milliseconds to the specified DateTime. The result is computed by rounding
+ // the number of milliseconds given by value to the nearest integer,
+ // and adding that interval to the specified DateTime. The value
+ // argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddMilliseconds(DateTime time, double milliseconds) {
+ return (Add(time, milliseconds, 1));
+ }
+
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // days to the specified DateTime. The result is computed by rounding the
+ // fractional number of days given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddDays(DateTime time, int days) {
+ return (Add(time, days, MillisPerDay));
+ }
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // hours to the specified DateTime. The result is computed by rounding the
+ // fractional number of hours given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddHours(DateTime time, int hours) {
+ return (Add(time, hours, MillisPerHour));
+ }
+
+
+ // Returns the DateTime resulting from adding a fractional number of
+ // minutes to the specified DateTime. The result is computed by rounding the
+ // fractional number of minutes given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddMinutes(DateTime time, int minutes) {
+ return (Add(time, minutes, MillisPerMinute));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public abstract DateTime AddMonths(DateTime time, int months);
+
+ // Returns the DateTime resulting from adding a number of
+ // seconds to the specified DateTime. The result is computed by rounding the
+ // fractional number of seconds given by value to the nearest
+ // millisecond, and adding that interval to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddSeconds(DateTime time, int seconds) {
+ return Add(time, seconds, MillisPerSecond);
+ }
+
+ // Returns the DateTime resulting from adding a number of
+ // weeks to the specified DateTime. The
+ // value argument is permitted to be negative.
+ //
+
+ public virtual DateTime AddWeeks(DateTime time, int weeks) {
+ return (AddDays(time, weeks * 7));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public abstract DateTime AddYears(DateTime time, int years);
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public abstract int GetDayOfMonth(DateTime time);
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public abstract DayOfWeek GetDayOfWeek(DateTime time);
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public abstract int GetDayOfYear(DateTime time);
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public virtual int GetDaysInMonth(int year, int month)
+ {
+ return (GetDaysInMonth(year, month, CurrentEra));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments for the specified era.
+ //
+
+ public abstract int GetDaysInMonth(int year, int month, int era);
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public virtual int GetDaysInYear(int year)
+ {
+ return (GetDaysInYear(year, CurrentEra));
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public abstract int GetDaysInYear(int year, int era);
+
+ // Returns the era for the specified DateTime value.
+
+ public abstract int GetEra(DateTime time);
+
+ /*=================================Eras==========================
+ **Action: Get the list of era values.
+ **Returns: The int array of the era names supported in this calendar.
+ ** null if era is not used.
+ **Arguments: None.
+ **Exceptions: None.
+ ============================================================================*/
+
+
+ public abstract int[] Eras {
+ get;
+ }
+
+
+ // Returns the hour part of the specified DateTime. The returned value is an
+ // integer between 0 and 23.
+ //
+
+ public virtual int GetHour(DateTime time) {
+ return ((int)((time.Ticks / TicksPerHour) % 24));
+ }
+
+ // Returns the millisecond part of the specified DateTime. The returned value
+ // is an integer between 0 and 999.
+ //
+
+ public virtual double GetMilliseconds(DateTime time) {
+ return (double)((time.Ticks / TicksPerMillisecond) % 1000);
+ }
+
+ // Returns the minute part of the specified DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+
+ public virtual int GetMinute(DateTime time) {
+ return ((int)((time.Ticks / TicksPerMinute) % 60));
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public abstract int GetMonth(DateTime time);
+
+ // Returns the number of months in the specified year in the current era.
+
+ public virtual int GetMonthsInYear(int year)
+ {
+ return (GetMonthsInYear(year, CurrentEra));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public abstract int GetMonthsInYear(int year, int era);
+
+ // Returns the second part of the specified DateTime. The returned value is
+ // an integer between 0 and 59.
+ //
+
+ public virtual int GetSecond(DateTime time) {
+ return ((int)((time.Ticks / TicksPerSecond) % 60));
+ }
+
+ /*=================================GetFirstDayWeekOfYear==========================
+ **Action: Get the week of year using the FirstDay rule.
+ **Returns: the week of year.
+ **Arguments:
+ ** time
+ ** firstDayOfWeek the first day of week (0=Sunday, 1=Monday, ... 6=Saturday)
+ **Notes:
+ ** The CalendarWeekRule.FirstDay rule: Week 1 begins on the first day of the year.
+ ** Assume f is the specifed firstDayOfWeek,
+ ** and n is the day of week for January 1 of the specified year.
+ ** Assign offset = n - f;
+ ** Case 1: offset = 0
+ ** E.g.
+ ** f=1
+ ** weekday 0 1 2 3 4 5 6 0 1
+ ** date 1/1
+ ** week# 1 2
+ ** then week of year = (GetDayOfYear(time) - 1) / 7 + 1
+ **
+ ** Case 2: offset < 0
+ ** e.g.
+ ** n=1 f=3
+ ** weekday 0 1 2 3 4 5 6 0
+ ** date 1/1
+ ** week# 1 2
+ ** This means that the first week actually starts 5 days before 1/1.
+ ** So week of year = (GetDayOfYear(time) + (7 + offset) - 1) / 7 + 1
+ ** Case 3: offset > 0
+ ** e.g.
+ ** f=0 n=2
+ ** weekday 0 1 2 3 4 5 6 0 1 2
+ ** date 1/1
+ ** week# 1 2
+ ** This means that the first week actually starts 2 days before 1/1.
+ ** So Week of year = (GetDayOfYear(time) + offset - 1) / 7 + 1
+ ============================================================================*/
+
+ internal int GetFirstDayWeekOfYear(DateTime time, int firstDayOfWeek) {
+ int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ // Calculate the day of week for the first day of the year.
+ // dayOfWeek - (dayOfYear % 7) is the day of week for the first day of this year. Note that
+ // this value can be less than 0. It's fine since we are making it positive again in calculating offset.
+ int dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
+ int offset = (dayForJan1 - firstDayOfWeek + 14) % 7;
+ Contract.Assert(offset >= 0, "Calendar.GetFirstDayWeekOfYear(): offset >= 0");
+ return ((dayOfYear + offset) / 7 + 1);
+ }
+
+ private int GetWeekOfYearFullDays(DateTime time, int firstDayOfWeek, int fullDays) {
+ int dayForJan1;
+ int offset;
+ int day;
+
+ int dayOfYear = GetDayOfYear(time) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ //
+ // Calculate the number of days between the first day of year (1/1) and the first day of the week.
+ // This value will be a positive value from 0 ~ 6. We call this value as "offset".
+ //
+ // If offset is 0, it means that the 1/1 is the start of the first week.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sun Mon Tue Wed Thu Fri Sat
+ // 12/31 1/1 1/2 1/3 1/4 1/5 1/6
+ // +--> First week starts here.
+ //
+ // If offset is 1, it means that the first day of the week is 1 day ahead of 1/1.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sun Mon Tue Wed Thu Fri Sat
+ // 1/1 1/2 1/3 1/4 1/5 1/6 1/7
+ // +--> First week starts here.
+ //
+ // If offset is 2, it means that the first day of the week is 2 days ahead of 1/1.
+ // Assume the first day of the week is Monday, it will look like this:
+ // Sat Sun Mon Tue Wed Thu Fri Sat
+ // 1/1 1/2 1/3 1/4 1/5 1/6 1/7 1/8
+ // +--> First week starts here.
+
+
+
+ // Day of week is 0-based.
+ // Get the day of week for 1/1. This can be derived from the day of week of the target day.
+ // Note that we can get a negative value. It's ok since we are going to make it a positive value when calculating the offset.
+ dayForJan1 = (int)GetDayOfWeek(time) - (dayOfYear % 7);
+
+ // Now, calculate the offset. Subtract the first day of week from the dayForJan1. And make it a positive value.
+ offset = (firstDayOfWeek - dayForJan1 + 14) % 7;
+ if (offset != 0 && offset >= fullDays)
+ {
+ //
+ // If the offset is greater than the value of fullDays, it means that
+ // the first week of the year starts on the week where Jan/1 falls on.
+ //
+ offset -= 7;
+ }
+ //
+ // Calculate the day of year for specified time by taking offset into account.
+ //
+ day = dayOfYear - offset;
+ if (day >= 0) {
+ //
+ // If the day of year value is greater than zero, get the week of year.
+ //
+ return (day/7 + 1);
+ }
+ //
+ // Otherwise, the specified time falls on the week of previous year.
+ // Call this method again by passing the last day of previous year.
+ //
+ // the last day of the previous year may "underflow" to no longer be a valid date time for
+ // this calendar if we just subtract so we need the subclass to provide us with
+ // that information
+ if (time <= MinSupportedDateTime.AddDays(dayOfYear))
+ {
+ return GetWeekOfYearOfMinSupportedDateTime(firstDayOfWeek, fullDays);
+ }
+ return (GetWeekOfYearFullDays(time.AddDays(-(dayOfYear + 1)), firstDayOfWeek, fullDays));
+ }
+
+ private int GetWeekOfYearOfMinSupportedDateTime(int firstDayOfWeek, int minimumDaysInFirstWeek)
+ {
+ int dayOfYear = GetDayOfYear(MinSupportedDateTime) - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ int dayOfWeekOfFirstOfYear = (int)GetDayOfWeek(MinSupportedDateTime) - dayOfYear % 7;
+
+ // Calculate the offset (how many days from the start of the year to the start of the week)
+ int offset = (firstDayOfWeek + 7 - dayOfWeekOfFirstOfYear) % 7;
+ if (offset == 0 || offset >= minimumDaysInFirstWeek)
+ {
+ // First of year falls in the first week of the year
+ return 1;
+ }
+
+ int daysInYearBeforeMinSupportedYear = DaysInYearBeforeMinSupportedYear - 1; // Make the day of year to be 0-based, so that 1/1 is day 0.
+ int dayOfWeekOfFirstOfPreviousYear = dayOfWeekOfFirstOfYear - 1 - (daysInYearBeforeMinSupportedYear % 7);
+
+ // starting from first day of the year, how many days do you have to go forward
+ // before getting to the first day of the week?
+ int daysInInitialPartialWeek = (firstDayOfWeek - dayOfWeekOfFirstOfPreviousYear + 14) % 7;
+ int day = daysInYearBeforeMinSupportedYear - daysInInitialPartialWeek;
+ if (daysInInitialPartialWeek >= minimumDaysInFirstWeek)
+ {
+ // If the offset is greater than the minimum Days in the first week, it means that
+ // First of year is part of the first week of the year even though it is only a partial week
+ // add another week
+ day += 7;
+ }
+
+ return (day / 7 + 1);
+ }
+
+ // it would be nice to make this abstract but we can't since that would break previous implementations
+ protected virtual int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ return 365;
+ }
+ }
+
+
+ // Returns the week of year for the specified DateTime. The returned value is an
+ // integer between 1 and 53.
+ //
+
+ public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ if ((int)firstDayOfWeek < 0 || (int)firstDayOfWeek > 6) {
+ throw new ArgumentOutOfRangeException(
+ "firstDayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+ switch (rule) {
+ case CalendarWeekRule.FirstDay:
+ return (GetFirstDayWeekOfYear(time, (int)firstDayOfWeek));
+ case CalendarWeekRule.FirstFullWeek:
+ return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 7));
+ case CalendarWeekRule.FirstFourDayWeek:
+ return (GetWeekOfYearFullDays(time, (int)firstDayOfWeek, 4));
+ }
+ throw new ArgumentOutOfRangeException(
+ "rule", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
+
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public abstract int GetYear(DateTime time);
+
+ // Checks whether a given day in the current era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public virtual bool IsLeapDay(int year, int month, int day)
+ {
+ return (IsLeapDay(year, month, day, CurrentEra));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public abstract bool IsLeapDay(int year, int month, int day, int era);
+
+ // Checks whether a given month in the current era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public virtual bool IsLeapMonth(int year, int month) {
+ return (IsLeapMonth(year, month, CurrentEra));
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public abstract bool IsLeapMonth(int year, int month, int era);
+
+ // Returns the leap month in a calendar year of the current era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int GetLeapMonth(int year)
+ {
+ return (GetLeapMonth(year, CurrentEra));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int GetLeapMonth(int year, int era)
+ {
+ if (!IsLeapYear(year, era))
+ return 0;
+
+ int monthsCount = GetMonthsInYear(year, era);
+ for (int month=1; month<=monthsCount; month++)
+ {
+ if (IsLeapMonth(year, month, era))
+ return month;
+ }
+
+ return 0;
+ }
+
+ // Checks whether a given year in the current era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public virtual bool IsLeapYear(int year)
+ {
+ return (IsLeapYear(year, CurrentEra));
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public abstract bool IsLeapYear(int year, int era);
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public virtual DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond)
+ {
+ return (ToDateTime(year, month, day, hour, minute, second, millisecond, CurrentEra));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public abstract DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era);
+
+ internal virtual Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) {
+ result = DateTime.MinValue;
+ try {
+ result = ToDateTime(year, month, day, hour, minute, second, millisecond, era);
+ return true;
+ }
+ catch (ArgumentException) {
+ return false;
+ }
+ }
+
+ internal virtual bool IsValidYear(int year, int era) {
+ return (year >= GetYear(MinSupportedDateTime) && year <= GetYear(MaxSupportedDateTime));
+ }
+
+ internal virtual bool IsValidMonth(int year, int month, int era) {
+ return (IsValidYear(year, era) && month >= 1 && month <= GetMonthsInYear(year, era));
+ }
+
+ internal virtual bool IsValidDay(int year, int month, int day, int era)
+ {
+ return (IsValidMonth(year, month, era) && day >= 1 && day <= GetDaysInMonth(year, month, era));
+ }
+
+
+ // Returns and assigns the maximum value to represent a two digit year. This
+ // value is the upper boundary of a 100 year range that allows a two digit year
+ // to be properly translated to a four digit year. For example, if 2029 is the
+ // upper boundary, then a two digit value of 30 should be interpreted as 1930
+ // while a two digit value of 29 should be interpreted as 2029. In this example
+ // , the 100 year range would be from 1930-2029. See ToFourDigitYear().
+
+ public virtual int TwoDigitYearMax
+ {
+ get
+ {
+ return (twoDigitYearMax);
+ }
+
+ set
+ {
+ VerifyWritable();
+ twoDigitYearMax = value;
+ }
+ }
+
+ // Converts the year value to the appropriate century by using the
+ // TwoDigitYearMax property. For example, if the TwoDigitYearMax value is 2029,
+ // then a two digit value of 30 will get converted to 1930 while a two digit
+ // value of 29 will get converted to 2029.
+
+ public virtual int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+ if (year < 100) {
+ return ((TwoDigitYearMax/100 - ( year > TwoDigitYearMax % 100 ? 1 : 0))*100 + year);
+ }
+ // If the year value is above 100, just return the year value. Don't have to do
+ // the TwoDigitYearMax comparison.
+ return (year);
+ }
+
+ // Return the tick count corresponding to the given hour, minute, second.
+ // Will check the if the parameters are valid.
+ internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
+ {
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
+ {
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), 0, MillisPerSecond - 1));
+ }
+ return TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond;
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static int GetSystemTwoDigitYearSetting(int CalID, int defaultYearValue)
+ {
+ // Call nativeGetTwoDigitYearMax
+ int twoDigitYearMax = CalendarData.nativeGetTwoDigitYearMax(CalID);
+ if (twoDigitYearMax < 0)
+ {
+ twoDigitYearMax = defaultYearValue;
+ }
+ return (twoDigitYearMax);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs b/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs
new file mode 100644
index 0000000000..4bf636656f
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CalendarAlgorithmType.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum CalendarAlgorithmType {
+ Unknown = 0, // This is the default value to return in the Calendar base class.
+ SolarCalendar = 1, // Solar-base calendar, such as GregorianCalendar, jaoaneseCalendar, JulianCalendar, etc.
+ // Solar calendars are based on the solar year and seasons.
+ LunarCalendar = 2, // Lunar-based calendar, such as Hijri and UmAlQuraCalendar.
+ // Lunar calendars are based on the path of the moon. The seasons are not accurately represented.
+ LunisolarCalendar = 3 // Lunisolar-based calendar which use leap month rule, such as HebrewCalendar and Asian Lunisolar calendars.
+ // Lunisolar calendars are based on the cycle of the moon, but consider the seasons as a secondary consideration,
+ // so they align with the seasons as well as lunar events.
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CalendarData.cs b/src/mscorlib/src/System/Globalization/CalendarData.cs
new file mode 100644
index 0000000000..8c187f0033
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CalendarData.cs
@@ -0,0 +1,455 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ //
+ // List of calendar data
+ // Note the we cache overrides.
+ // Note that localized names (resource names) aren't available from here.
+ //
+ // NOTE: Calendars depend on the locale name that creates it. Only a few
+ // properties are available without locales using CalendarData.GetCalendar(int)
+
+ // StructLayout is needed here otherwise compiler can re-arrange the fields.
+ // We have to keep this in-sync with the definition in calendardata.h
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CalendarDataBaseObject)
+ // WARNING: The type loader will rearrange class member offsets so the mscorwks!CalendarDataBaseObject
+ // WARNING: must be manually structured to match the true loaded class layout
+ //
+ internal class CalendarData
+ {
+ // Max calendars
+ internal const int MAX_CALENDARS = 23;
+
+ // Identity
+ internal String sNativeName ; // Calendar Name for the locale
+
+ // Formats
+ internal String[] saShortDates ; // Short Data format, default first
+ internal String[] saYearMonths ; // Year/Month Data format, default first
+ internal String[] saLongDates ; // Long Data format, default first
+ internal String sMonthDay ; // Month/Day format
+
+ // Calendar Parts Names
+ internal String[] saEraNames ; // Names of Eras
+ internal String[] saAbbrevEraNames ; // Abbreviated Era Names
+ internal String[] saAbbrevEnglishEraNames ; // Abbreviated Era Names in English
+ internal String[] saDayNames ; // Day Names, null to use locale data, starts on Sunday
+ internal String[] saAbbrevDayNames ; // Abbrev Day Names, null to use locale data, starts on Sunday
+ internal String[] saSuperShortDayNames ; // Super short Day of week names
+ internal String[] saMonthNames ; // Month Names (13)
+ internal String[] saAbbrevMonthNames ; // Abbrev Month Names (13)
+ internal String[] saMonthGenitiveNames ; // Genitive Month Names (13)
+ internal String[] saAbbrevMonthGenitiveNames; // Genitive Abbrev Month Names (13)
+ internal String[] saLeapYearMonthNames ; // Multiple strings for the month names in a leap year.
+
+ // Integers at end to make marshaller happier
+ internal int iTwoDigitYearMax=2029 ; // Max 2 digit year (for Y2K bug data entry)
+ internal int iCurrentEra=0 ; // current era # (usually 1)
+
+ // Use overrides?
+ internal bool bUseUserOverrides ; // True if we want user overrides.
+
+ // Static invariant for the invariant locale
+ internal static CalendarData Invariant;
+
+ // Private constructor
+ private CalendarData() {}
+
+ // Invariant constructor
+ static CalendarData()
+ {
+
+ // Set our default/gregorian US calendar data
+ // Calendar IDs are 1-based, arrays are 0 based.
+ CalendarData invariant = new CalendarData();
+
+ // Set default data for calendar
+ // Note that we don't load resources since this IS NOT supposed to change (by definition)
+ invariant.sNativeName = "Gregorian Calendar"; // Calendar Name
+
+ // Year
+ invariant.iTwoDigitYearMax = 2029; // Max 2 digit year (for Y2K bug data entry)
+ invariant.iCurrentEra = 1; // Current era #
+
+ // Formats
+ invariant.saShortDates = new String[] { "MM/dd/yyyy", "yyyy-MM-dd" }; // short date format
+ invariant.saLongDates = new String[] { "dddd, dd MMMM yyyy"}; // long date format
+ invariant.saYearMonths = new String[] { "yyyy MMMM" }; // year month format
+ invariant.sMonthDay = "MMMM dd"; // Month day pattern
+
+ // Calendar Parts Names
+ invariant.saEraNames = new String[] { "A.D." }; // Era names
+ invariant.saAbbrevEraNames = new String[] { "AD" }; // Abbreviated Era names
+ invariant.saAbbrevEnglishEraNames=new String[] { "AD" }; // Abbreviated era names in English
+ invariant.saDayNames = new String[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };// day names
+ invariant.saAbbrevDayNames = new String[] { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; // abbreviated day names
+ invariant.saSuperShortDayNames = new String[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" }; // The super short day names
+ invariant.saMonthNames = new String[] { "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December", String.Empty}; // month names
+ invariant.saAbbrevMonthNames = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", String.Empty}; // abbreviated month names
+ invariant.saMonthGenitiveNames = invariant.saMonthNames; // Genitive month names (same as month names for invariant)
+ invariant.saAbbrevMonthGenitiveNames=invariant.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
+ invariant.saLeapYearMonthNames = invariant.saMonthNames; // leap year month names are unused in Gregorian English (invariant)
+
+ invariant.bUseUserOverrides = false;
+
+ // Calendar was built, go ahead and assign it...
+ Invariant = invariant;
+ }
+
+
+
+ //
+ // Get a bunch of data for a calendar
+ //
+ internal CalendarData(String localeName, int calendarId, bool bUseUserOverrides)
+ {
+ // Call nativeGetCalendarData to populate the data
+ this.bUseUserOverrides = bUseUserOverrides;
+ if (!nativeGetCalendarData(this, localeName, calendarId))
+ {
+ Contract.Assert(false, "[CalendarData] nativeGetCalendarData call isn't expected to fail for calendar " + calendarId + " locale " +localeName);
+
+ // Something failed, try invariant for missing parts
+ // This is really not good, but we don't want the callers to crash.
+ if (this.sNativeName == null) this.sNativeName = String.Empty; // Calendar Name for the locale.
+
+ // Formats
+ if (this.saShortDates == null) this.saShortDates = Invariant.saShortDates; // Short Data format, default first
+ if (this.saYearMonths == null) this.saYearMonths = Invariant.saYearMonths; // Year/Month Data format, default first
+ if (this.saLongDates == null) this.saLongDates = Invariant.saLongDates; // Long Data format, default first
+ if (this.sMonthDay == null) this.sMonthDay = Invariant.sMonthDay; // Month/Day format
+
+ // Calendar Parts Names
+ if (this.saEraNames == null) this.saEraNames = Invariant.saEraNames; // Names of Eras
+ if (this.saAbbrevEraNames == null) this.saAbbrevEraNames = Invariant.saAbbrevEraNames; // Abbreviated Era Names
+ if (this.saAbbrevEnglishEraNames == null) this.saAbbrevEnglishEraNames = Invariant.saAbbrevEnglishEraNames; // Abbreviated Era Names in English
+ if (this.saDayNames == null) this.saDayNames = Invariant.saDayNames; // Day Names, null to use locale data, starts on Sunday
+ if (this.saAbbrevDayNames == null) this.saAbbrevDayNames = Invariant.saAbbrevDayNames; // Abbrev Day Names, null to use locale data, starts on Sunday
+ if (this.saSuperShortDayNames == null) this.saSuperShortDayNames = Invariant.saSuperShortDayNames; // Super short Day of week names
+ if (this.saMonthNames == null) this.saMonthNames = Invariant.saMonthNames; // Month Names (13)
+ if (this.saAbbrevMonthNames == null) this.saAbbrevMonthNames = Invariant.saAbbrevMonthNames; // Abbrev Month Names (13)
+ // Genitive and Leap names can follow the fallback below
+ }
+
+ // Clean up the escaping of the formats
+ this.saShortDates = CultureData.ReescapeWin32Strings(this.saShortDates);
+ this.saLongDates = CultureData.ReescapeWin32Strings(this.saLongDates);
+ this.saYearMonths = CultureData.ReescapeWin32Strings(this.saYearMonths);
+ this.sMonthDay = CultureData.ReescapeWin32String(this.sMonthDay);
+
+ if ((CalendarId)calendarId == CalendarId.TAIWAN)
+ {
+ if (CultureInfo.IsTaiwanSku)
+ {
+ // We got the month/day names from the OS (same as gregorian), but the native name is wrong
+ this.sNativeName = "\x4e2d\x83ef\x6c11\x570b\x66c6";
+ }
+ else
+ {
+ this.sNativeName = String.Empty;
+ }
+ }
+
+ // Check for null genitive names (in case unmanaged side skips it for non-gregorian calendars, etc)
+ if (this.saMonthGenitiveNames == null || String.IsNullOrEmpty(this.saMonthGenitiveNames[0]))
+ this.saMonthGenitiveNames = this.saMonthNames; // Genitive month names (same as month names for invariant)
+ if (this.saAbbrevMonthGenitiveNames == null || String.IsNullOrEmpty(this.saAbbrevMonthGenitiveNames[0]))
+ this.saAbbrevMonthGenitiveNames = this.saAbbrevMonthNames; // Abbreviated genitive month names (same as abbrev month names for invariant)
+ if (this.saLeapYearMonthNames == null || String.IsNullOrEmpty(this.saLeapYearMonthNames[0]))
+ this.saLeapYearMonthNames = this.saMonthNames;
+
+ InitializeEraNames(localeName, calendarId);
+
+ InitializeAbbreviatedEraNames(localeName, calendarId);
+
+ // Abbreviated English Era Names are only used for the Japanese calendar.
+ if (calendarId == (int)CalendarId.JAPAN)
+ {
+ this.saAbbrevEnglishEraNames = JapaneseCalendar.EnglishEraNames();
+ }
+ else
+ {
+ // For all others just use the an empty string (doesn't matter we'll never ask for it for other calendars)
+ this.saAbbrevEnglishEraNames = new String[] { "" };
+ }
+
+ // Japanese is the only thing with > 1 era. Its current era # is how many ever
+ // eras are in the array. (And the others all have 1 string in the array)
+ this.iCurrentEra = this.saEraNames.Length;
+ }
+
+ private void InitializeEraNames(string localeName, int calendarId)
+ {
+ // Note that the saEraNames only include "A.D." We don't have localized names for other calendars available from windows
+ switch ((CalendarId)calendarId)
+ {
+ // For Localized Gregorian we really expect the data from the OS.
+ case CalendarId.GREGORIAN:
+ // Fallback for CoreCLR < Win7 or culture.dll missing
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ {
+ this.saEraNames = new String[] { "A.D." };
+ }
+ break;
+
+ // The rest of the calendars have constant data, so we'll just use that
+ case CalendarId.GREGORIAN_US:
+ case CalendarId.JULIAN:
+ this.saEraNames = new String[] { "A.D." };
+ break;
+ case CalendarId.HEBREW:
+ this.saEraNames = new String[] { "C.E." };
+ break;
+ case CalendarId.HIJRI:
+ case CalendarId.UMALQURA:
+ if (localeName == "dv-MV")
+ {
+ // Special case for Divehi
+ this.saEraNames = new String[] { "\x0780\x07a8\x0796\x07b0\x0783\x07a9" };
+ }
+ else
+ {
+ this.saEraNames = new String[] { "\x0628\x0639\x062F \x0627\x0644\x0647\x062C\x0631\x0629" };
+ }
+ break;
+ case CalendarId.GREGORIAN_ARABIC:
+ case CalendarId.GREGORIAN_XLIT_ENGLISH:
+ case CalendarId.GREGORIAN_XLIT_FRENCH:
+ // These are all the same:
+ this.saEraNames = new String[] { "\x0645" };
+ break;
+
+ case CalendarId.GREGORIAN_ME_FRENCH:
+ this.saEraNames = new String[] { "ap. J.-C." };
+ break;
+
+ case CalendarId.TAIWAN:
+ if (CultureInfo.IsTaiwanSku)
+ {
+ this.saEraNames = new String[] { "\x4e2d\x83ef\x6c11\x570b" };
+ }
+ else
+ {
+ this.saEraNames = new String[] { String.Empty };
+ }
+ break;
+
+ case CalendarId.KOREA:
+ this.saEraNames = new String[] { "\xb2e8\xae30" };
+ break;
+
+ case CalendarId.THAI:
+ this.saEraNames = new String[] { "\x0e1e\x002e\x0e28\x002e" };
+ break;
+
+ case CalendarId.JAPAN:
+ case CalendarId.JAPANESELUNISOLAR:
+ this.saEraNames = JapaneseCalendar.EraNames();
+ break;
+
+ case CalendarId.PERSIAN:
+ if (this.saEraNames == null || this.saEraNames.Length == 0 || String.IsNullOrEmpty(this.saEraNames[0]))
+ {
+ this.saEraNames = new String[] { "\x0647\x002e\x0634" };
+ }
+ break;
+
+ default:
+ // Most calendars are just "A.D."
+ this.saEraNames = Invariant.saEraNames;
+ break;
+ }
+ }
+
+ private void InitializeAbbreviatedEraNames(string localeName, int calendarId)
+ {
+ // Note that the saAbbrevEraNames only include "AD" We don't have localized names for other calendars available from windows
+ switch ((CalendarId)calendarId)
+ {
+ // For Localized Gregorian we really expect the data from the OS.
+ case CalendarId.GREGORIAN:
+ // Fallback for culture.dll missing
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ {
+ this.saAbbrevEraNames = new String[] { "AD" };
+ }
+ break;
+
+ // The rest of the calendars have constant data, so we'll just use that
+ case CalendarId.GREGORIAN_US:
+ case CalendarId.JULIAN:
+ this.saAbbrevEraNames = new String[] { "AD" };
+ break;
+ case CalendarId.JAPAN:
+ case CalendarId.JAPANESELUNISOLAR:
+ this.saAbbrevEraNames = JapaneseCalendar.AbbrevEraNames();
+ break;
+ case CalendarId.HIJRI:
+ case CalendarId.UMALQURA:
+ if (localeName == "dv-MV")
+ {
+ // Special case for Divehi
+ this.saAbbrevEraNames = new String[] { "\x0780\x002e" };
+ }
+ else
+ {
+ this.saAbbrevEraNames = new String[] { "\x0647\x0640" };
+ }
+ break;
+ case CalendarId.TAIWAN:
+ // Get era name and abbreviate it
+ this.saAbbrevEraNames = new String[1];
+ if (this.saEraNames[0].Length == 4)
+ {
+ this.saAbbrevEraNames[0] = this.saEraNames[0].Substring(2,2);
+ }
+ else
+ {
+ this.saAbbrevEraNames[0] = this.saEraNames[0];
+ }
+ break;
+
+ case CalendarId.PERSIAN:
+ if (this.saAbbrevEraNames == null || this.saAbbrevEraNames.Length == 0 || String.IsNullOrEmpty(this.saAbbrevEraNames[0]))
+ {
+ this.saAbbrevEraNames = this.saEraNames;
+ }
+ break;
+
+ default:
+ // Most calendars just use the full name
+ this.saAbbrevEraNames = this.saEraNames;
+ break;
+ }
+ }
+
+ internal static CalendarData GetCalendarData(int calendarId)
+ {
+ //
+ // Get a calendar.
+ // Unfortunately we depend on the locale in the OS, so we need a locale
+ // no matter what. So just get the appropriate calendar from the
+ // appropriate locale here
+ //
+
+ // Get a culture name
+ String culture = CalendarIdToCultureName(calendarId);
+
+ // Return our calendar
+ return CultureInfo.GetCultureInfo(culture).m_cultureData.GetCalendar(calendarId);
+ }
+
+ //
+ // Helper methods
+ //
+ private static String CalendarIdToCultureName(int calendarId)
+ {
+ // note that this doesn't handle the new calendars (lunisolar, etc)
+ switch (calendarId)
+ {
+ case Calendar.CAL_GREGORIAN_US:
+ return "fa-IR"; // "fa-IR" Iran
+
+ case Calendar.CAL_JAPAN:
+ return "ja-JP"; // "ja-JP" Japan
+
+ case Calendar.CAL_TAIWAN: // zh-TW Taiwan
+ return "zh-TW";
+
+ case Calendar.CAL_KOREA:
+ return "ko-KR"; // "ko-KR" Korea
+
+ case Calendar.CAL_HIJRI:
+ case Calendar.CAL_GREGORIAN_ARABIC:
+ case Calendar.CAL_UMALQURA:
+ return "ar-SA"; // "ar-SA" Saudi Arabia
+
+ case Calendar.CAL_THAI:
+ return "th-TH"; // "th-TH" Thailand
+
+ case Calendar.CAL_HEBREW:
+ return "he-IL"; // "he-IL" Israel
+
+ case Calendar.CAL_GREGORIAN_ME_FRENCH:
+ return "ar-DZ"; // "ar-DZ" Algeria
+
+ case Calendar.CAL_GREGORIAN_XLIT_ENGLISH:
+ case Calendar.CAL_GREGORIAN_XLIT_FRENCH:
+ return "ar-IQ"; // "ar-IQ"; Iraq
+
+ default:
+ // Default to gregorian en-US
+ break;
+ }
+
+ return "en-US";
+ }
+
+ internal void FixupWin7MonthDaySemicolonBug()
+ {
+ int unescapedCharacterIndex = FindUnescapedCharacter(sMonthDay, ';');
+ if (unescapedCharacterIndex > 0)
+ {
+ sMonthDay = sMonthDay.Substring(0, unescapedCharacterIndex);
+ }
+ }
+ private static int FindUnescapedCharacter(string s, char charToFind)
+ {
+ bool inComment = false;
+ int length = s.Length;
+ for (int i = 0; i < length; i++)
+ {
+ char c = s[i];
+
+ switch (c)
+ {
+ case '\'':
+ inComment = !inComment;
+ break;
+ case '\\':
+ i++; // escape sequence -- skip next character
+ break;
+ default:
+ if (!inComment && charToFind == c)
+ {
+ return i;
+ }
+ break;
+ }
+ }
+ return -1;
+ }
+
+
+ // Get native two digit year max
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int nativeGetTwoDigitYearMax(int calID);
+
+ // Call native side to load our calendar data
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool nativeGetCalendarData(CalendarData data, String localeName, int calendar);
+
+ // Call native side to figure out which calendars are allowed
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int nativeGetCalendars(String localeName, bool useUserOverride, [In, Out] int[] calendars);
+
+ }
+ }
+
diff --git a/src/mscorlib/src/System/Globalization/CalendarWeekRule.cs b/src/mscorlib/src/System/Globalization/CalendarWeekRule.cs
new file mode 100644
index 0000000000..578b5672fc
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CalendarWeekRule.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum CalendarWeekRule
+ {
+
+ FirstDay = 0, // Week 1 begins on the first day of the year
+
+ FirstFullWeek = 1, // Week 1 begins on first FirstDayOfWeek not before the first day of the year
+
+ FirstFourDayWeek = 2 // Week 1 begins on first FirstDayOfWeek such that FirstDayOfWeek+3 is not before the first day of the year
+ };
+}
diff --git a/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs
new file mode 100644
index 0000000000..7084511ce9
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CalendricalCalculationsHelper.cs
@@ -0,0 +1,413 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ using System;
+ using System.Diagnostics.Contracts;
+
+ internal class CalendricalCalculationsHelper
+ {
+ const double FullCircleOfArc = 360.0; // 360.0;
+ const int HalfCircleOfArc = 180;
+ const double TwelveHours = 0.5; // half a day
+ const double Noon2000Jan01 = 730120.5;
+ internal const double MeanTropicalYearInDays = 365.242189;
+ const double MeanSpeedOfSun = MeanTropicalYearInDays / FullCircleOfArc;
+ const double LongitudeSpring = 0.0;
+ const double TwoDegreesAfterSpring = 2.0;
+ const int SecondsPerDay = 24 * 60 * 60; // 24 hours * 60 minutes * 60 seconds
+
+ const int DaysInUniformLengthCentury = 36525;
+ const int SecondsPerMinute = 60;
+ const int MinutesPerDegree = 60;
+
+ static long StartOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1));
+ static long StartOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1));
+
+ static double[] Coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 };
+ static double[] Coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 };
+ static double[] Coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 };
+ static double[] Coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 };
+ static double[] LambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 };
+ static double[] AnomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 };
+ static double[] EccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 };
+ static double[] Coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) };
+ static double[] CoefficientsA = new double[] { 124.90, -1934.134, 0.002063 };
+ static double[] CoefficientsB = new double[] { 201.11, 72001.5377, 0.00057 };
+
+ static double RadiansFromDegrees(double degree)
+ {
+ return degree * Math.PI / 180;
+ }
+
+ static double SinOfDegree(double degree)
+ {
+ return Math.Sin(RadiansFromDegrees(degree));
+ }
+
+ static double CosOfDegree(double degree)
+ {
+ return Math.Cos(RadiansFromDegrees(degree));
+ }
+ static double TanOfDegree(double degree)
+ {
+ return Math.Tan(RadiansFromDegrees(degree));
+ }
+
+ public static double Angle(int degrees, int minutes, double seconds)
+ {
+ return ((seconds / SecondsPerMinute + minutes) / MinutesPerDegree) + degrees;
+ }
+
+ static double Obliquity(double julianCenturies)
+ {
+ return PolynomialSum(Coefficients, julianCenturies);
+ }
+
+ internal static long GetNumberOfDays(DateTime date)
+ {
+ return date.Ticks / GregorianCalendar.TicksPerDay;
+ }
+
+ static int GetGregorianYear(double numberOfDays)
+ {
+ return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * GregorianCalendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year;
+ }
+
+ enum CorrectionAlgorithm
+ {
+ Default,
+ Year1988to2019,
+ Year1900to1987,
+ Year1800to1899,
+ Year1700to1799,
+ Year1620to1699
+ }
+
+ struct EphemerisCorrectionAlgorithmMap
+ {
+ public EphemerisCorrectionAlgorithmMap(int year, CorrectionAlgorithm algorithm)
+ {
+ _lowestYear = year;
+ _algorithm = algorithm;
+ }
+
+ internal int _lowestYear;
+ internal CorrectionAlgorithm _algorithm;
+ };
+
+ static EphemerisCorrectionAlgorithmMap[] EphemerisCorrectionTable = new EphemerisCorrectionAlgorithmMap[]
+ {
+ // lowest year that starts algorithm, algorithm to use
+ new EphemerisCorrectionAlgorithmMap(2020, CorrectionAlgorithm.Default),
+ new EphemerisCorrectionAlgorithmMap(1988, CorrectionAlgorithm.Year1988to2019),
+ new EphemerisCorrectionAlgorithmMap(1900, CorrectionAlgorithm.Year1900to1987),
+ new EphemerisCorrectionAlgorithmMap(1800, CorrectionAlgorithm.Year1800to1899),
+ new EphemerisCorrectionAlgorithmMap(1700, CorrectionAlgorithm.Year1700to1799),
+ new EphemerisCorrectionAlgorithmMap(1620, CorrectionAlgorithm.Year1620to1699),
+ new EphemerisCorrectionAlgorithmMap(int.MinValue, CorrectionAlgorithm.Default) // default must be last
+ };
+
+ static double Reminder(double divisor, double dividend)
+ {
+ double whole = Math.Floor(divisor / dividend);
+ return divisor - (dividend * whole);
+ }
+
+ static double NormalizeLongitude(double longitude)
+ {
+ longitude = Reminder(longitude, FullCircleOfArc);
+ if (longitude < 0)
+ {
+ longitude += FullCircleOfArc;
+ }
+ return longitude;
+ }
+
+ static public double AsDayFraction(double longitude)
+ {
+ return longitude / FullCircleOfArc;
+ }
+
+ static double PolynomialSum(double[] coefficients, double indeterminate)
+ {
+ double sum = coefficients[0];
+ double indeterminateRaised = 1;
+ for (int i=1; i<coefficients.Length; i++)
+ {
+ indeterminateRaised *= indeterminate;
+ sum += (coefficients[i] * indeterminateRaised);
+ }
+
+ return sum;
+ }
+
+ static double CenturiesFrom1900(int gregorianYear)
+ {
+ long july1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 7, 1));
+ return (double) (july1stOfYear - StartOf1900Century) / DaysInUniformLengthCentury;
+ }
+
+ // the following formulas defines a polynomial function which gives us the amount that the earth is slowing down for specific year ranges
+ static double DefaultEphemerisCorrection(int gregorianYear)
+ {
+ Contract.Assert(gregorianYear < 1620 || 2020 <= gregorianYear);
+ long january1stOfYear = GetNumberOfDays(new DateTime(gregorianYear, 1, 1));
+ double daysSinceStartOf1810 = january1stOfYear - StartOf1810;
+ double x = TwelveHours + daysSinceStartOf1810;
+ return ((Math.Pow(x, 2) / 41048480) - 15) / SecondsPerDay;
+ }
+
+ static double EphemerisCorrection1988to2019(int gregorianYear)
+ {
+ Contract.Assert(1988 <= gregorianYear && gregorianYear <= 2019);
+ return (double)(gregorianYear - 1933) / SecondsPerDay;
+ }
+
+ static double EphemerisCorrection1900to1987(int gregorianYear)
+ {
+ Contract.Assert(1900 <= gregorianYear && gregorianYear <= 1987);
+ double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
+ return PolynomialSum(Coefficients1900to1987, centuriesFrom1900);
+ }
+
+ static double EphemerisCorrection1800to1899(int gregorianYear)
+ {
+ Contract.Assert(1800 <= gregorianYear && gregorianYear <= 1899);
+ double centuriesFrom1900 = CenturiesFrom1900(gregorianYear);
+ return PolynomialSum(Coefficients1800to1899, centuriesFrom1900);
+ }
+
+ static double EphemerisCorrection1700to1799(int gregorianYear)
+ {
+ Contract.Assert(1700 <= gregorianYear && gregorianYear <= 1799);
+ double yearsSince1700 = gregorianYear - 1700;
+ return PolynomialSum(Coefficients1700to1799, yearsSince1700) / SecondsPerDay;
+ }
+
+ static double EphemerisCorrection1620to1699(int gregorianYear)
+ {
+ Contract.Assert(1620 <= gregorianYear && gregorianYear <= 1699);
+ double yearsSince1600 = gregorianYear - 1600;
+ return PolynomialSum(Coefficients1620to1699, yearsSince1600) / SecondsPerDay;
+ }
+
+ // ephemeris-correction: correction to account for the slowing down of the rotation of the earth
+ static double EphemerisCorrection(double time)
+ {
+ int year = GetGregorianYear(time);
+ foreach (EphemerisCorrectionAlgorithmMap map in EphemerisCorrectionTable)
+ {
+ if (map._lowestYear <= year)
+ {
+ switch (map._algorithm)
+ {
+ case CorrectionAlgorithm.Default: return DefaultEphemerisCorrection(year);
+ case CorrectionAlgorithm.Year1988to2019: return EphemerisCorrection1988to2019(year);
+ case CorrectionAlgorithm.Year1900to1987: return EphemerisCorrection1900to1987(year);
+ case CorrectionAlgorithm.Year1800to1899: return EphemerisCorrection1800to1899(year);
+ case CorrectionAlgorithm.Year1700to1799: return EphemerisCorrection1700to1799(year);
+ case CorrectionAlgorithm.Year1620to1699: return EphemerisCorrection1620to1699(year);
+ }
+
+ break; // break the loop and assert eventually
+ }
+ }
+
+ Contract.Assert(false, "Not expected to come here");
+ return DefaultEphemerisCorrection(year);
+ }
+
+ static public double JulianCenturies(double moment)
+ {
+ double dynamicalMoment = moment + EphemerisCorrection(moment);
+ return (dynamicalMoment - Noon2000Jan01) / DaysInUniformLengthCentury;
+ }
+
+ static bool IsNegative(double value)
+ {
+ return Math.Sign(value) == -1;
+ }
+
+ static double CopySign(double value, double sign)
+ {
+ return (IsNegative(value) == IsNegative(sign)) ? value : -value;
+ }
+
+ // equation-of-time; approximate the difference between apparent solar time and mean solar time
+ // formal definition is EOT = GHA - GMHA
+ // GHA is the Greenwich Hour Angle of the apparent (actual) Sun
+ // GMHA is the Greenwich Mean Hour Angle of the mean (fictitious) Sun
+ // http://www.esrl.noaa.gov/gmd/grad/solcalc/
+ // http://en.wikipedia.org/wiki/Equation_of_time
+ static double EquationOfTime(double time)
+ {
+ double julianCenturies = JulianCenturies(time);
+ double lambda = PolynomialSum(LambdaCoefficients, julianCenturies);
+ double anomaly = PolynomialSum(AnomalyCoefficients, julianCenturies);
+ double eccentricity = PolynomialSum(EccentricityCoefficients, julianCenturies);
+
+ double epsilon = Obliquity(julianCenturies);
+ double tanHalfEpsilon = TanOfDegree(epsilon / 2);
+ double y = tanHalfEpsilon * tanHalfEpsilon;
+
+ double dividend = ((y * SinOfDegree(2 * lambda))
+ - (2 * eccentricity * SinOfDegree(anomaly))
+ + (4 * eccentricity * y * SinOfDegree(anomaly) * CosOfDegree(2 * lambda))
+ - (0.5 * Math.Pow(y, 2) * SinOfDegree(4 * lambda))
+ - (1.25 * Math.Pow(eccentricity, 2) * SinOfDegree(2 * anomaly)));
+ double divisor = 2 * Math.PI;
+ double equation = dividend / divisor;
+
+ // approximation of equation of time is not valid for dates that are many millennia in the past or future
+ // thus limited to a half day
+ return CopySign(Math.Min(Math.Abs(equation), TwelveHours), equation);
+ }
+
+ static double AsLocalTime(double apparentMidday, double longitude)
+ {
+ // slightly inaccurate since equation of time takes mean time not apparent time as its argument, but the difference is negligible
+ double universalTime = apparentMidday - AsDayFraction(longitude);
+ return apparentMidday - EquationOfTime(universalTime);
+ }
+
+ // midday
+ static public double Midday(double date, double longitude)
+ {
+ return AsLocalTime(date+TwelveHours, longitude) - AsDayFraction(longitude);
+ }
+
+ static double InitLongitude(double longitude)
+ {
+ return NormalizeLongitude(longitude + HalfCircleOfArc) - HalfCircleOfArc;
+ }
+
+ // midday-in-tehran
+ static public double MiddayAtPersianObservationSite(double date)
+ {
+ return Midday(date, InitLongitude(52.5)); // 52.5 degrees east - longitude of UTC+3:30 which defines Iranian Standard Time
+ }
+
+ static double PeriodicTerm(double julianCenturies, int x, double y, double z)
+ {
+ return x * SinOfDegree(y + z * julianCenturies);
+ }
+
+ static double SumLongSequenceOfPeriodicTerms(double julianCenturies)
+ {
+ double sum = 0.0;
+ sum += PeriodicTerm(julianCenturies, 403406, 270.54861, 0.9287892);
+ sum += PeriodicTerm(julianCenturies, 195207, 340.19128, 35999.1376958);
+ sum += PeriodicTerm(julianCenturies, 119433, 63.91854, 35999.4089666);
+ sum += PeriodicTerm(julianCenturies, 112392, 331.2622, 35998.7287385);
+ sum += PeriodicTerm(julianCenturies, 3891, 317.843, 71998.20261);
+ sum += PeriodicTerm(julianCenturies, 2819, 86.631, 71998.4403);
+ sum += PeriodicTerm(julianCenturies, 1721, 240.052, 36000.35726);
+ sum += PeriodicTerm(julianCenturies, 660, 310.26, 71997.4812);
+ sum += PeriodicTerm(julianCenturies, 350, 247.23, 32964.4678);
+ sum += PeriodicTerm(julianCenturies, 334, 260.87, -19.441);
+ sum += PeriodicTerm(julianCenturies, 314, 297.82, 445267.1117);
+ sum += PeriodicTerm(julianCenturies, 268, 343.14, 45036.884);
+ sum += PeriodicTerm(julianCenturies, 242, 166.79, 3.1008);
+ sum += PeriodicTerm(julianCenturies, 234, 81.53, 22518.4434);
+ sum += PeriodicTerm(julianCenturies, 158, 3.5, -19.9739);
+ sum += PeriodicTerm(julianCenturies, 132, 132.75, 65928.9345);
+ sum += PeriodicTerm(julianCenturies, 129, 182.95, 9038.0293);
+ sum += PeriodicTerm(julianCenturies, 114, 162.03, 3034.7684);
+ sum += PeriodicTerm(julianCenturies, 99, 29.8, 33718.148);
+ sum += PeriodicTerm(julianCenturies, 93, 266.4, 3034.448);
+ sum += PeriodicTerm(julianCenturies, 86, 249.2, -2280.773);
+ sum += PeriodicTerm(julianCenturies, 78, 157.6, 29929.992);
+ sum += PeriodicTerm(julianCenturies, 72, 257.8, 31556.493);
+ sum += PeriodicTerm(julianCenturies, 68, 185.1, 149.588);
+ sum += PeriodicTerm(julianCenturies, 64, 69.9, 9037.75);
+ sum += PeriodicTerm(julianCenturies, 46, 8.0, 107997.405);
+ sum += PeriodicTerm(julianCenturies, 38, 197.1, -4444.176);
+ sum += PeriodicTerm(julianCenturies, 37, 250.4, 151.771);
+ sum += PeriodicTerm(julianCenturies, 32, 65.3, 67555.316);
+ sum += PeriodicTerm(julianCenturies, 29, 162.7, 31556.08);
+ sum += PeriodicTerm(julianCenturies, 28, 341.5, -4561.54);
+ sum += PeriodicTerm(julianCenturies, 27, 291.6, 107996.706);
+ sum += PeriodicTerm(julianCenturies, 27, 98.5, 1221.655);
+ sum += PeriodicTerm(julianCenturies, 25, 146.7, 62894.167);
+ sum += PeriodicTerm(julianCenturies, 24, 110.0, 31437.369);
+ sum += PeriodicTerm(julianCenturies, 21, 5.2, 14578.298);
+ sum += PeriodicTerm(julianCenturies, 21, 342.6, -31931.757);
+ sum += PeriodicTerm(julianCenturies, 20, 230.9, 34777.243);
+ sum += PeriodicTerm(julianCenturies, 18, 256.1, 1221.999);
+ sum += PeriodicTerm(julianCenturies, 17, 45.3, 62894.511);
+ sum += PeriodicTerm(julianCenturies, 14, 242.9, -4442.039);
+ sum += PeriodicTerm(julianCenturies, 13, 115.2, 107997.909);
+ sum += PeriodicTerm(julianCenturies, 13, 151.8, 119.066);
+ sum += PeriodicTerm(julianCenturies, 13, 285.3, 16859.071);
+ sum += PeriodicTerm(julianCenturies, 12, 53.3, -4.578);
+ sum += PeriodicTerm(julianCenturies, 10, 126.6, 26895.292);
+ sum += PeriodicTerm(julianCenturies, 10, 205.7, -39.127);
+ sum += PeriodicTerm(julianCenturies, 10, 85.9, 12297.536);
+ sum += PeriodicTerm(julianCenturies, 10, 146.1, 90073.778);
+ return sum;
+ }
+
+ static double Aberration(double julianCenturies)
+ {
+ return (0.0000974 * CosOfDegree(177.63 + (35999.01848 * julianCenturies))) - 0.005575;
+ }
+
+ static double Nutation(double julianCenturies)
+ {
+ double a = PolynomialSum(CoefficientsA, julianCenturies);
+ double b = PolynomialSum(CoefficientsB, julianCenturies);
+ return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b));
+ }
+
+ static public double Compute(double time)
+ {
+ double julianCenturies = JulianCenturies(time);
+ double lambda = 282.7771834
+ + (36000.76953744 * julianCenturies)
+ + (0.000005729577951308232 * SumLongSequenceOfPeriodicTerms(julianCenturies));
+
+ double longitude = lambda + Aberration(julianCenturies) + Nutation(julianCenturies);
+ return InitLongitude(longitude);
+ }
+
+ static public double AsSeason(double longitude)
+ {
+ return (longitude < 0) ? (longitude + FullCircleOfArc) : longitude;
+ }
+
+ static double EstimatePrior(double longitude, double time)
+ {
+ double timeSunLastAtLongitude = time - (MeanSpeedOfSun * AsSeason(InitLongitude(Compute(time) - longitude)));
+ double longitudeErrorDelta = InitLongitude(Compute(timeSunLastAtLongitude) - longitude);
+ return Math.Min(time, timeSunLastAtLongitude - (MeanSpeedOfSun * longitudeErrorDelta));
+ }
+
+ // persian-new-year-on-or-before
+ // number of days is the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ internal static long PersianNewYearOnOrBefore(long numberOfDays)
+ {
+ double date = (double) numberOfDays;
+
+ double approx = EstimatePrior(LongitudeSpring, MiddayAtPersianObservationSite(date));
+ long lowerBoundNewYearDay = (long) Math.Floor(approx) - 1;
+ long upperBoundNewYearDay = lowerBoundNewYearDay + 3; // estimate is generally within a day of the actual occurrance (at the limits, the error expands, since the calculations rely on the mean tropical year which changes...)
+ long day = lowerBoundNewYearDay;
+ for (; day != upperBoundNewYearDay; ++day)
+ {
+ double midday = MiddayAtPersianObservationSite((double) day);
+ double l = Compute(midday);
+ if ((LongitudeSpring <= l) && (l <= TwoDegreesAfterSpring))
+ {
+ break;
+ }
+ }
+ Contract.Assert(day != upperBoundNewYearDay);
+
+ return day - 1;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs
new file mode 100644
index 0000000000..63151951f9
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CharUnicodeInfo.cs
@@ -0,0 +1,522 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class implements a set of methods for retrieving
+// character type information. Character type information is
+// independent of culture and region.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+
+ //This class has only static members and therefore doesn't need to be serialized.
+
+ using System;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Reflection;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+
+ public static class CharUnicodeInfo
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //
+ // Native methods to access the Unicode category data tables in charinfo.nlp.
+ //
+ internal const char HIGH_SURROGATE_START = '\ud800';
+ internal const char HIGH_SURROGATE_END = '\udbff';
+ internal const char LOW_SURROGATE_START = '\udc00';
+ internal const char LOW_SURROGATE_END = '\udfff';
+
+ internal const int UNICODE_CATEGORY_OFFSET = 0;
+ internal const int BIDI_CATEGORY_OFFSET = 1;
+
+ static bool s_initialized = InitTable();
+
+ // The native pointer to the 12:4:4 index table of the Unicode cateogry data.
+ [SecurityCritical]
+ unsafe static ushort* s_pCategoryLevel1Index;
+ [SecurityCritical]
+ unsafe static byte* s_pCategoriesValue;
+
+ // The native pointer to the 12:4:4 index table of the Unicode numeric data.
+ // The value of this index table is an index into the real value table stored in s_pNumericValues.
+ [SecurityCritical]
+ unsafe static ushort* s_pNumericLevel1Index;
+
+ // The numeric value table, which is indexed by s_pNumericLevel1Index.
+ // Every item contains the value for numeric value.
+ // unsafe static double* s_pNumericValues;
+ // To get around the IA64 alignment issue. Our double data is aligned in 8-byte boundary, but loader loads the embeded table starting
+ // at 4-byte boundary. This cause a alignment issue since double is 8-byte.
+ [SecurityCritical]
+ unsafe static byte* s_pNumericValues;
+
+ // The digit value table, which is indexed by s_pNumericLevel1Index. It shares the same indice as s_pNumericValues.
+ // Every item contains the value for decimal digit/digit value.
+ [SecurityCritical]
+ unsafe static DigitValues* s_pDigitValues;
+
+ internal const String UNICODE_INFO_FILE_NAME = "charinfo.nlp";
+ // The starting codepoint for Unicode plane 1. Plane 1 contains 0x010000 ~ 0x01ffff.
+ internal const int UNICODE_PLANE01_START = 0x10000;
+
+
+ //
+ // This is the header for the native data table that we load from UNICODE_INFO_FILE_NAME.
+ //
+ // Excplicit layout is used here since a syntax like char[16] can not be used in sequential layout.
+ [StructLayout(LayoutKind.Explicit)]
+ internal unsafe struct UnicodeDataHeader {
+ [FieldOffset(0)]
+ internal char TableName; // WCHAR[16]
+ [FieldOffset(0x20)]
+ internal ushort version; // WORD[4]
+ [FieldOffset(0x28)]
+ internal uint OffsetToCategoriesIndex; // DWORD
+ [FieldOffset(0x2c)]
+ internal uint OffsetToCategoriesValue; // DWORD
+ [FieldOffset(0x30)]
+ internal uint OffsetToNumbericIndex; // DWORD
+ [FieldOffset(0x34)]
+ internal uint OffsetToDigitValue; // DWORD
+ [FieldOffset(0x38)]
+ internal uint OffsetToNumbericValue; // DWORD
+
+ }
+
+ // NOTE: It's important to specify pack size here, since the size of the structure is 2 bytes. Otherwise,
+ // the default pack size will be 4.
+
+ [StructLayout(LayoutKind.Sequential, Pack=2)]
+ internal struct DigitValues {
+ internal sbyte decimalDigit;
+ internal sbyte digit;
+ }
+
+
+ //We need to allocate the underlying table that provides us with the information that we
+ //use. We allocate this once in the class initializer and then we don't need to worry
+ //about it again.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe static bool InitTable() {
+
+ // Go to native side and get pointer to the native table
+ byte * pDataTable = GlobalizationAssembly.GetGlobalizationResourceBytePtr(typeof(CharUnicodeInfo).Assembly, UNICODE_INFO_FILE_NAME);
+
+ UnicodeDataHeader* mainHeader = (UnicodeDataHeader*)pDataTable;
+
+ // Set up the native pointer to different part of the tables.
+ s_pCategoryLevel1Index = (ushort*) (pDataTable + mainHeader->OffsetToCategoriesIndex);
+ s_pCategoriesValue = (byte*) (pDataTable + mainHeader->OffsetToCategoriesValue);
+ s_pNumericLevel1Index = (ushort*) (pDataTable + mainHeader->OffsetToNumbericIndex);
+ s_pNumericValues = (byte*) (pDataTable + mainHeader->OffsetToNumbericValue);
+ s_pDigitValues = (DigitValues*) (pDataTable + mainHeader->OffsetToDigitValue);
+
+ return true;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Convert the BMP character or surrogate pointed by index to a UTF32 value.
+ // This is similar to Char.ConvertToUTF32, but the difference is that
+ // it does not throw exceptions when invalid surrogate characters are passed in.
+ //
+ // WARNING: since it doesn't throw an exception it CAN return a value
+ // in the surrogate range D800-DFFF, which are not legal unicode values.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int InternalConvertToUtf32(String s, int index) {
+ Contract.Assert(s != null, "s != null");
+ Contract.Assert(index >= 0 && index < s.Length, "index < s.Length");
+ if (index < s.Length - 1) {
+ int temp1 = (int)s[index] - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= 0x3ff) {
+ int temp2 = (int)s[index+1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= 0x3ff) {
+ // Convert the surrogate to UTF32 and get the result.
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return ((int)s[index]);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Convert a character or a surrogate pair starting at index of string s
+ // to UTF32 value.
+ //
+ // Parameters:
+ // s The string
+ // index The starting index. It can point to a BMP character or
+ // a surrogate pair.
+ // len The length of the string.
+ // charLength [out] If the index points to a BMP char, charLength
+ // will be 1. If the index points to a surrogate pair,
+ // charLength will be 2.
+ //
+ // WARNING: since it doesn't throw an exception it CAN return a value
+ // in the surrogate range D800-DFFF, which are not legal unicode values.
+ //
+ // Returns:
+ // The UTF32 value
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int InternalConvertToUtf32(String s, int index, out int charLength) {
+ Contract.Assert(s != null, "s != null");
+ Contract.Assert(s.Length > 0, "s.Length > 0");
+ Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
+ charLength = 1;
+ if (index < s.Length - 1) {
+ int temp1 = (int)s[index] - HIGH_SURROGATE_START;
+ if (temp1 >= 0 && temp1 <= 0x3ff) {
+ int temp2 = (int)s[index+1] - LOW_SURROGATE_START;
+ if (temp2 >= 0 && temp2 <= 0x3ff) {
+ // Convert the surrogate to UTF32 and get the result.
+ charLength++;
+ return ((temp1 * 0x400) + temp2 + UNICODE_PLANE01_START);
+ }
+ }
+ }
+ return ((int)s[index]);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsWhiteSpace
+ //
+ // Determines if the given character is a white space character.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static bool IsWhiteSpace(String s, int index)
+ {
+ Contract.Assert(s != null, "s!=null");
+ Contract.Assert(index >= 0 && index < s.Length, "index >= 0 && index < s.Length");
+
+ UnicodeCategory uc = GetUnicodeCategory(s, index);
+ // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator".
+ // And U+2029 is th eonly character which is under the category "ParagraphSeparator".
+ switch (uc) {
+ case (UnicodeCategory.SpaceSeparator):
+ case (UnicodeCategory.LineSeparator):
+ case (UnicodeCategory.ParagraphSeparator):
+ return (true);
+ }
+ return (false);
+ }
+
+
+ internal static bool IsWhiteSpace(char c)
+ {
+ UnicodeCategory uc = GetUnicodeCategory(c);
+ // In Unicode 3.0, U+2028 is the only character which is under the category "LineSeparator".
+ // And U+2029 is th eonly character which is under the category "ParagraphSeparator".
+ switch (uc) {
+ case (UnicodeCategory.SpaceSeparator):
+ case (UnicodeCategory.LineSeparator):
+ case (UnicodeCategory.ParagraphSeparator):
+ return (true);
+ }
+
+ return (false);
+ }
+
+ //
+ // This is called by the public char and string, index versions
+ //
+ // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static double InternalGetNumericValue(int ch) {
+ Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
+ // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
+ ushort index = s_pNumericLevel1Index[ch >> 8];
+ // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
+ // The offset is referred to an float item in m_pNumericFloatData.
+ // Note that & has the lower precedence than addition, so don't forget the parathesis.
+ index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)];
+ byte* pBytePtr = (byte*)&(s_pNumericLevel1Index[index]);
+ // Get the result from the 0 -3 bit of ch.
+#if BIT64
+ // To get around the IA64 alignment issue. Our double data is aligned in 8-byte boundary, but loader loads the embeded table starting
+ // at 4-byte boundary. This cause a alignment issue since double is 8-byte.
+ byte* pSourcePtr = &(s_pNumericValues[pBytePtr[(ch & 0x000f)] * sizeof(double)]);
+ if (((long)pSourcePtr % 8) != 0) {
+ // We are not aligned in 8-byte boundary. Do a copy.
+ double ret;
+ byte* retPtr = (byte*)&ret;
+ Buffer.Memcpy(retPtr, pSourcePtr, sizeof(double));
+ return (ret);
+ }
+ return (((double*)s_pNumericValues)[pBytePtr[(ch & 0x000f)]]);
+#else
+ return (((double*)s_pNumericValues)[pBytePtr[(ch & 0x000f)]]);
+#endif
+ }
+
+ //
+ // This is called by the public char and string, index versions
+ //
+ // Note that for ch in the range D800-DFFF we just treat it as any other non-numeric character
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static DigitValues* InternalGetDigitValues(int ch) {
+ Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
+ // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
+ ushort index = s_pNumericLevel1Index[ch >> 8];
+ // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
+ // The offset is referred to an float item in m_pNumericFloatData.
+ // Note that & has the lower precedence than addition, so don't forget the parathesis.
+ index = s_pNumericLevel1Index[index + ((ch >> 4) & 0x000f)];
+ byte* pBytePtr = (byte*)&(s_pNumericLevel1Index[index]);
+ // Get the result from the 0 -3 bit of ch.
+ return &(s_pDigitValues[pBytePtr[(ch & 0x000f)]]);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static sbyte InternalGetDecimalDigitValue(int ch) {
+ return (InternalGetDigitValues(ch)->decimalDigit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static sbyte InternalGetDigitValue(int ch) {
+ return (InternalGetDigitValues(ch)->digit);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Returns the numeric value associated with the character c. If the character is a fraction,
+ // the return value will not be an integer. If the character does not have a numeric value, the return value is -1.
+ //
+ //Returns:
+ // the numeric value for the specified Unicode character. If the character does not have a numeric value, the return value is -1.
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // ArgumentNullException
+ // ArgumentOutOfRangeException
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static double GetNumericValue(char ch) {
+ return (InternalGetNumericValue(ch));
+ }
+
+
+ public static double GetNumericValue(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+ return (InternalGetNumericValue(InternalConvertToUtf32(s, index)));
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Returns the decimal digit value associated with the character c.
+ //
+ // The value should be from 0 ~ 9.
+ // If the character does not have a numeric value, the return value is -1.
+ // From Unicode.org: Decimal Digits. Digits that can be used to form decimal-radix numbers.
+ //Returns:
+ // the decimal digit value for the specified Unicode character. If the character does not have a decimal digit value, the return value is -1.
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // ArgumentNullException
+ // ArgumentOutOfRangeException
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static int GetDecimalDigitValue(char ch) {
+ return (InternalGetDecimalDigitValue(ch));
+ }
+
+
+ public static int GetDecimalDigitValue(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ return (InternalGetDecimalDigitValue(InternalConvertToUtf32(s, index)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Action: Returns the digit value associated with the character c.
+ // If the character does not have a numeric value, the return value is -1.
+ // From Unicode.org: If the character represents a digit, not necessarily a decimal digit,
+ // the value is here. This covers digits which do not form decimal radix forms, such as the compatibility superscript digits.
+ //
+ // An example is: U+2460 IRCLED DIGIT ONE. This character has digit value 1, but does not have associcated decimal digit value.
+ //
+ //Returns:
+ // the digit value for the specified Unicode character. If the character does not have a digit value, the return value is -1.
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // ArgumentNullException
+ // ArgumentOutOfRangeException
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static int GetDigitValue(char ch) {
+ return (InternalGetDigitValue(ch));
+ }
+
+
+ public static int GetDigitValue(String s, int index) {
+ if (s == null) {
+ throw new ArgumentNullException("s");
+ }
+ if (index < 0 || index >= s.Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+ return (InternalGetDigitValue(InternalConvertToUtf32(s, index)));
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(char ch)
+ {
+ return (InternalGetUnicodeCategory(ch)) ;
+ }
+
+ public static UnicodeCategory GetUnicodeCategory(String s, int index)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return InternalGetUnicodeCategory(s, index);
+ }
+
+ internal unsafe static UnicodeCategory InternalGetUnicodeCategory(int ch) {
+ return ((UnicodeCategory)InternalGetCategoryValue(ch, UNICODE_CATEGORY_OFFSET));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Action: Returns the Unicode Category property for the character c.
+ //Returns:
+ // an value in UnicodeCategory enum
+ //Arguments:
+ // ch a Unicode character
+ //Exceptions:
+ // None
+ //
+ //Note that this API will return values for D800-DF00 surrogate halves.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static byte InternalGetCategoryValue(int ch, int offset) {
+ Contract.Assert(ch >= 0 && ch <= 0x10ffff, "ch is not in valid Unicode range.");
+ // Get the level 2 item from the highest 12 bit (8 - 19) of ch.
+ ushort index = s_pCategoryLevel1Index[ch >> 8];
+ // Get the level 2 WORD offset from the 4 - 7 bit of ch. This provides the base offset of the level 3 table.
+ // Note that & has the lower precedence than addition, so don't forget the parathesis.
+ index = s_pCategoryLevel1Index[index + ((ch >> 4) & 0x000f)];
+ byte* pBytePtr = (byte*)&(s_pCategoryLevel1Index[index]);
+ // Get the result from the 0 -3 bit of ch.
+ byte valueIndex = pBytePtr[(ch & 0x000f)];
+ byte uc = s_pCategoriesValue[valueIndex * 2 + offset];
+ //
+ // Make sure that OtherNotAssigned is the last category in UnicodeCategory.
+ // If that changes, change the following assertion as well.
+ //
+ //Contract.Assert(uc >= 0 && uc <= UnicodeCategory.OtherNotAssigned, "Table returns incorrect Unicode category");
+ return (uc);
+ }
+
+// internal static BidiCategory GetBidiCategory(char ch) {
+// return ((BidiCategory)InternalGetCategoryValue(c, BIDI_CATEGORY_OFFSET));
+// }
+
+ internal static BidiCategory GetBidiCategory(String s, int index) {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ if (((uint)index)>=((uint)s.Length)) {
+ throw new ArgumentOutOfRangeException("index");
+ }
+ Contract.EndContractBlock();
+ return ((BidiCategory)InternalGetCategoryValue(InternalConvertToUtf32(s, index), BIDI_CATEGORY_OFFSET));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ //Action: Returns the Unicode Category property for the character c.
+ //Returns:
+ // an value in UnicodeCategory enum
+ //Arguments:
+ // value a Unicode String
+ // index Index for the specified string.
+ //Exceptions:
+ // None
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static UnicodeCategory InternalGetUnicodeCategory(String value, int index) {
+ Contract.Assert(value != null, "value can not be null");
+ Contract.Assert(index < value.Length, "index < value.Length");
+
+ return (InternalGetUnicodeCategory(InternalConvertToUtf32(value, index)));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the Unicode category of the character starting at index. If the character is in BMP, charLength will return 1.
+ // If the character is a valid surrogate pair, charLength will return 2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static UnicodeCategory InternalGetUnicodeCategory(String str, int index, out int charLength) {
+ Contract.Assert(str != null, "str can not be null");
+ Contract.Assert(str.Length > 0, "str.Length > 0");;
+ Contract.Assert(index >= 0 && index < str.Length, "index >= 0 && index < str.Length");
+
+ return (InternalGetUnicodeCategory(InternalConvertToUtf32(str, index, out charLength)));
+ }
+
+ internal static bool IsCombiningCategory(UnicodeCategory uc) {
+ Contract.Assert(uc >= 0, "uc >= 0");
+ return (
+ uc == UnicodeCategory.NonSpacingMark ||
+ uc == UnicodeCategory.SpacingCombiningMark ||
+ uc == UnicodeCategory.EnclosingMark
+ );
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs
new file mode 100644
index 0000000000..a5cf37f712
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/ChineseLunisolarCalendar.cs
@@ -0,0 +1,401 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about ChineseLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1901/02/19 2101/01/28
+ ** ChineseLunisolar 1901/01/01 2100/12/29
+ */
+
+ [Serializable]
+ public class ChineseLunisolarCalendar : EastAsianLunisolarCalendar {
+
+
+ //
+ // The era value for the current era.
+ //
+
+ public const int ChineseEra = 1;
+ //internal static Calendar m_defaultInstance;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1901;
+ internal const int MAX_LUNISOLAR_YEAR = 2100;
+
+ internal const int MIN_GREGORIAN_YEAR = 1901;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 19;
+
+ internal const int MAX_GREGORIAN_YEAR = 2101;
+ internal const int MAX_GREGORIAN_MONTH = 1;
+ internal const int MAX_GREGORIAN_DAY = 28;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1900: 1-29 2-30 3-29 4-29 5-30 6-29 7-30 8-30 Leap8-29 9-30 10-30 11-29 12-30 from Calendrical Tabulations
+ return 384;
+ }
+ }
+
+
+ static readonly int [,] yinfo =
+ {
+ /*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
+2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+2051 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+2052 */{ 8 , 2 , 1 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+2053 */{ 0 , 2 , 19 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+2054 */{ 0 , 2 , 8 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+2055 */{ 6 , 1 , 28 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+2056 */{ 0 , 2 , 15 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+2057 */{ 0 , 2 , 4 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
+2058 */{ 4 , 1 , 24 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+2059 */{ 0 , 2 , 12 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
+2060 */{ 0 , 2 , 2 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2061 */{ 3 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+2062 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2063 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2064 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2065 */{ 0 , 2 , 5 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2066 */{ 5 , 1 , 26 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2067 */{ 0 , 2 , 14 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2068 */{ 0 , 2 , 3 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+2069 */{ 4 , 1 , 23 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+2070 */{ 0 , 2 , 11 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
+2071 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+2072 */{ 0 , 2 , 19 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2073 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2074 */{ 6 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2075 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2076 */{ 0 , 2 , 5 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+2077 */{ 4 , 1 , 24 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+2078 */{ 0 , 2 , 12 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2079 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2080 */{ 3 , 1 , 22 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+2081 */{ 0 , 2 , 9 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+2082 */{ 7 , 1 , 29 , 29336 },/* 29 30 30 30 29 29 30 29 30 29 29 30 30 384
+2083 */{ 0 , 2 , 17 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2084 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2085 */{ 5 , 1 , 26 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2086 */{ 0 , 2 , 14 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2087 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2088 */{ 4 , 1 , 24 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+2089 */{ 0 , 2 , 10 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2090 */{ 8 , 1 , 30 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2091 */{ 0 , 2 , 18 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2092 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+2093 */{ 6 , 1 , 27 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2094 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2095 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2096 */{ 4 , 1 , 25 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+2097 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2098 */{ 0 , 2 , 1 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
+2099 */{ 2 , 1 , 21 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+2100 */{ 0 , 2 , 9 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+ */};
+
+
+ internal override int MinCalendarYear {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo {
+ get
+ {
+ return (null);
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index) {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR ));
+ }
+ Contract.EndContractBlock();
+
+ return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time) {
+ return year;
+ }
+
+ internal override int GetGregorianYear(int year, int era) {
+ if (era != CurrentEra && era != ChineseEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return year;
+ }
+
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of ChineseLunisolarCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ /*
+ internal static Calendar GetDefaultInstance()
+ {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new ChineseLunisolarCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+ // Construct an instance of ChineseLunisolar calendar.
+
+ public ChineseLunisolarCalendar() {
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetEra(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return (ChineseEra);
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_CHINESELUNISOLAR);
+ }
+ }
+
+ internal override int BaseCalendarID {
+ get {
+ //Use CAL_GREGORIAN just to get CurrentEraValue as 1 since we do not have data under the ID CAL_ChineseLunisolar yet
+ return (CAL_GREGORIAN);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int[] Eras {
+ get {
+ return (new int[] {ChineseEra});
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CompareInfo.cs b/src/mscorlib/src/System/Globalization/CompareInfo.cs
new file mode 100644
index 0000000000..0b14f05264
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CompareInfo.cs
@@ -0,0 +1,1359 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+// Purpose: This class implements a set of methods for comparing
+// strings.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+
+ //
+ // We pass all of the sorting calls to the native side, preferrably to the OS to do
+ // the actual work.
+ //
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Threading;
+ using System.Security.Permissions;
+ using Microsoft.Win32;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ //
+ // Options can be used during string comparison.
+ //
+ // Native implementation (COMNlsInfo.cpp & SortingTable.cpp) relies on the values of these,
+ // If you change the values below, be sure to change the values in native part as well.
+ //
+
+
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CompareOptions
+ {
+ None = 0x00000000,
+ IgnoreCase = 0x00000001,
+ IgnoreNonSpace = 0x00000002,
+ IgnoreSymbols = 0x00000004,
+ IgnoreKanaType = 0x00000008, // ignore kanatype
+ IgnoreWidth = 0x00000010, // ignore width
+ OrdinalIgnoreCase = 0x10000000, // This flag can not be used with other flags.
+ StringSort = 0x20000000, // use string sort method
+ Ordinal = 0x40000000, // This flag can not be used with other flags.
+
+ // StopOnNull = 0x10000000,
+
+ // StopOnNull is defined in SortingTable.h, but we didn't enable this option here.
+ // Do not use this value for other flags accidentally.
+ }
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class CompareInfo : IDeserializationCallback
+ {
+ // Mask used to check if IndexOf()/LastIndexOf()/IsPrefix()/IsPostfix() has the right flags.
+ private const CompareOptions ValidIndexMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
+
+ // Mask used to check if Compare() has the right flags.
+ private const CompareOptions ValidCompareMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType | CompareOptions.StringSort);
+
+ // Mask used to check if GetHashCodeOfString() has the right flags.
+ private const CompareOptions ValidHashCodeOfStringMaskOffFlags =
+ ~(CompareOptions.IgnoreCase | CompareOptions.IgnoreSymbols | CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType);
+
+ //
+ // CompareInfos have an interesting identity. They are attached to the locale that created them,
+ // ie: en-US would have an en-US sort. For haw-US (custom), then we serialize it as haw-US.
+ // The interesting part is that since haw-US doesn't have its own sort, it has to point at another
+ // locale, which is what SCOMPAREINFO does.
+
+ [OptionalField(VersionAdded = 2)]
+ private String m_name; // The name used to construct this CompareInfo
+
+ [NonSerialized]
+ private String m_sortName; // The name that defines our behavior
+
+ [NonSerialized]
+ private IntPtr m_dataHandle;
+
+ [NonSerialized]
+ private IntPtr m_handleOrigin;
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CompareInfo Constructor
+ //
+ //
+ ////////////////////////////////////////////////////////////////////////
+ // Constructs an instance that most closely corresponds to the NLS locale
+ // identifier.
+ internal CompareInfo(CultureInfo culture)
+ {
+ this.m_name = culture.m_name;
+ this.m_sortName = culture.SortName;
+
+ IntPtr handleOrigin;
+ this.m_dataHandle = InternalInitSortHandle(m_sortName, out handleOrigin);
+ this.m_handleOrigin = handleOrigin;
+ }
+
+ /*=================================GetCompareInfo==========================
+ **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture.
+ ** Warning: The assembly versioning mechanism is dead!
+ **Returns: The CompareInfo for the specified culture.
+ **Arguments:
+ ** culture the ID of the culture
+ ** assembly the assembly which contains the sorting table.
+ **Exceptions:
+ ** ArugmentNullException when the assembly is null
+ ** ArgumentException if culture is invalid.
+ ============================================================================*/
+#if FEATURE_USE_LCID
+ // Assembly constructor should be deprecated, we don't act on the assembly information any more
+ public static CompareInfo GetCompareInfo(int culture, Assembly assembly){
+ // Parameter checking.
+ if (assembly == null) {
+ throw new ArgumentNullException("assembly");
+ }
+ if (assembly!=typeof(Object).Module.Assembly) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib"));
+ }
+ Contract.EndContractBlock();
+
+ return GetCompareInfo(culture);
+ }
+#endif
+
+
+ /*=================================GetCompareInfo==========================
+ **Action: Get the CompareInfo constructed from the data table in the specified assembly for the specified culture.
+ ** The purpose of this method is to provide version for CompareInfo tables.
+ **Returns: The CompareInfo for the specified culture.
+ **Arguments:
+ ** name the name of the culture
+ ** assembly the assembly which contains the sorting table.
+ **Exceptions:
+ ** ArugmentNullException when the assembly is null
+ ** ArgumentException if name is invalid.
+ ============================================================================*/
+ // Assembly constructor should be deprecated, we don't act on the assembly information any more
+ public static CompareInfo GetCompareInfo(String name, Assembly assembly){
+ if (name == null || assembly == null) {
+ throw new ArgumentNullException(name == null ? "name" : "assembly");
+ }
+ Contract.EndContractBlock();
+
+ if (assembly!=typeof(Object).Module.Assembly) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OnlyMscorlib"));
+ }
+
+ return GetCompareInfo(name);
+ }
+
+ /*=================================GetCompareInfo==========================
+ **Action: Get the CompareInfo for the specified culture.
+ ** This method is provided for ease of integration with NLS-based software.
+ **Returns: The CompareInfo for the specified culture.
+ **Arguments:
+ ** culture the ID of the culture.
+ **Exceptions:
+ ** ArgumentException if culture is invalid.
+ ============================================================================*/
+
+#if FEATURE_USE_LCID
+ // People really shouldn't be calling LCID versions, no custom support
+ public static CompareInfo GetCompareInfo(int culture)
+ {
+ if (CultureData.IsCustomCultureId(culture))
+ {
+ // Customized culture cannot be created by the LCID.
+ throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", "culture"));
+ }
+
+ return CultureInfo.GetCultureInfo(culture).CompareInfo;
+ }
+#endif
+
+ /*=================================GetCompareInfo==========================
+ **Action: Get the CompareInfo for the specified culture.
+ **Returns: The CompareInfo for the specified culture.
+ **Arguments:
+ ** name the name of the culture.
+ **Exceptions:
+ ** ArgumentException if name is invalid.
+ ============================================================================*/
+
+ public static CompareInfo GetCompareInfo(String name)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+ Contract.EndContractBlock();
+
+ return CultureInfo.GetCultureInfo(name).CompareInfo;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static bool IsSortable(char ch) {
+ return(IsSortable(ch.ToString()));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static bool IsSortable(String text) {
+ if (text == null) {
+ // A null param is invalid here.
+ throw new ArgumentNullException("text");
+ }
+
+ if (0 == text.Length) {
+ // A zero length string is not invalid, but it is also not sortable.
+ return(false);
+ }
+
+ CompareInfo c = CultureInfo.InvariantCulture.CompareInfo;
+
+ return (InternalIsSortable(c.m_dataHandle, c.m_handleOrigin, c.m_sortName, text, text.Length));
+ }
+
+
+#region Serialization
+ // the following fields are defined to keep the compatibility with Whidbey.
+ // don't change/remove the names/types of these fields.
+#if FEATURE_USE_LCID
+ [OptionalField(VersionAdded = 1)]
+ private int win32LCID; // mapped sort culture id of this instance
+ private int culture; // the culture ID used to create this instance.
+#endif
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ this.m_name = null;
+ }
+
+ private void OnDeserialized()
+ {
+ CultureInfo ci;
+ // If we didn't have a name, use the LCID
+ if (this.m_name == null)
+ {
+#if FEATURE_USE_LCID
+ // From whidbey, didn't have a name
+ ci = CultureInfo.GetCultureInfo(this.culture);
+ this.m_name = ci.m_name;
+ this.m_sortName = ci.SortName;
+#endif
+ }
+ else
+ {
+ ci = CultureInfo.GetCultureInfo(m_name);
+ this.m_sortName = ci.SortName;
+ }
+
+ IntPtr handleOrigin;
+ this.m_dataHandle = InternalInitSortHandle(m_sortName, out handleOrigin);
+ this.m_handleOrigin = handleOrigin;
+
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserialized();
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+#if FEATURE_USE_LCID
+ // This is merely for serialization compatibility with Whidbey/Orcas, it can go away when we don't want that compat any more.
+ culture = CultureInfo.GetCultureInfo(this.Name).LCID; // This is the lcid of the constructing culture (still have to dereference to get target sort)
+ Contract.Assert(m_name != null, "CompareInfo.OnSerializing - expected m_name to be set already");
+#endif
+ }
+
+ void IDeserializationCallback.OnDeserialization(Object sender)
+ {
+ OnDeserialized();
+ }
+
+#endregion Serialization
+
+
+ ///////////////////////////----- Name -----/////////////////////////////////
+ //
+ // Returns the name of the culture (well actually, of the sort).
+ // Very important for providing a non-LCID way of identifying
+ // what the sort is.
+ //
+ // Note that this name isn't dereferenced in case the CompareInfo is a different locale
+ // which is consistent with the behaviors of earlier versions. (so if you ask for a sort
+ // and the locale's changed behavior, then you'll get changed behavior, which is like
+ // what happens for a version update)
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String Name
+ {
+ get
+ {
+ Contract.Assert(m_name != null, "CompareInfo.Name Expected m_name to be set");
+ if (m_name == "zh-CHT" || m_name == "zh-CHS")
+ {
+ return m_name;
+ }
+
+ return (m_sortName);
+ }
+ }
+
+ // These flags are used in the native Win32. so we need to map the managed options to those flags
+ private const int LINGUISTIC_IGNORECASE = 0x00000010; // linguistically appropriate 'ignore case'
+ private const int NORM_IGNORECASE = 0x00000001; // Ignores case. (use LINGUISTIC_IGNORECASE instead)
+ private const int NORM_IGNOREKANATYPE = 0x00010000; // Does not differentiate between Hiragana and Katakana characters. Corresponding Hiragana and Katakana will compare as equal.
+ private const int LINGUISTIC_IGNOREDIACRITIC = 0x00000020; // linguistically appropriate 'ignore nonspace'
+ private const int NORM_IGNORENONSPACE = 0x00000002; // Ignores nonspacing. This flag also removes Japanese accent characters. (use LINGUISTIC_IGNOREDIACRITIC instead)
+ private const int NORM_IGNORESYMBOLS = 0x00000004; // Ignores symbols.
+ private const int NORM_IGNOREWIDTH = 0x00020000; // Does not differentiate between a single-byte character and the same character as a double-byte character.
+ private const int SORT_STRINGSORT = 0x00001000; // Treats punctuation the same as symbols.
+ private const int COMPARE_OPTIONS_ORDINAL = 0x40000000; // Ordinal (handled by Comnlsinfo)
+ internal const int NORM_LINGUISTIC_CASING = 0x08000000; // use linguistic rules for casing
+
+
+ private const int RESERVED_FIND_ASCII_STRING = 0x20000000; // This flag used only to tell the sorting DLL can assume the string characters are in ASCII.
+
+ [Pure]
+ internal static int GetNativeCompareFlags(CompareOptions options)
+ {
+ // some NLS VM functions can handle COMPARE_OPTIONS_ORDINAL
+ // in which case options should be simply cast to int instead of using this function
+ // Does not look like the best approach to me but for now I am going to leave it as it is
+ Contract.Assert(options != CompareOptions.OrdinalIgnoreCase, "[CompareInfo.GetNativeCompareFlags]CompareOptions.OrdinalIgnoreCase should be handled separately");
+
+ // Use "linguistic casing" by default (load the culture's casing exception tables)
+ int nativeCompareFlags = NORM_LINGUISTIC_CASING;
+
+ if ((options & CompareOptions.IgnoreCase) != 0) { nativeCompareFlags |= NORM_IGNORECASE; }
+ if ((options & CompareOptions.IgnoreKanaType) != 0) { nativeCompareFlags |= NORM_IGNOREKANATYPE; }
+ if ((options & CompareOptions.IgnoreNonSpace) != 0) { nativeCompareFlags |= NORM_IGNORENONSPACE; }
+ if ((options & CompareOptions.IgnoreSymbols) != 0) { nativeCompareFlags |= NORM_IGNORESYMBOLS; }
+ if ((options & CompareOptions.IgnoreWidth) != 0) { nativeCompareFlags |= NORM_IGNOREWIDTH; }
+ if ((options & CompareOptions.StringSort) != 0) { nativeCompareFlags |= SORT_STRINGSORT; }
+
+ // Suffix & Prefix shouldn't use this, make sure to turn off the NORM_LINGUISTIC_CASING flag
+ if (options == CompareOptions.Ordinal) { nativeCompareFlags = COMPARE_OPTIONS_ORDINAL; }
+
+ Contract.Assert(((options & ~(CompareOptions.IgnoreCase |
+ CompareOptions.IgnoreKanaType |
+ CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreSymbols |
+ CompareOptions.IgnoreWidth |
+ CompareOptions.StringSort)) == 0) ||
+ (options == CompareOptions.Ordinal), "[CompareInfo.GetNativeCompareFlags]Expected all flags to be handled");
+
+ Contract.Assert((nativeCompareFlags & RESERVED_FIND_ASCII_STRING) == 0, "[CompareInfo.GetNativeCompareFlags] RESERVED_FIND_ASCII_STRING shouldn't be set here");
+
+ return nativeCompareFlags;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Compare
+ //
+ // Compares the two strings with the given options. Returns 0 if the
+ // two strings are equal, a number less than 0 if string1 is less
+ // than string2, and a number greater than 0 if string1 is greater
+ // than string2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public virtual int Compare(String string1, String string2)
+ {
+ return (Compare(string1, string2, CompareOptions.None));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int Compare(String string1, String string2, CompareOptions options){
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return String.Compare(string1, string2, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // Verify the options before we do any real comparison.
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ if (options != CompareOptions.Ordinal)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"), "options");
+ }
+ return String.CompareOrdinal(string1, string2);
+ }
+
+ if ((options & ValidCompareMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+
+ //Our paradigm is that null sorts less than any other string and
+ //that two nulls sort as equal.
+ if (string1 == null) {
+ if (string2 == null) {
+ return (0); // Equal
+ }
+ return (-1); // null < non-null
+ }
+ if (string2 == null) {
+ return (1); // non-null > null
+ }
+
+ return InternalCompareString(m_dataHandle, m_handleOrigin, m_sortName, string1, 0, string1.Length, string2, 0, string2.Length, GetNativeCompareFlags(options));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Compare
+ //
+ // Compares the specified regions of the two strings with the given
+ // options.
+ // Returns 0 if the two strings are equal, a number less than 0 if
+ // string1 is less than string2, and a number greater than 0 if
+ // string1 is greater than string2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2)
+ {
+ return Compare(string1, offset1, length1, string2, offset2, length2, 0);
+ }
+
+
+ public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2, CompareOptions options)
+ {
+ return Compare(string1, offset1, string1 == null ? 0 : string1.Length-offset1,
+ string2, offset2, string2 == null ? 0 : string2.Length-offset2, options);
+ }
+
+
+ public unsafe virtual int Compare(String string1, int offset1, String string2, int offset2)
+ {
+ return Compare(string1, offset1, string2, offset2, 0);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int Compare(String string1, int offset1, int length1, String string2, int offset2, int length2, CompareOptions options)
+ {
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ int result = String.Compare(string1, offset1, string2, offset2, length1<length2 ? length1 : length2, StringComparison.OrdinalIgnoreCase);
+ if ((length1 != length2) && result == 0)
+ return (length1 > length2? 1: -1);
+ return (result);
+ }
+
+ // Verify inputs
+ if (length1 < 0 || length2 < 0)
+ {
+ throw new ArgumentOutOfRangeException((length1 < 0) ? "length1" : "length2", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ if (offset1 < 0 || offset2 < 0)
+ {
+ throw new ArgumentOutOfRangeException((offset1 < 0) ? "offset1" : "offset2", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ if (offset1 > (string1 == null ? 0 : string1.Length) - length1)
+ {
+ throw new ArgumentOutOfRangeException("string1", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"));
+ }
+ if (offset2 > (string2 == null ? 0 : string2.Length) - length2)
+ {
+ throw new ArgumentOutOfRangeException("string2", Environment.GetResourceString("ArgumentOutOfRange_OffsetLength"));
+ }
+ if ((options & CompareOptions.Ordinal) != 0)
+ {
+ if (options != CompareOptions.Ordinal)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_CompareOptionOrdinal"),
+ "options");
+ }
+ }
+ else if ((options & ValidCompareMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+
+ //
+ // Check for the null case.
+ //
+ if (string1 == null)
+ {
+ if (string2 == null)
+ {
+ return (0);
+ }
+ return (-1);
+ }
+ if (string2 == null)
+ {
+ return (1);
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return string.CompareOrdinalHelper(string1, offset1, length1, string2, offset2, length2);
+ }
+ return InternalCompareString(this.m_dataHandle, this.m_handleOrigin, this.m_sortName,
+ string1, offset1, length1,
+ string2, offset2, length2,
+ GetNativeCompareFlags(options));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsPrefix
+ //
+ // Determines whether prefix is a prefix of string. If prefix equals
+ // String.Empty, true is returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options)
+ {
+ if (source == null || prefix == null) {
+ throw new ArgumentNullException((source == null ? "source" : "prefix"),
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ int prefixLen = prefix.Length;
+
+ if (prefixLen == 0)
+ {
+ return (true);
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return source.StartsWith(prefix, StringComparison.Ordinal);
+ }
+
+ if ((options & ValidIndexMaskOffFlags) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+
+ return (InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, source.Length, 0, prefix, prefix.Length) > -1);
+ }
+
+ public virtual bool IsPrefix(String source, String prefix)
+ {
+ return (IsPrefix(source, prefix, 0));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsSuffix
+ //
+ // Determines whether suffix is a suffix of string. If suffix equals
+ // String.Empty, true is returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual bool IsSuffix(String source, String suffix, CompareOptions options)
+ {
+ if (source == null || suffix == null) {
+ throw new ArgumentNullException((source == null ? "source" : "suffix"),
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ int suffixLen = suffix.Length;
+
+ if (suffixLen == 0)
+ {
+ return (true);
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase) {
+ return source.EndsWith(suffix, StringComparison.OrdinalIgnoreCase);
+ }
+
+ if (options == CompareOptions.Ordinal) {
+ return source.EndsWith(suffix, StringComparison.Ordinal);
+ }
+
+ if ((options & ValidIndexMaskOffFlags) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+ return InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_ENDSWITH | ((source.IsAscii() && suffix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, source.Length, source.Length - 1, suffix, suffix.Length) >= 0;
+ }
+
+
+ public virtual bool IsSuffix(String source, String suffix)
+ {
+ return (IsSuffix(source, suffix, 0));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IndexOf
+ //
+ // Returns the first index where value is found in string. The
+ // search starts from startIndex and ends at endIndex. Returns -1 if
+ // the specified value is not found. If value equals String.Empty,
+ // startIndex is returned. Throws IndexOutOfRange if startIndex or
+ // endIndex is less than zero or greater than the length of string.
+ // Throws ArgumentException if value is null.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int IndexOf(String source, char value)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, CompareOptions options)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, CompareOptions options)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, 0, source.Length, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, CompareOptions options)
+ {
+ if (source == null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ return IndexOf(source, value, startIndex, source.Length - startIndex, options);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, int count)
+ {
+ return IndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, int count)
+ {
+ return IndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int IndexOf(String source, char value, int startIndex, int count, CompareOptions options)
+ {
+ // Validate inputs
+ if (source == null)
+ throw new ArgumentNullException("source");
+
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count < 0 || startIndex > source.Length - count)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ Contract.EndContractBlock();
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.IndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+ return InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, count, startIndex, new String(value, 1), 1);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int IndexOf(String source, String value, int startIndex, int count, CompareOptions options)
+ {
+ // Validate inputs
+ if (source == null)
+ throw new ArgumentNullException("source");
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (startIndex > source.Length)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ // In Everett we used to return -1 for empty string even if startIndex is negative number so we keeping same behavior here.
+ // We return 0 if both source and value are empty strings for Everett compatibility too.
+ if (source.Length == 0)
+ {
+ if (value.Length == 0)
+ {
+ return 0;
+ }
+ return -1;
+ }
+
+ if (startIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (count < 0 || startIndex > source.Length - count)
+ throw new ArgumentOutOfRangeException("count",Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.IndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 && (options != CompareOptions.Ordinal))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+ return InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_FROMSTART | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, count, startIndex, value, value.Length);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // LastIndexOf
+ //
+ // Returns the last index where value is found in string. The
+ // search starts from startIndex and ends at endIndex. Returns -1 if
+ // the specified value is not found. If value equals String.Empty,
+ // endIndex is returned. Throws IndexOutOfRange if startIndex or
+ // endIndex is less than zero or greater than the length of string.
+ // Throws ArgumentException if value is null.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public unsafe virtual int LastIndexOf(String source, char value)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, CompareOptions.None);
+ }
+
+
+ public virtual int LastIndexOf(String source, String value)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, CompareOptions.None);
+ }
+
+
+ public virtual int LastIndexOf(String source, char value, CompareOptions options)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, options);
+ }
+
+ public unsafe virtual int LastIndexOf(String source, String value, CompareOptions options)
+ {
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Can't start at negative index, so make sure we check for the length == 0 case.
+ return LastIndexOf(source, value, source.Length - 1,
+ source.Length, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, CompareOptions options)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, CompareOptions options)
+ {
+ return LastIndexOf(source, value, startIndex, startIndex + 1, options);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count)
+ {
+ return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count)
+ {
+ return LastIndexOf(source, value, startIndex, count, CompareOptions.None);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int LastIndexOf(String source, char value, int startIndex, int count, CompareOptions options)
+ {
+ // Verify Arguments
+ if (source==null)
+ throw new ArgumentNullException("source");
+ Contract.EndContractBlock();
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 &&
+ (options != CompareOptions.Ordinal) &&
+ (options != CompareOptions.OrdinalIgnoreCase))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+
+ // Special case for 0 length input strings
+ if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
+ return -1;
+
+ // Make sure we're not out of range
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ // Make sure that we allow startIndex == source.Length
+ if (startIndex == source.Length)
+ {
+ startIndex--;
+ if (count > 0)
+ count--;
+ }
+
+ // 2nd have of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.LastIndexOf(value.ToString(), startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+ return InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && (value <= '\x007f')) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, count, startIndex, new String(value, 1), 1);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual int LastIndexOf(String source, String value, int startIndex, int count, CompareOptions options)
+ {
+ // Verify Arguments
+ if (source == null)
+ throw new ArgumentNullException("source");
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Validate CompareOptions
+ // Ordinal can't be selected with other flags
+ if ((options & ValidIndexMaskOffFlags) != 0 &&
+ (options != CompareOptions.Ordinal) &&
+ (options != CompareOptions.OrdinalIgnoreCase))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+
+ // Special case for 0 length input strings
+ if (source.Length == 0 && (startIndex == -1 || startIndex == 0))
+ return (value.Length == 0) ? 0 : -1;
+
+ // Make sure we're not out of range
+ if (startIndex < 0 || startIndex > source.Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ // Make sure that we allow startIndex == source.Length
+ if (startIndex == source.Length)
+ {
+ startIndex--;
+ if (count > 0)
+ count--;
+
+ // If we are looking for nothing, just return 0
+ if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0)
+ return startIndex;
+ }
+
+ // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return source.LastIndexOf(value, startIndex, count, StringComparison.OrdinalIgnoreCase);
+ }
+
+ // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to
+ // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString.
+ return InternalFindNLSStringEx(
+ m_dataHandle, m_handleOrigin, m_sortName,
+ GetNativeCompareFlags(options) | Win32Native.FIND_FROMEND | ((source.IsAscii() && value.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0),
+ source, count, startIndex, value, value.Length);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetSortKey
+ //
+ // Gets the SortKey for the given string with the given options.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public unsafe virtual SortKey GetSortKey(String source, CompareOptions options)
+ {
+ return CreateSortKey(source, options);
+ }
+
+
+ public unsafe virtual SortKey GetSortKey(String source)
+ {
+ return CreateSortKey(source, CompareOptions.None);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private SortKey CreateSortKey(String source, CompareOptions options)
+ {
+ if (source==null) { throw new ArgumentNullException("source"); }
+ Contract.EndContractBlock();
+
+ // Mask used to check if we have the right flags.
+ const CompareOptions ValidSortkeyCtorMaskOffFlags = ~(CompareOptions.IgnoreCase |
+ CompareOptions.IgnoreSymbols |
+ CompareOptions.IgnoreNonSpace |
+ CompareOptions.IgnoreWidth |
+ CompareOptions.IgnoreKanaType |
+ CompareOptions.StringSort);
+
+ if ((options & ValidSortkeyCtorMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+ byte[] keyData = null;
+ // The OS doesn't have quite the same behavior so we have to test for empty inputs
+ if (String.IsNullOrEmpty(source))
+ {
+ // Empty strings get an empty sort key
+ keyData = EmptyArray<Byte>.Value;
+ // Fake value to test though so we can verify our flags
+ source = "\x0000";
+ }
+
+ int flags = GetNativeCompareFlags(options);
+
+ // Go ahead and call the OS
+ // First get the count
+ int length = InternalGetSortKey(m_dataHandle, m_handleOrigin, m_sortName, flags, source, source.Length, null, 0);
+
+ // If there was an error, return an error
+ if (length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "source");
+ }
+
+ // If input was empty, return the empty byte[] we made earlier and skip this
+ if (keyData == null)
+ {
+ // Make an appropriate byte array
+ keyData = new byte[length];
+
+ // Fill up the array
+ length = InternalGetSortKey(m_dataHandle, m_handleOrigin, m_sortName, flags, source, source.Length, keyData, keyData.Length);
+ }
+ else
+ {
+ source = String.Empty; // back to original
+ }
+
+ return new SortKey(Name, source, options, keyData);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CompareInfo as the current
+ // instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Equals(Object value)
+ {
+ CompareInfo that = value as CompareInfo;
+
+ if (that != null)
+ {
+ return this.Name == that.Name;
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CompareInfo. The hash code is guaranteed to be the same for
+ // CompareInfo A and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode());
+ }
+
+ //
+ // return hash value for the string according to the input CompareOptions
+ //
+
+ public virtual int GetHashCode(string source, CompareOptions options)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if (options == CompareOptions.Ordinal)
+ {
+ return source.GetHashCode();
+ }
+
+ if (options == CompareOptions.OrdinalIgnoreCase)
+ {
+ return TextInfo.GetHashCodeOrdinalIgnoreCase(source);
+ }
+
+ //
+ // GetHashCodeOfString does more parameters validation. basically will throw when
+ // having Ordinal, OrdinalIgnoreCase and StringSort
+ //
+
+ return GetHashCodeOfString(source, options, false, 0);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCodeOfString
+ //
+ // This internal method allows a method that allows the equivalent of creating a Sortkey for a
+ // string from CompareInfo, and generate a hashcode value from it. It is not very convenient
+ // to use this method as is and it creates an unnecessary Sortkey object that will be GC'ed.
+ //
+ // The hash code is guaranteed to be the same for string A and B where A.Equals(B) is true and both
+ // the CompareInfo and the CompareOptions are the same. If two different CompareInfo objects
+ // treat the string the same way, this implementation will treat them differently (the same way that
+ // Sortkey does at the moment).
+ //
+ // This method will never be made public itself, but public consumers of it could be created, e.g.:
+ //
+ // string.GetHashCode(CultureInfo)
+ // string.GetHashCode(CompareInfo)
+ // string.GetHashCode(CultureInfo, CompareOptions)
+ // string.GetHashCode(CompareInfo, CompareOptions)
+ // etc.
+ //
+ // (the methods above that take a CultureInfo would use CultureInfo.CompareInfo)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ internal int GetHashCodeOfString(string source, CompareOptions options)
+ {
+ return GetHashCodeOfString(source, options, false, 0);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal int GetHashCodeOfString(string source, CompareOptions options, bool forceRandomizedHashing, long additionalEntropy)
+ {
+ //
+ // Parameter validation
+ //
+ if(null == source)
+ {
+ throw new ArgumentNullException("source");
+ }
+
+ if ((options & ValidHashCodeOfStringMaskOffFlags) != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options");
+ }
+ Contract.EndContractBlock();
+
+ if(0 == source.Length)
+ {
+ return(0);
+ }
+
+ //
+ ////////////////////////////////////////////////////////////////////////
+ return (InternalGetGlobalizedHashCode(m_dataHandle, m_handleOrigin, this.m_sortName, source, source.Length, GetNativeCompareFlags(options), forceRandomizedHashing, additionalEntropy));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns a string describing the
+ // CompareInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override String ToString()
+ {
+ return ("CompareInfo - " + this.Name);
+ }
+
+#if FEATURE_USE_LCID
+ public int LCID
+ {
+ get
+ {
+ return CultureInfo.GetCultureInfo(this.Name).LCID;
+ }
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical]
+ internal static IntPtr InternalInitSortHandle(String localeName, out IntPtr handleOrigin)
+ {
+ return NativeInternalInitSortHandle(localeName, out handleOrigin);
+ }
+
+#if !FEATURE_CORECLR
+ private const int SORT_VERSION_WHIDBEY = 0x00001000;
+ private const int SORT_VERSION_V4 = 0x00060101;
+
+ internal static bool IsLegacy20SortingBehaviorRequested
+ {
+ get
+ {
+ return InternalSortVersion == SORT_VERSION_WHIDBEY;
+ }
+ }
+
+ private static uint InternalSortVersion
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ return InternalGetSortVersion();
+ }
+ }
+
+ [OptionalField(VersionAdded = 3)]
+ private SortVersion m_SortVersion;
+
+ public SortVersion Version
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if(m_SortVersion == null)
+ {
+ Win32Native.NlsVersionInfoEx v = new Win32Native.NlsVersionInfoEx();
+ v.dwNLSVersionInfoSize = Marshal.SizeOf(typeof(Win32Native.NlsVersionInfoEx));
+ InternalGetNlsVersionEx(m_dataHandle, m_handleOrigin, m_sortName, ref v);
+ m_SortVersion = new SortVersion(v.dwNLSVersion, (v.dwEffectiveId != 0) ? v.dwEffectiveId : LCID, v.guidCustomVersion);
+ }
+
+ return m_SortVersion;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool InternalGetNlsVersionEx(IntPtr handle, IntPtr handleOrigin, String localeName, ref Win32Native.NlsVersionInfoEx lpNlsVersionInformation);
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern uint InternalGetSortVersion();
+
+#endif
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr NativeInternalInitSortHandle(String localeName, out IntPtr handleOrigin);
+
+ // Get a locale sensitive sort hash code from native code -- COMNlsInfo::InternalGetGlobalizedHashCode
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern int InternalGetGlobalizedHashCode(IntPtr handle, IntPtr handleOrigin, string localeName, string source, int length, int dwFlags, bool forceRandomizedHashing, long additionalEntropy);
+
+ // Use native API calls to see if this string is entirely defined -- COMNlsInfo::InternalIsSortable
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool InternalIsSortable(IntPtr handle, IntPtr handleOrigin, String localeName, String source, int length);
+
+ // Compare a string using the native API calls -- COMNlsInfo::InternalCompareString
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern int InternalCompareString(IntPtr handle, IntPtr handleOrigin, String localeName, String string1, int offset1, int length1,
+ String string2, int offset2, int length2, int flags);
+
+ // InternalFindNLSStringEx parameters is not exactly matching kernel32::FindNLSStringEx parameters.
+ // Call through to NewApis::FindNLSStringEx so we can get the right behavior
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern int InternalFindNLSStringEx(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, int startIndex, string target, int targetCount);
+
+ // Call through to NewAPis::LCMapStringEx so we can get appropriate behavior for all platforms
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern int InternalGetSortKey(IntPtr handle, IntPtr handleOrigin, String localeName, int flags, String source, int sourceCount, byte[] target, int targetCount);
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CultureData.cs b/src/mscorlib/src/System/Globalization/CultureData.cs
new file mode 100644
index 0000000000..ae1eeea298
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CultureData.cs
@@ -0,0 +1,3354 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Threading;
+#if !FEATURE_CORECLR
+ using System.Reflection;
+ using System.Resources;
+#endif
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+
+ //
+ // List of culture data
+ // Note the we cache overrides.
+ // Note that localized names (resource names) aren't available from here.
+ //
+
+ //
+ // Our names are a tad confusing.
+ //
+ // sWindowsName -- The name that windows thinks this culture is, ie:
+ // en-US if you pass in en-US
+ // de-DE_phoneb if you pass in de-DE_phoneb
+ // fj-FJ if you pass in fj (neutral, on a pre-Windows 7 machine)
+ // fj if you pass in fj (neutral, post-Windows 7 machine)
+ //
+ // sRealName -- The name you used to construct the culture, in pretty form
+ // en-US if you pass in EN-us
+ // en if you pass in en
+ // de-DE_phoneb if you pass in de-DE_phoneb
+ //
+ // sSpecificCulture -- The specific culture for this culture
+ // en-US for en-US
+ // en-US for en
+ // de-DE_phoneb for alt sort
+ // fj-FJ for fj (neutral)
+ //
+ // sName -- The IETF name of this culture (ie: no sort info, could be neutral)
+ // en-US if you pass in en-US
+ // en if you pass in en
+ // de-DE if you pass in de-DE_phoneb
+ //
+
+ // StructLayout is needed here otherwise compiler can re-arrange the fields.
+ // We have to keep this in-sync with the definition in comnlsinfo.h
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: Anything changed here also needs to be updated on the native side (object.h see type CultureDataBaseObject)
+ // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureDataBaseObject
+ // WARNING: must be manually structured to match the true loaded class layout
+ //
+ [FriendAccessAllowed]
+ internal class CultureData
+ {
+ const int undef = -1;
+
+ // Override flag
+ private String sRealName; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+ private String sWindowsName; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
+
+ // Identity
+ private String sName; // locale name (ie: en-us, NO sort info, but could be neutral)
+ private String sParent; // Parent name (which may be a custom locale/culture)
+ private String sLocalizedDisplayName; // Localized pretty name for this locale
+ private String sEnglishDisplayName; // English pretty name for this locale
+ private String sNativeDisplayName; // Native pretty name for this locale
+ private String sSpecificCulture; // The culture name to be used in CultureInfo.CreateSpecificCulture(), en-US form if neutral, sort name if sort
+
+ // Language
+ private String sISO639Language; // ISO 639 Language Name
+ private String sLocalizedLanguage; // Localized name for this language
+ private String sEnglishLanguage; // English name for this language
+ private String sNativeLanguage; // Native name of this language
+
+ // Region
+ private String sRegionName; // (RegionInfo)
+ private int iGeoId = undef; // GeoId
+ private String sLocalizedCountry; // localized country name
+ private String sEnglishCountry; // english country name (RegionInfo)
+ private String sNativeCountry; // native country name
+ private String sISO3166CountryName; // ISO 3166 (RegionInfo), ie: US
+
+ // Numbers
+ private String sPositiveSign; // (user can override) positive sign
+ private String sNegativeSign; // (user can override) negative sign
+ private String[] saNativeDigits; // (user can override) native characters for digits 0-9
+ // (nfi populates these 5, don't have to be = undef)
+ private int iDigitSubstitution; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused)
+ private int iLeadingZeros; // (user can override) leading zeros 0 = no leading zeros, 1 = leading zeros
+ private int iDigits; // (user can override) number of fractional digits
+ private int iNegativeNumber; // (user can override) negative number format
+ private int[] waGrouping; // (user can override) grouping of digits
+ private String sDecimalSeparator; // (user can override) decimal separator
+ private String sThousandSeparator; // (user can override) thousands separator
+ private String sNaN; // Not a Number
+ private String sPositiveInfinity; // + Infinity
+ private String sNegativeInfinity; // - Infinity
+
+ // Percent
+ private int iNegativePercent = undef; // Negative Percent (0-3)
+ private int iPositivePercent = undef; // Positive Percent (0-11)
+ private String sPercent; // Percent (%) symbol
+ private String sPerMille; // PerMille (‰) symbol
+
+ // Currency
+ private String sCurrency; // (user can override) local monetary symbol
+ private String sIntlMonetarySymbol; // international monetary symbol (RegionInfo)
+ private String sEnglishCurrency; // English name for this currency
+ private String sNativeCurrency; // Native name for this currency
+ // (nfi populates these 4, don't have to be = undef)
+ private int iCurrencyDigits; // (user can override) # local monetary fractional digits
+ private int iCurrency; // (user can override) positive currency format
+ private int iNegativeCurrency; // (user can override) negative currency format
+ private int[] waMonetaryGrouping; // (user can override) monetary grouping of digits
+ private String sMonetaryDecimal; // (user can override) monetary decimal separator
+ private String sMonetaryThousand; // (user can override) monetary thousands separator
+
+ // Misc
+ private int iMeasure = undef; // (user can override) system of measurement 0=metric, 1=US (RegionInfo)
+ private String sListSeparator; // (user can override) list separator
+ // private int iPaperSize ; // default paper size (RegionInfo)
+
+ // Time
+ private String sAM1159; // (user can override) AM designator
+ private String sPM2359; // (user can override) PM designator
+ private String sTimeSeparator;
+ private volatile String[] saLongTimes; // (user can override) time format
+ private volatile String[] saShortTimes; // short time format
+ private volatile String[] saDurationFormats; // time duration format
+
+ // Calendar specific data
+ private int iFirstDayOfWeek = undef; // (user can override) first day of week (gregorian really)
+ private int iFirstWeekOfYear = undef; // (user can override) first week of year (gregorian really)
+ private volatile int[] waCalendars; // all available calendar type(s). The first one is the default calendar
+
+ // Store for specific data about each calendar
+ private CalendarData[] calendars; // Store for specific calendar data
+
+ // Text information
+ private int iReadingLayout = undef; // Reading layout data
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+
+ private String sTextInfo; // Text info name to use for custom
+ private String sCompareInfo; // Compare info name (including sorting key) to use if custom
+ private String sScripts; // Typical Scripts for this locale (latn;cyrl; etc)
+
+ private int iDefaultAnsiCodePage = undef; // default ansi code page ID (ACP)
+ private int iDefaultOemCodePage = undef; // default oem code page ID (OCP or OEM)
+ private int iDefaultMacCodePage = undef; // default macintosh code page
+ private int iDefaultEbcdicCodePage = undef; // default EBCDIC code page
+
+ // These are desktop only, not coreclr
+ private int iLanguage; // locale ID (0409) - NO sort information
+ private String sAbbrevLang; // abbreviated language name (Windows Language Name) ex: ENU
+ private String sAbbrevCountry; // abbreviated country name (RegionInfo) (Windows Region Name) ex: USA
+ private String sISO639Language2; // 3 char ISO 639 lang name 2 ex: eng
+ private String sISO3166CountryName2; // 3 char ISO 3166 country name 2 2(RegionInfo) ex: USA (ISO)
+ private int iInputLanguageHandle=undef;// input language handle
+ private String sConsoleFallbackName; // The culture name for the console fallback UI culture
+ private String sKeyboardsToInstall; // Keyboard installation string.
+ private String fontSignature; // Font signature (16 WORDS)
+
+ // The bools all need to be in one spot
+ private bool bUseOverrides; // use user overrides?
+ private bool bNeutral; // Flags for the culture (ie: neutral or not right now)
+ private bool bWin32Installed; // Flags indicate if the culture is Win32 installed
+ private bool bFramework; // Flags for indicate if the culture is one of Whidbey cultures
+
+ // Region Name to Culture Name mapping table
+ // (In future would be nice to be in registry or something)
+
+ //Using a property so we avoid creating the dictionary untill we need it
+ private static Dictionary<string, string> RegionNames
+ {
+ get
+ {
+ if (s_RegionNames == null)
+ {
+ var regionNames = new Dictionary<string, string> {
+ { "029", "en-029" },
+ { "AE", "ar-AE" },
+ { "AF", "prs-AF" },
+ { "AL", "sq-AL" },
+ { "AM", "hy-AM" },
+ { "AR", "es-AR" },
+ { "AT", "de-AT" },
+ { "AU", "en-AU" },
+ { "AZ", "az-Cyrl-AZ" },
+ { "BA", "bs-Latn-BA" },
+ { "BD", "bn-BD" },
+ { "BE", "nl-BE" },
+ { "BG", "bg-BG" },
+ { "BH", "ar-BH" },
+ { "BN", "ms-BN" },
+ { "BO", "es-BO" },
+ { "BR", "pt-BR" },
+ { "BY", "be-BY" },
+ { "BZ", "en-BZ" },
+ { "CA", "en-CA" },
+ { "CH", "it-CH" },
+ { "CL", "es-CL" },
+ { "CN", "zh-CN" },
+ { "CO", "es-CO" },
+ { "CR", "es-CR" },
+ { "CS", "sr-Cyrl-CS" },
+ { "CZ", "cs-CZ" },
+ { "DE", "de-DE" },
+ { "DK", "da-DK" },
+ { "DO", "es-DO" },
+ { "DZ", "ar-DZ" },
+ { "EC", "es-EC" },
+ { "EE", "et-EE" },
+ { "EG", "ar-EG" },
+ { "ES", "es-ES" },
+ { "ET", "am-ET" },
+ { "FI", "fi-FI" },
+ { "FO", "fo-FO" },
+ { "FR", "fr-FR" },
+ { "GB", "en-GB" },
+ { "GE", "ka-GE" },
+ { "GL", "kl-GL" },
+ { "GR", "el-GR" },
+ { "GT", "es-GT" },
+ { "HK", "zh-HK" },
+ { "HN", "es-HN" },
+ { "HR", "hr-HR" },
+ { "HU", "hu-HU" },
+ { "ID", "id-ID" },
+ { "IE", "en-IE" },
+ { "IL", "he-IL" },
+ { "IN", "hi-IN" },
+ { "IQ", "ar-IQ" },
+ { "IR", "fa-IR" },
+ { "IS", "is-IS" },
+ { "IT", "it-IT" },
+ { "IV", "" },
+ { "JM", "en-JM" },
+ { "JO", "ar-JO" },
+ { "JP", "ja-JP" },
+ { "KE", "sw-KE" },
+ { "KG", "ky-KG" },
+ { "KH", "km-KH" },
+ { "KR", "ko-KR" },
+ { "KW", "ar-KW" },
+ { "KZ", "kk-KZ" },
+ { "LA", "lo-LA" },
+ { "LB", "ar-LB" },
+ { "LI", "de-LI" },
+ { "LK", "si-LK" },
+ { "LT", "lt-LT" },
+ { "LU", "lb-LU" },
+ { "LV", "lv-LV" },
+ { "LY", "ar-LY" },
+ { "MA", "ar-MA" },
+ { "MC", "fr-MC" },
+ { "ME", "sr-Latn-ME" },
+ { "MK", "mk-MK" },
+ { "MN", "mn-MN" },
+ { "MO", "zh-MO" },
+ { "MT", "mt-MT" },
+ { "MV", "dv-MV" },
+ { "MX", "es-MX" },
+ { "MY", "ms-MY" },
+ { "NG", "ig-NG" },
+ { "NI", "es-NI" },
+ { "NL", "nl-NL" },
+ { "NO", "nn-NO" },
+ { "NP", "ne-NP" },
+ { "NZ", "en-NZ" },
+ { "OM", "ar-OM" },
+ { "PA", "es-PA" },
+ { "PE", "es-PE" },
+ { "PH", "en-PH" },
+ { "PK", "ur-PK" },
+ { "PL", "pl-PL" },
+ { "PR", "es-PR" },
+ { "PT", "pt-PT" },
+ { "PY", "es-PY" },
+ { "QA", "ar-QA" },
+ { "RO", "ro-RO" },
+ { "RS", "sr-Latn-RS" },
+ { "RU", "ru-RU" },
+ { "RW", "rw-RW" },
+ { "SA", "ar-SA" },
+ { "SE", "sv-SE" },
+ { "SG", "zh-SG" },
+ { "SI", "sl-SI" },
+ { "SK", "sk-SK" },
+ { "SN", "wo-SN" },
+ { "SV", "es-SV" },
+ { "SY", "ar-SY" },
+ { "TH", "th-TH" },
+ { "TJ", "tg-Cyrl-TJ" },
+ { "TM", "tk-TM" },
+ { "TN", "ar-TN" },
+ { "TR", "tr-TR" },
+ { "TT", "en-TT" },
+ { "TW", "zh-TW" },
+ { "UA", "uk-UA" },
+ { "US", "en-US" },
+ { "UY", "es-UY" },
+ { "UZ", "uz-Cyrl-UZ" },
+ { "VE", "es-VE" },
+ { "VN", "vi-VN" },
+ { "YE", "ar-YE" },
+ { "ZA", "af-ZA" },
+ { "ZW", "en-ZW" }
+ };
+ s_RegionNames = regionNames;
+ }
+ return s_RegionNames;
+ }
+ }
+ private volatile static Dictionary<string, string> s_RegionNames;
+
+ /////////////////////////////////////////////////////////////////////////
+ // Build our invariant information
+ //
+ // We need an invariant instance, which we build hard-coded
+ /////////////////////////////////////////////////////////////////////////
+ internal static CultureData Invariant
+ {
+ get
+ {
+ if (s_Invariant == null)
+ {
+ // Make a new culturedata
+ CultureData invariant = new CultureData();
+
+ // Call the native code to get the value of bWin32Installed.
+ // For versions <= Vista, we set this to false for compatibility with v2.
+ // For Windows 7, the flag is true.
+ invariant.bUseOverrides = false;
+ invariant.sRealName = "";
+
+ // Ask the native code to fill it out for us, we only need the field IsWin32Installed
+ nativeInitCultureData(invariant);
+
+ // Basics
+ // Note that we override the resources since this IS NOT supposed to change (by definition)
+ invariant.bUseOverrides = false;
+ invariant.sRealName = ""; // Name you passed in (ie: en-US, en, or de-DE_phoneb)
+ invariant.sWindowsName = ""; // Name OS thinks the object is (ie: de-DE_phoneb, or en-US (even if en was passed in))
+
+ // Identity
+ invariant.sName = ""; // locale name (ie: en-us)
+ invariant.sParent = ""; // Parent name (which may be a custom locale/culture)
+ invariant.bNeutral = false; // Flags for the culture (ie: neutral or not right now)
+ // Don't set invariant.bWin32Installed, we used nativeInitCultureData for that.
+ invariant.bFramework = true;
+
+ invariant.sEnglishDisplayName = "Invariant Language (Invariant Country)"; // English pretty name for this locale
+ invariant.sNativeDisplayName = "Invariant Language (Invariant Country)"; // Native pretty name for this locale
+ invariant.sSpecificCulture = ""; // The culture name to be used in CultureInfo.CreateSpecificCulture()
+
+ // Language
+ invariant.sISO639Language = "iv"; // ISO 639 Language Name
+ invariant.sLocalizedLanguage = "Invariant Language"; // Display name for this Language
+ invariant.sEnglishLanguage = "Invariant Language"; // English name for this language
+ invariant.sNativeLanguage = "Invariant Language"; // Native name of this language
+
+ // Region
+ invariant.sRegionName = "IV"; // (RegionInfo)
+ // Unused for now:
+ // invariant.iCountry =1; // country code (RegionInfo)
+ invariant.iGeoId = 244; // GeoId (Windows Only)
+ invariant.sEnglishCountry = "Invariant Country"; // english country name (RegionInfo)
+ invariant.sNativeCountry = "Invariant Country"; // native country name (Windows Only)
+ invariant.sISO3166CountryName = "IV"; // (RegionInfo), ie: US
+
+ // Numbers
+ invariant.sPositiveSign = "+"; // positive sign
+ invariant.sNegativeSign = "-"; // negative sign
+ invariant.saNativeDigits = new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; // native characters for digits 0-9
+ invariant.iDigitSubstitution = 1; // Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only)
+ invariant.iLeadingZeros = 1; // leading zeros 0=no leading zeros, 1=leading zeros
+ invariant.iDigits = 2; // number of fractional digits
+ invariant.iNegativeNumber = 1; // negative number format
+ invariant.waGrouping = new int[] { 3 }; // grouping of digits
+ invariant.sDecimalSeparator = "."; // decimal separator
+ invariant.sThousandSeparator = ","; // thousands separator
+ invariant.sNaN = "NaN"; // Not a Number
+ invariant.sPositiveInfinity = "Infinity"; // + Infinity
+ invariant.sNegativeInfinity = "-Infinity"; // - Infinity
+
+ // Percent
+ invariant.iNegativePercent = 0; // Negative Percent (0-3)
+ invariant.iPositivePercent = 0; // Positive Percent (0-11)
+ invariant.sPercent = "%"; // Percent (%) symbol
+ invariant.sPerMille = "\x2030"; // PerMille(‰) symbol
+
+ // Currency
+ invariant.sCurrency = "\x00a4"; // local monetary symbol "¤: for international monetary symbol
+ invariant.sIntlMonetarySymbol = "XDR"; // international monetary symbol (RegionInfo)
+ invariant.sEnglishCurrency = "International Monetary Fund"; // English name for this currency (Windows Only)
+ invariant.sNativeCurrency = "International Monetary Fund"; // Native name for this currency (Windows Only)
+ invariant.iCurrencyDigits = 2; // # local monetary fractional digits
+ invariant.iCurrency = 0; // positive currency format
+ invariant.iNegativeCurrency = 0; // negative currency format
+ invariant.waMonetaryGrouping = new int[] { 3 }; // monetary grouping of digits
+ invariant.sMonetaryDecimal = "."; // monetary decimal separator
+ invariant.sMonetaryThousand = ","; // monetary thousands separator
+
+ // Misc
+ invariant.iMeasure = 0; // system of measurement 0=metric, 1=US (RegionInfo)
+ invariant.sListSeparator = ","; // list separator
+ // Unused for now:
+ // invariant.iPaperSize =9; // default paper size (RegionInfo)
+ // invariant.waFontSignature ="\x0002\x0000\x0000\x0000\x0000\x0000\x0000\x8000\x0001\x0000\x0000\x8000\x0001\x0000\x0000\x8000"; // Font signature (16 WORDS) (Windows Only)
+
+ // Time
+ invariant.sAM1159 = "AM"; // AM designator
+ invariant.sPM2359 = "PM"; // PM designator
+ invariant.saLongTimes = new String[] { "HH:mm:ss" }; // time format
+ invariant.saShortTimes = new String[] { "HH:mm", "hh:mm tt", "H:mm", "h:mm tt" }; // short time format
+ invariant.saDurationFormats = new String[] { "HH:mm:ss" }; // time duration format
+
+ // Calendar specific data
+ invariant.iFirstDayOfWeek = 0; // first day of week
+ invariant.iFirstWeekOfYear = 0; // first week of year
+ invariant.waCalendars = new int[] { (int)CalendarId.GREGORIAN }; // all available calendar type(s). The first one is the default calendar
+
+ // Store for specific data about each calendar
+ invariant.calendars = new CalendarData[CalendarData.MAX_CALENDARS];
+ invariant.calendars[0] = CalendarData.Invariant;
+
+ // Text information
+ invariant.iReadingLayout = 0; // Reading Layout = RTL
+
+ invariant.sTextInfo = ""; // Text info name to use for custom
+ invariant.sCompareInfo = ""; // Compare info name (including sorting key) to use if custom
+ invariant.sScripts = "Latn;"; // Typical Scripts for this locale (latn,cyrl, etc)
+
+ invariant.iLanguage = 0x007f; // locale ID (0409) - NO sort information
+ invariant.iDefaultAnsiCodePage = 1252; // default ansi code page ID (ACP)
+ invariant.iDefaultOemCodePage = 437; // default oem code page ID (OCP or OEM)
+ invariant.iDefaultMacCodePage = 10000; // default macintosh code page
+ invariant.iDefaultEbcdicCodePage = 037; // default EBCDIC code page
+ invariant.sAbbrevLang = "IVL"; // abbreviated language name (Windows Language Name)
+ invariant.sAbbrevCountry = "IVC"; // abbreviated country name (RegionInfo) (Windows Region Name)
+ invariant.sISO639Language2 = "ivl"; // 3 char ISO 639 lang name 2
+ invariant.sISO3166CountryName2 = "ivc"; // 3 char ISO 3166 country name 2 2(RegionInfo)
+ invariant.iInputLanguageHandle = 0x007f; // input language handle
+ invariant.sConsoleFallbackName = ""; // The culture name for the console fallback UI culture
+ invariant.sKeyboardsToInstall = "0409:00000409"; // Keyboard installation string.
+ // Remember it
+ s_Invariant = invariant;
+ }
+ return s_Invariant;
+ }
+ }
+ private volatile static CultureData s_Invariant;
+
+
+#if !FEATURE_CORECLR
+ internal static volatile ResourceSet MscorlibResourceSet;
+#endif
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool IsResourcePresent(String resourceKey)
+ {
+ if (MscorlibResourceSet == null)
+ {
+ MscorlibResourceSet = new ResourceSet(typeof(Environment).Assembly.GetManifestResourceStream("mscorlib.resources"));
+ }
+ return MscorlibResourceSet.GetString(resourceKey) != null;
+ }
+#endif
+
+ ///////////////
+ // Constructors //
+ ///////////////
+ // Cache of cultures we've already looked up
+ private static volatile Dictionary<String, CultureData> s_cachedCultures;
+
+ [FriendAccessAllowed]
+ internal static CultureData GetCultureData(String cultureName, bool useUserOverride)
+ {
+ // First do a shortcut for Invariant
+ if (String.IsNullOrEmpty(cultureName))
+ {
+ return CultureData.Invariant;
+ }
+
+ // Try the hash table first
+ String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
+ Dictionary<String, CultureData> tempHashTable = s_cachedCultures;
+ if (tempHashTable == null)
+ {
+ // No table yet, make a new one
+ tempHashTable = new Dictionary<String, CultureData>();
+ }
+ else
+ {
+ // Check the hash table
+ CultureData retVal;
+ lock (((ICollection)tempHashTable).SyncRoot)
+ {
+ tempHashTable.TryGetValue(hashName, out retVal);
+ }
+ if (retVal != null)
+ {
+ return retVal;
+ }
+ }
+
+ // Not found in the hash table, need to see if we can build one that works for us
+ CultureData culture = CreateCultureData(cultureName, useUserOverride);
+ if (culture == null)
+ {
+ return null;
+ }
+
+ // Found one, add it to the cache
+ lock (((ICollection)tempHashTable).SyncRoot)
+ {
+ tempHashTable[hashName] = culture;
+ }
+
+ // Copy the hashtable to the corresponding member variables. This will potentially overwrite
+ // new tables simultaneously created by a new thread, but maximizes thread safety.
+ s_cachedCultures = tempHashTable;
+
+ return culture;
+ }
+
+ private static CultureData CreateCultureData(string cultureName, bool useUserOverride)
+ {
+ CultureData culture = new CultureData();
+ culture.bUseOverrides = useUserOverride;
+ culture.sRealName = cultureName;
+
+ // Ask native code if that one's real
+ if (culture.InitCultureData() == false)
+ {
+#if !FEATURE_CORECLR
+ if (culture.InitCompatibilityCultureData() == false
+ && culture.InitLegacyAlternateSortData() == false)
+#endif
+ {
+ return null;
+ }
+ }
+
+ return culture;
+ }
+
+ private bool InitCultureData()
+ {
+ if (nativeInitCultureData(this) == false)
+ {
+ return false;
+ }
+
+#if !FEATURE_CORECLR
+ if (CultureInfo.IsTaiwanSku)
+ {
+ TreatTaiwanParentChainAsHavingTaiwanAsSpecific();
+ }
+#endif
+ return true;
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+ private void TreatTaiwanParentChainAsHavingTaiwanAsSpecific()
+ {
+ if (IsNeutralInParentChainOfTaiwan() && IsOsPriorToWin7() && !IsReplacementCulture)
+ {
+ // force population of fields that should have information that is
+ // different than zh-TW:
+ string s = SNATIVELANGUAGE;
+ s = SENGLISHLANGUAGE;
+ s = SLOCALIZEDLANGUAGE;
+ s = STEXTINFO;
+ s = SCOMPAREINFO;
+ s = FONTSIGNATURE;
+ int i = IDEFAULTANSICODEPAGE;
+ i = IDEFAULTOEMCODEPAGE;
+ i = IDEFAULTMACCODEPAGE;
+
+ this.sSpecificCulture = "zh-TW";
+ this.sWindowsName = "zh-TW";
+ }
+ }
+
+ private bool IsNeutralInParentChainOfTaiwan()
+ {
+ return this.sRealName == "zh" || this.sRealName == "zh-Hant";
+ }
+
+ static readonly Version s_win7Version = new Version(6, 1);
+ static private bool IsOsPriorToWin7()
+ {
+ return Environment.OSVersion.Platform == PlatformID.Win32NT &&
+ Environment.OSVersion.Version < s_win7Version;
+ }
+ static private bool IsOsWin7OrPrior()
+ {
+ return Environment.OSVersion.Platform == PlatformID.Win32NT &&
+ Environment.OSVersion.Version < new Version(6, 2); // Win7 is 6.1.Build.Revision so we have to check for anything less than 6.2
+ }
+
+ private bool InitCompatibilityCultureData()
+ {
+ // for compatibility handle the deprecated ids: zh-chs, zh-cht
+ string cultureName = this.sRealName;
+
+ string fallbackCultureName;
+ string realCultureName;
+ switch (AnsiToLower(cultureName))
+ {
+ case "zh-chs":
+ fallbackCultureName = "zh-Hans";
+ realCultureName = "zh-CHS";
+ break;
+ case "zh-cht":
+ fallbackCultureName = "zh-Hant";
+ realCultureName = "zh-CHT";
+ break;
+ default:
+ return false;
+ }
+
+ this.sRealName = fallbackCultureName;
+ if (InitCultureData() == false)
+ {
+ return false;
+ }
+ // fixup our data
+ this.sName = realCultureName; // the name that goes back to the user
+ this.sParent = fallbackCultureName;
+ this.bFramework = true;
+
+ return true;
+ }
+
+ private bool InitLegacyAlternateSortData()
+ {
+ if (!CompareInfo.IsLegacy20SortingBehaviorRequested)
+ {
+ return false;
+ }
+
+ // For V2 compatibility, handle deprecated alternate sorts
+ string cultureName = this.sRealName;
+
+ switch (AnsiToLower(cultureName))
+ {
+ case "ko-kr_unicod":
+ cultureName = "ko-KR_unicod";
+ this.sRealName = "ko-KR";
+ this.iLanguage = 0x00010412;
+ break;
+ case "ja-jp_unicod":
+ cultureName = "ja-JP_unicod";
+ this.sRealName = "ja-JP";
+ this.iLanguage = 0x00010411;
+ break;
+ case "zh-hk_stroke":
+ cultureName = "zh-HK_stroke";
+ this.sRealName = "zh-HK";
+ this.iLanguage = 0x00020c04;
+ break;
+ default:
+ return false;
+ }
+
+ if (nativeInitCultureData(this) == false)
+ {
+ return false;
+ }
+
+ this.sRealName = cultureName;
+ this.sCompareInfo = cultureName;
+ this.bFramework = true;
+
+ return true;
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ private static String s_RegionKey = @"System\CurrentControlSet\Control\Nls\RegionMapping";
+#endif // FEATURE_WIN32_REGISTRY
+
+#endif // !FEATURE_CORECLR
+ // Cache of regions we've already looked up
+ private static volatile Dictionary<String, CultureData> s_cachedRegions;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static CultureData GetCultureDataForRegion(String cultureName, bool useUserOverride)
+ {
+ // First do a shortcut for Invariant
+ if (String.IsNullOrEmpty(cultureName))
+ {
+ return CultureData.Invariant;
+ }
+
+ //
+ // First check if GetCultureData() can find it (ie: its a real culture)
+ //
+ CultureData retVal = GetCultureData(cultureName, useUserOverride);
+ if (retVal != null && (retVal.IsNeutralCulture == false)) return retVal;
+
+ //
+ // Not a specific culture, perhaps it's region-only name
+ // (Remember this isn't a core clr path where that's not supported)
+ //
+
+ // If it was neutral remember that so that RegionInfo() can throw the right exception
+ CultureData neutral = retVal;
+
+ // Try the hash table next
+ String hashName = AnsiToLower(useUserOverride ? cultureName : cultureName + '*');
+ Dictionary<String, CultureData> tempHashTable = s_cachedRegions;
+ if (tempHashTable == null)
+ {
+ // No table yet, make a new one
+ tempHashTable = new Dictionary<String, CultureData>();
+ }
+ else
+ {
+ // Check the hash table
+ lock (((ICollection)tempHashTable).SyncRoot)
+ {
+ tempHashTable.TryGetValue(hashName, out retVal);
+ }
+ if (retVal != null)
+ {
+ return retVal;
+ }
+ }
+
+ //
+ // Not found in the hash table, look it up the hard way
+ //
+#if !FEATURE_CORECLR
+#if FEATURE_WIN32_REGISTRY
+ // First try the registry in case there are overrides of our table
+ try
+ {
+ // Open in read-only mode.
+ // Use InternalOpenSubKey so that we avoid the security check.
+ Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.InternalOpenSubKey(s_RegionKey, false);
+
+ if (key != null)
+ {
+ try
+ {
+ Object value = key.InternalGetValue(cultureName, null, false, false);
+
+ if (value != null)
+ {
+ // Get the name of the locale to try.
+ String specificForRegion = value.ToString();
+
+ // See if it's real
+ retVal = GetCultureData(specificForRegion, useUserOverride);
+ }
+ }
+ finally
+ {
+ key.Close();
+ }
+ }
+ }
+ // If this fails for any reason, we'll just ignore it, likely it just isn't there.
+ catch (ObjectDisposedException) { }
+ catch (ArgumentException) { }
+#endif // FEATURE_WIN32_REGISTRY
+#endif // !FEATURE_CORECLR
+
+ // If not a valid mapping from the registry we'll have to try the hard coded table
+ if (retVal == null || (retVal.IsNeutralCulture == true))
+ {
+ // Not a valid mapping, try the hard coded table
+ if (RegionNames.ContainsKey(cultureName))
+ {
+ // Make sure we can get culture data for it
+ retVal = GetCultureData(RegionNames[cultureName], useUserOverride);
+ }
+ }
+
+ // If not found in the hard coded table we'll have to find a culture that works for us
+ if (retVal == null || (retVal.IsNeutralCulture == true))
+ {
+ // Not found in the hard coded table, need to see if we can find a culture that works for us
+ // Not a real culture name, see if it matches a region name
+ // (we just return the first culture we match)
+ CultureInfo[] specifics = SpecificCultures;
+ for (int i = 0; i < specifics.Length; i++)
+ {
+ if (String.Compare(specifics[i].m_cultureData.SREGIONNAME, cultureName, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ // Matched, use this culture
+ retVal = specifics[i].m_cultureData;
+ break;
+ }
+ }
+ }
+
+ // If we found one we can use, then cash it for next time
+ if (retVal != null && (retVal.IsNeutralCulture == false))
+ {
+ // first add it to the cache
+ lock (((ICollection)tempHashTable).SyncRoot)
+ {
+ tempHashTable[hashName] = retVal;
+ }
+
+ // Copy the hashtable to the corresponding member variables. This will potentially overwrite
+ // new tables simultaneously created by a new thread, but maximizes thread safety.
+ s_cachedRegions = tempHashTable;
+ }
+ else
+ {
+ // Unable to find a matching culture/region, return null or neutral
+ // (regionInfo throws a more specific exception on neutrals)
+ retVal = neutral;
+ }
+
+ // Return the found culture to use, null, or the neutral culture.
+ return retVal;
+ }
+
+#if FEATURE_USE_LCID
+ // Obtain locale name from LCID
+ // NOTE: This will get neutral names, unlike the OS API
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String LCIDToLocaleName(int lcid);
+
+ // We'd rather people use the named version since this doesn't allow custom locales
+ internal static CultureData GetCultureData(int culture, bool bUseUserOverride)
+ {
+ String localeName = null;
+ CultureData retVal = null;
+
+#if !FEATURE_CORECLR
+ // If V2 legacy sort is requested, then provide deprecated alternate sorts
+ if (CompareInfo.IsLegacy20SortingBehaviorRequested)
+ {
+ switch (culture)
+ {
+ case 0x00010412:
+ localeName = "ko-KR_unicod";
+ break;
+ case 0x00010411:
+ localeName = "ja-JP_unicod";
+ break;
+ case 0x00020c04:
+ localeName = "zh-HK_stroke";
+ break;
+ }
+ }
+#endif
+
+ if (localeName == null)
+ {
+ // Convert the lcid to a name, then use that
+ // Note that this'll return neutral names (unlike Vista native API)
+ localeName = LCIDToLocaleName(culture);
+ }
+
+ // If its not valid, then throw
+ if (String.IsNullOrEmpty(localeName))
+ {
+ // Could be valid for Invariant
+ if (culture == 0x007f)
+ return Invariant;
+ }
+ else
+ {
+#if !FEATURE_CORECLR
+ switch (localeName)
+ {
+ // for compatibility with Whidbey, when requesting
+ // a locale from LCID, return the old localeName
+ case "zh-Hans":
+ localeName = "zh-CHS";
+ break;
+ case "zh-Hant":
+ localeName = "zh-CHT";
+ break;
+ }
+#endif
+ // Valid name, use it
+ retVal = GetCultureData(localeName, bUseUserOverride);
+ }
+
+ // If not successful, throw
+ if (retVal == null)
+ throw new CultureNotFoundException(
+ "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
+
+ // Return the one we found
+ return retVal;
+ }
+#endif
+
+ // Clear our internal caches
+ internal static void ClearCachedData()
+ {
+ s_cachedCultures = null;
+ s_cachedRegions = null;
+ s_replacementCultureNames = null;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static CultureInfo[] GetCultures(CultureTypes types)
+ {
+ // Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
+#pragma warning disable 618
+ // Validate flags
+ if ((int)types <= 0 || ((int)types & (int)~(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures |
+ CultureTypes.InstalledWin32Cultures | CultureTypes.UserCustomCulture |
+ CultureTypes.ReplacementCultures | CultureTypes.WindowsOnlyCultures |
+ CultureTypes.FrameworkCultures)) != 0)
+ {
+ throw new ArgumentOutOfRangeException(
+ "types",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), CultureTypes.NeutralCultures, CultureTypes.FrameworkCultures));
+ }
+
+ //
+ // CHANGE FROM Whidbey
+ //
+ // We have deprecated CultureTypes.FrameworkCultures.
+ // When this enum is used, we will enumerate Whidbey framework cultures (for compatibility).
+ //
+
+ // We have deprecated CultureTypes.WindowsOnlyCultures.
+ // When this enum is used, we will return an empty array for this enum.
+ if ((types & CultureTypes.WindowsOnlyCultures) != 0)
+ {
+ // Remove the enum as it is an no-op.
+ types &= (~CultureTypes.WindowsOnlyCultures);
+ }
+
+ String[] cultureNames = null;
+
+ //
+ // Call nativeEnumCultureNames() to get a string array of culture names based on the specified
+ // enumeration type.
+ //
+ // nativeEnumCultureNames is a QCall. We need to use a reference to return the string array
+ // allocated from the QCall. That ref has to be wrapped as object handle.
+ // See vm\qcall.h for details in QCall.
+ //
+
+ if (nativeEnumCultureNames((int)types, JitHelpers.GetObjectHandleOnStack(ref cultureNames)) == 0)
+ {
+ return new CultureInfo[0];
+ }
+
+ int arrayLength = cultureNames.Length;
+
+ if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
+ {
+ arrayLength += 2;
+ }
+
+ CultureInfo[] cultures = new CultureInfo[arrayLength];
+
+ for (int i = 0; i < cultureNames.Length; i++)
+ {
+ cultures[i] = new CultureInfo(cultureNames[i]);
+ }
+
+ if ((types & (CultureTypes.NeutralCultures | CultureTypes.FrameworkCultures)) != 0) // add zh-CHT and zh-CHS
+ {
+ Contract.Assert(arrayLength == cultureNames.Length + 2, "CultureData.nativeEnumCultureNames() Incorrect array size");
+ cultures[cultureNames.Length] = new CultureInfo("zh-CHS");
+ cultures[cultureNames.Length + 1] = new CultureInfo("zh-CHT");
+ }
+
+#pragma warning restore 618
+
+ return cultures;
+ }
+
+ internal static volatile CultureInfo[] specificCultures;
+
+ private static CultureInfo[] SpecificCultures
+ {
+ get
+ {
+ if (specificCultures == null)
+ specificCultures = GetCultures(CultureTypes.SpecificCultures);
+
+ return specificCultures;
+ }
+ }
+
+ internal bool IsReplacementCulture
+ {
+ get
+ {
+ return IsReplacementCultureName(this.SNAME);
+ }
+ }
+
+ internal static volatile String[] s_replacementCultureNames;
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Cache for the known replacement cultures.
+ // This is used by CultureInfo.CultureType to check if a culture is a
+ // replacement culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static bool IsReplacementCultureName(String name)
+ {
+ Contract.Assert(name != null, "IsReplacementCultureName(): name should not be null");
+ String[] replacementCultureNames = s_replacementCultureNames;
+ if (replacementCultureNames == null)
+ {
+ if (nativeEnumCultureNames((int)CultureTypes.ReplacementCultures, JitHelpers.GetObjectHandleOnStack(ref replacementCultureNames)) == 0)
+ {
+ return false;
+ }
+
+ // Even if we don't have any replacement cultures, the returned replacementCultureNames will still an empty string array, not null.
+ Contract.Assert(name != null, "IsReplacementCultureName(): replacementCultureNames should not be null");
+ Array.Sort(replacementCultureNames);
+ s_replacementCultureNames = replacementCultureNames;
+ }
+ return Array.BinarySearch(replacementCultureNames, name) >= 0;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // All the accessors
+ //
+ // Accessors for our data object items
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ ///////////
+ // Identity //
+ ///////////
+
+ // The real name used to construct the locale (ie: de-DE_phoneb)
+ internal String CultureName
+ {
+ get
+ {
+ Contract.Assert(this.sRealName != null, "[CultureData.CultureName] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
+ // since windows doesn't know about zh-CHS and zh-CHT,
+ // we leave sRealName == zh-Hanx but we still need to
+ // pretend that it was zh-CHX.
+ switch (this.sName)
+ {
+ case "zh-CHS":
+ case "zh-CHT":
+ return this.sName;
+ }
+ return this.sRealName;
+ }
+ }
+
+ // Are overrides enabled?
+ internal bool UseUserOverride
+ {
+ get
+ {
+ return this.bUseOverrides;
+ }
+ }
+
+ // locale name (ie: de-DE, NO sort information)
+ internal String SNAME
+ {
+ get
+ {
+ // Contract.Assert(this.sName != null,
+ // "[CultureData.SNAME] Expected this.sName to be populated by COMNlsInfo::nativeInitCultureData already");
+ if (this.sName == null)
+ {
+ this.sName = String.Empty;
+ }
+ return this.sName;
+ }
+ }
+
+ // Parent name (which may be a custom locale/culture)
+ internal String SPARENT
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sParent == null)
+ {
+ // Ask using the real name, so that we get parents of neutrals
+ this.sParent = DoGetLocaleInfo(this.sRealName, LOCALE_SPARENT);
+
+#if !FEATURE_CORECLR
+ // for compatibility, the chain should be:
+ // zh-CN -> zh-CHS -> zh-Hans -> zh
+ // zh-TW -> zh-CHT -> zh-Hant -> zh
+ Contract.Assert(this.sName != "zh-CHS" && this.sName != "zh-CHT",
+ "sParent should have been initialized for zh-CHS and zh-CHT when they were constructed, otherwise we get recursion");
+ switch (this.sParent)
+ {
+ case "zh-Hans":
+ this.sParent = "zh-CHS";
+ break;
+ case "zh-Hant":
+ this.sParent = "zh-CHT";
+ break;
+ }
+#endif
+
+ }
+ return this.sParent;
+ }
+ }
+
+ // Localized pretty name for this locale (ie: Inglis (estados Unitos))
+ internal String SLOCALIZEDDISPLAYNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sLocalizedDisplayName == null)
+ {
+#if !FEATURE_CORECLR
+ String resourceKey = "Globalization.ci_" + this.sName;
+ if (IsResourcePresent(resourceKey))
+ {
+ this.sLocalizedDisplayName = Environment.GetResourceString(resourceKey);
+ }
+#endif
+ // If it hasn't been found (Windows 8 and up), fallback to the system
+ if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ this.sLocalizedDisplayName = this.SLOCALIZEDLANGUAGE;
+ }
+ else
+ {
+ // We have to make the neutral distinction in case the OS returns a specific name
+ if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name))
+ {
+ this.sLocalizedDisplayName = DoGetLocaleInfo(LOCALE_SLOCALIZEDDISPLAYNAME);
+ }
+ if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
+ {
+ this.sLocalizedDisplayName = this.SNATIVEDISPLAYNAME;
+ }
+ }
+ }
+ }
+ return this.sLocalizedDisplayName;
+ }
+ }
+
+ // English pretty name for this locale (ie: English (United States))
+ internal String SENGDISPLAYNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sEnglishDisplayName == null)
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ this.sEnglishDisplayName = this.SENGLISHLANGUAGE;
+#if !FEATURE_CORECLR
+ // differentiate the legacy display names
+ switch (this.sName)
+ {
+ case "zh-CHS":
+ case "zh-CHT":
+ this.sEnglishDisplayName += " Legacy";
+ break;
+ }
+#endif
+
+ }
+ else
+ {
+ this.sEnglishDisplayName = DoGetLocaleInfo(LOCALE_SENGLISHDISPLAYNAME);
+
+ // if it isn't found build one:
+ if (String.IsNullOrEmpty(this.sEnglishDisplayName))
+ {
+ // Our existing names mostly look like:
+ // "English" + "United States" -> "English (United States)"
+ // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
+ if (this.SENGLISHLANGUAGE.EndsWith(')'))
+ {
+ // "Azeri (Latin)" + "Azerbaijan" -> "Azeri (Latin, Azerbaijan)"
+ this.sEnglishDisplayName =
+ this.SENGLISHLANGUAGE.Substring(0, this.sEnglishLanguage.Length - 1) +
+ ", " + this.SENGCOUNTRY + ")";
+ }
+ else
+ {
+ // "English" + "United States" -> "English (United States)"
+ this.sEnglishDisplayName = this.SENGLISHLANGUAGE + " (" + this.SENGCOUNTRY + ")";
+ }
+ }
+ }
+ }
+ return this.sEnglishDisplayName;
+ }
+ }
+
+ // Native pretty name for this locale (ie: Deutsch (Deutschland))
+ internal String SNATIVEDISPLAYNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNativeDisplayName == null)
+ {
+ // If its neutral use the language name
+ if (this.IsNeutralCulture)
+ {
+ this.sNativeDisplayName = this.SNATIVELANGUAGE;
+#if !FEATURE_CORECLR
+ // differentiate the legacy display names
+ switch (this.sName)
+ {
+ case "zh-CHS":
+ this.sNativeDisplayName += " \u65E7\u7248";
+ break;
+ case "zh-CHT":
+ this.sNativeDisplayName += " \u820A\u7248";
+ break;
+ }
+#endif
+ }
+ else
+ {
+#if !FEATURE_CORECLR
+ if (IsIncorrectNativeLanguageForSinhala())
+ {
+ // work around bug in Windows 7 for native name of Sinhala
+ this.sNativeDisplayName ="\x0dc3\x0dd2\x0d82\x0dc4\x0dbd (\x0DC1\x0DCA\x200D\x0DBB\x0DD3\x0020\x0DBD\x0D82\x0D9A\x0DCF)";
+ }
+ else
+#endif
+ {
+ this.sNativeDisplayName = DoGetLocaleInfo(LOCALE_SNATIVEDISPLAYNAME);
+ }
+
+ // if it isn't found build one:
+ if (String.IsNullOrEmpty(this.sNativeDisplayName))
+ {
+ // These should primarily be "Deutsch (Deutschland)" type names
+ this.sNativeDisplayName = this.SNATIVELANGUAGE + " (" + this.SNATIVECOUNTRY + ")";
+ }
+ }
+ }
+ return this.sNativeDisplayName;
+ }
+ }
+
+ // The culture name to be used in CultureInfo.CreateSpecificCulture()
+ internal String SSPECIFICCULTURE
+ {
+ get
+ {
+ // This got populated when ComNlsInfo::nativeInitCultureData told us we had a culture
+ Contract.Assert(this.sSpecificCulture != null, "[CultureData.SSPECIFICCULTURE] Expected this.sSpecificCulture to be populated by COMNlsInfo::nativeInitCultureData already");
+ return this.sSpecificCulture;
+ }
+ }
+
+ /////////////
+ // Language //
+ /////////////
+
+ // iso 639 language name, ie: en
+ internal String SISO639LANGNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sISO639Language == null)
+ {
+ this.sISO639Language = DoGetLocaleInfo(LOCALE_SISO639LANGNAME);
+ }
+ return this.sISO639Language;
+ }
+ }
+
+ // iso 639 language name, ie: eng
+ internal String SISO639LANGNAME2
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sISO639Language2 == null)
+ {
+ this.sISO639Language2 = DoGetLocaleInfo(LOCALE_SISO639LANGNAME2);
+ }
+ return this.sISO639Language2;
+ }
+ }
+
+ // abbreviated windows language name (ie: enu) (non-standard, avoid this)
+ internal String SABBREVLANGNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sAbbrevLang == null)
+ {
+ this.sAbbrevLang = DoGetLocaleInfo(LOCALE_SABBREVLANGNAME);
+ }
+ return this.sAbbrevLang;
+ }
+ }
+
+ // Localized name for this language (Windows Only) ie: Inglis
+ // This is only valid for Windows 8 and higher neutrals:
+ internal String SLOCALIZEDLANGUAGE
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sLocalizedLanguage == null)
+ {
+ if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name))
+ {
+ this.sLocalizedLanguage = DoGetLocaleInfo(LOCALE_SLOCALIZEDLANGUAGENAME);
+ }
+ // Some OS's might not have this resource or LCTYPE
+ if (String.IsNullOrEmpty(this.sLocalizedLanguage))
+ {
+ this.sLocalizedLanguage = SNATIVELANGUAGE;
+ }
+ }
+
+ return this.sLocalizedLanguage;
+ }
+ }
+
+ // English name for this language (Windows Only) ie: German
+ internal String SENGLISHLANGUAGE
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sEnglishLanguage == null)
+ {
+ this.sEnglishLanguage = DoGetLocaleInfo(LOCALE_SENGLISHLANGUAGENAME);
+ }
+ return this.sEnglishLanguage;
+ }
+ }
+
+ // Native name of this language (Windows Only) ie: Deutsch
+ internal String SNATIVELANGUAGE
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNativeLanguage == null)
+ {
+#if !FEATURE_CORECLR
+ if (IsIncorrectNativeLanguageForSinhala())
+ {
+ this.sNativeLanguage = "\x0dc3\x0dd2\x0d82\x0dc4\x0dbd";
+ }
+ else
+#endif
+ {
+ this.sNativeLanguage = DoGetLocaleInfo(LOCALE_SNATIVELANGUAGENAME);
+ }
+ }
+ return this.sNativeLanguage;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ private bool IsIncorrectNativeLanguageForSinhala()
+ {
+ return IsOsWin7OrPrior()
+ && (sName == "si-LK" || sName == "si")
+ && !IsReplacementCulture;
+ }
+#endif
+
+ ///////////
+ // Region //
+ ///////////
+
+ // region name (eg US)
+ internal String SREGIONNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sRegionName == null)
+ {
+ this.sRegionName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME);
+ }
+ return this.sRegionName;
+ }
+ }
+
+ // (user can override) country code (RegionInfo)
+ internal int ICOUNTRY
+ {
+ get
+ {
+ return DoGetLocaleInfoInt(LOCALE_ICOUNTRY);
+ }
+ }
+
+ // GeoId
+ internal int IGEOID
+ {
+ get
+ {
+ if (this.iGeoId == undef)
+ {
+ this.iGeoId = DoGetLocaleInfoInt(LOCALE_IGEOID);
+ }
+ return this.iGeoId;
+ }
+ }
+
+ // localized name for the country
+ internal string SLOCALIZEDCOUNTRY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sLocalizedCountry == null)
+ {
+#if !FEATURE_CORECLR
+ String resourceKey = "Globalization.ri_" + this.SREGIONNAME;
+ if (IsResourcePresent(resourceKey))
+ {
+ this.sLocalizedCountry = Environment.GetResourceString(resourceKey);
+ }
+#endif
+ // If it hasn't been found (Windows 8 and up), fallback to the system
+ if (String.IsNullOrEmpty(this.sLocalizedCountry))
+ {
+ // We have to make the neutral distinction in case the OS returns a specific name
+ if (CultureInfo.UserDefaultUICulture.Name.Equals(Thread.CurrentThread.CurrentUICulture.Name))
+ {
+ this.sLocalizedCountry = DoGetLocaleInfo(LOCALE_SLOCALIZEDCOUNTRYNAME);
+ }
+ if (String.IsNullOrEmpty(this.sLocalizedDisplayName))
+ {
+ this.sLocalizedCountry = SNATIVECOUNTRY;
+ }
+ }
+ }
+ return this.sLocalizedCountry;
+ }
+ }
+
+ // english country name (RegionInfo) ie: Germany
+ internal String SENGCOUNTRY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sEnglishCountry == null)
+ {
+ this.sEnglishCountry = DoGetLocaleInfo(LOCALE_SENGLISHCOUNTRYNAME);
+ }
+ return this.sEnglishCountry;
+ }
+ }
+
+ // native country name (RegionInfo) ie: Deutschland
+ internal String SNATIVECOUNTRY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNativeCountry == null)
+ {
+ this.sNativeCountry = DoGetLocaleInfo(LOCALE_SNATIVECOUNTRYNAME);
+ }
+ return this.sNativeCountry;
+ }
+ }
+
+ // ISO 3166 Country Name
+ internal String SISO3166CTRYNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sISO3166CountryName == null)
+ {
+ this.sISO3166CountryName = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME);
+ }
+ return this.sISO3166CountryName;
+ }
+ }
+
+ // ISO 3166 Country Name
+ internal String SISO3166CTRYNAME2
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sISO3166CountryName2 == null)
+ {
+ this.sISO3166CountryName2 = DoGetLocaleInfo(LOCALE_SISO3166CTRYNAME2);
+ }
+ return this.sISO3166CountryName2;
+ }
+ }
+
+ // abbreviated Country Name (windows version, non-standard, avoid)
+ internal String SABBREVCTRYNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sAbbrevCountry == null)
+ {
+ this.sAbbrevCountry = DoGetLocaleInfo(LOCALE_SABBREVCTRYNAME);
+ }
+ return this.sAbbrevCountry;
+ }
+ }
+
+ // Default Country
+ private int IDEFAULTCOUNTRY
+ {
+ get
+ {
+ return DoGetLocaleInfoInt(LOCALE_IDEFAULTCOUNTRY);
+ }
+ }
+
+ // Console fallback name (ie: locale to use for console apps for unicode-only locales)
+ internal int IINPUTLANGUAGEHANDLE
+ {
+ get
+ {
+ if (this.iInputLanguageHandle == undef)
+ {
+ if (IsSupplementalCustomCulture)
+ {
+ this.iInputLanguageHandle = 0x0409;
+ }
+ else
+ {
+ // Input Language is same as LCID for built-in cultures
+ this.iInputLanguageHandle = this.ILANGUAGE;
+ }
+ }
+ return this.iInputLanguageHandle;
+ }
+ }
+
+ // Console fallback name (ie: locale to use for console apps for unicode-only locales)
+ internal String SCONSOLEFALLBACKNAME
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sConsoleFallbackName == null)
+ {
+ string consoleFallbackName = DoGetLocaleInfo(LOCALE_SCONSOLEFALLBACKNAME);
+ if (consoleFallbackName == "es-ES_tradnl")
+ {
+ consoleFallbackName = "es-ES";
+ }
+ this.sConsoleFallbackName = consoleFallbackName;
+ }
+ return this.sConsoleFallbackName;
+ }
+ }
+
+ /////////////
+ // Numbers //
+ ////////////
+
+ // internal String sPositiveSign ; // (user can override) positive sign
+ // internal String sNegativeSign ; // (user can override) negative sign
+ // internal String[] saNativeDigits ; // (user can override) native characters for digits 0-9
+ // internal int iDigitSubstitution ; // (user can override) Digit substitution 0=context, 1=none/arabic, 2=Native/national (2 seems to be unused) (Windows Only)
+ // internal int iDigits ; // (user can override) number of fractional digits
+ // internal int iNegativeNumber ; // (user can override) negative number format
+
+ // Leading zeroes
+ private bool ILEADINGZEROS
+ {
+ get
+ {
+ return (DoGetLocaleInfoInt(LOCALE_ILZERO) == 1);
+ }
+ }
+
+
+ // (user can override) grouping of digits
+ internal int[] WAGROUPING
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.waGrouping == null || UseUserOverride)
+ {
+ this.waGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SGROUPING));
+ }
+ return this.waGrouping;
+ }
+ }
+
+
+ // internal String sDecimalSeparator ; // (user can override) decimal separator
+ // internal String sThousandSeparator ; // (user can override) thousands separator
+
+ // Not a Number
+ internal String SNAN
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNaN == null)
+ {
+ this.sNaN = DoGetLocaleInfo(LOCALE_SNAN);
+ }
+ return this.sNaN;
+ }
+ }
+
+ // + Infinity
+ internal String SPOSINFINITY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sPositiveInfinity == null)
+ {
+ this.sPositiveInfinity = DoGetLocaleInfo(LOCALE_SPOSINFINITY);
+ }
+ return this.sPositiveInfinity;
+ }
+ }
+
+ // - Infinity
+ internal String SNEGINFINITY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNegativeInfinity == null)
+ {
+ this.sNegativeInfinity = DoGetLocaleInfo(LOCALE_SNEGINFINITY);
+ }
+ return this.sNegativeInfinity;
+ }
+ }
+
+
+ ////////////
+ // Percent //
+ ///////////
+
+ // Negative Percent (0-3)
+ internal int INEGATIVEPERCENT
+ {
+ get
+ {
+ if (this.iNegativePercent == undef)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ this.iNegativePercent = DoGetLocaleInfoInt(LOCALE_INEGATIVEPERCENT);
+ }
+ return this.iNegativePercent;
+ }
+ }
+
+ // Positive Percent (0-11)
+ internal int IPOSITIVEPERCENT
+ {
+ get
+ {
+ if (this.iPositivePercent == undef)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ this.iPositivePercent = DoGetLocaleInfoInt(LOCALE_IPOSITIVEPERCENT);
+ }
+ return this.iPositivePercent;
+ }
+ }
+
+ // Percent (%) symbol
+ internal String SPERCENT
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sPercent == null)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ this.sPercent = DoGetLocaleInfo(LOCALE_SPERCENT);
+ }
+ return this.sPercent;
+ }
+ }
+
+ // PerMille (‰) symbol
+ internal String SPERMILLE
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sPerMille == null)
+ {
+ // Note that <= Windows Vista this is synthesized by native code
+ this.sPerMille = DoGetLocaleInfo(LOCALE_SPERMILLE);
+ }
+ return this.sPerMille;
+ }
+ }
+
+ /////////////
+ // Currency //
+ /////////////
+
+ // (user can override) local monetary symbol, eg: $
+ internal String SCURRENCY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sCurrency == null || UseUserOverride)
+ {
+ this.sCurrency = DoGetLocaleInfo(LOCALE_SCURRENCY);
+ }
+ return this.sCurrency;
+ }
+ }
+
+ // international monetary symbol (RegionInfo), eg: USD
+ internal String SINTLSYMBOL
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sIntlMonetarySymbol == null)
+ {
+ this.sIntlMonetarySymbol = DoGetLocaleInfo(LOCALE_SINTLSYMBOL);
+ }
+ return this.sIntlMonetarySymbol;
+ }
+ }
+
+ // English name for this currency (RegionInfo), eg: US Dollar
+ internal String SENGLISHCURRENCY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sEnglishCurrency == null)
+ {
+ this.sEnglishCurrency = DoGetLocaleInfo(LOCALE_SENGCURRNAME);
+ }
+ return this.sEnglishCurrency;
+ }
+ }
+
+ // Native name for this currency (RegionInfo), eg: Schweiz Frank
+ internal String SNATIVECURRENCY
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sNativeCurrency == null)
+ {
+ this.sNativeCurrency = DoGetLocaleInfo(LOCALE_SNATIVECURRNAME);
+ }
+ return this.sNativeCurrency;
+ }
+ }
+
+ // internal int iCurrencyDigits ; // (user can override) # local monetary fractional digits
+ // internal int iCurrency ; // (user can override) positive currency format
+ // internal int iNegativeCurrency ; // (user can override) negative currency format
+
+ // (user can override) monetary grouping of digits
+ internal int[] WAMONGROUPING
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.waMonetaryGrouping == null || UseUserOverride)
+ {
+ this.waMonetaryGrouping = ConvertWin32GroupString(DoGetLocaleInfo(LOCALE_SMONGROUPING));
+ }
+ return this.waMonetaryGrouping;
+ }
+ }
+
+ // internal String sMonetaryDecimal ; // (user can override) monetary decimal separator
+ // internal String sMonetaryThousand ; // (user can override) monetary thousands separator
+
+ /////////
+ // Misc //
+ /////////
+
+ // (user can override) system of measurement 0=metric, 1=US (RegionInfo)
+ internal int IMEASURE
+ {
+ get
+ {
+ if (this.iMeasure == undef || UseUserOverride)
+ {
+ this.iMeasure = DoGetLocaleInfoInt(LOCALE_IMEASURE);
+ }
+ return this.iMeasure;
+ }
+ }
+
+ // (user can override) list Separator
+ internal String SLIST
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sListSeparator == null || UseUserOverride)
+ {
+ this.sListSeparator = DoGetLocaleInfo(LOCALE_SLIST);
+ }
+ return this.sListSeparator;
+ }
+ }
+
+ // Paper size
+ private int IPAPERSIZE
+ {
+ get
+ {
+ return DoGetLocaleInfoInt(LOCALE_IPAPERSIZE);
+ }
+ }
+
+ ////////////////////////////
+ // Calendar/Time (Gregorian) //
+ ////////////////////////////
+
+ // (user can override) AM designator
+ internal String SAM1159
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sAM1159 == null || UseUserOverride)
+ {
+ this.sAM1159 = DoGetLocaleInfo(LOCALE_S1159);
+ }
+ return this.sAM1159;
+ }
+ }
+
+ // (user can override) PM designator
+ internal String SPM2359
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.sPM2359 == null || UseUserOverride)
+ {
+ this.sPM2359 = DoGetLocaleInfo(LOCALE_S2359);
+ }
+ return this.sPM2359;
+ }
+ }
+
+ // (user can override) time format
+ internal String[] LongTimes
+ {
+ get
+ {
+ if (this.saLongTimes == null || UseUserOverride)
+ {
+ String[] longTimes = DoEnumTimeFormats();
+ if (longTimes == null || longTimes.Length == 0)
+ {
+ this.saLongTimes = Invariant.saLongTimes;
+ }
+ else
+ {
+ this.saLongTimes = longTimes;
+ }
+ }
+ return this.saLongTimes;
+ }
+ }
+
+ // short time format
+ // Short times (derived from long times format)
+ internal String[] ShortTimes
+ {
+ get
+ {
+ if (this.saShortTimes == null || UseUserOverride)
+ {
+ // Try to get the short times from the OS/culture.dll
+ String[] shortTimes = DoEnumShortTimeFormats();
+
+ if (shortTimes == null || shortTimes.Length == 0)
+ {
+ //
+ // If we couldn't find short times, then compute them from long times
+ // (eg: CORECLR on < Win7 OS & fallback for missing culture.dll)
+ //
+ shortTimes = DeriveShortTimesFromLong();
+ }
+
+ // Found short times, use them
+ this.saShortTimes = shortTimes;
+ }
+ return this.saShortTimes;
+ }
+ }
+
+ private string[] DeriveShortTimesFromLong()
+ {
+ // Our logic is to look for h,H,m,s,t. If we find an s, then we check the string
+ // between it and the previous marker, if any. If its a short, unescaped separator,
+ // then we don't retain that part.
+ // We then check after the ss and remove anything before the next h,H,m,t...
+ string[] shortTimes = new string[LongTimes.Length];
+
+ for (int i = 0; i < LongTimes.Length; i++)
+ {
+ shortTimes[i] = StripSecondsFromPattern(LongTimes[i]);
+ }
+ return shortTimes;
+ }
+
+ private static string StripSecondsFromPattern(string time)
+ {
+ bool bEscape = false;
+ int iLastToken = -1;
+
+ // Find the seconds
+ for (int j = 0; j < time.Length; j++)
+ {
+ // Change escape mode?
+ if (time[j] == '\'')
+ {
+ // Continue
+ bEscape = !bEscape;
+ continue;
+ }
+
+ // See if there was a single \
+ if (time[j] == '\\')
+ {
+ // Skip next char
+ j++;
+ continue;
+ }
+
+ if (bEscape)
+ {
+ continue;
+ }
+
+ switch (time[j])
+ {
+ // Check for seconds
+ case 's':
+ // Found seconds, see if there was something unescaped and short between
+ // the last marker and the seconds. Windows says separator can be a
+ // maximum of three characters (without null)
+ // If 1st or last characters were ', then ignore it
+ if ((j - iLastToken) <= 4 && (j - iLastToken) > 1 &&
+ (time[iLastToken + 1] != '\'') &&
+ (time[j - 1] != '\''))
+ {
+ // There was something there we want to remember
+ if (iLastToken >= 0)
+ {
+ j = iLastToken + 1;
+ }
+ }
+
+ bool containsSpace;
+ int endIndex = GetIndexOfNextTokenAfterSeconds(time, j, out containsSpace);
+ StringBuilder sb = new StringBuilder(time.Substring(0, j));
+ if (containsSpace)
+ {
+ sb.Append(' ');
+ }
+ sb.Append(time.Substring(endIndex));
+ time = sb.ToString();
+ break;
+ case 'm':
+ case 'H':
+ case 'h':
+ iLastToken = j;
+ break;
+ }
+ }
+ return time;
+ }
+
+ private static int GetIndexOfNextTokenAfterSeconds(string time, int index, out bool containsSpace)
+ {
+ bool bEscape = false;
+ containsSpace = false;
+ for (; index < time.Length; index++)
+ {
+ switch (time[index])
+ {
+ case '\'':
+ bEscape = !bEscape;
+ continue;
+ case '\\':
+ index++;
+ if (time[index] == ' ')
+ {
+ containsSpace = true;
+ }
+ continue;
+ case ' ':
+ containsSpace = true;
+ break;
+ case 't':
+ case 'm':
+ case 'H':
+ case 'h':
+ if (bEscape)
+ {
+ continue;
+ }
+ return index;
+ }
+ }
+ containsSpace = false;
+ return index;
+ }
+
+ // time duration format
+ internal String[] SADURATION
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (this.saDurationFormats == null)
+ {
+ String durationFormat = DoGetLocaleInfo(LOCALE_SDURATION);
+ this.saDurationFormats = new String[] { ReescapeWin32String(durationFormat) };
+ }
+ return this.saDurationFormats;
+ }
+ }
+
+ // (user can override) first day of week
+ internal int IFIRSTDAYOFWEEK
+ {
+ get
+ {
+ if (this.iFirstDayOfWeek == undef || UseUserOverride)
+ {
+ // Have to convert it from windows to .Net formats
+ this.iFirstDayOfWeek = ConvertFirstDayOfWeekMonToSun(DoGetLocaleInfoInt(LOCALE_IFIRSTDAYOFWEEK));
+ }
+ return this.iFirstDayOfWeek;
+ }
+ }
+
+ // (user can override) first week of year
+ internal int IFIRSTWEEKOFYEAR
+ {
+ get
+ {
+ if (this.iFirstWeekOfYear == undef || UseUserOverride)
+ {
+ this.iFirstWeekOfYear = DoGetLocaleInfoInt(LOCALE_IFIRSTWEEKOFYEAR);
+ }
+ return this.iFirstWeekOfYear;
+ }
+ }
+
+ // (user can override default only) short date format
+ internal String[] ShortDates(int calendarId)
+ {
+ return GetCalendar(calendarId).saShortDates;
+ }
+
+ // (user can override default only) long date format
+ internal String[] LongDates(int calendarId)
+ {
+ return GetCalendar(calendarId).saLongDates;
+ }
+
+ // (user can override) date year/month format.
+ internal String[] YearMonths(int calendarId)
+ {
+ return GetCalendar(calendarId).saYearMonths;
+ }
+
+ // day names
+ internal string[] DayNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saDayNames;
+ }
+
+ // abbreviated day names
+ internal string[] AbbreviatedDayNames(int calendarId)
+ {
+ // Get abbreviated day names for this calendar from the OS if necessary
+ return GetCalendar(calendarId).saAbbrevDayNames;
+ }
+
+ // The super short day names
+ internal string[] SuperShortDayNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saSuperShortDayNames;
+ }
+
+ // month names
+ internal string[] MonthNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saMonthNames;
+ }
+
+ // Genitive month names
+ internal string[] GenitiveMonthNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saMonthGenitiveNames;
+ }
+
+ // month names
+ internal string[] AbbreviatedMonthNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saAbbrevMonthNames;
+ }
+
+ // Genitive month names
+ internal string[] AbbreviatedGenitiveMonthNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saAbbrevMonthGenitiveNames;
+ }
+
+ // Leap year month names
+ // Note: This only applies to Hebrew, and it basically adds a "1" to the 6th month name
+ // the non-leap names skip the 7th name in the normal month name array
+ internal string[] LeapYearMonthNames(int calendarId)
+ {
+ return GetCalendar(calendarId).saLeapYearMonthNames;
+ }
+
+ // month/day format (single string, no override)
+ internal String MonthDay(int calendarId)
+ {
+ return GetCalendar(calendarId).sMonthDay;
+ }
+
+
+
+ /////////////
+ // Calendars //
+ /////////////
+
+ // all available calendar type(s), The first one is the default calendar.
+ internal int[] CalendarIds
+ {
+ get
+ {
+ if (this.waCalendars == null)
+ {
+ // We pass in an array of ints, and native side fills it up with count calendars.
+ // We then have to copy that list to a new array of the right size.
+ // Default calendar should be first
+ int[] calendarInts = new int[23];
+ Contract.Assert(this.sWindowsName != null, "[CultureData.CalendarIds] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ int count = CalendarData.nativeGetCalendars(this.sWindowsName, this.bUseOverrides, calendarInts);
+
+ // See if we had a calendar to add.
+ if (count == 0)
+ {
+ // Failed for some reason, just grab Gregorian from Invariant
+ this.waCalendars = Invariant.waCalendars;
+ }
+ else
+ {
+ // The OS may not return calendar 4 for zh-TW, but we've always allowed it.
+ if (this.sWindowsName == "zh-TW")
+ {
+ bool found = false;
+
+ // Do we need to insert calendar 4?
+ for (int i = 0; i < count; i++)
+ {
+ // Stop if we found calendar four
+ if (calendarInts[i] == Calendar.CAL_TAIWAN)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ // If not found then insert it
+ if (!found)
+ {
+ // Insert it as the 2nd calendar
+ count++;
+ // Copy them from the 2nd position to the end, -1 for skipping 1st, -1 for one being added.
+ Array.Copy(calendarInts, 1, calendarInts, 2, 23 - 1 - 1);
+ calendarInts[1] = Calendar.CAL_TAIWAN;
+ }
+ }
+
+ // It worked, remember the list
+ int[] temp = new int[count];
+ Array.Copy(calendarInts, temp, count);
+
+ // Want 1st calendar to be default
+ // Prior to Vista the enumeration didn't have default calendar first
+ // Only a coreclr concern, culture.dll does the right thing.
+#if FEATURE_CORECLR
+ if (temp.Length > 1)
+ {
+ int i = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
+ if (temp[1] == i)
+ {
+ temp[1] = temp[0];
+ temp[0] = i;
+ }
+ }
+#endif
+
+ this.waCalendars = temp;
+ }
+ }
+
+ return this.waCalendars;
+ }
+ }
+
+ // Native calendar names. index of optional calendar - 1, empty if no optional calendar at that number
+ internal String CalendarName(int calendarId)
+ {
+ // Get the calendar
+ return GetCalendar(calendarId).sNativeName;
+ }
+
+ internal CalendarData GetCalendar(int calendarId)
+ {
+ Contract.Assert(calendarId > 0 && calendarId <= CalendarData.MAX_CALENDARS,
+ "[CultureData.GetCalendar] Expect calendarId to be in a valid range");
+
+ // arrays are 0 based, calendarIds are 1 based
+ int calendarIndex = calendarId - 1;
+
+ // Have to have calendars
+ if (calendars == null)
+ {
+ calendars = new CalendarData[CalendarData.MAX_CALENDARS];
+ }
+
+ // we need the following local variable to avoid returning null
+ // when another thread creates a new array of CalendarData (above)
+ // right after we insert the newly created CalendarData (below)
+ CalendarData calendarData = calendars[calendarIndex];
+ // Make sure that calendar has data
+ if (calendarData == null || UseUserOverride)
+ {
+ Contract.Assert(this.sWindowsName != null, "[CultureData.GetCalendar] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ calendarData = new CalendarData(this.sWindowsName, calendarId, this.UseUserOverride);
+#if !FEATURE_CORECLR
+ //Work around issue where Win7 data for MonthDay contains invalid two sets of data separated by semicolon
+ //even though MonthDay is not enumerated
+ if (IsOsWin7OrPrior() && !IsSupplementalCustomCulture && !IsReplacementCulture)
+ {
+ calendarData.FixupWin7MonthDaySemicolonBug();
+ }
+#endif
+ calendars[calendarIndex] = calendarData;
+ }
+
+ return calendarData;
+ }
+
+ internal int CurrentEra(int calendarId)
+ {
+ return GetCalendar(calendarId).iCurrentEra;
+ }
+
+ ///////////////////
+ // Text Information //
+ ///////////////////
+
+ // IsRightToLeft
+ internal bool IsRightToLeft
+ {
+ get
+ {
+ // Returns one of the following 4 reading layout values:
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+ return (this.IREADINGLAYOUT == 1);
+ }
+ }
+
+ // IREADINGLAYOUT
+ // Returns one of the following 4 reading layout values:
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+ //
+ // If exposed as a public API, we'd have an enum with those 4 values
+ private int IREADINGLAYOUT
+ {
+ get
+ {
+ if (this.iReadingLayout == undef)
+ {
+ Contract.Assert(this.sRealName != null, "[CultureData.IsRightToLeft] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
+ this.iReadingLayout = DoGetLocaleInfoInt(LOCALE_IREADINGLAYOUT);
+ }
+
+ return (this.iReadingLayout);
+ }
+ }
+
+ // The TextInfo name never includes that alternate sort and is always specific
+ // For customs, it uses the SortLocale (since the textinfo is not exposed in Win7)
+ // en -> en-US
+ // en-US -> en-US
+ // fj (custom neutral) -> en-US (assuming that en-US is the sort locale for fj)
+ // fj_FJ (custom specific) -> en-US (assuming that en-US is the sort locale for fj-FJ)
+ // es-ES_tradnl -> es-ES
+ internal String STEXTINFO // Text info name to use for text information
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if (this.sTextInfo == null)
+ {
+ // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts.
+ // It is also not supported downlevel without culture.dll.
+ if (IsNeutralCulture || IsSupplementalCustomCulture)
+ {
+ string sortLocale = DoGetLocaleInfo(LOCALE_SSORTLOCALE);
+ this.sTextInfo = GetCultureData(sortLocale, bUseOverrides).SNAME;
+ }
+
+ if (this.sTextInfo == null)
+ {
+ this.sTextInfo = this.SNAME; // removes alternate sort
+ }
+ }
+
+ return this.sTextInfo;
+ }
+ }
+
+ // Compare info name (including sorting key) to use if custom
+ internal String SCOMPAREINFO
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if (this.sCompareInfo == null)
+ {
+ // LOCALE_SSORTLOCALE is broken in Win7 for Alt sorts.
+ // It is also not supported downlevel without culture.dll.
+ // We really only need it for the custom locale case though
+ // since for all other cases, it is the same as sWindowsName
+ if (IsSupplementalCustomCulture)
+ {
+ this.sCompareInfo = DoGetLocaleInfo(LOCALE_SSORTLOCALE);
+ }
+
+ if (this.sCompareInfo == null)
+ {
+ this.sCompareInfo = this.sWindowsName;
+ }
+ }
+
+ return this.sCompareInfo;
+ }
+ }
+
+ internal bool IsSupplementalCustomCulture
+ {
+ get
+ {
+ return IsCustomCultureId(this.ILANGUAGE);
+ }
+ }
+
+ // Typical Scripts for this locale (latn;cyrl; etc)
+
+ private String SSCRIPTS
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (this.sScripts == null)
+ {
+ this.sScripts = DoGetLocaleInfo(LOCALE_SSCRIPTS);
+ }
+ return this.sScripts;
+ }
+ }
+
+ private String SOPENTYPELANGUAGETAG
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return DoGetLocaleInfo(LOCALE_SOPENTYPELANGUAGETAG);
+ }
+ }
+
+ private String FONTSIGNATURE
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (this.fontSignature == null)
+ {
+ this.fontSignature = DoGetLocaleInfo(LOCALE_FONTSIGNATURE);
+ }
+ return this.fontSignature;
+ }
+ }
+
+ private String SKEYBOARDSTOINSTALL
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return DoGetLocaleInfo(LOCALE_SKEYBOARDSTOINSTALL);
+ }
+ }
+
+
+ internal int IDEFAULTANSICODEPAGE // default ansi code page ID (ACP)
+ {
+ get
+ {
+ if (this.iDefaultAnsiCodePage == undef)
+ {
+ this.iDefaultAnsiCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTANSICODEPAGE);
+ }
+ return this.iDefaultAnsiCodePage;
+ }
+ }
+
+ internal int IDEFAULTOEMCODEPAGE // default oem code page ID (OCP or OEM)
+ {
+ get
+ {
+ if (this.iDefaultOemCodePage == undef)
+ {
+ this.iDefaultOemCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTCODEPAGE);
+ }
+ return this.iDefaultOemCodePage;
+ }
+ }
+
+ internal int IDEFAULTMACCODEPAGE // default macintosh code page
+ {
+ get
+ {
+ if (this.iDefaultMacCodePage == undef)
+ {
+ this.iDefaultMacCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTMACCODEPAGE);
+ }
+ return this.iDefaultMacCodePage;
+ }
+ }
+
+ internal int IDEFAULTEBCDICCODEPAGE // default EBCDIC code page
+ {
+ get
+ {
+ if (this.iDefaultEbcdicCodePage == undef)
+ {
+ this.iDefaultEbcdicCodePage = DoGetLocaleInfoInt(LOCALE_IDEFAULTEBCDICCODEPAGE);
+ }
+ return this.iDefaultEbcdicCodePage;
+ }
+ }
+
+ // Obtain locale name from LCID
+ // NOTE: This will get neutral names, unlike the OS API
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int LocaleNameToLCID(String localeName);
+
+ // These are desktop only, not coreclr
+ // locale ID (0409), including sort information
+ internal int ILANGUAGE
+ {
+ get
+ {
+ if (this.iLanguage == 0)
+ {
+ Contract.Assert(this.sRealName != null, "[CultureData.ILANGUAGE] Expected this.sRealName to be populated by COMNlsInfo::nativeInitCultureData already");
+ this.iLanguage = LocaleNameToLCID(this.sRealName);
+ }
+ return this.iLanguage;
+ }
+ }
+
+ internal bool IsWin32Installed
+ {
+ get { return this.bWin32Installed; }
+ }
+
+ internal bool IsFramework
+ {
+ get { return this.bFramework; }
+ }
+
+ ////////////////////
+ // Derived properties //
+ ////////////////////
+
+ internal bool IsNeutralCulture
+ {
+ get
+ {
+ // NlsInfo::nativeInitCultureData told us if we're neutral or not
+ return this.bNeutral;
+ }
+ }
+
+ internal bool IsInvariantCulture
+ {
+ get
+ {
+ return String.IsNullOrEmpty(this.SNAME);
+ }
+ }
+
+ // Get an instance of our default calendar
+ internal Calendar DefaultCalendar
+ {
+ get
+ {
+ int defaultCalId = DoGetLocaleInfoInt(LOCALE_ICALENDARTYPE);
+ if (defaultCalId == 0)
+ {
+ defaultCalId = this.CalendarIds[0];
+ }
+
+ return CultureInfo.GetCalendarInstance(defaultCalId);
+ }
+ }
+
+ // All of our era names
+ internal String[] EraNames(int calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saEraNames;
+ }
+
+ internal String[] AbbrevEraNames(int calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saAbbrevEraNames;
+ }
+
+ internal String[] AbbreviatedEnglishEraNames(int calendarId)
+ {
+ Contract.Assert(calendarId > 0, "[CultureData.saAbbrevEraNames] Expected Calendar.ID > 0");
+
+ return this.GetCalendar(calendarId).saAbbrevEnglishEraNames;
+ }
+
+ // String array DEFAULTS
+ // Note: GetDTFIOverrideValues does the user overrides for these, so we don't have to.
+
+
+ // Time separator (derived from time format)
+ internal String TimeSeparator
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (sTimeSeparator == null || UseUserOverride)
+ {
+ string longTimeFormat = ReescapeWin32String(DoGetLocaleInfo(LOCALE_STIMEFORMAT));
+ if (String.IsNullOrEmpty(longTimeFormat))
+ {
+ longTimeFormat = LongTimes[0];
+ }
+
+ // Compute STIME from time format
+ sTimeSeparator = GetTimeSeparator(longTimeFormat);
+ }
+ return sTimeSeparator;
+ }
+ }
+
+ // Date separator (derived from short date format)
+ internal String DateSeparator(int calendarId)
+ {
+ return GetDateSeparator(ShortDates(calendarId)[0]);
+ }
+
+ //////////////////////////////////////
+ // Helper Functions to get derived properties //
+ //////////////////////////////////////
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Unescape a NLS style quote string
+ //
+ // This removes single quotes:
+ // 'fred' -> fred
+ // 'fred -> fred
+ // fred' -> fred
+ // fred's -> freds
+ //
+ // This removes the first \ of escaped characters:
+ // fred\'s -> fred's
+ // a\\b -> a\b
+ // a\b -> ab
+ //
+ // We don't build the stringbuilder unless we find a ' or a \. If we find a ' or a \, we
+ // always build a stringbuilder because we need to remove the ' or \.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ static private String UnescapeNlsString(String str, int start, int end)
+ {
+ Contract.Requires(str != null);
+ Contract.Requires(start >= 0);
+ Contract.Requires(end >= 0);
+ StringBuilder result = null;
+
+ for (int i = start; i < str.Length && i <= end; i++)
+ {
+ switch (str[i])
+ {
+ case '\'':
+ if (result == null)
+ {
+ result = new StringBuilder(str, start, i - start, str.Length);
+ }
+ break;
+ case '\\':
+ if (result == null)
+ {
+ result = new StringBuilder(str, start, i - start, str.Length);
+ }
+ ++i;
+ if (i < str.Length)
+ {
+ result.Append(str[i]);
+ }
+ break;
+ default:
+ if (result != null)
+ {
+ result.Append(str[i]);
+ }
+ break;
+ }
+ }
+
+ if (result == null)
+ return (str.Substring(start, end - start + 1));
+
+ return (result.ToString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Reescape a Win32 style quote string as a NLS+ style quoted string
+ //
+ // This is also the escaping style used by custom culture data files
+ //
+ // NLS+ uses \ to escape the next character, whether in a quoted string or
+ // not, so we always have to change \ to \\.
+ //
+ // NLS+ uses \' to escape a quote inside a quoted string so we have to change
+ // '' to \' (if inside a quoted string)
+ //
+ // We don't build the stringbuilder unless we find something to change
+ ////////////////////////////////////////////////////////////////////////////
+ static internal String ReescapeWin32String(String str)
+ {
+ // If we don't have data, then don't try anything
+ if (str == null)
+ return null;
+
+ StringBuilder result = null;
+
+ bool inQuote = false;
+ for (int i = 0; i < str.Length; i++)
+ {
+ // Look for quote
+ if (str[i] == '\'')
+ {
+ // Already in quote?
+ if (inQuote)
+ {
+ // See another single quote. Is this '' of 'fred''s' or '''', or is it an ending quote?
+ if (i + 1 < str.Length && str[i + 1] == '\'')
+ {
+ // Found another ', so we have ''. Need to add \' instead.
+ // 1st make sure we have our stringbuilder
+ if (result == null)
+ result = new StringBuilder(str, 0, i, str.Length * 2);
+
+ // Append a \' and keep going (so we don't turn off quote mode)
+ result.Append("\\'");
+ i++;
+ continue;
+ }
+
+ // Turning off quote mode, fall through to add it
+ inQuote = false;
+ }
+ else
+ {
+ // Found beginning quote, fall through to add it
+ inQuote = true;
+ }
+ }
+ // Is there a single \ character?
+ else if (str[i] == '\\')
+ {
+ // Found a \, need to change it to \\
+ // 1st make sure we have our stringbuilder
+ if (result == null)
+ result = new StringBuilder(str, 0, i, str.Length * 2);
+
+ // Append our \\ to the string & continue
+ result.Append("\\\\");
+ continue;
+ }
+
+ // If we have a builder we need to add our character
+ if (result != null)
+ result.Append(str[i]);
+ }
+
+ // Unchanged string? , just return input string
+ if (result == null)
+ return str;
+
+ // String changed, need to use the builder
+ return result.ToString();
+ }
+
+ static internal String[] ReescapeWin32Strings(String[] array)
+ {
+ if (array != null)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ array[i] = ReescapeWin32String(array[i]);
+ }
+ }
+
+ return array;
+ }
+
+ // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement()
+ // and breaking changes here will not show up at build time, only at run time.
+ static private String GetTimeSeparator(String format)
+ {
+ // Time format separator (ie: : in 12:39:00)
+ //
+ // We calculate this from the provided time format
+ //
+
+ //
+ // Find the time separator so that we can pretend we know STIME.
+ //
+ return GetSeparator(format, "Hhms");
+ }
+
+ // NOTE: this method is used through reflection by System.Globalization.CultureXmlParser.ReadDateElement()
+ // and breaking changes here will not show up at build time, only at run time.
+ static private String GetDateSeparator(String format)
+ {
+ // Date format separator (ie: / in 9/1/03)
+ //
+ // We calculate this from the provided short date
+ //
+
+ //
+ // Find the date separator so that we can pretend we know SDATE.
+ //
+ return GetSeparator(format, "dyM");
+ }
+
+ private static string GetSeparator(string format, string timeParts)
+ {
+ int index = IndexOfTimePart(format, 0, timeParts);
+
+ if (index != -1)
+ {
+ // Found a time part, find out when it changes
+ char cTimePart = format[index];
+
+ do
+ {
+ index++;
+ } while (index < format.Length && format[index] == cTimePart);
+
+ int separatorStart = index;
+
+ // Now we need to find the end of the separator
+ if (separatorStart < format.Length)
+ {
+ int separatorEnd = IndexOfTimePart(format, separatorStart, timeParts);
+ if (separatorEnd != -1)
+ {
+ // From [separatorStart, count) is our string, except we need to unescape
+ return UnescapeNlsString(format, separatorStart, separatorEnd - 1);
+ }
+ }
+ }
+
+ return String.Empty;
+ }
+
+ private static int IndexOfTimePart(string format, int startIndex, string timeParts)
+ {
+ Contract.Assert(startIndex >= 0, "startIndex cannot be negative");
+ Contract.Assert(timeParts.IndexOfAny(new char[] { '\'', '\\' }) == -1, "timeParts cannot include quote characters");
+ bool inQuote = false;
+ for (int i = startIndex; i < format.Length; ++i)
+ {
+ // See if we have a time Part
+ if (!inQuote && timeParts.IndexOf(format[i]) != -1)
+ {
+ return i;
+ }
+ switch (format[i])
+ {
+ case '\\':
+ if (i + 1 < format.Length)
+ {
+ ++i;
+ switch (format[i])
+ {
+ case '\'':
+ case '\\':
+ break;
+ default:
+ --i; //backup since we will move over this next
+ break;
+ }
+ }
+ break;
+ case '\'':
+ inQuote = !inQuote;
+ break;
+ }
+ }
+
+ return -1;
+ }
+
+ [System.Security.SecurityCritical]
+ string DoGetLocaleInfo(uint lctype)
+ {
+ Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfo] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ return DoGetLocaleInfo(this.sWindowsName, lctype);
+ }
+
+ // For LOCALE_SPARENT we need the option of using the "real" name (forcing neutral names) instead of the
+ // "windows" name, which can be specific for downlevel (< windows 7) os's.
+ [System.Security.SecurityCritical] // auto-generated
+ string DoGetLocaleInfo(string localeName, uint lctype)
+ {
+ // Fix lctype if we don't want overrides
+ if (!UseUserOverride)
+ {
+ lctype |= LOCALE_NOUSEROVERRIDE;
+ }
+
+ // Ask OS for data
+ Contract.Assert(localeName != null, "[CultureData.DoGetLocaleInfo] Expected localeName to be not be null");
+ string result = CultureInfo.nativeGetLocaleInfoEx(localeName, lctype);
+ if (result == null)
+ {
+ // Failed, just use empty string
+ result = String.Empty;
+ }
+
+ return result;
+ }
+
+ int DoGetLocaleInfoInt(uint lctype)
+ {
+ // Fix lctype if we don't want overrides
+ if (!UseUserOverride)
+ {
+ lctype |= LOCALE_NOUSEROVERRIDE;
+ }
+
+ // Ask OS for data, note that we presume it returns success, so we have to know that
+ // sWindowsName is valid before calling.
+ Contract.Assert(this.sWindowsName != null, "[CultureData.DoGetLocaleInfoInt] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ int result = CultureInfo.nativeGetLocaleInfoExInt(this.sWindowsName, lctype);
+
+ return result;
+ }
+
+ String[] DoEnumTimeFormats()
+ {
+ // Note that this gets overrides for us all the time
+ Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, 0, UseUserOverride));
+
+ return result;
+ }
+
+ String[] DoEnumShortTimeFormats()
+ {
+ // Note that this gets overrides for us all the time
+ Contract.Assert(this.sWindowsName != null, "[CultureData.DoEnumShortTimeFormats] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ String[] result = ReescapeWin32Strings(nativeEnumTimeFormats(this.sWindowsName, TIME_NOSECONDS, UseUserOverride));
+
+ return result;
+ }
+
+ /////////////////
+ // Static Helpers //
+ ////////////////
+ internal static bool IsCustomCultureId(int cultureId)
+ {
+ if (cultureId == CultureInfo.LOCALE_CUSTOM_DEFAULT || cultureId == CultureInfo.LOCALE_CUSTOM_UNSPECIFIED)
+ return true;
+
+ return false;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Parameters:
+ // calendarValueOnly Retrieve the values which are affected by the calendar change of DTFI.
+ // This will cause values like longTimePattern not be retrieved since it is
+ // not affected by the Calendar property in DTFI.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ [System.Security.SecurityCritical] // auto-generated
+ internal void GetNFIValues(NumberFormatInfo nfi)
+ {
+ if (this.IsInvariantCulture)
+ {
+ nfi.positiveSign = this.sPositiveSign;
+ nfi.negativeSign = this.sNegativeSign;
+
+ nfi.nativeDigits = this.saNativeDigits;
+ nfi.digitSubstitution = this.iDigitSubstitution;
+
+ nfi.numberGroupSeparator = this.sThousandSeparator;
+ nfi.numberDecimalSeparator = this.sDecimalSeparator;
+ nfi.numberDecimalDigits = this.iDigits;
+ nfi.numberNegativePattern = this.iNegativeNumber;
+
+ nfi.currencySymbol = this.sCurrency;
+ nfi.currencyGroupSeparator = this.sMonetaryThousand;
+ nfi.currencyDecimalSeparator = this.sMonetaryDecimal;
+ nfi.currencyDecimalDigits = this.iCurrencyDigits;
+ nfi.currencyNegativePattern = this.iNegativeCurrency;
+ nfi.currencyPositivePattern = this.iCurrency;
+ }
+ else
+ {
+ //
+ // We don't have information for the following four. All cultures use
+ // the same value of the number formatting values.
+ //
+ // PercentDecimalDigits
+ // PercentDecimalSeparator
+ // PercentGroupSize
+ // PercentGroupSeparator
+ //
+
+ //
+ // Ask native side for our data.
+ //
+ Contract.Assert(this.sWindowsName != null, "[CultureData.GetNFIValues] Expected this.sWindowsName to be populated by COMNlsInfo::nativeInitCultureData already");
+ CultureData.nativeGetNumberFormatInfoValues(this.sWindowsName, nfi, UseUserOverride);
+ }
+
+
+ //
+ // Gather additional data
+ //
+ nfi.numberGroupSizes = this.WAGROUPING;
+ nfi.currencyGroupSizes = this.WAMONGROUPING;
+
+ // prefer the cached value since these do not have user overrides
+ nfi.percentNegativePattern = this.INEGATIVEPERCENT;
+ nfi.percentPositivePattern = this.IPOSITIVEPERCENT;
+ nfi.percentSymbol = this.SPERCENT;
+ nfi.perMilleSymbol = this.SPERMILLE;
+
+ nfi.negativeInfinitySymbol = this.SNEGINFINITY;
+ nfi.positiveInfinitySymbol = this.SPOSINFINITY;
+ nfi.nanSymbol = this.SNAN;
+
+ //
+ // We don't have percent values, so use the number values
+ //
+ nfi.percentDecimalDigits = nfi.numberDecimalDigits;
+ nfi.percentDecimalSeparator = nfi.numberDecimalSeparator;
+ nfi.percentGroupSizes = nfi.numberGroupSizes;
+ nfi.percentGroupSeparator = nfi.numberGroupSeparator;
+
+ //
+ // Clean up a few odd values
+ //
+
+ // Windows usually returns an empty positive sign, but we like it to be "+"
+ if (nfi.positiveSign == null || nfi.positiveSign.Length == 0) nfi.positiveSign = "+";
+
+ //Special case for Italian. The currency decimal separator in the control panel is the empty string. When the user
+ //specifies C4 as the currency format, this results in the number apparently getting multiplied by 10000 because the
+ //decimal point doesn't show up. We'll just workaround this here because our default currency format will never use nfi.
+ if (nfi.currencyDecimalSeparator == null || nfi.currencyDecimalSeparator.Length == 0)
+ {
+ nfi.currencyDecimalSeparator = nfi.numberDecimalSeparator;
+ }
+
+#if !FEATURE_CORECLR
+ if ((932 == this.IDEFAULTANSICODEPAGE) ||
+ (949 == this.IDEFAULTANSICODEPAGE))
+ {
+ // Legacy behavior for cultures that use Japanese/Korean default ANSI code pages
+ // Note that this is a code point, not a character. On Japanese/Korean machines this
+ // will be rendered as their currency symbol, not rendered as a "\"
+ nfi.ansiCurrencySymbol = "\x5c";
+ }
+#endif // !FEATURE_CORECLR
+ }
+
+ static private int ConvertFirstDayOfWeekMonToSun(int iTemp)
+ {
+ // Convert Mon-Sun to Sun-Sat format
+ iTemp++;
+ if (iTemp > 6)
+ {
+ // Wrap Sunday and convert invalid data to Sunday
+ iTemp = 0;
+ }
+ return iTemp;
+ }
+
+ // Helper
+ // This is ONLY used for caching names and shouldn't be used for anything else
+ internal static string AnsiToLower(string testString)
+ {
+ StringBuilder sb = new StringBuilder(testString.Length);
+
+ for (int ich = 0; ich < testString.Length; ich++)
+ {
+ char ch = testString[ich];
+ sb.Append(ch <= 'Z' && ch >= 'A' ? (char)(ch - 'A' + 'a') : ch);
+ }
+
+ return (sb.ToString());
+ }
+
+ // If we get a group from windows, then its in 3;0 format with the 0 backwards
+ // of how NLS+ uses it (ie: if the string has a 0, then the int[] shouldn't and vice versa)
+ // EXCEPT in the case where the list only contains 0 in which NLS and NLS+ have the same meaning.
+ static private int[] ConvertWin32GroupString(String win32Str)
+ {
+ // None of these cases make any sense
+ if (win32Str == null || win32Str.Length == 0)
+ {
+ return (new int[] { 3 });
+ }
+
+ if (win32Str[0] == '0')
+ {
+ return (new int[] { 0 });
+ }
+
+ // Since its in n;n;n;n;n format, we can always get the length quickly
+ int[] values;
+ if (win32Str[win32Str.Length - 1] == '0')
+ {
+ // Trailing 0 gets dropped. 1;0 -> 1
+ values = new int[(win32Str.Length / 2)];
+ }
+ else
+ {
+ // Need extra space for trailing zero 1 -> 1;0
+ values = new int[(win32Str.Length / 2) + 2];
+ values[values.Length - 1] = 0;
+ }
+
+ int i;
+ int j;
+ for (i = 0, j = 0; i < win32Str.Length && j < values.Length; i += 2, j++)
+ {
+ // Note that this # shouldn't ever be zero, 'cause 0 is only at end
+ // But we'll test because its registry that could be anything
+ if (win32Str[i] < '1' || win32Str[i] > '9')
+ return new int[] { 3 };
+
+ values[j] = (int)(win32Str[i] - '0');
+ }
+
+ return (values);
+ }
+
+ // LCTYPES for GetLocaleInfo
+ private const uint LOCALE_NOUSEROVERRIDE = 0x80000000; // do not use user overrides
+ private const uint LOCALE_RETURN_NUMBER = 0x20000000; // return number instead of string
+
+ // Modifier for genitive names
+ private const uint LOCALE_RETURN_GENITIVE_NAMES = 0x10000000; //Flag to return the Genitive forms of month names
+
+ //
+ // The following LCTypes are mutually exclusive in that they may NOT
+ // be used in combination with each other.
+ //
+
+ //
+ // These are the various forms of the name of the locale:
+ //
+ private const uint LOCALE_SLOCALIZEDDISPLAYNAME = 0x00000002; // localized name of locale, eg "German (Germany)" in UI language
+ private const uint LOCALE_SENGLISHDISPLAYNAME = 0x00000072; // Display name (language + country usually) in English, eg "German (Germany)"
+ private const uint LOCALE_SNATIVEDISPLAYNAME = 0x00000073; // Display name in native locale language, eg "Deutsch (Deutschland)
+
+ private const uint LOCALE_SLOCALIZEDLANGUAGENAME = 0x0000006f; // Language Display Name for a language, eg "German" in UI language
+ private const uint LOCALE_SENGLISHLANGUAGENAME = 0x00001001; // English name of language, eg "German"
+ private const uint LOCALE_SNATIVELANGUAGENAME = 0x00000004; // native name of language, eg "Deutsch"
+
+ private const uint LOCALE_SLOCALIZEDCOUNTRYNAME = 0x00000006; // localized name of country, eg "Germany" in UI language
+ private const uint LOCALE_SENGLISHCOUNTRYNAME = 0x00001002; // English name of country, eg "Germany"
+ private const uint LOCALE_SNATIVECOUNTRYNAME = 0x00000008; // native name of country, eg "Deutschland"
+
+
+ // private const uint LOCALE_ILANGUAGE =0x00000001; // language id // Don't use, use NewApis::LocaleNameToLCID instead (GetLocaleInfo doesn't return neutrals)
+
+ // private const uint LOCALE_SLANGUAGE =LOCALE_SLOCALIZEDDISPLAYNAME; // localized name of language (use LOCALE_SLOCALIZEDDISPLAYNAME instead)
+ // private const uint LOCALE_SENGLANGUAGE =LOCALE_SENGLISHLANGUAGENAME; // English name of language (use LOCALE_SENGLISHLANGUAGENAME instead)
+ private const uint LOCALE_SABBREVLANGNAME = 0x00000003; // abbreviated language name
+ // private const uint LOCALE_SNATIVELANGNAME =LOCALE_SNATIVELANGUAGENAME; // native name of language (use LOCALE_SNATIVELANGUAGENAME instead)
+
+ private const uint LOCALE_ICOUNTRY = 0x00000005; // country code
+ // private const uint LOCALE_SCOUNTRY =LOCALE_SLOCALIZEDCOUNTRYNAME; // localized name of country (use LOCALE_SLOCALIZEDCOUNTRYNAME instead)
+ // private const uint LOCALE_SENGCOUNTRY =LOCALE_SENGLISHCOUNTRYNAME; // English name of country (use LOCALE_SENGLISHCOUNTRYNAME instead)
+ private const uint LOCALE_SABBREVCTRYNAME = 0x00000007; // abbreviated country name
+ // private const uint LOCALE_SNATIVECTRYNAME =LOCALE_SNATIVECOUNTRYNAME; // native name of country ( use LOCALE_SNATIVECOUNTRYNAME instead)
+ private const uint LOCALE_IGEOID = 0x0000005B; // geographical location id
+
+ private const uint LOCALE_IDEFAULTLANGUAGE = 0x00000009; // default language id
+ private const uint LOCALE_IDEFAULTCOUNTRY = 0x0000000A; // default country code
+ private const uint LOCALE_IDEFAULTCODEPAGE = 0x0000000B; // default oem code page
+ private const uint LOCALE_IDEFAULTANSICODEPAGE = 0x00001004; // default ansi code page
+ private const uint LOCALE_IDEFAULTMACCODEPAGE = 0x00001011; // default mac code page
+
+ private const uint LOCALE_SLIST = 0x0000000C; // list item separator
+ private const uint LOCALE_IMEASURE = 0x0000000D; // 0 = metric, 1 = US
+
+ private const uint LOCALE_SDECIMAL = 0x0000000E; // decimal separator
+ private const uint LOCALE_STHOUSAND = 0x0000000F; // thousand separator
+ private const uint LOCALE_SGROUPING = 0x00000010; // digit grouping
+ private const uint LOCALE_IDIGITS = 0x00000011; // number of fractional digits
+ private const uint LOCALE_ILZERO = 0x00000012; // leading zeros for decimal
+ private const uint LOCALE_INEGNUMBER = 0x00001010; // negative number mode
+ private const uint LOCALE_SNATIVEDIGITS = 0x00000013; // native digits for 0-9
+
+ private const uint LOCALE_SCURRENCY = 0x00000014; // local monetary symbol
+ private const uint LOCALE_SINTLSYMBOL = 0x00000015; // uintl monetary symbol
+ private const uint LOCALE_SMONDECIMALSEP = 0x00000016; // monetary decimal separator
+ private const uint LOCALE_SMONTHOUSANDSEP = 0x00000017; // monetary thousand separator
+ private const uint LOCALE_SMONGROUPING = 0x00000018; // monetary grouping
+ private const uint LOCALE_ICURRDIGITS = 0x00000019; // # local monetary digits
+ private const uint LOCALE_IINTLCURRDIGITS = 0x0000001A; // # uintl monetary digits
+ private const uint LOCALE_ICURRENCY = 0x0000001B; // positive currency mode
+ private const uint LOCALE_INEGCURR = 0x0000001C; // negative currency mode
+
+ private const uint LOCALE_SDATE = 0x0000001D; // date separator (derived from LOCALE_SSHORTDATE, use that instead)
+ private const uint LOCALE_STIME = 0x0000001E; // time separator (derived from LOCALE_STIMEFORMAT, use that instead)
+ private const uint LOCALE_SSHORTDATE = 0x0000001F; // short date format string
+ private const uint LOCALE_SLONGDATE = 0x00000020; // long date format string
+ private const uint LOCALE_STIMEFORMAT = 0x00001003; // time format string
+ private const uint LOCALE_IDATE = 0x00000021; // short date format ordering (derived from LOCALE_SSHORTDATE, use that instead)
+ private const uint LOCALE_ILDATE = 0x00000022; // long date format ordering (derived from LOCALE_SLONGDATE, use that instead)
+ private const uint LOCALE_ITIME = 0x00000023; // time format specifier (derived from LOCALE_STIMEFORMAT, use that instead)
+ private const uint LOCALE_ITIMEMARKPOSN = 0x00001005; // time marker position (derived from LOCALE_STIMEFORMAT, use that instead)
+ private const uint LOCALE_ICENTURY = 0x00000024; // century format specifier (short date, LOCALE_SSHORTDATE is preferred)
+ private const uint LOCALE_ITLZERO = 0x00000025; // leading zeros in time field (derived from LOCALE_STIMEFORMAT, use that instead)
+ private const uint LOCALE_IDAYLZERO = 0x00000026; // leading zeros in day field (short date, LOCALE_SSHORTDATE is preferred)
+ private const uint LOCALE_IMONLZERO = 0x00000027; // leading zeros in month field (short date, LOCALE_SSHORTDATE is preferred)
+ private const uint LOCALE_S1159 = 0x00000028; // AM designator
+ private const uint LOCALE_S2359 = 0x00000029; // PM designator
+
+ private const uint LOCALE_ICALENDARTYPE = 0x00001009; // type of calendar specifier
+ private const uint LOCALE_IOPTIONALCALENDAR = 0x0000100B; // additional calendar types specifier
+ private const uint LOCALE_IFIRSTDAYOFWEEK = 0x0000100C; // first day of week specifier
+ private const uint LOCALE_IFIRSTWEEKOFYEAR = 0x0000100D; // first week of year specifier
+
+ private const uint LOCALE_SDAYNAME1 = 0x0000002A; // long name for Monday
+ private const uint LOCALE_SDAYNAME2 = 0x0000002B; // long name for Tuesday
+ private const uint LOCALE_SDAYNAME3 = 0x0000002C; // long name for Wednesday
+ private const uint LOCALE_SDAYNAME4 = 0x0000002D; // long name for Thursday
+ private const uint LOCALE_SDAYNAME5 = 0x0000002E; // long name for Friday
+ private const uint LOCALE_SDAYNAME6 = 0x0000002F; // long name for Saturday
+ private const uint LOCALE_SDAYNAME7 = 0x00000030; // long name for Sunday
+ private const uint LOCALE_SABBREVDAYNAME1 = 0x00000031; // abbreviated name for Monday
+ private const uint LOCALE_SABBREVDAYNAME2 = 0x00000032; // abbreviated name for Tuesday
+ private const uint LOCALE_SABBREVDAYNAME3 = 0x00000033; // abbreviated name for Wednesday
+ private const uint LOCALE_SABBREVDAYNAME4 = 0x00000034; // abbreviated name for Thursday
+ private const uint LOCALE_SABBREVDAYNAME5 = 0x00000035; // abbreviated name for Friday
+ private const uint LOCALE_SABBREVDAYNAME6 = 0x00000036; // abbreviated name for Saturday
+ private const uint LOCALE_SABBREVDAYNAME7 = 0x00000037; // abbreviated name for Sunday
+ private const uint LOCALE_SMONTHNAME1 = 0x00000038; // long name for January
+ private const uint LOCALE_SMONTHNAME2 = 0x00000039; // long name for February
+ private const uint LOCALE_SMONTHNAME3 = 0x0000003A; // long name for March
+ private const uint LOCALE_SMONTHNAME4 = 0x0000003B; // long name for April
+ private const uint LOCALE_SMONTHNAME5 = 0x0000003C; // long name for May
+ private const uint LOCALE_SMONTHNAME6 = 0x0000003D; // long name for June
+ private const uint LOCALE_SMONTHNAME7 = 0x0000003E; // long name for July
+ private const uint LOCALE_SMONTHNAME8 = 0x0000003F; // long name for August
+ private const uint LOCALE_SMONTHNAME9 = 0x00000040; // long name for September
+ private const uint LOCALE_SMONTHNAME10 = 0x00000041; // long name for October
+ private const uint LOCALE_SMONTHNAME11 = 0x00000042; // long name for November
+ private const uint LOCALE_SMONTHNAME12 = 0x00000043; // long name for December
+ private const uint LOCALE_SMONTHNAME13 = 0x0000100E; // long name for 13th month (if exists)
+ private const uint LOCALE_SABBREVMONTHNAME1 = 0x00000044; // abbreviated name for January
+ private const uint LOCALE_SABBREVMONTHNAME2 = 0x00000045; // abbreviated name for February
+ private const uint LOCALE_SABBREVMONTHNAME3 = 0x00000046; // abbreviated name for March
+ private const uint LOCALE_SABBREVMONTHNAME4 = 0x00000047; // abbreviated name for April
+ private const uint LOCALE_SABBREVMONTHNAME5 = 0x00000048; // abbreviated name for May
+ private const uint LOCALE_SABBREVMONTHNAME6 = 0x00000049; // abbreviated name for June
+ private const uint LOCALE_SABBREVMONTHNAME7 = 0x0000004A; // abbreviated name for July
+ private const uint LOCALE_SABBREVMONTHNAME8 = 0x0000004B; // abbreviated name for August
+ private const uint LOCALE_SABBREVMONTHNAME9 = 0x0000004C; // abbreviated name for September
+ private const uint LOCALE_SABBREVMONTHNAME10 = 0x0000004D; // abbreviated name for October
+ private const uint LOCALE_SABBREVMONTHNAME11 = 0x0000004E; // abbreviated name for November
+ private const uint LOCALE_SABBREVMONTHNAME12 = 0x0000004F; // abbreviated name for December
+ private const uint LOCALE_SABBREVMONTHNAME13 = 0x0000100F; // abbreviated name for 13th month (if exists)
+
+ private const uint LOCALE_SPOSITIVESIGN = 0x00000050; // positive sign
+ private const uint LOCALE_SNEGATIVESIGN = 0x00000051; // negative sign
+ private const uint LOCALE_IPOSSIGNPOSN = 0x00000052; // positive sign position (derived from INEGCURR)
+ private const uint LOCALE_INEGSIGNPOSN = 0x00000053; // negative sign position (derived from INEGCURR)
+ private const uint LOCALE_IPOSSYMPRECEDES = 0x00000054; // mon sym precedes pos amt (derived from ICURRENCY)
+ private const uint LOCALE_IPOSSEPBYSPACE = 0x00000055; // mon sym sep by space from pos amt (derived from ICURRENCY)
+ private const uint LOCALE_INEGSYMPRECEDES = 0x00000056; // mon sym precedes neg amt (derived from INEGCURR)
+ private const uint LOCALE_INEGSEPBYSPACE = 0x00000057; // mon sym sep by space from neg amt (derived from INEGCURR)
+
+ private const uint LOCALE_FONTSIGNATURE = 0x00000058; // font signature
+ private const uint LOCALE_SISO639LANGNAME = 0x00000059; // ISO abbreviated language name
+ private const uint LOCALE_SISO3166CTRYNAME = 0x0000005A; // ISO abbreviated country name
+
+ private const uint LOCALE_IDEFAULTEBCDICCODEPAGE = 0x00001012; // default ebcdic code page
+ private const uint LOCALE_IPAPERSIZE = 0x0000100A; // 1 = letter, 5 = legal, 8 = a3, 9 = a4
+ private const uint LOCALE_SENGCURRNAME = 0x00001007; // english name of currency
+ private const uint LOCALE_SNATIVECURRNAME = 0x00001008; // native name of currency
+ private const uint LOCALE_SYEARMONTH = 0x00001006; // year month format string
+ private const uint LOCALE_SSORTNAME = 0x00001013; // sort name
+ private const uint LOCALE_IDIGITSUBSTITUTION = 0x00001014; // 0 = context, 1 = none, 2 = national
+
+ private const uint LOCALE_SNAME = 0x0000005c; // locale name (with sort info) (ie: de-DE_phoneb)
+ private const uint LOCALE_SDURATION = 0x0000005d; // time duration format
+ private const uint LOCALE_SKEYBOARDSTOINSTALL = 0x0000005e; // (windows only) keyboards to install
+ private const uint LOCALE_SSHORTESTDAYNAME1 = 0x00000060; // Shortest day name for Monday
+ private const uint LOCALE_SSHORTESTDAYNAME2 = 0x00000061; // Shortest day name for Tuesday
+ private const uint LOCALE_SSHORTESTDAYNAME3 = 0x00000062; // Shortest day name for Wednesday
+ private const uint LOCALE_SSHORTESTDAYNAME4 = 0x00000063; // Shortest day name for Thursday
+ private const uint LOCALE_SSHORTESTDAYNAME5 = 0x00000064; // Shortest day name for Friday
+ private const uint LOCALE_SSHORTESTDAYNAME6 = 0x00000065; // Shortest day name for Saturday
+ private const uint LOCALE_SSHORTESTDAYNAME7 = 0x00000066; // Shortest day name for Sunday
+ private const uint LOCALE_SISO639LANGNAME2 = 0x00000067; // 3 character ISO abbreviated language name
+ private const uint LOCALE_SISO3166CTRYNAME2 = 0x00000068; // 3 character ISO country name
+ private const uint LOCALE_SNAN = 0x00000069; // Not a Number
+ private const uint LOCALE_SPOSINFINITY = 0x0000006a; // + Infinity
+ private const uint LOCALE_SNEGINFINITY = 0x0000006b; // - Infinity
+ private const uint LOCALE_SSCRIPTS = 0x0000006c; // Typical scripts in the locale
+ private const uint LOCALE_SPARENT = 0x0000006d; // Fallback name for resources
+ private const uint LOCALE_SCONSOLEFALLBACKNAME = 0x0000006e; // Fallback name for within the console
+ // private const uint LOCALE_SLANGDISPLAYNAME =LOCALE_SLOCALIZEDLANGUAGENAME; // Language Display Name for a language (use LOCALE_SLOCALIZEDLANGUAGENAME instead)
+
+ // Windows 7 LCTYPES
+ private const uint LOCALE_IREADINGLAYOUT = 0x00000070; // Returns one of the following 4 reading layout values:
+ // 0 - Left to right (eg en-US)
+ // 1 - Right to left (eg arabic locales)
+ // 2 - Vertical top to bottom with columns to the left and also left to right (ja-JP locales)
+ // 3 - Vertical top to bottom with columns proceeding to the right
+ private const uint LOCALE_INEUTRAL = 0x00000071; // Returns 0 for specific cultures, 1 for neutral cultures.
+ private const uint LOCALE_INEGATIVEPERCENT = 0x00000074; // Returns 0-11 for the negative percent format
+ private const uint LOCALE_IPOSITIVEPERCENT = 0x00000075; // Returns 0-3 for the positive percent formatIPOSITIVEPERCENT
+ private const uint LOCALE_SPERCENT = 0x00000076; // Returns the percent symbol
+ private const uint LOCALE_SPERMILLE = 0x00000077; // Returns the permille (U+2030) symbol
+ private const uint LOCALE_SMONTHDAY = 0x00000078; // Returns the preferred month/day format
+ private const uint LOCALE_SSHORTTIME = 0x00000079; // Returns the preferred short time format (ie: no seconds, just h:mm)
+ private const uint LOCALE_SOPENTYPELANGUAGETAG = 0x0000007a; // Open type language tag, eg: "latn" or "dflt"
+ private const uint LOCALE_SSORTLOCALE = 0x0000007b; // Name of locale to use for sorting/collation/casing behavior.
+
+ // Time formats enumerations
+ internal const uint TIME_NOSECONDS = 0x00000002; // Don't use seconds (get short time format for enumtimeformats on win7+)
+
+ // Get our initial minimal culture data (name, parent, etc.)
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool nativeInitCultureData(CultureData cultureData);
+
+ // Grab the NumberFormatInfo data
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool nativeGetNumberFormatInfoValues(String localeName, NumberFormatInfo nfi, bool useUserOverride);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern String[] nativeEnumTimeFormats(String localeName, uint dwFlags, bool useUserOverride);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ internal static extern int nativeEnumCultureNames(int cultureTypes, ObjectHandleOnStack retStringArray);
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CultureInfo.cs b/src/mscorlib/src/System/Globalization/CultureInfo.cs
new file mode 100644
index 0000000000..d620d2dc24
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CultureInfo.cs
@@ -0,0 +1,2023 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+//
+// Purpose: This class represents the software preferences of a particular
+// culture or community. It includes information such as the
+// language, writing system, and a calendar used by the culture
+// as well as methods for common operations such as printing
+// dates and sorting strings.
+//
+//
+//
+// !!!! NOTE WHEN CHANGING THIS CLASS !!!!
+//
+// If adding or removing members to this class, please update CultureInfoBaseObject
+// in ndp/clr/src/vm/object.h. Note, the "actual" layout of the class may be
+// different than the order in which members are declared. For instance, all
+// reference types will come first in the class before value types (like ints, bools, etc)
+// regardless of the order in which they are declared. The best way to see the
+// actual order of the class is to do a !dumpobj on an instance of the managed
+// object inside of the debugger.
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+ using System;
+ using System.Security;
+ using System.Threading;
+ using System.Collections;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using Microsoft.Win32;
+ using System.Diagnostics.Contracts;
+ using System.Resources;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class CultureInfo : ICloneable, IFormatProvider {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //--------------------------------------------------------------------//
+ // Data members to be serialized:
+ //--------------------------------------------------------------------//
+
+ // We use an RFC4646 type string to construct CultureInfo.
+ // This string is stored in m_name and is authoritative.
+ // We use the m_cultureData to get the data for our object
+
+ // WARNING
+ // WARNING: All member fields declared here must also be in ndp/clr/src/vm/object.h
+ // WARNING: They aren't really private because object.h can access them, but other C# stuff cannot
+ // WARNING: The type loader will rearrange class member offsets so the mscorwks!CultureInfoBaseObject
+ // WARNING: must be manually structured to match the true loaded class layout
+ // WARNING
+ internal bool m_isReadOnly;
+ internal CompareInfo compareInfo;
+ internal TextInfo textInfo;
+ // Not serialized for now since we only build it privately for use in the CARIB (so rebuilding is OK)
+#if !FEATURE_CORECLR
+ [NonSerialized]internal RegionInfo regionInfo;
+#endif
+ internal NumberFormatInfo numInfo;
+ internal DateTimeFormatInfo dateTimeInfo;
+ internal Calendar calendar;
+ [OptionalField(VersionAdded = 1)]
+ internal int m_dataItem; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
+ [OptionalField(VersionAdded = 1)]
+ internal int cultureID = 0x007f; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
+ //
+ // The CultureData instance that we are going to read data from.
+ // For supported culture, this will be the CultureData instance that read data from mscorlib assembly.
+ // For customized culture, this will be the CultureData instance that read data from user customized culture binary file.
+ //
+ [NonSerialized]internal CultureData m_cultureData;
+
+ [NonSerialized]internal bool m_isInherited;
+#if FEATURE_LEAK_CULTURE_INFO
+ [NonSerialized]private bool m_isSafeCrossDomain;
+ [NonSerialized]private int m_createdDomainID;
+#endif // !FEATURE_CORECLR
+#if !FEATURE_CORECLR
+ [NonSerialized]private CultureInfo m_consoleFallbackCulture;
+#endif // !FEATURE_CORECLR
+
+ // Names are confusing. Here are 3 names we have:
+ //
+ // new CultureInfo() m_name m_nonSortName m_sortName
+ // en-US en-US en-US en-US
+ // de-de_phoneb de-DE_phoneb de-DE de-DE_phoneb
+ // fj-fj (custom) fj-FJ fj-FJ en-US (if specified sort is en-US)
+ // en en
+ //
+ // Note that in Silverlight we ask the OS for the text and sort behavior, so the
+ // textinfo and compareinfo names are the same as the name
+
+ // Note that the name used to be serialized for Everett; it is now serialized
+ // because alernate sorts can have alternate names.
+ // This has a de-DE, de-DE_phoneb or fj-FJ style name
+ internal string m_name;
+
+ // This will hold the non sorting name to be returned from CultureInfo.Name property.
+ // This has a de-DE style name even for de-DE_phoneb type cultures
+ [NonSerialized]private string m_nonSortName;
+
+ // This will hold the sorting name to be returned from CultureInfo.SortName property.
+ // This might be completely unrelated to the culture name if a custom culture. Ie en-US for fj-FJ.
+ // Otherwise its the sort name, ie: de-DE or de-DE_phoneb
+ [NonSerialized]private string m_sortName;
+
+
+ //--------------------------------------------------------------------//
+ //
+ // Static data members
+ //
+ //--------------------------------------------------------------------//
+
+ //Get the current user default culture. This one is almost always used, so we create it by default.
+ private static volatile CultureInfo s_userDefaultCulture;
+
+ //
+ // All of the following will be created on demand.
+ //
+
+ //The Invariant culture;
+ private static volatile CultureInfo s_InvariantCultureInfo;
+
+ //The culture used in the user interface. This is mostly used to load correct localized resources.
+ private static volatile CultureInfo s_userDefaultUICulture;
+
+ //This is the UI culture used to install the OS.
+ private static volatile CultureInfo s_InstalledUICultureInfo;
+
+ //These are defaults that we use if a thread has not opted into having an explicit culture
+ private static volatile CultureInfo s_DefaultThreadCurrentUICulture;
+ private static volatile CultureInfo s_DefaultThreadCurrentCulture;
+
+ //This is a cache of all previously created cultures. Valid keys are LCIDs or the name. We use two hashtables to track them,
+ // depending on how they are called.
+ private static volatile Hashtable s_LcidCachedCultures;
+ private static volatile Hashtable s_NameCachedCultures;
+
+#if FEATURE_APPX
+ // When running under AppX, we use this to get some information about the language list
+ [SecurityCritical]
+ private static volatile WindowsRuntimeResourceManagerBase s_WindowsRuntimeResourceManager;
+
+ [ThreadStatic]
+ private static bool ts_IsDoingAppXCultureInfoLookup;
+#endif
+
+ //The parent culture.
+ [NonSerialized]private CultureInfo m_parent;
+
+ // LOCALE constants of interest to us internally and privately for LCID functions
+ // (ie: avoid using these and use names if possible)
+ internal const int LOCALE_NEUTRAL = 0x0000;
+ private const int LOCALE_USER_DEFAULT = 0x0400;
+ private const int LOCALE_SYSTEM_DEFAULT = 0x0800;
+ internal const int LOCALE_CUSTOM_DEFAULT = 0x0c00;
+ internal const int LOCALE_CUSTOM_UNSPECIFIED = 0x1000;
+ internal const int LOCALE_INVARIANT = 0x007F;
+ private const int LOCALE_TRADITIONAL_SPANISH = 0x040a;
+
+ //
+ // The CultureData instance that reads the data provided by our CultureData class.
+ //
+ //Using a field initializer rather than a static constructor so that the whole class can be lazy
+ //init.
+ private static readonly bool init = Init();
+ private static bool Init()
+ {
+
+ if (s_InvariantCultureInfo == null)
+ {
+ CultureInfo temp = new CultureInfo("", false);
+ temp.m_isReadOnly = true;
+ s_InvariantCultureInfo = temp;
+ }
+ // First we set it to Invariant in case someone needs it before we're done finding it.
+ // For example, if we throw an exception in InitUserDefaultCulture, we will still need an valid
+ // s_userDefaultCulture to be used in Thread.CurrentCulture.
+ s_userDefaultCulture = s_userDefaultUICulture = s_InvariantCultureInfo;
+
+ s_userDefaultCulture = InitUserDefaultCulture();
+ s_userDefaultUICulture = InitUserDefaultUICulture();
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static CultureInfo InitUserDefaultCulture()
+ {
+ String strDefault = GetDefaultLocaleName(LOCALE_USER_DEFAULT);
+ if (strDefault == null)
+ {
+ strDefault = GetDefaultLocaleName(LOCALE_SYSTEM_DEFAULT);
+
+ if (strDefault == null)
+ {
+ // If system default doesn't work, keep using the invariant
+ return (CultureInfo.InvariantCulture);
+ }
+ }
+ CultureInfo temp = GetCultureByName(strDefault, true);
+
+ temp.m_isReadOnly = true;
+
+ return (temp);
+ }
+
+ static CultureInfo InitUserDefaultUICulture()
+ {
+ String strDefault = GetUserDefaultUILanguage();
+
+ // In most of cases, UserDefaultCulture == UserDefaultUICulture, so we should use the same instance if possible.
+ if (strDefault == UserDefaultCulture.Name)
+ {
+ return (UserDefaultCulture);
+ }
+
+ CultureInfo temp = GetCultureByName( strDefault, true);
+
+ if (temp == null)
+ {
+ return (CultureInfo.InvariantCulture);
+ }
+
+ temp.m_isReadOnly = true;
+
+ return (temp);
+ }
+
+#if FEATURE_APPX
+ [SecuritySafeCritical]
+ internal static CultureInfo GetCultureInfoForUserPreferredLanguageInAppX()
+ {
+ // If a call to GetCultureInfoForUserPreferredLanguageInAppX() generated a recursive
+ // call to itself, return null, since we don't want to stack overflow. For example,
+ // this can happen if some code in this method ends up calling CultureInfo.CurrentCulture
+ // (which is common on check'd build because of BCLDebug logging which calls Int32.ToString()).
+ // In this case, returning null will mean CultureInfo.CurrentCulture gets the default Win32
+ // value, which should be fine.
+ if(ts_IsDoingAppXCultureInfoLookup)
+ {
+ return null;
+ }
+
+ // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
+ // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
+ // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
+ // which should be fine because we should only ever need to access FX resources during NGEN.
+ // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
+ // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
+ if (AppDomain.IsAppXNGen)
+ {
+ return null;
+ }
+
+ CultureInfo toReturn = null;
+
+ try
+ {
+ ts_IsDoingAppXCultureInfoLookup = true;
+
+ if(s_WindowsRuntimeResourceManager == null)
+ {
+ s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager();
+ }
+
+ toReturn = s_WindowsRuntimeResourceManager.GlobalResourceContextBestFitCultureInfo;
+ }
+ finally
+ {
+ ts_IsDoingAppXCultureInfoLookup = false;
+ }
+
+ return toReturn;
+ }
+
+ [SecuritySafeCritical]
+ internal static bool SetCultureInfoForUserPreferredLanguageInAppX(CultureInfo ci)
+ {
+ // If running within a compilation process (mscorsvw.exe, for example), it is illegal to
+ // load any non-mscorlib assembly for execution. Since WindowsRuntimeResourceManager lives
+ // in System.Runtime.WindowsRuntime, caller will need to fall back to default Win32 value,
+ // which should be fine because we should only ever need to access FX resources during NGEN.
+ // FX resources are always loaded from satellite assemblies - even in AppX processes (see the
+ // comments in code:System.Resources.ResourceManager.SetAppXConfiguration for more details).
+ if (AppDomain.IsAppXNGen)
+ {
+ return false;
+ }
+
+ if (s_WindowsRuntimeResourceManager == null)
+ {
+ s_WindowsRuntimeResourceManager = ResourceManager.GetWinRTResourceManager();
+ }
+
+ return s_WindowsRuntimeResourceManager.SetGlobalResourceContextDefaultCulture(ci);
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CultureInfo Constructors
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public CultureInfo(String name) : this(name, true) {
+ }
+
+
+ public CultureInfo(String name, bool useUserOverride) {
+ if (name==null) {
+ throw new ArgumentNullException("name",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // Get our data providing record
+ this.m_cultureData = CultureData.GetCultureData(name, useUserOverride);
+
+ if (this.m_cultureData == null) {
+ throw new CultureNotFoundException("name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
+ }
+
+ this.m_name = this.m_cultureData.CultureName;
+ this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
+ }
+
+
+#if FEATURE_USE_LCID
+ public CultureInfo(int culture) : this(culture, true) {
+ }
+
+ public CultureInfo(int culture, bool useUserOverride) {
+ // We don't check for other invalid LCIDS here...
+ if (culture < 0) {
+ throw new ArgumentOutOfRangeException("culture",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ Contract.EndContractBlock();
+
+ InitializeFromCultureId(culture, useUserOverride);
+ }
+
+ private void InitializeFromCultureId(int culture, bool useUserOverride)
+ {
+ switch (culture)
+ {
+ case LOCALE_CUSTOM_DEFAULT:
+ case LOCALE_SYSTEM_DEFAULT:
+ case LOCALE_NEUTRAL:
+ case LOCALE_USER_DEFAULT:
+ case LOCALE_CUSTOM_UNSPECIFIED:
+ // Can't support unknown custom cultures and we do not support neutral or
+ // non-custom user locales.
+ throw new CultureNotFoundException(
+ "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
+
+ default:
+ // Now see if this LCID is supported in the system default CultureData table.
+ this.m_cultureData = CultureData.GetCultureData(culture, useUserOverride);
+ break;
+ }
+ this.m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
+ this.m_name = this.m_cultureData.CultureName;
+ }
+#endif // FEATURE_USE_LCID
+
+ //
+ // CheckDomainSafetyObject throw if the object is customized object which cannot be attached to
+ // other object (like CultureInfo or DateTimeFormatInfo).
+ //
+
+ internal static void CheckDomainSafetyObject(Object obj, Object container)
+ {
+ if (obj.GetType().Assembly != typeof(System.Globalization.CultureInfo).Assembly) {
+
+ throw new InvalidOperationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("InvalidOperation_SubclassedObject"),
+ obj.GetType(),
+ container.GetType()));
+ }
+ Contract.EndContractBlock();
+ }
+
+#region Serialization
+ // We need to store the override from the culture data record.
+ private bool m_useUserOverride;
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+#if FEATURE_USE_LCID
+ // Whidbey+ should remember our name
+ // but v1 and v1.1 did not store name -- only lcid
+ // Whidbey did not store actual alternate sort name in m_name
+ // like we do in v4 so we can't use name for alternate sort
+ // e.g. for es-ES_tradnl: v2 puts es-ES in m_name; v4 puts es-ES_tradnl
+ if (m_name == null || IsAlternateSortLcid(cultureID))
+ {
+ Contract.Assert(cultureID >=0, "[CultureInfo.OnDeserialized] cultureID >= 0");
+ InitializeFromCultureId(cultureID, m_useUserOverride);
+ }
+ else
+ {
+#endif
+ Contract.Assert(m_name != null, "[CultureInfo.OnDeserialized] m_name != null");
+
+ this.m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride);
+ if (this.m_cultureData == null)
+ throw new CultureNotFoundException(
+ "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported"));
+
+#if FEATURE_USE_LCID
+ }
+#endif
+ m_isInherited = (this.GetType() != typeof(System.Globalization.CultureInfo));
+
+ // in case we have non customized CultureInfo object we shouldn't allow any customized object
+ // to be attached to it for cross app domain safety.
+ if (this.GetType().Assembly == typeof(System.Globalization.CultureInfo).Assembly)
+ {
+ if (textInfo != null)
+ {
+ CheckDomainSafetyObject(textInfo, this);
+ }
+
+ if (compareInfo != null)
+ {
+ CheckDomainSafetyObject(compareInfo, this);
+ }
+ }
+ }
+
+#if FEATURE_USE_LCID
+ // A locale ID is a 32 bit value which is the combination of a
+ // language ID, a sort ID, and a reserved area. The bits are
+ // allocated as follows:
+ //
+ // +------------------------+-------+--------------------------------+
+ // | Reserved |Sort ID| Language ID |
+ // +------------------------+-------+--------------------------------+
+ // 31 20 19 16 15 0 bit
+ private const int LOCALE_SORTID_MASK = 0x000f0000;
+
+ static private bool IsAlternateSortLcid(int lcid)
+ {
+ if(lcid == LOCALE_TRADITIONAL_SPANISH)
+ {
+ return true;
+ }
+
+ return (lcid & LOCALE_SORTID_MASK) != 0;
+ }
+#endif
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ this.m_name = this.m_cultureData.CultureName;
+ this.m_useUserOverride = this.m_cultureData.UseUserOverride;
+#if FEATURE_USE_LCID
+ // for compatibility with v2 serialize cultureID
+ this.cultureID = this.m_cultureData.ILANGUAGE;
+#endif
+ }
+#endregion Serialization
+
+#if FEATURE_LEAK_CULTURE_INFO
+ // Is it safe to send this CultureInfo as an instance member of a Thread cross AppDomain boundaries?
+ // For Silverlight, the answer is always no.
+ internal bool IsSafeCrossDomain {
+ get {
+ Contract.Assert(m_createdDomainID != 0, "[CultureInfo.IsSafeCrossDomain] m_createdDomainID != 0");
+ return m_isSafeCrossDomain;
+ }
+ }
+
+ internal int CreatedDomainID {
+ get {
+ Contract.Assert(m_createdDomainID != 0, "[CultureInfo.CreatedDomain] m_createdDomainID != 0");
+ return m_createdDomainID;
+ }
+ }
+
+ internal void StartCrossDomainTracking() {
+
+ // If we have decided about cross domain safety of this instance, we are done
+ if (m_createdDomainID != 0)
+ return;
+
+ // If FEATURE_LEAK_CULTURE_INFO isn't enabled, we never want to pass
+ // CultureInfo as an instance member of a Thread.
+ if (CanSendCrossDomain())
+ {
+ m_isSafeCrossDomain = true;
+ }
+
+ // m_createdDomainID has to be assigned last. We use it to signal that we have
+ // completed the check.
+ System.Threading.Thread.MemoryBarrier();
+ m_createdDomainID = Thread.GetDomainID();
+ }
+#endif // FEATURE_LEAK_CULTURE_INFO
+
+ // Is it safe to pass the CultureInfo cross AppDomain boundaries, not necessarily as an instance
+ // member of Thread. This is different from IsSafeCrossDomain, which implies passing the CultureInfo
+ // as a Thread instance member.
+ internal bool CanSendCrossDomain()
+ {
+ bool isSafe = false;
+ if (this.GetType() == typeof(System.Globalization.CultureInfo))
+ {
+ isSafe = true;
+ }
+ return isSafe;
+ }
+
+ // Constructor called by SQL Server's special munged culture - creates a culture with
+ // a TextInfo and CompareInfo that come from a supplied alternate source. This object
+ // is ALWAYS read-only.
+ // Note that we really cannot use an LCID version of this override as the cached
+ // name we create for it has to include both names, and the logic for this is in
+ // the GetCultureInfo override *only*.
+ internal CultureInfo(String cultureName, String textAndCompareCultureName)
+ {
+ if (cultureName==null) {
+ throw new ArgumentNullException("cultureName",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ this.m_cultureData = CultureData.GetCultureData(cultureName, false);
+ if (this.m_cultureData == null)
+ throw new CultureNotFoundException(
+ "cultureName", cultureName, Environment.GetResourceString("Argument_CultureNotSupported"));
+
+ this.m_name = this.m_cultureData.CultureName;
+
+ CultureInfo altCulture = GetCultureInfo(textAndCompareCultureName);
+ this.compareInfo = altCulture.CompareInfo;
+ this.textInfo = altCulture.TextInfo;
+ }
+
+ // We do this to try to return the system UI language and the default user languages
+ // The callers should have a fallback if this fails (like Invariant)
+ private static CultureInfo GetCultureByName(String name, bool userOverride)
+ {
+ // Try to get our culture
+ try
+ {
+ return userOverride ? new CultureInfo(name) : CultureInfo.GetCultureInfo(name);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ return null;
+ }
+
+ //
+ // Return a specific culture. A tad irrelevent now since we always return valid data
+ // for neutral locales.
+ //
+ // Note that there's interesting behavior that tries to find a smaller name, ala RFC4647,
+ // if we can't find a bigger name. That doesn't help with things like "zh" though, so
+ // the approach is of questionable value
+ //
+ public static CultureInfo CreateSpecificCulture(String name) {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ CultureInfo culture;
+
+ try {
+ culture = new CultureInfo(name);
+ } catch(ArgumentException) {
+ // When CultureInfo throws this exception, it may be because someone passed the form
+ // like "az-az" because it came out of an http accept lang. We should try a little
+ // parsing to perhaps fall back to "az" here and use *it* to create the neutral.
+
+ int idx;
+
+ culture = null;
+ for(idx = 0; idx < name.Length; idx++) {
+ if('-' == name[idx]) {
+ try {
+ culture = new CultureInfo(name.Substring(0, idx));
+ break;
+ } catch(ArgumentException) {
+ // throw the original exception so the name in the string will be right
+ throw;
+ }
+ }
+ }
+
+ if(null == culture) {
+ // nothing to save here; throw the original exception
+ throw;
+ }
+ }
+
+ //In the most common case, they've given us a specific culture, so we'll just return that.
+ if (!(culture.IsNeutralCulture)) {
+ return culture;
+ }
+
+ return (new CultureInfo(culture.m_cultureData.SSPECIFICCULTURE));
+ }
+
+ internal static bool VerifyCultureName(String cultureName, bool throwException)
+ {
+ // This function is used by ResourceManager.GetResourceFileName().
+ // ResourceManager searches for resource using CultureInfo.Name,
+ // so we should check against CultureInfo.Name.
+
+ for (int i=0; i<cultureName.Length; i++) {
+ char c = cultureName[i];
+
+ if (Char.IsLetterOrDigit(c) || c=='-' || c=='_') {
+ continue;
+ }
+ if (throwException) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", cultureName));
+ }
+ return false;
+ }
+ return true;
+
+ }
+
+ internal static bool VerifyCultureName(CultureInfo culture, bool throwException) {
+ Contract.Assert(culture!=null, "[CultureInfo.VerifyCultureName]culture!=null");
+
+ //If we have an instance of one of our CultureInfos, the user can't have changed the
+ //name and we know that all names are valid in files.
+ if (!culture.m_isInherited) {
+ return true;
+ }
+
+ return VerifyCultureName(culture.Name, throwException);
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrentCulture
+ //
+ // This instance provides methods based on the current user settings.
+ // These settings are volatile and may change over the lifetime of the
+ // thread.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static CultureInfo CurrentCulture
+ {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+#if !FEATURE_CORECLR
+ return Thread.CurrentThread.CurrentCulture;
+#else
+ // In the case of CoreCLR, Thread.m_CurrentCulture and
+ // Thread.m_CurrentUICulture are thread static so as not to let
+ // CultureInfo objects leak across AppDomain boundaries. The
+ // fact that these fields are thread static introduces overhead
+ // in accessing them (through Thread.CurrentCulture). There is
+ // also overhead in accessing Thread.CurrentThread. In this
+ // case, we can avoid the overhead of Thread.CurrentThread
+ // because these fields are thread static, and so do not
+ // require a Thread instance to be accessed.
+#if FEATURE_APPX
+ if(AppDomain.IsAppXModel()) {
+ CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
+ if (culture != null)
+ return culture;
+ }
+#endif
+ return Thread.m_CurrentCulture ??
+ s_DefaultThreadCurrentCulture ??
+ s_userDefaultCulture ??
+ UserDefaultCulture;
+#endif
+ }
+
+ set {
+#if FEATURE_APPX
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if (AppDomain.IsAppXModel()) {
+ if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
+ // successfully set the culture, otherwise fallback to legacy path
+ return;
+ }
+ }
+#endif
+ Thread.CurrentThread.CurrentCulture = value;
+ }
+ }
+
+ //
+ // This is the equivalence of the Win32 GetUserDefaultLCID()
+ //
+ internal static CultureInfo UserDefaultCulture {
+ get
+ {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ CultureInfo temp = s_userDefaultCulture;
+ if (temp == null)
+ {
+ //
+ // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
+ // against recursion problem just in case if somebody called CurrentCulture from the CultureInfo
+ // creation path. the recursion can happen if the current user culture is a replaced custom culture.
+ //
+
+ s_userDefaultCulture = CultureInfo.InvariantCulture;
+ temp = InitUserDefaultCulture();
+ s_userDefaultCulture = temp;
+ }
+ return (temp);
+ }
+ }
+
+ //
+ // This is the equivalence of the Win32 GetUserDefaultUILanguage()
+ //
+ internal static CultureInfo UserDefaultUICulture {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ CultureInfo temp = s_userDefaultUICulture;
+ if (temp == null)
+ {
+ //
+ // setting the s_userDefaultCulture with invariant culture before intializing it is a protection
+ // against recursion problem just in case if somebody called CurrentUICulture from the CultureInfo
+ // creation path. the recursion can happen if the current user culture is a replaced custom culture.
+ //
+
+ s_userDefaultUICulture = CultureInfo.InvariantCulture;
+
+ temp = InitUserDefaultUICulture();
+ s_userDefaultUICulture = temp;
+ }
+ return (temp);
+ }
+ }
+
+
+ public static CultureInfo CurrentUICulture {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+#if !FEATURE_CORECLR
+ return Thread.CurrentThread.CurrentUICulture;
+#else
+ // In the case of CoreCLR, Thread.m_CurrentCulture and
+ // Thread.m_CurrentUICulture are thread static so as not to let
+ // CultureInfo objects leak across AppDomain boundaries. The
+ // fact that these fields are thread static introduces overhead
+ // in accessing them (through Thread.CurrentCulture). There is
+ // also overhead in accessing Thread.CurrentThread. In this
+ // case, we can avoid the overhead of Thread.CurrentThread
+ // because these fields are thread static, and so do not
+ // require a Thread instance to be accessed.
+#if FEATURE_APPX
+ if(AppDomain.IsAppXModel()) {
+ CultureInfo culture = GetCultureInfoForUserPreferredLanguageInAppX();
+ if (culture != null)
+ return culture;
+ }
+#endif
+ return Thread.m_CurrentUICulture ??
+ s_DefaultThreadCurrentUICulture ??
+ s_userDefaultUICulture ??
+ UserDefaultUICulture;
+#endif
+ }
+
+ set {
+#if FEATURE_APPX
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if (AppDomain.IsAppXModel()) {
+ if (SetCultureInfoForUserPreferredLanguageInAppX(value)) {
+ // successfully set the culture, otherwise fallback to legacy path
+ return;
+ }
+ }
+#endif
+ Thread.CurrentThread.CurrentUICulture = value;
+ }
+ }
+
+
+ //
+ // This is the equivalence of the Win32 GetSystemDefaultUILanguage()
+ //
+ public static CultureInfo InstalledUICulture {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ CultureInfo temp = s_InstalledUICultureInfo;
+ if (temp == null) {
+ String strDefault = GetSystemDefaultUILanguage();
+ temp = GetCultureByName(strDefault, true);
+
+ if (temp == null)
+ {
+ temp = InvariantCulture;
+ }
+
+ temp.m_isReadOnly = true;
+ s_InstalledUICultureInfo = temp;
+ }
+ return (temp);
+ }
+ }
+
+ public static CultureInfo DefaultThreadCurrentCulture {
+ get {
+ return s_DefaultThreadCurrentCulture;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
+#pragma warning restore 618
+ set {
+
+ // If you add pre-conditions to this method, check to see if you also need to
+ // add them to Thread.CurrentCulture.set.
+
+ s_DefaultThreadCurrentCulture = value;
+ }
+ }
+
+ public static CultureInfo DefaultThreadCurrentUICulture {
+ get {
+ return s_DefaultThreadCurrentUICulture;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
+#pragma warning restore 618
+ set {
+
+ //If they're trying to use a Culture with a name that we can't use in resource lookup,
+ //don't even let them set it on the thread.
+
+ // If you add more pre-conditions to this method, check to see if you also need to
+ // add them to Thread.CurrentUICulture.set.
+
+ if (value != null)
+ {
+ CultureInfo.VerifyCultureName(value, true);
+ }
+
+ s_DefaultThreadCurrentUICulture = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // InvariantCulture
+ //
+ // This instance provides methods, for example for casing and sorting,
+ // that are independent of the system and current user settings. It
+ // should be used only by processes such as some system services that
+ // require such invariant results (eg. file systems). In general,
+ // the results are not linguistically correct and do not match any
+ // culture info.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public static CultureInfo InvariantCulture {
+ [Pure]
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ return (s_InvariantCultureInfo);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Parent
+ //
+ // Return the parent CultureInfo for the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public virtual CultureInfo Parent
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ if (null == m_parent)
+ {
+ try
+ {
+ string parentName = this.m_cultureData.SPARENT;
+
+ if (String.IsNullOrEmpty(parentName))
+ {
+ m_parent = InvariantCulture;
+ }
+ else
+ {
+ m_parent = new CultureInfo(parentName, this.m_cultureData.UseUserOverride);
+ }
+ }
+ catch (ArgumentException)
+ {
+ // For whatever reason our IPARENT or SPARENT wasn't correct, so use invariant
+ // We can't allow ourselves to fail. In case of custom cultures the parent of the
+ // current custom culture isn't installed.
+ m_parent = InvariantCulture;
+ }
+ }
+ return m_parent;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // LCID
+ //
+ // Returns a properly formed culture identifier for the current
+ // culture info.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+#if FEATURE_USE_LCID
+ public virtual int LCID {
+ get {
+ return (this.m_cultureData.ILANGUAGE);
+ }
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // BaseInputLanguage
+ //
+ // Essentially an LCID, though one that may be different than LCID in the case
+ // of a customized culture (LCID == LOCALE_CUSTOM_UNSPECIFIED).
+ //
+ ////////////////////////////////////////////////////////////////////////
+#if FEATURE_USE_LCID
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int KeyboardLayoutId
+ {
+ get
+ {
+ int keyId = this.m_cultureData.IINPUTLANGUAGEHANDLE;
+
+ // Not a customized culture, return the default Keyboard layout ID, which is the same as the language ID.
+ return (keyId);
+ }
+ }
+#endif
+
+ public static CultureInfo[] GetCultures(CultureTypes types) {
+ Contract.Ensures(Contract.Result<CultureInfo[]>() != null);
+ // internally we treat UserCustomCultures as Supplementals but v2
+ // treats as Supplementals and Replacements
+ if((types & CultureTypes.UserCustomCulture) == CultureTypes.UserCustomCulture)
+ {
+ types |= CultureTypes.ReplacementCultures;
+ }
+ return (CultureData.GetCultures(types));
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Name
+ //
+ // Returns the full name of the CultureInfo. The name is in format like
+ // "en-US" This version does NOT include sort information in the name.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String Name {
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ // We return non sorting name here.
+ if (this.m_nonSortName == null) {
+ this.m_nonSortName = this.m_cultureData.SNAME;
+ if (this.m_nonSortName == null) {
+ this.m_nonSortName = String.Empty;
+ }
+ }
+ return this.m_nonSortName;
+ }
+ }
+
+ // This one has the sort information (ie: de-DE_phoneb)
+ internal String SortName
+ {
+ get
+ {
+ if (this.m_sortName == null)
+ {
+ this.m_sortName = this.m_cultureData.SCOMPAREINFO;
+ }
+
+ return this.m_sortName;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String IetfLanguageTag
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ // special case the compatibility cultures
+ switch (this.Name)
+ {
+ case "zh-CHT":
+ return "zh-Hant";
+ case "zh-CHS":
+ return "zh-Hans";
+ default:
+ return this.Name;
+ }
+ }
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // DisplayName
+ //
+ // Returns the full name of the CultureInfo in the localized language.
+ // For example, if the localized language of the runtime is Spanish and the CultureInfo is
+ // US English, "Ingles (Estados Unidos)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String DisplayName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Assert(m_name != null, "[CultureInfo.DisplayName]Always expect m_name to be set");
+
+ return m_cultureData.SLOCALIZEDDISPLAYNAME;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetNativeName
+ //
+ // Returns the full name of the CultureInfo in the native language.
+ // For example, if the CultureInfo is US English, "English
+ // (United States)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String NativeName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SNATIVEDISPLAYNAME);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetEnglishName
+ //
+ // Returns the full name of the CultureInfo in English.
+ // For example, if the CultureInfo is US English, "English
+ // (United States)" will be returned.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String EnglishName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SENGDISPLAYNAME);
+ }
+ }
+
+ // ie: en
+ public virtual String TwoLetterISOLanguageName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SISO639LANGNAME);
+ }
+ }
+
+ // ie: eng
+ public virtual String ThreeLetterISOLanguageName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SISO639LANGNAME2);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ThreeLetterWindowsLanguageName
+ //
+ // Returns the 3 letter windows language name for the current instance. eg: "ENU"
+ // The ISO names are much preferred
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ThreeLetterWindowsLanguageName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return (this.m_cultureData.SABBREVLANGNAME);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CompareInfo Read-Only Property
+ //
+ // Gets the CompareInfo for this culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual CompareInfo CompareInfo
+ {
+ get
+ {
+ Contract.Ensures(Contract.Result<CompareInfo>() != null);
+
+ if (this.compareInfo == null)
+ {
+ // Since CompareInfo's don't have any overrideable properties, get the CompareInfo from
+ // the Non-Overridden CultureInfo so that we only create one CompareInfo per culture
+ CompareInfo temp = UseUserOverride
+ ? GetCultureInfo(this.m_name).CompareInfo
+ : new CompareInfo(this);
+ if (CompatibilitySwitches.IsCompatibilityBehaviorDefined)
+ {
+ this.compareInfo = temp;
+ }
+ else
+ {
+ return temp;
+ }
+ }
+ return (compareInfo);
+ }
+ }
+
+#if !FEATURE_CORECLR
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // RegionInfo
+ //
+ // Gets the RegionInfo for this culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ private RegionInfo Region
+ {
+ get
+ {
+ if (regionInfo==null)
+ {
+ // Make a new regionInfo
+ RegionInfo tempRegionInfo = new RegionInfo(this.m_cultureData);
+ regionInfo = tempRegionInfo;
+ }
+ return (regionInfo);
+ }
+ }
+#endif // FEATURE_CORECLR
+
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // TextInfo
+ //
+ // Gets the TextInfo for this culture.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public virtual TextInfo TextInfo {
+ get {
+ Contract.Ensures(Contract.Result<TextInfo>() != null);
+
+ if (textInfo==null)
+ {
+ // Make a new textInfo
+ TextInfo tempTextInfo = new TextInfo(this.m_cultureData);
+ tempTextInfo.SetReadOnlyState(m_isReadOnly);
+
+ if (CompatibilitySwitches.IsCompatibilityBehaviorDefined)
+ {
+ textInfo = tempTextInfo;
+ }
+ else
+ {
+ return tempTextInfo;
+ }
+ }
+ return (textInfo);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CultureInfo as the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Equals(Object value)
+ {
+ if (Object.ReferenceEquals(this, value))
+ return true;
+
+ CultureInfo that = value as CultureInfo;
+
+ if (that != null)
+ {
+ // using CompareInfo to verify the data passed through the constructor
+ // CultureInfo(String cultureName, String textAndCompareCultureName)
+
+ return (this.Name.Equals(that.Name) && this.CompareInfo.Equals(that.CompareInfo));
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A
+ // and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode() + this.CompareInfo.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns the name of the CultureInfo,
+ // eg. "de-DE_phoneb", "en-US", or "fj-FJ".
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override String ToString()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ Contract.Assert(m_name != null, "[CultureInfo.ToString]Always expect m_name to be set");
+ return m_name;
+ }
+
+
+ public virtual Object GetFormat(Type formatType) {
+ if (formatType == typeof(NumberFormatInfo)) {
+ return (NumberFormat);
+ }
+ if (formatType == typeof(DateTimeFormatInfo)) {
+ return (DateTimeFormat);
+ }
+ return (null);
+ }
+
+ public virtual bool IsNeutralCulture {
+ get {
+ return this.m_cultureData.IsNeutralCulture;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public CultureTypes CultureTypes
+ {
+ get
+ {
+ CultureTypes types = 0;
+
+ if (m_cultureData.IsNeutralCulture)
+ types |= CultureTypes.NeutralCultures;
+ else
+ types |= CultureTypes.SpecificCultures;
+
+ types |= m_cultureData.IsWin32Installed ? CultureTypes.InstalledWin32Cultures : 0;
+
+// Disable warning 618: System.Globalization.CultureTypes.FrameworkCultures' is obsolete
+#pragma warning disable 618
+ types |= m_cultureData.IsFramework ? CultureTypes.FrameworkCultures : 0;
+
+#pragma warning restore 618
+ types |= m_cultureData.IsSupplementalCustomCulture ? CultureTypes.UserCustomCulture : 0;
+ types |= m_cultureData.IsReplacementCulture ? CultureTypes.ReplacementCultures | CultureTypes.UserCustomCulture : 0;
+
+ return types;
+ }
+ }
+#endif
+
+ public virtual NumberFormatInfo NumberFormat {
+ get
+ {
+ Contract.Ensures(Contract.Result<NumberFormatInfo>() != null);
+
+ if (numInfo == null) {
+ NumberFormatInfo temp = new NumberFormatInfo(this.m_cultureData);
+ temp.isReadOnly = m_isReadOnly;
+ numInfo = temp;
+ }
+ return (numInfo);
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ numInfo = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetDateTimeFormatInfo
+ //
+ // Create a DateTimeFormatInfo, and fill in the properties according to
+ // the CultureID.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public virtual DateTimeFormatInfo DateTimeFormat {
+ get {
+ Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
+
+ if (dateTimeInfo == null) {
+ // Change the calendar of DTFI to the specified calendar of this CultureInfo.
+ DateTimeFormatInfo temp = new DateTimeFormatInfo(
+ this.m_cultureData, this.Calendar);
+ temp.m_isReadOnly = m_isReadOnly;
+ System.Threading.Thread.MemoryBarrier();
+ dateTimeInfo = temp;
+ }
+ return (dateTimeInfo);
+ }
+
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ dateTimeInfo = value;
+ }
+ }
+
+
+
+ public void ClearCachedData() {
+ s_userDefaultUICulture = null;
+ s_userDefaultCulture = null;
+
+ RegionInfo.s_currentRegionInfo = null;
+#if !FEATURE_CORECLR // System.TimeZone does not exist in CoreCLR
+ TimeZone.ResetTimeZone();
+#endif // FEATURE_CORECLR
+ TimeZoneInfo.ClearCachedData();
+ // Delete the cached cultures.
+ s_LcidCachedCultures = null;
+ s_NameCachedCultures = null;
+
+ CultureData.ClearCachedData();
+ }
+
+ /*=================================GetCalendarInstance==========================
+ **Action: Map a Win32 CALID to an instance of supported calendar.
+ **Returns: An instance of calendar.
+ **Arguments: calType The Win32 CALID
+ **Exceptions:
+ ** Shouldn't throw exception since the calType value is from our data table or from Win32 registry.
+ ** If we are in trouble (like getting a weird value from Win32 registry), just return the GregorianCalendar.
+ ============================================================================*/
+ internal static Calendar GetCalendarInstance(int calType) {
+ if (calType==Calendar.CAL_GREGORIAN) {
+ return (new GregorianCalendar());
+ }
+ return GetCalendarInstanceRare(calType);
+ }
+
+ //This function exists as a shortcut to prevent us from loading all of the non-gregorian
+ //calendars unless they're required.
+ internal static Calendar GetCalendarInstanceRare(int calType) {
+ Contract.Assert(calType!=Calendar.CAL_GREGORIAN, "calType!=Calendar.CAL_GREGORIAN");
+
+ switch (calType) {
+ case Calendar.CAL_GREGORIAN_US: // Gregorian (U.S.) calendar
+ case Calendar.CAL_GREGORIAN_ME_FRENCH: // Gregorian Middle East French calendar
+ case Calendar.CAL_GREGORIAN_ARABIC: // Gregorian Arabic calendar
+ case Calendar.CAL_GREGORIAN_XLIT_ENGLISH: // Gregorian Transliterated English calendar
+ case Calendar.CAL_GREGORIAN_XLIT_FRENCH: // Gregorian Transliterated French calendar
+ return (new GregorianCalendar((GregorianCalendarTypes)calType));
+ case Calendar.CAL_TAIWAN: // Taiwan Era calendar
+ return (new TaiwanCalendar());
+ case Calendar.CAL_JAPAN: // Japanese Emperor Era calendar
+ return (new JapaneseCalendar());
+ case Calendar.CAL_KOREA: // Korean Tangun Era calendar
+ return (new KoreanCalendar());
+ case Calendar.CAL_THAI: // Thai calendar
+ return (new ThaiBuddhistCalendar());
+ case Calendar.CAL_HIJRI: // Hijri (Arabic Lunar) calendar
+ return (new HijriCalendar());
+ case Calendar.CAL_HEBREW: // Hebrew (Lunar) calendar
+ return (new HebrewCalendar());
+ case Calendar.CAL_UMALQURA:
+ return (new UmAlQuraCalendar());
+ case Calendar.CAL_PERSIAN:
+ return (new PersianCalendar());
+ case Calendar.CAL_CHINESELUNISOLAR:
+ return (new ChineseLunisolarCalendar());
+ case Calendar.CAL_JAPANESELUNISOLAR:
+ return (new JapaneseLunisolarCalendar());
+ case Calendar.CAL_KOREANLUNISOLAR:
+ return (new KoreanLunisolarCalendar());
+ case Calendar.CAL_TAIWANLUNISOLAR:
+ return (new TaiwanLunisolarCalendar());
+ }
+ return (new GregorianCalendar());
+ }
+
+
+ /*=================================Calendar==========================
+ **Action: Return/set the default calendar used by this culture.
+ ** This value can be overridden by regional option if this is a current culture.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ** ArgumentNull_Obj if the set value is null.
+ ============================================================================*/
+
+
+ public virtual Calendar Calendar {
+ get {
+ Contract.Ensures(Contract.Result<Calendar>() != null);
+ if (calendar == null) {
+ Contract.Assert(this.m_cultureData.CalendarIds.Length > 0, "this.m_cultureData.CalendarIds.Length > 0");
+ // Get the default calendar for this culture. Note that the value can be
+ // from registry if this is a user default culture.
+ Calendar newObj = this.m_cultureData.DefaultCalendar;
+
+ System.Threading.Thread.MemoryBarrier();
+ newObj.SetReadOnlyState(m_isReadOnly);
+ calendar = newObj;
+ }
+ return (calendar);
+ }
+ }
+
+ /*=================================OptionCalendars==========================
+ **Action: Return an array of the optional calendar for this culture.
+ **Returns: an array of Calendar.
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+
+ public virtual Calendar[] OptionalCalendars {
+ get {
+ Contract.Ensures(Contract.Result<Calendar[]>() != null);
+
+ //
+ // This property always returns a new copy of the calendar array.
+ //
+ int[] calID = this.m_cultureData.CalendarIds;
+ Calendar [] cals = new Calendar[calID.Length];
+ for (int i = 0; i < cals.Length; i++) {
+ cals[i] = GetCalendarInstance(calID[i]);
+ }
+ return (cals);
+ }
+ }
+
+
+ public bool UseUserOverride {
+ get {
+ return (this.m_cultureData.UseUserOverride);
+ }
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public CultureInfo GetConsoleFallbackUICulture()
+ {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ CultureInfo temp = m_consoleFallbackCulture;
+ if (temp == null)
+ {
+ temp = CreateSpecificCulture(this.m_cultureData.SCONSOLEFALLBACKNAME);
+ temp.m_isReadOnly = true;
+ m_consoleFallbackCulture = temp;
+ }
+ return (temp);
+ }
+#endif
+
+ public virtual Object Clone()
+ {
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ CultureInfo ci = (CultureInfo)MemberwiseClone();
+ ci.m_isReadOnly = false;
+
+ //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
+ //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
+ if (!m_isInherited)
+ {
+ if (this.dateTimeInfo != null)
+ {
+ ci.dateTimeInfo = (DateTimeFormatInfo)this.dateTimeInfo.Clone();
+ }
+ if (this.numInfo != null)
+ {
+ ci.numInfo = (NumberFormatInfo)this.numInfo.Clone();
+ }
+
+ }
+ else
+ {
+ ci.DateTimeFormat = (DateTimeFormatInfo)this.DateTimeFormat.Clone();
+ ci.NumberFormat = (NumberFormatInfo)this.NumberFormat.Clone();
+ }
+
+ if (textInfo != null)
+ {
+ ci.textInfo = (TextInfo) textInfo.Clone();
+ }
+
+ if (calendar != null)
+ {
+ ci.calendar = (Calendar) calendar.Clone();
+ }
+
+ return (ci);
+ }
+
+
+ public static CultureInfo ReadOnly(CultureInfo ci) {
+ if (ci == null) {
+ throw new ArgumentNullException("ci");
+ }
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ Contract.EndContractBlock();
+
+ if (ci.IsReadOnly) {
+ return (ci);
+ }
+ CultureInfo newInfo = (CultureInfo)(ci.MemberwiseClone());
+
+ if (!ci.IsNeutralCulture)
+ {
+ //If this is exactly our type, we can make certain optimizations so that we don't allocate NumberFormatInfo or DTFI unless
+ //they've already been allocated. If this is a derived type, we'll take a more generic codepath.
+ if (!ci.m_isInherited) {
+ if (ci.dateTimeInfo != null) {
+ newInfo.dateTimeInfo = DateTimeFormatInfo.ReadOnly(ci.dateTimeInfo);
+ }
+ if (ci.numInfo != null) {
+ newInfo.numInfo = NumberFormatInfo.ReadOnly(ci.numInfo);
+ }
+
+ } else {
+ newInfo.DateTimeFormat = DateTimeFormatInfo.ReadOnly(ci.DateTimeFormat);
+ newInfo.NumberFormat = NumberFormatInfo.ReadOnly(ci.NumberFormat);
+ }
+ }
+
+ if (ci.textInfo != null)
+ {
+ newInfo.textInfo = TextInfo.ReadOnly(ci.textInfo);
+ }
+
+ if (ci.calendar != null)
+ {
+ newInfo.calendar = Calendar.ReadOnly(ci.calendar);
+ }
+
+ // Don't set the read-only flag too early.
+ // We should set the read-only flag here. Otherwise, info.DateTimeFormat will not be able to set.
+ newInfo.m_isReadOnly = true;
+
+ return (newInfo);
+ }
+
+
+ public bool IsReadOnly {
+ get {
+ return (m_isReadOnly);
+ }
+ }
+
+ private void VerifyWritable() {
+ if (m_isReadOnly) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ // For resource lookup, we consider a culture the invariant culture by name equality.
+ // We perform this check frequently during resource lookup, so adding a property for
+ // improved readability.
+ internal bool HasInvariantCultureName
+ {
+ get { return Name == CultureInfo.InvariantCulture.Name; }
+ }
+
+ // Helper function both both overloads of GetCachedReadOnlyCulture. If lcid is 0, we use the name.
+ // If lcid is -1, use the altName and create one of those special SQL cultures.
+ internal static CultureInfo GetCultureInfoHelper(int lcid, string name, string altName)
+ {
+ // There is a race condition in this code with the side effect that the second thread's value
+ // clobbers the first in the dictionary. This is an acceptable race condition since the CultureInfo objects
+ // are content equal (but not reference equal). Since we make no guarantees there, this race condition is
+ // acceptable.
+ // See code:Dictionary#DictionaryVersusHashtableThreadSafety for details on Dictionary versus
+ // Hashtable thread safety.
+
+ // retval is our return value.
+ CultureInfo retval;
+
+ // Temporary hashtable for the names.
+ Hashtable tempNameHT = s_NameCachedCultures;
+
+ if (name != null)
+ {
+ name = CultureData.AnsiToLower(name);
+ }
+
+ if (altName != null)
+ {
+ altName = CultureData.AnsiToLower(altName);
+ }
+
+ // We expect the same result for both hashtables, but will test individually for added safety.
+ if (tempNameHT == null)
+ {
+ tempNameHT = Hashtable.Synchronized(new Hashtable());
+ }
+ else
+ {
+ // If we are called by name, check if the object exists in the hashtable. If so, return it.
+ if (lcid == -1)
+ {
+ retval = (CultureInfo)tempNameHT[name + '\xfffd' + altName];
+ if (retval != null)
+ {
+ return retval;
+ }
+ }
+ else if (lcid == 0)
+ {
+ retval = (CultureInfo)tempNameHT[name];
+ if (retval != null)
+ {
+ return retval;
+ }
+ }
+ }
+#if FEATURE_USE_LCID
+ // Next, the Lcid table.
+ Hashtable tempLcidHT = s_LcidCachedCultures;
+
+ if (tempLcidHT == null)
+ {
+ // Case insensitive is not an issue here, save the constructor call.
+ tempLcidHT = Hashtable.Synchronized(new Hashtable());
+ }
+ else
+ {
+ // If we were called by Lcid, check if the object exists in the table. If so, return it.
+ if (lcid > 0)
+ {
+ retval = (CultureInfo) tempLcidHT[lcid];
+ if (retval != null)
+ {
+ return retval;
+ }
+ }
+ }
+#endif
+ // We now have two temporary hashtables and the desired object was not found.
+ // We'll construct it. We catch any exceptions from the constructor call and return null.
+ try
+ {
+ switch(lcid)
+ {
+ case -1:
+ // call the private constructor
+ retval = new CultureInfo(name, altName);
+ break;
+
+ case 0:
+ retval = new CultureInfo(name, false);
+ break;
+
+ default:
+#if FEATURE_USE_LCID
+ retval = new CultureInfo(lcid, false);
+ break;
+#else
+ return null;
+#endif
+ }
+ }
+ catch(ArgumentException)
+ {
+ return null;
+ }
+
+ // Set it to read-only
+ retval.m_isReadOnly = true;
+
+ if (lcid == -1)
+ {
+ // This new culture will be added only to the name hash table.
+ tempNameHT[name + '\xfffd' + altName] = retval;
+
+ // when lcid == -1 then TextInfo object is already get created and we need to set it as read only.
+ retval.TextInfo.SetReadOnlyState(true);
+ }
+ else
+ {
+ // Remember our name (as constructed). Do NOT use alternate sort name versions because
+ // we have internal state representing the sort. (So someone would get the wrong cached version)
+ string newName = CultureData.AnsiToLower(retval.m_name);
+
+ // We add this new culture info object to both tables.
+ tempNameHT[newName] = retval;
+#if FEATURE_USE_LCID
+ const int LCID_ZH_CHS_HANS = 0x0004;
+ const int LCID_ZH_CHT_HANT = 0x7c04;
+
+ if ((retval.LCID == LCID_ZH_CHS_HANS && newName == "zh-hans")
+ || (retval.LCID == LCID_ZH_CHT_HANT && newName == "zh-hant"))
+ {
+ // do nothing because we only want zh-CHS and zh-CHT to cache
+ // by lcid
+ }
+ else
+ {
+ tempLcidHT[retval.LCID] = retval;
+ }
+
+#endif
+ }
+
+#if FEATURE_USE_LCID
+ // Copy the two hashtables to the corresponding member variables. This will potentially overwrite
+ // new tables simultaneously created by a new thread, but maximizes thread safety.
+ if(-1 != lcid)
+ {
+ // Only when we modify the lcid hash table, is there a need to overwrite.
+ s_LcidCachedCultures = tempLcidHT;
+ }
+#endif
+
+ s_NameCachedCultures = tempNameHT;
+
+ // Finally, return our new CultureInfo object.
+ return retval;
+ }
+
+#if FEATURE_USE_LCID
+ // Gets a cached copy of the specified culture from an internal hashtable (or creates it
+ // if not found). (LCID version)... use named version
+ public static CultureInfo GetCultureInfo(int culture)
+ {
+ // Must check for -1 now since the helper function uses the value to signal
+ // the altCulture code path for SQL Server.
+ // Also check for zero as this would fail trying to add as a key to the hash.
+ if (culture <= 0) {
+ throw new ArgumentOutOfRangeException("culture",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ Contract.EndContractBlock();
+ CultureInfo retval = GetCultureInfoHelper(culture, null, null);
+ if (null == retval)
+ {
+ throw new CultureNotFoundException(
+ "culture", culture, Environment.GetResourceString("Argument_CultureNotSupported"));
+ }
+ return retval;
+ }
+#endif
+
+ // Gets a cached copy of the specified culture from an internal hashtable (or creates it
+ // if not found). (Named version)
+ public static CultureInfo GetCultureInfo(string name)
+ {
+ // Make sure we have a valid, non-zero length string as name
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ Contract.EndContractBlock();
+
+ CultureInfo retval = GetCultureInfoHelper(0, name, null);
+ if (retval == null)
+ {
+ throw new CultureNotFoundException(
+ "name", name, Environment.GetResourceString("Argument_CultureNotSupported"));
+
+ }
+ return retval;
+ }
+
+ // Gets a cached copy of the specified culture from an internal hashtable (or creates it
+ // if not found).
+ public static CultureInfo GetCultureInfo(string name, string altName)
+ {
+ // Make sure we have a valid, non-zero length string as name
+ if (null == name)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ if (null == altName)
+ {
+ throw new ArgumentNullException("altName");
+ }
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+ Contract.EndContractBlock();
+
+ CultureInfo retval = GetCultureInfoHelper(-1, name, altName);
+ if (retval == null)
+ {
+ throw new CultureNotFoundException("name or altName",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Argument_OneOfCulturesNotSupported"),
+ name,
+ altName));
+ }
+ return retval;
+ }
+
+
+ // This function is deprecated, we don't like it
+ public static CultureInfo GetCultureInfoByIetfLanguageTag(string name)
+ {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ // Disallow old zh-CHT/zh-CHS names
+ if (name == "zh-CHT" || name == "zh-CHS")
+ {
+ throw new CultureNotFoundException(
+ "name",
+ String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
+ );
+ }
+
+ CultureInfo ci = GetCultureInfo(name);
+
+ // Disallow alt sorts and es-es_TS
+ if (ci.LCID > 0xffff || ci.LCID == 0x040a)
+ {
+ throw new CultureNotFoundException(
+ "name",
+ String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_CultureIetfNotSupported"), name)
+ );
+ }
+
+ return ci;
+ }
+
+ private static volatile bool s_isTaiwanSku;
+ private static volatile bool s_haveIsTaiwanSku;
+ internal static bool IsTaiwanSku
+ {
+ get
+ {
+ if (!s_haveIsTaiwanSku)
+ {
+ s_isTaiwanSku = (GetSystemDefaultUILanguage() == "zh-TW");
+ s_haveIsTaiwanSku = true;
+ }
+ return (bool)s_isTaiwanSku;
+ }
+ }
+
+ //
+ // Helper Methods.
+ //
+
+ // Get Locale Info Ex calls. So we don't have to muck with the different int/string return types we declared two of these:
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String nativeGetLocaleInfoEx(String localeName, uint field);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int nativeGetLocaleInfoExInt(String localeName, uint field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool nativeSetThreadLocale(String localeName);
+
+ [System.Security.SecurityCritical]
+ private static String GetDefaultLocaleName(int localeType)
+ {
+ Contract.Assert(localeType == LOCALE_USER_DEFAULT || localeType == LOCALE_SYSTEM_DEFAULT, "[CultureInfo.GetDefaultLocaleName] localeType must be LOCALE_USER_DEFAULT or LOCALE_SYSTEM_DEFAULT");
+
+ string localeName = null;
+ if(InternalGetDefaultLocaleName(localeType, JitHelpers.GetStringHandleOnStack(ref localeName)))
+ {
+ return localeName;
+ }
+ return string.Empty;
+ }
+
+ // Get the default locale name
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool InternalGetDefaultLocaleName(int localetype, StringHandleOnStack localeString);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static String GetUserDefaultUILanguage()
+ {
+ string userDefaultUiLanguage = null;
+ if(InternalGetUserDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref userDefaultUiLanguage)))
+ {
+ return userDefaultUiLanguage;
+ }
+ return String.Empty;
+ }
+
+ // Get the user's default UI language, return locale name
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool InternalGetUserDefaultUILanguage(StringHandleOnStack userDefaultUiLanguage);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static String GetSystemDefaultUILanguage()
+ {
+ string systemDefaultUiLanguage = null;
+ if(InternalGetSystemDefaultUILanguage(JitHelpers.GetStringHandleOnStack(ref systemDefaultUiLanguage)))
+ {
+ return systemDefaultUiLanguage;
+ }
+ return String.Empty;
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool InternalGetSystemDefaultUILanguage(StringHandleOnStack systemDefaultUiLanguage);
+
+// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String[] nativeGetResourceFallbackArray();
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs
new file mode 100644
index 0000000000..0486cc9d17
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CultureNotFoundException.cs
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Globalization {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public partial class CultureNotFoundException : ArgumentException, ISerializable
+ {
+ private string m_invalidCultureName; // unrecognized culture name
+ private Nullable<int> m_invalidCultureId; // unrecognized culture Lcid
+
+ public CultureNotFoundException()
+ : base(DefaultMessage)
+ {
+ }
+
+ public CultureNotFoundException(String message)
+ : base(message)
+ {
+ }
+
+ public CultureNotFoundException(String paramName, String message)
+ : base(message, paramName)
+ {
+ }
+
+ public CultureNotFoundException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
+
+ public CultureNotFoundException(String paramName, int invalidCultureId, String message)
+ : base(message, paramName)
+ {
+ m_invalidCultureId = invalidCultureId;
+ }
+
+ public CultureNotFoundException(String message, int invalidCultureId, Exception innerException)
+ : base(message, innerException)
+ {
+ m_invalidCultureId = invalidCultureId;
+ }
+
+ public CultureNotFoundException(String paramName, string invalidCultureName, String message)
+ : base(message, paramName)
+ {
+ m_invalidCultureName = invalidCultureName;
+ }
+
+ public CultureNotFoundException(String message, string invalidCultureName, Exception innerException)
+ : base(message, innerException)
+ {
+ m_invalidCultureName = invalidCultureName;
+ }
+
+ protected CultureNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ m_invalidCultureId = (Nullable<int>) info.GetValue("InvalidCultureId", typeof(Nullable<int>));
+ m_invalidCultureName = (string) info.GetValue("InvalidCultureName", typeof(string));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ Nullable<int> invalidCultureId = null;
+ invalidCultureId = m_invalidCultureId;
+ info.AddValue("InvalidCultureId", invalidCultureId, typeof(Nullable<int>));
+ info.AddValue("InvalidCultureName", m_invalidCultureName, typeof(string));
+ }
+ public virtual Nullable<int> InvalidCultureId
+ {
+ get { return m_invalidCultureId; }
+ }
+
+ public virtual string InvalidCultureName
+ {
+ get { return m_invalidCultureName; }
+ }
+
+ private static String DefaultMessage
+ {
+ get
+ {
+ return Environment.GetResourceString("Argument_CultureNotSupported");
+ }
+ }
+
+ private String FormatedInvalidCultureId
+ {
+ get
+ {
+ if (InvalidCultureId != null)
+ {
+ return String.Format(CultureInfo.InvariantCulture,
+ "{0} (0x{0:x4})", (int)InvalidCultureId);
+ }
+ return InvalidCultureName;
+ }
+ }
+
+ public override String Message
+ {
+ get
+ {
+ String s = base.Message;
+ if (
+ m_invalidCultureId != null ||
+ m_invalidCultureName != null)
+ {
+ String valueMessage = Environment.GetResourceString("Argument_CultureInvalidIdentifier", FormatedInvalidCultureId);
+ if (s == null)
+ return valueMessage;
+ return s + Environment.NewLine + valueMessage;
+ }
+ return s;
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/CultureTypes.cs b/src/mscorlib/src/System/Globalization/CultureTypes.cs
new file mode 100644
index 0000000000..d506d50c9d
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/CultureTypes.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// The enumeration constants used in CultureInfo.GetCultures().
+//
+// Note that this isn't exposed in Silverlight
+namespace System.Globalization {
+
+
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CultureTypes
+ {
+ NeutralCultures = 0x0001, // Neutral cultures are cultures like "en", "de", "zh", etc, for enumeration this includes ALL neutrals regardless of other flags
+ SpecificCultures = 0x0002, // Non-netural cultuers. Examples are "en-us", "zh-tw", etc., for enumeration this includes ALL specifics regardless of other flags
+ InstalledWin32Cultures = 0x0004, // Win32 installed cultures in the system and exists in the framework too., this is effectively all cultures
+
+ AllCultures = NeutralCultures | SpecificCultures | InstalledWin32Cultures,
+
+ UserCustomCulture = 0x0008, // User defined custom culture
+ ReplacementCultures = 0x0010, // User defined replacement custom culture.
+ [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")]
+ WindowsOnlyCultures = 0x0020, // this will always return empty list.
+ [Obsolete("This value has been deprecated. Please use other values in CultureTypes.")]
+ FrameworkCultures = 0x0040, // will return only the v2 cultures marked as Framework culture.
+ }
+
+}
diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormat.cs b/src/mscorlib/src/System/Globalization/DateTimeFormat.cs
new file mode 100644
index 0000000000..228e5f56a2
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DateTimeFormat.cs
@@ -0,0 +1,1054 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+ using System.Text;
+ using System.Threading;
+ using System.Globalization;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ /*
+ Customized format patterns:
+ P.S. Format in the table below is the internal number format used to display the pattern.
+
+ Patterns Format Description Example
+ ========= ========== ===================================== ========
+ "h" "0" hour (12-hour clock)w/o leading zero 3
+ "hh" "00" hour (12-hour clock)with leading zero 03
+ "hh*" "00" hour (12-hour clock)with leading zero 03
+
+ "H" "0" hour (24-hour clock)w/o leading zero 8
+ "HH" "00" hour (24-hour clock)with leading zero 08
+ "HH*" "00" hour (24-hour clock) 08
+
+ "m" "0" minute w/o leading zero
+ "mm" "00" minute with leading zero
+ "mm*" "00" minute with leading zero
+
+ "s" "0" second w/o leading zero
+ "ss" "00" second with leading zero
+ "ss*" "00" second with leading zero
+
+ "f" "0" second fraction (1 digit)
+ "ff" "00" second fraction (2 digit)
+ "fff" "000" second fraction (3 digit)
+ "ffff" "0000" second fraction (4 digit)
+ "fffff" "00000" second fraction (5 digit)
+ "ffffff" "000000" second fraction (6 digit)
+ "fffffff" "0000000" second fraction (7 digit)
+
+ "F" "0" second fraction (up to 1 digit)
+ "FF" "00" second fraction (up to 2 digit)
+ "FFF" "000" second fraction (up to 3 digit)
+ "FFFF" "0000" second fraction (up to 4 digit)
+ "FFFFF" "00000" second fraction (up to 5 digit)
+ "FFFFFF" "000000" second fraction (up to 6 digit)
+ "FFFFFFF" "0000000" second fraction (up to 7 digit)
+
+ "t" first character of AM/PM designator A
+ "tt" AM/PM designator AM
+ "tt*" AM/PM designator PM
+
+ "d" "0" day w/o leading zero 1
+ "dd" "00" day with leading zero 01
+ "ddd" short weekday name (abbreviation) Mon
+ "dddd" full weekday name Monday
+ "dddd*" full weekday name Monday
+
+
+ "M" "0" month w/o leading zero 2
+ "MM" "00" month with leading zero 02
+ "MMM" short month name (abbreviation) Feb
+ "MMMM" full month name Febuary
+ "MMMM*" full month name Febuary
+
+ "y" "0" two digit year (year % 100) w/o leading zero 0
+ "yy" "00" two digit year (year % 100) with leading zero 00
+ "yyy" "D3" year 2000
+ "yyyy" "D4" year 2000
+ "yyyyy" "D5" year 2000
+ ...
+
+ "z" "+0;-0" timezone offset w/o leading zero -8
+ "zz" "+00;-00" timezone offset with leading zero -08
+ "zzz" "+00;-00" for hour offset, "00" for minute offset full timezone offset -07:30
+ "zzz*" "+00;-00" for hour offset, "00" for minute offset full timezone offset -08:00
+
+ "K" -Local "zzz", e.g. -08:00
+ -Utc "'Z'", representing UTC
+ -Unspecified ""
+ -DateTimeOffset "zzzzz" e.g -07:30:15
+
+ "g*" the current era name A.D.
+
+ ":" time separator : -- DEPRECATED - Insert separator directly into pattern (eg: "H.mm.ss")
+ "/" date separator /-- DEPRECATED - Insert separator directly into pattern (eg: "M-dd-yyyy")
+ "'" quoted string 'ABC' will insert ABC into the formatted string.
+ '"' quoted string "ABC" will insert ABC into the formatted string.
+ "%" used to quote a single pattern characters E.g.The format character "%y" is to print two digit year.
+ "\" escaped character E.g. '\d' insert the character 'd' into the format string.
+ other characters insert the character into the format string.
+
+ Pre-defined format characters:
+ (U) to indicate Universal time is used.
+ (G) to indicate Gregorian calendar is used.
+
+ Format Description Real format Example
+ ========= ================================= ====================== =======================
+ "d" short date culture-specific 10/31/1999
+ "D" long data culture-specific Sunday, October 31, 1999
+ "f" full date (long date + short time) culture-specific Sunday, October 31, 1999 2:00 AM
+ "F" full date (long date + long time) culture-specific Sunday, October 31, 1999 2:00:00 AM
+ "g" general date (short date + short time) culture-specific 10/31/1999 2:00 AM
+ "G" general date (short date + long time) culture-specific 10/31/1999 2:00:00 AM
+ "m"/"M" Month/Day date culture-specific October 31
+(G) "o"/"O" Round Trip XML "yyyy-MM-ddTHH:mm:ss.fffffffK" 1999-10-31 02:00:00.0000000Z
+(G) "r"/"R" RFC 1123 date, "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'" Sun, 31 Oct 1999 10:00:00 GMT
+(G) "s" Sortable format, based on ISO 8601. "yyyy-MM-dd'T'HH:mm:ss" 1999-10-31T02:00:00
+ ('T' for local time)
+ "t" short time culture-specific 2:00 AM
+ "T" long time culture-specific 2:00:00 AM
+(G) "u" Universal time with sortable format, "yyyy'-'MM'-'dd HH':'mm':'ss'Z'" 1999-10-31 10:00:00Z
+ based on ISO 8601.
+(U) "U" Universal time with full culture-specific Sunday, October 31, 1999 10:00:00 AM
+ (long date + long time) format
+ "y"/"Y" Year/Month day culture-specific October, 1999
+
+ */
+
+ //This class contains only static members and does not require the serializable attribute.
+ internal static
+ class DateTimeFormat {
+
+ internal const int MaxSecondsFractionDigits = 7;
+ internal static readonly TimeSpan NullOffset = TimeSpan.MinValue;
+
+ internal static char[] allStandardFormats =
+ {
+ 'd', 'D', 'f', 'F', 'g', 'G',
+ 'm', 'M', 'o', 'O', 'r', 'R',
+ 's', 't', 'T', 'u', 'U', 'y', 'Y',
+ };
+
+ internal const String RoundtripFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK";
+ internal const String RoundtripDateTimeUnfixed = "yyyy'-'MM'-'ddTHH':'mm':'ss zzz";
+
+ private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
+
+ internal static String[] fixedNumberFormats = new String[] {
+ "0",
+ "00",
+ "000",
+ "0000",
+ "00000",
+ "000000",
+ "0000000",
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Format the positive integer value to a string and perfix with assigned
+ // length of leading zero.
+ //
+ // Parameters:
+ // value: The value to format
+ // len: The maximum length for leading zero.
+ // If the digits of the value is greater than len, no leading zero is added.
+ //
+ // Notes:
+ // The function can format to Int32.MaxValue.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static void FormatDigits(StringBuilder outputBuffer, int value, int len) {
+ Contract.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
+ FormatDigits(outputBuffer, value, len, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static void FormatDigits(StringBuilder outputBuffer, int value, int len, bool overrideLengthLimit) {
+ Contract.Assert(value >= 0, "DateTimeFormat.FormatDigits(): value >= 0");
+
+ // Limit the use of this function to be two-digits, so that we have the same behavior
+ // as RTM bits.
+ if (!overrideLengthLimit && len > 2)
+ {
+ len = 2;
+ }
+
+ char* buffer = stackalloc char[16];
+ char* p = buffer + 16;
+ int n = value;
+ do {
+ *--p = (char)(n % 10 + '0');
+ n /= 10;
+ } while ((n != 0)&&(p > buffer));
+
+ int digits = (int) (buffer + 16 - p);
+
+ //If the repeat count is greater than 0, we're trying
+ //to emulate the "00" format, so we have to prepend
+ //a zero if the string only has one character.
+ while ((digits < len) && (p > buffer)) {
+ *--p='0';
+ digits++;
+ }
+ outputBuffer.Append(p, digits);
+ }
+
+ private static void HebrewFormatDigits(StringBuilder outputBuffer, int digits) {
+ outputBuffer.Append(HebrewNumber.ToString(digits));
+ }
+
+ internal static int ParseRepeatPattern(String format, int pos, char patternChar)
+ {
+ int len = format.Length;
+ int index = pos + 1;
+ while ((index < len) && (format[index] == patternChar))
+ {
+ index++;
+ }
+ return (index - pos);
+ }
+
+ private static String FormatDayOfWeek(int dayOfWeek, int repeat, DateTimeFormatInfo dtfi)
+ {
+ Contract.Assert(dayOfWeek >= 0 && dayOfWeek <= 6, "dayOfWeek >= 0 && dayOfWeek <= 6");
+ if (repeat == 3)
+ {
+ return (dtfi.GetAbbreviatedDayName((DayOfWeek)dayOfWeek));
+ }
+ // Call dtfi.GetDayName() here, instead of accessing DayNames property, because we don't
+ // want a clone of DayNames, which will hurt perf.
+ return (dtfi.GetDayName((DayOfWeek)dayOfWeek));
+ }
+
+ private static String FormatMonth(int month, int repeatCount, DateTimeFormatInfo dtfi)
+ {
+ Contract.Assert(month >=1 && month <= 12, "month >=1 && month <= 12");
+ if (repeatCount == 3)
+ {
+ return (dtfi.GetAbbreviatedMonthName(month));
+ }
+ // Call GetMonthName() here, instead of accessing MonthNames property, because we don't
+ // want a clone of MonthNames, which will hurt perf.
+ return (dtfi.GetMonthName(month));
+ }
+
+ //
+ // FormatHebrewMonthName
+ //
+ // Action: Return the Hebrew month name for the specified DateTime.
+ // Returns: The month name string for the specified DateTime.
+ // Arguments:
+ // time the time to format
+ // month The month is the value of HebrewCalendar.GetMonth(time).
+ // repeat Return abbreviated month name if repeat=3, or full month name if repeat=4
+ // dtfi The DateTimeFormatInfo which uses the Hebrew calendars as its calendar.
+ // Exceptions: None.
+ //
+
+ /* Note:
+ If DTFI is using Hebrew calendar, GetMonthName()/GetAbbreviatedMonthName() will return month names like this:
+ 1 Hebrew 1st Month
+ 2 Hebrew 2nd Month
+ .. ...
+ 6 Hebrew 6th Month
+ 7 Hebrew 6th Month II (used only in a leap year)
+ 8 Hebrew 7th Month
+ 9 Hebrew 8th Month
+ 10 Hebrew 9th Month
+ 11 Hebrew 10th Month
+ 12 Hebrew 11th Month
+ 13 Hebrew 12th Month
+
+ Therefore, if we are in a regular year, we have to increment the month name if moth is greater or eqaul to 7.
+ */
+ private static String FormatHebrewMonthName(DateTime time, int month, int repeatCount, DateTimeFormatInfo dtfi)
+ {
+ Contract.Assert(repeatCount != 3 || repeatCount != 4, "repeateCount should be 3 or 4");
+ if (dtfi.Calendar.IsLeapYear(dtfi.Calendar.GetYear(time))) {
+ // This month is in a leap year
+ return (dtfi.internalGetMonthName(month, MonthNameStyles.LeapYear, (repeatCount == 3)));
+ }
+ // This is in a regular year.
+ if (month >= 7) {
+ month++;
+ }
+ if (repeatCount == 3) {
+ return (dtfi.GetAbbreviatedMonthName(month));
+ }
+ return (dtfi.GetMonthName(month));
+ }
+
+ //
+ // The pos should point to a quote character. This method will
+ // append to the result StringBuilder the string encloed by the quote character.
+ //
+ internal static int ParseQuoteString(String format, int pos, StringBuilder result)
+ {
+ //
+ // NOTE : pos will be the index of the quote character in the 'format' string.
+ //
+ int formatLen = format.Length;
+ int beginPos = pos;
+ char quoteChar = format[pos++]; // Get the character used to quote the following string.
+
+ bool foundQuote = false;
+ while (pos < formatLen)
+ {
+ char ch = format[pos++];
+ if (ch == quoteChar)
+ {
+ foundQuote = true;
+ break;
+ }
+ else if (ch == '\\') {
+ // The following are used to support escaped character.
+ // Escaped character is also supported in the quoted string.
+ // Therefore, someone can use a format like "'minute:' mm\"" to display:
+ // minute: 45"
+ // because the second double quote is escaped.
+ if (pos < formatLen) {
+ result.Append(format[pos++]);
+ } else {
+ //
+ // This means that '\' is at the end of the formatting string.
+ //
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ } else {
+ result.Append(ch);
+ }
+ }
+
+ if (!foundQuote)
+ {
+ // Here we can't find the matching quote.
+ throw new FormatException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Format_BadQuote"), quoteChar));
+ }
+
+ //
+ // Return the character count including the begin/end quote characters and enclosed string.
+ //
+ return (pos - beginPos);
+ }
+
+ //
+ // Get the next character at the index of 'pos' in the 'format' string.
+ // Return value of -1 means 'pos' is already at the end of the 'format' string.
+ // Otherwise, return value is the int value of the next character.
+ //
+ internal static int ParseNextChar(String format, int pos)
+ {
+ if (pos >= format.Length - 1)
+ {
+ return (-1);
+ }
+ return ((int)format[pos+1]);
+ }
+
+ //
+ // IsUseGenitiveForm
+ //
+ // Actions: Check the format to see if we should use genitive month in the formatting.
+ // Starting at the position (index) in the (format) string, look back and look ahead to
+ // see if there is "d" or "dd". In the case like "d MMMM" or "MMMM dd", we can use
+ // genitive form. Genitive form is not used if there is more than two "d".
+ // Arguments:
+ // format The format string to be scanned.
+ // index Where we should start the scanning. This is generally where "M" starts.
+ // tokenLen The len of the current pattern character. This indicates how many "M" that we have.
+ // patternToMatch The pattern that we want to search. This generally uses "d"
+ //
+ private static bool IsUseGenitiveForm(String format, int index, int tokenLen, char patternToMatch) {
+ int i;
+ int repeat = 0;
+ //
+ // Look back to see if we can find "d" or "ddd"
+ //
+
+ // Find first "d".
+ for (i = index - 1; i >= 0 && format[i] != patternToMatch; i--) { /*Do nothing here */ };
+
+ if (i >= 0) {
+ // Find a "d", so look back to see how many "d" that we can find.
+ while (--i >= 0 && format[i] == patternToMatch) {
+ repeat++;
+ }
+ //
+ // repeat == 0 means that we have one (patternToMatch)
+ // repeat == 1 means that we have two (patternToMatch)
+ //
+ if (repeat <= 1) {
+ return (true);
+ }
+ // Note that we can't just stop here. We may find "ddd" while looking back, and we have to look
+ // ahead to see if there is "d" or "dd".
+ }
+
+ //
+ // If we can't find "d" or "dd" by looking back, try look ahead.
+ //
+
+ // Find first "d"
+ for (i = index + tokenLen; i < format.Length && format[i] != patternToMatch; i++) { /* Do nothing here */ };
+
+ if (i < format.Length) {
+ repeat = 0;
+ // Find a "d", so contine the walk to see how may "d" that we can find.
+ while (++i < format.Length && format[i] == patternToMatch) {
+ repeat++;
+ }
+ //
+ // repeat == 0 means that we have one (patternToMatch)
+ // repeat == 1 means that we have two (patternToMatch)
+ //
+ if (repeat <= 1) {
+ return (true);
+ }
+ }
+ return (false);
+ }
+
+
+ //
+ // FormatCustomized
+ //
+ // Actions: Format the DateTime instance using the specified format.
+ //
+ private static String FormatCustomized(DateTime dateTime, String format, DateTimeFormatInfo dtfi, TimeSpan offset) {
+
+
+ Calendar cal = dtfi.Calendar;
+ StringBuilder result = StringBuilderCache.Acquire();
+ // This is a flag to indicate if we are format the dates using Hebrew calendar.
+
+ bool isHebrewCalendar = (cal.ID == Calendar.CAL_HEBREW);
+ // This is a flag to indicate if we are formating hour/minute/second only.
+ bool bTimeOnly = true;
+
+ int i = 0;
+ int tokenLen, hour12;
+
+ while (i < format.Length) {
+ char ch = format[i];
+ int nextChar;
+ switch (ch) {
+ case 'g':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ result.Append(dtfi.GetEraName(cal.GetEra(dateTime)));
+ break;
+ case 'h':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ hour12 = dateTime.Hour % 12;
+ if (hour12 == 0)
+ {
+ hour12 = 12;
+ }
+ FormatDigits(result, hour12, tokenLen);
+ break;
+ case 'H':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ FormatDigits(result, dateTime.Hour, tokenLen);
+ break;
+ case 'm':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ FormatDigits(result, dateTime.Minute, tokenLen);
+ break;
+ case 's':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ FormatDigits(result, dateTime.Second, tokenLen);
+ break;
+ case 'f':
+ case 'F':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ if (tokenLen <= MaxSecondsFractionDigits) {
+ long fraction = (dateTime.Ticks % Calendar.TicksPerSecond);
+ fraction = fraction / (long)Math.Pow(10, 7 - tokenLen);
+ if (ch == 'f') {
+ result.Append(((int)fraction).ToString(fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture));
+ }
+ else {
+ int effectiveDigits = tokenLen;
+ while (effectiveDigits > 0) {
+ if (fraction % 10 == 0) {
+ fraction = fraction / 10;
+ effectiveDigits--;
+ }
+ else {
+ break;
+ }
+ }
+ if (effectiveDigits > 0) {
+ result.Append(((int)fraction).ToString(fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ }
+ else {
+ // No fraction to emit, so see if we should remove decimal also.
+ if (result.Length > 0 && result[result.Length - 1] == '.') {
+ result.Remove(result.Length - 1, 1);
+ }
+ }
+ }
+ } else {
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ break;
+ case 't':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ if (tokenLen == 1)
+ {
+ if (dateTime.Hour < 12)
+ {
+ if (dtfi.AMDesignator.Length >= 1)
+ {
+ result.Append(dtfi.AMDesignator[0]);
+ }
+ }
+ else
+ {
+ if (dtfi.PMDesignator.Length >= 1)
+ {
+ result.Append(dtfi.PMDesignator[0]);
+ }
+ }
+
+ }
+ else
+ {
+ result.Append((dateTime.Hour < 12 ? dtfi.AMDesignator : dtfi.PMDesignator));
+ }
+ break;
+ case 'd':
+ //
+ // tokenLen == 1 : Day of month as digits with no leading zero.
+ // tokenLen == 2 : Day of month as digits with leading zero for single-digit months.
+ // tokenLen == 3 : Day of week as a three-leter abbreviation.
+ // tokenLen >= 4 : Day of week as its full name.
+ //
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ if (tokenLen <= 2)
+ {
+ int day = cal.GetDayOfMonth(dateTime);
+ if (isHebrewCalendar) {
+ // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values.
+ HebrewFormatDigits(result, day);
+ } else {
+ FormatDigits(result, day, tokenLen);
+ }
+ }
+ else
+ {
+ int dayOfWeek = (int)cal.GetDayOfWeek(dateTime);
+ result.Append(FormatDayOfWeek(dayOfWeek, tokenLen, dtfi));
+ }
+ bTimeOnly = false;
+ break;
+ case 'M':
+ //
+ // tokenLen == 1 : Month as digits with no leading zero.
+ // tokenLen == 2 : Month as digits with leading zero for single-digit months.
+ // tokenLen == 3 : Month as a three-letter abbreviation.
+ // tokenLen >= 4 : Month as its full name.
+ //
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ int month = cal.GetMonth(dateTime);
+ if (tokenLen <= 2)
+ {
+ if (isHebrewCalendar) {
+ // For Hebrew calendar, we need to convert numbers to Hebrew text for yyyy, MM, and dd values.
+ HebrewFormatDigits(result, month);
+ } else {
+ FormatDigits(result, month, tokenLen);
+ }
+ }
+ else {
+ if (isHebrewCalendar) {
+ result.Append(FormatHebrewMonthName(dateTime, month, tokenLen, dtfi));
+ } else {
+ if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0 && tokenLen >= 4) {
+ result.Append(
+ dtfi.internalGetMonthName(
+ month,
+ IsUseGenitiveForm(format, i, tokenLen, 'd')? MonthNameStyles.Genitive : MonthNameStyles.Regular,
+ false));
+ } else {
+ result.Append(FormatMonth(month, tokenLen, dtfi));
+ }
+ }
+ }
+ bTimeOnly = false;
+ break;
+ case 'y':
+ // Notes about OS behavior:
+ // y: Always print (year % 100). No leading zero.
+ // yy: Always print (year % 100) with leading zero.
+ // yyy/yyyy/yyyyy/... : Print year value. No leading zero.
+
+ int year = cal.GetYear(dateTime);
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ if (dtfi.HasForceTwoDigitYears) {
+ FormatDigits(result, year, tokenLen <= 2 ? tokenLen : 2);
+ }
+ else if (cal.ID == Calendar.CAL_HEBREW) {
+ HebrewFormatDigits(result, year);
+ }
+ else {
+ if (tokenLen <= 2) {
+ FormatDigits(result, year % 100, tokenLen);
+ }
+ else {
+ String fmtPattern = "D" + tokenLen.ToString();
+ result.Append(year.ToString(fmtPattern, CultureInfo.InvariantCulture));
+ }
+ }
+ bTimeOnly = false;
+ break;
+ case 'z':
+ tokenLen = ParseRepeatPattern(format, i, ch);
+ FormatCustomizedTimeZone(dateTime, offset, format, tokenLen, bTimeOnly, result);
+ break;
+ case 'K':
+ tokenLen = 1;
+ FormatCustomizedRoundripTimeZone(dateTime, offset, result);
+ break;
+ case ':':
+ result.Append(dtfi.TimeSeparator);
+ tokenLen = 1;
+ break;
+ case '/':
+ result.Append(dtfi.DateSeparator);
+ tokenLen = 1;
+ break;
+ case '\'':
+ case '\"':
+ tokenLen = ParseQuoteString(format, i, result);
+ break;
+ case '%':
+ // Optional format character.
+ // For example, format string "%d" will print day of month
+ // without leading zero. Most of the cases, "%" can be ignored.
+ nextChar = ParseNextChar(format, i);
+ // nextChar will be -1 if we already reach the end of the format string.
+ // Besides, we will not allow "%%" appear in the pattern.
+ if (nextChar >= 0 && nextChar != (int)'%') {
+ result.Append(FormatCustomized(dateTime, ((char)nextChar).ToString(), dtfi, offset));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '%' is at the end of the format string or
+ // "%%" appears in the format string.
+ //
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ break;
+ case '\\':
+ // Escaped character. Can be used to insert character into the format string.
+ // For exmple, "\d" will insert the character 'd' into the string.
+ //
+ // NOTENOTE : we can remove this format character if we enforce the enforced quote
+ // character rule.
+ // That is, we ask everyone to use single quote or double quote to insert characters,
+ // then we can remove this character.
+ //
+ nextChar = ParseNextChar(format, i);
+ if (nextChar >= 0)
+ {
+ result.Append(((char)nextChar));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '\' is at the end of the formatting string.
+ //
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ break;
+ default:
+ // NOTENOTE : we can remove this rule if we enforce the enforced quote
+ // character rule.
+ // That is, if we ask everyone to use single quote or double quote to insert characters,
+ // then we can remove this default block.
+ result.Append(ch);
+ tokenLen = 1;
+ break;
+ }
+ i += tokenLen;
+ }
+ return StringBuilderCache.GetStringAndRelease(result);
+
+ }
+
+
+ // output the 'z' famliy of formats, which output a the offset from UTC, e.g. "-07:30"
+ private static void FormatCustomizedTimeZone(DateTime dateTime, TimeSpan offset, String format, Int32 tokenLen, Boolean timeOnly, StringBuilder result) {
+ // See if the instance already has an offset
+ Boolean dateTimeFormat = (offset == NullOffset);
+ if (dateTimeFormat) {
+ // No offset. The instance is a DateTime and the output should be the local time zone
+
+ if (timeOnly && dateTime.Ticks < Calendar.TicksPerDay) {
+ // For time only format and a time only input, the time offset on 0001/01/01 is less
+ // accurate than the system's current offset because of daylight saving time.
+ offset = TimeZoneInfo.GetLocalUtcOffset(DateTime.Now, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ } else if (dateTime.Kind == DateTimeKind.Utc) {
+#if FEATURE_CORECLR
+ offset = TimeSpan.Zero;
+#else // FEATURE_CORECLR
+ // This code path points to a bug in user code. It would make sense to return a 0 offset in this case.
+ // However, because it was only possible to detect this in Whidbey, there is user code that takes a
+ // dependency on being serialize a UTC DateTime using the 'z' format, and it will work almost all the
+ // time if it is offset by an incorrect conversion to local time when parsed. Therefore, we need to
+ // explicitly emit the local time offset, which we can do by removing the UTC flag.
+ InvalidFormatForUtc(format, dateTime);
+ dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
+ offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+#endif // FEATURE_CORECLR
+ } else {
+ offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+ }
+ if (offset >= TimeSpan.Zero) {
+ result.Append('+');
+ }
+ else {
+ result.Append('-');
+ // get a positive offset, so that you don't need a separate code path for the negative numbers.
+ offset = offset.Negate();
+ }
+
+ if (tokenLen <= 1) {
+ // 'z' format e.g "-7"
+ result.AppendFormat(CultureInfo.InvariantCulture, "{0:0}", offset.Hours);
+ }
+ else {
+ // 'zz' or longer format e.g "-07"
+ result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}", offset.Hours);
+ if (tokenLen >= 3) {
+ // 'zzz*' or longer format e.g "-07:30"
+ result.AppendFormat(CultureInfo.InvariantCulture, ":{0:00}", offset.Minutes);
+ }
+ }
+ }
+
+ // output the 'K' format, which is for round-tripping the data
+ private static void FormatCustomizedRoundripTimeZone(DateTime dateTime, TimeSpan offset, StringBuilder result) {
+
+ // The objective of this format is to round trip the data in the type
+ // For DateTime it should round-trip the Kind value and preserve the time zone.
+ // DateTimeOffset instance, it should do so by using the internal time zone.
+
+ if (offset == NullOffset) {
+ // source is a date time, so behavior depends on the kind.
+ switch (dateTime.Kind) {
+ case DateTimeKind.Local:
+ // This should output the local offset, e.g. "-07:30"
+ offset = TimeZoneInfo.GetLocalUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ // fall through to shared time zone output code
+ break;
+ case DateTimeKind.Utc:
+ // The 'Z' constant is a marker for a UTC date
+ result.Append("Z");
+ return;
+ default:
+ // If the kind is unspecified, we output nothing here
+ return;
+ }
+ }
+ if (offset >= TimeSpan.Zero) {
+ result.Append('+');
+ }
+ else {
+ result.Append('-');
+ // get a positive offset, so that you don't need a separate code path for the negative numbers.
+ offset = offset.Negate();
+ }
+
+ result.AppendFormat(CultureInfo.InvariantCulture, "{0:00}:{1:00}", offset.Hours, offset.Minutes);
+ }
+
+
+ internal static String GetRealFormat(String format, DateTimeFormatInfo dtfi)
+ {
+ String realFormat = null;
+
+ switch (format[0])
+ {
+ case 'd': // Short Date
+ realFormat = dtfi.ShortDatePattern;
+ break;
+ case 'D': // Long Date
+ realFormat = dtfi.LongDatePattern;
+ break;
+ case 'f': // Full (long date + short time)
+ realFormat = dtfi.LongDatePattern + " " + dtfi.ShortTimePattern;
+ break;
+ case 'F': // Full (long date + long time)
+ realFormat = dtfi.FullDateTimePattern;
+ break;
+ case 'g': // General (short date + short time)
+ realFormat = dtfi.GeneralShortTimePattern;
+ break;
+ case 'G': // General (short date + long time)
+ realFormat = dtfi.GeneralLongTimePattern;
+ break;
+ case 'm':
+ case 'M': // Month/Day Date
+ realFormat = dtfi.MonthDayPattern;
+ break;
+ case 'o':
+ case 'O':
+ realFormat = RoundtripFormat;
+ break;
+ case 'r':
+ case 'R': // RFC 1123 Standard
+ realFormat = dtfi.RFC1123Pattern;
+ break;
+ case 's': // Sortable without Time Zone Info
+ realFormat = dtfi.SortableDateTimePattern;
+ break;
+ case 't': // Short Time
+ realFormat = dtfi.ShortTimePattern;
+ break;
+ case 'T': // Long Time
+ realFormat = dtfi.LongTimePattern;
+ break;
+ case 'u': // Universal with Sortable format
+ realFormat = dtfi.UniversalSortableDateTimePattern;
+ break;
+ case 'U': // Universal with Full (long date + long time) format
+ realFormat = dtfi.FullDateTimePattern;
+ break;
+ case 'y':
+ case 'Y': // Year/Month Date
+ realFormat = dtfi.YearMonthPattern;
+ break;
+ default:
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ return (realFormat);
+ }
+
+
+ // Expand a pre-defined format string (like "D" for long date) to the real format that
+ // we are going to use in the date time parsing.
+ // This method also convert the dateTime if necessary (e.g. when the format is in Universal time),
+ // and change dtfi if necessary (e.g. when the format should use invariant culture).
+ //
+ private static String ExpandPredefinedFormat(String format, ref DateTime dateTime, ref DateTimeFormatInfo dtfi, ref TimeSpan offset) {
+ switch (format[0]) {
+ case 'o':
+ case 'O': // Round trip format
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ case 'r':
+ case 'R': // RFC 1123 Standard
+ if (offset != NullOffset) {
+ // Convert to UTC invariants mean this will be in range
+ dateTime = dateTime - offset;
+ }
+ else if (dateTime.Kind == DateTimeKind.Local) {
+ InvalidFormatForLocal(format, dateTime);
+ }
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ case 's': // Sortable without Time Zone Info
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ case 'u': // Universal time in sortable format.
+ if (offset != NullOffset) {
+ // Convert to UTC invariants mean this will be in range
+ dateTime = dateTime - offset;
+ }
+ else if (dateTime.Kind == DateTimeKind.Local) {
+
+ InvalidFormatForLocal(format, dateTime);
+ }
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ case 'U': // Universal time in culture dependent format.
+ if (offset != NullOffset) {
+ // This format is not supported by DateTimeOffset
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ // Universal time is always in Greogrian calendar.
+ //
+ // Change the Calendar to be Gregorian Calendar.
+ //
+ dtfi = (DateTimeFormatInfo)dtfi.Clone();
+ if (dtfi.Calendar.GetType() != typeof(GregorianCalendar)) {
+ dtfi.Calendar = GregorianCalendar.GetDefaultInstance();
+ }
+ dateTime = dateTime.ToUniversalTime();
+ break;
+ }
+ format = GetRealFormat(format, dtfi);
+ return (format);
+ }
+
+ internal static String Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi) {
+ return Format(dateTime, format, dtfi, NullOffset);
+ }
+
+
+ internal static String Format(DateTime dateTime, String format, DateTimeFormatInfo dtfi, TimeSpan offset)
+ {
+ Contract.Requires(dtfi != null);
+ if (format==null || format.Length==0) {
+ Boolean timeOnlySpecialCase = false;
+ if (dateTime.Ticks < Calendar.TicksPerDay) {
+ // If the time is less than 1 day, consider it as time of day.
+ // Just print out the short time format.
+ //
+ // This is a workaround for VB, since they use ticks less then one day to be
+ // time of day. In cultures which use calendar other than Gregorian calendar, these
+ // alternative calendar may not support ticks less than a day.
+ // For example, Japanese calendar only supports date after 1868/9/8.
+ // This will pose a problem when people in VB get the time of day, and use it
+ // to call ToString(), which will use the general format (short date + long time).
+ // Since Japanese calendar does not support Gregorian year 0001, an exception will be
+ // thrown when we try to get the Japanese year for Gregorian year 0001.
+ // Therefore, the workaround allows them to call ToString() for time of day from a DateTime by
+ // formatting as ISO 8601 format.
+ switch (dtfi.Calendar.ID) {
+ case Calendar.CAL_JAPAN:
+ case Calendar.CAL_TAIWAN:
+ case Calendar.CAL_HIJRI:
+ case Calendar.CAL_HEBREW:
+ case Calendar.CAL_JULIAN:
+ case Calendar.CAL_UMALQURA:
+ case Calendar.CAL_PERSIAN:
+ timeOnlySpecialCase = true;
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ }
+ }
+ if (offset == NullOffset) {
+ // Default DateTime.ToString case.
+ if (timeOnlySpecialCase) {
+ format = "s";
+ }
+ else {
+ format = "G";
+ }
+ }
+ else {
+ // Default DateTimeOffset.ToString case.
+ if (timeOnlySpecialCase) {
+ format = RoundtripDateTimeUnfixed;
+ }
+ else {
+ format = dtfi.DateTimeOffsetPattern;
+ }
+
+ }
+
+ }
+
+ if (format.Length == 1) {
+ format = ExpandPredefinedFormat(format, ref dateTime, ref dtfi, ref offset);
+ }
+
+ return (FormatCustomized(dateTime, format, dtfi, offset));
+ }
+
+ internal static String[] GetAllDateTimes(DateTime dateTime, char format, DateTimeFormatInfo dtfi)
+ {
+ Contract.Requires(dtfi != null);
+ String [] allFormats = null;
+ String [] results = null;
+
+ switch (format)
+ {
+ case 'd':
+ case 'D':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ case 'm':
+ case 'M':
+ case 't':
+ case 'T':
+ case 'y':
+ case 'Y':
+ allFormats = dtfi.GetAllDateTimePatterns(format);
+ results = new String[allFormats.Length];
+ for (int i = 0; i < allFormats.Length; i++)
+ {
+ results[i] = Format(dateTime, allFormats[i], dtfi);
+ }
+ break;
+ case 'U':
+ DateTime universalTime = dateTime.ToUniversalTime();
+ allFormats = dtfi.GetAllDateTimePatterns(format);
+ results = new String[allFormats.Length];
+ for (int i = 0; i < allFormats.Length; i++)
+ {
+ results[i] = Format(universalTime, allFormats[i], dtfi);
+ }
+ break;
+ //
+ // The following ones are special cases because these patterns are read-only in
+ // DateTimeFormatInfo.
+ //
+ case 'r':
+ case 'R':
+ case 'o':
+ case 'O':
+ case 's':
+ case 'u':
+ results = new String[] {Format(dateTime, new String(format, 1), dtfi)};
+ break;
+ default:
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+
+ }
+ return (results);
+ }
+
+ internal static String[] GetAllDateTimes(DateTime dateTime, DateTimeFormatInfo dtfi)
+ {
+ List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+
+ for (int i = 0; i < allStandardFormats.Length; i++)
+ {
+ String[] strings = GetAllDateTimes(dateTime, allStandardFormats[i], dtfi);
+ for (int j = 0; j < strings.Length; j++)
+ {
+ results.Add(strings[j]);
+ }
+ }
+ String[] value = new String[results.Count];
+ results.CopyTo(0, value, 0, results.Count);
+ return (value);
+ }
+
+ // This is a placeholder for an MDA to detect when the user is using a
+ // local DateTime with a format that will be interpreted as UTC.
+ internal static void InvalidFormatForLocal(String format, DateTime dateTime) {
+ }
+
+ // This is an MDA for cases when the user is using a local format with
+ // a Utc DateTime.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void InvalidFormatForUtc(String format, DateTime dateTime) {
+#if MDA_SUPPORTED
+ Mda.DateTimeInvalidLocalFormat();
+#endif
+ }
+
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs
new file mode 100644
index 0000000000..00c2d1f439
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfo.cs
@@ -0,0 +1,2936 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Globalization {
+ using System;
+ using System.Security;
+ using System.Threading;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ //
+ // Flags used to indicate different styles of month names.
+ // This is an internal flag used by internalGetMonthName().
+ // Use flag here in case that we need to provide a combination of these styles
+ // (such as month name of a leap year in genitive form. Not likely for now,
+ // but would like to keep the option open).
+ //
+
+ [Flags]
+ internal enum MonthNameStyles {
+ Regular = 0x00000000,
+ Genitive = 0x00000001,
+ LeapYear = 0x00000002,
+ }
+
+ //
+ // Flags used to indicate special rule used in parsing/formatting
+ // for a specific DateTimeFormatInfo instance.
+ // This is an internal flag.
+ //
+ // This flag is different from MonthNameStyles because this flag
+ // can be expanded to accomodate parsing behaviors like CJK month names
+ // or alternative month names, etc.
+
+ [Flags]
+ internal enum DateTimeFormatFlags {
+ None = 0x00000000,
+ UseGenitiveMonth = 0x00000001,
+ UseLeapYearMonth = 0x00000002,
+ UseSpacesInMonthNames = 0x00000004, // Has spaces or non-breaking space in the month names.
+ UseHebrewRule = 0x00000008, // Format/Parse using the Hebrew calendar rule.
+ UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
+ UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
+
+ NotInitialized = -1,
+ }
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DateTimeFormatInfo : ICloneable, IFormatProvider
+ {
+ //
+ // Note, some fields are derived so don't really need to be serialized, but we can't mark as
+ // optional because Whidbey was expecting them. Post-Arrowhead we could fix that
+ // once Whidbey serialization is no longer necessary.
+ //
+
+ // cache for the invariant culture.
+ // invariantInfo is constant irrespective of your current culture.
+ private static volatile DateTimeFormatInfo invariantInfo;
+
+ // an index which points to a record in Culture Data Table.
+ [NonSerialized]private CultureData m_cultureData;
+
+ // The culture name used to create this DTFI.
+ [OptionalField(VersionAdded = 2)]
+ internal String m_name = null;
+
+ // The language name of the culture used to create this DTFI.
+ [NonSerialized]private String m_langName = null;
+
+ // CompareInfo usually used by the parser.
+ [NonSerialized]private CompareInfo m_compareInfo = null;
+
+ // Culture matches current DTFI. mainly used for string comparisons during parsing.
+ [NonSerialized]private CultureInfo m_cultureInfo = null;
+
+ //
+ // Caches for various properties.
+ //
+
+ internal String amDesignator = null;
+ internal String pmDesignator = null;
+ [OptionalField(VersionAdded = 1)]
+ internal String dateSeparator = null; // derived from short date (whidbey expects, arrowhead doesn't)
+ [OptionalField(VersionAdded = 1)]
+ internal String generalShortTimePattern = null; // short date + short time (whidbey expects, arrowhead doesn't)
+ [OptionalField(VersionAdded = 1)]
+ internal String generalLongTimePattern = null; // short date + long time (whidbey expects, arrowhead doesn't)
+ [OptionalField(VersionAdded = 1)]
+ internal String timeSeparator = null; // derived from long time (whidbey expects, arrowhead doesn't)
+ internal String monthDayPattern = null;
+ [OptionalField(VersionAdded = 2)] // added in .NET Framework Release {2.0SP1/3.0SP1/3.5RTM}
+ internal String dateTimeOffsetPattern = null;
+
+ //
+ // The following are constant values.
+ //
+ internal const String rfc1123Pattern = "ddd, dd MMM yyyy HH':'mm':'ss 'GMT'";
+
+ // The sortable pattern is based on ISO 8601.
+ internal const String sortableDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
+ internal const String universalSortableDateTimePattern = "yyyy'-'MM'-'dd HH':'mm':'ss'Z'";
+
+ //
+ // The following are affected by calendar settings.
+ //
+ internal Calendar calendar = null;
+
+ internal int firstDayOfWeek = -1;
+ internal int calendarWeekRule = -1;
+
+ [OptionalField(VersionAdded = 1)]
+ internal String fullDateTimePattern = null; // long date + long time (whidbey expects, arrowhead doesn't)
+
+ internal String[] abbreviatedDayNames = null;
+
+ [OptionalField(VersionAdded = 2)]
+ internal String[] m_superShortDayNames = null;
+
+ internal String[] dayNames = null;
+ internal String[] abbreviatedMonthNames = null;
+ internal String[] monthNames = null;
+ // Cache the genitive month names that we retrieve from the data table.
+ [OptionalField(VersionAdded = 2)]
+ internal String[] genitiveMonthNames = null;
+
+ // Cache the abbreviated genitive month names that we retrieve from the data table.
+ [OptionalField(VersionAdded = 2)]
+ internal String[] m_genitiveAbbreviatedMonthNames = null;
+
+ // Cache the month names of a leap year that we retrieve from the data table.
+ [OptionalField(VersionAdded = 2)]
+ internal String[] leapYearMonthNames = null;
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+
+ // The "default" Date/time patterns
+ internal String longDatePattern = null;
+ internal String shortDatePattern = null;
+ internal String yearMonthPattern = null;
+ internal String longTimePattern = null;
+ internal String shortTimePattern = null;
+
+ // These are Whidbey-serialization compatable arrays (eg: default not included)
+ // "all" is a bit of a misnomer since the "default" pattern stored above isn't
+ // necessarily a member of the list
+ [OptionalField(VersionAdded = 3)]
+ private String[] allYearMonthPatterns = null; // This was wasn't serialized in Whidbey
+ internal String[] allShortDatePatterns = null;
+ internal String[] allLongDatePatterns = null;
+ internal String[] allShortTimePatterns = null;
+ internal String[] allLongTimePatterns = null;
+
+ // Cache the era names for this DateTimeFormatInfo instance.
+ internal String[] m_eraNames = null;
+ internal String[] m_abbrevEraNames = null;
+ internal String[] m_abbrevEnglishEraNames = null;
+
+ internal int[] optionalCalendars = null;
+
+ private const int DEFAULT_ALL_DATETIMES_SIZE = 132;
+
+ // CultureInfo updates this
+ internal bool m_isReadOnly=false;
+
+ // This flag gives hints about if formatting/parsing should perform special code path for things like
+ // genitive form or leap year month names.
+ [OptionalField(VersionAdded = 2)]
+ internal DateTimeFormatFlags formatFlags = DateTimeFormatFlags.NotInitialized;
+ internal static bool preferExistingTokens = InitPreferExistingTokens();
+
+
+ [System.Security.SecuritySafeCritical]
+ static bool InitPreferExistingTokens()
+ {
+ bool ret = false;
+#if !FEATURE_CORECLR
+ ret = DateTime.LegacyParseMode();
+#endif
+ return ret;
+ }
+
+ private String CultureName
+ {
+ get
+ {
+ if (m_name == null)
+ {
+ m_name = this.m_cultureData.CultureName;
+ }
+ return (m_name);
+ }
+ }
+
+ private CultureInfo Culture
+ {
+ get
+ {
+ if (m_cultureInfo == null)
+ {
+ m_cultureInfo = CultureInfo.GetCultureInfo(this.CultureName);
+ }
+ return m_cultureInfo;
+ }
+ }
+
+ private String LanguageName
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (m_langName == null)
+ {
+ m_langName = this.m_cultureData.SISO639LANGNAME;
+ }
+ return (m_langName);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the abbreviated day names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetAbbreviatedDayOfWeekNames()
+ {
+ if (this.abbreviatedDayNames == null)
+ {
+ // Get the abbreviated day names for our current calendar
+ this.abbreviatedDayNames = this.m_cultureData.AbbreviatedDayNames(Calendar.ID);
+ Contract.Assert(this.abbreviatedDayNames.Length == 7, "[DateTimeFormatInfo.GetAbbreviatedDayOfWeekNames] Expected 7 day names in a week");
+ }
+ return (this.abbreviatedDayNames);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Action: Returns the string array of the one-letter day of week names.
+ // Returns:
+ // an array of one-letter day of week names
+ // Arguments:
+ // None
+ // Exceptions:
+ // None
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetSuperShortDayNames()
+ {
+ if (this.m_superShortDayNames == null)
+ {
+ // Get the super short day names for our current calendar
+ this.m_superShortDayNames = this.m_cultureData.SuperShortDayNames(Calendar.ID);
+ Contract.Assert(this.m_superShortDayNames.Length == 7, "[DateTimeFormatInfo.internalGetSuperShortDayNames] Expected 7 day names in a week");
+ }
+ return (this.m_superShortDayNames);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the day names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetDayOfWeekNames()
+ {
+ if (this.dayNames == null)
+ {
+ // Get the day names for our current calendar
+ this.dayNames = this.m_cultureData.DayNames(Calendar.ID);
+ Contract.Assert(this.dayNames.Length == 7, "[DateTimeFormatInfo.GetDayOfWeekNames] Expected 7 day names in a week");
+ }
+ return (this.dayNames);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the abbreviated month names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetAbbreviatedMonthNames()
+ {
+ if (this.abbreviatedMonthNames == null)
+ {
+ // Get the month names for our current calendar
+ this.abbreviatedMonthNames = this.m_cultureData.AbbreviatedMonthNames(Calendar.ID);
+ Contract.Assert(this.abbreviatedMonthNames.Length == 12 || this.abbreviatedMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetAbbreviatedMonthNames] Expected 12 or 13 month names in a year");
+ }
+ return (this.abbreviatedMonthNames);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Create an array of string which contains the month names.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ private String[] internalGetMonthNames()
+ {
+ if (this.monthNames == null)
+ {
+ // Get the month names for our current calendar
+ this.monthNames = this.m_cultureData.MonthNames(Calendar.ID);
+ Contract.Assert(this.monthNames.Length == 12 || this.monthNames.Length == 13,
+ "[DateTimeFormatInfo.GetMonthNames] Expected 12 or 13 month names in a year");
+ }
+
+ return (this.monthNames);
+ }
+
+
+ //
+ // Invariant DateTimeFormatInfo doesn't have user-overriden values
+ // Default calendar is gregorian
+ public DateTimeFormatInfo()
+ : this(CultureInfo.InvariantCulture.m_cultureData,
+ GregorianCalendar.GetDefaultInstance())
+ {
+ }
+
+ internal DateTimeFormatInfo(CultureData cultureData, Calendar cal)
+ {
+ Contract.Requires(cultureData != null);
+ Contract.Requires(cal != null);
+
+ // Remember our culture
+ this.m_cultureData = cultureData;
+
+ // m_isDefaultCalendar is set in the setter of Calendar below.
+ this.Calendar = cal;
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ private void InitializeOverridableProperties(CultureData cultureData, int calendarID)
+ {
+ // Silverlight 2.0 never took a snapshot of the user's overridable properties
+ // This has a substantial performance impact so skip when CoreCLR
+ Contract.Requires(cultureData != null);
+ Contract.Assert(calendarID > 0, "[DateTimeFormatInfo.Populate] Expected Calendar.ID > 0");
+
+ if (this.firstDayOfWeek == -1) { this.firstDayOfWeek = cultureData.IFIRSTDAYOFWEEK; }
+ if (this.calendarWeekRule == -1) { this.calendarWeekRule = cultureData.IFIRSTWEEKOFYEAR; }
+
+ if (this.amDesignator == null) { this.amDesignator = cultureData.SAM1159; }
+ if (this.pmDesignator == null) { this.pmDesignator = cultureData.SPM2359; }
+ if (this.timeSeparator == null) { this.timeSeparator = cultureData.TimeSeparator; }
+ if (this.dateSeparator == null) { this.dateSeparator = cultureData.DateSeparator(calendarID); }
+
+ this.allLongTimePatterns = this.m_cultureData.LongTimes;
+ Contract.Assert(this.allLongTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long time patterns");
+
+ this.allShortTimePatterns = this.m_cultureData.ShortTimes;
+ Contract.Assert(this.allShortTimePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short time patterns");
+
+ this.allLongDatePatterns = cultureData.LongDates(calendarID);
+ Contract.Assert(this.allLongDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some long date patterns");
+
+ this.allShortDatePatterns = cultureData.ShortDates(calendarID);
+ Contract.Assert(this.allShortDatePatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some short date patterns");
+
+ this.allYearMonthPatterns = cultureData.YearMonths(calendarID);
+ Contract.Assert(this.allYearMonthPatterns.Length > 0, "[DateTimeFormatInfo.Populate] Expected some year month patterns");
+ }
+
+#region Serialization
+ // The following fields are defined to keep the serialization compatibility with .NET V1.0/V1.1.
+ [OptionalField(VersionAdded = 1)]
+ private int CultureID;
+ [OptionalField(VersionAdded = 1)]
+ private bool m_useUserOverride;
+ [OptionalField(VersionAdded = 1)]
+ private bool bUseCalendarInfo;
+ [OptionalField(VersionAdded = 1)]
+ private int nDataItem;
+ [OptionalField(VersionAdded = 2)]
+ internal bool m_isDefaultCalendar; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey)
+ [OptionalField(VersionAdded = 2)]
+ private static volatile Hashtable s_calendarNativeNames; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey)
+
+ // This was synthesized by Whidbey so we knew what words might appear in the middle of a date string
+ // Now we always synthesize so its not helpful
+ [OptionalField(VersionAdded = 1)]
+ internal String[] m_dateWords = null; // calculated, no need to serialze (whidbey expects, arrowhead doesn't)
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (this.m_name != null)
+ {
+ m_cultureData = CultureData.GetCultureData(m_name, m_useUserOverride);
+
+ if (this.m_cultureData == null)
+ throw new CultureNotFoundException(
+ "m_name", m_name, Environment.GetResourceString("Argument_CultureNotSupported"));
+ }
+ // Note: This is for Everett compatibility
+
+#if FEATURE_USE_LCID
+ else
+ m_cultureData = CultureData.GetCultureData(CultureID, m_useUserOverride);
+#endif
+ if (calendar == null)
+ {
+ calendar = (Calendar) GregorianCalendar.GetDefaultInstance().Clone();
+ calendar.SetReadOnlyState(m_isReadOnly);
+ }
+ else
+ {
+ CultureInfo.CheckDomainSafetyObject(calendar, this);
+ }
+ InitializeOverridableProperties(m_cultureData, calendar.ID);
+
+ //
+ // turn off read only state till we finish initializing all fields and then store read only state after we are done.
+ //
+ bool isReadOnly = m_isReadOnly;
+ m_isReadOnly = false;
+
+ // If we deserialized defaults ala Whidbey, make sure they're still defaults
+ // Whidbey's arrays could get a bit mixed up.
+ if (longDatePattern != null) this.LongDatePattern = longDatePattern;
+ if (shortDatePattern != null) this.ShortDatePattern = shortDatePattern;
+ if (yearMonthPattern != null) this.YearMonthPattern = yearMonthPattern;
+ if (longTimePattern != null) this.LongTimePattern = longTimePattern;
+ if (shortTimePattern != null) this.ShortTimePattern = shortTimePattern;
+
+ m_isReadOnly = isReadOnly;
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+#if FEATURE_USE_LCID
+ CultureID = this.m_cultureData.ILANGUAGE; // Used for serialization compatibility with Whidbey which didn't always serialize the name
+#endif
+ m_useUserOverride = this.m_cultureData.UseUserOverride;
+
+ // make sure the m_name is initialized.
+ m_name = this.CultureName;
+
+#if !FEATURE_CORECLR
+ if (s_calendarNativeNames == null)
+ s_calendarNativeNames = new Hashtable();
+#endif // FEATURE_CORECLR
+
+ // Important to initialize these fields otherwise we may run into exception when deserializing on Whidbey
+ // because Whidbey try to initialize some of these fields using calendar data which could be null values
+ // and then we get exceptions. So we call the accessors to force the caches to get loaded.
+ Object o;
+ o = this.LongTimePattern;
+ o = this.LongDatePattern;
+ o = this.ShortTimePattern;
+ o = this.ShortDatePattern;
+ o = this.YearMonthPattern;
+ o = this.AllLongTimePatterns;
+ o = this.AllLongDatePatterns;
+ o = this.AllShortTimePatterns;
+ o = this.AllShortDatePatterns;
+ o = this.AllYearMonthPatterns;
+ }
+#endregion Serialization
+
+ // Returns a default DateTimeFormatInfo that will be universally
+ // supported and constant irrespective of the current culture.
+ // Used by FromString methods.
+ //
+
+ public static DateTimeFormatInfo InvariantInfo {
+ get {
+ Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
+ if (invariantInfo == null)
+ {
+ DateTimeFormatInfo info = new DateTimeFormatInfo();
+ info.Calendar.SetReadOnlyState(true);
+ info.m_isReadOnly = true;
+ invariantInfo = info;
+ }
+ return (invariantInfo);
+ }
+ }
+
+ // Returns the current culture's DateTimeFormatInfo. Used by Parse methods.
+ //
+
+ public static DateTimeFormatInfo CurrentInfo {
+ get {
+ Contract.Ensures(Contract.Result<DateTimeFormatInfo>() != null);
+ System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
+ if (!culture.m_isInherited) {
+ DateTimeFormatInfo info = culture.dateTimeInfo;
+ if (info != null) {
+ return info;
+ }
+ }
+ return (DateTimeFormatInfo)culture.GetFormat(typeof(DateTimeFormatInfo));
+ }
+ }
+
+
+ public static DateTimeFormatInfo GetInstance(IFormatProvider provider) {
+ // Fast case for a regular CultureInfo
+ DateTimeFormatInfo info;
+ CultureInfo cultureProvider = provider as CultureInfo;
+ if (cultureProvider != null && !cultureProvider.m_isInherited)
+ {
+ return cultureProvider.DateTimeFormat;
+ }
+ // Fast case for a DTFI;
+ info = provider as DateTimeFormatInfo;
+ if (info != null) {
+ return info;
+ }
+ // Wasn't cultureInfo or DTFI, do it the slower way
+ if (provider != null) {
+ info = provider.GetFormat(typeof(DateTimeFormatInfo)) as DateTimeFormatInfo;
+ if (info != null) {
+ return info;
+ }
+ }
+ // Couldn't get anything, just use currentInfo as fallback
+ return CurrentInfo;
+ }
+
+
+ public Object GetFormat(Type formatType)
+ {
+ return (formatType == typeof(DateTimeFormatInfo)? this: null);
+ }
+
+
+ public Object Clone()
+ {
+ DateTimeFormatInfo n = (DateTimeFormatInfo)MemberwiseClone();
+ // We can use the data member calendar in the setter, instead of the property Calendar,
+ // since the cloned copy should have the same state as the original copy.
+ n.calendar = (Calendar) this.Calendar.Clone();
+ n.m_isReadOnly = false;
+ return n;
+ }
+
+
+ public String AMDesignator
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ get
+ {
+#if FEATURE_CORECLR
+ if (this.amDesignator == null)
+ {
+ this.amDesignator = this.m_cultureData.SAM1159;
+ }
+#endif
+ Contract.Assert(this.amDesignator != null, "DateTimeFormatInfo.AMDesignator, amDesignator != null");
+ return (this.amDesignator);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+ amDesignator = value;
+ }
+ }
+
+
+ public Calendar Calendar {
+ get {
+ Contract.Ensures(Contract.Result<Calendar>() != null);
+
+ Contract.Assert(this.calendar != null, "DateTimeFormatInfo.Calendar: calendar != null");
+ return (this.calendar);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ if (value == calendar) {
+ return;
+ }
+
+ //
+ // Because the culture is agile object which can be attached to a thread and then thread can travel
+ // to another app domain then we prevent attaching any customized object to culture that we cannot contol.
+ //
+ CultureInfo.CheckDomainSafetyObject(value, this);
+
+ for (int i = 0; i < this.OptionalCalendars.Length; i++)
+ {
+ if (this.OptionalCalendars[i] == value.ID)
+ {
+ // We can use this one, so do so.
+
+ // Clean related properties if we already had a calendar set
+ if (calendar != null)
+ {
+ // clean related properties which are affected by the calendar setting,
+ // so that they will be refreshed when they are accessed next time.
+ //
+
+ // These properites are in the order as appearing in calendar.xml.
+ m_eraNames = null;
+ m_abbrevEraNames = null;
+ m_abbrevEnglishEraNames = null;
+
+ monthDayPattern = null;
+
+ dayNames = null;
+ abbreviatedDayNames = null;
+ m_superShortDayNames = null;
+ monthNames = null;
+ abbreviatedMonthNames = null;
+ genitiveMonthNames = null;
+ m_genitiveAbbreviatedMonthNames = null;
+ leapYearMonthNames = null;
+ formatFlags = DateTimeFormatFlags.NotInitialized;
+
+ allShortDatePatterns = null;
+ allLongDatePatterns = null;
+ allYearMonthPatterns = null;
+ dateTimeOffsetPattern = null;
+
+ // The defaults need reset as well:
+ longDatePattern = null;
+ shortDatePattern = null;
+ yearMonthPattern = null;
+
+ // These properies are not in the OS data, but they are dependent on the values like shortDatePattern.
+ fullDateTimePattern = null; // Long date + long time
+ generalShortTimePattern = null; // short date + short time
+ generalLongTimePattern = null; // short date + long time
+
+ // Derived item that changes
+ dateSeparator = null;
+
+ // We don't need to do these because they are not changed by changing calendar
+ // amDesignator
+ // pmDesignator
+ // timeSeparator
+ // longTimePattern
+ // firstDayOfWeek
+ // calendarWeekRule
+
+ // We don't need to clear these because they're only used for whidbey compat serialization
+ // the only values we use are the all...Patterns[0]
+ // longDatePattern
+ // shortDatePattern
+ // yearMonthPattern
+
+ // remember to reload tokens
+ ClearTokenHashTable();
+ }
+
+ // Remember the new calendar
+ calendar = value;
+ InitializeOverridableProperties(m_cultureData, calendar.ID);
+
+ // We succeeded, return
+ return;
+ }
+ }
+
+ // The assigned calendar is not a valid calendar for this culture, throw
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("Argument_InvalidCalendar"));
+ }
+ }
+
+ private int[] OptionalCalendars {
+ get {
+ if (this.optionalCalendars == null) {
+ this.optionalCalendars = this.m_cultureData.CalendarIds;
+ }
+ return (this.optionalCalendars);
+ }
+ }
+
+ /*=================================GetEra==========================
+ **Action: Get the era value by parsing the name of the era.
+ **Returns: The era value for the specified era name.
+ ** -1 if the name of the era is not valid or not supported.
+ **Arguments: eraName the name of the era.
+ **Exceptions: None.
+ ============================================================================*/
+
+
+ public int GetEra(String eraName) {
+ if (eraName == null) {
+ throw new ArgumentNullException("eraName",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // For Geo-Political reasons, the Era Name and Abbreviated Era Name
+ // for Taiwan Calendar on non-Taiwan SKU returns empty string (which
+ // would be matched below) but we don't want the empty string to give
+ // us an Era number
+ // confer 85900 DTFI.GetEra("") should fail on all cultures
+ if (eraName.Length == 0) {
+ return (-1);
+ }
+
+ // The following is based on the assumption that the era value is starting from 1, and has a
+ // serial values.
+ // If that ever changes, the code has to be changed.
+
+ // The calls to String.Compare should use the current culture for the string comparisons, but the
+ // invariant culture when comparing against the english names.
+ for (int i = 0; i < EraNames.Length; i++) {
+ // Compare the era name in a case-insensitive way for the appropriate culture.
+ if (m_eraNames[i].Length > 0) {
+ if (String.Compare(eraName, m_eraNames[i], this.Culture, CompareOptions.IgnoreCase)==0) {
+ return (i+1);
+ }
+ }
+ }
+ for (int i = 0; i < AbbreviatedEraNames.Length; i++) {
+ // Compare the abbreviated era name in a case-insensitive way for the appropriate culture.
+ if (String.Compare(eraName, m_abbrevEraNames[i], this.Culture, CompareOptions.IgnoreCase)==0) {
+ return (i+1);
+ }
+ }
+ for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) {
+ // this comparison should use the InvariantCulture. The English name could have linguistically
+ // interesting characters.
+ if (String.Compare(eraName, m_abbrevEnglishEraNames[i], StringComparison.InvariantCultureIgnoreCase)==0) {
+ return (i+1);
+ }
+ }
+ return (-1);
+ }
+
+ internal String[] EraNames
+ {
+ get
+ {
+ if (this.m_eraNames == null)
+ {
+ this.m_eraNames = this.m_cultureData.EraNames(Calendar.ID);;
+ }
+ return (this.m_eraNames);
+ }
+ }
+
+ /*=================================GetEraName==========================
+ **Action: Get the name of the era for the specified era value.
+ **Returns: The name of the specified era.
+ **Arguments:
+ ** era the era value.
+ **Exceptions:
+ ** ArguementException if the era valie is invalid.
+ ============================================================================*/
+
+ // Era names are 1 indexed
+ public String GetEraName(int era) {
+ if (era == Calendar.CurrentEra) {
+ era = Calendar.CurrentEraValue;
+ }
+
+ // The following is based on the assumption that the era value is starting from 1, and has a
+ // serial values.
+ // If that ever changes, the code has to be changed.
+ if ((--era) < EraNames.Length && (era >= 0)) {
+ return (m_eraNames[era]);
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ internal String[] AbbreviatedEraNames
+ {
+ get
+ {
+ if (this.m_abbrevEraNames == null)
+ {
+ this.m_abbrevEraNames = this.m_cultureData.AbbrevEraNames(Calendar.ID);
+ }
+ return (this.m_abbrevEraNames);
+ }
+ }
+
+ // Era names are 1 indexed
+ public String GetAbbreviatedEraName(int era) {
+ if (AbbreviatedEraNames.Length == 0) {
+ // If abbreviation era name is not used in this culture,
+ // return the full era name.
+ return (GetEraName(era));
+ }
+ if (era == Calendar.CurrentEra) {
+ era = Calendar.CurrentEraValue;
+ }
+ if ((--era) < m_abbrevEraNames.Length && (era >= 0)) {
+ return (m_abbrevEraNames[era]);
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ internal String[] AbbreviatedEnglishEraNames
+ {
+ get
+ {
+ if (this.m_abbrevEnglishEraNames == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.AbbreviatedEnglishEraNames] Expected Calendar.ID > 0");
+ this.m_abbrevEnglishEraNames = this.m_cultureData.AbbreviatedEnglishEraNames(Calendar.ID);
+ }
+ return (this.m_abbrevEnglishEraNames);
+ }
+ }
+
+
+ // Note that cultureData derives this from the short date format (unless someone's set this previously)
+ // Note that this property is quite undesirable.
+ public String DateSeparator
+ {
+ get
+ {
+#if FEATURE_CORECLR
+ if (this.dateSeparator == null)
+ {
+ this.dateSeparator = this.m_cultureData.DateSeparator(Calendar.ID);
+ }
+#endif
+ Contract.Assert(this.dateSeparator != null, "DateTimeFormatInfo.DateSeparator, dateSeparator != null");
+ return (this.dateSeparator);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+ this.dateSeparator = value;
+ }
+ }
+
+
+ public DayOfWeek FirstDayOfWeek
+ {
+ get
+ {
+#if FEATURE_CORECLR
+ if (this.firstDayOfWeek == -1)
+ {
+ this.firstDayOfWeek = this.m_cultureData.IFIRSTDAYOFWEEK;
+ }
+#endif
+ Contract.Assert(this.firstDayOfWeek != -1, "DateTimeFormatInfo.FirstDayOfWeek, firstDayOfWeek != -1");
+
+ return ((DayOfWeek)this.firstDayOfWeek);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value >= DayOfWeek.Sunday && value <= DayOfWeek.Saturday) {
+ firstDayOfWeek = (int)value;
+ } else {
+ throw new ArgumentOutOfRangeException(
+ "value", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ }
+ }
+
+
+ public CalendarWeekRule CalendarWeekRule
+ {
+ get
+ {
+#if FEATURE_CORECLR
+ if (this.calendarWeekRule == -1)
+ {
+ this.calendarWeekRule = this.m_cultureData.IFIRSTWEEKOFYEAR;
+ }
+#endif
+ Contract.Assert(this.calendarWeekRule != -1, "DateTimeFormatInfo.CalendarWeekRule, calendarWeekRule != -1");
+ return ((CalendarWeekRule)this.calendarWeekRule);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value >= CalendarWeekRule.FirstDay && value <= CalendarWeekRule.FirstFourDayWeek) {
+ calendarWeekRule = (int)value;
+ } else {
+ throw new ArgumentOutOfRangeException(
+ "value", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ CalendarWeekRule.FirstDay, CalendarWeekRule.FirstFourDayWeek));
+ }
+ }
+ }
+
+
+
+ public String FullDateTimePattern
+ {
+ get
+ {
+ if (fullDateTimePattern == null)
+ {
+ fullDateTimePattern = LongDatePattern + " " + LongTimePattern;
+ }
+ return (fullDateTimePattern);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ fullDateTimePattern = value;
+ }
+ }
+
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String LongDatePattern
+ {
+ get
+ {
+ // Initialize our long date pattern from the 1st array value if not set
+ if (this.longDatePattern == null)
+ {
+ // Initialize our data
+ this.longDatePattern = this.UnclonedLongDatePatterns[0];
+ }
+
+ return this.longDatePattern;
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.longDatePattern = value;
+
+ // Clear the token hash table
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ this.fullDateTimePattern = null;
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String LongTimePattern
+ {
+ get
+ {
+ // Initialize our long time pattern from the 1st array value if not set
+ if (this.longTimePattern == null)
+ {
+ // Initialize our data
+ this.longTimePattern = this.UnclonedLongTimePatterns[0];
+ }
+
+ return this.longTimePattern;
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.longTimePattern = value;
+
+ // Clear the token hash table
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ this.fullDateTimePattern = null; // Full date = long date + long Time
+ this.generalLongTimePattern = null; // General long date = short date + long Time
+ this.dateTimeOffsetPattern = null;
+ }
+ }
+
+
+ // Note: just to be confusing there's only 1 month day pattern, not a whole list
+ public String MonthDayPattern
+ {
+ get
+ {
+ if (this.monthDayPattern == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.MonthDayPattern] Expected calID > 0");
+ this.monthDayPattern = this.m_cultureData.MonthDay(Calendar.ID);
+ }
+ Contract.Assert(this.monthDayPattern != null, "DateTimeFormatInfo.MonthDayPattern, monthDayPattern != null");
+ return (this.monthDayPattern);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ this.monthDayPattern = value;
+ }
+ }
+
+
+ public String PMDesignator
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ get
+ {
+#if FEATURE_CORECLR
+ if (this.pmDesignator == null)
+ {
+ this.pmDesignator = this.m_cultureData.SPM2359;
+ }
+#endif
+ Contract.Assert(this.pmDesignator != null, "DateTimeFormatInfo.PMDesignator, pmDesignator != null");
+ return (this.pmDesignator);
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+
+ pmDesignator = value;
+ }
+
+ }
+
+
+ public String RFC1123Pattern
+ {
+ get
+ {
+ return (rfc1123Pattern);
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String ShortDatePattern
+ {
+ get
+ {
+ // Initialize our short date pattern from the 1st array value if not set
+ if (this.shortDatePattern == null)
+ {
+ // Initialize our data
+ this.shortDatePattern = this.UnclonedShortDatePatterns[0];
+ }
+
+ return this.shortDatePattern;
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.shortDatePattern = value;
+
+ // Clear the token hash table, note that even short dates could require this
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ generalLongTimePattern = null; // General long time = short date + long time
+ generalShortTimePattern = null; // General short time = short date + short Time
+ dateTimeOffsetPattern = null;
+ }
+ }
+
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String ShortTimePattern
+ {
+ get
+ {
+ // Initialize our short time pattern from the 1st array value if not set
+ if (this.shortTimePattern == null)
+ {
+ // Initialize our data
+ this.shortTimePattern = this.UnclonedShortTimePatterns[0];
+ }
+ return this.shortTimePattern;
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.shortTimePattern= value;
+
+ // Clear the token hash table, note that even short times could require this
+ ClearTokenHashTable();
+
+ // Clean up cached values that will be affected by this property.
+ generalShortTimePattern = null; // General short date = short date + short time.
+ }
+ }
+
+
+ public String SortableDateTimePattern {
+ get {
+ return (sortableDateTimePattern);
+ }
+ }
+
+ /*=================================GeneralShortTimePattern=====================
+ **Property: Return the pattern for 'g' general format: shortDate + short time
+ **Note: This is used by DateTimeFormat.cs to get the pattern for 'g'
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody asks for the general format.
+ ==============================================================================*/
+
+ internal String GeneralShortTimePattern {
+ get {
+ if (generalShortTimePattern == null) {
+ generalShortTimePattern = ShortDatePattern + " " + ShortTimePattern;
+ }
+ return (generalShortTimePattern);
+ }
+ }
+
+ /*=================================GeneralLongTimePattern=====================
+ **Property: Return the pattern for 'g' general format: shortDate + Long time
+ **Note: This is used by DateTimeFormat.cs to get the pattern for 'g'
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody asks for the general format.
+ ==============================================================================*/
+
+ internal String GeneralLongTimePattern {
+ get {
+ if (generalLongTimePattern == null) {
+ generalLongTimePattern = ShortDatePattern + " " + LongTimePattern;
+ }
+ return (generalLongTimePattern);
+ }
+ }
+
+ /*=================================DateTimeOffsetPattern==========================
+ **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset
+ **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody uses this form
+ ==============================================================================*/
+
+ /*=================================DateTimeOffsetPattern==========================
+ **Property: Return the default pattern DateTimeOffset : shortDate + long time + time zone offset
+ **Note: This is used by DateTimeFormat.cs to get the pattern for short Date + long time + time zone offset
+ ** We put this internal property here so that we can avoid doing the
+ ** concatation every time somebody uses this form
+ ==============================================================================*/
+
+ internal String DateTimeOffsetPattern {
+ get {
+ if (dateTimeOffsetPattern == null) {
+
+ string dateTimePattern = ShortDatePattern + " " + LongTimePattern;
+
+ /* LongTimePattern might contain a "z" as part of the format string in which case we don't want to append a time zone offset */
+
+ bool foundZ = false;
+ bool inQuote = false;
+ char quote = '\'';
+ for (int i = 0; !foundZ && i < LongTimePattern.Length; i++) {
+ switch (LongTimePattern[i]) {
+ case 'z':
+ /* if we aren't in a quote, we've found a z */
+ foundZ = !inQuote;
+ /* we'll fall out of the loop now because the test includes !foundZ */
+ break;
+ case '\'':
+ case '\"':
+ if (inQuote && (quote == LongTimePattern[i])) {
+ /* we were in a quote and found a matching exit quote, so we are outside a quote now */
+ inQuote = false;
+ } else if (!inQuote) {
+ quote = LongTimePattern[i];
+ inQuote = true;
+ } else {
+ /* we were in a quote and saw the other type of quote character, so we are still in a quote */
+ }
+ break;
+ case '%':
+ case '\\':
+ i++; /* skip next character that is escaped by this backslash */
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!foundZ) {
+ dateTimePattern = dateTimePattern + " zzz";
+ }
+
+ dateTimeOffsetPattern = dateTimePattern;
+ }
+ return (dateTimeOffsetPattern);
+ }
+ }
+
+ // Note that cultureData derives this from the long time format (unless someone's set this previously)
+ // Note that this property is quite undesirable.
+ public String TimeSeparator
+ {
+ get
+ {
+#if FEATURE_CORECLR
+ if (timeSeparator == null)
+ {
+ timeSeparator = this.m_cultureData.TimeSeparator;
+ }
+#endif
+ Contract.Assert(this.timeSeparator != null, "DateTimeFormatInfo.TimeSeparator, timeSeparator != null");
+ return (timeSeparator);
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ ClearTokenHashTable();
+
+ timeSeparator = value;
+ }
+ }
+
+
+ public String UniversalSortableDateTimePattern
+ {
+ get
+ {
+ return (universalSortableDateTimePattern);
+ }
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ public String YearMonthPattern
+ {
+ get
+ {
+ // Initialize our year/month pattern from the 1st array value if not set
+ if (this.yearMonthPattern == null)
+ {
+ // Initialize our data
+ this.yearMonthPattern = this.UnclonedYearMonthPatterns[0];
+ }
+ return this.yearMonthPattern;
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ // Remember the new string
+ this.yearMonthPattern = value;
+
+ // Clear the token hash table, note that even short times could require this
+ ClearTokenHashTable();
+ }
+ }
+
+ //
+ // Check if a string array contains a null value, and throw ArgumentNullException with parameter name "value"
+ //
+ static private void CheckNullValue(String[] values, int length) {
+ Contract.Requires(values != null, "value != null");
+ Contract.Requires(values.Length >= length);
+ for (int i = 0; i < length; i++) {
+ if (values[i] == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_ArrayValue"));
+ }
+ }
+ }
+
+
+ public String[] AbbreviatedDayNames
+ {
+ get
+ {
+ return ((String[])internalGetAbbreviatedDayOfWeekNames().Clone());
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 7) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ ClearTokenHashTable();
+
+ abbreviatedDayNames = value;
+ }
+ }
+
+
+ // Returns the string array of the one-letter day of week names.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] ShortestDayNames
+ {
+ get
+ {
+ return ((String[])internalGetSuperShortDayNames().Clone());
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 7)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ this.m_superShortDayNames = value;
+ }
+ }
+
+
+ public String[] DayNames
+ {
+ get
+ {
+ return ((String[])internalGetDayOfWeekNames().Clone());
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 7)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 7), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length);
+ ClearTokenHashTable();
+
+ dayNames = value;
+ }
+ }
+
+
+ public String[] AbbreviatedMonthNames {
+ get {
+ return ((String[])internalGetAbbreviatedMonthNames().Clone());
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ ClearTokenHashTable();
+ abbreviatedMonthNames = value;
+ }
+ }
+
+
+ public String[] MonthNames
+ {
+ get
+ {
+ return ((String[])internalGetMonthNames().Clone());
+ }
+
+ set {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null) {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ monthNames = value;
+ ClearTokenHashTable();
+ }
+ }
+
+ // Whitespaces that we allow in the month names.
+ // U+00a0 is non-breaking space.
+ static char[] MonthSpaces = {' ', '\u00a0'};
+
+ internal bool HasSpacesInMonthNames {
+ get {
+ return (FormatFlags & DateTimeFormatFlags.UseSpacesInMonthNames) != 0;
+ }
+ }
+
+ internal bool HasSpacesInDayNames {
+ get {
+ return (FormatFlags & DateTimeFormatFlags.UseSpacesInDayNames) != 0;
+ }
+ }
+
+
+ //
+ // internalGetMonthName
+ //
+ // Actions: Return the month name using the specified MonthNameStyles in either abbreviated form
+ // or full form.
+ // Arguments:
+ // month
+ // style To indicate a form like regular/genitive/month name in a leap year.
+ // abbreviated When true, return abbreviated form. Otherwise, return a full form.
+ // Exceptions:
+ // ArgumentOutOfRangeException When month name is invalid.
+ //
+ internal String internalGetMonthName(int month, MonthNameStyles style, bool abbreviated) {
+ //
+ // Right now, style is mutual exclusive, but I make the style to be flag so that
+ // maybe we can combine flag if there is such a need.
+ //
+ String[] monthNamesArray = null;
+ switch (style) {
+ case MonthNameStyles.Genitive:
+ monthNamesArray = internalGetGenitiveMonthNames(abbreviated);
+ break;
+ case MonthNameStyles.LeapYear:
+ monthNamesArray = internalGetLeapYearMonthNames(/*abbreviated*/);
+ break;
+ default:
+ monthNamesArray = (abbreviated ? internalGetAbbreviatedMonthNames(): internalGetMonthNames());
+ break;
+ }
+ // The month range is from 1 ~ this.m_monthNames.Length
+ // (actually is 13 right now for all cases)
+ if ((month < 1) || (month > monthNamesArray.Length)) {
+ throw new ArgumentOutOfRangeException(
+ "month", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, monthNamesArray.Length));
+ }
+ return (monthNamesArray[month-1]);
+ }
+
+ //
+ // internalGetGenitiveMonthNames
+ //
+ // Action: Retrieve the array which contains the month names in genitive form.
+ // If this culture does not use the gentive form, the normal month name is returned.
+ // Arguments:
+ // abbreviated When true, return abbreviated form. Otherwise, return a full form.
+ //
+ private String[] internalGetGenitiveMonthNames(bool abbreviated) {
+ if (abbreviated) {
+ if (this.m_genitiveAbbreviatedMonthNames == null)
+ {
+ this.m_genitiveAbbreviatedMonthNames = this.m_cultureData.AbbreviatedGenitiveMonthNames(this.Calendar.ID);
+ Contract.Assert(this.m_genitiveAbbreviatedMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 abbreviated genitive month names in a year");
+ }
+ return (this.m_genitiveAbbreviatedMonthNames);
+ }
+
+ if (this.genitiveMonthNames == null)
+ {
+ this.genitiveMonthNames = this.m_cultureData.GenitiveMonthNames(this.Calendar.ID);
+ Contract.Assert(this.genitiveMonthNames.Length == 13,
+ "[DateTimeFormatInfo.GetGenitiveMonthNames] Expected 13 genitive month names in a year");
+ }
+ return (this.genitiveMonthNames);
+ }
+
+ //
+ // internalGetLeapYearMonthNames
+ //
+ // Actions: Retrieve the month names used in a leap year.
+ // If this culture does not have different month names in a leap year, the normal month name is returned.
+ // Agruments: None. (can use abbreviated later if needed)
+ //
+ internal String[] internalGetLeapYearMonthNames(/*bool abbreviated*/) {
+ if (this.leapYearMonthNames == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expected Calendar.ID > 0");
+ this.leapYearMonthNames = this.m_cultureData.LeapYearMonthNames(Calendar.ID);
+ Contract.Assert(this.leapYearMonthNames.Length == 13,
+ "[DateTimeFormatInfo.internalGetLeapYearMonthNames] Expepcted 13 leap year month names");
+ }
+ return (leapYearMonthNames);
+ }
+
+
+ public String GetAbbreviatedDayName(DayOfWeek dayofweek)
+ {
+
+ if ((int)dayofweek < 0 || (int)dayofweek > 6) {
+ throw new ArgumentOutOfRangeException(
+ "dayofweek", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+ //
+ // Don't call the public property AbbreviatedDayNames here since a clone is needed in that
+ // property, so it will be slower. Instead, use GetAbbreviatedDayOfWeekNames() directly.
+ //
+ return (internalGetAbbreviatedDayOfWeekNames()[(int)dayofweek]);
+ }
+
+
+ // Returns the super short day of week names for the specified day of week.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String GetShortestDayName(DayOfWeek dayOfWeek)
+ {
+
+ if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) {
+ throw new ArgumentOutOfRangeException(
+ "dayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+ //
+ // Don't call the public property SuperShortDayNames here since a clone is needed in that
+ // property, so it will be slower. Instead, use internalGetSuperShortDayNames() directly.
+ //
+ return (internalGetSuperShortDayNames()[(int)dayOfWeek]);
+ }
+
+ // Get all possible combination of inputs
+ static private String[] GetCombinedPatterns(String[] patterns1, String[] patterns2, String connectString)
+ {
+ Contract.Requires(patterns1 != null);
+ Contract.Requires(patterns2 != null);
+
+ // Get array size
+ String[] result = new String[patterns1.Length * patterns2.Length];
+
+ // Counter of actual results
+ int k = 0;
+ for (int i = 0; i < patterns1.Length; i++)
+ {
+ for (int j = 0; j < patterns2.Length; j++)
+ {
+ // Can't combine if null or empty
+ result[k++] = patterns1[i] + connectString + patterns2[j];
+ }
+ }
+
+ // Return the combinations
+ return (result);
+ }
+
+
+ public String[] GetAllDateTimePatterns()
+ {
+ List<String> results = new List<String>(DEFAULT_ALL_DATETIMES_SIZE);
+
+ for (int i = 0; i < DateTimeFormat.allStandardFormats.Length; i++)
+ {
+ String[] strings = GetAllDateTimePatterns(DateTimeFormat.allStandardFormats[i]);
+ for (int j = 0; j < strings.Length; j++)
+ {
+ results.Add(strings[j]);
+ }
+ }
+ return results.ToArray();
+ }
+
+
+ public String[] GetAllDateTimePatterns(char format)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ String [] result = null;
+
+ switch (format)
+ {
+ case 'd':
+ result = this.AllShortDatePatterns;
+ break;
+ case 'D':
+ result = this.AllLongDatePatterns;
+ break;
+ case 'f':
+ result = GetCombinedPatterns(AllLongDatePatterns, AllShortTimePatterns, " ");
+ break;
+ case 'F':
+ case 'U':
+ result = GetCombinedPatterns(AllLongDatePatterns, AllLongTimePatterns, " ");
+ break;
+ case 'g':
+ result = GetCombinedPatterns(AllShortDatePatterns, AllShortTimePatterns, " ");
+ break;
+ case 'G':
+ result = GetCombinedPatterns(AllShortDatePatterns, AllLongTimePatterns, " ");
+ break;
+ case 'm':
+ case 'M':
+ result = new String[] {MonthDayPattern};
+ break;
+ case 'o':
+ case 'O':
+ result = new String[] {DateTimeFormat.RoundtripFormat};
+ break;
+ case 'r':
+ case 'R':
+ result = new String[] {rfc1123Pattern};
+ break;
+ case 's':
+ result = new String[] {sortableDateTimePattern};
+ break;
+ case 't':
+ result = this.AllShortTimePatterns;
+ break;
+ case 'T':
+ result = this.AllLongTimePatterns;
+ break;
+ case 'u':
+ result = new String[] {UniversalSortableDateTimePattern};
+ break;
+ case 'y':
+ case 'Y':
+ result = this.AllYearMonthPatterns;
+ break;
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), "format");
+ }
+ return (result);
+ }
+
+
+ public String GetDayName(DayOfWeek dayofweek)
+ {
+ if ((int)dayofweek < 0 || (int)dayofweek > 6) {
+ throw new ArgumentOutOfRangeException(
+ "dayofweek", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ DayOfWeek.Sunday, DayOfWeek.Saturday));
+ }
+ Contract.EndContractBlock();
+
+ // Use the internal one so that we don't clone the array unnecessarily
+ return (internalGetDayOfWeekNames()[(int)dayofweek]);
+ }
+
+
+
+ public String GetAbbreviatedMonthName(int month)
+ {
+ if (month < 1 || month > 13) {
+ throw new ArgumentOutOfRangeException(
+ "month", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, 13));
+ }
+ Contract.EndContractBlock();
+ // Use the internal one so we don't clone the array unnecessarily
+ return (internalGetAbbreviatedMonthNames()[month-1]);
+ }
+
+
+ public String GetMonthName(int month)
+ {
+ if (month < 1 || month > 13) {
+ throw new ArgumentOutOfRangeException(
+ "month", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, 13));
+ }
+ Contract.EndContractBlock();
+ // Use the internal one so we don't clone the array unnecessarily
+ return (internalGetMonthNames()[month-1]);
+ }
+
+ // For our "patterns" arrays we have 2 variables, a string and a string[]
+ //
+ // The string[] contains the list of patterns, EXCEPT the default may not be included.
+ // The string contains the default pattern.
+ // When we initially construct our string[], we set the string to string[0]
+ //
+ // The resulting [] can get returned to the calling app, so clone it.
+ private static string[] GetMergedPatterns(string [] patterns, string defaultPattern)
+ {
+ Contract.Assert(patterns != null && patterns.Length > 0,
+ "[DateTimeFormatInfo.GetMergedPatterns]Expected array of at least one pattern");
+ Contract.Assert(defaultPattern != null,
+ "[DateTimeFormatInfo.GetMergedPatterns]Expected non null default string");
+
+ // If the default happens to be the first in the list just return (a cloned) copy
+ if (defaultPattern == patterns[0])
+ {
+ return (string[])patterns.Clone();
+ }
+
+ // We either need a bigger list, or the pattern from the list.
+ int i;
+ for (i = 0; i < patterns.Length; i++)
+ {
+ // Stop if we found it
+ if (defaultPattern == patterns[i])
+ break;
+ }
+
+ // Either way we're going to need a new array
+ string[] newPatterns;
+
+ // Did we find it
+ if (i < patterns.Length)
+ {
+ // Found it, output will be same size
+ newPatterns = (string[])patterns.Clone();
+
+ // Have to move [0] item to [i] so we can re-write default at [0]
+ // (remember defaultPattern == [i] so this is OK)
+ newPatterns[i] = newPatterns[0];
+ }
+ else
+ {
+ // Not found, make room for it
+ newPatterns = new String[patterns.Length + 1];
+
+ // Copy existing array
+ Array.Copy(patterns, 0, newPatterns, 1, patterns.Length);
+ }
+
+ // Remember the default
+ newPatterns[0] = defaultPattern;
+
+ // Return the reconstructed list
+ return newPatterns;
+ }
+
+ // Default string isn't necessarily in our string array, so get the
+ // merged patterns of both
+ private String[] AllYearMonthPatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedYearMonthPatterns, this.YearMonthPattern);
+ }
+ }
+
+ private String[] AllShortDatePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedShortDatePatterns, this.ShortDatePattern);
+ }
+ }
+
+ private String[] AllShortTimePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedShortTimePatterns, this.ShortTimePattern);
+ }
+ }
+
+ private String[] AllLongDatePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedLongDatePatterns, this.LongDatePattern);
+ }
+ }
+
+ private String[] AllLongTimePatterns
+ {
+ get
+ {
+ return GetMergedPatterns(this.UnclonedLongTimePatterns, this.LongTimePattern);
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllYearMonthPatterns
+ private String[] UnclonedYearMonthPatterns
+ {
+ get
+ {
+ if (this.allYearMonthPatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected Calendar.ID > 0");
+ this.allYearMonthPatterns = this.m_cultureData.YearMonths(this.Calendar.ID);
+ Contract.Assert(this.allYearMonthPatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedYearMonthPatterns] Expected some year month patterns");
+ }
+
+ return this.allYearMonthPatterns;
+ }
+ }
+
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllShortDatePatterns
+ private String [] UnclonedShortDatePatterns
+ {
+ get
+ {
+ if (allShortDatePatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected Calendar.ID > 0");
+ this.allShortDatePatterns = this.m_cultureData.ShortDates(this.Calendar.ID);
+ Contract.Assert(this.allShortDatePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedShortDatePatterns] Expected some short date patterns");
+ }
+
+ return this.allShortDatePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllLongDatePatterns
+ private String[] UnclonedLongDatePatterns
+ {
+ get
+ {
+ if (allLongDatePatterns == null)
+ {
+ Contract.Assert(Calendar.ID > 0, "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected Calendar.ID > 0");
+ this.allLongDatePatterns = this.m_cultureData.LongDates(this.Calendar.ID);
+ Contract.Assert(this.allLongDatePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedLongDatePatterns] Expected some long date patterns");
+ }
+
+ return this.allLongDatePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllShortTimePatterns
+ private String[] UnclonedShortTimePatterns
+ {
+ get
+ {
+ if (this.allShortTimePatterns == null)
+ {
+ this.allShortTimePatterns = this.m_cultureData.ShortTimes;
+ Contract.Assert(this.allShortTimePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedShortTimePatterns] Expected some short time patterns");
+ }
+
+ return this.allShortTimePatterns;
+ }
+ }
+
+ // NOTE: Clone this string array if you want to return it to user. Otherwise, you are returning a writable cache copy.
+ // This won't include default, call AllLongTimePatterns
+ private String[] UnclonedLongTimePatterns
+ {
+ get
+ {
+ if (this.allLongTimePatterns == null)
+ {
+ this.allLongTimePatterns = this.m_cultureData.LongTimes;
+ Contract.Assert(this.allLongTimePatterns.Length > 0,
+ "[DateTimeFormatInfo.UnclonedLongTimePatterns] Expected some long time patterns");
+ }
+
+ return this.allLongTimePatterns;
+ }
+ }
+
+ public static DateTimeFormatInfo ReadOnly(DateTimeFormatInfo dtfi) {
+ if (dtfi == null) {
+ throw new ArgumentNullException("dtfi",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ if (dtfi.IsReadOnly) {
+ return (dtfi);
+ }
+ DateTimeFormatInfo newInfo = (DateTimeFormatInfo)(dtfi.MemberwiseClone());
+ // We can use the data member calendar in the setter, instead of the property Calendar,
+ // since the cloned copy should have the same state as the original copy.
+ newInfo.calendar = Calendar.ReadOnly(dtfi.Calendar);
+ newInfo.m_isReadOnly = true;
+ return (newInfo);
+ }
+
+
+ public bool IsReadOnly {
+ get {
+ return (m_isReadOnly);
+ }
+ }
+
+ // Return the native name for the calendar in DTFI.Calendar. The native name is referred to
+ // the culture used to create the DTFI. E.g. in the following example, the native language is Japanese.
+ // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new JapaneseCalendar();
+ // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Japanese calendar.
+ // DateTimeFormatInfo dtfi = new CultureInfo("ja-JP", false).DateTimeFormat.Calendar = new GregorianCalendar(GregorianCalendarTypes.Localized);
+ // String nativeName = dtfi.NativeCalendarName; // Get the Japanese name for the Gregorian calendar.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String NativeCalendarName
+ {
+ get
+ {
+ return m_cultureData.CalendarName(Calendar.ID);
+ }
+ }
+
+ //
+ // Used by custom cultures and others to set the list of available formats. Note that none of them are
+ // explicitly used unless someone calls GetAllDateTimePatterns and subsequently uses one of the items
+ // from the list.
+ //
+ // Most of the format characters that can be used in GetAllDateTimePatterns are
+ // not really needed since they are one of the following:
+ //
+ // r/R/s/u locale-independent constants -- cannot be changed!
+ // m/M/y/Y fields with a single string in them -- that can be set through props directly
+ // f/F/g/G/U derived fields based on combinations of various of the below formats
+ //
+ // NOTE: No special validation is done here beyond what is done when the actual respective fields
+ // are used (what would be the point of disallowing here what we allow in the appropriate property?)
+ //
+ // WARNING: If more validation is ever done in one place, it should be done in the other.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public void SetAllDateTimePatterns(String[] patterns, char format)
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (patterns == null) {
+ throw new ArgumentNullException("patterns",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+
+ if (patterns.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"), "patterns");
+ }
+ Contract.EndContractBlock();
+
+ for (int i=0; i<patterns.Length; i++)
+ {
+ if (patterns[i] == null)
+ {
+ throw new ArgumentNullException("patterns[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayValue"));
+ }
+ }
+
+ // Remember the patterns, and use the 1st as default
+ switch (format)
+ {
+ case 'd':
+ this.allShortDatePatterns = patterns;
+ this.shortDatePattern = this.allShortDatePatterns[0];
+ break;
+
+ case 'D':
+ this.allLongDatePatterns = patterns;
+ this.longDatePattern = this.allLongDatePatterns[0];
+ break;
+
+ case 't':
+ this.allShortTimePatterns = patterns;
+ this.shortTimePattern = this.allShortTimePatterns[0];
+ break;
+
+ case 'T':
+ this.allLongTimePatterns = patterns;
+ this.longTimePattern = this.allLongTimePatterns[0];
+ break;
+
+ case 'y':
+ case 'Y':
+ this.allYearMonthPatterns = patterns;
+ this.yearMonthPattern = this.allYearMonthPatterns[0];
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Format_BadFormatSpecifier"), "format");
+ }
+
+ // Clear the token hash table, note that even short dates could require this
+ ClearTokenHashTable();
+
+ return;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] AbbreviatedMonthGenitiveNames
+ {
+ get
+ {
+ return ((String[])internalGetGenitiveMonthNames(true).Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ ClearTokenHashTable();
+ this.m_genitiveAbbreviatedMonthNames= value;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] MonthGenitiveNames
+ {
+ get
+ {
+ return ((String[])internalGetGenitiveMonthNames(false).Clone());
+ }
+
+ set
+ {
+ if (IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ if (value == null)
+ {
+ throw new ArgumentNullException("value",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (value.Length != 13)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidArrayLength", 13), "value");
+ }
+ Contract.EndContractBlock();
+ CheckNullValue(value, value.Length - 1);
+ genitiveMonthNames= value;
+ ClearTokenHashTable();
+ }
+ }
+
+ //
+ // Positive TimeSpan Pattern
+ //
+ [NonSerialized]
+ private string m_fullTimeSpanPositivePattern;
+ internal String FullTimeSpanPositivePattern
+ {
+ get
+ {
+ if (m_fullTimeSpanPositivePattern == null)
+ {
+ CultureData cultureDataWithoutUserOverrides;
+ if (m_cultureData.UseUserOverride)
+ cultureDataWithoutUserOverrides = CultureData.GetCultureData(m_cultureData.CultureName, false);
+ else
+ cultureDataWithoutUserOverrides = m_cultureData;
+ String decimalSeparator = new NumberFormatInfo(cultureDataWithoutUserOverrides).NumberDecimalSeparator;
+
+ m_fullTimeSpanPositivePattern = "d':'h':'mm':'ss'" + decimalSeparator + "'FFFFFFF";
+ }
+ return m_fullTimeSpanPositivePattern;
+ }
+ }
+
+ //
+ // Negative TimeSpan Pattern
+ //
+ [NonSerialized]
+ private string m_fullTimeSpanNegativePattern;
+ internal String FullTimeSpanNegativePattern
+ {
+ get
+ {
+ if (m_fullTimeSpanNegativePattern == null)
+ m_fullTimeSpanNegativePattern = "'-'" + FullTimeSpanPositivePattern;
+ return m_fullTimeSpanNegativePattern;
+ }
+ }
+
+ //
+ // Get suitable CompareInfo from current DTFI object.
+ //
+ internal CompareInfo CompareInfo
+ {
+ get
+ {
+ if (m_compareInfo == null)
+ {
+ // We use the regular GetCompareInfo here to make sure the created CompareInfo object is stored in the
+ // CompareInfo cache. otherwise we would just create CompareInfo using m_cultureData.
+ m_compareInfo = CompareInfo.GetCompareInfo(m_cultureData.SCOMPAREINFO);
+ }
+
+ return m_compareInfo;
+ }
+ }
+
+
+ internal const DateTimeStyles InvalidDateTimeStyles = ~(DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite
+ | DateTimeStyles.AllowInnerWhite | DateTimeStyles.NoCurrentDateDefault
+ | DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeLocal
+ | DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind);
+
+ internal static void ValidateStyles(DateTimeStyles style, String parameterName) {
+ if ((style & InvalidDateTimeStyles) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeStyles"), parameterName);
+ }
+ if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeStyles"), parameterName);
+ }
+ Contract.EndContractBlock();
+ if (((style & DateTimeStyles.RoundtripKind) != 0)
+ && ((style & (DateTimeStyles.AssumeLocal | DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)) != 0)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeRoundtripStyles"), parameterName);
+ }
+ }
+
+ //
+ // Actions: Return the internal flag used in formatting and parsing.
+ // The flag can be used to indicate things like if genitive forms is used in this DTFi, or if leap year gets different month names.
+ //
+ internal DateTimeFormatFlags FormatFlags
+ {
+ get
+ {
+ if (formatFlags == DateTimeFormatFlags.NotInitialized)
+ {
+ // Build the format flags from the data in this DTFI
+ formatFlags = DateTimeFormatFlags.None;
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagGenitiveMonth(
+ MonthNames, internalGetGenitiveMonthNames(false), AbbreviatedMonthNames, internalGetGenitiveMonthNames(true));
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInMonthNames(
+ MonthNames, internalGetGenitiveMonthNames(false), AbbreviatedMonthNames, internalGetGenitiveMonthNames(true));
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseSpaceInDayNames(DayNames, AbbreviatedDayNames);
+ formatFlags |= (DateTimeFormatFlags)DateTimeFormatInfoScanner.GetFormatFlagUseHebrewCalendar((int)Calendar.ID);
+ }
+ return (formatFlags);
+ }
+ }
+
+ internal Boolean HasForceTwoDigitYears {
+ get {
+ switch (calendar.ID)
+ {
+ // If is y/yy, do not get (year % 100). "y" will print
+ // year without leading zero. "yy" will print year with two-digit in leading zero.
+ // If pattern is yyy/yyyy/..., print year value with two-digit in leading zero.
+ // So year 5 is "05", and year 125 is "125".
+ // The reason for not doing (year % 100) is for Taiwan calendar.
+ // If year 125, then output 125 and not 25.
+ // Note: OS uses "yyyy" for Taiwan calendar by default.
+ case (Calendar.CAL_JAPAN):
+ case (Calendar.CAL_TAIWAN):
+ return true;
+ }
+ return false;
+ }
+ }
+
+ // Returns whether the YearMonthAdjustment function has any fix-up work to do for this culture/calendar.
+ internal Boolean HasYearMonthAdjustment {
+ get {
+ return ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0);
+ }
+ }
+
+ // This is a callback that the parser can make back into the DTFI to let it fiddle with special
+ // cases associated with that culture or calendar. Currently this only has special cases for
+ // the Hebrew calendar, but this could be extended to other cultures.
+ //
+ // The return value is whether the year and month are actually valid for this calendar.
+ internal Boolean YearMonthAdjustment(ref int year, ref int month, Boolean parsedMonthName) {
+ if ((FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0) {
+
+ // Special rules to fix up the Hebrew year/month
+
+ // When formatting, we only format up to the hundred digit of the Hebrew year, although Hebrew year is now over 5000.
+ // E.g. if the year is 5763, we only format as 763.
+ if (year < 1000) {
+ year += 5000;
+ }
+
+ // Because we need to calculate leap year, we should fall out now for an invalid year.
+ if (year < Calendar.GetYear(Calendar.MinSupportedDateTime) || year > Calendar.GetYear(Calendar.MaxSupportedDateTime)) {
+ return false;
+ }
+
+ // To handle leap months, the set of month names in the symbol table does not always correspond to the numbers.
+ // For non-leap years, month 7 (Adar Bet) is not present, so we need to make using this month invalid and
+ // shuffle the other months down.
+ if (parsedMonthName) {
+ if (!Calendar.IsLeapYear(year)) {
+ if (month >= 8) {
+ month--;
+ }
+ else if (month == 7) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ //
+ // DateTimeFormatInfo tokenizer. This is used by DateTime.Parse() to break input string into tokens.
+ //
+ [NonSerialized]
+ TokenHashValue[] m_dtfiTokenHash;
+
+ private const int TOKEN_HASH_SIZE = 199;
+ private const int SECOND_PRIME = 197;
+ private const String dateSeparatorOrTimeZoneOffset = "-";
+ private const String invariantDateSeparator = "/";
+ private const String invariantTimeSeparator = ":";
+
+ //
+ // Common Ignorable Symbols
+ //
+ internal const String IgnorablePeriod = ".";
+ internal const String IgnorableComma = ",";
+
+ //
+ // Year/Month/Day suffixes
+ //
+ internal const String CJKYearSuff = "\u5e74";
+ internal const String CJKMonthSuff = "\u6708";
+ internal const String CJKDaySuff = "\u65e5";
+
+ internal const String KoreanYearSuff = "\ub144";
+ internal const String KoreanMonthSuff = "\uc6d4";
+ internal const String KoreanDaySuff = "\uc77c";
+
+ internal const String KoreanHourSuff = "\uc2dc";
+ internal const String KoreanMinuteSuff = "\ubd84";
+ internal const String KoreanSecondSuff = "\ucd08";
+
+ internal const String CJKHourSuff = "\u6642";
+ internal const String ChineseHourSuff = "\u65f6";
+
+ internal const String CJKMinuteSuff = "\u5206";
+ internal const String CJKSecondSuff = "\u79d2";
+
+ internal const String LocalTimeMark = "T";
+
+ internal const String KoreanLangName = "ko";
+ internal const String JapaneseLangName = "ja";
+ internal const String EnglishLangName = "en";
+
+ private static volatile DateTimeFormatInfo s_jajpDTFI;
+ private static volatile DateTimeFormatInfo s_zhtwDTFI;
+
+ //
+ // Create a Japanese DTFI which uses JapaneseCalendar. This is used to parse
+ // date string with Japanese era name correctly even when the supplied DTFI
+ // does not use Japanese calendar.
+ // The created instance is stored in global s_jajpDTFI.
+ //
+ internal static DateTimeFormatInfo GetJapaneseCalendarDTFI() {
+ DateTimeFormatInfo temp = s_jajpDTFI;
+ if (temp == null) {
+ temp = new CultureInfo("ja-JP", false).DateTimeFormat;
+ temp.Calendar = JapaneseCalendar.GetDefaultInstance();
+ s_jajpDTFI = temp;
+ }
+ return (temp);
+ }
+ internal static DateTimeFormatInfo GetTaiwanCalendarDTFI() {
+ DateTimeFormatInfo temp = s_zhtwDTFI;
+ if (temp == null) {
+ temp = new CultureInfo("zh-TW", false).DateTimeFormat;
+ temp.Calendar = TaiwanCalendar.GetDefaultInstance();
+ s_zhtwDTFI = temp;
+ }
+ return (temp);
+ }
+
+
+ // DTFI properties should call this when the setter are called.
+ private void ClearTokenHashTable()
+ {
+ m_dtfiTokenHash = null;
+ formatFlags = DateTimeFormatFlags.NotInitialized;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal TokenHashValue[] CreateTokenHashTable() {
+ TokenHashValue[] temp = m_dtfiTokenHash;
+ if (temp == null) {
+ temp = new TokenHashValue[TOKEN_HASH_SIZE];
+
+ bool koreanLanguage = LanguageName.Equals(KoreanLangName);
+
+ string sep = this.TimeSeparator.Trim();
+ if (IgnorableComma != sep) InsertHash(temp, IgnorableComma, TokenType.IgnorableSymbol, 0);
+ if (IgnorablePeriod != sep) InsertHash(temp, IgnorablePeriod, TokenType.IgnorableSymbol, 0);
+
+ if (KoreanHourSuff != sep && CJKHourSuff != sep && ChineseHourSuff != sep) {
+ //
+ // On the Macintosh, the default TimeSeparator is identical to the KoreanHourSuff, CJKHourSuff, or ChineseHourSuff for some cultures like
+ // ja-JP and ko-KR. In these cases having the same symbol inserted into the hash table with multiple TokenTypes causes undesirable
+ // DateTime.Parse behavior. For instance, the DateTimeFormatInfo.Tokenize() method might return SEP_DateOrOffset for KoreanHourSuff
+ // instead of SEP_HourSuff.
+ //
+ InsertHash(temp, this.TimeSeparator, TokenType.SEP_Time, 0);
+ }
+
+ InsertHash(temp, this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+
+ if (LanguageName.Equals("sq")) {
+ // Albanian allows time formats like "12:00.PD"
+ InsertHash(temp, IgnorablePeriod + this.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, IgnorablePeriod + this.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+ }
+
+ // CJK suffix
+ InsertHash(temp, CJKYearSuff, TokenType.SEP_YearSuff, 0);
+ InsertHash(temp, KoreanYearSuff, TokenType.SEP_YearSuff, 0);
+ InsertHash(temp, CJKMonthSuff, TokenType.SEP_MonthSuff, 0);
+ InsertHash(temp, KoreanMonthSuff, TokenType.SEP_MonthSuff, 0);
+ InsertHash(temp, CJKDaySuff, TokenType.SEP_DaySuff, 0);
+ InsertHash(temp, KoreanDaySuff, TokenType.SEP_DaySuff, 0);
+
+ InsertHash(temp, CJKHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, ChineseHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, CJKMinuteSuff, TokenType.SEP_MinuteSuff, 0);
+ InsertHash(temp, CJKSecondSuff, TokenType.SEP_SecondSuff, 0);
+
+ if (koreanLanguage) {
+ // Korean suffix
+ InsertHash(temp, KoreanHourSuff, TokenType.SEP_HourSuff, 0);
+ InsertHash(temp, KoreanMinuteSuff, TokenType.SEP_MinuteSuff, 0);
+ InsertHash(temp, KoreanSecondSuff, TokenType.SEP_SecondSuff, 0);
+ }
+
+ if ( LanguageName.Equals("ky")) {
+ // For some cultures, the date separator works more like a comma, being allowed before or after any date part
+ InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.IgnorableSymbol, 0);
+ }
+ else {
+ InsertHash(temp, dateSeparatorOrTimeZoneOffset, TokenType.SEP_DateOrOffset, 0);
+ }
+
+ String[] dateWords = null;
+ DateTimeFormatInfoScanner scanner = null;
+
+ // We need to rescan the date words since we're always synthetic
+ scanner = new DateTimeFormatInfoScanner();
+ // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
+ // The only reason they're being assigned to m_dateWords is for Whidbey Deserialization
+ m_dateWords = dateWords = scanner.GetDateWordsOfDTFI(this);
+ // Ensure the formatflags is initialized.
+ DateTimeFormatFlags flag = FormatFlags;
+
+ // For some cultures, the date separator works more like a comma, being allowed before or after any date part.
+ // In these cultures, we do not use normal date separator since we disallow date separator after a date terminal state.
+ // This is determined in DateTimeFormatInfoScanner. Use this flag to determine if we should treat date separator as ignorable symbol.
+ bool useDateSepAsIgnorableSymbol = false;
+
+ String monthPostfix = null;
+ if (dateWords != null)
+ {
+ // There are DateWords. It could be a real date word (such as "de"), or a monthPostfix.
+ // The monthPostfix starts with '\xfffe' (MonthPostfixChar), followed by the real monthPostfix.
+ for (int i = 0; i < dateWords.Length; i++)
+ {
+ switch (dateWords[i][0])
+ {
+ // This is a month postfix
+ case DateTimeFormatInfoScanner.MonthPostfixChar:
+ // Get the real month postfix.
+ monthPostfix = dateWords[i].Substring(1);
+ // Add the month name + postfix into the token.
+ AddMonthNames(temp, monthPostfix);
+ break;
+ case DateTimeFormatInfoScanner.IgnorableSymbolChar:
+ String symbol = dateWords[i].Substring(1);
+ InsertHash(temp, symbol, TokenType.IgnorableSymbol, 0);
+ if (this.DateSeparator.Trim(null).Equals(symbol))
+ {
+ // The date separator is the same as the ingorable symbol.
+ useDateSepAsIgnorableSymbol = true;
+ }
+ break;
+ default:
+ InsertHash(temp, dateWords[i], TokenType.DateWordToken, 0);
+ if (LanguageName.Equals("eu")) {
+ // Basque has date words with leading dots
+ InsertHash(temp, IgnorablePeriod + dateWords[i], TokenType.DateWordToken, 0);
+ }
+ break;
+ }
+ }
+ }
+
+ if (!useDateSepAsIgnorableSymbol)
+ {
+ // Use the normal date separator.
+ InsertHash(temp, this.DateSeparator, TokenType.SEP_Date, 0);
+ }
+ // Add the regular month names.
+ AddMonthNames(temp, null);
+
+ // Add the abbreviated month names.
+ for (int i = 1; i <= 13; i++) {
+ InsertHash(temp, GetAbbreviatedMonthName(i), TokenType.MonthToken, i);
+ }
+
+
+ if ((FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0) {
+ for (int i = 1; i <= 13; i++) {
+ String str;
+ str = internalGetMonthName(i, MonthNameStyles.Genitive, false);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+
+ if ((FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) {
+ for (int i = 1; i <= 13; i++) {
+ String str;
+ str = internalGetMonthName(i, MonthNameStyles.LeapYear, false);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+
+ for (int i = 0; i < 7; i++) {
+ //String str = GetDayOfWeekNames()[i];
+ // We have to call public methods here to work with inherited DTFI.
+ String str = GetDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ str = GetAbbreviatedDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ }
+
+ int[] eras = calendar.Eras;
+ for (int i = 1; i <= eras.Length; i++) {
+ InsertHash(temp, GetEraName(i), TokenType.EraToken, i);
+ InsertHash(temp, GetAbbreviatedEraName(i), TokenType.EraToken, i);
+ }
+
+ if (LanguageName.Equals(JapaneseLangName)) {
+ // Japanese allows day of week forms like: "(Tue)"
+ for (int i = 0; i < 7; i++) {
+ String specialDayOfWeek = "(" + GetAbbreviatedDayName((DayOfWeek)i) + ")";
+ InsertHash(temp, specialDayOfWeek, TokenType.DayOfWeekToken, i);
+ }
+ if (this.Calendar.GetType() != typeof(JapaneseCalendar)) {
+ // Special case for Japanese. If this is a Japanese DTFI, and the calendar is not Japanese calendar,
+ // we will check Japanese Era name as well when the calendar is Gregorian.
+ DateTimeFormatInfo jaDtfi = GetJapaneseCalendarDTFI();
+ for (int i = 1; i <= jaDtfi.Calendar.Eras.Length; i++) {
+ InsertHash(temp, jaDtfi.GetEraName(i), TokenType.JapaneseEraToken, i);
+ InsertHash(temp, jaDtfi.GetAbbreviatedEraName(i), TokenType.JapaneseEraToken, i);
+ // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
+ InsertHash(temp, jaDtfi.AbbreviatedEnglishEraNames[i-1], TokenType.JapaneseEraToken, i);
+ }
+ }
+ }
+ else if (CultureName.Equals("zh-TW")) {
+ DateTimeFormatInfo twDtfi = GetTaiwanCalendarDTFI();
+ for (int i = 1; i <= twDtfi.Calendar.Eras.Length; i++) {
+ if (twDtfi.GetEraName(i).Length > 0) {
+ InsertHash(temp, twDtfi.GetEraName(i), TokenType.TEraToken, i);
+ }
+ }
+ }
+
+ InsertHash(temp, InvariantInfo.AMDesignator, TokenType.SEP_Am | TokenType.Am, 0);
+ InsertHash(temp, InvariantInfo.PMDesignator, TokenType.SEP_Pm | TokenType.Pm, 1);
+
+ // Add invariant month names and day names.
+ for (int i = 1; i <= 12; i++) {
+ String str;
+ // We have to call public methods here to work with inherited DTFI.
+ // Insert the month name first, so that they are at the front of abbrevaited
+ // month names.
+ str = InvariantInfo.GetMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ str = InvariantInfo.GetAbbreviatedMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+
+ for (int i = 0; i < 7; i++) {
+ // We have to call public methods here to work with inherited DTFI.
+ String str = InvariantInfo.GetDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ str = InvariantInfo.GetAbbreviatedDayName((DayOfWeek)i);
+ InsertHash(temp, str, TokenType.DayOfWeekToken, i);
+
+ }
+
+ for (int i = 0; i < AbbreviatedEnglishEraNames.Length; i++) {
+ // m_abbrevEnglishEraNames[0] contains the name for era 1, so the token value is i+1.
+ InsertHash(temp, AbbreviatedEnglishEraNames[i], TokenType.EraToken, i + 1);
+ }
+
+ InsertHash(temp, LocalTimeMark, TokenType.SEP_LocalTimeMark, 0);
+ InsertHash(temp, DateTimeParse.GMTName, TokenType.TimeZoneToken, 0);
+ InsertHash(temp, DateTimeParse.ZuluName, TokenType.TimeZoneToken, 0);
+
+ InsertHash(temp, invariantDateSeparator, TokenType.SEP_Date, 0);
+ InsertHash(temp, invariantTimeSeparator, TokenType.SEP_Time, 0);
+
+ m_dtfiTokenHash = temp;
+ }
+ return (temp);
+ }
+
+ private void AddMonthNames(TokenHashValue[] temp, String monthPostfix)
+ {
+ for (int i = 1; i <= 13; i++) {
+ String str;
+ //str = internalGetMonthName(i, MonthNameStyles.Regular, false);
+ // We have to call public methods here to work with inherited DTFI.
+ // Insert the month name first, so that they are at the front of abbrevaited
+ // month names.
+ str = GetMonthName(i);
+ if (str.Length > 0) {
+ if (monthPostfix != null) {
+ // Insert the month name with the postfix first, so it can be matched first.
+ InsertHash(temp, str + monthPostfix, TokenType.MonthToken, i);
+ } else
+ {
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+ }
+ str = GetAbbreviatedMonthName(i);
+ InsertHash(temp, str, TokenType.MonthToken, i);
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Try to parse the current word to see if it is a Hebrew number.
+ // Tokens will be updated accordingly.
+ // This is called by the Lexer of DateTime.Parse().
+ //
+ // Unlike most of the functions in this class, the return value indicates
+ // whether or not it started to parse. The badFormat parameter indicates
+ // if parsing began, but the format was bad.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ private static bool TryParseHebrewNumber(
+ ref __DTString str,
+ out Boolean badFormat,
+ out int number) {
+
+ number = -1;
+ badFormat = false;
+
+ int i = str.Index;
+ if (!HebrewNumber.IsDigit(str.Value[i])) {
+ // If the current character is not a Hebrew digit, just return false.
+ // There is no chance that we can parse a valid Hebrew number from here.
+ return (false);
+ }
+ // The current character is a Hebrew digit. Try to parse this word as a Hebrew number.
+ HebrewNumberParsingContext context = new HebrewNumberParsingContext(0);
+ HebrewNumberParsingState state;
+
+ do {
+ state = HebrewNumber.ParseByChar(str.Value[i++], ref context);
+ switch (state) {
+ case HebrewNumberParsingState.InvalidHebrewNumber: // Not a valid Hebrew number.
+ case HebrewNumberParsingState.NotHebrewDigit: // The current character is not a Hebrew digit character.
+ // Break out so that we don't continue to try parse this as a Hebrew number.
+ return (false);
+ }
+ } while (i < str.Value.Length && (state != HebrewNumberParsingState.FoundEndOfHebrewNumber));
+
+ // When we are here, we are either at the end of the string, or we find a valid Hebrew number.
+ Contract.Assert(state == HebrewNumberParsingState.ContinueParsing || state == HebrewNumberParsingState.FoundEndOfHebrewNumber,
+ "Invalid returned state from HebrewNumber.ParseByChar()");
+
+ if (state != HebrewNumberParsingState.FoundEndOfHebrewNumber) {
+ // We reach end of the string but we can't find a terminal state in parsing Hebrew number.
+ return (false);
+ }
+
+ // We have found a valid Hebrew number. Update the index.
+ str.Advance(i - str.Index);
+
+ // Get the final Hebrew number value from the HebrewNumberParsingContext.
+ number = context.result;
+
+ return (true);
+ }
+
+ private static bool IsHebrewChar(char ch) {
+ return (ch >= '\x0590' && ch <= '\x05ff');
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool Tokenize(TokenType TokenMask, out TokenType tokenType, out int tokenValue, ref __DTString str) {
+ tokenType = TokenType.UnknownToken;
+ tokenValue = 0;
+
+ TokenHashValue value;
+ Contract.Assert(str.Index < str.Value.Length, "DateTimeFormatInfo.Tokenize(): start < value.Length");
+
+ char ch = str.m_current;
+ bool isLetter = Char.IsLetter(ch);
+ if (isLetter) {
+ ch = Char.ToLower(ch, this.Culture);
+ if (IsHebrewChar(ch) && TokenMask == TokenType.RegularTokenMask) {
+ bool badFormat;
+ if (TryParseHebrewNumber(ref str, out badFormat, out tokenValue)) {
+ if (badFormat) {
+ tokenType = TokenType.UnknownToken;
+ return (false);
+ }
+ // This is a Hebrew number.
+ // Do nothing here. TryParseHebrewNumber() will update token accordingly.
+ tokenType = TokenType.HebrewNumber;
+ return (true);
+ }
+ }
+ }
+
+
+ int hashcode = ch % TOKEN_HASH_SIZE;
+ int hashProbe = 1 + ch % SECOND_PRIME;
+ int remaining = str.len - str.Index;
+ int i = 0;
+
+ TokenHashValue[] hashTable = m_dtfiTokenHash;
+ if (hashTable == null) {
+ hashTable = CreateTokenHashTable();
+ }
+ do {
+ value = hashTable[hashcode];
+ if (value == null) {
+ // Not found.
+ break;
+ }
+ // Check this value has the right category (regular token or separator token) that we are looking for.
+ if (((int)value.tokenType & (int)TokenMask) > 0 && value.tokenString.Length <= remaining) {
+ if (String.Compare(str.Value, str.Index, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase)==0) {
+ if (isLetter) {
+ // If this token starts with a letter, make sure that we won't allow partial match. So you can't tokenize "MarchWed" separately.
+ int nextCharIndex;
+ if ((nextCharIndex = str.Index + value.tokenString.Length) < str.len) {
+ // Check word boundary. The next character should NOT be a letter.
+ char nextCh = str.Value[nextCharIndex];
+ if (Char.IsLetter(nextCh)) {
+ return (false);
+ }
+ }
+ }
+ tokenType = value.tokenType & TokenMask;
+ tokenValue = value.tokenValue;
+ str.Advance(value.tokenString.Length);
+ return (true);
+ } else if (value.tokenType == TokenType.MonthToken && HasSpacesInMonthNames) {
+ // For month token, we will match the month names which have spaces.
+ int matchStrLen = 0;
+ if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen)) {
+ tokenType = value.tokenType & TokenMask;
+ tokenValue = value.tokenValue;
+ str.Advance(matchStrLen);
+ return (true);
+ }
+ } else if (value.tokenType == TokenType.DayOfWeekToken && HasSpacesInDayNames) {
+ // For month token, we will match the month names which have spaces.
+ int matchStrLen = 0;
+ if (str.MatchSpecifiedWords(value.tokenString, true, ref matchStrLen)) {
+ tokenType = value.tokenType & TokenMask;
+ tokenValue = value.tokenValue;
+ str.Advance(matchStrLen);
+ return (true);
+ }
+ }
+ }
+ i++;
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ }while (i < TOKEN_HASH_SIZE);
+
+ return (false);
+ }
+
+ void InsertAtCurrentHashNode(TokenHashValue[] hashTable, String str, char ch, TokenType tokenType, int tokenValue, int pos, int hashcode, int hashProbe) {
+ // Remember the current slot.
+ TokenHashValue previousNode = hashTable[hashcode];
+
+ //// Console.WriteLine(" Insert Key: {0} in {1}", str, slotToInsert);
+ // Insert the new node into the current slot.
+ hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);;
+
+ while (++pos < TOKEN_HASH_SIZE) {
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ // Remember this slot
+ TokenHashValue temp = hashTable[hashcode];
+
+ if (temp != null && Char.ToLower(temp.tokenString[0], this.Culture) != ch) {
+ continue;
+ }
+ // Put the previous slot into this slot.
+ hashTable[hashcode] = previousNode;
+ //// Console.WriteLine(" Move {0} to slot {1}", previousNode.tokenString, hashcode);
+ if (temp == null) {
+ // Done
+ return;
+ }
+ previousNode = temp;
+ } ;
+ Contract.Assert(false, "The hashtable is full. This should not happen.");
+ }
+
+ void InsertHash(TokenHashValue[] hashTable, String str, TokenType tokenType, int tokenValue) {
+ // The month of the 13th month is allowed to be null, so make sure that we ignore null value here.
+ if (str == null || str.Length == 0) {
+ return;
+ }
+ TokenHashValue value;
+ int i = 0;
+ // If there is whitespace characters in the beginning and end of the string, trim them since whitespaces are skipped by
+ // DateTime.Parse().
+ if (Char.IsWhiteSpace(str[0]) || Char.IsWhiteSpace(str[str.Length - 1])) {
+ str = str.Trim(null); // Trim white space characters.
+ // Could have space for separators
+ if (str.Length == 0)
+ return;
+ }
+ char ch = Char.ToLower(str[0], this.Culture);
+ int hashcode = ch % TOKEN_HASH_SIZE;
+ int hashProbe = 1 + ch % SECOND_PRIME;
+ do {
+ value = hashTable[hashcode];
+ if (value == null) {
+ //// Console.WriteLine(" Put Key: {0} in {1}", str, hashcode);
+ hashTable[hashcode] = new TokenHashValue(str, tokenType, tokenValue);
+ return;
+ } else {
+ // Collision happens. Find another slot.
+ if (str.Length >= value.tokenString.Length) {
+ // If there are two tokens with the same prefix, we have to make sure that the longer token should be at the front of
+ // the shorter ones.
+ if (String.Compare(str, 0, value.tokenString, 0, value.tokenString.Length, this.Culture, CompareOptions.IgnoreCase) == 0) {
+ if (str.Length > value.tokenString.Length) {
+ // The str to be inserted has the same prefix as the current token, and str is longer.
+ // Insert str into this node, and shift every node behind it.
+ InsertAtCurrentHashNode(hashTable, str, ch, tokenType, tokenValue, i, hashcode, hashProbe);
+ return;
+ } else {
+ // Same token. If they have different types (regular token vs separator token). Add them.
+ // If we have the same regular token or separator token in the hash already, do NOT update the hash.
+ // Therefore, the order of inserting token is significant here regarding what tokenType will be kept in the hash.
+
+
+ //
+ // Check the current value of RegularToken (stored in the lower 8-bit of tokenType) , and insert the tokenType into the hash ONLY when we don't have a RegularToken yet.
+ // Also check the current value of SeparatorToken (stored in the upper 8-bit of token), and insert the tokenType into the hash ONLY when we don't have the SeparatorToken yet.
+ //
+
+ int nTokenType = (int)tokenType;
+ int nCurrentTokenTypeInHash = (int)value.tokenType;
+
+ // The idea behind this check is:
+ // - if the app is targetting 4.5.1 or above OR the compat flag is set, use the correct behavior by default.
+ // - if the app is targetting 4.5 or below AND the compat switch is set, use the correct behavior
+ // - if the app is targetting 4.5 or below AND the compat switch is NOT set, use the incorrect behavior
+ if (preferExistingTokens || BinaryCompatibility.TargetsAtLeast_Desktop_V4_5_1)
+ {
+ if (((nCurrentTokenTypeInHash & (int)TokenType.RegularTokenMask) == 0) && ((nTokenType & (int)TokenType.RegularTokenMask) != 0) ||
+ ((nCurrentTokenTypeInHash & (int)TokenType.SeparatorTokenMask) == 0) && ((nTokenType & (int)TokenType.SeparatorTokenMask) != 0))
+ {
+ value.tokenType |= tokenType;
+ if (tokenValue != 0)
+ {
+ value.tokenValue = tokenValue;
+ }
+ }
+ }
+ else
+ {
+ // The following logic is incorrect and causes updates to happen depending on the bitwise relationship between the existing token type and the
+ // the stored token type. It was this way in .NET 4 RTM. The behavior above is correct and will be adopted going forward.
+
+ if ((((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.RegularTokenMask) == nTokenType) ||
+ (((nTokenType | nCurrentTokenTypeInHash) & (int)TokenType.SeparatorTokenMask) == nTokenType))
+ {
+ value.tokenType |= tokenType;
+ if (tokenValue != 0)
+ {
+ value.tokenValue = tokenValue;
+ }
+ }
+ }
+ // The token to be inserted is already in the table. Skip it.
+ }
+ }
+ }
+ }
+ //// Console.WriteLine(" COLLISION. Old Key: {0}, New Key: {1}", hashTable[hashcode].tokenString, str);
+ i++;
+ hashcode += hashProbe;
+ if (hashcode >= TOKEN_HASH_SIZE) hashcode -= TOKEN_HASH_SIZE;
+ } while (i < TOKEN_HASH_SIZE);
+ Contract.Assert(false, "The hashtable is full. This should not happen.");
+ }
+ } // class DateTimeFormatInfo
+
+ internal class TokenHashValue {
+ internal String tokenString;
+ internal TokenType tokenType;
+ internal int tokenValue;
+
+ internal TokenHashValue(String tokenString, TokenType tokenType, int tokenValue) {
+ this.tokenString = tokenString;
+ this.tokenType = tokenType;
+ this.tokenValue = tokenValue;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs
new file mode 100644
index 0000000000..40cbabc096
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DateTimeFormatInfoScanner.cs
@@ -0,0 +1,750 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+////////////////////////////////////////////////////////////////////////////
+//
+// DateTimeFormatInfoScanner
+//
+// Scan a specified DateTimeFormatInfo to search for data used in DateTime.Parse()
+//
+// The data includes:
+//
+// DateWords: such as "de" used in es-ES (Spanish) LongDatePattern.
+// Postfix: such as "ta" used in fi-FI after the month name.
+//
+// This class is shared among mscorlib.dll and sysglobl.dll.
+// Use conditional CULTURE_AND_REGIONINFO_BUILDER_ONLY to differentiate between
+// methods for mscorlib.dll and sysglobl.dll.
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization
+{
+ using System;
+ using System.Globalization;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Text;
+
+ //
+ // from LocaleEx.txt header
+ //
+ //; IFORMATFLAGS
+ //; Parsing/formatting flags.
+ internal enum FORMATFLAGS {
+ None = 0x00000000,
+ UseGenitiveMonth = 0x00000001,
+ UseLeapYearMonth = 0x00000002,
+ UseSpacesInMonthNames = 0x00000004,
+ UseHebrewParsing = 0x00000008,
+ UseSpacesInDayNames = 0x00000010, // Has spaces or non-breaking space in the day names.
+ UseDigitPrefixInTokens = 0x00000020, // Has token starting with numbers.
+ }
+
+ //
+ // To change in CalendarId you have to do the same change in Calendar.cs
+ // To do: make the definintion shared between these two files.
+ //
+
+ internal enum CalendarId : ushort
+ {
+ GREGORIAN = 1 , // Gregorian (localized) calendar
+ GREGORIAN_US = 2 , // Gregorian (U.S.) calendar
+ JAPAN = 3 , // Japanese Emperor Era calendar
+/* SSS_WARNINGS_OFF */ TAIWAN = 4 , // Taiwan Era calendar /* SSS_WARNINGS_ON */
+ KOREA = 5 , // Korean Tangun Era calendar
+ HIJRI = 6 , // Hijri (Arabic Lunar) calendar
+ THAI = 7 , // Thai calendar
+ HEBREW = 8 , // Hebrew (Lunar) calendar
+ GREGORIAN_ME_FRENCH = 9 , // Gregorian Middle East French calendar
+ GREGORIAN_ARABIC = 10, // Gregorian Arabic calendar
+ GREGORIAN_XLIT_ENGLISH = 11, // Gregorian Transliterated English calendar
+ GREGORIAN_XLIT_FRENCH = 12,
+// Note that all calendars after this point are MANAGED ONLY for now.
+ JULIAN = 13,
+ JAPANESELUNISOLAR = 14,
+ CHINESELUNISOLAR = 15,
+ SAKA = 16, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_CHN = 17, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_KOR = 18, // reserved to match Office but not implemented in our code
+ LUNAR_ETO_ROKUYOU = 19, // reserved to match Office but not implemented in our code
+ KOREANLUNISOLAR = 20,
+ TAIWANLUNISOLAR = 21,
+ PERSIAN = 22,
+ UMALQURA = 23,
+ LAST_CALENDAR = 23 // Last calendar ID
+ }
+
+ internal class DateTimeFormatInfoScanner
+ {
+ // Special prefix-like flag char in DateWord array.
+
+ // Use char in PUA area since we won't be using them in real data.
+ // The char used to tell a read date word or a month postfix. A month postfix
+ // is "ta" in the long date pattern like "d. MMMM'ta 'yyyy" for fi-FI.
+ // In this case, it will be stored as "\xfffeta" in the date word array.
+ internal const char MonthPostfixChar = '\xe000';
+
+ // Add ignorable symbol in a DateWord array.
+
+ // hu-HU has:
+ // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
+ // long date pattern: yyyy. MMMM d.
+ // Here, "." is the date separator (derived from short date pattern). However,
+ // "." also appear at the end of long date pattern. In this case, we just
+ // "." as ignorable symbol so that the DateTime.Parse() state machine will not
+ // treat the additional date separator at the end of y,m,d pattern as an error
+ // condition.
+ internal const char IgnorableSymbolChar = '\xe001';
+
+ // Known CJK suffix
+ internal const String CJKYearSuff = "\u5e74";
+ internal const String CJKMonthSuff = "\u6708";
+ internal const String CJKDaySuff = "\u65e5";
+
+ internal const String KoreanYearSuff = "\ub144";
+ internal const String KoreanMonthSuff = "\uc6d4";
+ internal const String KoreanDaySuff = "\uc77c";
+
+ internal const String KoreanHourSuff = "\uc2dc";
+ internal const String KoreanMinuteSuff = "\ubd84";
+ internal const String KoreanSecondSuff = "\ucd08";
+
+ internal const String CJKHourSuff = "\u6642";
+ internal const String ChineseHourSuff = "\u65f6";
+
+ internal const String CJKMinuteSuff = "\u5206";
+ internal const String CJKSecondSuff = "\u79d2";
+
+ // The collection fo date words & postfix.
+ internal List<String> m_dateWords = new List<String>();
+ // Hashtable for the known words.
+ private static volatile Dictionary<String, String> s_knownWords;
+
+ static Dictionary<String, String> KnownWords
+ {
+ get
+ {
+ if (s_knownWords == null)
+ {
+ Dictionary<String, String> temp = new Dictionary<String, String>();
+ // Add known words into the hash table.
+
+ // Skip these special symbols.
+ temp.Add("/", String.Empty);
+ temp.Add("-", String.Empty);
+ temp.Add(".", String.Empty);
+ // Skip known CJK suffixes.
+ temp.Add(CJKYearSuff, String.Empty);
+ temp.Add(CJKMonthSuff, String.Empty);
+ temp.Add(CJKDaySuff, String.Empty);
+ temp.Add(KoreanYearSuff, String.Empty);
+ temp.Add(KoreanMonthSuff, String.Empty);
+ temp.Add(KoreanDaySuff, String.Empty);
+ temp.Add(KoreanHourSuff, String.Empty);
+ temp.Add(KoreanMinuteSuff, String.Empty);
+ temp.Add(KoreanSecondSuff, String.Empty);
+ temp.Add(CJKHourSuff, String.Empty);
+ temp.Add(ChineseHourSuff, String.Empty);
+ temp.Add(CJKMinuteSuff, String.Empty);
+ temp.Add(CJKSecondSuff, String.Empty);
+
+ s_knownWords = temp;
+ }
+ return (s_knownWords);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Parameters:
+ // pattern: The pattern to be scanned.
+ // currentIndex: the current index to start the scan.
+ //
+ // Returns:
+ // Return the index with the first character that is a letter, which will
+ // be the start of a date word.
+ // Note that the index can be pattern.Length if we reach the end of the string.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static int SkipWhiteSpacesAndNonLetter(String pattern, int currentIndex)
+ {
+ while (currentIndex < pattern.Length)
+ {
+ char ch = pattern[currentIndex];
+ if (ch == '\\')
+ {
+ // Escaped character. Look ahead one character.
+ currentIndex++;
+ if (currentIndex < pattern.Length)
+ {
+ ch = pattern[currentIndex];
+ if (ch == '\'')
+ {
+ // Skip the leading single quote. We will
+ // stop at the first letter.
+ continue;
+ }
+ // Fall thru to check if this is a letter.
+ } else
+ {
+ // End of string
+ break;
+ }
+ }
+ if (Char.IsLetter(ch) || ch == '\'' || ch == '.')
+ {
+ break;
+ }
+ // Skip the current char since it is not a letter.
+ currentIndex++;
+ }
+ return (currentIndex);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // A helper to add the found date word or month postfix into ArrayList for date words.
+ //
+ // Parameters:
+ // formatPostfix: What kind of postfix this is.
+ // Possible values:
+ // null: This is a regular date word
+ // "MMMM": month postfix
+ // word: The date word or postfix to be added.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal void AddDateWordOrPostfix(String formatPostfix, String str)
+ {
+ if (str.Length > 0)
+ {
+ // Some cultures use . like an abbreviation
+ if (str.Equals("."))
+ {
+ AddIgnorableSymbols(".");
+ return;
+ }
+ String words;
+ if (KnownWords.TryGetValue(str, out words) == false)
+ {
+ if (m_dateWords == null)
+ {
+ m_dateWords = new List<String>();
+ }
+ if (formatPostfix == "MMMM")
+ {
+ // Add the word into the ArrayList as "\xfffe" + real month postfix.
+ String temp = MonthPostfixChar + str;
+ if (!m_dateWords.Contains(temp))
+ {
+ m_dateWords.Add(temp);
+ }
+ } else
+ {
+ if (!m_dateWords.Contains(str))
+ {
+ m_dateWords.Add(str);
+ }
+ if (str[str.Length - 1] == '.')
+ {
+ // Old version ignore the trialing dot in the date words. Support this as well.
+ String strWithoutDot = str.Substring(0, str.Length - 1);
+ if (!m_dateWords.Contains(strWithoutDot))
+ {
+ m_dateWords.Add(strWithoutDot);
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the pattern from the specified index and add the date word/postfix
+ // when appropriate.
+ //
+ // Parameters:
+ // pattern: The pattern to be scanned.
+ // index: The starting index to be scanned.
+ // formatPostfix: The kind of postfix to be scanned.
+ // Possible values:
+ // null: This is a regular date word
+ // "MMMM": month postfix
+ //
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal int AddDateWords(String pattern, int index, String formatPostfix)
+ {
+ // Skip any whitespaces so we will start from a letter.
+ int newIndex = SkipWhiteSpacesAndNonLetter(pattern, index);
+ if (newIndex != index && formatPostfix != null)
+ {
+ // There are whitespaces. This will not be a postfix.
+ formatPostfix = null;
+ }
+ index = newIndex;
+
+ // This is the first char added into dateWord.
+ // Skip all non-letter character. We will add the first letter into DateWord.
+ StringBuilder dateWord = new StringBuilder();
+ // We assume that date words should start with a letter.
+ // Skip anything until we see a letter.
+
+ while (index < pattern.Length)
+ {
+ char ch = pattern[index];
+ if (ch == '\'')
+ {
+ // We have seen the end of quote. Add the word if we do not see it before,
+ // and break the while loop.
+ AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
+ index++;
+ break;
+ } else if (ch == '\\')
+ {
+ //
+ // Escaped character. Look ahead one character
+ //
+
+ // Skip escaped backslash.
+ index++;
+ if (index < pattern.Length)
+ {
+ dateWord.Append(pattern[index]);
+ index++;
+ }
+ } else if (Char.IsWhiteSpace(ch))
+ {
+ // Found a whitespace. We have to add the current date word/postfix.
+ AddDateWordOrPostfix(formatPostfix, dateWord.ToString());
+ if (formatPostfix != null)
+ {
+ // Done with postfix. The rest will be regular date word.
+ formatPostfix = null;
+ }
+ // Reset the dateWord.
+ dateWord.Length = 0;
+ index++;
+ } else
+ {
+ dateWord.Append(ch);
+ index++;
+ }
+ }
+ return (index);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // A simple helper to find the repeat count for a specified char.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static int ScanRepeatChar(String pattern, char ch, int index, out int count)
+ {
+ count = 1;
+ while (++index < pattern.Length && pattern[index] == ch) {
+ count++;
+ }
+ // Return the updated position.
+ return (index);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Add the text that is a date separator but is treated like ignroable symbol.
+ // E.g.
+ // hu-HU has:
+ // shrot date pattern: yyyy. MM. dd.;yyyy-MM-dd;yy-MM-dd
+ // long date pattern: yyyy. MMMM d.
+ // Here, "." is the date separator (derived from short date pattern). However,
+ // "." also appear at the end of long date pattern. In this case, we just
+ // "." as ignorable symbol so that the DateTime.Parse() state machine will not
+ // treat the additional date separator at the end of y,m,d pattern as an error
+ // condition.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal void AddIgnorableSymbols(String text)
+ {
+ if (m_dateWords == null)
+ {
+ // Create the date word array.
+ m_dateWords = new List<String>();
+ }
+ // Add the ingorable symbol into the ArrayList.
+ String temp = IgnorableSymbolChar + text;
+ if (!m_dateWords.Contains(temp))
+ {
+ m_dateWords.Add(temp);
+ }
+ }
+
+
+ //
+ // Flag used to trace the date patterns (yy/yyyyy/M/MM/MMM/MMM/d/dd) that we have seen.
+ //
+ enum FoundDatePattern
+ {
+ None = 0x0000,
+ FoundYearPatternFlag = 0x0001,
+ FoundMonthPatternFlag = 0x0002,
+ FoundDayPatternFlag = 0x0004,
+ FoundYMDPatternFlag = 0x0007, // FoundYearPatternFlag | FoundMonthPatternFlag | FoundDayPatternFlag;
+ }
+
+ // Check if we have found all of the year/month/day pattern.
+ FoundDatePattern m_ymdFlags = FoundDatePattern.None;
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Given a date format pattern, scan for date word or postfix.
+ //
+ // A date word should be always put in a single quoted string. And it will
+ // start from a letter, so whitespace and symbols will be ignored before
+ // the first letter.
+ //
+ // Examples of date word:
+ // 'de' in es-SP: dddd, dd' de 'MMMM' de 'yyyy
+ // "\x0443." in bg-BG: dd.M.yyyy '\x0433.'
+ //
+ // Example of postfix:
+ // month postfix:
+ // "ta" in fi-FI: d. MMMM'ta 'yyyy
+ // Currently, only month postfix is supported.
+ //
+ // Usage:
+ // Always call this with Framework-style pattern, instead of Windows style pattern.
+ // Windows style pattern uses '' for single quote, while .NET uses \'
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal void ScanDateWord(String pattern)
+ {
+
+ // Check if we have found all of the year/month/day pattern.
+ m_ymdFlags = FoundDatePattern.None;
+
+ int i = 0;
+ while (i < pattern.Length)
+ {
+ char ch = pattern[i];
+ int chCount;
+
+ switch (ch)
+ {
+ case '\'':
+ // Find a beginning quote. Search until the end quote.
+ i = AddDateWords(pattern, i+1, null);
+ break;
+ case 'M':
+ i = ScanRepeatChar(pattern, 'M', i, out chCount);
+ if (chCount >= 4)
+ {
+ if (i < pattern.Length && pattern[i] == '\'')
+ {
+ i = AddDateWords(pattern, i+1, "MMMM");
+ }
+ }
+ m_ymdFlags |= FoundDatePattern.FoundMonthPatternFlag;
+ break;
+ case 'y':
+ i = ScanRepeatChar(pattern, 'y', i, out chCount);
+ m_ymdFlags |= FoundDatePattern.FoundYearPatternFlag;
+ break;
+ case 'd':
+ i = ScanRepeatChar(pattern, 'd', i, out chCount);
+ if (chCount <= 2)
+ {
+ // Only count "d" & "dd".
+ // ddd, dddd are day names. Do not count them.
+ m_ymdFlags |= FoundDatePattern.FoundDayPatternFlag;
+ }
+ break;
+ case '\\':
+ // Found a escaped char not in a quoted string. Skip the current backslash
+ // and its next character.
+ i += 2;
+ break;
+ case '.':
+ if (m_ymdFlags == FoundDatePattern.FoundYMDPatternFlag)
+ {
+ // If we find a dot immediately after the we have seen all of the y, m, d pattern.
+ // treat it as a ignroable symbol. Check for comments in AddIgnorableSymbols for
+ // more details.
+ AddIgnorableSymbols(".");
+ m_ymdFlags = FoundDatePattern.None;
+ }
+ i++;
+ break;
+ default:
+ if (m_ymdFlags == FoundDatePattern.FoundYMDPatternFlag && !Char.IsWhiteSpace(ch))
+ {
+ // We are not seeing "." after YMD. Clear the flag.
+ m_ymdFlags = FoundDatePattern.None;
+ }
+ // We are not in quote. Skip the current character.
+ i++;
+ break;
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Given a DTFI, get all of the date words from date patterns and time patterns.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal String[] GetDateWordsOfDTFI(DateTimeFormatInfo dtfi) {
+ // Enumarate all LongDatePatterns, and get the DateWords and scan for month postfix.
+ String[] datePatterns = dtfi.GetAllDateTimePatterns('D');
+ int i;
+
+ // Scan the long date patterns
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the short date patterns
+ datePatterns = dtfi.GetAllDateTimePatterns('d');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+ // Scan the YearMonth patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('y');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the month/day pattern
+ ScanDateWord(dtfi.MonthDayPattern);
+
+ // Scan the long time patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('T');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ // Scan the short time patterns.
+ datePatterns = dtfi.GetAllDateTimePatterns('t');
+ for (i = 0; i < datePatterns.Length; i++)
+ {
+ ScanDateWord(datePatterns[i]);
+ }
+
+ String[] result = null;
+ if (m_dateWords != null && m_dateWords.Count > 0)
+ {
+ result = new String[m_dateWords.Count];
+ for (i = 0; i < m_dateWords.Count; i++)
+ {
+ result[i] = m_dateWords[i];
+ }
+ }
+ return (result);
+ }
+
+#if ADDITIONAL_DTFI_SCANNER_METHODS
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Reset the date word ArrayList
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal void Reset()
+ {
+ m_dateWords.RemoveRange(0, m_dateWords.Count);
+ }
+#endif
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the month names to see if genitive month names are used, and return
+ // the format flag.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagGenitiveMonth(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ {
+ // If we have different names in regular and genitive month names, use genitive month flag.
+ return ((!EqualStringArrays(monthNames, genitveMonthNames) || !EqualStringArrays(abbrevMonthNames, genetiveAbbrevMonthNames))
+ ? FORMATFLAGS.UseGenitiveMonth: 0);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the month names to see if spaces are used or start with a digit, and return the format flag
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInMonthNames(String[] monthNames, String[] genitveMonthNames, String[] abbrevMonthNames, String[] genetiveAbbrevMonthNames)
+ {
+ FORMATFLAGS formatFlags = 0;
+ formatFlags |= (ArrayElementsBeginWithDigit(monthNames) ||
+ ArrayElementsBeginWithDigit(genitveMonthNames) ||
+ ArrayElementsBeginWithDigit(abbrevMonthNames) ||
+ ArrayElementsBeginWithDigit(genetiveAbbrevMonthNames)
+ ? FORMATFLAGS.UseDigitPrefixInTokens : 0);
+
+ formatFlags |= (ArrayElementsHaveSpace(monthNames) ||
+ ArrayElementsHaveSpace(genitveMonthNames) ||
+ ArrayElementsHaveSpace(abbrevMonthNames) ||
+ ArrayElementsHaveSpace(genetiveAbbrevMonthNames)
+ ? FORMATFLAGS.UseSpacesInMonthNames : 0);
+ return (formatFlags);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Scan the day names and set the correct format flag.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseSpaceInDayNames(String[] dayNames, String[] abbrevDayNames)
+ {
+ return ((ArrayElementsHaveSpace(dayNames) ||
+ ArrayElementsHaveSpace(abbrevDayNames))
+ ? FORMATFLAGS.UseSpacesInDayNames : 0);
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Check the calendar to see if it is HebrewCalendar and set the Hebrew format flag if necessary.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ internal static FORMATFLAGS GetFormatFlagUseHebrewCalendar(int calID)
+ {
+ return (calID == (int)CalendarId.HEBREW ?
+ FORMATFLAGS.UseHebrewParsing | FORMATFLAGS.UseLeapYearMonth : 0);
+ }
+
+
+ //-----------------------------------------------------------------------------
+ // EqualStringArrays
+ // compares two string arrays and return true if all elements of the first
+ // array equals to all elmentsof the second array.
+ // otherwise it returns false.
+ //-----------------------------------------------------------------------------
+
+ private static bool EqualStringArrays(string [] array1, string [] array2)
+ {
+ // Shortcut if they're the same array
+ if (array1 == array2)
+ {
+ return true;
+ }
+
+ // This is effectively impossible
+ if (array1.Length != array2.Length)
+ {
+ return false;
+ }
+
+ // Check each string
+ for (int i=0; i<array1.Length; i++)
+ {
+ if (!array1[i].Equals(array2[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ //-----------------------------------------------------------------------------
+ // ArrayElementsHaveSpace
+ // It checks all input array elements if any of them has space character
+ // returns true if found space character in one of the array elements.
+ // otherwise returns false.
+ //-----------------------------------------------------------------------------
+
+ private static bool ArrayElementsHaveSpace(string [] array)
+ {
+
+ for (int i=0; i<array.Length; i++)
+ {
+ // it is faster to check for space character manually instead of calling IndexOf
+ // so we don't have to go to native code side.
+ for (int j=0; j<array[i].Length; j++)
+ {
+ if ( Char.IsWhiteSpace(array[i][j]) )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Check if any element of the array start with a digit.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ private static bool ArrayElementsBeginWithDigit(string [] array)
+ {
+
+ for (int i=0; i<array.Length; i++)
+ {
+ // it is faster to check for space character manually instead of calling IndexOf
+ // so we don't have to go to native code side.
+ if (array[i].Length > 0 &&
+ array[i][0] >= '0' && array[i][0] <= '9')
+ {
+ int index = 1;
+ while (index < array[i].Length && array[i][index] >= '0' && array[i][index] <= '9')
+ {
+ // Skip other digits.
+ index++;
+ }
+ if (index == array[i].Length)
+ {
+ return (false);
+ }
+
+ if (index == array[i].Length - 1)
+ {
+ // Skip known CJK month suffix.
+ // CJK uses month name like "1\x6708", since \x6708 is a known month suffix,
+ // we don't need the UseDigitPrefixInTokens since it is slower.
+ switch (array[i][index])
+ {
+ case '\x6708': // CJKMonthSuff
+ case '\xc6d4': // KoreanMonthSuff
+ return (false);
+ }
+ }
+
+ if (index == array[i].Length - 4)
+ {
+ // Skip known CJK month suffix.
+ // Starting with Windows 8, the CJK months for some cultures looks like: "1' \x6708'"
+ // instead of just "1\x6708"
+ if(array[i][index] == '\'' && array[i][index + 1] == ' ' &&
+ array[i][index + 2] == '\x6708' && array[i][index + 3] == '\'')
+ {
+ return (false);
+ }
+
+ }
+ return (true);
+ }
+ }
+
+ return false;
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/DateTimeParse.cs b/src/mscorlib/src/System/Globalization/DateTimeParse.cs
new file mode 100644
index 0000000000..8de3242f30
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DateTimeParse.cs
@@ -0,0 +1,5069 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class is called by DateTime to parse a date/time string.
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System {
+ using System;
+ using System.Text;
+ using System.Globalization;
+ using System.Threading;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////
+
+ //This class contains only static members
+
+ internal static
+ class DateTimeParse {
+
+ internal const Int32 MaxDateTimeNumberDigits = 8;
+
+ internal delegate bool MatchNumberDelegate(ref __DTString str, int digitLen, out int result);
+
+ internal static MatchNumberDelegate m_hebrewNumberParser = new MatchNumberDelegate(DateTimeParse.MatchHebrewDigits);
+
+#if !FEATURE_CORECLR
+ [SecuritySafeCritical]
+ internal static bool GetAmPmParseFlag()
+ {
+ return DateTime.EnableAmPmParseAdjustment();
+ }
+
+ internal static bool enableAmPmParseAdjustment = GetAmPmParseFlag();
+#endif
+
+ internal static DateTime ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ result.Init();
+ if (TryParseExact(s, format, dtfi, style, ref result)) {
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+ internal static DateTime ParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ offset = TimeSpan.Zero;
+ result.Init();
+ result.flags |= ParseFlags.CaptureOffset;
+ if (TryParseExact(s, format, dtfi, style, ref result)) {
+ offset = result.timeZoneOffset;
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+ internal static bool TryParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result) {
+ result = DateTime.MinValue;
+ DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
+ resultData.Init();
+ if (TryParseExact(s, format, dtfi, style, ref resultData)) {
+ result = resultData.parsedDate;
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool TryParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset) {
+ result = DateTime.MinValue;
+ offset = TimeSpan.Zero;
+ DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
+ resultData.Init();
+ resultData.flags |= ParseFlags.CaptureOffset;
+ if (TryParseExact(s, format, dtfi, style, ref resultData)) {
+ result = resultData.parsedDate;
+ offset = resultData.timeZoneOffset;
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool TryParseExact(String s, String format, DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result) {
+ if (s == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
+ return false;
+ }
+ if (format == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "format");
+ return false;
+ }
+ if (s.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (format.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+
+ Contract.Assert(dtfi != null, "dtfi == null");
+
+ return DoStrictParse(s, format, style, dtfi, ref result);
+ }
+
+ internal static DateTime ParseExactMultiple(String s, String[] formats,
+ DateTimeFormatInfo dtfi, DateTimeStyles style) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ result.Init();
+ if (TryParseExactMultiple(s, formats, dtfi, style, ref result)) {
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+
+ internal static DateTime ParseExactMultiple(String s, String[] formats,
+ DateTimeFormatInfo dtfi, DateTimeStyles style, out TimeSpan offset) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ offset = TimeSpan.Zero;
+ result.Init();
+ result.flags |= ParseFlags.CaptureOffset;
+ if (TryParseExactMultiple(s, formats, dtfi, style, ref result)) {
+ offset = result.timeZoneOffset;
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+ internal static bool TryParseExactMultiple(String s, String[] formats,
+ DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result, out TimeSpan offset) {
+ result = DateTime.MinValue;
+ offset = TimeSpan.Zero;
+ DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
+ resultData.Init();
+ resultData.flags |= ParseFlags.CaptureOffset;
+ if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData)) {
+ result = resultData.parsedDate;
+ offset = resultData.timeZoneOffset;
+ return true;
+ }
+ return false;
+ }
+
+
+ internal static bool TryParseExactMultiple(String s, String[] formats,
+ DateTimeFormatInfo dtfi, DateTimeStyles style, out DateTime result) {
+ result = DateTime.MinValue;
+ DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
+ resultData.Init();
+ if (TryParseExactMultiple(s, formats, dtfi, style, ref resultData)) {
+ result = resultData.parsedDate;
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool TryParseExactMultiple(String s, String[] formats,
+ DateTimeFormatInfo dtfi, DateTimeStyles style, ref DateTimeResult result) {
+ if (s == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
+ return false;
+ }
+ if (formats == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "formats");
+ return false;
+ }
+
+ if (s.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (formats.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+
+ Contract.Assert(dtfi != null, "dtfi == null");
+
+ //
+ // Do a loop through the provided formats and see if we can parse succesfully in
+ // one of the formats.
+ //
+ for (int i = 0; i < formats.Length; i++) {
+ if (formats[i] == null || formats[i].Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+ // Create a new result each time to ensure the runs are independent. Carry through
+ // flags from the caller and return the result.
+ DateTimeResult innerResult = new DateTimeResult(); // The buffer to store the parsing result.
+ innerResult.Init();
+ innerResult.flags = result.flags;
+ if (TryParseExact(s, formats[i], dtfi, style, ref innerResult)) {
+ result.parsedDate = innerResult.parsedDate;
+ result.timeZoneOffset = innerResult.timeZoneOffset;
+ return (true);
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // Date Token Types
+ //
+ // Following is the set of tokens that can be generated from a date
+ // string. Notice that the legal set of trailing separators have been
+ // folded in with the date number, and month name tokens. This set
+ // of tokens is chosen to reduce the number of date parse states.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum DTT: int {
+
+ End = 0, // '\0'
+ NumEnd = 1, // Num[ ]*[\0]
+ NumAmpm = 2, // Num[ ]+AmPm
+ NumSpace = 3, // Num[ ]+^[Dsep|Tsep|'0\']
+ NumDatesep = 4, // Num[ ]*Dsep
+ NumTimesep = 5, // Num[ ]*Tsep
+ MonthEnd = 6, // Month[ ]*'\0'
+ MonthSpace = 7, // Month[ ]+^[Dsep|Tsep|'\0']
+ MonthDatesep = 8, // Month[ ]*Dsep
+ NumDatesuff = 9, // Month[ ]*DSuff
+ NumTimesuff = 10, // Month[ ]*TSuff
+ DayOfWeek = 11, // Day of week name
+ YearSpace = 12, // Year+^[Dsep|Tsep|'0\']
+ YearDateSep = 13, // Year+Dsep
+ YearEnd = 14, // Year+['\0']
+ TimeZone = 15, // timezone name
+ Era = 16, // era name
+ NumUTCTimeMark = 17, // Num + 'Z'
+ // When you add a new token which will be in the
+ // state table, add it after NumLocalTimeMark.
+ Unk = 18, // unknown
+ NumLocalTimeMark = 19, // Num + 'T'
+ Max = 20, // marker
+ }
+
+ internal enum TM {
+ NotSet = -1,
+ AM = 0,
+ PM = 1,
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // DateTime parsing state enumeration (DS.*)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum DS {
+ BEGIN = 0,
+ N = 1, // have one number
+ NN = 2, // have two numbers
+
+ // The following are known to be part of a date
+
+ D_Nd = 3, // date string: have number followed by date separator
+ D_NN = 4, // date string: have two numbers
+ D_NNd = 5, // date string: have two numbers followed by date separator
+
+ D_M = 6, // date string: have a month
+ D_MN = 7, // date string: have a month and a number
+ D_NM = 8, // date string: have a number and a month
+ D_MNd = 9, // date string: have a month and number followed by date separator
+ D_NDS = 10, // date string: have one number followed a date suffix.
+
+ D_Y = 11, // date string: have a year.
+ D_YN = 12, // date string: have a year and a number
+ D_YNd = 13, // date string: have a year and a number and a date separator
+ D_YM = 14, // date string: have a year and a month
+ D_YMd = 15, // date string: have a year and a month and a date separator
+ D_S = 16, // have numbers followed by a date suffix.
+ T_S = 17, // have numbers followed by a time suffix.
+
+ // The following are known to be part of a time
+
+ T_Nt = 18, // have num followed by time separator
+ T_NNt = 19, // have two numbers followed by time separator
+
+
+ ERROR = 20,
+
+ // The following are terminal states. These all have an action
+ // associated with them; and transition back to BEGIN.
+
+ DX_NN = 21, // day from two numbers
+ DX_NNN = 22, // day from three numbers
+ DX_MN = 23, // day from month and one number
+ DX_NM = 24, // day from month and one number
+ DX_MNN = 25, // day from month and two numbers
+ DX_DS = 26, // a set of date suffixed numbers.
+ DX_DSN = 27, // day from date suffixes and one number.
+ DX_NDS = 28, // day from one number and date suffixes .
+ DX_NNDS = 29, // day from one number and date suffixes .
+
+ DX_YNN = 30, // date string: have a year and two number
+ DX_YMN = 31, // date string: have a year, a month, and a number.
+ DX_YN = 32, // date string: have a year and one number
+ DX_YM = 33, // date string: have a year, a month.
+ TX_N = 34, // time from one number (must have ampm)
+ TX_NN = 35, // time from two numbers
+ TX_NNN = 36, // time from three numbers
+ TX_TS = 37, // a set of time suffixed numbers.
+ DX_NNY = 38,
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // NOTE: The following state machine table is dependent on the order of the
+ // DS and DTT enumerations.
+ //
+ // For each non terminal state, the following table defines the next state
+ // for each given date token type.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+// End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCTimeMark
+private static DS[][] dateParsingStates = {
+// DS.BEGIN // DS.BEGIN
+new DS[] { DS.BEGIN, DS.ERROR, DS.TX_N, DS.N, DS.D_Nd, DS.T_Nt, DS.ERROR, DS.D_M, DS.D_M, DS.D_S, DS.T_S, DS.BEGIN, DS.D_Y, DS.D_Y, DS.ERROR, DS.BEGIN, DS.BEGIN, DS.ERROR},
+
+// DS.N // DS.N
+new DS[] { DS.ERROR, DS.DX_NN, DS.ERROR, DS.NN, DS.D_NNd, DS.ERROR, DS.DX_NM, DS.D_NM, DS.D_MNd, DS.D_NDS, DS.ERROR, DS.N, DS.D_YN, DS.D_YNd, DS.DX_YN, DS.N, DS.N, DS.ERROR},
+
+// DS.NN // DS.NN
+new DS[] { DS.DX_NN, DS.DX_NNN, DS.TX_N, DS.DX_NNN, DS.ERROR, DS.T_Nt, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.ERROR, DS.T_S, DS.NN, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.NN, DS.NN, DS.ERROR},
+
+// DS.D_Nd // DS.D_Nd
+new DS[] { DS.ERROR, DS.DX_NN, DS.ERROR, DS.D_NN, DS.D_NNd, DS.ERROR, DS.DX_NM, DS.D_MN, DS.D_MNd, DS.ERROR, DS.ERROR, DS.D_Nd, DS.D_YN, DS.D_YNd, DS.DX_YN, DS.ERROR, DS.D_Nd, DS.ERROR},
+
+// DS.D_NN // DS.D_NN
+new DS[] { DS.DX_NN, DS.DX_NNN, DS.TX_N, DS.DX_NNN, DS.ERROR, DS.T_Nt, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_NN, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.ERROR, DS.D_NN, DS.ERROR},
+
+// DS.D_NNd // DS.D_NNd
+new DS[] { DS.ERROR, DS.DX_NNN, DS.DX_NNN, DS.DX_NNN, DS.ERROR, DS.ERROR, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.DX_DS, DS.ERROR, DS.D_NNd, DS.DX_NNY, DS.ERROR, DS.DX_NNY, DS.ERROR, DS.D_NNd, DS.ERROR},
+
+// DS.D_M // DS.D_M
+new DS[] { DS.ERROR, DS.DX_MN, DS.ERROR, DS.D_MN, DS.D_MNd, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_M, DS.D_YM, DS.D_YMd, DS.DX_YM, DS.ERROR, DS.D_M, DS.ERROR},
+
+// DS.D_MN // DS.D_MN
+new DS[] { DS.DX_MN, DS.DX_MNN, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_MN, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_MN, DS.ERROR},
+
+// DS.D_NM // DS.D_NM
+new DS[] { DS.DX_NM, DS.DX_MNN, DS.DX_MNN, DS.DX_MNN, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.DX_DS, DS.T_S, DS.D_NM, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_NM, DS.ERROR},
+
+// DS.D_MNd // DS.D_MNd
+new DS[] { DS.ERROR, DS.DX_MNN, DS.ERROR, DS.DX_MNN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_MNd, DS.DX_YMN, DS.ERROR, DS.DX_YMN, DS.ERROR, DS.D_MNd, DS.ERROR},
+
+// DS.D_NDS, // DS.D_NDS,
+new DS[] { DS.DX_NDS,DS.DX_NNDS, DS.DX_NNDS, DS.DX_NNDS, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_NDS, DS.T_S, DS.D_NDS, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_NDS, DS.ERROR},
+
+// DS.D_Y // DS.D_Y
+new DS[] { DS.ERROR, DS.DX_YN, DS.ERROR, DS.D_YN, DS.D_YNd, DS.ERROR, DS.DX_YM, DS.D_YM, DS.D_YMd, DS.D_YM, DS.ERROR, DS.D_Y, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_Y, DS.ERROR},
+
+// DS.D_YN // DS.D_YN
+new DS[] { DS.DX_YN, DS.DX_YNN, DS.DX_YNN, DS.DX_YNN, DS.ERROR, DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR},
+
+// DS.D_YNd // DS.D_YNd
+new DS[] { DS.ERROR, DS.DX_YNN, DS.DX_YNN, DS.DX_YNN, DS.ERROR, DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YN, DS.ERROR},
+
+// DS.D_YM // DS.D_YM
+new DS[] { DS.DX_YM, DS.DX_YMN, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR},
+
+// DS.D_YMd // DS.D_YMd
+new DS[] { DS.ERROR, DS.DX_YMN, DS.DX_YMN, DS.DX_YMN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_YM, DS.ERROR},
+
+// DS.D_S // DS.D_S
+new DS[] { DS.DX_DS, DS.DX_DSN, DS.TX_N, DS.T_Nt, DS.ERROR, DS.T_Nt, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.T_S, DS.D_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.ERROR},
+
+// DS.T_S // DS.T_S
+new DS[] { DS.TX_TS, DS.TX_TS, DS.TX_TS, DS.T_Nt, DS.D_Nd, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.D_S, DS.T_S, DS.T_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_S, DS.T_S, DS.ERROR},
+
+// DS.T_Nt // DS.T_Nt
+new DS[] { DS.ERROR, DS.TX_NN, DS.TX_NN, DS.TX_NN, DS.ERROR, DS.T_NNt, DS.DX_NM, DS.D_NM, DS.ERROR, DS.ERROR, DS.T_S, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_Nt, DS.T_Nt, DS.TX_NN},
+
+// DS.T_NNt // DS.T_NNt
+new DS[] { DS.ERROR, DS.TX_NNN, DS.TX_NNN, DS.TX_NNN, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_S, DS.T_NNt, DS.ERROR, DS.ERROR, DS.ERROR, DS.T_NNt, DS.T_NNt, DS.TX_NNN},
+
+};
+// End NumEnd NumAmPm NumSpace NumDaySep NumTimesep MonthEnd MonthSpace MonthDSep NumDateSuff NumTimeSuff DayOfWeek YearSpace YearDateSep YearEnd TimeZone Era UTCMark
+
+ internal const String GMTName = "GMT";
+ internal const String ZuluName = "Z";
+
+ //
+ // Search from the index of str at str.Index to see if the target string exists in the str.
+ //
+ private static bool MatchWord(ref __DTString str, String target)
+ {
+ int length = target.Length;
+ if (length > (str.Value.Length - str.Index)) {
+ return false;
+ }
+
+ if (str.CompareInfo.Compare(str.Value, str.Index, length,
+ target, 0, length, CompareOptions.IgnoreCase)!=0) {
+ return (false);
+ }
+
+ int nextCharIndex = str.Index + target.Length;
+
+ if (nextCharIndex < str.Value.Length) {
+ char nextCh = str.Value[nextCharIndex];
+ if (Char.IsLetter(nextCh)) {
+ return (false);
+ }
+ }
+ str.Index = nextCharIndex;
+ if (str.Index < str.len) {
+ str.m_current = str.Value[str.Index];
+ }
+
+ return (true);
+ }
+
+
+ //
+ // Check the word at the current index to see if it matches GMT name or Zulu name.
+ //
+ private static bool GetTimeZoneName(ref __DTString str)
+ {
+ if (MatchWord(ref str, GMTName)) {
+ return (true);
+ }
+
+ if (MatchWord(ref str, ZuluName)) {
+ return (true);
+ }
+
+ return (false);
+ }
+
+ internal static bool IsDigit(char ch) {
+ return (ch >= '0' && ch <= '9');
+ }
+
+
+ /*=================================ParseFraction==========================
+ **Action: Starting at the str.Index, which should be a decimal symbol.
+ ** if the current character is a digit, parse the remaining
+ ** numbers as fraction. For example, if the sub-string starting at str.Index is "123", then
+ ** the method will return 0.123
+ **Returns: The fraction number.
+ **Arguments:
+ ** str the parsing string
+ **Exceptions:
+ ============================================================================*/
+
+ private static bool ParseFraction(ref __DTString str, out double result) {
+ result = 0;
+ double decimalBase = 0.1;
+ int digits = 0;
+ char ch;
+ while (str.GetNext()
+ && IsDigit(ch = str.m_current)) {
+ result += (ch - '0') * decimalBase;
+ decimalBase *= 0.1;
+ digits++;
+ }
+ return (digits > 0);
+ }
+
+ /*=================================ParseTimeZone==========================
+ **Action: Parse the timezone offset in the following format:
+ ** "+8", "+08", "+0800", "+0800"
+ ** This method is used by DateTime.Parse().
+ **Returns: The TimeZone offset.
+ **Arguments:
+ ** str the parsing string
+ **Exceptions:
+ ** FormatException if invalid timezone format is found.
+ ============================================================================*/
+
+ private static bool ParseTimeZone(ref __DTString str, ref TimeSpan result) {
+ // The hour/minute offset for timezone.
+ int hourOffset = 0;
+ int minuteOffset = 0;
+ DTSubString sub;
+
+ // Consume the +/- character that has already been read
+ sub = str.GetSubString();
+ if (sub.length != 1) {
+ return false;
+ }
+ char offsetChar = sub[0];
+ if (offsetChar != '+' && offsetChar != '-') {
+ return false;
+ }
+ str.ConsumeSubString(sub);
+
+ sub = str.GetSubString();
+ if (sub.type != DTSubStringType.Number) {
+ return false;
+ }
+ int value = sub.value;
+ int length = sub.length;
+ if (length == 1 || length == 2) {
+ // Parsing "+8" or "+08"
+ hourOffset = value;
+ str.ConsumeSubString(sub);
+ // See if we have minutes
+ sub = str.GetSubString();
+ if (sub.length == 1 && sub[0] == ':') {
+ // Parsing "+8:00" or "+08:00"
+ str.ConsumeSubString(sub);
+ sub = str.GetSubString();
+ if (sub.type != DTSubStringType.Number || sub.length < 1 || sub.length > 2) {
+ return false;
+ }
+ minuteOffset = sub.value;
+ str.ConsumeSubString(sub);
+ }
+ }
+ else if (length == 3 || length == 4) {
+ // Parsing "+800" or "+0800"
+ hourOffset = value / 100;
+ minuteOffset = value % 100;
+ str.ConsumeSubString(sub);
+ }
+ else {
+ // Wrong number of digits
+ return false;
+ }
+ Contract.Assert(hourOffset >= 0 && hourOffset <= 99, "hourOffset >= 0 && hourOffset <= 99");
+ Contract.Assert(minuteOffset >= 0 && minuteOffset <= 99, "minuteOffset >= 0 && minuteOffset <= 99");
+ if (minuteOffset < 0 || minuteOffset >= 60) {
+ return false;
+ }
+
+ result = new TimeSpan(hourOffset, minuteOffset, 0);
+ if (offsetChar == '-') {
+ result = result.Negate();
+ }
+ return true;
+ }
+
+ // This is the helper function to handle timezone in string in the format like +/-0800
+ private static bool HandleTimeZone(ref __DTString str, ref DateTimeResult result)
+ {
+ if ((str.Index < str.len - 1)) {
+ char nextCh = str.Value[str.Index];
+ // Skip whitespace, but don't update the index unless we find a time zone marker
+ int whitespaceCount = 0;
+ while (Char.IsWhiteSpace(nextCh) && str.Index + whitespaceCount < str.len - 1) {
+ whitespaceCount++;
+ nextCh = str.Value[str.Index + whitespaceCount];
+ }
+ if (nextCh == '+' || nextCh == '-') {
+ str.Index += whitespaceCount;
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0) {
+ // Should not have two timezone offsets.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ result.flags |= ParseFlags.TimeZoneUsed;
+ if (!ParseTimeZone(ref str, ref result.timeZoneOffset)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ //
+ // This is the lexer. Check the character at the current index, and put the found token in dtok and
+ // some raw date/time information in raw.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Boolean Lex(DS dps, ref __DTString str, ref DateTimeToken dtok, ref DateTimeRawInfo raw, ref DateTimeResult result, ref DateTimeFormatInfo dtfi, DateTimeStyles styles)
+ {
+
+ TokenType tokenType;
+ int tokenValue;
+ int indexBeforeSeparator;
+ char charBeforeSeparator;
+
+ TokenType sep;
+ dtok.dtt = DTT.Unk; // Assume the token is unkown.
+
+ str.GetRegularToken(out tokenType, out tokenValue, dtfi);
+
+#if _LOGGING
+ // Builds with _LOGGING defined (x86dbg, amd64chk, etc) support tracing
+ // Set the following internal-only/unsupported environment variables to enable DateTime tracing to the console:
+ //
+ // COMPlus_LogEnable=1
+ // COMPlus_LogToConsole=1
+ // COMPlus_LogLevel=9
+ // COMPlus_ManagedLogFacility=0x00001000
+ if (_tracingEnabled) {
+ BCLDebug.Trace("DATETIME", "[DATETIME] Lex({0})\tpos:{1}({2}), {3}, DS.{4}", Hex(str.Value),
+ str.Index, Hex(str.m_current), tokenType, dps);
+ }
+#endif // _LOGGING
+
+ // Look at the regular token.
+ switch (tokenType) {
+ case TokenType.NumberToken:
+ case TokenType.YearNumberToken:
+ if (raw.numCount == 3 || tokenValue == -1) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0010", dps);
+ return false;
+ }
+ //
+ // This is a digit.
+ //
+ // If the previous parsing state is DS.T_NNt (like 12:01), and we got another number,
+ // so we will have a terminal state DS.TX_NNN (like 12:01:02).
+ // If the previous parsing state is DS.T_Nt (like 12:), and we got another number,
+ // so we will have a terminal state DS.TX_NN (like 12:01).
+ //
+ // Look ahead to see if the following character is a decimal point or timezone offset.
+ // This enables us to parse time in the forms of:
+ // "11:22:33.1234" or "11:22:33-08".
+ if (dps == DS.T_NNt) {
+ if ((str.Index < str.len - 1)) {
+ char nextCh = str.Value[str.Index];
+ if (nextCh == '.') {
+ // While ParseFraction can fail, it just means that there were no digits after
+ // the dot. In this case ParseFraction just removes the dot. This is actually
+ // valid for cultures like Albanian, that join the time marker to the time with
+ // with a dot: e.g. "9:03.MD"
+ ParseFraction(ref str, out raw.fraction);
+ }
+ }
+ }
+ if (dps == DS.T_NNt || dps == DS.T_Nt) {
+ if ((str.Index < str.len - 1)) {
+ if (false == HandleTimeZone(ref str, ref result))
+ {
+ LexTraceExit("0020 (value like \"12:01\" or \"12:\" followed by a non-TZ number", dps);
+ return false;
+ }
+ }
+ }
+
+ dtok.num = tokenValue;
+ if (tokenType == TokenType.YearNumberToken)
+ {
+ if (raw.year == -1)
+ {
+ raw.year = tokenValue;
+ //
+ // If we have number which has 3 or more digits (like "001" or "0001"),
+ // we assume this number is a year. Save the currnet raw.numCount in
+ // raw.year.
+ //
+ switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
+ case TokenType.SEP_End:
+ dtok.dtt = DTT.YearEnd;
+ break;
+ case TokenType.SEP_Am:
+ case TokenType.SEP_Pm:
+ if (raw.timeMark == TM.NotSet) {
+ raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
+ dtok.dtt = DTT.YearSpace;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0030 (TM.AM/TM.PM Happened more than 1x)", dps);
+ }
+ break;
+ case TokenType.SEP_Space:
+ dtok.dtt = DTT.YearSpace;
+ break;
+ case TokenType.SEP_Date:
+ dtok.dtt = DTT.YearDateSep;
+ break;
+ case TokenType.SEP_Time:
+ if (!raw.hasSameDateAndTimeSeparators)
+ {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0040 (Invalid separator after number)", dps);
+ return false;
+ }
+
+ // we have the date and time separators are same and getting a year number, then change the token to YearDateSep as
+ // we are sure we are not parsing time.
+ dtok.dtt = DTT.YearDateSep;
+ break;
+ case TokenType.SEP_DateOrOffset:
+ // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
+ // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
+ if ((dateParsingStates[(int)dps][(int) DTT.YearDateSep] == DS.ERROR)
+ && (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR)) {
+ str.Index = indexBeforeSeparator;
+ str.m_current = charBeforeSeparator;
+ dtok.dtt = DTT.YearSpace;
+ }
+ else {
+ dtok.dtt = DTT.YearDateSep;
+ }
+ break;
+ case TokenType.SEP_YearSuff:
+ case TokenType.SEP_MonthSuff:
+ case TokenType.SEP_DaySuff:
+ dtok.dtt = DTT.NumDatesuff;
+ dtok.suffix = sep;
+ break;
+ case TokenType.SEP_HourSuff:
+ case TokenType.SEP_MinuteSuff:
+ case TokenType.SEP_SecondSuff:
+ dtok.dtt = DTT.NumTimesuff;
+ dtok.suffix = sep;
+ break;
+ default:
+ // Invalid separator after number number.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0040 (Invalid separator after number)", dps);
+ return false;
+ }
+ //
+ // Found the token already. Return now.
+ //
+ LexTraceExit("0050 (success)", dps);
+ return true;
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0060", dps);
+ return false;
+ }
+ switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
+ {
+ //
+ // Note here we check if the numCount is less than three.
+ // When we have more than three numbers, it will be caught as error in the state machine.
+ //
+ case TokenType.SEP_End:
+ dtok.dtt = DTT.NumEnd;
+ raw.AddNumber(dtok.num);
+ break;
+ case TokenType.SEP_Am:
+ case TokenType.SEP_Pm:
+ if (raw.timeMark == TM.NotSet) {
+ raw.timeMark = (sep == TokenType.SEP_Am ? TM.AM : TM.PM);
+ dtok.dtt = DTT.NumAmpm;
+ // Fix AM/PM parsing case, e.g. "1/10 5 AM"
+ if (dps == DS.D_NN
+#if !FEATURE_CORECLR
+ && enableAmPmParseAdjustment
+#endif
+ )
+ {
+ if (!ProcessTerminaltState(DS.DX_NN, ref result, ref styles, ref raw, dtfi))
+ {
+ return false;
+ }
+ }
+
+ raw.AddNumber(dtok.num);
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ break;
+ }
+ if (dps == DS.T_NNt || dps == DS.T_Nt) {
+ if (false == HandleTimeZone(ref str, ref result))
+ {
+ LexTraceExit("0070 (HandleTimeZone returned false)", dps);
+ return false;
+ }
+ }
+ break;
+ case TokenType.SEP_Space:
+ dtok.dtt = DTT.NumSpace;
+ raw.AddNumber(dtok.num);
+ break;
+ case TokenType.SEP_Date:
+ dtok.dtt = DTT.NumDatesep;
+ raw.AddNumber(dtok.num);
+ break;
+ case TokenType.SEP_DateOrOffset:
+ // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
+ // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
+ if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR)
+ && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) {
+ str.Index = indexBeforeSeparator;
+ str.m_current = charBeforeSeparator;
+ dtok.dtt = DTT.NumSpace;
+ }
+ else {
+ dtok.dtt = DTT.NumDatesep;
+ }
+ raw.AddNumber(dtok.num);
+ break;
+ case TokenType.SEP_Time:
+ if (raw.hasSameDateAndTimeSeparators &&
+ (dps == DS.D_Y || dps == DS.D_YN || dps == DS.D_YNd || dps == DS.D_YM || dps == DS.D_YMd))
+ {
+ // we are parsing a date and we have the time separator same as date separator, so we mark the token as date separator
+ dtok.dtt = DTT.NumDatesep;
+ raw.AddNumber(dtok.num);
+ break;
+ }
+ dtok.dtt = DTT.NumTimesep;
+ raw.AddNumber(dtok.num);
+ break;
+ case TokenType.SEP_YearSuff:
+ try {
+ dtok.num = dtfi.Calendar.ToFourDigitYear(tokenValue);
+ }
+ catch (ArgumentOutOfRangeException e) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e);
+ LexTraceExit("0075 (Calendar.ToFourDigitYear failed)", dps);
+ return false;
+ }
+ dtok.dtt = DTT.NumDatesuff;
+ dtok.suffix = sep;
+ break;
+ case TokenType.SEP_MonthSuff:
+ case TokenType.SEP_DaySuff:
+ dtok.dtt = DTT.NumDatesuff;
+ dtok.suffix = sep;
+ break;
+ case TokenType.SEP_HourSuff:
+ case TokenType.SEP_MinuteSuff:
+ case TokenType.SEP_SecondSuff:
+ dtok.dtt = DTT.NumTimesuff;
+ dtok.suffix = sep;
+ break;
+ case TokenType.SEP_LocalTimeMark:
+ dtok.dtt = DTT.NumLocalTimeMark;
+ raw.AddNumber(dtok.num);
+ break;
+ default:
+ // Invalid separator after number number.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0080", dps);
+ return false;
+ }
+ break;
+ case TokenType.HebrewNumber:
+ if (tokenValue >= 100) {
+ // This is a year number
+ if (raw.year == -1) {
+ raw.year = tokenValue;
+ //
+ // If we have number which has 3 or more digits (like "001" or "0001"),
+ // we assume this number is a year. Save the currnet raw.numCount in
+ // raw.year.
+ //
+ switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
+ case TokenType.SEP_End:
+ dtok.dtt = DTT.YearEnd;
+ break;
+ case TokenType.SEP_Space:
+ dtok.dtt = DTT.YearSpace;
+ break;
+ case TokenType.SEP_DateOrOffset:
+ // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
+ // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
+ if (dateParsingStates[(int)dps][(int) DTT.YearSpace] > DS.ERROR) {
+ str.Index = indexBeforeSeparator;
+ str.m_current = charBeforeSeparator;
+ dtok.dtt = DTT.YearSpace;
+ break;
+ }
+ goto default;
+ default:
+ // Invalid separator after number number.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0090", dps);
+ return false;
+ }
+ } else {
+ // Invalid separator after number number.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0100", dps);
+ return false;
+ }
+ } else {
+ // This is a day number
+ dtok.num = tokenValue;
+ raw.AddNumber(dtok.num);
+
+ switch (sep = str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator)) {
+ //
+ // Note here we check if the numCount is less than three.
+ // When we have more than three numbers, it will be caught as error in the state machine.
+ //
+ case TokenType.SEP_End:
+ dtok.dtt = DTT.NumEnd;
+ break;
+ case TokenType.SEP_Space:
+ case TokenType.SEP_Date:
+ dtok.dtt = DTT.NumDatesep;
+ break;
+ case TokenType.SEP_DateOrOffset:
+ // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
+ // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
+ if ((dateParsingStates[(int)dps][(int) DTT.NumDatesep] == DS.ERROR)
+ && (dateParsingStates[(int)dps][(int) DTT.NumSpace] > DS.ERROR)) {
+ str.Index = indexBeforeSeparator;
+ str.m_current = charBeforeSeparator;
+ dtok.dtt = DTT.NumSpace;
+ }
+ else {
+ dtok.dtt = DTT.NumDatesep;
+ }
+ break;
+ default:
+ // Invalid separator after number number.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0110", dps);
+ return false;
+ }
+ }
+ break;
+ case TokenType.DayOfWeekToken:
+ if (raw.dayOfWeek == -1)
+ {
+ //
+ // This is a day of week name.
+ //
+ raw.dayOfWeek = tokenValue;
+ dtok.dtt = DTT.DayOfWeek;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0120 (DayOfWeek seen more than 1x)", dps);
+ return false;
+ }
+ break;
+ case TokenType.MonthToken:
+ if (raw.month == -1)
+ {
+ //
+ // This is a month name
+ //
+ switch(sep=str.GetSeparatorToken(dtfi, out indexBeforeSeparator, out charBeforeSeparator))
+ {
+ case TokenType.SEP_End:
+ dtok.dtt = DTT.MonthEnd;
+ break;
+ case TokenType.SEP_Space:
+ dtok.dtt = DTT.MonthSpace;
+ break;
+ case TokenType.SEP_Date:
+ dtok.dtt = DTT.MonthDatesep;
+ break;
+ case TokenType.SEP_Time:
+ if (!raw.hasSameDateAndTimeSeparators)
+ {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0130 (Invalid separator after month name)", dps);
+ return false;
+ }
+
+ // we have the date and time separators are same and getting a Month name, then change the token to MonthDatesep as
+ // we are sure we are not parsing time.
+ dtok.dtt = DTT.MonthDatesep;
+ break;
+ case TokenType.SEP_DateOrOffset:
+ // The separator is either a date separator or the start of a time zone offset. If the token will complete the date then
+ // process just the number and roll back the index so that the outer loop can attempt to parse the time zone offset.
+ if ((dateParsingStates[(int)dps][(int) DTT.MonthDatesep] == DS.ERROR)
+ && (dateParsingStates[(int)dps][(int) DTT.MonthSpace] > DS.ERROR)) {
+ str.Index = indexBeforeSeparator;
+ str.m_current = charBeforeSeparator;
+ dtok.dtt = DTT.MonthSpace;
+ }
+ else {
+ dtok.dtt = DTT.MonthDatesep;
+ }
+ break;
+ default:
+ //Invalid separator after month name
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0130 (Invalid separator after month name)", dps);
+ return false;
+ }
+ raw.month = tokenValue;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0140 (MonthToken seen more than 1x)", dps);
+ return false;
+ }
+ break;
+ case TokenType.EraToken:
+ if (result.era != -1) {
+ result.era = tokenValue;
+ dtok.dtt = DTT.Era;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0150 (EraToken seen when result.era already set)", dps);
+ return false;
+ }
+ break;
+ case TokenType.JapaneseEraToken:
+ // Special case for Japanese. We allow Japanese era name to be used even if the calendar is not Japanese Calendar.
+ result.calendar = JapaneseCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.GetJapaneseCalendarDTFI();
+ if (result.era != -1) {
+ result.era = tokenValue;
+ dtok.dtt = DTT.Era;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0160 (JapaneseEraToken seen when result.era already set)", dps);
+ return false;
+ }
+ break;
+ case TokenType.TEraToken:
+ result.calendar = TaiwanCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.GetTaiwanCalendarDTFI();
+ if (result.era != -1) {
+ result.era = tokenValue;
+ dtok.dtt = DTT.Era;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0170 (TEraToken seen when result.era already set)", dps);
+ return false;
+ }
+ break;
+ case TokenType.TimeZoneToken:
+ //
+ // This is a timezone designator
+ //
+ // NOTENOTE : for now, we only support "GMT" and "Z" (for Zulu time).
+ //
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0) {
+ // Should not have two timezone offsets.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0180 (seen GMT or Z more than 1x)", dps);
+ return false;
+ }
+ dtok.dtt = DTT.TimeZone;
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(0);
+ result.flags |= ParseFlags.TimeZoneUtc;
+ break;
+ case TokenType.EndOfString:
+ dtok.dtt = DTT.End;
+ break;
+ case TokenType.DateWordToken:
+ case TokenType.IgnorableSymbol:
+ // Date words and ignorable symbols can just be skipped over
+ break;
+ case TokenType.Am:
+ case TokenType.Pm:
+ if (raw.timeMark == TM.NotSet) {
+ raw.timeMark = (TM)tokenValue;
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0190 (AM/PM timeMark already set)", dps);
+ return false;
+ }
+ break;
+ case TokenType.UnknownToken:
+ if (Char.IsLetter(str.m_current)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_UnknowDateTimeWord", str.Index);
+ LexTraceExit("0200", dps);
+ return (false);
+ }
+
+#if !FEATURE_CORECLR
+ // If DateTimeParseIgnorePunctuation is defined, we want to have the V1.1 behavior of just
+ // ignoring any unrecognized punctuation and moving on to the next character
+ if (Environment.GetCompatibilityFlag(CompatibilityFlag.DateTimeParseIgnorePunctuation) && ((result.flags & ParseFlags.CaptureOffset) == 0)) {
+ str.GetNext();
+ LexTraceExit("0210 (success)", dps);
+ return true;
+ }
+#endif // FEATURE_CORECLR
+
+ if ((str.m_current == '-' || str.m_current == '+') && ((result.flags & ParseFlags.TimeZoneUsed) == 0)) {
+ Int32 originalIndex = str.Index;
+ if (ParseTimeZone(ref str, ref result.timeZoneOffset)) {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ LexTraceExit("0220 (success)", dps);
+ return true;
+ }
+ else {
+ // Time zone parse attempt failed. Fall through to punctuation handling.
+ str.Index = originalIndex;
+ }
+ }
+
+ // Visual Basic implements string to date conversions on top of DateTime.Parse:
+ // CDate("#10/10/95#")
+ //
+ if (VerifyValidPunctuation(ref str)) {
+ LexTraceExit("0230 (success)", dps);
+ return true;
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ LexTraceExit("0240", dps);
+ return false;
+ }
+
+ LexTraceExit("0250 (success)", dps);
+ return true;
+ }
+
+ private static Boolean VerifyValidPunctuation(ref __DTString str) {
+ // Compatability Behavior. Allow trailing nulls and surrounding hashes
+ Char ch = str.Value[str.Index];
+ if (ch == '#') {
+ bool foundStart = false;
+ bool foundEnd = false;
+ for (int i = 0; i < str.len; i++) {
+ ch = str.Value[i];
+ if (ch == '#') {
+ if (foundStart) {
+ if (foundEnd) {
+ // Having more than two hashes is invalid
+ return false;
+ }
+ else {
+ foundEnd = true;
+ }
+ }
+ else {
+ foundStart = true;
+ }
+ }
+ else if (ch == '\0') {
+ // Allow nulls only at the end
+ if (!foundEnd) {
+ return false;
+ }
+ }
+ else if ((!Char.IsWhiteSpace(ch))) {
+ // Anthyhing other than whitespace outside hashes is invalid
+ if (!foundStart || foundEnd) {
+ return false;
+ }
+ }
+ }
+ if (!foundEnd) {
+ // The has was un-paired
+ return false;
+ }
+ // Valid Hash usage: eat the hash and continue.
+ str.GetNext();
+ return true;
+ }
+ else if (ch == '\0') {
+ for (int i = str.Index; i < str.len; i++) {
+ if (str.Value[i] != '\0') {
+ // Nulls are only valid if they are the only trailing character
+ return false;
+ }
+ }
+ // Move to the end of the string
+ str.Index = str.len;
+ return true;
+ }
+ return false;
+ }
+
+ private const int ORDER_YMD = 0; // The order of date is Year/Month/Day.
+ private const int ORDER_MDY = 1; // The order of date is Month/Day/Year.
+ private const int ORDER_DMY = 2; // The order of date is Day/Month/Year.
+ private const int ORDER_YDM = 3; // The order of date is Year/Day/Month
+ private const int ORDER_YM = 4; // Year/Month order.
+ private const int ORDER_MY = 5; // Month/Year order.
+ private const int ORDER_MD = 6; // Month/Day order.
+ private const int ORDER_DM = 7; // Day/Month order.
+
+ //
+ // Decide the year/month/day order from the datePattern.
+ //
+ // Return 0 for YMD, 1 for MDY, 2 for DMY, otherwise -1.
+ //
+ private static Boolean GetYearMonthDayOrder(String datePattern, DateTimeFormatInfo dtfi, out int order)
+ {
+ int yearOrder = -1;
+ int monthOrder = -1;
+ int dayOrder = -1;
+ int orderCount = 0;
+
+ bool inQuote = false;
+
+ for (int i = 0; i < datePattern.Length && orderCount < 3; i++)
+ {
+ char ch = datePattern[i];
+ if (ch == '\\' || ch == '%')
+ {
+ i++;
+ continue; // Skip next character that is escaped by this backslash
+ }
+
+ if (ch == '\'' || ch == '"')
+ {
+ inQuote = !inQuote;
+ }
+
+ if (!inQuote)
+ {
+ if (ch == 'y')
+ {
+ yearOrder = orderCount++;
+
+ //
+ // Skip all year pattern charaters.
+ //
+ for(; i+1 < datePattern.Length && datePattern[i+1] == 'y'; i++)
+ {
+ // Do nothing here.
+ }
+ }
+ else if (ch == 'M')
+ {
+ monthOrder = orderCount++;
+ //
+ // Skip all month pattern characters.
+ //
+ for(; i+1 < datePattern.Length && datePattern[i+1] == 'M'; i++)
+ {
+ // Do nothing here.
+ }
+ }
+ else if (ch == 'd')
+ {
+
+ int patternCount = 1;
+ //
+ // Skip all day pattern characters.
+ //
+ for(; i+1 < datePattern.Length && datePattern[i+1] == 'd'; i++)
+ {
+ patternCount++;
+ }
+ //
+ // Make sure this is not "ddd" or "dddd", which means day of week.
+ //
+ if (patternCount <= 2)
+ {
+ dayOrder = orderCount++;
+ }
+ }
+ }
+ }
+
+ if (yearOrder == 0 && monthOrder == 1 && dayOrder == 2)
+ {
+ order = ORDER_YMD;
+ return true;
+ }
+ if (monthOrder == 0 && dayOrder == 1 && yearOrder == 2)
+ {
+ order = ORDER_MDY;
+ return true;
+ }
+ if (dayOrder == 0 && monthOrder == 1 && yearOrder == 2)
+ {
+ order = ORDER_DMY;
+ return true;
+ }
+ if (yearOrder == 0 && dayOrder == 1 && monthOrder == 2)
+ {
+ order = ORDER_YDM;
+ return true;
+ }
+ order = -1;
+ return false;
+ }
+
+ //
+ // Decide the year/month order from the pattern.
+ //
+ // Return 0 for YM, 1 for MY, otherwise -1.
+ //
+ private static Boolean GetYearMonthOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ {
+ int yearOrder = -1;
+ int monthOrder = -1;
+ int orderCount = 0;
+
+ bool inQuote = false;
+ for (int i = 0; i < pattern.Length && orderCount < 2; i++)
+ {
+ char ch = pattern[i];
+ if (ch == '\\' || ch == '%')
+ {
+ i++;
+ continue; // Skip next character that is escaped by this backslash
+ }
+
+ if (ch == '\'' || ch == '"')
+ {
+ inQuote = !inQuote;
+ }
+
+ if (!inQuote)
+ {
+ if (ch == 'y')
+ {
+ yearOrder = orderCount++;
+
+ //
+ // Skip all year pattern charaters.
+ //
+ for(; i+1 < pattern.Length && pattern[i+1] == 'y'; i++)
+ {
+ }
+ }
+ else if (ch == 'M')
+ {
+ monthOrder = orderCount++;
+ //
+ // Skip all month pattern characters.
+ //
+ for(; i+1 < pattern.Length && pattern[i+1] == 'M'; i++)
+ {
+ }
+ }
+ }
+ }
+
+ if (yearOrder == 0 && monthOrder == 1)
+ {
+ order = ORDER_YM;
+ return true;
+ }
+ if (monthOrder == 0 && yearOrder == 1)
+ {
+ order = ORDER_MY;
+ return true;
+ }
+ order = -1;
+ return false;
+ }
+
+ //
+ // Decide the month/day order from the pattern.
+ //
+ // Return 0 for MD, 1 for DM, otherwise -1.
+ //
+ private static Boolean GetMonthDayOrder(String pattern, DateTimeFormatInfo dtfi, out int order)
+ {
+ int monthOrder = -1;
+ int dayOrder = -1;
+ int orderCount = 0;
+
+ bool inQuote = false;
+ for (int i = 0; i < pattern.Length && orderCount < 2; i++)
+ {
+ char ch = pattern[i];
+ if (ch == '\\' || ch == '%')
+ {
+ i++;
+ continue; // Skip next character that is escaped by this backslash
+ }
+
+ if (ch == '\'' || ch == '"')
+ {
+ inQuote = !inQuote;
+ }
+
+ if (!inQuote)
+ {
+ if (ch == 'd')
+ {
+ int patternCount = 1;
+ //
+ // Skip all day pattern charaters.
+ //
+ for(; i+1 < pattern.Length && pattern[i+1] == 'd'; i++)
+ {
+ patternCount++;
+ }
+
+ //
+ // Make sure this is not "ddd" or "dddd", which means day of week.
+ //
+ if (patternCount <= 2)
+ {
+ dayOrder = orderCount++;
+ }
+
+ }
+ else if (ch == 'M')
+ {
+ monthOrder = orderCount++;
+ //
+ // Skip all month pattern characters.
+ //
+ for(; i+1 < pattern.Length && pattern[i+1] == 'M'; i++)
+ {
+ }
+ }
+ }
+ }
+
+ if (monthOrder == 0 && dayOrder == 1)
+ {
+ order = ORDER_MD;
+ return true;
+ }
+ if (dayOrder == 0 && monthOrder == 1)
+ {
+ order = ORDER_DM;
+ return true;
+ }
+ order = -1;
+ return false;
+ }
+
+ //
+ // Adjust the two-digit year if necessary.
+ //
+ private static bool TryAdjustYear(ref DateTimeResult result, int year, out int adjustedYear)
+ {
+ if (year < 100)
+ {
+ try {
+ // the Calendar classes need some real work. Many of the calendars that throw
+ // don't implement a fast/non-allocating (and non-throwing) IsValid{Year|Day|Month} method.
+ // we are making a targeted try/catch fix in the in-place release but will revisit this code
+ // in the next side-by-side release.
+ year = result.calendar.ToFourDigitYear(year);
+ }
+ catch (ArgumentOutOfRangeException) {
+ adjustedYear = -1;
+ return false;
+ }
+ }
+ adjustedYear = year;
+ return true;
+ }
+
+ private static bool SetDateYMD(ref DateTimeResult result, int year, int month, int day)
+ {
+ // Note, longer term these checks should be done at the end of the parse. This current
+ // way of checking creates order dependence with parsing the era name.
+ if (result.calendar.IsValidDay(year, month, day, result.era))
+ {
+ result.SetDate(year, month, day); // YMD
+ return (true);
+ }
+ return (false);
+ }
+
+ private static bool SetDateMDY(ref DateTimeResult result, int month, int day, int year)
+ {
+ return (SetDateYMD(ref result, year, month, day));
+ }
+
+ private static bool SetDateDMY(ref DateTimeResult result, int day, int month, int year)
+ {
+ return (SetDateYMD(ref result, year, month, day));
+ }
+
+ private static bool SetDateYDM(ref DateTimeResult result, int year, int day, int month)
+ {
+ return (SetDateYMD(ref result, year, month, day));
+ }
+
+ private static void GetDefaultYear(ref DateTimeResult result, ref DateTimeStyles styles) {
+ result.Year = result.calendar.GetYear(GetDateTimeNow(ref result, ref styles));
+ result.flags |= ParseFlags.YearDefault;
+ }
+
+ // Processing teriminal case: DS.DX_NN
+ private static Boolean GetDayOfNN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ int n1 = raw.GetNumber(0);
+ int n2 = raw.GetNumber(1);
+
+ GetDefaultYear(ref result, ref styles);
+
+ int order;
+ if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out order)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ return false;
+ }
+
+ if (order == ORDER_MD)
+ {
+ if (SetDateYMD(ref result, result.Year, n1, n2)) // MD
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ } else {
+ // ORDER_DM
+ if (SetDateYMD(ref result, result.Year, n2, n1)) // DM
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ // Processing teriminal case: DS.DX_NNN
+ private static Boolean GetDayOfNNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ int n1 = raw.GetNumber(0);
+ int n2 = raw.GetNumber(1);;
+ int n3 = raw.GetNumber(2);
+
+ int order;
+ if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ return false;
+ }
+ int year;
+
+ if (order == ORDER_YMD) {
+ if (TryAdjustYear(ref result, n1, out year) && SetDateYMD(ref result, year, n2, n3)) // YMD
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ } else if (order == ORDER_MDY) {
+ if (TryAdjustYear(ref result, n3, out year) && SetDateMDY(ref result, n1, n2, year)) // MDY
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ } else if (order == ORDER_DMY) {
+ if (TryAdjustYear(ref result, n3, out year) && SetDateDMY(ref result, n1, n2, year)) // DMY
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ } else if (order == ORDER_YDM) {
+ if (TryAdjustYear(ref result, n1, out year) && SetDateYDM(ref result, year, n2, n3)) // YDM
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfMN(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ // The interpretation is based on the MonthDayPattern and YearMonthPattern
+ //
+ // MonthDayPattern YearMonthPattern Interpretation
+ // --------------- ---------------- ---------------
+ // MMMM dd MMMM yyyy Day
+ // MMMM dd yyyy MMMM Day
+ // dd MMMM MMMM yyyy Year
+ // dd MMMM yyyy MMMM Day
+ //
+ // In the first and last cases, it could be either or neither, but a day is a better default interpretation
+ // than a 2 digit year.
+
+ int monthDayOrder;
+ if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ return false;
+ }
+ if (monthDayOrder == ORDER_DM) {
+ int yearMonthOrder;
+ if (!GetYearMonthOrder(dtfi.YearMonthPattern, dtfi, out yearMonthOrder)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.YearMonthPattern);
+ return false;
+ }
+ if (yearMonthOrder == ORDER_MY) {
+ int year;
+ if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ GetDefaultYear(ref result, ref styles);
+ if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0))) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ return true;
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ // Actions:
+ // Deal with the terminal state for Hebrew Month/Day pattern
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ private static Boolean GetHebrewDayOfNM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ int monthDayOrder;
+ if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ return false;
+ }
+ result.Month = raw.month;
+ if (monthDayOrder == ORDER_DM || monthDayOrder == ORDER_MD)
+ {
+ if (result.calendar.IsValidDay(result.Year, result.Month, raw.GetNumber(0), result.era))
+ {
+ result.Day = raw.GetNumber(0);
+ return true;
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfNM(ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ // The interpretation is based on the MonthDayPattern and YearMonthPattern
+ //
+ // MonthDayPattern YearMonthPattern Interpretation
+ // --------------- ---------------- ---------------
+ // MMMM dd MMMM yyyy Day
+ // MMMM dd yyyy MMMM Year
+ // dd MMMM MMMM yyyy Day
+ // dd MMMM yyyy MMMM Day
+ //
+ // In the first and last cases, it could be either or neither, but a day is a better default interpretation
+ // than a 2 digit year.
+
+ int monthDayOrder;
+ if (!GetMonthDayOrder(dtfi.MonthDayPattern, dtfi, out monthDayOrder)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.MonthDayPattern);
+ return false;
+ }
+ if (monthDayOrder == ORDER_MD) {
+ int yearMonthOrder;
+ if (!GetYearMonthOrder(dtfi.YearMonthPattern, dtfi, out yearMonthOrder)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.YearMonthPattern);
+ return false;
+ }
+ if (yearMonthOrder == ORDER_YM) {
+ int year;
+ if (!TryAdjustYear(ref result, raw.GetNumber(0), out year) || !SetDateYMD(ref result, year, raw.month, 1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ GetDefaultYear(ref result, ref styles);
+ if (!SetDateYMD(ref result, result.Year, raw.month, raw.GetNumber(0))) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ return true;
+ }
+
+ private static Boolean GetDayOfMNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ int n1 = raw.GetNumber(0);
+ int n2 = raw.GetNumber(1);
+
+ int order;
+ if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ return false;
+ }
+ int year;
+
+ if (order == ORDER_MDY)
+ {
+ if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
+ {
+ result.SetDate(year, raw.month, n1); // MDY
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ else if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
+ {
+ result.SetDate(year, raw.month, n2); // YMD
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ }
+ else if (order == ORDER_YMD)
+ {
+ if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
+ {
+ result.SetDate(year, raw.month, n2); // YMD
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ else if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
+ {
+ result.SetDate(year, raw.month, n1); // DMY
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ }
+ else if (order == ORDER_DMY)
+ {
+ if (TryAdjustYear(ref result, n2, out year) && result.calendar.IsValidDay(year, raw.month, n1, result.era))
+ {
+ result.SetDate(year, raw.month, n1); // DMY
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ else if (TryAdjustYear(ref result, n1, out year) && result.calendar.IsValidDay(year, raw.month, n2, result.era))
+ {
+ result.SetDate(year, raw.month, n2); // YMD
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfYNN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ int n1 = raw.GetNumber(0);
+ int n2 = raw.GetNumber(1);
+ String pattern = dtfi.ShortDatePattern;
+
+ // For compatibility, don't throw if we can't determine the order, but default to YMD instead
+ int order;
+ if (GetYearMonthDayOrder(pattern, dtfi, out order) && order == ORDER_YDM) {
+ if (SetDateYMD(ref result, raw.year, n2, n1)) {
+ result.flags |= ParseFlags.HaveDate;
+ return true; // Year + DM
+ }
+ }
+ else {
+ if (SetDateYMD(ref result, raw.year, n1, n2)) {
+ result.flags |= ParseFlags.HaveDate;
+ return true; // Year + MD
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfNNY(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ int n1 = raw.GetNumber(0);
+ int n2 = raw.GetNumber(1);
+
+ int order;
+ if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ return false;
+ }
+
+ if (order == ORDER_MDY || order == ORDER_YMD) {
+ if (SetDateYMD(ref result, raw.year, n1, n2)) {
+ result.flags |= ParseFlags.HaveDate;
+ return true; // MD + Year
+ }
+ } else {
+ if (SetDateYMD(ref result, raw.year, n2, n1)) {
+ result.flags |= ParseFlags.HaveDate;
+ return true; // DM + Year
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+
+ private static Boolean GetDayOfYMN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (SetDateYMD(ref result, raw.year, raw.month, raw.GetNumber(0))) {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfYN(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (SetDateYMD(ref result, raw.year, raw.GetNumber(0), 1))
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static Boolean GetDayOfYM(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+ if ((result.flags & ParseFlags.HaveDate) != 0) {
+ // Multiple dates in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (SetDateYMD(ref result, raw.year, raw.month, 1))
+ {
+ result.flags |= ParseFlags.HaveDate;
+ return true;
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ private static void AdjustTimeMark(DateTimeFormatInfo dtfi, ref DateTimeRawInfo raw) {
+ // Specail case for culture which uses AM as empty string.
+ // E.g. af-ZA (0x0436)
+ // S1159 \x0000
+ // S2359 nm
+ // In this case, if we are parsing a string like "2005/09/14 12:23", we will assume this is in AM.
+
+ if (raw.timeMark == TM.NotSet) {
+ if (dtfi.AMDesignator != null && dtfi.PMDesignator != null) {
+ if (dtfi.AMDesignator.Length == 0 && dtfi.PMDesignator.Length != 0) {
+ raw.timeMark = TM.AM;
+ }
+ if (dtfi.PMDesignator.Length == 0 && dtfi.AMDesignator.Length != 0) {
+ raw.timeMark = TM.PM;
+ }
+ }
+ }
+ }
+
+ //
+ // Adjust hour according to the time mark.
+ //
+ private static Boolean AdjustHour(ref int hour, TM timeMark) {
+ if (timeMark != TM.NotSet) {
+
+ if (timeMark == TM.AM) {
+ if (hour < 0 || hour > 12) {
+ return false;
+ }
+ hour = (hour == 12) ? 0 : hour;
+ }
+ else {
+ if (hour < 0 || hour > 23) {
+ return false;
+ }
+ if (hour < 12) {
+ hour += 12;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static Boolean GetTimeOfN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ {
+ if ((result.flags & ParseFlags.HaveTime) != 0) {
+ // Multiple times in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ //
+ // In this case, we need a time mark. Check if so.
+ //
+ if (raw.timeMark == TM.NotSet)
+ {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ result.Hour = raw.GetNumber(0);
+ result.flags |= ParseFlags.HaveTime;
+ return true;
+ }
+
+ private static Boolean GetTimeOfNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ {
+ Contract.Assert(raw.numCount >= 2, "raw.numCount >= 2");
+ if ((result.flags & ParseFlags.HaveTime) != 0) {
+ // Multiple times in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ result.Hour = raw.GetNumber(0);
+ result.Minute = raw.GetNumber(1);
+ result.flags |= ParseFlags.HaveTime;
+ return true;
+ }
+
+ private static Boolean GetTimeOfNNN(DateTimeFormatInfo dtfi, ref DateTimeResult result, ref DateTimeRawInfo raw)
+ {
+ if ((result.flags & ParseFlags.HaveTime) != 0) {
+ // Multiple times in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ Contract.Assert(raw.numCount >= 3, "raw.numCount >= 3");
+ result.Hour = raw.GetNumber(0);
+ result.Minute = raw.GetNumber(1);
+ result.Second = raw.GetNumber(2);
+ result.flags |= ParseFlags.HaveTime;
+ return true;
+ }
+
+ //
+ // Processing terminal state: A Date suffix followed by one number.
+ //
+ private static Boolean GetDateOfDSN(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ {
+ if (raw.numCount != 1 || result.Day != -1)
+ {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ result.Day = raw.GetNumber(0);
+ return true;
+ }
+
+ private static Boolean GetDateOfNDS(ref DateTimeResult result, ref DateTimeRawInfo raw)
+ {
+ if (result.Month == -1)
+ {
+ //Should have a month suffix
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ if (result.Year != -1)
+ {
+ // Aleady has a year suffix
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ if (!TryAdjustYear(ref result, raw.GetNumber(0), out result.Year))
+ {
+ // the year value is out of range
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ result.Day = 1;
+ return true;
+ }
+
+ private static Boolean GetDateOfNNDS(ref DateTimeResult result, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+
+ // For partial CJK Dates, the only valid formats are with a specified year, followed by two numbers, which
+ // will be the Month and Day, and with a specified Month, when the numbers are either the year and day or
+ // day and year, depending on the short date pattern.
+
+ if ((result.flags & ParseFlags.HaveYear) != 0) {
+ if (((result.flags & ParseFlags.HaveMonth) == 0) && ((result.flags & ParseFlags.HaveDay) == 0)) {
+ if (TryAdjustYear(ref result, raw.year, out result.Year) && SetDateYMD(ref result, result.Year, raw.GetNumber(0), raw.GetNumber(1))) {
+ return true;
+ }
+ }
+ }
+ else if ((result.flags & ParseFlags.HaveMonth) != 0) {
+ if (((result.flags & ParseFlags.HaveYear) == 0) && ((result.flags & ParseFlags.HaveDay) == 0)) {
+ int order;
+ if (!GetYearMonthDayOrder(dtfi.ShortDatePattern, dtfi, out order)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadDatePattern", dtfi.ShortDatePattern);
+ return false;
+ }
+ int year;
+ if (order == ORDER_YMD) {
+ if (TryAdjustYear(ref result, raw.GetNumber(0), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(1))) {
+ return true;
+ }
+ }
+ else {
+ if (TryAdjustYear(ref result, raw.GetNumber(1), out year) && SetDateYMD(ref result, year, result.Month, raw.GetNumber(0))){
+ return true;
+ }
+ }
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ //
+ // A date suffix is found, use this method to put the number into the result.
+ //
+ private static bool ProcessDateTimeSuffix(ref DateTimeResult result, ref DateTimeRawInfo raw, ref DateTimeToken dtok)
+ {
+ switch (dtok.suffix)
+ {
+ case TokenType.SEP_YearSuff:
+ if ((result.flags & ParseFlags.HaveYear) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveYear;
+ result.Year = raw.year = dtok.num;
+ break;
+ case TokenType.SEP_MonthSuff:
+ if ((result.flags & ParseFlags.HaveMonth) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveMonth;
+ result.Month= raw.month = dtok.num;
+ break;
+ case TokenType.SEP_DaySuff:
+ if ((result.flags & ParseFlags.HaveDay) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveDay;
+ result.Day = dtok.num;
+ break;
+ case TokenType.SEP_HourSuff:
+ if ((result.flags & ParseFlags.HaveHour) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveHour;
+ result.Hour = dtok.num;
+ break;
+ case TokenType.SEP_MinuteSuff:
+ if ((result.flags & ParseFlags.HaveMinute) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveMinute;
+ result.Minute = dtok.num;
+ break;
+ case TokenType.SEP_SecondSuff:
+ if ((result.flags & ParseFlags.HaveSecond) != 0) {
+ return false;
+ }
+ result.flags |= ParseFlags.HaveSecond;
+ result.Second = dtok.num;
+ break;
+ }
+ return true;
+
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // This is used by DateTime.Parse().
+ // Process the terminal state for the Hebrew calendar parsing.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static Boolean ProcessHebrewTerminalState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi) {
+ // The following are accepted terminal state for Hebrew date.
+ switch (dps) {
+ case DS.DX_MNN:
+ // Deal with the default long/short date format when the year number is ambigous (i.e. year < 100).
+ raw.year = raw.GetNumber(1);
+ if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ if (!GetDayOfMNN(ref result, ref raw, dtfi)) {
+ return false;
+ }
+ break;
+ case DS.DX_YMN:
+ // Deal with the default long/short date format when the year number is NOT ambigous (i.e. year >= 100).
+ if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ if (!GetDayOfYMN(ref result, ref raw, dtfi)) {
+ return false;
+ }
+ break;
+ case DS.DX_NM:
+ case DS.DX_MN:
+ // Deal with Month/Day pattern.
+ GetDefaultYear(ref result, ref styles);
+ if (!dtfi.YearMonthAdjustment(ref result.Year, ref raw.month, true)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ if (!GetHebrewDayOfNM(ref result, ref raw, dtfi)) {
+ return false;
+ }
+ break;
+ case DS.DX_YM:
+ // Deal with Year/Month pattern.
+ if (!dtfi.YearMonthAdjustment(ref raw.year, ref raw.month, true)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ if (!GetDayOfYM(ref result, ref raw, dtfi)) {
+ return false;
+ }
+ break;
+ case DS.TX_N:
+ // Deal hour + AM/PM
+ if (!GetTimeOfN(dtfi, ref result, ref raw)) {
+ return false;
+ }
+ break;
+ case DS.TX_NN:
+ if (!GetTimeOfNN(dtfi, ref result, ref raw)) {
+ return false;
+ }
+ break;
+ case DS.TX_NNN:
+ if (!GetTimeOfNNN(dtfi, ref result, ref raw)) {
+ return false;
+ }
+ break;
+ default:
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+
+ }
+ if (dps > DS.ERROR)
+ {
+ //
+ // We have reached a terminal state. Reset the raw num count.
+ //
+ raw.numCount = 0;
+ }
+ return true;
+ }
+
+ //
+ // A terminal state has been reached, call the appropriate function to fill in the parsing result.
+ // Return true if the state is a terminal state.
+ //
+ internal static Boolean ProcessTerminaltState(DS dps, ref DateTimeResult result, ref DateTimeStyles styles, ref DateTimeRawInfo raw, DateTimeFormatInfo dtfi)
+ {
+
+ bool passed = true;
+ switch (dps)
+ {
+ case DS.DX_NN:
+ passed = GetDayOfNN(ref result, ref styles, ref raw, dtfi);
+ break;
+ case DS.DX_NNN:
+ passed = GetDayOfNNN(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_MN:
+ passed = GetDayOfMN(ref result, ref styles, ref raw, dtfi);
+ break;
+ case DS.DX_NM:
+ passed = GetDayOfNM(ref result, ref styles, ref raw, dtfi);
+ break;
+ case DS.DX_MNN:
+ passed = GetDayOfMNN(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_DS:
+ // The result has got the correct value. No need to process.
+ passed = true;
+ break;
+ case DS.DX_YNN:
+ passed = GetDayOfYNN(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_NNY:
+ passed = GetDayOfNNY(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_YMN:
+ passed = GetDayOfYMN(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_YN:
+ passed = GetDayOfYN(ref result, ref raw, dtfi);
+ break;
+ case DS.DX_YM:
+ passed = GetDayOfYM(ref result, ref raw, dtfi);
+ break;
+ case DS.TX_N:
+ passed = GetTimeOfN(dtfi, ref result, ref raw);
+ break;
+ case DS.TX_NN:
+ passed = GetTimeOfNN(dtfi, ref result, ref raw);
+ break;
+ case DS.TX_NNN:
+ passed = GetTimeOfNNN(dtfi, ref result, ref raw);
+ break;
+ case DS.TX_TS:
+ // The result has got the correct value. Nothing to do.
+ passed = true;
+ break;
+ case DS.DX_DSN:
+ passed = GetDateOfDSN(ref result, ref raw);
+ break;
+ case DS.DX_NDS:
+ passed = GetDateOfNDS(ref result, ref raw);
+ break;
+ case DS.DX_NNDS:
+ passed = GetDateOfNNDS(ref result, ref raw, dtfi);
+ break;
+ }
+
+ PTSTraceExit(dps, passed);
+ if (!passed) {
+ return false;
+ }
+
+ if (dps > DS.ERROR)
+ {
+ //
+ // We have reached a terminal state. Reset the raw num count.
+ //
+ raw.numCount = 0;
+ }
+ return true;
+ }
+
+ internal static DateTime Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ result.Init();
+ if (TryParse(s, dtfi, styles, ref result)) {
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+ internal static DateTime Parse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out TimeSpan offset) {
+ DateTimeResult result = new DateTimeResult(); // The buffer to store the parsing result.
+ result.Init();
+ result.flags |= ParseFlags.CaptureOffset;
+ if (TryParse(s, dtfi, styles, ref result)) {
+ offset = result.timeZoneOffset;
+ return result.parsedDate;
+ }
+ else {
+ throw GetDateTimeParseException(ref result);
+ }
+ }
+
+
+ internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out DateTime result) {
+ result = DateTime.MinValue;
+ DateTimeResult resultData = new DateTimeResult(); // The buffer to store the parsing result.
+ resultData.Init();
+ if (TryParse(s, dtfi, styles, ref resultData)) {
+ result = resultData.parsedDate;
+ return true;
+ }
+ return false;
+ }
+
+ internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, out DateTime result, out TimeSpan offset) {
+ result = DateTime.MinValue;
+ offset = TimeSpan.Zero;
+ DateTimeResult parseResult = new DateTimeResult(); // The buffer to store the parsing result.
+ parseResult.Init();
+ parseResult.flags |= ParseFlags.CaptureOffset;
+ if (TryParse(s, dtfi, styles, ref parseResult)) {
+ result = parseResult.parsedDate;
+ offset = parseResult.timeZoneOffset;
+ return true;
+ }
+ return false;
+ }
+
+
+ //
+ // This is the real method to do the parsing work.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool TryParse(String s, DateTimeFormatInfo dtfi, DateTimeStyles styles, ref DateTimeResult result) {
+ if (s == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "s");
+ return false;
+ }
+ if (s.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ Contract.Assert(dtfi != null, "dtfi == null");
+
+#if _LOGGING
+ DTFITrace(dtfi);
+#endif
+
+ DateTime time;
+ //
+ // First try the predefined format.
+ //
+
+ DS dps = DS.BEGIN; // Date Parsing State.
+ bool reachTerminalState = false;
+
+ DateTimeToken dtok = new DateTimeToken(); // The buffer to store the parsing token.
+ dtok.suffix = TokenType.SEP_Unk;
+ DateTimeRawInfo raw = new DateTimeRawInfo(); // The buffer to store temporary parsing information.
+ unsafe {
+ Int32 * numberPointer = stackalloc Int32[3];
+ raw.Init(numberPointer);
+ }
+ raw.hasSameDateAndTimeSeparators = dtfi.DateSeparator.Equals(dtfi.TimeSeparator, StringComparison.Ordinal);
+
+ result.calendar = dtfi.Calendar;
+ result.era = Calendar.CurrentEra;
+
+ //
+ // The string to be parsed. Use a __DTString wrapper so that we can trace the index which
+ // indicates the begining of next token.
+ //
+ __DTString str = new __DTString(s, dtfi);
+
+ str.GetNext();
+
+ //
+ // The following loop will break out when we reach the end of the str.
+ //
+ do {
+ //
+ // Call the lexer to get the next token.
+ //
+ // If we find a era in Lex(), the era value will be in raw.era.
+ if (!Lex(dps, ref str, ref dtok, ref raw, ref result, ref dtfi, styles))
+ {
+ TPTraceExit("0000", dps);
+ return false;
+ }
+
+ //
+ // If the token is not unknown, process it.
+ // Otherwise, just discard it.
+ //
+ if (dtok.dtt != DTT.Unk)
+ {
+ //
+ // Check if we got any CJK Date/Time suffix.
+ // Since the Date/Time suffix tells us the number belongs to year/month/day/hour/minute/second,
+ // store the number in the appropriate field in the result.
+ //
+ if (dtok.suffix != TokenType.SEP_Unk)
+ {
+ if (!ProcessDateTimeSuffix(ref result, ref raw, ref dtok)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ TPTraceExit("0010", dps);
+ return false;
+ }
+
+ dtok.suffix = TokenType.SEP_Unk; // Reset suffix to SEP_Unk;
+ }
+
+ if (dtok.dtt == DTT.NumLocalTimeMark) {
+ if (dps == DS.D_YNd || dps == DS.D_YN) {
+ // Consider this as ISO 8601 format:
+ // "yyyy-MM-dd'T'HH:mm:ss" 1999-10-31T02:00:00
+ TPTraceExit("0020", dps);
+ return (ParseISO8601(ref raw, ref str, styles, ref result));
+ }
+ else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ TPTraceExit("0030", dps);
+ return false;
+ }
+ }
+
+ if (raw.hasSameDateAndTimeSeparators)
+ {
+ if (dtok.dtt == DTT.YearEnd || dtok.dtt == DTT.YearSpace || dtok.dtt == DTT.YearDateSep)
+ {
+ // When time and date separators are same and we are hitting a year number while the first parsed part of the string was recognized
+ // as part of time (and not a date) DS.T_Nt, DS.T_NNt then change the state to be a date so we try to parse it as a date instead
+ if (dps == DS.T_Nt)
+ {
+ dps = DS.D_Nd;
+ }
+ if (dps == DS.T_NNt)
+ {
+ dps = DS.D_NNd;
+ }
+ }
+
+ bool atEnd = str.AtEnd();
+ if (dateParsingStates[(int)dps][(int)dtok.dtt] == DS.ERROR || atEnd)
+ {
+ switch (dtok.dtt)
+ {
+ // we have the case of Serbia have dates in forms 'd.M.yyyy.' so we can expect '.' after the date parts.
+ // changing the token to end with space instead of Date Separator will avoid failing the parsing.
+
+ case DTT.YearDateSep: dtok.dtt = atEnd ? DTT.YearEnd : DTT.YearSpace; break;
+ case DTT.NumDatesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
+ case DTT.NumTimesep: dtok.dtt = atEnd ? DTT.NumEnd : DTT.NumSpace; break;
+ case DTT.MonthDatesep: dtok.dtt = atEnd ? DTT.MonthEnd : DTT.MonthSpace; break;
+ }
+ }
+ }
+
+ //
+ // Advance to the next state, and continue
+ //
+ dps = dateParsingStates[(int)dps][(int)dtok.dtt];
+
+ if (dps == DS.ERROR)
+ {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ TPTraceExit("0040 (invalid state transition)", dps);
+ return false;
+ }
+ else if (dps > DS.ERROR)
+ {
+ if ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) != 0) {
+ if (!ProcessHebrewTerminalState(dps, ref result, ref styles, ref raw, dtfi)) {
+ TPTraceExit("0050 (ProcessHebrewTerminalState)", dps);
+ return false;
+ }
+ } else {
+ if (!ProcessTerminaltState(dps, ref result, ref styles, ref raw, dtfi)) {
+ TPTraceExit("0060 (ProcessTerminaltState)", dps);
+ return false;
+ }
+ }
+ reachTerminalState = true;
+
+ //
+ // If we have reached a terminal state, start over from DS.BEGIN again.
+ // For example, when we parsed "1999-12-23 13:30", we will reach a terminal state at "1999-12-23",
+ // and we start over so we can continue to parse "12:30".
+ //
+ dps = DS.BEGIN;
+ }
+ }
+ } while (dtok.dtt != DTT.End && dtok.dtt != DTT.NumEnd && dtok.dtt != DTT.MonthEnd);
+
+ if (!reachTerminalState) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ TPTraceExit("0070 (did not reach terminal state)", dps);
+ return false;
+ }
+
+ AdjustTimeMark(dtfi, ref raw);
+ if (!AdjustHour(ref result.Hour, raw.timeMark)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ TPTraceExit("0080 (AdjustHour)", dps);
+ return false;
+ }
+
+ // Check if the parased string only contains hour/minute/second values.
+ bool bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);
+
+ //
+ // Check if any year/month/day is missing in the parsing string.
+ // If yes, get the default value from today's date.
+ //
+ if (!CheckDefaultDateTime(ref result, ref result.calendar, styles)) {
+ TPTraceExit("0090 (failed to fill in missing year/month/day defaults)", dps);
+ return false;
+ }
+
+ if (!result.calendar.TryToDateTime(result.Year, result.Month, result.Day,
+ result.Hour, result.Minute, result.Second, 0, result.era, out time)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ TPTraceExit("0100 (result.calendar.TryToDateTime)", dps);
+ return false;
+ }
+ if (raw.fraction > 0) {
+ time = time.AddTicks((long)Math.Round(raw.fraction * Calendar.TicksPerSecond));
+ }
+
+ //
+ // We have to check day of week before we adjust to the time zone.
+ // Otherwise, the value of day of week may change after adjustting to the time zone.
+ //
+ if (raw.dayOfWeek != -1) {
+ //
+ // Check if day of week is correct.
+ //
+ if (raw.dayOfWeek != (int)result.calendar.GetDayOfWeek(time)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
+ TPTraceExit("0110 (dayOfWeek check)", dps);
+ return false;
+ }
+ }
+
+ result.parsedDate = time;
+
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) {
+ TPTraceExit("0120 (DetermineTimeZoneAdjustments)", dps);
+ return false;
+ }
+ TPTraceExit("0130 (success)", dps);
+ return true;
+ }
+
+
+ // Handles time zone adjustments and sets DateTimeKind values as required by the styles
+ private static Boolean DetermineTimeZoneAdjustments(ref DateTimeResult result, DateTimeStyles styles, Boolean bTimeOnly) {
+
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ // This is a DateTimeOffset parse, so the offset will actually be captured directly, and
+ // no adjustment is required in most cases
+ return DateTimeOffsetTimeZonePostProcessing(ref result, styles);
+ }
+#if FEATURE_CORECLR // on CoreCLR DateTime is also restricted to +- 14:00, just like DateTimeOffset
+ else {
+ Int64 offsetTicks = result.timeZoneOffset.Ticks;
+
+ // the DateTime offset must be within +- 14:00 hours.
+ if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset) {
+ result.SetFailure(ParseFailureKind.Format, "Format_OffsetOutOfRange", null);
+ return false;
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ // The flags AssumeUniveral and AssumeLocal only apply when the input does not have a time zone
+ if ((result.flags & ParseFlags.TimeZoneUsed) == 0) {
+
+ // If AssumeLocal or AssumeLocal is used, there will always be a kind specified. As in the
+ // case when a time zone is present, it will default to being local unless AdjustToUniversal
+ // is present. These comparisons determine whether setting the kind is sufficient, or if a
+ // time zone adjustment is required. For consistentcy with the rest of parsing, it is desirable
+ // to fall through to the Adjust methods below, so that there is consist handling of boundary
+ // cases like wrapping around on time-only dates and temporarily allowing an adjusted date
+ // to exceed DateTime.MaxValue
+ if ((styles & DateTimeStyles.AssumeLocal) != 0) {
+ if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeZoneInfo.GetLocalUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+ else {
+ result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Local);
+ return true;
+ }
+ }
+ else if ((styles & DateTimeStyles.AssumeUniversal) != 0) {
+ if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
+ result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Utc);
+ return true;
+ }
+ else {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeSpan.Zero;
+ }
+ }
+ else {
+ // No time zone and no Assume flags, so DateTimeKind.Unspecified is fine
+ Contract.Assert(result.parsedDate.Kind == DateTimeKind.Unspecified, "result.parsedDate.Kind == DateTimeKind.Unspecified");
+ return true;
+ }
+ }
+
+ if (((styles & DateTimeStyles.RoundtripKind) != 0) && ((result.flags & ParseFlags.TimeZoneUtc) != 0)) {
+ result.parsedDate = DateTime.SpecifyKind(result.parsedDate, DateTimeKind.Utc);
+ return true;
+ }
+
+ if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
+ return (AdjustTimeZoneToUniversal(ref result));
+ }
+ return (AdjustTimeZoneToLocal(ref result, bTimeOnly));
+ }
+
+ // Apply validation and adjustments specific to DateTimeOffset
+ private static Boolean DateTimeOffsetTimeZonePostProcessing(ref DateTimeResult result, DateTimeStyles styles) {
+
+ // For DateTimeOffset, default to the Utc or Local offset when an offset was not specified by
+ // the input string.
+ if ((result.flags & ParseFlags.TimeZoneUsed) == 0) {
+ if ((styles & DateTimeStyles.AssumeUniversal) != 0) {
+ // AssumeUniversal causes the offset to default to zero (0)
+ result.timeZoneOffset = TimeSpan.Zero;
+ }
+ else {
+ // AssumeLocal causes the offset to default to Local. This flag is on by default for DateTimeOffset.
+ result.timeZoneOffset = TimeZoneInfo.GetLocalUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+ }
+
+ Int64 offsetTicks = result.timeZoneOffset.Ticks;
+
+ // there should be no overflow, because the offset can be no more than -+100 hours and the date already
+ // fits within a DateTime.
+ Int64 utcTicks = result.parsedDate.Ticks - offsetTicks;
+
+ // For DateTimeOffset, both the parsed time and the corresponding UTC value must be within the boundaries
+ // of a DateTime instance.
+ if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks) {
+ result.SetFailure(ParseFailureKind.Format, "Format_UTCOutOfRange", null);
+ return false;
+ }
+
+ // the offset must be within +- 14:00 hours.
+ if (offsetTicks < DateTimeOffset.MinOffset || offsetTicks > DateTimeOffset.MaxOffset) {
+ result.SetFailure(ParseFailureKind.Format, "Format_OffsetOutOfRange", null);
+ return false;
+ }
+
+ // DateTimeOffset should still honor the AdjustToUniversal flag for consistency with DateTime. It means you
+ // want to return an adjusted UTC value, so store the utcTicks in the DateTime and set the offset to zero
+ if ((styles & DateTimeStyles.AdjustToUniversal) != 0) {
+ if (((result.flags & ParseFlags.TimeZoneUsed) == 0) && ((styles & DateTimeStyles.AssumeUniversal) == 0)) {
+ // Handle the special case where the timeZoneOffset was defaulted to Local
+ Boolean toUtcResult = AdjustTimeZoneToUniversal(ref result);
+ result.timeZoneOffset = TimeSpan.Zero;
+ return toUtcResult;
+ }
+
+ // The constructor should always succeed because of the range check earlier in the function
+ // Althought it is UTC, internally DateTimeOffset does not use this flag
+ result.parsedDate = new DateTime(utcTicks, DateTimeKind.Utc);
+ result.timeZoneOffset = TimeSpan.Zero;
+ }
+
+ return true;
+ }
+
+
+ //
+ // Adjust the specified time to universal time based on the supplied timezone.
+ // E.g. when parsing "2001/06/08 14:00-07:00",
+ // the time is 2001/06/08 14:00, and timeZoneOffset = -07:00.
+ // The result will be "2001/06/08 21:00"
+ //
+ private static Boolean AdjustTimeZoneToUniversal(ref DateTimeResult result) {
+ long resultTicks = result.parsedDate.Ticks;
+ resultTicks -= result.timeZoneOffset.Ticks;
+ if (resultTicks < 0) {
+ resultTicks += Calendar.TicksPerDay;
+ }
+
+ if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks) {
+ result.SetFailure(ParseFailureKind.Format, "Format_DateOutOfRange", null);
+ return false;
+ }
+ result.parsedDate = new DateTime(resultTicks, DateTimeKind.Utc);
+ return true;
+ }
+
+ //
+ // Adjust the specified time to universal time based on the supplied timezone,
+ // and then convert to local time.
+ // E.g. when parsing "2001/06/08 14:00-04:00", and local timezone is GMT-7.
+ // the time is 2001/06/08 14:00, and timeZoneOffset = -05:00.
+ // The result will be "2001/06/08 11:00"
+ //
+ private static Boolean AdjustTimeZoneToLocal(ref DateTimeResult result, bool bTimeOnly) {
+ long resultTicks = result.parsedDate.Ticks;
+ // Convert to local ticks
+ TimeZoneInfo tz = TimeZoneInfo.Local;
+ Boolean isAmbiguousLocalDst = false;
+ if (resultTicks < Calendar.TicksPerDay) {
+ //
+ // This is time of day.
+ //
+
+ // Adjust timezone.
+ resultTicks -= result.timeZoneOffset.Ticks;
+ // If the time is time of day, use the current timezone offset.
+ resultTicks += tz.GetUtcOffset(bTimeOnly ? DateTime.Now: result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
+
+ if (resultTicks < 0) {
+ resultTicks += Calendar.TicksPerDay;
+ }
+ } else {
+ // Adjust timezone to GMT.
+ resultTicks -= result.timeZoneOffset.Ticks;
+ if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks) {
+ // If the result ticks is greater than DateTime.MaxValue, we can not create a DateTime from this ticks.
+ // In this case, keep using the old code.
+ resultTicks += tz.GetUtcOffset(result.parsedDate, TimeZoneInfoOptions.NoThrowOnInvalidTime).Ticks;
+ } else {
+ // Convert the GMT time to local time.
+ DateTime utcDt = new DateTime(resultTicks, DateTimeKind.Utc);
+ Boolean isDaylightSavings = false;
+ resultTicks += TimeZoneInfo.GetUtcOffsetFromUtc(utcDt, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst).Ticks;
+ }
+ }
+ if (resultTicks < DateTime.MinTicks || resultTicks > DateTime.MaxTicks) {
+ result.parsedDate = DateTime.MinValue;
+ result.SetFailure(ParseFailureKind.Format, "Format_DateOutOfRange", null);
+ return false;
+ }
+ result.parsedDate = new DateTime(resultTicks, DateTimeKind.Local, isAmbiguousLocalDst);
+ return true;
+ }
+
+ //
+ // Parse the ISO8601 format string found during Parse();
+ //
+ //
+ private static bool ParseISO8601(ref DateTimeRawInfo raw, ref __DTString str, DateTimeStyles styles, ref DateTimeResult result) {
+ if (raw.year < 0 || raw.GetNumber(0) < 0 || raw.GetNumber(1) < 0) {
+ }
+ str.Index--;
+ int hour, minute;
+ int second = 0;
+ double partSecond = 0;
+
+ str.SkipWhiteSpaces();
+ if (!ParseDigits(ref str, 2, out hour)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.SkipWhiteSpaces();
+ if (!str.Match(':')) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.SkipWhiteSpaces();
+ if (!ParseDigits(ref str, 2, out minute)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.SkipWhiteSpaces();
+ if (str.Match(':')) {
+ str.SkipWhiteSpaces();
+ if (!ParseDigits(ref str, 2, out second)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ if (str.Match('.')) {
+ if (!ParseFraction(ref str, out partSecond)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.Index--;
+ }
+ str.SkipWhiteSpaces();
+ }
+ if (str.GetNext()) {
+ char ch = str.GetChar();
+ if (ch == '+' || ch == '-') {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ if (!ParseTimeZone(ref str, ref result.timeZoneOffset)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ } else if (ch == 'Z' || ch == 'z') {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeSpan.Zero;
+ result.flags |= ParseFlags.TimeZoneUtc;
+ } else {
+ str.Index--;
+ }
+ str.SkipWhiteSpaces();
+ if (str.Match('#')) {
+ if (!VerifyValidPunctuation(ref str)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.SkipWhiteSpaces();
+ }
+ if (str.Match('\0')) {
+ if (!VerifyValidPunctuation(ref str)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+ if (str.GetNext()) {
+ // If this is true, there were non-white space characters remaining in the DateTime
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+
+ DateTime time;
+ Calendar calendar = GregorianCalendar.GetDefaultInstance();
+ if (!calendar.TryToDateTime(raw.year, raw.GetNumber(0), raw.GetNumber(1),
+ hour, minute, second, 0, result.era, out time)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+
+ time = time.AddTicks((long)Math.Round(partSecond * Calendar.TicksPerSecond));
+ result.parsedDate = time;
+ if (!DetermineTimeZoneAdjustments(ref result, styles, false)) {
+ return false;
+ }
+ return true;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Parse the current word as a Hebrew number.
+ // This is used by DateTime.ParseExact().
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static bool MatchHebrewDigits(ref __DTString str, int digitLen, out int number) {
+ number = 0;
+
+ // Create a context object so that we can parse the Hebrew number text character by character.
+ HebrewNumberParsingContext context = new HebrewNumberParsingContext(0);
+
+ // Set this to ContinueParsing so that we will run the following while loop in the first time.
+ HebrewNumberParsingState state = HebrewNumberParsingState.ContinueParsing;
+
+ while (state == HebrewNumberParsingState.ContinueParsing && str.GetNext()) {
+ state = HebrewNumber.ParseByChar(str.GetChar(), ref context);
+ }
+
+ if (state == HebrewNumberParsingState.FoundEndOfHebrewNumber) {
+ // If we have reached a terminal state, update the result and returns.
+ number = context.result;
+ return (true);
+ }
+
+ // If we run out of the character before reaching FoundEndOfHebrewNumber, or
+ // the state is InvalidHebrewNumber or ContinueParsing, we fail to match a Hebrew number.
+ // Return an error.
+ return false;
+ }
+
+ /*=================================ParseDigits==================================
+ **Action: Parse the number string in __DTString that are formatted using
+ ** the following patterns:
+ ** "0", "00", and "000..0"
+ **Returns: the integer value
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if error in parsing number.
+ ==============================================================================*/
+
+ internal static bool ParseDigits(ref __DTString str, int digitLen, out int result) {
+ if (digitLen == 1) {
+ // 1 really means 1 or 2 for this call
+ return ParseDigits(ref str, 1, 2, out result);
+ }
+ else {
+ return ParseDigits(ref str, digitLen, digitLen, out result);
+ }
+ }
+
+ internal static bool ParseDigits(ref __DTString str, int minDigitLen, int maxDigitLen, out int result) {
+ Contract.Assert(minDigitLen > 0, "minDigitLen > 0");
+ Contract.Assert(maxDigitLen < 9, "maxDigitLen < 9");
+ Contract.Assert(minDigitLen <= maxDigitLen, "minDigitLen <= maxDigitLen");
+ result = 0;
+ int startingIndex = str.Index;
+ int tokenLength = 0;
+ while (tokenLength < maxDigitLen) {
+ if (!str.GetNextDigit()) {
+ str.Index--;
+ break;
+ }
+ result = result * 10 + str.GetDigit();
+ tokenLength++;
+ }
+ if (tokenLength < minDigitLen) {
+ str.Index = startingIndex;
+ return false;
+ }
+ return true;
+ }
+
+ /*=================================ParseFractionExact==================================
+ **Action: Parse the number string in __DTString that are formatted using
+ ** the following patterns:
+ ** "0", "00", and "000..0"
+ **Returns: the fraction value
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if error in parsing number.
+ ==============================================================================*/
+
+ private static bool ParseFractionExact(ref __DTString str, int maxDigitLen, ref double result) {
+ if (!str.GetNextDigit()) {
+ str.Index--;
+ return false;
+ }
+ result = str.GetDigit();
+
+ int digitLen = 1;
+ for (; digitLen < maxDigitLen; digitLen++) {
+ if (!str.GetNextDigit()) {
+ str.Index--;
+ break;
+ }
+ result = result * 10 + str.GetDigit();
+ }
+
+ result = ((double)result / Math.Pow(10, digitLen));
+ return (digitLen == maxDigitLen);
+ }
+
+ /*=================================ParseSign==================================
+ **Action: Parse a positive or a negative sign.
+ **Returns: true if postive sign. flase if negative sign.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if end of string is encountered or a sign
+ ** symbol is not found.
+ ==============================================================================*/
+
+ private static bool ParseSign(ref __DTString str, ref bool result) {
+ if (!str.GetNext()) {
+ // A sign symbol ('+' or '-') is expected. However, end of string is encountered.
+ return false;
+ }
+ char ch = str.GetChar();
+ if (ch == '+') {
+ result = true;
+ return (true);
+ } else if (ch == '-') {
+ result = false;
+ return (true);
+ }
+ // A sign symbol ('+' or '-') is expected.
+ return false;
+ }
+
+ /*=================================ParseTimeZoneOffset==================================
+ **Action: Parse the string formatted using "z", "zz", "zzz" in DateTime.Format().
+ **Returns: the TimeSpan for the parsed timezone offset.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ ** len: the repeated number of the "z"
+ **Exceptions: FormatException if errors in parsing.
+ ==============================================================================*/
+
+ private static bool ParseTimeZoneOffset(ref __DTString str, int len, ref TimeSpan result) {
+ bool isPositive = true;
+ int hourOffset;
+ int minuteOffset = 0;
+
+ switch (len) {
+ case 1:
+ case 2:
+ if (!ParseSign(ref str, ref isPositive)) {
+ return (false);
+ }
+ if (!ParseDigits(ref str, len, out hourOffset)) {
+ return (false);
+ }
+ break;
+ default:
+ if (!ParseSign(ref str, ref isPositive)) {
+ return (false);
+ }
+
+ // Parsing 1 digit will actually parse 1 or 2.
+ if (!ParseDigits(ref str, 1, out hourOffset)) {
+ return (false);
+ }
+ // ':' is optional.
+ if (str.Match(":")) {
+ // Found ':'
+ if (!ParseDigits(ref str, 2, out minuteOffset)) {
+ return (false);
+ }
+ } else {
+ // Since we can not match ':', put the char back.
+ str.Index--;
+ if (!ParseDigits(ref str, 2, out minuteOffset)) {
+ return (false);
+ }
+ }
+ break;
+ }
+ if (minuteOffset < 0 || minuteOffset >= 60) {
+ return false;
+ }
+
+ result = (new TimeSpan(hourOffset, minuteOffset, 0));
+ if (!isPositive) {
+ result = result.Negate();
+ }
+ return (true);
+ }
+
+ /*=================================MatchAbbreviatedMonthName==================================
+ **Action: Parse the abbreviated month name from string starting at str.Index.
+ **Returns: A value from 1 to 12 for the first month to the twelveth month.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if an abbreviated month name can not be found.
+ ==============================================================================*/
+
+ private static bool MatchAbbreviatedMonthName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) {
+ int maxMatchStrLen = 0;
+ result = -1;
+ if (str.GetNext()) {
+ //
+ // Scan the month names (note that some calendars has 13 months) and find
+ // the matching month name which has the max string length.
+ // We need to do this because some cultures (e.g. "cs-CZ") which have
+ // abbreviated month names with the same prefix.
+ //
+ int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12: 13);
+ for (int i = 1; i <= monthsInYear; i++) {
+ String searchStr = dtfi.GetAbbreviatedMonthName(i);
+ int matchStrLen = searchStr.Length;
+ if ( dtfi.HasSpacesInMonthNames
+ ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
+ : str.MatchSpecifiedWord(searchStr)) {
+ if (matchStrLen > maxMatchStrLen) {
+ maxMatchStrLen = matchStrLen;
+ result = i;
+ }
+ }
+ }
+
+ // Search leap year form.
+ if ((dtfi.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) {
+ int tempResult = str.MatchLongestWords(dtfi.internalGetLeapYearMonthNames(), ref maxMatchStrLen);
+ // We found a longer match in the leap year month name. Use this as the result.
+ // The result from MatchLongestWords is 0 ~ length of word array.
+ // So we increment the result by one to become the month value.
+ if (tempResult >= 0) {
+ result = tempResult + 1;
+ }
+ }
+
+
+ }
+ if (result > 0) {
+ str.Index += (maxMatchStrLen - 1);
+ return (true);
+ }
+ return false;
+ }
+
+ /*=================================MatchMonthName==================================
+ **Action: Parse the month name from string starting at str.Index.
+ **Returns: A value from 1 to 12 indicating the first month to the twelveth month.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if a month name can not be found.
+ ==============================================================================*/
+
+ private static bool MatchMonthName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) {
+ int maxMatchStrLen = 0;
+ result = -1;
+ if (str.GetNext()) {
+ //
+ // Scan the month names (note that some calendars has 13 months) and find
+ // the matching month name which has the max string length.
+ // We need to do this because some cultures (e.g. "vi-VN") which have
+ // month names with the same prefix.
+ //
+ int monthsInYear = (dtfi.GetMonthName(13).Length == 0 ? 12: 13);
+ for (int i = 1; i <= monthsInYear; i++) {
+ String searchStr = dtfi.GetMonthName(i);
+ int matchStrLen = searchStr.Length;
+ if ( dtfi.HasSpacesInMonthNames
+ ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
+ : str.MatchSpecifiedWord(searchStr)) {
+ if (matchStrLen > maxMatchStrLen) {
+ maxMatchStrLen = matchStrLen;
+ result = i;
+ }
+ }
+ }
+
+ // Search genitive form.
+ if ((dtfi.FormatFlags & DateTimeFormatFlags.UseGenitiveMonth) != 0) {
+ int tempResult = str.MatchLongestWords(dtfi.MonthGenitiveNames, ref maxMatchStrLen);
+ // We found a longer match in the genitive month name. Use this as the result.
+ // The result from MatchLongestWords is 0 ~ length of word array.
+ // So we increment the result by one to become the month value.
+ if (tempResult >= 0) {
+ result = tempResult + 1;
+ }
+ }
+
+ // Search leap year form.
+ if ((dtfi.FormatFlags & DateTimeFormatFlags.UseLeapYearMonth) != 0) {
+ int tempResult = str.MatchLongestWords(dtfi.internalGetLeapYearMonthNames(), ref maxMatchStrLen);
+ // We found a longer match in the leap year month name. Use this as the result.
+ // The result from MatchLongestWords is 0 ~ length of word array.
+ // So we increment the result by one to become the month value.
+ if (tempResult >= 0) {
+ result = tempResult + 1;
+ }
+ }
+
+
+ }
+
+ if (result > 0) {
+ str.Index += (maxMatchStrLen - 1);
+ return (true);
+ }
+ return false;
+ }
+
+ /*=================================MatchAbbreviatedDayName==================================
+ **Action: Parse the abbreviated day of week name from string starting at str.Index.
+ **Returns: A value from 0 to 6 indicating Sunday to Saturday.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if a abbreviated day of week name can not be found.
+ ==============================================================================*/
+
+ private static bool MatchAbbreviatedDayName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) {
+ int maxMatchStrLen = 0;
+ result = -1;
+ if (str.GetNext()) {
+ for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++) {
+ String searchStr = dtfi.GetAbbreviatedDayName(i);
+ int matchStrLen = searchStr.Length;
+ if ( dtfi.HasSpacesInDayNames
+ ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
+ : str.MatchSpecifiedWord(searchStr)) {
+ if (matchStrLen > maxMatchStrLen) {
+ maxMatchStrLen = matchStrLen;
+ result = (int)i;
+ }
+ }
+ }
+ }
+ if (result >= 0) {
+ str.Index += maxMatchStrLen - 1;
+ return (true);
+ }
+ return false;
+ }
+
+ /*=================================MatchDayName==================================
+ **Action: Parse the day of week name from string starting at str.Index.
+ **Returns: A value from 0 to 6 indicating Sunday to Saturday.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if a day of week name can not be found.
+ ==============================================================================*/
+
+ private static bool MatchDayName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) {
+ // Turkish (tr-TR) got day names with the same prefix.
+ int maxMatchStrLen = 0;
+ result = -1;
+ if (str.GetNext()) {
+ for (DayOfWeek i = DayOfWeek.Sunday; i <= DayOfWeek.Saturday; i++) {
+ String searchStr = dtfi.GetDayName(i);
+ int matchStrLen = searchStr.Length;
+ if ( dtfi.HasSpacesInDayNames
+ ? str.MatchSpecifiedWords(searchStr, false, ref matchStrLen)
+ : str.MatchSpecifiedWord(searchStr)) {
+ if (matchStrLen > maxMatchStrLen) {
+ maxMatchStrLen = matchStrLen;
+ result = (int)i;
+ }
+ }
+ }
+ }
+ if (result >= 0) {
+ str.Index += maxMatchStrLen - 1;
+ return (true);
+ }
+ return false;
+ }
+
+ /*=================================MatchEraName==================================
+ **Action: Parse era name from string starting at str.Index.
+ **Returns: An era value.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if an era name can not be found.
+ ==============================================================================*/
+
+ private static bool MatchEraName(ref __DTString str, DateTimeFormatInfo dtfi, ref int result) {
+ if (str.GetNext()) {
+ int[] eras = dtfi.Calendar.Eras;
+
+ if (eras != null) {
+ for (int i = 0; i < eras.Length; i++) {
+ String searchStr = dtfi.GetEraName(eras[i]);
+ if (str.MatchSpecifiedWord(searchStr)) {
+ str.Index += (searchStr.Length - 1);
+ result = eras[i];
+ return (true);
+ }
+ searchStr = dtfi.GetAbbreviatedEraName(eras[i]);
+ if (str.MatchSpecifiedWord(searchStr)) {
+ str.Index += (searchStr.Length - 1);
+ result = eras[i];
+ return (true);
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /*=================================MatchTimeMark==================================
+ **Action: Parse the time mark (AM/PM) from string starting at str.Index.
+ **Returns: TM_AM or TM_PM.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if a time mark can not be found.
+ ==============================================================================*/
+
+ private static bool MatchTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref TM result) {
+ result = TM.NotSet;
+ // In some cultures have empty strings in AM/PM mark. E.g. af-ZA (0x0436), the AM mark is "", and PM mark is "nm".
+ if (dtfi.AMDesignator.Length == 0) {
+ result = TM.AM;
+ }
+ if (dtfi.PMDesignator.Length == 0) {
+ result = TM.PM;
+ }
+
+ if (str.GetNext()) {
+ String searchStr = dtfi.AMDesignator;
+ if (searchStr.Length > 0) {
+ if (str.MatchSpecifiedWord(searchStr)) {
+ // Found an AM timemark with length > 0.
+ str.Index += (searchStr.Length - 1);
+ result = TM.AM;
+ return (true);
+ }
+ }
+ searchStr = dtfi.PMDesignator;
+ if (searchStr.Length > 0) {
+ if (str.MatchSpecifiedWord(searchStr)) {
+ // Found a PM timemark with length > 0.
+ str.Index += (searchStr.Length - 1);
+ result = TM.PM;
+ return (true);
+ }
+ }
+ str.Index--; // Undo the GetNext call.
+ }
+ if (result != TM.NotSet) {
+ // If one of the AM/PM marks is empty string, return the result.
+ return (true);
+ }
+ return false;
+ }
+
+ /*=================================MatchAbbreviatedTimeMark==================================
+ **Action: Parse the abbreviated time mark (AM/PM) from string starting at str.Index.
+ **Returns: TM_AM or TM_PM.
+ **Arguments: str: a __DTString. The parsing will start from the
+ ** next character after str.Index.
+ **Exceptions: FormatException if a abbreviated time mark can not be found.
+ ==============================================================================*/
+
+ private static bool MatchAbbreviatedTimeMark(ref __DTString str, DateTimeFormatInfo dtfi, ref TM result) {
+ // NOTENOTE : the assumption here is that abbreviated time mark is the first
+ // character of the AM/PM designator. If this invariant changes, we have to
+ // change the code below.
+ if (str.GetNext())
+ {
+ if (str.GetChar() == dtfi.AMDesignator[0]) {
+ result = TM.AM;
+ return (true);
+ }
+ if (str.GetChar() == dtfi.PMDesignator[0]) {
+ result = TM.PM;
+ return (true);
+ }
+ }
+ return false;
+ }
+
+ /*=================================CheckNewValue==================================
+ **Action: Check if currentValue is initialized. If not, return the newValue.
+ ** If yes, check if the current value is equal to newValue. Return false
+ ** if they are not equal. This is used to check the case like "d" and "dd" are both
+ ** used to format a string.
+ **Returns: the correct value for currentValue.
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+
+ private static bool CheckNewValue(ref int currentValue, int newValue, char patternChar, ref DateTimeResult result) {
+ if (currentValue == -1) {
+ currentValue = newValue;
+ return (true);
+ } else {
+ if (newValue != currentValue) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", patternChar);
+ return (false);
+ }
+ }
+ return (true);
+ }
+
+ private static DateTime GetDateTimeNow(ref DateTimeResult result, ref DateTimeStyles styles) {
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0) {
+ // use the supplied offset to calculate 'Now'
+ return new DateTime(DateTime.UtcNow.Ticks + result.timeZoneOffset.Ticks, DateTimeKind.Unspecified);
+ }
+ else if ((styles & DateTimeStyles.AssumeUniversal) != 0) {
+ // assume the offset is Utc
+ return DateTime.UtcNow;
+ }
+ }
+
+ // assume the offset is Local
+ return DateTime.Now;
+ }
+
+ private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles) {
+
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ // DateTimeOffset.Parse should allow dates without a year, but only if there is also no time zone marker;
+ // e.g. "May 1 5pm" is OK, but "May 1 5pm -08:30" is not. This is somewhat pragmatic, since we would
+ // have to rearchitect parsing completely to allow this one case to correctly handle things like leap
+ // years and leap months. Is is an extremely corner case, and DateTime is basically incorrect in that
+ // case today.
+ //
+ // values like "11:00Z" or "11:00 -3:00" are also acceptable
+ //
+ // if ((month or day is set) and (year is not set and time zone is set))
+ //
+ if ( ((result.Month != -1) || (result.Day != -1))
+ && ((result.Year == -1 || ((result.flags & ParseFlags.YearDefault) != 0)) && (result.flags & ParseFlags.TimeZoneUsed) != 0) ) {
+ result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", null);
+ return false;
+ }
+ }
+
+
+ if ((result.Year == -1) || (result.Month == -1) || (result.Day == -1)) {
+ /*
+ The following table describes the behaviors of getting the default value
+ when a certain year/month/day values are missing.
+
+ An "X" means that the value exists. And "--" means that value is missing.
+
+ Year Month Day => ResultYear ResultMonth ResultDay Note
+
+ X X X Parsed year Parsed month Parsed day
+ X X -- Parsed Year Parsed month First day If we have year and month, assume the first day of that month.
+ X -- X Parsed year First month Parsed day If the month is missing, assume first month of that year.
+ X -- -- Parsed year First month First day If we have only the year, assume the first day of that year.
+
+ -- X X CurrentYear Parsed month Parsed day If the year is missing, assume the current year.
+ -- X -- CurrentYear Parsed month First day If we have only a month value, assume the current year and current day.
+ -- -- X CurrentYear First month Parsed day If we have only a day value, assume current year and first month.
+ -- -- -- CurrentYear Current month Current day So this means that if the date string only contains time, you will get current date.
+
+ */
+
+ DateTime now = GetDateTimeNow(ref result, ref styles);
+ if (result.Month == -1 && result.Day == -1) {
+ if (result.Year == -1) {
+ if ((styles & DateTimeStyles.NoCurrentDateDefault) != 0) {
+ // If there is no year/month/day values, and NoCurrentDateDefault flag is used,
+ // set the year/month/day value to the beginning year/month/day of DateTime().
+ // Note we should be using Gregorian for the year/month/day.
+ cal = GregorianCalendar.GetDefaultInstance();
+ result.Year = result.Month = result.Day = 1;
+ } else {
+ // Year/Month/Day are all missing.
+ result.Year = cal.GetYear(now);
+ result.Month = cal.GetMonth(now);
+ result.Day = cal.GetDayOfMonth(now);
+ }
+ } else {
+ // Month/Day are both missing.
+ result.Month = 1;
+ result.Day = 1;
+ }
+ } else {
+ if (result.Year == -1) {
+ result.Year = cal.GetYear(now);
+ }
+ if (result.Month == -1) {
+ result.Month = 1;
+ }
+ if (result.Day == -1) {
+ result.Day = 1;
+ }
+ }
+ }
+ // Set Hour/Minute/Second to zero if these value are not in str.
+ if (result.Hour == -1) result.Hour = 0;
+ if (result.Minute == -1) result.Minute = 0;
+ if (result.Second == -1) result.Second = 0;
+ if (result.era == -1) result.era = Calendar.CurrentEra;
+ return true;
+ }
+
+ // Expand a pre-defined format string (like "D" for long date) to the real format that
+ // we are going to use in the date time parsing.
+ // This method also set the dtfi according/parseInfo to some special pre-defined
+ // formats.
+ //
+ private static String ExpandPredefinedFormat(String format, ref DateTimeFormatInfo dtfi, ref ParsingInfo parseInfo, ref DateTimeResult result) {
+ //
+ // Check the format to see if we need to override the dtfi to be InvariantInfo,
+ // and see if we need to set up the userUniversalTime flag.
+ //
+ switch (format[0]) {
+ case 'o':
+ case 'O': // Round Trip Format
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ break;
+ case 'r':
+ case 'R': // RFC 1123 Standard. (in Universal time)
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ result.flags |= ParseFlags.Rfc1123Pattern;
+ }
+ break;
+ case 's': // Sortable format (in local time)
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ break;
+ case 'u': // Universal time format in sortable format.
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ dtfi = DateTimeFormatInfo.InvariantInfo;
+
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ result.flags |= ParseFlags.UtcSortPattern;
+ }
+ break;
+ case 'U': // Universal time format with culture-dependent format.
+ parseInfo.calendar = GregorianCalendar.GetDefaultInstance();
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(0);
+ result.flags |= ParseFlags.TimeZoneUtc;
+ if (dtfi.Calendar.GetType() != typeof(GregorianCalendar)) {
+ dtfi = (DateTimeFormatInfo)dtfi.Clone();
+ dtfi.Calendar = GregorianCalendar.GetDefaultInstance();
+ }
+ break;
+ }
+
+ //
+ // Expand the pre-defined format character to the real format from DateTimeFormatInfo.
+ //
+ return (DateTimeFormat.GetRealFormat(format, dtfi));
+ }
+
+
+
+
+
+ // Given a specified format character, parse and update the parsing result.
+ //
+ private static bool ParseByFormat(
+ ref __DTString str,
+ ref __DTString format,
+ ref ParsingInfo parseInfo,
+ DateTimeFormatInfo dtfi,
+ ref DateTimeResult result) {
+
+ int tokenLen = 0;
+ int tempYear = 0, tempMonth = 0, tempDay = 0, tempDayOfWeek = 0, tempHour = 0, tempMinute = 0, tempSecond = 0;
+ double tempFraction = 0;
+ TM tempTimeMark = 0;
+
+ char ch = format.GetChar();
+
+ switch (ch) {
+ case 'y':
+ tokenLen = format.GetRepeatCount();
+ bool parseResult;
+ if (dtfi.HasForceTwoDigitYears) {
+ parseResult = ParseDigits(ref str, 1, 4, out tempYear);
+ }
+ else {
+ if (tokenLen <= 2) {
+ parseInfo.fUseTwoDigitYear = true;
+ }
+ parseResult = ParseDigits(ref str, tokenLen, out tempYear);
+ }
+ if (!parseResult && parseInfo.fCustomNumberParser) {
+ parseResult = parseInfo.parseNumberDelegate(ref str, tokenLen, out tempYear);
+ }
+ if (!parseResult) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if (!CheckNewValue(ref result.Year, tempYear, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 'M':
+ tokenLen = format.GetRepeatCount();
+ if (tokenLen <= 2) {
+ if (!ParseDigits(ref str, tokenLen, out tempMonth)) {
+ if (!parseInfo.fCustomNumberParser ||
+ !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempMonth)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+ } else {
+ if (tokenLen == 3) {
+ if (!MatchAbbreviatedMonthName(ref str, dtfi, ref tempMonth)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ } else {
+ if (!MatchMonthName(ref str, dtfi, ref tempMonth)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+ result.flags |= ParseFlags.ParsedMonthName;
+ }
+ if (!CheckNewValue(ref result.Month, tempMonth, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 'd':
+ // Day & Day of week
+ tokenLen = format.GetRepeatCount();
+ if (tokenLen <= 2) {
+ // "d" & "dd"
+
+ if (!ParseDigits(ref str, tokenLen, out tempDay)) {
+ if (!parseInfo.fCustomNumberParser ||
+ !parseInfo.parseNumberDelegate(ref str, tokenLen, out tempDay)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+ if (!CheckNewValue(ref result.Day, tempDay, ch, ref result)) {
+ return (false);
+ }
+ } else {
+ if (tokenLen == 3) {
+ // "ddd"
+ if (!MatchAbbreviatedDayName(ref str, dtfi, ref tempDayOfWeek)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ } else {
+ // "dddd*"
+ if (!MatchDayName(ref str, dtfi, ref tempDayOfWeek)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+ if (!CheckNewValue(ref parseInfo.dayOfWeek, tempDayOfWeek, ch, ref result)) {
+ return (false);
+ }
+ }
+ break;
+ case 'g':
+ tokenLen = format.GetRepeatCount();
+ // Put the era value in result.era.
+ if (!MatchEraName(ref str, dtfi, ref result.era)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ break;
+ case 'h':
+ parseInfo.fUseHour12 = true;
+ tokenLen = format.GetRepeatCount();
+ if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempHour)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 'H':
+ tokenLen = format.GetRepeatCount();
+ if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempHour)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if (!CheckNewValue(ref result.Hour, tempHour, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 'm':
+ tokenLen = format.GetRepeatCount();
+ if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempMinute)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if (!CheckNewValue(ref result.Minute, tempMinute, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 's':
+ tokenLen = format.GetRepeatCount();
+ if (!ParseDigits(ref str, (tokenLen < 2? 1 : 2), out tempSecond)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if (!CheckNewValue(ref result.Second, tempSecond, ch, ref result)) {
+ return (false);
+ }
+ break;
+ case 'f':
+ case 'F':
+ tokenLen = format.GetRepeatCount();
+ if (tokenLen <= DateTimeFormat.MaxSecondsFractionDigits) {
+ if (!ParseFractionExact(ref str, tokenLen, ref tempFraction)) {
+ if (ch == 'f') {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+ if (result.fraction < 0) {
+ result.fraction = tempFraction;
+ } else {
+ if (tempFraction != result.fraction) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch);
+ return (false);
+ }
+ }
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ break;
+ case 't':
+ // AM/PM designator
+ tokenLen = format.GetRepeatCount();
+ if (tokenLen == 1) {
+ if (!MatchAbbreviatedTimeMark(ref str, dtfi, ref tempTimeMark)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ } else {
+ if (!MatchTimeMark(ref str, dtfi, ref tempTimeMark)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ }
+
+ if (parseInfo.timeMark == TM.NotSet) {
+ parseInfo.timeMark = tempTimeMark;
+ }
+ else {
+ if (parseInfo.timeMark != tempTimeMark) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", ch);
+ return (false);
+ }
+ }
+ break;
+ case 'z':
+ // timezone offset
+ tokenLen = format.GetRepeatCount();
+ {
+ TimeSpan tempTimeZoneOffset = new TimeSpan(0);
+ if (!ParseTimeZoneOffset(ref str, tokenLen, ref tempTimeZoneOffset)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'z');
+ return (false);
+ }
+ result.timeZoneOffset = tempTimeZoneOffset;
+ result.flags |= ParseFlags.TimeZoneUsed;
+ }
+ break;
+ case 'Z':
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'Z');
+ return (false);
+ }
+
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(0);
+ result.flags |= ParseFlags.TimeZoneUtc;
+
+ // The updating of the indexes is to reflect that ParseExact MatchXXX methods assume that
+ // they need to increment the index and Parse GetXXX do not. Since we are calling a Parse
+ // method from inside ParseExact we need to adjust this. Long term, we should try to
+ // eliminate this discrepancy.
+ str.Index++;
+ if (!GetTimeZoneName(ref str)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ str.Index--;
+ break;
+ case 'K':
+ // This should parse either as a blank, the 'Z' character or a local offset like "-07:00"
+ if (str.Match('Z')) {
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && result.timeZoneOffset != TimeSpan.Zero) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K');
+ return (false);
+ }
+
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = new TimeSpan(0);
+ result.flags |= ParseFlags.TimeZoneUtc;
+ }
+ else if (str.Match('+') || str.Match('-')) {
+ str.Index--; // Put the character back for the parser
+ TimeSpan tempTimeZoneOffset = new TimeSpan(0);
+ if (!ParseTimeZoneOffset(ref str, 3, ref tempTimeZoneOffset)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return (false);
+ }
+ if ((result.flags & ParseFlags.TimeZoneUsed) != 0 && tempTimeZoneOffset != result.timeZoneOffset) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_RepeatDateTimePattern", 'K');
+ return (false);
+ }
+ result.timeZoneOffset = tempTimeZoneOffset;
+ result.flags |= ParseFlags.TimeZoneUsed;
+ }
+ // Otherwise it is unspecified and we consume no characters
+ break;
+ case ':':
+ // We match the separator in time pattern with the character in the time string if both equal to ':' or the date separator is matching the characters in the date string
+ // We have to exclude the case when the time separator is more than one character and starts with ':' something like "::" for instance.
+ if (((dtfi.TimeSeparator.Length > 1 && dtfi.TimeSeparator[0] == ':') || !str.Match(':')) &&
+ !str.Match(dtfi.TimeSeparator)) {
+ // A time separator is expected.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ break;
+ case '/':
+ // We match the separator in date pattern with the character in the date string if both equal to '/' or the date separator is matching the characters in the date string
+ // We have to exclude the case when the date separator is more than one character and starts with '/' something like "//" for instance.
+ if (((dtfi.DateSeparator.Length > 1 && dtfi.DateSeparator[0] == '/') || !str.Match('/')) &&
+ !str.Match(dtfi.DateSeparator))
+ {
+ // A date separator is expected.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ break;
+ case '\"':
+ case '\'':
+ StringBuilder enquotedString = new StringBuilder();
+ // Use ParseQuoteString so that we can handle escape characters within the quoted string.
+ if (!TryParseQuoteString(format.Value, format.Index, enquotedString, out tokenLen)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", ch);
+ return (false);
+ }
+ format.Index += tokenLen - 1;
+
+ // Some cultures uses space in the quoted string. E.g. Spanish has long date format as:
+ // "dddd, dd' de 'MMMM' de 'yyyy". When inner spaces flag is set, we should skip whitespaces if there is space
+ // in the quoted string.
+ String quotedStr = enquotedString.ToString();
+
+ for (int i = 0; i < quotedStr.Length; i++) {
+ if (quotedStr[i] == ' ' && parseInfo.fAllowInnerWhite) {
+ str.SkipWhiteSpaces();
+ } else if (!str.Match(quotedStr[i])) {
+ // Can not find the matching quoted string.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+
+ // The "r" and "u" formats incorrectly quoted 'GMT' and 'Z', respectively. We cannot
+ // correct this mistake for DateTime.ParseExact for compatibility reasons, but we can
+ // fix it for DateTimeOffset.ParseExact as DateTimeOffset has not been publically released
+ // with this issue.
+ if ((result.flags & ParseFlags.CaptureOffset) != 0) {
+ if ((result.flags & ParseFlags.Rfc1123Pattern) != 0 && quotedStr == GMTName) {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeSpan.Zero;
+ }
+ else if ((result.flags & ParseFlags.UtcSortPattern) != 0 && quotedStr == ZuluName) {
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeSpan.Zero;
+ }
+ }
+
+ break;
+ case '%':
+ // Skip this so we can get to the next pattern character.
+ // Used in case like "%d", "%y"
+
+ // Make sure the next character is not a '%' again.
+ if (format.Index >= format.Value.Length - 1 || format.Value[format.Index + 1] == '%') {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+ break;
+ case '\\':
+ // Escape character. For example, "\d".
+ // Get the next character in format, and see if we can
+ // find a match in str.
+ if (format.GetNext()) {
+ if (!str.Match(format.GetChar())) {
+ // Can not find a match for the escaped character.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ } else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+ break;
+ case '.':
+ if (!str.Match(ch)) {
+ if (format.GetNext()) {
+ // If we encounter the pattern ".F", and the dot is not present, it is an optional
+ // second fraction and we can skip this format.
+ if (format.Match('F')) {
+ format.GetRepeatCount();
+ break;
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ break;
+ default:
+ if (ch == ' ') {
+ if (parseInfo.fAllowInnerWhite) {
+ // Skip whitespaces if AllowInnerWhite.
+ // Do nothing here.
+ } else {
+ if (!str.Match(ch)) {
+ // If the space does not match, and trailing space is allowed, we do
+ // one more step to see if the next format character can lead to
+ // successful parsing.
+ // This is used to deal with special case that a empty string can match
+ // a specific pattern.
+ // The example here is af-ZA, which has a time format like "hh:mm:ss tt". However,
+ // its AM symbol is "" (empty string). If fAllowTrailingWhite is used, and time is in
+ // the AM, we will trim the whitespaces at the end, which will lead to a failure
+ // when we are trying to match the space before "tt".
+ if (parseInfo.fAllowTrailingWhite) {
+ if (format.GetNext()) {
+ if (ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) {
+ return (true);
+ }
+ }
+ }
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ // Found a macth.
+ }
+ } else {
+ if (format.MatchSpecifiedWord(GMTName)) {
+ format.Index += (GMTName.Length - 1);
+ // Found GMT string in format. This means the DateTime string
+ // is in GMT timezone.
+ result.flags |= ParseFlags.TimeZoneUsed;
+ result.timeZoneOffset = TimeSpan.Zero;
+ if (!str.Match(GMTName)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ } else if (!str.Match(ch)) {
+ // ch is expected.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+ break;
+ } // switch
+ return (true);
+ }
+
+ //
+ // The pos should point to a quote character. This method will
+ // get the string enclosed by the quote character.
+ //
+ internal static bool TryParseQuoteString(String format, int pos, StringBuilder result, out int returnValue) {
+ //
+ // NOTE : pos will be the index of the quote character in the 'format' string.
+ //
+ returnValue = 0;
+ int formatLen = format.Length;
+ int beginPos = pos;
+ char quoteChar = format[pos++]; // Get the character used to quote the following string.
+
+ bool foundQuote = false;
+ while (pos < formatLen) {
+ char ch = format[pos++];
+ if (ch == quoteChar) {
+ foundQuote = true;
+ break;
+ }
+ else if (ch == '\\') {
+ // The following are used to support escaped character.
+ // Escaped character is also supported in the quoted string.
+ // Therefore, someone can use a format like "'minute:' mm\"" to display:
+ // minute: 45"
+ // because the second double quote is escaped.
+ if (pos < formatLen) {
+ result.Append(format[pos++]);
+ } else {
+ //
+ // This means that '\' is at the end of the formatting string.
+ //
+ return false;
+ }
+ } else {
+ result.Append(ch);
+ }
+ }
+
+ if (!foundQuote) {
+ // Here we can't find the matching quote.
+ return false;
+ }
+
+ //
+ // Return the character count including the begin/end quote characters and enclosed string.
+ //
+ returnValue = (pos - beginPos);
+ return true;
+ }
+
+
+
+
+ /*=================================DoStrictParse==================================
+ **Action: Do DateTime parsing using the format in formatParam.
+ **Returns: The parsed DateTime.
+ **Arguments:
+ **Exceptions:
+ **
+ **Notes:
+ ** When the following general formats are used, InvariantInfo is used in dtfi:
+ ** 'r', 'R', 's'.
+ ** When the following general formats are used, the time is assumed to be in Universal time.
+ **
+ **Limitations:
+ ** Only GregarianCalendar is supported for now.
+ ** Only support GMT timezone.
+ ==============================================================================*/
+
+ private static bool DoStrictParse(
+ String s,
+ String formatParam,
+ DateTimeStyles styles,
+ DateTimeFormatInfo dtfi,
+ ref DateTimeResult result) {
+
+
+
+ ParsingInfo parseInfo = new ParsingInfo();
+ parseInfo.Init();
+
+ parseInfo.calendar = dtfi.Calendar;
+ parseInfo.fAllowInnerWhite = ((styles & DateTimeStyles.AllowInnerWhite) != 0);
+ parseInfo.fAllowTrailingWhite = ((styles & DateTimeStyles.AllowTrailingWhite) != 0);
+
+ // We need the original values of the following two below.
+ String originalFormat = formatParam;
+
+ if (formatParam.Length == 1) {
+ if (((result.flags & ParseFlags.CaptureOffset) != 0) && formatParam[0] == 'U') {
+ // The 'U' format is not allowed for DateTimeOffset
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier", null);
+ return false;
+ }
+ formatParam = ExpandPredefinedFormat(formatParam, ref dtfi, ref parseInfo, ref result);
+ }
+
+ bool bTimeOnly = false;
+ result.calendar = parseInfo.calendar;
+
+ if (parseInfo.calendar.ID == Calendar.CAL_HEBREW) {
+ parseInfo.parseNumberDelegate = m_hebrewNumberParser;
+ parseInfo.fCustomNumberParser = true;
+ }
+
+ // Reset these values to negative one so that we could throw exception
+ // if we have parsed every item twice.
+ result.Hour = result.Minute = result.Second = -1;
+
+ __DTString format = new __DTString(formatParam, dtfi, false);
+ __DTString str = new __DTString(s, dtfi, false);
+
+ if (parseInfo.fAllowTrailingWhite) {
+ // Trim trailing spaces if AllowTrailingWhite.
+ format.TrimTail();
+ format.RemoveTrailingInQuoteSpaces();
+ str.TrimTail();
+ }
+
+ if ((styles & DateTimeStyles.AllowLeadingWhite) != 0) {
+ format.SkipWhiteSpaces();
+ format.RemoveLeadingInQuoteSpaces();
+ str.SkipWhiteSpaces();
+ }
+
+ //
+ // Scan every character in format and match the pattern in str.
+ //
+ while (format.GetNext()) {
+ // We trim inner spaces here, so that we will not eat trailing spaces when
+ // AllowTrailingWhite is not used.
+ if (parseInfo.fAllowInnerWhite) {
+ str.SkipWhiteSpaces();
+ }
+ if (!ParseByFormat(ref str, ref format, ref parseInfo, dtfi, ref result)) {
+ return (false);
+ }
+ }
+
+ if (str.Index < str.Value.Length - 1) {
+ // There are still remaining character in str.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+
+ if (parseInfo.fUseTwoDigitYear && ((dtfi.FormatFlags & DateTimeFormatFlags.UseHebrewRule) == 0)) {
+ // A two digit year value is expected. Check if the parsed year value is valid.
+ if (result.Year >= 100) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ try {
+ result.Year = parseInfo.calendar.ToFourDigitYear(result.Year);
+ }
+ catch (ArgumentOutOfRangeException e) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", e);
+ return false;
+ }
+ }
+
+ if (parseInfo.fUseHour12) {
+ if (parseInfo.timeMark == TM.NotSet) {
+ // hh is used, but no AM/PM designator is specified.
+ // Assume the time is AM.
+ // Don't throw exceptions in here becasue it is very confusing for the caller.
+ // I always got confused myself when I use "hh:mm:ss" to parse a time string,
+ // and ParseExact() throws on me (because I didn't use the 24-hour clock 'HH').
+ parseInfo.timeMark = TM.AM;
+ }
+ if (result.Hour > 12) {
+ // AM/PM is used, but the value for HH is too big.
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ if (parseInfo.timeMark == TM.AM) {
+ if (result.Hour == 12) {
+ result.Hour = 0;
+ }
+ } else {
+ result.Hour = (result.Hour == 12) ? 12 : result.Hour + 12;
+ }
+ }
+ else
+ {
+ // Military (24-hour time) mode
+ //
+ // AM cannot be set with a 24-hour time like 17:15.
+ // PM cannot be set with a 24-hour time like 03:15.
+ if ( (parseInfo.timeMark == TM.AM && result.Hour >= 12)
+ ||(parseInfo.timeMark == TM.PM && result.Hour < 12)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDateTime", null);
+ return false;
+ }
+ }
+
+
+ // Check if the parased string only contains hour/minute/second values.
+ bTimeOnly = (result.Year == -1 && result.Month == -1 && result.Day == -1);
+ if (!CheckDefaultDateTime(ref result, ref parseInfo.calendar, styles)) {
+ return false;
+ }
+
+ if (!bTimeOnly && dtfi.HasYearMonthAdjustment) {
+ if (!dtfi.YearMonthAdjustment(ref result.Year, ref result.Month, ((result.flags & ParseFlags.ParsedMonthName) != 0))) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ }
+ if (!parseInfo.calendar.TryToDateTime(result.Year, result.Month, result.Day,
+ result.Hour, result.Minute, result.Second, 0, result.era, out result.parsedDate)) {
+ result.SetFailure(ParseFailureKind.FormatBadDateTimeCalendar, "Format_BadDateTimeCalendar", null);
+ return false;
+ }
+ if (result.fraction > 0) {
+ result.parsedDate = result.parsedDate.AddTicks((long)Math.Round(result.fraction * Calendar.TicksPerSecond));
+ }
+
+ //
+ // We have to check day of week before we adjust to the time zone.
+ // It is because the value of day of week may change after adjusting
+ // to the time zone.
+ //
+ if (parseInfo.dayOfWeek != -1) {
+ //
+ // Check if day of week is correct.
+ //
+ if (parseInfo.dayOfWeek != (int)parseInfo.calendar.GetDayOfWeek(result.parsedDate)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadDayOfWeek", null);
+ return false;
+ }
+ }
+
+
+ if (!DetermineTimeZoneAdjustments(ref result, styles, bTimeOnly)) {
+ return false;
+ }
+ return true;
+ }
+
+ private static Exception GetDateTimeParseException(ref DateTimeResult result) {
+ switch (result.failure) {
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(result.failureArgumentName, Environment.GetResourceString(result.failureMessageID));
+ case ParseFailureKind.Format:
+ return new FormatException(Environment.GetResourceString(result.failureMessageID));
+ case ParseFailureKind.FormatWithParameter:
+ return new FormatException(Environment.GetResourceString(result.failureMessageID, result.failureMessageFormatArgument));
+ case ParseFailureKind.FormatBadDateTimeCalendar:
+ return new FormatException(Environment.GetResourceString(result.failureMessageID, result.calendar));
+ default:
+ Contract.Assert(false, "Unkown DateTimeParseFailure: " + result);
+ return null;
+
+ }
+ }
+
+ // Builds with _LOGGING defined (x86dbg, amd64chk, etc) support tracing
+ // Set the following internal-only/unsupported environment variables to enable DateTime tracing to the console:
+ //
+ // COMPlus_LogEnable=1
+ // COMPlus_LogToConsole=1
+ // COMPlus_LogLevel=9
+ // COMPlus_ManagedLogFacility=0x00001000
+ [Pure]
+ [Conditional("_LOGGING")]
+ internal static void LexTraceExit(string message, DS dps) {
+#if _LOGGING
+ if (!_tracingEnabled)
+ return;
+ BCLDebug.Trace("DATETIME", "[DATETIME] Lex return {0}, DS.{1}", message, dps);
+#endif // _LOGGING
+ }
+ [Pure]
+ [Conditional("_LOGGING")]
+ internal static void PTSTraceExit(DS dps, bool passed) {
+#if _LOGGING
+ if (!_tracingEnabled)
+ return;
+ BCLDebug.Trace("DATETIME", "[DATETIME] ProcessTerminalState {0} @ DS.{1}", passed ? "passed" : "failed", dps);
+#endif // _LOGGING
+ }
+ [Pure]
+ [Conditional("_LOGGING")]
+ internal static void TPTraceExit(string message, DS dps) {
+#if _LOGGING
+ if (!_tracingEnabled)
+ return;
+ BCLDebug.Trace("DATETIME", "[DATETIME] TryParse return {0}, DS.{1}", message, dps);
+#endif // _LOGGING
+ }
+ [Pure]
+ [Conditional("_LOGGING")]
+ internal static void DTFITrace(DateTimeFormatInfo dtfi) {
+#if _LOGGING
+ if (!_tracingEnabled)
+ return;
+
+ BCLDebug.Trace("DATETIME", "[DATETIME] DateTimeFormatInfo Properties");
+#if !FEATURE_COREFX_GLOBALIZATION
+ BCLDebug.Trace("DATETIME", " NativeCalendarName {0}", Hex(dtfi.NativeCalendarName));
+#endif
+ BCLDebug.Trace("DATETIME", " AMDesignator {0}", Hex(dtfi.AMDesignator));
+ BCLDebug.Trace("DATETIME", " PMDesignator {0}", Hex(dtfi.PMDesignator));
+ BCLDebug.Trace("DATETIME", " TimeSeparator {0}", Hex(dtfi.TimeSeparator));
+ BCLDebug.Trace("DATETIME", " AbbrvDayNames {0}", Hex(dtfi.AbbreviatedDayNames));
+ BCLDebug.Trace("DATETIME", " ShortestDayNames {0}", Hex(dtfi.ShortestDayNames));
+ BCLDebug.Trace("DATETIME", " DayNames {0}", Hex(dtfi.DayNames));
+ BCLDebug.Trace("DATETIME", " AbbrvMonthNames {0}", Hex(dtfi.AbbreviatedMonthNames));
+ BCLDebug.Trace("DATETIME", " MonthNames {0}", Hex(dtfi.MonthNames));
+ BCLDebug.Trace("DATETIME", " AbbrvMonthGenNames {0}", Hex(dtfi.AbbreviatedMonthGenitiveNames));
+ BCLDebug.Trace("DATETIME", " MonthGenNames {0}", Hex(dtfi.MonthGenitiveNames));
+#endif // _LOGGING
+ }
+#if _LOGGING
+ [Pure]
+ // return a string in the form: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ internal static string Hex(string[] strs) {
+ if (strs == null || strs.Length == 0)
+ return String.Empty;
+ if (strs.Length == 1)
+ return Hex(strs[0]);
+
+ int curLineLength = 0;
+ int maxLineLength = 55;
+ int newLinePadding = 20;
+
+
+ //invariant: strs.Length >= 2
+ StringBuilder buffer = new StringBuilder();
+ buffer.Append(Hex(strs[0]));
+ curLineLength = buffer.Length;
+ String s;
+
+ for (int i = 1; i < strs.Length-1; i++) {
+ s = Hex(strs[i]);
+
+ if (s.Length > maxLineLength || (curLineLength + s.Length + 2) > maxLineLength) {
+ buffer.Append(',');
+ buffer.Append(Environment.NewLine);
+ buffer.Append(' ', newLinePadding);
+ curLineLength = 0;
+ }
+ else {
+ buffer.Append(", ");
+ curLineLength += 2;
+ }
+ buffer.Append(s);
+ curLineLength += s.Length;
+ }
+
+ buffer.Append(',');
+ s = Hex(strs[strs.Length-1]);
+ if (s.Length > maxLineLength || (curLineLength + s.Length + 6) > maxLineLength) {
+ buffer.Append(Environment.NewLine);
+ buffer.Append(' ', newLinePadding);
+ }
+ else {
+ buffer.Append(' ');
+ }
+ buffer.Append(s);
+ return buffer.ToString();
+ }
+ [Pure]
+ // return a string in the form: "Sun"
+ internal static string Hex(string str) {
+ StringBuilder buffer = new StringBuilder();
+ buffer.Append("\"");
+ for (int i = 0; i < str.Length; i++) {
+ if (str[i] <= '\x007f')
+ buffer.Append(str[i]);
+ else
+ buffer.Append("\\u" + ((int)str[i]).ToString("x4", CultureInfo.InvariantCulture));
+ }
+ buffer.Append("\"");
+ return buffer.ToString();
+ }
+ [Pure]
+ // return an unicode escaped string form of char c
+ internal static String Hex(char c) {
+ if (c <= '\x007f')
+ return c.ToString(CultureInfo.InvariantCulture);
+ else
+ return "\\u" + ((int)c).ToString("x4", CultureInfo.InvariantCulture);
+ }
+
+ internal static bool _tracingEnabled = BCLDebug.CheckEnabled("DATETIME");
+#endif // _LOGGING
+ }
+
+
+ //
+ // This is a string parsing helper which wraps a String object.
+ // It has a Index property which tracks
+ // the current parsing pointer of the string.
+ //
+ internal
+ struct __DTString
+ {
+
+ //
+ // Value propery: stores the real string to be parsed.
+ //
+ internal String Value;
+
+ //
+ // Index property: points to the character that we are currently parsing.
+ //
+ internal int Index;
+
+ // The length of Value string.
+ internal int len;
+
+ // The current chracter to be looked at.
+ internal char m_current;
+
+ private CompareInfo m_info;
+ // Flag to indicate if we encouter an digit, we should check for token or not.
+ // In some cultures, such as mn-MN, it uses "\x0031\x00a0\x0434\x04af\x0433\x044d\x044d\x0440\x00a0\x0441\x0430\x0440" in month names.
+ private bool m_checkDigitToken;
+
+ internal __DTString(String str, DateTimeFormatInfo dtfi, bool checkDigitToken) : this (str, dtfi)
+ {
+ m_checkDigitToken = checkDigitToken;
+ }
+
+ internal __DTString(String str, DateTimeFormatInfo dtfi)
+ {
+ Index = -1;
+ Value = str;
+ len = Value.Length;
+
+ m_current = '\0';
+ if (dtfi != null)
+ {
+ m_info = dtfi.CompareInfo;
+ m_checkDigitToken = ((dtfi.FormatFlags & DateTimeFormatFlags.UseDigitPrefixInTokens) != 0);
+ } else
+ {
+ m_info = Thread.CurrentThread.CurrentCulture.CompareInfo;
+ m_checkDigitToken = false;
+ }
+ }
+
+ internal CompareInfo CompareInfo
+ {
+ get { return m_info; }
+ }
+
+ //
+ // Advance the Index.
+ // Return true if Index is NOT at the end of the string.
+ //
+ // Typical usage:
+ // while (str.GetNext())
+ // {
+ // char ch = str.GetChar()
+ // }
+ internal bool GetNext() {
+ Index++;
+ if (Index < len) {
+ m_current = Value[Index];
+ return (true);
+ }
+ return (false);
+ }
+
+ internal bool AtEnd()
+ {
+ return Index < len ? false : true;
+ }
+
+ internal bool Advance(int count) {
+ Contract.Assert(Index + count <= len, "__DTString::Advance: Index + count <= len");
+ Index += count;
+ if (Index < len) {
+ m_current = Value[Index];
+ return (true);
+ }
+ return (false);
+ }
+
+
+ // Used by DateTime.Parse() to get the next token.
+ [System.Security.SecurityCritical] // auto-generated
+ internal void GetRegularToken(out TokenType tokenType, out int tokenValue, DateTimeFormatInfo dtfi) {
+ tokenValue = 0;
+ if (Index >= len) {
+ tokenType = TokenType.EndOfString;
+ return;
+ }
+
+ tokenType = TokenType.UnknownToken;
+
+Start:
+ if (DateTimeParse.IsDigit(m_current)) {
+ // This is a digit.
+ tokenValue = m_current - '0';
+ int value;
+ int start = Index;
+
+ //
+ // Collect other digits.
+ //
+ while (++Index < len)
+ {
+ m_current = Value[Index];
+ value = m_current - '0';
+ if (value >= 0 && value <= 9) {
+ tokenValue = tokenValue * 10 + value;
+ } else {
+ break;
+ }
+ }
+ if (Index - start > DateTimeParse.MaxDateTimeNumberDigits) {
+ tokenType = TokenType.NumberToken;
+ tokenValue = -1;
+ } else if (Index - start < 3) {
+ tokenType = TokenType.NumberToken;
+ } else {
+ // If there are more than 3 digits, assume that it's a year value.
+ tokenType = TokenType.YearNumberToken;
+ }
+ if (m_checkDigitToken)
+ {
+ int save = Index;
+ char saveCh = m_current;
+ // Re-scan using the staring Index to see if this is a token.
+ Index = start; // To include the first digit.
+ m_current = Value[Index];
+ TokenType tempType;
+ int tempValue;
+ // This DTFI has tokens starting with digits.
+ // E.g. mn-MN has month name like "\x0031\x00a0\x0434\x04af\x0433\x044d\x044d\x0440\x00a0\x0441\x0430\x0440"
+ if (dtfi.Tokenize(TokenType.RegularTokenMask, out tempType, out tempValue, ref this))
+ {
+ tokenType = tempType;
+ tokenValue = tempValue;
+ // This is a token, so the Index has been advanced propertly in DTFI.Tokenizer().
+ } else
+ {
+ // Use the number token value.
+ // Restore the index.
+ Index = save;
+ m_current = saveCh;
+ }
+
+ }
+
+ } else if (Char.IsWhiteSpace( m_current)) {
+ // Just skip to the next character.
+ while (++Index < len) {
+ m_current = Value[Index];
+ if (!(Char.IsWhiteSpace(m_current))) {
+ goto Start;
+ }
+ }
+ // We have reached the end of string.
+ tokenType = TokenType.EndOfString;
+ } else {
+ dtfi.Tokenize(TokenType.RegularTokenMask, out tokenType, out tokenValue, ref this);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal TokenType GetSeparatorToken(DateTimeFormatInfo dtfi, out int indexBeforeSeparator, out char charBeforeSeparator) {
+ indexBeforeSeparator = Index;
+ charBeforeSeparator = m_current;
+ TokenType tokenType;
+ if (!SkipWhiteSpaceCurrent()) {
+ // Reach the end of the string.
+ return (TokenType.SEP_End);
+ }
+ if (!DateTimeParse.IsDigit(m_current)) {
+ // Not a digit. Tokenize it.
+ int tokenValue;
+ bool found = dtfi.Tokenize(TokenType.SeparatorTokenMask, out tokenType, out tokenValue, ref this);
+ if (!found) {
+ tokenType = TokenType.SEP_Space;
+ }
+ } else {
+ // Do nothing here. If we see a number, it will not be a separator. There is no need wasting time trying to find the
+ // separator token.
+ tokenType = TokenType.SEP_Space;
+ }
+ return (tokenType);
+ }
+
+ internal bool MatchSpecifiedWord(String target) {
+ return MatchSpecifiedWord(target, target.Length + Index);
+ }
+
+ internal bool MatchSpecifiedWord(String target, int endIndex) {
+ int count = endIndex - Index;
+
+ if (count != target.Length) {
+ return false;
+ }
+
+ if (Index + count > len) {
+ return false;
+ }
+
+ return (m_info.Compare(Value, Index, count, target, 0, count, CompareOptions.IgnoreCase)==0);
+ }
+
+ private static Char[] WhiteSpaceChecks = new Char[] { ' ', '\u00A0' };
+
+ internal bool MatchSpecifiedWords(String target, bool checkWordBoundary, ref int matchLength) {
+ int valueRemaining = Value.Length - Index;
+ matchLength = target.Length;
+
+ if (matchLength > valueRemaining || m_info.Compare(Value, Index, matchLength, target, 0, matchLength, CompareOptions.IgnoreCase) !=0) {
+ // Check word by word
+ int targetPosition = 0; // Where we are in the target string
+ int thisPosition = Index; // Where we are in this string
+ int wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition);
+ if (wsIndex == -1) {
+ return false;
+ }
+ do {
+ int segmentLength = wsIndex - targetPosition;
+ if (thisPosition >= Value.Length - segmentLength) { // Subtraction to prevent overflow.
+ return false;
+ }
+ if (segmentLength == 0) {
+ // If segmentLength == 0, it means that we have leading space in the target string.
+ // In that case, skip the leading spaces in the target and this string.
+ matchLength--;
+ } else {
+ // Make sure we also have whitespace in the input string
+ if (!Char.IsWhiteSpace(Value[thisPosition + segmentLength])) {
+ return false;
+ }
+ if (m_info.Compare(Value, thisPosition, segmentLength, target, targetPosition, segmentLength, CompareOptions.IgnoreCase) !=0) {
+ return false;
+ }
+ // Advance the input string
+ thisPosition = thisPosition + segmentLength + 1;
+ }
+ // Advance our target string
+ targetPosition = wsIndex + 1;
+
+
+ // Skip past multiple whitespace
+ while (thisPosition < Value.Length && Char.IsWhiteSpace(Value[thisPosition])) {
+ thisPosition++;
+ matchLength++;
+ }
+ } while ((wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition)) >= 0);
+ // now check the last segment;
+ if (targetPosition < target.Length) {
+ int segmentLength = target.Length - targetPosition;
+ if (thisPosition > Value.Length - segmentLength) {
+ return false;
+ }
+ if (m_info.Compare(Value, thisPosition, segmentLength, target, targetPosition, segmentLength, CompareOptions.IgnoreCase) !=0) {
+ return false;
+ }
+ }
+ }
+
+ if (checkWordBoundary) {
+ int nextCharIndex = Index + matchLength;
+ if (nextCharIndex < Value.Length) {
+ if (Char.IsLetter(Value[nextCharIndex])) {
+ return (false);
+ }
+ }
+ }
+ return (true);
+ }
+
+ //
+ // Check to see if the string starting from Index is a prefix of
+ // str.
+ // If a match is found, true value is returned and Index is updated to the next character to be parsed.
+ // Otherwise, Index is unchanged.
+ //
+ internal bool Match(String str) {
+ if (++Index >= len) {
+ return (false);
+ }
+
+ if (str.Length > (Value.Length - Index)) {
+ return false;
+ }
+
+ if (m_info.Compare(Value, Index, str.Length, str, 0, str.Length, CompareOptions.Ordinal)==0) {
+ // Update the Index to the end of the matching string.
+ // So the following GetNext()/Match() opeartion will get
+ // the next character to be parsed.
+ Index += (str.Length - 1);
+ return (true);
+ }
+ return (false);
+ }
+
+ internal bool Match(char ch) {
+ if (++Index >= len) {
+ return (false);
+ }
+ if (Value[Index] == ch) {
+ m_current = ch;
+ return (true);
+ }
+ Index--;
+ return (false);
+ }
+
+ //
+ // Actions: From the current position, try matching the longest word in the specified string array.
+ // E.g. words[] = {"AB", "ABC", "ABCD"}, if the current position points to a substring like "ABC DEF",
+ // MatchLongestWords(words, ref MaxMatchStrLen) will return 1 (the index), and maxMatchLen will be 3.
+ // Returns:
+ // The index that contains the longest word to match
+ // Arguments:
+ // words The string array that contains words to search.
+ // maxMatchStrLen [in/out] the initailized maximum length. This parameter can be used to
+ // find the longest match in two string arrays.
+ //
+ internal int MatchLongestWords(String[] words, ref int maxMatchStrLen) {
+ int result = -1;
+ for (int i = 0; i < words.Length; i++) {
+ String word = words[i];
+ int matchLength = word.Length;
+ if (MatchSpecifiedWords(word, false, ref matchLength)) {
+ if (matchLength > maxMatchStrLen) {
+ maxMatchStrLen = matchLength;
+ result = i;
+ }
+ }
+ }
+
+ return (result);
+ }
+
+ //
+ // Get the number of repeat character after the current character.
+ // For a string "hh:mm:ss" at Index of 3. GetRepeatCount() = 2, and Index
+ // will point to the second ':'.
+ //
+ internal int GetRepeatCount() {
+ char repeatChar = Value[Index];
+ int pos = Index + 1;
+ while ((pos < len) && (Value[pos] == repeatChar)) {
+ pos++;
+ }
+ int repeatCount = (pos - Index);
+ // Update the Index to the end of the repeated characters.
+ // So the following GetNext() opeartion will get
+ // the next character to be parsed.
+ Index = pos - 1;
+ return (repeatCount);
+ }
+
+ // Return false when end of string is encountered or a non-digit character is found.
+ internal bool GetNextDigit() {
+ if (++Index >= len) {
+ return (false);
+ }
+ return (DateTimeParse.IsDigit(Value[Index]));
+ }
+
+ //
+ // Get the current character.
+ //
+ internal char GetChar() {
+ Contract.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len");
+ return (Value[Index]);
+ }
+
+ //
+ // Convert the current character to a digit, and return it.
+ //
+ internal int GetDigit() {
+ Contract.Assert(Index >= 0 && Index < len, "Index >= 0 && Index < len");
+ Contract.Assert(DateTimeParse.IsDigit(Value[Index]), "IsDigit(Value[Index])");
+ return (Value[Index] - '0');
+ }
+
+ //
+ // Eat White Space ahead of the current position
+ //
+ // Return false if end of string is encountered.
+ //
+ internal void SkipWhiteSpaces()
+ {
+ // Look ahead to see if the next character
+ // is a whitespace.
+ while (Index+1 < len)
+ {
+ char ch = Value[Index+1];
+ if (!Char.IsWhiteSpace(ch)) {
+ return;
+ }
+ Index++;
+ }
+ return;
+ }
+
+ //
+ // Skip white spaces from the current position
+ //
+ // Return false if end of string is encountered.
+ //
+ internal bool SkipWhiteSpaceCurrent()
+ {
+ if (Index >= len) {
+ return (false);
+ }
+
+ if (!Char.IsWhiteSpace(m_current))
+ {
+ return (true);
+ }
+
+ while (++Index < len)
+ {
+ m_current = Value[Index];
+ if (!Char.IsWhiteSpace(m_current))
+ {
+ return (true);
+ }
+ // Nothing here.
+ }
+ return (false);
+ }
+
+ internal void TrimTail() {
+ int i = len - 1;
+ while (i >= 0 && Char.IsWhiteSpace(Value[i])) {
+ i--;
+ }
+ Value = Value.Substring(0, i + 1);
+ len = Value.Length;
+ }
+
+ // Trim the trailing spaces within a quoted string.
+ // Call this after TrimTail() is done.
+ internal void RemoveTrailingInQuoteSpaces() {
+ int i = len - 1;
+ if (i <= 1) {
+ return;
+ }
+ char ch = Value[i];
+ // Check if the last character is a quote.
+ if (ch == '\'' || ch == '\"') {
+ if (Char.IsWhiteSpace(Value[i-1])) {
+ i--;
+ while (i >= 1 && Char.IsWhiteSpace(Value[i-1])) {
+ i--;
+ }
+ Value = Value.Remove(i, Value.Length - 1 - i);
+ len = Value.Length;
+ }
+ }
+ }
+
+ // Trim the leading spaces within a quoted string.
+ // Call this after the leading spaces before quoted string are trimmed.
+ internal void RemoveLeadingInQuoteSpaces() {
+ if (len <= 2) {
+ return;
+ }
+ int i = 0;
+ char ch = Value[i];
+ // Check if the last character is a quote.
+ if (ch == '\'' || ch == '\"') {
+ while ((i + 1) < len && Char.IsWhiteSpace(Value[i+1])) {
+ i++;
+ }
+ if (i != 0) {
+ Value = Value.Remove(1, i);
+ len = Value.Length;
+ }
+ }
+ }
+
+ internal DTSubString GetSubString() {
+ DTSubString sub = new DTSubString();
+ sub.index = Index;
+ sub.s = Value;
+ while (Index + sub.length < len) {
+ DTSubStringType currentType;
+ Char ch = Value[Index + sub.length];
+ if (ch >= '0' && ch <= '9') {
+ currentType = DTSubStringType.Number;
+ }
+ else {
+ currentType = DTSubStringType.Other;
+ }
+
+ if (sub.length == 0) {
+ sub.type = currentType;
+ }
+ else {
+ if (sub.type != currentType) {
+ break;
+ }
+ }
+ sub.length++;
+ if (currentType == DTSubStringType.Number) {
+ // Incorporate the number into the value
+ // Limit the digits to prevent overflow
+ if (sub.length > DateTimeParse.MaxDateTimeNumberDigits) {
+ sub.type = DTSubStringType.Invalid;
+ return sub;
+ }
+ int number = ch - '0';
+ Contract.Assert(number >= 0 && number <= 9, "number >= 0 && number <= 9");
+ sub.value = sub.value * 10 + number;
+ }
+ else {
+ // For non numbers, just return this length 1 token. This should be expanded
+ // to more types of thing if this parsing approach is used for things other
+ // than numbers and single characters
+ break;
+ }
+ }
+ if (sub.length == 0) {
+ sub.type = DTSubStringType.End;
+ return sub;
+ }
+
+ return sub;
+ }
+
+ internal void ConsumeSubString(DTSubString sub) {
+ Contract.Assert(sub.index == Index, "sub.index == Index");
+ Contract.Assert(sub.index + sub.length <= len, "sub.index + sub.length <= len");
+ Index = sub.index + sub.length;
+ if (Index < len) {
+ m_current = Value[Index];
+ }
+ }
+ }
+
+ internal enum DTSubStringType {
+ Unknown = 0,
+ Invalid = 1,
+ Number = 2,
+ End = 3,
+ Other = 4,
+ }
+
+ internal struct DTSubString {
+ internal String s;
+ internal Int32 index;
+ internal Int32 length;
+ internal DTSubStringType type;
+ internal Int32 value;
+
+ internal Char this[Int32 relativeIndex] {
+ get {
+ return s[index + relativeIndex];
+ }
+ }
+ }
+
+ //
+ // The buffer to store the parsing token.
+ //
+ internal
+ struct DateTimeToken {
+ internal DateTimeParse.DTT dtt; // Store the token
+ internal TokenType suffix; // Store the CJK Year/Month/Day suffix (if any)
+ internal int num; // Store the number that we are parsing (if any)
+ }
+
+ //
+ // The buffer to store temporary parsing information.
+ //
+ internal
+ unsafe struct DateTimeRawInfo {
+ [SecurityCritical]
+ private int* num;
+ internal int numCount;
+ internal int month;
+ internal int year;
+ internal int dayOfWeek;
+ internal int era;
+ internal DateTimeParse.TM timeMark;
+ internal double fraction;
+ internal bool hasSameDateAndTimeSeparators;
+ //
+
+ internal bool timeZone;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void Init(int * numberBuffer) {
+ month = -1;
+ year = -1;
+ dayOfWeek = -1;
+ era = -1;
+ timeMark = DateTimeParse.TM.NotSet;
+ fraction = -1;
+ num = numberBuffer;
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe void AddNumber(int value) {
+ num[numCount++] = value;
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe int GetNumber(int index) {
+ return num[index];
+ }
+ }
+
+ internal enum ParseFailureKind {
+ None = 0,
+ ArgumentNull = 1,
+ Format = 2,
+ FormatWithParameter = 3,
+ FormatBadDateTimeCalendar = 4, // FormatException when ArgumentOutOfRange is thrown by a Calendar.TryToDateTime().
+ };
+
+ [Flags]
+ internal enum ParseFlags {
+ HaveYear = 0x00000001,
+ HaveMonth = 0x00000002,
+ HaveDay = 0x00000004,
+ HaveHour = 0x00000008,
+ HaveMinute = 0x00000010,
+ HaveSecond = 0x00000020,
+ HaveTime = 0x00000040,
+ HaveDate = 0x00000080,
+ TimeZoneUsed = 0x00000100,
+ TimeZoneUtc = 0x00000200,
+ ParsedMonthName = 0x00000400,
+ CaptureOffset = 0x00000800,
+ YearDefault = 0x00001000,
+ Rfc1123Pattern = 0x00002000,
+ UtcSortPattern = 0x00004000,
+ }
+
+ //
+ // This will store the result of the parsing. And it will be eventually
+ // used to construct a DateTime instance.
+ //
+ internal
+ struct DateTimeResult
+ {
+ internal int Year;
+ internal int Month;
+ internal int Day;
+ //
+ // Set time defualt to 00:00:00.
+ //
+ internal int Hour;
+ internal int Minute;
+ internal int Second;
+ internal double fraction;
+
+ internal int era;
+
+ internal ParseFlags flags;
+
+ internal TimeSpan timeZoneOffset;
+
+ internal Calendar calendar;
+
+ internal DateTime parsedDate;
+
+ internal ParseFailureKind failure;
+ internal string failureMessageID;
+ internal object failureMessageFormatArgument;
+ internal string failureArgumentName;
+
+ internal void Init() {
+ Year = -1;
+ Month = -1;
+ Day = -1;
+ fraction = -1;
+ era = -1;
+ }
+
+ internal void SetDate(int year, int month, int day)
+ {
+ Year = year;
+ Month = month;
+ Day = day;
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) {
+ this.failure = failure;
+ this.failureMessageID = failureMessageID;
+ this.failureMessageFormatArgument = failureMessageFormatArgument;
+ }
+
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument, string failureArgumentName) {
+ this.failure = failure;
+ this.failureMessageID = failureMessageID;
+ this.failureMessageFormatArgument = failureMessageFormatArgument;
+ this.failureArgumentName = failureArgumentName;
+ }
+
+
+
+
+ }
+
+ // This is the helper data structure used in ParseExact().
+ internal struct ParsingInfo {
+
+ internal Calendar calendar;
+ internal int dayOfWeek;
+ internal DateTimeParse.TM timeMark;
+
+ internal bool fUseHour12;
+ internal bool fUseTwoDigitYear;
+ internal bool fAllowInnerWhite;
+ internal bool fAllowTrailingWhite;
+ internal bool fCustomNumberParser;
+ internal DateTimeParse.MatchNumberDelegate parseNumberDelegate;
+
+ internal void Init() {
+ dayOfWeek = -1;
+ timeMark = DateTimeParse.TM.NotSet;
+ }
+
+ }
+
+ //
+ // The type of token that will be returned by DateTimeFormatInfo.Tokenize().
+ //
+ internal enum TokenType {
+ // The valid token should start from 1.
+
+ // Regular tokens. The range is from 0x00 ~ 0xff.
+ NumberToken = 1, // The number. E.g. "12"
+ YearNumberToken = 2, // The number which is considered as year number, which has 3 or more digits. E.g. "2003"
+ Am = 3, // AM timemark. E.g. "AM"
+ Pm = 4, // PM timemark. E.g. "PM"
+ MonthToken = 5, // A word (or words) that represents a month name. E.g. "March"
+ EndOfString = 6, // End of string
+ DayOfWeekToken = 7, // A word (or words) that represents a day of week name. E.g. "Monday" or "Mon"
+ TimeZoneToken = 8, // A word that represents a timezone name. E.g. "GMT"
+ EraToken = 9, // A word that represents a era name. E.g. "A.D."
+ DateWordToken = 10, // A word that can appear in a DateTime string, but serves no parsing semantics. E.g. "de" in Spanish culture.
+ UnknownToken = 11, // An unknown word, which signals an error in parsing.
+ HebrewNumber = 12, // A number that is composed of Hebrew text. Hebrew calendar uses Hebrew digits for year values, month values, and day values.
+ JapaneseEraToken= 13, // Era name for JapaneseCalendar
+ TEraToken = 14, // Era name for TaiwanCalendar
+ IgnorableSymbol = 15, // A separator like "," that is equivalent to whitespace
+
+
+ // Separator tokens.
+ SEP_Unk = 0x100, // Unknown separator.
+ SEP_End = 0x200, // The end of the parsing string.
+ SEP_Space = 0x300, // Whitespace (including comma).
+ SEP_Am = 0x400, // AM timemark. E.g. "AM"
+ SEP_Pm = 0x500, // PM timemark. E.g. "PM"
+ SEP_Date = 0x600, // date separator. E.g. "/"
+ SEP_Time = 0x700, // time separator. E.g. ":"
+ SEP_YearSuff = 0x800, // Chinese/Japanese/Korean year suffix.
+ SEP_MonthSuff = 0x900, // Chinese/Japanese/Korean month suffix.
+ SEP_DaySuff = 0xa00, // Chinese/Japanese/Korean day suffix.
+ SEP_HourSuff = 0xb00, // Chinese/Japanese/Korean hour suffix.
+ SEP_MinuteSuff = 0xc00, // Chinese/Japanese/Korean minute suffix.
+ SEP_SecondSuff = 0xd00, // Chinese/Japanese/Korean second suffix.
+ SEP_LocalTimeMark = 0xe00, // 'T', used in ISO 8601 format.
+ SEP_DateOrOffset = 0xf00, // '-' which could be a date separator or start of a time zone offset
+
+ RegularTokenMask = 0x00ff,
+ SeparatorTokenMask = 0xff00,
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/DateTimeStyles.cs b/src/mscorlib/src/System/Globalization/DateTimeStyles.cs
new file mode 100644
index 0000000000..ddae7b2f29
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DateTimeStyles.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Contains valid formats for DateTime recognized by
+** the DateTime class' parsing code.
+**
+**
+===========================================================*/
+namespace System.Globalization {
+
+
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum DateTimeStyles {
+ // Bit flag indicating that leading whitespace is allowed. Character values
+ // 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, and 0x0020 are considered to be
+ // whitespace.
+
+
+ None = 0x00000000,
+
+ AllowLeadingWhite = 0x00000001,
+
+ AllowTrailingWhite = 0x00000002, //Bitflag indicating trailing whitespace is allowed.
+
+ AllowInnerWhite = 0x00000004,
+
+ AllowWhiteSpaces = AllowLeadingWhite | AllowInnerWhite | AllowTrailingWhite,
+ // When parsing a date/time string, if all year/month/day are missing, set the default date
+ // to 0001/1/1, instead of the current year/month/day.
+
+ NoCurrentDateDefault = 0x00000008,
+ // When parsing a date/time string, if a timezone specifier ("GMT","Z","+xxxx", "-xxxx" exists), we will
+ // ajdust the parsed time based to GMT.
+
+ AdjustToUniversal = 0x00000010,
+
+ AssumeLocal = 0x00000020,
+
+ AssumeUniversal = 0x00000040,
+ // Attempt to preserve whether the input is unspecified, local or UTC
+ RoundtripKind = 0x00000080,
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/DaylightTime.cs b/src/mscorlib/src/System/Globalization/DaylightTime.cs
new file mode 100644
index 0000000000..037d9ffdf3
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DaylightTime.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ // This class represents a starting/ending time for a period of daylight saving time.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class DaylightTime
+ {
+ internal DateTime m_start;
+ internal DateTime m_end;
+ internal TimeSpan m_delta;
+
+ private DaylightTime() {
+ }
+
+ public DaylightTime(DateTime start, DateTime end, TimeSpan delta) {
+ m_start = start;
+ m_end = end;
+ m_delta = delta;
+ }
+
+ // The start date of a daylight saving period.
+ public DateTime Start {
+ get {
+ return m_start;
+ }
+ }
+
+ // The end date of a daylight saving period.
+ public DateTime End {
+ get {
+ return m_end;
+ }
+ }
+
+ // Delta to stardard offset in ticks.
+ public TimeSpan Delta {
+ get {
+ return m_delta;
+ }
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Globalization/DigitShapes.cs b/src/mscorlib/src/System/Globalization/DigitShapes.cs
new file mode 100644
index 0000000000..d5b5ecc89c
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/DigitShapes.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// The enumeration constants used in NumberFormatInfo.DigitSubstitution.
+//
+namespace System.Globalization {
+
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum DigitShapes : int {
+
+ Context = 0x0000, // The shape depends on the previous text in the same output.
+
+ None = 0x0001, // Gives full Unicode compatibility.
+
+ NativeNational = 0x0002, // National shapes determined by LOCALE_SNATIVEDIGITS
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs
new file mode 100644
index 0000000000..2460eee3af
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/EastAsianLunisolarCalendar.cs
@@ -0,0 +1,644 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about EastAsianLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class EastAsianLunisolarCalendar : Calendar {
+ internal const int LeapMonth = 0;
+ internal const int Jan1Month = 1;
+ internal const int Jan1Date = 2;
+ internal const int nDaysPerMonth = 3;
+
+ // # of days so far in the solar year
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335
+ };
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ // Return the type of the East Asian Lunisolar calendars.
+ //
+
+ public override CalendarAlgorithmType AlgorithmType {
+ get {
+ return CalendarAlgorithmType.LunisolarCalendar;
+ }
+ }
+
+ // Return the year number in the 60-year cycle.
+ //
+
+ public virtual int GetSexagenaryYear (DateTime time) {
+ CheckTicksRange(time.Ticks);
+
+ int year = 0, month = 0, day = 0;
+ TimeToLunar(time, ref year, ref month, ref day);
+
+ return ((year - 4) % 60) + 1;
+ }
+
+ // Return the celestial year from the 60-year cycle.
+ // The returned value is from 1 ~ 10.
+ //
+
+ public int GetCelestialStem(int sexagenaryYear) {
+ if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) {
+ throw new ArgumentOutOfRangeException(
+ "sexagenaryYear",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60));
+ }
+ Contract.EndContractBlock();
+
+ return ((sexagenaryYear - 1) % 10) + 1;
+ }
+
+ // Return the Terrestial Branch from the the 60-year cycle.
+ // The returned value is from 1 ~ 12.
+ //
+
+ public int GetTerrestrialBranch(int sexagenaryYear) {
+ if ((sexagenaryYear < 1) || (sexagenaryYear > 60)) {
+ throw new ArgumentOutOfRangeException(
+ "sexagenaryYear",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", 1, 60));
+ }
+ Contract.EndContractBlock();
+
+ return ((sexagenaryYear - 1) % 12) + 1;
+ }
+
+ internal abstract int GetYearInfo(int LunarYear, int Index);
+ internal abstract int GetYear(int year, DateTime time);
+ internal abstract int GetGregorianYear(int year, int era);
+
+ internal abstract int MinCalendarYear {get;}
+ internal abstract int MaxCalendarYear {get;}
+ internal abstract EraInfo[] CalEraInfo{get;}
+ internal abstract DateTime MinDate {get;}
+ internal abstract DateTime MaxDate {get;}
+
+ internal const int MaxCalendarMonth = 13;
+ internal const int MaxCalendarDay = 30;
+
+ internal int MinEraCalendarYear (int era) {
+ EraInfo[] mEraInfo = CalEraInfo;
+ //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null
+ if (mEraInfo == null) {
+ return MinCalendarYear;
+ }
+
+ if (era == Calendar.CurrentEra) {
+ era = CurrentEraValue;
+ }
+ //era has to be in the supported range otherwise we will throw exception in CheckEraRange()
+ if (era == GetEra(MinDate)) {
+ return (GetYear(MinCalendarYear, MinDate));
+ }
+
+ for (int i = 0; i < mEraInfo.Length; i++) {
+ if (era == mEraInfo[i].era) {
+ return (mEraInfo[i].minEraYear);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ internal int MaxEraCalendarYear (int era) {
+ EraInfo[] mEraInfo = CalEraInfo;
+ //ChineseLunisolarCalendar does not has m_EraInfo it is going to retuen null
+ if (mEraInfo == null) {
+ return MaxCalendarYear;
+ }
+
+ if (era == Calendar.CurrentEra) {
+ era = CurrentEraValue;
+ }
+ //era has to be in the supported range otherwise we will throw exception in CheckEraRange()
+ if (era == GetEra(MaxDate)) {
+ return (GetYear(MaxCalendarYear, MaxDate));
+ }
+
+ for (int i = 0; i < mEraInfo.Length; i++) {
+ if (era == mEraInfo[i].era) {
+ return (mEraInfo[i].maxEraYear);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ // Construct an instance of EastAsianLunisolar calendar.
+
+ internal EastAsianLunisolarCalendar() {
+ }
+
+ internal void CheckTicksRange(long ticks) {
+ if (ticks < MinSupportedDateTime.Ticks || ticks > MaxSupportedDateTime.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ MinSupportedDateTime, MaxSupportedDateTime));
+ }
+ Contract.EndContractBlock();
+ }
+
+ internal void CheckEraRange (int era) {
+ if (era == Calendar.CurrentEra) {
+ era = CurrentEraValue;
+ }
+
+ if ((era <GetEra(MinDate)) || (era > GetEra(MaxDate))) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ internal int CheckYearRange(int year, int era) {
+ CheckEraRange(era);
+ year = GetGregorianYear(year, era);
+
+ if ((year < MinCalendarYear) || (year > MaxCalendarYear)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", MinEraCalendarYear(era), MaxEraCalendarYear(era)));
+ }
+ return year;
+ }
+
+ internal int CheckYearMonthRange(int year, int month, int era) {
+ year = CheckYearRange(year, era);
+
+ if (month == 13)
+ {
+ //Reject if there is no leap month this year
+ if (GetYearInfo(year , LeapMonth) == 0)
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+
+ if (month < 1 || month > 13) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ return year;
+ }
+
+ internal int InternalGetDaysInMonth(int year, int month) {
+ int nDays;
+ int mask; // mask for extracting bits
+
+ mask = 0x8000;
+ // convert the lunar day into a lunar month/date
+ mask >>= (month-1);
+ if ((GetYearInfo(year, nDaysPerMonth) & mask)== 0)
+ nDays = 29;
+ else
+ nDays = 30;
+ return nDays;
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ year = CheckYearMonthRange(year, month, era);
+ return InternalGetDaysInMonth(year, month);
+ }
+
+ static int GregorianIsLeapYear(int y) {
+ return ((((y)%4)!=0)?0:((((y)%100)!=0)?1:((((y)%400)!=0)?0:1)));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ year = CheckYearMonthRange(year, month, era);
+ int daysInMonth = InternalGetDaysInMonth(year, month);
+ if (day < 1 || day > daysInMonth) {
+ BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
+ throw new ArgumentOutOfRangeException(
+ "day",
+ Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month));
+ }
+
+ int gy=0; int gm=0; int gd=0;
+
+ if (LunarToGregorian(year, month, day, ref gy, ref gm, ref gd)) {
+ return new DateTime(gy, gm, gd, hour, minute, second, millisecond);
+ } else {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+ }
+
+
+ //
+ // GregorianToLunar calculates lunar calendar info for the given gregorian year, month, date.
+ // The input date should be validated before calling this method.
+ //
+ internal void GregorianToLunar(int nSYear, int nSMonth, int nSDate, ref int nLYear, ref int nLMonth, ref int nLDate) {
+ // unsigned int nLYear, nLMonth, nLDate; // lunar ymd
+ int nSolarDay; // day # in solar year
+ int nLunarDay; // day # in lunar year
+ int fLeap; // is it a solar leap year?
+ int LDpM; // lunar days/month bitfield
+ int mask; // mask for extracting bits
+ int nDays; // # days this lunar month
+ int nJan1Month, nJan1Date;
+
+ // calc the solar day of year
+ fLeap = GregorianIsLeapYear(nSYear);
+ nSolarDay = (fLeap==1) ? DaysToMonth366[nSMonth-1]: DaysToMonth365[nSMonth-1] ;
+ nSolarDay += nSDate;
+
+ // init lunar year info
+ nLunarDay = nSolarDay;
+ nLYear = nSYear;
+ if (nLYear == (MaxCalendarYear + 1)) {
+ nLYear--;
+ nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365);
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear,Jan1Date);
+ } else {
+
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear,Jan1Date);
+
+ // check if this solar date is actually part of the previous
+ // lunar year
+ if ((nSMonth < nJan1Month) ||
+ (nSMonth == nJan1Month && nSDate < nJan1Date)) {
+ // the corresponding lunar day is actually part of the previous
+ // lunar year
+ nLYear--;
+
+ // add a solar year to the lunar day #
+ nLunarDay += ((GregorianIsLeapYear(nLYear) == 1) ? 366 : 365);
+
+ // update the new start of year
+ nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ nJan1Date = GetYearInfo(nLYear, Jan1Date);
+ }
+ }
+
+ // convert solar day into lunar day.
+ // subtract off the beginning part of the solar year which is not
+ // part of the lunar year. since this part is always in Jan or Feb,
+ // we don't need to handle Leap Year (LY only affects March
+ // and later).
+ nLunarDay -= DaysToMonth365[nJan1Month-1];
+ nLunarDay -= (nJan1Date - 1);
+
+ // convert the lunar day into a lunar month/date
+ mask = 0x8000;
+ LDpM = GetYearInfo(nLYear, nDaysPerMonth);
+ nDays = ((LDpM & mask) != 0) ? 30 : 29;
+ nLMonth = 1;
+ while (nLunarDay > nDays) {
+ nLunarDay -= nDays;
+ nLMonth++;
+ mask >>= 1;
+ nDays = ((LDpM & mask) != 0) ? 30 : 29;
+ }
+ nLDate = nLunarDay;
+ }
+
+ /*
+ //Convert from Lunar to Gregorian
+ //Highly inefficient, but it works based on the forward conversion
+ */
+ internal bool LunarToGregorian(int nLYear, int nLMonth, int nLDate, ref int nSolarYear, ref int nSolarMonth, ref int nSolarDay) {
+ int numLunarDays;
+
+ if (nLDate < 1 || nLDate > 30)
+ return false;
+
+ numLunarDays = nLDate-1;
+
+ //Add previous months days to form the total num of days from the first of the month.
+ for (int i = 1; i < nLMonth; i++) {
+ numLunarDays += InternalGetDaysInMonth(nLYear, i);
+ }
+
+ //Get Gregorian First of year
+ int nJan1Month = GetYearInfo(nLYear, Jan1Month);
+ int nJan1Date = GetYearInfo(nLYear, Jan1Date);
+
+ // calc the solar day of year of 1 Lunar day
+ int fLeap = GregorianIsLeapYear(nLYear);
+ int[] days = (fLeap==1)? DaysToMonth366: DaysToMonth365;
+
+ nSolarDay = nJan1Date;
+
+ if (nJan1Month > 1)
+ nSolarDay += days [nJan1Month-1];
+
+ // Add the actual lunar day to get the solar day we want
+ nSolarDay = nSolarDay + numLunarDays;// - 1;
+
+ if ( nSolarDay > (fLeap + 365)) {
+ nSolarYear = nLYear + 1;
+ nSolarDay -= (fLeap + 365);
+ } else {
+ nSolarYear = nLYear;
+ }
+
+ for (nSolarMonth = 1; nSolarMonth < 12; nSolarMonth++) {
+ if (days[nSolarMonth] >= nSolarDay)
+ break;
+ }
+
+ nSolarDay -= days[nSolarMonth-1];
+ return true;
+ }
+
+ internal DateTime LunarToTime(DateTime time, int year, int month, int day) {
+ int gy=0; int gm=0; int gd=0;
+ LunarToGregorian(year, month, day, ref gy, ref gm, ref gd);
+ return (GregorianCalendar.GetDefaultInstance().ToDateTime(gy,gm,gd,time.Hour,time.Minute,time.Second,time.Millisecond));
+ }
+
+ internal void TimeToLunar(DateTime time, ref int year, ref int month, ref int day) {
+ int gy=0; int gm=0; int gd=0;
+
+ Calendar Greg = GregorianCalendar.GetDefaultInstance();
+ gy = Greg.GetYear(time);
+ gm = Greg.GetMonth(time);
+ gd = Greg.GetDayOfMonth(time);
+
+ GregorianToLunar(gy, gm, gd, ref year, ref month, ref day);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", -120000, 120000));
+ }
+ Contract.EndContractBlock();
+
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ int i = m + months;
+ if (i > 0) {
+ int monthsInYear = InternalIsLeapYear(y)?13:12;
+
+ while (i-monthsInYear > 0) {
+ i -= monthsInYear;
+ y++;
+ monthsInYear = InternalIsLeapYear(y)?13:12;
+ }
+ m = i;
+ } else {
+ int monthsInYear;
+ while (i <= 0) {
+ monthsInYear = InternalIsLeapYear(y-1)?13:12;
+ i += monthsInYear;
+ y--;
+ }
+ m = i;
+ }
+
+ int days = InternalGetDaysInMonth(y, m);
+ if (d > days) {
+ d = days;
+ }
+ DateTime dt = LunarToTime(time, y, m, d);
+
+ CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ y += years;
+
+ if (m==13 && !InternalIsLeapYear(y)) {
+ m = 12;
+ d = InternalGetDaysInMonth(y, m);
+ }
+ int DaysInMonths = InternalGetDaysInMonth(y, m);
+ if (d > DaysInMonths) {
+ d = DaysInMonths;
+ }
+
+ DateTime dt = LunarToTime(time, y, m, d);
+ CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and [354|355 |383|384].
+ //
+
+ public override int GetDayOfYear(DateTime time) {
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ for (int i=1; i<m ;i++)
+ {
+ d = d + InternalGetDaysInMonth(y, i);
+ }
+ return d;
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 29 or 30.
+ //
+
+ public override int GetDayOfMonth(DateTime time) {
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return d;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era) {
+ year = CheckYearRange(year, era);
+
+ int Days = 0;
+ int monthsInYear = InternalIsLeapYear(year) ? 13 : 12;
+
+ while (monthsInYear != 0)
+ Days += InternalGetDaysInMonth(year, monthsInYear--);
+
+ return Days;
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 13.
+ //
+
+ public override int GetMonth(DateTime time) {
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return m;
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+ public override int GetYear(DateTime time) {
+ CheckTicksRange(time.Ticks);
+
+ int y=0; int m=0; int d=0;
+ TimeToLunar(time, ref y, ref m, ref d);
+
+ return GetYear(y, time);
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return ((DayOfWeek)((int)(time.Ticks / Calendar.TicksPerDay + 1) % 7));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era) {
+ year = CheckYearRange(year, era);
+ return (InternalIsLeapYear(year)?13:12);
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era) {
+ year = CheckYearMonthRange(year, month, era);
+ int daysInMonth = InternalGetDaysInMonth(year, month);
+
+ if (day < 1 || day > daysInMonth) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ Environment.GetResourceString("ArgumentOutOfRange_Day", daysInMonth, month));
+ }
+ int m = GetYearInfo(year, LeapMonth);
+ return ((m!=0) && (month == (m+1)));
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ year = CheckYearMonthRange(year, month, era);
+ int m = GetYearInfo(year, LeapMonth);
+ return ((m!=0) && (month == (m+1)));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this this year is not a leap year.
+ //
+
+ public override int GetLeapMonth(int year, int era) {
+ year = CheckYearRange(year, era);
+ int month = GetYearInfo(year, LeapMonth);
+ if (month>0)
+ {
+ return (month+1);
+ }
+ return 0;
+ }
+
+ internal bool InternalIsLeapYear(int year) {
+ return (GetYearInfo(year, LeapMonth)!=0);
+ }
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era) {
+ year = CheckYearRange(year, era);
+ return InternalIsLeapYear(year);
+ }
+
+ private const int DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX = 2029;
+
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(BaseCalendarID, GetYear(new DateTime(DEFAULT_GREGORIAN_TWO_DIGIT_YEAR_MAX, 1, 1)));
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", 99, MaxCalendarYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ year = base.ToFourDigitYear(year);
+ CheckYearRange(year, CurrentEra);
+ return (year);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/EncodingDataItem.Unix.cs b/src/mscorlib/src/System/Globalization/EncodingDataItem.Unix.cs
new file mode 100644
index 0000000000..408f6e681e
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/EncodingDataItem.Unix.cs
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ [Serializable]
+ internal class CodePageDataItem
+ {
+ private readonly int _codePage;
+ private readonly int _uiFamilyCodePage;
+ private readonly string _webName;
+ private readonly uint _flags;
+ private string _displayNameResourceKey;
+
+ internal CodePageDataItem(int codePage, int uiFamilyCodePage, string webName, uint flags)
+ {
+ _codePage = codePage;
+ _uiFamilyCodePage = uiFamilyCodePage;
+ _webName = webName;
+ _flags = flags;
+ }
+
+ public int CodePage
+ {
+ get { return _codePage; }
+ }
+
+ public int UIFamilyCodePage
+ {
+ get { return _uiFamilyCodePage; }
+ }
+
+ public String WebName
+ {
+ get { return _webName; }
+ }
+
+ public String HeaderName
+ {
+ get { return _webName; } // all the code pages used on unix only have a single name
+ }
+
+ public String BodyName
+ {
+ get { return _webName; } // all the code pages used on unix only have a single name
+ }
+
+ public uint Flags
+ {
+ get { return _flags; }
+ }
+
+ // PAL ends here
+
+ public string DisplayNameResourceKey
+ {
+ get
+ {
+ if (_displayNameResourceKey == null)
+ {
+ _displayNameResourceKey = "Globalization.cp_" + CodePage;
+ }
+
+ return _displayNameResourceKey;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/EncodingDataItem.cs b/src/mscorlib/src/System/Globalization/EncodingDataItem.cs
new file mode 100644
index 0000000000..1dc1bd2eaf
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/EncodingDataItem.cs
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System.Text;
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security;
+
+ //
+ // Data item for EncodingTable. Along with EncodingTable, they are used by
+ // System.Text.Encoding.
+ //
+ // This class stores a pointer to the internal data and the index into that data
+ // where our required information is found. We load the code page, flags and uiFamilyCodePage
+ // immediately because they don't require creating an object. Creating any of the string
+ // names is delayed until somebody actually asks for them and the names are then cached.
+
+ [Serializable]
+ internal class CodePageDataItem
+ {
+ internal int m_dataIndex;
+ internal int m_uiFamilyCodePage;
+ internal String m_webName;
+ internal String m_headerName;
+ internal String m_bodyName;
+ internal uint m_flags;
+
+ [SecurityCritical]
+ unsafe internal CodePageDataItem(int dataIndex) {
+ m_dataIndex = dataIndex;
+ m_uiFamilyCodePage = EncodingTable.codePageDataPtr[dataIndex].uiFamilyCodePage;
+ m_flags = EncodingTable.codePageDataPtr[dataIndex].flags;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe internal static String CreateString(sbyte* pStrings, uint index)
+ {
+ if (pStrings[0] == '|') // |str1|str2|str3
+ {
+ int start = 1;
+
+ for (int i = 1; true; i ++)
+ {
+ sbyte ch = pStrings[i];
+
+ if ((ch == '|') || (ch == 0))
+ {
+ if (index == 0)
+ {
+ return new String(pStrings, start, i - start);
+ }
+
+ index --;
+ start = i + 1;
+
+ if (ch == 0)
+ {
+ break;
+ }
+ }
+ }
+
+ throw new ArgumentException("pStrings");
+ }
+ else
+ {
+ return new String(pStrings);
+ }
+ }
+
+ unsafe public String WebName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_webName==null) {
+ m_webName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 0);
+ }
+ return m_webName;
+ }
+ }
+
+ public virtual int UIFamilyCodePage {
+ get {
+ return m_uiFamilyCodePage;
+ }
+ }
+
+ unsafe public String HeaderName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_headerName==null) {
+ m_headerName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 1);
+ }
+ return m_headerName;
+ }
+ }
+
+ unsafe public String BodyName {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_bodyName==null) {
+ m_bodyName = CreateString(EncodingTable.codePageDataPtr[m_dataIndex].Names, 2);
+ }
+ return m_bodyName;
+ }
+ }
+
+ unsafe public uint Flags {
+ get {
+ return (m_flags);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs b/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs
new file mode 100644
index 0000000000..5628a2def9
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/EncodingTable.Unix.cs
@@ -0,0 +1,178 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Text;
+
+namespace System.Globalization
+{
+ internal static class EncodingTable
+ {
+ // Return a list of all EncodingInfo objects describing all of our encodings
+ internal static EncodingInfo[] GetEncodings()
+ {
+ EncodingInfo[] arrayEncodingInfo = new EncodingInfo[s_encodingDataTableItems.Length];
+
+ for (int i = 0; i < s_encodingDataTableItems.Length; i++)
+ {
+ CodePageDataItem dataItem = s_encodingDataTableItems[i];
+
+ arrayEncodingInfo[i] = new EncodingInfo(dataItem.CodePage, dataItem.WebName,
+ Environment.GetResourceString(dataItem.DisplayNameResourceKey));
+ }
+
+ return arrayEncodingInfo;
+ }
+
+ internal static int GetCodePageFromName(string name)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+ Contract.EndContractBlock();
+
+ ushort codePage;
+ if (s_encodingDataTable.TryGetValue(name, out codePage))
+ {
+ return codePage;
+ }
+
+ // The encoding name is not valid.
+ throw new ArgumentException(
+ string.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Argument_EncodingNotSupported"), name), "name");
+ }
+
+ internal static CodePageDataItem GetCodePageDataItem(int codepage)
+ {
+ CodePageDataItem item;
+
+ switch (codepage)
+ {
+ case 1200:
+ item = s_encodingDataTableItems[0];
+ break;
+ case 1201:
+ item = s_encodingDataTableItems[1];
+ break;
+ case 12000:
+ item = s_encodingDataTableItems[2];
+ break;
+ case 12001:
+ item = s_encodingDataTableItems[3];
+ break;
+ case 20127:
+ item = s_encodingDataTableItems[4];
+ break;
+ case 28591:
+ item = s_encodingDataTableItems[5];
+ break;
+ case 65000:
+ item = s_encodingDataTableItems[6];
+ break;
+ case 65001:
+ item = s_encodingDataTableItems[7];
+ break;
+ default:
+ item = null;
+ break;
+ }
+
+ Contract.Assert(item == null || item.CodePage == codepage, "item.CodePage needs to equal the specified codepage");
+ return item;
+ }
+
+ // PAL ends here.
+
+#if DEBUG
+ static EncodingTable()
+ {
+ Contract.Assert(
+ s_encodingDataTable.Count == EncodingTableCapacity,
+ string.Format(CultureInfo.InvariantCulture,
+ "EncodingTable s_encodingDataTable's initial capacity (EncodingTableCapacity) is incorrect.{0}Expected (s_encodingDataTable.Count): {1}, Actual (EncodingTableCapacity): {2}",
+ Environment.NewLine,
+ s_encodingDataTable.Count,
+ EncodingTableCapacity));
+ }
+#endif
+
+ // NOTE: the following two lists were taken from ~\src\classlibnative\nls\encodingdata.cpp
+ // and should be kept in sync with those lists
+
+ private const int EncodingTableCapacity = 42;
+ private readonly static Dictionary<string, ushort> s_encodingDataTable =
+ new Dictionary<string, ushort>(EncodingTableCapacity, StringComparer.OrdinalIgnoreCase)
+ {
+ { "ANSI_X3.4-1968", 20127 },
+ { "ANSI_X3.4-1986", 20127 },
+ { "ascii", 20127 },
+ { "cp367", 20127 },
+ { "cp819", 28591 },
+ { "csASCII", 20127 },
+ { "csISOLatin1", 28591 },
+ { "csUnicode11UTF7", 65000 },
+ { "IBM367", 20127 },
+ { "ibm819", 28591 },
+ { "ISO-10646-UCS-2", 1200 },
+ { "iso-8859-1", 28591 },
+ { "iso-ir-100", 28591 },
+ { "iso-ir-6", 20127 },
+ { "ISO646-US", 20127 },
+ { "iso8859-1", 28591 },
+ { "ISO_646.irv:1991", 20127 },
+ { "iso_8859-1", 28591 },
+ { "iso_8859-1:1987", 28591 },
+ { "l1", 28591 },
+ { "latin1", 28591 },
+ { "ucs-2", 1200 },
+ { "unicode", 1200},
+ { "unicode-1-1-utf-7", 65000 },
+ { "unicode-1-1-utf-8", 65001 },
+ { "unicode-2-0-utf-7", 65000 },
+ { "unicode-2-0-utf-8", 65001 },
+ // People get confused about the FFFE here. We can't change this because it'd break existing apps.
+ // This has been this way for a long time, including in Mlang.
+ // Big Endian, BOM seems backwards, think of the BOM in little endian order.
+ { "unicodeFFFE", 1201},
+ { "us", 20127 },
+ { "us-ascii", 20127 },
+ { "utf-16", 1200 },
+ { "UTF-16BE", 1201},
+ { "UTF-16LE", 1200},
+ { "utf-32", 12000 },
+ { "UTF-32BE", 12001 },
+ { "UTF-32LE", 12000 },
+ { "utf-7", 65000 },
+ { "utf-8", 65001 },
+ { "x-unicode-1-1-utf-7", 65000 },
+ { "x-unicode-1-1-utf-8", 65001 },
+ { "x-unicode-2-0-utf-7", 65000 },
+ { "x-unicode-2-0-utf-8", 65001 },
+ };
+
+ // redeclaring these constants here for readability below
+ private const uint MIMECONTF_MAILNEWS = Encoding.MIMECONTF_MAILNEWS;
+ private const uint MIMECONTF_BROWSER = Encoding.MIMECONTF_BROWSER;
+ private const uint MIMECONTF_SAVABLE_MAILNEWS = Encoding.MIMECONTF_SAVABLE_MAILNEWS;
+ private const uint MIMECONTF_SAVABLE_BROWSER = Encoding.MIMECONTF_SAVABLE_BROWSER;
+
+ // keep this array sorted by code page, so the order is consistent for GetEncodings()
+ // Remember to update GetCodePageDataItem() if this list is updated
+ private readonly static CodePageDataItem[] s_encodingDataTableItems = new[]
+ {
+ new CodePageDataItem(1200, 1200, "utf-16", MIMECONTF_SAVABLE_BROWSER), // "Unicode"
+ new CodePageDataItem(1201, 1200, "utf-16BE", 0), // Big Endian, old FFFE BOM seems backwards, think of the BOM in little endian order.
+ new CodePageDataItem(12000, 1200, "utf-32", 0), // "Unicode (UTF-32)"
+ new CodePageDataItem(12001, 1200, "utf-32BE", 0), // "Unicode (UTF-32 Big Endian)"
+ new CodePageDataItem(20127, 1252, "us-ascii", MIMECONTF_MAILNEWS | MIMECONTF_SAVABLE_MAILNEWS), // "US-ASCII"
+ new CodePageDataItem(28591, 1252, "iso-8859-1", MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER), // "Western European (ISO)"
+ new CodePageDataItem(65000, 1200, "utf-7", MIMECONTF_MAILNEWS | MIMECONTF_SAVABLE_MAILNEWS), // "Unicode (UTF-7)"
+ new CodePageDataItem(65001, 1200, "utf-8", MIMECONTF_MAILNEWS | MIMECONTF_BROWSER | MIMECONTF_SAVABLE_MAILNEWS | MIMECONTF_SAVABLE_BROWSER), // "Unicode (UTF-8)"
+ };
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/EncodingTable.cs b/src/mscorlib/src/System/Globalization/EncodingTable.cs
new file mode 100644
index 0000000000..cdda9eaf6d
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/EncodingTable.cs
@@ -0,0 +1,250 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ using System;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+ //
+ // Data table for encoding classes. Used by System.Text.Encoding.
+ // This class contains two hashtables to allow System.Text.Encoding
+ // to retrieve the data item either by codepage value or by webName.
+ //
+
+ // Only statics, does not need to be marked with the serializable attribute
+ internal static class EncodingTable
+ {
+
+ //This number is the size of the table in native. The value is retrieved by
+ //calling the native GetNumEncodingItems().
+ private static int lastEncodingItem = GetNumEncodingItems() - 1;
+
+ //This number is the size of the code page table. Its generated when we walk the table the first time.
+ private static volatile int lastCodePageItem;
+
+ //
+ // This points to a native data table which maps an encoding name to the correct code page.
+ //
+ [SecurityCritical]
+ unsafe internal static InternalEncodingDataItem *encodingDataPtr = GetEncodingData();
+ //
+ // This points to a native data table which stores the properties for the code page, and
+ // the table is indexed by code page.
+ //
+ [SecurityCritical]
+ unsafe internal static InternalCodePageDataItem *codePageDataPtr = GetCodePageData();
+ //
+ // This caches the mapping of an encoding name to a code page.
+ //
+ private static Hashtable hashByName = Hashtable.Synchronized(new Hashtable(StringComparer.OrdinalIgnoreCase));
+ //
+ // THe caches the data item which is indexed by the code page value.
+ //
+ private static Hashtable hashByCodePage = Hashtable.Synchronized(new Hashtable());
+
+ [System.Security.SecuritySafeCritical] // static constructors should be safe to call
+ static EncodingTable()
+ {
+ }
+
+ // Find the data item by binary searching the table that we have in native.
+ // nativeCompareOrdinalWC is an internal-only function.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe private static int internalGetCodePageFromName(String name) {
+ int left = 0;
+ int right = lastEncodingItem;
+ int index;
+ int result;
+
+ //Binary search the array until we have only a couple of elements left and then
+ //just walk those elements.
+ while ((right - left)>3) {
+ index = ((right - left)/2) + left;
+
+ result = String.nativeCompareOrdinalIgnoreCaseWC(name, encodingDataPtr[index].webName);
+
+ if (result == 0) {
+ //We found the item, return the associated codepage.
+ return (encodingDataPtr[index].codePage);
+ } else if (result<0) {
+ //The name that we're looking for is less than our current index.
+ right = index;
+ } else {
+ //The name that we're looking for is greater than our current index
+ left = index;
+ }
+ }
+
+ //Walk the remaining elements (it'll be 3 or fewer).
+ for (; left<=right; left++) {
+ if (String.nativeCompareOrdinalIgnoreCaseWC(name, encodingDataPtr[left].webName) == 0) {
+ return (encodingDataPtr[left].codePage);
+ }
+ }
+ // The encoding name is not valid.
+ throw new ArgumentException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Argument_EncodingNotSupported"), name), "name");
+ }
+
+ // Return a list of all EncodingInfo objects describing all of our encodings
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static unsafe EncodingInfo[] GetEncodings()
+ {
+ if (lastCodePageItem == 0)
+ {
+ int count;
+ for (count = 0; codePageDataPtr[count].codePage != 0; count++)
+ {
+ // Count them
+ }
+ lastCodePageItem = count;
+ }
+
+ EncodingInfo[] arrayEncodingInfo = new EncodingInfo[lastCodePageItem];
+
+ int i;
+ for (i = 0; i < lastCodePageItem; i++)
+ {
+ arrayEncodingInfo[i] = new EncodingInfo(codePageDataPtr[i].codePage, CodePageDataItem.CreateString(codePageDataPtr[i].Names, 0),
+ Environment.GetResourceString("Globalization.cp_" + codePageDataPtr[i].codePage));
+ }
+
+ return arrayEncodingInfo;
+ }
+
+ /*=================================GetCodePageFromName==========================
+ **Action: Given a encoding name, return the correct code page number for this encoding.
+ **Returns: The code page for the encoding.
+ **Arguments:
+ ** name the name of the encoding
+ **Exceptions:
+ ** ArgumentNullException if name is null.
+ ** internalGetCodePageFromName will throw ArgumentException if name is not a valid encoding name.
+ ============================================================================*/
+
+ internal static int GetCodePageFromName(String name)
+ {
+ if (name==null) {
+ throw new ArgumentNullException("name");
+ }
+ Contract.EndContractBlock();
+
+ Object codePageObj;
+
+ //
+ // The name is case-insensitive, but ToLower isn't free. Check for
+ // the code page in the given capitalization first.
+ //
+ codePageObj = hashByName[name];
+
+ if (codePageObj!=null) {
+ return ((int)codePageObj);
+ }
+
+ //Okay, we didn't find it in the hash table, try looking it up in the
+ //unmanaged data.
+ int codePage = internalGetCodePageFromName(name);
+
+ hashByName[name] = codePage;
+
+ return codePage;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe internal static CodePageDataItem GetCodePageDataItem(int codepage) {
+ CodePageDataItem dataItem;
+
+ // We synchronize around dictionary gets/sets. There's still a possibility that two threads
+ // will create a CodePageDataItem and the second will clobber the first in the dictionary.
+ // However, that's acceptable because the contents are correct and we make no guarantees
+ // other than that.
+
+ //Look up the item in the hashtable.
+ dataItem = (CodePageDataItem)hashByCodePage[codepage];
+
+ //If we found it, return it.
+ if (dataItem!=null) {
+ return dataItem;
+ }
+
+
+ //If we didn't find it, try looking it up now.
+ //If we find it, add it to the hashtable.
+ //This is a linear search, but we probably won't be doing it very often.
+ //
+ int i = 0;
+ int data;
+ while ((data = codePageDataPtr[i].codePage) != 0) {
+ if (data == codepage) {
+ dataItem = new CodePageDataItem(i);
+ hashByCodePage[codepage] = dataItem;
+ return (dataItem);
+ }
+ i++;
+ }
+
+ //Nope, we didn't find it.
+ return null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe static extern InternalEncodingDataItem *GetEncodingData();
+
+ //
+ // Return the number of encoding data items.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int GetNumEncodingItems();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe static extern InternalCodePageDataItem* GetCodePageData();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe static extern byte* nativeCreateOpenFileMapping(
+ String inSectionName, int inBytesToAllocate, out IntPtr mappedFileHandle);
+ }
+
+ /*=================================InternalEncodingDataItem==========================
+ **Action: This is used to map a encoding name to a correct code page number. By doing this,
+ ** we can get the properties of this encoding via the InternalCodePageDataItem.
+ **
+ ** We use this structure to access native data exposed by the native side.
+ ============================================================================*/
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct InternalEncodingDataItem {
+ [SecurityCritical]
+ internal sbyte * webName;
+ internal UInt16 codePage;
+ }
+
+ /*=================================InternalCodePageDataItem==========================
+ **Action: This is used to access the properties related to a code page.
+ ** We use this structure to access native data exposed by the native side.
+ ============================================================================*/
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ internal unsafe struct InternalCodePageDataItem {
+ internal UInt16 codePage;
+ internal UInt16 uiFamilyCodePage;
+ internal uint flags;
+ [SecurityCritical]
+ internal sbyte * Names;
+ }
+
+}
diff --git a/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs b/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs
new file mode 100644
index 0000000000..4de3fd399b
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/GlobalizationAssembly.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Globalization {
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.IO;
+ using System.Diagnostics.Contracts;
+
+
+ /*=================================GlobalizationAssembly==========================
+ **
+ ** This class provides the table loading wrapper that calls GetManifestResourceStream
+ **
+ ** It used to provide an idea for sort versioning, but that proved to not work
+ **
+ ============================================================================*/
+ internal sealed class GlobalizationAssembly
+ {
+ // ----------------------------------------------------------------------------------------------------
+ //
+ // Instance data members and instance methods.
+ //
+ // ----------------------------------------------------------------------------------------------------
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static byte* GetGlobalizationResourceBytePtr(Assembly assembly, String tableName) {
+ Contract.Assert(assembly != null, "assembly can not be null. This should be generally the "+System.CoreLib.Name+" assembly.");
+ Contract.Assert(tableName != null, "table name can not be null");
+
+ Stream stream = assembly.GetManifestResourceStream(tableName);
+ UnmanagedMemoryStream bytesStream = stream as UnmanagedMemoryStream;
+ if (bytesStream != null) {
+ byte* bytes = bytesStream.PositionPointer;
+ if (bytes != null) {
+ return (bytes);
+ }
+ }
+
+ Contract.Assert(
+ false,
+ String.Format(
+ CultureInfo.CurrentCulture,
+ "Didn't get the resource table {0} for System.Globalization from {1}",
+ tableName,
+ assembly));
+
+ // We can not continue if we can't get the resource.
+ throw new InvalidOperationException();
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendar.cs b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs
new file mode 100644
index 0000000000..e540adda9f
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/GregorianCalendar.cs
@@ -0,0 +1,627 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ //
+ // N.B.:
+ // A lot of this code is directly from DateTime.cs. If you update that class,
+ // update this one as well.
+ // However, we still need these duplicated code because we will add era support
+ // in this class.
+ //
+ //
+
+ using System.Threading;
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ // This calendar recognizes two era values:
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class GregorianCalendar : Calendar
+ {
+ /*
+ A.D. = anno Domini
+ */
+
+ public const int ADEra = 1;
+
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ //
+ // This is the max Gregorian year can be represented by DateTime class. The limitation
+ // is derived from DateTime class.
+ //
+ internal const int MaxYear = 9999;
+
+ internal GregorianCalendarTypes m_type;
+
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ private static volatile Calendar s_defaultInstance;
+
+
+#region Serialization
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (m_type < GregorianCalendarTypes.Localized ||
+ m_type > GregorianCalendarTypes.TransliteratedFrench)
+ {
+ throw new SerializationException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString(
+ "Serialization_MemberOutOfRange"),
+ "type",
+ "GregorianCalendar"));
+ }
+ }
+#endregion Serialization
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Gregorian calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of GregorianCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance() {
+ if (s_defaultInstance == null) {
+ s_defaultInstance = new GregorianCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+ // Construct an instance of gregorian calendar.
+
+ public GregorianCalendar() :
+ this(GregorianCalendarTypes.Localized) {
+ }
+
+
+ public GregorianCalendar(GregorianCalendarTypes type) {
+ if ((int)type < (int)GregorianCalendarTypes.Localized || (int)type > (int)GregorianCalendarTypes.TransliteratedFrench) {
+ throw new ArgumentOutOfRangeException(
+ "type",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ GregorianCalendarTypes.Localized, GregorianCalendarTypes.TransliteratedFrench));
+ }
+ Contract.EndContractBlock();
+ this.m_type = type;
+ }
+
+ public virtual GregorianCalendarTypes CalendarType {
+ get {
+ return (m_type);
+ }
+
+ set {
+ VerifyWritable();
+
+ switch (value) {
+ case GregorianCalendarTypes.Localized:
+ case GregorianCalendarTypes.USEnglish:
+ case GregorianCalendarTypes.MiddleEastFrench:
+ case GregorianCalendarTypes.Arabic:
+ case GregorianCalendarTypes.TransliteratedEnglish:
+ case GregorianCalendarTypes.TransliteratedFrench:
+ m_type = value;
+ break;
+
+ default:
+ throw new ArgumentOutOfRangeException("m_type", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ }
+ }
+ }
+
+ internal override int ID {
+ get {
+ // By returning different ID for different variations of GregorianCalendar,
+ // we can support the Transliterated Gregorian calendar.
+ // DateTimeFormatInfo will use this ID to get formatting information about
+ // the calendar.
+ return ((int)m_type);
+ }
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ // n = number of days since 1/1/0001
+ int n = (int)(ticks / TicksPerDay);
+ // y400 = number of whole 400-year periods since 1/1/0001
+ int y400 = n / DaysPer400Years;
+ // n = day number within 400-year period
+ n -= y400 * DaysPer400Years;
+ // y100 = number of whole 100-year periods within 400-year period
+ int y100 = n / DaysPer100Years;
+ // Last 100-year period has an extra day, so decrement result if 4
+ if (y100 == 4) y100 = 3;
+ // n = day number within 100-year period
+ n -= y100 * DaysPer100Years;
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / DaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * DaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / DaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * DaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3));
+ int[] days = leapYear? DaysToMonth366: DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ /*=================================GetAbsoluteDate==========================
+ **Action: Gets the absolute date for the given Gregorian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns: the absolute date
+ **Arguments:
+ ** year the Gregorian year
+ ** month the Gregorian month
+ ** day the day
+ **Exceptions:
+ ** ArgumentOutOfRangException if year, month, day value is valid.
+ **Note:
+ ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
+ ** Number of Days in Prior Years (both common and leap years) +
+ ** Number of Days in Prior Months of Current Year +
+ ** Number of Days in Current Month
+ **
+ ============================================================================*/
+
+ internal static long GetAbsoluteDate(int year, int month, int day) {
+ if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12)
+ {
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366: DaysToMonth365;
+ if (day >= 1 && (day <= days[month] - days[month - 1])) {
+ int y = year - 1;
+ int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
+ return (absoluteDate);
+ }
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ // Will check the if the parameters are valid.
+ internal virtual long DateToTicks(int year, int month, int day) {
+ return (GetAbsoluteDate(year, month, day)* TicksPerDay);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366: DaysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+
+ return (new DateTime(ticks));
+ }
+
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ if (era == CurrentEra || era == ADEra) {
+ if (year < 1 || year > MaxYear) {
+ throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, MaxYear));
+ }
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366: DaysToMonth365);
+ return (days[month] - days[month - 1]);
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ if (era == CurrentEra || era == ADEra) {
+ if (year >= 1 && year <= MaxYear) {
+ return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366:365);
+ }
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time)
+ {
+ return (ADEra);
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {ADEra} );
+ }
+ }
+
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ if (era == CurrentEra || era == ADEra) {
+ if (year >= 1 && year <= MaxYear)
+ {
+ return (12);
+ }
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, 12));
+ }
+ Contract.EndContractBlock();
+
+ if (era != CurrentEra && era != ADEra)
+ {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ if (year < 1 || year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ Environment.GetResourceString("ArgumentOutOfRange_Range", 1, MaxYear));
+ }
+
+ if (day < 1 || day > GetDaysInMonth(year, month)) {
+ throw new ArgumentOutOfRangeException("day", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, GetDaysInMonth(year, month)));
+ }
+ if (!IsLeapYear(year)) {
+ return (false);
+ }
+ if (month == 2 && day == 29) {
+ return (true);
+ }
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ if (era != CurrentEra && era != ADEra)
+ {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ if (year < 1 || year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear));
+ }
+ Contract.EndContractBlock();
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ if (era != CurrentEra && era != ADEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ if (year < 1 || year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear));
+ }
+
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 1, 12));
+ }
+ Contract.EndContractBlock();
+ return (false);
+
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era) {
+ if (era == CurrentEra || era == ADEra) {
+ if (year >= 1 && year <= MaxYear) {
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+ }
+
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear));
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ if (era == CurrentEra || era == ADEra) {
+ return new DateTime(year, month, day, hour, minute, second, millisecond);
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ internal override Boolean TryToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era, out DateTime result) {
+ if (era == CurrentEra || era == ADEra) {
+ return DateTime.TryCreate(year, month, day, hour, minute, second, millisecond, out result);
+ }
+ result = DateTime.MinValue;
+ return false;
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2029;
+
+
+ public override int TwoDigitYearMax
+ {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ MaxYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), 1, MaxYear));
+ }
+ return (base.ToFourDigitYear(year));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs
new file mode 100644
index 0000000000..75b280d457
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/GregorianCalendarHelper.cs
@@ -0,0 +1,633 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Globalization {
+ using System;
+ using System.Runtime.Serialization;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ // Gregorian Calendars use Era Info
+ // Note: We shouldn't have to serialize this since the info doesn't change, but we have been.
+ // (We really only need the calendar #, and maybe culture)
+ [Serializable]
+ internal class EraInfo
+ {
+ internal int era; // The value of the era.
+ internal long ticks; // The time in ticks when the era starts
+ internal int yearOffset; // The offset to Gregorian year when the era starts.
+ // Gregorian Year = Era Year + yearOffset
+ // Era Year = Gregorian Year - yearOffset
+ internal int minEraYear; // Min year value in this era. Generally, this value is 1, but this may
+ // be affected by the DateTime.MinValue;
+ internal int maxEraYear; // Max year value in this era. (== the year length of the era + 1)
+
+ [OptionalField(VersionAdded = 4)]
+ internal String eraName; // The era name
+ [OptionalField(VersionAdded = 4)]
+ internal String abbrevEraName; // Abbreviated Era Name
+ [OptionalField(VersionAdded = 4)]
+ internal String englishEraName; // English era name
+
+ internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear)
+ {
+ this.era = era;
+ this.yearOffset = yearOffset;
+ this.minEraYear = minEraYear;
+ this.maxEraYear = maxEraYear;
+ this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
+ }
+
+ internal EraInfo(int era, int startYear, int startMonth, int startDay, int yearOffset, int minEraYear, int maxEraYear,
+ String eraName, String abbrevEraName, String englishEraName)
+ {
+ this.era = era;
+ this.yearOffset = yearOffset;
+ this.minEraYear = minEraYear;
+ this.maxEraYear = maxEraYear;
+ this.ticks = new DateTime(startYear, startMonth, startDay).Ticks;
+ this.eraName = eraName;
+ this.abbrevEraName = abbrevEraName;
+ this.englishEraName = englishEraName;
+ }
+ }
+
+ // This calendar recognizes two era values:
+ // 0 CurrentEra (AD)
+ // 1 BeforeCurrentEra (BC)
+ [Serializable] internal class GregorianCalendarHelper {
+
+ // 1 tick = 100ns = 10E-7 second
+ // Number of ticks per time unit
+ internal const long TicksPerMillisecond = 10000;
+ internal const long TicksPerSecond = TicksPerMillisecond * 1000;
+ internal const long TicksPerMinute = TicksPerSecond * 60;
+ internal const long TicksPerHour = TicksPerMinute * 60;
+ internal const long TicksPerDay = TicksPerHour * 24;
+
+ // Number of milliseconds per time unit
+ internal const int MillisPerSecond = 1000;
+ internal const int MillisPerMinute = MillisPerSecond * 60;
+ internal const int MillisPerHour = MillisPerMinute * 60;
+ internal const int MillisPerDay = MillisPerHour * 24;
+
+ // Number of days in a non-leap year
+ internal const int DaysPerYear = 365;
+ // Number of days in 4 years
+ internal const int DaysPer4Years = DaysPerYear * 4 + 1;
+ // Number of days in 100 years
+ internal const int DaysPer100Years = DaysPer4Years * 25 - 1;
+ // Number of days in 400 years
+ internal const int DaysPer400Years = DaysPer100Years * 4 + 1;
+
+ // Number of days from 1/1/0001 to 1/1/10000
+ internal const int DaysTo10000 = DaysPer400Years * 25 - 366;
+
+ internal const long MaxMillis = (long)DaysTo10000 * MillisPerDay;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ //
+ // This is the max Gregorian year can be represented by DateTime class. The limitation
+ // is derived from DateTime class.
+ //
+ internal int MaxYear {
+ get {
+ return (m_maxYear);
+ }
+ }
+
+ internal static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ internal static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ // Strictly these don't need serialized since they can be recreated from the calendar id
+ [OptionalField(VersionAdded = 1)]
+ internal int m_maxYear = 9999;
+ [OptionalField(VersionAdded = 1)]
+ internal int m_minYear;
+ internal Calendar m_Cal;
+
+ // Era information doesn't need serialized, its constant for the same calendars (ie: we can recreate it from the calendar id)
+ [OptionalField(VersionAdded = 1)]
+ internal EraInfo[] m_EraInfo;
+ [OptionalField(VersionAdded = 1)]
+ internal int[] m_eras = null;
+
+ // m_minDate is existing here just to keep the serialization compatibility.
+ // it has nothing to do with the code anymore.
+ [OptionalField(VersionAdded = 1)]
+ internal DateTime m_minDate;
+
+ // Construct an instance of gregorian calendar.
+ internal GregorianCalendarHelper(Calendar cal, EraInfo[] eraInfo) {
+ m_Cal = cal;
+ m_EraInfo = eraInfo;
+ // m_minDate is existing here just to keep the serialization compatibility.
+ // it has nothing to do with the code anymore.
+ m_minDate = m_Cal.MinSupportedDateTime;
+ m_maxYear = m_EraInfo[0].maxEraYear;
+ m_minYear = m_EraInfo[0].minEraYear;;
+ }
+
+ /*=================================GetGregorianYear==========================
+ **Action: Get the Gregorian year value for the specified year in an era.
+ **Returns: The Gregorian year value.
+ **Arguments:
+ ** year the year value in Japanese calendar
+ ** era the Japanese emperor era value.
+ **Exceptions:
+ ** ArgumentOutOfRangeException if year value is invalid or era value is invalid.
+ ============================================================================*/
+
+ internal int GetGregorianYear(int year, int era) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (era == Calendar.CurrentEra) {
+ era = m_Cal.CurrentEraValue;
+ }
+
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ if (era == m_EraInfo[i].era) {
+ if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ m_EraInfo[i].minEraYear,
+ m_EraInfo[i].maxEraYear));
+ }
+ return (m_EraInfo[i].yearOffset + year);
+ }
+ }
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+
+ internal bool IsValidYear(int year, int era) {
+ if (year < 0) {
+ return false;
+ }
+
+ if (era == Calendar.CurrentEra) {
+ era = m_Cal.CurrentEraValue;
+ }
+
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ if (era == m_EraInfo[i].era) {
+ if (year < m_EraInfo[i].minEraYear || year > m_EraInfo[i].maxEraYear) {
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ internal virtual int GetDatePart(long ticks, int part)
+ {
+ CheckTicksRange(ticks);
+ // n = number of days since 1/1/0001
+ int n = (int)(ticks / TicksPerDay);
+ // y400 = number of whole 400-year periods since 1/1/0001
+ int y400 = n / DaysPer400Years;
+ // n = day number within 400-year period
+ n -= y400 * DaysPer400Years;
+ // y100 = number of whole 100-year periods within 400-year period
+ int y100 = n / DaysPer100Years;
+ // Last 100-year period has an extra day, so decrement result if 4
+ if (y100 == 4) y100 = 3;
+ // n = day number within 100-year period
+ n -= y100 * DaysPer100Years;
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / DaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * DaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / DaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * DaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3 && (y4 != 24 || y100 == 3));
+ int[] days = leapYear? DaysToMonth366: DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ /*=================================GetAbsoluteDate==========================
+ **Action: Gets the absolute date for the given Gregorian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns: the absolute date
+ **Arguments:
+ ** year the Gregorian year
+ ** month the Gregorian month
+ ** day the day
+ **Exceptions:
+ ** ArgumentOutOfRangException if year, month, day value is valid.
+ **Note:
+ ** This is an internal method used by DateToTicks() and the calculations of Hijri and Hebrew calendars.
+ ** Number of Days in Prior Years (both common and leap years) +
+ ** Number of Days in Prior Months of Current Year +
+ ** Number of Days in Current Month
+ **
+ ============================================================================*/
+
+ internal static long GetAbsoluteDate(int year, int month, int day) {
+ if (year >= 1 && year <= 9999 && month >= 1 && month <= 12)
+ {
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) ? DaysToMonth366: DaysToMonth365;
+ if (day >= 1 && (day <= days[month] - days[month - 1])) {
+ int y = year - 1;
+ int absoluteDate = y * 365 + y / 4 - y / 100 + y / 400 + days[month - 1] + day - 1;
+ return (absoluteDate);
+ }
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ // Will check the if the parameters are valid.
+ internal static long DateToTicks(int year, int month, int day) {
+ return (GetAbsoluteDate(year, month, day)* TicksPerDay);
+ }
+
+ // Return the tick count corresponding to the given hour, minute, second.
+ // Will check the if the parameters are valid.
+ internal static long TimeToTicks(int hour, int minute, int second, int millisecond)
+ {
+ //TimeSpan.TimeToTicks is a family access function which does no error checking, so
+ //we need to put some error checking out here.
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
+ {
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ MillisPerSecond - 1));
+ }
+ return (TimeSpan.TimeToTicks(hour, minute, second) + millisecond * TicksPerMillisecond);;
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
+ }
+
+
+ internal void CheckTicksRange(long ticks) {
+ if (ticks < m_Cal.MinSupportedDateTime.Ticks || ticks > m_Cal.MaxSupportedDateTime.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ m_Cal.MinSupportedDateTime,
+ m_Cal.MaxSupportedDateTime));
+ }
+ Contract.EndContractBlock();
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+ public DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ CheckTicksRange(time.Ticks);
+
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0)
+ {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else
+ {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366: DaysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days)
+ {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, m_Cal.MinSupportedDateTime, m_Cal.MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+ public DateTime AddYears(DateTime time, int years)
+ {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+ public int GetDayOfMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+ public DayOfWeek GetDayOfWeek(DateTime time)
+ {
+ CheckTicksRange(time.Ticks);
+ return ((DayOfWeek)((time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+ public int GetDayOfYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+ [Pure]
+ public int GetDaysInMonth(int year, int month, int era) {
+ //
+ // Convert year/era value to Gregorain year value.
+ //
+ year = GetGregorianYear(year, era);
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366: DaysToMonth365);
+ return (days[month] - days[month - 1]);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public int GetDaysInYear(int year, int era)
+ {
+ //
+ // Convert year/era value to Gregorain year value.
+ //
+ year = GetGregorianYear(year, era);
+ return ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 366:365);
+ }
+
+ // Returns the era for the specified DateTime value.
+ public int GetEra(DateTime time)
+ {
+ long ticks = time.Ticks;
+ // The assumption here is that m_EraInfo is listed in reverse order.
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ if (ticks >= m_EraInfo[i].ticks) {
+ return (m_EraInfo[i].era);
+ }
+ }
+ throw new ArgumentOutOfRangeException("time", Environment.GetResourceString("ArgumentOutOfRange_Era"));
+ }
+
+
+ public int[] Eras {
+ get {
+ if (m_eras == null) {
+ m_eras = new int[m_EraInfo.Length];
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ m_eras[i] = m_EraInfo[i].era;
+ }
+ }
+ return ((int[])m_eras.Clone());
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+ public int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+ public int GetMonthsInYear(int year, int era)
+ {
+ year = GetGregorianYear(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int GetYear(DateTime time)
+ {
+ long ticks = time.Ticks;
+ int year = GetDatePart(ticks, DatePartYear);
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ if (ticks >= m_EraInfo[i].ticks) {
+ return (year - m_EraInfo[i].yearOffset);
+ }
+ }
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoEra"));
+ }
+
+ // Returns the year that match the specified Gregorian year. The returned value is an
+ // integer between 1 and 9999.
+ //
+ public int GetYear(int year, DateTime time)
+ {
+ long ticks = time.Ticks;
+ for (int i = 0; i < m_EraInfo.Length; i++) {
+ // while calculating dates with JapaneseLuniSolarCalendar, we can run into cases right after the start of the era
+ // and still belong to the month which is started in previous era. Calculating equivalent calendar date will cause
+ // using the new era info which will have the year offset equal to the year we are calculating year = m_EraInfo[i].yearOffset
+ // which will end up with zero as calendar year.
+ // We should use the previous era info instead to get the right year number. Example of such date is Feb 2nd 1989
+ if (ticks >= m_EraInfo[i].ticks && year > m_EraInfo[i].yearOffset) {
+ return (year - m_EraInfo[i].yearOffset);
+ }
+ }
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoEra"));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+ public bool IsLeapDay(int year, int month, int day, int era)
+ {
+ // year/month/era checking is done in GetDaysInMonth()
+ if (day < 1 || day > GetDaysInMonth(year, month, era)) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ GetDaysInMonth(year, month, era)));
+ }
+ Contract.EndContractBlock();
+
+ if (!IsLeapYear(year, era)) {
+ return (false);
+ }
+
+ if (month == 2 && day == 29) {
+ return (true);
+ }
+
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+ public int GetLeapMonth(int year, int era)
+ {
+ year = GetGregorianYear(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+ public bool IsLeapMonth(int year, int month, int era)
+ {
+ year = GetGregorianYear(year, era);
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ 12));
+ }
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+ public bool IsLeapYear(int year, int era) {
+ year = GetGregorianYear(year, era);
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+ public DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ year = GetGregorianYear(year, era);
+ long ticks = DateToTicks(year, month, day) + TimeToTicks(hour, minute, second, millisecond);
+ CheckTicksRange(ticks);
+ return (new DateTime(ticks));
+ }
+
+ public virtual int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek) {
+ CheckTicksRange(time.Ticks);
+ // Use GregorianCalendar to get around the problem that the implmentation in Calendar.GetWeekOfYear()
+ // can call GetYear() that exceeds the supported range of the Gregorian-based calendars.
+ return (GregorianCalendar.GetDefaultInstance().GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public int ToFourDigitYear(int year, int twoDigitYearMax) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100) {
+ int y = year % 100;
+ return ((twoDigitYearMax/100 - ( y > twoDigitYearMax % 100 ? 1 : 0))*100 + y);
+ }
+
+ if (year < m_minYear || year > m_maxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), m_minYear, m_maxYear));
+ }
+ // If the year value is above 100, just return the year value. Don't have to do
+ // the TwoDigitYearMax comparison.
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs b/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs
new file mode 100644
index 0000000000..a9e25d06bf
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/GregorianCalendarTypes.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum GregorianCalendarTypes {
+ Localized = Calendar.CAL_GREGORIAN,
+ USEnglish = Calendar.CAL_GREGORIAN_US,
+ MiddleEastFrench = Calendar.CAL_GREGORIAN_ME_FRENCH,
+ Arabic = Calendar.CAL_GREGORIAN_ARABIC,
+ TransliteratedEnglish = Calendar.CAL_GREGORIAN_XLIT_ENGLISH,
+ TransliteratedFrench = Calendar.CAL_GREGORIAN_XLIT_FRENCH,
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/HebrewCalendar.cs b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs
new file mode 100644
index 0000000000..3a17494001
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/HebrewCalendar.cs
@@ -0,0 +1,1084 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Rules for the Hebrew calendar:
+ // - The Hebrew calendar is both a Lunar (months) and Solar (years)
+ // calendar, but allows for a week of seven days.
+ // - Days begin at sunset.
+ // - Leap Years occur in the 3, 6, 8, 11, 14, 17, & 19th years of a
+ // 19-year cycle. Year = leap iff ((7y+1) mod 19 < 7).
+ // - There are 12 months in a common year and 13 months in a leap year.
+ // - In a common year, the 6th month, Adar, has 29 days. In a leap
+ // year, the 6th month, Adar I, has 30 days and the leap month,
+ // Adar II, has 29 days.
+ // - Common years have 353-355 days. Leap years have 383-385 days.
+ // - The Hebrew new year (Rosh HaShanah) begins on the 1st of Tishri,
+ // the 7th month in the list below.
+ // - The new year may not begin on Sunday, Wednesday, or Friday.
+ // - If the new year would fall on a Tuesday and the conjunction of
+ // the following year were at midday or later, the new year is
+ // delayed until Thursday.
+ // - If the new year would fall on a Monday after a leap year, the
+ // new year is delayed until Tuesday.
+ // - The length of the 8th and 9th months vary from year to year,
+ // depending on the overall length of the year.
+ // - The length of a year is determined by the dates of the new
+ // years (Tishri 1) preceding and following the year in question.
+ // - The 2th month is long (30 days) if the year has 355 or 385 days.
+ // - The 3th month is short (29 days) if the year has 353 or 383 days.
+ // - The Hebrew months are:
+ // 1. Tishri (30 days)
+ // 2. Heshvan (29 or 30 days)
+ // 3. Kislev (29 or 30 days)
+ // 4. Teveth (29 days)
+ // 5. Shevat (30 days)
+ // 6. Adar I (30 days)
+ // 7. Adar {II} (29 days, this only exists if that year is a leap year)
+ // 8. Nisan (30 days)
+ // 9. Iyyar (29 days)
+ // 10. Sivan (30 days)
+ // 11. Tammuz (29 days)
+ // 12. Av (30 days)
+ // 13. Elul (29 days)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1583/01/01 2239/09/29
+ ** Hebrew 5343/04/07 5999/13/29
+ */
+
+// Includes CHebrew implemetation;i.e All the code necessary for converting
+// Gregorian to Hebrew Lunar from 1583 to 2239.
+
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class HebrewCalendar : Calendar {
+
+
+ public static readonly int HebrewEra = 1;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+ internal const int DatePartDayOfWeek = 4;
+
+ //
+ // Hebrew Translation Table.
+ //
+ // This table is used to get the following Hebrew calendar information for a
+ // given Gregorian year:
+ // 1. The day of the Hebrew month corresponding to Gregorian January 1st
+ // for a given Gregorian year.
+ // 2. The month of the Hebrew month corresponding to Gregorian January 1st
+ // for a given Gregorian year.
+ // The information is not directly in the table. Instead, the info is decoded
+ // by special values (numbers above 29 and below 1).
+ // 3. The type of the Hebrew year for a given Gregorian year.
+ //
+
+ /*
+ More notes:
+
+ This table includes 2 numbers for each year.
+ The offset into the table determines the year. (offset 0 is Gregorian year 1500)
+ 1st number determines the day of the Hebrew month coresponeds to January 1st.
+ 2nd number determines the type of the Hebrew year. (the type determines how
+ many days are there in the year.)
+
+ normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ Leap years : 4 = 383 5 384 6 = 385 days.
+
+ A 99 means the year is not supported for translation.
+ for convenience the table was defined for 750 year,
+ but only 640 years are supported. (from 1583 to 2239)
+ the years before 1582 (starting of Georgian calander)
+ and after 2239, are filled with 99.
+
+ Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
+ That's why, there no nead to specify the lunar month in the table.
+ There are exceptions, these are coded by giving numbers above 29 and below 1.
+ Actual decoding is takenig place whenever fetching information from the table.
+ The function for decoding is in GetLunarMonthDay().
+
+ Example:
+ The data for 2000 - 2005 A.D. is:
+
+ 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004
+
+ For year 2000, we know it has a Hebrew year type 6, which means it has 385 days.
+ And 1/1/2000 A.D. is Hebrew year 5760, 23rd day of 4th month.
+ */
+
+ //
+ // Jewish Era in use today is dated from the supposed year of the
+ // Creation with its beginning in 3761 B.C.
+ //
+
+ // The Hebrew year of Gregorian 1st year AD.
+ // 0001/01/01 AD is Hebrew 3760/01/01
+ private const int HebrewYearOf1AD = 3760;
+
+ // The first Gregorian year in HebrewTable.
+ private const int FirstGregorianTableYear = 1583; // == Hebrew Year 5343
+ // The last Gregorian year in HebrewTable.
+ private const int LastGregorianTableYear = 2239; // == Hebrew Year 5999
+ private const int TABLESIZE = (LastGregorianTableYear-FirstGregorianTableYear);
+
+ private const int MinHebrewYear = HebrewYearOf1AD + FirstGregorianTableYear; // == 5343
+ private const int MaxHebrewYear = HebrewYearOf1AD + LastGregorianTableYear; // == 5999
+
+ private static readonly int[] HebrewTable = {
+ 7,3,17,3, // 1583-1584 (Hebrew year: 5343 - 5344)
+ 0,4,11,2,21,6,1,3,13,2, // 1585-1589
+ 25,4,5,3,16,2,27,6,9,1, // 1590-1594
+ 20,2,0,6,11,3,23,4,4,2, // 1595-1599
+ 14,3,27,4,8,2,18,3,28,6, // 1600
+ 11,1,22,5,2,3,12,3,25,4, // 1605
+ 6,2,16,3,26,6,8,2,20,1, // 1610
+ 0,6,11,2,24,4,4,3,15,2, // 1615
+ 25,6,8,1,19,2,29,6,9,3, // 1620
+ 22,4,3,2,13,3,25,4,6,3, // 1625
+ 17,2,27,6,7,3,19,2,31,4, // 1630
+ 11,3,23,4,5,2,15,3,25,6, // 1635
+ 6,2,19,1,29,6,10,2,22,4, // 1640
+ 3,3,14,2,24,6,6,1,17,3, // 1645
+ 28,5,8,3,20,1,32,5,12,3, // 1650
+ 22,6,4,1,16,2,26,6,6,3, // 1655
+ 17,2,0,4,10,3,22,4,3,2, // 1660
+ 14,3,24,6,5,2,17,1,28,6, // 1665
+ 9,2,19,3,31,4,13,2,23,6, // 1670
+ 3,3,15,1,27,5,7,3,17,3, // 1675
+ 29,4,11,2,21,6,3,1,14,2, // 1680
+ 25,6,5,3,16,2,28,4,9,3, // 1685
+ 20,2,0,6,12,1,23,6,4,2, // 1690
+ 14,3,26,4,8,2,18,3,0,4, // 1695
+ 10,3,21,5,1,3,13,1,24,5, // 1700
+ 5,3,15,3,27,4,8,2,19,3, // 1705
+ 29,6,10,2,22,4,3,3,14,2, // 1710
+ 26,4,6,3,18,2,28,6,10,1, // 1715
+ 20,6,2,2,12,3,24,4,5,2, // 1720
+ 16,3,28,4,8,3,19,2,0,6, // 1725
+ 12,1,23,5,3,3,14,3,26,4, // 1730
+ 7,2,17,3,28,6,9,2,21,4, // 1735
+ 1,3,13,2,25,4,5,3,16,2, // 1740
+ 27,6,9,1,19,3,0,5,11,3, // 1745
+ 23,4,4,2,14,3,25,6,7,1, // 1750
+ 18,2,28,6,9,3,21,4,2,2, // 1755
+ 12,3,25,4,6,2,16,3,26,6, // 1760
+ 8,2,20,1,0,6,11,2,22,6, // 1765
+ 4,1,15,2,25,6,6,3,18,1, // 1770
+ 29,5,9,3,22,4,2,3,13,2, // 1775
+ 23,6,4,3,15,2,27,4,7,3, // 1780
+ 19,2,31,4,11,3,21,6,3,2, // 1785
+ 15,1,25,6,6,2,17,3,29,4, // 1790
+ 10,2,20,6,3,1,13,3,24,5, // 1795
+ 4,3,16,1,27,5,7,3,17,3, // 1800
+ 0,4,11,2,21,6,1,3,13,2, // 1805
+ 25,4,5,3,16,2,29,4,9,3, // 1810
+ 19,6,30,2,13,1,23,6,4,2, // 1815
+ 14,3,27,4,8,2,18,3,0,4, // 1820
+ 11,3,22,5,2,3,14,1,26,5, // 1825
+ 6,3,16,3,28,4,10,2,20,6, // 1830
+ 30,3,11,2,24,4,4,3,15,2, // 1835
+ 25,6,8,1,19,2,29,6,9,3, // 1840
+ 22,4,3,2,13,3,25,4,7,2, // 1845
+ 17,3,27,6,9,1,21,5,1,3, // 1850
+ 11,3,23,4,5,2,15,3,25,6, // 1855
+ 6,2,19,1,29,6,10,2,22,4, // 1860
+ 3,3,14,2,24,6,6,1,18,2, // 1865
+ 28,6,8,3,20,4,2,2,12,3, // 1870
+ 24,4,4,3,16,2,26,6,6,3, // 1875
+ 17,2,0,4,10,3,22,4,3,2, // 1880
+ 14,3,24,6,5,2,17,1,28,6, // 1885
+ 9,2,21,4,1,3,13,2,23,6, // 1890
+ 5,1,15,3,27,5,7,3,19,1, // 1895
+ 0,5,10,3,22,4,2,3,13,2, // 1900
+ 24,6,4,3,15,2,27,4,8,3, // 1905
+ 20,4,1,2,11,3,22,6,3,2, // 1910
+ 15,1,25,6,7,2,17,3,29,4, // 1915
+ 10,2,21,6,1,3,13,1,24,5, // 1920
+ 5,3,15,3,27,4,8,2,19,6, // 1925
+ 1,1,12,2,22,6,3,3,14,2, // 1930
+ 26,4,6,3,18,2,28,6,10,1, // 1935
+ 20,6,2,2,12,3,24,4,5,2, // 1940
+ 16,3,28,4,9,2,19,6,30,3, // 1945
+ 12,1,23,5,3,3,14,3,26,4, // 1950
+ 7,2,17,3,28,6,9,2,21,4, // 1955
+ 1,3,13,2,25,4,5,3,16,2, // 1960
+ 27,6,9,1,19,6,30,2,11,3, // 1965
+ 23,4,4,2,14,3,27,4,7,3, // 1970
+ 18,2,28,6,11,1,22,5,2,3, // 1975
+ 12,3,25,4,6,2,16,3,26,6, // 1980
+ 8,2,20,4,30,3,11,2,24,4, // 1985
+ 4,3,15,2,25,6,8,1,18,3, // 1990
+ 29,5,9,3,22,4,3,2,13,3, // 1995
+ 23,6,6,1,17,2,27,6,7,3, // 2000 - 2004
+ 20,4,1,2,11,3,23,4,5,2, // 2005 - 2009
+ 15,3,25,6,6,2,19,1,29,6, // 2010
+ 10,2,20,6,3,1,14,2,24,6, // 2015
+ 4,3,17,1,28,5,8,3,20,4, // 2020
+ 1,3,12,2,22,6,2,3,14,2, // 2025
+ 26,4,6,3,17,2,0,4,10,3, // 2030
+ 20,6,1,2,14,1,24,6,5,2, // 2035
+ 15,3,28,4,9,2,19,6,1,1, // 2040
+ 12,3,23,5,3,3,15,1,27,5, // 2045
+ 7,3,17,3,29,4,11,2,21,6, // 2050
+ 1,3,12,2,25,4,5,3,16,2, // 2055
+ 28,4,9,3,19,6,30,2,12,1, // 2060
+ 23,6,4,2,14,3,26,4,8,2, // 2065
+ 18,3,0,4,10,3,22,5,2,3, // 2070
+ 14,1,25,5,6,3,16,3,28,4, // 2075
+ 9,2,20,6,30,3,11,2,23,4, // 2080
+ 4,3,15,2,27,4,7,3,19,2, // 2085
+ 29,6,11,1,21,6,3,2,13,3, // 2090
+ 25,4,6,2,17,3,27,6,9,1, // 2095
+ 20,5,30,3,10,3,22,4,3,2, // 2100
+ 14,3,24,6,5,2,17,1,28,6, // 2105
+ 9,2,21,4,1,3,13,2,23,6, // 2110
+ 5,1,16,2,27,6,7,3,19,4, // 2115
+ 30,2,11,3,23,4,3,3,14,2, // 2120
+ 25,6,5,3,16,2,28,4,9,3, // 2125
+ 21,4,2,2,12,3,23,6,4,2, // 2130
+ 16,1,26,6,8,2,20,4,30,3, // 2135
+ 11,2,22,6,4,1,14,3,25,5, // 2140
+ 6,3,18,1,29,5,9,3,22,4, // 2145
+ 2,3,13,2,23,6,4,3,15,2, // 2150
+ 27,4,7,3,20,4,1,2,11,3, // 2155
+ 21,6,3,2,15,1,25,6,6,2, // 2160
+ 17,3,29,4,10,2,20,6,3,1, // 2165
+ 13,3,24,5,4,3,17,1,28,5, // 2170
+ 8,3,18,6,1,1,12,2,22,6, // 2175
+ 2,3,14,2,26,4,6,3,17,2, // 2180
+ 28,6,10,1,20,6,1,2,12,3, // 2185
+ 24,4,5,2,15,3,28,4,9,2, // 2190
+ 19,6,33,3,12,1,23,5,3,3, // 2195
+ 13,3,25,4,6,2,16,3,26,6, // 2200
+ 8,2,20,4,30,3,11,2,24,4, // 2205
+ 4,3,15,2,25,6,8,1,18,6, // 2210
+ 33,2,9,3,22,4,3,2,13,3, // 2215
+ 25,4,6,3,17,2,27,6,9,1, // 2220
+ 21,5,1,3,11,3,23,4,5,2, // 2225
+ 15,3,25,6,6,2,19,4,33,3, // 2230
+ 10,2,22,4,3,3,14,2,24,6, // 2235
+ 6,1 // 2240 (Hebrew year: 6000)
+ };
+
+ //
+ // The lunar calendar has 6 different variations of month lengths
+ // within a year.
+ //
+ private static readonly int[,] LunarMonthLen = {
+ {0,00,00,00,00,00,00,00,00,00,00,00,00,0},
+ {0,30,29,29,29,30,29,30,29,30,29,30,29,0}, // 3 common year variations
+ {0,30,29,30,29,30,29,30,29,30,29,30,29,0},
+ {0,30,30,30,29,30,29,30,29,30,29,30,29,0},
+ {0,30,29,29,29,30,30,29,30,29,30,29,30,29}, // 3 leap year variations
+ {0,30,29,30,29,30,30,29,30,29,30,29,30,29},
+ {0,30,30,30,29,30,30,29,30,29,30,29,30,29}
+ };
+
+ //internal static Calendar m_defaultInstance;
+
+ internal static readonly DateTime calendarMinValue = new DateTime(1583, 1, 1);
+ // Gregorian 2239/9/29 = Hebrew 5999/13/29 (last day in Hebrew year 5999).
+ // We can only format/parse Hebrew numbers up to 999, so we limit the max range to Hebrew year 5999.
+ internal static readonly DateTime calendarMaxValue = new DateTime((new DateTime(2239, 9, 29, 23, 59, 59, 999)).Ticks + 9999);
+
+
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (calendarMaxValue);
+ }
+ }
+
+
+ // Return the type of the Hebrew calendar.
+ //
+
+
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.LunisolarCalendar;
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of HebrewCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new HebrewCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+
+ // Construct an instance of gregorian calendar.
+
+ public HebrewCalendar() {
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_HEBREW);
+ }
+ }
+
+
+ /*=================================CheckHebrewYearValue==========================
+ **Action: Check if the Hebrew year value is supported in this class.
+ **Returns: None.
+ **Arguments: y Hebrew year value
+ ** ear Hebrew era value
+ **Exceptions: ArgumentOutOfRange_Range if the year value is not supported.
+ **Note:
+ ** We use a table for the Hebrew calendar calculation, so the year supported is limited.
+ ============================================================================*/
+
+ static private void CheckHebrewYearValue(int y, int era, String varName) {
+ CheckEraRange(era);
+ if (y > MaxHebrewYear || y < MinHebrewYear) {
+ throw new ArgumentOutOfRangeException(
+ varName,
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MinHebrewYear,
+ MaxHebrewYear));
+ }
+ }
+
+ /*=================================CheckHebrewMonthValue==========================
+ **Action: Check if the Hebrew month value is valid.
+ **Returns: None.
+ **Arguments: year Hebrew year value
+ ** month Hebrew month value
+ **Exceptions: ArgumentOutOfRange_Range if the month value is not valid.
+ **Note:
+ ** Call CheckHebrewYearValue() before calling this to verify the year value is supported.
+ ============================================================================*/
+
+ private void CheckHebrewMonthValue(int year, int month, int era) {
+ int monthsInYear = GetMonthsInYear(year, era);
+ if (month < 1 || month > monthsInYear) {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ monthsInYear));
+ }
+ }
+
+ /*=================================CheckHebrewDayValue==========================
+ **Action: Check if the Hebrew day value is valid.
+ **Returns: None.
+ **Arguments: year Hebrew year value
+ ** month Hebrew month value
+ ** day Hebrew day value.
+ **Exceptions: ArgumentOutOfRange_Range if the day value is not valid.
+ **Note:
+ ** Call CheckHebrewYearValue()/CheckHebrewMonthValue() before calling this to verify the year/month values are valid.
+ ============================================================================*/
+
+ private void CheckHebrewDayValue(int year, int month, int day, int era) {
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ daysInMonth));
+ }
+ }
+
+ static internal void CheckEraRange(int era) {
+ if (era != CurrentEra && era != HebrewEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ static private void CheckTicksRange(long ticks) {
+ if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ // Print out the date in Gregorian using InvariantCulture since the DateTime is based on GreograinCalendar.
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ calendarMinValue,
+ calendarMaxValue));
+ }
+ }
+
+ static internal int GetResult(__DateBuffer result, int part) {
+ switch (part) {
+ case DatePartYear:
+ return (result.year);
+ case DatePartMonth:
+ return (result.month);
+ case DatePartDay:
+ return (result.day);
+ }
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing"));
+ }
+
+ /*=================================GetLunarMonthDay==========================
+ **Action: Using the Hebrew table (HebrewTable) to get the Hebrew month/day value for Gregorian January 1st
+ ** in a given Gregorian year.
+ ** Greogrian January 1st falls usually in Tevet (4th month). Tevet has always 29 days.
+ ** That's why, there no nead to specify the lunar month in the table. There are exceptions, and these
+ ** are coded by giving numbers above 29 and below 1.
+ ** Actual decoding is takenig place in the switch statement below.
+ **Returns:
+ ** The Hebrew year type. The value is from 1 to 6.
+ ** normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ ** Leap years : 4 = 383 5 384 6 = 385 days.
+ **Arguments:
+ ** gregorianYear The year value in Gregorian calendar. The value should be between 1500 and 2239.
+ ** lunarDate Object to take the result of the Hebrew year/month/day.
+ **Exceptions:
+ ============================================================================*/
+
+ static internal int GetLunarMonthDay(int gregorianYear, __DateBuffer lunarDate) {
+ //
+ // Get the offset into the LunarMonthLen array and the lunar day
+ // for January 1st.
+ //
+ int index = gregorianYear - FirstGregorianTableYear;
+ if (index < 0 || index > TABLESIZE) {
+ throw new ArgumentOutOfRangeException("gregorianYear");
+ }
+
+ index *= 2;
+ lunarDate.day = HebrewTable[index];
+
+ // Get the type of the year. The value is from 1 to 6
+ int LunarYearType = HebrewTable[index + 1];
+
+ //
+ // Get the Lunar Month.
+ //
+ switch (lunarDate.day) {
+ case ( 0 ) : // 1/1 is on Shvat 1
+ lunarDate.month = 5;
+ lunarDate.day = 1;
+ break;
+ case ( 30 ) : // 1/1 is on Kislev 30
+ lunarDate.month = 3;
+ break;
+ case ( 31 ) : // 1/1 is on Shvat 2
+ lunarDate.month = 5;
+ lunarDate.day = 2;
+ break;
+ case ( 32 ) : // 1/1 is on Shvat 3
+ lunarDate.month = 5;
+ lunarDate.day = 3;
+ break;
+ case ( 33 ) : // 1/1 is on Kislev 29
+ lunarDate.month = 3;
+ lunarDate.day = 29;
+ break;
+ default : // 1/1 is on Tevet (This is the general case)
+ lunarDate.month = 4;
+ break;
+ }
+ return (LunarYearType);
+ }
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+
+ internal virtual int GetDatePart(long ticks, int part) {
+ // The Gregorian year, month, day value for ticks.
+ int gregorianYear, gregorianMonth, gregorianDay;
+ int hebrewYearType; // lunar year type
+ long AbsoluteDate; // absolute date - absolute date 1/1/1600
+
+ //
+ // Make sure we have a valid Gregorian date that will fit into our
+ // Hebrew conversion limits.
+ //
+ CheckTicksRange(ticks);
+
+ DateTime time = new DateTime(ticks);
+
+ //
+ // Save the Gregorian date values.
+ //
+ gregorianYear = time.Year;
+ gregorianMonth = time.Month;
+ gregorianDay = time.Day;
+
+ __DateBuffer lunarDate = new __DateBuffer(); // lunar month and day for Jan 1
+
+ // From the table looking-up value of HebrewTable[index] (stored in lunarDate.day), we get the the
+ // lunar month and lunar day where the Gregorian date 1/1 falls.
+ lunarDate.year = gregorianYear + HebrewYearOf1AD;
+ hebrewYearType = GetLunarMonthDay(gregorianYear, lunarDate);
+
+ // This is the buffer used to store the result Hebrew date.
+ __DateBuffer result = new __DateBuffer();
+
+ //
+ // Store the values for the start of the new year - 1/1.
+ //
+ result.year = lunarDate.year;
+ result.month = lunarDate.month;
+ result.day = lunarDate.day;
+
+ //
+ // Get the absolute date from 1/1/1600.
+ //
+ AbsoluteDate = GregorianCalendar.GetAbsoluteDate(gregorianYear, gregorianMonth, gregorianDay);
+
+ //
+ // If the requested date was 1/1, then we're done.
+ //
+ if ((gregorianMonth == 1) && (gregorianDay == 1)) {
+ return (GetResult(result, part));
+ }
+
+ //
+ // Calculate the number of days between 1/1 and the requested date.
+ //
+ long NumDays; // number of days since 1/1
+ NumDays = AbsoluteDate - GregorianCalendar.GetAbsoluteDate(gregorianYear, 1, 1);
+
+ //
+ // If the requested date is within the current lunar month, then
+ // we're done.
+ //
+ if ((NumDays + (long)lunarDate.day) <= (long)(LunarMonthLen[hebrewYearType, lunarDate.month])) {
+ result.day += (int)NumDays;
+ return (GetResult(result, part));
+ }
+
+ //
+ // Adjust for the current partial month.
+ //
+ result.month++;
+ result.day = 1;
+
+ //
+ // Adjust the Lunar Month and Year (if necessary) based on the number
+ // of days between 1/1 and the requested date.
+ //
+ // Assumes Jan 1 can never translate to the last Lunar month, which
+ // is true.
+ //
+ NumDays -= (long)(LunarMonthLen[hebrewYearType, lunarDate.month] - lunarDate.day);
+ Contract.Assert(NumDays >= 1, "NumDays >= 1");
+
+ // If NumDays is 1, then we are done. Otherwise, find the correct Hebrew month
+ // and day.
+ if (NumDays > 1) {
+ //
+ // See if we're on the correct Lunar month.
+ //
+ while (NumDays > (long)(LunarMonthLen[hebrewYearType, result.month])) {
+ //
+ // Adjust the number of days and move to the next month.
+ //
+ NumDays -= (long)(LunarMonthLen[hebrewYearType, result.month++]);
+
+ //
+ // See if we need to adjust the Year.
+ // Must handle both 12 and 13 month years.
+ //
+ if ((result.month > 13) || (LunarMonthLen[hebrewYearType, result.month] == 0)) {
+ //
+ // Adjust the Year.
+ //
+ result.year++;
+ hebrewYearType = HebrewTable[(gregorianYear + 1 - FirstGregorianTableYear) * 2 + 1];
+
+ //
+ // Adjust the Month.
+ //
+ result.month = 1;
+ }
+ }
+ //
+ // Found the right Lunar month.
+ //
+ result.day += (int)(NumDays - 1);
+ }
+ return (GetResult(result, part));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ try {
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+
+
+ int monthsInYear;
+ int i;
+ if (months >= 0) {
+ i = m + months;
+ while (i > (monthsInYear = GetMonthsInYear(y, CurrentEra))) {
+ y++;
+ i -= monthsInYear;
+ }
+ } else {
+ if ((i = m + months) <= 0) {
+ months = -months;
+ months -= m;
+ y--;
+
+ while (months > (monthsInYear = GetMonthsInYear(y, CurrentEra))) {
+ y--;
+ months -= monthsInYear;
+ }
+ monthsInYear = GetMonthsInYear(y, CurrentEra);
+ i = monthsInYear - months;
+ }
+ }
+
+ int days = GetDaysInMonth(y, i);
+ if (d > days) {
+ d = days;
+ }
+ return (new DateTime(ToDateTime(y, i, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay)));
+ }
+ // We expect ArgumentException and ArgumentOutOfRangeException (which is subclass of ArgumentException)
+ // If exception is thrown in the calls above, we are out of the supported range of this calendar.
+ catch (ArgumentException)
+ {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_AddValue")));
+ }
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years) {
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+
+ y += years;
+ CheckHebrewYearValue(y, Calendar.CurrentEra, "years");
+
+ int months = GetMonthsInYear(y, CurrentEra);
+ if (m > months) {
+ m = months;
+ }
+
+ int days = GetDaysInMonth(y, m);
+ if (d > days) {
+ d = days;
+ }
+
+ long ticks = ToDateTime(y, m, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ // If we calculate back, the Hebrew day of week for Gregorian 0001/1/1 is Monday (1).
+ // Therfore, the fomula is:
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ static internal int GetHebrewYearType(int year, int era) {
+ CheckHebrewYearValue(year, era, "year");
+ // The HebrewTable is indexed by Gregorian year and starts from FirstGregorianYear.
+ // So we need to convert year (Hebrew year value) to Gregorian Year below.
+ return (HebrewTable[(year - HebrewYearOf1AD - FirstGregorianTableYear) * 2 + 1]);
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time) {
+ // Get Hebrew year value of the specified time.
+ int year = GetYear(time);
+ DateTime beginOfYearDate;
+ if (year == 5343)
+ {
+ // Gregorian 1583/01/01 corresponds to Hebrew 5343/04/07 (MinSupportedDateTime)
+ // To figure out the Gregorian date associated with Hebrew 5343/01/01, we need to
+ // count the days from 5343/01/01 to 5343/04/07 and subtract that from Gregorian
+ // 1583/01/01.
+ // 1. Tishri (30 days)
+ // 2. Heshvan (30 days since 5343 has 355 days)
+ // 3. Kislev (30 days since 5343 has 355 days)
+ // 96 days to get from 5343/01/01 to 5343/04/07
+ // Gregorian 1583/01/01 - 96 days = 1582/9/27
+
+ // the beginning of Hebrew year 5343 corresponds to Gregorian September 27, 1582.
+ beginOfYearDate = new DateTime(1582, 9, 27);
+ }
+ else
+ {
+ // following line will fail when year is 5343 (first supported year)
+ beginOfYearDate = ToDateTime(year, 1, 1, 0, 0, 0, 0, CurrentEra);
+ }
+ return ((int)((time.Ticks - beginOfYearDate.Ticks) / TicksPerDay) + 1);
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ CheckEraRange(era);
+ int hebrewYearType = GetHebrewYearType(year, era);
+ CheckHebrewMonthValue(year, month, era);
+
+ Contract.Assert(hebrewYearType>= 1 && hebrewYearType <= 6,
+ "hebrewYearType should be from 1 to 6, but now hebrewYearType = " + hebrewYearType + " for hebrew year " + year);
+ int monthDays = LunarMonthLen[hebrewYearType, month];
+ if (monthDays == 0) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ return (monthDays);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era) {
+ CheckEraRange(era);
+ // normal years : 1 = 353 days 2 = 354 days 3 = 355 days.
+ // Leap years : 4 = 383 5 384 6 = 385 days.
+
+ // LunarYearType is from 1 to 6
+ int LunarYearType = GetHebrewYearType(year, era);
+ if (LunarYearType < 4) {
+ // common year: LunarYearType = 1, 2, 3
+ return (352 + LunarYearType);
+ }
+ return (382 + (LunarYearType - 3));
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time) {
+
+ return (HebrewEra);
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {HebrewEra});
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era) {
+ return (IsLeapYear(year, era) ? 13 : 12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and 9999.
+ //
+
+ public override int GetYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era) {
+ if (IsLeapMonth(year, month, era)) {
+ // Every day in a leap month is a leap day.
+ CheckHebrewDayValue(year, month, day, era);
+ return (true);
+ } else if (IsLeapYear(year, Calendar.CurrentEra)) {
+ // There is an additional day in the 6th month in the leap year (the extra day is the 30th day in the 6th month),
+ // so we should return true for 6/30 if that's in a leap year.
+ if (month == 6 && day == 30) {
+ return (true);
+ }
+ }
+ CheckHebrewDayValue(year, month, day, era);
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ // Year/era values are checked in IsLeapYear().
+ if (IsLeapYear(year, era))
+ {
+ // The 7th month in a leap year is a leap month.
+ return (7);
+ }
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ // Year/era values are checked in IsLeapYear().
+ bool isLeapYear = IsLeapYear(year, era);
+ CheckHebrewMonthValue(year, month, era);
+ // The 7th month in a leap year is a leap month.
+ if (isLeapYear) {
+ if (month == 7) {
+ return (true);
+ }
+ }
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era) {
+ CheckHebrewYearValue(year, era, "year");
+ return (((7 * (long)year + 1) % 19) < 7);
+ }
+
+ // (month1, day1) - (month2, day2)
+ static int GetDayDifference(int lunarYearType, int month1, int day1, int month2, int day2) {
+ if (month1 == month2) {
+ return (day1 - day2);
+ }
+
+ // Make sure that (month1, day1) < (month2, day2)
+ bool swap = (month1 > month2);
+ if (swap) {
+ // (month1, day1) < (month2, day2). Swap the values.
+ // The result will be a negative number.
+ int tempMonth, tempDay;
+ tempMonth = month1; tempDay = day1;
+ month1 = month2; day1 = day2;
+ month2 = tempMonth; day2 = tempDay;
+ }
+
+ // Get the number of days from (month1,day1) to (month1, end of month1)
+ int days = LunarMonthLen[lunarYearType, month1] - day1;
+
+ // Move to next month.
+ month1++;
+
+ // Add up the days.
+ while (month1 < month2) {
+ days += LunarMonthLen[lunarYearType, month1++];
+ }
+ days += day2;
+
+ return (swap ? days : -days);
+ }
+
+ /*=================================HebrewToGregorian==========================
+ **Action: Convert Hebrew date to Gregorian date.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ** The algorithm is like this:
+ ** The hebrew year has an offset to the Gregorian year, so we can guess the Gregorian year for
+ ** the specified Hebrew year. That is, GreogrianYear = HebrewYear - FirstHebrewYearOf1AD.
+ **
+ ** From the Gregorian year and HebrewTable, we can get the Hebrew month/day value
+ ** of the Gregorian date January 1st. Let's call this month/day value [hebrewDateForJan1]
+ **
+ ** If the requested Hebrew month/day is less than [hebrewDateForJan1], we know the result
+ ** Gregorian date falls in previous year. So we decrease the Gregorian year value, and
+ ** retrieve the Hebrew month/day value of the Gregorian date january 1st again.
+ **
+ ** Now, we get the answer of the Gregorian year.
+ **
+ ** The next step is to get the number of days between the requested Hebrew month/day
+ ** and [hebrewDateForJan1]. When we get that, we can create the DateTime by adding/subtracting
+ ** the ticks value of the number of days.
+ **
+ ============================================================================*/
+
+
+ static DateTime HebrewToGregorian(int hebrewYear, int hebrewMonth, int hebrewDay, int hour, int minute, int second, int millisecond) {
+ // Get the rough Gregorian year for the specified hebrewYear.
+ //
+ int gregorianYear = hebrewYear - HebrewYearOf1AD;
+
+ __DateBuffer hebrewDateOfJan1 = new __DateBuffer(); // year value is unused.
+ int lunarYearType = GetLunarMonthDay(gregorianYear, hebrewDateOfJan1);
+
+ if ((hebrewMonth == hebrewDateOfJan1.month) && (hebrewDay == hebrewDateOfJan1.day)) {
+ return (new DateTime(gregorianYear, 1, 1, hour, minute, second, millisecond));
+ }
+
+ int days = GetDayDifference(lunarYearType, hebrewMonth, hebrewDay, hebrewDateOfJan1.month, hebrewDateOfJan1.day);
+
+ DateTime gregorianNewYear = new DateTime(gregorianYear, 1, 1);
+ return (new DateTime(gregorianNewYear.Ticks + days * TicksPerDay
+ + TimeToTicks(hour, minute, second, millisecond)));
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ CheckHebrewYearValue(year, era, "year");
+ CheckHebrewMonthValue(year, month, era);
+ CheckHebrewDayValue(year, month, day, era);
+ DateTime dt = HebrewToGregorian(year, month, day, hour, minute, second, millisecond);
+ CheckTicksRange(dt.Ticks);
+ return (dt);
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 5790;
+
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value == 99)
+ {
+ // Do nothing here. Year 99 is allowed so that TwoDitYearMax is disabled.
+ }
+ else
+ {
+ CheckHebrewYearValue(value, HebrewEra, "value");
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100) {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxHebrewYear || year < MinHebrewYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MinHebrewYear,
+ MaxHebrewYear));
+ }
+ return (year);
+ }
+
+ internal class __DateBuffer {
+ internal int year;
+ internal int month;
+ internal int day;
+ }
+
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/Globalization/HebrewNumber.cs b/src/mscorlib/src/System/Globalization/HebrewNumber.cs
new file mode 100644
index 0000000000..cf0595585a
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/HebrewNumber.cs
@@ -0,0 +1,402 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Globalization {
+ using System;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Used in HebrewNumber.ParseByChar to maintain the context information (
+ // the state in the state machine and current Hebrew number values, etc.)
+ // when parsing Hebrew number character by character.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal struct HebrewNumberParsingContext {
+ // The current state of the state machine for parsing Hebrew numbers.
+ internal HebrewNumber.HS state;
+ // The current value of the Hebrew number.
+ // The final value is determined when state is FoundEndOfHebrewNumber.
+ internal int result;
+
+ public HebrewNumberParsingContext(int result) {
+ // Set the start state of the state machine for parsing Hebrew numbers.
+ state = HebrewNumber.HS.Start;
+ this.result = result;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Please see ParseByChar() for comments about different states defined here.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum HebrewNumberParsingState {
+ InvalidHebrewNumber,
+ NotHebrewDigit,
+ FoundEndOfHebrewNumber,
+ ContinueParsing,
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // class HebrewNumber
+ //
+ // Provides static methods for formatting integer values into
+ // Hebrew text and parsing Hebrew number text.
+ //
+ // Limitations:
+ // Parse can only handles value 1 ~ 999.
+ // ToString() can only handles 1 ~ 999. If value is greater than 5000,
+ // 5000 will be subtracted from the value.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal class HebrewNumber {
+
+ // This class contains only static methods. Add a private ctor so that
+ // compiler won't generate a default one for us.
+ private HebrewNumber() {
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Converts the given number to Hebrew letters according to the numeric
+ // value of each Hebrew letter. Basically, this converts the lunar year
+ // and the lunar month to letters.
+ //
+ // The character of a year is described by three letters of the Hebrew
+ // alphabet, the first and third giving, respectively, the days of the
+ // weeks on which the New Year occurs and Passover begins, while the
+ // second is the initial of the Hebrew word for defective, normal, or
+ // complete.
+ //
+ // Defective Year : Both Heshvan and Kislev are defective (353 or 383 days)
+ // Normal Year : Heshvan is defective, Kislev is full (354 or 384 days)
+ // Complete Year : Both Heshvan and Kislev are full (355 or 385 days)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal static String ToString(int Number) {
+ char cTens = '\x0';
+ char cUnits; // tens and units chars
+ int Hundreds, Tens; // hundreds and tens values
+ StringBuilder szHebrew = new StringBuilder();
+
+
+ //
+ // Adjust the number if greater than 5000.
+ //
+ if (Number > 5000) {
+ Number -= 5000;
+ }
+
+ Contract.Assert(Number > 0 && Number <= 999, "Number is out of range.");;
+
+ //
+ // Get the Hundreds.
+ //
+ Hundreds = Number / 100;
+
+ if (Hundreds > 0) {
+ Number -= Hundreds * 100;
+ // \x05e7 = 100
+ // \x05e8 = 200
+ // \x05e9 = 300
+ // \x05ea = 400
+ // If the number is greater than 400, use the multiples of 400.
+ for (int i = 0; i < (Hundreds / 4) ; i++) {
+ szHebrew.Append('\x05ea');
+ }
+
+ int remains = Hundreds % 4;
+ if (remains > 0) {
+ szHebrew.Append((char)((int)'\x05e6' + remains));
+ }
+ }
+
+ //
+ // Get the Tens.
+ //
+ Tens = Number / 10;
+ Number %= 10;
+
+ switch (Tens) {
+ case ( 0 ) :
+ cTens = '\x0';
+ break;
+ case ( 1 ) :
+ cTens = '\x05d9'; // Hebrew Letter Yod
+ break;
+ case ( 2 ) :
+ cTens = '\x05db'; // Hebrew Letter Kaf
+ break;
+ case ( 3 ) :
+ cTens = '\x05dc'; // Hebrew Letter Lamed
+ break;
+ case ( 4 ) :
+ cTens = '\x05de'; // Hebrew Letter Mem
+ break;
+ case ( 5 ) :
+ cTens = '\x05e0'; // Hebrew Letter Nun
+ break;
+ case ( 6 ) :
+ cTens = '\x05e1'; // Hebrew Letter Samekh
+ break;
+ case ( 7 ) :
+ cTens = '\x05e2'; // Hebrew Letter Ayin
+ break;
+ case ( 8 ) :
+ cTens = '\x05e4'; // Hebrew Letter Pe
+ break;
+ case ( 9 ) :
+ cTens = '\x05e6'; // Hebrew Letter Tsadi
+ break;
+ }
+
+ //
+ // Get the Units.
+ //
+ cUnits = (char)(Number > 0 ? ((int)'\x05d0' + Number - 1) : 0);
+
+ if ((cUnits == '\x05d4') && // Hebrew Letter He (5)
+ (cTens == '\x05d9')) { // Hebrew Letter Yod (10)
+ cUnits = '\x05d5'; // Hebrew Letter Vav (6)
+ cTens = '\x05d8'; // Hebrew Letter Tet (9)
+ }
+
+ if ((cUnits == '\x05d5') && // Hebrew Letter Vav (6)
+ (cTens == '\x05d9')) { // Hebrew Letter Yod (10)
+ cUnits = '\x05d6'; // Hebrew Letter Zayin (7)
+ cTens = '\x05d8'; // Hebrew Letter Tet (9)
+ }
+
+ //
+ // Copy the appropriate info to the given buffer.
+ //
+
+ if (cTens != '\x0') {
+ szHebrew.Append(cTens);
+ }
+
+ if (cUnits != '\x0') {
+ szHebrew.Append(cUnits);
+ }
+
+ if (szHebrew.Length > 1) {
+ szHebrew.Insert(szHebrew.Length - 1, '"');
+ } else {
+ szHebrew.Append('\'');
+ }
+
+ //
+ // Return success.
+ //
+ return (szHebrew.ToString());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Token used to tokenize a Hebrew word into tokens so that we can use in the
+ // state machine.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ enum HebrewToken {
+ Invalid = -1,
+ Digit400 = 0,
+ Digit200_300 = 1,
+ Digit100 = 2,
+ Digit10 = 3, // 10 ~ 90
+ Digit1 = 4, // 1, 2, 3, 4, 5, 8,
+ Digit6_7 = 5,
+ Digit7 = 6,
+ Digit9 = 7,
+ SingleQuote = 8,
+ DoubleQuote = 9,
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // This class is used to map a token into its Hebrew digit value.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ class HebrewValue {
+ internal HebrewToken token;
+ internal int value;
+ internal HebrewValue(HebrewToken token, int value) {
+ this.token = token;
+ this.value = value;
+ }
+ }
+
+ //
+ // Map a Hebrew character from U+05D0 ~ U+05EA to its digit value.
+ // The value is -1 if the Hebrew character does not have a associated value.
+ //
+ static HebrewValue[] HebrewValues = {
+ new HebrewValue(HebrewToken.Digit1, 1) , // '\x05d0
+ new HebrewValue(HebrewToken.Digit1, 2) , // '\x05d1
+ new HebrewValue(HebrewToken.Digit1, 3) , // '\x05d2
+ new HebrewValue(HebrewToken.Digit1, 4) , // '\x05d3
+ new HebrewValue(HebrewToken.Digit1, 5) , // '\x05d4
+ new HebrewValue(HebrewToken.Digit6_7,6) , // '\x05d5
+ new HebrewValue(HebrewToken.Digit6_7,7) , // '\x05d6
+ new HebrewValue(HebrewToken.Digit1, 8) , // '\x05d7
+ new HebrewValue(HebrewToken.Digit9, 9) , // '\x05d8
+ new HebrewValue(HebrewToken.Digit10, 10) , // '\x05d9; // Hebrew Letter Yod
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05da;
+ new HebrewValue(HebrewToken.Digit10, 20) , // '\x05db; // Hebrew Letter Kaf
+ new HebrewValue(HebrewToken.Digit10, 30) , // '\x05dc; // Hebrew Letter Lamed
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05dd;
+ new HebrewValue(HebrewToken.Digit10, 40) , // '\x05de; // Hebrew Letter Mem
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05df;
+ new HebrewValue(HebrewToken.Digit10, 50) , // '\x05e0; // Hebrew Letter Nun
+ new HebrewValue(HebrewToken.Digit10, 60) , // '\x05e1; // Hebrew Letter Samekh
+ new HebrewValue(HebrewToken.Digit10, 70) , // '\x05e2; // Hebrew Letter Ayin
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e3;
+ new HebrewValue(HebrewToken.Digit10, 80) , // '\x05e4; // Hebrew Letter Pe
+ new HebrewValue(HebrewToken.Invalid, -1) , // '\x05e5;
+ new HebrewValue(HebrewToken.Digit10, 90) , // '\x05e6; // Hebrew Letter Tsadi
+ new HebrewValue(HebrewToken.Digit100, 100) , // '\x05e7;
+ new HebrewValue(HebrewToken.Digit200_300, 200) , // '\x05e8;
+ new HebrewValue(HebrewToken.Digit200_300, 300) , // '\x05e9;
+ new HebrewValue(HebrewToken.Digit400, 400) , // '\x05ea;
+ };
+
+ const int minHebrewNumberCh = 0x05d0;
+ static char maxHebrewNumberCh = (char)(minHebrewNumberCh + HebrewValues.Length - 1);
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Hebrew number parsing State
+ // The current state and the next token will lead to the next state in the state machine.
+ // DQ = Double Quote
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ internal enum HS {
+ _err = -1, // an error state
+ Start = 0,
+ S400 = 1, // a Hebrew digit 400
+ S400_400 = 2, // Two Hebrew digit 400
+ S400_X00 = 3, // Two Hebrew digit 400 and followed by 100
+ S400_X0 = 4, // Hebrew digit 400 and followed by 10 ~ 90
+ X00_DQ = 5, // A hundred number and followed by a double quote.
+ S400_X00_X0 = 6,
+ X0_DQ = 7, // A two-digit number and followed by a double quote.
+ X = 8, // A single digit Hebrew number.
+ X0 = 9, // A two-digit Hebrew number
+ X00 = 10, // A three-digit Hebrew number
+ S400_DQ = 11, // A Hebrew digit 400 and followed by a double quote.
+ S400_400_DQ = 12,
+ S400_400_100 = 13,
+ S9 = 14, // Hebrew digit 9
+ X00_S9 = 15, // A hundered number and followed by a digit 9
+ S9_DQ = 16, // Hebrew digit 9 and followed by a double quote
+ END = 100, // A terminial state is reached.
+ }
+
+ //
+ // The state machine for Hebrew number pasing.
+ //
+ readonly static HS[][] NumberPasingState = {
+ // 400 300/200 100 90~10 8~1 6, 7, 9, ' "
+ /* 0 */ new HS[] {HS.S400, HS.X00, HS.X00, HS.X0, HS.X, HS.X, HS.X, HS.S9, HS._err, HS._err},
+ /* 1: S400 */ new HS[] {HS.S400_400, HS.S400_X00, HS.S400_X00, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS.END, HS.S400_DQ},
+ /* 2: S400_400 */ new HS[] {HS._err, HS._err, HS.S400_400_100,HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.S400_400_DQ},
+ /* 3: S400_X00 */ new HS[] {HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9 ,HS._err, HS.X00_DQ},
+ /* 4: S400_X0 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ},
+ /* 5: X00_DQ */ new HS[] {HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err},
+ /* 6: S400_X00_X0 */new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.X0_DQ},
+ /* 7: X0_DQ */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err},
+ /* 8: X */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS._err},
+ /* 9: X0 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.X0_DQ},
+ /* 10: X00 */ new HS[] {HS._err, HS._err, HS._err, HS.S400_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS.END, HS.X00_DQ},
+ /* 11: S400_DQ */ new HS[] {HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err},
+ /* 12: S400_400_DQ*/new HS[] {HS._err, HS._err, HS.END, HS.END, HS.END, HS.END, HS.END, HS.END, HS._err, HS._err},
+ /* 13: S400_400_100*/new HS[]{HS._err, HS._err, HS._err, HS.S400_X00_X0, HS._err, HS._err, HS._err, HS.X00_S9, HS._err, HS.X00_DQ},
+ /* 14: S9 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err,HS.END, HS.S9_DQ},
+ /* 15: X00_S9 */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS._err, HS.S9_DQ},
+ /* 16: S9_DQ */ new HS[] {HS._err, HS._err, HS._err, HS._err, HS._err, HS.END, HS.END, HS._err, HS._err, HS._err},
+ };
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Parse the Hebrew number by passing one character at a time.
+ // The state between characters are maintained at HebrewNumberPasingContext.
+ // Returns:
+ // Return a enum of HebrewNumberParsingState.
+ // NotHebrewDigit: The specified ch is not a valid Hebrew digit.
+ // InvalidHebrewNumber: After parsing the specified ch, it will lead into
+ // an invalid Hebrew number text.
+ // FoundEndOfHebrewNumber: A terminal state is reached. This means that
+ // we find a valid Hebrew number text after the specified ch is parsed.
+ // ContinueParsing: The specified ch is a valid Hebrew digit, and
+ // it will lead into a valid state in the state machine, we should
+ // continue to parse incoming characters.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static HebrewNumberParsingState ParseByChar(char ch, ref HebrewNumberParsingContext context) {
+ HebrewToken token;
+ if (ch == '\'') {
+ token = HebrewToken.SingleQuote;
+ } else if (ch == '\"') {
+ token = HebrewToken.DoubleQuote;
+ } else {
+ int index = (int)ch - minHebrewNumberCh;
+ if (index >= 0 && index < HebrewValues.Length ) {
+ token = HebrewValues[index].token;
+ if (token == HebrewToken.Invalid) {
+ return (HebrewNumberParsingState.NotHebrewDigit);
+ }
+ context.result += HebrewValues[index].value;
+ } else {
+ // Not in valid Hebrew digit range.
+ return (HebrewNumberParsingState.NotHebrewDigit);
+ }
+ }
+ context.state = NumberPasingState[(int)context.state][(int)token];
+ if (context.state == HS._err) {
+ // Invalid Hebrew state. This indicates an incorrect Hebrew number.
+ return (HebrewNumberParsingState.InvalidHebrewNumber);
+ }
+ if (context.state == HS.END) {
+ // Reach a terminal state.
+ return (HebrewNumberParsingState.FoundEndOfHebrewNumber);
+ }
+ // We should continue to parse.
+ return (HebrewNumberParsingState.ContinueParsing);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Actions:
+ // Check if the ch is a valid Hebrew number digit.
+ // This function will return true if the specified char is a legal Hebrew
+ // digit character, single quote, or double quote.
+ // Returns:
+ // true if the specified character is a valid Hebrew number character.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static bool IsDigit(char ch) {
+ if (ch >= minHebrewNumberCh && ch <= maxHebrewNumberCh) {
+ return (HebrewValues[ch - minHebrewNumberCh].value >= 0);
+ }
+ return (ch == '\'' || ch == '\"');
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/HijriCalendar.cs b/src/mscorlib/src/System/Globalization/HijriCalendar.cs
new file mode 100644
index 0000000000..194d329d25
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/HijriCalendar.cs
@@ -0,0 +1,723 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_WIN32_REGISTRY
+ using System.Text;
+ using Microsoft.Win32;
+#endif // FEATURE_WIN32_REGISTRY
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Rules for the Hijri calendar:
+ // - The Hijri calendar is a strictly Lunar calendar.
+ // - Days begin at sunset.
+ // - Islamic Year 1 (Muharram 1, 1 A.H.) is equivalent to absolute date
+ // 227015 (Friday, July 16, 622 C.E. - Julian).
+ // - Leap Years occur in the 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, & 29th
+ // years of a 30-year cycle. Year = leap iff ((11y+14) mod 30 < 11).
+ // - There are 12 months which contain alternately 30 and 29 days.
+ // - The 12th month, Dhu al-Hijjah, contains 30 days instead of 29 days
+ // in a leap year.
+ // - Common years have 354 days. Leap years have 355 days.
+ // - There are 10,631 days in a 30-year cycle.
+ // - The Islamic months are:
+ // 1. Muharram (30 days) 7. Rajab (30 days)
+ // 2. Safar (29 days) 8. Sha'ban (29 days)
+ // 3. Rabi I (30 days) 9. Ramadan (30 days)
+ // 4. Rabi II (29 days) 10. Shawwal (29 days)
+ // 5. Jumada I (30 days) 11. Dhu al-Qada (30 days)
+ // 6. Jumada II (29 days) 12. Dhu al-Hijjah (29 days) {30}
+ //
+ // NOTENOTE
+ // The calculation of the HijriCalendar is based on the absolute date. And the
+ // absolute date means the number of days from January 1st, 1 A.D.
+ // Therefore, we do not support the days before the January 1st, 1 A.D.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0622/07/18 9999/12/31
+ ** Hijri 0001/01/01 9666/04/03
+ */
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class HijriCalendar : Calendar {
+
+
+ public static readonly int HijriEra = 1;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ internal const int MinAdvancedHijri = -2;
+ internal const int MaxAdvancedHijri = 2;
+
+ internal static readonly int[] HijriMonthDays = {0,30,59,89,118,148,177,207,236,266,295,325,355};
+
+ //internal static Calendar m_defaultInstance;
+
+#if FEATURE_WIN32_REGISTRY
+ private const String InternationalRegKey = "Control Panel\\International";
+ private const String HijriAdvanceRegKeyEntry = "AddHijriDate";
+#endif
+
+ private int m_HijriAdvance = Int32.MinValue;
+
+ // DateTime.MaxValue = Hijri calendar (year:9666, month: 4, day: 3).
+ internal const int MaxCalendarYear = 9666;
+ internal const int MaxCalendarMonth = 4;
+ internal const int MaxCalendarDay = 3;
+ // Hijri calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 7, day: 18)
+ // This is the minimal Gregorian date that we support in the HijriCalendar.
+ internal static readonly DateTime calendarMinValue = new DateTime(622, 7, 18);
+ internal static readonly DateTime calendarMaxValue = DateTime.MaxValue;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (calendarMaxValue);
+ }
+ }
+
+ // Return the type of the Hijri calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.LunarCalendar;
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of HijriCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new HijriCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+ // Construct an instance of Hijri calendar.
+
+ public HijriCalendar() {
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_HIJRI);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // the year before the 1st year of the cycle would have been the 30th year
+ // of the previous cycle which is not a leap year. Common years have 354 days.
+ return 354;
+ }
+ }
+
+
+
+ /*=================================GetAbsoluteDateHijri==========================
+ **Action: Gets the Absolute date for the given Hijri date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ long GetAbsoluteDateHijri(int y, int m, int d) {
+ return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m-1] + d - 1 - HijriAdjustment);
+ }
+
+ /*=================================DaysUpToHijriYear==========================
+ **Action: Gets the total number of days (absolute date) up to the given Hijri Year.
+ ** The absolute date means the number of days from January 1st, 1 A.D.
+ **Returns: Gets the total number of days (absolute date) up to the given Hijri Year.
+ **Arguments: HijriYear year value in Hijri calendar.
+ **Exceptions: None
+ **Notes:
+ ============================================================================*/
+
+ long DaysUpToHijriYear(int HijriYear) {
+ long NumDays; // number of absolute days
+ int NumYear30; // number of years up to current 30 year cycle
+ int NumYearsLeft; // number of years into 30 year cycle
+
+ //
+ // Compute the number of years up to the current 30 year cycle.
+ //
+ NumYear30 = ((HijriYear - 1) / 30) * 30;
+
+ //
+ // Compute the number of years left. This is the number of years
+ // into the 30 year cycle for the given year.
+ //
+ NumYearsLeft = HijriYear - NumYear30 - 1;
+
+ //
+ // Compute the number of absolute days up to the given year.
+ //
+ NumDays = ((NumYear30 * 10631L) / 30L) + 227013L;
+ while (NumYearsLeft > 0) {
+ // Common year is 354 days, and leap year is 355 days.
+ NumDays += 354 + (IsLeapYear(NumYearsLeft, CurrentEra) ? 1: 0);
+ NumYearsLeft--;
+ }
+
+ //
+ // Return the number of absolute days.
+ //
+ return (NumDays);
+ }
+
+
+ public int HijriAdjustment {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (m_HijriAdvance == Int32.MinValue) {
+ // Never been set before. Use the system value from registry.
+ m_HijriAdvance = GetAdvanceHijriDate();
+ }
+ return (m_HijriAdvance);
+ }
+
+ set {
+ // NOTE: Check the value of Min/MaxAdavncedHijri with Arabic speakers to see if the assumption is good.
+ if (value < MinAdvancedHijri || value > MaxAdvancedHijri) {
+ throw new ArgumentOutOfRangeException(
+ "HijriAdjustment",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"),
+ MinAdvancedHijri,
+ MaxAdvancedHijri));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ m_HijriAdvance = value;
+ }
+ }
+
+ /*=================================GetAdvanceHijriDate==========================
+ **Action: Gets the AddHijriDate value from the registry.
+ **Returns:
+ **Arguments: None.
+ **Exceptions:
+ **Note:
+ ** The HijriCalendar has a user-overidable calculation. That is, use can set a value from the control
+ ** panel, so that the calculation of the Hijri Calendar can move ahead or backwards from -2 to +2 days.
+ **
+ ** The valid string values in the registry are:
+ ** "AddHijriDate-2" => Add -2 days to the current calculated Hijri date.
+ ** "AddHijriDate" => Add -1 day to the current calculated Hijri date.
+ ** "" => Add 0 day to the current calculated Hijri date.
+ ** "AddHijriDate+1" => Add +1 days to the current calculated Hijri date.
+ ** "AddHijriDate+2" => Add +2 days to the current calculated Hijri date.
+ ============================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ static int GetAdvanceHijriDate() {
+#if FEATURE_WIN32_REGISTRY
+
+ int hijriAdvance = 0;
+ Microsoft.Win32.RegistryKey key = null;
+
+ try {
+ // Open in read-only mode.
+ // Use InternalOpenSubKey so that we avoid the security check.
+ key = Microsoft.Win32.Registry.CurrentUser.InternalOpenSubKey(InternationalRegKey, false);
+ }
+ //If this fails for any reason, we'll just return 0.
+ catch (ObjectDisposedException) { return 0; }
+ catch (ArgumentException) { return 0; }
+
+ if (key != null) {
+ try {
+ Object value = key.InternalGetValue(HijriAdvanceRegKeyEntry, null, false, false);
+ if (value == null) {
+ return (0);
+ }
+ String str = value.ToString();
+ if (String.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) {
+ if (str.Length == HijriAdvanceRegKeyEntry.Length)
+ hijriAdvance = -1;
+ else {
+ str = str.Substring(HijriAdvanceRegKeyEntry.Length);
+ try {
+ int advance = Int32.Parse(str.ToString(), CultureInfo.InvariantCulture);
+ if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) {
+ hijriAdvance = advance;
+ }
+ }
+ // If we got garbage from registry just ignore it.
+ // hijriAdvance = 0 because of declaraction assignment up above.
+ catch (ArgumentException) { }
+ catch (FormatException) { }
+ catch (OverflowException) { }
+ }
+ }
+ }
+ finally {
+ key.Close();
+ }
+
+ }
+ return (hijriAdvance);
+
+#else //FEATURE_WIN32_REGISTRY
+ return 0;
+#endif // FEATURE_WIN32_REGISTRY
+ }
+
+ static internal void CheckTicksRange(long ticks) {
+ if (ticks < calendarMinValue.Ticks || ticks > calendarMaxValue.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ calendarMinValue,
+ calendarMaxValue));
+ }
+ }
+
+ static internal void CheckEraRange(int era) {
+ if (era != CurrentEra && era != HijriEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ static internal void CheckYearRange(int year, int era) {
+ CheckEraRange(era);
+ if (year < 1 || year > MaxCalendarYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarYear));
+ }
+ }
+
+ static internal void CheckYearMonthRange(int year, int month, int era) {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear) {
+ if (month > MaxCalendarMonth) {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarMonth));
+ }
+ }
+
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ **Notes:
+ ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
+ ** Use the formula (((AbsoluteDate - 227013) * 30) / 10631) + 1, we can a rough value for the Hijri year.
+ ** In order to get the exact Hijri year, we compare the exact absolute date for HijriYear and (HijriYear + 1).
+ ** From here, we can get the correct Hijri year.
+ ============================================================================*/
+
+ internal virtual int GetDatePart(long ticks, int part) {
+ int HijriYear; // Hijri year
+ int HijriMonth; // Hijri month
+ int HijriDay; // Hijri day
+ long NumDays; // The calculation buffer in number of days.
+
+ CheckTicksRange(ticks);
+
+ //
+ // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ //
+ NumDays = ticks / GregorianCalendar.TicksPerDay + 1;
+
+ //
+ // See how much we need to backup or advance
+ //
+ NumDays += HijriAdjustment;
+
+ //
+ // Calculate the appromixate Hijri Year from this magic formula.
+ //
+ HijriYear = (int)(((NumDays - 227013) * 30) / 10631) + 1;
+
+ long daysToHijriYear = DaysUpToHijriYear(HijriYear); // The absoulte date for HijriYear
+ long daysOfHijriYear = GetDaysInYear(HijriYear, CurrentEra); // The number of days for (HijriYear+1) year.
+
+ if (NumDays < daysToHijriYear) {
+ daysToHijriYear -= daysOfHijriYear;
+ HijriYear--;
+ } else if (NumDays == daysToHijriYear) {
+ HijriYear--;
+ daysToHijriYear -= GetDaysInYear(HijriYear, CurrentEra);
+ } else {
+ if (NumDays > daysToHijriYear + daysOfHijriYear) {
+ daysToHijriYear += daysOfHijriYear;
+ HijriYear++;
+ }
+ }
+ if (part == DatePartYear) {
+ return (HijriYear);
+ }
+
+ //
+ // Calculate the Hijri Month.
+ //
+
+ HijriMonth = 1;
+ NumDays -= daysToHijriYear;
+
+ if (part == DatePartDayOfYear) {
+ return ((int)NumDays);
+ }
+
+ while ((HijriMonth <= 12) && (NumDays > HijriMonthDays[HijriMonth - 1])) {
+ HijriMonth++;
+ }
+ HijriMonth--;
+
+ if (part == DatePartMonth) {
+ return (HijriMonth);
+ }
+
+ //
+ // Calculate the Hijri Day.
+ //
+ HijriDay = (int)(NumDays - HijriMonthDays[HijriMonth - 1]);
+
+ if (part == DatePartDay) {
+ return (HijriDay);
+ }
+ // Incorrect part value.
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing"));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in Hijri calendar.
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0) {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ } else {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int days = GetDaysInMonth(y, m);
+ if (d > days) {
+ d = days;
+ }
+ long ticks = GetAbsoluteDateHijri(y, m, d)* TicksPerDay + (time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+ public override int GetDayOfYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+ [Pure]
+ public override int GetDaysInMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+ if (month == 12) {
+ // For the 12th month, leap year has 30 days, and common year has 29 days.
+ return (IsLeapYear(year, CurrentEra) ? 30 : 29);
+ }
+ // Other months contain 30 and 29 days alternatively. The 1st month has 30 days.
+ return (((month % 2) == 1) ? 30 : 29);
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era) {
+ CheckYearRange(year, era);
+ // Common years have 354 days. Leap years have 355 days.
+ return (IsLeapYear(year, CurrentEra) ? 355: 354);
+ }
+
+ // Returns the era for the specified DateTime value.
+
+ public override int GetEra(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return (HijriEra);
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {HijriEra});
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+ public override int GetMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+ public override int GetMonthsInYear(int year, int era) {
+ CheckYearRange(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+ public override int GetYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+ public override bool IsLeapDay(int year, int month, int day, int era) {
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+ return (IsLeapYear(year, era) && month == 12 && day == 30);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era) {
+ CheckYearRange(year, era);
+ return ((((year * 11) + 14) % 30) < 11);
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ // The year/month/era checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+
+ long lDate = GetAbsoluteDateHijri(year, month, day);
+
+ if (lDate >= 0) {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ } else {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451;
+
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ MaxCalendarYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100) {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxCalendarYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/IdnMapping.cs b/src/mscorlib/src/System/Globalization/IdnMapping.cs
new file mode 100644
index 0000000000..599a32ad87
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/IdnMapping.cs
@@ -0,0 +1,1189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// This file contains the IDN functions and implementation.
+//
+// This allows encoding of non-ASCII domain names in a "punycode" form,
+// for example:
+//
+// \u5B89\u5BA4\u5948\u7F8E\u6075-with-SUPER-MONKEYS
+//
+// is encoded as:
+//
+// xn---with-SUPER-MONKEYS-pc58ag80a8qai00g7n9n
+//
+// Additional options are provided to allow unassigned IDN characters and
+// to validate according to the Std3ASCII Rules (like DNS names).
+//
+// There are also rules regarding bidirectionality of text and the length
+// of segments.
+//
+// For additional rules see also:
+// RFC 3490 - Internationalizing Domain Names in Applications (IDNA)
+// RFC 3491 - Nameprep: A Stringprep Profile for Internationalized Domain Names (IDN)
+// RFC 3492 - Punycode: A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)
+//
+
+/*
+
+The punycode implementation is based on the sample code in RFC 3492
+
+Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+This document and translations of it may be copied and furnished to
+others, and derivative works that comment on or otherwise explain it
+or assist in its implementation may be prepared, copied, published
+and distributed, in whole or in part, without restriction of any
+kind, provided that the above copyright notice and this paragraph are
+included on all such copies and derivative works. However, this
+document itself may not be modified in any way, such as by removing
+the copyright notice or references to the Internet Society or other
+Internet organizations, except as needed for the purpose of
+developing Internet standards in which case the procedures for
+copyrights defined in the Internet Standards process must be
+followed, or as required to translate it into languages other than
+English.
+
+The limited permissions granted above are perpetual and will not be
+revoked by the Internet Society or its successors or assigns.
+
+This document and the information contained herein is provided on an
+"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+*/
+
+namespace System.Globalization
+{
+ using System;
+ using System.Security;
+ using System.Globalization;
+ using System.Text;
+ using System.Runtime.Versioning;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // IdnMapping class used to map names to Punycode
+
+ public sealed class IdnMapping
+ {
+ // Legal name lengths for domain names
+ const int M_labelLimit = 63; // Not including dots
+ const int M_defaultNameLimit = 255; // Including dots
+
+ // IDNA prefix
+ const String M_strAcePrefix = "xn--";
+
+ // Legal "dot" seperators (i.e: . in www.microsoft.com)
+ static char[] M_Dots =
+ {
+ '.', '\u3002', '\uFF0E', '\uFF61'
+ };
+
+ bool m_bAllowUnassigned;
+ bool m_bUseStd3AsciiRules;
+
+ public IdnMapping()
+ {
+ }
+
+ public bool AllowUnassigned
+ {
+ get
+ {
+ return this.m_bAllowUnassigned;
+ }
+
+ set
+ {
+ this.m_bAllowUnassigned = value;
+ }
+ }
+
+ public bool UseStd3AsciiRules
+ {
+ get
+ {
+ return this.m_bUseStd3AsciiRules;
+ }
+
+ set
+ {
+ this.m_bUseStd3AsciiRules = value;
+ }
+ }
+
+ // Gets ASCII (Punycode) version of the string
+ public String GetAscii(String unicode)
+ {
+ return GetAscii(unicode, 0);
+ }
+
+ public String GetAscii(String unicode, int index)
+ {
+ if (unicode==null) throw new ArgumentNullException("unicode");
+ Contract.EndContractBlock();
+ return GetAscii(unicode, index, unicode.Length - index);
+ }
+
+ public String GetAscii(String unicode, int index, int count)
+ {
+ throw null;
+ /*if (unicode==null) throw new ArgumentNullException("unicode");
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (index > unicode.Length)
+ throw new ArgumentOutOfRangeException("byteIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (index > unicode.Length - count)
+ throw new ArgumentOutOfRangeException("unicode",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ Contract.EndContractBlock();
+
+ // We're only using part of the string
+ unicode = unicode.Substring(index, count);
+
+ if (Environment.IsWindows8OrAbove)
+ {
+ return GetAsciiUsingOS(unicode);
+ }
+
+ // Check for ASCII only string, which will be unchanged
+ if (ValidateStd3AndAscii(unicode, UseStd3AsciiRules, true))
+ {
+ return unicode;
+ }
+
+ // Cannot be null terminated (normalization won't help us with this one, and
+ // may have returned false before checking the whole string above)
+ Contract.Assert(unicode.Length >= 1, "[IdnMapping.GetAscii]Expected 0 length strings to fail before now.");
+ if (unicode[unicode.Length - 1] <= 0x1f)
+ {
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length-1 ),
+ "unicode");
+ }
+
+ // Have to correctly IDNA normalize the string and Unassigned flags
+ bool bHasLastDot = (unicode.Length > 0) && IsDot(unicode[unicode.Length - 1]);
+ unicode = unicode.Normalize((NormalizationForm)(m_bAllowUnassigned ?
+ ExtendedNormalizationForms.FormIdna : ExtendedNormalizationForms.FormIdnaDisallowUnassigned));
+
+ // Make sure we didn't normalize away something after a last dot
+ if ((!bHasLastDot) && unicode.Length > 0 && IsDot(unicode[unicode.Length - 1]))
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+ }
+
+ // May need to check Std3 rules again for non-ascii
+ if (UseStd3AsciiRules)
+ {
+ ValidateStd3AndAscii(unicode, true, false);
+ }
+
+ // Go ahead and encode it
+ return punycode_encode(unicode);*/
+ }
+
+
+ [System.Security.SecuritySafeCritical]
+ private String GetAsciiUsingOS(String unicode)
+ {
+ if (unicode.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+ }
+
+ if (unicode[unicode.Length - 1] == 0)
+ {
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequence", unicode.Length - 1),
+ "unicode");
+ }
+
+ uint flags = (uint) ((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0));
+ int length = IdnToAscii(flags, unicode, unicode.Length, null, 0);
+
+ int lastError;
+
+ if (length == 0)
+ {
+ lastError = Marshal.GetLastWin32Error();
+ if (lastError == ERROR_INVALID_NAME)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "unicode");
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), "unicode");
+ }
+
+ char [] output = new char[length];
+
+ length = IdnToAscii(flags, unicode, unicode.Length, output, length);
+ if (length == 0)
+ {
+ lastError = Marshal.GetLastWin32Error();
+ if (lastError == ERROR_INVALID_NAME)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "unicode");
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"), "unicode");
+ }
+
+ return new String(output, 0, length);
+ }
+
+ // Gets Unicode version of the string. Normalized and limited to IDNA characters.
+ public String GetUnicode(String ascii)
+ {
+ return GetUnicode(ascii, 0);
+ }
+
+ public String GetUnicode(String ascii, int index)
+ {
+ if (ascii==null) throw new ArgumentNullException("ascii");
+ Contract.EndContractBlock();
+ return GetUnicode(ascii, index, ascii.Length - index);
+ }
+
+ public String GetUnicode(String ascii, int index, int count)
+ {
+ if (ascii==null) throw new ArgumentNullException("ascii");
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0) ? "index" : "count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (index > ascii.Length)
+ throw new ArgumentOutOfRangeException("byteIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (index > ascii.Length - count)
+ throw new ArgumentOutOfRangeException("ascii",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ // This is a case (i.e. explicitly null-terminated input) where behavior in .NET and Win32 intentionally differ.
+ // The .NET APIs should (and did in v4.0 and earlier) throw an ArgumentException on input that includes a terminating null.
+ // The Win32 APIs fail on an embedded null, but not on a terminating null.
+ if (count > 0 && ascii[index + count - 1] == (char)0)
+ throw new ArgumentException("ascii",
+ Environment.GetResourceString("Argument_IdnBadPunycode"));
+ Contract.EndContractBlock();
+
+ // We're only using part of the string
+ ascii = ascii.Substring(index, count);
+
+ if (Environment.IsWindows8OrAbove)
+ {
+ return GetUnicodeUsingOS(ascii);
+ }
+
+ // Convert Punycode to Unicode
+ String strUnicode = punycode_decode(ascii);
+
+ // Output name MUST obey IDNA rules & round trip (casing differences are allowed)
+ if (!ascii.Equals(GetAscii(strUnicode), StringComparison.OrdinalIgnoreCase))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnIllegalName"), "ascii");
+
+ return strUnicode;
+ }
+
+
+ [System.Security.SecuritySafeCritical]
+ private string GetUnicodeUsingOS(string ascii)
+ {
+ uint flags = (uint)((AllowUnassigned ? IDN_ALLOW_UNASSIGNED : 0) | (UseStd3AsciiRules ? IDN_USE_STD3_ASCII_RULES : 0));
+ int length = IdnToUnicode(flags, ascii, ascii.Length, null, 0);
+ int lastError;
+
+ if (length == 0)
+ {
+ lastError = Marshal.GetLastWin32Error();
+ if (lastError == ERROR_INVALID_NAME)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "ascii");
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), "ascii");
+ }
+
+ char [] output = new char[length];
+
+ length = IdnToUnicode(flags, ascii, ascii.Length, output, length);
+ if (length == 0)
+ {
+ lastError = Marshal.GetLastWin32Error();
+ if (lastError == ERROR_INVALID_NAME)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnIllegalName"), "ascii");
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_IdnBadPunycode"), "ascii");
+ }
+
+ return new String(output, 0, length);
+ }
+
+ public override bool Equals(Object obj)
+ {
+ IdnMapping that = obj as IdnMapping;
+
+ if (that != null)
+ {
+ return this.m_bAllowUnassigned == that.m_bAllowUnassigned &&
+ this.m_bUseStd3AsciiRules == that.m_bUseStd3AsciiRules;
+ }
+
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return (this.m_bAllowUnassigned ? 100 : 200) + (this.m_bUseStd3AsciiRules ? 1000 : 2000);
+ }
+
+ // Helpers
+ static bool IsSupplementary(int cTest)
+ {
+ return cTest >= 0x10000;
+ }
+
+ // Is it a dot?
+ // are we U+002E (., full stop), U+3002 (ideographic full stop), U+FF0E (fullwidth full stop), or
+ // U+FF61 (halfwidth ideographic full stop).
+ // Note: IDNA Normalization gets rid of dots now, but testing for last dot is before normalization
+ static bool IsDot(char c)
+ {
+ return c == '.' || c == '\u3002' || c == '\uFF0E' || c == '\uFF61';
+ }
+
+
+ // See if we're only ASCII
+ static bool ValidateStd3AndAscii(string unicode, bool bUseStd3, bool bCheckAscii)
+ {
+ // If its empty, then its too small
+ if (unicode.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+ Contract.EndContractBlock();
+
+ int iLastDot = -1;
+
+ // Loop the whole string
+ for (int i = 0; i < unicode.Length; i++)
+ {
+ // Aren't allowing control chars (or 7f, but idn tables catch that, they don't catch \0 at end though)
+ if (unicode[i] <= 0x1f)
+ {
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequence", i ),
+ "unicode");
+ }
+
+ // If its Unicode or a control character, return false (non-ascii)
+ if (bCheckAscii && unicode[i] >= 0x7f)
+ return false;
+
+ // Check for dots
+ if (IsDot(unicode[i]))
+ {
+ // Can't have 2 dots in a row
+ if (i == iLastDot + 1)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+
+ // If its too far between dots then fail
+ if (i - iLastDot > M_labelLimit + 1)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "Unicode");
+
+ // If validating Std3, then char before dot can't be - char
+ if (bUseStd3 && i > 0)
+ ValidateStd3(unicode[i-1], true);
+
+ // Remember where the last dot is
+ iLastDot = i;
+ continue;
+ }
+
+ // If necessary, make sure its a valid std3 character
+ if (bUseStd3)
+ {
+ ValidateStd3(unicode[i], (i == iLastDot + 1));
+ }
+ }
+
+ // If we never had a dot, then we need to be shorter than the label limit
+ if (iLastDot == -1 && unicode.Length > M_labelLimit)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+
+ // Need to validate entire string length, 1 shorter if last char wasn't a dot
+ if (unicode.Length > M_defaultNameLimit - (IsDot(unicode[unicode.Length-1])? 0 : 1))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadNameSize",
+ M_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)),
+ "unicode");
+
+ // If last char wasn't a dot we need to check for trailing -
+ if (bUseStd3 && !IsDot(unicode[unicode.Length-1]))
+ ValidateStd3(unicode[unicode.Length-1], true);
+
+ return true;
+ }
+
+ // Validate Std3 rules for a character
+ static void ValidateStd3(char c, bool bNextToDot)
+ {
+ // Check for illegal characters
+ if ((c <= ',' || c == '/' || (c >= ':' && c <= '@') || // Lots of characters not allowed
+ (c >= '[' && c <= '`') || (c >= '{' && c <= (char)0x7F)) ||
+ (c == '-' && bNextToDot))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadStd3", c), "Unicode");
+ }
+
+ //
+ // The following punycode implementation is ported from the sample punycode.c in RFC 3492
+ // Original sample code was written by Adam M. Costello.
+ //
+
+ // Return whether a punycode code point is flagged as being upper case.
+
+ static bool HasUpperCaseFlag(char punychar)
+ {
+ return (punychar >= 'A' && punychar <= 'Z');
+ }
+
+
+ /**********************************************************/
+ /* Implementation (would normally go in its own .c file): */
+
+ /*** Bootstring parameters for Punycode ***/
+ const int punycodeBase = 36;
+ const int tmin = 1;
+ const int tmax = 26;
+ const int skew = 38;
+ const int damp = 700;
+ const int initial_bias = 72;
+ const int initial_n = 0x80;
+ const char delimiter = '-';
+
+ /* basic(cp) tests whether cp is a basic code point: */
+ static bool basic(uint cp)
+ {
+ // Is it in ASCII range?
+ return cp < 0x80;
+ }
+
+ // decode_digit(cp) returns the numeric value of a basic code */
+ // point (for use in representing integers) in the range 0 to */
+ // punycodeBase-1, or <0 if cp is does not represent a value. */
+
+ static int decode_digit(char cp)
+ {
+ if (cp >= '0' && cp <= '9')
+ return cp - '0' + 26;
+
+ // Two flavors for case differences
+ if (cp >= 'a' && cp <= 'z')
+ return cp - 'a';
+
+ if (cp >= 'A' && cp <= 'Z')
+ return cp - 'A';
+
+ // Expected 0-9, A-Z or a-z, everything else is illegal
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+ }
+
+ /* encode_digit(d,flag) returns the basic code point whose value */
+ /* (when used for representing integers) is d, which needs to be in */
+ /* the range 0 to punycodeBase-1. The lowercase form is used unless flag is */
+ /* true, in which case the uppercase form is used. */
+
+ static char encode_digit(int d)
+ {
+ Contract.Assert(d >= 0 && d < punycodeBase, "[IdnMapping.encode_digit]Expected 0 <= d < punycodeBase");
+ // 26-35 map to ASCII 0-9
+ if (d > 25) return (char)(d - 26 + '0');
+
+ // 0-25 map to a-z or A-Z
+ return (char)(d + 'a');
+ }
+
+
+
+ /* encode_basic(bcp,flag) forces a basic code point to lowercase */
+ /* if flag is false, uppercase if flag is true, and returns */
+ /* the resulting code point. The code point is unchanged if it */
+ /* is caseless. The behavior is undefined if bcp is not a basic */
+ /* code point. */
+
+ static char encode_basic(char bcp)
+ {
+ if (HasUpperCaseFlag(bcp))
+ bcp += (char)('a' - 'A');
+
+ return bcp;
+ }
+
+ /*** Platform-specific constants ***/
+
+ /* maxint is the maximum value of a uint variable: */
+ const int maxint = 0x7ffffff;
+
+ /*** Bias adaptation function ***/
+
+ static int adapt(
+ int delta, int numpoints, bool firsttime )
+ {
+ uint k;
+
+ delta = firsttime ? delta / damp : delta / 2;
+ Contract.Assert(numpoints != 0, "[IdnMapping.adapt]Expected non-zero numpoints.");
+ delta += delta / numpoints;
+
+ for (k = 0; delta > ((punycodeBase - tmin) * tmax) / 2; k += punycodeBase)
+ {
+ delta /= punycodeBase - tmin;
+ }
+
+ Contract.Assert(delta + skew != 0, "[IdnMapping.adapt]Expected non-zero delta+skew.");
+ return (int)(k + (punycodeBase - tmin + 1) * delta / (delta + skew));
+ }
+
+ /*** Main encode function ***/
+
+ /* punycode_encode() converts Unicode to Punycode. The input */
+ /* is represented as an array of Unicode code points (not code */
+ /* units; surrogate pairs are not allowed), and the output */
+ /* will be represented as an array of ASCII code points. The */
+ /* output string is *not* null-terminated; it will contain */
+ /* zeros if and only if the input contains zeros. (Of course */
+ /* the caller can leave room for a terminator and add one if */
+ /* needed.) The input_length is the number of code points in */
+ /* the input. The output_length is an in/out argument: the */
+ /* caller passes in the maximum number of code points that it */
+
+ /* can receive, and on successful return it will contain the */
+ /* number of code points actually output. The case_flags array */
+ /* holds input_length boolean values, where nonzero suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* after being decoded (if possible), and zero suggests that */
+ /* it be forced to lowercase (if possible). ASCII code points */
+ /* are encoded literally, except that ASCII letters are forced */
+ /* to uppercase or lowercase according to the corresponding */
+ /* uppercase flags. If case_flags is a null pointer then ASCII */
+ /* letters are left as they are, and other code points are */
+ /* treated as if their uppercase flags were zero. The return */
+ /* value can be any of the punycode_status values defined above */
+ /* except punycode_bad_input; if not punycode_success, then */
+ /* output_size and output might contain garbage. */
+
+ static String punycode_encode(String unicode)
+ {
+ // 0 length strings aren't allowed
+ if (unicode.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+ Contract.EndContractBlock();
+
+ StringBuilder output = new StringBuilder(unicode.Length);
+ int iNextDot = 0;
+ int iAfterLastDot = 0;
+ int iOutputAfterLastDot = 0;
+
+ // Find the next dot
+ while (iNextDot < unicode.Length)
+ {
+ // Find end of this segment
+ iNextDot = unicode.IndexOfAny(M_Dots, iAfterLastDot);
+ Contract.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken");
+ if (iNextDot < 0)
+ iNextDot = unicode.Length;
+
+ // Only allowed to have empty . section at end (www.microsoft.com.)
+ if (iNextDot == iAfterLastDot)
+ {
+ // Only allowed to have empty sections as trailing .
+ if (iNextDot != unicode.Length)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+ // Last dot, stop
+ break;
+ }
+
+ // We'll need an Ace prefix
+ output.Append(M_strAcePrefix);
+
+ // Everything resets every segment.
+ bool bRightToLeft = false;
+
+ // Check for RTL. If right-to-left, then 1st & last chars must be RTL
+ BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iAfterLastDot);
+ if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
+ {
+ // It has to be right to left.
+ bRightToLeft = true;
+
+ // Check last char
+ int iTest = iNextDot - 1;
+ if (Char.IsLowSurrogate(unicode, iTest))
+ {
+ iTest--;
+ }
+
+ eBidi = CharUnicodeInfo.GetBidiCategory(unicode, iTest);
+ if (eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic)
+ {
+ // Oops, last wasn't RTL, last should be RTL if first is RTL
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadBidi"), "unicode");
+ }
+ }
+
+ // Handle the basic code points
+ int basicCount;
+ int numProcessed = 0; // Num code points that have been processed so far (this segment)
+ for (basicCount = iAfterLastDot; basicCount < iNextDot; basicCount++)
+ {
+ // Can't be lonely surrogate because it would've thrown in normalization
+ Contract.Assert(Char.IsLowSurrogate(unicode, basicCount) == false,
+ "[IdnMapping.punycode_encode]Unexpected low surrogate");
+
+ // Double check our bidi rules
+ BidiCategory testBidi = CharUnicodeInfo.GetBidiCategory(unicode, basicCount);
+
+ // If we're RTL, we can't have LTR chars
+ if (bRightToLeft && testBidi == BidiCategory.LeftToRight)
+ {
+ // Oops, throw error
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadBidi"), "unicode");
+ }
+
+ // If we're not RTL we can't have RTL chars
+ if (!bRightToLeft && (testBidi == BidiCategory.RightToLeft ||
+ testBidi == BidiCategory.RightToLeftArabic))
+ {
+ // Oops, throw error
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadBidi"), "unicode");
+ }
+
+ // If its basic then add it
+ if (basic(unicode[basicCount]))
+ {
+ output.Append(encode_basic(unicode[basicCount]));
+ numProcessed++;
+ }
+ // If its a surrogate, skip the next since our bidi category tester doesn't handle it.
+ else if (Char.IsSurrogatePair(unicode, basicCount))
+ basicCount++;
+ }
+
+ int numBasicCodePoints = numProcessed; // number of basic code points
+
+ // Stop if we ONLY had basic code points
+ if (numBasicCodePoints == iNextDot - iAfterLastDot)
+ {
+ // Get rid of xn-- and this segments done
+ output.Remove(iOutputAfterLastDot, M_strAcePrefix.Length);
+ }
+ else
+ {
+ // If it has some non-basic code points the input cannot start with xn--
+ if (unicode.Length - iAfterLastDot >= M_strAcePrefix.Length &&
+ unicode.Substring(iAfterLastDot, M_strAcePrefix.Length).Equals(
+ M_strAcePrefix, StringComparison.OrdinalIgnoreCase))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "unicode");
+
+ // Need to do ACE encoding
+ int numSurrogatePairs = 0; // number of surrogate pairs so far
+
+ // Add a delimiter (-) if we had any basic code points (between basic and encoded pieces)
+ if (numBasicCodePoints > 0)
+ {
+ output.Append(delimiter);
+ }
+
+ // Initialize the state
+ int n = initial_n;
+ int delta = 0;
+ int bias = initial_bias;
+
+ // Main loop
+ while (numProcessed < (iNextDot - iAfterLastDot))
+ {
+ /* All non-basic code points < n have been */
+ /* handled already. Find the next larger one: */
+ int j;
+ int m;
+ int test = 0;
+ for (m = maxint, j = iAfterLastDot;
+ j < iNextDot;
+ j += IsSupplementary(test) ? 2 : 1)
+ {
+ test = Char.ConvertToUtf32(unicode, j);
+ if (test >= n && test < m) m = test;
+ }
+
+ /* Increase delta enough to advance the decoder's */
+ /* <n,i> state to <m,0>, but guard against overflow: */
+ delta += (int)((m - n) * ((numProcessed - numSurrogatePairs) + 1));
+ Contract.Assert(delta > 0, "[IdnMapping.cs]1 punycode_encode - delta overflowed int");
+ n = m;
+
+ for (j = iAfterLastDot; j < iNextDot; j+= IsSupplementary(test) ? 2 : 1)
+ {
+ // Make sure we're aware of surrogates
+ test = Char.ConvertToUtf32(unicode, j);
+
+ // Adjust for character position (only the chars in our string already, some
+ // haven't been processed.
+
+ if (test < n)
+ {
+ delta++;
+ Contract.Assert(delta > 0, "[IdnMapping.cs]2 punycode_encode - delta overflowed int");
+ }
+
+ if (test == n)
+ {
+ // Represent delta as a generalized variable-length integer:
+ int q, k;
+ for (q = delta, k = punycodeBase; ; k += punycodeBase)
+ {
+ int t = k <= bias ? tmin :
+ k >= bias + tmax ? tmax : k - bias;
+ if (q < t) break;
+ Contract.Assert(punycodeBase != t, "[IdnMapping.punycode_encode]Expected punycodeBase (36) to be != t");
+ output.Append(encode_digit(t + (q - t) % (punycodeBase - t)));
+ q = (q - t) / (punycodeBase - t);
+ }
+
+ output.Append(encode_digit(q));
+ bias = adapt(delta, (numProcessed - numSurrogatePairs) + 1, numProcessed == numBasicCodePoints);
+ delta = 0;
+ numProcessed++;
+
+ if (IsSupplementary(m))
+ {
+ numProcessed++;
+ numSurrogatePairs++;
+ }
+ }
+ }
+ ++delta;
+ ++n;
+ Contract.Assert(delta > 0, "[IdnMapping.cs]3 punycode_encode - delta overflowed int");
+ }
+ }
+
+ // Make sure its not too big
+ if (output.Length - iOutputAfterLastDot > M_labelLimit)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "unicode");
+
+ // Done with this segment, add dot if necessary
+ if (iNextDot != unicode.Length)
+ output.Append('.');
+
+ iAfterLastDot = iNextDot + 1;
+ iOutputAfterLastDot = output.Length;
+ }
+
+ // Throw if we're too long
+ if (output.Length > M_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadNameSize",
+ M_defaultNameLimit - (IsDot(unicode[unicode.Length-1]) ? 0 : 1)),
+ "unicode");
+
+ // Return our output string
+ return output.ToString();
+ }
+
+ /*** Main decode function ***/
+
+ /* punycode_decode() converts Punycode to Unicode. The input is */
+ /* represented as an array of ASCII code points, and the output */
+ /* will be represented as an array of Unicode code points. The */
+ /* input_length is the number of code points in the input. The */
+ /* output_length is an in/out argument: the caller passes in */
+ /* the maximum number of code points that it can receive, and */
+ /* on successful return it will contain the actual number of */
+ /* code points output. The case_flags array needs room for at */
+ /* least output_length values, or it can be a null pointer if the */
+ /* case information is not needed. A nonzero flag suggests that */
+ /* the corresponding Unicode character be forced to uppercase */
+ /* by the caller (if possible), while zero suggests that it be */
+ /* forced to lowercase (if possible). ASCII code points are */
+ /* output already in the proper case, but their flags will be set */
+ /* appropriately so that applying the flags would be harmless. */
+ /* The return value can be any of the punycode_status values */
+ /* defined above; if not punycode_success, then output_length, */
+ /* output, and case_flags might contain garbage. On success, the */
+ /* decoder will never need to write an output_length greater than */
+ /* input_length, because of how the encoding is defined. */
+
+ static String punycode_decode( String ascii )
+ {
+ // 0 length strings aren't allowed
+ if (ascii.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "ascii");
+ Contract.EndContractBlock();
+
+ // Throw if we're too long
+ if (ascii.Length > M_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadNameSize",
+ M_defaultNameLimit - (IsDot(ascii[ascii.Length-1]) ? 0 : 1)), "ascii");
+
+ // output stringbuilder
+ StringBuilder output = new StringBuilder(ascii.Length);
+
+ // Dot searching
+ int iNextDot = 0;
+ int iAfterLastDot = 0;
+ int iOutputAfterLastDot = 0;
+
+ while (iNextDot < ascii.Length)
+ {
+ // Find end of this segment
+ iNextDot = ascii.IndexOf('.', iAfterLastDot);
+ if (iNextDot < 0 || iNextDot > ascii.Length)
+ iNextDot = ascii.Length;
+
+ // Only allowed to have empty . section at end (www.microsoft.com.)
+ if (iNextDot == iAfterLastDot)
+ {
+ // Only allowed to have empty sections as trailing .
+ if (iNextDot != ascii.Length)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "ascii");
+
+ // Last dot, stop
+ break;
+ }
+
+ // In either case it can't be bigger than segment size
+ if (iNextDot - iAfterLastDot > M_labelLimit)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "ascii");
+
+ // See if this section's ASCII or ACE
+ if (ascii.Length < M_strAcePrefix.Length + iAfterLastDot ||
+ !ascii.Substring(iAfterLastDot, M_strAcePrefix.Length).Equals(
+ M_strAcePrefix, StringComparison.OrdinalIgnoreCase))
+ {
+ // Its supposed to be just ASCII
+ // Actually, for non xn-- stuff do we want to allow Unicode?
+ // for (int i = iAfterLastDot; i < iNextDot; i++)
+ // {
+ // // Only ASCII is allowed
+ // if (ascii[i] >= 0x80)
+ // throw new ArgumentException(Environment.GetResourceString(
+ // "Argument_IdnBadPunycode"), "ascii");
+// }
+
+ // Its ASCII, copy it
+ output.Append(ascii.Substring(iAfterLastDot, iNextDot - iAfterLastDot));
+
+ // ASCII doesn't have BIDI issues
+ }
+ else
+ {
+ // Not ASCII, bump up iAfterLastDot to be after ACE Prefix
+ iAfterLastDot += M_strAcePrefix.Length;
+
+ // Get number of basic code points (where delimiter is)
+ // numBasicCodePoints < 0 if there're no basic code points
+ int iTemp = ascii.LastIndexOf(delimiter, iNextDot - 1);
+
+ // Trailing - not allowed
+ if (iTemp == iNextDot - 1)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+
+ int numBasicCodePoints;
+ if (iTemp <= iAfterLastDot)
+ numBasicCodePoints = 0;
+ else
+ {
+ numBasicCodePoints = iTemp - iAfterLastDot;
+
+ // Copy all the basic code points, making sure they're all in the allowed range,
+ // and losing the casing for all of them.
+ for (int copyAscii = iAfterLastDot;
+ copyAscii < iAfterLastDot + numBasicCodePoints;
+ copyAscii++)
+ {
+ // Make sure we don't allow unicode in the ascii part
+ if (ascii[copyAscii] > 0x7f)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+
+ // When appending make sure they get lower cased
+ output.Append((char)(ascii[copyAscii] >= 'A' && ascii[copyAscii] <='Z' ?
+ ascii[copyAscii] - 'A' + 'a' :
+ ascii[copyAscii]));
+ }
+ }
+
+ // Get ready for main loop. Start at beginning if we didn't have any
+ // basic code points, otherwise start after the -.
+ // asciiIndex will be next character to read from ascii
+ int asciiIndex = iAfterLastDot +
+ ( numBasicCodePoints > 0 ? numBasicCodePoints + 1 : 0);
+
+ // initialize our state
+ int n = initial_n;
+ int bias = initial_bias;
+ int i = 0;
+
+ int w, k;
+
+ // no Supplementary characters yet
+ int numSurrogatePairs = 0;
+
+ // Main loop, read rest of ascii
+ while (asciiIndex < iNextDot)
+ {
+ /* Decode a generalized variable-length integer into delta, */
+ /* which gets added to i. The overflow checking is easier */
+ /* if we increase i as we go, then subtract off its starting */
+ /* value at the end to obtain delta. */
+ int oldi = i;
+
+ for (w = 1, k = punycodeBase; ; k += punycodeBase)
+ {
+ // Check to make sure we aren't overrunning our ascii string
+ if (asciiIndex >= iNextDot)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+
+ // decode the digit from the next char
+ int digit = decode_digit(ascii[asciiIndex++]);
+
+ Contract.Assert(w > 0, "[IdnMapping.punycode_decode]Expected w > 0");
+ if (digit > (maxint - i) / w)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+
+ i += (int)(digit * w);
+ int t = k <= bias ? tmin :
+ k >= bias + tmax ? tmax : k - bias;
+ if (digit < t) break;
+ Contract.Assert(punycodeBase != t, "[IdnMapping.punycode_decode]Expected t != punycodeBase (36)");
+ if (w > maxint / (punycodeBase - t))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+ w *= (punycodeBase - t);
+ }
+
+ bias = adapt(i - oldi,
+ (output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1, oldi == 0);
+
+ /* i was supposed to wrap around from output.Length to 0, */
+ /* incrementing n each time, so we'll fix that now: */
+ Contract.Assert((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1 > 0,
+ "[IdnMapping.punycode_decode]Expected to have added > 0 characters this segment");
+ if (i / ((output.Length - iOutputAfterLastDot - numSurrogatePairs) + 1) > maxint - n)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+ n += (int)(i / (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1));
+ i %= (output.Length - iOutputAfterLastDot - numSurrogatePairs + 1);
+
+ // If it was flagged it needs to be capitalized
+ // if (HasUpperCaseFlag(ascii[asciiIndex - 1]))
+ // {
+ // /* Case of last character determines uppercase flag: */
+ // // Any casing stuff need to happen last.
+ // If we wanted to reverse the IDNA casing data
+ // n = MakeNUpperCase(n)
+ // }
+
+ // Make sure n is legal
+ if ((n < 0 || n > 0x10ffff) || (n >= 0xD800 && n <= 0xDFFF))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+
+ // insert n at position i of the output: Really tricky if we have surrogates
+ int iUseInsertLocation;
+ String strTemp = Char.ConvertFromUtf32(n);
+
+ // If we have supplimentary characters
+ if (numSurrogatePairs > 0)
+ {
+ // Hard way, we have supplimentary characters
+ int iCount;
+ for (iCount = i, iUseInsertLocation = iOutputAfterLastDot;
+ iCount > 0;
+ iCount--, iUseInsertLocation++)
+ {
+ // If its a surrogate, we have to go one more
+ if (iUseInsertLocation >= output.Length)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadPunycode"), "ascii");
+ if (Char.IsSurrogate(output[iUseInsertLocation]))
+ iUseInsertLocation++;
+ }
+ }
+ else
+ {
+ // No Supplementary chars yet, just add i
+ iUseInsertLocation = iOutputAfterLastDot + i;
+ }
+
+ // Insert it
+ output.Insert(iUseInsertLocation, strTemp);
+
+ // If it was a surrogate increment our counter
+ if (IsSupplementary(n))
+ numSurrogatePairs++;
+
+ // Index gets updated
+ i++;
+ }
+
+ // Do BIDI testing
+ bool bRightToLeft = false;
+
+ // Check for RTL. If right-to-left, then 1st & last chars must be RTL
+ BidiCategory eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iOutputAfterLastDot);
+ if (eBidi == BidiCategory.RightToLeft || eBidi == BidiCategory.RightToLeftArabic)
+ {
+ // It has to be right to left.
+ bRightToLeft = true;
+ }
+
+ // Check the rest of them to make sure RTL/LTR is consistent
+ for (int iTest = iOutputAfterLastDot; iTest < output.Length; iTest++)
+ {
+ // This might happen if we run into a pair
+ if (Char.IsLowSurrogate(output.ToString(), iTest)) continue;
+
+ // Check to see if its LTR
+ eBidi = CharUnicodeInfo.GetBidiCategory(output.ToString(), iTest);
+ if ((bRightToLeft && eBidi == BidiCategory.LeftToRight) ||
+ (!bRightToLeft && (eBidi == BidiCategory.RightToLeft ||
+ eBidi == BidiCategory.RightToLeftArabic)))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadBidi"), "ascii");
+
+ // Make it lower case if we must (so we can test IsNormalized later)
+ // if (output[iTest] >= 'A' && output[iTest] <= 'Z')
+ // output[iTest] = (char)(output[iTest] + (char)('a' - 'A'));
+ }
+
+ // Its also a requirement that the last one be RTL if 1st is RTL
+ if (bRightToLeft && eBidi != BidiCategory.RightToLeft && eBidi != BidiCategory.RightToLeftArabic)
+ {
+ // Oops, last wasn't RTL, last should be RTL if first is RTL
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadBidi"), "ascii");
+ }
+ }
+
+ // See if this label was too long
+ if (iNextDot - iAfterLastDot > M_labelLimit)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadLabelSize"), "ascii");
+
+ // Done with this segment, add dot if necessary
+ if (iNextDot != ascii.Length)
+ output.Append('.');
+
+ iAfterLastDot = iNextDot + 1;
+ iOutputAfterLastDot = output.Length;
+ }
+
+ // Throw if we're too long
+ if (output.Length > M_defaultNameLimit - (IsDot(output[output.Length-1]) ? 0 : 1))
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_IdnBadNameSize",
+ M_defaultNameLimit -(IsDot(output[output.Length-1]) ? 0 : 1)), "ascii");
+
+ // Return our output string
+ return output.ToString();
+ }
+
+ /*
+ The previous punycode implimentation is based on the sample code in RFC 3492
+
+ Full Copyright Statement
+
+ Copyright (C) The Internet Society (2003). All Rights Reserved.
+
+ This document and translations of it may be copied and furnished to
+ others, and derivative works that comment on or otherwise explain it
+ or assist in its implementation may be prepared, copied, published
+ and distributed, in whole or in part, without restriction of any
+ kind, provided that the above copyright notice and this paragraph are
+ included on all such copies and derivative works. However, this
+ document itself may not be modified in any way, such as by removing
+ the copyright notice or references to the Internet Society or other
+ Internet organizations, except as needed for the purpose of
+ developing Internet standards in which case the procedures for
+ copyrights defined in the Internet Standards process must be
+ followed, or as required to translate it into languages other than
+ English.
+
+ The limited permissions granted above are perpetual and will not be
+ revoked by the Internet Society or its successors or assigns.
+
+ This document and the information contained herein is provided on an
+ "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+ private const int IDN_ALLOW_UNASSIGNED = 0x1;
+ private const int IDN_USE_STD3_ASCII_RULES = 0x2;
+
+ private const int ERROR_INVALID_NAME = 123;
+
+
+ [System.Security.SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
+ private static extern int IdnToAscii(
+ uint dwFlags,
+ [InAttribute()]
+ [MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
+ String lpUnicodeCharStr,
+ int cchUnicodeChar,
+ [System.Runtime.InteropServices.OutAttribute()]
+
+ char [] lpASCIICharStr,
+ int cchASCIIChar);
+
+ [System.Security.SecurityCritical]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
+ private static extern int IdnToUnicode(
+ uint dwFlags,
+ [InAttribute()]
+ [MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.LPWStr)]
+ string lpASCIICharStr,
+ int cchASCIIChar,
+ [System.Runtime.InteropServices.OutAttribute()]
+
+ char [] lpUnicodeCharStr,
+ int cchUnicodeChar);
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs
new file mode 100644
index 0000000000..2984d08ab3
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/JapaneseCalendar.cs
@@ -0,0 +1,594 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Win32;
+ using PermissionSet = System.Security.PermissionSet;
+ using System.Security.Permissions;
+
+ /*=================================JapaneseCalendar==========================
+ **
+ ** JapaneseCalendar is based on Gregorian calendar. The month and day values are the same as
+ ** Gregorian calendar. However, the year value is an offset to the Gregorian
+ ** year based on the era.
+ **
+ ** This system is adopted by Emperor Meiji in 1868. The year value is counted based on the reign of an emperor,
+ ** and the era begins on the day an emperor ascends the throne and continues until his death.
+ ** The era changes at 12:00AM.
+ **
+ ** For example, the current era is Heisei. It started on 1989/1/8 A.D. Therefore, Gregorian year 1989 is also Heisei 1st.
+ ** 1989/1/8 A.D. is also Heisei 1st 1/8.
+ **
+ ** Any date in the year during which era is changed can be reckoned in either era. For example,
+ ** 1989/1/1 can be 1/1 Heisei 1st year or 1/1 Showa 64th year.
+ **
+ ** Note:
+ ** The DateTime can be represented by the JapaneseCalendar are limited to two factors:
+ ** 1. The min value and max value of DateTime class.
+ ** 2. The available era information.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1868/09/08 9999/12/31
+ ** Japanese Meiji 01/01 Heisei 8011/12/31
+ ============================================================================*/
+
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class JapaneseCalendar : Calendar
+ {
+ internal static readonly DateTime calendarMinValue = new DateTime(1868, 9, 8);
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Japanese calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ //
+ // Using a field initializer rather than a static constructor so that the whole class can be lazy
+ // init.
+ static internal volatile EraInfo[] japaneseEraInfo;
+
+ //
+ // Read our era info
+ //
+ // m_EraInfo must be listed in reverse chronological order. The most recent era
+ // should be the first element.
+ // That is, m_EraInfo[0] contains the most recent era.
+ //
+ // We know about 4 built-in eras, however users may add additional era(s) from the
+ // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
+ //
+ // Registry values look like:
+ // yyyy.mm.dd=era_abbrev_english_englishabbrev
+ //
+ // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
+ // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
+ // era is the Japanese Era name
+ // abbrev is the Abbreviated Japanese Era Name
+ // english is the English name for the Era (unused)
+ // englishabbrev is the Abbreviated English name for the era.
+ // . is a delimiter, but the value of . doesn't matter.
+ // '_' marks the space between the japanese era name, japanese abbreviated era name
+ // english name, and abbreviated english names.
+ //
+ internal static EraInfo[] GetEraInfo()
+ {
+ // See if we need to build it
+ if (japaneseEraInfo == null)
+ {
+ // See if we have any eras from the registry
+ japaneseEraInfo = GetErasFromRegistry();
+
+ // See if we have to use the built-in eras
+ if (japaneseEraInfo == null)
+ {
+ // We know about some built-in ranges
+ EraInfo[] defaultEraRanges = new EraInfo[4];
+ defaultEraRanges[0] = new EraInfo( 4, 1989, 1, 8, 1988, 1, GregorianCalendar.MaxYear - 1988,
+ "\x5e73\x6210", "\x5e73", "H"); // era #4 start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[1] = new EraInfo( 3, 1926, 12, 25, 1925, 1, 1989-1925,
+ "\x662d\x548c", "\x662d", "S"); // era #3,start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[2] = new EraInfo( 2, 1912, 7, 30, 1911, 1, 1926-1911,
+ "\x5927\x6b63", "\x5927", "T"); // era #2,start year/month/day, yearOffset, minEraYear
+ defaultEraRanges[3] = new EraInfo( 1, 1868, 1, 1, 1867, 1, 1912-1867,
+ "\x660e\x6cbb", "\x660e", "M"); // era #1,start year/month/day, yearOffset, minEraYear
+
+ // Remember the ranges we built
+ japaneseEraInfo = defaultEraRanges;
+ }
+ }
+
+ // return the era we found/made
+ return japaneseEraInfo;
+ }
+
+
+#if FEATURE_WIN32_REGISTRY
+ private const string c_japaneseErasHive = @"System\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras";
+ private const string c_japaneseErasHivePermissionList = @"HKEY_LOCAL_MACHINE\" + c_japaneseErasHive;
+
+ //
+ // GetErasFromRegistry()
+ //
+ // We know about 4 built-in eras, however users may add additional era(s) from the
+ // registry, by adding values to HKLM\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras
+ //
+ // Registry values look like:
+ // yyyy.mm.dd=era_abbrev_english_englishabbrev
+ //
+ // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
+ // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
+ // era is the Japanese Era name
+ // abbrev is the Abbreviated Japanese Era Name
+ // english is the English name for the Era (unused)
+ // englishabbrev is the Abbreviated English name for the era.
+ // . is a delimiter, but the value of . doesn't matter.
+ // '_' marks the space between the japanese era name, japanese abbreviated era name
+ // english name, and abbreviated english names.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static EraInfo[] GetErasFromRegistry()
+ {
+ // Look in the registry key and see if we can find any ranges
+ int iFoundEras = 0;
+ EraInfo[] registryEraRanges = null;
+
+ try
+ {
+ // Need to access registry
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_japaneseErasHivePermissionList));
+ permSet.Assert();
+ RegistryKey key = Registry.LocalMachine.OpenSubKey(c_japaneseErasHive, writable: false);
+
+ // Abort if we didn't find anything
+ if (key == null) return null;
+
+ // Look up the values in our reg key
+ String[] valueNames = key.GetValueNames();
+ if (valueNames != null && valueNames.Length > 0)
+ {
+ registryEraRanges = new EraInfo[valueNames.Length];
+
+ // Loop through the registry and read in all the values
+ for (int i = 0; i < valueNames.Length; i++)
+ {
+ // See if the era is a valid date
+ EraInfo era = GetEraFromValue(valueNames[i], key.GetValue(valueNames[i]).ToString());
+
+ // continue if not valid
+ if (era == null) continue;
+
+ // Remember we found one.
+ registryEraRanges[iFoundEras] = era;
+ iFoundEras++;
+ }
+ }
+ }
+ catch (System.Security.SecurityException)
+ {
+ // If we weren't allowed to read, then just ignore the error
+ return null;
+ }
+ catch (System.IO.IOException)
+ {
+ // If key is being deleted just ignore the error
+ return null;
+ }
+ catch (System.UnauthorizedAccessException)
+ {
+ // Registry access rights permissions, just ignore the error
+ return null;
+ }
+
+ //
+ // If we didn't have valid eras, then fail
+ // should have at least 4 eras
+ //
+ if (iFoundEras < 4) return null;
+
+ //
+ // Now we have eras, clean them up.
+ //
+ // Clean up array length
+ Array.Resize(ref registryEraRanges, iFoundEras);
+
+ // Sort them
+ Array.Sort(registryEraRanges, CompareEraRanges);
+
+ // Clean up era information
+ for (int i = 0; i < registryEraRanges.Length; i++)
+ {
+ // eras count backwards from length to 1 (and are 1 based indexes into string arrays)
+ registryEraRanges[i].era = registryEraRanges.Length - i;
+
+ // update max era year
+ if (i == 0)
+ {
+ // First range is 'til the end of the calendar
+ registryEraRanges[0].maxEraYear = GregorianCalendar.MaxYear - registryEraRanges[0].yearOffset;
+ }
+ else
+ {
+ // Rest are until the next era (remember most recent era is first in array)
+ registryEraRanges[i].maxEraYear = registryEraRanges[i-1].yearOffset + 1 - registryEraRanges[i].yearOffset;
+ }
+ }
+
+ // Return our ranges
+ return registryEraRanges;
+ }
+#else
+ private static EraInfo[] GetErasFromRegistry()
+ {
+ return null;
+ }
+#endif
+
+ //
+ // Compare two era ranges, eg just the ticks
+ // Remember the era array is supposed to be in reverse chronological order
+ //
+ private static int CompareEraRanges(EraInfo a, EraInfo b)
+ {
+ return b.ticks.CompareTo(a.ticks);
+ }
+
+ //
+ // GetEraFromValue
+ //
+ // Parse the registry value name/data pair into an era
+ //
+ // Registry values look like:
+ // yyyy.mm.dd=era_abbrev_english_englishabbrev
+ //
+ // Where yyyy.mm.dd is the registry value name, and also the date of the era start.
+ // yyyy, mm, and dd are the year, month & day the era begins (4, 2 & 2 digits long)
+ // era is the Japanese Era name
+ // abbrev is the Abbreviated Japanese Era Name
+ // english is the English name for the Era (unused)
+ // englishabbrev is the Abbreviated English name for the era.
+ // . is a delimiter, but the value of . doesn't matter.
+ // '_' marks the space between the japanese era name, japanese abbreviated era name
+ // english name, and abbreviated english names.
+ private static EraInfo GetEraFromValue(String value, String data)
+ {
+ // Need inputs
+ if (value == null || data == null) return null;
+
+ //
+ // Get Date
+ //
+ // Need exactly 10 characters in name for date
+ // yyyy.mm.dd although the . can be any character
+ if (value.Length != 10) return null;
+
+ int year;
+ int month;
+ int day;
+
+ if (!Number.TryParseInt32(value.Substring(0,4), NumberStyles.None, NumberFormatInfo.InvariantInfo, out year) ||
+ !Number.TryParseInt32(value.Substring(5,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out month) ||
+ !Number.TryParseInt32(value.Substring(8,2), NumberStyles.None, NumberFormatInfo.InvariantInfo, out day))
+ {
+ // Couldn't convert integer, fail
+ return null;
+ }
+
+ //
+ // Get Strings
+ //
+ // Needs to be a certain length e_a_E_A at least (7 chars, exactly 4 groups)
+ String[] names = data.Split(new char[] {'_'});
+
+ // Should have exactly 4 parts
+ // 0 - Era Name
+ // 1 - Abbreviated Era Name
+ // 2 - English Era Name
+ // 3 - Abbreviated English Era Name
+ if (names.Length != 4) return null;
+
+ // Each part should have data in it
+ if (names[0].Length == 0 ||
+ names[1].Length == 0 ||
+ names[2].Length == 0 ||
+ names[3].Length == 0)
+ return null;
+
+ //
+ // Now we have an era we can build
+ // Note that the era # and max era year need cleaned up after sorting
+ // Don't use the full English Era Name (names[2])
+ //
+ return new EraInfo( 0, year, month, day, year - 1, 1, 0,
+ names[0], names[1], names[3]);
+ }
+
+ internal static volatile Calendar s_defaultInstance;
+ internal GregorianCalendarHelper helper;
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of JapaneseCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance() {
+ if (s_defaultInstance == null) {
+ s_defaultInstance = new JapaneseCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+
+ public JapaneseCalendar() {
+ try {
+ new CultureInfo("ja-JP");
+ } catch (ArgumentException e) {
+ throw new TypeInitializationException(this.GetType().FullName, e);
+ }
+ helper = new GregorianCalendarHelper(this, GetEraInfo());
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_JAPAN);
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (helper.AddYears(time, years));
+ }
+
+ /*=================================GetDaysInMonth==========================
+ **Action: Returns the number of days in the month given by the year and month arguments.
+ **Returns: The number of days in the given month.
+ **Arguments:
+ ** year The year in Japanese calendar.
+ ** month The month
+ ** era The Japanese era value.
+ **Exceptions
+ ** ArgumentException If month is less than 1 or greater * than 12.
+ ============================================================================*/
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era) {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+ /*=================================GetEra==========================
+ **Action: Get the era value of the specified time.
+ **Returns: The era value for the specified time.
+ **Arguments:
+ ** time the specified date time.
+ **Exceptions: ArgumentOutOfRangeException if time is out of the valid era ranges.
+ ============================================================================*/
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+
+ public override int GetMonth(DateTime time) {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time) {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era) {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+ // For Japanese calendar, four digit year is not used. Few emperors will live for more than one hundred years.
+ // Therefore, for any two digit number, we just return the original number.
+
+ public override int ToFourDigitYear(int year) {
+ if (year <= 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year > helper.MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ helper.MaxYear));
+ }
+ return (year);
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+
+ //
+ // Return the various era strings
+ // Note: The arrays are backwards of the eras
+ //
+ internal static String[] EraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] eraNames = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ eraNames[i] = eras[eras.Length - i - 1].eraName;
+ }
+
+ return eraNames;
+ }
+
+ internal static String[] AbbrevEraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] erasAbbrev = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ erasAbbrev[i] = eras[eras.Length - i - 1].abbrevEraName;
+ }
+
+ return erasAbbrev;
+ }
+
+ internal static String[] EnglishEraNames()
+ {
+ EraInfo[] eras = GetEraInfo();
+ String[] erasEnglish = new String[eras.Length];
+
+ for (int i = 0; i < eras.Length; i++)
+ {
+ // Strings are in chronological order, eras are backwards order.
+ erasEnglish[i] = eras[eras.Length - i - 1].englishEraName;
+ }
+
+ return erasEnglish;
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99;
+
+ internal override bool IsValidYear(int year, int era) {
+ return helper.IsValidYear(year, era);
+ }
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ helper.MaxYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs
new file mode 100644
index 0000000000..67cfb23833
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/JapaneseLunisolarCalendar.cs
@@ -0,0 +1,293 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about JapaneseLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1960/01/28 2050/01/22
+ ** JapaneseLunisolar 1960/01/01 2049/12/29
+ */
+
+ [Serializable]
+ public class JapaneseLunisolarCalendar : EastAsianLunisolarCalendar {
+
+ //
+ // The era value for the current era.
+ //
+
+ public const int JapaneseEra = 1;
+
+ internal GregorianCalendarHelper helper;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1960;
+ internal const int MAX_LUNISOLAR_YEAR = 2049;
+
+ internal const int MIN_GREGORIAN_YEAR = 1960;
+ internal const int MIN_GREGORIAN_MONTH = 1;
+ internal const int MIN_GREGORIAN_DAY = 28;
+
+ internal const int MAX_GREGORIAN_YEAR = 2050;
+ internal const int MAX_GREGORIAN_MONTH = 1;
+ internal const int MAX_GREGORIAN_DAY = 22;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1959 from ChineseLunisolarCalendar
+ return 354;
+ }
+ }
+
+ static readonly int [,] yinfo =
+ {
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19808 },/* 29 30 29 29 30 30 29 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+ */ };
+
+ internal override int MinCalendarYear {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo {
+ get
+ {
+ return (JapaneseCalendar.GetEraInfo());
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index) {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR ));
+ }
+ Contract.EndContractBlock();
+
+ return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time) {
+ return helper.GetYear(year, time);
+ }
+
+ internal override int GetGregorianYear(int year, int era) {
+ return helper.GetGregorianYear(year, era);
+ }
+
+ // Trim off the eras that are before our date range
+ private static EraInfo[] TrimEras(EraInfo[] baseEras)
+ {
+ EraInfo[] newEras = new EraInfo[baseEras.Length];
+ int newIndex = 0;
+
+ // Eras have most recent first, so start with that
+ for (int i = 0; i < baseEras.Length; i++)
+ {
+ // If this one's minimum year is bigger than our maximum year
+ // then we can't use it.
+ if (baseEras[i].yearOffset + baseEras[i].minEraYear >= MAX_LUNISOLAR_YEAR)
+ {
+ // skip this one.
+ continue;
+ }
+
+ // If this one's maximum era is less than our minimum era
+ // then we've gotten too low in the era #s, so we're done
+ if (baseEras[i].yearOffset + baseEras[i].maxEraYear < MIN_LUNISOLAR_YEAR)
+ {
+ break;
+ }
+
+ // Wasn't too large or too small, can use this one
+ newEras[newIndex] = baseEras[i];
+ newIndex++;
+ }
+
+ // If we didn't copy any then something was wrong, just return base
+ if (newIndex == 0) return baseEras;
+
+ // Resize the output array
+ Array.Resize(ref newEras, newIndex);
+ return newEras;
+ }
+
+
+ // Construct an instance of JapaneseLunisolar calendar.
+ public JapaneseLunisolarCalendar()
+ {
+ helper = new GregorianCalendarHelper(this, TrimEras(JapaneseCalendar.GetEraInfo()));
+ }
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+ internal override int BaseCalendarID {
+ get {
+ return (CAL_JAPAN);
+ }
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_JAPANESELUNISOLAR);
+ }
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/JulianCalendar.cs b/src/mscorlib/src/System/Globalization/JulianCalendar.cs
new file mode 100644
index 0000000000..9c8db3415c
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/JulianCalendar.cs
@@ -0,0 +1,441 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Diagnostics.Contracts;
+ //
+ // This class implements the Julian calendar. In 48 B.C. Julius Caesar ordered a calendar reform, and this calendar
+ // is called Julian calendar. It consisted of a solar year of twelve months and of 365 days with an extra day
+ // every fourth year.
+ //*
+ //* Calendar support range:
+ //* Calendar Minimum Maximum
+ //* ========== ========== ==========
+ //* Gregorian 0001/01/01 9999/12/31
+ //* Julia 0001/01/03 9999/10/19
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class JulianCalendar : Calendar {
+
+
+ public static readonly int JulianEra = 1;
+
+ private const int DatePartYear = 0;
+ private const int DatePartDayOfYear = 1;
+ private const int DatePartMonth = 2;
+ private const int DatePartDay = 3;
+
+ // Number of days in a non-leap year
+ private const int JulianDaysPerYear = 365;
+ // Number of days in 4 years
+ private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1;
+
+ //internal static Calendar m_defaultInstance;
+
+ private static readonly int[] DaysToMonth365 =
+ {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
+ };
+
+ private static readonly int[] DaysToMonth366 =
+ {
+ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
+ };
+
+ // Gregorian Calendar 9999/12/31 = Julian Calendar 9999/10/19
+ // keep it as variable field for serialization compat.
+ internal int MaxYear = 9999;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Julian calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of JulianCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new JulianCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+ // Construct an instance of gregorian calendar.
+
+ public JulianCalendar() {
+ // There is no system setting of TwoDigitYear max, so set the value here.
+ twoDigitYearMax = 2029;
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_JULIAN);
+ }
+ }
+
+ static internal void CheckEraRange(int era) {
+ if (era != CurrentEra && era != JulianEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ internal void CheckYearEraRange(int year, int era) {
+ CheckEraRange(era);
+ if (year <= 0 || year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxYear));
+ }
+ }
+
+ static internal void CheckMonthRange(int month) {
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Check for if the day value is valid.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ **Notes:
+ ** Before calling this method, call CheckYearEraRange()/CheckMonthRange() to make
+ ** sure year/month values are correct.
+ ============================================================================*/
+
+ static internal void CheckDayRange(int year, int month, int day) {
+ if (year == 1 && month == 1)
+ {
+ // The mimimum supported Julia date is Julian 0001/01/03.
+ if (day < 3) {
+ throw new ArgumentOutOfRangeException(null,
+ Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+ }
+ bool isLeapYear = (year % 4) == 0;
+ int[] days = isLeapYear ? DaysToMonth366 : DaysToMonth365;
+ int monthDays = days[month] - days[month - 1];
+ if (day < 1 || day > monthDays) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ monthDays));
+ }
+ }
+
+
+ // Returns a given date part of this DateTime. This method is used
+ // to compute the year, day-of-year, month, or day part.
+ static internal int GetDatePart(long ticks, int part)
+ {
+ // Gregorian 1/1/0001 is Julian 1/3/0001. Remember DateTime(0) is refered to Gregorian 1/1/0001.
+ // The following line convert Gregorian ticks to Julian ticks.
+ long julianTicks = ticks + TicksPerDay * 2;
+ // n = number of days since 1/1/0001
+ int n = (int)(julianTicks / TicksPerDay);
+ // y4 = number of whole 4-year periods within 100-year period
+ int y4 = n / JulianDaysPer4Years;
+ // n = day number within 4-year period
+ n -= y4 * JulianDaysPer4Years;
+ // y1 = number of whole years within 4-year period
+ int y1 = n / JulianDaysPerYear;
+ // Last year has an extra day, so decrement result if 4
+ if (y1 == 4) y1 = 3;
+ // If year was requested, compute and return it
+ if (part == DatePartYear)
+ {
+ return (y4 * 4 + y1 + 1);
+ }
+ // n = day number within year
+ n -= y1 * JulianDaysPerYear;
+ // If day-of-year was requested, return it
+ if (part == DatePartDayOfYear)
+ {
+ return (n + 1);
+ }
+ // Leap year calculation looks different from IsLeapYear since y1, y4,
+ // and y100 are relative to year 1, not year 0
+ bool leapYear = (y1 == 3);
+ int[] days = leapYear? DaysToMonth366: DaysToMonth365;
+ // All months have less than 32 days, so n >> 5 is a good conservative
+ // estimate for the month
+ int m = n >> 5 + 1;
+ // m = 1-based month number
+ while (n >= days[m]) m++;
+ // If month was requested, return it
+ if (part == DatePartMonth) return (m);
+ // Return 1-based day-of-month
+ return (n - days[m - 1] + 1);
+ }
+
+ // Returns the tick count corresponding to the given year, month, and day.
+ static internal long DateToTicks(int year, int month, int day)
+ {
+ int[] days = (year % 4 == 0)? DaysToMonth366: DaysToMonth365;
+ int y = year - 1;
+ int n = y * 365 + y / 4 + days[month - 1] + day - 1;
+ // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar.
+ // Therefore, we subtract two days in the following to convert the ticks in JulianCalendar
+ // to ticks in Gregorian calendar.
+ return ((n - 2) * TicksPerDay);
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months)
+ {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0) {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ }
+ else {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366: DaysToMonth365;
+ int days = (daysArray[m] - daysArray[m - 1]);
+
+ if (d > days) {
+ d = days;
+ }
+ long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (AddMonths(time, years * 12));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+
+ public override int GetDayOfYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ int[] days = (year % 4 == 0) ? DaysToMonth366: DaysToMonth365;
+ return (days[month] - days[month - 1]);
+ }
+
+
+ public override int GetDaysInYear(int year, int era) {
+ // Year/Era range is done in IsLeapYear().
+ return (IsLeapYear(year, era) ? 366:365);
+ }
+
+
+ public override int GetEra(DateTime time)
+ {
+ return (JulianEra);
+ }
+
+
+ public override int GetMonth(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {JulianEra});
+ }
+ }
+
+
+ public override int GetMonthsInYear(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (12);
+ }
+
+
+ public override int GetYear(DateTime time)
+ {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ CheckMonthRange(month);
+ // Year/Era range check is done in IsLeapYear().
+ if (IsLeapYear(year, era)) {
+ CheckDayRange(year, month, day);
+ return (month == 2 && day == 29);
+ }
+ CheckDayRange(year, month, day);
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (0);
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era)
+ {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearEraRange(year, era);
+ return (year % 4 == 0);
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era)
+ {
+ CheckYearEraRange(year, era);
+ CheckMonthRange(month);
+ CheckDayRange(year, month, day);
+ if (millisecond < 0 || millisecond >= MillisPerSecond) {
+ throw new ArgumentOutOfRangeException(
+ "millisecond",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ MillisPerSecond - 1));
+ }
+
+ if (hour >= 0 && hour < 24 && minute >= 0 && minute < 60 && second >=0 && second < 60)
+ {
+ return new DateTime(DateToTicks(year, month, day) + (new TimeSpan(0, hour, minute, second, millisecond)).Ticks);
+ } else
+ {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadHourMinuteSecond"));
+ }
+ }
+
+
+ public override int TwoDigitYearMax {
+ get {
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ MaxYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year > MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper"),
+ 1,
+ MaxYear));
+ }
+ return (base.ToFourDigitYear(year));
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Globalization/KoreanCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs
new file mode 100644
index 0000000000..9343884445
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/KoreanCalendar.cs
@@ -0,0 +1,265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ /*=================================KoreanCalendar==========================
+ **
+ ** Korean calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
+ ** That is,
+ ** Korean year = Gregorian year + 2333. So 2000/01/01 A.D. is Korean 4333/01/01
+ **
+ ** 0001/1/1 A.D. is Korean year 2334.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0001/01/01 9999/12/31
+ ** Korean 2334/01/01 12332/12/31
+ ============================================================================*/
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable] public class KoreanCalendar: Calendar {
+ //
+ // The era value for the current era.
+ //
+
+ public const int KoreanEra = 1;
+
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // Gregorian Year 1 is Korean year 2334, so that
+ // 1 = 2334 + yearOffset
+ // So yearOffset = -2333
+ // Gregorian year 2001 is Korean year 4334.
+
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1, 1, 1).Ticks, -2333, 2334, GregorianCalendar.MaxYear + 2333);
+
+ // Initialize our era info.
+ static internal EraInfo[] koreanEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1, 1, 1, -2333, 2334, GregorianCalendar.MaxYear + 2333) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal GregorianCalendarHelper helper;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Korean calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of KoreanCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new KoreanCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+
+ public KoreanCalendar() {
+ try {
+ new CultureInfo("ko-KR");
+ } catch (ArgumentException e) {
+ throw new TypeInitializationException(this.GetType().FullName, e);
+ }
+ helper = new GregorianCalendarHelper(this, koreanEraInfo);
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_KOREA);
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (helper.AddYears(time, years));
+ }
+
+ /*=================================GetDaysInMonth==========================
+ **Action: Returns the number of days in the month given by the year and month arguments.
+ **Returns: The number of days in the given month.
+ **Arguments:
+ ** year The year in Korean calendar.
+ ** month The month
+ ** era The Japanese era value.
+ **Exceptions
+ ** ArgumentException If month is less than 1 or greater * than 12.
+ ============================================================================*/
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era) {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era) {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time) {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time) {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era) {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 4362;
+
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ helper.MaxYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ return (helper.ToFourDigitYear(year, this.TwoDigitYearMax));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs
new file mode 100644
index 0000000000..eb0a810864
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/KoreanLunisolarCalendar.cs
@@ -0,0 +1,1334 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about KoreanLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 918/02/14 2051/02/10
+ ** KoreanLunisolar 918/01/01 2050/13/29
+ */
+
+ [Serializable]
+ public class KoreanLunisolarCalendar : EastAsianLunisolarCalendar {
+
+
+ //
+ // The era value for the current era.
+ //
+
+ public const int GregorianEra = 1;
+
+ //internal static Calendar m_defaultInstance;
+
+ internal const int MIN_LUNISOLAR_YEAR = 918;
+ internal const int MAX_LUNISOLAR_YEAR = 2050;
+
+ internal const int MIN_GREGORIAN_YEAR = 918;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 14;
+
+ internal const int MAX_GREGORIAN_YEAR = 2051;
+ internal const int MAX_GREGORIAN_MONTH = 2;
+ internal const int MAX_GREGORIAN_DAY = 10;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 917 -- From http://emr.cs.iit.edu/home/reingold/calendar-book/Calendrica.html
+ // using ChineseLunisolar
+ return 384;
+ }
+ }
+
+ static readonly int [,] yinfo =
+ {
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+918 */{ 0 , 2 , 14 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+919 */{ 0 , 2 , 4 , 17872 },/* 29 30 29 29 29 30 29 30 30 30 29 30 0 354
+920 */{ 6 , 1 , 24 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+921 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+922 */{ 0 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+923 */{ 4 , 1 , 20 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+924 */{ 0 , 2 , 8 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+925 */{ 12 , 1 , 27 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+926 */{ 0 , 2 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+927 */{ 0 , 2 , 5 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+928 */{ 8 , 1 , 26 , 17848 },/* 29 30 29 29 29 30 29 30 30 29 30 30 30 384
+929 */{ 0 , 2 , 13 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+930 */{ 0 , 2 , 2 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+931 */{ 5 , 1 , 22 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 29 383
+932 */{ 0 , 2 , 9 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+933 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+934 */{ 1 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+935 */{ 0 , 2 , 6 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+936 */{ 11 , 1 , 27 , 21344 },/* 29 30 29 30 29 29 30 30 29 30 30 29 29 383
+937 */{ 0 , 2 , 13 , 51904 },/* 30 30 29 29 30 29 30 29 30 30 29 29 0 354
+938 */{ 0 , 2 , 2 , 58720 },/* 30 30 30 29 29 30 29 30 29 30 30 29 0 355
+939 */{ 7 , 1 , 23 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+940 */{ 0 , 2 , 11 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+941 */{ 0 , 1 , 30 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+942 */{ 3 , 1 , 20 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+943 */{ 0 , 2 , 8 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+944 */{ 12 , 1 , 28 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+945 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+946 */{ 0 , 2 , 5 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+947 */{ 7 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+948 */{ 0 , 2 , 13 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+949 */{ 0 , 2 , 1 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
+950 */{ 5 , 1 , 21 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+951 */{ 0 , 2 , 9 , 45936 },/* 30 29 30 30 29 30 29 30 29 30 29 0 0 325
+952 */{ 0 , 12 , 31 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+953 */{ 1 , 1 , 18 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+954 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+955 */{ 9 , 1 , 27 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+956 */{ 0 , 2 , 15 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+957 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+958 */{ 7 , 1 , 23 , 43672 },/* 30 29 30 29 30 29 30 29 30 29 29 30 30 384
+959 */{ 0 , 2 , 11 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+960 */{ 0 , 1 , 31 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+961 */{ 3 , 1 , 20 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+962 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+963 */{ 12 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+964 */{ 0 , 2 , 16 , 41840 },/* 30 29 30 29 29 29 30 30 29 30 30 30 0 355
+965 */{ 0 , 2 , 5 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 0 354
+966 */{ 8 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+967 */{ 0 , 2 , 12 , 54448 },/* 30 30 29 30 29 30 29 29 30 29 30 30 0 355
+968 */{ 0 , 2 , 2 , 23184 },/* 29 30 29 30 30 29 30 29 30 29 29 30 0 354
+969 */{ 5 , 1 , 21 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+970 */{ 0 , 2 , 9 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+971 */{ 0 , 1 , 30 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+972 */{ 2 , 1 , 19 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+973 */{ 0 , 2 , 6 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+974 */{ 10 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+975 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+976 */{ 0 , 2 , 3 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+977 */{ 7 , 1 , 22 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 29 384
+978 */{ 0 , 2 , 10 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+979 */{ 0 , 1 , 31 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+980 */{ 3 , 1 , 21 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+981 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+982 */{ 12 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+983 */{ 0 , 2 , 16 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+984 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+985 */{ 9 , 1 , 24 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+986 */{ 0 , 2 , 12 , 44192 },/* 30 29 30 29 30 30 29 29 30 29 30 29 0 354
+987 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+988 */{ 5 , 1 , 22 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+989 */{ 0 , 2 , 9 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+990 */{ 0 , 1 , 30 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+991 */{ 2 , 1 , 19 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+992 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+993 */{ 10 , 1 , 26 , 26968 },/* 29 30 30 29 30 29 29 30 29 30 29 30 30 384
+994 */{ 0 , 2 , 14 , 22864 },/* 29 30 29 30 30 29 29 30 29 30 29 30 0 354
+995 */{ 0 , 2 , 3 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+996 */{ 7 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+997 */{ 0 , 2 , 10 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+998 */{ 0 , 1 , 31 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+999 */{ 3 , 1 , 20 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1000 */{ 0 , 2 , 8 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1001 */{ 12 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1002 */{ 0 , 2 , 15 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1003 */{ 0 , 2 , 4 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1004 */{ 9 , 1 , 25 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1005 */{ 0 , 2 , 12 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1006 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1007 */{ 5 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1008 */{ 0 , 2 , 10 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1009 */{ 0 , 1 , 29 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1010 */{ 2 , 1 , 18 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1011 */{ 0 , 2 , 6 , 45664 },/* 30 29 30 30 29 29 30 29 29 30 30 29 0 354
+1012 */{ 10 , 1 , 26 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1013 */{ 0 , 2 , 13 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1014 */{ 0 , 2 , 3 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1015 */{ 6 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1016 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1017 */{ 0 , 1 , 31 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1018 */{ 4 , 1 , 20 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1019 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1020 */{ 12 , 1 , 28 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1021 */{ 0 , 2 , 15 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1022 */{ 0 , 2 , 4 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1023 */{ 9 , 1 , 25 , 11688 },/* 29 29 30 29 30 30 29 30 30 29 30 29 30 384
+1024 */{ 0 , 2 , 13 , 11088 },/* 29 29 30 29 30 29 30 30 29 30 29 30 0 354
+1025 */{ 0 , 2 , 1 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1026 */{ 5 , 1 , 22 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1027 */{ 0 , 2 , 9 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
+1028 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1029 */{ 2 , 1 , 18 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1030 */{ 0 , 2 , 5 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1031 */{ 10 , 1 , 26 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1032 */{ 0 , 2 , 14 , 26320 },/* 29 30 30 29 29 30 30 29 30 30 29 30 0 355
+1033 */{ 0 , 2 , 3 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1034 */{ 6 , 1 , 23 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1035 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1036 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1037 */{ 4 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1038 */{ 0 , 2 , 7 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1039 */{ 12 , 1 , 27 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1040 */{ 0 , 2 , 15 , 46464 },/* 30 29 30 30 29 30 29 30 30 29 29 29 0 354
+1041 */{ 0 , 2 , 3 , 54960 },/* 30 30 29 30 29 30 30 29 30 29 30 30 0 356
+1042 */{ 9 , 1 , 25 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1043 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1044 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1045 */{ 5 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1046 */{ 0 , 2 , 9 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1047 */{ 0 , 1 , 29 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1048 */{ 1 , 1 , 18 , 46424 },/* 30 29 30 30 29 30 29 30 29 30 29 30 30 385
+1049 */{ 0 , 2 , 6 , 11600 },/* 29 29 30 29 30 30 29 30 29 30 29 30 0 354
+1050 */{ 11 , 1 , 26 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1051 */{ 0 , 2 , 14 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1052 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1053 */{ 7 , 1 , 23 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1054 */{ 0 , 2 , 11 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1055 */{ 0 , 1 , 31 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1056 */{ 3 , 1 , 20 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1057 */{ 0 , 2 , 7 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1058 */{ 12 , 1 , 27 , 43864 },/* 30 29 30 29 30 29 30 30 29 30 29 30 30 385
+1059 */{ 0 , 2 , 16 , 10064 },/* 29 29 30 29 29 30 30 30 29 30 29 30 0 354
+1060 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1061 */{ 8 , 1 , 24 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1062 */{ 0 , 2 , 12 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1063 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1064 */{ 5 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1065 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1066 */{ 0 , 1 , 29 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1067 */{ 1 , 1 , 18 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1068 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1069 */{ 11 , 1 , 26 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1070 */{ 0 , 2 , 14 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1071 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1072 */{ 7 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1073 */{ 0 , 2 , 10 , 43616 },/* 30 29 30 29 30 29 30 29 29 30 30 29 0 354
+1074 */{ 0 , 1 , 30 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1075 */{ 4 , 1 , 20 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1076 */{ 0 , 2 , 8 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1077 */{ 0 , 1 , 27 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1078 */{ 1 , 1 , 17 , 19352 },/* 29 30 29 29 30 29 30 30 30 29 29 30 30 384
+1079 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1080 */{ 9 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1081 */{ 0 , 2 , 12 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1082 */{ 0 , 2 , 1 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1083 */{ 6 , 1 , 21 , 46408 },/* 30 29 30 30 29 30 29 30 29 30 29 29 30 384
+1084 */{ 0 , 2 , 9 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1085 */{ 0 , 1 , 29 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1086 */{ 2 , 1 , 18 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1087 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1088 */{ 12 , 1 , 27 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1089 */{ 0 , 2 , 13 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 0 355
+1090 */{ 0 , 2 , 3 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1091 */{ 8 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1092 */{ 0 , 2 , 10 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1093 */{ 0 , 1 , 30 , 23360 },/* 29 30 29 30 30 29 30 30 29 30 29 29 0 354
+1094 */{ 4 , 1 , 19 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1095 */{ 0 , 2 , 8 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1096 */{ 0 , 1 , 28 , 58896 },/* 30 30 30 29 29 30 30 29 29 29 29 30 0 354
+1097 */{ 2 , 1 , 16 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1098 */{ 0 , 2 , 4 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1099 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1100 */{ 0 , 2 , 12 , 21664 },/* 29 30 29 30 29 30 29 29 30 29 30 29 0 353
+1101 */{ 0 , 1 , 31 , 54864 },/* 30 30 29 30 29 30 30 29 29 30 29 30 0 355
+1102 */{ 6 , 1 , 21 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1103 */{ 0 , 2 , 9 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1104 */{ 0 , 1 , 30 , 9936 },/* 29 29 30 29 29 30 30 29 30 30 29 30 0 354
+1105 */{ 2 , 1 , 18 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1106 */{ 0 , 2 , 6 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1107 */{ 10 , 1 , 26 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1108 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1109 */{ 0 , 2 , 2 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1110 */{ 8 , 1 , 22 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1111 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1112 */{ 0 , 1 , 31 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1113 */{ 4 , 1 , 20 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1114 */{ 0 , 2 , 8 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1115 */{ 0 , 1 , 28 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1116 */{ 1 , 1 , 17 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1117 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1118 */{ 9 , 1 , 24 , 29352 },/* 29 30 30 30 29 29 30 29 30 29 30 29 30 384
+1119 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1120 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1121 */{ 5 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1122 */{ 0 , 2 , 9 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1123 */{ 0 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1124 */{ 3 , 1 , 19 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1125 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1126 */{ 11 , 1 , 25 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1127 */{ 0 , 2 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1128 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1129 */{ 8 , 1 , 22 , 39824 },/* 30 29 29 30 30 29 30 30 30 29 29 30 29 384
+1130 */{ 0 , 2 , 10 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1131 */{ 0 , 1 , 31 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1132 */{ 4 , 1 , 20 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1133 */{ 0 , 2 , 7 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1134 */{ 0 , 1 , 27 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1135 */{ 2 , 1 , 16 , 55592 },/* 30 30 29 30 30 29 29 30 29 29 30 29 30 384
+1136 */{ 0 , 2 , 4 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1137 */{ 10 , 1 , 23 , 54952 },/* 30 30 29 30 29 30 30 29 30 29 30 29 30 385
+1138 */{ 0 , 2 , 12 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1139 */{ 0 , 2 , 1 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1140 */{ 6 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1141 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1142 */{ 0 , 1 , 29 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1143 */{ 4 , 1 , 18 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1144 */{ 0 , 2 , 6 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1145 */{ 11 , 1 , 25 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1146 */{ 0 , 2 , 13 , 27456 },/* 29 30 30 29 30 29 30 30 29 30 29 29 0 354
+1147 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1148 */{ 8 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1149 */{ 0 , 2 , 10 , 39280 },/* 30 29 29 30 30 29 29 30 29 30 30 30 0 355
+1150 */{ 0 , 1 , 31 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1151 */{ 4 , 1 , 20 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1152 */{ 0 , 2 , 8 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
+1153 */{ 12 , 1 , 27 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1154 */{ 0 , 2 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1155 */{ 0 , 2 , 4 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1156 */{ 10 , 1 , 24 , 43880 },/* 30 29 30 29 30 29 30 30 29 30 30 29 30 385
+1157 */{ 0 , 2 , 12 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1158 */{ 0 , 2 , 1 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1159 */{ 6 , 1 , 21 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1160 */{ 0 , 2 , 9 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1161 */{ 0 , 1 , 28 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1162 */{ 2 , 1 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1163 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1164 */{ 11 , 1 , 26 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1165 */{ 0 , 2 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1166 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1167 */{ 7 , 1 , 23 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1168 */{ 0 , 2 , 11 , 37488 },/* 30 29 29 30 29 29 30 29 29 30 30 30 0 354
+1169 */{ 0 , 1 , 30 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1170 */{ 5 , 1 , 19 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1171 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1172 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1173 */{ 1 , 1 , 16 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1174 */{ 0 , 2 , 4 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
+1175 */{ 9 , 1 , 25 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 29 383
+1176 */{ 0 , 2 , 12 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1177 */{ 0 , 2 , 1 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1178 */{ 6 , 1 , 21 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1179 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1180 */{ 0 , 1 , 29 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1181 */{ 3 , 1 , 17 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1182 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1183 */{ 11 , 1 , 26 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1184 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1185 */{ 0 , 2 , 2 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1186 */{ 7 , 1 , 23 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1187 */{ 0 , 2 , 10 , 53392 },/* 30 30 29 30 29 29 30 29 29 30 30 0 0 325
+1188 */{ 0 , 1 , 1 , 29848 },/* 29 30 30 30 29 30 29 29 30 29 29 30 30 384
+1189 */{ 5 , 1 , 19 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1190 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1191 */{ 0 , 1 , 27 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
+1192 */{ 2 , 1 , 17 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1193 */{ 0 , 2 , 4 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1194 */{ 10 , 1 , 24 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1195 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1196 */{ 0 , 2 , 1 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1197 */{ 6 , 1 , 20 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1198 */{ 0 , 2 , 8 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1199 */{ 0 , 1 , 28 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1200 */{ 2 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1201 */{ 0 , 2 , 5 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1202 */{ 12 , 1 , 26 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1203 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1204 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1205 */{ 8 , 1 , 22 , 43608 },/* 30 29 30 29 30 29 30 29 29 30 29 30 30 384
+1206 */{ 0 , 2 , 10 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1207 */{ 0 , 1 , 30 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1208 */{ 4 , 1 , 19 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 29 384
+1209 */{ 0 , 2 , 6 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1210 */{ 0 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1211 */{ 2 , 1 , 17 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1212 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1213 */{ 9 , 1 , 24 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1214 */{ 0 , 2 , 12 , 21680 },/* 29 30 29 30 29 30 29 29 30 29 30 30 0 354
+1215 */{ 0 , 2 , 1 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1216 */{ 7 , 1 , 21 , 27944 },/* 29 30 30 29 30 30 29 30 29 29 30 29 30 384
+1217 */{ 0 , 2 , 8 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1218 */{ 0 , 1 , 28 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1219 */{ 3 , 1 , 18 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1220 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1221 */{ 12 , 1 , 25 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1222 */{ 0 , 2 , 13 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1223 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1224 */{ 8 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1225 */{ 0 , 2 , 9 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1226 */{ 0 , 1 , 30 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1227 */{ 5 , 1 , 19 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1228 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1229 */{ 0 , 1 , 27 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1230 */{ 2 , 1 , 16 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1231 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1232 */{ 9 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1233 */{ 0 , 2 , 11 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1234 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1235 */{ 7 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1236 */{ 0 , 2 , 9 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1237 */{ 0 , 1 , 28 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1238 */{ 4 , 1 , 18 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1239 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1240 */{ 12 , 1 , 26 , 43320 },/* 30 29 30 29 30 29 29 30 29 29 30 30 30 384
+1241 */{ 0 , 2 , 13 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1242 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1243 */{ 8 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1244 */{ 0 , 2 , 10 , 44624 },/* 30 29 30 29 30 30 30 29 29 30 29 30 0 355
+1245 */{ 0 , 1 , 30 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1246 */{ 4 , 1 , 19 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1247 */{ 0 , 2 , 7 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1248 */{ 0 , 1 , 28 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1249 */{ 2 , 1 , 16 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1250 */{ 0 , 2 , 3 , 58672 },/* 30 30 30 29 29 30 29 30 29 29 30 30 0 355
+1251 */{ 10 , 1 , 24 , 27800 },/* 29 30 30 29 30 30 29 29 30 29 29 30 30 384
+1252 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1253 */{ 0 , 1 , 31 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1254 */{ 6 , 1 , 21 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1255 */{ 0 , 2 , 9 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1256 */{ 0 , 1 , 29 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1257 */{ 4 , 1 , 17 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1258 */{ 0 , 2 , 5 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1259 */{ 11 , 1 , 25 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1260 */{ 0 , 2 , 13 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1261 */{ 0 , 2 , 1 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1262 */{ 9 , 1 , 22 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1263 */{ 0 , 2 , 10 , 21872 },/* 29 30 29 30 29 30 29 30 29 30 30 30 0 355
+1264 */{ 0 , 1 , 31 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1265 */{ 5 , 1 , 19 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1266 */{ 0 , 2 , 7 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1267 */{ 0 , 1 , 27 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1268 */{ 1 , 1 , 16 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1269 */{ 0 , 2 , 3 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1270 */{ 11 , 1 , 23 , 46528 },/* 30 29 30 30 29 30 29 30 30 30 29 29 29 384
+1271 */{ 0 , 2 , 11 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1272 */{ 0 , 2 , 1 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1273 */{ 6 , 1 , 21 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1274 */{ 0 , 2 , 9 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1275 */{ 0 , 1 , 29 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1276 */{ 3 , 1 , 18 , 27224 },/* 29 30 30 29 30 29 30 29 29 30 29 30 30 384
+1277 */{ 0 , 2 , 5 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1278 */{ 11 , 1 , 25 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1279 */{ 0 , 2 , 13 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1280 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1281 */{ 8 , 1 , 22 , 10984 },/* 29 29 30 29 30 29 30 29 30 30 30 29 30 384
+1282 */{ 0 , 2 , 10 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
+1283 */{ 0 , 1 , 30 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1284 */{ 5 , 1 , 19 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1285 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+1286 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1287 */{ 2 , 1 , 15 , 62096 },/* 30 30 30 30 29 29 30 29 30 29 29 30 29 384
+1288 */{ 0 , 2 , 3 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1289 */{ 10 , 1 , 23 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1290 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1291 */{ 0 , 2 , 1 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1292 */{ 6 , 1 , 21 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1293 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1294 */{ 0 , 1 , 28 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1295 */{ 4 , 1 , 17 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1296 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1297 */{ 12 , 1 , 24 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 29 384
+1298 */{ 0 , 2 , 12 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1299 */{ 0 , 2 , 2 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1300 */{ 8 , 1 , 23 , 2424 },/* 29 29 29 29 30 29 29 30 29 30 30 30 30 383
+1301 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1302 */{ 0 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1303 */{ 5 , 1 , 19 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1304 */{ 0 , 2 , 6 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1305 */{ 0 , 1 , 26 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1306 */{ 1 , 1 , 15 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1307 */{ 0 , 2 , 3 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1308 */{ 11 , 1 , 24 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1309 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1310 */{ 0 , 1 , 31 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1311 */{ 7 , 1 , 20 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1312 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1313 */{ 0 , 1 , 27 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1314 */{ 3 , 1 , 17 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1315 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1316 */{ 0 , 1 , 25 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1317 */{ 1 , 1 , 14 , 37608 },/* 30 29 29 30 29 29 30 29 30 30 30 29 30 384
+1318 */{ 0 , 2 , 2 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1319 */{ 8 , 1 , 22 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1320 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1321 */{ 0 , 1 , 29 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1322 */{ 5 , 1 , 18 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1323 */{ 0 , 2 , 6 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1324 */{ 0 , 1 , 27 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1325 */{ 1 , 1 , 15 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1326 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1327 */{ 9 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1328 */{ 0 , 2 , 12 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1329 */{ 0 , 1 , 31 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1330 */{ 7 , 1 , 20 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1331 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1332 */{ 0 , 1 , 28 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1333 */{ 3 , 1 , 17 , 19368 },/* 29 30 29 29 30 29 30 30 30 29 30 29 30 384
+1334 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1335 */{ 12 , 1 , 25 , 42608 },/* 30 29 30 29 29 30 30 29 29 30 30 30 29 384
+1336 */{ 0 , 2 , 13 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+1337 */{ 0 , 2 , 1 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1338 */{ 8 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1339 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1340 */{ 0 , 1 , 29 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1341 */{ 5 , 1 , 18 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1342 */{ 0 , 2 , 6 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1343 */{ 0 , 1 , 27 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1344 */{ 2 , 1 , 16 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1345 */{ 0 , 2 , 3 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1346 */{ 10 , 1 , 23 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1347 */{ 0 , 2 , 11 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1348 */{ 0 , 1 , 31 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1349 */{ 7 , 1 , 19 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1350 */{ 0 , 2 , 7 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1351 */{ 0 , 1 , 28 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1352 */{ 3 , 1 , 18 , 18904 },/* 29 30 29 29 30 29 29 30 30 30 29 30 30 384
+1353 */{ 0 , 2 , 5 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1354 */{ 0 , 1 , 25 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1355 */{ 1 , 1 , 14 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1356 */{ 0 , 2 , 2 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1357 */{ 9 , 1 , 21 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1358 */{ 0 , 2 , 9 , 27424 },/* 29 30 30 29 30 29 30 30 29 29 30 29 0 354
+1359 */{ 0 , 1 , 29 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
+1360 */{ 5 , 1 , 19 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1361 */{ 0 , 2 , 6 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1362 */{ 0 , 1 , 27 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1363 */{ 3 , 1 , 16 , 41656 },/* 30 29 30 29 29 29 30 29 30 29 30 30 30 384
+1364 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1365 */{ 10 , 1 , 23 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 29 383
+1366 */{ 0 , 2 , 10 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1367 */{ 0 , 1 , 31 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1368 */{ 7 , 1 , 20 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1369 */{ 0 , 2 , 7 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1370 */{ 0 , 1 , 28 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
+1371 */{ 3 , 1 , 17 , 50544 },/* 30 30 29 29 29 30 29 30 29 30 30 30 29 384
+1372 */{ 0 , 2 , 5 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1373 */{ 11 , 1 , 24 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1374 */{ 0 , 2 , 12 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1375 */{ 0 , 2 , 1 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1376 */{ 9 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1377 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1378 */{ 0 , 1 , 29 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1379 */{ 5 , 1 , 19 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1380 */{ 0 , 2 , 7 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1381 */{ 0 , 1 , 26 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
+1382 */{ 2 , 1 , 15 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1383 */{ 0 , 2 , 3 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1384 */{ 10 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1385 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1386 */{ 0 , 1 , 31 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1387 */{ 6 , 1 , 20 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1388 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1389 */{ 0 , 1 , 28 , 20912 },/* 29 30 29 30 29 29 29 30 30 29 30 30 0 354
+1390 */{ 4 , 1 , 17 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1391 */{ 0 , 2 , 5 , 25904 },/* 29 30 30 29 29 30 29 30 29 29 30 30 0 354
+1392 */{ 12 , 1 , 25 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1393 */{ 0 , 2 , 12 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1394 */{ 0 , 2 , 1 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1395 */{ 9 , 1 , 22 , 11176 },/* 29 29 30 29 30 29 30 30 30 29 30 29 30 384
+1396 */{ 0 , 2 , 10 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1397 */{ 0 , 1 , 29 , 50032 },/* 30 30 29 29 29 29 30 30 29 30 30 30 0 355
+1398 */{ 5 , 1 , 19 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1399 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1400 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1401 */{ 3 , 1 , 15 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1402 */{ 0 , 2 , 2 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1403 */{ 11 , 1 , 23 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1404 */{ 0 , 2 , 11 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1405 */{ 0 , 1 , 31 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1406 */{ 7 , 1 , 20 , 41704 },/* 30 29 30 29 29 29 30 29 30 30 30 29 30 384
+1407 */{ 0 , 2 , 8 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1408 */{ 0 , 1 , 28 , 53584 },/* 30 30 29 30 29 29 29 30 29 30 29 30 0 354
+1409 */{ 4 , 1 , 16 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1410 */{ 0 , 2 , 4 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1411 */{ 12 , 1 , 24 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 29 384
+1412 */{ 0 , 2 , 12 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1413 */{ 0 , 2 , 1 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1414 */{ 9 , 1 , 22 , 9688 },/* 29 29 30 29 29 30 29 30 30 30 29 30 30 384
+1415 */{ 0 , 2 , 10 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1416 */{ 0 , 1 , 30 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1417 */{ 5 , 1 , 18 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1418 */{ 0 , 2 , 6 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1419 */{ 0 , 1 , 26 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1420 */{ 1 , 1 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1421 */{ 0 , 2 , 2 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1422 */{ 12 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1423 */{ 0 , 2 , 11 , 19312 },/* 29 30 29 29 30 29 30 30 29 30 30 30 0 355
+1424 */{ 0 , 2 , 1 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1425 */{ 7 , 1 , 20 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1426 */{ 0 , 2 , 8 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1427 */{ 0 , 1 , 28 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1428 */{ 4 , 1 , 17 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1429 */{ 0 , 2 , 4 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1430 */{ 12 , 1 , 24 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 29 384
+1431 */{ 0 , 2 , 12 , 42720 },/* 30 29 30 29 29 30 30 29 30 30 30 29 0 355
+1432 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1433 */{ 8 , 1 , 21 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1434 */{ 0 , 2 , 9 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1435 */{ 0 , 1 , 29 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1436 */{ 6 , 1 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1437 */{ 0 , 2 , 5 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1438 */{ 0 , 1 , 26 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1439 */{ 2 , 1 , 15 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1440 */{ 0 , 2 , 3 , 38368 },/* 30 29 29 30 29 30 29 30 30 30 30 29 0 355
+1441 */{ 11 , 1 , 23 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1442 */{ 0 , 2 , 11 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1443 */{ 0 , 1 , 31 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1444 */{ 7 , 1 , 20 , 53872 },/* 30 30 29 30 29 29 30 29 29 30 30 30 29 384
+1445 */{ 0 , 2 , 7 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1446 */{ 0 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1447 */{ 4 , 1 , 17 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1448 */{ 0 , 2 , 5 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1449 */{ 0 , 1 , 24 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1450 */{ 1 , 1 , 14 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1451 */{ 0 , 2 , 2 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1452 */{ 9 , 1 , 22 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1453 */{ 0 , 2 , 9 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1454 */{ 0 , 1 , 29 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1455 */{ 6 , 1 , 18 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1456 */{ 0 , 2 , 6 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1457 */{ 0 , 1 , 26 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1458 */{ 2 , 1 , 15 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1459 */{ 0 , 2 , 3 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1460 */{ 11 , 1 , 24 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 29 383
+1461 */{ 0 , 2 , 10 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1462 */{ 0 , 1 , 30 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
+1463 */{ 7 , 1 , 20 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1464 */{ 0 , 2 , 7 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1465 */{ 0 , 1 , 27 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1466 */{ 3 , 1 , 17 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1467 */{ 0 , 2 , 5 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1468 */{ 0 , 1 , 25 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1469 */{ 2 , 1 , 13 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1470 */{ 0 , 2 , 1 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1471 */{ 9 , 1 , 21 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1472 */{ 0 , 2 , 9 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1473 */{ 0 , 1 , 28 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1474 */{ 6 , 1 , 18 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1475 */{ 0 , 2 , 6 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1476 */{ 0 , 1 , 27 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1477 */{ 2 , 1 , 15 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1478 */{ 0 , 2 , 3 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1479 */{ 10 , 1 , 23 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1480 */{ 0 , 2 , 11 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1481 */{ 0 , 1 , 30 , 29856 },/* 29 30 30 30 29 30 29 29 30 29 30 29 0 354
+1482 */{ 8 , 1 , 19 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1483 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1484 */{ 0 , 1 , 28 , 21424 },/* 29 30 29 30 29 29 30 30 30 29 30 30 0 355
+1485 */{ 4 , 1 , 17 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1486 */{ 0 , 2 , 5 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1487 */{ 0 , 1 , 25 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1488 */{ 1 , 1 , 14 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1489 */{ 0 , 2 , 1 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1490 */{ 9 , 1 , 21 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1491 */{ 0 , 2 , 9 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1492 */{ 0 , 1 , 29 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1493 */{ 5 , 1 , 18 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1494 */{ 0 , 2 , 6 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1495 */{ 0 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1496 */{ 3 , 1 , 16 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 29 383
+1497 */{ 0 , 2 , 2 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1498 */{ 11 , 1 , 22 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 29 384
+1499 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1500 */{ 0 , 1 , 31 , 5792 },/* 29 29 29 30 29 30 30 29 30 29 30 29 0 353
+1501 */{ 7 , 1 , 19 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1502 */{ 0 , 2 , 7 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1503 */{ 0 , 1 , 28 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1504 */{ 4 , 1 , 17 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1505 */{ 0 , 2 , 4 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1506 */{ 0 , 1 , 24 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1507 */{ 1 , 1 , 13 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 29 384
+1508 */{ 0 , 2 , 1 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1509 */{ 9 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1510 */{ 0 , 2 , 9 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1511 */{ 0 , 1 , 29 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1512 */{ 5 , 1 , 19 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1513 */{ 0 , 2 , 6 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1514 */{ 0 , 1 , 26 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1515 */{ 4 , 1 , 15 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1516 */{ 0 , 2 , 3 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1517 */{ 12 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1518 */{ 0 , 2 , 10 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1519 */{ 0 , 1 , 31 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1520 */{ 8 , 1 , 20 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1521 */{ 0 , 2 , 7 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 0 355
+1522 */{ 0 , 1 , 28 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1523 */{ 4 , 1 , 17 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1524 */{ 0 , 2 , 4 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1525 */{ 12 , 1 , 23 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1526 */{ 0 , 2 , 11 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 0 355
+1527 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1528 */{ 10 , 1 , 22 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1529 */{ 0 , 2 , 9 , 9952 },/* 29 29 30 29 29 30 30 29 30 30 30 29 0 354
+1530 */{ 0 , 1 , 29 , 21216 },/* 29 30 29 30 29 29 30 29 30 30 30 29 0 354
+1531 */{ 6 , 1 , 18 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1532 */{ 0 , 2 , 6 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1533 */{ 0 , 1 , 25 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1534 */{ 2 , 1 , 14 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1535 */{ 0 , 2 , 2 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 0 355
+1536 */{ 12 , 1 , 23 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1537 */{ 0 , 2 , 10 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1538 */{ 0 , 1 , 31 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1539 */{ 7 , 1 , 20 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1540 */{ 0 , 2 , 8 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1541 */{ 0 , 1 , 27 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1542 */{ 5 , 1 , 16 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1543 */{ 0 , 2 , 4 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1544 */{ 0 , 1 , 24 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1545 */{ 1 , 1 , 13 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1546 */{ 0 , 2 , 1 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1547 */{ 9 , 1 , 22 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1548 */{ 0 , 2 , 10 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1549 */{ 0 , 1 , 29 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1550 */{ 6 , 1 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1551 */{ 0 , 2 , 5 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1552 */{ 0 , 1 , 26 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1553 */{ 3 , 1 , 14 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1554 */{ 0 , 2 , 2 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1555 */{ 11 , 1 , 23 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1556 */{ 0 , 2 , 11 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1557 */{ 0 , 1 , 30 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1558 */{ 7 , 1 , 20 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1559 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1560 */{ 0 , 1 , 27 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1561 */{ 5 , 1 , 16 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1562 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1563 */{ 0 , 1 , 24 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1564 */{ 2 , 1 , 14 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1565 */{ 0 , 2 , 1 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1566 */{ 10 , 1 , 21 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1567 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1568 */{ 0 , 1 , 29 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1569 */{ 6 , 1 , 17 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1570 */{ 0 , 2 , 5 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1571 */{ 0 , 1 , 26 , 13728 },/* 29 29 30 30 29 30 29 30 30 29 30 29 0 354
+1572 */{ 2 , 1 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1573 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1574 */{ 12 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1575 */{ 0 , 2 , 11 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1576 */{ 0 , 1 , 31 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1577 */{ 8 , 1 , 19 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1578 */{ 0 , 2 , 7 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1579 */{ 0 , 1 , 27 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1580 */{ 4 , 1 , 16 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1581 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1582 */{ 0 , 1 , 24 , 39024 },/* 30 29 29 30 29 29 30 30 39 30 30 30 0 365
+1583 */{ 2 , 1 , 24 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1584 */{ 0 , 2 , 12 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1585 */{ 9 , 1 , 31 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1586 */{ 0 , 2 , 18 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1587 */{ 0 , 3 , 9 , 53968 },/* 30 30 29 30 29 30 29 29 30 29 30 0 0 325
+1588 */{ 6 , 1 , 28 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1589 */{ 0 , 2 , 15 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1590 */{ 0 , 2 , 5 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1591 */{ 3 , 1 , 25 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1592 */{ 0 , 2 , 13 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1593 */{ 11 , 2 , 1 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1594 */{ 0 , 2 , 20 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1595 */{ 0 , 2 , 9 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1596 */{ 8 , 1 , 29 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1597 */{ 0 , 2 , 16 , 46288 },/* 30 29 30 30 29 30 29 29 30 30 29 30 0 355
+1598 */{ 0 , 2 , 6 , 22192 },/* 29 30 29 30 29 30 30 29 30 29 30 30 0 355
+1599 */{ 4 , 1 , 27 , 9944 },/* 29 29 30 29 29 30 30 29 30 30 29 30 30 384
+1600 */{ 0 , 2 , 15 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1601 */{ 0 , 2 , 3 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1602 */{ 2 , 1 , 23 , 51608 },/* 30 30 29 29 30 29 29 30 30 29 29 30 30 384
+1603 */{ 0 , 2 , 11 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1604 */{ 9 , 1 , 31 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1605 */{ 0 , 2 , 18 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1606 */{ 0 , 2 , 7 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1607 */{ 6 , 1 , 28 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1608 */{ 0 , 2 , 16 , 19376 },/* 29 30 29 29 30 29 30 30 30 29 30 30 0 355
+1609 */{ 0 , 2 , 5 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1610 */{ 3 , 1 , 25 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1611 */{ 0 , 2 , 13 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1612 */{ 11 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1613 */{ 0 , 2 , 19 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1614 */{ 0 , 2 , 9 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1615 */{ 8 , 1 , 29 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1616 */{ 0 , 2 , 17 , 39760 },/* 30 29 29 30 30 29 30 30 29 30 29 30 0 355
+1617 */{ 0 , 2 , 6 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1618 */{ 4 , 1 , 26 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1619 */{ 0 , 2 , 14 , 42224 },/* 30 29 30 29 29 30 29 29 30 30 30 30 0 355
+1620 */{ 0 , 2 , 4 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1621 */{ 2 , 1 , 22 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1622 */{ 0 , 2 , 10 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1623 */{ 10 , 1 , 31 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1624 */{ 0 , 2 , 19 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1625 */{ 0 , 2 , 7 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1626 */{ 6 , 1 , 28 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1627 */{ 0 , 2 , 16 , 18912 },/* 29 30 29 29 30 29 29 30 30 30 30 29 0 354
+1628 */{ 0 , 2 , 5 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1629 */{ 4 , 1 , 24 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1630 */{ 0 , 2 , 12 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1631 */{ 11 , 2 , 1 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1632 */{ 0 , 2 , 20 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1633 */{ 0 , 2 , 8 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1634 */{ 8 , 1 , 29 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 29 384
+1635 */{ 0 , 2 , 17 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1636 */{ 0 , 2 , 7 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1637 */{ 4 , 1 , 26 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1638 */{ 0 , 2 , 14 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1639 */{ 0 , 2 , 3 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1640 */{ 1 , 1 , 23 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1641 */{ 0 , 2 , 10 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1642 */{ 11 , 1 , 30 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1643 */{ 0 , 2 , 19 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1644 */{ 0 , 2 , 8 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1645 */{ 6 , 1 , 28 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1646 */{ 0 , 2 , 16 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1647 */{ 0 , 2 , 5 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1648 */{ 3 , 1 , 24 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1649 */{ 0 , 2 , 11 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1650 */{ 11 , 2 , 1 , 27464 },/* 29 30 30 29 30 29 30 30 29 30 29 29 30 384
+1651 */{ 0 , 2 , 20 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1652 */{ 0 , 2 , 10 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
+1653 */{ 7 , 1 , 29 , 37616 },/* 30 29 29 30 29 29 30 29 30 30 30 30 29 384
+1654 */{ 0 , 2 , 17 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1655 */{ 0 , 2 , 6 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1656 */{ 5 , 1 , 26 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1657 */{ 0 , 2 , 13 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1658 */{ 0 , 2 , 2 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1659 */{ 3 , 1 , 23 , 39592 },/* 30 29 29 30 30 29 30 29 30 29 30 29 30 384
+1660 */{ 0 , 2 , 11 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1661 */{ 7 , 1 , 30 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 29 384
+1662 */{ 0 , 2 , 18 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 0 355
+1663 */{ 0 , 2 , 8 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1664 */{ 6 , 1 , 28 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1665 */{ 0 , 2 , 15 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1666 */{ 0 , 2 , 4 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1667 */{ 4 , 1 , 24 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1668 */{ 0 , 2 , 12 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1669 */{ 0 , 2 , 1 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+1670 */{ 2 , 1 , 21 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1671 */{ 0 , 2 , 9 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1672 */{ 7 , 1 , 30 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1673 */{ 0 , 2 , 17 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1674 */{ 0 , 2 , 6 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1675 */{ 5 , 1 , 26 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+1676 */{ 0 , 2 , 14 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1677 */{ 0 , 2 , 2 , 44432 },/* 30 29 30 29 30 30 29 30 30 29 29 30 0 355
+1678 */{ 3 , 1 , 23 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1679 */{ 0 , 2 , 11 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1680 */{ 8 , 1 , 31 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1681 */{ 0 , 2 , 18 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1682 */{ 0 , 2 , 7 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1683 */{ 6 , 1 , 27 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1684 */{ 0 , 2 , 15 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+1685 */{ 0 , 2 , 3 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1686 */{ 4 , 1 , 24 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+1687 */{ 0 , 2 , 12 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1688 */{ 0 , 2 , 2 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1689 */{ 3 , 1 , 21 , 42216 },/* 30 29 30 29 29 30 29 29 30 30 30 29 30 384
+1690 */{ 0 , 2 , 9 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1691 */{ 7 , 1 , 29 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1692 */{ 0 , 2 , 17 , 45136 },/* 30 29 29 32 29 29 29 29 29 30 29 30 0 354
+1693 */{ 0 , 2 , 5 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+1694 */{ 5 , 1 , 25 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 29 384
+1695 */{ 0 , 2 , 13 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+1696 */{ 0 , 2 , 3 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1697 */{ 3 , 1 , 23 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1698 */{ 0 , 2 , 11 , 18896 },/* 29 30 29 29 30 29 29 30 30 30 29 30 0 354
+1699 */{ 7 , 1 , 31 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1700 */{ 0 , 2 , 19 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1701 */{ 0 , 2 , 8 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1702 */{ 6 , 1 , 28 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+1703 */{ 0 , 2 , 16 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+1704 */{ 0 , 2 , 5 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1705 */{ 4 , 1 , 25 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1706 */{ 0 , 2 , 13 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1707 */{ 0 , 2 , 3 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1708 */{ 3 , 1 , 23 , 25784 },/* 29 30 30 29 29 30 29 29 30 29 30 30 30 384
+1709 */{ 0 , 2 , 10 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1710 */{ 7 , 1 , 30 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1711 */{ 0 , 2 , 17 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+1712 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1713 */{ 5 , 1 , 26 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 29 384
+1714 */{ 0 , 2 , 14 , 43744 },/* 30 29 30 29 30 29 30 29 30 30 30 29 0 355
+1715 */{ 0 , 2 , 4 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1716 */{ 3 , 1 , 24 , 51568 },/* 30 30 29 29 30 29 29 30 29 30 30 30 29 384
+1717 */{ 0 , 2 , 11 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+1718 */{ 8 , 1 , 31 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1719 */{ 0 , 2 , 19 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1720 */{ 0 , 2 , 8 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1721 */{ 6 , 1 , 28 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1722 */{ 0 , 2 , 16 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1723 */{ 0 , 2 , 5 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1724 */{ 4 , 1 , 26 , 21224 },/* 29 30 29 30 29 29 30 29 30 30 30 29 30 384
+1725 */{ 0 , 2 , 13 , 21200 },/* 29 30 29 30 29 29 30 29 30 30 29 30 0 354
+1726 */{ 0 , 2 , 2 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1727 */{ 3 , 1 , 22 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+1728 */{ 0 , 2 , 10 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1729 */{ 7 , 1 , 29 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1730 */{ 0 , 2 , 17 , 40272 },/* 30 29 29 30 30 30 29 30 29 30 29 30 0 355
+1731 */{ 0 , 2 , 7 , 21920 },/* 29 30 29 30 29 30 29 30 30 29 30 29 0 354
+1732 */{ 5 , 1 , 27 , 42448 },/* 30 29 30 29 29 30 29 30 30 30 29 30 29 384
+1733 */{ 0 , 2 , 14 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1734 */{ 0 , 2 , 4 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1735 */{ 4 , 1 , 24 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1736 */{ 0 , 2 , 12 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 0 354
+1737 */{ 9 , 1 , 31 , 27288 },/* 29 30 30 29 30 29 30 29 30 29 29 30 30 384
+1738 */{ 0 , 2 , 19 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1739 */{ 0 , 2 , 8 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1740 */{ 6 , 1 , 29 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+1741 */{ 0 , 2 , 16 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1742 */{ 0 , 2 , 5 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1743 */{ 4 , 1 , 26 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1744 */{ 0 , 2 , 13 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1745 */{ 0 , 2 , 1 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 0 355
+1746 */{ 3 , 1 , 22 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1747 */{ 0 , 2 , 9 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 0 355
+1748 */{ 7 , 1 , 30 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 29 384
+1749 */{ 0 , 2 , 17 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1750 */{ 0 , 2 , 7 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1751 */{ 5 , 1 , 27 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1752 */{ 0 , 2 , 15 , 41680 },/* 30 29 30 29 29 29 30 29 30 30 29 30 0 354
+1753 */{ 0 , 2 , 3 , 53592 },/* 30 30 29 30 29 29 29 30 29 30 29 30 30 384
+1754 */{ 4 , 2 , 22 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+1755 */{ 0 , 2 , 11 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1756 */{ 9 , 1 , 31 , 54928 },/* 30 30 29 30 29 30 30 29 30 29 29 30 29 384
+1757 */{ 0 , 2 , 18 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+1758 */{ 0 , 2 , 8 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1759 */{ 6 , 1 , 29 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1760 */{ 0 , 2 , 17 , 17840 },/* 29 30 29 29 29 30 29 30 30 29 30 30 0 354
+1761 */{ 0 , 2 , 5 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1762 */{ 5 , 1 , 25 , 45400 },/* 30 29 30 30 29 29 29 30 29 30 29 30 30 384
+1763 */{ 0 , 2 , 13 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1764 */{ 0 , 2 , 2 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1765 */{ 2 , 1 , 21 , 46480 },/* 30 29 30 30 29 30 29 30 30 29 29 30 29 384
+1766 */{ 0 , 2 , 9 , 44384 },/* 30 29 30 29 30 30 29 30 29 30 30 29 0 355
+1767 */{ 7 , 1 , 30 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+1768 */{ 0 , 2 , 18 , 21360 },/* 29 30 29 30 29 29 30 30 29 30 30 30 0 355
+1769 */{ 0 , 2 , 7 , 17776 },/* 29 30 29 29 29 30 29 30 29 30 30 30 0 354
+1770 */{ 5 , 1 , 27 , 25272 },/* 29 30 30 29 29 29 30 29 30 29 30 30 30 384
+1771 */{ 0 , 2 , 15 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1772 */{ 0 , 2 , 4 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1773 */{ 3 , 1 , 23 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1774 */{ 0 , 2 , 11 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1775 */{ 10 , 1 , 31 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1776 */{ 0 , 2 , 19 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1777 */{ 0 , 2 , 8 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1778 */{ 6 , 1 , 28 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1779 */{ 0 , 2 , 16 , 42336 },/* 30 29 30 29 29 30 29 30 29 30 30 29 0 354
+1780 */{ 0 , 2 , 5 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1781 */{ 5 , 1 , 24 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1782 */{ 0 , 2 , 12 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1783 */{ 0 , 2 , 2 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1784 */{ 3 , 1 , 22 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+1785 */{ 0 , 2 , 9 , 42704 },/* 30 29 30 29 29 30 30 29 30 30 29 30 0 355
+1786 */{ 7 , 1 , 30 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1787 */{ 0 , 2 , 18 , 19120 },/* 29 30 29 29 30 29 30 29 30 29 30 30 0 354
+1788 */{ 0 , 2 , 7 , 43216 },/* 30 29 30 29 30 29 29 29 30 30 29 30 0 354
+1789 */{ 5 , 1 , 26 , 53928 },/* 30 30 29 30 29 29 30 29 30 29 30 29 30 384
+1790 */{ 0 , 2 , 14 , 45728 },/* 30 29 30 30 29 29 30 29 30 29 30 29 0 354
+1791 */{ 0 , 2 , 3 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1792 */{ 4 , 1 , 24 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1793 */{ 0 , 2 , 11 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1794 */{ 0 , 1 , 31 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1795 */{ 2 , 1 , 21 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1796 */{ 0 , 2 , 9 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1797 */{ 6 , 1 , 28 , 43192 },/* 30 29 30 29 30 29 29 29 30 29 30 30 30 384
+1798 */{ 0 , 2 , 16 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1799 */{ 0 , 2 , 5 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1800 */{ 4 , 1 , 25 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1801 */{ 0 , 2 , 13 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1802 */{ 0 , 2 , 3 , 11168 },/* 29 29 30 29 30 29 30 30 30 29 30 29 0 354
+1803 */{ 2 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1804 */{ 0 , 2 , 11 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1805 */{ 6 , 1 , 31 , 20848 },/* 29 30 29 30 29 29 29 30 29 30 30 30 29 383
+1806 */{ 0 , 2 , 18 , 53600 },/* 30 30 29 30 29 29 29 30 29 30 30 29 0 354
+1807 */{ 0 , 2 , 7 , 58544 },/* 30 30 30 29 29 30 29 29 30 29 30 30 0 355
+1808 */{ 5 , 1 , 28 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 29 383
+1809 */{ 0 , 2 , 14 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1810 */{ 0 , 2 , 4 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1811 */{ 3 , 1 , 25 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1812 */{ 0 , 2 , 13 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1813 */{ 0 , 2 , 1 , 41696 },/* 30 29 30 29 29 29 30 29 30 30 30 29 0 354
+1814 */{ 2 , 1 , 21 , 53608 },/* 30 30 29 30 29 29 29 30 29 30 30 29 30 384
+1815 */{ 0 , 2 , 9 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1816 */{ 6 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1817 */{ 0 , 2 , 16 , 46368 },/* 30 29 30 30 29 30 29 30 29 29 30 29 0 354
+1818 */{ 0 , 2 , 5 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1819 */{ 4 , 1 , 26 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1820 */{ 0 , 2 , 14 , 21968 },/* 29 30 29 30 29 30 29 30 30 30 29 30 0 355
+1821 */{ 0 , 2 , 3 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1822 */{ 3 , 1 , 23 , 41688 },/* 30 29 30 29 29 29 30 29 30 30 29 30 30 384
+1823 */{ 0 , 2 , 11 , 41648 },/* 30 29 30 29 29 29 30 29 30 29 30 30 0 354
+1824 */{ 7 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1825 */{ 0 , 2 , 18 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1826 */{ 0 , 2 , 7 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1827 */{ 5 , 1 , 27 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+1828 */{ 0 , 2 , 15 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+1829 */{ 0 , 2 , 4 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1830 */{ 4 , 1 , 25 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1831 */{ 0 , 2 , 13 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1832 */{ 9 , 2 , 2 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1833 */{ 0 , 2 , 20 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1834 */{ 0 , 2 , 9 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1835 */{ 6 , 1 , 29 , 27816 },/* 29 30 30 29 30 30 29 29 30 29 30 29 30 384
+1836 */{ 0 , 2 , 17 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1837 */{ 0 , 2 , 5 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1838 */{ 4 , 1 , 26 , 21352 },/* 29 30 29 30 29 29 30 30 29 30 30 29 30 384
+1839 */{ 0 , 2 , 14 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1840 */{ 0 , 2 , 3 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1841 */{ 3 , 1 , 23 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 29 383
+1842 */{ 0 , 2 , 10 , 53920 },/* 30 30 29 30 29 29 30 29 30 29 30 29 0 354
+1843 */{ 7 , 1 , 30 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 29 384
+1844 */{ 0 , 2 , 18 , 54608 },/* 30 30 29 30 29 30 29 30 29 30 29 30 0 355
+1845 */{ 0 , 2 , 7 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+1846 */{ 5 , 1 , 27 , 43728 },/* 30 29 30 29 30 29 30 29 30 30 29 30 29 384
+1847 */{ 0 , 2 , 15 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1848 */{ 0 , 2 , 5 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1849 */{ 4 , 1 , 24 , 42328 },/* 30 29 30 29 29 30 29 30 29 30 29 30 30 384
+1850 */{ 0 , 2 , 12 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1851 */{ 8 , 2 , 1 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+1852 */{ 0 , 2 , 20 , 45712 },/* 30 29 30 30 29 29 30 29 30 29 29 30 0 354
+1853 */{ 0 , 2 , 8 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1854 */{ 7 , 1 , 29 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1855 */{ 0 , 2 , 17 , 11680 },/* 29 29 30 29 30 30 29 30 30 29 30 29 0 354
+1856 */{ 0 , 2 , 6 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1857 */{ 5 , 1 , 26 , 19128 },/* 29 30 29 29 30 29 30 29 30 29 30 30 30 384
+1858 */{ 0 , 2 , 14 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1859 */{ 0 , 2 , 3 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1860 */{ 3 , 1 , 23 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1861 */{ 0 , 2 , 10 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1862 */{ 8 , 1 , 30 , 44360 },/* 30 29 30 29 30 30 29 30 29 30 29 29 30 384
+1863 */{ 0 , 2 , 18 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 0 355
+1864 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1865 */{ 5 , 1 , 27 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+1866 */{ 0 , 2 , 15 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 0 355
+1867 */{ 0 , 2 , 5 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1868 */{ 4 , 1 , 25 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1869 */{ 0 , 2 , 11 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
+1870 */{ 10 , 1 , 31 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 29 384
+1871 */{ 0 , 2 , 19 , 55952 },/* 30 30 29 30 30 29 30 29 30 29 29 30 0 355
+1872 */{ 0 , 2 , 9 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1873 */{ 6 , 1 , 29 , 11112 },/* 29 29 30 29 30 29 30 30 29 30 30 29 30 384
+1874 */{ 0 , 2 , 17 , 10976 },/* 29 29 30 29 30 29 30 29 30 30 30 29 0 354
+1875 */{ 0 , 2 , 6 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1876 */{ 5 , 1 , 26 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1877 */{ 0 , 2 , 13 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1878 */{ 0 , 2 , 2 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1879 */{ 3 , 1 , 22 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1880 */{ 0 , 2 , 10 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1881 */{ 7 , 1 , 30 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 29 384
+1882 */{ 0 , 2 , 18 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1883 */{ 0 , 2 , 8 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1884 */{ 5 , 1 , 28 , 37592 },/* 30 29 29 30 29 29 30 29 30 30 29 30 30 384
+1885 */{ 0 , 2 , 15 , 37552 },/* 30 29 29 30 29 29 30 29 30 29 30 30 0 354
+1886 */{ 0 , 2 , 4 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1887 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1888 */{ 0 , 2 , 12 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1889 */{ 0 , 1 , 31 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1890 */{ 2 , 1 , 21 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1891 */{ 0 , 2 , 9 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 0 355
+1892 */{ 6 , 1 , 30 , 9656 },/* 29 29 30 29 29 30 29 30 30 29 30 30 30 384
+1893 */{ 0 , 2 , 17 , 9584 },/* 29 29 30 29 29 30 29 30 29 30 30 30 0 354
+1894 */{ 0 , 2 , 6 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1895 */{ 5 , 1 , 26 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1896 */{ 0 , 2 , 13 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1897 */{ 0 , 2 , 2 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1898 */{ 3 , 1 , 22 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1899 */{ 0 , 2 , 10 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1900 */{ 8 , 1 , 31 , 19304 },/* 29 30 29 29 30 29 30 30 29 30 30 29 30 384
+1901 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1902 */{ 0 , 2 , 8 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1903 */{ 5 , 1 , 29 , 21096 },/* 29 30 29 30 29 29 30 29 29 30 30 29 30 383
+1904 */{ 0 , 2 , 16 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+1905 */{ 0 , 2 , 4 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1906 */{ 4 , 1 , 25 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1907 */{ 0 , 2 , 13 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1908 */{ 0 , 2 , 2 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1909 */{ 2 , 1 , 22 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1910 */{ 0 , 2 , 10 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1911 */{ 6 , 1 , 30 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 55624 },/* 30 30 29 30 30 29 29 30 29 30 29 29 30 384
+1915 */{ 0 , 2 , 14 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1916 */{ 0 , 2 , 4 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38352 },/* 30 29 29 30 29 30 29 30 30 30 29 30 0 355
+1919 */{ 7 , 2 , 1 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+1920 */{ 0 , 2 , 20 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27280 },/* 29 30 30 29 30 29 30 29 30 29 29 30 0 354
+1924 */{ 0 , 2 , 5 , 44352 },/* 30 29 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 58528 },/* 30 30 30 29 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23376 },/* 29 30 29 30 30 29 30 30 29 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46736 },/* 30 29 30 30 29 30 30 29 30 29 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+1944 */{ 4 , 1 , 26 , 10968 },/* 29 29 30 29 30 29 30 29 30 30 29 30 30 384
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 22184 },/* 29 30 29 30 29 30 30 29 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19888 },/* 29 30 29 29 30 30 29 30 30 29 30 30 0 355
+1954 */{ 0 , 2 , 4 , 9648 },/* 29 29 30 29 29 30 29 30 30 29 30 30 0 354
+1955 */{ 3 , 1 , 24 , 37560 },/* 30 29 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43352 },/* 30 29 30 29 30 29 29 30 29 30 29 30 30 384
+1958 */{ 0 , 2 , 19 , 26960 },/* 29 30 30 29 30 29 29 30 29 30 29 30 0 354
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+1966 */{ 3 , 1 , 22 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 27304 },/* 29 30 30 29 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 39632 },/* 30 29 29 30 30 29 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+1973 */{ 0 , 2 , 3 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54600 },/* 30 30 29 30 29 30 29 30 29 30 29 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42200 },/* 30 29 30 29 29 30 29 29 30 30 29 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 46504 },/* 30 29 30 30 29 30 29 30 30 29 30 29 30 385
+1988 */{ 0 , 2 , 18 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1989 */{ 0 , 2 , 6 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1996 */{ 0 , 2 , 19 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1997 */{ 0 , 2 , 8 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1998 */{ 5 , 1 , 28 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 58536 },/* 30 30 30 29 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22208 },/* 29 30 29 30 29 30 30 29 30 30 29 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 3 , 1 , 23 , 47696 },/* 30 29 30 30 30 29 30 29 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 5 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2020 */{ 4 , 1 , 25 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+2027 */{ 0 , 2 , 7 , 21104 },/* 29 30 29 30 29 29 30 29 29 30 30 30 0 354
+2028 */{ 5 , 1 , 27 , 26928 },/* 29 30 30 29 30 29 29 30 29 29 30 30 29 383
+2029 */{ 0 , 2 , 13 , 55600 },/* 30 30 29 30 30 29 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19168 },/* 29 30 29 29 30 29 30 29 30 30 30 29 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 45648 },/* 30 29 30 30 29 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 29 384
+ */};
+
+
+ internal override int MinCalendarYear {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo {
+ get
+ {
+ return null;
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index) {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR ));
+ }
+ Contract.EndContractBlock();
+ return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time)
+ {
+ return year;
+ }
+
+ internal override int GetGregorianYear(int year, int era)
+ {
+ if (era != CurrentEra && era != GregorianEra)
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+
+ if (year < MIN_LUNISOLAR_YEAR || year > MAX_LUNISOLAR_YEAR)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"), MIN_LUNISOLAR_YEAR, MAX_LUNISOLAR_YEAR));
+ }
+ Contract.EndContractBlock();
+
+ return year;
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of KoreanLunisolarCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance()
+ {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new KoreanLunisolarCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+ // Construct an instance of KoreanLunisolar calendar.
+
+ public KoreanLunisolarCalendar() {
+ }
+
+
+
+ public override int GetEra(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return (GregorianEra);
+ }
+
+ internal override int BaseCalendarID {
+ get {
+ return (CAL_KOREA);
+ }
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_KOREANLUNISOLAR);
+ }
+ }
+
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {GregorianEra});
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs
new file mode 100644
index 0000000000..fae91c2a1d
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/NumberFormatInfo.cs
@@ -0,0 +1,842 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System.Security.Permissions;
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ //
+ // Property Default Description
+ // PositiveSign '+' Character used to indicate positive values.
+ // NegativeSign '-' Character used to indicate negative values.
+ // NumberDecimalSeparator '.' The character used as the decimal separator.
+ // NumberGroupSeparator ',' The character used to separate groups of
+ // digits to the left of the decimal point.
+ // NumberDecimalDigits 2 The default number of decimal places.
+ // NumberGroupSizes 3 The number of digits in each group to the
+ // left of the decimal point.
+ // NaNSymbol "NaN" The string used to represent NaN values.
+ // PositiveInfinitySymbol"Infinity" The string used to represent positive
+ // infinities.
+ // NegativeInfinitySymbol"-Infinity" The string used to represent negative
+ // infinities.
+ //
+ //
+ //
+ // Property Default Description
+ // CurrencyDecimalSeparator '.' The character used as the decimal
+ // separator.
+ // CurrencyGroupSeparator ',' The character used to separate groups
+ // of digits to the left of the decimal
+ // point.
+ // CurrencyDecimalDigits 2 The default number of decimal places.
+ // CurrencyGroupSizes 3 The number of digits in each group to
+ // the left of the decimal point.
+ // CurrencyPositivePattern 0 The format of positive values.
+ // CurrencyNegativePattern 0 The format of negative values.
+ // CurrencySymbol "$" String used as local monetary symbol.
+ //
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public partial class NumberFormatInfo : ICloneable, IFormatProvider
+ {
+ // invariantInfo is constant irrespective of your current culture.
+ private static volatile NumberFormatInfo invariantInfo;
+
+ // READTHIS READTHIS READTHIS
+ // This class has an exact mapping onto a native structure defined in COMNumber.cpp
+ // DO NOT UPDATE THIS WITHOUT UPDATING THAT STRUCTURE. IF YOU ADD BOOL, ADD THEM AT THE END.
+ // ALSO MAKE SURE TO UPDATE mscorlib.h in the VM directory to check field offsets.
+ // READTHIS READTHIS READTHIS
+ internal int[] numberGroupSizes = new int[] {3};
+ internal int[] currencyGroupSizes = new int[] {3};
+ internal int[] percentGroupSizes = new int[] {3};
+ internal String positiveSign = "+";
+ internal String negativeSign = "-";
+ internal String numberDecimalSeparator = ".";
+ internal String numberGroupSeparator = ",";
+ internal String currencyGroupSeparator = ",";
+ internal String currencyDecimalSeparator = ".";
+ internal String currencySymbol = "\x00a4"; // U+00a4 is the symbol for International Monetary Fund.
+ // The alternative currency symbol used in Win9x ANSI codepage, that can not roundtrip between ANSI and Unicode.
+ // Currently, only ja-JP and ko-KR has non-null values (which is U+005c, backslash)
+ // NOTE: The only legal values for this string are null and "\x005c"
+ internal String ansiCurrencySymbol = null;
+ internal String nanSymbol = "NaN";
+ internal String positiveInfinitySymbol = "Infinity";
+ internal String negativeInfinitySymbol = "-Infinity";
+ internal String percentDecimalSeparator = ".";
+ internal String percentGroupSeparator = ",";
+ internal String percentSymbol = "%";
+ internal String perMilleSymbol = "\u2030";
+
+ [OptionalField(VersionAdded = 2)]
+ internal String[] nativeDigits = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
+
+ // an index which points to a record in Culture Data Table.
+ // We shouldn't be persisting dataItem (since its useless & we weren't using it),
+ // but since COMNumber.cpp uses it and since serialization isn't implimented, its stuck for now.
+ [OptionalField(VersionAdded = 1)]
+ internal int m_dataItem = 0; // NEVER USED, DO NOT USE THIS! (Serialized in Everett)
+
+ internal int numberDecimalDigits = 2;
+ internal int currencyDecimalDigits = 2;
+ internal int currencyPositivePattern = 0;
+ internal int currencyNegativePattern = 0;
+ internal int numberNegativePattern = 1;
+ internal int percentPositivePattern = 0;
+ internal int percentNegativePattern = 0;
+ internal int percentDecimalDigits = 2;
+
+ [OptionalField(VersionAdded = 2)]
+ internal int digitSubstitution = 1; // DigitShapes.None
+
+ internal bool isReadOnly=false;
+ // We shouldn't be persisting m_useUserOverride (since its useless & we weren't using it),
+ // but since COMNumber.cpp uses it and since serialization isn't implimented, its stuck for now.
+ [OptionalField(VersionAdded = 1)]
+ internal bool m_useUserOverride=false; // NEVER USED, DO NOT USE THIS! (Serialized in Everett)
+
+ // Is this NumberFormatInfo for invariant culture?
+ [OptionalField(VersionAdded = 2)]
+ internal bool m_isInvariant=false;
+
+ public NumberFormatInfo() : this(null) {
+ }
+
+#region Serialization
+ // Check if NumberFormatInfo was not set up ambiguously for parsing as number and currency
+ // eg. if the NumberDecimalSeparator and the NumberGroupSeparator were the same. This check
+ // is solely for backwards compatibility / version tolerant serialization
+ [OptionalField(VersionAdded = 1)]
+ internal bool validForParseAsNumber = true; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
+ [OptionalField(VersionAdded = 1)]
+ internal bool validForParseAsCurrency = true; // NEVER USED, DO NOT USE THIS! (Serialized in Whidbey/Everett)
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+#if !FEATURE_CORECLR
+ // Update these legacy flags, so that 1.1/2.0 versions of the framework
+ // can still throw while parsing; even when using a de-serialized
+ // NumberFormatInfo from a 4.0+ version of the framework
+ if (numberDecimalSeparator != numberGroupSeparator) {
+ validForParseAsNumber = true;
+ } else {
+ validForParseAsNumber = false;
+ }
+
+ if ((numberDecimalSeparator != numberGroupSeparator) &&
+ (numberDecimalSeparator != currencyGroupSeparator) &&
+ (currencyDecimalSeparator != numberGroupSeparator) &&
+ (currencyDecimalSeparator != currencyGroupSeparator)) {
+ validForParseAsCurrency = true;
+ } else {
+ validForParseAsCurrency = false;
+ }
+#endif // !FEATURE_CORECLR
+ }
+
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ }
+#endregion Serialization
+
+
+ static private void VerifyDecimalSeparator(String decSep, String propertyName) {
+ if (decSep==null) {
+ throw new ArgumentNullException(propertyName,
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+
+ if (decSep.Length==0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyDecString"));
+ }
+ Contract.EndContractBlock();
+
+ }
+
+ static private void VerifyGroupSeparator(String groupSep, String propertyName) {
+ if (groupSep==null) {
+ throw new ArgumentNullException(propertyName,
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ static private void VerifyNativeDigits(String [] nativeDig, String propertyName) {
+ if (nativeDig==null) {
+ throw new ArgumentNullException(propertyName,
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+
+ if (nativeDig.Length != 10)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitCount"), propertyName);
+ }
+ Contract.EndContractBlock();
+
+ for(int i = 0; i < nativeDig.Length; i++)
+ {
+ if (nativeDig[i] == null)
+ {
+ throw new ArgumentNullException(propertyName,
+ Environment.GetResourceString("ArgumentNull_ArrayValue"));
+ }
+
+
+ if (nativeDig[i].Length != 1) {
+ if(nativeDig[i].Length != 2) {
+ // Not 1 or 2 UTF-16 code points
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName);
+ } else if(!char.IsSurrogatePair(nativeDig[i][0], nativeDig[i][1])) {
+ // 2 UTF-6 code points, but not a surrogate pair
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName);
+ }
+ }
+
+ if (CharUnicodeInfo.GetDecimalDigitValue(nativeDig[i], 0) != i &&
+ CharUnicodeInfo.GetUnicodeCategory(nativeDig[i], 0) != UnicodeCategory.PrivateUse) {
+ // Not the appropriate digit according to the Unicode data properties
+ // (Digit 0 must be a 0, etc.).
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNativeDigitValue"), propertyName);
+ }
+ }
+ }
+
+ static private void VerifyDigitSubstitution(DigitShapes digitSub, String propertyName) {
+ switch(digitSub)
+ {
+ case DigitShapes.Context:
+ case DigitShapes.None:
+ case DigitShapes.NativeNational:
+ // Success.
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDigitSubstitution"), propertyName);
+ }
+ }
+
+ // We aren't persisting dataItem any more (since its useless & we weren't using it),
+ // Ditto with m_useUserOverride. Don't use them, we use a local copy of everything.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal NumberFormatInfo(CultureData cultureData)
+ {
+ if (cultureData != null)
+ {
+ // We directly use fields here since these data is coming from data table or Win32, so we
+ // don't need to verify their values (except for invalid parsing situations).
+ cultureData.GetNFIValues(this);
+
+ if (cultureData.IsInvariantCulture)
+ {
+ // For invariant culture
+ this.m_isInvariant = true;
+ }
+ }
+ }
+
+ [Pure]
+ private void VerifyWritable() {
+ if (isReadOnly) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ // Returns a default NumberFormatInfo that will be universally
+ // supported and constant irrespective of the current culture.
+ // Used by FromString methods.
+ //
+
+ public static NumberFormatInfo InvariantInfo {
+ get {
+ if (invariantInfo == null) {
+ // Lazy create the invariant info. This cannot be done in a .cctor because exceptions can
+ // be thrown out of a .cctor stack that will need this.
+ NumberFormatInfo nfi = new NumberFormatInfo();
+ nfi.m_isInvariant = true;
+ invariantInfo = ReadOnly(nfi);
+ }
+ return invariantInfo;
+ }
+ }
+
+
+ public static NumberFormatInfo GetInstance(IFormatProvider formatProvider) {
+ // Fast case for a regular CultureInfo
+ NumberFormatInfo info;
+ CultureInfo cultureProvider = formatProvider as CultureInfo;
+ if (cultureProvider != null && !cultureProvider.m_isInherited) {
+ info = cultureProvider.numInfo;
+ if (info != null) {
+ return info;
+ }
+ else {
+ return cultureProvider.NumberFormat;
+ }
+ }
+ // Fast case for an NFI;
+ info = formatProvider as NumberFormatInfo;
+ if (info != null) {
+ return info;
+ }
+ if (formatProvider != null) {
+ info = formatProvider.GetFormat(typeof(NumberFormatInfo)) as NumberFormatInfo;
+ if (info != null) {
+ return info;
+ }
+ }
+ return CurrentInfo;
+ }
+
+
+
+ public Object Clone() {
+ NumberFormatInfo n = (NumberFormatInfo)MemberwiseClone();
+ n.isReadOnly = false;
+ return n;
+ }
+
+
+ public int CurrencyDecimalDigits {
+ get { return currencyDecimalDigits; }
+ set {
+ if (value < 0 || value > 99) {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyDecimalDigits = value;
+ }
+ }
+
+
+ public String CurrencyDecimalSeparator {
+ get { return currencyDecimalSeparator; }
+ set {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "CurrencyDecimalSeparator");
+ currencyDecimalSeparator = value;
+ }
+ }
+
+
+ public bool IsReadOnly {
+ get {
+ return isReadOnly;
+ }
+ }
+
+ //
+ // Check the values of the groupSize array.
+ //
+ // Every element in the groupSize array should be between 1 and 9
+ // excpet the last element could be zero.
+ //
+ static internal void CheckGroupSize(String propName, int[] groupSize)
+ {
+ for (int i = 0; i < groupSize.Length; i++)
+ {
+ if (groupSize[i] < 1)
+ {
+ if (i == groupSize.Length - 1 && groupSize[i] == 0)
+ return;
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGroupSize"), propName);
+ }
+ else if (groupSize[i] > 9)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGroupSize"), propName);
+ }
+ }
+ }
+
+
+ public int[] CurrencyGroupSizes {
+ get {
+ return ((int[])currencyGroupSizes.Clone());
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("CurrencyGroupSizes",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("CurrencyGroupSizes", inputSizes);
+ currencyGroupSizes = inputSizes;
+ }
+
+ }
+
+
+
+ public int[] NumberGroupSizes {
+ get {
+ return ((int[])numberGroupSizes.Clone());
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("NumberGroupSizes",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("NumberGroupSizes", inputSizes);
+ numberGroupSizes = inputSizes;
+ }
+ }
+
+
+ public int[] PercentGroupSizes {
+ get {
+ return ((int[])percentGroupSizes.Clone());
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("PercentGroupSizes",
+ Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ Int32[] inputSizes = (Int32[])value.Clone();
+ CheckGroupSize("PercentGroupSizes", inputSizes);
+ percentGroupSizes = inputSizes;
+ }
+
+ }
+
+
+ public String CurrencyGroupSeparator {
+ get { return currencyGroupSeparator; }
+ set {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "CurrencyGroupSeparator");
+ currencyGroupSeparator = value;
+ }
+ }
+
+
+ public String CurrencySymbol {
+ get { return currencySymbol; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("CurrencySymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencySymbol = value;
+ }
+ }
+
+ // Returns the current culture's NumberFormatInfo. Used by Parse methods.
+ //
+
+ public static NumberFormatInfo CurrentInfo {
+ get {
+ System.Globalization.CultureInfo culture = System.Threading.Thread.CurrentThread.CurrentCulture;
+ if (!culture.m_isInherited) {
+ NumberFormatInfo info = culture.numInfo;
+ if (info != null) {
+ return info;
+ }
+ }
+ return ((NumberFormatInfo)culture.GetFormat(typeof(NumberFormatInfo)));
+ }
+ }
+
+
+ public String NaNSymbol {
+ get {
+ return nanSymbol;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("NaNSymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ nanSymbol = value;
+ }
+ }
+
+
+
+ public int CurrencyNegativePattern {
+ get { return currencyNegativePattern; }
+ set {
+ if (value < 0 || value > 15) {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 15));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyNegativePattern = value;
+ }
+ }
+
+
+ public int NumberNegativePattern {
+ get { return numberNegativePattern; }
+ set {
+ //
+ // NOTENOTE: the range of value should correspond to negNumberFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 4) {
+ throw new ArgumentOutOfRangeException(
+ "NumberNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 4));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ numberNegativePattern = value;
+ }
+ }
+
+
+ public int PercentPositivePattern {
+ get { return percentPositivePattern; }
+ set {
+ //
+ // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 3) {
+ throw new ArgumentOutOfRangeException(
+ "PercentPositivePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 3));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentPositivePattern = value;
+ }
+ }
+
+
+ public int PercentNegativePattern {
+ get { return percentNegativePattern; }
+ set {
+ //
+ // NOTENOTE: the range of value should correspond to posPercentFormats[] in vm\COMNumber.cpp.
+ //
+ if (value < 0 || value > 11) {
+ throw new ArgumentOutOfRangeException(
+ "PercentNegativePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 11));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentNegativePattern = value;
+ }
+ }
+
+
+ public String NegativeInfinitySymbol {
+ get {
+ return negativeInfinitySymbol;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("NegativeInfinitySymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ negativeInfinitySymbol = value;
+ }
+ }
+
+
+ public String NegativeSign {
+ get { return negativeSign; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("NegativeSign",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ negativeSign = value;
+ }
+ }
+
+
+ public int NumberDecimalDigits {
+ get { return numberDecimalDigits; }
+ set {
+ if (value < 0 || value > 99) {
+ throw new ArgumentOutOfRangeException(
+ "NumberDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ numberDecimalDigits = value;
+ }
+ }
+
+
+ public String NumberDecimalSeparator {
+ get { return numberDecimalSeparator; }
+ set {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "NumberDecimalSeparator");
+ numberDecimalSeparator = value;
+ }
+ }
+
+
+ public String NumberGroupSeparator {
+ get { return numberGroupSeparator; }
+ set {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "NumberGroupSeparator");
+ numberGroupSeparator = value;
+ }
+ }
+
+
+ public int CurrencyPositivePattern {
+ get { return currencyPositivePattern; }
+ set {
+ if (value < 0 || value > 3) {
+ throw new ArgumentOutOfRangeException(
+ "CurrencyPositivePattern",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 3));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ currencyPositivePattern = value;
+ }
+ }
+
+
+ public String PositiveInfinitySymbol {
+ get {
+ return positiveInfinitySymbol;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("PositiveInfinitySymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ positiveInfinitySymbol = value;
+ }
+ }
+
+
+ public String PositiveSign {
+ get { return positiveSign; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("PositiveSign",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ positiveSign = value;
+ }
+ }
+
+
+ public int PercentDecimalDigits {
+ get { return percentDecimalDigits; }
+ set {
+ if (value < 0 || value > 99) {
+ throw new ArgumentOutOfRangeException(
+ "PercentDecimalDigits",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 0,
+ 99));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentDecimalDigits = value;
+ }
+ }
+
+
+ public String PercentDecimalSeparator {
+ get { return percentDecimalSeparator; }
+ set {
+ VerifyWritable();
+ VerifyDecimalSeparator(value, "PercentDecimalSeparator");
+ percentDecimalSeparator = value;
+ }
+ }
+
+
+ public String PercentGroupSeparator {
+ get { return percentGroupSeparator; }
+ set {
+ VerifyWritable();
+ VerifyGroupSeparator(value, "PercentGroupSeparator");
+ percentGroupSeparator = value;
+ }
+ }
+
+
+ public String PercentSymbol {
+ get {
+ return percentSymbol;
+ }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("PercentSymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ percentSymbol = value;
+ }
+ }
+
+
+ public String PerMilleSymbol {
+ get { return perMilleSymbol; }
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("PerMilleSymbol",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ perMilleSymbol = value;
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public String[] NativeDigits
+ {
+ get { return (String[])nativeDigits.Clone(); }
+ set
+ {
+ VerifyWritable();
+ VerifyNativeDigits(value, "NativeDigits");
+ nativeDigits = value;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public DigitShapes DigitSubstitution
+ {
+ get { return (DigitShapes)digitSubstitution; }
+ set
+ {
+ VerifyWritable();
+ VerifyDigitSubstitution(value, "DigitSubstitution");
+ digitSubstitution = (int)value;
+ }
+ }
+
+ public Object GetFormat(Type formatType) {
+ return formatType == typeof(NumberFormatInfo)? this: null;
+ }
+
+ public static NumberFormatInfo ReadOnly(NumberFormatInfo nfi) {
+ if (nfi == null) {
+ throw new ArgumentNullException("nfi");
+ }
+ Contract.EndContractBlock();
+ if (nfi.IsReadOnly) {
+ return (nfi);
+ }
+ NumberFormatInfo info = (NumberFormatInfo)(nfi.MemberwiseClone());
+ info.isReadOnly = true;
+ return info;
+ }
+
+ // private const NumberStyles InvalidNumberStyles = unchecked((NumberStyles) 0xFFFFFC00);
+ private const NumberStyles InvalidNumberStyles = ~(NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite
+ | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign
+ | NumberStyles.AllowParentheses | NumberStyles.AllowDecimalPoint
+ | NumberStyles.AllowThousands | NumberStyles.AllowExponent
+ | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier);
+
+ internal static void ValidateParseStyleInteger(NumberStyles style) {
+ // Check for undefined flags
+ if ((style & InvalidNumberStyles) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), "style");
+ }
+ Contract.EndContractBlock();
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number
+ if ((style & ~NumberStyles.HexNumber) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHexStyle"));
+ }
+ }
+ }
+
+ internal static void ValidateParseStyleFloatingPoint(NumberStyles style) {
+ // Check for undefined flags
+ if ((style & InvalidNumberStyles) != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNumberStyles"), "style");
+ }
+ Contract.EndContractBlock();
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // Check for hex number
+ throw new ArgumentException(Environment.GetResourceString("Arg_HexStyleNotSupported"));
+ }
+ }
+ } // NumberFormatInfo
+}
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Globalization/NumberStyles.cs b/src/mscorlib/src/System/Globalization/NumberStyles.cs
new file mode 100644
index 0000000000..42b9847ed3
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/NumberStyles.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Contains valid formats for Numbers recognized by
+** the Number class' parsing code.
+**
+**
+===========================================================*/
+namespace System.Globalization {
+
+ using System;
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum NumberStyles {
+ // Bit flag indicating that leading whitespace is allowed. Character values
+ // 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, and 0x0020 are considered to be
+ // whitespace.
+
+ None = 0x00000000,
+
+ AllowLeadingWhite = 0x00000001,
+
+ AllowTrailingWhite = 0x00000002, //Bitflag indicating trailing whitespace is allowed.
+
+ AllowLeadingSign = 0x00000004, //Can the number start with a sign char.
+ //Specified by NumberFormatInfo.PositiveSign and NumberFormatInfo.NegativeSign
+
+ AllowTrailingSign = 0x00000008, //Allow the number to end with a sign char
+
+ AllowParentheses = 0x00000010, //Allow the number to be enclosed in parens
+
+ AllowDecimalPoint = 0x00000020, //Allow a decimal point
+
+ AllowThousands = 0x00000040, //Allow thousands separators (more properly, allow group separators)
+
+ AllowExponent = 0x00000080, //Allow an exponent
+
+ AllowCurrencySymbol = 0x00000100, //Allow a currency symbol.
+
+ AllowHexSpecifier = 0x00000200, //Allow specifiying hexadecimal.
+ //Common uses. These represent some of the most common combinations of these flags.
+
+
+ Integer = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign,
+
+ HexNumber = AllowLeadingWhite | AllowTrailingWhite | AllowHexSpecifier,
+
+ Number = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
+ AllowDecimalPoint | AllowThousands,
+
+ Float = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign |
+ AllowDecimalPoint | AllowExponent,
+
+ Currency = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
+ AllowParentheses | AllowDecimalPoint | AllowThousands | AllowCurrencySymbol,
+
+ Any = AllowLeadingWhite | AllowTrailingWhite | AllowLeadingSign | AllowTrailingSign |
+ AllowParentheses | AllowDecimalPoint | AllowThousands | AllowCurrencySymbol | AllowExponent,
+
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/PersianCalendar.cs b/src/mscorlib/src/System/Globalization/PersianCalendar.cs
new file mode 100644
index 0000000000..2f1ffacee7
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/PersianCalendar.cs
@@ -0,0 +1,577 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about PersianCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ // Modern Persian calendar is a solar observation based calendar. Each new year begins on the day when the vernal equinox occurs before noon.
+ // The epoch is the date of the vernal equinox prior to the epoch of the Islamic calendar (March 19, 622 Julian or March 22, 622 Gregorian)
+
+ // There is no Persian year 0. Ordinary years have 365 days. Leap years have 366 days with the last month (Esfand) gaining the extra day.
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0622/03/22 9999/12/31
+ ** Persian 0001/01/01 9378/10/13
+ */
+
+ [Serializable]
+ public class PersianCalendar : Calendar {
+
+
+ public static readonly int PersianEra = 1;
+
+ internal static long PersianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay;
+ const int ApproximateHalfYear = 180;
+
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+ internal const int MonthsPerYear = 12;
+
+ internal static int[] DaysToMonth = { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 };
+
+ internal const int MaxCalendarYear = 9378;
+ internal const int MaxCalendarMonth = 10;
+ internal const int MaxCalendarDay = 13;
+
+ // Persian calendar (year: 1, month: 1, day:1 ) = Gregorian (year: 622, month: 3, day: 22)
+ // This is the minimal Gregorian date that we support in the PersianCalendar.
+ internal static DateTime minDate = new DateTime(622, 3, 22);
+ internal static DateTime maxDate = DateTime.MaxValue;
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of PersianCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new PersianCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ // Return the type of the Persian calendar.
+ //
+
+
+ public override CalendarAlgorithmType AlgorithmType {
+ get {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ // Construct an instance of Persian calendar.
+
+ public PersianCalendar() {
+ }
+
+
+ internal override int BaseCalendarID {
+ get {
+ return (CAL_GREGORIAN);
+ }
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_PERSIAN);
+ }
+ }
+
+
+ /*=================================GetAbsoluteDatePersian==========================
+ **Action: Gets the Absolute date for the given Persian date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ long GetAbsoluteDatePersian(int year, int month, int day) {
+ if (year >= 1 && year <= MaxCalendarYear && month >= 1 && month <= 12)
+ {
+ int ordinalDay = DaysInPreviousMonths(month) + day - 1; // day is one based, make 0 based since this will be the number of days we add to beginning of year below
+ int approximateDaysFromEpochForYearStart = (int)(CalendricalCalculationsHelper.MeanTropicalYearInDays * (year - 1));
+ long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(PersianEpoch + approximateDaysFromEpochForYearStart + ApproximateHalfYear);
+ yearStart += ordinalDay;
+ return yearStart;
+ }
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+
+ static internal void CheckTicksRange(long ticks) {
+ if (ticks < minDate.Ticks || ticks > maxDate.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ minDate,
+ maxDate));
+ }
+ }
+
+ static internal void CheckEraRange(int era) {
+ if (era != CurrentEra && era != PersianEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ static internal void CheckYearRange(int year, int era) {
+ CheckEraRange(era);
+ if (year < 1 || year > MaxCalendarYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarYear));
+ }
+ }
+
+ static internal void CheckYearMonthRange(int year, int month, int era) {
+ CheckYearRange(year, era);
+ if (year == MaxCalendarYear) {
+ if (month > MaxCalendarMonth) {
+ throw new ArgumentOutOfRangeException(
+ "month",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarMonth));
+ }
+ }
+
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ }
+
+ static int MonthFromOrdinalDay(int ordinalDay)
+ {
+ Contract.Assert(ordinalDay <= 366);
+ int index = 0;
+ while (ordinalDay > DaysToMonth[index])
+ index++;
+
+ return index;
+ }
+
+ static int DaysInPreviousMonths(int month)
+ {
+ Contract.Assert(1 <= month && month <= 12);
+ --month; // months are one based but for calculations use 0 based
+ return DaysToMonth[month];
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ ============================================================================*/
+
+ internal int GetDatePart(long ticks, int part) {
+ long NumDays; // The calculation buffer in number of days.
+
+ CheckTicksRange(ticks);
+
+ //
+ // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
+ // 1/1/0001 is absolute date 1.
+ //
+ NumDays = ticks / GregorianCalendar.TicksPerDay + 1;
+
+ //
+ // Calculate the appromixate Persian Year.
+ //
+
+ long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(NumDays);
+ int y = (int)(Math.Floor(((yearStart - PersianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1;
+ Contract.Assert(y >= 1);
+
+ if (part == DatePartYear)
+ {
+ return y;
+ }
+
+ //
+ // Calculate the Persian Month.
+ //
+
+ int ordinalDay = (int)(NumDays - CalendricalCalculationsHelper.GetNumberOfDays(this.ToDateTime(y, 1, 1, 0, 0, 0, 0, 1)));
+
+ if (part == DatePartDayOfYear)
+ {
+ return ordinalDay;
+ }
+
+ int m = MonthFromOrdinalDay(ordinalDay);
+ Contract.Assert(ordinalDay >= 1);
+ Contract.Assert(m >= 1 && m <= 12);
+ if (part == DatePartMonth)
+ {
+ return m;
+ }
+
+ int d = ordinalDay - DaysInPreviousMonths(m);
+ Contract.Assert(1 <= d);
+ Contract.Assert(d <= 31);
+
+ //
+ // Calculate the Persian Day.
+ //
+
+ if (part == DatePartDay)
+ {
+ return (d);
+ }
+
+ // Incorrect part value.
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing"));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in Persian calendar.
+ int y = GetDatePart(time.Ticks, DatePartYear);
+ int m = GetDatePart(time.Ticks, DatePartMonth);
+ int d = GetDatePart(time.Ticks, DatePartDay);
+ int i = m - 1 + months;
+ if (i >= 0) {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ } else {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+ int days = GetDaysInMonth(y, m);
+ if (d > days) {
+ d = days;
+ }
+ long ticks = GetAbsoluteDatePersian(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay;
+ Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (new DateTime(ticks));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 366.
+ //
+
+
+ public override int GetDayOfYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartDayOfYear));
+ }
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+
+ if ((month==MaxCalendarMonth) && (year==MaxCalendarYear)) {
+ return MaxCalendarDay;
+ }
+
+ int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1];
+ if ((month == MonthsPerYear) && !IsLeapYear(year))
+ {
+ Contract.Assert(daysInMonth == 30);
+ --daysInMonth;
+ }
+ return daysInMonth;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+ public override int GetDaysInYear(int year, int era) {
+ CheckYearRange(year, era);
+ if (year==MaxCalendarYear) {
+ return DaysToMonth[MaxCalendarMonth-1] + MaxCalendarDay;
+ }
+ // Common years have 365 days. Leap years have 366 days.
+ return (IsLeapYear(year, CurrentEra) ? 366: 365);
+ }
+
+ // Returns the era for the specified DateTime value.
+
+
+ public override int GetEra(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return (PersianEra);
+ }
+
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {PersianEra});
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+
+ public override int GetMonth(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+
+ public override int GetMonthsInYear(int year, int era) {
+ CheckYearRange(year, era);
+ if (year==MaxCalendarYear) {
+ return MaxCalendarMonth;
+ }
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between 1 and MaxCalendarYear.
+ //
+
+
+ public override int GetYear(DateTime time) {
+ return (GetDatePart(time.Ticks, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era) {
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+ return (IsLeapYear(year, era) && month == 12 && day == 30);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+ public override bool IsLeapYear(int year, int era) {
+ CheckYearRange(year, era);
+
+ if (year == MaxCalendarYear)
+ {
+ return false;
+ }
+
+ return (GetAbsoluteDatePersian(year + 1, 1, 1) - GetAbsoluteDatePersian(year, 1, 1)) == 366;
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ // The year/month/era checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+
+ long lDate = GetAbsoluteDatePersian(year, month, day);
+
+ if (lDate >= 0) {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ } else {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1410;
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > MaxCalendarYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ MaxCalendarYear));
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100) {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if (year > MaxCalendarYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/RegionInfo.cs b/src/mscorlib/src/System/Globalization/RegionInfo.cs
new file mode 100644
index 0000000000..f06d63f1d2
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/RegionInfo.cs
@@ -0,0 +1,629 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class represents settings specified by de jure or
+// de facto standards for a particular country/region. In
+// contrast to CultureInfo, the RegionInfo does not represent
+// preferences of the user and does not depend on the user's
+// language or culture.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class RegionInfo
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //
+ // Variables.
+ //
+
+ //
+ // Name of this region (ie: es-US): serialized, the field used for deserialization
+ //
+ internal String m_name;
+
+ //
+ // The CultureData instance that we are going to read data from.
+ //
+ [NonSerialized]internal CultureData m_cultureData;
+
+ //
+ // The RegionInfo for our current region
+ //
+ internal static volatile RegionInfo s_currentRegionInfo;
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // RegionInfo Constructors
+ //
+ // Note: We prefer that a region be created with a full culture name (ie: en-US)
+ // because otherwise the native strings won't be right.
+ //
+ // In Silverlight we enforce that RegionInfos must be created with a full culture name
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public RegionInfo(String name) {
+ if (name==null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0) //The InvariantCulture has no matching region
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture"), "name");
+ }
+
+ Contract.EndContractBlock();
+
+ //
+ // First try it as an entire culture. We must have user override as true here so
+ // that we can pick up custom cultures *before* built-in ones (if they want to
+ // prefer built-in cultures they will pass "us" instead of "en-US").
+ //
+ this.m_cultureData = CultureData.GetCultureDataForRegion(name,true);
+ // this.m_name = name.ToUpper(CultureInfo.InvariantCulture);
+
+ if (this.m_cultureData == null)
+ throw new ArgumentException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Argument_InvalidCultureName"), name), "name");
+
+
+ // Not supposed to be neutral
+ if (this.m_cultureData.IsNeutralCulture)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidNeutralRegionName", name), "name");
+
+ SetName(name);
+ }
+
+#if FEATURE_USE_LCID
+ // We'd rather people use the named version since this doesn't allow custom locales
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public RegionInfo(int culture)
+ {
+ if (culture == CultureInfo.LOCALE_INVARIANT) //The InvariantCulture has no matching region
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoRegionInvariantCulture"));
+ }
+
+ if (culture == CultureInfo.LOCALE_NEUTRAL)
+ {
+ // Not supposed to be neutral
+ throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), "culture");
+ }
+
+ if (culture == CultureInfo.LOCALE_CUSTOM_DEFAULT)
+ {
+ // Not supposed to be neutral
+ throw new ArgumentException(Environment.GetResourceString("Argument_CustomCultureCannotBePassedByNumber", culture), "culture");
+ }
+
+ this.m_cultureData = CultureData.GetCultureData(culture,true);
+ this.m_name = this.m_cultureData.SREGIONNAME;
+
+ if (this.m_cultureData.IsNeutralCulture)
+ {
+ // Not supposed to be neutral
+ throw new ArgumentException(Environment.GetResourceString("Argument_CultureIsNeutral", culture), "culture");
+ }
+ m_cultureId = culture;
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RegionInfo(CultureData cultureData)
+ {
+ this.m_cultureData = cultureData;
+ this.m_name = this.m_cultureData.SREGIONNAME;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetName(string name)
+ {
+#if FEATURE_CORECLR
+ // Use the name of the region we found
+ this.m_name = this.m_cultureData.SREGIONNAME;
+#else
+ // when creating region by culture name, we keep the region name as the culture name so regions
+ // created by custom culture names can be differentiated from built in regions.
+ this.m_name = name.Equals(this.m_cultureData.SREGIONNAME, StringComparison.OrdinalIgnoreCase) ?
+ this.m_cultureData.SREGIONNAME :
+ this.m_cultureData.CultureName;
+#endif // FEATURE_CORECLR
+ }
+
+
+#region Serialization
+ //
+ // m_cultureId is needed for serialization only to detect the case if the region info is created using the name or using the LCID.
+ // in case m_cultureId is zero means that the RigionInfo is created using name. otherwise it is created using LCID.
+ //
+
+ [OptionalField(VersionAdded = 2)]
+ int m_cultureId;
+ // the following field is defined to keep the compatibility with Everett.
+ // don't change/remove the names/types of these field.
+ [OptionalField(VersionAdded = 2)]
+ internal int m_dataItem = 0;
+
+#if !FEATURE_CORECLR
+ static private readonly int[] IdFromEverettRegionInfoDataItem =
+ {
+ 0x3801, /* 0 */ // AE ar-AE Arabic (U.A.E.)
+ 0x041C, /* 1 */ // AL sq-AL Albanian (Albania)
+ 0x042B, /* 2 */ // AM hy-AM Armenian (Armenia)
+ 0x2C0A, /* 3 */ // AR es-AR Spanish (Argentina)
+ 0x0C07, /* 4 */ // AT de-AT German (Austria)
+ 0x0C09, /* 5 */ // AU en-AU English (Australia)
+ 0x042C, /* 6 */ // AZ az-AZ-Latn Azeri (Latin) (Azerbaijan)
+ // 0x082C, 6, // AZ az-AZ-Cyrl Azeri (Cyrillic) (Azerbaijan)
+ 0x080C, /* 7 */ // BE fr-BE French (Belgium)
+ // 0x0813, 7, // BE nl-BE Dutch (Belgium)
+ 0x0402, /* 8 */ // BG bg-BG Bulgarian (Bulgaria)
+ 0x3C01, /* 9 */ // BH ar-BH Arabic (Bahrain)
+ 0x083E, /* 10 */ // BN ms-BN Malay (Brunei Darussalam)
+ 0x400A, /* 11 */ // BO es-BO Spanish (Bolivia)
+ 0x0416, /* 12 */ // BR pt-BR Portuguese (Brazil)
+ 0x0423, /* 13 */ // BY be-BY Belarusian (Belarus)
+ 0x2809, /* 14 */ // BZ en-BZ English (Belize)
+ 0x0C0C, /* 15 */ // CA fr-CA French (Canada)
+ // 0x1009, 15, // CA en-CA English (Canada)
+ 0x2409, /* 16 */ // CB en-CB English (Caribbean)
+ 0x0807, /* 17 */ // CH de-CH German (Switzerland)
+ // 0x0810, 17, // CH it-CH Italian (Switzerland)
+ // 0x100C, 17, // CH fr-CH French (Switzerland)
+ 0x340A, /* 18 */ // CL es-CL Spanish (Chile)
+ 0x0804, /* 19 */ // CN zh-CN Chinese (People's Republic of China)
+ 0x240A, /* 20 */ // CO es-CO Spanish (Colombia)
+ 0x140A, /* 21 */ // CR es-CR Spanish (Costa Rica)
+ 0x0405, /* 22 */ // CZ cs-CZ Czech (Czech Republic)
+ 0x0407, /* 23 */ // DE de-DE German (Germany)
+ 0x0406, /* 24 */ // DK da-DK Danish (Denmark)
+ 0x1C0A, /* 25 */ // DO es-DO Spanish (Dominican Republic)
+ 0x1401, /* 26 */ // DZ ar-DZ Arabic (Algeria)
+ 0x300A, /* 27 */ // EC es-EC Spanish (Ecuador)
+ 0x0425, /* 28 */ // EE et-EE Estonian (Estonia)
+ 0x0C01, /* 29 */ // EG ar-EG Arabic (Egypt)
+ 0x0403, /* 30 */ // ES ca-ES Catalan (Catalan)
+ // 0x042D, 30, // ES eu-ES Basque (Basque)
+ // 0x0456, 30, // ES gl-ES Galician (Galician)
+ // 0x0C0A, 30, // ES es-ES Spanish (Spain)
+ 0x040B, /* 31 */ // FI fi-FI Finnish (Finland)
+ // 0x081D, 31, // FI sv-FI Swedish (Finland)
+ 0x0438, /* 32 */ // FO fo-FO Faroese (Faroe Islands)
+ 0x040C, /* 33 */ // FR fr-FR French (France)
+ 0x0809, /* 34 */ // GB en-GB English (United Kingdom)
+ 0x0437, /* 35 */ // GE ka-GE Georgian (Georgia)
+ 0x0408, /* 36 */ // GR el-GR Greek (Greece)
+ 0x100A, /* 37 */ // GT es-GT Spanish (Guatemala)
+ 0x0C04, /* 38 */ // HK zh-HK Chinese (Hong Kong S.A.R.)
+ 0x480A, /* 39 */ // HN es-HN Spanish (Honduras)
+ 0x041A, /* 40 */ // HR hr-HR Croatian (Croatia)
+ 0x040E, /* 41 */ // HU hu-HU Hungarian (Hungary)
+ 0x0421, /* 42 */ // ID id-ID Indonesian (Indonesia)
+ 0x1809, /* 43 */ // IE en-IE English (Ireland)
+ 0x040D, /* 44 */ // IL he-IL Hebrew (Israel)
+ 0x0439, /* 45 */ // IN hi-IN Hindi (India)
+ // 0x0446, 45, // IN pa-IN Punjabi (India)
+ // 0x0447, 45, // IN gu-IN Gujarati (India)
+ // 0x0449, 45, // IN ta-IN Tamil (India)
+ // 0x044A, 45, // IN te-IN Telugu (India)
+ // 0x044B, 45, // IN kn-IN Kannada (India)
+ // 0x044E, 45, // IN mr-IN Marathi (India)
+ // 0x044F, 45, // IN sa-IN Sanskrit (India)
+ // 0x0457, 45, // IN kok-IN Konkani (India)
+ 0x0801, /* 46 */ // IQ ar-IQ Arabic (Iraq)
+ 0x0429, /* 47 */ // IR fa-IR (Iran)
+ 0x040F, /* 48 */ // IS is-IS Icelandic (Iceland)
+ 0x0410, /* 49 */ // IT it-IT Italian (Italy)
+ 0x2009, /* 50 */ // JM en-JM English (Jamaica)
+ 0x2C01, /* 51 */ // JO ar-JO Arabic (Jordan)
+ 0x0411, /* 52 */ // JP ja-JP Japanese (Japan)
+ 0x0441, /* 53 */ // KE sw-KE Swahili (Kenya)
+ 0x0440, /* 54 */ // KG ky-KG Kyrgyz (Kyrgyzstan)
+ 0x0412, /* 55 */ // KR ko-KR Korean (Korea)
+ 0x3401, /* 56 */ // KW ar-KW Arabic (Kuwait)
+ 0x043F, /* 57 */ // KZ kk-KZ Kazakh (Kazakhstan)
+ 0x3001, /* 58 */ // LB ar-LB Arabic (Lebanon)
+ 0x1407, /* 59 */ // LI de-LI German (Liechtenstein)
+ 0x0427, /* 60 */ // LT lt-LT Lithuanian (Lithuania)
+ 0x1007, /* 61 */ // LU de-LU German (Luxembourg)
+ // 0x140C, 61, // LU fr-LU French (Luxembourg)
+ 0x0426, /* 62 */ // LV lv-LV Latvian (Latvia)
+ 0x1001, /* 63 */ // LY ar-LY Arabic (Libya)
+ 0x1801, /* 64 */ // MA ar-MA Arabic (Morocco)
+ 0x180C, /* 65 */ // MC fr-MC French (Principality of Monaco)
+ 0x042F, /* 66 */ // MK mk-MK Macedonian (Macedonia, FYRO)
+ 0x0450, /* 67 */ // MN mn-MN Mongolian (Mongolia)
+ 0x1404, /* 68 */ // MO zh-MO Chinese (Macau S.A.R.)
+ 0x0465, /* 69 */ // MV div-MV Divehi (Maldives)
+ 0x080A, /* 70 */ // MX es-MX Spanish (Mexico)
+ 0x043E, /* 71 */ // MY ms-MY Malay (Malaysia)
+ 0x4C0A, /* 72 */ // NI es-NI Spanish (Nicaragua)
+ 0x0413, /* 73 */ // NL nl-NL Dutch (Netherlands)
+ 0x0414, /* 74 */ // NO nb-NO Norwegian (Bokm?) (Norway)
+ // 0x0814, 74, // NO nn-NO Norwegian (Nynorsk) (Norway)
+ 0x1409, /* 75 */ // NZ en-NZ English (New Zealand)
+ 0x2001, /* 76 */ // OM ar-OM Arabic (Oman)
+ 0x180A, /* 77 */ // PA es-PA Spanish (Panama)
+ 0x280A, /* 78 */ // PE es-PE Spanish (Peru)
+ 0x3409, /* 79 */ // PH en-PH English (Republic of the Philippines)
+ 0x0420, /* 80 */ // PK ur-PK Urdu (Islamic Republic of Pakistan)
+ 0x0415, /* 81 */ // PL pl-PL Polish (Poland)
+ 0x500A, /* 82 */ // PR es-PR Spanish (Puerto Rico)
+ 0x0816, /* 83 */ // PT pt-PT Portuguese (Portugal)
+ 0x3C0A, /* 84 */ // PY es-PY Spanish (Paraguay)
+ 0x4001, /* 85 */ // QA ar-QA Arabic (Qatar)
+ 0x0418, /* 86 */ // RO ro-RO Romanian (Romania)
+ 0x0419, /* 87 */ // RU ru-RU Russian (Russia)
+ // 0x0444, 87, // RU tt-RU Tatar (Russia)
+ 0x0401, /* 88 */ // SA ar-SA Arabic (Saudi Arabia)
+ 0x041D, /* 89 */ // SE sv-SE Swedish (Sweden)
+ 0x1004, /* 90 */ // SG zh-SG Chinese (Singapore)
+ 0x0424, /* 91 */ // SI sl-SI Slovenian (Slovenia)
+ 0x041B, /* 92 */ // SK sk-SK Slovak (Slovakia)
+ 0x081A, /* 93 */ // SP sr-SP-Latn Serbian (Latin) (Serbia)
+ // 0x0C1A, 93, // SP sr-SP-Cyrl Serbian (Cyrillic) (Serbia)
+ 0x440A, /* 94 */ // SV es-SV Spanish (El Salvador)
+ 0x045A, /* 95 */ // SY syr-SY Syriac (Syria)
+ // 0x2801, 95, // SY ar-SY Arabic (Syria)
+ 0x041E, /* 96 */ // TH th-TH Thai (Thailand)
+ 0x1C01, /* 97 */ // TN ar-TN Arabic (Tunisia)
+ 0x041F, /* 98 */ // TR tr-TR Turkish (Turkey)
+ 0x2C09, /* 99 */ // TT en-TT English (Trinidad and Tobago)
+ 0x0404, /*100 */ // TW zh-TW Chinese (Taiwan)
+ 0x0422, /*101 */ // UA uk-UA Ukrainian (Ukraine)
+ 0x0409, /*102 */ // US en-US English (United States)
+ 0x380A, /*103 */ // UY es-UY Spanish (Uruguay)
+ 0x0443, /*104 */ // UZ uz-UZ-Latn Uzbek (Latin) (Uzbekistan)
+ // 0x0843, 104 // UZ uz-UZ-Cyrl Uzbek (Cyrillic) (Uzbekistan)
+ 0x200A, /*105*/ // VE es-VE Spanish (Venezuela)
+ 0x042A, /*106*/ // VN vi-VN Vietnamese (Viet Nam)
+ 0x2401, /*107*/ // YE ar-YE Arabic (Yemen)
+ 0x0436, /*108*/ // ZA af-ZA Afrikaans (South Africa)
+ // 0x1C09, 108, // ZA en-ZA English (South Africa)
+ 0x3009, /*109*/ // ZW en-ZW English (Zimbabwe)
+ };
+#endif
+ [System.Security.SecurityCritical] // auto-generated
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+#if FEATURE_CORECLR
+ // This won't happen anyway since CoreCLR doesn't support serialization
+ this.m_cultureData = CultureData.GetCultureData(m_name, true);
+#else
+ if (m_name == null)
+ {
+ Contract.Assert(m_dataItem >= 0, "[RegionInfo.OnDeserialized] null name and invalid dataItem");
+ m_cultureId = IdFromEverettRegionInfoDataItem[m_dataItem];
+ }
+
+ if (m_cultureId == 0)
+ {
+ this.m_cultureData = CultureData.GetCultureDataForRegion(this.m_name, true);
+ }
+ else
+ {
+ this.m_cultureData = CultureData.GetCultureData(m_cultureId, true);
+ }
+
+#endif
+ if (this.m_cultureData == null)
+ throw new ArgumentException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Argument_InvalidCultureName"), m_name), "m_name");
+
+ if (m_cultureId == 0)
+ {
+ SetName(this.m_name);
+ }
+ else
+ {
+ this.m_name = this.m_cultureData.SREGIONNAME;
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ // Used to fill in everett data item, unnecessary now
+ }
+#endregion Serialization
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetCurrentRegion
+ //
+ // This instance provides methods based on the current user settings.
+ // These settings are volatile and may change over the lifetime of the
+ // thread.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public static RegionInfo CurrentRegion {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ RegionInfo temp = s_currentRegionInfo;
+ if (temp == null)
+ {
+ temp = new RegionInfo(CultureInfo.CurrentCulture.m_cultureData);
+
+ // Need full name for custom cultures
+ temp.m_name=temp.m_cultureData.SREGIONNAME;
+ s_currentRegionInfo = temp;
+ }
+ return temp;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetName
+ //
+ // Returns the name of the region (ie: en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String Name {
+ get {
+ Contract.Assert(m_name != null, "Expected RegionInfo.m_name to be populated already");
+ return (m_name);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetEnglishName
+ //
+ // Returns the name of the region in English. (ie: United States)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String EnglishName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SENGCOUNTRY);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetDisplayName
+ //
+ // Returns the display name (localized) of the region. (ie: United States
+ // if the current UI language is en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String DisplayName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SLOCALIZEDCOUNTRY);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetNativeName
+ //
+ // Returns the native name of the region. (ie: Deutschland)
+ // WARNING: You need a full locale name for this to make sense.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String NativeName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SNATIVECOUNTRY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // TwoLetterISORegionName
+ //
+ // Returns the two letter ISO region name (ie: US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String TwoLetterISORegionName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SISO3166CTRYNAME);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ThreeLetterISORegionName
+ //
+ // Returns the three letter ISO region name (ie: USA)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ThreeLetterISORegionName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SISO3166CTRYNAME2);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ThreeLetterWindowsRegionName
+ //
+ // Returns the three letter windows region name (ie: USA)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ThreeLetterWindowsRegionName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SABBREVCTRYNAME);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsMetric
+ //
+ // Returns true if this region uses the metric measurement system
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual bool IsMetric {
+ get {
+ int value = this.m_cultureData.IMEASURE;
+ return (value==0);
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int GeoId
+ {
+ get
+ {
+ return (this.m_cultureData.IGEOID);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrencyEnglishName
+ //
+ // English name for this region's currency, ie: Swiss Franc
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String CurrencyEnglishName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SENGLISHCURRENCY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrencyEnglishName
+ //
+ // English name for this region's currency, ie: Schweizer Franken
+ // WARNING: You need a full locale name for this to make sense.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual String CurrencyNativeName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (this.m_cultureData.SNATIVECURRENCY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CurrencySymbol
+ //
+ // Currency Symbol for this locale, ie: Fr. or $
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String CurrencySymbol {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return (this.m_cultureData.SCURRENCY);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ISOCurrencySymbol
+ //
+ // ISO Currency Symbol for this locale, ie: CHF
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String ISOCurrencySymbol {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return (this.m_cultureData.SINTLSYMBOL);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same RegionInfo as the current instance.
+ //
+ // RegionInfos are considered equal if and only if they have the same name
+ // (ie: en-US)
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override bool Equals(Object value)
+ {
+ RegionInfo that = value as RegionInfo;
+ if (that != null)
+ {
+ return this.Name.Equals(that.Name);
+ }
+
+ return (false);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for RegionInfo
+ // A and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override int GetHashCode()
+ {
+ return (this.Name.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns the name of the Region, ie: es-US
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override String ToString()
+ {
+ return (Name);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/SortKey.cs b/src/mscorlib/src/System/Globalization/SortKey.cs
new file mode 100644
index 0000000000..e3308dc4f8
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/SortKey.cs
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class implements a set of methods for retrieving
+// sort key information.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public partial class SortKey
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ //
+ // Variables.
+ //
+
+ [OptionalField(VersionAdded = 3)]
+ internal String localeName; // locale identifier
+
+ [OptionalField(VersionAdded = 1)] // LCID field so serialization is Whidbey compatible though we don't officially support it
+ internal int win32LCID;
+ // Whidbey serialization
+
+ internal CompareOptions options; // options
+ internal String m_String; // original string
+ internal byte[] m_KeyData; // sortkey data
+
+ //
+ // The following constructor is designed to be called from CompareInfo to get the
+ // the sort key of specific string for synthetic culture
+ //
+ internal SortKey(String localeName, String str, CompareOptions options, byte[] keyData)
+ {
+ this.m_KeyData = keyData;
+ this.localeName = localeName;
+ this.options = options;
+ this.m_String = str;
+ }
+
+#if FEATURE_USE_LCID
+ [OnSerializing]
+ private void OnSerializing(StreamingContext context)
+ {
+ //set LCID to proper value for Whidbey serialization (no other use)
+ if (win32LCID == 0)
+ {
+ win32LCID = CultureInfo.GetCultureInfo(localeName).LCID;
+ }
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext context)
+ {
+ //set locale name to proper value after Whidbey deserialization
+ if (String.IsNullOrEmpty(localeName) && win32LCID != 0)
+ {
+ localeName = CultureInfo.GetCultureInfo(win32LCID).Name;
+ }
+ }
+#endif //FEATURE_USE_LCID
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetOriginalString
+ //
+ // Returns the original string used to create the current instance
+ // of SortKey.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual String OriginalString
+ {
+ get {
+ return (m_String);
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetKeyData
+ //
+ // Returns a byte array representing the current instance of the
+ // sort key.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public virtual byte[] KeyData
+ {
+ get {
+ return (byte[])(m_KeyData.Clone());
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Compare
+ //
+ // Compares the two sort keys. Returns 0 if the two sort keys are
+ // equal, a number less than 0 if sortkey1 is less than sortkey2,
+ // and a number greater than 0 if sortkey1 is greater than sortkey2.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public static int Compare(SortKey sortkey1, SortKey sortkey2) {
+
+ if (sortkey1==null || sortkey2==null) {
+ throw new ArgumentNullException((sortkey1==null ? "sortkey1": "sortkey2"));
+ }
+ Contract.EndContractBlock();
+
+ byte[] key1Data = sortkey1.m_KeyData;
+ byte[] key2Data = sortkey2.m_KeyData;
+
+ Contract.Assert(key1Data!=null, "key1Data!=null");
+ Contract.Assert(key2Data!=null, "key2Data!=null");
+
+ if (key1Data.Length == 0) {
+ if (key2Data.Length == 0) {
+ return (0);
+ }
+ return (-1);
+ }
+ if (key2Data.Length == 0) {
+ return (1);
+ }
+
+ int compLen = (key1Data.Length<key2Data.Length)?key1Data.Length:key2Data.Length;
+
+ for (int i=0; i<compLen; i++) {
+ if (key1Data[i]>key2Data[i]) {
+ return (1);
+ }
+ if (key1Data[i]<key2Data[i]) {
+ return (-1);
+ }
+ }
+
+ return 0;
+
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same SortKey as the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override bool Equals(Object value)
+ {
+ SortKey that = value as SortKey;
+
+ if (that != null)
+ {
+ return Compare(this, that) == 0;
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // SortKey. The hash code is guaranteed to be the same for
+ // SortKey A and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override int GetHashCode()
+ {
+ return (CompareInfo.GetCompareInfo(
+ this.localeName).GetHashCodeOfString(this.m_String, this.options));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns a string describing the
+ // SortKey.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ public override String ToString()
+ {
+ return ("SortKey - " + localeName + ", " + options + ", " + m_String);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/SortVersion.cs b/src/mscorlib/src/System/Globalization/SortVersion.cs
new file mode 100644
index 0000000000..24fe8546fc
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/SortVersion.cs
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization
+{
+ using System;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public sealed class SortVersion : IEquatable<SortVersion>
+ {
+ private int m_NlsVersion;
+ private Guid m_SortId;
+
+ public int FullVersion
+ {
+ get
+ {
+ return m_NlsVersion;
+ }
+ }
+
+ public Guid SortId
+ {
+ get
+ {
+ return m_SortId;
+ }
+ }
+
+ public SortVersion(int fullVersion, Guid sortId)
+ {
+ m_SortId = sortId;
+ m_NlsVersion = fullVersion;
+ }
+
+ internal SortVersion(int nlsVersion, int effectiveId, Guid customVersion)
+ {
+ m_NlsVersion = nlsVersion;
+
+ if (customVersion == Guid.Empty)
+ {
+ byte[] b = BitConverter.GetBytes(effectiveId);
+ byte b1 = (byte) ((uint) effectiveId >> 24);
+ byte b2 = (byte) ((effectiveId & 0x00FF0000) >> 16);
+ byte b3 = (byte) ((effectiveId & 0x0000FF00) >> 8);
+ byte b4 = (byte) (effectiveId & 0xFF);
+ customVersion = new Guid(0,0,0,0,0,0,0,b1,b2,b3,b4);
+ }
+
+ m_SortId = customVersion;
+ }
+
+ public override bool Equals(object obj)
+ {
+ SortVersion n = obj as SortVersion;
+ if(n != null)
+ {
+ return this.Equals(n);
+ }
+
+ return false;
+ }
+
+ public bool Equals(SortVersion other)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ return m_NlsVersion == other.m_NlsVersion && m_SortId == other.m_SortId;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_NlsVersion * 7 | m_SortId.GetHashCode();
+ }
+
+ public static bool operator ==(SortVersion left, SortVersion right)
+ {
+ if (((object) left) != null)
+ {
+ return left.Equals(right);
+ }
+
+ if (((object) right) != null)
+ {
+ return right.Equals(left);
+ }
+
+ // Both null.
+ return true;
+ }
+
+ public static bool operator !=(SortVersion left, SortVersion right)
+ {
+ return !(left == right);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/Globalization/StringInfo.cs b/src/mscorlib/src/System/Globalization/StringInfo.cs
new file mode 100644
index 0000000000..b1151bde4f
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/StringInfo.cs
@@ -0,0 +1,361 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class defines behaviors specific to a writing system.
+// A writing system is the collection of scripts and
+// orthographic rules required to represent a language as text.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+namespace System.Globalization {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class StringInfo
+ {
+
+ [OptionalField(VersionAdded = 2)]
+ private String m_str;
+
+ // We allow this class to be serialized but there is no conceivable reason
+ // for them to do so. Thus, we do not serialize the instance variables.
+ [NonSerialized] private int[] m_indexes;
+
+ // Legacy constructor
+ public StringInfo() : this(""){}
+
+ // Primary, useful constructor
+ public StringInfo(String value) {
+ this.String = value;
+ }
+
+#region Serialization
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ m_str = String.Empty;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (m_str.Length == 0)
+ {
+ m_indexes = null;
+ }
+ }
+#endregion Serialization
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals(Object value)
+ {
+ StringInfo that = value as StringInfo;
+ if (that != null)
+ {
+ return (this.m_str.Equals(that.m_str));
+ }
+ return (false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ return this.m_str.GetHashCode();
+ }
+
+
+ // Our zero-based array of index values into the string. Initialize if
+ // our private array is not yet, in fact, initialized.
+ private int[] Indexes {
+ get {
+ if((null == this.m_indexes) && (0 < this.String.Length)) {
+ this.m_indexes = StringInfo.ParseCombiningCharacters(this.String);
+ }
+
+ return(this.m_indexes);
+ }
+ }
+
+ public String String {
+ get {
+ return(this.m_str);
+ }
+ set {
+ if (null == value) {
+ throw new ArgumentNullException("String",
+ Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+
+ this.m_str = value;
+ this.m_indexes = null;
+ }
+ }
+
+ public int LengthInTextElements {
+ get {
+ if(null == this.Indexes) {
+ // Indexes not initialized, so assume length zero
+ return(0);
+ }
+
+ return(this.Indexes.Length);
+ }
+ }
+
+ public String SubstringByTextElements(int startingTextElement) {
+ // If the string is empty, no sense going further.
+ if(null == this.Indexes) {
+ // Just decide which error to give depending on the param they gave us....
+ if(startingTextElement < 0) {
+ throw new ArgumentOutOfRangeException("startingTextElement",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ else {
+ throw new ArgumentOutOfRangeException("startingTextElement",
+ Environment.GetResourceString("Arg_ArgumentOutOfRangeException"));
+ }
+ }
+ return (this.SubstringByTextElements(startingTextElement, this.Indexes.Length - startingTextElement));
+ }
+
+ public String SubstringByTextElements(int startingTextElement, int lengthInTextElements) {
+
+ //
+ // Parameter checking
+ //
+ if(startingTextElement < 0) {
+ throw new ArgumentOutOfRangeException("startingTextElement",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+
+ if(this.String.Length == 0 || startingTextElement >= this.Indexes.Length) {
+ throw new ArgumentOutOfRangeException("startingTextElement",
+ Environment.GetResourceString("Arg_ArgumentOutOfRangeException"));
+ }
+
+ if(lengthInTextElements < 0) {
+ throw new ArgumentOutOfRangeException("lengthInTextElements",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+
+ if(startingTextElement > this.Indexes.Length - lengthInTextElements) {
+ throw new ArgumentOutOfRangeException("lengthInTextElements",
+ Environment.GetResourceString("Arg_ArgumentOutOfRangeException"));
+ }
+
+ int start = this.Indexes[startingTextElement];
+
+ if(startingTextElement + lengthInTextElements == this.Indexes.Length) {
+ // We are at the last text element in the string and because of that
+ // must handle the call differently.
+ return(this.String.Substring(start));
+ }
+ else {
+ return(this.String.Substring(start, (this.Indexes[lengthInTextElements + startingTextElement] - start)));
+ }
+ }
+
+ public static String GetNextTextElement(String str)
+ {
+ return (GetNextTextElement(str, 0));
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Get the code point count of the current text element.
+ //
+ // A combining class is defined as:
+ // A character/surrogate that has the following Unicode category:
+ // * NonSpacingMark (e.g. U+0300 COMBINING GRAVE ACCENT)
+ // * SpacingCombiningMark (e.g. U+ 0903 DEVANGARI SIGN VISARGA)
+ // * EnclosingMark (e.g. U+20DD COMBINING ENCLOSING CIRCLE)
+ //
+ // In the context of GetNextTextElement() and ParseCombiningCharacters(), a text element is defined as:
+ //
+ // 1. If a character/surrogate is in the following category, it is a text element.
+ // It can NOT further combine with characters in the combinging class to form a text element.
+ // * one of the Unicode category in the combinging class
+ // * UnicodeCategory.Format
+ // * UnicodeCateogry.Control
+ // * UnicodeCategory.OtherNotAssigned
+ // 2. Otherwise, the character/surrogate can be combined with characters in the combinging class to form a text element.
+ //
+ // Return:
+ // The length of the current text element
+ //
+ // Parameters:
+ // String str
+ // index The starting index
+ // len The total length of str (to define the upper boundary)
+ // ucCurrent The Unicode category pointed by Index. It will be updated to the uc of next character if this is not the last text element.
+ // currentCharCount The char count of an abstract char pointed by Index. It will be updated to the char count of next abstract character if this is not the last text element.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ internal static int GetCurrentTextElementLen(String str, int index, int len, ref UnicodeCategory ucCurrent, ref int currentCharCount)
+ {
+ Contract.Assert(index >= 0 && len >= 0, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
+ Contract.Assert(index < len, "StringInfo.GetCurrentTextElementLen() : index = " + index + ", len = " + len);
+ if (index + currentCharCount == len)
+ {
+ // This is the last character/surrogate in the string.
+ return (currentCharCount);
+ }
+
+ // Call an internal GetUnicodeCategory, which will tell us both the unicode category, and also tell us if it is a surrogate pair or not.
+ int nextCharCount;
+ UnicodeCategory ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index + currentCharCount, out nextCharCount);
+ if (CharUnicodeInfo.IsCombiningCategory(ucNext)) {
+ // The next element is a combining class.
+ // Check if the current text element to see if it is a valid base category (i.e. it should not be a combining category,
+ // not a format character, and not a control character).
+
+ if (CharUnicodeInfo.IsCombiningCategory(ucCurrent)
+ || (ucCurrent == UnicodeCategory.Format)
+ || (ucCurrent == UnicodeCategory.Control)
+ || (ucCurrent == UnicodeCategory.OtherNotAssigned)
+ || (ucCurrent == UnicodeCategory.Surrogate)) // An unpair high surrogate or low surrogate
+ {
+ // Will fall thru and return the currentCharCount
+ } else {
+ int startIndex = index; // Remember the current index.
+
+ // We have a valid base characters, and we have a character (or surrogate) that is combining.
+ // Check if there are more combining characters to follow.
+ // Check if the next character is a nonspacing character.
+ index += currentCharCount + nextCharCount;
+
+ while (index < len)
+ {
+ ucNext = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out nextCharCount);
+ if (!CharUnicodeInfo.IsCombiningCategory(ucNext)) {
+ ucCurrent = ucNext;
+ currentCharCount = nextCharCount;
+ break;
+ }
+ index += nextCharCount;
+ }
+ return (index - startIndex);
+ }
+ }
+ // The return value will be the currentCharCount.
+ int ret = currentCharCount;
+ ucCurrent = ucNext;
+ // Update currentCharCount.
+ currentCharCount = nextCharCount;
+ return (ret);
+ }
+
+ // Returns the str containing the next text element in str starting at
+ // index index. If index is not supplied, then it will start at the beginning
+ // of str. It recognizes a base character plus one or more combining
+ // characters or a properly formed surrogate pair as a text element. See also
+ // the ParseCombiningCharacters() and the ParseSurrogates() methods.
+ public static String GetNextTextElement(String str, int index) {
+ //
+ // Validate parameters.
+ //
+ if (str==null) {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ if (index < 0 || index >= len) {
+ if (index == len) {
+ return (String.Empty);
+ }
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ int charLen;
+ UnicodeCategory uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
+ return (str.Substring(index, GetCurrentTextElementLen(str, index, len, ref uc, ref charLen)));
+ }
+
+ public static TextElementEnumerator GetTextElementEnumerator(String str)
+ {
+ return (GetTextElementEnumerator(str, 0));
+ }
+
+ public static TextElementEnumerator GetTextElementEnumerator(String str, int index)
+ {
+ //
+ // Validate parameters.
+ //
+ if (str==null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ if (index < 0 || (index > len))
+ {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ return (new TextElementEnumerator(str, index, len));
+ }
+
+ /*
+ * Returns the indices of each base character or properly formed surrogate pair
+ * within the str. It recognizes a base character plus one or more combining
+ * characters or a properly formed surrogate pair as a text element and returns
+ * the index of the base character or high surrogate. Each index is the
+ * beginning of a text element within a str. The length of each element is
+ * easily computed as the difference between successive indices. The length of
+ * the array will always be less than or equal to the length of the str. For
+ * example, given the str \u4f00\u302a\ud800\udc00\u4f01, this method would
+ * return the indices: 0, 2, 4.
+ */
+
+ public static int[] ParseCombiningCharacters(String str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ int len = str.Length;
+ int[] result = new int[len];
+ if (len == 0)
+ {
+ return (result);
+ }
+
+ int resultCount = 0;
+
+ int i = 0;
+ int currentCharLen;
+ UnicodeCategory currentCategory = CharUnicodeInfo.InternalGetUnicodeCategory(str, 0, out currentCharLen);
+
+ while (i < len) {
+ result[resultCount++] = i;
+ i += GetCurrentTextElementLen(str, i, len, ref currentCategory, ref currentCharLen);
+ }
+
+ if (resultCount < len)
+ {
+ int[] returnArray = new int[resultCount];
+ Array.Copy(result, returnArray, resultCount);
+ return (returnArray);
+ }
+ return (result);
+
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/Tables/charinfo.nlp b/src/mscorlib/src/System/Globalization/Tables/charinfo.nlp
new file mode 100644
index 0000000000..2d5444f524
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/Tables/charinfo.nlp
Binary files differ
diff --git a/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs
new file mode 100644
index 0000000000..013e2cd50e
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TaiwanCalendar.cs
@@ -0,0 +1,262 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ /* SSS_DROP_BEGIN */ /* SSS_WARNINGS_OFF */
+ /*=================================TaiwanCalendar==========================
+ **
+ ** Taiwan calendar is based on the Gregorian calendar. And the year is an offset to Gregorian calendar.
+ ** That is,
+ ** Taiwan year = Gregorian year - 1911. So 1912/01/01 A.D. is Taiwan 1/01/01
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1912/01/01 9999/12/31
+ ** Taiwan 01/01/01 8088/12/31
+ ============================================================================*/
+ /* SSS_WARNINGS_ON */ /* SSS_DROP_END */
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable] public class TaiwanCalendar: Calendar {
+ //
+ // The era value for the current era.
+ //
+
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // When Gregorian Year 1912 is year 1, so that
+ // 1912 = 1 + yearOffset
+ // So yearOffset = 1911
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911);
+
+ // Initialize our era info.
+ static internal EraInfo[] taiwanEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal static volatile Calendar s_defaultInstance;
+
+ internal GregorianCalendarHelper helper;
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of TaiwanCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+
+ internal static Calendar GetDefaultInstance() {
+ if (s_defaultInstance == null) {
+ s_defaultInstance = new TaiwanCalendar();
+ }
+ return (s_defaultInstance);
+ }
+
+ internal static readonly DateTime calendarMinValue = new DateTime(1912, 1, 1);
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (calendarMinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Taiwan calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+
+ public TaiwanCalendar() {
+ try {
+ new CultureInfo("zh-TW");
+ } catch (ArgumentException e) {
+ throw new TypeInitializationException(this.GetType().FullName, e);
+ }
+ helper = new GregorianCalendarHelper(this, taiwanEraInfo);
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_TAIWAN);
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (helper.AddYears(time, years));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era) {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era) {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time) {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time) {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era) {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 99;
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear)
+ {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ helper.MaxYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+ // For Taiwan calendar, four digit year is not used.
+ // Therefore, for any two digit number, we just return the original number.
+
+ public override int ToFourDigitYear(int year) {
+ if (year <= 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year > helper.MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 1,
+ helper.MaxYear));
+ }
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs b/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs
new file mode 100644
index 0000000000..d96c450f49
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TaiwanLunisolarCalendar.cs
@@ -0,0 +1,330 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about TaiwanLunisolarCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1912/02/18 2051/02/10
+ ** TaiwanLunisolar 1912/01/01 2050/13/29
+ */
+
+ [Serializable]
+ public class TaiwanLunisolarCalendar : EastAsianLunisolarCalendar {
+
+ // Since
+ // Gregorian Year = Era Year + yearOffset
+ // When Gregorian Year 1912 is year 1, so that
+ // 1912 = 1 + yearOffset
+ // So yearOffset = 1911
+ //m_EraInfo[0] = new EraInfo(1, new DateTime(1912, 1, 1).Ticks, 1911, 1, GregorianCalendar.MaxYear - 1911);
+
+ // Initialize our era info.
+ static internal EraInfo[] taiwanLunisolarEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1912, 1, 1, 1911, 1, GregorianCalendar.MaxYear - 1911) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ internal GregorianCalendarHelper helper;
+
+ internal const int MIN_LUNISOLAR_YEAR = 1912;
+ internal const int MAX_LUNISOLAR_YEAR = 2050;
+
+ internal const int MIN_GREGORIAN_YEAR = 1912;
+ internal const int MIN_GREGORIAN_MONTH = 2;
+ internal const int MIN_GREGORIAN_DAY = 18;
+
+ internal const int MAX_GREGORIAN_YEAR = 2051;
+ internal const int MAX_GREGORIAN_MONTH = 2;
+ internal const int MAX_GREGORIAN_DAY = 10;
+
+ internal static DateTime minDate = new DateTime(MIN_GREGORIAN_YEAR, MIN_GREGORIAN_MONTH, MIN_GREGORIAN_DAY);
+ internal static DateTime maxDate = new DateTime((new DateTime(MAX_GREGORIAN_YEAR, MAX_GREGORIAN_MONTH, MAX_GREGORIAN_DAY, 23, 59, 59, 999)).Ticks + 9999);
+
+ public override DateTime MinSupportedDateTime {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+
+ public override DateTime MaxSupportedDateTime {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // 1911 from ChineseLunisolarCalendar
+ return 384;
+ }
+ }
+
+ static readonly int [,] yinfo =
+ {
+/*Y LM Lmon Lday DaysPerMonth D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 D13 #Days
+1912 */{ 0 , 2 , 18 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1913 */{ 0 , 2 , 6 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1914 */{ 5 , 1 , 26 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1915 */{ 0 , 2 , 14 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1916 */{ 0 , 2 , 3 , 54944 },/* 30 30 29 30 29 30 30 29 30 29 30 29 0 355
+1917 */{ 2 , 1 , 23 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1918 */{ 0 , 2 , 11 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1919 */{ 7 , 2 , 1 , 18872 },/* 29 30 29 29 30 29 29 30 30 29 30 30 30 384
+1920 */{ 0 , 2 , 20 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1921 */{ 0 , 2 , 8 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1922 */{ 5 , 1 , 28 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1923 */{ 0 , 2 , 16 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1924 */{ 0 , 2 , 5 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1925 */{ 4 , 1 , 24 , 44456 },/* 30 29 30 29 30 30 29 30 30 29 30 29 30 385
+1926 */{ 0 , 2 , 13 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1927 */{ 0 , 2 , 2 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1928 */{ 2 , 1 , 23 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1929 */{ 0 , 2 , 10 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1930 */{ 6 , 1 , 30 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 29 383
+1931 */{ 0 , 2 , 17 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1932 */{ 0 , 2 , 6 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1933 */{ 5 , 1 , 26 , 27976 },/* 29 30 30 29 30 30 29 30 29 30 29 29 30 384
+1934 */{ 0 , 2 , 14 , 23248 },/* 29 30 29 30 30 29 30 29 30 30 29 30 0 355
+1935 */{ 0 , 2 , 4 , 11104 },/* 29 29 30 29 30 29 30 30 29 30 30 29 0 354
+1936 */{ 3 , 1 , 24 , 37744 },/* 30 29 29 30 29 29 30 30 29 30 30 30 29 384
+1937 */{ 0 , 2 , 11 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+1938 */{ 7 , 1 , 31 , 51560 },/* 30 30 29 29 30 29 29 30 29 30 30 29 30 384
+1939 */{ 0 , 2 , 19 , 51536 },/* 30 30 29 29 30 29 29 30 29 30 29 30 0 354
+1940 */{ 0 , 2 , 8 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+1941 */{ 6 , 1 , 27 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 29 384
+1942 */{ 0 , 2 , 15 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1943 */{ 0 , 2 , 5 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1944 */{ 4 , 1 , 25 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+1945 */{ 0 , 2 , 13 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+1946 */{ 0 , 2 , 2 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+1947 */{ 2 , 1 , 22 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+1948 */{ 0 , 2 , 10 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+1949 */{ 7 , 1 , 29 , 46248 },/* 30 29 30 30 29 30 29 29 30 29 30 29 30 384
+1950 */{ 0 , 2 , 17 , 27808 },/* 29 30 30 29 30 30 29 29 30 29 30 29 0 354
+1951 */{ 0 , 2 , 6 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 0 355
+1952 */{ 5 , 1 , 27 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+1953 */{ 0 , 2 , 14 , 19872 },/* 29 30 29 29 30 30 29 30 30 29 30 29 0 354
+1954 */{ 0 , 2 , 3 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+1955 */{ 3 , 1 , 24 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+1956 */{ 0 , 2 , 12 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+1957 */{ 8 , 1 , 31 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 29 383
+1958 */{ 0 , 2 , 18 , 59728 },/* 30 30 30 29 30 29 29 30 29 30 29 30 0 355
+1959 */{ 0 , 2 , 8 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+1960 */{ 6 , 1 , 28 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 29 384
+1961 */{ 0 , 2 , 15 , 43856 },/* 30 29 30 29 30 29 30 30 29 30 29 30 0 355
+1962 */{ 0 , 2 , 5 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+1963 */{ 4 , 1 , 25 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+1964 */{ 0 , 2 , 13 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 0 355
+1965 */{ 0 , 2 , 2 , 21088 },/* 29 30 29 30 29 29 30 29 29 30 30 29 0 353
+1966 */{ 3 , 1 , 21 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+1967 */{ 0 , 2 , 9 , 55632 },/* 30 30 29 30 30 29 29 30 29 30 29 30 0 355
+1968 */{ 7 , 1 , 30 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+1969 */{ 0 , 2 , 17 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+1970 */{ 0 , 2 , 6 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+1971 */{ 5 , 1 , 27 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+1972 */{ 0 , 2 , 15 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+1973 */{ 0 , 2 , 3 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+1974 */{ 4 , 1 , 23 , 53864 },/* 30 30 29 30 29 29 30 29 29 30 30 29 30 384
+1975 */{ 0 , 2 , 11 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+1976 */{ 8 , 1 , 31 , 54568 },/* 30 30 29 30 29 30 29 30 29 29 30 29 30 384
+1977 */{ 0 , 2 , 18 , 46400 },/* 30 29 30 30 29 30 29 30 29 30 29 29 0 354
+1978 */{ 0 , 2 , 7 , 46752 },/* 30 29 30 30 29 30 30 29 30 29 30 29 0 355
+1979 */{ 6 , 1 , 28 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 29 384
+1980 */{ 0 , 2 , 16 , 38320 },/* 30 29 29 30 29 30 29 30 30 29 30 30 0 355
+1981 */{ 0 , 2 , 5 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+1982 */{ 4 , 1 , 25 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+1983 */{ 0 , 2 , 13 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+1984 */{ 10 , 2 , 2 , 45656 },/* 30 29 30 30 29 29 30 29 29 30 29 30 30 384
+1985 */{ 0 , 2 , 20 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 0 354
+1986 */{ 0 , 2 , 9 , 27968 },/* 29 30 30 29 30 30 29 30 29 30 29 29 0 354
+1987 */{ 6 , 1 , 29 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 29 384
+1988 */{ 0 , 2 , 17 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1989 */{ 0 , 2 , 6 , 38256 },/* 30 29 29 30 29 30 29 30 29 30 30 30 0 355
+1990 */{ 5 , 1 , 27 , 18808 },/* 29 30 29 29 30 29 29 30 29 30 30 30 30 384
+1991 */{ 0 , 2 , 15 , 18800 },/* 29 30 29 29 30 29 29 30 29 30 30 30 0 354
+1992 */{ 0 , 2 , 4 , 25776 },/* 29 30 30 29 29 30 29 29 30 29 30 30 0 354
+1993 */{ 3 , 1 , 23 , 27216 },/* 29 30 30 29 30 29 30 29 29 30 29 30 29 383
+1994 */{ 0 , 2 , 10 , 59984 },/* 30 30 30 29 30 29 30 29 29 30 29 30 0 355
+1995 */{ 8 , 1 , 31 , 27432 },/* 29 30 30 29 30 29 30 30 29 29 30 29 30 384
+1996 */{ 0 , 2 , 19 , 23232 },/* 29 30 29 30 30 29 30 29 30 30 29 29 0 354
+1997 */{ 0 , 2 , 7 , 43872 },/* 30 29 30 29 30 29 30 30 29 30 30 29 0 355
+1998 */{ 5 , 1 , 28 , 37736 },/* 30 29 29 30 29 29 30 30 29 30 30 29 30 384
+1999 */{ 0 , 2 , 16 , 37600 },/* 30 29 29 30 29 29 30 29 30 30 30 29 0 354
+2000 */{ 0 , 2 , 5 , 51552 },/* 30 30 29 29 30 29 29 30 29 30 30 29 0 354
+2001 */{ 4 , 1 , 24 , 54440 },/* 30 30 29 30 29 30 29 29 30 29 30 29 30 384
+2002 */{ 0 , 2 , 12 , 54432 },/* 30 30 29 30 29 30 29 29 30 29 30 29 0 354
+2003 */{ 0 , 2 , 1 , 55888 },/* 30 30 29 30 30 29 30 29 29 30 29 30 0 355
+2004 */{ 2 , 1 , 22 , 23208 },/* 29 30 29 30 30 29 30 29 30 29 30 29 30 384
+2005 */{ 0 , 2 , 9 , 22176 },/* 29 30 29 30 29 30 30 29 30 29 30 29 0 354
+2006 */{ 7 , 1 , 29 , 43736 },/* 30 29 30 29 30 29 30 29 30 30 29 30 30 385
+2007 */{ 0 , 2 , 18 , 9680 },/* 29 29 30 29 29 30 29 30 30 30 29 30 0 354
+2008 */{ 0 , 2 , 7 , 37584 },/* 30 29 29 30 29 29 30 29 30 30 29 30 0 354
+2009 */{ 5 , 1 , 26 , 51544 },/* 30 30 29 29 30 29 29 30 29 30 29 30 30 384
+2010 */{ 0 , 2 , 14 , 43344 },/* 30 29 30 29 30 29 29 30 29 30 29 30 0 354
+2011 */{ 0 , 2 , 3 , 46240 },/* 30 29 30 30 29 30 29 29 30 29 30 29 0 354
+2012 */{ 4 , 1 , 23 , 46416 },/* 30 29 30 30 29 30 29 30 29 30 29 30 29 384
+2013 */{ 0 , 2 , 10 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2014 */{ 9 , 1 , 31 , 21928 },/* 29 30 29 30 29 30 29 30 30 29 30 29 30 384
+2015 */{ 0 , 2 , 19 , 19360 },/* 29 30 29 29 30 29 30 30 30 29 30 29 0 354
+2016 */{ 0 , 2 , 8 , 42416 },/* 30 29 30 29 29 30 29 30 30 29 30 30 0 355
+2017 */{ 6 , 1 , 28 , 21176 },/* 29 30 29 30 29 29 30 29 30 29 30 30 30 384
+2018 */{ 0 , 2 , 16 , 21168 },/* 29 30 29 30 29 29 30 29 30 29 30 30 0 354
+2019 */{ 0 , 2 , 5 , 43312 },/* 30 29 30 29 30 29 29 30 29 29 30 30 0 354
+2020 */{ 4 , 1 , 25 , 29864 },/* 29 30 30 30 29 30 29 29 30 29 30 29 30 384
+2021 */{ 0 , 2 , 12 , 27296 },/* 29 30 30 29 30 29 30 29 30 29 30 29 0 354
+2022 */{ 0 , 2 , 1 , 44368 },/* 30 29 30 29 30 30 29 30 29 30 29 30 0 355
+2023 */{ 2 , 1 , 22 , 19880 },/* 29 30 29 29 30 30 29 30 30 29 30 29 30 384
+2024 */{ 0 , 2 , 10 , 19296 },/* 29 30 29 29 30 29 30 30 29 30 30 29 0 354
+2025 */{ 6 , 1 , 29 , 42352 },/* 30 29 30 29 29 30 29 30 29 30 30 30 29 384
+2026 */{ 0 , 2 , 17 , 42208 },/* 30 29 30 29 29 30 29 29 30 30 30 29 0 354
+2027 */{ 0 , 2 , 6 , 53856 },/* 30 30 29 30 29 29 30 29 29 30 30 29 0 354
+2028 */{ 5 , 1 , 26 , 59696 },/* 30 30 30 29 30 29 29 30 29 29 30 30 29 384
+2029 */{ 0 , 2 , 13 , 54576 },/* 30 30 29 30 29 30 29 30 29 29 30 30 0 355
+2030 */{ 0 , 2 , 3 , 23200 },/* 29 30 29 30 30 29 30 29 30 29 30 29 0 354
+2031 */{ 3 , 1 , 23 , 27472 },/* 29 30 30 29 30 29 30 30 29 30 29 30 29 384
+2032 */{ 0 , 2 , 11 , 38608 },/* 30 29 29 30 29 30 30 29 30 30 29 30 0 355
+2033 */{ 11 , 1 , 31 , 19176 },/* 29 30 29 29 30 29 30 29 30 30 30 29 30 384
+2034 */{ 0 , 2 , 19 , 19152 },/* 29 30 29 29 30 29 30 29 30 30 29 30 0 354
+2035 */{ 0 , 2 , 8 , 42192 },/* 30 29 30 29 29 30 29 29 30 30 29 30 0 354
+2036 */{ 6 , 1 , 28 , 53848 },/* 30 30 29 30 29 29 30 29 29 30 29 30 30 384
+2037 */{ 0 , 2 , 15 , 53840 },/* 30 30 29 30 29 29 30 29 29 30 29 30 0 354
+2038 */{ 0 , 2 , 4 , 54560 },/* 30 30 29 30 29 30 29 30 29 29 30 29 0 354
+2039 */{ 5 , 1 , 24 , 55968 },/* 30 30 29 30 30 29 30 29 30 29 30 29 29 384
+2040 */{ 0 , 2 , 12 , 46496 },/* 30 29 30 30 29 30 29 30 30 29 30 29 0 355
+2041 */{ 0 , 2 , 1 , 22224 },/* 29 30 29 30 29 30 30 29 30 30 29 30 0 355
+2042 */{ 2 , 1 , 22 , 19160 },/* 29 30 29 29 30 29 30 29 30 30 29 30 30 384
+2043 */{ 0 , 2 , 10 , 18864 },/* 29 30 29 29 30 29 29 30 30 29 30 30 0 354
+2044 */{ 7 , 1 , 30 , 42168 },/* 30 29 30 29 29 30 29 29 30 29 30 30 30 384
+2045 */{ 0 , 2 , 17 , 42160 },/* 30 29 30 29 29 30 29 29 30 29 30 30 0 354
+2046 */{ 0 , 2 , 6 , 43600 },/* 30 29 30 29 30 29 30 29 29 30 29 30 0 354
+2047 */{ 5 , 1 , 26 , 46376 },/* 30 29 30 30 29 30 29 30 29 29 30 29 30 384
+2048 */{ 0 , 2 , 14 , 27936 },/* 29 30 30 29 30 30 29 30 29 29 30 29 0 354
+2049 */{ 0 , 2 , 2 , 44448 },/* 30 29 30 29 30 30 29 30 30 29 30 29 0 355
+2050 */{ 3 , 1 , 23 , 21936 },/* 29 30 29 30 29 30 29 30 30 29 30 30 29 384
+ */};
+
+
+ internal override int MinCalendarYear {
+ get
+ {
+ return (MIN_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override int MaxCalendarYear {
+ get
+ {
+ return (MAX_LUNISOLAR_YEAR);
+ }
+ }
+
+ internal override DateTime MinDate {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+ internal override DateTime MaxDate {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+ internal override EraInfo[] CalEraInfo {
+ get
+ {
+ return (taiwanLunisolarEraInfo);
+ }
+ }
+
+ internal override int GetYearInfo(int LunarYear, int Index) {
+ if ((LunarYear < MIN_LUNISOLAR_YEAR) || (LunarYear > MAX_LUNISOLAR_YEAR)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MIN_LUNISOLAR_YEAR,
+ MAX_LUNISOLAR_YEAR ));
+ }
+ Contract.EndContractBlock();
+
+ return yinfo[LunarYear - MIN_LUNISOLAR_YEAR, Index];
+ }
+
+ internal override int GetYear(int year, DateTime time) {
+ return helper.GetYear(year, time);
+ }
+
+ internal override int GetGregorianYear(int year, int era) {
+ return helper.GetGregorianYear(year, era);
+ }
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of TaiwanLunisolarCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance()
+ {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new TaiwanLunisolarCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+ // Construct an instance of TaiwanLunisolar calendar.
+
+ public TaiwanLunisolarCalendar() {
+ helper = new GregorianCalendarHelper(this, taiwanLunisolarEraInfo);
+ }
+
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+ internal override int BaseCalendarID {
+ get {
+ return (CAL_TAIWAN);
+ }
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_TAIWANLUNISOLAR);
+ }
+ }
+
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs
new file mode 100644
index 0000000000..5f47f5fbd4
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TextElementEnumerator.cs
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose:
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System.Runtime.Serialization;
+
+
+namespace System.Globalization {
+ using System.Collections;
+ using System.Diagnostics.Contracts;
+
+ //
+ // This is public because GetTextElement() is public.
+ //
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class TextElementEnumerator: IEnumerator
+ {
+ private String str;
+ private int index;
+ private int startIndex;
+
+ [NonSerialized]
+ private int strLen; // This is the length of the total string, counting from the beginning of string.
+
+ [NonSerialized]
+ private int currTextElementLen; // The current text element lenght after MoveNext() is called.
+
+ [OptionalField(VersionAdded = 2)]
+ private UnicodeCategory uc;
+
+ [OptionalField(VersionAdded = 2)]
+ private int charLen; // The next abstract char to look at after MoveNext() is called. It could be 1 or 2, depending on if it is a surrogate or not.
+
+ internal TextElementEnumerator(String str, int startIndex, int strLen)
+ {
+ Contract.Assert(str != null, "TextElementEnumerator(): str != null");
+ Contract.Assert(startIndex >= 0 && strLen >= 0, "TextElementEnumerator(): startIndex >= 0 && strLen >= 0");
+ Contract.Assert(strLen >= startIndex, "TextElementEnumerator(): strLen >= startIndex");
+ this.str = str;
+ this.startIndex = startIndex;
+ this.strLen = strLen;
+ Reset();
+ }
+
+#region Serialization
+ // the following fields is defined to keep the compatibility with Everett.
+ // don't change/remove the names/types of these fields.
+ private int endIndex;
+ private int nextTextElementLen;
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ charLen = -1;
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ strLen = endIndex + 1;
+ currTextElementLen = nextTextElementLen;
+
+ if (charLen == -1)
+ {
+ uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ endIndex = strLen - 1;
+ nextTextElementLen = currTextElementLen;
+ }
+
+#endregion Serialization
+
+
+
+ public bool MoveNext()
+ {
+ if (index >= strLen)
+ {
+ // Make the index to be greater than strLen so that we can throw exception if GetTextElement() is called.
+ index = strLen + 1;
+ return (false);
+ }
+ currTextElementLen = StringInfo.GetCurrentTextElementLen(str, index, strLen, ref uc, ref charLen);
+ index += currTextElementLen;
+ return (true);
+ }
+
+ //
+ // Get the current text element.
+ //
+
+ public Object Current {
+ get {
+ return (GetTextElement());
+ }
+ }
+
+ //
+ // Get the current text element.
+ //
+
+ public String GetTextElement()
+ {
+ if (index == startIndex) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
+ }
+ if (index > strLen) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumEnded"));
+ }
+
+ return (str.Substring(index - currTextElementLen, currTextElementLen));
+ }
+
+ //
+ // Get the starting index of the current text element.
+ //
+
+ public int ElementIndex
+ {
+ get
+ {
+ if (index == startIndex)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
+ }
+ return (index - currTextElementLen);
+ }
+ }
+
+
+ public void Reset()
+ {
+ index = startIndex;
+ if (index < strLen) {
+ // If we have more than 1 character, get the category of the current char.
+ uc = CharUnicodeInfo.InternalGetUnicodeCategory(str, index, out charLen);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/TextInfo.cs b/src/mscorlib/src/System/Globalization/TextInfo.cs
new file mode 100644
index 0000000000..9b84486f4e
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TextInfo.cs
@@ -0,0 +1,1004 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This Class defines behaviors specific to a writing system.
+// A writing system is the collection of scripts and
+// orthographic rules required to represent a language as text.
+//
+//
+////////////////////////////////////////////////////////////////////////////
+
+using System.Security;
+
+namespace System.Globalization {
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public partial class TextInfo : ICloneable, IDeserializationCallback
+ {
+ //--------------------------------------------------------------------//
+ // Internal Information //
+ //--------------------------------------------------------------------//
+
+ private enum Tristate : byte
+ {
+ NotInitialized,
+ True,
+ False,
+ }
+
+ //
+ // Variables.
+ //
+
+ [OptionalField(VersionAdded = 2)]
+ private String m_listSeparator;
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_isReadOnly = false;
+
+ //
+ // In Whidbey we had several names:
+ // m_win32LangID is the name of the culture, but only used for (de)serialization.
+ // customCultureName is the name of the creating custom culture (if custom) In combination with m_win32LangID
+ // this is authoratative, ie when deserializing.
+ // m_cultureTableRecord was the data record of the creating culture. (could have different name if custom)
+ // m_textInfoID is the LCID of the textinfo itself (no longer used)
+ // m_name is the culture name (from cultureinfo.name)
+ //
+ // In Silverlight/Arrowhead this is slightly different:
+ // m_cultureName is the name of the creating culture. Note that we consider this authoratative,
+ // if the culture's textinfo changes when deserializing, then behavior may change.
+ // (ala Whidbey behavior). This is the only string Arrowhead needs to serialize.
+ // m_cultureData is the data that backs this class.
+ // m_textInfoName is the actual name of the textInfo (from cultureData.STEXTINFO)
+ // m_textInfoName can be the same as m_cultureName on Silverlight since the OS knows
+ // how to do the sorting. However in the desktop, when we call the sorting dll, it doesn't
+ // know how to resolve custom locle names to sort ids so we have to have alredy resolved this.
+ //
+
+ [OptionalField(VersionAdded = 3)]
+ private String m_cultureName; // Name of the culture that created this text info
+ [NonSerialized]private CultureData m_cultureData; // Data record for the culture that made us, not for this textinfo
+ [NonSerialized]private String m_textInfoName; // Name of the text info we're using (ie: m_cultureData.STEXTINFO)
+ [NonSerialized]private IntPtr m_dataHandle; // Sort handle
+ [NonSerialized]private IntPtr m_handleOrigin;
+ [NonSerialized]private Tristate m_IsAsciiCasingSameAsInvariant = Tristate.NotInitialized;
+
+
+ // Invariant text info
+ internal static TextInfo Invariant
+ {
+ get
+ {
+ if (s_Invariant == null)
+ s_Invariant = new TextInfo(CultureData.Invariant);
+ return s_Invariant;
+ }
+ }
+ internal volatile static TextInfo s_Invariant;
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // TextInfo Constructors
+ //
+ // Implements CultureInfo.TextInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ internal TextInfo(CultureData cultureData)
+ {
+ // This is our primary data source, we don't need most of the rest of this
+ this.m_cultureData = cultureData;
+ this.m_cultureName = this.m_cultureData.CultureName;
+ this.m_textInfoName = this.m_cultureData.STEXTINFO;
+#if !FEATURE_CORECLR
+ IntPtr handleOrigin;
+ this.m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out handleOrigin);
+ this.m_handleOrigin = handleOrigin;
+#endif
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Serialization / Deserialization
+ //
+ // Note that we have to respect the Whidbey behavior for serialization compatibility
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+#region Serialization
+ // the following fields are defined to keep the compatibility with Whidbey.
+ // don't change/remove the names/types of these fields.
+ [OptionalField(VersionAdded = 2)]
+ private string customCultureName;
+
+ // the following fields are defined to keep compatibility with Everett.
+ // don't change/remove the names/types of these fields.
+ [OptionalField(VersionAdded = 1)]
+ internal int m_nDataItem;
+ [OptionalField(VersionAdded = 1)]
+ internal bool m_useUserOverride;
+ [OptionalField(VersionAdded = 1)]
+ internal int m_win32LangID;
+
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ // Clear these so we can check if we've fixed them yet
+ this.m_cultureData = null;
+ this.m_cultureName = null;
+ }
+
+ private void OnDeserialized()
+ {
+ // this method will be called twice because of the support of IDeserializationCallback
+ if (this.m_cultureData == null)
+ {
+ if (this.m_cultureName == null)
+ {
+ // This is whidbey data, get it from customCultureName/win32langid
+ if (this.customCultureName != null)
+ {
+ // They gave a custom cultuer name, so use that
+ this.m_cultureName = this.customCultureName;
+ }
+#if FEATURE_USE_LCID
+ else
+ {
+ if (m_win32LangID == 0)
+ {
+ // m_cultureName and m_win32LangID are nulls which means we got uninitialized textinfo serialization stream.
+ // To be compatible with v2/3/3.5 we need to return ar-SA TextInfo in this case.
+ m_cultureName = "ar-SA";
+ }
+ else
+ {
+ // No custom culture, use the name from the LCID
+ m_cultureName = CultureInfo.GetCultureInfo(m_win32LangID).m_cultureData.CultureName;
+ }
+ }
+#endif
+ }
+
+ // Get the text info name belonging to that culture
+ this.m_cultureData = CultureInfo.GetCultureInfo(m_cultureName).m_cultureData;
+ this.m_textInfoName = this.m_cultureData.STEXTINFO;
+#if !FEATURE_CORECLR
+ IntPtr handleOrigin;
+ this.m_dataHandle = CompareInfo.InternalInitSortHandle(m_textInfoName, out handleOrigin);
+ this.m_handleOrigin = handleOrigin;
+#endif
+ }
+ }
+
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserialized();
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+#if !FEATURE_CORECLR
+ // Initialize the fields Whidbey expects:
+ // Whidbey expected this, so set it, but the value doesn't matter much
+ this.m_useUserOverride = false;
+#endif // FEATURE_CORECLR
+
+ // Relabel our name since Whidbey expects it to be called customCultureName
+ this.customCultureName = this.m_cultureName;
+
+#if FEATURE_USE_LCID
+ // Ignore the m_win32LangId because whidbey'll just get it by name if we make it the LOCALE_CUSTOM_UNSPECIFIED.
+ this.m_win32LangID = (CultureInfo.GetCultureInfo(m_cultureName)).LCID;
+#endif
+ }
+
+#endregion Serialization
+
+ //
+ // Internal ordinal comparison functions
+ //
+ internal static int GetHashCodeOrdinalIgnoreCase(String s)
+ {
+ return GetHashCodeOrdinalIgnoreCase(s, false, 0);
+ }
+
+ internal static int GetHashCodeOrdinalIgnoreCase(String s, bool forceRandomizedHashing, long additionalEntropy)
+ {
+ // This is the same as an case insensitive hash for Invariant
+ // (not necessarily true for sorting, but OK for casing & then we apply normal hash code rules)
+ return (Invariant.GetCaseInsensitiveHashCode(s, forceRandomizedHashing, additionalEntropy));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static unsafe bool TryFastFindStringOrdinalIgnoreCase(int searchFlags, String source, int startIndex, String value, int count, ref int foundIndex)
+ {
+ return InternalTryFindStringOrdinalIgnoreCase(searchFlags, source, count, startIndex, value, value.Length, ref foundIndex);
+ }
+
+ // This function doesn't check arguments. Please do check in the caller.
+ // The underlying unmanaged code will assert the sanity of arguments.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static unsafe int CompareOrdinalIgnoreCase(String str1, String str2)
+ {
+ // Compare the whole string and ignore case.
+ return InternalCompareStringOrdinalIgnoreCase(str1, 0, str2, 0, str1.Length, str2.Length);
+ }
+
+ // This function doesn't check arguments. Please do check in the caller.
+ // The underlying unmanaged code will assert the sanity of arguments.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static unsafe int CompareOrdinalIgnoreCaseEx(String strA, int indexA, String strB, int indexB, int lengthA, int lengthB )
+ {
+ Contract.Assert(strA.Length >= indexA + lengthA, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strA.Length >= indexA + lengthA");
+ Contract.Assert(strB.Length >= indexB + lengthB, "[TextInfo.CompareOrdinalIgnoreCaseEx] Caller should've validated strB.Length >= indexB + lengthB");
+ return InternalCompareStringOrdinalIgnoreCase(strA, indexA, strB, indexB, lengthA, lengthB);
+ }
+
+ internal static int IndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
+ {
+ Contract.Assert(source != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated source != null");
+ Contract.Assert(value != null, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated value != null");
+ Contract.Assert(startIndex + count <= source.Length, "[TextInfo.IndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex + count <= source.Length");
+
+ // We return 0 if both inputs are empty strings
+ if (source.Length == 0 && value.Length == 0)
+ {
+ return 0;
+ }
+
+ // fast path
+ int ret = -1;
+ if (TryFastFindStringOrdinalIgnoreCase(Microsoft.Win32.Win32Native.FIND_FROMSTART, source, startIndex, value, count, ref ret))
+ return ret;
+
+ // the search space within [source] starts at offset [startIndex] inclusive and includes
+ // [count] characters (thus the last included character is at index [startIndex + count -1]
+ // [end] is the index of the next character after the search space
+ // (it points past the end of the search space)
+ int end = startIndex + count;
+
+ // maxStartIndex is the index beyond which we never *start* searching, inclusive; in other words;
+ // a search could include characters beyond maxStartIndex, but we'd never begin a search at an
+ // index strictly greater than maxStartIndex.
+ int maxStartIndex = end - value.Length;
+
+ for (; startIndex <= maxStartIndex; startIndex++)
+ {
+ // We should always have the same or more characters left to search than our actual pattern
+ Contract.Assert(end - startIndex >= value.Length);
+ // since this is an ordinal comparison, we can assume that the lengths must match
+ if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0)
+ {
+ return startIndex;
+ }
+ }
+
+ // Not found
+ return -1;
+ }
+
+ internal static int LastIndexOfStringOrdinalIgnoreCase(String source, String value, int startIndex, int count)
+ {
+ Contract.Assert(source != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated source != null");
+ Contract.Assert(value != null, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated value != null");
+ Contract.Assert(startIndex - count+1 >= 0, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex - count+1 >= 0");
+ Contract.Assert(startIndex <= source.Length, "[TextInfo.LastIndexOfStringOrdinalIgnoreCase] Caller should've validated startIndex <= source.Length");
+
+ // If value is Empty, the return value is startIndex
+ if (value.Length == 0)
+ {
+ return startIndex;
+ }
+
+ // fast path
+ int ret = -1;
+ if (TryFastFindStringOrdinalIgnoreCase(Microsoft.Win32.Win32Native.FIND_FROMEND, source, startIndex, value, count, ref ret))
+ return ret;
+
+ // the search space within [source] ends at offset [startIndex] inclusive
+ // and includes [count] characters
+ // minIndex is the first included character and is at index [startIndex - count + 1]
+ int minIndex = startIndex - count + 1;
+
+ // First place we can find it is start index - (value.length -1)
+ if (value.Length > 0)
+ {
+ startIndex -= (value.Length - 1);
+ }
+
+ for (; startIndex >= minIndex; startIndex--)
+ {
+ if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0)
+ {
+ return startIndex;
+ }
+ }
+
+ // Not found
+ return -1;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CodePage
+ //
+ // Returns the number of the code page used by this writing system.
+ // The type parameter can be any of the following values:
+ // ANSICodePage
+ // OEMCodePage
+ // MACCodePage
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public virtual int ANSICodePage
+ {
+ get
+ {
+ return (this.m_cultureData.IDEFAULTANSICODEPAGE);
+ }
+ }
+
+
+ public virtual int OEMCodePage
+ {
+ get
+ {
+ return (this.m_cultureData.IDEFAULTOEMCODEPAGE);
+ }
+ }
+
+
+ public virtual int MacCodePage
+ {
+ get
+ {
+ return (this.m_cultureData.IDEFAULTMACCODEPAGE);
+ }
+ }
+
+
+ public virtual int EBCDICCodePage
+ {
+ get
+ {
+ return (this.m_cultureData.IDEFAULTEBCDICCODEPAGE);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // LCID
+ //
+ // We need a way to get an LCID from outside of the BCL. This prop is the way.
+ // NOTE: neutral cultures will cause GPS incorrect LCIDS from this
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+#if FEATURE_USE_LCID
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public int LCID
+ {
+ get
+ {
+ // Just use the LCID from our text info name
+ return CultureInfo.GetCultureInfo(this.m_textInfoName).LCID;
+ }
+ }
+#endif
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // CultureName
+ //
+ // The name of the culture associated with the current TextInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public string CultureName
+ {
+ get
+ {
+ return(this.m_textInfoName);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // IsReadOnly
+ //
+ // Detect if the object is readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsReadOnly
+ {
+ get { return (m_isReadOnly); }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Clone
+ //
+ // Is the implementation of ICloneable.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual Object Clone()
+ {
+ object o = MemberwiseClone();
+ ((TextInfo) o).SetReadOnlyState(false);
+ return (o);
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ReadOnly
+ //
+ // Create a cloned readonly instance or return the input one if it is
+ // readonly.
+ //
+ ////////////////////////////////////////////////////////////////////////
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static TextInfo ReadOnly(TextInfo textInfo)
+ {
+ if (textInfo == null) { throw new ArgumentNullException("textInfo"); }
+ Contract.EndContractBlock();
+ if (textInfo.IsReadOnly) { return (textInfo); }
+
+ TextInfo clonedTextInfo = (TextInfo)(textInfo.MemberwiseClone());
+ clonedTextInfo.SetReadOnlyState(true);
+
+ return (clonedTextInfo);
+ }
+
+ private void VerifyWritable()
+ {
+ if (m_isReadOnly)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ internal void SetReadOnlyState(bool readOnly)
+ {
+ m_isReadOnly = readOnly;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ListSeparator
+ //
+ // Returns the string used to separate items in a list.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public virtual String ListSeparator
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_listSeparator == null) {
+ m_listSeparator = this.m_cultureData.SLIST;
+ }
+ return (m_listSeparator);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ set
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value", Environment.GetResourceString("ArgumentNull_String"));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ m_listSeparator = value;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToLower
+ //
+ // Converts the character or string to lower case. Certain locales
+ // have different casing semantics from the file systems in Win32.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual char ToLower(char c)
+ {
+ if(IsAscii(c) && IsAsciiCasingSameAsInvariant)
+ {
+ return ToLowerAsciiInvariant(c);
+ }
+ return (InternalChangeCaseChar(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, c, false));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual String ToLower(String str)
+ {
+ if (str == null) { throw new ArgumentNullException("str"); }
+ Contract.EndContractBlock();
+
+ return InternalChangeCaseString(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, str, false);
+
+ }
+
+ static private Char ToLowerAsciiInvariant(Char c)
+ {
+ if ('A' <= c && c <= 'Z')
+ {
+ c = (Char)(c | 0x20);
+ }
+ return c;
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToUpper
+ //
+ // Converts the character or string to upper case. Certain locales
+ // have different casing semantics from the file systems in Win32.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual char ToUpper(char c)
+ {
+ if (IsAscii(c) && IsAsciiCasingSameAsInvariant)
+ {
+ return ToUpperAsciiInvariant(c);
+ }
+ return (InternalChangeCaseChar(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, c, true));
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual String ToUpper(String str)
+ {
+ if (str == null) { throw new ArgumentNullException("str"); }
+ Contract.EndContractBlock();
+ return InternalChangeCaseString(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, str, true);
+ }
+
+ static private Char ToUpperAsciiInvariant(Char c)
+ {
+ if ('a' <= c && c <= 'z')
+ {
+ c = (Char)(c & ~0x20);
+ }
+ return c;
+ }
+
+ static private bool IsAscii(Char c)
+ {
+ return c < 0x80;
+ }
+
+ private bool IsAsciiCasingSameAsInvariant
+ {
+ get
+ {
+ if (m_IsAsciiCasingSameAsInvariant == Tristate.NotInitialized)
+ {
+ m_IsAsciiCasingSameAsInvariant =
+ CultureInfo.GetCultureInfo(m_textInfoName).CompareInfo.Compare("abcdefghijklmnopqrstuvwxyz",
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ CompareOptions.IgnoreCase) == 0 ? Tristate.True : Tristate.False;
+ }
+ return m_IsAsciiCasingSameAsInvariant == Tristate.True;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // Equals
+ //
+ // Implements Object.Equals(). Returns a boolean indicating whether
+ // or not object refers to the same CultureInfo as the current instance.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override bool Equals(Object obj)
+ {
+ TextInfo that = obj as TextInfo;
+
+ if (that != null)
+ {
+ return this.CultureName.Equals(that.CultureName);
+ }
+
+ return (false);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // GetHashCode
+ //
+ // Implements Object.GetHashCode(). Returns the hash code for the
+ // CultureInfo. The hash code is guaranteed to be the same for CultureInfo A
+ // and B where A.Equals(B) is true.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override int GetHashCode()
+ {
+ return (this.CultureName.GetHashCode());
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////
+ //
+ // ToString
+ //
+ // Implements Object.ToString(). Returns a string describing the
+ // TextInfo.
+ //
+ ////////////////////////////////////////////////////////////////////////
+
+
+ public override String ToString()
+ {
+ return ("TextInfo - " + this.m_cultureData.CultureName);
+ }
+
+
+ //
+ // Titlecasing:
+ // -----------
+ // Titlecasing refers to a casing practice wherein the first letter of a word is an uppercase letter
+ // and the rest of the letters are lowercase. The choice of which words to titlecase in headings
+ // and titles is dependent on language and local conventions. For example, "The Merry Wives of Windor"
+ // is the appropriate titlecasing of that play's name in English, with the word "of" not titlecased.
+ // In German, however, the title is "Die lustigen Weiber von Windsor," and both "lustigen" and "von"
+ // are not titlecased. In French even fewer words are titlecased: "Les joyeuses commeres de Windsor."
+ //
+ // Moreover, the determination of what actually constitutes a word is language dependent, and this can
+ // influence which letter or letters of a "word" are uppercased when titlecasing strings. For example
+ // "l'arbre" is considered two words in French, whereas "can't" is considered one word in English.
+ //
+ //
+ // Differences between UNICODE 5.0 and the .NET Framework:
+ // -------------------------------------------------------------------------------------
+ // The .NET Framework previously shipped a naive titlecasing implementation. Every word is titlecased
+ // regardless of language or orthographic practice. Furthermore, apostrophe is always considered to be
+ // a word joiner as used in English. The longterm vision is to depend on the operating system for
+ // titlecasing. Windows 7 is expected to be the first release with this feature. On the Macintosh side,
+ // titlecasing is not available as of version 10.5 of the operating system.
+ //
+ public unsafe String ToTitleCase(String str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+ if (str.Length == 0)
+ {
+ return (str);
+ }
+
+ StringBuilder result = new StringBuilder();
+ String lowercaseData = null;
+
+ for (int i = 0; i < str.Length; i++)
+ {
+ UnicodeCategory charType;
+ int charLen;
+
+ charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen);
+ if (Char.CheckLetter(charType))
+ {
+ // Do the titlecasing for the first character of the word.
+ i = AddTitlecaseLetter(ref result, ref str, i, charLen) + 1;
+
+ //
+ // Convert the characters until the end of the this word
+ // to lowercase.
+ //
+ int lowercaseStart = i;
+
+ //
+ // Use hasLowerCase flag to prevent from lowercasing acronyms (like "URT", "USA", etc)
+ // This is in line with Word 2000 behavior of titlecasing.
+ //
+ bool hasLowerCase = (charType == UnicodeCategory.LowercaseLetter);
+ // Use a loop to find all of the other letters following this letter.
+ while (i < str.Length)
+ {
+ charType = CharUnicodeInfo.InternalGetUnicodeCategory(str, i, out charLen);
+ if (IsLetterCategory(charType))
+ {
+ if (charType == UnicodeCategory.LowercaseLetter)
+ {
+ hasLowerCase = true;
+ }
+ i += charLen;
+ }
+ else if (str[i] == '\'')
+ {
+ i++;
+ if (hasLowerCase)
+ {
+ if (lowercaseData == null)
+ {
+ lowercaseData = this.ToLower(str);
+ }
+ result.Append(lowercaseData, lowercaseStart, i - lowercaseStart);
+ }
+ else
+ {
+ result.Append(str, lowercaseStart, i - lowercaseStart);
+ }
+ lowercaseStart = i;
+ hasLowerCase = true;
+ }
+ else if (!IsWordSeparator(charType))
+ {
+ // This category is considered to be part of the word.
+ // This is any category that is marked as false in wordSeprator array.
+ i+= charLen;
+ }
+ else
+ {
+ // A word separator. Break out of the loop.
+ break;
+ }
+ }
+
+ int count = i - lowercaseStart;
+
+ if (count>0)
+ {
+ if (hasLowerCase)
+ {
+ if (lowercaseData == null)
+ {
+ lowercaseData = this.ToLower(str);
+ }
+ result.Append(lowercaseData, lowercaseStart, count);
+ }
+ else
+ {
+ result.Append(str, lowercaseStart, count);
+ }
+ }
+
+ if (i < str.Length)
+ {
+ // not a letter, just append it
+ i = AddNonLetter(ref result, ref str, i, charLen);
+ }
+ }
+ else
+ {
+ // not a letter, just append it
+ i = AddNonLetter(ref result, ref str, i, charLen);
+ }
+ }
+ return (result.ToString());
+ }
+
+ private static int AddNonLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen)
+ {
+ Contract.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddNonLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
+ if (charLen == 2)
+ {
+ // Surrogate pair
+ result.Append(input[inputIndex++]);
+ result.Append(input[inputIndex]);
+ }
+ else
+ {
+ result.Append(input[inputIndex]);
+ }
+ return inputIndex;
+ }
+
+
+ private int AddTitlecaseLetter(ref StringBuilder result, ref String input, int inputIndex, int charLen)
+ {
+ Contract.Assert(charLen == 1 || charLen == 2, "[TextInfo.AddTitlecaseLetter] CharUnicodeInfo.InternalGetUnicodeCategory returned an unexpected charLen!");
+
+ // for surrogate pairs do a simple ToUpper operation on the substring
+ if (charLen == 2)
+ {
+ // Surrogate pair
+ result.Append( this.ToUpper(input.Substring(inputIndex, charLen)) );
+ inputIndex++;
+ }
+ else
+ {
+ switch (input[inputIndex])
+ {
+ //
+ // For AppCompat, the Titlecase Case Mapping data from NDP 2.0 is used below.
+ case (char)0x01C4: // DZ with Caron -> Dz with Caron
+ case (char)0x01C5: // Dz with Caron -> Dz with Caron
+ case (char)0x01C6: // dz with Caron -> Dz with Caron
+ result.Append( (char)0x01C5 );
+ break;
+ case (char)0x01C7: // LJ -> Lj
+ case (char)0x01C8: // Lj -> Lj
+ case (char)0x01C9: // lj -> Lj
+ result.Append( (char)0x01C8 );
+ break;
+ case (char)0x01CA: // NJ -> Nj
+ case (char)0x01CB: // Nj -> Nj
+ case (char)0x01CC: // nj -> Nj
+ result.Append( (char)0x01CB );
+ break;
+ case (char)0x01F1: // DZ -> Dz
+ case (char)0x01F2: // Dz -> Dz
+ case (char)0x01F3: // dz -> Dz
+ result.Append( (char)0x01F2 );
+ break;
+ default:
+ result.Append( this.ToUpper(input[inputIndex]) );
+ break;
+ }
+ }
+ return inputIndex;
+ }
+
+
+ //
+ // Used in ToTitleCase():
+ // When we find a starting letter, the following array decides if a category should be
+ // considered as word seprator or not.
+ //
+ private const int wordSeparatorMask =
+ /* false */ (0 << 0) | // UppercaseLetter = 0,
+ /* false */ (0 << 1) | // LowercaseLetter = 1,
+ /* false */ (0 << 2) | // TitlecaseLetter = 2,
+ /* false */ (0 << 3) | // ModifierLetter = 3,
+ /* false */ (0 << 4) | // OtherLetter = 4,
+ /* false */ (0 << 5) | // NonSpacingMark = 5,
+ /* false */ (0 << 6) | // SpacingCombiningMark = 6,
+ /* false */ (0 << 7) | // EnclosingMark = 7,
+ /* false */ (0 << 8) | // DecimalDigitNumber = 8,
+ /* false */ (0 << 9) | // LetterNumber = 9,
+ /* false */ (0 << 10) | // OtherNumber = 10,
+ /* true */ (1 << 11) | // SpaceSeparator = 11,
+ /* true */ (1 << 12) | // LineSeparator = 12,
+ /* true */ (1 << 13) | // ParagraphSeparator = 13,
+ /* true */ (1 << 14) | // Control = 14,
+ /* true */ (1 << 15) | // Format = 15,
+ /* false */ (0 << 16) | // Surrogate = 16,
+ /* false */ (0 << 17) | // PrivateUse = 17,
+ /* true */ (1 << 18) | // ConnectorPunctuation = 18,
+ /* true */ (1 << 19) | // DashPunctuation = 19,
+ /* true */ (1 << 20) | // OpenPunctuation = 20,
+ /* true */ (1 << 21) | // ClosePunctuation = 21,
+ /* true */ (1 << 22) | // InitialQuotePunctuation = 22,
+ /* true */ (1 << 23) | // FinalQuotePunctuation = 23,
+ /* true */ (1 << 24) | // OtherPunctuation = 24,
+ /* true */ (1 << 25) | // MathSymbol = 25,
+ /* true */ (1 << 26) | // CurrencySymbol = 26,
+ /* true */ (1 << 27) | // ModifierSymbol = 27,
+ /* true */ (1 << 28) | // OtherSymbol = 28,
+ /* false */ (0 << 29); // OtherNotAssigned = 29;
+
+ private static bool IsWordSeparator(UnicodeCategory category)
+ {
+ return (wordSeparatorMask & (1 << (int)category)) != 0;
+ }
+
+ private static bool IsLetterCategory(UnicodeCategory uc)
+ {
+ return (uc == UnicodeCategory.UppercaseLetter
+ || uc == UnicodeCategory.LowercaseLetter
+ || uc == UnicodeCategory.TitlecaseLetter
+ || uc == UnicodeCategory.ModifierLetter
+ || uc == UnicodeCategory.OtherLetter);
+ }
+
+ // IsRightToLeft
+ //
+ // Returns true if the dominant direction of text and UI such as the relative position of buttons and scroll bars
+ //
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsRightToLeft
+ {
+ get
+ {
+ return this.m_cultureData.IsRightToLeft;
+ }
+ }
+
+ /// <internalonly/>
+ void IDeserializationCallback.OnDeserialization(Object sender)
+ {
+ OnDeserialized();
+ }
+
+ //
+ // Get case-insensitive hash code for the specified string.
+ //
+ // NOTENOTE: this is an internal function. The caller should verify the string
+ // is not null before calling this. Currenlty, CaseInsensitiveHashCodeProvider
+ // does that.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe int GetCaseInsensitiveHashCode(String str)
+ {
+ return GetCaseInsensitiveHashCode(str, false, 0);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe int GetCaseInsensitiveHashCode(String str, bool forceRandomizedHashing, long additionalEntropy)
+ {
+ // Validate inputs
+ if (str==null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ // Return our result
+ return (InternalGetCaseInsHash(this.m_dataHandle, this.m_handleOrigin, this.m_textInfoName, str, forceRandomizedHashing, additionalEntropy));
+ }
+
+ // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseChar
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern char InternalChangeCaseChar(IntPtr handle, IntPtr handleOrigin, String localeName, char ch, bool isToUpper);
+
+ // Change case (ToUpper/ToLower) -- COMNlsInfo::InternalChangeCaseString
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern String InternalChangeCaseString(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool isToUpper);
+
+ // Get case insensitive hash -- ComNlsInfo::InternalGetCaseInsHash
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern int InternalGetCaseInsHash(IntPtr handle, IntPtr handleOrigin, String localeName, String str, bool forceRandomizedHashing, long additionalEntropy);
+
+ // Call ::CompareStringOrdinal -- ComNlsInfo::InternalCompareStringOrdinalIgnoreCase
+ // Start at indexes and compare for length characters (or remainder of string if length == -1)
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static unsafe extern int InternalCompareStringOrdinalIgnoreCase(String string1, int index1, String string2, int index2, int length1, int length2);
+
+ // ComNlsInfo::InternalTryFindStringOrdinalIgnoreCase attempts a faster IndexOf/LastIndexOf OrdinalIgnoreCase using a kernel function.
+ // Returns true if FindStringOrdinal was handled, with foundIndex set to the target's index into the source
+ // Returns false when FindStringOrdinal wasn't handled
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static unsafe extern bool InternalTryFindStringOrdinalIgnoreCase(int searchFlags, String source, int sourceCount, int startIndex, String target, int targetCount, ref int foundIndex);
+ }
+
+}
+
+
diff --git a/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs
new file mode 100644
index 0000000000..f26c68adce
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/ThaiBuddhistCalendar.cs
@@ -0,0 +1,225 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+
+ /*=================================ThaiBuddhistCalendar==========================
+ **
+ ** ThaiBuddhistCalendar is based on Gregorian calendar. Its year value has
+ ** an offset to the Gregorain calendar.
+ **
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 0001/01/01 9999/12/31
+ ** Thai 0544/01/01 10542/12/31
+ ============================================================================*/
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable] public class ThaiBuddhistCalendar: Calendar {
+
+ // Initialize our era info.
+ static internal EraInfo[] thaiBuddhistEraInfo = new EraInfo[] {
+ new EraInfo( 1, 1, 1, 1, -543, 544, GregorianCalendar.MaxYear + 543) // era #, start year/month/day, yearOffset, minEraYear
+ };
+
+ //
+ // The era value for the current era.
+ //
+
+ public const int ThaiBuddhistEra = 1;
+
+ //internal static Calendar m_defaultInstance;
+
+ internal GregorianCalendarHelper helper;
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MinValue);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (DateTime.MaxValue);
+ }
+ }
+
+ // Return the type of the Thai Buddhist calendar.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override CalendarAlgorithmType AlgorithmType
+ {
+ get
+ {
+ return CalendarAlgorithmType.SolarCalendar;
+ }
+ }
+
+ public ThaiBuddhistCalendar() {
+ helper = new GregorianCalendarHelper(this, thaiBuddhistEraInfo);
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_THAI);
+ }
+ }
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ return (helper.AddMonths(time, months));
+ }
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (helper.AddYears(time, years));
+ }
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ return (helper.GetDaysInMonth(year, month, era));
+ }
+
+
+ public override int GetDaysInYear(int year, int era) {
+ return (helper.GetDaysInYear(year, era));
+ }
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (helper.GetDayOfMonth(time));
+ }
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return (helper.GetDayOfWeek(time));
+ }
+
+
+ public override int GetDayOfYear(DateTime time)
+ {
+ return (helper.GetDayOfYear(time));
+ }
+
+
+ public override int GetMonthsInYear(int year, int era) {
+ return (helper.GetMonthsInYear(year, era));
+ }
+
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetWeekOfYear(DateTime time, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
+ {
+ return (helper.GetWeekOfYear(time, rule, firstDayOfWeek));
+ }
+
+
+ public override int GetEra(DateTime time) {
+ return (helper.GetEra(time));
+ }
+
+ public override int GetMonth(DateTime time) {
+ return (helper.GetMonth(time));
+ }
+
+
+ public override int GetYear(DateTime time) {
+ return (helper.GetYear(time));
+ }
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era)
+ {
+ return (helper.IsLeapDay(year, month, day, era));
+ }
+
+
+ public override bool IsLeapYear(int year, int era) {
+ return (helper.IsLeapYear(year, era));
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetLeapMonth(int year, int era)
+ {
+ return (helper.GetLeapMonth(year, era));
+ }
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ return (helper.IsLeapMonth(year, month, era));
+ }
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ return (helper.ToDateTime(year, month, day, hour, minute, second, millisecond, era));
+ }
+
+
+ public override int[] Eras {
+ get {
+ return (helper.Eras);
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 2572;
+
+
+ public override int TwoDigitYearMax
+ {
+ get
+ {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ VerifyWritable();
+ if (value < 99 || value > helper.MaxYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ 99,
+ helper.MaxYear));
+
+ }
+ twoDigitYearMax = value;
+ }
+ }
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ return (helper.ToFourDigitYear(year, this.TwoDigitYearMax));
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs b/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs
new file mode 100644
index 0000000000..8f58623868
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TimeSpanFormat.cs
@@ -0,0 +1,474 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+namespace System.Globalization {
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+
+ internal static class TimeSpanFormat {
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static String IntToString(int n, int digits) {
+ return ParseNumbers.IntToString(n, 10, digits, '0', 0);
+ }
+
+ internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(false /*isNegative*/);
+ internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(true /*isNegative*/);
+
+ internal enum Pattern {
+ None = 0,
+ Minimum = 1,
+ Full = 2,
+ }
+
+ //
+ // Format
+ //
+ // Actions: Main method called from TimeSpan.ToString
+ //
+ internal static String Format(TimeSpan value, String format, IFormatProvider formatProvider) {
+ if (format == null || format.Length == 0)
+ format = "c";
+
+ // standard formats
+ if (format.Length == 1) {
+ char f = format[0];
+
+ if (f == 'c' || f == 't' || f == 'T')
+ return FormatStandard(value, true, format, Pattern.Minimum);
+ if (f == 'g' || f == 'G') {
+ Pattern pattern;
+ DateTimeFormatInfo dtfi = DateTimeFormatInfo.GetInstance(formatProvider);
+
+ if (value._ticks < 0)
+ format = dtfi.FullTimeSpanNegativePattern;
+ else
+ format = dtfi.FullTimeSpanPositivePattern;
+ if (f == 'g')
+ pattern = Pattern.Minimum;
+ else
+ pattern = Pattern.Full;
+
+ return FormatStandard(value, false, format, pattern);
+ }
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+
+ return FormatCustomized(value, format, DateTimeFormatInfo.GetInstance(formatProvider));
+ }
+
+ //
+ // FormatStandard
+ //
+ // Actions: Format the TimeSpan instance using the specified format.
+ //
+ private static String FormatStandard(TimeSpan value, bool isInvariant, String format, Pattern pattern) {
+ StringBuilder sb = StringBuilderCache.Acquire();
+ int day = (int)(value._ticks / TimeSpan.TicksPerDay);
+ long time = value._ticks % TimeSpan.TicksPerDay;
+
+ if (value._ticks < 0) {
+ day = -day;
+ time = -time;
+ }
+ int hours = (int)(time / TimeSpan.TicksPerHour % 24);
+ int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
+ int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
+ int fraction = (int)(time % TimeSpan.TicksPerSecond);
+
+ FormatLiterals literal;
+ if (isInvariant) {
+ if (value._ticks < 0)
+ literal = NegativeInvariantFormatLiterals;
+ else
+ literal = PositiveInvariantFormatLiterals;
+ }
+ else {
+ literal = new FormatLiterals();
+ literal.Init(format, pattern == Pattern.Full);
+ }
+ if (fraction != 0) { // truncate the partial second to the specified length
+ fraction = (int)((long)fraction / (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - literal.ff));
+ }
+
+ // Pattern.Full: [-]dd.hh:mm:ss.fffffff
+ // Pattern.Minimum: [-][d.]hh:mm:ss[.fffffff]
+
+ sb.Append(literal.Start); // [-]
+ if (pattern == Pattern.Full || day != 0) { //
+ sb.Append(day); // [dd]
+ sb.Append(literal.DayHourSep); // [.]
+ } //
+ sb.Append(IntToString(hours, literal.hh)); // hh
+ sb.Append(literal.HourMinuteSep); // :
+ sb.Append(IntToString(minutes, literal.mm)); // mm
+ sb.Append(literal.MinuteSecondSep); // :
+ sb.Append(IntToString(seconds, literal.ss)); // ss
+ if (!isInvariant && pattern == Pattern.Minimum) {
+ int effectiveDigits = literal.ff;
+ while (effectiveDigits > 0) {
+ if (fraction % 10 == 0) {
+ fraction = fraction / 10;
+ effectiveDigits--;
+ }
+ else {
+ break;
+ }
+ }
+ if (effectiveDigits > 0) {
+ sb.Append(literal.SecondFractionSep); // [.FFFFFFF]
+ sb.Append((fraction).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ }
+ }
+ else if (pattern == Pattern.Full || fraction != 0) {
+ sb.Append(literal.SecondFractionSep); // [.]
+ sb.Append(IntToString(fraction, literal.ff)); // [fffffff]
+ } //
+ sb.Append(literal.End); //
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+
+
+
+ //
+ // FormatCustomized
+ //
+ // Actions: Format the TimeSpan instance using the specified format.
+ //
+ internal static String FormatCustomized(TimeSpan value, String format, DateTimeFormatInfo dtfi) {
+
+ Contract.Assert(dtfi != null, "dtfi == null");
+
+ int day = (int)(value._ticks / TimeSpan.TicksPerDay);
+ long time = value._ticks % TimeSpan.TicksPerDay;
+
+ if (value._ticks < 0) {
+ day = -day;
+ time = -time;
+ }
+ int hours = (int)(time / TimeSpan.TicksPerHour % 24);
+ int minutes = (int)(time / TimeSpan.TicksPerMinute % 60);
+ int seconds = (int)(time / TimeSpan.TicksPerSecond % 60);
+ int fraction = (int)(time % TimeSpan.TicksPerSecond);
+
+ long tmp = 0;
+ int i = 0;
+ int tokenLen;
+ StringBuilder result = StringBuilderCache.Acquire();
+
+ while (i < format.Length) {
+ char ch = format[i];
+ int nextChar;
+ switch (ch) {
+ case 'h':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ DateTimeFormat.FormatDigits(result, hours, tokenLen);
+ break;
+ case 'm':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ DateTimeFormat.FormatDigits(result, minutes, tokenLen);
+ break;
+ case 's':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ DateTimeFormat.FormatDigits(result, seconds, tokenLen);
+ break;
+ case 'f':
+ //
+ // The fraction of a second in single-digit precision. The remaining digits are truncated.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+
+ tmp = (long)fraction;
+ tmp /= (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
+ result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[tokenLen - 1], CultureInfo.InvariantCulture));
+ break;
+ case 'F':
+ //
+ // Displays the most significant digit of the seconds fraction. Nothing is displayed if the digit is zero.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+
+ tmp = (long)fraction;
+ tmp /= (long)Math.Pow(10, DateTimeFormat.MaxSecondsFractionDigits - tokenLen);
+ int effectiveDigits = tokenLen;
+ while (effectiveDigits > 0) {
+ if (tmp % 10 == 0) {
+ tmp = tmp / 10;
+ effectiveDigits--;
+ }
+ else {
+ break;
+ }
+ }
+ if (effectiveDigits > 0) {
+ result.Append((tmp).ToString(DateTimeFormat.fixedNumberFormats[effectiveDigits - 1], CultureInfo.InvariantCulture));
+ }
+ break;
+ case 'd':
+ //
+ // tokenLen == 1 : Day as digits with no leading zero.
+ // tokenLen == 2+: Day as digits with leading zero for single-digit days.
+ //
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 8)
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ DateTimeFormat.FormatDigits(result, day, tokenLen, true);
+ break;
+ case '\'':
+ case '\"':
+ tokenLen = DateTimeFormat.ParseQuoteString(format, i, result);
+ break;
+ case '%':
+ // Optional format character.
+ // For example, format string "%d" will print day
+ // Most of the cases, "%" can be ignored.
+ nextChar = DateTimeFormat.ParseNextChar(format, i);
+ // nextChar will be -1 if we already reach the end of the format string.
+ // Besides, we will not allow "%%" appear in the pattern.
+ if (nextChar >= 0 && nextChar != (int)'%') {
+ result.Append(TimeSpanFormat.FormatCustomized(value, ((char)nextChar).ToString(), dtfi));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '%' is at the end of the format string or
+ // "%%" appears in the format string.
+ //
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ break;
+ case '\\':
+ // Escaped character. Can be used to insert character into the format string.
+ // For example, "\d" will insert the character 'd' into the string.
+ //
+ nextChar = DateTimeFormat.ParseNextChar(format, i);
+ if (nextChar >= 0)
+ {
+ result.Append(((char)nextChar));
+ tokenLen = 2;
+ }
+ else
+ {
+ //
+ // This means that '\' is at the end of the formatting string.
+ //
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ break;
+ default:
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ i += tokenLen;
+ }
+ return StringBuilderCache.GetStringAndRelease(result);
+
+ }
+
+
+
+
+ internal struct FormatLiterals {
+ internal String Start {
+ get {
+ return literals[0];
+ }
+ }
+ internal String DayHourSep {
+ get {
+ return literals[1];
+ }
+ }
+ internal String HourMinuteSep {
+ get {
+ return literals[2];
+ }
+ }
+ internal String MinuteSecondSep {
+ get {
+ return literals[3];
+ }
+ }
+ internal String SecondFractionSep {
+ get {
+ return literals[4];
+ }
+ }
+ internal String End {
+ get {
+ return literals[5];
+ }
+ }
+ internal String AppCompatLiteral;
+ internal int dd;
+ internal int hh;
+ internal int mm;
+ internal int ss;
+ internal int ff;
+
+ private String[] literals;
+
+
+ /* factory method for static invariant FormatLiterals */
+ internal static FormatLiterals InitInvariant(bool isNegative) {
+ FormatLiterals x = new FormatLiterals();
+ x.literals = new String[6];
+ x.literals[0] = isNegative ? "-" : String.Empty;
+ x.literals[1] = ".";
+ x.literals[2] = ":";
+ x.literals[3] = ":";
+ x.literals[4] = ".";
+ x.literals[5] = String.Empty;
+ x.AppCompatLiteral = ":."; // MinuteSecondSep+SecondFractionSep;
+ x.dd = 2;
+ x.hh = 2;
+ x.mm = 2;
+ x.ss = 2;
+ x.ff = DateTimeFormat.MaxSecondsFractionDigits;
+ return x;
+ }
+
+ // For the "v1" TimeSpan localized patterns, the data is simply literal field separators with
+ // the constants guaranteed to include DHMSF ordered greatest to least significant.
+ // Once the data becomes more complex than this we will need to write a proper tokenizer for
+ // parsing and formatting
+ internal void Init(String format, bool useInvariantFieldLengths) {
+ literals = new String[6];
+ for (int i = 0; i < literals.Length; i++)
+ literals[i] = String.Empty;
+ dd = 0;
+ hh = 0;
+ mm = 0;
+ ss = 0;
+ ff = 0;
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ bool inQuote = false;
+ char quote = '\'';
+ int field = 0;
+
+ for (int i = 0; i < format.Length; i++) {
+ switch (format[i]) {
+ case '\'':
+ case '\"':
+ if (inQuote && (quote == format[i])) {
+ /* we were in a quote and found a matching exit quote, so we are outside a quote now */
+ Contract.Assert(field >= 0 && field <= 5, "field >= 0 && field <= 5");
+ if (field >= 0 && field <= 5) {
+ literals[field] = sb.ToString();
+ sb.Length = 0;
+ inQuote = false;
+ }
+ else {
+ return; // how did we get here?
+ }
+ }
+ else if (!inQuote) {
+ /* we are at the start of a new quote block */
+ quote = format[i];
+ inQuote = true;
+ }
+ else {
+ /* we were in a quote and saw the other type of quote character, so we are still in a quote */
+ }
+ break;
+ case '%':
+ Contract.Assert(false, "Unexpected special token '%', Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ goto default;
+ case '\\':
+ if (!inQuote) {
+ i++; /* skip next character that is escaped by this backslash or percent sign */
+ break;
+ }
+ goto default;
+ case 'd':
+ if (!inQuote) {
+ Contract.Assert((field == 0 && sb.Length == 0) || field == 1,
+ "field == 0 || field == 1, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 1; // DayHourSep
+ dd++;
+ }
+ break;
+ case 'h':
+ if (!inQuote) {
+ Contract.Assert((field == 1 && sb.Length == 0) || field == 2,
+ "field == 1 || field == 2, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 2; // HourMinuteSep
+ hh++;
+ }
+ break;
+ case 'm':
+ if (!inQuote) {
+ Contract.Assert((field == 2 && sb.Length == 0) || field == 3,
+ "field == 2 || field == 3, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 3; // MinuteSecondSep
+ mm++;
+ }
+ break;
+ case 's':
+ if (!inQuote) {
+ Contract.Assert((field == 3 && sb.Length == 0) || field == 4,
+ "field == 3 || field == 4, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 4; // SecondFractionSep
+ ss++;
+ }
+ break;
+ case 'f':
+ case 'F':
+ if (!inQuote) {
+ Contract.Assert((field == 4 && sb.Length == 0) || field == 5,
+ "field == 4 || field == 5, Bug in DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ field = 5; // End
+ ff++;
+ }
+ break;
+ default:
+ sb.Append(format[i]);
+ break;
+ }
+ }
+
+ Contract.Assert(field == 5);
+ AppCompatLiteral = MinuteSecondSep + SecondFractionSep;
+
+ Contract.Assert(0 < dd && dd < 3, "0 < dd && dd < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Contract.Assert(0 < hh && hh < 3, "0 < hh && hh < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Contract.Assert(0 < mm && mm < 3, "0 < mm && mm < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Contract.Assert(0 < ss && ss < 3, "0 < ss && ss < 3, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+ Contract.Assert(0 < ff && ff < 8, "0 < ff && ff < 8, Bug in System.Globalization.DateTimeFormatInfo.FullTimeSpan[Positive|Negative]Pattern");
+
+ if (useInvariantFieldLengths) {
+ dd = 2;
+ hh = 2;
+ mm = 2;
+ ss = 2;
+ ff = DateTimeFormat.MaxSecondsFractionDigits;
+ }
+ else {
+ if (dd < 1 || dd > 2) dd = 2; // The DTFI property has a problem. let's try to make the best of the situation.
+ if (hh < 1 || hh > 2) hh = 2;
+ if (mm < 1 || mm > 2) mm = 2;
+ if (ss < 1 || ss > 2) ss = 2;
+ if (ff < 1 || ff > 7) ff = 7;
+ }
+ StringBuilderCache.Release(sb);
+ }
+ } //end of struct FormatLiterals
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/TimeSpanParse.cs b/src/mscorlib/src/System/Globalization/TimeSpanParse.cs
new file mode 100644
index 0000000000..e72e582a97
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TimeSpanParse.cs
@@ -0,0 +1,1557 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+////////////////////////////////////////////////////////////////////////////
+//
+//
+// Purpose: This class is called by TimeSpan to parse a time interval string.
+//
+// Standard Format:
+// -=-=-=-=-=-=-=-
+// "c": Constant format. [-][d'.']hh':'mm':'ss['.'fffffff]
+// Not culture sensitive. Default format (and null/empty format string) map to this format.
+//
+// "g": General format, short: [-][d':']h':'mm':'ss'.'FFFFFFF
+// Only print what's needed. Localized (if you want Invariant, pass in Invariant).
+// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
+//
+// "G": General format, long: [-]d':'hh':'mm':'ss'.'fffffff
+// Always print days and 7 fractional digits. Localized (if you want Invariant, pass in Invariant).
+// The fractional seconds separator is localized, equal to the culture's DecimalSeparator.
+//
+//
+// * "TryParseTimeSpan" is the main method for Parse/TryParse
+//
+// - TimeSpanTokenizer.GetNextToken() is used to split the input string into number and literal tokens.
+// - TimeSpanRawInfo.ProcessToken() adds the next token into the parsing intermediary state structure
+// - ProcessTerminalState() uses the fully initialized TimeSpanRawInfo to find a legal parse match.
+// The terminal states are attempted as follows:
+// foreach (+InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern) try
+// 1 number => d
+// 2 numbers => h:m
+// 3 numbers => h:m:s | d.h:m | h:m:.f
+// 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
+// 5 numbers => d.h:m:s.f
+//
+// Custom Format:
+// -=-=-=-=-=-=-=
+//
+// * "TryParseExactTimeSpan" is the main method for ParseExact/TryParseExact methods
+// * "TryParseExactMultipleTimeSpan" is the main method for ParseExact/TryparseExact
+// methods that take a String[] of formats
+//
+// - For single-letter formats "TryParseTimeSpan" is called (see above)
+// - For multi-letter formats "TryParseByFormat" is called
+// - TryParseByFormat uses helper methods (ParseExactLiteral, ParseExactDigits, etc)
+// which drive the underlying TimeSpanTokenizer. However, unlike standard formatting which
+// operates on whole-tokens, ParseExact operates at the character-level. As such,
+// TimeSpanTokenizer.NextChar and TimeSpanTokenizer.BackOne() are called directly.
+//
+////////////////////////////////////////////////////////////////////////////
+namespace System.Globalization {
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+
+ internal static class TimeSpanParse {
+ // ---- SECTION: members for internal support ---------*
+ internal static void ValidateStyles(TimeSpanStyles style, String parameterName) {
+ if (style != TimeSpanStyles.None && style != TimeSpanStyles.AssumeNegative)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTimeSpanStyles"), parameterName);
+ }
+
+ internal const int unlimitedDigits = -1;
+ internal const int maxFractionDigits = 7;
+
+ internal const int maxDays = 10675199;
+ internal const int maxHours = 23;
+ internal const int maxMinutes = 59;
+ internal const int maxSeconds = 59;
+ internal const int maxFraction = 9999999;
+
+ #region InternalSupport
+ enum TimeSpanThrowStyle {
+ None = 0,
+ All = 1,
+ }
+
+ private enum ParseFailureKind {
+ None = 0,
+ ArgumentNull = 1,
+ Format = 2,
+ FormatWithParameter = 3,
+ Overflow = 4,
+ }
+
+ [Flags]
+ enum TimeSpanStandardStyles { // Standard Format Styles
+ None = 0x00000000,
+ Invariant = 0x00000001, //Allow Invariant Culture
+ Localized = 0x00000002, //Allow Localized Culture
+ RequireFull = 0x00000004, //Require the input to be in DHMSF format
+ Any = Invariant | Localized,
+ }
+
+ // TimeSpan Token Types
+ private enum TTT {
+ None = 0, // None of the TimeSpanToken fields are set
+ End = 1, // '\0'
+ Num = 2, // Number
+ Sep = 3, // literal
+ NumOverflow = 4, // Number that overflowed
+ }
+
+ private static readonly TimeSpanToken zero = new TimeSpanToken(0);
+ struct TimeSpanToken {
+ internal TTT ttt;
+ internal int num; // Store the number that we are parsing (if any)
+ internal int zeroes; // Store the number of leading zeroes (if any)
+ internal String sep; // Store the literal that we are parsing (if any)
+
+ public TimeSpanToken(int number) {
+ ttt = TTT.Num;
+ num = number;
+ zeroes = 0;
+ sep = null;
+ }
+
+ public TimeSpanToken(int leadingZeroes, int number) {
+ ttt = TTT.Num;
+ num = number;
+ zeroes = leadingZeroes;
+ sep = null;
+ }
+
+ public bool IsInvalidNumber(int maxValue, int maxPrecision) {
+ Contract.Assert(ttt == TTT.Num);
+ Contract.Assert(num > -1);
+ Contract.Assert(maxValue > 0);
+ Contract.Assert(maxPrecision == maxFractionDigits || maxPrecision == unlimitedDigits);
+
+ if (num > maxValue)
+ return true;
+ if (maxPrecision == unlimitedDigits)
+ return false; // all validation past this point applies only to fields with precision limits
+ if (zeroes > maxPrecision)
+ return true;
+ if (num == 0 || zeroes == 0)
+ return false;
+
+ // num > 0 && zeroes > 0 && num <= maxValue && zeroes <= maxPrecision
+ return (num >= (maxValue/(long)Math.Pow(10, zeroes-1)));
+ }
+ }
+
+ //
+ // TimeSpanTokenizer
+ //
+ // Actions: TimeSpanTokenizer.GetNextToken() returns the next token in the input string.
+ //
+ struct TimeSpanTokenizer {
+ private int m_pos;
+ private String m_value;
+
+ internal void Init(String input) {
+ Init(input, 0);
+ }
+ internal void Init(String input, int startPosition) {
+ m_pos = startPosition;
+ m_value = input;
+ }
+ // used by the parsing routines that operate on standard-formats
+ internal TimeSpanToken GetNextToken() {
+ Contract.Assert(m_pos > -1);
+
+ TimeSpanToken tok = new TimeSpanToken();
+ char ch = CurrentChar;
+
+ if (ch == (char)0) {
+ tok.ttt = TTT.End;
+ return tok;
+ }
+
+ if (ch >= '0' && ch <= '9') {
+ tok.ttt = TTT.Num;
+ tok.num = 0;
+ tok.zeroes = 0;
+ do {
+ if ((tok.num & 0xF0000000) != 0) {
+ tok.ttt = TTT.NumOverflow;
+ return tok;
+ }
+ tok.num = tok.num * 10 + ch - '0';
+ if (tok.num == 0) tok.zeroes++;
+ if (tok.num < 0) {
+ tok.ttt = TTT.NumOverflow;
+ return tok;
+ }
+ ch = NextChar;
+ } while (ch >= '0' && ch <= '9');
+ return tok;
+ }
+ else {
+ tok.ttt = TTT.Sep;
+ int startIndex = m_pos;
+ int length = 0;
+
+ while (ch != (char)0 && (ch < '0' || '9' < ch)) {
+ ch = NextChar;
+ length++;
+ }
+ tok.sep = m_value.Substring(startIndex, length);
+ return tok;
+ }
+ }
+
+ internal Boolean EOL {
+ get {
+ return m_pos >= (m_value.Length-1);
+ }
+ }
+ // BackOne, NextChar, CurrentChar - used by ParseExact (ParseByFormat) to operate
+ // on custom-formats where exact character-by-character control is allowed
+ internal void BackOne() {
+ if (m_pos > 0) --m_pos;
+ }
+
+ internal char NextChar {
+ get {
+ m_pos++;
+ return CurrentChar;
+ }
+ }
+ internal char CurrentChar {
+ get {
+ if (m_pos > -1 && m_pos < m_value.Length) {
+ return m_value[m_pos];
+ }
+ else {
+ return (char) 0;
+ }
+ }
+ }
+ }
+
+
+
+ // This stores intermediary parsing state for the standard formats
+ struct TimeSpanRawInfo {
+ internal TimeSpanFormat.FormatLiterals PositiveInvariant {
+ get {
+ return TimeSpanFormat.PositiveInvariantFormatLiterals;
+ }
+ }
+ internal TimeSpanFormat.FormatLiterals NegativeInvariant {
+ get {
+ return TimeSpanFormat.NegativeInvariantFormatLiterals;
+ }
+ }
+
+ internal TimeSpanFormat.FormatLiterals PositiveLocalized {
+ get {
+ if (!m_posLocInit) {
+ m_posLoc = new TimeSpanFormat.FormatLiterals();
+ m_posLoc.Init(m_fullPosPattern, false);
+ m_posLocInit = true;
+ }
+ return m_posLoc;
+ }
+ }
+ internal TimeSpanFormat.FormatLiterals NegativeLocalized {
+ get {
+ if (!m_negLocInit) {
+ m_negLoc = new TimeSpanFormat.FormatLiterals();
+ m_negLoc.Init(m_fullNegPattern, false);
+ m_negLocInit = true;
+ }
+ return m_negLoc;
+ }
+ }
+
+ internal Boolean FullAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 5
+ && NumCount == 4
+ && pattern.Start == literals[0]
+ && pattern.DayHourSep == literals[1]
+ && pattern.HourMinuteSep == literals[2]
+ && pattern.AppCompatLiteral == literals[3]
+ && pattern.End == literals[4];
+ }
+
+ internal Boolean PartialAppCompatMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 4
+ && NumCount == 3
+ && pattern.Start == literals[0]
+ && pattern.HourMinuteSep == literals[1]
+ && pattern.AppCompatLiteral == literals[2]
+ && pattern.End == literals[3];
+ }
+ // DHMSF (all values matched)
+ internal Boolean FullMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == MaxLiteralTokens
+ && NumCount == MaxNumericTokens
+ && pattern.Start == literals[0]
+ && pattern.DayHourSep == literals[1]
+ && pattern.HourMinuteSep == literals[2]
+ && pattern.MinuteSecondSep == literals[3]
+ && pattern.SecondFractionSep == literals[4]
+ && pattern.End == literals[5];
+ }
+ // D (no hours, minutes, seconds, or fractions)
+ internal Boolean FullDMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 2
+ && NumCount == 1
+ && pattern.Start == literals[0]
+ && pattern.End == literals[1];
+ }
+ // HM (no days, seconds, or fractions)
+ internal Boolean FullHMMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 3
+ && NumCount == 2
+ && pattern.Start == literals[0]
+ && pattern.HourMinuteSep == literals[1]
+ && pattern.End == literals[2];
+ }
+ // DHM (no seconds or fraction)
+ internal Boolean FullDHMMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 4
+ && NumCount == 3
+ && pattern.Start == literals[0]
+ && pattern.DayHourSep == literals[1]
+ && pattern.HourMinuteSep == literals[2]
+ && pattern.End == literals[3];
+
+ }
+ // HMS (no days or fraction)
+ internal Boolean FullHMSMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 4
+ && NumCount == 3
+ && pattern.Start == literals[0]
+ && pattern.HourMinuteSep == literals[1]
+ && pattern.MinuteSecondSep == literals[2]
+ && pattern.End == literals[3];
+ }
+ // DHMS (no fraction)
+ internal Boolean FullDHMSMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 5
+ && NumCount == 4
+ && pattern.Start == literals[0]
+ && pattern.DayHourSep == literals[1]
+ && pattern.HourMinuteSep == literals[2]
+ && pattern.MinuteSecondSep == literals[3]
+ && pattern.End == literals[4];
+ }
+ // HMSF (no days)
+ internal Boolean FullHMSFMatch(TimeSpanFormat.FormatLiterals pattern) {
+ return SepCount == 5
+ && NumCount == 4
+ && pattern.Start == literals[0]
+ && pattern.HourMinuteSep == literals[1]
+ && pattern.MinuteSecondSep == literals[2]
+ && pattern.SecondFractionSep == literals[3]
+ && pattern.End == literals[4];
+ }
+
+ internal TTT lastSeenTTT;
+ internal int tokenCount;
+ internal int SepCount;
+ internal int NumCount;
+ internal String[] literals;
+ internal TimeSpanToken[] numbers; // raw numbers
+
+ private TimeSpanFormat.FormatLiterals m_posLoc;
+ private TimeSpanFormat.FormatLiterals m_negLoc;
+ private Boolean m_posLocInit;
+ private Boolean m_negLocInit;
+ private String m_fullPosPattern;
+ private String m_fullNegPattern;
+
+ private const int MaxTokens = 11;
+ private const int MaxLiteralTokens = 6;
+ private const int MaxNumericTokens = 5;
+
+ internal void Init(DateTimeFormatInfo dtfi) {
+ Contract.Assert(dtfi != null);
+
+ lastSeenTTT = TTT.None;
+ tokenCount = 0;
+ SepCount = 0;
+ NumCount = 0;
+
+ literals = new String[MaxLiteralTokens];
+ numbers = new TimeSpanToken[MaxNumericTokens];
+
+ m_fullPosPattern = dtfi.FullTimeSpanPositivePattern;
+ m_fullNegPattern = dtfi.FullTimeSpanNegativePattern;
+ m_posLocInit = false;
+ m_negLocInit = false;
+ }
+
+ internal Boolean ProcessToken(ref TimeSpanToken tok, ref TimeSpanResult result) {
+ if (tok.ttt == TTT.NumOverflow) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge", null);
+ return false;
+ }
+ if (tok.ttt != TTT.Sep && tok.ttt != TTT.Num) {
+ // Some unknown token or a repeat token type in the input
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan", null);
+ return false;
+ }
+
+ switch (tok.ttt) {
+ case TTT.Sep:
+ if (!AddSep(tok.sep, ref result)) return false;
+ break;
+ case TTT.Num:
+ if (tokenCount == 0) {
+ if (!AddSep(String.Empty, ref result)) return false;
+ }
+ if (!AddNum(tok, ref result)) return false;
+ break;
+ default:
+ break;
+ }
+
+ lastSeenTTT = tok.ttt;
+ Contract.Assert(tokenCount == (SepCount + NumCount), "tokenCount == (SepCount + NumCount)");
+ return true;
+ }
+
+ private bool AddSep(String sep, ref TimeSpanResult result) {
+ if (SepCount >= MaxLiteralTokens || tokenCount >= MaxTokens) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan", null);
+ return false;
+ }
+ literals[SepCount++] = sep;
+ tokenCount++;
+ return true;
+ }
+ private bool AddNum(TimeSpanToken num, ref TimeSpanResult result) {
+ if (NumCount >= MaxNumericTokens || tokenCount >= MaxTokens) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan", null);
+ return false;
+ }
+ numbers[NumCount++] = num;
+ tokenCount++;
+ return true;
+ }
+ }
+
+ // This will store the result of the parsing. And it will eventually be used to construct a TimeSpan instance.
+ struct TimeSpanResult {
+ internal TimeSpan parsedTimeSpan;
+ internal TimeSpanThrowStyle throwStyle;
+
+ internal ParseFailureKind m_failure;
+ internal string m_failureMessageID;
+ internal object m_failureMessageFormatArgument;
+ internal string m_failureArgumentName;
+
+ internal void Init(TimeSpanThrowStyle canThrow) {
+ parsedTimeSpan = default(TimeSpan);
+ throwStyle = canThrow;
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID) {
+ SetFailure(failure, failureMessageID, null, null);
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) {
+ SetFailure(failure, failureMessageID, failureMessageFormatArgument, null);
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument,
+ string failureArgumentName) {
+ m_failure = failure;
+ m_failureMessageID = failureMessageID;
+ m_failureMessageFormatArgument = failureMessageFormatArgument;
+ m_failureArgumentName = failureArgumentName;
+ if (throwStyle != TimeSpanThrowStyle.None) {
+ throw GetTimeSpanParseException();
+ }
+ }
+
+ internal Exception GetTimeSpanParseException() {
+ switch (m_failure) {
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(m_failureArgumentName, Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.FormatWithParameter:
+ return new FormatException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument));
+
+ case ParseFailureKind.Format:
+ return new FormatException(Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.Overflow:
+ return new OverflowException(Environment.GetResourceString(m_failureMessageID));
+
+ default:
+ Contract.Assert(false, "Unknown TimeSpanParseFailure: " + m_failure);
+ return new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ }
+ }
+
+ static bool TryTimeToTicks(bool positive, TimeSpanToken days, TimeSpanToken hours, TimeSpanToken minutes, TimeSpanToken seconds, TimeSpanToken fraction, out long result) {
+ if (days.IsInvalidNumber(maxDays, unlimitedDigits)
+ || hours.IsInvalidNumber(maxHours, unlimitedDigits)
+ || minutes.IsInvalidNumber(maxMinutes, unlimitedDigits)
+ || seconds.IsInvalidNumber(maxSeconds, unlimitedDigits)
+ || fraction.IsInvalidNumber(maxFraction, maxFractionDigits)) {
+ result = 0;
+ return false;
+ }
+
+ Int64 ticks = ((Int64)days.num * 3600 * 24 + (Int64)hours.num * 3600 + (Int64)minutes.num * 60 + seconds.num) * 1000;
+ if (ticks > TimeSpan.MaxMilliSeconds || ticks < TimeSpan.MinMilliSeconds) {
+ result = 0;
+ return false;
+ }
+
+ // Normalize the fraction component
+ //
+ // string representation => (zeroes,num) => resultant fraction ticks
+ // --------------------- ------------ ------------------------
+ // ".9999999" => (0,9999999) => 9,999,999 ticks (same as constant maxFraction)
+ // ".1" => (0,1) => 1,000,000 ticks
+ // ".01" => (1,1) => 100,000 ticks
+ // ".001" => (2,1) => 10,000 ticks
+ long f = fraction.num;
+ if (f != 0) {
+ long lowerLimit = TimeSpan.TicksPerTenthSecond;
+ if (fraction.zeroes > 0) {
+ long divisor = (long)Math.Pow(10, fraction.zeroes);
+ lowerLimit = lowerLimit / divisor;
+ }
+ while (f < lowerLimit) {
+ f *= 10;
+ }
+ }
+ result = ((long)ticks * TimeSpan.TicksPerMillisecond) + f;
+ if (positive && result < 0) {
+ result = 0;
+ return false;
+ }
+ return true;
+ }
+ #endregion
+
+
+ // ---- SECTION: internal static methods called by System.TimeSpan ---------*
+ //
+ // [Try]Parse, [Try]ParseExact, and [Try]ParseExactMultiple
+ //
+ // Actions: Main methods called from TimeSpan.Parse
+ #region ParseMethods
+ internal static TimeSpan Parse(String input, IFormatProvider formatProvider) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.All);
+
+ if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult)) {
+ return parseResult.parsedTimeSpan;
+ }
+ else {
+ throw parseResult.GetTimeSpanParseException();
+ }
+ }
+ internal static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.None);
+
+ if (TryParseTimeSpan(input, TimeSpanStandardStyles.Any, formatProvider, ref parseResult)) {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+ else {
+ result = default(TimeSpan);
+ return false;
+ }
+ }
+ internal static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.All);
+
+ if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult)) {
+ return parseResult.parsedTimeSpan;
+ }
+ else {
+ throw parseResult.GetTimeSpanParseException();
+ }
+ }
+ internal static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.None);
+
+ if (TryParseExactTimeSpan(input, format, formatProvider, styles, ref parseResult)) {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+ else {
+ result = default(TimeSpan);
+ return false;
+ }
+ }
+ internal static TimeSpan ParseExactMultiple(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.All);
+
+ if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult)) {
+ return parseResult.parsedTimeSpan;
+ }
+ else {
+ throw parseResult.GetTimeSpanParseException();
+ }
+ }
+ internal static Boolean TryParseExactMultiple(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) {
+ TimeSpanResult parseResult = new TimeSpanResult();
+ parseResult.Init(TimeSpanThrowStyle.None);
+
+ if (TryParseExactMultipleTimeSpan(input, formats, formatProvider, styles, ref parseResult)) {
+ result = parseResult.parsedTimeSpan;
+ return true;
+ }
+ else {
+ result = default(TimeSpan);
+ return false;
+ }
+ }
+ #endregion
+
+
+ // ---- SECTION: private static methods that do the actual work ---------*
+ #region TryParseTimeSpan
+ //
+ // TryParseTimeSpan
+ //
+ // Actions: Common private Parse method called by both Parse and TryParse
+ //
+ private static Boolean TryParseTimeSpan(String input, TimeSpanStandardStyles style, IFormatProvider formatProvider, ref TimeSpanResult result) {
+ if (input == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input");
+ return false;
+ }
+
+ input = input.Trim();
+ if (input == String.Empty) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ TimeSpanTokenizer tokenizer = new TimeSpanTokenizer();
+ tokenizer.Init(input);
+
+ TimeSpanRawInfo raw = new TimeSpanRawInfo();
+ raw.Init(DateTimeFormatInfo.GetInstance(formatProvider));
+
+ TimeSpanToken tok = tokenizer.GetNextToken();
+
+ /* The following loop will break out when we reach the end of the str or
+ * when we can determine that the input is invalid. */
+ while (tok.ttt != TTT.End) {
+ if (!raw.ProcessToken(ref tok, ref result)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ tok = tokenizer.GetNextToken();
+ }
+ if (!tokenizer.EOL) {
+ // embedded nulls in the input string
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ if (!ProcessTerminalState(ref raw, style, ref result)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ return true;
+ }
+
+
+
+ //
+ // ProcessTerminalState
+ //
+ // Actions: Validate the terminal state of a standard format parse.
+ // Sets result.parsedTimeSpan on success.
+ //
+ // Calculates the resultant TimeSpan from the TimeSpanRawInfo
+ //
+ // try => +InvariantPattern, -InvariantPattern, +LocalizedPattern, -LocalizedPattern
+ // 1) Verify Start matches
+ // 2) Verify End matches
+ // 3) 1 number => d
+ // 2 numbers => h:m
+ // 3 numbers => h:m:s | d.h:m | h:m:.f
+ // 4 numbers => h:m:s.f | d.h:m:s | d.h:m:.f
+ // 5 numbers => d.h:m:s.f
+ private static Boolean ProcessTerminalState(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.lastSeenTTT == TTT.Num) {
+ TimeSpanToken tok = new TimeSpanToken();
+ tok.ttt = TTT.Sep;
+ tok.sep = String.Empty;
+ if (!raw.ProcessToken(ref tok, ref result)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ }
+
+ switch (raw.NumCount) {
+ case 1:
+ return ProcessTerminal_D(ref raw, style, ref result);
+ case 2:
+ return ProcessTerminal_HM(ref raw, style, ref result);
+ case 3:
+ return ProcessTerminal_HM_S_D(ref raw, style, ref result);
+ case 4:
+ return ProcessTerminal_HMS_F_D(ref raw, style, ref result);
+ case 5:
+ return ProcessTerminal_DHMSF(ref raw, style, ref result);
+ default:
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ }
+
+ //
+ // ProcessTerminal_DHMSF
+ //
+ // Actions: Validate the 5-number "Days.Hours:Minutes:Seconds.Fraction" terminal case.
+ // Sets result.parsedTimeSpan on success.
+ //
+ private static Boolean ProcessTerminal_DHMSF(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.SepCount != 6 || raw.NumCount != 5) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false;
+ bool match = false;
+
+ if (inv) {
+ if (raw.FullMatch(raw.PositiveInvariant)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullMatch(raw.NegativeInvariant)) {
+ match = true;
+ positive = false;
+ }
+ }
+ if (loc) {
+ if (!match && raw.FullMatch(raw.PositiveLocalized)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullMatch(raw.NegativeLocalized)) {
+ match = true;
+ positive = false;
+ }
+ }
+ long ticks;
+ if (match) {
+ if (!TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], raw.numbers[4], out ticks)) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ if (!positive) {
+ ticks = -ticks;
+ if (ticks > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ //
+ // ProcessTerminal_HMS_F_D
+ //
+ // Actions: Validate the ambiguous 4-number "Hours:Minutes:Seconds.Fraction", "Days.Hours:Minutes:Seconds", or "Days.Hours:Minutes:.Fraction" terminal case.
+ // Sets result.parsedTimeSpan on success.
+ //
+ private static Boolean ProcessTerminal_HMS_F_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.SepCount != 5 || raw.NumCount != 4 || (style & TimeSpanStandardStyles.RequireFull) != 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ long ticks = 0;
+ bool positive = false;
+ bool match = false;
+ bool overflow = false;
+
+ if (inv) {
+ if (raw.FullHMSFMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMSMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullAppCompatMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullHMSFMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMSMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullAppCompatMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ }
+ if (loc) {
+ if (!match && raw.FullHMSFMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMSMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullAppCompatMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullHMSFMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMSMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], raw.numbers[3], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullAppCompatMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, raw.numbers[3], out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (match) {
+ if (!positive) {
+ ticks = -ticks;
+ if (ticks > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ if (overflow) {
+ // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ else {
+ // we couldn't find a thing
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ }
+
+ //
+ // ProcessTerminal_HM_S_D
+ //
+ // Actions: Validate the ambiguous 3-number "Hours:Minutes:Seconds", "Days.Hours:Minutes", or "Hours:Minutes:.Fraction" terminal case
+ //
+ private static Boolean ProcessTerminal_HM_S_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.SepCount != 4 || raw.NumCount != 3 || (style & TimeSpanStandardStyles.RequireFull) != 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false;
+ bool match = false;
+ bool overflow = false;
+
+ long ticks = 0;
+
+ if (inv) {
+ if (raw.FullHMSMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.PartialAppCompatMatch(raw.PositiveInvariant)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullHMSMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.PartialAppCompatMatch(raw.NegativeInvariant)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks);
+ overflow = overflow || !match;
+ }
+ }
+ if (loc) {
+ if (!match && raw.FullHMSMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.PartialAppCompatMatch(raw.PositiveLocalized)) {
+ positive = true;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullHMSMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.FullDHMMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, raw.numbers[0], raw.numbers[1], raw.numbers[2], zero, zero, out ticks);
+ overflow = overflow || !match;
+ }
+ if (!match && raw.PartialAppCompatMatch(raw.NegativeLocalized)) {
+ positive = false;
+ match = TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, raw.numbers[2], out ticks);
+ overflow = overflow || !match;
+ }
+ }
+
+ if (match) {
+ if (!positive) {
+ ticks = -ticks;
+ if (ticks > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ if (overflow) {
+ // we found at least one literal pattern match but the numbers just didn't fit
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ else {
+ // we couldn't find a thing
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ }
+
+ //
+ // ProcessTerminal_HM
+ //
+ // Actions: Validate the 2-number "Hours:Minutes" terminal case
+ //
+ private static Boolean ProcessTerminal_HM(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.SepCount != 3 || raw.NumCount != 2 || (style & TimeSpanStandardStyles.RequireFull) != 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false;
+ bool match = false;
+
+ if (inv) {
+ if (raw.FullHMMatch(raw.PositiveInvariant)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullHMMatch(raw.NegativeInvariant)) {
+ match = true;
+ positive = false;
+ }
+ }
+ if (loc) {
+ if (!match && raw.FullHMMatch(raw.PositiveLocalized)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullHMMatch(raw.NegativeLocalized)) {
+ match = true;
+ positive = false;
+ }
+ }
+
+ long ticks = 0;
+ if (match) {
+ if (!TryTimeToTicks(positive, zero, raw.numbers[0], raw.numbers[1], zero, zero, out ticks)) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ if (!positive) {
+ ticks = -ticks;
+ if (ticks > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+
+ //
+ // ProcessTerminal_D
+ //
+ // Actions: Validate the 1-number "Days" terminal case
+ //
+ private static Boolean ProcessTerminal_D(ref TimeSpanRawInfo raw, TimeSpanStandardStyles style, ref TimeSpanResult result) {
+ if (raw.SepCount != 2 || raw.NumCount != 1 || (style & TimeSpanStandardStyles.RequireFull) != 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ bool inv = ((style & TimeSpanStandardStyles.Invariant) != 0);
+ bool loc = ((style & TimeSpanStandardStyles.Localized) != 0);
+
+ bool positive = false;
+ bool match = false;
+
+ if (inv) {
+ if (raw.FullDMatch(raw.PositiveInvariant)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullDMatch(raw.NegativeInvariant)) {
+ match = true;
+ positive = false;
+ }
+ }
+ if (loc) {
+ if (!match && raw.FullDMatch(raw.PositiveLocalized)) {
+ match = true;
+ positive = true;
+ }
+ if (!match && raw.FullDMatch(raw.NegativeLocalized)) {
+ match = true;
+ positive = false;
+ }
+ }
+
+ long ticks = 0;
+ if (match) {
+ if (!TryTimeToTicks(positive, raw.numbers[0], zero, zero, zero, zero, out ticks)) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ if (!positive) {
+ ticks = -ticks;
+ if (ticks > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ #endregion
+
+ #region TryParseExactTimeSpan
+ //
+ // TryParseExactTimeSpan
+ //
+ // Actions: Common private ParseExact method called by both ParseExact and TryParseExact
+ //
+ private static Boolean TryParseExactTimeSpan(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) {
+ if (input == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input");
+ return false;
+ }
+ if (format == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "format");
+ return false;
+ }
+ if (format.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier");
+ return false;
+ }
+
+ if (format.Length == 1) {
+ TimeSpanStandardStyles style = TimeSpanStandardStyles.None;
+
+ if (format[0] == 'c' || format[0] == 't' || format[0] == 'T') {
+ // fast path for legacy style TimeSpan formats.
+ return TryParseTimeSpanConstant(input, ref result);
+ }
+ else if (format[0] == 'g') {
+ style = TimeSpanStandardStyles.Localized;
+ }
+ else if (format[0] == 'G') {
+ style = TimeSpanStandardStyles.Localized | TimeSpanStandardStyles.RequireFull;
+ }
+ else {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier");
+ return false;
+ }
+ return TryParseTimeSpan(input, style, formatProvider, ref result);
+ }
+
+ return TryParseByFormat(input, format, styles, ref result);
+ }
+
+ //
+ // TryParseByFormat
+ //
+ // Actions: Parse the TimeSpan instance using the specified format. Used by TryParseExactTimeSpan.
+ //
+ private static Boolean TryParseByFormat(String input, String format, TimeSpanStyles styles, ref TimeSpanResult result) {
+ Contract.Assert(input != null, "input != null");
+ Contract.Assert(format != null, "format != null");
+
+ bool seenDD = false; // already processed days?
+ bool seenHH = false; // already processed hours?
+ bool seenMM = false; // already processed minutes?
+ bool seenSS = false; // already processed seconds?
+ bool seenFF = false; // already processed fraction?
+ int dd = 0; // parsed days
+ int hh = 0; // parsed hours
+ int mm = 0; // parsed minutes
+ int ss = 0; // parsed seconds
+ int leadingZeroes = 0; // number of leading zeroes in the parsed fraction
+ int ff = 0; // parsed fraction
+ int i = 0; // format string position
+ int tokenLen = 0; // length of current format token, used to update index 'i'
+
+ TimeSpanTokenizer tokenizer = new TimeSpanTokenizer();
+ tokenizer.Init(input, -1);
+
+ while (i < format.Length) {
+ char ch = format[i];
+ int nextFormatChar;
+ switch (ch) {
+ case 'h':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenHH || !ParseExactDigits(ref tokenizer, tokenLen, out hh)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ seenHH = true;
+ break;
+ case 'm':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenMM || !ParseExactDigits(ref tokenizer, tokenLen, out mm)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ seenMM = true;
+ break;
+ case 's':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > 2 || seenSS || !ParseExactDigits(ref tokenizer, tokenLen, out ss)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ seenSS = true;
+ break;
+ case 'f':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF || !ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ seenFF = true;
+ break;
+ case 'F':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ if (tokenLen > DateTimeFormat.MaxSecondsFractionDigits || seenFF) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ ParseExactDigits(ref tokenizer, tokenLen, tokenLen, out leadingZeroes, out ff);
+ seenFF = true;
+ break;
+ case 'd':
+ tokenLen = DateTimeFormat.ParseRepeatPattern(format, i, ch);
+ int tmp = 0;
+ if (tokenLen > 8 || seenDD || !ParseExactDigits(ref tokenizer, (tokenLen<2) ? 1 : tokenLen, (tokenLen<2) ? 8 : tokenLen, out tmp, out dd)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ seenDD = true;
+ break;
+ case '\'':
+ case '\"':
+ StringBuilder enquotedString = new StringBuilder();
+ if (!DateTimeParse.TryParseQuoteString(format, i, enquotedString, out tokenLen)) {
+ result.SetFailure(ParseFailureKind.FormatWithParameter, "Format_BadQuote", ch);
+ return false;
+ }
+ if (!ParseExactLiteral(ref tokenizer, enquotedString)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ break;
+ case '%':
+ // Optional format character.
+ // For example, format string "%d" will print day
+ // Most of the cases, "%" can be ignored.
+ nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
+ // nextFormatChar will be -1 if we already reach the end of the format string.
+ // Besides, we will not allow "%%" appear in the pattern.
+ if (nextFormatChar >= 0 && nextFormatChar != (int)'%') {
+ tokenLen = 1; // skip the '%' and process the format character
+ break;
+ }
+ else {
+ // This means that '%' is at the end of the format string or
+ // "%%" appears in the format string.
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ case '\\':
+ // Escaped character. Can be used to insert character into the format string.
+ // For example, "\d" will insert the character 'd' into the string.
+ //
+ nextFormatChar = DateTimeFormat.ParseNextChar(format, i);
+ if (nextFormatChar >= 0 && tokenizer.NextChar == (char)nextFormatChar) {
+ tokenLen = 2;
+ }
+ else {
+ // This means that '\' is at the end of the format string or the literal match failed.
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ break;
+ default:
+ result.SetFailure(ParseFailureKind.Format, "Format_InvalidString");
+ return false;
+ }
+ i += tokenLen;
+ }
+
+
+ if (!tokenizer.EOL) {
+ // the custom format didn't consume the entire input
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ long ticks = 0;
+ bool positive = (styles & TimeSpanStyles.AssumeNegative) == 0;
+ if (TryTimeToTicks(positive, new TimeSpanToken(dd),
+ new TimeSpanToken(hh),
+ new TimeSpanToken(mm),
+ new TimeSpanToken(ss),
+ new TimeSpanToken(leadingZeroes, ff),
+ out ticks)) {
+ if (!positive) ticks = -ticks;
+ result.parsedTimeSpan._ticks = ticks;
+ return true;
+ }
+ else {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+
+ }
+ }
+
+ private static Boolean ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, out int result) {
+ result = 0;
+ int zeroes = 0;
+ int maxDigitLength = (minDigitLength == 1) ? 2 : minDigitLength;
+ return ParseExactDigits(ref tokenizer, minDigitLength, maxDigitLength, out zeroes, out result);
+ }
+ private static Boolean ParseExactDigits(ref TimeSpanTokenizer tokenizer, int minDigitLength, int maxDigitLength, out int zeroes, out int result) {
+ result = 0;
+ zeroes = 0;
+
+ int tokenLength = 0;
+ while (tokenLength < maxDigitLength) {
+ char ch = tokenizer.NextChar;
+ if (ch < '0' || ch > '9') {
+ tokenizer.BackOne();
+ break;
+ }
+ result = result * 10 + (ch - '0');
+ if (result == 0) zeroes++;
+ tokenLength++;
+ }
+ return (tokenLength >= minDigitLength);
+ }
+ private static Boolean ParseExactLiteral(ref TimeSpanTokenizer tokenizer, StringBuilder enquotedString) {
+ for (int i = 0; i < enquotedString.Length; i++) {
+ if (enquotedString[i] != tokenizer.NextChar)
+ return false;
+ }
+ return true;
+ }
+ #endregion
+
+ #region TryParseTimeSpanConstant
+ //
+ // TryParseTimeSpanConstant
+ //
+ // Actions: Parses the "c" (constant) format. This code is 100% identical to the non-globalized v1.0-v3.5 TimeSpan.Parse() routine
+ // and exists for performance/appcompat with legacy callers who cannot move onto the globalized Parse overloads.
+ //
+ private static Boolean TryParseTimeSpanConstant(String input, ref TimeSpanResult result) {
+ return (new StringParser().TryParse(input, ref result));
+ }
+
+ private struct StringParser {
+ private String str;
+ private char ch;
+ private int pos;
+ private int len;
+
+ internal void NextChar() {
+ if (pos < len) pos++;
+ ch = pos < len? str[pos]: (char) 0;
+ }
+
+ internal char NextNonDigit() {
+ int i = pos;
+ while (i < len) {
+ char ch = str[i];
+ if (ch < '0' || ch > '9') return ch;
+ i++;
+ }
+ return (char) 0;
+ }
+
+ internal bool TryParse(String input, ref TimeSpanResult result) {
+ result.parsedTimeSpan._ticks = 0;
+
+ if (input == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input");
+ return false;
+ }
+ str = input;
+ len = input.Length;
+ pos = -1;
+ NextChar();
+ SkipBlanks();
+ bool negative = false;
+ if (ch == '-') {
+ negative = true;
+ NextChar();
+ }
+ long time;
+ if (NextNonDigit() == ':') {
+ if (!ParseTime(out time, ref result)) {
+ return false;
+ };
+ }
+ else {
+ int days;
+ if (!ParseInt((int)(0x7FFFFFFFFFFFFFFFL / TimeSpan.TicksPerDay), out days, ref result)) {
+ return false;
+ }
+ time = days * TimeSpan.TicksPerDay;
+ if (ch == '.') {
+ NextChar();
+ long remainingTime;
+ if (!ParseTime(out remainingTime, ref result)) {
+ return false;
+ };
+ time += remainingTime;
+ }
+ }
+ if (negative) {
+ time = -time;
+ // Allow -0 as well
+ if (time > 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ else {
+ if (time < 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ }
+ SkipBlanks();
+ if (pos < len) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ result.parsedTimeSpan._ticks = time;
+ return true;
+ }
+
+ internal bool ParseInt(int max, out int i, ref TimeSpanResult result) {
+ i = 0;
+ int p = pos;
+ while (ch >= '0' && ch <= '9') {
+ if ((i & 0xF0000000) != 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ i = i * 10 + ch - '0';
+ if (i < 0) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ NextChar();
+ }
+ if (p == pos) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ if (i > max) {
+ result.SetFailure(ParseFailureKind.Overflow, "Overflow_TimeSpanElementTooLarge");
+ return false;
+ }
+ return true;
+ }
+
+ internal bool ParseTime(out long time, ref TimeSpanResult result) {
+ time = 0;
+ int unit;
+ if (!ParseInt(23, out unit, ref result)) {
+ return false;
+ }
+ time = unit * TimeSpan.TicksPerHour;
+ if (ch != ':') {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+ NextChar();
+ if (!ParseInt(59, out unit, ref result)) {
+ return false;
+ }
+ time += unit * TimeSpan.TicksPerMinute;
+ if (ch == ':') {
+ NextChar();
+ // allow seconds with the leading zero
+ if (ch != '.') {
+ if (!ParseInt(59, out unit, ref result)) {
+ return false;
+ }
+ time += unit * TimeSpan.TicksPerSecond;
+ }
+ if (ch == '.') {
+ NextChar();
+ int f = (int)TimeSpan.TicksPerSecond;
+ while (f > 1 && ch >= '0' && ch <= '9') {
+ f /= 10;
+ time += (ch - '0') * f;
+ NextChar();
+ }
+ }
+ }
+ return true;
+ }
+
+ internal void SkipBlanks() {
+ while (ch == ' ' || ch == '\t') NextChar();
+ }
+ }
+ #endregion
+
+ #region TryParseExactMultipleTimeSpan
+ //
+ // TryParseExactMultipleTimeSpan
+ //
+ // Actions: Common private ParseExactMultiple method called by both ParseExactMultiple and TryParseExactMultiple
+ //
+ private static Boolean TryParseExactMultipleTimeSpan(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, ref TimeSpanResult result) {
+ if (input == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "input");
+ return false;
+ }
+ if (formats == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNull, "ArgumentNull_String", null, "formats");
+ return false;
+ }
+
+ if (input.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return false;
+ }
+
+ if (formats.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier");
+ return false;
+ }
+
+ //
+ // Do a loop through the provided formats and see if we can parse succesfully in
+ // one of the formats.
+ //
+ for (int i = 0; i < formats.Length; i++) {
+ if (formats[i] == null || formats[i].Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_BadFormatSpecifier");
+ return false;
+ }
+
+ // Create a new non-throwing result each time to ensure the runs are independent.
+ TimeSpanResult innerResult = new TimeSpanResult();
+ innerResult.Init(TimeSpanThrowStyle.None);
+
+ if(TryParseExactTimeSpan(input, formats[i], formatProvider, styles, ref innerResult)) {
+ result.parsedTimeSpan = innerResult.parsedTimeSpan;
+ return true;
+ }
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_BadTimeSpan");
+ return (false);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/TimeSpanStyles.cs b/src/mscorlib/src/System/Globalization/TimeSpanStyles.cs
new file mode 100644
index 0000000000..7ba5327324
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/TimeSpanStyles.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+
+ [Flags]
+ public enum TimeSpanStyles {
+ None = 0x00000000,
+ AssumeNegative = 0x00000001,
+ }
+}
diff --git a/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs
new file mode 100644
index 0000000000..94b235085e
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/UmAlQuraCalendar.cs
@@ -0,0 +1,849 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Globalization {
+ using System;
+ using System.Diagnostics.Contracts;
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Notes about UmAlQuraCalendar
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /*
+ ** Calendar support range:
+ ** Calendar Minimum Maximum
+ ** ========== ========== ==========
+ ** Gregorian 1900/04/30 2077/11/17
+ ** UmAlQura 1318/01/01 1500/12/30
+ */
+
+ [Serializable]
+ public class UmAlQuraCalendar : Calendar {
+
+ internal const int MinCalendarYear = 1318;
+ internal const int MaxCalendarYear = 1500;
+
+ internal struct DateMapping
+ {
+ internal DateMapping(int MonthsLengthFlags, int GYear, int GMonth, int GDay)
+ {
+ HijriMonthsLengthFlags = MonthsLengthFlags;
+ GregorianDate = new DateTime(GYear, GMonth, GDay);
+ }
+ internal int HijriMonthsLengthFlags;
+ internal DateTime GregorianDate;
+ }
+
+ static readonly DateMapping [] HijriYearInfo = InitDateMapping();
+
+ static DateMapping[] InitDateMapping()
+ {
+ short[] rawData = new short[] {
+//These data is taken from Tables/Excel/UmAlQura.xls please make sure that the two places are in sync
+/* DaysPerM GY GM GD D1 D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12
+1318*/0x02EA, 1900, 4, 30,/* 0 1 0 1 0 1 1 1 0 1 0 0 4/30/1900
+1319*/0x06E9, 1901, 4, 19,/* 1 0 0 1 0 1 1 1 0 1 1 0 4/19/1901
+1320*/0x0ED2, 1902, 4, 9,/* 0 1 0 0 1 0 1 1 0 1 1 1 4/9/1902
+1321*/0x0EA4, 1903, 3, 30,/* 0 0 1 0 0 1 0 1 0 1 1 1 3/30/1903
+1322*/0x0D4A, 1904, 3, 18,/* 0 1 0 1 0 0 1 0 1 0 1 1 3/18/1904
+1323*/0x0A96, 1905, 3, 7,/* 0 1 1 0 1 0 0 1 0 1 0 1 3/7/1905
+1324*/0x0536, 1906, 2, 24,/* 0 1 1 0 1 1 0 0 1 0 1 0 2/24/1906
+1325*/0x0AB5, 1907, 2, 13,/* 1 0 1 0 1 1 0 1 0 1 0 1 2/13/1907
+1326*/0x0DAA, 1908, 2, 3,/* 0 1 0 1 0 1 0 1 1 0 1 1 2/3/1908
+1327*/0x0BA4, 1909, 1, 23,/* 0 0 1 0 0 1 0 1 1 1 0 1 1/23/1909
+1328*/0x0B49, 1910, 1, 12,/* 1 0 0 1 0 0 1 0 1 1 0 1 1/12/1910
+1329*/0x0A93, 1911, 1, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 1/1/1911
+1330*/0x052B, 1911, 12, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 12/21/1911
+1331*/0x0A57, 1912, 12, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 12/9/1912
+1332*/0x04B6, 1913, 11, 29,/* 0 1 1 0 1 1 0 1 0 0 1 0 11/29/1913
+1333*/0x0AB5, 1914, 11, 18,/* 1 0 1 0 1 1 0 1 0 1 0 1 11/18/1914
+1334*/0x05AA, 1915, 11, 8,/* 0 1 0 1 0 1 0 1 1 0 1 0 11/8/1915
+1335*/0x0D55, 1916, 10, 27,/* 1 0 1 0 1 0 1 0 1 0 1 1 10/27/1916
+1336*/0x0D2A, 1917, 10, 17,/* 0 1 0 1 0 1 0 0 1 0 1 1 10/17/1917
+1337*/0x0A56, 1918, 10, 6,/* 0 1 1 0 1 0 1 0 0 1 0 1 10/6/1918
+1338*/0x04AE, 1919, 9, 25,/* 0 1 1 1 0 1 0 1 0 0 1 0 9/25/1919
+1339*/0x095D, 1920, 9, 13,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/13/1920
+1340*/0x02EC, 1921, 9, 3,/* 0 0 1 1 0 1 1 1 0 1 0 0 9/3/1921
+1341*/0x06D5, 1922, 8, 23,/* 1 0 1 0 1 0 1 1 0 1 1 0 8/23/1922
+1342*/0x06AA, 1923, 8, 13,/* 0 1 0 1 0 1 0 1 0 1 1 0 8/13/1923
+1343*/0x0555, 1924, 8, 1,/* 1 0 1 0 1 0 1 0 1 0 1 0 8/1/1924
+1344*/0x04AB, 1925, 7, 21,/* 1 1 0 1 0 1 0 1 0 0 1 0 7/21/1925
+1345*/0x095B, 1926, 7, 10,/* 1 1 0 1 1 0 1 0 1 0 0 1 7/10/1926
+1346*/0x02BA, 1927, 6, 30,/* 0 1 0 1 1 1 0 1 0 1 0 0 6/30/1927
+1347*/0x0575, 1928, 6, 18,/* 1 0 1 0 1 1 1 0 1 0 1 0 6/18/1928
+1348*/0x0BB2, 1929, 6, 8,/* 0 1 0 0 1 1 0 1 1 1 0 1 6/8/1929
+1349*/0x0764, 1930, 5, 29,/* 0 0 1 0 0 1 1 0 1 1 1 0 5/29/1930
+1350*/0x0749, 1931, 5, 18,/* 1 0 0 1 0 0 1 0 1 1 1 0 5/18/1931
+1351*/0x0655, 1932, 5, 6,/* 1 0 1 0 1 0 1 0 0 1 1 0 5/6/1932
+1352*/0x02AB, 1933, 4, 25,/* 1 1 0 1 0 1 0 1 0 1 0 0 4/25/1933
+1353*/0x055B, 1934, 4, 14,/* 1 1 0 1 1 0 1 0 1 0 1 0 4/14/1934
+1354*/0x0ADA, 1935, 4, 4,/* 0 1 0 1 1 0 1 1 0 1 0 1 4/4/1935
+1355*/0x06D4, 1936, 3, 24,/* 0 0 1 0 1 0 1 1 0 1 1 0 3/24/1936
+1356*/0x0EC9, 1937, 3, 13,/* 1 0 0 1 0 0 1 1 0 1 1 1 3/13/1937
+1357*/0x0D92, 1938, 3, 3,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/3/1938
+1358*/0x0D25, 1939, 2, 20,/* 1 0 1 0 0 1 0 0 1 0 1 1 2/20/1939
+1359*/0x0A4D, 1940, 2, 9,/* 1 0 1 1 0 0 1 0 0 1 0 1 2/9/1940
+1360*/0x02AD, 1941, 1, 28,/* 1 0 1 1 0 1 0 1 0 1 0 0 1/28/1941
+1361*/0x056D, 1942, 1, 17,/* 1 0 1 1 0 1 1 0 1 0 1 0 1/17/1942
+1362*/0x0B6A, 1943, 1, 7,/* 0 1 0 1 0 1 1 0 1 1 0 1 1/7/1943
+1363*/0x0B52, 1943, 12, 28,/* 0 1 0 0 1 0 1 0 1 1 0 1 12/28/1943
+1364*/0x0AA5, 1944, 12, 16,/* 1 0 1 0 0 1 0 1 0 1 0 1 12/16/1944
+1365*/0x0A4B, 1945, 12, 5,/* 1 1 0 1 0 0 1 0 0 1 0 1 12/5/1945
+1366*/0x0497, 1946, 11, 24,/* 1 1 1 0 1 0 0 1 0 0 1 0 11/24/1946
+1367*/0x0937, 1947, 11, 13,/* 1 1 1 0 1 1 0 0 1 0 0 1 11/13/1947
+1368*/0x02B6, 1948, 11, 2,/* 0 1 1 0 1 1 0 1 0 1 0 0 11/2/1948
+1369*/0x0575, 1949, 10, 22,/* 1 0 1 0 1 1 1 0 1 0 1 0 10/22/1949
+1370*/0x0D6A, 1950, 10, 12,/* 0 1 0 1 0 1 1 0 1 0 1 1 10/12/1950
+1371*/0x0D52, 1951, 10, 2,/* 0 1 0 0 1 0 1 0 1 0 1 1 10/2/1951
+1372*/0x0A96, 1952, 9, 20,/* 0 1 1 0 1 0 0 1 0 1 0 1 9/20/1952
+1373*/0x092D, 1953, 9, 9,/* 1 0 1 1 0 1 0 0 1 0 0 1 9/9/1953
+1374*/0x025D, 1954, 8, 29,/* 1 0 1 1 1 0 1 0 0 1 0 0 8/29/1954
+1375*/0x04DD, 1955, 8, 18,/* 1 0 1 1 1 0 1 1 0 0 1 0 8/18/1955
+1376*/0x0ADA, 1956, 8, 7,/* 0 1 0 1 1 0 1 1 0 1 0 1 8/7/1956
+1377*/0x05D4, 1957, 7, 28,/* 0 0 1 0 1 0 1 1 1 0 1 0 7/28/1957
+1378*/0x0DA9, 1958, 7, 17,/* 1 0 0 1 0 1 0 1 1 0 1 1 7/17/1958
+1379*/0x0D52, 1959, 7, 7,/* 0 1 0 0 1 0 1 0 1 0 1 1 7/7/1959
+1380*/0x0AAA, 1960, 6, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 6/25/1960
+1381*/0x04D6, 1961, 6, 14,/* 0 1 1 0 1 0 1 1 0 0 1 0 6/14/1961
+1382*/0x09B6, 1962, 6, 3,/* 0 1 1 0 1 1 0 1 1 0 0 1 6/3/1962
+1383*/0x0374, 1963, 5, 24,/* 0 0 1 0 1 1 1 0 1 1 0 0 5/24/1963
+1384*/0x0769, 1964, 5, 12,/* 1 0 0 1 0 1 1 0 1 1 1 0 5/12/1964
+1385*/0x0752, 1965, 5, 2,/* 0 1 0 0 1 0 1 0 1 1 1 0 5/2/1965
+1386*/0x06A5, 1966, 4, 21,/* 1 0 1 0 0 1 0 1 0 1 1 0 4/21/1966
+1387*/0x054B, 1967, 4, 10,/* 1 1 0 1 0 0 1 0 1 0 1 0 4/10/1967
+1388*/0x0AAB, 1968, 3, 29,/* 1 1 0 1 0 1 0 1 0 1 0 1 3/29/1968
+1389*/0x055A, 1969, 3, 19,/* 0 1 0 1 1 0 1 0 1 0 1 0 3/19/1969
+1390*/0x0AD5, 1970, 3, 8,/* 1 0 1 0 1 0 1 1 0 1 0 1 3/8/1970
+1391*/0x0DD2, 1971, 2, 26,/* 0 1 0 0 1 0 1 1 1 0 1 1 2/26/1971
+1392*/0x0DA4, 1972, 2, 16,/* 0 0 1 0 0 1 0 1 1 0 1 1 2/16/1972
+1393*/0x0D49, 1973, 2, 4,/* 1 0 0 1 0 0 1 0 1 0 1 1 2/4/1973
+1394*/0x0A95, 1974, 1, 24,/* 1 0 1 0 1 0 0 1 0 1 0 1 1/24/1974
+1395*/0x052D, 1975, 1, 13,/* 1 0 1 1 0 1 0 0 1 0 1 0 1/13/1975
+1396*/0x0A5D, 1976, 1, 2,/* 1 0 1 1 1 0 1 0 0 1 0 1 1/2/1976
+1397*/0x055A, 1976, 12, 22,/* 0 1 0 1 1 0 1 0 1 0 1 0 12/22/1976
+1398*/0x0AD5, 1977, 12, 11,/* 1 0 1 0 1 0 1 1 0 1 0 1 12/11/1977
+1399*/0x06AA, 1978, 12, 1,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/1/1978
+1400*/0x0695, 1979, 11, 20,/* 1 0 1 0 1 0 0 1 0 1 1 0 11/20/1979
+1401*/0x052B, 1980, 11, 8,/* 1 1 0 1 0 1 0 0 1 0 1 0 11/8/1980
+1402*/0x0A57, 1981, 10, 28,/* 1 1 1 0 1 0 1 0 0 1 0 1 10/28/1981
+1403*/0x04AE, 1982, 10, 18,/* 0 1 1 1 0 1 0 1 0 0 1 0 10/18/1982
+1404*/0x0976, 1983, 10, 7,/* 0 1 1 0 1 1 1 0 1 0 0 1 10/7/1983
+1405*/0x056C, 1984, 9, 26,/* 0 0 1 1 0 1 1 0 1 0 1 0 9/26/1984
+1406*/0x0B55, 1985, 9, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 9/15/1985
+1407*/0x0AAA, 1986, 9, 5,/* 0 1 0 1 0 1 0 1 0 1 0 1 9/5/1986
+1408*/0x0A55, 1987, 8, 25,/* 1 0 1 0 1 0 1 0 0 1 0 1 8/25/1987
+1409*/0x04AD, 1988, 8, 13,/* 1 0 1 1 0 1 0 1 0 0 1 0 8/13/1988
+1410*/0x095D, 1989, 8, 2,/* 1 0 1 1 1 0 1 0 1 0 0 1 8/2/1989
+1411*/0x02DA, 1990, 7, 23,/* 0 1 0 1 1 0 1 1 0 1 0 0 7/23/1990
+1412*/0x05D9, 1991, 7, 12,/* 1 0 0 1 1 0 1 1 1 0 1 0 7/12/1991
+1413*/0x0DB2, 1992, 7, 1,/* 0 1 0 0 1 1 0 1 1 0 1 1 7/1/1992
+1414*/0x0BA4, 1993, 6, 21,/* 0 0 1 0 0 1 0 1 1 1 0 1 6/21/1993
+1415*/0x0B4A, 1994, 6, 10,/* 0 1 0 1 0 0 1 0 1 1 0 1 6/10/1994
+1416*/0x0A55, 1995, 5, 30,/* 1 0 1 0 1 0 1 0 0 1 0 1 5/30/1995
+1417*/0x02B5, 1996, 5, 18,/* 1 0 1 0 1 1 0 1 0 1 0 0 5/18/1996
+1418*/0x0575, 1997, 5, 7,/* 1 0 1 0 1 1 1 0 1 0 1 0 5/7/1997
+1419*/0x0B6A, 1998, 4, 27,/* 0 1 0 1 0 1 1 0 1 1 0 1 4/27/1998
+1420*/0x0BD2, 1999, 4, 17,/* 0 1 0 0 1 0 1 1 1 1 0 1 4/17/1999
+1421*/0x0BC4, 2000, 4, 6,/* 0 0 1 0 0 0 1 1 1 1 0 1 4/6/2000
+1422*/0x0B89, 2001, 3, 26,/* 1 0 0 1 0 0 0 1 1 1 0 1 3/26/2001
+1423*/0x0A95, 2002, 3, 15,/* 1 0 1 0 1 0 0 1 0 1 0 1 3/15/2002
+1424*/0x052D, 2003, 3, 4,/* 1 0 1 1 0 1 0 0 1 0 1 0 3/4/2003
+1425*/0x05AD, 2004, 2, 21,/* 1 0 1 1 0 1 0 1 1 0 1 0 2/21/2004
+1426*/0x0B6A, 2005, 2, 10,/* 0 1 0 1 0 1 1 0 1 1 0 1 2/10/2005
+1427*/0x06D4, 2006, 1, 31,/* 0 0 1 0 1 0 1 1 0 1 1 0 1/31/2006
+1428*/0x0DC9, 2007, 1, 20,/* 1 0 0 1 0 0 1 1 1 0 1 1 1/20/2007
+1429*/0x0D92, 2008, 1, 10,/* 0 1 0 0 1 0 0 1 1 0 1 1 1/10/2008
+1430*/0x0AA6, 2008, 12, 29,/* 0 1 1 0 0 1 0 1 0 1 0 1 12/29/2008
+1431*/0x0956, 2009, 12, 18,/* 0 1 1 0 1 0 1 0 1 0 0 1 12/18/2009
+1432*/0x02AE, 2010, 12, 7,/* 0 1 1 1 0 1 0 1 0 1 0 0 12/7/2010
+1433*/0x056D, 2011, 11, 26,/* 1 0 1 1 0 1 1 0 1 0 1 0 11/26/2011
+1434*/0x036A, 2012, 11, 15,/* 0 1 0 1 0 1 1 0 1 1 0 0 11/15/2012
+1435*/0x0B55, 2013, 11, 4,/* 1 0 1 0 1 0 1 0 1 1 0 1 11/4/2013
+1436*/0x0AAA, 2014, 10, 25,/* 0 1 0 1 0 1 0 1 0 1 0 1 10/25/2014
+1437*/0x094D, 2015, 10, 14,/* 1 0 1 1 0 0 1 0 1 0 0 1 10/14/2015
+1438*/0x049D, 2016, 10, 2,/* 1 0 1 1 1 0 0 1 0 0 1 0 10/2/2016
+1439*/0x095D, 2017, 9, 21,/* 1 0 1 1 1 0 1 0 1 0 0 1 9/21/2017
+1440*/0x02BA, 2018, 9, 11,/* 0 1 0 1 1 1 0 1 0 1 0 0 9/11/2018
+1441*/0x05B5, 2019, 8, 31,/* 1 0 1 0 1 1 0 1 1 0 1 0 8/31/2019
+1442*/0x05AA, 2020, 8, 20,/* 0 1 0 1 0 1 0 1 1 0 1 0 8/20/2020
+1443*/0x0D55, 2021, 8, 9,/* 1 0 1 0 1 0 1 0 1 0 1 1 8/9/2021
+1444*/0x0A9A, 2022, 7, 30,/* 0 1 0 1 1 0 0 1 0 1 0 1 7/30/2022
+1445*/0x092E, 2023, 7, 19,/* 0 1 1 1 0 1 0 0 1 0 0 1 7/19/2023
+1446*/0x026E, 2024, 7, 7,/* 0 1 1 1 0 1 1 0 0 1 0 0 7/7/2024
+1447*/0x055D, 2025, 6, 26,/* 1 0 1 1 1 0 1 0 1 0 1 0 6/26/2025
+1448*/0x0ADA, 2026, 6, 16,/* 0 1 0 1 1 0 1 1 0 1 0 1 6/16/2026
+1449*/0x06D4, 2027, 6, 6,/* 0 0 1 0 1 0 1 1 0 1 1 0 6/6/2027
+1450*/0x06A5, 2028, 5, 25,/* 1 0 1 0 0 1 0 1 0 1 1 0 5/25/2028
+1451*/0x054B, 2029, 5, 14,/* 1 1 0 1 0 0 1 0 1 0 1 0 5/14/2029
+1452*/0x0A97, 2030, 5, 3,/* 1 1 1 0 1 0 0 1 0 1 0 1 5/3/2030
+1453*/0x054E, 2031, 4, 23,/* 0 1 1 1 0 0 1 0 1 0 1 0 4/23/2031
+1454*/0x0AAE, 2032, 4, 11,/* 0 1 1 1 0 1 0 1 0 1 0 1 4/11/2032
+1455*/0x05AC, 2033, 4, 1,/* 0 0 1 1 0 1 0 1 1 0 1 0 4/1/2033
+1456*/0x0BA9, 2034, 3, 21,/* 1 0 0 1 0 1 0 1 1 1 0 1 3/21/2034
+1457*/0x0D92, 2035, 3, 11,/* 0 1 0 0 1 0 0 1 1 0 1 1 3/11/2035
+1458*/0x0B25, 2036, 2, 28,/* 1 0 1 0 0 1 0 0 1 1 0 1 2/28/2036
+1459*/0x064B, 2037, 2, 16,/* 1 1 0 1 0 0 1 0 0 1 1 0 2/16/2037
+1460*/0x0CAB, 2038, 2, 5,/* 1 1 0 1 0 1 0 1 0 0 1 1 2/5/2038
+1461*/0x055A, 2039, 1, 26,/* 0 1 0 1 1 0 1 0 1 0 1 0 1/26/2039
+1462*/0x0B55, 2040, 1, 15,/* 1 0 1 0 1 0 1 0 1 1 0 1 1/15/2040
+1463*/0x06D2, 2041, 1, 4,/* 0 1 0 0 1 0 1 1 0 1 1 0 1/4/2041
+1464*/0x0EA5, 2041, 12, 24,/* 1 0 1 0 0 1 0 1 0 1 1 1 12/24/2041
+1465*/0x0E4A, 2042, 12, 14,/* 0 1 0 1 0 0 1 0 0 1 1 1 12/14/2042
+1466*/0x0A95, 2043, 12, 3,/* 1 0 1 0 1 0 0 1 0 1 0 1 12/3/2043
+1467*/0x052D, 2044, 11, 21,/* 1 0 1 1 0 1 0 0 1 0 1 0 11/21/2044
+1468*/0x0AAD, 2045, 11, 10,/* 1 0 1 1 0 1 0 1 0 1 0 1 11/10/2045
+1469*/0x036C, 2046, 10, 31,/* 0 0 1 1 0 1 1 0 1 1 0 0 10/31/2046
+1470*/0x0759, 2047, 10, 20,/* 1 0 0 1 1 0 1 0 1 1 1 0 10/20/2047
+1471*/0x06D2, 2048, 10, 9,/* 0 1 0 0 1 0 1 1 0 1 1 0 10/9/2048
+1472*/0x0695, 2049, 9, 28,/* 1 0 1 0 1 0 0 1 0 1 1 0 9/28/2049
+1473*/0x052D, 2050, 9, 17,/* 1 0 1 1 0 1 0 0 1 0 1 0 9/17/2050
+1474*/0x0A5B, 2051, 9, 6,/* 1 1 0 1 1 0 1 0 0 1 0 1 9/6/2051
+1475*/0x04BA, 2052, 8, 26,/* 0 1 0 1 1 1 0 1 0 0 1 0 8/26/2052
+1476*/0x09BA, 2053, 8, 15,/* 0 1 0 1 1 1 0 1 1 0 0 1 8/15/2053
+1477*/0x03B4, 2054, 8, 5,/* 0 0 1 0 1 1 0 1 1 1 0 0 8/5/2054
+1478*/0x0B69, 2055, 7, 25,/* 1 0 0 1 0 1 1 0 1 1 0 1 7/25/2055
+1479*/0x0B52, 2056, 7, 14,/* 0 1 0 0 1 0 1 0 1 1 0 1 7/14/2056
+1480*/0x0AA6, 2057, 7, 3,/* 0 1 1 0 0 1 0 1 0 1 0 1 7/3/2057
+1481*/0x04B6, 2058, 6, 22,/* 0 1 1 0 1 1 0 1 0 0 1 0 6/22/2058
+1482*/0x096D, 2059, 6, 11,/* 1 0 1 1 0 1 1 0 1 0 0 1 6/11/2059
+1483*/0x02EC, 2060, 5, 31,/* 0 0 1 1 0 1 1 1 0 1 0 0 5/31/2060
+1484*/0x06D9, 2061, 5, 20,/* 1 0 0 1 1 0 1 1 0 1 1 0 5/20/2061
+1485*/0x0EB2, 2062, 5, 10,/* 0 1 0 0 1 1 0 1 0 1 1 1 5/10/2062
+1486*/0x0D54, 2063, 4, 30,/* 0 0 1 0 1 0 1 0 1 0 1 1 4/30/2063
+1487*/0x0D2A, 2064, 4, 18,/* 0 1 0 1 0 1 0 0 1 0 1 1 4/18/2064
+1488*/0x0A56, 2065, 4, 7,/* 0 1 1 0 1 0 1 0 0 1 0 1 4/7/2065
+1489*/0x04AE, 2066, 3, 27,/* 0 1 1 1 0 1 0 1 0 0 1 0 3/27/2066
+1490*/0x096D, 2067, 3, 16,/* 1 0 1 1 0 1 1 0 1 0 0 1 3/16/2067
+1491*/0x0D6A, 2068, 3, 5,/* 0 1 0 1 0 1 1 0 1 0 1 1 3/5/2068
+1492*/0x0B54, 2069, 2, 23,/* 0 0 1 0 1 0 1 0 1 1 0 1 2/23/2069
+1493*/0x0B29, 2070, 2, 12,/* 1 0 0 1 0 1 0 0 1 1 0 1 2/12/2070
+1494*/0x0A93, 2071, 2, 1,/* 1 1 0 0 1 0 0 1 0 1 0 1 2/1/2071
+1495*/0x052B, 2072, 1, 21,/* 1 1 0 1 0 1 0 0 1 0 1 0 1/21/2072
+1496*/0x0A57, 2073, 1, 9,/* 1 1 1 0 1 0 1 0 0 1 0 1 1/9/2073
+1497*/0x0536, 2073, 12, 30,/* 0 1 1 0 1 1 0 0 1 0 1 0 12/30/2073
+1498*/0x0AB5, 2074, 12, 19,/* 1 0 1 0 1 1 0 1 0 1 0 1 12/19/2074
+1499*/0x06AA, 2075, 12, 9,/* 0 1 0 1 0 1 0 1 0 1 1 0 12/9/2075
+1500*/0x0E93, 2076, 11, 27,/* 1 1 0 0 1 0 0 1 0 1 1 1 11/27/2076
+1501*/ 0, 2077, 11, 17,/* 0 0 0 0 0 0 0 0 0 0 0 0 11/17/2077
+
+*/ };
+
+ // Direct inline initialization of DateMapping array would produce a lot of code bloat.
+
+ // We take advantage of C# compiler compiles inline initialization of primitive type array into very compact code.
+ // So we start with raw data stored in primitive type array, and initialize the DateMapping out of it
+
+ DateMapping[] mapping = new DateMapping[rawData.Length / 4];
+ for (int i = 0; i < mapping.Length; i++)
+ mapping[i] = new DateMapping(rawData[i * 4], rawData[i * 4 + 1], rawData[i * 4 + 2], rawData[i * 4 + 3]);
+ return mapping;
+ }
+
+ public const int UmAlQuraEra = 1;
+
+ internal const int DateCycle = 30;
+ internal const int DatePartYear = 0;
+ internal const int DatePartDayOfYear = 1;
+ internal const int DatePartMonth = 2;
+ internal const int DatePartDay = 3;
+
+ //internal static Calendar m_defaultInstance;
+
+
+ // This is the minimal Gregorian date that we support in the UmAlQuraCalendar.
+ internal static DateTime minDate = new DateTime(1900, 4, 30);
+ internal static DateTime maxDate = new DateTime((new DateTime(2077, 11, 16, 23, 59, 59, 999)).Ticks + 9999);
+
+ /*=================================GetDefaultInstance==========================
+ **Action: Internal method to provide a default intance of UmAlQuraCalendar. Used by NLS+ implementation
+ ** and other calendars.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ /*
+ internal static Calendar GetDefaultInstance() {
+ if (m_defaultInstance == null) {
+ m_defaultInstance = new UmAlQuraCalendar();
+ }
+ return (m_defaultInstance);
+ }
+ */
+
+
+
+ public override DateTime MinSupportedDateTime
+ {
+ get
+ {
+ return (minDate);
+ }
+ }
+
+
+ public override DateTime MaxSupportedDateTime
+ {
+ get
+ {
+ return (maxDate);
+ }
+ }
+
+
+ // Return the type of the UmAlQura calendar.
+ //
+
+
+ public override CalendarAlgorithmType AlgorithmType {
+ get {
+ return CalendarAlgorithmType.LunarCalendar;
+ }
+ }
+
+ // Construct an instance of UmAlQura calendar.
+
+ public UmAlQuraCalendar() {
+ }
+
+ internal override int BaseCalendarID {
+ get {
+ return (CAL_HIJRI);
+ }
+ }
+
+ internal override int ID {
+ get {
+ return (CAL_UMALQURA);
+ }
+ }
+
+ protected override int DaysInYearBeforeMinSupportedYear
+ {
+ get
+ {
+ // HijriCalendar has same number of days as UmAlQuraCalendar for any given year
+ // HijriCalendar says year 1317 has 355 days.
+ return 355;
+ }
+ }
+
+ /*==========================ConvertHijriToGregorian==========================
+ ** Purpose: convert Hdate(year,month,day) to Gdate(year,month,day)
+ ** Arguments:
+ ** Input: Hijrah date: year:HijriYear, month:HijriMonth, day:HijriDay
+ ** Output: Gregorian date: year:yg, month:mg, day:dg
+ =========================ConvertHijriToGregorian============================*/
+ static void ConvertHijriToGregorian(int HijriYear, int HijriMonth, int HijriDay, ref int yg, ref int mg, ref int dg)
+ {
+ Contract.Assert( (HijriYear >= MinCalendarYear) && (HijriYear <= MaxCalendarYear), "Hijri year is out of range.");
+ Contract.Assert( HijriMonth >= 1, "Hijri month is out of range.");
+ Contract.Assert( HijriDay >= 1, "Hijri day is out of range.");
+ int index, b, nDays = HijriDay-1;
+ DateTime dt;
+
+
+ index = HijriYear - MinCalendarYear;
+ dt = HijriYearInfo[index].GregorianDate;
+
+
+ b = HijriYearInfo[index].HijriMonthsLengthFlags;
+
+ for(int m = 1; m < HijriMonth; m++)
+ {
+ nDays += 29 + (b & 0x1);
+ b = b >> 1;
+ }
+
+ dt = dt.AddDays(nDays);
+ yg = dt.Year;
+ mg = dt.Month;
+ dg = dt.Day;
+ }
+
+ /*=================================GetAbsoluteDateUmAlQura==========================
+ **Action: Gets the Absolute date for the given UmAlQura date. The absolute date means
+ ** the number of days from January 1st, 1 A.D.
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ============================================================================*/
+ static long GetAbsoluteDateUmAlQura(int year, int month, int day) {
+ //Caller should check the validaty of year, month and day.
+
+ int yg=0,mg=0,dg=0;
+ ConvertHijriToGregorian(year, month, day, ref yg, ref mg, ref dg);
+ return GregorianCalendar.GetAbsoluteDate(yg,mg,dg);
+ }
+
+ static internal void CheckTicksRange(long ticks) {
+ if (ticks < minDate.Ticks || ticks > maxDate.Ticks) {
+ throw new ArgumentOutOfRangeException(
+ "time",
+ String.Format(
+ CultureInfo.InvariantCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_CalendarRange"),
+ minDate,
+ maxDate));
+ }
+ }
+
+ static internal void CheckEraRange(int era) {
+ if (era != CurrentEra && era != UmAlQuraEra) {
+ throw new ArgumentOutOfRangeException("era", Environment.GetResourceString("ArgumentOutOfRange_InvalidEraValue"));
+ }
+ }
+
+ static internal void CheckYearRange(int year, int era) {
+ CheckEraRange(era);
+ if (year < MinCalendarYear || year > MaxCalendarYear) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ }
+
+ static internal void CheckYearMonthRange(int year, int month, int era) {
+ CheckYearRange(year, era);
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_Month"));
+ }
+ }
+
+ /*========================ConvertGregorianToHijri============================
+ ** Purpose: convert DateTime to Hdate(year,month,day)
+ ** Arguments:
+ ** Input: DateTime
+ ** Output: Hijrah date: year:HijriYear, month:HijriMonth, day:HijriDay
+ ============================================================================*/
+ static void ConvertGregorianToHijri(DateTime time, ref int HijriYear, ref int HijriMonth, ref int HijriDay)
+ {
+
+ int index, b, DaysPerThisMonth;
+ double nDays;
+ TimeSpan ts;
+ int yh1=0, mh1=0, dh1=0;
+
+ Contract.Assert((time.Ticks >= minDate.Ticks) && (time.Ticks <= maxDate.Ticks), "Gregorian date is out of range.");
+
+ // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo.
+ // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index.
+
+ index = (int)((time.Ticks - minDate.Ticks) / Calendar.TicksPerDay) / 355;
+ do
+ {
+ } while (time.CompareTo(HijriYearInfo[++index].GregorianDate)>0); //while greater
+
+ if (time.CompareTo(HijriYearInfo[index].GregorianDate) != 0)
+ {
+ index--;
+ }
+
+ ts = time.Subtract(HijriYearInfo[index].GregorianDate);
+ yh1 = index + MinCalendarYear;
+
+ mh1 = 1;
+ dh1 = 1;
+ nDays = ts.TotalDays;
+ b = HijriYearInfo[index].HijriMonthsLengthFlags;
+ DaysPerThisMonth = 29 + (b&1);
+
+ while (nDays >= DaysPerThisMonth)
+ {
+ nDays -= DaysPerThisMonth;
+ b = b >> 1;
+ DaysPerThisMonth = 29 + (b&1);
+ mh1++;
+ }
+ dh1 += (int)nDays;
+
+ HijriDay = dh1;
+ HijriMonth = mh1;
+ HijriYear = yh1;
+ }
+
+ /*=================================GetDatePart==========================
+ **Action: Returns a given date part of this <i>DateTime</i>. This method is used
+ ** to compute the year, day-of-year, month, or day part.
+ **Returns:
+ **Arguments:
+ **Exceptions: ArgumentException if part is incorrect.
+ **Notes:
+ ** First, we get the absolute date (the number of days from January 1st, 1 A.C) for the given ticks.
+ ** Use the formula (((AbsoluteDate - 226894) * 33) / (33 * 365 + 8)) + 1, we can a rough value for the UmAlQura year.
+ ** In order to get the exact UmAlQura year, we compare the exact absolute date for UmAlQuraYear and (UmAlQuraYear + 1).
+ ** From here, we can get the correct UmAlQura year.
+ ============================================================================*/
+
+ internal virtual int GetDatePart(DateTime time, int part) {
+ int UmAlQuraYear=0; // UmAlQura year
+ int UmAlQuraMonth=0; // UmAlQura month
+ int UmAlQuraDay=0; // UmAlQura day
+ long ticks = time.Ticks;
+ CheckTicksRange(ticks);
+
+ ConvertGregorianToHijri(time, ref UmAlQuraYear, ref UmAlQuraMonth, ref UmAlQuraDay);
+
+ if (part == DatePartYear)
+ return (UmAlQuraYear);
+
+ if (part == DatePartMonth)
+ return (UmAlQuraMonth);
+
+ if (part == DatePartDay)
+ return (UmAlQuraDay);
+
+ if (part == DatePartDayOfYear)
+ return (int)(GetAbsoluteDateUmAlQura(UmAlQuraYear, UmAlQuraMonth, UmAlQuraDay) - GetAbsoluteDateUmAlQura(UmAlQuraYear, 1, 1) + 1);
+
+ // Incorrect part value.
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DateTimeParsing"));
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // months to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year and month parts of the specified DateTime by
+ // value months, and, if required, adjusting the day part of the
+ // resulting date downwards to the last day of the resulting month in the
+ // resulting year. The time-of-day part of the result is the same as the
+ // time-of-day part of the specified DateTime.
+ //
+ // In more precise terms, considering the specified DateTime to be of the
+ // form y / m / d + t, where y is the
+ // year, m is the month, d is the day, and t is the
+ // time-of-day, the result is y1 / m1 / d1 + t,
+ // where y1 and m1 are computed by adding value months
+ // to y and m, and d1 is the largest value less than
+ // or equal to d that denotes a valid day in month m1 of year
+ // y1.
+ //
+
+
+ public override DateTime AddMonths(DateTime time, int months) {
+ if (months < -120000 || months > 120000) {
+ throw new ArgumentOutOfRangeException(
+ "months",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ -120000,
+ 120000));
+ }
+ Contract.EndContractBlock();
+ // Get the date in UmAlQura calendar.
+ int y = GetDatePart(time, DatePartYear);
+ int m = GetDatePart(time, DatePartMonth);
+ int d = GetDatePart(time, DatePartDay);
+ int i = m - 1 + months;
+
+ if (i >= 0) {
+ m = i % 12 + 1;
+ y = y + i / 12;
+ } else {
+ m = 12 + (i + 1) % 12;
+ y = y + (i - 11) / 12;
+ }
+
+ if (d>29)
+ {
+ int days = GetDaysInMonth(y, m);
+ if (d > days) {
+ d = days;
+ }
+ }
+ CheckYearRange(y, UmAlQuraEra);
+ DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay);
+ Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime);
+ return (dt);
+ }
+
+ // Returns the DateTime resulting from adding the given number of
+ // years to the specified DateTime. The result is computed by incrementing
+ // (or decrementing) the year part of the specified DateTime by value
+ // years. If the month and day of the specified DateTime is 2/29, and if the
+ // resulting year is not a leap year, the month and day of the resulting
+ // DateTime becomes 2/28. Otherwise, the month, day, and time-of-day
+ // parts of the result are the same as those of the specified DateTime.
+ //
+
+
+ public override DateTime AddYears(DateTime time, int years) {
+ return (AddMonths(time, years * 12));
+ }
+
+ // Returns the day-of-month part of the specified DateTime. The returned
+ // value is an integer between 1 and 31.
+ //
+
+
+ public override int GetDayOfMonth(DateTime time) {
+ return (GetDatePart(time, DatePartDay));
+ }
+
+ // Returns the day-of-week part of the specified DateTime. The returned value
+ // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
+ // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
+ // Thursday, 5 indicates Friday, and 6 indicates Saturday.
+ //
+
+
+ public override DayOfWeek GetDayOfWeek(DateTime time) {
+ return ((DayOfWeek)((int)(time.Ticks / TicksPerDay + 1) % 7));
+ }
+
+ // Returns the day-of-year part of the specified DateTime. The returned value
+ // is an integer between 1 and 354 or 355.
+ //
+
+
+ public override int GetDayOfYear(DateTime time) {
+ return (GetDatePart(time, DatePartDayOfYear));
+ }
+
+ /*
+ internal bool CouldBeLeapYear(int year)
+ {
+ return ((((year * 11) + 14) % 30) < 11);
+ }
+ */
+
+ // Returns the number of days in the month given by the year and
+ // month arguments.
+ //
+
+
+ public override int GetDaysInMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+
+ if ((HijriYearInfo[year-MinCalendarYear].HijriMonthsLengthFlags & (1<<month-1))==0)
+ return 29;
+ else
+ return 30;
+ }
+
+ static internal int RealGetDaysInYear(int year)
+ {
+ int days = 0, b;
+
+ Contract.Assert( (year >= MinCalendarYear) && (year <= MaxCalendarYear), "Hijri year is out of range.");
+
+ b = HijriYearInfo[year-MinCalendarYear].HijriMonthsLengthFlags;
+
+ for(int m = 1; m <= 12; m++)
+ {
+ days += 29 + (b & 0x1);
+ b = b >> 1;
+ }
+ Contract.Assert((days == 354)||(days == 355), "Hijri year has to be 354 or 355 days.");
+ return days;
+ }
+
+ // Returns the number of days in the year given by the year argument for the current era.
+ //
+
+
+ public override int GetDaysInYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (RealGetDaysInYear(year));
+ }
+
+ // Returns the era for the specified DateTime value.
+
+
+ public override int GetEra(DateTime time) {
+ CheckTicksRange(time.Ticks);
+ return (UmAlQuraEra);
+ }
+
+
+
+ public override int[] Eras {
+ get {
+ return (new int[] {UmAlQuraEra});
+ }
+ }
+
+ // Returns the month part of the specified DateTime. The returned value is an
+ // integer between 1 and 12.
+ //
+
+
+ public override int GetMonth(DateTime time) {
+ return (GetDatePart(time, DatePartMonth));
+ }
+
+ // Returns the number of months in the specified year and era.
+
+
+ public override int GetMonthsInYear(int year, int era) {
+ CheckYearRange(year, era);
+ return (12);
+ }
+
+ // Returns the year part of the specified DateTime. The returned value is an
+ // integer between MinCalendarYear and MaxCalendarYear.
+ //
+
+
+ public override int GetYear(DateTime time) {
+ return (GetDatePart(time, DatePartYear));
+ }
+
+ // Checks whether a given day in the specified era is a leap day. This method returns true if
+ // the date is a leap day, or false if not.
+ //
+
+
+ public override bool IsLeapDay(int year, int month, int day, int era) {
+ if (day>=1 && day <=29)
+ {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+ if (day < 1 || day > daysInMonth) {
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+ return (false);
+ }
+
+ // Returns the leap month in a calendar year of the specified era. This method returns 0
+ // if this calendar does not have leap month, or this year is not a leap year.
+ //
+
+
+ public override int GetLeapMonth(int year, int era)
+ {
+ CheckYearRange(year, era);
+ return (0);
+ }
+
+ // Checks whether a given month in the specified era is a leap month. This method returns true if
+ // month is a leap month, or false if not.
+ //
+
+
+ public override bool IsLeapMonth(int year, int month, int era) {
+ CheckYearMonthRange(year, month, era);
+ return (false);
+ }
+
+ // Checks whether a given year in the specified era is a leap year. This method returns true if
+ // year is a leap year, or false if not.
+ //
+
+
+ public override bool IsLeapYear(int year, int era)
+ {
+ CheckYearRange(year, era);
+ if (RealGetDaysInYear(year) == 355)
+ return true;
+ else
+ return false;
+ }
+
+ // Returns the date and time converted to a DateTime value. Throws an exception if the n-tuple is invalid.
+ //
+
+
+ public override DateTime ToDateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int era) {
+ if (day >= 1 && day <= 29)
+ {
+ CheckYearMonthRange(year, month, era);
+ goto DayInRang;
+ }
+
+ // The year/month/era value checking is done in GetDaysInMonth().
+ int daysInMonth = GetDaysInMonth(year, month, era);
+
+ if (day < 1 || day > daysInMonth) {
+ BCLDebug.Log("year = " + year + ", month = " + month + ", day = " + day);
+ throw new ArgumentOutOfRangeException(
+ "day",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Day"),
+ daysInMonth,
+ month));
+ }
+DayInRang:
+ long lDate = GetAbsoluteDateUmAlQura(year, month, day);
+
+ if (lDate >= 0) {
+ return (new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)));
+ } else {
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("ArgumentOutOfRange_BadYearMonthDay"));
+ }
+ }
+
+ private const int DEFAULT_TWO_DIGIT_YEAR_MAX = 1451;
+
+
+
+ public override int TwoDigitYearMax {
+ get {
+ if (twoDigitYearMax == -1) {
+ twoDigitYearMax = GetSystemTwoDigitYearSetting(ID, DEFAULT_TWO_DIGIT_YEAR_MAX);
+ }
+ return (twoDigitYearMax);
+ }
+
+ set {
+ if (value != 99 && (value < MinCalendarYear || value > MaxCalendarYear)) {
+ throw new ArgumentOutOfRangeException(
+ "value",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ Contract.EndContractBlock();
+ VerifyWritable();
+ // We allow year 99 to be set so that one can make ToFourDigitYearMax a no-op by setting TwoDigitYearMax to 99.
+ twoDigitYearMax = value;
+ }
+ }
+
+
+
+ public override int ToFourDigitYear(int year) {
+ if (year < 0) {
+ throw new ArgumentOutOfRangeException("year",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (year < 100) {
+ return (base.ToFourDigitYear(year));
+ }
+
+ if ((year < MinCalendarYear) || (year > MaxCalendarYear)) {
+ throw new ArgumentOutOfRangeException(
+ "year",
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("ArgumentOutOfRange_Range"),
+ MinCalendarYear,
+ MaxCalendarYear));
+ }
+ return (year);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Globalization/UnicodeCategory.cs b/src/mscorlib/src/System/Globalization/UnicodeCategory.cs
new file mode 100644
index 0000000000..3848b6142f
--- /dev/null
+++ b/src/mscorlib/src/System/Globalization/UnicodeCategory.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+============================================================*/
+namespace System.Globalization {
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum UnicodeCategory {
+
+ UppercaseLetter = 0,
+
+ LowercaseLetter = 1,
+
+ TitlecaseLetter = 2,
+
+ ModifierLetter = 3,
+
+ OtherLetter = 4,
+
+ NonSpacingMark = 5,
+
+ SpacingCombiningMark = 6,
+
+ EnclosingMark = 7,
+
+ DecimalDigitNumber = 8,
+
+ LetterNumber = 9,
+
+ OtherNumber = 10,
+
+ SpaceSeparator = 11,
+
+ LineSeparator = 12,
+
+ ParagraphSeparator = 13,
+
+ Control = 14,
+
+ Format = 15,
+
+ Surrogate = 16,
+
+ PrivateUse = 17,
+
+ ConnectorPunctuation = 18,
+
+ DashPunctuation = 19,
+
+ OpenPunctuation = 20,
+
+ ClosePunctuation = 21,
+
+ InitialQuotePunctuation = 22,
+
+ FinalQuotePunctuation = 23,
+
+ OtherPunctuation = 24,
+
+ MathSymbol = 25,
+
+ CurrencySymbol = 26,
+
+ ModifierSymbol = 27,
+
+ OtherSymbol = 28,
+
+ OtherNotAssigned = 29,
+ }
+}
diff --git a/src/mscorlib/src/System/Guid.cs b/src/mscorlib/src/System/Guid.cs
new file mode 100644
index 0000000000..1ccabeb8db
--- /dev/null
+++ b/src/mscorlib/src/System/Guid.cs
@@ -0,0 +1,1299 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Text;
+ using Microsoft.Win32;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // Represents a Globally Unique Identifier.
+ [StructLayout(LayoutKind.Sequential)]
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ public struct Guid : IFormattable, IComparable
+ , IComparable<Guid>, IEquatable<Guid>
+ {
+ public static readonly Guid Empty = new Guid();
+ ////////////////////////////////////////////////////////////////////////////////
+ // Member variables
+ ////////////////////////////////////////////////////////////////////////////////
+ private int _a;
+ private short _b;
+ private short _c;
+ private byte _d;
+ private byte _e;
+ private byte _f;
+ private byte _g;
+ private byte _h;
+ private byte _i;
+ private byte _j;
+ private byte _k;
+
+
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Constructors
+ ////////////////////////////////////////////////////////////////////////////////
+
+ // Creates a new guid from an array of bytes.
+ //
+ public Guid(byte[] b)
+ {
+ if (b==null)
+ throw new ArgumentNullException("b");
+ if (b.Length != 16)
+ throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "16"), "b");
+ Contract.EndContractBlock();
+
+ _a = ((int)b[3] << 24) | ((int)b[2] << 16) | ((int)b[1] << 8) | b[0];
+ _b = (short)(((int)b[5] << 8) | b[4]);
+ _c = (short)(((int)b[7] << 8) | b[6]);
+ _d = b[8];
+ _e = b[9];
+ _f = b[10];
+ _g = b[11];
+ _h = b[12];
+ _i = b[13];
+ _j = b[14];
+ _k = b[15];
+ }
+
+ [CLSCompliant(false)]
+ public Guid (uint a, ushort b, ushort c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
+ {
+ _a = (int)a;
+ _b = (short)b;
+ _c = (short)c;
+ _d = d;
+ _e = e;
+ _f = f;
+ _g = g;
+ _h = h;
+ _i = i;
+ _j = j;
+ _k = k;
+ }
+
+
+ // Creates a new GUID initialized to the value represented by the arguments.
+ //
+ public Guid(int a, short b, short c, byte[] d)
+ {
+ if (d==null)
+ throw new ArgumentNullException("d");
+ // Check that array is not too big
+ if(d.Length != 8)
+ throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", "8"), "d");
+ Contract.EndContractBlock();
+
+ _a = a;
+ _b = b;
+ _c = c;
+ _d = d[0];
+ _e = d[1];
+ _f = d[2];
+ _g = d[3];
+ _h = d[4];
+ _i = d[5];
+ _j = d[6];
+ _k = d[7];
+ }
+
+ // Creates a new GUID initialized to the value represented by the
+ // arguments. The bytes are specified like this to avoid endianness issues.
+ //
+ public Guid(int a, short b, short c, byte d, byte e, byte f, byte g, byte h, byte i, byte j, byte k)
+ {
+ _a = a;
+ _b = b;
+ _c = c;
+ _d = d;
+ _e = e;
+ _f = f;
+ _g = g;
+ _h = h;
+ _i = i;
+ _j = j;
+ _k = k;
+ }
+
+ [Flags]
+ private enum GuidStyles {
+ None = 0x00000000,
+ AllowParenthesis = 0x00000001, //Allow the guid to be enclosed in parens
+ AllowBraces = 0x00000002, //Allow the guid to be enclosed in braces
+ AllowDashes = 0x00000004, //Allow the guid to contain dash group separators
+ AllowHexPrefix = 0x00000008, //Allow the guid to contain {0xdd,0xdd}
+ RequireParenthesis = 0x00000010, //Require the guid to be enclosed in parens
+ RequireBraces = 0x00000020, //Require the guid to be enclosed in braces
+ RequireDashes = 0x00000040, //Require the guid to contain dash group separators
+ RequireHexPrefix = 0x00000080, //Require the guid to contain {0xdd,0xdd}
+
+ HexFormat = RequireBraces | RequireHexPrefix, /* X */
+ NumberFormat = None, /* N */
+ DigitFormat = RequireDashes, /* D */
+ BraceFormat = RequireBraces | RequireDashes, /* B */
+ ParenthesisFormat = RequireParenthesis | RequireDashes, /* P */
+
+ Any = AllowParenthesis | AllowBraces | AllowDashes | AllowHexPrefix,
+ }
+ private enum GuidParseThrowStyle {
+ None = 0,
+ All = 1,
+ AllButOverflow = 2
+ }
+ private enum ParseFailureKind {
+ None = 0,
+ ArgumentNull = 1,
+ Format = 2,
+ FormatWithParameter = 3,
+ NativeException = 4,
+ FormatWithInnerException = 5
+ }
+
+ // This will store the result of the parsing. And it will eventually be used to construct a Guid instance.
+ private struct GuidResult {
+ internal Guid parsedGuid;
+ internal GuidParseThrowStyle throwStyle;
+
+ internal ParseFailureKind m_failure;
+ internal string m_failureMessageID;
+ internal object m_failureMessageFormatArgument;
+ internal string m_failureArgumentName;
+ internal Exception m_innerException;
+
+ internal void Init(GuidParseThrowStyle canThrow) {
+ parsedGuid = Guid.Empty;
+ throwStyle = canThrow;
+ }
+ internal void SetFailure(Exception nativeException) {
+ m_failure = ParseFailureKind.NativeException;
+ m_innerException = nativeException;
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID) {
+ SetFailure(failure, failureMessageID, null, null, null);
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument) {
+ SetFailure(failure, failureMessageID, failureMessageFormatArgument, null, null);
+ }
+ internal void SetFailure(ParseFailureKind failure, string failureMessageID, object failureMessageFormatArgument,
+ string failureArgumentName, Exception innerException) {
+ Contract.Assert(failure != ParseFailureKind.NativeException, "ParseFailureKind.NativeException should not be used with this overload");
+ m_failure = failure;
+ m_failureMessageID = failureMessageID;
+ m_failureMessageFormatArgument = failureMessageFormatArgument;
+ m_failureArgumentName = failureArgumentName;
+ m_innerException = innerException;
+ if (throwStyle != GuidParseThrowStyle.None) {
+ throw GetGuidParseException();
+ }
+ }
+
+ internal Exception GetGuidParseException() {
+ switch (m_failure) {
+ case ParseFailureKind.ArgumentNull:
+ return new ArgumentNullException(m_failureArgumentName, Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.FormatWithInnerException:
+ return new FormatException(Environment.GetResourceString(m_failureMessageID), m_innerException);
+
+ case ParseFailureKind.FormatWithParameter:
+ return new FormatException(Environment.GetResourceString(m_failureMessageID, m_failureMessageFormatArgument));
+
+ case ParseFailureKind.Format:
+ return new FormatException(Environment.GetResourceString(m_failureMessageID));
+
+ case ParseFailureKind.NativeException:
+ return m_innerException;
+
+ default:
+ Contract.Assert(false, "Unknown GuidParseFailure: " + m_failure);
+ return new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"));
+ }
+ }
+ }
+
+ // Creates a new guid based on the value in the string. The value is made up
+ // of hex digits speared by the dash ("-"). The string may begin and end with
+ // brackets ("{", "}").
+ //
+ // The string must be of the form dddddddd-dddd-dddd-dddd-dddddddddddd. where
+ // d is a hex digit. (That is 8 hex digits, followed by 4, then 4, then 4,
+ // then 12) such as: "CA761232-ED42-11CE-BACD-00AA0057B223"
+ //
+ public Guid(String g)
+ {
+ if (g==null) {
+ throw new ArgumentNullException("g");
+ }
+ Contract.EndContractBlock();
+ this = Guid.Empty;
+
+ GuidResult result = new GuidResult();
+ result.Init(GuidParseThrowStyle.All);
+ if (TryParseGuid(g, GuidStyles.Any, ref result)) {
+ this = result.parsedGuid;
+ }
+ else {
+ throw result.GetGuidParseException();
+ }
+ }
+
+
+ public static Guid Parse(String input)
+ {
+ if (input == null) {
+ throw new ArgumentNullException("input");
+ }
+ Contract.EndContractBlock();
+
+ GuidResult result = new GuidResult();
+ result.Init(GuidParseThrowStyle.AllButOverflow);
+ if (TryParseGuid(input, GuidStyles.Any, ref result)) {
+ return result.parsedGuid;
+ }
+ else {
+ throw result.GetGuidParseException();
+ }
+ }
+
+ public static bool TryParse(String input, out Guid result)
+ {
+ GuidResult parseResult = new GuidResult();
+ parseResult.Init(GuidParseThrowStyle.None);
+ if (TryParseGuid(input, GuidStyles.Any, ref parseResult)) {
+ result = parseResult.parsedGuid;
+ return true;
+ }
+ else {
+ result = Guid.Empty;
+ return false;
+ }
+ }
+
+ public static Guid ParseExact(String input, String format)
+ {
+ if (input == null)
+ throw new ArgumentNullException("input");
+
+ if (format == null)
+ throw new ArgumentNullException("format");
+
+ if( format.Length != 1) {
+ // all acceptable format strings are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification"));
+ }
+
+ GuidStyles style;
+ char formatCh = format[0];
+ if (formatCh == 'D' || formatCh == 'd') {
+ style = GuidStyles.DigitFormat;
+ }
+ else if (formatCh == 'N' || formatCh == 'n') {
+ style = GuidStyles.NumberFormat;
+ }
+ else if (formatCh == 'B' || formatCh == 'b') {
+ style = GuidStyles.BraceFormat;
+ }
+ else if (formatCh == 'P' || formatCh == 'p') {
+ style = GuidStyles.ParenthesisFormat;
+ }
+ else if (formatCh == 'X' || formatCh == 'x') {
+ style = GuidStyles.HexFormat;
+ }
+ else {
+ throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification"));
+ }
+
+ GuidResult result = new GuidResult();
+ result.Init(GuidParseThrowStyle.AllButOverflow);
+ if (TryParseGuid(input, style, ref result)) {
+ return result.parsedGuid;
+ }
+ else {
+ throw result.GetGuidParseException();
+ }
+ }
+
+ public static bool TryParseExact(String input, String format, out Guid result)
+ {
+ if (format == null || format.Length != 1) {
+ result = Guid.Empty;
+ return false;
+ }
+
+ GuidStyles style;
+ char formatCh = format[0];
+
+ if (formatCh == 'D' || formatCh == 'd') {
+ style = GuidStyles.DigitFormat;
+ }
+ else if (formatCh == 'N' || formatCh == 'n') {
+ style = GuidStyles.NumberFormat;
+ }
+ else if (formatCh == 'B' || formatCh == 'b') {
+ style = GuidStyles.BraceFormat;
+ }
+ else if (formatCh == 'P' || formatCh == 'p') {
+ style = GuidStyles.ParenthesisFormat;
+ }
+ else if (formatCh == 'X' || formatCh == 'x') {
+ style = GuidStyles.HexFormat;
+ }
+ else {
+ // invalid guid format specification
+ result = Guid.Empty;
+ return false;
+ }
+
+ GuidResult parseResult = new GuidResult();
+ parseResult.Init(GuidParseThrowStyle.None);
+ if (TryParseGuid(input, style, ref parseResult)) {
+ result = parseResult.parsedGuid;
+ return true;
+ }
+ else {
+ result = Guid.Empty;
+ return false;
+ }
+ }
+
+
+ private static bool TryParseGuid(String g, GuidStyles flags, ref GuidResult result)
+ {
+ if (g == null) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ String guidString = g.Trim(); //Remove Whitespace
+
+ if (guidString.Length == 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+
+ // Check for dashes
+ bool dashesExistInString = (guidString.IndexOf('-', 0) >= 0);
+
+ if (dashesExistInString) {
+ if ((flags & (GuidStyles.AllowDashes | GuidStyles.RequireDashes)) == 0) {
+ // dashes are not allowed
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+ else {
+ if ((flags & GuidStyles.RequireDashes) != 0) {
+ // dashes are required
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+
+ // Check for braces
+ bool bracesExistInString = (guidString.IndexOf('{', 0) >= 0);
+
+ if (bracesExistInString) {
+ if ((flags & (GuidStyles.AllowBraces | GuidStyles.RequireBraces)) == 0) {
+ // braces are not allowed
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+ else {
+ if ((flags & GuidStyles.RequireBraces) != 0) {
+ // braces are required
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+
+ // Check for parenthesis
+ bool parenthesisExistInString = (guidString.IndexOf('(', 0) >= 0);
+
+ if (parenthesisExistInString) {
+ if ((flags & (GuidStyles.AllowParenthesis | GuidStyles.RequireParenthesis)) == 0) {
+ // parenthesis are not allowed
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+ else {
+ if ((flags & GuidStyles.RequireParenthesis) != 0) {
+ // parenthesis are required
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidUnrecognized");
+ return false;
+ }
+ }
+
+ try {
+ // let's get on with the parsing
+ if (dashesExistInString) {
+ // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)]
+ return TryParseGuidWithDashes(guidString, ref result);
+ }
+ else if (bracesExistInString) {
+ // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
+ return TryParseGuidWithHexPrefix(guidString, ref result);
+ }
+ else {
+ // Check if it's of the form dddddddddddddddddddddddddddddddd
+ return TryParseGuidWithNoStyle(guidString, ref result);
+ }
+ }
+ catch(IndexOutOfRangeException ex) {
+ result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex);
+ return false;
+ }
+ catch (ArgumentException ex) {
+ result.SetFailure(ParseFailureKind.FormatWithInnerException, "Format_GuidUnrecognized", null, null, ex);
+ return false;
+ }
+ }
+
+
+ // Check if it's of the form {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
+ private static bool TryParseGuidWithHexPrefix(String guidString, ref GuidResult result) {
+ int numStart = 0;
+ int numLen = 0;
+
+ // Eat all of the whitespace
+ guidString = EatAllWhitespace(guidString);
+
+ // Check for leading '{'
+ if(String.IsNullOrEmpty(guidString) || guidString[0] != '{') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace");
+ return false;
+ }
+
+ // Check for '0x'
+ if(!IsHexPrefix(guidString, 1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, etc}");
+ return false;
+ }
+
+ // Find the end of this hex number (since it is not fixed length)
+ numStart = 3;
+ numLen = guidString.IndexOf(',', numStart) - numStart;
+ if(numLen <= 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidComma");
+ return false;
+ }
+
+
+ if (!StringToInt(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result))
+ return false;
+
+ // Check for '0x'
+ if(!IsHexPrefix(guidString, numStart+numLen+1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, etc}");
+ return false;
+ }
+ // +3 to get by ',0x'
+ numStart = numStart + numLen + 3;
+ numLen = guidString.IndexOf(',', numStart) - numStart;
+ if(numLen <= 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidComma");
+ return false;
+ }
+
+ // Read in the number
+ if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result))
+ return false;
+ // Check for '0x'
+ if(!IsHexPrefix(guidString, numStart+numLen+1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{0xdddddddd, 0xdddd, 0xdddd, etc}");
+ return false;
+ }
+ // +3 to get by ',0x'
+ numStart = numStart + numLen + 3;
+ numLen = guidString.IndexOf(',', numStart) - numStart;
+ if(numLen <= 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidComma");
+ return false;
+ }
+
+ // Read in the number
+ if (!StringToShort(guidString.Substring(numStart, numLen) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result))
+ return false;
+
+ // Check for '{'
+ if(guidString.Length <= numStart+numLen+1 || guidString[numStart+numLen+1] != '{') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidBrace");
+ return false;
+ }
+
+ // Prepare for loop
+ numLen++;
+ byte[] bytes = new byte[8];
+
+ for(int i = 0; i < 8; i++)
+ {
+ // Check for '0x'
+ if(!IsHexPrefix(guidString, numStart+numLen+1)) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidHexPrefix", "{... { ... 0xdd, ...}}");
+ return false;
+ }
+
+ // +3 to get by ',0x' or '{0x' for first case
+ numStart = numStart + numLen + 3;
+
+ // Calculate number length
+ if(i < 7) // first 7 cases
+ {
+ numLen = guidString.IndexOf(',', numStart) - numStart;
+ if(numLen <= 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidComma");
+ return false;
+ }
+ }
+ else // last case ends with '}', not ','
+ {
+ numLen = guidString.IndexOf('}', numStart) - numStart;
+ if(numLen <= 0) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidBraceAfterLastNumber");
+ return false;
+ }
+ }
+
+ // Read in the number
+ int signedNumber;
+ if (!StringToInt(guidString.Substring(numStart, numLen), -1, ParseNumbers.IsTight, out signedNumber, ref result)) {
+ return false;
+ }
+ uint number = (uint)signedNumber;
+
+ // check for overflow
+ if(number > 255) {
+ result.SetFailure(ParseFailureKind.Format, "Overflow_Byte");
+ return false;
+ }
+ bytes[i] = (byte)number;
+ }
+
+ result.parsedGuid._d = bytes[0];
+ result.parsedGuid._e = bytes[1];
+ result.parsedGuid._f = bytes[2];
+ result.parsedGuid._g = bytes[3];
+ result.parsedGuid._h = bytes[4];
+ result.parsedGuid._i = bytes[5];
+ result.parsedGuid._j = bytes[6];
+ result.parsedGuid._k = bytes[7];
+
+ // Check for last '}'
+ if(numStart+numLen+1 >= guidString.Length || guidString[numStart+numLen+1] != '}') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidEndBrace");
+ return false;
+ }
+
+ // Check if we have extra characters at the end
+ if( numStart+numLen+1 != guidString.Length -1) {
+ result.SetFailure(ParseFailureKind.Format, "Format_ExtraJunkAtEnd");
+ return false;
+ }
+
+ return true;
+ }
+
+ // Check if it's of the form dddddddddddddddddddddddddddddddd
+ private static bool TryParseGuidWithNoStyle(String guidString, ref GuidResult result) {
+ int startPos=0;
+ int temp;
+ long templ;
+ int currentPos = 0;
+
+ if(guidString.Length != 32) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+
+ for(int i= 0; i< guidString.Length; i++) {
+ char ch = guidString[i];
+ if(ch >= '0' && ch <= '9') {
+ continue;
+ }
+ else {
+ char upperCaseCh = Char.ToUpper(ch, CultureInfo.InvariantCulture);
+ if(upperCaseCh >= 'A' && upperCaseCh <= 'F') {
+ continue;
+ }
+ }
+
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar");
+ return false;
+ }
+
+ if (!StringToInt(guidString.Substring(startPos, 8) /*first DWORD*/, -1, ParseNumbers.IsTight, out result.parsedGuid._a, ref result))
+ return false;
+
+ startPos += 8;
+ if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._b, ref result))
+ return false;
+
+ startPos += 4;
+ if (!StringToShort(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out result.parsedGuid._c, ref result))
+ return false;
+
+ startPos += 4;
+ if (!StringToInt(guidString.Substring(startPos, 4), -1, ParseNumbers.IsTight, out temp, ref result))
+ return false;
+
+ startPos += 4;
+ currentPos = startPos;
+
+ if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result))
+ return false;
+
+ if (currentPos - startPos!=12) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+
+ result.parsedGuid._d = (byte)(temp>>8);
+ result.parsedGuid._e = (byte)(temp);
+ temp = (int)(templ >> 32);
+ result.parsedGuid._f = (byte)(temp>>8);
+ result.parsedGuid._g = (byte)(temp);
+ temp = (int)(templ);
+ result.parsedGuid._h = (byte)(temp>>24);
+ result.parsedGuid._i = (byte)(temp>>16);
+ result.parsedGuid._j = (byte)(temp>>8);
+ result.parsedGuid._k = (byte)(temp);
+
+ return true;
+ }
+
+
+ // Check if it's of the form [{|(]dddddddd-dddd-dddd-dddd-dddddddddddd[}|)]
+ private static bool TryParseGuidWithDashes(String guidString, ref GuidResult result) {
+ int startPos=0;
+ int temp;
+ long templ;
+ int currentPos = 0;
+
+ // check to see that it's the proper length
+ if (guidString[0]=='{') {
+ if (guidString.Length!=38 || guidString[37]!='}') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+ startPos=1;
+ }
+ else if (guidString[0]=='(') {
+ if (guidString.Length!=38 || guidString[37]!=')') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+ startPos=1;
+ }
+ else if(guidString.Length != 36) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+
+ if (guidString[8+startPos] != '-' ||
+ guidString[13+startPos] != '-' ||
+ guidString[18+startPos] != '-' ||
+ guidString[23+startPos] != '-') {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidDashes");
+ return false;
+ }
+
+ currentPos = startPos;
+ if (!StringToInt(guidString, ref currentPos, 8, ParseNumbers.NoSpace, out temp, ref result))
+ return false;
+ result.parsedGuid._a = temp;
+ ++currentPos; //Increment past the '-';
+
+ if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result))
+ return false;
+ result.parsedGuid._b = (short)temp;
+ ++currentPos; //Increment past the '-';
+
+ if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result))
+ return false;
+ result.parsedGuid._c = (short)temp;
+ ++currentPos; //Increment past the '-';
+
+ if (!StringToInt(guidString, ref currentPos, 4, ParseNumbers.NoSpace, out temp, ref result))
+ return false;
+ ++currentPos; //Increment past the '-';
+ startPos=currentPos;
+
+ if (!StringToLong(guidString, ref currentPos, ParseNumbers.NoSpace, out templ, ref result))
+ return false;
+
+ if (currentPos - startPos != 12) {
+ result.SetFailure(ParseFailureKind.Format, "Format_GuidInvLen");
+ return false;
+ }
+ result.parsedGuid._d = (byte)(temp>>8);
+ result.parsedGuid._e = (byte)(temp);
+ temp = (int)(templ >> 32);
+ result.parsedGuid._f = (byte)(temp>>8);
+ result.parsedGuid._g = (byte)(temp);
+ temp = (int)(templ);
+ result.parsedGuid._h = (byte)(temp>>24);
+ result.parsedGuid._i = (byte)(temp>>16);
+ result.parsedGuid._j = (byte)(temp>>8);
+ result.parsedGuid._k = (byte)(temp);
+
+ return true;
+ }
+
+
+ //
+ // StringToShort, StringToInt, and StringToLong are wrappers around COMUtilNative integer parsing routines;
+
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToShort(String str, int requiredLength, int flags, out short result, ref GuidResult parseResult) {
+ return StringToShort(str, null, requiredLength, flags, out result, ref parseResult);
+ }
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToShort(String str, ref int parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) {
+ fixed(int * ppos = &parsePos) {
+ return StringToShort(str, ppos, requiredLength, flags, out result, ref parseResult);
+ }
+ }
+ [System.Security.SecurityCritical]
+ private static unsafe bool StringToShort(String str, int* parsePos, int requiredLength, int flags, out short result, ref GuidResult parseResult) {
+ result = 0;
+ int x;
+ bool retValue = StringToInt(str, parsePos, requiredLength, flags, out x, ref parseResult);
+ result = (short)x;
+ return retValue;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToInt(String str, int requiredLength, int flags, out int result, ref GuidResult parseResult) {
+ return StringToInt(str, null, requiredLength, flags, out result, ref parseResult);
+ }
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToInt(String str, ref int parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) {
+ fixed(int * ppos = &parsePos) {
+ return StringToInt(str, ppos, requiredLength, flags, out result, ref parseResult);
+ }
+ }
+ [System.Security.SecurityCritical]
+ private static unsafe bool StringToInt(String str, int* parsePos, int requiredLength, int flags, out int result, ref GuidResult parseResult) {
+ result = 0;
+
+ int currStart = (parsePos == null) ? 0 : (*parsePos);
+ try {
+ result = ParseNumbers.StringToInt(str, 16, flags, parsePos);
+ }
+ catch (OverflowException ex) {
+ if (parseResult.throwStyle == GuidParseThrowStyle.All) {
+ throw;
+ }
+ else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) {
+ throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex);
+ }
+ else {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ catch (Exception ex) {
+ if (parseResult.throwStyle == GuidParseThrowStyle.None) {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ else {
+ throw;
+ }
+ }
+
+ //If we didn't parse enough characters, there's clearly an error.
+ if (requiredLength != -1 && parsePos != null && (*parsePos) - currStart != requiredLength) {
+ parseResult.SetFailure(ParseFailureKind.Format, "Format_GuidInvalidChar");
+ return false;
+ }
+ return true;
+ }
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToLong(String str, int flags, out long result, ref GuidResult parseResult) {
+ return StringToLong(str, null, flags, out result, ref parseResult);
+ }
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToLong(String str, ref int parsePos, int flags, out long result, ref GuidResult parseResult) {
+ fixed(int * ppos = &parsePos) {
+ return StringToLong(str, ppos, flags, out result, ref parseResult);
+ }
+ }
+ [System.Security.SecuritySafeCritical]
+ private static unsafe bool StringToLong(String str, int* parsePos, int flags, out long result, ref GuidResult parseResult) {
+ result = 0;
+
+ try {
+ result = ParseNumbers.StringToLong(str, 16, flags, parsePos);
+ }
+ catch (OverflowException ex) {
+ if (parseResult.throwStyle == GuidParseThrowStyle.All) {
+ throw;
+ }
+ else if (parseResult.throwStyle == GuidParseThrowStyle.AllButOverflow) {
+ throw new FormatException(Environment.GetResourceString("Format_GuidUnrecognized"), ex);
+ }
+ else {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ }
+ catch (Exception ex) {
+ if (parseResult.throwStyle == GuidParseThrowStyle.None) {
+ parseResult.SetFailure(ex);
+ return false;
+ }
+ else {
+ throw;
+ }
+ }
+ return true;
+ }
+
+
+ private static String EatAllWhitespace(String str)
+ {
+ int newLength = 0;
+ char[] chArr = new char[str.Length];
+ char curChar;
+
+ // Now get each char from str and if it is not whitespace add it to chArr
+ for(int i = 0; i < str.Length; i++)
+ {
+ curChar = str[i];
+ if(!Char.IsWhiteSpace(curChar))
+ {
+ chArr[newLength++] = curChar;
+ }
+ }
+
+ // Return a new string based on chArr
+ return new String(chArr, 0, newLength);
+ }
+
+ private static bool IsHexPrefix(String str, int i)
+ {
+ if(str.Length > i+1 && str[i] == '0' && (Char.ToLower(str[i+1], CultureInfo.InvariantCulture) == 'x'))
+ return true;
+ else
+ return false;
+ }
+
+
+ // Returns an unsigned byte array containing the GUID.
+ public byte[] ToByteArray()
+ {
+ byte[] g = new byte[16];
+
+ g[0] = (byte)(_a);
+ g[1] = (byte)(_a >> 8);
+ g[2] = (byte)(_a >> 16);
+ g[3] = (byte)(_a >> 24);
+ g[4] = (byte)(_b);
+ g[5] = (byte)(_b >> 8);
+ g[6] = (byte)(_c);
+ g[7] = (byte)(_c >> 8);
+ g[8] = _d;
+ g[9] = _e;
+ g[10] = _f;
+ g[11] = _g;
+ g[12] = _h;
+ g[13] = _i;
+ g[14] = _j;
+ g[15] = _k;
+
+ return g;
+ }
+
+
+ // Returns the guid in "registry" format.
+ public override String ToString()
+ {
+ return ToString("D",null);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public unsafe override int GetHashCode()
+ {
+ // Simply XOR all the bits of the GUID 32 bits at a time.
+ fixed (int* ptr = &this._a)
+ return ptr[0] ^ ptr[1] ^ ptr[2] ^ ptr[3];
+ }
+
+ // Returns true if and only if the guid represented
+ // by o is the same as this instance.
+ public override bool Equals(Object o)
+ {
+ Guid g;
+ // Check that o is a Guid first
+ if(o == null || !(o is Guid))
+ return false;
+ else g = (Guid) o;
+
+ // Now compare each of the elements
+ if(g._a != _a)
+ return false;
+ if(g._b != _b)
+ return false;
+ if(g._c != _c)
+ return false;
+ if (g._d != _d)
+ return false;
+ if (g._e != _e)
+ return false;
+ if (g._f != _f)
+ return false;
+ if (g._g != _g)
+ return false;
+ if (g._h != _h)
+ return false;
+ if (g._i != _i)
+ return false;
+ if (g._j != _j)
+ return false;
+ if (g._k != _k)
+ return false;
+
+ return true;
+ }
+
+ public bool Equals(Guid g)
+ {
+ // Now compare each of the elements
+ if(g._a != _a)
+ return false;
+ if(g._b != _b)
+ return false;
+ if(g._c != _c)
+ return false;
+ if (g._d != _d)
+ return false;
+ if (g._e != _e)
+ return false;
+ if (g._f != _f)
+ return false;
+ if (g._g != _g)
+ return false;
+ if (g._h != _h)
+ return false;
+ if (g._i != _i)
+ return false;
+ if (g._j != _j)
+ return false;
+ if (g._k != _k)
+ return false;
+
+ return true;
+ }
+
+ private int GetResult(uint me, uint them) {
+ if (me<them) {
+ return -1;
+ }
+ return 1;
+ }
+
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (!(value is Guid)) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeGuid"), "value");
+ }
+ Guid g = (Guid)value;
+
+ if (g._a!=this._a) {
+ return GetResult((uint)this._a, (uint)g._a);
+ }
+
+ if (g._b!=this._b) {
+ return GetResult((uint)this._b, (uint)g._b);
+ }
+
+ if (g._c!=this._c) {
+ return GetResult((uint)this._c, (uint)g._c);
+ }
+
+ if (g._d!=this._d) {
+ return GetResult((uint)this._d, (uint)g._d);
+ }
+
+ if (g._e!=this._e) {
+ return GetResult((uint)this._e, (uint)g._e);
+ }
+
+ if (g._f!=this._f) {
+ return GetResult((uint)this._f, (uint)g._f);
+ }
+
+ if (g._g!=this._g) {
+ return GetResult((uint)this._g, (uint)g._g);
+ }
+
+ if (g._h!=this._h) {
+ return GetResult((uint)this._h, (uint)g._h);
+ }
+
+ if (g._i!=this._i) {
+ return GetResult((uint)this._i, (uint)g._i);
+ }
+
+ if (g._j!=this._j) {
+ return GetResult((uint)this._j, (uint)g._j);
+ }
+
+ if (g._k!=this._k) {
+ return GetResult((uint)this._k, (uint)g._k);
+ }
+
+ return 0;
+ }
+
+ public int CompareTo(Guid value)
+ {
+ if (value._a!=this._a) {
+ return GetResult((uint)this._a, (uint)value._a);
+ }
+
+ if (value._b!=this._b) {
+ return GetResult((uint)this._b, (uint)value._b);
+ }
+
+ if (value._c!=this._c) {
+ return GetResult((uint)this._c, (uint)value._c);
+ }
+
+ if (value._d!=this._d) {
+ return GetResult((uint)this._d, (uint)value._d);
+ }
+
+ if (value._e!=this._e) {
+ return GetResult((uint)this._e, (uint)value._e);
+ }
+
+ if (value._f!=this._f) {
+ return GetResult((uint)this._f, (uint)value._f);
+ }
+
+ if (value._g!=this._g) {
+ return GetResult((uint)this._g, (uint)value._g);
+ }
+
+ if (value._h!=this._h) {
+ return GetResult((uint)this._h, (uint)value._h);
+ }
+
+ if (value._i!=this._i) {
+ return GetResult((uint)this._i, (uint)value._i);
+ }
+
+ if (value._j!=this._j) {
+ return GetResult((uint)this._j, (uint)value._j);
+ }
+
+ if (value._k!=this._k) {
+ return GetResult((uint)this._k, (uint)value._k);
+ }
+
+ return 0;
+ }
+
+ public static bool operator ==(Guid a, Guid b)
+ {
+ // Now compare each of the elements
+ if(a._a != b._a)
+ return false;
+ if(a._b != b._b)
+ return false;
+ if(a._c != b._c)
+ return false;
+ if(a._d != b._d)
+ return false;
+ if(a._e != b._e)
+ return false;
+ if(a._f != b._f)
+ return false;
+ if(a._g != b._g)
+ return false;
+ if(a._h != b._h)
+ return false;
+ if(a._i != b._i)
+ return false;
+ if(a._j != b._j)
+ return false;
+ if(a._k != b._k)
+ return false;
+
+ return true;
+ }
+
+ public static bool operator !=(Guid a, Guid b)
+ {
+ return !(a == b);
+ }
+
+ // This will create a new guid. Since we've now decided that constructors should 0-init,
+ // we need a method that allows users to create a guid.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Guid NewGuid() {
+ // CoCreateGuid should never return Guid.Empty, since it attempts to maintain some
+ // uniqueness guarantees. It should also never return a known GUID, but it's unclear
+ // how extensively it checks for known values.
+ Contract.Ensures(Contract.Result<Guid>() != Guid.Empty);
+
+ Guid guid;
+ Marshal.ThrowExceptionForHR(Win32Native.CoCreateGuid(out guid), new IntPtr(-1));
+ return guid;
+ }
+
+ public String ToString(String format) {
+ return ToString(format, null);
+ }
+
+ private static char HexToChar(int a)
+ {
+ a = a & 0xf;
+ return (char) ((a > 9) ? a - 10 + 0x61 : a + 0x30);
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b)
+ {
+ return HexsToChars(guidChars, offset, a, b, false);
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe private static int HexsToChars(char* guidChars, int offset, int a, int b, bool hex)
+ {
+ if (hex) {
+ guidChars[offset++] = '0';
+ guidChars[offset++] = 'x';
+ }
+ guidChars[offset++] = HexToChar(a>>4);
+ guidChars[offset++] = HexToChar(a);
+ if (hex) {
+ guidChars[offset++] = ',';
+ guidChars[offset++] = '0';
+ guidChars[offset++] = 'x';
+ }
+ guidChars[offset++] = HexToChar(b>>4);
+ guidChars[offset++] = HexToChar(b);
+ return offset;
+ }
+
+ // IFormattable interface
+ // We currently ignore provider
+ [System.Security.SecuritySafeCritical]
+ public String ToString(String format, IFormatProvider provider)
+ {
+ if (format == null || format.Length == 0)
+ format = "D";
+
+ string guidString;
+ int offset = 0;
+ bool dash = true;
+ bool hex = false;
+
+ if( format.Length != 1) {
+ // all acceptable format strings are of length 1
+ throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification"));
+ }
+
+ char formatCh = format[0];
+ if (formatCh == 'D' || formatCh == 'd') {
+ guidString = string.FastAllocateString(36);
+ }
+ else if (formatCh == 'N' || formatCh == 'n') {
+ guidString = string.FastAllocateString(32);
+ dash = false;
+ }
+ else if (formatCh == 'B' || formatCh == 'b') {
+ guidString = string.FastAllocateString(38);
+ unsafe {
+ fixed (char* guidChars = guidString) {
+ guidChars[offset++] = '{';
+ guidChars[37] = '}';
+ }
+ }
+ }
+ else if (formatCh == 'P' || formatCh == 'p') {
+ guidString = string.FastAllocateString(38);
+ unsafe {
+ fixed (char* guidChars = guidString) {
+ guidChars[offset++] = '(';
+ guidChars[37] = ')';
+ }
+ }
+ }
+ else if (formatCh == 'X' || formatCh == 'x') {
+ guidString = string.FastAllocateString(68);
+ unsafe {
+ fixed (char* guidChars = guidString) {
+ guidChars[offset++] = '{';
+ guidChars[67] = '}';
+ }
+ }
+ dash = false;
+ hex = true;
+ }
+ else {
+ throw new FormatException(Environment.GetResourceString("Format_InvalidGuidFormatSpecification"));
+ }
+
+ unsafe {
+ fixed (char* guidChars = guidString) {
+ if (hex) {
+ // {0xdddddddd,0xdddd,0xdddd,{0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd}}
+ guidChars[offset++] = '0';
+ guidChars[offset++] = 'x';
+ offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16);
+ offset = HexsToChars(guidChars, offset, _a >> 8, _a);
+ guidChars[offset++] = ',';
+ guidChars[offset++] = '0';
+ guidChars[offset++] = 'x';
+ offset = HexsToChars(guidChars, offset, _b >> 8, _b);
+ guidChars[offset++] = ',';
+ guidChars[offset++] = '0';
+ guidChars[offset++] = 'x';
+ offset = HexsToChars(guidChars, offset, _c >> 8, _c);
+ guidChars[offset++] = ',';
+ guidChars[offset++] = '{';
+ offset = HexsToChars(guidChars, offset, _d, _e, true);
+ guidChars[offset++] = ',';
+ offset = HexsToChars(guidChars, offset, _f, _g, true);
+ guidChars[offset++] = ',';
+ offset = HexsToChars(guidChars, offset, _h, _i, true);
+ guidChars[offset++] = ',';
+ offset = HexsToChars(guidChars, offset, _j, _k, true);
+ guidChars[offset++] = '}';
+ }
+ else {
+ // [{|(]dddddddd[-]dddd[-]dddd[-]dddd[-]dddddddddddd[}|)]
+ offset = HexsToChars(guidChars, offset, _a >> 24, _a >> 16);
+ offset = HexsToChars(guidChars, offset, _a >> 8, _a);
+ if (dash) guidChars[offset++] = '-';
+ offset = HexsToChars(guidChars, offset, _b >> 8, _b);
+ if (dash) guidChars[offset++] = '-';
+ offset = HexsToChars(guidChars, offset, _c >> 8, _c);
+ if (dash) guidChars[offset++] = '-';
+ offset = HexsToChars(guidChars, offset, _d, _e);
+ if (dash) guidChars[offset++] = '-';
+ offset = HexsToChars(guidChars, offset, _f, _g);
+ offset = HexsToChars(guidChars, offset, _h, _i);
+ offset = HexsToChars(guidChars, offset, _j, _k);
+ }
+ }
+ }
+ return guidString;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IAppDomain.cs b/src/mscorlib/src/System/IAppDomain.cs
new file mode 100644
index 0000000000..bd8b876577
--- /dev/null
+++ b/src/mscorlib/src/System/IAppDomain.cs
@@ -0,0 +1,268 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IAppDomain
+**
+**
+**
+**
+** Purpose: Properties and methods exposed to COM
+**
+**
+===========================================================*/
+namespace System {
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using SecurityManager = System.Security.SecurityManager;
+ using System.Security.Permissions;
+ using IEvidenceFactory = System.Security.IEvidenceFactory;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Security.Policy;
+ using System.Security;
+ using System.Security.Util;
+ using System.Collections;
+ using System.Text;
+ using System.Configuration.Assemblies;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.Reflection.Emit;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.IO;
+ using System.Runtime.Versioning;
+
+ [GuidAttribute("05F696DC-2B29-3663-AD8B-C4389CF2A713")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _AppDomain
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+
+ String ToString();
+
+ bool Equals (Object other);
+
+ int GetHashCode ();
+
+ Type GetType ();
+
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated_required
+ Object InitializeLifetimeService ();
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ Object GetLifetimeService ();
+#endif // FEATURE_REMOTING
+
+#if FEATURE_CAS_POLICY
+ Evidence Evidence { get; }
+#endif // FEATURE_CAS_POLICY
+ event EventHandler DomainUnload;
+
+ [method:System.Security.SecurityCritical]
+ event AssemblyLoadEventHandler AssemblyLoad;
+
+ event EventHandler ProcessExit;
+
+ [method:System.Security.SecurityCritical]
+ event ResolveEventHandler TypeResolve;
+
+ [method:System.Security.SecurityCritical]
+ event ResolveEventHandler ResourceResolve;
+
+ [method:System.Security.SecurityCritical]
+ event ResolveEventHandler AssemblyResolve;
+
+ [method:System.Security.SecurityCritical]
+ event UnhandledExceptionEventHandler UnhandledException;
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ Evidence evidence);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions);
+
+ AssemblyBuilder DefineDynamicAssembly(AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ bool isSynchronized);
+
+ ObjectHandle CreateInstance(String assemblyName,
+ String typeName);
+
+
+ ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName);
+
+
+ ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ Object[] activationAttributes);
+
+ ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ Object[] activationAttributes);
+
+ ObjectHandle CreateInstance(String assemblyName,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes);
+
+ ObjectHandle CreateInstanceFrom(String assemblyFile,
+ String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes,
+ Evidence securityAttributes);
+
+ Assembly Load(AssemblyName assemblyRef);
+
+ Assembly Load(String assemblyString);
+
+ Assembly Load(byte[] rawAssembly);
+
+ Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore);
+
+ Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore,
+ Evidence securityEvidence);
+
+ Assembly Load(AssemblyName assemblyRef,
+ Evidence assemblySecurity);
+
+ Assembly Load(String assemblyString,
+ Evidence assemblySecurity);
+
+ int ExecuteAssembly(String assemblyFile,
+ Evidence assemblySecurity);
+
+ int ExecuteAssembly(String assemblyFile);
+
+ int ExecuteAssembly(String assemblyFile,
+ Evidence assemblySecurity,
+ String[] args);
+
+ String FriendlyName
+ { get; }
+#if FEATURE_FUSION
+ String BaseDirectory
+ {
+ get;
+ }
+
+ String RelativeSearchPath
+ { get; }
+
+ bool ShadowCopyFiles
+ { get; }
+#endif
+ Assembly[] GetAssemblies();
+#if FEATURE_FUSION
+ [System.Security.SecurityCritical] // auto-generated_required
+ void AppendPrivatePath(String path);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ClearPrivatePath();
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void SetShadowCopyPath (String s);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ClearShadowCopyPath ( );
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void SetCachePath (String s);
+#endif //FEATURE_FUSION
+ [System.Security.SecurityCritical] // auto-generated_required
+ void SetData(String name, Object data);
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ Object GetData(string name);
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated_required
+ void SetAppDomainPolicy(PolicyLevel domainPolicy);
+
+#if FEATURE_IMPERSONATION
+ void SetThreadPrincipal(IPrincipal principal);
+#endif // FEATURE_IMPERSONATION
+
+ void SetPrincipalPolicy(PrincipalPolicy policy);
+#endif
+
+#if FEATURE_REMOTING
+ void DoCallBack(CrossAppDomainDelegate theDelegate);
+#endif
+
+ String DynamicDirectory
+ { get; }
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/IAppDomainPauseManager.cs b/src/mscorlib/src/System/IAppDomainPauseManager.cs
new file mode 100644
index 0000000000..7e031454a4
--- /dev/null
+++ b/src/mscorlib/src/System/IAppDomainPauseManager.cs
@@ -0,0 +1,100 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: Interface meant for CLR to participate in framework rundown.
+** AppDomainPauseManager is the class that encapsulates all Fx rundown work.
+**
+**
+=============================================================================*/
+
+namespace System
+{
+ using System;
+ using System.Threading;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.Versioning;
+ using System.Runtime.CompilerServices;
+
+ [System.Security.SecurityCritical]
+ internal class AppDomainPauseManager
+ {
+ [System.Security.SecurityCritical]
+ public AppDomainPauseManager()
+ {
+ isPaused = false;
+ }
+
+ [System.Security.SecurityCritical]
+ static AppDomainPauseManager()
+ {
+ }
+
+ static readonly AppDomainPauseManager instance = new AppDomainPauseManager();
+ internal static AppDomainPauseManager Instance
+ {
+ [System.Security.SecurityCritical]
+ get { return instance; }
+ }
+
+ // FAS: IAppDomainPauseConsumer interface implementation
+ // currently there is nothing we do here as the implementation
+ // of updating pause times have been moved to native CorHost2
+ [System.Security.SecurityCritical]
+ public void Pausing()
+ {
+ }
+
+ [System.Security.SecurityCritical]
+ public void Paused()
+ {
+ Contract.Assert(!isPaused);
+
+ if(ResumeEvent == null)
+ ResumeEvent = new ManualResetEvent(false);
+ else
+ ResumeEvent.Reset();
+
+ Timer.Pause();
+
+ // Set IsPaused at the last as other threads seeing it set, will expect a valid
+ // reset ResumeEvent. Also the requirement here is that only after Paused
+ // returns other threads should block on this event. So there is a race condition here.
+ isPaused = true;
+ }
+
+ [System.Security.SecurityCritical]
+ public void Resuming()
+ {
+ Contract.Assert(isPaused);
+ isPaused = false;
+ ResumeEvent.Set();
+ }
+
+ [System.Security.SecurityCritical]
+ public void Resumed()
+ {
+ Timer.Resume();
+ }
+
+ private static volatile bool isPaused;
+
+ internal static bool IsPaused
+ {
+ [System.Security.SecurityCritical]
+ get { return isPaused; }
+ }
+
+ internal static ManualResetEvent ResumeEvent
+ {
+ [System.Security.SecurityCritical]
+ get;
+ [System.Security.SecurityCritical]
+ set;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IAppDomainSetup.cs b/src/mscorlib/src/System/IAppDomainSetup.cs
new file mode 100644
index 0000000000..a088c629d8
--- /dev/null
+++ b/src/mscorlib/src/System/IAppDomainSetup.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IAppDomainSetup
+**
+**
+**
+**
+** Purpose: Properties exposed to COM
+**
+**
+===========================================================*/
+namespace System {
+
+ using System.Runtime.InteropServices;
+
+ [GuidAttribute("27FFF232-A7A8-40dd-8D4A-734AD59FCD41")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IAppDomainSetup
+ {
+ String ApplicationBase {
+ get;
+ set;
+ }
+
+ String ApplicationName
+ {
+ get;
+ set;
+ }
+
+ String CachePath
+ {
+ get;
+ set;
+ }
+
+ String ConfigurationFile {
+ get;
+ set;
+ }
+
+ String DynamicBase
+ {
+ get;
+ set;
+ }
+
+ String LicenseFile
+ {
+ get;
+ set;
+ }
+
+ String PrivateBinPath
+ {
+ get;
+ set;
+ }
+
+ String PrivateBinPathProbe
+ {
+ get;
+ set;
+ }
+
+ String ShadowCopyDirectories
+ {
+ get;
+ set;
+ }
+
+ String ShadowCopyFiles
+ {
+ get;
+ set;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/IAsyncResult.cs b/src/mscorlib/src/System/IAsyncResult.cs
new file mode 100644
index 0000000000..2591c726c7
--- /dev/null
+++ b/src/mscorlib/src/System/IAsyncResult.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IAsyncResult
+**
+** Purpose: Interface to encapsulate the results of an async
+** operation
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Threading;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IAsyncResult
+ {
+ bool IsCompleted { get; }
+
+ WaitHandle AsyncWaitHandle { get; }
+
+
+ Object AsyncState { get; }
+
+ bool CompletedSynchronously { get; }
+
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/ICloneable.cs b/src/mscorlib/src/System/ICloneable.cs
new file mode 100644
index 0000000000..2931802539
--- /dev/null
+++ b/src/mscorlib/src/System/ICloneable.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** This interface is implemented by classes that support cloning.
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ // Defines an interface indicating that an object may be cloned. Only objects
+ // that implement ICloneable may be cloned. The interface defines a single
+ // method which is called to create a clone of the object. Object defines a method
+ // MemberwiseClone to support default clone operations.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICloneable
+ {
+ // Interface does not need to be marked with the serializable attribute
+ // Make a new object which is a copy of the object instanced. This object may be either
+ // deep copy or a shallow copy depending on the implementation of clone. The default
+ // Object support for clone does a shallow copy.
+ //
+ Object Clone();
+ }
+}
diff --git a/src/mscorlib/src/System/IComparable.cs b/src/mscorlib/src/System/IComparable.cs
new file mode 100644
index 0000000000..111d892129
--- /dev/null
+++ b/src/mscorlib/src/System/IComparable.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ // The IComparable interface is implemented by classes that support an
+ // ordering of instances of the class. The ordering represented by
+ // IComparable can be used to sort arrays and collections of objects
+ // that implement the interface.
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IComparable
+ {
+ // Interface does not need to be marked with the serializable attribute
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship. An implementation of this method must return
+ // a value less than zero if this is less than object, zero
+ // if this is equal to object, or a value greater than zero
+ // if this is greater than object.
+ //
+ int CompareTo(Object obj);
+ }
+
+ // Generic version of IComparable.
+
+ public interface IComparable<in T>
+ {
+ // Interface does not need to be marked with the serializable attribute
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship. An implementation of this method must return
+ // a value less than zero if this is less than object, zero
+ // if this is equal to object, or a value greater than zero
+ // if this is greater than object.
+ //
+ int CompareTo(T other);
+ }
+}
diff --git a/src/mscorlib/src/System/IConvertible.cs b/src/mscorlib/src/System/IConvertible.cs
new file mode 100644
index 0000000000..174b25b180
--- /dev/null
+++ b/src/mscorlib/src/System/IConvertible.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System.Diagnostics.Contracts;
+ using System.Threading;
+
+ // The IConvertible interface represents an object that contains a value. This
+ // interface is implemented by the following types in the System namespace:
+ // Boolean, Char, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64,
+ // Single, Double, Decimal, DateTime, TimeSpan, and String. The interface may
+ // be implemented by other types that are to be considered values. For example,
+ // a library of nullable database types could implement IConvertible.
+ //
+ // Note: The interface was originally proposed as IValue.
+ //
+ // The implementations of IConvertible provided by the System.XXX value classes
+ // simply forward to the appropriate Value.ToXXX(YYY) methods (a description of
+ // the Value class follows below). In cases where a Value.ToXXX(YYY) method
+ // does not exist (because the particular conversion is not supported), the
+ // IConvertible implementation should simply throw an InvalidCastException.
+
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IConvertible
+ {
+ // Returns the type code of this object. An implementation of this method
+ // must not return TypeCode.Empty (which represents a null reference) or
+ // TypeCode.Object (which represents an object that doesn't implement the
+ // IConvertible interface). An implementation of this method should return
+ // TypeCode.DBNull if the value of this object is a database null. For
+ // example, a nullable integer type should return TypeCode.DBNull if the
+ // value of the object is the database null. Otherwise, an implementation
+ // of this method should return the TypeCode that best describes the
+ // internal representation of the object.
+
+ TypeCode GetTypeCode();
+
+ // The ToXXX methods convert the value of the underlying object to the
+ // given type. If a particular conversion is not supported, the
+ // implementation must throw an InvalidCastException. If the value of the
+ // underlying object is not within the range of the target type, the
+ // implementation must throw an OverflowException. The
+ // IFormatProvider will be used to get a NumberFormatInfo or similar
+ // appropriate service object, and may safely be null.
+
+ bool ToBoolean(IFormatProvider provider);
+ char ToChar(IFormatProvider provider);
+ sbyte ToSByte(IFormatProvider provider);
+ byte ToByte(IFormatProvider provider);
+ short ToInt16(IFormatProvider provider);
+ ushort ToUInt16(IFormatProvider provider);
+ int ToInt32(IFormatProvider provider);
+ uint ToUInt32(IFormatProvider provider);
+ long ToInt64(IFormatProvider provider);
+ ulong ToUInt64(IFormatProvider provider);
+ float ToSingle(IFormatProvider provider);
+ double ToDouble(IFormatProvider provider);
+ Decimal ToDecimal(IFormatProvider provider);
+ DateTime ToDateTime(IFormatProvider provider);
+ String ToString(IFormatProvider provider);
+ Object ToType(Type conversionType, IFormatProvider provider);
+ }
+}
+
diff --git a/src/mscorlib/src/System/ICustomFormatter.cs b/src/mscorlib/src/System/ICustomFormatter.cs
new file mode 100644
index 0000000000..cbc3816a82
--- /dev/null
+++ b/src/mscorlib/src/System/ICustomFormatter.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ICustomFormatter
+**
+**
+** Purpose: Marks a class as providing special formatting
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICustomFormatter
+ {
+ // Interface does not need to be marked with the serializable attribute
+ String Format (String format, Object arg, IFormatProvider formatProvider);
+ }
+}
diff --git a/src/mscorlib/src/System/IDisposable.cs b/src/mscorlib/src/System/IDisposable.cs
new file mode 100644
index 0000000000..fcb65bea14
--- /dev/null
+++ b/src/mscorlib/src/System/IDisposable.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IDisposable
+**
+**
+** Purpose: Interface for assisting with deterministic finalization.
+**
+**
+===========================================================*/
+namespace System {
+ // IDisposable is an attempt at helping to solve problems with deterministic
+ // finalization. The GC of course doesn't leave any way to deterministically
+ // know when a finalizer will run. This forces classes that hold onto OS
+ // resources or some sort of important state (such as a FileStream or a
+ // network connection) to provide a Close or Dispose method so users can
+ // run clean up code deterministically. We have formalized this into an
+ // interface with one method. Classes may privately implement IDisposable and
+ // provide a Close method instead, if that name is by far the expected name
+ // for objects in that domain (ie, you don't Dispose of a FileStream, you Close
+ // it).
+ //
+ // This interface could be theoretically used as a marker by a compiler to
+ // ensure a disposable object has been cleaned up along all code paths if it's
+ // been allocated in that method, though in practice any compiler that
+ // draconian may tick off any number of people. Perhaps an external tool (like
+ // like Purify or BoundsChecker) could do this. Instead, C# has added a using
+ // clause, which will generate a try/finally statement where the resource
+ // passed into the using clause will always have it's Dispose method called.
+ // Syntax is using(FileStream fs = ...) { .. };
+ //
+ // Dispose should meet the following conditions:
+ // 1) Be safely callable multiple times
+ // 2) Release any resources associated with the instance
+ // 3) Call the base class's Dispose method, if necessary
+ // 4) Suppress finalization of this class to help the GC by reducing the
+ // number of objects on the finalization queue.
+ // 5) Dispose shouldn't generally throw exceptions, except for very serious
+ // errors that are particularly unexpected. (ie, OutOfMemoryException)
+ // Ideally, nothing should go wrong with your object by calling Dispose.
+ //
+ // If possible, a class should define a finalizer that calls Dispose.
+ // However, in many situations, this is impractical. For instance, take the
+ // classic example of a Stream and a StreamWriter (which has an internal
+ // buffer of data to write to the Stream). If both objects are collected
+ // before Close or Dispose has been called on either, then the GC may run the
+ // finalizer for the Stream first, before the StreamWriter. At that point, any
+ // data buffered by the StreamWriter cannot be written to the Stream. In this
+ // case, it doesn't make much sense to provide a finalizer on the StreamWriter
+ // since you cannot solve this problem correctly.
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IDisposable {
+ void Dispose();
+ }
+}
diff --git a/src/mscorlib/src/System/IEquatable.cs b/src/mscorlib/src/System/IEquatable.cs
new file mode 100644
index 0000000000..aa034da68c
--- /dev/null
+++ b/src/mscorlib/src/System/IEquatable.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ public interface IEquatable<T>
+ {
+ bool Equals(T other);
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/IFormatProvider.cs b/src/mscorlib/src/System/IFormatProvider.cs
new file mode 100644
index 0000000000..a5cc783969
--- /dev/null
+++ b/src/mscorlib/src/System/IFormatProvider.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Notes a class which knows how to return formatting information
+**
+**
+============================================================*/
+namespace System {
+
+ using System;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IFormatProvider
+ {
+ // Interface does not need to be marked with the serializable attribute
+ Object GetFormat(Type formatType);
+ }
+}
diff --git a/src/mscorlib/src/System/IFormattable.cs b/src/mscorlib/src/System/IFormattable.cs
new file mode 100644
index 0000000000..414b4686df
--- /dev/null
+++ b/src/mscorlib/src/System/IFormattable.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IFormattable
+ {
+ [Pure]
+ String ToString(String format, IFormatProvider formatProvider);
+ }
+}
diff --git a/src/mscorlib/src/System/IO/BinaryReader.cs b/src/mscorlib/src/System/IO/BinaryReader.cs
new file mode 100644
index 0000000000..8accf0bd77
--- /dev/null
+++ b/src/mscorlib/src/System/IO/BinaryReader.cs
@@ -0,0 +1,601 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Wraps a stream and provides convenient read functionality
+** for strings and primitive types.
+**
+**
+============================================================*/
+namespace System.IO {
+
+ using System;
+ using System.Runtime;
+ using System.Text;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class BinaryReader : IDisposable
+ {
+ private const int MaxCharBytesSize = 128;
+
+ private Stream m_stream;
+ private byte[] m_buffer;
+ private Decoder m_decoder;
+ private byte[] m_charBytes;
+ private char[] m_singleChar;
+ private char[] m_charBuffer;
+ private int m_maxCharsSize; // From MaxCharBytesSize & Encoding
+
+ // Performance optimization for Read() w/ Unicode. Speeds us up by ~40%
+ private bool m_2BytesPerChar;
+ private bool m_isMemoryStream; // "do we sit on MemoryStream?" for Read/ReadInt32 perf
+ private bool m_leaveOpen;
+
+ public BinaryReader(Stream input) : this(input, new UTF8Encoding(), false) {
+ }
+
+ public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) {
+ }
+
+ public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) {
+ if (input==null) {
+ throw new ArgumentNullException("input");
+ }
+ if (encoding==null) {
+ throw new ArgumentNullException("encoding");
+ }
+ if (!input.CanRead)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));
+ Contract.EndContractBlock();
+ m_stream = input;
+ m_decoder = encoding.GetDecoder();
+ m_maxCharsSize = encoding.GetMaxCharCount(MaxCharBytesSize);
+ int minBufferSize = encoding.GetMaxByteCount(1); // max bytes per one char
+ if (minBufferSize < 16)
+ minBufferSize = 16;
+ m_buffer = new byte[minBufferSize];
+ // m_charBuffer and m_charBytes will be left null.
+
+ // For Encodings that always use 2 bytes per char (or more),
+ // special case them here to make Read() & Peek() faster.
+ m_2BytesPerChar = encoding is UnicodeEncoding;
+ // check if BinaryReader is based on MemoryStream, and keep this for it's life
+ // we cannot use "as" operator, since derived classes are not allowed
+ m_isMemoryStream = (m_stream.GetType() == typeof(MemoryStream));
+ m_leaveOpen = leaveOpen;
+
+ Contract.Assert(m_decoder!=null, "[BinaryReader.ctor]m_decoder!=null");
+ }
+
+ public virtual Stream BaseStream {
+ get {
+ return m_stream;
+ }
+ }
+
+ public virtual void Close() {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ if (disposing) {
+ Stream copyOfStream = m_stream;
+ m_stream = null;
+ if (copyOfStream != null && !m_leaveOpen)
+ copyOfStream.Close();
+ }
+ m_stream = null;
+ m_buffer = null;
+ m_decoder = null;
+ m_charBytes = null;
+ m_singleChar = null;
+ m_charBuffer = null;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public virtual int PeekChar() {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+
+ if (m_stream==null) __Error.FileNotOpen();
+
+ if (!m_stream.CanSeek)
+ return -1;
+ long origPos = m_stream.Position;
+ int ch = Read();
+ m_stream.Position = origPos;
+ return ch;
+ }
+
+ public virtual int Read() {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+
+ if (m_stream==null) {
+ __Error.FileNotOpen();
+ }
+ return InternalReadOneChar();
+ }
+
+ public virtual bool ReadBoolean(){
+ FillBuffer(1);
+ return (m_buffer[0]!=0);
+ }
+
+ public virtual byte ReadByte() {
+ // Inlined to avoid some method call overhead with FillBuffer.
+ if (m_stream==null) __Error.FileNotOpen();
+
+ int b = m_stream.ReadByte();
+ if (b == -1)
+ __Error.EndOfFile();
+ return (byte) b;
+ }
+
+ [CLSCompliant(false)]
+ public virtual sbyte ReadSByte() {
+ FillBuffer(1);
+ return (sbyte)(m_buffer[0]);
+ }
+
+ public virtual char ReadChar() {
+ int value = Read();
+ if (value==-1) {
+ __Error.EndOfFile();
+ }
+ return (char)value;
+ }
+
+ public virtual short ReadInt16() {
+ FillBuffer(2);
+ return (short)(m_buffer[0] | m_buffer[1] << 8);
+ }
+
+ [CLSCompliant(false)]
+ public virtual ushort ReadUInt16(){
+ FillBuffer(2);
+ return (ushort)(m_buffer[0] | m_buffer[1] << 8);
+ }
+
+ public virtual int ReadInt32() {
+ if (m_isMemoryStream) {
+ if (m_stream==null) __Error.FileNotOpen();
+ // read directly from MemoryStream buffer
+ MemoryStream mStream = m_stream as MemoryStream;
+ Contract.Assert(mStream != null, "m_stream as MemoryStream != null");
+
+ return mStream.InternalReadInt32();
+ }
+ else
+ {
+ FillBuffer(4);
+ return (int)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24);
+ }
+ }
+
+ [CLSCompliant(false)]
+ public virtual uint ReadUInt32() {
+ FillBuffer(4);
+ return (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24);
+ }
+
+ public virtual long ReadInt64() {
+ FillBuffer(8);
+ uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 |
+ m_buffer[2] << 16 | m_buffer[3] << 24);
+ uint hi = (uint)(m_buffer[4] | m_buffer[5] << 8 |
+ m_buffer[6] << 16 | m_buffer[7] << 24);
+ return (long) ((ulong)hi) << 32 | lo;
+ }
+
+ [CLSCompliant(false)]
+ public virtual ulong ReadUInt64() {
+ FillBuffer(8);
+ uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 |
+ m_buffer[2] << 16 | m_buffer[3] << 24);
+ uint hi = (uint)(m_buffer[4] | m_buffer[5] << 8 |
+ m_buffer[6] << 16 | m_buffer[7] << 24);
+ return ((ulong)hi) << 32 | lo;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual unsafe float ReadSingle() {
+ FillBuffer(4);
+ uint tmpBuffer = (uint)(m_buffer[0] | m_buffer[1] << 8 | m_buffer[2] << 16 | m_buffer[3] << 24);
+ return *((float*)&tmpBuffer);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual unsafe double ReadDouble() {
+ FillBuffer(8);
+ uint lo = (uint)(m_buffer[0] | m_buffer[1] << 8 |
+ m_buffer[2] << 16 | m_buffer[3] << 24);
+ uint hi = (uint)(m_buffer[4] | m_buffer[5] << 8 |
+ m_buffer[6] << 16 | m_buffer[7] << 24);
+
+ ulong tmpBuffer = ((ulong)hi) << 32 | lo;
+ return *((double*)&tmpBuffer);
+ }
+
+ public virtual decimal ReadDecimal() {
+ FillBuffer(16);
+ try {
+ return Decimal.ToDecimal(m_buffer);
+ }
+ catch (ArgumentException e) {
+ // ReadDecimal cannot leak out ArgumentException
+ throw new IOException(Environment.GetResourceString("Arg_DecBitCtor"), e);
+ }
+ }
+
+ public virtual String ReadString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ if (m_stream == null)
+ __Error.FileNotOpen();
+
+ int currPos = 0;
+ int n;
+ int stringLength;
+ int readLength;
+ int charsRead;
+
+ // Length of the string in bytes, not chars
+ stringLength = Read7BitEncodedInt();
+ if (stringLength<0) {
+ throw new IOException(Environment.GetResourceString("IO.IO_InvalidStringLen_Len", stringLength));
+ }
+
+ if (stringLength==0) {
+ return String.Empty;
+ }
+
+ if (m_charBytes==null) {
+ m_charBytes = new byte[MaxCharBytesSize];
+ }
+
+ if (m_charBuffer == null) {
+ m_charBuffer = new char[m_maxCharsSize];
+ }
+
+ StringBuilder sb = null;
+ do
+ {
+ readLength = ((stringLength - currPos)>MaxCharBytesSize)?MaxCharBytesSize:(stringLength - currPos);
+
+ n = m_stream.Read(m_charBytes, 0, readLength);
+ if (n==0) {
+ __Error.EndOfFile();
+ }
+
+ charsRead = m_decoder.GetChars(m_charBytes, 0, n, m_charBuffer, 0);
+
+ if (currPos == 0 && n == stringLength)
+ return new String(m_charBuffer, 0, charsRead);
+
+ if (sb == null)
+ sb = StringBuilderCache.Acquire(stringLength); // Actual string length in chars may be smaller.
+ sb.Append(m_charBuffer, 0, charsRead);
+ currPos +=n;
+
+ } while (currPos<stringLength);
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ [SecuritySafeCritical]
+ public virtual int Read(char[] buffer, int index, int count) {
+ if (buffer==null) {
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ }
+ if (index < 0) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (buffer.Length - index < count) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ }
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= count);
+ Contract.EndContractBlock();
+
+ if (m_stream==null)
+ __Error.FileNotOpen();
+
+ // SafeCritical: index and count have already been verified to be a valid range for the buffer
+ return InternalReadChars(buffer, index, count);
+ }
+
+ [SecurityCritical]
+ private int InternalReadChars(char[] buffer, int index, int count) {
+ Contract.Requires(buffer != null);
+ Contract.Requires(index >= 0 && count >= 0);
+ Contract.Assert(m_stream != null);
+
+ int numBytes = 0;
+ int charsRemaining = count;
+
+ if (m_charBytes==null) {
+ m_charBytes = new byte[MaxCharBytesSize];
+ }
+
+ while (charsRemaining > 0) {
+ int charsRead = 0;
+ // We really want to know what the minimum number of bytes per char
+ // is for our encoding. Otherwise for UnicodeEncoding we'd have to
+ // do ~1+log(n) reads to read n characters.
+ numBytes = charsRemaining;
+
+ // special case for DecoderNLS subclasses when there is a hanging byte from the previous loop
+ DecoderNLS decoder = m_decoder as DecoderNLS;
+ if (decoder != null && decoder.HasState && numBytes > 1) {
+ numBytes -= 1;
+ }
+
+ if (m_2BytesPerChar)
+ numBytes <<= 1;
+ if (numBytes > MaxCharBytesSize)
+ numBytes = MaxCharBytesSize;
+
+ int position = 0;
+ byte[] byteBuffer = null;
+ if (m_isMemoryStream)
+ {
+ MemoryStream mStream = m_stream as MemoryStream;
+ Contract.Assert(mStream != null, "m_stream as MemoryStream != null");
+
+ position = mStream.InternalGetPosition();
+ numBytes = mStream.InternalEmulateRead(numBytes);
+ byteBuffer = mStream.InternalGetBuffer();
+ }
+ else
+ {
+ numBytes = m_stream.Read(m_charBytes, 0, numBytes);
+ byteBuffer = m_charBytes;
+ }
+
+ if (numBytes == 0) {
+ return (count - charsRemaining);
+ }
+
+ Contract.Assert(byteBuffer != null, "expected byteBuffer to be non-null");
+
+ checked
+ {
+ if (position < 0 || numBytes < 0 || position > byteBuffer.Length - numBytes)
+ {
+ throw new ArgumentOutOfRangeException(nameof(numBytes));
+ }
+ if (index < 0 || charsRemaining < 0 || index > buffer.Length - charsRemaining)
+ {
+ throw new ArgumentOutOfRangeException(nameof(charsRemaining));
+ }
+ unsafe
+ {
+ fixed (byte* pBytes = byteBuffer)
+ fixed (char* pChars = buffer)
+ {
+ charsRead = m_decoder.GetChars(pBytes + position, numBytes, pChars + index, charsRemaining, flush: false);
+ }
+ }
+ }
+
+ charsRemaining -= charsRead;
+ index+=charsRead;
+ }
+
+ // this should never fail
+ Contract.Assert(charsRemaining >= 0, "We read too many characters.");
+
+ // we may have read fewer than the number of characters requested if end of stream reached
+ // or if the encoding makes the char count too big for the buffer (e.g. fallback sequence)
+ return (count - charsRemaining);
+ }
+
+ private int InternalReadOneChar() {
+ // I know having a separate InternalReadOneChar method seems a little
+ // redundant, but this makes a scenario like the security parser code
+ // 20% faster, in addition to the optimizations for UnicodeEncoding I
+ // put in InternalReadChars.
+ int charsRead = 0;
+ int numBytes = 0;
+ long posSav = posSav = 0;
+
+ if (m_stream.CanSeek)
+ posSav = m_stream.Position;
+
+ if (m_charBytes==null) {
+ m_charBytes = new byte[MaxCharBytesSize];
+ }
+ if (m_singleChar==null) {
+ m_singleChar = new char[1];
+ }
+
+ while (charsRead == 0) {
+ // We really want to know what the minimum number of bytes per char
+ // is for our encoding. Otherwise for UnicodeEncoding we'd have to
+ // do ~1+log(n) reads to read n characters.
+ // Assume 1 byte can be 1 char unless m_2BytesPerChar is true.
+ numBytes = m_2BytesPerChar ? 2 : 1;
+
+ int r = m_stream.ReadByte();
+ m_charBytes[0] = (byte) r;
+ if (r == -1)
+ numBytes = 0;
+ if (numBytes == 2) {
+ r = m_stream.ReadByte();
+ m_charBytes[1] = (byte) r;
+ if (r == -1)
+ numBytes = 1;
+ }
+
+ if (numBytes==0) {
+ // Console.WriteLine("Found no bytes. We're outta here.");
+ return -1;
+ }
+
+ Contract.Assert(numBytes == 1 || numBytes == 2, "BinaryReader::InternalReadOneChar assumes it's reading one or 2 bytes only.");
+
+ try {
+
+ charsRead = m_decoder.GetChars(m_charBytes, 0, numBytes, m_singleChar, 0);
+ }
+ catch
+ {
+ // Handle surrogate char
+
+ if (m_stream.CanSeek)
+ m_stream.Seek((posSav - m_stream.Position), SeekOrigin.Current);
+ // else - we can't do much here
+
+ throw;
+ }
+
+ Contract.Assert(charsRead < 2, "InternalReadOneChar - assuming we only got 0 or 1 char, not 2!");
+ // Console.WriteLine("That became: " + charsRead + " characters.");
+ }
+ if (charsRead == 0)
+ return -1;
+ return m_singleChar[0];
+ }
+
+ [SecuritySafeCritical]
+ public virtual char[] ReadChars(int count) {
+ if (count<0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.Ensures(Contract.Result<char[]>() != null);
+ Contract.Ensures(Contract.Result<char[]>().Length <= count);
+ Contract.EndContractBlock();
+ if (m_stream == null) {
+ __Error.FileNotOpen();
+ }
+
+ if (count == 0) {
+ return EmptyArray<Char>.Value;
+ }
+
+ // SafeCritical: we own the chars buffer, and therefore can guarantee that the index and count are valid
+ char[] chars = new char[count];
+ int n = InternalReadChars(chars, 0, count);
+ if (n!=count) {
+ char[] copy = new char[n];
+ Buffer.InternalBlockCopy(chars, 0, copy, 0, 2*n); // sizeof(char)
+ chars = copy;
+ }
+
+ return chars;
+ }
+
+ public virtual int Read(byte[] buffer, int index, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= count);
+ Contract.EndContractBlock();
+
+ if (m_stream==null) __Error.FileNotOpen();
+ return m_stream.Read(buffer, index, count);
+ }
+
+ public virtual byte[] ReadBytes(int count) {
+ if (count < 0) throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length <= Contract.OldValue(count));
+ Contract.EndContractBlock();
+ if (m_stream==null) __Error.FileNotOpen();
+
+ if (count == 0) {
+ return EmptyArray<Byte>.Value;
+ }
+
+ byte[] result = new byte[count];
+
+ int numRead = 0;
+ do {
+ int n = m_stream.Read(result, numRead, count);
+ if (n == 0)
+ break;
+ numRead += n;
+ count -= n;
+ } while (count > 0);
+
+ if (numRead != result.Length) {
+ // Trim array. This should happen on EOF & possibly net streams.
+ byte[] copy = new byte[numRead];
+ Buffer.InternalBlockCopy(result, 0, copy, 0, numRead);
+ result = copy;
+ }
+
+ return result;
+ }
+
+ protected virtual void FillBuffer(int numBytes) {
+ if (m_buffer != null && (numBytes < 0 || numBytes > m_buffer.Length)) {
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_BinaryReaderFillBuffer"));
+ }
+ int bytesRead=0;
+ int n = 0;
+
+ if (m_stream==null) __Error.FileNotOpen();
+
+ // Need to find a good threshold for calling ReadByte() repeatedly
+ // vs. calling Read(byte[], int, int) for both buffered & unbuffered
+ // streams.
+ if (numBytes==1) {
+ n = m_stream.ReadByte();
+ if (n==-1)
+ __Error.EndOfFile();
+ m_buffer[0] = (byte)n;
+ return;
+ }
+
+ do {
+ n = m_stream.Read(m_buffer, bytesRead, numBytes-bytesRead);
+ if (n==0) {
+ __Error.EndOfFile();
+ }
+ bytesRead+=n;
+ } while (bytesRead<numBytes);
+ }
+
+ internal protected int Read7BitEncodedInt() {
+ // Read out an Int32 7 bits at a time. The high bit
+ // of the byte when on means to continue reading more bytes.
+ int count = 0;
+ int shift = 0;
+ byte b;
+ do {
+ // Check for a corrupted stream. Read a max of 5 bytes.
+ // In a future version, add a DataFormatException.
+ if (shift == 5 * 7) // 5 bytes max per Int32, shift += 7
+ throw new FormatException(Environment.GetResourceString("Format_Bad7BitInt32"));
+
+ // ReadByte handles end of stream cases for us.
+ b = ReadByte();
+ count |= (b & 0x7F) << shift;
+ shift += 7;
+ } while ((b & 0x80) != 0);
+ return count;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/BinaryWriter.cs b/src/mscorlib/src/System/IO/BinaryWriter.cs
new file mode 100644
index 0000000000..c775cbc9ff
--- /dev/null
+++ b/src/mscorlib/src/System/IO/BinaryWriter.cs
@@ -0,0 +1,427 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Provides a way to write primitives types in
+** binary from a Stream, while also supporting writing Strings
+** in a particular encoding.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ // This abstract base class represents a writer that can write
+ // primitives to an arbitrary stream. A subclass can override methods to
+ // give unique encodings.
+ //
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class BinaryWriter : IDisposable
+ {
+ public static readonly BinaryWriter Null = new BinaryWriter();
+
+ protected Stream OutStream;
+ private byte[] _buffer; // temp space for writing primitives to.
+ private Encoding _encoding;
+ private Encoder _encoder;
+
+ [OptionalField] // New in .NET FX 4.5. False is the right default value.
+ private bool _leaveOpen;
+
+ // This field should never have been serialized and has not been used since before v2.0.
+ // However, this type is serializable, and we need to keep the field name around when deserializing.
+ // Also, we'll make .NET FX 4.5 not break if it's missing.
+#pragma warning disable 169
+ [OptionalField]
+ private char[] _tmpOneCharBuffer;
+#pragma warning restore 169
+
+ // Perf optimization stuff
+ private byte[] _largeByteBuffer; // temp space for writing chars.
+ private int _maxChars; // max # of chars we can put in _largeByteBuffer
+ // Size should be around the max number of chars/string * Encoding's max bytes/char
+ private const int LargeByteBufferSize = 256;
+
+ // Protected default constructor that sets the output stream
+ // to a null stream (a bit bucket).
+ protected BinaryWriter()
+ {
+ OutStream = Stream.Null;
+ _buffer = new byte[16];
+ _encoding = new UTF8Encoding(false, true);
+ _encoder = _encoding.GetEncoder();
+ }
+
+ public BinaryWriter(Stream output) : this(output, new UTF8Encoding(false, true), false)
+ {
+ }
+
+ public BinaryWriter(Stream output, Encoding encoding) : this(output, encoding, false)
+ {
+ }
+
+ public BinaryWriter(Stream output, Encoding encoding, bool leaveOpen)
+ {
+ if (output==null)
+ throw new ArgumentNullException("output");
+ if (encoding==null)
+ throw new ArgumentNullException("encoding");
+ if (!output.CanWrite)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable"));
+ Contract.EndContractBlock();
+
+ OutStream = output;
+ _buffer = new byte[16];
+ _encoding = encoding;
+ _encoder = _encoding.GetEncoder();
+ _leaveOpen = leaveOpen;
+ }
+
+ // Closes this writer and releases any system resources associated with the
+ // writer. Following a call to Close, any operations on the writer
+ // may raise exceptions.
+ public virtual void Close()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing) {
+ if (_leaveOpen)
+ OutStream.Flush();
+ else
+ OutStream.Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ /*
+ * Returns the stream associate with the writer. It flushes all pending
+ * writes before returning. All subclasses should override Flush to
+ * ensure that all buffered data is sent to the stream.
+ */
+ public virtual Stream BaseStream {
+ get {
+ Flush();
+ return OutStream;
+ }
+ }
+
+ // Clears all buffers for this writer and causes any buffered data to be
+ // written to the underlying device.
+ public virtual void Flush()
+ {
+ OutStream.Flush();
+ }
+
+ public virtual long Seek(int offset, SeekOrigin origin)
+ {
+ return OutStream.Seek(offset, origin);
+ }
+
+ // Writes a boolean to this stream. A single byte is written to the stream
+ // with the value 0 representing false or the value 1 representing true.
+ //
+ public virtual void Write(bool value) {
+ _buffer[0] = (byte) (value ? 1 : 0);
+ OutStream.Write(_buffer, 0, 1);
+ }
+
+ // Writes a byte to this stream. The current position of the stream is
+ // advanced by one.
+ //
+ public virtual void Write(byte value)
+ {
+ OutStream.WriteByte(value);
+ }
+
+ // Writes a signed byte to this stream. The current position of the stream
+ // is advanced by one.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(sbyte value)
+ {
+ OutStream.WriteByte((byte) value);
+ }
+
+ // Writes a byte array to this stream.
+ //
+ // This default implementation calls the Write(Object, int, int)
+ // method to write the byte array.
+ //
+ public virtual void Write(byte[] buffer) {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+ Contract.EndContractBlock();
+ OutStream.Write(buffer, 0, buffer.Length);
+ }
+
+ // Writes a section of a byte array to this stream.
+ //
+ // This default implementation calls the Write(Object, int, int)
+ // method to write the byte array.
+ //
+ public virtual void Write(byte[] buffer, int index, int count) {
+ OutStream.Write(buffer, index, count);
+ }
+
+
+ // Writes a character to this stream. The current position of the stream is
+ // advanced by two.
+ // Note this method cannot handle surrogates properly in UTF-8.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual void Write(char ch) {
+ if (Char.IsSurrogate(ch))
+ throw new ArgumentException(Environment.GetResourceString("Arg_SurrogatesNotAllowedAsSingleChar"));
+ Contract.EndContractBlock();
+
+ Contract.Assert(_encoding.GetMaxByteCount(1) <= 16, "_encoding.GetMaxByteCount(1) <= 16)");
+ int numBytes = 0;
+ fixed(byte * pBytes = _buffer) {
+ numBytes = _encoder.GetBytes(&ch, 1, pBytes, _buffer.Length, flush: true);
+ }
+ OutStream.Write(_buffer, 0, numBytes);
+ }
+
+ // Writes a character array to this stream.
+ //
+ // This default implementation calls the Write(Object, int, int)
+ // method to write the character array.
+ //
+ public virtual void Write(char[] chars)
+ {
+ if (chars == null)
+ throw new ArgumentNullException("chars");
+ Contract.EndContractBlock();
+
+ byte[] bytes = _encoding.GetBytes(chars, 0, chars.Length);
+ OutStream.Write(bytes, 0, bytes.Length);
+ }
+
+ // Writes a section of a character array to this stream.
+ //
+ // This default implementation calls the Write(Object, int, int)
+ // method to write the character array.
+ //
+ public virtual void Write(char[] chars, int index, int count)
+ {
+ byte[] bytes = _encoding.GetBytes(chars, index, count);
+ OutStream.Write(bytes, 0, bytes.Length);
+ }
+
+
+ // Writes a double to this stream. The current position of the stream is
+ // advanced by eight.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual void Write(double value)
+ {
+ ulong TmpValue = *(ulong *)&value;
+ _buffer[0] = (byte) TmpValue;
+ _buffer[1] = (byte) (TmpValue >> 8);
+ _buffer[2] = (byte) (TmpValue >> 16);
+ _buffer[3] = (byte) (TmpValue >> 24);
+ _buffer[4] = (byte) (TmpValue >> 32);
+ _buffer[5] = (byte) (TmpValue >> 40);
+ _buffer[6] = (byte) (TmpValue >> 48);
+ _buffer[7] = (byte) (TmpValue >> 56);
+ OutStream.Write(_buffer, 0, 8);
+ }
+
+ public virtual void Write(decimal value)
+ {
+ Decimal.GetBytes(value,_buffer);
+ OutStream.Write(_buffer, 0, 16);
+ }
+
+ // Writes a two-byte signed integer to this stream. The current position of
+ // the stream is advanced by two.
+ //
+ public virtual void Write(short value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ OutStream.Write(_buffer, 0, 2);
+ }
+
+ // Writes a two-byte unsigned integer to this stream. The current position
+ // of the stream is advanced by two.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(ushort value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ OutStream.Write(_buffer, 0, 2);
+ }
+
+ // Writes a four-byte signed integer to this stream. The current position
+ // of the stream is advanced by four.
+ //
+ public virtual void Write(int value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ _buffer[2] = (byte) (value >> 16);
+ _buffer[3] = (byte) (value >> 24);
+ OutStream.Write(_buffer, 0, 4);
+ }
+
+ // Writes a four-byte unsigned integer to this stream. The current position
+ // of the stream is advanced by four.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(uint value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ _buffer[2] = (byte) (value >> 16);
+ _buffer[3] = (byte) (value >> 24);
+ OutStream.Write(_buffer, 0, 4);
+ }
+
+ // Writes an eight-byte signed integer to this stream. The current position
+ // of the stream is advanced by eight.
+ //
+ public virtual void Write(long value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ _buffer[2] = (byte) (value >> 16);
+ _buffer[3] = (byte) (value >> 24);
+ _buffer[4] = (byte) (value >> 32);
+ _buffer[5] = (byte) (value >> 40);
+ _buffer[6] = (byte) (value >> 48);
+ _buffer[7] = (byte) (value >> 56);
+ OutStream.Write(_buffer, 0, 8);
+ }
+
+ // Writes an eight-byte unsigned integer to this stream. The current
+ // position of the stream is advanced by eight.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(ulong value)
+ {
+ _buffer[0] = (byte) value;
+ _buffer[1] = (byte) (value >> 8);
+ _buffer[2] = (byte) (value >> 16);
+ _buffer[3] = (byte) (value >> 24);
+ _buffer[4] = (byte) (value >> 32);
+ _buffer[5] = (byte) (value >> 40);
+ _buffer[6] = (byte) (value >> 48);
+ _buffer[7] = (byte) (value >> 56);
+ OutStream.Write(_buffer, 0, 8);
+ }
+
+ // Writes a float to this stream. The current position of the stream is
+ // advanced by four.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual void Write(float value)
+ {
+ uint TmpValue = *(uint *)&value;
+ _buffer[0] = (byte) TmpValue;
+ _buffer[1] = (byte) (TmpValue >> 8);
+ _buffer[2] = (byte) (TmpValue >> 16);
+ _buffer[3] = (byte) (TmpValue >> 24);
+ OutStream.Write(_buffer, 0, 4);
+ }
+
+
+ // Writes a length-prefixed string to this stream in the BinaryWriter's
+ // current Encoding. This method first writes the length of the string as
+ // a four-byte unsigned integer, and then writes that many characters
+ // to the stream.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe virtual void Write(String value)
+ {
+ if (value==null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ int len = _encoding.GetByteCount(value);
+ Write7BitEncodedInt(len);
+
+ if (_largeByteBuffer == null) {
+ _largeByteBuffer = new byte[LargeByteBufferSize];
+ _maxChars = _largeByteBuffer.Length / _encoding.GetMaxByteCount(1);
+ }
+
+ 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);
+ }
+ else {
+ // Aggressively try to not allocate memory in this loop for
+ // runtime performance reasons. Use an Encoder to write out
+ // the string correctly (handling surrogates crossing buffer
+ // boundaries properly).
+ int charStart = 0;
+ int numLeft = value.Length;
+#if _DEBUG
+ int totalBytes = 0;
+#endif
+ while (numLeft > 0) {
+ // Figure out how many chars to process this round.
+ int charCount = (numLeft > _maxChars) ? _maxChars : numLeft;
+ int byteLen;
+
+ checked
+ {
+ if (charStart < 0 || charCount < 0 || charStart > value.Length - charCount)
+ {
+ throw new ArgumentOutOfRangeException(nameof(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 <= _largeByteBuffer.Length, "BinaryWriter::Write(String) - More bytes encoded than expected!");
+#endif
+ OutStream.Write(_largeByteBuffer, 0, byteLen);
+ charStart += charCount;
+ numLeft -= charCount;
+ }
+#if _DEBUG
+ Contract.Assert(totalBytes == len, "BinaryWriter::Write(String) - Didn't write out all the bytes!");
+#endif
+ }
+ }
+
+ protected void Write7BitEncodedInt(int value) {
+ // Write out an int 7 bits at a time. The high bit of the byte,
+ // when on, tells reader to continue reading more bytes.
+ uint v = (uint) value; // support negative numbers
+ while (v >= 0x80) {
+ Write((byte) (v | 0x80));
+ v >>= 7;
+ }
+ Write((byte)v);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/BufferedStream.cs b/src/mscorlib/src/System/IO/BufferedStream.cs
new file mode 100644
index 0000000000..0c73b5c0f5
--- /dev/null
+++ b/src/mscorlib/src/System/IO/BufferedStream.cs
@@ -0,0 +1,1320 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: A composable Stream that buffers reads & writes to the underlying stream.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Collections.ObjectModel;
+using System.Security;
+using System.Threading.Tasks;
+
+namespace System.IO {
+
+/// <summary>
+/// One of the design goals here is to prevent the buffer from getting in the way and slowing
+/// down underlying stream accesses when it is not needed. If you always read & write for sizes
+/// greater than the internal buffer size, then this class may not even allocate the internal buffer.
+/// See a large comment in Write for the details of the write buffer heuristic.
+///
+/// This class buffers reads & writes in a shared buffer.
+/// (If you maintained two buffers separately, one operation would always trash the other buffer
+/// anyways, so we might as well use one buffer.)
+/// The assumption here is you will almost always be doing a series of reads or writes, but rarely
+/// alternate between the two of them on the same stream.
+///
+/// Class Invariants:
+/// The class has one buffer, shared for reading & writing.
+/// It can only be used for one or the other at any point in time - not both.
+/// The following should be true:
+/// <![CDATA[
+/// * 0 <= _readPos <= _readLen < _bufferSize
+/// * 0 <= _writePos < _bufferSize
+/// * _readPos == _readLen && _readPos > 0 implies the read buffer is valid, but we're at the end of the buffer.
+/// * _readPos == _readLen == 0 means the read buffer contains garbage.
+/// * Either _writePos can be greater than 0, or _readLen & _readPos can be greater than zero,
+/// but neither can be greater than zero at the same time.
+/// ]]>
+/// This class will never cache more bytes than the max specified buffer size.
+/// However, it may use a temporary buffer of up to twice the size in order to combine several IO operations on
+/// the underlying stream into a single operation. This is because we assume that memory copies are significantly
+/// faster than IO operations on the underlying stream (if this was not true, using buffering is never appropriate).
+/// The max size of this "shadow" buffer is limited as to not allocate it on the LOH.
+/// Shadowing is always transient. Even when using this technique, this class still guarantees that the number of
+/// bytes cached (not yet written to the target stream or not yet consumed by the user) is never larger than the
+/// actual specified buffer size.
+/// </summary>
+[ComVisible(true)]
+public sealed class BufferedStream : Stream {
+
+
+ private const Int32 _DefaultBufferSize = 4096;
+
+
+ private Stream _stream; // Underlying stream. Close sets _stream to null.
+
+ private Byte[] _buffer; // Shared read/write buffer. Alloc on first use.
+
+ private readonly Int32 _bufferSize; // Length of internal buffer (not counting the shadow buffer).
+
+ private Int32 _readPos; // Read pointer within shared buffer.
+ private Int32 _readLen; // Number of bytes read in buffer from _stream.
+ private Int32 _writePos; // Write pointer within shared buffer.
+
+ private BeginEndAwaitableAdapter _beginEndAwaitable; // Used to be able to await a BeginXxx call and thus to share code
+ // between the APM and Async pattern implementations
+
+ private Task<Int32> _lastSyncCompletedReadTask; // The last successful Task returned from ReadAsync
+ // (perf optimization for successive reads of the same size)
+
+
+ // Removing a private default constructor is a breaking change for the DataContractSerializer.
+ // Because this ctor was here previously we need to keep it around.
+ private BufferedStream() { }
+
+
+ public BufferedStream(Stream stream)
+
+ : this(stream, _DefaultBufferSize) {
+ }
+
+
+ public BufferedStream(Stream stream, Int32 bufferSize) {
+
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "bufferSize"));
+
+ Contract.EndContractBlock();
+
+ BCLDebug.Perf(!(stream is FileStream), "FileStream is buffered - don't wrap it in a BufferedStream");
+ BCLDebug.Perf(!(stream is MemoryStream), "MemoryStream shouldn't be wrapped in a BufferedStream!");
+ BCLDebug.Perf(!(stream is BufferedStream), "BufferedStream shouldn't be wrapped in another BufferedStream!");
+
+ _stream = stream;
+ _bufferSize = bufferSize;
+
+ // Allocate _buffer on its first use - it will not be used if all reads
+ // & writes are greater than or equal to buffer size.
+
+ if (!_stream.CanRead && !_stream.CanWrite)
+ __Error.StreamIsClosed();
+ }
+
+
+ private void EnsureNotClosed() {
+
+ if (_stream == null)
+ __Error.StreamIsClosed();
+ }
+
+
+ private void EnsureCanSeek() {
+
+ Contract.Requires(_stream != null);
+
+ if (!_stream.CanSeek)
+ __Error.SeekNotSupported();
+ }
+
+
+ private void EnsureCanRead() {
+
+ Contract.Requires(_stream != null);
+
+ if (!_stream.CanRead)
+ __Error.ReadNotSupported();
+ }
+
+
+ private void EnsureCanWrite() {
+
+ Contract.Requires(_stream != null);
+
+ if (!_stream.CanWrite)
+ __Error.WriteNotSupported();
+ }
+
+
+ private void EnsureBeginEndAwaitableAllocated() {
+ // We support only a single ongoing async operation and enforce this with a semaphore,
+ // so singleton is fine and no need to worry about a race condition here.
+ if (_beginEndAwaitable == null)
+ _beginEndAwaitable = new BeginEndAwaitableAdapter();
+ }
+
+
+ /// <summary><code>MaxShadowBufferSize</code> is chosed such that shadow buffers are not allocated on the Large Object Heap.
+ /// Currently, an object is allocated on the LOH if it is larger than 85000 bytes. See LARGE_OBJECT_SIZE in ndp\clr\src\vm\gc.h
+ /// We will go with exactly 80 KBytes, although this is somewhat arbitrary.</summary>
+ private const Int32 MaxShadowBufferSize = 81920; // Make sure not to get to the Large Object Heap.
+ private void EnsureShadowBufferAllocated() {
+
+ Contract.Assert(_buffer != null);
+ Contract.Assert(_bufferSize > 0);
+
+ // Already have shadow buffer?
+ if (_buffer.Length != _bufferSize || _bufferSize >= MaxShadowBufferSize)
+ return;
+
+ Byte[] shadowBuffer = new Byte[Math.Min(_bufferSize + _bufferSize, MaxShadowBufferSize)];
+ Buffer.InternalBlockCopy(_buffer, 0, shadowBuffer, 0, _writePos);
+ _buffer = shadowBuffer;
+ }
+
+
+ private void EnsureBufferAllocated() {
+
+ Contract.Assert(_bufferSize > 0);
+
+ // BufferedStream is not intended for multi-threaded use, so no worries about the get/set race conditions on _buffer.
+ if (_buffer == null)
+ _buffer = new Byte[_bufferSize];
+ }
+
+
+ internal Stream UnderlyingStream {
+ [FriendAccessAllowed]
+ [Pure]
+ get { return _stream; }
+ }
+
+
+ internal Int32 BufferSize {
+ [FriendAccessAllowed]
+ [Pure]
+ get { return _bufferSize; }
+ }
+
+
+ public override bool CanRead {
+ [Pure]
+ get { return _stream != null && _stream.CanRead; }
+ }
+
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _stream != null && _stream.CanWrite; }
+ }
+
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _stream != null && _stream.CanSeek; }
+ }
+
+
+ public override Int64 Length {
+ get {
+ EnsureNotClosed();
+
+ if (_writePos > 0)
+ FlushWrite();
+
+ return _stream.Length;
+ }
+ }
+
+
+ public override Int64 Position {
+ get {
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ Contract.Assert(! (_writePos > 0 && _readPos != _readLen), "Read and Write buffers cannot both have data in them at the same time.");
+ return _stream.Position + (_readPos - _readLen + _writePos);
+ }
+ set {
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ if (_writePos > 0)
+ FlushWrite();
+
+ _readPos = 0;
+ _readLen = 0;
+ _stream.Seek(value, SeekOrigin.Begin);
+ }
+ }
+
+
+ protected override void Dispose(bool disposing) {
+
+ try {
+ if (disposing && _stream != null) {
+ try {
+ Flush();
+ } finally {
+ _stream.Close();
+ }
+ }
+ } finally {
+ _stream = null;
+ _buffer = null;
+ _lastSyncCompletedReadTask = null;
+
+ // Call base.Dispose(bool) to cleanup async IO resources
+ base.Dispose(disposing);
+ }
+ }
+
+
+ public override void Flush() {
+
+ EnsureNotClosed();
+
+ // Has WRITE data in the buffer:
+ if (_writePos > 0) {
+
+ FlushWrite();
+ Contract.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0);
+ return;
+ }
+
+ // Has READ data in the buffer:
+ if (_readPos < _readLen) {
+
+ // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
+ // We can either throw away the buffer resulting in data loss (!) or ignore the Flush.
+ // (We cannot throw becasue it would be a breaking change.) We opt into ignoring the Flush in that situation.
+ if (!_stream.CanSeek)
+ return;
+
+ FlushRead();
+
+ // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
+ // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
+ // Let us make a best effort attempt:
+ if (_stream.CanWrite || _stream is BufferedStream)
+ _stream.Flush();
+
+ Contract.Assert(_writePos == 0 && _readPos == 0 && _readLen == 0);
+ return;
+ }
+
+ // We had no data in the buffer, but we still need to tell the underlying stream to flush.
+ if (_stream.CanWrite || _stream is BufferedStream)
+ _stream.Flush();
+
+ _writePos = _readPos = _readLen = 0;
+ }
+
+ public override Task FlushAsync(CancellationToken cancellationToken) {
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<Int32>(cancellationToken);
+
+ EnsureNotClosed();
+
+ return FlushAsyncInternal(cancellationToken, this, _stream, _writePos, _readPos, _readLen);
+ }
+
+
+ private static async Task FlushAsyncInternal(CancellationToken cancellationToken,
+ BufferedStream _this, Stream stream, Int32 writePos, Int32 readPos, Int32 readLen) {
+
+ // We bring instance fields down as local parameters to this async method becasue BufferedStream is derived from MarshalByRefObject.
+ // Field access would be from the async state machine i.e., not via the this pointer and would require runtime checking to see
+ // if we are talking to a remote object, which is currently very slow
+
+ Contract.Assert(stream != null);
+
+ SemaphoreSlim sem = _this.EnsureAsyncActiveSemaphoreInitialized();
+ await sem.WaitAsync().ConfigureAwait(false);
+ try {
+
+ if (writePos > 0) {
+
+ await _this.FlushWriteAsync(cancellationToken).ConfigureAwait(false);
+ Contract.Assert(_this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0);
+ return;
+ }
+
+ if (readPos < readLen) {
+
+ // If the underlying stream is not seekable AND we have something in the read buffer, then FlushRead would throw.
+ // We can either throw away the buffer resulting in date loss (!) or ignore the Flush. (We cannot throw becasue it
+ // would be a breaking change.) We opt into ignoring the Flush in that situation.
+ if (!stream.CanSeek)
+ return;
+
+ _this.FlushRead(); // not async; it uses Seek, but there's no SeekAsync
+
+ // User streams may have opted to throw from Flush if CanWrite is false (although the abstract Stream does not do so).
+ // However, if we do not forward the Flush to the underlying stream, we may have problems when chaining several streams.
+ // Let us make a best effort attempt:
+ if (stream.CanRead || stream is BufferedStream)
+ await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
+
+ Contract.Assert(_this._writePos == 0 && _this._readPos == 0 && _this._readLen == 0);
+ return;
+ }
+
+ // We had no data in the buffer, but we still need to tell the underlying stream to flush.
+ if (stream.CanWrite || stream is BufferedStream)
+ await stream.FlushAsync(cancellationToken).ConfigureAwait(false);
+
+ // There was nothing in the buffer:
+ Contract.Assert(_this._writePos == 0 && _this._readPos == _this._readLen);
+
+ } finally {
+ sem.Release();
+ }
+ }
+
+
+ // Reading is done in blocks, but someone could read 1 byte from the buffer then write.
+ // At that point, the underlying stream's pointer is out of sync with this stream's position.
+ // All write functions should call this function to ensure that the buffered data is not lost.
+ private void FlushRead() {
+
+ Contract.Assert(_writePos == 0, "BufferedStream: Write buffer must be empty in FlushRead!");
+
+ if (_readPos - _readLen != 0)
+ _stream.Seek(_readPos - _readLen, SeekOrigin.Current);
+
+ _readPos = 0;
+ _readLen = 0;
+ }
+
+
+ private void ClearReadBufferBeforeWrite() {
+
+ // This is called by write methods to clear the read buffer.
+
+ Contract.Assert(_readPos <= _readLen, "_readPos <= _readLen [" + _readPos +" <= " + _readLen + "]");
+
+ // No READ data in the buffer:
+ if (_readPos == _readLen) {
+
+ _readPos = _readLen = 0;
+ return;
+ }
+
+ // Must have READ data.
+ Contract.Assert(_readPos < _readLen);
+
+ // If the underlying stream cannot seek, FlushRead would end up throwing NotSupported.
+ // However, since the user did not call a method that is intuitively expected to seek, a better message is in order.
+ // Ideally, we would throw an InvalidOperation here, but for backward compat we have to stick with NotSupported.
+ if (!_stream.CanSeek)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed"));
+
+ FlushRead();
+ }
+
+
+ private void FlushWrite() {
+
+ Contract.Assert(_readPos == 0 && _readLen == 0,
+ "BufferedStream: Read buffer must be empty in FlushWrite!");
+ Contract.Assert(_buffer != null && _bufferSize >= _writePos,
+ "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!");
+
+ _stream.Write(_buffer, 0, _writePos);
+ _writePos = 0;
+ _stream.Flush();
+ }
+
+
+ private async Task FlushWriteAsync(CancellationToken cancellationToken) {
+
+ Contract.Assert(_readPos == 0 && _readLen == 0,
+ "BufferedStream: Read buffer must be empty in FlushWrite!");
+ Contract.Assert(_buffer != null && _bufferSize >= _writePos,
+ "BufferedStream: Write buffer must be allocated and write position must be in the bounds of the buffer in FlushWrite!");
+
+ await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false);
+ _writePos = 0;
+ await _stream.FlushAsync(cancellationToken).ConfigureAwait(false);
+ }
+
+
+ private Int32 ReadFromBuffer(Byte[] array, Int32 offset, Int32 count) {
+
+ Int32 readBytes = _readLen - _readPos;
+ Contract.Assert(readBytes >= 0);
+
+ if (readBytes == 0)
+ return 0;
+
+ Contract.Assert(readBytes > 0);
+
+ if (readBytes > count)
+ readBytes = count;
+
+ Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, readBytes);
+ _readPos += readBytes;
+
+ return readBytes;
+ }
+
+
+ private Int32 ReadFromBuffer(Byte[] array, Int32 offset, Int32 count, out Exception error) {
+
+ try {
+
+ error = null;
+ return ReadFromBuffer(array, offset, count);
+
+ } catch (Exception ex) {
+ error = ex;
+ return 0;
+ }
+ }
+
+
+ public override int Read([In, Out] Byte[] array, Int32 offset, Int32 count) {
+
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count);
+
+ // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract.
+
+ // Reading again for more data may cause us to block if we're using a device with no clear end of file,
+ // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving two processes.
+ // BUT - this is a breaking change.
+ // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
+ // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
+ if (bytesFromBuffer == count)
+ return bytesFromBuffer;
+
+ Int32 alreadySatisfied = bytesFromBuffer;
+ if (bytesFromBuffer > 0) {
+ count -= bytesFromBuffer;
+ offset += bytesFromBuffer;
+ }
+
+ // So the READ buffer is empty.
+ Contract.Assert(_readLen == _readPos);
+ _readPos = _readLen = 0;
+
+ // If there was anything in the WRITE buffer, clear it.
+ if (_writePos > 0)
+ FlushWrite();
+
+ // If the requested read is larger than buffer size, avoid the buffer and still use a single read:
+ if (count >= _bufferSize) {
+
+ return _stream.Read(array, offset, count) + alreadySatisfied;
+ }
+
+ // Ok. We can fill the buffer:
+ EnsureBufferAllocated();
+ _readLen = _stream.Read(_buffer, 0, _bufferSize);
+
+ bytesFromBuffer = ReadFromBuffer(array, offset, count);
+
+ // We may have read less than the number of bytes the user asked for, but that is part of the Stream contract.
+ // Reading again for more data may cause us to block if we're using a device with no clear end of stream,
+ // such as a serial port or pipe. If we blocked here & this code was used with redirected pipes for a process's
+ // standard output, this can lead to deadlocks involving two processes. Additionally, translating one read on the
+ // BufferedStream to more than one read on the underlying Stream may defeat the whole purpose of buffering of the
+ // underlying reads are significantly more expensive.
+
+ return bytesFromBuffer + alreadySatisfied;
+ }
+
+
+ public override IAsyncResult BeginRead(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state) {
+
+ if (buffer == null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // Previous version incorrectly threw NotSupported instead of ObjectDisposed. We keep that behaviour for back-compat.
+ // EnsureNotClosed();
+ if (_stream == null) __Error.ReadNotSupported();
+ EnsureCanRead();
+
+ Int32 bytesFromBuffer = 0;
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) {
+
+ bool completeSynchronously = true;
+ try {
+
+ Exception error;
+ bytesFromBuffer = ReadFromBuffer(buffer, offset, count, out error);
+
+ // If we satistied enough data from the buffer, we can complete synchronously.
+ // Reading again for more data may cause us to block if we're using a device with no clear end of file,
+ // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving two processes.
+ // BUT - this is a breaking change.
+ // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
+ // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
+ completeSynchronously = (bytesFromBuffer == count || error != null);
+
+ if (completeSynchronously) {
+
+ SynchronousAsyncResult asyncResult = (error == null)
+ ? new SynchronousAsyncResult(bytesFromBuffer, state)
+ : new SynchronousAsyncResult(error, state, isWrite: false);
+ if (callback != null)
+ callback(asyncResult);
+
+ return asyncResult;
+ }
+ } finally {
+ if (completeSynchronously) // if this is FALSE, we will be entering ReadFromUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return BeginReadFromUnderlyingStream(buffer, offset + bytesFromBuffer, count - bytesFromBuffer, callback, state,
+ bytesFromBuffer, semaphoreLockTask);
+ }
+
+
+ private IAsyncResult BeginReadFromUnderlyingStream(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state,
+ Int32 bytesAlreadySatisfied, Task semaphoreLockTask) {
+
+ Task<Int32> readOp = ReadFromUnderlyingStreamAsync(buffer, offset, count, CancellationToken.None,
+ bytesAlreadySatisfied, semaphoreLockTask, useApmPattern: true);
+ return TaskToApm.Begin(readOp, callback, state);
+ }
+
+
+ public override Int32 EndRead(IAsyncResult asyncResult) {
+
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.Ensures(Contract.Result<Int32>() >= 0);
+ Contract.EndContractBlock();
+
+ var sAR = asyncResult as SynchronousAsyncResult;
+ if (sAR != null)
+ return SynchronousAsyncResult.EndRead(asyncResult);
+ return TaskToApm.End<Int32>(asyncResult);
+ }
+
+
+ private Task<Int32> LastSyncCompletedReadTask(Int32 val) {
+
+ Task<Int32> t = _lastSyncCompletedReadTask;
+ Contract.Assert(t == null || t.Status == TaskStatus.RanToCompletion);
+
+ if (t != null && t.Result == val)
+ return t;
+
+ t = Task.FromResult<Int32>(val);
+ _lastSyncCompletedReadTask = t;
+ return t;
+ }
+
+
+ public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+
+ if (buffer == null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // Fast path check for cancellation already requested
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<Int32>(cancellationToken);
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ Int32 bytesFromBuffer = 0;
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) {
+
+ bool completeSynchronously = true;
+ try {
+ Exception error;
+ bytesFromBuffer = ReadFromBuffer(buffer, offset, count, out error);
+
+ // If we satistied enough data from the buffer, we can complete synchronously.
+ // Reading again for more data may cause us to block if we're using a device with no clear end of file,
+ // such as a serial port or pipe. If we blocked here and this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving two processes.
+ // BUT - this is a breaking change.
+ // So: If we could not read all bytes the user asked for from the buffer, we will try once from the underlying
+ // stream thus ensuring the same blocking behaviour as if the underlying stream was not wrapped in this BufferedStream.
+ completeSynchronously = (bytesFromBuffer == count || error != null);
+
+ if (completeSynchronously) {
+
+ return (error == null)
+ ? LastSyncCompletedReadTask(bytesFromBuffer)
+ : Task.FromException<Int32>(error);
+ }
+ } finally {
+ if (completeSynchronously) // if this is FALSE, we will be entering ReadFromUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return ReadFromUnderlyingStreamAsync(buffer, offset + bytesFromBuffer, count - bytesFromBuffer, cancellationToken,
+ bytesFromBuffer, semaphoreLockTask, useApmPattern: false);
+ }
+
+
+ /// <summary>BufferedStream should be as thin a wrapper as possible. We want that ReadAsync delegates to
+ /// ReadAsync of the underlying _stream and that BeginRead delegates to BeginRead of the underlying stream,
+ /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream
+ /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as
+ /// much code between the APM and the Async pattern implementations as possible. This method is called by both with
+ /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult.</summary>
+ /// <returns>-2 if _bufferSize was set to 0 while waiting on the semaphore; otherwise num of bytes read.</returns>
+ private async Task<Int32> ReadFromUnderlyingStreamAsync(Byte[] array, Int32 offset, Int32 count,
+ CancellationToken cancellationToken,
+ Int32 bytesAlreadySatisfied,
+ Task semaphoreLockTask, bool useApmPattern) {
+
+ // Same conditions validated with exceptions in ReadAsync:
+ // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.)
+ Contract.Assert(array != null);
+ Contract.Assert(offset >= 0);
+ Contract.Assert(count >= 0);
+ Contract.Assert(array.Length - offset >= count);
+ Contract.Assert(_stream != null);
+ Contract.Assert(_stream.CanRead);
+ Contract.Assert(_bufferSize > 0);
+ Contract.Assert(semaphoreLockTask != null);
+
+ // Employ async waiting based on the same synchronization used in BeginRead of the abstract Stream.
+ await semaphoreLockTask.ConfigureAwait(false);
+ try {
+
+ // The buffer might have been changed by another async task while we were waiting on the semaphore.
+ // Check it now again.
+ Int32 bytesFromBuffer = ReadFromBuffer(array, offset, count);
+ if (bytesFromBuffer == count)
+ return bytesAlreadySatisfied + bytesFromBuffer;
+
+ if (bytesFromBuffer > 0) {
+ count -= bytesFromBuffer;
+ offset += bytesFromBuffer;
+ bytesAlreadySatisfied += bytesFromBuffer;
+ }
+
+ Contract.Assert(_readLen == _readPos);
+ _readPos = _readLen = 0;
+
+ // If there was anything in the WRITE buffer, clear it.
+ if (_writePos > 0)
+ await FlushWriteAsync(cancellationToken).ConfigureAwait(false); // no Begin-End read version for Flush. Use Async.
+
+ // If the requested read is larger than buffer size, avoid the buffer and still use a single read:
+ if (count >= _bufferSize) {
+
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginRead(array, offset, count, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ return bytesAlreadySatisfied + _stream.EndRead(await _beginEndAwaitable);
+ } else {
+ return bytesAlreadySatisfied + await _stream.ReadAsync(array, offset, count, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ // Ok. We can fill the buffer:
+ EnsureBufferAllocated();
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginRead(_buffer, 0, _bufferSize, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ _readLen = _stream.EndRead(await _beginEndAwaitable);
+ } else {
+ _readLen = await _stream.ReadAsync(_buffer, 0, _bufferSize, cancellationToken).ConfigureAwait(false);
+ }
+
+ bytesFromBuffer = ReadFromBuffer(array, offset, count);
+ return bytesAlreadySatisfied + bytesFromBuffer;
+
+ } finally {
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ sem.Release();
+ }
+ }
+
+
+ public override Int32 ReadByte() {
+
+ EnsureNotClosed();
+ EnsureCanRead();
+
+ if (_readPos == _readLen) {
+
+ if (_writePos > 0)
+ FlushWrite();
+
+ EnsureBufferAllocated();
+ _readLen = _stream.Read(_buffer, 0, _bufferSize);
+ _readPos = 0;
+ }
+
+ if (_readPos == _readLen)
+ return -1;
+
+ Int32 b = _buffer[_readPos++];
+ return b;
+ }
+
+
+ private void WriteToBuffer(Byte[] array, ref Int32 offset, ref Int32 count) {
+
+ Int32 bytesToWrite = Math.Min(_bufferSize - _writePos, count);
+
+ if (bytesToWrite <= 0)
+ return;
+
+ EnsureBufferAllocated();
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, bytesToWrite);
+
+ _writePos += bytesToWrite;
+ count -= bytesToWrite;
+ offset += bytesToWrite;
+ }
+
+
+ private void WriteToBuffer(Byte[] array, ref Int32 offset, ref Int32 count, out Exception error) {
+
+ try {
+
+ error = null;
+ WriteToBuffer(array, ref offset, ref count);
+
+ } catch (Exception ex) {
+ error = ex;
+ }
+ }
+
+
+ public override void Write(Byte[] array, Int32 offset, Int32 count) {
+
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanWrite();
+
+ if (_writePos == 0)
+ ClearReadBufferBeforeWrite();
+
+ #region Write algorithm comment
+ // We need to use the buffer, while avoiding unnecessary buffer usage / memory copies.
+ // We ASSUME that memory copies are much cheaper than writes to the underlying stream, so if an extra copy is
+ // guaranteed to reduce the number of writes, we prefer it.
+ // We pick a simple strategy that makes degenerate cases rare if our assumptions are right.
+ //
+ // For every write, we use a simple heuristic (below) to decide whether to use the buffer.
+ // The heuristic has the desirable property (*) that if the specified user data can fit into the currently available
+ // buffer space without filling it up completely, the heuristic will always tell us to use the buffer. It will also
+ // tell us to use the buffer in cases where the current write would fill the buffer, but the remaining data is small
+ // enough such that subsequent operations can use the buffer again.
+ //
+ // Algorithm:
+ // Determine whether or not to buffer according to the heuristic (below).
+ // If we decided to use the buffer:
+ // Copy as much user data as we can into the buffer.
+ // If we consumed all data: We are finished.
+ // Otherwise, write the buffer out.
+ // Copy the rest of user data into the now cleared buffer (no need to write out the buffer again as the heuristic
+ // will prevent it from being filled twice).
+ // If we decided not to use the buffer:
+ // Can the data already in the buffer and current user data be combines to a single write
+ // by allocating a "shadow" buffer of up to twice the size of _bufferSize (up to a limit to avoid LOH)?
+ // Yes, it can:
+ // Allocate a larger "shadow" buffer and ensure the buffered data is moved there.
+ // Copy user data to the shadow buffer.
+ // Write shadow buffer to the underlying stream in a single operation.
+ // No, it cannot (amount of data is still too large):
+ // Write out any data possibly in the buffer.
+ // Write out user data directly.
+ //
+ // Heuristic:
+ // If the subsequent write operation that follows the current write operation will result in a write to the
+ // underlying stream in case that we use the buffer in the current write, while it would not have if we avoided
+ // using the buffer in the current write (by writing current user data to the underlying stream directly), then we
+ // prefer to avoid using the buffer since the corresponding memory copy is wasted (it will not reduce the number
+ // of writes to the underlying stream, which is what we are optimising for).
+ // ASSUME that the next write will be for the same amount of bytes as the current write (most common case) and
+ // determine if it will cause a write to the underlying stream. If the next write is actually larger, our heuristic
+ // still yields the right behaviour, if the next write is actually smaller, we may making an unnecessary write to
+ // the underlying stream. However, this can only occur if the current write is larger than half the buffer size and
+ // we will recover after one iteration.
+ // We have:
+ // useBuffer = (_writePos + count + count < _bufferSize + _bufferSize)
+ //
+ // Example with _bufferSize = 20, _writePos = 6, count = 10:
+ //
+ // +---------------------------------------+---------------------------------------+
+ // | current buffer | next iteration's "future" buffer |
+ // +---------------------------------------+---------------------------------------+
+ // |0| | | | | | | | | |1| | | | | | | | | |2| | | | | | | | | |3| | | | | | | | | |
+ // |0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|0|1|2|3|4|5|6|7|8|9|
+ // +-----------+-------------------+-------------------+---------------------------+
+ // | _writePos | current count | assumed next count|avail buff after next write|
+ // +-----------+-------------------+-------------------+---------------------------+
+ //
+ // A nice property (*) of this heuristic is that it will always succeed if the user data completely fits into the
+ // available buffer, i.e. if count < (_bufferSize - _writePos).
+ #endregion Write algorithm comment
+
+ Contract.Assert(_writePos < _bufferSize);
+
+ Int32 totalUserBytes;
+ bool useBuffer;
+ checked { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early:
+ totalUserBytes = _writePos + count;
+ useBuffer = (totalUserBytes + count < (_bufferSize + _bufferSize));
+ }
+
+ if (useBuffer) {
+
+ WriteToBuffer(array, ref offset, ref count);
+
+ if (_writePos < _bufferSize) {
+
+ Contract.Assert(count == 0);
+ return;
+ }
+
+ Contract.Assert(count >= 0);
+ Contract.Assert(_writePos == _bufferSize);
+ Contract.Assert(_buffer != null);
+
+ _stream.Write(_buffer, 0, _writePos);
+ _writePos = 0;
+
+ WriteToBuffer(array, ref offset, ref count);
+
+ Contract.Assert(count == 0);
+ Contract.Assert(_writePos < _bufferSize);
+
+ } else { // if (!useBuffer)
+
+ // Write out the buffer if necessary.
+ if (_writePos > 0) {
+
+ Contract.Assert(_buffer != null);
+ Contract.Assert(totalUserBytes >= _bufferSize);
+
+ // Try avoiding extra write to underlying stream by combining previously buffered data with current user data:
+ if (totalUserBytes <= (_bufferSize + _bufferSize) && totalUserBytes <= MaxShadowBufferSize) {
+
+ EnsureShadowBufferAllocated();
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count);
+ _stream.Write(_buffer, 0, totalUserBytes);
+ _writePos = 0;
+ return;
+ }
+
+ _stream.Write(_buffer, 0, _writePos);
+ _writePos = 0;
+ }
+
+ // Write out user data.
+ _stream.Write(array, offset, count);
+ }
+ }
+
+
+
+
+ public override IAsyncResult BeginWrite(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state) {
+
+ if (buffer == null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // Previous version incorrectly threw NotSupported instead of ObjectDisposed. We keep that behaviour for back-compat.
+ // EnsureNotClosed();
+ if (_stream == null) __Error.ReadNotSupported();
+ EnsureCanWrite();
+
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) {
+
+ bool completeSynchronously = true;
+ try {
+ if (_writePos == 0)
+ ClearReadBufferBeforeWrite();
+
+ // If the write completely fits into the buffer, we can complete synchronously.
+ Contract.Assert(_writePos < _bufferSize);
+ completeSynchronously = (count < _bufferSize - _writePos);
+
+ if (completeSynchronously) {
+
+ Exception error;
+ WriteToBuffer(buffer, ref offset, ref count, out error);
+ Contract.Assert(count == 0);
+
+ SynchronousAsyncResult asyncResult = (error == null)
+ ? new SynchronousAsyncResult(state)
+ : new SynchronousAsyncResult(error, state, isWrite: true);
+ if (callback != null)
+ callback(asyncResult);
+
+ return asyncResult;
+ }
+ } finally {
+ if (completeSynchronously) // if this is FALSE, we will be entering WriteToUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return BeginWriteToUnderlyingStream(buffer, offset, count, callback, state, semaphoreLockTask);
+ }
+
+
+ private IAsyncResult BeginWriteToUnderlyingStream(Byte[] buffer, Int32 offset, Int32 count, AsyncCallback callback, Object state,
+ Task semaphoreLockTask) {
+
+ Task writeOp = WriteToUnderlyingStreamAsync(buffer, offset, count, CancellationToken.None, semaphoreLockTask, useApmPattern: true);
+ return TaskToApm.Begin(writeOp, callback, state);
+ }
+
+
+ public override void EndWrite(IAsyncResult asyncResult) {
+
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ var sAR = asyncResult as SynchronousAsyncResult;
+ if (sAR != null) {
+ SynchronousAsyncResult.EndWrite(asyncResult);
+ return;
+ }
+
+ TaskToApm.End(asyncResult);
+ }
+
+
+ public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+
+ if (buffer == null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // Fast path check for cancellation already requested
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<Int32>(cancellationToken);
+
+ EnsureNotClosed();
+ EnsureCanWrite();
+
+ // Try to satisfy the request from the buffer synchronously. But still need a sem-lock in case that another
+ // Async IO Task accesses the buffer concurrently. If we fail to acquire the lock without waiting, make this
+ // an Async operation.
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreLockTask = sem.WaitAsync();
+ if (semaphoreLockTask.Status == TaskStatus.RanToCompletion) {
+
+ bool completeSynchronously = true;
+ try {
+
+ if (_writePos == 0)
+ ClearReadBufferBeforeWrite();
+
+ Contract.Assert(_writePos < _bufferSize);
+
+ // If the write completely fits into the buffer, we can complete synchronously:
+ completeSynchronously = (count < _bufferSize - _writePos);
+
+ if (completeSynchronously) {
+
+ Exception error;
+ WriteToBuffer(buffer, ref offset, ref count, out error);
+ Contract.Assert(count == 0);
+
+ return (error == null)
+ ? Task.CompletedTask
+ : Task.FromException(error);
+ }
+ } finally {
+ if (completeSynchronously) // if this is FALSE, we will be entering WriteToUnderlyingStreamAsync and releasing there.
+ sem.Release();
+ }
+ }
+
+ // Delegate to the async implementation.
+ return WriteToUnderlyingStreamAsync(buffer, offset, count, cancellationToken, semaphoreLockTask, useApmPattern: false);
+ }
+
+
+ /// <summary>BufferedStream should be as thin a wrapper as possible. We want that WriteAsync delegates to
+ /// WriteAsync of the underlying _stream and that BeginWrite delegates to BeginWrite of the underlying stream,
+ /// rather than calling the base Stream which implements the one in terms of the other. This allows BufferedStream
+ /// to affect the semantics of the stream it wraps as little as possible. At the same time, we want to share as
+ /// much code between the APM and the Async pattern implementations as possible. This method is called by both with
+ /// a corresponding useApmPattern value. Recall that Task implements IAsyncResult.</summary>
+ private async Task WriteToUnderlyingStreamAsync(Byte[] array, Int32 offset, Int32 count,
+ CancellationToken cancellationToken,
+ Task semaphoreLockTask, bool useApmPattern) {
+
+ // (These should be Contract.Requires(..) but that method had some issues in async methods; using Assert(..) for now.)
+ Contract.Assert(array != null);
+ Contract.Assert(offset >= 0);
+ Contract.Assert(count >= 0);
+ Contract.Assert(array.Length - offset >= count);
+ Contract.Assert(_stream != null);
+ Contract.Assert(_stream.CanWrite);
+ Contract.Assert(_bufferSize > 0);
+ Contract.Assert(semaphoreLockTask != null);
+
+ // See the LARGE COMMENT in Write(..) for the explanation of the write buffer algorithm.
+
+ await semaphoreLockTask.ConfigureAwait(false);
+ try {
+
+ // The buffer might have been changed by another async task while we were waiting on the semaphore.
+ // However, note that if we recalculate the sync completion condition to TRUE, then useBuffer will also be TRUE.
+
+ if (_writePos == 0)
+ ClearReadBufferBeforeWrite();
+
+ Int32 totalUserBytes;
+ bool useBuffer;
+ checked { // We do not expect buffer sizes big enough for an overflow, but if it happens, lets fail early:
+ totalUserBytes = _writePos + count;
+ useBuffer = (totalUserBytes + count < (_bufferSize + _bufferSize));
+ }
+
+ if (useBuffer) {
+
+ WriteToBuffer(array, ref offset, ref count);
+
+ if (_writePos < _bufferSize) {
+
+ Contract.Assert(count == 0);
+ return;
+ }
+
+ Contract.Assert(count >= 0);
+ Contract.Assert(_writePos == _bufferSize);
+ Contract.Assert(_buffer != null);
+
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginWrite(_buffer, 0, _writePos, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ _stream.EndWrite(await _beginEndAwaitable);
+ } else {
+ await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false);
+ }
+ _writePos = 0;
+
+ WriteToBuffer(array, ref offset, ref count);
+
+ Contract.Assert(count == 0);
+ Contract.Assert(_writePos < _bufferSize);
+
+ } else { // if (!useBuffer)
+
+ // Write out the buffer if necessary.
+ if (_writePos > 0) {
+
+ Contract.Assert(_buffer != null);
+ Contract.Assert(totalUserBytes >= _bufferSize);
+
+ // Try avoiding extra write to underlying stream by combining previously buffered data with current user data:
+ if (totalUserBytes <= (_bufferSize + _bufferSize) && totalUserBytes <= MaxShadowBufferSize) {
+
+ EnsureShadowBufferAllocated();
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count);
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginWrite(_buffer, 0, totalUserBytes, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ _stream.EndWrite(await _beginEndAwaitable);
+ } else {
+ await _stream.WriteAsync(_buffer, 0, totalUserBytes, cancellationToken).ConfigureAwait(false);
+ }
+ _writePos = 0;
+ return;
+ }
+
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginWrite(_buffer, 0, _writePos, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ _stream.EndWrite(await _beginEndAwaitable);
+ } else {
+ await _stream.WriteAsync(_buffer, 0, _writePos, cancellationToken).ConfigureAwait(false);
+ }
+ _writePos = 0;
+ }
+
+ // Write out user data.
+ if (useApmPattern) {
+ EnsureBeginEndAwaitableAllocated();
+ _stream.BeginWrite(array, offset, count, BeginEndAwaitableAdapter.Callback, _beginEndAwaitable);
+ _stream.EndWrite(await _beginEndAwaitable);
+ } else {
+ await _stream.WriteAsync(array, offset, count, cancellationToken).ConfigureAwait(false);
+ }
+ }
+ } finally {
+ SemaphoreSlim sem = base.EnsureAsyncActiveSemaphoreInitialized();
+ sem.Release();
+ }
+ }
+
+
+ public override void WriteByte(Byte value) {
+
+ EnsureNotClosed();
+
+ if (_writePos == 0) {
+
+ EnsureCanWrite();
+ ClearReadBufferBeforeWrite();
+ EnsureBufferAllocated();
+ }
+
+ // We should not be flushing here, but only writing to the underlying stream, but previous version flushed, so we keep this.
+ if (_writePos >= _bufferSize - 1)
+ FlushWrite();
+
+ _buffer[_writePos++] = value;
+
+ Contract.Assert(_writePos < _bufferSize);
+ }
+
+
+ public override Int64 Seek(Int64 offset, SeekOrigin origin) {
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+
+ // If we have bytes in the WRITE buffer, flush them out, seek and be done.
+ if (_writePos > 0) {
+
+ // We should be only writing the buffer and not flushing,
+ // but the previous version did flush and we stick to it for back-compat reasons.
+ FlushWrite();
+ return _stream.Seek(offset, origin);
+ }
+
+ // The buffer is either empty or we have a buffered READ.
+
+ if (_readLen - _readPos > 0 && origin == SeekOrigin.Current) {
+
+ // If we have bytes in the READ buffer, adjust the seek offset to account for the resulting difference
+ // between this stream's position and the underlying stream's position.
+ offset -= (_readLen - _readPos);
+ }
+
+ Int64 oldPos = Position;
+ Contract.Assert(oldPos == _stream.Position + (_readPos - _readLen));
+
+ Int64 newPos = _stream.Seek(offset, origin);
+
+ // If the seek destination is still within the data currently in the buffer, we want to keep the buffer data and continue using it.
+ // Otherwise we will throw away the buffer. This can only happen on READ, as we flushed WRITE data above.
+
+ // The offset of the new/updated seek pointer within _buffer:
+ _readPos = (Int32) (newPos - (oldPos - _readPos));
+
+ // If the offset of the updated seek pointer in the buffer is still legal, then we can keep using the buffer:
+ if (0 <= _readPos && _readPos < _readLen) {
+
+ // Adjust the seek pointer of the underlying stream to reflect the amount of useful bytes in the read buffer:
+ _stream.Seek(_readLen - _readPos, SeekOrigin.Current);
+
+ } else { // The offset of the updated seek pointer is not a legal offset. Loose the buffer.
+
+ _readPos = _readLen = 0;
+ }
+
+ Contract.Assert(newPos == Position, "newPos (=" + newPos + ") == Position (=" + Position + ")");
+ return newPos;
+ }
+
+
+ public override void SetLength(Int64 value) {
+
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegFileSize"));
+ Contract.EndContractBlock();
+
+ EnsureNotClosed();
+ EnsureCanSeek();
+ EnsureCanWrite();
+
+ Flush();
+ _stream.SetLength(value);
+ }
+
+} // class BufferedStream
+} // namespace
diff --git a/src/mscorlib/src/System/IO/Directory.cs b/src/mscorlib/src/System/IO/Directory.cs
new file mode 100644
index 0000000000..be74538d2d
--- /dev/null
+++ b/src/mscorlib/src/System/IO/Directory.cs
@@ -0,0 +1,1389 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exposes routines for enumerating through a
+** directory.
+**
+** April 11,2000
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Security;
+using System.Security.Permissions;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+using System.Threading;
+
+#if FEATURE_MACL
+using System.Security.AccessControl;
+#endif
+
+namespace System.IO {
+ [ComVisible(true)]
+ public static class Directory {
+ public static DirectoryInfo GetParent(String path)
+ {
+ if (path==null)
+ throw new ArgumentNullException("path");
+
+ if (path.Length==0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+
+ String s = Path.GetDirectoryName(fullPath);
+ if (s==null)
+ return null;
+ return new DirectoryInfo(s);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static DirectoryInfo CreateDirectory(String path) {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"));
+ Contract.EndContractBlock();
+
+ return InternalCreateDirectoryHelper(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static DirectoryInfo UnsafeCreateDirectory(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"));
+ Contract.EndContractBlock();
+
+ return InternalCreateDirectoryHelper(path, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static DirectoryInfo InternalCreateDirectoryHelper(String path, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(path.Length != 0);
+
+ String fullPath = Path.GetFullPathInternal(path);
+
+ // You need read access to the directory to be returned back and write access to all the directories
+ // that you need to create. If we fail any security checks we will not create any directories at all.
+ // 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);
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, demandDir);
+ state.EnsureState(); // do the check on the AppDomainManager to make sure this is allowed
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false);
+#endif
+
+ InternalCreateDirectory(fullPath, path, null, checkHost);
+
+ return new DirectoryInfo(fullPath, false);
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static DirectoryInfo CreateDirectory(String path, DirectorySecurity directorySecurity) {
+ if (path==null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"));
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+
+ // You need read access to the directory to be returned back and write access to all the directories
+ // that you need to create. If we fail any security checks we will not create any directories at all.
+ // 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);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandDir, false, false );
+
+ InternalCreateDirectory(fullPath, path, directorySecurity);
+
+ return new DirectoryInfo(fullPath, false);
+ }
+#endif // FEATURE_MACL
+
+ // Input to this method should already be fullpath. This method will ensure that we append
+ // the trailing slash only when appropriate and when thisDirOnly is specified append a "."
+ // at the end of the path to indicate that the demand is only for the fullpath and not
+ // everything underneath it.
+ internal static String GetDemandDir(string fullPath, bool thisDirOnly)
+ {
+ String demandPath;
+
+ if (thisDirOnly) {
+ if (fullPath.EndsWith( Path.DirectorySeparatorChar )
+ || fullPath.EndsWith( Path.AltDirectorySeparatorChar ) )
+ demandPath = fullPath + ".";
+ else
+ demandPath = fullPath + Path.DirectorySeparatorCharAsString + ".";
+ }
+ else {
+ if (!(fullPath.EndsWith( Path.DirectorySeparatorChar )
+ || fullPath.EndsWith( Path.AltDirectorySeparatorChar )) )
+ demandPath = fullPath + Path.DirectorySeparatorCharAsString;
+ else
+ demandPath = fullPath;
+ }
+ return demandPath;
+ }
+
+ internal static void InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj)
+ {
+ InternalCreateDirectory(fullPath, path, dirSecurityObj, false);
+ }
+
+
+ [System.Security.SecuritySafeCritical]
+ internal unsafe static void InternalCreateDirectory(String fullPath, String path, Object dirSecurityObj, bool checkHost)
+ {
+#if FEATURE_MACL
+ DirectorySecurity dirSecurity = (DirectorySecurity)dirSecurityObj;
+#endif // FEATURE_MACL
+
+ int length = fullPath.Length;
+
+ // We need to trim the trailing slash or the code will try to create 2 directories of the same name.
+ if (length >= 2 && Path.IsDirectorySeparator(fullPath[length - 1]))
+ length--;
+
+ int lengthRoot = Path.GetRootLength(fullPath);
+
+ // For UNC paths that are only // or ///
+ if (length == 2 && Path.IsDirectorySeparator(fullPath[1]))
+ throw new IOException(Environment.GetResourceString("IO.IO_CannotCreateDirectory", path));
+
+ // We can save a bunch of work if the directory we want to create already exists. This also
+ // saves us in the case where sub paths are inaccessible (due to ERROR_ACCESS_DENIED) but the
+ // final path is accessable and the directory already exists. For example, consider trying
+ // to create c:\Foo\Bar\Baz, where everything already exists but ACLS prevent access to c:\Foo
+ // and c:\Foo\Bar. In that case, this code will think it needs to create c:\Foo, and c:\Foo\Bar
+ // and fail to due so, causing an exception to be thrown. This is not what we want.
+ if (InternalExists(fullPath)) {
+ return;
+ }
+
+ List<string> stackDir = new List<string>();
+
+ // Attempt to figure out which directories don't exist, and only
+ // create the ones we need. Note that InternalExists may fail due
+ // to Win32 ACL's preventing us from seeing a directory, and this
+ // isn't threadsafe.
+
+ bool somepathexists = false;
+
+ if (length > lengthRoot) { // Special case root (fullpath = X:\\)
+ int i = length-1;
+ while (i >= lengthRoot && !somepathexists) {
+ String dir = fullPath.Substring(0, i+1);
+
+ if (!InternalExists(dir)) // Create only the ones missing
+ stackDir.Add(dir);
+ else
+ somepathexists = true;
+
+ while (i > lengthRoot && fullPath[i] != Path.DirectorySeparatorChar && fullPath[i] != Path.AltDirectorySeparatorChar) i--;
+ i--;
+ }
+ }
+
+ int count = stackDir.Count;
+
+ 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);
+ 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_MACL
+ AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change;
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, control, securityList, false, false);
+#else
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ foreach (String demandPath in securityList)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, demandPath);
+ state.EnsureState();
+ }
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, securityList, false, false);
+#endif
+#endif //FEATURE_MACL
+ }
+
+ // If we were passed a DirectorySecurity, convert it to a security
+ // descriptor and set it in he call to CreateDirectory.
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if FEATURE_MACL
+ if (dirSecurity != null) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ // For ACL's, get the security descriptor from the FileSecurity.
+ byte[] sd = dirSecurity.GetSecurityDescriptorBinaryForm();
+ byte * bytesOnStack = stackalloc byte[sd.Length];
+ Buffer.Memcpy(bytesOnStack, 0, sd, 0, sd.Length);
+ secAttrs.pSecurityDescriptor = bytesOnStack;
+ }
+#endif
+
+ bool r = true;
+ int firstError = 0;
+ String errorString = path;
+ // If all the security checks succeeded create all the directories
+ while (stackDir.Count > 0) {
+ String name = stackDir[stackDir.Count - 1];
+ stackDir.RemoveAt(stackDir.Count - 1);
+ if (PathInternal.IsDirectoryTooLong(name))
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ r = Win32Native.CreateDirectory(name, secAttrs);
+ if (!r && (firstError == 0)) {
+ int currentError = Marshal.GetLastWin32Error();
+ // While we tried to avoid creating directories that don't
+ // exist above, there are at least two cases that will
+ // cause us to see ERROR_ALREADY_EXISTS here. InternalExists
+ // can fail because we didn't have permission to the
+ // directory. Secondly, another thread or process could
+ // create the directory between the time we check and the
+ // time we try using the directory. Thirdly, it could
+ // fail because the target does exist, but is a file.
+ if (currentError != Win32Native.ERROR_ALREADY_EXISTS)
+ firstError = currentError;
+ else {
+ // If there's a file in this directory's place, or if we have ERROR_ACCESS_DENIED when checking if the directory already exists throw.
+ if (File.InternalExists(name) || (!InternalExists(name, out currentError) && currentError == Win32Native.ERROR_ACCESS_DENIED)) {
+ firstError = currentError;
+ // Give the user a nice error message, but don't leak path information.
+ try {
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, GetDemandDir(name, true));
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true));
+#endif // FEATURE_CORECLR
+ errorString = name;
+ }
+ catch(SecurityException) {}
+ }
+ }
+ }
+ }
+
+ // We need this check to mask OS differences
+ // Handle CreateDirectory("X:\\foo") when X: doesn't exist. Similarly for n/w paths.
+ if ((count == 0) && !somepathexists) {
+ String root = InternalGetDirectoryRoot(fullPath);
+ if (!InternalExists(root)) {
+ // Extract the root from the passed in path again for security.
+ __Error.WinIOError(Win32Native.ERROR_PATH_NOT_FOUND, InternalGetDirectoryRoot(path));
+ }
+ return;
+ }
+
+ // Only throw an exception if creating the exact directory we
+ // wanted failed to work correctly.
+ if (!r && (firstError != 0)) {
+ __Error.WinIOError(firstError, errorString);
+ }
+ }
+
+
+ // Tests if the given path refers to an existing DirectoryInfo on disk.
+ //
+ // Your application must have Read permission to the directory's
+ // contents.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool Exists(String path)
+ {
+ return InternalExistsHelper(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool UnsafeExists(String path)
+ {
+ return InternalExistsHelper(path, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool InternalExistsHelper(String path, bool checkHost) {
+ try
+ {
+ if (path == null)
+ return false;
+ if (path.Length == 0)
+ return false;
+
+ // Get fully qualified file name ending in \* for security check
+
+ String fullPath = Path.GetFullPathInternal(path);
+ String demandPath = GetDemandDir(fullPath, true);
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, demandPath);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, demandPath, false, false);
+#endif
+
+
+ return InternalExists(fullPath);
+ }
+ catch (ArgumentException) { }
+ catch (NotSupportedException) { } // Security can throw this on ":"
+ catch (SecurityException) { }
+ catch (IOException) { }
+ catch (UnauthorizedAccessException)
+ {
+ Contract.Assert(false, "Ignore this assert and send a repro to Microsoft. This assert was tracking purposes only.");
+ }
+ return false;
+ }
+
+ // Determine whether path describes an existing directory
+ // on disk, avoiding security checks.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool InternalExists(String path) {
+ int lastError = Win32Native.ERROR_SUCCESS;
+ return InternalExists(path, out lastError);
+ }
+
+ // Determine whether path describes an existing directory
+ // on disk, avoiding security checks.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool InternalExists(String path, out int lastError) {
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ lastError = File.FillAttributeInfo(path, ref data, false, true);
+
+ return (lastError == 0) && (data.fileAttributes != -1)
+ && ((data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0);
+ }
+
+ public static void SetCreationTime(String path,DateTime creationTime)
+ {
+ SetCreationTimeUtc(path, creationTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetCreationTimeUtc(String path,DateTime creationTimeUtc)
+ {
+ using (SafeFileHandle handle = Directory.OpenHandle(path)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(creationTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, &fileTime, null, null);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ public static DateTime GetCreationTime(String path)
+ {
+ return File.GetCreationTime(path);
+ }
+
+ public static DateTime GetCreationTimeUtc(String path)
+ {
+ return File.GetCreationTimeUtc(path);
+ }
+
+ public static void SetLastWriteTime(String path,DateTime lastWriteTime)
+ {
+ SetLastWriteTimeUtc(path, lastWriteTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetLastWriteTimeUtc(String path,DateTime lastWriteTimeUtc)
+ {
+ using (SafeFileHandle handle = Directory.OpenHandle(path)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastWriteTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, null, null, &fileTime);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ public static DateTime GetLastWriteTime(String path)
+ {
+ return File.GetLastWriteTime(path);
+ }
+
+ public static DateTime GetLastWriteTimeUtc(String path)
+ {
+ return File.GetLastWriteTimeUtc(path);
+ }
+
+ public static void SetLastAccessTime(String path,DateTime lastAccessTime)
+ {
+ SetLastAccessTimeUtc(path, lastAccessTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetLastAccessTimeUtc(String path,DateTime lastAccessTimeUtc)
+ {
+ using (SafeFileHandle handle = Directory.OpenHandle(path)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastAccessTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, null, &fileTime, null);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ public static DateTime GetLastAccessTime(String path)
+ {
+ return File.GetLastAccessTime(path);
+ }
+
+ public static DateTime GetLastAccessTimeUtc(String path)
+ {
+ return File.GetLastAccessTimeUtc(path);
+ }
+
+#if FEATURE_MACL
+ public static DirectorySecurity GetAccessControl(String path)
+ {
+ return new DirectorySecurity(path, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ public static DirectorySecurity GetAccessControl(String path, AccessControlSections includeSections)
+ {
+ return new DirectorySecurity(path, includeSections);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetAccessControl(String path, DirectorySecurity directorySecurity)
+ {
+ if (directorySecurity == null)
+ throw new ArgumentNullException("directorySecurity");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+ directorySecurity.Persist(fullPath);
+ }
+#endif
+
+ // Returns an array of filenames in the DirectoryInfo specified by path
+ public static String[] GetFiles(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFiles(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search pattern (ie, "*.txt").
+ public static String[] GetFiles(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search pattern (ie, "*.txt") and search option
+ public static String[] GetFiles(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFiles(path, searchPattern, searchOption);
+ }
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search pattern (ie, "*.txt") and search option
+ private static String[] InternalGetFiles(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return InternalGetFileDirectoryNames(path, path, searchPattern, true, false, searchOption, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String[] UnsafeGetFiles(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return InternalGetFileDirectoryNames(path, path, searchPattern, true, false, searchOption, false);
+ }
+
+ // Returns an array of Directories in the current directory.
+ public static String[] GetDirectories(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetDirectories(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ public static String[] GetDirectories(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ public static String[] GetDirectories(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetDirectories(path, searchPattern, searchOption);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ private static String[] InternalGetDirectories(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+ return InternalGetFileDirectoryNames(path, path, searchPattern, false, true, searchOption, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String[] UnsafeGetDirectories(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+ return InternalGetFileDirectoryNames(path, path, searchPattern, false, true, searchOption, false);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path
+ public static String[] GetFileSystemEntries(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path with the
+ // given search criteria (ie, "*.txt"). We disallow .. as a part of the search criteria
+ public static String[] GetFileSystemEntries(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFileSystemEntries(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path with the
+ // given search criteria (ie, "*.txt"). We disallow .. as a part of the search criteria
+ public static String[] GetFileSystemEntries(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ return InternalGetFileSystemEntries(path, searchPattern, searchOption);
+ }
+
+ private static String[] InternalGetFileSystemEntries(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return InternalGetFileDirectoryNames(path, path, searchPattern, true, true, searchOption, true);
+ }
+
+
+ // Private class that holds search data that is passed around
+ // in the heap based stack recursion
+ internal sealed class SearchData
+ {
+ public SearchData(String fullPath, String userPath, SearchOption searchOption)
+ {
+ Contract.Requires(fullPath != null && fullPath.Length > 0);
+ Contract.Requires(userPath != null && userPath.Length > 0);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ this.fullPath = fullPath;
+ this.userPath = userPath;
+ this.searchOption = searchOption;
+ }
+
+ public readonly string fullPath; // Fully qualified search path excluding the search criteria in the end (ex, c:\temp\bar\foo)
+ public readonly string userPath; // User specified path (ex, bar\foo)
+ public readonly SearchOption searchOption;
+ }
+
+
+ // Returns fully qualified user path of dirs/files that matches the search parameters.
+ // For recursive search this method will search through all the sub dirs and execute
+ // the given search criteria against every dir.
+ // For all the dirs/files returned, it will then demand path discovery permission for
+ // their parent folders (it will avoid duplicate permission checks)
+ internal static String[] InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, bool includeFiles, bool includeDirs, SearchOption searchOption, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(userPathOriginal != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ IEnumerable<String> enble = FileSystemEnumerableFactory.CreateFileNameIterator(
+ path, userPathOriginal, searchPattern,
+ includeFiles, includeDirs, searchOption, checkHost);
+ List<String> fileList = new List<String>(enble);
+ return fileList.ToArray();
+ }
+
+ public static IEnumerable<String> EnumerateDirectories(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ return InternalEnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateDirectories(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalEnumerateDirectories(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateDirectories(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalEnumerateDirectories(path, searchPattern, searchOption);
+ }
+
+ private static IEnumerable<String> InternalEnumerateDirectories(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return EnumerateFileSystemNames(path, searchPattern, searchOption, false, true);
+ }
+
+ public static IEnumerable<String> EnumerateFiles(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateFiles(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFiles(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateFiles(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFiles(path, searchPattern, searchOption);
+ }
+
+ private static IEnumerable<String> InternalEnumerateFiles(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+
+ return EnumerateFileSystemNames(path, searchPattern, searchOption, true, false);
+ }
+
+ public static IEnumerable<String> EnumerateFileSystemEntries(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateFileSystemEntries(String path, String searchPattern)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFileSystemEntries(path, searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public static IEnumerable<String> EnumerateFileSystemEntries(String path, String searchPattern, SearchOption searchOption)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFileSystemEntries(path, searchPattern, searchOption);
+ }
+
+ private static IEnumerable<String> InternalEnumerateFileSystemEntries(String path, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+
+ return EnumerateFileSystemNames(path, searchPattern, searchOption, true, true);
+ }
+
+ private static IEnumerable<String> EnumerateFileSystemNames(String path, String searchPattern, SearchOption searchOption,
+ bool includeFiles, bool includeDirs)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Ensures(Contract.Result<IEnumerable<String>>() != null);
+
+ return FileSystemEnumerableFactory.CreateFileNameIterator(path, path, searchPattern,
+ includeFiles, includeDirs, searchOption, true);
+ }
+
+ // Retrieves the names of the logical drives on this machine in the
+ // form "C:\".
+ //
+ // Your application must have System Info permission.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String[] GetLogicalDrives()
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+
+ int drives = Win32Native.GetLogicalDrives();
+ if (drives==0)
+ __Error.WinIOError();
+ uint d = (uint)drives;
+ int count = 0;
+ while (d != 0) {
+ if (((int)d & 1) != 0) count++;
+ d >>= 1;
+ }
+ String[] result = new String[count];
+ char[] root = new char[] {'A', ':', '\\'};
+ d = (uint)drives;
+ count = 0;
+ while (d != 0) {
+ if (((int)d & 1) != 0) {
+ result[count++] = new String(root);
+ }
+ d >>= 1;
+ root[0]++;
+ }
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static String GetDirectoryRoot(String path) {
+ if (path==null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+ String root = fullPath.Substring(0, Path.GetRootLength(fullPath));
+ String demandPath = GetDemandDir(root, true);
+
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, path, demandPath);
+ state.EnsureState();
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, demandPath, false, false);
+#endif
+
+ return root;
+ }
+
+ internal static String InternalGetDirectoryRoot(String path) {
+ if (path == null) return null;
+ return path.Substring(0, Path.GetRootLength(path));
+ }
+
+ /*===============================CurrentDirectory===============================
+ **Action: Provides a getter and setter for the current directory. The original
+ ** current DirectoryInfo is the one from which the process was started.
+ **Returns: The current DirectoryInfo (from the getter). Void from the setter.
+ **Arguments: The current DirectoryInfo to which to switch to the setter.
+ **Exceptions:
+ ==============================================================================*/
+ [System.Security.SecuritySafeCritical]
+ public static String GetCurrentDirectory()
+ {
+ return InternalGetCurrentDirectory(true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String UnsafeGetCurrentDirectory()
+ {
+ return InternalGetCurrentDirectory(false);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static string InternalGetCurrentDirectory(bool checkHost)
+ {
+ string currentDirectory = (
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.UseLegacyPathHandling ? LegacyGetCurrentDirectory() :
+#endif
+ 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;
+ }
+
+#if FEATURE_PATHCOMPAT
+ [System.Security.SecurityCritical]
+ private static String LegacyGetCurrentDirectory()
+ {
+ StringBuilder sb = StringBuilderCache.Acquire(Path.MaxPath + 1);
+ if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0)
+ __Error.WinIOError();
+ 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) {
+ int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity);
+ if (r == 0 || r >= Path.MaxPath) {
+ int errorCode = Marshal.GetLastWin32Error();
+ if (r >= Path.MaxPath)
+ 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);
+ }
+ currentDirectory = sb.ToString();
+ }
+ StringBuilderCache.Release(sb);
+ String demandPath = GetDemandDir(currentDirectory, true);
+
+ return currentDirectory;
+ }
+#endif // FEATURE_PATHCOMPAT
+
+ [System.Security.SecurityCritical]
+ private static string NewGetCurrentDirectory()
+ {
+ using (StringBuffer buffer = new StringBuffer(PathInternal.MaxShortPath))
+ {
+ 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 !PLATFORM_UNIX
+ if (buffer.Contains('~'))
+ return LongPathHelper.GetLongPathName(buffer);
+#endif
+
+ return buffer.ToString();
+ }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ 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.MaxPath)
+ 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
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+
+ String fulldestDirName = Path.GetFullPathInternal(path);
+
+ if (!Win32Native.SetCurrentDirectory(fulldestDirName)) {
+ // If path doesn't exist, this sets last error to 2 (File
+ // not Found). LEGACY: This may potentially have worked correctly
+ // on Win9x, maybe.
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == Win32Native.ERROR_FILE_NOT_FOUND)
+ errorCode = Win32Native.ERROR_PATH_NOT_FOUND;
+ __Error.WinIOError(errorCode, fulldestDirName);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static void Move(String sourceDirName,String destDirName) {
+ InternalMove(sourceDirName, destDirName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeMove(String sourceDirName,String destDirName) {
+ InternalMove(sourceDirName, destDirName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ 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)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName");
+ Contract.EndContractBlock();
+
+ String fullsourceDirName = Path.GetFullPathInternal(sourceDirName);
+ String sourcePath = GetDemandDir(fullsourceDirName, false);
+
+ if (PathInternal.IsDirectoryTooLong(sourcePath))
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ String fulldestDirName = Path.GetFullPathInternal(destDirName);
+ String destPath = GetDemandDir(fulldestDirName, false);
+
+ if (PathInternal.IsDirectoryTooLong(destPath))
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+#if FEATURE_CORECLR
+ if (checkHost) {
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceDirName, sourcePath);
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, destPath);
+ sourceState.EnsureState();
+ destState.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, sourcePath, false, false);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, destPath, false, false);
+#endif
+
+ if (String.Compare(sourcePath, destPath, StringComparison.OrdinalIgnoreCase) == 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent"));
+
+ String sourceRoot = Path.GetPathRoot(sourcePath);
+ String destinationRoot = Path.GetPathRoot(destPath);
+ if (String.Compare(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase) != 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot"));
+
+ if (!Win32Native.MoveFile(sourceDirName, destDirName))
+ {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // Source dir not found
+ {
+ hr = Win32Native.ERROR_PATH_NOT_FOUND;
+ __Error.WinIOError(hr, fullsourceDirName);
+ }
+ // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons.
+ if (hr == Win32Native.ERROR_ACCESS_DENIED) // WinNT throws IOException. This check is for Win9x. We can't change it for backcomp.
+ throw new IOException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", sourceDirName), Win32Native.MakeHRFromErrorCode(hr));
+ __Error.WinIOError(hr, String.Empty);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static void Delete(String path)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+ Delete(fullPath, path, false, true);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static void Delete(String path, bool recursive)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+ Delete(fullPath, path, recursive, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeDelete(String path, bool recursive)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+ Delete(fullPath, path, recursive, false);
+ }
+
+ // Called from DirectoryInfo as well. FullPath is fully qualified,
+ // while the user path is used for feedback in exceptions.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Delete(String fullPath, String userPath, bool recursive, bool checkHost)
+ {
+ String demandPath;
+
+ // If not recursive, do permission check only on this directory
+ // else check for the whole directory structure rooted below
+ demandPath = GetDemandDir(fullPath, !recursive);
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, userPath, demandPath);
+ state.EnsureState();
+ }
+#else
+ // Make sure we have write permission to this directory
+ new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false ).Demand();
+#endif
+
+ // Do not recursively delete through reparse points. Perhaps in a
+ // future version we will add a new flag to control this behavior,
+ // but for now we're much safer if we err on the conservative side.
+ // This applies to symbolic links and mount points.
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = File.FillAttributeInfo(fullPath, ref data, false, true);
+ if (dataInitialised != 0) {
+ // Ensure we throw a DirectoryNotFoundException.
+ if (dataInitialised == Win32Native.ERROR_FILE_NOT_FOUND)
+ dataInitialised = Win32Native.ERROR_PATH_NOT_FOUND;
+ __Error.WinIOError(dataInitialised, fullPath);
+ }
+
+ if (((FileAttributes)data.fileAttributes & FileAttributes.ReparsePoint) != 0)
+ recursive = false;
+
+ DeleteHelper(fullPath, userPath, recursive, true);
+ }
+
+ // Note that fullPath is fully qualified, while userPath may be
+ // relative. Use userPath for all exception messages to avoid leaking
+ // fully qualified path information.
+ [System.Security.SecurityCritical] // auto-generated
+ private static void DeleteHelper(String fullPath, String userPath, bool recursive, bool throwOnTopLevelDirectoryNotFound)
+ {
+ bool r;
+ int hr;
+ Exception ex = null;
+
+ // Do not recursively delete through reparse points. Perhaps in a
+ // future version we will add a new flag to control this behavior,
+ // but for now we're much safer if we err on the conservative side.
+ // This applies to symbolic links and mount points.
+ // Note the logic to check whether fullPath is a reparse point is
+ // in Delete(String, String, bool), and will set "recursive" to false.
+ // Note that Win32's DeleteFile and RemoveDirectory will just delete
+ // the reparse point itself.
+
+ if (recursive) {
+ Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA();
+
+ // Open a Find handle
+ using (SafeFindHandle hnd = Win32Native.FindFirstFile(fullPath+Path.DirectorySeparatorCharAsString+"*", data)) {
+ if (hnd.IsInvalid) {
+ hr = Marshal.GetLastWin32Error();
+ __Error.WinIOError(hr, fullPath);
+ }
+
+ do {
+ bool isDir = (0!=(data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY));
+ if (isDir) {
+ // Skip ".", "..".
+ if (data.cFileName.Equals(".") || data.cFileName.Equals(".."))
+ continue;
+
+ // Recurse for all directories, unless they are
+ // reparse points. Do not follow mount points nor
+ // symbolic links, but do delete the reparse point
+ // itself.
+ bool shouldRecurse = (0 == (data.dwFileAttributes & (int) FileAttributes.ReparsePoint));
+ if (shouldRecurse) {
+ String newFullPath = Path.InternalCombine(fullPath, data.cFileName);
+ String newUserPath = Path.InternalCombine(userPath, data.cFileName);
+ try {
+ DeleteHelper(newFullPath, newUserPath, recursive, false);
+ }
+ catch(Exception e) {
+ if (ex == null) {
+ ex = e;
+ }
+ }
+ }
+ else {
+ // Check to see if this is a mount point, and
+ // unmount it.
+ if (data.dwReserved0 == Win32Native.IO_REPARSE_TAG_MOUNT_POINT) {
+ // Use full path plus a trailing '\'
+ String mountPoint = Path.InternalCombine(fullPath, data.cFileName + Path.DirectorySeparatorChar);
+ r = Win32Native.DeleteVolumeMountPoint(mountPoint);
+ if (!r) {
+ hr = Marshal.GetLastWin32Error();
+ if (hr != Win32Native.ERROR_PATH_NOT_FOUND) {
+ try {
+ __Error.WinIOError(hr, data.cFileName);
+ }
+ catch(Exception e) {
+ if (ex == null) {
+ ex = e;
+ }
+ }
+ }
+ }
+ }
+
+ // RemoveDirectory on a symbolic link will
+ // remove the link itself.
+ String reparsePoint = Path.InternalCombine(fullPath, data.cFileName);
+ r = Win32Native.RemoveDirectory(reparsePoint);
+ if (!r) {
+ hr = Marshal.GetLastWin32Error();
+ if (hr != Win32Native.ERROR_PATH_NOT_FOUND) {
+ try {
+ __Error.WinIOError(hr, data.cFileName);
+ }
+ catch(Exception e) {
+ if (ex == null) {
+ ex = e;
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ String fileName = Path.InternalCombine(fullPath, data.cFileName);
+ r = Win32Native.DeleteFile(fileName);
+ if (!r) {
+ hr = Marshal.GetLastWin32Error();
+ if (hr != Win32Native.ERROR_FILE_NOT_FOUND) {
+ try {
+ __Error.WinIOError(hr, data.cFileName);
+ }
+ catch (Exception e) {
+ if (ex == null) {
+ ex = e;
+ }
+ }
+ }
+ }
+ }
+ } while (Win32Native.FindNextFile(hnd, data));
+ // Make sure we quit with a sensible error.
+ hr = Marshal.GetLastWin32Error();
+ }
+
+ if (ex != null)
+ throw ex;
+ if (hr!=0 && hr!=Win32Native.ERROR_NO_MORE_FILES)
+ __Error.WinIOError(hr, userPath);
+ }
+
+ r = Win32Native.RemoveDirectory(fullPath);
+
+ if (!r) {
+ hr = Marshal.GetLastWin32Error();
+ if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // A dubious error code.
+ hr = Win32Native.ERROR_PATH_NOT_FOUND;
+ // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons.
+ if (hr == Win32Native.ERROR_ACCESS_DENIED)
+ throw new IOException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", userPath));
+
+ // don't throw the DirectoryNotFoundException since this is a subdir and there could be a race condition
+ // between two Directory.Delete callers
+ if (hr == Win32Native.ERROR_PATH_NOT_FOUND && !throwOnTopLevelDirectoryNotFound)
+ return;
+
+ __Error.WinIOError(hr, fullPath);
+ }
+ }
+
+ // WinNT only. Win9x this code will not work.
+ [System.Security.SecurityCritical] // auto-generated
+ private static SafeFileHandle OpenHandle(String path)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+ String root = Path.GetPathRoot(fullPath);
+ if (root == fullPath && root[1] == Path.VolumeSeparatorChar)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIsVolume"));
+
+#if !FEATURE_CORECLR
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, GetDemandDir(fullPath, true), false, false);
+#endif
+
+ SafeFileHandle handle = Win32Native.SafeCreateFile (
+ fullPath,
+ GENERIC_WRITE,
+ (FileShare) (FILE_SHARE_WRITE|FILE_SHARE_DELETE),
+ null,
+ FileMode.Open,
+ FILE_FLAG_BACKUP_SEMANTICS,
+ IntPtr.Zero
+ );
+
+ if (handle.IsInvalid) {
+ int hr = Marshal.GetLastWin32Error();
+ __Error.WinIOError(hr, fullPath);
+ }
+ return handle;
+ }
+
+ private const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
+ private const int GENERIC_WRITE = unchecked((int)0x40000000);
+ private const int FILE_SHARE_WRITE = 0x00000002;
+ private const int FILE_SHARE_DELETE = 0x00000004;
+ private const int OPEN_EXISTING = 0x00000003;
+ private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000;
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/IO/DirectoryInfo.cs b/src/mscorlib/src/System/IO/DirectoryInfo.cs
new file mode 100644
index 0000000000..f7b0709e9e
--- /dev/null
+++ b/src/mscorlib/src/System/IO/DirectoryInfo.cs
@@ -0,0 +1,672 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exposes routines for enumerating through a
+** directory.
+**
+** April 11,2000
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Security;
+#if FEATURE_MACL
+using System.Security.AccessControl;
+#endif
+using System.Security.Permissions;
+using Microsoft.Win32;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ [Serializable]
+ [ComVisible(true)]
+ public sealed class DirectoryInfo : FileSystemInfo {
+ private String[] demandDir;
+
+#if FEATURE_CORECLR
+ // Migrating InheritanceDemands requires this default ctor, so we can annotate it.
+#if FEATURE_CORESYSTEM
+ [System.Security.SecurityCritical]
+#else
+ [System.Security.SecuritySafeCritical]
+#endif //FEATURE_CORESYSTEM
+ private DirectoryInfo(){}
+
+
+ [System.Security.SecurityCritical]
+ public static DirectoryInfo UnsafeCreateDirectoryInfo(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ DirectoryInfo di = new DirectoryInfo();
+ di.Init(path, false);
+ return di;
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical]
+ public DirectoryInfo(String path)
+ {
+ if (path==null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ Init(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ private void Init(String path, bool checkHost)
+ {
+ // Special case "<DriveLetter>:" to point to "<CurrentDirectory>" instead
+ if ((path.Length == 2) && (path[1] == ':'))
+ {
+ OriginalPath = ".";
+ }
+ else
+ {
+ OriginalPath = path;
+ }
+
+ // Must fully qualify the path for the security check
+ String fullPath = Path.GetFullPathInternal(path);
+
+ demandDir = new String[] {Directory.GetDemandDir(fullPath, true)};
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, OriginalPath, fullPath);
+ state.EnsureState();
+ }
+#else
+ new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
+#endif
+
+ FullPath = fullPath;
+ DisplayPath = GetDisplayName(OriginalPath, FullPath);
+ }
+
+#if FEATURE_CORESYSTEM
+ [System.Security.SecuritySafeCritical]
+#endif //FEATURE_CORESYSTEM
+ internal DirectoryInfo(String fullPath, bool junk)
+ {
+ Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
+ // Fast path when we know a DirectoryInfo exists.
+ OriginalPath = Path.GetFileName(fullPath);
+
+ FullPath = fullPath;
+ DisplayPath = GetDisplayName(OriginalPath, FullPath);
+ demandDir = new String[] {Directory.GetDemandDir(fullPath, true)};
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private DirectoryInfo(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+#if !FEATURE_CORECLR
+ demandDir = new String[] {Directory.GetDemandDir(FullPath, true)};
+ new FileIOPermission(FileIOPermissionAccess.Read, demandDir, false, false ).Demand();
+#endif
+ DisplayPath = GetDisplayName(OriginalPath, FullPath);
+ }
+
+ public override String Name {
+ get
+ {
+#if FEATURE_CORECLR
+ // DisplayPath is dir name for coreclr
+ return DisplayPath;
+#else
+ // Return just dir name
+ return GetDirName(FullPath);
+#endif
+ }
+ }
+
+ public DirectoryInfo Parent {
+ [System.Security.SecuritySafeCritical]
+ get {
+ String parentName;
+ // FullPath might be either "c:\bar" or "c:\bar\". Handle
+ // those cases, as well as avoiding mangling "c:\".
+ String s = FullPath;
+ if (s.Length > 3 && s.EndsWith(Path.DirectorySeparatorChar))
+ s = FullPath.Substring(0, FullPath.Length - 1);
+ parentName = Path.GetDirectoryName(s);
+ if (parentName==null)
+ return null;
+ DirectoryInfo dir = new DirectoryInfo(parentName,false);
+#if FEATURE_CORECLR
+ 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();
+#endif
+ return dir;
+ }
+ }
+
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public DirectoryInfo CreateSubdirectory(String path) {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ return CreateSubdirectory(path, null);
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public DirectoryInfo CreateSubdirectory(String path, DirectorySecurity directorySecurity)
+ {
+ return CreateSubdirectoryHelper(path, directorySecurity);
+ }
+#else // FEATURE_MACL
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public DirectoryInfo CreateSubdirectory(String path, Object directorySecurity)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ return CreateSubdirectoryHelper(path, directorySecurity);
+ }
+#endif // FEATURE_MACL
+
+ [System.Security.SecurityCritical] // auto-generated
+ private DirectoryInfo CreateSubdirectoryHelper(String path, Object directorySecurity)
+ {
+ Contract.Requires(path != null);
+
+ String newDirs = Path.InternalCombine(FullPath, path);
+ String fullPath = Path.GetFullPathInternal(newDirs);
+
+ if (0!=String.Compare(FullPath,0,fullPath,0, FullPath.Length,StringComparison.OrdinalIgnoreCase)) {
+ String displayPath = __Error.GetDisplayablePath(DisplayPath, false);
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSubPath", path, displayPath));
+ }
+
+ // Ensure we have permission to create this subdirectory.
+ String demandDirForCreation = Directory.GetDemandDir(fullPath, true);
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, OriginalPath, demandDirForCreation);
+ state.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandDirForCreation }, false, false).Demand();
+#endif
+
+ Directory.InternalCreateDirectory(fullPath, path, directorySecurity);
+
+ // Check for read permission to directory we hand back by calling this constructor.
+ return new DirectoryInfo(fullPath);
+ }
+
+ public void Create()
+ {
+ Directory.InternalCreateDirectory(FullPath, OriginalPath, null, true);
+ }
+
+#if FEATURE_MACL
+ public void Create(DirectorySecurity directorySecurity)
+ {
+ Directory.InternalCreateDirectory(FullPath, OriginalPath, directorySecurity, true);
+ }
+#endif
+
+ // Tests if the given path refers to an existing DirectoryInfo on disk.
+ //
+ // Your application must have Read permission to the directory's
+ // contents.
+ //
+ public override bool Exists {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ try
+ {
+ if (_dataInitialised == -1)
+ Refresh();
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ return false;
+
+ return _data.fileAttributes != -1 && (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+#if FEATURE_MACL
+ public DirectorySecurity GetAccessControl()
+ {
+ return Directory.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ public DirectorySecurity GetAccessControl(AccessControlSections includeSections)
+ {
+ return Directory.GetAccessControl(FullPath, includeSections);
+ }
+
+ public void SetAccessControl(DirectorySecurity directorySecurity)
+ {
+ Directory.SetAccessControl(FullPath, directorySecurity);
+ }
+#endif
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ public FileInfo[] GetFiles(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalGetFiles(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ public FileInfo[] GetFiles(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalGetFiles(searchPattern, searchOption);
+ }
+
+ // Returns an array of Files in the current DirectoryInfo matching the
+ // given search criteria (ie, "*.txt").
+ private FileInfo[] InternalGetFiles(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ IEnumerable<FileInfo> enble = FileSystemEnumerableFactory.CreateFileInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ List<FileInfo> fileList = new List<FileInfo>(enble);
+ return fileList.ToArray();
+ }
+
+ // Returns an array of Files in the DirectoryInfo specified by path
+ public FileInfo[] GetFiles()
+ {
+ return InternalGetFiles("*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Directories in the current directory.
+ public DirectoryInfo[] GetDirectories()
+ {
+ return InternalGetDirectories("*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path with the
+ // given search criteria (ie, "*.txt").
+ public FileSystemInfo[] GetFileSystemInfos(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalGetFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path with the
+ // given search criteria (ie, "*.txt").
+ public FileSystemInfo[] GetFileSystemInfos(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalGetFileSystemInfos(searchPattern, searchOption);
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries in the path with the
+ // given search criteria (ie, "*.txt").
+ private FileSystemInfo[] InternalGetFileSystemInfos(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ IEnumerable<FileSystemInfo> enble = FileSystemEnumerableFactory.CreateFileSystemInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ List<FileSystemInfo> fileList = new List<FileSystemInfo>(enble);
+ return fileList.ToArray();
+ }
+
+ // Returns an array of strongly typed FileSystemInfo entries which will contain a listing
+ // of all the files and directories.
+ public FileSystemInfo[] GetFileSystemInfos()
+ {
+ return InternalGetFileSystemInfos("*", SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "System*" could match the System & System32
+ // directories).
+ public DirectoryInfo[] GetDirectories(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalGetDirectories(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "System*" could match the System & System32
+ // directories).
+ public DirectoryInfo[] GetDirectories(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalGetDirectories(searchPattern, searchOption);
+ }
+
+ // Returns an array of Directories in the current DirectoryInfo matching the
+ // given search criteria (ie, "System*" could match the System & System32
+ // directories).
+ private DirectoryInfo[] InternalGetDirectories(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ IEnumerable<DirectoryInfo> enble = FileSystemEnumerableFactory.CreateDirectoryInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ List<DirectoryInfo> fileList = new List<DirectoryInfo>(enble);
+ return fileList.ToArray();
+ }
+
+ public IEnumerable<DirectoryInfo> EnumerateDirectories()
+ {
+ return InternalEnumerateDirectories("*", SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<DirectoryInfo> EnumerateDirectories(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalEnumerateDirectories(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<DirectoryInfo> EnumerateDirectories(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalEnumerateDirectories(searchPattern, searchOption);
+ }
+
+ private IEnumerable<DirectoryInfo> InternalEnumerateDirectories(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return FileSystemEnumerableFactory.CreateDirectoryInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ }
+
+ public IEnumerable<FileInfo> EnumerateFiles()
+ {
+ return InternalEnumerateFiles("*", SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<FileInfo> EnumerateFiles(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<FileInfo> EnumerateFiles(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFiles(searchPattern, searchOption);
+ }
+
+ private IEnumerable<FileInfo> InternalEnumerateFiles(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return FileSystemEnumerableFactory.CreateFileInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ }
+
+ public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos()
+ {
+ return InternalEnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(String searchPattern)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly);
+ }
+
+ public IEnumerable<FileSystemInfo> EnumerateFileSystemInfos(String searchPattern, SearchOption searchOption)
+ {
+ if (searchPattern == null)
+ throw new ArgumentNullException("searchPattern");
+ if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories))
+ throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ return InternalEnumerateFileSystemInfos(searchPattern, searchOption);
+ }
+
+ private IEnumerable<FileSystemInfo> InternalEnumerateFileSystemInfos(String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+
+ return FileSystemEnumerableFactory.CreateFileSystemInfoIterator(FullPath, OriginalPath, searchPattern, searchOption);
+ }
+
+ // 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
+ // empty string (a relative path on the current drive), "\" (an absolute
+ // path on the current drive), "X:" (a relative path on a given drive,
+ // where X is the drive letter), "X:\" (an absolute path on a given drive),
+ // and "\\server\share" (a UNC path for a given server and share name).
+ // The resulting string is null if path is null.
+ //
+
+ public DirectoryInfo Root {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ String demandPath;
+ int rootLength = Path.GetRootLength(FullPath);
+ String rootPath = FullPath.Substring(0, rootLength);
+ demandPath = Directory.GetDemandDir(rootPath, true);
+
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPath);
+ sourceState.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false).Demand();
+#endif
+ return new DirectoryInfo(rootPath);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public void MoveTo(String destDirName) {
+ if (destDirName==null)
+ throw new ArgumentNullException("destDirName");
+ if (destDirName.Length==0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName");
+ Contract.EndContractBlock();
+
+#if FEATURE_CORECLR
+ 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();
+#endif
+ String fullDestDirName = Path.GetFullPathInternal(destDirName);
+ String demandPath;
+ if (!fullDestDirName.EndsWith(Path.DirectorySeparatorChar))
+ fullDestDirName = fullDestDirName + Path.DirectorySeparatorChar;
+
+ demandPath = fullDestDirName + '.';
+
+ // Demand read & write permission to destination. The reason is
+ // we hand back a DirectoryInfo to the destination that would allow
+ // you to read a directory listing from that directory. Sure, you
+ // had the ability to read the file contents in the old location,
+ // but you technically also need read permissions to the new
+ // location as well, and write is not a true superset of read.
+#if FEATURE_CORECLR
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destDirName, demandPath);
+ destState.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, demandPath).Demand();
+#endif
+
+ String fullSourcePath;
+ if (FullPath.EndsWith(Path.DirectorySeparatorChar))
+ fullSourcePath = FullPath;
+ else
+ fullSourcePath = FullPath + Path.DirectorySeparatorChar;
+
+ if (String.Compare(fullSourcePath, fullDestDirName, StringComparison.OrdinalIgnoreCase) == 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent"));
+
+ String sourceRoot = Path.GetPathRoot(fullSourcePath);
+ String destinationRoot = Path.GetPathRoot(fullDestDirName);
+
+ if (String.Compare(sourceRoot, destinationRoot, StringComparison.OrdinalIgnoreCase) != 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot"));
+
+ if (!Win32Native.MoveFile(FullPath, destDirName))
+ {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // A dubious error code
+ {
+ hr = Win32Native.ERROR_PATH_NOT_FOUND;
+ __Error.WinIOError(hr, DisplayPath);
+ }
+
+ if (hr == Win32Native.ERROR_ACCESS_DENIED) // We did this for Win9x. We can't change it for backcomp.
+ throw new IOException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", DisplayPath));
+
+ __Error.WinIOError(hr,String.Empty);
+ }
+ FullPath = fullDestDirName;
+ OriginalPath = destDirName;
+ DisplayPath = GetDisplayName(OriginalPath, FullPath);
+ demandDir = new String[] { Directory.GetDemandDir(FullPath, true) };
+
+ // Flush any cached information about the directory.
+ _dataInitialised = -1;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override void Delete()
+ {
+ Directory.Delete(FullPath, OriginalPath, false, true);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public void Delete(bool recursive)
+ {
+ Directory.Delete(FullPath, OriginalPath, recursive, true);
+ }
+
+ // Returns the fully qualified path
+ public override String ToString()
+ {
+ return DisplayPath;
+ }
+
+ private static String GetDisplayName(String originalPath, String fullPath)
+ {
+ Contract.Assert(originalPath != null);
+ Contract.Assert(fullPath != null);
+
+ String displayName = "";
+
+ // Special case "<DriveLetter>:" to point to "<CurrentDirectory>" instead
+ if ((originalPath.Length == 2) && (originalPath[1] == ':'))
+ {
+ displayName = ".";
+ }
+ else
+ {
+#if FEATURE_CORECLR
+ displayName = GetDirName(fullPath);
+#else
+ displayName = originalPath;
+#endif
+ }
+ return displayName;
+ }
+
+ private static String GetDirName(String fullPath)
+ {
+ Contract.Assert(fullPath != null);
+
+ String dirName = null;
+ if (fullPath.Length > 3)
+ {
+ String s = fullPath;
+ if (fullPath.EndsWith(Path.DirectorySeparatorChar))
+ {
+ s = fullPath.Substring(0, fullPath.Length - 1);
+ }
+ dirName = Path.GetFileName(s);
+ }
+ else
+ {
+ dirName = fullPath; // For rooted paths, like "c:\"
+ }
+ return dirName;
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/IO/DirectoryNotFoundException.cs b/src/mscorlib/src/System/IO/DirectoryNotFoundException.cs
new file mode 100644
index 0000000000..09d7e7d4e7
--- /dev/null
+++ b/src/mscorlib/src/System/IO/DirectoryNotFoundException.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception for accessing a path that doesn't exist.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO {
+ /*
+ * Thrown when trying to access a directory that doesn't exist on disk.
+ * From COM Interop, this exception is thrown for 2 HRESULTS:
+ * the Win32 errorcode-as-HRESULT ERROR_PATH_NOT_FOUND (0x80070003)
+ * and STG_E_PATHNOTFOUND (0x80030003).
+ */
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class DirectoryNotFoundException : IOException {
+ public DirectoryNotFoundException()
+ : base(Environment.GetResourceString("Arg_DirectoryNotFoundException")) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ public DirectoryNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ public DirectoryNotFoundException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ protected DirectoryNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/DriveInfo.cs b/src/mscorlib/src/System/IO/DriveInfo.cs
new file mode 100644
index 0000000000..be75e8979d
--- /dev/null
+++ b/src/mscorlib/src/System/IO/DriveInfo.cs
@@ -0,0 +1,281 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exposes routines for exploring a drive.
+**
+**
+===========================================================*/
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using Microsoft.Win32;
+using System.Security.Permissions;
+using System.Runtime.Serialization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO
+{
+ // Matches Win32's DRIVE_XXX #defines from winbase.h
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum DriveType
+ {
+ Unknown = 0,
+ NoRootDirectory = 1,
+ Removable = 2,
+ Fixed = 3,
+ Network = 4,
+ CDRom = 5,
+ Ram = 6
+ }
+
+ // Ideally we'll get a better security permission, but possibly
+ // not for Whidbey.
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ [ComVisible(true)]
+ public sealed class DriveInfo
+#if FEATURE_SERIALIZATION
+ : ISerializable
+#endif
+ {
+ private String _name;
+
+ private const String NameField = "_name"; // For serialization
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public DriveInfo(String driveName)
+ {
+ if (driveName == null)
+ throw new ArgumentNullException("driveName");
+ Contract.EndContractBlock();
+ if (driveName.Length == 1)
+ _name = driveName + ":\\";
+ else {
+ // GetPathRoot does not check all invalid characters
+ Path.CheckInvalidPathChars(driveName);
+ _name = Path.GetPathRoot(driveName);
+ // Disallow null or empty drive letters and UNC paths
+ if (_name == null || _name.Length == 0 || _name.StartsWith("\\\\", StringComparison.Ordinal))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDriveLetterOrRootDir"));
+ }
+ // We want to normalize to have a trailing backslash so we don't have two equivalent forms and
+ // because some Win32 API don't work without it.
+ if (_name.Length == 2 && _name[1] == ':') {
+ _name = _name + "\\";
+ }
+
+ // Now verify that the drive letter could be a real drive name.
+ // On Windows this means it's between A and Z, ignoring case.
+ // On a Unix platform, perhaps this should be a device name with
+ // a partition like /dev/hdc0, or possibly a mount point.
+ char letter = driveName[0];
+ if (!((letter >= 'A' && letter <= 'Z') || (letter >= 'a' && letter <= 'z')))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDriveLetterOrRootDir"));
+
+ // Now do a security check.
+ String demandPath = _name + '.';
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPath).Demand();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private DriveInfo(SerializationInfo info, StreamingContext context)
+ {
+ // Need to add in a security check here once it has been spec'ed.
+ _name = (String) info.GetValue(NameField, typeof(String));
+
+ // Now do a security check.
+ String demandPath = _name + '.';
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPath).Demand();
+ }
+
+ public String Name {
+ get { return _name; }
+ }
+
+ public DriveType DriveType {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ // GetDriveType can't fail
+ return (DriveType) Win32Native.GetDriveType(Name);
+ }
+ }
+
+ public String DriveFormat {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ const int volNameLen = 50;
+ StringBuilder volumeName = new StringBuilder(volNameLen);
+ const int fileSystemNameLen = 50;
+ StringBuilder fileSystemName = new StringBuilder(fileSystemNameLen);
+ int serialNumber, maxFileNameLen, fileSystemFlags;
+
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.GetVolumeInformation(Name, volumeName, volNameLen, out serialNumber, out maxFileNameLen, out fileSystemFlags, fileSystemName, fileSystemNameLen);
+ if (!r) {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIODriveError(Name, errorCode);
+ }
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ return fileSystemName.ToString();
+ }
+ }
+
+ public bool IsReady {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return Directory.InternalExists(Name);
+ }
+ }
+
+ public long AvailableFreeSpace {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ long userBytes, totalBytes, freeBytes;
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
+ if (!r)
+ __Error.WinIODriveError(Name);
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ return userBytes;
+ }
+ }
+
+ public long TotalFreeSpace {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ long userBytes, totalBytes, freeBytes;
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
+ if (!r)
+ __Error.WinIODriveError(Name);
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ return freeBytes;
+ }
+ }
+
+ public long TotalSize {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ // Don't cache this, to handle variable sized floppy drives
+ // or other various removable media drives.
+ long userBytes, totalBytes, freeBytes;
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.GetDiskFreeSpaceEx(Name, out userBytes, out totalBytes, out freeBytes);
+ if (!r)
+ __Error.WinIODriveError(Name);
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ return totalBytes;
+ }
+ }
+
+ public static DriveInfo[] GetDrives()
+ {
+ // Directory.GetLogicalDrives demands unmanaged code permission
+ String[] drives = Directory.GetLogicalDrives();
+ DriveInfo[] di = new DriveInfo[drives.Length];
+ for(int i=0; i<drives.Length; i++)
+ di[i] = new DriveInfo(drives[i]);
+ return di;
+ }
+
+ public DirectoryInfo RootDirectory {
+ get {
+ return new DirectoryInfo(Name);
+ }
+ }
+
+ // Null is a valid volume label.
+ public String VolumeLabel {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ // NTFS uses a limit of 32 characters for the volume label,
+ // as of Windows Server 2003.
+ const int volNameLen = 50;
+ StringBuilder volumeName = new StringBuilder(volNameLen);
+ const int fileSystemNameLen = 50;
+ StringBuilder fileSystemName = new StringBuilder(fileSystemNameLen);
+ int serialNumber, maxFileNameLen, fileSystemFlags;
+
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.GetVolumeInformation(Name, volumeName, volNameLen, out serialNumber, out maxFileNameLen, out fileSystemFlags, fileSystemName, fileSystemNameLen);
+ if (!r) {
+ int errorCode = Marshal.GetLastWin32Error();
+ // Win9x appears to return ERROR_INVALID_DATA when a
+ // drive doesn't exist.
+ if (errorCode == Win32Native.ERROR_INVALID_DATA)
+ errorCode = Win32Native.ERROR_INVALID_DRIVE;
+ __Error.WinIODriveError(Name, errorCode);
+ }
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ return volumeName.ToString();
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ set {
+ String demandPath = _name + '.';
+ new FileIOPermission(FileIOPermissionAccess.Write, demandPath).Demand();
+
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool r = Win32Native.SetVolumeLabel(Name, value);
+ if (!r) {
+ int errorCode = Marshal.GetLastWin32Error();
+ // Provide better message
+ if (errorCode == Win32Native.ERROR_ACCESS_DENIED)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("InvalidOperation_SetVolumeLabelFailed"));
+ __Error.WinIODriveError(Name, errorCode);
+ }
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+ }
+ }
+
+ public override String ToString()
+ {
+ return Name;
+ }
+
+#if FEATURE_SERIALIZATION
+ /// <internalonly/>
+ [System.Security.SecurityCritical]
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // No need for an additional security check - everything is public.
+ info.AddValue(NameField, _name, typeof(String));
+ }
+#endif
+
+ }
+}
diff --git a/src/mscorlib/src/System/IO/DriveNotFoundException.cs b/src/mscorlib/src/System/IO/DriveNotFoundException.cs
new file mode 100644
index 0000000000..04155bcc0e
--- /dev/null
+++ b/src/mscorlib/src/System/IO/DriveNotFoundException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//============================================================
+//
+//
+//
+// Purpose: Exception for accessing a drive that is not available.
+//
+//
+//============================================================
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO {
+
+ //Thrown when trying to access a drive that is not availabe.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class DriveNotFoundException : IOException {
+ public DriveNotFoundException()
+ : base(Environment.GetResourceString("Arg_DriveNotFoundException")) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ public DriveNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ public DriveNotFoundException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_DIRECTORYNOTFOUND);
+ }
+
+ protected DriveNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/EndOfStreamException.cs b/src/mscorlib/src/System/IO/EndOfStreamException.cs
new file mode 100644
index 0000000000..60f5109a0f
--- /dev/null
+++ b/src/mscorlib/src/System/IO/EndOfStreamException.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception to be thrown when reading past end-of-file.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class EndOfStreamException : IOException
+ {
+ public EndOfStreamException()
+ : base(Environment.GetResourceString("Arg_EndOfStreamException")) {
+ SetErrorCode(__HResults.COR_E_ENDOFSTREAM);
+ }
+
+ public EndOfStreamException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ENDOFSTREAM);
+ }
+
+ public EndOfStreamException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_ENDOFSTREAM);
+ }
+
+ protected EndOfStreamException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/IO/File.cs b/src/mscorlib/src/System/IO/File.cs
new file mode 100644
index 0000000000..cfcb469bc3
--- /dev/null
+++ b/src/mscorlib/src/System/IO/File.cs
@@ -0,0 +1,1255 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of methods for manipulating Files.
+**
+** April 09,2000 (some design refactorization)
+**
+===========================================================*/
+
+using System;
+using System.Security.Permissions;
+using PermissionSet = System.Security.PermissionSet;
+using Win32Native = Microsoft.Win32.Win32Native;
+using System.Runtime.InteropServices;
+using System.Security;
+#if FEATURE_MACL
+using System.Security.AccessControl;
+#endif
+using System.Text;
+using Microsoft.Win32.SafeHandles;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ // Class for creating FileStream objects, and some basic file management
+ // routines such as Delete, etc.
+ [ComVisible(true)]
+ public static class File
+ {
+ private const int GetFileExInfoStandard = 0;
+
+ public static StreamReader OpenText(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+ return new StreamReader(path);
+ }
+
+ public static StreamWriter CreateText(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+ return new StreamWriter(path,false);
+ }
+
+ public static StreamWriter AppendText(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+ return new StreamWriter(path,true);
+ }
+
+
+ // Copies an existing file to a new file. An exception is raised if the
+ // destination file already exists. Use the
+ // Copy(String, String, boolean) method to allow
+ // overwriting an existing file.
+ //
+ // The caller must have certain FileIOPermissions. The caller must have
+ // Read permission to sourceFileName and Create
+ // and Write permissions to destFileName.
+ //
+ public static void Copy(String sourceFileName, String destFileName) {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (sourceFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName");
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ InternalCopy(sourceFileName, destFileName, false, true);
+ }
+
+ // Copies an existing file to a new file. If overwrite is
+ // false, then an IOException is thrown if the destination file
+ // already exists. If overwrite is true, the file is
+ // overwritten.
+ //
+ // The caller must have certain FileIOPermissions. The caller must have
+ // Read permission to sourceFileName
+ // and Write permissions to destFileName.
+ //
+ public static void Copy(String sourceFileName, String destFileName, bool overwrite) {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (sourceFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName");
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ InternalCopy(sourceFileName, destFileName, overwrite, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeCopy(String sourceFileName, String destFileName, bool overwrite) {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (sourceFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName");
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ InternalCopy(sourceFileName, destFileName, overwrite, false);
+ }
+
+ /// <devdoc>
+ /// Note: This returns the fully qualified name of the destination file.
+ /// </devdoc>
+ [System.Security.SecuritySafeCritical]
+ internal static String InternalCopy(String sourceFileName, String destFileName, bool overwrite, bool checkHost) {
+ Contract.Requires(sourceFileName != null);
+ Contract.Requires(destFileName != null);
+ Contract.Requires(sourceFileName.Length > 0);
+ Contract.Requires(destFileName.Length > 0);
+
+ String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
+ String fullDestFileName = Path.GetFullPathInternal(destFileName);
+
+#if FEATURE_CORECLR
+ if (checkHost) {
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, sourceFileName, fullSourceFileName);
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName);
+ sourceState.EnsureState();
+ destState.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullSourceFileName, false, false);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
+#endif
+
+ bool r = Win32Native.CopyFile(fullSourceFileName, fullDestFileName, !overwrite);
+ if (!r) {
+ // Save Win32 error because subsequent checks will overwrite this HRESULT.
+ int errorCode = Marshal.GetLastWin32Error();
+ String fileName = destFileName;
+
+ if (errorCode != Win32Native.ERROR_FILE_EXISTS) {
+ // For a number of error codes (sharing violation, path
+ // not found, etc) we don't know if the problem was with
+ // the source or dest file. Try reading the source file.
+ using(SafeFileHandle handle = Win32Native.UnsafeCreateFile(fullSourceFileName, FileStream.GENERIC_READ, FileShare.Read, null, FileMode.Open, 0, IntPtr.Zero)) {
+ if (handle.IsInvalid)
+ fileName = sourceFileName;
+ }
+
+ if (errorCode == Win32Native.ERROR_ACCESS_DENIED) {
+ if (Directory.InternalExists(fullDestFileName))
+ throw new IOException(Environment.GetResourceString("Arg_FileIsDirectory_Name", destFileName), Win32Native.ERROR_ACCESS_DENIED, fullDestFileName);
+ }
+ }
+
+ __Error.WinIOError(errorCode, fileName);
+ }
+
+ return fullDestFileName;
+ }
+
+
+ // Creates a file in a particular path. If the file exists, it is replaced.
+ // The file is opened with ReadWrite accessand cannot be opened by another
+ // application until it has been closed. An IOException is thrown if the
+ // directory specified doesn't exist.
+ //
+ // Your application must have Create, Read, and Write permissions to
+ // the file.
+ //
+ public static FileStream Create(String path) {
+ return Create(path, FileStream.DefaultBufferSize);
+ }
+
+ // Creates a file in a particular path. If the file exists, it is replaced.
+ // The file is opened with ReadWrite access and cannot be opened by another
+ // application until it has been closed. An IOException is thrown if the
+ // directory specified doesn't exist.
+ //
+ // Your application must have Create, Read, and Write permissions to
+ // the file.
+ //
+ public static FileStream Create(String path, int bufferSize) {
+ return new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize);
+ }
+
+ public static FileStream Create(String path, int bufferSize, FileOptions options) {
+ return new FileStream(path, FileMode.Create, FileAccess.ReadWrite,
+ FileShare.None, bufferSize, options);
+ }
+
+#if FEATURE_MACL
+ public static FileStream Create(String path, int bufferSize, FileOptions options, FileSecurity fileSecurity) {
+ return new FileStream(path, FileMode.Create, FileSystemRights.Read | FileSystemRights.Write,
+ FileShare.None, bufferSize, options, fileSecurity);
+ }
+#endif
+
+ // Deletes a file. The file specified by the designated path is deleted.
+ // If the file does not exist, Delete succeeds without throwing
+ // an exception.
+ //
+ // On NT, Delete will fail for a file that is open for normal I/O
+ // or a file that is memory mapped.
+ //
+ // Your application must have Delete permission to the target file.
+ //
+ [System.Security.SecuritySafeCritical]
+ public static void Delete(String path) {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ InternalDelete(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeDelete(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ InternalDelete(path, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void InternalDelete(String path, bool checkHost)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, path, fullPath);
+ state.EnsureState();
+ }
+#else
+ // For security check, path should be resolved to an absolute path.
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false);
+
+#endif
+ bool r = Win32Native.DeleteFile(fullPath);
+ if (!r) {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr==Win32Native.ERROR_FILE_NOT_FOUND)
+ return;
+ else
+ __Error.WinIOError(hr, fullPath);
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Decrypt(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, fullPath, false, false);
+
+ bool r = Win32Native.DecryptFile(fullPath, 0);
+ if (!r) {
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == Win32Native.ERROR_ACCESS_DENIED) {
+ // Check to see if the file system is not NTFS. If so,
+ // throw a different exception.
+ DriveInfo di = new DriveInfo(Path.GetPathRoot(fullPath));
+ if (!String.Equals("NTFS", di.DriveFormat))
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));
+ }
+ __Error.WinIOError(errorCode, fullPath);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Encrypt(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read | FileIOPermissionAccess.Write, fullPath, false, false);
+
+ bool r = Win32Native.EncryptFile(fullPath);
+ if (!r) {
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == Win32Native.ERROR_ACCESS_DENIED) {
+ // Check to see if the file system is not NTFS. If so,
+ // throw a different exception.
+ DriveInfo di = new DriveInfo(Path.GetPathRoot(fullPath));
+ if (!String.Equals("NTFS", di.DriveFormat))
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_EncryptionNeedsNTFS"));
+ }
+ __Error.WinIOError(errorCode, fullPath);
+ }
+ }
+
+ // Tests if a file exists. The result is true if the file
+ // given by the specified path exists; otherwise, the result is
+ // false. Note that if path describes a directory,
+ // Exists will return true.
+ //
+ // Your application must have Read permission for the target directory.
+ //
+ [System.Security.SecuritySafeCritical]
+ public static bool Exists(String path)
+ {
+ return InternalExistsHelper(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool UnsafeExists(String path)
+ {
+ return InternalExistsHelper(path, false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static bool InternalExistsHelper(String path, bool checkHost)
+ {
+ try
+ {
+ if (path == null)
+ return false;
+ if (path.Length == 0)
+ return false;
+
+ path = Path.GetFullPathInternal(path);
+ // After normalizing, check whether path ends in directory separator.
+ // Otherwise, FillAttributeInfo removes it and we may return a false positive.
+ // GetFullPathInternal should never return null
+ Contract.Assert(path != null, "File.Exists: GetFullPathInternal returned null");
+ if (path.Length > 0 && Path.IsDirectorySeparator(path[path.Length - 1]))
+ {
+ return false;
+ }
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, path);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, path, false, false);
+#endif
+
+ return InternalExists(path);
+ }
+ catch (ArgumentException) { }
+ catch (NotSupportedException) { } // Security can throw this on ":"
+ catch (SecurityException) { }
+ catch (IOException) { }
+ catch (UnauthorizedAccessException) { }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool InternalExists(String path) {
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = FillAttributeInfo(path, ref data, false, true);
+
+ return (dataInitialised == 0) && (data.fileAttributes != -1)
+ && ((data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0);
+ }
+
+ public static FileStream Open(String path, FileMode mode) {
+ return Open(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.None);
+ }
+
+ public static FileStream Open(String path, FileMode mode, FileAccess access) {
+ return Open(path,mode, access, FileShare.None);
+ }
+
+ public static FileStream Open(String path, FileMode mode, FileAccess access, FileShare share) {
+ return new FileStream(path, mode, access, share);
+ }
+
+ public static void SetCreationTime(String path, DateTime creationTime)
+ {
+ SetCreationTimeUtc(path, creationTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetCreationTimeUtc(String path, DateTime creationTimeUtc)
+ {
+ SafeFileHandle handle;
+ using(OpenFile(path, FileAccess.Write, out handle)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(creationTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, &fileTime, null, null);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static DateTime GetCreationTime(String path)
+ {
+ return InternalGetCreationTimeUtc(path, true).ToLocalTime();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static DateTime GetCreationTimeUtc(String path)
+ {
+ return InternalGetCreationTimeUtc(path, false); // this API isn't exposed in Silverlight
+ }
+
+ [System.Security.SecurityCritical]
+ private static DateTime InternalGetCreationTimeUtc(String path, bool checkHost)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
+#endif
+
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false);
+ if (dataInitialised != 0)
+ __Error.WinIOError(dataInitialised, fullPath);
+
+ long dt = ((long)(data.ftCreationTimeHigh) << 32) | ((long)data.ftCreationTimeLow);
+ return DateTime.FromFileTimeUtc(dt);
+ }
+
+ public static void SetLastAccessTime(String path, DateTime lastAccessTime)
+ {
+ SetLastAccessTimeUtc(path, lastAccessTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetLastAccessTimeUtc(String path, DateTime lastAccessTimeUtc)
+ {
+ SafeFileHandle handle;
+ using(OpenFile(path, FileAccess.Write, out handle)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastAccessTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, null, &fileTime, null);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static DateTime GetLastAccessTime(String path)
+ {
+ return InternalGetLastAccessTimeUtc(path, true).ToLocalTime();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static DateTime GetLastAccessTimeUtc(String path)
+ {
+ return InternalGetLastAccessTimeUtc(path, false); // this API isn't exposed in Silverlight
+ }
+
+ [System.Security.SecurityCritical]
+ private static DateTime InternalGetLastAccessTimeUtc(String path, bool checkHost)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
+#endif
+
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false);
+ if (dataInitialised != 0)
+ __Error.WinIOError(dataInitialised, fullPath);
+
+ long dt = ((long)(data.ftLastAccessTimeHigh) << 32) | ((long)data.ftLastAccessTimeLow);
+ return DateTime.FromFileTimeUtc(dt);
+ }
+
+ public static void SetLastWriteTime(String path, DateTime lastWriteTime)
+ {
+ SetLastWriteTimeUtc(path, lastWriteTime.ToUniversalTime());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static void SetLastWriteTimeUtc(String path, DateTime lastWriteTimeUtc)
+ {
+ SafeFileHandle handle;
+ using(OpenFile(path, FileAccess.Write, out handle)) {
+ Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastWriteTimeUtc.ToFileTimeUtc());
+ bool r = Win32Native.SetFileTime(handle, null, null, &fileTime);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ __Error.WinIOError(errorCode, path);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static DateTime GetLastWriteTime(String path)
+ {
+ return InternalGetLastWriteTimeUtc(path, true).ToLocalTime();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static DateTime GetLastWriteTimeUtc(String path)
+ {
+ return InternalGetLastWriteTimeUtc(path, false); // this API isn't exposed in Silverlight
+ }
+
+ [System.Security.SecurityCritical]
+ private static DateTime InternalGetLastWriteTimeUtc(String path, bool checkHost)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
+#endif
+
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = FillAttributeInfo(fullPath, ref data, false, false);
+ if (dataInitialised != 0)
+ __Error.WinIOError(dataInitialised, fullPath);
+
+ long dt = ((long)data.ftLastWriteTimeHigh << 32) | ((long)data.ftLastWriteTimeLow);
+ return DateTime.FromFileTimeUtc(dt);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static FileAttributes GetAttributes(String path)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, path, fullPath);
+ state.EnsureState();
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
+#endif
+
+ Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ int dataInitialised = FillAttributeInfo(fullPath, ref data, false, true);
+ if (dataInitialised != 0)
+ __Error.WinIOError(dataInitialised, fullPath);
+
+ return (FileAttributes) data.fileAttributes;
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public static void SetAttributes(String path, FileAttributes fileAttributes)
+ {
+ String fullPath = Path.GetFullPathInternal(path);
+#if !FEATURE_CORECLR
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullPath, false, false);
+#endif
+ bool r = Win32Native.SetFileAttributes(fullPath, (int) fileAttributes);
+ if (!r) {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr==ERROR_INVALID_PARAMETER)
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileAttrs"));
+ __Error.WinIOError(hr, fullPath);
+ }
+ }
+
+#if FEATURE_MACL
+ public static FileSecurity GetAccessControl(String path)
+ {
+ return GetAccessControl(path, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ public static FileSecurity GetAccessControl(String path, AccessControlSections includeSections)
+ {
+ // Appropriate security check should be done for us by FileSecurity.
+ return new FileSecurity(path, includeSections);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void SetAccessControl(String path, FileSecurity fileSecurity)
+ {
+ if (fileSecurity == null)
+ throw new ArgumentNullException("fileSecurity");
+ Contract.EndContractBlock();
+
+ String fullPath = Path.GetFullPathInternal(path);
+ // Appropriate security check should be done for us by FileSecurity.
+ fileSecurity.Persist(fullPath);
+ }
+#endif
+
+ public static FileStream OpenRead(String path) {
+ return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
+ }
+
+
+ public static FileStream OpenWrite(String path) {
+ return new FileStream(path, FileMode.OpenOrCreate,
+ FileAccess.Write, FileShare.None);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ReadAllText(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ return InternalReadAllText(path, Encoding.UTF8, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String ReadAllText(String path, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ return InternalReadAllText(path, encoding, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String UnsafeReadAllText(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ return InternalReadAllText(path, Encoding.UTF8, false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static String InternalReadAllText(String path, Encoding encoding, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(encoding != null);
+ Contract.Requires(path.Length > 0);
+
+ using (StreamReader sr = new StreamReader(path, encoding, true, StreamReader.DefaultBufferSize, checkHost))
+ return sr.ReadToEnd();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void WriteAllText(String path, String contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void WriteAllText(String path, String contents, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllText(path, contents, encoding, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeWriteAllText(String path, String contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllText(path, contents, StreamWriter.UTF8NoBOM, false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static void InternalWriteAllText(String path, String contents, Encoding encoding, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(encoding != null);
+ Contract.Requires(path.Length > 0);
+
+ using (StreamWriter sw = new StreamWriter(path, false, encoding, StreamWriter.DefaultBufferSize, checkHost))
+ sw.Write(contents);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static byte[] ReadAllBytes(String path)
+ {
+ return InternalReadAllBytes(path, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static byte[] UnsafeReadAllBytes(String path)
+ {
+ return InternalReadAllBytes(path, false);
+ }
+
+
+ [System.Security.SecurityCritical]
+ private static byte[] InternalReadAllBytes(String path, bool checkHost)
+ {
+ byte[] bytes;
+ using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read,
+ FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, checkHost)) {
+ // Do a blocking read
+ int index = 0;
+ long fileLength = fs.Length;
+ if (fileLength > Int32.MaxValue)
+ throw new IOException(Environment.GetResourceString("IO.IO_FileTooLong2GB"));
+ int count = (int) fileLength;
+ bytes = new byte[count];
+ while(count > 0) {
+ int n = fs.Read(bytes, index, count);
+ if (n == 0)
+ __Error.EndOfFile();
+ index += n;
+ count -= n;
+ }
+ }
+ return bytes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void WriteAllBytes(String path, byte[] bytes)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ if (bytes == null)
+ throw new ArgumentNullException("bytes");
+ Contract.EndContractBlock();
+
+ InternalWriteAllBytes(path, bytes, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeWriteAllBytes(String path, byte[] bytes)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ if (bytes == null)
+ throw new ArgumentNullException("bytes");
+ Contract.EndContractBlock();
+
+ InternalWriteAllBytes(path, bytes, false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static void InternalWriteAllBytes(String path, byte[] bytes, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(path.Length != 0);
+ Contract.Requires(bytes != null);
+
+ using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read,
+ FileStream.DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, checkHost))
+ {
+ fs.Write(bytes, 0, bytes.Length);
+ }
+ }
+
+ public static String[] ReadAllLines(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ return InternalReadAllLines(path, Encoding.UTF8);
+ }
+
+ public static String[] ReadAllLines(String path, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ return InternalReadAllLines(path, encoding);
+ }
+
+ private static String[] InternalReadAllLines(String path, Encoding encoding)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(encoding != null);
+ Contract.Requires(path.Length != 0);
+
+ String line;
+ List<String> lines = new List<String>();
+
+ using (StreamReader sr = new StreamReader(path, encoding))
+ while ((line = sr.ReadLine()) != null)
+ lines.Add(line);
+
+ return lines.ToArray();
+ }
+
+ public static IEnumerable<String> ReadLines(String path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "path");
+ Contract.EndContractBlock();
+
+ return ReadLinesIterator.CreateIterator(path, Encoding.UTF8);
+ }
+
+ public static IEnumerable<String> ReadLines(String path, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "path");
+ Contract.EndContractBlock();
+
+ return ReadLinesIterator.CreateIterator(path, encoding);
+ }
+
+ public static void WriteAllLines(String path, String[] contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, false, StreamWriter.UTF8NoBOM), contents);
+ }
+
+ public static void WriteAllLines(String path, String[] contents, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, false, encoding), contents);
+ }
+
+ public static void WriteAllLines(String path, IEnumerable<String> contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, false, StreamWriter.UTF8NoBOM), contents);
+ }
+
+ public static void WriteAllLines(String path, IEnumerable<String> contents, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, false, encoding), contents);
+ }
+
+ private static void InternalWriteAllLines(TextWriter writer, IEnumerable<String> contents)
+ {
+ Contract.Requires(writer != null);
+ Contract.Requires(contents != null);
+
+ using (writer)
+ {
+ foreach (String line in contents)
+ {
+ writer.WriteLine(line);
+ }
+ }
+ }
+
+ public static void AppendAllText(String path, String contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalAppendAllText(path, contents, StreamWriter.UTF8NoBOM);
+ }
+
+ public static void AppendAllText(String path, String contents, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalAppendAllText(path, contents, encoding);
+ }
+
+ private static void InternalAppendAllText(String path, String contents, Encoding encoding)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(encoding != null);
+ Contract.Requires(path.Length > 0);
+
+ using (StreamWriter sw = new StreamWriter(path, true, encoding))
+ sw.Write(contents);
+ }
+
+ public static void AppendAllLines(String path, IEnumerable<String> contents)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, true, StreamWriter.UTF8NoBOM), contents);
+ }
+
+ public static void AppendAllLines(String path, IEnumerable<String> contents, Encoding encoding)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (contents == null)
+ throw new ArgumentNullException("contents");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+ InternalWriteAllLines(new StreamWriter(path, true, encoding), contents);
+ }
+
+ // Moves a specified file to a new location and potentially a new file name.
+ // This method does work across volumes.
+ //
+ // The caller must have certain FileIOPermissions. The caller must
+ // have Read and Write permission to
+ // sourceFileName and Write
+ // permissions to destFileName.
+ //
+ [System.Security.SecuritySafeCritical]
+ public static void Move(String sourceFileName, String destFileName) {
+ InternalMove(sourceFileName, destFileName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static void UnsafeMove(String sourceFileName, String destFileName) {
+ InternalMove(sourceFileName, destFileName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static void InternalMove(String sourceFileName, String destFileName, bool checkHost) {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (sourceFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName");
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ String fullSourceFileName = Path.GetFullPathInternal(sourceFileName);
+ String fullDestFileName = Path.GetFullPathInternal(destFileName);
+
+#if FEATURE_CORECLR
+ if (checkHost) {
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, sourceFileName, fullSourceFileName);
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName);
+ sourceState.EnsureState();
+ destState.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, fullSourceFileName, false, false);
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
+#endif
+
+ if (!InternalExists(fullSourceFileName))
+ __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, fullSourceFileName);
+
+ if (!Win32Native.MoveFile(fullSourceFileName, fullDestFileName))
+ {
+ __Error.WinIOError();
+ }
+ }
+
+
+ public static void Replace(String sourceFileName, String destinationFileName, String destinationBackupFileName)
+ {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName");
+ if (destinationFileName == null)
+ throw new ArgumentNullException("destinationFileName");
+ Contract.EndContractBlock();
+
+ InternalReplace(sourceFileName, destinationFileName, destinationBackupFileName, false);
+ }
+
+ public static void Replace(String sourceFileName, String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors)
+ {
+ if (sourceFileName == null)
+ throw new ArgumentNullException("sourceFileName");
+ if (destinationFileName == null)
+ throw new ArgumentNullException("destinationFileName");
+ Contract.EndContractBlock();
+
+ InternalReplace(sourceFileName, destinationFileName, destinationBackupFileName, ignoreMetadataErrors);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static void InternalReplace(String sourceFileName, String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors)
+ {
+ Contract.Requires(sourceFileName != null);
+ Contract.Requires(destinationFileName != null);
+
+ // Write permission to all three files, read permission to source
+ // and dest.
+ String fullSrcPath = Path.GetFullPathInternal(sourceFileName);
+ String fullDestPath = Path.GetFullPathInternal(destinationFileName);
+ String fullBackupPath = null;
+ if (destinationBackupFileName != null)
+ fullBackupPath = Path.GetFullPathInternal(destinationBackupFileName);
+
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, sourceFileName, fullSrcPath);
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, destinationFileName, fullDestPath);
+ FileSecurityState backupState = new FileSecurityState(FileSecurityStateAccess.Read | FileSecurityStateAccess.Write, destinationBackupFileName, fullBackupPath);
+ sourceState.EnsureState();
+ 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();
+#endif
+
+ int flags = Win32Native.REPLACEFILE_WRITE_THROUGH;
+ if (ignoreMetadataErrors)
+ flags |= Win32Native.REPLACEFILE_IGNORE_MERGE_ERRORS;
+
+ bool r = Win32Native.ReplaceFile(fullDestPath, fullSrcPath, fullBackupPath, flags, IntPtr.Zero, IntPtr.Zero);
+ if (!r)
+ __Error.WinIOError();
+ }
+
+
+ // Returns 0 on success, otherwise a Win32 error code. Note that
+ // classes should use -1 as the uninitialized state for dataInitialized.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static int FillAttributeInfo(String path, ref Win32Native.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound)
+ {
+ int dataInitialised = 0;
+ if (tryagain) // someone has a handle to the file open, or other error
+ {
+ Win32Native.WIN32_FIND_DATA findData;
+ findData = new Win32Native.WIN32_FIND_DATA ();
+
+ // Remove trialing slash since this can cause grief to FindFirstFile. You will get an invalid argument error
+ String tempPath = path.TrimEnd(new char [] {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar});
+
+ // For floppy drives, normally the OS will pop up a dialog saying
+ // there is no disk in drive A:, please insert one. We don't want that.
+ // SetErrorMode will let us disable this, but we should set the error
+ // mode back, since this may have wide-ranging effects.
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ bool error = false;
+ SafeFindHandle handle = Win32Native.FindFirstFile(tempPath,findData);
+ try {
+ if (handle.IsInvalid) {
+ error = true;
+ dataInitialised = Marshal.GetLastWin32Error();
+
+ if (dataInitialised == Win32Native.ERROR_FILE_NOT_FOUND ||
+ dataInitialised == Win32Native.ERROR_PATH_NOT_FOUND ||
+ dataInitialised == Win32Native.ERROR_NOT_READY) // floppy device not ready
+ {
+ if (!returnErrorOnNotFound) {
+ // Return default value for backward compatibility
+ dataInitialised = 0;
+ data.fileAttributes = -1;
+ }
+ }
+ return dataInitialised;
+ }
+ }
+ finally {
+ // Close the Win32 handle
+ try {
+ handle.Close();
+ }
+ catch {
+ // if we're already returning an error, don't throw another one.
+ if (!error) {
+ Contract.Assert(false, "File::FillAttributeInfo - FindClose failed!");
+ __Error.WinIOError();
+ }
+ }
+ }
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+
+ // Copy the information to data
+ data.PopulateFrom(findData);
+ }
+ else
+ {
+
+ // For floppy drives, normally the OS will pop up a dialog saying
+ // there is no disk in drive A:, please insert one. We don't want that.
+ // SetErrorMode will let us disable this, but we should set the error
+ // mode back, since this may have wide-ranging effects.
+ bool success = false;
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ success = Win32Native.GetFileAttributesEx(path, GetFileExInfoStandard, ref data);
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+
+ if (!success) {
+ dataInitialised = Marshal.GetLastWin32Error();
+ if (dataInitialised != Win32Native.ERROR_FILE_NOT_FOUND &&
+ dataInitialised != Win32Native.ERROR_PATH_NOT_FOUND &&
+ dataInitialised != Win32Native.ERROR_NOT_READY) // floppy device not ready
+ {
+ // In case someone latched onto the file. Take the perf hit only for failure
+ return FillAttributeInfo(path, ref data, true, returnErrorOnNotFound);
+ }
+ else {
+ if (!returnErrorOnNotFound) {
+ // Return default value for backward compbatibility
+ dataInitialised = 0;
+ data.fileAttributes = -1;
+ }
+ }
+ }
+ }
+
+ return dataInitialised;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static FileStream OpenFile(String path, FileAccess access, out SafeFileHandle handle)
+ {
+ FileStream fs = new FileStream(path, FileMode.Open, access, FileShare.ReadWrite, 1);
+ handle = fs.SafeFileHandle;
+
+ if (handle.IsInvalid) {
+ // Return a meaningful error, using the RELATIVE path to
+ // the file to avoid returning extra information to the caller.
+
+ // NT5 oddity - when trying to open "C:\" as a FileStream,
+ // we usually get ERROR_PATH_NOT_FOUND from the OS. We should
+ // probably be consistent w/ every other directory.
+ int hr = Marshal.GetLastWin32Error();
+ String FullPath = Path.GetFullPathInternal(path);
+ if (hr==__Error.ERROR_PATH_NOT_FOUND && FullPath.Equals(Directory.GetDirectoryRoot(FullPath)))
+ hr = __Error.ERROR_ACCESS_DENIED;
+
+
+ __Error.WinIOError(hr, path);
+ }
+ return fs;
+ }
+
+
+ // Defined in WinError.h
+ private const int ERROR_INVALID_PARAMETER = 87;
+ private const int ERROR_ACCESS_DENIED = 0x5;
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileAccess.cs b/src/mscorlib/src/System/IO/FileAccess.cs
new file mode 100644
index 0000000000..f708a284c1
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileAccess.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileAccess
+**
+**
+**
+**
+** Purpose: Enum describing whether you want read and/or write
+** permission to a file.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO {
+ // Contains constants for specifying the access you want for a file.
+ // You can have Read, Write or ReadWrite access.
+ //
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileAccess
+ {
+ // Specifies read access to the file. Data can be read from the file and
+ // the file pointer can be moved. Combine with WRITE for read-write access.
+ Read = 1,
+
+ // Specifies write access to the file. Data can be written to the file and
+ // the file pointer can be moved. Combine with READ for read-write access.
+ Write = 2,
+
+ // Specifies read and write access to the file. Data can be written to the
+ // file and the file pointer can be moved. Data can also be read from the
+ // file.
+ ReadWrite = 3,
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileAttributes.cs b/src/mscorlib/src/System/IO/FileAttributes.cs
new file mode 100644
index 0000000000..19d5f227d7
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileAttributes.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: File attribute flags corresponding to NT's flags.
+**
+**
+===========================================================*/
+using System;
+
+namespace System.IO {
+ // File attributes for use with the FileEnumerator class.
+ // These constants correspond to the constants in WinNT.h.
+ //
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileAttributes
+ {
+ // From WinNT.h (FILE_ATTRIBUTE_XXX)
+ ReadOnly = 0x1,
+ Hidden = 0x2,
+ System = 0x4,
+ Directory = 0x10,
+ Archive = 0x20,
+ Device = 0x40,
+ Normal = 0x80,
+ Temporary = 0x100,
+ SparseFile = 0x200,
+ ReparsePoint = 0x400,
+ Compressed = 0x800,
+ Offline = 0x1000,
+ NotContentIndexed = 0x2000,
+ Encrypted = 0x4000,
+
+#if !FEATURE_CORECLR
+#if FEATURE_COMINTEROP
+ [System.Runtime.InteropServices.ComVisible(false)]
+#endif // FEATURE_COMINTEROP
+ IntegrityStream = 0x8000,
+
+#if FEATURE_COMINTEROP
+ [System.Runtime.InteropServices.ComVisible(false)]
+#endif // FEATURE_COMINTEROP
+ NoScrubData = 0x20000,
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileInfo.cs b/src/mscorlib/src/System/IO/FileInfo.cs
new file mode 100644
index 0000000000..3ab1a5122e
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileInfo.cs
@@ -0,0 +1,431 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of methods for manipulating Files.
+**
+** April 09,2000 (some design refactorization)
+**
+===========================================================*/
+
+using System;
+#if FEATURE_MACL
+using System.Security.AccessControl;
+#endif
+using System.Security.Permissions;
+using PermissionSet = System.Security.PermissionSet;
+using Win32Native = Microsoft.Win32.Win32Native;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Runtime.Serialization;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ // Class for creating FileStream objects, and some basic file management
+ // routines such as Delete, etc.
+ [Serializable]
+ [ComVisible(true)]
+ public sealed class FileInfo: FileSystemInfo
+ {
+ private String _name;
+
+#if FEATURE_CORECLR
+ // Migrating InheritanceDemands requires this default ctor, so we can annotate it.
+#if FEATURE_CORESYSTEM
+ [System.Security.SecurityCritical]
+#else
+ [System.Security.SecuritySafeCritical]
+#endif //FEATURE_CORESYSTEM
+ private FileInfo(){}
+
+ [System.Security.SecurityCritical]
+ public static FileInfo UnsafeCreateFileInfo(String fileName)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ Contract.EndContractBlock();
+
+ FileInfo fi = new FileInfo();
+ fi.Init(fileName, false);
+ return fi;
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical]
+ public FileInfo(String fileName)
+ {
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ Contract.EndContractBlock();
+
+ Init(fileName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ private void Init(String fileName, bool checkHost)
+ {
+ OriginalPath = fileName;
+ // Must fully qualify the path for the security check
+ String fullPath = Path.GetFullPathInternal(fileName);
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, fileName, fullPath);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Read, fullPath, false, false);
+#endif
+
+ _name = Path.GetFileName(fileName);
+ FullPath = fullPath;
+ DisplayPath = GetDisplayPath(fileName);
+ }
+
+ private String GetDisplayPath(String originalPath)
+ {
+#if FEATURE_CORECLR
+ return Path.GetFileName(originalPath);
+#else
+ return originalPath;
+#endif
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FileInfo(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand();
+#endif
+ _name = Path.GetFileName(OriginalPath);
+ DisplayPath = GetDisplayPath(OriginalPath);
+ }
+
+#if FEATURE_CORESYSTEM
+ [System.Security.SecuritySafeCritical]
+#endif //FEATURE_CORESYSTEM
+ internal FileInfo(String fullPath, bool ignoreThis)
+ {
+ Contract.Assert(Path.GetRootLength(fullPath) > 0, "fullPath must be fully qualified!");
+ _name = Path.GetFileName(fullPath);
+ OriginalPath = _name;
+ FullPath = fullPath;
+ DisplayPath = _name;
+ }
+
+ public override String Name {
+ get { return _name; }
+ }
+
+
+ public long Length {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_dataInitialised == -1)
+ Refresh();
+
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ __Error.WinIOError(_dataInitialised, DisplayPath);
+
+ if ((_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0)
+ __Error.WinIOError(Win32Native.ERROR_FILE_NOT_FOUND, DisplayPath);
+
+ return ((long)_data.fileSizeHigh) << 32 | ((long)_data.fileSizeLow & 0xFFFFFFFFL);
+ }
+ }
+
+ /* Returns the name of the directory that the file is in */
+ public String DirectoryName
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ String directoryName = Path.GetDirectoryName(FullPath);
+ if (directoryName != null)
+ {
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, DisplayPath, FullPath);
+ state.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { directoryName }, false, false).Demand();
+#endif
+ }
+ return directoryName;
+ }
+ }
+
+ /* Creates an instance of the the parent directory */
+ public DirectoryInfo Directory
+ {
+ get
+ {
+ String dirName = DirectoryName;
+ if (dirName == null)
+ return null;
+ return new DirectoryInfo(dirName);
+ }
+ }
+
+ public bool IsReadOnly {
+ get {
+ return (Attributes & FileAttributes.ReadOnly) != 0;
+ }
+ set {
+ if (value)
+ Attributes |= FileAttributes.ReadOnly;
+ else
+ Attributes &= ~FileAttributes.ReadOnly;
+ }
+ }
+
+#if FEATURE_MACL
+ public FileSecurity GetAccessControl()
+ {
+ return File.GetAccessControl(FullPath, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ public FileSecurity GetAccessControl(AccessControlSections includeSections)
+ {
+ return File.GetAccessControl(FullPath, includeSections);
+ }
+
+ public void SetAccessControl(FileSecurity fileSecurity)
+ {
+ File.SetAccessControl(FullPath, fileSecurity);
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StreamReader OpenText()
+ {
+ return new StreamReader(FullPath, Encoding.UTF8, true, StreamReader.DefaultBufferSize, false);
+ }
+
+ public StreamWriter CreateText()
+ {
+ return new StreamWriter(FullPath,false);
+ }
+
+ public StreamWriter AppendText()
+ {
+ return new StreamWriter(FullPath,true);
+ }
+
+
+ // Copies an existing file to a new file. An exception is raised if the
+ // destination file already exists. Use the
+ // Copy(String, String, boolean) method to allow
+ // overwriting an existing file.
+ //
+ // The caller must have certain FileIOPermissions. The caller must have
+ // Read permission to sourceFileName
+ // and Write permissions to destFileName.
+ //
+ public FileInfo CopyTo(String destFileName) {
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ destFileName = File.InternalCopy(FullPath, destFileName, false, true);
+ return new FileInfo(destFileName, false);
+ }
+
+
+ // Copies an existing file to a new file. If overwrite is
+ // false, then an IOException is thrown if the destination file
+ // already exists. If overwrite is true, the file is
+ // overwritten.
+ //
+ // The caller must have certain FileIOPermissions. The caller must have
+ // Read permission to sourceFileName and Create
+ // and Write permissions to destFileName.
+ //
+ public FileInfo CopyTo(String destFileName, bool overwrite) {
+ if (destFileName == null)
+ throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
+ if (destFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ destFileName = File.InternalCopy(FullPath, destFileName, overwrite, true);
+ return new FileInfo(destFileName, false);
+ }
+
+ public FileStream Create() {
+ return File.Create(FullPath);
+ }
+
+ // Deletes a file. The file specified by the designated path is deleted.
+ // If the file does not exist, Delete succeeds without throwing
+ // an exception.
+ //
+ // On NT, Delete will fail for a file that is open for normal I/O
+ // or a file that is memory mapped. On Win95, the file will be
+ // deleted irregardless of whether the file is being used.
+ //
+ // Your application must have Delete permission to the target file.
+ //
+ [System.Security.SecuritySafeCritical]
+ public override void Delete()
+ {
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, DisplayPath, FullPath);
+ state.EnsureState();
+#else
+ // For security check, path should be resolved to an absolute path.
+ new FileIOPermission(FileIOPermissionAccess.Write, new String[] { FullPath }, false, false).Demand();
+#endif
+
+ bool r = Win32Native.DeleteFile(FullPath);
+ if (!r) {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr==Win32Native.ERROR_FILE_NOT_FOUND)
+ return;
+ else
+ __Error.WinIOError(hr, DisplayPath);
+ }
+ }
+
+ [ComVisible(false)]
+ public void Decrypt()
+ {
+ File.Decrypt(FullPath);
+ }
+
+ [ComVisible(false)]
+ public void Encrypt()
+ {
+ File.Encrypt(FullPath);
+ }
+
+ // Tests if the given file exists. The result is true if the file
+ // given by the specified path exists; otherwise, the result is
+ // false.
+ //
+ // Your application must have Read permission for the target directory.
+ public override bool Exists {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ try {
+ if (_dataInitialised == -1)
+ Refresh();
+ if (_dataInitialised != 0) {
+ // Refresh was unable to initialise the data.
+ // We should normally be throwing an exception here,
+ // but Exists is supposed to return true or false.
+ return false;
+ }
+ return (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+ }
+
+
+
+
+ // User must explicitly specify opening a new file or appending to one.
+ public FileStream Open(FileMode mode) {
+ return Open(mode, FileAccess.ReadWrite, FileShare.None);
+ }
+
+ public FileStream Open(FileMode mode, FileAccess access) {
+ return Open(mode, access, FileShare.None);
+ }
+
+ public FileStream Open(FileMode mode, FileAccess access, FileShare share) {
+ return new FileStream(FullPath, mode, access, share);
+ }
+
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ public FileStream OpenRead()
+ {
+ return new FileStream(FullPath, FileMode.Open, FileAccess.Read,
+ FileShare.Read, 4096, false);
+ }
+
+
+ public FileStream OpenWrite() {
+ return new FileStream(FullPath, FileMode.OpenOrCreate,
+ FileAccess.Write, FileShare.None);
+ }
+
+
+
+
+
+
+ // Moves a given file to a new location and potentially a new file name.
+ // This method does work across volumes.
+ //
+ // The caller must have certain FileIOPermissions. The caller must
+ // have Read and Write permission to
+ // sourceFileName and Write
+ // permissions to destFileName.
+ //
+ [System.Security.SecuritySafeCritical]
+ public void MoveTo(String destFileName) {
+ if (destFileName==null)
+ throw new ArgumentNullException("destFileName");
+ if (destFileName.Length==0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
+ Contract.EndContractBlock();
+
+ String fullDestFileName = Path.GetFullPathInternal(destFileName);
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Write | FileSecurityStateAccess.Read, DisplayPath, FullPath);
+ FileSecurityState destState = new FileSecurityState(FileSecurityStateAccess.Write, destFileName, fullDestFileName);
+ sourceState.EnsureState();
+ destState.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { FullPath }, false, false).Demand();
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, fullDestFileName, false, false);
+#endif
+
+ if (!Win32Native.MoveFile(FullPath, fullDestFileName))
+ __Error.WinIOError();
+ FullPath = fullDestFileName;
+ OriginalPath = destFileName;
+ _name = Path.GetFileName(fullDestFileName);
+ DisplayPath = GetDisplayPath(destFileName);
+ // Flush any cached information about the file.
+ _dataInitialised = -1;
+ }
+
+ [ComVisible(false)]
+ public FileInfo Replace(String destinationFileName, String destinationBackupFileName)
+ {
+ return Replace(destinationFileName, destinationBackupFileName, false);
+ }
+
+ [ComVisible(false)]
+ public FileInfo Replace(String destinationFileName, String destinationBackupFileName, bool ignoreMetadataErrors)
+ {
+ File.Replace(FullPath, destinationFileName, destinationBackupFileName, ignoreMetadataErrors);
+ return new FileInfo(destinationFileName);
+ }
+
+ // Returns the display path
+ public override String ToString()
+ {
+ return DisplayPath;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileLoadException.cs b/src/mscorlib/src/System/IO/FileLoadException.cs
new file mode 100644
index 0000000000..fabe2613c3
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileLoadException.cs
@@ -0,0 +1,191 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Exception for failure to load a file that was successfully found.
+**
+**
+===========================================================*/
+
+using System;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.Versioning;
+using SecurityException = System.Security.SecurityException;
+
+namespace System.IO {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class FileLoadException : IOException {
+
+ private String _fileName; // the name of the file we could not load.
+ private String _fusionLog; // fusion log (when applicable)
+
+ public FileLoadException()
+ : base(Environment.GetResourceString("IO.FileLoad")) {
+ SetErrorCode(__HResults.COR_E_FILELOAD);
+ }
+
+ public FileLoadException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_FILELOAD);
+ }
+
+ public FileLoadException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_FILELOAD);
+ }
+
+ public FileLoadException(String message, String fileName) : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_FILELOAD);
+ _fileName = fileName;
+ }
+
+ public FileLoadException(String message, String fileName, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_FILELOAD);
+ _fileName = fileName;
+ }
+
+ public override String Message
+ {
+ get {
+ SetMessageField();
+ return _message;
+ }
+ }
+
+ private void SetMessageField()
+ {
+ if (_message == null)
+ _message = FormatFileLoadExceptionMessage(_fileName, HResult);
+ }
+
+ public String FileName {
+ get { return _fileName; }
+ }
+
+ public override String ToString()
+ {
+ String s = GetType().FullName + ": " + Message;
+
+ if (_fileName != null && _fileName.Length != 0)
+ s += Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", _fileName);
+
+ if (InnerException != null)
+ s = s + " ---> " + InnerException.ToString();
+
+ if (StackTrace != null)
+ s += Environment.NewLine + StackTrace;
+
+#if FEATURE_FUSION
+ try
+ {
+ if(FusionLog!=null)
+ {
+ if (s==null)
+ s=" ";
+ s+=Environment.NewLine;
+ s+=Environment.NewLine;
+ s+=FusionLog;
+ }
+ }
+ catch(SecurityException)
+ {
+
+ }
+#endif // FEATURE_FUSION
+
+ return s;
+ }
+
+ protected FileLoadException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ // Base class constructor will check info != null.
+
+ _fileName = info.GetString("FileLoad_FileName");
+
+#if FEATURE_FUSION
+ try
+ {
+ _fusionLog = info.GetString("FileLoad_FusionLog");
+ }
+ catch
+ {
+ _fusionLog = null;
+ }
+#endif
+ }
+
+ private FileLoadException(String fileName, String fusionLog,int hResult)
+ : base(null)
+ {
+ SetErrorCode(hResult);
+ _fileName = fileName;
+ _fusionLog=fusionLog;
+ SetMessageField();
+ }
+
+#if FEATURE_FUSION
+ public String FusionLog {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get { return _fusionLog; }
+ }
+#endif // FEATURE_FUSION
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ // Serialize data for our base classes. base will verify info != null.
+ base.GetObjectData(info, context);
+
+ // Serialize data for this class
+ info.AddValue("FileLoad_FileName", _fileName, typeof(String));
+
+#if FEATURE_FUSION
+ try
+ {
+ info.AddValue("FileLoad_FusionLog", FusionLog, typeof(String));
+ }
+ catch (SecurityException)
+ {
+ }
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static String FormatFileLoadExceptionMessage(String fileName,
+ int hResult)
+ {
+ string format = null;
+ GetFileLoadExceptionMessage(hResult, JitHelpers.GetStringHandleOnStack(ref format));
+
+ string message = null;
+ GetMessageForHR(hResult, JitHelpers.GetStringHandleOnStack(ref message));
+
+ return String.Format(CultureInfo.CurrentCulture, format, fileName, message);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetFileLoadExceptionMessage(int hResult, StringHandleOnStack retString);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetMessageForHR(int hresult, StringHandleOnStack retString);
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileMode.cs b/src/mscorlib/src/System/IO/FileMode.cs
new file mode 100644
index 0000000000..9b9c2024a7
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileMode.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileMode
+**
+**
+**
+**
+** Purpose: Enum describing whether to create a new file or
+** open an existing one.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO {
+ // Contains constants for specifying how the OS should open a file.
+ // These will control whether you overwrite a file, open an existing
+ // file, or some combination thereof.
+ //
+ // To append to a file, use Append (which maps to OpenOrCreate then we seek
+ // to the end of the file). To truncate a file or create it if it doesn't
+ // exist, use Create.
+ //
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileMode
+ {
+ // Creates a new file. An exception is raised if the file already exists.
+ CreateNew = 1,
+
+ // Creates a new file. If the file already exists, it is overwritten.
+ Create = 2,
+
+ // Opens an existing file. An exception is raised if the file does not exist.
+ Open = 3,
+
+ // Opens the file if it exists. Otherwise, creates a new file.
+ OpenOrCreate = 4,
+
+ // Opens an existing file. Once opened, the file is truncated so that its
+ // size is zero bytes. The calling process must open the file with at least
+ // WRITE access. An exception is raised if the file does not exist.
+ Truncate = 5,
+
+ // Opens the file if it exists and seeks to the end. Otherwise,
+ // creates a new file.
+ Append = 6,
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileNotFoundException.cs b/src/mscorlib/src/System/IO/FileNotFoundException.cs
new file mode 100644
index 0000000000..933e4fd94c
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileNotFoundException.cs
@@ -0,0 +1,170 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Exception for accessing a file that doesn't exist.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using SecurityException = System.Security.SecurityException;
+using System.Globalization;
+
+namespace System.IO {
+ // Thrown when trying to access a file that doesn't exist on disk.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class FileNotFoundException : IOException {
+
+ private String _fileName; // The name of the file that isn't found.
+ private String _fusionLog; // fusion log (when applicable)
+
+ public FileNotFoundException()
+ : base(Environment.GetResourceString("IO.FileNotFound")) {
+ SetErrorCode(__HResults.COR_E_FILENOTFOUND);
+ }
+
+ public FileNotFoundException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_FILENOTFOUND);
+ }
+
+ public FileNotFoundException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_FILENOTFOUND);
+ }
+
+ public FileNotFoundException(String message, String fileName) : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_FILENOTFOUND);
+ _fileName = fileName;
+ }
+
+ public FileNotFoundException(String message, String fileName, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_FILENOTFOUND);
+ _fileName = fileName;
+ }
+
+ public override String Message
+ {
+ get {
+ SetMessageField();
+ return _message;
+ }
+ }
+
+ private void SetMessageField()
+ {
+ if (_message == null) {
+ if ((_fileName == null) &&
+ (HResult == System.__HResults.COR_E_EXCEPTION))
+ _message = Environment.GetResourceString("IO.FileNotFound");
+
+ else if( _fileName != null)
+ _message = FileLoadException.FormatFileLoadExceptionMessage(_fileName, HResult);
+ }
+ }
+
+ public String FileName {
+ get { return _fileName; }
+ }
+
+ public override String ToString()
+ {
+ String s = GetType().FullName + ": " + Message;
+
+ if (_fileName != null && _fileName.Length != 0)
+ s += Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", _fileName);
+
+ if (InnerException != null)
+ s = s + " ---> " + InnerException.ToString();
+
+ if (StackTrace != null)
+ s += Environment.NewLine + StackTrace;
+
+#if FEATURE_FUSION
+ try
+ {
+ if(FusionLog!=null)
+ {
+ if (s==null)
+ s=" ";
+ s+=Environment.NewLine;
+ s+=Environment.NewLine;
+ s+=FusionLog;
+ }
+ }
+ catch(SecurityException)
+ {
+
+ }
+#endif
+ return s;
+
+ }
+
+ protected FileNotFoundException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ // Base class constructor will check info != null.
+
+ _fileName = info.GetString("FileNotFound_FileName");
+#if FEATURE_FUSION
+ try
+ {
+ _fusionLog = info.GetString("FileNotFound_FusionLog");
+ }
+ catch
+ {
+ _fusionLog = null;
+ }
+#endif
+ }
+
+ private FileNotFoundException(String fileName, String fusionLog,int hResult)
+ : base(null)
+ {
+ SetErrorCode(hResult);
+ _fileName = fileName;
+ _fusionLog=fusionLog;
+ SetMessageField();
+ }
+
+#if FEATURE_FUSION
+ public String FusionLog {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get { return _fusionLog; }
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ // Serialize data for our base classes. base will verify info != null.
+ base.GetObjectData(info, context);
+
+ // Serialize data for this class
+ info.AddValue("FileNotFound_FileName", _fileName, typeof(String));
+
+#if FEATURE_FUSION
+ try
+ {
+ info.AddValue("FileNotFound_FusionLog", FusionLog, typeof(String));
+ }
+ catch (SecurityException)
+ {
+ }
+#endif
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/IO/FileOptions.cs b/src/mscorlib/src/System/IO/FileOptions.cs
new file mode 100644
index 0000000000..ffd6ddad90
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileOptions.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileOptions
+**
+**
+**
+**
+** Purpose: Additional options to how to create a FileStream.
+** Exposes the more obscure CreateFile functionality.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.IO {
+ // Maps to FILE_FLAG_DELETE_ON_CLOSE and similar values from winbase.h.
+ // We didn't expose a number of these values because we didn't believe
+ // a number of them made sense in managed code, at least not yet.
+ [Serializable]
+ [Flags]
+ [ComVisible(true)]
+ public enum FileOptions
+ {
+ // NOTE: any change to FileOptions enum needs to be
+ // matched in the FileStream ctor for error validation
+ None = 0,
+ WriteThrough = unchecked((int)0x80000000),
+ Asynchronous = unchecked((int)0x40000000), // FILE_FLAG_OVERLAPPED
+ // NoBuffering = 0x20000000,
+ RandomAccess = 0x10000000,
+ DeleteOnClose = 0x04000000,
+ SequentialScan = 0x08000000,
+ // AllowPosix = 0x01000000, // FILE_FLAG_POSIX_SEMANTICS
+ // BackupOrRestore,
+ // DisallowReparsePoint = 0x00200000, // FILE_FLAG_OPEN_REPARSE_POINT
+ // NoRemoteRecall = 0x00100000, // FILE_FLAG_OPEN_NO_RECALL
+ // FirstPipeInstance = 0x00080000, // FILE_FLAG_FIRST_PIPE_INSTANCE
+ Encrypted = 0x00004000, // FILE_ATTRIBUTE_ENCRYPTED
+ }
+}
+
diff --git a/src/mscorlib/src/System/IO/FileSecurityState.cs b/src/mscorlib/src/System/IO/FileSecurityState.cs
new file mode 100644
index 0000000000..249848ac02
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileSecurityState.cs
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileSecurityState
+**
+**
+**
+**
+** Purpose: Determines whether file system access is safe
+**
+**
+===========================================================*/
+
+using System;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Security;
+using System.Security.Permissions;
+
+namespace System.IO
+{
+ [SecurityCritical]
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal class FileSecurityState : SecurityState
+ {
+#if !PLATFORM_UNIX
+ private static readonly char[] m_illegalCharacters = { '?', '*' };
+#endif // !PLATFORM_UNIX
+
+ private FileSecurityStateAccess m_access;
+ private String m_userPath;
+ private String m_canonicalizedPath;
+
+ // default ctor needed for security rule consistency
+ [SecurityCritical]
+ private FileSecurityState()
+ {
+ }
+
+ internal FileSecurityState(FileSecurityStateAccess access, String path)
+ {
+ if (path == null)
+ {
+ throw new ArgumentNullException("path");
+ }
+ VerifyAccess(access);
+ m_access = access;
+ m_userPath = path;
+ if (path.Equals(String.Empty, StringComparison.OrdinalIgnoreCase))
+ {
+ m_canonicalizedPath = String.Empty;
+ }
+ else
+ {
+ VerifyPath(path);
+ m_canonicalizedPath = System.IO.Path.GetFullPathInternal(path);
+ }
+ }
+
+ // slight perf savings for trusted internal callers
+ internal FileSecurityState(FileSecurityStateAccess access, String path, String canonicalizedPath)
+ {
+ VerifyAccess(access);
+ VerifyPath(path);
+ VerifyPath(canonicalizedPath);
+
+ m_access = access;
+ m_userPath = path;
+ m_canonicalizedPath = canonicalizedPath;
+ }
+
+ internal FileSecurityStateAccess Access
+ {
+ get
+ {
+ return m_access;
+ }
+ }
+
+ public String Path {
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ get
+ {
+ return m_canonicalizedPath;
+ }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override void EnsureState()
+ {
+ // this is the case for empty string machine name, etc
+ if (String.Empty.Equals(m_canonicalizedPath))
+ return;
+
+ if (!IsStateAvailable())
+ {
+ throw new SecurityException(Environment.GetResourceString("FileSecurityState_OperationNotPermitted", (m_userPath == null) ? String.Empty : m_userPath));
+ }
+ }
+
+ internal static FileSecurityStateAccess ToFileSecurityState(FileIOPermissionAccess access)
+ {
+ Contract.Requires((access & ~FileIOPermissionAccess.AllAccess) == 0);
+ return (FileSecurityStateAccess)access; // flags are identical; just cast
+ }
+
+ private static void VerifyAccess(FileSecurityStateAccess access)
+ {
+ if ((access & ~FileSecurityStateAccess.AllAccess) != 0)
+ throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("Arg_EnumIllegalVal"));
+ }
+
+ private static void VerifyPath(String path)
+ {
+ if (path != null)
+ {
+ path = path.Trim();
+
+#if !PLATFORM_UNIX
+ if (!PathInternal.IsDevice(path) && PathInternal.HasInvalidVolumeSeparator(path))
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathFormatNotSupported"));
+#endif
+
+ System.IO.Path.CheckInvalidPathChars(path, checkAdditional: true);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileSecurityStateAccess.cs b/src/mscorlib/src/System/IO/FileSecurityStateAccess.cs
new file mode 100644
index 0000000000..b6378c6142
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileSecurityStateAccess.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileSecurityStateAccess
+**
+**
+**
+**
+** Purpose: FileSecurityState enum
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO
+{
+ [Flags]
+ internal enum FileSecurityStateAccess
+ {
+ NoAccess = 0,
+ Read = 1,
+ Write = 2,
+ Append = 4,
+ PathDiscovery = 8,
+ AllAccess = 15
+ }
+}
+
diff --git a/src/mscorlib/src/System/IO/FileShare.cs b/src/mscorlib/src/System/IO/FileShare.cs
new file mode 100644
index 0000000000..ad76d5da09
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileShare.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: FileShare
+**
+**
+**
+**
+** Purpose: Enum describing how to share files with other
+** processes - ie, whether two processes can simultaneously
+** read from the same file.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO {
+ // Contains constants for controlling file sharing options while
+ // opening files. You can specify what access other processes trying
+ // to open the same file concurrently can have.
+ //
+ // Note these values currently match the values for FILE_SHARE_READ,
+ // FILE_SHARE_WRITE, and FILE_SHARE_DELETE in winnt.h
+ //
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileShare
+ {
+ // No sharing. Any request to open the file (by this process or another
+ // process) will fail until the file is closed.
+ None = 0,
+
+ // Allows subsequent opening of the file for reading. If this flag is not
+ // specified, any request to open the file for reading (by this process or
+ // another process) will fail until the file is closed.
+ Read = 1,
+
+ // Allows subsequent opening of the file for writing. If this flag is not
+ // specified, any request to open the file for writing (by this process or
+ // another process) will fail until the file is closed.
+ Write = 2,
+
+ // Allows subsequent opening of the file for writing or reading. If this flag
+ // is not specified, any request to open the file for writing or reading (by
+ // this process or another process) will fail until the file is closed.
+ ReadWrite = 3,
+
+ // Open the file, but allow someone else to delete the file.
+ Delete = 4,
+
+ // Whether the file handle should be inheritable by child processes.
+ // Note this is not directly supported like this by Win32.
+ Inheritable = 0x10,
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileStream.cs b/src/mscorlib/src/System/IO/FileStream.cs
new file mode 100644
index 0000000000..deef30c480
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileStream.cs
@@ -0,0 +1,2695 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exposes a Stream around a file, with full
+** synchronous and asychronous support, and buffering.
+**
+**
+===========================================================*/
+using System;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Security;
+#if FEATURE_MACL
+using System.Security.AccessControl;
+#endif
+using System.Security.Permissions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Runtime.InteropServices;
+#if FEATURE_REMOTING
+using System.Runtime.Remoting.Messaging;
+#endif
+using System.Runtime.CompilerServices;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+using System.Diagnostics.Tracing;
+
+/*
+ * FileStream supports different modes of accessing the disk - async mode
+ * and sync mode. They are two completely different codepaths in the
+ * sync & async methods (ie, Read/Write vs. BeginRead/BeginWrite). File
+ * handles in NT can be opened in only sync or overlapped (async) mode,
+ * and we have to deal with this pain. Stream has implementations of
+ * the sync methods in terms of the async ones, so we'll
+ * call through to our base class to get those methods when necessary.
+ *
+ * Also buffering is added into FileStream as well. Folded in the
+ * code from BufferedStream, so all the comments about it being mostly
+ * aggressive (and the possible perf improvement) apply to FileStream as
+ * well. Also added some buffering to the async code paths.
+ *
+ * Class Invariants:
+ * The class has one buffer, shared for reading & writing. It can only be
+ * used for one or the other at any point in time - not both. The following
+ * should be true:
+ * 0 <= _readPos <= _readLen < _bufferSize
+ * 0 <= _writePos < _bufferSize
+ * _readPos == _readLen && _readPos > 0 implies the read buffer is valid,
+ * but we're at the end of the buffer.
+ * _readPos == _readLen == 0 means the read buffer contains garbage.
+ * Either _writePos can be greater than 0, or _readLen & _readPos can be
+ * greater than zero, but neither can be greater than zero at the same time.
+ *
+ */
+
+namespace System.IO {
+
+ // This is an internal object implementing IAsyncResult with fields
+ // for all of the relevant data necessary to complete the IO operation.
+ // This is used by AsyncFSCallback and all of the async methods.
+ // We should probably make this a nested type of FileStream. But
+ // I don't know how to define a nested class in mscorlib.h
+
+ unsafe internal sealed class FileStreamAsyncResult : IAsyncResult
+ {
+ // README:
+ // If you modify the order of these fields, make sure to update
+ // the native VM definition of this class as well!!!
+ // User code callback
+ private AsyncCallback _userCallback;
+ private Object _userStateObject;
+ private ManualResetEvent _waitHandle;
+ [System.Security.SecurityCritical]
+ private SafeFileHandle _handle; // For cancellation support.
+
+ [SecurityCritical]
+ private NativeOverlapped* _overlapped;
+ internal NativeOverlapped* OverLapped { [SecurityCritical]get { return _overlapped; } }
+ internal bool IsAsync { [SecuritySafeCritical]get { return _overlapped != null; } }
+
+
+ internal int _EndXxxCalled; // Whether we've called EndXxx already.
+ private int _numBytes; // number of bytes read OR written
+ internal int NumBytes { get { return _numBytes; } }
+
+ private int _errorCode;
+ internal int ErrorCode { get { return _errorCode; } }
+
+ private int _numBufferedBytes;
+ internal int NumBufferedBytes { get { return _numBufferedBytes; } }
+
+ internal int NumBytesRead { get { return _numBytes + _numBufferedBytes; } }
+
+ private bool _isWrite; // Whether this is a read or a write
+ internal bool IsWrite { get { return _isWrite; } }
+
+ private bool _isComplete; // Value for IsCompleted property
+ private bool _completedSynchronously; // Which thread called callback
+
+ // The NativeOverlapped struct keeps a GCHandle to this IAsyncResult object.
+ // So if the user doesn't call EndRead/EndWrite, a finalizer won't help because
+ // it'll never get called.
+
+ // Overlapped class will take care of the async IO operations in progress
+ // when an appdomain unload occurs.
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static IOCompletionCallback s_IOCallback;
+
+ [SecuritySafeCritical]
+ internal FileStreamAsyncResult(
+ int numBufferedBytes,
+ byte[] bytes,
+ SafeFileHandle handle,
+ AsyncCallback userCallback,
+ Object userStateObject,
+ bool isWrite)
+ {
+ _userCallback = userCallback;
+ _userStateObject = userStateObject;
+ _isWrite = isWrite;
+ _numBufferedBytes = numBufferedBytes;
+ _handle = handle;
+
+ // For Synchronous IO, I could go with either a callback and using
+ // the managed Monitor class, or I could create a handle and wait on it.
+ ManualResetEvent waitHandle = new ManualResetEvent(false);
+ _waitHandle = waitHandle;
+
+ // Create a managed overlapped class
+ // We will set the file offsets later
+ Overlapped overlapped = new Overlapped(0, 0, IntPtr.Zero, this);
+
+ // Pack the Overlapped class, and store it in the async result
+ if (userCallback != null)
+ {
+ var ioCallback = s_IOCallback; // cached static delegate; delay initialized due to it being SecurityCritical
+ if (ioCallback == null) s_IOCallback = ioCallback = new IOCompletionCallback(AsyncFSCallback);
+ _overlapped = overlapped.Pack(ioCallback, bytes);
+ }
+ else
+ {
+ _overlapped = overlapped.UnsafePack(null, bytes);
+ }
+
+ Contract.Assert(_overlapped != null, "Did Overlapped.Pack or Overlapped.UnsafePack just return a null?");
+ }
+
+ internal static FileStreamAsyncResult CreateBufferedReadResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite)
+ {
+ FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(numBufferedBytes, userCallback, userStateObject, isWrite);
+ asyncResult.CallUserCallback();
+ return asyncResult;
+ }
+
+ // This creates a synchronous Async Result. We should consider making this a separate class and maybe merge it with
+ // System.IO.Stream.SynchronousAsyncResult
+ private FileStreamAsyncResult(int numBufferedBytes, AsyncCallback userCallback, Object userStateObject, bool isWrite)
+ {
+ _userCallback = userCallback;
+ _userStateObject = userStateObject;
+ _isWrite = isWrite;
+ _numBufferedBytes = numBufferedBytes;
+ }
+
+ public Object AsyncState
+ {
+ get { return _userStateObject; }
+ }
+
+ public bool IsCompleted
+ {
+ get { return _isComplete; }
+ }
+
+ public WaitHandle AsyncWaitHandle
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ // Consider uncommenting this someday soon - the EventHandle
+ // in the Overlapped struct is really useless half of the
+ // time today since the OS doesn't signal it. If users call
+ // EndXxx after the OS call happened to complete, there's no
+ // reason to create a synchronization primitive here. Fixing
+ // this will save us some perf, assuming we can correctly
+ // initialize the ManualResetEvent.
+ if (_waitHandle == null) {
+ ManualResetEvent mre = new ManualResetEvent(false);
+ if (_overlapped != null && _overlapped->EventHandle != IntPtr.Zero) {
+ mre.SafeWaitHandle = new SafeWaitHandle(_overlapped->EventHandle, true);
+ }
+
+ // make sure only one thread sets _waitHandle
+ if (Interlocked.CompareExchange<ManualResetEvent>(ref _waitHandle, mre, null) == null) {
+ if (_isComplete)
+ _waitHandle.Set();
+ }
+ else {
+ // There's a slight but acceptable race condition if we weren't
+ // the thread that set _waitHandle and this code path
+ // returns before the code in the if statement
+ // executes (on the other thread). However, the
+ // caller is waiting for the wait handle to be set,
+ // which will still happen.
+ mre.Close();
+ }
+ }
+ return _waitHandle;
+ }
+ }
+
+ // Returns true iff the user callback was called by the thread that
+ // called BeginRead or BeginWrite. If we use an async delegate or
+ // threadpool thread internally, this will be false. This is used
+ // by code to determine whether a successive call to BeginRead needs
+ // to be done on their main thread or in their callback to avoid a
+ // stack overflow on many reads or writes.
+ public bool CompletedSynchronously
+ {
+ get { return _completedSynchronously; }
+ }
+
+ private void CallUserCallbackWorker()
+ {
+ _isComplete = true;
+
+ // ensure _isComplete is set before reading _waitHandle
+ Thread.MemoryBarrier();
+ if (_waitHandle != null)
+ _waitHandle.Set();
+
+ _userCallback(this);
+ }
+
+ internal void CallUserCallback()
+ {
+ // Convenience method for me, since I have to do this in a number
+ // of places in the buffering code for fake IAsyncResults.
+ // AsyncFSCallback intentionally does not use this method.
+
+ if (_userCallback != null) {
+ // Call user's callback on a threadpool thread.
+ // Set completedSynchronously to false, since it's on another
+ // thread, not the main thread.
+ _completedSynchronously = false;
+ ThreadPool.QueueUserWorkItem(state => ((FileStreamAsyncResult)state).CallUserCallbackWorker(), this);
+ }
+ else {
+ _isComplete = true;
+
+ // ensure _isComplete is set before reading _waitHandle
+ Thread.MemoryBarrier();
+ if (_waitHandle != null)
+ _waitHandle.Set();
+ }
+ }
+
+ [SecurityCritical]
+ internal void ReleaseNativeResource()
+ {
+ // Free memory & GC handles.
+ if (this._overlapped != null)
+ Overlapped.Free(_overlapped);
+ }
+
+ internal void Wait()
+ {
+ if (_waitHandle != null)
+ {
+ // We must block to ensure that AsyncFSCallback has completed,
+ // and we should close the WaitHandle in here. AsyncFSCallback
+ // and the hand-ported imitation version in COMThreadPool.cpp
+ // are the only places that set this event.
+ try
+ {
+ _waitHandle.WaitOne();
+ Contract.Assert(_isComplete == true, "FileStreamAsyncResult::Wait - AsyncFSCallback didn't set _isComplete to true!");
+ }
+ finally
+ {
+ _waitHandle.Close();
+ }
+ }
+ }
+
+ // When doing IO asynchronously (ie, _isAsync==true), this callback is
+ // called by a free thread in the threadpool when the IO operation
+ // completes.
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe private static void AsyncFSCallback(uint errorCode, uint numBytes, NativeOverlapped* pOverlapped)
+ {
+ BCLDebug.Log(String.Format("AsyncFSCallback called. errorCode: " + errorCode + " numBytes: " + numBytes));
+
+ // Unpack overlapped
+ Overlapped overlapped = Overlapped.Unpack(pOverlapped);
+ // Free the overlapped struct in EndRead/EndWrite.
+
+ // Extract async result from overlapped
+ FileStreamAsyncResult asyncResult =
+ (FileStreamAsyncResult)overlapped.AsyncResult;
+ asyncResult._numBytes = (int)numBytes;
+
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer))
+ FrameworkEventSource.Log.ThreadTransferReceive((long)(asyncResult.OverLapped), 2, string.Empty);
+
+ // Handle reading from & writing to closed pipes. While I'm not sure
+ // this is entirely necessary anymore, maybe it's possible for
+ // an async read on a pipe to be issued and then the pipe is closed,
+ // returning this error. This may very well be necessary.
+ if (errorCode == FileStream.ERROR_BROKEN_PIPE || errorCode == FileStream.ERROR_NO_DATA)
+ errorCode = 0;
+
+ asyncResult._errorCode = (int)errorCode;
+
+ // Call the user-provided callback. It can and often should
+ // call EndRead or EndWrite. There's no reason to use an async
+ // delegate here - we're already on a threadpool thread.
+ // IAsyncResult's completedSynchronously property must return
+ // false here, saying the user callback was called on another thread.
+ asyncResult._completedSynchronously = false;
+ asyncResult._isComplete = true;
+
+ // ensure _isComplete is set before reading _waitHandle
+ Thread.MemoryBarrier();
+
+ // The OS does not signal this event. We must do it ourselves.
+ ManualResetEvent wh = asyncResult._waitHandle;
+ if (wh != null)
+ {
+ Contract.Assert(!wh.SafeWaitHandle.IsClosed, "ManualResetEvent already closed!");
+ bool r = wh.Set();
+ Contract.Assert(r, "ManualResetEvent::Set failed!");
+ if (!r) __Error.WinIOError();
+ }
+
+ AsyncCallback userCallback = asyncResult._userCallback;
+ if (userCallback != null)
+ userCallback(asyncResult);
+ }
+
+ [SecuritySafeCritical]
+ [HostProtection(ExternalThreading = true)]
+ internal void Cancel()
+ {
+ Contract.Assert(_handle != null, "_handle should not be null.");
+ Contract.Assert(_overlapped != null, "Cancel should only be called on true asynchronous FileStreamAsyncResult, i.e. _overlapped is not null");
+
+ if (IsCompleted)
+ return;
+
+ if (_handle.IsInvalid)
+ return;
+
+ bool r = Win32Native.CancelIoEx(_handle, _overlapped);
+ if (!r)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ // ERROR_NOT_FOUND is returned if CancelIoEx cannot find the request to cancel.
+ // This probably means that the IO operation has completed.
+ if (errorCode != Win32Native.ERROR_NOT_FOUND)
+ __Error.WinIOError(errorCode, String.Empty);
+ }
+ }
+ }
+
+ [ComVisible(true)]
+ public class FileStream : Stream
+ {
+ internal const int DefaultBufferSize = 4096;
+
+ private byte[] _buffer; // Shared read/write buffer. Alloc on first use.
+ private String _fileName; // Fully qualified file name.
+ private bool _isAsync; // Whether we opened the handle for overlapped IO
+ private bool _canRead;
+ private bool _canWrite;
+ private bool _canSeek;
+ private bool _exposedHandle; // Could other code be using this handle?
+ private bool _isPipe; // Whether to disable async buffering code.
+ private int _readPos; // Read pointer within shared buffer.
+ private int _readLen; // Number of bytes read in buffer from file.
+ private int _writePos; // Write pointer within shared buffer.
+ private int _bufferSize; // Length of internal buffer, if it's allocated.
+ [System.Security.SecurityCritical] // auto-generated
+ private SafeFileHandle _handle;
+ private long _pos; // Cache current location in the file.
+ private long _appendStart;// When appending, prevent overwriting file.
+ private static AsyncCallback s_endReadTask;
+ private static AsyncCallback s_endWriteTask;
+ private static Action<object> s_cancelReadHandler;
+ private static Action<object> s_cancelWriteHandler;
+
+ //This exists only to support IsolatedStorageFileStream.
+ //Any changes to FileStream must include the corresponding changes in IsolatedStorage.
+ internal FileStream() {
+ }
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+ public FileStream(String path, FileMode mode)
+ : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public FileStream(String path, FileMode mode, FileAccess access)
+ : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share)
+ : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false, false, true) {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
+ : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false, false, true)
+ {
+ }
+
+#else // FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode)
+ : this(path, mode, (mode == FileMode.Append ? FileAccess.Write : FileAccess.ReadWrite), FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileAccess access)
+ : this(path, mode, access, FileShare.Read, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share)
+ : this(path, mode, access, share, DefaultBufferSize, FileOptions.None, Path.GetFileName(path), false) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
+ : this(path, mode, access, share, bufferSize, FileOptions.None, Path.GetFileName(path), false)
+ {
+ }
+#endif // FEATURE_CORECLR
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options)
+ : this(path, mode, access, share, bufferSize, options, Path.GetFileName(path), false)
+ {
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync)
+ : this(path, mode, access, share, bufferSize, (useAsync ? FileOptions.Asynchronous : FileOptions.None), Path.GetFileName(path), false)
+ {
+ }
+
+#if FEATURE_MACL
+ // This constructor is done differently to avoid loading a few more
+ // classes, and more importantly, to build correctly on Rotor.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options, FileSecurity fileSecurity)
+ {
+ Object pinningHandle;
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share, fileSecurity, out pinningHandle);
+ try {
+ Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false, false);
+ }
+ finally {
+ if (pinningHandle != null) {
+ GCHandle pinHandle = (GCHandle) pinningHandle;
+ pinHandle.Free();
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(String path, FileMode mode, FileSystemRights rights, FileShare share, int bufferSize, FileOptions options)
+ {
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
+ Init(path, mode, (FileAccess)0, (int)rights, true, share, bufferSize, options, secAttrs, Path.GetFileName(path), false, false, false);
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy)
+ {
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
+ Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, false, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath)
+ {
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
+ Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal FileStream(String path, FileMode mode, FileAccess access, FileShare share, int bufferSize, FileOptions options, String msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
+ {
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share);
+ Init(path, mode, access, 0, false, share, bufferSize, options, secAttrs, msgPath, bFromProxy, useLongPath, checkHost);
+ }
+
+ // AccessControl namespace is not defined in Rotor
+ [System.Security.SecuritySafeCritical]
+ private void Init(String path, FileMode mode, FileAccess access, int rights, bool useRights, FileShare share, int bufferSize, FileOptions options, Win32Native.SECURITY_ATTRIBUTES secAttrs, String msgPath, bool bFromProxy, bool useLongPath, bool checkHost)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path", Environment.GetResourceString("ArgumentNull_Path"));
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ Contract.EndContractBlock();
+
+#if FEATURE_MACL
+ FileSystemRights fileSystemRights = (FileSystemRights)rights;
+#endif
+ // msgPath must be safe to hand back to untrusted code.
+
+ _fileName = msgPath; // To handle odd cases of finalizing partially constructed objects.
+ _exposedHandle = false;
+
+ // don't include inheritable in our bounds check for share
+ FileShare tempshare = share & ~FileShare.Inheritable;
+ String badArg = null;
+
+ if (mode < FileMode.CreateNew || mode > FileMode.Append)
+ badArg = "mode";
+ else if (!useRights && (access < FileAccess.Read || access > FileAccess.ReadWrite))
+ badArg = "access";
+#if FEATURE_MACL
+ else if (useRights && (fileSystemRights < FileSystemRights.ReadData || fileSystemRights > FileSystemRights.FullControl))
+ badArg = "rights";
+#endif
+ else if (tempshare < FileShare.None || tempshare > (FileShare.ReadWrite | FileShare.Delete))
+ badArg = "share";
+
+ if (badArg != null)
+ throw new ArgumentOutOfRangeException(badArg, Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+
+ // NOTE: any change to FileOptions enum needs to be matched here in the error validation
+ if (options != FileOptions.None && (options & ~(FileOptions.WriteThrough | FileOptions.Asynchronous | FileOptions.RandomAccess | FileOptions.DeleteOnClose | FileOptions.SequentialScan | FileOptions.Encrypted | (FileOptions)0x20000000 /* NoBuffering */)) != 0)
+ throw new ArgumentOutOfRangeException("options", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+
+ // Write access validation
+#if FEATURE_MACL
+ if ((!useRights && (access & FileAccess.Write) == 0)
+ || (useRights && (fileSystemRights & FileSystemRights.Write) == 0))
+#else
+ if (!useRights && (access & FileAccess.Write) == 0)
+#endif //FEATURE_MACL
+ {
+ if (mode==FileMode.Truncate || mode==FileMode.CreateNew || mode==FileMode.Create || mode==FileMode.Append) {
+ // No write access
+ if (!useRights)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&AccessCombo", mode, access));
+#if FEATURE_MACL
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileMode&RightsCombo", mode, fileSystemRights));
+#endif //FEATURE_MACL
+ }
+ }
+
+#if FEATURE_MACL
+ // FileMode.Truncate only works with GENERIC_WRITE (FileAccess.Write), source:MSDN
+ // For backcomp use FileAccess.Write when FileSystemRights.Write is specified
+ if (useRights && (mode == FileMode.Truncate)) {
+ if (fileSystemRights == FileSystemRights.Write) {
+ useRights = false;
+ access = FileAccess.Write;
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFileModeTruncate&RightsCombo", mode, fileSystemRights));
+ }
+ }
+#endif
+
+ int fAccess;
+ if (!useRights) {
+ fAccess = access == FileAccess.Read? GENERIC_READ:
+ access == FileAccess.Write? GENERIC_WRITE:
+ GENERIC_READ | GENERIC_WRITE;
+ }
+ else {
+ fAccess = rights;
+ }
+
+ // 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);
+
+ _fileName = filePath;
+
+ // Prevent access to your disk drives as raw block devices.
+ if (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 !PLATFORM_UNIX
+ if (filePath.IndexOf( ':', 2 ) != -1)
+ throw new NotSupportedException( Environment.GetResourceString( "Argument_PathFormatNotSupported" ) );
+#endif // !PLATFORM_UNIX
+
+ bool read = false;
+
+#if FEATURE_MACL
+ if ((!useRights && (access & FileAccess.Read) != 0) || (useRights && (fileSystemRights & FileSystemRights.ReadAndExecute) != 0))
+#else
+ if (!useRights && (access & FileAccess.Read) != 0)
+#endif //FEATURE_MACL
+ {
+ if (mode == FileMode.Append)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidAppendMode"));
+ else
+ read = true;
+ }
+
+ // All demands in full trust domains are no-ops, so skip
+#if FEATURE_CAS_POLICY
+ if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+#endif // FEATURE_CAS_POLICY
+ {
+ // Build up security permissions required, as well as validate we
+ // have a sensible set of parameters. IE, creating a brand new file
+ // for reading doesn't make much sense.
+ FileIOPermissionAccess secAccess = FileIOPermissionAccess.NoAccess;
+
+ if (read)
+ {
+ Contract.Assert(mode != FileMode.Append);
+ secAccess = secAccess | FileIOPermissionAccess.Read;
+ }
+
+ // I can't think of any combos of FileMode we should disallow if we
+ // don't have read access. Writing would pretty much always be valid
+ // in those cases.
+
+ // For any FileSystemRights other than ReadAndExecute, demand Write permission
+ // This is probably bit overkill for TakeOwnership etc but we don't have any
+ // matching FileIOPermissionAccess to demand. It is better that we ask for Write permission.
+
+#if FEATURE_MACL
+ // FileMode.OpenOrCreate & FileSystemRights.Synchronize can create 0-byte file; demand write
+ if ((!useRights && (access & FileAccess.Write) != 0)
+ || (useRights && (fileSystemRights & (FileSystemRights.Write | FileSystemRights.Delete
+ | FileSystemRights.DeleteSubdirectoriesAndFiles
+ | FileSystemRights.ChangePermissions
+ | FileSystemRights.TakeOwnership)) != 0)
+ || (useRights && ((fileSystemRights & FileSystemRights.Synchronize) != 0)
+ && mode==FileMode.OpenOrCreate)
+ )
+#else
+ if (!useRights && (access & FileAccess.Write) != 0)
+#endif //FEATURE_MACL
+ {
+ if (mode==FileMode.Append)
+ secAccess = secAccess | FileIOPermissionAccess.Append;
+ else
+ secAccess = secAccess | FileIOPermissionAccess.Write;
+ }
+
+#if FEATURE_MACL
+ bool specifiedAcl;
+ unsafe {
+ specifiedAcl = secAttrs != null && secAttrs.pSecurityDescriptor != null;
+ }
+
+ AccessControlActions control = specifiedAcl ? AccessControlActions.Change : AccessControlActions.None;
+ new FileIOPermission(secAccess, control, new String[] { filePath }, false, false).Demand();
+#else
+#if FEATURE_CORECLR
+ if (checkHost) {
+ FileSecurityState state = new FileSecurityState(FileSecurityState.ToFileSecurityState(secAccess), path, filePath);
+ state.EnsureState();
+ }
+#else
+ new FileIOPermission(secAccess, new String[] { filePath }, false, false).Demand();
+#endif // FEATURE_CORECLR
+#endif
+ }
+
+ // Our Inheritable bit was stolen from Windows, but should be set in
+ // the security attributes class. Don't leave this bit set.
+ share &= ~FileShare.Inheritable;
+
+ bool seekToEnd = (mode==FileMode.Append);
+ // Must use a valid Win32 constant here...
+ if (mode == FileMode.Append)
+ mode = FileMode.OpenOrCreate;
+
+ // WRT async IO, do the right thing for whatever platform we're on.
+ // This way, someone can easily write code that opens a file
+ // asynchronously no matter what their platform is.
+ if ((options & FileOptions.Asynchronous) != 0)
+ _isAsync = true;
+ else
+ options &= ~FileOptions.Asynchronous;
+
+ int flagsAndAttributes = (int) options;
+
+#if !PLATFORM_UNIX
+ // For mitigating local elevation of privilege attack through named pipes
+ // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the
+ // named pipe server can't impersonate a high privileged client security context
+ flagsAndAttributes |= (Win32Native.SECURITY_SQOS_PRESENT | Win32Native.SECURITY_ANONYMOUS);
+#endif
+
+ // Don't pop up a dialog for reading from an emtpy floppy drive
+ int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+ try {
+ String tempPath = filePath;
+ if (useLongPath)
+ tempPath = Path.AddLongPathPrefix(tempPath);
+ _handle = Win32Native.SafeCreateFile(tempPath, fAccess, share, secAttrs, mode, flagsAndAttributes, IntPtr.Zero);
+
+ if (_handle.IsInvalid) {
+ // Return a meaningful exception, using the RELATIVE path to
+ // the file to avoid returning extra information to the caller
+ // unless they have path discovery permission, in which case
+ // the full path is fine & useful.
+
+ // NT5 oddity - when trying to open "C:\" as a FileStream,
+ // we usually get ERROR_PATH_NOT_FOUND from the OS. We should
+ // probably be consistent w/ every other directory.
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode==__Error.ERROR_PATH_NOT_FOUND && filePath.Equals(Directory.InternalGetDirectoryRoot(filePath)))
+ errorCode = __Error.ERROR_ACCESS_DENIED;
+
+ // We need to give an exception, and preferably it would include
+ // the fully qualified path name. Do security check here. If
+ // we fail, give back the msgPath, which should not reveal much.
+ // While this logic is largely duplicated in
+ // __Error.WinIOError, we need this for
+ // IsolatedStorageFileStream.
+ bool canGiveFullPath = false;
+
+ if (!bFromProxy)
+ {
+ try {
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false ).Demand();
+#endif
+ canGiveFullPath = true;
+ }
+ catch(SecurityException) {}
+ }
+
+ if (canGiveFullPath)
+ __Error.WinIOError(errorCode, _fileName);
+ else
+ __Error.WinIOError(errorCode, msgPath);
+ }
+ }
+ finally {
+ Win32Native.SetErrorMode(oldMode);
+ }
+
+ // Disallow access to all non-file devices from the FileStream
+ // constructors that take a String. Everyone else can call
+ // CreateFile themselves then use the constructor that takes an
+ // IntPtr. Disallows "con:", "com1:", "lpt1:", etc.
+ int fileType = Win32Native.GetFileType(_handle);
+ if (fileType != Win32Native.FILE_TYPE_DISK) {
+ _handle.Close();
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_FileStreamOnNonFiles"));
+ }
+
+ // This is necessary for async IO using IO Completion ports via our
+ // managed Threadpool API's. This (theoretically) calls the OS's
+ // BindIoCompletionCallback method, and passes in a stub for the
+ // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped
+ // struct for this request and gets a delegate to a managed callback
+ // from there, which it then calls on a threadpool thread. (We allocate
+ // our native OVERLAPPED structs 2 pointers too large and store EE state
+ // & GC handles there, one to an IAsyncResult, the other to a delegate.)
+ if (_isAsync) {
+ bool b = false;
+ // BindHandle requires UnmanagedCode permission
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
+#pragma warning restore 618
+ try {
+ b = ThreadPool.BindHandle(_handle);
+ }
+ finally {
+ CodeAccessPermission.RevertAssert();
+ if (!b) {
+ // We should close the handle so that the handle is not open until SafeFileHandle GC
+ Contract.Assert(!_exposedHandle, "Are we closing handle that we exposed/not own, how?");
+ _handle.Close();
+ }
+ }
+ if (!b)
+ throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed"));
+ }
+
+ if (!useRights) {
+ _canRead = (access & FileAccess.Read) != 0;
+ _canWrite = (access & FileAccess.Write) != 0;
+ }
+#if FEATURE_MACL
+ else {
+ _canRead = (fileSystemRights & FileSystemRights.ReadData) != 0;
+ _canWrite = ((fileSystemRights & FileSystemRights.WriteData) != 0)
+ || ((fileSystemRights & FileSystemRights.AppendData) != 0);
+ }
+#endif //FEATURE_MACL
+
+ _canSeek = true;
+ _isPipe = false;
+ _pos = 0;
+ _bufferSize = bufferSize;
+ _readPos = 0;
+ _readLen = 0;
+ _writePos = 0;
+
+ // For Append mode...
+ if (seekToEnd) {
+ _appendStart = SeekCore(0, SeekOrigin.End);
+ }
+ else {
+ _appendStart = -1;
+ }
+ }
+
+ [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public FileStream(IntPtr handle, FileAccess access)
+ : this(handle, access, true, DefaultBufferSize, false) {
+ }
+
+ [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public FileStream(IntPtr handle, FileAccess access, bool ownsHandle)
+ : this(handle, access, ownsHandle, DefaultBufferSize, false) {
+ }
+
+ [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize)
+ : this(handle, access, ownsHandle, bufferSize, false) {
+ }
+
+ // We explicitly do a Demand, not a LinkDemand here.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This constructor has been deprecated. Please use new FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) instead, and optionally make a new SafeFileHandle with ownsHandle=false if needed. http://go.microsoft.com/fwlink/?linkid=14202")]
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public FileStream(IntPtr handle, FileAccess access, bool ownsHandle, int bufferSize, bool isAsync)
+ : this(new SafeFileHandle(handle, ownsHandle), access, bufferSize, isAsync) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(SafeFileHandle handle, FileAccess access)
+ : this(handle, access, DefaultBufferSize, false) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize)
+ : this(handle, access, bufferSize, false) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public FileStream(SafeFileHandle handle, FileAccess access, int bufferSize, bool isAsync) {
+ // To ensure we don't leak a handle, put it in a SafeFileHandle first
+ if (handle.IsInvalid)
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidHandle"), "handle");
+ Contract.EndContractBlock();
+
+ _handle = handle;
+ _exposedHandle = true;
+
+ // Now validate arguments.
+ if (access < FileAccess.Read || access > FileAccess.ReadWrite)
+ throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+
+ int handleType = Win32Native.GetFileType(_handle);
+ Contract.Assert(handleType == Win32Native.FILE_TYPE_DISK || handleType == Win32Native.FILE_TYPE_PIPE || handleType == Win32Native.FILE_TYPE_CHAR, "FileStream was passed an unknown file type!");
+ _isAsync = isAsync;
+ _canRead = 0 != (access & FileAccess.Read);
+ _canWrite = 0 != (access & FileAccess.Write);
+ _canSeek = handleType == Win32Native.FILE_TYPE_DISK;
+ _bufferSize = bufferSize;
+ _readPos = 0;
+ _readLen = 0;
+ _writePos = 0;
+ _fileName = null;
+ _isPipe = handleType == Win32Native.FILE_TYPE_PIPE;
+
+ // This is necessary for async IO using IO Completion ports via our
+ // managed Threadpool API's. This calls the OS's
+ // BindIoCompletionCallback method, and passes in a stub for the
+ // LPOVERLAPPED_COMPLETION_ROUTINE. This stub looks at the Overlapped
+ // struct for this request and gets a delegate to a managed callback
+ // from there, which it then calls on a threadpool thread. (We allocate
+ // our native OVERLAPPED structs 2 pointers too large and store EE
+ // state & a handle to a delegate there.)
+#if !FEATURE_CORECLR
+ if (_isAsync) {
+ bool b = false;
+ try {
+ b = ThreadPool.BindHandle(_handle);
+ }
+ catch (ApplicationException) {
+ // If you passed in a synchronous handle and told us to use
+ // it asynchronously, throw here.
+ throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotAsync"));
+ }
+ if (!b) {
+ throw new IOException(Environment.GetResourceString("IO.IO_BindHandleFailed"));
+ }
+ }
+ else {
+#endif // FEATURE_CORECLR
+ if (handleType != Win32Native.FILE_TYPE_PIPE)
+ VerifyHandleIsSync();
+#if !FEATURE_CORECLR
+ }
+#endif // FEATURE_CORECLR
+
+ if (_canSeek)
+ SeekCore(0, SeekOrigin.Current);
+ else
+ _pos = 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share)
+ {
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+ if ((share & FileShare.Inheritable) != 0) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ secAttrs.bInheritHandle = 1;
+ }
+ return secAttrs;
+ }
+
+#if FEATURE_MACL
+ // If pinningHandle is not null, caller must free it AFTER the call to
+ // CreateFile has returned.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Win32Native.SECURITY_ATTRIBUTES GetSecAttrs(FileShare share, FileSecurity fileSecurity, out Object pinningHandle)
+ {
+ pinningHandle = null;
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+ if ((share & FileShare.Inheritable) != 0 || fileSecurity != null) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ if ((share & FileShare.Inheritable) != 0) {
+ secAttrs.bInheritHandle = 1;
+ }
+
+ // For ACL's, get the security descriptor from the FileSecurity.
+ if (fileSecurity != null) {
+ byte[] sd = fileSecurity.GetSecurityDescriptorBinaryForm();
+ pinningHandle = GCHandle.Alloc(sd, GCHandleType.Pinned);
+ fixed(byte* pSecDescriptor = sd)
+ secAttrs.pSecurityDescriptor = pSecDescriptor;
+ }
+ }
+ return secAttrs;
+ }
+#endif
+
+ // Verifies that this handle supports synchronous IO operations (unless you
+ // didn't open it for either reading or writing).
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void VerifyHandleIsSync()
+ {
+ // Do NOT use this method on pipes. Reading or writing to a pipe may
+ // cause an app to block incorrectly, introducing a deadlock (depending
+ // on whether a write will wake up an already-blocked thread or this
+ // FileStream's thread).
+
+ // Do NOT change this to use a byte[] of length 0, or test test won't
+ // work. Our ReadFile & WriteFile methods are special cased to return
+ // for arrays of length 0, since we'd get an IndexOutOfRangeException
+ // while using C#'s fixed syntax.
+ byte[] bytes = new byte[1];
+ int hr = 0;
+ int r = 0;
+
+ // If the handle is a pipe, ReadFile will block until there
+ // has been a write on the other end. We'll just have to deal with it,
+ // For the read end of a pipe, you can mess up and
+ // accidentally read synchronously from an async pipe.
+ if (CanRead) {
+ r = ReadFileNative(_handle, bytes, 0, 0, null, out hr);
+ }
+ else if (CanWrite) {
+ r = WriteFileNative(_handle, bytes, 0, 0, null, out hr);
+ }
+
+ if (hr==ERROR_INVALID_PARAMETER)
+ throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync"));
+ if (hr == Win32Native.ERROR_INVALID_HANDLE)
+ __Error.WinIOError(hr, "<OS handle>");
+ }
+
+
+ public override bool CanRead {
+ [Pure]
+ get { return _canRead; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _canWrite; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _canSeek; }
+ }
+
+ public virtual bool IsAsync {
+ get { return _isAsync; }
+ }
+
+ public override long Length {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (!CanSeek) __Error.SeekNotSupported();
+ int hi = 0, lo = 0;
+
+ lo = Win32Native.GetFileSize(_handle, out hi);
+
+ if (lo==-1) { // Check for either an error or a 4GB - 1 byte file.
+ int hr = Marshal.GetLastWin32Error();
+ if (hr != 0)
+ __Error.WinIOError(hr, String.Empty);
+ }
+ long len = (((long)hi) << 32) | ((uint) lo);
+ // If we're writing near the end of the file, we must include our
+ // internal buffer in our Length calculation. Don't flush because
+ // we use the length of the file in our async write method.
+ if (_writePos > 0 && _pos + _writePos > len)
+ len = _writePos + _pos;
+ return len;
+ }
+ }
+
+ public String Name {
+ [System.Security.SecuritySafeCritical]
+ get {
+ if (_fileName == null)
+ return Environment.GetResourceString("IO_UnknownFileName");
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, _fileName);
+ sourceState.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { _fileName }, false, false).Demand();
+#endif
+ return _fileName;
+ }
+ }
+
+ internal String NameInternal {
+ get {
+ if (_fileName == null)
+ return "<UnknownFileName>";
+ return _fileName;
+ }
+ }
+
+ public override long Position {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (!CanSeek) __Error.SeekNotSupported();
+
+ Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+
+ // Verify that internal position is in sync with the handle
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ // Compensate for buffer that we read from the handle (_readLen) Vs what the user
+ // read so far from the internel buffer (_readPos). Of course add any unwrittern
+ // buffered data
+ return _pos + (_readPos - _readLen + _writePos);
+ }
+ set {
+ if (value < 0) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_writePos > 0) FlushWrite(false);
+ _readPos = 0;
+ _readLen = 0;
+ Seek(value, SeekOrigin.Begin);
+ }
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileSecurity GetAccessControl()
+ {
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ return new FileSecurity(_handle, _fileName, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAccessControl(FileSecurity fileSecurity)
+ {
+ if (fileSecurity == null)
+ throw new ArgumentNullException("fileSecurity");
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ fileSecurity.Persist(_handle, _fileName);
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override void Dispose(bool disposing)
+ {
+ // Nothing will be done differently based on whether we are
+ // disposing vs. finalizing. This is taking advantage of the
+ // weak ordering between normal finalizable objects & critical
+ // finalizable objects, which I included in the SafeHandle
+ // design for FileStream, which would often "just work" when
+ // finalized.
+ try {
+ if (_handle != null && !_handle.IsClosed) {
+ // Flush data to disk iff we were writing. After
+ // thinking about this, we also don't need to flush
+ // our read position, regardless of whether the handle
+ // was exposed to the user. They probably would NOT
+ // want us to do this.
+ if (_writePos > 0) {
+ FlushWrite(!disposing);
+ }
+ }
+ }
+ finally {
+ if (_handle != null && !_handle.IsClosed)
+ _handle.Dispose();
+
+ _canRead = false;
+ _canWrite = false;
+ _canSeek = false;
+ // Don't set the buffer to null, to avoid a NullReferenceException
+ // when users have a race condition in their code (ie, they call
+ // Close when calling another method on Stream like Read).
+ //_buffer = null;
+ base.Dispose(disposing);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ ~FileStream()
+ {
+ if (_handle != null) {
+ BCLDebug.Correctness(_handle.IsClosed, "You didn't close a FileStream & it got finalized. Name: \""+_fileName+"\"");
+ Dispose(false);
+ }
+ }
+
+ public override void Flush()
+ {
+ Flush(false);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public virtual void Flush(Boolean flushToDisk)
+ {
+ // This code is duplicated in Dispose
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ FlushInternalBuffer();
+
+ if (flushToDisk && CanWrite)
+ {
+ FlushOSBuffer();
+ }
+ }
+
+ private void FlushInternalBuffer()
+ {
+ if (_writePos > 0)
+ {
+ FlushWrite(false);
+ }
+ else if (_readPos < _readLen && CanSeek)
+ {
+ FlushRead();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void FlushOSBuffer()
+ {
+ if (!Win32Native.FlushFileBuffers(_handle))
+ {
+ __Error.WinIOError();
+ }
+ }
+
+ // Reading is done by blocks from the file, but someone could read
+ // 1 byte from the buffer then write. At that point, the OS's file
+ // pointer is out of sync with the stream's position. All write
+ // functions should call this function to preserve the position in the file.
+ private void FlushRead() {
+ Contract.Assert(_writePos == 0, "FileStream: Write buffer must be empty in FlushRead!");
+ if (_readPos - _readLen != 0) {
+ Contract.Assert(CanSeek, "FileStream will lose buffered read data now.");
+ SeekCore(_readPos - _readLen, SeekOrigin.Current);
+ }
+ _readPos = 0;
+ _readLen = 0;
+ }
+
+ // Writes are buffered. Anytime the buffer fills up
+ // (_writePos + delta > _bufferSize) or the buffer switches to reading
+ // and there is left over data (_writePos > 0), this function must be called.
+ private void FlushWrite(bool calledFromFinalizer) {
+ Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream: Read buffer must be empty in FlushWrite!");
+
+ if (_isAsync) {
+ IAsyncResult asyncResult = BeginWriteCore(_buffer, 0, _writePos, null, null);
+ // With our Whidbey async IO & overlapped support for AD unloads,
+ // we don't strictly need to block here to release resources
+ // since that support takes care of the pinning & freeing the
+ // overlapped struct. We need to do this when called from
+ // Close so that the handle is closed when Close returns, but
+ // we do't need to call EndWrite from the finalizer.
+ // Additionally, if we do call EndWrite, we block forever
+ // because AD unloads prevent us from running the managed
+ // callback from the IO completion port. Blocking here when
+ // called from the finalizer during AD unload is clearly wrong,
+ // but we can't use any sort of test for whether the AD is
+ // unloading because if we weren't unloading, an AD unload
+ // could happen on a separate thread before we call EndWrite.
+ if (!calledFromFinalizer)
+ EndWrite(asyncResult);
+ }
+ else
+ WriteCore(_buffer, 0, _writePos);
+
+ _writePos = 0;
+ }
+
+
+ [Obsolete("This property has been deprecated. Please use FileStream's SafeFileHandle property instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public virtual IntPtr Handle {
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#endif
+ get {
+ Flush();
+ // Explicitly dump any buffered data, since the user could move our
+ // position or write to the file.
+ _readPos = 0;
+ _readLen = 0;
+ _writePos = 0;
+ _exposedHandle = true;
+
+ return _handle.DangerousGetHandle();
+ }
+ }
+
+ public virtual SafeFileHandle SafeFileHandle {
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#endif
+ get {
+ Flush();
+ // Explicitly dump any buffered data, since the user could move our
+ // position or write to the file.
+ _readPos = 0;
+ _readLen = 0;
+ _writePos = 0;
+ _exposedHandle = true;
+
+ return _handle;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void SetLength(long value)
+ {
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (!CanSeek) __Error.SeekNotSupported();
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ // Handle buffering updates.
+ if (_writePos > 0) {
+ FlushWrite(false);
+ }
+ else if (_readPos < _readLen) {
+ FlushRead();
+ }
+ _readPos = 0;
+ _readLen = 0;
+
+ if (_appendStart != -1 && value < _appendStart)
+ throw new IOException(Environment.GetResourceString("IO.IO_SetLengthAppendTruncate"));
+ SetLengthCore(value);
+ }
+
+ // We absolutely need this method broken out so that BeginWriteCore can call
+ // a method without having to go through buffering code that might call
+ // FlushWrite.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void SetLengthCore(long value)
+ {
+ Contract.Assert(value >= 0, "value >= 0");
+ long origPos = _pos;
+
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+ if (_pos != value)
+ SeekCore(value, SeekOrigin.Begin);
+ if (!Win32Native.SetEndOfFile(_handle)) {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr==__Error.ERROR_INVALID_PARAMETER)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig"));
+ __Error.WinIOError(hr, String.Empty);
+ }
+ // Return file pointer to where it was before setting length
+ if (origPos != value) {
+ if (origPos < value)
+ SeekCore(origPos, SeekOrigin.Begin);
+ else
+ SeekCore(0, SeekOrigin.End);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int Read([In, Out] byte[] array, int offset, int count) {
+ if (array==null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+
+ bool isBlocked = false;
+ int n = _readLen - _readPos;
+ // if the read buffer is empty, read into either user's array or our
+ // buffer, depending on number of bytes user asked for and buffer size.
+ if (n == 0) {
+ if (!CanRead) __Error.ReadNotSupported();
+ if (_writePos > 0) FlushWrite(false);
+ if (!CanSeek || (count >= _bufferSize)) {
+ n = ReadCore(array, offset, count);
+ // Throw away read buffer.
+ _readPos = 0;
+ _readLen = 0;
+ return n;
+ }
+ if (_buffer == null) _buffer = new byte[_bufferSize];
+ n = ReadCore(_buffer, 0, _bufferSize);
+ if (n == 0) return 0;
+ isBlocked = n < _bufferSize;
+ _readPos = 0;
+ _readLen = n;
+ }
+ // Now copy min of count or numBytesAvailable (ie, near EOF) to array.
+ if (n > count) n = count;
+ Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
+ _readPos += n;
+
+ // We may have read less than the number of bytes the user asked
+ // for, but that is part of the Stream contract. Reading again for
+ // more data may cause us to block if we're using a device with
+ // no clear end of file, such as a serial port or pipe. If we
+ // blocked here & this code was used with redirected pipes for a
+ // process's standard output, this can lead to deadlocks involving
+ // two processes. But leave this here for files to avoid what would
+ // probably be a breaking change. --
+
+ // If we are reading from a device with no clear EOF like a
+ // serial port or a pipe, this will cause us to block incorrectly.
+ if (!_isPipe) {
+ // If we hit the end of the buffer and didn't have enough bytes, we must
+ // read some more from the underlying stream. However, if we got
+ // fewer bytes from the underlying stream than we asked for (ie, we're
+ // probably blocked), don't ask for more bytes.
+ if (n < count && !isBlocked) {
+ Contract.Assert(_readPos == _readLen, "Read buffer should be empty!");
+ int moreBytesRead = ReadCore(array, offset + n, count - n);
+ n += moreBytesRead;
+ // We've just made our buffer inconsistent with our position
+ // pointer. We must throw away the read buffer.
+ _readPos = 0;
+ _readLen = 0;
+ }
+ }
+
+ return n;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe int ReadCore(byte[] buffer, int offset, int count) {
+ Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
+ Contract.Assert(CanRead, "CanRead");
+
+ Contract.Assert(buffer != null, "buffer != null");
+ Contract.Assert(_writePos == 0, "_writePos == 0");
+ Contract.Assert(offset >= 0, "offset is negative");
+ Contract.Assert(count >= 0, "count is negative");
+
+ if (_isAsync) {
+ IAsyncResult result = BeginReadCore(buffer, offset, count, null, null, 0);
+ return EndRead(result);
+ }
+
+ // Make sure we are reading from the right spot
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ int hr = 0;
+ int r = ReadFileNative(_handle, buffer, offset, count, null, out hr);
+ if (r == -1) {
+ // For pipes, ERROR_BROKEN_PIPE is the normal end of the pipe.
+ if (hr == ERROR_BROKEN_PIPE) {
+ r = 0;
+ }
+ else {
+ if (hr == ERROR_INVALID_PARAMETER)
+ throw new ArgumentException(Environment.GetResourceString("Arg_HandleNotSync"));
+
+ __Error.WinIOError(hr, String.Empty);
+ }
+ }
+ Contract.Assert(r >= 0, "FileStream's ReadCore is likely broken.");
+ _pos += r;
+
+ return r;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override long Seek(long offset, SeekOrigin origin) {
+ if (origin<SeekOrigin.Begin || origin>SeekOrigin.End)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin"));
+ Contract.EndContractBlock();
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (!CanSeek) __Error.SeekNotSupported();
+
+ Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+
+ // If we've got bytes in our buffer to write, write them out.
+ // If we've read in and consumed some bytes, we'll have to adjust
+ // our seek positions ONLY IF we're seeking relative to the current
+ // position in the stream. This simulates doing a seek to the new
+ // position, then a read for the number of bytes we have in our buffer.
+ if (_writePos > 0) {
+ FlushWrite(false);
+ }
+ else if (origin == SeekOrigin.Current) {
+ // Don't call FlushRead here, which would have caused an infinite
+ // loop. Simply adjust the seek origin. This isn't necessary
+ // if we're seeking relative to the beginning or end of the stream.
+ offset -= (_readLen - _readPos);
+ }
+
+ // Verify that internal position is in sync with the handle
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ long oldPos = _pos + (_readPos - _readLen);
+ long pos = SeekCore(offset, origin);
+
+ // Prevent users from overwriting data in a file that was opened in
+ // append mode.
+ if (_appendStart != -1 && pos < _appendStart) {
+ SeekCore(oldPos, SeekOrigin.Begin);
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekAppendOverwrite"));
+ }
+
+ // We now must update the read buffer. We can in some cases simply
+ // update _readPos within the buffer, copy around the buffer so our
+ // Position property is still correct, and avoid having to do more
+ // reads from the disk. Otherwise, discard the buffer's contents.
+ if (_readLen > 0) {
+ // We can optimize the following condition:
+ // oldPos - _readPos <= pos < oldPos + _readLen - _readPos
+ if (oldPos == pos) {
+ if (_readPos > 0) {
+ //Console.WriteLine("Seek: seeked for 0, adjusting buffer back by: "+_readPos+" _readLen: "+_readLen);
+ Buffer.InternalBlockCopy(_buffer, _readPos, _buffer, 0, _readLen - _readPos);
+ _readLen -= _readPos;
+ _readPos = 0;
+ }
+ // If we still have buffered data, we must update the stream's
+ // position so our Position property is correct.
+ if (_readLen > 0)
+ SeekCore(_readLen, SeekOrigin.Current);
+ }
+ else if (oldPos - _readPos < pos && pos < oldPos + _readLen - _readPos) {
+ int diff = (int)(pos - oldPos);
+ //Console.WriteLine("Seek: diff was "+diff+", readpos was "+_readPos+" adjusting buffer - shrinking by "+ (_readPos + diff));
+ Buffer.InternalBlockCopy(_buffer, _readPos+diff, _buffer, 0, _readLen - (_readPos + diff));
+ _readLen -= (_readPos + diff);
+ _readPos = 0;
+ if (_readLen > 0)
+ SeekCore(_readLen, SeekOrigin.Current);
+ }
+ else {
+ // Lose the read buffer.
+ _readPos = 0;
+ _readLen = 0;
+ }
+ Contract.Assert(_readLen >= 0 && _readPos <= _readLen, "_readLen should be nonnegative, and _readPos should be less than or equal _readLen");
+ Contract.Assert(pos == Position, "Seek optimization: pos != Position! Buffer math was mangled.");
+ }
+ return pos;
+ }
+
+ // This doesn't do argument checking. Necessary for SetLength, which must
+ // set the file pointer beyond the end of the file. This will update the
+ // internal position
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private long SeekCore(long offset, SeekOrigin origin) {
+ Contract.Assert(!_handle.IsClosed && CanSeek, "!_handle.IsClosed && CanSeek");
+ Contract.Assert(origin>=SeekOrigin.Begin && origin<=SeekOrigin.End, "origin>=SeekOrigin.Begin && origin<=SeekOrigin.End");
+ int hr = 0;
+ long ret = 0;
+
+ ret = Win32Native.SetFilePointer(_handle, offset, origin, out hr);
+ if (ret == -1) {
+ // #errorInvalidHandle
+ // If ERROR_INVALID_HANDLE is returned, it doesn't suffice to set
+ // the handle as invalid; the handle must also be closed.
+ //
+ // Marking the handle as invalid but not closing the handle
+ // resulted in exceptions during finalization and locked column
+ // values (due to invalid but unclosed handle) in SQL FileStream
+ // scenarios.
+ //
+ // A more mainstream scenario involves accessing a file on a
+ // network share. ERROR_INVALID_HANDLE may occur because the network
+ // connection was dropped and the server closed the handle. However,
+ // the client side handle is still open and even valid for certain
+ // operations.
+ //
+ // Note that Dispose doesn't throw so we don't need to special case.
+ // SetHandleAsInvalid only sets _closed field to true (without
+ // actually closing handle) so we don't need to call that as well.
+ if (hr == Win32Native.ERROR_INVALID_HANDLE)
+ _handle.Dispose();
+ __Error.WinIOError(hr, String.Empty);
+ }
+
+ _pos = ret;
+ return ret;
+ }
+
+ // Checks the position of the OS's handle equals what we expect it to.
+ // This will fail if someone else moved the FileStream's handle or if
+ // we've hit a bug in FileStream's position updating code.
+ private void VerifyOSHandlePosition()
+ {
+ if (!CanSeek)
+ return;
+
+ // SeekCore will override the current _pos, so save it now
+ long oldPos = _pos;
+ long curPos = SeekCore(0, SeekOrigin.Current);
+
+ if (curPos != oldPos) {
+ // For reads, this is non-fatal but we still could have returned corrupted
+ // data in some cases. So discard the internal buffer. Potential MDA
+ _readPos = 0;
+ _readLen = 0;
+ if(_writePos > 0) {
+ // Discard the buffer and let the user know!
+ _writePos = 0;
+ throw new IOException(Environment.GetResourceString("IO.IO_FileStreamHandlePosition"));
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Write(byte[] array, int offset, int count) {
+ if (array==null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ if (_writePos == 0)
+ {
+ // Ensure we can write to the stream, and ready buffer for writing.
+ if (!CanWrite) __Error.WriteNotSupported();
+ if (_readPos < _readLen) FlushRead();
+ _readPos = 0;
+ _readLen = 0;
+ }
+
+ // If our buffer has data in it, copy data from the user's array into
+ // the buffer, and if we can fit it all there, return. Otherwise, write
+ // the buffer to disk and copy any remaining data into our buffer.
+ // The assumption here is memcpy is cheaper than disk (or net) IO.
+ // (10 milliseconds to disk vs. ~20-30 microseconds for a 4K memcpy)
+ // So the extra copying will reduce the total number of writes, in
+ // non-pathological cases (ie, write 1 byte, then write for the buffer
+ // size repeatedly)
+ if (_writePos > 0) {
+ int numBytes = _bufferSize - _writePos; // space left in buffer
+ if (numBytes > 0) {
+ if (numBytes > count)
+ numBytes = count;
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
+ _writePos += numBytes;
+ if (count==numBytes) return;
+ offset += numBytes;
+ count -= numBytes;
+ }
+ // Reset our buffer. We essentially want to call FlushWrite
+ // without calling Flush on the underlying Stream.
+
+ if (_isAsync) {
+ IAsyncResult result = BeginWriteCore(_buffer, 0, _writePos, null, null);
+ EndWrite(result);
+ }
+ else
+ {
+ WriteCore(_buffer, 0, _writePos);
+ }
+
+ _writePos = 0;
+ }
+ // If the buffer would slow writes down, avoid buffer completely.
+ if (count >= _bufferSize) {
+ Contract.Assert(_writePos == 0, "FileStream cannot have buffered data to write here! Your stream will be corrupted.");
+ WriteCore(array, offset, count);
+ return;
+ }
+ else if (count == 0)
+ return; // Don't allocate a buffer then call memcpy for 0 bytes.
+ if (_buffer==null) _buffer = new byte[_bufferSize];
+ // Copy remaining bytes into buffer, to write at a later date.
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, count);
+ _writePos = count;
+ return;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void WriteCore(byte[] buffer, int offset, int count) {
+ Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
+ Contract.Assert(CanWrite, "CanWrite");
+
+ Contract.Assert(buffer != null, "buffer != null");
+ Contract.Assert(_readPos == _readLen, "_readPos == _readLen");
+ Contract.Assert(offset >= 0, "offset is negative");
+ Contract.Assert(count >= 0, "count is negative");
+
+ if (_isAsync) {
+ IAsyncResult result = BeginWriteCore(buffer, offset, count, null, null);
+ EndWrite(result);
+ return;
+ }
+
+ // Make sure we are writing to the position that we think we are
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ int hr = 0;
+ int r = WriteFileNative(_handle, buffer, offset, count, null, out hr);
+ if (r == -1) {
+ // For pipes, ERROR_NO_DATA is not an error, but the pipe is closing.
+ if (hr == ERROR_NO_DATA) {
+ r = 0;
+ }
+ else {
+ // ERROR_INVALID_PARAMETER may be returned for writes
+ // where the position is too large (ie, writing at Int64.MaxValue
+ // on Win9x) OR for synchronous writes to a handle opened
+ // asynchronously.
+ if (hr == ERROR_INVALID_PARAMETER)
+ throw new IOException(Environment.GetResourceString("IO.IO_FileTooLongOrHandleNotSync"));
+ __Error.WinIOError(hr, String.Empty);
+ }
+ }
+ Contract.Assert(r >= 0, "FileStream's WriteCore is likely broken.");
+ _pos += r;
+ return;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading = true)]
+ public override IAsyncResult BeginRead(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
+ {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (numBytes < 0)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < numBytes)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ if (!_isAsync)
+ return base.BeginRead(array, offset, numBytes, userCallback, stateObject);
+ else
+ return BeginReadAsync(array, offset, numBytes, userCallback, stateObject);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading = true)]
+ private FileStreamAsyncResult BeginReadAsync(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
+ {
+ Contract.Assert(_isAsync);
+
+ if (!CanRead) __Error.ReadNotSupported();
+
+ Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+
+ if (_isPipe)
+ {
+ // When redirecting stdout & stderr with the Process class, it's easy to deadlock your
+ // parent & child processes when doing writes 4K at a time. The
+ // OS appears to use a 4K buffer internally. If you write to a
+ // pipe that is full, you will block until someone read from
+ // that pipe. If you try reading from an empty pipe and
+ // FileStream's BeginRead blocks waiting for data to fill it's
+ // internal buffer, you will be blocked. In a case where a child
+ // process writes to stdout & stderr while a parent process tries
+ // reading from both, you can easily get into a deadlock here.
+ // To avoid this deadlock, don't buffer when doing async IO on
+ // pipes. But don't completely ignore buffered data either.
+ if (_readPos < _readLen)
+ {
+ int n = _readLen - _readPos;
+ if (n > numBytes) n = numBytes;
+ Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
+ _readPos += n;
+
+ // Return a synchronous FileStreamAsyncResult
+ return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false);
+ }
+ else
+ {
+ Contract.Assert(_writePos == 0, "FileStream must not have buffered write data here! Pipes should be unidirectional.");
+ return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
+ }
+ }
+
+ Contract.Assert(!_isPipe, "Should not be a pipe.");
+
+ // Handle buffering.
+ if (_writePos > 0) FlushWrite(false);
+ if (_readPos == _readLen)
+ {
+ // I can't see how to handle buffering of async requests when
+ // filling the buffer asynchronously, without a lot of complexity.
+ // The problems I see are issuing an async read, we do an async
+ // read to fill the buffer, then someone issues another read
+ // (either synchronously or asynchronously) before the first one
+ // returns. This would involve some sort of complex buffer locking
+ // that we probably don't want to get into, at least not in V1.
+ // If we did a sync read to fill the buffer, we could avoid the
+ // problem, and any async read less than 64K gets turned into a
+ // synchronous read by NT anyways... --
+
+ if (numBytes < _bufferSize)
+ {
+ if (_buffer == null) _buffer = new byte[_bufferSize];
+ IAsyncResult bufferRead = BeginReadCore(_buffer, 0, _bufferSize, null, null, 0);
+ _readLen = EndRead(bufferRead);
+ int n = _readLen;
+ if (n > numBytes) n = numBytes;
+ Buffer.InternalBlockCopy(_buffer, 0, array, offset, n);
+ _readPos = n;
+
+ // Return a synchronous FileStreamAsyncResult
+ return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false);
+ }
+ else
+ {
+ // Here we're making our position pointer inconsistent
+ // with our read buffer. Throw away the read buffer's contents.
+ _readPos = 0;
+ _readLen = 0;
+ return BeginReadCore(array, offset, numBytes, userCallback, stateObject, 0);
+ }
+ }
+ else
+ {
+ int n = _readLen - _readPos;
+ if (n > numBytes) n = numBytes;
+ Buffer.InternalBlockCopy(_buffer, _readPos, array, offset, n);
+ _readPos += n;
+
+ if (n >= numBytes)
+ {
+ // Return a synchronous FileStreamAsyncResult
+ return FileStreamAsyncResult.CreateBufferedReadResult(n, userCallback, stateObject, false);
+ }
+ else
+ {
+ // For streams with no clear EOF like serial ports or pipes
+ // we cannot read more data without causing an app to block
+ // incorrectly. Pipes don't go down this path
+ // though. This code needs to be fixed.
+ // Throw away read buffer.
+ _readPos = 0;
+ _readLen = 0;
+ return BeginReadCore(array, offset + n, numBytes - n, userCallback, stateObject, n);
+ }
+ // WARNING: all state on asyncResult objects must be set before
+ // we call ReadFile in BeginReadCore, since the OS can run our
+ // callback & the user's callback before ReadFile returns.
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe private FileStreamAsyncResult BeginReadCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject, int numBufferedBytesRead)
+ {
+ Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
+ Contract.Assert(CanRead, "CanRead");
+ Contract.Assert(bytes != null, "bytes != null");
+ Contract.Assert(_writePos == 0, "_writePos == 0");
+ Contract.Assert(_isAsync, "BeginReadCore doesn't work on synchronous file streams!");
+ Contract.Assert(offset >= 0, "offset is negative");
+ Contract.Assert(numBytes >= 0, "numBytes is negative");
+
+ // Create and store async stream class library specific data in the async result
+
+ // Must pass in _numBufferedBytes here to ensure all the state on the IAsyncResult
+ // object is set before we call ReadFile, which gives the OS an
+ // opportunity to run our callback (including the user callback &
+ // the call to EndRead) before ReadFile has returned.
+ FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(numBufferedBytesRead, bytes, _handle, userCallback, stateObject, false);
+ NativeOverlapped* intOverlapped = asyncResult.OverLapped;
+
+ // Calculate position in the file we should be at after the read is done
+ if (CanSeek) {
+ long len = Length;
+
+ // Make sure we are reading from the position that we think we are
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ if (_pos + numBytes > len) {
+ if (_pos <= len)
+ numBytes = (int) (len - _pos);
+ else
+ numBytes = 0;
+ }
+
+ // Now set the position to read from in the NativeOverlapped struct
+ // For pipes, we should leave the offset fields set to 0.
+ intOverlapped->OffsetLow = unchecked((int)_pos);
+ intOverlapped->OffsetHigh = (int)(_pos>>32);
+
+ // When using overlapped IO, the OS is not supposed to
+ // touch the file pointer location at all. We will adjust it
+ // ourselves. This isn't threadsafe.
+
+ // WriteFile should not update the file pointer when writing
+ // in overlapped mode, according to MSDN. But it does update
+ // the file pointer when writing to a UNC path!
+ // So changed the code below to seek to an absolute
+ // location, not a relative one. ReadFile seems consistent though.
+ SeekCore(numBytes, SeekOrigin.Current);
+ }
+
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer))
+ FrameworkEventSource.Log.ThreadTransferSend((long)(asyncResult.OverLapped), 2, string.Empty, false);
+
+ // queue an async ReadFile operation and pass in a packed overlapped
+ int hr = 0;
+ int r = ReadFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr);
+ // ReadFile, the OS version, will return 0 on failure. But
+ // my ReadFileNative wrapper returns -1. My wrapper will return
+ // the following:
+ // On error, r==-1.
+ // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
+ // on async requests that completed sequentially, r==0
+ // You will NEVER RELIABLY be able to get the number of bytes
+ // read back from this call when using overlapped structures! You must
+ // not pass in a non-null lpNumBytesRead to ReadFile when using
+ // overlapped structures! This is by design NT behavior.
+ if (r==-1 && numBytes!=-1) {
+
+ // For pipes, when they hit EOF, they will come here.
+ if (hr == ERROR_BROKEN_PIPE) {
+ // Not an error, but EOF. AsyncFSCallback will NOT be
+ // called. Call the user callback here.
+
+ // We clear the overlapped status bit for this special case.
+ // Failure to do so looks like we are freeing a pending overlapped later.
+ intOverlapped->InternalLow = IntPtr.Zero;
+ asyncResult.CallUserCallback();
+ // EndRead will free the Overlapped struct correctly.
+ }
+ else if (hr != ERROR_IO_PENDING) {
+ if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere.
+ SeekCore(0, SeekOrigin.Current);
+
+ if (hr == ERROR_HANDLE_EOF)
+ __Error.EndOfFile();
+ else
+ __Error.WinIOError(hr, String.Empty);
+ }
+ }
+ else {
+ // Due to a workaround for a race condition in NT's ReadFile &
+ // WriteFile routines, we will always be returning 0 from ReadFileNative
+ // when we do async IO instead of the number of bytes read,
+ // irregardless of whether the operation completed
+ // synchronously or asynchronously. We absolutely must not
+ // set asyncResult._numBytes here, since will never have correct
+ // results.
+ //Console.WriteLine("ReadFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on a separate thread");
+ }
+
+ return asyncResult;
+ }
+
+ [System.Security.SecuritySafeCritical] // Although the unsafe code is only required in PAL, the block is wide scoped. Leave it here for desktop to ensure it's reviewed.
+ public unsafe override int EndRead(IAsyncResult asyncResult)
+ {
+ // There are 3 significantly different IAsyncResults we'll accept
+ // here. One is from Stream::BeginRead. The other two are variations
+ // on our FileStreamAsyncResult. One is from BeginReadCore,
+ // while the other is from the BeginRead buffering wrapper.
+ if (asyncResult==null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ if (!_isAsync)
+ return base.EndRead(asyncResult);
+
+ FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
+ if (afsar==null || afsar.IsWrite)
+ __Error.WrongAsyncResult();
+
+ // Ensure we don't have any race conditions by doing an interlocked
+ // CompareExchange here. Avoids corrupting memory via freeing the
+ // NativeOverlapped class or GCHandle twice. --
+ if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0))
+ __Error.EndReadCalledTwice();
+
+ // Obtain the WaitHandle, but don't use public property in case we
+ // delay initialize the manual reset event in the future.
+ afsar.Wait();
+
+ // Free memory & GC handles.
+ afsar.ReleaseNativeResource();
+
+ // Now check for any error during the read.
+ if (afsar.ErrorCode != 0)
+ __Error.WinIOError(afsar.ErrorCode, String.Empty);
+
+ return afsar.NumBytesRead;
+ }
+
+ // Reads a byte from the file stream. Returns the byte cast to an int
+ // or -1 if reading from the end of the stream.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int ReadByte() {
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (_readLen==0 && !CanRead) __Error.ReadNotSupported();
+ Contract.Assert((_readPos==0 && _readLen==0 && _writePos >= 0) || (_writePos==0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+ if (_readPos == _readLen) {
+ if (_writePos > 0) FlushWrite(false);
+ Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
+ if (_buffer == null) _buffer = new byte[_bufferSize];
+ _readLen = ReadCore(_buffer, 0, _bufferSize);
+ _readPos = 0;
+ }
+ if (_readPos == _readLen)
+ return -1;
+
+ int result = _buffer[_readPos];
+ _readPos++;
+ return result;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading=true)]
+ public override IAsyncResult BeginWrite(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
+ {
+ if (array==null)
+ throw new ArgumentNullException("array");
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (numBytes < 0)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - offset < numBytes)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ if (!_isAsync)
+ return base.BeginWrite(array, offset, numBytes, userCallback, stateObject);
+ else
+ return BeginWriteAsync(array, offset, numBytes, userCallback, stateObject);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading = true)]
+ private FileStreamAsyncResult BeginWriteAsync(byte[] array, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
+ {
+ Contract.Assert(_isAsync);
+
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ Contract.Assert((_readPos == 0 && _readLen == 0 && _writePos >= 0) || (_writePos == 0 && _readPos <= _readLen), "We're either reading or writing, but not both.");
+
+ if (_isPipe)
+ {
+ // When redirecting stdout & stderr with the Process class, it's easy to deadlock your
+ // parent & child processes when doing writes 4K at a time. The
+ // OS appears to use a 4K buffer internally. If you write to a
+ // pipe that is full, you will block until someone read from
+ // that pipe. If you try reading from an empty pipe and
+ // FileStream's BeginRead blocks waiting for data to fill it's
+ // internal buffer, you will be blocked. In a case where a child
+ // process writes to stdout & stderr while a parent process tries
+ // reading from both, you can easily get into a deadlock here.
+ // To avoid this deadlock, don't buffer when doing async IO on
+ // pipes.
+ Contract.Assert(_readPos == 0 && _readLen == 0, "FileStream must not have buffered data here! Pipes should be unidirectional.");
+
+ if (_writePos > 0)
+ FlushWrite(false);
+
+ return BeginWriteCore(array, offset, numBytes, userCallback, stateObject);
+ }
+
+ // Handle buffering.
+ if (_writePos == 0)
+ {
+ if (_readPos < _readLen) FlushRead();
+ _readPos = 0;
+ _readLen = 0;
+ }
+
+ int n = _bufferSize - _writePos;
+ if (numBytes <= n)
+ {
+ if (_writePos == 0) _buffer = new byte[_bufferSize];
+ Buffer.InternalBlockCopy(array, offset, _buffer, _writePos, numBytes);
+ _writePos += numBytes;
+
+ // Return a synchronous FileStreamAsyncResult
+ return FileStreamAsyncResult.CreateBufferedReadResult(numBytes, userCallback, stateObject, true);
+ }
+
+ if (_writePos > 0)
+ FlushWrite(false);
+
+ return BeginWriteCore(array, offset, numBytes, userCallback, stateObject);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe private FileStreamAsyncResult BeginWriteCore(byte[] bytes, int offset, int numBytes, AsyncCallback userCallback, Object stateObject)
+ {
+ Contract.Assert(!_handle.IsClosed, "!_handle.IsClosed");
+ Contract.Assert(CanWrite, "CanWrite");
+ Contract.Assert(bytes != null, "bytes != null");
+ Contract.Assert(_readPos == _readLen, "_readPos == _readLen");
+ Contract.Assert(_isAsync, "BeginWriteCore doesn't work on synchronous file streams!");
+ Contract.Assert(offset >= 0, "offset is negative");
+ Contract.Assert(numBytes >= 0, "numBytes is negative");
+
+ // Create and store async stream class library specific data in the async result
+ FileStreamAsyncResult asyncResult = new FileStreamAsyncResult(0, bytes, _handle, userCallback, stateObject, true);
+ NativeOverlapped* intOverlapped = asyncResult.OverLapped;
+
+ if (CanSeek) {
+ // Make sure we set the length of the file appropriately.
+ long len = Length;
+ //Console.WriteLine("BeginWrite - Calculating end pos. pos: "+pos+" len: "+len+" numBytes: "+numBytes);
+
+ // Make sure we are writing to the position that we think we are
+ if (_exposedHandle)
+ VerifyOSHandlePosition();
+
+ if (_pos + numBytes > len) {
+ //Console.WriteLine("BeginWrite - Setting length to: "+(pos + numBytes));
+ SetLengthCore(_pos + numBytes);
+ }
+
+ // Now set the position to read from in the NativeOverlapped struct
+ // For pipes, we should leave the offset fields set to 0.
+ intOverlapped->OffsetLow = (int)_pos;
+ intOverlapped->OffsetHigh = (int)(_pos>>32);
+
+ // When using overlapped IO, the OS is not supposed to
+ // touch the file pointer location at all. We will adjust it
+ // ourselves. This isn't threadsafe.
+
+ SeekCore(numBytes, SeekOrigin.Current);
+ }
+
+ //Console.WriteLine("BeginWrite finishing. pos: "+pos+" numBytes: "+numBytes+" _pos: "+_pos+" Position: "+Position);
+
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer))
+ FrameworkEventSource.Log.ThreadTransferSend((long)(asyncResult.OverLapped), 2, string.Empty, false);
+
+ int hr = 0;
+ // queue an async WriteFile operation and pass in a packed overlapped
+ int r = WriteFileNative(_handle, bytes, offset, numBytes, intOverlapped, out hr);
+
+ // WriteFile, the OS version, will return 0 on failure. But
+ // my WriteFileNative wrapper returns -1. My wrapper will return
+ // the following:
+ // On error, r==-1.
+ // On async requests that are still pending, r==-1 w/ hr==ERROR_IO_PENDING
+ // On async requests that completed sequentially, r==0
+ // You will NEVER RELIABLY be able to get the number of bytes
+ // written back from this call when using overlapped IO! You must
+ // not pass in a non-null lpNumBytesWritten to WriteFile when using
+ // overlapped structures! This is ByDesign NT behavior.
+ if (r==-1 && numBytes!=-1) {
+ //Console.WriteLine("WriteFile returned 0; Write will complete asynchronously (if hr==3e5) hr: 0x{0:x}", hr);
+
+ // For pipes, when they are closed on the other side, they will come here.
+ if (hr == ERROR_NO_DATA) {
+ // Not an error, but EOF. AsyncFSCallback will NOT be
+ // called. Call the user callback here.
+ asyncResult.CallUserCallback();
+ // EndWrite will free the Overlapped struct correctly.
+ }
+ else if (hr != ERROR_IO_PENDING) {
+ if (!_handle.IsClosed && CanSeek) // Update Position - It could be anywhere.
+ SeekCore(0, SeekOrigin.Current);
+
+ if (hr == ERROR_HANDLE_EOF)
+ __Error.EndOfFile();
+ else
+ __Error.WinIOError(hr, String.Empty);
+ }
+ }
+ else {
+ // Due to a workaround for a race condition in NT's ReadFile &
+ // WriteFile routines, we will always be returning 0 from WriteFileNative
+ // when we do async IO instead of the number of bytes written,
+ // irregardless of whether the operation completed
+ // synchronously or asynchronously. We absolutely must not
+ // set asyncResult._numBytes here, since will never have correct
+ // results.
+ //Console.WriteLine("WriteFile returned: "+r+" (0x"+Int32.Format(r, "x")+") The IO completed synchronously, but the user callback was called on another thread.");
+ }
+
+ return asyncResult;
+ }
+
+ [System.Security.SecuritySafeCritical] // Although the unsafe code is only required in PAL, the block is wide scoped. Leave it here for desktop to ensure it's reviewed.
+ public unsafe override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult==null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ if (!_isAsync) {
+ base.EndWrite(asyncResult);
+ return;
+ }
+
+ FileStreamAsyncResult afsar = asyncResult as FileStreamAsyncResult;
+ if (afsar==null || !afsar.IsWrite)
+ __Error.WrongAsyncResult();
+
+ // Ensure we can't have any race conditions by doing an interlocked
+ // CompareExchange here. Avoids corrupting memory via freeing the
+ // NativeOverlapped class or GCHandle twice. --
+ if (1 == Interlocked.CompareExchange(ref afsar._EndXxxCalled, 1, 0))
+ __Error.EndWriteCalledTwice();
+
+ // Obtain the WaitHandle, but don't use public property in case we
+ // delay initialize the manual reset event in the future.
+ afsar.Wait();
+
+ // Free memory & GC handles.
+ afsar.ReleaseNativeResource();
+
+ // Now check for any error during the write.
+ if (afsar.ErrorCode != 0)
+ __Error.WinIOError(afsar.ErrorCode, String.Empty);
+
+ // Number of bytes written is afsar._numBytes + afsar._numBufferedBytes.
+ return;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void WriteByte(byte value)
+ {
+ if (_handle.IsClosed) __Error.FileNotOpen();
+ if (_writePos==0) {
+ if (!CanWrite) __Error.WriteNotSupported();
+ if (_readPos < _readLen) FlushRead();
+ _readPos = 0;
+ _readLen = 0;
+ Contract.Assert(_bufferSize > 0, "_bufferSize > 0");
+ if (_buffer==null) _buffer = new byte[_bufferSize];
+ }
+ if (_writePos == _bufferSize)
+ FlushWrite(false);
+
+ _buffer[_writePos] = value;
+ _writePos++;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void Lock(long position, long length) {
+ if (position < 0 || length < 0)
+ throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ int positionLow = unchecked((int)(position ));
+ int positionHigh = unchecked((int)(position >> 32));
+ int lengthLow = unchecked((int)(length ));
+ int lengthHigh = unchecked((int)(length >> 32));
+
+ if (!Win32Native.LockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
+ __Error.WinIOError();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void Unlock(long position, long length) {
+ if (position < 0 || length < 0)
+ throw new ArgumentOutOfRangeException((position < 0 ? "position" : "length"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_handle.IsClosed) __Error.FileNotOpen();
+
+ int positionLow = unchecked((int)(position ));
+ int positionHigh = unchecked((int)(position >> 32));
+ int lengthLow = unchecked((int)(length ));
+ int lengthHigh = unchecked((int)(length >> 32));
+
+ if (!Win32Native.UnlockFile(_handle, positionLow, positionHigh, lengthLow, lengthHigh))
+ __Error.WinIOError();
+ }
+
+ // Windows API definitions, from winbase.h and others
+
+ private const int FILE_ATTRIBUTE_NORMAL = 0x00000080;
+ private const int FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
+ private const int FILE_FLAG_OVERLAPPED = 0x40000000;
+ internal const int GENERIC_READ = unchecked((int)0x80000000);
+ private const int GENERIC_WRITE = 0x40000000;
+
+ private const int FILE_BEGIN = 0;
+ private const int FILE_CURRENT = 1;
+ private const int FILE_END = 2;
+
+ // Error codes (not HRESULTS), from winerror.h
+ internal const int ERROR_BROKEN_PIPE = 109;
+ internal const int ERROR_NO_DATA = 232;
+ private const int ERROR_HANDLE_EOF = 38;
+ private const int ERROR_INVALID_PARAMETER = 87;
+ private const int ERROR_IO_PENDING = 997;
+
+
+ // __ConsoleStream also uses this code.
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int ReadFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr)
+ {
+ Contract.Requires(handle != null, "handle != null");
+ Contract.Requires(offset >= 0, "offset >= 0");
+ Contract.Requires(count >= 0, "count >= 0");
+ Contract.Requires(bytes != null, "bytes != null");
+ // Don't corrupt memory when multiple threads are erroneously writing
+ // to this stream simultaneously.
+ if (bytes.Length - offset < count)
+ throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
+ Contract.EndContractBlock();
+
+ Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter mismatch in call to ReadFileNative.");
+
+ // You can't use the fixed statement on an array of length 0.
+ if (bytes.Length==0) {
+ hr = 0;
+ return 0;
+ }
+
+ int r = 0;
+ int numBytesRead = 0;
+
+ fixed(byte* p = bytes) {
+ if (_isAsync)
+ r = Win32Native.ReadFile(handle, p + offset, count, IntPtr.Zero, overlapped);
+ else
+ r = Win32Native.ReadFile(handle, p + offset, count, out numBytesRead, IntPtr.Zero);
+ }
+
+ if (r==0) {
+ hr = Marshal.GetLastWin32Error();
+ // We should never silently drop an error here without some
+ // extra work. We must make sure that BeginReadCore won't return an
+ // IAsyncResult that will cause EndRead to block, since the OS won't
+ // call AsyncFSCallback for us.
+ if (hr == ERROR_BROKEN_PIPE || hr == Win32Native.ERROR_PIPE_NOT_CONNECTED) {
+ // This handle was a pipe, and it's done. Not an error, but EOF.
+ // However, the OS will not call AsyncFSCallback!
+ // Let the caller handle this, since BeginReadCore & ReadCore
+ // need to do different things.
+ return -1;
+ }
+
+ // See code:#errorInvalidHandle in "private long SeekCore(long offset, SeekOrigin origin)".
+ if (hr == Win32Native.ERROR_INVALID_HANDLE)
+ _handle.Dispose();
+
+ return -1;
+ }
+ else
+ hr = 0;
+ return numBytesRead;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int WriteFileNative(SafeFileHandle handle, byte[] bytes, int offset, int count, NativeOverlapped* overlapped, out int hr) {
+ Contract.Requires(handle != null, "handle != null");
+ Contract.Requires(offset >= 0, "offset >= 0");
+ Contract.Requires(count >= 0, "count >= 0");
+ Contract.Requires(bytes != null, "bytes != null");
+ // Don't corrupt memory when multiple threads are erroneously writing
+ // to this stream simultaneously. (the OS is reading from
+ // the array we pass to WriteFile, but if we read beyond the end and
+ // that memory isn't allocated, we could get an AV.)
+ if (bytes.Length - offset < count)
+ throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
+ Contract.EndContractBlock();
+
+ Contract.Assert((_isAsync && overlapped != null) || (!_isAsync && overlapped == null), "Async IO parameter missmatch in call to WriteFileNative.");
+
+ // You can't use the fixed statement on an array of length 0.
+ if (bytes.Length==0) {
+ hr = 0;
+ return 0;
+ }
+
+ int numBytesWritten = 0;
+ int r = 0;
+
+ fixed(byte* p = bytes) {
+ if (_isAsync)
+ r = Win32Native.WriteFile(handle, p + offset, count, IntPtr.Zero, overlapped);
+ else
+ r = Win32Native.WriteFile(handle, p + offset, count, out numBytesWritten, IntPtr.Zero);
+ }
+
+ if (r==0) {
+ hr = Marshal.GetLastWin32Error();
+ // We should never silently drop an error here without some
+ // extra work. We must make sure that BeginWriteCore won't return an
+ // IAsyncResult that will cause EndWrite to block, since the OS won't
+ // call AsyncFSCallback for us.
+
+ if (hr==ERROR_NO_DATA) {
+ // This handle was a pipe, and the pipe is being closed on the
+ // other side. Let the caller handle this, since BeginWriteCore
+ // & WriteCore need to do different things.
+ return -1;
+ }
+
+ // See code:#errorInvalidHandle in "private long SeekCore(long offset, SeekOrigin origin)".
+ if (hr == Win32Native.ERROR_INVALID_HANDLE)
+ _handle.Dispose();
+
+ return -1;
+ }
+ else
+ hr = 0;
+ return numBytesWritten;
+ }
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ [SecuritySafeCritical]
+ public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() or BeginRead() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read/BeginRead) when we are not sure.
+ if (this.GetType() != typeof(FileStream))
+ return base.ReadAsync(buffer, offset, count, cancellationToken);
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<int>(cancellationToken);
+
+ if (_handle.IsClosed)
+ __Error.FileNotOpen();
+
+ // If async IO is not supported on this platform or
+ // if this FileStream was not opened with FileOptions.Asynchronous.
+ if (!_isAsync)
+ return base.ReadAsync(buffer, offset, count, cancellationToken);
+
+ var readTask = new FileStreamReadWriteTask<int>(cancellationToken);
+ var endReadTask = s_endReadTask;
+ if (endReadTask == null) s_endReadTask = endReadTask = EndReadTask; // benign initialization race condition
+ readTask._asyncResult = BeginReadAsync(buffer, offset, count, endReadTask, readTask);
+
+ if (readTask._asyncResult.IsAsync && cancellationToken.CanBeCanceled)
+ {
+ var cancelReadHandler = s_cancelReadHandler;
+ if (cancelReadHandler == null) s_cancelReadHandler = cancelReadHandler = CancelTask<int>; // benign initialization race condition
+ readTask._registration = cancellationToken.Register(cancelReadHandler, readTask);
+
+ // In case the task is completed right before we register the cancellation callback.
+ if (readTask._asyncResult.IsCompleted)
+ readTask._registration.Dispose();
+ }
+
+ return readTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ [SecuritySafeCritical]
+ public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer");
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() or BeginWrite() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write/BeginWrite) when we are not sure.
+ if (this.GetType() != typeof(FileStream))
+ return base.WriteAsync(buffer, offset, count, cancellationToken);
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ if (_handle.IsClosed)
+ __Error.FileNotOpen();
+
+ // If async IO is not supported on this platform or
+ // if this FileStream was not opened with FileOptions.Asynchronous.
+ if (!_isAsync)
+ return base.WriteAsync(buffer, offset, count, cancellationToken);
+
+ var writeTask = new FileStreamReadWriteTask<VoidTaskResult>(cancellationToken);
+ var endWriteTask = s_endWriteTask;
+ if (endWriteTask == null) s_endWriteTask = endWriteTask = EndWriteTask; // benign initialization race condition
+ writeTask._asyncResult = BeginWriteAsync(buffer, offset, count, endWriteTask, writeTask);
+
+ if (writeTask._asyncResult.IsAsync && cancellationToken.CanBeCanceled)
+ {
+ var cancelWriteHandler = s_cancelWriteHandler;
+ if (cancelWriteHandler == null) s_cancelWriteHandler = cancelWriteHandler = CancelTask<VoidTaskResult>; // benign initialization race condition
+ writeTask._registration = cancellationToken.Register(cancelWriteHandler, writeTask);
+
+ // In case the task is completed right before we register the cancellation callback.
+ if (writeTask._asyncResult.IsCompleted)
+ writeTask._registration.Dispose();
+ }
+
+ return writeTask;
+ }
+
+ // The task instance returned from ReadAsync and WriteAsync.
+ // Also stores all of the state necessary for those calls to avoid closures and extraneous delegate allocations.
+ private sealed class FileStreamReadWriteTask<T> : Task<T>
+ {
+ internal CancellationToken _cancellationToken;
+ internal CancellationTokenRegistration _registration;
+ internal FileStreamAsyncResult _asyncResult; // initialized after Begin call completes
+
+ internal FileStreamReadWriteTask(CancellationToken cancellationToken) : base()
+ {
+ _cancellationToken = cancellationToken;
+ }
+ }
+
+ // Cancellation callback for both ReadAsync and WriteAsync.
+ [SecuritySafeCritical]
+ private static void CancelTask<T>(object state)
+ {
+ var task = state as FileStreamReadWriteTask<T>;
+ Contract.Assert(task != null);
+ FileStreamAsyncResult asyncResult = task._asyncResult;
+
+ // This method is used as both the completion callback and the cancellation callback.
+ // We should try to cancel the operation if this is running as the completion callback
+ // or if cancellation is not applicable:
+ // 1. asyncResult is not a FileStreamAsyncResult
+ // 2. asyncResult.IsAsync is false: asyncResult is a "synchronous" FileStreamAsyncResult.
+ // 3. The asyncResult is completed: this should never happen.
+ Contract.Assert((!asyncResult.IsWrite && typeof(T) == typeof(int)) ||
+ (asyncResult.IsWrite && typeof(T) == typeof(VoidTaskResult)));
+ Contract.Assert(asyncResult != null);
+ Contract.Assert(asyncResult.IsAsync);
+
+ try
+ {
+ // Cancel the overlapped read and set the task to cancelled state.
+ if (!asyncResult.IsCompleted)
+ asyncResult.Cancel();
+ }
+ catch (Exception ex)
+ {
+ task.TrySetException(ex);
+ }
+ }
+
+ // Completion callback for ReadAsync
+ [SecuritySafeCritical]
+ private static void EndReadTask(IAsyncResult iar)
+ {
+ FileStreamAsyncResult asyncResult = iar as FileStreamAsyncResult;
+ Contract.Assert(asyncResult != null);
+ Contract.Assert(asyncResult.IsCompleted, "How can we end up in the completion callback if the IAsyncResult is not completed?");
+
+ var readTask = asyncResult.AsyncState as FileStreamReadWriteTask<int>;
+ Contract.Assert(readTask != null);
+
+ try
+ {
+ if (asyncResult.IsAsync)
+ {
+ asyncResult.ReleaseNativeResource();
+
+ // release the resource held by CancellationTokenRegistration
+ readTask._registration.Dispose();
+ }
+
+ if (asyncResult.ErrorCode == Win32Native.ERROR_OPERATION_ABORTED)
+ {
+ var cancellationToken = readTask._cancellationToken;
+ Contract.Assert(cancellationToken.IsCancellationRequested, "How can the IO operation be aborted if cancellation was not requested?");
+ readTask.TrySetCanceled(cancellationToken);
+ }
+ else
+ readTask.TrySetResult(asyncResult.NumBytesRead);
+ }
+ catch (Exception ex)
+ {
+ readTask.TrySetException(ex);
+ }
+ }
+
+ // Completion callback for WriteAsync
+ [SecuritySafeCritical]
+ private static void EndWriteTask(IAsyncResult iar)
+ {
+ var asyncResult = iar as FileStreamAsyncResult;
+ Contract.Assert(asyncResult != null);
+ Contract.Assert(asyncResult.IsCompleted, "How can we end up in the completion callback if the IAsyncResult is not completed?");
+
+ var writeTask = iar.AsyncState as FileStreamReadWriteTask<VoidTaskResult>;
+ Contract.Assert(writeTask != null);
+
+ try
+ {
+ if (asyncResult.IsAsync)
+ {
+ asyncResult.ReleaseNativeResource();
+
+ // release the resource held by CancellationTokenRegistration
+ writeTask._registration.Dispose();
+ }
+
+ if (asyncResult.ErrorCode == Win32Native.ERROR_OPERATION_ABORTED)
+ {
+ var cancellationToken = writeTask._cancellationToken;
+ Contract.Assert(cancellationToken.IsCancellationRequested, "How can the IO operation be aborted if cancellation was not requested?");
+ writeTask.TrySetCanceled(cancellationToken);
+ }
+ else
+ writeTask.TrySetResult(default(VoidTaskResult));
+ }
+ catch (Exception ex)
+ {
+ writeTask.TrySetException(ex);
+ }
+ }
+
+ // Unlike Flush(), FlushAsync() always flushes to disk. This is intentional.
+ // Legend is that we chose not to flush the OS file buffers in Flush() in fear of
+ // perf problems with frequent, long running FlushFileBuffers() calls. But we don't
+ // have that problem with FlushAsync() because we will call FlushFileBuffers() in the background.
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ [System.Security.SecuritySafeCritical]
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Flush() which a subclass might have overriden. To be safe
+ // we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Flush) when we are not sure.
+ if (this.GetType() != typeof(FileStream))
+ return base.FlushAsync(cancellationToken);
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ if (_handle.IsClosed)
+ __Error.FileNotOpen();
+
+ // The always synchronous data transfer between the OS and the internal buffer is intentional
+ // because this is needed to allow concurrent async IO requests. Concurrent data transfer
+ // between the OS and the internal buffer will result in race conditions. Since FlushWrite and
+ // FlushRead modify internal state of the stream and transfer data between the OS and the
+ // internal buffer, they cannot be truly async. We will, however, flush the OS file buffers
+ // asynchronously because it doesn't modify any internal state of the stream and is potentially
+ // a long running process.
+ try
+ {
+ FlushInternalBuffer();
+ }
+ catch (Exception e)
+ {
+ return Task.FromException(e);
+ }
+
+ if (CanWrite)
+ return Task.Factory.StartNew(
+ state => ((FileStream)state).FlushOSBuffer(),
+ this,
+ cancellationToken,
+ TaskCreationOptions.DenyChildAttach,
+ TaskScheduler.Default);
+ else
+ return Task.CompletedTask;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/IO/FileSystemEnumerable.cs b/src/mscorlib/src/System/IO/FileSystemEnumerable.cs
new file mode 100644
index 0000000000..c2e603c06a
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileSystemEnumerable.cs
@@ -0,0 +1,852 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Enumerates files and dirs
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Security;
+using System.Security.Permissions;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+using System.Threading;
+
+namespace System.IO
+{
+
+ // Overview:
+ // The key methods instantiate FileSystemEnumerableIterators. These compose the iterator with search result
+ // handlers that instantiate the FileInfo, DirectoryInfo, String, etc. The handlers then perform any
+ // additional required permission demands.
+ internal static class FileSystemEnumerableFactory
+ {
+ internal static IEnumerable<String> CreateFileNameIterator(String path, String originalUserPath, String searchPattern,
+ bool includeFiles, bool includeDirs, SearchOption searchOption, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(originalUserPath != null);
+ Contract.Requires(searchPattern != null);
+
+ SearchResultHandler<String> handler = new StringResultHandler(includeFiles, includeDirs);
+ return new FileSystemEnumerableIterator<String>(path, originalUserPath, searchPattern, searchOption, handler, checkHost);
+ }
+
+ internal static IEnumerable<FileInfo> CreateFileInfoIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(originalUserPath != null);
+ Contract.Requires(searchPattern != null);
+
+ SearchResultHandler<FileInfo> handler = new FileInfoResultHandler();
+ return new FileSystemEnumerableIterator<FileInfo>(path, originalUserPath, searchPattern, searchOption, handler, true);
+ }
+
+ internal static IEnumerable<DirectoryInfo> CreateDirectoryInfoIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption)
+ {
+
+ Contract.Requires(path != null);
+ Contract.Requires(originalUserPath != null);
+ Contract.Requires(searchPattern != null);
+
+ SearchResultHandler<DirectoryInfo> handler = new DirectoryInfoResultHandler();
+ return new FileSystemEnumerableIterator<DirectoryInfo>(path, originalUserPath, searchPattern, searchOption, handler, true);
+ }
+
+ internal static IEnumerable<FileSystemInfo> CreateFileSystemInfoIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(originalUserPath != null);
+ Contract.Requires(searchPattern != null);
+
+ SearchResultHandler<FileSystemInfo> handler = new FileSystemInfoResultHandler();
+ return new FileSystemEnumerableIterator<FileSystemInfo>(path, originalUserPath, searchPattern, searchOption, handler, true);
+ }
+ }
+
+ // Abstract Iterator, borrowed from Linq. Used in anticipation of need for similar enumerables
+ // in the future
+ abstract internal class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
+ {
+ int threadId;
+ internal int state;
+ internal TSource current;
+
+ public Iterator()
+ {
+ threadId = Thread.CurrentThread.ManagedThreadId;
+ }
+
+ public TSource Current
+ {
+ get { return current; }
+ }
+
+ protected abstract Iterator<TSource> Clone();
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ current = default(TSource);
+ state = -1;
+ }
+
+ public IEnumerator<TSource> GetEnumerator()
+ {
+ if (threadId == Thread.CurrentThread.ManagedThreadId && state == 0)
+ {
+ state = 1;
+ return this;
+ }
+
+ Iterator<TSource> duplicate = Clone();
+ duplicate.state = 1;
+ return duplicate;
+ }
+
+ public abstract bool MoveNext();
+
+ object IEnumerator.Current
+ {
+ get { return Current; }
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ void IEnumerator.Reset()
+ {
+ throw new NotSupportedException();
+ }
+
+ }
+
+ // Overview:
+ // Enumerates file system entries matching the search parameters. For recursive searches this
+ // searches through all the sub dirs and executes the search criteria against every dir.
+ //
+ // Generic implementation:
+ // FileSystemEnumerableIterator is generic. When it gets a WIN32_FIND_DATA, it calls the
+ // result handler to create an instance of the generic type.
+ //
+ // Usage:
+ // Use FileSystemEnumerableFactory to obtain FSEnumerables that can enumerate file system
+ // entries as String path names, FileInfos, DirectoryInfos, or FileSystemInfos.
+ //
+ // Security:
+ // For all the dirs/files returned, demands path discovery permission for their parent folders
+ internal class FileSystemEnumerableIterator<TSource> : Iterator<TSource>
+ {
+
+ private const int STATE_INIT = 1;
+ private const int STATE_SEARCH_NEXT_DIR = 2;
+ private const int STATE_FIND_NEXT_FILE = 3;
+ private const int STATE_FINISH = 4;
+
+ private SearchResultHandler<TSource> _resultHandler;
+ private List<Directory.SearchData> searchStack;
+ private Directory.SearchData searchData;
+ private String searchCriteria;
+ [System.Security.SecurityCritical]
+ SafeFindHandle _hnd = null;
+ bool needsParentPathDiscoveryDemand;
+
+ // empty means we know in advance that we won’t find any search results, which can happen if:
+ // 1. we don’t have a search pattern
+ // 2. we’re enumerating only the top directory and found no matches during the first call
+ // This flag allows us to return early for these cases. We can’t know this in advance for
+ // SearchOption.AllDirectories because we do a “*” search for subdirs and then use the
+ // searchPattern at each directory level.
+ bool empty;
+
+ private String userPath;
+ private SearchOption searchOption;
+ private String fullPath;
+ private String normalizedSearchPath;
+ private int oldMode;
+ private bool _checkHost;
+
+ [System.Security.SecuritySafeCritical]
+ internal FileSystemEnumerableIterator(String path, String originalUserPath, String searchPattern, SearchOption searchOption, SearchResultHandler<TSource> resultHandler, bool checkHost)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(originalUserPath != null);
+ Contract.Requires(searchPattern != null);
+ Contract.Requires(searchOption == SearchOption.AllDirectories || searchOption == SearchOption.TopDirectoryOnly);
+ Contract.Requires(resultHandler != null);
+
+ oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS);
+
+ searchStack = new List<Directory.SearchData>();
+
+ String normalizedSearchPattern = NormalizeSearchPattern(searchPattern);
+
+ if (normalizedSearchPattern.Length == 0)
+ {
+ empty = true;
+ }
+ else
+ {
+ _resultHandler = resultHandler;
+ this.searchOption = searchOption;
+
+ fullPath = Path.GetFullPathInternal(path);
+ String fullSearchString = GetFullSearchString(fullPath, normalizedSearchPattern);
+ normalizedSearchPath = Path.GetDirectoryName(fullSearchString);
+
+ // permission demands
+ String[] demandPaths = new String[2];
+ // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters
+ demandPaths[0] = Directory.GetDemandDir(fullPath, true);
+ // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
+ // Do a demand on the combined path so that we can fail early in case of deny
+ demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true);
+ _checkHost = checkHost;
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state1 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[0]);
+ state1.EnsureState();
+ FileSecurityState state2 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[1]);
+ state2.EnsureState();
+ }
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+#endif
+
+ // normalize search criteria
+ searchCriteria = GetNormalizedSearchCriteria(fullSearchString, normalizedSearchPath);
+
+ // fix up user path
+ String searchPatternDirName = Path.GetDirectoryName(normalizedSearchPattern);
+ String userPathTemp = originalUserPath;
+ if (searchPatternDirName != null && searchPatternDirName.Length != 0)
+ {
+ userPathTemp = Path.Combine(userPathTemp, searchPatternDirName);
+ }
+ this.userPath = userPathTemp;
+
+ searchData = new Directory.SearchData(normalizedSearchPath, this.userPath, searchOption);
+
+ CommonInit();
+ }
+
+ }
+
+ [System.Security.SecurityCritical]
+ private void CommonInit()
+ {
+ Contract.Assert(searchCriteria != null && searchData != null, "searchCriteria and searchData should be initialized");
+
+ // Execute searchCriteria against the current directory
+ String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria);
+
+ Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA();
+
+ // Open a Find handle
+ _hnd = Win32Native.FindFirstFile(searchPath, data);
+
+ if (_hnd.IsInvalid)
+ {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr != Win32Native.ERROR_FILE_NOT_FOUND && hr != Win32Native.ERROR_NO_MORE_FILES)
+ {
+ HandleError(hr, searchData.fullPath);
+ }
+ else
+ {
+ // flag this as empty only if we're searching just top directory
+ // Used in fast path for top directory only
+ empty = searchData.searchOption == SearchOption.TopDirectoryOnly;
+ }
+ }
+ // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to
+ // current. If empty, dispose handle.
+ if (searchData.searchOption == SearchOption.TopDirectoryOnly)
+ {
+ if (empty)
+ {
+ _hnd.Dispose();
+ }
+ else
+ {
+ SearchResult searchResult = CreateSearchResult(searchData, data);
+ if (_resultHandler.IsResultIncluded(searchResult))
+ {
+ current = _resultHandler.CreateObject(searchResult);
+ }
+ }
+ }
+ // for AllDirectories, we first recurse into dirs, so cleanup and add searchData
+ // to the stack
+ else
+ {
+ _hnd.Dispose();
+ searchStack.Add(searchData);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private FileSystemEnumerableIterator(String fullPath, String normalizedSearchPath, String searchCriteria, String userPath, SearchOption searchOption, SearchResultHandler<TSource> resultHandler, bool checkHost)
+ {
+ this.fullPath = fullPath;
+ this.normalizedSearchPath = normalizedSearchPath;
+ this.searchCriteria = searchCriteria;
+ this._resultHandler = resultHandler;
+ this.userPath = userPath;
+ this.searchOption = searchOption;
+ this._checkHost = checkHost;
+
+ searchStack = new List<Directory.SearchData>();
+
+ if (searchCriteria != null)
+ {
+ // permission demands
+ String[] demandPaths = new String[2];
+ // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters
+ demandPaths[0] = Directory.GetDemandDir(fullPath, true);
+ // For filters like foo\*.cs we need to verify if the directory foo is not denied access.
+ // Do a demand on the combined path so that we can fail early in case of deny
+ demandPaths[1] = Directory.GetDemandDir(normalizedSearchPath, true);
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state1 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[0]);
+ state1.EnsureState();
+ FileSecurityState state2 = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandPaths[1]);
+ state2.EnsureState();
+ }
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+#endif
+ searchData = new Directory.SearchData(normalizedSearchPath, userPath, searchOption);
+ CommonInit();
+ }
+ else
+ {
+ empty = true;
+ }
+ }
+
+ protected override Iterator<TSource> Clone()
+ {
+ return new FileSystemEnumerableIterator<TSource>(fullPath, normalizedSearchPath, searchCriteria, userPath, searchOption, _resultHandler, _checkHost);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ protected override void Dispose(bool disposing)
+ {
+ try
+ {
+ if (_hnd != null)
+ {
+ _hnd.Dispose();
+ }
+ }
+ finally
+ {
+ Win32Native.SetErrorMode(oldMode);
+ base.Dispose(disposing);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override bool MoveNext()
+ {
+ Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA();
+ switch (state)
+ {
+ case STATE_INIT:
+ {
+ if (empty)
+ {
+ state = STATE_FINISH;
+ goto case STATE_FINISH;
+ }
+ if (searchData.searchOption == SearchOption.TopDirectoryOnly)
+ {
+ state = STATE_FIND_NEXT_FILE;
+ if (current != null)
+ {
+ return true;
+ }
+ else
+ {
+ goto case STATE_FIND_NEXT_FILE;
+ }
+ }
+ else
+ {
+ state = STATE_SEARCH_NEXT_DIR;
+ goto case STATE_SEARCH_NEXT_DIR;
+ }
+ }
+ case STATE_SEARCH_NEXT_DIR:
+ {
+ Contract.Assert(searchData.searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly");
+ // Traverse directory structure. We need to get '*'
+ while (searchStack.Count > 0)
+ {
+ searchData = searchStack[0];
+ Contract.Assert((searchData.fullPath != null), "fullpath can't be null!");
+ searchStack.RemoveAt(0);
+
+ // Traverse the subdirs
+ AddSearchableDirsToStack(searchData);
+
+ // Execute searchCriteria against the current directory
+ String searchPath = Path.InternalCombine(searchData.fullPath, searchCriteria);
+
+ // Open a Find handle
+ _hnd = Win32Native.FindFirstFile(searchPath, data);
+ if (_hnd.IsInvalid)
+ {
+ int hr = Marshal.GetLastWin32Error();
+ if (hr == Win32Native.ERROR_FILE_NOT_FOUND || hr == Win32Native.ERROR_NO_MORE_FILES || hr == Win32Native.ERROR_PATH_NOT_FOUND)
+ continue;
+
+ _hnd.Dispose();
+ HandleError(hr, searchData.fullPath);
+ }
+
+ state = STATE_FIND_NEXT_FILE;
+ needsParentPathDiscoveryDemand = true;
+ SearchResult searchResult = CreateSearchResult(searchData, data);
+ if (_resultHandler.IsResultIncluded(searchResult))
+ {
+ if (needsParentPathDiscoveryDemand)
+ {
+ DoDemand(searchData.fullPath);
+ needsParentPathDiscoveryDemand = false;
+ }
+ current = _resultHandler.CreateObject(searchResult);
+ return true;
+ }
+ else
+ {
+ goto case STATE_FIND_NEXT_FILE;
+ }
+ }
+ state = STATE_FINISH;
+ goto case STATE_FINISH;
+ }
+ case STATE_FIND_NEXT_FILE:
+ {
+ if (searchData != null && _hnd != null)
+ {
+ // Keep asking for more matching files/dirs, add it to the list
+ while (Win32Native.FindNextFile(_hnd, data))
+ {
+ SearchResult searchResult = CreateSearchResult(searchData, data);
+ if (_resultHandler.IsResultIncluded(searchResult))
+ {
+ if (needsParentPathDiscoveryDemand)
+ {
+ DoDemand(searchData.fullPath);
+ needsParentPathDiscoveryDemand = false;
+ }
+ current = _resultHandler.CreateObject(searchResult);
+ return true;
+ }
+ }
+
+ // Make sure we quit with a sensible error.
+ int hr = Marshal.GetLastWin32Error();
+
+ if (_hnd != null)
+ _hnd.Dispose();
+
+ // ERROR_FILE_NOT_FOUND is valid here because if the top level
+ // dir doen't contain any subdirs and matching files then
+ // we will get here with this errorcode from the searchStack walk
+ if ((hr != 0) && (hr != Win32Native.ERROR_NO_MORE_FILES)
+ && (hr != Win32Native.ERROR_FILE_NOT_FOUND))
+ {
+ HandleError(hr, searchData.fullPath);
+ }
+ }
+ if (searchData.searchOption == SearchOption.TopDirectoryOnly)
+ {
+ state = STATE_FINISH;
+ goto case STATE_FINISH;
+ }
+ else
+ {
+ state = STATE_SEARCH_NEXT_DIR;
+ goto case STATE_SEARCH_NEXT_DIR;
+ }
+ }
+ case STATE_FINISH:
+ {
+ Dispose();
+ break;
+ }
+ }
+ return false;
+ }
+
+ [System.Security.SecurityCritical]
+ private SearchResult CreateSearchResult(Directory.SearchData localSearchData, Win32Native.WIN32_FIND_DATA findData)
+ {
+ String userPathFinal = Path.InternalCombine(localSearchData.userPath, findData.cFileName);
+ String fullPathFinal = Path.InternalCombine(localSearchData.fullPath, findData.cFileName);
+ return new SearchResult(fullPathFinal, userPathFinal, findData);
+ }
+
+ [System.Security.SecurityCritical]
+ private void HandleError(int hr, String path)
+ {
+ Dispose();
+ __Error.WinIOError(hr, path);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddSearchableDirsToStack(Directory.SearchData localSearchData)
+ {
+ Contract.Requires(localSearchData != null);
+
+ String searchPath = Path.InternalCombine(localSearchData.fullPath, "*");
+ SafeFindHandle hnd = null;
+ Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA();
+ try
+ {
+ // Get all files and dirs
+ hnd = Win32Native.FindFirstFile(searchPath, data);
+
+ if (hnd.IsInvalid)
+ {
+ int hr = Marshal.GetLastWin32Error();
+
+ // This could happen if the dir doesn't contain any files.
+ // Continue with the recursive search though, eventually
+ // searchStack will become empty
+ if (hr == Win32Native.ERROR_FILE_NOT_FOUND || hr == Win32Native.ERROR_NO_MORE_FILES || hr == Win32Native.ERROR_PATH_NOT_FOUND)
+ return;
+
+ HandleError(hr, localSearchData.fullPath);
+ }
+
+ // Add subdirs to searchStack. Exempt ReparsePoints as appropriate
+ int incr = 0;
+ do
+ {
+ if (FileSystemEnumerableHelpers.IsDir(data))
+ {
+ String tempFullPath = Path.InternalCombine(localSearchData.fullPath, data.cFileName);
+ String tempUserPath = Path.InternalCombine(localSearchData.userPath, data.cFileName);
+
+ SearchOption option = localSearchData.searchOption;
+
+#if EXCLUDE_REPARSEPOINTS
+ // Traverse reparse points depending on the searchoption specified
+ if ((searchDataSubDir.searchOption == SearchOption.AllDirectories) && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_REPARSE_POINT)))
+ option = SearchOption.TopDirectoryOnly;
+#endif
+ // Setup search data for the sub directory and push it into the stack
+ Directory.SearchData searchDataSubDir = new Directory.SearchData(tempFullPath, tempUserPath, option);
+
+ searchStack.Insert(incr++, searchDataSubDir);
+ }
+ } while (Win32Native.FindNextFile(hnd, data));
+ // We don't care about errors here
+ }
+ finally
+ {
+ if (hnd != null)
+ hnd.Dispose();
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal void DoDemand(String fullPathToDemand)
+ {
+#if FEATURE_CORECLR
+ if(_checkHost) {
+ String demandDir = Directory.GetDemandDir(fullPathToDemand, true);
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir);
+ state.EnsureState();
+ }
+#else
+ String demandDir = Directory.GetDemandDir(fullPathToDemand, true);
+ String[] demandPaths = new String[] { demandDir };
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand();
+#endif
+ }
+
+ private static String NormalizeSearchPattern(String searchPattern)
+ {
+ Contract.Requires(searchPattern != null);
+
+ // Win32 normalization trims only U+0020.
+ String tempSearchPattern = searchPattern.TrimEnd(Path.TrimEndChars);
+
+ // Make this corner case more useful, like dir
+ if (tempSearchPattern.Equals("."))
+ {
+ tempSearchPattern = "*";
+ }
+
+ Path.CheckSearchPattern(tempSearchPattern);
+ return tempSearchPattern;
+ }
+
+ private static String GetNormalizedSearchCriteria(String fullSearchString, String fullPathMod)
+ {
+ Contract.Requires(fullSearchString != null);
+ Contract.Requires(fullPathMod != null);
+ Contract.Requires(fullSearchString.Length >= fullPathMod.Length);
+
+ String searchCriteria = null;
+ char lastChar = fullPathMod[fullPathMod.Length - 1];
+ if (Path.IsDirectorySeparator(lastChar))
+ {
+ // Can happen if the path is C:\temp, in which case GetDirectoryName would return C:\
+ searchCriteria = fullSearchString.Substring(fullPathMod.Length);
+ }
+ else
+ {
+ Contract.Assert(fullSearchString.Length > fullPathMod.Length);
+ searchCriteria = fullSearchString.Substring(fullPathMod.Length + 1);
+ }
+ return searchCriteria;
+ }
+
+ private static String GetFullSearchString(String fullPath, String searchPattern)
+ {
+ Contract.Requires(fullPath != null);
+ Contract.Requires(searchPattern != null);
+
+ String tempStr = Path.InternalCombine(fullPath, searchPattern);
+
+ // If path ends in a trailing slash (\), append a * or we'll get a "Cannot find the file specified" exception
+ char lastChar = tempStr[tempStr.Length - 1];
+ if (Path.IsDirectorySeparator(lastChar) || lastChar == Path.VolumeSeparatorChar)
+ {
+ tempStr = tempStr + '*';
+ }
+
+ return tempStr;
+ }
+ }
+
+ internal abstract class SearchResultHandler<TSource>
+ {
+
+ [System.Security.SecurityCritical]
+ internal abstract bool IsResultIncluded(SearchResult result);
+
+ [System.Security.SecurityCritical]
+ internal abstract TSource CreateObject(SearchResult result);
+
+ }
+
+ internal class StringResultHandler : SearchResultHandler<String>
+ {
+ private bool _includeFiles;
+ private bool _includeDirs;
+
+ internal StringResultHandler(bool includeFiles, bool includeDirs)
+ {
+ _includeFiles = includeFiles;
+ _includeDirs = includeDirs;
+ }
+
+ [System.Security.SecurityCritical]
+ internal override bool IsResultIncluded(SearchResult result)
+ {
+ bool includeFile = _includeFiles && FileSystemEnumerableHelpers.IsFile(result.FindData);
+ bool includeDir = _includeDirs && FileSystemEnumerableHelpers.IsDir(result.FindData);
+ Contract.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!");
+ return (includeFile || includeDir);
+ }
+
+ [System.Security.SecurityCritical]
+ internal override String CreateObject(SearchResult result)
+ {
+ return result.UserPath;
+ }
+ }
+
+ internal class FileInfoResultHandler : SearchResultHandler<FileInfo>
+ {
+ [System.Security.SecurityCritical]
+ internal override bool IsResultIncluded(SearchResult result)
+ {
+ return FileSystemEnumerableHelpers.IsFile(result.FindData);
+ }
+
+ [System.Security.SecurityCritical]
+ internal override FileInfo CreateObject(SearchResult result)
+ {
+ String name = result.FullPath;
+#if FEATURE_CORECLR
+ 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();
+#endif
+ FileInfo fi = new FileInfo(name, false);
+ fi.InitializeFrom(result.FindData);
+ return fi;
+ }
+ }
+
+ internal class DirectoryInfoResultHandler : SearchResultHandler<DirectoryInfo>
+ {
+ [System.Security.SecurityCritical]
+ internal override bool IsResultIncluded(SearchResult result)
+ {
+ return FileSystemEnumerableHelpers.IsDir(result.FindData);
+ }
+
+ [System.Security.SecurityCritical]
+ internal override DirectoryInfo CreateObject(SearchResult result)
+ {
+ String name = result.FullPath;
+ String permissionName = name + "\\.";
+
+#if FEATURE_CORECLR
+ 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();
+#endif
+ DirectoryInfo di = new DirectoryInfo(name, false);
+ di.InitializeFrom(result.FindData);
+ return di;
+ }
+ }
+
+ internal class FileSystemInfoResultHandler : SearchResultHandler<FileSystemInfo>
+ {
+
+ [System.Security.SecurityCritical]
+ internal override bool IsResultIncluded(SearchResult result)
+ {
+ bool includeFile = FileSystemEnumerableHelpers.IsFile(result.FindData);
+ bool includeDir = FileSystemEnumerableHelpers.IsDir(result.FindData);
+ Contract.Assert(!(includeFile && includeDir), result.FindData.cFileName + ": current item can't be both file and dir!");
+
+ return (includeDir || includeFile);
+ }
+
+ [System.Security.SecurityCritical]
+ internal override FileSystemInfo CreateObject(SearchResult result)
+ {
+ bool isFile = FileSystemEnumerableHelpers.IsFile(result.FindData);
+ bool isDir = FileSystemEnumerableHelpers.IsDir(result.FindData);
+
+ if (isDir)
+ {
+ String name = result.FullPath;
+ String permissionName = name + "\\.";
+
+#if FEATURE_CORECLR
+ 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();
+#endif
+ DirectoryInfo di = new DirectoryInfo(name, false);
+ di.InitializeFrom(result.FindData);
+ return di;
+ }
+ else
+ {
+ Contract.Assert(isFile);
+ String name = result.FullPath;
+
+#if FEATURE_CORECLR
+ 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();
+#endif
+ FileInfo fi = new FileInfo(name, false);
+ fi.InitializeFrom(result.FindData);
+ return fi;
+ }
+ }
+
+ }
+
+ internal sealed class SearchResult
+ {
+ private String fullPath; // fully-qualifed path
+ private String userPath; // user-specified path
+ [System.Security.SecurityCritical]
+ private Win32Native.WIN32_FIND_DATA findData;
+
+ [System.Security.SecurityCritical]
+ internal SearchResult(String fullPath, String userPath, Win32Native.WIN32_FIND_DATA findData)
+ {
+ Contract.Requires(fullPath != null);
+ Contract.Requires(userPath != null);
+
+ this.fullPath = fullPath;
+ this.userPath = userPath;
+ this.findData = findData;
+ }
+
+ internal String FullPath
+ {
+ get { return fullPath; }
+ }
+
+ internal String UserPath
+ {
+ get { return userPath; }
+ }
+
+ internal Win32Native.WIN32_FIND_DATA FindData
+ {
+ [System.Security.SecurityCritical]
+ get { return findData; }
+ }
+
+ }
+
+ internal static class FileSystemEnumerableHelpers
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDir(Win32Native.WIN32_FIND_DATA data)
+ {
+ // Don't add "." nor ".."
+ return (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY))
+ && !data.cFileName.Equals(".") && !data.cFileName.Equals("..");
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsFile(Win32Native.WIN32_FIND_DATA data)
+ {
+ return 0 == (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY);
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/IO/FileSystemInfo.cs b/src/mscorlib/src/System/IO/FileSystemInfo.cs
new file mode 100644
index 0000000000..7a17a417af
--- /dev/null
+++ b/src/mscorlib/src/System/IO/FileSystemInfo.cs
@@ -0,0 +1,361 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Security;
+using System.Security.Permissions;
+using Microsoft.Win32;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+#if !FEATURE_CORECLR
+ [FileIOPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)]
+#endif
+ [ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class FileSystemInfo : MarshalByRefObject, ISerializable {
+#else // FEATURE_REMOTING
+ public abstract class FileSystemInfo : ISerializable {
+#endif //FEATURE_REMOTING
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Win32Native.WIN32_FILE_ATTRIBUTE_DATA _data; // Cache the file information
+ internal int _dataInitialised = -1; // We use this field in conjunction with the Refresh methods, if we succeed
+ // we store a zero, on failure we store the HResult in it so that we can
+ // give back a generic error back.
+
+ private const int ERROR_INVALID_PARAMETER = 87;
+ internal const int ERROR_ACCESS_DENIED = 0x5;
+
+ protected String FullPath; // fully qualified path of the directory
+ protected String OriginalPath; // path passed in by the user
+ private String _displayPath = ""; // path that can be displayed to the user
+
+#if FEATURE_CORECLR
+#if FEATURE_CORESYSTEM
+ [System.Security.SecurityCritical]
+#else
+ [System.Security.SecuritySafeCritical]
+#endif //FEATURE_CORESYSTEM
+#endif
+ protected FileSystemInfo()
+ {
+ }
+
+ protected FileSystemInfo(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Must use V1 field names here, since V1 didn't implement
+ // ISerializable.
+ FullPath = Path.GetFullPathInternal(info.GetString("FullPath"));
+ OriginalPath = info.GetString("OriginalPath");
+
+ // Lazily initialize the file attributes.
+ _dataInitialised = -1;
+ }
+
+ [System.Security.SecurityCritical]
+ internal void InitializeFrom(Win32Native.WIN32_FIND_DATA findData)
+ {
+ _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ _data.PopulateFrom(findData);
+ _dataInitialised = 0;
+ }
+
+ // Full path of the direcory/file
+ public virtual String FullName {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ String demandDir;
+ if (this is DirectoryInfo)
+ demandDir = Directory.GetDemandDir(FullPath, true);
+ else
+ demandDir = FullPath;
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, String.Empty, demandDir);
+ sourceState.EnsureState();
+#else
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand();
+#endif
+ return FullPath;
+ }
+ }
+
+ internal virtual String UnsafeGetFullName
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+ String demandDir;
+ if (this is DirectoryInfo)
+ demandDir = Directory.GetDemandDir(FullPath, true);
+ else
+ demandDir = FullPath;
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandDir).Demand();
+#endif
+ return FullPath;
+ }
+ }
+
+ public String Extension
+ {
+ get
+ {
+ // GetFullPathInternal would have already stripped out the terminating "." if present.
+ int length = FullPath.Length;
+ for (int i = length; --i >= 0;) {
+ char ch = FullPath[i];
+ if (ch == '.')
+ return FullPath.Substring(i, length - i);
+ if (ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar || ch == Path.VolumeSeparatorChar)
+ break;
+ }
+ return String.Empty;
+ }
+ }
+
+ // For files name of the file is returned, for directories the last directory in hierarchy is returned if possible,
+ // otherwise the fully qualified name s returned
+ public abstract String Name {
+ get;
+ }
+
+ // Whether a file/directory exists
+ public abstract bool Exists
+ {
+ get;
+ }
+
+ // Delete a file/directory
+ public abstract void Delete();
+
+ public DateTime CreationTime
+ {
+ get {
+ // depends on the security check in get_CreationTimeUtc
+ return CreationTimeUtc.ToLocalTime();
+ }
+
+ set {
+ CreationTimeUtc = value.ToUniversalTime();
+ }
+ }
+
+ [ComVisible(false)]
+ public DateTime CreationTimeUtc {
+ [System.Security.SecuritySafeCritical]
+ get {
+#if FEATURE_CORECLR
+ // get_CreationTime also depends on this security check
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath);
+ sourceState.EnsureState();
+#endif
+ if (_dataInitialised == -1) {
+ _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ Refresh();
+ }
+
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ __Error.WinIOError(_dataInitialised, DisplayPath);
+
+ long fileTime = ((long)_data.ftCreationTimeHigh << 32) | _data.ftCreationTimeLow;
+ return DateTime.FromFileTimeUtc(fileTime);
+
+ }
+
+ set {
+ if (this is DirectoryInfo)
+ Directory.SetCreationTimeUtc(FullPath,value);
+ else
+ File.SetCreationTimeUtc(FullPath,value);
+ _dataInitialised = -1;
+ }
+ }
+
+
+ public DateTime LastAccessTime
+ {
+ get {
+ // depends on the security check in get_LastAccessTimeUtc
+ return LastAccessTimeUtc.ToLocalTime();
+ }
+ set {
+ LastAccessTimeUtc = value.ToUniversalTime();
+ }
+ }
+
+ [ComVisible(false)]
+ public DateTime LastAccessTimeUtc {
+ [System.Security.SecuritySafeCritical]
+ get {
+#if FEATURE_CORECLR
+ // get_LastAccessTime also depends on this security check
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath);
+ sourceState.EnsureState();
+#endif
+ if (_dataInitialised == -1) {
+ _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ Refresh();
+ }
+
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ __Error.WinIOError(_dataInitialised, DisplayPath);
+
+ long fileTime = ((long)_data.ftLastAccessTimeHigh << 32) | _data.ftLastAccessTimeLow;
+ return DateTime.FromFileTimeUtc(fileTime);
+
+ }
+
+ set {
+ if (this is DirectoryInfo)
+ Directory.SetLastAccessTimeUtc(FullPath,value);
+ else
+ File.SetLastAccessTimeUtc(FullPath,value);
+ _dataInitialised = -1;
+ }
+ }
+
+ public DateTime LastWriteTime
+ {
+ get {
+ // depends on the security check in get_LastWriteTimeUtc
+ return LastWriteTimeUtc.ToLocalTime();
+ }
+
+ set {
+ LastWriteTimeUtc = value.ToUniversalTime();
+ }
+ }
+
+ [ComVisible(false)]
+ public DateTime LastWriteTimeUtc {
+ [System.Security.SecuritySafeCritical]
+ get {
+#if FEATURE_CORECLR
+ // get_LastWriteTime also depends on this security check
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath);
+ sourceState.EnsureState();
+#endif
+ if (_dataInitialised == -1) {
+ _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ Refresh();
+ }
+
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ __Error.WinIOError(_dataInitialised, DisplayPath);
+
+
+ long fileTime = ((long)_data.ftLastWriteTimeHigh << 32) | _data.ftLastWriteTimeLow;
+ return DateTime.FromFileTimeUtc(fileTime);
+ }
+
+ set {
+ if (this is DirectoryInfo)
+ Directory.SetLastWriteTimeUtc(FullPath,value);
+ else
+ File.SetLastWriteTimeUtc(FullPath,value);
+ _dataInitialised = -1;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Refresh()
+ {
+ _dataInitialised = File.FillAttributeInfo(FullPath, ref _data, false, false);
+ }
+
+ public FileAttributes Attributes {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+#if FEATURE_CORECLR
+ FileSecurityState sourceState = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, FullPath);
+ sourceState.EnsureState();
+#endif
+ if (_dataInitialised == -1) {
+ _data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA();
+ Refresh(); // Call refresh to intialise the data
+ }
+
+ if (_dataInitialised != 0) // Refresh was unable to initialise the data
+ __Error.WinIOError(_dataInitialised, DisplayPath);
+
+ return (FileAttributes) _data.fileAttributes;
+ }
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ set {
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.Write, FullPath).Demand();
+#endif
+ bool r = Win32Native.SetFileAttributes(FullPath, (int) value);
+ if (!r) {
+ int hr = Marshal.GetLastWin32Error();
+
+ if (hr==ERROR_INVALID_PARAMETER)
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileAttrs"));
+
+ // For whatever reason we are turning ERROR_ACCESS_DENIED into
+ // ArgumentException here (probably done for some 9x code path).
+ // We can't change this now but special casing the error message instead.
+ if (hr == ERROR_ACCESS_DENIED)
+ throw new ArgumentException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
+ __Error.WinIOError(hr, DisplayPath);
+ }
+ _dataInitialised = -1;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ComVisible(false)]
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, FullPath).Demand();
+#endif
+
+ info.AddValue("OriginalPath", OriginalPath, typeof(String));
+ info.AddValue("FullPath", FullPath, typeof(String));
+ }
+
+ internal String DisplayPath
+ {
+ get
+ {
+ return _displayPath;
+ }
+ set
+ {
+ _displayPath = value;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/IOException.cs b/src/mscorlib/src/System/IO/IOException.cs
new file mode 100644
index 0000000000..b3db033b0d
--- /dev/null
+++ b/src/mscorlib/src/System/IO/IOException.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception for a generic IO error.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class IOException : SystemException
+ {
+ // For debugging purposes, store the complete path in the IOException
+ // if possible. Don't give it back to users due to security concerns.
+ // Let the code that throws the exception worry about that. But we can
+ // at least assist people attached to the process with a managed
+ // debugger. Don't serialize it to avoid any security problems.
+ // This information isn't guaranteed to be correct, but is our second
+ // best effort at a file or directory involved, after the exception
+ // message.
+ [NonSerialized]
+ private String _maybeFullPath; // For debuggers on partial trust code
+
+ public IOException()
+ : base(Environment.GetResourceString("Arg_IOException")) {
+ SetErrorCode(__HResults.COR_E_IO);
+ }
+
+ public IOException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_IO);
+ }
+
+ public IOException(String message, int hresult)
+ : base(message) {
+ SetErrorCode(hresult);
+ }
+
+ // Adding this for debuggers when looking at exceptions in partial
+ // trust code that may not have interesting path information in
+ // the exception message.
+ internal IOException(String message, int hresult, String maybeFullPath)
+ : base(message) {
+ SetErrorCode(hresult);
+ _maybeFullPath = maybeFullPath;
+ }
+
+ public IOException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_IO);
+ }
+
+ protected IOException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/LongPathHelper.cs b/src/mscorlib/src/System/IO/LongPathHelper.cs
new file mode 100644
index 0000000000..9746fdc0aa
--- /dev/null
+++ b/src/mscorlib/src/System/IO/LongPathHelper.cs
@@ -0,0 +1,521 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Microsoft.Win32;
+
+namespace System.IO
+{
+ /// <summary>
+ /// Wrapper to help with path normalization.
+ /// </summary>
+ internal class LongPathHelper
+ {
+ // Can't be over 8.3 and be a short name
+ private const int MaxShortName = 12;
+
+ private const char LastAnsi = (char)255;
+ private const char Delete = (char)127;
+
+ [ThreadStatic]
+ private static StringBuffer t_fullPathBuffer;
+
+ /// <summary>
+ /// Normalize the given path.
+ /// </summary>
+ /// <remarks>
+ /// Normalizes via Win32 GetFullPathName(). It will also trim all "typical" whitespace at the end of the path (see s_trimEndChars). Will also trim initial
+ /// spaces if the path is determined to be rooted.
+ ///
+ /// Note that invalid characters will be checked after the path is normalized, which could remove bad characters. (C:\|\..\a.txt -- C:\a.txt)
+ /// </remarks>
+ /// <param name="path">Path to normalize</param>
+ /// <param name="checkInvalidCharacters">True to check for invalid characters</param>
+ /// <param name="expandShortPaths">Attempt to expand short paths if true</param>
+ /// <exception cref="ArgumentException">Thrown if the path is an illegal UNC (does not contain a full server/share) or contains illegal characters.</exception>
+ /// <exception cref="PathTooLongException">Thrown if the path or a path segment exceeds the filesystem limits.</exception>
+ /// <exception cref="FileNotFoundException">Thrown if Windows returns ERROR_FILE_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error)</exception>
+ /// <exception cref="DirectoryNotFoundException">Thrown if Windows returns ERROR_PATH_NOT_FOUND. (See Win32Marshal.GetExceptionForWin32Error)</exception>
+ /// <exception cref="UnauthorizedAccessException">Thrown if Windows returns ERROR_ACCESS_DENIED. (See Win32Marshal.GetExceptionForWin32Error)</exception>
+ /// <exception cref="IOException">Thrown if Windows returns an error that doesn't map to the above. (See Win32Marshal.GetExceptionForWin32Error)</exception>
+ /// <returns>Normalized path</returns>
+ [System.Security.SecurityCritical]
+ unsafe internal static string Normalize(string path, uint maxPathLength, bool checkInvalidCharacters, bool expandShortPaths)
+ {
+ // Get the full path
+ StringBuffer fullPath = t_fullPathBuffer ?? (t_fullPathBuffer = new StringBuffer(PathInternal.MaxShortPath));
+ try
+ {
+ GetFullPathName(path, fullPath);
+
+ // Trim whitespace off the end of the string. Win32 normalization trims only U+0020.
+ fullPath.TrimEnd(Path.TrimEndChars);
+
+ if (fullPath.Length >= maxPathLength)
+ {
+ // Fullpath is genuinely too long
+ throw new PathTooLongException();
+ }
+
+ // Checking path validity used to happen before getting the full path name. To avoid additional input allocation
+ // (to trim trailing whitespace) we now do it after the Win32 call. This will allow legitimate paths through that
+ // used to get kicked back (notably segments with invalid characters might get removed via "..").
+ //
+ // There is no way that GetLongPath can invalidate the path so we'll do this (cheaper) check before we attempt to
+ // expand short file names.
+
+ // Scan the path for:
+ //
+ // - Illegal path characters.
+ // - Invalid UNC paths like \\, \\server, \\server\.
+ // - Segments that are too long (over MaxComponentLength)
+
+ // As the path could be > 60K, we'll combine the validity scan. None of these checks are performed by the Win32
+ // GetFullPathName() API.
+
+ bool possibleShortPath = false;
+ bool foundTilde = false;
+
+ // We can get UNCs as device paths through this code (e.g. \\.\UNC\), we won't validate them as there isn't
+ // an easy way to normalize without extensive cost (we'd have to hunt down the canonical name for any device
+ // path that contains UNC or to see if the path was doing something like \\.\GLOBALROOT\Device\Mup\,
+ // \\.\GLOBAL\UNC\, \\.\GLOBALROOT\GLOBAL??\UNC\, etc.
+ bool specialPath = fullPath.Length > 1 && fullPath[0] == '\\' && fullPath[1] == '\\';
+ bool isDevice = PathInternal.IsDevice(fullPath);
+ bool possibleBadUnc = specialPath && !isDevice;
+ uint index = specialPath ? 2u : 0;
+ uint lastSeparator = specialPath ? 1u : 0;
+ uint segmentLength;
+ char* start = fullPath.CharPointer;
+ char current;
+
+ while (index < fullPath.Length)
+ {
+ current = start[index];
+
+ // Try to skip deeper analysis. '?' and higher are valid/ignorable except for '\', '|', and '~'
+ if (current < '?' || current == '\\' || current == '|' || current == '~')
+ {
+ switch (current)
+ {
+ case '|':
+ case '>':
+ case '<':
+ case '\"':
+ if (checkInvalidCharacters) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+ // No point in expanding a bad path
+ foundTilde = false;
+ break;
+ case '~':
+ foundTilde = true;
+ break;
+ case '\\':
+ segmentLength = index - lastSeparator - 1;
+ if (segmentLength > (uint)PathInternal.MaxComponentLength)
+ throw new PathTooLongException();
+ lastSeparator = index;
+
+ if (foundTilde)
+ {
+ if (segmentLength <= MaxShortName)
+ {
+ // Possibly a short path.
+ possibleShortPath = true;
+ }
+
+ foundTilde = false;
+ }
+
+ if (possibleBadUnc)
+ {
+ // If we're at the end of the path and this is the first separator, we're missing the share.
+ // Otherwise we're good, so ignore UNC tracking from here.
+ if (index == fullPath.Length - 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC"));
+ else
+ possibleBadUnc = false;
+ }
+
+ break;
+
+ default:
+ if (checkInvalidCharacters && current < ' ') throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+ break;
+ }
+ }
+
+ index++;
+ }
+
+ if (possibleBadUnc)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC"));
+
+ segmentLength = fullPath.Length - lastSeparator - 1;
+ if (segmentLength > (uint)PathInternal.MaxComponentLength)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ if (foundTilde && segmentLength <= MaxShortName)
+ possibleShortPath = true;
+
+ // Check for a short filename path and try and expand it. Technically you don't need to have a tilde for a short name, but
+ // this is how we've always done this. This expansion is costly so we'll continue to let other short paths slide.
+ if (expandShortPaths && possibleShortPath)
+ {
+ return TryExpandShortFileName(fullPath, originalPath: path);
+ }
+ else
+ {
+ if (fullPath.Length == (uint)path.Length && fullPath.StartsWith(path))
+ {
+ // If we have the exact same string we were passed in, don't bother to allocate another string from the StringBuilder.
+ return path;
+ }
+ else
+ {
+ return fullPath.ToString();
+ }
+ }
+ }
+ finally
+ {
+ // Clear the buffer
+ fullPath.Free();
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe private static void GetFullPathName(string path, StringBuffer fullPath)
+ {
+ // If the string starts with an extended prefix we would need to remove it from the path before we call GetFullPathName as
+ // it doesn't root extended paths correctly. We don't currently resolve extended paths, so we'll just assert here.
+ Contract.Assert(PathInternal.IsPartiallyQualified(path) || !PathInternal.IsExtended(path));
+
+ // Historically we would skip leading spaces *only* if the path started with a drive " C:" or a UNC " \\"
+ int startIndex = PathInternal.PathStartSkip(path);
+
+ fixed (char* pathStart = path)
+ {
+ uint result = 0;
+ while ((result = Win32Native.GetFullPathNameW(pathStart + startIndex, fullPath.CharCapacity, fullPath.GetHandle(), IntPtr.Zero)) > fullPath.CharCapacity)
+ {
+ // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity.
+ fullPath.EnsureCharCapacity(result);
+ }
+
+ if (result == 0)
+ {
+ // Failure, get the error and throw
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == 0)
+ errorCode = Win32Native.ERROR_BAD_PATHNAME;
+ __Error.WinIOError(errorCode, path);
+ }
+
+ fullPath.Length = result;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe internal static string GetLongPathName(StringBuffer path)
+ {
+ using (StringBuffer outputBuffer = new StringBuffer(path.Length))
+ {
+ uint result = 0;
+ while ((result = Win32Native.GetLongPathNameW(path.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity)) > outputBuffer.CharCapacity)
+ {
+ // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity.
+ outputBuffer.EnsureCharCapacity(result);
+ }
+
+ if (result == 0)
+ {
+ // Failure, get the error and throw
+ GetErrorAndThrow(path.ToString());
+ }
+
+ outputBuffer.Length = result;
+ return outputBuffer.ToString();
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe internal static string GetLongPathName(string path)
+ {
+ using (StringBuffer outputBuffer = new StringBuffer((uint)path.Length))
+ {
+ uint result = 0;
+ while ((result = Win32Native.GetLongPathNameW(path, outputBuffer.GetHandle(), outputBuffer.CharCapacity)) > outputBuffer.CharCapacity)
+ {
+ // Reported size (which does not include the null) is greater than the buffer size. Increase the capacity.
+ outputBuffer.EnsureCharCapacity(result);
+ }
+
+ if (result == 0)
+ {
+ // Failure, get the error and throw
+ GetErrorAndThrow(path);
+ }
+
+ outputBuffer.Length = result;
+ return outputBuffer.ToString();
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private static void GetErrorAndThrow(string path)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == 0)
+ errorCode = Win32Native.ERROR_BAD_PATHNAME;
+ __Error.WinIOError(errorCode, path);
+ }
+
+ // It is significantly more complicated to get the long path with minimal allocations if we're injecting the extended dos path prefix. The implicit version
+ // should match up with what is in CoreFx System.Runtime.Extensions.
+#if !FEATURE_IMPLICIT_LONGPATH
+ [System.Security.SecuritySafeCritical]
+ private unsafe static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath)
+ {
+ // We guarantee we'll expand short names for paths that only partially exist. As such, we need to find the part of the path that actually does exist. To
+ // avoid allocating like crazy we'll create only one input array and modify the contents with embedded nulls.
+
+ Contract.Assert(!PathInternal.IsPartiallyQualified(outputBuffer), "should have resolved by now");
+
+ using (StringBuffer inputBuffer = new StringBuffer(outputBuffer))
+ {
+ bool success = false;
+ uint lastIndex = outputBuffer.Length - 1;
+ uint foundIndex = lastIndex;
+ uint rootLength = PathInternal.GetRootLength(outputBuffer);
+
+ while (!success)
+ {
+ uint result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity);
+
+ // Replace any temporary null we added
+ if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\';
+
+ if (result == 0)
+ {
+ // Look to see if we couldn't find the file
+ int error = Marshal.GetLastWin32Error();
+ if (error != Win32Native.ERROR_FILE_NOT_FOUND && error != Win32Native.ERROR_PATH_NOT_FOUND)
+ {
+ // Some other failure, give up
+ break;
+ }
+
+ // We couldn't find the path at the given index, start looking further back in the string.
+ foundIndex--;
+
+ for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ;
+ if (foundIndex == rootLength)
+ {
+ // Can't trim the path back any further
+ break;
+ }
+ else
+ {
+ // Temporarily set a null in the string to get Windows to look further up the path
+ inputBuffer[foundIndex] = '\0';
+ }
+ }
+ else if (result > outputBuffer.CharCapacity)
+ {
+ // Not enough space. The result count for this API does not include the null terminator.
+ outputBuffer.EnsureCharCapacity(result);
+ }
+ else
+ {
+ // Found the path
+ success = true;
+ outputBuffer.Length = result;
+ if (foundIndex < lastIndex)
+ {
+ // It was a partial find, put the non-existant part of the path back
+ outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex);
+ }
+ }
+ }
+
+ StringBuffer bufferToUse = success ? outputBuffer : inputBuffer;
+
+ if (bufferToUse.SubstringEquals(originalPath))
+ {
+ // Use the original path to avoid allocating
+ return originalPath;
+ }
+
+ return bufferToUse.ToString();
+ }
+ }
+#else // !FEATURE_IMPLICIT_LONGPATH
+
+ private static uint GetInputBuffer(StringBuffer content, bool isDosUnc, out StringBuffer buffer)
+ {
+ uint length = content.Length;
+
+ length += isDosUnc
+ ? (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength
+ : PathInternal.DevicePrefixLength;
+
+ buffer = new StringBuffer(length);
+
+ if (isDosUnc)
+ {
+ // Put the extended UNC prefix (\\?\UNC\) in front of the path
+ buffer.CopyFrom(bufferIndex: 0, source: PathInternal.UncExtendedPathPrefix);
+
+ // Copy the source buffer over after the existing UNC prefix
+ content.CopyTo(
+ bufferIndex: PathInternal.UncPrefixLength,
+ destination: buffer,
+ destinationIndex: PathInternal.UncExtendedPrefixLength,
+ count: content.Length - PathInternal.UncPrefixLength);
+
+ // Return the prefix difference
+ return (uint)PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength;
+ }
+ else
+ {
+ uint prefixSize = (uint)PathInternal.ExtendedPathPrefix.Length;
+ buffer.CopyFrom(bufferIndex: 0, source: PathInternal.ExtendedPathPrefix);
+ content.CopyTo(bufferIndex: 0, destination: buffer, destinationIndex: prefixSize, count: content.Length);
+ return prefixSize;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static string TryExpandShortFileName(StringBuffer outputBuffer, string originalPath)
+ {
+ // We'll have one of a few cases by now (the normalized path will have already:
+ //
+ // 1. Dos path (C:\)
+ // 2. Dos UNC (\\Server\Share)
+ // 3. Dos device path (\\.\C:\, \\?\C:\)
+ //
+ // We want to put the extended syntax on the front if it doesn't already have it, which may mean switching from \\.\.
+
+ uint rootLength = PathInternal.GetRootLength(outputBuffer);
+ bool isDevice = PathInternal.IsDevice(outputBuffer);
+
+ StringBuffer inputBuffer = null;
+ bool isDosUnc = false;
+ uint rootDifference = 0;
+ bool wasDotDevice = false;
+
+ // Add the extended prefix before expanding to allow growth over MAX_PATH
+ if (isDevice)
+ {
+ // We have one of the following (\\?\ or \\.\)
+ // We will never get \??\ here as GetFullPathName() does not recognize \??\ and will return it as C:\??\ (or whatever the current drive is).
+ inputBuffer = new StringBuffer();
+ inputBuffer.Append(outputBuffer);
+
+ if (outputBuffer[2] == '.')
+ {
+ wasDotDevice = true;
+ inputBuffer[2] = '?';
+ }
+ }
+ else
+ {
+ // \\Server\Share, but not \\.\ or \\?\.
+ // We need to know this to be able to push \\?\UNC\ on if required
+ isDosUnc = outputBuffer.Length > 1 && outputBuffer[0] == '\\' && outputBuffer[1] == '\\' && !PathInternal.IsDevice(outputBuffer);
+ rootDifference = GetInputBuffer(outputBuffer, isDosUnc, out inputBuffer);
+ }
+
+ rootLength += rootDifference;
+ uint inputLength = inputBuffer.Length;
+
+ bool success = false;
+ uint foundIndex = inputBuffer.Length - 1;
+
+ while (!success)
+ {
+ uint result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity);
+
+ // Replace any temporary null we added
+ if (inputBuffer[foundIndex] == '\0') inputBuffer[foundIndex] = '\\';
+
+ if (result == 0)
+ {
+ // Look to see if we couldn't find the file
+ int error = Marshal.GetLastWin32Error();
+ if (error != Win32Native.ERROR_FILE_NOT_FOUND && error != Win32Native.ERROR_PATH_NOT_FOUND)
+ {
+ // Some other failure, give up
+ break;
+ }
+
+ // We couldn't find the path at the given index, start looking further back in the string.
+ foundIndex--;
+
+ for (; foundIndex > rootLength && inputBuffer[foundIndex] != '\\'; foundIndex--) ;
+ if (foundIndex == rootLength)
+ {
+ // Can't trim the path back any further
+ break;
+ }
+ else
+ {
+ // Temporarily set a null in the string to get Windows to look further up the path
+ inputBuffer[foundIndex] = '\0';
+ }
+ }
+ else if (result > outputBuffer.CharCapacity)
+ {
+ // Not enough space. The result count for this API does not include the null terminator.
+ outputBuffer.EnsureCharCapacity(result);
+ result = Win32Native.GetLongPathNameW(inputBuffer.GetHandle(), outputBuffer.GetHandle(), outputBuffer.CharCapacity);
+ }
+ else
+ {
+ // Found the path
+ success = true;
+ outputBuffer.Length = result;
+ if (foundIndex < inputLength - 1)
+ {
+ // It was a partial find, put the non-existent part of the path back
+ outputBuffer.Append(inputBuffer, foundIndex, inputBuffer.Length - foundIndex);
+ }
+ }
+ }
+
+ // Strip out the prefix and return the string
+ StringBuffer bufferToUse = success ? outputBuffer : inputBuffer;
+
+ // Switch back from \\?\ to \\.\ if necessary
+ if (wasDotDevice)
+ bufferToUse[2] = '.';
+
+ string returnValue = null;
+
+ int newLength = (int)(bufferToUse.Length - rootDifference);
+ if (isDosUnc)
+ {
+ // Need to go from \\?\UNC\ to \\?\UN\\
+ bufferToUse[PathInternal.UncExtendedPrefixLength - PathInternal.UncPrefixLength] = '\\';
+ }
+
+ // We now need to strip out any added characters at the front of the string
+ if (bufferToUse.SubstringEquals(originalPath, rootDifference, newLength))
+ {
+ // Use the original path to avoid allocating
+ returnValue = originalPath;
+ }
+ else
+ {
+ returnValue = bufferToUse.Substring(rootDifference, newLength);
+ }
+
+ inputBuffer.Dispose();
+ return returnValue;
+ }
+#endif // FEATURE_IMPLICIT_LONGPATH
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/IO/MemoryStream.cs b/src/mscorlib/src/System/IO/MemoryStream.cs
new file mode 100644
index 0000000000..edb583b9b5
--- /dev/null
+++ b/src/mscorlib/src/System/IO/MemoryStream.cs
@@ -0,0 +1,646 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A Stream whose backing store is memory. Great
+** for temporary storage without creating a temp file. Also
+** lets users expose a byte[] as a stream.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Security.Permissions;
+
+namespace System.IO {
+ // A MemoryStream represents a Stream in memory (ie, it has no backing store).
+ // This stream may reduce the need for temporary buffers and files in
+ // an application.
+ //
+ // There are two ways to create a MemoryStream. You can initialize one
+ // from an unsigned byte array, or you can create an empty one. Empty
+ // memory streams are resizable, while ones created with a byte array provide
+ // a stream "view" of the data.
+ [Serializable]
+ [ComVisible(true)]
+ public class MemoryStream : Stream
+ {
+ private byte[] _buffer; // Either allocated internally or externally.
+ private int _origin; // For user-provided arrays, start at this origin
+ private int _position; // read/write head.
+ [ContractPublicPropertyName("Length")]
+ private int _length; // Number of bytes within the memory stream
+ private int _capacity; // length of usable portion of buffer for stream
+ // Note that _capacity == _buffer.Length for non-user-provided byte[]'s
+
+ private bool _expandable; // User-provided buffers aren't expandable.
+ private bool _writable; // Can user write to this stream?
+ private bool _exposable; // Whether the array can be returned to the user.
+ private bool _isOpen; // Is this stream open or closed?
+
+ [NonSerialized]
+ private Task<int> _lastReadTask; // The last successful task returned from ReadAsync
+
+ private const int MemStreamMaxLength = Int32.MaxValue;
+
+ public MemoryStream()
+ : this(0) {
+ }
+
+ public MemoryStream(int capacity) {
+ if (capacity < 0) {
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ _buffer = capacity != 0 ? new byte[capacity] : EmptyArray<byte>.Value;
+ _capacity = capacity;
+ _expandable = true;
+ _writable = true;
+ _exposable = true;
+ _origin = 0; // Must be 0 for byte[]'s created by MemoryStream
+ _isOpen = true;
+ }
+
+ public MemoryStream(byte[] buffer)
+ : this(buffer, true) {
+ }
+
+ public MemoryStream(byte[] buffer, bool writable) {
+ if (buffer == null) throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ Contract.EndContractBlock();
+ _buffer = buffer;
+ _length = _capacity = buffer.Length;
+ _writable = writable;
+ _exposable = false;
+ _origin = 0;
+ _isOpen = true;
+ }
+
+ public MemoryStream(byte[] buffer, int index, int count)
+ : this(buffer, index, count, true, false) {
+ }
+
+ public MemoryStream(byte[] buffer, int index, int count, bool writable)
+ : this(buffer, index, count, writable, false) {
+ }
+
+ public MemoryStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ _buffer = buffer;
+ _origin = _position = index;
+ _length = _capacity = index + count;
+ _writable = writable;
+ _exposable = publiclyVisible; // Can TryGetBuffer/GetBuffer return the array?
+ _expandable = false;
+ _isOpen = true;
+ }
+
+ public override bool CanRead {
+ [Pure]
+ get { return _isOpen; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _isOpen; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _writable; }
+ }
+
+ private void EnsureWriteable() {
+ if (!CanWrite) __Error.WriteNotSupported();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ try {
+ if (disposing) {
+ _isOpen = false;
+ _writable = false;
+ _expandable = false;
+ // Don't set buffer to null - allow TryGetBuffer, GetBuffer & ToArray to work.
+ _lastReadTask = null;
+ }
+ }
+ finally {
+ // Call base.Close() to cleanup async IO resources
+ base.Dispose(disposing);
+ }
+ }
+
+ // returns a bool saying whether we allocated a new array.
+ private bool EnsureCapacity(int value) {
+ // Check for overflow
+ if (value < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_StreamTooLong"));
+ if (value > _capacity) {
+ int newCapacity = value;
+ if (newCapacity < 256)
+ newCapacity = 256;
+ // We are ok with this overflowing since the next statement will deal
+ // with the cases where _capacity*2 overflows.
+ if (newCapacity < _capacity * 2)
+ newCapacity = _capacity * 2;
+ // We want to expand the array up to Array.MaxArrayLengthOneDimensional
+ // And we want to give the user the value that they asked for
+ if ((uint)(_capacity * 2) > Array.MaxByteArrayLength)
+ newCapacity = value > Array.MaxByteArrayLength ? value : Array.MaxByteArrayLength;
+
+ Capacity = newCapacity;
+ return true;
+ }
+ return false;
+ }
+
+ public override void Flush() {
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task FlushAsync(CancellationToken cancellationToken) {
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ try {
+
+ Flush();
+ return Task.CompletedTask;
+
+ } catch(Exception ex) {
+
+ return Task.FromException(ex);
+ }
+ }
+
+
+ public virtual byte[] GetBuffer() {
+ if (!_exposable)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_MemStreamBuffer"));
+ return _buffer;
+ }
+
+ public virtual bool TryGetBuffer(out ArraySegment<byte> buffer) {
+ if (!_exposable) {
+ buffer = default(ArraySegment<byte>);
+ return false;
+ }
+
+ buffer = new ArraySegment<byte>(_buffer, offset:_origin, count:(_length - _origin));
+ return true;
+ }
+
+ // -------------- PERF: Internal functions for fast direct access of MemoryStream buffer (cf. BinaryReader for usage) ---------------
+
+ // PERF: Internal sibling of GetBuffer, always returns a buffer (cf. GetBuffer())
+ internal byte[] InternalGetBuffer() {
+ return _buffer;
+ }
+
+ // PERF: Get origin and length - used in ResourceWriter.
+ [FriendAccessAllowed]
+ internal void InternalGetOriginAndLength(out int origin, out int length)
+ {
+ if (!_isOpen) __Error.StreamIsClosed();
+ origin = _origin;
+ length = _length;
+ }
+
+ // PERF: True cursor position, we don't need _origin for direct access
+ internal int InternalGetPosition() {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return _position;
+ }
+
+ // PERF: Takes out Int32 as fast as possible
+ internal int InternalReadInt32() {
+ if (!_isOpen)
+ __Error.StreamIsClosed();
+
+ int pos = (_position += 4); // use temp to avoid a race condition
+ if (pos > _length)
+ {
+ _position = _length;
+ __Error.EndOfFile();
+ }
+ return (int)(_buffer[pos-4] | _buffer[pos-3] << 8 | _buffer[pos-2] << 16 | _buffer[pos-1] << 24);
+ }
+
+ // PERF: Get actual length of bytes available for read; do sanity checks; shift position - i.e. everything except actual copying bytes
+ internal int InternalEmulateRead(int count) {
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ int n = _length - _position;
+ if (n > count) n = count;
+ if (n < 0) n = 0;
+
+ Contract.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1.
+ _position += n;
+ return n;
+ }
+
+ // Gets & sets the capacity (number of bytes allocated) for this stream.
+ // The capacity cannot be set to a value less than the current length
+ // of the stream.
+ //
+ public virtual int Capacity {
+ get {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return _capacity - _origin;
+ }
+ set {
+ // Only update the capacity if the MS is expandable and the value is different than the current capacity.
+ // Special behavior if the MS isn't expandable: we don't throw if value is the same as the current capacity
+ if (value < Length) throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ Contract.Ensures(_capacity - _origin == value);
+ Contract.EndContractBlock();
+
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!_expandable && (value != Capacity)) __Error.MemoryStreamNotExpandable();
+
+ // MemoryStream has this invariant: _origin > 0 => !expandable (see ctors)
+ if (_expandable && value != _capacity) {
+ if (value > 0) {
+ byte[] newBuffer = new byte[value];
+ if (_length > 0) Buffer.InternalBlockCopy(_buffer, 0, newBuffer, 0, _length);
+ _buffer = newBuffer;
+ }
+ else {
+ _buffer = null;
+ }
+ _capacity = value;
+ }
+ }
+ }
+
+ public override long Length {
+ get {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return _length - _origin;
+ }
+ }
+
+ public override long Position {
+ get {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return _position - _origin;
+ }
+ set {
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.Ensures(Position == value);
+ Contract.EndContractBlock();
+
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ if (value > MemStreamMaxLength)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength"));
+ _position = _origin + (int)value;
+ }
+ }
+
+ public override int Read([In, Out] byte[] buffer, int offset, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ int n = _length - _position;
+ if (n > count) n = count;
+ if (n <= 0)
+ return 0;
+
+ Contract.Assert(_position + n >= 0, "_position + n >= 0"); // len is less than 2^31 -1.
+
+ if (n <= 8)
+ {
+ int byteCount = n;
+ while (--byteCount >= 0)
+ buffer[offset + byteCount] = _buffer[_position + byteCount];
+ }
+ else
+ Buffer.InternalBlockCopy(_buffer, _position, buffer, offset, n);
+ _position += n;
+
+ return n;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // contract validation copied from Read(...)
+
+ // If cancellation was requested, bail early
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<int>(cancellationToken);
+
+ try
+ {
+ int n = Read(buffer, offset, count);
+ var t = _lastReadTask;
+ Contract.Assert(t == null || t.Status == TaskStatus.RanToCompletion,
+ "Expected that a stored last task completed successfully");
+ return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult<int>(n));
+ }
+ catch (OperationCanceledException oce)
+ {
+ return Task.FromCancellation<int>(oce);
+ }
+ catch (Exception exception)
+ {
+ return Task.FromException<int>(exception);
+ }
+ }
+
+
+ public override int ReadByte() {
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ if (_position >= _length) return -1;
+
+ return _buffer[_position++];
+ }
+
+
+ public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) {
+
+ // This implementation offers beter performance compared to the base class version.
+
+ // The parameter checks must be in sync with the base version:
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+
+ if (!CanRead && !CanWrite)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+
+ if (!destination.CanRead && !destination.CanWrite)
+ throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+
+ if (!CanRead)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
+
+ if (!destination.CanWrite)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
+
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() or Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read/Write) when we are not sure.
+ if (this.GetType() != typeof(MemoryStream))
+ return base.CopyToAsync(destination, bufferSize, cancellationToken);
+
+ // If cancelled - return fast:
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ // Avoid copying data from this buffer into a temp buffer:
+ // (require that InternalEmulateRead does not throw,
+ // otherwise it needs to be wrapped into try-catch-Task.FromException like memStrDest.Write below)
+
+ Int32 pos = _position;
+ Int32 n = InternalEmulateRead(_length - _position);
+
+ // If destination is not a memory stream, write there asynchronously:
+ MemoryStream memStrDest = destination as MemoryStream;
+ if (memStrDest == null)
+ return destination.WriteAsync(_buffer, pos, n, cancellationToken);
+
+ try {
+
+ // If destination is a MemoryStream, CopyTo synchronously:
+ memStrDest.Write(_buffer, pos, n);
+ return Task.CompletedTask;
+
+ } catch(Exception ex) {
+ return Task.FromException(ex);
+ }
+ }
+
+
+ public override long Seek(long offset, SeekOrigin loc) {
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ if (offset > MemStreamMaxLength)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_StreamLength"));
+ switch(loc) {
+ case SeekOrigin.Begin: {
+ int tempPosition = unchecked(_origin + (int)offset);
+ if (offset < 0 || tempPosition < _origin)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ _position = tempPosition;
+ break;
+ }
+ case SeekOrigin.Current: {
+ int tempPosition = unchecked(_position + (int)offset);
+ if (unchecked(_position + offset) < _origin || tempPosition < _origin)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ _position = tempPosition;
+ break;
+ }
+ case SeekOrigin.End: {
+ int tempPosition = unchecked(_length + (int)offset);
+ if ( unchecked(_length + offset) < _origin || tempPosition < _origin )
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ _position = tempPosition;
+ break;
+ }
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin"));
+ }
+
+ Contract.Assert(_position >= 0, "_position >= 0");
+ return _position;
+ }
+
+ // Sets the length of the stream to a given value. The new
+ // value must be nonnegative and less than the space remaining in
+ // the array, Int32.MaxValue - origin
+ // Origin is 0 in all cases other than a MemoryStream created on
+ // top of an existing array and a specific starting offset was passed
+ // into the MemoryStream constructor. The upper bounds prevents any
+ // situations where a stream may be created on top of an array then
+ // the stream is made longer than the maximum possible length of the
+ // array (Int32.MaxValue).
+ //
+ public override void SetLength(long value) {
+ if (value < 0 || value > Int32.MaxValue) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength"));
+ }
+ Contract.Ensures(_length - _origin == value);
+ Contract.EndContractBlock();
+ EnsureWriteable();
+
+ // Origin wasn't publicly exposed above.
+ Contract.Assert(MemStreamMaxLength == Int32.MaxValue); // Check parameter validation logic in this method if this fails.
+ if (value > (Int32.MaxValue - _origin)) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength"));
+ }
+
+ int newLength = _origin + (int)value;
+ bool allocatedNewArray = EnsureCapacity(newLength);
+ if (!allocatedNewArray && newLength > _length)
+ Array.Clear(_buffer, _length, newLength - _length);
+ _length = newLength;
+ if (_position > newLength) _position = newLength;
+
+ }
+
+ public virtual byte[] ToArray() {
+ BCLDebug.Perf(_exposable, "MemoryStream::GetBuffer will let you avoid a copy.");
+ byte[] copy = new byte[_length - _origin];
+ Buffer.InternalBlockCopy(_buffer, _origin, copy, 0, _length - _origin);
+ return copy;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (!_isOpen) __Error.StreamIsClosed();
+ EnsureWriteable();
+
+ int i = _position + count;
+ // Check for overflow
+ if (i < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_StreamTooLong"));
+
+ if (i > _length) {
+ bool mustZero = _position > _length;
+ if (i > _capacity) {
+ bool allocatedNewArray = EnsureCapacity(i);
+ if (allocatedNewArray)
+ mustZero = false;
+ }
+ if (mustZero)
+ Array.Clear(_buffer, _length, i - _length);
+ _length = i;
+ }
+ if ((count <= 8) && (buffer != _buffer))
+ {
+ int byteCount = count;
+ while (--byteCount >= 0)
+ _buffer[_position + byteCount] = buffer[offset + byteCount];
+ }
+ else
+ Buffer.InternalBlockCopy(buffer, offset, _buffer, _position, count);
+ _position = i;
+
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // contract validation copied from Write(...)
+
+ // If cancellation is already requested, bail early
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ try
+ {
+ Write(buffer, offset, count);
+ return Task.CompletedTask;
+ }
+ catch (OperationCanceledException oce)
+ {
+ return Task.FromCancellation<VoidTaskResult>(oce);
+ }
+ catch (Exception exception)
+ {
+ return Task.FromException(exception);
+ }
+ }
+
+ public override void WriteByte(byte value) {
+ if (!_isOpen) __Error.StreamIsClosed();
+ EnsureWriteable();
+
+ if (_position >= _length) {
+ int newLength = _position + 1;
+ bool mustZero = _position > _length;
+ if (newLength >= _capacity) {
+ bool allocatedNewArray = EnsureCapacity(newLength);
+ if (allocatedNewArray)
+ mustZero = false;
+ }
+ if (mustZero)
+ Array.Clear(_buffer, _length, _position - _length);
+ _length = newLength;
+ }
+ _buffer[_position++] = value;
+
+ }
+
+ // Writes this MemoryStream to another stream.
+ public virtual void WriteTo(Stream stream) {
+ if (stream==null)
+ throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream"));
+ Contract.EndContractBlock();
+
+ if (!_isOpen) __Error.StreamIsClosed();
+ stream.Write(_buffer, _origin, _length - _origin);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/Path.cs b/src/mscorlib/src/System/IO/Path.cs
new file mode 100644
index 0000000000..4f7993633b
--- /dev/null
+++ b/src/mscorlib/src/System/IO/Path.cs
@@ -0,0 +1,1435 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of path manipulation methods.
+**
+**
+===========================================================*/
+
+using System;
+using System.Security.Permissions;
+using Win32Native = Microsoft.Win32.Win32Native;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Security;
+#if FEATURE_LEGACYSURFACE
+using System.Security.Cryptography;
+#endif
+using System.Runtime.CompilerServices;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ // Provides methods for processing directory strings in an ideally
+ // cross-platform manner. Most of the methods don't do a complete
+ // full parsing (such as examining a UNC hostname), but they will
+ // handle most string operations.
+ [ComVisible(true)]
+ public static class Path
+ {
+ // Platform specific directory separator character. This is backslash
+ // ('\') on Windows and slash ('/') on Unix.
+ //
+#if !PLATFORM_UNIX
+ public static readonly char DirectorySeparatorChar = '\\';
+ internal const string DirectorySeparatorCharAsString = "\\";
+#else
+ public static readonly char DirectorySeparatorChar = '/';
+ internal const string DirectorySeparatorCharAsString = "/";
+#endif // !PLATFORM_UNIX
+
+ // Platform specific alternate directory separator character.
+ // There is only one directory separator char on Unix,
+ // so the same definition is used for both Unix and Windows.
+ 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".
+ //
+#if !PLATFORM_UNIX
+ public static readonly char VolumeSeparatorChar = ':';
+#else
+ public static readonly char VolumeSeparatorChar = '/';
+#endif // !PLATFORM_UNIX
+
+ // 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
+ // is legal in a path name).
+ // Note: This list is duplicated in CheckInvalidPathChars
+ [Obsolete("Please use GetInvalidPathChars or GetInvalidFileNameChars instead.")]
+#if !PLATFORM_UNIX
+ 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 };
+#else
+ public static readonly char[] InvalidPathChars = { '\0' };
+#endif // !PLATFORM_UNIX
+
+ // 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)0x09, // Horizontal tab
+ (char)0x0A, // Line feed
+ (char)0x0B, // Vertical tab
+ (char)0x0C, // Form feed
+ (char)0x0D, // Carriage return
+ (char)0x20, // Space
+ (char)0x85, // Next line
+ (char)0xA0 // Non breaking space
+ };
+
+#if !PLATFORM_UNIX
+ private static readonly char[] RealInvalidPathChars = PathInternal.InvalidPathChars;
+
+ private static readonly char[] InvalidFileNameChars = { '\"', '<', '>', '|', '\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, ':', '*', '?', '\\', '/' };
+#else
+ private static readonly char[] RealInvalidPathChars = { '\0' };
+
+ private static readonly char[] InvalidFileNameChars = { '\0', '/' };
+#endif // !PLATFORM_UNIX
+
+#if !PLATFORM_UNIX
+ public static readonly char PathSeparator = ';';
+#else
+ public static readonly char PathSeparator = ':';
+#endif // !PLATFORM_UNIX
+
+
+ // 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 = PathInternal.MaxShortPath;
+
+ internal static readonly int MaxPathComponentLength = 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
+
+ // Changes the extension of a file path. The path parameter
+ // specifies a file path, and the extension parameter
+ // specifies a file extension (with a leading period, such as
+ // ".exe" or ".cs").
+ //
+ // The function returns a file path with the same root, directory, and base
+ // name parts as path, but with the file extension changed to
+ // the specified extension. If path is null, the function
+ // returns null. If path does not contain a file extension,
+ // the new file extension is appended to the path. If extension
+ // is null, any exsiting extension is removed from path.
+ //
+ public static String ChangeExtension(String path, String extension) {
+ if (path != null) {
+ CheckInvalidPathChars(path);
+
+ String s = path;
+ for (int i = path.Length; --i >= 0;) {
+ char ch = path[i];
+ if (ch == '.') {
+ s = path.Substring(0, i);
+ break;
+ }
+ if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) break;
+ }
+ if (extension != null && path.Length != 0) {
+ if (extension.Length == 0 || extension[0] != '.') {
+ s = s + ".";
+ }
+ s = s + extension;
+ }
+ return s;
+ }
+ 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
+ // backslash ("\") in the file path. The returned value is null if the file
+ // path is null or if the file path denotes a root (such as "\", "C:", or
+ // "\\server\share").
+ public static String GetDirectoryName(String path)
+ {
+ return GetDirectoryNameInternal(path);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static string GetDirectoryNameInternal(string path)
+ {
+ if (path != null)
+ {
+ CheckInvalidPathChars(path);
+
+ // 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:
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.UseLegacyPathHandling
+#else
+ false
+#endif
+ );
+
+ // 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 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 = RemoveLongPathPrefix(path);
+
+ // FileIOPermission cannot handle paths that contain ? or *
+ // So we only pass to FileIOPermission the text up to them.
+ int pos = 0;
+ while (pos < tempPath.Length && (tempPath[pos] != '?' && tempPath[pos] != '*'))
+ pos++;
+
+ // GetFullPath will Demand that we have the PathDiscovery FileIOPermission and thus throw
+ // SecurityException if we don't.
+ // 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)
+ 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);
+ }
+ }
+ catch (PathTooLongException) { }
+ catch (NotSupportedException) { } // Security can throw this on "c:\foo:"
+ catch (IOException) { }
+ catch (ArgumentException) { } // The normalizePath with fullCheck will throw this for file: and http:
+ }
+
+ path = normalizedPath;
+
+ int root = GetRootLength(path);
+ int i = path.Length;
+ if (i > root)
+ {
+ i = path.Length;
+ if (i == root) return null;
+ while (i > root && path[--i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar);
+ return path.Substring(0, i);
+ }
+ }
+ return null;
+ }
+
+ // 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)
+ {
+ CheckInvalidPathChars(path);
+
+#if !PLATFORM_UNIX && FEATURE_PATHCOMPAT
+ if (AppContextSwitches.UseLegacyPathHandling)
+ {
+ int i = 0;
+ int length = path.Length;
+
+ if (length >= 1 && (IsDirectorySeparator(path[0])))
+ {
+ // handles UNC names and directories off current drive's root.
+ i = 1;
+ if (length >= 2 && (IsDirectorySeparator(path[1])))
+ {
+ i = 2;
+ int n = 2;
+ while (i < length && ((path[i] != DirectorySeparatorChar && path[i] != AltDirectorySeparatorChar) || --n > 0)) i++;
+ }
+ }
+ else if (length >= 2 && path[1] == VolumeSeparatorChar)
+ {
+ // handles A:\foo.
+ i = 2;
+ if (length >= 3 && (IsDirectorySeparator(path[2]))) i++;
+ }
+ return i;
+ }
+ else
+#endif // !PLATFORM_UNIX && FEATURE_PATHCOMPAT
+ {
+ return PathInternal.GetRootLength(path);
+ }
+ }
+
+ internal static bool IsDirectorySeparator(char c) {
+ return (c==DirectorySeparatorChar || c == AltDirectorySeparatorChar);
+ }
+
+ public static char[] GetInvalidPathChars()
+ {
+ return (char[]) RealInvalidPathChars.Clone();
+ }
+
+ public static char[] GetInvalidFileNameChars()
+ {
+ return (char[]) InvalidFileNameChars.Clone();
+ }
+
+ // Returns the extension of the given path. The returned value includes the
+ // period (".") character of the extension except when you have a terminal period when you get String.Empty, such as ".exe" or
+ // ".cpp". The returned value is null if the given path is
+ // null or if the given path does not include an extension.
+ //
+ [Pure]
+ public static String GetExtension(String path) {
+ if (path==null)
+ return null;
+
+ CheckInvalidPathChars(path);
+ int length = path.Length;
+ for (int i = length; --i >= 0;) {
+ char ch = path[i];
+ if (ch == '.')
+ {
+ if (i != length - 1)
+ return path.Substring(i, length - i);
+ else
+ return String.Empty;
+ }
+ if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar)
+ break;
+ }
+ return String.Empty;
+ }
+
+ // Expands the given path to a fully qualified path. The resulting string
+ // consists of a drive letter, a colon, and a root relative path. This
+ // function does not verify that the resulting path
+ // refers to an existing file or directory on the associated volume.
+ [Pure]
+ [System.Security.SecuritySafeCritical]
+ public static String GetFullPath(String path) {
+ String fullPath = GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.PathDiscovery, path, fullPath);
+ state.EnsureState();
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, fullPath, false, false);
+#endif
+ return fullPath;
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String UnsafeGetFullPath(String path)
+ {
+ String fullPath = GetFullPathInternal(path);
+#if !FEATURE_CORECLR
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.PathDiscovery, fullPath, false, false);
+#endif
+ return fullPath;
+ }
+
+ // This method is package access to let us quickly get a string name
+ // while avoiding a security check. This also serves a slightly
+ // different purpose - when we open a file, we need to resolve the
+ // path into a fully qualified, non-relative path name. This
+ // method does that, finding the current drive &; directory. But
+ // as long as we don't return this info to the user, we're good. However,
+ // the public GetFullPath does need to do a security check.
+ internal static string GetFullPathInternal(string path)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+ Contract.EndContractBlock();
+
+ string newPath = NormalizePath(path, fullCheck: true);
+ return newPath;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static string NormalizePath(string path, bool fullCheck)
+ {
+ return NormalizePath(path, fullCheck,
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath :
+#endif
+ PathInternal.MaxLongPath);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static string NormalizePath(string path, bool fullCheck, bool expandShortPaths)
+ {
+ return NormalizePath(path, fullCheck,
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath :
+#endif
+ PathInternal.MaxLongPath,
+ expandShortPaths);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static string NormalizePath(string path, bool fullCheck, int maxPathLength)
+ {
+ return NormalizePath(path, fullCheck, maxPathLength, expandShortPaths: true);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static string NormalizePath(string path, bool fullCheck, int maxPathLength, bool expandShortPaths)
+ {
+#if FEATURE_PATHCOMPAT
+ if (AppContextSwitches.UseLegacyPathHandling)
+ {
+ return LegacyNormalizePath(path, fullCheck, maxPathLength, expandShortPaths);
+ }
+ else
+#endif // FEATURE_APPCOMPAT
+ {
+ 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 !PLATFORM_UNIX
+ 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.
+ }
+ }
+#endif
+
+ 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");
+
+ // 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"));
+
+#if !PLATFORM_UNIX
+ // 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);
+#else
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ // Expand with current directory if necessary
+ if (!IsPathRooted(path))
+ path = Combine(Directory.GetCurrentDirectory(), path);
+
+ // We would ideally use realpath to do this, but it resolves symlinks, requires that the file actually exist,
+ // and turns it into a full path, which we only want if fullCheck is true.
+ string collapsedString = PathInternal.RemoveRelativeSegments(path);
+
+ if (collapsedString.Length > maxPathLength)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ return collapsedString.Length == 0 ? "/" : collapsedString;
+#endif // PLATFORM_UNIX
+ }
+
+#if FEATURE_PATHCOMPAT
+ [System.Security.SecurityCritical] // auto-generated
+ 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.
+ if (PathInternal.AnyPathHasIllegalCharacters(path))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPathChars"));
+ }
+
+ int index = 0;
+ // We prefer to allocate on the stack for workingset/perf gain. If the
+ // starting path is less than MaxPath then we can stackalloc; otherwise we'll
+ // use a StringBuilder (PathHelper does this under the hood). The latter may
+ // happen in 2 cases:
+ // 1. Starting path is greater than MaxPath but it normalizes down to MaxPath.
+ // This is relevant for paths containing escape sequences. In this case, we
+ // attempt to normalize down to MaxPath, but the caller pays a perf penalty
+ // since StringBuilder is used.
+ // 2. IsolatedStorage, which supports paths longer than MaxPath (value given
+ // by maxPathLength.
+ PathHelper newBuffer;
+ if (path.Length + 1 <= MaxPath) {
+ char* m_arrayPtr = stackalloc char[MaxPath];
+ newBuffer = new PathHelper(m_arrayPtr, MaxPath);
+ } else {
+ newBuffer = new PathHelper(path.Length + Path.MaxPath, maxPathLength);
+ }
+
+ uint numSpaces = 0;
+ uint numDots = 0;
+ bool fixupDirectorySeparator = false;
+ // Number of significant chars other than potentially suppressible
+ // dots and spaces since the last directory or volume separator char
+ uint numSigChars = 0;
+ int lastSigChar = -1; // Index of last significant character.
+ // Whether this segment of the path (not the complete path) started
+ // with a volume separator char. Reject "c:...".
+ bool startedWithVolumeSeparator = false;
+ bool firstSegment = true;
+ int lastDirectorySeparatorPos = 0;
+
+#if !PLATFORM_UNIX
+ bool mightBeShortFileName = false;
+
+ // LEGACY: This code is here for backwards compatibility reasons. It
+ // ensures that \\foo.cs\bar.cs stays \\foo.cs\bar.cs instead of being
+ // turned into \foo.cs\bar.cs.
+ if (path.Length > 0 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar)) {
+ newBuffer.Append('\\');
+ index++;
+ lastSigChar = 0;
+ }
+#endif
+
+ // Normalize the string, stripping out redundant dots, spaces, and
+ // slashes.
+ while (index < path.Length) {
+ char currentChar = path[index];
+
+ // We handle both directory separators and dots specially. For
+ // directory separators, we consume consecutive appearances.
+ // For dots, we consume all dots beyond the second in
+ // succession. All other characters are added as is. In
+ // addition we consume all spaces after the last other char
+ // in a directory name up until the directory separator.
+
+ if (currentChar == DirectorySeparatorChar || currentChar == AltDirectorySeparatorChar) {
+ // If we have a path like "123.../foo", remove the trailing dots.
+ // However, if we found "c:\temp\..\bar" or "c:\temp\...\bar", don't.
+ // Also remove trailing spaces from both files & directory names.
+ // This was agreed on with the OS team to fix undeletable directory
+ // names ending in spaces.
+
+ // If we saw a '\' as the previous last significant character and
+ // are simply going to write out dots, suppress them.
+ // If we only contain dots and slashes though, only allow
+ // a string like [dot]+ [space]*. Ignore everything else.
+ // Legal: "\.. \", "\...\", "\. \"
+ // Illegal: "\.. .\", "\. .\", "\ .\"
+ if (numSigChars == 0) {
+ // Dot and space handling
+ if (numDots > 0) {
+ // Look for ".[space]*" or "..[space]*"
+ int start = lastSigChar + 1;
+ if (path[start] != '.')
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ // Only allow "[dot]+[space]*", and normalize the
+ // legal ones to "." or ".."
+ if (numDots >= 2) {
+ // Reject "C:..."
+ if (startedWithVolumeSeparator && numDots > 2)
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ if (path[start + 1] == '.') {
+ // Search for a space in the middle of the
+ // dots and throw
+ for(int i=start + 2; i < start + numDots; i++) {
+ if (path[i] != '.')
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+ }
+
+ numDots = 2;
+ }
+ else {
+ if (numDots > 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+ numDots = 1;
+ }
+ }
+
+ if (numDots == 2) {
+ newBuffer.Append('.');
+ }
+
+ newBuffer.Append('.');
+ fixupDirectorySeparator = false;
+
+ // Continue in this case, potentially writing out '\'.
+ }
+
+ if (numSpaces > 0 && firstSegment) {
+ // Handle strings like " \\server\share".
+ if (index + 1 < path.Length &&
+ (path[index + 1] == DirectorySeparatorChar || path[index + 1] == AltDirectorySeparatorChar))
+ {
+ newBuffer.Append(DirectorySeparatorChar);
+ }
+ }
+ }
+ numDots = 0;
+ numSpaces = 0; // Suppress trailing spaces
+
+ if (!fixupDirectorySeparator) {
+ fixupDirectorySeparator = true;
+ newBuffer.Append(DirectorySeparatorChar);
+ }
+ numSigChars = 0;
+ lastSigChar = index;
+ startedWithVolumeSeparator = false;
+ firstSegment = false;
+
+#if !PLATFORM_UNIX
+ // For short file names, we must try to expand each of them as
+ // soon as possible. We need to allow people to specify a file
+ // name that doesn't exist using a path with short file names
+ // in it, such as this for a temp file we're trying to create:
+ // C:\DOCUME~1\USERNA~1.RED\LOCALS~1\Temp\bg3ylpzp
+ // We could try doing this afterwards piece by piece, but it's
+ // probably a lot simpler to do it here.
+ if (mightBeShortFileName) {
+ newBuffer.TryExpandShortFileName();
+ mightBeShortFileName = false;
+ }
+#endif
+ int thisPos = newBuffer.Length - 1;
+ if (thisPos - lastDirectorySeparatorPos > MaxPathComponentLength)
+ {
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ }
+ lastDirectorySeparatorPos = thisPos;
+ } // if (Found directory separator)
+ else if (currentChar == '.') {
+ // Reduce only multiple .'s only after slash to 2 dots. For
+ // instance a...b is a valid file name.
+ numDots++;
+ // Don't flush out non-terminal spaces here, because they may in
+ // the end not be significant. Turn "c:\ . .\foo" -> "c:\foo"
+ // which is the conclusion of removing trailing dots & spaces,
+ // as well as folding multiple '\' characters.
+ }
+ else if (currentChar == ' ') {
+ numSpaces++;
+ }
+ else { // Normal character logic
+#if !PLATFORM_UNIX
+ if (currentChar == '~' && expandShortPaths)
+ mightBeShortFileName = true;
+#endif
+
+ fixupDirectorySeparator = false;
+
+#if !PLATFORM_UNIX
+ // To reject strings like "C:...\foo" and "C :\foo"
+ if (firstSegment && currentChar == VolumeSeparatorChar) {
+ // Only accept "C:", not "c :" or ":"
+ // Get a drive letter or ' ' if index is 0.
+ char driveLetter = (index > 0) ? path[index-1] : ' ';
+ bool validPath = ((numDots == 0) && (numSigChars >= 1) && (driveLetter != ' '));
+ if (!validPath)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ startedWithVolumeSeparator = true;
+ // We need special logic to make " c:" work, we should not fix paths like " foo::$DATA"
+ if (numSigChars > 1) { // Common case, simply do nothing
+ int spaceCount = 0; // How many spaces did we write out, numSpaces has already been reset.
+ while((spaceCount < newBuffer.Length) && newBuffer[spaceCount] == ' ')
+ spaceCount++;
+ if (numSigChars - spaceCount == 1) {
+ //Safe to update stack ptr directly
+ newBuffer.Length = 0;
+ newBuffer.Append(driveLetter); // Overwrite spaces, we need a special case to not break " foo" as a relative path.
+ }
+ }
+ numSigChars = 0;
+ }
+ else
+#endif // !PLATFORM_UNIX
+ {
+ numSigChars += 1 + numDots + numSpaces;
+ }
+
+ // Copy any spaces & dots since the last significant character
+ // to here. Note we only counted the number of dots & spaces,
+ // and don't know what order they're in. Hence the copy.
+ if (numDots > 0 || numSpaces > 0) {
+ int numCharsToCopy = (lastSigChar >= 0) ? index - lastSigChar - 1 : index;
+ if (numCharsToCopy > 0) {
+ for (int i=0; i<numCharsToCopy; i++) {
+ newBuffer.Append(path[lastSigChar + 1 + i]);
+ }
+ }
+ numDots = 0;
+ numSpaces = 0;
+ }
+
+ newBuffer.Append(currentChar);
+ lastSigChar = index;
+ }
+
+ index++;
+ } // end while
+
+ if (newBuffer.Length - 1 - lastDirectorySeparatorPos > MaxPathComponentLength)
+ {
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ }
+
+ // Drop any trailing dots and spaces from file & directory names, EXCEPT
+ // we MUST make sure that "C:\foo\.." is correctly handled.
+ // Also handle "C:\foo\." -> "C:\foo", while "C:\." -> "C:\"
+ if (numSigChars == 0) {
+ if (numDots > 0) {
+ // Look for ".[space]*" or "..[space]*"
+ int start = lastSigChar + 1;
+ if (path[start] != '.')
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ // Only allow "[dot]+[space]*", and normalize the
+ // legal ones to "." or ".."
+ if (numDots >= 2) {
+ // Reject "C:..."
+ if (startedWithVolumeSeparator && numDots > 2)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ if (path[start + 1] == '.') {
+ // Search for a space in the middle of the
+ // dots and throw
+ for(int i=start + 2; i < start + numDots; i++) {
+ if (path[i] != '.')
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+ }
+
+ numDots = 2;
+ }
+ else {
+ if (numDots > 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+ numDots = 1;
+ }
+ }
+
+ if (numDots == 2) {
+ newBuffer.Append('.');
+ }
+
+ newBuffer.Append('.');
+ }
+ } // if (numSigChars == 0)
+
+ // If we ended up eating all the characters, bail out.
+ if (newBuffer.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegal"));
+
+ // Disallow URL's here. Some of our other Win32 API calls will reject
+ // them later, so we might be better off rejecting them here.
+ // Note we've probably turned them into "file:\D:\foo.tmp" by now.
+ // But for compatibility, ensure that callers that aren't doing a
+ // full check aren't rejected here.
+ if (fullCheck) {
+ if ( newBuffer.OrdinalStartsWith("http:", false) ||
+ newBuffer.OrdinalStartsWith("file:", false))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathUriFormatNotSupported"));
+ }
+ }
+
+#if !PLATFORM_UNIX
+ // If the last part of the path (file or directory name) had a tilde,
+ // expand that too.
+ if (mightBeShortFileName) {
+ newBuffer.TryExpandShortFileName();
+ }
+#endif
+
+ // Call the Win32 API to do the final canonicalization step.
+ int result = 1;
+
+ if (fullCheck) {
+ // NOTE: Win32 GetFullPathName requires the input buffer to be big enough to fit the initial
+ // path which is a concat of CWD and the relative path, this can be of an arbitrary
+ // size and could be > MAX_PATH (which becomes an artificial limit at this point),
+ // even though the final normalized path after fixing up the relative path syntax
+ // might be well within the MAX_PATH restriction. For ex,
+ // "c:\SomeReallyLongDirName(thinkGreaterThan_MAXPATH)\..\foo.txt" which actually requires a
+ // buffer well with in the MAX_PATH as the normalized path is just "c:\foo.txt"
+ // This buffer requirement seems wrong, it could be a bug or a perf optimization
+ // like returning required buffer length quickly or avoid stratch buffer etc.
+ // Ideally we would get the required buffer length first by calling GetFullPathName
+ // once without the buffer and use that in the later call but this doesn't always work
+ // due to Win32 GetFullPathName bug. For instance, in Win2k, when the path we are trying to
+ // fully qualify is a single letter name (such as "a", "1", ",") GetFullPathName
+ // fails to return the right buffer size (i.e, resulting in insufficient buffer).
+ // To workaround this bug we will start with MAX_PATH buffer and grow it once if the
+ // return value is > MAX_PATH.
+
+ result = newBuffer.GetFullPathName();
+
+#if !PLATFORM_UNIX
+ // If we called GetFullPathName with something like "foo" and our
+ // command window was in short file name mode (ie, by running edlin or
+ // DOS versions of grep, etc), we might have gotten back a short file
+ // name. So, check to see if we need to expand it.
+ mightBeShortFileName = false;
+ for(int i=0; i < newBuffer.Length && !mightBeShortFileName; i++) {
+ if (newBuffer[i] == '~' && expandShortPaths)
+ mightBeShortFileName = true;
+ }
+
+ if (mightBeShortFileName) {
+ bool r = newBuffer.TryExpandShortFileName();
+ // Consider how the path "Doesn'tExist" would expand. If
+ // we add in the current directory, it too will need to be
+ // fully expanded, which doesn't happen if we use a file
+ // name that doesn't exist.
+ if (!r) {
+ int lastSlash = -1;
+
+ for (int i = newBuffer.Length - 1; i >= 0; i--) {
+ if (newBuffer[i] == DirectorySeparatorChar) {
+ lastSlash = i;
+ break;
+ }
+ }
+
+ if (lastSlash >= 0) {
+
+ // This bounds check is for safe memcpy but we should never get this far
+ if (newBuffer.Length >= maxPathLength)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ int lenSavedName = newBuffer.Length - lastSlash - 1;
+ Contract.Assert(lastSlash < newBuffer.Length, "path unexpectedly ended in a '\'");
+
+ newBuffer.Fixup(lenSavedName, lastSlash);
+ }
+ }
+ }
+#endif // PLATFORM_UNIX
+ }
+
+ if (result != 0) {
+ /* Throw an ArgumentException for paths like \\, \\server, \\server\
+ This check can only be properly done after normalizing, so
+ \\foo\.. will be properly rejected. Also, reject \\?\GLOBALROOT\
+ (an internal kernel path) because it provides aliases for drives. */
+ if (newBuffer.Length > 1 && newBuffer[0] == '\\' && newBuffer[1] == '\\') {
+ int startIndex = 2;
+ while (startIndex < result) {
+ if (newBuffer[startIndex] == '\\') {
+ startIndex++;
+ break;
+ }
+ else {
+ startIndex++;
+ }
+ }
+ if (startIndex == result)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathIllegalUNC"));
+
+ // Check for \\?\Globalroot, an internal mechanism to the kernel
+ // that provides aliases for drives and other undocumented stuff.
+ // The kernel team won't even describe the full set of what
+ // is available here - we don't want managed apps mucking
+ // with this for security reasons.
+ if ( newBuffer.OrdinalStartsWith("\\\\?\\globalroot", true))
+ throw new ArgumentException(Environment.GetResourceString("Arg_PathGlobalRoot"));
+ }
+ }
+
+ // Check our result and form the managed string as necessary.
+ if (newBuffer.Length >= maxPathLength)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ if (result == 0) {
+ int errorCode = Marshal.GetLastWin32Error();
+ if (errorCode == 0)
+ errorCode = Win32Native.ERROR_BAD_PATHNAME;
+ __Error.WinIOError(errorCode, path);
+ return null; // Unreachable - silence a compiler error.
+ }
+
+ return newBuffer.ToStringOrExisting(path);
+ }
+#endif // FEATURE_PATHCOMPAT
+
+ internal const int MaxLongPath = PathInternal.MaxLongPath;
+
+ 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)
+ {
+#if FEATURE_PATHCOMPAT
+ if (AppContextSwitches.UseLegacyPathHandling)
+ return path.StartsWith(LongPathPrefix, StringComparison.Ordinal);
+ else
+#endif
+ return PathInternal.IsExtended(path);
+ }
+
+ internal static string AddLongPathPrefix(string path)
+ {
+#if FEATURE_PATHCOMPAT
+ 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.
+
+ return LongPathPrefix + path;
+ }
+ else
+#endif
+ {
+ return PathInternal.EnsureExtendedPrefix(path);
+ }
+ }
+
+ internal static string RemoveLongPathPrefix(string path)
+ {
+#if FEATURE_PATHCOMPAT
+ 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.
+
+ return path.Substring(4);
+ }
+ else
+#endif
+ {
+ return PathInternal.RemoveExtendedPrefix(path);
+ }
+ }
+
+ internal static StringBuilder RemoveLongPathPrefix(StringBuilder pathSB)
+ {
+#if FEATURE_PATHCOMPAT
+ if (AppContextSwitches.UseLegacyPathHandling)
+ {
+ if (!PathInternal.StartsWithOrdinal(pathSB, LongPathPrefix))
+ return pathSB;
+
+ // 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);
+ }
+ else
+#endif
+ {
+ return PathInternal.RemoveExtendedPrefix(pathSB);
+ }
+ }
+
+
+ // Returns the name and extension parts of the given path. The resulting
+ // string contains the characters of path that follow the last
+ // backslash ("\"), slash ("/"), or colon (":") character in
+ // path. The resulting string is the entire path if path
+ // contains no backslash after removing trailing slashes, slash, or colon characters. The resulting
+ // string is null if path is null.
+ //
+ [Pure]
+ public static String GetFileName(String path) {
+ if (path != null) {
+ CheckInvalidPathChars(path);
+
+ int length = path.Length;
+ for (int i = length; --i >= 0;) {
+ char ch = path[i];
+ if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar)
+ return path.Substring(i + 1, length - i - 1);
+
+ }
+ }
+ return path;
+ }
+
+ [Pure]
+ public static String GetFileNameWithoutExtension(String path) {
+ path = GetFileName(path);
+ if (path != null)
+ {
+ int i;
+ if ((i=path.LastIndexOf('.')) == -1)
+ return path; // No path extension found
+ else
+ return path.Substring(0,i);
+ }
+ 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
+ // empty string (a relative path on the current drive), "\" (an absolute
+ // path on the current drive), "X:" (a relative path on a given drive,
+ // where X is the drive letter), "X:\" (an absolute path on a given drive),
+ // and "\\server\share" (a UNC path for a given server and share name).
+ // The resulting string is null if path is null.
+ //
+ [Pure]
+ public static String GetPathRoot(String path) {
+ if (path == null) return null;
+
+ // 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));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static String GetTempPath()
+ {
+#if !FEATURE_CORECLR
+ new EnvironmentPermission(PermissionState.Unrestricted).Demand();
+#endif
+ StringBuilder sb = new StringBuilder(PathInternal.MaxShortPath);
+ uint r = Win32Native.GetTempPath(PathInternal.MaxShortPath, sb);
+ String path = sb.ToString();
+ if (r==0) __Error.WinIOError();
+ path = GetFullPathInternal(path);
+#if FEATURE_CORECLR
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, path);
+ state.EnsureState();
+#endif
+ return path;
+ }
+
+ internal static bool IsRelative(string path)
+ {
+ Contract.Assert(path != null, "path can't be null");
+ 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.
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public static String GetRandomFileName()
+ {
+ // 5 bytes == 40 bits == 40/5 == 8 chars in our encoding
+ // This gives us exactly 8 chars. We want to avoid the 8.3 short name issue
+ byte[] key = new byte[10];
+
+#if FEATURE_CORECLR
+ Win32Native.Random(true, key, key.Length);
+#else
+ // RNGCryptoServiceProvider is disposable in post-Orcas desktop mscorlibs, but not in CoreCLR's
+ // mscorlib, so we need to do a manual using block for it.
+ RNGCryptoServiceProvider rng = null;
+ try
+ {
+ rng = new RNGCryptoServiceProvider();
+
+ rng.GetBytes(key);
+ }
+ finally
+ {
+ if (rng != null)
+ {
+ rng.Dispose();
+ }
+ }
+#endif
+
+ // rndCharArray is expected to be 16 chars
+ char[] rndCharArray = Path.ToBase32StringSuitableForDirName(key).ToCharArray();
+ rndCharArray[8] = '.';
+ return new String(rndCharArray, 0, 12);
+ }
+
+ // Returns a unique temporary file name, and creates a 0-byte file by that
+ // name on disk.
+ [System.Security.SecuritySafeCritical]
+ public static String GetTempFileName()
+ {
+ return InternalGetTempFileName(true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String UnsafeGetTempFileName()
+ {
+ return InternalGetTempFileName(false);
+ }
+
+ [System.Security.SecurityCritical]
+ private static String InternalGetTempFileName(bool checkHost)
+ {
+ String path = GetTempPath();
+
+ // Since this can write to the temp directory and theoretically
+ // cause a denial of service attack, demand FileIOPermission to
+ // that directory.
+
+#if FEATURE_CORECLR
+ if (checkHost)
+ {
+ FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Write, String.Empty, path);
+ state.EnsureState();
+ }
+#else
+ FileIOPermission.QuickDemand(FileIOPermissionAccess.Write, path);
+#endif
+ StringBuilder sb = new StringBuilder(MaxPath);
+ uint r = Win32Native.GetTempFileName(path, "tmp", 0, sb);
+ if (r==0) __Error.WinIOError();
+ return sb.ToString();
+ }
+
+ // Tests if a path includes a file extension. The result is
+ // true if the characters that follow the last directory
+ // separator ('\\' or '/') or volume separator (':') in the path include
+ // a period (".") other than a terminal period. The result is false otherwise.
+ //
+ [Pure]
+ public static bool HasExtension(String path) {
+ if (path != null) {
+ CheckInvalidPathChars(path);
+
+ for (int i = path.Length; --i >= 0;) {
+ char ch = path[i];
+ if (ch == '.') {
+ if ( i != path.Length - 1)
+ return true;
+ else
+ return false;
+ }
+ if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar) break;
+ }
+ }
+ return false;
+ }
+
+ // Tests if the given path contains a root. A path is considered rooted
+ // if it starts with a backslash ("\") or a drive letter and a colon (":").
+ //
+ [Pure]
+ public static bool IsPathRooted(String path) {
+ if (path != null) {
+ CheckInvalidPathChars(path);
+
+ int length = path.Length;
+#if !PLATFORM_UNIX
+ if ((length >= 1 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar)) || (length >= 2 && path[1] == VolumeSeparatorChar))
+ return true;
+#else
+ if (length >= 1 && (path[0] == DirectorySeparatorChar || path[0] == AltDirectorySeparatorChar))
+ return true;
+#endif
+ }
+ return false;
+ }
+
+ public static String Combine(String path1, String path2) {
+ if (path1==null || path2==null)
+ throw new ArgumentNullException((path1==null) ? "path1" : "path2");
+ Contract.EndContractBlock();
+ CheckInvalidPathChars(path1);
+ CheckInvalidPathChars(path2);
+
+ return CombineNoChecks(path1, path2);
+ }
+
+ public static String Combine(String path1, String path2, String path3) {
+ if (path1 == null || path2 == null || path3 == null)
+ throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : "path3");
+ Contract.EndContractBlock();
+ CheckInvalidPathChars(path1);
+ CheckInvalidPathChars(path2);
+ CheckInvalidPathChars(path3);
+
+ return CombineNoChecks(CombineNoChecks(path1, path2), path3);
+ }
+
+ public static String Combine(String path1, String path2, String path3, String path4) {
+ if (path1 == null || path2 == null || path3 == null || path4 == null)
+ throw new ArgumentNullException((path1 == null) ? "path1" : (path2 == null) ? "path2" : (path3 == null) ? "path3" : "path4");
+ Contract.EndContractBlock();
+ CheckInvalidPathChars(path1);
+ CheckInvalidPathChars(path2);
+ CheckInvalidPathChars(path3);
+ CheckInvalidPathChars(path4);
+
+ return CombineNoChecks(CombineNoChecks(CombineNoChecks(path1, path2), path3), path4);
+ }
+
+ public static String Combine(params String[] paths) {
+ if (paths == null) {
+ throw new ArgumentNullException("paths");
+ }
+ Contract.EndContractBlock();
+
+ int finalSize = 0;
+ int firstComponent = 0;
+
+ // We have two passes, the first calcuates how large a buffer to allocate and does some precondition
+ // checks on the paths passed in. The second actually does the combination.
+
+ for (int i = 0; i < paths.Length; i++) {
+ if (paths[i] == null) {
+ throw new ArgumentNullException("paths");
+ }
+
+ if (paths[i].Length == 0) {
+ continue;
+ }
+
+ CheckInvalidPathChars(paths[i]);
+
+ if (Path.IsPathRooted(paths[i])) {
+ firstComponent = i;
+ finalSize = paths[i].Length;
+ } else {
+ finalSize += paths[i].Length;
+ }
+
+ char ch = paths[i][paths[i].Length - 1];
+ if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar)
+ finalSize++;
+ }
+
+ StringBuilder finalPath = StringBuilderCache.Acquire(finalSize);
+
+ for (int i = firstComponent; i < paths.Length; i++) {
+ if (paths[i].Length == 0) {
+ continue;
+ }
+
+ if (finalPath.Length == 0) {
+ finalPath.Append(paths[i]);
+ } else {
+ char ch = finalPath[finalPath.Length - 1];
+ if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar) {
+ finalPath.Append(DirectorySeparatorChar);
+ }
+
+ finalPath.Append(paths[i]);
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(finalPath);
+ }
+
+ private static String CombineNoChecks(String path1, String path2) {
+ if (path2.Length == 0)
+ return path1;
+
+ if (path1.Length == 0)
+ return path2;
+
+ if (IsPathRooted(path2))
+ return path2;
+
+ char ch = path1[path1.Length - 1];
+ if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar)
+ return path1 + DirectorySeparatorCharAsString + path2;
+ return path1 + path2;
+ }
+
+ private static readonly Char[] s_Base32Char = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'y', 'z', '0', '1', '2', '3', '4', '5'};
+
+ internal static String ToBase32StringSuitableForDirName(byte[] buff)
+ {
+ // This routine is optimised to be used with buffs of length 20
+ Contract.Assert(((buff.Length % 5) == 0), "Unexpected hash length");
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ byte b0, b1, b2, b3, b4;
+ int l, i;
+
+ l = buff.Length;
+ i = 0;
+
+ // Create l chars using the last 5 bits of each byte.
+ // Consume 3 MSB bits 5 bytes at a time.
+
+ do
+ {
+ b0 = (i < l) ? buff[i++] : (byte)0;
+ b1 = (i < l) ? buff[i++] : (byte)0;
+ b2 = (i < l) ? buff[i++] : (byte)0;
+ b3 = (i < l) ? buff[i++] : (byte)0;
+ b4 = (i < l) ? buff[i++] : (byte)0;
+
+ // Consume the 5 Least significant bits of each byte
+ sb.Append(s_Base32Char[b0 & 0x1F]);
+ sb.Append(s_Base32Char[b1 & 0x1F]);
+ sb.Append(s_Base32Char[b2 & 0x1F]);
+ sb.Append(s_Base32Char[b3 & 0x1F]);
+ sb.Append(s_Base32Char[b4 & 0x1F]);
+
+ // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
+ sb.Append(s_Base32Char[(
+ ((b0 & 0xE0) >> 5) |
+ ((b3 & 0x60) >> 2))]);
+
+ sb.Append(s_Base32Char[(
+ ((b1 & 0xE0) >> 5) |
+ ((b4 & 0x60) >> 2))]);
+
+ // Consume 3 MSB bits of b2, 1 MSB bit of b3, b4
+
+ b2 >>= 5;
+
+ Contract.Assert(((b2 & 0xF8) == 0), "Unexpected set bits");
+
+ if ((b3 & 0x80) != 0)
+ b2 |= 0x08;
+ if ((b4 & 0x80) != 0)
+ b2 |= 0x10;
+
+ sb.Append(s_Base32Char[b2]);
+
+ } while (i < l);
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ // ".." can only be used if it is specified as a part of a valid File/Directory name. We disallow
+ // the user being able to use it to move up directories. Here are some examples eg
+ // Valid: a..b abc..d
+ // Invalid: ..ab ab.. .. abc..d\abc..
+ //
+ internal static void CheckSearchPattern(String searchPattern)
+ {
+ int index;
+ while ((index = searchPattern.IndexOf("..", StringComparison.Ordinal)) != -1) {
+
+ if (index + 2 == searchPattern.Length) // Terminal ".." . Files names cannot end in ".."
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidSearchPattern"));
+
+ if ((searchPattern[index+2] == DirectorySeparatorChar)
+ || (searchPattern[index+2] == AltDirectorySeparatorChar))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidSearchPattern"));
+
+ searchPattern = searchPattern.Substring(index + 2);
+ }
+
+ }
+
+ internal static void CheckInvalidPathChars(String path, bool checkAdditional = false)
+ {
+ if (path == null)
+ throw new ArgumentNullException("path");
+
+ 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");
+ Contract.EndContractBlock();
+ CheckInvalidPathChars(path1);
+ CheckInvalidPathChars(path2);
+
+ if (path2.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path2");
+ if (IsPathRooted(path2))
+ throw new ArgumentException(Environment.GetResourceString("Arg_Path2IsRooted"), "path2");
+ int i = path1.Length;
+ if (i == 0) return path2;
+ char ch = path1[i - 1];
+ if (ch != DirectorySeparatorChar && ch != AltDirectorySeparatorChar && ch != VolumeSeparatorChar)
+ return path1 + DirectorySeparatorCharAsString + path2;
+ return path1 + path2;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/IO/PathHelper.cs b/src/mscorlib/src/System/IO/PathHelper.cs
new file mode 100644
index 0000000000..8e39b3c537
--- /dev/null
+++ b/src/mscorlib/src/System/IO/PathHelper.cs
@@ -0,0 +1,448 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if FEATURE_PATHCOMPAT
+using System;
+using System.Collections;
+using System.Text;
+using Microsoft.Win32;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Security;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+
+ // ABOUT:
+ // Helps with path normalization; support allocating on the stack or heap
+ //
+ // PathHelper can't stackalloc the array for obvious reasons; you must pass
+ // in an array of chars allocated on the stack.
+ //
+ // USAGE:
+ // Suppose you need to represent a char array of length len. Then this is the
+ // suggested way to instantiate PathHelper:
+ // ***************************************************************************
+ // PathHelper pathHelper;
+ // if (charArrayLength less than stack alloc threshold == Path.MaxPath)
+ // char* arrayPtr = stackalloc char[Path.MaxPath];
+ // pathHelper = new PathHelper(arrayPtr);
+ // else
+ // pathHelper = new PathHelper(capacity, maxPath);
+ // ***************************************************************************
+ //
+ // note in the StringBuilder ctor:
+ // - maxPath may be greater than Path.MaxPath (for isolated storage)
+ // - capacity may be greater than maxPath. This is even used for non-isolated
+ // storage scenarios where we want to temporarily allow strings greater
+ // than Path.MaxPath if they can be normalized down to Path.MaxPath. This
+ // can happen if the path contains escape characters "..".
+ //
+ unsafe internal struct PathHelper { // should not be serialized
+
+ // maximum size, max be greater than max path if contains escape sequence
+ private int m_capacity;
+ // current length (next character position)
+ private int m_length;
+ // max path, may be less than capacity
+ private int m_maxPath;
+
+ // ptr to stack alloc'd array of chars
+ [SecurityCritical]
+ private char* m_arrayPtr;
+
+ // StringBuilder
+ private StringBuilder m_sb;
+
+ // whether to operate on stack alloc'd or heap alloc'd array
+ private bool useStackAlloc;
+
+ // Whether to skip calls to Win32Native.GetLongPathName becasue we tried before and failed:
+ private bool doNotTryExpandShortFileName;
+
+ // Instantiates a PathHelper with a stack alloc'd array of chars
+ [System.Security.SecurityCritical]
+ internal PathHelper(char* charArrayPtr, int length) {
+ Contract.Requires(charArrayPtr != null);
+ // force callers to be aware of this
+ Contract.Requires(length == Path.MaxPath);
+ this.m_length = 0;
+ this.m_sb = null;
+
+ this.m_arrayPtr = charArrayPtr;
+ this.m_capacity = length;
+ this.m_maxPath = Path.MaxPath;
+ useStackAlloc = true;
+ doNotTryExpandShortFileName = false;
+ }
+
+ // Instantiates a PathHelper with a heap alloc'd array of ints. Will create a StringBuilder
+ [System.Security.SecurityCritical]
+ internal PathHelper(int capacity, int maxPath)
+ {
+ this.m_length = 0;
+ this.m_arrayPtr = null;
+ this.useStackAlloc = false;
+
+ this.m_sb = new StringBuilder(capacity);
+ this.m_capacity = capacity;
+ this.m_maxPath = maxPath;
+ doNotTryExpandShortFileName = false;
+ }
+
+ internal int Length {
+ get {
+ if (useStackAlloc) {
+ return m_length;
+ }
+ else {
+ return m_sb.Length;
+ }
+ }
+ set {
+ if (useStackAlloc) {
+ m_length = value;
+ }
+ else {
+ m_sb.Length = value;
+ }
+ }
+ }
+
+ internal int Capacity {
+ get {
+ return m_capacity;
+ }
+ }
+
+ internal char this[int index] {
+ [System.Security.SecurityCritical]
+ get {
+ Contract.Requires(index >= 0 && index < Length);
+ if (useStackAlloc) {
+ return m_arrayPtr[index];
+ }
+ else {
+ return m_sb[index];
+ }
+ }
+ [System.Security.SecurityCritical]
+ set {
+ Contract.Requires(index >= 0 && index < Length);
+ if (useStackAlloc) {
+ m_arrayPtr[index] = value;
+ }
+ else {
+ m_sb[index] = value;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe void Append(char value) {
+ if (Length + 1 >= m_capacity)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ if (useStackAlloc) {
+ m_arrayPtr[Length] = value;
+ m_length++;
+ }
+ else {
+ m_sb.Append(value);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe int GetFullPathName() {
+ if (useStackAlloc) {
+ char* finalBuffer = stackalloc char[Path.MaxPath + 1];
+ int result = Win32Native.GetFullPathName(m_arrayPtr, Path.MaxPath + 1, finalBuffer, IntPtr.Zero);
+
+ // If success, the return buffer length does not account for the terminating null character.
+ // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character.
+ // If failure, the return buffer length is zero
+ if (result > Path.MaxPath) {
+ char* tempBuffer = stackalloc char[result];
+ finalBuffer = tempBuffer;
+ result = Win32Native.GetFullPathName(m_arrayPtr, result, finalBuffer, IntPtr.Zero);
+ }
+
+ // Full path is genuinely long
+ if (result >= Path.MaxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ Contract.Assert(result < Path.MaxPath, "did we accidently remove a PathTooLongException check?");
+ if (result == 0 && m_arrayPtr[0] != '\0') {
+ __Error.WinIOError();
+ }
+
+ else if (result < Path.MaxPath) {
+ // Null terminate explicitly (may be only needed for some cases such as empty strings)
+ // GetFullPathName return length doesn't account for null terminating char...
+ finalBuffer[result] = '\0'; // Safe to write directly as result is < Path.MaxPath
+ }
+
+ // We have expanded the paths and GetLongPathName may or may not behave differently from before.
+ // We need to call it again to see:
+ doNotTryExpandShortFileName = false;
+
+ String.wstrcpy(m_arrayPtr, finalBuffer, result);
+ // Doesn't account for null terminating char. Think of this as the last
+ // valid index into the buffer but not the length of the buffer
+ Length = result;
+ return result;
+ }
+ else {
+ StringBuilder finalBuffer = new StringBuilder(m_capacity + 1);
+ int result = Win32Native.GetFullPathName(m_sb.ToString(), m_capacity + 1, finalBuffer, IntPtr.Zero);
+
+ // If success, the return buffer length does not account for the terminating null character.
+ // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character.
+ // If failure, the return buffer length is zero
+ if (result > m_maxPath) {
+ finalBuffer.Length = result;
+ result = Win32Native.GetFullPathName(m_sb.ToString(), result, finalBuffer, IntPtr.Zero);
+ }
+
+ // Fullpath is genuinely long
+ if (result >= m_maxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ Contract.Assert(result < m_maxPath, "did we accidentally remove a PathTooLongException check?");
+ if (result == 0 && m_sb[0] != '\0') {
+ if (Length >= m_maxPath) {
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ }
+ __Error.WinIOError();
+ }
+
+ // We have expanded the paths and GetLongPathName may or may not behave differently from before.
+ // We need to call it again to see:
+ doNotTryExpandShortFileName = false;
+
+ m_sb = finalBuffer;
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe bool TryExpandShortFileName() {
+
+ if (doNotTryExpandShortFileName)
+ return false;
+
+ if (useStackAlloc) {
+ NullTerminate();
+ char* buffer = UnsafeGetArrayPtr();
+ char* shortFileNameBuffer = stackalloc char[Path.MaxPath + 1];
+
+ int r = Win32Native.GetLongPathName(buffer, shortFileNameBuffer, Path.MaxPath);
+
+ // If success, the return buffer length does not account for the terminating null character.
+ // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character.
+ // If failure, the return buffer length is zero
+ if (r >= Path.MaxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ if (r == 0) {
+ // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a
+ // path like \\.\PHYSICALDEVICE0 - some device driver doesn't
+ // support GetLongPathName on that string. This behavior is
+ // by design, according to the Core File Services team.
+ // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs
+ // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\
+
+ // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist:
+ int lastErr = Marshal.GetLastWin32Error();
+ if (lastErr == Win32Native.ERROR_FILE_NOT_FOUND || lastErr == Win32Native.ERROR_PATH_NOT_FOUND)
+ doNotTryExpandShortFileName = true;
+
+ return false;
+ }
+
+ // Safe to copy as we have already done Path.MaxPath bound checking
+ String.wstrcpy(buffer, shortFileNameBuffer, r);
+ Length = r;
+ // We should explicitly null terminate as in some cases the long version of the path
+ // might actually be shorter than what we started with because of Win32's normalization
+ // Safe to write directly as bufferLength is guaranteed to be < Path.MaxPath
+ NullTerminate();
+ return true;
+ }
+ else {
+ StringBuilder sb = GetStringBuilder();
+
+ String origName = sb.ToString();
+ String tempName = origName;
+ bool addedPrefix = false;
+ if (tempName.Length > Path.MaxPath) {
+ tempName = Path.AddLongPathPrefix(tempName);
+ addedPrefix = true;
+ }
+ sb.Capacity = m_capacity;
+ sb.Length = 0;
+ int r = Win32Native.GetLongPathName(tempName, sb, m_capacity);
+
+ if (r == 0) {
+ // Note: GetLongPathName will return ERROR_INVALID_FUNCTION on a
+ // path like \\.\PHYSICALDEVICE0 - some device driver doesn't
+ // support GetLongPathName on that string. This behavior is
+ // by design, according to the Core File Services team.
+ // We also get ERROR_NOT_ENOUGH_QUOTA in SQL_CLR_STRESS runs
+ // intermittently on paths like D:\DOCUME~1\user\LOCALS~1\Temp\
+
+ // We do not need to call GetLongPathName if we know it will fail becasue the path does not exist:
+ int lastErr = Marshal.GetLastWin32Error();
+ if (Win32Native.ERROR_FILE_NOT_FOUND == lastErr || Win32Native.ERROR_PATH_NOT_FOUND == lastErr)
+ doNotTryExpandShortFileName = true;
+
+ sb.Length = 0;
+ sb.Append(origName);
+ return false;
+ }
+
+ if (addedPrefix)
+ r -= 4;
+
+ // If success, the return buffer length does not account for the terminating null character.
+ // If in-sufficient buffer, the return buffer length does account for the path + the terminating null character.
+ // If failure, the return buffer length is zero
+ if (r >= m_maxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+
+ sb = Path.RemoveLongPathPrefix(sb);
+ Length = sb.Length;
+ return true;
+
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe void Fixup(int lenSavedName, int lastSlash) {
+ if (useStackAlloc) {
+ char* savedName = stackalloc char[lenSavedName];
+ String.wstrcpy(savedName, m_arrayPtr + lastSlash + 1, lenSavedName);
+ Length = lastSlash;
+ NullTerminate();
+ doNotTryExpandShortFileName = false;
+ bool r = TryExpandShortFileName();
+ // Clean up changes made to the newBuffer.
+ Append(Path.DirectorySeparatorChar);
+ if (Length + lenSavedName >= Path.MaxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ String.wstrcpy(m_arrayPtr + Length, savedName, lenSavedName);
+ Length = Length + lenSavedName;
+
+ }
+ else {
+ String savedName = m_sb.ToString(lastSlash + 1, lenSavedName);
+ Length = lastSlash;
+ doNotTryExpandShortFileName = false;
+ bool r = TryExpandShortFileName();
+ // Clean up changes made to the newBuffer.
+ Append(Path.DirectorySeparatorChar);
+ if (Length + lenSavedName >= m_maxPath)
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+ m_sb.Append(savedName);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe bool OrdinalStartsWith(String compareTo, bool ignoreCase) {
+ if (Length < compareTo.Length)
+ return false;
+
+ if (useStackAlloc) {
+ NullTerminate();
+ if (ignoreCase) {
+ String s = new String(m_arrayPtr, 0, compareTo.Length);
+ return compareTo.Equals(s, StringComparison.OrdinalIgnoreCase);
+ }
+ else {
+ for (int i = 0; i < compareTo.Length; i++) {
+ if (m_arrayPtr[i] != compareTo[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ else {
+ if (ignoreCase) {
+ return m_sb.ToString().StartsWith(compareTo, StringComparison.OrdinalIgnoreCase);
+ }
+ else {
+ return m_sb.ToString().StartsWith(compareTo, StringComparison.Ordinal);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe bool OrdinalEqualsStackAlloc(String compareTo)
+ {
+ Contract.Requires(useStackAlloc, "Currently no efficient implementation for StringBuilder.OrdinalEquals(String)");
+
+ if (Length != compareTo.Length) {
+ return false;
+ }
+
+ for (int i = 0; i < compareTo.Length; i++) {
+ if (m_arrayPtr[i] != compareTo[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override String ToString() {
+ if (useStackAlloc) {
+ return new String(m_arrayPtr, 0, Length);
+ }
+ else {
+ return m_sb.ToString();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal String ToStringOrExisting(String existingString)
+ {
+ if (useStackAlloc) {
+ return OrdinalEqualsStackAlloc(existingString) ?
+ existingString :
+ new String(m_arrayPtr, 0, Length);
+ }
+ else {
+ string newString = m_sb.ToString(); // currently no good StringBuilder.OrdinalEquals(string)
+ return String.Equals(newString, existingString, StringComparison.Ordinal) ?
+ existingString :
+ newString;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe char* UnsafeGetArrayPtr() {
+ Contract.Requires(useStackAlloc, "This should never be called for PathHelpers wrapping a StringBuilder");
+ return m_arrayPtr;
+ }
+
+ private StringBuilder GetStringBuilder() {
+ Contract.Requires(!useStackAlloc, "This should never be called for PathHelpers that wrap a stackalloc'd buffer");
+ return m_sb;
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe void NullTerminate() {
+ Contract.Requires(useStackAlloc, "This should never be called for PathHelpers wrapping a StringBuilder");
+ m_arrayPtr[m_length] = '\0';
+ }
+
+ }
+}
+#endif // FEATURE_PATHCOMPAT \ No newline at end of file
diff --git a/src/mscorlib/src/System/IO/PathInternal.cs b/src/mscorlib/src/System/IO/PathInternal.cs
new file mode 100644
index 0000000000..3970e2264a
--- /dev/null
+++ b/src/mscorlib/src/System/IO/PathInternal.cs
@@ -0,0 +1,806 @@
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using Microsoft.Win32;
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Text;
+
+namespace System.IO
+{
+ /// <summary>Contains internal path helpers that are shared between many projects.</summary>
+ internal static class PathInternal
+ {
+ internal const string ExtendedPathPrefix = @"\\?\";
+ internal const string UncPathPrefix = @"\\";
+ internal const string UncExtendedPrefixToInsert = @"?\UNC\";
+ internal const string UncExtendedPathPrefix = @"\\?\UNC\";
+ internal const string DevicePathPrefix = @"\\.\";
+ // \\?\, \\.\, \??\
+ internal const int DevicePrefixLength = 4;
+ // \\
+ internal const int UncPrefixLength = 2;
+ // \\?\UNC\, \\.\UNC\
+ internal const int UncExtendedPrefixLength = 8;
+#if !PLATFORM_UNIX
+ internal const int MaxShortPath = 260;
+ internal const int MaxShortDirectoryPath = 248;
+#else
+ internal const int MaxShortPath = 1024;
+ internal const int MaxShortDirectoryPath = MaxShortPath;
+#endif
+
+ // Windows is limited in long paths by the max size of its internal representation of a unicode string.
+ // UNICODE_STRING has a max length of USHORT in _bytes_ without a trailing null.
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/ff564879.aspx
+ internal const int MaxLongPath = short.MaxValue;
+ internal static readonly int MaxComponentLength = 255;
+
+#if !PLATFORM_UNIX
+ internal 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
+ };
+#else
+ internal static readonly char[] InvalidPathChars = { '\0' };
+#endif
+
+
+ /// <summary>
+ /// Validates volume separator only occurs as C: or \\?\C:. This logic is meant to filter out Alternate Data Streams.
+ /// </summary>
+ /// <returns>True if the path has an invalid volume separator.</returns>
+ internal static bool HasInvalidVolumeSeparator(string path)
+ {
+ // Toss out paths with colons that aren't a valid drive specifier.
+ // Cannot start with a colon and can only be of the form "C:" or "\\?\C:".
+ // (Note that we used to explicitly check "http:" and "file:"- these are caught by this check now.)
+
+ // We don't care about skipping starting space for extended paths. Assume no knowledge of extended paths if we're forcing old path behavior.
+ bool isExtended =
+#if FEATURE_PATHCOMPAT
+ !AppContextSwitches.UseLegacyPathHandling &&
+#endif
+ IsExtended(path);
+ int startIndex = isExtended ? ExtendedPathPrefix.Length : PathStartSkip(path);
+
+ // If we start with a colon
+ if ((path.Length > startIndex && path[startIndex] == Path.VolumeSeparatorChar)
+ // Or have an invalid drive letter and colon
+ || (path.Length >= startIndex + 2 && path[startIndex + 1] == Path.VolumeSeparatorChar && !IsValidDriveChar(path[startIndex]))
+ // Or have any colons beyond the drive colon
+ || (path.Length > startIndex + 2 && path.IndexOf(Path.VolumeSeparatorChar, startIndex + 2) != -1))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if the given StringBuilder starts with the given value.
+ /// </summary>
+ /// <param name="value">The string to compare against the start of the StringBuilder.</param>
+ internal static bool StartsWithOrdinal(StringBuilder builder, string value, bool ignoreCase = false)
+ {
+ if (value == null || builder.Length < value.Length)
+ return false;
+
+ if (ignoreCase)
+ {
+ for (int i = 0; i < value.Length; i++)
+ if (char.ToUpperInvariant(builder[i]) != char.ToUpperInvariant(value[i])) return false;
+ }
+ else
+ {
+ for (int i = 0; i < value.Length; i++)
+ if (builder[i] != value[i]) return false;
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if the given character is a valid drive letter
+ /// </summary>
+ internal static bool IsValidDriveChar(char value)
+ {
+ return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
+ }
+
+ /// <summary>
+ /// Returns true if the path is too long
+ /// </summary>
+ internal static bool IsPathTooLong(string fullPath)
+ {
+ // We'll never know precisely what will fail as paths get changed internally in Windows and
+ // may grow beyond / shrink below exceed MaxLongPath.
+#if FEATURE_PATHCOMPAT
+ if (AppContextSwitches.BlockLongPaths)
+ {
+ // We allow paths of any length if extended (and not in compat mode)
+ if (AppContextSwitches.UseLegacyPathHandling || !IsExtended(fullPath))
+ return fullPath.Length >= MaxShortPath;
+ }
+#endif
+
+ return fullPath.Length >= MaxLongPath;
+ }
+
+ /// <summary>
+ /// Return true if any path segments are too long
+ /// </summary>
+ internal static bool AreSegmentsTooLong(string fullPath)
+ {
+ int length = fullPath.Length;
+ int lastSeparator = 0;
+
+ for (int i = 0; i < length; i++)
+ {
+ if (IsDirectorySeparator(fullPath[i]))
+ {
+ if (i - lastSeparator > MaxComponentLength)
+ return true;
+ lastSeparator = i;
+ }
+ }
+
+ if (length - 1 - lastSeparator > MaxComponentLength)
+ return true;
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if the directory is too long
+ /// </summary>
+ internal static bool IsDirectoryTooLong(string fullPath)
+ {
+#if FEATURE_PATHCOMPAT
+ if (AppContextSwitches.BlockLongPaths)
+ {
+ // We allow paths of any length if extended (and not in compat mode)
+ if (AppContextSwitches.UseLegacyPathHandling || !IsExtended(fullPath))
+ return (fullPath.Length >= MaxShortDirectoryPath);
+ }
+#endif
+
+ return IsPathTooLong(fullPath);
+ }
+
+ /// <summary>
+ /// Adds the extended path prefix (\\?\) if not relative or already a device path.
+ /// </summary>
+ internal static string EnsureExtendedPrefix(string path)
+ {
+ // Putting the extended prefix on the path changes the processing of the path. It won't get normalized, which
+ // means adding to relative paths will prevent them from getting the appropriate current directory inserted.
+
+ // If it already has some variant of a device path (\??\, \\?\, \\.\, //./, etc.) we don't need to change it
+ // as it is either correct or we will be changing the behavior. When/if Windows supports long paths implicitly
+ // in the future we wouldn't want normalization to come back and break existing code.
+
+ // In any case, all internal usages should be hitting normalize path (Path.GetFullPath) before they hit this
+ // shimming method. (Or making a change that doesn't impact normalization, such as adding a filename to a
+ // normalized base path.)
+ if (IsPartiallyQualified(path) || IsDevice(path))
+ return path;
+
+ // Given \\server\share in longpath becomes \\?\UNC\server\share
+ if (path.StartsWith(UncPathPrefix, StringComparison.OrdinalIgnoreCase))
+ return path.Insert(2, UncExtendedPrefixToInsert);
+
+ return ExtendedPathPrefix + path;
+ }
+
+ /// <summary>
+ /// Removes the extended path prefix (\\?\) if present.
+ /// </summary>
+ internal static string RemoveExtendedPrefix(string path)
+ {
+ if (!IsExtended(path))
+ return path;
+
+ // Given \\?\UNC\server\share we return \\server\share
+ if (IsExtendedUnc(path))
+ return path.Remove(2, 6);
+
+ return path.Substring(DevicePrefixLength);
+ }
+
+ /// <summary>
+ /// Removes the extended path prefix (\\?\) if present.
+ /// </summary>
+ internal static StringBuilder RemoveExtendedPrefix(StringBuilder path)
+ {
+ if (!IsExtended(path))
+ return path;
+
+ // Given \\?\UNC\server\share we return \\server\share
+ if (IsExtendedUnc(path))
+ return path.Remove(2, 6);
+
+ return path.Remove(0, DevicePrefixLength);
+ }
+
+ /// <summary>
+ /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\")
+ /// </summary>
+ internal static bool IsDevice(string path)
+ {
+ // If the path begins with any two separators it will be recognized and normalized and prepped with
+ // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not.
+ return IsExtended(path)
+ ||
+ (
+ path.Length >= DevicePrefixLength
+ && IsDirectorySeparator(path[0])
+ && IsDirectorySeparator(path[1])
+ && (path[2] == '.' || path[2] == '?')
+ && IsDirectorySeparator(path[3])
+ );
+ }
+
+ /// <summary>
+ /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\")
+ /// </summary>
+ internal static bool IsDevice(StringBuffer path)
+ {
+ // If the path begins with any two separators it will be recognized and normalized and prepped with
+ // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not.
+ return IsExtended(path)
+ ||
+ (
+ path.Length >= DevicePrefixLength
+ && IsDirectorySeparator(path[0])
+ && IsDirectorySeparator(path[1])
+ && (path[2] == '.' || path[2] == '?')
+ && IsDirectorySeparator(path[3])
+ );
+ }
+
+ /// <summary>
+ /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the
+ /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization
+ /// and path length checks.
+ /// </summary>
+ internal static bool IsExtended(string path)
+ {
+ // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths.
+ // Skipping of normalization will *only* occur if back slashes ('\') are used.
+ return path.Length >= DevicePrefixLength
+ && path[0] == '\\'
+ && (path[1] == '\\' || path[1] == '?')
+ && path[2] == '?'
+ && path[3] == '\\';
+ }
+
+ /// <summary>
+ /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the
+ /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization
+ /// and path length checks.
+ /// </summary>
+ internal static bool IsExtended(StringBuilder path)
+ {
+ // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths.
+ // Skipping of normalization will *only* occur if back slashes ('\') are used.
+ return path.Length >= DevicePrefixLength
+ && path[0] == '\\'
+ && (path[1] == '\\' || path[1] == '?')
+ && path[2] == '?'
+ && path[3] == '\\';
+ }
+
+ /// <summary>
+ /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the
+ /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization
+ /// and path length checks.
+ /// </summary>
+ internal static bool IsExtended(StringBuffer path)
+ {
+ // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths.
+ // Skipping of normalization will *only* occur if back slashes ('\') are used.
+ return path.Length >= DevicePrefixLength
+ && path[0] == '\\'
+ && (path[1] == '\\' || path[1] == '?')
+ && path[2] == '?'
+ && path[3] == '\\';
+ }
+
+ /// <summary>
+ /// Returns true if the path uses the extended UNC syntax (\\?\UNC\ or \??\UNC\)
+ /// </summary>
+ internal static bool IsExtendedUnc(string path)
+ {
+ return path.Length >= UncExtendedPathPrefix.Length
+ && IsExtended(path)
+ && char.ToUpper(path[4]) == 'U'
+ && char.ToUpper(path[5]) == 'N'
+ && char.ToUpper(path[6]) == 'C'
+ && path[7] == '\\';
+ }
+
+ /// <summary>
+ /// Returns true if the path uses the extended UNC syntax (\\?\UNC\ or \??\UNC\)
+ /// </summary>
+ internal static bool IsExtendedUnc(StringBuilder path)
+ {
+ return path.Length >= UncExtendedPathPrefix.Length
+ && IsExtended(path)
+ && char.ToUpper(path[4]) == 'U'
+ && char.ToUpper(path[5]) == 'N'
+ && char.ToUpper(path[6]) == 'C'
+ && path[7] == '\\';
+ }
+
+ /// <summary>
+ /// Returns a value indicating if the given path contains invalid characters (", &lt;, &gt;, |
+ /// NUL, or any ASCII char whose integer representation is in the range of 1 through 31).
+ /// Does not check for wild card characters ? and *.
+ ///
+ /// Will not check if the path is a device path and not in Legacy mode as many of these
+ /// characters are valid for devices (pipes for example).
+ /// </summary>
+ internal static bool HasIllegalCharacters(string path, bool checkAdditional = false)
+ {
+ if (
+#if FEATURE_PATHCOMPAT
+ !AppContextSwitches.UseLegacyPathHandling &&
+#endif
+ IsDevice(path))
+ {
+ return false;
+ }
+
+ return AnyPathHasIllegalCharacters(path, checkAdditional: checkAdditional);
+ }
+
+ /// <summary>
+ /// Version of HasIllegalCharacters that checks no AppContextSwitches. Only use if you know you need to skip switches and don't care
+ /// about proper device path handling.
+ /// </summary>
+ internal static bool AnyPathHasIllegalCharacters(string path, bool checkAdditional = false)
+ {
+ return path.IndexOfAny(InvalidPathChars) >= 0
+#if !PLATFORM_UNIX
+ || (checkAdditional && AnyPathHasWildCardCharacters(path))
+#endif
+ ;
+ }
+
+ /// <summary>
+ /// Check for ? and *.
+ /// </summary>
+ internal static bool HasWildCardCharacters(string path)
+ {
+ // Question mark is part of some device paths
+ int startIndex =
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.UseLegacyPathHandling ? 0 :
+#endif
+ IsDevice(path) ? ExtendedPathPrefix.Length : 0;
+ return AnyPathHasWildCardCharacters(path, startIndex: startIndex);
+ }
+
+ /// <summary>
+ /// Version of HasWildCardCharacters that checks no AppContextSwitches. Only use if you know you need to skip switches and don't care
+ /// about proper device path handling.
+ /// </summary>
+ internal static bool AnyPathHasWildCardCharacters(string path, int startIndex = 0)
+ {
+ char currentChar;
+ for (int i = startIndex; i < path.Length; i++)
+ {
+ currentChar = path[i];
+ if (currentChar == '*' || currentChar == '?') return true;
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets the length of the root of the path (drive, share, etc.).
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ internal unsafe static int GetRootLength(string path)
+ {
+ fixed (char* value = path)
+ {
+ return (int)GetRootLength(value, (ulong)path.Length);
+ }
+ }
+
+ /// <summary>
+ /// Gets the length of the root of the path (drive, share, etc.).
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ internal unsafe static uint GetRootLength(StringBuffer path)
+ {
+ if (path.Length == 0) return 0;
+ return GetRootLength(path.CharPointer, path.Length);
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe static uint GetRootLength(char* path, ulong pathLength)
+ {
+ uint i = 0;
+
+#if PLATFORM_UNIX
+ if (pathLength >= 1 && (IsDirectorySeparator(path[0])))
+ i = 1;
+#else
+ uint volumeSeparatorLength = 2; // Length to the colon "C:"
+ uint uncRootLength = 2; // Length to the start of the server name "\\"
+
+ bool extendedSyntax = StartsWithOrdinal(path, pathLength, ExtendedPathPrefix);
+ bool extendedUncSyntax = StartsWithOrdinal(path, pathLength, UncExtendedPathPrefix);
+ if (extendedSyntax)
+ {
+ // Shift the position we look for the root from to account for the extended prefix
+ if (extendedUncSyntax)
+ {
+ // "\\" -> "\\?\UNC\"
+ uncRootLength = (uint)UncExtendedPathPrefix.Length;
+ }
+ else
+ {
+ // "C:" -> "\\?\C:"
+ volumeSeparatorLength += (uint)ExtendedPathPrefix.Length;
+ }
+ }
+
+ if ((!extendedSyntax || extendedUncSyntax) && pathLength > 0 && IsDirectorySeparator(path[0]))
+ {
+ // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo")
+
+ i = 1; // Drive rooted (\foo) is one character
+ if (extendedUncSyntax || (pathLength > 1 && IsDirectorySeparator(path[1])))
+ {
+ // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most
+ // (e.g. to \\?\UNC\Server\Share or \\Server\Share\)
+ i = uncRootLength;
+ int n = 2; // Maximum separators to skip
+ while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0)) i++;
+ }
+ }
+ else if (pathLength >= volumeSeparatorLength && path[volumeSeparatorLength - 1] == Path.VolumeSeparatorChar)
+ {
+ // Path is at least longer than where we expect a colon, and has a colon (\\?\A:, A:)
+ // If the colon is followed by a directory separator, move past it
+ i = volumeSeparatorLength;
+ if (pathLength >= volumeSeparatorLength + 1 && IsDirectorySeparator(path[volumeSeparatorLength])) i++;
+ }
+#endif // !PLATFORM_UNIX
+ return i;
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe static bool StartsWithOrdinal(char* source, ulong sourceLength, string value)
+ {
+ if (sourceLength < (ulong)value.Length) return false;
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (value[i] != source[i]) return false;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// Returns true if the path specified is relative to the current drive or working directory.
+ /// Returns false if the path is fixed to a specific drive or UNC path. This method does no
+ /// validation of the path (URIs will be returned as relative as a result).
+ /// </summary>
+ /// <remarks>
+ /// Handles paths that use the alternate directory separator. It is a frequent mistake to
+ /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case.
+ /// "C:a" is drive relative- meaning that it will be resolved against the current directory
+ /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory
+ /// will not be used to modify the path).
+ /// </remarks>
+ internal static bool IsPartiallyQualified(string path)
+ {
+#if PLATFORM_UNIX
+ return !(path.Length >= 1 && path[0] == Path.DirectorySeparatorChar);
+#else
+ if (path.Length < 2)
+ {
+ // It isn't fixed, it must be relative. There is no way to specify a fixed
+ // path with one character (or less).
+ return true;
+ }
+
+ if (IsDirectorySeparator(path[0]))
+ {
+ // There is no valid way to specify a relative path with two initial slashes or
+ // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
+ return !(path[1] == '?' || IsDirectorySeparator(path[1]));
+ }
+
+ // The only way to specify a fixed path that doesn't begin with two slashes
+ // is the drive, colon, slash format- i.e. C:\
+ return !((path.Length >= 3)
+ && (path[1] == Path.VolumeSeparatorChar)
+ && IsDirectorySeparator(path[2])
+ // To match old behavior we'll check the drive character for validity as the path is technically
+ // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
+ && IsValidDriveChar(path[0]));
+#endif // !PLATFORM_UNIX
+ }
+
+ /// <summary>
+ /// Returns true if the path specified is relative to the current drive or working directory.
+ /// Returns false if the path is fixed to a specific drive or UNC path. This method does no
+ /// validation of the path (URIs will be returned as relative as a result).
+ /// </summary>
+ /// <remarks>
+ /// Handles paths that use the alternate directory separator. It is a frequent mistake to
+ /// assume that rooted paths (Path.IsPathRooted) are not relative. This isn't the case.
+ /// "C:a" is drive relative- meaning that it will be resolved against the current directory
+ /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory
+ /// will not be used to modify the path).
+ /// </remarks>
+ internal static bool IsPartiallyQualified(StringBuffer path)
+ {
+#if PLATFORM_UNIX
+ return !(path.Length >= 1 && path[0] == Path.DirectorySeparatorChar);
+#else
+ if (path.Length < 2)
+ {
+ // It isn't fixed, it must be relative. There is no way to specify a fixed
+ // path with one character (or less).
+ return true;
+ }
+
+ if (IsDirectorySeparator(path[0]))
+ {
+ // There is no valid way to specify a relative path with two initial slashes or
+ // \? as ? isn't valid for drive relative paths and \??\ is equivalent to \\?\
+ return !(path[1] == '?' || IsDirectorySeparator(path[1]));
+ }
+
+ // The only way to specify a fixed path that doesn't begin with two slashes
+ // is the drive, colon, slash format- i.e. C:\
+ return !((path.Length >= 3)
+ && (path[1] == Path.VolumeSeparatorChar)
+ && IsDirectorySeparator(path[2])
+ // To match old behavior we'll check the drive character for validity as the path is technically
+ // not qualified if you don't have a valid drive. "=:\" is the "=" file's default data stream.
+ && IsValidDriveChar(path[0]));
+#endif // !PLATFORM_UNIX
+ }
+
+ /// <summary>
+ /// On Windows, returns the characters to skip at the start of the path if it starts with space(s) and a drive or directory separator.
+ /// (examples are " C:", " \")
+ /// This is a legacy behavior of Path.GetFullPath().
+ /// </summary>
+ /// <remarks>
+ /// Note that this conflicts with IsPathRooted() which doesn't (and never did) such a skip.
+ /// </remarks>
+ internal static int PathStartSkip(string path)
+ {
+#if !PLATFORM_UNIX
+ int startIndex = 0;
+ while (startIndex < path.Length && path[startIndex] == ' ') startIndex++;
+
+ if (startIndex > 0 && (startIndex < path.Length && IsDirectorySeparator(path[startIndex]))
+ || (startIndex + 1 < path.Length && path[startIndex + 1] == Path.VolumeSeparatorChar && IsValidDriveChar(path[startIndex])))
+ {
+ // Go ahead and skip spaces as we're either " C:" or " \"
+ return startIndex;
+ }
+#endif
+
+ return 0;
+ }
+
+ /// <summary>
+ /// True if the given character is a directory separator.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool IsDirectorySeparator(char c)
+ {
+ return c == Path.DirectorySeparatorChar
+#if !PLATFORM_UNIX
+ || c == Path.AltDirectorySeparatorChar
+#endif
+ ;
+ }
+
+ /// <summary>
+ /// Normalize separators in the given path. Converts forward slashes into back slashes and compresses slash runs, keeping initial 2 if present.
+ /// Also trims initial whitespace in front of "rooted" paths (see PathStartSkip).
+ ///
+ /// This effectively replicates the behavior of the legacy NormalizePath when it was called with fullCheck=false and expandShortpaths=false.
+ /// The current NormalizePath gets directory separator normalization from Win32's GetFullPathName(), which will resolve relative paths and as
+ /// such can't be used here (and is overkill for our uses).
+ ///
+ /// Like the current NormalizePath this will not try and analyze periods/spaces within directory segments.
+ /// </summary>
+ /// <remarks>
+ /// The only callers that used to use Path.Normalize(fullCheck=false) were Path.GetDirectoryName() and Path.GetPathRoot(). Both usages do
+ /// not need trimming of trailing whitespace here.
+ ///
+ /// GetPathRoot() could technically skip normalizing separators after the second segment- consider as a future optimization.
+ ///
+ /// For legacy desktop behavior with ExpandShortPaths:
+ /// - It has no impact on GetPathRoot() so doesn't need consideration.
+ /// - It could impact GetDirectoryName(), but only if the path isn't relative (C:\ or \\Server\Share).
+ ///
+ /// In the case of GetDirectoryName() the ExpandShortPaths behavior was undocumented and provided inconsistent results if the path was
+ /// fixed/relative. For example: "C:\PROGRA~1\A.TXT" would return "C:\Program Files" while ".\PROGRA~1\A.TXT" would return ".\PROGRA~1". If you
+ /// ultimately call GetFullPath() this doesn't matter, but if you don't or have any intermediate string handling could easily be tripped up by
+ /// this undocumented behavior.
+ /// </remarks>
+ internal static string NormalizeDirectorySeparators(string path)
+ {
+ if (string.IsNullOrEmpty(path)) return path;
+
+ char current;
+ int start = PathStartSkip(path);
+
+ if (start == 0)
+ {
+ // Make a pass to see if we need to normalize so we can potentially skip allocating
+ bool normalized = true;
+
+ for (int i = 0; i < path.Length; i++)
+ {
+ current = path[i];
+ if (IsDirectorySeparator(current)
+ && (current != Path.DirectorySeparatorChar
+#if !PLATFORM_UNIX
+ // Check for sequential separators past the first position (we need to keep initial two for UNC/extended)
+ || (i > 0 && i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))
+#endif
+ ))
+ {
+ normalized = false;
+ break;
+ }
+ }
+
+ if (normalized) return path;
+ }
+
+ StringBuilder builder = StringBuilderCache.Acquire(path.Length);
+
+#if !PLATFORM_UNIX
+ // On Windows we always keep the first separator, even if the next is a separator (we need to keep initial two for UNC/extended)
+ if (IsDirectorySeparator(path[start]))
+ {
+ start++;
+ builder.Append(Path.DirectorySeparatorChar);
+ }
+#endif
+
+ for (int i = start; i < path.Length; i++)
+ {
+ current = path[i];
+
+ // If we have a separator
+ if (IsDirectorySeparator(current))
+ {
+ // If the next is a separator, skip adding this
+ if (i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))
+ {
+ continue;
+ }
+
+ // Ensure it is the primary separator
+ current = Path.DirectorySeparatorChar;
+ }
+
+ builder.Append(current);
+ }
+
+ return StringBuilderCache.GetStringAndRelease(builder);
+ }
+
+#if PLATFORM_UNIX
+ // We rely on Windows to remove relative segments on Windows. This would need to be updated to
+ // handle the proper rooting on Windows if we for some reason need it.
+
+ /// <summary>
+ /// Try to remove relative segments from the given path (without combining with a root).
+ /// </summary>
+ /// <param name="skip">Skip the specified number of characters before evaluating.</param>
+ internal static string RemoveRelativeSegments(string path, int skip = 0)
+ {
+ bool flippedSeparator = false;
+
+ // Remove "//", "/./", and "/../" from the path by copying each character to the output,
+ // except the ones we're removing, such that the builder contains the normalized path
+ // at the end.
+ var sb = StringBuilderCache.Acquire(path.Length);
+ if (skip > 0)
+ {
+ sb.Append(path, 0, skip);
+ }
+
+ int componentCharCount = 0;
+ for (int i = skip; i < path.Length; i++)
+ {
+ char c = path[i];
+
+ if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
+ {
+ componentCharCount = 0;
+
+ // Skip this character if it's a directory separator and if the next character is, too,
+ // e.g. "parent//child" => "parent/child"
+ if (PathInternal.IsDirectorySeparator(path[i + 1]))
+ {
+ continue;
+ }
+
+ // Skip this character and the next if it's referring to the current directory,
+ // e.g. "parent/./child" =? "parent/child"
+ if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
+ path[i + 1] == '.')
+ {
+ i++;
+ continue;
+ }
+
+ // Skip this character and the next two if it's referring to the parent directory,
+ // e.g. "parent/child/../grandchild" => "parent/grandchild"
+ if (i + 2 < path.Length &&
+ (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
+ path[i + 1] == '.' && path[i + 2] == '.')
+ {
+ // Unwind back to the last slash (and if there isn't one, clear out everything).
+ int s;
+ for (s = sb.Length - 1; s >= 0; s--)
+ {
+ if (PathInternal.IsDirectorySeparator(sb[s]))
+ {
+ sb.Length = s;
+ break;
+ }
+ }
+ if (s < 0)
+ {
+ sb.Length = 0;
+ }
+
+ i += 2;
+ continue;
+ }
+ }
+
+ if (++componentCharCount > PathInternal.MaxComponentLength)
+ {
+ throw new PathTooLongException();
+ }
+
+ // Normalize the directory separator if needed
+ if (c != Path.DirectorySeparatorChar && c == Path.AltDirectorySeparatorChar)
+ {
+ c = Path.DirectorySeparatorChar;
+ flippedSeparator = true;
+ }
+
+ sb.Append(c);
+ }
+
+ if (flippedSeparator || sb.Length != path.Length)
+ {
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+ else
+ {
+ // We haven't changed the source path, return the original
+ StringBuilderCache.Release(sb);
+ return path;
+ }
+ }
+#endif // PLATFORM_UNIX
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/IO/PathTooLongException.cs b/src/mscorlib/src/System/IO/PathTooLongException.cs
new file mode 100644
index 0000000000..b1063232a1
--- /dev/null
+++ b/src/mscorlib/src/System/IO/PathTooLongException.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception for paths and/or filenames that are
+** too long.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.IO {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class PathTooLongException : IOException
+ {
+ public PathTooLongException()
+ : base(Environment.GetResourceString("IO.PathTooLong")) {
+ SetErrorCode(__HResults.COR_E_PATHTOOLONG);
+ }
+
+ public PathTooLongException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_PATHTOOLONG);
+ }
+
+ public PathTooLongException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_PATHTOOLONG);
+ }
+
+ protected PathTooLongException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs b/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs
new file mode 100644
index 0000000000..4fd54f57f5
--- /dev/null
+++ b/src/mscorlib/src/System/IO/PinnedBufferMemoryStream.cs
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Pins a byte[], exposing it as an unmanaged memory
+** stream. Used in ResourceReader for corner cases.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ internal sealed unsafe class PinnedBufferMemoryStream : UnmanagedMemoryStream
+ {
+ private byte[] _array;
+ private GCHandle _pinningHandle;
+
+ // The new inheritance model requires a Critical default ctor since base (UnmanagedMemoryStream) has one
+ [System.Security.SecurityCritical]
+ private PinnedBufferMemoryStream():base(){}
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal PinnedBufferMemoryStream(byte[] array)
+ {
+ Contract.Assert(array != null, "Array can't be null");
+
+ int len = array.Length;
+ // Handle 0 length byte arrays specially.
+ if (len == 0) {
+ array = new byte[1];
+ len = 0;
+ }
+
+ _array = array;
+ _pinningHandle = new GCHandle(array, GCHandleType.Pinned);
+ // Now the byte[] is pinned for the lifetime of this instance.
+ // But I also need to get a pointer to that block of memory...
+ fixed(byte* ptr = _array)
+ Initialize(ptr, len, len, FileAccess.Read, true);
+ }
+
+ ~PinnedBufferMemoryStream()
+ {
+ Dispose(false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override void Dispose(bool disposing)
+ {
+ if (_isOpen) {
+ _pinningHandle.Free();
+ _isOpen = false;
+ }
+#if _DEBUG
+ // To help track down lifetime issues on checked builds, force
+ //a full GC here.
+ if (disposing) {
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ }
+#endif
+ base.Dispose(disposing);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/ReadLinesIterator.cs b/src/mscorlib/src/System/IO/ReadLinesIterator.cs
new file mode 100644
index 0000000000..ce2ad2ad0f
--- /dev/null
+++ b/src/mscorlib/src/System/IO/ReadLinesIterator.cs
@@ -0,0 +1,102 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.Versioning;
+using System.Text;
+
+namespace System.IO
+{
+ // An iterator that returns a single line at-a-time from a given file.
+ //
+ // Known issues which cannot be changed to remain compatible with 4.0:
+ //
+ // - The underlying StreamReader is allocated upfront for the IEnumerable<T> before
+ // GetEnumerator has even been called. While this is good in that exceptions such as
+ // DirectoryNotFoundException and FileNotFoundException are thrown directly by
+ // File.ReadLines (which the user probably expects), it also means that the reader
+ // will be leaked if the user never actually foreach's over the enumerable (and hence
+ // calls Dispose on at least one IEnumerator<T> instance).
+ //
+ // - Reading to the end of the IEnumerator<T> disposes it. This means that Dispose
+ // is called twice in a normal foreach construct.
+ //
+ // - IEnumerator<T> instances from the same IEnumerable<T> party on the same underlying
+ // reader (Dev10 Bugs 904764).
+ //
+ internal class ReadLinesIterator : Iterator<string>
+ {
+ private readonly string _path;
+ private readonly Encoding _encoding;
+ private StreamReader _reader;
+
+ private ReadLinesIterator(string path, Encoding encoding, StreamReader reader)
+ {
+ Contract.Requires(path != null);
+ Contract.Requires(path.Length > 0);
+ Contract.Requires(encoding != null);
+ Contract.Requires(reader != null);
+
+ _path = path;
+ _encoding = encoding;
+ _reader = reader;
+ }
+
+ public override bool MoveNext()
+ {
+ if (this._reader != null)
+ {
+ this.current = _reader.ReadLine();
+ if (this.current != null)
+ return true;
+
+ // To maintain 4.0 behavior we Dispose
+ // after reading to the end of the reader.
+ Dispose();
+ }
+
+ return false;
+ }
+
+ protected override Iterator<string> Clone()
+ {
+ // NOTE: To maintain the same behavior with the previous yield-based
+ // iterator in 4.0, we have all the IEnumerator<T> instances share the same
+ // underlying reader. If we have already been disposed, _reader will be null,
+ // which will cause CreateIterator to simply new up a new instance to start up
+ // a new iteration. Dev10 Bugs 904764 has been filed to fix this in next side-
+ // by-side release.
+ return CreateIterator(_path, _encoding, _reader);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ try
+ {
+ if (disposing)
+ {
+ if (_reader != null)
+ {
+ _reader.Dispose();
+ }
+ }
+ }
+ finally
+ {
+ _reader = null;
+ base.Dispose(disposing);
+ }
+ }
+
+ internal static ReadLinesIterator CreateIterator(string path, Encoding encoding)
+ {
+ return CreateIterator(path, encoding, (StreamReader)null);
+ }
+
+ private static ReadLinesIterator CreateIterator(string path, Encoding encoding, StreamReader reader)
+ {
+ return new ReadLinesIterator(path, encoding, reader ?? new StreamReader(path, encoding));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/SearchOption.cs b/src/mscorlib/src/System/IO/SearchOption.cs
new file mode 100644
index 0000000000..aa9b9e37f8
--- /dev/null
+++ b/src/mscorlib/src/System/IO/SearchOption.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: SearchOption
+**
+**
+**
+**
+** Purpose: Enum describing whether the search operation should
+** retrieve files/directories from the current directory alone
+** or should include all the subdirectories also.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO {
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum SearchOption
+ {
+ // Include only the current directory in the search operation
+ TopDirectoryOnly,
+
+ // Include the current directory and all the sub-directories
+ // underneath it including reparse points in the search operation.
+ // This will traverse reparse points (i.e, mounted points and symbolic links)
+ // recursively. If the directory structure searched contains a loop
+ // because of hard links, the search operation will go on for ever.
+ AllDirectories,
+ }
+}
diff --git a/src/mscorlib/src/System/IO/SeekOrigin.cs b/src/mscorlib/src/System/IO/SeekOrigin.cs
new file mode 100644
index 0000000000..a0a013e7aa
--- /dev/null
+++ b/src/mscorlib/src/System/IO/SeekOrigin.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: SeekOrigin
+**
+**
+**
+**
+** Purpose: Enum describing locations in a stream you could
+** seek relative to.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.IO {
+ // Provides seek reference points. To seek to the end of a stream,
+ // call stream.Seek(0, SeekOrigin.End).
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum SeekOrigin
+ {
+ // These constants match Win32's FILE_BEGIN, FILE_CURRENT, and FILE_END
+ Begin = 0,
+ Current = 1,
+ End = 2,
+ }
+}
diff --git a/src/mscorlib/src/System/IO/Stream.cs b/src/mscorlib/src/System/IO/Stream.cs
new file mode 100644
index 0000000000..a1f29364cb
--- /dev/null
+++ b/src/mscorlib/src/System/IO/Stream.cs
@@ -0,0 +1,1304 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstract base class for all Streams. Provides
+** default implementations of asynchronous reads & writes, in
+** terms of the synchronous reads & writes (and vice versa).
+**
+**
+===========================================================*/
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+using System.Runtime;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+using System.Reflection;
+
+namespace System.IO {
+ [Serializable]
+ [ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class Stream : MarshalByRefObject, IDisposable {
+#else // FEATURE_REMOTING
+ public abstract class Stream : IDisposable {
+#endif // FEATURE_REMOTING
+
+ public static readonly Stream Null = new NullStream();
+
+ //We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
+ // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
+ // improvement in Copy performance.
+ private const int _DefaultCopyBufferSize = 81920;
+
+ // To implement Async IO operations on streams that don't support async IO
+
+ [NonSerialized]
+ private ReadWriteTask _activeReadWriteTask;
+ [NonSerialized]
+ private SemaphoreSlim _asyncActiveSemaphore;
+
+ internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
+ {
+ // Lazily-initialize _asyncActiveSemaphore. As we're never accessing the SemaphoreSlim's
+ // WaitHandle, we don't need to worry about Disposing it.
+ return LazyInitializer.EnsureInitialized(ref _asyncActiveSemaphore, () => new SemaphoreSlim(1, 1));
+ }
+
+ public abstract bool CanRead {
+ [Pure]
+ get;
+ }
+
+ // If CanSeek is false, Position, Seek, Length, and SetLength should throw.
+ public abstract bool CanSeek {
+ [Pure]
+ get;
+ }
+
+ [ComVisible(false)]
+ public virtual bool CanTimeout {
+ [Pure]
+ get {
+ return false;
+ }
+ }
+
+ public abstract bool CanWrite {
+ [Pure]
+ get;
+ }
+
+ public abstract long Length {
+ get;
+ }
+
+ public abstract long Position {
+ get;
+ set;
+ }
+
+ [ComVisible(false)]
+ public virtual int ReadTimeout {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
+ }
+ set {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
+ }
+ }
+
+ [ComVisible(false)]
+ public virtual int WriteTimeout {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
+ }
+ set {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TimeoutsNotSupported"));
+ }
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task CopyToAsync(Stream destination)
+ {
+ int bufferSize = _DefaultCopyBufferSize;
+
+#if FEATURE_CORECLR
+ if (CanSeek)
+ {
+ long length = Length;
+ long position = Position;
+ if (length <= position) // Handles negative overflows
+ {
+ // If we go down this branch, it means there are
+ // no bytes left in this stream.
+
+ // Ideally we would just return Task.CompletedTask here,
+ // but CopyToAsync(Stream, int, CancellationToken) was already
+ // virtual at the time this optimization was introduced. So
+ // if it does things like argument validation (checking if destination
+ // is null and throwing an exception), then await fooStream.CopyToAsync(null)
+ // would no longer throw if there were no bytes left. On the other hand,
+ // we also can't roll our own argument validation and return Task.CompletedTask,
+ // because it would be a breaking change if the stream's override didn't throw before,
+ // or in a different order. So for simplicity, we just set the bufferSize to 1
+ // (not 0 since the default implementation throws for 0) and forward to the virtual method.
+ bufferSize = 1;
+ }
+ else
+ {
+ long remaining = length - position;
+ if (remaining > 0) // In the case of a positive overflow, stick to the default size
+ bufferSize = (int)Math.Min(bufferSize, remaining);
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ return CopyToAsync(destination, bufferSize);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task CopyToAsync(Stream destination, Int32 bufferSize)
+ {
+ return CopyToAsync(destination, bufferSize, CancellationToken.None);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
+ {
+ ValidateCopyToArguments(destination, bufferSize);
+
+ return CopyToAsyncInternal(destination, bufferSize, cancellationToken);
+ }
+
+ private async Task CopyToAsyncInternal(Stream destination, Int32 bufferSize, CancellationToken cancellationToken)
+ {
+ Contract.Requires(destination != null);
+ Contract.Requires(bufferSize > 0);
+ Contract.Requires(CanRead);
+ Contract.Requires(destination.CanWrite);
+
+ byte[] buffer = new byte[bufferSize];
+ int bytesRead;
+ while ((bytesRead = await ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0)
+ {
+ await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ // Reads the bytes from the current stream and writes the bytes to
+ // the destination stream until all bytes are read, starting at
+ // the current position.
+ public void CopyTo(Stream destination)
+ {
+ int bufferSize = _DefaultCopyBufferSize;
+
+#if FEATURE_CORECLR
+ if (CanSeek)
+ {
+ long length = Length;
+ long position = Position;
+ if (length <= position) // Handles negative overflows
+ {
+ // No bytes left in stream
+ // Call the other overload with a bufferSize of 1,
+ // in case it's made virtual in the future
+ bufferSize = 1;
+ }
+ else
+ {
+ long remaining = length - position;
+ if (remaining > 0) // In the case of a positive overflow, stick to the default size
+ bufferSize = (int)Math.Min(bufferSize, remaining);
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ CopyTo(destination, bufferSize);
+ }
+
+ public virtual void CopyTo(Stream destination, int bufferSize)
+ {
+ ValidateCopyToArguments(destination, bufferSize);
+
+ byte[] buffer = new byte[bufferSize];
+ int read;
+ while ((read = Read(buffer, 0, buffer.Length)) != 0)
+ destination.Write(buffer, 0, read);
+ }
+
+ // Stream used to require that all cleanup logic went into Close(),
+ // which was thought up before we invented IDisposable. However, we
+ // need to follow the IDisposable pattern so that users can write
+ // sensible subclasses without needing to inspect all their base
+ // classes, and without worrying about version brittleness, from a
+ // base class switching to the Dispose pattern. We're moving
+ // Stream to the Dispose(bool) pattern - that's where all subclasses
+ // should put their cleanup starting in V2.
+ public virtual void Close()
+ {
+ /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully.
+ Contract.Ensures(CanRead == false);
+ Contract.Ensures(CanWrite == false);
+ Contract.Ensures(CanSeek == false);
+ */
+
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public void Dispose()
+ {
+ /* These are correct, but we'd have to fix PipeStream & NetworkStream very carefully.
+ Contract.Ensures(CanRead == false);
+ Contract.Ensures(CanWrite == false);
+ Contract.Ensures(CanSeek == false);
+ */
+
+ Close();
+ }
+
+
+ protected virtual void Dispose(bool disposing)
+ {
+ // Note: Never change this to call other virtual methods on Stream
+ // like Write, since the state on subclasses has already been
+ // torn down. This is the last code to run on cleanup for a stream.
+ }
+
+ public abstract void Flush();
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public Task FlushAsync()
+ {
+ return FlushAsync(CancellationToken.None);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public virtual Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(state => ((Stream)state).Flush(), this,
+ cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [Obsolete("CreateWaitHandle will be removed eventually. Please use \"new ManualResetEvent(false)\" instead.")]
+ protected virtual WaitHandle CreateWaitHandle()
+ {
+ Contract.Ensures(Contract.Result<WaitHandle>() != null);
+ return new ManualResetEvent(false);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ public virtual IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+ return BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ internal IAsyncResult BeginReadInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, Object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+ if (!CanRead) __Error.ReadNotSupported();
+
+ // To avoid a race with a stream's position pointer & generating race conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync();
+ }
+ else
+ {
+ semaphore.Wait();
+ }
+
+ // Create the task to asynchronously do a Read. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(true /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Read.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Read and return the number of bytes read
+ return thisTask._stream.Read(thisTask._buffer, thisTask._offset, thisTask._count);
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+
+ return asyncResult; // return it
+ }
+
+ public virtual int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.EndContractBlock();
+
+ var readTask = _activeReadWriteTask;
+
+ if (readTask == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
+ }
+ else if (readTask != asyncResult)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
+ }
+ else if (!readTask._isRead)
+ {
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple"));
+ }
+
+ try
+ {
+ return readTask.GetAwaiter().GetResult(); // block until completion, then get result / propagate any exception
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task<int> ReadAsync(Byte[] buffer, int offset, int count)
+ {
+ return ReadAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled<int>(cancellationToken)
+ : BeginEndReadAsync(buffer, offset, count);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool HasOverriddenBeginEndRead();
+
+ private Task<Int32> BeginEndReadAsync(Byte[] buffer, Int32 offset, Int32 count)
+ {
+ if (!HasOverriddenBeginEndRead())
+ {
+ // If the Stream does not override Begin/EndRead, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task<Int32>)BeginReadInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<Int32>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer = buffer, Offset = offset, Count = count },
+ (stream, args, callback, state) => stream.BeginRead(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => stream.EndRead(asyncResult)); // cached by compiler
+ }
+
+ private struct ReadWriteParameters // struct for arguments to Read and Write calls
+ {
+ internal byte[] Buffer;
+ internal int Offset;
+ internal int Count;
+ }
+
+
+
+ [HostProtection(ExternalThreading=true)]
+ public virtual IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+ return BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: false, apm: true);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ internal IAsyncResult BeginWriteInternal(
+ byte[] buffer, int offset, int count, AsyncCallback callback, Object state,
+ bool serializeAsynchronously, bool apm)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread if it does a second IO request until the first one completes.
+ var semaphore = EnsureAsyncActiveSemaphoreInitialized();
+ Task semaphoreTask = null;
+ if (serializeAsynchronously)
+ {
+ semaphoreTask = semaphore.WaitAsync(); // kick off the asynchronous wait, but don't block
+ }
+ else
+ {
+ semaphore.Wait(); // synchronously wait here
+ }
+
+ // Create the task to asynchronously do a Write. This task serves both
+ // as the asynchronous work item and as the IAsyncResult returned to the user.
+ var asyncResult = new ReadWriteTask(false /*isRead*/, apm, delegate
+ {
+ // The ReadWriteTask stores all of the parameters to pass to Write.
+ // As we're currently inside of it, we can get the current task
+ // and grab the parameters from it.
+ var thisTask = Task.InternalCurrent as ReadWriteTask;
+ Contract.Assert(thisTask != null, "Inside ReadWriteTask, InternalCurrent should be the ReadWriteTask");
+
+ try
+ {
+ // Do the Write
+ thisTask._stream.Write(thisTask._buffer, thisTask._offset, thisTask._count);
+ return 0; // not used, but signature requires a value be returned
+ }
+ finally
+ {
+ // If this implementation is part of Begin/EndXx, then the EndXx method will handle
+ // finishing the async operation. However, if this is part of XxAsync, then there won't
+ // be an end method, and this task is responsible for cleaning up.
+ if (!thisTask._apm)
+ {
+ thisTask._stream.FinishTrackingAsyncOperation();
+ }
+
+ thisTask.ClearBeginState(); // just to help alleviate some memory pressure
+ }
+ }, state, this, buffer, offset, count, callback);
+
+ // Schedule it
+ if (semaphoreTask != null)
+ RunReadWriteTaskWhenReady(semaphoreTask, asyncResult);
+ else
+ RunReadWriteTask(asyncResult);
+
+ return asyncResult; // return it
+ }
+
+ private void RunReadWriteTaskWhenReady(Task asyncWaiter, ReadWriteTask readWriteTask)
+ {
+ Contract.Assert(readWriteTask != null); // Should be Contract.Requires, but CCRewrite is doing a poor job with
+ // preconditions in async methods that await.
+ Contract.Assert(asyncWaiter != null); // Ditto
+
+ // If the wait has already completed, run the task.
+ if (asyncWaiter.IsCompleted)
+ {
+ Contract.Assert(asyncWaiter.IsRanToCompletion, "The semaphore wait should always complete successfully.");
+ RunReadWriteTask(readWriteTask);
+ }
+ else // Otherwise, wait for our turn, and then run the task.
+ {
+ asyncWaiter.ContinueWith((t, state) => {
+ Contract.Assert(t.IsRanToCompletion, "The semaphore wait should always complete successfully.");
+ var rwt = (ReadWriteTask)state;
+ rwt._stream.RunReadWriteTask(rwt); // RunReadWriteTask(readWriteTask);
+ }, readWriteTask, default(CancellationToken), TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
+ }
+ }
+
+ private void RunReadWriteTask(ReadWriteTask readWriteTask)
+ {
+ Contract.Requires(readWriteTask != null);
+ Contract.Assert(_activeReadWriteTask == null, "Expected no other readers or writers");
+
+ // Schedule the task. ScheduleAndStart must happen after the write to _activeReadWriteTask to avoid a race.
+ // Internally, we're able to directly call ScheduleAndStart rather than Start, avoiding
+ // two interlocked operations. However, if ReadWriteTask is ever changed to use
+ // a cancellation token, this should be changed to use Start.
+ _activeReadWriteTask = readWriteTask; // store the task so that EndXx can validate it's given the right one
+ readWriteTask.m_taskScheduler = TaskScheduler.Default;
+ readWriteTask.ScheduleAndStart(needsProtection: false);
+ }
+
+ private void FinishTrackingAsyncOperation()
+ {
+ _activeReadWriteTask = null;
+ Contract.Assert(_asyncActiveSemaphore != null, "Must have been initialized in order to get here.");
+ _asyncActiveSemaphore.Release();
+ }
+
+ public virtual void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult==null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ var writeTask = _activeReadWriteTask;
+ if (writeTask == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
+ }
+ else if (writeTask != asyncResult)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
+ }
+ else if (writeTask._isRead)
+ {
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple"));
+ }
+
+ try
+ {
+ writeTask.GetAwaiter().GetResult(); // block until completion, then propagate any exceptions
+ Contract.Assert(writeTask.Status == TaskStatus.RanToCompletion);
+ }
+ finally
+ {
+ FinishTrackingAsyncOperation();
+ }
+ }
+
+ // Task used by BeginRead / BeginWrite to do Read / Write asynchronously.
+ // A single instance of this task serves four purposes:
+ // 1. The work item scheduled to run the Read / Write operation
+ // 2. The state holding the arguments to be passed to Read / Write
+ // 3. The IAsyncResult returned from BeginRead / BeginWrite
+ // 4. The completion action that runs to invoke the user-provided callback.
+ // This last item is a bit tricky. Before the AsyncCallback is invoked, the
+ // IAsyncResult must have completed, so we can't just invoke the handler
+ // from within the task, since it is the IAsyncResult, and thus it's not
+ // yet completed. Instead, we use AddCompletionAction to install this
+ // task as its own completion handler. That saves the need to allocate
+ // a separate completion handler, it guarantees that the task will
+ // have completed by the time the handler is invoked, and it allows
+ // the handler to be invoked synchronously upon the completion of the
+ // task. This all enables BeginRead / BeginWrite to be implemented
+ // with a single allocation.
+ private sealed class ReadWriteTask : Task<int>, ITaskCompletionAction
+ {
+ internal readonly bool _isRead;
+ internal readonly bool _apm; // true if this is from Begin/EndXx; false if it's from XxAsync
+ internal Stream _stream;
+ internal byte [] _buffer;
+ internal readonly int _offset;
+ internal readonly int _count;
+ private AsyncCallback _callback;
+ private ExecutionContext _context;
+
+ internal void ClearBeginState() // Used to allow the args to Read/Write to be made available for GC
+ {
+ _stream = null;
+ _buffer = null;
+ }
+
+ [SecuritySafeCritical] // necessary for EC.Capture
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ public ReadWriteTask(
+ bool isRead,
+ bool apm,
+ Func<object,int> function, object state,
+ Stream stream, byte[] buffer, int offset, int count, AsyncCallback callback) :
+ base(function, state, CancellationToken.None, TaskCreationOptions.DenyChildAttach)
+ {
+ Contract.Requires(function != null);
+ Contract.Requires(stream != null);
+ Contract.Requires(buffer != null);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // Store the arguments
+ _isRead = isRead;
+ _apm = apm;
+ _stream = stream;
+ _buffer = buffer;
+ _offset = offset;
+ _count = count;
+
+ // If a callback was provided, we need to:
+ // - Store the user-provided handler
+ // - Capture an ExecutionContext under which to invoke the handler
+ // - Add this task as its own completion handler so that the Invoke method
+ // will run the callback when this task completes.
+ if (callback != null)
+ {
+ _callback = callback;
+ _context = ExecutionContext.Capture(ref stackMark,
+ ExecutionContext.CaptureOptions.OptimizeDefaultCase | ExecutionContext.CaptureOptions.IgnoreSyncCtx);
+ base.AddCompletionAction(this);
+ }
+ }
+
+ [SecurityCritical] // necessary for CoreCLR
+ private static void InvokeAsyncCallback(object completedTask)
+ {
+ var rwc = (ReadWriteTask)completedTask;
+ var callback = rwc._callback;
+ rwc._callback = null;
+ callback(rwc);
+ }
+
+ [SecurityCritical] // necessary for CoreCLR
+ private static ContextCallback s_invokeAsyncCallback;
+
+ [SecuritySafeCritical] // necessary for ExecutionContext.Run
+ void ITaskCompletionAction.Invoke(Task completingTask)
+ {
+ // Get the ExecutionContext. If there is none, just run the callback
+ // directly, passing in the completed task as the IAsyncResult.
+ // If there is one, process it with ExecutionContext.Run.
+ var context = _context;
+ if (context == null)
+ {
+ var callback = _callback;
+ _callback = null;
+ callback(completingTask);
+ }
+ else
+ {
+ _context = null;
+
+ var invokeAsyncCallback = s_invokeAsyncCallback;
+ if (invokeAsyncCallback == null) s_invokeAsyncCallback = invokeAsyncCallback = InvokeAsyncCallback; // benign race condition
+
+ using(context) ExecutionContext.Run(context, invokeAsyncCallback, this, true);
+ }
+ }
+
+ bool ITaskCompletionAction.InvokeMayRunArbitraryCode { get { return true; } }
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task WriteAsync(Byte[] buffer, int offset, int count)
+ {
+ return WriteAsync(buffer, offset, count, CancellationToken.None);
+ }
+
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ // If cancellation was requested, bail early with an already completed task.
+ // Otherwise, return a task that represents the Begin/End methods.
+ return cancellationToken.IsCancellationRequested
+ ? Task.FromCanceled(cancellationToken)
+ : BeginEndWriteAsync(buffer, offset, count);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool HasOverriddenBeginEndWrite();
+
+ private Task BeginEndWriteAsync(Byte[] buffer, Int32 offset, Int32 count)
+ {
+ if (!HasOverriddenBeginEndWrite())
+ {
+ // If the Stream does not override Begin/EndWrite, then we can take an optimized path
+ // that skips an extra layer of tasks / IAsyncResults.
+ return (Task)BeginWriteInternal(buffer, offset, count, null, null, serializeAsynchronously: true, apm: false);
+ }
+
+ // Otherwise, we need to wrap calls to Begin/EndWrite to ensure we use the derived type's functionality.
+ return TaskFactory<VoidTaskResult>.FromAsyncTrim(
+ this, new ReadWriteParameters { Buffer=buffer, Offset=offset, Count=count },
+ (stream, args, callback, state) => stream.BeginWrite(args.Buffer, args.Offset, args.Count, callback, state), // cached by compiler
+ (stream, asyncResult) => // cached by compiler
+ {
+ stream.EndWrite(asyncResult);
+ return default(VoidTaskResult);
+ });
+ }
+
+ public abstract long Seek(long offset, SeekOrigin origin);
+
+ public abstract void SetLength(long value);
+
+ public abstract int Read([In, Out] byte[] buffer, int offset, int count);
+
+ // Reads one byte from the stream by calling Read(byte[], int, int).
+ // Will return an unsigned byte cast to an int or -1 on end of stream.
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are reading one byte at a time.
+ public virtual int ReadByte()
+ {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ Contract.Ensures(Contract.Result<int>() < 256);
+
+ byte[] oneByteArray = new byte[1];
+ int r = Read(oneByteArray, 0, 1);
+ if (r==0)
+ return -1;
+ return oneByteArray[0];
+ }
+
+ public abstract void Write(byte[] buffer, int offset, int count);
+
+ // Writes one byte from the stream by calling Write(byte[], int, int).
+ // This implementation does not perform well because it allocates a new
+ // byte[] each time you call it, and should be overridden by any
+ // subclass that maintains an internal buffer. Then, it can help perf
+ // significantly for people who are writing one byte at a time.
+ public virtual void WriteByte(byte value)
+ {
+ byte[] oneByteArray = new byte[1];
+ oneByteArray[0] = value;
+ Write(oneByteArray, 0, 1);
+ }
+
+ [HostProtection(Synchronization=true)]
+ public static Stream Synchronized(Stream stream)
+ {
+ if (stream==null)
+ throw new ArgumentNullException("stream");
+ Contract.Ensures(Contract.Result<Stream>() != null);
+ Contract.EndContractBlock();
+ if (stream is SyncStream)
+ return stream;
+
+ return new SyncStream(stream);
+ }
+
+ [Obsolete("Do not call or override this method.")]
+ protected virtual void ObjectInvariant()
+ {
+ }
+
+ internal IAsyncResult BlockingBeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+
+ // To avoid a race with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try {
+ int numRead = Read(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(numRead, state);
+ }
+ catch (IOException ex) {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: false);
+ }
+
+ if (callback != null) {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static int BlockingEndRead(IAsyncResult asyncResult)
+ {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+
+ return SynchronousAsyncResult.EndRead(asyncResult);
+ }
+
+ internal IAsyncResult BlockingBeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ Contract.Ensures(Contract.Result<IAsyncResult>() != null);
+
+ // To avoid a race condition with a stream's position pointer & generating conditions
+ // with internal buffer indexes in our own streams that
+ // don't natively support async IO operations when there are multiple
+ // async requests outstanding, we will block the application's main
+ // thread and do the IO synchronously.
+ // This can't perform well - use a different approach.
+ SynchronousAsyncResult asyncResult;
+ try {
+ Write(buffer, offset, count);
+ asyncResult = new SynchronousAsyncResult(state);
+ }
+ catch (IOException ex) {
+ asyncResult = new SynchronousAsyncResult(ex, state, isWrite: true);
+ }
+
+ if (callback != null) {
+ callback(asyncResult);
+ }
+
+ return asyncResult;
+ }
+
+ internal static void BlockingEndWrite(IAsyncResult asyncResult)
+ {
+ SynchronousAsyncResult.EndWrite(asyncResult);
+ }
+
+ internal void ValidateCopyToArguments(Stream destination, int bufferSize)
+ {
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ if (!CanRead && !CanWrite)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+ if (!destination.CanRead && !destination.CanWrite)
+ throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+ if (!CanRead)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
+ if (!destination.CanWrite)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
+ Contract.EndContractBlock();
+ }
+
+ [Serializable]
+ private sealed class NullStream : Stream
+ {
+ internal NullStream() {}
+
+ public override bool CanRead {
+ [Pure]
+ get { return true; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return true; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return true; }
+ }
+
+ public override long Length {
+ get { return 0; }
+ }
+
+ public override long Position {
+ get { return 0; }
+ set {}
+ }
+
+ public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
+ {
+ // Validate arguments here for compat, since previously this method
+ // was inherited from Stream (which did check its arguments).
+ ValidateCopyToArguments(destination, bufferSize);
+
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Do nothing - we don't want NullStream singleton (static) to be closable
+ }
+
+ public override void Flush()
+ {
+ }
+
+ [ComVisible(false)]
+ public override Task FlushAsync(CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ if (!CanRead) __Error.ReadNotSupported();
+
+ return BlockingBeginRead(buffer, offset, count, callback, state);
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ return BlockingEndRead(asyncResult);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ return BlockingBeginWrite(buffer, offset, count, callback, state);
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ BlockingEndWrite(asyncResult);
+ }
+
+ public override int Read([In, Out] byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+
+ [ComVisible(false)]
+ public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ var nullReadTask = s_nullReadTask;
+ if (nullReadTask == null)
+ s_nullReadTask = nullReadTask = new Task<int>(false, 0, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, CancellationToken.None); // benign race condition
+ return nullReadTask;
+ }
+ private static Task<int> s_nullReadTask;
+
+ public override int ReadByte()
+ {
+ return -1;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ }
+
+ [ComVisible(false)]
+ public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
+ public override void WriteByte(byte value)
+ {
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ return 0;
+ }
+
+ public override void SetLength(long length)
+ {
+ }
+ }
+
+
+ /// <summary>Used as the IAsyncResult object when using asynchronous IO methods on the base Stream class.</summary>
+ internal sealed class SynchronousAsyncResult : IAsyncResult {
+
+ private readonly Object _stateObject;
+ private readonly bool _isWrite;
+ private ManualResetEvent _waitHandle;
+ private ExceptionDispatchInfo _exceptionInfo;
+
+ private bool _endXxxCalled;
+ private Int32 _bytesRead;
+
+ internal SynchronousAsyncResult(Int32 bytesRead, Object asyncStateObject) {
+ _bytesRead = bytesRead;
+ _stateObject = asyncStateObject;
+ //_isWrite = false;
+ }
+
+ internal SynchronousAsyncResult(Object asyncStateObject) {
+ _stateObject = asyncStateObject;
+ _isWrite = true;
+ }
+
+ internal SynchronousAsyncResult(Exception ex, Object asyncStateObject, bool isWrite) {
+ _exceptionInfo = ExceptionDispatchInfo.Capture(ex);
+ _stateObject = asyncStateObject;
+ _isWrite = isWrite;
+ }
+
+ public bool IsCompleted {
+ // We never hand out objects of this type to the user before the synchronous IO completed:
+ get { return true; }
+ }
+
+ public WaitHandle AsyncWaitHandle {
+ get {
+ return LazyInitializer.EnsureInitialized(ref _waitHandle, () => new ManualResetEvent(true));
+ }
+ }
+
+ public Object AsyncState {
+ get { return _stateObject; }
+ }
+
+ public bool CompletedSynchronously {
+ get { return true; }
+ }
+
+ internal void ThrowIfError() {
+ if (_exceptionInfo != null)
+ _exceptionInfo.Throw();
+ }
+
+ internal static Int32 EndRead(IAsyncResult asyncResult) {
+
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || ar._isWrite)
+ __Error.WrongAsyncResult();
+
+ if (ar._endXxxCalled)
+ __Error.EndReadCalledTwice();
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ return ar._bytesRead;
+ }
+
+ internal static void EndWrite(IAsyncResult asyncResult) {
+
+ SynchronousAsyncResult ar = asyncResult as SynchronousAsyncResult;
+ if (ar == null || !ar._isWrite)
+ __Error.WrongAsyncResult();
+
+ if (ar._endXxxCalled)
+ __Error.EndWriteCalledTwice();
+
+ ar._endXxxCalled = true;
+
+ ar.ThrowIfError();
+ }
+ } // class SynchronousAsyncResult
+
+
+ // SyncStream is a wrapper around a stream that takes
+ // a lock for every operation making it thread safe.
+ [Serializable]
+ internal sealed class SyncStream : Stream, IDisposable
+ {
+ private Stream _stream;
+
+ internal SyncStream(Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ Contract.EndContractBlock();
+ _stream = stream;
+ }
+
+ public override bool CanRead {
+ [Pure]
+ get { return _stream.CanRead; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _stream.CanWrite; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _stream.CanSeek; }
+ }
+
+ [ComVisible(false)]
+ public override bool CanTimeout {
+ [Pure]
+ get {
+ return _stream.CanTimeout;
+ }
+ }
+
+ public override long Length {
+ get {
+ lock(_stream) {
+ return _stream.Length;
+ }
+ }
+ }
+
+ public override long Position {
+ get {
+ lock(_stream) {
+ return _stream.Position;
+ }
+ }
+ set {
+ lock(_stream) {
+ _stream.Position = value;
+ }
+ }
+ }
+
+ [ComVisible(false)]
+ public override int ReadTimeout {
+ get {
+ return _stream.ReadTimeout;
+ }
+ set {
+ _stream.ReadTimeout = value;
+ }
+ }
+
+ [ComVisible(false)]
+ public override int WriteTimeout {
+ get {
+ return _stream.WriteTimeout;
+ }
+ set {
+ _stream.WriteTimeout = value;
+ }
+ }
+
+ // In the off chance that some wrapped stream has different
+ // semantics for Close vs. Dispose, let's preserve that.
+ public override void Close()
+ {
+ lock(_stream) {
+ try {
+ _stream.Close();
+ }
+ finally {
+ base.Dispose(true);
+ }
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ lock(_stream) {
+ try {
+ // Explicitly pick up a potentially methodimpl'ed Dispose
+ if (disposing)
+ ((IDisposable)_stream).Dispose();
+ }
+ finally {
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ public override void Flush()
+ {
+ lock(_stream)
+ _stream.Flush();
+ }
+
+ public override int Read([In, Out]byte[] bytes, int offset, int count)
+ {
+ lock(_stream)
+ return _stream.Read(bytes, offset, count);
+ }
+
+ public override int ReadByte()
+ {
+ lock(_stream)
+ return _stream.ReadByte();
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ bool overridesBeginRead = _stream.HasOverriddenBeginEndRead();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginRead implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginRead ?
+ _stream.BeginRead(buffer, offset, count, callback, state) :
+ _stream.BeginReadInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+ }
+
+ public override int EndRead(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.EndContractBlock();
+
+ lock(_stream)
+ return _stream.EndRead(asyncResult);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ lock(_stream)
+ return _stream.Seek(offset, origin);
+ }
+
+ public override void SetLength(long length)
+ {
+ lock(_stream)
+ _stream.SetLength(length);
+ }
+
+ public override void Write(byte[] bytes, int offset, int count)
+ {
+ lock(_stream)
+ _stream.Write(bytes, offset, count);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ lock(_stream)
+ _stream.WriteByte(b);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state)
+ {
+ bool overridesBeginWrite = _stream.HasOverriddenBeginEndWrite();
+
+ lock (_stream)
+ {
+ // If the Stream does have its own BeginWrite implementation, then we must use that override.
+ // If it doesn't, then we'll use the base implementation, but we'll make sure that the logic
+ // which ensures only one asynchronous operation does so with an asynchronous wait rather
+ // than a synchronous wait. A synchronous wait will result in a deadlock condition, because
+ // the EndXx method for the outstanding async operation won't be able to acquire the lock on
+ // _stream due to this call blocked while holding the lock.
+ return overridesBeginWrite ?
+ _stream.BeginWrite(buffer, offset, count, callback, state) :
+ _stream.BeginWriteInternal(buffer, offset, count, callback, state, serializeAsynchronously: true, apm: true);
+ }
+ }
+
+ public override void EndWrite(IAsyncResult asyncResult)
+ {
+ if (asyncResult == null)
+ throw new ArgumentNullException("asyncResult");
+ Contract.EndContractBlock();
+
+ lock(_stream)
+ _stream.EndWrite(asyncResult);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/StreamReader.cs b/src/mscorlib/src/System/IO/StreamReader.cs
new file mode 100644
index 0000000000..549733bb47
--- /dev/null
+++ b/src/mscorlib/src/System/IO/StreamReader.cs
@@ -0,0 +1,1293 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: For reading text from streams in a particular
+** encoding.
+**
+**
+===========================================================*/
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Security.Permissions;
+using System.Threading.Tasks;
+
+namespace System.IO
+{
+ // This class implements a TextReader for reading characters to a Stream.
+ // This is designed for character input in a particular Encoding,
+ // whereas the Stream class is designed for byte input and output.
+ //
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class StreamReader : TextReader
+ {
+ // StreamReader.Null is threadsafe.
+ public new static readonly StreamReader Null = new NullStreamReader();
+
+ // Encoding.GetPreamble() always allocates and returns a new byte[] array for
+ // encodings that have a preamble.
+ // We can avoid repeated allocations for the default and commonly used Encoding.UTF8
+ // encoding by using our own private cached instance of the UTF8 preamble.
+ // This is lazily allocated the first time it is used.
+ private static byte[] s_utf8Preamble;
+
+ // Using a 1K byte buffer and a 4K FileStream buffer works out pretty well
+ // perf-wise. On even a 40 MB text file, any perf loss by using a 4K
+ // buffer is negated by the win of allocating a smaller byte[], which
+ // saves construction time. This does break adaptive buffering,
+ // but this is slightly faster.
+ internal static int DefaultBufferSize
+ {
+ get
+ {
+ return 1024;
+ }
+ }
+
+ private const int DefaultFileStreamBufferSize = 4096;
+ private const int MinBufferSize = 128;
+ private const int MaxSharedBuilderCapacity = 360; // also the max capacity used in StringBuilderCache
+
+ private Stream stream;
+ private Encoding encoding;
+ private Decoder decoder;
+ private byte[] byteBuffer;
+ private char[] charBuffer;
+ private byte[] _preamble; // Encoding's preamble, which identifies this encoding.
+ private int charPos;
+ private int charLen;
+ // Record the number of valid bytes in the byteBuffer, for a few checks.
+ private int byteLen;
+ // This is used only for preamble detection
+ private int bytePos;
+
+ [NonSerialized]
+ private StringBuilder _builder;
+
+ // This is the maximum number of chars we can get from one call to
+ // ReadBuffer. Used so ReadBuffer can tell when to copy data into
+ // a user's char[] directly, instead of our internal char[].
+ private int _maxCharsPerBuffer;
+
+ // We will support looking for byte order marks in the stream and trying
+ // to decide what the encoding might be from the byte order marks, IF they
+ // exist. But that's all we'll do.
+ private bool _detectEncoding;
+
+ // Whether we must still check for the encoding's given preamble at the
+ // beginning of this file.
+ private bool _checkPreamble;
+
+ // Whether the stream is most likely not going to give us back as much
+ // data as we want the next time we call it. We must do the computation
+ // before we do any byte order mark handling and save the result. Note
+ // that we need this to allow users to handle streams used for an
+ // interactive protocol, where they block waiting for the remote end
+ // to send a response, like logging in on a Unix machine.
+ private bool _isBlocked;
+
+ // The intent of this field is to leave open the underlying stream when
+ // disposing of this StreamReader. A name like _leaveOpen is better,
+ // but this type is serializable, and this field's name was _closable.
+ private bool _closable; // Whether to close the underlying stream.
+
+ // We don't guarantee thread safety on StreamReader, but we should at
+ // least prevent users from trying to read anything while an Async
+ // read from the same thread is in progress.
+ [NonSerialized]
+ private volatile Task _asyncReadTask;
+
+ private void CheckAsyncTaskInProgress()
+ {
+ // We are not locking the access to _asyncReadTask because this is not meant to guarantee thread safety.
+ // We are simply trying to deter calling any Read APIs while an async Read from the same thread is in progress.
+
+ Task t = _asyncReadTask;
+
+ if (t != null && !t.IsCompleted)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncIOInProgress"));
+ }
+
+ // StreamReader by default will ignore illegal UTF8 characters. We don't want to
+ // throw here because we want to be able to read ill-formed data without choking.
+ // The high level goal is to be tolerant of encoding errors when we read and very strict
+ // when we write. Hence, default StreamWriter encoding will throw on error.
+
+ internal StreamReader() {
+ }
+
+ public StreamReader(Stream stream)
+ : this(stream, true) {
+ }
+
+ public StreamReader(Stream stream, bool detectEncodingFromByteOrderMarks)
+ : this(stream, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize, false) {
+ }
+
+ public StreamReader(Stream stream, Encoding encoding)
+ : this(stream, encoding, true, DefaultBufferSize, false) {
+ }
+
+ public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks)
+ : this(stream, encoding, detectEncodingFromByteOrderMarks, DefaultBufferSize, false) {
+ }
+
+ // Creates a new StreamReader for the given stream. The
+ // character encoding is set by encoding and the buffer size,
+ // in number of 16-bit characters, is set by bufferSize.
+ //
+ // Note that detectEncodingFromByteOrderMarks is a very
+ // loose attempt at detecting the encoding by looking at the first
+ // 3 bytes of the stream. It will recognize UTF-8, little endian
+ // unicode, and big endian unicode text, but that's it. If neither
+ // of those three match, it will use the Encoding you provided.
+ //
+ public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
+ : this(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false) {
+ }
+
+ public StreamReader(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen)
+ {
+ if (stream == null || encoding == null)
+ throw new ArgumentNullException((stream == null ? "stream" : "encoding"));
+ if (!stream.CanRead)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ Contract.EndContractBlock();
+
+ Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, leaveOpen);
+ }
+
+ public StreamReader(String path)
+ : this(path, true) {
+ }
+
+ public StreamReader(String path, bool detectEncodingFromByteOrderMarks)
+ : this(path, Encoding.UTF8, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
+ }
+
+ public StreamReader(String path, Encoding encoding)
+ : this(path, encoding, true, DefaultBufferSize) {
+ }
+
+ public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks)
+ : this(path, encoding, detectEncodingFromByteOrderMarks, DefaultBufferSize) {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
+ : this(path, encoding, detectEncodingFromByteOrderMarks, bufferSize, true) {
+ }
+
+ [System.Security.SecurityCritical]
+ internal StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool checkHost)
+ {
+ // Don't open a Stream before checking for invalid arguments,
+ // or we'll create a FileStream on disk and we won't close it until
+ // the finalizer runs, causing problems for applications.
+ if (path==null || encoding==null)
+ throw new ArgumentNullException((path==null ? "path" : "encoding"));
+ if (path.Length==0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ Contract.EndContractBlock();
+
+ Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
+ Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false);
+ }
+
+ private void Init(Stream stream, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize, bool leaveOpen) {
+ this.stream = stream;
+ this.encoding = encoding;
+ decoder = encoding.GetDecoder();
+ if (bufferSize < MinBufferSize) bufferSize = MinBufferSize;
+ byteBuffer = new byte[bufferSize];
+ _maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize);
+ charBuffer = new char[_maxCharsPerBuffer];
+ byteLen = 0;
+ bytePos = 0;
+ _detectEncoding = detectEncodingFromByteOrderMarks;
+
+ // Encoding.GetPreamble() always allocates and returns a new byte[] array for
+ // encodings that have a preamble.
+ // We can avoid repeated allocations for the default and commonly used Encoding.UTF8
+ // encoding by using our own private cached instance of the UTF8 preamble.
+ // We specifically look for Encoding.UTF8 because we know it has a preamble,
+ // whereas other instances of UTF8Encoding may not have a preamble enabled, and
+ // there's no public way to tell if the preamble is enabled for an instance other
+ // than calling GetPreamble(), which we're trying to avoid.
+ // This means that other instances of UTF8Encoding are excluded from this optimization.
+ _preamble = object.ReferenceEquals(encoding, Encoding.UTF8) ?
+ (s_utf8Preamble ?? (s_utf8Preamble = encoding.GetPreamble())) :
+ encoding.GetPreamble();
+
+ _checkPreamble = (_preamble.Length > 0);
+ _isBlocked = false;
+ _closable = !leaveOpen;
+ }
+
+ // Init used by NullStreamReader, to delay load encoding
+ internal void Init(Stream stream)
+ {
+ this.stream = stream;
+ _closable = true;
+ }
+
+ public override void Close()
+ {
+ Dispose(true);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Dispose of our resources if this StreamReader is closable.
+ // Note that Console.In should be left open.
+ try {
+ // Note that Stream.Close() can potentially throw here. So we need to
+ // ensure cleaning up internal resources, inside the finally block.
+ if (!LeaveOpen && disposing && (stream != null))
+ stream.Close();
+ }
+ finally {
+ if (!LeaveOpen && (stream != null)) {
+ stream = null;
+ encoding = null;
+ decoder = null;
+ byteBuffer = null;
+ charBuffer = null;
+ charPos = 0;
+ charLen = 0;
+ _builder = null;
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ public virtual Encoding CurrentEncoding {
+ get { return encoding; }
+ }
+
+ public virtual Stream BaseStream {
+ get { return stream; }
+ }
+
+ internal bool LeaveOpen {
+ get { return !_closable; }
+ }
+
+ // DiscardBufferedData tells StreamReader to throw away its internal
+ // buffer contents. This is useful if the user needs to seek on the
+ // underlying stream to a known location then wants the StreamReader
+ // to start reading from this new point. This method should be called
+ // very sparingly, if ever, since it can lead to very poor performance.
+ // However, it may be the only way of handling some scenarios where
+ // users need to re-read the contents of a StreamReader a second time.
+ public void DiscardBufferedData()
+ {
+ CheckAsyncTaskInProgress();
+
+ byteLen = 0;
+ charLen = 0;
+ charPos = 0;
+ // in general we'd like to have an invariant that encoding isn't null. However,
+ // for startup improvements for NullStreamReader, we want to delay load encoding.
+ if (encoding != null) {
+ decoder = encoding.GetDecoder();
+ }
+ _isBlocked = false;
+ }
+
+ public bool EndOfStream {
+ get {
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ if (charPos < charLen)
+ return false;
+
+ // This may block on pipes!
+ int numRead = ReadBuffer();
+ return numRead == 0;
+ }
+ }
+
+ [Pure]
+ public override int Peek() {
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ if (charPos == charLen)
+ {
+ if (_isBlocked || ReadBuffer() == 0) return -1;
+ }
+ return charBuffer[charPos];
+ }
+
+ public override int Read() {
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ if (charPos == charLen) {
+ if (ReadBuffer() == 0) return -1;
+ }
+ int result = charBuffer[charPos];
+ charPos++;
+ return result;
+ }
+
+ public override int Read([In, Out] char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ int charsRead = 0;
+ // As a perf optimization, if we had exactly one buffer's worth of
+ // data read in, let's try writing directly to the user's buffer.
+ bool readToUserBuffer = false;
+ while (count > 0) {
+ int n = charLen - charPos;
+ if (n == 0) n = ReadBuffer(buffer, index + charsRead, count, out readToUserBuffer);
+ if (n == 0) break; // We're at EOF
+ if (n > count) n = count;
+ if (!readToUserBuffer) {
+ Buffer.InternalBlockCopy(charBuffer, charPos * 2, buffer, (index + charsRead) * 2, n*2);
+ charPos += n;
+ }
+ charsRead += n;
+ count -= n;
+ // This function shouldn't block for an indefinite amount of time,
+ // or reading from a network stream won't work right. If we got
+ // fewer bytes than we requested, then we want to break right here.
+ if (_isBlocked)
+ break;
+ }
+
+ return charsRead;
+ }
+
+ public override String ReadToEnd()
+ {
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ // Call ReadBuffer, then pull data out of charBuffer.
+ StringBuilder sb = AcquireSharedStringBuilder(charLen - charPos);
+ do {
+ sb.Append(charBuffer, charPos, charLen - charPos);
+ charPos = charLen; // Note we consumed these characters
+ ReadBuffer();
+ } while (charLen > 0);
+
+ return GetStringAndReleaseSharedStringBuilder(sb);
+ }
+
+ public override int ReadBlock([In, Out] char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ return base.ReadBlock(buffer, index, count);
+ }
+
+ // Trims n bytes from the front of the buffer.
+ private void CompressBuffer(int n)
+ {
+ Contract.Assert(byteLen >= n, "CompressBuffer was called with a number of bytes greater than the current buffer length. Are two threads using this StreamReader at the same time?");
+ Buffer.InternalBlockCopy(byteBuffer, n, byteBuffer, 0, byteLen - n);
+ byteLen -= n;
+ }
+
+ private void DetectEncoding()
+ {
+ if (byteLen < 2)
+ return;
+ _detectEncoding = false;
+ bool changedEncoding = false;
+ if (byteBuffer[0]==0xFE && byteBuffer[1]==0xFF) {
+ // Big Endian Unicode
+
+ encoding = Encoding.BigEndianUnicode;
+ CompressBuffer(2);
+ changedEncoding = true;
+ }
+
+ else if (byteBuffer[0]==0xFF && byteBuffer[1]==0xFE) {
+ // Little Endian Unicode, or possibly little endian UTF32
+ if (byteLen < 4 || byteBuffer[2] != 0 || byteBuffer[3] != 0) {
+ encoding = Encoding.Unicode;
+ CompressBuffer(2);
+ changedEncoding = true;
+ }
+ else {
+ encoding = Encoding.UTF32;
+ CompressBuffer(4);
+ changedEncoding = true;
+ }
+ }
+
+ else if (byteLen >= 3 && byteBuffer[0]==0xEF && byteBuffer[1]==0xBB && byteBuffer[2]==0xBF) {
+ // UTF-8
+ encoding = Encoding.UTF8;
+ CompressBuffer(3);
+ changedEncoding = true;
+ }
+ else if (byteLen >= 4 && byteBuffer[0] == 0 && byteBuffer[1] == 0 &&
+ byteBuffer[2] == 0xFE && byteBuffer[3] == 0xFF) {
+ // Big Endian UTF32
+ encoding = new UTF32Encoding(true, true);
+ CompressBuffer(4);
+ changedEncoding = true;
+ }
+ else if (byteLen == 2)
+ _detectEncoding = true;
+ // Note: in the future, if we change this algorithm significantly,
+ // we can support checking for the preamble of the given encoding.
+
+ if (changedEncoding) {
+ decoder = encoding.GetDecoder();
+ _maxCharsPerBuffer = encoding.GetMaxCharCount(byteBuffer.Length);
+ charBuffer = new char[_maxCharsPerBuffer];
+ }
+ }
+
+ // Trims the preamble bytes from the byteBuffer. This routine can be called multiple times
+ // and we will buffer the bytes read until the preamble is matched or we determine that
+ // there is no match. If there is no match, every byte read previously will be available
+ // for further consumption. If there is a match, we will compress the buffer for the
+ // leading preamble bytes
+ private bool IsPreamble()
+ {
+ if (!_checkPreamble)
+ return _checkPreamble;
+
+ Contract.Assert(bytePos <= _preamble.Length, "_compressPreamble was called with the current bytePos greater than the preamble buffer length. Are two threads using this StreamReader at the same time?");
+ int len = (byteLen >= (_preamble.Length))? (_preamble.Length - bytePos) : (byteLen - bytePos);
+
+ for(int i=0; i<len; i++, bytePos++) {
+ if (byteBuffer[bytePos] != _preamble[bytePos]) {
+ bytePos = 0;
+ _checkPreamble = false;
+ break;
+ }
+ }
+
+ Contract.Assert(bytePos <= _preamble.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?");
+
+ if (_checkPreamble) {
+ if (bytePos == _preamble.Length) {
+ // We have a match
+ CompressBuffer(_preamble.Length);
+ bytePos = 0;
+ _checkPreamble = false;
+ _detectEncoding = false;
+ }
+ }
+
+ return _checkPreamble;
+ }
+
+ private StringBuilder AcquireSharedStringBuilder(int capacity)
+ {
+ // Do not touch the shared builder if it will be removed on release
+ if (capacity > MaxSharedBuilderCapacity)
+ return new StringBuilder(capacity);
+
+ // note that since StreamReader does not support concurrent reads it is not needed to
+ // set _builder to null to avoid parallel acquisitions.
+ StringBuilder sb = _builder;
+
+ if (sb == null)
+ return _builder = new StringBuilder(capacity);
+
+ // Clear the shared builder. Does not remove the allocated buffers so they are reused.
+ sb.Length = 0;
+
+ // When needed, recreate the buffer backing the StringBuilder so that further Append calls
+ // are less likely to internally allocate new StringBuilders (or chunks).
+ if (sb.Capacity < capacity)
+ sb.Capacity = capacity;
+
+ return sb;
+ }
+
+ private string GetStringAndReleaseSharedStringBuilder(StringBuilder sb)
+ {
+ if (sb == _builder && sb.Capacity > MaxSharedBuilderCapacity)
+ _builder = null;
+
+ return sb.ToString();
+ }
+
+ internal virtual int ReadBuffer() {
+ charLen = 0;
+ charPos = 0;
+
+ if (!_checkPreamble)
+ byteLen = 0;
+ do {
+ if (_checkPreamble) {
+ Contract.Assert(bytePos <= _preamble.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?");
+ int len = stream.Read(byteBuffer, bytePos, byteBuffer.Length - bytePos);
+ Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (len == 0) {
+ // EOF but we might have buffered bytes from previous
+ // attempt to detect preamble that needs to be decoded now
+ if (byteLen > 0)
+ {
+ charLen += decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, charLen);
+ // Need to zero out the byteLen after we consume these bytes so that we don't keep infinitely hitting this code path
+ bytePos = byteLen = 0;
+ }
+
+ return charLen;
+ }
+
+ byteLen += len;
+ }
+ else {
+ Contract.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?");
+ byteLen = stream.Read(byteBuffer, 0, byteBuffer.Length);
+ Contract.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (byteLen == 0) // We're at EOF
+ return charLen;
+ }
+
+ // _isBlocked == whether we read fewer bytes than we asked for.
+ // Note we must check it here because CompressBuffer or
+ // DetectEncoding will change byteLen.
+ _isBlocked = (byteLen < byteBuffer.Length);
+
+ // Check for preamble before detect encoding. This is not to override the
+ // user suppplied Encoding for the one we implicitly detect. The user could
+ // customize the encoding which we will loose, such as ThrowOnError on UTF8
+ if (IsPreamble())
+ continue;
+
+ // If we're supposed to detect the encoding and haven't done so yet,
+ // do it. Note this may need to be called more than once.
+ if (_detectEncoding && byteLen >= 2)
+ DetectEncoding();
+
+ charLen += decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, charLen);
+ } while (charLen == 0);
+ //Console.WriteLine("ReadBuffer called. chars: "+charLen);
+ return charLen;
+ }
+
+
+ // This version has a perf optimization to decode data DIRECTLY into the
+ // user's buffer, bypassing StreamReader's own buffer.
+ // This gives a > 20% perf improvement for our encodings across the board,
+ // but only when asking for at least the number of characters that one
+ // buffer's worth of bytes could produce.
+ // This optimization, if run, will break SwitchEncoding, so we must not do
+ // this on the first call to ReadBuffer.
+ private int ReadBuffer(char[] userBuffer, int userOffset, int desiredChars, out bool readToUserBuffer)
+ {
+ charLen = 0;
+ charPos = 0;
+
+ if (!_checkPreamble)
+ byteLen = 0;
+
+ int charsRead = 0;
+
+ // As a perf optimization, we can decode characters DIRECTLY into a
+ // user's char[]. We absolutely must not write more characters
+ // into the user's buffer than they asked for. Calculating
+ // encoding.GetMaxCharCount(byteLen) each time is potentially very
+ // expensive - instead, cache the number of chars a full buffer's
+ // worth of data may produce. Yes, this makes the perf optimization
+ // less aggressive, in that all reads that asked for fewer than AND
+ // returned fewer than _maxCharsPerBuffer chars won't get the user
+ // buffer optimization. This affects reads where the end of the
+ // Stream comes in the middle somewhere, and when you ask for
+ // fewer chars than your buffer could produce.
+ readToUserBuffer = desiredChars >= _maxCharsPerBuffer;
+
+ do {
+ Contract.Assert(charsRead == 0);
+
+ if (_checkPreamble) {
+ Contract.Assert(bytePos <= _preamble.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?");
+ int len = stream.Read(byteBuffer, bytePos, byteBuffer.Length - bytePos);
+ Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (len == 0) {
+ // EOF but we might have buffered bytes from previous
+ // attempt to detect preamble that needs to be decoded now
+ if (byteLen > 0) {
+ if (readToUserBuffer) {
+ charsRead = decoder.GetChars(byteBuffer, 0, byteLen, userBuffer, userOffset + charsRead);
+ charLen = 0; // StreamReader's buffer is empty.
+ }
+ else {
+ charsRead = decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, charsRead);
+ charLen += charsRead; // Number of chars in StreamReader's buffer.
+ }
+ }
+
+ return charsRead;
+ }
+
+ byteLen += len;
+ }
+ else {
+ Contract.Assert(bytePos == 0, "bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?");
+
+ byteLen = stream.Read(byteBuffer, 0, byteBuffer.Length);
+
+ Contract.Assert(byteLen >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (byteLen == 0) // EOF
+ break;
+ }
+
+ // _isBlocked == whether we read fewer bytes than we asked for.
+ // Note we must check it here because CompressBuffer or
+ // DetectEncoding will change byteLen.
+ _isBlocked = (byteLen < byteBuffer.Length);
+
+ // Check for preamble before detect encoding. This is not to override the
+ // user suppplied Encoding for the one we implicitly detect. The user could
+ // customize the encoding which we will loose, such as ThrowOnError on UTF8
+ // Note: we don't need to recompute readToUserBuffer optimization as IsPreamble
+ // doesn't change the encoding or affect _maxCharsPerBuffer
+ if (IsPreamble())
+ continue;
+
+ // On the first call to ReadBuffer, if we're supposed to detect the encoding, do it.
+ if (_detectEncoding && byteLen >= 2) {
+ DetectEncoding();
+ // DetectEncoding changes some buffer state. Recompute this.
+ readToUserBuffer = desiredChars >= _maxCharsPerBuffer;
+ }
+
+ charPos = 0;
+ if (readToUserBuffer) {
+ charsRead += decoder.GetChars(byteBuffer, 0, byteLen, userBuffer, userOffset + charsRead);
+ charLen = 0; // StreamReader's buffer is empty.
+ }
+ else {
+ charsRead = decoder.GetChars(byteBuffer, 0, byteLen, charBuffer, charsRead);
+ charLen += charsRead; // Number of chars in StreamReader's buffer.
+ }
+ } while (charsRead == 0);
+
+ _isBlocked &= charsRead < desiredChars;
+
+ //Console.WriteLine("ReadBuffer: charsRead: "+charsRead+" readToUserBuffer: "+readToUserBuffer);
+ return charsRead;
+ }
+
+
+ // Reads a line. A line is defined as a sequence of characters followed by
+ // a carriage return ('\r'), a line feed ('\n'), or a carriage return
+ // immediately followed by a line feed. The resulting string does not
+ // contain the terminating carriage return and/or line feed. The returned
+ // value is null if the end of the input stream has been reached.
+ //
+ public override String ReadLine()
+ {
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ if (charPos == charLen)
+ {
+ if (ReadBuffer() == 0) return null;
+ }
+
+ StringBuilder sb = null;
+ do {
+ int i = charPos;
+ do {
+ char ch = charBuffer[i];
+ // Note the following common line feed chars:
+ // \n - UNIX \r\n - DOS \r - Mac
+ if (ch == '\r' || ch == '\n') {
+ String s;
+ if (sb != null) {
+ sb.Append(charBuffer, charPos, i - charPos);
+ s = GetStringAndReleaseSharedStringBuilder(sb);
+ }
+ else {
+ s = new String(charBuffer, charPos, i - charPos);
+ }
+ charPos = i + 1;
+ if (ch == '\r' && (charPos < charLen || ReadBuffer() > 0)) {
+ if (charBuffer[charPos] == '\n') charPos++;
+ }
+ return s;
+ }
+ i++;
+ } while (i < charLen);
+ i = charLen - charPos;
+ if (sb == null) sb = AcquireSharedStringBuilder(i + 80);
+ sb.Append(charBuffer, charPos, i);
+ } while (ReadBuffer() > 0);
+ return GetStringAndReleaseSharedStringBuilder(sb);
+ }
+
+ #region Task based Async APIs
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task<String> ReadLineAsync()
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read) when we are not sure.
+ if (this.GetType() != typeof(StreamReader))
+ return base.ReadLineAsync();
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task<String> task = ReadLineAsyncInternal();
+ _asyncReadTask = task;
+
+ return task;
+ }
+
+ private async Task<String> ReadLineAsyncInternal()
+ {
+ if (CharPos_Prop == CharLen_Prop && (await ReadBufferAsync().ConfigureAwait(false)) == 0)
+ return null;
+
+ StringBuilder sb = null;
+
+ do
+ {
+ char[] tmpCharBuffer = CharBuffer_Prop;
+ int tmpCharLen = CharLen_Prop;
+ int tmpCharPos = CharPos_Prop;
+ int i = tmpCharPos;
+
+ do
+ {
+ char ch = tmpCharBuffer[i];
+
+ // Note the following common line feed chars:
+ // \n - UNIX \r\n - DOS \r - Mac
+ if (ch == '\r' || ch == '\n')
+ {
+ String s;
+
+ if (sb != null)
+ {
+ sb.Append(tmpCharBuffer, tmpCharPos, i - tmpCharPos);
+ s = GetStringAndReleaseSharedStringBuilder(sb);
+ }
+ else
+ {
+ s = new String(tmpCharBuffer, tmpCharPos, i - tmpCharPos);
+ }
+
+ CharPos_Prop = tmpCharPos = i + 1;
+
+ if (ch == '\r' && (tmpCharPos < tmpCharLen || (await ReadBufferAsync().ConfigureAwait(false)) > 0))
+ {
+ tmpCharPos = CharPos_Prop;
+ if (CharBuffer_Prop[tmpCharPos] == '\n')
+ CharPos_Prop = ++tmpCharPos;
+ }
+
+ return s;
+ }
+
+ i++;
+
+ } while (i < tmpCharLen);
+
+ i = tmpCharLen - tmpCharPos;
+ if (sb == null) sb = AcquireSharedStringBuilder(i + 80);
+ sb.Append(tmpCharBuffer, tmpCharPos, i);
+
+ } while (await ReadBufferAsync().ConfigureAwait(false) > 0);
+
+ return GetStringAndReleaseSharedStringBuilder(sb);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task<String> ReadToEndAsync()
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read) when we are not sure.
+ if (this.GetType() != typeof(StreamReader))
+ return base.ReadToEndAsync();
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task<String> task = ReadToEndAsyncInternal();
+ _asyncReadTask = task;
+
+ return task;
+ }
+
+ private async Task<String> ReadToEndAsyncInternal()
+ {
+ // Call ReadBuffer, then pull data out of charBuffer.
+ StringBuilder sb = AcquireSharedStringBuilder(CharLen_Prop - CharPos_Prop);
+ do
+ {
+ int tmpCharPos = CharPos_Prop;
+ sb.Append(CharBuffer_Prop, tmpCharPos, CharLen_Prop - tmpCharPos);
+ CharPos_Prop = CharLen_Prop; // We consumed these characters
+ await ReadBufferAsync().ConfigureAwait(false);
+ } while (CharLen_Prop > 0);
+
+ return GetStringAndReleaseSharedStringBuilder(sb);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task<int> ReadAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read) when we are not sure.
+ if (this.GetType() != typeof(StreamReader))
+ return base.ReadAsync(buffer, index, count);
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task<int> task = ReadAsyncInternal(buffer, index, count);
+ _asyncReadTask = task;
+
+ return task;
+ }
+
+ internal override async Task<int> ReadAsyncInternal(char[] buffer, int index, int count)
+ {
+ if (CharPos_Prop == CharLen_Prop && (await ReadBufferAsync().ConfigureAwait(false)) == 0)
+ return 0;
+
+ int charsRead = 0;
+
+ // As a perf optimization, if we had exactly one buffer's worth of
+ // data read in, let's try writing directly to the user's buffer.
+ bool readToUserBuffer = false;
+
+ Byte[] tmpByteBuffer = ByteBuffer_Prop;
+ Stream tmpStream = Stream_Prop;
+
+ while (count > 0)
+ {
+ // n is the characters available in _charBuffer
+ int n = CharLen_Prop - CharPos_Prop;
+
+ // charBuffer is empty, let's read from the stream
+ if (n == 0)
+ {
+ CharLen_Prop = 0;
+ CharPos_Prop = 0;
+
+ if (!CheckPreamble_Prop)
+ ByteLen_Prop = 0;
+
+ readToUserBuffer = count >= MaxCharsPerBuffer_Prop;
+
+ // We loop here so that we read in enough bytes to yield at least 1 char.
+ // We break out of the loop if the stream is blocked (EOF is reached).
+ do
+ {
+ Contract.Assert(n == 0);
+
+ if (CheckPreamble_Prop)
+ {
+ Contract.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?");
+ int tmpBytePos = BytePos_Prop;
+ int len = await tmpStream.ReadAsync(tmpByteBuffer, tmpBytePos, tmpByteBuffer.Length - tmpBytePos).ConfigureAwait(false);
+ Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (len == 0)
+ {
+ // EOF but we might have buffered bytes from previous
+ // attempts to detect preamble that needs to be decoded now
+ if (ByteLen_Prop > 0)
+ {
+ if (readToUserBuffer)
+ {
+ n = Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, buffer, index + charsRead);
+ CharLen_Prop = 0; // StreamReader's buffer is empty.
+ }
+ else
+ {
+ n = Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, CharBuffer_Prop, 0);
+ CharLen_Prop += n; // Number of chars in StreamReader's buffer.
+ }
+ }
+
+ // How can part of the preamble yield any chars?
+ Contract.Assert(n == 0);
+
+ IsBlocked_Prop = true;
+ break;
+ }
+ else
+ {
+ ByteLen_Prop += len;
+ }
+ }
+ else
+ {
+ Contract.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?");
+
+ ByteLen_Prop = await tmpStream.ReadAsync(tmpByteBuffer, 0, tmpByteBuffer.Length).ConfigureAwait(false);
+
+ Contract.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (ByteLen_Prop == 0) // EOF
+ {
+ IsBlocked_Prop = true;
+ break;
+ }
+ }
+
+ // _isBlocked == whether we read fewer bytes than we asked for.
+ // Note we must check it here because CompressBuffer or
+ // DetectEncoding will change _byteLen.
+ IsBlocked_Prop = (ByteLen_Prop < tmpByteBuffer.Length);
+
+ // Check for preamble before detect encoding. This is not to override the
+ // user suppplied Encoding for the one we implicitly detect. The user could
+ // customize the encoding which we will loose, such as ThrowOnError on UTF8
+ // Note: we don't need to recompute readToUserBuffer optimization as IsPreamble
+ // doesn't change the encoding or affect _maxCharsPerBuffer
+ if (IsPreamble())
+ continue;
+
+ // On the first call to ReadBuffer, if we're supposed to detect the encoding, do it.
+ if (DetectEncoding_Prop && ByteLen_Prop >= 2)
+ {
+ DetectEncoding();
+ // DetectEncoding changes some buffer state. Recompute this.
+ readToUserBuffer = count >= MaxCharsPerBuffer_Prop;
+ }
+
+ Contract.Assert(n == 0);
+
+ CharPos_Prop = 0;
+ if (readToUserBuffer)
+ {
+ n += Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, buffer, index + charsRead);
+
+ // Why did the bytes yield no chars?
+ Contract.Assert(n > 0);
+
+ CharLen_Prop = 0; // StreamReader's buffer is empty.
+ }
+ else
+ {
+ n = Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, CharBuffer_Prop, 0);
+
+ // Why did the bytes yield no chars?
+ Contract.Assert(n > 0);
+
+ CharLen_Prop += n; // Number of chars in StreamReader's buffer.
+ }
+
+ } while (n == 0);
+
+ if (n == 0) break; // We're at EOF
+ } // if (n == 0)
+
+ // Got more chars in charBuffer than the user requested
+ if (n > count)
+ n = count;
+
+ if (!readToUserBuffer)
+ {
+ Buffer.InternalBlockCopy(CharBuffer_Prop, CharPos_Prop * 2, buffer, (index + charsRead) * 2, n * 2);
+ CharPos_Prop += n;
+ }
+
+ charsRead += n;
+ count -= n;
+
+ // This function shouldn't block for an indefinite amount of time,
+ // or reading from a network stream won't work right. If we got
+ // fewer bytes than we requested, then we want to break right here.
+ if (IsBlocked_Prop)
+ break;
+ } // while (count > 0)
+
+ return charsRead;
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task<int> ReadBlockAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Read() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Read) when we are not sure.
+ if (this.GetType() != typeof(StreamReader))
+ return base.ReadBlockAsync(buffer, index, count);
+
+ if (stream == null)
+ __Error.ReaderClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task<int> task = base.ReadBlockAsync(buffer, index, count);
+ _asyncReadTask = task;
+
+ return task;
+ }
+
+ #region Private properties for async method performance
+ // Access to instance fields of MarshalByRefObject-derived types requires special JIT helpers that check
+ // if the instance operated on is remote. This is optimised for fields on this but if a method is Async
+ // and is thus lifted to a state machine type, access will be slow.
+ // As a workaround, we either cache instance fields in locals or use properties to access such fields.
+
+ private Int32 CharLen_Prop {
+ get { return charLen; }
+ set { charLen = value; }
+ }
+
+ private Int32 CharPos_Prop {
+ get { return charPos; }
+ set { charPos = value; }
+ }
+
+ private Int32 ByteLen_Prop {
+ get { return byteLen; }
+ set { byteLen = value; }
+ }
+
+ private Int32 BytePos_Prop {
+ get { return bytePos; }
+ set { bytePos = value; }
+ }
+
+ private Byte[] Preamble_Prop {
+ get { return _preamble; }
+ }
+
+ private bool CheckPreamble_Prop {
+ get { return _checkPreamble; }
+ }
+
+ private Decoder Decoder_Prop {
+ get { return decoder; }
+ }
+
+ private bool DetectEncoding_Prop {
+ get { return _detectEncoding; }
+ }
+
+ private Char[] CharBuffer_Prop {
+ get { return charBuffer; }
+ }
+
+ private Byte[] ByteBuffer_Prop {
+ get { return byteBuffer; }
+ }
+
+ private bool IsBlocked_Prop {
+ get { return _isBlocked; }
+ set { _isBlocked = value; }
+ }
+
+ private Stream Stream_Prop {
+ get { return stream; }
+ }
+
+ private Int32 MaxCharsPerBuffer_Prop {
+ get { return _maxCharsPerBuffer; }
+ }
+ #endregion Private properties for async method performance
+ private async Task<int> ReadBufferAsync()
+ {
+ CharLen_Prop = 0;
+ CharPos_Prop = 0;
+ Byte[] tmpByteBuffer = ByteBuffer_Prop;
+ Stream tmpStream = Stream_Prop;
+
+ if (!CheckPreamble_Prop)
+ ByteLen_Prop = 0;
+ do {
+ if (CheckPreamble_Prop) {
+ Contract.Assert(BytePos_Prop <= Preamble_Prop.Length, "possible bug in _compressPreamble. Are two threads using this StreamReader at the same time?");
+ int tmpBytePos = BytePos_Prop;
+ int len = await tmpStream.ReadAsync(tmpByteBuffer, tmpBytePos, tmpByteBuffer.Length - tmpBytePos).ConfigureAwait(false);
+ Contract.Assert(len >= 0, "Stream.Read returned a negative number! This is a bug in your stream class.");
+
+ if (len == 0) {
+ // EOF but we might have buffered bytes from previous
+ // attempt to detect preamble that needs to be decoded now
+ if (ByteLen_Prop > 0)
+ {
+ CharLen_Prop += Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, CharBuffer_Prop, CharLen_Prop);
+ // Need to zero out the _byteLen after we consume these bytes so that we don't keep infinitely hitting this code path
+ BytePos_Prop = 0; ByteLen_Prop = 0;
+ }
+
+ return CharLen_Prop;
+ }
+
+ ByteLen_Prop += len;
+ }
+ else {
+ Contract.Assert(BytePos_Prop == 0, "_bytePos can be non zero only when we are trying to _checkPreamble. Are two threads using this StreamReader at the same time?");
+ ByteLen_Prop = await tmpStream.ReadAsync(tmpByteBuffer, 0, tmpByteBuffer.Length).ConfigureAwait(false);
+ Contract.Assert(ByteLen_Prop >= 0, "Stream.Read returned a negative number! Bug in stream class.");
+
+ if (ByteLen_Prop == 0) // We're at EOF
+ return CharLen_Prop;
+ }
+
+ // _isBlocked == whether we read fewer bytes than we asked for.
+ // Note we must check it here because CompressBuffer or
+ // DetectEncoding will change _byteLen.
+ IsBlocked_Prop = (ByteLen_Prop < tmpByteBuffer.Length);
+
+ // Check for preamble before detect encoding. This is not to override the
+ // user suppplied Encoding for the one we implicitly detect. The user could
+ // customize the encoding which we will loose, such as ThrowOnError on UTF8
+ if (IsPreamble())
+ continue;
+
+ // If we're supposed to detect the encoding and haven't done so yet,
+ // do it. Note this may need to be called more than once.
+ if (DetectEncoding_Prop && ByteLen_Prop >= 2)
+ DetectEncoding();
+
+ CharLen_Prop += Decoder_Prop.GetChars(tmpByteBuffer, 0, ByteLen_Prop, CharBuffer_Prop, CharLen_Prop);
+ } while (CharLen_Prop == 0);
+
+ return CharLen_Prop;
+ }
+ #endregion
+
+ // No data, class doesn't need to be serializable.
+ // Note this class is threadsafe.
+ private class NullStreamReader : StreamReader
+ {
+ // Instantiating Encoding causes unnecessary perf hit.
+ internal NullStreamReader() {
+ Init(Stream.Null);
+ }
+
+ public override Stream BaseStream {
+ get { return Stream.Null; }
+ }
+
+ public override Encoding CurrentEncoding {
+ get { return Encoding.Unicode; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Do nothing - this is essentially unclosable.
+ }
+
+ public override int Peek()
+ {
+ return -1;
+ }
+
+ public override int Read()
+ {
+ return -1;
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int Read(char[] buffer, int index, int count) {
+ return 0;
+ }
+
+ public override String ReadLine() {
+ return null;
+ }
+
+ public override String ReadToEnd()
+ {
+ return String.Empty;
+ }
+
+ internal override int ReadBuffer()
+ {
+ return 0;
+ }
+
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/StreamWriter.cs b/src/mscorlib/src/System/IO/StreamWriter.cs
new file mode 100644
index 0000000000..65613bb0a6
--- /dev/null
+++ b/src/mscorlib/src/System/IO/StreamWriter.cs
@@ -0,0 +1,866 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: For writing text to streams in a particular
+** encoding.
+**
+**
+===========================================================*/
+using System;
+using System.Text;
+using System.Threading;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.Security.Permissions;
+using System.Runtime.Serialization;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+
+namespace System.IO
+{
+ // This class implements a TextWriter for writing characters to a Stream.
+ // This is designed for character output in a particular Encoding,
+ // whereas the Stream class is designed for byte input and output.
+ //
+ [Serializable]
+ [ComVisible(true)]
+ public class StreamWriter : TextWriter
+ {
+ // For UTF-8, the values of 1K for the default buffer size and 4K for the
+ // file stream buffer size are reasonable & give very reasonable
+ // performance for in terms of construction time for the StreamWriter and
+ // write perf. Note that for UTF-8, we end up allocating a 4K byte buffer,
+ // which means we take advantage of adaptive buffering code.
+ // The performance using UnicodeEncoding is acceptable.
+ internal const int DefaultBufferSize = 1024; // char[]
+ private const int DefaultFileStreamBufferSize = 4096;
+ private const int MinBufferSize = 128;
+
+ private const Int32 DontCopyOnWriteLineThreshold = 512;
+
+ // Bit bucket - Null has no backing store. Non closable.
+ public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, new UTF8Encoding(false, true), MinBufferSize, true);
+
+ private Stream stream;
+ private Encoding encoding;
+ private Encoder encoder;
+ private byte[] byteBuffer;
+ private char[] charBuffer;
+ private int charPos;
+ private int charLen;
+ private bool autoFlush;
+ private bool haveWrittenPreamble;
+ private bool closable;
+
+#if MDA_SUPPORTED
+ [NonSerialized]
+ // For StreamWriterBufferedDataLost MDA
+ private MdaHelper mdaHelper;
+#endif
+
+ // We don't guarantee thread safety on StreamWriter, but we should at
+ // least prevent users from trying to write anything while an Async
+ // write from the same thread is in progress.
+ [NonSerialized]
+ private volatile Task _asyncWriteTask;
+
+ private void CheckAsyncTaskInProgress()
+ {
+ // We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety.
+ // We are simply trying to deter calling any Write APIs while an async Write from the same thread is in progress.
+
+ Task t = _asyncWriteTask;
+
+ if (t != null && !t.IsCompleted)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncIOInProgress"));
+ }
+
+ // The high level goal is to be tolerant of encoding errors when we read and very strict
+ // when we write. Hence, default StreamWriter encoding will throw on encoding error.
+ // Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character
+ // D800-DBFF without a following low surrogate character DC00-DFFF), it will cause the
+ // internal StreamWriter's state to be irrecoverable as it would have buffered the
+ // illegal chars and any subsequent call to Flush() would hit the encoding error again.
+ // Even Close() will hit the exception as it would try to flush the unwritten data.
+ // Maybe we can add a DiscardBufferedData() method to get out of such situation (like
+ // StreamReader though for different reason). Either way, the buffered data will be lost!
+ private static volatile Encoding _UTF8NoBOM;
+
+ internal static Encoding UTF8NoBOM {
+ [FriendAccessAllowed]
+ get {
+ if (_UTF8NoBOM == null) {
+ // No need for double lock - we just want to avoid extra
+ // allocations in the common case.
+ UTF8Encoding noBOM = new UTF8Encoding(false, true);
+ Thread.MemoryBarrier();
+ _UTF8NoBOM = noBOM;
+ }
+ return _UTF8NoBOM;
+ }
+ }
+
+
+ internal StreamWriter(): base(null) { // Ask for CurrentCulture all the time
+ }
+
+ public StreamWriter(Stream stream)
+ : this(stream, UTF8NoBOM, DefaultBufferSize, false) {
+ }
+
+ public StreamWriter(Stream stream, Encoding encoding)
+ : this(stream, encoding, DefaultBufferSize, false) {
+ }
+
+ // Creates a new StreamWriter for the given stream. The
+ // character encoding is set by encoding and the buffer size,
+ // in number of 16-bit characters, is set by bufferSize.
+ //
+ public StreamWriter(Stream stream, Encoding encoding, int bufferSize)
+ : this(stream, encoding, bufferSize, false) {
+ }
+
+ public StreamWriter(Stream stream, Encoding encoding, int bufferSize, bool leaveOpen)
+ : base(null) // Ask for CurrentCulture all the time
+ {
+ if (stream == null || encoding == null)
+ throw new ArgumentNullException((stream == null ? "stream" : "encoding"));
+ if (!stream.CanWrite)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable"));
+ if (bufferSize <= 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ Contract.EndContractBlock();
+
+ Init(stream, encoding, bufferSize, leaveOpen);
+ }
+
+ public StreamWriter(String path)
+ : this(path, false, UTF8NoBOM, DefaultBufferSize) {
+ }
+
+ public StreamWriter(String path, bool append)
+ : this(path, append, UTF8NoBOM, DefaultBufferSize) {
+ }
+
+ public StreamWriter(String path, bool append, Encoding encoding)
+ : this(path, append, encoding, DefaultBufferSize) {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public StreamWriter(String path, bool append, Encoding encoding, int bufferSize): this(path, append, encoding, bufferSize, true) {
+ }
+
+ [System.Security.SecurityCritical]
+ internal StreamWriter(String path, bool append, Encoding encoding, int bufferSize, bool checkHost)
+ : base(null)
+ { // Ask for CurrentCulture all the time
+ if (path == null)
+ throw new ArgumentNullException("path");
+ if (encoding == null)
+ throw new ArgumentNullException("encoding");
+ if (path.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
+ if (bufferSize <= 0) throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ Contract.EndContractBlock();
+
+ Stream stream = CreateFile(path, append, checkHost);
+ Init(stream, encoding, bufferSize, false);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void Init(Stream streamArg, Encoding encodingArg, int bufferSize, bool shouldLeaveOpen)
+ {
+ this.stream = streamArg;
+ this.encoding = encodingArg;
+ this.encoder = encoding.GetEncoder();
+ if (bufferSize < MinBufferSize) bufferSize = MinBufferSize;
+ charBuffer = new char[bufferSize];
+ byteBuffer = new byte[encoding.GetMaxByteCount(bufferSize)];
+ charLen = bufferSize;
+ // If we're appending to a Stream that already has data, don't write
+ // the preamble.
+ if (stream.CanSeek && stream.Position > 0)
+ haveWrittenPreamble = true;
+ closable = !shouldLeaveOpen;
+#if MDA_SUPPORTED
+ if (Mda.StreamWriterBufferedDataLost.Enabled) {
+ String callstack = null;
+ if (Mda.StreamWriterBufferedDataLost.CaptureAllocatedCallStack)
+ callstack = Environment.GetStackTrace(null, false);
+ mdaHelper = new MdaHelper(this, callstack);
+ }
+#endif
+ }
+
+ [System.Security.SecurityCritical]
+ private static Stream CreateFile(String path, bool append, bool checkHost) {
+ FileMode mode = append? FileMode.Append: FileMode.Create;
+ FileStream f = new FileStream(path, mode, FileAccess.Write, FileShare.Read,
+ DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
+ return f;
+ }
+
+ public override void Close() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected override void Dispose(bool disposing) {
+ try {
+ // We need to flush any buffered data if we are being closed/disposed.
+ // Also, we never close the handles for stdout & friends. So we can safely
+ // write any buffered data to those streams even during finalization, which
+ // is generally the right thing to do.
+ if (stream != null) {
+ // Note: flush on the underlying stream can throw (ex., low disk space)
+#if FEATURE_CORECLR
+ if (disposing)
+#else
+ if (disposing || (LeaveOpen && stream is __ConsoleStream))
+#endif
+ {
+ CheckAsyncTaskInProgress();
+
+ Flush(true, true);
+#if MDA_SUPPORTED
+ // Disable buffered data loss mda
+ if (mdaHelper != null)
+ GC.SuppressFinalize(mdaHelper);
+#endif
+ }
+ }
+ }
+ finally {
+ // Dispose of our resources if this StreamWriter is closable.
+ // Note: Console.Out and other such non closable streamwriters should be left alone
+ if (!LeaveOpen && stream != null) {
+ try {
+ // Attempt to close the stream even if there was an IO error from Flushing.
+ // Note that Stream.Close() can potentially throw here (may or may not be
+ // due to the same Flush error). In this case, we still need to ensure
+ // cleaning up internal resources, hence the finally block.
+ if (disposing)
+ stream.Close();
+ }
+ finally {
+ stream = null;
+ byteBuffer = null;
+ charBuffer = null;
+ encoding = null;
+ encoder = null;
+ charLen = 0;
+ base.Dispose(disposing);
+ }
+ }
+ }
+ }
+
+ public override void Flush()
+ {
+ CheckAsyncTaskInProgress();
+
+ Flush(true, true);
+ }
+
+ private void Flush(bool flushStream, bool flushEncoder)
+ {
+ // flushEncoder should be true at the end of the file and if
+ // the user explicitly calls Flush (though not if AutoFlush is true).
+ // This is required to flush any dangling characters from our UTF-7
+ // and UTF-8 encoders.
+ if (stream == null)
+ __Error.WriterClosed();
+
+ // Perf boost for Flush on non-dirty writers.
+ if (charPos==0 && (!flushStream && !flushEncoder))
+ return;
+
+ if (!haveWrittenPreamble) {
+ haveWrittenPreamble = true;
+ byte[] preamble = encoding.GetPreamble();
+ if (preamble.Length > 0)
+ stream.Write(preamble, 0, preamble.Length);
+ }
+
+ int count = encoder.GetBytes(charBuffer, 0, charPos, byteBuffer, 0, flushEncoder);
+ charPos = 0;
+ if (count > 0)
+ stream.Write(byteBuffer, 0, count);
+ // By definition, calling Flush should flush the stream, but this is
+ // only necessary if we passed in true for flushStream. The Web
+ // Services guys have some perf tests where flushing needlessly hurts.
+ if (flushStream)
+ stream.Flush();
+ }
+
+ public virtual bool AutoFlush {
+ get { return autoFlush; }
+
+ set
+ {
+ CheckAsyncTaskInProgress();
+
+ autoFlush = value;
+ if (value) Flush(true, false);
+ }
+ }
+
+ public virtual Stream BaseStream {
+ get { return stream; }
+ }
+
+ internal bool LeaveOpen {
+ get { return !closable; }
+ }
+
+ internal bool HaveWrittenPreamble {
+ set { haveWrittenPreamble= value; }
+ }
+
+ public override Encoding Encoding {
+ get { return encoding; }
+ }
+
+ public override void Write(char value)
+ {
+ CheckAsyncTaskInProgress();
+
+ if (charPos == charLen) Flush(false, false);
+ charBuffer[charPos] = value;
+ charPos++;
+ if (autoFlush) Flush(true, false);
+ }
+
+ public override void Write(char[] buffer)
+ {
+ // This may be faster than the one with the index & count since it
+ // has to do less argument checking.
+ if (buffer==null)
+ return;
+
+ CheckAsyncTaskInProgress();
+
+ int index = 0;
+ int count = buffer.Length;
+ while (count > 0) {
+ if (charPos == charLen) Flush(false, false);
+ int n = charLen - charPos;
+ if (n > count) n = count;
+ Contract.Assert(n > 0, "StreamWriter::Write(char[]) isn't making progress! This is most likely a race condition in user code.");
+ Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char));
+ charPos += n;
+ index += n;
+ count -= n;
+ }
+ if (autoFlush) Flush(true, false);
+ }
+
+ public override void Write(char[] buffer, int index, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ CheckAsyncTaskInProgress();
+
+ while (count > 0) {
+ if (charPos == charLen) Flush(false, false);
+ int n = charLen - charPos;
+ if (n > count) n = count;
+ Contract.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code.");
+ Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char));
+ charPos += n;
+ index += n;
+ count -= n;
+ }
+ if (autoFlush) Flush(true, false);
+ }
+
+ public override void Write(String value)
+ {
+ if (value != null)
+ {
+
+ CheckAsyncTaskInProgress();
+
+ int count = value.Length;
+ int index = 0;
+ while (count > 0) {
+ if (charPos == charLen) Flush(false, false);
+ int n = charLen - charPos;
+ if (n > count) n = count;
+ Contract.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code.");
+ value.CopyTo(index, charBuffer, charPos, n);
+ charPos += n;
+ index += n;
+ count -= n;
+ }
+ if (autoFlush) Flush(true, false);
+ }
+ }
+
+ #region Task based Async APIs
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char value)
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteAsync(value);
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+ // We pass in private instance fields of this MarshalByRefObject-derived type as local params
+ // to ensure performant access inside the state machine that corresponds this async method.
+ // Fields that are written to must be assigned at the end of the method *and* before instance invocations.
+ private static async Task WriteAsyncInternal(StreamWriter _this, Char value,
+ Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine,
+ bool autoFlush, bool appendNewLine)
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ charBuffer[charPos] = value;
+ charPos++;
+
+ if (appendNewLine)
+ {
+ for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ charBuffer[charPos] = coreNewLine[i];
+ charPos++;
+ }
+ }
+
+ if (autoFlush) {
+ await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ _this.CharPos_Prop = charPos;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(String value)
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteAsync(value);
+
+ if (value != null)
+ {
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+ else
+ {
+ return Task.CompletedTask;
+ }
+ }
+
+ // We pass in private instance fields of this MarshalByRefObject-derived type as local params
+ // to ensure performant access inside the state machine that corresponds this async method.
+ // Fields that are written to must be assigned at the end of the method *and* before instance invocations.
+ private static async Task WriteAsyncInternal(StreamWriter _this, String value,
+ Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine,
+ bool autoFlush, bool appendNewLine)
+ {
+ Contract.Requires(value != null);
+
+ int count = value.Length;
+ int index = 0;
+
+ while (count > 0)
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ int n = charLen - charPos;
+ if (n > count)
+ n = count;
+
+ Contract.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code.");
+
+ value.CopyTo(index, charBuffer, charPos, n);
+
+ charPos += n;
+ index += n;
+ count -= n;
+ }
+
+ if (appendNewLine)
+ {
+ for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ charBuffer[charPos] = coreNewLine[i];
+ charPos++;
+ }
+ }
+
+ if (autoFlush) {
+ await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ _this.CharPos_Prop = charPos;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteAsync(buffer, index, count);
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, buffer, index, count, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+ // We pass in private instance fields of this MarshalByRefObject-derived type as local params
+ // to ensure performant access inside the state machine that corresponds this async method.
+ // Fields that are written to must be assigned at the end of the method *and* before instance invocations.
+ private static async Task WriteAsyncInternal(StreamWriter _this, Char[] buffer, Int32 index, Int32 count,
+ Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine,
+ bool autoFlush, bool appendNewLine)
+ {
+ Contract.Requires(count == 0 || (count > 0 && buffer != null));
+ Contract.Requires(index >= 0);
+ Contract.Requires(count >= 0);
+ Contract.Requires(buffer == null || (buffer != null && buffer.Length - index >= count));
+
+ while (count > 0)
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ int n = charLen - charPos;
+ if (n > count) n = count;
+
+ Contract.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code.");
+
+ Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char));
+
+ charPos += n;
+ index += n;
+ count -= n;
+ }
+
+ if (appendNewLine)
+ {
+ for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy
+ {
+ if (charPos == charLen) {
+ await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ charBuffer[charPos] = coreNewLine[i];
+ charPos++;
+ }
+ }
+
+ if (autoFlush) {
+ await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false);
+ Contract.Assert(_this.charPos == 0);
+ charPos = 0;
+ }
+
+ _this.CharPos_Prop = charPos;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync()
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteLineAsync();
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, null, 0, 0, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char value)
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteLineAsync(value);
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(String value)
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteLineAsync(value);
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Write() which a subclass might have overriden.
+ // To be safe we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Write) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.WriteLineAsync(buffer, index, count);
+
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = WriteAsyncInternal(this, buffer, index, count, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task FlushAsync()
+ {
+ // If we have been inherited into a subclass, the following implementation could be incorrect
+ // since it does not call through to Flush() which a subclass might have overriden. To be safe
+ // we will only use this implementation in cases where we know it is safe to do so,
+ // and delegate to our base class (which will call into Flush) when we are not sure.
+ if (this.GetType() != typeof(StreamWriter))
+ return base.FlushAsync();
+
+ // flushEncoder should be true at the end of the file and if
+ // the user explicitly calls Flush (though not if AutoFlush is true).
+ // This is required to flush any dangling characters from our UTF-7
+ // and UTF-8 encoders.
+ if (stream == null)
+ __Error.WriterClosed();
+
+ CheckAsyncTaskInProgress();
+
+ Task task = FlushAsyncInternal(true, true, charBuffer, charPos);
+ _asyncWriteTask = task;
+
+ return task;
+ }
+
+ private Int32 CharPos_Prop {
+ set { this.charPos = value; }
+ }
+
+ private bool HaveWrittenPreamble_Prop {
+ set { this.haveWrittenPreamble = value; }
+ }
+
+ private Task FlushAsyncInternal(bool flushStream, bool flushEncoder,
+ Char[] sCharBuffer, Int32 sCharPos) {
+
+ // Perf boost for Flush on non-dirty writers.
+ if (sCharPos == 0 && !flushStream && !flushEncoder)
+ return Task.CompletedTask;
+
+ Task flushTask = FlushAsyncInternal(this, flushStream, flushEncoder, sCharBuffer, sCharPos, this.haveWrittenPreamble,
+ this.encoding, this.encoder, this.byteBuffer, this.stream);
+
+ this.charPos = 0;
+ return flushTask;
+ }
+
+
+ // We pass in private instance fields of this MarshalByRefObject-derived type as local params
+ // to ensure performant access inside the state machine that corresponds this async method.
+ private static async Task FlushAsyncInternal(StreamWriter _this, bool flushStream, bool flushEncoder,
+ Char[] charBuffer, Int32 charPos, bool haveWrittenPreamble,
+ Encoding encoding, Encoder encoder, Byte[] byteBuffer, Stream stream)
+ {
+ if (!haveWrittenPreamble)
+ {
+ _this.HaveWrittenPreamble_Prop = true;
+ byte[] preamble = encoding.GetPreamble();
+ if (preamble.Length > 0)
+ await stream.WriteAsync(preamble, 0, preamble.Length).ConfigureAwait(false);
+ }
+
+ int count = encoder.GetBytes(charBuffer, 0, charPos, byteBuffer, 0, flushEncoder);
+ if (count > 0)
+ await stream.WriteAsync(byteBuffer, 0, count).ConfigureAwait(false);
+
+ // By definition, calling Flush should flush the stream, but this is
+ // only necessary if we passed in true for flushStream. The Web
+ // Services guys have some perf tests where flushing needlessly hurts.
+ if (flushStream)
+ await stream.FlushAsync().ConfigureAwait(false);
+ }
+ #endregion
+
+#if MDA_SUPPORTED
+ // StreamWriterBufferedDataLost MDA
+ // Instead of adding a finalizer to StreamWriter for detecting buffered data loss
+ // (ie, when the user forgets to call Close/Flush on the StreamWriter), we will
+ // have a separate object with normal finalization semantics that maintains a
+ // back pointer to this StreamWriter and alerts about any data loss
+ private sealed class MdaHelper
+ {
+ private StreamWriter streamWriter;
+ private String allocatedCallstack; // captures the callstack when this streamwriter was allocated
+
+ internal MdaHelper(StreamWriter sw, String cs)
+ {
+ streamWriter = sw;
+ allocatedCallstack = cs;
+ }
+
+ // Finalizer
+ ~MdaHelper()
+ {
+ // Make sure people closed this StreamWriter, exclude StreamWriter::Null.
+ if (streamWriter.charPos != 0 && streamWriter.stream != null && streamWriter.stream != Stream.Null) {
+ String fileName = (streamWriter.stream is FileStream) ? ((FileStream)streamWriter.stream).NameInternal : "<unknown>";
+ String callStack = allocatedCallstack;
+
+ if (callStack == null)
+ callStack = Environment.GetResourceString("IO_StreamWriterBufferedDataLostCaptureAllocatedFromCallstackNotEnabled");
+
+ String message = Environment.GetResourceString("IO_StreamWriterBufferedDataLost", streamWriter.stream.GetType().FullName, fileName, callStack);
+
+ Mda.StreamWriterBufferedDataLost.ReportError(message);
+ }
+ }
+ } // class MdaHelper
+#endif // MDA_SUPPORTED
+
+ } // class StreamWriter
+} // namespace
diff --git a/src/mscorlib/src/System/IO/StringReader.cs b/src/mscorlib/src/System/IO/StringReader.cs
new file mode 100644
index 0000000000..e5fa811453
--- /dev/null
+++ b/src/mscorlib/src/System/IO/StringReader.cs
@@ -0,0 +1,187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: For reading text from strings
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+using System.Security.Permissions;
+using System.Threading.Tasks;
+
+namespace System.IO {
+ // This class implements a text reader that reads from a string.
+ //
+ [Serializable]
+ [ComVisible(true)]
+ public class StringReader : TextReader
+ {
+ private String _s;
+ private int _pos;
+ private int _length;
+
+ public StringReader(String s) {
+ if (s == null)
+ throw new ArgumentNullException("s");
+ Contract.EndContractBlock();
+ _s = s;
+ _length = s == null? 0: s.Length;
+ }
+
+ // Closes this StringReader. Following a call to this method, the String
+ // Reader will throw an ObjectDisposedException.
+ public override void Close() {
+ Dispose(true);
+ }
+
+ protected override void Dispose(bool disposing) {
+ _s = null;
+ _pos = 0;
+ _length = 0;
+ base.Dispose(disposing);
+ }
+
+ // Returns the next available character without actually reading it from
+ // the underlying string. The current position of the StringReader is not
+ // changed by this operation. The returned value is -1 if no further
+ // characters are available.
+ //
+ [Pure]
+ public override int Peek() {
+ if (_s == null)
+ __Error.ReaderClosed();
+ if (_pos == _length) return -1;
+ return _s[_pos];
+ }
+
+ // Reads the next character from the underlying string. The returned value
+ // is -1 if no further characters are available.
+ //
+ public override int Read() {
+ if (_s == null)
+ __Error.ReaderClosed();
+ if (_pos == _length) return -1;
+ return _s[_pos++];
+ }
+
+ // Reads a block of characters. This method will read up to count
+ // characters from this StringReader into the buffer character
+ // array starting at position index. Returns the actual number of
+ // characters read, or zero if the end of the string is reached.
+ //
+ public override int Read([In, Out] char[] buffer, int index, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+ if (_s == null)
+ __Error.ReaderClosed();
+
+ int n = _length - _pos;
+ if (n > 0) {
+ if (n > count) n = count;
+ _s.CopyTo(_pos, buffer, index, n);
+ _pos += n;
+ }
+ return n;
+ }
+
+ public override String ReadToEnd()
+ {
+ if (_s == null)
+ __Error.ReaderClosed();
+ String s;
+ if (_pos==0)
+ s = _s;
+ else
+ s = _s.Substring(_pos, _length - _pos);
+ _pos = _length;
+ return s;
+ }
+
+ // Reads a line. A line is defined as a sequence of characters followed by
+ // a carriage return ('\r'), a line feed ('\n'), or a carriage return
+ // immediately followed by a line feed. The resulting string does not
+ // contain the terminating carriage return and/or line feed. The returned
+ // value is null if the end of the underlying string has been reached.
+ //
+ public override String ReadLine() {
+ if (_s == null)
+ __Error.ReaderClosed();
+ int i = _pos;
+ while (i < _length) {
+ char ch = _s[i];
+ if (ch == '\r' || ch == '\n') {
+ String result = _s.Substring(_pos, i - _pos);
+ _pos = i + 1;
+ if (ch == '\r' && _pos < _length && _s[_pos] == '\n') _pos++;
+ return result;
+ }
+ i++;
+ }
+ if (i > _pos) {
+ String result = _s.Substring(_pos, i - _pos);
+ _pos = i;
+ return result;
+ }
+ return null;
+ }
+
+ #region Task based Async APIs
+ [ComVisible(false)]
+ public override Task<String> ReadLineAsync()
+ {
+ return Task.FromResult(ReadLine());
+ }
+
+ [ComVisible(false)]
+ public override Task<String> ReadToEndAsync()
+ {
+ return Task.FromResult(ReadToEnd());
+ }
+
+ [ComVisible(false)]
+ public override Task<int> ReadBlockAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ Contract.EndContractBlock();
+
+ return Task.FromResult(ReadBlock(buffer, index, count));
+ }
+
+ [ComVisible(false)]
+ public override Task<int> ReadAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ return Task.FromResult(Read(buffer, index, count));
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/IO/StringWriter.cs b/src/mscorlib/src/System/IO/StringWriter.cs
new file mode 100644
index 0000000000..282a7910c2
--- /dev/null
+++ b/src/mscorlib/src/System/IO/StringWriter.cs
@@ -0,0 +1,196 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: For writing text to a string
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime;
+using System.Text;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+using System.Threading.Tasks;
+
+namespace System.IO {
+ // This class implements a text writer that writes to a string buffer and allows
+ // the resulting sequence of characters to be presented as a string.
+ //
+ [Serializable]
+ [ComVisible(true)]
+ public class StringWriter : TextWriter
+ {
+ private static volatile UnicodeEncoding m_encoding=null;
+
+ private StringBuilder _sb;
+ private bool _isOpen;
+
+ // Constructs a new StringWriter. A new StringBuilder is automatically
+ // created and associated with the new StringWriter.
+ public StringWriter()
+ : this(new StringBuilder(), CultureInfo.CurrentCulture)
+ {
+ }
+
+ public StringWriter(IFormatProvider formatProvider)
+ : this(new StringBuilder(), formatProvider) {
+ }
+
+ // Constructs a new StringWriter that writes to the given StringBuilder.
+ //
+ public StringWriter(StringBuilder sb) : this(sb, CultureInfo.CurrentCulture) {
+ }
+
+ public StringWriter(StringBuilder sb, IFormatProvider formatProvider) : base(formatProvider) {
+ if (sb==null)
+ throw new ArgumentNullException("sb", Environment.GetResourceString("ArgumentNull_Buffer"));
+ Contract.EndContractBlock();
+ _sb = sb;
+ _isOpen = true;
+ }
+
+ public override void Close()
+ {
+ Dispose(true);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // Do not destroy _sb, so that we can extract this after we are
+ // done writing (similar to MemoryStream's GetBuffer & ToArray methods)
+ _isOpen = false;
+ base.Dispose(disposing);
+ }
+
+
+ public override Encoding Encoding {
+ get {
+ if (m_encoding==null) {
+ m_encoding = new UnicodeEncoding(false, false);
+ }
+ return m_encoding;
+ }
+ }
+
+ // Returns the underlying StringBuilder. This is either the StringBuilder
+ // that was passed to the constructor, or the StringBuilder that was
+ // automatically created.
+ //
+ public virtual StringBuilder GetStringBuilder() {
+ return _sb;
+ }
+
+ // Writes a character to the underlying string buffer.
+ //
+ public override void Write(char value) {
+ if (!_isOpen)
+ __Error.WriterClosed();
+ _sb.Append(value);
+ }
+
+ // Writes a range of a character array to the underlying string buffer.
+ // This method will write count characters of data into this
+ // StringWriter from the buffer character array starting at position
+ // index.
+ //
+ public override void Write(char[] buffer, int index, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (!_isOpen)
+ __Error.WriterClosed();
+
+ _sb.Append(buffer, index, count);
+ }
+
+ // Writes a string to the underlying string buffer. If the given string is
+ // null, nothing is written.
+ //
+ public override void Write(String value) {
+ if (!_isOpen)
+ __Error.WriterClosed();
+ if (value != null) _sb.Append(value);
+ }
+
+
+ #region Task based Async APIs
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char value)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(String value)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char[] buffer, int index, int count)
+ {
+ Write(buffer, index, count);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char value)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(String value)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char[] buffer, int index, int count)
+ {
+ WriteLine(buffer, index, count);
+ return Task.CompletedTask;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task FlushAsync()
+ {
+ return Task.CompletedTask;
+ }
+ #endregion
+
+ // Returns a string containing the characters written to this TextWriter
+ // so far.
+ //
+ public override String ToString() {
+ return _sb.ToString();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/TextReader.cs b/src/mscorlib/src/System/IO/TextReader.cs
new file mode 100644
index 0000000000..ede482784a
--- /dev/null
+++ b/src/mscorlib/src/System/IO/TextReader.cs
@@ -0,0 +1,413 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstract base class for all Text-only Readers.
+** Subclasses will include StreamReader & StringReader.
+**
+**
+===========================================================*/
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Security.Permissions;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO {
+ // This abstract base class represents a reader that can read a sequential
+ // stream of characters. This is not intended for reading bytes -
+ // there are methods on the Stream class to read bytes.
+ // A subclass must minimally implement the Peek() and Read() methods.
+ //
+ // This class is intended for character input, not bytes.
+ // There are methods on the Stream class for reading bytes.
+ [Serializable]
+ [ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class TextReader : MarshalByRefObject, IDisposable {
+#else // FEATURE_REMOTING
+ public abstract class TextReader : IDisposable {
+#endif // FEATURE_REMOTING
+
+ public static readonly TextReader Null = new NullTextReader();
+
+ protected TextReader() {}
+
+ // Closes this TextReader and releases any system resources associated with the
+ // TextReader. Following a call to Close, any operations on the TextReader
+ // may raise exceptions.
+ //
+ // This default method is empty, but descendant classes can override the
+ // method to provide the appropriate functionality.
+ public virtual void Close()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+ // Returns the next available character without actually reading it from
+ // the input stream. The current position of the TextReader is not changed by
+ // this operation. The returned value is -1 if no further characters are
+ // available.
+ //
+ // This default method simply returns -1.
+ //
+ [Pure]
+ public virtual int Peek()
+ {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+
+ return -1;
+ }
+
+ // Reads the next character from the input stream. The returned value is
+ // -1 if no further characters are available.
+ //
+ // This default method simply returns -1.
+ //
+ public virtual int Read()
+ {
+ Contract.Ensures(Contract.Result<int>() >= -1);
+ return -1;
+ }
+
+ // Reads a block of characters. This method will read up to
+ // count characters from this TextReader into the
+ // buffer character array starting at position
+ // index. Returns the actual number of characters read.
+ //
+ public virtual int Read([In, Out] char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= Contract.OldValue(count));
+ Contract.EndContractBlock();
+
+ int n = 0;
+ do {
+ int ch = Read();
+ if (ch == -1) break;
+ buffer[index + n++] = (char)ch;
+ } while (n < count);
+ return n;
+ }
+
+ // Reads all characters from the current position to the end of the
+ // TextReader, and returns them as one string.
+ public virtual String ReadToEnd()
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ char[] chars = new char[4096];
+ int len;
+ StringBuilder sb = new StringBuilder(4096);
+ while((len=Read(chars, 0, chars.Length)) != 0)
+ {
+ sb.Append(chars, 0, len);
+ }
+ return sb.ToString();
+ }
+
+ // Blocking version of read. Returns only when count
+ // characters have been read or the end of the file was reached.
+ //
+ public virtual int ReadBlock([In, Out] char[] buffer, int index, int count)
+ {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ Contract.Ensures(Contract.Result<int>() <= count);
+
+ int i, n = 0;
+ do {
+ n += (i = Read(buffer, index + n, count - n));
+ } while (i > 0 && n < count);
+ return n;
+ }
+
+ // Reads a line. A line is defined as a sequence of characters followed by
+ // a carriage return ('\r'), a line feed ('\n'), or a carriage return
+ // immediately followed by a line feed. The resulting string does not
+ // contain the terminating carriage return and/or line feed. The returned
+ // value is null if the end of the input stream has been reached.
+ //
+ public virtual String ReadLine()
+ {
+ StringBuilder sb = new StringBuilder();
+ while (true) {
+ int ch = Read();
+ if (ch == -1) break;
+ if (ch == '\r' || ch == '\n')
+ {
+ if (ch == '\r' && Peek() == '\n') Read();
+ return sb.ToString();
+ }
+ sb.Append((char)ch);
+ }
+ if (sb.Length > 0) return sb.ToString();
+ return null;
+ }
+
+ #region Task based Async APIs
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public virtual Task<String> ReadLineAsync()
+ {
+ return Task<String>.Factory.StartNew(state =>
+ {
+ return ((TextReader)state).ReadLine();
+ },
+ this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public async virtual Task<String> ReadToEndAsync()
+ {
+ char[] chars = new char[4096];
+ int len;
+ StringBuilder sb = new StringBuilder(4096);
+ while((len = await ReadAsyncInternal(chars, 0, chars.Length).ConfigureAwait(false)) != 0)
+ {
+ sb.Append(chars, 0, len);
+ }
+ return sb.ToString();
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public virtual Task<int> ReadAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ return ReadAsyncInternal(buffer, index, count);
+ }
+
+ internal virtual Task<int> ReadAsyncInternal(char[] buffer, int index, int count)
+ {
+ Contract.Requires(buffer != null);
+ Contract.Requires(index >= 0);
+ Contract.Requires(count >= 0);
+ Contract.Requires(buffer.Length - index >= count);
+
+ var tuple = new Tuple<TextReader, char[], int, int>(this, buffer, index, count);
+ return Task<int>.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextReader, char[], int, int>)state;
+ return t.Item1.Read(t.Item2, t.Item3, t.Item4);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public virtual Task<int> ReadBlockAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ Contract.EndContractBlock();
+
+ return ReadBlockAsyncInternal(buffer, index, count);
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ private async Task<int> ReadBlockAsyncInternal(char[] buffer, int index, int count)
+ {
+ Contract.Requires(buffer != null);
+ Contract.Requires(index >= 0);
+ Contract.Requires(count >= 0);
+ Contract.Requires(buffer.Length - index >= count);
+
+ int i, n = 0;
+ do
+ {
+ i = await ReadAsyncInternal(buffer, index + n, count - n).ConfigureAwait(false);
+ n += i;
+ } while (i > 0 && n < count);
+
+ return n;
+ }
+ #endregion
+
+ [HostProtection(Synchronization=true)]
+ public static TextReader Synchronized(TextReader reader)
+ {
+ if (reader==null)
+ throw new ArgumentNullException("reader");
+ Contract.Ensures(Contract.Result<TextReader>() != null);
+ Contract.EndContractBlock();
+
+ if (reader is SyncTextReader)
+ return reader;
+
+ return new SyncTextReader(reader);
+ }
+
+ [Serializable]
+ private sealed class NullTextReader : TextReader
+ {
+ public NullTextReader(){}
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override int Read(char[] buffer, int index, int count)
+ {
+ return 0;
+ }
+
+ public override String ReadLine()
+ {
+ return null;
+ }
+ }
+
+ [Serializable]
+ internal sealed class SyncTextReader : TextReader
+ {
+ internal TextReader _in;
+
+ internal SyncTextReader(TextReader t)
+ {
+ _in = t;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Close()
+ {
+ // So that any overriden Close() gets run
+ _in.Close();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ protected override void Dispose(bool disposing)
+ {
+ // Explicitly pick up a potentially methodimpl'ed Dispose
+ if (disposing)
+ ((IDisposable)_in).Dispose();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override int Peek()
+ {
+ return _in.Peek();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override int Read()
+ {
+ return _in.Read();
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override int Read([In, Out] char[] buffer, int index, int count)
+ {
+ return _in.Read(buffer, index, count);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override int ReadBlock([In, Out] char[] buffer, int index, int count)
+ {
+ return _in.ReadBlock(buffer, index, count);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override String ReadLine()
+ {
+ return _in.ReadLine();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override String ReadToEnd()
+ {
+ return _in.ReadToEnd();
+ }
+
+ //
+ // On SyncTextReader all APIs should run synchronously, even the async ones.
+ //
+
+ [ComVisible(false)]
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override Task<String> ReadLineAsync()
+ {
+ return Task.FromResult(ReadLine());
+ }
+
+ [ComVisible(false)]
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override Task<String> ReadToEndAsync()
+ {
+ return Task.FromResult(ReadToEnd());
+ }
+
+ [ComVisible(false)]
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override Task<int> ReadBlockAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+
+ Contract.EndContractBlock();
+
+ return Task.FromResult(ReadBlock(buffer, index, count));
+ }
+
+ [ComVisible(false)]
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override Task<int> ReadAsync(char[] buffer, int index, int count)
+ {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ return Task.FromResult(Read(buffer, index, count));
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/TextWriter.cs b/src/mscorlib/src/System/IO/TextWriter.cs
new file mode 100644
index 0000000000..165001e1a6
--- /dev/null
+++ b/src/mscorlib/src/System/IO/TextWriter.cs
@@ -0,0 +1,915 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstract base class for Text-only Writers.
+** Subclasses will include StreamWriter & StringWriter.
+**
+**
+===========================================================*/
+
+using System;
+using System.Text;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Reflection;
+using System.Security.Permissions;
+using System.Globalization;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Threading.Tasks;
+
+namespace System.IO {
+ // This abstract base class represents a writer that can write a sequential
+ // stream of characters. A subclass must minimally implement the
+ // Write(char) method.
+ //
+ // This class is intended for character output, not bytes.
+ // There are methods on the Stream class for writing bytes.
+ [Serializable]
+ [ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class TextWriter : MarshalByRefObject, IDisposable {
+#else // FEATURE_REMOTING
+ public abstract class TextWriter : IDisposable {
+#endif // FEATURE_REMOTING
+ public static readonly TextWriter Null = new NullTextWriter();
+
+ // This should be initialized to Environment.NewLine, but
+ // to avoid loading Environment unnecessarily so I've duplicated
+ // the value here.
+#if !PLATFORM_UNIX
+ private const String InitialNewLine = "\r\n";
+
+ protected char[] CoreNewLine = new char[] { '\r', '\n' };
+#else
+ private const String InitialNewLine = "\n";
+
+ protected char[] CoreNewLine = new char[] {'\n'};
+#endif // !PLATFORM_UNIX
+
+ // Can be null - if so, ask for the Thread's CurrentCulture every time.
+ private IFormatProvider InternalFormatProvider;
+
+ protected TextWriter()
+ {
+ InternalFormatProvider = null; // Ask for CurrentCulture all the time.
+ }
+
+ protected TextWriter(IFormatProvider formatProvider)
+ {
+ InternalFormatProvider = formatProvider;
+ }
+
+ public virtual IFormatProvider FormatProvider {
+ get {
+ if (InternalFormatProvider == null)
+ return Thread.CurrentThread.CurrentCulture;
+ else
+ return InternalFormatProvider;
+ }
+ }
+
+ // Closes this TextWriter and releases any system resources associated with the
+ // TextWriter. Following a call to Close, any operations on the TextWriter
+ // may raise exceptions. This default method is empty, but descendant
+ // classes can override the method to provide the appropriate
+ // functionality.
+ public virtual void Close() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ // Clears all buffers for this TextWriter and causes any buffered data to be
+ // written to the underlying device. This default method is empty, but
+ // descendant classes can override the method to provide the appropriate
+ // functionality.
+ public virtual void Flush() {
+ }
+
+ public abstract Encoding Encoding {
+ get;
+ }
+
+ // Returns the line terminator string used by this TextWriter. The default line
+ // terminator string is a carriage return followed by a line feed ("\r\n").
+ //
+ // Sets the line terminator string for this TextWriter. The line terminator
+ // string is written to the text stream whenever one of the
+ // WriteLine methods are called. In order for text written by
+ // the TextWriter to be readable by a TextReader, only one of the following line
+ // terminator strings should be used: "\r", "\n", or "\r\n".
+ //
+ public virtual String NewLine {
+ get { return new String(CoreNewLine); }
+ set {
+ if (value == null)
+ value = InitialNewLine;
+ CoreNewLine = value.ToCharArray();
+ }
+ }
+
+
+ [HostProtection(Synchronization=true)]
+ public static TextWriter Synchronized(TextWriter writer) {
+ if (writer==null)
+ throw new ArgumentNullException("writer");
+ Contract.Ensures(Contract.Result<TextWriter>() != null);
+ Contract.EndContractBlock();
+
+ if (writer is SyncTextWriter)
+ return writer;
+
+ return new SyncTextWriter(writer);
+ }
+
+ // Writes a character to the text stream. This default method is empty,
+ // but descendant classes can override the method to provide the
+ // appropriate functionality.
+ //
+ public virtual void Write(char value) {
+ }
+
+ // Writes a character array to the text stream. This default method calls
+ // Write(char) for each of the characters in the character array.
+ // If the character array is null, nothing is written.
+ //
+ public virtual void Write(char[] buffer) {
+ if (buffer != null) Write(buffer, 0, buffer.Length);
+ }
+
+ // Writes a range of a character array to the text stream. This method will
+ // write count characters of data into this TextWriter from the
+ // buffer character array starting at position index.
+ //
+ public virtual void Write(char[] buffer, int index, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ for (int i = 0; i < count; i++) Write(buffer[index + i]);
+ }
+
+ // Writes the text representation of a boolean to the text stream. This
+ // method outputs either Boolean.TrueString or Boolean.FalseString.
+ //
+ public virtual void Write(bool value) {
+ Write(value ? Boolean.TrueLiteral : Boolean.FalseLiteral);
+ }
+
+ // Writes the text representation of an integer to the text stream. The
+ // text representation of the given value is produced by calling the
+ // Int32.ToString() method.
+ //
+ public virtual void Write(int value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes the text representation of an integer to the text stream. The
+ // text representation of the given value is produced by calling the
+ // UInt32.ToString() method.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(uint value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes the text representation of a long to the text stream. The
+ // text representation of the given value is produced by calling the
+ // Int64.ToString() method.
+ //
+ public virtual void Write(long value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes the text representation of an unsigned long to the text
+ // stream. The text representation of the given value is produced
+ // by calling the UInt64.ToString() method.
+ //
+ [CLSCompliant(false)]
+ public virtual void Write(ulong value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes the text representation of a float to the text stream. The
+ // text representation of the given value is produced by calling the
+ // Float.toString(float) method.
+ //
+ public virtual void Write(float value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes the text representation of a double to the text stream. The
+ // text representation of the given value is produced by calling the
+ // Double.toString(double) method.
+ //
+ public virtual void Write(double value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ public virtual void Write(Decimal value) {
+ Write(value.ToString(FormatProvider));
+ }
+
+ // Writes a string to the text stream. If the given string is null, nothing
+ // is written to the text stream.
+ //
+ public virtual void Write(String value) {
+ if (value != null) Write(value.ToCharArray());
+ }
+
+ // Writes the text representation of an object to the text stream. If the
+ // given object is null, nothing is written to the text stream.
+ // Otherwise, the object's ToString method is called to produce the
+ // string representation, and the resulting string is then written to the
+ // output stream.
+ //
+ public virtual void Write(Object value) {
+ if (value != null) {
+ IFormattable f = value as IFormattable;
+ if (f != null)
+ Write(f.ToString(null, FormatProvider));
+ else
+ Write(value.ToString());
+ }
+ }
+
+#if false
+ // // Converts the wchar * to a string and writes this to the stream.
+ // //
+ // __attribute NonCLSCompliantAttribute()
+ // public void Write(wchar *value) {
+ // Write(new String(value));
+ // }
+
+ // // Treats the byte* as a LPCSTR, converts it to a string, and writes it to the stream.
+ // //
+ // __attribute NonCLSCompliantAttribute()
+ // public void Write(byte *value) {
+ // Write(new String(value));
+ // }
+#endif
+
+
+ // Writes out a formatted string. Uses the same semantics as
+ // String.Format.
+ //
+ public virtual void Write(String format, Object arg0)
+ {
+ Write(String.Format(FormatProvider, format, arg0));
+ }
+
+ // Writes out a formatted string. Uses the same semantics as
+ // String.Format.
+ //
+ public virtual void Write(String format, Object arg0, Object arg1)
+ {
+ Write(String.Format(FormatProvider, format, arg0, arg1));
+ }
+
+ // Writes out a formatted string. Uses the same semantics as
+ // String.Format.
+ //
+ public virtual void Write(String format, Object arg0, Object arg1, Object arg2)
+ {
+ Write(String.Format(FormatProvider, format, arg0, arg1, arg2));
+ }
+
+ // Writes out a formatted string. Uses the same semantics as
+ // String.Format.
+ //
+ public virtual void Write(String format, params Object[] arg)
+ {
+ Write(String.Format(FormatProvider, format, arg));
+ }
+
+
+ // Writes a line terminator to the text stream. The default line terminator
+ // is a carriage return followed by a line feed ("\r\n"), but this value
+ // can be changed by setting the NewLine property.
+ //
+ public virtual void WriteLine() {
+ Write(CoreNewLine);
+ }
+
+ // Writes a character followed by a line terminator to the text stream.
+ //
+ public virtual void WriteLine(char value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes an array of characters followed by a line terminator to the text
+ // stream.
+ //
+ public virtual void WriteLine(char[] buffer) {
+ Write(buffer);
+ WriteLine();
+ }
+
+ // Writes a range of a character array followed by a line terminator to the
+ // text stream.
+ //
+ public virtual void WriteLine(char[] buffer, int index, int count) {
+ Write(buffer, index, count);
+ WriteLine();
+ }
+
+ // Writes the text representation of a boolean followed by a line
+ // terminator to the text stream.
+ //
+ public virtual void WriteLine(bool value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of an integer followed by a line
+ // terminator to the text stream.
+ //
+ public virtual void WriteLine(int value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of an unsigned integer followed by
+ // a line terminator to the text stream.
+ //
+ [CLSCompliant(false)]
+ public virtual void WriteLine(uint value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of a long followed by a line terminator
+ // to the text stream.
+ //
+ public virtual void WriteLine(long value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of an unsigned long followed by
+ // a line terminator to the text stream.
+ //
+ [CLSCompliant(false)]
+ public virtual void WriteLine(ulong value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of a float followed by a line terminator
+ // to the text stream.
+ //
+ public virtual void WriteLine(float value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes the text representation of a double followed by a line terminator
+ // to the text stream.
+ //
+ public virtual void WriteLine(double value) {
+ Write(value);
+ WriteLine();
+ }
+
+ public virtual void WriteLine(decimal value) {
+ Write(value);
+ WriteLine();
+ }
+
+ // Writes a string followed by a line terminator to the text stream.
+ //
+ public virtual void WriteLine(String value) {
+
+ if (value==null) {
+ WriteLine();
+ }
+ else {
+ // We'd ideally like WriteLine to be atomic, in that one call
+ // to WriteLine equals one call to the OS (ie, so writing to
+ // console while simultaneously calling printf will guarantee we
+ // write out a string and new line chars, without any interference).
+ // Additionally, we need to call ToCharArray on Strings anyways,
+ // so allocating a char[] here isn't any worse than what we were
+ // doing anyways. We do reduce the number of calls to the
+ // backing store this way, potentially.
+ int vLen = value.Length;
+ int nlLen = CoreNewLine.Length;
+ char[] chars = new char[vLen+nlLen];
+ value.CopyTo(0, chars, 0, vLen);
+ // CoreNewLine will almost always be 2 chars, and possibly 1.
+ if (nlLen == 2) {
+ chars[vLen] = CoreNewLine[0];
+ chars[vLen+1] = CoreNewLine[1];
+ }
+ else if (nlLen == 1)
+ chars[vLen] = CoreNewLine[0];
+ else
+ Buffer.InternalBlockCopy(CoreNewLine, 0, chars, vLen * 2, nlLen * 2);
+ Write(chars, 0, vLen + nlLen);
+ }
+ /*
+ Write(value); // We could call Write(String) on StreamWriter...
+ WriteLine();
+ */
+ }
+
+ // Writes the text representation of an object followed by a line
+ // terminator to the text stream.
+ //
+ public virtual void WriteLine(Object value) {
+ if (value==null) {
+ WriteLine();
+ }
+ else {
+ // Call WriteLine(value.ToString), not Write(Object), WriteLine().
+ // This makes calls to WriteLine(Object) atomic.
+ IFormattable f = value as IFormattable;
+ if (f != null)
+ WriteLine(f.ToString(null, FormatProvider));
+ else
+ WriteLine(value.ToString());
+ }
+ }
+
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as String.Format.
+ //
+ public virtual void WriteLine(String format, Object arg0)
+ {
+ WriteLine(String.Format(FormatProvider, format, arg0));
+ }
+
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as String.Format.
+ //
+ public virtual void WriteLine (String format, Object arg0, Object arg1)
+ {
+ WriteLine(String.Format(FormatProvider, format, arg0, arg1));
+ }
+
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as String.Format.
+ //
+ public virtual void WriteLine (String format, Object arg0, Object arg1, Object arg2)
+ {
+ WriteLine(String.Format(FormatProvider, format, arg0, arg1, arg2));
+ }
+
+ // Writes out a formatted string and a new line. Uses the same
+ // semantics as String.Format.
+ //
+ public virtual void WriteLine (String format, params Object[] arg)
+ {
+ WriteLine(String.Format(FormatProvider, format, arg));
+ }
+
+ #region Task based Async APIs
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteAsync(char value)
+ {
+ var tuple = new Tuple<TextWriter, char>(this, value);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, char>)state;
+ t.Item1.Write(t.Item2);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteAsync(String value)
+ {
+ var tuple = new Tuple<TextWriter, string>(this, value);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, string>)state;
+ t.Item1.Write(t.Item2);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task WriteAsync(char[] buffer)
+ {
+ if (buffer == null) return Task.CompletedTask;
+ return WriteAsync(buffer, 0, buffer.Length);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteAsync(char[] buffer, int index, int count)
+ {
+ var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, char[], int, int>)state;
+ t.Item1.Write(t.Item2, t.Item3, t.Item4);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteLineAsync(char value)
+ {
+ var tuple = new Tuple<TextWriter, char>(this, value);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, char>)state;
+ t.Item1.WriteLine(t.Item2);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteLineAsync(String value)
+ {
+ var tuple = new Tuple<TextWriter, string>(this, value);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, string>)state;
+ t.Item1.WriteLine(t.Item2);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public Task WriteLineAsync(char[] buffer)
+ {
+ if (buffer == null) return Task.CompletedTask;
+ return WriteLineAsync(buffer, 0, buffer.Length);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteLineAsync(char[] buffer, int index, int count)
+ {
+ var tuple = new Tuple<TextWriter, char[], int, int>(this, buffer, index, count);
+ return Task.Factory.StartNew(state =>
+ {
+ var t = (Tuple<TextWriter, char[], int, int>)state;
+ t.Item1.WriteLine(t.Item2, t.Item3, t.Item4);
+ },
+ tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task WriteLineAsync()
+ {
+ return WriteAsync(CoreNewLine);
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public virtual Task FlushAsync()
+ {
+ return Task.Factory.StartNew(state =>
+ {
+ ((TextWriter)state).Flush();
+ },
+ this, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+ #endregion
+
+ [Serializable]
+ private sealed class NullTextWriter : TextWriter
+ {
+ internal NullTextWriter(): base(CultureInfo.InvariantCulture) {
+ }
+
+ public override Encoding Encoding {
+ get { return Encoding.Default; }
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void Write(char[] buffer, int index, int count) {
+ }
+
+ public override void Write(String value) {
+ }
+
+ // Not strictly necessary, but for perf reasons
+ public override void WriteLine() {
+ }
+
+ // Not strictly necessary, but for perf reasons
+ public override void WriteLine(String value) {
+ }
+
+ public override void WriteLine(Object value) {
+ }
+ }
+
+ [Serializable]
+ internal sealed class SyncTextWriter : TextWriter, IDisposable
+ {
+ private TextWriter _out;
+
+ internal SyncTextWriter(TextWriter t): base(t.FormatProvider) {
+ _out = t;
+ }
+
+ public override Encoding Encoding {
+ get { return _out.Encoding; }
+ }
+
+ public override IFormatProvider FormatProvider {
+ get { return _out.FormatProvider; }
+ }
+
+ public override String NewLine {
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ get { return _out.NewLine; }
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ set { _out.NewLine = value; }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Close() {
+ // So that any overriden Close() gets run
+ _out.Close();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ protected override void Dispose(bool disposing) {
+ // Explicitly pick up a potentially methodimpl'ed Dispose
+ if (disposing)
+ ((IDisposable)_out).Dispose();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Flush() {
+ _out.Flush();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(char value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(char[] buffer) {
+ _out.Write(buffer);
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(char[] buffer, int index, int count) {
+ _out.Write(buffer, index, count);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(bool value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(int value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(uint value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(long value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(ulong value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(float value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(double value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(Decimal value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(String value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(Object value) {
+ _out.Write(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(String format, Object arg0) {
+ _out.Write(format, arg0);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(String format, Object arg0, Object arg1) {
+ _out.Write(format, arg0, arg1);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(String format, Object arg0, Object arg1, Object arg2) {
+ _out.Write(format, arg0, arg1, arg2);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void Write(String format, Object[] arg) {
+ _out.Write(format, arg);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine() {
+ _out.WriteLine();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(char value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(decimal value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(char[] buffer) {
+ _out.WriteLine(buffer);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(char[] buffer, int index, int count) {
+ _out.WriteLine(buffer, index, count);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(bool value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(int value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(uint value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(long value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(ulong value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(float value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(double value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(String value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(Object value) {
+ _out.WriteLine(value);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(String format, Object arg0) {
+ _out.WriteLine(format, arg0);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(String format, Object arg0, Object arg1) {
+ _out.WriteLine(format, arg0, arg1);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(String format, Object arg0, Object arg1, Object arg2) {
+ _out.WriteLine(format, arg0, arg1, arg2);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public override void WriteLine(String format, Object[] arg) {
+ _out.WriteLine(format, arg);
+ }
+
+
+ //
+ // On SyncTextWriter all APIs should run synchronously, even the async ones.
+ //
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char value)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteAsync(String value)
+ {
+ Write(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteAsync(char[] buffer, int index, int count)
+ {
+ Write(buffer, index, count);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char value)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(String value)
+ {
+ WriteLine(value);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task WriteLineAsync(char[] buffer, int index, int count)
+ {
+ WriteLine(buffer, index, count);
+ return Task.CompletedTask;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ [ComVisible(false)]
+ public override Task FlushAsync()
+ {
+ Flush();
+ return Task.CompletedTask;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs
new file mode 100644
index 0000000000..ea70057217
--- /dev/null
+++ b/src/mscorlib/src/System/IO/UnmanagedMemoryAccessor.cs
@@ -0,0 +1,1176 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Provides a fast, AV free, cross-language way of
+** accessing unmanaged memory in a random fashion.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using System.Security.Permissions;
+using Microsoft.Win32.SafeHandles;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+
+ /// Perf notes: ReadXXX, WriteXXX (for basic types) acquire and release the
+ /// SafeBuffer pointer rather than relying on generic Read(T) from SafeBuffer because
+ /// this gives better throughput; benchmarks showed about 12-15% better.
+ public class UnmanagedMemoryAccessor : IDisposable {
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SafeBuffer _buffer;
+ private Int64 _offset;
+ [ContractPublicPropertyName("Capacity")]
+ private Int64 _capacity;
+ private FileAccess _access;
+ private bool _isOpen;
+ private bool _canRead;
+ private bool _canWrite;
+
+ protected UnmanagedMemoryAccessor() {
+ _isOpen = false;
+ }
+
+ #region SafeBuffer ctors and initializers
+ // <SecurityKernel Critical="True" Ring="1">
+ // <ReferencesCritical Name="Method: Initialize(SafeBuffer, Int64, Int64, FileAccess):Void" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical]
+ public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity) {
+ Initialize(buffer, offset, capacity, FileAccess.Read);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public UnmanagedMemoryAccessor(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) {
+ Initialize(buffer, offset, capacity, access);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ protected void Initialize(SafeBuffer buffer, Int64 offset, Int64 capacity, FileAccess access) {
+ if (buffer == null) {
+ throw new ArgumentNullException("buffer");
+ }
+ if (offset < 0) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (capacity < 0) {
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (buffer.ByteLength < (UInt64)(offset + capacity)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndCapacityOutOfBounds"));
+ }
+ if (access < FileAccess.Read || access > FileAccess.ReadWrite) {
+ throw new ArgumentOutOfRangeException("access");
+ }
+ Contract.EndContractBlock();
+
+ if (_isOpen) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
+ }
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ buffer.AcquirePointer(ref pointer);
+ if (((byte*)((Int64)pointer + offset + capacity)) < pointer) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_UnmanagedMemAccessorWrapAround"));
+ }
+ }
+ finally {
+ if (pointer != null) {
+ buffer.ReleasePointer();
+ }
+ }
+ }
+
+ _offset = offset;
+ _buffer = buffer;
+ _capacity = capacity;
+ _access = access;
+ _isOpen = true;
+ _canRead = (_access & FileAccess.Read) != 0;
+ _canWrite = (_access & FileAccess.Write) != 0;
+ }
+
+ #endregion
+
+ public Int64 Capacity {
+ get {
+ return _capacity;
+ }
+ }
+
+ public bool CanRead {
+ get {
+ return _isOpen && _canRead;
+ }
+ }
+
+ public bool CanWrite {
+ get {
+ return _isOpen && _canWrite;
+ }
+ }
+
+ protected virtual void Dispose(bool disposing) {
+ _isOpen = false;
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected bool IsOpen {
+ get { return _isOpen; }
+ }
+
+ public bool ReadBoolean(Int64 position) {
+ int sizeOfType = sizeof(bool);
+ EnsureSafeToRead(position, sizeOfType);
+
+ byte b = InternalReadByte(position);
+ return b != 0;
+ }
+
+ public byte ReadByte(Int64 position) {
+ int sizeOfType = sizeof(byte);
+ EnsureSafeToRead(position, sizeOfType);
+
+ return InternalReadByte(position);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public char ReadChar(Int64 position) {
+ int sizeOfType = sizeof(char);
+ EnsureSafeToRead(position, sizeOfType);
+
+ char result;
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((char*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ result = (char)( *pointer | *(pointer + 1) << 8 ) ;
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ // See comment above.
+ [System.Security.SecuritySafeCritical]
+ public Int16 ReadInt16(Int64 position) {
+ int sizeOfType = sizeof(Int16);
+ EnsureSafeToRead(position, sizeOfType);
+
+ Int16 result;
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((Int16*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ result = (Int16)( *pointer | *(pointer + 1) << 8 );
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Int32 ReadInt32(Int64 position) {
+ int sizeOfType = sizeof(Int32);
+ EnsureSafeToRead(position, sizeOfType);
+
+ Int32 result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((Int32*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ result = (Int32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Int64 ReadInt64(Int64 position) {
+ int sizeOfType = sizeof(Int64);
+ EnsureSafeToRead(position, sizeOfType);
+
+ Int64 result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((Int64*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ int lo = *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24;
+ int hi = *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24;
+ result = (Int64)(((Int64)hi << 32) | (UInt32)lo);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Decimal ReadDecimal(Int64 position) {
+ int sizeOfType = sizeof(Decimal);
+ EnsureSafeToRead(position, sizeOfType);
+
+ int[] decimalArray = new int[4];
+ ReadArray<int>(position, decimalArray, 0, decimalArray.Length);
+
+ return new Decimal(decimalArray);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Single ReadSingle(Int64 position) {
+ int sizeOfType = sizeof(Single);
+ EnsureSafeToRead(position, sizeOfType);
+
+ Single result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((Single*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ UInt32 tempResult = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
+ result = *((float*)&tempResult);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Double ReadDouble(Int64 position) {
+ int sizeOfType = sizeof(Double);
+ EnsureSafeToRead(position, sizeOfType);
+
+ Double result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((Double*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+
+ UInt32 lo = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
+ UInt32 hi = (UInt32)( *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24 );
+ UInt64 tempResult = ((UInt64)hi) << 32 | lo;
+ result = *((double*)&tempResult);
+
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public SByte ReadSByte(Int64 position) {
+ int sizeOfType = sizeof(SByte);
+ EnsureSafeToRead(position, sizeOfType);
+
+ SByte result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+ result = *((SByte*)pointer);
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public UInt16 ReadUInt16(Int64 position) {
+ int sizeOfType = sizeof(UInt16);
+ EnsureSafeToRead(position, sizeOfType);
+
+ UInt16 result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((UInt16*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ result = (UInt16)( *pointer | *(pointer + 1) << 8 );
+ }
+#endif
+
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public UInt32 ReadUInt32(Int64 position) {
+ int sizeOfType = sizeof(UInt32);
+ EnsureSafeToRead(position, sizeOfType);
+
+ UInt32 result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((UInt32*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ result = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
+ }
+#endif
+
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public UInt64 ReadUInt64(Int64 position) {
+ int sizeOfType = sizeof(UInt64);
+ EnsureSafeToRead(position, sizeOfType);
+
+ UInt64 result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ result = *((UInt64*)(pointer));
+#if ALIGN_ACCESS
+ }
+ else {
+ UInt32 lo = (UInt32)( *pointer | *(pointer + 1) << 8 | *(pointer + 2) << 16 | *(pointer + 3) << 24 );
+ UInt32 hi = (UInt32)( *(pointer + 4) | *(pointer + 5) << 8 | *(pointer + 6) << 16 | *(pointer + 7) << 24 );
+ result = (UInt64)(((UInt64)hi << 32) | lo );
+ }
+#endif
+
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ // Reads a struct of type T from unmanaged memory, into the reference pointed to by ref value.
+ // Note: this method is not safe, since it overwrites the contents of a structure, it can be
+ // used to modify the private members of a struct. Furthermore, using this with a struct that
+ // contains reference members will most likely cause the runtime to AV. Note, that despite
+ // various checks made by the C++ code used by Marshal.PtrToStructure, Marshal.PtrToStructure
+ // will still overwrite privates and will also crash the runtime when used with structs
+ // containing reference members. For this reason, I am sticking an UnmanagedCode requirement
+ // on this method to match Marshal.PtrToStructure.
+
+ // Alos note that this method is most performant when used with medium to large sized structs
+ // (larger than 8 bytes -- though this is number is JIT and architecture dependent). As
+ // such, it is best to use the ReadXXX methods for small standard types such as ints, longs,
+ // bools, etc.
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void Read<T>(Int64 position, out T structure) where T : struct {
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ if (!CanRead) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
+ }
+
+ UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
+ if (position > _capacity - sizeOfT) {
+ if (position >= _capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead", typeof(T).FullName), "position");
+ }
+ }
+
+ structure = _buffer.Read<T>((UInt64)(_offset + position));
+ }
+
+ // Reads 'count' structs of type T from unmanaged memory, into 'array' starting at 'offset'.
+ // Note: this method is not safe, since it overwrites the contents of structures, it can
+ // be used to modify the private members of a struct. Furthermore, using this with a
+ // struct that contains reference members will most likely cause the runtime to AV. This
+ // is consistent with Marshal.PtrToStructure.
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public int ReadArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct {
+ if (array == null) {
+ throw new ArgumentNullException("array", "Buffer cannot be null.");
+ }
+ if (offset < 0) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (array.Length - offset < count) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds"));
+ }
+ Contract.EndContractBlock();
+ if (!CanRead) {
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ else {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
+ }
+ }
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ UInt32 sizeOfT = Marshal.AlignedSizeOf<T>();
+
+ // only check position and ask for fewer Ts if count is too big
+ if (position >= _capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+
+ int n = count;
+ long spaceLeft = _capacity - position;
+ if (spaceLeft < 0) {
+ n = 0;
+ }
+ else {
+ ulong spaceNeeded = (ulong)(sizeOfT * count);
+ if ((ulong)spaceLeft < spaceNeeded) {
+ n = (int)(spaceLeft / sizeOfT);
+ }
+ }
+
+ _buffer.ReadArray<T>((UInt64)(_offset + position), array, offset, n);
+
+ return n;
+ }
+
+ // ************** Write Methods ****************/
+
+ // The following 13 WriteXXX methods write a value of type XXX into unmanaged memory at 'positon'.
+ // The bounds of the unmanaged memory are checked against to ensure that there is enough
+ // space after 'position' to write a value of type XXX. XXX can be a bool, byte, char, decimal,
+ // double, short, int, long, sbyte, float, ushort, uint, or ulong.
+
+
+ public void Write(Int64 position, bool value) {
+ int sizeOfType = sizeof(bool);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ byte b = (byte)(value ? 1 : 0);
+ InternalWrite(position, b);
+ }
+
+ public void Write(Int64 position, byte value) {
+ int sizeOfType = sizeof(byte);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ InternalWrite(position, value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, char value) {
+ int sizeOfType = sizeof(char);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((char*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer+1) = (byte)(value >> 8);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Int16 value) {
+ int sizeOfType = sizeof(Int16);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((Int16*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Int32 value) {
+ int sizeOfType = sizeof(Int32);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((Int32*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ *(pointer + 2) = (byte)(value >> 16);
+ *(pointer + 3) = (byte)(value >> 24);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Int64 value) {
+ int sizeOfType = sizeof(Int64);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((Int64*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ *(pointer + 2) = (byte)(value >> 16);
+ *(pointer + 3) = (byte)(value >> 24);
+ *(pointer + 4) = (byte)(value >> 32);
+ *(pointer + 5) = (byte)(value >> 40);
+ *(pointer + 6) = (byte)(value >> 48);
+ *(pointer + 7) = (byte)(value >> 56);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Decimal value) {
+ int sizeOfType = sizeof(Decimal);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ byte[] decimalArray = new byte[16];
+ Decimal.GetBytes(value, decimalArray);
+
+ int[] bits = new int[4];
+ int flags = ((int)decimalArray[12]) | ((int)decimalArray[13] << 8) | ((int)decimalArray[14] << 16) | ((int)decimalArray[15] << 24);
+ int lo = ((int)decimalArray[0]) | ((int)decimalArray[1] << 8) | ((int)decimalArray[2] << 16) | ((int)decimalArray[3] << 24);
+ int mid = ((int)decimalArray[4]) | ((int)decimalArray[5] << 8) | ((int)decimalArray[6] << 16) | ((int)decimalArray[7] << 24);
+ int hi = ((int)decimalArray[8]) | ((int)decimalArray[9] << 8) | ((int)decimalArray[10] << 16) | ((int)decimalArray[11] << 24);
+ bits[0] = lo;
+ bits[1] = mid;
+ bits[2] = hi;
+ bits[3] = flags;
+
+ WriteArray<int>(position, bits, 0, bits.Length);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Single value) {
+ int sizeOfType = sizeof(Single);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((Single*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ UInt32 tmpValue = *(UInt32*)&value;
+ *(pointer) = (byte)tmpValue;
+ *(pointer + 1) = (byte)(tmpValue >> 8);
+ *(pointer + 2) = (byte)(tmpValue >> 16);
+ *(pointer + 3) = (byte)(tmpValue >> 24);
+
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Write(Int64 position, Double value) {
+ int sizeOfType = sizeof(Double);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((Double*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ UInt64 tmpValue = *(UInt64 *)&value;
+ *(pointer) = (byte) tmpValue;
+ *(pointer + 1) = (byte) (tmpValue >> 8);
+ *(pointer + 2) = (byte) (tmpValue >> 16);
+ *(pointer + 3) = (byte) (tmpValue >> 24);
+ *(pointer + 4) = (byte) (tmpValue >> 32);
+ *(pointer + 5) = (byte) (tmpValue >> 40);
+ *(pointer + 6) = (byte) (tmpValue >> 48);
+ *(pointer + 7) = (byte) (tmpValue >> 56);
+
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public void Write(Int64 position, SByte value) {
+ int sizeOfType = sizeof(SByte);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+ *((SByte*)pointer) = value;
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public void Write(Int64 position, UInt16 value) {
+ int sizeOfType = sizeof(UInt16);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((UInt16*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ }
+#endif
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public void Write(Int64 position, UInt32 value) {
+ int sizeOfType = sizeof(UInt32);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((UInt32*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ *(pointer + 2) = (byte)(value >> 16);
+ *(pointer + 3) = (byte)(value >> 24);
+ }
+#endif
+
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public void Write(Int64 position, UInt64 value) {
+ int sizeOfType = sizeof(UInt64);
+ EnsureSafeToWrite(position, sizeOfType);
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ pointer += (_offset + position);
+#if ALIGN_ACCESS
+ // check if pointer is aligned
+ if (((int)pointer & (sizeOfType - 1)) == 0) {
+#endif
+ *((UInt64*)pointer) = value;
+#if ALIGN_ACCESS
+ }
+ else {
+ *(pointer) = (byte)value;
+ *(pointer + 1) = (byte)(value >> 8);
+ *(pointer + 2) = (byte)(value >> 16);
+ *(pointer + 3) = (byte)(value >> 24);
+ *(pointer + 4) = (byte)(value >> 32);
+ *(pointer + 5) = (byte)(value >> 40);
+ *(pointer + 6) = (byte)(value >> 48);
+ *(pointer + 7) = (byte)(value >> 56);
+ }
+#endif
+
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ // Writes the struct pointed to by ref value into unmanaged memory. Note that this method
+ // is most performant when used with medium to large sized structs (larger than 8 bytes
+ // though this is number is JIT and architecture dependent). As such, it is best to use
+ // the WriteX methods for small standard types such as ints, longs, bools, etc.
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void Write<T>(Int64 position, ref T structure) where T : struct {
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ if (!CanWrite) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
+ }
+
+ UInt32 sizeOfT = Marshal.SizeOfType(typeof(T));
+ if (position > _capacity - sizeOfT) {
+ if (position >= _capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", typeof(T).FullName), "position");
+ }
+ }
+
+ _buffer.Write<T>((UInt64)(_offset + position), structure);
+ }
+
+ // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory.
+
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void WriteArray<T>(Int64 position, T[] array, Int32 offset, Int32 count) where T : struct {
+ if (array == null) {
+ throw new ArgumentNullException("array", "Buffer cannot be null.");
+ }
+ if (offset < 0) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (array.Length - offset < count) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetAndLengthOutOfBounds"));
+ }
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (position >= Capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+ Contract.EndContractBlock();
+
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ if (!CanWrite) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
+ }
+
+ _buffer.WriteArray<T>((UInt64)(_offset + position), array, offset, count);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private byte InternalReadByte(Int64 position) {
+ Contract.Assert(CanRead, "UMA not readable");
+ Contract.Assert(position >= 0, "position less than 0");
+ Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
+
+ byte result;
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ result = *((byte*)(pointer + _offset + position));
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void InternalWrite(Int64 position, byte value) {
+ Contract.Assert(CanWrite, "UMA not writeable");
+ Contract.Assert(position >= 0, "position less than 0");
+ Contract.Assert(position <= _capacity - sizeof(byte), "position is greater than capacity - sizeof(byte)");
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ *((byte*)(pointer + _offset + position)) = value;
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+
+ private void EnsureSafeToRead(Int64 position, int sizeOfType) {
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ if (!CanRead) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Reading"));
+ }
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+ if (position > _capacity - sizeOfType) {
+ if (position >= _capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToRead"), "position");
+ }
+ }
+ }
+
+ private void EnsureSafeToWrite(Int64 position, int sizeOfType) {
+ if (!_isOpen) {
+ throw new ObjectDisposedException("UnmanagedMemoryAccessor", Environment.GetResourceString("ObjectDisposed_ViewAccessorClosed"));
+ }
+ if (!CanWrite) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_Writing"));
+ }
+ if (position < 0) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+ if (position > _capacity - sizeOfType) {
+ if (position >= _capacity) {
+ throw new ArgumentOutOfRangeException("position", Environment.GetResourceString("ArgumentOutOfRange_PositionLessThanCapacityRequired"));
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotEnoughBytesToWrite", "Byte"), "position");
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs
new file mode 100644
index 0000000000..6b506ea5b1
--- /dev/null
+++ b/src/mscorlib/src/System/IO/UnmanagedMemoryStream.cs
@@ -0,0 +1,712 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Create a stream over unmanaged memory, mostly
+** useful for memory-mapped files.
+**
+**
+===========================================================*/
+using System;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+using System.Diagnostics.Contracts;
+using System.Threading.Tasks;
+
+
+namespace System.IO {
+
+ /*
+ * This class is used to access a contiguous block of memory, likely outside
+ * the GC heap (or pinned in place in the GC heap, but a MemoryStream may
+ * make more sense in those cases). It's great if you have a pointer and
+ * a length for a section of memory mapped in by someone else and you don't
+ * want to copy this into the GC heap. UnmanagedMemoryStream assumes these
+ * two things:
+ *
+ * 1) All the memory in the specified block is readable or writable,
+ * depending on the values you pass to the constructor.
+ * 2) The lifetime of the block of memory is at least as long as the lifetime
+ * of the UnmanagedMemoryStream.
+ * 3) You clean up the memory when appropriate. The UnmanagedMemoryStream
+ * currently will do NOTHING to free this memory.
+ * 4) All calls to Write and WriteByte may not be threadsafe currently.
+ *
+ * It may become necessary to add in some sort of
+ * DeallocationMode enum, specifying whether we unmap a section of memory,
+ * call free, run a user-provided delegate to free the memory, etc etc.
+ * We'll suggest user write a subclass of UnmanagedMemoryStream that uses
+ * a SafeHandle subclass to hold onto the memory.
+ * Check for problems when using this in the negative parts of a
+ * process's address space. We may need to use unsigned longs internally
+ * and change the overflow detection logic.
+ *
+ * -----SECURITY MODEL AND SILVERLIGHT-----
+ * A few key notes about exposing UMS in silverlight:
+ * 1. No ctors are exposed to transparent code. This version of UMS only
+ * supports byte* (not SafeBuffer). Therefore, framework code can create
+ * a UMS and hand it to transparent code. Transparent code can use most
+ * operations on a UMS, but not operations that directly expose a
+ * pointer.
+ *
+ * 2. Scope of "unsafe" and non-CLS compliant operations reduced: The
+ * Whidbey version of this class has CLSCompliant(false) at the class
+ * level and unsafe modifiers at the method level. These were reduced to
+ * only where the unsafe operation is performed -- i.e. immediately
+ * around the pointer manipulation. Note that this brings UMS in line
+ * with recent changes in pu/clr to support SafeBuffer.
+ *
+ * 3. Currently, the only caller that creates a UMS is ResourceManager,
+ * which creates read-only UMSs, and therefore operations that can
+ * change the length will throw because write isn't supported. A
+ * conservative option would be to formalize the concept that _only_
+ * read-only UMSs can be creates, and enforce this by making WriteX and
+ * SetLength SecurityCritical. However, this is a violation of
+ * security inheritance rules, so we must keep these safe. The
+ * following notes make this acceptable for future use.
+ * a. a race condition in WriteX that could have allowed a thread to
+ * read from unzeroed memory was fixed
+ * b. memory region cannot be expanded beyond _capacity; in other
+ * words, a UMS creator is saying a writeable UMS is safe to
+ * write to anywhere in the memory range up to _capacity, specified
+ * in the ctor. Even if the caller doesn't specify a capacity, then
+ * length is used as the capacity.
+ */
+ public class UnmanagedMemoryStream : Stream
+ {
+ private const long UnmanagedMemStreamMaxLength = Int64.MaxValue;
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SafeBuffer _buffer;
+ [SecurityCritical]
+ private unsafe byte* _mem;
+ private long _length;
+ private long _capacity;
+ private long _position;
+ private long _offset;
+ private FileAccess _access;
+ internal bool _isOpen;
+ [NonSerialized]
+ private Task<Int32> _lastReadTask; // The last successful task returned from ReadAsync
+
+
+ // Needed for subclasses that need to map a file, etc.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected UnmanagedMemoryStream()
+ {
+ unsafe {
+ _mem = null;
+ }
+ _isOpen = false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length) {
+ Initialize(buffer, offset, length, FileAccess.Read, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access) {
+ Initialize(buffer, offset, length, access, false);
+ }
+
+ // We must create one of these without doing a security check. This
+ // class is created while security is trying to start up. Plus, doing
+ // a Demand from Assembly.GetManifestResourceStream isn't useful.
+ [System.Security.SecurityCritical] // auto-generated
+ internal UnmanagedMemoryStream(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck) {
+ Initialize(buffer, offset, length, access, skipSecurityCheck);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access) {
+ Initialize(buffer, offset, length, access, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void Initialize(SafeBuffer buffer, long offset, long length, FileAccess access, bool skipSecurityCheck) {
+ if (buffer == null) {
+ throw new ArgumentNullException("buffer");
+ }
+ if (offset < 0) {
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (buffer.ByteLength < (ulong)(offset + length)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSafeBufferOffLen"));
+ }
+ if (access < FileAccess.Read || access > FileAccess.ReadWrite) {
+ throw new ArgumentOutOfRangeException("access");
+ }
+ Contract.EndContractBlock();
+
+ if (_isOpen) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
+ }
+ if (!skipSecurityCheck) {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+
+ // check for wraparound
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ buffer.AcquirePointer(ref pointer);
+ if ( (pointer + offset + length) < pointer) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround"));
+ }
+ }
+ finally {
+ if (pointer != null) {
+ buffer.ReleasePointer();
+ }
+ }
+ }
+
+ _offset = offset;
+ _buffer = buffer;
+ _length = length;
+ _capacity = length;
+ _access = access;
+ _isOpen = true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe UnmanagedMemoryStream(byte* pointer, long length)
+ {
+ Initialize(pointer, length, length, FileAccess.Read, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access)
+ {
+ Initialize(pointer, length, capacity, access, false);
+ }
+
+ // We must create one of these without doing a security check. This
+ // class is created while security is trying to start up. Plus, doing
+ // a Demand from Assembly.GetManifestResourceStream isn't useful.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe UnmanagedMemoryStream(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck)
+ {
+ Initialize(pointer, length, capacity, access, skipSecurityCheck);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ protected unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access)
+ {
+ Initialize(pointer, length, capacity, access, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void Initialize(byte* pointer, long length, long capacity, FileAccess access, bool skipSecurityCheck)
+ {
+ if (pointer == null)
+ throw new ArgumentNullException("pointer");
+ if (length < 0 || capacity < 0)
+ throw new ArgumentOutOfRangeException((length < 0) ? "length" : "capacity", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (length > capacity)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_LengthGreaterThanCapacity"));
+ Contract.EndContractBlock();
+ // Check for wraparound.
+ if (((byte*) ((long)pointer + capacity)) < pointer)
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamWrapAround"));
+ if (access < FileAccess.Read || access > FileAccess.ReadWrite)
+ throw new ArgumentOutOfRangeException("access", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ if (_isOpen)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CalledTwice"));
+
+ if (!skipSecurityCheck)
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+
+ _mem = pointer;
+ _offset = 0;
+ _length = length;
+ _capacity = capacity;
+ _access = access;
+ _isOpen = true;
+ }
+
+ public override bool CanRead {
+ [Pure]
+ get { return _isOpen && (_access & FileAccess.Read) != 0; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _isOpen; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _isOpen && (_access & FileAccess.Write) != 0; }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override void Dispose(bool disposing)
+ {
+ _isOpen = false;
+ unsafe { _mem = null; }
+
+ // Stream allocates WaitHandles for async calls. So for correctness
+ // call base.Dispose(disposing) for better perf, avoiding waiting
+ // for the finalizers to run on those types.
+ base.Dispose(disposing);
+ }
+
+ public override void Flush() {
+ if (!_isOpen) __Error.StreamIsClosed();
+ }
+
+ [HostProtection(ExternalThreading=true)]
+ [ComVisible(false)]
+ public override Task FlushAsync(CancellationToken cancellationToken) {
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ try {
+
+ Flush();
+ return Task.CompletedTask;
+
+ } catch(Exception ex) {
+
+ return Task.FromException(ex);
+ }
+ }
+
+
+ public override long Length {
+ get {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return Interlocked.Read(ref _length);
+ }
+ }
+
+ public long Capacity {
+ get {
+ if (!_isOpen) __Error.StreamIsClosed();
+ return _capacity;
+ }
+ }
+
+ public override long Position {
+ get {
+ if (!CanSeek) __Error.StreamIsClosed();
+ Contract.EndContractBlock();
+ return Interlocked.Read(ref _position);
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ set {
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (!CanSeek) __Error.StreamIsClosed();
+
+#if !BIT64
+ unsafe {
+ // On 32 bit machines, ensure we don't wrap around.
+ if (value > (long) Int32.MaxValue || _mem + value < _mem)
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_StreamLength"));
+ }
+#endif
+ Interlocked.Exchange(ref _position, value);
+ }
+ }
+
+ [CLSCompliant(false)]
+ public unsafe byte* PositionPointer {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get {
+ if (_buffer != null) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer"));
+ }
+
+ // Use a temp to avoid a race
+ long pos = Interlocked.Read(ref _position);
+ if (pos > _capacity)
+ throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_UMSPosition"));
+ byte * ptr = _mem + pos;
+ if (!_isOpen) __Error.StreamIsClosed();
+ return ptr;
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ set {
+ if (_buffer != null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer"));
+ if (!_isOpen) __Error.StreamIsClosed();
+
+ // Note: subtracting pointers returns an Int64. Working around
+ // to avoid hitting compiler warning CS0652 on this line.
+ if (new IntPtr(value - _mem).ToInt64() > UnmanagedMemStreamMaxLength)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamLength"));
+ if (value < _mem)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+
+ Interlocked.Exchange(ref _position, value - _mem);
+ }
+ }
+
+ internal unsafe byte* Pointer {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ if (_buffer != null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer"));
+
+ return _mem;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int Read([In, Out] byte[] buffer, int offset, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // Keep this in sync with contract validation in ReadAsync
+
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!CanRead) __Error.ReadNotSupported();
+
+ // Use a local variable to avoid a race where another thread
+ // changes our position after we decide we can read some bytes.
+ long pos = Interlocked.Read(ref _position);
+ long len = Interlocked.Read(ref _length);
+ long n = len - pos;
+ if (n > count)
+ n = count;
+ if (n <= 0)
+ return 0;
+
+ int nInt = (int) n; // Safe because n <= count, which is an Int32
+ if (nInt < 0)
+ nInt = 0; // _position could be beyond EOF
+ Contract.Assert(pos + nInt >= 0, "_position + n >= 0"); // len is less than 2^63 -1.
+
+ if (_buffer != null) {
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ Buffer.Memcpy(buffer, offset, pointer + pos + _offset, 0, nInt);
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+ else {
+ unsafe {
+ Buffer.Memcpy(buffer, offset, _mem + pos, 0, nInt);
+ }
+ }
+ Interlocked.Exchange(ref _position, pos + n);
+ return nInt;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // contract validation copied from Read(...)
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<Int32>(cancellationToken);
+
+ try {
+
+ Int32 n = Read(buffer, offset, count);
+ Task<Int32> t = _lastReadTask;
+ return (t != null && t.Result == n) ? t : (_lastReadTask = Task.FromResult<Int32>(n));
+
+ } catch (Exception ex) {
+
+ Contract.Assert(! (ex is OperationCanceledException));
+ return Task.FromException<Int32>(ex);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int ReadByte() {
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!CanRead) __Error.ReadNotSupported();
+
+ long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
+ long len = Interlocked.Read(ref _length);
+ if (pos >= len)
+ return -1;
+ Interlocked.Exchange(ref _position, pos + 1);
+ int result;
+ if (_buffer != null) {
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ result = *(pointer + pos + _offset);
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+ else {
+ unsafe {
+ result = _mem[pos];
+ }
+ }
+ return result;
+ }
+
+ public override long Seek(long offset, SeekOrigin loc) {
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (offset > UnmanagedMemStreamMaxLength)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_UnmanagedMemStreamLength"));
+ switch(loc) {
+ case SeekOrigin.Begin:
+ if (offset < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ Interlocked.Exchange(ref _position, offset);
+ break;
+
+ case SeekOrigin.Current:
+ long pos = Interlocked.Read(ref _position);
+ if (offset + pos < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ Interlocked.Exchange(ref _position, offset + pos);
+ break;
+
+ case SeekOrigin.End:
+ long len = Interlocked.Read(ref _length);
+ if (len + offset < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SeekBeforeBegin"));
+ Interlocked.Exchange(ref _position, len + offset);
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSeekOrigin"));
+ }
+
+ long finalPos = Interlocked.Read(ref _position);
+ Contract.Assert(finalPos >= 0, "_position >= 0");
+ return finalPos;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void SetLength(long value) {
+ if (value < 0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ if (_buffer != null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UmsSafeBuffer"));
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ if (value > _capacity)
+ throw new IOException(Environment.GetResourceString("IO.IO_FixedCapacity"));
+
+ long pos = Interlocked.Read(ref _position);
+ long len = Interlocked.Read(ref _length);
+ if (value > len) {
+ unsafe {
+ Buffer.ZeroMemory(_mem+len, value-len);
+ }
+ }
+ Interlocked.Exchange(ref _length, value);
+ if (pos > value) {
+ Interlocked.Exchange(ref _position, value);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Write(byte[] buffer, int offset, int count) {
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // Keep contract validation in sync with WriteAsync(..)
+
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
+ long len = Interlocked.Read(ref _length);
+ long n = pos + count;
+ // Check for overflow
+ if (n < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_StreamTooLong"));
+
+ if (n > _capacity) {
+ throw new NotSupportedException(Environment.GetResourceString("IO.IO_FixedCapacity"));
+ }
+
+ if (_buffer == null) {
+ // Check to see whether we are now expanding the stream and must
+ // zero any memory in the middle.
+ if (pos > len) {
+ unsafe {
+ Buffer.ZeroMemory(_mem+len, pos-len);
+ }
+ }
+
+ // set length after zeroing memory to avoid race condition of accessing unzeroed memory
+ if (n > len) {
+ Interlocked.Exchange(ref _length, n);
+ }
+ }
+
+ if (_buffer != null) {
+
+ long bytesLeft = _capacity - pos;
+ if (bytesLeft < count) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_BufferTooSmall"));
+ }
+
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ Buffer.Memcpy(pointer + pos + _offset, 0, buffer, offset, count);
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+ else {
+ unsafe {
+ Buffer.Memcpy(_mem + pos, 0, buffer, offset, count);
+ }
+ }
+ Interlocked.Exchange(ref _position, n);
+ return;
+ }
+
+ [HostProtection(ExternalThreading = true)]
+ [ComVisible(false)]
+ public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+
+ if (buffer==null)
+ throw new ArgumentNullException("buffer", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (offset < 0)
+ throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (buffer.Length - offset < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock(); // contract validation copied from Write(..)
+
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ try {
+
+ Write(buffer, offset, count);
+ return Task.CompletedTask;
+
+ } catch (Exception ex) {
+
+ Contract.Assert(! (ex is OperationCanceledException));
+ return Task.FromException<Int32>(ex);
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void WriteByte(byte value) {
+ if (!_isOpen) __Error.StreamIsClosed();
+ if (!CanWrite) __Error.WriteNotSupported();
+
+ long pos = Interlocked.Read(ref _position); // Use a local to avoid a race condition
+ long len = Interlocked.Read(ref _length);
+ long n = pos + 1;
+ if (pos >= len) {
+ // Check for overflow
+ if (n < 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_StreamTooLong"));
+
+ if (n > _capacity)
+ throw new NotSupportedException(Environment.GetResourceString("IO.IO_FixedCapacity"));
+
+ // Check to see whether we are now expanding the stream and must
+ // zero any memory in the middle.
+ // don't do if created from SafeBuffer
+ if (_buffer == null) {
+ if (pos > len) {
+ unsafe {
+ Buffer.ZeroMemory(_mem+len, pos-len);
+ }
+ }
+
+ // set length after zeroing memory to avoid race condition of accessing unzeroed memory
+ Interlocked.Exchange(ref _length, n);
+ }
+ }
+
+ if (_buffer != null) {
+ unsafe {
+ byte* pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ _buffer.AcquirePointer(ref pointer);
+ *(pointer + pos + _offset) = value;
+ }
+ finally {
+ if (pointer != null) {
+ _buffer.ReleasePointer();
+ }
+ }
+ }
+ }
+ else {
+ unsafe {
+ _mem[pos] = value;
+ }
+ }
+ Interlocked.Exchange(ref _position, n);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs b/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs
new file mode 100644
index 0000000000..5727eeddf5
--- /dev/null
+++ b/src/mscorlib/src/System/IO/UnmanagedMemoryStreamWrapper.cs
@@ -0,0 +1,197 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Create a Memorystream over an UnmanagedMemoryStream
+**
+===========================================================*/
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.IO {
+ // Needed for backwards compatibility with V1.x usages of the
+ // ResourceManager, where a MemoryStream is now returned as an
+ // UnmanagedMemoryStream from ResourceReader.
+ internal sealed class UnmanagedMemoryStreamWrapper : MemoryStream {
+ private UnmanagedMemoryStream _unmanagedStream;
+
+ internal UnmanagedMemoryStreamWrapper(UnmanagedMemoryStream stream) {
+ _unmanagedStream = stream;
+ }
+
+ public override bool CanRead {
+ [Pure]
+ get { return _unmanagedStream.CanRead; }
+ }
+
+ public override bool CanSeek {
+ [Pure]
+ get { return _unmanagedStream.CanSeek; }
+ }
+
+ public override bool CanWrite {
+ [Pure]
+ get { return _unmanagedStream.CanWrite; }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ try {
+ if (disposing)
+ _unmanagedStream.Close();
+ }
+ finally {
+ base.Dispose(disposing);
+ }
+ }
+
+ public override void Flush() {
+ _unmanagedStream.Flush();
+ }
+
+ public override byte[] GetBuffer() {
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_MemStreamBuffer"));
+ }
+
+ public override bool TryGetBuffer(out ArraySegment<byte> buffer) {
+ buffer = default(ArraySegment<byte>);
+ return false;
+ }
+
+ public override int Capacity {
+ get {
+ return (int) _unmanagedStream.Capacity;
+ }
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ set {
+ throw new IOException(Environment.GetResourceString("IO.IO_FixedCapacity"));
+ }
+ }
+
+ public override long Length {
+ get {
+ return _unmanagedStream.Length;
+ }
+ }
+
+ public override long Position {
+ get {
+ return _unmanagedStream.Position;
+ }
+ set {
+ _unmanagedStream.Position = value;
+ }
+ }
+
+ public override int Read([In, Out] byte[] buffer, int offset, int count) {
+ return _unmanagedStream.Read(buffer, offset, count);
+ }
+
+ public override int ReadByte() {
+ return _unmanagedStream.ReadByte();
+ }
+
+ public override long Seek(long offset, SeekOrigin loc) {
+ return _unmanagedStream.Seek(offset, loc);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override byte[] ToArray() {
+ if (!_unmanagedStream._isOpen) __Error.StreamIsClosed();
+ if (!_unmanagedStream.CanRead) __Error.ReadNotSupported();
+
+ byte[] buffer = new byte[_unmanagedStream.Length];
+ Buffer.Memcpy(buffer, 0, _unmanagedStream.Pointer, 0, (int)_unmanagedStream.Length);
+ return buffer;
+ }
+
+ public override void Write(byte[] buffer, int offset, int count) {
+ _unmanagedStream.Write(buffer, offset, count);
+ }
+
+ public override void WriteByte(byte value) {
+ _unmanagedStream.WriteByte(value);
+ }
+
+ // Writes this MemoryStream to another stream.
+ public unsafe override void WriteTo(Stream stream) {
+ if (stream==null)
+ throw new ArgumentNullException("stream", Environment.GetResourceString("ArgumentNull_Stream"));
+ Contract.EndContractBlock();
+
+ if (!_unmanagedStream._isOpen) __Error.StreamIsClosed();
+ if (!CanRead) __Error.ReadNotSupported();
+
+ byte[] buffer = ToArray();
+
+ stream.Write(buffer, 0, buffer.Length);
+ }
+
+ public override void SetLength(Int64 value) {
+
+ // This was probably meant to call _unmanagedStream.SetLength(value), but it was forgotten in V.4.0.
+ // Now this results in a call to the base which touches the underlying array which is never actually used.
+ // We cannot fix it due to compat now, but we should fix this at the next SxS release oportunity.
+ base.SetLength(value);
+ }
+
+
+ public override Task CopyToAsync(Stream destination, Int32 bufferSize, CancellationToken cancellationToken) {
+
+ // The parameter checks must be in sync with the base version:
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+
+ if (bufferSize <= 0)
+ throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+
+ if (!CanRead && !CanWrite)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+
+ if (!destination.CanRead && !destination.CanWrite)
+ throw new ObjectDisposedException("destination", Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+
+ if (!CanRead)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
+
+ if (!destination.CanWrite)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
+
+ Contract.EndContractBlock();
+
+ return _unmanagedStream.CopyToAsync(destination, bufferSize, cancellationToken);
+ }
+
+
+ public override Task FlushAsync(CancellationToken cancellationToken) {
+
+ return _unmanagedStream.FlushAsync(cancellationToken);
+ }
+
+
+ public override Task<Int32> ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+
+ return _unmanagedStream.ReadAsync(buffer, offset, count, cancellationToken);
+ }
+
+
+ public override Task WriteAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken) {
+
+ return _unmanagedStream.WriteAsync(buffer, offset, count, cancellationToken);
+ }
+
+ } // class UnmanagedMemoryStreamWrapper
+} // namespace
+
+
diff --git a/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs b/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs
new file mode 100644
index 0000000000..621bc41b4b
--- /dev/null
+++ b/src/mscorlib/src/System/IO/__DebugOutputTextWriter.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if _DEBUG
+// This class writes to wherever OutputDebugString writes to. If you don't have
+// a Windows app (ie, something hosted in IE), you can use this to redirect Console
+// output for some good old-fashioned console spew in MSDEV's debug output window.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Security;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using Microsoft.Win32;
+using System.Globalization;
+
+namespace System.IO {
+ internal class __DebugOutputTextWriter : TextWriter {
+ private readonly String _consoleType;
+
+ internal __DebugOutputTextWriter(String consoleType): base(CultureInfo.InvariantCulture)
+ {
+ _consoleType = consoleType;
+ }
+
+ public override Encoding Encoding {
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ get {
+ if (Marshal.SystemDefaultCharSize == 1)
+ return Encoding.Default;
+ else
+ return new UnicodeEncoding(false, false);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Write(char c)
+ {
+ OutputDebugString(c.ToString());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Write(String str)
+ {
+ OutputDebugString(str);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Write(char[] array)
+ {
+ if (array != null)
+ OutputDebugString(new String(array));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void WriteLine(String str)
+ {
+ if (str != null)
+ OutputDebugString(_consoleType + str);
+ else
+ OutputDebugString("<null>");
+ OutputDebugString(new String(CoreNewLine));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(Win32Native.KERNEL32, CharSet=CharSet.Auto)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ private static extern void OutputDebugString(String output);
+ }
+}
+
+#endif // _DEBUG
diff --git a/src/mscorlib/src/System/IO/__Error.cs b/src/mscorlib/src/System/IO/__Error.cs
new file mode 100644
index 0000000000..a31d9657e8
--- /dev/null
+++ b/src/mscorlib/src/System/IO/__Error.cs
@@ -0,0 +1,232 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Centralized error methods for the IO package.
+** Mostly useful for translating Win32 HRESULTs into meaningful
+** error strings & exceptions.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.InteropServices;
+using Win32Native = Microsoft.Win32.Win32Native;
+using System.Text;
+using System.Globalization;
+using System.Security;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+
+namespace System.IO {
+ [Pure]
+ internal static class __Error
+ {
+ internal static void EndOfFile() {
+ throw new EndOfStreamException(Environment.GetResourceString("IO.EOF_ReadBeyondEOF"));
+ }
+
+ internal static void FileNotOpen() {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_FileClosed"));
+ }
+
+ internal static void StreamIsClosed() {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_StreamClosed"));
+ }
+
+ internal static void MemoryStreamNotExpandable() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_MemStreamNotExpandable"));
+ }
+
+ internal static void ReaderClosed() {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ReaderClosed"));
+ }
+
+ internal static void ReadNotSupported() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnreadableStream"));
+ }
+
+ internal static void SeekNotSupported() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnseekableStream"));
+ }
+
+ internal static void WrongAsyncResult() {
+ throw new ArgumentException(Environment.GetResourceString("Arg_WrongAsyncResult"));
+ }
+
+ internal static void EndReadCalledTwice() {
+ // Should ideally be InvalidOperationExc but we can't maitain parity with Stream and FileStream without some work
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndReadCalledMultiple"));
+ }
+
+ internal static void EndWriteCalledTwice() {
+ // Should ideally be InvalidOperationExc but we can't maintain parity with Stream and FileStream without some work
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EndWriteCalledMultiple"));
+ }
+
+ // Given a possible fully qualified path, ensure that we have path
+ // discovery permission to that path. If we do not, return just the
+ // file name. If we know it is a directory, then don't return the
+ // directory name.
+ [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 path;
+
+ bool safeToReturn = false;
+ try {
+ if (!isInvalidPath) {
+#if !FEATURE_CORECLR
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { path }, false, false).Demand();
+#endif
+ safeToReturn = true;
+ }
+ }
+ catch (SecurityException) {
+ }
+ catch (ArgumentException) {
+ // ? and * characters cause ArgumentException to be thrown from HasIllegalCharacters
+ // inside FileIOPermission.AddPathList
+ }
+ catch (NotSupportedException) {
+ // paths like "!Bogus\\dir:with/junk_.in it" can cause NotSupportedException to be thrown
+ // from Security.Util.StringExpressionSet.CanonicalizePath when ':' is found in the path
+ // beyond string index position 1.
+ }
+
+ if (!safeToReturn) {
+ if (Path.IsDirectorySeparator(path[path.Length - 1]))
+ path = Environment.GetResourceString("IO.IO_NoPermissionToDirectoryName");
+ else
+ path = Path.GetFileName(path);
+ }
+
+ return path;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void WinIOError() {
+ int errorCode = Marshal.GetLastWin32Error();
+ WinIOError(errorCode, String.Empty);
+ }
+
+ // After calling GetLastWin32Error(), it clears the last error field,
+ // so you must save the HResult and pass it to this method. This method
+ // will determine the appropriate exception to throw dependent on your
+ // error, and depending on the error, insert a string into the message
+ // gotten from the ResourceManager.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void WinIOError(int errorCode, String maybeFullPath) {
+ // This doesn't have to be perfect, but is a perf optimization.
+ bool isInvalidPath = errorCode == Win32Native.ERROR_INVALID_NAME || errorCode == Win32Native.ERROR_BAD_PATHNAME;
+ String str = GetDisplayablePath(maybeFullPath, isInvalidPath);
+
+ switch (errorCode) {
+ case Win32Native.ERROR_FILE_NOT_FOUND:
+ if (str.Length == 0)
+ throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound"));
+ else
+ throw new FileNotFoundException(Environment.GetResourceString("IO.FileNotFound_FileName", str), str);
+
+ case Win32Native.ERROR_PATH_NOT_FOUND:
+ if (str.Length == 0)
+ throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_NoPathName"));
+ else
+ throw new DirectoryNotFoundException(Environment.GetResourceString("IO.PathNotFound_Path", str));
+
+ case Win32Native.ERROR_ACCESS_DENIED:
+ if (str.Length == 0)
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_NoPathName"));
+ else
+ throw new UnauthorizedAccessException(Environment.GetResourceString("UnauthorizedAccess_IODenied_Path", str));
+
+ case Win32Native.ERROR_ALREADY_EXISTS:
+ if (str.Length == 0)
+ goto default;
+ throw new IOException(Environment.GetResourceString("IO.IO_AlreadyExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+
+ case Win32Native.ERROR_FILENAME_EXCED_RANGE:
+ throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong"));
+
+ case Win32Native.ERROR_INVALID_DRIVE:
+ throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", str));
+
+ case Win32Native.ERROR_INVALID_PARAMETER:
+ throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+
+ case Win32Native.ERROR_SHARING_VIOLATION:
+ if (str.Length == 0)
+ throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_NoFileName"), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+ else
+ throw new IOException(Environment.GetResourceString("IO.IO_SharingViolation_File", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+
+ case Win32Native.ERROR_FILE_EXISTS:
+ if (str.Length == 0)
+ goto default;
+ throw new IOException(Environment.GetResourceString("IO.IO_FileExists_Name", str), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+
+ case Win32Native.ERROR_OPERATION_ABORTED:
+ throw new OperationCanceledException();
+
+ default:
+ throw new IOException(Win32Native.GetMessage(errorCode), Win32Native.MakeHRFromErrorCode(errorCode), maybeFullPath);
+ }
+ }
+
+ // An alternative to WinIOError with friendlier messages for drives
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void WinIODriveError(String driveName) {
+ int errorCode = Marshal.GetLastWin32Error();
+ WinIODriveError(driveName, errorCode);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void WinIODriveError(String driveName, int errorCode)
+ {
+ switch (errorCode) {
+ case Win32Native.ERROR_PATH_NOT_FOUND:
+ case Win32Native.ERROR_INVALID_DRIVE:
+ throw new DriveNotFoundException(Environment.GetResourceString("IO.DriveNotFound_Drive", driveName));
+
+ default:
+ WinIOError(errorCode, driveName);
+ break;
+ }
+ }
+
+ internal static void WriteNotSupported() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnwritableStream"));
+ }
+
+ internal static void WriterClosed() {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_WriterClosed"));
+ }
+
+ // From WinError.h
+ internal const int ERROR_FILE_NOT_FOUND = Win32Native.ERROR_FILE_NOT_FOUND;
+ internal const int ERROR_PATH_NOT_FOUND = Win32Native.ERROR_PATH_NOT_FOUND;
+ internal const int ERROR_ACCESS_DENIED = Win32Native.ERROR_ACCESS_DENIED;
+ internal const int ERROR_INVALID_PARAMETER = Win32Native.ERROR_INVALID_PARAMETER;
+ }
+}
diff --git a/src/mscorlib/src/System/IO/__HResults.cs b/src/mscorlib/src/System/IO/__HResults.cs
new file mode 100644
index 0000000000..e19f28f833
--- /dev/null
+++ b/src/mscorlib/src/System/IO/__HResults.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//=============================================================================
+//
+//
+//
+//
+// Purpose: Define HResult constants. Every exception has one of these.
+//
+//
+//===========================================================================*/
+namespace System.IO {
+ using System;
+ // Only static data no need to serialize
+ internal static class __HResults
+ {
+ // These use an error code from WinError.h
+ public const int COR_E_ENDOFSTREAM = unchecked((int)0x80070026); // OS defined
+ public const int COR_E_FILELOAD = unchecked((int)0x80131621);
+ public const int COR_E_FILENOTFOUND = unchecked((int)0x80070002);
+ public const int COR_E_DIRECTORYNOTFOUND = unchecked((int)0x80070003);
+ public const int COR_E_PATHTOOLONG = unchecked((int)0x800700CE);
+
+ public const int COR_E_IO = unchecked((int)0x80131620);
+ }
+}
diff --git a/src/mscorlib/src/System/IObservable.cs b/src/mscorlib/src/System/IObservable.cs
new file mode 100644
index 0000000000..c231c45485
--- /dev/null
+++ b/src/mscorlib/src/System/IObservable.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Interface for exposing an Observable in the
+** Observer pattern
+**
+**
+===========================================================*/
+
+namespace System
+{
+ public interface IObservable<out T>
+ {
+ IDisposable Subscribe(IObserver<T> observer);
+ }
+
+}
diff --git a/src/mscorlib/src/System/IObserver.cs b/src/mscorlib/src/System/IObserver.cs
new file mode 100644
index 0000000000..7f55ce0c46
--- /dev/null
+++ b/src/mscorlib/src/System/IObserver.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Interface for exposing an Observer in the
+** Observer pattern
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System
+{
+ public interface IObserver<in T>
+ {
+ void OnNext(T value);
+ void OnError(Exception error);
+ void OnCompleted();
+ }
+}
diff --git a/src/mscorlib/src/System/IProgress.cs b/src/mscorlib/src/System/IProgress.cs
new file mode 100644
index 0000000000..e1043015ce
--- /dev/null
+++ b/src/mscorlib/src/System/IProgress.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Interface for providing progress updates.
+**
+**
+===========================================================*/
+
+namespace System
+{
+ /// <summary>Defines a provider for progress updates.</summary>
+ /// <typeparam name="T">The type of progress update value.</typeparam>
+ public interface IProgress<in T>
+ {
+ /// <summary>Reports a progress update.</summary>
+ /// <param name="value">The value of the updated progress.</param>
+ void Report(T value);
+ }
+}
diff --git a/src/mscorlib/src/System/IServiceObjectProvider.cs b/src/mscorlib/src/System/IServiceObjectProvider.cs
new file mode 100644
index 0000000000..feb1143487
--- /dev/null
+++ b/src/mscorlib/src/System/IServiceObjectProvider.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Runtime.InteropServices;
+
+
+ public interface IServiceProvider
+ {
+ // Interface does not need to be marked with the serializable attribute
+ Object GetService(Type serviceType);
+ }
+}
diff --git a/src/mscorlib/src/System/IndexOutOfRangeException.cs b/src/mscorlib/src/System/IndexOutOfRangeException.cs
new file mode 100644
index 0000000000..e641b5eab4
--- /dev/null
+++ b/src/mscorlib/src/System/IndexOutOfRangeException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for invalid array indices.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class IndexOutOfRangeException : SystemException {
+ public IndexOutOfRangeException()
+ : base(Environment.GetResourceString("Arg_IndexOutOfRangeException")) {
+ SetErrorCode(__HResults.COR_E_INDEXOUTOFRANGE);
+ }
+
+ public IndexOutOfRangeException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INDEXOUTOFRANGE);
+ }
+
+ public IndexOutOfRangeException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_INDEXOUTOFRANGE);
+ }
+
+ internal IndexOutOfRangeException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/InsufficientExecutionStackException.cs b/src/mscorlib/src/System/InsufficientExecutionStackException.cs
new file mode 100644
index 0000000000..6b02f46f29
--- /dev/null
+++ b/src/mscorlib/src/System/InsufficientExecutionStackException.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class used when there is insufficient execution stack
+** to allow most Framework methods to execute.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ public sealed class InsufficientExecutionStackException : SystemException
+ {
+ public InsufficientExecutionStackException()
+ : base(Environment.GetResourceString("Arg_InsufficientExecutionStackException"))
+ {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTEXECUTIONSTACK);
+ }
+
+ public InsufficientExecutionStackException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTEXECUTIONSTACK);
+ }
+
+ public InsufficientExecutionStackException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTEXECUTIONSTACK);
+ }
+
+ private InsufficientExecutionStackException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/InsufficientMemoryException.cs b/src/mscorlib/src/System/InsufficientMemoryException.cs
new file mode 100644
index 0000000000..448a061821
--- /dev/null
+++ b/src/mscorlib/src/System/InsufficientMemoryException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for running out of memory
+** but most likely in a non-fatal way that shouldn't
+** be affected by escalation policy. Use this for cases
+** like MemoryFailPoint or a TryAllocate method, where you
+** expect OOM's with no shared state corruption and you
+** want to recover from these errors.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ public sealed class InsufficientMemoryException : OutOfMemoryException
+ {
+ public InsufficientMemoryException()
+ : base(GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)) {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTMEMORY);
+ }
+
+ public InsufficientMemoryException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTMEMORY);
+ }
+
+ public InsufficientMemoryException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_INSUFFICIENTMEMORY);
+ }
+
+ private InsufficientMemoryException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Int16.cs b/src/mscorlib/src/System/Int16.cs
new file mode 100644
index 0000000000..0adc64cd13
--- /dev/null
+++ b/src/mscorlib/src/System/Int16.cs
@@ -0,0 +1,267 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a short and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ public struct Int16 : IComparable, IFormattable, IConvertible
+ , IComparable<Int16>, IEquatable<Int16>
+ {
+ internal short m_value;
+
+ public const short MaxValue = (short)0x7FFF;
+ public const short MinValue = unchecked((short)0x8000);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Int16, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+
+ if (value is Int16) {
+ return m_value - ((Int16)value).m_value;
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt16"));
+ }
+
+ public int CompareTo(Int16 value) {
+ return m_value - value;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is Int16)) {
+ return false;
+ }
+ return m_value == ((Int16)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Int16 obj)
+ {
+ return m_value == obj;
+ }
+
+ // Returns a HashCode for the Int16
+ public override int GetHashCode() {
+ return ((int)((ushort)m_value) | (((int)m_value) << 16));
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String ToString(String format, NumberFormatInfo info) {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ if (m_value<0 && format!=null && format.Length>0 && (format[0]=='X' || format[0]=='x')) {
+ uint temp = (uint)(m_value & 0x0000FFFF);
+ return Number.FormatUInt32(temp,format, info);
+ }
+ return Number.FormatInt32(m_value, format, info);
+ }
+
+ public static short Parse(String s) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static short Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static short Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static short Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static short Parse(String s, NumberStyles style, NumberFormatInfo info) {
+
+ int i = 0;
+ try {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch(OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int16"), e);
+ }
+
+ // We need this check here since we don't allow signs to specified in hex numbers. So we fixup the result
+ // for negative numbers
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // We are parsing a hexadecimal number
+ if ((i < 0) || (i > UInt16.MaxValue)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int16"));
+ }
+ return (short)i;
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Int16"));
+ return (short)i;
+ }
+
+ public static bool TryParse(String s, out Int16 result) {
+ return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int16 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out Int16 result) {
+
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i)) {
+ return false;
+ }
+
+ // We need this check here since we don't allow signs to specified in hex numbers. So we fixup the result
+ // for negative numbers
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // We are parsing a hexadecimal number
+ if ((i < 0) || i > UInt16.MaxValue) {
+ return false;
+ }
+ result = (Int16) i;
+ return true;
+ }
+
+ if (i < MinValue || i > MaxValue) {
+ return false;
+ }
+ result = (Int16) i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Int16;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Int16", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Int32.cs b/src/mscorlib/src/System/Int32.cs
new file mode 100644
index 0000000000..778a893672
--- /dev/null
+++ b/src/mscorlib/src/System/Int32.cs
@@ -0,0 +1,239 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A representation of a 32 bit 2's complement
+** integer.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct Int32 : IComparable, IFormattable, IConvertible
+ , IComparable<Int32>, IEquatable<Int32>
+ {
+ internal int m_value;
+
+ public const int MaxValue = 0x7fffffff;
+ public const int MinValue = unchecked((int)0x80000000);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Int32, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is Int32) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ int i = (int)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeInt32"));
+ }
+
+ public int CompareTo(int value) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is Int32)) {
+ return false;
+ }
+ return m_value == ((Int32)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Int32 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The absolute value of the int contained.
+ public override int GetHashCode() {
+ return m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [Pure]
+ public static int Parse(String s) {
+ return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [Pure]
+ public static int Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt32(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ // Parses an integer from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [Pure]
+ public static int Parse(String s, IFormatProvider provider) {
+ return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses an integer from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [Pure]
+ public static int Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt32(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses an integer from a String. Returns false rather
+ // than throwing exceptin if input is invalid
+ //
+ [Pure]
+ public static bool TryParse(String s, out Int32 result) {
+ return Number.TryParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ // Parses an integer from a String in the given style. Returns false rather
+ // than throwing exceptin if input is invalid
+ //
+ [Pure]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out Int32 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseInt32(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ [Pure]
+ public TypeCode GetTypeCode() {
+ return TypeCode.Int32;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Int32", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Int64.cs b/src/mscorlib/src/System/Int64.cs
new file mode 100644
index 0000000000..0cd2558997
--- /dev/null
+++ b/src/mscorlib/src/System/Int64.cs
@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate a long and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct Int64 : IComparable, IFormattable, IConvertible
+ , IComparable<Int64>, IEquatable<Int64>
+ {
+ internal long m_value;
+
+ public const long MaxValue = 0x7fffffffffffffffL;
+ public const long MinValue = unchecked((long)0x8000000000000000L);
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Int64, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is Int64) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ long i = (long)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeInt64"));
+ }
+
+ public int CompareTo(Int64 value) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is Int64)) {
+ return false;
+ }
+ return m_value == ((Int64)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(Int64 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The value of the lower 32 bits XORed with the uppper 32 bits.
+ public override int GetHashCode() {
+ return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt64(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static long Parse(String s) {
+ return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static long Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt64(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static long Parse(String s, IFormatProvider provider) {
+ return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ // Parses a long from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ public static long Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static Boolean TryParse(String s, out Int64 result) {
+ return Number.TryParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Int64 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseInt64(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Int64;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Int64", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/IntPtr.cs b/src/mscorlib/src/System/IntPtr.cs
new file mode 100644
index 0000000000..c7eea36447
--- /dev/null
+++ b/src/mscorlib/src/System/IntPtr.cs
@@ -0,0 +1,303 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Platform independent integer
+**
+**
+===========================================================*/
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct IntPtr : IEquatable<IntPtr>, ISerializable
+ {
+ [SecurityCritical]
+ unsafe private void* m_value; // The compiler treats void* closest to uint hence explicit casts are required to preserve int behavior
+
+ public static readonly IntPtr Zero;
+
+ // fast way to compare IntPtr to (IntPtr)0 while IntPtr.Zero doesn't work due to slow statics access
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe bool IsNull()
+ {
+ return (this.m_value == null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe IntPtr(int value)
+ {
+#if BIT64
+ m_value = (void *)(long)value;
+#else // !BIT64 (32)
+ m_value = (void *)value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe IntPtr(long value)
+ {
+#if BIT64
+ m_value = (void *)value;
+#else // !BIT64 (32)
+ m_value = (void *)checked((int)value);
+#endif
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe IntPtr(void* value)
+ {
+ m_value = value;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe IntPtr(SerializationInfo info, StreamingContext context) {
+ long l = info.GetInt64("value");
+
+ if (Size==4 && (l>Int32.MaxValue || l<Int32.MinValue)) {
+ throw new ArgumentException(Environment.GetResourceString("Serialization_InvalidPtrValue"));
+ }
+
+ m_value = (void *)l;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+#if BIT64
+ info.AddValue("value", (long)(m_value));
+#else // !BIT64 (32)
+ info.AddValue("value", (long)((int)m_value));
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override bool Equals(Object obj) {
+ if (obj is IntPtr) {
+ return (m_value == ((IntPtr)obj).m_value);
+ }
+ return false;
+ }
+
+ [SecuritySafeCritical]
+ unsafe bool IEquatable<IntPtr>.Equals(IntPtr other)
+ {
+ return m_value == other.m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override int GetHashCode() {
+#if FEATURE_CORECLR
+#if BIT64
+ long l = (long)m_value;
+ return (unchecked((int)l) ^ (int)(l >> 32));
+#else // !BIT64 (32)
+ return unchecked((int)m_value);
+#endif
+#else
+ return unchecked((int)((long)m_value));
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe int ToInt32() {
+#if BIT64
+ long l = (long)m_value;
+ return checked((int)l);
+#else // !BIT64 (32)
+ return (int)m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe long ToInt64() {
+#if BIT64
+ return (long)m_value;
+#else // !BIT64 (32)
+ return (long)(int)m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override String ToString() {
+#if BIT64
+ return ((long)m_value).ToString(CultureInfo.InvariantCulture);
+#else // !BIT64 (32)
+ return ((int)m_value).ToString(CultureInfo.InvariantCulture);
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe String ToString(String format)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+#if BIT64
+ return ((long)m_value).ToString(format, CultureInfo.InvariantCulture);
+#else // !BIT64 (32)
+ return ((int)m_value).ToString(format, CultureInfo.InvariantCulture);
+#endif
+ }
+
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static explicit operator IntPtr (int value)
+ {
+ return new IntPtr(value);
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static explicit operator IntPtr (long value)
+ {
+ return new IntPtr(value);
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false), ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static unsafe explicit operator IntPtr (void* value)
+ {
+ return new IntPtr(value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static unsafe explicit operator void* (IntPtr value)
+ {
+ return value.m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static explicit operator int (IntPtr value)
+ {
+#if BIT64
+ long l = (long)value.m_value;
+ return checked((int)l);
+#else // !BIT64 (32)
+ return (int)value.m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static explicit operator long (IntPtr value)
+ {
+#if BIT64
+ return (long)value.m_value;
+#else // !BIT64 (32)
+ return (long)(int)value.m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool operator == (IntPtr value1, IntPtr value2)
+ {
+ return value1.m_value == value2.m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool operator != (IntPtr value1, IntPtr value2)
+ {
+ return value1.m_value != value2.m_value;
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static IntPtr Add(IntPtr pointer, int offset)
+ {
+ return pointer + offset;
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static IntPtr operator +(IntPtr pointer, int offset)
+ {
+#if BIT64
+ return new IntPtr(pointer.ToInt64() + offset);
+#else // !BIT64 (32)
+ return new IntPtr(pointer.ToInt32() + offset);
+#endif
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static IntPtr Subtract(IntPtr pointer, int offset) {
+ return pointer - offset;
+ }
+
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static IntPtr operator -(IntPtr pointer, int offset) {
+#if BIT64
+ return new IntPtr(pointer.ToInt64() - offset);
+#else // !BIT64 (32)
+ return new IntPtr(pointer.ToInt32() - offset);
+#endif
+ }
+
+ public static int Size
+ {
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ get
+ {
+#if BIT64
+ return 8;
+#else // !BIT64 (32)
+ return 4;
+#endif
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe void* ToPointer()
+ {
+ return m_value;
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Internal.cs b/src/mscorlib/src/System/Internal.cs
new file mode 100644
index 0000000000..c6be49f83f
--- /dev/null
+++ b/src/mscorlib/src/System/Internal.cs
@@ -0,0 +1,377 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** This file exists to contain miscellaneous module-level attributes
+** and other miscellaneous stuff.
+**
+**
+**
+===========================================================*/
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Security;
+using System.StubHelpers;
+using System.Threading.Tasks;
+
+#if FEATURE_COMINTEROP
+
+using System.Runtime.InteropServices.WindowsRuntime;
+
+[assembly:Guid("BED7F4EA-1A96-11d2-8F08-00A0C9A6186D")]
+
+// The following attribute are required to ensure COM compatibility.
+[assembly:System.Runtime.InteropServices.ComCompatibleVersion(1, 0, 3300, 0)]
+[assembly:System.Runtime.InteropServices.TypeLibVersion(2, 4)]
+
+#endif // FEATURE_COMINTEROP
+
+[assembly:DefaultDependencyAttribute(LoadHint.Always)]
+// mscorlib would like to have its literal strings frozen if possible
+[assembly: System.Runtime.CompilerServices.StringFreezingAttribute()]
+
+namespace System
+{
+ static class Internal
+ {
+ // This method is purely an aid for NGen to statically deduce which
+ // instantiations to save in the ngen image.
+ // Otherwise, the JIT-compiler gets used, which is bad for working-set.
+ // Note that IBC can provide this information too.
+ // However, this helps in keeping the JIT-compiler out even for
+ // test scenarios which do not use IBC.
+ // This can be removed after V2, when we implement other schemes
+ // of keeping the JIT-compiler out for generic instantiations.
+
+ // Method marked as NoOptimization as we don't want the JIT to
+ // inline any methods or take any short-circuit paths since the
+ // instantiation closure process is driven by "fixup" references
+ // left in the final code stream.
+ [MethodImplAttribute(MethodImplOptions.NoOptimization)]
+ static void CommonlyUsedGenericInstantiations()
+ {
+ // Make absolutely sure we include some of the most common
+ // instantiations here in mscorlib's ngen image.
+ // Note that reference type instantiations are already included
+ // automatically for us.
+
+ // Need to sort non null, len > 1 array or paths will short-circuit
+ Array.Sort<double>(new double[1]);
+ Array.Sort<int>(new int[1]);
+ Array.Sort<IntPtr>(new IntPtr[1]);
+
+ new ArraySegment<byte>(new byte[1], 0, 0);
+
+ new Dictionary<Char, Object>();
+ new Dictionary<Guid, Byte>();
+ new Dictionary<Guid, Object>();
+ new Dictionary<Guid, Guid>(); // Added for Visual Studio 2010
+ new Dictionary<Int16, IntPtr>();
+ new Dictionary<Int32, Byte>();
+ new Dictionary<Int32, Int32>();
+ new Dictionary<Int32, Object>();
+ new Dictionary<IntPtr, Boolean>();
+ new Dictionary<IntPtr, Int16>();
+ new Dictionary<Object, Boolean>();
+ new Dictionary<Object, Char>();
+ new Dictionary<Object, Guid>();
+ new Dictionary<Object, Int32>();
+ new Dictionary<Object, Int64>(); // Added for Visual Studio 2010
+ new Dictionary<uint, WeakReference>(); // NCL team needs this
+ new Dictionary<Object, UInt32>();
+ new Dictionary<UInt32, Object>();
+ new Dictionary<Int64, Object>();
+#if FEATURE_CORECLR
+ // to genereate mdil for Dictionary instantiation when key is user defined value type
+ new Dictionary<Guid, Int32>();
+#endif
+
+ // Microsoft.Windows.Design
+ new Dictionary<System.Reflection.MemberTypes, Object>();
+ new EnumEqualityComparer<System.Reflection.MemberTypes>();
+
+ // Microsoft.Expression.DesignModel
+ new Dictionary<Object, KeyValuePair<Object,Object>>();
+ new Dictionary<KeyValuePair<Object,Object>, Object>();
+
+ NullableHelper<Boolean>();
+ NullableHelper<Byte>();
+ NullableHelper<Char>();
+ NullableHelper<DateTime>();
+ NullableHelper<Decimal>();
+ NullableHelper<Double>();
+ NullableHelper<Guid>();
+ NullableHelper<Int16>();
+ NullableHelper<Int32>();
+ NullableHelper<Int64>();
+ NullableHelper<Single>();
+ NullableHelper<TimeSpan>();
+ NullableHelper<DateTimeOffset>(); // For SQL
+
+ new List<Boolean>();
+ new List<Byte>();
+ new List<Char>();
+ new List<DateTime>();
+ new List<Decimal>();
+ new List<Double>();
+ new List<Guid>();
+ new List<Int16>();
+ new List<Int32>();
+ new List<Int64>();
+ new List<TimeSpan>();
+ new List<SByte>();
+ new List<Single>();
+ new List<UInt16>();
+ new List<UInt32>();
+ new List<UInt64>();
+ new List<IntPtr>();
+ new List<KeyValuePair<Object, Object>>();
+ new List<GCHandle>(); // NCL team needs this
+ new List<DateTimeOffset>();
+
+ new KeyValuePair<Char, UInt16>('\0', UInt16.MinValue);
+ new KeyValuePair<UInt16, Double>(UInt16.MinValue, Double.MinValue);
+ new KeyValuePair<Object, Int32>(String.Empty, Int32.MinValue);
+ new KeyValuePair<Int32, Int32>(Int32.MinValue, Int32.MinValue);
+ SZArrayHelper<Boolean>(null);
+ SZArrayHelper<Byte>(null);
+ SZArrayHelper<DateTime>(null);
+ SZArrayHelper<Decimal>(null);
+ SZArrayHelper<Double>(null);
+ SZArrayHelper<Guid>(null);
+ SZArrayHelper<Int16>(null);
+ SZArrayHelper<Int32>(null);
+ SZArrayHelper<Int64>(null);
+ SZArrayHelper<TimeSpan>(null);
+ SZArrayHelper<SByte>(null);
+ SZArrayHelper<Single>(null);
+ SZArrayHelper<UInt16>(null);
+ SZArrayHelper<UInt32>(null);
+ SZArrayHelper<UInt64>(null);
+ SZArrayHelper<DateTimeOffset>(null);
+
+ SZArrayHelper<CustomAttributeTypedArgument>(null);
+ SZArrayHelper<CustomAttributeNamedArgument>(null);
+
+#if FEATURE_CORECLR
+#pragma warning disable 4014
+ // This is necessary to generate MDIL for AsyncVoidMethodBuilder
+ AsyncHelper<int>();
+ AsyncHelper2<int>();
+ AsyncHelper3();
+#pragma warning restore 4014
+#endif
+ }
+
+ static T NullableHelper<T>() where T : struct
+ {
+ Nullable.Compare<T>(null, null);
+ Nullable.Equals<T>(null, null);
+ Nullable<T> nullable = new Nullable<T>();
+ return nullable.GetValueOrDefault();
+ }
+
+ static void SZArrayHelper<T>(SZArrayHelper oSZArrayHelper)
+ {
+ // Instantiate common methods for IList implementation on Array
+ oSZArrayHelper.get_Count<T>();
+ oSZArrayHelper.get_Item<T>(0);
+ oSZArrayHelper.GetEnumerator<T>();
+ }
+
+#if FEATURE_CORECLR
+ // System.Runtime.CompilerServices.AsyncVoidMethodBuilder
+ // System.Runtime.CompilerServices.TaskAwaiter
+ static async void AsyncHelper<T>()
+ {
+ await Task.Delay(1);
+ }
+ // System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[System.__Canon]
+ // System.Runtime.CompilerServices.TaskAwaiter'[System.__Canon]
+ static async Task<String> AsyncHelper2<T>()
+ {
+ return await Task.FromResult<string>("");
+ }
+
+ // System.Runtime.CompilerServices.AsyncTaskMethodBuilder
+ // System.Runtime.CompilerServices.AsyncTaskMethodBuilder'1[VoidTaskResult]
+ static async Task AsyncHelper3()
+ {
+ await Task.FromResult<string>("");
+ }
+#endif
+
+#if FEATURE_COMINTEROP
+
+ // Similar to CommonlyUsedGenericInstantiations but for instantiations of marshaling stubs used
+ // for WinRT redirected interfaces. Note that we do care about reference types here as well because,
+ // say, IList<string> and IList<object> cannot share marshaling stubs.
+ // The methods below "call" most commonly used stub methods on redirected interfaces and take arguments
+ // typed as matching instantiations of mscorlib copies of WinRT interfaces (IIterable<T>, IVector<T>,
+ // IMap<K, V>, ...) which is necessary to generate all required IL stubs.
+
+ [SecurityCritical]
+ static void CommonlyUsedWinRTRedirectedInterfaceStubs()
+ {
+ WinRT_IEnumerable<byte>(null, null, null);
+ WinRT_IEnumerable<char>(null, null, null);
+ WinRT_IEnumerable<short>(null, null, null);
+ WinRT_IEnumerable<ushort>(null, null, null);
+ WinRT_IEnumerable<int>(null, null, null);
+ WinRT_IEnumerable<uint>(null, null, null);
+ WinRT_IEnumerable<long>(null, null, null);
+ WinRT_IEnumerable<ulong>(null, null, null);
+ WinRT_IEnumerable<float>(null, null, null);
+ WinRT_IEnumerable<double>(null, null, null);
+
+ // The underlying WinRT types for shared instantiations have to be referenced explicitly.
+ // They are not guaranteeed to be created indirectly because of generic code sharing.
+ WinRT_IEnumerable<string>(null, null, null); typeof(IIterable<string>).ToString(); typeof(IIterator<string>).ToString();
+ WinRT_IEnumerable<object>(null, null, null); typeof(IIterable<object>).ToString(); typeof(IIterator<object>).ToString();
+
+ WinRT_IList<int>(null, null, null, null);
+ WinRT_IList<string>(null, null, null, null); typeof(IVector<string>).ToString();
+ WinRT_IList<object>(null, null, null, null); typeof(IVector<object>).ToString();
+
+ WinRT_IReadOnlyList<int>(null, null, null);
+ WinRT_IReadOnlyList<string>(null, null, null); typeof(IVectorView<string>).ToString();
+ WinRT_IReadOnlyList<object>(null, null, null); typeof(IVectorView<object>).ToString();
+
+ WinRT_IDictionary<string, int>(null, null, null, null); typeof(IMap<string, int>).ToString();
+ WinRT_IDictionary<string, string>(null, null, null, null); typeof(IMap<string, string>).ToString();
+ WinRT_IDictionary<string, object>(null, null, null, null); typeof(IMap<string, object>).ToString();
+ WinRT_IDictionary<object, object>(null, null, null, null); typeof(IMap<object, object>).ToString();
+
+ WinRT_IReadOnlyDictionary<string, int>(null, null, null, null); typeof(IMapView<string, int>).ToString();
+ WinRT_IReadOnlyDictionary<string, string>(null, null, null, null); typeof(IMapView<string, string>).ToString();
+ WinRT_IReadOnlyDictionary<string, object>(null, null, null, null); typeof(IMapView<string, object>).ToString();
+ WinRT_IReadOnlyDictionary<object, object>(null, null, null, null); typeof(IMapView<object, object>).ToString();
+
+ WinRT_Nullable<bool>();
+ WinRT_Nullable<byte>();
+ WinRT_Nullable<int>();
+ WinRT_Nullable<uint>();
+ WinRT_Nullable<long>();
+ WinRT_Nullable<ulong>();
+ WinRT_Nullable<float>();
+ WinRT_Nullable<double>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IEnumerable<T>(IterableToEnumerableAdapter iterableToEnumerableAdapter, EnumerableToIterableAdapter enumerableToIterableAdapter, IIterable<T> iterable)
+ {
+ // instantiate stubs for the one method on IEnumerable<T> and the one method on IIterable<T>
+ iterableToEnumerableAdapter.GetEnumerator_Stub<T>();
+ enumerableToIterableAdapter.First_Stub<T>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IList<T>(VectorToListAdapter vectorToListAdapter, VectorToCollectionAdapter vectorToCollectionAdapter, ListToVectorAdapter listToVectorAdapter, IVector<T> vector)
+ {
+ WinRT_IEnumerable<T>(null, null, null);
+
+ // instantiate stubs for commonly used methods on IList<T> and ICollection<T>
+ vectorToListAdapter.Indexer_Get<T>(0);
+ vectorToListAdapter.Indexer_Set<T>(0, default(T));
+ vectorToListAdapter.Insert<T>(0, default(T));
+ vectorToListAdapter.RemoveAt<T>(0);
+ vectorToCollectionAdapter.Count<T>();
+ vectorToCollectionAdapter.Add<T>(default(T));
+ vectorToCollectionAdapter.Clear<T>();
+
+ // instantiate stubs for commonly used methods on IVector<T>
+ listToVectorAdapter.GetAt<T>(0);
+ listToVectorAdapter.Size<T>();
+ listToVectorAdapter.SetAt<T>(0, default(T));
+ listToVectorAdapter.InsertAt<T>(0, default(T));
+ listToVectorAdapter.RemoveAt<T>(0);
+ listToVectorAdapter.Append<T>(default(T));
+ listToVectorAdapter.RemoveAtEnd<T>();
+ listToVectorAdapter.Clear<T>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IReadOnlyCollection<T>(VectorViewToReadOnlyCollectionAdapter vectorViewToReadOnlyCollectionAdapter)
+ {
+ WinRT_IEnumerable<T>(null, null, null);
+
+ // instantiate stubs for commonly used methods on IReadOnlyCollection<T>
+ vectorViewToReadOnlyCollectionAdapter.Count<T>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IReadOnlyList<T>(IVectorViewToIReadOnlyListAdapter vectorToListAdapter, IReadOnlyListToIVectorViewAdapter listToVectorAdapter, IVectorView<T> vectorView)
+ {
+ WinRT_IEnumerable<T>(null, null, null);
+ WinRT_IReadOnlyCollection<T>(null);
+
+ // instantiate stubs for commonly used methods on IReadOnlyList<T>
+ vectorToListAdapter.Indexer_Get<T>(0);
+
+ // instantiate stubs for commonly used methods on IVectorView<T>
+ listToVectorAdapter.GetAt<T>(0);
+ listToVectorAdapter.Size<T>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IDictionary<K, V>(MapToDictionaryAdapter mapToDictionaryAdapter, MapToCollectionAdapter mapToCollectionAdapter, DictionaryToMapAdapter dictionaryToMapAdapter, IMap<K, V> map)
+ {
+ WinRT_IEnumerable<KeyValuePair<K, V>>(null, null, null);
+
+ // instantiate stubs for commonly used methods on IDictionary<K, V> and ICollection<KeyValuePair<K, V>>
+ V dummy;
+ mapToDictionaryAdapter.Indexer_Get<K, V>(default(K));
+ mapToDictionaryAdapter.Indexer_Set<K, V>(default(K), default(V));
+ mapToDictionaryAdapter.ContainsKey<K, V>(default(K));
+ mapToDictionaryAdapter.Add<K, V>(default(K), default(V));
+ mapToDictionaryAdapter.Remove<K, V>(default(K));
+ mapToDictionaryAdapter.TryGetValue<K, V>(default(K), out dummy);
+ mapToCollectionAdapter.Count<K, V>();
+ mapToCollectionAdapter.Add<K, V>(new KeyValuePair<K, V>(default(K), default(V)));
+ mapToCollectionAdapter.Clear<K, V>();
+
+ // instantiate stubs for commonly used methods on IMap<K, V>
+ dictionaryToMapAdapter.Lookup<K, V>(default(K));
+ dictionaryToMapAdapter.Size<K, V>();
+ dictionaryToMapAdapter.HasKey<K, V>(default(K));
+ dictionaryToMapAdapter.Insert<K, V>(default(K), default(V));
+ dictionaryToMapAdapter.Remove<K, V>(default(K));
+ dictionaryToMapAdapter.Clear<K, V>();
+ }
+
+ [SecurityCritical]
+ static void WinRT_IReadOnlyDictionary<K, V>(IMapViewToIReadOnlyDictionaryAdapter mapToDictionaryAdapter, IReadOnlyDictionaryToIMapViewAdapter dictionaryToMapAdapter, IMapView<K, V> mapView, MapViewToReadOnlyCollectionAdapter mapViewToReadOnlyCollectionAdapter)
+ {
+ WinRT_IEnumerable<KeyValuePair<K, V>>(null, null, null);
+ WinRT_IReadOnlyCollection<KeyValuePair<K, V>>(null);
+
+ // instantiate stubs for commonly used methods on IReadOnlyDictionary<K, V>
+ V dummy;
+ mapToDictionaryAdapter.Indexer_Get<K, V>(default(K));
+ mapToDictionaryAdapter.ContainsKey<K, V>(default(K));
+ mapToDictionaryAdapter.TryGetValue<K, V>(default(K), out dummy);
+
+ // instantiate stubs for commonly used methods in IReadOnlyCollection<T>
+ mapViewToReadOnlyCollectionAdapter.Count<K, V>();
+
+ // instantiate stubs for commonly used methods on IMapView<K, V>
+ dictionaryToMapAdapter.Lookup<K, V>(default(K));
+ dictionaryToMapAdapter.Size<K, V>();
+ dictionaryToMapAdapter.HasKey<K, V>(default(K));
+ }
+
+ [SecurityCritical]
+ static void WinRT_Nullable<T>() where T : struct
+ {
+ Nullable<T> nullable = new Nullable<T>();
+ NullableMarshaler.ConvertToNative(ref nullable);
+ NullableMarshaler.ConvertToManagedRetVoid(IntPtr.Zero, ref nullable);
+ }
+
+#endif // FEATURE_COMINTEROP
+ }
+}
diff --git a/src/mscorlib/src/System/InvalidCastException.cs b/src/mscorlib/src/System/InvalidCastException.cs
new file mode 100644
index 0000000000..ba7b722434
--- /dev/null
+++ b/src/mscorlib/src/System/InvalidCastException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for bad cast conditions!
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class InvalidCastException : SystemException {
+ public InvalidCastException()
+ : base(Environment.GetResourceString("Arg_InvalidCastException")) {
+ SetErrorCode(__HResults.COR_E_INVALIDCAST);
+ }
+
+ public InvalidCastException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDCAST);
+ }
+
+ public InvalidCastException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_INVALIDCAST);
+ }
+
+ protected InvalidCastException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public InvalidCastException(String message, int errorCode)
+ : base(message) {
+ SetErrorCode(errorCode);
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/InvalidOperationException.cs b/src/mscorlib/src/System/InvalidOperationException.cs
new file mode 100644
index 0000000000..5f29e79056
--- /dev/null
+++ b/src/mscorlib/src/System/InvalidOperationException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for denoting an object was in a state that
+** made calling a method illegal.
+**
+**
+=============================================================================*/
+namespace System {
+
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class InvalidOperationException : SystemException
+ {
+ public InvalidOperationException()
+ : base(Environment.GetResourceString("Arg_InvalidOperationException")) {
+ SetErrorCode(__HResults.COR_E_INVALIDOPERATION);
+ }
+
+ public InvalidOperationException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDOPERATION);
+ }
+
+ public InvalidOperationException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_INVALIDOPERATION);
+ }
+
+ protected InvalidOperationException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/InvalidProgramException.cs b/src/mscorlib/src/System/InvalidProgramException.cs
new file mode 100644
index 0000000000..649849a8bd
--- /dev/null
+++ b/src/mscorlib/src/System/InvalidProgramException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for programs with invalid IL or bad metadata.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class InvalidProgramException : SystemException {
+ public InvalidProgramException()
+ : base(Environment.GetResourceString("InvalidProgram_Default")) {
+ SetErrorCode(__HResults.COR_E_INVALIDPROGRAM);
+ }
+
+ public InvalidProgramException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDPROGRAM);
+ }
+
+ public InvalidProgramException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_INVALIDPROGRAM);
+ }
+
+ internal InvalidProgramException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/InvalidTimeZoneException.cs b/src/mscorlib/src/System/InvalidTimeZoneException.cs
new file mode 100644
index 0000000000..2c57bc8341
--- /dev/null
+++ b/src/mscorlib/src/System/InvalidTimeZoneException.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+
+ [Serializable]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class InvalidTimeZoneException : Exception {
+ public InvalidTimeZoneException(String message)
+ : base(message) { }
+
+ public InvalidTimeZoneException(String message, Exception innerException)
+ : base(message, innerException) { }
+
+ protected InvalidTimeZoneException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+
+ public InvalidTimeZoneException() { }
+ }
+}
diff --git a/src/mscorlib/src/System/Lazy.cs b/src/mscorlib/src/System/Lazy.cs
new file mode 100644
index 0000000000..883979ef56
--- /dev/null
+++ b/src/mscorlib/src/System/Lazy.cs
@@ -0,0 +1,517 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// --------------------------------------------------------------------------------------
+//
+// A class that provides a simple, lightweight implementation of lazy initialization,
+// obviating the need for a developer to implement a custom, thread-safe lazy initialization
+// solution.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Runtime;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Diagnostics;
+using System.Runtime.Serialization;
+using System.Threading;
+using System.Diagnostics.Contracts;
+using System.Runtime.ExceptionServices;
+
+namespace System
+{
+ // Lazy<T> is generic, but not all of its state needs to be generic. Avoid creating duplicate
+ // objects per instantiation by putting them here.
+ internal static class LazyHelpers
+ {
+ // Dummy object used as the value of m_threadSafeObj if in PublicationOnly mode.
+ internal static readonly object PUBLICATION_ONLY_SENTINEL = new object();
+ }
+
+ /// <summary>
+ /// Provides support for lazy initialization.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of element being lazily initialized.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// By default, all public and protected members of <see cref="Lazy{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads. These thread-safety guarantees may be removed optionally and per instance
+ /// using parameters to the type's constructors.
+ /// </para>
+ /// </remarks>
+ [Serializable]
+ [ComVisible(false)]
+#if !FEATURE_CORECLR
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+#endif
+ [DebuggerTypeProxy(typeof(System_LazyDebugView<>))]
+ [DebuggerDisplay("ThreadSafetyMode={Mode}, IsValueCreated={IsValueCreated}, IsValueFaulted={IsValueFaulted}, Value={ValueForDebugDisplay}")]
+ public class Lazy<T>
+ {
+
+#region Inner classes
+ /// <summary>
+ /// wrapper class to box the initialized value, this is mainly created to avoid boxing/unboxing the value each time the value is called in case T is
+ /// a value type
+ /// </summary>
+ [Serializable]
+ class Boxed
+ {
+ internal Boxed(T value)
+ {
+ m_value = value;
+ }
+ internal T m_value;
+ }
+
+
+ /// <summary>
+ /// Wrapper class to wrap the excpetion thrown by the value factory
+ /// </summary>
+ class LazyInternalExceptionHolder
+ {
+ internal ExceptionDispatchInfo m_edi;
+ internal LazyInternalExceptionHolder(Exception ex)
+ {
+ m_edi = ExceptionDispatchInfo.Capture(ex);
+ }
+ }
+#endregion
+
+ // A dummy delegate used as a :
+ // 1- Flag to avoid recursive call to Value in None and ExecutionAndPublication modes in m_valueFactory
+ // 2- Flag to m_threadSafeObj if ExecutionAndPublication mode and the value is known to be initialized
+ static readonly Func<T> ALREADY_INVOKED_SENTINEL = delegate
+ {
+ Contract.Assert(false, "ALREADY_INVOKED_SENTINEL should never be invoked.");
+ return default(T);
+ };
+
+ //null --> value is not created
+ //m_value is Boxed --> the value is created, and m_value holds the value
+ //m_value is LazyExceptionHolder --> it holds an exception
+ private object m_boxed;
+
+ // The factory delegate that returns the value.
+ // In None and ExecutionAndPublication modes, this will be set to ALREADY_INVOKED_SENTINEL as a flag to avoid recursive calls
+ [NonSerialized]
+ private Func<T> m_valueFactory;
+
+ // null if it is not thread safe mode
+ // LazyHelpers.PUBLICATION_ONLY_SENTINEL if PublicationOnly mode
+ // object if ExecutionAndPublication mode (may be ALREADY_INVOKED_SENTINEL if the value is already initialized)
+ [NonSerialized]
+ private object m_threadSafeObj;
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that
+ /// uses <typeparamref name="T"/>'s default constructor for lazy initialization.
+ /// </summary>
+ /// <remarks>
+ /// An instance created with this constructor may be used concurrently from multiple threads.
+ /// </remarks>
+ public Lazy()
+ : this(LazyThreadSafetyMode.ExecutionAndPublication)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that
+ /// uses a pre-initialized specified value.
+ /// </summary>
+ /// <remarks>
+ /// An instance created with this constructor should be usable by multiple threads
+ // concurrently.
+ /// </remarks>
+ public Lazy(T value)
+ {
+ m_boxed = new Boxed(value);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class that uses a
+ /// specified initialization function.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce the lazily-initialized value when it is
+ /// needed.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException"><paramref name="valueFactory"/> is a null
+ /// reference (Nothing in Visual Basic).</exception>
+ /// <remarks>
+ /// An instance created with this constructor may be used concurrently from multiple threads.
+ /// </remarks>
+ public Lazy(Func<T> valueFactory)
+ : this(valueFactory, LazyThreadSafetyMode.ExecutionAndPublication)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/>
+ /// class that uses <typeparamref name="T"/>'s default constructor and a specified thread-safety mode.
+ /// </summary>
+ /// <param name="isThreadSafe">true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time.
+ /// </param>
+ public Lazy(bool isThreadSafe) :
+ this(isThreadSafe? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/>
+ /// class that uses <typeparamref name="T"/>'s default constructor and a specified thread-safety mode.
+ /// </summary>
+ /// <param name="mode">The lazy thread-safety mode mode</param>
+ /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="mode"/> mode contains an invalid valuee</exception>
+ public Lazy(LazyThreadSafetyMode mode)
+ {
+ m_threadSafeObj = GetObjectFromMode(mode);
+ }
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class
+ /// that uses a specified initialization function and a specified thread-safety mode.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce the lazily-initialized value when it is needed.
+ /// </param>
+ /// <param name="isThreadSafe">true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException"><paramref name="valueFactory"/> is
+ /// a null reference (Nothing in Visual Basic).</exception>
+ public Lazy(Func<T> valueFactory, bool isThreadSafe)
+ : this(valueFactory, isThreadSafe ? LazyThreadSafetyMode.ExecutionAndPublication : LazyThreadSafetyMode.None)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Lazy{T}"/> class
+ /// that uses a specified initialization function and a specified thread-safety mode.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce the lazily-initialized value when it is needed.
+ /// </param>
+ /// <param name="mode">The lazy thread-safety mode.</param>
+ /// <exception cref="System.ArgumentNullException"><paramref name="valueFactory"/> is
+ /// a null reference (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="mode"/> mode contains an invalid value.</exception>
+ public Lazy(Func<T> valueFactory, LazyThreadSafetyMode mode)
+ {
+ if (valueFactory == null)
+ throw new ArgumentNullException("valueFactory");
+
+ m_threadSafeObj = GetObjectFromMode(mode);
+ m_valueFactory = valueFactory;
+ }
+
+ /// <summary>
+ /// Static helper function that returns an object based on the given mode. it also throws an exception if the mode is invalid
+ /// </summary>
+ private static object GetObjectFromMode(LazyThreadSafetyMode mode)
+ {
+ if (mode == LazyThreadSafetyMode.ExecutionAndPublication)
+ return new object();
+ else if (mode == LazyThreadSafetyMode.PublicationOnly)
+ return LazyHelpers.PUBLICATION_ONLY_SENTINEL;
+ else if (mode != LazyThreadSafetyMode.None)
+ throw new ArgumentOutOfRangeException("mode", Environment.GetResourceString("Lazy_ctor_ModeInvalid"));
+
+ return null; // None mode
+ }
+
+ /// <summary>Forces initialization during serialization.</summary>
+ /// <param name="context">The StreamingContext for the serialization operation.</param>
+ [OnSerializing]
+ private void OnSerializing(StreamingContext context)
+ {
+ // Force initialization
+ T dummy = Value;
+ }
+
+ /// <summary>Creates and returns a string representation of this instance.</summary>
+ /// <returns>The result of calling <see cref="System.Object.ToString"/> on the <see
+ /// cref="Value"/>.</returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <see cref="Value"/> is null.
+ /// </exception>
+ public override string ToString()
+ {
+ return IsValueCreated ? Value.ToString() : Environment.GetResourceString("Lazy_ToString_ValueNotCreated");
+ }
+
+ /// <summary>Gets the value of the Lazy&lt;T&gt; for debugging display purposes.</summary>
+ internal T ValueForDebugDisplay
+ {
+ get
+ {
+ if (!IsValueCreated)
+ {
+ return default(T);
+ }
+ return ((Boxed)m_boxed).m_value;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether this instance may be used concurrently from multiple threads.
+ /// </summary>
+ internal LazyThreadSafetyMode Mode
+ {
+ get
+ {
+ if (m_threadSafeObj == null) return LazyThreadSafetyMode.None;
+ if (m_threadSafeObj == (object)LazyHelpers.PUBLICATION_ONLY_SENTINEL) return LazyThreadSafetyMode.PublicationOnly;
+ return LazyThreadSafetyMode.ExecutionAndPublication;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the value creation is faulted or not
+ /// </summary>
+ internal bool IsValueFaulted
+ {
+ get { return m_boxed is LazyInternalExceptionHolder; }
+ }
+
+ /// <summary>Gets a value indicating whether the <see cref="T:System.Lazy{T}"/> has been initialized.
+ /// </summary>
+ /// <value>true if the <see cref="T:System.Lazy{T}"/> instance has been initialized;
+ /// otherwise, false.</value>
+ /// <remarks>
+ /// The initialization of a <see cref="T:System.Lazy{T}"/> instance may result in either
+ /// a value being produced or an exception being thrown. If an exception goes unhandled during initialization,
+ /// <see cref="IsValueCreated"/> will return false.
+ /// </remarks>
+ public bool IsValueCreated
+ {
+ get
+ {
+ return m_boxed != null && m_boxed is Boxed;
+ }
+ }
+
+ /// <summary>Gets the lazily initialized value of the current <see
+ /// cref="T:System.Threading.Lazy{T}"/>.</summary>
+ /// <value>The lazily initialized value of the current <see
+ /// cref="T:System.Threading.Lazy{T}"/>.</value>
+ /// <exception cref="T:System.MissingMemberException">
+ /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
+ /// of the type being lazily initialized, and that type does not have a public, parameterless constructor.
+ /// </exception>
+ /// <exception cref="T:System.MemberAccessException">
+ /// The <see cref="T:System.Threading.Lazy{T}"/> was initialized to use the default constructor
+ /// of the type being lazily initialized, and permissions to access the constructor were missing.
+ /// </exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The <see cref="T:System.Threading.Lazy{T}"/> was constructed with the <see cref="T:System.Threading.LazyThreadSafetyMode.ExecutionAndPublication"/> or
+ /// <see cref="T:System.Threading.LazyThreadSafetyMode.None"/> and the initialization function attempted to access <see cref="Value"/> on this instance.
+ /// </exception>
+ /// <remarks>
+ /// If <see cref="IsValueCreated"/> is false, accessing <see cref="Value"/> will force initialization.
+ /// Please <see cref="System.Threading.LazyThreadSafetyMode"> for more information on how <see cref="T:System.Threading.Lazy{T}"/> will behave if an exception is thrown
+ /// from initialization delegate.
+ /// </remarks>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ public T Value
+ {
+ get
+ {
+ Boxed boxed = null;
+ if (m_boxed != null )
+ {
+ // Do a quick check up front for the fast path.
+ boxed = m_boxed as Boxed;
+ if (boxed != null)
+ {
+ return boxed.m_value;
+ }
+
+ LazyInternalExceptionHolder exc = m_boxed as LazyInternalExceptionHolder;
+ Contract.Assert(exc != null);
+ exc.m_edi.Throw();
+ }
+
+ // Fall through to the slow path.
+#if !FEATURE_CORECLR
+ // We call NOCTD to abort attempts by the debugger to funceval this property (e.g. on mouseover)
+ // (the debugger proxy is the correct way to look at state/value of this object)
+ Debugger.NotifyOfCrossThreadDependency();
+#endif
+ return LazyInitValue();
+
+ }
+ }
+
+ /// <summary>
+ /// local helper method to initialize the value
+ /// </summary>
+ /// <returns>The inititialized T value</returns>
+ private T LazyInitValue()
+ {
+ Boxed boxed = null;
+ LazyThreadSafetyMode mode = Mode;
+ if (mode == LazyThreadSafetyMode.None)
+ {
+ boxed = CreateValue();
+ m_boxed = boxed;
+ }
+ else if (mode == LazyThreadSafetyMode.PublicationOnly)
+ {
+ boxed = CreateValue();
+ if (boxed == null ||
+ Interlocked.CompareExchange(ref m_boxed, boxed, null) != null)
+ {
+ // If CreateValue returns null, it means another thread successfully invoked the value factory
+ // and stored the result, so we should just take what was stored. If CreateValue returns non-null
+ // but another thread set the value we should just take what was stored.
+ boxed = (Boxed)m_boxed;
+ }
+ else
+ {
+ // We successfully created and stored the value. At this point, the value factory delegate is
+ // no longer needed, and we don't want to hold onto its resources.
+ m_valueFactory = ALREADY_INVOKED_SENTINEL;
+ }
+ }
+ else
+ {
+ object threadSafeObj = Volatile.Read(ref m_threadSafeObj);
+ bool lockTaken = false;
+ try
+ {
+ if (threadSafeObj != (object)ALREADY_INVOKED_SENTINEL)
+ Monitor.Enter(threadSafeObj, ref lockTaken);
+ else
+ Contract.Assert(m_boxed != null);
+
+ if (m_boxed == null)
+ {
+ boxed = CreateValue();
+ m_boxed = boxed;
+ Volatile.Write(ref m_threadSafeObj, ALREADY_INVOKED_SENTINEL);
+ }
+ else // got the lock but the value is not null anymore, check if it is created by another thread or faulted and throw if so
+ {
+ boxed = m_boxed as Boxed;
+ if (boxed == null) // it is not Boxed, so it is a LazyInternalExceptionHolder
+ {
+ LazyInternalExceptionHolder exHolder = m_boxed as LazyInternalExceptionHolder;
+ Contract.Assert(exHolder != null);
+ exHolder.m_edi.Throw();
+ }
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ Monitor.Exit(threadSafeObj);
+ }
+ }
+ Contract.Assert(boxed != null);
+ return boxed.m_value;
+ }
+
+ /// <summary>Creates an instance of T using m_valueFactory in case its not null or use reflection to create a new T()</summary>
+ /// <returns>An instance of Boxed.</returns>
+ private Boxed CreateValue()
+ {
+ Boxed boxed = null;
+ LazyThreadSafetyMode mode = Mode;
+ if (m_valueFactory != null)
+ {
+ try
+ {
+ // check for recursion
+ if (mode != LazyThreadSafetyMode.PublicationOnly && m_valueFactory == ALREADY_INVOKED_SENTINEL)
+ throw new InvalidOperationException(Environment.GetResourceString("Lazy_Value_RecursiveCallsToValue"));
+
+ Func<T> factory = m_valueFactory;
+ if (mode != LazyThreadSafetyMode.PublicationOnly) // only detect recursion on None and ExecutionAndPublication modes
+ {
+ m_valueFactory = ALREADY_INVOKED_SENTINEL;
+ }
+ else if (factory == ALREADY_INVOKED_SENTINEL)
+ {
+ // Another thread raced to successfully invoke the factory.
+ return null;
+ }
+ boxed = new Boxed(factory());
+ }
+ catch (Exception ex)
+ {
+ if (mode != LazyThreadSafetyMode.PublicationOnly) // don't cache the exception for PublicationOnly mode
+ m_boxed = new LazyInternalExceptionHolder(ex);
+ throw;
+ }
+ }
+ else
+ {
+ try
+ {
+ boxed = new Boxed((T)Activator.CreateInstance(typeof(T)));
+
+ }
+ catch (System.MissingMethodException)
+ {
+ Exception ex = new System.MissingMemberException(Environment.GetResourceString("Lazy_CreateValue_NoParameterlessCtorForT"));
+ if (mode != LazyThreadSafetyMode.PublicationOnly) // don't cache the exception for PublicationOnly mode
+ m_boxed = new LazyInternalExceptionHolder(ex);
+ throw ex;
+ }
+ }
+
+ return boxed;
+ }
+
+ }
+
+ /// <summary>A debugger view of the Lazy&lt;T&gt; to surface additional debugging properties and
+ /// to ensure that the Lazy&lt;T&gt; does not become initialized if it was not already.</summary>
+ internal sealed class System_LazyDebugView<T>
+ {
+ //The Lazy object being viewed.
+ private readonly Lazy<T> m_lazy;
+
+ /// <summary>Constructs a new debugger view object for the provided Lazy object.</summary>
+ /// <param name="lazy">A Lazy object to browse in the debugger.</param>
+ public System_LazyDebugView(Lazy<T> lazy)
+ {
+ m_lazy = lazy;
+ }
+
+ /// <summary>Returns whether the Lazy object is initialized or not.</summary>
+ public bool IsValueCreated
+ {
+ get { return m_lazy.IsValueCreated; }
+ }
+
+ /// <summary>Returns the value of the Lazy object.</summary>
+ public T Value
+ {
+ get
+ { return m_lazy.ValueForDebugDisplay; }
+ }
+
+ /// <summary>Returns the execution mode of the Lazy object</summary>
+ public LazyThreadSafetyMode Mode
+ {
+ get { return m_lazy.Mode; }
+ }
+
+ /// <summary>Returns the execution mode of the Lazy object</summary>
+ public bool IsValueFaulted
+ {
+ get { return m_lazy.IsValueFaulted; }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/LowLevelConsole.cs b/src/mscorlib/src/System/LowLevelConsole.cs
new file mode 100644
index 0000000000..3aba3db4d1
--- /dev/null
+++ b/src/mscorlib/src/System/LowLevelConsole.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Text;
+using System.Security;
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+
+namespace System
+{
+ //
+ // Simple limited console class for internal printf-style debugging in mscorlib
+ // and low-level tests that just want to depend on mscorlib.
+ //
+
+ public static class Console
+ {
+ [SecurityCritical]
+ static SafeFileHandle _outputHandle;
+
+ [SecuritySafeCritical]
+ static Console()
+ {
+ _outputHandle = new SafeFileHandle(Win32Native.GetStdHandle(Win32Native.STD_OUTPUT_HANDLE), false);
+ }
+
+ [SecuritySafeCritical]
+ public static unsafe void Write(string s)
+ {
+ byte[] bytes = Encoding.UTF8.GetBytes(s);
+
+ fixed (byte * pBytes = bytes)
+ {
+ int bytesWritten;
+ Win32Native.WriteFile(_outputHandle, pBytes, bytes.Length, out bytesWritten, IntPtr.Zero);
+ }
+ }
+
+ public static void WriteLine(string s)
+ {
+ Write(s + Environment.NewLine);
+ }
+
+ public static void WriteLine()
+ {
+ Write(Environment.NewLine);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/MarshalByRefObject.cs b/src/mscorlib/src/System/MarshalByRefObject.cs
new file mode 100644
index 0000000000..4948a4316d
--- /dev/null
+++ b/src/mscorlib/src/System/MarshalByRefObject.cs
@@ -0,0 +1,262 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: Defines the root type for all marshal by reference aka
+** AppDomain bound types
+**
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Lifetime;
+ using System.Runtime.Remoting.Services;
+#endif
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class MarshalByRefObject
+ {
+#if FEATURE_REMOTING
+ private Object __identity;
+
+ private Object Identity { get { return __identity; } set { __identity = value; } }
+#if FEATURE_COMINTEROP
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal IntPtr GetComIUnknown(bool fIsBeingMarshalled)
+ {
+ IntPtr pUnk;
+ if(RemotingServices.IsTransparentProxy(this))
+ {
+ pUnk = RemotingServices.GetRealProxy(this).GetCOMIUnknown(fIsBeingMarshalled);
+ }
+ else
+ {
+ pUnk = Marshal.GetIUnknownForObject(this);
+ }
+ return pUnk;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr GetComIUnknown(MarshalByRefObject o);
+#endif // FEATURE_COMINTEROP
+
+ // (1) for remote COM objects IsInstance of can't be executed on
+ // the proxies, so we need this method to be executed on the
+ // actual object.
+ // (2) for remote objects that do not have the complete type information
+ // we intercept calls to check the type and execute it on the actual
+ // object
+ internal bool IsInstanceOfType(Type T)
+ {
+ return T.IsInstanceOfType(this);
+ }
+
+ // for remote COM Objects the late binding methods can't be
+ // executed on proxies, so we need this method to execute on
+ // the real object
+ internal Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder,
+ Object[] args,ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters)
+ {
+ Type t = GetType();
+
+ // Sanity check
+ if(!t.IsCOMObject)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_InvokeMember"));
+
+ // Call into the runtime to invoke on the COM object.
+ return t.InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters);
+ }
+
+ // Returns a new cloned MBR instance that is a memberwise copy of this
+ // with the identity nulled out, so there are no identity conflicts
+ // when the cloned object is marshalled
+ protected MarshalByRefObject MemberwiseClone(bool cloneIdentity)
+ {
+ MarshalByRefObject mbr = (MarshalByRefObject)base.MemberwiseClone();
+ // set the identity on the cloned object to null
+ if (!cloneIdentity)
+ mbr.Identity = null;
+ return mbr;
+ }
+
+
+
+ // A helper routine to extract the identity either from the marshalbyrefobject base
+ // class if it is not a proxy, otherwise from the real proxy.
+ // A flag is set to indicate whether the object passed in is a server or a proxy
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Identity GetIdentity(MarshalByRefObject obj, out bool fServer)
+ {
+ fServer = true;
+ Identity id = null;
+
+ if(null != obj)
+ {
+ if(!RemotingServices.IsTransparentProxy(obj))
+ {
+ id = (Identity)obj.Identity;
+ }
+ else
+ {
+ // Toggle flag to indicate that we have a proxy
+ fServer = false;
+ id = RemotingServices.GetRealProxy(obj).IdentityObject;
+ }
+ }
+
+ return id;
+ }
+
+ // Another helper that delegates to the helper above
+ internal static Identity GetIdentity(MarshalByRefObject obj)
+ {
+ Contract.Assert(!RemotingServices.IsTransparentProxy(obj), "Use this method for server objects only");
+
+ bool fServer;
+ return GetIdentity(obj, out fServer);
+ }
+
+
+ internal ServerIdentity __RaceSetServerIdentity(ServerIdentity id)
+ {
+ if (__identity == null)
+ {
+ // For strictly MBR types, the TP field in the identity
+ // holds the real server
+ if (!id.IsContextBound)
+ {
+ id.RaceSetTransparentProxy(this);
+ }
+ Interlocked.CompareExchange(ref __identity, id, null);
+ }
+ return (ServerIdentity)__identity;
+ }
+
+
+ internal void __ResetServerIdentity()
+ {
+ __identity = null;
+ }
+
+ // This method is used return a lifetime service object which
+ // is used to control the lifetime policy to the object.
+ // For the default Lifetime service this will be an object of typoe ILease.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public Object GetLifetimeService()
+ {
+ return LifetimeServices.GetLease(this);
+ }
+
+ // This method is used return lifetime service object. This method
+ // can be overridden to return a LifetimeService object with properties unique to
+ // this object.
+ // For the default Lifetime service this will be an object of type ILease.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual Object InitializeLifetimeService()
+ {
+ return LifetimeServices.GetLeaseInitial(this);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual ObjRef CreateObjRef(Type requestedType)
+ {
+ if(__identity == null)
+ {
+ throw new RemotingException(Environment.GetResourceString(
+ "Remoting_NoIdentityEntry"));
+ }
+ return new ObjRef(this, requestedType);
+ }
+
+ // This is for casting interop ObjRefLite's.
+ // ObjRefLite's have been deprecated. These methods are not exposed
+ // through any user APIs and would be removed in the future
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool CanCastToXmlType(String xmlTypeName, String xmlTypeNamespace)
+ {
+ Type castType = SoapServices.GetInteropTypeFromXmlType(xmlTypeName, xmlTypeNamespace);
+ if (castType == null)
+ {
+ String typeNamespace;
+ String assemblyName;
+ if (!SoapServices.DecodeXmlNamespaceForClrTypeNamespace(xmlTypeNamespace,
+ out typeNamespace, out assemblyName))
+ return false;
+
+ String typeName;
+ if ((typeNamespace != null) && (typeNamespace.Length > 0))
+ typeName = typeNamespace + "." + xmlTypeName;
+ else
+ typeName = xmlTypeName;
+
+ try
+ {
+ Assembly asm = Assembly.Load(assemblyName);
+ castType = asm.GetType(typeName, false, false);
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ if (castType != null)
+ return castType.IsAssignableFrom(this.GetType());
+
+ return false;
+ } // CanCastToXmlType
+
+ // helper method for calling CanCastToXmlType
+ // ObjRefLite's have been deprecated. These methods are not exposed
+ // through any user APIs and would be removed in the future
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool CanCastToXmlTypeHelper(RuntimeType castType, MarshalByRefObject o)
+ {
+ if (castType == null)
+ throw new ArgumentNullException("castType");
+
+ Contract.EndContractBlock();
+ // MarshalByRefObject's can only be casted to MarshalByRefObject's or interfaces.
+ if (!castType.IsInterface && !castType.IsMarshalByRef)
+ return false;
+
+ // figure out xml type name
+ String xmlTypeName = null;
+ String xmlTypeNamespace = null;
+ if (!SoapServices.GetXmlTypeForInteropType(castType, out xmlTypeName, out xmlTypeNamespace))
+ {
+ // There's no registered interop type name, so just use the default.
+ xmlTypeName = castType.Name;
+ xmlTypeNamespace =
+ SoapServices.CodeXmlNamespaceForClrTypeNamespace(
+ castType.Namespace, castType.GetRuntimeAssembly().GetSimpleName());
+ }
+
+ return o.CanCastToXmlType(xmlTypeName, xmlTypeNamespace);
+ } // CanCastToXmlType
+
+#endif // FEATURE_REMOTING
+ }
+} // namespace
diff --git a/src/mscorlib/src/System/Math.cs b/src/mscorlib/src/System/Math.cs
new file mode 100644
index 0000000000..4e280d5fd9
--- /dev/null
+++ b/src/mscorlib/src/System/Math.cs
@@ -0,0 +1,594 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Some floating-point math operations
+**
+**
+===========================================================*/
+namespace System {
+
+ //This class contains only static members and doesn't require serialization.
+ using System;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ public static class Math {
+
+ private static double doubleRoundLimit = 1e16d;
+
+ private const int maxRoundingDigits = 15;
+
+ // This table is required for the Round function which can specify the number of digits to round to
+ private static double[] roundPower10Double = new double[] {
+ 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,
+ 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15
+ };
+
+ public const double PI = 3.14159265358979323846;
+ public const double E = 2.7182818284590452354;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Acos(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Asin(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Atan(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Atan2(double y,double x);
+
+ public static Decimal Ceiling(Decimal d) {
+ return Decimal.Ceiling(d);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Ceiling(double a);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Cos (double d);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Cosh(double value);
+
+ public static Decimal Floor(Decimal d) {
+ return Decimal.Floor(d);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Floor(double d);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) {
+ if (Abs(value) < doubleRoundLimit) {
+ Double power10 = roundPower10Double[digits];
+ value *= power10;
+ if (mode == MidpointRounding.AwayFromZero) {
+ double fraction = SplitFractionDouble(&value);
+ if (Abs(fraction) >= 0.5d) {
+ value += Sign(fraction);
+ }
+ }
+ else {
+ // On X86 this can be inlined to just a few instructions
+ value = Round(value);
+ }
+ value /= power10;
+ }
+ return value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static double InternalTruncate(double d) {
+ SplitFractionDouble(&d);
+ return d;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Sin(double a);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Tan(double a);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Sinh(double value);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Tanh(double value);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Round(double a);
+
+ public static double Round(double value, int digits)
+ {
+ if ((digits < 0) || (digits > maxRoundingDigits))
+ throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
+ Contract.EndContractBlock();
+ return InternalRound(value, digits, MidpointRounding.ToEven);
+ }
+
+ public static double Round(double value, MidpointRounding mode) {
+ return Round(value, 0, mode);
+ }
+
+ public static double Round(double value, int digits, MidpointRounding mode) {
+ if ((digits < 0) || (digits > maxRoundingDigits))
+ throw new ArgumentOutOfRangeException("digits", Environment.GetResourceString("ArgumentOutOfRange_RoundingDigits"));
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, "MidpointRounding"), "mode");
+ }
+ Contract.EndContractBlock();
+ return InternalRound(value, digits, mode);
+ }
+
+ public static Decimal Round(Decimal d) {
+ return Decimal.Round(d,0);
+ }
+
+ public static Decimal Round(Decimal d, int decimals) {
+ return Decimal.Round(d,decimals);
+ }
+
+ public static Decimal Round(Decimal d, MidpointRounding mode) {
+ return Decimal.Round(d, 0, mode);
+ }
+
+ public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) {
+ return Decimal.Round(d, decimals, mode);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern double SplitFractionDouble(double* value);
+
+ public static Decimal Truncate(Decimal d) {
+ return Decimal.Truncate(d);
+ }
+
+ public static double Truncate(double d) {
+ return InternalTruncate(d);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Sqrt(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Log (double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Log10(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Exp(double d);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern double Pow(double x, double y);
+
+ public static double IEEERemainder(double x, double y) {
+ if (Double.IsNaN(x)) {
+ return x; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if (Double.IsNaN(y)) {
+ return y; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ double regularMod = x % y;
+ if (Double.IsNaN(regularMod)) {
+ return Double.NaN;
+ }
+ if (regularMod == 0) {
+ if (Double.IsNegative(x)) {
+ return Double.NegativeZero;
+ }
+ }
+ double alternativeResult;
+ alternativeResult = regularMod - (Math.Abs(y) * Math.Sign(x));
+ if (Math.Abs(alternativeResult) == Math.Abs(regularMod)) {
+ double divisionResult = x/y;
+ double roundedResult = Math.Round(divisionResult);
+ if (Math.Abs(roundedResult) > Math.Abs(divisionResult)) {
+ return alternativeResult;
+ }
+ else {
+ return regularMod;
+ }
+ }
+ if (Math.Abs(alternativeResult) < Math.Abs(regularMod)) {
+ return alternativeResult;
+ }
+ else {
+ return regularMod;
+ }
+ }
+
+ /*================================Abs=========================================
+ **Returns the absolute value of it's argument.
+ ============================================================================*/
+ [CLSCompliant(false)]
+ public static sbyte Abs(sbyte value) {
+ if (value >= 0)
+ return value;
+ else
+ return AbsHelper(value);
+ }
+
+ private static sbyte AbsHelper(sbyte value)
+ {
+ Contract.Requires(value < 0, "AbsHelper should only be called for negative values! (workaround for JIT inlining)");
+ if (value == SByte.MinValue)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ Contract.EndContractBlock();
+ return ((sbyte)(-value));
+ }
+
+ public static short Abs(short value) {
+ if (value >= 0)
+ return value;
+ else
+ return AbsHelper(value);
+ }
+
+ private static short AbsHelper(short value) {
+ Contract.Requires(value < 0, "AbsHelper should only be called for negative values! (workaround for JIT inlining)");
+ if (value == Int16.MinValue)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ Contract.EndContractBlock();
+ return (short) -value;
+ }
+
+ public static int Abs(int value) {
+ if (value >= 0)
+ return value;
+ else
+ return AbsHelper(value);
+ }
+
+ private static int AbsHelper(int value) {
+ Contract.Requires(value < 0, "AbsHelper should only be called for negative values! (workaround for JIT inlining)");
+ if (value == Int32.MinValue)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ Contract.EndContractBlock();
+ return -value;
+ }
+
+ public static long Abs(long value) {
+ if (value >= 0)
+ return value;
+ else
+ return AbsHelper(value);
+ }
+
+ private static long AbsHelper(long value) {
+ Contract.Requires(value < 0, "AbsHelper should only be called for negative values! (workaround for JIT inlining)");
+ if (value == Int64.MinValue)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ Contract.EndContractBlock();
+ return -value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern public static float Abs(float value);
+ // This is special code to handle NaN (We need to make sure NaN's aren't
+ // negated). In CSharp, the else clause here should always be taken if
+ // value is NaN, since the normal case is taken if and only if value < 0.
+ // To illustrate this completely, a compiler has translated this into:
+ // "load value; load 0; bge; ret -value ; ret value".
+ // The bge command branches for comparisons with the unordered NaN. So
+ // it runs the else case, which returns +value instead of negating it.
+ // return (value < 0) ? -value : value;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern public static double Abs(double value);
+ // This is special code to handle NaN (We need to make sure NaN's aren't
+ // negated). In CSharp, the else clause here should always be taken if
+ // value is NaN, since the normal case is taken if and only if value < 0.
+ // To illustrate this completely, a compiler has translated this into:
+ // "load value; load 0; bge; ret -value ; ret value".
+ // The bge command branches for comparisons with the unordered NaN. So
+ // it runs the else case, which returns +value instead of negating it.
+ // return (value < 0) ? -value : value;
+
+ public static Decimal Abs(Decimal value)
+ {
+ return Decimal.Abs(value);
+ }
+
+ /*================================MAX=========================================
+ **Returns the larger of val1 and val2
+ ============================================================================*/
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static sbyte Max(sbyte val1, sbyte val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static byte Max(byte val1, byte val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static short Max(short val1, short val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static ushort Max(ushort val1, ushort val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static int Max(int val1, int val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static uint Max(uint val1, uint val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static long Max(long val1, long val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static ulong Max(ulong val1, ulong val2) {
+ return (val1>=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static float Max(float val1, float val2) {
+ if (val1 > val2)
+ return val1;
+
+ if (Single.IsNaN(val1))
+ return val1;
+
+ return val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static double Max(double val1, double val2) {
+ if (val1 > val2)
+ return val1;
+
+ if (Double.IsNaN(val1))
+ return val1;
+
+ return val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static Decimal Max(Decimal val1, Decimal val2) {
+ return Decimal.Max(val1,val2);
+ }
+
+ /*================================MIN=========================================
+ **Returns the smaller of val1 and val2.
+ ============================================================================*/
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static sbyte Min(sbyte val1, sbyte val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static byte Min(byte val1, byte val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static short Min(short val1, short val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static ushort Min(ushort val1, ushort val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static int Min(int val1, int val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static uint Min(uint val1, uint val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static long Min(long val1, long val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static ulong Min(ulong val1, ulong val2) {
+ return (val1<=val2)?val1:val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static float Min(float val1, float val2) {
+ if (val1 < val2)
+ return val1;
+
+ if (Single.IsNaN(val1))
+ return val1;
+
+ return val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static double Min(double val1, double val2) {
+ if (val1 < val2)
+ return val1;
+
+ if (Double.IsNaN(val1))
+ return val1;
+
+ return val2;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static Decimal Min(Decimal val1, Decimal val2) {
+ return Decimal.Min(val1,val2);
+ }
+
+ /*=====================================Log======================================
+ **
+ ==============================================================================*/
+ public static double Log(double a, double newBase) {
+ if (Double.IsNaN(a)) {
+ return a; // IEEE 754-2008: NaN payload must be preserved
+ }
+ if (Double.IsNaN(newBase)) {
+ return newBase; // IEEE 754-2008: NaN payload must be preserved
+ }
+
+ if (newBase == 1)
+ return Double.NaN;
+ if (a != 1 && (newBase == 0 || Double.IsPositiveInfinity(newBase)))
+ return Double.NaN;
+
+ return (Log(a)/Log(newBase));
+ }
+
+
+ // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
+ // is negative, 0, or positive. Throws for floating point NaN's.
+ [CLSCompliant(false)]
+ public static int Sign(sbyte value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else
+ return 0;
+ }
+
+
+ // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
+ // is negative, 0, or positive. Throws for floating point NaN's.
+ public static int Sign(short value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ // Sign function for VB. Returns -1, 0, or 1 if the sign of the number
+ // is negative, 0, or positive. Throws for floating point NaN's.
+ public static int Sign(int value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ public static int Sign(long value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ public static int Sign (float value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else if (value == 0)
+ return 0;
+ throw new ArithmeticException(Environment.GetResourceString("Arithmetic_NaN"));
+ }
+
+ public static int Sign(double value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else if (value == 0)
+ return 0;
+ throw new ArithmeticException(Environment.GetResourceString("Arithmetic_NaN"));
+ }
+
+ public static int Sign(Decimal value)
+ {
+ if (value < 0)
+ return -1;
+ else if (value > 0)
+ return 1;
+ else
+ return 0;
+ }
+
+ public static long BigMul(int a, int b) {
+ return ((long)a) * b;
+ }
+
+ public static int DivRem(int a, int b, out int result) {
+ result = a%b;
+ return a/b;
+ }
+
+ public static long DivRem(long a, long b, out long result) {
+ result = a%b;
+ return a/b;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/MemberAccessException.cs b/src/mscorlib/src/System/MemberAccessException.cs
new file mode 100644
index 0000000000..bc21248dae
--- /dev/null
+++ b/src/mscorlib/src/System/MemberAccessException.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+// MemberAccessException
+// Thrown when we try accessing a member that we cannot
+// access, due to it being removed, private or something similar.
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ // The MemberAccessException is thrown when trying to access a class
+ // member fails.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MemberAccessException : SystemException {
+
+ // Creates a new MemberAccessException with its message string set to
+ // the empty string, its HRESULT set to COR_E_MEMBERACCESS,
+ // and its ExceptionInfo reference set to null.
+ public MemberAccessException()
+ : base(Environment.GetResourceString("Arg_AccessException")) {
+ SetErrorCode(__HResults.COR_E_MEMBERACCESS);
+ }
+
+ // Creates a new MemberAccessException with its message string set to
+ // message, its HRESULT set to COR_E_ACCESS,
+ // and its ExceptionInfo reference set to null.
+ //
+ public MemberAccessException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MEMBERACCESS);
+ }
+
+ public MemberAccessException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MEMBERACCESS);
+ }
+
+ protected MemberAccessException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/MethodAccessException.cs b/src/mscorlib/src/System/MethodAccessException.cs
new file mode 100644
index 0000000000..3feaf3ed54
--- /dev/null
+++ b/src/mscorlib/src/System/MethodAccessException.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: The exception class for class loading failures.
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MethodAccessException : MemberAccessException {
+ public MethodAccessException()
+ : base(Environment.GetResourceString("Arg_MethodAccessException")) {
+ SetErrorCode(__HResults.COR_E_METHODACCESS);
+ }
+
+ public MethodAccessException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_METHODACCESS);
+ }
+
+ public MethodAccessException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_METHODACCESS);
+ }
+
+ protected MethodAccessException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/MidpointRounding.cs b/src/mscorlib/src/System/MidpointRounding.cs
new file mode 100644
index 0000000000..ff709240c5
--- /dev/null
+++ b/src/mscorlib/src/System/MidpointRounding.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System {
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum MidpointRounding {
+ ToEven = 0,
+ AwayFromZero = 1,
+ }
+}
diff --git a/src/mscorlib/src/System/MissingFieldException.cs b/src/mscorlib/src/System/MissingFieldException.cs
new file mode 100644
index 0000000000..4196ea8f6b
--- /dev/null
+++ b/src/mscorlib/src/System/MissingFieldException.cs
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: The exception class for class loading failures.
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MissingFieldException : MissingMemberException, ISerializable {
+ public MissingFieldException()
+ : base(Environment.GetResourceString("Arg_MissingFieldException")) {
+ SetErrorCode(__HResults.COR_E_MISSINGFIELD);
+ }
+
+ public MissingFieldException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MISSINGFIELD);
+ }
+
+ public MissingFieldException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MISSINGFIELD);
+ }
+
+ protected MissingFieldException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public override String Message
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (ClassName == null) {
+ return base.Message;
+ } else {
+ // do any desired fixups to classname here.
+ return Environment.GetResourceString("MissingField_Name",
+ (Signature != null ? FormatSignature(Signature) + " " : "") +
+ ClassName + "." + MemberName);
+ }
+ }
+ }
+
+ // Called from the EE
+ private MissingFieldException(String className, String fieldName, byte[] signature)
+ {
+ ClassName = className;
+ MemberName = fieldName;
+ Signature = signature;
+ }
+
+ public MissingFieldException(String className, String fieldName)
+ {
+ ClassName = className;
+ MemberName = fieldName;
+ }
+
+ // If ClassName != null, Message will construct on the fly using it
+ // and the other variables. This allows customization of the
+ // format depending on the language environment.
+ }
+}
diff --git a/src/mscorlib/src/System/MissingMemberException.cs b/src/mscorlib/src/System/MissingMemberException.cs
new file mode 100644
index 0000000000..30ce5b8fd0
--- /dev/null
+++ b/src/mscorlib/src/System/MissingMemberException.cs
@@ -0,0 +1,105 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for versioning problems with DLLS.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Security.Permissions;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MissingMemberException : MemberAccessException, ISerializable {
+ public MissingMemberException()
+ : base(Environment.GetResourceString("Arg_MissingMemberException")) {
+ SetErrorCode(__HResults.COR_E_MISSINGMEMBER);
+ }
+
+ public MissingMemberException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MISSINGMEMBER);
+ }
+
+ public MissingMemberException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MISSINGMEMBER);
+ }
+
+ protected MissingMemberException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ ClassName = (String)info.GetString("MMClassName");
+ MemberName = (String)info.GetString("MMMemberName");
+ Signature = (byte[])info.GetValue("MMSignature", typeof(byte[]));
+ }
+
+ public override String Message
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (ClassName == null) {
+ return base.Message;
+ } else {
+ // do any desired fixups to classname here.
+ return Environment.GetResourceString("MissingMember_Name",
+ ClassName + "." + MemberName +
+ (Signature != null ? " " + FormatSignature(Signature) : ""));
+ }
+ }
+ }
+
+ // Called to format signature
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String FormatSignature(byte [] signature);
+
+
+
+ // Potentially called from the EE
+ private MissingMemberException(String className, String memberName, byte[] signature)
+ {
+ ClassName = className;
+ MemberName = memberName;
+ Signature = signature;
+ }
+
+ public MissingMemberException(String className, String memberName)
+ {
+ ClassName = className;
+ MemberName = memberName;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("MMClassName", ClassName, typeof(String));
+ info.AddValue("MMMemberName", MemberName, typeof(String));
+ info.AddValue("MMSignature", Signature, typeof(byte[]));
+ }
+
+
+ // If ClassName != null, GetMessage will construct on the fly using it
+ // and the other variables. This allows customization of the
+ // format depending on the language environment.
+ protected String ClassName;
+ protected String MemberName;
+ protected byte[] Signature;
+ }
+}
diff --git a/src/mscorlib/src/System/MissingMethodException.cs b/src/mscorlib/src/System/MissingMethodException.cs
new file mode 100644
index 0000000000..cba33efa0f
--- /dev/null
+++ b/src/mscorlib/src/System/MissingMethodException.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for class loading failures.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MissingMethodException : MissingMemberException, ISerializable {
+ public MissingMethodException()
+ : base(Environment.GetResourceString("Arg_MissingMethodException")) {
+ SetErrorCode(__HResults.COR_E_MISSINGMETHOD);
+ }
+
+ public MissingMethodException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MISSINGMETHOD);
+ }
+
+ public MissingMethodException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MISSINGMETHOD);
+ }
+
+ protected MissingMethodException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public override String Message
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (ClassName == null) {
+ return base.Message;
+ } else {
+ // do any desired fixups to classname here.
+ return Environment.GetResourceString("MissingMethod_Name",
+ ClassName + "." + MemberName +
+ (Signature != null ? " " + FormatSignature(Signature) : ""));
+ }
+ }
+ }
+
+ // Called from the EE
+ private MissingMethodException(String className, String methodName, byte[] signature)
+ {
+ ClassName = className;
+ MemberName = methodName;
+ Signature = signature;
+ }
+
+ public MissingMethodException(String className, String methodName)
+ {
+ ClassName = className;
+ MemberName = methodName;
+ }
+
+ // If ClassName != null, Message will construct on the fly using it
+ // and the other variables. This allows customization of the
+ // format depending on the language environment.
+ }
+}
diff --git a/src/mscorlib/src/System/MulticastDelegate.cs b/src/mscorlib/src/System/MulticastDelegate.cs
new file mode 100644
index 0000000000..f59db16850
--- /dev/null
+++ b/src/mscorlib/src/System/MulticastDelegate.cs
@@ -0,0 +1,754 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System
+{
+ using System;
+ using System.Reflection;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+ using System.Reflection.Emit;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class MulticastDelegate : Delegate
+ {
+ // This is set under 3 circumstances
+ // 1. Multicast delegate
+ // 2. Secure/Wrapper delegate
+ // 3. Inner delegate of secure delegate where the secure delegate security context is a collectible method
+ [System.Security.SecurityCritical]
+ private Object _invocationList;
+ [System.Security.SecurityCritical]
+ private IntPtr _invocationCount;
+
+ // This constructor is called from the class generated by the
+ // compiler generated code (This must match the constructor
+ // in Delegate
+ protected MulticastDelegate(Object target, String method) : base(target, method)
+ {
+ }
+
+ // This constructor is called from a class to generate a
+ // delegate based upon a static method name and the Type object
+ // for the class defining the method.
+ protected MulticastDelegate(Type target, String method) : base(target, method)
+ {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal bool IsUnmanagedFunctionPtr()
+ {
+ return (_invocationCount == (IntPtr)(-1));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal bool InvocationListLogicallyNull()
+ {
+ return (_invocationList == null) || (_invocationList is LoaderAllocator) || (_invocationList is DynamicResolver);
+ }
+
+ [System.Security.SecurityCritical]
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ int targetIndex = 0;
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList == null)
+ {
+ MethodInfo method = Method;
+ // A MethodInfo object can be a RuntimeMethodInfo, a RefEmit method (MethodBuilder, etc), or a DynamicMethod
+ // One can only create delegates on RuntimeMethodInfo and DynamicMethod.
+ // If it is not a RuntimeMethodInfo (must be a DynamicMethod) or if it is an unmanaged function pointer, throw
+ if ( !(method is RuntimeMethodInfo) || IsUnmanagedFunctionPtr() )
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
+
+ // We can't deal with secure delegates either.
+ if (!InvocationListLogicallyNull() && !_invocationCount.IsNull() && !_methodPtrAux.IsNull())
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
+
+ DelegateSerializationHolder.GetDelegateSerializationInfo(info, this.GetType(), Target, method, targetIndex);
+ }
+ else
+ {
+ DelegateSerializationHolder.DelegateEntry nextDe = null;
+ int invocationCount = (int)_invocationCount;
+ for (int i = invocationCount; --i >= 0; )
+ {
+ MulticastDelegate d = (MulticastDelegate)invocationList[i];
+ MethodInfo method = d.Method;
+ // If it is not a RuntimeMethodInfo (must be a DynamicMethod) or if it is an unmanaged function pointer, skip
+ if ( !(method is RuntimeMethodInfo) || IsUnmanagedFunctionPtr() )
+ continue;
+
+ // We can't deal with secure delegates either.
+ if (!d.InvocationListLogicallyNull() && !d._invocationCount.IsNull() && !d._methodPtrAux.IsNull())
+ continue;
+
+ DelegateSerializationHolder.DelegateEntry de = DelegateSerializationHolder.GetDelegateSerializationInfo(info, d.GetType(), d.Target, method, targetIndex++);
+ if (nextDe != null)
+ nextDe.Entry = de;
+
+ nextDe = de;
+ }
+ // if nothing was serialized it is a delegate over a DynamicMethod, so just throw
+ if (nextDe == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidDelegateType"));
+ }
+ }
+
+ // equals returns true IIF the delegate is not null and has the
+ // same target, method and invocation list as this object
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override sealed bool Equals(Object obj)
+ {
+ if (obj == null)
+ return false;
+ if (object.ReferenceEquals(this, obj))
+ return true;
+ if (!InternalEqualTypes(this, obj))
+ return false;
+
+ // Since this is a MulticastDelegate and we know
+ // the types are the same, obj should also be a
+ // MulticastDelegate
+ Contract.Assert(obj is MulticastDelegate, "Shouldn't have failed here since we already checked the types are the same!");
+ var d = JitHelpers.UnsafeCast<MulticastDelegate>(obj);
+
+ if (_invocationCount != (IntPtr)0)
+ {
+ // there are 4 kind of delegate kinds that fall into this bucket
+ // 1- Multicast (_invocationList is Object[])
+ // 2- Secure/Wrapper (_invocationList is Delegate)
+ // 3- Unmanaged FntPtr (_invocationList == null)
+ // 4- Open virtual (_invocationCount == MethodDesc of target, _invocationList == null, LoaderAllocator, or DynamicResolver)
+
+ if (InvocationListLogicallyNull())
+ {
+ if (IsUnmanagedFunctionPtr())
+ {
+ if (!d.IsUnmanagedFunctionPtr())
+ return false;
+
+ return CompareUnmanagedFunctionPtrs(this, d);
+ }
+
+ // now we know 'this' is not a special one, so we can work out what the other is
+ if ((d._invocationList as Delegate) != null)
+ // this is a secure/wrapper delegate so we need to unwrap and check the inner one
+ return Equals(d._invocationList);
+
+ return base.Equals(obj);
+ }
+ else
+ {
+ if ((_invocationList as Delegate) != null)
+ {
+ // this is a secure/wrapper delegate so we need to unwrap and check the inner one
+ return _invocationList.Equals(obj);
+ }
+ else
+ {
+ Contract.Assert((_invocationList as Object[]) != null, "empty invocation list on multicast delegate");
+ return InvocationListEquals(d);
+ }
+ }
+ }
+ else
+ {
+ // among the several kind of delegates falling into this bucket one has got a non
+ // empty _invocationList (open static with special sig)
+ // to be equals we need to check that _invocationList matches (both null is fine)
+ // and call the base.Equals()
+ if (!InvocationListLogicallyNull())
+ {
+ if (!_invocationList.Equals(d._invocationList))
+ return false;
+ return base.Equals(d);
+ }
+
+ // now we know 'this' is not a special one, so we can work out what the other is
+ if ((d._invocationList as Delegate) != null)
+ // this is a secure/wrapper delegate so we need to unwrap and check the inner one
+ return Equals(d._invocationList);
+
+ // now we can call on the base
+ return base.Equals(d);
+ }
+ }
+
+ // Recursive function which will check for equality of the invocation list.
+ [System.Security.SecuritySafeCritical]
+ private bool InvocationListEquals(MulticastDelegate d)
+ {
+ Contract.Assert(d != null && (_invocationList as Object[]) != null, "bogus delegate in multicast list comparison");
+ Object[] invocationList = _invocationList as Object[];
+ if (d._invocationCount != _invocationCount)
+ return false;
+
+ int invocationCount = (int)_invocationCount;
+ for (int i = 0; i < invocationCount; i++)
+ {
+ Delegate dd = (Delegate)invocationList[i];
+ Object[] dInvocationList = d._invocationList as Object[];
+ if (!dd.Equals(dInvocationList[i]))
+ return false;
+ }
+ return true;
+ }
+
+ [System.Security.SecurityCritical]
+ private bool TrySetSlot(Object[] a, int index, Object o)
+ {
+ if (a[index] == null && System.Threading.Interlocked.CompareExchange<Object>(ref a[index], o, null) == null)
+ return true;
+
+ // The slot may be already set because we have added and removed the same method before.
+ // Optimize this case, because it's cheaper than copying the array.
+ if (a[index] != null)
+ {
+ MulticastDelegate d = (MulticastDelegate)o;
+ MulticastDelegate dd = (MulticastDelegate)a[index];
+
+ if (dd._methodPtr == d._methodPtr &&
+ dd._target == d._target &&
+ dd._methodPtrAux == d._methodPtrAux)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ [System.Security.SecurityCritical]
+ private MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount, bool thisIsMultiCastAlready)
+ {
+ // First, allocate a new multicast delegate just like this one, i.e. same type as the this object
+ MulticastDelegate result = (MulticastDelegate)InternalAllocLike(this);
+
+ // Performance optimization - if this already points to a true multicast delegate,
+ // copy _methodPtr and _methodPtrAux fields rather than calling into the EE to get them
+ if (thisIsMultiCastAlready)
+ {
+ result._methodPtr = this._methodPtr;
+ result._methodPtrAux = this._methodPtrAux;
+ }
+ else
+ {
+ result._methodPtr = GetMulticastInvoke();
+ result._methodPtrAux = GetInvokeMethod();
+ }
+ result._target = result;
+ result._invocationList = invocationList;
+ result._invocationCount = (IntPtr)invocationCount;
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical]
+ internal MulticastDelegate NewMulticastDelegate(Object[] invocationList, int invocationCount)
+ {
+ return NewMulticastDelegate(invocationList, invocationCount, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal void StoreDynamicMethod(MethodInfo dynamicMethod)
+ {
+ if (_invocationCount != (IntPtr)0)
+ {
+ Contract.Assert(!IsUnmanagedFunctionPtr(), "dynamic method and unmanaged fntptr delegate combined");
+ // must be a secure/wrapper one, unwrap and save
+ MulticastDelegate d = (MulticastDelegate)_invocationList;
+ d._methodBase = dynamicMethod;
+
+ }
+ else
+ _methodBase = dynamicMethod;
+ }
+
+ // This method will combine this delegate with the passed delegate
+ // to form a new delegate.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override sealed Delegate CombineImpl(Delegate follow)
+ {
+ if ((Object)follow == null) // cast to object for a more efficient test
+ return this;
+
+ // Verify that the types are the same...
+ if (!InternalEqualTypes(this, follow))
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTypeMis"));
+
+ MulticastDelegate dFollow = (MulticastDelegate)follow;
+ Object[] resultList;
+ int followCount = 1;
+ Object[] followList = dFollow._invocationList as Object[];
+ if (followList != null)
+ followCount = (int)dFollow._invocationCount;
+
+ int resultCount;
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList == null)
+ {
+ resultCount = 1 + followCount;
+ resultList = new Object[resultCount];
+ resultList[0] = this;
+ if (followList == null)
+ {
+ resultList[1] = dFollow;
+ }
+ else
+ {
+ for (int i = 0; i < followCount; i++)
+ resultList[1 + i] = followList[i];
+ }
+ return NewMulticastDelegate(resultList, resultCount);
+ }
+ else
+ {
+ int invocationCount = (int)_invocationCount;
+ resultCount = invocationCount + followCount;
+ resultList = null;
+ if (resultCount <= invocationList.Length)
+ {
+ resultList = invocationList;
+ if (followList == null)
+ {
+ if (!TrySetSlot(resultList, invocationCount, dFollow))
+ resultList = null;
+ }
+ else
+ {
+ for (int i = 0; i < followCount; i++)
+ {
+ if (!TrySetSlot(resultList, invocationCount + i, followList[i]))
+ {
+ resultList = null;
+ break;
+ }
+ }
+ }
+ }
+
+ if (resultList == null)
+ {
+ int allocCount = invocationList.Length;
+ while (allocCount < resultCount)
+ allocCount *= 2;
+
+ resultList = new Object[allocCount];
+
+ for (int i = 0; i < invocationCount; i++)
+ resultList[i] = invocationList[i];
+
+ if (followList == null)
+ {
+ resultList[invocationCount] = dFollow;
+ }
+ else
+ {
+ for (int i = 0; i < followCount; i++)
+ resultList[invocationCount + i] = followList[i];
+ }
+ }
+ return NewMulticastDelegate(resultList, resultCount, true);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private Object[] DeleteFromInvocationList(Object[] invocationList, int invocationCount, int deleteIndex, int deleteCount)
+ {
+ Object[] thisInvocationList = _invocationList as Object[];
+ int allocCount = thisInvocationList.Length;
+ while (allocCount/2 >= invocationCount - deleteCount)
+ allocCount /= 2;
+
+ Object[] newInvocationList = new Object[allocCount];
+
+ for (int i = 0; i < deleteIndex; i++)
+ newInvocationList[i] = invocationList[i];
+
+ for (int i = deleteIndex + deleteCount; i < invocationCount; i++)
+ newInvocationList[i - deleteCount] = invocationList[i];
+
+ return newInvocationList;
+ }
+
+ private bool EqualInvocationLists(Object[] a, Object[] b, int start, int count)
+ {
+ for (int i = 0; i < count; i++)
+ {
+ if (!(a[start + i].Equals(b[i])))
+ return false;
+ }
+ return true;
+ }
+
+ // This method currently looks backward on the invocation list
+ // for an element that has Delegate based equality with value. (Doesn't
+ // look at the invocation list.) If this is found we remove it from
+ // this list and return a new delegate. If its not found a copy of the
+ // current list is returned.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override sealed Delegate RemoveImpl(Delegate value)
+ {
+ // There is a special case were we are removing using a delegate as
+ // the value we need to check for this case
+ //
+ MulticastDelegate v = value as MulticastDelegate;
+
+ if (v == null)
+ return this;
+ if (v._invocationList as Object[] == null)
+ {
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList == null)
+ {
+ // they are both not real Multicast
+ if (this.Equals(value))
+ return null;
+ }
+ else
+ {
+ int invocationCount = (int)_invocationCount;
+ for (int i = invocationCount; --i >= 0; )
+ {
+ if (value.Equals(invocationList[i]))
+ {
+ if (invocationCount == 2)
+ {
+ // Special case - only one value left, either at the beginning or the end
+ return (Delegate)invocationList[1-i];
+ }
+ else
+ {
+ Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, 1);
+ return NewMulticastDelegate(list, invocationCount-1, true);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList != null) {
+ int invocationCount = (int)_invocationCount;
+ int vInvocationCount = (int)v._invocationCount;
+ for (int i = invocationCount - vInvocationCount; i >= 0; i--)
+ {
+ if (EqualInvocationLists(invocationList, v._invocationList as Object[], i, vInvocationCount))
+ {
+ if (invocationCount - vInvocationCount == 0)
+ {
+ // Special case - no values left
+ return null;
+ }
+ else if (invocationCount - vInvocationCount == 1)
+ {
+ // Special case - only one value left, either at the beginning or the end
+ return (Delegate)invocationList[i != 0 ? 0 : invocationCount-1];
+ }
+ else
+ {
+ Object[] list = DeleteFromInvocationList(invocationList, invocationCount, i, vInvocationCount);
+ return NewMulticastDelegate(list, invocationCount - vInvocationCount, true);
+ }
+ }
+ }
+ }
+ }
+
+ return this;
+ }
+
+ // This method returns the Invocation list of this multicast delegate.
+ [System.Security.SecuritySafeCritical]
+ public override sealed Delegate[] GetInvocationList()
+ {
+ Contract.Ensures(Contract.Result<Delegate[]>() != null);
+
+ Delegate[] del;
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList == null)
+ {
+ del = new Delegate[1];
+ del[0] = this;
+ }
+ else
+ {
+ // Create an array of delegate copies and each
+ // element into the array
+ int invocationCount = (int)_invocationCount;
+ del = new Delegate[invocationCount];
+
+ for (int i = 0; i < invocationCount; i++)
+ del[i] = (Delegate)invocationList[i];
+ }
+ return del;
+ }
+
+ public static bool operator ==(MulticastDelegate d1, MulticastDelegate d2)
+ {
+ if ((Object)d1 == null)
+ return (Object)d2 == null;
+
+ return d1.Equals(d2);
+ }
+
+ public static bool operator !=(MulticastDelegate d1, MulticastDelegate d2)
+ {
+ if ((Object)d1 == null)
+ return (Object)d2 != null;
+
+ return !d1.Equals(d2);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override sealed int GetHashCode()
+ {
+ if (IsUnmanagedFunctionPtr())
+ return ValueType.GetHashCodeOfPtr(_methodPtr) ^ ValueType.GetHashCodeOfPtr(_methodPtrAux);
+
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList == null)
+ {
+ return base.GetHashCode();
+ }
+ else
+ {
+ int hash = 0;
+ for (int i = 0; i < (int)_invocationCount; i++)
+ {
+ hash = hash*33 + invocationList[i].GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal override Object GetTarget()
+ {
+ if (_invocationCount != (IntPtr)0)
+ {
+ // _invocationCount != 0 we are in one of these cases:
+ // - Multicast -> return the target of the last delegate in the list
+ // - Secure/wrapper delegate -> return the target of the inner delegate
+ // - unmanaged function pointer - return null
+ // - virtual open delegate - return null
+ if (InvocationListLogicallyNull())
+ {
+ // both open virtual and ftn pointer return null for the target
+ return null;
+ }
+ else
+ {
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList != null)
+ {
+ int invocationCount = (int)_invocationCount;
+ return ((Delegate)invocationList[invocationCount - 1]).GetTarget();
+ }
+ else
+ {
+ Delegate receiver = _invocationList as Delegate;
+ if (receiver != null)
+ return receiver.GetTarget();
+ }
+ }
+ }
+ return base.GetTarget();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ protected override MethodInfo GetMethodImpl()
+ {
+ if (_invocationCount != (IntPtr)0 && _invocationList != null)
+ {
+ // multicast case
+ Object[] invocationList = _invocationList as Object[];
+ if (invocationList != null)
+ {
+ int index = (int)_invocationCount - 1;
+ return ((Delegate)invocationList[index]).Method;
+ }
+ MulticastDelegate innerDelegate = _invocationList as MulticastDelegate;
+ if (innerDelegate != null)
+ {
+ // must be a secure/wrapper delegate
+ return innerDelegate.GetMethodImpl();
+ }
+ }
+ else if (IsUnmanagedFunctionPtr())
+ {
+ // we handle unmanaged function pointers here because the generic ones (used for WinRT) would otherwise
+ // be treated as open delegates by the base implementation, resulting in failure to get the MethodInfo
+ if ((_methodBase == null) || !(_methodBase is MethodInfo))
+ {
+ IRuntimeMethodInfo method = FindMethodHandle();
+ RuntimeType declaringType = RuntimeMethodHandle.GetDeclaringType(method);
+
+ // need a proper declaring type instance method on a generic type
+ if (RuntimeTypeHandle.IsGenericTypeDefinition(declaringType) || RuntimeTypeHandle.HasInstantiation(declaringType))
+ {
+ // we are returning the 'Invoke' method of this delegate so use this.GetType() for the exact type
+ RuntimeType reflectedType = GetType() as RuntimeType;
+ declaringType = reflectedType;
+ }
+ _methodBase = (MethodInfo)RuntimeType.GetMethodBase(declaringType, method);
+ }
+ return (MethodInfo)_methodBase;
+ }
+
+ // Otherwise, must be an inner delegate of a SecureDelegate of an open virtual method. In that case, call base implementation
+ return base.GetMethodImpl();
+ }
+
+ // this should help inlining
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void ThrowNullThisInDelegateToInstance()
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtNullInst"));
+ }
+
+ [System.Security.SecurityCritical]
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorClosed(Object target, IntPtr methodPtr)
+ {
+ if (target == null)
+ ThrowNullThisInDelegateToInstance();
+ this._target = target;
+ this._methodPtr = methodPtr;
+ }
+
+ [System.Security.SecurityCritical]
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorClosedStatic(Object target, IntPtr methodPtr)
+ {
+ this._target = target;
+ this._methodPtr = methodPtr;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorRTClosed(Object target, IntPtr methodPtr)
+ {
+ this._target = target;
+ this._methodPtr = AdjustTarget(target, methodPtr);
+ }
+
+ [System.Security.SecurityCritical]
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
+ {
+ this._target = this;
+ this._methodPtr = shuffleThunk;
+ this._methodPtrAux = methodPtr;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorSecureClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
+ {
+ MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAllocLike(this);
+ realDelegate.CtorClosed(target, methodPtr);
+ this._invocationList = realDelegate;
+ this._target = this;
+ this._methodPtr = callThunk;
+ this._methodPtrAux = creatorMethod;
+ this._invocationCount = GetInvokeMethod();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorSecureClosedStatic(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
+ {
+ MulticastDelegate realDelegate = (MulticastDelegate)Delegate.InternalAllocLike(this);
+ realDelegate.CtorClosedStatic(target, methodPtr);
+ this._invocationList = realDelegate;
+ this._target = this;
+ this._methodPtr = callThunk;
+ this._methodPtrAux = creatorMethod;
+ this._invocationCount = GetInvokeMethod();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorSecureRTClosed(Object target, IntPtr methodPtr, IntPtr callThunk, IntPtr creatorMethod)
+ {
+ MulticastDelegate realDelegate = Delegate.InternalAllocLike(this);
+ realDelegate.CtorRTClosed(target, methodPtr);
+ this._invocationList = realDelegate;
+ this._target = this;
+ this._methodPtr = callThunk;
+ this._methodPtrAux = creatorMethod;
+ this._invocationCount = GetInvokeMethod();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorSecureOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
+ {
+ MulticastDelegate realDelegate = Delegate.InternalAllocLike(this);
+ realDelegate.CtorOpened(target, methodPtr, shuffleThunk);
+ this._invocationList = realDelegate;
+ this._target = this;
+ this._methodPtr = callThunk;
+ this._methodPtrAux = creatorMethod;
+ this._invocationCount = GetInvokeMethod();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk)
+ {
+ this._target = this;
+ this._methodPtr = shuffleThunk;
+ this._methodPtrAux = GetCallStub(methodPtr);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorSecureVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr callThunk, IntPtr creatorMethod)
+ {
+ MulticastDelegate realDelegate = Delegate.InternalAllocLike(this);
+ realDelegate.CtorVirtualDispatch(target, methodPtr, shuffleThunk);
+ this._invocationList = realDelegate;
+ this._target = this;
+ this._methodPtr = callThunk;
+ this._methodPtrAux = creatorMethod;
+ this._invocationCount = GetInvokeMethod();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorCollectibleClosedStatic(Object target, IntPtr methodPtr, IntPtr gchandle)
+ {
+ this._target = target;
+ this._methodPtr = methodPtr;
+ this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorCollectibleOpened(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
+ {
+ this._target = this;
+ this._methodPtr = shuffleThunk;
+ this._methodPtrAux = methodPtr;
+ this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.DebuggerNonUserCode]
+ private void CtorCollectibleVirtualDispatch(Object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle)
+ {
+ this._target = this;
+ this._methodPtr = shuffleThunk;
+ this._methodPtrAux = GetCallStub(methodPtr);
+ this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/MulticastNotSupportedException.cs b/src/mscorlib/src/System/MulticastNotSupportedException.cs
new file mode 100644
index 0000000000..ad8eeebb21
--- /dev/null
+++ b/src/mscorlib/src/System/MulticastNotSupportedException.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+// MulticastNotSupportedException
+// This is thrown when you add multiple callbacks to a non-multicast delegate.
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class MulticastNotSupportedException : SystemException {
+
+ public MulticastNotSupportedException()
+ : base(Environment.GetResourceString("Arg_MulticastNotSupportedException")) {
+ SetErrorCode(__HResults.COR_E_MULTICASTNOTSUPPORTED);
+ }
+
+ public MulticastNotSupportedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MULTICASTNOTSUPPORTED);
+ }
+
+ public MulticastNotSupportedException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MULTICASTNOTSUPPORTED);
+ }
+
+ internal MulticastNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/NonSerializedAttribute.cs b/src/mscorlib/src/System/NonSerializedAttribute.cs
new file mode 100644
index 0000000000..c3cd9a540c
--- /dev/null
+++ b/src/mscorlib/src/System/NonSerializedAttribute.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Used to mark a member as being not-serialized
+**
+**
+============================================================*/
+namespace System
+{
+ using System.Reflection;
+
+ [AttributeUsage(AttributeTargets.Field, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class NonSerializedAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeFieldInfo field)
+ {
+ if ((field.Attributes & FieldAttributes.NotSerialized) == 0)
+ return null;
+
+ return new NonSerializedAttribute();
+ }
+
+ internal static bool IsDefined(RuntimeFieldInfo field)
+ {
+ return (field.Attributes & FieldAttributes.NotSerialized) != 0;
+ }
+
+ public NonSerializedAttribute() { }
+ }
+}
diff --git a/src/mscorlib/src/System/NotFiniteNumberException.cs b/src/mscorlib/src/System/NotFiniteNumberException.cs
new file mode 100644
index 0000000000..a3d455aac6
--- /dev/null
+++ b/src/mscorlib/src/System/NotFiniteNumberException.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class NotFiniteNumberException : ArithmeticException {
+ private double _offendingNumber;
+
+ public NotFiniteNumberException()
+ : base(Environment.GetResourceString("Arg_NotFiniteNumberException")) {
+ _offendingNumber = 0;
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ public NotFiniteNumberException(double offendingNumber)
+ : base() {
+ _offendingNumber = offendingNumber;
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ public NotFiniteNumberException(String message)
+ : base(message) {
+ _offendingNumber = 0;
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ public NotFiniteNumberException(String message, double offendingNumber)
+ : base(message) {
+ _offendingNumber = offendingNumber;
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ public NotFiniteNumberException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ public NotFiniteNumberException(String message, double offendingNumber, Exception innerException)
+ : base(message, innerException) {
+ _offendingNumber = offendingNumber;
+ SetErrorCode(__HResults.COR_E_NOTFINITENUMBER);
+ }
+
+ protected NotFiniteNumberException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ _offendingNumber = info.GetInt32("OffendingNumber");
+ }
+
+ public double OffendingNumber {
+ get { return _offendingNumber; }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("OffendingNumber", _offendingNumber, typeof(Int32));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/NotImplementedException.cs b/src/mscorlib/src/System/NotImplementedException.cs
new file mode 100644
index 0000000000..d6c966805a
--- /dev/null
+++ b/src/mscorlib/src/System/NotImplementedException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception thrown when a requested method or operation is not
+** implemented.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class NotImplementedException : SystemException
+ {
+ public NotImplementedException()
+ : base(Environment.GetResourceString("Arg_NotImplementedException")) {
+ SetErrorCode(__HResults.E_NOTIMPL);
+ }
+ public NotImplementedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.E_NOTIMPL);
+ }
+ public NotImplementedException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.E_NOTIMPL);
+ }
+
+ protected NotImplementedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/NotSupportedException.cs b/src/mscorlib/src/System/NotSupportedException.cs
new file mode 100644
index 0000000000..ecef1d199a
--- /dev/null
+++ b/src/mscorlib/src/System/NotSupportedException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: For methods that should be implemented on subclasses.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class NotSupportedException : SystemException
+ {
+ public NotSupportedException()
+ : base(Environment.GetResourceString("Arg_NotSupportedException")) {
+ SetErrorCode(__HResults.COR_E_NOTSUPPORTED);
+ }
+
+ public NotSupportedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_NOTSUPPORTED);
+ }
+
+ public NotSupportedException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_NOTSUPPORTED);
+ }
+
+ protected NotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/NullReferenceException.cs b/src/mscorlib/src/System/NullReferenceException.cs
new file mode 100644
index 0000000000..d66ad9ca41
--- /dev/null
+++ b/src/mscorlib/src/System/NullReferenceException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for dereferencing a null reference.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class NullReferenceException : SystemException {
+ public NullReferenceException()
+ : base(Environment.GetResourceString("Arg_NullReferenceException")) {
+ SetErrorCode(__HResults.COR_E_NULLREFERENCE);
+ }
+
+ public NullReferenceException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_NULLREFERENCE);
+ }
+
+ public NullReferenceException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_NULLREFERENCE);
+ }
+
+ protected NullReferenceException(SerializationInfo info, StreamingContext context) : base(info, context) {}
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Nullable.cs b/src/mscorlib/src/System/Nullable.cs
new file mode 100644
index 0000000000..2091e20af3
--- /dev/null
+++ b/src/mscorlib/src/System/Nullable.cs
@@ -0,0 +1,158 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+ using System;
+
+namespace System
+{
+ using System.Globalization;
+ using System.Reflection;
+ using System.Collections.Generic;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ // Warning, don't put System.Runtime.Serialization.On*Serializ*Attribute
+ // on this class without first fixing ObjectClone::InvokeVtsCallbacks
+ // Also, because we have special type system support that says a a boxed Nullable<T>
+ // can be used where a boxed<T> is use, Nullable<T> can not implement any intefaces
+ // at all (since T may not). Do NOT add any interfaces to Nullable!
+ //
+ [Serializable]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ public struct Nullable<T> where T : struct
+ {
+ private bool hasValue;
+ internal T value;
+
+ [System.Runtime.Versioning.NonVersionable]
+ public Nullable(T value) {
+ this.value = value;
+ this.hasValue = true;
+ }
+
+ public bool HasValue {
+ [System.Runtime.Versioning.NonVersionable]
+ get {
+ return hasValue;
+ }
+ }
+
+ public T Value {
+ get {
+ if (!hasValue) {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_NoValue);
+ }
+ return value;
+ }
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public T GetValueOrDefault() {
+ return value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public T GetValueOrDefault(T defaultValue) {
+ return hasValue ? value : defaultValue;
+ }
+
+ public override bool Equals(object other) {
+ if (!hasValue) return other == null;
+ if (other == null) return false;
+ return value.Equals(other);
+ }
+
+ public override int GetHashCode() {
+ return hasValue ? value.GetHashCode() : 0;
+ }
+
+ public override string ToString() {
+ return hasValue ? value.ToString() : "";
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static implicit operator Nullable<T>(T value) {
+ return new Nullable<T>(value);
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static explicit operator T(Nullable<T> value) {
+ return value.Value;
+ }
+
+ // The following already obsoleted methods were removed:
+ // public int CompareTo(object other)
+ // public int CompareTo(Nullable<T> other)
+ // public bool Equals(Nullable<T> other)
+ // public static Nullable<T> FromObject(object value)
+ // public object ToObject()
+ // public string ToString(string format)
+ // public string ToString(IFormatProvider provider)
+ // public string ToString(string format, IFormatProvider provider)
+
+ // The following newly obsoleted methods were removed:
+ // string IFormattable.ToString(string format, IFormatProvider provider)
+ // int IComparable.CompareTo(object other)
+ // int IComparable<Nullable<T>>.CompareTo(Nullable<T> other)
+ // bool IEquatable<Nullable<T>>.Equals(Nullable<T> other)
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static class Nullable
+ {
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static int Compare<T>(Nullable<T> n1, Nullable<T> n2) where T : struct
+ {
+ if (n1.HasValue) {
+ if (n2.HasValue) return Comparer<T>.Default.Compare(n1.value, n2.value);
+ return 1;
+ }
+ if (n2.HasValue) return -1;
+ return 0;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static bool Equals<T>(Nullable<T> n1, Nullable<T> n2) where T : struct
+ {
+ if (n1.HasValue) {
+ if (n2.HasValue) return EqualityComparer<T>.Default.Equals(n1.value, n2.value);
+ return false;
+ }
+ if (n2.HasValue) return false;
+ return true;
+ }
+
+ // If the type provided is not a Nullable Type, return null.
+ // Otherwise, returns the underlying type of the Nullable type
+ public static Type GetUnderlyingType(Type nullableType) {
+ if((object)nullableType == null) {
+ throw new ArgumentNullException("nullableType");
+ }
+ Contract.EndContractBlock();
+ Type result = null;
+ if( nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition) {
+ // instantiated generic type only
+ Type genericType = nullableType.GetGenericTypeDefinition();
+ if( Object.ReferenceEquals(genericType, typeof(Nullable<>))) {
+ result = nullableType.GetGenericArguments()[0];
+ }
+ }
+ return result;
+ }
+
+ // The following already obsoleted methods were removed:
+ // public static bool HasValue<T>(Nullable<T> value)
+ // public static T GetValueOrDefault<T>(Nullable<T> value)
+ // public static T GetValueOrDefault<T>(Nullable<T> value, T valueWhenNull)
+
+ // The following newly obsoleted methods were removed:
+ // public static Nullable<T> FromObject<T>(object value)
+ // public static object ToObject<T>(Nullable<T> value)
+ // public static object Wrap(object value, Type type)
+ // public static object Unwrap(object value)
+ }
+}
diff --git a/src/mscorlib/src/System/Number.cs b/src/mscorlib/src/System/Number.cs
new file mode 100644
index 0000000000..3c1215d418
--- /dev/null
+++ b/src/mscorlib/src/System/Number.cs
@@ -0,0 +1,1215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ // The Number class implements methods for formatting and parsing
+ // numeric values. To format and parse numeric values, applications should
+ // use the Format and Parse methods provided by the numeric
+ // classes (Byte, Int16, Int32, Int64,
+ // Single, Double, Currency, and Decimal). Those
+ // Format and Parse methods share a common implementation
+ // provided by this class, and are thus documented in detail here.
+ //
+ // Formatting
+ //
+ // The Format methods provided by the numeric classes are all of the
+ // form
+ //
+ // public static String Format(XXX value, String format);
+ // public static String Format(XXX value, String format, NumberFormatInfo info);
+ //
+ // where XXX is the name of the particular numeric class. The methods convert
+ // the numeric value to a string using the format string given by the
+ // format parameter. If the format parameter is null or
+ // an empty string, the number is formatted as if the string "G" (general
+ // format) was specified. The info parameter specifies the
+ // NumberFormatInfo instance to use when formatting the number. If the
+ // info parameter is null or omitted, the numeric formatting information
+ // is obtained from the current culture. The NumberFormatInfo supplies
+ // such information as the characters to use for decimal and thousand
+ // separators, and the spelling and placement of currency symbols in monetary
+ // values.
+ //
+ // Format strings fall into two categories: Standard format strings and
+ // user-defined format strings. A format string consisting of a single
+ // alphabetic character (A-Z or a-z), optionally followed by a sequence of
+ // digits (0-9), is a standard format string. All other format strings are
+ // used-defined format strings.
+ //
+ // A standard format string takes the form Axx, where A is an
+ // alphabetic character called the format specifier and xx is a
+ // sequence of digits called the precision specifier. The format
+ // specifier controls the type of formatting applied to the number and the
+ // precision specifier controls the number of significant digits or decimal
+ // places of the formatting operation. The following table describes the
+ // supported standard formats.
+ //
+ // C c - Currency format. The number is
+ // converted to a string that represents a currency amount. The conversion is
+ // controlled by the currency format information of the NumberFormatInfo
+ // used to format the number. The precision specifier indicates the desired
+ // number of decimal places. If the precision specifier is omitted, the default
+ // currency precision given by the NumberFormatInfo is used.
+ //
+ // D d - Decimal format. This format is
+ // supported for integral types only. The number is converted to a string of
+ // decimal digits, prefixed by a minus sign if the number is negative. The
+ // precision specifier indicates the minimum number of digits desired in the
+ // resulting string. If required, the number will be left-padded with zeros to
+ // produce the number of digits given by the precision specifier.
+ //
+ // E e Engineering (scientific) format.
+ // The number is converted to a string of the form
+ // "-d.ddd...E+ddd" or "-d.ddd...e+ddd", where each
+ // 'd' indicates a digit (0-9). The string starts with a minus sign if the
+ // number is negative, and one digit always precedes the decimal point. The
+ // precision specifier indicates the desired number of digits after the decimal
+ // point. If the precision specifier is omitted, a default of 6 digits after
+ // the decimal point is used. The format specifier indicates whether to prefix
+ // the exponent with an 'E' or an 'e'. The exponent is always consists of a
+ // plus or minus sign and three digits.
+ //
+ // F f Fixed point format. The number is
+ // converted to a string of the form "-ddd.ddd....", where each
+ // 'd' indicates a digit (0-9). The string starts with a minus sign if the
+ // number is negative. The precision specifier indicates the desired number of
+ // decimal places. If the precision specifier is omitted, the default numeric
+ // precision given by the NumberFormatInfo is used.
+ //
+ // G g - General format. The number is
+ // converted to the shortest possible decimal representation using fixed point
+ // or scientific format. The precision specifier determines the number of
+ // significant digits in the resulting string. If the precision specifier is
+ // omitted, the number of significant digits is determined by the type of the
+ // number being converted (10 for int, 19 for long, 7 for
+ // float, 15 for double, 19 for Currency, and 29 for
+ // Decimal). Trailing zeros after the decimal point are removed, and the
+ // resulting string contains a decimal point only if required. The resulting
+ // string uses fixed point format if the exponent of the number is less than
+ // the number of significant digits and greater than or equal to -4. Otherwise,
+ // the resulting string uses scientific format, and the case of the format
+ // specifier controls whether the exponent is prefixed with an 'E' or an
+ // 'e'.
+ //
+ // N n Number format. The number is
+ // converted to a string of the form "-d,ddd,ddd.ddd....", where
+ // each 'd' indicates a digit (0-9). The string starts with a minus sign if the
+ // number is negative. Thousand separators are inserted between each group of
+ // three digits to the left of the decimal point. The precision specifier
+ // indicates the desired number of decimal places. If the precision specifier
+ // is omitted, the default numeric precision given by the
+ // NumberFormatInfo is used.
+ //
+ // X x - Hexadecimal format. This format is
+ // supported for integral types only. The number is converted to a string of
+ // hexadecimal digits. The format specifier indicates whether to use upper or
+ // lower case characters for the hexadecimal digits above 9 ('X' for 'ABCDEF',
+ // and 'x' for 'abcdef'). The precision specifier indicates the minimum number
+ // of digits desired in the resulting string. If required, the number will be
+ // left-padded with zeros to produce the number of digits given by the
+ // precision specifier.
+ //
+ // Some examples of standard format strings and their results are shown in the
+ // table below. (The examples all assume a default NumberFormatInfo.)
+ //
+ // Value Format Result
+ // 12345.6789 C $12,345.68
+ // -12345.6789 C ($12,345.68)
+ // 12345 D 12345
+ // 12345 D8 00012345
+ // 12345.6789 E 1.234568E+004
+ // 12345.6789 E10 1.2345678900E+004
+ // 12345.6789 e4 1.2346e+004
+ // 12345.6789 F 12345.68
+ // 12345.6789 F0 12346
+ // 12345.6789 F6 12345.678900
+ // 12345.6789 G 12345.6789
+ // 12345.6789 G7 12345.68
+ // 123456789 G7 1.234568E8
+ // 12345.6789 N 12,345.68
+ // 123456789 N4 123,456,789.0000
+ // 0x2c45e x 2c45e
+ // 0x2c45e X 2C45E
+ // 0x2c45e X8 0002C45E
+ //
+ // Format strings that do not start with an alphabetic character, or that start
+ // with an alphabetic character followed by a non-digit, are called
+ // user-defined format strings. The following table describes the formatting
+ // characters that are supported in user defined format strings.
+ //
+ //
+ // 0 - Digit placeholder. If the value being
+ // formatted has a digit in the position where the '0' appears in the format
+ // string, then that digit is copied to the output string. Otherwise, a '0' is
+ // stored in that position in the output string. The position of the leftmost
+ // '0' before the decimal point and the rightmost '0' after the decimal point
+ // determines the range of digits that are always present in the output
+ // string.
+ //
+ // # - Digit placeholder. If the value being
+ // formatted has a digit in the position where the '#' appears in the format
+ // string, then that digit is copied to the output string. Otherwise, nothing
+ // is stored in that position in the output string.
+ //
+ // . - Decimal point. The first '.' character
+ // in the format string determines the location of the decimal separator in the
+ // formatted value; any additional '.' characters are ignored. The actual
+ // character used as a the decimal separator in the output string is given by
+ // the NumberFormatInfo used to format the number.
+ //
+ // , - Thousand separator and number scaling.
+ // The ',' character serves two purposes. First, if the format string contains
+ // a ',' character between two digit placeholders (0 or #) and to the left of
+ // the decimal point if one is present, then the output will have thousand
+ // separators inserted between each group of three digits to the left of the
+ // decimal separator. The actual character used as a the decimal separator in
+ // the output string is given by the NumberFormatInfo used to format the
+ // number. Second, if the format string contains one or more ',' characters
+ // immediately to the left of the decimal point, or after the last digit
+ // placeholder if there is no decimal point, then the number will be divided by
+ // 1000 times the number of ',' characters before it is formatted. For example,
+ // the format string '0,,' will represent 100 million as just 100. Use of the
+ // ',' character to indicate scaling does not also cause the formatted number
+ // to have thousand separators. Thus, to scale a number by 1 million and insert
+ // thousand separators you would use the format string '#,##0,,'.
+ //
+ // % - Percentage placeholder. The presence of
+ // a '%' character in the format string causes the number to be multiplied by
+ // 100 before it is formatted. The '%' character itself is inserted in the
+ // output string where it appears in the format string.
+ //
+ // E+ E- e+ e- - Scientific notation.
+ // If any of the strings 'E+', 'E-', 'e+', or 'e-' are present in the format
+ // string and are immediately followed by at least one '0' character, then the
+ // number is formatted using scientific notation with an 'E' or 'e' inserted
+ // between the number and the exponent. The number of '0' characters following
+ // the scientific notation indicator determines the minimum number of digits to
+ // output for the exponent. The 'E+' and 'e+' formats indicate that a sign
+ // character (plus or minus) should always precede the exponent. The 'E-' and
+ // 'e-' formats indicate that a sign character should only precede negative
+ // exponents.
+ //
+ // \ - Literal character. A backslash character
+ // causes the next character in the format string to be copied to the output
+ // string as-is. The backslash itself isn't copied, so to place a backslash
+ // character in the output string, use two backslashes (\\) in the format
+ // string.
+ //
+ // 'ABC' "ABC" - Literal string. Characters
+ // enclosed in single or double quotation marks are copied to the output string
+ // as-is and do not affect formatting.
+ //
+ // ; - Section separator. The ';' character is
+ // used to separate sections for positive, negative, and zero numbers in the
+ // format string.
+ //
+ // Other - All other characters are copied to
+ // the output string in the position they appear.
+ //
+ // For fixed point formats (formats not containing an 'E+', 'E-', 'e+', or
+ // 'e-'), the number is rounded to as many decimal places as there are digit
+ // placeholders to the right of the decimal point. If the format string does
+ // not contain a decimal point, the number is rounded to the nearest
+ // integer. If the number has more digits than there are digit placeholders to
+ // the left of the decimal point, the extra digits are copied to the output
+ // string immediately before the first digit placeholder.
+ //
+ // For scientific formats, the number is rounded to as many significant digits
+ // as there are digit placeholders in the format string.
+ //
+ // To allow for different formatting of positive, negative, and zero values, a
+ // user-defined format string may contain up to three sections separated by
+ // semicolons. The results of having one, two, or three sections in the format
+ // string are described in the table below.
+ //
+ // Sections:
+ //
+ // One - The format string applies to all values.
+ //
+ // Two - The first section applies to positive values
+ // and zeros, and the second section applies to negative values. If the number
+ // to be formatted is negative, but becomes zero after rounding according to
+ // the format in the second section, then the resulting zero is formatted
+ // according to the first section.
+ //
+ // Three - The first section applies to positive
+ // values, the second section applies to negative values, and the third section
+ // applies to zeros. The second section may be left empty (by having no
+ // characters between the semicolons), in which case the first section applies
+ // to all non-zero values. If the number to be formatted is non-zero, but
+ // becomes zero after rounding according to the format in the first or second
+ // section, then the resulting zero is formatted according to the third
+ // section.
+ //
+ // For both standard and user-defined formatting operations on values of type
+ // float and double, if the value being formatted is a NaN (Not
+ // a Number) or a positive or negative infinity, then regardless of the format
+ // string, the resulting string is given by the NaNSymbol,
+ // PositiveInfinitySymbol, or NegativeInfinitySymbol property of
+ // the NumberFormatInfo used to format the number.
+ //
+ // Parsing
+ //
+ // The Parse methods provided by the numeric classes are all of the form
+ //
+ // public static XXX Parse(String s);
+ // public static XXX Parse(String s, int style);
+ // public static XXX Parse(String s, int style, NumberFormatInfo info);
+ //
+ // where XXX is the name of the particular numeric class. The methods convert a
+ // string to a numeric value. The optional style parameter specifies the
+ // permitted style of the numeric string. It must be a combination of bit flags
+ // from the NumberStyles enumeration. The optional info parameter
+ // specifies the NumberFormatInfo instance to use when parsing the
+ // string. If the info parameter is null or omitted, the numeric
+ // formatting information is obtained from the current culture.
+ //
+ // Numeric strings produced by the Format methods using the Currency,
+ // Decimal, Engineering, Fixed point, General, or Number standard formats
+ // (the C, D, E, F, G, and N format specifiers) are guaranteed to be parseable
+ // by the Parse methods if the NumberStyles.Any style is
+ // specified. Note, however, that the Parse methods do not accept
+ // NaNs or Infinities.
+ //
+ //This class contains only static members and does not need to be serializable
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal class Number
+ {
+ private Number() {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatDecimal(Decimal value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatDouble(double value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatInt32(int value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatUInt32(uint value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatInt64(long value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatUInt64(ulong value, String format, NumberFormatInfo info);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern String FormatSingle(float value, String format, NumberFormatInfo info);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public unsafe static extern Boolean NumberBufferToDecimal(byte* number, ref Decimal value);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe static extern Boolean NumberBufferToDouble(byte* number, ref Double value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ [System.Security.SecurityCritical] // auto-generated
+ internal static extern unsafe string FormatNumberBuffer(byte* number, string format, NumberFormatInfo info, char* allDigits);
+
+ // Constants used by number parsing
+ private const Int32 NumberMaxDigits = 50;
+
+ private const Int32 Int32Precision = 10;
+ private const Int32 UInt32Precision = Int32Precision;
+ private const Int32 Int64Precision = 19;
+ private const Int32 UInt64Precision = 20;
+
+ // NumberBuffer is a partial wrapper around a stack pointer that maps on to
+ // the native NUMBER struct so that it can be passed to native directly. It
+ // must be initialized with a stack Byte * of size NumberBufferBytes.
+ // For performance, this structure should attempt to be completely inlined.
+ //
+ // It should always be initialized like so:
+ //
+ // Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ // NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ //
+ // For performance, when working on the buffer in managed we use the values in this
+ // structure, except for the digits, and pack those values into the byte buffer
+ // if called out to managed.
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal unsafe struct NumberBuffer {
+
+ // Enough space for NumberMaxDigit characters plus null and 3 32 bit integers and a pointer
+ public static readonly Int32 NumberBufferBytes = 12 + ((NumberMaxDigits + 1) * 2) + IntPtr.Size;
+
+ [SecurityCritical]
+ private Byte * baseAddress;
+ [SecurityCritical]
+ public Char * digits;
+ public Int32 precision;
+ public Int32 scale;
+ public Boolean sign;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public NumberBuffer(Byte* stackBuffer) {
+ this.baseAddress = stackBuffer;
+ this.digits = (((Char*) stackBuffer) + 6);
+ this.precision = 0;
+ this.scale = 0;
+ this.sign = false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Byte* PackForNative() {
+ Int32* baseInteger = (Int32*) baseAddress;
+ baseInteger[0] = precision;
+ baseInteger[1] = scale;
+ baseInteger[2] = sign ? 1 : 0;
+ return baseAddress;
+ }
+ }
+
+ private static Boolean HexNumberToInt32(ref NumberBuffer number, ref Int32 value) {
+ UInt32 passedValue = 0;
+ Boolean returnValue = HexNumberToUInt32(ref number, ref passedValue);
+ value = (Int32)passedValue;
+ return returnValue;
+ }
+
+ private static Boolean HexNumberToInt64(ref NumberBuffer number, ref Int64 value) {
+ UInt64 passedValue = 0;
+ Boolean returnValue = HexNumberToUInt64(ref number, ref passedValue);
+ value = (Int64)passedValue;
+ return returnValue;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean HexNumberToUInt32(ref NumberBuffer number, ref UInt32 value) {
+
+ Int32 i = number.scale;
+ if (i > UInt32Precision || i < number.precision) {
+ return false;
+ }
+ Char* p = number.digits;
+ Contract.Assert(p != null, "");
+
+ UInt32 n = 0;
+ while (--i >= 0) {
+ if (n > ((UInt32)0xFFFFFFFF / 16)) {
+ return false;
+ }
+ n *= 16;
+ if (*p != '\0') {
+ UInt32 newN = n;
+ if (*p != '\0') {
+ if (*p >= '0' && *p <= '9') {
+ newN += (UInt32)(*p - '0');
+ }
+ else {
+ if (*p >= 'A' && *p <= 'F') {
+ newN += (UInt32)((*p - 'A') + 10);
+ }
+ else {
+ Contract.Assert(*p >= 'a' && *p <= 'f', "");
+ newN += (UInt32)((*p - 'a') + 10);
+ }
+ }
+ p++;
+ }
+
+ // Detect an overflow here...
+ if (newN < n) {
+ return false;
+ }
+ n = newN;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean HexNumberToUInt64(ref NumberBuffer number, ref UInt64 value) {
+
+ Int32 i = number.scale;
+ if (i > UInt64Precision || i < number.precision) {
+ return false;
+ }
+ Char* p = number.digits;
+ Contract.Assert(p != null, "");
+
+ UInt64 n = 0;
+ while (--i >= 0) {
+ if (n > (0xFFFFFFFFFFFFFFFF / 16)) {
+ return false;
+ }
+ n *= 16;
+ if (*p != '\0') {
+ UInt64 newN = n;
+ if (*p != '\0') {
+ if (*p >= '0' && *p <= '9') {
+ newN += (UInt64)(*p - '0');
+ }
+ else {
+ if (*p >= 'A' && *p <= 'F') {
+ newN += (UInt64)((*p - 'A') + 10);
+ }
+ else {
+ Contract.Assert(*p >= 'a' && *p <= 'f', "");
+ newN += (UInt64)((*p - 'a') + 10);
+ }
+ }
+ p++;
+ }
+
+ // Detect an overflow here...
+ if (newN < n) {
+ return false;
+ }
+ n = newN;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ private static Boolean IsWhite(char ch) {
+ return (((ch) == 0x20) || ((ch) >= 0x09 && (ch) <= 0x0D));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean NumberToInt32(ref NumberBuffer number, ref Int32 value) {
+
+ Int32 i = number.scale;
+ if (i > Int32Precision || i < number.precision) {
+ return false;
+ }
+ char * p = number.digits;
+ Contract.Assert(p != null, "");
+ Int32 n = 0;
+ while (--i >= 0) {
+ if ((UInt32)n > (0x7FFFFFFF / 10)) {
+ return false;
+ }
+ n *= 10;
+ if (*p != '\0') {
+ n += (Int32)(*p++ - '0');
+ }
+ }
+ if (number.sign) {
+ n = -n;
+ if (n > 0) {
+ return false;
+ }
+ }
+ else {
+ if (n < 0) {
+ return false;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean NumberToInt64(ref NumberBuffer number, ref Int64 value) {
+
+ Int32 i = number.scale;
+ if (i > Int64Precision || i < number.precision) {
+ return false;
+ }
+ char* p = number.digits;
+ Contract.Assert(p != null, "");
+ Int64 n = 0;
+ while (--i >= 0) {
+ if ((UInt64)n > (0x7FFFFFFFFFFFFFFF / 10)) {
+ return false;
+ }
+ n *= 10;
+ if (*p != '\0') {
+ n += (Int32)(*p++ - '0');
+ }
+ }
+ if (number.sign) {
+ n = -n;
+ if (n > 0) {
+ return false;
+ }
+ }
+ else {
+ if (n < 0) {
+ return false;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean NumberToUInt32(ref NumberBuffer number, ref UInt32 value) {
+
+ Int32 i = number.scale;
+ if (i > UInt32Precision || i < number.precision || number.sign ) {
+ return false;
+ }
+ char* p = number.digits;
+ Contract.Assert(p != null, "");
+ UInt32 n = 0;
+ while (--i >= 0) {
+ if (n > (0xFFFFFFFF / 10)) {
+ return false;
+ }
+ n *= 10;
+ if (*p != '\0') {
+ UInt32 newN = n + (UInt32)(*p++ - '0');
+ // Detect an overflow here...
+ if (newN < n) {
+ return false;
+ }
+ n = newN;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static Boolean NumberToUInt64(ref NumberBuffer number, ref UInt64 value) {
+
+ Int32 i = number.scale;
+ if (i > UInt64Precision || i < number.precision || number.sign) {
+ return false;
+ }
+ char * p = number.digits;
+ Contract.Assert(p != null, "");
+ UInt64 n = 0;
+ while (--i >= 0) {
+ if (n > (0xFFFFFFFFFFFFFFFF / 10)) {
+ return false;
+ }
+ n *= 10;
+ if (*p != '\0') {
+ UInt64 newN = n + (UInt64)(*p++ - '0');
+ // Detect an overflow here...
+ if (newN < n) {
+ return false;
+ }
+ n = newN;
+ }
+ }
+ value = n;
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static char * MatchChars(char* p, string str) {
+ fixed (char* stringPointer = str) {
+ return MatchChars(p, stringPointer);
+ }
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static char * MatchChars(char* p, char* str) {
+ Contract.Assert(p != null && str != null, "");
+
+ if (*str == '\0') {
+ return null;
+ }
+ for (; (*str != '\0'); p++, str++) {
+ if (*p != *str) { //We only hurt the failure case
+ if ((*str == '\u00A0') && (*p == '\u0020')) {// This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 as a
+ // space character we use 0x20 space character instead to mean the same.
+ continue;
+ }
+ return null;
+ }
+ }
+ return p;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Decimal ParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ Decimal result = 0;
+
+ StringToNumber(value, options, ref number, numfmt, true);
+
+ if (!NumberBufferToDecimal(number.PackForNative(), ref result)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Decimal"));
+ }
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Double ParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ Double d = 0;
+
+ if (!TryStringToNumber(value, options, ref number, numfmt, false)) {
+ //If we failed TryStringToNumber, it may be from one of our special strings.
+ //Check the three with which we're concerned and rethrow if it's not one of
+ //those strings.
+ String sTrim = value.Trim();
+ if (sTrim.Equals(numfmt.PositiveInfinitySymbol)) {
+ return Double.PositiveInfinity;
+ }
+ if (sTrim.Equals(numfmt.NegativeInfinitySymbol)) {
+ return Double.NegativeInfinity;
+ }
+ if (sTrim.Equals(numfmt.NaNSymbol)) {
+ return Double.NaN;
+ }
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+
+ if (!NumberBufferToDouble(number.PackForNative(), ref d)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Double"));
+ }
+
+ return d;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Int32 ParseInt32(String s, NumberStyles style, NumberFormatInfo info) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ Int32 i = 0;
+
+ StringToNumber(s, style, ref number, info, false);
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToInt32(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
+ }
+ }
+ else {
+ if (!NumberToInt32(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
+ }
+ }
+ return i;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Int64 ParseInt64(String value, NumberStyles options, NumberFormatInfo numfmt) {
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ Int64 i = 0;
+
+ StringToNumber(value, options, ref number, numfmt, false);
+
+ if ((options & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToInt64(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
+ }
+ }
+ else {
+ if (!NumberToInt64(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Int64"));
+ }
+ }
+ return i;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static Boolean ParseNumber(ref char * str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, Boolean parseDecimal) {
+
+ const Int32 StateSign = 0x0001;
+ const Int32 StateParens = 0x0002;
+ const Int32 StateDigits = 0x0004;
+ const Int32 StateNonZero = 0x0008;
+ const Int32 StateDecimal = 0x0010;
+ const Int32 StateCurrency = 0x0020;
+
+ number.scale = 0;
+ number.sign = false;
+ string decSep; // decimal separator from NumberFormatInfo.
+ string groupSep; // group separator from NumberFormatInfo.
+ string currSymbol = null; // currency symbol from NumberFormatInfo.
+
+ // The alternative currency symbol used in ANSI codepage, that can not roundtrip between ANSI and Unicode.
+ // Currently, only ja-JP and ko-KR has non-null values (which is U+005c, backslash)
+ string ansicurrSymbol = null; // currency symbol from NumberFormatInfo.
+ string altdecSep = null; // decimal separator from NumberFormatInfo as a decimal
+ string altgroupSep = null; // group separator from NumberFormatInfo as a decimal
+
+ Boolean parsingCurrency = false;
+ if ((options & NumberStyles.AllowCurrencySymbol) != 0) {
+ currSymbol = numfmt.CurrencySymbol;
+
+#if !FEATURE_COREFX_GLOBALIZATION
+ if (numfmt.ansiCurrencySymbol != null) {
+ ansicurrSymbol = numfmt.ansiCurrencySymbol;
+ }
+#endif
+
+ // The idea here is to match the currency separators and on failure match the number separators to keep the perf of VB's IsNumeric fast.
+ // The values of decSep are setup to use the correct relevant separator (currency in the if part and decimal in the else part).
+ altdecSep = numfmt.NumberDecimalSeparator;
+ altgroupSep = numfmt.NumberGroupSeparator;
+ decSep = numfmt.CurrencyDecimalSeparator;
+ groupSep = numfmt.CurrencyGroupSeparator;
+ parsingCurrency = true;
+ }
+ else {
+ decSep = numfmt.NumberDecimalSeparator;
+ groupSep = numfmt.NumberGroupSeparator;
+ }
+
+ Int32 state = 0;
+ Boolean signflag = false; // Cache the results of "options & PARSE_LEADINGSIGN && !(state & STATE_SIGN)" to avoid doing this twice
+ Boolean bigNumber = (sb != null); // When a StringBuilder is provided then we use it in place of the number.digits char[50]
+ Boolean bigNumberHex = (bigNumber && ((options & NumberStyles.AllowHexSpecifier) != 0));
+ Int32 maxParseDigits = bigNumber ? Int32.MaxValue : NumberMaxDigits;
+
+ char* p = str;
+ char ch = *p;
+ char* next;
+
+ while (true) {
+ // Eat whitespace unless we've found a sign which isn't followed by a currency symbol.
+ // "-Kr 1231.47" is legal but "- 1231.47" is not.
+ if (IsWhite(ch) && ((options & NumberStyles.AllowLeadingWhite) != 0) && (((state & StateSign) == 0) || (((state & StateSign) != 0) && (((state & StateCurrency) != 0) || numfmt.numberNegativePattern == 2)))) {
+ // Do nothing here. We will increase p at the end of the loop.
+ }
+ else if ((signflag = (((options & NumberStyles.AllowLeadingSign) != 0) && ((state & StateSign) == 0))) && ((next = MatchChars(p, numfmt.positiveSign)) != null)) {
+ state |= StateSign;
+ p = next - 1;
+ } else if (signflag && (next = MatchChars(p, numfmt.negativeSign)) != null) {
+ state |= StateSign;
+ number.sign = true;
+ p = next - 1;
+ }
+ else if (ch == '(' && ((options & NumberStyles.AllowParentheses) != 0) && ((state & StateSign) == 0)) {
+ state |= StateSign | StateParens;
+ number.sign = true;
+ }
+ else if ((currSymbol != null && (next = MatchChars(p, currSymbol)) != null) || (ansicurrSymbol != null && (next = MatchChars(p, ansicurrSymbol)) != null)) {
+ state |= StateCurrency;
+ currSymbol = null;
+ ansicurrSymbol = null;
+ // We already found the currency symbol. There should not be more currency symbols. Set
+ // currSymbol to NULL so that we won't search it again in the later code path.
+ p = next - 1;
+ }
+ else {
+ break;
+ }
+ ch = *++p;
+ }
+ Int32 digCount = 0;
+ Int32 digEnd = 0;
+ while (true) {
+ if ((ch >= '0' && ch <= '9') || (((options & NumberStyles.AllowHexSpecifier) != 0) && ((ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F')))) {
+ state |= StateDigits;
+
+ if (ch != '0' || (state & StateNonZero) != 0 || bigNumberHex) {
+ if (digCount < maxParseDigits) {
+ if (bigNumber)
+ sb.Append(ch);
+ else
+ number.digits[digCount++] = ch;
+ if (ch != '0' || parseDecimal) {
+ digEnd = digCount;
+ }
+ }
+ if ((state & StateDecimal) == 0) {
+ number.scale++;
+ }
+ state |= StateNonZero;
+ }
+ else if ((state & StateDecimal) != 0) {
+ number.scale--;
+ }
+ }
+ else if (((options & NumberStyles.AllowDecimalPoint) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, decSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, altdecSep)) != null)) {
+ state |= StateDecimal;
+ p = next - 1;
+ }
+ else if (((options & NumberStyles.AllowThousands) != 0) && ((state & StateDigits) != 0) && ((state & StateDecimal) == 0) && ((next = MatchChars(p, groupSep)) != null || ((parsingCurrency) && (state & StateCurrency) == 0) && (next = MatchChars(p, altgroupSep)) != null)) {
+ p = next - 1;
+ }
+ else {
+ break;
+ }
+ ch = *++p;
+ }
+
+ Boolean negExp = false;
+ number.precision = digEnd;
+ if (bigNumber)
+ sb.Append('\0');
+ else
+ number.digits[digEnd] = '\0';
+ if ((state & StateDigits) != 0) {
+ if ((ch == 'E' || ch == 'e') && ((options & NumberStyles.AllowExponent) != 0)) {
+ char* temp = p;
+ ch = *++p;
+ if ((next = MatchChars(p, numfmt.positiveSign)) != null) {
+ ch = *(p = next);
+ }
+ else if ((next = MatchChars(p, numfmt.negativeSign)) != null) {
+ ch = *(p = next);
+ negExp = true;
+ }
+ if (ch >= '0' && ch <= '9') {
+ Int32 exp = 0;
+ do {
+ exp = exp * 10 + (ch - '0');
+ ch = *++p;
+ if (exp > 1000) {
+ exp = 9999;
+ while (ch >= '0' && ch <= '9') {
+ ch = *++p;
+ }
+ }
+ } while (ch >= '0' && ch <= '9');
+ if (negExp) {
+ exp = -exp;
+ }
+ number.scale += exp;
+ }
+ else {
+ p = temp;
+ ch = *p;
+ }
+ }
+ while (true) {
+ if (IsWhite(ch) && ((options & NumberStyles.AllowTrailingWhite) != 0)) {
+ }
+ else if ((signflag = (((options & NumberStyles.AllowTrailingSign) != 0) && ((state & StateSign) == 0))) && (next = MatchChars(p, numfmt.positiveSign)) != null) {
+ state |= StateSign;
+ p = next - 1;
+ } else if (signflag && (next = MatchChars(p, numfmt.negativeSign)) != null) {
+ state |= StateSign;
+ number.sign = true;
+ p = next - 1;
+ }
+ else if (ch == ')' && ((state & StateParens) != 0)) {
+ state &= ~StateParens;
+ }
+ else if ((currSymbol != null && (next = MatchChars(p, currSymbol)) != null) || (ansicurrSymbol != null && (next = MatchChars(p, ansicurrSymbol)) != null)) {
+ currSymbol = null;
+ ansicurrSymbol = null;
+ p = next - 1;
+ }
+ else {
+ break;
+ }
+ ch = *++p;
+ }
+ if ((state & StateParens) == 0) {
+ if ((state & StateNonZero) == 0) {
+ if (!parseDecimal) {
+ number.scale = 0;
+ }
+ if ((state & StateDecimal) == 0) {
+ number.sign = false;
+ }
+ }
+ str = p;
+ return true;
+ }
+ }
+ str = p;
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Single ParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt) {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ Double d = 0;
+
+ if (!TryStringToNumber(value, options, ref number, numfmt, false)) {
+ //If we failed TryStringToNumber, it may be from one of our special strings.
+ //Check the three with which we're concerned and rethrow if it's not one of
+ //those strings.
+ String sTrim = value.Trim();
+ if (sTrim.Equals(numfmt.PositiveInfinitySymbol)) {
+ return Single.PositiveInfinity;
+ }
+ if (sTrim.Equals(numfmt.NegativeInfinitySymbol)) {
+ return Single.NegativeInfinity;
+ }
+ if (sTrim.Equals(numfmt.NaNSymbol)) {
+ return Single.NaN;
+ }
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+
+ if (!NumberBufferToDouble(number.PackForNative(), ref d)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Single"));
+ }
+ Single castSingle = (Single)d;
+ if (Single.IsInfinity(castSingle)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_Single"));
+ }
+ return castSingle;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static UInt32 ParseUInt32(String value, NumberStyles options, NumberFormatInfo numfmt) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ UInt32 i = 0;
+
+ StringToNumber(value, options, ref number, numfmt, false);
+
+ if ((options & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToUInt32(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt32"));
+ }
+ }
+ else {
+ if (!NumberToUInt32(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt32"));
+ }
+ }
+
+ return i;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static UInt64 ParseUInt64(String value, NumberStyles options, NumberFormatInfo numfmt) {
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ UInt64 i = 0;
+
+ StringToNumber(value, options, ref number, numfmt, false);
+ if ((options & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToUInt64(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt64"));
+ }
+ }
+ else {
+ if (!NumberToUInt64(ref number, ref i)) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt64"));
+ }
+ }
+ return i;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static void StringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo info, Boolean parseDecimal) {
+
+ if (str == null) {
+ throw new ArgumentNullException("String");
+ }
+ Contract.EndContractBlock();
+ Contract.Assert(info != null, "");
+ fixed (char* stringPointer = str) {
+ char * p = stringPointer;
+ if (!ParseNumber(ref p, options, ref number, null, info , parseDecimal)
+ || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer)))) {
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+ }
+ }
+
+ private static Boolean TrailingZeros(String s, Int32 index) {
+ // For compatibility, we need to allow trailing zeros at the end of a number string
+ for (int i = index; i < s.Length; i++) {
+ if (s[i] != '\0') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseDecimal(String value, NumberStyles options, NumberFormatInfo numfmt, out Decimal result) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+ if (!TryStringToNumber(value, options, ref number, numfmt, true)) {
+ return false;
+ }
+
+ if (!NumberBufferToDecimal(number.PackForNative(), ref result)) {
+ return false;
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseDouble(String value, NumberStyles options, NumberFormatInfo numfmt, out Double result) {
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+
+ if (!TryStringToNumber(value, options, ref number, numfmt, false)) {
+ return false;
+ }
+ if (!NumberBufferToDouble(number.PackForNative(), ref result)) {
+ return false;
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseInt32(String s, NumberStyles style, NumberFormatInfo info, out Int32 result) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+ if (!TryStringToNumber(s, style, ref number, info, false)) {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToInt32(ref number, ref result)) {
+ return false;
+ }
+ }
+ else {
+ if (!NumberToInt32(ref number, ref result)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseInt64(String s, NumberStyles style, NumberFormatInfo info, out Int64 result) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+ if (!TryStringToNumber(s, style, ref number, info, false)) {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToInt64(ref number, ref result)) {
+ return false;
+ }
+ }
+ else {
+ if (!NumberToInt64(ref number, ref result)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseSingle(String value, NumberStyles options, NumberFormatInfo numfmt, out Single result) {
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+ Double d = 0;
+
+ if (!TryStringToNumber(value, options, ref number, numfmt, false)) {
+ return false;
+ }
+ if (!NumberBufferToDouble(number.PackForNative(), ref d)) {
+ return false;
+ }
+ Single castSingle = (Single)d;
+ if (Single.IsInfinity(castSingle)) {
+ return false;
+ }
+
+ result = castSingle;
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseUInt32(String s, NumberStyles style, NumberFormatInfo info, out UInt32 result) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+ if (!TryStringToNumber(s, style, ref number, info, false)) {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToUInt32(ref number, ref result)) {
+ return false;
+ }
+ }
+ else {
+ if (!NumberToUInt32(ref number, ref result)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Boolean TryParseUInt64(String s, NumberStyles style, NumberFormatInfo info, out UInt64 result) {
+
+ Byte * numberBufferBytes = stackalloc Byte[NumberBuffer.NumberBufferBytes];
+ NumberBuffer number = new NumberBuffer(numberBufferBytes);
+ result = 0;
+
+ if (!TryStringToNumber(s, style, ref number, info, false)) {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) {
+ if (!HexNumberToUInt64(ref number, ref result)) {
+ return false;
+ }
+ }
+ else {
+ if (!NumberToUInt64(ref number, ref result)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal static Boolean TryStringToNumber(String str, NumberStyles options, ref NumberBuffer number, NumberFormatInfo numfmt, Boolean parseDecimal) {
+ return TryStringToNumber(str, options, ref number, null, numfmt, parseDecimal);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal unsafe static Boolean TryStringToNumber(String str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, Boolean parseDecimal) {
+
+ if (str == null) {
+ return false;
+ }
+ Contract.Assert(numfmt != null, "");
+
+ fixed (char* stringPointer = str) {
+ char * p = stringPointer;
+ if (!ParseNumber(ref p, options, ref number, sb, numfmt, parseDecimal)
+ || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer)))) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Object.cs b/src/mscorlib/src/System/Object.cs
new file mode 100644
index 0000000000..769c5a6bd6
--- /dev/null
+++ b/src/mscorlib/src/System/Object.cs
@@ -0,0 +1,255 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Object is the root class for all CLR objects. This class
+** defines only the basics.
+**
+**
+===========================================================*/
+
+namespace System {
+ using System;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using FieldInfo = System.Reflection.FieldInfo;
+ using BindingFlags = System.Reflection.BindingFlags;
+#if FEATURE_REMOTING
+ using RemotingException = System.Runtime.Remoting.RemotingException;
+#endif
+// The Object is the root class for all object in the CLR System. Object
+// is the super class for all other CLR objects and provide a set of methods and low level
+// services to subclasses. These services include object synchronization and support for clone
+// operations.
+//
+ //This class contains no data and does not need to be serializable
+[Serializable]
+[ClassInterface(ClassInterfaceType.AutoDual)]
+[System.Runtime.InteropServices.ComVisible(true)]
+public class Object
+{
+ // Creates a new instance of an Object.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [System.Runtime.Versioning.NonVersionable]
+ public Object()
+ {
+ }
+
+ // Returns a String which represents the object instance. The default
+ // for an object is to return the fully qualified name of the class.
+ //
+ public virtual String ToString()
+ {
+ return GetType().ToString();
+ }
+
+ // Returns a boolean indicating if the passed in object obj is
+ // Equal to this. Equality is defined as object equality for reference
+ // types and bitwise equality for value types using a loader trick to
+ // replace Equals with EqualsValue for value types).
+ //
+
+ public virtual bool Equals(Object obj)
+ {
+ return RuntimeHelpers.Equals(this, obj);
+ }
+
+ public static bool Equals(Object objA, Object objB)
+ {
+ if (objA==objB) {
+ return true;
+ }
+ if (objA==null || objB==null) {
+ return false;
+ }
+ return objA.Equals(objB);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool ReferenceEquals (Object objA, Object objB) {
+ return objA == objB;
+ }
+
+ // GetHashCode is intended to serve as a hash function for this object.
+ // Based on the contents of the object, the hash function will return a suitable
+ // value with a relatively random distribution over the various inputs.
+ //
+ // The default implementation returns the sync block index for this instance.
+ // Calling it on the same object multiple times will return the same value, so
+ // it will technically meet the needs of a hash function, but it's less than ideal.
+ // Objects (& especially value classes) should override this method.
+ //
+ public virtual int GetHashCode()
+ {
+ return RuntimeHelpers.GetHashCode(this);
+ }
+
+ // Returns a Type object which represent this object instance.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Pure]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern Type GetType();
+
+ // Allow an object to free resources before the object is reclaimed by the GC.
+ //
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ ~Object()
+ {
+ }
+
+ // Returns a new object instance that is a memberwise copy of this
+ // object. This is always a shallow copy of the instance. The method is protected
+ // so that other object may only call this method on themselves. It is entended to
+ // support the ICloneable interface.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ protected extern Object MemberwiseClone();
+
+
+ // Sets the value specified in the variant on the field
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ private void FieldSetter(String typeName, String fieldName, Object val)
+ {
+ Contract.Requires(typeName != null);
+ Contract.Requires(fieldName != null);
+
+ // Extract the field info object
+ FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
+
+ if (fldInfo.IsInitOnly)
+ throw new FieldAccessException(Environment.GetResourceString("FieldAccess_InitOnly"));
+
+ // Make sure that the value is compatible with the type
+ // of field
+#if FEATURE_REMOTING
+ System.Runtime.Remoting.Messaging.Message.CoerceArg(val, fldInfo.FieldType);
+#else
+ Type pt=fldInfo.FieldType;
+ if (pt.IsByRef)
+ {
+ pt = pt.GetElementType();
+ }
+
+ if (!pt.IsInstanceOfType(val))
+ {
+ val = Convert.ChangeType(val, pt, CultureInfo.InvariantCulture);
+ }
+
+#endif
+
+ // Set the value
+ fldInfo.SetValue(this, val);
+ }
+
+ // Gets the value specified in the variant on the field
+ //
+ private void FieldGetter(String typeName, String fieldName, ref Object val)
+ {
+ Contract.Requires(typeName != null);
+ Contract.Requires(fieldName != null);
+
+ // Extract the field info object
+ FieldInfo fldInfo = GetFieldInfo(typeName, fieldName);
+
+ // Get the value
+ val = fldInfo.GetValue(this);
+ }
+
+ // Gets the field info object given the type name and field name.
+ //
+ private FieldInfo GetFieldInfo(String typeName, String fieldName)
+ {
+ Contract.Requires(typeName != null);
+ Contract.Requires(fieldName != null);
+ Contract.Ensures(Contract.Result<FieldInfo>() != null);
+
+ Type t = GetType();
+ while(null != t)
+ {
+ if(t.FullName.Equals(typeName))
+ {
+ break;
+ }
+
+ t = t.BaseType;
+ }
+
+ if (null == t)
+ {
+#if FEATURE_REMOTING
+ throw new RemotingException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadType"),
+ typeName));
+#else
+ throw new ArgumentException();
+#endif
+ }
+
+ FieldInfo fldInfo = t.GetField(fieldName, BindingFlags.Public |
+ BindingFlags.Instance |
+ BindingFlags.IgnoreCase);
+ if(null == fldInfo)
+ {
+#if FEATURE_REMOTING
+ throw new RemotingException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Remoting_BadField"),
+ fieldName, typeName));
+#else
+ throw new ArgumentException();
+#endif
+
+ }
+
+ return fldInfo;
+ }
+}
+
+
+// Internal methodtable used to instantiate the "canonical" methodtable for generic instantiations.
+// The name "__Canon" will never been seen by users but it will appear a lot in debugger stack traces
+// involving generics so it is kept deliberately short as to avoid being a nuisance.
+
+[Serializable]
+[ClassInterface(ClassInterfaceType.AutoDual)]
+[System.Runtime.InteropServices.ComVisible(true)]
+internal class __Canon
+{
+}
+
+// This class is used to define the name of the base class library
+internal class CoreLib
+{
+
+#if FEATURE_CORECLR
+ public const string Name = "System.Private.CoreLib";
+#else
+ public const string Name = "mscorlib";
+#endif
+
+ public static string FixupCoreLibName(string strToFixup)
+ {
+#if FEATURE_CORECLR
+ if (!String.IsNullOrEmpty(strToFixup))
+ {
+ strToFixup = strToFixup.Replace("mscorlib", System.CoreLib.Name);
+ }
+#endif
+ return strToFixup;
+ }
+}
+
+}
diff --git a/src/mscorlib/src/System/ObjectDisposedException.cs b/src/mscorlib/src/System/ObjectDisposedException.cs
new file mode 100644
index 0000000000..cf92cef5ee
--- /dev/null
+++ b/src/mscorlib/src/System/ObjectDisposedException.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+ using System;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security.Permissions;
+
+ /// <devdoc>
+ /// <para> The exception that is thrown when accessing an object that was
+ /// disposed.</para>
+ /// </devdoc>
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ObjectDisposedException : InvalidOperationException {
+ private String objectName;
+
+ // This constructor should only be called by the EE (COMPlusThrow)
+ private ObjectDisposedException() :
+ this(null ,Environment.GetResourceString("ObjectDisposed_Generic")) {
+ }
+
+ public ObjectDisposedException(String objectName) :
+ this(objectName, Environment.GetResourceString("ObjectDisposed_Generic")) {
+ }
+
+ public ObjectDisposedException(String objectName, String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_OBJECTDISPOSED);
+ this.objectName = objectName;
+ }
+
+ public ObjectDisposedException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_OBJECTDISPOSED);
+ }
+
+ /// <devdoc>
+ /// <para>Gets the text for the message for this exception.</para>
+ /// </devdoc>
+ public override String Message {
+ get {
+ String name = ObjectName;
+ if (name == null || name.Length == 0)
+ return base.Message;
+
+ String objectDisposed = Environment.GetResourceString("ObjectDisposed_ObjectName_Name", name);
+ return base.Message + Environment.NewLine + objectDisposed;
+ }
+ }
+
+ public String ObjectName {
+ get {
+ if (objectName == null)
+ {
+ return String.Empty;
+ }
+ return objectName;
+ }
+ }
+
+ protected ObjectDisposedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ objectName = info.GetString("ObjectName");
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ base.GetObjectData(info, context);
+ info.AddValue("ObjectName",ObjectName,typeof(String));
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/ObsoleteAttribute.cs b/src/mscorlib/src/System/ObsoleteAttribute.cs
new file mode 100644
index 0000000000..679e32a974
--- /dev/null
+++ b/src/mscorlib/src/System/ObsoleteAttribute.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Attribute for functions, etc that will be removed.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime.Remoting;
+ // This attribute is attached to members that are not to be used any longer.
+ // Message is some human readable explanation of what to use
+ // Error indicates if the compiler should treat usage of such a method as an
+ // error. (this would be used if the actual implementation of the obsolete
+ // method's implementation had changed).
+ //
+[Serializable]
+[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum |
+ AttributeTargets.Interface | AttributeTargets.Constructor | AttributeTargets.Method| AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Delegate
+ , Inherited = false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ObsoleteAttribute : Attribute
+ {
+ private String _message;
+ private bool _error;
+
+ public ObsoleteAttribute ()
+ {
+ _message = null;
+ _error = false;
+ }
+
+ public ObsoleteAttribute (String message)
+ {
+ _message = message;
+ _error = false;
+ }
+
+ public ObsoleteAttribute (String message, bool error)
+ {
+ _message = message;
+ _error = error;
+ }
+
+ public String Message {
+ get {return _message;}
+ }
+
+ public bool IsError{
+ get {return _error;}
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/OleAutBinder.cs b/src/mscorlib/src/System/OleAutBinder.cs
new file mode 100644
index 0000000000..1ed1e32ca9
--- /dev/null
+++ b/src/mscorlib/src/System/OleAutBinder.cs
@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// This class represents the Ole Automation binder.
+
+// #define DISPLAY_DEBUG_INFO
+
+namespace System {
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using Microsoft.Win32;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ // Made serializable in anticipation of this class eventually having state.
+ [Serializable]
+ internal class OleAutBinder : DefaultBinder
+ {
+ // ChangeType
+ // This binder uses OLEAUT to change the type of the variant.
+ [System.Security.SecuritySafeCritical] // overrides transparent member
+ public override Object ChangeType(Object value, Type type, CultureInfo cultureInfo)
+ {
+ Variant myValue = new Variant(value);
+ if (cultureInfo == null)
+ cultureInfo = CultureInfo.CurrentCulture;
+
+ #if DISPLAY_DEBUG_INFO
+ Console.WriteLine("In OleAutBinder::ChangeType converting variant of type: {0} to type: {1}", myValue.VariantType, type.Name);
+ #endif
+
+ if (type.IsByRef)
+ {
+ #if DISPLAY_DEBUG_INFO
+ Console.WriteLine("Stripping byref from the type to convert to.");
+ #endif
+ type = type.GetElementType();
+ }
+
+ // If we are trying to convert from an object to another type then we don't
+ // need the OLEAUT change type, we can just use the normal COM+ mechanisms.
+ if (!type.IsPrimitive && type.IsInstanceOfType(value))
+ {
+ #if DISPLAY_DEBUG_INFO
+ Console.WriteLine("Source variant can be assigned to destination type");
+ #endif
+ return value;
+ }
+
+ Type srcType = value.GetType();
+
+ // Handle converting primitives to enums.
+ if (type.IsEnum && srcType.IsPrimitive)
+ {
+ #if DISPLAY_DEBUG_INFO
+ Console.WriteLine("Converting primitive to enum");
+ #endif
+ return Enum.Parse(type, value.ToString());
+ }
+
+#if !FEATURE_CORECLR
+ // Special case the convertion from DBNull.
+ if (srcType == typeof(DBNull))
+ {
+ // The requested type is a DBNull so no convertion is required.
+ if (type == typeof(DBNull))
+ return value;
+
+ // Visual J++ supported converting from DBNull to null so customers
+ // have requested (via a CDCR) that DBNull be convertible to null.
+ // We don't however allow this when converting to a value class, since null
+ // doesn't make sense for these, or to object since this would change existing
+ // semantics.
+ if ((type.IsClass && type != typeof(Object)) || type.IsInterface)
+ return null;
+ }
+#endif //!FEATURE_CORECLR
+
+ // Use the OA variant lib to convert primitive types.
+ try
+ {
+#if DISPLAY_DEBUG_INFO
+ Console.WriteLine("Using OAVariantLib.ChangeType() to do the conversion");
+#endif
+ // Specify the LocalBool flag to have BOOL values converted to local language rather
+ // than 0 or -1.
+ Object RetObj = OAVariantLib.ChangeType(myValue, type, OAVariantLib.LocalBool, cultureInfo).ToObject();
+
+#if DISPLAY_DEBUG_INFO
+ Console.WriteLine("Object returned from ChangeType is of type: " + RetObj.GetType().Name);
+#endif
+
+ return RetObj;
+ }
+#if DISPLAY_DEBUG_INFO
+ catch(NotSupportedException e)
+#else
+ catch(NotSupportedException)
+#endif
+ {
+#if DISPLAY_DEBUG_INFO
+ Console.Write("Exception thrown: ");
+ Console.WriteLine(e);
+#endif
+ throw new COMException(Environment.GetResourceString("Interop.COM_TypeMismatch"), unchecked((int)0x80020005));
+ }
+ }
+
+
+ }
+}
diff --git a/src/mscorlib/src/System/OperatingSystem.cs b/src/mscorlib/src/System/OperatingSystem.cs
new file mode 100644
index 0000000000..6955310acf
--- /dev/null
+++ b/src/mscorlib/src/System/OperatingSystem.cs
@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+namespace System {
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+
+ [ComVisible(true)]
+ [Serializable]
+ public sealed class OperatingSystem : ICloneable , ISerializable
+ {
+ private Version _version;
+ private PlatformID _platform;
+ private string _servicePack;
+ private string _versionString;
+
+ private OperatingSystem()
+ {
+ }
+
+ public OperatingSystem(PlatformID platform, Version version) : this(platform, version, null) {
+ }
+
+ internal OperatingSystem(PlatformID platform, Version version, string servicePack) {
+ if( platform < PlatformID.Win32S || platform > PlatformID.MacOSX) {
+ throw new ArgumentException(
+ Environment.GetResourceString("Arg_EnumIllegalVal", (int)platform),
+ "platform");
+ }
+
+ if ((Object) version == null)
+ throw new ArgumentNullException("version");
+ Contract.EndContractBlock();
+
+ _platform = platform;
+ _version = (Version) version.Clone();
+ _servicePack = servicePack;
+ }
+
+ private OperatingSystem(SerializationInfo info, StreamingContext context) {
+ SerializationInfoEnumerator enumerator = info.GetEnumerator();
+ while( enumerator.MoveNext()) {
+ switch( enumerator.Name) {
+ case "_version":
+ _version = (Version) info.GetValue("_version", typeof(Version));
+ break;
+ case "_platform":
+ _platform = (PlatformID) info.GetValue("_platform", typeof(PlatformID));
+ break;
+ case "_servicePack":
+ _servicePack = info.GetString("_servicePack");
+ break;
+ }
+ }
+
+ if (_version == null ) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_MissField", "_version"));
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if( info == null ) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ info.AddValue("_version", _version);
+ info.AddValue("_platform", _platform);
+ info.AddValue("_servicePack", _servicePack);
+ }
+
+ public PlatformID Platform {
+ get { return _platform; }
+ }
+
+ public string ServicePack {
+ get {
+ if( _servicePack == null) {
+ return string.Empty;
+ }
+
+ return _servicePack;
+ }
+ }
+
+ public Version Version {
+ get { return _version; }
+ }
+
+ public Object Clone() {
+ return new OperatingSystem(_platform,
+ _version, _servicePack );
+ }
+
+ public override String ToString() {
+ return VersionString;
+ }
+
+ public String VersionString {
+ get {
+ if(_versionString != null) {
+ return _versionString;
+ }
+
+ String os;
+ switch(_platform)
+ {
+ case PlatformID.Win32NT:
+ os = "Microsoft Windows NT ";
+ break;
+ case PlatformID.Win32Windows:
+ if ((_version.Major > 4) ||
+ ((_version.Major == 4) && (_version.Minor > 0)))
+ os = "Microsoft Windows 98 ";
+ else
+ os = "Microsoft Windows 95 ";
+ break;
+ case PlatformID.Win32S:
+ os = "Microsoft Win32S ";
+ break;
+ case PlatformID.WinCE:
+ os = "Microsoft Windows CE ";
+ break;
+ case PlatformID.MacOSX:
+ os = "Mac OS X ";
+ break;
+ default:
+ os = "<unknown> ";
+ break;
+ }
+
+ if( String.IsNullOrEmpty(_servicePack)) {
+ _versionString = os + _version.ToString();
+ }
+ else {
+ _versionString = os + _version.ToString(3) + " " + _servicePack;
+ }
+
+ return _versionString;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/OperationCanceledException.cs b/src/mscorlib/src/System/OperationCanceledException.cs
new file mode 100644
index 0000000000..14781f5653
--- /dev/null
+++ b/src/mscorlib/src/System/OperationCanceledException.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Exception for cancelled IO requests.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+using System.Threading;
+
+namespace System {
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class OperationCanceledException : SystemException
+ {
+ [NonSerialized]
+ private CancellationToken _cancellationToken;
+
+ public CancellationToken CancellationToken
+ {
+ get { return _cancellationToken;}
+ private set { _cancellationToken = value;}
+ }
+
+ public OperationCanceledException()
+ : base(Environment.GetResourceString("OperationCanceled")) {
+ SetErrorCode(__HResults.COR_E_OPERATIONCANCELED);
+ }
+
+ public OperationCanceledException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_OPERATIONCANCELED);
+ }
+
+ public OperationCanceledException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_OPERATIONCANCELED);
+ }
+
+
+ public OperationCanceledException(CancellationToken token)
+ :this()
+ {
+ CancellationToken = token;
+ }
+
+ public OperationCanceledException(String message, CancellationToken token)
+ : this(message)
+ {
+ CancellationToken = token;
+ }
+
+ public OperationCanceledException(String message, Exception innerException, CancellationToken token)
+ : this(message, innerException)
+ {
+ CancellationToken = token;
+ }
+
+ protected OperationCanceledException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/OutOfMemoryException.cs b/src/mscorlib/src/System/OutOfMemoryException.cs
new file mode 100644
index 0000000000..9bea0b46d7
--- /dev/null
+++ b/src/mscorlib/src/System/OutOfMemoryException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for OOM.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class OutOfMemoryException : SystemException {
+ public OutOfMemoryException()
+ : base(GetMessageFromNativeResources(ExceptionMessageKind.OutOfMemory)) {
+ SetErrorCode(__HResults.COR_E_OUTOFMEMORY);
+ }
+
+ public OutOfMemoryException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_OUTOFMEMORY);
+ }
+
+ public OutOfMemoryException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_OUTOFMEMORY);
+ }
+
+ protected OutOfMemoryException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/OverflowException.cs b/src/mscorlib/src/System/OverflowException.cs
new file mode 100644
index 0000000000..ab717fb065
--- /dev/null
+++ b/src/mscorlib/src/System/OverflowException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for Arthimatic Overflows.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class OverflowException : ArithmeticException {
+ public OverflowException()
+ : base(Environment.GetResourceString("Arg_OverflowException")) {
+ SetErrorCode(__HResults.COR_E_OVERFLOW);
+ }
+
+ public OverflowException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_OVERFLOW);
+ }
+
+ public OverflowException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_OVERFLOW);
+ }
+
+ protected OverflowException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/ParamArrayAttribute.cs b/src/mscorlib/src/System/ParamArrayAttribute.cs
new file mode 100644
index 0000000000..3a8e2e8302
--- /dev/null
+++ b/src/mscorlib/src/System/ParamArrayAttribute.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Attribute for multiple parameters.
+**
+**
+=============================================================================*/
+namespace System
+{
+//This class contains only static members and does not need to be serializable
+ [AttributeUsage (AttributeTargets.Parameter, Inherited=true, AllowMultiple=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ParamArrayAttribute : Attribute
+ {
+ public ParamArrayAttribute () {}
+ }
+}
diff --git a/src/mscorlib/src/System/ParamsArray.cs b/src/mscorlib/src/System/ParamsArray.cs
new file mode 100644
index 0000000000..ed8919c586
--- /dev/null
+++ b/src/mscorlib/src/System/ParamsArray.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace System
+{
+ internal struct ParamsArray
+ {
+ // Sentinel fixed-length arrays eliminate the need for a "count" field keeping this
+ // struct down to just 4 fields. These are only used for their "Length" property,
+ // that is, their elements are never set or referenced.
+ private static readonly object[] oneArgArray = new object[1];
+ private static readonly object[] twoArgArray = new object[2];
+ private static readonly object[] threeArgArray = new object[3];
+
+ private readonly object arg0;
+ private readonly object arg1;
+ private readonly object arg2;
+
+ // After construction, the first three elements of this array will never be accessed
+ // because the indexer will retrieve those values from arg0, arg1, and arg2.
+ private readonly object[] args;
+
+ public ParamsArray(object arg0)
+ {
+ this.arg0 = arg0;
+ this.arg1 = null;
+ this.arg2 = null;
+
+ // Always assign this.args to make use of its "Length" property
+ this.args = oneArgArray;
+ }
+
+ public ParamsArray(object arg0, object arg1)
+ {
+ this.arg0 = arg0;
+ this.arg1 = arg1;
+ this.arg2 = null;
+
+ // Always assign this.args to make use of its "Length" property
+ this.args = twoArgArray;
+ }
+
+ public ParamsArray(object arg0, object arg1, object arg2)
+ {
+ this.arg0 = arg0;
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+
+ // Always assign this.args to make use of its "Length" property
+ this.args = threeArgArray;
+ }
+
+ public ParamsArray(object[] args)
+ {
+ int len = args.Length;
+ this.arg0 = len > 0 ? args[0] : null;
+ this.arg1 = len > 1 ? args[1] : null;
+ this.arg2 = len > 2 ? args[2] : null;
+ this.args = args;
+ }
+
+ public int Length
+ {
+ get { return this.args.Length; }
+ }
+
+ public object this[int index]
+ {
+ get { return index == 0 ? this.arg0 : GetAtSlow(index); }
+ }
+
+ private object GetAtSlow(int index)
+ {
+ if (index == 1)
+ return this.arg1;
+ if (index == 2)
+ return this.arg2;
+ return this.args[index];
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ParseNumbers.cs b/src/mscorlib/src/System/ParseNumbers.cs
new file mode 100644
index 0000000000..01c2ae3019
--- /dev/null
+++ b/src/mscorlib/src/System/ParseNumbers.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Methods for Parsing numbers and Strings.
+** All methods are implemented in native.
+**
+**
+===========================================================*/
+namespace System {
+
+ //This class contains only static members and does not need to be serializable.
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ internal static class ParseNumbers {
+ internal const int PrintAsI1=0x40;
+ internal const int PrintAsI2=0x80;
+ internal const int PrintAsI4=0x100;
+ internal const int TreatAsUnsigned=0x200;
+ internal const int TreatAsI1=0x400;
+ internal const int TreatAsI2=0x800;
+ internal const int IsTight=0x1000;
+ internal const int NoSpace=0x2000;
+
+ //
+ //
+ // NATIVE METHODS
+ // For comments on these methods please see $\src\vm\COMUtilNative.cpp
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static long StringToLong(System.String s, int radix, int flags) {
+ return StringToLong(s,radix,flags, null);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public unsafe extern static long StringToLong(System.String s, int radix, int flags, int* currPos);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static long StringToLong(System.String s, int radix, int flags, ref int currPos) {
+ fixed(int * ppos = &currPos) {
+ return StringToLong( s, radix, flags, ppos);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static int StringToInt(System.String s, int radix, int flags) {
+ return StringToInt(s,radix,flags, null);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public unsafe extern static int StringToInt(System.String s, int radix, int flags, int* currPos);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static int StringToInt(System.String s, int radix, int flags, ref int currPos) {
+ fixed(int * ppos = &currPos) {
+ return StringToInt( s, radix, flags, ppos);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static String IntToString(int l, int radix, int width, char paddingChar, int flags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern static String LongToString(long l, int radix, int width, char paddingChar, int flags);
+ }
+}
diff --git a/src/mscorlib/src/System/PlatformID.cs b/src/mscorlib/src/System/PlatformID.cs
new file mode 100644
index 0000000000..57941996ee
--- /dev/null
+++ b/src/mscorlib/src/System/PlatformID.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Defines IDs for supported platforms
+**
+**
+===========================================================*/
+namespace System {
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum PlatformID
+ {
+ Win32S = 0,
+ Win32Windows = 1,
+ Win32NT = 2,
+ WinCE = 3,
+ Unix = 4,
+ Xbox = 5,
+ MacOSX = 6
+ }
+
+}
diff --git a/src/mscorlib/src/System/PlatformNotSupportedException.cs b/src/mscorlib/src/System/PlatformNotSupportedException.cs
new file mode 100644
index 0000000000..75d6d1d110
--- /dev/null
+++ b/src/mscorlib/src/System/PlatformNotSupportedException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: To handle features that don't run on particular platforms
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class PlatformNotSupportedException : NotSupportedException
+ {
+ public PlatformNotSupportedException()
+ : base(Environment.GetResourceString("Arg_PlatformNotSupported")) {
+ SetErrorCode(__HResults.COR_E_PLATFORMNOTSUPPORTED);
+ }
+
+ public PlatformNotSupportedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_PLATFORMNOTSUPPORTED);
+ }
+
+ public PlatformNotSupportedException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_PLATFORMNOTSUPPORTED);
+ }
+
+ protected PlatformNotSupportedException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Progress.cs b/src/mscorlib/src/System/Progress.cs
new file mode 100644
index 0000000000..8800c0322a
--- /dev/null
+++ b/src/mscorlib/src/System/Progress.cs
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Event-based implementation of IProgress<T>.
+**
+**
+===========================================================*/
+
+using System;
+using System.Threading;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ /// <summary>
+ /// Provides an IProgress{T} that invokes callbacks for each reported progress value.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of the progress report value.</typeparam>
+ /// <remarks>
+ /// Any handler provided to the constructor or event handlers registered with
+ /// the <see cref="ProgressChanged"/> event are invoked through a
+ /// <see cref="System.Threading.SynchronizationContext"/> instance captured
+ /// when the instance is constructed. If there is no current SynchronizationContext
+ /// at the time of construction, the callbacks will be invoked on the ThreadPool.
+ /// </remarks>
+ public class Progress<T> : IProgress<T>
+ {
+ /// <summary>The synchronization context captured upon construction. This will never be null.</summary>
+ private readonly SynchronizationContext m_synchronizationContext;
+ /// <summary>The handler specified to the constructor. This may be null.</summary>
+ private readonly Action<T> m_handler;
+ /// <summary>A cached delegate used to post invocation to the synchronization context.</summary>
+ private readonly SendOrPostCallback m_invokeHandlers;
+
+ /// <summary>Initializes the <see cref="Progress{T}"/>.</summary>
+ public Progress()
+ {
+ // Capture the current synchronization context. "current" is determined by CurrentNoFlow,
+ // which doesn't consider the sync ctx flown with an ExecutionContext, avoiding
+ // sync ctx reference identity issues where the sync ctx for one thread could be Current on another.
+ // If there is no current context, we use a default instance targeting the ThreadPool.
+ m_synchronizationContext = SynchronizationContext.CurrentNoFlow ?? ProgressStatics.DefaultContext;
+ Contract.Assert(m_synchronizationContext != null);
+ m_invokeHandlers = new SendOrPostCallback(InvokeHandlers);
+ }
+
+ /// <summary>Initializes the <see cref="Progress{T}"/> with the specified callback.</summary>
+ /// <param name="handler">
+ /// A handler to invoke for each reported progress value. This handler will be invoked
+ /// in addition to any delegates registered with the <see cref="ProgressChanged"/> event.
+ /// Depending on the <see cref="System.Threading.SynchronizationContext"/> instance captured by
+ /// the <see cref="Progress"/> at construction, it's possible that this handler instance
+ /// could be invoked concurrently with itself.
+ /// </param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="handler"/> is null (Nothing in Visual Basic).</exception>
+ public Progress(Action<T> handler) : this()
+ {
+ if (handler == null) throw new ArgumentNullException("handler");
+ m_handler = handler;
+ }
+
+ /// <summary>Raised for each reported progress value.</summary>
+ /// <remarks>
+ /// Handlers registered with this event will be invoked on the
+ /// <see cref="System.Threading.SynchronizationContext"/> captured when the instance was constructed.
+ /// </remarks>
+ public event EventHandler<T> ProgressChanged;
+
+ /// <summary>Reports a progress change.</summary>
+ /// <param name="value">The value of the updated progress.</param>
+ protected virtual void OnReport(T value)
+ {
+ // If there's no handler, don't bother going through the sync context.
+ // Inside the callback, we'll need to check again, in case
+ // an event handler is removed between now and then.
+ Action<T> handler = m_handler;
+ EventHandler<T> changedEvent = ProgressChanged;
+ if (handler != null || changedEvent != null)
+ {
+ // Post the processing to the sync context.
+ // (If T is a value type, it will get boxed here.)
+ m_synchronizationContext.Post(m_invokeHandlers, value);
+ }
+ }
+
+ /// <summary>Reports a progress change.</summary>
+ /// <param name="value">The value of the updated progress.</param>
+ void IProgress<T>.Report(T value) { OnReport(value); }
+
+ /// <summary>Invokes the action and event callbacks.</summary>
+ /// <param name="state">The progress value.</param>
+ private void InvokeHandlers(object state)
+ {
+ T value = (T)state;
+
+ Action<T> handler = m_handler;
+ EventHandler<T> changedEvent = ProgressChanged;
+
+ if (handler != null) handler(value);
+ if (changedEvent != null) changedEvent(this, value);
+ }
+ }
+
+ /// <summary>Holds static values for <see cref="Progress{T}"/>.</summary>
+ /// <remarks>This avoids one static instance per type T.</remarks>
+ internal static class ProgressStatics
+ {
+ /// <summary>A default synchronization context that targets the ThreadPool.</summary>
+ internal static readonly SynchronizationContext DefaultContext = new SynchronizationContext();
+ }
+}
diff --git a/src/mscorlib/src/System/Random.cs b/src/mscorlib/src/System/Random.cs
new file mode 100644
index 0000000000..adede6a101
--- /dev/null
+++ b/src/mscorlib/src/System/Random.cs
@@ -0,0 +1,214 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A random number generator.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class Random {
+ //
+ // Private Constants
+ //
+ private const int MBIG = Int32.MaxValue;
+ private const int MSEED = 161803398;
+ private const int MZ = 0;
+
+
+ //
+ // Member Variables
+ //
+ private int inext;
+ private int inextp;
+ private int[] SeedArray = new int[56];
+
+ //
+ // Public Constants
+ //
+
+ //
+ // Native Declarations
+ //
+
+ //
+ // Constructors
+ //
+
+ public Random()
+ : this(Environment.TickCount) {
+ }
+
+ public Random(int Seed) {
+ int ii;
+ int mj, mk;
+
+ //Initialize our Seed array.
+ int subtraction = (Seed == Int32.MinValue) ? Int32.MaxValue : Math.Abs(Seed);
+ mj = MSEED - subtraction;
+ SeedArray[55]=mj;
+ mk=1;
+ for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position.
+ ii = (21*i)%55;
+ SeedArray[ii]=mk;
+ mk = mj - mk;
+ if (mk<0) mk+=MBIG;
+ mj=SeedArray[ii];
+ }
+ for (int k=1; k<5; k++) {
+ for (int i=1; i<56; i++) {
+ SeedArray[i] -= SeedArray[1+(i+30)%55];
+ if (SeedArray[i]<0) SeedArray[i]+=MBIG;
+ }
+ }
+ inext=0;
+ inextp = 21;
+ Seed = 1;
+ }
+
+ //
+ // Package Private Methods
+ //
+
+ /*====================================Sample====================================
+ **Action: Return a new random number [0..1) and reSeed the Seed array.
+ **Returns: A double [0..1)
+ **Arguments: None
+ **Exceptions: None
+ ==============================================================================*/
+ protected virtual double Sample() {
+ //Including this division at the end gives us significantly improved
+ //random number distribution.
+ return (InternalSample()*(1.0/MBIG));
+ }
+
+ private int InternalSample() {
+ int retVal;
+ int locINext = inext;
+ int locINextp = inextp;
+
+ if (++locINext >=56) locINext=1;
+ if (++locINextp>= 56) locINextp = 1;
+
+ retVal = SeedArray[locINext]-SeedArray[locINextp];
+
+ if (retVal == MBIG) retVal--;
+ if (retVal<0) retVal+=MBIG;
+
+ SeedArray[locINext]=retVal;
+
+ inext = locINext;
+ inextp = locINextp;
+
+ return retVal;
+ }
+
+ //
+ // Public Instance Methods
+ //
+
+
+ /*=====================================Next=====================================
+ **Returns: An int [0..Int32.MaxValue)
+ **Arguments: None
+ **Exceptions: None.
+ ==============================================================================*/
+ public virtual int Next() {
+ return InternalSample();
+ }
+
+ private double GetSampleForLargeRange() {
+ // The distribution of double value returned by Sample
+ // is not distributed well enough for a large range.
+ // If we use Sample for a range [Int32.MinValue..Int32.MaxValue)
+ // We will end up getting even numbers only.
+
+ int result = InternalSample();
+ // Note we can't use addition here. The distribution will be bad if we do that.
+ bool negative = (InternalSample()%2 == 0) ? true : false; // decide the sign based on second sample
+ if( negative) {
+ result = -result;
+ }
+ double d = result;
+ d += (Int32.MaxValue - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1)
+ d /= 2*(uint)Int32.MaxValue - 1 ;
+ return d;
+ }
+
+
+ /*=====================================Next=====================================
+ **Returns: An int [minvalue..maxvalue)
+ **Arguments: minValue -- the least legal value for the Random number.
+ ** maxValue -- One greater than the greatest legal return value.
+ **Exceptions: None.
+ ==============================================================================*/
+ public virtual int Next(int minValue, int maxValue) {
+ if (minValue>maxValue) {
+ throw new ArgumentOutOfRangeException("minValue",Environment.GetResourceString("Argument_MinMaxValue", "minValue", "maxValue"));
+ }
+ Contract.EndContractBlock();
+
+ long range = (long)maxValue-minValue;
+ if( range <= (long)Int32.MaxValue) {
+ return ((int)(Sample() * range) + minValue);
+ }
+ else {
+ return (int)((long)(GetSampleForLargeRange() * range) + minValue);
+ }
+ }
+
+
+ /*=====================================Next=====================================
+ **Returns: An int [0..maxValue)
+ **Arguments: maxValue -- One more than the greatest legal return value.
+ **Exceptions: None.
+ ==============================================================================*/
+ public virtual int Next(int maxValue) {
+ if (maxValue<0) {
+ throw new ArgumentOutOfRangeException("maxValue", Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "maxValue"));
+ }
+ Contract.EndContractBlock();
+ return (int)(Sample()*maxValue);
+ }
+
+
+ /*=====================================Next=====================================
+ **Returns: A double [0..1)
+ **Arguments: None
+ **Exceptions: None
+ ==============================================================================*/
+ public virtual double NextDouble() {
+ return Sample();
+ }
+
+
+ /*==================================NextBytes===================================
+ **Action: Fills the byte array with random bytes [0..0x7f]. The entire array is filled.
+ **Returns:Void
+ **Arugments: buffer -- the array to be filled.
+ **Exceptions: None
+ ==============================================================================*/
+ public virtual void NextBytes(byte [] buffer){
+ if (buffer==null) throw new ArgumentNullException("buffer");
+ Contract.EndContractBlock();
+ for (int i=0; i<buffer.Length; i++) {
+ buffer[i]=(byte)(InternalSample()%(Byte.MaxValue+1));
+ }
+ }
+ }
+
+
+
+}
diff --git a/src/mscorlib/src/System/RankException.cs b/src/mscorlib/src/System/RankException.cs
new file mode 100644
index 0000000000..8639bba30e
--- /dev/null
+++ b/src/mscorlib/src/System/RankException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: For methods that are passed arrays with the wrong number of
+** dimensions.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class RankException : SystemException
+ {
+ public RankException()
+ : base(Environment.GetResourceString("Arg_RankException")) {
+ SetErrorCode(__HResults.COR_E_RANK);
+ }
+
+ public RankException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_RANK);
+ }
+
+ public RankException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_RANK);
+ }
+
+ protected RankException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/AmbiguousMatchException.cs b/src/mscorlib/src/System/Reflection/AmbiguousMatchException.cs
new file mode 100644
index 0000000000..6df371bd11
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/AmbiguousMatchException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// AmbiguousMatchException is thrown when binding to a method results in more
+//
+// than one method matching the binding criteria. This exception is thrown in
+// general when something is Ambiguous.
+//
+//
+//
+//
+namespace System.Reflection {
+ using System;
+ using SystemException = System.SystemException;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AmbiguousMatchException : SystemException
+ {
+
+ public AmbiguousMatchException()
+ : base(Environment.GetResourceString("RFLCT.Ambiguous")) {
+ SetErrorCode(__HResults.COR_E_AMBIGUOUSMATCH);
+ }
+
+ public AmbiguousMatchException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_AMBIGUOUSMATCH);
+ }
+
+ public AmbiguousMatchException(String message, Exception inner) : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_AMBIGUOUSMATCH);
+ }
+
+ internal AmbiguousMatchException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Assembly.cs b/src/mscorlib/src/System/Reflection/Assembly.cs
new file mode 100644
index 0000000000..479d6ca3a6
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Assembly.cs
@@ -0,0 +1,3013 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+**
+** Purpose: For Assembly-related stuff.
+**
+**
+=============================================================================*/
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Security;
+ using System.Security.Policy;
+ using System.Security.Permissions;
+ using System.IO;
+ using StringBuilder = System.Text.StringBuilder;
+ using System.Configuration.Assemblies;
+ using StackCrawlMark = System.Threading.StackCrawlMark;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using SecurityZone = System.Security.SecurityZone;
+ using IEvidenceFactory = System.Security.IEvidenceFactory;
+ using System.Runtime.Serialization;
+ using Microsoft.Win32;
+ using System.Threading;
+ using __HResults = System.__HResults;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate Module ModuleResolveEventHandler(Object sender, ResolveEventArgs e);
+
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Assembly))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ public abstract class Assembly : _Assembly, IEvidenceFactory, ICustomAttributeProvider, ISerializable
+ {
+#region constructors
+ protected Assembly() {}
+#endregion
+
+#region public static methods
+
+ public static String CreateQualifiedName(String assemblyName, String typeName)
+ {
+ return typeName + ", " + assemblyName;
+ }
+
+ public static Assembly GetAssembly(Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ Module m = type.Module;
+ if (m == null)
+ return null;
+ else
+ return m.Assembly;
+ }
+
+ public static bool operator ==(Assembly left, Assembly right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeAssembly || right is RuntimeAssembly)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Assembly left, Assembly right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object o)
+ {
+ return base.Equals(o);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ // Locate an assembly by the name of the file containing the manifest.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadFrom(String assemblyFile)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+#if FEATURE_WINDOWSPHONE
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_WindowsPhone", "Assembly.LoadFrom"));
+#else
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(
+ assemblyFile,
+ null, // securityEvidence
+ null, // hashValue
+ AssemblyHashAlgorithm.None,
+ false,// forIntrospection
+ false,// suppressSecurityChecks
+ ref stackMark);
+#endif // FEATURE_WINDOWSPHONE
+ }
+
+ // Locate an assembly for reflection by the name of the file containing the manifest.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly ReflectionOnlyLoadFrom(String assemblyFile)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(
+ assemblyFile,
+ null, //securityEvidence
+ null, //hashValue
+ AssemblyHashAlgorithm.None,
+ true, //forIntrospection
+ false, //suppressSecurityChecks
+ ref stackMark);
+ }
+
+ // Evidence is protected in Assembly.Load()
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadFrom(String assemblyFile,
+ Evidence securityEvidence)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(
+ assemblyFile,
+ securityEvidence,
+ null, // hashValue
+ AssemblyHashAlgorithm.None,
+ false,// forIntrospection);
+ false,// suppressSecurityChecks
+ ref stackMark);
+ }
+
+ // Evidence is protected in Assembly.Load()
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFrom which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadFrom(String assemblyFile,
+ Evidence securityEvidence,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(
+ assemblyFile,
+ securityEvidence,
+ hashValue,
+ hashAlgorithm,
+ false,
+ false,
+ ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadFrom(String assemblyFile,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(
+ assemblyFile,
+ null,
+ hashValue,
+ hashAlgorithm,
+ false,
+ false,
+ ref stackMark);
+ }
+
+#if FEATURE_CAS_POLICY
+ // Load an assembly into the LoadFrom context bypassing some security checks
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly UnsafeLoadFrom(string assemblyFile)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ return RuntimeAssembly.InternalLoadFrom(assemblyFile,
+ null, // securityEvidence
+ null, // hashValue
+ AssemblyHashAlgorithm.None,
+ false, // forIntrospection
+ true, // suppressSecurityChecks
+ ref stackMark);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // Locate an assembly by the long form of the assembly name.
+ // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890"
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(String assemblyString)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, false /*forIntrospection*/);
+ }
+
+ // Returns type from the assembly while keeping compatibility with Assembly.Load(assemblyString).GetType(typeName) for managed types.
+ // Calls Type.GetType for WinRT types.
+ // Note: Type.GetType fails for assembly names that start with weird characters like '['. By calling it for managed types we would
+ // break AppCompat.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static Type GetType_Compat(String assemblyString, String typeName)
+ {
+ // Normally we would get the stackMark only in public APIs. This is internal API, but it is AppCompat replacement of public API
+ // call Assembly.Load(assemblyString).GetType(typeName), therefore we take the stackMark here as well, to be fully compatible with
+ // the call sequence.
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ RuntimeAssembly assembly;
+ AssemblyName assemblyName = RuntimeAssembly.CreateAssemblyName(
+ assemblyString,
+ false /*forIntrospection*/,
+ out assembly);
+
+ if (assembly == null) {
+ if (assemblyName.ContentType == AssemblyContentType.WindowsRuntime) {
+ return Type.GetType(typeName + ", " + assemblyString, true /*throwOnError*/, false /*ignoreCase*/);
+ }
+
+ assembly = RuntimeAssembly.InternalLoadAssemblyName(
+ assemblyName, null, null, ref stackMark,
+ true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/);
+ }
+ return assembly.GetType(typeName, true /*throwOnError*/, false /*ignoreCase*/);
+ }
+
+ // Locate an assembly for reflection by the long form of the assembly name.
+ // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890"
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly ReflectionOnlyLoad(String assemblyString)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoad(assemblyString, null, ref stackMark, true /*forIntrospection*/);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static Assembly Load(String assemblyString, Evidence assemblySecurity)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoad(assemblyString, assemblySecurity, ref stackMark, false /*forIntrospection*/);
+ }
+
+ // Locate an assembly by its name. The name can be strong or
+ // weak. The assembly is loaded into the domain of the caller.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(AssemblyName assemblyRef)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+#if FEATURE_WINDOWSPHONE
+ if (assemblyRef != null && assemblyRef.CodeBase != null)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AssemblyLoadCodeBase"));
+ }
+#endif
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/);
+ }
+
+ // Locate an assembly by its name. The name can be strong or
+ // weak. The assembly is loaded into the domain of the caller.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static Assembly Load(AssemblyName assemblyRef, IntPtr ptrLoadContextBinder)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+#if FEATURE_WINDOWSPHONE
+ if (assemblyRef != null && assemblyRef.CodeBase != null)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AssemblyLoadCodeBase"));
+ }
+#endif
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, null, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/, ptrLoadContextBinder);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static Assembly Load(AssemblyName assemblyRef, Evidence assemblySecurity)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadAssemblyName(assemblyRef, assemblySecurity, null, ref stackMark, true /*thrownOnFileNotFound*/, false /*forIntrospection*/, false /*suppressSecurityChecks*/);
+ }
+
+#if FEATURE_FUSION
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadWithPartialName(String partialName)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.LoadWithPartialNameInternal(partialName, null, ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method has been deprecated. Please use Assembly.Load() instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly LoadWithPartialName(String partialName, Evidence securityEvidence)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.LoadWithPartialNameInternal(partialName, securityEvidence, ref stackMark);
+ }
+#endif // FEATURE_FUSION
+
+ // Loads the assembly with a COFF based IMAGE containing
+ // an emitted assembly. The assembly is loaded into the domain
+ // of the caller.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(byte[] rawAssembly)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadByteArraySupported();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(
+ rawAssembly,
+ null, // symbol store
+ null, // evidence
+ ref stackMark,
+ false, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ // Loads the assembly for reflection with a COFF based IMAGE containing
+ // an emitted assembly. The assembly is loaded into the domain
+ // of the caller.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly ReflectionOnlyLoad(byte[] rawAssembly)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+
+ AppDomain.CheckReflectionOnlyLoadSupported();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(
+ rawAssembly,
+ null, // symbol store
+ null, // evidence
+ ref stackMark,
+ true, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ // Loads the assembly with a COFF based IMAGE containing
+ // an emitted assembly. The assembly is loaded into the domain
+ // of the caller. The second parameter is the raw bytes
+ // representing the symbol store that matches the assembly.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadByteArraySupported();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(
+ rawAssembly,
+ rawSymbolStore,
+ null, // evidence
+ ref stackMark,
+ false, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+
+ // Load an assembly from a byte array, controlling where the grant set of this assembly is
+ // propigated from.
+ [SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.NoInlining)] // Due to the stack crawl mark
+ public static Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore,
+ SecurityContextSource securityContextSource)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadByteArraySupported();
+
+ if (securityContextSource < SecurityContextSource.CurrentAppDomain ||
+ securityContextSource > SecurityContextSource.CurrentAssembly)
+ {
+ throw new ArgumentOutOfRangeException("securityContextSource");
+ }
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(rawAssembly,
+ rawSymbolStore,
+ null, // evidence
+ ref stackMark,
+ false, // fIntrospection
+ securityContextSource);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of Load which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static Assembly Load(byte[] rawAssembly,
+ byte[] rawSymbolStore,
+ Evidence securityEvidence)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadByteArraySupported();
+
+ if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ // A zone of MyComputer could not have been used to sandbox, so for compatibility we do not
+ // throw an exception when we see it.
+ Zone zone = securityEvidence.GetHostEvidence<Zone>();
+ if (zone == null || zone.SecurityZone != SecurityZone.MyComputer)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+ }
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.nLoadImage(
+ rawAssembly,
+ rawSymbolStore,
+ securityEvidence,
+ ref stackMark,
+ false, // fIntrospection
+ SecurityContextSource.CurrentAssembly);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Assembly LoadFile(String path)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadFileSupported();
+
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand();
+ return RuntimeAssembly.nLoadFile(path, null);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlEvidence)]
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. Please use an overload of LoadFile which does not take an Evidence parameter. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static Assembly LoadFile(String path,
+ Evidence securityEvidence)
+ {
+
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ AppDomain.CheckLoadFileSupported();
+
+ if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, path).Demand();
+ return RuntimeAssembly.nLoadFile(path, securityEvidence);
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(Stream assemblyStream, Stream pdbStream)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadFromStream(assemblyStream, pdbStream, ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly Load(Stream assemblyStream)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null);
+ Contract.Ensures(!Contract.Result<Assembly>().ReflectionOnly);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.InternalLoadFromStream(assemblyStream, null, ref stackMark);
+ }
+#endif //FEATURE_CORECLR
+
+ /*
+ * Get the assembly that the current code is running from.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly GetExecutingAssembly()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Assembly GetCallingAssembly()
+ {
+ // LookForMyCallersCaller is not guarantee to return the correct stack frame
+ // because of inlining, tail calls, etc. As a result GetCallingAssembly is not
+ // ganranteed to return the correct result. We should document it as such.
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
+ return RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Assembly GetEntryAssembly() {
+ AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
+ if (domainManager == null)
+ domainManager = new AppDomainManager();
+ return domainManager.EntryAssembly;
+ }
+
+#endregion // public static methods
+
+#region public methods
+ public virtual event ModuleResolveEventHandler ModuleResolve
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ add
+ {
+ throw new NotImplementedException();
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ remove
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual String CodeBase
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual String EscapedCodeBase
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return AssemblyName.EscapeCodeBase(CodeBase);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public virtual AssemblyName GetName()
+ {
+ return GetName(false);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public virtual AssemblyName GetName(bool copiedName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual String FullName
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual MethodInfo EntryPoint
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+#if !FEATURE_CORECLR
+ Type _Assembly.GetType()
+ {
+ return base.GetType();
+ }
+#endif
+
+ public virtual Type GetType(String name)
+ {
+ return GetType(name, false, false);
+ }
+
+ public virtual Type GetType(String name, bool throwOnError)
+ {
+ return GetType(name, throwOnError, false);
+ }
+
+ public virtual Type GetType(String name, bool throwOnError, bool ignoreCase)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual IEnumerable<Type> ExportedTypes
+ {
+ get
+ {
+ return GetExportedTypes();
+ }
+ }
+
+ public virtual Type[] GetExportedTypes()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual IEnumerable<TypeInfo> DefinedTypes
+ {
+ get
+ {
+ Type[] types = GetTypes();
+
+ TypeInfo[] typeinfos = new TypeInfo[types.Length];
+
+ for (int i = 0; i < types.Length; i++)
+ {
+
+ TypeInfo typeinfo = types[i].GetTypeInfo();
+ if (typeinfo == null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NoTypeInfo", types[i].FullName));
+
+ typeinfos[i] = typeinfo;
+ }
+
+ return typeinfos;
+ }
+ }
+
+ public virtual Type[] GetTypes()
+ {
+ Module[] m = GetModules(false);
+
+ int iNumModules = m.Length;
+ int iFinalLength = 0;
+ Type[][] ModuleTypes = new Type[iNumModules][];
+
+ for (int i = 0; i < iNumModules; i++)
+ {
+ ModuleTypes[i] = m[i].GetTypes();
+ iFinalLength += ModuleTypes[i].Length;
+ }
+
+ int iCurrent = 0;
+ Type[] ret = new Type[iFinalLength];
+ for (int i = 0; i < iNumModules; i++)
+ {
+ int iLength = ModuleTypes[i].Length;
+ Array.Copy(ModuleTypes[i], 0, ret, iCurrent, iLength);
+ iCurrent += iLength;
+ }
+
+ return ret;
+ }
+
+ // Load a resource based on the NameSpace of the type.
+ public virtual Stream GetManifestResourceStream(Type type, String name)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Stream GetManifestResourceStream(String name)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Assembly GetSatelliteAssembly(CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+
+ // Useful for binding to a very specific version of a satellite assembly
+ public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version version)
+ {
+ throw new NotImplementedException();
+ }
+
+#if FEATURE_CAS_POLICY
+ public virtual Evidence Evidence
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual PermissionSet PermissionSet
+ {
+ // SecurityCritical because permissions can contain sensitive information such as paths
+ [SecurityCritical]
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public bool IsFullyTrusted
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ return PermissionSet.IsUnrestricted();
+ }
+ }
+
+ public virtual SecurityRuleSet SecurityRuleSet
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+#endif // FEATURE_CAS_POLICY
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotImplementedException();
+ }
+
+ [ComVisible(false)]
+ public virtual Module ManifestModule
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeAssembly rtAssembly = this as RuntimeAssembly;
+ if (rtAssembly != null)
+ return rtAssembly.ManifestModule;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return GetCustomAttributesData();
+ }
+ }
+ public virtual Object[] GetCustomAttributes(bool inherit)
+ {
+ Contract.Ensures(Contract.Result<Object[]>() != null);
+ throw new NotImplementedException();
+ }
+
+ public virtual Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ Contract.Ensures(Contract.Result<Object[]>() != null);
+ throw new NotImplementedException();
+ }
+
+ public virtual bool IsDefined(Type attributeType, bool inherit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ throw new NotImplementedException();
+ }
+
+ // To not break compatibility with the V1 _Assembly interface we need to make this
+ // new member ComVisible(false).
+ [ComVisible(false)]
+ public virtual bool ReflectionOnly
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+#if FEATURE_MULTIMODULE_ASSEMBLIES
+
+ public Module LoadModule(String moduleName,
+ byte[] rawModule)
+ {
+ return LoadModule(moduleName, rawModule, null);
+ }
+
+ public virtual Module LoadModule(String moduleName,
+ byte[] rawModule,
+ byte[] rawSymbolStore)
+ {
+ throw new NotImplementedException();
+ }
+#endif //FEATURE_MULTIMODULE_ASSEMBLIES
+
+ //
+ // Locates a type from this assembly and creates an instance of it using
+ // the system activator.
+ //
+ public Object CreateInstance(String typeName)
+ {
+ return CreateInstance(typeName,
+ false, // ignore case
+ BindingFlags.Public | BindingFlags.Instance,
+ null, // binder
+ null, // args
+ null, // culture
+ null); // activation attributes
+ }
+
+ public Object CreateInstance(String typeName,
+ bool ignoreCase)
+ {
+ return CreateInstance(typeName,
+ ignoreCase,
+ BindingFlags.Public | BindingFlags.Instance,
+ null, // binder
+ null, // args
+ null, // culture
+ null); // activation attributes
+ }
+
+ public virtual Object CreateInstance(String typeName,
+ bool ignoreCase,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Object[] args,
+ CultureInfo culture,
+ Object[] activationAttributes)
+ {
+ Type t = GetType(typeName, false, ignoreCase);
+ if (t == null) return null;
+ return Activator.CreateInstance(t,
+ bindingAttr,
+ binder,
+ args,
+ culture,
+ activationAttributes);
+ }
+
+ public virtual IEnumerable<Module> Modules
+ {
+ get
+ {
+ return GetLoadedModules(true);
+ }
+ }
+
+ public Module[] GetLoadedModules()
+ {
+ return GetLoadedModules(false);
+ }
+
+ public virtual Module[] GetLoadedModules(bool getResourceModules)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Module[] GetModules()
+ {
+ return GetModules(false);
+ }
+
+ public virtual Module[] GetModules(bool getResourceModules)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Module GetModule(String name)
+ {
+ throw new NotImplementedException();
+ }
+
+ // Returns the file in the File table of the manifest that matches the
+ // given name. (Name should not include path.)
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public virtual FileStream GetFile(String name)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual FileStream[] GetFiles()
+ {
+ return GetFiles(false);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public virtual FileStream[] GetFiles(bool getResourceModules)
+ {
+ throw new NotImplementedException();
+ }
+
+ // Returns the names of all the resources
+ public virtual String[] GetManifestResourceNames()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual AssemblyName[] GetReferencedAssemblies()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual ManifestResourceInfo GetManifestResourceInfo(String resourceName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override String ToString()
+ {
+ String displayName = FullName;
+ if (displayName == null)
+ return base.ToString();
+ else
+ return displayName;
+ }
+
+ public virtual String Location
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ // To not break compatibility with the V1 _Assembly interface we need to make this
+ // new member ComVisible(false).
+ [ComVisible(false)]
+ public virtual String ImageRuntimeVersion
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ /*
+ Returns true if the assembly was loaded from the global assembly cache.
+ */
+ public virtual bool GlobalAssemblyCache
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ [ComVisible(false)]
+ public virtual Int64 HostContext
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeAssembly rtAssembly = this as RuntimeAssembly;
+ if (rtAssembly != null)
+ return rtAssembly.HostContext;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual bool IsDynamic
+ {
+ get
+ {
+ return false;
+ }
+ }
+#endregion // public methods
+
+ }
+
+ // Keep this in sync with LOADCTX_TYPE defined in fusionpriv.idl
+ internal enum LoadContext
+ {
+ DEFAULT,
+ LOADFROM,
+ UNKNOWN,
+ HOSTED,
+ }
+
+ [Serializable]
+ internal class RuntimeAssembly : Assembly
+#if !FEATURE_CORECLR
+ , ICustomQueryInterface
+#endif
+ {
+#if !FEATURE_CORECLR
+#region ICustomQueryInterface
+ [System.Security.SecurityCritical]
+ CustomQueryInterfaceResult ICustomQueryInterface.GetInterface([In]ref Guid iid, out IntPtr ppv)
+ {
+ if (iid == typeof(NativeMethods.IDispatch).GUID)
+ {
+ ppv = Marshal.GetComInterfaceForObject(this, typeof(_Assembly));
+ return CustomQueryInterfaceResult.Handled;
+ }
+
+ ppv = IntPtr.Zero;
+ return CustomQueryInterfaceResult.NotHandled;
+ }
+#endregion
+#endif // !FEATURE_CORECLR
+
+#if FEATURE_APPX
+ // The highest byte is the flags and the lowest 3 bytes are
+ // the cached ctor token of [DynamicallyInvocableAttribute].
+ private enum ASSEMBLY_FLAGS : uint
+ {
+ ASSEMBLY_FLAGS_UNKNOWN = 0x00000000,
+ ASSEMBLY_FLAGS_INITIALIZED = 0x01000000,
+ ASSEMBLY_FLAGS_FRAMEWORK = 0x02000000,
+ ASSEMBLY_FLAGS_SAFE_REFLECTION = 0x04000000,
+ ASSEMBLY_FLAGS_TOKEN_MASK = 0x00FFFFFF,
+ }
+#endif // FEATURE_APPX
+
+ private const uint COR_E_LOADING_REFERENCE_ASSEMBLY = 0x80131058U;
+
+ internal RuntimeAssembly() { throw new NotSupportedException(); }
+
+#region private data members
+ [method: System.Security.SecurityCritical]
+ private event ModuleResolveEventHandler _ModuleResolve;
+ private string m_fullname;
+ private object m_syncRoot; // Used to keep collectible types alive and as the syncroot for reflection.emit
+ private IntPtr m_assembly; // slack for ptr datum on unmanaged side
+
+#if FEATURE_APPX
+ private ASSEMBLY_FLAGS m_flags;
+#endif
+#endregion
+
+#if FEATURE_APPX
+ internal int InvocableAttributeCtorToken
+ {
+ get
+ {
+ int token = (int)(Flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_TOKEN_MASK);
+
+ return token | (int)MetadataTokenType.MethodDef;
+ }
+ }
+
+ private ASSEMBLY_FLAGS Flags
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if ((m_flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_INITIALIZED) == 0)
+ {
+ ASSEMBLY_FLAGS flags = ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_UNKNOWN;
+
+#if FEATURE_CORECLR
+ flags |= ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION;
+#else
+ if (RuntimeAssembly.IsFrameworkAssembly(GetName()))
+ {
+ flags |= ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION;
+
+ foreach (string name in s_unsafeFrameworkAssemblyNames)
+ {
+ if (String.Compare(GetSimpleName(), name, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ flags &= ~ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION;
+ break;
+ }
+ }
+
+ // Each blessed API will be annotated with a "__DynamicallyInvokableAttribute".
+ // This "__DynamicallyInvokableAttribute" is a type defined in its own assembly.
+ // So the ctor is always a MethodDef and the type a TypeDef.
+ // We cache this ctor MethodDef token for faster custom attribute lookup.
+ // If this attribute type doesn't exist in the assembly, it means the assembly
+ // doesn't contain any blessed APIs.
+ Type invocableAttribute = GetType("__DynamicallyInvokableAttribute", false);
+ if (invocableAttribute != null)
+ {
+ Contract.Assert(((MetadataToken)invocableAttribute.MetadataToken).IsTypeDef);
+
+ ConstructorInfo ctor = invocableAttribute.GetConstructor(Type.EmptyTypes);
+ Contract.Assert(ctor != null);
+
+ int token = ctor.MetadataToken;
+ Contract.Assert(((MetadataToken)token).IsMethodDef);
+
+ flags |= (ASSEMBLY_FLAGS)token & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_TOKEN_MASK;
+ }
+ }
+ else if (IsDesignerBindingContext())
+ {
+ flags = ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION;
+ }
+#endif
+
+ m_flags = flags | ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_INITIALIZED;
+ }
+
+ return m_flags;
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ internal object SyncRoot
+ {
+ get
+ {
+ if (m_syncRoot == null)
+ {
+ Interlocked.CompareExchange<object>(ref m_syncRoot, new object(), null);
+ }
+ return m_syncRoot;
+ }
+ }
+
+ public override event ModuleResolveEventHandler ModuleResolve
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ add
+ {
+ _ModuleResolve += value;
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ remove
+ {
+ _ModuleResolve -= value;
+ }
+ }
+
+ private const String s_localFilePrefix = "file:";
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetCodeBase(RuntimeAssembly assembly,
+ bool copiedName,
+ StringHandleOnStack retString);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal String GetCodeBase(bool copiedName)
+ {
+ String codeBase = null;
+ GetCodeBase(GetNativeHandle(), copiedName, JitHelpers.GetStringHandleOnStack(ref codeBase));
+ return codeBase;
+ }
+
+ public override String CodeBase
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ get {
+ String codeBase = GetCodeBase(false);
+ VerifyCodeBaseDiscovery(codeBase);
+ return codeBase;
+ }
+ }
+
+ internal RuntimeAssembly GetNativeHandle()
+ {
+ return this;
+ }
+
+ // If the assembly is copied before it is loaded, the codebase will be set to the
+ // actual file loaded if copiedName is true. If it is false, then the original code base
+ // is returned.
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override AssemblyName GetName(bool copiedName)
+ {
+ AssemblyName an = new AssemblyName();
+
+ String codeBase = GetCodeBase(copiedName);
+ VerifyCodeBaseDiscovery(codeBase);
+
+ an.Init(GetSimpleName(),
+ GetPublicKey(),
+ null, // public key token
+ GetVersion(),
+ GetLocale(),
+ GetHashAlgorithm(),
+ AssemblyVersionCompatibility.SameMachine,
+ codeBase,
+ GetFlags() | AssemblyNameFlags.PublicKey,
+ null); // strong name key pair
+
+ PortableExecutableKinds pek;
+ ImageFileMachine ifm;
+
+ Module manifestModule = ManifestModule;
+ if (manifestModule != null)
+ {
+ if (manifestModule.MDStreamVersion > 0x10000)
+ {
+ ManifestModule.GetPEKind(out pek, out ifm);
+ an.SetProcArchIndex(pek,ifm);
+ }
+ }
+ return an;
+ }
+
+#if FEATURE_APTCA
+ // This method is called from the VM when creating conditional APTCA exceptions, in order to include
+ // the text which must be added to the partial trust visible assembly list
+ [SecurityCritical]
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+ private string GetNameForConditionalAptca()
+ {
+ AssemblyName assemblyName = GetName();
+ return assemblyName.GetNameWithPublicKey();
+
+ }
+#endif // FEATURE_APTCA
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetFullName(RuntimeAssembly assembly, StringHandleOnStack retString);
+
+ public override String FullName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ // If called by Object.ToString(), return val may be NULL.
+ if (m_fullname == null)
+ {
+ string s = null;
+ GetFullName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref s));
+ Interlocked.CompareExchange<string>(ref m_fullname, s, null);
+ }
+
+ return m_fullname;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetEntryPoint(RuntimeAssembly assembly, ObjectHandleOnStack retMethod);
+
+ public override MethodInfo EntryPoint
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ IRuntimeMethodInfo methodHandle = null;
+ GetEntryPoint(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref methodHandle));
+
+ if (methodHandle == null)
+ return null;
+
+ return (MethodInfo)RuntimeType.GetMethodBase(methodHandle);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetType(RuntimeAssembly assembly,
+ String name,
+ bool throwOnError,
+ bool ignoreCase,
+ ObjectHandleOnStack type,
+ ObjectHandleOnStack keepAlive);
+
+ [System.Security.SecuritySafeCritical]
+ public override Type GetType(String name, bool throwOnError, bool ignoreCase)
+ {
+ // throw on null strings regardless of the value of "throwOnError"
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ RuntimeType type = null;
+ Object keepAlive = null;
+ GetType(GetNativeHandle(), name, throwOnError, ignoreCase, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive));
+ GC.KeepAlive(keepAlive);
+
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static void GetForwardedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetExportedTypes(RuntimeAssembly assembly, ObjectHandleOnStack retTypes);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetExportedTypes()
+ {
+ Type[] types = null;
+ GetExportedTypes(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types));
+ return types;
+ }
+
+ public override IEnumerable<TypeInfo> DefinedTypes
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ List<RuntimeType> rtTypes = new List<RuntimeType>();
+
+ RuntimeModule[] modules = GetModulesInternal(true, false);
+
+ for (int i = 0; i < modules.Length; i++)
+ {
+ rtTypes.AddRange(modules[i].GetDefinedTypes());
+ }
+
+ return rtTypes.ToArray();
+ }
+ }
+
+ // Load a resource based on the NameSpace of the type.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Stream GetManifestResourceStream(Type type, String name)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return GetManifestResourceStream(type, name, false, ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Stream GetManifestResourceStream(String name)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return GetManifestResourceStream(name, ref stackMark, false);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetEvidence(RuntimeAssembly assembly, ObjectHandleOnStack retEvidence);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static SecurityRuleSet GetSecurityRuleSet(RuntimeAssembly assembly);
+
+ public override Evidence Evidence
+ {
+ [SecuritySafeCritical]
+ [SecurityPermissionAttribute( SecurityAction.Demand, ControlEvidence = true )]
+ get
+ {
+ Evidence evidence = EvidenceNoDemand;
+ return evidence.Clone();
+ }
+ }
+
+ internal Evidence EvidenceNoDemand
+ {
+ [SecurityCritical]
+ get
+ {
+ Evidence evidence = null;
+ GetEvidence(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref evidence));
+ return evidence;
+ }
+ }
+
+ public override PermissionSet PermissionSet
+ {
+ [SecurityCritical]
+ get
+ {
+ PermissionSet grantSet = null;
+ PermissionSet deniedSet = null;
+
+ GetGrantSet(out grantSet, out deniedSet);
+
+ if (grantSet != null)
+ {
+ return grantSet.Copy();
+ }
+ else
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ }
+ }
+
+ public override SecurityRuleSet SecurityRuleSet
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ return GetSecurityRuleSet(GetNativeHandle());
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+
+ Contract.EndContractBlock();
+
+ UnitySerializationHolder.GetUnitySerializationInfo(info,
+ UnitySerializationHolder.AssemblyUnity,
+ this.FullName,
+ this);
+ }
+
+ public override Module ManifestModule
+ {
+ get
+ {
+ // We don't need to return the "external" ModuleBuilder because
+ // it is meant to be read-only
+ return RuntimeAssembly.GetManifestModule(GetNativeHandle());
+ }
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"caType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static RuntimeAssembly InternalLoadFrom(String assemblyFile,
+ Evidence securityEvidence,
+ byte[] hashValue,
+ AssemblyHashAlgorithm hashAlgorithm,
+ bool forIntrospection,
+ bool suppressSecurityChecks,
+ ref StackCrawlMark stackMark)
+ {
+ if (assemblyFile == null)
+ throw new ArgumentNullException("assemblyFile");
+
+ Contract.EndContractBlock();
+
+#if FEATURE_CAS_POLICY
+ if (securityEvidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+ AssemblyName an = new AssemblyName();
+ an.CodeBase = assemblyFile;
+ an.SetHashControl(hashValue, hashAlgorithm);
+ // The stack mark is used for MDA filtering
+ return InternalLoadAssemblyName(an, securityEvidence, null, ref stackMark, true /*thrownOnFileNotFound*/, forIntrospection, suppressSecurityChecks);
+ }
+
+ // Wrapper function to wrap the typical use of InternalLoad.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly InternalLoad(String assemblyString,
+ Evidence assemblySecurity,
+ ref StackCrawlMark stackMark,
+ bool forIntrospection)
+ {
+ return InternalLoad(assemblyString, assemblySecurity, ref stackMark, IntPtr.Zero, forIntrospection);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static RuntimeAssembly InternalLoad(String assemblyString,
+ Evidence assemblySecurity,
+ ref StackCrawlMark stackMark,
+ IntPtr pPrivHostBinder,
+ bool forIntrospection)
+ {
+ RuntimeAssembly assembly;
+ AssemblyName an = CreateAssemblyName(assemblyString, forIntrospection, out assembly);
+
+ if (assembly != null) {
+ // The assembly was returned from ResolveAssemblyEvent
+ return assembly;
+ }
+
+ return InternalLoadAssemblyName(an, assemblySecurity, null, ref stackMark,
+ pPrivHostBinder,
+ true /*thrownOnFileNotFound*/, forIntrospection, false /* suppressSecurityChecks */);
+ }
+
+ // Creates AssemblyName. Fills assembly if AssemblyResolve event has been raised.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static AssemblyName CreateAssemblyName(
+ String assemblyString,
+ bool forIntrospection,
+ out RuntimeAssembly assemblyFromResolveEvent)
+ {
+ if (assemblyString == null)
+ throw new ArgumentNullException("assemblyString");
+ Contract.EndContractBlock();
+
+ if ((assemblyString.Length == 0) ||
+ (assemblyString[0] == '\0'))
+ throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
+
+ if (forIntrospection)
+ AppDomain.CheckReflectionOnlyLoadSupported();
+
+ AssemblyName an = new AssemblyName();
+
+ an.Name = assemblyString;
+ an.nInit(out assemblyFromResolveEvent, forIntrospection, true);
+
+ return an;
+ }
+
+ // Wrapper function to wrap the typical use of InternalLoadAssemblyName.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly InternalLoadAssemblyName(
+ AssemblyName assemblyRef,
+ Evidence assemblySecurity,
+ RuntimeAssembly reqAssembly,
+ ref StackCrawlMark stackMark,
+ bool throwOnFileNotFound,
+ bool forIntrospection,
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder = default(IntPtr))
+ {
+ return InternalLoadAssemblyName(assemblyRef, assemblySecurity, reqAssembly, ref stackMark, IntPtr.Zero, true /*throwOnError*/, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly InternalLoadAssemblyName(
+ AssemblyName assemblyRef,
+ Evidence assemblySecurity,
+ RuntimeAssembly reqAssembly,
+ ref StackCrawlMark stackMark,
+ IntPtr pPrivHostBinder,
+ bool throwOnFileNotFound,
+ bool forIntrospection,
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder = default(IntPtr))
+ {
+
+ if (assemblyRef == null)
+ throw new ArgumentNullException("assemblyRef");
+ Contract.EndContractBlock();
+
+ if (assemblyRef.CodeBase != null)
+ {
+ AppDomain.CheckLoadFromSupported();
+ }
+
+ assemblyRef = (AssemblyName)assemblyRef.Clone();
+#if FEATURE_VERSIONING
+ if (!forIntrospection &&
+ (assemblyRef.ProcessorArchitecture != ProcessorArchitecture.None)) {
+ // PA does not have a semantics for by-name binds for execution
+ assemblyRef.ProcessorArchitecture = ProcessorArchitecture.None;
+ }
+#endif
+
+ if (assemblySecurity != null)
+ {
+#if FEATURE_CAS_POLICY
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ if (!suppressSecurityChecks)
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+#pragma warning restore 618
+ }
+ }
+
+
+ String codeBase = VerifyCodeBase(assemblyRef.CodeBase);
+ if (codeBase != null && !suppressSecurityChecks) {
+
+ if (String.Compare( codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) != 0) {
+#if FEATURE_FUSION // Of all the binders, Fusion is the only one that understands Web locations
+ IPermission perm = CreateWebPermission( assemblyRef.EscapedCodeBase );
+ perm.Demand();
+#else
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "assemblyRef.CodeBase");
+#endif
+ }
+ else {
+ System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true );
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read , urlString.GetFileName() ).Demand();
+ }
+ }
+
+ return nLoad(assemblyRef, codeBase, assemblySecurity, reqAssembly, ref stackMark,
+ pPrivHostBinder,
+ throwOnFileNotFound, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
+ }
+
+ // These are the framework assemblies that does reflection invocation
+ // on behalf of user code. We allow framework code to invoke non-W8P
+ // framework APIs but don't want user code to gain that privilege
+ // through these assemblies. So we blaklist them.
+ static string[] s_unsafeFrameworkAssemblyNames = new string[] {
+ "System.Reflection.Context",
+ "Microsoft.VisualBasic"
+ };
+
+#if FEATURE_APPX
+ [System.Security.SecuritySafeCritical]
+ internal bool IsFrameworkAssembly()
+ {
+ ASSEMBLY_FLAGS flags = Flags;
+ return (flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_FRAMEWORK) != 0;
+ }
+
+ // Returns true if we want to allow this assembly to invoke non-W8P
+ // framework APIs through reflection.
+ internal bool IsSafeForReflection()
+ {
+ ASSEMBLY_FLAGS flags = Flags;
+ return (flags & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_SAFE_REFLECTION) != 0;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private bool IsDesignerBindingContext()
+ {
+ return RuntimeAssembly.nIsDesignerBindingContext(this);
+ }
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static bool nIsDesignerBindingContext(RuntimeAssembly assembly);
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern RuntimeAssembly _nLoad(AssemblyName fileName,
+ String codeBase,
+ Evidence assemblySecurity,
+ RuntimeAssembly locationHint,
+ ref StackCrawlMark stackMark,
+ IntPtr pPrivHostBinder,
+ bool throwOnFileNotFound,
+ bool forIntrospection,
+ bool suppressSecurityChecks,
+ IntPtr ptrLoadContextBinder);
+
+#if !FEATURE_CORECLR
+ // The NGEN task uses this method, so please do not modify its signature
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool IsFrameworkAssembly(AssemblyName assemblyName);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsNewPortableAssembly(AssemblyName assemblyName);
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static RuntimeAssembly nLoad(AssemblyName fileName,
+ String codeBase,
+ Evidence assemblySecurity,
+ RuntimeAssembly locationHint,
+ ref StackCrawlMark stackMark,
+ IntPtr pPrivHostBinder,
+ bool throwOnFileNotFound,
+ bool forIntrospection,
+ bool suppressSecurityChecks, IntPtr ptrLoadContextBinder = default(IntPtr))
+ {
+ return _nLoad(fileName, codeBase, assemblySecurity, locationHint, ref stackMark,
+ pPrivHostBinder,
+ throwOnFileNotFound, forIntrospection, suppressSecurityChecks, ptrLoadContextBinder);
+ }
+
+#if FEATURE_FUSION
+ // used by vm
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private static unsafe RuntimeAssembly LoadWithPartialNameHack(String partialName, bool cropPublicKey)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ AssemblyName an = new AssemblyName(partialName);
+
+ if (!IsSimplyNamed(an))
+ {
+ if (cropPublicKey)
+ {
+ an.SetPublicKey(null);
+ an.SetPublicKeyToken(null);
+ }
+
+ if(IsFrameworkAssembly(an) || !AppDomain.IsAppXModel())
+ {
+ AssemblyName GACAssembly = EnumerateCache(an);
+ if(GACAssembly != null)
+ return InternalLoadAssemblyName(GACAssembly, null, null,ref stackMark, true /*thrownOnFileNotFound*/, false, false);
+ else
+ return null;
+ }
+ }
+
+ if (AppDomain.IsAppXModel())
+ {
+ // also try versionless bind from the package
+ an.Version = null;
+ return nLoad(an, null, null, null, ref stackMark,
+ IntPtr.Zero,
+ false, false, false);
+ }
+ return null;
+
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly LoadWithPartialNameInternal(String partialName, Evidence securityEvidence, ref StackCrawlMark stackMark)
+ {
+ AssemblyName an = new AssemblyName(partialName);
+ return LoadWithPartialNameInternal(an, securityEvidence, ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly LoadWithPartialNameInternal(AssemblyName an, Evidence securityEvidence, ref StackCrawlMark stackMark)
+ {
+ if (securityEvidence != null)
+ {
+#if FEATURE_CAS_POLICY
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyImplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ }
+
+ AppDomain.CheckLoadWithPartialNameSupported(stackMark);
+
+ RuntimeAssembly result = null;
+ try {
+ result = nLoad(an, null, securityEvidence, null, ref stackMark,
+ IntPtr.Zero,
+ true, false, false);
+ }
+ catch(Exception e) {
+ if (e.IsTransient)
+ throw e;
+
+ if (IsUserError(e))
+ throw;
+
+
+ if(IsFrameworkAssembly(an) || !AppDomain.IsAppXModel())
+ {
+ if (IsSimplyNamed(an))
+ return null;
+
+ AssemblyName GACAssembly = EnumerateCache(an);
+ if(GACAssembly != null)
+ result = InternalLoadAssemblyName(GACAssembly, securityEvidence, null, ref stackMark, true /*thrownOnFileNotFound*/, false, false);
+ }
+ else
+ {
+ an.Version = null;
+ result = nLoad(an, null, securityEvidence, null, ref stackMark,
+ IntPtr.Zero,
+ false, false, false);
+ }
+ }
+
+
+ return result;
+ }
+#endif // !FEATURE_CORECLR
+
+ [SecuritySafeCritical]
+ private static bool IsUserError(Exception e)
+ {
+ return (uint)e.HResult == COR_E_LOADING_REFERENCE_ASSEMBLY;
+ }
+
+ private static bool IsSimplyNamed(AssemblyName partialName)
+ {
+ byte[] pk = partialName.GetPublicKeyToken();
+ if ((pk != null) &&
+ (pk.Length == 0))
+ return true;
+
+ pk = partialName.GetPublicKey();
+ if ((pk != null) &&
+ (pk.Length == 0))
+ return true;
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static AssemblyName EnumerateCache(AssemblyName partialName)
+ {
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
+
+ partialName.Version = null;
+
+ ArrayList a = new ArrayList();
+ Fusion.ReadCache(a, partialName.FullName, ASM_CACHE.GAC);
+
+ IEnumerator myEnum = a.GetEnumerator();
+ AssemblyName ainfoBest = null;
+ CultureInfo refCI = partialName.CultureInfo;
+
+ while (myEnum.MoveNext()) {
+ AssemblyName ainfo = new AssemblyName((String)myEnum.Current);
+
+ if (CulturesEqual(refCI, ainfo.CultureInfo)) {
+ if (ainfoBest == null)
+ ainfoBest = ainfo;
+ else {
+ // Choose highest version
+ if (ainfo.Version > ainfoBest.Version)
+ ainfoBest = ainfo;
+ }
+ }
+ }
+
+ return ainfoBest;
+ }
+
+ private static bool CulturesEqual(CultureInfo refCI, CultureInfo defCI)
+ {
+ bool defNoCulture = defCI.Equals(CultureInfo.InvariantCulture);
+
+ // cultured asms aren't allowed to be bound to if
+ // the ref doesn't ask for them specifically
+ if ((refCI == null) || refCI.Equals(CultureInfo.InvariantCulture))
+ return defNoCulture;
+
+ if (defNoCulture ||
+ ( !defCI.Equals(refCI) ))
+ return false;
+
+ return true;
+ }
+#endif // FEATURE_FUSION
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool IsReflectionOnly(RuntimeAssembly assembly);
+
+ // To not break compatibility with the V1 _Assembly interface we need to make this
+ // new member ComVisible(false).
+ [ComVisible(false)]
+ public override bool ReflectionOnly
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return IsReflectionOnly(GetNativeHandle());
+ }
+ }
+
+#if FEATURE_CORECLR
+ // Loads the assembly with a COFF based IMAGE containing
+ // an emitted assembly. The assembly is loaded into the domain
+ // of the caller. Currently is implemented only for UnmanagedMemoryStream
+ // (no derived classes since we are not calling Read())
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly InternalLoadFromStream(Stream assemblyStream, Stream pdbStream, ref StackCrawlMark stackMark)
+ {
+ if (assemblyStream == null)
+ throw new ArgumentNullException("assemblyStream");
+
+ if (assemblyStream.GetType()!=typeof(UnmanagedMemoryStream))
+ throw new NotSupportedException();
+
+ if (pdbStream!= null && pdbStream.GetType()!=typeof(UnmanagedMemoryStream))
+ throw new NotSupportedException();
+
+ AppDomain.CheckLoadFromSupported();
+
+ UnmanagedMemoryStream umAssemblyStream = (UnmanagedMemoryStream)assemblyStream;
+ UnmanagedMemoryStream umPdbStream = (UnmanagedMemoryStream)pdbStream;
+
+ unsafe
+ {
+ byte* umAssemblyStreamBuffer=umAssemblyStream.PositionPointer;
+ byte* umPdbStreamBuffer=(umPdbStream!=null)?umPdbStream.PositionPointer:null;
+ long assemblyDataLength = umAssemblyStream.Length-umAssemblyStream.Position;
+ long pdbDataLength = (umPdbStream!=null)?(umPdbStream.Length-umPdbStream.Position):0;
+
+ // use Seek() to benefit from boundary checking, the actual read is done using *StreamBuffer
+ umAssemblyStream.Seek(assemblyDataLength,SeekOrigin.Current);
+
+ if(umPdbStream != null)
+ {
+ umPdbStream.Seek(pdbDataLength,SeekOrigin.Current);
+ }
+
+ BCLDebug.Assert(assemblyDataLength > 0L, "assemblyDataLength > 0L");
+
+ RuntimeAssembly assembly = null;
+
+ nLoadFromUnmanagedArray(false,
+ umAssemblyStreamBuffer,
+ (ulong)assemblyDataLength,
+ umPdbStreamBuffer,
+ (ulong)pdbDataLength,
+ JitHelpers.GetStackCrawlMarkHandle(ref stackMark),
+ JitHelpers.GetObjectHandleOnStack(ref assembly));
+
+ return assembly;
+ }
+ }
+#endif //FEATURE_CORECLR
+
+#if FEATURE_MULTIMODULE_ASSEMBLIES
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void LoadModule(RuntimeAssembly assembly,
+ String moduleName,
+ byte[] rawModule, int cbModule,
+ byte[] rawSymbolStore, int cbSymbolStore,
+ ObjectHandleOnStack retModule);
+
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlEvidence = true)]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Module LoadModule(String moduleName, byte[] rawModule, byte[] rawSymbolStore)
+ {
+ RuntimeModule retModule = null;
+ LoadModule(
+ GetNativeHandle(),
+ moduleName,
+ rawModule,
+ (rawModule != null) ? rawModule.Length : 0,
+ rawSymbolStore,
+ (rawSymbolStore != null) ? rawSymbolStore.Length : 0,
+ JitHelpers.GetObjectHandleOnStack(ref retModule));
+
+ return retModule;
+ }
+#endif //FEATURE_MULTIMODULE_ASSEMBLIES
+
+ // Returns the module in this assembly with name 'name'
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetModule(RuntimeAssembly assembly, String name, ObjectHandleOnStack retModule);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Module GetModule(String name)
+ {
+ Module retModule = null;
+ GetModule(GetNativeHandle(), name, JitHelpers.GetObjectHandleOnStack(ref retModule));
+ return retModule;
+ }
+
+ // Returns the file in the File table of the manifest that matches the
+ // given name. (Name should not include path.)
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override FileStream GetFile(String name)
+ {
+ RuntimeModule m = (RuntimeModule)GetModule(name);
+ if (m == null)
+ return null;
+
+ return new FileStream(m.GetFullyQualifiedName(),
+ FileMode.Open,
+ FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public override FileStream[] GetFiles(bool getResourceModules)
+ {
+ Module[] m = GetModules(getResourceModules);
+ int iLength = m.Length;
+ FileStream[] fs = new FileStream[iLength];
+
+ for(int i = 0; i < iLength; i++)
+ fs[i] = new FileStream(((RuntimeModule)m[i]).GetFullyQualifiedName(),
+ FileMode.Open,
+ FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false);
+
+ return fs;
+ }
+
+
+ // Returns the names of all the resources
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern String[] GetManifestResourceNames(RuntimeAssembly assembly);
+
+ // Returns the names of all the resources
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String[] GetManifestResourceNames()
+ {
+ return GetManifestResourceNames(GetNativeHandle());
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetExecutingAssembly(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retAssembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeAssembly GetExecutingAssembly(ref StackCrawlMark stackMark)
+ {
+ RuntimeAssembly retAssembly = null;
+ GetExecutingAssembly(JitHelpers.GetStackCrawlMarkHandle(ref stackMark), JitHelpers.GetObjectHandleOnStack(ref retAssembly));
+ return retAssembly;
+ }
+
+ // Returns the names of all the resources
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern AssemblyName[] GetReferencedAssemblies(RuntimeAssembly assembly);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override AssemblyName[] GetReferencedAssemblies()
+ {
+ return GetReferencedAssemblies(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern int GetManifestResourceInfo(RuntimeAssembly assembly,
+ String resourceName,
+ ObjectHandleOnStack assemblyRef,
+ StringHandleOnStack retFileName,
+ StackCrawlMarkHandle stackMark);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override ManifestResourceInfo GetManifestResourceInfo(String resourceName)
+ {
+ RuntimeAssembly retAssembly = null;
+ String fileName = null;
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ int location = GetManifestResourceInfo(GetNativeHandle(), resourceName,
+ JitHelpers.GetObjectHandleOnStack(ref retAssembly),
+ JitHelpers.GetStringHandleOnStack(ref fileName),
+ JitHelpers.GetStackCrawlMarkHandle(ref stackMark));
+
+ if (location == -1)
+ return null;
+
+ return new ManifestResourceInfo(retAssembly, fileName,
+ (ResourceLocation) location);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetLocation(RuntimeAssembly assembly, StringHandleOnStack retString);
+
+ public override String Location
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ get {
+ String location = null;
+
+ GetLocation(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref location));
+
+ if (location != null)
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, location ).Demand();
+
+ return location;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetImageRuntimeVersion(RuntimeAssembly assembly, StringHandleOnStack retString);
+
+ // To not break compatibility with the V1 _Assembly interface we need to make this
+ // new member ComVisible(false).
+ [ComVisible(false)]
+ public override String ImageRuntimeVersion
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get{
+ String s = null;
+ GetImageRuntimeVersion(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref s));
+ return s;
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static bool IsGlobalAssemblyCache(RuntimeAssembly assembly);
+
+ public override bool GlobalAssemblyCache
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return IsGlobalAssemblyCache(GetNativeHandle());
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static Int64 GetHostContext(RuntimeAssembly assembly);
+
+ public override Int64 HostContext
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return GetHostContext(GetNativeHandle());
+ }
+ }
+
+ private static String VerifyCodeBase(String codebase)
+ {
+ if(codebase == null)
+ return null;
+
+ int len = codebase.Length;
+ if (len == 0)
+ return null;
+
+
+ int j = codebase.IndexOf(':');
+ // Check to see if the url has a prefix
+ if( (j != -1) &&
+ (j+2 < len) &&
+ ((codebase[j+1] == '/') || (codebase[j+1] == '\\')) &&
+ ((codebase[j+2] == '/') || (codebase[j+2] == '\\')) )
+ return codebase;
+#if !PLATFORM_UNIX
+ else if ((len > 2) && (codebase[0] == '\\') && (codebase[1] == '\\'))
+ return "file://" + codebase;
+ else
+ return "file:///" + Path.GetFullPathInternal( codebase );
+#else
+ else
+ return "file://" + Path.GetFullPathInternal( codebase );
+#endif // !PLATFORM_UNIX
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Stream GetManifestResourceStream(
+ Type type,
+ String name,
+ bool skipSecurityCheck,
+ ref StackCrawlMark stackMark)
+ {
+ StringBuilder sb = new StringBuilder();
+ if(type == null) {
+ if (name == null)
+ throw new ArgumentNullException("type");
+ }
+ else {
+ String nameSpace = type.Namespace;
+ if(nameSpace != null) {
+ sb.Append(nameSpace);
+ if(name != null)
+ sb.Append(Type.Delimiter);
+ }
+ }
+
+ if(name != null)
+ sb.Append(name);
+
+ return GetManifestResourceStream(sb.ToString(), ref stackMark, skipSecurityCheck);
+ }
+
+#if FEATURE_CAS_POLICY
+ internal bool IsStrongNameVerified
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get { return GetIsStrongNameVerified(GetNativeHandle()); }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern bool GetIsStrongNameVerified(RuntimeAssembly assembly);
+#endif // FEATURE_CAS_POLICY
+
+ // GetResource will return a pointer to the resources in memory.
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static unsafe extern byte* GetResource(RuntimeAssembly assembly,
+ String resourceName,
+ out ulong length,
+ StackCrawlMarkHandle stackMark,
+ bool skipSecurityCheck);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe Stream GetManifestResourceStream(String name, ref StackCrawlMark stackMark, bool skipSecurityCheck)
+ {
+ ulong length = 0;
+ byte* pbInMemoryResource = GetResource(GetNativeHandle(), name, out length, JitHelpers.GetStackCrawlMarkHandle(ref stackMark), skipSecurityCheck);
+
+ if (pbInMemoryResource != null) {
+ //Console.WriteLine("Creating an unmanaged memory stream of length "+length);
+ if (length > Int64.MaxValue)
+ throw new NotImplementedException(Environment.GetResourceString("NotImplemented_ResourcesLongerThan2^63"));
+
+ return new UnmanagedMemoryStream(pbInMemoryResource, (long)length, (long)length, FileAccess.Read, true);
+ }
+
+ //Console.WriteLine("GetManifestResourceStream: Blob "+name+" not found...");
+ return null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetVersion(RuntimeAssembly assembly,
+ out int majVer,
+ out int minVer,
+ out int buildNum,
+ out int revNum);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Version GetVersion()
+ {
+ int majorVer, minorVer, build, revision;
+ GetVersion(GetNativeHandle(), out majorVer, out minorVer, out build, out revision);
+ return new Version (majorVer, minorVer, build, revision);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetLocale(RuntimeAssembly assembly, StringHandleOnStack retString);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal CultureInfo GetLocale()
+ {
+ String locale = null;
+
+ GetLocale(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref locale));
+
+ if (locale == null)
+ return CultureInfo.InvariantCulture;
+
+ return new CultureInfo(locale);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool FCallIsDynamic(RuntimeAssembly assembly);
+
+ public override bool IsDynamic
+ {
+ [SecuritySafeCritical]
+ get {
+ return FCallIsDynamic(GetNativeHandle());
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void VerifyCodeBaseDiscovery(String codeBase)
+ {
+#if FEATURE_CAS_POLICY
+ if (CodeAccessSecurityEngine.QuickCheckForAllDemands()) {
+ return;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ if ((codeBase != null) &&
+ (String.Compare( codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) == 0)) {
+ System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true );
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, urlString.GetFileName() ).Demand();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetSimpleName(RuntimeAssembly assembly, StringHandleOnStack retSimpleName);
+
+ [SecuritySafeCritical]
+ internal String GetSimpleName()
+ {
+ string name = null;
+ GetSimpleName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref name));
+ return name;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static AssemblyHashAlgorithm GetHashAlgorithm(RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private AssemblyHashAlgorithm GetHashAlgorithm()
+ {
+ return GetHashAlgorithm(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static AssemblyNameFlags GetFlags(RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private AssemblyNameFlags GetFlags()
+ {
+ return GetFlags(GetNativeHandle());
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetRawBytes(RuntimeAssembly assembly, ObjectHandleOnStack retRawBytes);
+
+ // Get the raw bytes of the assembly
+ [SecuritySafeCritical]
+ internal byte[] GetRawBytes()
+ {
+ byte[] rawBytes = null;
+
+ GetRawBytes(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref rawBytes));
+ return rawBytes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetPublicKey(RuntimeAssembly assembly, ObjectHandleOnStack retPublicKey);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal byte[] GetPublicKey()
+ {
+ byte[] publicKey = null;
+ GetPublicKey(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref publicKey));
+ return publicKey;
+ }
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetGrantSet(RuntimeAssembly assembly, ObjectHandleOnStack granted, ObjectHandleOnStack denied);
+
+ [SecurityCritical]
+ internal void GetGrantSet(out PermissionSet newGrant, out PermissionSet newDenied)
+ {
+ PermissionSet granted = null, denied = null;
+ GetGrantSet(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref granted), JitHelpers.GetObjectHandleOnStack(ref denied));
+ newGrant = granted; newDenied = denied;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private extern static bool IsAllSecurityCritical(RuntimeAssembly assembly);
+
+ // Is everything introduced by this assembly critical
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsAllSecurityCritical()
+ {
+ return IsAllSecurityCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private extern static bool IsAllSecuritySafeCritical(RuntimeAssembly assembly);
+
+ // Is everything introduced by this assembly safe critical
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsAllSecuritySafeCritical()
+ {
+ return IsAllSecuritySafeCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private extern static bool IsAllPublicAreaSecuritySafeCritical(RuntimeAssembly assembly);
+
+ // Is everything introduced by this assembly safe critical
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsAllPublicAreaSecuritySafeCritical()
+ {
+ return IsAllPublicAreaSecuritySafeCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private extern static bool IsAllSecurityTransparent(RuntimeAssembly assembly);
+
+ // Is everything introduced by this assembly transparent
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsAllSecurityTransparent()
+ {
+ return IsAllSecurityTransparent(GetNativeHandle());
+ }
+
+#if FEATURE_FUSION
+ // demandFlag:
+ // 0 demand PathDiscovery permission only
+ // 1 demand Read permission only
+ // 2 demand both Read and PathDiscovery
+ // 3 demand Web permission only
+ [System.Security.SecurityCritical] // auto-generated
+ private static void DemandPermission(String codeBase, bool havePath,
+ int demandFlag)
+ {
+ FileIOPermissionAccess access = FileIOPermissionAccess.PathDiscovery;
+ switch(demandFlag) {
+
+ case 0: // default
+ break;
+ case 1:
+ access = FileIOPermissionAccess.Read;
+ break;
+ case 2:
+ access = FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read;
+ break;
+
+ case 3:
+ IPermission perm = CreateWebPermission(AssemblyName.EscapeCodeBase(codeBase));
+ perm.Demand();
+ return;
+ }
+
+ if (!havePath) {
+ System.Security.Util.URLString urlString = new System.Security.Util.URLString( codeBase, true );
+ codeBase = urlString.GetFileName();
+ }
+
+ codeBase = Path.GetFullPathInternal(codeBase); // canonicalize
+
+ new FileIOPermission(access, codeBase).Demand();
+ }
+#endif
+
+#if FEATURE_FUSION
+ private static IPermission CreateWebPermission( String codeBase )
+ {
+ Contract.Assert( codeBase != null, "Must pass in a valid CodeBase" );
+ Assembly sys = Assembly.Load("System, Version=" + ThisAssembly.Version + ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken);
+
+ Type type = sys.GetType("System.Net.NetworkAccess", true);
+
+ IPermission retval = null;
+ if (!type.IsEnum || !type.IsVisible)
+ goto Exit;
+
+ Object[] webArgs = new Object[2];
+ webArgs[0] = (Enum) Enum.Parse(type, "Connect", true);
+ if (webArgs[0] == null)
+ goto Exit;
+
+ webArgs[1] = codeBase;
+
+ type = sys.GetType("System.Net.WebPermission", true);
+
+ if (!type.IsVisible)
+ goto Exit;
+
+ retval = (IPermission) Activator.CreateInstance(type, webArgs);
+
+ Exit:
+ if (retval == null) {
+ Contract.Assert( false, "Unable to create WebPermission" );
+ throw new InvalidOperationException();
+ }
+
+ return retval;
+ }
+#endif
+ // This method is called by the VM.
+ [System.Security.SecurityCritical]
+ private RuntimeModule OnModuleResolveEvent(String moduleName)
+ {
+ ModuleResolveEventHandler moduleResolve = _ModuleResolve;
+ if (moduleResolve == null)
+ return null;
+
+ Delegate[] ds = moduleResolve.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++) {
+ RuntimeModule ret = (RuntimeModule)((ModuleResolveEventHandler) ds[i])(this, new ResolveEventArgs(moduleName,this));
+ if (ret != null)
+ return ret;
+ }
+
+ return null;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Assembly GetSatelliteAssembly(CultureInfo culture)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalGetSatelliteAssembly(culture, null, ref stackMark);
+ }
+
+ // Useful for binding to a very specific version of a satellite assembly
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version version)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalGetSatelliteAssembly(culture, version, ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal Assembly InternalGetSatelliteAssembly(CultureInfo culture,
+ Version version,
+ ref StackCrawlMark stackMark)
+ {
+ if (culture == null)
+ throw new ArgumentNullException("culture");
+ Contract.EndContractBlock();
+
+
+ String name = GetSimpleName() + ".resources";
+ return InternalGetSatelliteAssembly(name, culture, version, true, ref stackMark);
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool UseRelativeBindForSatellites();
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal RuntimeAssembly InternalGetSatelliteAssembly(String name,
+ CultureInfo culture,
+ Version version,
+ bool throwOnFileNotFound,
+ ref StackCrawlMark stackMark)
+ {
+
+ AssemblyName an = new AssemblyName();
+
+ an.SetPublicKey(GetPublicKey());
+ an.Flags = GetFlags() | AssemblyNameFlags.PublicKey;
+
+ if (version == null)
+ an.Version = GetVersion();
+ else
+ an.Version = version;
+
+ an.CultureInfo = culture;
+ an.Name = name;
+
+ RuntimeAssembly retAssembly = null;
+
+#if !FEATURE_CORECLR
+ bool bIsAppXDevMode = AppDomain.IsAppXDesignMode();
+
+ bool useRelativeBind = false;
+ if (CodeAccessSecurityEngine.QuickCheckForAllDemands())
+ {
+ if (IsFrameworkAssembly())
+ useRelativeBind = true;
+ else
+ useRelativeBind = UseRelativeBindForSatellites();
+ }
+
+
+ if (bIsAppXDevMode || useRelativeBind)
+ {
+ if (GlobalAssemblyCache)
+ {
+ // lookup in GAC
+ ArrayList a = new ArrayList();
+ bool bTryLoadAnyway = false;
+ try
+ {
+ Fusion.ReadCache(a, an.FullName, ASM_CACHE.GAC);
+ }
+ catch(Exception e)
+ {
+ if (e.IsTransient)
+ throw;
+
+ // We also catch any other exception types we haven't come across yet,
+ // not just UnauthorizedAccessException.
+
+ // We do not want this by itself to cause us to fail to load resources.
+
+ // On Classic, try the old unoptimized way, for full compatibility with 4.0.
+ // i.e. fall back to using nLoad.
+ if (!AppDomain.IsAppXModel())
+ bTryLoadAnyway = true;
+
+ // On AppX:
+ // Do not try nLoad since that would effectively allow Framework
+ // resource satellite assemblies to be placed in AppX packages.
+ // Instead, leave retAssembly == null. If we were called by the
+ // ResourceManager, this will usually result in falling back to
+ // the next culture in the resource fallback chain, possibly the
+ // neutral culture.
+
+ // Note: if throwOnFileNotFound is true, arbitrary
+ // exceptions will be absorbed here and
+ // FileNotFoundException will be thrown in their place.
+ // (See below: "throw new FileNotFoundException").
+ }
+ if (a.Count > 0 || bTryLoadAnyway)
+ {
+ // present in the GAC, load it from there
+ retAssembly = nLoad(an, null, null, this, ref stackMark,
+ IntPtr.Zero,
+ throwOnFileNotFound, false, false);
+ }
+ }
+ else
+ {
+ String codeBase = CodeBase;
+
+ if ((codeBase != null) &&
+ (String.Compare(codeBase, 0, s_localFilePrefix, 0, 5, StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ retAssembly = InternalProbeForSatelliteAssemblyNextToParentAssembly(an,
+ name,
+ codeBase,
+ culture,
+ throwOnFileNotFound,
+ bIsAppXDevMode /* useLoadFile */, // if bIsAppXDevMode is false, then useRelativeBind is true.
+ ref stackMark);
+ if (retAssembly != null && !IsSimplyNamed(an))
+ {
+ AssemblyName defName = retAssembly.GetName();
+ if (!AssemblyName.ReferenceMatchesDefinitionInternal(an,defName,false))
+ retAssembly = null;
+ }
+ }
+ else if (!bIsAppXDevMode)
+ {
+ retAssembly = nLoad(an, null, null, this, ref stackMark,
+ IntPtr.Zero,
+ throwOnFileNotFound, false, false);
+ }
+ }
+ }
+ else
+#endif // !FEATURE_CORECLR
+ {
+ retAssembly = nLoad(an, null, null, this, ref stackMark,
+ IntPtr.Zero,
+ throwOnFileNotFound, false, false);
+ }
+
+ if (retAssembly == this || (retAssembly == null && throwOnFileNotFound))
+ {
+ throw new FileNotFoundException(String.Format(culture, Environment.GetResourceString("IO.FileNotFound_FileName"), an.Name));
+ }
+
+ return retAssembly;
+ }
+
+ // Helper method used by InternalGetSatelliteAssembly only. Not abstracted for use elsewhere.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private RuntimeAssembly InternalProbeForSatelliteAssemblyNextToParentAssembly(AssemblyName an,
+ String name,
+ String codeBase,
+ CultureInfo culture,
+ bool throwOnFileNotFound,
+ bool useLoadFile,
+ ref StackCrawlMark stackMark)
+ {
+ // if useLoadFile == false, we do LoadFrom binds
+
+ RuntimeAssembly retAssembly = null;
+ String location = null;
+
+ if (useLoadFile)
+ location = Location;
+
+ FileNotFoundException dllNotFoundException = null;
+
+ StringBuilder assemblyFile = new StringBuilder(useLoadFile ? location : codeBase,
+ 0,
+ useLoadFile ? location.LastIndexOf('\\') + 1 : codeBase.LastIndexOf('/') + 1,
+ Path.MaxPath);
+ assemblyFile.Append(an.CultureInfo.Name);
+ assemblyFile.Append(useLoadFile ? '\\' : '/');
+ assemblyFile.Append(name);
+ assemblyFile.Append(".DLL");
+
+ string fileNameOrCodeBase = assemblyFile.ToString();
+
+ AssemblyName loadFromAsmName = null;
+
+ if (useLoadFile == false)
+ {
+ loadFromAsmName = new AssemblyName();
+ // set just the codebase - we want this to be a pure LoadFrom
+ loadFromAsmName.CodeBase = fileNameOrCodeBase;
+ }
+
+ try
+ {
+ try
+ {
+ retAssembly = useLoadFile ? nLoadFile(fileNameOrCodeBase, null) :
+ nLoad(loadFromAsmName, fileNameOrCodeBase, null, this, ref stackMark,
+ IntPtr.Zero,
+ throwOnFileNotFound, false, false);
+ }
+ catch (FileNotFoundException)
+ {
+ // Create our own exception since the one caught doesn't have a filename associated with it, making it less useful for debugging.
+ dllNotFoundException = new FileNotFoundException(String.Format(culture,
+ Environment.GetResourceString("IO.FileNotFound_FileName"),
+ fileNameOrCodeBase),
+ fileNameOrCodeBase); // Save this exception so we can throw it if we also don't find the .EXE
+ retAssembly = null;
+ }
+
+ if (retAssembly == null)
+ {
+ // LoadFile will always throw, but LoadFrom will only throw if throwOnFileNotFound is true.
+ // If an exception was thrown, we must have a dllNotFoundException ready for throwing later.
+ BCLDebug.Assert((useLoadFile == false && throwOnFileNotFound == false) || dllNotFoundException != null,
+ "(useLoadFile == false && throwOnFileNotFound == false) || dllNotFoundException != null");
+
+ assemblyFile.Remove(assemblyFile.Length - 4, 4);
+ assemblyFile.Append(".EXE");
+ fileNameOrCodeBase = assemblyFile.ToString();
+
+ if (useLoadFile == false)
+ loadFromAsmName.CodeBase = fileNameOrCodeBase;
+
+ try
+ {
+ retAssembly = useLoadFile ? nLoadFile(fileNameOrCodeBase, null) :
+ nLoad(loadFromAsmName, fileNameOrCodeBase, null, this, ref stackMark,
+ IntPtr.Zero,
+ false /* do not throw on file not found */, false, false);
+
+ }
+ catch (FileNotFoundException)
+ {
+ retAssembly = null;
+ }
+
+ // It would be messy to have a FileNotFoundException that reports both .DLL and .EXE not found.
+ // Using a .DLL extension for satellite assemblies is the more common scenario,
+ // so just throw that exception.
+
+ // In classic (i.e. non-AppX) mode, if binder logging is turned on, there will be separate logs for
+ // the .DLL and .EXE load attempts if the user is interested in digging deeper.
+
+ if (retAssembly == null && throwOnFileNotFound)
+ throw dllNotFoundException;
+ }
+ }
+ catch (DirectoryNotFoundException)
+ {
+ if (throwOnFileNotFound)
+ throw;
+ retAssembly = null;
+ }
+ // No other exceptions should be caught here.
+
+ return retAssembly;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern RuntimeAssembly nLoadFile(String path, Evidence evidence);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern RuntimeAssembly nLoadImage(byte[] rawAssembly,
+ byte[] rawSymbolStore,
+ Evidence evidence,
+ ref StackCrawlMark stackMark,
+ bool fIntrospection,
+ SecurityContextSource securityContextSource);
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static internal extern unsafe void nLoadFromUnmanagedArray(bool fIntrospection,
+ byte* assemblyContent,
+ ulong assemblySize,
+ byte* pdbContent,
+ ulong pdbSize,
+ StackCrawlMarkHandle stackMark,
+ ObjectHandleOnStack retAssembly);
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetModules(RuntimeAssembly assembly,
+ bool loadIfNotFound,
+ bool getResourceModules,
+ ObjectHandleOnStack retModuleHandles);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private RuntimeModule[] GetModulesInternal(bool loadIfNotFound,
+ bool getResourceModules)
+ {
+ RuntimeModule[] modules = null;
+ GetModules(GetNativeHandle(), loadIfNotFound, getResourceModules, JitHelpers.GetObjectHandleOnStack(ref modules));
+ return modules;
+ }
+
+ public override Module[] GetModules(bool getResourceModules)
+ {
+ return GetModulesInternal(true, getResourceModules);
+ }
+
+ public override Module[] GetLoadedModules(bool getResourceModules)
+ {
+ return GetModulesInternal(false, getResourceModules);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeModule GetManifestModule(RuntimeAssembly assembly);
+
+#if FEATURE_APTCA
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool AptcaCheck(RuntimeAssembly targetAssembly, RuntimeAssembly sourceAssembly);
+#endif // FEATURE_APTCA
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetToken(RuntimeAssembly assembly);
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs b/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs
new file mode 100644
index 0000000000..955255572b
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/AssemblyAttributes.cs
@@ -0,0 +1,406 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: For Assembly-related custom attributes.
+**
+**
+=============================================================================*/
+
+namespace System.Reflection {
+
+ using System;
+ using System.Configuration.Assemblies;
+ using System.Diagnostics.Contracts;
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyCopyrightAttribute : Attribute
+ {
+ private String m_copyright;
+
+ public AssemblyCopyrightAttribute(String copyright)
+ {
+ m_copyright = copyright;
+ }
+
+ public String Copyright
+ {
+ get { return m_copyright; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyTrademarkAttribute : Attribute
+ {
+ private String m_trademark;
+
+ public AssemblyTrademarkAttribute(String trademark)
+ {
+ m_trademark = trademark;
+ }
+
+ public String Trademark
+ {
+ get { return m_trademark; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyProductAttribute : Attribute
+ {
+ private String m_product;
+
+ public AssemblyProductAttribute(String product)
+ {
+ m_product = product;
+ }
+
+ public String Product
+ {
+ get { return m_product; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyCompanyAttribute : Attribute
+ {
+ private String m_company;
+
+ public AssemblyCompanyAttribute(String company)
+ {
+ m_company = company;
+ }
+
+ public String Company
+ {
+ get { return m_company; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyDescriptionAttribute : Attribute
+ {
+ private String m_description;
+
+ public AssemblyDescriptionAttribute(String description)
+ {
+ m_description = description;
+ }
+
+ public String Description
+ {
+ get { return m_description; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyTitleAttribute : Attribute
+ {
+ private String m_title;
+
+ public AssemblyTitleAttribute(String title)
+ {
+ m_title = title;
+ }
+
+ public String Title
+ {
+ get { return m_title; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyConfigurationAttribute : Attribute
+ {
+ private String m_configuration;
+
+ public AssemblyConfigurationAttribute(String configuration)
+ {
+ m_configuration = configuration;
+ }
+
+ public String Configuration
+ {
+ get { return m_configuration; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyDefaultAliasAttribute : Attribute
+ {
+ private String m_defaultAlias;
+
+ public AssemblyDefaultAliasAttribute(String defaultAlias)
+ {
+ m_defaultAlias = defaultAlias;
+ }
+
+ public String DefaultAlias
+ {
+ get { return m_defaultAlias; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyInformationalVersionAttribute : Attribute
+ {
+ private String m_informationalVersion;
+
+ public AssemblyInformationalVersionAttribute(String informationalVersion)
+ {
+ m_informationalVersion = informationalVersion;
+ }
+
+ public String InformationalVersion
+ {
+ get { return m_informationalVersion; }
+ }
+ }
+
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyFileVersionAttribute : Attribute
+ {
+ private String _version;
+
+ public AssemblyFileVersionAttribute(String version)
+ {
+ if (version == null)
+ throw new ArgumentNullException("version");
+ Contract.EndContractBlock();
+ _version = version;
+ }
+
+ public String Version {
+ get { return _version; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class AssemblyCultureAttribute : Attribute
+ {
+ private String m_culture;
+
+ public AssemblyCultureAttribute(String culture)
+ {
+ m_culture = culture;
+ }
+
+ public String Culture
+ {
+ get { return m_culture; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class AssemblyVersionAttribute : Attribute
+ {
+ private String m_version;
+
+ public AssemblyVersionAttribute(String version)
+ {
+ m_version = version;
+ }
+
+ public String Version
+ {
+ get { return m_version; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyKeyFileAttribute : Attribute
+ {
+ private String m_keyFile;
+
+ public AssemblyKeyFileAttribute(String keyFile)
+ {
+ m_keyFile = keyFile;
+ }
+
+ public String KeyFile
+ {
+ get { return m_keyFile; }
+ }
+ }
+
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyDelaySignAttribute : Attribute
+ {
+ private bool m_delaySign;
+
+ public AssemblyDelaySignAttribute(bool delaySign)
+ {
+ m_delaySign = delaySign;
+ }
+
+ public bool DelaySign
+ { get
+ { return m_delaySign; }
+ }
+ }
+
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class AssemblyAlgorithmIdAttribute : Attribute
+ {
+ private uint m_algId;
+
+ public AssemblyAlgorithmIdAttribute(AssemblyHashAlgorithm algorithmId)
+ {
+ m_algId = (uint) algorithmId;
+ }
+
+ [CLSCompliant(false)]
+ public AssemblyAlgorithmIdAttribute(uint algorithmId)
+ {
+ m_algId = algorithmId;
+ }
+
+ [CLSCompliant(false)]
+ public uint AlgorithmId
+ {
+ get { return m_algId; }
+ }
+ }
+
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class AssemblyFlagsAttribute : Attribute
+ {
+ private AssemblyNameFlags m_flags;
+
+ [Obsolete("This constructor has been deprecated. Please use AssemblyFlagsAttribute(AssemblyNameFlags) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [CLSCompliant(false)]
+ public AssemblyFlagsAttribute(uint flags)
+ {
+ m_flags = (AssemblyNameFlags)flags;
+ }
+
+ [Obsolete("This property has been deprecated. Please use AssemblyFlags instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [CLSCompliant(false)]
+ public uint Flags
+ {
+ get { return (uint)m_flags; }
+ }
+
+ // This, of course, should be typed as AssemblyNameFlags. The compat police don't allow such changes.
+ public int AssemblyFlags
+ {
+ get { return (int)m_flags; }
+ }
+
+ [Obsolete("This constructor has been deprecated. Please use AssemblyFlagsAttribute(AssemblyNameFlags) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public AssemblyFlagsAttribute(int assemblyFlags)
+ {
+ m_flags = (AssemblyNameFlags)assemblyFlags;
+ }
+
+
+ public AssemblyFlagsAttribute(AssemblyNameFlags assemblyFlags)
+ {
+ m_flags = assemblyFlags;
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)]
+ public sealed class AssemblyMetadataAttribute : Attribute
+ {
+ private String m_key;
+ private String m_value;
+
+ public AssemblyMetadataAttribute(string key, string value)
+ {
+ m_key = key;
+ m_value = value;
+ }
+
+ public string Key
+ {
+ get { return m_key; }
+ }
+
+ public string Value
+ {
+ get { return m_value;}
+ }
+ }
+
+#if FEATURE_STRONGNAME_MIGRATION
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple=false)]
+ public sealed class AssemblySignatureKeyAttribute : Attribute
+ {
+ private String _publicKey;
+ private String _countersignature;
+
+ public AssemblySignatureKeyAttribute(String publicKey, String countersignature)
+ {
+ _publicKey = publicKey;
+ _countersignature = countersignature;
+ }
+
+ public String PublicKey
+ {
+ get { return _publicKey; }
+ }
+
+ public String Countersignature
+ {
+ get { return _countersignature; }
+ }
+ }
+#endif
+
+ [AttributeUsage (AttributeTargets.Assembly, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyKeyNameAttribute : Attribute
+ {
+ private String m_keyName;
+
+ public AssemblyKeyNameAttribute(String keyName)
+ {
+ m_keyName = keyName;
+ }
+
+ public String KeyName
+ {
+ get { return m_keyName; }
+ }
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/Reflection/AssemblyName.cs b/src/mscorlib/src/System/Reflection/AssemblyName.cs
new file mode 100644
index 0000000000..051f3b5f0e
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/AssemblyName.cs
@@ -0,0 +1,539 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Used for binding and retrieving info about an assembly
+**
+**
+===========================================================*/
+namespace System.Reflection {
+ using System;
+ using System.IO;
+ using System.Configuration.Assemblies;
+ using System.Runtime.CompilerServices;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_AssemblyName))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AssemblyName : _AssemblyName, ICloneable, ISerializable, IDeserializationCallback
+ {
+ //
+ // READ ME
+ // If you modify any of these fields, you must also update the
+ // AssemblyBaseObject structure in object.h
+ //
+ private String _Name; // Name
+ private byte[] _PublicKey;
+ private byte[] _PublicKeyToken;
+ private CultureInfo _CultureInfo;
+ private String _CodeBase; // Potential location to get the file
+ private Version _Version;
+
+ private StrongNameKeyPair _StrongNameKeyPair;
+
+ private SerializationInfo m_siInfo; //A temporary variable which we need during deserialization.
+
+ private byte[] _HashForControl;
+ private AssemblyHashAlgorithm _HashAlgorithm;
+ private AssemblyHashAlgorithm _HashAlgorithmForControl;
+
+ private AssemblyVersionCompatibility _VersionCompatibility;
+ private AssemblyNameFlags _Flags;
+
+ public AssemblyName()
+ {
+ _HashAlgorithm = AssemblyHashAlgorithm.None;
+ _VersionCompatibility = AssemblyVersionCompatibility.SameMachine;
+ _Flags = AssemblyNameFlags.None;
+ }
+
+ // Set and get the name of the assembly. If this is a weak Name
+ // then it optionally contains a site. For strong assembly names,
+ // the name partitions up the strong name's namespace
+ public String Name
+ {
+ get { return _Name; }
+ set { _Name = value; }
+ }
+
+ public Version Version
+ {
+ get {
+ return _Version;
+ }
+ set {
+ _Version = value;
+ }
+ }
+
+ // Locales, internally the LCID is used for the match.
+ public CultureInfo CultureInfo
+ {
+ get {
+ return _CultureInfo;
+ }
+ set {
+ _CultureInfo = value;
+ }
+ }
+
+ public String CultureName
+ {
+ get {
+ return (_CultureInfo == null) ? null : _CultureInfo.Name;
+ }
+ set {
+ _CultureInfo = (value == null) ? null : new CultureInfo(value);
+ }
+ }
+
+ public String CodeBase
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ get { return _CodeBase; }
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ set { _CodeBase = value; }
+ }
+
+ public String EscapedCodeBase
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (_CodeBase == null)
+ return null;
+ else
+ return EscapeCodeBase(_CodeBase);
+ }
+ }
+
+ public ProcessorArchitecture ProcessorArchitecture
+ {
+ get {
+ int x = (((int)_Flags) & 0x70) >> 4;
+ if(x > 5)
+ x = 0;
+ return (ProcessorArchitecture)x;
+ }
+ set {
+ int x = ((int)value) & 0x07;
+ if(x <= 5) {
+ _Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFFF0F);
+ _Flags |= (AssemblyNameFlags)(x << 4);
+ }
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public AssemblyContentType ContentType
+ {
+ get
+ {
+ int x = (((int)_Flags) & 0x00000E00) >> 9;
+ if (x > 1)
+ x = 0;
+ return (AssemblyContentType)x;
+ }
+ set
+ {
+ int x = ((int)value) & 0x07;
+ if (x <= 1)
+ {
+ _Flags = (AssemblyNameFlags)((int)_Flags & 0xFFFFF1FF);
+ _Flags |= (AssemblyNameFlags)(x << 9);
+ }
+ }
+ }
+
+
+
+ // Make a copy of this assembly name.
+ public Object Clone()
+ {
+ AssemblyName name = new AssemblyName();
+ name.Init(_Name,
+ _PublicKey,
+ _PublicKeyToken,
+ _Version,
+ _CultureInfo,
+ _HashAlgorithm,
+ _VersionCompatibility,
+ _CodeBase,
+ _Flags,
+ _StrongNameKeyPair);
+ name._HashForControl=_HashForControl;
+ name._HashAlgorithmForControl=_HashAlgorithmForControl;
+ return name;
+ }
+
+ /*
+ * Get the AssemblyName for a given file. This will only work
+ * if the file contains an assembly manifest. This method causes
+ * the file to be opened and closed.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static public AssemblyName GetAssemblyName(String assemblyFile)
+ {
+ if(assemblyFile == null)
+ throw new ArgumentNullException("assemblyFile");
+ Contract.EndContractBlock();
+
+ // Assembly.GetNameInternal() will not demand path discovery
+ // permission, so do that first.
+ String fullPath = Path.GetFullPathInternal(assemblyFile);
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullPath ).Demand();
+ return nGetFileInformation(fullPath);
+ }
+
+ internal void SetHashControl(byte[] hash, AssemblyHashAlgorithm hashAlgorithm)
+ {
+ _HashForControl=hash;
+ _HashAlgorithmForControl=hashAlgorithm;
+ }
+
+ // The public key that is used to verify an assemblies
+ // inclusion into the namespace. If the public key associated
+ // with the namespace cannot verify the assembly the assembly
+ // will fail to load.
+ public byte[] GetPublicKey()
+ {
+ return _PublicKey;
+ }
+
+ public void SetPublicKey(byte[] publicKey)
+ {
+ _PublicKey = publicKey;
+
+ if (publicKey == null)
+ _Flags &= ~AssemblyNameFlags.PublicKey;
+ else
+ _Flags |= AssemblyNameFlags.PublicKey;
+ }
+
+ // The compressed version of the public key formed from a truncated hash.
+ // Will throw a SecurityException if _PublicKey is invalid
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public byte[] GetPublicKeyToken()
+ {
+ if (_PublicKeyToken == null)
+ _PublicKeyToken = nGetPublicKeyToken();
+ return _PublicKeyToken;
+ }
+
+ public void SetPublicKeyToken(byte[] publicKeyToken)
+ {
+ _PublicKeyToken = publicKeyToken;
+ }
+
+ // Flags modifying the name. So far the only flag is PublicKey, which
+ // indicates that a full public key and not the compressed version is
+ // present.
+ // Processor Architecture flags are set only through ProcessorArchitecture
+ // property and can't be set or retrieved directly
+ // Content Type flags are set only through ContentType property and can't be
+ // set or retrieved directly
+ public AssemblyNameFlags Flags
+ {
+ get { return (AssemblyNameFlags)((uint)_Flags & 0xFFFFF10F); }
+ set {
+ _Flags &= unchecked((AssemblyNameFlags)0x00000EF0);
+ _Flags |= (value & unchecked((AssemblyNameFlags)0xFFFFF10F));
+ }
+ }
+
+ public AssemblyHashAlgorithm HashAlgorithm
+ {
+ get { return _HashAlgorithm; }
+ set { _HashAlgorithm = value; }
+ }
+
+ public AssemblyVersionCompatibility VersionCompatibility
+ {
+ get { return _VersionCompatibility; }
+ set { _VersionCompatibility = value; }
+ }
+
+ public StrongNameKeyPair KeyPair
+ {
+ get { return _StrongNameKeyPair; }
+ set { _StrongNameKeyPair = value; }
+ }
+
+ public String FullName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return nToString();
+ }
+ }
+
+ // Returns the stringized version of the assembly name.
+ public override String ToString()
+ {
+ String s = FullName;
+ if(s == null)
+ return base.ToString();
+ else
+ return s;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ //Allocate the serialization info and serialize our static data.
+ info.AddValue("_Name", _Name);
+ info.AddValue("_PublicKey", _PublicKey, typeof(byte[]));
+ info.AddValue("_PublicKeyToken", _PublicKeyToken, typeof(byte[]));
+#if FEATURE_USE_LCID
+ info.AddValue("_CultureInfo", (_CultureInfo == null) ? -1 :_CultureInfo.LCID);
+#endif
+ info.AddValue("_CodeBase", _CodeBase);
+ info.AddValue("_Version", _Version);
+ info.AddValue("_HashAlgorithm", _HashAlgorithm, typeof(AssemblyHashAlgorithm));
+ info.AddValue("_HashAlgorithmForControl", _HashAlgorithmForControl, typeof(AssemblyHashAlgorithm));
+ info.AddValue("_StrongNameKeyPair", _StrongNameKeyPair, typeof(StrongNameKeyPair));
+ info.AddValue("_VersionCompatibility", _VersionCompatibility, typeof(AssemblyVersionCompatibility));
+ info.AddValue("_Flags", _Flags, typeof(AssemblyNameFlags));
+ info.AddValue("_HashForControl",_HashForControl,typeof(byte[]));
+ }
+
+ public void OnDeserialization(Object sender)
+ {
+ // Deserialization has already been performed
+ if (m_siInfo == null)
+ return;
+
+ _Name = m_siInfo.GetString("_Name");
+ _PublicKey = (byte[]) m_siInfo.GetValue("_PublicKey", typeof(byte[]));
+ _PublicKeyToken = (byte[]) m_siInfo.GetValue("_PublicKeyToken", typeof(byte[]));
+#if FEATURE_USE_LCID
+ int lcid = (int)m_siInfo.GetInt32("_CultureInfo");
+ if (lcid != -1)
+ _CultureInfo = new CultureInfo(lcid);
+#endif
+
+ _CodeBase = m_siInfo.GetString("_CodeBase");
+ _Version = (Version) m_siInfo.GetValue("_Version", typeof(Version));
+ _HashAlgorithm = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithm", typeof(AssemblyHashAlgorithm));
+ _StrongNameKeyPair = (StrongNameKeyPair) m_siInfo.GetValue("_StrongNameKeyPair", typeof(StrongNameKeyPair));
+ _VersionCompatibility = (AssemblyVersionCompatibility)m_siInfo.GetValue("_VersionCompatibility", typeof(AssemblyVersionCompatibility));
+ _Flags = (AssemblyNameFlags) m_siInfo.GetValue("_Flags", typeof(AssemblyNameFlags));
+
+ try {
+ _HashAlgorithmForControl = (AssemblyHashAlgorithm) m_siInfo.GetValue("_HashAlgorithmForControl", typeof(AssemblyHashAlgorithm));
+ _HashForControl = (byte[]) m_siInfo.GetValue("_HashForControl", typeof(byte[]));
+ }
+ catch (SerializationException) { // RTM did not have these defined
+ _HashAlgorithmForControl = AssemblyHashAlgorithm.None;
+ _HashForControl = null;
+ }
+
+ m_siInfo = null;
+ }
+
+ // Constructs a new AssemblyName during deserialization.
+ internal AssemblyName(SerializationInfo info, StreamingContext context)
+ {
+ //The graph is not valid until OnDeserialization() has been called.
+ m_siInfo = info;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public AssemblyName(String assemblyName)
+ {
+ if (assemblyName == null)
+ throw new ArgumentNullException("assemblyName");
+ Contract.EndContractBlock();
+ if ((assemblyName.Length == 0) ||
+ (assemblyName[0] == '\0'))
+ throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
+
+ _Name = assemblyName;
+ nInit();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static public bool ReferenceMatchesDefinition(AssemblyName reference,
+ AssemblyName definition)
+ {
+ // Optimization for common use case
+ if (Object.ReferenceEquals(reference, definition))
+ {
+ return true;
+ }
+ return ReferenceMatchesDefinitionInternal(reference, definition, true);
+ }
+
+
+ /// "parse" tells us to parse the simple name of the assembly as if it was the full name
+ /// almost never the right thing to do, but needed for compat
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern bool ReferenceMatchesDefinitionInternal(AssemblyName reference,
+ AssemblyName definition,
+ bool parse);
+
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void nInit(out RuntimeAssembly assembly, bool forIntrospection, bool raiseResolveEvent);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void nInit()
+ {
+ RuntimeAssembly dummy = null;
+ nInit(out dummy, false, false);
+ }
+
+ internal void SetProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm)
+ {
+ ProcessorArchitecture = CalculateProcArchIndex(pek, ifm, _Flags);
+ }
+
+ internal static ProcessorArchitecture CalculateProcArchIndex(PortableExecutableKinds pek, ImageFileMachine ifm, AssemblyNameFlags flags)
+ {
+ if (((uint)flags & 0xF0) == 0x70)
+ return ProcessorArchitecture.None;
+
+ if ((pek & System.Reflection.PortableExecutableKinds.PE32Plus) == System.Reflection.PortableExecutableKinds.PE32Plus)
+ {
+ switch (ifm)
+ {
+ case System.Reflection.ImageFileMachine.IA64:
+ return ProcessorArchitecture.IA64;
+ case System.Reflection.ImageFileMachine.AMD64:
+ return ProcessorArchitecture.Amd64;
+ case System.Reflection.ImageFileMachine.I386:
+ if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
+ return ProcessorArchitecture.MSIL;
+ break;
+ }
+ }
+ else
+ {
+ if (ifm == System.Reflection.ImageFileMachine.I386)
+ {
+ if ((pek & System.Reflection.PortableExecutableKinds.Required32Bit) == System.Reflection.PortableExecutableKinds.Required32Bit)
+ return ProcessorArchitecture.X86;
+
+ if ((pek & System.Reflection.PortableExecutableKinds.ILOnly) == System.Reflection.PortableExecutableKinds.ILOnly)
+ return ProcessorArchitecture.MSIL;
+
+ return ProcessorArchitecture.X86;
+ }
+ if (ifm == System.Reflection.ImageFileMachine.ARM)
+ {
+ return ProcessorArchitecture.Arm;
+ }
+ }
+ return ProcessorArchitecture.None;
+ }
+
+ internal void Init(String name,
+ byte[] publicKey,
+ byte[] publicKeyToken,
+ Version version,
+ CultureInfo cultureInfo,
+ AssemblyHashAlgorithm hashAlgorithm,
+ AssemblyVersionCompatibility versionCompatibility,
+ String codeBase,
+ AssemblyNameFlags flags,
+ StrongNameKeyPair keyPair) // Null if ref, matching Assembly if def
+ {
+ _Name = name;
+
+ if (publicKey != null) {
+ _PublicKey = new byte[publicKey.Length];
+ Array.Copy(publicKey, _PublicKey, publicKey.Length);
+ }
+
+ if (publicKeyToken != null) {
+ _PublicKeyToken = new byte[publicKeyToken.Length];
+ Array.Copy(publicKeyToken, _PublicKeyToken, publicKeyToken.Length);
+ }
+
+ if (version != null)
+ _Version = (Version) version.Clone();
+
+ _CultureInfo = cultureInfo;
+ _HashAlgorithm = hashAlgorithm;
+ _VersionCompatibility = versionCompatibility;
+ _CodeBase = codeBase;
+ _Flags = flags;
+ _StrongNameKeyPair = keyPair;
+ }
+
+#if !FEATURE_CORECLR
+ void _AssemblyName.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AssemblyName.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AssemblyName.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AssemblyName.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+#if FEATURE_APTCA
+ internal string GetNameWithPublicKey()
+ {
+ byte[] key = GetPublicKey();
+
+ // The following string should not be localized because it is used in security decisions.
+ return Name + ", PublicKey=" + System.Security.Util.Hex.EncodeHexString(key);
+ }
+#endif
+
+ // This call opens and closes the file, but does not add the
+ // assembly to the domain.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern AssemblyName nGetFileInformation(String s);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern String nToString();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern byte[] nGetPublicKeyToken();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern String EscapeCodeBase(String codeBase);
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/AssemblyNameFlags.cs b/src/mscorlib/src/System/Reflection/AssemblyNameFlags.cs
new file mode 100644
index 0000000000..35a5370cc6
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/AssemblyNameFlags.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Flags controlling how an AssemblyName is used
+** during binding
+**
+**
+===========================================================*/
+namespace System.Reflection {
+
+ using System;
+ [Serializable]
+ [FlagsAttribute()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum AssemblyNameFlags
+ {
+ None = 0x0000,
+ // Flag used to indicate that an assembly ref contains the full public key, not the compressed token.
+ // Must match afPublicKey in CorHdr.h.
+ PublicKey = 0x0001,
+ //ProcArchMask = 0x00F0, // Bits describing the processor architecture
+ // Accessible via AssemblyName.ProcessorArchitecture
+ EnableJITcompileOptimizer = 0x4000,
+ EnableJITcompileTracking = 0x8000,
+ Retargetable = 0x0100,
+ //ContentType = 0x0E00, // Bits describing the ContentType are accessible via AssemblyName.ContentType
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public enum AssemblyContentType
+ {
+ Default = 0x0000,
+ WindowsRuntime = 0x0001
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ProcessorArchitecture
+ {
+ None = 0x0000,
+ MSIL = 0x0001,
+ X86 = 0x0002,
+ IA64 = 0x0003,
+ Amd64 = 0x0004,
+ Arm = 0x0005
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/AssemblyNameProxy.cs b/src/mscorlib/src/System/Reflection/AssemblyNameProxy.cs
new file mode 100644
index 0000000000..8c8fa8d286
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/AssemblyNameProxy.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Remotable version the AssemblyName
+**
+**
+===========================================================*/
+namespace System.Reflection {
+ using System;
+ using System.Runtime.Versioning;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class AssemblyNameProxy : MarshalByRefObject
+ {
+ public AssemblyName GetAssemblyName(String assemblyFile)
+ {
+ return AssemblyName.GetAssemblyName(assemblyFile);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Associates.cs b/src/mscorlib/src/System/Reflection/Associates.cs
new file mode 100644
index 0000000000..8b34e77b63
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Associates.cs
@@ -0,0 +1,212 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ internal static class Associates
+ {
+ [Flags]
+ internal enum Attributes
+ {
+ ComposedOfAllVirtualMethods = 0x1,
+ ComposedOfAllPrivateMethods = 0x2,
+ ComposedOfNoPublicMembers = 0x4,
+ ComposedOfNoStaticMembers = 0x8,
+ }
+
+ internal static bool IncludeAccessor(MethodInfo associate, bool nonPublic)
+ {
+ if ((object)associate == null)
+ return false;
+
+ if (nonPublic)
+ return true;
+
+ if (associate.IsPublic)
+ return true;
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe RuntimeMethodInfo AssignAssociates(
+ int tkMethod,
+ RuntimeType declaredType,
+ RuntimeType reflectedType)
+ {
+ if (MetadataToken.IsNullToken(tkMethod))
+ return null;
+
+ Contract.Assert(declaredType != null);
+ Contract.Assert(reflectedType != null);
+
+ bool isInherited = declaredType != reflectedType;
+
+ IntPtr[] genericArgumentHandles = null;
+ int genericArgumentCount = 0;
+ RuntimeType [] genericArguments = declaredType.GetTypeHandleInternal().GetInstantiationInternal();
+ if (genericArguments != null)
+ {
+ genericArgumentCount = genericArguments.Length;
+ genericArgumentHandles = new IntPtr[genericArguments.Length];
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ genericArgumentHandles[i] = genericArguments[i].GetTypeHandleInternal().Value;
+ }
+ }
+
+ RuntimeMethodHandleInternal associateMethodHandle = ModuleHandle.ResolveMethodHandleInternalCore(RuntimeTypeHandle.GetModule(declaredType), tkMethod, genericArgumentHandles, genericArgumentCount, null, 0);
+ Contract.Assert(!associateMethodHandle.IsNullHandle(), "Failed to resolve associateRecord methodDef token");
+
+ if (isInherited)
+ {
+ MethodAttributes methAttr = RuntimeMethodHandle.GetAttributes(associateMethodHandle);
+
+ // ECMA MethodSemantics: "All methods for a given Property or Event shall have the same accessibility
+ //(ie the MemberAccessMask subfield of their Flags row) and cannot be CompilerControlled [CLS]"
+ // Consequently, a property may be composed of public and private methods. If the declared type !=
+ // the reflected type, the private methods should not be exposed. Note that this implies that the
+ // identity of a property includes it's reflected type.
+
+ if ((methAttr & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
+ return null;
+
+ // Note this is the first time the property was encountered walking from the most derived class
+ // towards the base class. It would seem to follow that any associated methods would not
+ // be overriden -- but this is not necessarily true. A more derived class may have overriden a
+ // virtual method associated with a property in a base class without associating the override with
+ // the same or any property in the derived class.
+ if ((methAttr & MethodAttributes.Virtual) != 0)
+ {
+ bool declaringTypeIsClass =
+ (RuntimeTypeHandle.GetAttributes(declaredType) & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class;
+
+ // It makes no sense to search for a virtual override of a method declared on an interface.
+ if (declaringTypeIsClass)
+ {
+ int slot = RuntimeMethodHandle.GetSlot(associateMethodHandle);
+
+ // Find the override visible from the reflected type
+ associateMethodHandle = RuntimeTypeHandle.GetMethodAt(reflectedType, slot);
+ }
+ }
+ }
+
+ RuntimeMethodInfo associateMethod =
+ RuntimeType.GetMethodBase(reflectedType, associateMethodHandle) as RuntimeMethodInfo;
+
+ // suppose a property was mapped to a method not in the derivation hierarchy of the reflectedTypeHandle
+ if (associateMethod == null)
+ associateMethod = reflectedType.Module.ResolveMethod(tkMethod, null, null) as RuntimeMethodInfo;
+
+ return associateMethod;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe void AssignAssociates(
+ MetadataImport scope,
+ int mdPropEvent,
+ RuntimeType declaringType,
+ RuntimeType reflectedType,
+ out RuntimeMethodInfo addOn,
+ out RuntimeMethodInfo removeOn,
+ out RuntimeMethodInfo fireOn,
+ out RuntimeMethodInfo getter,
+ out RuntimeMethodInfo setter,
+ out MethodInfo[] other,
+ out bool composedOfAllPrivateMethods,
+ out BindingFlags bindingFlags)
+ {
+ addOn = removeOn = fireOn = getter = setter = null;
+
+ Attributes attributes =
+ Attributes.ComposedOfAllPrivateMethods |
+ Attributes.ComposedOfAllVirtualMethods |
+ Attributes.ComposedOfNoPublicMembers |
+ Attributes.ComposedOfNoStaticMembers;
+
+ while(RuntimeTypeHandle.IsGenericVariable(reflectedType))
+ reflectedType = (RuntimeType)reflectedType.BaseType;
+
+ bool isInherited = declaringType != reflectedType;
+
+ List<MethodInfo> otherList = null;
+
+ MetadataEnumResult associatesData;
+ scope.Enum(MetadataTokenType.MethodDef, mdPropEvent, out associatesData);
+
+ int cAssociates = associatesData.Length / 2;
+
+ for (int i = 0; i < cAssociates; i++)
+ {
+ int methodDefToken = associatesData[i * 2];
+ MethodSemanticsAttributes semantics = (MethodSemanticsAttributes)associatesData[i * 2 + 1];
+
+ #region Assign each associate
+ RuntimeMethodInfo associateMethod =
+ AssignAssociates(methodDefToken, declaringType, reflectedType);
+
+ if (associateMethod == null)
+ continue;
+
+ MethodAttributes methAttr = associateMethod.Attributes;
+ bool isPrivate =(methAttr & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
+ bool isVirtual =(methAttr & MethodAttributes.Virtual) != 0;
+
+ MethodAttributes visibility = methAttr & MethodAttributes.MemberAccessMask;
+ bool isPublic = visibility == MethodAttributes.Public;
+ bool isStatic =(methAttr & MethodAttributes.Static) != 0;
+
+ if (isPublic)
+ {
+ attributes &= ~Attributes.ComposedOfNoPublicMembers;
+ attributes &= ~Attributes.ComposedOfAllPrivateMethods;
+ }
+ else if (!isPrivate)
+ {
+ attributes &= ~Attributes.ComposedOfAllPrivateMethods;
+ }
+
+ if (isStatic)
+ attributes &= ~Attributes.ComposedOfNoStaticMembers;
+
+ if (!isVirtual)
+ attributes &= ~Attributes.ComposedOfAllVirtualMethods;
+ #endregion
+
+ if (semantics == MethodSemanticsAttributes.Setter)
+ setter = associateMethod;
+ else if (semantics == MethodSemanticsAttributes.Getter)
+ getter = associateMethod;
+ else if (semantics == MethodSemanticsAttributes.Fire)
+ fireOn = associateMethod;
+ else if (semantics == MethodSemanticsAttributes.AddOn)
+ addOn = associateMethod;
+ else if (semantics == MethodSemanticsAttributes.RemoveOn)
+ removeOn = associateMethod;
+ else
+ {
+ if (otherList == null)
+ otherList = new List<MethodInfo>(cAssociates);
+ otherList.Add(associateMethod);
+ }
+ }
+
+ bool isPseudoPublic = (attributes & Attributes.ComposedOfNoPublicMembers) == 0;
+ bool isPseudoStatic = (attributes & Attributes.ComposedOfNoStaticMembers) == 0;
+ bindingFlags = RuntimeType.FilterPreCalculate(isPseudoPublic, isInherited, isPseudoStatic);
+
+ composedOfAllPrivateMethods =(attributes & Attributes.ComposedOfAllPrivateMethods) != 0;
+
+ other = (otherList != null) ? otherList.ToArray() : null;
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Binder.cs b/src/mscorlib/src/System/Reflection/Binder.cs
new file mode 100644
index 0000000000..d06899f6c6
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Binder.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+//
+// This interface defines a set of methods which interact with reflection
+// during the binding process. This control allows systems to apply language
+// specific semantics to the binding and invocation process.
+//
+//
+namespace System.Reflection {
+ using System;
+ using System.Runtime.InteropServices;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Binder
+ {
+ // Given a set of methods that match the basic criteria, select a method to
+ // invoke. When this method is finished, we should have
+ public abstract MethodBase BindToMethod(BindingFlags bindingAttr,MethodBase[] match,ref Object[] args,
+ ParameterModifier[] modifiers,CultureInfo culture,String[] names, out Object state);
+
+ // Given a set of methods that match the basic criteria, select a method to
+ // invoke. When this method is finished, we should have
+ public abstract FieldInfo BindToField(BindingFlags bindingAttr,FieldInfo[] match,
+ Object value,CultureInfo culture);
+
+ // Given a set of methods that match the base criteria, select a method based
+ // upon an array of types. This method should return null if no method matchs
+ // the criteria.
+ public abstract MethodBase SelectMethod(BindingFlags bindingAttr,MethodBase[] match,
+ Type[] types,ParameterModifier[] modifiers);
+
+
+ // Given a set of propreties that match the base criteria, select one.
+ public abstract PropertyInfo SelectProperty(BindingFlags bindingAttr,PropertyInfo[] match,
+ Type returnType,Type[] indexes,ParameterModifier[] modifiers);
+
+ // ChangeType
+ // This method will convert the value into the property type.
+ // It throws a cast exception if this fails.
+ public abstract Object ChangeType(Object value,Type type,CultureInfo culture);
+
+ public abstract void ReorderArgumentArray(ref Object[] args, Object state);
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/BindingFlags.cs b/src/mscorlib/src/System/Reflection/BindingFlags.cs
new file mode 100644
index 0000000000..591dfbb249
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/BindingFlags.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// BindingFlags are a set of flags that control the binding and invocation process
+//
+// in Reflection. There are two processes. The first is selection of a Member which
+// is the binding phase. The second, is invocation. These flags control how this
+// process works.
+//
+//
+namespace System.Reflection {
+
+ using System;
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum BindingFlags
+ {
+
+ // NOTES: We have lookup masks defined in RuntimeType and Activator. If we
+ // change the lookup values then these masks may need to change also.
+
+ // a place holder for no flag specifed
+ Default = 0x00,
+
+ // These flags indicate what to search for when binding
+ IgnoreCase = 0x01, // Ignore the case of Names while searching
+ DeclaredOnly = 0x02, // Only look at the members declared on the Type
+ Instance = 0x04, // Include Instance members in search
+ Static = 0x08, // Include Static members in search
+ Public = 0x10, // Include Public members in search
+ NonPublic = 0x20, // Include Non-Public members in search
+ FlattenHierarchy = 0x40, // Rollup the statics into the class.
+
+ // These flags are used by InvokeMember to determine
+ // what type of member we are trying to Invoke.
+ // BindingAccess = 0xFF00;
+ InvokeMethod = 0x0100,
+ CreateInstance = 0x0200,
+ GetField = 0x0400,
+ SetField = 0x0800,
+ GetProperty = 0x1000,
+ SetProperty = 0x2000,
+
+ // These flags are also used by InvokeMember but they should only
+ // be used when calling InvokeMember on a COM object.
+ PutDispProperty = 0x4000,
+ PutRefDispProperty = 0x8000,
+
+ ExactBinding = 0x010000, // Bind with Exact Type matching, No Change type
+ SuppressChangeType = 0x020000,
+
+ // DefaultValueBinding will return the set of methods having ArgCount or
+ // more parameters. This is used for default values, etc.
+ OptionalParamBinding = 0x040000,
+
+ // These are a couple of misc attributes used
+ IgnoreReturn = 0x01000000, // This is used in COM Interop
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/CallingConventions.cs b/src/mscorlib/src/System/Reflection/CallingConventions.cs
new file mode 100644
index 0000000000..6ca11c9021
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/CallingConventions.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// CallingConventions is a set of Bits representing the calling conventions
+//
+// in the system.
+//
+//
+namespace System.Reflection {
+ using System.Runtime.InteropServices;
+ using System;
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum CallingConventions
+ {
+ //NOTE: If you change this please update COMMember.cpp. These
+ // are defined there.
+ Standard = 0x0001,
+ VarArgs = 0x0002,
+ Any = Standard | VarArgs,
+ HasThis = 0x0020,
+ ExplicitThis = 0x0040,
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ComInterfaces.cs b/src/mscorlib/src/System/Reflection/ComInterfaces.cs
new file mode 100644
index 0000000000..63438115fc
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ComInterfaces.cs
@@ -0,0 +1,673 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Security.Policy;
+
+namespace System.Runtime.InteropServices
+{
+ [GuidAttribute("BCA8B44D-AAD6-3A86-8AB7-03349F4F2DA2")]
+ [CLSCompliant(false)]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [TypeLibImportClassAttribute(typeof(System.Type))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Type
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region Type Members
+ Guid GUID { get; }
+ Module Module { get; }
+ Assembly Assembly { get; }
+ RuntimeTypeHandle TypeHandle { get; }
+ String FullName { get; }
+ String Namespace { get; }
+ String AssemblyQualifiedName { get; }
+ int GetArrayRank();
+ Type BaseType { get; }
+
+ ConstructorInfo[] GetConstructors(BindingFlags bindingAttr);
+ Type GetInterface(String name, bool ignoreCase);
+ Type[] GetInterfaces();
+ Type[] FindInterfaces(TypeFilter filter,Object filterCriteria);
+ EventInfo GetEvent(String name,BindingFlags bindingAttr);
+ EventInfo[] GetEvents();
+ EventInfo[] GetEvents(BindingFlags bindingAttr);
+ Type[] GetNestedTypes(BindingFlags bindingAttr);
+ Type GetNestedType(String name, BindingFlags bindingAttr);
+ MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr);
+ MemberInfo[] GetDefaultMembers();
+ MemberInfo[] FindMembers(MemberTypes memberType,BindingFlags bindingAttr,MemberFilter filter,Object filterCriteria);
+ Type GetElementType();
+ bool IsSubclassOf(Type c);
+ bool IsInstanceOfType(Object o);
+ bool IsAssignableFrom(Type c);
+ InterfaceMapping GetInterfaceMap(Type interfaceType);
+ MethodInfo GetMethod(String name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers);
+ MethodInfo GetMethod(String name, BindingFlags bindingAttr);
+ MethodInfo[] GetMethods(BindingFlags bindingAttr);
+ FieldInfo GetField(String name, BindingFlags bindingAttr);
+ FieldInfo[] GetFields(BindingFlags bindingAttr);
+ PropertyInfo GetProperty(String name, BindingFlags bindingAttr);
+ PropertyInfo GetProperty(String name,BindingFlags bindingAttr,Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers);
+ PropertyInfo[] GetProperties(BindingFlags bindingAttr);
+ MemberInfo[] GetMember(String name, BindingFlags bindingAttr);
+ MemberInfo[] GetMembers(BindingFlags bindingAttr);
+ Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters);
+ Type UnderlyingSystemType
+ {
+ get;
+ }
+
+ Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args, CultureInfo culture);
+ Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args);
+ ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
+ ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers);
+ ConstructorInfo GetConstructor(Type[] types);
+ ConstructorInfo[] GetConstructors();
+ ConstructorInfo TypeInitializer
+ {
+ get;
+ }
+
+ MethodInfo GetMethod(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers);
+ MethodInfo GetMethod(String name, Type[] types, ParameterModifier[] modifiers);
+ MethodInfo GetMethod(String name, Type[] types);
+ MethodInfo GetMethod(String name);
+ MethodInfo[] GetMethods();
+ FieldInfo GetField(String name);
+ FieldInfo[] GetFields();
+ Type GetInterface(String name);
+ EventInfo GetEvent(String name);
+ PropertyInfo GetProperty(String name, Type returnType, Type[] types,ParameterModifier[] modifiers);
+ PropertyInfo GetProperty(String name, Type returnType, Type[] types);
+ PropertyInfo GetProperty(String name, Type[] types);
+ PropertyInfo GetProperty(String name, Type returnType);
+ PropertyInfo GetProperty(String name);
+ PropertyInfo[] GetProperties();
+ Type[] GetNestedTypes();
+ Type GetNestedType(String name);
+ MemberInfo[] GetMember(String name);
+ MemberInfo[] GetMembers();
+ TypeAttributes Attributes { get; }
+ bool IsNotPublic { get; }
+ bool IsPublic { get; }
+ bool IsNestedPublic { get; }
+ bool IsNestedPrivate { get; }
+ bool IsNestedFamily { get; }
+ bool IsNestedAssembly { get; }
+ bool IsNestedFamANDAssem { get; }
+ bool IsNestedFamORAssem { get; }
+ bool IsAutoLayout { get; }
+ bool IsLayoutSequential { get; }
+ bool IsExplicitLayout { get; }
+ bool IsClass { get; }
+ bool IsInterface { get; }
+ bool IsValueType { get; }
+ bool IsAbstract { get; }
+ bool IsSealed { get; }
+ bool IsEnum { get; }
+ bool IsSpecialName { get; }
+ bool IsImport { get; }
+ bool IsSerializable { get; }
+ bool IsAnsiClass { get; }
+ bool IsUnicodeClass { get; }
+ bool IsAutoClass { get; }
+ bool IsArray { get; }
+ bool IsByRef { get; }
+ bool IsPointer { get; }
+ bool IsPrimitive { get; }
+ bool IsCOMObject { get; }
+ bool HasElementType { get; }
+ bool IsContextful { get; }
+ bool IsMarshalByRef { get; }
+ bool Equals(Type o);
+ #endregion
+#endif
+ }
+
+ [GuidAttribute("17156360-2f1a-384a-bc52-fde93c215c5b")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Assembly))]
+ [CLSCompliant(false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Assembly
+ {
+#if !FEATURE_CORECLR
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region Assembly Members
+ String CodeBase {
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#endif
+get; }
+ String EscapedCodeBase { get; }
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ AssemblyName GetName();
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ AssemblyName GetName(bool copiedName);
+ String FullName { get; }
+ MethodInfo EntryPoint { get; }
+ Type GetType(String name);
+ Type GetType(String name, bool throwOnError);
+ Type[] GetExportedTypes();
+ Type[] GetTypes();
+ Stream GetManifestResourceStream(Type type, String name);
+ Stream GetManifestResourceStream(String name);
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ FileStream GetFile(String name);
+ FileStream[] GetFiles();
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ FileStream[] GetFiles(bool getResourceModules);
+ String[] GetManifestResourceNames();
+ ManifestResourceInfo GetManifestResourceInfo(String resourceName);
+ String Location {
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#endif
+get; }
+#if FEATURE_CAS_POLICY
+ Evidence Evidence { get; }
+#endif // FEATURE_CAS_POLICY
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+#if FEATURE_SERIALIZATION
+ [System.Security.SecurityCritical] // auto-generated_required
+ void GetObjectData(SerializationInfo info, StreamingContext context);
+#endif
+ [method: System.Security.SecurityCritical]
+ event ModuleResolveEventHandler ModuleResolve;
+ Type GetType(String name, bool throwOnError, bool ignoreCase);
+ Assembly GetSatelliteAssembly(CultureInfo culture);
+ Assembly GetSatelliteAssembly(CultureInfo culture, Version version);
+#if FEATURE_MULTIMODULE_ASSEMBLIES
+ Module LoadModule(String moduleName, byte[] rawModule);
+ Module LoadModule(String moduleName, byte[] rawModule, byte[] rawSymbolStore);
+#endif
+ Object CreateInstance(String typeName);
+ Object CreateInstance(String typeName, bool ignoreCase);
+ Object CreateInstance(String typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes);
+ Module[] GetLoadedModules();
+ Module[] GetLoadedModules(bool getResourceModules);
+ Module[] GetModules();
+ Module[] GetModules(bool getResourceModules);
+ Module GetModule(String name);
+ AssemblyName[] GetReferencedAssemblies();
+ bool GlobalAssemblyCache { get; }
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("f7102fa9-cabb-3a74-a6da-b4567ef1b079")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.MemberInfo))]
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _MemberInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("6240837A-707F-3181-8E98-A36AE086766B")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.MethodBase))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _MethodBase
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region MethodBase Members
+ ParameterInfo[] GetParameters();
+ MethodImplAttributes GetMethodImplementationFlags();
+ RuntimeMethodHandle MethodHandle { get; }
+ MethodAttributes Attributes { get; }
+ CallingConventions CallingConvention { get; }
+ Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+ bool IsPublic { get; }
+ bool IsPrivate { get; }
+ bool IsFamily { get; }
+ bool IsAssembly { get; }
+ bool IsFamilyAndAssembly { get; }
+ bool IsFamilyOrAssembly { get; }
+ bool IsStatic { get; }
+ bool IsFinal { get; }
+ bool IsVirtual { get; }
+ bool IsHideBySig { get; }
+ bool IsAbstract { get; }
+ bool IsSpecialName { get; }
+ bool IsConstructor { get; }
+ Object Invoke(Object obj, Object[] parameters);
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("FFCC1B5D-ECB8-38DD-9B01-3DC8ABC2AA5F")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.MethodInfo))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _MethodInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region MethodBase Members
+ ParameterInfo[] GetParameters();
+ MethodImplAttributes GetMethodImplementationFlags();
+ RuntimeMethodHandle MethodHandle { get; }
+ MethodAttributes Attributes { get; }
+ CallingConventions CallingConvention { get; }
+ Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+ bool IsPublic { get; }
+ bool IsPrivate { get; }
+ bool IsFamily { get; }
+ bool IsAssembly { get; }
+ bool IsFamilyAndAssembly { get; }
+ bool IsFamilyOrAssembly { get; }
+ bool IsStatic { get; }
+ bool IsFinal { get; }
+ bool IsVirtual { get; }
+ bool IsHideBySig { get; }
+ bool IsAbstract { get; }
+ bool IsSpecialName { get; }
+ bool IsConstructor { get; }
+ Object Invoke(Object obj, Object[] parameters);
+ #endregion
+
+ #region MethodInfo Members
+ Type ReturnType { get; }
+ ICustomAttributeProvider ReturnTypeCustomAttributes { get; }
+ MethodInfo GetBaseDefinition();
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("E9A19478-9646-3679-9B10-8411AE1FD57D")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.ConstructorInfo))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ConstructorInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region MethodBase Members
+ ParameterInfo[] GetParameters();
+ MethodImplAttributes GetMethodImplementationFlags();
+ RuntimeMethodHandle MethodHandle { get; }
+ MethodAttributes Attributes { get; }
+ CallingConventions CallingConvention { get; }
+ Object Invoke_2(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+ bool IsPublic { get; }
+ bool IsPrivate { get; }
+ bool IsFamily { get; }
+ bool IsAssembly { get; }
+ bool IsFamilyAndAssembly { get; }
+ bool IsFamilyOrAssembly { get; }
+ bool IsStatic { get; }
+ bool IsFinal { get; }
+ bool IsVirtual { get; }
+ bool IsHideBySig { get; }
+ bool IsAbstract { get; }
+ bool IsSpecialName { get; }
+ bool IsConstructor { get; }
+ Object Invoke_3(Object obj, Object[] parameters);
+ #endregion
+
+ #region ConstructorInfo
+ Object Invoke_4(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+ Object Invoke_5(Object[] parameters);
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("8A7C1442-A9FB-366B-80D8-4939FFA6DBE0")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.FieldInfo))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _FieldInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region FieldInfo Members
+ Type FieldType { get; }
+ Object GetValue(Object obj);
+ Object GetValueDirect(TypedReference obj);
+ void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture);
+ void SetValueDirect(TypedReference obj,Object value);
+ RuntimeFieldHandle FieldHandle { get; }
+ FieldAttributes Attributes { get; }
+ void SetValue(Object obj, Object value);
+ bool IsPublic { get; }
+ bool IsPrivate { get; }
+ bool IsFamily { get; }
+ bool IsAssembly { get; }
+ bool IsFamilyAndAssembly { get; }
+ bool IsFamilyOrAssembly { get; }
+ bool IsStatic { get; }
+ bool IsInitOnly { get; }
+ bool IsLiteral { get; }
+ bool IsNotSerialized { get; }
+ bool IsSpecialName { get; }
+ bool IsPinvokeImpl { get; }
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("F59ED4E4-E68F-3218-BD77-061AA82824BF")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.PropertyInfo))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _PropertyInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region Property Members
+ Type PropertyType { get; }
+ Object GetValue(Object obj,Object[] index);
+ Object GetValue(Object obj,BindingFlags invokeAttr,Binder binder, Object[] index, CultureInfo culture);
+ void SetValue(Object obj, Object value, Object[] index);
+ void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture);
+ MethodInfo[] GetAccessors(bool nonPublic);
+ MethodInfo GetGetMethod(bool nonPublic);
+ MethodInfo GetSetMethod(bool nonPublic);
+ ParameterInfo[] GetIndexParameters();
+ PropertyAttributes Attributes { get; }
+ bool CanRead { get; }
+ bool CanWrite { get; }
+ MethodInfo[] GetAccessors();
+ MethodInfo GetGetMethod();
+ MethodInfo GetSetMethod();
+ bool IsSpecialName { get; }
+ #endregion
+#endif
+ }
+
+
+ [GuidAttribute("9DE59C64-D889-35A1-B897-587D74469E5B")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.EventInfo))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _EventInfo
+ {
+#if !FEATURE_CORECLR
+ #region IDispatch Members
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ #endregion
+
+ #region Object Members
+ String ToString();
+ bool Equals(Object other);
+ int GetHashCode();
+ Type GetType();
+ #endregion
+
+ #region MemberInfo Members
+ MemberTypes MemberType { get; }
+ String Name { get; }
+ Type DeclaringType { get; }
+ Type ReflectedType { get; }
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+ Object[] GetCustomAttributes(bool inherit);
+ bool IsDefined(Type attributeType, bool inherit);
+ #endregion
+
+ #region EventInfo Members
+ MethodInfo GetAddMethod(bool nonPublic);
+ MethodInfo GetRemoveMethod(bool nonPublic);
+ MethodInfo GetRaiseMethod(bool nonPublic);
+ EventAttributes Attributes { get; }
+ MethodInfo GetAddMethod();
+ MethodInfo GetRemoveMethod();
+ MethodInfo GetRaiseMethod();
+ void AddEventHandler(Object target, Delegate handler);
+ void RemoveEventHandler(Object target, Delegate handler);
+ Type EventHandlerType { get; }
+ bool IsSpecialName { get; }
+ bool IsMulticast { get; }
+ #endregion
+#endif
+ }
+
+ [GuidAttribute("993634C4-E47A-32CC-BE08-85F567DC27D6")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.ParameterInfo))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ParameterInfo
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("D002E9BA-D9E3-3749-B1D3-D565A08B13E7")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Module))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Module
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("B42B6AAC-317E-34D5-9FA9-093BB4160C50")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.AssemblyName))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _AssemblyName
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/ConstructorInfo.cs b/src/mscorlib/src/System/Reflection/ConstructorInfo.cs
new file mode 100644
index 0000000000..d5b5cc36eb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ConstructorInfo.cs
@@ -0,0 +1,781 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Metadata;
+#endif //FEATURE_REMOTING
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using MemberListType = System.RuntimeType.MemberListType;
+ using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+ using System.Runtime.CompilerServices;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ConstructorInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class ConstructorInfo : MethodBase, _ConstructorInfo
+ {
+ #region Static Members
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public readonly static String ConstructorName = ".ctor";
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public readonly static String TypeConstructorName = ".cctor";
+ #endregion
+
+ #region Constructor
+ protected ConstructorInfo() { }
+ #endregion
+
+ public static bool operator ==(ConstructorInfo left, ConstructorInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeConstructorInfo || right is RuntimeConstructorInfo)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(ConstructorInfo left, ConstructorInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Internal Members
+ internal virtual Type GetReturnType() { throw new NotImplementedException(); }
+ #endregion
+
+ #region MemberInfo Overrides
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Constructor; } }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public abstract Object Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+ #endregion
+
+ #region Public Members
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public Object Invoke(Object[] parameters)
+ {
+ // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
+ // But to maintain backward compatibility we can't switch to calling an
+ // internal overload that takes a stack mark.
+ // Fortunately the stack walker skips all the reflection invocation frames including this one.
+ // So this method will never be returned by the stack walker as the caller.
+ // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
+ return Invoke(BindingFlags.Default, null, parameters, null);
+ }
+ #endregion
+
+#if !FEATURE_CORECLR
+ #region COM Interop Support
+ Type _ConstructorInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ Object _ConstructorInfo.Invoke_2(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ return Invoke(obj, invokeAttr, binder, parameters, culture);
+ }
+
+ Object _ConstructorInfo.Invoke_3(Object obj, Object[] parameters)
+ {
+ return Invoke(obj, parameters);
+ }
+
+ Object _ConstructorInfo.Invoke_4(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ return Invoke(invokeAttr, binder, parameters, culture);
+ }
+
+ Object _ConstructorInfo.Invoke_5(Object[] parameters)
+ {
+ return Invoke(parameters);
+ }
+
+ void _ConstructorInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ConstructorInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ConstructorInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _ConstructorInfo.Invoke in VM\DangerousAPIs.h and
+ // include _ConstructorInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _ConstructorInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+#endif
+ }
+
+ [Serializable]
+ internal sealed class RuntimeConstructorInfo : ConstructorInfo, ISerializable, IRuntimeMethodInfo
+ {
+ #region Private Data Members
+ private volatile RuntimeType m_declaringType;
+ private RuntimeTypeCache m_reflectedTypeCache;
+ private string m_toString;
+ private ParameterInfo[] m_parameters = null; // Created lazily when GetParameters() is called.
+#pragma warning disable 169
+ private object _empty1; // These empties are used to ensure that RuntimeConstructorInfo and RuntimeMethodInfo are have a layout which is sufficiently similar
+ private object _empty2;
+ private object _empty3;
+#pragma warning restore 169
+ private IntPtr m_handle;
+ private MethodAttributes m_methodAttributes;
+ private BindingFlags m_bindingFlags;
+ private volatile Signature m_signature;
+ private INVOCATION_FLAGS m_invocationFlags;
+
+#if FEATURE_APPX
+ private bool IsNonW8PFrameworkAPI()
+ {
+ if (DeclaringType.IsArray && IsPublic && !IsStatic)
+ return false;
+
+ RuntimeAssembly rtAssembly = GetRuntimeAssembly();
+ if (rtAssembly.IsFrameworkAssembly())
+ {
+ int ctorToken = rtAssembly.InvocableAttributeCtorToken;
+ if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
+ !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
+ return true;
+ }
+
+ if (GetRuntimeType().IsNonW8PFrameworkAPI())
+ return true;
+
+ return false;
+ }
+
+ internal override bool IsDynamicallyInvokable
+ {
+ get
+ {
+ return !AppDomain.ProfileAPICheck || !IsNonW8PFrameworkAPI();
+ }
+ }
+#endif // FEATURE_APPX
+
+ internal INVOCATION_FLAGS InvocationFlags
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_IS_CTOR; // this is a given
+
+ Type declaringType = DeclaringType;
+
+ //
+ // first take care of all the NO_INVOKE cases.
+ if ( declaringType == typeof(void) ||
+ (declaringType != null && declaringType.ContainsGenericParameters) ||
+ ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) ||
+ ((Attributes & MethodAttributes.RequireSecObject) == MethodAttributes.RequireSecObject))
+ {
+ // We don't need other flags if this method cannot be invoked
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
+ }
+ else if (IsStatic || declaringType != null && declaringType.IsAbstract)
+ {
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE;
+ }
+ else
+ {
+ // this should be an invocable method, determine the other flags that participate in invocation
+ invocationFlags |= RuntimeMethodHandle.GetSecurityFlags(this);
+
+ if ( (invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) == 0 &&
+ ((Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public ||
+ (declaringType != null && declaringType.NeedsReflectionSecurityCheck)) )
+ {
+ // If method is non-public, or declaring type is not visible
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
+ }
+
+ // Check for attempt to create a delegate class, we demand unmanaged
+ // code permission for this since it's hard to validate the target address.
+ if (typeof(Delegate).IsAssignableFrom(DeclaringType))
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR;
+ }
+
+#if FEATURE_APPX
+ if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
+#endif // FEATURE_APPX
+
+ m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ }
+
+ return m_invocationFlags;
+ }
+ }
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeConstructorInfo(
+ RuntimeMethodHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache,
+ MethodAttributes methodAttributes, BindingFlags bindingFlags)
+ {
+ Contract.Ensures(methodAttributes == RuntimeMethodHandle.GetAttributes(handle));
+
+ m_bindingFlags = bindingFlags;
+ m_reflectedTypeCache = reflectedTypeCache;
+ m_declaringType = declaringType;
+ m_handle = handle.Value;
+ m_methodAttributes = methodAttributes;
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
+ // This member is currently being used by Remoting for caching remoting data. If you
+ // need to cache data here, talk to the Remoting team to work out a mechanism, so that
+ // both caching systems can happily work together.
+ private RemotingMethodCachedData m_cachedData;
+
+ internal RemotingMethodCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingMethodCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingMethodCachedData(this);
+ RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+
+ #region NonPublic Methods
+ RuntimeMethodHandleInternal IRuntimeMethodInfo.Value
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ return new RuntimeMethodHandleInternal(m_handle);
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RuntimeConstructorInfo m = o as RuntimeConstructorInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_handle == m_handle;
+ }
+
+ private Signature Signature
+ {
+ get
+ {
+ if (m_signature == null)
+ m_signature = new Signature(this, m_declaringType);
+
+ return m_signature;
+ }
+ }
+
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ private void CheckConsistency(Object target)
+ {
+ if (target == null && IsStatic)
+ return;
+
+ if (!m_declaringType.IsInstanceOfType(target))
+ {
+ if (target == null)
+ throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatMethReqTarg"));
+
+ throw new TargetException(Environment.GetResourceString("RFLCT.Targ_ITargMismatch"));
+ }
+ }
+
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+
+ // Differs from MethodHandle in that it will return a valid handle even for reflection only loaded types
+ internal RuntimeMethodHandle GetMethodHandle()
+ {
+ return new RuntimeMethodHandle(this);
+ }
+
+ internal bool IsOverloaded
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetConstructorList(MemberListType.CaseSensitive, Name).Length > 1;
+ }
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ // "Void" really doesn't make sense here. But we'll keep it for compat reasons.
+ if (m_toString == null)
+ m_toString = "Void " + FormatNameAndSig();
+
+ return m_toString;
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return RuntimeMethodHandle.GetName(this); }
+ }
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override MemberTypes MemberType { get { return MemberTypes.Constructor; } }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return m_reflectedTypeCache.IsGlobal ? null : m_declaringType;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return m_reflectedTypeCache.IsGlobal ? null : ReflectedTypeInternal;
+ }
+ }
+
+ public override int MetadataToken
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return RuntimeMethodHandle.GetMethodDef(this); }
+ }
+ public override Module Module
+ {
+ get { return GetRuntimeModule(); }
+ }
+
+ internal RuntimeType GetRuntimeType() { return m_declaringType; }
+ internal RuntimeModule GetRuntimeModule() { return RuntimeTypeHandle.GetModule(m_declaringType); }
+ internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); }
+ #endregion
+
+ #region MethodBase Overrides
+
+ // This seems to always returns System.Void.
+ internal override Type GetReturnType() { return Signature.ReturnType; }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal override ParameterInfo[] GetParametersNoCopy()
+ {
+ if (m_parameters == null)
+ m_parameters = RuntimeParameterInfo.GetParameters(this, this, Signature);
+
+ return m_parameters;
+ }
+
+ [Pure]
+ public override ParameterInfo[] GetParameters()
+ {
+ ParameterInfo[] parameters = GetParametersNoCopy();
+
+ if (parameters.Length == 0)
+ return parameters;
+
+ ParameterInfo[] ret = new ParameterInfo[parameters.Length];
+ Array.Copy(parameters, ret, parameters.Length);
+ return ret;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return RuntimeMethodHandle.GetImplAttributes(this);
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get
+ {
+ Type declaringType = DeclaringType;
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+ return new RuntimeMethodHandle(this);
+ }
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get
+ {
+ return m_methodAttributes;
+ }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ return Signature.CallingConvention;
+ }
+ }
+
+ internal static void CheckCanCreateInstance(Type declaringType, bool isVarArg)
+ {
+ if (declaringType == null)
+ throw new ArgumentNullException("declaringType");
+ Contract.EndContractBlock();
+
+ // ctor is ReflectOnly
+ if (declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke"));
+
+ // ctor is declared on interface class
+ else if (declaringType.IsInterface)
+ throw new MemberAccessException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Acc_CreateInterfaceEx"), declaringType));
+
+ // ctor is on an abstract class
+ else if (declaringType.IsAbstract)
+ throw new MemberAccessException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Acc_CreateAbstEx"), declaringType));
+
+ // ctor is on a class that contains stack pointers
+ else if (declaringType.GetRootElementType() == typeof(ArgIterator))
+ throw new NotSupportedException();
+
+ // ctor is vararg
+ else if (isVarArg)
+ throw new NotSupportedException();
+
+ // ctor is generic or on a generic class
+ else if (declaringType.ContainsGenericParameters)
+ {
+ throw new MemberAccessException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Acc_CreateGenericEx"), declaringType));
+ }
+
+ // ctor is declared on System.Void
+ else if (declaringType == typeof(void))
+ throw new MemberAccessException(Environment.GetResourceString("Access_Void"));
+ }
+
+ internal void ThrowNoInvokeException()
+ {
+ CheckCanCreateInstance(DeclaringType, (CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs);
+
+ // ctor is .cctor
+ if ((Attributes & MethodAttributes.Static) == MethodAttributes.Static)
+ throw new MemberAccessException(Environment.GetResourceString("Acc_NotClassInit"));
+
+ throw new TargetException();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Object Invoke(
+ Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
+ ThrowNoInvokeException();
+
+ // check basic method consistency. This call will throw if there are problems in the target/method relationship
+ CheckConsistency(obj);
+
+#if FEATURE_APPX
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
+ }
+#endif
+
+ if (obj != null)
+ {
+
+#if FEATURE_CORECLR
+ // For unverifiable code, we require the caller to be critical.
+ // Adding the INVOCATION_FLAGS_NEED_SECURITY flag makes that check happen
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
+#else // FEATURE_CORECLR
+ new SecurityPermission(SecurityPermissionFlag.SkipVerification).Demand();
+#endif // FEATURE_CORECLR
+
+ }
+
+#if !FEATURE_CORECLR
+ if ((invocationFlags &(INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
+ {
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0)
+ CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess);
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
+ RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags);
+ }
+#endif // !FEATURE_CORECLR
+
+ Signature sig = Signature;
+
+ // get the signature
+ int formalCount = sig.Arguments.Length;
+ int actualCount =(parameters != null) ? parameters.Length : 0;
+ if (formalCount != actualCount)
+ throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
+
+ // if we are here we passed all the previous checks. Time to look at the arguments
+ if (actualCount > 0)
+ {
+ Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig);
+ Object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, sig, false);
+ // copy out. This should be made only if ByRef are present.
+ for (int index = 0; index < arguments.Length; index++)
+ parameters[index] = arguments[index];
+ return retValue;
+ }
+ return RuntimeMethodHandle.InvokeMethod(obj, null, sig, false);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // overrides SC member
+#pragma warning disable 618
+ [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)]
+#pragma warning restore 618
+ public override MethodBody GetMethodBody()
+ {
+ MethodBody mb = RuntimeMethodHandle.GetMethodBody(this, ReflectedTypeInternal);
+ if (mb != null)
+ mb.m_methodBase = this;
+ return mb;
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get { return RuntimeMethodHandle.IsSecurityCritical(this); }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ get { return RuntimeMethodHandle.IsSecurityTransparent(this); }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ return (DeclaringType != null && DeclaringType.ContainsGenericParameters);
+ }
+ }
+ #endregion
+
+ #region ConstructorInfo Overrides
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Object Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+
+ // get the declaring TypeHandle early for consistent exceptions in IntrospectionOnly context
+ RuntimeTypeHandle declaringTypeHandle = m_declaringType.TypeHandle;
+
+ if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS | INVOCATION_FLAGS.INVOCATION_FLAGS_NO_CTOR_INVOKE)) != 0)
+ ThrowNoInvokeException();
+
+#if FEATURE_APPX
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
+ }
+#endif
+
+#if !FEATURE_CORECLR
+ if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY | INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR)) != 0)
+ {
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0)
+ CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess);
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
+ RuntimeMethodHandle.PerformSecurityCheck(null, this, m_declaringType, (uint)(m_invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_CONSTRUCTOR_INVOKE));
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_IS_DELEGATE_CTOR) != 0)
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+ }
+#endif // !FEATURE_CORECLR
+
+ // get the signature
+ Signature sig = Signature;
+
+ int formalCount = sig.Arguments.Length;
+ int actualCount =(parameters != null) ? parameters.Length : 0;
+ if (formalCount != actualCount)
+ throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
+
+ // We don't need to explicitly invoke the class constructor here,
+ // JIT/NGen will insert the call to .cctor in the instance ctor.
+
+ // if we are here we passed all the previous checks. Time to look at the arguments
+ if (actualCount > 0)
+ {
+ Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig);
+ Object retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, true);
+ // copy out. This should be made only if ByRef are present.
+ for (int index = 0; index < arguments.Length; index++)
+ parameters[index] = arguments[index];
+ return retValue;
+ }
+ return RuntimeMethodHandle.InvokeMethod(null, null, sig, true);
+ }
+ #endregion
+
+ #region ISerializable Implementation
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+ MemberInfoSerializationHolder.GetSerializationInfo(
+ info,
+ Name,
+ ReflectedTypeInternal,
+ ToString(),
+ SerializationToString(),
+ MemberTypes.Constructor,
+ null);
+ }
+
+ internal string SerializationToString()
+ {
+ // We don't need the return type for constructors.
+ return FormatNameAndSig(true);
+ }
+
+ internal void SerializationInvoke(Object target, SerializationInfo info, StreamingContext context)
+ {
+ RuntimeMethodHandle.SerializationInvoke(this, target, info, ref context);
+ }
+ #endregion
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/CustomAttribute.cs b/src/mscorlib/src/System/Reflection/CustomAttribute.cs
new file mode 100644
index 0000000000..463c976357
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/CustomAttribute.cs
@@ -0,0 +1,2527 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Collections;
+using System.Collections.Generic;
+using System.Resources;
+using System.Diagnostics;
+using System.Diagnostics.Tracing;
+using System.Globalization;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.Reflection
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CustomAttributeData
+ {
+ #region Public Static Members
+ public static IList<CustomAttributeData> GetCustomAttributes(MemberInfo target)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+
+ return target.GetCustomAttributesData();
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(Module target)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ Contract.EndContractBlock();
+
+ return target.GetCustomAttributesData();
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(Assembly target)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ Contract.EndContractBlock();
+
+ return target.GetCustomAttributesData();
+ }
+
+ public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo target)
+ {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ Contract.EndContractBlock();
+
+ return target.GetCustomAttributesData();
+ }
+ #endregion
+
+ #region Internal Static Members
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeType target)
+ {
+ Contract.Assert(target != null);
+
+ IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+
+ int pcaCount = 0;
+ Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeType)target, typeof(object) as RuntimeType, true, out pcaCount);
+
+ if (pcaCount == 0)
+ return cad;
+
+ CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
+ cad.CopyTo(pca, pcaCount);
+ for (int i = 0; i < pcaCount; i++)
+ {
+ pca[i] = new CustomAttributeData(a[i]);
+ }
+
+ return Array.AsReadOnly(pca);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeFieldInfo target)
+ {
+ Contract.Assert(target != null);
+
+ IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+
+ int pcaCount = 0;
+ Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeFieldInfo)target, typeof(object) as RuntimeType, out pcaCount);
+
+ if (pcaCount == 0)
+ return cad;
+
+ CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
+ cad.CopyTo(pca, pcaCount);
+ for (int i = 0; i < pcaCount; i++)
+ {
+ pca[i] = new CustomAttributeData(a[i]);
+ }
+
+ return Array.AsReadOnly(pca);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeMethodInfo target)
+ {
+ Contract.Assert(target != null);
+
+ IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+
+ int pcaCount = 0;
+ Attribute[] a = PseudoCustomAttribute.GetCustomAttributes((RuntimeMethodInfo)target, typeof(object) as RuntimeType, true, out pcaCount);
+
+ if (pcaCount == 0)
+ return cad;
+
+ CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
+ cad.CopyTo(pca, pcaCount);
+ for (int i = 0; i < pcaCount; i++)
+ {
+ pca[i] = new CustomAttributeData(a[i]);
+ }
+
+ return Array.AsReadOnly(pca);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeConstructorInfo target)
+ {
+ Contract.Assert(target != null);
+
+ return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeEventInfo target)
+ {
+ Contract.Assert(target != null);
+
+ return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimePropertyInfo target)
+ {
+ Contract.Assert(target != null);
+
+ return GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeModule target)
+ {
+ Contract.Assert(target != null);
+
+ if (target.IsResource())
+ return new List<CustomAttributeData>();
+
+ return GetCustomAttributes(target, target.MetadataToken);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeAssembly target)
+ {
+ Contract.Assert(target != null);
+
+ IList<CustomAttributeData> cad = GetCustomAttributes((RuntimeModule)target.ManifestModule, RuntimeAssembly.GetToken(target.GetNativeHandle()));
+
+ int pcaCount = 0;
+ Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, false, out pcaCount);
+
+ if (pcaCount == 0)
+ return cad;
+
+ CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
+ cad.CopyTo(pca, pcaCount);
+ for (int i = 0; i < pcaCount; i++)
+ {
+ pca[i] = new CustomAttributeData(a[i]);
+ }
+
+ return Array.AsReadOnly(pca);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IList<CustomAttributeData> GetCustomAttributesInternal(RuntimeParameterInfo target)
+ {
+ Contract.Assert(target != null);
+
+ IList<CustomAttributeData> cad = GetCustomAttributes(target.GetRuntimeModule(), target.MetadataToken);
+
+ int pcaCount = 0;
+ Attribute[] a = PseudoCustomAttribute.GetCustomAttributes(target, typeof(object) as RuntimeType, out pcaCount);
+
+ if (pcaCount == 0)
+ return cad;
+
+ CustomAttributeData[] pca = new CustomAttributeData[cad.Count + pcaCount];
+ cad.CopyTo(pca, pcaCount);
+ for (int i = 0; i < pcaCount; i++)
+ pca[i] = new CustomAttributeData(a[i]);
+
+ return Array.AsReadOnly(pca);
+ }
+ #endregion
+
+ #region Private Static Methods
+ private static CustomAttributeEncoding TypeToCustomAttributeEncoding(RuntimeType type)
+ {
+ if (type == (RuntimeType)typeof(int))
+ return CustomAttributeEncoding.Int32;
+
+ if (type.IsEnum)
+ return CustomAttributeEncoding.Enum;
+
+ if (type == (RuntimeType)typeof(string))
+ return CustomAttributeEncoding.String;
+
+ if (type == (RuntimeType)typeof(Type))
+ return CustomAttributeEncoding.Type;
+
+ if (type == (RuntimeType)typeof(object))
+ return CustomAttributeEncoding.Object;
+
+ if (type.IsArray)
+ return CustomAttributeEncoding.Array;
+
+ if (type == (RuntimeType)typeof(char))
+ return CustomAttributeEncoding.Char;
+
+ if (type == (RuntimeType)typeof(bool))
+ return CustomAttributeEncoding.Boolean;
+
+ if (type == (RuntimeType)typeof(byte))
+ return CustomAttributeEncoding.Byte;
+
+ if (type == (RuntimeType)typeof(sbyte))
+ return CustomAttributeEncoding.SByte;
+
+ if (type == (RuntimeType)typeof(short))
+ return CustomAttributeEncoding.Int16;
+
+ if (type == (RuntimeType)typeof(ushort))
+ return CustomAttributeEncoding.UInt16;
+
+ if (type == (RuntimeType)typeof(uint))
+ return CustomAttributeEncoding.UInt32;
+
+ if (type == (RuntimeType)typeof(long))
+ return CustomAttributeEncoding.Int64;
+
+ if (type == (RuntimeType)typeof(ulong))
+ return CustomAttributeEncoding.UInt64;
+
+ if (type == (RuntimeType)typeof(float))
+ return CustomAttributeEncoding.Float;
+
+ if (type == (RuntimeType)typeof(double))
+ return CustomAttributeEncoding.Double;
+
+ // System.Enum is neither an Enum nor a Class
+ if (type == (RuntimeType)typeof(Enum))
+ return CustomAttributeEncoding.Object;
+
+ if (type.IsClass)
+ return CustomAttributeEncoding.Object;
+
+ if (type.IsInterface)
+ return CustomAttributeEncoding.Object;
+
+ if (type.IsValueType)
+ return CustomAttributeEncoding.Undefined;
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKindOfTypeForCA"), "type");
+ }
+ private static CustomAttributeType InitCustomAttributeType(RuntimeType parameterType)
+ {
+ CustomAttributeEncoding encodedType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
+ CustomAttributeEncoding encodedArrayType = CustomAttributeEncoding.Undefined;
+ CustomAttributeEncoding encodedEnumType = CustomAttributeEncoding.Undefined;
+ string enumName = null;
+
+ if (encodedType == CustomAttributeEncoding.Array)
+ {
+ parameterType = (RuntimeType)parameterType.GetElementType();
+ encodedArrayType = CustomAttributeData.TypeToCustomAttributeEncoding(parameterType);
+ }
+
+ if (encodedType == CustomAttributeEncoding.Enum || encodedArrayType == CustomAttributeEncoding.Enum)
+ {
+ encodedEnumType = TypeToCustomAttributeEncoding((RuntimeType)Enum.GetUnderlyingType(parameterType));
+ enumName = parameterType.AssemblyQualifiedName;
+ }
+
+ return new CustomAttributeType(encodedType, encodedArrayType, encodedEnumType, enumName);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ private static IList<CustomAttributeData> GetCustomAttributes(RuntimeModule module, int tkTarget)
+ {
+ CustomAttributeRecord[] records = GetCustomAttributeRecords(module, tkTarget);
+
+ CustomAttributeData[] customAttributes = new CustomAttributeData[records.Length];
+ for (int i = 0; i < records.Length; i++)
+ customAttributes[i] = new CustomAttributeData(module, records[i]);
+
+ return Array.AsReadOnly(customAttributes);
+ }
+ #endregion
+
+ #region Internal Static Members
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static CustomAttributeRecord[] GetCustomAttributeRecords(RuntimeModule module, int targetToken)
+ {
+ MetadataImport scope = module.MetadataImport;
+
+ MetadataEnumResult tkCustomAttributeTokens;
+ scope.EnumCustomAttributes(targetToken, out tkCustomAttributeTokens);
+
+ if (tkCustomAttributeTokens.Length == 0)
+ {
+ return Array.Empty<CustomAttributeRecord>();
+ }
+
+ CustomAttributeRecord[] records = new CustomAttributeRecord[tkCustomAttributeTokens.Length];
+
+ for (int i = 0; i < records.Length; i++)
+ {
+ scope.GetCustomAttributeProps(
+ tkCustomAttributeTokens[i], out records[i].tkCtor.Value, out records[i].blob);
+ }
+
+ return records;
+ }
+
+ internal static CustomAttributeTypedArgument Filter(IList<CustomAttributeData> attrs, Type caType, int parameter)
+ {
+ for (int i = 0; i < attrs.Count; i++)
+ {
+ if (attrs[i].Constructor.DeclaringType == caType)
+ {
+ return attrs[i].ConstructorArguments[parameter];
+ }
+ }
+
+ return new CustomAttributeTypedArgument();
+ }
+ #endregion
+
+ #region Private Data Members
+ private ConstructorInfo m_ctor;
+ private RuntimeModule m_scope;
+ private MemberInfo[] m_members;
+ private CustomAttributeCtorParameter[] m_ctorParams;
+ private CustomAttributeNamedParameter[] m_namedParams;
+ private IList<CustomAttributeTypedArgument> m_typedCtorArgs;
+ private IList<CustomAttributeNamedArgument> m_namedArgs;
+ #endregion
+
+ #region Constructor
+ protected CustomAttributeData()
+ {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private CustomAttributeData(RuntimeModule scope, CustomAttributeRecord caRecord)
+ {
+ m_scope = scope;
+ m_ctor = (RuntimeConstructorInfo)RuntimeType.GetMethodBase(scope, caRecord.tkCtor);
+
+ ParameterInfo[] parameters = m_ctor.GetParametersNoCopy();
+ m_ctorParams = new CustomAttributeCtorParameter[parameters.Length];
+ for (int i = 0; i < parameters.Length; i++)
+ m_ctorParams[i] = new CustomAttributeCtorParameter(InitCustomAttributeType((RuntimeType)parameters[i].ParameterType));
+
+ FieldInfo[] fields = m_ctor.DeclaringType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ PropertyInfo[] properties = m_ctor.DeclaringType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ m_namedParams = new CustomAttributeNamedParameter[properties.Length + fields.Length];
+ for (int i = 0; i < fields.Length; i++)
+ m_namedParams[i] = new CustomAttributeNamedParameter(
+ fields[i].Name, CustomAttributeEncoding.Field, InitCustomAttributeType((RuntimeType)fields[i].FieldType));
+ for (int i = 0; i < properties.Length; i++)
+ m_namedParams[i + fields.Length] = new CustomAttributeNamedParameter(
+ properties[i].Name, CustomAttributeEncoding.Property, InitCustomAttributeType((RuntimeType)properties[i].PropertyType));
+
+ m_members = new MemberInfo[fields.Length + properties.Length];
+ fields.CopyTo(m_members, 0);
+ properties.CopyTo(m_members, fields.Length);
+
+ CustomAttributeEncodedArgument.ParseAttributeArguments(caRecord.blob, ref m_ctorParams, ref m_namedParams, m_scope);
+ }
+ #endregion
+
+ #region Pseudo Custom Attribute Constructor
+ internal CustomAttributeData(Attribute attribute)
+ {
+ if (attribute is DllImportAttribute)
+ Init((DllImportAttribute)attribute);
+ else if (attribute is FieldOffsetAttribute)
+ Init((FieldOffsetAttribute)attribute);
+ else if (attribute is MarshalAsAttribute)
+ Init((MarshalAsAttribute)attribute);
+ else if (attribute is TypeForwardedToAttribute)
+ Init((TypeForwardedToAttribute)attribute);
+ else
+ Init(attribute);
+ }
+ private void Init(DllImportAttribute dllImport)
+ {
+ Type type = typeof(DllImportAttribute);
+ m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
+ m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
+ {
+ new CustomAttributeTypedArgument(dllImport.Value),
+ });
+
+ m_namedArgs = Array.AsReadOnly(new CustomAttributeNamedArgument[]
+ {
+ new CustomAttributeNamedArgument(type.GetField("EntryPoint"), dllImport.EntryPoint),
+ new CustomAttributeNamedArgument(type.GetField("CharSet"), dllImport.CharSet),
+ new CustomAttributeNamedArgument(type.GetField("ExactSpelling"), dllImport.ExactSpelling),
+ new CustomAttributeNamedArgument(type.GetField("SetLastError"), dllImport.SetLastError),
+ new CustomAttributeNamedArgument(type.GetField("PreserveSig"), dllImport.PreserveSig),
+ new CustomAttributeNamedArgument(type.GetField("CallingConvention"), dllImport.CallingConvention),
+ new CustomAttributeNamedArgument(type.GetField("BestFitMapping"), dllImport.BestFitMapping),
+ new CustomAttributeNamedArgument(type.GetField("ThrowOnUnmappableChar"), dllImport.ThrowOnUnmappableChar)
+
+ });
+ }
+ private void Init(FieldOffsetAttribute fieldOffset)
+ {
+ m_ctor = typeof(FieldOffsetAttribute).GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
+ m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[] {
+ new CustomAttributeTypedArgument(fieldOffset.Value)
+ });
+ m_namedArgs = Array.AsReadOnly(Array.Empty<CustomAttributeNamedArgument>());
+ }
+ private void Init(MarshalAsAttribute marshalAs)
+ {
+ Type type = typeof(MarshalAsAttribute);
+ m_ctor = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
+ m_typedCtorArgs = Array.AsReadOnly(new CustomAttributeTypedArgument[]
+ {
+ new CustomAttributeTypedArgument(marshalAs.Value),
+ });
+
+ int i = 3; // ArraySubType, SizeParamIndex, SizeConst
+ if (marshalAs.MarshalType != null) i++;
+ if (marshalAs.MarshalTypeRef != null) i++;
+ if (marshalAs.MarshalCookie != null) i++;
+ i++; // IidParameterIndex
+ i++; // SafeArraySubType
+ if (marshalAs.SafeArrayUserDefinedSubType != null) i++;
+ CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[i];
+
+ // For compatibility with previous runtimes, we always include the following 5 attributes, regardless
+ // of if they apply to the UnmanagedType being marshaled or not.
+ i = 0;
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("ArraySubType"), marshalAs.ArraySubType);
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeParamIndex"), marshalAs.SizeParamIndex);
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SizeConst"), marshalAs.SizeConst);
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("IidParameterIndex"), marshalAs.IidParameterIndex);
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArraySubType"), marshalAs.SafeArraySubType);
+ if (marshalAs.MarshalType != null)
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalType"), marshalAs.MarshalType);
+ if (marshalAs.MarshalTypeRef != null)
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalTypeRef"), marshalAs.MarshalTypeRef);
+ if (marshalAs.MarshalCookie != null)
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("MarshalCookie"), marshalAs.MarshalCookie);
+ if (marshalAs.SafeArrayUserDefinedSubType != null)
+ namedArgs[i++] = new CustomAttributeNamedArgument(type.GetField("SafeArrayUserDefinedSubType"), marshalAs.SafeArrayUserDefinedSubType);
+
+ m_namedArgs = Array.AsReadOnly(namedArgs);
+ }
+ private void Init(TypeForwardedToAttribute forwardedTo)
+ {
+ Type type = typeof(TypeForwardedToAttribute);
+
+ Type[] sig = new Type[] { typeof(Type) };
+ m_ctor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, sig, null);
+
+ CustomAttributeTypedArgument[] typedArgs = new CustomAttributeTypedArgument[1];
+ typedArgs[0] = new CustomAttributeTypedArgument(typeof(Type), forwardedTo.Destination);
+ m_typedCtorArgs = Array.AsReadOnly(typedArgs);
+
+ CustomAttributeNamedArgument[] namedArgs = Array.Empty<CustomAttributeNamedArgument>();
+ m_namedArgs = Array.AsReadOnly(namedArgs);
+ }
+ private void Init(object pca)
+ {
+ m_ctor = pca.GetType().GetConstructors(BindingFlags.Public | BindingFlags.Instance)[0];
+ m_typedCtorArgs = Array.AsReadOnly(Array.Empty<CustomAttributeTypedArgument>());
+ m_namedArgs = Array.AsReadOnly(Array.Empty<CustomAttributeNamedArgument>());
+ }
+ #endregion
+
+ #region Object Override
+ public override string ToString()
+ {
+ string ctorArgs = "";
+ for (int i = 0; i < ConstructorArguments.Count; i ++)
+ ctorArgs += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", ConstructorArguments[i]);
+
+ string namedArgs = "";
+ for (int i = 0; i < NamedArguments.Count; i ++)
+ namedArgs += String.Format(CultureInfo.CurrentCulture, i == 0 && ctorArgs.Length == 0 ? "{0}" : ", {0}", NamedArguments[i]);
+
+ return String.Format(CultureInfo.CurrentCulture, "[{0}({1}{2})]", Constructor.DeclaringType.FullName, ctorArgs, namedArgs);
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ return obj == (object)this;
+ }
+ #endregion
+
+ #region Public Members
+ public Type AttributeType { get { return Constructor.DeclaringType; } }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual ConstructorInfo Constructor { get { return m_ctor; } }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual IList<CustomAttributeTypedArgument> ConstructorArguments
+ {
+ get
+ {
+ if (m_typedCtorArgs == null)
+ {
+ CustomAttributeTypedArgument[] typedCtorArgs = new CustomAttributeTypedArgument[m_ctorParams.Length];
+
+ for (int i = 0; i < typedCtorArgs.Length; i++)
+ {
+ CustomAttributeEncodedArgument encodedArg = m_ctorParams[i].CustomAttributeEncodedArgument;
+
+ typedCtorArgs[i] = new CustomAttributeTypedArgument(m_scope, m_ctorParams[i].CustomAttributeEncodedArgument);
+ }
+
+ m_typedCtorArgs = Array.AsReadOnly(typedCtorArgs);
+ }
+
+ return m_typedCtorArgs;
+ }
+ }
+
+ public virtual IList<CustomAttributeNamedArgument> NamedArguments
+ {
+ get
+ {
+ if (m_namedArgs == null)
+ {
+ if (m_namedParams == null)
+ return null;
+
+ int cNamedArgs = 0;
+ for (int i = 0; i < m_namedParams.Length; i++)
+ {
+ if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
+ cNamedArgs++;
+ }
+
+ CustomAttributeNamedArgument[] namedArgs = new CustomAttributeNamedArgument[cNamedArgs];
+
+ for (int i = 0, j = 0; i < m_namedParams.Length; i++)
+ {
+ if (m_namedParams[i].EncodedArgument.CustomAttributeType.EncodedType != CustomAttributeEncoding.Undefined)
+ namedArgs[j++] = new CustomAttributeNamedArgument(
+ m_members[i], new CustomAttributeTypedArgument(m_scope, m_namedParams[i].EncodedArgument));
+ }
+
+ m_namedArgs = Array.AsReadOnly(namedArgs);
+ }
+
+ return m_namedArgs;
+ }
+ }
+ #endregion
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct CustomAttributeNamedArgument
+ {
+ #region Public Static Members
+ public static bool operator ==(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
+ {
+ return left.Equals(right);
+ }
+ public static bool operator !=(CustomAttributeNamedArgument left, CustomAttributeNamedArgument right)
+ {
+ return !left.Equals(right);
+ }
+ #endregion
+
+ #region Private Data Members
+ private MemberInfo m_memberInfo;
+ private CustomAttributeTypedArgument m_value;
+ #endregion
+
+ #region Constructor
+ public CustomAttributeNamedArgument(MemberInfo memberInfo, object value)
+ {
+ if (memberInfo == null)
+ throw new ArgumentNullException("memberInfo");
+
+ Type type = null;
+ FieldInfo field = memberInfo as FieldInfo;
+ PropertyInfo property = memberInfo as PropertyInfo;
+
+ if (field != null)
+ type = field.FieldType;
+ else if (property != null)
+ type = property.PropertyType;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMemberForNamedArgument"));
+
+ m_memberInfo = memberInfo;
+ m_value = new CustomAttributeTypedArgument(type, value);
+ }
+
+ public CustomAttributeNamedArgument(MemberInfo memberInfo, CustomAttributeTypedArgument typedArgument)
+ {
+ if (memberInfo == null)
+ throw new ArgumentNullException("memberInfo");
+
+ m_memberInfo = memberInfo;
+ m_value = typedArgument;
+ }
+ #endregion
+
+ #region Object Override
+ public override string ToString()
+ {
+ if (m_memberInfo == null)
+ return base.ToString();
+
+ return String.Format(CultureInfo.CurrentCulture, "{0} = {1}", MemberInfo.Name, TypedValue.ToString(ArgumentType != typeof(object)));
+ }
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ return obj == (object)this;
+ }
+ #endregion
+
+ #region Internal Members
+ internal Type ArgumentType
+ {
+ get
+ {
+ return m_memberInfo is FieldInfo ?
+ ((FieldInfo)m_memberInfo).FieldType :
+ ((PropertyInfo)m_memberInfo).PropertyType;
+ }
+ }
+ #endregion
+
+ #region Public Members
+ public MemberInfo MemberInfo { get { return m_memberInfo; } }
+ public CustomAttributeTypedArgument TypedValue { get { return m_value; } }
+ public string MemberName { get { return MemberInfo.Name; } }
+ public bool IsField { get { return MemberInfo is FieldInfo; } }
+ #endregion
+
+ }
+
+ [Serializable]
+ [ComVisible(true)]
+ public struct CustomAttributeTypedArgument
+ {
+ #region Public Static Members
+ public static bool operator ==(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
+ {
+ return left.Equals(right);
+ }
+ public static bool operator !=(CustomAttributeTypedArgument left, CustomAttributeTypedArgument right)
+ {
+ return !left.Equals(right);
+ }
+ #endregion
+
+ #region Private Static Methods
+ private static Type CustomAttributeEncodingToType(CustomAttributeEncoding encodedType)
+ {
+ switch (encodedType)
+ {
+ case (CustomAttributeEncoding.Enum):
+ return typeof(Enum);
+
+ case (CustomAttributeEncoding.Int32):
+ return typeof(int);
+
+ case (CustomAttributeEncoding.String):
+ return typeof(string);
+
+ case (CustomAttributeEncoding.Type):
+ return typeof(Type);
+
+ case (CustomAttributeEncoding.Array):
+ return typeof(Array);
+
+ case (CustomAttributeEncoding.Char):
+ return typeof(char);
+
+ case (CustomAttributeEncoding.Boolean):
+ return typeof(bool);
+
+ case (CustomAttributeEncoding.SByte):
+ return typeof(sbyte);
+
+ case (CustomAttributeEncoding.Byte):
+ return typeof(byte);
+
+ case (CustomAttributeEncoding.Int16):
+ return typeof(short);
+
+ case (CustomAttributeEncoding.UInt16):
+ return typeof(ushort);
+
+ case (CustomAttributeEncoding.UInt32):
+ return typeof(uint);
+
+ case (CustomAttributeEncoding.Int64):
+ return typeof(long);
+
+ case (CustomAttributeEncoding.UInt64):
+ return typeof(ulong);
+
+ case (CustomAttributeEncoding.Float):
+ return typeof(float);
+
+ case (CustomAttributeEncoding.Double):
+ return typeof(double);
+
+ case (CustomAttributeEncoding.Object):
+ return typeof(object);
+
+ default :
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)encodedType), "encodedType");
+ }
+ }
+
+ [SecuritySafeCritical]
+ private static object EncodedValueToRawValue(long val, CustomAttributeEncoding encodedType)
+ {
+ switch (encodedType)
+ {
+ case CustomAttributeEncoding.Boolean:
+ return (byte)val != 0;
+
+ case CustomAttributeEncoding.Char:
+ return (char)val;
+
+ case CustomAttributeEncoding.Byte:
+ return (byte)val;
+
+ case CustomAttributeEncoding.SByte:
+ return (sbyte)val;
+
+ case CustomAttributeEncoding.Int16:
+ return (short)val;
+
+ case CustomAttributeEncoding.UInt16:
+ return (ushort)val;
+
+ case CustomAttributeEncoding.Int32:
+ return (int)val;
+
+ case CustomAttributeEncoding.UInt32:
+ return (uint)val;
+
+ case CustomAttributeEncoding.Int64:
+ return (long)val;
+
+ case CustomAttributeEncoding.UInt64:
+ return (ulong)val;
+
+ case CustomAttributeEncoding.Float:
+ unsafe { return *(float*)&val; }
+
+ case CustomAttributeEncoding.Double:
+ unsafe { return *(double*)&val; }
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)val), "val");
+ }
+ }
+ private static RuntimeType ResolveType(RuntimeModule scope, string typeName)
+ {
+ RuntimeType type = RuntimeTypeHandle.GetTypeByNameUsingCARules(typeName, scope);
+
+ if (type == null)
+ throw new InvalidOperationException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_CATypeResolutionFailed"), typeName));
+
+ return type;
+ }
+ #endregion
+
+ #region Private Data Members
+ private object m_value;
+ private Type m_argumentType;
+ #endregion
+
+ #region Constructor
+ public CustomAttributeTypedArgument(Type argumentType, object value)
+ {
+ // value can be null.
+ if (argumentType == null)
+ throw new ArgumentNullException("argumentType");
+
+ m_value = (value == null) ? null : CanonicalizeValue(value);
+ m_argumentType = argumentType;
+ }
+
+ public CustomAttributeTypedArgument(object value)
+ {
+ // value cannot be null.
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ m_value = CanonicalizeValue(value);
+ m_argumentType = value.GetType();
+ }
+
+ private static object CanonicalizeValue(object value)
+ {
+ Contract.Assert(value != null);
+
+ if (value.GetType().IsEnum)
+ {
+ return ((Enum)value).GetValue();
+ }
+ return value;
+ }
+
+ internal CustomAttributeTypedArgument(RuntimeModule scope, CustomAttributeEncodedArgument encodedArg)
+ {
+ CustomAttributeEncoding encodedType = encodedArg.CustomAttributeType.EncodedType;
+
+ if (encodedType == CustomAttributeEncoding.Undefined)
+ throw new ArgumentException("encodedArg");
+
+ else if (encodedType == CustomAttributeEncoding.Enum)
+ {
+ m_argumentType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
+ m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedArg.CustomAttributeType.EncodedEnumType);
+ }
+ else if (encodedType == CustomAttributeEncoding.String)
+ {
+ m_argumentType = typeof(string);
+ m_value = encodedArg.StringValue;
+ }
+ else if (encodedType == CustomAttributeEncoding.Type)
+ {
+ m_argumentType = typeof(Type);
+
+ m_value = null;
+
+ if (encodedArg.StringValue != null)
+ m_value = ResolveType(scope, encodedArg.StringValue);
+ }
+ else if (encodedType == CustomAttributeEncoding.Array)
+ {
+ encodedType = encodedArg.CustomAttributeType.EncodedArrayType;
+ Type elementType;
+
+ if (encodedType == CustomAttributeEncoding.Enum)
+ {
+ elementType = ResolveType(scope, encodedArg.CustomAttributeType.EnumName);
+ }
+ else
+ {
+ elementType = CustomAttributeEncodingToType(encodedType);
+ }
+
+ m_argumentType = elementType.MakeArrayType();
+
+ if (encodedArg.ArrayValue == null)
+ {
+ m_value = null;
+ }
+ else
+ {
+ CustomAttributeTypedArgument[] arrayValue = new CustomAttributeTypedArgument[encodedArg.ArrayValue.Length];
+ for (int i = 0; i < arrayValue.Length; i++)
+ arrayValue[i] = new CustomAttributeTypedArgument(scope, encodedArg.ArrayValue[i]);
+
+ m_value = Array.AsReadOnly(arrayValue);
+ }
+ }
+ else
+ {
+ m_argumentType = CustomAttributeEncodingToType(encodedType);
+ m_value = EncodedValueToRawValue(encodedArg.PrimitiveValue, encodedType);
+ }
+ }
+ #endregion
+
+ #region Object Overrides
+ public override string ToString() { return ToString(false); }
+
+ internal string ToString(bool typed)
+ {
+ if (m_argumentType == null)
+ return base.ToString();
+
+ if (ArgumentType.IsEnum)
+ return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.FullName);
+
+ else if (Value == null)
+ return String.Format(CultureInfo.CurrentCulture, typed ? "null" : "({0})null", ArgumentType.Name);
+
+ else if (ArgumentType == typeof(string))
+ return String.Format(CultureInfo.CurrentCulture, "\"{0}\"", Value);
+
+ else if (ArgumentType == typeof(char))
+ return String.Format(CultureInfo.CurrentCulture, "'{0}'", Value);
+
+ else if (ArgumentType == typeof(Type))
+ return String.Format(CultureInfo.CurrentCulture, "typeof({0})", ((Type)Value).FullName);
+
+ else if (ArgumentType.IsArray)
+ {
+ string result = null;
+ IList<CustomAttributeTypedArgument> array = Value as IList<CustomAttributeTypedArgument>;
+
+ Type elementType = ArgumentType.GetElementType();
+ result = String.Format(CultureInfo.CurrentCulture, @"new {0}[{1}] {{ ", elementType.IsEnum ? elementType.FullName : elementType.Name, array.Count);
+
+ for (int i = 0; i < array.Count; i++)
+ result += String.Format(CultureInfo.CurrentCulture, i == 0 ? "{0}" : ", {0}", array[i].ToString(elementType != typeof(object)));
+
+ return result += " }";
+ }
+
+ return String.Format(CultureInfo.CurrentCulture, typed ? "{0}" : "({1}){0}", Value, ArgumentType.Name);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ public override bool Equals(object obj)
+ {
+ return obj == (object)this;
+ }
+ #endregion
+
+ #region Public Members
+ public Type ArgumentType
+ {
+ get
+ {
+ return m_argumentType;
+ }
+ }
+ public object Value
+ {
+ get
+ {
+ return m_value;
+ }
+ }
+ #endregion
+ }
+
+ [Serializable]
+ internal struct CustomAttributeRecord
+ {
+ internal ConstArray blob;
+ internal MetadataToken tkCtor;
+ }
+
+ [Serializable]
+ internal enum CustomAttributeEncoding : int
+ {
+ Undefined = 0,
+ Boolean = CorElementType.Boolean,
+ Char = CorElementType.Char,
+ SByte = CorElementType.I1,
+ Byte = CorElementType.U1,
+ Int16 = CorElementType.I2,
+ UInt16 = CorElementType.U2,
+ Int32 = CorElementType.I4,
+ UInt32 = CorElementType.U4,
+ Int64 = CorElementType.I8,
+ UInt64 = CorElementType.U8,
+ Float = CorElementType.R4,
+ Double = CorElementType.R8,
+ String = CorElementType.String,
+ Array = CorElementType.SzArray,
+ Type = 0x50,
+ Object = 0x51,
+ Field = 0x53,
+ Property = 0x54,
+ Enum = 0x55
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ internal struct CustomAttributeEncodedArgument
+ {
+ #region Parser
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ParseAttributeArguments(
+ IntPtr pCa,
+ int cCa,
+ ref CustomAttributeCtorParameter[] CustomAttributeCtorParameters,
+ ref CustomAttributeNamedParameter[] CustomAttributeTypedArgument,
+ RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void ParseAttributeArguments(ConstArray attributeBlob,
+ ref CustomAttributeCtorParameter[] customAttributeCtorParameters,
+ ref CustomAttributeNamedParameter[] customAttributeNamedParameters,
+ RuntimeModule customAttributeModule)
+ {
+ if (customAttributeModule == null)
+ throw new ArgumentNullException("customAttributeModule");
+ Contract.EndContractBlock();
+
+ Contract.Assert(customAttributeCtorParameters != null);
+ Contract.Assert(customAttributeNamedParameters != null);
+
+ if (customAttributeCtorParameters.Length != 0 || customAttributeNamedParameters.Length != 0)
+ {
+ unsafe
+ {
+ ParseAttributeArguments(
+ attributeBlob.Signature,
+ (int)attributeBlob.Length,
+ ref customAttributeCtorParameters,
+ ref customAttributeNamedParameters,
+ (RuntimeAssembly)customAttributeModule.Assembly);
+ }
+ }
+ }
+ #endregion
+
+ #region Private Data Members
+ private long m_primitiveValue;
+ private CustomAttributeEncodedArgument[] m_arrayValue;
+ private string m_stringValue;
+ private CustomAttributeType m_type;
+ #endregion
+
+ #region Public Members
+ public CustomAttributeType CustomAttributeType { get { return m_type; } }
+ public long PrimitiveValue { get { return m_primitiveValue; } }
+ public CustomAttributeEncodedArgument[] ArrayValue { get { return m_arrayValue; } }
+ public string StringValue { get { return m_stringValue; } }
+ #endregion
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ internal struct CustomAttributeNamedParameter
+ {
+ #region Private Data Members
+ private string m_argumentName;
+ private CustomAttributeEncoding m_fieldOrProperty;
+ private CustomAttributeEncoding m_padding;
+ private CustomAttributeType m_type;
+ private CustomAttributeEncodedArgument m_encodedArgument;
+ #endregion
+
+ #region Constructor
+ public CustomAttributeNamedParameter(string argumentName, CustomAttributeEncoding fieldOrProperty, CustomAttributeType type)
+ {
+ if (argumentName == null)
+ throw new ArgumentNullException("argumentName");
+ Contract.EndContractBlock();
+
+ m_argumentName = argumentName;
+ m_fieldOrProperty = fieldOrProperty;
+ m_padding = fieldOrProperty;
+ m_type = type;
+ m_encodedArgument = new CustomAttributeEncodedArgument();
+ }
+ #endregion
+
+ #region Public Members
+ public CustomAttributeEncodedArgument EncodedArgument { get { return m_encodedArgument; } }
+ #endregion
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ internal struct CustomAttributeCtorParameter
+ {
+ #region Private Data Members
+ private CustomAttributeType m_type;
+ private CustomAttributeEncodedArgument m_encodedArgument;
+ #endregion
+
+ #region Constructor
+ public CustomAttributeCtorParameter(CustomAttributeType type)
+ {
+ m_type = type;
+ m_encodedArgument = new CustomAttributeEncodedArgument();
+ }
+ #endregion
+
+ #region Public Members
+ public CustomAttributeEncodedArgument CustomAttributeEncodedArgument { get { return m_encodedArgument; } }
+ #endregion
+ }
+
+ // Note: This is a managed representation of a frame type defined in vm\frames.h; please ensure the layout remains
+ // synchronized.
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct SecurityContextFrame
+ {
+ IntPtr m_GSCookie; // This is actually at a negative offset in the real frame definition
+ IntPtr __VFN_table; // This is the real start of the SecurityContextFrame
+ IntPtr m_Next;
+ IntPtr m_Assembly;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void Push(RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public extern void Pop();
+ }
+
+ [Serializable]
+ [StructLayout(LayoutKind.Auto)]
+ internal struct CustomAttributeType
+ {
+ #region Private Data Members
+ /// The most complicated type is an enum[] in which case...
+ private string m_enumName; // ...enum name
+ private CustomAttributeEncoding m_encodedType; // ...array
+ private CustomAttributeEncoding m_encodedEnumType; // ...enum
+ private CustomAttributeEncoding m_encodedArrayType; // ...enum type
+ private CustomAttributeEncoding m_padding;
+ #endregion
+
+ #region Constructor
+ public CustomAttributeType(CustomAttributeEncoding encodedType, CustomAttributeEncoding encodedArrayType,
+ CustomAttributeEncoding encodedEnumType, string enumName)
+ {
+ m_encodedType = encodedType;
+ m_encodedArrayType = encodedArrayType;
+ m_encodedEnumType = encodedEnumType;
+ m_enumName = enumName;
+ m_padding = m_encodedType;
+ }
+ #endregion
+
+ #region Public Members
+ public CustomAttributeEncoding EncodedType { get { return m_encodedType; } }
+ public CustomAttributeEncoding EncodedEnumType { get { return m_encodedEnumType; } }
+ public CustomAttributeEncoding EncodedArrayType { get { return m_encodedArrayType; } }
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public string EnumName { get { return m_enumName; } }
+ #endregion
+ }
+
+ internal unsafe static class CustomAttribute
+ {
+ #region Private Data Members
+ private static RuntimeType Type_RuntimeType = (RuntimeType)typeof(RuntimeType);
+ private static RuntimeType Type_Type = (RuntimeType)typeof(Type);
+ #endregion
+
+ #region Internal Static Members
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeType type, RuntimeType caType, bool inherit)
+ {
+ Contract.Requires(type != null);
+
+ if (type.GetElementType() != null)
+ return false;
+
+ if (PseudoCustomAttribute.IsDefined(type, caType))
+ return true;
+
+ if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType))
+ return true;
+
+ if (!inherit)
+ return false;
+
+ type = type.BaseType as RuntimeType;
+
+ while (type != null)
+ {
+ if (IsCustomAttributeDefined(type.GetRuntimeModule(), type.MetadataToken, caType, 0, inherit))
+ return true;
+
+ type = type.BaseType as RuntimeType;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
+ {
+ Contract.Requires(method != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(method, caType))
+ return true;
+
+ if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType))
+ return true;
+
+ if (!inherit)
+ return false;
+
+ method = method.GetParentDefinition();
+
+ while (method != null)
+ {
+ if (IsCustomAttributeDefined(method.GetRuntimeModule(), method.MetadataToken, caType, 0, inherit))
+ return true;
+
+ method = method.GetParentDefinition();
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
+ {
+ Contract.Requires(ctor != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(ctor, caType))
+ return true;
+
+ return IsCustomAttributeDefined(ctor.GetRuntimeModule(), ctor.MetadataToken, caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
+ {
+ Contract.Requires(property != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(property, caType))
+ return true;
+
+ return IsCustomAttributeDefined(property.GetRuntimeModule(), property.MetadataToken, caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
+ {
+ Contract.Requires(e != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(e, caType))
+ return true;
+
+ return IsCustomAttributeDefined(e.GetRuntimeModule(), e.MetadataToken, caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
+ {
+ Contract.Requires(field != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(field, caType))
+ return true;
+
+ return IsCustomAttributeDefined(field.GetRuntimeModule(), field.MetadataToken, caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
+ {
+ Contract.Requires(parameter != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(parameter, caType))
+ return true;
+
+ return IsCustomAttributeDefined(parameter.GetRuntimeModule(), parameter.MetadataToken, caType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
+ {
+ Contract.Requires(assembly != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(assembly, caType))
+ return true;
+
+ return IsCustomAttributeDefined(assembly.ManifestModule as RuntimeModule, RuntimeAssembly.GetToken(assembly.GetNativeHandle()), caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
+ {
+ Contract.Requires(module != null);
+ Contract.Requires(caType != null);
+
+ if (PseudoCustomAttribute.IsDefined(module, caType))
+ return true;
+
+ return IsCustomAttributeDefined(module, module.MetadataToken, caType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool inherit)
+ {
+ Contract.Requires(type != null);
+ Contract.Requires(caType != null);
+
+ if (type.GetElementType() != null)
+ return (caType.IsValueType) ? EmptyArray<Object>.Value : CreateAttributeArrayHelper(caType, 0);
+
+ if (type.IsGenericType && !type.IsGenericTypeDefinition)
+ type = type.GetGenericTypeDefinition() as RuntimeType;
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(type, caType, true, out pcaCount);
+
+ // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
+ // attribute usage for the specific attribute because a derived attribute may override the usage...
+ // ... however if the attribute is sealed we can rely on the attribute usage
+ if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
+ {
+ object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(type));
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ List<object> result = new List<object>();
+ bool mustBeInheritable = false;
+ bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
+ Type arrayType = useObjectArray ? typeof(object) : caType;
+
+ while (pcaCount > 0)
+ result.Add(pca[--pcaCount]);
+
+ while (type != (RuntimeType)typeof(object) && type != null)
+ {
+ object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, 0, caType, mustBeInheritable, result, !AllowCriticalCustomAttributes(type));
+ mustBeInheritable = true;
+ for (int i = 0; i < attributes.Length; i++)
+ result.Add(attributes[i]);
+
+ type = type.BaseType as RuntimeType;
+ }
+
+ object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
+ Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
+ return typedResult;
+ }
+
+ private static bool AllowCriticalCustomAttributes(RuntimeType type)
+ {
+ if (type.IsGenericParameter)
+ {
+ // Generic parameters don't have transparency state, so look at the
+ // declaring method/type. One of declaringMethod or declaringType
+ // must be set.
+ MethodBase declaringMethod = type.DeclaringMethod;
+ if (declaringMethod != null)
+ {
+ return AllowCriticalCustomAttributes(declaringMethod);
+ }
+ else
+ {
+ type = type.DeclaringType as RuntimeType;
+ Contract.Assert(type != null);
+ }
+ }
+
+ return !type.IsSecurityTransparent || SpecialAllowCriticalAttributes(type);
+ }
+
+ private static bool SpecialAllowCriticalAttributes(RuntimeType type)
+ {
+ // Types participating in Type Equivalence are always transparent.
+ // See TokenSecurityDescriptor::VerifySemanticDataComputed in securitymeta.cpp.
+ // Because of that we allow critical attributes applied to full trust equivalent types.
+ // DeclaringType is null for global methods and fields and the global type never participates in type equivalency.
+
+#if FEATURE_CORECLR
+ return false;
+#else
+ return type != null && type.Assembly.IsFullyTrusted && RuntimeTypeHandle.IsEquivalentType(type);
+#endif //!FEATURE_CORECLR
+ }
+
+ private static bool AllowCriticalCustomAttributes(MethodBase method)
+ {
+ Contract.Requires(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
+
+ return !method.IsSecurityTransparent ||
+ SpecialAllowCriticalAttributes((RuntimeType)method.DeclaringType);
+ }
+
+ private static bool AllowCriticalCustomAttributes(RuntimeFieldInfo field)
+ {
+ return !field.IsSecurityTransparent ||
+ SpecialAllowCriticalAttributes((RuntimeType)field.DeclaringType);
+ }
+
+ private static bool AllowCriticalCustomAttributes(RuntimeParameterInfo parameter)
+ {
+ // Since parameters have no transparency state, we look at the defining method instead.
+ return AllowCriticalCustomAttributes(parameter.DefiningMethod);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool inherit)
+ {
+ Contract.Requires(method != null);
+ Contract.Requires(caType != null);
+
+ if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
+ method = method.GetGenericMethodDefinition() as RuntimeMethodInfo;
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(method, caType, true, out pcaCount);
+
+ // if we are asked to go up the hierarchy chain we have to do it now and regardless of the
+ // attribute usage for the specific attribute because a derived attribute may override the usage...
+ // ... however if the attribute is sealed we can rely on the attribute usage
+ if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited))
+ {
+ object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(method));
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ List<object> result = new List<object>();
+ bool mustBeInheritable = false;
+ bool useObjectArray = (caType == null || caType.IsValueType || caType.ContainsGenericParameters);
+ Type arrayType = useObjectArray ? typeof(object) : caType;
+
+ while (pcaCount > 0)
+ result.Add(pca[--pcaCount]);
+
+ while (method != null)
+ {
+ object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, 0, caType, mustBeInheritable, result, !AllowCriticalCustomAttributes(method));
+ mustBeInheritable = true;
+ for (int i = 0; i < attributes.Length; i++)
+ result.Add(attributes[i]);
+
+ method = method.GetParentDefinition();
+ }
+
+ object[] typedResult = CreateAttributeArrayHelper(arrayType, result.Count);
+ Array.Copy(result.ToArray(), 0, typedResult, 0, result.Count);
+ return typedResult;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType)
+ {
+ Contract.Requires(ctor != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(ctor, caType, true, out pcaCount);
+ object[] attributes = GetCustomAttributes(ctor.GetRuntimeModule(), ctor.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(ctor));
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType)
+ {
+ Contract.Requires(property != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(property, caType, out pcaCount);
+ // Since properties and events have no transparency state, logically we should check the declaring types.
+ // But then if someone wanted to apply critical attributes on a property/event he would need to make the type critical,
+ // which would also implicitly made all the members critical.
+ // So we check the containing assembly instead. If the assembly can contain critical code we allow critical attributes on properties/events.
+ bool disallowCriticalCustomAttributes = property.GetRuntimeModule().GetRuntimeAssembly().IsAllSecurityTransparent();
+
+ object[] attributes = GetCustomAttributes(property.GetRuntimeModule(), property.MetadataToken, pcaCount, caType, disallowCriticalCustomAttributes);
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType)
+ {
+ Contract.Requires(e != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(e, caType, out pcaCount);
+ // Since properties and events have no transparency state, logically we should check the declaring types.
+ // But then if someone wanted to apply critical attributes on a property/event he would need to make the type critical,
+ // which would also implicitly made all the members critical.
+ // So we check the containing assembly instead. If the assembly can contain critical code we allow critical attributes on properties/events.
+ bool disallowCriticalCustomAttributes = e.GetRuntimeModule().GetRuntimeAssembly().IsAllSecurityTransparent();
+ object[] attributes = GetCustomAttributes(e.GetRuntimeModule(), e.MetadataToken, pcaCount, caType, disallowCriticalCustomAttributes);
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType)
+ {
+ Contract.Requires(field != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(field, caType, out pcaCount);
+ object[] attributes = GetCustomAttributes(field.GetRuntimeModule(), field.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(field));
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType)
+ {
+ Contract.Requires(parameter != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(parameter, caType, out pcaCount);
+ object[] attributes = GetCustomAttributes(parameter.GetRuntimeModule(), parameter.MetadataToken, pcaCount, caType, !AllowCriticalCustomAttributes(parameter));
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType)
+ {
+ Contract.Requires(assembly != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(assembly, caType, true, out pcaCount);
+ int assemblyToken = RuntimeAssembly.GetToken(assembly.GetNativeHandle());
+ bool isAssemblySecurityTransparent = assembly.IsAllSecurityTransparent();
+ object[] attributes = GetCustomAttributes(assembly.ManifestModule as RuntimeModule, assemblyToken, pcaCount, caType, isAssemblySecurityTransparent);
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object[] GetCustomAttributes(RuntimeModule module, RuntimeType caType)
+ {
+ Contract.Requires(module != null);
+ Contract.Requires(caType != null);
+
+ int pcaCount = 0;
+ Attribute[] pca = PseudoCustomAttribute.GetCustomAttributes(module, caType, out pcaCount);
+ bool isModuleSecurityTransparent = module.GetRuntimeAssembly().IsAllSecurityTransparent();
+ object[] attributes = GetCustomAttributes(module, module.MetadataToken, pcaCount, caType, isModuleSecurityTransparent);
+ if (pcaCount > 0) Array.Copy(pca, 0, attributes, attributes.Length - pcaCount, pcaCount);
+ return attributes;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static bool IsAttributeDefined(RuntimeModule decoratedModule, int decoratedMetadataToken, int attributeCtorToken)
+ {
+ return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, null, attributeCtorToken, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool IsCustomAttributeDefined(
+ RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType)
+ {
+ return IsCustomAttributeDefined(decoratedModule, decoratedMetadataToken, attributeFilterType, 0, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool IsCustomAttributeDefined(
+ RuntimeModule decoratedModule, int decoratedMetadataToken, RuntimeType attributeFilterType, int attributeCtorToken, bool mustBeInheritable)
+ {
+ if (decoratedModule.Assembly.ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA"));
+ Contract.EndContractBlock();
+
+ CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
+
+ if (attributeFilterType != null)
+ {
+ Contract.Assert(attributeCtorToken == 0);
+
+ MetadataImport scope = decoratedModule.MetadataImport;
+ RuntimeType attributeType;
+ IRuntimeMethodInfo ctor;
+ bool ctorHasParameters, isVarArg;
+
+ // Optimization for the case where attributes decorate entities in the same assembly in which case
+ // we can cache the successful APTCA check between the decorated and the declared assembly.
+ Assembly lastAptcaOkAssembly = null;
+
+ for (int i = 0; i < car.Length; i++)
+ {
+ CustomAttributeRecord caRecord = car[i];
+
+ if (FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly,
+ decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable, null, null,
+ out attributeType, out ctor, out ctorHasParameters, out isVarArg))
+ return true;
+ }
+ }
+ else
+ {
+ Contract.Assert(attributeFilterType == null);
+ Contract.Assert(!MetadataToken.IsNullToken(attributeCtorToken));
+
+ for (int i = 0; i < car.Length; i++)
+ {
+ CustomAttributeRecord caRecord = car[i];
+
+ if (caRecord.tkCtor == attributeCtorToken)
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static object[] GetCustomAttributes(
+ RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount, RuntimeType attributeFilterType, bool isDecoratedTargetSecurityTransparent)
+ {
+ return GetCustomAttributes(decoratedModule, decoratedMetadataToken, pcaCount, attributeFilterType, false, null, isDecoratedTargetSecurityTransparent);
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe static object[] GetCustomAttributes(
+ RuntimeModule decoratedModule, int decoratedMetadataToken, int pcaCount,
+ RuntimeType attributeFilterType, bool mustBeInheritable, IList derivedAttributes, bool isDecoratedTargetSecurityTransparent)
+ {
+ if (decoratedModule.Assembly.ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyCA"));
+ Contract.EndContractBlock();
+
+ MetadataImport scope = decoratedModule.MetadataImport;
+ CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedMetadataToken);
+
+ bool useObjectArray = (attributeFilterType == null || attributeFilterType.IsValueType || attributeFilterType.ContainsGenericParameters);
+ Type arrayType = useObjectArray ? typeof(object) : attributeFilterType;
+
+ if (attributeFilterType == null && car.Length == 0)
+ return CreateAttributeArrayHelper(arrayType, 0);
+
+ object[] attributes = CreateAttributeArrayHelper(arrayType, car.Length);
+ int cAttributes = 0;
+
+ // Custom attribute security checks are done with respect to the assembly *decorated* with the
+ // custom attribute as opposed to the *caller of GetCustomAttributes*.
+ // Since this assembly might not be on the stack and the attribute ctor or property setters we're about to invoke may
+ // make security demands, we push a frame on the stack as a proxy for the decorated assembly (this frame will be picked
+ // up an interpreted by the security stackwalker).
+ // Once we push the frame it will be automatically popped in the event of an exception, so no need to use CERs or the
+ // like.
+ SecurityContextFrame frame = new SecurityContextFrame();
+ frame.Push(decoratedModule.GetRuntimeAssembly());
+
+ // Optimization for the case where attributes decorate entities in the same assembly in which case
+ // we can cache the successful APTCA check between the decorated and the declared assembly.
+ Assembly lastAptcaOkAssembly = null;
+
+ for (int i = 0; i < car.Length; i++)
+ {
+ object attribute = null;
+ CustomAttributeRecord caRecord = car[i];
+
+ IRuntimeMethodInfo ctor = null;
+ RuntimeType attributeType = null;
+ bool ctorHasParameters, isVarArg;
+ int cNamedArgs = 0;
+
+ IntPtr blobStart = caRecord.blob.Signature;
+ IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
+ int blobLen = (int)((byte*)blobEnd - (byte*)blobStart);
+
+ if (!FilterCustomAttributeRecord(caRecord, scope, ref lastAptcaOkAssembly,
+ decoratedModule, decoratedMetadataToken, attributeFilterType, mustBeInheritable,
+ attributes, derivedAttributes,
+ out attributeType, out ctor, out ctorHasParameters, out isVarArg))
+ continue;
+
+ if (ctor != null)
+ {
+ // Linktime demand checks
+ // decoratedMetadataToken needed as it may be "transparent" in which case we do a full stack walk
+ RuntimeMethodHandle.CheckLinktimeDemands(ctor, decoratedModule, isDecoratedTargetSecurityTransparent);
+ }
+ else
+ {
+
+ }
+
+ // Leverage RuntimeConstructorInfo standard .ctor verfication
+ RuntimeConstructorInfo.CheckCanCreateInstance(attributeType, isVarArg);
+
+ // Create custom attribute object
+ if (ctorHasParameters)
+ {
+ attribute = CreateCaObject(decoratedModule, ctor, ref blobStart, blobEnd, out cNamedArgs);
+ }
+ else
+ {
+ attribute = RuntimeTypeHandle.CreateCaInstance(attributeType, ctor);
+
+ // It is allowed by the ECMA spec to have an empty signature blob
+ if (blobLen == 0)
+ cNamedArgs = 0;
+ else
+ {
+ // Metadata is always written in little-endian format. Must account for this on
+ // big-endian platforms.
+#if BIGENDIAN
+ const int CustomAttributeVersion = 0x0100;
+#else
+ const int CustomAttributeVersion = 0x0001;
+#endif
+ if (Marshal.ReadInt16(blobStart) != CustomAttributeVersion)
+ throw new CustomAttributeFormatException();
+ blobStart = (IntPtr)((byte*)blobStart + 2); // skip version prefix
+
+ cNamedArgs = Marshal.ReadInt16(blobStart);
+ blobStart = (IntPtr)((byte*)blobStart + 2); // skip namedArgs count
+#if BIGENDIAN
+ cNamedArgs = ((cNamedArgs & 0xff00) >> 8) | ((cNamedArgs & 0x00ff) << 8);
+#endif
+ }
+ }
+
+ for (int j = 0; j < cNamedArgs; j++)
+ {
+ #region // Initialize named properties and fields
+ string name;
+ bool isProperty;
+ RuntimeType type;
+ object value;
+
+ IntPtr blobItr = caRecord.blob.Signature;
+
+ GetPropertyOrFieldData(decoratedModule, ref blobStart, blobEnd, out name, out isProperty, out type, out value);
+
+ try
+ {
+ if (isProperty)
+ {
+ #region // Initialize property
+ if (type == null && value != null)
+ {
+ type = (RuntimeType)value.GetType();
+ if (type == Type_RuntimeType)
+ type = Type_Type;
+ }
+
+ RuntimePropertyInfo property = null;
+
+ if (type == null)
+ property = attributeType.GetProperty(name) as RuntimePropertyInfo;
+ else
+ property = attributeType.GetProperty(name, type, Type.EmptyTypes) as RuntimePropertyInfo;
+
+ // Did we get a valid property reference?
+ if (property == null)
+ {
+ throw new CustomAttributeFormatException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString(
+ isProperty ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), name));
+ }
+
+ RuntimeMethodInfo setMethod = property.GetSetMethod(true) as RuntimeMethodInfo;
+
+ // Public properties may have non-public setter methods
+ if (!setMethod.IsPublic)
+ continue;
+
+ RuntimeMethodHandle.CheckLinktimeDemands(setMethod, decoratedModule, isDecoratedTargetSecurityTransparent);
+
+ setMethod.UnsafeInvoke(attribute, BindingFlags.Default, null, new object[] { value }, null);
+ #endregion
+ }
+ else
+ {
+ RtFieldInfo field = attributeType.GetField(name) as RtFieldInfo;
+
+ if (isDecoratedTargetSecurityTransparent)
+ {
+ RuntimeFieldHandle.CheckAttributeAccess(field.FieldHandle, decoratedModule.GetNativeHandle());
+ }
+
+ field.CheckConsistency(attribute);
+ field.UnsafeSetValue(attribute, value, BindingFlags.Default, Type.DefaultBinder, null);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new CustomAttributeFormatException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString(
+ isProperty ? "RFLCT.InvalidPropFail" : "RFLCT.InvalidFieldFail"), name), e);
+ }
+ #endregion
+ }
+
+ if (!blobStart.Equals(blobEnd))
+ throw new CustomAttributeFormatException();
+
+ attributes[cAttributes++] = attribute;
+ }
+
+ // The frame will be popped automatically if we take an exception any time after we pushed it. So no need of a catch or
+ // finally or CERs here.
+ frame.Pop();
+
+ if (cAttributes == car.Length && pcaCount == 0)
+ return attributes;
+
+ object[] result = CreateAttributeArrayHelper(arrayType, cAttributes + pcaCount);
+ Array.Copy(attributes, 0, result, 0, cAttributes);
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static bool FilterCustomAttributeRecord(
+ CustomAttributeRecord caRecord,
+ MetadataImport scope,
+ ref Assembly lastAptcaOkAssembly,
+ RuntimeModule decoratedModule,
+ MetadataToken decoratedToken,
+ RuntimeType attributeFilterType,
+ bool mustBeInheritable,
+ object[] attributes,
+ IList derivedAttributes,
+ out RuntimeType attributeType,
+ out IRuntimeMethodInfo ctor,
+ out bool ctorHasParameters,
+ out bool isVarArg)
+ {
+ ctor = null;
+ attributeType = null;
+ ctorHasParameters = false;
+ isVarArg = false;
+
+ IntPtr blobStart = caRecord.blob.Signature;
+ IntPtr blobEnd = (IntPtr)((byte*)blobStart + caRecord.blob.Length);
+
+ // Resolve attribute type from ctor parent token found in decorated decoratedModule scope
+ attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
+
+
+ // Test attribute type against user provided attribute type filter
+ if (!(attributeFilterType.IsAssignableFrom(attributeType)))
+ return false;
+
+ // Ensure if attribute type must be inheritable that it is inhertiable
+ // Ensure that to consider a duplicate attribute type AllowMultiple is true
+ if (!AttributeUsageCheck(attributeType, mustBeInheritable, attributes, derivedAttributes))
+ return false;
+
+ // Windows Runtime attributes aren't real types - they exist to be read as metadata only, and as such
+ // should be filtered out of the GetCustomAttributes path.
+ if ((attributeType.Attributes & TypeAttributes.WindowsRuntime) == TypeAttributes.WindowsRuntime)
+ {
+ return false;
+ }
+
+#if FEATURE_APTCA
+ // APTCA checks
+ RuntimeAssembly attributeAssembly = (RuntimeAssembly)attributeType.Assembly;
+ RuntimeAssembly decoratedModuleAssembly = (RuntimeAssembly)decoratedModule.Assembly;
+
+ if (attributeAssembly != lastAptcaOkAssembly &&
+ !RuntimeAssembly.AptcaCheck(attributeAssembly, decoratedModuleAssembly))
+ return false;
+
+ // Cache last successful APTCA check (optimization)
+ lastAptcaOkAssembly = decoratedModuleAssembly;
+#endif // FEATURE_APTCA
+
+ // Resolve the attribute ctor
+ ConstArray ctorSig = scope.GetMethodSignature(caRecord.tkCtor);
+ isVarArg = (ctorSig[0] & 0x05) != 0;
+ ctorHasParameters = ctorSig[1] != 0;
+
+ if (ctorHasParameters)
+ {
+ // Resolve method ctor token found in decorated decoratedModule scope
+ ctor = ModuleHandle.ResolveMethodHandleInternal(decoratedModule.GetNativeHandle(), caRecord.tkCtor);
+ }
+ else
+ {
+ // Resolve method ctor token from decorated decoratedModule scope
+ ctor = attributeType.GetTypeHandleInternal().GetDefaultConstructor();
+
+ if (ctor == null && !attributeType.IsValueType)
+ throw new MissingMethodException(".ctor");
+ }
+
+ // Visibility checks
+ MetadataToken tkParent = new MetadataToken();
+
+ if (decoratedToken.IsParamDef)
+ {
+ tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
+ tkParent = new MetadataToken(scope.GetParentToken(tkParent));
+ }
+ else if (decoratedToken.IsMethodDef || decoratedToken.IsProperty || decoratedToken.IsEvent || decoratedToken.IsFieldDef)
+ {
+ tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
+ }
+ else if (decoratedToken.IsTypeDef)
+ {
+ tkParent = decoratedToken;
+ }
+ else if (decoratedToken.IsGenericPar)
+ {
+ tkParent = new MetadataToken(scope.GetParentToken(decoratedToken));
+
+ // decoratedToken is a generic parameter on a method. Get the declaring Type of the method.
+ if (tkParent.IsMethodDef)
+ tkParent = new MetadataToken(scope.GetParentToken(tkParent));
+ }
+ else
+ {
+ // We need to relax this when we add support for other types of decorated tokens.
+ Contract.Assert(decoratedToken.IsModule || decoratedToken.IsAssembly,
+ "The decoratedToken must be either an assembly, a module, a type, or a member.");
+ }
+
+ // If the attribute is on a type, member, or parameter we check access against the (declaring) type,
+ // otherwise we check access against the module.
+ RuntimeTypeHandle parentTypeHandle = tkParent.IsTypeDef ?
+ decoratedModule.ModuleHandle.ResolveTypeHandle(tkParent) :
+ new RuntimeTypeHandle();
+
+ return RuntimeMethodHandle.IsCAVisibleFromDecoratedType(attributeType.TypeHandle, ctor, parentTypeHandle, decoratedModule);
+ }
+ #endregion
+
+ #region Private Static Methods
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool AttributeUsageCheck(
+ RuntimeType attributeType, bool mustBeInheritable, object[] attributes, IList derivedAttributes)
+ {
+ AttributeUsageAttribute attributeUsageAttribute = null;
+
+ if (mustBeInheritable)
+ {
+ attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
+
+ if (!attributeUsageAttribute.Inherited)
+ return false;
+ }
+
+ // Legacy: AllowMultiple ignored for none inheritable attributes
+
+ if (derivedAttributes == null)
+ return true;
+
+ for (int i = 0; i < derivedAttributes.Count; i++)
+ {
+ if (derivedAttributes[i].GetType() == attributeType)
+ {
+ if (attributeUsageAttribute == null)
+ attributeUsageAttribute = CustomAttribute.GetAttributeUsage(attributeType);
+
+ return attributeUsageAttribute.AllowMultiple;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static AttributeUsageAttribute GetAttributeUsage(RuntimeType decoratedAttribute)
+ {
+ RuntimeModule decoratedModule = decoratedAttribute.GetRuntimeModule();
+ MetadataImport scope = decoratedModule.MetadataImport;
+ CustomAttributeRecord[] car = CustomAttributeData.GetCustomAttributeRecords(decoratedModule, decoratedAttribute.MetadataToken);
+
+ AttributeUsageAttribute attributeUsageAttribute = null;
+
+ for (int i = 0; i < car.Length; i++)
+ {
+ CustomAttributeRecord caRecord = car[i];
+ RuntimeType attributeType = decoratedModule.ResolveType(scope.GetParentToken(caRecord.tkCtor), null, null) as RuntimeType;
+
+ if (attributeType != (RuntimeType)typeof(AttributeUsageAttribute))
+ continue;
+
+ if (attributeUsageAttribute != null)
+ throw new FormatException(String.Format(
+ CultureInfo.CurrentUICulture, Environment.GetResourceString("Format_AttributeUsage"), attributeType));
+
+ AttributeTargets targets;
+ bool inherited, allowMultiple;
+ ParseAttributeUsageAttribute(caRecord.blob, out targets, out inherited, out allowMultiple);
+ attributeUsageAttribute = new AttributeUsageAttribute(targets, allowMultiple, inherited);
+ }
+
+ if (attributeUsageAttribute == null)
+ return AttributeUsageAttribute.Default;
+
+ return attributeUsageAttribute;
+ }
+ #endregion
+
+ #region Private Static FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _ParseAttributeUsageAttribute(
+ IntPtr pCa, int cCa, out int targets, out bool inherited, out bool allowMultiple);
+ [System.Security.SecurityCritical] // auto-generated
+ private static void ParseAttributeUsageAttribute(
+ ConstArray ca, out AttributeTargets targets, out bool inherited, out bool allowMultiple)
+ {
+ int _targets;
+ _ParseAttributeUsageAttribute(ca.Signature, ca.Length, out _targets, out inherited, out allowMultiple);
+ targets = (AttributeTargets)_targets;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern Object _CreateCaObject(RuntimeModule pModule, IRuntimeMethodInfo pCtor, byte** ppBlob, byte* pEndBlob, int* pcNamedArgs);
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe Object CreateCaObject(RuntimeModule module, IRuntimeMethodInfo ctor, ref IntPtr blob, IntPtr blobEnd, out int namedArgs)
+ {
+ byte* pBlob = (byte*)blob;
+ byte* pBlobEnd = (byte*)blobEnd;
+ int cNamedArgs;
+ object ca = _CreateCaObject(module, ctor, &pBlob, pBlobEnd, &cNamedArgs);
+ blob = (IntPtr)pBlob;
+ namedArgs = cNamedArgs;
+ return ca;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe extern static void _GetPropertyOrFieldData(
+ RuntimeModule pModule, byte** ppBlobStart, byte* pBlobEnd, out string name, out bool bIsProperty, out RuntimeType type, out object value);
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe static void GetPropertyOrFieldData(
+ RuntimeModule module, ref IntPtr blobStart, IntPtr blobEnd, out string name, out bool isProperty, out RuntimeType type, out object value)
+ {
+ byte* pBlobStart = (byte*)blobStart;
+ _GetPropertyOrFieldData(
+ module.GetNativeHandle(), &pBlobStart, (byte*)blobEnd, out name, out isProperty, out type, out value);
+ blobStart = (IntPtr)pBlobStart;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static object[] CreateAttributeArrayHelper(Type elementType, int elementCount)
+ {
+ return (object[])Array.UnsafeCreateInstance(elementType, elementCount);
+ }
+ #endregion
+ }
+
+ internal static class PseudoCustomAttribute
+ {
+ #region Private Static Data Members
+ // Here we can avoid the need to take a lock when using Dictionary by rearranging
+ // the only method that adds values to the Dictionary. For more details on
+ // Dictionary versus Hashtable thread safety:
+ // See code:Dictionary#DictionaryVersusHashtableThreadSafety
+ private static Dictionary<RuntimeType, RuntimeType> s_pca;
+ private static int s_pcasCount;
+ #endregion
+
+ #region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe private static extern void _GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes);
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe internal static void GetSecurityAttributes(RuntimeModule module, int token, bool assembly, out object[] securityAttributes)
+ {
+ _GetSecurityAttributes(module.GetNativeHandle(), token, assembly, out securityAttributes);
+ }
+ #endregion
+
+ #region Static Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ static PseudoCustomAttribute()
+ {
+ RuntimeType[] pcas = new RuntimeType[]
+ {
+ // See //depot/DevDiv/private/Main/ndp/clr/src/MD/Compiler/CustAttr.cpp
+ typeof(FieldOffsetAttribute) as RuntimeType, // field
+ typeof(SerializableAttribute) as RuntimeType, // class, struct, enum, delegate
+ typeof(MarshalAsAttribute) as RuntimeType, // parameter, field, return-value
+ typeof(ComImportAttribute) as RuntimeType, // class, interface
+ typeof(NonSerializedAttribute) as RuntimeType, // field, inherited
+ typeof(InAttribute) as RuntimeType, // parameter
+ typeof(OutAttribute) as RuntimeType, // parameter
+ typeof(OptionalAttribute) as RuntimeType, // parameter
+ typeof(DllImportAttribute) as RuntimeType, // method
+ typeof(PreserveSigAttribute) as RuntimeType, // method
+ typeof(TypeForwardedToAttribute) as RuntimeType, // assembly
+ };
+
+ s_pcasCount = pcas.Length;
+ Dictionary<RuntimeType, RuntimeType> temp_pca = new Dictionary<RuntimeType, RuntimeType>(s_pcasCount);
+
+ for (int i = 0; i < s_pcasCount; i++)
+ {
+ VerifyPseudoCustomAttribute(pcas[i]);
+ temp_pca[pcas[i]] = pcas[i];
+ }
+ s_pca = temp_pca;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [Conditional("_DEBUG")]
+ private static void VerifyPseudoCustomAttribute(RuntimeType pca)
+ {
+ // If any of these are invariants are no longer true will have to
+ // re-architect the PCA product logic and test cases -- you've been warned!
+ Contract.Assert(pca.BaseType == (RuntimeType)typeof(Attribute), "Pseudo CA Error");
+ AttributeUsageAttribute usage = CustomAttribute.GetAttributeUsage(pca);
+ Contract.Assert(usage.Inherited == false, "Pseudo CA Error");
+ //AllowMultiple is true for TypeForwardedToAttribute
+ //Contract.Assert(usage.AllowMultiple == false, "Pseudo CA Error");
+ }
+ #endregion
+
+ #region Internal Static
+ internal static bool IsSecurityAttribute(RuntimeType type)
+ {
+#pragma warning disable 618
+ return type == (RuntimeType)typeof(SecurityAttribute) || type.IsSubclassOf(typeof(SecurityAttribute));
+#pragma warning restore 618
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeType type, RuntimeType caType, bool includeSecCa, out int count)
+ {
+ Contract.Requires(type != null);
+ Contract.Requires(caType != null);
+
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
+ return Array.Empty<Attribute>();
+
+ List<Attribute> pcas = new List<Attribute>();
+ Attribute pca = null;
+
+ if (all || caType == (RuntimeType)typeof(SerializableAttribute))
+ {
+ pca = SerializableAttribute.GetCustomAttribute(type);
+ if (pca != null) pcas.Add(pca);
+ }
+ if (all || caType == (RuntimeType)typeof(ComImportAttribute))
+ {
+ pca = ComImportAttribute.GetCustomAttribute(type);
+ if (pca != null) pcas.Add(pca);
+ }
+ if (includeSecCa && (all || IsSecurityAttribute(caType)))
+ {
+ if (!type.IsGenericParameter && type.GetElementType() == null)
+ {
+ if (type.IsGenericType)
+ type = (RuntimeType)type.GetGenericTypeDefinition();
+
+ object[] securityAttributes;
+ GetSecurityAttributes(type.Module.ModuleHandle.GetRuntimeModule(), type.MetadataToken, false, out securityAttributes);
+ if (securityAttributes != null)
+ foreach (object a in securityAttributes)
+ if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
+ pcas.Add((Attribute)a);
+ }
+ }
+
+ count = pcas.Count;
+ return pcas.ToArray();
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeType type, RuntimeType caType)
+ {
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
+ return false;
+
+ if (all || caType == (RuntimeType)typeof(SerializableAttribute))
+ {
+ if (SerializableAttribute.IsDefined(type)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(ComImportAttribute))
+ {
+ if (ComImportAttribute.IsDefined(type)) return true;
+ }
+ if (all || IsSecurityAttribute(caType))
+ {
+ int count;
+ if (GetCustomAttributes(type, caType, true, out count).Length != 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeType caType, bool includeSecCa, out int count)
+ {
+ Contract.Requires(method != null);
+ Contract.Requires(caType != null);
+
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
+ return Array.Empty<Attribute>();
+
+ List<Attribute> pcas = new List<Attribute>();
+ Attribute pca = null;
+
+ if (all || caType == (RuntimeType)typeof(DllImportAttribute))
+ {
+ pca = DllImportAttribute.GetCustomAttribute(method);
+ if (pca != null) pcas.Add(pca);
+ }
+ if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
+ {
+ pca = PreserveSigAttribute.GetCustomAttribute(method);
+ if (pca != null) pcas.Add(pca);
+ }
+ if (includeSecCa && (all || IsSecurityAttribute(caType)))
+ {
+ object[] securityAttributes;
+
+ GetSecurityAttributes(method.Module.ModuleHandle.GetRuntimeModule(), method.MetadataToken, false, out securityAttributes);
+ if (securityAttributes != null)
+ foreach (object a in securityAttributes)
+ if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
+ pcas.Add((Attribute)a);
+ }
+
+ count = pcas.Count;
+ return pcas.ToArray();
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeMethodInfo method, RuntimeType caType)
+ {
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return false;
+
+ if (all || caType == (RuntimeType)typeof(DllImportAttribute))
+ {
+ if (DllImportAttribute.IsDefined(method)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(PreserveSigAttribute))
+ {
+ if (PreserveSigAttribute.IsDefined(method)) return true;
+ }
+ if (all || IsSecurityAttribute(caType))
+ {
+ int count;
+
+ if (GetCustomAttributes(method, caType, true, out count).Length != 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeParameterInfo parameter, RuntimeType caType, out int count)
+ {
+ Contract.Requires(parameter != null);
+ Contract.Requires(caType != null);
+
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return null;
+
+ Attribute[] pcas = new Attribute[s_pcasCount];
+ Attribute pca = null;
+
+ if (all || caType == (RuntimeType)typeof(InAttribute))
+ {
+ pca = InAttribute.GetCustomAttribute(parameter);
+ if (pca != null) pcas[count++] = pca;
+ }
+ if (all || caType == (RuntimeType)typeof(OutAttribute))
+ {
+ pca = OutAttribute.GetCustomAttribute(parameter);
+ if (pca != null) pcas[count++] = pca;
+ }
+ if (all || caType == (RuntimeType)typeof(OptionalAttribute))
+ {
+ pca = OptionalAttribute.GetCustomAttribute(parameter);
+ if (pca != null) pcas[count++] = pca;
+ }
+ if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
+ {
+ pca = MarshalAsAttribute.GetCustomAttribute(parameter);
+ if (pca != null) pcas[count++] = pca;
+ }
+ return pcas;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeParameterInfo parameter, RuntimeType caType)
+ {
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return false;
+
+
+ if (all || caType == (RuntimeType)typeof(InAttribute))
+ {
+ if (InAttribute.IsDefined(parameter)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(OutAttribute))
+ {
+ if (OutAttribute.IsDefined(parameter)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(OptionalAttribute))
+ {
+ if (OptionalAttribute.IsDefined(parameter)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
+ {
+ if (MarshalAsAttribute.IsDefined(parameter)) return true;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeAssembly assembly, RuntimeType caType, bool includeSecCa, out int count)
+ {
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+
+ if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
+ return Array.Empty<Attribute>();
+
+ List<Attribute> pcas = new List<Attribute>();
+ if (includeSecCa && (all || IsSecurityAttribute(caType)))
+ {
+ object[] securityAttributes;
+
+ GetSecurityAttributes(assembly.ManifestModule.ModuleHandle.GetRuntimeModule(), RuntimeAssembly.GetToken(assembly.GetNativeHandle()), true, out securityAttributes);
+ if (securityAttributes != null)
+ foreach (object a in securityAttributes)
+ if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
+ pcas.Add((Attribute)a);
+ }
+
+ //TypeForwardedToAttribute.GetCustomAttribute(assembly) throws FileNotFoundException if the forwarded-to
+ //assemblies are not present. This breaks many V4 scenarios because some framework types are forwarded
+ //to assemblies not included in the client SKU. Let's omit TypeForwardedTo for now until we have a better solution.
+
+ //if (all || caType == (RuntimeType)typeof(TypeForwardedToAttribute))
+ //{
+ // TypeForwardedToAttribute[] attrs = TypeForwardedToAttribute.GetCustomAttribute(assembly);
+ // pcas.AddRange(attrs);
+ //}
+
+ count = pcas.Count;
+ return pcas.ToArray();
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeAssembly assembly, RuntimeType caType)
+ {
+ int count;
+ return GetCustomAttributes(assembly, caType, true, out count).Length > 0;
+ }
+
+ internal static Attribute[] GetCustomAttributes(RuntimeModule module, RuntimeType caType, out int count)
+ {
+ count = 0;
+ return null;
+ }
+ internal static bool IsDefined(RuntimeModule module, RuntimeType caType)
+ {
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeFieldInfo field, RuntimeType caType, out int count)
+ {
+ Contract.Requires(field != null);
+ Contract.Requires(caType != null);
+
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return null;
+
+ Attribute[] pcas = new Attribute[s_pcasCount];
+ Attribute pca = null;
+
+ if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
+ {
+ pca = MarshalAsAttribute.GetCustomAttribute(field);
+ if (pca != null) pcas[count++] = pca;
+ }
+ if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
+ {
+ pca = FieldOffsetAttribute.GetCustomAttribute(field);
+ if (pca != null) pcas[count++] = pca;
+ }
+ if (all || caType == (RuntimeType)typeof(NonSerializedAttribute))
+ {
+ pca = NonSerializedAttribute.GetCustomAttribute(field);
+ if (pca != null) pcas[count++] = pca;
+ }
+ return pcas;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeFieldInfo field, RuntimeType caType)
+ {
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return false;
+
+ if (all || caType == (RuntimeType)typeof(MarshalAsAttribute))
+ {
+ if (MarshalAsAttribute.IsDefined(field)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(FieldOffsetAttribute))
+ {
+ if (FieldOffsetAttribute.IsDefined(field)) return true;
+ }
+ if (all || caType == (RuntimeType)typeof(NonSerializedAttribute))
+ {
+ if (NonSerializedAttribute.IsDefined(field)) return true;
+ }
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute[] GetCustomAttributes(RuntimeConstructorInfo ctor, RuntimeType caType, bool includeSecCa, out int count)
+ {
+ count = 0;
+
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+
+ if (!all && s_pca.GetValueOrDefault(caType) == null && !IsSecurityAttribute(caType))
+ return Array.Empty<Attribute>();
+
+ List<Attribute> pcas = new List<Attribute>();
+
+ if (includeSecCa && (all || IsSecurityAttribute(caType)))
+ {
+ object[] securityAttributes;
+
+ GetSecurityAttributes(ctor.Module.ModuleHandle.GetRuntimeModule(), ctor.MetadataToken, false, out securityAttributes);
+ if (securityAttributes != null)
+ foreach (object a in securityAttributes)
+ if (caType == a.GetType() || a.GetType().IsSubclassOf(caType))
+ pcas.Add((Attribute)a);
+ }
+
+ count = pcas.Count;
+ return pcas.ToArray();
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeConstructorInfo ctor, RuntimeType caType)
+ {
+ bool all = caType == (RuntimeType)typeof(object) || caType == (RuntimeType)typeof(Attribute);
+
+ if (!all && s_pca.GetValueOrDefault(caType) == null)
+ return false;
+
+ if (all || IsSecurityAttribute(caType))
+ {
+ int count;
+
+ if (GetCustomAttributes(ctor, caType, true, out count).Length != 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ internal static Attribute[] GetCustomAttributes(RuntimePropertyInfo property, RuntimeType caType, out int count)
+ {
+ count = 0;
+ return null;
+ }
+ internal static bool IsDefined(RuntimePropertyInfo property, RuntimeType caType)
+ {
+ return false;
+ }
+
+ internal static Attribute[] GetCustomAttributes(RuntimeEventInfo e, RuntimeType caType, out int count)
+ {
+ count = 0;
+ return null;
+ }
+ internal static bool IsDefined(RuntimeEventInfo e, RuntimeType caType)
+ {
+ return false;
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/CustomAttributeExtensions.cs b/src/mscorlib/src/System/Reflection/CustomAttributeExtensions.cs
new file mode 100644
index 0000000000..c3287e17d1
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/CustomAttributeExtensions.cs
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Collections.Generic;
+
+namespace System.Reflection
+{
+ public static class CustomAttributeExtensions
+ {
+ #region APIs that return a single attribute
+ public static Attribute GetCustomAttribute(this Assembly element, Type attributeType)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType);
+ }
+ public static Attribute GetCustomAttribute(this Module element, Type attributeType)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType);
+ }
+ public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType);
+ }
+ public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType);
+ }
+
+ public static T GetCustomAttribute<T>(this Assembly element) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T));
+ }
+ public static T GetCustomAttribute<T>(this Module element) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T));
+ }
+ public static T GetCustomAttribute<T>(this MemberInfo element) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T));
+ }
+ public static T GetCustomAttribute<T>(this ParameterInfo element) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T));
+ }
+
+ public static Attribute GetCustomAttribute(this MemberInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType, inherit);
+ }
+ public static Attribute GetCustomAttribute(this ParameterInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.GetCustomAttribute(element, attributeType, inherit);
+ }
+
+ public static T GetCustomAttribute<T>(this MemberInfo element, bool inherit) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T), inherit);
+ }
+ public static T GetCustomAttribute<T>(this ParameterInfo element, bool inherit) where T : Attribute
+ {
+ return (T)GetCustomAttribute(element, typeof(T), inherit);
+ }
+ #endregion
+
+ #region APIs that return all attributes
+ public static IEnumerable<Attribute> GetCustomAttributes(this Assembly element)
+ {
+ return Attribute.GetCustomAttributes(element);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this Module element)
+ {
+ return Attribute.GetCustomAttributes(element);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this MemberInfo element)
+ {
+ return Attribute.GetCustomAttributes(element);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element)
+ {
+ return Attribute.GetCustomAttributes(element);
+ }
+
+ public static IEnumerable<Attribute> GetCustomAttributes(this MemberInfo element, bool inherit)
+ {
+ return Attribute.GetCustomAttributes(element, inherit);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element, bool inherit)
+ {
+ return Attribute.GetCustomAttributes(element, inherit);
+ }
+ #endregion
+
+ #region APIs that return all attributes of a particular type
+ public static IEnumerable<Attribute> GetCustomAttributes(this Assembly element, Type attributeType)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this Module element, Type attributeType)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this MemberInfo element, Type attributeType)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element, Type attributeType)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType);
+ }
+
+ public static IEnumerable<T> GetCustomAttributes<T>(this Assembly element) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T));
+ }
+ public static IEnumerable<T> GetCustomAttributes<T>(this Module element) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T));
+ }
+ public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo element) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T));
+ }
+ public static IEnumerable<T> GetCustomAttributes<T>(this ParameterInfo element) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T));
+ }
+
+ public static IEnumerable<Attribute> GetCustomAttributes(this MemberInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType, inherit);
+ }
+ public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.GetCustomAttributes(element, attributeType, inherit);
+ }
+
+ public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo element, bool inherit) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T), inherit);
+ }
+ public static IEnumerable<T> GetCustomAttributes<T>(this ParameterInfo element, bool inherit) where T : Attribute
+ {
+ return (IEnumerable<T>)GetCustomAttributes(element, typeof(T), inherit);
+ }
+ #endregion
+
+ #region IsDefined
+ public static bool IsDefined(this Assembly element, Type attributeType)
+ {
+ return Attribute.IsDefined(element, attributeType);
+ }
+ public static bool IsDefined(this Module element, Type attributeType)
+ {
+ return Attribute.IsDefined(element, attributeType);
+ }
+ public static bool IsDefined(this MemberInfo element, Type attributeType)
+ {
+ return Attribute.IsDefined(element, attributeType);
+ }
+ public static bool IsDefined(this ParameterInfo element, Type attributeType)
+ {
+ return Attribute.IsDefined(element, attributeType);
+ }
+
+ public static bool IsDefined(this MemberInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.IsDefined(element, attributeType, inherit);
+ }
+ public static bool IsDefined(this ParameterInfo element, Type attributeType, bool inherit)
+ {
+ return Attribute.IsDefined(element, attributeType, inherit);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/CustomAttributeFormatException.cs b/src/mscorlib/src/System/Reflection/CustomAttributeFormatException.cs
new file mode 100644
index 0000000000..3eb8b1f1ef
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/CustomAttributeFormatException.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// CustomAttributeFormatException is thrown when the binary format of a
+//
+// custom attribute is invalid.
+//
+//
+namespace System.Reflection {
+ using System;
+ using ApplicationException = System.ApplicationException;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CustomAttributeFormatException : FormatException {
+
+ public CustomAttributeFormatException()
+ : base(Environment.GetResourceString("Arg_CustomAttributeFormatException")) {
+ SetErrorCode(__HResults.COR_E_CUSTOMATTRIBUTEFORMAT);
+ }
+
+ public CustomAttributeFormatException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_CUSTOMATTRIBUTEFORMAT);
+ }
+
+ public CustomAttributeFormatException(String message, Exception inner) : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_CUSTOMATTRIBUTEFORMAT);
+ }
+
+ protected CustomAttributeFormatException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/DefaultMemberAttribute.cs b/src/mscorlib/src/System/Reflection/DefaultMemberAttribute.cs
new file mode 100644
index 0000000000..1fec75906a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/DefaultMemberAttribute.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// DefaultMemberAttribute is defines the Member of a Type that is the "default"
+//
+// member used by Type.InvokeMember. The default member is simply a name given
+// to a type.
+//
+//
+//
+//
+namespace System.Reflection {
+
+ using System;
+
+[Serializable]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DefaultMemberAttribute : Attribute
+ {
+ // The name of the member
+ private String m_memberName;
+
+ // You must provide the name of the member, this is required
+ public DefaultMemberAttribute(String memberName) {
+ m_memberName = memberName;
+ }
+
+ // A get accessor to return the name from the attribute.
+ // NOTE: There is no setter because the name must be provided
+ // to the constructor. The name is not optional.
+ public String MemberName {
+ get {return m_memberName;}
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs
new file mode 100644
index 0000000000..6484677c62
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/AQNBuilder.cs
@@ -0,0 +1,208 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Reflection.Emit
+{
+ // TypeNameBuilder is NOT thread safe NOR reliable
+ internal class TypeNameBuilder
+ {
+ internal enum Format
+ {
+ ToString,
+ FullName,
+ AssemblyQualifiedName,
+ }
+
+ #region QCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr CreateTypeNameBuilder();
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void ReleaseTypeNameBuilder(IntPtr pAQN);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void OpenGenericArguments(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void CloseGenericArguments(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void OpenGenericArgument(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void CloseGenericArgument(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddName(IntPtr tnb, string name);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddPointer(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddByRef(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddSzArray(IntPtr tnb);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddArray(IntPtr tnb, int rank);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddAssemblySpec(IntPtr tnb, string assemblySpec);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void ToString(IntPtr tnb, StringHandleOnStack retString);
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void Clear(IntPtr tnb);
+ #endregion
+
+ #region Static Members
+
+ // TypeNameBuilder is NOT thread safe NOR reliable
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static string ToString(Type type, Format format)
+ {
+ if (format == Format.FullName || format == Format.AssemblyQualifiedName)
+ {
+ if (!type.IsGenericTypeDefinition && type.ContainsGenericParameters)
+ return null;
+ }
+
+ TypeNameBuilder tnb = new TypeNameBuilder(CreateTypeNameBuilder());
+ tnb.Clear();
+ tnb.ConstructAssemblyQualifiedNameWorker(type, format);
+ string toString = tnb.ToString();
+ tnb.Dispose();
+ return toString;
+ }
+ #endregion
+
+ #region Private Data Members
+ private IntPtr m_typeNameBuilder;
+ #endregion
+
+ #region Constructor
+ private TypeNameBuilder(IntPtr typeNameBuilder) { m_typeNameBuilder = typeNameBuilder; }
+ [System.Security.SecurityCritical] // auto-generated
+ internal void Dispose() { ReleaseTypeNameBuilder(m_typeNameBuilder); }
+ #endregion
+
+ #region private Members
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddElementType(Type elementType)
+ {
+ if (elementType.HasElementType)
+ AddElementType(elementType.GetElementType());
+
+ if (elementType.IsPointer)
+ AddPointer();
+
+ else if (elementType.IsByRef)
+ AddByRef();
+
+ else if (elementType.IsSzArray)
+ AddSzArray();
+
+ else if (elementType.IsArray)
+ AddArray(elementType.GetArrayRank());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void ConstructAssemblyQualifiedNameWorker(Type type, Format format)
+ {
+ Type rootType = type;
+
+ while (rootType.HasElementType)
+ rootType = rootType.GetElementType();
+
+ // Append namespace + nesting + name
+ List<Type> nestings = new List<Type>();
+ for (Type t = rootType; t != null; t = t.IsGenericParameter ? null : t.DeclaringType)
+ nestings.Add(t);
+
+ for (int i = nestings.Count - 1; i >= 0; i--)
+ {
+ Type enclosingType = nestings[i];
+ string name = enclosingType.Name;
+
+ if (i == nestings.Count - 1 && enclosingType.Namespace != null && enclosingType.Namespace.Length != 0)
+ name = enclosingType.Namespace + "." + name;
+
+ AddName(name);
+ }
+
+ // Append generic arguments
+ if (rootType.IsGenericType && (!rootType.IsGenericTypeDefinition || format == Format.ToString))
+ {
+ Type[] genericArguments = rootType.GetGenericArguments();
+
+ OpenGenericArguments();
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ Format genericArgumentsFormat = format == Format.FullName ? Format.AssemblyQualifiedName : format;
+
+ OpenGenericArgument();
+ ConstructAssemblyQualifiedNameWorker(genericArguments[i], genericArgumentsFormat);
+ CloseGenericArgument();
+ }
+ CloseGenericArguments();
+ }
+
+ // Append pointer, byRef and array qualifiers
+ AddElementType(type);
+
+ if (format == Format.AssemblyQualifiedName)
+ AddAssemblySpec(type.Module.Assembly.FullName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void OpenGenericArguments() { OpenGenericArguments(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void CloseGenericArguments() { CloseGenericArguments(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void OpenGenericArgument() { OpenGenericArgument(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void CloseGenericArgument() { CloseGenericArgument(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddName(string name) { AddName(m_typeNameBuilder, name); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddPointer() { AddPointer(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddByRef() { AddByRef(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddSzArray() { AddSzArray(m_typeNameBuilder); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddArray(int rank) { AddArray(m_typeNameBuilder, rank); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddAssemblySpec(string assemblySpec) { AddAssemblySpec(m_typeNameBuilder, assemblySpec); }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override string ToString() { string ret = null; ToString(m_typeNameBuilder, JitHelpers.GetStringHandleOnStack(ref ret)); return ret; }
+ [System.Security.SecurityCritical] // auto-generated
+ private void Clear() { Clear(m_typeNameBuilder); }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs
new file mode 100644
index 0000000000..5e7f83f2df
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilder.cs
@@ -0,0 +1,2245 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//*************************************************************************************************************
+// For each dynamic assembly there will be two AssemblyBuilder objects: the "internal"
+// AssemblyBuilder object and the "external" AssemblyBuilder object.
+// 1. The "internal" object is the real assembly object that the VM creates and knows about. However,
+// you can perform RefEmit operations on it only if you have its granted permission. From the AppDomain
+// and other "internal" objects like the "internal" ModuleBuilders and runtime types, you can only
+// get the "internal" objects. This is to prevent low-trust code from getting a hold of the dynamic
+// AssemblyBuilder/ModuleBuilder/TypeBuilder/MethodBuilder/etc other people have created by simply
+// enumerating the AppDomain and inject code in it.
+// 2. The "external" object is merely an wrapper of the "internal" object and all operations on it
+// are directed to the internal object. This is the one you get by calling DefineDynamicAssembly
+// on AppDomain and the one you can always perform RefEmit operations on. You can get other "external"
+// objects from the "external" AssemblyBuilder, ModuleBuilder, TypeBuilder, MethodBuilder, etc. Note
+// that VM doesn't know about this object. So every time we call into the VM we need to pass in the
+// "internal" object.
+//
+// "internal" and "external" ModuleBuilders are similar
+//*************************************************************************************************************
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.SymbolStore;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.IO;
+ using System.Reflection;
+ using System.Resources;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Security.Policy;
+ using System.Threading;
+
+ // These must match the definitions in Assembly.hpp
+ [Flags]
+ internal enum DynamicAssemblyFlags
+ {
+ None = 0x00000000,
+
+ // Security attributes which affect the module security descriptor
+ AllCritical = 0x00000001,
+ Aptca = 0x00000002,
+ Critical = 0x00000004,
+ Transparent = 0x00000008,
+ TreatAsSafe = 0x00000010,
+ }
+
+ // When the user calls AppDomain.DefineDynamicAssembly the loader creates a new InternalAssemblyBuilder.
+ // This InternalAssemblyBuilder can be retrieved via a call to Assembly.GetAssemblies() by untrusted code.
+ // In the past, when InternalAssemblyBuilder was AssemblyBuilder, the untrusted user could down cast the
+ // Assembly to an AssemblyBuilder and emit code with the elevated permissions of the trusted code which
+ // origionally created the AssemblyBuilder via DefineDynamicAssembly. Today, this can no longer happen
+ // because the Assembly returned via AssemblyGetAssemblies() will be an InternalAssemblyBuilder.
+
+ // Only the caller of DefineDynamicAssembly will get an AssemblyBuilder.
+ // There is a 1-1 relationship between InternalAssemblyBuilder and AssemblyBuilder.
+ // AssemblyBuilder is composed of its InternalAssemblyBuilder.
+ // The AssemblyBuilder data members (e.g. m_foo) were changed to properties which then delegate
+ // the access to the composed InternalAssemblyBuilder. This way, AssemblyBuilder simply wraps
+ // InternalAssemblyBuilder and still operates on InternalAssemblyBuilder members.
+ // This also makes the change transparent to the loader. This is good because most of the complexity
+ // of Assembly building is in the loader code so not touching that code reduces the chance of
+ // introducing new bugs.
+ internal sealed class InternalAssemblyBuilder : RuntimeAssembly
+ {
+ private InternalAssemblyBuilder() { }
+
+ #region object overrides
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (obj is InternalAssemblyBuilder)
+ return ((object)this == obj);
+
+ return obj.Equals(this);
+ }
+ // Need a dummy GetHashCode to pair with Equals
+ public override int GetHashCode() { return base.GetHashCode(); }
+ #endregion
+
+ // Assembly methods that are overridden by AssemblyBuilder should be overridden by InternalAssemblyBuilder too
+ #region Methods inherited from Assembly
+ public override String[] GetManifestResourceNames()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override FileStream GetFile(String name)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override FileStream[] GetFiles(bool getResourceModules)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ public override Stream GetManifestResourceStream(Type type, String name)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ public override Stream GetManifestResourceStream(String name)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ public override ManifestResourceInfo GetManifestResourceInfo(String resourceName)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ public override String Location
+ {
+#if FEATURE_CORECLR
+ [SecurityCritical]
+#endif // FEATURE_CORECLR
+ get
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+ }
+
+ public override String CodeBase
+ {
+#if FEATURE_CORECLR
+ [SecurityCritical]
+#endif // FEATURE_CORECLR
+ get
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+ }
+
+ public override Type[] GetExportedTypes()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicAssembly"));
+ }
+
+ public override String ImageRuntimeVersion
+ {
+ get
+ {
+ return RuntimeEnvironment.GetSystemVersion();
+ }
+ }
+ #endregion
+ }
+
+ // AssemblyBuilder class.
+ // deliberately not [serializable]
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_AssemblyBuilder))]
+ [ComVisible(true)]
+ public sealed class AssemblyBuilder : Assembly, _AssemblyBuilder
+ {
+ #region FCALL
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern RuntimeModule GetInMemoryAssemblyModule(RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private Module nGetInMemoryAssemblyModule()
+ {
+ return AssemblyBuilder.GetInMemoryAssemblyModule(GetNativeHandle());
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern RuntimeModule GetOnDiskAssemblyModule(RuntimeAssembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ModuleBuilder GetOnDiskAssemblyModuleBuilder()
+ {
+ if (m_onDiskAssemblyModuleBuilder == null)
+ {
+ Module module = AssemblyBuilder.GetOnDiskAssemblyModule(InternalAssembly.GetNativeHandle());
+ ModuleBuilder modBuilder = new ModuleBuilder(this, (InternalModuleBuilder)module);
+ modBuilder.Init("RefEmit_OnDiskManifestModule", null, 0);
+ m_onDiskAssemblyModuleBuilder = modBuilder;
+ }
+
+ return m_onDiskAssemblyModuleBuilder;
+ }
+#endif // FEATURE_CORECLR
+
+ #endregion
+
+ #region Internal Data Members
+ // This is only valid in the "external" AssemblyBuilder
+ internal AssemblyBuilderData m_assemblyData;
+ private InternalAssemblyBuilder m_internalAssemblyBuilder;
+ private ModuleBuilder m_manifestModuleBuilder;
+ // Set to true if the manifest module was returned by code:DefineDynamicModule to the user
+ private bool m_fManifestModuleUsedAsDefinedModule;
+ internal const string MANIFEST_MODULE_NAME = "RefEmit_InMemoryManifestModule";
+#if !FEATURE_CORECLR
+ private ModuleBuilder m_onDiskAssemblyModuleBuilder;
+#endif // !FEATURE_CORECLR
+
+#if FEATURE_APPX
+ private bool m_profileAPICheck;
+#endif
+
+ internal ModuleBuilder GetModuleBuilder(InternalModuleBuilder module)
+ {
+ Contract.Requires(module != null);
+ Contract.Assert(this.InternalAssembly == module.Assembly);
+
+ lock(SyncRoot)
+ {
+#if !FEATURE_CORECLR
+ foreach (ModuleBuilder modBuilder in m_assemblyData.m_moduleBuilderList)
+ {
+ if (modBuilder.InternalModule == module)
+ return modBuilder;
+ }
+
+ // m_onDiskAssemblyModuleBuilder is null before Save
+ if (m_onDiskAssemblyModuleBuilder != null && m_onDiskAssemblyModuleBuilder.InternalModule == module)
+ return m_onDiskAssemblyModuleBuilder;
+#endif // !FEATURE_CORECLR
+
+ // in CoreCLR there is only one module in each dynamic assembly, the manifest module
+ if (m_manifestModuleBuilder.InternalModule == module)
+ return m_manifestModuleBuilder;
+
+ throw new ArgumentException("module");
+ }
+ }
+
+ internal object SyncRoot
+ {
+ get
+ {
+ return InternalAssembly.SyncRoot;
+ }
+ }
+
+ internal InternalAssemblyBuilder InternalAssembly
+ {
+ get
+ {
+ return m_internalAssemblyBuilder;
+ }
+ }
+
+ internal RuntimeAssembly GetNativeHandle()
+ {
+ return InternalAssembly.GetNativeHandle();
+ }
+
+ [SecurityCritical]
+ internal Version GetVersion()
+ {
+ return InternalAssembly.GetVersion();
+ }
+
+#if FEATURE_APPX
+ internal bool ProfileAPICheck
+ {
+ get
+ {
+ return m_profileAPICheck;
+ }
+ }
+#endif
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal AssemblyBuilder(AppDomain domain,
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ ref StackCrawlMark stackMark,
+ IEnumerable<CustomAttributeBuilder> unsafeAssemblyAttributes,
+ SecurityContextSource securityContextSource)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (access != AssemblyBuilderAccess.Run
+#if !FEATURE_CORECLR
+ && access != AssemblyBuilderAccess.Save
+ && access != AssemblyBuilderAccess.RunAndSave
+#endif // !FEATURE_CORECLR
+#if FEATURE_REFLECTION_ONLY_LOAD
+ && access != AssemblyBuilderAccess.ReflectionOnly
+#endif // FEATURE_REFLECTION_ONLY_LOAD
+#if FEATURE_COLLECTIBLE_TYPES
+ && access != AssemblyBuilderAccess.RunAndCollect
+#endif // FEATURE_COLLECTIBLE_TYPES
+ )
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access), "access");
+ }
+
+ if (securityContextSource < SecurityContextSource.CurrentAppDomain ||
+ securityContextSource > SecurityContextSource.CurrentAssembly)
+ {
+ throw new ArgumentOutOfRangeException("securityContextSource");
+ }
+
+ // Clone the name in case the caller modifies it underneath us.
+ name = (AssemblyName)name.Clone();
+
+#if !FEATURE_CORECLR
+ // Set the public key from the key pair if one has been provided.
+ // (Overwite any public key in the Assembly name, since it's no
+ // longer valid to have a disparity).
+ if (name.KeyPair != null)
+ name.SetPublicKey(name.KeyPair.PublicKey);
+#endif
+
+ // If the caller is trusted they can supply identity
+ // evidence for the new assembly. Otherwise we copy the
+ // current grant and deny sets from the caller's assembly,
+ // inject them into the new assembly and mark policy as
+ // resolved. If/when the assembly is persisted and
+ // reloaded, the normal rules for gathering evidence will
+ // be used.
+ if (evidence != null)
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+#pragma warning restore 618
+
+#if FEATURE_COLLECTIBLE_TYPES && !FEATURE_CORECLR
+ // Collectible assemblies require FullTrust. This demand may be removed if we deem the
+ // feature robust enough to be used directly by untrusted API consumers.
+ if (access == AssemblyBuilderAccess.RunAndCollect)
+ new PermissionSet(PermissionState.Unrestricted).Demand();
+#endif // FEATURE_COLLECTIBLE_TYPES && !FEATURE_CORECLR
+
+ // Scan the assembly level attributes for any attributes which modify how we create the
+ // assembly. Currently, we look for any attribute which modifies the security transparency
+ // of the assembly.
+ List<CustomAttributeBuilder> assemblyAttributes = null;
+ DynamicAssemblyFlags assemblyFlags = DynamicAssemblyFlags.None;
+ byte[] securityRulesBlob = null;
+ byte[] aptcaBlob = null;
+ if (unsafeAssemblyAttributes != null)
+ {
+ // Create a copy to ensure that it cannot be modified from another thread
+ // as it is used further below.
+ assemblyAttributes = new List<CustomAttributeBuilder>(unsafeAssemblyAttributes);
+
+#pragma warning disable 618 // We deal with legacy attributes here as well for compat
+ foreach (CustomAttributeBuilder attribute in assemblyAttributes)
+ {
+ if (attribute.m_con.DeclaringType == typeof(SecurityTransparentAttribute))
+ {
+ assemblyFlags |= DynamicAssemblyFlags.Transparent;
+ }
+ else if (attribute.m_con.DeclaringType == typeof(SecurityCriticalAttribute))
+ {
+#if !FEATURE_CORECLR
+ SecurityCriticalScope scope = SecurityCriticalScope.Everything;
+ if (attribute.m_constructorArgs != null &&
+ attribute.m_constructorArgs.Length == 1 &&
+ attribute.m_constructorArgs[0] is SecurityCriticalScope)
+ {
+ scope = (SecurityCriticalScope)attribute.m_constructorArgs[0];
+ }
+
+ assemblyFlags |= DynamicAssemblyFlags.Critical;
+ if (scope == SecurityCriticalScope.Everything)
+#endif // !FEATURE_CORECLR
+ {
+ assemblyFlags |= DynamicAssemblyFlags.AllCritical;
+ }
+ }
+#if !FEATURE_CORECLR
+ else if (attribute.m_con.DeclaringType == typeof(SecurityRulesAttribute))
+ {
+ securityRulesBlob = new byte[attribute.m_blob.Length];
+ Buffer.BlockCopy(attribute.m_blob, 0, securityRulesBlob, 0, securityRulesBlob.Length);
+ }
+ else if (attribute.m_con.DeclaringType == typeof(SecurityTreatAsSafeAttribute))
+ {
+ assemblyFlags |= DynamicAssemblyFlags.TreatAsSafe;
+ }
+#endif // !FEATURE_CORECLR
+#if FEATURE_APTCA
+ else if (attribute.m_con.DeclaringType == typeof(AllowPartiallyTrustedCallersAttribute))
+ {
+ assemblyFlags |= DynamicAssemblyFlags.Aptca;
+ aptcaBlob = new byte[attribute.m_blob.Length];
+ Buffer.BlockCopy(attribute.m_blob, 0, aptcaBlob, 0, aptcaBlob.Length);
+ }
+#endif // FEATURE_APTCA
+ }
+#pragma warning restore 618
+ }
+
+ m_internalAssemblyBuilder = (InternalAssemblyBuilder)nCreateDynamicAssembly(domain,
+ name,
+ evidence,
+ ref stackMark,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ securityRulesBlob,
+ aptcaBlob,
+ access,
+ assemblyFlags,
+ securityContextSource);
+
+ m_assemblyData = new AssemblyBuilderData(m_internalAssemblyBuilder,
+ name.Name,
+ access,
+ dir);
+ m_assemblyData.AddPermissionRequests(requiredPermissions,
+ optionalPermissions,
+ refusedPermissions);
+
+#if FEATURE_APPX
+ if (AppDomain.ProfileAPICheck)
+ {
+ RuntimeAssembly creator = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (creator != null && !creator.IsFrameworkAssembly())
+ m_profileAPICheck = true;
+ }
+#endif
+ // Make sure that ManifestModule is properly initialized
+ // We need to do this before setting any CustomAttribute
+ InitManifestModule();
+
+ if (assemblyAttributes != null)
+ {
+ foreach (CustomAttributeBuilder assemblyAttribute in assemblyAttributes)
+ SetCustomAttribute(assemblyAttribute);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void InitManifestModule()
+ {
+ InternalModuleBuilder modBuilder = (InternalModuleBuilder)nGetInMemoryAssemblyModule();
+
+ // Note that this ModuleBuilder cannot be used for RefEmit yet
+ // because it hasn't been initialized.
+ // However, it can be used to set the custom attribute on the Assembly
+ m_manifestModuleBuilder = new ModuleBuilder(this, modBuilder);
+
+ // We are only setting the name in the managed ModuleBuilderData here.
+ // The name in the underlying metadata will be set when the
+ // manifest module is created during nCreateDynamicAssembly.
+
+ // This name needs to stay in sync with that used in
+ // Assembly::Init to call ReflectionModule::Create (in VM)
+ m_manifestModuleBuilder.Init(AssemblyBuilder.MANIFEST_MODULE_NAME, null, 0);
+
+ m_fManifestModuleUsedAsDefinedModule = false;
+ }
+ #endregion
+
+ #region DefineDynamicAssembly
+
+ /**********************************************
+ * If an AssemblyName has a public key specified, the assembly is assumed
+ * to have a strong name and a hash will be computed when the assembly
+ * is saved.
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name, access, null,
+ null, null, null, null, ref stackMark, null, SecurityContextSource.CurrentAssembly);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static AssemblyBuilder DefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ IEnumerable<CustomAttributeBuilder> assemblyAttributes)
+ {
+ Contract.Ensures(Contract.Result<AssemblyBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalDefineDynamicAssembly(name,
+ access,
+ null, null, null, null, null,
+ ref stackMark,
+ assemblyAttributes, SecurityContextSource.CurrentAssembly);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Assembly nCreateDynamicAssembly(AppDomain domain,
+ AssemblyName name,
+ Evidence identity,
+ ref StackCrawlMark stackMark,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ byte[] securityRulesBlob,
+ byte[] aptcaBlob,
+ AssemblyBuilderAccess access,
+ DynamicAssemblyFlags flags,
+ SecurityContextSource securityContextSource);
+
+ private class AssemblyBuilderLock { }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static AssemblyBuilder InternalDefineDynamicAssembly(
+ AssemblyName name,
+ AssemblyBuilderAccess access,
+ String dir,
+ Evidence evidence,
+ PermissionSet requiredPermissions,
+ PermissionSet optionalPermissions,
+ PermissionSet refusedPermissions,
+ ref StackCrawlMark stackMark,
+ IEnumerable<CustomAttributeBuilder> unsafeAssemblyAttributes,
+ SecurityContextSource securityContextSource)
+ {
+#if FEATURE_CAS_POLICY
+ if (evidence != null && !AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ lock (typeof(AssemblyBuilderLock))
+ {
+ // we can only create dynamic assemblies in the current domain
+ return new AssemblyBuilder(AppDomain.CurrentDomain,
+ name,
+ access,
+ dir,
+ evidence,
+ requiredPermissions,
+ optionalPermissions,
+ refusedPermissions,
+ ref stackMark,
+ unsafeAssemblyAttributes,
+ securityContextSource);
+ } //lock(typeof(AssemblyBuilderLock))
+ }
+ #endregion
+
+ #region DefineDynamicModule
+ /**********************************************
+ *
+ * Defines a named dynamic module. It is an error to define multiple
+ * modules within an Assembly with the same name. This dynamic module is
+ * a transient module.
+ *
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ModuleBuilder DefineDynamicModule(
+ String name)
+ {
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return DefineDynamicModuleInternal(name, false, ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ModuleBuilder DefineDynamicModule(
+ String name,
+ bool emitSymbolInfo) // specify if emit symbol info or not
+ {
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return DefineDynamicModuleInternal( name, emitSymbolInfo, ref stackMark );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ModuleBuilder DefineDynamicModuleInternal(
+ String name,
+ bool emitSymbolInfo, // specify if emit symbol info or not
+ ref StackCrawlMark stackMark)
+ {
+ lock(SyncRoot)
+ {
+ return DefineDynamicModuleInternalNoLock(name, emitSymbolInfo, ref stackMark);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ModuleBuilder DefineDynamicModuleInternalNoLock(
+ String name,
+ bool emitSymbolInfo, // specify if emit symbol info or not
+ ref StackCrawlMark stackMark)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ if (name[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name");
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + " )");
+
+ Contract.Assert(m_assemblyData != null, "m_assemblyData is null in DefineDynamicModuleInternal");
+
+ ModuleBuilder dynModule;
+ ISymbolWriter writer = null;
+ IntPtr pInternalSymWriter = new IntPtr();
+
+ // create the dynamic module
+
+#if FEATURE_MULTIMODULE_ASSEMBLIES
+
+#if FEATURE_CORECLR
+#error FEATURE_MULTIMODULE_ASSEMBLIES should always go with !FEATURE_CORECLR
+#endif //FEATURE_CORECLR
+
+ m_assemblyData.CheckNameConflict(name);
+
+ if (m_fManifestModuleUsedAsDefinedModule == true)
+ { // We need to define a new module
+ int tkFile;
+ InternalModuleBuilder internalDynModule = (InternalModuleBuilder)DefineDynamicModule(
+ InternalAssembly,
+ emitSymbolInfo,
+ name,
+ name,
+ ref stackMark,
+ ref pInternalSymWriter,
+ true /*fIsTransient*/,
+ out tkFile);
+ dynModule = new ModuleBuilder(this, internalDynModule);
+
+ // initialize the dynamic module's managed side information
+ dynModule.Init(name, null, tkFile);
+ }
+ else
+ { // We will reuse the manifest module
+ m_manifestModuleBuilder.ModifyModuleName(name);
+ dynModule = m_manifestModuleBuilder;
+
+ if (emitSymbolInfo)
+ {
+ pInternalSymWriter = ModuleBuilder.nCreateISymWriterForDynamicModule(dynModule.InternalModule, name);
+ }
+ }
+
+#else // FEATURE_MULTIMODULE_ASSEMBLIES
+ // Without FEATURE_MULTIMODULE_ASSEMBLIES only one ModuleBuilder per AssemblyBuilder can be created
+ if (m_fManifestModuleUsedAsDefinedModule == true)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoMultiModuleAssembly"));
+
+ // Init(...) has already been called on m_manifestModuleBuilder in InitManifestModule()
+ dynModule = m_manifestModuleBuilder;
+#endif // FEATURE_MULTIMODULE_ASSEMBLIES
+
+ // Create the symbol writer
+ if (emitSymbolInfo)
+ {
+#if FEATURE_MULTIMODULE_ASSEMBLIES && !FEATURE_CORECLR
+ // this is the code path for the desktop runtime
+
+ // create the default SymWriter
+ Assembly assem = LoadISymWrapper();
+ Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false);
+ if (symWriter != null && !symWriter.IsVisible)
+ symWriter = null;
+
+ if (symWriter == null)
+ {
+ // cannot find SymWriter - throw TypeLoadException since we couldnt find the type.
+ throw new TypeLoadException(Environment.GetResourceString(ResId.MissingType, "SymWriter"));
+ }
+
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+
+ try
+ {
+ (new PermissionSet(PermissionState.Unrestricted)).Assert();
+ writer = (ISymbolWriter)Activator.CreateInstance(symWriter);
+
+ // Set the underlying writer for the managed writer
+ // that we're using. Note that this function requires
+ // unmanaged code access.
+ writer.SetUnderlyingWriter(pInternalSymWriter);
+ }
+ finally
+ {
+ CodeAccessPermission.RevertAssert();
+ }
+#endif // FEATURE_MULTIMODULE_ASSEMBLIES && !FEATURE_CORECLR
+
+#if !FEATURE_MULTIMODULE_ASSEMBLIES && FEATURE_CORECLR
+ // this is the code path for CoreCLR
+
+ writer = SymWrapperCore.SymWriter.CreateSymWriter();
+ // Set the underlying writer for the managed writer
+ // that we're using. Note that this function requires
+ // unmanaged code access.
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
+#pragma warning restore 618
+
+ String fileName = "Unused"; // this symfile is never written to disk so filename does not matter.
+
+ // Pass the "real" module to the VM
+ pInternalSymWriter = ModuleBuilder.nCreateISymWriterForDynamicModule(dynModule.InternalModule, fileName);
+
+ // In Telesto, we took the SetUnderlyingWriter method private as it's a very rickety method.
+ // This might someday be a good move for the desktop CLR too.
+ ((SymWrapperCore.SymWriter)writer).InternalSetUnderlyingWriter(pInternalSymWriter);
+#endif // !FEATURE_MULTIMODULE_ASSEMBLIES && FEATURE_CORECLR
+ } // Creating the symbol writer
+
+ dynModule.SetSymWriter(writer);
+ m_assemblyData.AddModule(dynModule);
+
+ if (dynModule == m_manifestModuleBuilder)
+ { // We are reusing manifest module as user-defined dynamic module
+ m_fManifestModuleUsedAsDefinedModule = true;
+ }
+
+ return dynModule;
+ } // DefineDynamicModuleInternalNoLock
+
+#if !FEATURE_CORECLR
+ // All dynamic modules in SilverLight are transient so we removed this overload of DefineDynamicModule
+ // Note that it is assumed that !FEATURE_CORECLR always goes with FEATURE_MULTIMODULE_ASSEMBLIES
+ // If we ever will build a non coreclr version of the runtime without FEATURE_MULTIMODULE_ASSEMBLIES
+ // we will need to make the same changes here as the ones we made in the transient overload
+
+ /**********************************************
+ *
+ * Defines a named dynamic module. It is an error to define multiple
+ * modules within an Assembly with the same name. No symbol information
+ * will be emitted.
+ *
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ModuleBuilder DefineDynamicModule(
+ String name,
+ String fileName)
+ {
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // delegate to the next DefineDynamicModule
+ return DefineDynamicModuleInternal(name, fileName, false, ref stackMark);
+ }
+
+ /**********************************************
+ *
+ * Emit symbol information if emitSymbolInfo is true using the
+ * default symbol writer interface.
+ * An exception will be thrown if the assembly is transient.
+ *
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ModuleBuilder DefineDynamicModule(
+ String name, // module name
+ String fileName, // module file name
+ bool emitSymbolInfo) // specify if emit symbol info or not
+ {
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return DefineDynamicModuleInternal(name, fileName, emitSymbolInfo, ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ModuleBuilder DefineDynamicModuleInternal(
+ String name, // module name
+ String fileName, // module file name
+ bool emitSymbolInfo, // specify if emit symbol info or not
+ ref StackCrawlMark stackMark) // stack crawl mark used to find caller
+ {
+ lock(SyncRoot)
+ {
+ return DefineDynamicModuleInternalNoLock(name, fileName, emitSymbolInfo, ref stackMark);
+ }
+ }
+
+ // "name" will be used for:
+ // 1. The Name field in the Module table.
+ // 2. ModuleBuilder.GetModule(string).
+ // "fileName" will be used for:
+ // 1. The name field in the ModuleRef table when this module is being referenced by
+ // another module in the same assembly.
+ // 2. .file record in the in memory assembly manifest when the module is created in memory
+ // 3. .file record in the on disk assembly manifest when the assembly is saved to disk
+ // 4. The file name of the saved module.
+ [System.Security.SecurityCritical] // auto-generated
+ private ModuleBuilder DefineDynamicModuleInternalNoLock(
+ String name, // module name
+ String fileName, // module file name
+ bool emitSymbolInfo, // specify if emit symbol info or not
+ ref StackCrawlMark stackMark) // stack crawl mark used to find caller
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ if (name[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidName"), "name");
+
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ if (fileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName");
+ if (!String.Equals(fileName, Path.GetFileName(fileName)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
+ Contract.Ensures(Contract.Result<ModuleBuilder>() != null);
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineDynamicModule( " + name + ", " + fileName + ", " + emitSymbolInfo + " )");
+ if (m_assemblyData.m_access == AssemblyBuilderAccess.Run)
+ {
+ // Error! You cannot define a persistable module within a transient data.
+ throw new NotSupportedException(Environment.GetResourceString("Argument_BadPersistableModuleInTransientAssembly"));
+ }
+
+ if (m_assemblyData.m_isSaved == true)
+ {
+ // assembly has been saved before!
+ throw new InvalidOperationException(Environment.GetResourceString(
+ "InvalidOperation_CannotAlterAssembly"));
+ }
+
+ ModuleBuilder dynModule;
+ ISymbolWriter writer = null;
+ IntPtr pInternalSymWriter = new IntPtr();
+
+ // create the dynamic module
+
+ m_assemblyData.CheckNameConflict(name);
+ m_assemblyData.CheckFileNameConflict(fileName);
+
+ int tkFile;
+ InternalModuleBuilder internalDynModule = (InternalModuleBuilder)DefineDynamicModule(
+ InternalAssembly,
+ emitSymbolInfo,
+ name,
+ fileName,
+ ref stackMark,
+ ref pInternalSymWriter,
+ false /*fIsTransient*/,
+ out tkFile);
+ dynModule = new ModuleBuilder(this, internalDynModule);
+
+ // initialize the dynamic module's managed side information
+ dynModule.Init(name, fileName, tkFile);
+
+ // Create the symbol writer
+ if (emitSymbolInfo)
+ {
+ // create the default SymWriter
+ Assembly assem = LoadISymWrapper();
+ Type symWriter = assem.GetType("System.Diagnostics.SymbolStore.SymWriter", true, false);
+ if (symWriter != null && !symWriter.IsVisible)
+ symWriter = null;
+
+ if (symWriter == null)
+ {
+ // cannot find SymWriter - throw TypeLoadException since we couldnt find the type.
+ throw new TypeLoadException(Environment.GetResourceString("MissingType", "SymWriter"));
+ }
+ try
+ {
+ (new PermissionSet(PermissionState.Unrestricted)).Assert();
+ writer = (ISymbolWriter)Activator.CreateInstance(symWriter);
+
+ // Set the underlying writer for the managed writer
+ // that we're using. Note that this function requires
+ // unmanaged code access.
+ writer.SetUnderlyingWriter(pInternalSymWriter);
+ }
+ finally
+ {
+ CodeAccessPermission.RevertAssert();
+ }
+ }
+
+ dynModule.SetSymWriter(writer);
+
+ m_assemblyData.AddModule(dynModule);
+
+ return dynModule;
+ } // DefineDynamicModuleInternalNoLock
+#endif // !FEATURE_CORECLR
+ #endregion
+
+ private Assembly LoadISymWrapper()
+ {
+ if (m_assemblyData.m_ISymWrapperAssembly != null)
+ return m_assemblyData.m_ISymWrapperAssembly;
+
+ Assembly assem = Assembly.Load("ISymWrapper, Version=" + ThisAssembly.Version +
+ ", Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken);
+
+ m_assemblyData.m_ISymWrapperAssembly = assem;
+ return assem;
+ }
+
+ internal void CheckContext(params Type[][] typess)
+ {
+ if (typess == null)
+ return;
+
+ foreach(Type[] types in typess)
+ if (types != null)
+ CheckContext(types);
+ }
+
+ internal void CheckContext(params Type[] types)
+ {
+ if (types == null)
+ return;
+
+ foreach (Type type in types)
+ {
+ if (type == null)
+ continue;
+
+ if (type.Module == null || type.Module.Assembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotValid"));
+
+ if (type.Module.Assembly == typeof(object).Module.Assembly)
+ continue;
+
+ if (type.Module.Assembly.ReflectionOnly && !ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("Arugment_EmitMixedContext1", type.AssemblyQualifiedName));
+
+ if (!type.Module.Assembly.ReflectionOnly && ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("Arugment_EmitMixedContext2", type.AssemblyQualifiedName));
+ }
+ }
+
+#if !FEATURE_CORECLR
+ /**********************************************
+ *
+ * Define stand alone managed resource for Assembly
+ *
+ **********************************************/
+ public IResourceWriter DefineResource(
+ String name,
+ String description,
+ String fileName)
+ {
+ return DefineResource(name, description, fileName, ResourceAttributes.Public);
+ }
+
+ /**********************************************
+ *
+ * Define stand alone managed resource for Assembly
+ *
+ **********************************************/
+ public IResourceWriter DefineResource(
+ String name,
+ String description,
+ String fileName,
+ ResourceAttributes attribute)
+ {
+ lock(SyncRoot)
+ {
+ return DefineResourceNoLock(name, description, fileName, attribute);
+ }
+ }
+
+ private IResourceWriter DefineResourceNoLock(
+ String name,
+ String description,
+ String fileName,
+ ResourceAttributes attribute)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name);
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ if (fileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "fileName");
+ if (!String.Equals(fileName, Path.GetFileName(fileName)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.DefineResource( " + name + ", " + fileName + ")");
+
+ m_assemblyData.CheckResNameConflict(name);
+ m_assemblyData.CheckFileNameConflict(fileName);
+
+ ResourceWriter resWriter;
+ String fullFileName;
+
+ if (m_assemblyData.m_strDir == null)
+ {
+ // If assembly directory is null, use current directory
+ fullFileName = Path.Combine(Directory.GetCurrentDirectory(), fileName);
+ resWriter = new ResourceWriter(fullFileName);
+ }
+ else
+ {
+ // Form the full path given the directory provided by user
+ fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName);
+ resWriter = new ResourceWriter(fullFileName);
+ }
+ // get the full path
+ fullFileName = Path.GetFullPath(fullFileName);
+
+ // retrieve just the file name
+ fileName = Path.GetFileName(fullFileName);
+
+ m_assemblyData.AddResWriter( new ResWriterData( resWriter, null, name, fileName, fullFileName, attribute) );
+ return resWriter;
+ }
+
+#endif // !FEATURE_CORECLR
+
+ /**********************************************
+ *
+ * Add an existing resource file to the Assembly
+ *
+ **********************************************/
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void AddResourceFile(
+ String name,
+ String fileName)
+ {
+ AddResourceFile(name, fileName, ResourceAttributes.Public);
+ }
+
+ /**********************************************
+ *
+ * Add an existing resource file to the Assembly
+ *
+ **********************************************/
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void AddResourceFile(
+ String name,
+ String fileName,
+ ResourceAttributes attribute)
+ {
+ lock(SyncRoot)
+ {
+ AddResourceFileNoLock(name, fileName, attribute);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void AddResourceFileNoLock(
+ String name,
+ String fileName,
+ ResourceAttributes attribute)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), name);
+ if (fileName == null)
+ throw new ArgumentNullException("fileName");
+ if (fileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), fileName);
+ if (!String.Equals(fileName, Path.GetFileName(fileName)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "fileName");
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.AddResourceFile( " + name + ", " + fileName + ")");
+
+ m_assemblyData.CheckResNameConflict(name);
+ m_assemblyData.CheckFileNameConflict(fileName);
+
+ String fullFileName;
+
+ if (m_assemblyData.m_strDir == null)
+ {
+ // If assembly directory is null, use current directory
+ fullFileName = Path.Combine(Directory.GetCurrentDirectory(), fileName);
+ }
+ else
+ {
+ // Form the full path given the directory provided by user
+ fullFileName = Path.Combine(m_assemblyData.m_strDir, fileName);
+ }
+
+ // get the full path
+ fullFileName = Path.UnsafeGetFullPath(fullFileName);
+
+ // retrieve just the file name
+ fileName = Path.GetFileName(fullFileName);
+
+ if (File.UnsafeExists(fullFileName) == false)
+ throw new FileNotFoundException(Environment.GetResourceString(
+ "IO.FileNotFound_FileName",
+ fileName), fileName);
+ m_assemblyData.AddResWriter( new ResWriterData( null, null, name, fileName, fullFileName, attribute) );
+ }
+
+ #region object overrides
+ public override bool Equals(object obj)
+ {
+ return InternalAssembly.Equals(obj);
+ }
+ // Need a dummy GetHashCode to pair with Equals
+ public override int GetHashCode() { return InternalAssembly.GetHashCode(); }
+ #endregion
+
+ #region ICustomAttributeProvider Members
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return InternalAssembly.GetCustomAttributes(inherit);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return InternalAssembly.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return InternalAssembly.IsDefined(attributeType, inherit);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return InternalAssembly.GetCustomAttributesData();
+ }
+ #endregion
+
+ #region Assembly overrides
+ // Returns the names of all the resources
+ public override String[] GetManifestResourceNames()
+ {
+ return InternalAssembly.GetManifestResourceNames();
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override FileStream GetFile(String name)
+ {
+ return InternalAssembly.GetFile(name);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override FileStream[] GetFiles(bool getResourceModules)
+ {
+ return InternalAssembly.GetFiles(getResourceModules);
+ }
+
+ public override Stream GetManifestResourceStream(Type type, String name)
+ {
+ return InternalAssembly.GetManifestResourceStream(type, name);
+ }
+
+ public override Stream GetManifestResourceStream(String name)
+ {
+ return InternalAssembly.GetManifestResourceStream(name);
+ }
+
+ public override ManifestResourceInfo GetManifestResourceInfo(String resourceName)
+ {
+ return InternalAssembly.GetManifestResourceInfo(resourceName);
+ }
+
+ public override String Location
+ {
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ get
+ {
+ return InternalAssembly.Location;
+ }
+ }
+
+ public override String ImageRuntimeVersion
+ {
+ get
+ {
+ return InternalAssembly.ImageRuntimeVersion;
+ }
+ }
+
+ public override String CodeBase
+ {
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ get
+ {
+ return InternalAssembly.CodeBase;
+ }
+ }
+
+ // Override the EntryPoint method on Assembly.
+ // This doesn't need to be synchronized because it is simple enough
+ public override MethodInfo EntryPoint
+ {
+ get
+ {
+ return m_assemblyData.m_entryPointMethod;
+ }
+ }
+
+ // Get an array of all the public types defined in this assembly
+ public override Type[] GetExportedTypes()
+ {
+ return InternalAssembly.GetExportedTypes();
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public override AssemblyName GetName(bool copiedName)
+ {
+ return InternalAssembly.GetName(copiedName);
+ }
+
+ public override String FullName
+ {
+ get
+ {
+ return InternalAssembly.FullName;
+ }
+ }
+
+ public override Type GetType(String name, bool throwOnError, bool ignoreCase)
+ {
+ return InternalAssembly.GetType(name, throwOnError, ignoreCase);
+ }
+
+#if FEATURE_CAS_POLICY
+ public override Evidence Evidence
+ {
+ get
+ {
+ return InternalAssembly.Evidence;
+ }
+ }
+
+ public override PermissionSet PermissionSet
+ {
+ [SecurityCritical]
+ get
+ {
+ return InternalAssembly.PermissionSet;
+ }
+ }
+
+ public override SecurityRuleSet SecurityRuleSet
+ {
+ get
+ {
+ return InternalAssembly.SecurityRuleSet;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public override Module ManifestModule
+ {
+ get
+ {
+ return m_manifestModuleBuilder.InternalModule;
+ }
+ }
+
+ public override bool ReflectionOnly
+ {
+ get
+ {
+ return InternalAssembly.ReflectionOnly;
+ }
+ }
+
+ public override Module GetModule(String name)
+ {
+ return InternalAssembly.GetModule(name);
+ }
+
+ public override AssemblyName[] GetReferencedAssemblies()
+ {
+ return InternalAssembly.GetReferencedAssemblies();
+ }
+
+ public override bool GlobalAssemblyCache
+ {
+ get
+ {
+ return InternalAssembly.GlobalAssemblyCache;
+ }
+ }
+
+ public override Int64 HostContext
+ {
+ get
+ {
+ return InternalAssembly.HostContext;
+ }
+ }
+
+ public override Module[] GetModules(bool getResourceModules)
+ {
+ return InternalAssembly.GetModules(getResourceModules);
+ }
+
+ public override Module[] GetLoadedModules(bool getResourceModules)
+ {
+ return InternalAssembly.GetLoadedModules(getResourceModules);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Assembly GetSatelliteAssembly(CultureInfo culture)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalAssembly.InternalGetSatelliteAssembly(culture, null, ref stackMark);
+ }
+
+ // Useful for binding to a very specific version of a satellite assembly
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version version)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalAssembly.InternalGetSatelliteAssembly(culture, version, ref stackMark);
+ }
+
+ public override bool IsDynamic
+ {
+ get {
+ return true;
+ }
+ }
+ #endregion
+
+
+ /**********************************************
+ *
+ * Add an unmanaged Version resource to the
+ * assembly
+ *
+ **********************************************/
+ public void DefineVersionInfoResource(
+ String product,
+ String productVersion,
+ String company,
+ String copyright,
+ String trademark)
+ {
+ lock(SyncRoot)
+ {
+ DefineVersionInfoResourceNoLock(
+ product,
+ productVersion,
+ company,
+ copyright,
+ trademark);
+ }
+ }
+
+ private void DefineVersionInfoResourceNoLock(
+ String product,
+ String productVersion,
+ String company,
+ String copyright,
+ String trademark)
+ {
+ if (m_assemblyData.m_strResourceFileName != null ||
+ m_assemblyData.m_resourceBytes != null ||
+ m_assemblyData.m_nativeVersion != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ m_assemblyData.m_nativeVersion = new NativeVersionInfo();
+
+ m_assemblyData.m_nativeVersion.m_strCopyright = copyright;
+ m_assemblyData.m_nativeVersion.m_strTrademark = trademark;
+ m_assemblyData.m_nativeVersion.m_strCompany = company;
+ m_assemblyData.m_nativeVersion.m_strProduct = product;
+ m_assemblyData.m_nativeVersion.m_strProductVersion = productVersion;
+ m_assemblyData.m_hasUnmanagedVersionInfo = true;
+ m_assemblyData.m_OverrideUnmanagedVersionInfo = true;
+
+ }
+
+ public void DefineVersionInfoResource()
+ {
+ lock(SyncRoot)
+ {
+ DefineVersionInfoResourceNoLock();
+ }
+ }
+
+ private void DefineVersionInfoResourceNoLock()
+ {
+ if (m_assemblyData.m_strResourceFileName != null ||
+ m_assemblyData.m_resourceBytes != null ||
+ m_assemblyData.m_nativeVersion != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ m_assemblyData.m_hasUnmanagedVersionInfo = true;
+ m_assemblyData.m_nativeVersion = new NativeVersionInfo();
+ }
+
+ public void DefineUnmanagedResource(Byte[] resource)
+ {
+ if (resource == null)
+ throw new ArgumentNullException("resource");
+ Contract.EndContractBlock();
+
+ lock(SyncRoot)
+ {
+ DefineUnmanagedResourceNoLock(resource);
+ }
+ }
+
+ private void DefineUnmanagedResourceNoLock(Byte[] resource)
+ {
+ if (m_assemblyData.m_strResourceFileName != null ||
+ m_assemblyData.m_resourceBytes != null ||
+ m_assemblyData.m_nativeVersion != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ m_assemblyData.m_resourceBytes = new byte[resource.Length];
+ Buffer.BlockCopy(resource, 0, m_assemblyData.m_resourceBytes, 0, resource.Length);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DefineUnmanagedResource(String resourceFileName)
+ {
+ if (resourceFileName == null)
+ throw new ArgumentNullException("resourceFileName");
+ Contract.EndContractBlock();
+
+ lock(SyncRoot)
+ {
+ DefineUnmanagedResourceNoLock(resourceFileName);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void DefineUnmanagedResourceNoLock(String resourceFileName)
+ {
+ if (m_assemblyData.m_strResourceFileName != null ||
+ m_assemblyData.m_resourceBytes != null ||
+ m_assemblyData.m_nativeVersion != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ // Check caller has the right to read the file.
+ string strFullFileName;
+ if (m_assemblyData.m_strDir == null)
+ {
+ // If assembly directory is null, use current directory
+ strFullFileName = Path.Combine(Directory.GetCurrentDirectory(), resourceFileName);
+ }
+ else
+ {
+ // Form the full path given the directory provided by user
+ strFullFileName = Path.Combine(m_assemblyData.m_strDir, resourceFileName);
+ }
+ strFullFileName = Path.GetFullPath(resourceFileName);
+ new FileIOPermission(FileIOPermissionAccess.Read, strFullFileName).Demand();
+
+ if (File.Exists(strFullFileName) == false)
+ throw new FileNotFoundException(Environment.GetResourceString(
+ "IO.FileNotFound_FileName",
+ resourceFileName), resourceFileName);
+ m_assemblyData.m_strResourceFileName = strFullFileName;
+ }
+
+
+
+ /**********************************************
+ *
+ * return a dynamic module with the specified name.
+ *
+ **********************************************/
+ public ModuleBuilder GetDynamicModule(
+ String name) // the name of module for the look up
+ {
+ lock(SyncRoot)
+ {
+ return GetDynamicModuleNoLock(name);
+ }
+ }
+
+ private ModuleBuilder GetDynamicModuleNoLock(
+ String name) // the name of module for the look up
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.GetDynamicModule( " + name + " )");
+ int size = m_assemblyData.m_moduleBuilderList.Count;
+ for (int i = 0; i < size; i++)
+ {
+ ModuleBuilder moduleBuilder = (ModuleBuilder) m_assemblyData.m_moduleBuilderList[i];
+ if (moduleBuilder.m_moduleData.m_strModuleName.Equals(name))
+ {
+ return moduleBuilder;
+ }
+ }
+ return null;
+ }
+
+ /**********************************************
+ *
+ * Setting the entry point if the assembly builder is building
+ * an exe.
+ *
+ **********************************************/
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void SetEntryPoint(
+ MethodInfo entryMethod)
+ {
+ SetEntryPoint(entryMethod, PEFileKinds.ConsoleApplication);
+ }
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void SetEntryPoint(
+ MethodInfo entryMethod, // entry method for the assembly. We use this to determine the entry module
+ PEFileKinds fileKind) // file kind for the assembly.
+ {
+ lock(SyncRoot)
+ {
+ SetEntryPointNoLock(entryMethod, fileKind);
+ }
+ }
+
+ private void SetEntryPointNoLock(
+ MethodInfo entryMethod, // entry method for the assembly. We use this to determine the entry module
+ PEFileKinds fileKind) // file kind for the assembly.
+ {
+
+ if (entryMethod == null)
+ throw new ArgumentNullException("entryMethod");
+ Contract.EndContractBlock();
+
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: AssemblyBuilder.SetEntryPoint");
+
+ Module tmpModule = entryMethod.Module;
+ if (tmpModule == null || !InternalAssembly.Equals(tmpModule.Assembly))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EntryMethodNotDefinedInAssembly"));
+
+ m_assemblyData.m_entryPointMethod = entryMethod;
+ m_assemblyData.m_peFileKind = fileKind;
+
+#if !FEATURE_CORECLR
+ // Setting the entry point
+ ModuleBuilder tmpMB = tmpModule as ModuleBuilder;
+ if (tmpMB != null)
+ m_assemblyData.m_entryPointModule = tmpMB;
+ else
+ m_assemblyData.m_entryPointModule = GetModuleBuilder((InternalModuleBuilder)tmpModule);
+
+ MethodToken entryMethodToken = m_assemblyData.m_entryPointModule.GetMethodToken(entryMethod);
+ m_assemblyData.m_entryPointModule.SetEntryPoint(entryMethodToken);
+#endif //!FEATURE_CORECLR
+ }
+
+
+ /**********************************************
+ * Use this function if client decides to form the custom attribute blob themselves
+ **********************************************/
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ lock(SyncRoot)
+ {
+ SetCustomAttributeNoLock(con, binaryAttribute);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetCustomAttributeNoLock(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ TypeBuilder.DefineCustomAttribute(
+ m_manifestModuleBuilder, // pass in the in-memory assembly module
+ AssemblyBuilderData.m_tkAssembly, // This is the AssemblyDef token
+ m_manifestModuleBuilder.GetConstructorToken(con).Token,
+ binaryAttribute,
+ false,
+ typeof(System.Diagnostics.DebuggableAttribute) == con.DeclaringType);
+
+ // Track the CA for persistence
+ if (m_assemblyData.m_access != AssemblyBuilderAccess.Run)
+ {
+ // tracking the CAs for persistence
+ m_assemblyData.AddCustomAttribute(con, binaryAttribute);
+ }
+ }
+
+ /**********************************************
+ * Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
+ **********************************************/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ {
+ throw new ArgumentNullException("customBuilder");
+ }
+ Contract.EndContractBlock();
+
+ lock(SyncRoot)
+ {
+ SetCustomAttributeNoLock(customBuilder);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetCustomAttributeNoLock(CustomAttributeBuilder customBuilder)
+ {
+ customBuilder.CreateCustomAttribute(
+ m_manifestModuleBuilder,
+ AssemblyBuilderData.m_tkAssembly); // This is the AssemblyDef token
+
+ // Track the CA for persistence
+ if (m_assemblyData.m_access != AssemblyBuilderAccess.Run)
+ {
+ m_assemblyData.AddCustomAttribute(customBuilder);
+ }
+ }
+
+
+ /**********************************************
+ *
+ * Saves the assembly to disk. Also saves all dynamic modules defined
+ * in this dynamic assembly. Assembly file name can be the same as one of
+ * the module's name. If so, assembly info is stored within that module.
+ * Assembly file name can be different from all of the modules underneath. In
+ * this case, assembly is stored stand alone.
+ *
+ **********************************************/
+
+ public void Save(String assemblyFileName) // assembly file name
+ {
+ Save(assemblyFileName, System.Reflection.PortableExecutableKinds.ILOnly, System.Reflection.ImageFileMachine.I386);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Save(String assemblyFileName,
+ PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ lock(SyncRoot)
+ {
+ SaveNoLock(assemblyFileName, portableExecutableKind, imageFileMachine);
+ }
+ }
+
+#if FEATURE_CORECLR
+ private void SaveNoLock(String assemblyFileName,
+ PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ // AssemblyBuilderAccess.Save can never be set with FEATURE_CORECLR
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CantSaveTransientAssembly"));
+ }
+#else // FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ private void SaveNoLock(String assemblyFileName,
+ PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ if (assemblyFileName == null)
+ throw new ArgumentNullException("assemblyFileName");
+ if (assemblyFileName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "assemblyFileName");
+ if (!String.Equals(assemblyFileName, Path.GetFileName(assemblyFileName)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotSimpleFileName"), "assemblyFileName");
+ Contract.EndContractBlock();
+
+ int i;
+ int size;
+ Type type;
+ TypeBuilder typeBuilder;
+ ModuleBuilder modBuilder;
+ String strModFileName;
+ ModuleBuilder assemblyModule;
+ ResWriterData tempRes;
+ int[] tkAttrs = null;
+ int[] tkAttrs2 = null;
+ ModuleBuilder onDiskAssemblyModule;
+
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilder.Save( " + assemblyFileName + " )");
+
+ String tmpVersionFile = null;
+
+ try
+ {
+ if (m_assemblyData.m_iCABuilder != 0)
+ tkAttrs = new int[m_assemblyData.m_iCABuilder];
+ if ( m_assemblyData.m_iCAs != 0)
+ tkAttrs2 = new int[m_assemblyData.m_iCAs];
+
+ if (m_assemblyData.m_isSaved == true)
+ {
+ // assembly has been saved before!
+ throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_AssemblyHasBeenSaved,
+ InternalAssembly.GetSimpleName()));
+ }
+
+ if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) != AssemblyBuilderAccess.Save)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CantSaveTransientAssembly"));
+ }
+
+ // Check if assembly info is supposed to be stored with one of the module files.
+ assemblyModule = m_assemblyData.FindModuleWithFileName(assemblyFileName);
+
+ if (assemblyModule != null)
+ {
+ m_onDiskAssemblyModuleBuilder = assemblyModule;
+
+ // In memory this module is not the manifest module and has a valid file token
+ // On disk it will be the manifest module so lets clean the file token
+ // We should not retrieve FileToken after the assembly has been saved
+ // If that is absolutely necessary, we need two separate fields on ModuleBuilderData:
+ // the in memory file token and the on disk file token.
+ assemblyModule.m_moduleData.FileToken = 0;
+ }
+ else
+ { // If assembly is to be stored alone, then no file name should conflict with it.
+ // This check will ensure resource file names are different assembly file name.
+ m_assemblyData.CheckFileNameConflict(assemblyFileName);
+ }
+
+ if (m_assemblyData.m_strDir == null)
+ {
+ // set it to current directory
+ m_assemblyData.m_strDir = Directory.GetCurrentDirectory();
+ }
+ else if (Directory.Exists(m_assemblyData.m_strDir) == false)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectory",
+ m_assemblyData.m_strDir));
+ }
+
+ // after this point, assemblyFileName is the full path name.
+ assemblyFileName = Path.Combine(m_assemblyData.m_strDir, assemblyFileName);
+ assemblyFileName = Path.GetFullPath(assemblyFileName);
+
+ // Check caller has the right to create the assembly file itself.
+ new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, assemblyFileName).Demand();
+
+ // 1. setup/create the IMetaDataAssemblyEmit for the on disk version
+ if (assemblyModule != null)
+ {
+ // prepare saving CAs on assembly def. We need to introduce the MemberRef for
+ // the CA's type first of all. This is for the case the we have embedded manifest.
+ // We need to introduce these MRs before we call PreSave where we will snap
+ // into a ondisk metadata. If we do it after this, the ondisk metadata will
+ // not contain the proper MRs.
+ //
+ for (i=0; i < m_assemblyData.m_iCABuilder; i++)
+ {
+ tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk(
+ assemblyModule);
+ }
+ for (i=0; i < m_assemblyData.m_iCAs; i++)
+ {
+ tkAttrs2[i] = assemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token;
+ }
+ assemblyModule.PreSave(assemblyFileName, portableExecutableKind, imageFileMachine);
+ }
+
+ RuntimeModule runtimeAssemblyModule = (assemblyModule != null) ? assemblyModule.ModuleHandle.GetRuntimeModule() : null;
+ PrepareForSavingManifestToDisk(GetNativeHandle(), runtimeAssemblyModule);
+
+ // This function will return the embedded manifest module, an already exposed ModuleBuilder
+ // created by user, or make the stand alone manifest module exposed through managed code.
+ //
+ onDiskAssemblyModule = GetOnDiskAssemblyModuleBuilder();
+
+ // Set any native resources on the OnDiskAssemblyModule.
+ if (m_assemblyData.m_strResourceFileName != null)
+ onDiskAssemblyModule.DefineUnmanagedResourceFileInternalNoLock(m_assemblyData.m_strResourceFileName);
+ else if (m_assemblyData.m_resourceBytes != null)
+ onDiskAssemblyModule.DefineUnmanagedResourceInternalNoLock(m_assemblyData.m_resourceBytes);
+ else if (m_assemblyData.m_hasUnmanagedVersionInfo == true)
+ {
+ // calculate unmanaged version info from assembly's custom attributes
+ m_assemblyData.FillUnmanagedVersionInfo();
+
+ String strFileVersion = m_assemblyData.m_nativeVersion.m_strFileVersion;
+ if (strFileVersion == null)
+ strFileVersion = GetVersion().ToString();
+
+ // Create the file.
+ CreateVersionInfoResource(
+ assemblyFileName,
+ m_assemblyData.m_nativeVersion.m_strTitle, // title
+ null, // Icon filename
+ m_assemblyData.m_nativeVersion.m_strDescription, // description
+ m_assemblyData.m_nativeVersion.m_strCopyright,
+ m_assemblyData.m_nativeVersion.m_strTrademark,
+ m_assemblyData.m_nativeVersion.m_strCompany,
+ m_assemblyData.m_nativeVersion.m_strProduct,
+ m_assemblyData.m_nativeVersion.m_strProductVersion,
+ strFileVersion,
+ m_assemblyData.m_nativeVersion.m_lcid,
+ m_assemblyData.m_peFileKind == PEFileKinds.Dll,
+ JitHelpers.GetStringHandleOnStack(ref tmpVersionFile));
+
+ onDiskAssemblyModule.DefineUnmanagedResourceFileInternalNoLock(tmpVersionFile);
+ }
+
+ if (assemblyModule == null)
+ {
+
+ // This is for introducing the MRs for CA's type. This case is for stand alone
+ // manifest. We need to wait till PrepareForSavingManifestToDisk is called.
+ // That will trigger the creation of the on-disk stand alone manifest module.
+ //
+ for (i=0; i < m_assemblyData.m_iCABuilder; i++)
+ {
+ tkAttrs[i] = m_assemblyData.m_CABuilders[i].PrepareCreateCustomAttributeToDisk(
+ onDiskAssemblyModule);
+ }
+ for (i=0; i < m_assemblyData.m_iCAs; i++)
+ {
+ tkAttrs2[i] = onDiskAssemblyModule.InternalGetConstructorToken(m_assemblyData.m_CACons[i], true).Token;
+ }
+ }
+
+ // 2. save all of the persistable modules contained by this AssemblyBuilder except the module that is going to contain
+ // Assembly information
+ //
+ // 3. create the file list in the manifest and track the file token. If it is embedded assembly,
+ // the assembly file should not be on the file list.
+ //
+ size = m_assemblyData.m_moduleBuilderList.Count;
+ for (i = 0; i < size; i++)
+ {
+ ModuleBuilder mBuilder = (ModuleBuilder) m_assemblyData.m_moduleBuilderList[i];
+ if (mBuilder.IsTransient() == false && mBuilder != assemblyModule)
+ {
+ strModFileName = mBuilder.m_moduleData.m_strFileName;
+ if (m_assemblyData.m_strDir != null)
+ {
+ strModFileName = Path.Combine(m_assemblyData.m_strDir, strModFileName);
+ strModFileName = Path.GetFullPath(strModFileName);
+ }
+
+ // Check caller has the right to create the Module file itself.
+ new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, strModFileName).Demand();
+
+ mBuilder.m_moduleData.FileToken = AddFile(GetNativeHandle(), mBuilder.m_moduleData.m_strFileName);
+ mBuilder.PreSave(strModFileName, portableExecutableKind, imageFileMachine);
+ mBuilder.Save(strModFileName, false, portableExecutableKind, imageFileMachine);
+
+ // Cannot set the hash value when creating the file since the file token
+ // is needed to created the entries for the embedded resources in the
+ // module and the resources need to be there before you figure the hash.
+ SetFileHashValue(GetNativeHandle(), mBuilder.m_moduleData.FileToken, strModFileName);
+ }
+ }
+
+ // 4. Add the public ComType
+ for (i=0; i < m_assemblyData.m_iPublicComTypeCount; i++)
+ {
+ type = m_assemblyData.m_publicComTypeList[i];
+ // If the type that was added as a Public Com Type was obtained via Reflection,
+ // it will be a System.RuntimeType, even if it was really, at the same time,
+ // a TypeBuilder. Unfortunately, you can't get back to the TypeBuilder, so
+ // this code has to deal with either-or.
+ if (type is RuntimeType)
+ {
+ // If type is a runtime type, it must be a baked TypeBuilder,
+ // ttype.Module should be an InternalModuleBuilder
+
+ InternalModuleBuilder internalMB = (InternalModuleBuilder)type.Module;
+ modBuilder = this.GetModuleBuilder(internalMB);
+ if (modBuilder != assemblyModule)
+ DefineNestedComType(type, modBuilder.m_moduleData.FileToken, type.MetadataToken);
+ }
+ else
+ {
+ // Could assert that "type" is a TypeBuilder, but next statement throws if it isn't.
+ typeBuilder = (TypeBuilder) type;
+ // If type is a TypeBuilder, type.Module must be a ModuleBuilder.
+ modBuilder = typeBuilder.GetModuleBuilder();
+ if (modBuilder != assemblyModule)
+ DefineNestedComType(type, modBuilder.m_moduleData.FileToken, typeBuilder.MetadataTokenInternal);
+ }
+ }
+
+ // 5. write AssemblyDef's CAs (only if we are not saving directly the manifest module itself)
+ if (onDiskAssemblyModule != m_manifestModuleBuilder)
+ {
+ for (i = 0; i < m_assemblyData.m_iCABuilder; i++)
+ {
+ m_assemblyData.m_CABuilders[i].CreateCustomAttribute(
+ onDiskAssemblyModule,
+ AssemblyBuilderData.m_tkAssembly, // This is the AssemblyDef token
+ tkAttrs[i], true);
+ }
+
+ for (i = 0; i < m_assemblyData.m_iCAs; i++)
+ {
+ TypeBuilder.DefineCustomAttribute(
+ onDiskAssemblyModule, // pass in the in-memory assembly module
+ AssemblyBuilderData.m_tkAssembly, // This is the AssemblyDef token
+ tkAttrs2[i],
+ m_assemblyData.m_CABytes[i],
+ true, false);
+ }
+ }
+
+ // 6. write security permission requests to the manifest.
+#pragma warning disable 618
+ if (m_assemblyData.m_RequiredPset != null)
+ AddDeclarativeSecurity(m_assemblyData.m_RequiredPset, SecurityAction.RequestMinimum);
+
+ if (m_assemblyData.m_RefusedPset != null)
+ AddDeclarativeSecurity(m_assemblyData.m_RefusedPset, SecurityAction.RequestRefuse);
+
+ if (m_assemblyData.m_OptionalPset != null)
+ AddDeclarativeSecurity(m_assemblyData.m_OptionalPset, SecurityAction.RequestOptional);
+#pragma warning restore 618
+
+ // 7. Save the stand alone managed resources
+ size = m_assemblyData.m_resWriterList.Count;
+ for (i = 0; i < size; i++)
+ {
+ tempRes = null;
+
+ try
+ {
+ tempRes = (ResWriterData)m_assemblyData.m_resWriterList[i];
+
+ // If the user added an existing resource to the manifest, the
+ // corresponding ResourceWriter will be null.
+ if (tempRes.m_resWriter != null)
+ // Check caller has the right to create the Resource file itself.
+ new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Append, tempRes.m_strFullFileName).Demand();
+ }
+ finally
+ {
+ if (tempRes != null && tempRes.m_resWriter != null)
+ tempRes.m_resWriter.Close();
+ }
+
+ // Add entry to manifest for this stand alone resource
+ AddStandAloneResource(GetNativeHandle(), tempRes.m_strName, tempRes.m_strFileName, tempRes.m_strFullFileName, (int)tempRes.m_attribute);
+ }
+
+ // Save now!!
+ if (assemblyModule == null)
+ {
+ onDiskAssemblyModule.DefineNativeResource(portableExecutableKind, imageFileMachine);
+
+ // Stand alone manifest
+ int entryPoint = (m_assemblyData.m_entryPointModule != null) ? m_assemblyData.m_entryPointModule.m_moduleData.FileToken : 0;
+
+ SaveManifestToDisk(GetNativeHandle(), assemblyFileName, entryPoint, (int)m_assemblyData.m_peFileKind,
+ (int)portableExecutableKind, (int)imageFileMachine);
+ }
+ else
+ {
+ // embedded manifest
+
+ // If the module containing the entry point is not the manifest file, we need to
+ // let the manifest file point to the module which contains the entry point.
+ //
+ //
+ //
+ //
+ if (m_assemblyData.m_entryPointModule != null && m_assemblyData.m_entryPointModule != assemblyModule)
+ assemblyModule.SetEntryPoint(new MethodToken(m_assemblyData.m_entryPointModule.m_moduleData.FileToken));
+ assemblyModule.Save(assemblyFileName, true, portableExecutableKind, imageFileMachine);
+ }
+ m_assemblyData.m_isSaved = true;
+ }
+ finally
+ {
+ if (tmpVersionFile != null)
+ {
+ // Delete file.
+ System.IO.File.Delete(tmpVersionFile);
+ }
+ }
+ }
+#endif // FEATURE_CORECLR
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddDeclarativeSecurity(PermissionSet pset, SecurityAction action)
+ {
+ // Translate sets into internal encoding (uses standard binary serialization).
+ byte[] blob = pset.EncodeXml();
+ AddDeclarativeSecurity(GetNativeHandle(), action, blob, blob.Length);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ internal bool IsPersistable()
+ {
+#if !FEATURE_CORECLR // AssemblyBuilderAccess.Save is never set in CoreCLR
+ if ((m_assemblyData.m_access & AssemblyBuilderAccess.Save) == AssemblyBuilderAccess.Save)
+ {
+ return true;
+ }
+ else
+#endif // FEATURE_CORECLR
+ {
+ return false;
+ }
+ }
+
+ /**********************************************
+ *
+ * Internal helper to walk the nested type hierachy
+ *
+ **********************************************/
+ [System.Security.SecurityCritical] // auto-generated
+ private int DefineNestedComType(Type type, int tkResolutionScope, int tkTypeDef)
+ {
+ Type enclosingType = type.DeclaringType;
+ if (enclosingType == null)
+ {
+ // Use full type name for non-nested types.
+ return AddExportedTypeOnDisk(GetNativeHandle(), type.FullName, tkResolutionScope, tkTypeDef, type.Attributes);
+ }
+
+ tkResolutionScope = DefineNestedComType(enclosingType, tkResolutionScope, tkTypeDef);
+ // Use simple name for nested types.
+ return AddExportedTypeOnDisk(GetNativeHandle(), type.Name, tkResolutionScope, tkTypeDef, type.Attributes);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int DefineExportedTypeInMemory(Type type, int tkResolutionScope, int tkTypeDef)
+ {
+ Type enclosingType = type.DeclaringType;
+ if (enclosingType == null)
+ {
+ // Use full type name for non-nested types.
+ return AddExportedTypeInMemory(GetNativeHandle(), type.FullName, tkResolutionScope, tkTypeDef, type.Attributes);
+ }
+
+ tkResolutionScope = DefineExportedTypeInMemory(enclosingType, tkResolutionScope, tkTypeDef);
+ // Use simple name for nested types.
+ return AddExportedTypeInMemory(GetNativeHandle(), type.Name, tkResolutionScope, tkTypeDef, type.Attributes);
+ }
+
+ /**********************************************
+ *
+ * Private methods
+ *
+ **********************************************/
+
+ /**********************************************
+ * Make a private constructor so these cannot be constructed externally.
+ * @internonly
+ **********************************************/
+ private AssemblyBuilder() {}
+
+#if !FEATURE_CORECLR
+ void _AssemblyBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AssemblyBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _AssemblyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _AssemblyBuilder.Invoke in VM\DangerousAPIs.h and
+ // include _AssemblyBuilder in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _AssemblyBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ // Create a new module in which to emit code. This module will not contain the manifest.
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void DefineDynamicModule(RuntimeAssembly containingAssembly,
+ bool emitSymbolInfo,
+ String name,
+ String filename,
+ StackCrawlMarkHandle stackMark,
+ ref IntPtr pInternalSymWriter,
+ ObjectHandleOnStack retModule,
+ bool fIsTransient,
+ out int tkFile);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static Module DefineDynamicModule(RuntimeAssembly containingAssembly,
+ bool emitSymbolInfo,
+ String name,
+ String filename,
+ ref StackCrawlMark stackMark,
+ ref IntPtr pInternalSymWriter,
+ bool fIsTransient,
+ out int tkFile)
+ {
+ RuntimeModule retModule = null;
+
+ DefineDynamicModule(containingAssembly.GetNativeHandle(),
+ emitSymbolInfo,
+ name,
+ filename,
+ JitHelpers.GetStackCrawlMarkHandle(ref stackMark),
+ ref pInternalSymWriter,
+ JitHelpers.GetObjectHandleOnStack(ref retModule),
+ fIsTransient,
+ out tkFile);
+
+ return retModule;
+ }
+
+ // The following functions are native helpers for creating on-disk manifest
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void PrepareForSavingManifestToDisk(RuntimeAssembly assembly, RuntimeModule assemblyModule); // module to contain assembly information if assembly is embedded
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void SaveManifestToDisk(RuntimeAssembly assembly,
+ String strFileName,
+ int entryPoint,
+ int fileKind,
+ int portableExecutableKind,
+ int ImageFileMachine);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern int AddFile(RuntimeAssembly assembly, String strFileName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void SetFileHashValue(RuntimeAssembly assembly,
+ int tkFile,
+ String strFullFileName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern int AddExportedTypeInMemory(RuntimeAssembly assembly,
+ String strComTypeName,
+ int tkAssemblyRef,
+ int tkTypeDef,
+ TypeAttributes flags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern int AddExportedTypeOnDisk(RuntimeAssembly assembly,
+ String strComTypeName,
+ int tkAssemblyRef,
+ int tkTypeDef,
+ TypeAttributes flags);
+
+ // Add an entry to assembly's manifestResource table for a stand alone resource.
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void AddStandAloneResource(RuntimeAssembly assembly,
+ String strName,
+ String strFileName,
+ String strFullFileName,
+ int attribute);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+#pragma warning disable 618
+ static private extern void AddDeclarativeSecurity(RuntimeAssembly assembly, SecurityAction action, byte[] blob, int length);
+#pragma warning restore 618
+
+ // Functions for defining unmanaged resources.
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void CreateVersionInfoResource(String filename, String title, String iconFilename, String description,
+ String copyright, String trademark, String company, String product,
+ String productVersion, String fileVersion, int lcid, bool isDll,
+ StringHandleOnStack retFileName);
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs
new file mode 100644
index 0000000000..00a961dd89
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderAccess.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+// This enumeration defines the access modes for a dynamic assembly.
+// EE uses these enum values..look for m_dwDynamicAssemblyAccess in Assembly.hpp
+
+namespace System.Reflection.Emit
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Flags]
+ public enum AssemblyBuilderAccess
+ {
+ Run = 1,
+#if !FEATURE_CORECLR // these are unsupported
+ Save = 2,
+ RunAndSave = Run | Save,
+#endif // !FEATURE_CORECLR
+#if FEATURE_REFLECTION_ONLY_LOAD
+ ReflectionOnly = 6, // 4 | Save,
+#endif // FEATURE_REFLECTION_ONLY_LOAD
+#if FEATURE_COLLECTIBLE_TYPES
+ RunAndCollect = 8 | Run
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs
new file mode 100644
index 0000000000..f1a38c611b
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/AssemblyBuilderData.cs
@@ -0,0 +1,583 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+
+namespace System.Reflection.Emit {
+ using System;
+ using IList = System.Collections.IList;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Security;
+ using System.Diagnostics;
+ using CultureInfo = System.Globalization.CultureInfo;
+#if !FEATURE_CORECLR
+ using ResourceWriter = System.Resources.ResourceWriter;
+#else // FEATURE_CORECLR
+ using IResourceWriter = System.Resources.IResourceWriter;
+#endif // !FEATURE_CORECLR
+ using System.IO;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.SymbolStore;
+ using System.Diagnostics.Contracts;
+
+ // This is a package private class. This class hold all of the managed
+ // data member for AssemblyBuilder. Note that what ever data members added to
+ // this class cannot be accessed from the EE.
+ internal class AssemblyBuilderData
+ {
+ [SecurityCritical]
+ internal AssemblyBuilderData(
+ InternalAssemblyBuilder assembly,
+ String strAssemblyName,
+ AssemblyBuilderAccess access,
+ String dir)
+ {
+ m_assembly = assembly;
+ m_strAssemblyName = strAssemblyName;
+ m_access = access;
+ m_moduleBuilderList = new List<ModuleBuilder>();
+ m_resWriterList = new List<ResWriterData>();
+
+ //Init to null/0 done for you by the CLR. FXCop has spoken
+
+ if (dir == null && access != AssemblyBuilderAccess.Run)
+ m_strDir = Environment.CurrentDirectory;
+ else
+ m_strDir = dir;
+
+ m_peFileKind = PEFileKinds.Dll;
+ }
+
+ // Helper to add a dynamic module into the tracking list
+ internal void AddModule(ModuleBuilder dynModule)
+ {
+ m_moduleBuilderList.Add(dynModule);
+ }
+
+ // Helper to add a resource information into the tracking list
+ internal void AddResWriter(ResWriterData resData)
+ {
+ m_resWriterList.Add(resData);
+ }
+
+
+ // Helper to track CAs to persist onto disk
+ internal void AddCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+
+ // make sure we have room for this CA
+ if (m_CABuilders == null)
+ {
+ m_CABuilders = new CustomAttributeBuilder[m_iInitialSize];
+ }
+ if (m_iCABuilder == m_CABuilders.Length)
+ {
+ CustomAttributeBuilder[] tempCABuilders = new CustomAttributeBuilder[m_iCABuilder * 2];
+ Array.Copy(m_CABuilders, 0, tempCABuilders, 0, m_iCABuilder);
+ m_CABuilders = tempCABuilders;
+ }
+ m_CABuilders[m_iCABuilder] = customBuilder;
+
+ m_iCABuilder++;
+ }
+
+ // Helper to track CAs to persist onto disk
+ internal void AddCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+
+ // make sure we have room for this CA
+ if (m_CABytes == null)
+ {
+ m_CABytes = new byte[m_iInitialSize][];
+ m_CACons = new ConstructorInfo[m_iInitialSize];
+ }
+ if (m_iCAs == m_CABytes.Length)
+ {
+ // enlarge the arrays
+ byte[][] temp = new byte[m_iCAs * 2][];
+ ConstructorInfo[] tempCon = new ConstructorInfo[m_iCAs * 2];
+ for (int i=0; i < m_iCAs; i++)
+ {
+ temp[i] = m_CABytes[i];
+ tempCon[i] = m_CACons[i];
+ }
+ m_CABytes = temp;
+ m_CACons = tempCon;
+ }
+
+ byte[] attrs = new byte[binaryAttribute.Length];
+ Buffer.BlockCopy(binaryAttribute, 0, attrs, 0, binaryAttribute.Length);
+ m_CABytes[m_iCAs] = attrs;
+ m_CACons[m_iCAs] = con;
+ m_iCAs++;
+ }
+
+ // Helper to calculate unmanaged version info from Assembly's custom attributes.
+ // If DefineUnmanagedVersionInfo is called, the parameter provided will override
+ // the CA's value.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ internal void FillUnmanagedVersionInfo()
+ {
+ // Get the lcid set on the assembly name as default if available
+ // Note that if LCID is not avaible from neither AssemblyName or AssemblyCultureAttribute,
+ // it is default to -1 which is treated as language neutral.
+ //
+ CultureInfo locale = m_assembly.GetLocale();
+#if FEATURE_USE_LCID
+ if (locale != null)
+ m_nativeVersion.m_lcid = locale.LCID;
+#endif
+
+ for (int i = 0; i < m_iCABuilder; i++)
+ {
+ // check for known attributes
+ Type conType = m_CABuilders[i].m_con.DeclaringType;
+ if (m_CABuilders[i].m_constructorArgs.Length == 0 || m_CABuilders[i].m_constructorArgs[0] == null)
+ continue;
+
+ if (conType.Equals(typeof(System.Reflection.AssemblyCopyrightAttribute)))
+ {
+ // assert that we should only have one argument for this CA and the type should
+ // be a string.
+ //
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ m_nativeVersion.m_strCopyright = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyTrademarkAttribute)))
+ {
+ // assert that we should only have one argument for this CA and the type should
+ // be a string.
+ //
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ m_nativeVersion.m_strTrademark = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyProductAttribute)))
+ {
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ // assert that we should only have one argument for this CA and the type should
+ // be a string.
+ //
+ m_nativeVersion.m_strProduct = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyCompanyAttribute)))
+ {
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ // assert that we should only have one argument for this CA and the type should
+ // be a string.
+ //
+ m_nativeVersion.m_strCompany = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyDescriptionAttribute)))
+ {
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ m_nativeVersion.m_strDescription = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyTitleAttribute)))
+ {
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ m_nativeVersion.m_strTitle = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyInformationalVersionAttribute)))
+ {
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ m_nativeVersion.m_strProductVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyCultureAttribute)))
+ {
+ // retrieve the LCID
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ // CultureInfo attribute overrides the lcid from AssemblyName.
+ CultureInfo culture = new CultureInfo(m_CABuilders[i].m_constructorArgs[0].ToString());
+#if FEATURE_USE_LCID
+ m_nativeVersion.m_lcid = culture.LCID;
+#endif
+ }
+ else if (conType.Equals(typeof(System.Reflection.AssemblyFileVersionAttribute)))
+ {
+ if (m_CABuilders[i].m_constructorArgs.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_BadCAForUnmngRSC",
+ m_CABuilders[i].m_con.ReflectedType.Name));
+ }
+ if (m_OverrideUnmanagedVersionInfo == false)
+ {
+ m_nativeVersion.m_strFileVersion = m_CABuilders[i].m_constructorArgs[0].ToString();
+ }
+ }
+ }
+ }
+
+
+ // Helper to ensure the resource name is unique underneath assemblyBuilder
+ internal void CheckResNameConflict(String strNewResName)
+ {
+ int size = m_resWriterList.Count;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ ResWriterData resWriter = m_resWriterList[i];
+ if (resWriter.m_strName.Equals(strNewResName))
+ {
+ // Cannot have two resources with the same name
+ throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateResourceName"));
+ }
+ }
+ }
+
+
+ // Helper to ensure the module name is unique underneath assemblyBuilder
+ internal void CheckNameConflict(String strNewModuleName)
+ {
+ int size = m_moduleBuilderList.Count;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
+ if (moduleBuilder.m_moduleData.m_strModuleName.Equals(strNewModuleName))
+ {
+ // Cannot have two dynamic modules with the same name
+ throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
+ }
+ }
+
+ // Right now dynamic modules can only be added to dynamic assemblies in which
+ // all modules are dynamic. Otherwise we would also need to check the static modules
+ // with this:
+ // if (m_assembly.GetModule(strNewModuleName) != null)
+ // {
+ // // Cannot have two dynamic modules with the same name
+ // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateModuleName"));
+ // }
+ }
+
+ // Helper to ensure the type name is unique underneath assemblyBuilder
+ internal void CheckTypeNameConflict(String strTypeName, TypeBuilder enclosingType)
+ {
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.CheckTypeNameConflict( " + strTypeName + " )");
+ for (int i = 0; i < m_moduleBuilderList.Count; i++)
+ {
+ ModuleBuilder curModule = m_moduleBuilderList[i];
+ curModule.CheckTypeNameConflict(strTypeName, enclosingType);
+ }
+
+ // Right now dynamic modules can only be added to dynamic assemblies in which
+ // all modules are dynamic. Otherwise we would also need to check loaded types.
+ // We only need to make this test for non-nested types since any
+ // duplicates in nested types will be caught at the top level.
+ // if (enclosingType == null && m_assembly.GetType(strTypeName, false, false) != null)
+ // {
+ // // Cannot have two types with the same name
+ // throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName"));
+ // }
+ }
+
+
+ // Helper to ensure the file name is unique underneath assemblyBuilder. This includes
+ // modules and resources.
+ //
+ //
+ //
+ internal void CheckFileNameConflict(String strFileName)
+ {
+ int size = m_moduleBuilderList.Count;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
+ if (moduleBuilder.m_moduleData.m_strFileName != null)
+ {
+ if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ // Cannot have two dynamic module with the same name
+ throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
+ }
+ }
+ }
+ size = m_resWriterList.Count;
+ for (i = 0; i < size; i++)
+ {
+ ResWriterData resWriter = m_resWriterList[i];
+ if (resWriter.m_strFileName != null)
+ {
+ if (String.Compare(resWriter.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ // Cannot have two dynamic module with the same name
+ throw new ArgumentException(Environment.GetResourceString("Argument_DuplicatedFileName"));
+ }
+ }
+ }
+
+ }
+
+ // Helper to look up which module that assembly is supposed to be stored at
+ //
+ //
+ //
+ internal ModuleBuilder FindModuleWithFileName(String strFileName)
+ {
+ int size = m_moduleBuilderList.Count;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
+ if (moduleBuilder.m_moduleData.m_strFileName != null)
+ {
+ if (String.Compare(moduleBuilder.m_moduleData.m_strFileName, strFileName, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ return moduleBuilder;
+ }
+ }
+ }
+ return null;
+ }
+
+ // Helper to look up module by name.
+ //
+ //
+ //
+ internal ModuleBuilder FindModuleWithName(String strName)
+ {
+ int size = m_moduleBuilderList.Count;
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ ModuleBuilder moduleBuilder = m_moduleBuilderList[i];
+ if (moduleBuilder.m_moduleData.m_strModuleName != null)
+ {
+ if (String.Compare(moduleBuilder.m_moduleData.m_strModuleName, strName, StringComparison.OrdinalIgnoreCase) == 0)
+ return moduleBuilder;
+ }
+ }
+ return null;
+ }
+
+
+ // add type to public COMType tracking list
+ internal void AddPublicComType(Type type)
+ {
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPublicComType( " + type.FullName + " )");
+ if (m_isSaved == true)
+ {
+ // assembly has been saved before!
+ throw new InvalidOperationException(Environment.GetResourceString(
+ "InvalidOperation_CannotAlterAssembly"));
+ }
+ EnsurePublicComTypeCapacity();
+ m_publicComTypeList[m_iPublicComTypeCount] = type;
+ m_iPublicComTypeCount++;
+ }
+
+ // add security permission requests
+ internal void AddPermissionRequests(
+ PermissionSet required,
+ PermissionSet optional,
+ PermissionSet refused)
+ {
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: AssemblyBuilderData.AddPermissionRequests");
+ if (m_isSaved == true)
+ {
+ // assembly has been saved before!
+ throw new InvalidOperationException(Environment.GetResourceString(
+ "InvalidOperation_CannotAlterAssembly"));
+ }
+ m_RequiredPset = required;
+ m_OptionalPset = optional;
+ m_RefusedPset = refused;
+ }
+
+ private void EnsurePublicComTypeCapacity()
+ {
+ if (m_publicComTypeList == null)
+ {
+ m_publicComTypeList = new Type[m_iInitialSize];
+ }
+ if (m_iPublicComTypeCount == m_publicComTypeList.Length)
+ {
+ Type[] tempTypeList = new Type[m_iPublicComTypeCount * 2];
+ Array.Copy(m_publicComTypeList, 0, tempTypeList, 0, m_iPublicComTypeCount);
+ m_publicComTypeList = tempTypeList;
+ }
+ }
+
+ internal List<ModuleBuilder> m_moduleBuilderList;
+ internal List<ResWriterData> m_resWriterList;
+ internal String m_strAssemblyName;
+ internal AssemblyBuilderAccess m_access;
+ private InternalAssemblyBuilder m_assembly;
+
+ internal Type[] m_publicComTypeList;
+ internal int m_iPublicComTypeCount;
+
+ internal bool m_isSaved;
+ internal const int m_iInitialSize = 16;
+ internal String m_strDir;
+
+ // hard coding the assembly def token
+ internal const int m_tkAssembly = 0x20000001;
+
+ // Security permission requests
+ internal PermissionSet m_RequiredPset;
+ internal PermissionSet m_OptionalPset;
+ internal PermissionSet m_RefusedPset;
+
+ // tracking AssemblyDef's CAs for persistence to disk
+ internal CustomAttributeBuilder[] m_CABuilders;
+ internal int m_iCABuilder;
+ internal byte[][] m_CABytes;
+ internal ConstructorInfo[] m_CACons;
+ internal int m_iCAs;
+ internal PEFileKinds m_peFileKind; // assembly file kind
+ internal MethodInfo m_entryPointMethod;
+ internal Assembly m_ISymWrapperAssembly;
+
+#if !FEATURE_CORECLR
+ internal ModuleBuilder m_entryPointModule;
+#endif //!FEATURE_CORECLR
+
+ // For unmanaged resources
+ internal String m_strResourceFileName;
+ internal byte[] m_resourceBytes;
+ internal NativeVersionInfo m_nativeVersion;
+ internal bool m_hasUnmanagedVersionInfo;
+ internal bool m_OverrideUnmanagedVersionInfo;
+
+ }
+
+
+ /**********************************************
+ *
+ * Internal structure to track the list of ResourceWriter for
+ * AssemblyBuilder & ModuleBuilder.
+ *
+ **********************************************/
+ internal class ResWriterData
+ {
+#if FEATURE_CORECLR
+ internal ResWriterData(
+ IResourceWriter resWriter,
+ Stream memoryStream,
+ String strName,
+ String strFileName,
+ String strFullFileName,
+ ResourceAttributes attribute)
+ {
+ m_resWriter = resWriter;
+ m_memoryStream = memoryStream;
+ m_strName = strName;
+ m_strFileName = strFileName;
+ m_strFullFileName = strFullFileName;
+ m_nextResWriter = null;
+ m_attribute = attribute;
+ }
+#else
+ internal ResWriterData(
+ ResourceWriter resWriter,
+ Stream memoryStream,
+ String strName,
+ String strFileName,
+ String strFullFileName,
+ ResourceAttributes attribute)
+ {
+ m_resWriter = resWriter;
+ m_memoryStream = memoryStream;
+ m_strName = strName;
+ m_strFileName = strFileName;
+ m_strFullFileName = strFullFileName;
+ m_nextResWriter = null;
+ m_attribute = attribute;
+ }
+#endif
+#if !FEATURE_CORECLR
+ internal ResourceWriter m_resWriter;
+#else // FEATURE_CORECLR
+ internal IResourceWriter m_resWriter;
+#endif // !FEATURE_CORECLR
+ internal String m_strName;
+ internal String m_strFileName;
+ internal String m_strFullFileName;
+ internal Stream m_memoryStream;
+ internal ResWriterData m_nextResWriter;
+ internal ResourceAttributes m_attribute;
+ }
+
+ internal class NativeVersionInfo
+ {
+ internal NativeVersionInfo()
+ {
+ m_strDescription = null;
+ m_strCompany = null;
+ m_strTitle = null;
+ m_strCopyright = null;
+ m_strTrademark = null;
+ m_strProduct = null;
+ m_strProductVersion = null;
+ m_strFileVersion = null;
+ m_lcid = -1;
+ }
+
+ internal String m_strDescription;
+ internal String m_strCompany;
+ internal String m_strTitle;
+ internal String m_strCopyright;
+ internal String m_strTrademark;
+ internal String m_strProduct;
+ internal String m_strProductVersion;
+ internal String m_strFileVersion;
+ internal int m_lcid;
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs b/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs
new file mode 100644
index 0000000000..0d8ce5a8d4
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ComInterfaces.cs
@@ -0,0 +1,288 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Security.Policy;
+
+namespace System.Runtime.InteropServices
+{
+ [GuidAttribute("BEBB2505-8B54-3443-AEAD-142A16DD9CC7")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.AssemblyBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _AssemblyBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("ED3E4384-D7E2-3FA7-8FFD-8940D330519A")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ConstructorBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ConstructorBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("BE9ACCE8-AAFF-3B91-81AE-8211663F5CAD")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.CustomAttributeBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _CustomAttributeBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("C7BD73DE-9F85-3290-88EE-090B8BDFE2DF")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.EnumBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _EnumBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("AADABA99-895D-3D65-9760-B1F12621FAE8")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.EventBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _EventBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("CE1A3BF5-975E-30CC-97C9-1EF70F8F3993")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.FieldBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _FieldBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("A4924B27-6E3B-37F7-9B83-A4501955E6A7")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ILGenerator))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ILGenerator
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("4E6350D1-A08B-3DEC-9A3E-C465F9AEEC0C")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.LocalBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _LocalBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("007D8A14-FDF3-363E-9A0B-FEC0618260A2")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.MethodBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _MethodBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+#if FEATURE_METHOD_RENTAL
+ [GuidAttribute("C2323C25-F57F-3880-8A4D-12EBEA7A5852")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.MethodRental))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _MethodRental
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+#endif
+
+ [GuidAttribute("D05FFA9A-04AF-3519-8EE1-8D93AD73430B")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ModuleBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ModuleBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("36329EBA-F97A-3565-BC07-0ED5C6EF19FC")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.ParameterBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _ParameterBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("15F9A479-9397-3A63-ACBD-F51977FB0F02")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.PropertyBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _PropertyBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("7D13DD37-5A04-393C-BBCA-A5FEA802893D")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.SignatureHelper))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _SignatureHelper
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("7E5678EE-48B3-3F83-B076-C58543498A58")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Reflection.Emit.TypeBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _TypeBuilder
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs
new file mode 100644
index 0000000000..e5062d3365
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ConstructorBuilder.cs
@@ -0,0 +1,335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Reflection;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Collections.Generic;
+ using System.Diagnostics.SymbolStore;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ConstructorBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ConstructorBuilder : ConstructorInfo, _ConstructorBuilder
+ {
+ private readonly MethodBuilder m_methodBuilder;
+ internal bool m_isDefaultConstructor;
+
+ #region Constructor
+
+ private ConstructorBuilder()
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ConstructorBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers, ModuleBuilder mod, TypeBuilder type)
+ {
+ int sigLength;
+ byte[] sigBytes;
+ MethodToken token;
+
+ m_methodBuilder = new MethodBuilder(name, attributes, callingConvention, null, null, null,
+ parameterTypes, requiredCustomModifiers, optionalCustomModifiers, mod, type, false);
+
+ type.m_listMethods.Add(m_methodBuilder);
+
+ sigBytes = m_methodBuilder.GetMethodSignature().InternalGetSignature(out sigLength);
+
+ token = m_methodBuilder.GetToken();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ConstructorBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type[] parameterTypes, ModuleBuilder mod, TypeBuilder type) :
+ this(name, attributes, callingConvention, parameterTypes, null, null, mod, type)
+ {
+ }
+
+ #endregion
+
+ #region Internal
+ internal override Type[] GetParameterTypes()
+ {
+ return m_methodBuilder.GetParameterTypes();
+ }
+
+ private TypeBuilder GetTypeBuilder()
+ {
+ return m_methodBuilder.GetTypeBuilder();
+ }
+
+ internal ModuleBuilder GetModuleBuilder()
+ {
+ return GetTypeBuilder().GetModuleBuilder();
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return m_methodBuilder.ToString();
+ }
+
+ #endregion
+
+ #region MemberInfo Overrides
+ internal int MetadataTokenInternal
+ {
+ get { return m_methodBuilder.MetadataTokenInternal; }
+ }
+
+ public override Module Module
+ {
+ get { return m_methodBuilder.Module; }
+ }
+
+ public override Type ReflectedType
+ {
+ get { return m_methodBuilder.ReflectedType; }
+ }
+
+ public override Type DeclaringType
+ {
+ get { return m_methodBuilder.DeclaringType; }
+ }
+
+ public override String Name
+ {
+ get { return m_methodBuilder.Name; }
+ }
+
+ #endregion
+
+ #region MethodBase Overrides
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ [Pure]
+ public override ParameterInfo[] GetParameters()
+ {
+ ConstructorInfo rci = GetTypeBuilder().GetConstructor(m_methodBuilder.m_parameterTypes);
+ return rci.GetParameters();
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return m_methodBuilder.Attributes; }
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return m_methodBuilder.GetMethodImplementationFlags();
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get { return m_methodBuilder.MethodHandle; }
+ }
+
+ #endregion
+
+ #region ConstructorInfo Overrides
+ public override Object Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return m_methodBuilder.GetCustomAttributes(inherit);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return m_methodBuilder.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ return m_methodBuilder.IsDefined(attributeType, inherit);
+ }
+
+ #endregion
+
+ #region Public Members
+ public MethodToken GetToken()
+ {
+ return m_methodBuilder.GetToken();
+ }
+
+ public ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attributes, String strParamName)
+ {
+ // Theoretically we shouldn't allow iSequence to be 0 because in reflection ctors don't have
+ // return parameters. But we'll allow it for backward compatibility with V2. The attributes
+ // defined on the return parameters won't be very useful but won't do much harm either.
+
+ // MD will assert if we try to set the reserved bits explicitly
+ attributes = attributes & ~ParameterAttributes.ReservedMask;
+ return m_methodBuilder.DefineParameter(iSequence, attributes, strParamName);
+ }
+
+ public void SetSymCustomAttribute(String name, byte[] data)
+ {
+ m_methodBuilder.SetSymCustomAttribute(name, data);
+ }
+
+ public ILGenerator GetILGenerator()
+ {
+ if (m_isDefaultConstructor)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DefaultConstructorILGen"));
+
+ return m_methodBuilder.GetILGenerator();
+ }
+
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ if (m_isDefaultConstructor)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DefaultConstructorILGen"));
+
+ return m_methodBuilder.GetILGenerator(streamSize);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
+ {
+ if (m_isDefaultConstructor)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_DefaultConstructorDefineBody"));
+ }
+
+ m_methodBuilder.SetMethodBody(il, maxStack, localSignature, exceptionHandlers, tokenFixups);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset)
+ {
+ if (pset == null)
+ throw new ArgumentNullException("pset");
+
+#pragma warning disable 618
+ if (!Enum.IsDefined(typeof(SecurityAction), action) ||
+ action == SecurityAction.RequestMinimum ||
+ action == SecurityAction.RequestOptional ||
+ action == SecurityAction.RequestRefuse)
+ {
+ throw new ArgumentOutOfRangeException("action");
+ }
+#pragma warning restore 618
+ Contract.EndContractBlock();
+
+ // Cannot add declarative security after type is created.
+ if (m_methodBuilder.IsTypeCreated())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated"));
+
+ // Translate permission set into serialized format (use standard binary serialization).
+ byte[] blob = pset.EncodeXml();
+
+ // Write the blob into the metadata.
+ TypeBuilder.AddDeclarativeSecurity(GetModuleBuilder().GetNativeHandle(), GetToken().Token, action, blob, blob.Length);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ if (DeclaringType.IsGenericType)
+ return CallingConventions.HasThis;
+
+ return CallingConventions.Standard;
+ }
+ }
+
+ public Module GetModule()
+ {
+ return m_methodBuilder.GetModule();
+ }
+
+
+ [Obsolete("This property has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")] //It always returns null.
+ public Type ReturnType
+ {
+ get { return GetReturnType(); }
+ }
+
+ // This always returns null. Is that what we want?
+ internal override Type GetReturnType()
+ {
+ return m_methodBuilder.ReturnType;
+ }
+
+ public String Signature
+ {
+ get { return m_methodBuilder.Signature; }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ m_methodBuilder.SetCustomAttribute(con, binaryAttribute);
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ m_methodBuilder.SetCustomAttribute(customBuilder);
+ }
+
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ m_methodBuilder.SetImplementationFlags(attributes);
+ }
+
+ public bool InitLocals
+ {
+ get { return m_methodBuilder.InitLocals; }
+ set { m_methodBuilder.InitLocals = value; }
+ }
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _ConstructorBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ConstructorBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ConstructorBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ConstructorBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs
new file mode 100644
index 0000000000..2a29a5c190
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/CustomAttributeBuilder.cs
@@ -0,0 +1,582 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** CustomAttributeBuilder is a helper class to help building custom attribute.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+
+ using System;
+ using System.Reflection;
+ using System.IO;
+ using System.Text;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_CustomAttributeBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CustomAttributeBuilder : _CustomAttributeBuilder
+ {
+ // public constructor to form the custom attribute with constructor and constructor
+ // parameters.
+ public CustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs)
+ {
+ InitCustomAttributeBuilder(con, constructorArgs,
+ new PropertyInfo[]{}, new Object[]{},
+ new FieldInfo[]{}, new Object[]{});
+ }
+
+ // public constructor to form the custom attribute with constructor, constructor
+ // parameters and named properties.
+ public CustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs,
+ PropertyInfo[] namedProperties, Object[] propertyValues)
+ {
+ InitCustomAttributeBuilder(con, constructorArgs, namedProperties,
+ propertyValues, new FieldInfo[]{}, new Object[]{});
+ }
+
+ // public constructor to form the custom attribute with constructor and constructor
+ // parameters.
+ public CustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs,
+ FieldInfo[] namedFields, Object[] fieldValues)
+ {
+ InitCustomAttributeBuilder(con, constructorArgs, new PropertyInfo[]{},
+ new Object[]{}, namedFields, fieldValues);
+ }
+
+ // public constructor to form the custom attribute with constructor and constructor
+ // parameters.
+ public CustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs,
+ PropertyInfo[] namedProperties, Object[] propertyValues,
+ FieldInfo[] namedFields, Object[] fieldValues)
+ {
+ InitCustomAttributeBuilder(con, constructorArgs, namedProperties,
+ propertyValues, namedFields, fieldValues);
+ }
+
+ // Check that a type is suitable for use in a custom attribute.
+ private bool ValidateType(Type t)
+ {
+ if (t.IsPrimitive || t == typeof(String) || t == typeof(Type))
+ return true;
+ if (t.IsEnum)
+ {
+ switch (Type.GetTypeCode(Enum.GetUnderlyingType(t)))
+ {
+ case TypeCode.SByte:
+ case TypeCode.Byte:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ return true;
+ default:
+ return false;
+ }
+ }
+ if (t.IsArray)
+ {
+ if (t.GetArrayRank() != 1)
+ return false;
+ return ValidateType(t.GetElementType());
+ }
+ return t == typeof(Object);
+ }
+
+ internal void InitCustomAttributeBuilder(ConstructorInfo con, Object[] constructorArgs,
+ PropertyInfo[] namedProperties, Object[] propertyValues,
+ FieldInfo[] namedFields, Object[] fieldValues)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (constructorArgs == null)
+ throw new ArgumentNullException("constructorArgs");
+ if (namedProperties == null)
+ throw new ArgumentNullException("namedProperties");
+ if (propertyValues == null)
+ throw new ArgumentNullException("propertyValues");
+ if (namedFields == null)
+ throw new ArgumentNullException("namedFields");
+ if (fieldValues == null)
+ throw new ArgumentNullException("fieldValues");
+ if (namedProperties.Length != propertyValues.Length)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedProperties, propertyValues");
+ if (namedFields.Length != fieldValues.Length)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayLengthsDiffer"), "namedFields, fieldValues");
+ Contract.EndContractBlock();
+
+ if ((con.Attributes & MethodAttributes.Static) == MethodAttributes.Static ||
+ (con.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructor"));
+
+ if ((con.CallingConvention & CallingConventions.Standard) != CallingConventions.Standard)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadConstructorCallConv"));
+
+ // Cache information used elsewhere.
+ m_con = con;
+ m_constructorArgs = new Object[constructorArgs.Length];
+ Array.Copy(constructorArgs, 0, m_constructorArgs, 0, constructorArgs.Length);
+
+ Type[] paramTypes;
+ int i;
+
+ // Get the types of the constructor's formal parameters.
+ paramTypes = con.GetParameterTypes();
+
+ // Since we're guaranteed a non-var calling convention, the number of arguments must equal the number of parameters.
+ if (paramTypes.Length != constructorArgs.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterCountsForConstructor"));
+
+ // Verify that the constructor has a valid signature (custom attributes only support a subset of our type system).
+ for (i = 0; i < paramTypes.Length; i++)
+ if (!ValidateType(paramTypes[i]))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
+
+ // Now verify that the types of the actual parameters are compatible with the types of the formal parameters.
+ for (i = 0; i < paramTypes.Length; i++)
+ {
+ if (constructorArgs[i] == null)
+ continue;
+ TypeCode paramTC = Type.GetTypeCode(paramTypes[i]);
+ if (paramTC != Type.GetTypeCode(constructorArgs[i].GetType()))
+ if (paramTC != TypeCode.Object || !ValidateType(constructorArgs[i].GetType()))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForConstructor", i));
+ }
+
+ // Allocate a memory stream to represent the CA blob in the metadata and a binary writer to help format it.
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+
+ // Write the blob protocol version (currently 1).
+ writer.Write((ushort)1);
+
+ // Now emit the constructor argument values (no need for types, they're inferred from the constructor signature).
+ for (i = 0; i < constructorArgs.Length; i++)
+ EmitValue(writer, paramTypes[i], constructorArgs[i]);
+
+ // Next a short with the count of properties and fields.
+ writer.Write((ushort)(namedProperties.Length + namedFields.Length));
+
+ // Emit all the property sets.
+ for (i = 0; i < namedProperties.Length; i++)
+ {
+ // Validate the property.
+ if (namedProperties[i] == null)
+ throw new ArgumentNullException("namedProperties[" + i + "]");
+
+ // Allow null for non-primitive types only.
+ Type propType = namedProperties[i].PropertyType;
+ if (propertyValues[i] == null && propType.IsPrimitive)
+ throw new ArgumentNullException("propertyValues[" + i + "]");
+
+ // Validate property type.
+ if (!ValidateType(propType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
+
+ // Property has to be writable.
+ if (!namedProperties[i].CanWrite)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotAWritableProperty"));
+
+ // Property has to be from the same class or base class as ConstructorInfo.
+ if (namedProperties[i].DeclaringType != con.DeclaringType
+ && (!(con.DeclaringType is TypeBuilderInstantiation))
+ && !con.DeclaringType.IsSubclassOf(namedProperties[i].DeclaringType))
+ {
+ // Might have failed check because one type is a XXXBuilder
+ // and the other is not. Deal with these special cases
+ // separately.
+ if (!TypeBuilder.IsTypeEqual(namedProperties[i].DeclaringType, con.DeclaringType))
+ {
+ // IsSubclassOf is overloaded to do the right thing if
+ // the constructor is a TypeBuilder, but we still need
+ // to deal with the case where the property's declaring
+ // type is one.
+ if (!(namedProperties[i].DeclaringType is TypeBuilder) ||
+ !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedProperties[i].DeclaringType).BakedRuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadPropertyForConstructorBuilder"));
+ }
+ }
+
+ // Make sure the property's type can take the given value.
+ // Note that there will be no coersion.
+ if (propertyValues[i] != null &&
+ propType != typeof(Object) &&
+ Type.GetTypeCode(propertyValues[i].GetType()) != Type.GetTypeCode(propType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+
+ // First a byte indicating that this is a property.
+ writer.Write((byte)CustomAttributeEncoding.Property);
+
+ // Emit the property type, name and value.
+ EmitType(writer, propType);
+ EmitString(writer, namedProperties[i].Name);
+ EmitValue(writer, propType, propertyValues[i]);
+ }
+
+ // Emit all the field sets.
+ for (i = 0; i < namedFields.Length; i++)
+ {
+ // Validate the field.
+ if (namedFields[i] == null)
+ throw new ArgumentNullException("namedFields[" + i + "]");
+
+ // Allow null for non-primitive types only.
+ Type fldType = namedFields[i].FieldType;
+ if (fieldValues[i] == null && fldType.IsPrimitive)
+ throw new ArgumentNullException("fieldValues[" + i + "]");
+
+ // Validate field type.
+ if (!ValidateType(fldType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeInCustomAttribute"));
+
+ // Field has to be from the same class or base class as ConstructorInfo.
+ if (namedFields[i].DeclaringType != con.DeclaringType
+ && (!(con.DeclaringType is TypeBuilderInstantiation))
+ && !con.DeclaringType.IsSubclassOf(namedFields[i].DeclaringType))
+ {
+ // Might have failed check because one type is a XXXBuilder
+ // and the other is not. Deal with these special cases
+ // separately.
+ if (!TypeBuilder.IsTypeEqual(namedFields[i].DeclaringType, con.DeclaringType))
+ {
+ // IsSubclassOf is overloaded to do the right thing if
+ // the constructor is a TypeBuilder, but we still need
+ // to deal with the case where the field's declaring
+ // type is one.
+ if (!(namedFields[i].DeclaringType is TypeBuilder) ||
+ !con.DeclaringType.IsSubclassOf(((TypeBuilder)namedFields[i].DeclaringType).BakedRuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldForConstructorBuilder"));
+ }
+ }
+
+ // Make sure the field's type can take the given value.
+ // Note that there will be no coersion.
+ if (fieldValues[i] != null &&
+ fldType != typeof(Object) &&
+ Type.GetTypeCode(fieldValues[i].GetType()) != Type.GetTypeCode(fldType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+
+ // First a byte indicating that this is a field.
+ writer.Write((byte)CustomAttributeEncoding.Field);
+
+ // Emit the field type, name and value.
+ EmitType(writer, fldType);
+ EmitString(writer, namedFields[i].Name);
+ EmitValue(writer, fldType, fieldValues[i]);
+ }
+
+ // Create the blob array.
+ m_blob = ((MemoryStream)writer.BaseStream).ToArray();
+ }
+
+ private void EmitType(BinaryWriter writer, Type type)
+ {
+ if (type.IsPrimitive)
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.SByte:
+ writer.Write((byte)CustomAttributeEncoding.SByte);
+ break;
+ case TypeCode.Byte:
+ writer.Write((byte)CustomAttributeEncoding.Byte);
+ break;
+ case TypeCode.Char:
+ writer.Write((byte)CustomAttributeEncoding.Char);
+ break;
+ case TypeCode.Boolean:
+ writer.Write((byte)CustomAttributeEncoding.Boolean);
+ break;
+ case TypeCode.Int16:
+ writer.Write((byte)CustomAttributeEncoding.Int16);
+ break;
+ case TypeCode.UInt16:
+ writer.Write((byte)CustomAttributeEncoding.UInt16);
+ break;
+ case TypeCode.Int32:
+ writer.Write((byte)CustomAttributeEncoding.Int32);
+ break;
+ case TypeCode.UInt32:
+ writer.Write((byte)CustomAttributeEncoding.UInt32);
+ break;
+ case TypeCode.Int64:
+ writer.Write((byte)CustomAttributeEncoding.Int64);
+ break;
+ case TypeCode.UInt64:
+ writer.Write((byte)CustomAttributeEncoding.UInt64);
+ break;
+ case TypeCode.Single:
+ writer.Write((byte)CustomAttributeEncoding.Float);
+ break;
+ case TypeCode.Double:
+ writer.Write((byte)CustomAttributeEncoding.Double);
+ break;
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ break;
+ }
+ }
+ else if (type.IsEnum)
+ {
+ writer.Write((byte)CustomAttributeEncoding.Enum);
+ EmitString(writer, type.AssemblyQualifiedName);
+ }
+ else if (type == typeof(String))
+ {
+ writer.Write((byte)CustomAttributeEncoding.String);
+ }
+ else if (type == typeof(Type))
+ {
+ writer.Write((byte)CustomAttributeEncoding.Type);
+ }
+ else if (type.IsArray)
+ {
+ writer.Write((byte)CustomAttributeEncoding.Array);
+ EmitType(writer, type.GetElementType());
+ }
+ else
+ {
+ // Tagged object case.
+ writer.Write((byte)CustomAttributeEncoding.Object);
+ }
+ }
+
+ private void EmitString(BinaryWriter writer, String str)
+ {
+ // Strings are emitted with a length prefix in a compressed format (1, 2 or 4 bytes) as used internally by metadata.
+ byte[] utf8Str = Encoding.UTF8.GetBytes(str);
+ uint length = (uint)utf8Str.Length;
+ if (length <= 0x7f)
+ {
+ writer.Write((byte)length);
+ }
+ else if (length <= 0x3fff)
+ {
+ writer.Write((byte)((length >> 8) | 0x80));
+ writer.Write((byte)(length & 0xff));
+ }
+ else
+ {
+ writer.Write((byte)((length >> 24) | 0xc0));
+ writer.Write((byte)((length >> 16) & 0xff));
+ writer.Write((byte)((length >> 8) & 0xff));
+ writer.Write((byte)(length & 0xff));
+ }
+ writer.Write(utf8Str);
+ }
+
+ private void EmitValue(BinaryWriter writer, Type type, Object value)
+ {
+ if (type.IsEnum)
+ {
+ switch (Type.GetTypeCode(Enum.GetUnderlyingType(type)))
+ {
+ case TypeCode.SByte:
+ writer.Write((sbyte)value);
+ break;
+ case TypeCode.Byte:
+ writer.Write((byte)value);
+ break;
+ case TypeCode.Int16:
+ writer.Write((short)value);
+ break;
+ case TypeCode.UInt16:
+ writer.Write((ushort)value);
+ break;
+ case TypeCode.Int32:
+ writer.Write((int)value);
+ break;
+ case TypeCode.UInt32:
+ writer.Write((uint)value);
+ break;
+ case TypeCode.Int64:
+ writer.Write((long)value);
+ break;
+ case TypeCode.UInt64:
+ writer.Write((ulong)value);
+ break;
+ default:
+ Contract.Assert(false, "Invalid enum base type");
+ break;
+ }
+ }
+ else if (type == typeof(String))
+ {
+ if (value == null)
+ writer.Write((byte)0xff);
+ else
+ EmitString(writer, (String)value);
+ }
+ else if (type == typeof(Type))
+ {
+ if (value == null)
+ writer.Write((byte)0xff);
+ else
+ {
+ String typeName = TypeNameBuilder.ToString((Type)value, TypeNameBuilder.Format.AssemblyQualifiedName);
+ if (typeName == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeForCA",
+ value.GetType()));
+ EmitString(writer, typeName);
+ }
+ }
+ else if (type.IsArray)
+ {
+ if (value == null)
+ writer.Write((uint)0xffffffff);
+ else
+ {
+ Array a = (Array)value;
+ Type et = type.GetElementType();
+ writer.Write(a.Length);
+ for (int i = 0; i < a.Length; i++)
+ EmitValue(writer, et, a.GetValue(i));
+ }
+ }
+ else if (type.IsPrimitive)
+ {
+ switch (Type.GetTypeCode(type))
+ {
+ case TypeCode.SByte:
+ writer.Write((sbyte)value);
+ break;
+ case TypeCode.Byte:
+ writer.Write((byte)value);
+ break;
+ case TypeCode.Char:
+ writer.Write(Convert.ToUInt16((char)value));
+ break;
+ case TypeCode.Boolean:
+ writer.Write((byte)((bool)value ? 1 : 0));
+ break;
+ case TypeCode.Int16:
+ writer.Write((short)value);
+ break;
+ case TypeCode.UInt16:
+ writer.Write((ushort)value);
+ break;
+ case TypeCode.Int32:
+ writer.Write((int)value);
+ break;
+ case TypeCode.UInt32:
+ writer.Write((uint)value);
+ break;
+ case TypeCode.Int64:
+ writer.Write((long)value);
+ break;
+ case TypeCode.UInt64:
+ writer.Write((ulong)value);
+ break;
+ case TypeCode.Single:
+ writer.Write((float)value);
+ break;
+ case TypeCode.Double:
+ writer.Write((double)value);
+ break;
+ default:
+ Contract.Assert(false, "Invalid primitive type");
+ break;
+ }
+ }
+ else if (type == typeof(object))
+ {
+ // Tagged object case. Type instances aren't actually Type, they're some subclass (such as RuntimeType or
+ // TypeBuilder), so we need to canonicalize this case back to Type. If we have a null value we follow the convention
+ // used by C# and emit a null typed as a string (it doesn't really matter what type we pick as long as it's a
+ // reference type).
+ Type ot = value == null ? typeof(String) : value is Type ? typeof(Type) : value.GetType();
+
+ // value cannot be a "System.Object" object.
+ // If we allow this we will get into an infinite recursion
+ if (ot == typeof(object))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForCAB", ot.ToString()));
+
+ EmitType(writer, ot);
+ EmitValue(writer, ot, value);
+ }
+ else
+ {
+ string typename = "null";
+
+ if (value != null)
+ typename = value.GetType().ToString();
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadParameterTypeForCAB", typename));
+ }
+ }
+
+
+
+
+ // return the byte interpretation of the custom attribute
+ [System.Security.SecurityCritical] // auto-generated
+ internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner)
+ {
+ CreateCustomAttribute(mod, tkOwner, mod.GetConstructorToken(m_con).Token, false);
+ }
+
+ //*************************************************
+ // Upon saving to disk, we need to create the memberRef token for the custom attribute's type
+ // first of all. So when we snap the in-memory module for on disk, this token will be there.
+ // We also need to enforce the use of MemberRef. Because MemberDef token might move.
+ // This function has to be called before we snap the in-memory module for on disk (i.e. Presave on
+ // ModuleBuilder.
+ //*************************************************
+ [System.Security.SecurityCritical] // auto-generated
+ internal int PrepareCreateCustomAttributeToDisk(ModuleBuilder mod)
+ {
+ return mod.InternalGetConstructorToken(m_con, true).Token;
+ }
+
+ //*************************************************
+ // Call this function with toDisk=1, after on disk module has been snapped.
+ //*************************************************
+ [System.Security.SecurityCritical] // auto-generated
+ internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner, int tkAttrib, bool toDisk)
+ {
+ TypeBuilder.DefineCustomAttribute(mod, tkOwner, tkAttrib, m_blob, toDisk,
+ typeof(System.Diagnostics.DebuggableAttribute) == m_con.DeclaringType);
+ }
+
+#if !FEATURE_CORECLR
+ void _CustomAttributeBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _CustomAttributeBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _CustomAttributeBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _CustomAttributeBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ internal ConstructorInfo m_con;
+ internal Object[] m_constructorArgs;
+ internal byte[] m_blob;
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs
new file mode 100644
index 0000000000..b66fdad1e2
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs
@@ -0,0 +1,1329 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+
+ using System;
+ using System.Globalization;
+ using TextWriter = System.IO.TextWriter;
+ using System.Diagnostics.SymbolStore;
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+
+ internal class DynamicILGenerator : ILGenerator
+ {
+
+ internal DynamicScope m_scope;
+ private int m_methodSigToken;
+
+ internal unsafe DynamicILGenerator(DynamicMethod method, byte[] methodSignature, int size)
+ : base(method, size)
+ {
+ m_scope = new DynamicScope();
+
+ m_methodSigToken = m_scope.GetTokenFor(methodSignature);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void GetCallableMethod(RuntimeModule module, DynamicMethod dm)
+ {
+ dm.m_methodHandle = ModuleHandle.GetDynamicMethod(dm,
+ module,
+ m_methodBuilder.Name,
+ (byte[])m_scope[m_methodSigToken],
+ new DynamicResolver(this));
+ }
+
+#if FEATURE_APPX
+ private bool ProfileAPICheck
+ {
+ get
+ {
+ return ((DynamicMethod)m_methodBuilder).ProfileAPICheck;
+ }
+ }
+#endif // FEATURE_APPX
+
+ // *** ILGenerator api ***
+
+ public override LocalBuilder DeclareLocal(Type localType, bool pinned)
+ {
+ LocalBuilder localBuilder;
+ if (localType == null)
+ throw new ArgumentNullException("localType");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = localType as RuntimeType;
+
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+#if FEATURE_APPX
+ if (ProfileAPICheck && (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+#endif
+
+ localBuilder = new LocalBuilder(m_localCount, localType, m_methodBuilder);
+ // add the localType to local signature
+ m_localSignature.AddArgument(localType, pinned);
+ m_localCount++;
+ return localBuilder;
+ }
+
+ //
+ //
+ // Token resolution calls
+ //
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void Emit(OpCode opcode, MethodInfo meth)
+ {
+ if (meth == null)
+ throw new ArgumentNullException("meth");
+ Contract.EndContractBlock();
+
+ int stackchange = 0;
+ int token = 0;
+ DynamicMethod dynMeth = meth as DynamicMethod;
+ if (dynMeth == null)
+ {
+ RuntimeMethodInfo rtMeth = meth as RuntimeMethodInfo;
+ if (rtMeth == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "meth");
+
+ RuntimeType declaringType = rtMeth.GetRuntimeType();
+ if (declaringType != null && (declaringType.IsGenericType || declaringType.IsArray))
+ token = GetTokenFor(rtMeth, declaringType);
+ else
+ token = GetTokenFor(rtMeth);
+ }
+ else
+ {
+ // rule out not allowed operations on DynamicMethods
+ if (opcode.Equals(OpCodes.Ldtoken) || opcode.Equals(OpCodes.Ldftn) || opcode.Equals(OpCodes.Ldvirtftn))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOpCodeOnDynamicMethod"));
+ }
+ token = GetTokenFor(dynMeth);
+ }
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ if (opcode.StackBehaviourPush == StackBehaviour.Varpush
+ && meth.ReturnType != typeof(void))
+ {
+ stackchange++;
+ }
+ if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
+ {
+ stackchange -= meth.GetParametersNoCopy().Length;
+ }
+ // Pop the "this" parameter if the method is non-static,
+ // and the instruction is not newobj/ldtoken/ldftn.
+ if (!meth.IsStatic &&
+ !(opcode.Equals(OpCodes.Newobj) || opcode.Equals(OpCodes.Ldtoken) || opcode.Equals(OpCodes.Ldftn)))
+ {
+ stackchange--;
+ }
+
+ UpdateStackSize(opcode, stackchange);
+
+ PutInteger4(token);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override void Emit(OpCode opcode, ConstructorInfo con)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ Contract.EndContractBlock();
+
+ RuntimeConstructorInfo rtConstructor = con as RuntimeConstructorInfo;
+ if (rtConstructor == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "con");
+
+ RuntimeType declaringType = rtConstructor.GetRuntimeType();
+ int token;
+
+ if (declaringType != null && (declaringType.IsGenericType || declaringType.IsArray))
+ // need to sort out the stack size story
+ token = GetTokenFor(rtConstructor, declaringType);
+ else
+ token = GetTokenFor(rtConstructor);
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // need to sort out the stack size story
+ UpdateStackSize(opcode, 1);
+
+ PutInteger4(token);
+ }
+
+ public override void Emit(OpCode opcode, Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = type as RuntimeType;
+
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ int token = GetTokenFor(rtType);
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ PutInteger4(token);
+ }
+
+ public override void Emit(OpCode opcode, FieldInfo field)
+ {
+ if (field == null)
+ throw new ArgumentNullException("field");
+ Contract.EndContractBlock();
+
+ RuntimeFieldInfo runtimeField = field as RuntimeFieldInfo;
+ if (runtimeField == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), "field");
+
+ int token;
+ if (field.DeclaringType == null)
+ token = GetTokenFor(runtimeField);
+ else
+ token = GetTokenFor(runtimeField, runtimeField.GetRuntimeType());
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ PutInteger4(token);
+ }
+
+ public override void Emit(OpCode opcode, String str)
+ {
+ if (str == null)
+ throw new ArgumentNullException("str");
+ Contract.EndContractBlock();
+
+ int tempVal = GetTokenForString(str);
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ PutInteger4(tempVal);
+ }
+
+ //
+ //
+ // Signature related calls (vararg, calli)
+ //
+ //
+ [System.Security.SecuritySafeCritical] // overrides SC
+ public override void EmitCalli(OpCode opcode,
+ CallingConventions callingConvention,
+ Type returnType,
+ Type[] parameterTypes,
+ Type[] optionalParameterTypes)
+ {
+ int stackchange = 0;
+ SignatureHelper sig;
+ if (optionalParameterTypes != null)
+ if ((callingConvention & CallingConventions.VarArgs) == 0)
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
+
+ sig = GetMemberRefSignature(callingConvention,
+ returnType,
+ parameterTypes,
+ optionalParameterTypes);
+
+ EnsureCapacity(7);
+ Emit(OpCodes.Calli);
+
+ // If there is a non-void return type, push one.
+ if (returnType != typeof(void))
+ stackchange++;
+ // Pop off arguments if any.
+ if (parameterTypes != null)
+ stackchange -= parameterTypes.Length;
+ // Pop off vararg arguments.
+ if (optionalParameterTypes != null)
+ stackchange -= optionalParameterTypes.Length;
+ // Pop the this parameter if the method has a this parameter.
+ if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
+ stackchange--;
+ // Pop the native function pointer.
+ stackchange--;
+ UpdateStackSize(OpCodes.Calli, stackchange);
+
+ int token = GetTokenForSig(sig.GetSignature(true));
+ PutInteger4(token);
+ }
+
+ public override void EmitCalli(OpCode opcode,
+ CallingConvention unmanagedCallConv,
+ Type returnType,
+ Type[] parameterTypes)
+ {
+ int stackchange = 0;
+ int cParams = 0;
+ int i;
+ SignatureHelper sig;
+
+ if (parameterTypes != null)
+ cParams = parameterTypes.Length;
+
+ sig = SignatureHelper.GetMethodSigHelper(unmanagedCallConv, returnType);
+
+ if (parameterTypes != null)
+ for (i = 0; i < cParams; i++)
+ sig.AddArgument(parameterTypes[i]);
+
+ // If there is a non-void return type, push one.
+ if (returnType != typeof(void))
+ stackchange++;
+
+ // Pop off arguments if any.
+ if (parameterTypes != null)
+ stackchange -= cParams;
+
+ // Pop the native function pointer.
+ stackchange--;
+ UpdateStackSize(OpCodes.Calli, stackchange);
+
+ EnsureCapacity(7);
+ Emit(OpCodes.Calli);
+ int token = GetTokenForSig(sig.GetSignature(true));
+ PutInteger4(token);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
+ {
+ if (methodInfo == null)
+ throw new ArgumentNullException("methodInfo");
+
+ if (!(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), "opcode");
+
+ if (methodInfo.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo");
+
+ if (methodInfo.DeclaringType != null && methodInfo.DeclaringType.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "methodInfo");
+ Contract.EndContractBlock();
+
+ int tk;
+ int stackchange = 0;
+
+ tk = GetMemberRefToken(methodInfo, optionalParameterTypes);
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // Push the return value if there is one.
+ if (methodInfo.ReturnType != typeof(void))
+ stackchange++;
+ // Pop the parameters.
+ stackchange -= methodInfo.GetParameterTypes().Length;
+ // Pop the this parameter if the method is non-static and the
+ // instruction is not newobj.
+ if (!(methodInfo is SymbolMethod) && methodInfo.IsStatic == false && !(opcode.Equals(OpCodes.Newobj)))
+ stackchange--;
+ // Pop the optional parameters off the stack.
+ if (optionalParameterTypes != null)
+ stackchange -= optionalParameterTypes.Length;
+ UpdateStackSize(opcode, stackchange);
+
+ PutInteger4(tk);
+ }
+
+ public override void Emit(OpCode opcode, SignatureHelper signature)
+ {
+ if (signature == null)
+ throw new ArgumentNullException("signature");
+ Contract.EndContractBlock();
+
+ int stackchange = 0;
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // The only IL instruction that has VarPop behaviour, that takes a
+ // Signature token as a parameter is calli. Pop the parameters and
+ // the native function pointer. To be conservative, do not pop the
+ // this pointer since this information is not easily derived from
+ // SignatureHelper.
+ if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
+ {
+ Contract.Assert(opcode.Equals(OpCodes.Calli),
+ "Unexpected opcode encountered for StackBehaviour VarPop.");
+ // Pop the arguments..
+ stackchange -= signature.ArgumentCount;
+ // Pop native function pointer off the stack.
+ stackchange--;
+ UpdateStackSize(opcode, stackchange);
+ }
+
+ int token = GetTokenForSig(signature.GetSignature(true)); ;
+ PutInteger4(token);
+ }
+
+ //
+ //
+ // Exception related generation
+ //
+ //
+ public override Label BeginExceptionBlock()
+ {
+ return base.BeginExceptionBlock();
+ }
+
+ public override void EndExceptionBlock()
+ {
+ base.EndExceptionBlock();
+ }
+
+ public override void BeginExceptFilterBlock()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ public override void BeginCatchBlock(Type exceptionType)
+ {
+ if (CurrExcStackCount == 0)
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+ Contract.EndContractBlock();
+
+ __ExceptionInfo current = CurrExcStack[CurrExcStackCount - 1];
+
+ RuntimeType rtType = exceptionType as RuntimeType;
+
+ if (current.GetCurrentState() == __ExceptionInfo.State_Filter)
+ {
+ if (exceptionType != null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ShouldNotSpecifyExceptionType"));
+ }
+
+ this.Emit(OpCodes.Endfilter);
+ }
+ else
+ {
+ // execute this branch if previous clause is Catch or Fault
+ if (exceptionType == null)
+ throw new ArgumentNullException("exceptionType");
+
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ Label endLabel = current.GetEndLabel();
+ this.Emit(OpCodes.Leave, endLabel);
+
+ // if this is a catch block the exception will be pushed on the stack and we need to update the stack info
+ UpdateStackSize(OpCodes.Nop, 1);
+ }
+
+ current.MarkCatchAddr(ILOffset, exceptionType);
+
+
+ // this is relying on too much implementation details of the base and so it's highly breaking
+ // Need to have a more integreted story for exceptions
+ current.m_filterAddr[current.m_currentCatch - 1] = GetTokenFor(rtType);
+ }
+
+ public override void BeginFaultBlock()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ public override void BeginFinallyBlock()
+ {
+ base.BeginFinallyBlock();
+ }
+
+ //
+ //
+ // debugger related calls.
+ //
+ //
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void UsingNamespace(String ns)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public override void MarkSequencePoint(ISymbolDocumentWriter document,
+ int startLine,
+ int startColumn,
+ int endLine,
+ int endColumn)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ public override void BeginScope()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ public override void EndScope()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefToken(MethodBase methodInfo, Type[] optionalParameterTypes)
+ {
+ Type[] parameterTypes;
+
+ if (optionalParameterTypes != null && (methodInfo.CallingConvention & CallingConventions.VarArgs) == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
+
+ RuntimeMethodInfo rtMeth = methodInfo as RuntimeMethodInfo;
+ DynamicMethod dm = methodInfo as DynamicMethod;
+
+ if (rtMeth == null && dm == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "methodInfo");
+
+ ParameterInfo[] paramInfo = methodInfo.GetParametersNoCopy();
+ if (paramInfo != null && paramInfo.Length != 0)
+ {
+ parameterTypes = new Type[paramInfo.Length];
+ for (int i = 0; i < paramInfo.Length; i++)
+ parameterTypes[i] = paramInfo[i].ParameterType;
+ }
+ else
+ {
+ parameterTypes = null;
+ }
+
+ SignatureHelper sig = GetMemberRefSignature(methodInfo.CallingConvention,
+ MethodBuilder.GetMethodBaseReturnType(methodInfo),
+ parameterTypes,
+ optionalParameterTypes);
+
+ if (rtMeth != null)
+ return GetTokenForVarArgMethod(rtMeth, sig);
+ else
+ return GetTokenForVarArgMethod(dm, sig);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override SignatureHelper GetMemberRefSignature(
+ CallingConventions call,
+ Type returnType,
+ Type[] parameterTypes,
+ Type[] optionalParameterTypes)
+ {
+ int cParams;
+ int i;
+ SignatureHelper sig;
+ if (parameterTypes == null)
+ cParams = 0;
+ else
+ cParams = parameterTypes.Length;
+ sig = SignatureHelper.GetMethodSigHelper(call, returnType);
+ for (i = 0; i < cParams; i++)
+ sig.AddArgument(parameterTypes[i]);
+ if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
+ {
+ // add the sentinel
+ sig.AddSentinel();
+ for (i = 0; i < optionalParameterTypes.Length; i++)
+ sig.AddArgument(optionalParameterTypes[i]);
+ }
+ return sig;
+ }
+
+ internal override void RecordTokenFixup()
+ {
+ // DynamicMethod doesn't need fixup.
+ }
+
+ #region GetTokenFor helpers
+ private int GetTokenFor(RuntimeType rtType)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck && (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+#endif
+
+ return m_scope.GetTokenFor(rtType.TypeHandle);
+ }
+
+ private int GetTokenFor(RuntimeFieldInfo runtimeField)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck)
+ {
+ RtFieldInfo rtField = runtimeField as RtFieldInfo;
+ if (rtField != null && (rtField.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtField.FullName));
+ }
+#endif
+
+ return m_scope.GetTokenFor(runtimeField.FieldHandle);
+ }
+
+ private int GetTokenFor(RuntimeFieldInfo runtimeField, RuntimeType rtType)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck)
+ {
+ RtFieldInfo rtField = runtimeField as RtFieldInfo;
+ if (rtField != null && (rtField.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtField.FullName));
+
+ if ((rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+ }
+#endif
+
+ return m_scope.GetTokenFor(runtimeField.FieldHandle, rtType.TypeHandle);
+ }
+
+ private int GetTokenFor(RuntimeConstructorInfo rtMeth)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck && (rtMeth.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtMeth.FullName));
+#endif
+
+ return m_scope.GetTokenFor(rtMeth.MethodHandle);
+ }
+
+ private int GetTokenFor(RuntimeConstructorInfo rtMeth, RuntimeType rtType)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck)
+ {
+ if ((rtMeth.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtMeth.FullName));
+
+ if ((rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+ }
+#endif
+
+ return m_scope.GetTokenFor(rtMeth.MethodHandle, rtType.TypeHandle);
+ }
+
+ private int GetTokenFor(RuntimeMethodInfo rtMeth)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck && (rtMeth.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtMeth.FullName));
+#endif
+
+ return m_scope.GetTokenFor(rtMeth.MethodHandle);
+ }
+
+ private int GetTokenFor(RuntimeMethodInfo rtMeth, RuntimeType rtType)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck)
+ {
+ if ((rtMeth.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtMeth.FullName));
+
+ if ((rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+ }
+#endif
+
+ return m_scope.GetTokenFor(rtMeth.MethodHandle, rtType.TypeHandle);
+ }
+
+ private int GetTokenFor(DynamicMethod dm)
+ {
+ return m_scope.GetTokenFor(dm);
+ }
+
+ private int GetTokenForVarArgMethod(RuntimeMethodInfo rtMeth, SignatureHelper sig)
+ {
+#if FEATURE_APPX
+ if (ProfileAPICheck && (rtMeth.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtMeth.FullName));
+#endif
+ VarArgMethod varArgMeth = new VarArgMethod(rtMeth, sig);
+ return m_scope.GetTokenFor(varArgMeth);
+ }
+
+ private int GetTokenForVarArgMethod(DynamicMethod dm, SignatureHelper sig)
+ {
+ VarArgMethod varArgMeth = new VarArgMethod(dm, sig);
+ return m_scope.GetTokenFor(varArgMeth);
+ }
+
+ private int GetTokenForString(String s)
+ {
+ return m_scope.GetTokenFor(s);
+ }
+
+ private int GetTokenForSig(byte[] sig)
+ {
+ return m_scope.GetTokenFor(sig);
+ }
+ #endregion
+
+ }
+
+ internal class DynamicResolver : Resolver
+ {
+ #region Private Data Members
+ private __ExceptionInfo[] m_exceptions;
+ private byte[] m_exceptionHeader;
+ private DynamicMethod m_method;
+ private byte[] m_code;
+ private byte[] m_localSignature;
+ private int m_stackSize;
+ private DynamicScope m_scope;
+ #endregion
+
+ #region Internal Methods
+ internal DynamicResolver(DynamicILGenerator ilGenerator)
+ {
+ m_stackSize = ilGenerator.GetMaxStackSize();
+ m_exceptions = ilGenerator.GetExceptions();
+ m_code = ilGenerator.BakeByteArray();
+ m_localSignature = ilGenerator.m_localSignature.InternalGetSignatureArray();
+ m_scope = ilGenerator.m_scope;
+
+ m_method = (DynamicMethod)ilGenerator.m_methodBuilder;
+ m_method.m_resolver = this;
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ internal DynamicResolver(DynamicILInfo dynamicILInfo)
+ {
+ m_stackSize = dynamicILInfo.MaxStackSize;
+ m_code = dynamicILInfo.Code;
+ m_localSignature = dynamicILInfo.LocalSignature;
+ m_exceptionHeader = dynamicILInfo.Exceptions;
+ //m_exceptions = dynamicILInfo.Exceptions;
+ m_scope = dynamicILInfo.DynamicScope;
+
+ m_method = dynamicILInfo.DynamicMethod;
+ m_method.m_resolver = this;
+ }
+
+ //
+ // We can destroy the unmanaged part of dynamic method only after the managed part is definitely gone and thus
+ // nobody can call the dynamic method anymore. A call to finalizer alone does not guarantee that the managed
+ // part is gone. A malicious code can keep a reference to DynamicMethod in long weak reference that survives finalization,
+ // or we can be running during shutdown where everything is finalized.
+ //
+ // The unmanaged resolver keeps a reference to the managed resolver in long weak handle. If the long weak handle
+ // is null, we can be sure that the managed part of the dynamic method is definitely gone and that it is safe to
+ // destroy the unmanaged part. (Note that the managed finalizer has to be on the same object that the long weak handle
+ // points to in order for this to work.) Unfortunately, we can not perform the above check when out finalizer
+ // is called - the long weak handle won't be cleared yet. Instead, we create a helper scout object that will attempt
+ // to do the destruction after next GC.
+ //
+ // The finalization does not have to be done using CriticalFinalizerObject. We have to go over all DynamicMethodDescs
+ // during AppDomain shutdown anyway to avoid leaks e.g. if somebody stores reference to DynamicMethod in static.
+ //
+ ~DynamicResolver()
+ {
+ DynamicMethod method = m_method;
+
+ if (method == null)
+ return;
+
+ if (method.m_methodHandle == null)
+ return;
+
+ DestroyScout scout = null;
+ try
+ {
+ scout = new DestroyScout();
+ }
+ catch
+ {
+ // We go over all DynamicMethodDesc during AppDomain shutdown and make sure
+ // that everything associated with them is released. So it is ok to skip reregistration
+ // for finalization during appdomain shutdown
+ if (!Environment.HasShutdownStarted &&
+ !AppDomain.CurrentDomain.IsFinalizingForUnload())
+ {
+ // Try again later.
+ GC.ReRegisterForFinalize(this);
+ }
+ return;
+ }
+
+ // We can never ever have two active destroy scouts for the same method. We need to initialize the scout
+ // outside the try/reregister block to avoid possibility of reregistration for finalization with active scout.
+ scout.m_methodHandle = method.m_methodHandle.Value;
+ }
+
+ private class DestroyScout
+ {
+ internal RuntimeMethodHandleInternal m_methodHandle;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ ~DestroyScout()
+ {
+ if (m_methodHandle.IsNullHandle())
+ return;
+
+ // It is not safe to destroy the method if the managed resolver is alive.
+ if (RuntimeMethodHandle.GetResolver(m_methodHandle) != null)
+ {
+ if (!Environment.HasShutdownStarted &&
+ !AppDomain.CurrentDomain.IsFinalizingForUnload())
+ {
+ // Somebody might have been holding a reference on us via weak handle.
+ // We will keep trying. It will be hopefully released eventually.
+ GC.ReRegisterForFinalize(this);
+ }
+ return;
+ }
+
+ RuntimeMethodHandle.Destroy(m_methodHandle);
+ }
+ }
+
+ // Keep in sync with vm/dynamicmethod.h
+ [Flags]
+ internal enum SecurityControlFlags
+ {
+ Default = 0x0,
+ SkipVisibilityChecks = 0x1,
+ RestrictedSkipVisibilityChecks = 0x2,
+ HasCreationContext = 0x4,
+ CanSkipCSEvaluation = 0x8,
+ }
+
+ internal override RuntimeType GetJitContext(ref int securityControlFlags)
+ {
+ RuntimeType typeOwner;
+
+ SecurityControlFlags flags = SecurityControlFlags.Default;
+
+ if (m_method.m_restrictedSkipVisibility)
+ flags |= SecurityControlFlags.RestrictedSkipVisibilityChecks;
+ else if (m_method.m_skipVisibility)
+ flags |= SecurityControlFlags.SkipVisibilityChecks;
+
+ typeOwner = m_method.m_typeOwner;
+
+#if FEATURE_COMPRESSEDSTACK
+ if (m_method.m_creationContext != null)
+ {
+ flags |= SecurityControlFlags.HasCreationContext;
+ if(m_method.m_creationContext.CanSkipEvaluation)
+ {
+ flags |= SecurityControlFlags.CanSkipCSEvaluation;
+ }
+ }
+
+#endif // FEATURE_COMPRESSEDSTACK
+
+ securityControlFlags = (int)flags;
+
+ return typeOwner;
+ }
+
+ private static int CalculateNumberOfExceptions(__ExceptionInfo[] excp)
+ {
+ int num = 0;
+ if (excp == null)
+ return 0;
+ for (int i = 0; i < excp.Length; i++)
+ num += excp[i].GetNumberOfCatches();
+ return num;
+ }
+
+ internal override byte[] GetCodeInfo(
+ ref int stackSize, ref int initLocals, ref int EHCount)
+ {
+ stackSize = m_stackSize;
+ if (m_exceptionHeader != null && m_exceptionHeader.Length != 0)
+ {
+ if (m_exceptionHeader.Length < 4)
+ throw new FormatException();
+
+ byte header = m_exceptionHeader[0];
+
+ if ((header & 0x40) != 0) // Fat
+ {
+ byte[] size = new byte[4];
+ for (int q = 0; q < 3; q++)
+ size[q] = m_exceptionHeader[q + 1];
+ EHCount = (BitConverter.ToInt32(size, 0) - 4) / 24;
+ }
+ else
+ EHCount = (m_exceptionHeader[1] - 2) / 12;
+ }
+ else
+ {
+ EHCount = CalculateNumberOfExceptions(m_exceptions);
+ }
+ initLocals = (m_method.InitLocals) ? 1 : 0;
+ return m_code;
+ }
+
+ internal override byte[] GetLocalsSignature()
+ {
+ return m_localSignature;
+ }
+
+ internal override unsafe byte[] GetRawEHInfo()
+ {
+ return m_exceptionHeader;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe void GetEHInfo(int excNumber, void* exc)
+ {
+ CORINFO_EH_CLAUSE* exception = (CORINFO_EH_CLAUSE*)exc;
+ for (int i = 0; i < m_exceptions.Length; i++)
+ {
+ int excCount = m_exceptions[i].GetNumberOfCatches();
+ if (excNumber < excCount)
+ {
+ // found the right exception block
+ exception->Flags = m_exceptions[i].GetExceptionTypes()[excNumber];
+ exception->TryOffset = m_exceptions[i].GetStartAddress();
+ if ((exception->Flags & __ExceptionInfo.Finally) != __ExceptionInfo.Finally)
+ exception->TryLength = m_exceptions[i].GetEndAddress() - exception->TryOffset;
+ else
+ exception->TryLength = m_exceptions[i].GetFinallyEndAddress() - exception->TryOffset;
+ exception->HandlerOffset = m_exceptions[i].GetCatchAddresses()[excNumber];
+ exception->HandlerLength = m_exceptions[i].GetCatchEndAddresses()[excNumber] - exception->HandlerOffset;
+ // this is cheating because the filter address is the token of the class only for light code gen
+ exception->ClassTokenOrFilterOffset = m_exceptions[i].GetFilterAddresses()[excNumber];
+ break;
+ }
+ excNumber -= excCount;
+ }
+ }
+
+ internal override String GetStringLiteral(int token) { return m_scope.GetString(token); }
+
+#if FEATURE_COMPRESSEDSTACK
+ internal override CompressedStack GetSecurityContext()
+ {
+ return m_method.m_creationContext;
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+
+ [System.Security.SecurityCritical]
+ internal override void ResolveToken(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle)
+ {
+ typeHandle = new IntPtr();
+ methodHandle = new IntPtr();
+ fieldHandle = new IntPtr();
+
+ Object handle = m_scope[token];
+
+ if (handle == null)
+ throw new InvalidProgramException();
+
+ if (handle is RuntimeTypeHandle)
+ {
+ typeHandle = ((RuntimeTypeHandle)handle).Value;
+ return;
+ }
+
+ if (handle is RuntimeMethodHandle)
+ {
+ methodHandle = ((RuntimeMethodHandle)handle).Value;
+ return;
+ }
+
+ if (handle is RuntimeFieldHandle)
+ {
+ fieldHandle = ((RuntimeFieldHandle)handle).Value;
+ return;
+ }
+
+ DynamicMethod dm = handle as DynamicMethod;
+ if (dm != null)
+ {
+ methodHandle = dm.GetMethodDescriptor().Value;
+ return;
+ }
+
+ GenericMethodInfo gmi = handle as GenericMethodInfo;
+ if (gmi != null)
+ {
+ methodHandle = gmi.m_methodHandle.Value;
+ typeHandle = gmi.m_context.Value;
+ return;
+ }
+
+ GenericFieldInfo gfi = handle as GenericFieldInfo;
+ if (gfi != null)
+ {
+ fieldHandle = gfi.m_fieldHandle.Value;
+ typeHandle = gfi.m_context.Value;
+ return;
+ }
+
+ VarArgMethod vaMeth = handle as VarArgMethod;
+ if (vaMeth != null)
+ {
+ if (vaMeth.m_dynamicMethod == null)
+ {
+ methodHandle = vaMeth.m_method.MethodHandle.Value;
+ typeHandle = vaMeth.m_method.GetDeclaringTypeInternal().GetTypeHandleInternal().Value;
+ }
+ else
+ methodHandle = vaMeth.m_dynamicMethod.GetMethodDescriptor().Value;
+
+ return;
+ }
+ }
+
+ internal override byte[] ResolveSignature(int token, int fromMethod)
+ {
+ return m_scope.ResolveSignature(token, fromMethod);
+ }
+
+ internal override MethodInfo GetDynamicMethod()
+ {
+ return m_method.GetMethodInfo();
+ }
+ #endregion
+ }
+
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class DynamicILInfo
+ {
+ #region Private Data Members
+ private DynamicMethod m_method;
+ private DynamicScope m_scope;
+ private byte[] m_exceptions;
+ private byte[] m_code;
+ private byte[] m_localSignature;
+ private int m_maxStackSize;
+ private int m_methodSignature;
+ #endregion
+
+ #region Constructor
+ internal DynamicILInfo(DynamicScope scope, DynamicMethod method, byte[] methodSignature)
+ {
+ m_method = method;
+ m_scope = scope;
+ m_methodSignature = m_scope.GetTokenFor(methodSignature);
+ m_exceptions = EmptyArray<Byte>.Value;
+ m_code = EmptyArray<Byte>.Value;
+ m_localSignature = EmptyArray<Byte>.Value;
+ }
+ #endregion
+
+ #region Internal Methods
+ [System.Security.SecurityCritical] // auto-generated
+ internal void GetCallableMethod(RuntimeModule module, DynamicMethod dm)
+ {
+ dm.m_methodHandle = ModuleHandle.GetDynamicMethod(dm,
+ module, m_method.Name, (byte[])m_scope[m_methodSignature], new DynamicResolver(this));
+ }
+
+ internal byte[] LocalSignature
+ {
+ get
+ {
+ if (m_localSignature == null)
+ m_localSignature = SignatureHelper.GetLocalVarSigHelper().InternalGetSignatureArray();
+
+ return m_localSignature;
+ }
+ }
+ internal byte[] Exceptions { get { return m_exceptions; } }
+ internal byte[] Code { get { return m_code; } }
+ internal int MaxStackSize { get { return m_maxStackSize; } }
+ #endregion
+
+ #region Public ILGenerator Methods
+ public DynamicMethod DynamicMethod { get { return m_method; } }
+ internal DynamicScope DynamicScope { get { return m_scope; } }
+
+ public void SetCode(byte[] code, int maxStackSize)
+ {
+ m_code = (code != null) ? (byte[])code.Clone() : EmptyArray<Byte>.Value;
+ m_maxStackSize = maxStackSize;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe void SetCode(byte* code, int codeSize, int maxStackSize)
+ {
+ if (codeSize < 0)
+ throw new ArgumentOutOfRangeException("codeSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+
+ if (codeSize > 0 && code == null)
+ throw new ArgumentNullException("code");
+ Contract.EndContractBlock();
+
+ m_code = new byte[codeSize];
+ for (int i = 0; i < codeSize; i++)
+ {
+ m_code[i] = *code;
+ code++;
+ }
+
+ m_maxStackSize = maxStackSize;
+ }
+
+ public void SetExceptions(byte[] exceptions)
+ {
+ m_exceptions = (exceptions != null) ? (byte[])exceptions.Clone() : EmptyArray<Byte>.Value;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe void SetExceptions(byte* exceptions, int exceptionsSize)
+ {
+ if (exceptionsSize < 0)
+ throw new ArgumentOutOfRangeException("exceptionsSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+
+ if (exceptionsSize > 0 && exceptions == null)
+ throw new ArgumentNullException("exceptions");
+ Contract.EndContractBlock();
+
+ m_exceptions = new byte[exceptionsSize];
+
+ for (int i = 0; i < exceptionsSize; i++)
+ {
+ m_exceptions[i] = *exceptions;
+ exceptions++;
+ }
+ }
+
+ public void SetLocalSignature(byte[] localSignature)
+ {
+ m_localSignature = (localSignature != null) ? (byte[])localSignature.Clone() : EmptyArray<Byte>.Value;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe void SetLocalSignature(byte* localSignature, int signatureSize)
+ {
+ if (signatureSize < 0)
+ throw new ArgumentOutOfRangeException("signatureSize", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+
+ if (signatureSize > 0 && localSignature == null)
+ throw new ArgumentNullException("localSignature");
+ Contract.EndContractBlock();
+
+ m_localSignature = new byte[signatureSize];
+ for (int i = 0; i < signatureSize; i++)
+ {
+ m_localSignature[i] = *localSignature;
+ localSignature++;
+ }
+ }
+ #endregion
+
+ #region Public Scope Methods
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int GetTokenFor(RuntimeMethodHandle method)
+ {
+ return DynamicScope.GetTokenFor(method);
+ }
+ public int GetTokenFor(DynamicMethod method)
+ {
+ return DynamicScope.GetTokenFor(method);
+ }
+ public int GetTokenFor(RuntimeMethodHandle method, RuntimeTypeHandle contextType)
+ {
+ return DynamicScope.GetTokenFor(method, contextType);
+ }
+ public int GetTokenFor(RuntimeFieldHandle field)
+ {
+ return DynamicScope.GetTokenFor(field);
+ }
+ public int GetTokenFor(RuntimeFieldHandle field, RuntimeTypeHandle contextType)
+ {
+ return DynamicScope.GetTokenFor(field, contextType);
+ }
+ public int GetTokenFor(RuntimeTypeHandle type)
+ {
+ return DynamicScope.GetTokenFor(type);
+ }
+ public int GetTokenFor(string literal)
+ {
+ return DynamicScope.GetTokenFor(literal);
+ }
+ public int GetTokenFor(byte[] signature)
+ {
+ return DynamicScope.GetTokenFor(signature);
+ }
+ #endregion
+ }
+
+ internal class DynamicScope
+ {
+ #region Private Data Members
+ internal List<Object> m_tokens;
+ #endregion
+
+ #region Constructor
+ internal unsafe DynamicScope()
+ {
+ m_tokens = new List<Object>();
+ m_tokens.Add(null);
+ }
+ #endregion
+
+ #region Internal Methods
+ internal object this[int token]
+ {
+ get
+ {
+ token &= 0x00FFFFFF;
+
+ if (token < 0 || token > m_tokens.Count)
+ return null;
+
+ return m_tokens[token];
+ }
+ }
+
+ internal int GetTokenFor(VarArgMethod varArgMethod)
+ {
+ m_tokens.Add(varArgMethod);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.MemberRef;
+ }
+ internal string GetString(int token) { return this[token] as string; }
+
+ internal byte[] ResolveSignature(int token, int fromMethod)
+ {
+ if (fromMethod == 0)
+ return (byte[])this[token];
+
+ VarArgMethod vaMethod = this[token] as VarArgMethod;
+
+ if (vaMethod == null)
+ return null;
+
+ return vaMethod.m_signature.GetSignature(true);
+ }
+ #endregion
+
+ #region Public Methods
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int GetTokenFor(RuntimeMethodHandle method)
+ {
+ IRuntimeMethodInfo methodReal = method.GetMethodInfo();
+ RuntimeMethodHandleInternal rmhi = methodReal.Value;
+
+ if (methodReal != null && !RuntimeMethodHandle.IsDynamicMethod(rmhi))
+ {
+ RuntimeType type = RuntimeMethodHandle.GetDeclaringType(rmhi);
+ if ((type != null) && RuntimeTypeHandle.HasInstantiation(type))
+ {
+ // Do we really need to retrieve this much info just to throw an exception?
+ MethodBase m = RuntimeType.GetMethodBase(methodReal);
+ Type t = m.DeclaringType.GetGenericTypeDefinition();
+
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_MethodDeclaringTypeGenericLcg"), m, t));
+ }
+ }
+
+ m_tokens.Add(method);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.MethodDef;
+ }
+ public int GetTokenFor(RuntimeMethodHandle method, RuntimeTypeHandle typeContext)
+ {
+ m_tokens.Add(new GenericMethodInfo(method, typeContext));
+ return m_tokens.Count - 1 | (int)MetadataTokenType.MethodDef;
+ }
+ public int GetTokenFor(DynamicMethod method)
+ {
+ m_tokens.Add(method);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.MethodDef;
+ }
+ public int GetTokenFor(RuntimeFieldHandle field)
+ {
+ m_tokens.Add(field);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.FieldDef;
+ }
+ public int GetTokenFor(RuntimeFieldHandle field, RuntimeTypeHandle typeContext)
+ {
+ m_tokens.Add(new GenericFieldInfo(field, typeContext));
+ return m_tokens.Count - 1 | (int)MetadataTokenType.FieldDef;
+ }
+ public int GetTokenFor(RuntimeTypeHandle type)
+ {
+ m_tokens.Add(type);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.TypeDef;
+ }
+ public int GetTokenFor(string literal)
+ {
+ m_tokens.Add(literal);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.String;
+ }
+ public int GetTokenFor(byte[] signature)
+ {
+ m_tokens.Add(signature);
+ return m_tokens.Count - 1 | (int)MetadataTokenType.Signature;
+ }
+ #endregion
+ }
+
+ internal sealed class GenericMethodInfo
+ {
+ internal RuntimeMethodHandle m_methodHandle;
+ internal RuntimeTypeHandle m_context;
+
+ internal GenericMethodInfo(RuntimeMethodHandle methodHandle, RuntimeTypeHandle context)
+ {
+ m_methodHandle = methodHandle;
+ m_context = context;
+ }
+ }
+
+ internal sealed class GenericFieldInfo
+ {
+ internal RuntimeFieldHandle m_fieldHandle;
+ internal RuntimeTypeHandle m_context;
+
+ internal GenericFieldInfo(RuntimeFieldHandle fieldHandle, RuntimeTypeHandle context)
+ {
+ m_fieldHandle = fieldHandle;
+ m_context = context;
+ }
+ }
+
+ internal sealed class VarArgMethod
+ {
+ internal RuntimeMethodInfo m_method;
+ internal DynamicMethod m_dynamicMethod;
+ internal SignatureHelper m_signature;
+
+ internal VarArgMethod(DynamicMethod dm, SignatureHelper signature)
+ {
+ m_dynamicMethod = dm;
+ m_signature = signature;
+ }
+
+ internal VarArgMethod(RuntimeMethodInfo method, SignatureHelper signature)
+ {
+ m_method = method;
+ m_signature = signature;
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs
new file mode 100644
index 0000000000..6f6b436706
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/DynamicMethod.cs
@@ -0,0 +1,1039 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Collections.Generic;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DynamicMethod : MethodInfo
+ {
+ private RuntimeType[] m_parameterTypes;
+ internal IRuntimeMethodInfo m_methodHandle;
+ private RuntimeType m_returnType;
+ private DynamicILGenerator m_ilGenerator;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ private DynamicILInfo m_DynamicILInfo;
+ private bool m_fInitLocals;
+ private RuntimeModule m_module;
+ internal bool m_skipVisibility;
+ internal RuntimeType m_typeOwner; // can be null
+
+ // We want the creator of the DynamicMethod to control who has access to the
+ // DynamicMethod (just like we do for delegates). However, a user can get to
+ // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
+ // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
+ // not be able to bound access to the DynamicMethod. Hence, we need to ensure that
+ // we do not allow direct use of RTDynamicMethod.
+ private RTDynamicMethod m_dynMethod;
+
+ // needed to keep the object alive during jitting
+ // assigned by the DynamicResolver ctor
+ internal DynamicResolver m_resolver;
+
+ // Always false unless we are in an immersive (non dev mode) process.
+#if FEATURE_APPX
+ private bool m_profileAPICheck;
+
+ private RuntimeAssembly m_creatorAssembly;
+#endif
+
+ internal bool m_restrictedSkipVisibility;
+ // The context when the method was created. We use this to do the RestrictedMemberAccess checks.
+ // These checks are done when the method is compiled. This can happen at an arbitrary time,
+ // when CreateDelegate or Invoke is called, or when another DynamicMethod executes OpCodes.Call.
+ // We capture the creation context so that we can do the checks against the same context,
+ // irrespective of when the method gets compiled. Note that the DynamicMethod does not know when
+ // it is ready for use since there is not API which indictates that IL generation has completed.
+#if FEATURE_COMPRESSEDSTACK
+ internal CompressedStack m_creationContext;
+#endif // FEATURE_COMPRESSEDSTACK
+ private static volatile InternalModuleBuilder s_anonymouslyHostedDynamicMethodsModule;
+ private static readonly object s_anonymouslyHostedDynamicMethodsModuleLock = new object();
+
+ //
+ // class initialization (ctor and init)
+ //
+
+ private DynamicMethod() { }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ null, // owner
+ null, // m
+ false, // skipVisibility
+ true,
+ ref stackMark); // transparentMethod
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes,
+ bool restrictedSkipVisibility)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ null, // owner
+ null, // m
+ restrictedSkipVisibility,
+ true,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes,
+ Module m) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(m, ref stackMark, false);
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ null, // owner
+ m, // m
+ false, // skipVisibility
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes,
+ Module m,
+ bool skipVisibility) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(m, ref stackMark, skipVisibility);
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ null, // owner
+ m, // m
+ skipVisibility,
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ MethodAttributes attributes,
+ CallingConventions callingConvention,
+ Type returnType,
+ Type[] parameterTypes,
+ Module m,
+ bool skipVisibility) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(m, ref stackMark, skipVisibility);
+ Init(name,
+ attributes,
+ callingConvention,
+ returnType,
+ parameterTypes,
+ null, // owner
+ m, // m
+ skipVisibility,
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes,
+ Type owner) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(owner, ref stackMark, false);
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ owner, // owner
+ null, // m
+ false, // skipVisibility
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ Type returnType,
+ Type[] parameterTypes,
+ Type owner,
+ bool skipVisibility) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(owner, ref stackMark, skipVisibility);
+ Init(name,
+ MethodAttributes.Public | MethodAttributes.Static,
+ CallingConventions.Standard,
+ returnType,
+ parameterTypes,
+ owner, // owner
+ null, // m
+ skipVisibility,
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public DynamicMethod(string name,
+ MethodAttributes attributes,
+ CallingConventions callingConvention,
+ Type returnType,
+ Type[] parameterTypes,
+ Type owner,
+ bool skipVisibility) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PerformSecurityCheck(owner, ref stackMark, skipVisibility);
+ Init(name,
+ attributes,
+ callingConvention,
+ returnType,
+ parameterTypes,
+ owner, // owner
+ null, // m
+ skipVisibility,
+ false,
+ ref stackMark); // transparentMethod
+ }
+
+ // helpers for intialization
+
+ static private void CheckConsistency(MethodAttributes attributes, CallingConventions callingConvention) {
+ // only static public for method attributes
+ if ((attributes & ~MethodAttributes.MemberAccessMask) != MethodAttributes.Static)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
+ if ((attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
+ Contract.EndContractBlock();
+
+ // only standard or varargs supported
+ if (callingConvention != CallingConventions.Standard && callingConvention != CallingConventions.VarArgs)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
+
+ // vararg is not supported at the moment
+ if (callingConvention == CallingConventions.VarArgs)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicMethodFlags"));
+ }
+
+ // We create a transparent assembly to host DynamicMethods. Since the assembly does not have any
+ // non-public fields (or any fields at all), it is a safe anonymous assembly to host DynamicMethods
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private static RuntimeModule GetDynamicMethodsModule()
+ {
+ if (s_anonymouslyHostedDynamicMethodsModule != null)
+ return s_anonymouslyHostedDynamicMethodsModule;
+
+ lock (s_anonymouslyHostedDynamicMethodsModuleLock)
+ {
+ if (s_anonymouslyHostedDynamicMethodsModule != null)
+ return s_anonymouslyHostedDynamicMethodsModule;
+
+ ConstructorInfo transparencyCtor = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes);
+ CustomAttributeBuilder transparencyAttribute = new CustomAttributeBuilder(transparencyCtor, EmptyArray<Object>.Value);
+ List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
+ assemblyAttributes.Add(transparencyAttribute);
+#if !FEATURE_CORECLR
+ // On the desktop, we need to use the security rule set level 1 for anonymously hosted
+ // dynamic methods. In level 2, transparency rules are strictly enforced, which leads to
+ // errors when a fully trusted application causes a dynamic method to be generated that tries
+ // to call a method with a LinkDemand or a SecurityCritical method. To retain compatibility
+ // with the v2.0 and v3.x frameworks, these calls should be allowed.
+ //
+ // If this rule set was not explicitly called out, then the anonymously hosted dynamic methods
+ // assembly would inherit the rule set from the creating assembly - which would cause it to
+ // be level 2 because mscorlib.dll is using the level 2 rules.
+ ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
+ CustomAttributeBuilder securityRulesAttribute =
+ new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level1 });
+ assemblyAttributes.Add(securityRulesAttribute);
+#endif // !FEATURE_CORECLR
+
+ AssemblyName assemblyName = new AssemblyName("Anonymously Hosted DynamicMethods Assembly");
+ StackCrawlMark stackMark = StackCrawlMark.LookForMe;
+
+ AssemblyBuilder assembly = AssemblyBuilder.InternalDefineDynamicAssembly(
+ assemblyName,
+ AssemblyBuilderAccess.Run,
+ null, null, null, null, null,
+ ref stackMark,
+ assemblyAttributes,
+ SecurityContextSource.CurrentAssembly);
+
+ AppDomain.PublishAnonymouslyHostedDynamicMethodsAssembly(assembly.GetNativeHandle());
+
+ // this always gets the internal module.
+ s_anonymouslyHostedDynamicMethodsModule = (InternalModuleBuilder)assembly.ManifestModule;
+ }
+
+ return s_anonymouslyHostedDynamicMethodsModule;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void Init(String name,
+ MethodAttributes attributes,
+ CallingConventions callingConvention,
+ Type returnType,
+ Type[] signature,
+ Type owner,
+ Module m,
+ bool skipVisibility,
+ bool transparentMethod,
+ ref StackCrawlMark stackMark)
+ {
+ DynamicMethod.CheckConsistency(attributes, callingConvention);
+
+ // check and store the signature
+ if (signature != null) {
+ m_parameterTypes = new RuntimeType[signature.Length];
+ for (int i = 0; i < signature.Length; i++) {
+ if (signature[i] == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
+ m_parameterTypes[i] = signature[i].UnderlyingSystemType as RuntimeType;
+ if ( m_parameterTypes[i] == null || !(m_parameterTypes[i] is RuntimeType) || m_parameterTypes[i] == (RuntimeType)typeof(void) )
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidTypeInSignature"));
+ }
+ }
+ else {
+ m_parameterTypes = Array.Empty<RuntimeType>();
+ }
+
+ // check and store the return value
+ m_returnType = (returnType == null) ? (RuntimeType)typeof(void) : returnType.UnderlyingSystemType as RuntimeType;
+ if ( (m_returnType == null) || !(m_returnType is RuntimeType) || m_returnType.IsByRef )
+ throw new NotSupportedException(Environment.GetResourceString("Arg_InvalidTypeInRetType"));
+
+ if (transparentMethod)
+ {
+ Contract.Assert(owner == null && m == null, "owner and m cannot be set for transparent methods");
+ m_module = GetDynamicMethodsModule();
+ if (skipVisibility)
+ {
+ m_restrictedSkipVisibility = true;
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ m_creationContext = CompressedStack.Capture();
+#endif // FEATURE_COMPRESSEDSTACK
+ }
+ else
+ {
+ Contract.Assert(m != null || owner != null, "PerformSecurityCheck should ensure that either m or owner is set");
+ Contract.Assert(m == null || !m.Equals(s_anonymouslyHostedDynamicMethodsModule), "The user cannot explicitly use this assembly");
+ Contract.Assert(m == null || owner == null, "m and owner cannot both be set");
+
+ if (m != null)
+ m_module = m.ModuleHandle.GetRuntimeModule(); // this returns the underlying module for all RuntimeModule and ModuleBuilder objects.
+ else
+ {
+ RuntimeType rtOwner = null;
+ if (owner != null)
+ rtOwner = owner.UnderlyingSystemType as RuntimeType;
+
+ if (rtOwner != null)
+ {
+ if (rtOwner.HasElementType || rtOwner.ContainsGenericParameters
+ || rtOwner.IsGenericParameter || rtOwner.IsInterface)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeForDynamicMethod"));
+
+ m_typeOwner = rtOwner;
+ m_module = rtOwner.GetRuntimeModule();
+ }
+ }
+
+ m_skipVisibility = skipVisibility;
+ }
+
+ // initialize remaining fields
+ m_ilGenerator = null;
+ m_fInitLocals = true;
+ m_methodHandle = null;
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+#if FEATURE_APPX
+ if (AppDomain.ProfileAPICheck)
+ {
+ if (m_creatorAssembly == null)
+ m_creatorAssembly = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+
+ if (m_creatorAssembly != null && !m_creatorAssembly.IsFrameworkAssembly())
+ m_profileAPICheck = true;
+ }
+#endif // FEATURE_APPX
+
+ m_dynMethod = new RTDynamicMethod(this, name, attributes, callingConvention);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void PerformSecurityCheck(Module m, ref StackCrawlMark stackMark, bool skipVisibility)
+ {
+ if (m == null)
+ throw new ArgumentNullException("m");
+ Contract.EndContractBlock();
+#if !FEATURE_CORECLR
+
+ RuntimeModule rtModule;
+ ModuleBuilder mb = m as ModuleBuilder;
+ if (mb != null)
+ rtModule = mb.InternalModule;
+ else
+ rtModule = m as RuntimeModule;
+
+ if (rtModule == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeModule"), "m");
+ }
+
+ // The user cannot explicitly use this assembly
+ if (rtModule == s_anonymouslyHostedDynamicMethodsModule)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidValue"), "m");
+
+ // ask for member access if skip visibility
+ if (skipVisibility)
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+
+#if !FEATURE_CORECLR
+ // ask for control evidence if outside of the caller assembly
+ RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
+ m_creatorAssembly = callingType.GetRuntimeAssembly();
+ if (m.Assembly != m_creatorAssembly)
+ {
+ // Demand the permissions of the assembly where the DynamicMethod will live
+ CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
+ m.Assembly.PermissionSet);
+ }
+#else //FEATURE_CORECLR
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+#pragma warning restore 618
+#endif //FEATURE_CORECLR
+#endif //!FEATURE_CORECLR
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void PerformSecurityCheck(Type owner, ref StackCrawlMark stackMark, bool skipVisibility)
+ {
+ if (owner == null)
+ throw new ArgumentNullException("owner");
+#if !FEATURE_CORECLR
+
+ RuntimeType rtOwner = owner as RuntimeType;
+ if (rtOwner == null)
+ rtOwner = owner.UnderlyingSystemType as RuntimeType;
+
+ if (rtOwner == null)
+ throw new ArgumentNullException("owner", Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ // get the type the call is coming from
+ RuntimeType callingType = RuntimeMethodHandle.GetCallerType(ref stackMark);
+
+ // ask for member access if skip visibility
+ if (skipVisibility)
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+ else
+ {
+ // if the call is not coming from the same class ask for member access
+ if (callingType != rtOwner)
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+ }
+#if !FEATURE_CORECLR
+ m_creatorAssembly = callingType.GetRuntimeAssembly();
+
+ // ask for control evidence if outside of the caller module
+ if (rtOwner.Assembly != m_creatorAssembly)
+ {
+ // Demand the permissions of the assembly where the DynamicMethod will live
+ CodeAccessSecurityEngine.ReflectionTargetDemandHelper(PermissionType.SecurityControlEvidence,
+ owner.Assembly.PermissionSet);
+ }
+#else //FEATURE_CORECLR
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+#pragma warning restore 618
+#endif //FEATURE_CORECLR
+#endif //!FEATURE_CORECLR
+ }
+
+ //
+ // Delegate and method creation
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed override Delegate CreateDelegate(Type delegateType) {
+ if (m_restrictedSkipVisibility)
+ {
+ // Compile the method since accessibility checks are done as part of compilation.
+ GetMethodDescriptor();
+ System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
+ }
+
+ MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, null, GetMethodDescriptor());
+ // stash this MethodInfo by brute force.
+ d.StoreDynamicMethod(GetMethodInfo());
+ return d;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed override Delegate CreateDelegate(Type delegateType, Object target) {
+ if (m_restrictedSkipVisibility)
+ {
+ // Compile the method since accessibility checks are done as part of compilation
+ GetMethodDescriptor();
+ System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(m_methodHandle);
+ }
+
+ MulticastDelegate d = (MulticastDelegate)Delegate.CreateDelegateNoSecurityCheck(delegateType, target, GetMethodDescriptor());
+ // stash this MethodInfo by brute force.
+ d.StoreDynamicMethod(GetMethodInfo());
+ return d;
+ }
+
+#if FEATURE_APPX
+ internal bool ProfileAPICheck
+ {
+ get
+ {
+ return m_profileAPICheck;
+ }
+
+ [FriendAccessAllowed]
+ set
+ {
+ m_profileAPICheck = value;
+ }
+ }
+#endif
+
+ // This is guaranteed to return a valid handle
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe RuntimeMethodHandle GetMethodDescriptor() {
+ if (m_methodHandle == null) {
+ lock (this) {
+ if (m_methodHandle == null) {
+ if (m_DynamicILInfo != null)
+ m_DynamicILInfo.GetCallableMethod(m_module, this);
+ else {
+ if (m_ilGenerator == null || m_ilGenerator.ILOffset == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadEmptyMethodBody", Name));
+
+ m_ilGenerator.GetCallableMethod(m_module, this);
+ }
+ }
+ }
+ }
+ return new RuntimeMethodHandle(m_methodHandle);
+ }
+
+ //
+ // MethodInfo api. They mostly forward to RTDynamicMethod
+ //
+
+ public override String ToString() { return m_dynMethod.ToString(); }
+
+ public override String Name { get { return m_dynMethod.Name; } }
+
+ public override Type DeclaringType { get { return m_dynMethod.DeclaringType; } }
+
+ public override Type ReflectedType { get { return m_dynMethod.ReflectedType; } }
+
+ public override Module Module { get { return m_dynMethod.Module; } }
+
+ // we cannot return a MethodHandle because we cannot track it via GC so this method is off limits
+ public override RuntimeMethodHandle MethodHandle { get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); } }
+
+ public override MethodAttributes Attributes { get { return m_dynMethod.Attributes; } }
+
+ public override CallingConventions CallingConvention { get { return m_dynMethod.CallingConvention; } }
+
+ public override MethodInfo GetBaseDefinition() { return this; }
+
+ [Pure]
+ public override ParameterInfo[] GetParameters() { return m_dynMethod.GetParameters(); }
+
+ public override MethodImplAttributes GetMethodImplementationFlags() { return m_dynMethod.GetMethodImplementationFlags(); }
+
+ //
+ // Security transparency accessors
+ //
+ // Since the dynamic method may not be JITed yet, we don't always have the runtime method handle
+ // which is needed to determine the official runtime transparency status of the dynamic method. We
+ // fall back to saying that the dynamic method matches the transparency of its containing module
+ // until we get a JITed version, since dynamic methods cannot have attributes of their own.
+ //
+
+ public override bool IsSecurityCritical
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if (m_methodHandle != null)
+ {
+ return RuntimeMethodHandle.IsSecurityCritical(m_methodHandle);
+ }
+ else if (m_typeOwner != null)
+ {
+ RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return assembly.IsAllSecurityCritical();
+ }
+ else
+ {
+ RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return assembly.IsAllSecurityCritical();
+ }
+ }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if (m_methodHandle != null)
+ {
+ return RuntimeMethodHandle.IsSecuritySafeCritical(m_methodHandle);
+ }
+ else if (m_typeOwner != null)
+ {
+ RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return assembly.IsAllPublicAreaSecuritySafeCritical();
+ }
+ else
+ {
+ RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return assembly.IsAllSecuritySafeCritical();
+ }
+ }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ if (m_methodHandle != null)
+ {
+ return RuntimeMethodHandle.IsSecurityTransparent(m_methodHandle);
+ }
+ else if (m_typeOwner != null)
+ {
+ RuntimeAssembly assembly = m_typeOwner.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return !assembly.IsAllSecurityCritical();
+ }
+ else
+ {
+ RuntimeAssembly assembly = m_module.Assembly as RuntimeAssembly;
+ Contract.Assert(assembly != null);
+
+ return !assembly.IsAllSecurityCritical();
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
+ if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CallToVarArg"));
+ Contract.EndContractBlock();
+
+ //
+ // We do not demand any permission here because the caller already has access
+ // to the current DynamicMethod object, and it could just as easily emit another
+ // Transparent DynamicMethod to call the current DynamicMethod.
+ //
+
+ RuntimeMethodHandle method = GetMethodDescriptor();
+ // ignore obj since it's a static method
+
+ // create a signature object
+ Signature sig = new Signature(
+ this.m_methodHandle, m_parameterTypes, m_returnType, CallingConvention);
+
+
+ // verify arguments
+ int formalCount = sig.Arguments.Length;
+ int actualCount = (parameters != null) ? parameters.Length : 0;
+ if (formalCount != actualCount)
+ throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
+
+ // if we are here we passed all the previous checks. Time to look at the arguments
+ Object retValue = null;
+ if (actualCount > 0)
+ {
+ Object[] arguments = CheckArguments(parameters, binder, invokeAttr, culture, sig);
+ retValue = RuntimeMethodHandle.InvokeMethod(null, arguments, sig, false);
+ // copy out. This should be made only if ByRef are present.
+ for (int index = 0; index < arguments.Length; index++)
+ parameters[index] = arguments[index];
+ }
+ else
+ {
+ retValue = RuntimeMethodHandle.InvokeMethod(null, null, sig, false);
+ }
+
+ GC.KeepAlive(this);
+ return retValue;
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return m_dynMethod.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit) { return m_dynMethod.GetCustomAttributes(inherit); }
+
+ public override bool IsDefined(Type attributeType, bool inherit) { return m_dynMethod.IsDefined(attributeType, inherit); }
+
+ public override Type ReturnType { get { return m_dynMethod.ReturnType; } }
+
+ public override ParameterInfo ReturnParameter { get { return m_dynMethod.ReturnParameter; } }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { return m_dynMethod.ReturnTypeCustomAttributes; } }
+
+ //
+ // DynamicMethod specific methods
+ //
+
+ public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String parameterName) {
+ if (position < 0 || position > m_parameterTypes.Length)
+ throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence"));
+ position--; // it's 1 based. 0 is the return value
+
+ if (position >= 0) {
+ ParameterInfo[] parameters = m_dynMethod.LoadParameters();
+ parameters[position].SetName(parameterName);
+ parameters[position].SetAttributes(attributes);
+ }
+ return null;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public DynamicILInfo GetDynamicILInfo()
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+
+ if (m_DynamicILInfo != null)
+ return m_DynamicILInfo;
+
+ return GetDynamicILInfo(new DynamicScope());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal DynamicILInfo GetDynamicILInfo(DynamicScope scope)
+ {
+ if (m_DynamicILInfo == null)
+ {
+ byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
+ null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
+ m_DynamicILInfo = new DynamicILInfo(scope, this, methodSignature);
+ }
+
+ return m_DynamicILInfo;
+ }
+
+ public ILGenerator GetILGenerator() {
+ return GetILGenerator(64);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ILGenerator GetILGenerator(int streamSize)
+ {
+ if (m_ilGenerator == null)
+ {
+ byte[] methodSignature = SignatureHelper.GetMethodSigHelper(
+ null, CallingConvention, ReturnType, null, null, m_parameterTypes, null, null).GetSignature(true);
+ m_ilGenerator = new DynamicILGenerator(this, methodSignature, streamSize);
+ }
+ return m_ilGenerator;
+ }
+
+ public bool InitLocals {
+ get {return m_fInitLocals;}
+ set {m_fInitLocals = value;}
+ }
+
+ //
+ // Internal API
+ //
+
+ internal MethodInfo GetMethodInfo() {
+ return m_dynMethod;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////////////////
+ // RTDynamicMethod
+ //
+ // this is actually the real runtime instance of a method info that gets used for invocation
+ // We need this so we never leak the DynamicMethod out via an exception.
+ // This way the DynamicMethod creator is the only one responsible for DynamicMethod access,
+ // and can control exactly who gets access to it.
+ //
+ internal class RTDynamicMethod : MethodInfo {
+
+ internal DynamicMethod m_owner;
+ ParameterInfo[] m_parameters;
+ String m_name;
+ MethodAttributes m_attributes;
+ CallingConventions m_callingConvention;
+
+ //
+ // ctors
+ //
+ private RTDynamicMethod() {}
+
+ internal RTDynamicMethod(DynamicMethod owner, String name, MethodAttributes attributes, CallingConventions callingConvention) {
+ m_owner = owner;
+ m_name = name;
+ m_attributes = attributes;
+ m_callingConvention = callingConvention;
+ }
+
+ //
+ // MethodInfo api
+ //
+ public override String ToString() {
+ return ReturnType.FormatTypeName() + " " + FormatNameAndSig();
+ }
+
+ public override String Name {
+ get { return m_name; }
+ }
+
+ public override Type DeclaringType {
+ get { return null; }
+ }
+
+ public override Type ReflectedType {
+ get { return null; }
+ }
+
+ public override Module Module {
+ get { return m_owner.m_module; }
+ }
+
+ public override RuntimeMethodHandle MethodHandle {
+ get { throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInDynamicMethod")); }
+ }
+
+ public override MethodAttributes Attributes {
+ get { return m_attributes; }
+ }
+
+ public override CallingConventions CallingConvention {
+ get { return m_callingConvention; }
+ }
+
+ public override MethodInfo GetBaseDefinition() {
+ return this;
+ }
+
+ [Pure]
+ public override ParameterInfo[] GetParameters() {
+ ParameterInfo[] privateParameters = LoadParameters();
+ ParameterInfo[] parameters = new ParameterInfo[privateParameters.Length];
+ Array.Copy(privateParameters, 0, parameters, 0, privateParameters.Length);
+ return parameters;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags() {
+ return MethodImplAttributes.IL | MethodImplAttributes.NoInlining;
+ }
+
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) {
+ // We want the creator of the DynamicMethod to control who has access to the
+ // DynamicMethod (just like we do for delegates). However, a user can get to
+ // the corresponding RTDynamicMethod using Exception.TargetSite, StackFrame.GetMethod, etc.
+ // If we allowed use of RTDynamicMethod, the creator of the DynamicMethod would
+ // not be able to bound access to the DynamicMethod. Hence, we do not allow
+ // direct use of RTDynamicMethod.
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "this");
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute)))
+ return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
+ else
+ return EmptyArray<Object>.Value;
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit) {
+ // support for MethodImplAttribute PCA
+ return new Object[] { new MethodImplAttribute(GetMethodImplementationFlags()) };
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit) {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ if (attributeType.IsAssignableFrom(typeof(MethodImplAttribute)))
+ return true;
+ else
+ return false;
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get { return m_owner.IsSecurityCritical; }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ get { return m_owner.IsSecuritySafeCritical; }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ get { return m_owner.IsSecurityTransparent; }
+ }
+
+ public override Type ReturnType
+ {
+ get
+ {
+ return m_owner.m_returnType;
+ }
+ }
+
+ public override ParameterInfo ReturnParameter {
+ get { return null; }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes {
+ get { return GetEmptyCAHolder(); }
+ }
+
+ //
+ // private implementation
+ //
+
+ internal ParameterInfo[] LoadParameters() {
+ if (m_parameters == null) {
+ Type[] parameterTypes = m_owner.m_parameterTypes;
+ ParameterInfo[] parameters = new ParameterInfo[parameterTypes.Length];
+ for (int i = 0; i < parameterTypes.Length; i++)
+ parameters[i] = new RuntimeParameterInfo(this, null, parameterTypes[i], i);
+ if (m_parameters == null)
+ // should we interlockexchange?
+ m_parameters = parameters;
+ }
+ return m_parameters;
+ }
+
+ // private implementation of CA for the return type
+ private ICustomAttributeProvider GetEmptyCAHolder() {
+ return new EmptyCAHolder();
+ }
+
+ ///////////////////////////////////////////////////
+ // EmptyCAHolder
+ private class EmptyCAHolder : ICustomAttributeProvider {
+ internal EmptyCAHolder() {}
+
+ Object[] ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit) {
+ return EmptyArray<Object>.Value;
+ }
+
+ Object[] ICustomAttributeProvider.GetCustomAttributes(bool inherit) {
+ return EmptyArray<Object>.Value;
+ }
+
+ bool ICustomAttributeProvider.IsDefined (Type attributeType, bool inherit) {
+ return false;
+ }
+ }
+
+ }
+
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs
new file mode 100644
index 0000000000..f8e3ab2991
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/EnumBuilder.cs
@@ -0,0 +1,448 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** EnumBuilder is a helper class to build Enum ( a special type ).
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Security.Permissions;
+
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_EnumBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class EnumBuilder : TypeInfo, _EnumBuilder
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ // Define literal for enum
+
+ public FieldBuilder DefineLiteral(String literalName, Object literalValue)
+ {
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: EnumBuilder.DefineLiteral( " + literalName + " )");
+
+ // Define the underlying field for the enum. It will be a non-static, private field with special name bit set.
+ FieldBuilder fieldBuilder = m_typeBuilder.DefineField(
+ literalName,
+ this,
+ FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
+ fieldBuilder.SetConstant(literalValue);
+ return fieldBuilder;
+ }
+
+ public TypeInfo CreateTypeInfo()
+ {
+ BCLDebug.Log("DYNIL", "## DYNIL LOGGING: EnumBuilder.CreateType() ");
+ return m_typeBuilder.CreateTypeInfo();
+ }
+
+ // CreateType cause EnumBuilder to be baked.
+ public Type CreateType()
+ {
+ BCLDebug.Log("DYNIL","## DYNIL LOGGING: EnumBuilder.CreateType() ");
+ return m_typeBuilder.CreateType();
+ }
+
+ // Get the internal metadata token for this class.
+ public TypeToken TypeToken {
+ get {return m_typeBuilder.TypeToken; }
+ }
+
+
+ // return the underlying field for the enum
+ public FieldBuilder UnderlyingField {
+ get {return m_underlyingField; }
+ }
+
+ public override String Name {
+ get { return m_typeBuilder.Name; }
+ }
+
+ /****************************************************
+ *
+ * abstract methods defined in the base class
+ *
+ */
+ public override Guid GUID {
+ get {
+ return m_typeBuilder.GUID;
+ }
+ }
+
+ public override Object InvokeMember(
+ String name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ Object target,
+ Object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ String[] namedParameters)
+ {
+ return m_typeBuilder.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
+ }
+
+ public override Module Module {
+ get {return m_typeBuilder.Module;}
+ }
+
+ public override Assembly Assembly {
+ get {return m_typeBuilder.Assembly;}
+ }
+
+ public override RuntimeTypeHandle TypeHandle {
+ get {return m_typeBuilder.TypeHandle;}
+ }
+
+ public override String FullName {
+ get { return m_typeBuilder.FullName;}
+ }
+
+ public override String AssemblyQualifiedName {
+ get {
+ return m_typeBuilder.AssemblyQualifiedName;
+ }
+ }
+
+ public override String Namespace {
+ get { return m_typeBuilder.Namespace;}
+ }
+
+ public override Type BaseType {
+ get{return m_typeBuilder.BaseType;}
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ return m_typeBuilder.GetConstructor(bindingAttr, binder, callConvention,
+ types, modifiers);
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetConstructors(bindingAttr);
+ }
+
+ protected override MethodInfo GetMethodImpl(String name,BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ if (types == null)
+ return m_typeBuilder.GetMethod(name, bindingAttr);
+ else
+ return m_typeBuilder.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetMethods(bindingAttr);
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetField(name, bindingAttr);
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetFields(bindingAttr);
+ }
+
+ public override Type GetInterface(String name, bool ignoreCase)
+ {
+ return m_typeBuilder.GetInterface(name, ignoreCase);
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return m_typeBuilder.GetInterfaces();
+ }
+
+ public override EventInfo GetEvent(String name, BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetEvent(name, bindingAttr);
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ return m_typeBuilder.GetEvents();
+ }
+
+ protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetProperties(bindingAttr);
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetNestedTypes(bindingAttr);
+ }
+
+ public override Type GetNestedType(String name, BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetNestedType(name,bindingAttr);
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetMember(name, type, bindingAttr);
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetMembers(bindingAttr);
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ return m_typeBuilder.GetInterfaceMap(interfaceType);
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return m_typeBuilder.GetEvents(bindingAttr);
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return m_typeBuilder.Attributes;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return false;
+ }
+ protected override bool IsPrimitiveImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ return true;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return false;
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override Type GetElementType()
+ {
+ return m_typeBuilder.GetElementType();
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return m_typeBuilder.HasElementType;
+ }
+
+ // About the SuppressMessageAttribute here - CCRewrite wants us to repeat the base type's precondition
+ // here, but it will always be true. Rather than adding dead code, I'll silence the warning.
+ [SuppressMessage("Microsoft.Contracts", "CC1055")]
+ // Legacy: JScript needs it.
+ public override Type GetEnumUnderlyingType()
+ {
+ return m_underlyingField.FieldType;
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return GetEnumUnderlyingType();
+ }
+ }
+
+ //ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return m_typeBuilder.GetCustomAttributes(inherit);
+ }
+
+ // Return a custom attribute identified by Type
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return m_typeBuilder.GetCustomAttributes(attributeType, inherit);
+ }
+
+ // Use this function if client decides to form the custom attribute blob themselves
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#endif
+[System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ m_typeBuilder.SetCustomAttribute(con, binaryAttribute);
+ }
+
+ // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ m_typeBuilder.SetCustomAttribute(customBuilder);
+ }
+
+ // Return the class that declared this Field.
+ public override Type DeclaringType {
+ get {return m_typeBuilder.DeclaringType;}
+ }
+
+ // Return the class that was used to obtain this field.
+
+ public override Type ReflectedType {
+ get {return m_typeBuilder.ReflectedType;}
+ }
+
+
+ // Returns true if one or more instance of attributeType is defined on this member.
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ return m_typeBuilder.IsDefined(attributeType, inherit);
+ }
+
+
+ internal int MetadataTokenInternal { get { return m_typeBuilder.MetadataTokenInternal; } }
+
+ /*****************************************************
+ *
+ * private/protected functions
+ *
+ */
+
+ //*******************************
+ // Make a private constructor so these cannot be constructed externally.
+ //*******************************
+ private EnumBuilder() {}
+
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType("*", this, 0);
+ }
+
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType("&", this, 0);
+ }
+
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType("[]", this, 0);
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+
+ string szrank = "";
+ if (rank == 1)
+ {
+ szrank = "*";
+ }
+ else
+ {
+ for(int i = 1; i < rank; i++)
+ szrank += ",";
+ }
+
+ string s = String.Format(CultureInfo.InvariantCulture, "[{0}]", szrank); // [,,]
+ return SymbolType.FormCompoundType(s, this, 0);
+ }
+
+
+ // Constructs a EnumBuilder.
+ // EnumBuilder can only be a top-level (not nested) enum type.
+ [System.Security.SecurityCritical] // auto-generated
+ internal EnumBuilder(
+ String name, // name of type
+ Type underlyingType, // underlying type for an Enum
+ TypeAttributes visibility, // any bits on TypeAttributes.VisibilityMask)
+ ModuleBuilder module) // module containing this type
+ {
+ // Client should not set any bits other than the visibility bits.
+ if ((visibility & ~TypeAttributes.VisibilityMask) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ShouldOnlySetVisibilityFlags"), "name");
+ m_typeBuilder = new TypeBuilder(name, visibility | TypeAttributes.Sealed, typeof(System.Enum), null, module, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null);
+
+ // Define the underlying field for the enum. It will be a non-static, private field with special name bit set.
+ m_underlyingField = m_typeBuilder.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
+ }
+
+#if !FEATURE_CORECLR
+ void _EnumBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EnumBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EnumBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EnumBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+
+ /*****************************************************
+ *
+ * private data members
+ *
+ */
+ internal TypeBuilder m_typeBuilder;
+ private FieldBuilder m_underlyingField;
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs
new file mode 100644
index 0000000000..42a5252102
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/EventBuilder.cs
@@ -0,0 +1,174 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Eventbuilder is for client to define eevnts for a class
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ //
+ // A EventBuilder is always associated with a TypeBuilder. The TypeBuilder.DefineEvent
+ // method will return a new EventBuilder to a client.
+ //
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_EventBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class EventBuilder : _EventBuilder
+ {
+
+ // Make a private constructor so these cannot be constructed externally.
+ private EventBuilder() {}
+
+ // Constructs a EventBuilder.
+ //
+ internal EventBuilder(
+ ModuleBuilder mod, // the module containing this EventBuilder
+ String name, // Event name
+ EventAttributes attr, // event attribute such as Public, Private, and Protected defined above
+ //int eventType, // event type
+ TypeBuilder type, // containing type
+ EventToken evToken)
+ {
+ m_name = name;
+ m_module = mod;
+ m_attributes = attr;
+ m_evToken = evToken;
+ m_type = type;
+ }
+
+ // Return the Token for this event within the TypeBuilder that the
+ // event is defined within.
+ public EventToken GetEventToken()
+ {
+ return m_evToken;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetMethodSemantics(MethodBuilder mdBuilder, MethodSemanticsAttributes semantics)
+ {
+ if (mdBuilder == null)
+ {
+ throw new ArgumentNullException("mdBuilder");
+ }
+ Contract.EndContractBlock();
+
+ m_type.ThrowIfCreated();
+ TypeBuilder.DefineMethodSemantics(
+ m_module.GetNativeHandle(),
+ m_evToken.Token,
+ semantics,
+ mdBuilder.GetToken().Token);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAddOnMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.AddOn);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetRemoveOnMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.RemoveOn);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetRaiseMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Fire);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Other);
+ }
+
+ // Use this function if client decides to form the custom attribute blob themselves
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#else
+[System.Security.SecuritySafeCritical]
+#endif
+[System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+ m_type.ThrowIfCreated();
+
+ TypeBuilder.DefineCustomAttribute(
+ m_module,
+ m_evToken.Token,
+ m_module.GetConstructorToken(con).Token,
+ binaryAttribute,
+ false, false);
+ }
+
+ // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ {
+ throw new ArgumentNullException("customBuilder");
+ }
+ Contract.EndContractBlock();
+ m_type.ThrowIfCreated();
+ customBuilder.CreateCustomAttribute(m_module, m_evToken.Token);
+ }
+
+#if !FEATURE_CORECLR
+ void _EventBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EventBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EventBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EventBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+
+ // These are package private so that TypeBuilder can access them.
+ private String m_name; // The name of the event
+ private EventToken m_evToken; // The token of this event
+ private ModuleBuilder m_module;
+ private EventAttributes m_attributes;
+ private TypeBuilder m_type;
+ }
+
+
+
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/EventToken.cs b/src/mscorlib/src/System/Reflection/Emit/EventToken.cs
new file mode 100644
index 0000000000..0642cec822
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/EventToken.cs
@@ -0,0 +1,69 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Propertybuilder is for client to define properties for a class
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct EventToken
+ {
+ public static readonly EventToken Empty = new EventToken();
+
+ internal int m_event;
+
+ internal EventToken(int str) {
+ m_event=str;
+ }
+
+ public int Token {
+ get { return m_event; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_event;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is EventToken)
+ return Equals((EventToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(EventToken obj)
+ {
+ return obj.m_event == m_event;
+ }
+
+ public static bool operator ==(EventToken a, EventToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(EventToken a, EventToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+
+
+
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs
new file mode 100644
index 0000000000..0f2de5be43
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/FieldBuilder.cs
@@ -0,0 +1,281 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_FieldBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class FieldBuilder : FieldInfo, _FieldBuilder
+ {
+ #region Private Data Members
+ private int m_fieldTok;
+ private FieldToken m_tkField;
+ private TypeBuilder m_typeBuilder;
+ private String m_fieldName;
+ private FieldAttributes m_Attributes;
+ private Type m_fieldType;
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal FieldBuilder(TypeBuilder typeBuilder, String fieldName, Type type,
+ Type[] requiredCustomModifiers, Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ if (fieldName == null)
+ throw new ArgumentNullException("fieldName");
+
+ if (fieldName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "fieldName");
+
+ if (fieldName[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "fieldName");
+
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ if (type == typeof(void))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldType"));
+ Contract.EndContractBlock();
+
+ m_fieldName = fieldName;
+ m_typeBuilder = typeBuilder;
+ m_fieldType = type;
+ m_Attributes = attributes & ~FieldAttributes.ReservedMask;
+
+ SignatureHelper sigHelp = SignatureHelper.GetFieldSigHelper(m_typeBuilder.Module);
+ sigHelp.AddArgument(type, requiredCustomModifiers, optionalCustomModifiers);
+
+ int sigLength;
+ byte[] signature = sigHelp.InternalGetSignature(out sigLength);
+
+ m_fieldTok = TypeBuilder.DefineField(m_typeBuilder.GetModuleBuilder().GetNativeHandle(),
+ typeBuilder.TypeToken.Token, fieldName, signature, sigLength, m_Attributes);
+
+ m_tkField = new FieldToken(m_fieldTok, type);
+ }
+
+ #endregion
+
+ #region Internal Members
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetData(byte[] data, int size)
+ {
+ ModuleBuilder.SetFieldRVAContent(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), m_tkField.Token, data, size);
+ }
+
+ internal TypeBuilder GetTypeBuilder() { return m_typeBuilder; }
+ #endregion
+
+ #region MemberInfo Overrides
+ internal int MetadataTokenInternal
+ {
+ get { return m_fieldTok; }
+ }
+
+ public override Module Module
+ {
+ get { return m_typeBuilder.Module; }
+ }
+
+ public override String Name
+ {
+ get {return m_fieldName; }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ if (m_typeBuilder.m_isHiddenGlobalType == true)
+ return null;
+
+ return m_typeBuilder;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ if (m_typeBuilder.m_isHiddenGlobalType == true)
+ return null;
+
+ return m_typeBuilder;
+ }
+ }
+
+ #endregion
+
+ #region FieldInfo Overrides
+ public override Type FieldType
+ {
+ get { return m_fieldType; }
+ }
+
+ public override Object GetValue(Object obj)
+ {
+ // NOTE!! If this is implemented, make sure that this throws
+ // a NotSupportedException for Save-only dynamic assemblies.
+ // Otherwise, it could cause the .cctor to be executed.
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override void SetValue(Object obj,Object val,BindingFlags invokeAttr,Binder binder,CultureInfo culture)
+ {
+ // NOTE!! If this is implemented, make sure that this throws
+ // a NotSupportedException for Save-only dynamic assemblies.
+ // Otherwise, it could cause the .cctor to be executed.
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override RuntimeFieldHandle FieldHandle
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get { return m_Attributes; }
+ }
+
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ #endregion
+
+ #region Public Members
+ public FieldToken GetToken()
+ {
+ return m_tkField;
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public void SetOffset(int iOffset)
+ {
+ m_typeBuilder.ThrowIfCreated();
+
+ TypeBuilder.SetFieldLayoutOffset(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), GetToken().Token, iOffset);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetMarshal(UnmanagedMarshal unmanagedMarshal)
+ {
+ if (unmanagedMarshal == null)
+ throw new ArgumentNullException("unmanagedMarshal");
+ Contract.EndContractBlock();
+
+ m_typeBuilder.ThrowIfCreated();
+
+ byte[] ubMarshal = unmanagedMarshal.InternalGetBytes();
+
+ TypeBuilder.SetFieldMarshal(m_typeBuilder.GetModuleBuilder().GetNativeHandle(), GetToken().Token, ubMarshal, ubMarshal.Length);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetConstant(Object defaultValue)
+ {
+ m_typeBuilder.ThrowIfCreated();
+
+ TypeBuilder.SetConstantValue(m_typeBuilder.GetModuleBuilder(), GetToken().Token, m_fieldType, defaultValue);
+ }
+
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#else
+[System.Security.SecuritySafeCritical]
+#endif
+[System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ ModuleBuilder module = m_typeBuilder.Module as ModuleBuilder;
+
+ m_typeBuilder.ThrowIfCreated();
+
+ TypeBuilder.DefineCustomAttribute(module,
+ m_tkField.Token, module.GetConstructorToken(con).Token, binaryAttribute, false, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ throw new ArgumentNullException("customBuilder");
+ Contract.EndContractBlock();
+
+ m_typeBuilder.ThrowIfCreated();
+
+ ModuleBuilder module = m_typeBuilder.Module as ModuleBuilder;
+
+ customBuilder.CreateCustomAttribute(module, m_tkField.Token);
+ }
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _FieldBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _FieldBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _FieldBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _FieldBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/FieldToken.cs b/src/mscorlib/src/System/Reflection/Emit/FieldToken.cs
new file mode 100644
index 0000000000..42fd684e7c
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/FieldToken.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Represents a Field to the ILGenerator Class
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ // The FieldToken class is an opaque representation of the Token returned
+ // by the Metadata to represent the field. FieldTokens are generated by
+ // Module.GetFieldToken(). There are no meaningful accessors on this class,
+ // but it can be passed to ILGenerator which understands it's internals.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct FieldToken
+ {
+ public static readonly FieldToken Empty = new FieldToken();
+
+ internal int m_fieldTok;
+ internal Object m_class;
+
+ // Creates an empty FieldToken. A publicly visible constructor so that
+ // it can be created on the stack.
+ //public FieldToken() {
+ // m_fieldTok=0;
+ // m_attributes=0;
+ // m_class=null;
+ //}
+ // The actual constructor. Sets the field, attributes and class
+ // variables
+
+ internal FieldToken (int field, Type fieldClass) {
+ m_fieldTok=field;
+ m_class = fieldClass;
+ }
+
+ public int Token {
+ get { return m_fieldTok; }
+ }
+
+
+ // Generates the hash code for this field.
+ public override int GetHashCode()
+ {
+ return (m_fieldTok);
+ }
+
+ // Returns true if obj is an instance of FieldToken and is
+ // equal to this instance.
+ public override bool Equals(Object obj)
+ {
+ if (obj is FieldToken)
+ return Equals((FieldToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(FieldToken obj)
+ {
+ return obj.m_fieldTok == m_fieldTok && obj.m_class == m_class;
+ }
+
+ public static bool operator ==(FieldToken a, FieldToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(FieldToken a, FieldToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs b/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs
new file mode 100644
index 0000000000..5bfe5bb7bb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/FlowControl.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+**
+**Purpose: Exposes FlowControl Attribute of IL .
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See clrsrcincopcodegen.pl for more information.**
+============================================================*/
+namespace System.Reflection.Emit {
+
+using System;
+
+[Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+public enum FlowControl
+{
+
+ Branch = 0,
+ Break = 1,
+ Call = 2,
+ Cond_Branch = 3,
+ Meta = 4,
+ Next = 5,
+#if !FEATURE_CORECLR
+ /// <internalonly/>
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Phi = 6,
+#endif
+ Return = 7,
+ Throw = 8,
+}
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs
new file mode 100644
index 0000000000..bcf70dbe46
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/GenericTypeParameterBuilder.cs
@@ -0,0 +1,248 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class GenericTypeParameterBuilder: TypeInfo
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ #region Private Data Mebers
+ internal TypeBuilder m_type;
+ #endregion
+
+ #region Constructor
+ internal GenericTypeParameterBuilder(TypeBuilder type)
+ {
+ m_type = type;
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return m_type.Name;
+ }
+ public override bool Equals(object o)
+ {
+ GenericTypeParameterBuilder g = o as GenericTypeParameterBuilder;
+
+ if (g == null)
+ return false;
+
+ return object.ReferenceEquals(g.m_type, m_type);
+ }
+ public override int GetHashCode() { return m_type.GetHashCode(); }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override Type DeclaringType { get { return m_type.DeclaringType; } }
+
+ public override Type ReflectedType { get { return m_type.ReflectedType; } }
+
+ public override String Name { get { return m_type.Name; } }
+
+ public override Module Module { get { return m_type.Module; } }
+
+ internal int MetadataTokenInternal { get { return m_type.MetadataTokenInternal; } }
+ #endregion
+
+ #region Type Overrides
+
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType("*", this, 0);
+ }
+
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType("&", this, 0);
+ }
+
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType("[]", this, 0);
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ string szrank = "";
+ if (rank == 1)
+ {
+ szrank = "*";
+ }
+ else
+ {
+ for(int i = 1; i < rank; i++)
+ szrank += ",";
+ }
+
+ string s = String.Format(CultureInfo.InvariantCulture, "[{0}]", szrank); // [,,]
+ SymbolType st = SymbolType.FormCompoundType(s, this, 0) as SymbolType;
+ return st;
+ }
+
+ public override Guid GUID { get { throw new NotSupportedException(); } }
+
+ public override Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) { throw new NotSupportedException(); }
+
+ public override Assembly Assembly { get { return m_type.Assembly; } }
+
+ public override RuntimeTypeHandle TypeHandle { get { throw new NotSupportedException(); } }
+
+ public override String FullName { get { return null; } }
+
+ public override String Namespace { get { return null; } }
+
+ public override String AssemblyQualifiedName { get { return null; } }
+
+ public override Type BaseType { get { return m_type.BaseType; } }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ protected override MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override Type GetInterface(String name, bool ignoreCase) { throw new NotSupportedException(); }
+
+ public override Type[] GetInterfaces() { throw new NotSupportedException(); }
+
+ public override EventInfo GetEvent(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override EventInfo[] GetEvents() { throw new NotSupportedException(); }
+
+ protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override Type GetNestedType(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType) { throw new NotSupportedException(); }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ protected override TypeAttributes GetAttributeFlagsImpl() { return TypeAttributes.Public; }
+
+ protected override bool IsArrayImpl() { return false; }
+
+ protected override bool IsByRefImpl() { return false; }
+
+ protected override bool IsPointerImpl() { return false; }
+
+ protected override bool IsPrimitiveImpl() { return false; }
+
+ protected override bool IsCOMObjectImpl() { return false; }
+
+ public override Type GetElementType() { throw new NotSupportedException(); }
+
+ protected override bool HasElementTypeImpl() { return false; }
+
+ public override Type UnderlyingSystemType { get { return this; } }
+
+ public override Type[] GetGenericArguments() { throw new InvalidOperationException(); }
+
+ public override bool IsGenericTypeDefinition { get { return false; } }
+
+ public override bool IsGenericType { get { return false; } }
+
+ public override bool IsGenericParameter { get { return true; } }
+
+ public override bool IsConstructedGenericType { get { return false; } }
+
+ public override int GenericParameterPosition { get { return m_type.GenericParameterPosition; } }
+
+ public override bool ContainsGenericParameters { get { return m_type.ContainsGenericParameters; } }
+
+ public override GenericParameterAttributes GenericParameterAttributes { get { return m_type.GenericParameterAttributes; } }
+
+ public override MethodBase DeclaringMethod { get { return m_type.DeclaringMethod; } }
+
+ public override Type GetGenericTypeDefinition() { throw new InvalidOperationException(); }
+
+ public override Type MakeGenericType(params Type[] typeArguments) { throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericTypeDefinition")); }
+
+ protected override bool IsValueTypeImpl() { return false; }
+
+ public override bool IsAssignableFrom(Type c) { throw new NotSupportedException(); }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public override bool IsSubclassOf(Type c) { throw new NotSupportedException(); }
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit) { throw new NotSupportedException(); }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { throw new NotSupportedException(); }
+
+ public override bool IsDefined(Type attributeType, bool inherit) { throw new NotSupportedException(); }
+ #endregion
+
+ #region Public Members
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ m_type.SetGenParamCustomAttribute(con, binaryAttribute);
+ }
+
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ m_type.SetGenParamCustomAttribute(customBuilder);
+ }
+
+ public void SetBaseTypeConstraint(Type baseTypeConstraint)
+ {
+ m_type.CheckContext(baseTypeConstraint);
+ m_type.SetParent(baseTypeConstraint);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetInterfaceConstraints(params Type[] interfaceConstraints)
+ {
+ m_type.CheckContext(interfaceConstraints);
+ m_type.SetInterfaces(interfaceConstraints);
+ }
+
+ public void SetGenericParameterAttributes(GenericParameterAttributes genericParameterAttributes)
+ {
+ m_type.SetGenParamAttributes(genericParameterAttributes);
+ }
+ #endregion
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs b/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs
new file mode 100644
index 0000000000..15dece9fcb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs
@@ -0,0 +1,2012 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using TextWriter = System.IO.TextWriter;
+ using System.Diagnostics.SymbolStore;
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ILGenerator))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ILGenerator : _ILGenerator
+ {
+ #region Const Members
+ private const int defaultSize = 16;
+ private const int DefaultFixupArraySize = 8;
+ private const int DefaultLabelArraySize = 4;
+ private const int DefaultExceptionArraySize = 2;
+ #endregion
+
+ #region Internal Statics
+ internal static T[] EnlargeArray<T>(T[] incoming)
+ {
+ return EnlargeArray(incoming, incoming.Length * 2);
+ }
+
+ internal static T[] EnlargeArray<T>(T[] incoming, int requiredSize)
+ {
+ Contract.Requires(incoming != null);
+ Contract.Ensures(Contract.Result<T[]>() != null);
+ Contract.Ensures(Contract.Result<T[]>().Length == requiredSize);
+
+ T[] temp = new T[requiredSize];
+ Array.Copy(incoming, 0, temp, 0, incoming.Length);
+ return temp;
+ }
+
+ private static byte[] EnlargeArray(byte[] incoming)
+ {
+ return EnlargeArray(incoming, incoming.Length * 2);
+ }
+
+ private static byte[] EnlargeArray(byte[] incoming, int requiredSize)
+ {
+ Contract.Requires(incoming != null);
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+ Contract.Ensures(Contract.Result<byte[]>().Length == requiredSize);
+
+ byte[] temp = new byte[requiredSize];
+ Buffer.BlockCopy(incoming, 0, temp, 0, incoming.Length);
+ return temp;
+ }
+ #endregion
+
+ #region Internal Data Members
+ private int m_length;
+ private byte[] m_ILStream;
+
+ private int[] m_labelList;
+ private int m_labelCount;
+
+ private __FixupData[] m_fixupData;
+
+ private int m_fixupCount;
+
+ private int[] m_RelocFixupList;
+ private int m_RelocFixupCount;
+
+ private int m_exceptionCount;
+ private int m_currExcStackCount;
+ private __ExceptionInfo[] m_exceptions; //This is the list of all of the exceptions in this ILStream.
+ private __ExceptionInfo[] m_currExcStack; //This is the stack of exceptions which we're currently in.
+
+ internal ScopeTree m_ScopeTree; // this variable tracks all debugging scope information
+ internal LineNumberInfo m_LineNumberInfo; // this variable tracks all line number information
+
+ internal MethodInfo m_methodBuilder;
+ internal int m_localCount;
+ internal SignatureHelper m_localSignature;
+
+ private int m_maxStackSize = 0; // Maximum stack size not counting the exceptions.
+
+ private int m_maxMidStack = 0; // Maximum stack size for a given basic block.
+ private int m_maxMidStackCur = 0; // Running count of the maximum stack size for the current basic block.
+
+ internal int CurrExcStackCount
+ {
+ get { return m_currExcStackCount; }
+ }
+
+ internal __ExceptionInfo[] CurrExcStack
+ {
+ get { return m_currExcStack; }
+ }
+ #endregion
+
+ #region Constructor
+ // package private constructor. This code path is used when client create
+ // ILGenerator through MethodBuilder.
+ internal ILGenerator(MethodInfo methodBuilder) : this(methodBuilder, 64)
+ {
+ }
+
+ internal ILGenerator(MethodInfo methodBuilder, int size)
+ {
+ Contract.Requires(methodBuilder != null);
+ Contract.Requires(methodBuilder is MethodBuilder || methodBuilder is DynamicMethod);
+
+ if (size < defaultSize)
+ {
+ m_ILStream = new byte[defaultSize];
+ }
+ else
+ {
+ m_ILStream = new byte[size];
+ }
+
+ m_length = 0;
+
+ m_labelCount = 0;
+ m_fixupCount = 0;
+ m_labelList = null;
+
+ m_fixupData = null;
+
+ m_exceptions = null;
+ m_exceptionCount = 0;
+ m_currExcStack = null;
+ m_currExcStackCount = 0;
+
+ m_RelocFixupList = null;
+ m_RelocFixupCount = 0;
+
+ // initialize the scope tree
+ m_ScopeTree = new ScopeTree();
+ m_LineNumberInfo = new LineNumberInfo();
+ m_methodBuilder = methodBuilder;
+
+ // initialize local signature
+ m_localCount = 0;
+ MethodBuilder mb = m_methodBuilder as MethodBuilder;
+ if (mb == null)
+ m_localSignature = SignatureHelper.GetLocalVarSigHelper(null);
+ else
+ m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb.GetTypeBuilder().Module);
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal virtual void RecordTokenFixup()
+ {
+ if (m_RelocFixupList == null)
+ m_RelocFixupList = new int[DefaultFixupArraySize];
+ else if (m_RelocFixupList.Length <= m_RelocFixupCount)
+ m_RelocFixupList = EnlargeArray(m_RelocFixupList);
+
+ m_RelocFixupList[m_RelocFixupCount++] = m_length;
+ }
+
+ internal void InternalEmit(OpCode opcode)
+ {
+ if (opcode.Size != 1)
+ {
+ m_ILStream[m_length++] = (byte)(opcode.Value >> 8);
+ }
+
+ m_ILStream[m_length++] = (byte)opcode.Value;
+
+ UpdateStackSize(opcode, opcode.StackChange());
+
+ }
+
+ internal void UpdateStackSize(OpCode opcode, int stackchange)
+ {
+ // Updates internal variables for keeping track of the stack size
+ // requirements for the function. stackchange specifies the amount
+ // by which the stacksize needs to be updated.
+
+ // Special case for the Return. Returns pops 1 if there is a
+ // non-void return value.
+
+ // Update the running stacksize. m_maxMidStack specifies the maximum
+ // amount of stack required for the current basic block irrespective of
+ // where you enter the block.
+ m_maxMidStackCur += stackchange;
+ if (m_maxMidStackCur > m_maxMidStack)
+ m_maxMidStack = m_maxMidStackCur;
+ else if (m_maxMidStackCur < 0)
+ m_maxMidStackCur = 0;
+
+ // If the current instruction signifies end of a basic, which basically
+ // means an unconditional branch, add m_maxMidStack to m_maxStackSize.
+ // m_maxStackSize will eventually be the sum of the stack requirements for
+ // each basic block.
+ if (opcode.EndsUncondJmpBlk())
+ {
+ m_maxStackSize += m_maxMidStack;
+ m_maxMidStack = 0;
+ m_maxMidStackCur = 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMethodToken(MethodBase method, Type[] optionalParameterTypes, bool useMethodDef)
+ {
+ return ((ModuleBuilder)m_methodBuilder.Module).GetMethodTokenInternal(method, optionalParameterTypes, useMethodDef);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType,
+ Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ return GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, 0);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType,
+ Type[] parameterTypes, Type[] optionalParameterTypes, int cGenericParameters)
+ {
+ return ((ModuleBuilder)m_methodBuilder.Module).GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, cGenericParameters);
+ }
+
+ internal byte[] BakeByteArray()
+ {
+ // BakeByteArray is an internal function designed to be called by MethodBuilder to do
+ // all of the fixups and return a new byte array representing the byte stream with labels resolved, etc.
+
+ int newSize;
+ int updateAddr;
+ byte[] newBytes;
+
+ if (m_currExcStackCount != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_UnclosedExceptionBlock"));
+ }
+ if (m_length == 0)
+ return null;
+
+ //Calculate the size of the new array.
+ newSize = m_length;
+
+ //Allocate space for the new array.
+ newBytes = new byte[newSize];
+
+ //Copy the data from the old array
+ Buffer.BlockCopy(m_ILStream, 0, newBytes, 0, newSize);
+
+ //Do the fixups.
+ //This involves iterating over all of the labels and
+ //replacing them with their proper values.
+ for (int i =0; i < m_fixupCount; i++)
+ {
+ updateAddr = GetLabelPos(m_fixupData[i].m_fixupLabel) - (m_fixupData[i].m_fixupPos + m_fixupData[i].m_fixupInstSize);
+
+ //Handle single byte instructions
+ //Throw an exception if they're trying to store a jump in a single byte instruction that doesn't fit.
+ if (m_fixupData[i].m_fixupInstSize == 1)
+ {
+
+ //Verify that our one-byte arg will fit into a Signed Byte.
+ if (updateAddr < SByte.MinValue || updateAddr > SByte.MaxValue)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_IllegalOneByteBranch",m_fixupData[i].m_fixupPos, updateAddr));
+ }
+
+ //Place the one-byte arg
+ if (updateAddr < 0)
+ {
+ newBytes[m_fixupData[i].m_fixupPos] = (byte)(256 + updateAddr);
+ }
+ else
+ {
+ newBytes[m_fixupData[i].m_fixupPos] = (byte)updateAddr;
+ }
+ }
+ else
+ {
+ //Place the four-byte arg
+ PutInteger4InArray(updateAddr, m_fixupData[i].m_fixupPos, newBytes);
+ }
+ }
+ return newBytes;
+ }
+
+ internal __ExceptionInfo[] GetExceptions()
+ {
+ __ExceptionInfo []temp;
+ if (m_currExcStackCount != 0)
+ {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.Argument_UnclosedExceptionBlock));
+ }
+
+ if (m_exceptionCount == 0)
+ {
+ return null;
+ }
+
+ temp = new __ExceptionInfo[m_exceptionCount];
+ Array.Copy(m_exceptions, 0, temp, 0, m_exceptionCount);
+ SortExceptions(temp);
+ return temp;
+ }
+
+ internal void EnsureCapacity(int size)
+ {
+ // Guarantees an array capable of holding at least size elements.
+ if (m_length + size >= m_ILStream.Length)
+ {
+ if (m_length + size >= 2 * m_ILStream.Length)
+ {
+ m_ILStream = EnlargeArray(m_ILStream, m_length + size);
+ }
+ else
+ {
+ m_ILStream = EnlargeArray(m_ILStream);
+ }
+ }
+ }
+
+ internal void PutInteger4(int value)
+ {
+ m_length = PutInteger4InArray(value, m_length, m_ILStream);
+ }
+
+ private static int PutInteger4InArray(int value, int startPos, byte []array)
+ {
+ // Puts an Int32 onto the stream. This is an internal routine, so it does not do any error checking.
+
+ array[startPos++] = (byte)value;
+ array[startPos++] = (byte)(value >>8);
+ array[startPos++] = (byte)(value >>16);
+ array[startPos++] = (byte)(value >>24);
+ return startPos;
+ }
+
+ private int GetLabelPos(Label lbl)
+ {
+ // Gets the position in the stream of a particular label.
+ // Verifies that the label exists and that it has been given a value.
+
+ int index = lbl.GetLabelValue();
+
+ if (index < 0 || index >= m_labelCount)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadLabel"));
+
+ if (m_labelList[index] < 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadLabelContent"));
+
+ return m_labelList[index];
+ }
+
+ private void AddFixup(Label lbl, int pos, int instSize)
+ {
+ // Notes the label, position, and instruction size of a new fixup. Expands
+ // all of the fixup arrays as appropriate.
+
+ if (m_fixupData == null)
+ {
+ m_fixupData = new __FixupData[DefaultFixupArraySize];
+ }
+ else if (m_fixupData.Length <= m_fixupCount)
+ {
+ m_fixupData = EnlargeArray(m_fixupData);
+ }
+
+ m_fixupData[m_fixupCount].m_fixupPos = pos;
+ m_fixupData[m_fixupCount].m_fixupLabel = lbl;
+ m_fixupData[m_fixupCount].m_fixupInstSize = instSize;
+
+ m_fixupCount++;
+ }
+
+ internal int GetMaxStackSize()
+ {
+ return m_maxStackSize;
+ }
+
+ private static void SortExceptions(__ExceptionInfo []exceptions)
+ {
+ // In order to call exceptions properly we have to sort them in ascending order by their end position.
+ // Just a cheap insertion sort. We don't expect many exceptions (<10), where InsertionSort beats QuickSort.
+ // If we have more exceptions than this in real life, we should consider moving to a QuickSort.
+
+ int least;
+ __ExceptionInfo temp;
+ int length = exceptions.Length;
+ for (int i =0; i < length; i++)
+ {
+ least = i;
+ for (int j =i + 1; j < length; j++)
+ {
+ if (exceptions[least].IsInner(exceptions[j]))
+ {
+ least = j;
+ }
+ }
+ temp = exceptions[i];
+ exceptions[i] = exceptions[least];
+ exceptions[least] = temp;
+ }
+ }
+
+ internal int[] GetTokenFixups()
+ {
+ if (m_RelocFixupCount == 0)
+ {
+ Contract.Assert(m_RelocFixupList == null);
+ return null;
+ }
+
+ int[] narrowTokens = new int[m_RelocFixupCount];
+ Array.Copy(m_RelocFixupList, 0, narrowTokens, 0, m_RelocFixupCount);
+ return narrowTokens;
+ }
+ #endregion
+
+ #region Public Members
+
+ #region Emit
+ public virtual void Emit(OpCode opcode)
+ {
+ EnsureCapacity(3);
+ InternalEmit(opcode);
+
+ }
+
+ public virtual void Emit(OpCode opcode, byte arg)
+ {
+ EnsureCapacity(4);
+ InternalEmit(opcode);
+ m_ILStream[m_length++]=arg;
+ }
+
+ [CLSCompliant(false)]
+ public void Emit(OpCode opcode, sbyte arg)
+ {
+ // Puts opcode onto the stream of instructions followed by arg
+
+ EnsureCapacity(4);
+ InternalEmit(opcode);
+ if (arg<0) {
+ m_ILStream[m_length++]=(byte)(256+arg);
+ } else {
+ m_ILStream[m_length++]=(byte) arg;
+ }
+ }
+
+ public virtual void Emit(OpCode opcode, short arg)
+ {
+ // Puts opcode onto the stream of instructions followed by arg
+ EnsureCapacity(5);
+ InternalEmit(opcode);
+ m_ILStream[m_length++]=(byte) arg;
+ m_ILStream[m_length++]=(byte) (arg>>8);
+ }
+
+ public virtual void Emit(OpCode opcode, int arg)
+ {
+ // Puts opcode onto the stream of instructions followed by arg
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ PutInteger4(arg);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void Emit(OpCode opcode, MethodInfo meth)
+ {
+ if (meth == null)
+ throw new ArgumentNullException("meth");
+ Contract.EndContractBlock();
+
+ if (opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj))
+ {
+ EmitCall(opcode, meth, null);
+ }
+ else
+ {
+ int stackchange = 0;
+
+ // Reflection doesn't distinguish between these two concepts:
+ // 1. A generic method definition: Foo`1
+ // 2. A generic method definition instantiated over its own generic arguments: Foo`1<!!0>
+ // In RefEmit, we always want 1 for Ld* opcodes and 2 for Call* and Newobj.
+ bool useMethodDef = opcode.Equals(OpCodes.Ldtoken) || opcode.Equals(OpCodes.Ldftn) || opcode.Equals(OpCodes.Ldvirtftn);
+ int tk = GetMethodToken(meth, null, useMethodDef);
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ UpdateStackSize(opcode, stackchange);
+ RecordTokenFixup();
+ PutInteger4(tk);
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
+ {
+ int stackchange = 0;
+ SignatureHelper sig;
+ if (optionalParameterTypes != null)
+ {
+ if ((callingConvention & CallingConventions.VarArgs) == 0)
+ {
+ // Client should not supply optional parameter in default calling convention
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
+ }
+ }
+
+ ModuleBuilder modBuilder = (ModuleBuilder) m_methodBuilder.Module;
+ sig = GetMemberRefSignature(callingConvention,
+ returnType,
+ parameterTypes,
+ optionalParameterTypes);
+
+ EnsureCapacity(7);
+ Emit(OpCodes.Calli);
+
+ // If there is a non-void return type, push one.
+ if (returnType != typeof(void))
+ stackchange++;
+ // Pop off arguments if any.
+ if (parameterTypes != null)
+ stackchange -= parameterTypes.Length;
+ // Pop off vararg arguments.
+ if (optionalParameterTypes != null)
+ stackchange -= optionalParameterTypes.Length;
+ // Pop the this parameter if the method has a this parameter.
+ if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
+ stackchange--;
+ // Pop the native function pointer.
+ stackchange--;
+ UpdateStackSize(OpCodes.Calli, stackchange);
+
+ RecordTokenFixup();
+ PutInteger4(modBuilder.GetSignatureToken(sig).Token);
+ }
+
+ public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
+ {
+ int stackchange = 0;
+ int cParams = 0;
+ int i;
+ SignatureHelper sig;
+
+ ModuleBuilder modBuilder = (ModuleBuilder) m_methodBuilder.Module;
+
+ if (parameterTypes != null)
+ {
+ cParams = parameterTypes.Length;
+ }
+
+ sig = SignatureHelper.GetMethodSigHelper(
+ modBuilder,
+ unmanagedCallConv,
+ returnType);
+
+ if (parameterTypes != null)
+ {
+ for (i = 0; i < cParams; i++)
+ {
+ sig.AddArgument(parameterTypes[i]);
+ }
+ }
+
+ // If there is a non-void return type, push one.
+ if (returnType != typeof(void))
+ stackchange++;
+
+ // Pop off arguments if any.
+ if (parameterTypes != null)
+ stackchange -= cParams;
+
+ // Pop the native function pointer.
+ stackchange--;
+ UpdateStackSize(OpCodes.Calli, stackchange);
+
+ EnsureCapacity(7);
+ Emit(OpCodes.Calli);
+ RecordTokenFixup();
+ PutInteger4(modBuilder.GetSignatureToken(sig).Token);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
+ {
+ if (methodInfo == null)
+ throw new ArgumentNullException("methodInfo");
+
+ if (!(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotMethodCallOpcode"), "opcode");
+
+ Contract.EndContractBlock();
+
+ int stackchange = 0;
+ int tk = GetMethodToken(methodInfo, optionalParameterTypes, false);
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // Push the return value if there is one.
+ if (methodInfo.ReturnType != typeof(void))
+ stackchange++;
+ // Pop the parameters.
+ Type[] parameters = methodInfo.GetParameterTypes();
+ if (parameters != null)
+ stackchange -= parameters.Length;
+
+ // Pop the this parameter if the method is non-static and the
+ // instruction is not newobj.
+ if (!(methodInfo is SymbolMethod) && methodInfo.IsStatic == false && !(opcode.Equals(OpCodes.Newobj)))
+ stackchange--;
+ // Pop the optional parameters off the stack.
+ if (optionalParameterTypes != null)
+ stackchange -= optionalParameterTypes.Length;
+ UpdateStackSize(opcode, stackchange);
+
+ RecordTokenFixup();
+ PutInteger4(tk);
+ }
+
+ public virtual void Emit(OpCode opcode, SignatureHelper signature)
+ {
+ if (signature == null)
+ throw new ArgumentNullException("signature");
+ Contract.EndContractBlock();
+
+ int stackchange = 0;
+ ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
+ SignatureToken sig = modBuilder.GetSignatureToken(signature);
+
+ int tempVal = sig.Token;
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // The only IL instruction that has VarPop behaviour, that takes a
+ // Signature token as a parameter is calli. Pop the parameters and
+ // the native function pointer. To be conservative, do not pop the
+ // this pointer since this information is not easily derived from
+ // SignatureHelper.
+ if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
+ {
+ Contract.Assert(opcode.Equals(OpCodes.Calli),
+ "Unexpected opcode encountered for StackBehaviour VarPop.");
+ // Pop the arguments..
+ stackchange -= signature.ArgumentCount;
+ // Pop native function pointer off the stack.
+ stackchange--;
+ UpdateStackSize(opcode, stackchange);
+ }
+
+ RecordTokenFixup();
+ PutInteger4(tempVal);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual void Emit(OpCode opcode, ConstructorInfo con)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ Contract.EndContractBlock();
+
+ int stackchange = 0;
+
+ // Constructors cannot be generic so the value of UseMethodDef doesn't matter.
+ int tk = GetMethodToken(con, null, true);
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ // Make a conservative estimate by assuming a return type and no
+ // this parameter.
+ if (opcode.StackBehaviourPush == StackBehaviour.Varpush)
+ {
+ // Instruction must be one of call or callvirt.
+ Contract.Assert(opcode.Equals(OpCodes.Call) ||
+ opcode.Equals(OpCodes.Callvirt),
+ "Unexpected opcode encountered for StackBehaviour of VarPush.");
+ stackchange++;
+ }
+ if (opcode.StackBehaviourPop == StackBehaviour.Varpop)
+ {
+ // Instruction must be one of call, callvirt or newobj.
+ Contract.Assert(opcode.Equals(OpCodes.Call) ||
+ opcode.Equals(OpCodes.Callvirt) ||
+ opcode.Equals(OpCodes.Newobj),
+ "Unexpected opcode encountered for StackBehaviour of VarPop.");
+
+ Type[] parameters = con.GetParameterTypes();
+ if (parameters != null)
+ stackchange -= parameters.Length;
+ }
+ UpdateStackSize(opcode, stackchange);
+
+ RecordTokenFixup();
+ PutInteger4(tk);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void Emit(OpCode opcode, Type cls)
+ {
+ // Puts opcode onto the stream and then the metadata token represented
+ // by cls. The location of cls is recorded so that the token can be
+ // patched if necessary when persisting the module to a PE.
+
+ int tempVal = 0;
+ ModuleBuilder modBuilder = (ModuleBuilder) m_methodBuilder.Module;
+ if (opcode == OpCodes.Ldtoken && cls != null && cls.IsGenericTypeDefinition)
+ {
+ // This gets the token for the generic type definition if cls is one.
+ tempVal = modBuilder.GetTypeToken( cls ).Token;
+ }
+ else
+ {
+ // This gets the token for the generic type instantiated on the formal parameters
+ // if cls is a generic type definition.
+ tempVal = modBuilder.GetTypeTokenInternal(cls).Token;
+ }
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ RecordTokenFixup();
+ PutInteger4(tempVal);
+ }
+
+ public virtual void Emit(OpCode opcode, long arg) {
+ EnsureCapacity(11);
+ InternalEmit(opcode);
+ m_ILStream[m_length++] = (byte) arg;
+ m_ILStream[m_length++] = (byte) (arg>>8);
+ m_ILStream[m_length++] = (byte) (arg>>16);
+ m_ILStream[m_length++] = (byte) (arg>>24);
+ m_ILStream[m_length++] = (byte) (arg>>32);
+ m_ILStream[m_length++] = (byte) (arg>>40);
+ m_ILStream[m_length++] = (byte) (arg>>48);
+ m_ILStream[m_length++] = (byte) (arg>>56);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public virtual void Emit(OpCode opcode, float arg) {
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ uint tempVal = *(uint*)&arg;
+ m_ILStream[m_length++] = (byte) tempVal;
+ m_ILStream[m_length++] = (byte) (tempVal>>8);
+ m_ILStream[m_length++] = (byte) (tempVal>>16);
+ m_ILStream[m_length++] = (byte) (tempVal>>24);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public virtual void Emit(OpCode opcode, double arg) {
+ EnsureCapacity(11);
+ InternalEmit(opcode);
+ ulong tempVal = *(ulong*)&arg;
+ m_ILStream[m_length++] = (byte) tempVal;
+ m_ILStream[m_length++] = (byte) (tempVal>>8);
+ m_ILStream[m_length++] = (byte) (tempVal>>16);
+ m_ILStream[m_length++] = (byte) (tempVal>>24);
+ m_ILStream[m_length++] = (byte) (tempVal>>32);
+ m_ILStream[m_length++] = (byte) (tempVal>>40);
+ m_ILStream[m_length++] = (byte) (tempVal>>48);
+ m_ILStream[m_length++] = (byte) (tempVal>>56);
+ }
+
+ public virtual void Emit(OpCode opcode, Label label)
+ {
+ // Puts opcode onto the stream and leaves space to include label
+ // when fixups are done. Labels are created using ILGenerator.DefineLabel and
+ // their location within the stream is fixed by using ILGenerator.MarkLabel.
+ // If a single-byte instruction (designated by the _S suffix in OpCodes.cs) is used,
+ // the label can represent a jump of at most 127 bytes along the stream.
+ //
+ // opcode must represent a branch instruction (although we don't explicitly
+ // verify this). Since branches are relative instructions, label will be replaced with the
+ // correct offset to branch during the fixup process.
+
+ int tempVal = label.GetLabelValue();
+ EnsureCapacity(7);
+
+
+ InternalEmit(opcode);
+ if (OpCodes.TakesSingleByteArgument(opcode)) {
+ AddFixup(label, m_length, 1);
+ m_length++;
+ } else {
+ AddFixup(label, m_length, 4);
+ m_length+=4;
+ }
+ }
+
+ public virtual void Emit(OpCode opcode, Label[] labels)
+ {
+ if (labels == null)
+ throw new ArgumentNullException("labels");
+ Contract.EndContractBlock();
+
+ // Emitting a switch table
+
+ int i;
+ int remaining; // number of bytes remaining for this switch instruction to be substracted
+ // for computing the offset
+
+ int count = labels.Length;
+
+ EnsureCapacity( count * 4 + 7 );
+ InternalEmit(opcode);
+ PutInteger4(count);
+ for ( remaining = count * 4, i = 0; remaining > 0; remaining -= 4, i++ ) {
+ AddFixup( labels[i], m_length, remaining );
+ m_length += 4;
+ }
+ }
+
+ public virtual void Emit(OpCode opcode, FieldInfo field)
+ {
+ ModuleBuilder modBuilder = (ModuleBuilder) m_methodBuilder.Module;
+ int tempVal = modBuilder.GetFieldToken( field ).Token;
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ RecordTokenFixup();
+ PutInteger4(tempVal);
+ }
+
+ public virtual void Emit(OpCode opcode, String str)
+ {
+ // Puts the opcode onto the IL stream followed by the metadata token
+ // represented by str. The location of str is recorded for future
+ // fixups if the module is persisted to a PE.
+
+ ModuleBuilder modBuilder = (ModuleBuilder) m_methodBuilder.Module;
+ int tempVal = modBuilder.GetStringConstant(str).Token;
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+ PutInteger4(tempVal);
+ }
+
+ public virtual void Emit(OpCode opcode, LocalBuilder local)
+ {
+ // Puts the opcode onto the IL stream followed by the information for local variable local.
+
+ if (local == null)
+ {
+ throw new ArgumentNullException("local");
+ }
+ Contract.EndContractBlock();
+ int tempVal = local.GetLocalIndex();
+ if (local.GetMethodBuilder() != m_methodBuilder)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchedMethodForLocal"), "local");
+ }
+ // If the instruction is a ldloc, ldloca a stloc, morph it to the optimal form.
+ if (opcode.Equals(OpCodes.Ldloc))
+ {
+ switch(tempVal)
+ {
+ case 0:
+ opcode = OpCodes.Ldloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Ldloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Ldloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Ldloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloc_S;
+ break;
+ }
+ }
+ else if (opcode.Equals(OpCodes.Stloc))
+ {
+ switch(tempVal)
+ {
+ case 0:
+ opcode = OpCodes.Stloc_0;
+ break;
+ case 1:
+ opcode = OpCodes.Stloc_1;
+ break;
+ case 2:
+ opcode = OpCodes.Stloc_2;
+ break;
+ case 3:
+ opcode = OpCodes.Stloc_3;
+ break;
+ default:
+ if (tempVal <= 255)
+ opcode = OpCodes.Stloc_S;
+ break;
+ }
+ }
+ else if (opcode.Equals(OpCodes.Ldloca))
+ {
+ if (tempVal <= 255)
+ opcode = OpCodes.Ldloca_S;
+ }
+
+ EnsureCapacity(7);
+ InternalEmit(opcode);
+
+ if (opcode.OperandType == OperandType.InlineNone)
+ return;
+ else if (!OpCodes.TakesSingleByteArgument(opcode))
+ {
+ m_ILStream[m_length++]=(byte) tempVal;
+ m_ILStream[m_length++]=(byte) (tempVal>>8);
+ }
+ else
+ {
+ //Handle stloc_1, ldloc_1
+ if (tempVal > Byte.MaxValue)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadInstructionOrIndexOutOfBound"));
+ }
+ m_ILStream[m_length++]=(byte)tempVal;
+ }
+ }
+ #endregion
+
+ #region Exceptions
+ public virtual Label BeginExceptionBlock()
+ {
+ // Begin an Exception block. Creating an Exception block records some information,
+ // but does not actually emit any IL onto the stream. Exceptions should be created and
+ // marked in the following form:
+ //
+ // Emit Some IL
+ // BeginExceptionBlock
+ // Emit the IL which should appear within the "try" block
+ // BeginCatchBlock
+ // Emit the IL which should appear within the "catch" block
+ // Optional: BeginCatchBlock (this can be repeated an arbitrary number of times
+ // EndExceptionBlock
+
+ // Delay init
+ if (m_exceptions == null)
+ {
+ m_exceptions = new __ExceptionInfo[DefaultExceptionArraySize];
+ }
+
+ if (m_currExcStack == null)
+ {
+ m_currExcStack = new __ExceptionInfo[DefaultExceptionArraySize];
+ }
+
+ if (m_exceptionCount>=m_exceptions.Length) {
+ m_exceptions=EnlargeArray(m_exceptions);
+ }
+
+ if (m_currExcStackCount>=m_currExcStack.Length) {
+ m_currExcStack = EnlargeArray(m_currExcStack);
+ }
+
+ Label endLabel = DefineLabel();
+ __ExceptionInfo exceptionInfo = new __ExceptionInfo(m_length, endLabel);
+
+ // add the exception to the tracking list
+ m_exceptions[m_exceptionCount++] = exceptionInfo;
+
+ // Make this exception the current active exception
+ m_currExcStack[m_currExcStackCount++] = exceptionInfo;
+ return endLabel;
+ }
+
+ public virtual void EndExceptionBlock() {
+ if (m_currExcStackCount==0) {
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+ }
+
+ // Pop the current exception block
+ __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1];
+ m_currExcStack[m_currExcStackCount-1] = null;
+ m_currExcStackCount--;
+
+ Label endLabel = current.GetEndLabel();
+ int state = current.GetCurrentState();
+
+ if (state == __ExceptionInfo.State_Filter ||
+ state == __ExceptionInfo.State_Try)
+ {
+
+
+ throw new InvalidOperationException(Environment.GetResourceString("Argument_BadExceptionCodeGen"));
+ }
+
+ if (state == __ExceptionInfo.State_Catch) {
+ this.Emit(OpCodes.Leave, endLabel);
+ } else if (state == __ExceptionInfo.State_Finally || state == __ExceptionInfo.State_Fault) {
+ this.Emit(OpCodes.Endfinally);
+ }
+
+ //Check if we've alredy set this label.
+ //The only reason why we might have set this is if we have a finally block.
+ if (m_labelList[endLabel.GetLabelValue()]==-1) {
+ MarkLabel(endLabel);
+ } else {
+ MarkLabel(current.GetFinallyEndLabel());
+ }
+
+ current.Done(m_length);
+ }
+
+ public virtual void BeginExceptFilterBlock()
+ {
+ // Begins a eception filter block. Emits a branch instruction to the end of the current exception block.
+
+ if (m_currExcStackCount == 0)
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+
+ __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1];
+
+ Label endLabel = current.GetEndLabel();
+ this.Emit(OpCodes.Leave, endLabel);
+
+ current.MarkFilterAddr(m_length);
+ }
+
+ public virtual void BeginCatchBlock(Type exceptionType)
+ {
+ // Begins a catch block. Emits a branch instruction to the end of the current exception block.
+
+ if (m_currExcStackCount==0) {
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+ }
+ __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1];
+
+ if (current.GetCurrentState() == __ExceptionInfo.State_Filter) {
+ if (exceptionType != null) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ShouldNotSpecifyExceptionType"));
+ }
+
+ this.Emit(OpCodes.Endfilter);
+ } else {
+ // execute this branch if previous clause is Catch or Fault
+ if (exceptionType==null) {
+ throw new ArgumentNullException("exceptionType");
+ }
+
+ Label endLabel = current.GetEndLabel();
+ this.Emit(OpCodes.Leave, endLabel);
+
+ }
+
+ current.MarkCatchAddr(m_length, exceptionType);
+ }
+
+ public virtual void BeginFaultBlock()
+ {
+ if (m_currExcStackCount==0) {
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+ }
+ __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1];
+
+ // emit the leave for the clause before this one.
+ Label endLabel = current.GetEndLabel();
+ this.Emit(OpCodes.Leave, endLabel);
+
+ current.MarkFaultAddr(m_length);
+ }
+
+ public virtual void BeginFinallyBlock()
+ {
+ if (m_currExcStackCount==0) {
+ throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
+ }
+ __ExceptionInfo current = m_currExcStack[m_currExcStackCount-1];
+ int state = current.GetCurrentState();
+ Label endLabel = current.GetEndLabel();
+ int catchEndAddr = 0;
+ if (state != __ExceptionInfo.State_Try)
+ {
+ // generate leave for any preceeding catch clause
+ this.Emit(OpCodes.Leave, endLabel);
+ catchEndAddr = m_length;
+ }
+
+ MarkLabel(endLabel);
+
+
+ Label finallyEndLabel = this.DefineLabel();
+ current.SetFinallyEndLabel(finallyEndLabel);
+
+ // generate leave for try clause
+ this.Emit(OpCodes.Leave, finallyEndLabel);
+ if (catchEndAddr == 0)
+ catchEndAddr = m_length;
+ current.MarkFinallyAddr(m_length, catchEndAddr);
+ }
+
+ #endregion
+
+ #region Labels
+ public virtual Label DefineLabel()
+ {
+ // Declares a new Label. This is just a token and does not yet represent any particular location
+ // within the stream. In order to set the position of the label within the stream, you must call
+ // Mark Label.
+
+ // Delay init the lable array in case we dont use it
+ if (m_labelList == null){
+ m_labelList = new int[DefaultLabelArraySize];
+ }
+
+ if (m_labelCount>=m_labelList.Length) {
+ m_labelList = EnlargeArray(m_labelList);
+ }
+ m_labelList[m_labelCount]=-1;
+ return new Label(m_labelCount++);
+ }
+
+ public virtual void MarkLabel(Label loc)
+ {
+ // Defines a label by setting the position where that label is found within the stream.
+ // Does not allow a label to be defined more than once.
+
+ int labelIndex = loc.GetLabelValue();
+
+ //This should never happen.
+ if (labelIndex<0 || labelIndex>=m_labelList.Length) {
+ throw new ArgumentException (Environment.GetResourceString("Argument_InvalidLabel"));
+ }
+
+ if (m_labelList[labelIndex]!=-1) {
+ throw new ArgumentException (Environment.GetResourceString("Argument_RedefinedLabel"));
+ }
+
+ m_labelList[labelIndex]=m_length;
+ }
+
+ #endregion
+
+ #region IL Macros
+ public virtual void ThrowException(Type excType)
+ {
+ // Emits the il to throw an exception
+
+ if (excType==null) {
+ throw new ArgumentNullException("excType");
+ }
+
+ if (!excType.IsSubclassOf(typeof(Exception)) && excType!=typeof(Exception)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotExceptionType"));
+ }
+ Contract.EndContractBlock();
+ ConstructorInfo con = excType.GetConstructor(Type.EmptyTypes);
+ if (con==null) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_MissingDefaultConstructor"));
+ }
+ this.Emit(OpCodes.Newobj, con);
+ this.Emit(OpCodes.Throw);
+ }
+
+ private static Type GetConsoleType()
+ {
+#if FEATURE_LEGACYSURFACE
+ return typeof(Console);
+#else
+ return Type.GetType(
+ "System.Console, System.Console, Version=4.0.0.0, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ throwOnError: true);
+#endif
+ }
+
+ public virtual void EmitWriteLine(String value)
+ {
+ // Emits the IL to call Console.WriteLine with a string.
+
+ Emit(OpCodes.Ldstr, value);
+ Type[] parameterTypes = new Type[1];
+ parameterTypes[0] = typeof(String);
+ MethodInfo mi = GetConsoleType().GetMethod("WriteLine", parameterTypes);
+ Emit(OpCodes.Call, mi);
+ }
+
+ public virtual void EmitWriteLine(LocalBuilder localBuilder)
+ {
+ // Emits the IL necessary to call WriteLine with lcl. It is
+ // an error to call EmitWriteLine with a lcl which is not of
+ // one of the types for which Console.WriteLine implements overloads. (e.g.
+ // we do *not* call ToString on the locals.
+
+ Object cls;
+ if (m_methodBuilder==null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_BadILGeneratorUsage"));
+ }
+
+ MethodInfo prop = GetConsoleType().GetMethod("get_Out");
+ Emit(OpCodes.Call, prop);
+ Emit(OpCodes.Ldloc, localBuilder);
+ Type[] parameterTypes = new Type[1];
+ cls = localBuilder.LocalType;
+ if (cls is TypeBuilder || cls is EnumBuilder) {
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder"));
+ }
+ parameterTypes[0] = (Type)cls;
+ MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes);
+ if (mi==null) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "localBuilder");
+ }
+
+ Emit(OpCodes.Callvirt, mi);
+ }
+
+ public virtual void EmitWriteLine(FieldInfo fld)
+ {
+ // Emits the IL necessary to call WriteLine with fld. It is
+ // an error to call EmitWriteLine with a fld which is not of
+ // one of the types for which Console.WriteLine implements overloads. (e.g.
+ // we do *not* call ToString on the fields.
+
+ Object cls;
+
+ if (fld == null)
+ {
+ throw new ArgumentNullException("fld");
+ }
+ Contract.EndContractBlock();
+
+ MethodInfo prop = GetConsoleType().GetMethod("get_Out");
+ Emit(OpCodes.Call, prop);
+
+ if ((fld.Attributes & FieldAttributes.Static)!=0) {
+ Emit(OpCodes.Ldsfld, fld);
+ } else {
+ Emit(OpCodes.Ldarg, (short)0); //Load the this ref.
+ Emit(OpCodes.Ldfld, fld);
+ }
+ Type[] parameterTypes = new Type[1];
+ cls = fld.FieldType;
+ if (cls is TypeBuilder || cls is EnumBuilder) {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder"));
+ }
+ parameterTypes[0] = (Type)cls;
+ MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes);
+ if (mi==null) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "fld");
+ }
+ Emit(OpCodes.Callvirt, mi);
+ }
+
+ #endregion
+
+ #region Debug API
+ public virtual LocalBuilder DeclareLocal(Type localType)
+ {
+ return DeclareLocal(localType, false);
+ }
+
+ public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
+ {
+ // Declare a local of type "local". The current active lexical scope
+ // will be the scope that local will live.
+
+ LocalBuilder localBuilder;
+
+ MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
+ if (methodBuilder == null)
+ throw new NotSupportedException();
+
+ if (methodBuilder.IsTypeCreated())
+ {
+ // cannot change method after its containing type has been created
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated"));
+ }
+
+ if (localType==null) {
+ throw new ArgumentNullException("localType");
+ }
+
+ if (methodBuilder.m_bIsBaked) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked"));
+ }
+
+ // add the localType to local signature
+ m_localSignature.AddArgument(localType, pinned);
+
+ localBuilder = new LocalBuilder(m_localCount, localType, methodBuilder, pinned);
+ m_localCount++;
+ return localBuilder;
+ }
+
+ public virtual void UsingNamespace(String usingNamespace)
+ {
+ // Specifying the namespace to be used in evaluating locals and watches
+ // for the current active lexical scope.
+
+ if (usingNamespace == null)
+ throw new ArgumentNullException("usingNamespace");
+
+ if (usingNamespace.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "usingNamespace");
+ Contract.EndContractBlock();
+
+ int index;
+ MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
+ if (methodBuilder == null)
+ throw new NotSupportedException();
+
+ index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex();
+ if (index == -1)
+ {
+ methodBuilder.m_localSymInfo.AddUsingNamespace(usingNamespace);
+ }
+ else
+ {
+ m_ScopeTree.AddUsingNamespaceToCurrentScope(usingNamespace);
+ }
+ }
+
+ public virtual void MarkSequencePoint(
+ ISymbolDocumentWriter document,
+ int startLine, // line number is 1 based
+ int startColumn, // column is 0 based
+ int endLine, // line number is 1 based
+ int endColumn) // column is 0 based
+ {
+ if (startLine == 0 || startLine < 0 || endLine == 0 || endLine < 0)
+ {
+ throw new ArgumentOutOfRangeException("startLine");
+ }
+ Contract.EndContractBlock();
+ m_LineNumberInfo.AddLineNumberInfo(document, m_length, startLine, startColumn, endLine, endColumn);
+ }
+
+ public virtual void BeginScope()
+ {
+ m_ScopeTree.AddScopeInfo(ScopeAction.Open, m_length);
+ }
+
+ public virtual void EndScope()
+ {
+ m_ScopeTree.AddScopeInfo(ScopeAction.Close, m_length);
+ }
+
+ public virtual int ILOffset
+ {
+ get
+ {
+ return m_length;
+ }
+ }
+
+ #endregion
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _ILGenerator.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ILGenerator.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ILGenerator.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ILGenerator.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ internal struct __FixupData
+ {
+ internal Label m_fixupLabel;
+ internal int m_fixupPos;
+
+ internal int m_fixupInstSize;
+ }
+
+ internal sealed class __ExceptionInfo {
+
+ internal const int None = 0x0000; //COR_ILEXCEPTION_CLAUSE_NONE
+ internal const int Filter = 0x0001; //COR_ILEXCEPTION_CLAUSE_FILTER
+ internal const int Finally = 0x0002; //COR_ILEXCEPTION_CLAUSE_FINALLY
+ internal const int Fault = 0x0004; //COR_ILEXCEPTION_CLAUSE_FAULT
+ internal const int PreserveStack = 0x0004; //COR_ILEXCEPTION_CLAUSE_PRESERVESTACK
+
+ internal const int State_Try = 0;
+ internal const int State_Filter =1;
+ internal const int State_Catch = 2;
+ internal const int State_Finally = 3;
+ internal const int State_Fault = 4;
+ internal const int State_Done = 5;
+
+ internal int m_startAddr;
+ internal int []m_filterAddr;
+ internal int []m_catchAddr;
+ internal int []m_catchEndAddr;
+ internal int []m_type;
+ internal Type []m_catchClass;
+ internal Label m_endLabel;
+ internal Label m_finallyEndLabel;
+ internal int m_endAddr;
+ internal int m_endFinally;
+ internal int m_currentCatch;
+
+ int m_currentState;
+
+
+ //This will never get called. The values exist merely to keep the
+ //compiler happy.
+ private __ExceptionInfo() {
+ m_startAddr = 0;
+ m_filterAddr = null;
+ m_catchAddr = null;
+ m_catchEndAddr = null;
+ m_endAddr = 0;
+ m_currentCatch = 0;
+ m_type = null;
+ m_endFinally = -1;
+ m_currentState = State_Try;
+ }
+
+ internal __ExceptionInfo(int startAddr, Label endLabel) {
+ m_startAddr=startAddr;
+ m_endAddr=-1;
+ m_filterAddr=new int[4];
+ m_catchAddr=new int[4];
+ m_catchEndAddr=new int[4];
+ m_catchClass=new Type[4];
+ m_currentCatch=0;
+ m_endLabel=endLabel;
+ m_type=new int[4];
+ m_endFinally=-1;
+ m_currentState = State_Try;
+ }
+
+ private void MarkHelper(
+ int catchorfilterAddr, // the starting address of a clause
+ int catchEndAddr, // the end address of a previous catch clause. Only use when finally is following a catch
+ Type catchClass, // catch exception type
+ int type) // kind of clause
+ {
+ if (m_currentCatch>=m_catchAddr.Length) {
+ m_filterAddr=ILGenerator.EnlargeArray(m_filterAddr);
+ m_catchAddr=ILGenerator.EnlargeArray(m_catchAddr);
+ m_catchEndAddr=ILGenerator.EnlargeArray(m_catchEndAddr);
+ m_catchClass=ILGenerator.EnlargeArray(m_catchClass);
+ m_type = ILGenerator.EnlargeArray(m_type);
+ }
+ if (type == Filter)
+ {
+ m_type[m_currentCatch]=type;
+ m_filterAddr[m_currentCatch] = catchorfilterAddr;
+ m_catchAddr[m_currentCatch] = -1;
+ if (m_currentCatch > 0)
+ {
+ Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1");
+ m_catchEndAddr[m_currentCatch-1] = catchorfilterAddr;
+ }
+ }
+ else
+ {
+ // catch or Fault clause
+ m_catchClass[m_currentCatch]=catchClass;
+ if (m_type[m_currentCatch] != Filter)
+ {
+ m_type[m_currentCatch]=type;
+ }
+ m_catchAddr[m_currentCatch]=catchorfilterAddr;
+ if (m_currentCatch > 0)
+ {
+ if (m_type[m_currentCatch] != Filter)
+ {
+ Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1");
+ m_catchEndAddr[m_currentCatch-1] = catchEndAddr;
+ }
+ }
+ m_catchEndAddr[m_currentCatch]=-1;
+ m_currentCatch++;
+ }
+
+ if (m_endAddr==-1)
+ {
+ m_endAddr=catchorfilterAddr;
+ }
+ }
+
+ internal void MarkFilterAddr(int filterAddr)
+ {
+ m_currentState = State_Filter;
+ MarkHelper(filterAddr, filterAddr, null, Filter);
+ }
+
+ internal void MarkFaultAddr(int faultAddr)
+ {
+ m_currentState = State_Fault;
+ MarkHelper(faultAddr, faultAddr, null, Fault);
+ }
+
+ internal void MarkCatchAddr(int catchAddr, Type catchException) {
+ m_currentState = State_Catch;
+ MarkHelper(catchAddr, catchAddr, catchException, None);
+ }
+
+ internal void MarkFinallyAddr(int finallyAddr, int endCatchAddr) {
+ if (m_endFinally!=-1) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_TooManyFinallyClause"));
+ } else {
+ m_currentState = State_Finally;
+ m_endFinally=finallyAddr;
+ }
+ MarkHelper(finallyAddr, endCatchAddr, null, Finally);
+ }
+
+ internal void Done(int endAddr) {
+ Contract.Assert(m_currentCatch > 0,"m_currentCatch > 0");
+ Contract.Assert(m_catchAddr[m_currentCatch-1] > 0,"m_catchAddr[m_currentCatch-1] > 0");
+ Contract.Assert(m_catchEndAddr[m_currentCatch-1] == -1,"m_catchEndAddr[m_currentCatch-1] == -1");
+ m_catchEndAddr[m_currentCatch-1] = endAddr;
+ m_currentState = State_Done;
+ }
+
+ internal int GetStartAddress() {
+ return m_startAddr;
+ }
+
+ internal int GetEndAddress() {
+ return m_endAddr;
+ }
+
+ internal int GetFinallyEndAddress() {
+ return m_endFinally;
+ }
+
+ internal Label GetEndLabel() {
+ return m_endLabel;
+ }
+
+ internal int [] GetFilterAddresses() {
+ return m_filterAddr;
+ }
+
+ internal int [] GetCatchAddresses() {
+ return m_catchAddr;
+ }
+
+ internal int [] GetCatchEndAddresses() {
+ return m_catchEndAddr;
+ }
+
+ internal Type [] GetCatchClass() {
+ return m_catchClass;
+ }
+
+ internal int GetNumberOfCatches() {
+ return m_currentCatch;
+ }
+
+ internal int[] GetExceptionTypes() {
+ return m_type;
+ }
+
+ internal void SetFinallyEndLabel(Label lbl) {
+ m_finallyEndLabel=lbl;
+ }
+
+ internal Label GetFinallyEndLabel() {
+ return m_finallyEndLabel;
+ }
+
+ // Specifies whether exc is an inner exception for "this". The way
+ // its determined is by comparing the end address for the last catch
+ // clause for both exceptions. If they're the same, the start address
+ // for the exception is compared.
+ // WARNING: This is not a generic function to determine the innerness
+ // of an exception. This is somewhat of a mis-nomer. This gives a
+ // random result for cases where the two exceptions being compared do
+ // not having a nesting relation.
+ internal bool IsInner(__ExceptionInfo exc) {
+ Contract.Requires(exc != null);
+ Contract.Assert(m_currentCatch > 0,"m_currentCatch > 0");
+ Contract.Assert(exc.m_currentCatch > 0,"exc.m_currentCatch > 0");
+
+ int exclast = exc.m_currentCatch - 1;
+ int last = m_currentCatch - 1;
+
+ if (exc.m_catchEndAddr[exclast] < m_catchEndAddr[last])
+ return true;
+ else if (exc.m_catchEndAddr[exclast] == m_catchEndAddr[last])
+ {
+ Contract.Assert(exc.GetEndAddress() != GetEndAddress(),
+ "exc.GetEndAddress() != GetEndAddress()");
+ if (exc.GetEndAddress() > GetEndAddress())
+ return true;
+ }
+ return false;
+ }
+
+ // 0 indicates in a try block
+ // 1 indicates in a filter block
+ // 2 indicates in a catch block
+ // 3 indicates in a finally block
+ // 4 indicates Done
+ internal int GetCurrentState() {
+ return m_currentState;
+ }
+ }
+
+
+ /***************************
+ *
+ * Scope Tree is a class that track the scope structure within a method body
+ * It keeps track two parallel array. m_ScopeAction keeps track the action. It can be
+ * OpenScope or CloseScope. m_iOffset records the offset where the action
+ * takes place.
+ *
+ ***************************/
+ [Serializable]
+ enum ScopeAction
+ {
+ Open = 0x0,
+ Close = 0x1,
+ }
+
+ internal sealed class ScopeTree
+ {
+ internal ScopeTree()
+ {
+ // initialize data variables
+ m_iOpenScopeCount = 0;
+ m_iCount = 0;
+ }
+
+ /***************************
+ *
+ * Find the current active lexcial scope. For example, if we have
+ * "Open Open Open Close",
+ * we will return 1 as the second BeginScope is currently active.
+ *
+ ***************************/
+ internal int GetCurrentActiveScopeIndex()
+ {
+ int cClose = 0;
+ int i = m_iCount - 1;
+
+ if (m_iCount == 0)
+ {
+ return -1;
+ }
+ for (; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--)
+ {
+ if (m_ScopeActions[i] == ScopeAction.Open)
+ {
+ cClose--;
+ }
+ else
+ cClose++;
+ }
+
+ return i;
+ }
+
+ internal void AddLocalSymInfoToCurrentScope(
+ String strName,
+ byte[] signature,
+ int slot,
+ int startOffset,
+ int endOffset)
+ {
+ int i = GetCurrentActiveScopeIndex();
+ if (m_localSymInfos[i] == null)
+ {
+ m_localSymInfos[i] = new LocalSymInfo();
+ }
+ m_localSymInfos[i].AddLocalSymInfo(strName, signature, slot, startOffset, endOffset);
+ }
+
+ internal void AddUsingNamespaceToCurrentScope(
+ String strNamespace)
+ {
+ int i = GetCurrentActiveScopeIndex();
+ if (m_localSymInfos[i] == null)
+ {
+ m_localSymInfos[i] = new LocalSymInfo();
+ }
+ m_localSymInfos[i].AddUsingNamespace(strNamespace);
+ }
+
+ internal void AddScopeInfo(ScopeAction sa, int iOffset)
+ {
+ if (sa == ScopeAction.Close && m_iOpenScopeCount <=0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchingSymScope"));
+ }
+ Contract.EndContractBlock();
+
+ // make sure that arrays are large enough to hold addition info
+ EnsureCapacity();
+
+
+ m_ScopeActions[m_iCount] = sa;
+ m_iOffsets[m_iCount] = iOffset;
+ m_localSymInfos[m_iCount] = null;
+ checked { m_iCount++; }
+ if (sa == ScopeAction.Open)
+ {
+ m_iOpenScopeCount++;
+ }
+ else
+ m_iOpenScopeCount--;
+
+ }
+
+ /**************************
+ *
+ * Helper to ensure arrays are large enough
+ *
+ **************************/
+ internal void EnsureCapacity()
+ {
+ if (m_iCount == 0)
+ {
+ // First time. Allocate the arrays.
+ m_iOffsets = new int[InitialSize];
+ m_ScopeActions = new ScopeAction[InitialSize];
+ m_localSymInfos = new LocalSymInfo[InitialSize];
+ }
+ else if (m_iCount == m_iOffsets.Length)
+ {
+ // the arrays are full. Enlarge the arrays
+ // It would probably be simpler to just use Lists here.
+ int newSize = checked(m_iCount * 2);
+ int[] temp = new int[newSize];
+ Array.Copy(m_iOffsets, 0, temp, 0, m_iCount);
+ m_iOffsets = temp;
+
+ ScopeAction[] tempSA = new ScopeAction[newSize];
+ Array.Copy(m_ScopeActions, 0, tempSA, 0, m_iCount);
+ m_ScopeActions = tempSA;
+
+ LocalSymInfo[] tempLSI = new LocalSymInfo[newSize];
+ Array.Copy(m_localSymInfos, 0, tempLSI, 0, m_iCount);
+ m_localSymInfos = tempLSI;
+ }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void EmitScopeTree(ISymbolWriter symWriter)
+ {
+ int i;
+ for (i = 0; i < m_iCount; i++)
+ {
+ if (m_ScopeActions[i] == ScopeAction.Open)
+ {
+ symWriter.OpenScope(m_iOffsets[i]);
+ }
+ else
+ {
+ symWriter.CloseScope(m_iOffsets[i]);
+ }
+ if (m_localSymInfos[i] != null)
+ {
+ m_localSymInfos[i].EmitLocalSymInfo(symWriter);
+ }
+ }
+ }
+
+ internal int[] m_iOffsets; // array of offsets
+ internal ScopeAction[] m_ScopeActions; // array of scope actions
+ internal int m_iCount; // how many entries in the arrays are occupied
+ internal int m_iOpenScopeCount; // keep track how many scopes are open
+ internal const int InitialSize = 16;
+ internal LocalSymInfo[] m_localSymInfos; // keep track debugging local information
+ }
+
+
+ /***************************
+ *
+ * This class tracks the line number info
+ *
+ ***************************/
+ internal sealed class LineNumberInfo
+ {
+ internal LineNumberInfo()
+ {
+ // initialize data variables
+ m_DocumentCount = 0;
+ m_iLastFound = 0;
+ }
+
+ internal void AddLineNumberInfo(
+ ISymbolDocumentWriter document,
+ int iOffset,
+ int iStartLine,
+ int iStartColumn,
+ int iEndLine,
+ int iEndColumn)
+ {
+ int i;
+
+ // make sure that arrays are large enough to hold addition info
+ i = FindDocument(document);
+
+ Contract.Assert(i < m_DocumentCount, "Bad document look up!");
+ m_Documents[i].AddLineNumberInfo(document, iOffset, iStartLine, iStartColumn, iEndLine, iEndColumn);
+ }
+
+ // Find a REDocument representing document. If we cannot find one, we will add a new entry into
+ // the REDocument array.
+ private int FindDocument(ISymbolDocumentWriter document)
+ {
+ int i;
+
+ // This is an optimization. The chance that the previous line is coming from the same
+ // document is very high.
+ if (m_iLastFound < m_DocumentCount && m_Documents[m_iLastFound].m_document == document)
+ return m_iLastFound;
+
+ for (i = 0; i < m_DocumentCount; i++)
+ {
+ if (m_Documents[i].m_document == document)
+ {
+ m_iLastFound = i;
+ return m_iLastFound;
+ }
+ }
+
+ // cannot find an existing document so add one to the array
+ EnsureCapacity();
+ m_iLastFound = m_DocumentCount;
+ m_Documents[m_iLastFound] = new REDocument(document);
+ checked { m_DocumentCount++; }
+ return m_iLastFound;
+ }
+
+ /**************************
+ *
+ * Helper to ensure arrays are large enough
+ *
+ **************************/
+ private void EnsureCapacity()
+ {
+ if (m_DocumentCount == 0)
+ {
+ // First time. Allocate the arrays.
+ m_Documents = new REDocument[InitialSize];
+ }
+ else if (m_DocumentCount == m_Documents.Length)
+ {
+ // the arrays are full. Enlarge the arrays
+ REDocument[] temp = new REDocument [m_DocumentCount * 2];
+ Array.Copy(m_Documents, 0, temp, 0, m_DocumentCount);
+ m_Documents = temp;
+ }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void EmitLineNumberInfo(ISymbolWriter symWriter)
+ {
+ for (int i = 0; i < m_DocumentCount; i++)
+ m_Documents[i].EmitLineNumberInfo(symWriter);
+ }
+
+ private int m_DocumentCount; // how many documents that we have right now
+ private REDocument[] m_Documents; // array of documents
+ private const int InitialSize = 16;
+ private int m_iLastFound;
+ }
+
+
+ /***************************
+ *
+ * This class tracks the line number info
+ *
+ ***************************/
+ internal sealed class REDocument
+ {
+ internal REDocument(ISymbolDocumentWriter document)
+ {
+ // initialize data variables
+ m_iLineNumberCount = 0;
+ m_document = document;
+ }
+
+ internal void AddLineNumberInfo(
+ ISymbolDocumentWriter document,
+ int iOffset,
+ int iStartLine,
+ int iStartColumn,
+ int iEndLine,
+ int iEndColumn)
+ {
+ Contract.Assert(document == m_document, "Bad document look up!");
+
+ // make sure that arrays are large enough to hold addition info
+ EnsureCapacity();
+
+ m_iOffsets[m_iLineNumberCount] = iOffset;
+ m_iLines[m_iLineNumberCount] = iStartLine;
+ m_iColumns[m_iLineNumberCount] = iStartColumn;
+ m_iEndLines[m_iLineNumberCount] = iEndLine;
+ m_iEndColumns[m_iLineNumberCount] = iEndColumn;
+ checked { m_iLineNumberCount++; }
+ }
+
+ /**************************
+ *
+ * Helper to ensure arrays are large enough
+ *
+ **************************/
+ private void EnsureCapacity()
+ {
+ if (m_iLineNumberCount == 0)
+ {
+ // First time. Allocate the arrays.
+ m_iOffsets = new int[InitialSize];
+ m_iLines = new int[InitialSize];
+ m_iColumns = new int[InitialSize];
+ m_iEndLines = new int[InitialSize];
+ m_iEndColumns = new int[InitialSize];
+ }
+ else if (m_iLineNumberCount == m_iOffsets.Length)
+ {
+ // the arrays are full. Enlarge the arrays
+ // It would probably be simpler to just use Lists here
+ int newSize = checked(m_iLineNumberCount * 2);
+ int[] temp = new int [newSize];
+ Array.Copy(m_iOffsets, 0, temp, 0, m_iLineNumberCount);
+ m_iOffsets = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iLines, 0, temp, 0, m_iLineNumberCount);
+ m_iLines = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iColumns, 0, temp, 0, m_iLineNumberCount);
+ m_iColumns = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iEndLines, 0, temp, 0, m_iLineNumberCount);
+ m_iEndLines = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iEndColumns, 0, temp, 0, m_iLineNumberCount);
+ m_iEndColumns = temp;
+ }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void EmitLineNumberInfo(ISymbolWriter symWriter)
+ {
+ int[] iOffsetsTemp;
+ int[] iLinesTemp;
+ int[] iColumnsTemp;
+ int[] iEndLinesTemp;
+ int[] iEndColumnsTemp;
+
+ if (m_iLineNumberCount == 0)
+ return;
+ // reduce the array size to be exact
+ iOffsetsTemp = new int [m_iLineNumberCount];
+ Array.Copy(m_iOffsets, 0, iOffsetsTemp, 0, m_iLineNumberCount);
+
+ iLinesTemp = new int [m_iLineNumberCount];
+ Array.Copy(m_iLines, 0, iLinesTemp, 0, m_iLineNumberCount);
+
+ iColumnsTemp = new int [m_iLineNumberCount];
+ Array.Copy(m_iColumns, 0, iColumnsTemp, 0, m_iLineNumberCount);
+
+ iEndLinesTemp = new int [m_iLineNumberCount];
+ Array.Copy(m_iEndLines, 0, iEndLinesTemp, 0, m_iLineNumberCount);
+
+ iEndColumnsTemp = new int [m_iLineNumberCount];
+ Array.Copy(m_iEndColumns, 0, iEndColumnsTemp, 0, m_iLineNumberCount);
+
+ symWriter.DefineSequencePoints(m_document, iOffsetsTemp, iLinesTemp, iColumnsTemp, iEndLinesTemp, iEndColumnsTemp);
+ }
+
+ private int[] m_iOffsets; // array of offsets
+ private int[] m_iLines; // array of offsets
+ private int[] m_iColumns; // array of offsets
+ private int[] m_iEndLines; // array of offsets
+ private int[] m_iEndColumns; // array of offsets
+ internal ISymbolDocumentWriter m_document; // The ISymbolDocumentWriter that this REDocument is tracking.
+ private int m_iLineNumberCount; // how many entries in the arrays are occupied
+ private const int InitialSize = 16;
+ } // end of REDocument
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs b/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs
new file mode 100644
index 0000000000..00fdd00315
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ISymWrapperCore.cs
@@ -0,0 +1,828 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+#if FEATURE_CORECLR
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Security;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.SymbolStore;
+
+
+ //-----------------------------------------------------------------------------------
+ // On Telesto, we don't ship the ISymWrapper.dll assembly. However, ReflectionEmit
+ // relies on that assembly to write out managed PDBs.
+ //
+ // This file implements the minimum subset of ISymWrapper.dll required to restore
+ // that functionality. Namely, the SymWriter and SymDocumentWriter objects.
+ //
+ // Ideally we wouldn't need ISymWrapper.dll on desktop either - it's an ugly piece
+ // of legacy. We could just use this (or COM-interop code) everywhere, but we might
+ // have to worry about compatibility.
+ //
+ // We've now got a real implementation even when no debugger is attached. It's
+ // up to the runtime to ensure it doesn't provide us with an insecure writer
+ // (eg. diasymreader) in the no-trust scenarios (no debugger, partial-trust code).
+ //-----------------------------------------------------------------------------------
+
+
+ //------------------------------------------------------------------------------
+ // SymWrapperCore is never instantiated and is used as an encapsulation class.
+ // It is our "ISymWrapper.dll" assembly within an assembly.
+ //------------------------------------------------------------------------------
+ class SymWrapperCore
+ {
+ //------------------------------------------------------------------------------
+ // Block instantiation
+ //------------------------------------------------------------------------------
+ private SymWrapperCore()
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ // Implements Telesto's version of SymDocumentWriter (in the desktop world,
+ // this type is exposed from ISymWrapper.dll.)
+ //
+ // The only thing user code can do with this wrapper is to receive it from
+ // SymWriter.DefineDocument and pass it back to SymWriter.DefineSequencePoints.
+ //------------------------------------------------------------------------------
+ private unsafe class SymDocumentWriter : ISymbolDocumentWriter
+ {
+
+ //------------------------------------------------------------------------------
+ // Ctor
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal SymDocumentWriter(PunkSafeHandle pDocumentWriterSafeHandle)
+ {
+ m_pDocumentWriterSafeHandle = pDocumentWriterSafeHandle;
+ // The handle is actually a pointer to a native ISymUnmanagedDocumentWriter.
+ m_pDocWriter = (ISymUnmanagedDocumentWriter *)m_pDocumentWriterSafeHandle.DangerousGetHandle();
+ m_vtable = (ISymUnmanagedDocumentWriterVTable)(Marshal.PtrToStructure(m_pDocWriter->m_unmanagedVTable, typeof(ISymUnmanagedDocumentWriterVTable)));
+ }
+
+ //------------------------------------------------------------------------------
+ // Returns the underlying ISymUnmanagedDocumentWriter* (as a safehandle.)
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal PunkSafeHandle GetUnmanaged()
+ {
+ return m_pDocumentWriterSafeHandle;
+ }
+
+
+ //=========================================================================================
+ // Public interface methods start here. (Well actually, they're all NotSupported
+ // stubs since that's what they are on the real ISymWrapper.dll.)
+ //=========================================================================================
+
+ //------------------------------------------------------------------------------
+ // SetSource() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolDocumentWriter.SetSource(byte[] source)
+ {
+ throw new NotSupportedException(); // Intentionally not supported to match desktop CLR
+ }
+
+ //------------------------------------------------------------------------------
+ // SetCheckSum() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+ #endif
+ void ISymbolDocumentWriter.SetCheckSum(Guid algorithmId, byte [] checkSum)
+ {
+ int hr = m_vtable.SetCheckSum(m_pDocWriter, algorithmId, (uint)checkSum.Length, checkSum);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private delegate int DSetCheckSum(ISymUnmanagedDocumentWriter * pThis, Guid algorithmId, uint checkSumSize, [In] byte[] checkSum);
+
+ //------------------------------------------------------------------------------
+ // This layout must match the unmanaged ISymUnmanagedDocumentWriter* COM vtable
+ // exactly. If a member is declared as an IntPtr rather than a delegate, it means
+ // we don't call that particular member.
+ //------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ISymUnmanagedDocumentWriterVTable
+ {
+ internal IntPtr QueryInterface;
+ internal IntPtr AddRef;
+ internal IntPtr Release;
+
+ internal IntPtr SetSource;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+ #endif
+ internal DSetCheckSum SetCheckSum;
+ }
+
+ //------------------------------------------------------------------------------
+ // This layout must match the (start) of the unmanaged ISymUnmanagedDocumentWriter
+ // COM object.
+ //------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ISymUnmanagedDocumentWriter
+ {
+ internal IntPtr m_unmanagedVTable;
+ }
+
+ //------------------------------------------------------------------------------
+ // Stores underlying ISymUnmanagedDocumentWriter* pointer (wrapped in a safehandle.)
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ private PunkSafeHandle m_pDocumentWriterSafeHandle;
+
+ [SecurityCritical]
+ private ISymUnmanagedDocumentWriter * m_pDocWriter;
+
+ //------------------------------------------------------------------------------
+ // Stores the "managed vtable" (actually a structure full of delegates that
+ // P/Invoke to the corresponding unmanaged COM methods.)
+ //------------------------------------------------------------------------------
+ [SecurityCritical]
+ private ISymUnmanagedDocumentWriterVTable m_vtable;
+
+
+ } // class SymDocumentWriter
+
+
+ //------------------------------------------------------------------------------
+ // Implements Telesto's version of SymWriter (in the desktop world,
+ // this type is expored from ISymWrapper.dll.)
+ //------------------------------------------------------------------------------
+ internal unsafe class SymWriter : ISymbolWriter
+ {
+
+
+ //------------------------------------------------------------------------------
+ // Creates a SymWriter. The SymWriter is a managed wrapper around the unmanaged
+ // symbol writer provided by the runtime (ildbsymlib or diasymreader.dll).
+ //------------------------------------------------------------------------------
+ internal static ISymbolWriter CreateSymWriter()
+ {
+ return new SymWriter();
+ }
+
+
+ //------------------------------------------------------------------------------
+ // Basic ctor. You'd think this ctor would take the unmanaged symwriter object as an argument
+ // but to fit in with existing desktop code, the unmanaged writer is passed in
+ // through a subsequent call to InternalSetUnderlyingWriter
+ //------------------------------------------------------------------------------
+ private SymWriter()
+ {
+ }
+
+ //=========================================================================================
+ // Public interface methods start here.
+ //=========================================================================================
+
+
+ //------------------------------------------------------------------------------
+ // Initialize() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.Initialize(IntPtr emitter, String filename, bool fFullBuild)
+ {
+ int hr = m_vtable.Initialize(m_pWriter, emitter, filename, (IntPtr)0, fFullBuild);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineDocument() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ ISymbolDocumentWriter ISymbolWriter.DefineDocument(String url,
+ Guid language,
+ Guid languageVendor,
+ Guid documentType)
+ {
+ PunkSafeHandle psymUnmanagedDocumentWriter = new PunkSafeHandle();
+
+ int hr = m_vtable.DefineDocument(m_pWriter, url, ref language, ref languageVendor, ref documentType, out psymUnmanagedDocumentWriter);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ if (psymUnmanagedDocumentWriter.IsInvalid)
+ {
+ return null;
+ }
+ return new SymDocumentWriter(psymUnmanagedDocumentWriter);
+ }
+
+ //------------------------------------------------------------------------------
+ // SetUserEntryPoint() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.SetUserEntryPoint(SymbolToken entryMethod)
+ {
+ int hr = m_vtable.SetUserEntryPoint(m_pWriter, entryMethod.GetToken());
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // OpenMethod() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.OpenMethod(SymbolToken method)
+ {
+ int hr = m_vtable.OpenMethod(m_pWriter, method.GetToken());
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // CloseMethod() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.CloseMethod()
+ {
+ int hr = m_vtable.CloseMethod(m_pWriter);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineSequencePoints() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.DefineSequencePoints(ISymbolDocumentWriter document,
+ int[] offsets,
+ int[] lines,
+ int[] columns,
+ int[] endLines,
+ int[] endColumns)
+ {
+ int spCount = 0;
+ if (offsets != null)
+ {
+ spCount = offsets.Length;
+ }
+ else if (lines != null)
+ {
+ spCount = lines.Length;
+ }
+ else if (columns != null)
+ {
+ spCount = columns.Length;
+ }
+ else if (endLines != null)
+ {
+ spCount = endLines.Length;
+ }
+ else if (endColumns != null)
+ {
+ spCount = endColumns.Length;
+ }
+ if (spCount == 0)
+ {
+ return;
+ }
+ if ( (offsets != null && offsets.Length != spCount) ||
+ (lines != null && lines.Length != spCount) ||
+ (columns != null && columns.Length != spCount) ||
+ (endLines != null && endLines.Length != spCount) ||
+ (endColumns != null && endColumns.Length != spCount) )
+ {
+ throw new ArgumentException();
+ }
+
+ // Sure, claim to accept any type that implements ISymbolDocumentWriter but the only one that actually
+ // works is the one returned by DefineDocument. The desktop ISymWrapper commits the same signature fraud.
+ // Ideally we'd just return a sealed opaque cookie type, which had an internal accessor to
+ // get the writer out.
+ // Regardless, this cast is important for security - we cannot allow our caller to provide
+ // arbitrary instances of this interface.
+ SymDocumentWriter docwriter = (SymDocumentWriter)document;
+ int hr = m_vtable.DefineSequencePoints(m_pWriter, docwriter.GetUnmanaged(), spCount, offsets, lines, columns, endLines, endColumns);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+
+ }
+
+ //------------------------------------------------------------------------------
+ // OpenScope() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ int ISymbolWriter.OpenScope(int startOffset)
+ {
+ int ret;
+ int hr = m_vtable.OpenScope(m_pWriter, startOffset, out ret);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ return ret;
+ }
+
+ //------------------------------------------------------------------------------
+ // CloseScope() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.CloseScope(int endOffset)
+ {
+ int hr = m_vtable.CloseScope(m_pWriter, endOffset);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // SetScopeRange() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.SetScopeRange(int scopeID, int startOffset, int endOffset)
+ {
+ int hr = m_vtable.SetScopeRange(m_pWriter, scopeID, startOffset, endOffset);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineLocalVariable() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.DefineLocalVariable(String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3,
+ int startOffset,
+ int endOffset)
+ {
+ int hr = m_vtable.DefineLocalVariable(m_pWriter,
+ name,
+ (int)attributes,
+ signature.Length,
+ signature,
+ (int)addrKind,
+ addr1,
+ addr2,
+ addr3,
+ startOffset,
+ endOffset);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineParameter() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.DefineParameter(String name,
+ ParameterAttributes attributes,
+ int sequence,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3)
+ {
+ throw new NotSupportedException(); // Intentionally not supported to match desktop CLR
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineField() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.DefineField(SymbolToken parent,
+ String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3)
+ {
+ throw new NotSupportedException(); // Intentionally not supported to match desktop CLR
+ }
+
+ //------------------------------------------------------------------------------
+ // DefineGlobalVariable() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.DefineGlobalVariable(String name,
+ FieldAttributes attributes,
+ byte[] signature,
+ SymAddressKind addrKind,
+ int addr1,
+ int addr2,
+ int addr3)
+ {
+ throw new NotSupportedException(); // Intentionally not supported to match desktop CLR
+ }
+
+ //------------------------------------------------------------------------------
+ // Close() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.Close()
+ {
+ int hr = m_vtable.Close(m_pWriter);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // SetSymAttribute() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.SetSymAttribute(SymbolToken parent, String name, byte[] data)
+ {
+ int hr = m_vtable.SetSymAttribute(m_pWriter, parent.GetToken(), name, data.Length, data);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // OpenNamespace() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.OpenNamespace(String name)
+ {
+ int hr = m_vtable.OpenNamespace(m_pWriter, name);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // CloseNamespace() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.CloseNamespace()
+ {
+ int hr = m_vtable.CloseNamespace(m_pWriter);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // UsingNamespace() wrapper
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ void ISymbolWriter.UsingNamespace(String name)
+ {
+ int hr = m_vtable.UsingNamespace(m_pWriter, name);
+ if (hr < 0)
+ {
+ throw Marshal.GetExceptionForHR(hr);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ // SetMethodSourceRange() wrapper
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.SetMethodSourceRange(ISymbolDocumentWriter startDoc,
+ int startLine,
+ int startColumn,
+ ISymbolDocumentWriter endDoc,
+ int endLine,
+ int endColumn)
+ {
+ throw new NotSupportedException(); // Intentionally not supported to match desktop CLR
+ }
+
+ //------------------------------------------------------------------------------
+ // SetUnderlyingWriter() wrapper.
+ //------------------------------------------------------------------------------
+ void ISymbolWriter.SetUnderlyingWriter(IntPtr ppUnderlyingWriter)
+ {
+ throw new NotSupportedException(); // Intentionally not supported on Telesto as it's a very unsafe api
+ }
+
+ //------------------------------------------------------------------------------
+ // InternalSetUnderlyingWriter() wrapper.
+ //
+ // Furnishes the native ISymUnmanagedWriter* pointer.
+ //
+ // The parameter is actually a pointer to a pointer to an ISymUnmanagedWriter. As
+ // with the real ISymWrapper.dll, ISymWrapper performs *no* Release (or AddRef) on pointers
+ // furnished through SetUnderlyingWriter. Lifetime management is entirely up to the caller.
+ //------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal void InternalSetUnderlyingWriter(IntPtr ppUnderlyingWriter)
+ {
+ m_pWriter = *((ISymUnmanagedWriter**)ppUnderlyingWriter);
+ m_vtable = (ISymUnmanagedWriterVTable) (Marshal.PtrToStructure(m_pWriter->m_unmanagedVTable, typeof(ISymUnmanagedWriterVTable)));
+ }
+
+ //------------------------------------------------------------------------------
+ // Define delegates for the unmanaged COM methods we invoke.
+ //------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ private delegate int DInitialize(ISymUnmanagedWriter* pthis,
+ IntPtr emitter, //IUnknown*
+ [MarshalAs(UnmanagedType.LPWStr)] String filename, //WCHAR*
+ IntPtr pIStream, //IStream*
+ [MarshalAs(UnmanagedType.Bool)] bool fFullBuild
+ );
+
+ [System.Security.SecurityCritical]
+ private delegate int DDefineDocument(ISymUnmanagedWriter* pthis,
+ [MarshalAs(UnmanagedType.LPWStr)] String url,
+ [In] ref Guid language,
+ [In] ref Guid languageVender,
+ [In] ref Guid documentType,
+ [Out] out PunkSafeHandle ppsymUnmanagedDocumentWriter
+ );
+
+ [System.Security.SecurityCritical]
+ private delegate int DSetUserEntryPoint(ISymUnmanagedWriter* pthis, int entryMethod);
+ [System.Security.SecurityCritical]
+ private delegate int DOpenMethod(ISymUnmanagedWriter* pthis, int entryMethod);
+ [System.Security.SecurityCritical]
+ private delegate int DCloseMethod(ISymUnmanagedWriter* pthis);
+
+ [System.Security.SecurityCritical]
+ private delegate int DDefineSequencePoints(ISymUnmanagedWriter* pthis,
+ PunkSafeHandle document,
+ int spCount,
+ [In] int[] offsets,
+ [In] int[] lines,
+ [In] int[] columns,
+ [In] int[] endLines,
+ [In] int[] endColumns);
+
+ [System.Security.SecurityCritical]
+ private delegate int DOpenScope(ISymUnmanagedWriter* pthis, int startOffset, [Out] out int pretval);
+ [System.Security.SecurityCritical]
+ private delegate int DCloseScope(ISymUnmanagedWriter* pthis, int endOffset);
+
+ [System.Security.SecurityCritical]
+ private delegate int DSetScopeRange(ISymUnmanagedWriter* pthis, int scopeID, int startOffset, int endOffset);
+
+ [System.Security.SecurityCritical]
+ private delegate int DDefineLocalVariable(ISymUnmanagedWriter* pthis,
+ [MarshalAs(UnmanagedType.LPWStr)] String name,
+ int attributes,
+ int cSig,
+ [In] byte[] signature,
+ int addrKind,
+ int addr1,
+ int addr2,
+ int addr3,
+ int startOffset,
+ int endOffset
+ );
+
+ [System.Security.SecurityCritical]
+ private delegate int DClose(ISymUnmanagedWriter* pthis);
+
+ [System.Security.SecurityCritical]
+ private delegate int DSetSymAttribute(ISymUnmanagedWriter* pthis,
+ int parent,
+ [MarshalAs(UnmanagedType.LPWStr)] String name,
+ int cData,
+ [In] byte[] data
+ );
+
+
+ [System.Security.SecurityCritical]
+ private delegate int DOpenNamespace(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String name);
+ [System.Security.SecurityCritical]
+ private delegate int DCloseNamespace(ISymUnmanagedWriter* pthis);
+ [System.Security.SecurityCritical]
+ private delegate int DUsingNamespace(ISymUnmanagedWriter* pthis, [MarshalAs(UnmanagedType.LPWStr)] String name);
+
+
+
+ //------------------------------------------------------------------------------
+ // This layout must match the unmanaged ISymUnmanagedWriter* COM vtable
+ // exactly. If a member is declared as an IntPtr rather than a delegate, it means
+ // we don't call that particular member.
+ //------------------------------------------------------------------------------
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ISymUnmanagedWriterVTable
+ {
+ internal IntPtr QueryInterface;
+ internal IntPtr AddRef;
+ internal IntPtr Release;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DDefineDocument DefineDocument;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DSetUserEntryPoint SetUserEntryPoint;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DOpenMethod OpenMethod;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DCloseMethod CloseMethod;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DOpenScope OpenScope;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DCloseScope CloseScope;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DSetScopeRange SetScopeRange;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DDefineLocalVariable DefineLocalVariable;
+ internal IntPtr DefineParameter;
+ internal IntPtr DefineField;
+ internal IntPtr DefineGlobalVariable;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DClose Close;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DSetSymAttribute SetSymAttribute;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DOpenNamespace OpenNamespace;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DCloseNamespace CloseNamespace;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DUsingNamespace UsingNamespace;
+
+ internal IntPtr SetMethodSourceRange;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DInitialize Initialize;
+ internal IntPtr GetDebugInfo;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal DDefineSequencePoints DefineSequencePoints;
+
+ }
+
+ //------------------------------------------------------------------------------
+ // This layout must match the (start) of the unmanaged ISymUnmanagedWriter
+ // COM object.
+ //------------------------------------------------------------------------------
+ [StructLayout(LayoutKind.Sequential)]
+ private struct ISymUnmanagedWriter
+ {
+ internal IntPtr m_unmanagedVTable;
+ }
+
+ //------------------------------------------------------------------------------
+ // Stores native ISymUnmanagedWriter* pointer.
+ //
+ // As with the real ISymWrapper.dll, ISymWrapper performs *no* Release (or AddRef) on this pointer.
+ // Managing lifetime is up to the caller (coreclr.dll).
+ //------------------------------------------------------------------------------
+ [SecurityCritical]
+ private ISymUnmanagedWriter *m_pWriter;
+
+ //------------------------------------------------------------------------------
+ // Stores the "managed vtable" (actually a structure full of delegates that
+ // P/Invoke to the corresponding unmanaged COM methods.)
+ //------------------------------------------------------------------------------
+ private ISymUnmanagedWriterVTable m_vtable;
+
+ } // class SymWriter
+
+
+
+
+ } //class SymWrapperCore
+
+
+
+ //--------------------------------------------------------------------------------------
+ // SafeHandle for RAW MTA IUnknown's.
+ //
+ // ! Because the Release occurs in the finalizer thread, this safehandle really takes
+ // ! an ostrich approach to apartment issues. We only tolerate this here because we're emulating
+ // ! the desktop CLR's use of ISymWrapper which also pays lip service to COM apartment rules.
+ // !
+ // ! However, think twice about pulling this safehandle out for other uses.
+ //
+ // Had to make this a non-nested class since FCall's don't like to bind to nested classes.
+ //--------------------------------------------------------------------------------------
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ sealed class PunkSafeHandle : SafeHandle
+ {
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal PunkSafeHandle()
+ : base((IntPtr)0, true)
+ {
+ }
+
+ [SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ m_Release(handle);
+ return true;
+ }
+
+ public override bool IsInvalid
+ {
+ [SecurityCritical]
+ get { return handle == ((IntPtr)0); }
+ }
+
+ private delegate void DRelease(IntPtr punk); // Delegate type for P/Invoking to coreclr.dll and doing an IUnknown::Release()
+ private static DRelease m_Release;
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr nGetDReleaseTarget(); // FCall gets us the native DRelease target (so we don't need named dllexport from coreclr.dll)
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ static PunkSafeHandle()
+ {
+ m_Release = (DRelease)(Marshal.GetDelegateForFunctionPointer(nGetDReleaseTarget(), typeof(DRelease)));
+ m_Release((IntPtr)0); // make one call to make sure the delegate is fully prepped before we're in the critical finalizer situation.
+ }
+
+ } // PunkSafeHandle
+
+} //namespace System.Reflection.Emit
+
+
+#endif //FEATURE_CORECLR
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/Label.cs b/src/mscorlib/src/System/Reflection/Emit/Label.cs
new file mode 100644
index 0000000000..dd248b62fe
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/Label.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Represents a Label to the ILGenerator class.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+
+ // The Label class is an opaque representation of a label used by the
+ // ILGenerator class. The token is used to mark where labels occur in the IL
+ // stream and then the necessary offsets are put back in the code when the ILGenerator
+ // is passed to the MethodWriter.
+ // Labels are created by using ILGenerator.CreateLabel and their position is set
+ // by using ILGenerator.MarkLabel.
+ [Serializable]
+ [ComVisible(true)]
+ public struct Label {
+
+ internal int m_label;
+
+ //public Label() {
+ // m_label=0;
+ //}
+
+ internal Label (int label) {
+ m_label=label;
+ }
+
+ internal int GetLabelValue() {
+ return m_label;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_label;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is Label)
+ return Equals((Label)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(Label obj)
+ {
+ return obj.m_label == m_label;
+ }
+
+ public static bool operator ==(Label a, Label b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(Label a, Label b)
+ {
+ return !(a == b);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs
new file mode 100644
index 0000000000..4008703ca7
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/LocalBuilder.cs
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Reflection;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+
+namespace System.Reflection.Emit
+{
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_LocalBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class LocalBuilder : LocalVariableInfo, _LocalBuilder
+ {
+ #region Private Data Members
+ private int m_localIndex;
+ private Type m_localType;
+ private MethodInfo m_methodBuilder;
+ private bool m_isPinned;
+ #endregion
+
+ #region Constructor
+ private LocalBuilder() { }
+ internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder)
+ : this(localIndex, localType, methodBuilder, false) { }
+ internal LocalBuilder(int localIndex, Type localType, MethodInfo methodBuilder, bool isPinned)
+ {
+ m_isPinned = isPinned;
+ m_localIndex = localIndex;
+ m_localType = localType;
+ m_methodBuilder = methodBuilder;
+ }
+ #endregion
+
+ #region Internal Members
+ internal int GetLocalIndex()
+ {
+ return m_localIndex;
+ }
+ internal MethodInfo GetMethodBuilder()
+ {
+ return m_methodBuilder;
+ }
+ #endregion
+
+ #region LocalVariableInfo Override
+ public override bool IsPinned { get { return m_isPinned; } }
+ public override Type LocalType
+ {
+ get
+ {
+ return m_localType;
+ }
+ }
+ public override int LocalIndex { get { return m_localIndex; } }
+ #endregion
+
+ #region Public Members
+ public void SetLocalSymInfo(String name)
+ {
+ SetLocalSymInfo(name, 0, 0);
+ }
+
+ public void SetLocalSymInfo(String name, int startOffset, int endOffset)
+ {
+ ModuleBuilder dynMod;
+ SignatureHelper sigHelp;
+ int sigLength;
+ byte[] signature;
+ byte[] mungedSig;
+ int index;
+
+ MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
+ if (methodBuilder == null)
+ // it's a light code gen entity
+ throw new NotSupportedException();
+ dynMod = (ModuleBuilder) methodBuilder.Module;
+ if (methodBuilder.IsTypeCreated())
+ {
+ // cannot change method after its containing type has been created
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated"));
+ }
+
+ // set the name and range of offset for the local
+ if (dynMod.GetSymWriter() == null)
+ {
+ // cannot set local name if not debug module
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+
+ sigHelp = SignatureHelper.GetFieldSigHelper(dynMod);
+ sigHelp.AddArgument(m_localType);
+ signature = sigHelp.InternalGetSignature(out sigLength);
+
+ // The symbol store doesn't want the calling convention on the
+ // front of the signature, but InternalGetSignature returns
+ // the callinging convention. So we strip it off. This is a
+ // bit unfortunate, since it means that we need to allocate
+ // yet another array of bytes...
+ mungedSig = new byte[sigLength - 1];
+ Buffer.BlockCopy(signature, 1, mungedSig, 0, sigLength - 1);
+
+ index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex();
+ if (index == -1)
+ {
+ // top level scope information is kept with methodBuilder
+ methodBuilder.m_localSymInfo.AddLocalSymInfo(
+ name,
+ mungedSig,
+ m_localIndex,
+ startOffset,
+ endOffset);
+ }
+ else
+ {
+ methodBuilder.GetILGenerator().m_ScopeTree.AddLocalSymInfoToCurrentScope(
+ name,
+ mungedSig,
+ m_localIndex,
+ startOffset,
+ endOffset);
+ }
+ }
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _LocalBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _LocalBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _LocalBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _LocalBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs
new file mode 100644
index 0000000000..015a73be09
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/MethodBuilder.cs
@@ -0,0 +1,1610 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Text;
+ using System;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Diagnostics.SymbolStore;
+ using System.Reflection;
+ using System.Security;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_MethodBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class MethodBuilder : MethodInfo, _MethodBuilder
+ {
+ #region Private Data Members
+ // Identity
+ internal String m_strName; // The name of the method
+ private MethodToken m_tkMethod; // The token of this method
+ private ModuleBuilder m_module;
+ internal TypeBuilder m_containingType;
+
+ // IL
+ private int[] m_mdMethodFixups; // The location of all of the token fixups. Null means no fixups.
+ private byte[] m_localSignature; // Local signature if set explicitly via DefineBody. Null otherwise.
+ internal LocalSymInfo m_localSymInfo; // keep track debugging local information
+ internal ILGenerator m_ilGenerator; // Null if not used.
+ private byte[] m_ubBody; // The IL for the method
+ private ExceptionHandler[] m_exceptions; // Exception handlers or null if there are none.
+ private const int DefaultMaxStack = 16;
+ private int m_maxStack = DefaultMaxStack;
+
+ // Flags
+ internal bool m_bIsBaked;
+ private bool m_bIsGlobalMethod;
+ private bool m_fInitLocals; // indicating if the method stack frame will be zero initialized or not.
+
+ // Attributes
+ private MethodAttributes m_iAttributes;
+ private CallingConventions m_callingConvention;
+ private MethodImplAttributes m_dwMethodImplFlags;
+
+ // Parameters
+ private SignatureHelper m_signature;
+ internal Type[] m_parameterTypes;
+ private ParameterBuilder m_retParam;
+ private Type m_returnType;
+ private Type[] m_returnTypeRequiredCustomModifiers;
+ private Type[] m_returnTypeOptionalCustomModifiers;
+ private Type[][] m_parameterTypeRequiredCustomModifiers;
+ private Type[][] m_parameterTypeOptionalCustomModifiers;
+
+ // Generics
+ private GenericTypeParameterBuilder[] m_inst;
+ private bool m_bIsGenMethDef;
+ #endregion
+
+ #region Constructor
+ internal MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes, ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)
+ {
+ Init(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null, mod, type, bIsGlobalMethod);
+ }
+
+ internal MethodBuilder(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)
+ {
+ Init(name, attributes, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
+ mod, type, bIsGlobalMethod);
+ }
+
+ private void Init(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ ModuleBuilder mod, TypeBuilder type, bool bIsGlobalMethod)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+
+ if (name[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name");
+
+ if (mod == null)
+ throw new ArgumentNullException("mod");
+ Contract.EndContractBlock();
+
+ if (parameterTypes != null)
+ {
+ foreach(Type t in parameterTypes)
+ {
+ if (t == null)
+ throw new ArgumentNullException("parameterTypes");
+ }
+ }
+
+ m_strName = name;
+ m_module = mod;
+ m_containingType = type;
+
+ //
+ //if (returnType == null)
+ //{
+ // m_returnType = typeof(void);
+ //}
+ //else
+ {
+ m_returnType = returnType;
+ }
+
+ if ((attributes & MethodAttributes.Static) == 0)
+ {
+ // turn on the has this calling convention
+ callingConvention = callingConvention | CallingConventions.HasThis;
+ }
+ else if ((attributes & MethodAttributes.Virtual) != 0)
+ {
+ // A method can't be both static and virtual
+ throw new ArgumentException(Environment.GetResourceString("Arg_NoStaticVirtual"));
+ }
+
+ if ((attributes & MethodAttributes.SpecialName) != MethodAttributes.SpecialName)
+ {
+ if ((type.Attributes & TypeAttributes.Interface) == TypeAttributes.Interface)
+ {
+ // methods on interface have to be abstract + virtual except special name methods such as type initializer
+ if ((attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual)) !=
+ (MethodAttributes.Abstract | MethodAttributes.Virtual) &&
+ (attributes & MethodAttributes.Static) == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadAttributeOnInterfaceMethod"));
+ }
+ }
+
+ m_callingConvention = callingConvention;
+
+ if (parameterTypes != null)
+ {
+ m_parameterTypes = new Type[parameterTypes.Length];
+ Array.Copy(parameterTypes, 0, m_parameterTypes, 0, parameterTypes.Length);
+ }
+ else
+ {
+ m_parameterTypes = null;
+ }
+
+ m_returnTypeRequiredCustomModifiers = returnTypeRequiredCustomModifiers;
+ m_returnTypeOptionalCustomModifiers = returnTypeOptionalCustomModifiers;
+ m_parameterTypeRequiredCustomModifiers = parameterTypeRequiredCustomModifiers;
+ m_parameterTypeOptionalCustomModifiers = parameterTypeOptionalCustomModifiers;
+
+// m_signature = SignatureHelper.GetMethodSigHelper(mod, callingConvention,
+// returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+// parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+
+ m_iAttributes = attributes;
+ m_bIsGlobalMethod = bIsGlobalMethod;
+ m_bIsBaked = false;
+ m_fInitLocals = true;
+
+ m_localSymInfo = new LocalSymInfo();
+ m_ubBody = null;
+ m_ilGenerator = null;
+
+ // Default is managed IL. Manged IL has bit flag 0x0020 set off
+ m_dwMethodImplFlags = MethodImplAttributes.IL;
+ }
+
+ #endregion
+
+ #region Internal Members
+
+ internal void CheckContext(params Type[][] typess)
+ {
+ m_module.CheckContext(typess);
+ }
+
+ internal void CheckContext(params Type[] types)
+ {
+ m_module.CheckContext(types);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void CreateMethodBodyHelper(ILGenerator il)
+ {
+ // Sets the IL of the method. An ILGenerator is passed as an argument and the method
+ // queries this instance to get all of the information which it needs.
+ if (il == null)
+ {
+ throw new ArgumentNullException("il");
+ }
+ Contract.EndContractBlock();
+
+ __ExceptionInfo[] excp;
+ int counter=0;
+ int[] filterAddrs;
+ int[] catchAddrs;
+ int[] catchEndAddrs;
+ Type[] catchClass;
+ int[] type;
+ int numCatch;
+ int start, end;
+ ModuleBuilder dynMod = (ModuleBuilder) m_module;
+
+ m_containingType.ThrowIfCreated();
+
+ if (m_bIsBaked)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodHasBody"));
+ }
+
+ if (il.m_methodBuilder != this && il.m_methodBuilder != null)
+ {
+ // you don't need to call DefineBody when you get your ILGenerator
+ // through MethodBuilder::GetILGenerator.
+ //
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadILGeneratorUsage"));
+ }
+
+ ThrowIfShouldNotHaveBody();
+
+ if (il.m_ScopeTree.m_iOpenScopeCount != 0)
+ {
+ // There are still unclosed local scope
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_OpenLocalVariableScope"));
+ }
+
+
+ m_ubBody = il.BakeByteArray();
+
+ m_mdMethodFixups = il.GetTokenFixups();
+
+ //Okay, now the fun part. Calculate all of the exceptions.
+ excp = il.GetExceptions();
+ int numExceptions = CalculateNumberOfExceptions(excp);
+ if (numExceptions > 0)
+ {
+ m_exceptions = new ExceptionHandler[numExceptions];
+
+ for (int i = 0; i < excp.Length; i++)
+ {
+ filterAddrs = excp[i].GetFilterAddresses();
+ catchAddrs = excp[i].GetCatchAddresses();
+ catchEndAddrs = excp[i].GetCatchEndAddresses();
+ catchClass = excp[i].GetCatchClass();
+
+ numCatch = excp[i].GetNumberOfCatches();
+ start = excp[i].GetStartAddress();
+ end = excp[i].GetEndAddress();
+ type = excp[i].GetExceptionTypes();
+ for (int j = 0; j < numCatch; j++)
+ {
+ int tkExceptionClass = 0;
+ if (catchClass[j] != null)
+ {
+ tkExceptionClass = dynMod.GetTypeTokenInternal(catchClass[j]).Token;
+ }
+
+ switch (type[j])
+ {
+ case __ExceptionInfo.None:
+ case __ExceptionInfo.Fault:
+ case __ExceptionInfo.Filter:
+ m_exceptions[counter++] = new ExceptionHandler(start, end, filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass);
+ break;
+
+ case __ExceptionInfo.Finally:
+ m_exceptions[counter++] = new ExceptionHandler(start, excp[i].GetFinallyEndAddress(), filterAddrs[j], catchAddrs[j], catchEndAddrs[j], type[j], tkExceptionClass);
+ break;
+ }
+ }
+
+ }
+ }
+
+
+ m_bIsBaked=true;
+
+ if (dynMod.GetSymWriter() != null)
+ {
+
+ // set the debugging information such as scope and line number
+ // if it is in a debug module
+ //
+ SymbolToken tk = new SymbolToken(MetadataTokenInternal);
+ ISymbolWriter symWriter = dynMod.GetSymWriter();
+
+ // call OpenMethod to make this method the current method
+ symWriter.OpenMethod(tk);
+
+ // call OpenScope because OpenMethod no longer implicitly creating
+ // the top-levelsmethod scope
+ //
+ symWriter.OpenScope(0);
+
+ if (m_symCustomAttrs != null)
+ {
+ foreach(SymCustomAttr symCustomAttr in m_symCustomAttrs)
+ dynMod.GetSymWriter().SetSymAttribute(
+ new SymbolToken (MetadataTokenInternal),
+ symCustomAttr.m_name,
+ symCustomAttr.m_data);
+ }
+
+ if (m_localSymInfo != null)
+ m_localSymInfo.EmitLocalSymInfo(symWriter);
+ il.m_ScopeTree.EmitScopeTree(symWriter);
+ il.m_LineNumberInfo.EmitLineNumberInfo(symWriter);
+ symWriter.CloseScope(il.ILOffset);
+ symWriter.CloseMethod();
+ }
+ }
+
+ // This is only called from TypeBuilder.CreateType after the method has been created
+ internal void ReleaseBakedStructures()
+ {
+ if (!m_bIsBaked)
+ {
+ // We don't need to do anything here if we didn't baked the method body
+ return;
+ }
+
+ m_ubBody = null;
+ m_localSymInfo = null;
+ m_mdMethodFixups = null;
+ m_localSignature = null;
+ m_exceptions = null;
+ }
+
+ internal override Type[] GetParameterTypes()
+ {
+ if (m_parameterTypes == null)
+ m_parameterTypes = EmptyArray<Type>.Value;
+
+ return m_parameterTypes;
+ }
+
+ internal static Type GetMethodBaseReturnType(MethodBase method)
+ {
+ MethodInfo mi = null;
+ ConstructorInfo ci = null;
+
+ if ( (mi = method as MethodInfo) != null )
+ {
+ return mi.ReturnType;
+ }
+ else if ( (ci = method as ConstructorInfo) != null)
+ {
+ return ci.GetReturnType();
+ }
+ else
+ {
+ Contract.Assert(false, "We should never get here!");
+ return null;
+ }
+ }
+
+ internal void SetToken(MethodToken token)
+ {
+ m_tkMethod = token;
+ }
+
+ internal byte[] GetBody()
+ {
+ // Returns the il bytes of this method.
+ // This il is not valid until somebody has called BakeByteArray
+ return m_ubBody;
+ }
+
+ internal int[] GetTokenFixups()
+ {
+ return m_mdMethodFixups;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal SignatureHelper GetMethodSignature()
+ {
+ if (m_parameterTypes == null)
+ m_parameterTypes = EmptyArray<Type>.Value;
+
+ m_signature = SignatureHelper.GetMethodSigHelper (m_module, m_callingConvention, m_inst != null ? m_inst.Length : 0,
+ m_returnType == null ? typeof(void) : m_returnType, m_returnTypeRequiredCustomModifiers, m_returnTypeOptionalCustomModifiers,
+ m_parameterTypes, m_parameterTypeRequiredCustomModifiers, m_parameterTypeOptionalCustomModifiers);
+
+ return m_signature;
+ }
+
+ // Returns a buffer whose initial signatureLength bytes contain encoded local signature.
+ internal byte[] GetLocalSignature(out int signatureLength)
+ {
+ if (m_localSignature != null)
+ {
+ signatureLength = m_localSignature.Length;
+ return m_localSignature;
+ }
+
+ if (m_ilGenerator != null)
+ {
+ if (m_ilGenerator.m_localCount != 0)
+ {
+ // If user is using ILGenerator::DeclareLocal, then get local signaturefrom there.
+ return m_ilGenerator.m_localSignature.InternalGetSignature(out signatureLength);
+ }
+ }
+
+ return SignatureHelper.GetLocalVarSigHelper(m_module).InternalGetSignature(out signatureLength);
+ }
+
+ internal int GetMaxStack()
+ {
+ if (m_ilGenerator != null)
+ {
+ return m_ilGenerator.GetMaxStackSize() + ExceptionHandlerCount;
+ }
+ else
+ {
+ // this is the case when client provide an array of IL byte stream rather than going through ILGenerator.
+ return m_maxStack;
+ }
+ }
+
+ internal ExceptionHandler[] GetExceptionHandlers()
+ {
+ return m_exceptions;
+ }
+
+ internal int ExceptionHandlerCount
+ {
+ get { return m_exceptions != null ? m_exceptions.Length : 0; }
+ }
+
+ internal int CalculateNumberOfExceptions(__ExceptionInfo[] excp)
+ {
+ int num=0;
+
+ if (excp==null)
+ {
+ return 0;
+ }
+
+ for (int i=0; i<excp.Length; i++)
+ {
+ num+=excp[i].GetNumberOfCatches();
+ }
+
+ return num;
+ }
+
+ internal bool IsTypeCreated()
+ {
+ return (m_containingType != null && m_containingType.IsCreated());
+ }
+
+ internal TypeBuilder GetTypeBuilder()
+ {
+ return m_containingType;
+ }
+
+ internal ModuleBuilder GetModuleBuilder()
+ {
+ return m_module;
+ }
+ #endregion
+
+ #region Object Overrides
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool Equals(Object obj) {
+ if (!(obj is MethodBuilder)) {
+ return false;
+ }
+ if (!(this.m_strName.Equals(((MethodBuilder)obj).m_strName))) {
+ return false;
+ }
+
+ if (m_iAttributes!=(((MethodBuilder)obj).m_iAttributes)) {
+ return false;
+ }
+
+ SignatureHelper thatSig = ((MethodBuilder)obj).GetMethodSignature();
+ if (thatSig.Equals(GetMethodSignature())) {
+ return true;
+ }
+ return false;
+ }
+
+ public override int GetHashCode()
+ {
+ return this.m_strName.GetHashCode();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder(1000);
+ sb.Append("Name: " + m_strName + " " + Environment.NewLine);
+ sb.Append("Attributes: " + (int)m_iAttributes + Environment.NewLine);
+ sb.Append("Method Signature: " + GetMethodSignature() + Environment.NewLine);
+ sb.Append(Environment.NewLine);
+ return sb.ToString();
+ }
+
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ get
+ {
+ return m_strName;
+ }
+ }
+
+ internal int MetadataTokenInternal
+ {
+ get
+ {
+ return GetToken().Token;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return m_containingType.Module;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ if (m_containingType.m_isHiddenGlobalType == true)
+ return null;
+ return m_containingType;
+ }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return DeclaringType;
+ }
+ }
+
+ #endregion
+
+ #region MethodBase Overrides
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return m_dwMethodImplFlags;
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { return m_iAttributes; }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get {return m_callingConvention;}
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+ #endregion
+
+ #region MethodInfo Overrides
+ public override MethodInfo GetBaseDefinition()
+ {
+ return this;
+ }
+
+ public override Type ReturnType
+ {
+ get
+ {
+ return m_returnType;
+ }
+ }
+
+ [Pure]
+ public override ParameterInfo[] GetParameters()
+ {
+ if (!m_bIsBaked || m_containingType == null || m_containingType.BakedRuntimeType == null)
+ throw new NotSupportedException(Environment.GetResourceString("InvalidOperation_TypeNotCreated"));
+
+ MethodInfo rmi = m_containingType.GetMethod(m_strName, m_parameterTypes);
+
+ return rmi.GetParameters();
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ get
+ {
+ if (!m_bIsBaked || m_containingType == null || m_containingType.BakedRuntimeType == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeNotCreated"));
+
+ MethodInfo rmi = m_containingType.GetMethod(m_strName, m_parameterTypes);
+
+ return rmi.ReturnParameter;
+ }
+ }
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ #endregion
+
+ #region Generic Members
+ public override bool IsGenericMethodDefinition { get { return m_bIsGenMethDef; } }
+
+ public override bool ContainsGenericParameters { get { throw new NotSupportedException(); } }
+
+ public override MethodInfo GetGenericMethodDefinition() { if (!IsGenericMethod) throw new InvalidOperationException(); return this; }
+
+ public override bool IsGenericMethod { get { return m_inst != null; } }
+
+ public override Type[] GetGenericArguments() { return m_inst; }
+
+ public override MethodInfo MakeGenericMethod(params Type[] typeArguments)
+ {
+ return MethodBuilderInstantiation.MakeGenericMethod(this, typeArguments);
+ }
+
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters (params string[] names)
+ {
+ if (names == null)
+ throw new ArgumentNullException("names");
+
+ if (names.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EmptyArray"), "names");
+ Contract.EndContractBlock();
+
+ if (m_inst != null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GenericParametersAlreadySet"));
+
+ for (int i = 0; i < names.Length; i ++)
+ if (names[i] == null)
+ throw new ArgumentNullException("names");
+
+ if (m_tkMethod.Token != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBuilderBaked"));
+
+ m_bIsGenMethDef = true;
+ m_inst = new GenericTypeParameterBuilder[names.Length];
+ for (int i = 0; i < names.Length; i ++)
+ m_inst[i] = new GenericTypeParameterBuilder(new TypeBuilder(names[i], i, this));
+
+ return m_inst;
+ }
+
+ internal void ThrowIfGeneric () { if (IsGenericMethod && !IsGenericMethodDefinition) throw new InvalidOperationException (); }
+ #endregion
+
+ #region Public Members
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodToken GetToken()
+ {
+ // We used to always "tokenize" a MethodBuilder when it is constructed. After change list 709498
+ // we only "tokenize" a method when requested. But the order in which the methods are tokenized
+ // didn't change: the same order the MethodBuilders are constructed. The recursion introduced
+ // will overflow the stack when there are many methods on the same type (10000 in my experiment).
+ // The change also introduced race conditions. Before the code change GetToken is called from
+ // the MethodBuilder .ctor which is protected by lock(ModuleBuilder.SyncRoot). Now it
+ // could be called more than once on the the same method introducing duplicate (invalid) tokens.
+ // I don't fully understand this change. So I will keep the logic and only fix the recursion and
+ // the race condition.
+
+ if (m_tkMethod.Token != 0)
+ {
+ return m_tkMethod;
+ }
+
+ MethodBuilder currentMethod = null;
+ MethodToken currentToken = new MethodToken(0);
+ int i;
+
+ // We need to lock here to prevent a method from being "tokenized" twice.
+ // We don't need to synchronize this with Type.DefineMethod because it only appends newly
+ // constructed MethodBuilders to the end of m_listMethods
+ lock (m_containingType.m_listMethods)
+ {
+ if (m_tkMethod.Token != 0)
+ {
+ return m_tkMethod;
+ }
+
+ // If m_tkMethod is still 0 when we obtain the lock, m_lastTokenizedMethod must be smaller
+ // than the index of the current method.
+ for (i = m_containingType.m_lastTokenizedMethod + 1; i < m_containingType.m_listMethods.Count; ++i)
+ {
+ currentMethod = m_containingType.m_listMethods[i];
+ currentToken = currentMethod.GetTokenNoLock();
+
+ if (currentMethod == this)
+ break;
+ }
+
+ m_containingType.m_lastTokenizedMethod = i;
+ }
+
+ Contract.Assert(currentMethod == this, "We should have found this method in m_containingType.m_listMethods");
+ Contract.Assert(currentToken.Token != 0, "The token should not be 0");
+
+ return currentToken;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodToken GetTokenNoLock()
+ {
+ Contract.Assert(m_tkMethod.Token == 0, "m_tkMethod should not have been initialized");
+
+ int sigLength;
+ byte[] sigBytes = GetMethodSignature().InternalGetSignature(out sigLength);
+
+ int token = TypeBuilder.DefineMethod(m_module.GetNativeHandle(), m_containingType.MetadataTokenInternal, m_strName, sigBytes, sigLength, Attributes);
+ m_tkMethod = new MethodToken(token);
+
+ if (m_inst != null)
+ foreach (GenericTypeParameterBuilder tb in m_inst)
+ if (!tb.m_type.IsCreated()) tb.m_type.CreateType();
+
+ TypeBuilder.SetMethodImpl(m_module.GetNativeHandle(), token, m_dwMethodImplFlags);
+
+ return m_tkMethod;
+ }
+
+ public void SetParameters (params Type[] parameterTypes)
+ {
+ CheckContext(parameterTypes);
+
+ SetSignature (null, null, null, parameterTypes, null, null);
+ }
+
+ public void SetReturnType (Type returnType)
+ {
+ CheckContext(returnType);
+
+ SetSignature (returnType, null, null, null, null, null);
+ }
+
+ public void SetSignature(
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ // We should throw InvalidOperation_MethodBuilderBaked here if the method signature has been baked.
+ // But we cannot because that would be a breaking change from V2.
+ if (m_tkMethod.Token != 0)
+ return;
+
+ CheckContext(returnType);
+ CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes);
+ CheckContext(parameterTypeRequiredCustomModifiers);
+ CheckContext(parameterTypeOptionalCustomModifiers);
+
+ ThrowIfGeneric();
+
+ if (returnType != null)
+ {
+ m_returnType = returnType;
+ }
+
+ if (parameterTypes != null)
+ {
+ m_parameterTypes = new Type[parameterTypes.Length];
+ Array.Copy (parameterTypes, 0, m_parameterTypes, 0, parameterTypes.Length);
+ }
+
+ m_returnTypeRequiredCustomModifiers = returnTypeRequiredCustomModifiers;
+ m_returnTypeOptionalCustomModifiers = returnTypeOptionalCustomModifiers;
+ m_parameterTypeRequiredCustomModifiers = parameterTypeRequiredCustomModifiers;
+ m_parameterTypeOptionalCustomModifiers = parameterTypeOptionalCustomModifiers;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ParameterBuilder DefineParameter(int position, ParameterAttributes attributes, String strParamName)
+ {
+ if (position < 0)
+ throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence"));
+ Contract.EndContractBlock();
+
+ ThrowIfGeneric();
+ m_containingType.ThrowIfCreated ();
+
+ if (position > 0 && (m_parameterTypes == null || position > m_parameterTypes.Length))
+ throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_ParamSequence"));
+
+ attributes = attributes & ~ParameterAttributes.ReservedMask;
+ return new ParameterBuilder(this, position, attributes, strParamName);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public void SetMarshal(UnmanagedMarshal unmanagedMarshal)
+ {
+ ThrowIfGeneric ();
+
+ // set Marshal info for the return type
+
+ m_containingType.ThrowIfCreated();
+
+ if (m_retParam == null)
+ {
+ m_retParam = new ParameterBuilder(this, 0, 0, null);
+ }
+
+ m_retParam.SetMarshal(unmanagedMarshal);
+ }
+
+ private List<SymCustomAttr> m_symCustomAttrs;
+ private struct SymCustomAttr
+ {
+ public SymCustomAttr(String name, byte[] data)
+ {
+ m_name = name;
+ m_data = data;
+ }
+ public String m_name;
+ public byte[] m_data;
+ }
+
+ public void SetSymCustomAttribute(String name, byte[] data)
+ {
+ // Note that this API is rarely used. Support for custom attributes in PDB files was added in
+ // Whidbey and as of 8/2007 the only known user is the C# compiler. There seems to be little
+ // value to this for Reflection.Emit users since they can always use metadata custom attributes.
+ // Some versions of the symbol writer used in the CLR will ignore these entirely. This API has
+ // been removed from the Silverlight API surface area, but we should also consider removing it
+ // from future desktop product versions as well.
+
+ ThrowIfGeneric ();
+
+ // This is different from CustomAttribute. This is stored into the SymWriter.
+ m_containingType.ThrowIfCreated();
+
+ ModuleBuilder dynMod = (ModuleBuilder) m_module;
+ if ( dynMod.GetSymWriter() == null)
+ {
+ // Cannot SetSymCustomAttribute when it is not a debug module
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+
+ if (m_symCustomAttrs == null)
+ m_symCustomAttrs = new List<SymCustomAttr>();
+
+ m_symCustomAttrs.Add(new SymCustomAttr(name, data));
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset)
+ {
+ if (pset == null)
+ throw new ArgumentNullException("pset");
+ Contract.EndContractBlock();
+
+ ThrowIfGeneric ();
+
+#pragma warning disable 618
+ if (!Enum.IsDefined(typeof(SecurityAction), action) ||
+ action == SecurityAction.RequestMinimum ||
+ action == SecurityAction.RequestOptional ||
+ action == SecurityAction.RequestRefuse)
+ {
+ throw new ArgumentOutOfRangeException("action");
+ }
+#pragma warning restore 618
+
+ // cannot declarative security after type is created
+ m_containingType.ThrowIfCreated();
+
+ // Translate permission set into serialized format (uses standard binary serialization format).
+ byte[] blob = null;
+ int length = 0;
+ if (!pset.IsEmpty())
+ {
+ blob = pset.EncodeXml();
+ length = blob.Length;
+ }
+
+ // Write the blob into the metadata.
+ TypeBuilder.AddDeclarativeSecurity(m_module.GetNativeHandle(), MetadataTokenInternal, action, blob, length);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void SetMethodBody(byte[] il, int maxStack, byte[] localSignature, IEnumerable<ExceptionHandler> exceptionHandlers, IEnumerable<int> tokenFixups)
+ {
+ if (il == null)
+ {
+ throw new ArgumentNullException("il", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (maxStack < 0)
+ {
+ throw new ArgumentOutOfRangeException("maxStack", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ if (m_bIsBaked)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked"));
+ }
+
+ m_containingType.ThrowIfCreated();
+ ThrowIfGeneric();
+
+ byte[] newLocalSignature = null;
+ ExceptionHandler[] newHandlers = null;
+ int[] newTokenFixups = null;
+
+ byte[] newIL = (byte[])il.Clone();
+
+ if (localSignature != null)
+ {
+ newLocalSignature = (byte[])localSignature.Clone();
+ }
+
+ if (exceptionHandlers != null)
+ {
+ newHandlers = ToArray(exceptionHandlers);
+ CheckExceptionHandlerRanges(newHandlers, newIL.Length);
+
+ // Note: Fixup entries for type tokens stored in ExceptionHandlers are added by the method body emitter.
+ }
+
+ if (tokenFixups != null)
+ {
+ newTokenFixups = ToArray(tokenFixups);
+ int maxTokenOffset = newIL.Length - 4;
+
+ for (int i = 0; i < newTokenFixups.Length; i++)
+ {
+ // Check that fixups are within the range of this method's IL, otherwise some random memory might get "fixed up".
+ if (newTokenFixups[i] < 0 || newTokenFixups[i] > maxTokenOffset)
+ {
+ throw new ArgumentOutOfRangeException("tokenFixups[" + i + "]", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, maxTokenOffset));
+ }
+ }
+ }
+
+ m_ubBody = newIL;
+ m_localSignature = newLocalSignature;
+ m_exceptions = newHandlers;
+ m_mdMethodFixups = newTokenFixups;
+ m_maxStack = maxStack;
+
+ // discard IL generator, all information stored in it is now irrelevant
+ m_ilGenerator = null;
+ m_bIsBaked = true;
+ }
+
+ private static T[] ToArray<T>(IEnumerable<T> sequence)
+ {
+ T[] array = sequence as T[];
+ if (array != null)
+ {
+ return (T[])array.Clone();
+ }
+
+ return new List<T>(sequence).ToArray();
+ }
+
+ private static void CheckExceptionHandlerRanges(ExceptionHandler[] exceptionHandlers, int maxOffset)
+ {
+ // Basic checks that the handler ranges are within the method body (ranges are end-exclusive).
+ // Doesn't verify that the ranges are otherwise correct - it is very well possible to emit invalid IL.
+ for (int i = 0; i < exceptionHandlers.Length; i++)
+ {
+ var handler = exceptionHandlers[i];
+ if (handler.m_filterOffset > maxOffset || handler.m_tryEndOffset > maxOffset || handler.m_handlerEndOffset > maxOffset)
+ {
+ throw new ArgumentOutOfRangeException("exceptionHandlers[" + i + "]", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, maxOffset));
+ }
+
+ // Type token might be 0 if the ExceptionHandler was created via a default constructor.
+ // Other tokens migth also be invalid. We only check nil tokens as the implementation (SectEH_Emit in corhlpr.cpp) requires it,
+ // and we can't check for valid tokens until the module is baked.
+ if (handler.Kind == ExceptionHandlingClauseOptions.Clause && handler.ExceptionTypeToken == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", handler.ExceptionTypeToken), "exceptionHandlers[" + i + "]");
+ }
+ }
+ }
+
+ /// <summary>
+ /// Obsolete.
+ /// </summary>
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public void CreateMethodBody(byte[] il, int count)
+ {
+ ThrowIfGeneric();
+
+ // Note that when user calls this function, there are a few information that client is
+ // not able to supply: local signature, exception handlers, max stack size, a list of Token fixup, a list of RVA fixup
+
+ if (m_bIsBaked)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked"));
+ }
+
+ m_containingType.ThrowIfCreated();
+
+ if (il != null && (count < 0 || count > il.Length))
+ {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (il == null)
+ {
+ m_ubBody = null;
+ return;
+ }
+
+ m_ubBody = new byte[count];
+ Buffer.BlockCopy(il, 0, m_ubBody, 0, count);
+
+ m_localSignature = null;
+ m_exceptions = null;
+ m_mdMethodFixups = null;
+ m_maxStack = DefaultMaxStack;
+
+ m_bIsBaked = true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetImplementationFlags(MethodImplAttributes attributes)
+ {
+ ThrowIfGeneric ();
+
+ m_containingType.ThrowIfCreated ();
+
+ m_dwMethodImplFlags = attributes;
+
+ m_canBeRuntimeImpl = true;
+
+ TypeBuilder.SetMethodImpl(m_module.GetNativeHandle(), MetadataTokenInternal, attributes);
+ }
+
+ public ILGenerator GetILGenerator() {
+ Contract.Ensures(Contract.Result<ILGenerator>() != null);
+
+ ThrowIfGeneric();
+ ThrowIfShouldNotHaveBody();
+
+ if (m_ilGenerator == null)
+ m_ilGenerator = new ILGenerator(this);
+ return m_ilGenerator;
+ }
+
+ public ILGenerator GetILGenerator(int size) {
+ Contract.Ensures(Contract.Result<ILGenerator>() != null);
+
+ ThrowIfGeneric ();
+ ThrowIfShouldNotHaveBody();
+
+ if (m_ilGenerator == null)
+ m_ilGenerator = new ILGenerator(this, size);
+ return m_ilGenerator;
+ }
+
+ private void ThrowIfShouldNotHaveBody() {
+ if ((m_dwMethodImplFlags & MethodImplAttributes.CodeTypeMask) != MethodImplAttributes.IL ||
+ (m_dwMethodImplFlags & MethodImplAttributes.Unmanaged) != 0 ||
+ (m_iAttributes & MethodAttributes.PinvokeImpl) != 0 ||
+ m_isDllImport)
+ {
+ // cannot attach method body if methodimpl is marked not marked as managed IL
+ //
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ShouldNotHaveMethodBody"));
+ }
+ }
+
+
+ public bool InitLocals
+ {
+ // Property is set to true if user wishes to have zero initialized stack frame for this method. Default to false.
+ get { ThrowIfGeneric (); return m_fInitLocals; }
+ set { ThrowIfGeneric (); m_fInitLocals = value; }
+ }
+
+ public Module GetModule()
+ {
+ return GetModuleBuilder();
+ }
+
+ public String Signature
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return GetMethodSignature().ToString();
+ }
+ }
+
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#else
+[System.Security.SecuritySafeCritical]
+#endif
+[System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ ThrowIfGeneric();
+
+ TypeBuilder.DefineCustomAttribute(m_module, MetadataTokenInternal,
+ ((ModuleBuilder)m_module).GetConstructorToken(con).Token,
+ binaryAttribute,
+ false, false);
+
+ if (IsKnownCA(con))
+ ParseCA(con, binaryAttribute);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ throw new ArgumentNullException("customBuilder");
+ Contract.EndContractBlock();
+
+ ThrowIfGeneric();
+
+ customBuilder.CreateCustomAttribute((ModuleBuilder)m_module, MetadataTokenInternal);
+
+ if (IsKnownCA(customBuilder.m_con))
+ ParseCA(customBuilder.m_con, customBuilder.m_blob);
+ }
+
+ // this method should return true for any and every ca that requires more work
+ // than just setting the ca
+ private bool IsKnownCA(ConstructorInfo con)
+ {
+ Type caType = con.DeclaringType;
+ if (caType == typeof(System.Runtime.CompilerServices.MethodImplAttribute)) return true;
+ else if (caType == typeof(DllImportAttribute)) return true;
+ else return false;
+ }
+
+ private void ParseCA(ConstructorInfo con, byte[] blob)
+ {
+ Type caType = con.DeclaringType;
+ if (caType == typeof(System.Runtime.CompilerServices.MethodImplAttribute))
+ {
+ // dig through the blob looking for the MethodImplAttributes flag
+ // that must be in the MethodCodeType field
+
+ // for now we simply set a flag that relaxes the check when saving and
+ // allows this method to have no body when any kind of MethodImplAttribute is present
+ m_canBeRuntimeImpl = true;
+ }
+ else if (caType == typeof(DllImportAttribute)) {
+ m_canBeRuntimeImpl = true;
+ m_isDllImport = true;
+ }
+
+ }
+
+ internal bool m_canBeRuntimeImpl = false;
+ internal bool m_isDllImport = false;
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _MethodBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ }
+
+ internal class LocalSymInfo
+ {
+ // This class tracks the local variable's debugging information
+ // and namespace information with a given active lexical scope.
+
+ #region Internal Data Members
+ internal String[] m_strName;
+ internal byte[][] m_ubSignature;
+ internal int[] m_iLocalSlot;
+ internal int[] m_iStartOffset;
+ internal int[] m_iEndOffset;
+ internal int m_iLocalSymCount; // how many entries in the arrays are occupied
+ internal String[] m_namespace;
+ internal int m_iNameSpaceCount;
+ internal const int InitialSize = 16;
+ #endregion
+
+ #region Constructor
+ internal LocalSymInfo()
+ {
+ // initialize data variables
+ m_iLocalSymCount = 0;
+ m_iNameSpaceCount = 0;
+ }
+ #endregion
+
+ #region Private Members
+ private void EnsureCapacityNamespace()
+ {
+ if (m_iNameSpaceCount == 0)
+ {
+ m_namespace = new String[InitialSize];
+ }
+ else if (m_iNameSpaceCount == m_namespace.Length)
+ {
+ String [] strTemp = new String [checked(m_iNameSpaceCount * 2)];
+ Array.Copy(m_namespace, 0, strTemp, 0, m_iNameSpaceCount);
+ m_namespace = strTemp;
+ }
+ }
+
+ private void EnsureCapacity()
+ {
+ if (m_iLocalSymCount == 0)
+ {
+ // First time. Allocate the arrays.
+ m_strName = new String[InitialSize];
+ m_ubSignature = new byte[InitialSize][];
+ m_iLocalSlot = new int[InitialSize];
+ m_iStartOffset = new int[InitialSize];
+ m_iEndOffset = new int[InitialSize];
+ }
+ else if (m_iLocalSymCount == m_strName.Length)
+ {
+ // the arrays are full. Enlarge the arrays
+ // why aren't we just using lists here?
+ int newSize = checked(m_iLocalSymCount * 2);
+ int[] temp = new int [newSize];
+ Array.Copy(m_iLocalSlot, 0, temp, 0, m_iLocalSymCount);
+ m_iLocalSlot = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iStartOffset, 0, temp, 0, m_iLocalSymCount);
+ m_iStartOffset = temp;
+
+ temp = new int [newSize];
+ Array.Copy(m_iEndOffset, 0, temp, 0, m_iLocalSymCount);
+ m_iEndOffset = temp;
+
+ String [] strTemp = new String [newSize];
+ Array.Copy(m_strName, 0, strTemp, 0, m_iLocalSymCount);
+ m_strName = strTemp;
+
+ byte[][] ubTemp = new byte[newSize][];
+ Array.Copy(m_ubSignature, 0, ubTemp, 0, m_iLocalSymCount);
+ m_ubSignature = ubTemp;
+
+ }
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal void AddLocalSymInfo(String strName,byte[] signature,int slot,int startOffset,int endOffset)
+ {
+ // make sure that arrays are large enough to hold addition info
+ EnsureCapacity();
+ m_iStartOffset[m_iLocalSymCount] = startOffset;
+ m_iEndOffset[m_iLocalSymCount] = endOffset;
+ m_iLocalSlot[m_iLocalSymCount] = slot;
+ m_strName[m_iLocalSymCount] = strName;
+ m_ubSignature[m_iLocalSymCount] = signature;
+ checked {m_iLocalSymCount++; }
+ }
+
+ internal void AddUsingNamespace(String strNamespace)
+ {
+ EnsureCapacityNamespace();
+ m_namespace[m_iNameSpaceCount] = strNamespace;
+ checked { m_iNameSpaceCount++; }
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ internal virtual void EmitLocalSymInfo(ISymbolWriter symWriter)
+ {
+ int i;
+
+ for (i = 0; i < m_iLocalSymCount; i ++)
+ {
+ symWriter.DefineLocalVariable(
+ m_strName[i],
+ FieldAttributes.PrivateScope,
+ m_ubSignature[i],
+ SymAddressKind.ILOffset,
+ m_iLocalSlot[i],
+ 0, // addr2 is not used yet
+ 0, // addr3 is not used
+ m_iStartOffset[i],
+ m_iEndOffset[i]);
+ }
+ for (i = 0; i < m_iNameSpaceCount; i ++)
+ {
+ symWriter.UsingNamespace(m_namespace[i]);
+ }
+ }
+
+ #endregion
+ }
+
+ /// <summary>
+ /// Describes exception handler in a method body.
+ /// </summary>
+ [StructLayout(LayoutKind.Sequential)]
+ [ComVisible(false)]
+ public struct ExceptionHandler : IEquatable<ExceptionHandler>
+ {
+ // Keep in sync with unmanged structure.
+ internal readonly int m_exceptionClass;
+ internal readonly int m_tryStartOffset;
+ internal readonly int m_tryEndOffset;
+ internal readonly int m_filterOffset;
+ internal readonly int m_handlerStartOffset;
+ internal readonly int m_handlerEndOffset;
+ internal readonly ExceptionHandlingClauseOptions m_kind;
+
+ public int ExceptionTypeToken
+ {
+ get { return m_exceptionClass; }
+ }
+
+ public int TryOffset
+ {
+ get { return m_tryStartOffset; }
+ }
+
+ public int TryLength
+ {
+ get { return m_tryEndOffset - m_tryStartOffset; }
+ }
+
+ public int FilterOffset
+ {
+ get { return m_filterOffset; }
+ }
+
+ public int HandlerOffset
+ {
+ get { return m_handlerStartOffset; }
+ }
+
+ public int HandlerLength
+ {
+ get { return m_handlerEndOffset - m_handlerStartOffset; }
+ }
+
+ public ExceptionHandlingClauseOptions Kind
+ {
+ get { return m_kind; }
+ }
+
+ #region Constructors
+
+ /// <summary>
+ /// Creates a description of an exception handler.
+ /// </summary>
+ /// <param name="tryOffset">The offset of the first instruction protected by this handler.</param>
+ /// <param name="tryLength">The number of bytes protected by this handler.</param>
+ /// <param name="filterOffset">The filter code begins at the specified offset and ends at the first instruction of the handler block. Specify 0 if not applicable (this is not a filter handler).</param>
+ /// <param name="handlerOffset">The offset of the first instruction of this handler.</param>
+ /// <param name="handlerLength">The number of bytes of the handler.</param>
+ /// <param name="kind">The kind of handler, the handler might be a catch handler, filter handler, fault handler, or finally handler.</param>
+ /// <param name="exceptionTypeToken">The token of the exception type handled by this handler. Specify 0 if not applicable (this is finally handler).</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Some of the instruction offset is negative,
+ /// the end offset of specified range is less than its start offset,
+ /// or <paramref name="kind"/> has an invalid value.
+ /// </exception>
+ public ExceptionHandler(int tryOffset, int tryLength, int filterOffset, int handlerOffset, int handlerLength,
+ ExceptionHandlingClauseOptions kind, int exceptionTypeToken)
+ {
+ if (tryOffset < 0)
+ {
+ throw new ArgumentOutOfRangeException("tryOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (tryLength < 0)
+ {
+ throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (filterOffset < 0)
+ {
+ throw new ArgumentOutOfRangeException("filterOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (handlerOffset < 0)
+ {
+ throw new ArgumentOutOfRangeException("handlerOffset", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (handlerLength < 0)
+ {
+ throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if ((long)tryOffset + tryLength > Int32.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("tryLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - tryOffset));
+ }
+
+ if ((long)handlerOffset + handlerLength > Int32.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("handlerLength", Environment.GetResourceString("ArgumentOutOfRange_Range", 0, Int32.MaxValue - handlerOffset));
+ }
+
+ // Other tokens migth also be invalid. We only check nil tokens as the implementation (SectEH_Emit in corhlpr.cpp) requires it,
+ // and we can't check for valid tokens until the module is baked.
+ if (kind == ExceptionHandlingClauseOptions.Clause && (exceptionTypeToken & 0x00FFFFFF) == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeToken", exceptionTypeToken), "exceptionTypeToken");
+ }
+
+ Contract.EndContractBlock();
+
+ if (!IsValidKind(kind))
+ {
+ throw new ArgumentOutOfRangeException("kind", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ }
+
+ m_tryStartOffset = tryOffset;
+ m_tryEndOffset = tryOffset + tryLength;
+ m_filterOffset = filterOffset;
+ m_handlerStartOffset = handlerOffset;
+ m_handlerEndOffset = handlerOffset + handlerLength;
+ m_kind = kind;
+ m_exceptionClass = exceptionTypeToken;
+ }
+
+ internal ExceptionHandler(int tryStartOffset, int tryEndOffset, int filterOffset, int handlerStartOffset, int handlerEndOffset,
+ int kind, int exceptionTypeToken)
+ {
+ Contract.Assert(tryStartOffset >= 0);
+ Contract.Assert(tryEndOffset >= 0);
+ Contract.Assert(filterOffset >= 0);
+ Contract.Assert(handlerStartOffset >= 0);
+ Contract.Assert(handlerEndOffset >= 0);
+ Contract.Assert(IsValidKind((ExceptionHandlingClauseOptions)kind));
+ Contract.Assert(kind != (int)ExceptionHandlingClauseOptions.Clause || (exceptionTypeToken & 0x00FFFFFF) != 0);
+
+ m_tryStartOffset = tryStartOffset;
+ m_tryEndOffset = tryEndOffset;
+ m_filterOffset = filterOffset;
+ m_handlerStartOffset = handlerStartOffset;
+ m_handlerEndOffset = handlerEndOffset;
+ m_kind = (ExceptionHandlingClauseOptions)kind;
+ m_exceptionClass = exceptionTypeToken;
+ }
+
+ private static bool IsValidKind(ExceptionHandlingClauseOptions kind)
+ {
+ switch (kind)
+ {
+ case ExceptionHandlingClauseOptions.Clause:
+ case ExceptionHandlingClauseOptions.Filter:
+ case ExceptionHandlingClauseOptions.Finally:
+ case ExceptionHandlingClauseOptions.Fault:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ #endregion
+
+ #region Equality
+
+ public override int GetHashCode()
+ {
+ return m_exceptionClass ^ m_tryStartOffset ^ m_tryEndOffset ^ m_filterOffset ^ m_handlerStartOffset ^ m_handlerEndOffset ^ (int)m_kind;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ return obj is ExceptionHandler && Equals((ExceptionHandler)obj);
+ }
+
+ public bool Equals(ExceptionHandler other)
+ {
+ return
+ other.m_exceptionClass == m_exceptionClass &&
+ other.m_tryStartOffset == m_tryStartOffset &&
+ other.m_tryEndOffset == m_tryEndOffset &&
+ other.m_filterOffset == m_filterOffset &&
+ other.m_handlerStartOffset == m_handlerStartOffset &&
+ other.m_handlerEndOffset == m_handlerEndOffset &&
+ other.m_kind == m_kind;
+ }
+
+ public static bool operator ==(ExceptionHandler left, ExceptionHandler right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(ExceptionHandler left, ExceptionHandler right)
+ {
+ return !left.Equals(right);
+ }
+
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs b/src/mscorlib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs
new file mode 100644
index 0000000000..5b69b6e607
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs
@@ -0,0 +1,142 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class MethodBuilderInstantiation : MethodInfo
+ {
+ #region Static Members
+ internal static MethodInfo MakeGenericMethod(MethodInfo method, Type[] inst)
+ {
+ if (!method.IsGenericMethodDefinition)
+ throw new InvalidOperationException();
+ Contract.EndContractBlock();
+
+ return new MethodBuilderInstantiation(method, inst);
+ }
+
+ #endregion
+
+ #region Private Data Mebers
+ internal MethodInfo m_method;
+ private Type[] m_inst;
+ #endregion
+
+ #region Constructor
+ internal MethodBuilderInstantiation(MethodInfo method, Type[] inst)
+ {
+ m_method = method;
+ m_inst = inst;
+ }
+ #endregion
+
+ internal override Type[] GetParameterTypes()
+ {
+ return m_method.GetParameterTypes();
+ }
+
+ #region MemberBase
+ public override MemberTypes MemberType { get { return m_method.MemberType; } }
+ public override String Name { get { return m_method.Name; } }
+ public override Type DeclaringType { get { return m_method.DeclaringType; } }
+ public override Type ReflectedType { get { return m_method.ReflectedType; } }
+ public override Object[] GetCustomAttributes(bool inherit) { return m_method.GetCustomAttributes(inherit); }
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { return m_method.GetCustomAttributes(attributeType, inherit); }
+ public override bool IsDefined(Type attributeType, bool inherit) { return m_method.IsDefined(attributeType, inherit); }
+ public override Module Module { get { return m_method.Module; } }
+ public new Type GetType() { return base.GetType(); }
+ #endregion
+
+ #region MethodBase Members
+ [Pure]
+ public override ParameterInfo[] GetParameters() { throw new NotSupportedException(); }
+ public override MethodImplAttributes GetMethodImplementationFlags() { return m_method.GetMethodImplementationFlags(); }
+ public override RuntimeMethodHandle MethodHandle { get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); } }
+ public override MethodAttributes Attributes { get { return m_method.Attributes; } }
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ public override CallingConventions CallingConvention { get { return m_method.CallingConvention; } }
+ public override Type[] GetGenericArguments() { return m_inst; }
+ public override MethodInfo GetGenericMethodDefinition() { return m_method; }
+ public override bool IsGenericMethodDefinition { get { return false; } }
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ for (int i = 0; i < m_inst.Length; i++)
+ {
+ if (m_inst[i].ContainsGenericParameters)
+ return true;
+ }
+
+ if (DeclaringType != null && DeclaringType.ContainsGenericParameters)
+ return true;
+
+ return false;
+ }
+ }
+
+ public override MethodInfo MakeGenericMethod(params Type[] arguments)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericMethodDefinition"));
+ }
+
+ public override bool IsGenericMethod { get { return true; } }
+
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public override Type ReturnType
+ {
+ get
+ {
+ return m_method.ReturnType;
+ }
+ }
+
+ public override ParameterInfo ReturnParameter { get { throw new NotSupportedException(); } }
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw new NotSupportedException(); } }
+ public override MethodInfo GetBaseDefinition() { throw new NotSupportedException(); }
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/MethodToken.cs b/src/mscorlib/src/System/Reflection/Emit/MethodToken.cs
new file mode 100644
index 0000000000..cc28e173d7
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/MethodToken.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Represents a Method to the ILGenerator class.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct MethodToken
+ {
+ public static readonly MethodToken Empty = new MethodToken();
+ internal int m_method;
+
+ internal MethodToken(int str) {
+ m_method=str;
+ }
+
+ public int Token {
+ get { return m_method; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_method;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is MethodToken)
+ return Equals((MethodToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(MethodToken obj)
+ {
+ return obj.m_method == m_method;
+ }
+
+ public static bool operator ==(MethodToken a, MethodToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(MethodToken a, MethodToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs
new file mode 100644
index 0000000000..ce2a592ae2
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs
@@ -0,0 +1,2422 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.SymbolStore;
+ using System.Globalization;
+ using System.Reflection;
+ using System.Diagnostics;
+ using System.IO;
+ using System.Resources;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.Versioning;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class InternalModuleBuilder : RuntimeModule
+ {
+ #region Private Data Members
+ // WARNING!! WARNING!!
+ // InternalModuleBuilder should not contain any data members as its reflectbase is the same as Module.
+ #endregion
+
+ private InternalModuleBuilder() { }
+
+ #region object overrides
+ public override bool Equals(object obj)
+ {
+ if (obj == null)
+ return false;
+
+ if (obj is InternalModuleBuilder)
+ return ((object)this == obj);
+
+ return obj.Equals(this);
+ }
+ // Need a dummy GetHashCode to pair with Equals
+ public override int GetHashCode() { return base.GetHashCode(); }
+ #endregion
+ }
+
+ // deliberately not [serializable]
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ModuleBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ModuleBuilder : Module, _ModuleBuilder
+ {
+ #region FCalls
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr nCreateISymWriterForDynamicModule(Module module, String filename);
+
+ #endregion
+
+ #region Internal Static Members
+ static internal String UnmangleTypeName(String typeName)
+ {
+ // Gets the original type name, without '+' name mangling.
+
+ int i = typeName.Length - 1;
+ while (true)
+ {
+ i = typeName.LastIndexOf('+', i);
+ if (i == -1)
+ break;
+
+ bool evenSlashes = true;
+ int iSlash = i;
+ while (typeName[--iSlash] == '\\')
+ evenSlashes = !evenSlashes;
+
+ // Even number of slashes means this '+' is a name separator
+ if (evenSlashes)
+ break;
+
+ i = iSlash;
+ }
+
+ return typeName.Substring(i + 1);
+ }
+
+ #endregion
+
+ #region Intenral Data Members
+ // m_TypeBuilder contains both TypeBuilder and EnumBuilder objects
+ private Dictionary<string, Type> m_TypeBuilderDict;
+ private ISymbolWriter m_iSymWriter;
+ internal ModuleBuilderData m_moduleData;
+#if !FEATURE_CORECLR
+ private MethodToken m_EntryPoint;
+#endif //!FEATURE_CORECLR
+ internal InternalModuleBuilder m_internalModuleBuilder;
+ // This is the "external" AssemblyBuilder
+ // only the "external" ModuleBuilder has this set
+ private AssemblyBuilder m_assemblyBuilder;
+ internal AssemblyBuilder ContainingAssemblyBuilder { get { return m_assemblyBuilder; } }
+ #endregion
+
+ #region Constructor
+ internal ModuleBuilder(AssemblyBuilder assemblyBuilder, InternalModuleBuilder internalModuleBuilder)
+ {
+ m_internalModuleBuilder = internalModuleBuilder;
+ m_assemblyBuilder = assemblyBuilder;
+ }
+ #endregion
+
+ #region Private Members
+ internal void AddType(string name, Type type)
+ {
+ m_TypeBuilderDict.Add(name, type);
+ }
+
+ internal void CheckTypeNameConflict(String strTypeName, Type enclosingType)
+ {
+ Type foundType = null;
+ if (m_TypeBuilderDict.TryGetValue(strTypeName, out foundType) &&
+ object.ReferenceEquals(foundType.DeclaringType, enclosingType))
+ {
+ // Cannot have two types with the same name
+ throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateTypeName"));
+ }
+ }
+
+ private Type GetType(String strFormat, Type baseType)
+ {
+ // This function takes a string to describe the compound type, such as "[,][]", and a baseType.
+
+ if (strFormat == null || strFormat.Equals(String.Empty))
+ {
+ return baseType;
+ }
+
+ // convert the format string to byte array and then call FormCompoundType
+ return SymbolType.FormCompoundType(strFormat, baseType, 0);
+
+ }
+
+
+ internal void CheckContext(params Type[][] typess)
+ {
+ ContainingAssemblyBuilder.CheckContext(typess);
+ }
+ internal void CheckContext(params Type[] types)
+ {
+ ContainingAssemblyBuilder.CheckContext(types);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetTypeRef(RuntimeModule module, String strFullName, RuntimeModule refedModule, String strRefedModuleFileName, int tkResolution);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetMemberRef(RuntimeModule module, RuntimeModule refedModule, int tr, int defToken);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRef(Module refedModule, int tr, int defToken)
+ {
+ return GetMemberRef(GetNativeHandle(), GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), tr, defToken);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetMemberRefFromSignature(RuntimeModule module, int tr, String methodName, byte[] signature, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefFromSignature(int tr, String methodName, byte[] signature, int length)
+ {
+ return GetMemberRefFromSignature(GetNativeHandle(), tr, methodName, signature, length);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetMemberRefOfMethodInfo(RuntimeModule module, int tr, IRuntimeMethodInfo method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefOfMethodInfo(int tr, RuntimeMethodInfo method)
+ {
+ Contract.Assert(method != null);
+
+#if FEATURE_APPX
+ if (ContainingAssemblyBuilder.ProfileAPICheck)
+ {
+ if ((method.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", method.FullName));
+ }
+#endif
+
+ return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefOfMethodInfo(int tr, RuntimeConstructorInfo method)
+ {
+ Contract.Assert(method != null);
+
+#if FEATURE_APPX
+ if (ContainingAssemblyBuilder.ProfileAPICheck)
+ {
+ if ((method.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", method.FullName));
+ }
+#endif
+
+ return GetMemberRefOfMethodInfo(GetNativeHandle(), tr, method);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetMemberRefOfFieldInfo(RuntimeModule module, int tkType, RuntimeTypeHandle declaringType, int tkField);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefOfFieldInfo(int tkType, RuntimeTypeHandle declaringType, RuntimeFieldInfo runtimeField)
+ {
+ Contract.Assert(runtimeField != null);
+
+#if FEATURE_APPX
+ if (ContainingAssemblyBuilder.ProfileAPICheck)
+ {
+ RtFieldInfo rtField = runtimeField as RtFieldInfo;
+ if (rtField != null && (rtField.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtField.FullName));
+ }
+#endif
+
+ return GetMemberRefOfFieldInfo(GetNativeHandle(), tkType, declaringType, runtimeField.MetadataToken);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetTokenFromTypeSpec(RuntimeModule pModule, byte[] signature, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetTokenFromTypeSpec(byte[] signature, int length)
+ {
+ return GetTokenFromTypeSpec(GetNativeHandle(), signature, length);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetArrayMethodToken(RuntimeModule module, int tkTypeSpec, String methodName, byte[] signature, int sigLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetStringConstant(RuntimeModule module, String str, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void PreSavePEFile(RuntimeModule module, int portableExecutableKind, int imageFileMachine);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void SavePEFile(RuntimeModule module, String fileName, int entryPoint, int isExe, bool isManifestFile);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void AddResource(
+ RuntimeModule module, String strName,
+ byte[] resBytes, int resByteCount, int tkFile, int attribute,
+ int portableExecutableKind, int imageFileMachine);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void SetModuleName(RuntimeModule module, String strModuleName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static void SetFieldRVAContent(RuntimeModule module, int fdToken, byte[] data, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void DefineNativeResourceFile(RuntimeModule module,
+ String strFilename,
+ int portableExecutableKind,
+ int ImageFileMachine);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void DefineNativeResourceBytes(RuntimeModule module,
+ byte[] pbResource, int cbResource,
+ int portableExecutableKind,
+ int imageFileMachine);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void DefineNativeResource(PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ string strResourceFileName = m_moduleData.m_strResourceFileName;
+ byte[] resourceBytes = m_moduleData.m_resourceBytes;
+
+ if (strResourceFileName != null)
+ {
+ DefineNativeResourceFile(GetNativeHandle(),
+ strResourceFileName,
+ (int)portableExecutableKind, (int)imageFileMachine);
+ }
+ else
+ if (resourceBytes != null)
+ {
+ DefineNativeResourceBytes(GetNativeHandle(),
+ resourceBytes, resourceBytes.Length,
+ (int)portableExecutableKind, (int)imageFileMachine);
+ }
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal virtual Type FindTypeBuilderWithName(String strTypeName, bool ignoreCase)
+ {
+ if (ignoreCase)
+ {
+ foreach (string name in m_TypeBuilderDict.Keys)
+ {
+ if (String.Compare(name, strTypeName, (StringComparison.OrdinalIgnoreCase)) == 0)
+ return m_TypeBuilderDict[name];
+ }
+ }
+ else
+ {
+ Type foundType;
+ if (m_TypeBuilderDict.TryGetValue(strTypeName, out foundType))
+ return foundType;
+ }
+
+ return null;
+ }
+
+#if !FEATURE_CORECLR
+ internal void SetEntryPoint(MethodToken entryPoint)
+ {
+ // Sets the entry point of the module to be a given method. If no entry point
+ // is specified, calling EmitPEFile will generate a dll.
+ // AssemblyBuilder.SetEntryPoint has already demanded required permission
+ m_EntryPoint = entryPoint;
+ }
+#endif //!FEATURE_CORECLR
+
+
+#if !FEATURE_CORECLR
+ // This is a helper called by AssemblyBuilder save to presave information for the persistable modules.
+ // no need to lock here because we have already taken the lock in AssemblyBuilder.Save
+ [System.Security.SecurityCritical] // auto-generated
+ internal void PreSave(String fileName,
+ PortableExecutableKinds portableExecutableKind, ImageFileMachine imageFileMachine)
+ {
+ if (m_moduleData.m_isSaved == true)
+ {
+ // can only save once
+ throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture,
+ Environment.GetResourceString("InvalidOperation_ModuleHasBeenSaved"),
+ m_moduleData.m_strModuleName));
+ }
+
+ if (m_moduleData.m_fGlobalBeenCreated == false && m_moduleData.m_fHasGlobal == true)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalFunctionNotBaked"));
+
+ TypeBuilder typeBuilder;
+ foreach (Type item in m_TypeBuilderDict.Values)
+ {
+ if (item is TypeBuilder)
+ {
+ typeBuilder = (TypeBuilder)item;
+ }
+ else
+ {
+ EnumBuilder enumBuilder = (EnumBuilder)item;
+ typeBuilder = enumBuilder.m_typeBuilder;
+ }
+
+ if (!typeBuilder.IsCreated())
+ {
+ // cannot save to PE file without creating all of the types first
+ throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture,
+ Environment.GetResourceString("NotSupported_NotAllTypesAreBaked"),
+ typeBuilder.FullName));
+ }
+ }
+
+ PreSavePEFile(GetNativeHandle(), (int)portableExecutableKind, (int)imageFileMachine);
+ }
+
+ // no need to lock here because we have already taken the lock in AssemblyBuilder.Save
+ [System.Security.SecurityCritical] // auto-generated
+ internal void Save(String fileName, bool isAssemblyFile, PortableExecutableKinds portableExecutableKind,
+ ImageFileMachine imageFileMachine)
+ {
+ // This is a helper called by AssemblyBuilder save to save information for the persistable modules.
+ if (m_moduleData.m_embeddedRes != null)
+ {
+ // There are embedded resources for this module
+ ResWriterData resWriter;
+
+ // Add each resource content into the to be saved PE file
+ for (resWriter = m_moduleData.m_embeddedRes; resWriter != null; resWriter = resWriter.m_nextResWriter)
+ {
+ if (resWriter.m_resWriter != null)
+ resWriter.m_resWriter.Generate();
+
+ byte[] resBytes = new byte[resWriter.m_memoryStream.Length];
+ resWriter.m_memoryStream.Flush();
+ resWriter.m_memoryStream.Position = 0;
+ resWriter.m_memoryStream.Read(resBytes, 0, resBytes.Length);
+
+ AddResource(GetNativeHandle(),
+ resWriter.m_strName,
+ resBytes,
+ resBytes.Length,
+ m_moduleData.FileToken,
+ (int)resWriter.m_attribute,
+ (int)portableExecutableKind,
+ (int)imageFileMachine);
+ }
+ }
+
+ DefineNativeResource(portableExecutableKind, imageFileMachine);
+
+ PEFileKinds pekind = isAssemblyFile ? ContainingAssemblyBuilder.m_assemblyData.m_peFileKind : PEFileKinds.Dll;
+
+ SavePEFile(GetNativeHandle(), fileName, m_EntryPoint.Token, (int)pekind, isAssemblyFile);
+
+ m_moduleData.m_isSaved = true;
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetTypeRefNested(Type type, Module refedModule, String strRefedModuleFileName)
+ {
+ // This function will generate correct TypeRef token for top level type and nested type.
+
+ Type enclosingType = type.DeclaringType;
+ int tkResolution = 0;
+ String typeName = type.FullName;
+
+ if (enclosingType != null)
+ {
+ tkResolution = GetTypeRefNested(enclosingType, refedModule, strRefedModuleFileName);
+ typeName = UnmangleTypeName(typeName);
+ }
+
+ Contract.Assert(!type.IsByRef, "Must not be ByRef.");
+ Contract.Assert(!type.IsGenericType || type.IsGenericTypeDefinition, "Must not have generic arguments.");
+
+#if FEATURE_APPX
+ if (ContainingAssemblyBuilder.ProfileAPICheck)
+ {
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType != null && (rtType.InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", rtType.FullName));
+ }
+ }
+#endif
+
+ return GetTypeRef(GetNativeHandle(), typeName, GetRuntimeModuleFromModule(refedModule).GetNativeHandle(), strRefedModuleFileName, tkResolution);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal MethodToken InternalGetConstructorToken(ConstructorInfo con, bool usingRef)
+ {
+ // Helper to get constructor token. If usingRef is true, we will never use the def token
+
+ if (con == null)
+ throw new ArgumentNullException("con");
+ Contract.EndContractBlock();
+
+ int tr;
+ int mr = 0;
+
+ ConstructorBuilder conBuilder = null;
+ ConstructorOnTypeBuilderInstantiation conOnTypeBuilderInst = null;
+ RuntimeConstructorInfo rtCon = null;
+
+ if ( (conBuilder = con as ConstructorBuilder) != null )
+ {
+ if (usingRef == false && conBuilder.Module.Equals(this))
+ return conBuilder.GetToken();
+
+ // constructor is defined in a different module
+ tr = GetTypeTokenInternal(con.ReflectedType).Token;
+ mr = GetMemberRef(con.ReflectedType.Module, tr, conBuilder.GetToken().Token);
+ }
+ else if ( (conOnTypeBuilderInst = con as ConstructorOnTypeBuilderInstantiation) != null )
+ {
+ if (usingRef == true) throw new InvalidOperationException();
+
+ tr = GetTypeTokenInternal(con.DeclaringType).Token;
+ mr = GetMemberRef(con.DeclaringType.Module, tr, conOnTypeBuilderInst.MetadataTokenInternal);
+ }
+ else if ( (rtCon = con as RuntimeConstructorInfo) != null && con.ReflectedType.IsArray == false)
+ {
+ // constructor is not a dynamic field
+ // We need to get the TypeRef tokens
+
+ tr = GetTypeTokenInternal(con.ReflectedType).Token;
+ mr = GetMemberRefOfMethodInfo(tr, rtCon);
+ }
+ else
+ {
+ // some user derived ConstructorInfo
+ // go through the slower code path, i.e. retrieve parameters and form signature helper.
+ ParameterInfo[] parameters = con.GetParameters();
+ if (parameters == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo"));
+
+ int count = parameters.Length;
+ Type[] parameterTypes = new Type[count];
+ Type[][] requiredCustomModifiers = new Type[count][];
+ Type[][] optionalCustomModifiers = new Type[count][];
+
+ for (int i = 0; i < count; i++)
+ {
+ if (parameters[i] == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo"));
+
+ parameterTypes[i] = parameters[i].ParameterType;
+ requiredCustomModifiers[i] = parameters[i].GetRequiredCustomModifiers();
+ optionalCustomModifiers[i] = parameters[i].GetOptionalCustomModifiers();
+ }
+
+ tr = GetTypeTokenInternal(con.ReflectedType).Token;
+
+ SignatureHelper sigHelp = SignatureHelper.GetMethodSigHelper(this, con.CallingConvention, null, null, null, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+ int length;
+ byte[] sigBytes = sigHelp.InternalGetSignature(out length);
+
+ mr = GetMemberRefFromSignature(tr, con.Name, sigBytes, length);
+ }
+
+ return new MethodToken( mr );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void Init(String strModuleName, String strFileName, int tkFile)
+ {
+ m_moduleData = new ModuleBuilderData(this, strModuleName, strFileName, tkFile);
+ m_TypeBuilderDict = new Dictionary<string, Type>();
+ }
+
+ // This is a method for changing module and file name of the manifest module (created by default for
+ // each assembly).
+ [System.Security.SecurityCritical] // auto-generated
+ internal void ModifyModuleName(string name)
+ {
+ // Reset the names in the managed ModuleBuilderData
+ m_moduleData.ModifyModuleName(name);
+
+ // Reset the name in the underlying metadata
+ ModuleBuilder.SetModuleName(GetNativeHandle(), name);
+ }
+
+ internal void SetSymWriter(ISymbolWriter writer)
+ {
+ m_iSymWriter = writer;
+ }
+
+ internal object SyncRoot
+ {
+ get
+ {
+ return ContainingAssemblyBuilder.SyncRoot;
+ }
+ }
+
+ #endregion
+
+ #region Module Overrides
+
+ // m_internalModuleBuilder is null iff this is a "internal" ModuleBuilder
+ internal InternalModuleBuilder InternalModule
+ {
+ get
+ {
+ return m_internalModuleBuilder;
+ }
+ }
+
+ internal override ModuleHandle GetModuleHandle()
+ {
+ return new ModuleHandle(GetNativeHandle());
+ }
+
+ internal RuntimeModule GetNativeHandle()
+ {
+ return InternalModule.GetNativeHandle();
+ }
+
+ private static RuntimeModule GetRuntimeModuleFromModule(Module m)
+ {
+ ModuleBuilder mb = m as ModuleBuilder;
+ if (mb != null)
+ {
+ return mb.InternalModule;
+ }
+
+ return m as RuntimeModule;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private int GetMemberRefToken(MethodBase method, IEnumerable<Type> optionalParameterTypes)
+ {
+ Type[] parameterTypes;
+ Type returnType;
+ int tkParent;
+ int cGenericParameters = 0;
+
+ if (method.IsGenericMethod)
+ {
+ if (!method.IsGenericMethodDefinition)
+ throw new InvalidOperationException();
+
+ cGenericParameters = method.GetGenericArguments().Length;
+ }
+
+ if (optionalParameterTypes != null)
+ {
+ if ((method.CallingConvention & CallingConventions.VarArgs) == 0)
+ {
+ // Client should not supply optional parameter in default calling convention
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
+ }
+ }
+
+ MethodInfo masmi = method as MethodInfo;
+
+ if (method.DeclaringType.IsGenericType)
+ {
+ MethodBase methDef = null; // methodInfo = G<Foo>.M<Bar> ==> methDef = G<T>.M<S>
+
+ MethodOnTypeBuilderInstantiation motbi;
+ ConstructorOnTypeBuilderInstantiation cotbi;
+
+ if ((motbi = method as MethodOnTypeBuilderInstantiation) != null)
+ {
+ methDef = motbi.m_method;
+ }
+ else if ((cotbi = method as ConstructorOnTypeBuilderInstantiation) != null)
+ {
+ methDef = cotbi.m_ctor;
+ }
+ else if (method is MethodBuilder || method is ConstructorBuilder)
+ {
+ // methodInfo must be GenericMethodDefinition; trying to emit G<?>.M<S>
+ methDef = method;
+ }
+ else
+ {
+ Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
+
+ if (method.IsGenericMethod)
+ {
+ Contract.Assert(masmi != null);
+
+ methDef = masmi.GetGenericMethodDefinition();
+ methDef = methDef.Module.ResolveMethod(
+ method.MetadataToken,
+ methDef.DeclaringType != null ? methDef.DeclaringType.GetGenericArguments() : null,
+ methDef.GetGenericArguments());
+ }
+ else
+ {
+ methDef = method.Module.ResolveMethod(
+ method.MetadataToken,
+ method.DeclaringType != null ? method.DeclaringType.GetGenericArguments() : null,
+ null);
+ }
+ }
+
+ parameterTypes = methDef.GetParameterTypes();
+ returnType = MethodBuilder.GetMethodBaseReturnType(methDef);
+ }
+ else
+ {
+ parameterTypes = method.GetParameterTypes();
+ returnType = MethodBuilder.GetMethodBaseReturnType(method);
+ }
+
+ int sigLength;
+ byte[] sigBytes = GetMemberRefSignature(method.CallingConvention, returnType, parameterTypes,
+ optionalParameterTypes, cGenericParameters).InternalGetSignature(out sigLength);
+
+ if (method.DeclaringType.IsGenericType)
+ {
+ int length;
+ byte[] sig = SignatureHelper.GetTypeSigToken(this, method.DeclaringType).InternalGetSignature(out length);
+ tkParent = GetTokenFromTypeSpec(sig, length);
+ }
+ else if (!method.Module.Equals(this))
+ {
+ // Use typeRef as parent because the method's declaringType lives in a different assembly
+ tkParent = GetTypeToken(method.DeclaringType).Token;
+ }
+ else
+ {
+ // Use methodDef as parent because the method lives in this assembly and its declaringType has no generic arguments
+ if (masmi != null)
+ tkParent = GetMethodToken(masmi).Token;
+ else
+ tkParent = GetConstructorToken(method as ConstructorInfo).Token;
+ }
+
+ return GetMemberRefFromSignature(tkParent, method.Name, sigBytes, sigLength);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType,
+ Type[] parameterTypes, IEnumerable<Type> optionalParameterTypes, int cGenericParameters)
+ {
+ int cParams = (parameterTypes == null) ? 0 : parameterTypes.Length;
+ SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters);
+
+ for (int i = 0; i < cParams; i++)
+ {
+ sig.AddArgument(parameterTypes[i]);
+ }
+
+ if (optionalParameterTypes != null) {
+ int i = 0;
+ foreach (Type type in optionalParameterTypes)
+ {
+ // add the sentinel
+ if (i == 0)
+ {
+ sig.AddSentinel();
+ }
+
+ sig.AddArgument(type);
+ i++;
+ }
+ }
+
+ return sig;
+ }
+
+ #endregion
+
+ #region object overrides
+ public override bool Equals(object obj)
+ {
+ return InternalModule.Equals(obj);
+ }
+ // Need a dummy GetHashCode to pair with Equals
+ public override int GetHashCode() { return InternalModule.GetHashCode(); }
+ #endregion
+
+ #region ICustomAttributeProvider Members
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return InternalModule.GetCustomAttributes(inherit);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return InternalModule.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return InternalModule.IsDefined(attributeType, inherit);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return InternalModule.GetCustomAttributesData();
+ }
+ #endregion
+
+ #region Module Overrides
+
+ public override Type[] GetTypes()
+ {
+ lock(SyncRoot)
+ {
+ return GetTypesNoLock();
+ }
+ }
+
+ internal Type[] GetTypesNoLock()
+ {
+ int size = m_TypeBuilderDict.Count;
+ Type[] typeList = new Type[m_TypeBuilderDict.Count];
+ int i = 0;
+
+ foreach (Type builder in m_TypeBuilderDict.Values)
+ {
+ EnumBuilder enumBldr = builder as EnumBuilder;
+ TypeBuilder tmpTypeBldr;
+
+ if (enumBldr != null)
+ tmpTypeBldr = enumBldr.m_typeBuilder;
+ else
+ tmpTypeBldr = (TypeBuilder)builder;
+
+ // We should not return TypeBuilders.
+ // Otherwise anyone can emit code in it.
+ if (tmpTypeBldr.IsCreated())
+ typeList[i++] = tmpTypeBldr.UnderlyingSystemType;
+ else
+ typeList[i++] = builder;
+ }
+
+ return typeList;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override Type GetType(String className)
+ {
+ return GetType(className, false, false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override Type GetType(String className, bool ignoreCase)
+ {
+ return GetType(className, false, ignoreCase);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override Type GetType(String className, bool throwOnError, bool ignoreCase)
+ {
+ lock(SyncRoot)
+ {
+ return GetTypeNoLock(className, throwOnError, ignoreCase);
+ }
+ }
+
+ private Type GetTypeNoLock(String className, bool throwOnError, bool ignoreCase)
+ {
+ // public API to to a type. The reason that we need this function override from module
+ // is because clients might need to get foo[] when foo is being built. For example, if
+ // foo class contains a data member of type foo[].
+ // This API first delegate to the Module.GetType implementation. If succeeded, great!
+ // If not, we have to look up the current module to find the TypeBuilder to represent the base
+ // type and form the Type object for "foo[,]".
+
+ // Module.GetType() will verify className.
+ Type baseType = InternalModule.GetType(className, throwOnError, ignoreCase);
+ if (baseType != null)
+ return baseType;
+
+ // Now try to see if we contain a TypeBuilder for this type or not.
+ // Might have a compound type name, indicated via an unescaped
+ // '[', '*' or '&'. Split the name at this point.
+ String baseName = null;
+ String parameters = null;
+ int startIndex = 0;
+
+ while (startIndex <= className.Length)
+ {
+ // Are there any possible special characters left?
+ int i = className.IndexOfAny(new char[]{'[', '*', '&'}, startIndex);
+ if (i == -1)
+ {
+ // No, type name is simple.
+ baseName = className;
+ parameters = null;
+ break;
+ }
+
+ // Found a potential special character, but it might be escaped.
+ int slashes = 0;
+ for (int j = i - 1; j >= 0 && className[j] == '\\'; j--)
+ slashes++;
+
+ // Odd number of slashes indicates escaping.
+ if (slashes % 2 == 1)
+ {
+ startIndex = i + 1;
+ continue;
+ }
+
+ // Found the end of the base type name.
+ baseName = className.Substring(0, i);
+ parameters = className.Substring(i);
+ break;
+ }
+
+ // If we didn't find a basename yet, the entire class name is
+ // the base name and we don't have a composite type.
+ if (baseName == null)
+ {
+ baseName = className;
+ parameters = null;
+ }
+
+ baseName = baseName.Replace(@"\\",@"\").Replace(@"\[",@"[").Replace(@"\*",@"*").Replace(@"\&",@"&");
+
+ if (parameters != null)
+ {
+ // try to see if reflection can find the base type. It can be such that reflection
+ // does not support the complex format string yet!
+
+ baseType = InternalModule.GetType(baseName, false, ignoreCase);
+ }
+
+ if (baseType == null)
+ {
+ // try to find it among the unbaked types.
+ // starting with the current module first of all.
+ baseType = FindTypeBuilderWithName(baseName, ignoreCase);
+ if (baseType == null && Assembly is AssemblyBuilder)
+ {
+ // now goto Assembly level to find the type.
+ int size;
+ List<ModuleBuilder> modList;
+
+ modList = ContainingAssemblyBuilder.m_assemblyData.m_moduleBuilderList;
+ size = modList.Count;
+ for (int i = 0; i < size && baseType == null; i++)
+ {
+ ModuleBuilder mBuilder = modList[i];
+ baseType = mBuilder.FindTypeBuilderWithName(baseName, ignoreCase);
+ }
+ }
+ if (baseType == null)
+ return null;
+ }
+
+ if (parameters == null)
+ return baseType;
+
+ return GetType(parameters, baseType);
+ }
+
+ public override String FullyQualifiedName
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ get
+ {
+ String fullyQualifiedName = m_moduleData.m_strFileName;
+ if (fullyQualifiedName == null)
+ return null;
+ if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null)
+ {
+ fullyQualifiedName = Path.Combine(ContainingAssemblyBuilder.m_assemblyData.m_strDir, fullyQualifiedName);
+ fullyQualifiedName = Path.UnsafeGetFullPath(fullyQualifiedName);
+ }
+
+ if (ContainingAssemblyBuilder.m_assemblyData.m_strDir != null && fullyQualifiedName != null)
+ {
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullyQualifiedName ).Demand();
+ }
+
+ return fullyQualifiedName;
+ }
+ }
+
+ public override byte[] ResolveSignature(int metadataToken)
+ {
+ return InternalModule.ResolveSignature(metadataToken);
+ }
+
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ return InternalModule.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
+ }
+
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ return InternalModule.ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
+ }
+
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ return InternalModule.ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
+ }
+
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ return InternalModule.ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments);
+ }
+
+ public override string ResolveString(int metadataToken)
+ {
+ return InternalModule.ResolveString(metadataToken);
+ }
+
+ public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ InternalModule.GetPEKind(out peKind, out machine);
+ }
+
+ public override int MDStreamVersion
+ {
+ get
+ {
+ return InternalModule.MDStreamVersion;
+ }
+ }
+
+ public override Guid ModuleVersionId
+ {
+ get
+ {
+ return InternalModule.ModuleVersionId;
+ }
+ }
+
+ public override int MetadataToken
+ {
+ get
+ {
+ return InternalModule.MetadataToken;
+ }
+ }
+
+ public override bool IsResource()
+ {
+ return InternalModule.IsResource();
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingFlags)
+ {
+ return InternalModule.GetFields(bindingFlags);
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ return InternalModule.GetField(name, bindingAttr);
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingFlags)
+ {
+ return InternalModule.GetMethods(bindingFlags);
+ }
+
+ protected override MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder,
+ CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ // Cannot call InternalModule.GetMethods because it doesn't allow types to be null
+ return InternalModule.GetMethodInternal(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public override String ScopeName
+ {
+ get
+ {
+ return InternalModule.ScopeName;
+ }
+ }
+
+ public override String Name
+ {
+ get
+ {
+ return InternalModule.Name;
+ }
+ }
+
+ public override Assembly Assembly
+ {
+ [Pure]
+ get
+ {
+ return m_assemblyBuilder;
+ }
+ }
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate()
+ {
+ return InternalModule.GetSignerCertificate();
+ }
+#endif // FEATURE_X509 && FEATURE_CAS_POLICY
+ #endregion
+
+ #region Public Members
+
+ #region Define Type
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineType(String name)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineTypeNoLock(name, TypeAttributes.NotPublic, null, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineType(String name, TypeAttributes attr)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineTypeNoLock(name, attr, null, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ // Why do we only call CheckContext here? Why don't we call it in the other overloads?
+ CheckContext(parent);
+
+ return DefineTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, int typesize)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, typesize);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packingSize, int typesize)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock (SyncRoot)
+ {
+ return DefineTypeNoLock(name, attr, parent, null, packingSize, typesize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineTypeNoLock(name, attr, parent, interfaces, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packingSize, int typesize)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ return new TypeBuilder(name, attr, parent, interfaces, this, packingSize, typesize, null); ;
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineType(String name, TypeAttributes attr, Type parent, PackingSize packsize)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineTypeNoLock(name, attr, parent, packsize);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeBuilder DefineTypeNoLock(String name, TypeAttributes attr, Type parent, PackingSize packsize)
+ {
+ Contract.Ensures(Contract.Result<TypeBuilder>() != null);
+
+ return new TypeBuilder(name, attr, parent, null, this, packsize, TypeBuilder.UnspecifiedTypeSize, null);
+ }
+
+ #endregion
+
+ #region Define Enum
+
+ // This API can only be used to construct a top-level (not nested) enum type.
+ // Nested enum types can be defined manually using ModuleBuilder.DefineType.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public EnumBuilder DefineEnum(String name, TypeAttributes visibility, Type underlyingType)
+ {
+ Contract.Ensures(Contract.Result<EnumBuilder>() != null);
+
+ CheckContext(underlyingType);
+ lock(SyncRoot)
+ {
+ EnumBuilder enumBuilder = DefineEnumNoLock(name, visibility, underlyingType);
+
+ // This enum is not generic, nested, and cannot have any element type.
+ Contract.Assert(name == enumBuilder.FullName);
+
+ // Replace the TypeBuilder object in m_TypeBuilderDict with this EnumBuilder object.
+ Contract.Assert(enumBuilder.m_typeBuilder == m_TypeBuilderDict[name]);
+ m_TypeBuilderDict[name] = enumBuilder;
+
+ return enumBuilder;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private EnumBuilder DefineEnumNoLock(String name, TypeAttributes visibility, Type underlyingType)
+ {
+ Contract.Ensures(Contract.Result<EnumBuilder>() != null);
+
+ return new EnumBuilder(name, underlyingType, visibility, this);
+ }
+
+ #endregion
+
+ #region Define Resource
+#if !FEATURE_CORECLR
+ public IResourceWriter DefineResource(String name, String description)
+ {
+ // Define embedded managed resource to be stored in this module
+ Contract.Ensures(Contract.Result<IResourceWriter>() != null);
+
+ return DefineResource(name, description, ResourceAttributes.Public);
+ }
+
+ public IResourceWriter DefineResource(String name, String description, ResourceAttributes attribute)
+ {
+ // Define embedded managed resource to be stored in this module
+ Contract.Ensures(Contract.Result<IResourceWriter>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineResourceNoLock(name, description, attribute);
+ }
+ }
+
+ private IResourceWriter DefineResourceNoLock(String name, String description, ResourceAttributes attribute)
+ {
+ // Define embedded managed resource to be stored in this module
+
+ if (IsTransient())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer"));
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ Contract.Ensures(Contract.Result<IResourceWriter>() != null);
+ Contract.EndContractBlock();
+
+ if (m_assemblyBuilder.IsPersistable())
+ {
+ m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name);
+
+ MemoryStream stream = new MemoryStream();
+ ResourceWriter resWriter = new ResourceWriter(stream);
+ ResWriterData resWriterData = new ResWriterData( resWriter, stream, name, String.Empty, String.Empty, attribute);
+
+ // chain it to the embedded resource list
+ resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes;
+ m_moduleData.m_embeddedRes = resWriterData;
+ return resWriter;
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer"));
+ }
+ }
+#endif // !FEATURE_CORECLR
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public void DefineManifestResource(String name, Stream stream, ResourceAttributes attribute)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (stream == null)
+ throw new ArgumentNullException("stream");
+ Contract.EndContractBlock();
+
+ // Define embedded managed resource to be stored in this module
+
+ lock(SyncRoot)
+ {
+ DefineManifestResourceNoLock(name, stream, attribute);
+ }
+ }
+
+ private void DefineManifestResourceNoLock(String name, Stream stream, ResourceAttributes attribute)
+ {
+ // Define embedded managed resource to be stored in this module
+ if (IsTransient())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer"));
+ Contract.EndContractBlock();
+
+#if !FEATURE_CORECLR
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+
+ if (m_assemblyBuilder.IsPersistable())
+ {
+ m_assemblyBuilder.m_assemblyData.CheckResNameConflict(name);
+
+ ResWriterData resWriterData = new ResWriterData( null, stream, name, String.Empty, String.Empty, attribute);
+
+ // chain it to the embedded resource list
+ resWriterData.m_nextResWriter = m_moduleData.m_embeddedRes;
+ m_moduleData.m_embeddedRes = resWriterData;
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadResourceContainer"));
+ }
+#endif // !FEATURE_CORECLR
+ }
+
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public void DefineUnmanagedResource(Byte[] resource)
+ {
+ lock(SyncRoot)
+ {
+ DefineUnmanagedResourceInternalNoLock(resource);
+ }
+ }
+
+ internal void DefineUnmanagedResourceInternalNoLock(Byte[] resource)
+ {
+ if (resource == null)
+ throw new ArgumentNullException("resource");
+ Contract.EndContractBlock();
+
+ if (m_moduleData.m_strResourceFileName != null || m_moduleData.m_resourceBytes != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ m_moduleData.m_resourceBytes = new byte[resource.Length];
+ Buffer.BlockCopy(resource, 0, m_moduleData.m_resourceBytes, 0, resource.Length);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public void DefineUnmanagedResource(String resourceFileName)
+ {
+ lock(SyncRoot)
+ {
+ DefineUnmanagedResourceFileInternalNoLock(resourceFileName);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void DefineUnmanagedResourceFileInternalNoLock(String resourceFileName)
+ {
+ if (resourceFileName == null)
+ throw new ArgumentNullException("resourceFileName");
+ Contract.EndContractBlock();
+
+ if (m_moduleData.m_resourceBytes != null || m_moduleData.m_strResourceFileName != null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NativeResourceAlreadyDefined"));
+
+ // Check caller has the right to read the file.
+ string strFullFileName;
+ strFullFileName = Path.UnsafeGetFullPath(resourceFileName);
+ new FileIOPermission(FileIOPermissionAccess.Read, strFullFileName).Demand();
+
+ new EnvironmentPermission(PermissionState.Unrestricted).Assert();
+ try
+ {
+ if (File.UnsafeExists(resourceFileName) == false)
+ throw new FileNotFoundException(Environment.GetResourceString(
+ "IO.FileNotFound_FileName",
+ resourceFileName), resourceFileName);
+ }
+ finally
+ {
+ CodeAccessPermission.RevertAssert();
+ }
+
+ m_moduleData.m_strResourceFileName = strFullFileName;
+ }
+ #endregion
+
+ #region Define Global Method
+ public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineGlobalMethod(name, attributes, CallingConventions.Standard, returnType, parameterTypes);
+ }
+
+ public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineGlobalMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public MethodBuilder DefineGlobalMethod(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ lock(SyncRoot)
+ {
+ return DefineGlobalMethodNoLock(name, attributes, callingConvention, returnType,
+ requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
+ parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+ }
+
+ private MethodBuilder DefineGlobalMethodNoLock(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ if (m_moduleData.m_fGlobalBeenCreated == true)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated"));
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+
+ if ((attributes & MethodAttributes.Static) == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GlobalFunctionHasToBeStatic"));
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+ Contract.EndContractBlock();
+
+ CheckContext(returnType);
+ CheckContext(requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers, parameterTypes);
+ CheckContext(requiredParameterTypeCustomModifiers);
+ CheckContext(optionalParameterTypeCustomModifiers);
+
+ m_moduleData.m_fHasGlobal = true;
+
+ return m_moduleData.m_globalTypeBuilder.DefineMethod(name, attributes, callingConvention,
+ returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
+ parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public MethodBuilder DefinePInvokeMethod(String name, String dllName, MethodAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefinePInvokeMethod(name, dllName, name, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv,
+ CharSet nativeCharSet)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefinePInvokeMethodNoLock(name, dllName, entryName, attributes, callingConvention,
+ returnType, parameterTypes, nativeCallConv, nativeCharSet);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private MethodBuilder DefinePInvokeMethodNoLock(String name, String dllName, String entryName, MethodAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes, CallingConvention nativeCallConv,
+ CharSet nativeCharSet)
+ {
+ //Global methods must be static.
+ if ((attributes & MethodAttributes.Static) == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_GlobalFunctionHasToBeStatic"));
+ }
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+ Contract.EndContractBlock();
+
+ CheckContext(returnType);
+ CheckContext(parameterTypes);
+
+ m_moduleData.m_fHasGlobal = true;
+ return m_moduleData.m_globalTypeBuilder.DefinePInvokeMethod(name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
+ }
+
+ public void CreateGlobalFunctions()
+ {
+ lock(SyncRoot)
+ {
+ CreateGlobalFunctionsNoLock();
+ }
+ }
+
+ private void CreateGlobalFunctionsNoLock()
+ {
+ if (m_moduleData.m_fGlobalBeenCreated)
+ {
+ // cannot create globals twice
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+ m_moduleData.m_globalTypeBuilder.CreateType();
+ m_moduleData.m_fGlobalBeenCreated = true;
+ }
+
+ #endregion
+
+ #region Define Data
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public FieldBuilder DefineInitializedData(String name, byte[] data, FieldAttributes attributes)
+ {
+ // This method will define an initialized Data in .sdata.
+ // We will create a fake TypeDef to represent the data with size. This TypeDef
+ // will be the signature for the Field.
+ Contract.Ensures(Contract.Result<FieldBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineInitializedDataNoLock(name, data, attributes);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private FieldBuilder DefineInitializedDataNoLock(String name, byte[] data, FieldAttributes attributes)
+ {
+ // This method will define an initialized Data in .sdata.
+ // We will create a fake TypeDef to represent the data with size. This TypeDef
+ // will be the signature for the Field.
+ if (m_moduleData.m_fGlobalBeenCreated == true)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated"));
+ }
+ Contract.Ensures(Contract.Result<FieldBuilder>() != null);
+ Contract.EndContractBlock();
+
+ m_moduleData.m_fHasGlobal = true;
+ return m_moduleData.m_globalTypeBuilder.DefineInitializedData(name, data, attributes);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ public FieldBuilder DefineUninitializedData(String name, int size, FieldAttributes attributes)
+ {
+ Contract.Ensures(Contract.Result<FieldBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineUninitializedDataNoLock(name, size, attributes);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private FieldBuilder DefineUninitializedDataNoLock(String name, int size, FieldAttributes attributes)
+ {
+ // This method will define an uninitialized Data in .sdata.
+ // We will create a fake TypeDef to represent the data with size. This TypeDef
+ // will be the signature for the Field.
+
+ if (m_moduleData.m_fGlobalBeenCreated == true)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_GlobalsHaveBeenCreated"));
+ }
+ Contract.Ensures(Contract.Result<FieldBuilder>() != null);
+ Contract.EndContractBlock();
+
+ m_moduleData.m_fHasGlobal = true;
+ return m_moduleData.m_globalTypeBuilder.DefineUninitializedData(name, size, attributes);
+ }
+
+ #endregion
+
+ #region GetToken
+ // For a generic type definition, we should return the token for the generic type definition itself in two cases:
+ // 1. GetTypeToken
+ // 2. ldtoken (see ILGenerator)
+ // For all other occasions we should return the generic type instantiated on its formal parameters.
+ [System.Security.SecurityCritical] // auto-generated
+ internal TypeToken GetTypeTokenInternal(Type type)
+ {
+ return GetTypeTokenInternal(type, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeToken GetTypeTokenInternal(Type type, bool getGenericDefinition)
+ {
+ lock(SyncRoot)
+ {
+ return GetTypeTokenWorkerNoLock(type, getGenericDefinition);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeToken GetTypeToken(Type type)
+ {
+ return GetTypeTokenInternal(type, true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeToken GetTypeTokenWorkerNoLock(Type type, bool getGenericDefinition)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+
+ CheckContext(type);
+
+ // Return a token for the class relative to the Module. Tokens
+ // are used to indentify objects when the objects are used in IL
+ // instructions. Tokens are always relative to the Module. For example,
+ // the token value for System.String is likely to be different from
+ // Module to Module. Calling GetTypeToken will cause a reference to be
+ // added to the Module. This reference becomes a perminate part of the Module,
+ // multiple calles to this method with the same class have no additional side affects.
+ // This function is optimized to use the TypeDef token if Type is within the same module.
+ // We should also be aware of multiple dynamic modules and multiple implementation of Type!!!
+
+ if (type.IsByRef)
+ throw new ArgumentException(Environment.GetResourceString("Argument_CannotGetTypeTokenForByRef"));
+
+ if ((type.IsGenericType && (!type.IsGenericTypeDefinition || !getGenericDefinition)) ||
+ type.IsGenericParameter ||
+ type.IsArray ||
+ type.IsPointer)
+ {
+ int length;
+ byte[] sig = SignatureHelper.GetTypeSigToken(this, type).InternalGetSignature(out length);
+ return new TypeToken(GetTokenFromTypeSpec(sig, length));
+ }
+
+ Module refedModule = type.Module;
+
+ if (refedModule.Equals(this))
+ {
+ // no need to do anything additional other than defining the TypeRef Token
+ TypeBuilder typeBuilder = null;
+ GenericTypeParameterBuilder paramBuilder = null;
+
+ EnumBuilder enumBuilder = type as EnumBuilder;
+ if (enumBuilder != null)
+ typeBuilder = enumBuilder.m_typeBuilder;
+ else
+ typeBuilder = type as TypeBuilder;
+
+ if (typeBuilder != null)
+ {
+ // optimization: if the type is defined in this module,
+ // just return the token
+ //
+ return typeBuilder.TypeToken;
+ }
+ else if ((paramBuilder = type as GenericTypeParameterBuilder) != null)
+ {
+ return new TypeToken(paramBuilder.MetadataTokenInternal);
+ }
+
+ return new TypeToken(GetTypeRefNested(type, this, String.Empty));
+ }
+
+ // After this point, the referenced module is not the same as the referencing
+ // module.
+ //
+ ModuleBuilder refedModuleBuilder = refedModule as ModuleBuilder;
+
+#if !FEATURE_CORECLR
+ Contract.Assert(refedModuleBuilder != null || refedModule is RuntimeModule);
+ bool isRefedModuleTransient = refedModuleBuilder != null ?
+ refedModuleBuilder.IsTransient() :
+ ((RuntimeModule)refedModule).IsTransientInternal();
+
+ // We cannot have a non-transient module referencing to a transient module.
+ if (IsTransient() == false && isRefedModuleTransient)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadTransientModuleReference"));
+ }
+#endif // !FEATURE_CORECLR
+
+ String strRefedModuleFileName = String.Empty;
+ if (refedModule.Assembly.Equals(this.Assembly))
+ {
+ // if the referenced module is in the same assembly, the resolution
+ // scope of the type token will be a module ref, we will need
+ // the file name of the referenced module for that.
+ // if the refed module is in a different assembly, the resolution
+ // scope of the type token will be an assembly ref. We don't need
+ // the file name of the referenced module.
+ if (refedModuleBuilder == null)
+ {
+ refedModuleBuilder = this.ContainingAssemblyBuilder.GetModuleBuilder((InternalModuleBuilder)refedModule);
+ }
+ strRefedModuleFileName = refedModuleBuilder.m_moduleData.m_strFileName;
+ }
+
+ return new TypeToken(GetTypeRefNested(type, refedModule, strRefedModuleFileName));
+ }
+
+ public TypeToken GetTypeToken(String name)
+ {
+ // Return a token for the class relative to the Module.
+ // Module.GetType() verifies name
+
+ // Unfortunately, we will need to load the Type and then call GetTypeToken in
+ // order to correctly track the assembly reference information.
+
+ return GetTypeToken(InternalModule.GetType(name, false, true));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodToken GetMethodToken(MethodInfo method)
+ {
+ lock(SyncRoot)
+ {
+ return GetMethodTokenNoLock(method, true);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal MethodToken GetMethodTokenInternal(MethodInfo method)
+ {
+ lock(SyncRoot)
+ {
+ return GetMethodTokenNoLock(method, false);
+ }
+ }
+
+ // For a method on a generic type, we should return the methoddef token on the generic type definition in two cases
+ // 1. GetMethodToken
+ // 2. ldtoken (see ILGenerator)
+ // For all other occasions we should return the method on the generic type instantiated on the formal parameters.
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodToken GetMethodTokenNoLock(MethodInfo method, bool getGenericTypeDefinition)
+ {
+ // Return a MemberRef token if MethodInfo is not defined in this module. Or
+ // return the MethodDef token.
+ if (method == null)
+ throw new ArgumentNullException("method");
+ Contract.EndContractBlock();
+
+ int tr;
+ int mr = 0;
+
+ SymbolMethod symMethod = null;
+ MethodBuilder methBuilder = null;
+
+ if ( (methBuilder = method as MethodBuilder) != null )
+ {
+ int methodToken = methBuilder.MetadataTokenInternal;
+ if (method.Module.Equals(this))
+ return new MethodToken(methodToken);
+
+ if (method.DeclaringType == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule"));
+
+ // method is defined in a different module
+ tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token;
+ mr = GetMemberRef(method.DeclaringType.Module, tr, methodToken);
+ }
+ else if (method is MethodOnTypeBuilderInstantiation)
+ {
+ return new MethodToken(GetMemberRefToken(method, null));
+ }
+ else if ((symMethod = method as SymbolMethod) != null)
+ {
+ if (symMethod.GetModule() == this)
+ return symMethod.GetToken();
+
+ // form the method token
+ return symMethod.GetToken(this);
+ }
+ else
+ {
+ Type declaringType = method.DeclaringType;
+
+ // We need to get the TypeRef tokens
+ if (declaringType == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule"));
+
+ RuntimeMethodInfo rtMeth = null;
+
+ if (declaringType.IsArray == true)
+ {
+ // use reflection to build signature to work around the E_T_VAR problem in EEClass
+ ParameterInfo[] paramInfo = method.GetParameters();
+
+ Type[] tt = new Type[paramInfo.Length];
+
+ for (int i = 0; i < paramInfo.Length; i++)
+ tt[i] = paramInfo[i].ParameterType;
+
+ return GetArrayMethodToken(declaringType, method.Name, method.CallingConvention, method.ReturnType, tt);
+ }
+ else if ( (rtMeth = method as RuntimeMethodInfo) != null )
+ {
+ tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token;
+ mr = GetMemberRefOfMethodInfo(tr, rtMeth);
+ }
+ else
+ {
+ // some user derived ConstructorInfo
+ // go through the slower code path, i.e. retrieve parameters and form signature helper.
+ ParameterInfo[] parameters = method.GetParameters();
+
+ Type[] parameterTypes = new Type[parameters.Length];
+ Type[][] requiredCustomModifiers = new Type[parameterTypes.Length][];
+ Type[][] optionalCustomModifiers = new Type[parameterTypes.Length][];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ parameterTypes[i] = parameters[i].ParameterType;
+ requiredCustomModifiers[i] = parameters[i].GetRequiredCustomModifiers();
+ optionalCustomModifiers[i] = parameters[i].GetOptionalCustomModifiers();
+ }
+
+ tr = getGenericTypeDefinition ? GetTypeToken(method.DeclaringType).Token : GetTypeTokenInternal(method.DeclaringType).Token;
+
+ SignatureHelper sigHelp;
+
+ try
+ {
+ sigHelp = SignatureHelper.GetMethodSigHelper(
+ this, method.CallingConvention, method.ReturnType,
+ method.ReturnParameter.GetRequiredCustomModifiers(), method.ReturnParameter.GetOptionalCustomModifiers(),
+ parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ catch(NotImplementedException)
+ {
+ // Legacy code deriving from MethodInfo may not have implemented ReturnParameter.
+ sigHelp = SignatureHelper.GetMethodSigHelper(this, method.ReturnType, parameterTypes);
+ }
+
+ int length;
+ byte[] sigBytes = sigHelp.InternalGetSignature(out length);
+ mr = GetMemberRefFromSignature(tr, method.Name, sigBytes, length);
+ }
+ }
+
+ return new MethodToken(mr);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodToken GetConstructorToken(ConstructorInfo constructor, IEnumerable<Type> optionalParameterTypes)
+ {
+ if (constructor == null)
+ {
+ throw new ArgumentNullException("constructor");
+ }
+
+ lock (SyncRoot)
+ {
+ // useMethodDef is not applicable - constructors aren't generic
+ return new MethodToken(GetMethodTokenInternal(constructor, optionalParameterTypes, false));
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodToken GetMethodToken(MethodInfo method, IEnumerable<Type> optionalParameterTypes)
+ {
+ if (method == null)
+ {
+ throw new ArgumentNullException("method");
+ }
+
+ // useMethodDef flag only affects the result if we pass in a generic method definition.
+ // If the caller is looking for a token for an ldtoken/ldftn/ldvirtftn instruction and passes in a generic method definition info/builder,
+ // we correclty return the MethodDef/Ref token of the generic definition that can be used with ldtoken/ldftn/ldvirtftn.
+ //
+ // If the caller is looking for a token for a call/callvirt/jmp instruction and passes in a generic method definition info/builder,
+ // we also return the generic MethodDef/Ref token, which is indeed not acceptable for call/callvirt/jmp instruction.
+ // But the caller can always instantiate the info/builder and pass it in. Then we build the right MethodSpec.
+
+ lock (SyncRoot)
+ {
+ return new MethodToken(GetMethodTokenInternal(method, optionalParameterTypes, true));
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int GetMethodTokenInternal(MethodBase method, IEnumerable<Type> optionalParameterTypes, bool useMethodDef)
+ {
+ int tk = 0;
+ MethodInfo methodInfo = method as MethodInfo;
+
+ if (method.IsGenericMethod)
+ {
+ // Constructors cannot be generic.
+ Contract.Assert(methodInfo != null);
+
+ // Given M<Bar> unbind to M<S>
+ MethodInfo methodInfoUnbound = methodInfo;
+ bool isGenericMethodDef = methodInfo.IsGenericMethodDefinition;
+
+ if (!isGenericMethodDef)
+ {
+ methodInfoUnbound = methodInfo.GetGenericMethodDefinition();
+ }
+
+ if (!this.Equals(methodInfoUnbound.Module)
+ || (methodInfoUnbound.DeclaringType != null && methodInfoUnbound.DeclaringType.IsGenericType))
+ {
+ tk = GetMemberRefToken(methodInfoUnbound, null);
+ }
+ else
+ {
+ tk = GetMethodTokenInternal(methodInfoUnbound).Token;
+ }
+
+ // For Ldtoken, Ldftn, and Ldvirtftn, we should emit the method def/ref token for a generic method definition.
+ if (isGenericMethodDef && useMethodDef)
+ {
+ return tk;
+ }
+
+ // Create signature of method instantiation M<Bar>
+ int sigLength;
+ byte[] sigBytes = SignatureHelper.GetMethodSpecSigHelper(
+ this, methodInfo.GetGenericArguments()).InternalGetSignature(out sigLength);
+
+ // Create MethodSepc M<Bar> with parent G?.M<S>
+ tk = TypeBuilder.DefineMethodSpec(this.GetNativeHandle(), tk, sigBytes, sigLength);
+ }
+ else
+ {
+ if (((method.CallingConvention & CallingConventions.VarArgs) == 0) &&
+ (method.DeclaringType == null || !method.DeclaringType.IsGenericType))
+ {
+ if (methodInfo != null)
+ {
+ tk = GetMethodTokenInternal(methodInfo).Token;
+ }
+ else
+ {
+ tk = GetConstructorToken(method as ConstructorInfo).Token;
+ }
+ }
+ else
+ {
+ tk = GetMemberRefToken(method, optionalParameterTypes);
+ }
+ }
+
+ return tk;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodToken GetArrayMethodToken(Type arrayClass, String methodName, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes)
+ {
+ lock(SyncRoot)
+ {
+ return GetArrayMethodTokenNoLock(arrayClass, methodName, callingConvention, returnType, parameterTypes);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodToken GetArrayMethodTokenNoLock(Type arrayClass, String methodName, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes)
+ {
+ if (arrayClass == null)
+ throw new ArgumentNullException("arrayClass");
+
+ if (methodName == null)
+ throw new ArgumentNullException("methodName");
+
+ if (methodName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "methodName");
+
+ if (arrayClass.IsArray == false)
+ throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass"));
+ Contract.EndContractBlock();
+
+ CheckContext(returnType, arrayClass);
+ CheckContext(parameterTypes);
+
+ // Return a token for the MethodInfo for a method on an Array. This is primarily
+ // used to get the LoadElementAddress method.
+
+ int length;
+
+ SignatureHelper sigHelp = SignatureHelper.GetMethodSigHelper(
+ this, callingConvention, returnType, null, null, parameterTypes, null, null);
+
+ byte[] sigBytes = sigHelp.InternalGetSignature(out length);
+
+ TypeToken typeSpec = GetTypeTokenInternal(arrayClass);
+
+ return new MethodToken(GetArrayMethodToken(GetNativeHandle(),
+ typeSpec.Token, methodName, sigBytes, length));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MethodInfo GetArrayMethod(Type arrayClass, String methodName, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes)
+ {
+ CheckContext(returnType, arrayClass);
+ CheckContext(parameterTypes);
+
+ // GetArrayMethod is useful when you have an array of a type whose definition has not been completed and
+ // you want to access methods defined on Array. For example, you might define a type and want to define a
+ // method that takes an array of the type as a parameter. In order to access the elements of the array,
+ // you will need to call methods of the Array class.
+
+ MethodToken token = GetArrayMethodToken(arrayClass, methodName, callingConvention, returnType, parameterTypes);
+
+ return new SymbolMethod(this, token, arrayClass, methodName, callingConvention, returnType, parameterTypes);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public MethodToken GetConstructorToken(ConstructorInfo con)
+ {
+ // Return a token for the ConstructorInfo relative to the Module.
+ return InternalGetConstructorToken(con, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FieldToken GetFieldToken(FieldInfo field)
+ {
+ lock(SyncRoot)
+ {
+ return GetFieldTokenNoLock(field);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldToken GetFieldTokenNoLock(FieldInfo field)
+ {
+ if (field == null) {
+ throw new ArgumentNullException("con");
+ }
+ Contract.EndContractBlock();
+
+ int tr;
+ int mr = 0;
+
+ FieldBuilder fdBuilder = null;
+ RuntimeFieldInfo rtField = null;
+ FieldOnTypeBuilderInstantiation fOnTB = null;
+
+ if ((fdBuilder = field as FieldBuilder) != null)
+ {
+ if (field.DeclaringType != null && field.DeclaringType.IsGenericType)
+ {
+ int length;
+ byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length);
+ tr = GetTokenFromTypeSpec(sig, length);
+ mr = GetMemberRef(this, tr, fdBuilder.GetToken().Token);
+ }
+ else if (fdBuilder.Module.Equals(this))
+ {
+ // field is defined in the same module
+ return fdBuilder.GetToken();
+ }
+ else
+ {
+ // field is defined in a different module
+ if (field.DeclaringType == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule"));
+ }
+ tr = GetTypeTokenInternal(field.DeclaringType).Token;
+ mr = GetMemberRef(field.ReflectedType.Module, tr, fdBuilder.GetToken().Token);
+ }
+ }
+ else if ( (rtField = field as RuntimeFieldInfo) != null)
+ {
+ // FieldInfo is not an dynamic field
+
+ // We need to get the TypeRef tokens
+ if (field.DeclaringType == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotImportGlobalFromDifferentModule"));
+ }
+
+ if (field.DeclaringType != null && field.DeclaringType.IsGenericType)
+ {
+ int length;
+ byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length);
+ tr = GetTokenFromTypeSpec(sig, length);
+ mr = GetMemberRefOfFieldInfo(tr, field.DeclaringType.GetTypeHandleInternal(), rtField);
+ }
+ else
+ {
+ tr = GetTypeTokenInternal(field.DeclaringType).Token;
+ mr = GetMemberRefOfFieldInfo(tr, field.DeclaringType.GetTypeHandleInternal(), rtField);
+ }
+ }
+ else if ( (fOnTB = field as FieldOnTypeBuilderInstantiation) != null)
+ {
+ FieldInfo fb = fOnTB.FieldInfo;
+ int length;
+ byte[] sig = SignatureHelper.GetTypeSigToken(this, field.DeclaringType).InternalGetSignature(out length);
+ tr = GetTokenFromTypeSpec(sig, length);
+ mr = GetMemberRef(fb.ReflectedType.Module, tr, fOnTB.MetadataTokenInternal);
+ }
+ else
+ {
+ // user defined FieldInfo
+ tr = GetTypeTokenInternal(field.ReflectedType).Token;
+
+ SignatureHelper sigHelp = SignatureHelper.GetFieldSigHelper(this);
+
+ sigHelp.AddArgument(field.FieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers());
+
+ int length;
+ byte[] sigBytes = sigHelp.InternalGetSignature(out length);
+
+ mr = GetMemberRefFromSignature(tr, field.Name, sigBytes, length);
+ }
+
+ return new FieldToken(mr, field.GetType());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringToken GetStringConstant(String str)
+ {
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+ Contract.EndContractBlock();
+
+ // Returns a token representing a String constant. If the string
+ // value has already been defined, the existing token will be returned.
+ return new StringToken(GetStringConstant(GetNativeHandle(), str, str.Length));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SignatureToken GetSignatureToken(SignatureHelper sigHelper)
+ {
+ // Define signature token given a signature helper. This will define a metadata
+ // token for the signature described by SignatureHelper.
+
+ if (sigHelper == null)
+ {
+ throw new ArgumentNullException("sigHelper");
+ }
+ Contract.EndContractBlock();
+
+ int sigLength;
+ byte[] sigBytes;
+
+ // get the signature in byte form
+ sigBytes = sigHelper.InternalGetSignature(out sigLength);
+ return new SignatureToken(TypeBuilder.GetTokenFromSig(GetNativeHandle(), sigBytes, sigLength), this);
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SignatureToken GetSignatureToken(byte[] sigBytes, int sigLength)
+ {
+ if (sigBytes == null)
+ throw new ArgumentNullException("sigBytes");
+ Contract.EndContractBlock();
+
+ byte[] localSigBytes = new byte[sigBytes.Length];
+ Buffer.BlockCopy(sigBytes, 0, localSigBytes, 0, sigBytes.Length);
+
+ return new SignatureToken(TypeBuilder.GetTokenFromSig(GetNativeHandle(), localSigBytes, sigLength), this);
+ }
+
+ #endregion
+
+ #region Other
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ TypeBuilder.DefineCustomAttribute(
+ this,
+ 1, // This is hard coding the module token to 1
+ this.GetConstructorToken(con).Token,
+ binaryAttribute,
+ false, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ {
+ throw new ArgumentNullException("customBuilder");
+ }
+ Contract.EndContractBlock();
+
+ customBuilder.CreateCustomAttribute(this, 1); // This is hard coding the module token to 1
+ }
+
+ // This API returns the symbol writer being used to write debug symbols for this
+ // module (if any).
+ //
+ // WARNING: It is unlikely this API can be used correctly by applications in any
+ // reasonable way. It may be called internally from within TypeBuilder.CreateType.
+ //
+ // Specifically:
+ // 1. The underlying symbol writer (written in unmanaged code) is not necessarily well
+ // hardenned and fuzz-tested against malicious API calls. The security of partial-trust
+ // symbol writing is improved by restricting usage of the writer APIs to the well-structured
+ // uses in ModuleBuilder.
+ // 2. TypeBuilder.CreateType emits all the symbols for the type. This will effectively
+ // overwrite anything someone may have written manually about the type (specifically
+ // ISymbolWriter.OpenMethod is specced to clear anything previously written for the
+ // specified method)
+ // 3. Someone could technically update the symbols for a method after CreateType is
+ // called, but the debugger (which uses these symbols) assumes that they are only
+ // updated at TypeBuilder.CreateType time. The changes wouldn't be visible (committed
+ // to the underlying stream) until another type was baked.
+ // 4. Access to the writer is supposed to be synchronized (the underlying COM API is
+ // not thread safe, and these are only thin wrappers on top of them). Exposing this
+ // directly allows the synchronization to be violated. We know that concurrent symbol
+ // writer access can cause AVs and other problems. The writer APIs should not be callable
+ // directly by partial-trust code, but if they could this would be a security hole.
+ // Regardless, this is a reliability bug.
+ //
+ // For these reasons, we should consider making this API internal in Arrowhead
+ // (as it is in Silverlight), and consider validating that we're within a call
+ // to TypeBuilder.CreateType whenever this is used.
+ public ISymbolWriter GetSymWriter()
+ {
+ return m_iSymWriter;
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ public ISymbolDocumentWriter DefineDocument(String url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ // url cannot be null but can be an empty string
+ if (url == null)
+ throw new ArgumentNullException("url");
+ Contract.EndContractBlock();
+
+ lock(SyncRoot)
+ {
+ return DefineDocumentNoLock(url, language, languageVendor, documentType);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ private ISymbolDocumentWriter DefineDocumentNoLock(String url, Guid language, Guid languageVendor, Guid documentType)
+ {
+ if (m_iSymWriter == null)
+ {
+ // Cannot DefineDocument when it is not a debug module
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+
+ return m_iSymWriter.DefineDocument(url, language, languageVendor, documentType);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public void SetUserEntryPoint(MethodInfo entryPoint)
+ {
+ lock(SyncRoot)
+ {
+ SetUserEntryPointNoLock(entryPoint);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetUserEntryPointNoLock(MethodInfo entryPoint)
+ {
+ // Set the user entry point. Compiler may generate startup stub before calling user main.
+ // The startup stub will be the entry point. While the user "main" will be the user entry
+ // point so that debugger will not step into the compiler entry point.
+
+ if (entryPoint == null)
+ {
+ throw new ArgumentNullException("entryPoint");
+ }
+ Contract.EndContractBlock();
+
+ if (m_iSymWriter == null)
+ {
+ // Cannot set entry point when it is not a debug module
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+
+ if (entryPoint.DeclaringType != null)
+ {
+ if (!entryPoint.Module.Equals(this))
+ {
+ // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder
+ throw new InvalidOperationException(Environment.GetResourceString("Argument_NotInTheSameModuleBuilder"));
+ }
+ }
+ else
+ {
+ // unfortunately this check is missing for global function passed in as RuntimeMethodInfo.
+ // The problem is that Reflection does not
+ // allow us to get the containing module giving a global function
+ MethodBuilder mb = entryPoint as MethodBuilder;
+ if (mb != null && mb.GetModuleBuilder() != this)
+ {
+ // you cannot pass in a MethodInfo that is not contained by this ModuleBuilder
+ throw new InvalidOperationException(Environment.GetResourceString("Argument_NotInTheSameModuleBuilder"));
+ }
+ }
+
+ // get the metadata token value and create the SymbolStore's token value class
+ SymbolToken tkMethod = new SymbolToken(GetMethodTokenInternal(entryPoint).Token);
+
+ // set the UserEntryPoint
+ m_iSymWriter.SetUserEntryPoint(tkMethod);
+ }
+
+ public void SetSymCustomAttribute(String name, byte[] data)
+ {
+ lock(SyncRoot)
+ {
+ SetSymCustomAttributeNoLock(name, data);
+ }
+ }
+
+ private void SetSymCustomAttributeNoLock(String name, byte[] data)
+ {
+ if (m_iSymWriter == null)
+ {
+ // Cannot SetSymCustomAttribute when it is not a debug module
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotADebugModule"));
+ }
+
+ // This API has never worked. It seems like we might want to call m_iSymWriter.SetSymAttribute,
+ // but we don't have a metadata token to associate the attribute with. Instead
+ // MethodBuilder.SetSymCustomAttribute could be used to associate a symbol attribute with a specific method.
+ }
+
+ [Pure]
+ public bool IsTransient()
+ {
+ return InternalModule.IsTransientInternal();
+ }
+
+ #endregion
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _ModuleBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ModuleBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ModuleBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ModuleBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs
new file mode 100644
index 0000000000..2bec04abe5
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ModuleBuilderData.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.Versioning;
+
+ // This is a package private class. This class hold all of the managed
+ // data member for ModuleBuilder. Note that what ever data members added to
+ // this class cannot be accessed from the EE.
+ [Serializable]
+ internal class ModuleBuilderData
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal ModuleBuilderData(ModuleBuilder module, String strModuleName, String strFileName, int tkFile)
+ {
+ m_globalTypeBuilder = new TypeBuilder(module);
+ m_module = module;
+ m_tkFile = tkFile;
+
+ InitNames(strModuleName, strFileName);
+ }
+
+ // Initialize module and file names.
+ [System.Security.SecurityCritical] // auto-generated
+ private void InitNames(String strModuleName, String strFileName)
+ {
+ m_strModuleName = strModuleName;
+ if (strFileName == null)
+ {
+ // fake a transient module file name
+ m_strFileName = strModuleName;
+ }
+ else
+ {
+ String strExtension = Path.GetExtension(strFileName);
+ if (strExtension == null || strExtension == String.Empty)
+ {
+ // This is required by our loader. It cannot load module file that does not have file extension.
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoModuleFileExtension", strFileName));
+ }
+ m_strFileName = strFileName;
+ }
+ }
+
+ // This is a method for changing module and file name of the manifest module (created by default for
+ // each assembly).
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual void ModifyModuleName(String strModuleName)
+ {
+ Contract.Assert(m_strModuleName == AssemblyBuilder.MANIFEST_MODULE_NAME, "Changing names for non-manifest module");
+ InitNames(strModuleName, null /*strFileName*/);
+ }
+
+ internal int FileToken
+ {
+ get
+ {
+ // Before save, the scope of m_tkFile is the in-memory assembly manifest
+ // During save, the scope of m_tkFile is the on-disk assembly manifest
+ // For transient modules m_tkFile never change.
+
+ // Theoretically no one should emit anything after a dynamic assembly has
+ // been saved. So m_tkFile shouldn't used when m_isSaved is true.
+ // But that was never completely enforced: you can still emit everything after
+ // the assembly has been saved (except for public types in persistent modules).
+
+ return m_tkFile;
+ }
+
+ set
+ {
+ m_tkFile = value;
+ }
+ }
+
+ internal String m_strModuleName; // scope name (can be different from file name)
+ internal String m_strFileName;
+ internal bool m_fGlobalBeenCreated;
+ internal bool m_fHasGlobal;
+ [NonSerialized]
+ internal TypeBuilder m_globalTypeBuilder;
+ [NonSerialized]
+ internal ModuleBuilder m_module;
+
+ private int m_tkFile;
+ internal bool m_isSaved;
+ [NonSerialized]
+ internal ResWriterData m_embeddedRes;
+ internal const String MULTI_BYTE_VALUE_CLASS = "$ArrayType$";
+ internal String m_strResourceFileName;
+ internal byte[] m_resourceBytes;
+ } // class ModuleBuilderData
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/OpCodes.cs b/src/mscorlib/src/System/Reflection/Emit/OpCodes.cs
new file mode 100644
index 0000000000..345694ec80
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/OpCodes.cs
@@ -0,0 +1,2552 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+**
+**Purpose: Exposes all of the il instructions supported by the runtime.
+**
+**
+============================================================*/
+namespace System.Reflection.Emit {
+
+using System;
+using System.Security.Permissions;
+
+//
+// Internal enums for opcode values. Note that the value names are used to construct
+// publicly visible ilasm-compatible opcode names, so their exact form is important!
+//
+internal enum OpCodeValues {
+ Nop = 0x00,
+ Break = 0x01,
+ Ldarg_0 = 0x02,
+ Ldarg_1 = 0x03,
+ Ldarg_2 = 0x04,
+ Ldarg_3 = 0x05,
+ Ldloc_0 = 0x06,
+ Ldloc_1 = 0x07,
+ Ldloc_2 = 0x08,
+ Ldloc_3 = 0x09,
+ Stloc_0 = 0x0a,
+ Stloc_1 = 0x0b,
+ Stloc_2 = 0x0c,
+ Stloc_3 = 0x0d,
+ Ldarg_S = 0x0e,
+ Ldarga_S = 0x0f,
+ Starg_S = 0x10,
+ Ldloc_S = 0x11,
+ Ldloca_S = 0x12,
+ Stloc_S = 0x13,
+ Ldnull = 0x14,
+ Ldc_I4_M1 = 0x15,
+ Ldc_I4_0 = 0x16,
+ Ldc_I4_1 = 0x17,
+ Ldc_I4_2 = 0x18,
+ Ldc_I4_3 = 0x19,
+ Ldc_I4_4 = 0x1a,
+ Ldc_I4_5 = 0x1b,
+ Ldc_I4_6 = 0x1c,
+ Ldc_I4_7 = 0x1d,
+ Ldc_I4_8 = 0x1e,
+ Ldc_I4_S = 0x1f,
+ Ldc_I4 = 0x20,
+ Ldc_I8 = 0x21,
+ Ldc_R4 = 0x22,
+ Ldc_R8 = 0x23,
+ Dup = 0x25,
+ Pop = 0x26,
+ Jmp = 0x27,
+ Call = 0x28,
+ Calli = 0x29,
+ Ret = 0x2a,
+ Br_S = 0x2b,
+ Brfalse_S = 0x2c,
+ Brtrue_S = 0x2d,
+ Beq_S = 0x2e,
+ Bge_S = 0x2f,
+ Bgt_S = 0x30,
+ Ble_S = 0x31,
+ Blt_S = 0x32,
+ Bne_Un_S = 0x33,
+ Bge_Un_S = 0x34,
+ Bgt_Un_S = 0x35,
+ Ble_Un_S = 0x36,
+ Blt_Un_S = 0x37,
+ Br = 0x38,
+ Brfalse = 0x39,
+ Brtrue = 0x3a,
+ Beq = 0x3b,
+ Bge = 0x3c,
+ Bgt = 0x3d,
+ Ble = 0x3e,
+ Blt = 0x3f,
+ Bne_Un = 0x40,
+ Bge_Un = 0x41,
+ Bgt_Un = 0x42,
+ Ble_Un = 0x43,
+ Blt_Un = 0x44,
+ Switch = 0x45,
+ Ldind_I1 = 0x46,
+ Ldind_U1 = 0x47,
+ Ldind_I2 = 0x48,
+ Ldind_U2 = 0x49,
+ Ldind_I4 = 0x4a,
+ Ldind_U4 = 0x4b,
+ Ldind_I8 = 0x4c,
+ Ldind_I = 0x4d,
+ Ldind_R4 = 0x4e,
+ Ldind_R8 = 0x4f,
+ Ldind_Ref = 0x50,
+ Stind_Ref = 0x51,
+ Stind_I1 = 0x52,
+ Stind_I2 = 0x53,
+ Stind_I4 = 0x54,
+ Stind_I8 = 0x55,
+ Stind_R4 = 0x56,
+ Stind_R8 = 0x57,
+ Add = 0x58,
+ Sub = 0x59,
+ Mul = 0x5a,
+ Div = 0x5b,
+ Div_Un = 0x5c,
+ Rem = 0x5d,
+ Rem_Un = 0x5e,
+ And = 0x5f,
+ Or = 0x60,
+ Xor = 0x61,
+ Shl = 0x62,
+ Shr = 0x63,
+ Shr_Un = 0x64,
+ Neg = 0x65,
+ Not = 0x66,
+ Conv_I1 = 0x67,
+ Conv_I2 = 0x68,
+ Conv_I4 = 0x69,
+ Conv_I8 = 0x6a,
+ Conv_R4 = 0x6b,
+ Conv_R8 = 0x6c,
+ Conv_U4 = 0x6d,
+ Conv_U8 = 0x6e,
+ Callvirt = 0x6f,
+ Cpobj = 0x70,
+ Ldobj = 0x71,
+ Ldstr = 0x72,
+ Newobj = 0x73,
+ Castclass = 0x74,
+ Isinst = 0x75,
+ Conv_R_Un = 0x76,
+ Unbox = 0x79,
+ Throw = 0x7a,
+ Ldfld = 0x7b,
+ Ldflda = 0x7c,
+ Stfld = 0x7d,
+ Ldsfld = 0x7e,
+ Ldsflda = 0x7f,
+ Stsfld = 0x80,
+ Stobj = 0x81,
+ Conv_Ovf_I1_Un = 0x82,
+ Conv_Ovf_I2_Un = 0x83,
+ Conv_Ovf_I4_Un = 0x84,
+ Conv_Ovf_I8_Un = 0x85,
+ Conv_Ovf_U1_Un = 0x86,
+ Conv_Ovf_U2_Un = 0x87,
+ Conv_Ovf_U4_Un = 0x88,
+ Conv_Ovf_U8_Un = 0x89,
+ Conv_Ovf_I_Un = 0x8a,
+ Conv_Ovf_U_Un = 0x8b,
+ Box = 0x8c,
+ Newarr = 0x8d,
+ Ldlen = 0x8e,
+ Ldelema = 0x8f,
+ Ldelem_I1 = 0x90,
+ Ldelem_U1 = 0x91,
+ Ldelem_I2 = 0x92,
+ Ldelem_U2 = 0x93,
+ Ldelem_I4 = 0x94,
+ Ldelem_U4 = 0x95,
+ Ldelem_I8 = 0x96,
+ Ldelem_I = 0x97,
+ Ldelem_R4 = 0x98,
+ Ldelem_R8 = 0x99,
+ Ldelem_Ref = 0x9a,
+ Stelem_I = 0x9b,
+ Stelem_I1 = 0x9c,
+ Stelem_I2 = 0x9d,
+ Stelem_I4 = 0x9e,
+ Stelem_I8 = 0x9f,
+ Stelem_R4 = 0xa0,
+ Stelem_R8 = 0xa1,
+ Stelem_Ref = 0xa2,
+ Ldelem = 0xa3,
+ Stelem = 0xa4,
+ Unbox_Any = 0xa5,
+ Conv_Ovf_I1 = 0xb3,
+ Conv_Ovf_U1 = 0xb4,
+ Conv_Ovf_I2 = 0xb5,
+ Conv_Ovf_U2 = 0xb6,
+ Conv_Ovf_I4 = 0xb7,
+ Conv_Ovf_U4 = 0xb8,
+ Conv_Ovf_I8 = 0xb9,
+ Conv_Ovf_U8 = 0xba,
+ Refanyval = 0xc2,
+ Ckfinite = 0xc3,
+ Mkrefany = 0xc6,
+ Ldtoken = 0xd0,
+ Conv_U2 = 0xd1,
+ Conv_U1 = 0xd2,
+ Conv_I = 0xd3,
+ Conv_Ovf_I = 0xd4,
+ Conv_Ovf_U = 0xd5,
+ Add_Ovf = 0xd6,
+ Add_Ovf_Un = 0xd7,
+ Mul_Ovf = 0xd8,
+ Mul_Ovf_Un = 0xd9,
+ Sub_Ovf = 0xda,
+ Sub_Ovf_Un = 0xdb,
+ Endfinally = 0xdc,
+ Leave = 0xdd,
+ Leave_S = 0xde,
+ Stind_I = 0xdf,
+ Conv_U = 0xe0,
+ Prefix7 = 0xf8,
+ Prefix6 = 0xf9,
+ Prefix5 = 0xfa,
+ Prefix4 = 0xfb,
+ Prefix3 = 0xfc,
+ Prefix2 = 0xfd,
+ Prefix1 = 0xfe,
+ Prefixref = 0xff,
+ Arglist = 0xfe00,
+ Ceq = 0xfe01,
+ Cgt = 0xfe02,
+ Cgt_Un = 0xfe03,
+ Clt = 0xfe04,
+ Clt_Un = 0xfe05,
+ Ldftn = 0xfe06,
+ Ldvirtftn = 0xfe07,
+ Ldarg = 0xfe09,
+ Ldarga = 0xfe0a,
+ Starg = 0xfe0b,
+ Ldloc = 0xfe0c,
+ Ldloca = 0xfe0d,
+ Stloc = 0xfe0e,
+ Localloc = 0xfe0f,
+ Endfilter = 0xfe11,
+ Unaligned_ = 0xfe12,
+ Volatile_ = 0xfe13,
+ Tail_ = 0xfe14,
+ Initobj = 0xfe15,
+ Constrained_ = 0xfe16,
+ Cpblk = 0xfe17,
+ Initblk = 0xfe18,
+ Rethrow = 0xfe1a,
+ Sizeof = 0xfe1c,
+ Refanytype = 0xfe1d,
+ Readonly_ = 0xfe1e,
+
+ // If you add more opcodes here, modify OpCode.Name to handle them correctly
+};
+
+[System.Runtime.InteropServices.ComVisible(true)]
+public class OpCodes {
+
+/// <summary>
+/// <para>
+/// The IL instruction opcodes supported by the
+/// runtime. The IL Instruction Specification describes each
+/// Opcode.
+/// </para>
+/// </summary>
+/// <seealso topic='IL Instruction Set Specification'/>
+
+ private OpCodes() {
+ }
+
+ public static readonly OpCode Nop = new OpCode(OpCodeValues.Nop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Break = new OpCode(OpCodeValues.Break,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Break << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_0 = new OpCode(OpCodeValues.Ldarg_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_1 = new OpCode(OpCodeValues.Ldarg_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_2 = new OpCode(OpCodeValues.Ldarg_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_3 = new OpCode(OpCodeValues.Ldarg_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_0 = new OpCode(OpCodeValues.Ldloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_1 = new OpCode(OpCodeValues.Ldloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_2 = new OpCode(OpCodeValues.Ldloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_3 = new OpCode(OpCodeValues.Ldloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_0 = new OpCode(OpCodeValues.Stloc_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_1 = new OpCode(OpCodeValues.Stloc_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_2 = new OpCode(OpCodeValues.Stloc_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_3 = new OpCode(OpCodeValues.Stloc_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg_S = new OpCode(OpCodeValues.Ldarg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga_S = new OpCode(OpCodeValues.Ldarga_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg_S = new OpCode(OpCodeValues.Starg_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc_S = new OpCode(OpCodeValues.Ldloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca_S = new OpCode(OpCodeValues.Ldloca_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc_S = new OpCode(OpCodeValues.Stloc_S,
+ ((int)OperandType.ShortInlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldnull = new OpCode(OpCodeValues.Ldnull,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_M1 = new OpCode(OpCodeValues.Ldc_I4_M1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_0 = new OpCode(OpCodeValues.Ldc_I4_0,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_1 = new OpCode(OpCodeValues.Ldc_I4_1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_2 = new OpCode(OpCodeValues.Ldc_I4_2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_3 = new OpCode(OpCodeValues.Ldc_I4_3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_4 = new OpCode(OpCodeValues.Ldc_I4_4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_5 = new OpCode(OpCodeValues.Ldc_I4_5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_6 = new OpCode(OpCodeValues.Ldc_I4_6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_7 = new OpCode(OpCodeValues.Ldc_I4_7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_8 = new OpCode(OpCodeValues.Ldc_I4_8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4_S = new OpCode(OpCodeValues.Ldc_I4_S,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I4 = new OpCode(OpCodeValues.Ldc_I4,
+ ((int)OperandType.InlineI) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_I8 = new OpCode(OpCodeValues.Ldc_I8,
+ ((int)OperandType.InlineI8) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R4 = new OpCode(OpCodeValues.Ldc_R4,
+ ((int)OperandType.ShortInlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldc_R8 = new OpCode(OpCodeValues.Ldc_R8,
+ ((int)OperandType.InlineR) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Dup = new OpCode(OpCodeValues.Dup,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1_push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Pop = new OpCode(OpCodeValues.Pop,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Jmp = new OpCode(OpCodeValues.Jmp,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Call = new OpCode(OpCodeValues.Call,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Calli = new OpCode(OpCodeValues.Calli,
+ ((int)OperandType.InlineSig) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ret = new OpCode(OpCodeValues.Ret,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br_S = new OpCode(OpCodeValues.Br_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse_S = new OpCode(OpCodeValues.Brfalse_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue_S = new OpCode(OpCodeValues.Brtrue_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq_S = new OpCode(OpCodeValues.Beq_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_S = new OpCode(OpCodeValues.Bge_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_S = new OpCode(OpCodeValues.Bgt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_S = new OpCode(OpCodeValues.Ble_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_S = new OpCode(OpCodeValues.Blt_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un_S = new OpCode(OpCodeValues.Bne_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un_S = new OpCode(OpCodeValues.Bge_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un_S = new OpCode(OpCodeValues.Bgt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un_S = new OpCode(OpCodeValues.Ble_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un_S = new OpCode(OpCodeValues.Blt_Un_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Br = new OpCode(OpCodeValues.Br,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brfalse = new OpCode(OpCodeValues.Brfalse,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Brtrue = new OpCode(OpCodeValues.Brtrue,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Beq = new OpCode(OpCodeValues.Beq,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge = new OpCode(OpCodeValues.Bge,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt = new OpCode(OpCodeValues.Bgt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble = new OpCode(OpCodeValues.Ble,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt = new OpCode(OpCodeValues.Blt,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bne_Un = new OpCode(OpCodeValues.Bne_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bge_Un = new OpCode(OpCodeValues.Bge_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Bgt_Un = new OpCode(OpCodeValues.Bgt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ble_Un = new OpCode(OpCodeValues.Ble_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Blt_Un = new OpCode(OpCodeValues.Blt_Un,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Macro << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Switch = new OpCode(OpCodeValues.Switch,
+ ((int)OperandType.InlineSwitch) |
+ ((int)FlowControl.Cond_Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I1 = new OpCode(OpCodeValues.Ldind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U1 = new OpCode(OpCodeValues.Ldind_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I2 = new OpCode(OpCodeValues.Ldind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U2 = new OpCode(OpCodeValues.Ldind_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I4 = new OpCode(OpCodeValues.Ldind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_U4 = new OpCode(OpCodeValues.Ldind_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I8 = new OpCode(OpCodeValues.Ldind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_I = new OpCode(OpCodeValues.Ldind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R4 = new OpCode(OpCodeValues.Ldind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_R8 = new OpCode(OpCodeValues.Ldind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldind_Ref = new OpCode(OpCodeValues.Ldind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_Ref = new OpCode(OpCodeValues.Stind_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I1 = new OpCode(OpCodeValues.Stind_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I2 = new OpCode(OpCodeValues.Stind_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I4 = new OpCode(OpCodeValues.Stind_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I8 = new OpCode(OpCodeValues.Stind_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R4 = new OpCode(OpCodeValues.Stind_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_R8 = new OpCode(OpCodeValues.Stind_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add = new OpCode(OpCodeValues.Add,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub = new OpCode(OpCodeValues.Sub,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul = new OpCode(OpCodeValues.Mul,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div = new OpCode(OpCodeValues.Div,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Div_Un = new OpCode(OpCodeValues.Div_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem = new OpCode(OpCodeValues.Rem,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rem_Un = new OpCode(OpCodeValues.Rem_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode And = new OpCode(OpCodeValues.And,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Or = new OpCode(OpCodeValues.Or,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Xor = new OpCode(OpCodeValues.Xor,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shl = new OpCode(OpCodeValues.Shl,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr = new OpCode(OpCodeValues.Shr,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Shr_Un = new OpCode(OpCodeValues.Shr_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Neg = new OpCode(OpCodeValues.Neg,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Not = new OpCode(OpCodeValues.Not,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I1 = new OpCode(OpCodeValues.Conv_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I2 = new OpCode(OpCodeValues.Conv_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I4 = new OpCode(OpCodeValues.Conv_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I8 = new OpCode(OpCodeValues.Conv_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R4 = new OpCode(OpCodeValues.Conv_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R8 = new OpCode(OpCodeValues.Conv_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U4 = new OpCode(OpCodeValues.Conv_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U8 = new OpCode(OpCodeValues.Conv_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Callvirt = new OpCode(OpCodeValues.Callvirt,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Varpush << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpobj = new OpCode(OpCodeValues.Cpobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldobj = new OpCode(OpCodeValues.Ldobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldstr = new OpCode(OpCodeValues.Ldstr,
+ ((int)OperandType.InlineString) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newobj = new OpCode(OpCodeValues.Newobj,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Call << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Varpop << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static readonly OpCode Castclass = new OpCode(OpCodeValues.Castclass,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Isinst = new OpCode(OpCodeValues.Isinst,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_R_Un = new OpCode(OpCodeValues.Conv_R_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox = new OpCode(OpCodeValues.Unbox,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Throw = new OpCode(OpCodeValues.Throw,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldfld = new OpCode(OpCodeValues.Ldfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldflda = new OpCode(OpCodeValues.Ldflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stfld = new OpCode(OpCodeValues.Stfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsfld = new OpCode(OpCodeValues.Ldsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldsflda = new OpCode(OpCodeValues.Ldsflda,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stsfld = new OpCode(OpCodeValues.Stsfld,
+ ((int)OperandType.InlineField) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stobj = new OpCode(OpCodeValues.Stobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1_Un = new OpCode(OpCodeValues.Conv_Ovf_I1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2_Un = new OpCode(OpCodeValues.Conv_Ovf_I2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4_Un = new OpCode(OpCodeValues.Conv_Ovf_I4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8_Un = new OpCode(OpCodeValues.Conv_Ovf_I8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1_Un = new OpCode(OpCodeValues.Conv_Ovf_U1_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2_Un = new OpCode(OpCodeValues.Conv_Ovf_U2_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4_Un = new OpCode(OpCodeValues.Conv_Ovf_U4_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8_Un = new OpCode(OpCodeValues.Conv_Ovf_U8_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I_Un = new OpCode(OpCodeValues.Conv_Ovf_I_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U_Un = new OpCode(OpCodeValues.Conv_Ovf_U_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Box = new OpCode(OpCodeValues.Box,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Newarr = new OpCode(OpCodeValues.Newarr,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldlen = new OpCode(OpCodeValues.Ldlen,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelema = new OpCode(OpCodeValues.Ldelema,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I1 = new OpCode(OpCodeValues.Ldelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U1 = new OpCode(OpCodeValues.Ldelem_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I2 = new OpCode(OpCodeValues.Ldelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U2 = new OpCode(OpCodeValues.Ldelem_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I4 = new OpCode(OpCodeValues.Ldelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_U4 = new OpCode(OpCodeValues.Ldelem_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I8 = new OpCode(OpCodeValues.Ldelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_I = new OpCode(OpCodeValues.Ldelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R4 = new OpCode(OpCodeValues.Ldelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr4 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_R8 = new OpCode(OpCodeValues.Ldelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem_Ref = new OpCode(OpCodeValues.Ldelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushref << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I = new OpCode(OpCodeValues.Stelem_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I1 = new OpCode(OpCodeValues.Stelem_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I2 = new OpCode(OpCodeValues.Stelem_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I4 = new OpCode(OpCodeValues.Stelem_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_I8 = new OpCode(OpCodeValues.Stelem_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popi8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R4 = new OpCode(OpCodeValues.Stelem_R4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr4 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_R8 = new OpCode(OpCodeValues.Stelem_R8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popr8 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem_Ref = new OpCode(OpCodeValues.Stelem_Ref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldelem = new OpCode(OpCodeValues.Ldelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stelem = new OpCode(OpCodeValues.Stelem,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref_popi_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unbox_Any = new OpCode(OpCodeValues.Unbox_Any,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I1 = new OpCode(OpCodeValues.Conv_Ovf_I1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U1 = new OpCode(OpCodeValues.Conv_Ovf_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I2 = new OpCode(OpCodeValues.Conv_Ovf_I2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U2 = new OpCode(OpCodeValues.Conv_Ovf_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I4 = new OpCode(OpCodeValues.Conv_Ovf_I4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U4 = new OpCode(OpCodeValues.Conv_Ovf_U4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I8 = new OpCode(OpCodeValues.Conv_Ovf_I8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U8 = new OpCode(OpCodeValues.Conv_Ovf_U8,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanyval = new OpCode(OpCodeValues.Refanyval,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ckfinite = new OpCode(OpCodeValues.Ckfinite,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushr8 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mkrefany = new OpCode(OpCodeValues.Mkrefany,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldtoken = new OpCode(OpCodeValues.Ldtoken,
+ ((int)OperandType.InlineTok) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U2 = new OpCode(OpCodeValues.Conv_U2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U1 = new OpCode(OpCodeValues.Conv_U1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_I = new OpCode(OpCodeValues.Conv_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_I = new OpCode(OpCodeValues.Conv_Ovf_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_Ovf_U = new OpCode(OpCodeValues.Conv_Ovf_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf = new OpCode(OpCodeValues.Add_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Add_Ovf_Un = new OpCode(OpCodeValues.Add_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf = new OpCode(OpCodeValues.Mul_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Mul_Ovf_Un = new OpCode(OpCodeValues.Mul_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf = new OpCode(OpCodeValues.Sub_Ovf,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sub_Ovf_Un = new OpCode(OpCodeValues.Sub_Ovf_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfinally = new OpCode(OpCodeValues.Endfinally,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave = new OpCode(OpCodeValues.Leave,
+ ((int)OperandType.InlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Leave_S = new OpCode(OpCodeValues.Leave_S,
+ ((int)OperandType.ShortInlineBrTarget) |
+ ((int)FlowControl.Branch << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stind_I = new OpCode(OpCodeValues.Stind_I,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (-2 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Conv_U = new OpCode(OpCodeValues.Conv_U,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix7 = new OpCode(OpCodeValues.Prefix7,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix6 = new OpCode(OpCodeValues.Prefix6,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix5 = new OpCode(OpCodeValues.Prefix5,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix4 = new OpCode(OpCodeValues.Prefix4,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix3 = new OpCode(OpCodeValues.Prefix3,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix2 = new OpCode(OpCodeValues.Prefix2,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefix1 = new OpCode(OpCodeValues.Prefix1,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Prefixref = new OpCode(OpCodeValues.Prefixref,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Nternal << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (1 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Arglist = new OpCode(OpCodeValues.Arglist,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ceq = new OpCode(OpCodeValues.Ceq,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt = new OpCode(OpCodeValues.Cgt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cgt_Un = new OpCode(OpCodeValues.Cgt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt = new OpCode(OpCodeValues.Clt,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Clt_Un = new OpCode(OpCodeValues.Clt_Un,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1_pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldftn = new OpCode(OpCodeValues.Ldftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldvirtftn = new OpCode(OpCodeValues.Ldvirtftn,
+ ((int)OperandType.InlineMethod) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popref << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarg = new OpCode(OpCodeValues.Ldarg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldarga = new OpCode(OpCodeValues.Ldarga,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Starg = new OpCode(OpCodeValues.Starg,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloc = new OpCode(OpCodeValues.Ldloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push1 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Ldloca = new OpCode(OpCodeValues.Ldloca,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Stloc = new OpCode(OpCodeValues.Stloc,
+ ((int)OperandType.InlineVar) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Localloc = new OpCode(OpCodeValues.Localloc,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Endfilter = new OpCode(OpCodeValues.Endfilter,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Return << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Unaligned = new OpCode(OpCodeValues.Unaligned_,
+ ((int)OperandType.ShortInlineI) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Volatile = new OpCode(OpCodeValues.Volatile_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Tailcall = new OpCode(OpCodeValues.Tail_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initobj = new OpCode(OpCodeValues.Initobj,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Constrained = new OpCode(OpCodeValues.Constrained_,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Cpblk = new OpCode(OpCodeValues.Cpblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Initblk = new OpCode(OpCodeValues.Initblk,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Popi_popi_popi << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (-3 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Rethrow = new OpCode(OpCodeValues.Rethrow,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Throw << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Objmodel << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ OpCode.EndsUncondJmpBlkFlag |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Sizeof = new OpCode(OpCodeValues.Sizeof,
+ ((int)OperandType.InlineType) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (1 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Refanytype = new OpCode(OpCodeValues.Refanytype,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Next << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Primitive << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop1 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Pushi << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+ public static readonly OpCode Readonly = new OpCode(OpCodeValues.Readonly_,
+ ((int)OperandType.InlineNone) |
+ ((int)FlowControl.Meta << OpCode.FlowControlShift) |
+ ((int)OpCodeType.Prefix << OpCode.OpCodeTypeShift) |
+ ((int)StackBehaviour.Pop0 << OpCode.StackBehaviourPopShift) |
+ ((int)StackBehaviour.Push0 << OpCode.StackBehaviourPushShift) |
+ (2 << OpCode.SizeShift) |
+ (0 << OpCode.StackChangeShift)
+ );
+
+
+ public static bool TakesSingleByteArgument(OpCode inst)
+ {
+ switch (inst.OperandType)
+ {
+ case OperandType.ShortInlineBrTarget :
+ case OperandType.ShortInlineI :
+ case OperandType.ShortInlineVar :
+ return true;
+ };
+ return false;
+ }
+}
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/Opcode.cs b/src/mscorlib/src/System/Reflection/Emit/Opcode.cs
new file mode 100644
index 0000000000..cae4f0564e
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/Opcode.cs
@@ -0,0 +1,312 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit {
+using System;
+using System.Threading;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+public struct OpCode
+{
+ //
+ // Use packed bitfield for flags to avoid code bloat
+ //
+
+ internal const int OperandTypeMask = 0x1F; // 000000000000000000000000000XXXXX
+
+ internal const int FlowControlShift = 5; // 00000000000000000000000XXXX00000
+ internal const int FlowControlMask = 0x0F;
+
+ internal const int OpCodeTypeShift = 9; // 00000000000000000000XXX000000000
+ internal const int OpCodeTypeMask = 0x07;
+
+ internal const int StackBehaviourPopShift = 12; // 000000000000000XXXXX000000000000
+ internal const int StackBehaviourPushShift = 17; // 0000000000XXXXX00000000000000000
+ internal const int StackBehaviourMask = 0x1F;
+
+ internal const int SizeShift = 22; // 00000000XX0000000000000000000000
+ internal const int SizeMask = 0x03;
+
+ internal const int EndsUncondJmpBlkFlag = 0x01000000; // 0000000X000000000000000000000000
+
+ // unused // 0000XXX0000000000000000000000000
+
+ internal const int StackChangeShift = 28; // XXXX0000000000000000000000000000
+
+#if FEATURE_CORECLR
+ private OpCodeValues m_value;
+ private int m_flags;
+
+ internal OpCode(OpCodeValues value, int flags)
+ {
+ m_value = value;
+ m_flags = flags;
+ }
+
+ internal bool EndsUncondJmpBlk()
+ {
+ return (m_flags & EndsUncondJmpBlkFlag) != 0;
+ }
+
+ internal int StackChange()
+ {
+ return (m_flags >> StackChangeShift);
+ }
+
+ public OperandType OperandType
+ {
+ get
+ {
+ return (OperandType)(m_flags & OperandTypeMask);
+ }
+ }
+
+ public FlowControl FlowControl
+ {
+ get
+ {
+ return (FlowControl)((m_flags >> FlowControlShift) & FlowControlMask);
+ }
+ }
+
+ public OpCodeType OpCodeType
+ {
+ get
+ {
+ return (OpCodeType)((m_flags >> OpCodeTypeShift) & OpCodeTypeMask);
+ }
+ }
+
+
+ public StackBehaviour StackBehaviourPop
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPopShift) & StackBehaviourMask);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPush
+ {
+ get
+ {
+ return (StackBehaviour)((m_flags >> StackBehaviourPushShift) & StackBehaviourMask);
+ }
+ }
+
+ public int Size
+ {
+ get
+ {
+ return (m_flags >> SizeShift) & SizeMask;
+ }
+ }
+
+ public short Value
+ {
+ get
+ {
+ return (short)m_value;
+ }
+ }
+#else // FEATURE_CORECLR
+ //
+ // The exact layout is part of the legacy COM mscorlib surface, so it is
+ // pretty much set in stone for desktop CLR. Ideally, we would use the packed
+ // bit field like for CoreCLR, but that would be a breaking change.
+ //
+
+// disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ private String m_stringname; // not used - computed lazily
+#pragma warning restore 0414
+ private StackBehaviour m_pop;
+ private StackBehaviour m_push;
+ private OperandType m_operand;
+ private OpCodeType m_type;
+ private int m_size;
+ private byte m_s1;
+ private byte m_s2;
+ private FlowControl m_ctrl;
+
+ // Specifies whether the current instructions causes the control flow to
+ // change unconditionally.
+ private bool m_endsUncondJmpBlk;
+
+
+ // Specifies the stack change that the current instruction causes not
+ // taking into account the operand dependant stack changes.
+ private int m_stackChange;
+
+
+ internal OpCode(OpCodeValues value, int flags)
+ {
+ m_stringname = null; // computed lazily
+ m_pop = (StackBehaviour)((flags >> StackBehaviourPopShift) & StackBehaviourMask);
+ m_push = (StackBehaviour)((flags >> StackBehaviourPushShift) & StackBehaviourMask);
+ m_operand = (OperandType)(flags & OperandTypeMask);
+ m_type = (OpCodeType)((flags >> OpCodeTypeShift) & OpCodeTypeMask);
+ m_size = (flags >> SizeShift) & SizeMask;
+ m_s1 = (byte)((int)value >> 8);
+ m_s2 = (byte)(int)value;
+ m_ctrl = (FlowControl)((flags >> FlowControlShift) & FlowControlMask);
+ m_endsUncondJmpBlk = (flags & EndsUncondJmpBlkFlag) != 0;
+ m_stackChange = (flags >> StackChangeShift);
+ }
+
+ internal bool EndsUncondJmpBlk()
+ {
+ return m_endsUncondJmpBlk;
+ }
+
+ internal int StackChange()
+ {
+ return m_stackChange;
+ }
+
+ public OperandType OperandType
+ {
+ get
+ {
+ return (m_operand);
+ }
+ }
+
+ public FlowControl FlowControl
+ {
+ get
+ {
+ return (m_ctrl);
+ }
+ }
+
+ public OpCodeType OpCodeType
+ {
+ get
+ {
+ return (m_type);
+ }
+ }
+
+
+ public StackBehaviour StackBehaviourPop
+ {
+ get
+ {
+ return (m_pop);
+ }
+ }
+
+ public StackBehaviour StackBehaviourPush
+ {
+ get
+ {
+ return (m_push);
+ }
+ }
+
+ public int Size
+ {
+ get
+ {
+ return (m_size);
+ }
+ }
+
+ public short Value
+ {
+ get
+ {
+ if (m_size == 2)
+ return (short)(m_s1 << 8 | m_s2);
+ return (short)m_s2;
+ }
+ }
+#endif // FEATURE_CORECLR
+
+
+ private static volatile string[] g_nameCache;
+
+ public String Name
+ {
+ get
+ {
+ if (Size == 0)
+ return null;
+
+ // Create and cache the opcode names lazily. They should be rarely used (only for logging, etc.)
+ // Note that we do not any locks here because of we always get the same names. The last one wins.
+ string[] nameCache = g_nameCache;
+ if (nameCache == null) {
+ nameCache = new String[0x11f];
+ g_nameCache = nameCache;
+ }
+
+ OpCodeValues opCodeValue = (OpCodeValues)(ushort)Value;
+
+ int idx = (int)opCodeValue;
+ if (idx > 0xFF) {
+ if (idx >= 0xfe00 && idx <= 0xfe1e) {
+ // Transform two byte opcode value to lower range that's suitable
+ // for array index
+ idx = 0x100 + (idx - 0xfe00);
+ }
+ else {
+ // Unknown opcode
+ return null;
+ }
+ }
+
+ String name = Volatile.Read(ref nameCache[idx]);
+ if (name != null)
+ return name;
+
+ // Create ilasm style name from the enum value name.
+ name = Enum.GetName(typeof(OpCodeValues), opCodeValue).ToLowerInvariant().Replace("_", ".");
+ Volatile.Write(ref nameCache[idx], name);
+ return name;
+ }
+ }
+
+ [Pure]
+ public override bool Equals(Object obj)
+ {
+ if (obj is OpCode)
+ return Equals((OpCode)obj);
+ else
+ return false;
+ }
+
+ [Pure]
+ public bool Equals(OpCode obj)
+ {
+ return obj.Value == Value;
+ }
+
+ [Pure]
+ public static bool operator ==(OpCode a, OpCode b)
+ {
+ return a.Equals(b);
+ }
+
+ [Pure]
+ public static bool operator !=(OpCode a, OpCode b)
+ {
+ return !(a == b);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value;
+ }
+
+ public override String ToString()
+ {
+ return Name;
+ }
+}
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs b/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs
new file mode 100644
index 0000000000..5ef5f80b15
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/OpcodeType.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**Purpose: Exposes OpCodeType Attribute of IL .
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See opcodegen.pl for more information.**
+============================================================*/
+namespace System.Reflection.Emit {
+
+using System;
+
+[Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+public enum OpCodeType
+{
+
+#if !FEATURE_CORECLR
+ /// <internalonly/>
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ Annotation = 0,
+#endif
+ Macro = 1,
+ Nternal = 2,
+ Objmodel = 3,
+ Prefix = 4,
+ Primitive = 5,
+}
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/OperandType.cs b/src/mscorlib/src/System/Reflection/Emit/OperandType.cs
new file mode 100644
index 0000000000..fdde19a73e
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/OperandType.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**Purpose: Exposes OperandType Attribute of IL .
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See opcodegen.pl for more information.**
+============================================================*/
+namespace System.Reflection.Emit {
+
+using System;
+
+[Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+public enum OperandType
+{
+
+ InlineBrTarget = 0,
+ InlineField = 1,
+ InlineI = 2,
+ InlineI8 = 3,
+ InlineMethod = 4,
+ InlineNone = 5,
+#if !FEATURE_CORECLR
+ /// <internalonly/>
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ InlinePhi = 6,
+#endif
+ InlineR = 7,
+ InlineSig = 9,
+ InlineString = 10,
+ InlineSwitch = 11,
+ InlineTok = 12,
+ InlineType = 13,
+ InlineVar = 14,
+ ShortInlineBrTarget = 15,
+ ShortInlineI = 16,
+ ShortInlineR = 17,
+ ShortInlineVar = 18,
+}
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/PEFileKinds.cs b/src/mscorlib/src/System/Reflection/Emit/PEFileKinds.cs
new file mode 100644
index 0000000000..d9c9c0327c
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/PEFileKinds.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit {
+
+ using System;
+ // This Enum matchs the CorFieldAttr defined in CorHdr.h
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum PEFileKinds
+ {
+ Dll = 0x0001,
+ ConsoleApplication = 0x0002,
+ WindowApplication = 0x0003,
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs
new file mode 100644
index 0000000000..693e2d3660
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ParameterBuilder.cs
@@ -0,0 +1,172 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** ParameterBuilder is used to create/associate parameter information
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ParameterBuilder))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class ParameterBuilder : _ParameterBuilder
+ {
+ // set ParamMarshal
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public virtual void SetMarshal(UnmanagedMarshal unmanagedMarshal)
+ {
+ if (unmanagedMarshal == null)
+ {
+ throw new ArgumentNullException("unmanagedMarshal");
+ }
+ Contract.EndContractBlock();
+
+ byte [] ubMarshal = unmanagedMarshal.InternalGetBytes();
+ TypeBuilder.SetFieldMarshal(
+ m_methodBuilder.GetModuleBuilder().GetNativeHandle(),
+ m_pdToken.Token,
+ ubMarshal,
+ ubMarshal.Length);
+ }
+
+ // Set the default value of the parameter
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual void SetConstant(Object defaultValue)
+ {
+ TypeBuilder.SetConstantValue(
+ m_methodBuilder.GetModuleBuilder(),
+ m_pdToken.Token,
+ m_iPosition == 0 ? m_methodBuilder.ReturnType : m_methodBuilder.m_parameterTypes[m_iPosition - 1],
+ defaultValue);
+ }
+
+ // Use this function if client decides to form the custom attribute blob themselves
+
+ [System.Security.SecuritySafeCritical]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ TypeBuilder.DefineCustomAttribute(
+ m_methodBuilder.GetModuleBuilder(),
+ m_pdToken.Token,
+ ((ModuleBuilder )m_methodBuilder.GetModule()).GetConstructorToken(con).Token,
+ binaryAttribute,
+ false, false);
+ }
+
+ // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ {
+ throw new ArgumentNullException("customBuilder");
+ }
+ Contract.EndContractBlock();
+ customBuilder.CreateCustomAttribute((ModuleBuilder) (m_methodBuilder .GetModule()), m_pdToken.Token);
+ }
+
+ //*******************************
+ // Make a private constructor so these cannot be constructed externally.
+ //*******************************
+ private ParameterBuilder() {}
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal ParameterBuilder(
+ MethodBuilder methodBuilder,
+ int sequence,
+ ParameterAttributes attributes,
+ String strParamName) // can be NULL string
+ {
+ m_iPosition = sequence;
+ m_strParamName = strParamName;
+ m_methodBuilder = methodBuilder;
+ m_strParamName = strParamName;
+ m_attributes = attributes;
+ m_pdToken = new ParameterToken( TypeBuilder.SetParamInfo(
+ m_methodBuilder.GetModuleBuilder().GetNativeHandle(),
+ m_methodBuilder.GetToken().Token,
+ sequence,
+ attributes,
+ strParamName));
+ }
+
+ public virtual ParameterToken GetToken()
+ {
+ return m_pdToken;
+ }
+
+#if !FEATURE_CORECLR
+ void _ParameterBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ internal int MetadataTokenInternal { get { return m_pdToken.Token; } }
+
+ public virtual String Name {
+ get {return m_strParamName;}
+ }
+
+ public virtual int Position {
+ get {return m_iPosition;}
+ }
+
+ public virtual int Attributes {
+ get {return (int) m_attributes;}
+ }
+
+ public bool IsIn {
+ get {return ((m_attributes & ParameterAttributes.In) != 0);}
+ }
+ public bool IsOut {
+ get {return ((m_attributes & ParameterAttributes.Out) != 0);}
+ }
+ public bool IsOptional {
+ get {return ((m_attributes & ParameterAttributes.Optional) != 0);}
+ }
+
+ private String m_strParamName;
+ private int m_iPosition;
+ private ParameterAttributes m_attributes;
+ private MethodBuilder m_methodBuilder;
+ private ParameterToken m_pdToken;
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/ParameterToken.cs b/src/mscorlib/src/System/Reflection/Emit/ParameterToken.cs
new file mode 100644
index 0000000000..d65368bf0d
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/ParameterToken.cs
@@ -0,0 +1,73 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: metadata tokens for a parameter
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ // The ParameterToken class is an opaque representation of the Token returned
+ // by the Metadata to represent the parameter.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct ParameterToken {
+
+ public static readonly ParameterToken Empty = new ParameterToken();
+ internal int m_tkParameter;
+
+#if false
+ public ParameterToken() {
+ m_tkParameter=0;
+ }
+#endif
+
+ internal ParameterToken(int tkParam) {
+ m_tkParameter = tkParam;
+ }
+
+ public int Token {
+ get { return m_tkParameter; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_tkParameter;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is ParameterToken)
+ return Equals((ParameterToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(ParameterToken obj)
+ {
+ return obj.m_tkParameter == m_tkParameter;
+ }
+
+ public static bool operator ==(ParameterToken a, ParameterToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(ParameterToken a, ParameterToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs
new file mode 100644
index 0000000000..5ac69f205f
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/PropertyBuilder.cs
@@ -0,0 +1,306 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Propertybuilder is for client to define properties for a class
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ //
+ // A PropertyBuilder is always associated with a TypeBuilder. The TypeBuilder.DefineProperty
+ // method will return a new PropertyBuilder to a client.
+ //
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_PropertyBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class PropertyBuilder : PropertyInfo, _PropertyBuilder
+ {
+
+ // Make a private constructor so these cannot be constructed externally.
+ private PropertyBuilder() {}
+
+ // Constructs a PropertyBuilder.
+ //
+ internal PropertyBuilder(
+ ModuleBuilder mod, // the module containing this PropertyBuilder
+ String name, // property name
+ SignatureHelper sig, // property signature descriptor info
+ PropertyAttributes attr, // property attribute such as DefaultProperty, Bindable, DisplayBind, etc
+ Type returnType, // return type of the property.
+ PropertyToken prToken, // the metadata token for this property
+ TypeBuilder containingType) // the containing type
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ if (name[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name");
+ Contract.EndContractBlock();
+
+ m_name = name;
+ m_moduleBuilder = mod;
+ m_signature = sig;
+ m_attributes = attr;
+ m_returnType = returnType;
+ m_prToken = prToken;
+ m_tkProperty = prToken.Token;
+ m_containingType = containingType;
+ }
+
+ //************************************************
+ // Set the default value of the Property
+ //************************************************
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetConstant(Object defaultValue)
+ {
+ m_containingType.ThrowIfCreated();
+
+ TypeBuilder.SetConstantValue(
+ m_moduleBuilder,
+ m_prToken.Token,
+ m_returnType,
+ defaultValue);
+ }
+
+
+ // Return the Token for this property within the TypeBuilder that the
+ // property is defined within.
+ public PropertyToken PropertyToken
+ {
+ get {return m_prToken;}
+ }
+
+ internal int MetadataTokenInternal
+ {
+ get
+ {
+ return m_tkProperty;
+ }
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ return m_containingType.Module;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetMethodSemantics(MethodBuilder mdBuilder, MethodSemanticsAttributes semantics)
+ {
+ if (mdBuilder == null)
+ {
+ throw new ArgumentNullException("mdBuilder");
+ }
+
+ m_containingType.ThrowIfCreated();
+ TypeBuilder.DefineMethodSemantics(
+ m_moduleBuilder.GetNativeHandle(),
+ m_prToken.Token,
+ semantics,
+ mdBuilder.GetToken().Token);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetGetMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Getter);
+ m_getMethod = mdBuilder;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetSetMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Setter);
+ m_setMethod = mdBuilder;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddOtherMethod(MethodBuilder mdBuilder)
+ {
+ SetMethodSemantics(mdBuilder, MethodSemanticsAttributes.Other);
+ }
+
+ // Use this function if client decides to form the custom attribute blob themselves
+
+#if FEATURE_CORECLR
+[System.Security.SecurityCritical] // auto-generated
+#else
+[System.Security.SecuritySafeCritical]
+#endif
+[System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+
+ m_containingType.ThrowIfCreated();
+ TypeBuilder.DefineCustomAttribute(
+ m_moduleBuilder,
+ m_prToken.Token,
+ m_moduleBuilder.GetConstructorToken(con).Token,
+ binaryAttribute,
+ false, false);
+ }
+
+ // Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ {
+ throw new ArgumentNullException("customBuilder");
+ }
+ m_containingType.ThrowIfCreated();
+ customBuilder.CreateCustomAttribute(m_moduleBuilder, m_prToken.Token);
+ }
+
+ // Not supported functions in dynamic module.
+ public override Object GetValue(Object obj,Object[] index)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override Object GetValue(Object obj,BindingFlags invokeAttr,Binder binder,Object[] index,CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override void SetValue(Object obj,Object value,Object[] index)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override void SetValue(Object obj,Object value,BindingFlags invokeAttr,Binder binder,Object[] index,CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ if (nonPublic || m_getMethod == null)
+ return m_getMethod;
+ // now check to see if m_getMethod is public
+ if ((m_getMethod.Attributes & MethodAttributes.Public) == MethodAttributes.Public)
+ return m_getMethod;
+ return null;
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ if (nonPublic || m_setMethod == null)
+ return m_setMethod;
+ // now check to see if m_setMethod is public
+ if ((m_setMethod.Attributes & MethodAttributes.Public) == MethodAttributes.Public)
+ return m_setMethod;
+ return null;
+ }
+
+ public override ParameterInfo[] GetIndexParameters()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override Type PropertyType {
+ get { return m_returnType; }
+ }
+
+ public override PropertyAttributes Attributes {
+ get { return m_attributes;}
+ }
+
+ public override bool CanRead {
+ get { if (m_getMethod != null) return true; else return false; } }
+
+ public override bool CanWrite {
+ get { if (m_setMethod != null) return true; else return false; }
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+#if !FEATURE_CORECLR
+ void _PropertyBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _PropertyBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _PropertyBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _PropertyBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ public override String Name {
+ get { return m_name; }
+ }
+
+ public override Type DeclaringType {
+ get { return m_containingType; }
+ }
+
+ public override Type ReflectedType {
+ get { return m_containingType; }
+ }
+
+ // These are package private so that TypeBuilder can access them.
+ private String m_name; // The name of the property
+ private PropertyToken m_prToken; // The token of this property
+ private int m_tkProperty;
+ private ModuleBuilder m_moduleBuilder;
+ private SignatureHelper m_signature;
+ private PropertyAttributes m_attributes; // property's attribute flags
+ private Type m_returnType; // property's return type
+ private MethodInfo m_getMethod;
+ private MethodInfo m_setMethod;
+ private TypeBuilder m_containingType;
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/PropertyToken.cs b/src/mscorlib/src/System/Reflection/Emit/PropertyToken.cs
new file mode 100644
index 0000000000..d70cad057a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/PropertyToken.cs
@@ -0,0 +1,70 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Propertybuilder is for client to define properties for a class
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct PropertyToken {
+
+ public static readonly PropertyToken Empty = new PropertyToken();
+
+ internal int m_property;
+
+ internal PropertyToken(int str) {
+ m_property=str;
+ }
+
+ public int Token {
+ get { return m_property; }
+ }
+
+ // Satisfy value class requirements
+ public override int GetHashCode()
+ {
+ return m_property;
+ }
+
+ // Satisfy value class requirements
+ public override bool Equals(Object obj)
+ {
+ if (obj is PropertyToken)
+ return Equals((PropertyToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(PropertyToken obj)
+ {
+ return obj.m_property == m_property;
+ }
+
+ public static bool operator ==(PropertyToken a, PropertyToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(PropertyToken a, PropertyToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs
new file mode 100644
index 0000000000..35e8cc7e31
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/SignatureHelper.cs
@@ -0,0 +1,1019 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_SignatureHelper))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SignatureHelper : _SignatureHelper
+ {
+ #region Consts Fields
+ private const int NO_SIZE_IN_SIG = -1;
+ #endregion
+
+ #region Static Members
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static SignatureHelper GetMethodSigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ return GetMethodSigHelper(mod, CallingConventions.Standard, returnType, null, null, parameterTypes, null, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType, int cGenericParam)
+ {
+ return GetMethodSigHelper(mod, callingConvention, cGenericParam, returnType, null, null, null, null, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static SignatureHelper GetMethodSigHelper(Module mod, CallingConventions callingConvention, Type returnType)
+ {
+ return GetMethodSigHelper(mod, callingConvention, returnType, null, null, null, null, null);
+ }
+
+ internal static SignatureHelper GetMethodSpecSigHelper(Module scope, Type[] inst)
+ {
+ SignatureHelper sigHelp = new SignatureHelper(scope, MdSigCallingConvention.GenericInst);
+ sigHelp.AddData(inst.Length);
+ foreach(Type t in inst)
+ sigHelp.AddArgument(t);
+ return sigHelp;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SignatureHelper GetMethodSigHelper(
+ Module scope, CallingConventions callingConvention,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ return GetMethodSigHelper(scope, callingConvention, 0, returnType, requiredReturnTypeCustomModifiers,
+ optionalReturnTypeCustomModifiers, parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SignatureHelper GetMethodSigHelper(
+ Module scope, CallingConventions callingConvention, int cGenericParam,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ SignatureHelper sigHelp;
+ MdSigCallingConvention intCall;
+
+ if (returnType == null)
+ {
+ returnType = typeof(void);
+ }
+
+ intCall = MdSigCallingConvention.Default;
+
+ if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
+ intCall = MdSigCallingConvention.Vararg;
+
+ if (cGenericParam > 0)
+ {
+ intCall |= MdSigCallingConvention.Generic;
+ }
+
+ if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
+ intCall |= MdSigCallingConvention.HasThis;
+
+ sigHelp = new SignatureHelper(scope, intCall, cGenericParam, returnType,
+ requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
+ sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+
+ return sigHelp;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static SignatureHelper GetMethodSigHelper(Module mod, CallingConvention unmanagedCallConv, Type returnType)
+ {
+ SignatureHelper sigHelp;
+ MdSigCallingConvention intCall;
+
+ if (returnType == null)
+ returnType = typeof(void);
+
+ if (unmanagedCallConv == CallingConvention.Cdecl)
+ {
+ intCall = MdSigCallingConvention.C;
+ }
+ else if (unmanagedCallConv == CallingConvention.StdCall || unmanagedCallConv == CallingConvention.Winapi)
+ {
+ intCall = MdSigCallingConvention.StdCall;
+ }
+ else if (unmanagedCallConv == CallingConvention.ThisCall)
+ {
+ intCall = MdSigCallingConvention.ThisCall;
+ }
+ else if (unmanagedCallConv == CallingConvention.FastCall)
+ {
+ intCall = MdSigCallingConvention.FastCall;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_UnknownUnmanagedCallConv"), "unmanagedCallConv");
+ }
+
+ sigHelp = new SignatureHelper(mod, intCall, returnType, null, null);
+
+ return sigHelp;
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper()
+ {
+ return GetLocalVarSigHelper(null);
+ }
+
+ public static SignatureHelper GetMethodSigHelper(CallingConventions callingConvention, Type returnType)
+ {
+ return GetMethodSigHelper(null, callingConvention, returnType);
+ }
+
+ public static SignatureHelper GetMethodSigHelper(CallingConvention unmanagedCallingConvention, Type returnType)
+ {
+ return GetMethodSigHelper(null, unmanagedCallingConvention, returnType);
+ }
+
+ public static SignatureHelper GetLocalVarSigHelper(Module mod)
+ {
+ return new SignatureHelper(mod, MdSigCallingConvention.LocalSig);
+ }
+
+ public static SignatureHelper GetFieldSigHelper(Module mod)
+ {
+ return new SignatureHelper(mod, MdSigCallingConvention.Field);
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod, Type returnType, Type[] parameterTypes)
+ {
+ return GetPropertySigHelper(mod, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public static SignatureHelper GetPropertySigHelper(Module mod,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ return GetPropertySigHelper(mod, (CallingConventions)0, returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
+ parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static SignatureHelper GetPropertySigHelper(Module mod, CallingConventions callingConvention,
+ Type returnType, Type[] requiredReturnTypeCustomModifiers, Type[] optionalReturnTypeCustomModifiers,
+ Type[] parameterTypes, Type[][] requiredParameterTypeCustomModifiers, Type[][] optionalParameterTypeCustomModifiers)
+ {
+ SignatureHelper sigHelp;
+
+ if (returnType == null)
+ {
+ returnType = typeof(void);
+ }
+
+ MdSigCallingConvention intCall = MdSigCallingConvention.Property;
+
+ if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
+ intCall |= MdSigCallingConvention.HasThis;
+
+ sigHelp = new SignatureHelper(mod, intCall,
+ returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers);
+ sigHelp.AddArguments(parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
+
+ return sigHelp;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static SignatureHelper GetTypeSigToken(Module mod, Type type)
+ {
+ if (mod == null)
+ throw new ArgumentNullException("module");
+
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ return new SignatureHelper(mod, type);
+ }
+ #endregion
+
+ #region Private Data Members
+ private byte[] m_signature;
+ private int m_currSig; // index into m_signature buffer for next available byte
+ private int m_sizeLoc; // index into m_signature buffer to put m_argCount (will be NO_SIZE_IN_SIG if no arg count is needed)
+ private ModuleBuilder m_module;
+ private bool m_sigDone;
+ private int m_argCount; // tracking number of arguments in the signature
+ #endregion
+
+ #region Constructor
+ private SignatureHelper(Module mod, MdSigCallingConvention callingConvention)
+ {
+ // Use this constructor to instantiate a local var sig or Field where return type is not applied.
+ Init(mod, callingConvention);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SignatureHelper(Module mod, MdSigCallingConvention callingConvention, int cGenericParameters,
+ Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ // Use this constructor to instantiate a any signatures that will require a return type.
+ Init(mod, callingConvention, cGenericParameters);
+
+ if (callingConvention == MdSigCallingConvention.Field)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadFieldSig"));
+
+ AddOneArgTypeHelper(returnType, requiredCustomModifiers, optionalCustomModifiers);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SignatureHelper(Module mod, MdSigCallingConvention callingConvention,
+ Type returnType, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ : this(mod, callingConvention, 0, returnType, requiredCustomModifiers, optionalCustomModifiers)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private SignatureHelper(Module mod, Type type)
+ {
+ Init(mod);
+
+ AddOneArgTypeHelper(type);
+ }
+
+ private void Init(Module mod)
+ {
+ m_signature = new byte[32];
+ m_currSig = 0;
+ m_module = mod as ModuleBuilder;
+ m_argCount = 0;
+ m_sigDone = false;
+ m_sizeLoc = NO_SIZE_IN_SIG;
+
+ if (m_module == null && mod != null)
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_MustBeModuleBuilder"));
+ }
+
+ private void Init(Module mod, MdSigCallingConvention callingConvention)
+ {
+ Init(mod, callingConvention, 0);
+ }
+
+ private void Init(Module mod, MdSigCallingConvention callingConvention, int cGenericParam)
+ {
+ Init(mod);
+
+ AddData((byte)callingConvention);
+
+ if (callingConvention == MdSigCallingConvention.Field ||
+ callingConvention == MdSigCallingConvention.GenericInst)
+ {
+ m_sizeLoc = NO_SIZE_IN_SIG;
+ }
+ else
+ {
+ if (cGenericParam > 0)
+ AddData(cGenericParam);
+
+ m_sizeLoc = m_currSig++;
+ }
+ }
+
+ #endregion
+
+ #region Private Members
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddOneArgTypeHelper(Type argument, bool pinned)
+ {
+ if (pinned)
+ AddElementType(CorElementType.Pinned);
+
+ AddOneArgTypeHelper(argument);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddOneArgTypeHelper(Type clsArgument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ // This function will not increase the argument count. It only fills in bytes
+ // in the signature based on clsArgument. This helper is called for return type.
+
+ Contract.Requires(clsArgument != null);
+ Contract.Requires((optionalCustomModifiers == null && requiredCustomModifiers == null) || !clsArgument.ContainsGenericParameters);
+
+ if (optionalCustomModifiers != null)
+ {
+ for (int i = 0; i < optionalCustomModifiers.Length; i++)
+ {
+ Type t = optionalCustomModifiers[i];
+
+ if (t == null)
+ throw new ArgumentNullException("optionalCustomModifiers");
+
+ if (t.HasElementType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "optionalCustomModifiers");
+
+ if (t.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "optionalCustomModifiers");
+
+ AddElementType(CorElementType.CModOpt);
+
+ int token = m_module.GetTypeToken(t).Token;
+ Contract.Assert(!MetadataToken.IsNullToken(token));
+ AddToken(token);
+ }
+ }
+
+ if (requiredCustomModifiers != null)
+ {
+ for (int i = 0; i < requiredCustomModifiers.Length; i++)
+ {
+ Type t = requiredCustomModifiers[i];
+
+ if (t == null)
+ throw new ArgumentNullException("requiredCustomModifiers");
+
+ if (t.HasElementType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArraysInvalid"), "requiredCustomModifiers");
+
+ if (t.ContainsGenericParameters)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericsInvalid"), "requiredCustomModifiers");
+
+ AddElementType(CorElementType.CModReqd);
+
+ int token = m_module.GetTypeToken(t).Token;
+ Contract.Assert(!MetadataToken.IsNullToken(token));
+ AddToken(token);
+ }
+ }
+
+ AddOneArgTypeHelper(clsArgument);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddOneArgTypeHelper(Type clsArgument) { AddOneArgTypeHelperWorker(clsArgument, false); }
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddOneArgTypeHelperWorker(Type clsArgument, bool lastWasGenericInst)
+ {
+ if (clsArgument.IsGenericParameter)
+ {
+ if (clsArgument.DeclaringMethod != null)
+ AddElementType(CorElementType.MVar);
+ else
+ AddElementType(CorElementType.Var);
+
+ AddData(clsArgument.GenericParameterPosition);
+ }
+ else if (clsArgument.IsGenericType && (!clsArgument.IsGenericTypeDefinition || !lastWasGenericInst))
+ {
+ AddElementType(CorElementType.GenericInst);
+
+ AddOneArgTypeHelperWorker(clsArgument.GetGenericTypeDefinition(), true);
+
+ Type[] args = clsArgument.GetGenericArguments();
+
+ AddData(args.Length);
+
+ foreach (Type t in args)
+ AddOneArgTypeHelper(t);
+ }
+ else if (clsArgument is TypeBuilder)
+ {
+ TypeBuilder clsBuilder = (TypeBuilder)clsArgument;
+ TypeToken tkType;
+
+ if (clsBuilder.Module.Equals(m_module))
+ {
+ tkType = clsBuilder.TypeToken;
+ }
+ else
+ {
+ tkType = m_module.GetTypeToken(clsArgument);
+ }
+
+ if (clsArgument.IsValueType)
+ {
+ InternalAddTypeToken(tkType, CorElementType.ValueType);
+ }
+ else
+ {
+ InternalAddTypeToken(tkType, CorElementType.Class);
+ }
+ }
+ else if (clsArgument is EnumBuilder)
+ {
+ TypeBuilder clsBuilder = ((EnumBuilder)clsArgument).m_typeBuilder;
+ TypeToken tkType;
+
+ if (clsBuilder.Module.Equals(m_module))
+ {
+ tkType = clsBuilder.TypeToken;
+ }
+ else
+ {
+ tkType = m_module.GetTypeToken(clsArgument);
+ }
+
+ if (clsArgument.IsValueType)
+ {
+ InternalAddTypeToken(tkType, CorElementType.ValueType);
+ }
+ else
+ {
+ InternalAddTypeToken(tkType, CorElementType.Class);
+ }
+ }
+ else if (clsArgument.IsByRef)
+ {
+ AddElementType(CorElementType.ByRef);
+ clsArgument = clsArgument.GetElementType();
+ AddOneArgTypeHelper(clsArgument);
+ }
+ else if (clsArgument.IsPointer)
+ {
+ AddElementType(CorElementType.Ptr);
+ AddOneArgTypeHelper(clsArgument.GetElementType());
+ }
+ else if (clsArgument.IsArray)
+ {
+ if (clsArgument.IsSzArray)
+ {
+ AddElementType(CorElementType.SzArray);
+
+ AddOneArgTypeHelper(clsArgument.GetElementType());
+ }
+ else
+ {
+ AddElementType(CorElementType.Array);
+
+ AddOneArgTypeHelper(clsArgument.GetElementType());
+
+ // put the rank information
+ int rank = clsArgument.GetArrayRank();
+ AddData(rank); // rank
+ AddData(0); // upper bounds
+ AddData(rank); // lower bound
+ for (int i = 0; i < rank; i++)
+ AddData(0);
+ }
+ }
+ else
+ {
+ CorElementType type = CorElementType.Max;
+
+ if (clsArgument is RuntimeType)
+ {
+ type = RuntimeTypeHandle.GetCorElementType((RuntimeType)clsArgument);
+
+ //GetCorElementType returns CorElementType.Class for both object and string
+ if (type == CorElementType.Class)
+ {
+ if (clsArgument == typeof(object))
+ type = CorElementType.Object;
+ else if (clsArgument == typeof(string))
+ type = CorElementType.String;
+ }
+ }
+
+ if (IsSimpleType(type))
+ {
+ AddElementType(type);
+ }
+ else if (m_module == null)
+ {
+ InternalAddRuntimeType(clsArgument);
+ }
+ else if (clsArgument.IsValueType)
+ {
+ InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.ValueType);
+ }
+ else
+ {
+ InternalAddTypeToken(m_module.GetTypeToken(clsArgument), CorElementType.Class);
+ }
+ }
+ }
+
+ private void AddData(int data)
+ {
+ // A managed representation of CorSigCompressData;
+
+ if (m_currSig + 4 > m_signature.Length)
+ {
+ m_signature = ExpandArray(m_signature);
+ }
+
+ if (data <= 0x7F)
+ {
+ m_signature[m_currSig++] = (byte)(data & 0xFF);
+ }
+ else if (data <= 0x3FFF)
+ {
+ m_signature[m_currSig++] = (byte)((data >>8) | 0x80);
+ m_signature[m_currSig++] = (byte)(data & 0xFF);
+ }
+ else if (data <= 0x1FFFFFFF)
+ {
+ m_signature[m_currSig++] = (byte)((data >>24) | 0xC0);
+ m_signature[m_currSig++] = (byte)((data >>16) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data >>8) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data) & 0xFF);
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
+ }
+
+ }
+
+ private void AddData(uint data)
+ {
+ if (m_currSig + 4 > m_signature.Length)
+ {
+ m_signature = ExpandArray(m_signature);
+ }
+
+ m_signature[m_currSig++] = (byte)((data) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>8) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
+ }
+
+ private void AddData(ulong data)
+ {
+ if (m_currSig + 8 > m_signature.Length)
+ {
+ m_signature = ExpandArray(m_signature);
+ }
+
+ m_signature[m_currSig++] = (byte)((data) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>8) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>16) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>24) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>32) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>40) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>48) & 0xFF);
+ m_signature[m_currSig++] = (byte)((data>>56) & 0xFF);
+ }
+
+ private void AddElementType(CorElementType cvt)
+ {
+ // Adds an element to the signature. A managed represenation of CorSigCompressElement
+ if (m_currSig + 1 > m_signature.Length)
+ m_signature = ExpandArray(m_signature);
+
+ m_signature[m_currSig++] = (byte)cvt;
+ }
+
+ private void AddToken(int token)
+ {
+ // A managed represenation of CompressToken
+ // Pulls the token appart to get a rid, adds some appropriate bits
+ // to the token and then adds this to the signature.
+
+ int rid = (token & 0x00FFFFFF); //This is RidFromToken;
+ MetadataTokenType type = (MetadataTokenType)(token & unchecked((int)0xFF000000)); //This is TypeFromToken;
+
+ if (rid > 0x3FFFFFF)
+ {
+ // token is too big to be compressed
+ throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
+ }
+
+ rid = (rid << 2);
+
+ // TypeDef is encoded with low bits 00
+ // TypeRef is encoded with low bits 01
+ // TypeSpec is encoded with low bits 10
+ if (type == MetadataTokenType.TypeRef)
+ {
+ //if type is mdtTypeRef
+ rid|=0x1;
+ }
+ else if (type == MetadataTokenType.TypeSpec)
+ {
+ //if type is mdtTypeSpec
+ rid|=0x2;
+ }
+
+ AddData(rid);
+ }
+
+ private void InternalAddTypeToken(TypeToken clsToken, CorElementType CorType)
+ {
+ // Add a type token into signature. CorType will be either CorElementType.Class or CorElementType.ValueType
+ AddElementType(CorType);
+ AddToken(clsToken.Token);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void InternalAddRuntimeType(Type type)
+ {
+ // Add a runtime type into the signature.
+
+ AddElementType(CorElementType.Internal);
+
+ IntPtr handle = type.GetTypeHandleInternal().Value;
+
+ // Internal types must have their pointer written into the signature directly (we don't
+ // want to convert to little-endian format on big-endian machines because the value is
+ // going to be extracted and used directly as a pointer (and only within this process)).
+
+ if (m_currSig + sizeof(void*) > m_signature.Length)
+ m_signature = ExpandArray(m_signature);
+
+ byte *phandle = (byte*)&handle;
+ for (int i = 0; i < sizeof(void*); i++)
+ m_signature[m_currSig++] = phandle[i];
+ }
+
+ private byte[] ExpandArray(byte[] inArray)
+ {
+ // Expand the signature buffer size
+ return ExpandArray(inArray, inArray.Length * 2);
+ }
+
+ private byte[] ExpandArray(byte[] inArray, int requiredLength)
+ {
+ // Expand the signature buffer size
+
+ if (requiredLength < inArray.Length)
+ requiredLength = inArray.Length*2;
+
+ byte[] outArray = new byte[requiredLength];
+ Buffer.BlockCopy(inArray, 0, outArray, 0, inArray.Length);
+ return outArray;
+ }
+
+ private void IncrementArgCounts()
+ {
+ if (m_sizeLoc == NO_SIZE_IN_SIG)
+ {
+ //We don't have a size if this is a field.
+ return;
+ }
+
+ m_argCount++;
+ }
+
+ private void SetNumberOfSignatureElements(bool forceCopy)
+ {
+ // For most signatures, this will set the number of elements in a byte which we have reserved for it.
+ // However, if we have a field signature, we don't set the length and return.
+ // If we have a signature with more than 128 arguments, we can't just set the number of elements,
+ // we actually have to allocate more space (e.g. shift everything in the array one or more spaces to the
+ // right. We do this by making a copy of the array and leaving the correct number of blanks. This new
+ // array is now set to be m_signature and we use the AddData method to set the number of elements properly.
+ // The forceCopy argument can be used to force SetNumberOfSignatureElements to make a copy of
+ // the array. This is useful for GetSignature which promises to trim the array to be the correct size anyway.
+
+ byte[] temp;
+ int newSigSize;
+ int currSigHolder = m_currSig;
+
+ if (m_sizeLoc == NO_SIZE_IN_SIG)
+ return;
+
+ //If we have fewer than 128 arguments and we haven't been told to copy the
+ //array, we can just set the appropriate bit and return.
+ if (m_argCount < 0x80 && !forceCopy)
+ {
+ m_signature[m_sizeLoc] = (byte)m_argCount;
+ return;
+ }
+
+ //We need to have more bytes for the size. Figure out how many bytes here.
+ //Since we need to copy anyway, we're just going to take the cost of doing a
+ //new allocation.
+ if (m_argCount < 0x80)
+ {
+ newSigSize = 1;
+ }
+ else if (m_argCount < 0x4000)
+ {
+ newSigSize = 2;
+ }
+ else
+ {
+ newSigSize = 4;
+ }
+
+ //Allocate the new array.
+ temp = new byte[m_currSig + newSigSize - 1];
+
+ //Copy the calling convention. The calling convention is always just one byte
+ //so we just copy that byte. Then copy the rest of the array, shifting everything
+ //to make room for the new number of elements.
+ temp[0] = m_signature[0];
+ Buffer.BlockCopy(m_signature, m_sizeLoc + 1, temp, m_sizeLoc + newSigSize, currSigHolder - (m_sizeLoc + 1));
+ m_signature = temp;
+
+ //Use the AddData method to add the number of elements appropriately compressed.
+ m_currSig = m_sizeLoc;
+ AddData(m_argCount);
+ m_currSig = currSigHolder + (newSigSize - 1);
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal int ArgumentCount
+ {
+ get
+ {
+ return m_argCount;
+ }
+ }
+
+ internal static bool IsSimpleType(CorElementType type)
+ {
+ if (type <= CorElementType.String)
+ return true;
+
+ if (type == CorElementType.TypedByRef || type == CorElementType.I || type == CorElementType.U || type == CorElementType.Object)
+ return true;
+
+ return false;
+ }
+
+ internal byte[] InternalGetSignature(out int length)
+ {
+ // An internal method to return the signature. Does not trim the
+ // array, but passes out the length of the array in an out parameter.
+ // This is the actual array -- not a copy -- so the callee must agree
+ // to not copy it.
+ //
+ // param length : an out param indicating the length of the array.
+ // return : A reference to the internal ubyte array.
+
+ if (!m_sigDone)
+ {
+ m_sigDone = true;
+
+ // If we have more than 128 variables, we can't just set the length, we need
+ // to compress it. Unfortunately, this means that we need to copy the entire
+ // array. Bummer, eh?
+ SetNumberOfSignatureElements(false);
+ }
+
+ length = m_currSig;
+ return m_signature;
+ }
+
+
+
+
+ internal byte[] InternalGetSignatureArray()
+ {
+ int argCount = m_argCount;
+ int currSigLength = m_currSig;
+ int newSigSize = currSigLength;
+
+ //Allocate the new array.
+ if (argCount < 0x7F)
+ newSigSize += 1;
+ else if (argCount < 0x3FFF)
+ newSigSize += 2;
+ else
+ newSigSize += 4;
+ byte[] temp = new byte[newSigSize];
+
+ // copy the sig
+ int sigCopyIndex = 0;
+ // calling convention
+ temp[sigCopyIndex++] = m_signature[0];
+ // arg size
+ if (argCount <= 0x7F)
+ temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
+ else if (argCount <= 0x3FFF)
+ {
+ temp[sigCopyIndex++] = (byte)((argCount >>8) | 0x80);
+ temp[sigCopyIndex++] = (byte)(argCount & 0xFF);
+ }
+ else if (argCount <= 0x1FFFFFFF)
+ {
+ temp[sigCopyIndex++] = (byte)((argCount >>24) | 0xC0);
+ temp[sigCopyIndex++] = (byte)((argCount >>16) & 0xFF);
+ temp[sigCopyIndex++] = (byte)((argCount >>8) & 0xFF);
+ temp[sigCopyIndex++] = (byte)((argCount) & 0xFF);
+ }
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_LargeInteger"));
+ // copy the sig part of the sig
+ Buffer.BlockCopy(m_signature, 2, temp, sigCopyIndex, currSigLength - 2);
+ // mark the end of sig
+ temp[newSigSize - 1] = (byte)CorElementType.End;
+
+ return temp;
+ }
+
+ #endregion
+
+ #region Public Methods
+ public void AddArgument(Type clsArgument)
+ {
+ AddArgument(clsArgument, null, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddArgument(Type argument, bool pinned)
+ {
+ if (argument == null)
+ throw new ArgumentNullException("argument");
+
+ IncrementArgCounts();
+ AddOneArgTypeHelper(argument, pinned);
+ }
+
+ public void AddArguments(Type[] arguments, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ if (requiredCustomModifiers != null && (arguments == null || requiredCustomModifiers.Length != arguments.Length))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "requiredCustomModifiers", "arguments"));
+
+ if (optionalCustomModifiers != null && (arguments == null || optionalCustomModifiers.Length != arguments.Length))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "optionalCustomModifiers", "arguments"));
+
+ if (arguments != null)
+ {
+ for (int i =0; i < arguments.Length; i++)
+ {
+ AddArgument(arguments[i],
+ requiredCustomModifiers == null ? null : requiredCustomModifiers[i],
+ optionalCustomModifiers == null ? null : optionalCustomModifiers[i]);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddArgument(Type argument, Type[] requiredCustomModifiers, Type[] optionalCustomModifiers)
+ {
+ if (m_sigDone)
+ throw new ArgumentException(Environment.GetResourceString("Argument_SigIsFinalized"));
+
+ if (argument == null)
+ throw new ArgumentNullException("argument");
+
+ IncrementArgCounts();
+
+ // Add an argument to the signature. Takes a Type and determines whether it
+ // is one of the primitive types of which we have special knowledge or a more
+ // general class. In the former case, we only add the appropriate short cut encoding,
+ // otherwise we will calculate proper description for the type.
+ AddOneArgTypeHelper(argument, requiredCustomModifiers, optionalCustomModifiers);
+ }
+
+ public void AddSentinel()
+ {
+ AddElementType(CorElementType.Sentinel);
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (!(obj is SignatureHelper))
+ {
+ return false;
+ }
+
+ SignatureHelper temp = (SignatureHelper)obj;
+
+ if ( !temp.m_module.Equals(m_module) || temp.m_currSig!=m_currSig || temp.m_sizeLoc!=m_sizeLoc || temp.m_sigDone !=m_sigDone )
+ {
+ return false;
+ }
+
+ for (int i=0; i<m_currSig; i++)
+ {
+ if (m_signature[i]!=temp.m_signature[i])
+ return false;
+ }
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ // Start the hash code with the hash code of the module and the values of the member variables.
+ int HashCode = m_module.GetHashCode() + m_currSig + m_sizeLoc;
+
+ // Add one if the sig is done.
+ if (m_sigDone)
+ HashCode += 1;
+
+ // Then add the hash code of all the arguments.
+ for (int i=0; i < m_currSig; i++)
+ HashCode += m_signature[i].GetHashCode();
+
+ return HashCode;
+ }
+
+ public byte[] GetSignature()
+ {
+ return GetSignature(false);
+ }
+
+ internal byte[] GetSignature(bool appendEndOfSig)
+ {
+ // Chops the internal signature to the appropriate length. Adds the
+ // end token to the signature and marks the signature as finished so that
+ // no further tokens can be added. Return the full signature in a trimmed array.
+ if (!m_sigDone)
+ {
+ if (appendEndOfSig)
+ AddElementType(CorElementType.End);
+ SetNumberOfSignatureElements(true);
+ m_sigDone = true;
+ }
+
+ // This case will only happen if the user got the signature through
+ // InternalGetSignature first and then called GetSignature.
+ if (m_signature.Length > m_currSig)
+ {
+ byte[] temp = new byte[m_currSig];
+ Array.Copy(m_signature, 0, temp, 0, m_currSig);
+ m_signature = temp;
+ }
+
+ return m_signature;
+ }
+
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Length: " + m_currSig + Environment.NewLine);
+
+ if (m_sizeLoc != -1)
+ {
+ sb.Append("Arguments: " + m_signature[m_sizeLoc] + Environment.NewLine);
+ }
+ else
+ {
+ sb.Append("Field Signature" + Environment.NewLine);
+ }
+
+ sb.Append("Signature: " + Environment.NewLine);
+ for (int i=0; i<=m_currSig; i++)
+ {
+ sb.Append(m_signature[i] + " ");
+ }
+
+ sb.Append(Environment.NewLine);
+ return sb.ToString();
+ }
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _SignatureHelper.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _SignatureHelper.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _SignatureHelper.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _SignatureHelper.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/SignatureToken.cs b/src/mscorlib/src/System/Reflection/Emit/SignatureToken.cs
new file mode 100644
index 0000000000..0a87ac1398
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/SignatureToken.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Signature: SignatureToken
+**
+**
+**
+**
+** Purpose: Represents a Signature to the ILGenerator signature.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct SignatureToken {
+
+ public static readonly SignatureToken Empty = new SignatureToken();
+
+ internal int m_signature;
+ internal ModuleBuilder m_moduleBuilder;
+
+ internal SignatureToken(int str, ModuleBuilder mod) {
+ m_signature=str;
+ m_moduleBuilder = mod;
+ }
+
+ public int Token {
+ get { return m_signature; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_signature;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is SignatureToken)
+ return Equals((SignatureToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(SignatureToken obj)
+ {
+ return obj.m_signature == m_signature;
+ }
+
+ public static bool operator ==(SignatureToken a, SignatureToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(SignatureToken a, SignatureToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/StackBehaviour.cs b/src/mscorlib/src/System/Reflection/Emit/StackBehaviour.cs
new file mode 100644
index 0000000000..2d2c35ef26
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/StackBehaviour.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**Purpose: Exposes StackBehaviour Attribute of IL .
+**
+** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!
+** See clr\src\inc\opcodegen.pl for more information.**
+============================================================*/
+namespace System.Reflection.Emit {
+
+using System;
+
+[Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+public enum StackBehaviour
+{
+
+ Pop0 = 0,
+ Pop1 = 1,
+ Pop1_pop1 = 2,
+ Popi = 3,
+ Popi_pop1 = 4,
+ Popi_popi = 5,
+ Popi_popi8 = 6,
+ Popi_popi_popi = 7,
+ Popi_popr4 = 8,
+ Popi_popr8 = 9,
+ Popref = 10,
+ Popref_pop1 = 11,
+ Popref_popi = 12,
+ Popref_popi_popi = 13,
+ Popref_popi_popi8 = 14,
+ Popref_popi_popr4 = 15,
+ Popref_popi_popr8 = 16,
+ Popref_popi_popref = 17,
+ Push0 = 18,
+ Push1 = 19,
+ Push1_push1 = 20,
+ Pushi = 21,
+ Pushi8 = 22,
+ Pushr4 = 23,
+ Pushr8 = 24,
+ Pushref = 25,
+ Varpop = 26,
+ Varpush = 27,
+ Popref_popi_pop1 = 28,
+}
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/StringToken.cs b/src/mscorlib/src/System/Reflection/Emit/StringToken.cs
new file mode 100644
index 0000000000..cb0e979a7a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/StringToken.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Represents a String to the ILGenerator class.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct StringToken {
+
+ internal int m_string;
+
+ //public StringToken() {
+ // m_string=0;
+ //}
+
+ internal StringToken(int str) {
+ m_string=str;
+ }
+
+ // Returns the metadata token for this particular string.
+ // Generated by a call to Module.GetStringConstant().
+ //
+ public int Token {
+ get { return m_string; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_string;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is StringToken)
+ return Equals((StringToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(StringToken obj)
+ {
+ return obj.m_string == m_string;
+ }
+
+ public static bool operator ==(StringToken a, StringToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(StringToken a, StringToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs b/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs
new file mode 100644
index 0000000000..62780f4e3a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/SymbolMethod.cs
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Reflection;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ internal sealed class SymbolMethod : MethodInfo
+ {
+ #region Private Data Members
+ private ModuleBuilder m_module;
+ private Type m_containingType;
+ private String m_name;
+ private CallingConventions m_callingConvention;
+ private Type m_returnType;
+ private MethodToken m_mdMethod;
+ private Type[] m_parameterTypes;
+ private SignatureHelper m_signature;
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal SymbolMethod(ModuleBuilder mod, MethodToken token, Type arrayClass, String methodName,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ // This is a kind of MethodInfo to represent methods for array type of unbaked type
+
+ // Another way to look at this class is as a glorified MethodToken wrapper. At the time of this comment
+ // this class is only constructed inside ModuleBuilder.GetArrayMethod and the only interesting thing
+ // passed into it is this MethodToken. The MethodToken was forged using a TypeSpec for an Array type and
+ // the name of the method on Array.
+ // As none of the methods on Array have CustomModifiers their is no need to pass those around in here.
+ m_mdMethod = token;
+
+ // The ParameterTypes are also a bit interesting in that they may be unbaked TypeBuilders.
+ m_returnType = returnType;
+ if (parameterTypes != null)
+ {
+ m_parameterTypes = new Type[parameterTypes.Length];
+ Array.Copy(parameterTypes, 0, m_parameterTypes, 0, parameterTypes.Length);
+ }
+ else
+ {
+ m_parameterTypes = EmptyArray<Type>.Value;
+ }
+
+ m_module = mod;
+ m_containingType = arrayClass;
+ m_name = methodName;
+ m_callingConvention = callingConvention;
+
+ m_signature = SignatureHelper.GetMethodSigHelper(
+ mod, callingConvention, returnType, null, null, parameterTypes, null, null);
+ }
+ #endregion
+
+ #region Internal Members
+ internal override Type[] GetParameterTypes()
+ {
+ return m_parameterTypes;
+ }
+
+ internal MethodToken GetToken(ModuleBuilder mod)
+ {
+ return mod.GetArrayMethodToken(m_containingType, m_name, m_callingConvention, m_returnType, m_parameterTypes);
+ }
+
+ #endregion
+
+ #region MemberInfo Overrides
+ public override Module Module
+ {
+ get { return m_module; }
+ }
+
+ public override Type ReflectedType
+ {
+ get { return m_containingType as Type; }
+ }
+
+ public override String Name
+ {
+ get { return m_name; }
+ }
+
+ public override Type DeclaringType
+ {
+ get {return m_containingType;}
+ }
+ #endregion
+
+ #region MethodBase Overrides
+ [Pure]
+ public override ParameterInfo[] GetParameters()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ public override MethodAttributes Attributes
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod")); }
+ }
+
+ public override CallingConventions CallingConvention
+ {
+ get { return m_callingConvention; }
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod")); }
+ }
+
+ #endregion
+
+ #region MethodInfo Overrides
+ public override Type ReturnType
+ {
+ get
+ {
+ return m_returnType;
+ }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get { return null; }
+ }
+
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ public override MethodInfo GetBaseDefinition()
+ {
+ return this;
+ }
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SymbolMethod"));
+ }
+
+ #endregion
+
+ #region Public Members
+ public Module GetModule()
+ {
+ return m_module;
+ }
+
+ public MethodToken GetToken()
+ {
+ return m_mdMethod;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs b/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs
new file mode 100644
index 0000000000..633a2bffb4
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/SymbolType.cs
@@ -0,0 +1,606 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Reflection;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Serializable]
+ internal enum TypeKind
+ {
+ IsArray = 1,
+ IsPointer = 2,
+ IsByRef = 3,
+ }
+
+ // This is a kind of Type object that will represent the compound expression of a parameter type or field type.
+ internal sealed class SymbolType : TypeInfo
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ #region Static Members
+ internal static Type FormCompoundType(string format, Type baseType, int curIndex)
+ {
+ // This function takes a string to describe the compound type, such as "[,][]", and a baseType.
+ //
+ // Example: [2..4] - one dimension array with lower bound 2 and size of 3
+ // Example: [3, 5, 6] - three dimension array with lower bound 3, 5, 6
+ // Example: [-3, ] [] - one dimensional array of two dimensional array (with lower bound -3 for
+ // the first dimension)
+ // Example: []* - pointer to a one dimensional array
+ // Example: *[] - one dimensional array. The element type is a pointer to the baseType
+ // Example: []& - ByRef of a single dimensional array. Only one & is allowed and it must appear the last!
+ // Example: [?] - Array with unknown bound
+
+ SymbolType symbolType;
+ int iLowerBound;
+ int iUpperBound;
+
+ if (format == null || curIndex == format.Length)
+ {
+ // we have consumed all of the format string
+ return baseType;
+ }
+
+
+
+
+ if (format[curIndex] == '&')
+ {
+ // ByRef case
+
+ symbolType = new SymbolType(TypeKind.IsByRef);
+ symbolType.SetFormat(format, curIndex, 1);
+ curIndex++;
+
+ if (curIndex != format.Length)
+ // ByRef has to be the last char!!
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadSigFormat"));
+
+ symbolType.SetElementType(baseType);
+ return symbolType;
+ }
+
+ if (format[curIndex] == '[')
+ {
+ // Array type.
+ symbolType = new SymbolType(TypeKind.IsArray);
+ int startIndex = curIndex;
+ curIndex++;
+
+ iLowerBound = 0;
+ iUpperBound = -1;
+
+ // Example: [2..4] - one dimension array with lower bound 2 and size of 3
+ // Example: [3, 5, 6] - three dimension array with lower bound 3, 5, 6
+ // Example: [-3, ] [] - one dimensional array of two dimensional array (with lower bound -3 sepcified)
+
+ while (format[curIndex] != ']')
+ {
+ if (format[curIndex] == '*')
+ {
+ symbolType.m_isSzArray = false;
+ curIndex++;
+ }
+ // consume, one dimension at a time
+ if ((format[curIndex] >= '0' && format[curIndex] <= '9') || format[curIndex] == '-')
+ {
+ bool isNegative = false;
+ if (format[curIndex] == '-')
+ {
+ isNegative = true;
+ curIndex++;
+ }
+
+ // lower bound is specified. Consume the low bound
+ while (format[curIndex] >= '0' && format[curIndex] <= '9')
+ {
+ iLowerBound = iLowerBound * 10;
+ iLowerBound += format[curIndex] - '0';
+ curIndex++;
+ }
+
+ if (isNegative)
+ {
+ iLowerBound = 0 - iLowerBound;
+ }
+
+ // set the upper bound to be less than LowerBound to indicate that upper bound it not specified yet!
+ iUpperBound = iLowerBound - 1;
+
+ }
+ if (format[curIndex] == '.')
+ {
+ // upper bound is specified
+
+ // skip over ".."
+ curIndex++;
+ if (format[curIndex] != '.')
+ {
+ // bad format!! Throw exception
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadSigFormat"));
+ }
+
+ curIndex++;
+ // consume the upper bound
+ if ((format[curIndex] >= '0' && format[curIndex] <= '9') || format[curIndex] == '-')
+ {
+ bool isNegative = false;
+ iUpperBound = 0;
+ if (format[curIndex] == '-')
+ {
+ isNegative = true;
+ curIndex++;
+ }
+
+ // lower bound is specified. Consume the low bound
+ while (format[curIndex] >= '0' && format[curIndex] <= '9')
+ {
+ iUpperBound = iUpperBound * 10;
+ iUpperBound += format[curIndex] - '0';
+ curIndex++;
+ }
+ if (isNegative)
+ {
+ iUpperBound = 0 - iUpperBound;
+ }
+ if (iUpperBound < iLowerBound)
+ {
+ // User specified upper bound less than lower bound, this is an error.
+ // Throw error exception.
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadSigFormat"));
+ }
+ }
+ }
+
+ if (format[curIndex] == ',')
+ {
+ // We have more dimension to deal with.
+ // now set the lower bound, the size, and increase the dimension count!
+ curIndex++;
+ symbolType.SetBounds(iLowerBound, iUpperBound);
+
+ // clear the lower and upper bound information for next dimension
+ iLowerBound = 0;
+ iUpperBound = -1;
+ }
+ else if (format[curIndex] != ']')
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadSigFormat"));
+ }
+ }
+
+ // The last dimension information
+ symbolType.SetBounds(iLowerBound, iUpperBound);
+
+ // skip over ']'
+ curIndex++;
+
+ symbolType.SetFormat(format, startIndex, curIndex - startIndex);
+
+ // set the base type of array
+ symbolType.SetElementType(baseType);
+ return FormCompoundType(format, symbolType, curIndex);
+ }
+ else if (format[curIndex] == '*')
+ {
+ // pointer type.
+
+ symbolType = new SymbolType(TypeKind.IsPointer);
+ symbolType.SetFormat(format, curIndex, 1);
+ curIndex++;
+ symbolType.SetElementType(baseType);
+ return FormCompoundType(format, symbolType, curIndex);
+ }
+
+ return null;
+ }
+
+ #endregion
+
+ #region Data Members
+ internal TypeKind m_typeKind;
+ internal Type m_baseType;
+ internal int m_cRank; // count of dimension
+ // If LowerBound and UpperBound is equal, that means one element.
+ // If UpperBound is less than LowerBound, then the size is not specified.
+ internal int[] m_iaLowerBound;
+ internal int[] m_iaUpperBound; // count of dimension
+ private string m_format; // format string to form the full name.
+ private bool m_isSzArray = true;
+ #endregion
+
+ #region Constructor
+ internal SymbolType(TypeKind typeKind)
+ {
+ m_typeKind = typeKind;
+ m_iaLowerBound = new int[4];
+ m_iaUpperBound = new int[4];
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal void SetElementType(Type baseType)
+ {
+ if (baseType == null)
+ throw new ArgumentNullException("baseType");
+ Contract.EndContractBlock();
+
+ m_baseType = baseType;
+ }
+
+ private void SetBounds(int lower, int upper)
+ {
+ // Increase the rank, set lower and upper bound
+
+ if (lower != 0 || upper != -1)
+ m_isSzArray = false;
+
+ if (m_iaLowerBound.Length <= m_cRank)
+ {
+ // resize the bound array
+ int[] iaTemp = new int[m_cRank * 2];
+ Array.Copy(m_iaLowerBound, 0, iaTemp, 0, m_cRank);
+ m_iaLowerBound = iaTemp;
+ Array.Copy(m_iaUpperBound, 0, iaTemp, 0, m_cRank);
+ m_iaUpperBound = iaTemp;
+ }
+
+ m_iaLowerBound[m_cRank] = lower;
+ m_iaUpperBound[m_cRank] = upper;
+ m_cRank++;
+ }
+
+ internal void SetFormat(string format, int curIndex, int length)
+ {
+ // Cache the text display format for this SymbolType
+
+ m_format = format.Substring(curIndex, length);
+ }
+ #endregion
+
+ #region Type Overrides
+ internal override bool IsSzArray
+ {
+ get
+ {
+ if (m_cRank > 1)
+ return false;
+
+ return m_isSzArray;
+ }
+ }
+
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType(m_format + "*", m_baseType, 0);
+ }
+
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType(m_format + "&", m_baseType, 0);
+ }
+
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType(m_format + "[]", m_baseType, 0);
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ string szrank = "";
+ if (rank == 1)
+ {
+ szrank = "*";
+ }
+ else
+ {
+ for(int i = 1; i < rank; i++)
+ szrank += ",";
+ }
+
+ string s = String.Format(CultureInfo.InvariantCulture, "[{0}]", szrank); // [,,]
+ SymbolType st = SymbolType.FormCompoundType(m_format + s, m_baseType, 0) as SymbolType;
+ return st;
+ }
+
+ public override int GetArrayRank()
+ {
+ if (!IsArray)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ Contract.EndContractBlock();
+
+ return m_cRank;
+ }
+
+ public override Guid GUID
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType")); }
+ }
+
+ public override Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target,
+ Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Module Module
+ {
+ get
+ {
+ Type baseType;
+
+ for (baseType = m_baseType; baseType is SymbolType; baseType = ((SymbolType) baseType).m_baseType);
+
+ return baseType.Module;
+ }
+ }
+ public override Assembly Assembly
+ {
+ get
+ {
+ Type baseType;
+
+ for (baseType = m_baseType; baseType is SymbolType; baseType = ((SymbolType) baseType).m_baseType);
+
+ return baseType.Assembly;
+ }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType")); }
+ }
+
+ public override String Name
+ {
+ get
+ {
+ Type baseType;
+ String sFormat = m_format;
+
+ for (baseType = m_baseType; baseType is SymbolType; baseType = ((SymbolType)baseType).m_baseType)
+ sFormat = ((SymbolType)baseType).m_format + sFormat;
+
+ return baseType.Name + sFormat;
+ }
+ }
+
+ public override String FullName
+ {
+ get
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
+ }
+ }
+
+ public override String AssemblyQualifiedName
+ {
+ get
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName);
+ }
+ }
+
+ public override String ToString()
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.ToString);
+ }
+
+ public override String Namespace
+ {
+ get { return m_baseType.Namespace; }
+ }
+
+ public override Type BaseType
+ {
+
+ get { return typeof(System.Array); }
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ protected override MethodInfo GetMethodImpl(String name,BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Type GetInterface(String name,bool ignoreCase)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override EventInfo GetEvent(String name,BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Type GetNestedType(String name, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ // Return the attribute flags of the base type?
+ Type baseType;
+ for (baseType = m_baseType; baseType is SymbolType; baseType = ((SymbolType)baseType).m_baseType);
+ return baseType.Attributes;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return m_typeKind == TypeKind.IsArray;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return m_typeKind == TypeKind.IsPointer;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return m_typeKind == TypeKind.IsByRef;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return false;
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override Type GetElementType()
+ {
+ return m_baseType;
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return m_baseType != null;
+ }
+
+ public override Type UnderlyingSystemType
+ {
+
+ get { return this; }
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+
+ public override bool IsDefined (Type attributeType, bool inherit)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NonReflectedType"));
+ }
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs b/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs
new file mode 100644
index 0000000000..6db04717b5
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/TypeBuilder.cs
@@ -0,0 +1,2620 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+
+namespace System.Reflection.Emit {
+ using System;
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Diagnostics;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Collections.Generic;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Threading;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum PackingSize
+ {
+ Unspecified = 0,
+ Size1 = 1,
+ Size2 = 2,
+ Size4 = 4,
+ Size8 = 8,
+ Size16 = 16,
+ Size32 = 32,
+ Size64 = 64,
+ Size128 = 128,
+ }
+
+ [HostProtection(MayLeakOnAbort = true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_TypeBuilder))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeBuilder : TypeInfo, _TypeBuilder
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ #region Declarations
+ private class CustAttr
+ {
+ private ConstructorInfo m_con;
+ private byte[] m_binaryAttribute;
+ private CustomAttributeBuilder m_customBuilder;
+
+ public CustAttr(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ m_con = con;
+ m_binaryAttribute = binaryAttribute;
+ }
+
+ public CustAttr(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ throw new ArgumentNullException("customBuilder");
+ Contract.EndContractBlock();
+
+ m_customBuilder = customBuilder;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void Bake(ModuleBuilder module, int token)
+ {
+ if (m_customBuilder == null)
+ {
+ TypeBuilder.DefineCustomAttribute(module, token, module.GetConstructorToken(m_con).Token,
+ m_binaryAttribute, false, false);
+ }
+ else
+ {
+ m_customBuilder.CreateCustomAttribute(module, token);
+ }
+ }
+ }
+ #endregion
+
+ #region Public Static Methods
+ public static MethodInfo GetMethod(Type type, MethodInfo method)
+ {
+ if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
+
+ // The following checks establishes invariants that more simply put require type to be generic and
+ // method to be a generic method definition declared on the generic type definition of type.
+ // To create generic method G<Foo>.M<Bar> these invariants require that G<Foo>.M<S> be created by calling
+ // this function followed by MakeGenericMethod on the resulting MethodInfo to finally get G<Foo>.M<Bar>.
+ // We could also allow G<T>.M<Bar> to be created before G<Foo>.M<Bar> (BindGenParm followed by this method)
+ // if we wanted to but that just complicates things so these checks are designed to prevent that scenario.
+
+ if (method.IsGenericMethod && !method.IsGenericMethodDefinition)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedGenericMethodDefinition"), "method");
+
+ if (method.DeclaringType == null || !method.DeclaringType.IsGenericTypeDefinition)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MethodNeedGenericDeclaringType"), "method");
+
+ if (type.GetGenericTypeDefinition() != method.DeclaringType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidMethodDeclaringType"), "type");
+ Contract.EndContractBlock();
+
+ // The following converts from Type or TypeBuilder of G<T> to TypeBuilderInstantiation G<T>. These types
+ // both logically represent the same thing. The runtime displays a similar convention by having
+ // G<M>.M() be encoded by a typeSpec whose parent is the typeDef for G<M> and whose instantiation is also G<M>.
+ if (type.IsGenericTypeDefinition)
+ type = type.MakeGenericType(type.GetGenericArguments());
+
+ if (!(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
+
+ return MethodOnTypeBuilderInstantiation.GetMethod(method, type as TypeBuilderInstantiation);
+ }
+ public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor)
+ {
+ if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
+
+ if (!constructor.DeclaringType.IsGenericTypeDefinition)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstructorNeedGenericDeclaringType"), "constructor");
+ Contract.EndContractBlock();
+
+ if (!(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
+
+ // TypeBuilder G<T> ==> TypeBuilderInstantiation G<T>
+ if (type is TypeBuilder && type.IsGenericTypeDefinition)
+ type = type.MakeGenericType(type.GetGenericArguments());
+
+ if (type.GetGenericTypeDefinition() != constructor.DeclaringType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorDeclaringType"), "type");
+
+ return ConstructorOnTypeBuilderInstantiation.GetConstructor(constructor, type as TypeBuilderInstantiation);
+ }
+ public static FieldInfo GetField(Type type, FieldInfo field)
+ {
+ if (!(type is TypeBuilder) && !(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeTypeBuilder"));
+
+ if (!field.DeclaringType.IsGenericTypeDefinition)
+ throw new ArgumentException(Environment.GetResourceString("Argument_FieldNeedGenericDeclaringType"), "field");
+ Contract.EndContractBlock();
+
+ if (!(type is TypeBuilderInstantiation))
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
+
+ // TypeBuilder G<T> ==> TypeBuilderInstantiation G<T>
+ if (type is TypeBuilder && type.IsGenericTypeDefinition)
+ type = type.MakeGenericType(type.GetGenericArguments());
+
+ if (type.GetGenericTypeDefinition() != field.DeclaringType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFieldDeclaringType"), "type");
+
+ return FieldOnTypeBuilderInstantiation.GetField(field, type as TypeBuilderInstantiation);
+ }
+ #endregion
+
+ #region Public Const
+ public const int UnspecifiedTypeSize = 0;
+ #endregion
+
+ #region Private Static FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void SetParentType(RuntimeModule module, int tdTypeDef, int tkParent);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void AddInterfaceImpl(RuntimeModule module, int tdTypeDef, int tkInterface);
+ #endregion
+
+ #region Internal Static FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int DefineMethod(RuntimeModule module, int tkParent, String name, byte[] signature, int sigLength,
+ MethodAttributes attributes);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int DefineMethodSpec(RuntimeModule module, int tkParent, byte[] signature, int sigLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int DefineField(RuntimeModule module, int tkParent, String name, byte[] signature, int sigLength,
+ FieldAttributes attributes);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void SetMethodIL(RuntimeModule module, int tk, bool isInitLocals,
+ byte[] body, int bodyLength,
+ byte[] LocalSig, int sigLength,
+ int maxStackSize,
+ ExceptionHandler[] exceptions, int numExceptions,
+ int [] tokenFixups, int numTokenFixups);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void DefineCustomAttribute(RuntimeModule module, int tkAssociate, int tkConstructor,
+ byte[] attr, int attrLength, bool toDisk, bool updateCompilerFlags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void DefineCustomAttribute(ModuleBuilder module, int tkAssociate, int tkConstructor,
+ byte[] attr, bool toDisk, bool updateCompilerFlags)
+ {
+ byte[] localAttr = null;
+
+ if (attr != null)
+ {
+ localAttr = new byte[attr.Length];
+ Buffer.BlockCopy(attr, 0, localAttr, 0, attr.Length);
+ }
+
+ DefineCustomAttribute(module.GetNativeHandle(), tkAssociate, tkConstructor,
+ localAttr, (localAttr != null) ? localAttr.Length : 0, toDisk, updateCompilerFlags);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void SetPInvokeData(RuntimeModule module, String DllName, String name, int token, int linkFlags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int DefineProperty(RuntimeModule module, int tkParent, String name, PropertyAttributes attributes,
+ byte[] signature, int sigLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int DefineEvent(RuntimeModule module, int tkParent, String name, EventAttributes attributes, int tkEventType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void DefineMethodSemantics(RuntimeModule module, int tkAssociation,
+ MethodSemanticsAttributes semantics, int tkMethod);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void DefineMethodImpl(RuntimeModule module, int tkType, int tkBody, int tkDecl);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void SetMethodImpl(RuntimeModule module, int tkMethod, MethodImplAttributes MethodImplAttributes);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int SetParamInfo(RuntimeModule module, int tkMethod, int iSequence,
+ ParameterAttributes iParamAttributes, String strParamName);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int GetTokenFromSig(RuntimeModule module, byte[] signature, int sigLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void SetFieldLayoutOffset(RuntimeModule module, int fdToken, int iOffset);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void SetClassLayout(RuntimeModule module, int tk, PackingSize iPackingSize, int iTypeSize);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void SetFieldMarshal(RuntimeModule module, int tk, byte[] ubMarshal, int ubSize);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern unsafe void SetConstantValue(RuntimeModule module, int tk, int corType, void* pValue);
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void AddDeclarativeSecurity(RuntimeModule module, int parent, SecurityAction action, byte[] blob, int cb);
+#endif
+ #endregion
+
+ #region Internal\Private Static Members
+ private static bool IsPublicComType(Type type)
+ {
+ // Internal Helper to determine if a type should be added to ComType table.
+ // A top level type should be added if it is Public.
+ // A nested type should be added if the top most enclosing type is Public
+ // and all the enclosing types are NestedPublic
+
+ Type enclosingType = type.DeclaringType;
+ if (enclosingType != null)
+ {
+ if (IsPublicComType(enclosingType))
+ {
+ if ((type.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic)
+ {
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if ((type.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public)
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ [Pure]
+ internal static bool IsTypeEqual(Type t1, Type t2)
+ {
+ // Maybe we are lucky that they are equal in the first place
+ if (t1 == t2)
+ return true;
+ TypeBuilder tb1 = null;
+ TypeBuilder tb2 = null;
+ Type runtimeType1 = null;
+ Type runtimeType2 = null;
+
+ // set up the runtimeType and TypeBuilder type corresponding to t1 and t2
+ if (t1 is TypeBuilder)
+ {
+ tb1 =(TypeBuilder)t1;
+ // This will be null if it is not baked.
+ runtimeType1 = tb1.m_bakedRuntimeType;
+ }
+ else
+ {
+ runtimeType1 = t1;
+ }
+
+ if (t2 is TypeBuilder)
+ {
+ tb2 =(TypeBuilder)t2;
+ // This will be null if it is not baked.
+ runtimeType2 = tb2.m_bakedRuntimeType;
+ }
+ else
+ {
+ runtimeType2 = t2;
+ }
+
+ // If the type builder view is eqaul then it is equal
+ if (tb1 != null && tb2 != null && Object.ReferenceEquals(tb1, tb2))
+ return true;
+
+ // if the runtimetype view is eqaul than it is equal
+ if (runtimeType1 != null && runtimeType2 != null && runtimeType1 == runtimeType2)
+ return true;
+
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe void SetConstantValue(ModuleBuilder module, int tk, Type destType, Object value)
+ {
+ // This is a helper function that is used by ParameterBuilder, PropertyBuilder,
+ // and FieldBuilder to validate a default value and save it in the meta-data.
+
+ if (value != null)
+ {
+ Type type = value.GetType();
+
+ // We should allow setting a constant value on a ByRef parameter
+ if (destType.IsByRef)
+ destType = destType.GetElementType();
+
+ if (destType.IsEnum)
+ {
+ // | UnderlyingSystemType | Enum.GetUnderlyingType() | IsEnum
+ // ----------------------------------|---------------------------|---------------------------|---------
+ // runtime Enum Type | self | underlying type of enum | TRUE
+ // EnumBuilder | underlying type of enum | underlying type of enum* | TRUE
+ // TypeBuilder of enum types** | underlying type of enum | Exception | TRUE
+ // TypeBuilder of enum types (baked) | runtime enum type | Exception | TRUE
+
+ // *: the behavior of Enum.GetUnderlyingType(EnumBuilder) might change in the future
+ // so let's not depend on it.
+ // **: created with System.Enum as the parent type.
+
+ // The above behaviors might not be the most consistent but we have to live with them.
+
+ Type underlyingType;
+ EnumBuilder enumBldr;
+ TypeBuilder typeBldr;
+ if ((enumBldr = destType as EnumBuilder) != null)
+ {
+ underlyingType = enumBldr.GetEnumUnderlyingType();
+
+ // The constant value supplied should match either the baked enum type or its underlying type
+ // we don't need to compare it with the EnumBuilder itself because you can never have an object of that type
+ if (type != enumBldr.m_typeBuilder.m_bakedRuntimeType && type != underlyingType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+ }
+ else if ((typeBldr = destType as TypeBuilder) != null)
+ {
+ underlyingType = typeBldr.m_enumUnderlyingType;
+
+ // The constant value supplied should match either the baked enum type or its underlying type
+ // typeBldr.m_enumUnderlyingType is null if the user hasn't created a "value__" field on the enum
+ if (underlyingType == null || (type != typeBldr.UnderlyingSystemType && type != underlyingType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+ }
+ else // must be a runtime Enum Type
+ {
+ Contract.Assert(destType is RuntimeType, "destType is not a runtime type, an EnumBuilder, or a TypeBuilder.");
+
+ underlyingType = Enum.GetUnderlyingType(destType);
+
+ // The constant value supplied should match either the enum itself or its underlying type
+ if (type != destType && type != underlyingType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+ }
+
+ type = underlyingType;
+ }
+ else
+ {
+ // Note that it is non CLS compliant if destType != type. But RefEmit never guarantees CLS-Compliance.
+ if (!destType.IsAssignableFrom(type))
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantDoesntMatch"));
+ }
+
+ CorElementType corType = RuntimeTypeHandle.GetCorElementType((RuntimeType)type);
+
+ switch (corType)
+ {
+ case CorElementType.I1:
+ case CorElementType.U1:
+ case CorElementType.Boolean:
+ case CorElementType.I2:
+ case CorElementType.U2:
+ case CorElementType.Char:
+ case CorElementType.I4:
+ case CorElementType.U4:
+ case CorElementType.R4:
+ case CorElementType.I8:
+ case CorElementType.U8:
+ case CorElementType.R8:
+ fixed (byte* pData = &JitHelpers.GetPinningHelper(value).m_data)
+ SetConstantValue(module.GetNativeHandle(), tk, (int)corType, pData);
+ break;
+
+ default:
+ if (type == typeof(String))
+ {
+ fixed (char* pString = (string)value)
+ SetConstantValue(module.GetNativeHandle(), tk, (int)CorElementType.String, pString);
+ }
+ else if (type == typeof(DateTime))
+ {
+ //date is a I8 representation
+ long ticks = ((DateTime)value).Ticks;
+ SetConstantValue(module.GetNativeHandle(), tk, (int)CorElementType.I8, &ticks);
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantNotSupported", type.ToString()));
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (destType.IsValueType)
+ {
+ // nullable types can hold null value.
+ if (!(destType.IsGenericType && destType.GetGenericTypeDefinition() == typeof(Nullable<>)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConstantNull"));
+ }
+
+ SetConstantValue(module.GetNativeHandle(), tk, (int)CorElementType.Class, null);
+ }
+ }
+
+ #endregion
+
+ #region Private Data Members
+ private List<CustAttr> m_ca;
+ private TypeToken m_tdType;
+ private ModuleBuilder m_module;
+ private String m_strName;
+ private String m_strNameSpace;
+ private String m_strFullQualName;
+ private Type m_typeParent;
+ private List<Type> m_typeInterfaces;
+ private TypeAttributes m_iAttr;
+ private GenericParameterAttributes m_genParamAttributes;
+ internal List<MethodBuilder> m_listMethods;
+ internal int m_lastTokenizedMethod;
+ private int m_constructorCount;
+ private int m_iTypeSize;
+ private PackingSize m_iPackingSize;
+ private TypeBuilder m_DeclaringType;
+
+ // We cannot store this on EnumBuilder because users can define enum types manually using TypeBuilder.
+ private Type m_enumUnderlyingType;
+ internal bool m_isHiddenGlobalType;
+ private bool m_hasBeenCreated;
+ private RuntimeType m_bakedRuntimeType;
+
+ private int m_genParamPos;
+ private GenericTypeParameterBuilder[] m_inst;
+ private bool m_bIsGenParam;
+ private MethodBuilder m_declMeth;
+ private TypeBuilder m_genTypeDef;
+ #endregion
+
+ #region Constructor
+ // ctor for the global (module) type
+ internal TypeBuilder(ModuleBuilder module)
+ {
+ m_tdType = new TypeToken((int)MetadataTokenType.TypeDef);
+ m_isHiddenGlobalType = true;
+ m_module = (ModuleBuilder)module;
+ m_listMethods = new List<MethodBuilder>();
+ // No token has been created so let's initialize it to -1
+ // The first time we call MethodBuilder.GetToken this will incremented.
+ m_lastTokenizedMethod = -1;
+ }
+
+ // ctor for generic method parameter
+ internal TypeBuilder(string szName, int genParamPos, MethodBuilder declMeth)
+ {
+ Contract.Requires(declMeth != null);
+ m_declMeth = declMeth;
+ m_DeclaringType =m_declMeth.GetTypeBuilder();
+ m_module =declMeth.GetModuleBuilder();
+ InitAsGenericParam(szName, genParamPos);
+ }
+
+ // ctor for generic type parameter
+ private TypeBuilder(string szName, int genParamPos, TypeBuilder declType)
+ {
+ Contract.Requires(declType != null);
+ m_DeclaringType = declType;
+ m_module =declType.GetModuleBuilder();
+ InitAsGenericParam(szName, genParamPos);
+ }
+
+ private void InitAsGenericParam(string szName, int genParamPos)
+ {
+ m_strName = szName;
+ m_genParamPos = genParamPos;
+ m_bIsGenParam = true;
+ m_typeInterfaces = new List<Type>();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal TypeBuilder(
+ String name,
+ TypeAttributes attr,
+ Type parent,
+ Type[] interfaces,
+ ModuleBuilder module,
+ PackingSize iPackingSize,
+ int iTypeSize,
+ TypeBuilder enclosingType)
+ {
+ Init(name, attr, parent, interfaces, module, iPackingSize, iTypeSize, enclosingType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void Init(String fullname, TypeAttributes attr, Type parent, Type[] interfaces, ModuleBuilder module,
+ PackingSize iPackingSize, int iTypeSize, TypeBuilder enclosingType)
+ {
+ if (fullname == null)
+ throw new ArgumentNullException("fullname");
+
+ if (fullname.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "fullname");
+
+ if (fullname[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "fullname");
+
+
+ if (fullname.Length > 1023)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeNameTooLong"), "fullname");
+ Contract.EndContractBlock();
+
+ int i;
+ m_module = module;
+ m_DeclaringType = enclosingType;
+ AssemblyBuilder containingAssem = m_module.ContainingAssemblyBuilder;
+
+ // cannot have two types within the same assembly of the same name
+ containingAssem.m_assemblyData.CheckTypeNameConflict(fullname, enclosingType);
+
+ if (enclosingType != null)
+ {
+ // Nested Type should have nested attribute set.
+ // If we are renumbering TypeAttributes' bit, we need to change the logic here.
+ if (((attr & TypeAttributes.VisibilityMask) == TypeAttributes.Public) ||((attr & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic))
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadNestedTypeFlags"), "attr");
+ }
+
+ int[] interfaceTokens = null;
+ if (interfaces != null)
+ {
+ for(i = 0; i < interfaces.Length; i++)
+ {
+ if (interfaces[i] == null)
+ {
+ // cannot contain null in the interface list
+ throw new ArgumentNullException("interfaces");
+ }
+ }
+ interfaceTokens = new int[interfaces.Length + 1];
+ for(i = 0; i < interfaces.Length; i++)
+ {
+ interfaceTokens[i] = m_module.GetTypeTokenInternal(interfaces[i]).Token;
+ }
+ }
+
+ int iLast = fullname.LastIndexOf('.');
+ if (iLast == -1 || iLast == 0)
+ {
+ // no name space
+ m_strNameSpace = String.Empty;
+ m_strName = fullname;
+ }
+ else
+ {
+ // split the name space
+ m_strNameSpace = fullname.Substring(0, iLast);
+ m_strName = fullname.Substring(iLast + 1);
+ }
+
+ VerifyTypeAttributes(attr);
+
+ m_iAttr = attr;
+
+ SetParent(parent);
+
+ m_listMethods = new List<MethodBuilder>();
+ m_lastTokenizedMethod = -1;
+
+ SetInterfaces(interfaces);
+
+ int tkParent = 0;
+ if (m_typeParent != null)
+ tkParent = m_module.GetTypeTokenInternal(m_typeParent).Token;
+
+ int tkEnclosingType = 0;
+ if (enclosingType != null)
+ {
+ tkEnclosingType = enclosingType.m_tdType.Token;
+ }
+
+ m_tdType = new TypeToken(DefineType(m_module.GetNativeHandle(),
+ fullname, tkParent, m_iAttr, tkEnclosingType, interfaceTokens));
+
+ m_iPackingSize = iPackingSize;
+ m_iTypeSize = iTypeSize;
+ if ((m_iPackingSize != 0) ||(m_iTypeSize != 0))
+ SetClassLayout(GetModuleBuilder().GetNativeHandle(), m_tdType.Token, m_iPackingSize, m_iTypeSize);
+
+#if !FEATURE_CORECLR
+ // If the type is public and it is contained in a assemblyBuilder,
+ // update the public COMType list.
+ if (IsPublicComType(this))
+ {
+ if (containingAssem.IsPersistable() && m_module.IsTransient() == false)
+ {
+ // This will throw InvalidOperationException if the assembly has been saved
+ // Ideally we should reject all emit operations if the assembly has been saved,
+ // but that would be a breaking change for some. Currently you cannot define
+ // modules and public types, but you can still define private types and global methods.
+ containingAssem.m_assemblyData.AddPublicComType(this);
+ }
+
+ // Now add the type to the ExportedType table
+ if (!m_module.Equals(containingAssem.ManifestModule))
+ containingAssem.DefineExportedTypeInMemory(this, m_module.m_moduleData.FileToken, m_tdType.Token);
+ }
+#endif
+ m_module.AddType(FullName, this);
+ }
+
+ #endregion
+
+ #region Private Members
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodBuilder DefinePInvokeMethodHelper(
+ String name, String dllName, String importName, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ CheckContext(returnType);
+ CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes);
+ CheckContext(parameterTypeRequiredCustomModifiers);
+ CheckContext(parameterTypeOptionalCustomModifiers);
+
+ AppDomain.CheckDefinePInvokeSupported();
+
+ lock (SyncRoot)
+ {
+ return DefinePInvokeMethodHelperNoLock(name, dllName, importName, attributes, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
+ nativeCallConv, nativeCharSet);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private MethodBuilder DefinePInvokeMethodHelperNoLock(
+ String name, String dllName, String importName, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+
+ if (dllName == null)
+ throw new ArgumentNullException("dllName");
+
+ if (dllName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "dllName");
+
+ if (importName == null)
+ throw new ArgumentNullException("importName");
+
+ if (importName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "importName");
+
+ if ((attributes & MethodAttributes.Abstract) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadPInvokeMethod"));
+ Contract.EndContractBlock();
+
+ if ((m_iAttr & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadPInvokeOnInterface"));
+
+ ThrowIfCreated();
+
+ attributes = attributes | MethodAttributes.PinvokeImpl;
+ MethodBuilder method = new MethodBuilder(name, attributes, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
+ m_module, this, false);
+
+ //The signature grabbing code has to be up here or the signature won't be finished
+ //and our equals check won't work.
+ int sigLength;
+ byte[] sigBytes = method.GetMethodSignature().InternalGetSignature(out sigLength);
+
+ if (m_listMethods.Contains(method))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_MethodRedefined"));
+ }
+ m_listMethods.Add(method);
+
+ MethodToken token = method.GetToken();
+
+ int linkFlags = 0;
+ switch(nativeCallConv)
+ {
+ case CallingConvention.Winapi:
+ linkFlags =(int)PInvokeMap.CallConvWinapi;
+ break;
+ case CallingConvention.Cdecl:
+ linkFlags =(int)PInvokeMap.CallConvCdecl;
+ break;
+ case CallingConvention.StdCall:
+ linkFlags =(int)PInvokeMap.CallConvStdcall;
+ break;
+ case CallingConvention.ThisCall:
+ linkFlags =(int)PInvokeMap.CallConvThiscall;
+ break;
+ case CallingConvention.FastCall:
+ linkFlags =(int)PInvokeMap.CallConvFastcall;
+ break;
+ }
+ switch(nativeCharSet)
+ {
+ case CharSet.None:
+ linkFlags |=(int)PInvokeMap.CharSetNotSpec;
+ break;
+ case CharSet.Ansi:
+ linkFlags |=(int)PInvokeMap.CharSetAnsi;
+ break;
+ case CharSet.Unicode:
+ linkFlags |=(int)PInvokeMap.CharSetUnicode;
+ break;
+ case CharSet.Auto:
+ linkFlags |=(int)PInvokeMap.CharSetAuto;
+ break;
+ }
+
+ SetPInvokeData(m_module.GetNativeHandle(),
+ dllName,
+ importName,
+ token.Token,
+ linkFlags);
+ method.SetToken(token);
+
+ return method;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldBuilder DefineDataHelper(String name, byte[] data, int size, FieldAttributes attributes)
+ {
+ String strValueClassName;
+ TypeBuilder valueClassType;
+ FieldBuilder fdBuilder;
+ TypeAttributes typeAttributes;
+
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+
+ if (size <= 0 || size >= 0x003f0000)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadSizeForData"));
+ Contract.EndContractBlock();
+
+ ThrowIfCreated();
+
+ // form the value class name
+ strValueClassName = ModuleBuilderData.MULTI_BYTE_VALUE_CLASS + size.ToString();
+
+ // Is this already defined in this module?
+ Type temp = m_module.FindTypeBuilderWithName(strValueClassName, false);
+ valueClassType = temp as TypeBuilder;
+
+ if (valueClassType == null)
+ {
+ typeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass;
+
+ // Define the backing value class
+ valueClassType = m_module.DefineType(strValueClassName, typeAttributes, typeof(System.ValueType), PackingSize.Size1, size);
+ valueClassType.CreateType();
+ }
+
+ fdBuilder = DefineField(name, valueClassType,(attributes | FieldAttributes.Static));
+
+ // now we need to set the RVA
+ fdBuilder.SetData(data, size);
+ return fdBuilder;
+ }
+
+ private void VerifyTypeAttributes(TypeAttributes attr)
+ {
+ // Verify attr consistency for Nesting or otherwise.
+ if (DeclaringType == null)
+ {
+ // Not a nested class.
+ if (((attr & TypeAttributes.VisibilityMask) != TypeAttributes.NotPublic) &&((attr & TypeAttributes.VisibilityMask) != TypeAttributes.Public))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeAttrNestedVisibilityOnNonNestedType"));
+ }
+ }
+ else
+ {
+ // Nested class.
+ if (((attr & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic) ||((attr & TypeAttributes.VisibilityMask) == TypeAttributes.Public))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeAttrNonNestedVisibilityNestedType"));
+ }
+ }
+
+ // Verify that the layout mask is valid.
+ if (((attr & TypeAttributes.LayoutMask) != TypeAttributes.AutoLayout) &&((attr & TypeAttributes.LayoutMask) != TypeAttributes.SequentialLayout) &&((attr & TypeAttributes.LayoutMask) != TypeAttributes.ExplicitLayout))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeAttrInvalidLayout"));
+ }
+
+ // Check if the user attempted to set any reserved bits.
+ if ((attr & TypeAttributes.ReservedMask) != 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadTypeAttrReservedBitsSet"));
+ }
+ }
+
+ [Pure]
+ public bool IsCreated()
+ {
+ return m_hasBeenCreated;
+ }
+
+ #endregion
+
+ #region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int DefineType(RuntimeModule module,
+ String fullname, int tkParent, TypeAttributes attributes, int tkEnclosingType, int[] interfaceTokens);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int DefineGenericParam(RuntimeModule module,
+ String name, int tkParent, GenericParameterAttributes attributes, int position, int[] constraints);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void TermCreateClass(RuntimeModule module, int tk, ObjectHandleOnStack type);
+ #endregion
+
+ #region Internal Methods
+ internal void ThrowIfCreated()
+ {
+ if (IsCreated())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated"));
+ }
+
+ internal object SyncRoot
+ {
+ get
+ {
+ return m_module.SyncRoot;
+ }
+ }
+
+ internal ModuleBuilder GetModuleBuilder()
+ {
+ return m_module;
+ }
+
+ internal RuntimeType BakedRuntimeType
+ {
+ get
+ {
+ return m_bakedRuntimeType;
+ }
+ }
+
+ internal void SetGenParamAttributes(GenericParameterAttributes genericParameterAttributes)
+ {
+ m_genParamAttributes = genericParameterAttributes;
+ }
+
+ internal void SetGenParamCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ CustAttr ca = new CustAttr(con, binaryAttribute);
+
+ lock(SyncRoot)
+ {
+ SetGenParamCustomAttributeNoLock(ca);
+ }
+ }
+
+ internal void SetGenParamCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ CustAttr ca = new CustAttr(customBuilder);
+
+ lock(SyncRoot)
+ {
+ SetGenParamCustomAttributeNoLock(ca);
+ }
+ }
+
+ private void SetGenParamCustomAttributeNoLock(CustAttr ca)
+ {
+ if (m_ca == null)
+ m_ca = new List<TypeBuilder.CustAttr>();
+
+ m_ca.Add(ca);
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.ToString);
+ }
+
+ #endregion
+
+ #region MemberInfo Overrides
+ public override Type DeclaringType
+ {
+ get { return m_DeclaringType; }
+ }
+
+ public override Type ReflectedType
+ {
+ // Return the class that was used to obtain this field.
+
+ get { return m_DeclaringType; }
+ }
+
+ public override String Name
+ {
+ get { return m_strName; }
+ }
+
+ public override Module Module
+ {
+ get { return GetModuleBuilder(); }
+ }
+
+ internal int MetadataTokenInternal
+ {
+ get { return m_tdType.Token; }
+ }
+
+ #endregion
+
+ #region Type Overrides
+ public override Guid GUID
+ {
+ get
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GUID;
+ }
+ }
+
+ public override Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target,
+ Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
+ }
+
+ public override Assembly Assembly
+ {
+ get { return m_module.Assembly; }
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+
+ get { throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule")); }
+ }
+
+ public override String FullName
+ {
+ get
+ {
+ if (m_strFullQualName == null)
+ m_strFullQualName = TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
+
+ return m_strFullQualName;
+ }
+ }
+
+ public override String Namespace
+ {
+ get { return m_strNameSpace; }
+ }
+
+ public override String AssemblyQualifiedName
+ {
+ get
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName);
+ }
+ }
+
+ public override Type BaseType
+ {
+ get{ return m_typeParent; }
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetConstructors(bindingAttr);
+ }
+
+ protected override MethodInfo GetMethodImpl(String name,BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ if (types == null)
+ {
+ return m_bakedRuntimeType.GetMethod(name, bindingAttr);
+ }
+ else
+ {
+ return m_bakedRuntimeType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetMethods(bindingAttr);
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetField(name, bindingAttr);
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetFields(bindingAttr);
+ }
+
+ public override Type GetInterface(String name,bool ignoreCase)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetInterface(name, ignoreCase);
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ if (m_bakedRuntimeType != null)
+ {
+ return m_bakedRuntimeType.GetInterfaces();
+ }
+
+ if (m_typeInterfaces == null)
+ {
+ return EmptyArray<Type>.Value;
+ }
+
+ return m_typeInterfaces.ToArray();
+ }
+
+ public override EventInfo GetEvent(String name,BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetEvent(name, bindingAttr);
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetEvents();
+ }
+
+ protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetProperties(bindingAttr);
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetNestedTypes(bindingAttr);
+ }
+
+ public override Type GetNestedType(String name, BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetNestedType(name,bindingAttr);
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetMember(name, type, bindingAttr);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetInterfaceMap(interfaceType);
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetEvents(bindingAttr);
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.GetMembers(bindingAttr);
+ }
+
+ public override bool IsAssignableFrom(Type c)
+ {
+ if (TypeBuilder.IsTypeEqual(c, this))
+ return true;
+
+ Type fromRuntimeType = null;
+ TypeBuilder fromTypeBuilder = c as TypeBuilder;
+
+ if (fromTypeBuilder != null)
+ fromRuntimeType = fromTypeBuilder.m_bakedRuntimeType;
+ else
+ fromRuntimeType = c;
+
+ if (fromRuntimeType != null && fromRuntimeType is RuntimeType)
+ {
+ // fromType is baked. So if this type is not baked, it cannot be assignable to!
+ if (m_bakedRuntimeType == null)
+ return false;
+
+ // since toType is also baked, delegate to the base
+ return m_bakedRuntimeType.IsAssignableFrom(fromRuntimeType);
+ }
+
+ // So if c is not a runtimeType nor TypeBuilder. We don't know how to deal with it.
+ // return false then.
+ if (fromTypeBuilder == null)
+ return false;
+
+ // If fromTypeBuilder is a subclass of this class, then c can be cast to this type.
+ if (fromTypeBuilder.IsSubclassOf(this))
+ return true;
+
+ if (this.IsInterface == false)
+ return false;
+
+ // now is This type a base type on one of the interface impl?
+ Type[] interfaces = fromTypeBuilder.GetInterfaces();
+ for(int i = 0; i < interfaces.Length; i++)
+ {
+ // unfortunately, IsSubclassOf does not cover the case when they are the same type.
+ if (TypeBuilder.IsTypeEqual(interfaces[i], this))
+ return true;
+
+ if (interfaces[i].IsSubclassOf(this))
+ return true;
+ }
+ return false;
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return m_iAttr;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return false;
+ }
+ protected override bool IsByRefImpl()
+ {
+ return false;
+ }
+ protected override bool IsPointerImpl()
+ {
+ return false;
+ }
+ protected override bool IsPrimitiveImpl()
+ {
+ return false;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return((GetAttributeFlagsImpl() & TypeAttributes.Import) != 0) ? true : false;
+ }
+
+ public override Type GetElementType()
+ {
+
+ // You will never have to deal with a TypeBuilder if you are just referring to arrays.
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return false;
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.IsSecurityCritical;
+ }
+ }
+
+ public override bool IsSecuritySafeCritical
+ {
+ get
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.IsSecuritySafeCritical;
+ }
+ }
+
+ public override bool IsSecurityTransparent
+ {
+ get
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return m_bakedRuntimeType.IsSecurityTransparent;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public override bool IsSubclassOf(Type c)
+ {
+ Type p = this;
+
+ if (TypeBuilder.IsTypeEqual(p, c))
+ return false;
+
+ p = p.BaseType;
+
+ while(p != null)
+ {
+ if (TypeBuilder.IsTypeEqual(p, c))
+ return true;
+
+ p = p.BaseType;
+ }
+
+ return false;
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ if (m_bakedRuntimeType != null)
+ return m_bakedRuntimeType;
+
+ if (IsEnum)
+ {
+ if (m_enumUnderlyingType == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoUnderlyingTypeOnEnum"));
+
+ return m_enumUnderlyingType;
+ }
+ else
+ {
+ return this;
+ }
+ }
+ }
+
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType("*", this, 0);
+ }
+
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType("&", this, 0);
+ }
+
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType("[]", this, 0);
+ }
+
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ string szrank = "";
+ if (rank == 1)
+ {
+ szrank = "*";
+ }
+ else
+ {
+ for(int i = 1; i < rank; i++)
+ szrank += ",";
+ }
+
+ string s = String.Format(CultureInfo.InvariantCulture, "[{0}]", szrank); // [,,]
+ return SymbolType.FormCompoundType(s, this, 0);
+ }
+
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+ Contract.EndContractBlock();
+
+ return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, typeof(object) as RuntimeType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(m_bakedRuntimeType, attributeRuntimeType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (!IsCreated())
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_TypeNotYetCreated"));
+
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"caType");
+
+ return CustomAttribute.IsDefined(m_bakedRuntimeType, attributeRuntimeType, inherit);
+ }
+
+ #endregion
+
+ #region Public Member
+
+ #region DefineType
+ public override GenericParameterAttributes GenericParameterAttributes { get { return m_genParamAttributes; } }
+
+ internal void SetInterfaces(params Type[] interfaces)
+ {
+ ThrowIfCreated();
+
+ m_typeInterfaces = new List<Type>();
+ if (interfaces != null)
+ {
+ m_typeInterfaces.AddRange(interfaces);
+ }
+ }
+
+
+ public GenericTypeParameterBuilder[] DefineGenericParameters(params string[] names)
+ {
+ if (names == null)
+ throw new ArgumentNullException("names");
+
+ if (names.Length == 0)
+ throw new ArgumentException();
+ Contract.EndContractBlock();
+
+ for (int i = 0; i < names.Length; i ++)
+ if (names[i] == null)
+ throw new ArgumentNullException("names");
+
+ if (m_inst != null)
+ throw new InvalidOperationException();
+
+ m_inst = new GenericTypeParameterBuilder[names.Length];
+ for(int i = 0; i < names.Length; i ++)
+ m_inst[i] = new GenericTypeParameterBuilder(new TypeBuilder(names[i], i, this));
+
+ return m_inst;
+ }
+
+
+ public override Type MakeGenericType(params Type[] typeArguments)
+ {
+ CheckContext(typeArguments);
+
+ return TypeBuilderInstantiation.MakeGenericType(this, typeArguments);
+ }
+
+ public override Type[] GetGenericArguments() { return m_inst; }
+ // If a TypeBuilder is generic, it must be a generic type definition
+ // All instantiated generic types are TypeBuilderInstantiation.
+ public override bool IsGenericTypeDefinition { get { return IsGenericType; } }
+ public override bool IsGenericType { get { return m_inst != null; } }
+ public override bool IsGenericParameter { get { return m_bIsGenParam; } }
+ public override bool IsConstructedGenericType { get { return false; } }
+
+ public override int GenericParameterPosition { get { return m_genParamPos; } }
+ public override MethodBase DeclaringMethod { get { return m_declMeth; } }
+ public override Type GetGenericTypeDefinition() { if (IsGenericTypeDefinition) return this; if (m_genTypeDef == null) throw new InvalidOperationException(); return m_genTypeDef; }
+ #endregion
+
+ #region Define Method
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DefineMethodOverride(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
+ {
+ lock(SyncRoot)
+ {
+ DefineMethodOverrideNoLock(methodInfoBody, methodInfoDeclaration);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void DefineMethodOverrideNoLock(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration)
+ {
+ if (methodInfoBody == null)
+ throw new ArgumentNullException("methodInfoBody");
+
+ if (methodInfoDeclaration == null)
+ throw new ArgumentNullException("methodInfoDeclaration");
+ Contract.EndContractBlock();
+
+ ThrowIfCreated();
+
+ if (!object.ReferenceEquals(methodInfoBody.DeclaringType, this))
+ // Loader restriction: body method has to be from this class
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_BadMethodImplBody"));
+
+ MethodToken tkBody;
+ MethodToken tkDecl;
+
+ tkBody = m_module.GetMethodTokenInternal(methodInfoBody);
+ tkDecl = m_module.GetMethodTokenInternal(methodInfoDeclaration);
+
+ DefineMethodImpl(m_module.GetNativeHandle(), m_tdType.Token, tkBody.Token, tkDecl.Token);
+ }
+
+ public MethodBuilder DefineMethod(String name, MethodAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineMethod(name, attributes, CallingConventions.Standard, returnType, parameterTypes);
+ }
+
+ public MethodBuilder DefineMethod(String name, MethodAttributes attributes)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineMethod(name, attributes, CallingConventions.Standard, null, null);
+ }
+
+ public MethodBuilder DefineMethod(String name, MethodAttributes attributes, CallingConventions callingConvention)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineMethod(name, attributes, callingConvention, null, null);
+ }
+
+ public MethodBuilder DefineMethod(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] parameterTypes)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ return DefineMethod(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public MethodBuilder DefineMethod(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+
+ lock(SyncRoot)
+ {
+ return DefineMethodNoLock(name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers,
+ returnTypeOptionalCustomModifiers, parameterTypes, parameterTypeRequiredCustomModifiers,
+ parameterTypeOptionalCustomModifiers);
+ }
+ }
+
+ private MethodBuilder DefineMethodNoLock(String name, MethodAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ Contract.Ensures(Contract.Result<MethodBuilder>() != null);
+ Contract.EndContractBlock();
+
+ CheckContext(returnType);
+ CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes);
+ CheckContext(parameterTypeRequiredCustomModifiers);
+ CheckContext(parameterTypeOptionalCustomModifiers);
+
+ if (parameterTypes != null)
+ {
+ if (parameterTypeOptionalCustomModifiers != null && parameterTypeOptionalCustomModifiers.Length != parameterTypes.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "parameterTypeOptionalCustomModifiers", "parameterTypes"));
+
+ if (parameterTypeRequiredCustomModifiers != null && parameterTypeRequiredCustomModifiers.Length != parameterTypes.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MismatchedArrays", "parameterTypeRequiredCustomModifiers", "parameterTypes"));
+ }
+
+ ThrowIfCreated();
+
+ if (!m_isHiddenGlobalType)
+ {
+ if (((m_iAttr & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) &&
+ (attributes & MethodAttributes.Abstract) == 0 &&(attributes & MethodAttributes.Static) == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadAttributeOnInterfaceMethod"));
+ }
+
+ // pass in Method attributes
+ MethodBuilder method = new MethodBuilder(
+ name, attributes, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers,
+ m_module, this, false);
+
+ if (!m_isHiddenGlobalType)
+ {
+ //If this method is declared to be a constructor, increment our constructor count.
+ if ((method.Attributes & MethodAttributes.SpecialName) != 0 && method.Name.Equals(ConstructorInfo.ConstructorName))
+ {
+ m_constructorCount++;
+ }
+ }
+
+ m_listMethods.Add(method);
+
+ return method;
+ }
+
+ #endregion
+
+ #region Define Constructor
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorBuilder DefineTypeInitializer()
+ {
+ lock(SyncRoot)
+ {
+ return DefineTypeInitializerNoLock();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ConstructorBuilder DefineTypeInitializerNoLock()
+ {
+ ThrowIfCreated();
+
+ // change the attributes and the class constructor's name
+ MethodAttributes attr = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.SpecialName;
+
+ ConstructorBuilder constBuilder = new ConstructorBuilder(
+ ConstructorInfo.TypeConstructorName, attr, CallingConventions.Standard, null, m_module, this);
+
+ return constBuilder;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorBuilder DefineDefaultConstructor(MethodAttributes attributes)
+ {
+ if ((m_iAttr & TypeAttributes.Interface) == TypeAttributes.Interface)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConstructorNotAllowedOnInterface"));
+ }
+
+ lock(SyncRoot)
+ {
+ return DefineDefaultConstructorNoLock(attributes);
+ }
+ }
+
+ private ConstructorBuilder DefineDefaultConstructorNoLock(MethodAttributes attributes)
+ {
+ ConstructorBuilder constBuilder;
+
+ // get the parent class's default constructor
+ // We really don't want(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic) here. We really want
+ // constructors visible from the subclass, but that is not currently
+ // available in BindingFlags. This more open binding is open to
+ // runtime binding failures(like if we resolve to a private
+ // constructor).
+ ConstructorInfo con = null;
+
+ if (m_typeParent is TypeBuilderInstantiation)
+ {
+ Type genericTypeDefinition = m_typeParent.GetGenericTypeDefinition();
+
+ if (genericTypeDefinition is TypeBuilder)
+ genericTypeDefinition = ((TypeBuilder)genericTypeDefinition).m_bakedRuntimeType;
+
+ if (genericTypeDefinition == null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_DynamicModule"));
+
+ Type inst = genericTypeDefinition.MakeGenericType(m_typeParent.GetGenericArguments());
+
+ if (inst is TypeBuilderInstantiation)
+ con = TypeBuilder.GetConstructor(inst, genericTypeDefinition.GetConstructor(
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null));
+ else
+ con = inst.GetConstructor(
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
+ }
+
+ if (con == null)
+ {
+ con = m_typeParent.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
+ }
+
+ if (con == null)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NoParentDefaultConstructor"));
+
+ // Define the constructor Builder
+ constBuilder = DefineConstructor(attributes, CallingConventions.Standard, null);
+ m_constructorCount++;
+
+ // generate the code to call the parent's default constructor
+ ILGenerator il = constBuilder.GetILGenerator();
+ il.Emit(OpCodes.Ldarg_0);
+ il.Emit(OpCodes.Call,con);
+ il.Emit(OpCodes.Ret);
+
+ constBuilder.m_isDefaultConstructor = true;
+ return constBuilder;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorBuilder DefineConstructor(MethodAttributes attributes, CallingConventions callingConvention, Type[] parameterTypes)
+ {
+ return DefineConstructor(attributes, callingConvention, parameterTypes, null, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorBuilder DefineConstructor(MethodAttributes attributes, CallingConventions callingConvention,
+ Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ if ((m_iAttr & TypeAttributes.Interface) == TypeAttributes.Interface && (attributes & MethodAttributes.Static) != MethodAttributes.Static)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ConstructorNotAllowedOnInterface"));
+ }
+
+ lock(SyncRoot)
+ {
+ return DefineConstructorNoLock(attributes, callingConvention, parameterTypes, requiredCustomModifiers, optionalCustomModifiers);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ConstructorBuilder DefineConstructorNoLock(MethodAttributes attributes, CallingConventions callingConvention,
+ Type[] parameterTypes, Type[][] requiredCustomModifiers, Type[][] optionalCustomModifiers)
+ {
+ CheckContext(parameterTypes);
+ CheckContext(requiredCustomModifiers);
+ CheckContext(optionalCustomModifiers);
+
+ ThrowIfCreated();
+
+ String name;
+
+ if ((attributes & MethodAttributes.Static) == 0)
+ {
+ name = ConstructorInfo.ConstructorName;
+ }
+ else
+ {
+ name = ConstructorInfo.TypeConstructorName;
+ }
+
+ attributes = attributes | MethodAttributes.SpecialName;
+
+ ConstructorBuilder constBuilder =
+ new ConstructorBuilder(name, attributes, callingConvention,
+ parameterTypes, requiredCustomModifiers, optionalCustomModifiers, m_module, this);
+
+ m_constructorCount++;
+
+ return constBuilder;
+ }
+
+ #endregion
+
+ #region Define PInvoke
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public MethodBuilder DefinePInvokeMethod(String name, String dllName, MethodAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ MethodBuilder method = DefinePInvokeMethodHelper(
+ name, dllName, name, attributes, callingConvention, returnType, null, null,
+ parameterTypes, null, null, nativeCallConv, nativeCharSet);
+ return method;
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ MethodBuilder method = DefinePInvokeMethodHelper(
+ name, dllName, entryName, attributes, callingConvention, returnType, null, null,
+ parameterTypes, null, null, nativeCallConv, nativeCharSet);
+ return method;
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public MethodBuilder DefinePInvokeMethod(String name, String dllName, String entryName, MethodAttributes attributes,
+ CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers,
+ CallingConvention nativeCallConv, CharSet nativeCharSet)
+ {
+ MethodBuilder method = DefinePInvokeMethodHelper(
+ name, dllName, entryName, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers, nativeCallConv, nativeCharSet);
+ return method;
+ }
+
+ #endregion
+
+ #region Define Nested Type
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineNestedType(String name)
+ {
+ lock(SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, TypeAttributes.NestedPrivate, null, null, PackingSize.Unspecified, UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, Type[] interfaces)
+ {
+ lock(SyncRoot)
+ {
+ // Why do we only call CheckContext here? Why don't we call it in the other overloads?
+ CheckContext(parent);
+ CheckContext(interfaces);
+
+ return DefineNestedTypeNoLock(name, attr, parent, interfaces, PackingSize.Unspecified, UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent)
+ {
+ lock(SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, UnspecifiedTypeSize);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr)
+ {
+ lock(SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, attr, null, null, PackingSize.Unspecified, UnspecifiedTypeSize);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, int typeSize)
+ {
+ lock(SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, attr, parent, null, PackingSize.Unspecified, typeSize);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, PackingSize packSize)
+ {
+ lock(SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, attr, parent, null, packSize, UnspecifiedTypeSize);
+ }
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public TypeBuilder DefineNestedType(String name, TypeAttributes attr, Type parent, PackingSize packSize, int typeSize)
+ {
+ lock (SyncRoot)
+ {
+ return DefineNestedTypeNoLock(name, attr, parent, null, packSize, typeSize);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeBuilder DefineNestedTypeNoLock(String name, TypeAttributes attr, Type parent, Type[] interfaces, PackingSize packSize, int typeSize)
+ {
+ return new TypeBuilder(name, attr, parent, interfaces, m_module, packSize, typeSize, this);
+ }
+
+ #endregion
+
+ #region Define Field
+ public FieldBuilder DefineField(String fieldName, Type type, FieldAttributes attributes)
+ {
+ return DefineField(fieldName, type, null, null, attributes);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FieldBuilder DefineField(String fieldName, Type type, Type[] requiredCustomModifiers,
+ Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ lock(SyncRoot)
+ {
+ return DefineFieldNoLock(fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldBuilder DefineFieldNoLock(String fieldName, Type type, Type[] requiredCustomModifiers,
+ Type[] optionalCustomModifiers, FieldAttributes attributes)
+ {
+ ThrowIfCreated();
+ CheckContext(type);
+ CheckContext(requiredCustomModifiers);
+
+ if (m_enumUnderlyingType == null && IsEnum == true)
+ {
+ if ((attributes & FieldAttributes.Static) == 0)
+ {
+ // remember the underlying type for enum type
+ m_enumUnderlyingType = type;
+ }
+ }
+
+ return new FieldBuilder(this, fieldName, type, requiredCustomModifiers, optionalCustomModifiers, attributes);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public FieldBuilder DefineInitializedData(String name, byte[] data, FieldAttributes attributes)
+ {
+ lock(SyncRoot)
+ {
+ return DefineInitializedDataNoLock(name, data, attributes);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldBuilder DefineInitializedDataNoLock(String name, byte[] data, FieldAttributes attributes)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+ Contract.EndContractBlock();
+
+ // This method will define an initialized Data in .sdata.
+ // We will create a fake TypeDef to represent the data with size. This TypeDef
+ // will be the signature for the Field.
+
+ return DefineDataHelper(name, data, data.Length, attributes);
+ }
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ public FieldBuilder DefineUninitializedData(String name, int size, FieldAttributes attributes)
+ {
+ lock(SyncRoot)
+ {
+ return DefineUninitializedDataNoLock(name, size, attributes);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldBuilder DefineUninitializedDataNoLock(String name, int size, FieldAttributes attributes)
+ {
+ // This method will define an uninitialized Data in .sdata.
+ // We will create a fake TypeDef to represent the data with size. This TypeDef
+ // will be the signature for the Field.
+ return DefineDataHelper(name, null, size, attributes);
+ }
+
+ #endregion
+
+ #region Define Properties and Events
+ public PropertyBuilder DefineProperty(String name, PropertyAttributes attributes, Type returnType, Type[] parameterTypes)
+ {
+ return DefineProperty(name, attributes, returnType, null, null, parameterTypes, null, null);
+ }
+
+ public PropertyBuilder DefineProperty(String name, PropertyAttributes attributes,
+ CallingConventions callingConvention, Type returnType, Type[] parameterTypes)
+ {
+ return DefineProperty(name, attributes, callingConvention, returnType, null, null, parameterTypes, null, null);
+ }
+
+
+ public PropertyBuilder DefineProperty(String name, PropertyAttributes attributes,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ return DefineProperty(name, attributes, (CallingConventions)0, returnType,
+ returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public PropertyBuilder DefineProperty(String name, PropertyAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ lock(SyncRoot)
+ {
+ return DefinePropertyNoLock(name, attributes, callingConvention, returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private PropertyBuilder DefinePropertyNoLock(String name, PropertyAttributes attributes, CallingConventions callingConvention,
+ Type returnType, Type[] returnTypeRequiredCustomModifiers, Type[] returnTypeOptionalCustomModifiers,
+ Type[] parameterTypes, Type[][] parameterTypeRequiredCustomModifiers, Type[][] parameterTypeOptionalCustomModifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ Contract.EndContractBlock();
+
+ CheckContext(returnType);
+ CheckContext(returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypes);
+ CheckContext(parameterTypeRequiredCustomModifiers);
+ CheckContext(parameterTypeOptionalCustomModifiers);
+
+ SignatureHelper sigHelper;
+ int sigLength;
+ byte[] sigBytes;
+
+ ThrowIfCreated();
+
+ // get the signature in SignatureHelper form
+ sigHelper = SignatureHelper.GetPropertySigHelper(
+ m_module, callingConvention,
+ returnType, returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers,
+ parameterTypes, parameterTypeRequiredCustomModifiers, parameterTypeOptionalCustomModifiers);
+
+ // get the signature in byte form
+ sigBytes = sigHelper.InternalGetSignature(out sigLength);
+
+ PropertyToken prToken = new PropertyToken(DefineProperty(
+ m_module.GetNativeHandle(),
+ m_tdType.Token,
+ name,
+ attributes,
+ sigBytes,
+ sigLength));
+
+ // create the property builder now.
+ return new PropertyBuilder(
+ m_module,
+ name,
+ sigHelper,
+ attributes,
+ returnType,
+ prToken,
+ this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public EventBuilder DefineEvent(String name, EventAttributes attributes, Type eventtype)
+ {
+ lock(SyncRoot)
+ {
+ return DefineEventNoLock(name, attributes, eventtype);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private EventBuilder DefineEventNoLock(String name, EventAttributes attributes, Type eventtype)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ if (name[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Argument_IllegalName"), "name");
+ Contract.EndContractBlock();
+
+ int tkType;
+ EventToken evToken;
+
+ CheckContext(eventtype);
+
+ ThrowIfCreated();
+
+ tkType = m_module.GetTypeTokenInternal( eventtype ).Token;
+
+ // Internal helpers to define property records
+ evToken = new EventToken(DefineEvent(
+ m_module.GetNativeHandle(),
+ m_tdType.Token,
+ name,
+ attributes,
+ tkType));
+
+ // create the property builder now.
+ return new EventBuilder(
+ m_module,
+ name,
+ attributes,
+ //tkType,
+ this,
+ evToken);
+ }
+
+ #endregion
+
+ #region Create Type
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public TypeInfo CreateTypeInfo()
+ {
+ lock (SyncRoot)
+ {
+ return CreateTypeNoLock();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Type CreateType()
+ {
+ lock (SyncRoot)
+ {
+ return CreateTypeNoLock();
+ }
+ }
+
+ internal void CheckContext(params Type[][] typess)
+ {
+ m_module.CheckContext(typess);
+ }
+ internal void CheckContext(params Type[] types)
+ {
+ m_module.CheckContext(types);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeInfo CreateTypeNoLock()
+ {
+ if (IsCreated())
+ return m_bakedRuntimeType;
+
+ ThrowIfCreated();
+
+ if (m_typeInterfaces == null)
+ m_typeInterfaces = new List<Type>();
+
+ int[] interfaceTokens = new int[m_typeInterfaces.Count];
+ for(int i = 0; i < m_typeInterfaces.Count; i++)
+ {
+ interfaceTokens[i] = m_module.GetTypeTokenInternal(m_typeInterfaces[i]).Token;
+ }
+
+ int tkParent = 0;
+ if (m_typeParent != null)
+ tkParent = m_module.GetTypeTokenInternal(m_typeParent).Token;
+
+ if (IsGenericParameter)
+ {
+ int[] constraints; // Array of token constrains terminated by null token
+
+ if (m_typeParent != null)
+ {
+ constraints = new int[m_typeInterfaces.Count + 2];
+ constraints[constraints.Length - 2] = tkParent;
+ }
+ else
+ {
+ constraints = new int[m_typeInterfaces.Count + 1];
+ }
+
+ for (int i = 0; i < m_typeInterfaces.Count; i++)
+ {
+ constraints[i] = m_module.GetTypeTokenInternal(m_typeInterfaces[i]).Token;
+ }
+
+ int declMember = m_declMeth == null ? m_DeclaringType.m_tdType.Token : m_declMeth.GetToken().Token;
+ m_tdType = new TypeToken(DefineGenericParam(m_module.GetNativeHandle(),
+ m_strName, declMember, m_genParamAttributes, m_genParamPos, constraints));
+
+ if (m_ca != null)
+ {
+ foreach (CustAttr ca in m_ca)
+ ca.Bake(m_module, MetadataTokenInternal);
+ }
+
+ m_hasBeenCreated = true;
+
+ // Baking a generic parameter does not put sufficient information into the metadata to actually be able to load it as a type,
+ // the associated generic type/method needs to be baked first. So we return this rather than the baked type.
+ return this;
+ }
+ else
+ {
+ // Check for global typebuilder
+ if (((m_tdType.Token & 0x00FFFFFF) != 0) && ((tkParent & 0x00FFFFFF) != 0))
+ SetParentType(m_module.GetNativeHandle(), m_tdType.Token, tkParent);
+
+ if (m_inst != null)
+ foreach (Type tb in m_inst)
+ if (tb is GenericTypeParameterBuilder)
+ ((GenericTypeParameterBuilder)tb).m_type.CreateType();
+ }
+
+ byte [] body;
+ MethodAttributes methodAttrs;
+
+ if (!m_isHiddenGlobalType)
+ {
+ // create a public default constructor if this class has no constructor.
+ // except if the type is Interface, ValueType, Enum, or a static class.
+ if (m_constructorCount == 0 && ((m_iAttr & TypeAttributes.Interface) == 0) && !IsValueType && ((m_iAttr & (TypeAttributes.Abstract | TypeAttributes.Sealed)) != (TypeAttributes.Abstract | TypeAttributes.Sealed)))
+ {
+ DefineDefaultConstructor(MethodAttributes.Public);
+ }
+ }
+
+ int size = m_listMethods.Count;
+
+ for(int i = 0; i < size; i++)
+ {
+ MethodBuilder meth = m_listMethods[i];
+
+
+ if (meth.IsGenericMethodDefinition)
+ meth.GetToken(); // Doubles as "CreateMethod" for MethodBuilder -- analagous to CreateType()
+
+ methodAttrs = meth.Attributes;
+
+ // Any of these flags in the implemenation flags is set, we will not attach the IL method body
+ if (((meth.GetMethodImplementationFlags() &(MethodImplAttributes.CodeTypeMask|MethodImplAttributes.PreserveSig|MethodImplAttributes.Unmanaged)) != MethodImplAttributes.IL) ||
+ ((methodAttrs & MethodAttributes.PinvokeImpl) !=(MethodAttributes) 0))
+ {
+ continue;
+ }
+
+ int sigLength;
+ byte[] localSig = meth.GetLocalSignature(out sigLength);
+
+ // Check that they haven't declared an abstract method on a non-abstract class
+ if (((methodAttrs & MethodAttributes.Abstract) != 0) &&((m_iAttr & TypeAttributes.Abstract) == 0))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadTypeAttributesNotAbstract"));
+ }
+
+ body = meth.GetBody();
+
+ // If this is an abstract method or an interface, we don't need to set the IL.
+
+ if ((methodAttrs & MethodAttributes.Abstract) != 0)
+ {
+ // We won't check on Interface because we can have class static initializer on interface.
+ // We will just let EE or validator to catch the problem.
+
+ //((m_iAttr & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface))
+
+ if (body != null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadMethodBody"));
+ }
+ else if (body == null || body.Length == 0)
+ {
+ // If it's not an abstract or an interface, set the IL.
+ if (meth.m_ilGenerator != null)
+ {
+ // we need to bake the method here.
+ meth.CreateMethodBodyHelper(meth.GetILGenerator());
+ }
+
+ body = meth.GetBody();
+
+ if ((body == null || body.Length == 0) && !meth.m_canBeRuntimeImpl)
+ throw new InvalidOperationException(
+ Environment.GetResourceString("InvalidOperation_BadEmptyMethodBody", meth.Name) );
+ }
+
+ int maxStack = meth.GetMaxStack();
+
+ ExceptionHandler[] exceptions = meth.GetExceptionHandlers();
+ int[] tokenFixups = meth.GetTokenFixups();
+
+ SetMethodIL(m_module.GetNativeHandle(), meth.GetToken().Token, meth.InitLocals,
+ body, (body != null) ? body.Length : 0,
+ localSig, sigLength, maxStack,
+ exceptions, (exceptions != null) ? exceptions.Length : 0,
+ tokenFixups, (tokenFixups != null) ? tokenFixups.Length : 0);
+
+ if (m_module.ContainingAssemblyBuilder.m_assemblyData.m_access == AssemblyBuilderAccess.Run)
+ {
+ // if we don't need the data structures to build the method any more
+ // throw them away.
+ meth.ReleaseBakedStructures();
+ }
+ }
+
+ m_hasBeenCreated = true;
+
+ // Terminate the process.
+ RuntimeType cls = null;
+ TermCreateClass(m_module.GetNativeHandle(), m_tdType.Token, JitHelpers.GetObjectHandleOnStack(ref cls));
+
+ if (!m_isHiddenGlobalType)
+ {
+ m_bakedRuntimeType = cls;
+
+ // if this type is a nested type, we need to invalidate the cached nested runtime type on the nesting type
+ if (m_DeclaringType != null && m_DeclaringType.m_bakedRuntimeType != null)
+ {
+ m_DeclaringType.m_bakedRuntimeType.InvalidateCachedNestedType();
+ }
+
+ return cls;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ #endregion
+
+ #region Misc
+ public int Size
+ {
+ get { return m_iTypeSize; }
+ }
+
+ public PackingSize PackingSize
+ {
+ get { return m_iPackingSize; }
+ }
+
+ public void SetParent(Type parent)
+ {
+ ThrowIfCreated();
+
+ if (parent != null)
+ {
+ CheckContext(parent);
+
+ if (parent.IsInterface)
+ throw new ArgumentException(Environment.GetResourceString("Argument_CannotSetParentToInterface"));
+
+ m_typeParent = parent;
+ }
+ else
+ {
+ if ((m_iAttr & TypeAttributes.Interface) != TypeAttributes.Interface)
+ {
+ m_typeParent = typeof(Object);
+ }
+ else
+ {
+ if ((m_iAttr & TypeAttributes.Abstract) == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadInterfaceNotAbstract"));
+
+ // there is no extends for interface class
+ m_typeParent = null;
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void AddInterfaceImplementation(Type interfaceType)
+ {
+ if (interfaceType == null)
+ {
+ throw new ArgumentNullException("interfaceType");
+ }
+ Contract.EndContractBlock();
+
+ CheckContext(interfaceType);
+
+ ThrowIfCreated();
+
+ TypeToken tkInterface = m_module.GetTypeTokenInternal(interfaceType);
+ AddInterfaceImpl(m_module.GetNativeHandle(), m_tdType.Token, tkInterface.Token);
+
+ m_typeInterfaces.Add(interfaceType);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddDeclarativeSecurity(SecurityAction action, PermissionSet pset)
+ {
+ lock(SyncRoot)
+ {
+ AddDeclarativeSecurityNoLock(action, pset);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void AddDeclarativeSecurityNoLock(SecurityAction action, PermissionSet pset)
+ {
+ if (pset == null)
+ throw new ArgumentNullException("pset");
+
+#pragma warning disable 618
+ if (!Enum.IsDefined(typeof(SecurityAction), action) ||
+ action == SecurityAction.RequestMinimum ||
+ action == SecurityAction.RequestOptional ||
+ action == SecurityAction.RequestRefuse)
+ {
+ throw new ArgumentOutOfRangeException("action");
+ }
+#pragma warning restore 618
+
+ Contract.EndContractBlock();
+
+ ThrowIfCreated();
+
+ // Translate permission set into serialized format(uses standard binary serialization format).
+ byte[] blob = null;
+ int length = 0;
+ if (!pset.IsEmpty())
+ {
+ blob = pset.EncodeXml();
+ length = blob.Length;
+ }
+
+ // Write the blob into the metadata.
+ AddDeclarativeSecurity(m_module.GetNativeHandle(), m_tdType.Token, action, blob, length);
+ }
+#endif // FEATURE_CAS_POLICY
+
+public TypeToken TypeToken
+ {
+ get
+ {
+ if (IsGenericParameter)
+ ThrowIfCreated();
+
+ return m_tdType;
+ }
+ }
+
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
+ {
+ if (con == null)
+ throw new ArgumentNullException("con");
+
+ if (binaryAttribute == null)
+ throw new ArgumentNullException("binaryAttribute");
+ Contract.EndContractBlock();
+
+ TypeBuilder.DefineCustomAttribute(m_module, m_tdType.Token, ((ModuleBuilder)m_module).GetConstructorToken(con).Token,
+ binaryAttribute, false, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
+ {
+ if (customBuilder == null)
+ throw new ArgumentNullException("customBuilder");
+ Contract.EndContractBlock();
+
+ customBuilder.CreateCustomAttribute((ModuleBuilder)m_module, m_tdType.Token);
+ }
+
+ #endregion
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _TypeBuilder.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _TypeBuilder.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _TypeBuilder.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _TypeBuilder.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs b/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs
new file mode 100644
index 0000000000..13b98b6543
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs
@@ -0,0 +1,276 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class TypeBuilderInstantiation : TypeInfo
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ #region Static Members
+ internal static Type MakeGenericType(Type type, Type[] typeArguments)
+ {
+ Contract.Requires(type != null, "this is only called from RuntimeType.MakeGenericType and TypeBuilder.MakeGenericType so 'type' cannot be null");
+
+ if (!type.IsGenericTypeDefinition)
+ throw new InvalidOperationException();
+
+ if (typeArguments == null)
+ throw new ArgumentNullException("typeArguments");
+ Contract.EndContractBlock();
+
+ foreach (Type t in typeArguments)
+ {
+ if (t == null)
+ throw new ArgumentNullException("typeArguments");
+ }
+
+ return new TypeBuilderInstantiation(type, typeArguments);
+ }
+
+ #endregion
+
+ #region Private Data Mebers
+ private Type m_type;
+ private Type[] m_inst;
+ private string m_strFullQualName;
+ internal Hashtable m_hashtable = new Hashtable();
+
+ #endregion
+
+ #region Constructor
+ private TypeBuilderInstantiation(Type type, Type[] inst)
+ {
+ m_type = type;
+ m_inst = inst;
+ m_hashtable = new Hashtable();
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.ToString);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override Type DeclaringType { get { return m_type.DeclaringType; } }
+
+ public override Type ReflectedType { get { return m_type.ReflectedType; } }
+
+ public override String Name { get { return m_type.Name; } }
+
+ public override Module Module { get { return m_type.Module; } }
+ #endregion
+
+ #region Type Overrides
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType("*", this, 0);
+ }
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType("&", this, 0);
+ }
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType("[]", this, 0);
+ }
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ string comma = "";
+ for(int i = 1; i < rank; i++)
+ comma += ",";
+
+ string s = String.Format(CultureInfo.InvariantCulture, "[{0}]", comma);
+ return SymbolType.FormCompoundType(s, this, 0);
+ }
+ public override Guid GUID { get { throw new NotSupportedException(); } }
+ public override Object InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParameters) { throw new NotSupportedException(); }
+ public override Assembly Assembly { get { return m_type.Assembly; } }
+ public override RuntimeTypeHandle TypeHandle { get { throw new NotSupportedException(); } }
+ public override String FullName
+ {
+ get
+ {
+ if (m_strFullQualName == null)
+ m_strFullQualName = TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
+ return m_strFullQualName;
+ }
+ }
+ public override String Namespace { get { return m_type.Namespace; } }
+ public override String AssemblyQualifiedName { get { return TypeNameBuilder.ToString(this, TypeNameBuilder.Format.AssemblyQualifiedName); } }
+ private Type Substitute(Type[] substitutes)
+ {
+ Type[] inst = GetGenericArguments();
+ Type[] instSubstituted = new Type[inst.Length];
+
+ for (int i = 0; i < instSubstituted.Length; i++)
+ {
+ Type t = inst[i];
+
+ if (t is TypeBuilderInstantiation)
+ {
+ instSubstituted[i] = (t as TypeBuilderInstantiation).Substitute(substitutes);
+ }
+ else if (t is GenericTypeParameterBuilder)
+ {
+ // Substitute
+ instSubstituted[i] = substitutes[t.GenericParameterPosition];
+ }
+ else
+ {
+ instSubstituted[i] = t;
+ }
+ }
+
+ return GetGenericTypeDefinition().MakeGenericType(instSubstituted);
+ }
+ public override Type BaseType
+ {
+ // B<A,B,C>
+ // D<T,S> : B<S,List<T>,char>
+
+ // D<string,int> : B<int,List<string>,char>
+ // D<S,T> : B<T,List<S>,char>
+ // D<S,string> : B<string,List<S>,char>
+ get
+ {
+ Type typeBldrBase = m_type.BaseType;
+
+ if (typeBldrBase == null)
+ return null;
+
+ TypeBuilderInstantiation typeBldrBaseAs = typeBldrBase as TypeBuilderInstantiation;
+
+ if (typeBldrBaseAs == null)
+ return typeBldrBase;
+
+ return typeBldrBaseAs.Substitute(GetGenericArguments());
+ }
+ }
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ protected override MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override Type GetInterface(String name, bool ignoreCase) { throw new NotSupportedException(); }
+ public override Type[] GetInterfaces() { throw new NotSupportedException(); }
+ public override EventInfo GetEvent(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override EventInfo[] GetEvents() { throw new NotSupportedException(); }
+ protected override PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) { throw new NotSupportedException(); }
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override Type GetNestedType(String name, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr) { throw new NotSupportedException(); }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType) { throw new NotSupportedException(); }
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { throw new NotSupportedException(); }
+ protected override TypeAttributes GetAttributeFlagsImpl() { return m_type.Attributes; }
+ protected override bool IsArrayImpl() { return false; }
+ protected override bool IsByRefImpl() { return false; }
+ protected override bool IsPointerImpl() { return false; }
+ protected override bool IsPrimitiveImpl() { return false; }
+ protected override bool IsCOMObjectImpl() { return false; }
+ public override Type GetElementType() { throw new NotSupportedException(); }
+ protected override bool HasElementTypeImpl() { return false; }
+ public override Type UnderlyingSystemType { get { return this; } }
+ public override Type[] GetGenericArguments() { return m_inst; }
+ public override bool IsGenericTypeDefinition { get { return false; } }
+ public override bool IsGenericType { get { return true; } }
+ public override bool IsConstructedGenericType { get { return true; } }
+ public override bool IsGenericParameter { get { return false; } }
+ public override int GenericParameterPosition { get { throw new InvalidOperationException(); } }
+ protected override bool IsValueTypeImpl() { return m_type.IsValueType; }
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ for (int i = 0; i < m_inst.Length; i++)
+ {
+ if (m_inst[i].ContainsGenericParameters)
+ return true;
+ }
+
+ return false;
+ }
+ }
+ public override MethodBase DeclaringMethod { get { return null; } }
+ public override Type GetGenericTypeDefinition() { return m_type; }
+ public override Type MakeGenericType(params Type[] inst) { throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericTypeDefinition")); }
+ public override bool IsAssignableFrom(Type c) { throw new NotSupportedException(); }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public override bool IsSubclassOf(Type c)
+ {
+ throw new NotSupportedException();
+ }
+ #endregion
+
+ #region ICustomAttributeProvider Implementation
+ public override Object[] GetCustomAttributes(bool inherit) { throw new NotSupportedException(); }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { throw new NotSupportedException(); }
+
+ public override bool IsDefined(Type attributeType, bool inherit) { throw new NotSupportedException(); }
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/TypeToken.cs b/src/mscorlib/src/System/Reflection/Emit/TypeToken.cs
new file mode 100644
index 0000000000..228755641c
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/TypeToken.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Represents a Class to the ILGenerator class.
+**
+**
+===========================================================*/
+namespace System.Reflection.Emit {
+
+ using System;
+ using System.Reflection;
+ using System.Threading;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct TypeToken {
+
+ public static readonly TypeToken Empty = new TypeToken();
+
+ internal int m_class;
+
+#if false
+ public TypeToken() {
+ m_class=0;
+ }
+#endif
+
+ internal TypeToken(int str) {
+ m_class=str;
+ }
+
+ public int Token {
+ get { return m_class; }
+ }
+
+ public override int GetHashCode()
+ {
+ return m_class;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is TypeToken)
+ return Equals((TypeToken)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(TypeToken obj)
+ {
+ return obj.m_class == m_class;
+ }
+
+ public static bool operator ==(TypeToken a, TypeToken b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(TypeToken a, TypeToken b)
+ {
+ return !(a == b);
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs b/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs
new file mode 100644
index 0000000000..09eac3a272
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/UnmanagedMarshal.cs
@@ -0,0 +1,184 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection.Emit
+{
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Security.Permissions;
+
+ // This class is describing the fieldmarshal.
+ [Serializable]
+ [HostProtection(MayLeakOnAbort = true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Obsolete("An alternate API is available: Emit the MarshalAs custom attribute instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public sealed class UnmanagedMarshal
+ {
+ /******************************
+[System.Runtime.InteropServices.ComVisible(true)]
+ * public static constructors. You can only construct
+ * UnmanagedMarshal using these static constructors.
+ ******************************/
+ public static UnmanagedMarshal DefineUnmanagedMarshal(UnmanagedType unmanagedType)
+ {
+ if (unmanagedType == UnmanagedType.ByValTStr ||
+ unmanagedType == UnmanagedType.SafeArray ||
+ unmanagedType == UnmanagedType.CustomMarshaler ||
+ unmanagedType == UnmanagedType.ByValArray ||
+ unmanagedType == UnmanagedType.LPArray)
+ {
+ // not a simple native marshal
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotASimpleNativeType"));
+ }
+ return new UnmanagedMarshal(unmanagedType, Guid.Empty, 0, (UnmanagedType) 0);
+ }
+ public static UnmanagedMarshal DefineByValTStr(int elemCount)
+ {
+ return new UnmanagedMarshal(UnmanagedType.ByValTStr, Guid.Empty, elemCount, (UnmanagedType) 0);
+ }
+
+ public static UnmanagedMarshal DefineSafeArray(UnmanagedType elemType)
+ {
+ return new UnmanagedMarshal(UnmanagedType.SafeArray, Guid.Empty, 0, elemType);
+ }
+
+ public static UnmanagedMarshal DefineByValArray(int elemCount)
+ {
+ return new UnmanagedMarshal(UnmanagedType.ByValArray, Guid.Empty, elemCount, (UnmanagedType) 0);
+ }
+
+ public static UnmanagedMarshal DefineLPArray(UnmanagedType elemType)
+ {
+ return new UnmanagedMarshal(UnmanagedType.LPArray, Guid.Empty, 0, elemType);
+ }
+
+
+
+
+
+
+ // accessor function for the native type
+ public UnmanagedType GetUnmanagedType
+ {
+ get { return m_unmanagedType; }
+ }
+
+ public Guid IIDGuid
+ {
+ get
+ {
+ if (m_unmanagedType == UnmanagedType.CustomMarshaler)
+ return m_guid;
+
+ // throw exception here. There is Guid only if CustomMarshaler
+ throw new ArgumentException(Environment.GetResourceString("Argument_NotACustomMarshaler"));
+ }
+ }
+ public int ElementCount
+ {
+ get
+ {
+ if (m_unmanagedType != UnmanagedType.ByValArray &&
+ m_unmanagedType != UnmanagedType.ByValTStr)
+ {
+ // throw exception here. There is NumElement only if NativeTypeFixedArray
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoUnmanagedElementCount"));
+ }
+ return m_numElem;
+ }
+ }
+ public UnmanagedType BaseType
+ {
+ get
+ {
+ if (m_unmanagedType != UnmanagedType.LPArray && m_unmanagedType != UnmanagedType.SafeArray)
+ {
+ // throw exception here. There is NestedUnmanagedType only if LPArray or SafeArray
+ throw new ArgumentException(Environment.GetResourceString("Argument_NoNestedMarshal"));
+ }
+ return m_baseType;
+ }
+ }
+
+ private UnmanagedMarshal(UnmanagedType unmanagedType, Guid guid, int numElem, UnmanagedType type)
+ {
+ m_unmanagedType = unmanagedType;
+ m_guid = guid;
+ m_numElem = numElem;
+ m_baseType = type;
+ }
+
+ /************************
+ *
+ * Data member
+ *
+ *************************/
+ internal UnmanagedType m_unmanagedType;
+ internal Guid m_guid;
+ internal int m_numElem;
+ internal UnmanagedType m_baseType;
+
+
+ /************************
+ * this function return the byte representation of the marshal info.
+ *************************/
+ internal byte[] InternalGetBytes()
+ {
+ byte[] buf;
+ if (m_unmanagedType == UnmanagedType.SafeArray || m_unmanagedType == UnmanagedType.LPArray)
+ {
+
+ // syntax for NativeTypeSafeArray is
+ // <SafeArray | LPArray> <base type>
+ //
+ int cBuf = 2;
+ buf = new byte[cBuf];
+ buf[0] = (byte) (m_unmanagedType);
+ buf[1] = (byte) (m_baseType);
+ return buf;
+ }
+ else
+ if (m_unmanagedType == UnmanagedType.ByValArray ||
+ m_unmanagedType == UnmanagedType.ByValTStr)
+ {
+ // <ByValArray | ByValTStr> <encoded integer>
+ //
+ int cBuf;
+ int iBuf = 0;
+
+ if (m_numElem <= 0x7f)
+ cBuf = 1;
+ else if (m_numElem <= 0x3FFF)
+ cBuf = 2;
+ else
+ cBuf = 4;
+
+ // the total buffer size is the one byte + encoded integer size
+ cBuf = cBuf + 1;
+ buf = new byte[cBuf];
+
+
+ buf[iBuf++] = (byte) (m_unmanagedType);
+ if (m_numElem <= 0x7F)
+ {
+ buf[iBuf++] = (byte)(m_numElem & 0xFF);
+ } else if (m_numElem <= 0x3FFF)
+ {
+ buf[iBuf++] = (byte)((m_numElem >> 8) | 0x80);
+ buf[iBuf++] = (byte)(m_numElem & 0xFF);
+ } else if (m_numElem <= 0x1FFFFFFF)
+ {
+ buf[iBuf++] = (byte)((m_numElem >> 24) | 0xC0);
+ buf[iBuf++] = (byte)((m_numElem >> 16) & 0xFF);
+ buf[iBuf++] = (byte)((m_numElem >> 8) & 0xFF);
+ buf[iBuf++] = (byte)((m_numElem) & 0xFF);
+ }
+ return buf;
+ }
+ buf = new byte[1];
+ buf[0] = (byte) (m_unmanagedType);
+ return buf;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs b/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs
new file mode 100644
index 0000000000..5b36e0e372
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Emit/XXXOnTypeBuilderInstantiation.cs
@@ -0,0 +1,331 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection.Emit
+{
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class MethodOnTypeBuilderInstantiation : MethodInfo
+ {
+ #region Private Static Members
+ internal static MethodInfo GetMethod(MethodInfo method, TypeBuilderInstantiation type)
+ {
+ return new MethodOnTypeBuilderInstantiation(method, type);
+ }
+ #endregion
+
+ #region Private Data Mebers
+ internal MethodInfo m_method;
+ private TypeBuilderInstantiation m_type;
+ #endregion
+
+ #region Constructor
+ internal MethodOnTypeBuilderInstantiation(MethodInfo method, TypeBuilderInstantiation type)
+ {
+ Contract.Assert(method is MethodBuilder || method is RuntimeMethodInfo);
+
+ m_method = method;
+ m_type = type;
+ }
+ #endregion
+
+ internal override Type[] GetParameterTypes()
+ {
+ return m_method.GetParameterTypes();
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return m_method.MemberType; } }
+ public override String Name { get { return m_method.Name; } }
+ public override Type DeclaringType { get { return m_type; } }
+ public override Type ReflectedType { get { return m_type; } }
+ public override Object[] GetCustomAttributes(bool inherit) { return m_method.GetCustomAttributes(inherit); }
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { return m_method.GetCustomAttributes(attributeType, inherit); }
+ public override bool IsDefined(Type attributeType, bool inherit) { return m_method.IsDefined(attributeType, inherit); }
+ internal int MetadataTokenInternal
+ {
+ get
+ {
+ MethodBuilder mb = m_method as MethodBuilder;
+
+ if (mb != null)
+ return mb.MetadataTokenInternal;
+ else
+ {
+ Contract.Assert(m_method is RuntimeMethodInfo);
+ return m_method.MetadataToken;
+ }
+ }
+ }
+ public override Module Module { get { return m_method.Module; } }
+ public new Type GetType() { return base.GetType(); }
+ #endregion
+
+ #region MethodBase Members
+ [Pure]
+ public override ParameterInfo[] GetParameters() { return m_method.GetParameters(); }
+ public override MethodImplAttributes GetMethodImplementationFlags() { return m_method.GetMethodImplementationFlags(); }
+ public override RuntimeMethodHandle MethodHandle { get { return m_method.MethodHandle; } }
+ public override MethodAttributes Attributes { get { return m_method.Attributes; } }
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ public override CallingConventions CallingConvention { get { return m_method.CallingConvention; } }
+ public override Type [] GetGenericArguments() { return m_method.GetGenericArguments(); }
+ public override MethodInfo GetGenericMethodDefinition() { return m_method; }
+ public override bool IsGenericMethodDefinition { get { return m_method.IsGenericMethodDefinition; } }
+ public override bool ContainsGenericParameters { get { return m_method.ContainsGenericParameters; } }
+ public override MethodInfo MakeGenericMethod(params Type[] typeArgs)
+ {
+ if (!IsGenericMethodDefinition)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericMethodDefinition"));
+ Contract.EndContractBlock();
+
+ return MethodBuilderInstantiation.MakeGenericMethod(this, typeArgs);
+ }
+
+ public override bool IsGenericMethod { get { return m_method.IsGenericMethod; } }
+
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public override Type ReturnType { get { return m_method.ReturnType; } }
+ public override ParameterInfo ReturnParameter { get { throw new NotSupportedException(); } }
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes { get { throw new NotSupportedException(); } }
+ public override MethodInfo GetBaseDefinition() { throw new NotSupportedException(); }
+ #endregion
+ }
+
+ internal sealed class ConstructorOnTypeBuilderInstantiation : ConstructorInfo
+ {
+ #region Private Static Members
+ internal static ConstructorInfo GetConstructor(ConstructorInfo Constructor, TypeBuilderInstantiation type)
+ {
+ return new ConstructorOnTypeBuilderInstantiation(Constructor, type);
+ }
+ #endregion
+
+ #region Private Data Mebers
+ internal ConstructorInfo m_ctor;
+ private TypeBuilderInstantiation m_type;
+ #endregion
+
+ #region Constructor
+ internal ConstructorOnTypeBuilderInstantiation(ConstructorInfo constructor, TypeBuilderInstantiation type)
+ {
+ Contract.Assert(constructor is ConstructorBuilder || constructor is RuntimeConstructorInfo);
+
+ m_ctor = constructor;
+ m_type = type;
+ }
+ #endregion
+
+ internal override Type[] GetParameterTypes()
+ {
+ return m_ctor.GetParameterTypes();
+ }
+
+ internal override Type GetReturnType()
+ {
+ return DeclaringType;
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return m_ctor.MemberType; } }
+ public override String Name { get { return m_ctor.Name; } }
+ public override Type DeclaringType { get { return m_type; } }
+ public override Type ReflectedType { get { return m_type; } }
+ public override Object[] GetCustomAttributes(bool inherit) { return m_ctor.GetCustomAttributes(inherit); }
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { return m_ctor.GetCustomAttributes(attributeType, inherit); }
+ public override bool IsDefined(Type attributeType, bool inherit) { return m_ctor.IsDefined(attributeType, inherit); }
+ internal int MetadataTokenInternal
+ {
+ get
+ {
+ ConstructorBuilder cb = m_ctor as ConstructorBuilder;
+
+ if (cb != null)
+ return cb.MetadataTokenInternal;
+ else
+ {
+ Contract.Assert(m_ctor is RuntimeConstructorInfo);
+ return m_ctor.MetadataToken;
+ }
+ }
+ }
+ public override Module Module { get { return m_ctor.Module; } }
+ public new Type GetType() { return base.GetType(); }
+ #endregion
+
+ #region MethodBase Members
+ [Pure]
+ public override ParameterInfo[] GetParameters() { return m_ctor.GetParameters(); }
+ public override MethodImplAttributes GetMethodImplementationFlags() { return m_ctor.GetMethodImplementationFlags(); }
+ public override RuntimeMethodHandle MethodHandle { get { return m_ctor.MethodHandle; } }
+ public override MethodAttributes Attributes { get { return m_ctor.Attributes; } }
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+ public override CallingConventions CallingConvention { get { return m_ctor.CallingConvention; } }
+ public override Type[] GetGenericArguments() { return m_ctor.GetGenericArguments(); }
+ public override bool IsGenericMethodDefinition { get { return false; } }
+ public override bool ContainsGenericParameters { get { return false; } }
+
+ public override bool IsGenericMethod { get { return false; } }
+ #endregion
+
+ #region ConstructorInfo Members
+ public override Object Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ throw new InvalidOperationException();
+ }
+ #endregion
+ }
+
+ internal sealed class FieldOnTypeBuilderInstantiation : FieldInfo
+ {
+ #region Private Static Members
+ internal static FieldInfo GetField(FieldInfo Field, TypeBuilderInstantiation type)
+ {
+ FieldInfo m = null;
+
+ // This ifdef was introduced when non-generic collections were pulled from
+ // silverlight. See code:Dictionary#DictionaryVersusHashtableThreadSafety
+ // for information about this change.
+ //
+ // There is a pre-existing race condition in this code with the side effect
+ // that the second thread's value clobbers the first in the hashtable. This is
+ // an acceptable race condition since we make no guarantees that this will return the
+ // same object.
+ //
+ // We're not entirely sure if this cache helps any specific scenarios, so
+ // long-term, one could investigate whether it's needed. In any case, this
+ // method isn't expected to be on any critical paths for performance.
+ if (type.m_hashtable.Contains(Field)) {
+ m = type.m_hashtable[Field] as FieldInfo;
+ }
+ else {
+ m = new FieldOnTypeBuilderInstantiation(Field, type);
+ type.m_hashtable[Field] = m;
+ }
+
+ return m;
+ }
+ #endregion
+
+ #region Private Data Members
+ private FieldInfo m_field;
+ private TypeBuilderInstantiation m_type;
+ #endregion
+
+ #region Constructor
+ internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiation type)
+ {
+ Contract.Assert(field is FieldBuilder || field is RuntimeFieldInfo);
+
+ m_field = field;
+ m_type = type;
+ }
+ #endregion
+
+ internal FieldInfo FieldInfo { get { return m_field; } }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Field; } }
+ public override String Name { get { return m_field.Name; } }
+ public override Type DeclaringType { get { return m_type; } }
+ public override Type ReflectedType { get { return m_type; } }
+ public override Object[] GetCustomAttributes(bool inherit) { return m_field.GetCustomAttributes(inherit); }
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) { return m_field.GetCustomAttributes(attributeType, inherit); }
+ public override bool IsDefined(Type attributeType, bool inherit) { return m_field.IsDefined(attributeType, inherit); }
+ internal int MetadataTokenInternal
+ {
+ get
+ {
+ FieldBuilder fb = m_field as FieldBuilder;
+
+ if (fb != null)
+ return fb.MetadataTokenInternal;
+ else
+ {
+ Contract.Assert(m_field is RuntimeFieldInfo);
+ return m_field.MetadataToken;
+ }
+ }
+ }
+ public override Module Module { get { return m_field.Module; } }
+ public new Type GetType() { return base.GetType(); }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public override Type[] GetRequiredCustomModifiers() { return m_field.GetRequiredCustomModifiers(); }
+ public override Type[] GetOptionalCustomModifiers() { return m_field.GetOptionalCustomModifiers(); }
+ public override void SetValueDirect(TypedReference obj, Object value)
+ {
+ throw new NotImplementedException();
+ }
+ public override Object GetValueDirect(TypedReference obj)
+ {
+ throw new NotImplementedException();
+ }
+ public override RuntimeFieldHandle FieldHandle
+ {
+ get { throw new NotImplementedException(); }
+ }
+ public override Type FieldType { get { throw new NotImplementedException(); } }
+ public override Object GetValue(Object obj) { throw new InvalidOperationException(); }
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) { throw new InvalidOperationException(); }
+ public override FieldAttributes Attributes { get { return m_field.Attributes; } }
+ #endregion
+ }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Reflection/EventAttributes.cs b/src/mscorlib/src/System/Reflection/EventAttributes.cs
new file mode 100644
index 0000000000..c0285652ff
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/EventAttributes.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// EventAttributes are an enum defining the attributes associated with
+//
+// and Event. These are defined in CorHdr.h and are a combination of
+// bits and enums.
+//
+//
+namespace System.Reflection {
+
+ using System;
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum EventAttributes {
+ None = 0x0000,
+
+ // This Enum matchs the CorEventAttr defined in CorHdr.h
+ SpecialName = 0x0200, // event is special. Name describes how.
+
+ // Reserved flags for Runtime use only.
+ ReservedMask = 0x0400,
+ RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding.
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/EventInfo.cs b/src/mscorlib/src/System/Reflection/EventInfo.cs
new file mode 100644
index 0000000000..3fd1951b6c
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/EventInfo.cs
@@ -0,0 +1,443 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.ConstrainedExecution;
+ using System.Security.Permissions;
+ using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_EventInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class EventInfo : MemberInfo, _EventInfo
+ {
+ #region Constructor
+ protected EventInfo() { }
+ #endregion
+
+ public static bool operator ==(EventInfo left, EventInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeEventInfo || right is RuntimeEventInfo)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(EventInfo left, EventInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return MemberTypes.Event; } }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public virtual MethodInfo[] GetOtherMethods(bool nonPublic)
+ {
+ throw new NotImplementedException();
+ }
+
+ public abstract MethodInfo GetAddMethod(bool nonPublic);
+
+ public abstract MethodInfo GetRemoveMethod(bool nonPublic);
+
+ public abstract MethodInfo GetRaiseMethod(bool nonPublic);
+
+ public abstract EventAttributes Attributes { get; }
+ #endregion
+
+ #region Public Members
+ public virtual MethodInfo AddMethod
+ {
+ get
+ {
+ return GetAddMethod(true);
+ }
+ }
+
+ public virtual MethodInfo RemoveMethod
+ {
+ get
+ {
+ return GetRemoveMethod(true);
+ }
+ }
+
+ public virtual MethodInfo RaiseMethod
+ {
+ get
+ {
+ return GetRaiseMethod(true);
+ }
+ }
+
+ public MethodInfo[] GetOtherMethods() { return GetOtherMethods(false); }
+
+ public MethodInfo GetAddMethod() { return GetAddMethod(false); }
+
+ public MethodInfo GetRemoveMethod() { return GetRemoveMethod(false); }
+
+ public MethodInfo GetRaiseMethod() { return GetRaiseMethod(false); }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public virtual void AddEventHandler(Object target, Delegate handler)
+ {
+ MethodInfo addMethod = GetAddMethod();
+
+ if (addMethod == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoPublicAddMethod"));
+
+#if FEATURE_COMINTEROP
+ if (addMethod.ReturnType == typeof(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotSupportedOnWinRTEvent"));
+
+ // Must be a normal non-WinRT event
+ Contract.Assert(addMethod.ReturnType == typeof(void));
+#endif // FEATURE_COMINTEROP
+
+ addMethod.Invoke(target, new object[] { handler });
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public virtual void RemoveEventHandler(Object target, Delegate handler)
+ {
+ MethodInfo removeMethod = GetRemoveMethod();
+
+ if (removeMethod == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoPublicRemoveMethod"));
+
+#if FEATURE_COMINTEROP
+ ParameterInfo[] parameters = removeMethod.GetParametersNoCopy();
+ Contract.Assert(parameters != null && parameters.Length == 1);
+
+ if (parameters[0].ParameterType == typeof(System.Runtime.InteropServices.WindowsRuntime.EventRegistrationToken))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotSupportedOnWinRTEvent"));
+
+ // Must be a normal non-WinRT event
+ Contract.Assert(parameters[0].ParameterType.BaseType == typeof(MulticastDelegate));
+#endif // FEATURE_COMINTEROP
+
+ removeMethod.Invoke(target, new object[] { handler });
+ }
+
+ public virtual Type EventHandlerType
+ {
+ get
+ {
+ MethodInfo m = GetAddMethod(true);
+
+ ParameterInfo[] p = m.GetParametersNoCopy();
+
+ Type del = typeof(Delegate);
+
+ for (int i = 0; i < p.Length; i++)
+ {
+ Type c = p[i].ParameterType;
+
+ if (c.IsSubclassOf(del))
+ return c;
+ }
+ return null;
+ }
+ }
+ public bool IsSpecialName
+ {
+ get
+ {
+ return(Attributes & EventAttributes.SpecialName) != 0;
+ }
+ }
+
+ public virtual bool IsMulticast
+ {
+ get
+ {
+ Type cl = EventHandlerType;
+ Type mc = typeof(MulticastDelegate);
+ return mc.IsAssignableFrom(cl);
+ }
+ }
+ #endregion
+
+#if !FEATURE_CORECLR
+ Type _EventInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ void _EventInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EventInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _EventInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _EventInfo.Invoke in VM\DangerousAPIs.h and
+ // include _EventInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _EventInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ [Serializable]
+ internal unsafe sealed class RuntimeEventInfo : EventInfo, ISerializable
+ {
+ #region Private Data Members
+ private int m_token;
+ private EventAttributes m_flags;
+ private string m_name;
+ [System.Security.SecurityCritical]
+ private void* m_utf8name;
+ private RuntimeTypeCache m_reflectedTypeCache;
+ private RuntimeMethodInfo m_addMethod;
+ private RuntimeMethodInfo m_removeMethod;
+ private RuntimeMethodInfo m_raiseMethod;
+ private MethodInfo[] m_otherMethod;
+ private RuntimeType m_declaringType;
+ private BindingFlags m_bindingFlags;
+ #endregion
+
+ #region Constructor
+ internal RuntimeEventInfo()
+ {
+ // Used for dummy head node during population
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeEventInfo(int tkEvent, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate)
+ {
+ Contract.Requires(declaredType != null);
+ Contract.Requires(reflectedTypeCache != null);
+ Contract.Assert(!reflectedTypeCache.IsGlobal);
+
+ MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport;
+
+ m_token = tkEvent;
+ m_reflectedTypeCache = reflectedTypeCache;
+ m_declaringType = declaredType;
+
+
+ RuntimeType reflectedType = reflectedTypeCache.GetRuntimeType();
+
+ scope.GetEventProps(tkEvent, out m_utf8name, out m_flags);
+
+ RuntimeMethodInfo dummy;
+ Associates.AssignAssociates(scope, tkEvent, declaredType, reflectedType,
+ out m_addMethod, out m_removeMethod, out m_raiseMethod,
+ out dummy, out dummy, out m_otherMethod, out isPrivate, out m_bindingFlags);
+ }
+ #endregion
+
+ #region Internal Members
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RuntimeEventInfo m = o as RuntimeEventInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_token == m_token &&
+ RuntimeTypeHandle.GetModule(m_declaringType).Equals(
+ RuntimeTypeHandle.GetModule(m.m_declaringType));
+ }
+
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ if (m_addMethod == null || m_addMethod.GetParametersNoCopy().Length == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoPublicAddMethod"));
+
+ return m_addMethod.GetParametersNoCopy()[0].ParameterType.FormatTypeName() + " " + Name;
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return MemberTypes.Event; } }
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_name == null)
+ m_name = new Utf8String(m_utf8name).ToString();
+
+ return m_name;
+ }
+ }
+ public override Type DeclaringType { get { return m_declaringType; } }
+ public override Type ReflectedType
+ {
+ get
+ {
+ return ReflectedTypeInternal;
+ }
+ }
+
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ public override int MetadataToken { get { return m_token; } }
+ public override Module Module { get { return GetRuntimeModule(); } }
+ internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ MemberInfoSerializationHolder.GetSerializationInfo(
+ info,
+ Name,
+ ReflectedTypeInternal,
+ null,
+ MemberTypes.Event);
+ }
+ #endregion
+
+ #region EventInfo Overrides
+ public override MethodInfo[] GetOtherMethods(bool nonPublic)
+ {
+ List<MethodInfo> ret = new List<MethodInfo>();
+
+ if ((object)m_otherMethod == null)
+ return new MethodInfo[0];
+
+ for(int i = 0; i < m_otherMethod.Length; i ++)
+ {
+ if (Associates.IncludeAccessor((MethodInfo)m_otherMethod[i], nonPublic))
+ ret.Add(m_otherMethod[i]);
+ }
+
+ return ret.ToArray();
+ }
+
+ public override MethodInfo GetAddMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_addMethod, nonPublic))
+ return null;
+
+ return m_addMethod;
+ }
+
+ public override MethodInfo GetRemoveMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_removeMethod, nonPublic))
+ return null;
+
+ return m_removeMethod;
+ }
+
+ public override MethodInfo GetRaiseMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_raiseMethod, nonPublic))
+ return null;
+
+ return m_raiseMethod;
+ }
+
+ public override EventAttributes Attributes
+ {
+ get
+ {
+ return m_flags;
+ }
+ }
+ #endregion
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/FieldAttributes.cs b/src/mscorlib/src/System/Reflection/FieldAttributes.cs
new file mode 100644
index 0000000000..48c90a1a38
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/FieldAttributes.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection
+{
+ using System;
+ // This Enum matchs the CorFieldAttr defined in CorHdr.h
+ [Serializable]
+ [Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum FieldAttributes
+ {
+ // member access mask - Use this mask to retrieve accessibility information.
+ FieldAccessMask = 0x0007,
+ PrivateScope = 0x0000, // Member not referenceable.
+ Private = 0x0001, // Accessible only by the parent type.
+ FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
+ Assembly = 0x0003, // Accessibly by anyone in the Assembly.
+ Family = 0x0004, // Accessible only by type and sub-types.
+ FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
+ Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
+ // end member access mask
+
+ // field contract attributes.
+ Static = 0x0010, // Defined on type, else per instance.
+ InitOnly = 0x0020, // Field may only be initialized, not written to after init.
+ Literal = 0x0040, // Value is compile time constant.
+ NotSerialized = 0x0080, // Field does not have to be serialized when type is remoted.
+
+ SpecialName = 0x0200, // field is special. Name describes how.
+
+ // interop attributes
+ PinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke.
+
+ // Reserved flags for runtime use only.
+ ReservedMask = 0x9500,
+ RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding.
+ HasFieldMarshal = 0x1000, // Field has marshalling information.
+ HasDefault = 0x8000, // Field has default.
+ HasFieldRVA = 0x0100, // Field has RVA.
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/FieldInfo.cs b/src/mscorlib/src/System/Reflection/FieldInfo.cs
new file mode 100644
index 0000000000..c6a44d412b
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/FieldInfo.cs
@@ -0,0 +1,955 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Metadata;
+#endif //FEATURE_REMOTING
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Threading;
+ using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_FieldInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class FieldInfo : MemberInfo, _FieldInfo
+ {
+ #region Static Members
+ public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle)
+ {
+ if (handle.IsNullHandle())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"), "handle");
+
+ FieldInfo f = RuntimeType.GetFieldInfo(handle.GetRuntimeFieldInfo());
+
+ Type declaringType = f.DeclaringType;
+ if (declaringType != null && declaringType.IsGenericType)
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_FieldDeclaringTypeGeneric"),
+ f.Name, declaringType.GetGenericTypeDefinition()));
+
+ return f;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static FieldInfo GetFieldFromHandle(RuntimeFieldHandle handle, RuntimeTypeHandle declaringType)
+ {
+ if (handle.IsNullHandle())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
+
+ return RuntimeType.GetFieldInfo(declaringType.GetRuntimeType(), handle.GetRuntimeFieldInfo());
+ }
+ #endregion
+
+ #region Constructor
+ protected FieldInfo() { }
+ #endregion
+
+ public static bool operator ==(FieldInfo left, FieldInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeFieldInfo || right is RuntimeFieldInfo)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(FieldInfo left, FieldInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Field; } }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+
+ public virtual Type[] GetRequiredCustomModifiers()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Type[] GetOptionalCustomModifiers()
+ {
+ throw new NotImplementedException();
+ }
+
+ [CLSCompliant(false)]
+ public virtual void SetValueDirect(TypedReference obj, Object value)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
+ }
+
+ [CLSCompliant(false)]
+ public virtual Object GetValueDirect(TypedReference obj)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS"));
+ }
+
+ public abstract RuntimeFieldHandle FieldHandle { get; }
+
+ public abstract Type FieldType { get; }
+
+ public abstract Object GetValue(Object obj);
+
+ public virtual Object GetRawConstantValue() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_AbstractNonCLS")); }
+
+ public abstract void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture);
+
+ public abstract FieldAttributes Attributes { get; }
+ #endregion
+
+ #region Public Members
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public void SetValue(Object obj, Object value)
+ {
+ // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
+ // But to maintain backward compatibility we can't switch to calling an
+ // internal overload that takes a stack mark.
+ // Fortunately the stack walker skips all the reflection invocation frames including this one.
+ // So this method will never be returned by the stack walker as the caller.
+ // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
+ SetValue(obj, value, BindingFlags.Default, Type.DefaultBinder, null);
+ }
+
+ public bool IsPublic { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public; } }
+
+ public bool IsPrivate { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Private; } }
+
+ public bool IsFamily { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Family; } }
+
+ public bool IsAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Assembly; } }
+
+ public bool IsFamilyAndAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamANDAssem; } }
+
+ public bool IsFamilyOrAssembly { get { return(Attributes & FieldAttributes.FieldAccessMask) == FieldAttributes.FamORAssem; } }
+
+ public bool IsStatic { get { return(Attributes & FieldAttributes.Static) != 0; } }
+
+ public bool IsInitOnly { get { return(Attributes & FieldAttributes.InitOnly) != 0; } }
+
+ public bool IsLiteral { get { return(Attributes & FieldAttributes.Literal) != 0; } }
+
+ public bool IsNotSerialized { get { return(Attributes & FieldAttributes.NotSerialized) != 0; } }
+
+ public bool IsSpecialName { get { return(Attributes & FieldAttributes.SpecialName) != 0; } }
+
+ public bool IsPinvokeImpl { get { return(Attributes & FieldAttributes.PinvokeImpl) != 0; } }
+
+ public virtual bool IsSecurityCritical
+ {
+ get { return FieldHandle.IsSecurityCritical(); }
+ }
+
+ public virtual bool IsSecuritySafeCritical
+ {
+ get { return FieldHandle.IsSecuritySafeCritical(); }
+ }
+
+ public virtual bool IsSecurityTransparent
+ {
+ get { return FieldHandle.IsSecurityTransparent(); }
+ }
+
+ #endregion
+
+#if !FEATURE_CORECLR
+ Type _FieldInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ void _FieldInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _FieldInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _FieldInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _FieldInfo.Invoke in VM\DangerousAPIs.h and
+ // include _FieldInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _FieldInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ [Serializable]
+ internal abstract class RuntimeFieldInfo : FieldInfo, ISerializable
+ {
+ #region Private Data Members
+ private BindingFlags m_bindingFlags;
+ protected RuntimeTypeCache m_reflectedTypeCache;
+ protected RuntimeType m_declaringType;
+ #endregion
+
+ #region Constructor
+ protected RuntimeFieldInfo()
+ {
+ // Used for dummy head node during population
+ }
+ protected RuntimeFieldInfo(RuntimeTypeCache reflectedTypeCache, RuntimeType declaringType, BindingFlags bindingFlags)
+ {
+ m_bindingFlags = bindingFlags;
+ m_declaringType = declaringType;
+ m_reflectedTypeCache = reflectedTypeCache;
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
+ // This member is currently being used by Remoting for caching remoting data. If you
+ // need to cache data here, talk to the Remoting team to work out a mechanism, so that
+ // both caching systems can happily work together.
+ private RemotingFieldCachedData m_cachedData;
+
+ internal RemotingFieldCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingFieldCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingFieldCachedData(this);
+ RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+
+ #region NonPublic Members
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ internal RuntimeType GetDeclaringTypeInternal()
+ {
+ return m_declaringType;
+ }
+
+ internal RuntimeType GetRuntimeType() { return m_declaringType; }
+ internal abstract RuntimeModule GetRuntimeModule();
+ #endregion
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return MemberTypes.Field; } }
+ public override Type ReflectedType
+ {
+ get
+ {
+ return m_reflectedTypeCache.IsGlobal ? null : ReflectedTypeInternal;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return m_reflectedTypeCache.IsGlobal ? null : m_declaringType;
+ }
+ }
+
+ public override Module Module { get { return GetRuntimeModule(); } }
+ #endregion
+
+ #region Object Overrides
+ public unsafe override String ToString()
+ {
+ return FieldType.FormatTypeName() + " " + Name;
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region FieldInfo Overrides
+ // All implemented on derived classes
+ #endregion
+
+ #region ISerializable Implementation
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+ MemberInfoSerializationHolder.GetSerializationInfo(
+ info,
+ Name,
+ ReflectedTypeInternal,
+ ToString(),
+ MemberTypes.Field);
+ }
+ #endregion
+ }
+
+ [Serializable]
+ internal unsafe sealed class RtFieldInfo : RuntimeFieldInfo, IRuntimeFieldInfo
+ {
+ #region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static private extern void PerformVisibilityCheckOnField(IntPtr field, Object target, RuntimeType declaringType, FieldAttributes attr, uint invocationFlags);
+ #endregion
+
+ #region Private Data Members
+ // agressive caching
+ private IntPtr m_fieldHandle;
+ private FieldAttributes m_fieldAttributes;
+ // lazy caching
+ private string m_name;
+ private RuntimeType m_fieldType;
+ private INVOCATION_FLAGS m_invocationFlags;
+
+#if FEATURE_APPX
+ private bool IsNonW8PFrameworkAPI()
+ {
+ if (GetRuntimeType().IsNonW8PFrameworkAPI())
+ return true;
+
+ // Allow "value__"
+ if (m_declaringType.IsEnum)
+ return false;
+
+ RuntimeAssembly rtAssembly = GetRuntimeAssembly();
+ if (rtAssembly.IsFrameworkAssembly())
+ {
+ int ctorToken = rtAssembly.InvocableAttributeCtorToken;
+ if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
+ !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
+ return true;
+ }
+
+ return false;
+ }
+#endif
+
+ internal INVOCATION_FLAGS InvocationFlags
+ {
+ get
+ {
+ if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ Type declaringType = DeclaringType;
+ bool fIsReflectionOnlyType = (declaringType is ReflectionOnlyType);
+
+ INVOCATION_FLAGS invocationFlags = 0;
+
+ // first take care of all the NO_INVOKE cases
+ if (
+ (declaringType != null && declaringType.ContainsGenericParameters) ||
+ (declaringType == null && Module.Assembly.ReflectionOnly) ||
+ (fIsReflectionOnlyType)
+ )
+ {
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
+ }
+
+ // If the invocationFlags are still 0, then
+ // this should be an usable field, determine the other flags
+ if (invocationFlags == 0)
+ {
+ if ((m_fieldAttributes & FieldAttributes.InitOnly) != (FieldAttributes)0)
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
+
+ if ((m_fieldAttributes & FieldAttributes.HasFieldRVA) != (FieldAttributes)0)
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD;
+
+ // A public field is inaccesible to Transparent code if the field is Critical.
+ bool needsTransparencySecurityCheck = IsSecurityCritical && !IsSecuritySafeCritical;
+ bool needsVisibilitySecurityCheck = ((m_fieldAttributes & FieldAttributes.FieldAccessMask) != FieldAttributes.Public) ||
+ (declaringType != null && declaringType.NeedsReflectionSecurityCheck);
+ if (needsTransparencySecurityCheck || needsVisibilitySecurityCheck)
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
+
+ // find out if the field type is one of the following: Primitive, Enum or Pointer
+ Type fieldType = FieldType;
+ if (fieldType.IsPointer || fieldType.IsEnum || fieldType.IsPrimitive)
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_FIELD_SPECIAL_CAST;
+ }
+
+#if FEATURE_APPX
+ if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
+#endif // FEATURE_APPX
+
+ // must be last to avoid threading problems
+ m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ }
+
+ return m_invocationFlags;
+ }
+ }
+ #endregion
+
+ private RuntimeAssembly GetRuntimeAssembly() { return m_declaringType.GetRuntimeAssembly(); }
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal RtFieldInfo(
+ RuntimeFieldHandleInternal handle, RuntimeType declaringType, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags)
+ : base(reflectedTypeCache, declaringType, bindingFlags)
+ {
+ m_fieldHandle = handle.Value;
+ m_fieldAttributes = RuntimeFieldHandle.GetAttributes(handle);
+ }
+ #endregion
+
+ #region Private Members
+ RuntimeFieldHandleInternal IRuntimeFieldInfo.Value
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ return new RuntimeFieldHandleInternal(m_fieldHandle);
+ }
+ }
+
+ #endregion
+
+ #region Internal Members
+ internal void CheckConsistency(Object target)
+ {
+ // only test instance fields
+ if ((m_fieldAttributes & FieldAttributes.Static) != FieldAttributes.Static)
+ {
+ if (!m_declaringType.IsInstanceOfType(target))
+ {
+ if (target == null)
+ {
+ throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatFldReqTarg"));
+ }
+ else
+ {
+ throw new ArgumentException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_FieldDeclTarget"),
+ Name, m_declaringType, target.GetType()));
+ }
+ }
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RtFieldInfo m = o as RtFieldInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_fieldHandle == m_fieldHandle;
+ }
+
+ [System.Security.SecurityCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, ref StackCrawlMark stackMark)
+ {
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+ RuntimeType declaringType = DeclaringType as RuntimeType;
+
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
+ {
+ if (declaringType != null && declaringType.ContainsGenericParameters)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
+
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
+
+ throw new FieldAccessException();
+ }
+
+ CheckConsistency(obj);
+
+ RuntimeType fieldType = (RuntimeType)FieldType;
+ value = fieldType.CheckValue(value, binder, culture, invokeAttr);
+
+ #region Security Check
+#if FEATURE_APPX
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
+ }
+#endif
+
+ if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
+ PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)m_invocationFlags);
+ #endregion
+
+ bool domainInitialized = false;
+ if (declaringType == null)
+ {
+ RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
+ }
+ else
+ {
+ domainInitialized = declaringType.DomainInitialized;
+ RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
+ declaringType.DomainInitialized = domainInitialized;
+ }
+ }
+
+ // UnsafeSetValue doesn't perform any consistency or visibility check.
+ // It is the caller's responsibility to ensure the operation is safe.
+ // When the caller needs to perform visibility checks they should call
+ // InternalSetValue() instead. When the caller needs to perform
+ // consistency checks they should call CheckConsistency() before
+ // calling this method.
+ [System.Security.SecurityCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal void UnsafeSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
+ {
+ RuntimeType declaringType = DeclaringType as RuntimeType;
+ RuntimeType fieldType = (RuntimeType)FieldType;
+ value = fieldType.CheckValue(value, binder, culture, invokeAttr);
+
+ bool domainInitialized = false;
+ if (declaringType == null)
+ {
+ RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, null, ref domainInitialized);
+ }
+ else
+ {
+ domainInitialized = declaringType.DomainInitialized;
+ RuntimeFieldHandle.SetValue(this, obj, value, fieldType, m_fieldAttributes, declaringType, ref domainInitialized);
+ declaringType.DomainInitialized = domainInitialized;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal Object InternalGetValue(Object obj, ref StackCrawlMark stackMark)
+ {
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+ RuntimeType declaringType = DeclaringType as RuntimeType;
+
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE) != 0)
+ {
+ if (declaringType != null && DeclaringType.ContainsGenericParameters)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenField"));
+
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyField"));
+
+ throw new FieldAccessException();
+ }
+
+ CheckConsistency(obj);
+
+#if FEATURE_APPX
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
+ }
+#endif
+
+ RuntimeType fieldType = (RuntimeType)FieldType;
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
+ PerformVisibilityCheckOnField(m_fieldHandle, obj, m_declaringType, m_fieldAttributes, (uint)(m_invocationFlags & ~INVOCATION_FLAGS.INVOCATION_FLAGS_SPECIAL_FIELD));
+
+ return UnsafeGetValue(obj);
+ }
+
+ // UnsafeGetValue doesn't perform any consistency or visibility check.
+ // It is the caller's responsibility to ensure the operation is safe.
+ // When the caller needs to perform visibility checks they should call
+ // InternalGetValue() instead. When the caller needs to perform
+ // consistency checks they should call CheckConsistency() before
+ // calling this method.
+ [System.Security.SecurityCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal Object UnsafeGetValue(Object obj)
+ {
+ RuntimeType declaringType = DeclaringType as RuntimeType;
+
+ RuntimeType fieldType = (RuntimeType)FieldType;
+
+ bool domainInitialized = false;
+ if (declaringType == null)
+ {
+ return RuntimeFieldHandle.GetValue(this, obj, fieldType, null, ref domainInitialized);
+ }
+ else
+ {
+ domainInitialized = declaringType.DomainInitialized;
+ object retVal = RuntimeFieldHandle.GetValue(this, obj, fieldType, declaringType, ref domainInitialized);
+ declaringType.DomainInitialized = domainInitialized;
+ return retVal;
+ }
+ }
+
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_name == null)
+ m_name = RuntimeFieldHandle.GetName(this);
+
+ return m_name;
+ }
+ }
+
+ internal String FullName
+ {
+ get
+ {
+ return String.Format("{0}.{1}", DeclaringType.FullName, Name);
+ }
+ }
+
+ public override int MetadataToken
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return RuntimeFieldHandle.GetToken(this); }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal override RuntimeModule GetRuntimeModule()
+ {
+ return RuntimeTypeHandle.GetModule(RuntimeFieldHandle.GetApproxDeclaringType(this));
+ }
+
+ #endregion
+
+ #region FieldInfo Overrides
+ public override Object GetValue(Object obj)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalGetValue(obj, ref stackMark);
+ }
+
+ public override object GetRawConstantValue() { throw new InvalidOperationException(); }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValueDirect(TypedReference obj)
+ {
+ if (obj.IsNull)
+ throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
+ Contract.EndContractBlock();
+
+ unsafe
+ {
+ // Passing TypedReference by reference is easier to make correct in native code
+ return RuntimeFieldHandle.GetValueDirect(this, (RuntimeType)FieldType, &obj, (RuntimeType)DeclaringType);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ InternalSetValue(obj, value, invokeAttr, binder, culture, ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValueDirect(TypedReference obj, Object value)
+ {
+ if (obj.IsNull)
+ throw new ArgumentException(Environment.GetResourceString("Arg_TypedReference_Null"));
+ Contract.EndContractBlock();
+
+ unsafe
+ {
+ // Passing TypedReference by reference is easier to make correct in native code
+ RuntimeFieldHandle.SetValueDirect(this, (RuntimeType)FieldType, &obj, value, (RuntimeType)DeclaringType);
+ }
+ }
+
+ public override RuntimeFieldHandle FieldHandle
+ {
+ get
+ {
+ Type declaringType = DeclaringType;
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+ return new RuntimeFieldHandle(this);
+ }
+ }
+
+ internal IntPtr GetFieldHandle()
+ {
+ return m_fieldHandle;
+ }
+
+ public override FieldAttributes Attributes
+ {
+ get
+ {
+ return m_fieldAttributes;
+ }
+ }
+
+ public override Type FieldType
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_fieldType == null)
+ m_fieldType = new Signature(this, m_declaringType).FieldType;
+
+ return m_fieldType;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return new Signature(this, m_declaringType).GetCustomModifiers(1, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return new Signature(this, m_declaringType).GetCustomModifiers(1, false);
+ }
+
+ #endregion
+ }
+
+ [Serializable]
+ internal sealed unsafe class MdFieldInfo : RuntimeFieldInfo, ISerializable
+ {
+ #region Private Data Members
+ private int m_tkField;
+ private string m_name;
+ private RuntimeType m_fieldType;
+ private FieldAttributes m_fieldAttributes;
+ #endregion
+
+ #region Constructor
+ internal MdFieldInfo(
+ int tkField, FieldAttributes fieldAttributes, RuntimeTypeHandle declaringTypeHandle, RuntimeTypeCache reflectedTypeCache, BindingFlags bindingFlags)
+ : base(reflectedTypeCache, declaringTypeHandle.GetRuntimeType(), bindingFlags)
+ {
+ m_tkField = tkField;
+ m_name = null;
+ m_fieldAttributes = fieldAttributes;
+ }
+ #endregion
+
+ #region Internal Members
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ MdFieldInfo m = o as MdFieldInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_tkField == m_tkField &&
+ m_declaringType.GetTypeHandleInternal().GetModuleHandle().Equals(
+ m.m_declaringType.GetTypeHandleInternal().GetModuleHandle());
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_name == null)
+ m_name = GetRuntimeModule().MetadataImport.GetName(m_tkField).ToString();
+
+ return m_name;
+ }
+ }
+
+ public override int MetadataToken { get { return m_tkField; } }
+ internal override RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
+ #endregion
+
+ #region FieldInfo Overrides
+ public override RuntimeFieldHandle FieldHandle { get { throw new NotSupportedException(); } }
+ public override FieldAttributes Attributes { get { return m_fieldAttributes; } }
+
+ public override bool IsSecurityCritical { get { return DeclaringType.IsSecurityCritical; } }
+ public override bool IsSecuritySafeCritical { get { return DeclaringType.IsSecuritySafeCritical; } }
+ public override bool IsSecurityTransparent { get { return DeclaringType.IsSecurityTransparent; } }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValueDirect(TypedReference obj)
+ {
+ return GetValue(null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValueDirect(TypedReference obj,Object value)
+ {
+ throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public unsafe override Object GetValue(Object obj)
+ {
+ return GetValue(false);
+ }
+
+ public unsafe override Object GetRawConstantValue() { return GetValue(true); }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe Object GetValue(bool raw)
+ {
+ // Cannot cache these because they could be user defined non-agile enumerations
+
+ Object value = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_tkField, FieldType.GetTypeHandleInternal(), raw);
+
+ if (value == DBNull.Value)
+ throw new NotSupportedException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
+
+ return value;
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
+ {
+ throw new FieldAccessException(Environment.GetResourceString("Acc_ReadOnly"));
+ }
+
+ public override Type FieldType
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_fieldType == null)
+ {
+ ConstArray fieldMarshal = GetRuntimeModule().MetadataImport.GetSigOfFieldDef(m_tkField);
+
+ m_fieldType = new Signature(fieldMarshal.Signature.ToPointer(),
+ (int)fieldMarshal.Length, m_declaringType).FieldType;
+ }
+
+ return m_fieldType;
+ }
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return EmptyArray<Type>.Value;
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return EmptyArray<Type>.Value;
+ }
+
+ #endregion
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/GenericParameterAttributes.cs b/src/mscorlib/src/System/Reflection/GenericParameterAttributes.cs
new file mode 100644
index 0000000000..d954b2e0f2
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/GenericParameterAttributes.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ [Flags()]
+ public enum GenericParameterAttributes
+ {
+ None = 0x0000,
+ VarianceMask = 0x0003,
+ Covariant = 0x0001,
+ Contravariant = 0x0002,
+ SpecialConstraintMask = 0x001C,
+ ReferenceTypeConstraint = 0x0004,
+ NotNullableValueTypeConstraint = 0x0008,
+ DefaultConstructorConstraint = 0x0010,
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/ICustomAttributeProvider.cs b/src/mscorlib/src/System/Reflection/ICustomAttributeProvider.cs
new file mode 100644
index 0000000000..1fd361c889
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ICustomAttributeProvider.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// ICustomAttributeProvider is an interface that is implemented by reflection
+//
+// objects which support custom attributes.
+//
+//
+namespace System.Reflection {
+
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICustomAttributeProvider
+ {
+
+ // Return an array of custom attributes identified by Type
+ Object[] GetCustomAttributes(Type attributeType, bool inherit);
+
+
+ // Return an array of all of the custom attributes (named attributes are not included)
+ Object[] GetCustomAttributes(bool inherit);
+
+
+ // Returns true if one or more instance of attributeType is defined on this member.
+ bool IsDefined (Type attributeType, bool inherit);
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/IReflect.cs b/src/mscorlib/src/System/Reflection/IReflect.cs
new file mode 100644
index 0000000000..92ce3412fc
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/IReflect.cs
@@ -0,0 +1,117 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// IReflect is an interface that defines a subset of the Type reflection methods.
+//
+// This interface is used to access and invoke members of a Type. It can be either
+// type based (like Type) or instance based (like Expando). This interface is used in
+// combination with IExpando to model the IDispatchEx expando capibilities in
+// the interop layer.
+//
+//
+namespace System.Reflection {
+ using System;
+ using System.Runtime.InteropServices;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ // Interface does not need to be marked with the serializable attribute
+ [Guid("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IReflect
+ {
+ // Return the requested method if it is implemented by the Reflection object. The
+ // match is based upon the name and DescriptorInfo which describes the signature
+ // of the method.
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr,Binder binder,
+ Type[] types,ParameterModifier[] modifiers);
+
+ // Return the requested method if it is implemented by the Reflection object. The
+ // match is based upon the name of the method. If the object implementes multiple methods
+ // with the same name an AmbiguousMatchException is thrown.
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr);
+
+ MethodInfo[] GetMethods(BindingFlags bindingAttr);
+
+ // Return the requestion field if it is implemented by the Reflection object. The
+ // match is based upon a name. There cannot be more than a single field with
+ // a name.
+ FieldInfo GetField(
+ String name,
+ BindingFlags bindingAttr);
+
+ FieldInfo[] GetFields(
+ BindingFlags bindingAttr);
+
+ // Return the property based upon name. If more than one property has the given
+ // name an AmbiguousMatchException will be thrown. Returns null if no property
+ // is found.
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr);
+
+ // Return the property based upon the name and Descriptor info describing the property
+ // indexing. Return null if no property is found.
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type returnType,
+ Type[] types,
+ ParameterModifier[] modifiers);
+
+ // Returns an array of PropertyInfos for all the properties defined on
+ // the Reflection object.
+ PropertyInfo[] GetProperties(
+ BindingFlags bindingAttr);
+
+ // Return an array of members which match the passed in name.
+ MemberInfo[] GetMember(
+ String name,
+ BindingFlags bindingAttr);
+
+ // Return an array of all of the members defined for this object.
+ MemberInfo[] GetMembers(
+ BindingFlags bindingAttr);
+
+ // Description of the Binding Process.
+ // We must invoke a method that is accessable and for which the provided
+ // parameters have the most specific match. A method may be called if
+ // 1. The number of parameters in the method declaration equals the number of
+ // arguments provided to the invocation
+ // 2. The type of each argument can be converted by the binder to the
+ // type of the type of the parameter.
+ //
+ // The binder will find all of the matching methods. These method are found based
+ // upon the type of binding requested (MethodInvoke, Get/Set Properties). The set
+ // of methods is filtered by the name, number of arguments and a set of search modifiers
+ // defined in the Binder.
+ //
+ // After the method is selected, it will be invoked. Accessability is checked
+ // at that point. The search may be control which set of methods are searched based
+ // upon the accessibility attribute associated with the method.
+ //
+ // The BindToMethod method is responsible for selecting the method to be invoked.
+ // For the default binder, the most specific method will be selected.
+ //
+ // This will invoke a specific member...
+ Object InvokeMember(
+ String name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ Object target,
+ Object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ String[] namedParameters);
+
+ // Return the underlying Type that represents the IReflect Object. For expando object,
+ // this is the (Object) IReflectInstance.GetType(). For Type object it is this.
+ Type UnderlyingSystemType {
+ get;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/IReflectableType.cs b/src/mscorlib/src/System/Reflection/IReflectableType.cs
new file mode 100644
index 0000000000..7d4936868b
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/IReflectableType.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// IReflectableType is an interface that is implemented by a Type produced
+// by a ReflectionContext
+//
+
+//
+namespace System.Reflection {
+
+ using System;
+
+ public interface IReflectableType {
+ TypeInfo GetTypeInfo();
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/InterfaceMapping.cs b/src/mscorlib/src/System/Reflection/InterfaceMapping.cs
new file mode 100644
index 0000000000..488ef4484d
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/InterfaceMapping.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+//
+// Interface Map. This struct returns the mapping of an interface into the actual methods on a class
+// that implement that interface.
+//
+//
+namespace System.Reflection {
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct InterfaceMapping {
+[System.Runtime.InteropServices.ComVisible(true)]
+ public Type TargetType; // The type implementing the interface
+[System.Runtime.InteropServices.ComVisible(true)]
+ public Type InterfaceType; // The type representing the interface
+[System.Runtime.InteropServices.ComVisible(true)]
+ public MethodInfo[] TargetMethods; // The methods implementing the interface
+[System.Runtime.InteropServices.ComVisible(true)]
+ public MethodInfo[] InterfaceMethods; // The methods defined on the interface
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs b/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs
new file mode 100644
index 0000000000..ce2630a908
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/IntrospectionExtensions.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: go from type to type info
+**
+**
+=============================================================================*/
+
+namespace System.Reflection
+{
+ using System.Reflection;
+
+ public static class IntrospectionExtensions
+ {
+ public static TypeInfo GetTypeInfo(this Type type){
+ if(type == null){
+ throw new ArgumentNullException("type");
+ }
+ var rcType=(IReflectableType)type;
+ if(rcType==null){
+ return null;
+ }else{
+ return rcType.GetTypeInfo();
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs b/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs
new file mode 100644
index 0000000000..7c980da379
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/InvalidFilterCriteriaException.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// InvalidFilterCriteriaException is thrown in FindMembers when the
+//
+// filter criteria is not valid for the type of filter being used.
+//
+//
+//
+//
+namespace System.Reflection {
+
+ using System;
+ using System.Runtime.Serialization;
+ using ApplicationException = System.ApplicationException;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ public class InvalidFilterCriteriaException : Exception {
+#else
+ public class InvalidFilterCriteriaException : ApplicationException {
+#endif // FEATURE_CORECLR
+ public InvalidFilterCriteriaException()
+ : base(Environment.GetResourceString("Arg_InvalidFilterCriteriaException")) {
+ SetErrorCode(__HResults.COR_E_INVALIDFILTERCRITERIA);
+ }
+
+ public InvalidFilterCriteriaException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDFILTERCRITERIA);
+ }
+
+ public InvalidFilterCriteriaException(String message, Exception inner) : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_INVALIDFILTERCRITERIA);
+ }
+
+ protected InvalidFilterCriteriaException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/LoaderAllocator.cs b/src/mscorlib/src/System/Reflection/LoaderAllocator.cs
new file mode 100644
index 0000000000..a8b4b0c3a0
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/LoaderAllocator.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Collections.Generic;
+
+
+namespace System.Reflection
+{
+ //
+ // We can destroy the unmanaged part of collectible type only after the managed part is definitely gone and thus
+ // nobody can call/allocate/reference anything related to the collectible assembly anymore. A call to finalizer
+ // alone does not guarantee that the managed part is gone. A malicious code can keep a reference to some object
+ // in a way that that survives finalization, or we can be running during shutdown where everything is finalized.
+ //
+ // The unmanaged LoaderAllocator keeps a reference to the managed LoaderAllocator in long weak handle. If the long
+ // weak handle is null, we can be sure that the managed part of the LoaderAllocator is definitely gone and that it
+ // is safe to destroy the unmanaged part. Unfortunately, we can not perform the above check in a finalizer on the
+ // LoaderAllocator, but it can be performed on a helper object.
+ //
+ // The finalization does not have to be done using CriticalFinalizerObject. We have to go over all LoaderAllocators
+ // during AppDomain shutdown anyway to avoid leaks e.g. if somebody stores reference to LoaderAllocator in a static.
+ //
+ internal sealed class LoaderAllocatorScout
+ {
+ // This field is set by the VM to atomically transfer the ownership to the managed loader allocator
+ internal IntPtr m_nativeLoaderAllocator;
+
+ [SuppressUnmanagedCodeSecurity]
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern bool Destroy(IntPtr nativeLoaderAllocator);
+
+ [SecuritySafeCritical]
+ ~LoaderAllocatorScout()
+ {
+ if (m_nativeLoaderAllocator.IsNull())
+ return;
+
+ // Assemblies and LoaderAllocators will be cleaned up during AppDomain shutdown in
+ // unmanaged code
+ // So it is ok to skip reregistration and cleanup for finalization during appdomain shutdown.
+ // We also avoid early finalization of LoaderAllocatorScout due to AD unload when the object was inside DelayedFinalizationList.
+ if (!Environment.HasShutdownStarted &&
+ !AppDomain.CurrentDomain.IsFinalizingForUnload())
+ {
+
+ // Destroy returns false if the managed LoaderAllocator is still alive.
+ if (!Destroy(m_nativeLoaderAllocator))
+ {
+ // Somebody might have been holding a reference on us via weak handle.
+ // We will keep trying. It will be hopefully released eventually.
+ GC.ReRegisterForFinalize(this);
+ }
+ }
+ }
+ }
+
+ internal sealed class LoaderAllocator
+ {
+ LoaderAllocator()
+ {
+ m_slots = new object [5];
+ // m_slotsUsed = 0;
+
+ m_scout = new LoaderAllocatorScout();
+ }
+
+#pragma warning disable 169
+#pragma warning disable 414
+ LoaderAllocatorScout m_scout;
+ object [] m_slots;
+ internal CerHashtable<RuntimeMethodInfo, RuntimeMethodInfo> m_methodInstantiations;
+ int m_slotsUsed;
+#pragma warning restore 414
+#pragma warning restore 169
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/ManifestResourceInfo.cs b/src/mscorlib/src/System/Reflection/ManifestResourceInfo.cs
new file mode 100644
index 0000000000..a53d32abdb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ManifestResourceInfo.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: For info regarding a manifest resource's topology.
+**
+**
+=============================================================================*/
+
+namespace System.Reflection {
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class ManifestResourceInfo {
+ private Assembly _containingAssembly;
+ private String _containingFileName;
+ private ResourceLocation _resourceLocation;
+
+ public ManifestResourceInfo(Assembly containingAssembly,
+ String containingFileName,
+ ResourceLocation resourceLocation)
+ {
+ _containingAssembly = containingAssembly;
+ _containingFileName = containingFileName;
+ _resourceLocation = resourceLocation;
+ }
+
+ public virtual Assembly ReferencedAssembly
+ {
+ get {
+ return _containingAssembly;
+ }
+ }
+
+ public virtual String FileName
+ {
+ get {
+ return _containingFileName;
+ }
+ }
+
+ public virtual ResourceLocation ResourceLocation
+ {
+ get {
+ return _resourceLocation;
+ }
+ }
+ }
+
+ // The ResourceLocation is a combination of these flags, set or not.
+ // Linked means not Embedded.
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ResourceLocation
+ {
+ Embedded = 0x1,
+ ContainedInAnotherAssembly = 0x2,
+ ContainedInManifestFile = 0x4
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/MdConstant.cs b/src/mscorlib/src/System/Reflection/MdConstant.cs
new file mode 100644
index 0000000000..1941736787
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MdConstant.cs
@@ -0,0 +1,169 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+
+ internal static class MdConstant
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ public static unsafe Object GetValue(MetadataImport scope, int token, RuntimeTypeHandle fieldTypeHandle, bool raw)
+ {
+ CorElementType corElementType = 0;
+ long buffer = 0;
+ int length;
+ String stringVal;
+
+ stringVal = scope.GetDefaultValue(token, out buffer, out length, out corElementType);
+
+ RuntimeType fieldType = fieldTypeHandle.GetRuntimeType();
+
+ if (fieldType.IsEnum && raw == false)
+ {
+ long defaultValue = 0;
+
+ switch (corElementType)
+ {
+ #region Switch
+
+ case CorElementType.Void:
+ return DBNull.Value;
+
+ case CorElementType.Char:
+ defaultValue = *(char*)&buffer;
+ break;
+
+ case CorElementType.I1:
+ defaultValue = *(sbyte*)&buffer;
+ break;
+
+ case CorElementType.U1:
+ defaultValue = *(byte*)&buffer;
+ break;
+
+ case CorElementType.I2:
+ defaultValue = *(short*)&buffer;
+ break;
+
+ case CorElementType.U2:
+ defaultValue = *(ushort*)&buffer;
+ break;
+
+ case CorElementType.I4:
+ defaultValue = *(int*)&buffer;
+ break;
+
+ case CorElementType.U4:
+ defaultValue = *(uint*)&buffer;
+ break;
+
+ case CorElementType.I8:
+ defaultValue = buffer;
+ break;
+
+ case CorElementType.U8:
+ defaultValue = buffer;
+ break;
+
+ default:
+ throw new FormatException(Environment.GetResourceString("Arg_BadLiteralFormat"));
+ #endregion
+ }
+
+ return RuntimeType.CreateEnum(fieldType, defaultValue);
+ }
+ else if (fieldType == typeof(DateTime))
+ {
+ long defaultValue = 0;
+
+ switch (corElementType)
+ {
+ #region Switch
+
+ case CorElementType.Void:
+ return DBNull.Value;
+
+ case CorElementType.I8:
+ defaultValue = buffer;
+ break;
+
+ case CorElementType.U8:
+ defaultValue = buffer;
+ break;
+
+ default:
+ throw new FormatException(Environment.GetResourceString("Arg_BadLiteralFormat"));
+ #endregion
+ }
+
+ return new DateTime(defaultValue);
+ }
+ else
+ {
+ switch (corElementType)
+ {
+ #region Switch
+
+ case CorElementType.Void:
+ return DBNull.Value;
+
+ case CorElementType.Char:
+ return *(char*)&buffer;
+
+ case CorElementType.I1:
+ return *(sbyte*)&buffer;
+
+ case CorElementType.U1:
+ return *(byte*)&buffer;
+
+ case CorElementType.I2:
+ return *(short*)&buffer;
+
+ case CorElementType.U2:
+ return *(ushort*)&buffer;
+
+ case CorElementType.I4:
+ return *(int*)&buffer;
+
+ case CorElementType.U4:
+ return *(uint*)&buffer;
+
+ case CorElementType.I8:
+ return buffer;
+
+ case CorElementType.U8:
+ return (ulong)buffer;
+
+ case CorElementType.Boolean :
+ // The boolean value returned from the metadata engine is stored as a
+ // BOOL, which actually maps to an int. We need to read it out as an int
+ // to avoid problems on big-endian machines.
+ return (*(int*)&buffer != 0);
+
+ case CorElementType.R4 :
+ return *(float*)&buffer;
+
+ case CorElementType.R8:
+ return *(double*)&buffer;
+
+ case CorElementType.String:
+ // A string constant can be empty but never null.
+ // A nullref constant can only be type CorElementType.Class.
+ return stringVal == null ? String.Empty : stringVal;
+
+ case CorElementType.Class:
+ return null;
+
+ default:
+ throw new FormatException(Environment.GetResourceString("Arg_BadLiteralFormat"));
+ #endregion
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/MdImport.cs b/src/mscorlib/src/System/Reflection/MdImport.cs
new file mode 100644
index 0000000000..3bf8eddbcc
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MdImport.cs
@@ -0,0 +1,736 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Reflection;
+using System.Globalization;
+using System.Threading;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Collections;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Configuration.Assemblies;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System.Reflection
+{
+ [Serializable]
+ internal enum CorElementType : byte
+ {
+ End = 0x00,
+ Void = 0x01,
+ Boolean = 0x02,
+ Char = 0x03,
+ I1 = 0x04,
+ U1 = 0x05,
+ I2 = 0x06,
+ U2 = 0x07,
+ I4 = 0x08,
+ U4 = 0x09,
+ I8 = 0x0A,
+ U8 = 0x0B,
+ R4 = 0x0C,
+ R8 = 0x0D,
+ String = 0x0E,
+ Ptr = 0x0F,
+ ByRef = 0x10,
+ ValueType = 0x11,
+ Class = 0x12,
+ Var = 0x13,
+ Array = 0x14,
+ GenericInst = 0x15,
+ TypedByRef = 0x16,
+ I = 0x18,
+ U = 0x19,
+ FnPtr = 0x1B,
+ Object = 0x1C,
+ SzArray = 0x1D,
+ MVar = 0x1E,
+ CModReqd = 0x1F,
+ CModOpt = 0x20,
+ Internal = 0x21,
+ Max = 0x22,
+ Modifier = 0x40,
+ Sentinel = 0x41,
+ Pinned = 0x45,
+ }
+
+[Serializable]
+[Flags()]
+ internal enum MdSigCallingConvention: byte
+ {
+ CallConvMask = 0x0f, // Calling convention is bottom 4 bits
+
+ Default = 0x00,
+ C = 0x01,
+ StdCall = 0x02,
+ ThisCall = 0x03,
+ FastCall = 0x04,
+ Vararg = 0x05,
+ Field = 0x06,
+ LocalSig = 0x07,
+ Property = 0x08,
+ Unmgd = 0x09,
+ GenericInst = 0x0a, // generic method instantiation
+
+ Generic = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count)
+ HasThis = 0x20, // Top bit indicates a 'this' parameter
+ ExplicitThis = 0x40, // This parameter is explicitly in the signature
+ }
+
+
+[Serializable]
+[Flags()]
+ internal enum PInvokeAttributes
+ {
+ NoMangle = 0x0001,
+
+
+ CharSetMask = 0x0006,
+ CharSetNotSpec = 0x0000,
+ CharSetAnsi = 0x0002,
+ CharSetUnicode = 0x0004,
+ CharSetAuto = 0x0006,
+
+
+ BestFitUseAssem = 0x0000,
+ BestFitEnabled = 0x0010,
+ BestFitDisabled = 0x0020,
+ BestFitMask = 0x0030,
+
+ ThrowOnUnmappableCharUseAssem = 0x0000,
+ ThrowOnUnmappableCharEnabled = 0x1000,
+ ThrowOnUnmappableCharDisabled = 0x2000,
+ ThrowOnUnmappableCharMask = 0x3000,
+
+ SupportsLastError = 0x0040,
+
+ CallConvMask = 0x0700,
+ CallConvWinapi = 0x0100,
+ CallConvCdecl = 0x0200,
+ CallConvStdcall = 0x0300,
+ CallConvThiscall = 0x0400,
+ CallConvFastcall = 0x0500,
+
+ MaxValue = 0xFFFF,
+ }
+
+
+[Serializable]
+[Flags()]
+ internal enum MethodSemanticsAttributes
+ {
+ Setter = 0x0001,
+ Getter = 0x0002,
+ Other = 0x0004,
+ AddOn = 0x0008,
+ RemoveOn = 0x0010,
+ Fire = 0x0020,
+ }
+
+
+ [Serializable]
+ internal enum MetadataTokenType
+ {
+ Module = 0x00000000,
+ TypeRef = 0x01000000,
+ TypeDef = 0x02000000,
+ FieldDef = 0x04000000,
+ MethodDef = 0x06000000,
+ ParamDef = 0x08000000,
+ InterfaceImpl = 0x09000000,
+ MemberRef = 0x0a000000,
+ CustomAttribute = 0x0c000000,
+ Permission = 0x0e000000,
+ Signature = 0x11000000,
+ Event = 0x14000000,
+ Property = 0x17000000,
+ ModuleRef = 0x1a000000,
+ TypeSpec = 0x1b000000,
+ Assembly = 0x20000000,
+ AssemblyRef = 0x23000000,
+ File = 0x26000000,
+ ExportedType = 0x27000000,
+ ManifestResource = 0x28000000,
+ GenericPar = 0x2a000000,
+ MethodSpec = 0x2b000000,
+ String = 0x70000000,
+ Name = 0x71000000,
+ BaseType = 0x72000000,
+ Invalid = 0x7FFFFFFF,
+ }
+
+ [Serializable]
+ internal struct ConstArray
+ {
+ public IntPtr Signature { get { return m_constArray; } }
+ public int Length { get { return m_length; } }
+ public byte this[int index]
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (index < 0 || index >= m_length)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ unsafe
+ {
+ return ((byte*)m_constArray.ToPointer())[index];
+ }
+ }
+ }
+
+ // Keep the definition in sync with vm\ManagedMdImport.hpp
+ internal int m_length;
+ internal IntPtr m_constArray;
+ }
+
+ [Serializable]
+ internal struct MetadataToken
+ {
+ #region Implicit Cast Operators
+ public static implicit operator int(MetadataToken token) { return token.Value; }
+ public static implicit operator MetadataToken(int token) { return new MetadataToken(token); }
+ #endregion
+
+ #region Public Static Members
+ public static bool IsTokenOfType(int token, params MetadataTokenType[] types)
+ {
+ for (int i = 0; i < types.Length; i++)
+ {
+ if ((int)(token & 0xFF000000) == (int)types[i])
+ return true;
+ }
+
+ return false;
+ }
+
+ public static bool IsNullToken(int token)
+ {
+ return (token & 0x00FFFFFF) == 0;
+ }
+ #endregion
+
+ #region Public Data Members
+ public int Value;
+ #endregion
+
+ #region Constructor
+ public MetadataToken(int token) { Value = token; }
+ #endregion
+
+ #region Public Members
+ public bool IsGlobalTypeDefToken { get { return (Value == 0x02000001); } }
+ public MetadataTokenType TokenType { get { return (MetadataTokenType)(Value & 0xFF000000); } }
+ public bool IsTypeRef { get { return TokenType == MetadataTokenType.TypeRef; } }
+ public bool IsTypeDef { get { return TokenType == MetadataTokenType.TypeDef; } }
+ public bool IsFieldDef { get { return TokenType == MetadataTokenType.FieldDef; } }
+ public bool IsMethodDef { get { return TokenType == MetadataTokenType.MethodDef; } }
+ public bool IsMemberRef { get { return TokenType == MetadataTokenType.MemberRef; } }
+ public bool IsEvent { get { return TokenType == MetadataTokenType.Event; } }
+ public bool IsProperty { get { return TokenType == MetadataTokenType.Property; } }
+ public bool IsParamDef { get { return TokenType == MetadataTokenType.ParamDef; } }
+ public bool IsTypeSpec { get { return TokenType == MetadataTokenType.TypeSpec; } }
+ public bool IsMethodSpec { get { return TokenType == MetadataTokenType.MethodSpec; } }
+ public bool IsString { get { return TokenType == MetadataTokenType.String; } }
+ public bool IsSignature { get { return TokenType == MetadataTokenType.Signature; } }
+ public bool IsModule { get { return TokenType == MetadataTokenType.Module; } }
+ public bool IsAssembly { get { return TokenType == MetadataTokenType.Assembly; } }
+ public bool IsGenericPar { get { return TokenType == MetadataTokenType.GenericPar; } }
+ #endregion
+
+ #region Object Overrides
+ public override string ToString() { return String.Format(CultureInfo.InvariantCulture, "0x{0:x8}", Value); }
+ #endregion
+ }
+
+ internal unsafe struct MetadataEnumResult
+ {
+ // Keep the definition in sync with vm\ManagedMdImport.hpp
+ private int[] largeResult;
+ private int length;
+ private fixed int smallResult[16];
+
+ public int Length
+ {
+ get
+ {
+ return length;
+ }
+ }
+
+ public int this[int index]
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+ Contract.Requires(0 <= index && index < Length);
+ if (largeResult != null)
+ return largeResult[index];
+
+ fixed (int* p = smallResult)
+ return p[index];
+ }
+ }
+ }
+
+ internal struct MetadataImport
+ {
+ #region Private Data Members
+ private IntPtr m_metadataImport2;
+ private object m_keepalive;
+ #endregion
+
+ #region Override methods from Object
+ internal static readonly MetadataImport EmptyImport = new MetadataImport((IntPtr)0, null);
+
+ public override int GetHashCode()
+ {
+ return ValueType.GetHashCodeOfPtr(m_metadataImport2);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if(!(obj is MetadataImport))
+ return false;
+ return Equals((MetadataImport)obj);
+ }
+
+ private bool Equals(MetadataImport import)
+ {
+ return import.m_metadataImport2 == m_metadataImport2;
+ }
+
+ #endregion
+
+ #region Static Members
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetMarshalAs(IntPtr pNativeType, int cNativeType, out int unmanagedType, out int safeArraySubType, out string safeArrayUserDefinedSubType,
+ out int arraySubType, out int sizeParamIndex, out int sizeConst, out string marshalType, out string marshalCookie,
+ out int iidParamIndex);
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void GetMarshalAs(ConstArray nativeType,
+ out UnmanagedType unmanagedType, out VarEnum safeArraySubType, out string safeArrayUserDefinedSubType,
+ out UnmanagedType arraySubType, out int sizeParamIndex, out int sizeConst, out string marshalType, out string marshalCookie,
+ out int iidParamIndex)
+ {
+ int _unmanagedType, _safeArraySubType, _arraySubType;
+
+ _GetMarshalAs(nativeType.Signature, (int)nativeType.Length,
+ out _unmanagedType, out _safeArraySubType, out safeArrayUserDefinedSubType,
+ out _arraySubType, out sizeParamIndex, out sizeConst, out marshalType, out marshalCookie,
+ out iidParamIndex);
+ unmanagedType = (UnmanagedType)_unmanagedType;
+ safeArraySubType = (VarEnum)_safeArraySubType;
+ arraySubType = (UnmanagedType)_arraySubType;
+ }
+ #endregion
+
+ #region Internal Static Members
+ internal static void ThrowError(int hResult)
+ {
+ throw new MetadataException(hResult);
+ }
+ #endregion
+
+ #region Constructor
+ internal MetadataImport(IntPtr metadataImport2, object keepalive)
+ {
+ m_metadataImport2 = metadataImport2;
+ m_keepalive = keepalive;
+ }
+ #endregion
+
+ #region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private unsafe static extern void _Enum(IntPtr scope, int type, int parent, out MetadataEnumResult result);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void Enum(MetadataTokenType type, int parent, out MetadataEnumResult result)
+ {
+ _Enum(m_metadataImport2, (int)type, parent, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumNestedTypes(int mdTypeDef, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.TypeDef, mdTypeDef, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumCustomAttributes(int mdToken, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.CustomAttribute, mdToken, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumParams(int mdMethodDef, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.ParamDef, mdMethodDef, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumFields(int mdTypeDef, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.FieldDef, mdTypeDef, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumProperties(int mdTypeDef, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.Property, mdTypeDef, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void EnumEvents(int mdTypeDef, out MetadataEnumResult result)
+ {
+ Enum(MetadataTokenType.Event, mdTypeDef, out result);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static extern String _GetDefaultValue(IntPtr scope, int mdToken, out long value, out int length, out int corElementType);
+ [System.Security.SecurityCritical] // auto-generated
+ public String GetDefaultValue(int mdToken, out long value, out int length, out CorElementType corElementType)
+ {
+ int _corElementType;
+ String stringVal;
+ stringVal = _GetDefaultValue(m_metadataImport2, mdToken, out value, out length, out _corElementType);
+ corElementType = (CorElementType)_corElementType;
+ return stringVal;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static unsafe extern void _GetUserString(IntPtr scope, int mdToken, void** name, out int length);
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe String GetUserString(int mdToken)
+ {
+ void* name;
+ int length;
+ _GetUserString(m_metadataImport2, mdToken, &name, out length);
+
+ if (name == null)
+ return null;
+
+ char[] c = new char[length];
+ for (int i = 0; i < length; i ++)
+ {
+#if ALIGN_ACCESS
+ c[i] = (char)Marshal.ReadInt16( (IntPtr) (((char*)name) + i) );
+#else
+ c[i] = ((char*)name)[i];
+#endif
+ }
+
+ return new String(c);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static unsafe extern void _GetName(IntPtr scope, int mdToken, void** name);
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe Utf8String GetName(int mdToken)
+ {
+ void* name;
+ _GetName(m_metadataImport2, mdToken, &name);
+
+ return new Utf8String(name);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static unsafe extern void _GetNamespace(IntPtr scope, int mdToken, void** namesp);
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe Utf8String GetNamespace(int mdToken)
+ {
+ void* namesp;
+ _GetNamespace(m_metadataImport2, mdToken, &namesp);
+
+ return new Utf8String(namesp);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private unsafe static extern void _GetEventProps(IntPtr scope, int mdToken, void** name, out int eventAttributes);
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void GetEventProps(int mdToken, out void* name, out EventAttributes eventAttributes)
+ {
+ int _eventAttributes;
+ void* _name;
+ _GetEventProps(m_metadataImport2, mdToken, &_name, out _eventAttributes);
+ name = _name;
+ eventAttributes = (EventAttributes)_eventAttributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static extern void _GetFieldDefProps(IntPtr scope, int mdToken, out int fieldAttributes);
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetFieldDefProps(int mdToken, out FieldAttributes fieldAttributes)
+ {
+ int _fieldAttributes;
+ _GetFieldDefProps(m_metadataImport2, mdToken, out _fieldAttributes);
+ fieldAttributes = (FieldAttributes)_fieldAttributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private unsafe static extern void _GetPropertyProps(IntPtr scope,
+ int mdToken, void** name, out int propertyAttributes, out ConstArray signature);
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void GetPropertyProps(int mdToken, out void* name, out PropertyAttributes propertyAttributes, out ConstArray signature)
+ {
+ int _propertyAttributes;
+ void* _name;
+ _GetPropertyProps(m_metadataImport2, mdToken, &_name, out _propertyAttributes, out signature);
+ name = _name;
+ propertyAttributes = (PropertyAttributes)_propertyAttributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute (MethodImplOptions.InternalCall)]
+ private static extern void _GetParentToken(IntPtr scope,
+ int mdToken, out int tkParent);
+ [System.Security.SecurityCritical] // auto-generated
+ public int GetParentToken(int tkToken)
+ {
+ int tkParent;
+ _GetParentToken(m_metadataImport2, tkToken, out tkParent);
+ return tkParent;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetParamDefProps(IntPtr scope,
+ int parameterToken, out int sequence, out int attributes);
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetParamDefProps(int parameterToken, out int sequence, out ParameterAttributes attributes)
+ {
+ int _attributes;
+
+ _GetParamDefProps(m_metadataImport2, parameterToken, out sequence, out _attributes);
+
+ attributes = (ParameterAttributes)_attributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetGenericParamProps(IntPtr scope,
+ int genericParameter,
+ out int flags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetGenericParamProps(
+ int genericParameter,
+ out GenericParameterAttributes attributes)
+ {
+ int _attributes;
+ _GetGenericParamProps(m_metadataImport2, genericParameter, out _attributes);
+ attributes = (GenericParameterAttributes)_attributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetScopeProps(IntPtr scope,
+ out Guid mvid);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetScopeProps(
+ out Guid mvid)
+ {
+ _GetScopeProps(m_metadataImport2, out mvid);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetMethodSignature(MetadataToken token)
+ {
+ if (token.IsMemberRef)
+ return GetMemberRefProps(token);
+
+ return GetSigOfMethodDef(token);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetSigOfMethodDef(IntPtr scope,
+ int methodToken,
+ ref ConstArray signature);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetSigOfMethodDef(int methodToken)
+ {
+ ConstArray signature = new ConstArray();
+
+ _GetSigOfMethodDef(m_metadataImport2, methodToken, ref signature);
+
+ return signature;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetSignatureFromToken(IntPtr scope,
+ int methodToken,
+ ref ConstArray signature);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetSignatureFromToken(int token)
+ {
+ ConstArray signature = new ConstArray();
+
+ _GetSignatureFromToken(m_metadataImport2, token, ref signature);
+
+ return signature;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetMemberRefProps(IntPtr scope,
+ int memberTokenRef,
+ out ConstArray signature);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetMemberRefProps(int memberTokenRef)
+ {
+ ConstArray signature = new ConstArray();
+
+ _GetMemberRefProps(m_metadataImport2, memberTokenRef, out signature);
+
+ return signature;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetCustomAttributeProps(IntPtr scope,
+ int customAttributeToken,
+ out int constructorToken,
+ out ConstArray signature);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetCustomAttributeProps(
+ int customAttributeToken,
+ out int constructorToken,
+ out ConstArray signature)
+ {
+ _GetCustomAttributeProps(m_metadataImport2, customAttributeToken,
+ out constructorToken, out signature);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetClassLayout(IntPtr scope,
+ int typeTokenDef, out int packSize, out int classSize);
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetClassLayout(
+ int typeTokenDef,
+ out int packSize,
+ out int classSize)
+ {
+ _GetClassLayout(m_metadataImport2, typeTokenDef, out packSize, out classSize);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool _GetFieldOffset(IntPtr scope,
+ int typeTokenDef, int fieldTokenDef, out int offset);
+ [System.Security.SecurityCritical] // auto-generated
+ public bool GetFieldOffset(
+ int typeTokenDef,
+ int fieldTokenDef,
+ out int offset)
+ {
+ return _GetFieldOffset(m_metadataImport2, typeTokenDef, fieldTokenDef, out offset);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetSigOfFieldDef(IntPtr scope,
+ int fieldToken,
+ ref ConstArray fieldMarshal);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetSigOfFieldDef(int fieldToken)
+ {
+ ConstArray fieldMarshal = new ConstArray();
+
+ _GetSigOfFieldDef(m_metadataImport2, fieldToken, ref fieldMarshal);
+
+ return fieldMarshal;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetFieldMarshal(IntPtr scope,
+ int fieldToken,
+ ref ConstArray fieldMarshal);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ConstArray GetFieldMarshal(int fieldToken)
+ {
+ ConstArray fieldMarshal = new ConstArray();
+
+ _GetFieldMarshal(m_metadataImport2, fieldToken, ref fieldMarshal);
+
+ return fieldMarshal;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private unsafe static extern void _GetPInvokeMap(IntPtr scope,
+ int token,
+ out int attributes,
+ void** importName,
+ void** importDll);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe void GetPInvokeMap(
+ int token,
+ out PInvokeAttributes attributes,
+ out String importName,
+ out String importDll)
+ {
+ int _attributes;
+ void* _importName, _importDll;
+ _GetPInvokeMap(m_metadataImport2, token, out _attributes, &_importName, &_importDll);
+ importName = new Utf8String(_importName).ToString();
+ importDll = new Utf8String(_importDll).ToString();
+
+ attributes = (PInvokeAttributes)_attributes;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool _IsValidToken(IntPtr scope, int token);
+ [System.Security.SecurityCritical] // auto-generated
+ public bool IsValidToken(int token)
+ {
+ return _IsValidToken(m_metadataImport2, token);
+ }
+ #endregion
+ }
+
+
+ internal class MetadataException : Exception
+ {
+ private int m_hr;
+ internal MetadataException(int hr) { m_hr = hr; }
+
+ public override string ToString()
+ {
+ return String.Format(CultureInfo.CurrentCulture, "MetadataException HResult = {0:x}.", m_hr);
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Reflection/MemberFilter.cs b/src/mscorlib/src/System/Reflection/MemberFilter.cs
new file mode 100644
index 0000000000..b476409d5d
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MemberFilter.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// MemberFilter is a delegate used to filter Members. This delegate is used
+//
+// as a callback from Type.FindMembers.
+//
+//
+namespace System.Reflection {
+
+ // Define the delegate
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate bool MemberFilter(MemberInfo m, Object filterCriteria);
+}
diff --git a/src/mscorlib/src/System/Reflection/MemberInfo.cs b/src/mscorlib/src/System/Reflection/MemberInfo.cs
new file mode 100644
index 0000000000..248c78bf70
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MemberInfo.cs
@@ -0,0 +1,148 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_MemberInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class MemberInfo : ICustomAttributeProvider, _MemberInfo
+ {
+ #region Constructor
+ protected MemberInfo() { }
+ #endregion
+
+ #region Internal Methods
+ internal virtual bool CacheEquals(object o) { throw new NotImplementedException(); }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public abstract MemberTypes MemberType { get; }
+
+ public abstract String Name { get; }
+
+ public abstract Type DeclaringType { get; }
+
+ public abstract Type ReflectedType { get; }
+
+ public virtual IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return GetCustomAttributesData();
+ }
+ }
+ public abstract Object[] GetCustomAttributes(bool inherit);
+
+ public abstract Object[] GetCustomAttributes(Type attributeType, bool inherit);
+
+ public abstract bool IsDefined(Type attributeType, bool inherit);
+
+ public virtual IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual int MetadataToken { get { throw new InvalidOperationException(); } }
+
+ public virtual Module Module
+ {
+ get
+ {
+ if (this is Type)
+ return ((Type)this).Module;
+
+ throw new NotImplementedException();
+ }
+ }
+
+
+
+ #endregion
+
+ public static bool operator ==(MemberInfo left, MemberInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null)
+ return false;
+
+ Type type1, type2;
+ MethodBase method1, method2;
+ FieldInfo field1, field2;
+ EventInfo event1, event2;
+ PropertyInfo property1, property2;
+
+ if ((type1 = left as Type) != null && (type2 = right as Type) != null)
+ return type1 == type2;
+ else if ((method1 = left as MethodBase) != null && (method2 = right as MethodBase) != null)
+ return method1 == method2;
+ else if ((field1 = left as FieldInfo) != null && (field2 = right as FieldInfo) != null)
+ return field1 == field2;
+ else if ((event1 = left as EventInfo) != null && (event2 = right as EventInfo) != null)
+ return event1 == event2;
+ else if ((property1 = left as PropertyInfo) != null && (property2 = right as PropertyInfo) != null)
+ return property1 == property2;
+
+ return false;
+ }
+
+ public static bool operator !=(MemberInfo left, MemberInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+#if !FEATURE_CORECLR
+ // this method is required so Object.GetType is not made final virtual by the compiler
+ Type _MemberInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ void _MemberInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MemberInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MemberInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MemberInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs b/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs
new file mode 100644
index 0000000000..c1b4ee5fe1
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MemberInfoSerializationHolder.cs
@@ -0,0 +1,287 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime.Remoting;
+using System.Runtime.Serialization;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+
+namespace System.Reflection
+{
+ [Serializable]
+ internal class MemberInfoSerializationHolder : ISerializable, IObjectReference
+ {
+ #region Staitc Public Members
+ public static void GetSerializationInfo(SerializationInfo info, String name, RuntimeType reflectedClass, String signature, MemberTypes type)
+ {
+ GetSerializationInfo(info, name, reflectedClass, signature, null, type, null);
+ }
+
+ public static void GetSerializationInfo(
+ SerializationInfo info,
+ String name,
+ RuntimeType reflectedClass,
+ String signature,
+ String signature2,
+ MemberTypes type,
+ Type[] genericArguments)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ String assemblyName = reflectedClass.Module.Assembly.FullName;
+ String typeName = reflectedClass.FullName;
+
+ info.SetType(typeof(MemberInfoSerializationHolder));
+ info.AddValue("Name", name, typeof(String));
+ info.AddValue("AssemblyName", assemblyName, typeof(String));
+ info.AddValue("ClassName", typeName, typeof(String));
+ info.AddValue("Signature", signature, typeof(String));
+ info.AddValue("Signature2", signature2, typeof(String));
+ info.AddValue("MemberType", (int)type);
+ info.AddValue("GenericArguments", genericArguments, typeof(Type[]));
+ }
+ #endregion
+
+ #region Private Data Members
+ private String m_memberName;
+ private RuntimeType m_reflectedType;
+ // m_signature stores the ToString() representation of the member which is sometimes ambiguous.
+ // Mulitple overloads of the same methods or properties can identical ToString().
+ // m_signature2 stores the SerializationToString() representation which should be unique for each member.
+ // It is only written and used by post 4.0 CLR versions.
+ private String m_signature;
+ private String m_signature2;
+ private MemberTypes m_memberType;
+ private SerializationInfo m_info;
+ #endregion
+
+ #region Constructor
+ internal MemberInfoSerializationHolder(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ String assemblyName = info.GetString("AssemblyName");
+ String typeName = info.GetString("ClassName");
+
+ if (assemblyName == null || typeName == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+
+ Assembly assem = FormatterServices.LoadAssemblyFromString(assemblyName);
+ m_reflectedType = assem.GetType(typeName, true, false) as RuntimeType;
+ m_memberName = info.GetString("Name");
+ m_signature = info.GetString("Signature");
+ // Only v4.0 and later generates and consumes Signature2
+ m_signature2 = (string)info.GetValueNoThrow("Signature2", typeof(string));
+ m_memberType = (MemberTypes)info.GetInt32("MemberType");
+ m_info = info;
+ }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(Environment.GetResourceString(ResId.NotSupported_Method));
+ }
+ #endregion
+
+ #region IObjectReference
+ [System.Security.SecurityCritical] // auto-generated
+ public virtual Object GetRealObject(StreamingContext context)
+ {
+ if (m_memberName == null || m_reflectedType == null || m_memberType == 0)
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_InsufficientState));
+
+ BindingFlags bindingFlags =
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Static | BindingFlags.OptionalParamBinding;
+
+ switch (m_memberType)
+ {
+ #region case MemberTypes.Field:
+ case MemberTypes.Field:
+ {
+ FieldInfo[] fields = m_reflectedType.GetMember(m_memberName, MemberTypes.Field, bindingFlags) as FieldInfo[];
+
+ if (fields.Length == 0)
+ throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMember", m_memberName));
+
+ return fields[0];
+ }
+ #endregion
+
+ #region case MemberTypes.Event:
+ case MemberTypes.Event:
+ {
+ EventInfo[] events = m_reflectedType.GetMember(m_memberName, MemberTypes.Event, bindingFlags) as EventInfo[];
+
+ if (events.Length == 0)
+ throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMember", m_memberName));
+
+ return events[0];
+ }
+ #endregion
+
+ #region case MemberTypes.Property:
+ case MemberTypes.Property:
+ {
+ PropertyInfo[] properties = m_reflectedType.GetMember(m_memberName, MemberTypes.Property, bindingFlags) as PropertyInfo[];
+
+ if (properties.Length == 0)
+ throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMember", m_memberName));
+
+ if (properties.Length == 1)
+ return properties[0];
+
+ if (properties.Length > 1)
+ {
+ for (int i = 0; i < properties.Length; i++)
+ {
+ if (m_signature2 != null)
+ {
+ if (((RuntimePropertyInfo)properties[i]).SerializationToString().Equals(m_signature2))
+ return properties[i];
+ }
+ else
+ {
+ if ((properties[i]).ToString().Equals(m_signature))
+ return properties[i];
+ }
+ }
+ }
+
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_UnknownMember, m_memberName));
+ }
+ #endregion
+
+ #region case MemberTypes.Constructor:
+ case MemberTypes.Constructor:
+ {
+ if (m_signature == null)
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_NullSignature));
+
+ ConstructorInfo[] constructors = m_reflectedType.GetMember(m_memberName, MemberTypes.Constructor, bindingFlags) as ConstructorInfo[];
+
+ if (constructors.Length == 1)
+ return constructors[0];
+
+ if (constructors.Length > 1)
+ {
+ for (int i = 0; i < constructors.Length; i++)
+ {
+ if (m_signature2 != null)
+ {
+ if (((RuntimeConstructorInfo)constructors[i]).SerializationToString().Equals(m_signature2))
+ return constructors[i];
+ }
+ else
+ {
+ if (constructors[i].ToString().Equals(m_signature))
+ return constructors[i];
+ }
+ }
+ }
+
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_UnknownMember, m_memberName));
+ }
+ #endregion
+
+ #region case MemberTypes.Method:
+ case MemberTypes.Method:
+ {
+ MethodInfo methodInfo = null;
+
+ if (m_signature == null)
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_NullSignature));
+
+ Type[] genericArguments = m_info.GetValueNoThrow("GenericArguments", typeof(Type[])) as Type[];
+
+ MethodInfo[] methods = m_reflectedType.GetMember(m_memberName, MemberTypes.Method, bindingFlags) as MethodInfo[];
+
+ if (methods.Length == 1)
+ methodInfo = methods[0];
+
+ else if (methods.Length > 1)
+ {
+ for (int i = 0; i < methods.Length; i++)
+ {
+ if (m_signature2 != null)
+ {
+ if (((RuntimeMethodInfo)methods[i]).SerializationToString().Equals(m_signature2))
+ {
+ methodInfo = methods[i];
+ break;
+ }
+ }
+ else
+ {
+
+ if (methods[i].ToString().Equals(m_signature))
+ {
+ methodInfo = methods[i];
+ break;
+ }
+ }
+
+ // Handle generic methods specially since the signature match above probably won't work (the candidate
+ // method info hasn't been instantiated). If our target method is generic as well we can skip this.
+ if (genericArguments != null && methods[i].IsGenericMethod)
+ {
+ if (methods[i].GetGenericArguments().Length == genericArguments.Length)
+ {
+ MethodInfo candidateMethod = methods[i].MakeGenericMethod(genericArguments);
+
+ if (m_signature2 != null)
+ {
+ if (((RuntimeMethodInfo)candidateMethod).SerializationToString().Equals(m_signature2))
+ {
+ methodInfo = candidateMethod;
+ break;
+ }
+ }
+ else
+ {
+ if (candidateMethod.ToString().Equals(m_signature))
+ {
+ methodInfo = candidateMethod;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (methodInfo == null)
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_UnknownMember, m_memberName));
+
+ if (!methodInfo.IsGenericMethodDefinition)
+ return methodInfo;
+
+ if (genericArguments == null)
+ return methodInfo;
+
+ if (genericArguments[0] == null)
+ return null;
+
+ return methodInfo.MakeGenericMethod(genericArguments);
+ }
+ #endregion
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Serialization_MemberTypeNotRecognized"));
+ }
+ }
+ #endregion
+ }
+
+
+}
diff --git a/src/mscorlib/src/System/Reflection/MemberTypes.cs b/src/mscorlib/src/System/Reflection/MemberTypes.cs
new file mode 100644
index 0000000000..352a80244e
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MemberTypes.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// MemberTypes is an bit mask marking each type of Member that is defined as
+//
+// a subclass of MemberInfo. These are returned by MemberInfo.MemberType and
+// are useful in switch statements.
+//
+//
+namespace System.Reflection {
+
+ using System;
+ // This Enum matchs the CorTypeAttr defined in CorHdr.h
+ [Serializable]
+ [Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum MemberTypes
+ {
+ // The following are the known classes which extend MemberInfo
+ Constructor = 0x01,
+ Event = 0x02,
+ Field = 0x04,
+ Method = 0x08,
+ Property = 0x10,
+ TypeInfo = 0x20,
+ Custom = 0x40,
+ NestedType = 0x80,
+ All = Constructor | Event | Field | Method | Property | TypeInfo | NestedType,
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs
new file mode 100644
index 0000000000..dd5d69b1fb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Metadata/AssemblyExtensions.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Reflection.Metadata
+{
+ public static class AssemblyExtensions
+ {
+ [DllImport(JitHelpers.QCall)]
+ [SecurityCritical] // unsafe method
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private unsafe static extern bool InternalTryGetRawMetadata(RuntimeAssembly assembly, ref byte* blob, ref int length);
+
+ // Retrieves the metadata section of the assembly, for use with System.Reflection.Metadata.MetadataReader.
+ // - Returns false upon failure. Metadata might not be available for some assemblies, such as AssemblyBuilder, .NET
+ // native images, etc.
+ // - Callers should not write to the metadata blob
+ // - The metadata blob pointer will remain valid as long as the AssemblyLoadContext with which the assembly is
+ // associated, is alive. The caller is responsible for keeping the assembly object alive while accessing the
+ // metadata blob.
+ [CLSCompliant(false)] // out byte* blob
+ [SecurityCritical] // unsafe method
+ public unsafe static bool TryGetRawMetadata(this Assembly assembly, out byte* blob, out int length)
+ {
+ if (assembly == null)
+ {
+ throw new ArgumentNullException("assembly");
+ }
+
+ blob = null;
+ length = 0;
+
+ var runtimeAssembly = assembly as RuntimeAssembly;
+ if (runtimeAssembly == null)
+ {
+ return false;
+ }
+
+ return InternalTryGetRawMetadata(runtimeAssembly, ref blob, ref length);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/MethodAttributes.cs b/src/mscorlib/src/System/Reflection/MethodAttributes.cs
new file mode 100644
index 0000000000..92b637b9c0
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MethodAttributes.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+
+namespace System.Reflection
+{
+ using System;
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum MethodAttributes
+ {
+ // NOTE: This Enum matchs the CorMethodAttr defined in CorHdr.h
+
+ // member access mask - Use this mask to retrieve accessibility information.
+ MemberAccessMask = 0x0007,
+ PrivateScope = 0x0000, // Member not referenceable.
+ Private = 0x0001, // Accessible only by the parent type.
+ FamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly.
+ Assembly = 0x0003, // Accessibly by anyone in the Assembly.
+ Family = 0x0004, // Accessible only by type and sub-types.
+ FamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly.
+ Public = 0x0006, // Accessibly by anyone who has visibility to this scope.
+ // end member access mask
+
+ // method contract attributes.
+ Static = 0x0010, // Defined on type, else per instance.
+ Final = 0x0020, // Method may not be overridden.
+ Virtual = 0x0040, // Method virtual.
+ HideBySig = 0x0080, // Method hides by name+sig, else just by name.
+ CheckAccessOnOverride= 0x0200,
+
+ // vtable layout mask - Use this mask to retrieve vtable attributes.
+ VtableLayoutMask = 0x0100,
+ ReuseSlot = 0x0000, // The default.
+ NewSlot = 0x0100, // Method always gets a new slot in the vtable.
+ // end vtable layout mask
+
+ // method implementation attributes.
+ Abstract = 0x0400, // Method does not provide an implementation.
+ SpecialName = 0x0800, // Method is special. Name describes how.
+
+ // interop attributes
+ PinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke.
+ UnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code.
+ RTSpecialName = 0x1000, // Runtime should check name encoding.
+
+ // Reserved flags for runtime use only.
+ ReservedMask = 0xd000,
+ HasSecurity = 0x4000, // Method has security associate with it.
+ RequireSecObject = 0x8000, // Method calls another method containing security code.
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/MethodBase.cs b/src/mscorlib/src/System/Reflection/MethodBase.cs
new file mode 100644
index 0000000000..68363bf1e0
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MethodBase.cs
@@ -0,0 +1,402 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+
+ //
+ // Invocation cached flags. Those are used in unmanaged code as well
+ // so be careful if you change them
+ //
+ [Flags]
+ internal enum INVOCATION_FLAGS : uint
+ {
+ INVOCATION_FLAGS_UNKNOWN = 0x00000000,
+ INVOCATION_FLAGS_INITIALIZED = 0x00000001,
+ // it's used for both method and field to signify that no access is allowed
+ INVOCATION_FLAGS_NO_INVOKE = 0x00000002,
+ INVOCATION_FLAGS_NEED_SECURITY = 0x00000004,
+ // Set for static ctors and ctors on abstract types, which
+ // can be invoked only if the "this" object is provided (even if it's null).
+ INVOCATION_FLAGS_NO_CTOR_INVOKE = 0x00000008,
+ // because field and method are different we can reuse the same bits
+ // method
+ INVOCATION_FLAGS_IS_CTOR = 0x00000010,
+ INVOCATION_FLAGS_RISKY_METHOD = 0x00000020,
+ INVOCATION_FLAGS_NON_W8P_FX_API = 0x00000040,
+ INVOCATION_FLAGS_IS_DELEGATE_CTOR = 0x00000080,
+ INVOCATION_FLAGS_CONTAINS_STACK_POINTERS = 0x00000100,
+ // field
+ INVOCATION_FLAGS_SPECIAL_FIELD = 0x00000010,
+ INVOCATION_FLAGS_FIELD_SPECIAL_CAST = 0x00000020,
+
+ // temporary flag used for flagging invocation of method vs ctor
+ // this flag never appears on the instance m_invocationFlag and is simply
+ // passed down from within ConstructorInfo.Invoke()
+ INVOCATION_FLAGS_CONSTRUCTOR_INVOKE = 0x10000000,
+ }
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_MethodBase))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class MethodBase : MemberInfo, _MethodBase
+ {
+ #region Static Members
+ public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle)
+ {
+ if (handle.IsNullHandle())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
+
+ MethodBase m = RuntimeType.GetMethodBase(handle.GetMethodInfo());
+
+ Type declaringType = m.DeclaringType;
+ if (declaringType != null && declaringType.IsGenericType)
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_MethodDeclaringTypeGeneric"),
+ m, declaringType.GetGenericTypeDefinition()));
+
+ return m;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static MethodBase GetMethodFromHandle(RuntimeMethodHandle handle, RuntimeTypeHandle declaringType)
+ {
+ if (handle.IsNullHandle())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidHandle"));
+
+ return RuntimeType.GetMethodBase(declaringType.GetRuntimeType(), handle.GetMethodInfo());
+ }
+
+ [System.Security.DynamicSecurityMethod] // Specify DynamicSecurityMethod attribute to prevent inlining of the caller.
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static MethodBase GetCurrentMethod()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeMethodInfo.InternalGetCurrentMethod(ref stackMark);
+ }
+ #endregion
+
+ #region Constructor
+ protected MethodBase() { }
+ #endregion
+
+ public static bool operator ==(MethodBase left, MethodBase right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null)
+ return false;
+
+ MethodInfo method1, method2;
+ ConstructorInfo constructor1, constructor2;
+
+ if ((method1 = left as MethodInfo) != null && (method2 = right as MethodInfo) != null)
+ return method1 == method2;
+ else if ((constructor1 = left as ConstructorInfo) != null && (constructor2 = right as ConstructorInfo) != null)
+ return constructor1 == constructor2;
+
+ return false;
+ }
+
+ public static bool operator !=(MethodBase left, MethodBase right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region Internal Members
+ // used by EE
+ [System.Security.SecurityCritical]
+ private IntPtr GetMethodDesc() { return MethodHandle.Value; }
+
+#if FEATURE_APPX
+
+ // The C# dynamic and VB late bound binders need to call this API. Since we don't have time to make this
+ // public in Dev11, the C# and VB binders currently call this through a delegate.
+ // When we make this API public (hopefully) in Dev12 we need to change the C# and VB binders to call this
+ // probably statically. The code is located in:
+ // C#: ndp\fx\src\CSharp\Microsoft\CSharp\SymbolTable.cs - Microsoft.CSharp.RuntimeBinder.SymbolTable..cctor
+ // VB: vb\runtime\msvbalib\helpers\Symbols.vb - Microsoft.VisualBasic.CompilerServices.Symbols..cctor
+ internal virtual bool IsDynamicallyInvokable
+ {
+ get
+ {
+ return true;
+ }
+ }
+#endif
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ internal virtual ParameterInfo[] GetParametersNoCopy() { return GetParameters (); }
+
+ [System.Diagnostics.Contracts.Pure]
+ public abstract ParameterInfo[] GetParameters();
+
+ public virtual MethodImplAttributes MethodImplementationFlags
+ {
+ get
+ {
+ return GetMethodImplementationFlags();
+ }
+ }
+
+ public abstract MethodImplAttributes GetMethodImplementationFlags();
+
+ public abstract RuntimeMethodHandle MethodHandle { get; }
+
+ public abstract MethodAttributes Attributes { get; }
+
+ public abstract Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture);
+
+ public virtual CallingConventions CallingConvention { get { return CallingConventions.Standard; } }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+
+ public virtual bool IsGenericMethodDefinition { get { return false; } }
+
+ public virtual bool ContainsGenericParameters { get { return false; } }
+
+ public virtual bool IsGenericMethod { get { return false; } }
+
+ public virtual bool IsSecurityCritical { get { throw new NotImplementedException(); } }
+
+ public virtual bool IsSecuritySafeCritical { get { throw new NotImplementedException(); } }
+
+ public virtual bool IsSecurityTransparent { get { throw new NotImplementedException(); } }
+
+ #endregion
+
+ #region Public Members
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public Object Invoke(Object obj, Object[] parameters)
+ {
+ // Theoretically we should set up a LookForMyCaller stack mark here and pass that along.
+ // But to maintain backward compatibility we can't switch to calling an
+ // internal overload that takes a stack mark.
+ // Fortunately the stack walker skips all the reflection invocation frames including this one.
+ // So this method will never be returned by the stack walker as the caller.
+ // See SystemDomain::CallersMethodCallbackWithStackMark in AppDomain.cpp.
+ return Invoke(obj, BindingFlags.Default, null, parameters, null);
+ }
+
+ public bool IsPublic { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public; } }
+
+ public bool IsPrivate { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private; } }
+
+ public bool IsFamily { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family; } }
+
+ public bool IsAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly; } }
+
+ public bool IsFamilyAndAssembly { get { return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem; } }
+
+ public bool IsFamilyOrAssembly { get {return(Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem; } }
+
+ public bool IsStatic { get { return(Attributes & MethodAttributes.Static) != 0; } }
+
+ public bool IsFinal { get { return(Attributes & MethodAttributes.Final) != 0; }
+ }
+ public bool IsVirtual { get { return(Attributes & MethodAttributes.Virtual) != 0; }
+ }
+ public bool IsHideBySig { get { return(Attributes & MethodAttributes.HideBySig) != 0; } }
+
+ public bool IsAbstract { get { return(Attributes & MethodAttributes.Abstract) != 0; } }
+
+ public bool IsSpecialName { get { return(Attributes & MethodAttributes.SpecialName) != 0; } }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public bool IsConstructor
+ {
+ get
+ {
+ // To be backward compatible we only return true for instance RTSpecialName ctors.
+ return (this is ConstructorInfo &&
+ !IsStatic &&
+ ((Attributes & MethodAttributes.RTSpecialName) == MethodAttributes.RTSpecialName));
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+#pragma warning disable 618
+ [ReflectionPermissionAttribute(SecurityAction.Demand, Flags=ReflectionPermissionFlag.MemberAccess)]
+#pragma warning restore 618
+ public virtual MethodBody GetMethodBody()
+ {
+ throw new InvalidOperationException();
+ }
+ #endregion
+
+ #region Internal Methods
+ // helper method to construct the string representation of the parameter list
+
+ internal static string ConstructParameters(Type[] parameterTypes, CallingConventions callingConvention, bool serialization)
+ {
+ StringBuilder sbParamList = new StringBuilder();
+ string comma = "";
+
+ for (int i = 0; i < parameterTypes.Length; i++)
+ {
+ Type t = parameterTypes[i];
+
+ sbParamList.Append(comma);
+
+ string typeName = t.FormatTypeName(serialization);
+
+ // Legacy: Why use "ByRef" for by ref parameters? What language is this?
+ // VB uses "ByRef" but it should precede (not follow) the parameter name.
+ // Why don't we just use "&"?
+ if (t.IsByRef && !serialization)
+ {
+ sbParamList.Append(typeName.TrimEnd(new char[] { '&' }));
+ sbParamList.Append(" ByRef");
+ }
+ else
+ {
+ sbParamList.Append(typeName);
+ }
+
+ comma = ", ";
+ }
+
+ if ((callingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
+ {
+ sbParamList.Append(comma);
+ sbParamList.Append("...");
+ }
+
+ return sbParamList.ToString();
+ }
+
+ internal string FullName
+ {
+ get
+ {
+ return String.Format("{0}.{1}", DeclaringType.FullName, FormatNameAndSig());
+ }
+ }
+ internal string FormatNameAndSig()
+ {
+ return FormatNameAndSig(false);
+ }
+
+ internal virtual string FormatNameAndSig(bool serialization)
+ {
+ // Serialization uses ToString to resolve MethodInfo overloads.
+ StringBuilder sbName = new StringBuilder(Name);
+
+ sbName.Append("(");
+ sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization));
+ sbName.Append(")");
+
+ return sbName.ToString();
+ }
+
+ internal virtual Type[] GetParameterTypes()
+ {
+ ParameterInfo[] paramInfo = GetParametersNoCopy();
+
+ Type[] parameterTypes = new Type[paramInfo.Length];
+ for (int i = 0; i < paramInfo.Length; i++)
+ parameterTypes[i] = paramInfo[i].ParameterType;
+
+ return parameterTypes;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal Object[] CheckArguments(Object[] parameters, Binder binder,
+ BindingFlags invokeAttr, CultureInfo culture, Signature sig)
+ {
+ // copy the arguments in a different array so we detach from any user changes
+ Object[] copyOfParameters = new Object[parameters.Length];
+
+ ParameterInfo[] p = null;
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ Object arg = parameters[i];
+ RuntimeType argRT = sig.Arguments[i];
+
+ if (arg == Type.Missing)
+ {
+ if (p == null)
+ p = GetParametersNoCopy();
+ if (p[i].DefaultValue == System.DBNull.Value)
+ throw new ArgumentException(Environment.GetResourceString("Arg_VarMissNull"),"parameters");
+ arg = p[i].DefaultValue;
+ }
+ copyOfParameters[i] = argRT.CheckValue(arg, binder, culture, invokeAttr);
+ }
+
+ return copyOfParameters;
+ }
+ #endregion
+
+ #region _MethodBase Implementation
+#if !FEATURE_CORECLR
+ Type _MethodBase.GetType() { return base.GetType(); }
+ bool _MethodBase.IsPublic { get { return IsPublic; } }
+ bool _MethodBase.IsPrivate { get { return IsPrivate; } }
+ bool _MethodBase.IsFamily { get { return IsFamily; } }
+ bool _MethodBase.IsAssembly { get { return IsAssembly; } }
+ bool _MethodBase.IsFamilyAndAssembly { get { return IsFamilyAndAssembly; } }
+ bool _MethodBase.IsFamilyOrAssembly { get { return IsFamilyOrAssembly; } }
+ bool _MethodBase.IsStatic { get { return IsStatic; } }
+ bool _MethodBase.IsFinal { get { return IsFinal; } }
+ bool _MethodBase.IsVirtual { get { return IsVirtual; } }
+ bool _MethodBase.IsHideBySig { get { return IsHideBySig; } }
+ bool _MethodBase.IsAbstract { get { return IsAbstract; } }
+ bool _MethodBase.IsSpecialName { get { return IsSpecialName; } }
+ bool _MethodBase.IsConstructor { get { return IsConstructor; } }
+
+ void _MethodBase.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodBase.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodBase.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _MethodBase.Invoke in VM\DangerousAPIs.h and
+ // include _MethodBase in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _MethodBase.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ #endregion
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/MethodBody.cs b/src/mscorlib/src/System/Reflection/MethodBody.cs
new file mode 100644
index 0000000000..81d7a9ea0e
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MethodBody.cs
@@ -0,0 +1,169 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace System.Reflection
+{
+ [Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ExceptionHandlingClauseOptions: int
+ {
+ Clause = 0x0,
+ Filter = 0x1,
+ Finally = 0x2,
+ Fault = 0x4,
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ExceptionHandlingClause
+ {
+ #region costructor
+ // This class can only be created from inside the EE.
+ protected ExceptionHandlingClause() { }
+ #endregion
+
+ #region Private Data Members
+ private MethodBody m_methodBody;
+ [ContractPublicPropertyName("Flags")]
+ private ExceptionHandlingClauseOptions m_flags;
+ private int m_tryOffset;
+ private int m_tryLength;
+ private int m_handlerOffset;
+ private int m_handlerLength;
+ private int m_catchMetadataToken;
+ private int m_filterOffset;
+ #endregion
+
+ #region Public Members
+ public virtual ExceptionHandlingClauseOptions Flags { get { return m_flags; } }
+ public virtual int TryOffset { get { return m_tryOffset; } }
+ public virtual int TryLength { get { return m_tryLength; } }
+ public virtual int HandlerOffset { get { return m_handlerOffset; } }
+ public virtual int HandlerLength { get { return m_handlerLength; } }
+
+ public virtual int FilterOffset
+ {
+ get
+ {
+ if (m_flags != ExceptionHandlingClauseOptions.Filter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_EHClauseNotFilter"));
+
+ return m_filterOffset;
+ }
+ }
+
+ public virtual Type CatchType
+ {
+ get
+ {
+ if (m_flags != ExceptionHandlingClauseOptions.Clause)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_EHClauseNotClause"));
+
+ Type type = null;
+
+ if (!MetadataToken.IsNullToken(m_catchMetadataToken))
+ {
+ Type declaringType = m_methodBody.m_methodBase.DeclaringType;
+ Module module = (declaringType == null) ? m_methodBody.m_methodBase.Module : declaringType.Module;
+ type = module.ResolveType(m_catchMetadataToken, (declaringType == null) ? null : declaringType.GetGenericArguments(),
+ m_methodBody.m_methodBase is MethodInfo ? m_methodBody.m_methodBase.GetGenericArguments() : null);
+ }
+
+ return type;
+ }
+ }
+ #endregion
+
+ #region Object Overrides
+ public override string ToString()
+ {
+ if (Flags == ExceptionHandlingClauseOptions.Clause)
+ {
+ return String.Format(CultureInfo.CurrentUICulture,
+ "Flags={0}, TryOffset={1}, TryLength={2}, HandlerOffset={3}, HandlerLength={4}, CatchType={5}",
+ Flags, TryOffset, TryLength, HandlerOffset, HandlerLength, CatchType);
+ }
+
+ if (Flags == ExceptionHandlingClauseOptions.Filter)
+ {
+ return String.Format(CultureInfo.CurrentUICulture,
+ "Flags={0}, TryOffset={1}, TryLength={2}, HandlerOffset={3}, HandlerLength={4}, FilterOffset={5}",
+ Flags, TryOffset, TryLength, HandlerOffset, HandlerLength, FilterOffset);
+ }
+
+ return String.Format(CultureInfo.CurrentUICulture,
+ "Flags={0}, TryOffset={1}, TryLength={2}, HandlerOffset={3}, HandlerLength={4}",
+ Flags, TryOffset, TryLength, HandlerOffset, HandlerLength);
+
+ }
+ #endregion
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class MethodBody
+ {
+ #region costructor
+ // This class can only be created from inside the EE.
+ protected MethodBody() { }
+ #endregion
+
+ #region Private Data Members
+ private byte[] m_IL;
+ private ExceptionHandlingClause[] m_exceptionHandlingClauses;
+ private LocalVariableInfo[] m_localVariables;
+ internal MethodBase m_methodBase;
+ private int m_localSignatureMetadataToken;
+ private int m_maxStackSize;
+ private bool m_initLocals;
+ #endregion
+
+ #region Public Members
+ public virtual int LocalSignatureMetadataToken { get { return m_localSignatureMetadataToken; } }
+ public virtual IList<LocalVariableInfo> LocalVariables { get { return Array.AsReadOnly(m_localVariables); } }
+ public virtual int MaxStackSize { get { return m_maxStackSize; } }
+ public virtual bool InitLocals { get { return m_initLocals; } }
+ public virtual byte[] GetILAsByteArray() { return m_IL; }
+ public virtual IList<ExceptionHandlingClause> ExceptionHandlingClauses { get { return Array.AsReadOnly(m_exceptionHandlingClauses); } }
+ #endregion
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class LocalVariableInfo
+ {
+ #region Private Data Members
+ private RuntimeType m_type;
+ private int m_isPinned;
+ private int m_localIndex;
+ #endregion
+
+ #region Constructor
+ protected LocalVariableInfo() { }
+ #endregion
+
+ #region Object Overrides
+ public override string ToString()
+ {
+ string toString = LocalType.ToString() + " (" + LocalIndex + ")";
+
+ if (IsPinned)
+ toString += " (pinned)";
+
+ return toString;
+ }
+ #endregion
+
+ #region Public Members
+ public virtual Type LocalType { get { Contract.Assert(m_type != null, "type must be set!"); return m_type; } }
+ public virtual bool IsPinned { get { return m_isPinned != 0; } }
+ public virtual int LocalIndex { get { return m_localIndex; } }
+ #endregion
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/MethodImplAttributes.cs b/src/mscorlib/src/System/Reflection/MethodImplAttributes.cs
new file mode 100644
index 0000000000..0fa4d00f19
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MethodImplAttributes.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+
+ using System;
+ // This Enum matchs the CorMethodImpl defined in CorHdr.h
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum MethodImplAttributes
+ {
+ // code impl mask
+ CodeTypeMask = 0x0003, // Flags about code type.
+ IL = 0x0000, // Method impl is IL.
+ Native = 0x0001, // Method impl is native.
+ /// <internalonly/>
+ OPTIL = 0x0002, // Method impl is OPTIL
+ Runtime = 0x0003, // Method impl is provided by the runtime.
+ // end code impl mask
+
+ // managed mask
+ ManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged.
+ Unmanaged = 0x0004, // Method impl is unmanaged, otherwise managed.
+ Managed = 0x0000, // Method impl is managed.
+ // end managed mask
+
+ // implementation info and interop
+ ForwardRef = 0x0010, // Indicates method is not defined; used primarily in merge scenarios.
+ PreserveSig = 0x0080, // Indicates method sig is exported exactly as declared.
+
+ InternalCall = 0x1000, // Internal Call...
+
+ Synchronized = 0x0020, // Method is single threaded through the body.
+ NoInlining = 0x0008, // Method may not be inlined.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ AggressiveInlining = 0x0100, // Method should be inlined if possible.
+ NoOptimization = 0x0040, // Method may not be optimized.
+
+ MaxMethodImplVal = 0xFFFF, // Range check value
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/MethodInfo.cs b/src/mscorlib/src/System/Reflection/MethodInfo.cs
new file mode 100644
index 0000000000..eeb5a815a4
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/MethodInfo.cs
@@ -0,0 +1,1061 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Metadata;
+#endif //FEATURE_REMOTING
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+ using MemberListType = System.RuntimeType.MemberListType;
+ using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+ using System.Runtime.CompilerServices;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_MethodInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class MethodInfo : MethodBase, _MethodInfo
+ {
+ #region Constructor
+ protected MethodInfo() { }
+ #endregion
+
+ public static bool operator ==(MethodInfo left, MethodInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeMethodInfo || right is RuntimeMethodInfo)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(MethodInfo left, MethodInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Method; } }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public virtual Type ReturnType { get { throw new NotImplementedException(); } }
+
+ public virtual ParameterInfo ReturnParameter { get { throw new NotImplementedException(); } }
+
+ public abstract ICustomAttributeProvider ReturnTypeCustomAttributes { get; }
+
+ public abstract MethodInfo GetBaseDefinition();
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override Type[] GetGenericArguments() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual MethodInfo GetGenericMethodDefinition() { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+
+ public virtual MethodInfo MakeGenericMethod(params Type[] typeArguments) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+
+ public virtual Delegate CreateDelegate(Type delegateType) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+ public virtual Delegate CreateDelegate(Type delegateType, Object target) { throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride")); }
+ #endregion
+
+#if !FEATURE_CORECLR
+ Type _MethodInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ void _MethodInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _MethodInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _MethodInfo.Invoke in VM\DangerousAPIs.h and
+ // include _MethodInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _MethodInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ [Serializable]
+ internal sealed class RuntimeMethodInfo : MethodInfo, ISerializable, IRuntimeMethodInfo
+ {
+ #region Private Data Members
+ private IntPtr m_handle;
+ private RuntimeTypeCache m_reflectedTypeCache;
+ private string m_name;
+ private string m_toString;
+ private ParameterInfo[] m_parameters;
+ private ParameterInfo m_returnParameter;
+ private BindingFlags m_bindingFlags;
+ private MethodAttributes m_methodAttributes;
+ private Signature m_signature;
+ private RuntimeType m_declaringType;
+ private object m_keepalive;
+ private INVOCATION_FLAGS m_invocationFlags;
+
+#if FEATURE_APPX
+ private bool IsNonW8PFrameworkAPI()
+ {
+ if (m_declaringType.IsArray && IsPublic && !IsStatic)
+ return false;
+
+ RuntimeAssembly rtAssembly = GetRuntimeAssembly();
+ if (rtAssembly.IsFrameworkAssembly())
+ {
+ int ctorToken = rtAssembly.InvocableAttributeCtorToken;
+ if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
+ !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
+ return true;
+ }
+
+ if (GetRuntimeType().IsNonW8PFrameworkAPI())
+ return true;
+
+ if (IsGenericMethod && !IsGenericMethodDefinition)
+ {
+ foreach (Type t in GetGenericArguments())
+ {
+ if (((RuntimeType)t).IsNonW8PFrameworkAPI())
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal override bool IsDynamicallyInvokable
+ {
+ get
+ {
+ return !AppDomain.ProfileAPICheck || !IsNonW8PFrameworkAPI();
+ }
+ }
+#endif
+
+ internal INVOCATION_FLAGS InvocationFlags
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
+
+ Type declaringType = DeclaringType;
+
+ //
+ // first take care of all the NO_INVOKE cases.
+ if (ContainsGenericParameters ||
+ ReturnType.IsByRef ||
+ (declaringType != null && declaringType.ContainsGenericParameters) ||
+ ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs) ||
+ ((Attributes & MethodAttributes.RequireSecObject) == MethodAttributes.RequireSecObject))
+ {
+ // We don't need other flags if this method cannot be invoked
+ invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE;
+ }
+ else
+ {
+ // this should be an invocable method, determine the other flags that participate in invocation
+ invocationFlags = RuntimeMethodHandle.GetSecurityFlags(this);
+
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) == 0)
+ {
+ if ( (Attributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public ||
+ (declaringType != null && declaringType.NeedsReflectionSecurityCheck) )
+ {
+ // If method is non-public, or declaring type is not visible
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
+ }
+ else if (IsGenericMethod)
+ {
+ Type[] genericArguments = GetGenericArguments();
+
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ if (genericArguments[i].NeedsReflectionSecurityCheck)
+ {
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+#if FEATURE_APPX
+ if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
+#endif // FEATURE_APPX
+
+ m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ }
+
+ return m_invocationFlags;
+ }
+ }
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeMethodInfo(
+ RuntimeMethodHandleInternal handle, RuntimeType declaringType,
+ RuntimeTypeCache reflectedTypeCache, MethodAttributes methodAttributes, BindingFlags bindingFlags, object keepalive)
+ {
+ Contract.Ensures(!m_handle.IsNull());
+
+ Contract.Assert(!handle.IsNullHandle());
+ Contract.Assert(methodAttributes == RuntimeMethodHandle.GetAttributes(handle));
+
+ m_bindingFlags = bindingFlags;
+ m_declaringType = declaringType;
+ m_keepalive = keepalive;
+ m_handle = handle.Value;
+ m_reflectedTypeCache = reflectedTypeCache;
+ m_methodAttributes = methodAttributes;
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
+ // This member is currently being used by Remoting for caching remoting data. If you
+ // need to cache data here, talk to the Remoting team to work out a mechanism, so that
+ // both caching systems can happily work together.
+ private RemotingMethodCachedData m_cachedData;
+
+ internal RemotingMethodCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingMethodCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingMethodCachedData(this);
+ RemotingMethodCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+
+ #region Private Methods
+ RuntimeMethodHandleInternal IRuntimeMethodInfo.Value
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ return new RuntimeMethodHandleInternal(m_handle);
+ }
+ }
+
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ParameterInfo[] FetchNonReturnParameters()
+ {
+ if (m_parameters == null)
+ m_parameters = RuntimeParameterInfo.GetParameters(this, this, Signature);
+
+ return m_parameters;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ParameterInfo FetchReturnParameter()
+ {
+ if (m_returnParameter == null)
+ m_returnParameter = RuntimeParameterInfo.GetReturnParameter(this, this, Signature);
+
+ return m_returnParameter;
+ }
+ #endregion
+
+ #region Internal Members
+ internal override string FormatNameAndSig(bool serialization)
+ {
+ // Serialization uses ToString to resolve MethodInfo overloads.
+ StringBuilder sbName = new StringBuilder(Name);
+
+ // serialization == true: use unambiguous (except for assembly name) type names to distinguish between overloads.
+ // serialization == false: use basic format to maintain backward compatibility of MethodInfo.ToString().
+ TypeNameFormatFlags format = serialization ? TypeNameFormatFlags.FormatSerialization : TypeNameFormatFlags.FormatBasic;
+
+ if (IsGenericMethod)
+ sbName.Append(RuntimeMethodHandle.ConstructInstantiation(this, format));
+
+ sbName.Append("(");
+ sbName.Append(ConstructParameters(GetParameterTypes(), CallingConvention, serialization));
+ sbName.Append(")");
+
+ return sbName.ToString();
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RuntimeMethodInfo m = o as RuntimeMethodInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_handle == m_handle;
+ }
+
+ internal Signature Signature
+ {
+ get
+ {
+ if (m_signature == null)
+ m_signature = new Signature(this, m_declaringType);
+
+ return m_signature;
+ }
+ }
+
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+
+ // Differs from MethodHandle in that it will return a valid handle even for reflection only loaded types
+ internal RuntimeMethodHandle GetMethodHandle()
+ {
+ return new RuntimeMethodHandle(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeMethodInfo GetParentDefinition()
+ {
+ if (!IsVirtual || m_declaringType.IsInterface)
+ return null;
+
+ RuntimeType parent = (RuntimeType)m_declaringType.BaseType;
+
+ if (parent == null)
+ return null;
+
+ int slot = RuntimeMethodHandle.GetSlot(this);
+
+ if (RuntimeTypeHandle.GetNumVirtuals(parent) <= slot)
+ return null;
+
+ return (RuntimeMethodInfo)RuntimeType.GetMethodBase(parent, RuntimeTypeHandle.GetMethodAt(parent, slot));
+ }
+
+ // Unlike DeclaringType, this will return a valid type even for global methods
+ internal RuntimeType GetDeclaringTypeInternal()
+ {
+ return m_declaringType;
+ }
+
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ if (m_toString == null)
+ m_toString = ReturnType.FormatTypeName() + " " + FormatNameAndSig();
+
+ return m_toString;
+ }
+
+ public override int GetHashCode()
+ {
+ // See RuntimeMethodInfo.Equals() below.
+ if (IsGenericMethod)
+ return ValueType.GetHashCodeOfPtr(m_handle);
+ else
+ return base.GetHashCode();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool Equals(object obj)
+ {
+ if (!IsGenericMethod)
+ return obj == (object)this;
+
+ // We cannot do simple object identity comparisons for generic methods.
+ // Equals will be called in CerHashTable when RuntimeType+RuntimeTypeCache.GetGenericMethodInfo()
+ // retrieve items from and insert items into s_methodInstantiations which is a CerHashtable.
+
+ RuntimeMethodInfo mi = obj as RuntimeMethodInfo;
+
+ if (mi == null || !mi.IsGenericMethod)
+ return false;
+
+ // now we know that both operands are generic methods
+
+ IRuntimeMethodInfo handle1 = RuntimeMethodHandle.StripMethodInstantiation(this);
+ IRuntimeMethodInfo handle2 = RuntimeMethodHandle.StripMethodInstantiation(mi);
+ if (handle1.Value.Value != handle2.Value.Value)
+ return false;
+
+ Type[] lhs = GetGenericArguments();
+ Type[] rhs = mi.GetGenericArguments();
+
+ if (lhs.Length != rhs.Length)
+ return false;
+
+ for (int i = 0; i < lhs.Length; i++)
+ {
+ if (lhs[i] != rhs[i])
+ return false;
+ }
+
+ if (DeclaringType != mi.DeclaringType)
+ return false;
+
+ if (ReflectedType != mi.ReflectedType)
+ return false;
+
+ return true;
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType as RuntimeType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_name == null)
+ m_name = RuntimeMethodHandle.GetName(this);
+
+ return m_name;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ if (m_reflectedTypeCache.IsGlobal)
+ return null;
+
+ return m_declaringType;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ if (m_reflectedTypeCache.IsGlobal)
+ return null;
+
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ public override MemberTypes MemberType { get { return MemberTypes.Method; } }
+ public override int MetadataToken
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return RuntimeMethodHandle.GetMethodDef(this); }
+ }
+ public override Module Module { get { return GetRuntimeModule(); } }
+ internal RuntimeType GetRuntimeType() { return m_declaringType; }
+ internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
+ internal RuntimeAssembly GetRuntimeAssembly() { return GetRuntimeModule().GetRuntimeAssembly(); }
+
+ public override bool IsSecurityCritical
+ {
+ get { return RuntimeMethodHandle.IsSecurityCritical(this); }
+ }
+ public override bool IsSecuritySafeCritical
+ {
+ get { return RuntimeMethodHandle.IsSecuritySafeCritical(this); }
+ }
+ public override bool IsSecurityTransparent
+ {
+ get { return RuntimeMethodHandle.IsSecurityTransparent(this); }
+ }
+ #endregion
+
+ #region MethodBase Overrides
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal override ParameterInfo[] GetParametersNoCopy()
+ {
+ FetchNonReturnParameters();
+
+ return m_parameters;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Diagnostics.Contracts.Pure]
+ public override ParameterInfo[] GetParameters()
+ {
+ FetchNonReturnParameters();
+
+ if (m_parameters.Length == 0)
+ return m_parameters;
+
+ ParameterInfo[] ret = new ParameterInfo[m_parameters.Length];
+
+ Array.Copy(m_parameters, ret, m_parameters.Length);
+
+ return ret;
+ }
+
+ public override MethodImplAttributes GetMethodImplementationFlags()
+ {
+ return RuntimeMethodHandle.GetImplAttributes(this);
+ }
+
+ internal bool IsOverloaded
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetMethodList(MemberListType.CaseSensitive, Name).Length > 1;
+ }
+ }
+
+ public override RuntimeMethodHandle MethodHandle
+ {
+ get
+ {
+ Type declaringType = DeclaringType;
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+ return new RuntimeMethodHandle(this);
+ }
+ }
+
+ public override MethodAttributes Attributes { get { return m_methodAttributes; } }
+
+ public override CallingConventions CallingConvention
+ {
+ get
+ {
+ return Signature.CallingConvention;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // overrides SafeCritical member
+#if !FEATURE_CORECLR
+#pragma warning disable 618
+ [ReflectionPermissionAttribute(SecurityAction.Demand, Flags = ReflectionPermissionFlag.MemberAccess)]
+#pragma warning restore 618
+#endif
+ public override MethodBody GetMethodBody()
+ {
+ MethodBody mb = RuntimeMethodHandle.GetMethodBody(this, ReflectedTypeInternal);
+ if (mb != null)
+ mb.m_methodBase = this;
+ return mb;
+ }
+ #endregion
+
+ #region Invocation Logic(On MemberBase)
+ private void CheckConsistency(Object target)
+ {
+ // only test instance methods
+ if ((m_methodAttributes & MethodAttributes.Static) != MethodAttributes.Static)
+ {
+ if (!m_declaringType.IsInstanceOfType(target))
+ {
+ if (target == null)
+ throw new TargetException(Environment.GetResourceString("RFLCT.Targ_StatMethReqTarg"));
+ else
+ throw new TargetException(Environment.GetResourceString("RFLCT.Targ_ITargMismatch"));
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void ThrowNoInvokeException()
+ {
+ // method is ReflectionOnly
+ Type declaringType = DeclaringType;
+ if ((declaringType == null && Module.Assembly.ReflectionOnly) || declaringType is ReflectionOnlyType)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke"));
+ }
+ // method is on a class that contains stack pointers
+ else if ((InvocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS) != 0)
+ {
+ throw new NotSupportedException();
+ }
+ // method is vararg
+ else if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
+ {
+ throw new NotSupportedException();
+ }
+ // method is generic or on a generic class
+ else if (DeclaringType.ContainsGenericParameters || ContainsGenericParameters)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_UnboundGenParam"));
+ }
+ // method is abstract class
+ else if (IsAbstract)
+ {
+ throw new MemberAccessException();
+ }
+ // ByRef return are not allowed in reflection
+ else if (ReturnType.IsByRef)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ByRefReturn"));
+ }
+
+ throw new TargetException();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public override Object Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture);
+
+ #region Security Check
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+
+#if FEATURE_APPX
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", FullName));
+ }
+#endif
+
+#if !FEATURE_CORECLR
+ if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD | INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY)) != 0)
+ {
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_RISKY_METHOD) != 0)
+ CodeAccessPermission.Demand(PermissionType.ReflectionMemberAccess);
+
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NEED_SECURITY) != 0)
+ RuntimeMethodHandle.PerformSecurityCheck(obj, this, m_declaringType, (uint)m_invocationFlags);
+ }
+#endif // !FEATURE_CORECLR
+ #endregion
+
+ return UnsafeInvokeInternal(obj, parameters, arguments);
+ }
+
+ [System.Security.SecurityCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal object UnsafeInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ object[] arguments = InvokeArgumentsCheck(obj, invokeAttr, binder, parameters, culture);
+
+ return UnsafeInvokeInternal(obj, parameters, arguments);
+ }
+
+ [System.Security.SecurityCritical]
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ private object UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
+ {
+ if (arguments == null || arguments.Length == 0)
+ return RuntimeMethodHandle.InvokeMethod(obj, null, Signature, false);
+ else
+ {
+ Object retValue = RuntimeMethodHandle.InvokeMethod(obj, arguments, Signature, false);
+
+ // copy out. This should be made only if ByRef are present.
+ for (int index = 0; index < arguments.Length; index++)
+ parameters[index] = arguments[index];
+
+ return retValue;
+ }
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ private object[] InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
+ {
+ Signature sig = Signature;
+
+ // get the signature
+ int formalCount = sig.Arguments.Length;
+ int actualCount = (parameters != null) ? parameters.Length : 0;
+
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+
+ // INVOCATION_FLAGS_CONTAINS_STACK_POINTERS means that the struct (either the declaring type or the return type)
+ // contains pointers that point to the stack. This is either a ByRef or a TypedReference. These structs cannot
+ // be boxed and thus cannot be invoked through reflection which only deals with boxed value type objects.
+ if ((invocationFlags & (INVOCATION_FLAGS.INVOCATION_FLAGS_NO_INVOKE | INVOCATION_FLAGS.INVOCATION_FLAGS_CONTAINS_STACK_POINTERS)) != 0)
+ ThrowNoInvokeException();
+
+ // check basic method consistency. This call will throw if there are problems in the target/method relationship
+ CheckConsistency(obj);
+
+ if (formalCount != actualCount)
+ throw new TargetParameterCountException(Environment.GetResourceString("Arg_ParmCnt"));
+
+ if (actualCount != 0)
+ return CheckArguments(parameters, binder, invokeAttr, culture, sig);
+ else
+ return null;
+ }
+
+ #endregion
+
+ #region MethodInfo Overrides
+ public override Type ReturnType
+ {
+ get { return Signature.ReturnType; }
+ }
+
+ public override ICustomAttributeProvider ReturnTypeCustomAttributes
+ {
+ get { return ReturnParameter; }
+ }
+
+ public override ParameterInfo ReturnParameter
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ Contract.Ensures(m_returnParameter != null);
+
+ FetchReturnParameter();
+ return m_returnParameter as ParameterInfo;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MethodInfo GetBaseDefinition()
+ {
+ if (!IsVirtual || IsStatic || m_declaringType == null || m_declaringType.IsInterface)
+ return this;
+
+ int slot = RuntimeMethodHandle.GetSlot(this);
+ RuntimeType declaringType = (RuntimeType)DeclaringType;
+ RuntimeType baseDeclaringType = declaringType;
+ RuntimeMethodHandleInternal baseMethodHandle = new RuntimeMethodHandleInternal();
+
+ do {
+ int cVtblSlots = RuntimeTypeHandle.GetNumVirtuals(declaringType);
+
+ if (cVtblSlots <= slot)
+ break;
+
+ baseMethodHandle = RuntimeTypeHandle.GetMethodAt(declaringType, slot);
+ baseDeclaringType = declaringType;
+
+ declaringType = (RuntimeType)declaringType.BaseType;
+ } while (declaringType != null);
+
+ return(MethodInfo)RuntimeType.GetMethodBase(baseDeclaringType, baseMethodHandle);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override Delegate CreateDelegate(Type delegateType)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // This API existed in v1/v1.1 and only expected to create closed
+ // instance delegates. Constrain the call to BindToMethodInfo to
+ // open delegates only for backwards compatibility. But we'll allow
+ // relaxed signature checking and open static delegates because
+ // there's no ambiguity there (the caller would have to explicitly
+ // pass us a static method or a method with a non-exact signature
+ // and the only change in behavior from v1.1 there is that we won't
+ // fail the call).
+ return CreateDelegateInternal(
+ delegateType,
+ null,
+ DelegateBindingFlags.OpenDelegateOnly | DelegateBindingFlags.RelaxedSignature,
+ ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override Delegate CreateDelegate(Type delegateType, Object target)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // This API is new in Whidbey and allows the full range of delegate
+ // flexability (open or closed delegates binding to static or
+ // instance methods with relaxed signature checking). The delegate
+ // can also be closed over null. There's no ambiguity with all these
+ // options since the caller is providing us a specific MethodInfo.
+ return CreateDelegateInternal(
+ delegateType,
+ target,
+ DelegateBindingFlags.RelaxedSignature,
+ ref stackMark);
+ }
+
+ [System.Security.SecurityCritical]
+ private Delegate CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags, ref StackCrawlMark stackMark)
+ {
+ // Validate the parameters.
+ if (delegateType == null)
+ throw new ArgumentNullException("delegateType");
+ Contract.EndContractBlock();
+
+ RuntimeType rtType = delegateType as RuntimeType;
+ if (rtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "delegateType");
+
+ if (!rtType.IsDelegate())
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "delegateType");
+
+ Delegate d = Delegate.CreateDelegateInternal(rtType, this, firstArgument, bindingFlags, ref stackMark);
+ if (d == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_DlgtTargMeth"));
+ }
+
+ return d;
+ }
+
+ #endregion
+
+ #region Generics
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MethodInfo MakeGenericMethod(params Type[] methodInstantiation)
+ {
+ if (methodInstantiation == null)
+ throw new ArgumentNullException("methodInstantiation");
+ Contract.EndContractBlock();
+
+ RuntimeType[] methodInstantionRuntimeType = new RuntimeType[methodInstantiation.Length];
+
+ if (!IsGenericMethodDefinition)
+ throw new InvalidOperationException(
+ Environment.GetResourceString("Arg_NotGenericMethodDefinition", this));
+
+ for (int i = 0; i < methodInstantiation.Length; i++)
+ {
+ Type methodInstantiationElem = methodInstantiation[i];
+
+ if (methodInstantiationElem == null)
+ throw new ArgumentNullException();
+
+ RuntimeType rtMethodInstantiationElem = methodInstantiationElem as RuntimeType;
+
+ if (rtMethodInstantiationElem == null)
+ {
+ Type[] methodInstantiationCopy = new Type[methodInstantiation.Length];
+ for (int iCopy = 0; iCopy < methodInstantiation.Length; iCopy++)
+ methodInstantiationCopy[iCopy] = methodInstantiation[iCopy];
+ methodInstantiation = methodInstantiationCopy;
+ return System.Reflection.Emit.MethodBuilderInstantiation.MakeGenericMethod(this, methodInstantiation);
+ }
+
+ methodInstantionRuntimeType[i] = rtMethodInstantiationElem;
+ }
+
+ RuntimeType[] genericParameters = GetGenericArgumentsInternal();
+
+ RuntimeType.SanityCheckGenericArguments(methodInstantionRuntimeType, genericParameters);
+
+ MethodInfo ret = null;
+
+ try
+ {
+ ret = RuntimeType.GetMethodBase(ReflectedTypeInternal,
+ RuntimeMethodHandle.GetStubIfNeeded(new RuntimeMethodHandleInternal(this.m_handle), m_declaringType, methodInstantionRuntimeType)) as MethodInfo;
+ }
+ catch (VerificationException e)
+ {
+ RuntimeType.ValidateGenericArguments(this, methodInstantionRuntimeType, e);
+ throw;
+ }
+
+ return ret;
+ }
+
+ internal RuntimeType[] GetGenericArgumentsInternal()
+ {
+ return RuntimeMethodHandle.GetMethodInstantiationInternal(this);
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ Type[] types = RuntimeMethodHandle.GetMethodInstantiationPublic(this);
+
+ if (types == null)
+ {
+ types = EmptyArray<Type>.Value;
+ }
+ return types;
+ }
+
+ public override MethodInfo GetGenericMethodDefinition()
+ {
+ if (!IsGenericMethod)
+ throw new InvalidOperationException();
+ Contract.EndContractBlock();
+
+ return RuntimeType.GetMethodBase(m_declaringType, RuntimeMethodHandle.StripMethodInstantiation(this)) as MethodInfo;
+ }
+
+ public override bool IsGenericMethod
+ {
+ get { return RuntimeMethodHandle.HasMethodInstantiation(this); }
+ }
+
+ public override bool IsGenericMethodDefinition
+ {
+ get { return RuntimeMethodHandle.IsGenericMethodDefinition(this); }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get
+ {
+ if (DeclaringType != null && DeclaringType.ContainsGenericParameters)
+ return true;
+
+ if (!IsGenericMethod)
+ return false;
+
+ Type[] pis = GetGenericArguments();
+ for (int i = 0; i < pis.Length; i++)
+ {
+ if (pis[i].ContainsGenericParameters)
+ return true;
+ }
+
+ return false;
+ }
+ }
+ #endregion
+
+ #region ISerializable Implementation
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ if (m_reflectedTypeCache.IsGlobal)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_GlobalMethodSerialization"));
+
+ MemberInfoSerializationHolder.GetSerializationInfo(
+ info,
+ Name,
+ ReflectedTypeInternal,
+ ToString(),
+ SerializationToString(),
+ MemberTypes.Method,
+ IsGenericMethod & !IsGenericMethodDefinition ? GetGenericArguments() : null);
+ }
+
+ internal string SerializationToString()
+ {
+ return ReturnType.FormatTypeName(true) + " " + FormatNameAndSig(true);
+ }
+ #endregion
+
+ #region Legacy Internal
+ internal static MethodBase InternalGetCurrentMethod(ref StackCrawlMark stackMark)
+ {
+ IRuntimeMethodInfo method = RuntimeMethodHandle.GetCurrentMethod(ref stackMark);
+
+ if (method == null)
+ return null;
+
+ return RuntimeType.GetMethodBase(method);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Missing.cs b/src/mscorlib/src/System/Reflection/Missing.cs
new file mode 100644
index 0000000000..8289193191
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Missing.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // This is not serializable because it is a reflection command.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Missing : ISerializable
+ {
+ public static readonly Missing Value = new Missing();
+
+ #region Constructor
+ private Missing() { }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ UnitySerializationHolder.GetUnitySerializationInfo(info, this);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Module.cs b/src/mscorlib/src/System/Reflection/Module.cs
new file mode 100644
index 0000000000..34705a4211
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Module.cs
@@ -0,0 +1,1230 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Diagnostics.SymbolStore;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.IO;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum PortableExecutableKinds
+ {
+ NotAPortableExecutableImage = 0x0,
+
+ ILOnly = 0x1,
+
+ Required32Bit = 0x2,
+
+ PE32Plus = 0x4,
+
+ Unmanaged32Bit = 0x8,
+
+ [ComVisible(false)]
+ Preferred32Bit = 0x10,
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ImageFileMachine
+ {
+ I386 = 0x014c,
+
+ IA64 = 0x0200,
+
+ AMD64 = 0x8664,
+
+ ARM = 0x01c4,
+ }
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Module))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ public abstract class Module : _Module, ISerializable, ICustomAttributeProvider
+ {
+ #region Static Constructor
+ static Module()
+ {
+ __Filters _fltObj;
+ _fltObj = new __Filters();
+ FilterTypeName = new TypeFilter(_fltObj.FilterTypeName);
+ FilterTypeNameIgnoreCase = new TypeFilter(_fltObj.FilterTypeNameIgnoreCase);
+ }
+ #endregion
+
+ #region Constructor
+ protected Module()
+ {
+ }
+ #endregion
+
+ #region Public Statics
+ public static readonly TypeFilter FilterTypeName;
+ public static readonly TypeFilter FilterTypeNameIgnoreCase;
+
+ public static bool operator ==(Module left, Module right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimeModule || right is RuntimeModule)
+ {
+ return false;
+ }
+
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(Module left, Module right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object o)
+ {
+ return base.Equals(o);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ #endregion
+
+ #region Literals
+ private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
+ #endregion
+
+ #region object overrides
+ public override String ToString()
+ {
+ return ScopeName;
+ }
+ #endregion
+
+ public virtual IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return GetCustomAttributesData();
+ }
+ }
+ #region ICustomAttributeProvider Members
+ public virtual Object[] GetCustomAttributes(bool inherit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual bool IsDefined(Type attributeType, bool inherit)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+
+ #region public instances members
+ public MethodBase ResolveMethod(int metadataToken)
+ {
+ return ResolveMethod(metadataToken, null, null);
+ }
+
+ public virtual MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ throw new NotImplementedException();
+ }
+
+ public FieldInfo ResolveField(int metadataToken)
+ {
+ return ResolveField(metadataToken, null, null);
+ }
+
+ public virtual FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ throw new NotImplementedException();
+ }
+
+ public Type ResolveType(int metadataToken)
+ {
+ return ResolveType(metadataToken, null, null);
+ }
+
+ public virtual Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ throw new NotImplementedException();
+ }
+
+ public MemberInfo ResolveMember(int metadataToken)
+ {
+ return ResolveMember(metadataToken, null, null);
+ }
+
+ public virtual MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveMember(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ throw new NotImplementedException();
+ }
+
+ public virtual byte[] ResolveSignature(int metadataToken)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveSignature(metadataToken);
+
+ throw new NotImplementedException();
+ }
+
+ public virtual string ResolveString(int metadataToken)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ResolveString(metadataToken);
+
+ throw new NotImplementedException();
+ }
+
+ public virtual void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ rtModule.GetPEKind(out peKind, out machine);
+
+ throw new NotImplementedException();
+ }
+
+ public virtual int MDStreamVersion
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.MDStreamVersion;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotImplementedException();
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual Type GetType(String className, bool ignoreCase)
+ {
+ return GetType(className, false, ignoreCase);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual Type GetType(String className) {
+ return GetType(className, false, false);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual Type GetType(String className, bool throwOnError, bool ignoreCase)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual String FullyQualifiedName
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual Type[] FindTypes(TypeFilter filter,Object filterCriteria)
+ {
+ Type[] c = GetTypes();
+ int cnt = 0;
+ for (int i = 0;i<c.Length;i++) {
+ if (filter!=null && !filter(c[i],filterCriteria))
+ c[i] = null;
+ else
+ cnt++;
+ }
+ if (cnt == c.Length)
+ return c;
+
+ Type[] ret = new Type[cnt];
+ cnt=0;
+ for (int i=0;i<c.Length;i++) {
+ if (c[i] != null)
+ ret[cnt++] = c[i];
+ }
+ return ret;
+ }
+
+ public virtual Type[] GetTypes()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual Guid ModuleVersionId
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ModuleVersionId;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual int MetadataToken
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.MetadataToken;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual bool IsResource()
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.IsResource();
+
+ throw new NotImplementedException();
+ }
+
+ public FieldInfo[] GetFields()
+ {
+ return GetFields(Module.DefaultLookup);
+ }
+
+ public virtual FieldInfo[] GetFields(BindingFlags bindingFlags)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.GetFields(bindingFlags);
+
+ throw new NotImplementedException();
+ }
+
+ public FieldInfo GetField(String name)
+ {
+ return GetField(name,Module.DefaultLookup);
+ }
+
+ public virtual FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.GetField(name, bindingAttr);
+
+ throw new NotImplementedException();
+ }
+
+ public MethodInfo[] GetMethods()
+ {
+ return GetMethods(Module.DefaultLookup);
+ }
+
+ public virtual MethodInfo[] GetMethods(BindingFlags bindingFlags)
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.GetMethods(bindingFlags);
+
+ throw new NotImplementedException();
+ }
+
+ public MethodInfo GetMethod(
+ String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ }
+
+ return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public MethodInfo GetMethod(String name, Type[] types)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+
+ for (int i = 0; i < types.Length; i++)
+ {
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ }
+
+ return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any, types, null);
+ }
+
+ public MethodInfo GetMethod(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any,
+ null, null);
+ }
+
+ protected virtual MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder,
+ CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual String ScopeName
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.ScopeName;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual String Name
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.Name;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ public virtual Assembly Assembly
+ {
+ [Pure]
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeModule rtModule = this as RuntimeModule;
+ if (rtModule != null)
+ return rtModule.Assembly;
+
+ throw new NotImplementedException();
+ }
+ }
+
+ // This API never fails, it will return an empty handle for non-runtime handles and
+ // a valid handle for reflection only modules.
+ public ModuleHandle ModuleHandle
+ {
+ get
+ {
+ return GetModuleHandle();
+ }
+ }
+
+ // Used to provide implementation and overriding point for ModuleHandle.
+ // To get a module handle inside mscorlib, use GetNativeHandle instead.
+ internal virtual ModuleHandle GetModuleHandle()
+ {
+ return ModuleHandle.EmptyHandle;
+ }
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ public virtual System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate()
+ {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_X509 && FEATURE_CAS_POLICY
+ #endregion
+
+#if !FEATURE_CORECLR
+ void _Module.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Module.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Module.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Module.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ [Serializable]
+ internal class RuntimeModule : Module
+ {
+ internal RuntimeModule() { throw new NotSupportedException(); }
+
+ #region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetType(RuntimeModule module, String className, bool ignoreCase, bool throwOnError, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive);
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern bool nIsTransientInternal(RuntimeModule module);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetScopeName(RuntimeModule module, StringHandleOnStack retString);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetFullyQualifiedName(RuntimeModule module, StringHandleOnStack retString);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static RuntimeType[] GetTypes(RuntimeModule module);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeType[] GetDefinedTypes()
+ {
+ return GetTypes(GetNativeHandle());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static bool IsResource(RuntimeModule module);
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static private extern void GetSignerCertificate(RuntimeModule module, ObjectHandleOnStack retData);
+#endif // FEATURE_X509 && FEATURE_CAS_POLICY
+ #endregion
+
+ #region Module overrides
+ private static RuntimeTypeHandle[] ConvertToTypeHandleArray(Type[] genericArguments)
+ {
+ if (genericArguments == null)
+ return null;
+
+ int size = genericArguments.Length;
+ RuntimeTypeHandle[] typeHandleArgs = new RuntimeTypeHandle[size];
+ for (int i = 0; i < size; i++)
+ {
+ Type typeArg = genericArguments[i];
+ if (typeArg == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGenericInstArray"));
+ typeArg = typeArg.UnderlyingSystemType;
+ if (typeArg == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGenericInstArray"));
+ if (!(typeArg is RuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidGenericInstArray"));
+ typeHandleArgs[i] = typeArg.GetTypeHandleInternal();
+ }
+ return typeHandleArgs;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override byte[] ResolveSignature(int metadataToken)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", tk, this));
+
+ if (!tk.IsMemberRef && !tk.IsMethodDef && !tk.IsTypeSpec && !tk.IsSignature && !tk.IsFieldDef)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidToken", tk, this),
+ "metadataToken");
+
+ ConstArray signature;
+ if (tk.IsMemberRef)
+ signature = MetadataImport.GetMemberRefProps(metadataToken);
+ else
+ signature = MetadataImport.GetSignatureFromToken(metadataToken);
+
+ byte[] sig = new byte[signature.Length];
+
+ for (int i = 0; i < signature.Length; i++)
+ sig[i] = signature[i];
+
+ return sig;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", tk, this));
+
+ RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
+ RuntimeTypeHandle[] methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
+
+ try
+ {
+ if (!tk.IsMethodDef && !tk.IsMethodSpec)
+ {
+ if (!tk.IsMemberRef)
+ throw new ArgumentException("metadataToken",
+ Environment.GetResourceString("Argument_ResolveMethod", tk, this));
+
+ unsafe
+ {
+ ConstArray sig = MetadataImport.GetMemberRefProps(tk);
+
+ if (*(MdSigCallingConvention*)sig.Signature.ToPointer() == MdSigCallingConvention.Field)
+ throw new ArgumentException("metadataToken",
+ Environment.GetResourceString("Argument_ResolveMethod", tk, this));
+ }
+ }
+
+ IRuntimeMethodInfo methodHandle = ModuleHandle.ResolveMethodHandleInternal(GetNativeHandle(), tk, typeArgs, methodArgs);
+ Type declaringType = RuntimeMethodHandle.GetDeclaringType(methodHandle);
+
+ if (declaringType.IsGenericType || declaringType.IsArray)
+ {
+ MetadataToken tkDeclaringType = new MetadataToken(MetadataImport.GetParentToken(tk));
+
+ if (tk.IsMethodSpec)
+ tkDeclaringType = new MetadataToken(MetadataImport.GetParentToken(tkDeclaringType));
+
+ declaringType = ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
+ }
+
+ return System.RuntimeType.GetMethodBase(declaringType as RuntimeType, methodHandle);
+ }
+ catch (BadImageFormatException e)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadImageFormatExceptionResolve"), e);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private FieldInfo ResolveLiteralField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (!MetadataImport.IsValidToken(tk) || !tk.IsFieldDef)
+ throw new ArgumentOutOfRangeException("metadataToken",
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_InvalidToken", tk, this)));
+
+ int tkDeclaringType;
+ string fieldName;
+
+ fieldName = MetadataImport.GetName(tk).ToString();
+ tkDeclaringType = MetadataImport.GetParentToken(tk);
+
+ Type declaringType = ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
+
+ declaringType.GetFields();
+
+ try
+ {
+ return declaringType.GetField(fieldName,
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.DeclaredOnly);
+ }
+ catch
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResolveField", tk, this), "metadataToken");
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", tk, this));
+
+ RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
+ RuntimeTypeHandle[] methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
+
+ try
+ {
+ IRuntimeFieldInfo fieldHandle = null;
+
+ if (!tk.IsFieldDef)
+ {
+ if (!tk.IsMemberRef)
+ throw new ArgumentException("metadataToken",
+ Environment.GetResourceString("Argument_ResolveField", tk, this));
+
+ unsafe
+ {
+ ConstArray sig = MetadataImport.GetMemberRefProps(tk);
+
+ if (*(MdSigCallingConvention*)sig.Signature.ToPointer() != MdSigCallingConvention.Field)
+ throw new ArgumentException("metadataToken",
+ Environment.GetResourceString("Argument_ResolveField", tk, this));
+ }
+
+ fieldHandle = ModuleHandle.ResolveFieldHandleInternal(GetNativeHandle(), tk, typeArgs, methodArgs);
+ }
+
+ fieldHandle = ModuleHandle.ResolveFieldHandleInternal(GetNativeHandle(), metadataToken, typeArgs, methodArgs);
+ RuntimeType declaringType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle.Value);
+
+ if (declaringType.IsGenericType || declaringType.IsArray)
+ {
+ int tkDeclaringType = ModuleHandle.GetMetadataImport(GetNativeHandle()).GetParentToken(metadataToken);
+ declaringType = (RuntimeType)ResolveType(tkDeclaringType, genericTypeArguments, genericMethodArguments);
+ }
+
+ return System.RuntimeType.GetFieldInfo(declaringType, fieldHandle);
+ }
+ catch(MissingFieldException)
+ {
+ return ResolveLiteralField(tk, genericTypeArguments, genericMethodArguments);
+ }
+ catch (BadImageFormatException e)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadImageFormatExceptionResolve"), e);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (tk.IsGlobalTypeDefToken)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResolveModuleType", tk), "metadataToken");
+
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", tk, this));
+
+ if (!tk.IsTypeDef && !tk.IsTypeSpec && !tk.IsTypeRef)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), "metadataToken");
+
+ RuntimeTypeHandle[] typeArgs = ConvertToTypeHandleArray(genericTypeArguments);
+ RuntimeTypeHandle[] methodArgs = ConvertToTypeHandleArray(genericMethodArguments);
+
+ try
+ {
+ Type t = GetModuleHandle().ResolveTypeHandle(metadataToken, typeArgs, methodArgs).GetRuntimeType();
+
+ if (t == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResolveType", tk, this), "metadataToken");
+
+ return t;
+ }
+ catch (BadImageFormatException e)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadImageFormatExceptionResolve"), e);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+
+ if (tk.IsProperty)
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_PropertyInfoNotAvailable"));
+
+ if (tk.IsEvent)
+ throw new ArgumentException(Environment.GetResourceString("InvalidOperation_EventInfoNotAvailable"));
+
+ if (tk.IsMethodSpec || tk.IsMethodDef)
+ return ResolveMethod(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ if (tk.IsFieldDef)
+ return ResolveField(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ if (tk.IsTypeRef || tk.IsTypeDef || tk.IsTypeSpec)
+ return ResolveType(metadataToken, genericTypeArguments, genericMethodArguments);
+
+ if (tk.IsMemberRef)
+ {
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", tk, this));
+
+ ConstArray sig = MetadataImport.GetMemberRefProps(tk);
+
+ unsafe
+ {
+ if (*(MdSigCallingConvention*)sig.Signature.ToPointer() == MdSigCallingConvention.Field)
+ {
+ return ResolveField(tk, genericTypeArguments, genericMethodArguments);
+ }
+ else
+ {
+ return ResolveMethod(tk, genericTypeArguments, genericMethodArguments);
+ }
+ }
+ }
+
+ throw new ArgumentException("metadataToken",
+ Environment.GetResourceString("Argument_ResolveMember", tk, this));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override string ResolveString(int metadataToken)
+ {
+ MetadataToken tk = new MetadataToken(metadataToken);
+ if (!tk.IsString)
+ throw new ArgumentException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_ResolveString"), metadataToken, ToString()));
+
+ if (!MetadataImport.IsValidToken(tk))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_InvalidToken", tk, this)));
+
+ string str = MetadataImport.GetUserString(metadataToken);
+
+ if (str == null)
+ throw new ArgumentException(
+ String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Argument_ResolveString"), metadataToken, ToString()));
+
+ return str;
+ }
+
+ public override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ ModuleHandle.GetPEKind(GetNativeHandle(), out peKind, out machine);
+ }
+
+ public override int MDStreamVersion
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return ModuleHandle.GetMDStreamVersion(GetNativeHandle());
+ }
+ }
+ #endregion
+
+ #region Data Members
+ #pragma warning disable 169
+ // If you add any data members, you need to update the native declaration ReflectModuleBaseObject.
+ private RuntimeType m_runtimeType;
+ private RuntimeAssembly m_runtimeAssembly;
+ private IntPtr m_pRefClass;
+ private IntPtr m_pData;
+ private IntPtr m_pGlobals;
+ private IntPtr m_pFields;
+#pragma warning restore 169
+ #endregion
+
+ #region Protected Virtuals
+ protected override MethodInfo GetMethodImpl(String name, BindingFlags bindingAttr, Binder binder,
+ CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ return GetMethodInternal(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ internal MethodInfo GetMethodInternal(String name, BindingFlags bindingAttr, Binder binder,
+ CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (RuntimeType == null)
+ return null;
+
+ if (types == null)
+ {
+ return RuntimeType.GetMethod(name, bindingAttr);
+ }
+ else
+ {
+ return RuntimeType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+ }
+ #endregion
+
+ #region Internal Members
+ internal RuntimeType RuntimeType
+ {
+ get
+ {
+ if (m_runtimeType == null)
+ m_runtimeType = ModuleHandle.GetModuleType(GetNativeHandle());
+
+ return m_runtimeType;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal bool IsTransientInternal()
+ {
+ return RuntimeModule.nIsTransientInternal(this.GetNativeHandle());
+ }
+
+ internal MetadataImport MetadataImport
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ unsafe
+ {
+ return ModuleHandle.GetMetadataImport(GetNativeHandle());
+ }
+ }
+ }
+ #endregion
+
+ #region ICustomAttributeProvider Members
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region Public Virtuals
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ UnitySerializationHolder.GetUnitySerializationInfo(info, UnitySerializationHolder.ModuleUnity, this.ScopeName, this.GetRuntimeAssembly());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public override Type GetType(String className, bool throwOnError, bool ignoreCase)
+ {
+ // throw on null strings regardless of the value of "throwOnError"
+ if (className == null)
+ throw new ArgumentNullException("className");
+
+ RuntimeType retType = null;
+ Object keepAlive = null;
+ GetType(GetNativeHandle(), className, throwOnError, ignoreCase, JitHelpers.GetObjectHandleOnStack(ref retType), JitHelpers.GetObjectHandleOnStack(ref keepAlive));
+ GC.KeepAlive(keepAlive);
+ return retType;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal string GetFullyQualifiedName()
+ {
+ String fullyQualifiedName = null;
+ GetFullyQualifiedName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref fullyQualifiedName));
+ return fullyQualifiedName;
+ }
+
+ public override String FullyQualifiedName
+ {
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#else
+ [System.Security.SecuritySafeCritical]
+#endif
+ get
+ {
+ String fullyQualifiedName = GetFullyQualifiedName();
+
+ if (fullyQualifiedName != null) {
+ bool checkPermission = true;
+ try {
+ Path.GetFullPathInternal(fullyQualifiedName);
+ }
+ catch(ArgumentException) {
+ checkPermission = false;
+ }
+ if (checkPermission) {
+ new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullyQualifiedName ).Demand();
+ }
+ }
+
+ return fullyQualifiedName;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetTypes()
+ {
+ return GetTypes(GetNativeHandle());
+ }
+
+ #endregion
+
+ #region Public Members
+
+ public override Guid ModuleVersionId
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ unsafe
+ {
+ Guid mvid;
+ MetadataImport.GetScopeProps(out mvid);
+ return mvid;
+ }
+ }
+ }
+
+ public override int MetadataToken
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return ModuleHandle.GetToken(GetNativeHandle());
+ }
+ }
+
+ public override bool IsResource()
+ {
+ return IsResource(GetNativeHandle());
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingFlags)
+ {
+ if (RuntimeType == null)
+ return new FieldInfo[0];
+
+ return RuntimeType.GetFields(bindingFlags);
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (RuntimeType == null)
+ return null;
+
+ return RuntimeType.GetField(name, bindingAttr);
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingFlags)
+ {
+ if (RuntimeType == null)
+ return new MethodInfo[0];
+
+ return RuntimeType.GetMethods(bindingFlags);
+ }
+
+ public override String ScopeName
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ string scopeName = null;
+ GetScopeName(GetNativeHandle(), JitHelpers.GetStringHandleOnStack(ref scopeName));
+ return scopeName;
+ }
+ }
+
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ String s = GetFullyQualifiedName();
+
+#if !FEATURE_PAL
+ int i = s.LastIndexOf('\\');
+#else
+ int i = s.LastIndexOf(System.IO.Path.DirectorySeparatorChar);
+#endif
+ if (i == -1)
+ return s;
+
+ return s.Substring(i + 1);
+ }
+ }
+
+ public override Assembly Assembly
+ {
+ [Pure]
+ get
+ {
+ return GetRuntimeAssembly();
+ }
+ }
+
+ internal RuntimeAssembly GetRuntimeAssembly()
+ {
+ return m_runtimeAssembly;
+ }
+
+
+ internal override ModuleHandle GetModuleHandle()
+ {
+ return new ModuleHandle(this);
+ }
+
+ internal RuntimeModule GetNativeHandle()
+ {
+ return this;
+ }
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override System.Security.Cryptography.X509Certificates.X509Certificate GetSignerCertificate()
+ {
+ byte[] data = null;
+ GetSignerCertificate(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref data));
+ return (data != null) ? new System.Security.Cryptography.X509Certificates.X509Certificate(data) : null;
+ }
+#endif // FEATURE_X509 && FEATURE_CAS_POLICY
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ObfuscateAssemblyAttribute.cs b/src/mscorlib/src/System/Reflection/ObfuscateAssemblyAttribute.cs
new file mode 100644
index 0000000000..b852e5a4c2
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ObfuscateAssemblyAttribute.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Reflection;
+
+
+namespace System.Reflection
+{
+ [AttributeUsage (AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ObfuscateAssemblyAttribute : Attribute
+ {
+ private bool m_assemblyIsPrivate;
+ private bool m_strip = true;
+
+ public ObfuscateAssemblyAttribute(bool assemblyIsPrivate)
+ {
+ m_assemblyIsPrivate = assemblyIsPrivate;
+ }
+
+ public bool AssemblyIsPrivate
+ {
+ get
+ {
+ return m_assemblyIsPrivate;
+ }
+ }
+
+ public bool StripAfterObfuscation
+ {
+ get
+ {
+ return m_strip;
+ }
+ set
+ {
+ m_strip = value;
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/ObfuscationAttribute.cs b/src/mscorlib/src/System/Reflection/ObfuscationAttribute.cs
new file mode 100644
index 0000000000..0b987ce06d
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ObfuscationAttribute.cs
@@ -0,0 +1,75 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Reflection;
+
+namespace System.Reflection
+{
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Delegate,
+ AllowMultiple = true, Inherited = false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ObfuscationAttribute: Attribute
+ {
+ private bool m_strip = true;
+ private bool m_exclude = true;
+ private bool m_applyToMembers = true;
+ private string m_feature = "all";
+
+ public ObfuscationAttribute()
+ {
+ }
+
+ public bool StripAfterObfuscation
+ {
+ get
+ {
+ return m_strip;
+ }
+ set
+ {
+ m_strip = value;
+ }
+ }
+
+ public bool Exclude
+ {
+ get
+ {
+ return m_exclude;
+ }
+ set
+ {
+ m_exclude = value;
+ }
+ }
+
+ public bool ApplyToMembers
+ {
+ get
+ {
+ return m_applyToMembers;
+ }
+ set
+ {
+ m_applyToMembers = value;
+ }
+ }
+
+ public string Feature
+ {
+ get
+ {
+ return m_feature;
+ }
+ set
+ {
+ m_feature = value;
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/ParameterAttributes.cs b/src/mscorlib/src/System/Reflection/ParameterAttributes.cs
new file mode 100644
index 0000000000..12f8145ddd
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ParameterAttributes.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// ParameterAttributes is an enum defining the attributes that may be
+//
+// associated with a Parameter. These are defined in CorHdr.h.
+//
+//
+namespace System.Reflection {
+
+ using System;
+ // This Enum matchs the CorParamAttr defined in CorHdr.h
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ParameterAttributes
+ {
+ None = 0x0000, // no flag is specified
+ In = 0x0001, // Param is [In]
+ Out = 0x0002, // Param is [Out]
+ Lcid = 0x0004, // Param is [lcid]
+ Retval = 0x0008, // Param is [Retval]
+ Optional = 0x0010, // Param is optional
+
+ // Reserved flags for Runtime use only.
+ ReservedMask = 0xf000,
+ HasDefault = 0x1000, // Param has default value.
+ HasFieldMarshal = 0x2000, // Param has FieldMarshal.
+ Reserved3 = 0x4000, // reserved bit
+ Reserved4 = 0x8000 // reserved bit
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ParameterInfo.cs b/src/mscorlib/src/System/Reflection/ParameterInfo.cs
new file mode 100644
index 0000000000..63c6330b0a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ParameterInfo.cs
@@ -0,0 +1,795 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Metadata;
+#endif //FEATURE_REMOTING
+ using System.Security.Permissions;
+ using System.Threading;
+ using MdToken = System.Reflection.MetadataToken;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_ParameterInfo))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ParameterInfo : _ParameterInfo, ICustomAttributeProvider, IObjectReference
+ {
+ #region Legacy Protected Members
+ protected String NameImpl;
+ protected Type ClassImpl;
+ protected int PositionImpl;
+ protected ParameterAttributes AttrsImpl;
+ protected Object DefaultValueImpl; // cannot cache this as it may be non agile user defined enum
+ protected MemberInfo MemberImpl;
+ #endregion
+
+ #region Legacy Private Members
+ // These are here only for backwards compatibility -- they are not set
+ // until this instance is serialized, so don't rely on their values from
+ // arbitrary code.
+#pragma warning disable 169
+ [OptionalField]
+ private IntPtr _importer;
+ [OptionalField]
+ private int _token;
+ [OptionalField]
+ private bool bExtraConstChecked;
+#pragma warning restore 169
+ #endregion
+
+ #region Constructor
+ protected ParameterInfo()
+ {
+ }
+ #endregion
+
+ #region Internal Members
+ // this is an internal api for DynamicMethod. A better solution is to change the relationship
+ // between ParameterInfo and ParameterBuilder so that a ParameterBuilder can be seen as a writer
+ // api over a ParameterInfo. However that is a possible breaking change so it needs to go through some process first
+ internal void SetName(String name)
+ {
+ NameImpl = name;
+ }
+
+ internal void SetAttributes(ParameterAttributes attributes)
+ {
+ AttrsImpl = attributes;
+ }
+ #endregion
+
+ #region Public Methods
+ public virtual Type ParameterType
+ {
+ get
+ {
+ return ClassImpl;
+ }
+ }
+
+ public virtual String Name
+ {
+ get
+ {
+ return NameImpl;
+ }
+ }
+
+ public virtual bool HasDefaultValue { get { throw new NotImplementedException(); } }
+
+ public virtual Object DefaultValue { get { throw new NotImplementedException(); } }
+ public virtual Object RawDefaultValue { get { throw new NotImplementedException(); } }
+
+ public virtual int Position { get { return PositionImpl; } }
+ public virtual ParameterAttributes Attributes { get { return AttrsImpl; } }
+
+ public virtual MemberInfo Member {
+ get {
+ Contract.Ensures(Contract.Result<MemberInfo>() != null);
+ return MemberImpl;
+ }
+ }
+
+ public bool IsIn { get { return((Attributes & ParameterAttributes.In) != 0); } }
+ public bool IsOut { get { return((Attributes & ParameterAttributes.Out) != 0); } }
+ public bool IsLcid { get { return((Attributes & ParameterAttributes.Lcid) != 0); } }
+ public bool IsRetval { get { return((Attributes & ParameterAttributes.Retval) != 0); } }
+ public bool IsOptional { get { return((Attributes & ParameterAttributes.Optional) != 0); } }
+
+ public virtual int MetadataToken
+ {
+ get
+ {
+ // This API was made virtual in V4. Code compiled against V2 might use
+ // "call" rather than "callvirt" to call it.
+ // This makes sure those code still works.
+ RuntimeParameterInfo rtParam = this as RuntimeParameterInfo;
+ if (rtParam != null)
+ return rtParam.MetadataToken;
+
+ // return a null token
+ return (int)MetadataTokenType.ParamDef;
+ }
+ }
+
+ public virtual Type[] GetRequiredCustomModifiers()
+ {
+ return EmptyArray<Type>.Value;
+ }
+
+ public virtual Type[] GetOptionalCustomModifiers()
+ {
+ return EmptyArray<Type>.Value;
+ }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return ParameterType.FormatTypeName() + " " + Name;
+ }
+ #endregion
+
+ public virtual IEnumerable<CustomAttributeData> CustomAttributes
+ {
+ get
+ {
+ return GetCustomAttributesData();
+ }
+ }
+ #region ICustomAttributeProvider
+ public virtual Object[] GetCustomAttributes(bool inherit)
+ {
+ return EmptyArray<Object>.Value;
+ }
+
+ public virtual Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ return EmptyArray<Object>.Value;
+ }
+
+ public virtual bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ return false;
+ }
+
+ public virtual IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ throw new NotImplementedException();
+ }
+ #endregion
+
+ #region _ParameterInfo implementation
+
+#if !FEATURE_CORECLR
+ void _ParameterInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _ParameterInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ #endregion
+
+ #region IObjectReference
+ // In V4 RuntimeParameterInfo is introduced.
+ // To support deserializing ParameterInfo instances serialized in earlier versions
+ // we need to implement IObjectReference.
+ [System.Security.SecurityCritical]
+ public object GetRealObject(StreamingContext context)
+ {
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ // Once all the serializable fields have come in we can set up the real
+ // instance based on just two of them (MemberImpl and PositionImpl).
+
+ if (MemberImpl == null)
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_InsufficientState));
+
+ ParameterInfo[] args = null;
+
+ switch (MemberImpl.MemberType)
+ {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method:
+ if (PositionImpl == -1)
+ {
+ if (MemberImpl.MemberType == MemberTypes.Method)
+ return ((MethodInfo)MemberImpl).ReturnParameter;
+ else
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
+ }
+ else
+ {
+ args = ((MethodBase)MemberImpl).GetParametersNoCopy();
+
+ if (args != null && PositionImpl < args.Length)
+ return args[PositionImpl];
+ else
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
+ }
+
+ case MemberTypes.Property:
+ args = ((RuntimePropertyInfo)MemberImpl).GetIndexParametersNoCopy();
+
+ if (args != null && PositionImpl > -1 && PositionImpl < args.Length)
+ return args[PositionImpl];
+ else
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_BadParameterInfo));
+
+ default:
+ throw new SerializationException(Environment.GetResourceString(ResId.Serialization_NoParameterInfo));
+ }
+ }
+ #endregion
+ }
+
+ [Serializable]
+ internal unsafe sealed class RuntimeParameterInfo : ParameterInfo, ISerializable
+ {
+ #region Static Members
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static ParameterInfo[] GetParameters(IRuntimeMethodInfo method, MemberInfo member, Signature sig)
+ {
+ Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
+
+ ParameterInfo dummy;
+ return GetParameters(method, member, sig, out dummy, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static ParameterInfo GetReturnParameter(IRuntimeMethodInfo method, MemberInfo member, Signature sig)
+ {
+ Contract.Assert(method is RuntimeMethodInfo || method is RuntimeConstructorInfo);
+
+ ParameterInfo returnParameter;
+ GetParameters(method, member, sig, out returnParameter, true);
+ return returnParameter;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static ParameterInfo[] GetParameters(
+ IRuntimeMethodInfo methodHandle, MemberInfo member, Signature sig, out ParameterInfo returnParameter, bool fetchReturnParameter)
+ {
+ returnParameter = null;
+ int sigArgCount = sig.Arguments.Length;
+ ParameterInfo[] args = fetchReturnParameter ? null : new ParameterInfo[sigArgCount];
+
+ int tkMethodDef = RuntimeMethodHandle.GetMethodDef(methodHandle);
+ int cParamDefs = 0;
+
+ // Not all methods have tokens. Arrays, pointers and byRef types do not have tokens as they
+ // are generated on the fly by the runtime.
+ if (!MdToken.IsNullToken(tkMethodDef))
+ {
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(RuntimeMethodHandle.GetDeclaringType(methodHandle));
+
+ MetadataEnumResult tkParamDefs;
+ scope.EnumParams(tkMethodDef, out tkParamDefs);
+
+ cParamDefs = tkParamDefs.Length;
+
+ // Not all parameters have tokens. Parameters may have no token
+ // if they have no name and no attributes.
+ if (cParamDefs > sigArgCount + 1 /* return type */)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
+
+ for (int i = 0; i < cParamDefs; i++)
+ {
+ #region Populate ParameterInfos
+ ParameterAttributes attr;
+ int position, tkParamDef = tkParamDefs[i];
+
+ scope.GetParamDefProps(tkParamDef, out position, out attr);
+
+ position--;
+
+ if (fetchReturnParameter == true && position == -1)
+ {
+ // more than one return parameter?
+ if (returnParameter != null)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
+
+ returnParameter = new RuntimeParameterInfo(sig, scope, tkParamDef, position, attr, member);
+ }
+ else if (fetchReturnParameter == false && position >= 0)
+ {
+ // position beyong sigArgCount?
+ if (position >= sigArgCount)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ParameterSignatureMismatch"));
+
+ args[position] = new RuntimeParameterInfo(sig, scope, tkParamDef, position, attr, member);
+ }
+ #endregion
+ }
+ }
+
+ // Fill in empty ParameterInfos for those without tokens
+ if (fetchReturnParameter)
+ {
+ if (returnParameter == null)
+ {
+ returnParameter = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, -1, (ParameterAttributes)0, member);
+ }
+ }
+ else
+ {
+ if (cParamDefs < args.Length + 1)
+ {
+ for (int i = 0; i < args.Length; i++)
+ {
+ if (args[i] != null)
+ continue;
+
+ args[i] = new RuntimeParameterInfo(sig, MetadataImport.EmptyImport, 0, i, (ParameterAttributes)0, member);
+ }
+ }
+ }
+
+ return args;
+ }
+ #endregion
+
+ #region Private Statics
+ private static readonly Type s_DecimalConstantAttributeType = typeof(DecimalConstantAttribute);
+ private static readonly Type s_CustomConstantAttributeType = typeof(CustomConstantAttribute);
+ #endregion
+
+ #region Private Data Members
+ // These are new in Whidbey, so we cannot serialize them directly or we break backwards compatibility.
+ [NonSerialized]
+ private int m_tkParamDef;
+ [NonSerialized]
+ private MetadataImport m_scope;
+ [NonSerialized]
+ private Signature m_signature;
+ [NonSerialized]
+ private volatile bool m_nameIsCached = false;
+ [NonSerialized]
+ private readonly bool m_noMetadata = false;
+ [NonSerialized]
+ private bool m_noDefaultValue = false;
+ [NonSerialized]
+ private MethodBase m_originalMember = null;
+ #endregion
+
+ #region Internal Properties
+ internal MethodBase DefiningMethod
+ {
+ get
+ {
+ MethodBase result = m_originalMember != null ? m_originalMember : MemberImpl as MethodBase;
+ Contract.Assert(result != null);
+ return result;
+ }
+ }
+ #endregion
+
+ #region VTS magic to serialize/deserialized to/from pre-Whidbey endpoints.
+ [System.Security.SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // We could be serializing for consumption by a pre-Whidbey
+ // endpoint. Therefore we set up all the serialized fields to look
+ // just like a v1.0/v1.1 instance.
+
+ // Need to set the type to ParameterInfo so that pre-Whidbey and Whidbey code
+ // can deserialize this. This is also why we cannot simply use [OnSerializing].
+ info.SetType(typeof(ParameterInfo));
+
+ // Use the properties intead of the fields in case the fields haven't been et
+ // _importer, bExtraConstChecked, and m_cachedData don't need to be set
+
+ // Now set the legacy fields that the current implementation doesn't
+ // use any more. Note that _importer is a raw pointer that should
+ // never have been serialized in V1. We set it to zero here; if the
+ // deserializer uses it (by calling GetCustomAttributes() on this
+ // instance) they'll AV, but at least it will be a well defined
+ // exception and not a random AV.
+
+ info.AddValue("AttrsImpl", Attributes);
+ info.AddValue("ClassImpl", ParameterType);
+ info.AddValue("DefaultValueImpl", DefaultValue);
+ info.AddValue("MemberImpl", Member);
+ info.AddValue("NameImpl", Name);
+ info.AddValue("PositionImpl", Position);
+ info.AddValue("_token", m_tkParamDef);
+ }
+ #endregion
+
+ #region Constructor
+ // used by RuntimePropertyInfo
+ internal RuntimeParameterInfo(RuntimeParameterInfo accessor, RuntimePropertyInfo property)
+ : this(accessor, (MemberInfo)property)
+ {
+ m_signature = property.Signature;
+ }
+
+ private RuntimeParameterInfo(RuntimeParameterInfo accessor, MemberInfo member)
+ {
+ // Change ownership
+ MemberImpl = member;
+
+ // The original owner should always be a method, because this method is only used to
+ // change the owner from a method to a property.
+ m_originalMember = accessor.MemberImpl as MethodBase;
+ Contract.Assert(m_originalMember != null);
+
+ // Populate all the caches -- we inherit this behavior from RTM
+ NameImpl = accessor.Name;
+ m_nameIsCached = true;
+ ClassImpl = accessor.ParameterType;
+ PositionImpl = accessor.Position;
+ AttrsImpl = accessor.Attributes;
+
+ // Strictly speeking, property's don't contain paramter tokens
+ // However we need this to make ca's work... oh well...
+ m_tkParamDef = MdToken.IsNullToken(accessor.MetadataToken) ? (int)MetadataTokenType.ParamDef : accessor.MetadataToken;
+ m_scope = accessor.m_scope;
+ }
+
+ private RuntimeParameterInfo(
+ Signature signature, MetadataImport scope, int tkParamDef,
+ int position, ParameterAttributes attributes, MemberInfo member)
+ {
+ Contract.Requires(member != null);
+ Contract.Assert(MdToken.IsNullToken(tkParamDef) == scope.Equals(MetadataImport.EmptyImport));
+ Contract.Assert(MdToken.IsNullToken(tkParamDef) || MdToken.IsTokenOfType(tkParamDef, MetadataTokenType.ParamDef));
+
+ PositionImpl = position;
+ MemberImpl = member;
+ m_signature = signature;
+ m_tkParamDef = MdToken.IsNullToken(tkParamDef) ? (int)MetadataTokenType.ParamDef : tkParamDef;
+ m_scope = scope;
+ AttrsImpl = attributes;
+
+ ClassImpl = null;
+ NameImpl = null;
+ }
+
+ // ctor for no metadata MethodInfo in the DynamicMethod and RuntimeMethodInfo cases
+ internal RuntimeParameterInfo(MethodInfo owner, String name, Type parameterType, int position)
+ {
+ MemberImpl = owner;
+ NameImpl = name;
+ m_nameIsCached = true;
+ m_noMetadata = true;
+ ClassImpl = parameterType;
+ PositionImpl = position;
+ AttrsImpl = ParameterAttributes.None;
+ m_tkParamDef = (int)MetadataTokenType.ParamDef;
+ m_scope = MetadataImport.EmptyImport;
+ }
+ #endregion
+
+ #region Public Methods
+ public override Type ParameterType
+ {
+ get
+ {
+ // only instance of ParameterInfo has ClassImpl, all its subclasses don't
+ if (ClassImpl == null)
+ {
+ RuntimeType parameterType;
+ if (PositionImpl == -1)
+ parameterType = m_signature.ReturnType;
+ else
+ parameterType = m_signature.Arguments[PositionImpl];
+
+ Contract.Assert(parameterType != null);
+ // different thread could only write ClassImpl to the same value, so a race condition is not a problem here
+ ClassImpl = parameterType;
+ }
+
+ return ClassImpl;
+ }
+ }
+
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (!m_nameIsCached)
+ {
+ if (!MdToken.IsNullToken(m_tkParamDef))
+ {
+ string name;
+ name = m_scope.GetName(m_tkParamDef).ToString();
+ NameImpl = name;
+ }
+
+ // other threads could only write it to true, so a race condition is OK
+ // this field is volatile, so the write ordering is guaranteed
+ m_nameIsCached = true;
+ }
+
+ // name may be null
+ return NameImpl;
+ }
+ }
+
+ public override bool HasDefaultValue
+ {
+ get
+ {
+ if (m_noMetadata || m_noDefaultValue)
+ return false;
+
+ object defaultValue = GetDefaultValueInternal(false);
+
+ return (defaultValue != DBNull.Value);
+ }
+ }
+
+ public override Object DefaultValue { get { return GetDefaultValue(false); } }
+ public override Object RawDefaultValue { get { return GetDefaultValue(true); } }
+
+ private Object GetDefaultValue(bool raw)
+ {
+ // OLD COMMENT (Is this even true?)
+ // Cannot cache because default value could be non-agile user defined enumeration.
+ // OLD COMMENT ends
+ if (m_noMetadata)
+ return null;
+
+ // for dynamic method we pretend to have cached the value so we do not go to metadata
+ object defaultValue = GetDefaultValueInternal(raw);
+
+ if (defaultValue == DBNull.Value)
+ {
+ #region Handle case if no default value was found
+ if (IsOptional)
+ {
+ // If the argument is marked as optional then the default value is Missing.Value.
+ defaultValue = Type.Missing;
+ }
+ #endregion
+ }
+
+ return defaultValue;
+ }
+
+ // returns DBNull.Value if the parameter doesn't have a default value
+ [System.Security.SecuritySafeCritical]
+ private Object GetDefaultValueInternal(bool raw)
+ {
+ Contract.Assert(!m_noMetadata);
+
+ if (m_noDefaultValue)
+ return DBNull.Value;
+
+ object defaultValue = null;
+
+ // Why check the parameter type only for DateTime and only for the ctor arguments?
+ // No check on the parameter type is done for named args and for Decimal.
+
+ // We should move this after MdToken.IsNullToken(m_tkParamDef) and combine it
+ // with the other custom attribute logic. But will that be a breaking change?
+ // For a DateTime parameter on which both an md constant and a ca constant are set,
+ // which one should win?
+ if (ParameterType == typeof(DateTime))
+ {
+ if (raw)
+ {
+ CustomAttributeTypedArgument value =
+ CustomAttributeData.Filter(
+ CustomAttributeData.GetCustomAttributes(this), typeof(DateTimeConstantAttribute), 0);
+
+ if (value.ArgumentType != null)
+ return new DateTime((long)value.Value);
+ }
+ else
+ {
+ object[] dt = GetCustomAttributes(typeof(DateTimeConstantAttribute), false);
+ if (dt != null && dt.Length != 0)
+ return ((DateTimeConstantAttribute)dt[0]).Value;
+ }
+ }
+
+ #region Look for a default value in metadata
+ if (!MdToken.IsNullToken(m_tkParamDef))
+ {
+ // This will return DBNull.Value if no constant value is defined on m_tkParamDef in the metadata.
+ defaultValue = MdConstant.GetValue(m_scope, m_tkParamDef, ParameterType.GetTypeHandleInternal(), raw);
+ }
+ #endregion
+
+ if (defaultValue == DBNull.Value)
+ {
+ #region Look for a default value in the custom attributes
+ if (raw)
+ {
+ foreach (CustomAttributeData attr in CustomAttributeData.GetCustomAttributes(this))
+ {
+ Type attrType = attr.Constructor.DeclaringType;
+
+ if (attrType == typeof(DateTimeConstantAttribute))
+ {
+ defaultValue = DateTimeConstantAttribute.GetRawDateTimeConstant(attr);
+ }
+ else if (attrType == typeof(DecimalConstantAttribute))
+ {
+ defaultValue = DecimalConstantAttribute.GetRawDecimalConstant(attr);
+ }
+ else if (attrType.IsSubclassOf(s_CustomConstantAttributeType))
+ {
+ defaultValue = CustomConstantAttribute.GetRawConstant(attr);
+ }
+ }
+ }
+ else
+ {
+ Object[] CustomAttrs = GetCustomAttributes(s_CustomConstantAttributeType, false);
+ if (CustomAttrs.Length != 0)
+ {
+ defaultValue = ((CustomConstantAttribute)CustomAttrs[0]).Value;
+ }
+ else
+ {
+ CustomAttrs = GetCustomAttributes(s_DecimalConstantAttributeType, false);
+ if (CustomAttrs.Length != 0)
+ {
+ defaultValue = ((DecimalConstantAttribute)CustomAttrs[0]).Value;
+ }
+ }
+ }
+ #endregion
+ }
+
+ if (defaultValue == DBNull.Value)
+ m_noDefaultValue = true;
+
+ return defaultValue;
+ }
+
+ internal RuntimeModule GetRuntimeModule()
+ {
+ RuntimeMethodInfo method = Member as RuntimeMethodInfo;
+ RuntimeConstructorInfo constructor = Member as RuntimeConstructorInfo;
+ RuntimePropertyInfo property = Member as RuntimePropertyInfo;
+
+ if (method != null)
+ return method.GetRuntimeModule();
+ else if (constructor != null)
+ return constructor.GetRuntimeModule();
+ else if (property != null)
+ return property.GetRuntimeModule();
+ else
+ return null;
+ }
+
+ public override int MetadataToken
+ {
+ get
+ {
+ return m_tkParamDef;
+ }
+ }
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return m_signature.GetCustomModifiers(PositionImpl + 1, true);
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return m_signature.GetCustomModifiers(PositionImpl + 1, false);
+ }
+
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ if (MdToken.IsNullToken(m_tkParamDef))
+ return EmptyArray<Object>.Value;
+
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ if (MdToken.IsNullToken(m_tkParamDef))
+ return EmptyArray<Object>.Value;
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ if (MdToken.IsNullToken(m_tkParamDef))
+ return false;
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Remoting Cache
+ private RemotingParameterCachedData m_cachedData;
+
+ internal RemotingParameterCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingParameterCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingParameterCachedData(this);
+ RemotingParameterCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ParameterModifier.cs b/src/mscorlib/src/System/Reflection/ParameterModifier.cs
new file mode 100644
index 0000000000..97da1b9e00
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ParameterModifier.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Diagnostics.Contracts;
+namespace System.Reflection
+{
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct ParameterModifier
+ {
+ #region Private Data Members
+ private bool[] _byRef;
+ #endregion
+
+ #region Constructor
+ public ParameterModifier(int parameterCount)
+ {
+ if (parameterCount <= 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ParmArraySize"));
+ Contract.EndContractBlock();
+
+ _byRef = new bool[parameterCount];
+ }
+ #endregion
+
+ #region Internal Members
+ internal bool[] IsByRefArray { get { return _byRef; } }
+ #endregion
+
+ #region Public Members
+ public bool this[int index]
+ {
+ get
+ {
+ return _byRef[index];
+ }
+ set
+ {
+ _byRef[index] = value;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/Pointer.cs b/src/mscorlib/src/System/Reflection/Pointer.cs
new file mode 100644
index 0000000000..8105208288
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/Pointer.cs
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// This is a wrapper class for Pointers
+//
+//
+//
+//
+//
+namespace System.Reflection {
+ using System;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ [CLSCompliant(false)]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Pointer : ISerializable
+ {
+ [SecurityCritical]
+ unsafe private void* _ptr;
+ private RuntimeType _ptrType;
+
+ private Pointer() {}
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe Pointer(SerializationInfo info, StreamingContext context)
+ {
+ _ptr = ((IntPtr)(info.GetValue("_ptr", typeof(IntPtr)))).ToPointer();
+ _ptrType = (RuntimeType)info.GetValue("_ptrType", typeof(RuntimeType));
+ }
+
+ // This method will box an pointer. We save both the
+ // value and the type so we can access it from the native code
+ // during an Invoke.
+ [System.Security.SecurityCritical] // auto-generated
+ public static unsafe Object Box(void *ptr,Type type) {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (!type.IsPointer)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"ptr");
+ Contract.EndContractBlock();
+
+ RuntimeType rt = type as RuntimeType;
+ if (rt == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"), "ptr");
+
+ Pointer x = new Pointer();
+ x._ptr = ptr;
+ x._ptrType = rt;
+ return x;
+ }
+
+ // Returned the stored pointer.
+ [System.Security.SecurityCritical] // auto-generated
+ public static unsafe void* Unbox(Object ptr) {
+ if (!(ptr is Pointer))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"ptr");
+ return ((Pointer)ptr)._ptr;
+ }
+
+ internal RuntimeType GetPointerType() {
+ return _ptrType;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe Object GetPointerValue() {
+ return (IntPtr)_ptr;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ info.AddValue("_ptr", new IntPtr(_ptr));
+ info.AddValue("_ptrType", _ptrType);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/PropertyAttributes.cs b/src/mscorlib/src/System/Reflection/PropertyAttributes.cs
new file mode 100644
index 0000000000..d7c3d79b6a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/PropertyAttributes.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// PropertyAttributes is an enum which defines the attributes that may be associated
+//
+// with a property. The values here are defined in Corhdr.h.
+//
+//
+namespace System.Reflection {
+
+ using System;
+ // This Enum matchs the CorPropertyAttr defined in CorHdr.h
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum PropertyAttributes
+ {
+ None = 0x0000,
+ SpecialName = 0x0200, // property is special. Name describes how.
+
+ // Reserved flags for Runtime use only.
+ ReservedMask = 0xf400,
+ RTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding.
+ HasDefault = 0x1000, // Property has default
+ Reserved2 = 0x2000, // reserved bit
+ Reserved3 = 0x4000, // reserved bit
+ Reserved4 = 0x8000 // reserved bit
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/PropertyInfo.cs b/src/mscorlib/src/System/Reflection/PropertyInfo.cs
new file mode 100644
index 0000000000..3e451b15b6
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/PropertyInfo.cs
@@ -0,0 +1,657 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Reflection
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Text;
+ using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_PropertyInfo))]
+#pragma warning disable 618
+ [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
+#pragma warning restore 618
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class PropertyInfo : MemberInfo, _PropertyInfo
+ {
+ #region Constructor
+ protected PropertyInfo() { }
+ #endregion
+
+ public static bool operator ==(PropertyInfo left, PropertyInfo right)
+ {
+ if (ReferenceEquals(left, right))
+ return true;
+
+ if ((object)left == null || (object)right == null ||
+ left is RuntimePropertyInfo || right is RuntimePropertyInfo)
+ {
+ return false;
+ }
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(PropertyInfo left, PropertyInfo right)
+ {
+ return !(left == right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ return base.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return System.Reflection.MemberTypes.Property; } }
+ #endregion
+
+ #region Public Abstract\Virtual Members
+ public virtual object GetConstantValue()
+ {
+ throw new NotImplementedException();
+ }
+
+ public virtual object GetRawConstantValue()
+ {
+ throw new NotImplementedException();
+ }
+
+ public abstract Type PropertyType { get; }
+
+ public abstract void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture);
+
+ public abstract MethodInfo[] GetAccessors(bool nonPublic);
+
+ public abstract MethodInfo GetGetMethod(bool nonPublic);
+
+ public abstract MethodInfo GetSetMethod(bool nonPublic);
+
+ public abstract ParameterInfo[] GetIndexParameters();
+
+ public abstract PropertyAttributes Attributes { get; }
+
+ public abstract bool CanRead { get; }
+
+ public abstract bool CanWrite { get; }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public Object GetValue(Object obj)
+ {
+ return GetValue(obj, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public virtual Object GetValue(Object obj,Object[] index)
+ {
+ return GetValue(obj, BindingFlags.Default, null, index, null);
+ }
+
+ public abstract Object GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture);
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public void SetValue(Object obj, Object value)
+ {
+ SetValue(obj, value, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public virtual void SetValue(Object obj, Object value, Object[] index)
+ {
+ SetValue(obj, value, BindingFlags.Default, null, index, null);
+ }
+ #endregion
+
+ #region Public Members
+ public virtual Type[] GetRequiredCustomModifiers() { return EmptyArray<Type>.Value; }
+
+ public virtual Type[] GetOptionalCustomModifiers() { return EmptyArray<Type>.Value; }
+
+ public MethodInfo[] GetAccessors() { return GetAccessors(false); }
+
+ public virtual MethodInfo GetMethod
+ {
+ get
+ {
+ return GetGetMethod(true);
+ }
+ }
+
+ public virtual MethodInfo SetMethod
+ {
+ get
+ {
+ return GetSetMethod(true);
+ }
+ }
+
+ public MethodInfo GetGetMethod() { return GetGetMethod(false); }
+
+ public MethodInfo GetSetMethod() { return GetSetMethod(false); }
+
+ public bool IsSpecialName { get { return(Attributes & PropertyAttributes.SpecialName) != 0; } }
+ #endregion
+
+#if !FEATURE_CORECLR
+ Type _PropertyInfo.GetType()
+ {
+ return base.GetType();
+ }
+
+ void _PropertyInfo.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _PropertyInfo.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _PropertyInfo.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _PropertyInfo.Invoke in VM\DangerousAPIs.h and
+ // include _PropertyInfo in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _PropertyInfo.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+
+ [Serializable]
+ internal unsafe sealed class RuntimePropertyInfo : PropertyInfo, ISerializable
+ {
+ #region Private Data Members
+ private int m_token;
+ private string m_name;
+ [System.Security.SecurityCritical]
+ private void* m_utf8name;
+ private PropertyAttributes m_flags;
+ private RuntimeTypeCache m_reflectedTypeCache;
+ private RuntimeMethodInfo m_getterMethod;
+ private RuntimeMethodInfo m_setterMethod;
+ private MethodInfo[] m_otherMethod;
+ private RuntimeType m_declaringType;
+ private BindingFlags m_bindingFlags;
+ private Signature m_signature;
+ private ParameterInfo[] m_parameters;
+ #endregion
+
+ #region Constructor
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimePropertyInfo(
+ int tkProperty, RuntimeType declaredType, RuntimeTypeCache reflectedTypeCache, out bool isPrivate)
+ {
+ Contract.Requires(declaredType != null);
+ Contract.Requires(reflectedTypeCache != null);
+ Contract.Assert(!reflectedTypeCache.IsGlobal);
+
+ MetadataImport scope = declaredType.GetRuntimeModule().MetadataImport;
+
+ m_token = tkProperty;
+ m_reflectedTypeCache = reflectedTypeCache;
+ m_declaringType = declaredType;
+
+ ConstArray sig;
+ scope.GetPropertyProps(tkProperty, out m_utf8name, out m_flags, out sig);
+
+ RuntimeMethodInfo dummy;
+ Associates.AssignAssociates(scope, tkProperty, declaredType, reflectedTypeCache.GetRuntimeType(),
+ out dummy, out dummy, out dummy,
+ out m_getterMethod, out m_setterMethod, out m_otherMethod,
+ out isPrivate, out m_bindingFlags);
+ }
+ #endregion
+
+ #region Internal Members
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RuntimePropertyInfo m = o as RuntimePropertyInfo;
+
+ if ((object)m == null)
+ return false;
+
+ return m.m_token == m_token &&
+ RuntimeTypeHandle.GetModule(m_declaringType).Equals(
+ RuntimeTypeHandle.GetModule(m.m_declaringType));
+ }
+
+ internal Signature Signature
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_signature == null)
+ {
+ PropertyAttributes flags;
+ ConstArray sig;
+
+ void* name;
+ GetRuntimeModule().MetadataImport.GetPropertyProps(
+ m_token, out name, out flags, out sig);
+
+ m_signature = new Signature(sig.Signature.ToPointer(), (int)sig.Length, m_declaringType);
+ }
+
+ return m_signature;
+ }
+ }
+ internal bool EqualsSig(RuntimePropertyInfo target)
+ {
+ //@Asymmetry - Legacy policy is to remove duplicate properties, including hidden properties.
+ // The comparison is done by name and by sig. The EqualsSig comparison is expensive
+ // but forutnetly it is only called when an inherited property is hidden by name or
+ // when an interfaces declare properies with the same signature.
+ // Note that we intentionally don't resolve generic arguments so that we don't treat
+ // signatures that only match in certain instantiations as duplicates. This has the
+ // down side of treating overriding and overriden properties as different properties
+ // in some cases. But PopulateProperties in rttype.cs should have taken care of that
+ // by comparing VTable slots.
+ //
+ // Class C1(Of T, Y)
+ // Property Prop1(ByVal t1 As T) As Integer
+ // Get
+ // ... ...
+ // End Get
+ // End Property
+ // Property Prop1(ByVal y1 As Y) As Integer
+ // Get
+ // ... ...
+ // End Get
+ // End Property
+ // End Class
+ //
+
+ Contract.Requires(Name.Equals(target.Name));
+ Contract.Requires(this != target);
+ Contract.Requires(this.ReflectedType == target.ReflectedType);
+
+ return Signature.CompareSig(this.Signature, target.Signature);
+ }
+ internal BindingFlags BindingFlags { get { return m_bindingFlags; } }
+ #endregion
+
+ #region Object Overrides
+ public override String ToString()
+ {
+ return FormatNameAndSig(false);
+ }
+
+ private string FormatNameAndSig(bool serialization)
+ {
+ StringBuilder sbName = new StringBuilder(PropertyType.FormatTypeName(serialization));
+
+ sbName.Append(" ");
+ sbName.Append(Name);
+
+ RuntimeType[] arguments = Signature.Arguments;
+ if (arguments.Length > 0)
+ {
+ sbName.Append(" [");
+ sbName.Append(MethodBase.ConstructParameters(arguments, Signature.CallingConvention, serialization));
+ sbName.Append("]");
+ }
+
+ return sbName.ToString();
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, typeof(object) as RuntimeType);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if (attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override MemberTypes MemberType { get { return MemberTypes.Property; } }
+ public override String Name
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_name == null)
+ m_name = new Utf8String(m_utf8name).ToString();
+
+ return m_name;
+ }
+ }
+ public override Type DeclaringType
+ {
+ get
+ {
+ return m_declaringType;
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return ReflectedTypeInternal;
+ }
+ }
+
+ private RuntimeType ReflectedTypeInternal
+ {
+ get
+ {
+ return m_reflectedTypeCache.GetRuntimeType();
+ }
+ }
+
+ public override int MetadataToken { get { return m_token; } }
+
+ public override Module Module { get { return GetRuntimeModule(); } }
+ internal RuntimeModule GetRuntimeModule() { return m_declaringType.GetRuntimeModule(); }
+ #endregion
+
+ #region PropertyInfo Overrides
+
+ #region Non Dynamic
+
+ public override Type[] GetRequiredCustomModifiers()
+ {
+ return Signature.GetCustomModifiers(0, true);
+ }
+
+ public override Type[] GetOptionalCustomModifiers()
+ {
+ return Signature.GetCustomModifiers(0, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal object GetConstantValue(bool raw)
+ {
+ Object defaultValue = MdConstant.GetValue(GetRuntimeModule().MetadataImport, m_token, PropertyType.GetTypeHandleInternal(), raw);
+
+ if (defaultValue == DBNull.Value)
+ // Arg_EnumLitValueNotFound -> "Literal value was not found."
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_EnumLitValueNotFound"));
+
+ return defaultValue;
+ }
+
+ public override object GetConstantValue() { return GetConstantValue(false); }
+
+ public override object GetRawConstantValue() { return GetConstantValue(true); }
+
+ public override MethodInfo[] GetAccessors(bool nonPublic)
+ {
+ List<MethodInfo> accessorList = new List<MethodInfo>();
+
+ if (Associates.IncludeAccessor(m_getterMethod, nonPublic))
+ accessorList.Add(m_getterMethod);
+
+ if (Associates.IncludeAccessor(m_setterMethod, nonPublic))
+ accessorList.Add(m_setterMethod);
+
+ if ((object)m_otherMethod != null)
+ {
+ for(int i = 0; i < m_otherMethod.Length; i ++)
+ {
+ if (Associates.IncludeAccessor(m_otherMethod[i] as MethodInfo, nonPublic))
+ accessorList.Add(m_otherMethod[i]);
+ }
+ }
+ return accessorList.ToArray();
+ }
+
+ public override Type PropertyType
+ {
+ get { return Signature.ReturnType; }
+ }
+
+ public override MethodInfo GetGetMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_getterMethod, nonPublic))
+ return null;
+
+ return m_getterMethod;
+ }
+
+ public override MethodInfo GetSetMethod(bool nonPublic)
+ {
+ if (!Associates.IncludeAccessor(m_setterMethod, nonPublic))
+ return null;
+
+ return m_setterMethod;
+ }
+
+ public override ParameterInfo[] GetIndexParameters()
+ {
+ ParameterInfo[] indexParams = GetIndexParametersNoCopy();
+
+ int numParams = indexParams.Length;
+
+ if (numParams == 0)
+ return indexParams;
+
+ ParameterInfo[] ret = new ParameterInfo[numParams];
+
+ Array.Copy(indexParams, ret, numParams);
+
+ return ret;
+ }
+
+ internal ParameterInfo[] GetIndexParametersNoCopy()
+ {
+ // @History - Logic ported from RTM
+
+ // No need to lock because we don't guarantee the uniqueness of ParameterInfo objects
+ if (m_parameters == null)
+ {
+ int numParams = 0;
+ ParameterInfo[] methParams = null;
+
+ // First try to get the Get method.
+ MethodInfo m = GetGetMethod(true);
+ if (m != null)
+ {
+ // There is a Get method so use it.
+ methParams = m.GetParametersNoCopy();
+ numParams = methParams.Length;
+ }
+ else
+ {
+ // If there is no Get method then use the Set method.
+ m = GetSetMethod(true);
+
+ if (m != null)
+ {
+ methParams = m.GetParametersNoCopy();
+ numParams = methParams.Length - 1;
+ }
+ }
+
+ // Now copy over the parameter info's and change their
+ // owning member info to the current property info.
+
+ ParameterInfo[] propParams = new ParameterInfo[numParams];
+
+ for (int i = 0; i < numParams; i++)
+ propParams[i] = new RuntimeParameterInfo((RuntimeParameterInfo)methParams[i], this);
+
+ m_parameters = propParams;
+ }
+
+ return m_parameters;
+ }
+
+ public override PropertyAttributes Attributes
+ {
+ get
+ {
+ return m_flags;
+ }
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ return m_getterMethod != null;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ return m_setterMethod != null;
+ }
+ }
+ #endregion
+
+ #region Dynamic
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValue(Object obj,Object[] index)
+ {
+ return GetValue(obj, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
+ null, index, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object GetValue(Object obj, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
+ {
+
+ MethodInfo m = GetGetMethod(true);
+ if (m == null)
+ throw new ArgumentException(System.Environment.GetResourceString("Arg_GetMethNotFnd"));
+ return m.Invoke(obj, invokeAttr, binder, index, null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, Object[] index)
+ {
+ SetValue(obj,
+ value,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
+ null,
+ index,
+ null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
+ {
+
+ MethodInfo m = GetSetMethod(true);
+
+ if (m == null)
+ throw new ArgumentException(System.Environment.GetResourceString("Arg_SetMethNotFnd"));
+
+ Object[] args = null;
+
+ if (index != null)
+ {
+ args = new Object[index.Length + 1];
+
+ for(int i=0;i<index.Length;i++)
+ args[i] = index[i];
+
+ args[index.Length] = value;
+ }
+ else
+ {
+ args = new Object[1];
+ args[0] = value;
+ }
+
+ m.Invoke(obj, invokeAttr, binder, args, culture);
+ }
+ #endregion
+
+ #endregion
+
+ #region ISerializable Implementation
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ MemberInfoSerializationHolder.GetSerializationInfo(
+ info,
+ Name,
+ ReflectedTypeInternal,
+ ToString(),
+ SerializationToString(),
+ MemberTypes.Property,
+ null);
+ }
+
+ internal string SerializationToString()
+ {
+ return FormatNameAndSig(true);
+ }
+ #endregion
+ }
+
+}
diff --git a/src/mscorlib/src/System/Reflection/ReflectionContext.cs b/src/mscorlib/src/System/Reflection/ReflectionContext.cs
new file mode 100644
index 0000000000..f9bfa87d76
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ReflectionContext.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: For Assembly-related stuff.
+**
+**
+=============================================================================*/
+
+namespace System.Reflection
+{
+ using System;
+
+ public abstract class ReflectionContext
+ {
+ protected ReflectionContext() { }
+
+ public abstract Assembly MapAssembly(Assembly assembly);
+
+ public abstract TypeInfo MapType(TypeInfo type);
+
+ public virtual TypeInfo GetTypeForObject(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ return MapType(value.GetType().GetTypeInfo());
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs b/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs
new file mode 100644
index 0000000000..9b55c260cf
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ReflectionTypeLoadException.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// ReflectionTypeLoadException is thrown when multiple TypeLoadExceptions may occur.
+//
+// Specifically, when you call Module.GetTypes() this causes multiple class loads to occur.
+// If there are failures, we continue to load classes and build an array of the successfully
+// loaded classes. We also build an array of the errors that occur. Then we throw this exception
+// which exposes both the array of classes and the array of TypeLoadExceptions.
+//
+//
+//
+//
+namespace System.Reflection {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ReflectionTypeLoadException : SystemException, ISerializable {
+ private Type[] _classes;
+ private Exception[] _exceptions;
+
+ // private constructor. This is not called.
+ private ReflectionTypeLoadException()
+ : base(Environment.GetResourceString("ReflectionTypeLoad_LoadFailed")) {
+ SetErrorCode(__HResults.COR_E_REFLECTIONTYPELOAD);
+ }
+
+ // private constructor. This is called from inside the runtime.
+ private ReflectionTypeLoadException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_REFLECTIONTYPELOAD);
+ }
+
+ public ReflectionTypeLoadException(Type[] classes, Exception[] exceptions) : base(null)
+ {
+ _classes = classes;
+ _exceptions = exceptions;
+ SetErrorCode(__HResults.COR_E_REFLECTIONTYPELOAD);
+ }
+
+ public ReflectionTypeLoadException(Type[] classes, Exception[] exceptions, String message) : base(message)
+ {
+ _classes = classes;
+ _exceptions = exceptions;
+ SetErrorCode(__HResults.COR_E_REFLECTIONTYPELOAD);
+ }
+
+ internal ReflectionTypeLoadException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ _classes = (Type[])(info.GetValue("Types", typeof(Type[])));
+ _exceptions = (Exception[])(info.GetValue("Exceptions", typeof(Exception[])));
+ }
+
+ public Type[] Types {
+ get {return _classes;}
+ }
+
+ public Exception[] LoaderExceptions {
+ get {return _exceptions;}
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("Types", _classes, typeof(Type[]));
+ info.AddValue("Exceptions", _exceptions, typeof(Exception[]));
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/ResourceAttributes.cs b/src/mscorlib/src/System/Reflection/ResourceAttributes.cs
new file mode 100644
index 0000000000..646572677f
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/ResourceAttributes.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// ResourceAttributes is an enum which defines the attributes that may be associated
+//
+// with a manifest resource. The values here are defined in Corhdr.h.
+//
+//
+namespace System.Reflection {
+
+ using System;
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ResourceAttributes
+ {
+ Public = 0x0001,
+ Private = 0x0002,
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs b/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs
new file mode 100644
index 0000000000..b4ef9b9902
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/RuntimeReflectionExtensions.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Collections.Generic;
+
+namespace System.Reflection
+{
+ public static class RuntimeReflectionExtensions
+ {
+ private const BindingFlags everything = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
+
+ private static void CheckAndThrow(Type t)
+ {
+ if (t == null) throw new ArgumentNullException("type");
+ if (!(t is RuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+ }
+
+ private static void CheckAndThrow(MethodInfo m)
+ {
+ if (m == null) throw new ArgumentNullException("method");
+ if (!(m is RuntimeMethodInfo)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"));
+ }
+
+ public static IEnumerable<PropertyInfo> GetRuntimeProperties(this Type type)
+ {
+ CheckAndThrow(type);
+ return type.GetProperties(everything);
+ }
+ public static IEnumerable<EventInfo> GetRuntimeEvents(this Type type)
+ {
+ CheckAndThrow(type);
+ return type.GetEvents(everything);
+ }
+
+ public static IEnumerable<MethodInfo> GetRuntimeMethods(this Type type)
+ {
+ CheckAndThrow(type);
+ return type.GetMethods(everything);
+ }
+
+ public static IEnumerable<FieldInfo> GetRuntimeFields(this Type type)
+ {
+ CheckAndThrow(type);
+ return type.GetFields(everything);
+ }
+
+ public static PropertyInfo GetRuntimeProperty(this Type type, string name)
+ {
+ CheckAndThrow(type);
+ return type.GetProperty(name);
+ }
+ public static EventInfo GetRuntimeEvent(this Type type, string name)
+ {
+ CheckAndThrow(type);
+ return type.GetEvent(name);
+ }
+ public static MethodInfo GetRuntimeMethod(this Type type, string name, Type[] parameters)
+ {
+ CheckAndThrow(type);
+ return type.GetMethod(name, parameters);
+ }
+ public static FieldInfo GetRuntimeField(this Type type, string name)
+ {
+ CheckAndThrow(type);
+ return type.GetField(name);
+ }
+ public static MethodInfo GetRuntimeBaseDefinition(this MethodInfo method){
+ CheckAndThrow(method);
+ return method.GetBaseDefinition();
+ }
+
+ public static InterfaceMapping GetRuntimeInterfaceMap(this TypeInfo typeInfo, Type interfaceType)
+ {
+ if (typeInfo == null) throw new ArgumentNullException("typeInfo");
+ if (!(typeInfo is RuntimeType)) throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ return typeInfo.GetInterfaceMap(interfaceType);
+ }
+
+ public static MethodInfo GetMethodInfo(this Delegate del)
+ {
+ if (del == null) throw new ArgumentNullException("del");
+
+ return del.Method;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs b/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs
new file mode 100644
index 0000000000..e8a441ca8f
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/StrongNameKeyPair.cs
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Encapsulate access to a public/private key pair
+** used to sign strong name assemblies.
+**
+**
+===========================================================*/
+namespace System.Reflection
+{
+ using System;
+ using System.IO;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.Versioning;
+ using Microsoft.Win32;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_CORECLR
+ using Microsoft.Runtime.Hosting;
+#endif
+
+#if FEATURE_CORECLR
+ // Dummy type to avoid ifdefs in signature definitions
+ public class StrongNameKeyPair
+ {
+ private StrongNameKeyPair()
+ {
+ throw new NotSupportedException();
+ }
+ }
+#else
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class StrongNameKeyPair : IDeserializationCallback, ISerializable
+ {
+ private bool _keyPairExported;
+ private byte[] _keyPairArray;
+ private String _keyPairContainer;
+ private byte[] _publicKey;
+
+ // Build key pair from file.
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public StrongNameKeyPair(FileStream keyPairFile)
+ {
+ if (keyPairFile == null)
+ throw new ArgumentNullException("keyPairFile");
+ Contract.EndContractBlock();
+
+ int length = (int)keyPairFile.Length;
+ _keyPairArray = new byte[length];
+ keyPairFile.Read(_keyPairArray, 0, length);
+
+ _keyPairExported = true;
+ }
+
+ // Build key pair from byte array in memory.
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public StrongNameKeyPair(byte[] keyPairArray)
+ {
+ if (keyPairArray == null)
+ throw new ArgumentNullException("keyPairArray");
+ Contract.EndContractBlock();
+
+ _keyPairArray = new byte[keyPairArray.Length];
+ Array.Copy(keyPairArray, _keyPairArray, keyPairArray.Length);
+
+ _keyPairExported = true;
+ }
+
+ // Reference key pair in named key container.
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public StrongNameKeyPair(String keyPairContainer)
+ {
+ if (keyPairContainer == null)
+ throw new ArgumentNullException("keyPairContainer");
+ Contract.EndContractBlock();
+
+ _keyPairContainer = keyPairContainer;
+
+ _keyPairExported = false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ protected StrongNameKeyPair (SerializationInfo info, StreamingContext context) {
+ _keyPairExported = (bool) info.GetValue("_keyPairExported", typeof(bool));
+ _keyPairArray = (byte[]) info.GetValue("_keyPairArray", typeof(byte[]));
+ _keyPairContainer = (string) info.GetValue("_keyPairContainer", typeof(string));
+ _publicKey = (byte[]) info.GetValue("_publicKey", typeof(byte[]));
+ }
+
+ // Get the public portion of the key pair.
+ public byte[] PublicKey
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (_publicKey == null)
+ {
+ _publicKey = ComputePublicKey();
+ }
+
+ byte[] publicKey = new byte[_publicKey.Length];
+ Array.Copy(_publicKey, publicKey, _publicKey.Length);
+
+ return publicKey;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe byte[] ComputePublicKey()
+ {
+ byte[] publicKey = null;
+
+ // Make sure pbPublicKey is not leaked with async exceptions
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally
+ {
+ IntPtr pbPublicKey = IntPtr.Zero;
+ int cbPublicKey = 0;
+
+ try
+ {
+ bool result;
+ if (_keyPairExported)
+ {
+ result = StrongNameHelpers.StrongNameGetPublicKey(null, _keyPairArray, _keyPairArray.Length,
+ out pbPublicKey, out cbPublicKey);
+ }
+ else
+ {
+ result = StrongNameHelpers.StrongNameGetPublicKey(_keyPairContainer, null, 0,
+ out pbPublicKey, out cbPublicKey);
+ }
+ if (!result)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StrongNameGetPublicKey"));
+
+ publicKey = new byte[cbPublicKey];
+ Buffer.Memcpy(publicKey, 0, (byte*)(pbPublicKey.ToPointer()), 0, cbPublicKey);
+ }
+ finally
+ {
+ if (pbPublicKey != IntPtr.Zero)
+ StrongNameHelpers.StrongNameFreeBuffer(pbPublicKey);
+ }
+ }
+ return publicKey;
+ }
+
+ /// <internalonly/>
+ [System.Security.SecurityCritical]
+ void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) {
+ info.AddValue("_keyPairExported", _keyPairExported);
+ info.AddValue("_keyPairArray", _keyPairArray);
+ info.AddValue("_keyPairContainer", _keyPairContainer);
+ info.AddValue("_publicKey", _publicKey);
+ }
+
+ /// <internalonly/>
+ void IDeserializationCallback.OnDeserialization (Object sender) {}
+
+ // Internal routine used to retrieve key pair info from unmanaged code.
+ private bool GetKeyPair(out Object arrayOrContainer)
+ {
+ arrayOrContainer = _keyPairExported ? (Object)_keyPairArray : (Object)_keyPairContainer;
+ return _keyPairExported;
+ }
+ }
+#endif // FEATURE_CORECLR
+}
diff --git a/src/mscorlib/src/System/Reflection/TargetException.cs b/src/mscorlib/src/System/Reflection/TargetException.cs
new file mode 100644
index 0000000000..02772f763f
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TargetException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// TargetException is thrown when the target to an Invoke is invalid. This may
+//
+// occur because the caller doesn't have access to the member, or the target doesn't
+// define the member, etc.
+//
+//
+//
+//
+namespace System.Reflection {
+
+ using System;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ public class TargetException : Exception {
+#else
+ public class TargetException : ApplicationException {
+#endif //FEATURE_CORECLR
+ public TargetException() : base() {
+ SetErrorCode(__HResults.COR_E_TARGET);
+ }
+
+ public TargetException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_TARGET);
+ }
+
+ public TargetException(String message, Exception inner) : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_TARGET);
+ }
+
+ protected TargetException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/TargetInvocationException.cs b/src/mscorlib/src/System/Reflection/TargetInvocationException.cs
new file mode 100644
index 0000000000..70de4227dd
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TargetInvocationException.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// TargetInvocationException is used to report an exception that was thrown
+//
+// by the target of an invocation.
+//
+//
+//
+//
+namespace System.Reflection {
+
+
+ using System;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ public sealed class TargetInvocationException : Exception {
+#else
+ public sealed class TargetInvocationException : ApplicationException {
+#endif //FEATURE_CORECLR
+ // This exception is not creatable without specifying the
+ // inner exception.
+ private TargetInvocationException()
+ : base(Environment.GetResourceString("Arg_TargetInvocationException")) {
+ SetErrorCode(__HResults.COR_E_TARGETINVOCATION);
+ }
+
+ // This is called from within the runtime.
+ private TargetInvocationException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_TARGETINVOCATION);
+ }
+
+ public TargetInvocationException(System.Exception inner)
+ : base(Environment.GetResourceString("Arg_TargetInvocationException"), inner) {
+ SetErrorCode(__HResults.COR_E_TARGETINVOCATION);
+ }
+
+ public TargetInvocationException(String message, Exception inner) : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_TARGETINVOCATION);
+ }
+
+ internal TargetInvocationException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs b/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs
new file mode 100644
index 0000000000..4f95b09c40
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TargetParameterCountException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// TargetParameterCountException is thrown when the number of parameter to an
+//
+// invocation doesn't match the number expected.
+//
+//
+//
+//
+namespace System.Reflection {
+
+ using System;
+ using SystemException = System.SystemException;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ public sealed class TargetParameterCountException : Exception {
+#else
+ public sealed class TargetParameterCountException : ApplicationException {
+#endif //FEATURE_CORECLR
+ public TargetParameterCountException()
+ : base(Environment.GetResourceString("Arg_TargetParameterCountException")) {
+ SetErrorCode(__HResults.COR_E_TARGETPARAMCOUNT);
+ }
+
+ public TargetParameterCountException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_TARGETPARAMCOUNT);
+ }
+
+ public TargetParameterCountException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_TARGETPARAMCOUNT);
+ }
+
+ internal TargetParameterCountException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/TypeAttributes.cs b/src/mscorlib/src/System/Reflection/TypeAttributes.cs
new file mode 100644
index 0000000000..4fa6fb06ba
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TypeAttributes.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Reflection {
+ using System.Runtime.InteropServices;
+ using System;
+ // This Enum matchs the CorTypeAttr defined in CorHdr.h
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeAttributes
+ {
+ VisibilityMask = 0x00000007,
+ NotPublic = 0x00000000, // Class is not public scope.
+ Public = 0x00000001, // Class is public scope.
+ NestedPublic = 0x00000002, // Class is nested with public visibility.
+ NestedPrivate = 0x00000003, // Class is nested with private visibility.
+ NestedFamily = 0x00000004, // Class is nested with family visibility.
+ NestedAssembly = 0x00000005, // Class is nested with assembly visibility.
+ NestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility.
+ NestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility.
+
+ // Use this mask to retrieve class layout informaiton
+ // 0 is AutoLayout, 0x2 is SequentialLayout, 4 is ExplicitLayout
+ LayoutMask = 0x00000018,
+ AutoLayout = 0x00000000, // Class fields are auto-laid out
+ SequentialLayout = 0x00000008, // Class fields are laid out sequentially
+ ExplicitLayout = 0x00000010, // Layout is supplied explicitly
+ // end layout mask
+
+ // Use this mask to distinguish whether a type declaration is an interface. (Class vs. ValueType done based on whether it subclasses S.ValueType)
+ ClassSemanticsMask= 0x00000020,
+ Class = 0x00000000, // Type is a class (or a value type).
+ Interface = 0x00000020, // Type is an interface.
+
+ // Special semantics in addition to class semantics.
+ Abstract = 0x00000080, // Class is abstract
+ Sealed = 0x00000100, // Class is concrete and may not be extended
+ SpecialName = 0x00000400, // Class name is special. Name describes how.
+
+ // Implementation attributes.
+ Import = 0x00001000, // Class / interface is imported
+ Serializable = 0x00002000, // The class is Serializable.
+
+ [ComVisible(false)]
+ WindowsRuntime = 0x00004000, // Type is a Windows Runtime type.
+
+ // Use tdStringFormatMask to retrieve string information for native interop
+ StringFormatMask = 0x00030000,
+ AnsiClass = 0x00000000, // LPTSTR is interpreted as ANSI in this class
+ UnicodeClass = 0x00010000, // LPTSTR is interpreted as UNICODE
+ AutoClass = 0x00020000, // LPTSTR is interpreted automatically
+ CustomFormatClass = 0x00030000, // A non-standard encoding specified by CustomFormatMask
+ CustomFormatMask = 0x00C00000, // Use this mask to retrieve non-standard encoding information for native interop. The meaning of the values of these 2 bits is unspecified.
+
+ // end string format mask
+
+ BeforeFieldInit = 0x00100000, // Initialize the class any time before first static field access.
+
+ // Flags reserved for runtime use.
+ ReservedMask = 0x00040800,
+ RTSpecialName = 0x00000800, // Runtime should check name encoding.
+ HasSecurity = 0x00040000, // Class has security associate with it.
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/TypeDelegator.cs b/src/mscorlib/src/System/Reflection/TypeDelegator.cs
new file mode 100644
index 0000000000..cad4a4295a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TypeDelegator.cs
@@ -0,0 +1,263 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// TypeDelegator
+//
+// This class wraps a Type object and delegates all methods to that Type.
+
+namespace System.Reflection {
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class TypeDelegator : TypeInfo
+ {
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ protected Type typeImpl;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #endif
+ protected TypeDelegator() {}
+
+ public TypeDelegator(Type delegatingType) {
+ if (delegatingType == null)
+ throw new ArgumentNullException("delegatingType");
+ Contract.EndContractBlock();
+
+ typeImpl = delegatingType;
+ }
+
+ public override Guid GUID {
+ get {return typeImpl.GUID;}
+ }
+
+ public override int MetadataToken { get { return typeImpl.MetadataToken; } }
+
+ public override Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder,Object target,
+ Object[] args,ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters)
+ {
+ return typeImpl.InvokeMember(name,invokeAttr,binder,target,args,modifiers,culture,namedParameters);
+ }
+
+ public override Module Module {
+ get {return typeImpl.Module;}
+ }
+
+ public override Assembly Assembly {
+ get {return typeImpl.Assembly;}
+ }
+
+ public override RuntimeTypeHandle TypeHandle {
+ get{return typeImpl.TypeHandle;}
+ }
+
+ public override String Name {
+ get{return typeImpl.Name;}
+ }
+
+ public override String FullName {
+ get{return typeImpl.FullName;}
+ }
+
+ public override String Namespace {
+ get{return typeImpl.Namespace;}
+ }
+
+ public override String AssemblyQualifiedName {
+ get {
+ return typeImpl.AssemblyQualifiedName;
+ }
+ }
+
+ public override Type BaseType {
+ get{return typeImpl.BaseType;}
+ }
+
+ protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ return typeImpl.GetConstructor(bindingAttr,binder,callConvention,types,modifiers);
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetConstructors(bindingAttr);
+ }
+
+ protected override MethodInfo GetMethodImpl(String name,BindingFlags bindingAttr,Binder binder,
+ CallingConventions callConvention, Type[] types,ParameterModifier[] modifiers)
+ {
+ // This is interesting there are two paths into the impl. One that validates
+ // type as non-null and one where type may be null.
+ if (types == null)
+ return typeImpl.GetMethod(name,bindingAttr);
+ else
+ return typeImpl.GetMethod(name,bindingAttr,binder,callConvention,types,modifiers);
+ }
+
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetMethods(bindingAttr);
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ return typeImpl.GetField(name,bindingAttr);
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetFields(bindingAttr);
+ }
+
+ public override Type GetInterface(String name, bool ignoreCase)
+ {
+ return typeImpl.GetInterface(name,ignoreCase);
+ }
+
+ public override Type[] GetInterfaces()
+ {
+ return typeImpl.GetInterfaces();
+ }
+
+ public override EventInfo GetEvent(String name,BindingFlags bindingAttr)
+ {
+ return typeImpl.GetEvent(name,bindingAttr);
+ }
+
+ public override EventInfo[] GetEvents()
+ {
+ return typeImpl.GetEvents();
+ }
+
+ protected override PropertyInfo GetPropertyImpl(String name,BindingFlags bindingAttr,Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (returnType == null && types == null)
+ return typeImpl.GetProperty(name,bindingAttr);
+ else
+ return typeImpl.GetProperty(name,bindingAttr,binder,returnType,types,modifiers);
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetProperties(bindingAttr);
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetEvents(bindingAttr);
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetNestedTypes(bindingAttr);
+ }
+
+ public override Type GetNestedType(String name, BindingFlags bindingAttr)
+ {
+ return typeImpl.GetNestedType(name,bindingAttr);
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ return typeImpl.GetMember(name,type,bindingAttr);
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ return typeImpl.GetMembers(bindingAttr);
+ }
+
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return typeImpl.Attributes;
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return typeImpl.IsArray;
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return typeImpl.IsPrimitive;
+ }
+
+ protected override bool IsByRefImpl()
+ {
+ return typeImpl.IsByRef;
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return typeImpl.IsPointer;
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ return typeImpl.IsValueType;
+ }
+
+ protected override bool IsCOMObjectImpl()
+ {
+ return typeImpl.IsCOMObject;
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get
+ {
+ return typeImpl.IsConstructedGenericType;
+ }
+ }
+
+ public override Type GetElementType()
+ {
+ return typeImpl.GetElementType();
+ }
+
+ protected override bool HasElementTypeImpl()
+ {
+ return typeImpl.HasElementType;
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get {return typeImpl.UnderlyingSystemType;}
+ }
+
+ // ICustomAttributeProvider
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return typeImpl.GetCustomAttributes(inherit);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ return typeImpl.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ return typeImpl.IsDefined(attributeType, inherit);
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ return typeImpl.GetInterfaceMap(interfaceType);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Reflection/TypeFilter.cs b/src/mscorlib/src/System/Reflection/TypeFilter.cs
new file mode 100644
index 0000000000..560618ff79
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TypeFilter.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// TypeFilter defines a delegate that is as a callback function for filtering
+//
+// a list of Types.
+//
+//
+namespace System.Reflection {
+
+ // Define the delegate
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate bool TypeFilter(Type m, Object filterCriteria);
+}
diff --git a/src/mscorlib/src/System/Reflection/TypeInfo.cs b/src/mscorlib/src/System/Reflection/TypeInfo.cs
new file mode 100644
index 0000000000..706fb0a61a
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/TypeInfo.cs
@@ -0,0 +1,195 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: Notion of a type definition
+**
+**
+=============================================================================*/
+
+namespace System.Reflection
+{
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ //all today's runtime Type derivations derive now from TypeInfo
+ //we make TypeInfo implement IRCT - simplifies work
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public abstract class TypeInfo:Type,IReflectableType
+ {
+ [FriendAccessAllowed]
+ internal TypeInfo() { }
+
+ TypeInfo IReflectableType.GetTypeInfo(){
+ return this;
+ }
+ public virtual Type AsType(){
+ return (Type)this;
+ }
+
+ public virtual Type[] GenericTypeParameters{
+ get{
+ if(IsGenericTypeDefinition){
+ return GetGenericArguments();
+ }
+ else{
+ return Type.EmptyTypes;
+ }
+
+ }
+ }
+ //a re-implementation of ISAF from Type, skipping the use of UnderlyingType
+ [Pure]
+ public virtual bool IsAssignableFrom(TypeInfo typeInfo)
+ {
+ if (typeInfo == null)
+ return false;
+
+ if (this == typeInfo)
+ return true;
+
+ // If c is a subclass of this class, then c can be cast to this type.
+ if (typeInfo.IsSubclassOf(this))
+ return true;
+
+ if (this.IsInterface)
+ {
+ return typeInfo.ImplementInterface(this);
+ }
+ else if (IsGenericParameter)
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+ for (int i = 0; i < constraints.Length; i++)
+ if (!constraints[i].IsAssignableFrom(typeInfo))
+ return false;
+
+ return true;
+ }
+
+ return false;
+ }
+#region moved over from Type
+ // Fields
+
+ public virtual EventInfo GetDeclaredEvent(String name)
+ {
+ return GetEvent(name, Type.DeclaredOnlyLookup);
+ }
+ public virtual FieldInfo GetDeclaredField(String name)
+ {
+ return GetField(name, Type.DeclaredOnlyLookup);
+ }
+ public virtual MethodInfo GetDeclaredMethod(String name)
+ {
+ return GetMethod(name, Type.DeclaredOnlyLookup);
+ }
+
+ public virtual IEnumerable<MethodInfo> GetDeclaredMethods(String name)
+ {
+ foreach (MethodInfo method in GetMethods(Type.DeclaredOnlyLookup))
+ {
+ if (method.Name == name)
+ yield return method;
+ }
+ }
+ public virtual System.Reflection.TypeInfo GetDeclaredNestedType(String name)
+ {
+ var nt=GetNestedType(name, Type.DeclaredOnlyLookup);
+ if(nt == null){
+ return null; //the extension method GetTypeInfo throws for null
+ }else{
+ return nt.GetTypeInfo();
+ }
+ }
+ public virtual PropertyInfo GetDeclaredProperty(String name)
+ {
+ return GetProperty(name, Type.DeclaredOnlyLookup);
+ }
+
+
+
+
+
+ // Properties
+
+ public virtual IEnumerable<ConstructorInfo> DeclaredConstructors
+ {
+ get
+ {
+ return GetConstructors(Type.DeclaredOnlyLookup);
+ }
+ }
+
+ public virtual IEnumerable<EventInfo> DeclaredEvents
+ {
+ get
+ {
+ return GetEvents(Type.DeclaredOnlyLookup);
+ }
+ }
+
+ public virtual IEnumerable<FieldInfo> DeclaredFields
+ {
+ get
+ {
+ return GetFields(Type.DeclaredOnlyLookup);
+ }
+ }
+
+ public virtual IEnumerable<MemberInfo> DeclaredMembers
+ {
+ get
+ {
+ return GetMembers(Type.DeclaredOnlyLookup);
+ }
+ }
+
+ public virtual IEnumerable<MethodInfo> DeclaredMethods
+ {
+ get
+ {
+ return GetMethods(Type.DeclaredOnlyLookup);
+ }
+ }
+ public virtual IEnumerable<System.Reflection.TypeInfo> DeclaredNestedTypes
+ {
+ get
+ {
+ foreach (var t in GetNestedTypes(Type.DeclaredOnlyLookup)){
+ yield return t.GetTypeInfo();
+ }
+ }
+ }
+
+ public virtual IEnumerable<PropertyInfo> DeclaredProperties
+ {
+ get
+ {
+ return GetProperties(Type.DeclaredOnlyLookup);
+ }
+ }
+
+
+ public virtual IEnumerable<Type> ImplementedInterfaces
+ {
+ get
+ {
+ return GetInterfaces();
+ }
+ }
+
+
+#endregion
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Reflection/__Filters.cs b/src/mscorlib/src/System/Reflection/__Filters.cs
new file mode 100644
index 0000000000..8edcd0d7cb
--- /dev/null
+++ b/src/mscorlib/src/System/Reflection/__Filters.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+//
+// This class defines the delegate methods for the COM+ implemented filters.
+// This is the reflection version of these. There is also a _Filters class in
+// runtime which is related to this.
+//
+//
+//
+//
+namespace System.Reflection {
+ using System;
+ using System.Globalization;
+
+ [Serializable]
+ internal class __Filters {
+
+ // FilterTypeName
+ // This method will filter the class based upon the name. It supports
+ // a trailing wild card.
+ public virtual bool FilterTypeName(Type cls,Object filterCriteria)
+ {
+ // Check that the criteria object is a String object
+ if (filterCriteria == null || !(filterCriteria is String))
+ throw new InvalidFilterCriteriaException(System.Environment.GetResourceString("RFLCT.FltCritString"));
+
+ String str = (String) filterCriteria;
+ //str = str.Trim();
+
+ // Check to see if this is a prefix or exact match requirement
+ if (str.Length > 0 && str[str.Length - 1] == '*') {
+ str = str.Substring(0, str.Length - 1);
+ return cls.Name.StartsWith(str, StringComparison.Ordinal);
+ }
+
+ return cls.Name.Equals(str);
+ }
+
+ // FilterFieldNameIgnoreCase
+ // This method filter the Type based upon name, it ignores case.
+ public virtual bool FilterTypeNameIgnoreCase(Type cls, Object filterCriteria)
+ {
+ // Check that the criteria object is a String object
+ if(filterCriteria == null || !(filterCriteria is String))
+ throw new InvalidFilterCriteriaException(System.Environment.GetResourceString("RFLCT.FltCritString"));
+
+ String str = (String) filterCriteria;
+ //str = str.Trim();
+
+ // Check to see if this is a prefix or exact match requirement
+ if (str.Length > 0 && str[str.Length - 1] == '*') {
+ str = str.Substring(0, str.Length - 1);
+ String name = cls.Name;
+ if (name.Length >= str.Length)
+ return (String.Compare(name,0,str,0,str.Length, StringComparison.OrdinalIgnoreCase)==0);
+ else
+ return false;
+ }
+ return (String.Compare(str,cls.Name, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ResId.cs b/src/mscorlib/src/System/ResId.cs
new file mode 100644
index 0000000000..e6a2423c28
--- /dev/null
+++ b/src/mscorlib/src/System/ResId.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Contains identifiers for each of the resources
+** specified in resources.txt
+**
+**
+===========================================================*/
+namespace System {
+ //This class contains only static members and does not need to be serializable.
+ using System.Configuration.Assemblies;
+ using System;
+ internal static class ResId {
+ // Only statics, does not need to be marked with the serializable attribute
+ internal const String Arg_ArrayLengthsDiffer="Arg_ArrayLengthsDiffer";
+ internal const String Argument_InvalidNumberOfMembers="Argument_InvalidNumberOfMembers";
+ internal const String Argument_UnequalMembers="Argument_UnequalMembers";
+ internal const String Argument_SpecifyValueSize="Argument_SpecifyValueSize";
+ internal const String Argument_UnmatchingSymScope="Argument_UnmatchingSymScope";
+ internal const String Argument_NotInExceptionBlock="Argument_NotInExceptionBlock";
+ internal const String Argument_NotExceptionType="Argument_NotExceptionType";
+ internal const String Argument_InvalidLabel="Argument_InvalidLabel";
+ internal const String Argument_UnclosedExceptionBlock="Argument_UnclosedExceptionBlock";
+ internal const String Argument_MissingDefaultConstructor="Argument_MissingDefaultConstructor";
+ internal const String Argument_TooManyFinallyClause="Argument_TooManyFinallyClause";
+ internal const String Argument_NotInTheSameModuleBuilder="Argument_NotInTheSameModuleBuilder";
+ internal const String Argument_BadCurrentLocalVariable="Argument_BadCurrentLocalVariable";
+ internal const String Argument_DuplicateModuleName="Argument_DuplicateModuleName";
+ internal const String Argument_BadPersistableModuleInTransientAssembly="Argument_BadPersistableModuleInTransientAssembly";
+ internal const String Argument_HasToBeArrayClass="Argument_HasToBeArrayClass";
+ internal const String Argument_InvalidDirectory="Argument_InvalidDirectory";
+
+ internal const String MissingType="MissingType";
+ internal const String MissingModule="MissingModule";
+
+ internal const String ArgumentOutOfRange_Index="ArgumentOutOfRange_Index";
+ internal const String ArgumentOutOfRange_Range="ArgumentOutOfRange_Range";
+
+ internal const String ExecutionEngine_YoureHosed="ExecutionEngine_YoureHosed";
+
+ internal const String Format_NeedSingleChar="Format_NeedSingleChar";
+ internal const String Format_StringZeroLength="Format_StringZeroLength";
+
+ internal const String InvalidOperation_EnumEnded="InvalidOperation_EnumEnded";
+ internal const String InvalidOperation_EnumFailedVersion="InvalidOperation_EnumFailedVersion";
+ internal const String InvalidOperation_EnumNotStarted="InvalidOperation_EnumNotStarted";
+ internal const String InvalidOperation_EnumOpCantHappen="InvalidOperation_EnumOpCantHappen";
+ internal const String InvalidOperation_InternalState="InvalidOperation_InternalState";
+ internal const String InvalidOperation_ModifyRONumFmtInfo="InvalidOperation_ModifyRONumFmtInfo";
+ internal const String InvalidOperation_MethodBaked="InvalidOperation_MethodBaked";
+ internal const String InvalidOperation_NotADebugModule="InvalidOperation_NotADebugModule";
+ internal const String InvalidOperation_MethodHasBody="InvalidOperation_MethodHasBody";
+ internal const String InvalidOperation_OpenLocalVariableScope="InvalidOperation_OpenLocalVariableScope";
+ internal const String InvalidOperation_TypeHasBeenCreated="InvalidOperation_TypeHasBeenCreated";
+ internal const String InvalidOperation_RefedAssemblyNotSaved="InvalidOperation_RefedAssemblyNotSaved";
+ internal const String InvalidOperation_AssemblyHasBeenSaved="InvalidOperation_AssemblyHasBeenSaved";
+ internal const String InvalidOperation_ModuleHasBeenSaved="InvalidOperation_ModuleHasBeenSaved";
+ internal const String InvalidOperation_CannotAlterAssembly="InvalidOperation_CannotAlterAssembly";
+
+ internal const String NotSupported_CannotSaveModuleIndividually="NotSupported_CannotSaveModuleIndividually";
+ internal const String NotSupported_Constructor="NotSupported_Constructor";
+ internal const String NotSupported_Method="NotSupported_Method";
+ internal const String NotSupported_NYI="NotSupported_NYI";
+ internal const String NotSupported_DynamicModule="NotSupported_DynamicModule";
+ internal const String NotSupported_NotDynamicModule="NotSupported_NotDynamicModule";
+ internal const String NotSupported_NotAllTypesAreBaked="NotSupported_NotAllTypesAreBaked";
+ internal const String NotSupported_SortedListNestedWrite="NotSupported_SortedListNestedWrite";
+
+
+ internal const String Serialization_ArrayInvalidLength="Serialization_ArrayInvalidLength";
+ internal const String Serialization_ArrayNoLength="Serialization_ArrayNoLength";
+ internal const String Serialization_CannotGetType="Serialization_CannotGetType";
+ internal const String Serialization_InsufficientState="Serialization_InsufficientState";
+ internal const String Serialization_InvalidID="Serialization_InvalidID";
+ internal const String Serialization_MalformedArray="Serialization_MalformedArray";
+ internal const String Serialization_MultipleMembers="Serialization_MultipleMembers";
+ internal const String Serialization_NoID="Serialization_NoID";
+ internal const String Serialization_NoType="Serialization_NoType";
+ internal const String Serialization_NoBaseType="Serialization_NoBaseType";
+ internal const String Serialization_NullSignature="Serialization_NullSignature";
+ internal const String Serialization_UnknownMember="Serialization_UnknownMember";
+ internal const String Serialization_BadParameterInfo="Serialization_BadParameterInfo";
+ internal const String Serialization_NoParameterInfo="Serialization_NoParameterInfo";
+
+ internal const String WeakReference_NoLongerValid="WeakReference_NoLongerValid";
+ internal const String Loader_InvalidPath="Loader_InvalidPath";
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs b/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs
new file mode 100644
index 0000000000..efd949f565
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/FileBasedResourceGroveler.cs
@@ -0,0 +1,175 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Searches for resources on disk, used for file-
+** based resource lookup.
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.IO;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Text;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ internal class FileBasedResourceGroveler : IResourceGroveler
+ {
+ private ResourceManager.ResourceManagerMediator _mediator;
+
+ public FileBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator)
+ {
+ Contract.Assert(mediator != null, "mediator shouldn't be null; check caller");
+ _mediator = mediator;
+ }
+
+ // Consider modifying IResourceGroveler interface (hence this method signature) when we figure out
+ // serialization compat story for moving ResourceManager members to either file-based or
+ // manifest-based classes. Want to continue tightening the design to get rid of unused params.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark)
+ {
+ Contract.Assert(culture != null, "culture shouldn't be null; check caller");
+
+ String fileName = null;
+ ResourceSet rs = null;
+
+ // Don't use Assembly manifest, but grovel on disk for a file.
+ try
+ {
+ new System.Security.Permissions.FileIOPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
+
+ // Create new ResourceSet, if a file exists on disk for it.
+ String tempFileName = _mediator.GetResourceFileName(culture);
+ fileName = FindResourceFile(culture, tempFileName);
+ if (fileName == null)
+ {
+ if (tryParents)
+ {
+ // If we've hit top of the Culture tree, return.
+ if (culture.HasInvariantCultureName)
+ {
+ // We really don't think this should happen - we always
+ // expect the neutral locale's resources to be present.
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoNeutralDisk") + Environment.NewLine + "baseName: " + _mediator.BaseNameField + " locationInfo: " + (_mediator.LocationInfo == null ? "<null>" : _mediator.LocationInfo.FullName) + " fileName: " + _mediator.GetResourceFileName(culture));
+ }
+ }
+ }
+ else
+ {
+ rs = CreateResourceSet(fileName);
+ }
+ return rs;
+ }
+ finally
+ {
+ System.Security.CodeAccessPermission.RevertAssert();
+ }
+ }
+
+#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr
+ public bool HasNeutralResources(CultureInfo culture, String defaultResName)
+ {
+ // Detect missing neutral locale resources.
+ String defaultResPath = FindResourceFile(culture, defaultResName);
+ if (defaultResPath == null || !File.Exists(defaultResPath))
+ {
+ String dir = _mediator.ModuleDir;
+ if (defaultResPath != null)
+ {
+ dir = Path.GetDirectoryName(defaultResPath);
+ }
+ return false;
+ }
+ return true;
+ }
+#endif
+
+ // Given a CultureInfo, it generates the path &; file name for
+ // the .resources file for that CultureInfo. This method will grovel
+ // the disk looking for the correct file name & path. Uses CultureInfo's
+ // Name property. If the module directory was set in the ResourceManager
+ // constructor, we'll look there first. If it couldn't be found in the module
+ // diretory or the module dir wasn't provided, look in the current
+ // directory.
+
+ private String FindResourceFile(CultureInfo culture, String fileName)
+ {
+ Contract.Assert(culture != null, "culture shouldn't be null; check caller");
+ Contract.Assert(fileName != null, "fileName shouldn't be null; check caller");
+
+ // If we have a moduleDir, check there first. Get module fully
+ // qualified name, append path to that.
+ if (_mediator.ModuleDir != null)
+ {
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 3)
+ BCLDebug.Log("FindResourceFile: checking module dir: \""+_mediator.ModuleDir+'\"');
+#endif
+
+ String path = Path.Combine(_mediator.ModuleDir, fileName);
+ if (File.Exists(path))
+ {
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 3)
+ BCLDebug.Log("Found resource file in module dir! "+path);
+#endif
+ return path;
+ }
+ }
+
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 3)
+ BCLDebug.Log("Couldn't find resource file in module dir, checking .\\"+fileName);
+#endif
+
+ // look in .
+ if (File.Exists(fileName))
+ return fileName;
+
+ return null; // give up.
+ }
+
+ // Constructs a new ResourceSet for a given file name. The logic in
+ // here avoids a ReflectionPermission check for our RuntimeResourceSet
+ // for perf and working set reasons.
+ [System.Security.SecurityCritical]
+ private ResourceSet CreateResourceSet(String file)
+ {
+ Contract.Assert(file != null, "file shouldn't be null; check caller");
+
+ if (_mediator.UserResourceSet == null)
+ {
+ // Explicitly avoid CreateInstance if possible, because it
+ // requires ReflectionPermission to call private & protected
+ // constructors.
+ return new RuntimeResourceSet(file);
+ }
+ else
+ {
+ Object[] args = new Object[1];
+ args[0] = file;
+ try
+ {
+ return (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
+ }
+ catch (MissingMethodException e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResMgrBadResSet_Type", _mediator.UserResourceSet.AssemblyQualifiedName), e);
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/IResourceGroveler.cs b/src/mscorlib/src/System/Resources/IResourceGroveler.cs
new file mode 100644
index 0000000000..983fd1204c
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/IResourceGroveler.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Interface for resource grovelers
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.Globalization;
+ using System.Threading;
+ using System.Collections.Generic;
+ using System.Runtime.Versioning;
+
+ internal interface IResourceGroveler
+ {
+ ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents,
+ bool createIfNotExists, ref StackCrawlMark stackMark);
+
+#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr
+
+ bool HasNeutralResources(CultureInfo culture, String defaultResName);
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/IResourceReader.cs b/src/mscorlib/src/System/Resources/IResourceReader.cs
new file mode 100644
index 0000000000..7ab25ec1a0
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/IResourceReader.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Abstraction to read streams of resources.
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.IO;
+ using System.Collections;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IResourceReader : IEnumerable, IDisposable
+ {
+ // Interface does not need to be marked with the serializable attribute
+ // Closes the ResourceReader, releasing any resources associated with it.
+ // This could close a network connection, a file, or do nothing.
+ void Close();
+
+
+ new IDictionaryEnumerator GetEnumerator();
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/IResourceWriter.cs b/src/mscorlib/src/System/Resources/IResourceWriter.cs
new file mode 100644
index 0000000000..ae41b84cd7
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/IResourceWriter.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Default way to write strings to a COM+ resource
+** file.
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.IO;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IResourceWriter : IDisposable
+ {
+ // Interface does not need to be marked with the serializable attribute
+ // Adds a string resource to the list of resources to be written to a file.
+ // They aren't written until WriteFile() is called.
+ //
+ void AddResource(String name, String value);
+
+ // Adds a resource to the list of resources to be written to a file.
+ // They aren't written until WriteFile() is called.
+ //
+ void AddResource(String name, Object value);
+
+ // Adds a named byte array as a resource to the list of resources to
+ // be written to a file. They aren't written until WriteFile() is called.
+ //
+ void AddResource(String name, byte[] value);
+
+ // Closes the underlying resource file.
+ void Close();
+
+ // After calling AddResource, this writes all resources to the output
+ // stream. This does NOT close the output stream.
+ void Generate();
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs b/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs
new file mode 100644
index 0000000000..8235d608be
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/LooselyLinkedResourceReference.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Provides a localizable way of retrieving a file
+** that is linked into your assembly and/or satellite assembly
+** while also leaving the file on disk for unmanaged tools.
+**
+**
+===========================================================*/
+
+// Removing LooselyLinkedResourceReference from Whidbey. We don't
+// yet have any strong customer need for it yet.
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+
+namespace System.Resources {
+ using System.Reflection;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+
+ [Serializable]
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct LooselyLinkedResourceReference {
+ private String _manifestResourceName;
+ private String _typeName;
+
+ public LooselyLinkedResourceReference(String looselyLinkedResourceName, String typeName)
+ {
+ if (looselyLinkedResourceName == null)
+ throw new ArgumentNullException("looselyLinkedResourceName");
+ if (typeName == null)
+ throw new ArgumentNullException("typeName");
+ if (looselyLinkedResourceName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "looselyLinkedResourceName");
+ if (typeName.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "typeName");
+ Contract.EndContractBlock();
+
+ _manifestResourceName = looselyLinkedResourceName;
+ _typeName = typeName;
+ }
+
+ public String LooselyLinkedResourceName {
+ get { return _manifestResourceName; }
+ }
+
+ public String TypeName {
+ get { return _typeName; }
+ }
+
+ public Object Resolve(Assembly assembly)
+ {
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+ Contract.EndContractBlock();
+
+ Stream data = assembly.GetManifestResourceStream(_manifestResourceName);
+ if (data == null)
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_LooselyLinked", _manifestResourceName, assembly.FullName));
+
+ Type type = Type.GetType(_typeName, true);
+
+ Object obj = Activator.CreateInstance(type, new Object[] { data });
+ return obj;
+ }
+
+ // For good debugging with tools like ResView
+ public override String ToString()
+ {
+ // This is for debugging only. Since we use the property names,
+ // this does not need to be localized.
+ return "LooselyLinkedResourceName = \""+ _manifestResourceName +"\", TypeName = \"" + _typeName + "\"";
+ }
+ }
+}
+
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
diff --git a/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs
new file mode 100644
index 0000000000..5fd0daad09
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ManifestBasedResourceGroveler.cs
@@ -0,0 +1,677 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Searches for resources in Assembly manifest, used
+** for assembly-based resource lookup.
+**
+**
+===========================================================*/
+namespace System.Resources {
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Text;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+ using Microsoft.Win32;
+
+#if !FEATURE_CORECLR
+ using System.Diagnostics.Tracing;
+#endif
+
+ //
+ // Note: this type is integral to the construction of exception objects,
+ // and sometimes this has to be done in low memory situtations (OOM) or
+ // to create TypeInitializationExceptions due to failure of a static class
+ // constructor. This type needs to be extremely careful and assume that
+ // any type it references may have previously failed to construct, so statics
+ // belonging to that type may not be initialized. FrameworkEventSource.Log
+ // is one such example.
+ //
+ internal class ManifestBasedResourceGroveler : IResourceGroveler
+ {
+
+ private ResourceManager.ResourceManagerMediator _mediator;
+
+ public ManifestBasedResourceGroveler(ResourceManager.ResourceManagerMediator mediator)
+ {
+ // here and below: convert asserts to preconditions where appropriate when we get
+ // contracts story in place.
+ Contract.Requires(mediator != null, "mediator shouldn't be null; check caller");
+ _mediator = mediator;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public ResourceSet GrovelForResourceSet(CultureInfo culture, Dictionary<String, ResourceSet> localResourceSets, bool tryParents, bool createIfNotExists, ref StackCrawlMark stackMark)
+ {
+ Contract.Assert(culture != null, "culture shouldn't be null; check caller");
+ Contract.Assert(localResourceSets != null, "localResourceSets shouldn't be null; check caller");
+
+ ResourceSet rs = null;
+ Stream stream = null;
+ RuntimeAssembly satellite = null;
+
+ // 1. Fixups for ultimate fallbacks
+ CultureInfo lookForCulture = UltimateFallbackFixup(culture);
+
+ // 2. Look for satellite assembly or main assembly, as appropriate
+ if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly)
+ {
+ // don't bother looking in satellites in this case
+ satellite = _mediator.MainAssembly;
+ }
+#if RESOURCE_SATELLITE_CONFIG
+ // If our config file says the satellite isn't here, don't ask for it.
+ else if (!lookForCulture.HasInvariantCultureName && !_mediator.TryLookingForSatellite(lookForCulture))
+ {
+ satellite = null;
+ }
+#endif
+ else
+ {
+ satellite = GetSatelliteAssembly(lookForCulture, ref stackMark);
+
+ if (satellite == null)
+ {
+ bool raiseException = (culture.HasInvariantCultureName && (_mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite));
+ // didn't find satellite, give error if necessary
+ if (raiseException)
+ {
+ HandleSatelliteMissing();
+ }
+ }
+ }
+
+ // get resource file name we'll search for. Note, be careful if you're moving this statement
+ // around because lookForCulture may be modified from originally requested culture above.
+ String fileName = _mediator.GetResourceFileName(lookForCulture);
+
+ // 3. If we identified an assembly to search; look in manifest resource stream for resource file
+ if (satellite != null)
+ {
+ // Handle case in here where someone added a callback for assembly load events.
+ // While no other threads have called into GetResourceSet, our own thread can!
+ // At that point, we could already have an RS in our hash table, and we don't
+ // want to add it twice.
+ lock (localResourceSets)
+ {
+ if (localResourceSets.TryGetValue(culture.Name, out rs))
+ {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCacheUnexpected(_mediator.BaseName, _mediator.MainAssembly, culture.Name);
+ }
+#endif
+ }
+ }
+
+ stream = GetManifestResourceStream(satellite, fileName, ref stackMark);
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ if (stream != null)
+ {
+ FrameworkEventSource.Log.ResourceManagerStreamFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName);
+ }
+ else
+ {
+ FrameworkEventSource.Log.ResourceManagerStreamNotFound(_mediator.BaseName, _mediator.MainAssembly, culture.Name, satellite, fileName);
+ }
+ }
+#endif
+
+ // 4a. Found a stream; create a ResourceSet if possible
+ if (createIfNotExists && stream != null && rs == null)
+ {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name, fileName);
+ }
+#endif
+ rs = CreateResourceSet(stream, satellite);
+ }
+ else if (stream == null && tryParents)
+ {
+ // 4b. Didn't find stream; give error if necessary
+ bool raiseException = culture.HasInvariantCultureName;
+ if (raiseException)
+ {
+ HandleResourceStreamMissing(fileName);
+ }
+ }
+
+#if !FEATURE_CORECLR
+ if (!createIfNotExists && stream != null && rs == null)
+ {
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerNotCreatingResourceSet(_mediator.BaseName, _mediator.MainAssembly, culture.Name);
+ }
+ }
+#endif
+
+ return rs;
+ }
+
+#if !FEATURE_CORECLR
+ // Returns whether or not the main assembly contains a particular resource
+ // file in it's assembly manifest. Used to verify that the neutral
+ // Culture's .resources file is present in the main assembly
+ public bool HasNeutralResources(CultureInfo culture, String defaultResName)
+ {
+ String resName = defaultResName;
+ if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null)
+ resName = _mediator.LocationInfo.Namespace + Type.Delimiter + defaultResName;
+ String[] resourceFiles = _mediator.MainAssembly.GetManifestResourceNames();
+ foreach(String s in resourceFiles)
+ if (s.Equals(resName))
+ return true;
+ return false;
+ }
+#endif
+
+ private CultureInfo UltimateFallbackFixup(CultureInfo lookForCulture)
+ {
+
+ CultureInfo returnCulture = lookForCulture;
+
+ // If our neutral resources were written in this culture AND we know the main assembly
+ // does NOT contain neutral resources, don't probe for this satellite.
+ if (lookForCulture.Name == _mediator.NeutralResourcesCulture.Name &&
+ _mediator.FallbackLoc == UltimateResourceFallbackLocation.MainAssembly)
+ {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerNeutralResourcesSufficient(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name);
+ }
+#endif
+
+ returnCulture = CultureInfo.InvariantCulture;
+ }
+ else if (lookForCulture.HasInvariantCultureName && _mediator.FallbackLoc == UltimateResourceFallbackLocation.Satellite)
+ {
+ returnCulture = _mediator.NeutralResourcesCulture;
+ }
+
+ return returnCulture;
+
+ }
+
+ [System.Security.SecurityCritical]
+ internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, ref UltimateResourceFallbackLocation fallbackLocation)
+ {
+ Contract.Assert(a != null, "assembly != null");
+ string cultureName = null;
+ short fallback = 0;
+ if (GetNeutralResourcesLanguageAttribute(((RuntimeAssembly)a).GetNativeHandle(),
+ JitHelpers.GetStringHandleOnStack(ref cultureName),
+ out fallback)) {
+ if ((UltimateResourceFallbackLocation)fallback < UltimateResourceFallbackLocation.MainAssembly || (UltimateResourceFallbackLocation)fallback > UltimateResourceFallbackLocation.Satellite) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_FallbackLoc", fallback));
+ }
+ fallbackLocation = (UltimateResourceFallbackLocation)fallback;
+ }
+ else {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized) {
+ FrameworkEventSource.Log.ResourceManagerNeutralResourceAttributeMissing(a);
+ }
+#endif
+ fallbackLocation = UltimateResourceFallbackLocation.MainAssembly;
+ return CultureInfo.InvariantCulture;
+ }
+
+ try
+ {
+ CultureInfo c = CultureInfo.GetCultureInfo(cultureName);
+ return c;
+ }
+ catch (ArgumentException e)
+ { // we should catch ArgumentException only.
+ // Note we could go into infinite loops if mscorlib's
+ // NeutralResourcesLanguageAttribute is mangled. If this assert
+ // fires, please fix the build process for the BCL directory.
+ if (a == typeof(Object).Assembly)
+ {
+ Contract.Assert(false, System.CoreLib.Name+"'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + cultureName + "\" Exception: " + e);
+ return CultureInfo.InvariantCulture;
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_Asm_Culture", a.ToString(), cultureName), e);
+ }
+ }
+
+ // Constructs a new ResourceSet for a given file name. The logic in
+ // here avoids a ReflectionPermission check for our RuntimeResourceSet
+ // for perf and working set reasons.
+ // Use the assembly to resolve assembly manifest resource references.
+ // Note that is can be null, but probably shouldn't be.
+ // This method could use some refactoring. One thing at a time.
+ [System.Security.SecurityCritical]
+ internal ResourceSet CreateResourceSet(Stream store, Assembly assembly)
+ {
+ Contract.Assert(store != null, "I need a Stream!");
+ // Check to see if this is a Stream the ResourceManager understands,
+ // and check for the correct resource reader type.
+ if (store.CanSeek && store.Length > 4)
+ {
+ long startPos = store.Position;
+
+ // not disposing because we want to leave stream open
+ BinaryReader br = new BinaryReader(store);
+
+ // Look for our magic number as a little endian Int32.
+ int bytes = br.ReadInt32();
+ if (bytes == ResourceManager.MagicNumber)
+ {
+ int resMgrHeaderVersion = br.ReadInt32();
+ String readerTypeName = null, resSetTypeName = null;
+ if (resMgrHeaderVersion == ResourceManager.HeaderVersionNumber)
+ {
+ br.ReadInt32(); // We don't want the number of bytes to skip.
+ readerTypeName = System.CoreLib.FixupCoreLibName(br.ReadString());
+ resSetTypeName = System.CoreLib.FixupCoreLibName(br.ReadString());
+ }
+ else if (resMgrHeaderVersion > ResourceManager.HeaderVersionNumber)
+ {
+ // Assume that the future ResourceManager headers will
+ // have two strings for us - the reader type name and
+ // resource set type name. Read those, then use the num
+ // bytes to skip field to correct our position.
+ int numBytesToSkip = br.ReadInt32();
+ long endPosition = br.BaseStream.Position + numBytesToSkip;
+
+ readerTypeName = System.CoreLib.FixupCoreLibName(br.ReadString());
+ resSetTypeName = System.CoreLib.FixupCoreLibName(br.ReadString());
+
+ br.BaseStream.Seek(endPosition, SeekOrigin.Begin);
+ }
+ else
+ {
+ // resMgrHeaderVersion is older than this ResMgr version.
+ // We should add in backwards compatibility support here.
+
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ObsoleteResourcesFile", _mediator.MainAssembly.GetSimpleName()));
+ }
+
+ store.Position = startPos;
+ // Perf optimization - Don't use Reflection for our defaults.
+ // Note there are two different sets of strings here - the
+ // assembly qualified strings emitted by ResourceWriter, and
+ // the abbreviated ones emitted by InternalResGen.
+ if (CanUseDefaultResourceClasses(readerTypeName, resSetTypeName))
+ {
+ RuntimeResourceSet rs;
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ rs = new RuntimeResourceSet(store, assembly);
+#else
+ rs = new RuntimeResourceSet(store);
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ return rs;
+ }
+ else
+ {
+ // we do not want to use partial binding here.
+ Type readerType = Type.GetType(readerTypeName, true);
+ Object[] args = new Object[1];
+ args[0] = store;
+ IResourceReader reader = (IResourceReader)Activator.CreateInstance(readerType, args);
+
+ Object[] resourceSetArgs =
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ new Object[2];
+#else
+ new Object[1];
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ resourceSetArgs[0] = reader;
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ resourceSetArgs[1] = assembly;
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ Type resSetType;
+ if (_mediator.UserResourceSet == null)
+ {
+ Contract.Assert(resSetTypeName != null, "We should have a ResourceSet type name from the custom resource file here.");
+ resSetType = Type.GetType(resSetTypeName, true, false);
+ }
+ else
+ resSetType = _mediator.UserResourceSet;
+ ResourceSet rs = (ResourceSet)Activator.CreateInstance(resSetType,
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.CreateInstance,
+ null,
+ resourceSetArgs,
+ null,
+ null);
+ return rs;
+ }
+ }
+ else
+ {
+ store.Position = startPos;
+ }
+
+ }
+
+ if (_mediator.UserResourceSet == null)
+ {
+ // Explicitly avoid CreateInstance if possible, because it
+ // requires ReflectionPermission to call private & protected
+ // constructors.
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ return new RuntimeResourceSet(store, assembly);
+#else
+ return new RuntimeResourceSet(store);
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ }
+ else
+ {
+ Object[] args = new Object[2];
+ args[0] = store;
+ args[1] = assembly;
+ try
+ {
+ ResourceSet rs = null;
+ // Add in a check for a constructor taking in an assembly first.
+ try
+ {
+ rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
+ return rs;
+ }
+ catch (MissingMethodException) { }
+
+ args = new Object[1];
+ args[0] = store;
+ rs = (ResourceSet)Activator.CreateInstance(_mediator.UserResourceSet, args);
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ rs.Assembly = assembly;
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ return rs;
+ }
+ catch (MissingMethodException e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResMgrBadResSet_Type", _mediator.UserResourceSet.AssemblyQualifiedName), e);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private Stream GetManifestResourceStream(RuntimeAssembly satellite, String fileName, ref StackCrawlMark stackMark)
+ {
+ Contract.Requires(satellite != null, "satellite shouldn't be null; check caller");
+ Contract.Requires(fileName != null, "fileName shouldn't be null; check caller");
+
+ // If we're looking in the main assembly AND if the main assembly was the person who
+ // created the ResourceManager, skip a security check for private manifest resources.
+ bool canSkipSecurityCheck = (_mediator.MainAssembly == satellite)
+ && (_mediator.CallingAssembly == _mediator.MainAssembly);
+
+ Stream stream = satellite.GetManifestResourceStream(_mediator.LocationInfo, fileName, canSkipSecurityCheck, ref stackMark);
+ if (stream == null)
+ {
+ stream = CaseInsensitiveManifestResourceStreamLookup(satellite, fileName);
+ }
+
+ return stream;
+ }
+
+ // Looks up a .resources file in the assembly manifest using
+ // case-insensitive lookup rules. Yes, this is slow. The metadata
+ // dev lead refuses to make all assembly manifest resource lookups case-insensitive,
+ // even optionally case-insensitive.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ private Stream CaseInsensitiveManifestResourceStreamLookup(RuntimeAssembly satellite, String name)
+ {
+ Contract.Requires(satellite != null, "satellite shouldn't be null; check caller");
+ Contract.Requires(name != null, "name shouldn't be null; check caller");
+
+ StringBuilder sb = new StringBuilder();
+ if (_mediator.LocationInfo != null)
+ {
+ String nameSpace = _mediator.LocationInfo.Namespace;
+ if (nameSpace != null)
+ {
+ sb.Append(nameSpace);
+ if (name != null)
+ sb.Append(Type.Delimiter);
+ }
+ }
+ sb.Append(name);
+
+ String givenName = sb.ToString();
+ CompareInfo comparer = CultureInfo.InvariantCulture.CompareInfo;
+ String canonicalName = null;
+ foreach (String existingName in satellite.GetManifestResourceNames())
+ {
+ if (comparer.Compare(existingName, givenName, CompareOptions.IgnoreCase) == 0)
+ {
+ if (canonicalName == null)
+ {
+ canonicalName = existingName;
+ }
+ else
+ {
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_MultipleBlobs", givenName, satellite.ToString()));
+ }
+ }
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ if (canonicalName != null)
+ {
+ FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupSucceeded(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName);
+ }
+ else
+ {
+ FrameworkEventSource.Log.ResourceManagerCaseInsensitiveResourceStreamLookupFailed(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), givenName);
+ }
+ }
+#endif
+
+ if (canonicalName == null)
+ {
+ return null;
+ }
+ // If we're looking in the main assembly AND if the main
+ // assembly was the person who created the ResourceManager,
+ // skip a security check for private manifest resources.
+ bool canSkipSecurityCheck = _mediator.MainAssembly == satellite && _mediator.CallingAssembly == _mediator.MainAssembly;
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Stream s = satellite.GetManifestResourceStream(canonicalName, ref stackMark, canSkipSecurityCheck);
+ // GetManifestResourceStream will return null if we don't have
+ // permission to read this stream from the assembly. For example,
+ // if the stream is private and we're trying to access it from another
+ // assembly (ie, ResMgr in mscorlib accessing anything else), we
+ // require Reflection TypeInformation permission to be able to read
+ // this.
+#if !FEATURE_CORECLR
+ if (s!=null) {
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerManifestResourceAccessDenied(_mediator.BaseName, _mediator.MainAssembly, satellite.GetSimpleName(), canonicalName);
+ }
+ }
+#endif
+ return s;
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ private RuntimeAssembly GetSatelliteAssembly(CultureInfo lookForCulture, ref StackCrawlMark stackMark)
+ {
+ if (!_mediator.LookedForSatelliteContractVersion)
+ {
+ _mediator.SatelliteContractVersion = _mediator.ObtainSatelliteContractVersion(_mediator.MainAssembly);
+ _mediator.LookedForSatelliteContractVersion = true;
+ }
+
+ RuntimeAssembly satellite = null;
+ String satAssemblyName = GetSatelliteAssemblyName();
+
+ // Look up the satellite assembly, but don't let problems
+ // like a partially signed satellite assembly stop us from
+ // doing fallback and displaying something to the user.
+ // Yet also somehow log this error for a developer.
+ try
+ {
+ satellite = _mediator.MainAssembly.InternalGetSatelliteAssembly(satAssemblyName, lookForCulture, _mediator.SatelliteContractVersion, false, ref stackMark);
+ }
+
+ // Jun 08: for cases other than ACCESS_DENIED, we'll assert instead of throw to give release builds more opportunity to fallback.
+
+ catch (FileLoadException fle)
+ {
+ // Ignore cases where the loader gets an access
+ // denied back from the OS. This showed up for
+ // href-run exe's at one point.
+ int hr = fle._HResult;
+ if (hr != Win32Native.MakeHRFromErrorCode(Win32Native.ERROR_ACCESS_DENIED))
+ {
+ Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + " with error code 0x" + hr.ToString("X", CultureInfo.InvariantCulture) + Environment.NewLine + "Exception: " + fle);
+ }
+ }
+
+ // Don't throw for zero-length satellite assemblies, for compat with v1
+ catch (BadImageFormatException bife)
+ {
+ Contract.Assert(false, "[This assert catches satellite assembly build/deployment problems - report this message to your build lab & loc engineer]" + Environment.NewLine + "GetSatelliteAssembly failed for culture " + lookForCulture.Name + " and version " + (_mediator.SatelliteContractVersion == null ? _mediator.MainAssembly.GetVersion().ToString() : _mediator.SatelliteContractVersion.ToString()) + " of assembly " + _mediator.MainAssembly.GetSimpleName() + Environment.NewLine + "Exception: " + bife);
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ if (satellite != null)
+ {
+ FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblySucceeded(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName);
+ }
+ else
+ {
+ FrameworkEventSource.Log.ResourceManagerGetSatelliteAssemblyFailed(_mediator.BaseName, _mediator.MainAssembly, lookForCulture.Name, satAssemblyName);
+ }
+ }
+#endif
+
+ return satellite;
+ }
+
+ // Perf optimization - Don't use Reflection for most cases with
+ // our .resources files. This makes our code run faster and we can
+ // creating a ResourceReader via Reflection. This would incur
+ // a security check (since the link-time check on the constructor that
+ // takes a String is turned into a full demand with a stack walk)
+ // and causes partially trusted localized apps to fail.
+ private bool CanUseDefaultResourceClasses(String readerTypeName, String resSetTypeName)
+ {
+ Contract.Assert(readerTypeName != null, "readerTypeName shouldn't be null; check caller");
+ Contract.Assert(resSetTypeName != null, "resSetTypeName shouldn't be null; check caller");
+
+ if (_mediator.UserResourceSet != null)
+ return false;
+
+ // Ignore the actual version of the ResourceReader and
+ // RuntimeResourceSet classes. Let those classes deal with
+ // versioning themselves.
+ AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
+
+ if (readerTypeName != null)
+ {
+ if (!ResourceManager.CompareNames(readerTypeName, ResourceManager.ResReaderTypeName, mscorlib))
+ return false;
+ }
+
+ if (resSetTypeName != null)
+ {
+ if (!ResourceManager.CompareNames(resSetTypeName, ResourceManager.ResSetTypeName, mscorlib))
+ return false;
+ }
+
+ return true;
+ }
+
+ [System.Security.SecurityCritical]
+ private String GetSatelliteAssemblyName()
+ {
+ String satAssemblyName = _mediator.MainAssembly.GetSimpleName();
+ satAssemblyName += ".resources";
+ return satAssemblyName;
+ }
+
+ [System.Security.SecurityCritical]
+ private void HandleSatelliteMissing()
+ {
+ String satAssemName = _mediator.MainAssembly.GetSimpleName() + ".resources.dll";
+ if (_mediator.SatelliteContractVersion != null)
+ {
+ satAssemName += ", Version=" + _mediator.SatelliteContractVersion.ToString();
+ }
+
+ AssemblyName an = new AssemblyName();
+ an.SetPublicKey(_mediator.MainAssembly.GetPublicKey());
+ byte[] token = an.GetPublicKeyToken();
+
+ int iLen = token.Length;
+ StringBuilder publicKeyTok = new StringBuilder(iLen * 2);
+ for (int i = 0; i < iLen; i++)
+ {
+ publicKeyTok.Append(token[i].ToString("x", CultureInfo.InvariantCulture));
+ }
+ satAssemName += ", PublicKeyToken=" + publicKeyTok;
+
+ String missingCultureName = _mediator.NeutralResourcesCulture.Name;
+ if (missingCultureName.Length == 0)
+ {
+ missingCultureName = "<invariant>";
+ }
+ throw new MissingSatelliteAssemblyException(Environment.GetResourceString("MissingSatelliteAssembly_Culture_Name", _mediator.NeutralResourcesCulture, satAssemName), missingCultureName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void HandleResourceStreamMissing(String fileName)
+ {
+ // Keep people from bothering me about resources problems
+ if (_mediator.MainAssembly == typeof(Object).Assembly && _mediator.BaseName.Equals(System.CoreLib.Name))
+ {
+ // This would break CultureInfo & all our exceptions.
+ Contract.Assert(false, "Couldn't get " + System.CoreLib.Name+ResourceManager.ResFileExtension + " from "+System.CoreLib.Name+"'s assembly" + Environment.NewLine + Environment.NewLine + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug.");
+
+ // We cannot continue further - simply FailFast.
+ string mesgFailFast = System.CoreLib.Name + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!";
+ System.Environment.FailFast(mesgFailFast);
+ }
+ // We really don't think this should happen - we always
+ // expect the neutral locale's resources to be present.
+ String resName = String.Empty;
+ if (_mediator.LocationInfo != null && _mediator.LocationInfo.Namespace != null)
+ resName = _mediator.LocationInfo.Namespace + Type.Delimiter;
+ resName += fileName;
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoNeutralAsm", resName, _mediator.MainAssembly.GetSimpleName()));
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [System.Security.SecurityCritical] // Our security team doesn't yet allow safe-critical P/Invoke methods.
+ [System.Security.SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool GetNeutralResourcesLanguageAttribute(RuntimeAssembly assemblyHandle, StringHandleOnStack cultureName, out short fallbackLocation);
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/MissingManifestResourceException.cs b/src/mscorlib/src/System/Resources/MissingManifestResourceException.cs
new file mode 100644
index 0000000000..e616bfe68b
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/MissingManifestResourceException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception for a missing assembly-level resource
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.Resources {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class MissingManifestResourceException : SystemException
+ {
+ public MissingManifestResourceException()
+ : base(Environment.GetResourceString("Arg_MissingManifestResourceException")) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGMANIFESTRESOURCE);
+ }
+
+ public MissingManifestResourceException(String message)
+ : base(message) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGMANIFESTRESOURCE);
+ }
+
+ public MissingManifestResourceException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGMANIFESTRESOURCE);
+ }
+
+ protected MissingManifestResourceException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/MissingSatelliteAssemblyException.cs b/src/mscorlib/src/System/Resources/MissingSatelliteAssemblyException.cs
new file mode 100644
index 0000000000..3d59f856b1
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/MissingSatelliteAssemblyException.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Exception for a missing satellite assembly needed
+** for ultimate resource fallback. This usually
+** indicates a setup and/or deployment problem.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System.Resources {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class MissingSatelliteAssemblyException : SystemException
+ {
+ private String _cultureName;
+
+ public MissingSatelliteAssemblyException()
+ : base(Environment.GetResourceString("MissingSatelliteAssembly_Default")) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY);
+ }
+
+ public MissingSatelliteAssemblyException(String message)
+ : base(message) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY);
+ }
+
+ public MissingSatelliteAssemblyException(String message, String cultureName)
+ : base(message) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY);
+ _cultureName = cultureName;
+ }
+
+ public MissingSatelliteAssemblyException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(System.__HResults.COR_E_MISSINGSATELLITEASSEMBLY);
+ }
+
+ protected MissingSatelliteAssemblyException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+
+ public String CultureName {
+ get { return _cultureName; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs b/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs
new file mode 100644
index 0000000000..560cd5faa9
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/NeutralResourcesLanguageAttribute.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Tells the ResourceManager what language your main
+** assembly's resources are written in. The
+** ResourceManager won't try loading a satellite
+** assembly for that culture, which helps perf.
+**
+**
+** NOTE:
+**
+** This custom attribute is no longer implemented in managed code. As part of a perf optimization,
+** it is now read in Module::GetNeutralResourcesLanguage, accessed from ManifestBasedResourceGroveler
+** through an internal runtime call.
+===========================================================*/
+
+namespace System.Resources {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class NeutralResourcesLanguageAttribute : Attribute
+ {
+ private String _culture;
+ private UltimateResourceFallbackLocation _fallbackLoc;
+
+ public NeutralResourcesLanguageAttribute(String cultureName)
+ {
+ if (cultureName == null)
+ throw new ArgumentNullException("cultureName");
+ Contract.EndContractBlock();
+
+ _culture = cultureName;
+ _fallbackLoc = UltimateResourceFallbackLocation.MainAssembly;
+ }
+
+ public NeutralResourcesLanguageAttribute(String cultureName, UltimateResourceFallbackLocation location)
+ {
+ if (cultureName == null)
+ throw new ArgumentNullException("cultureName");
+ if (!Enum.IsDefined(typeof(UltimateResourceFallbackLocation), location))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidNeutralResourcesLanguage_FallbackLoc", location));
+ Contract.EndContractBlock();
+
+ _culture = cultureName;
+ _fallbackLoc = location;
+ }
+
+ public String CultureName {
+ get { return _culture; }
+ }
+
+ public UltimateResourceFallbackLocation Location {
+ get { return _fallbackLoc; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs
new file mode 100644
index 0000000000..def7836e05
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ResourceFallbackManager.cs
@@ -0,0 +1,278 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Encapsulates CultureInfo fallback for resource
+** lookup
+**
+**
+===========================================================*/
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+#if FEATURE_CORECLR
+using System.Diagnostics.Contracts;
+#endif
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+
+namespace System.Resources
+{
+ internal class ResourceFallbackManager : IEnumerable<CultureInfo>
+ {
+ private CultureInfo m_startingCulture;
+ private CultureInfo m_neutralResourcesCulture;
+ private bool m_useParents;
+
+// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
+#if FEATURE_CORECLR
+ // This is a cache of the thread, process, user, and OS-preferred fallback cultures.
+ // However, each thread may have a different value, and these may change during the
+ // lifetime of the process. So this cache must be verified each time we use it.
+ // Hence, we'll keep an array of strings for culture names & check it each time,
+ // but we'll really cache an array of CultureInfo's. Using thread-local statics
+ // as well to avoid differences across threads.
+ [ThreadStatic]
+ private static CultureInfo[] cachedOsFallbackArray;
+#endif // FEATURE_CORECLR
+
+ internal ResourceFallbackManager(CultureInfo startingCulture, CultureInfo neutralResourcesCulture, bool useParents)
+ {
+ if (startingCulture != null)
+ {
+ m_startingCulture = startingCulture;
+ }
+ else
+ {
+ m_startingCulture = CultureInfo.CurrentUICulture;
+ }
+
+ m_neutralResourcesCulture = neutralResourcesCulture;
+ m_useParents = useParents;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ // WARING: This function must be kept in sync with ResourceManager.GetFirstResourceSet()
+ public IEnumerator<CultureInfo> GetEnumerator()
+ {
+ bool reachedNeutralResourcesCulture = false;
+
+ // 1. starting culture chain, up to neutral
+ CultureInfo currentCulture = m_startingCulture;
+ do
+ {
+ if (m_neutralResourcesCulture != null && currentCulture.Name == m_neutralResourcesCulture.Name)
+ {
+ // Return the invariant culture all the time, even if the UltimateResourceFallbackLocation
+ // is a satellite assembly. This is fixed up later in ManifestBasedResourceGroveler::UltimateFallbackFixup.
+ yield return CultureInfo.InvariantCulture;
+ reachedNeutralResourcesCulture = true;
+ break;
+ }
+ yield return currentCulture;
+ currentCulture = currentCulture.Parent;
+ } while (m_useParents && !currentCulture.HasInvariantCultureName);
+
+ if (!m_useParents || m_startingCulture.HasInvariantCultureName)
+ {
+ yield break;
+ }
+
+// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
+#if FEATURE_CORECLR
+ // 2. user preferred cultures, omitting starting culture if tried already
+ // Compat note: For console apps, this API will return cultures like Arabic
+ // or Hebrew that are displayed right-to-left. These don't work with today's
+ // CMD.exe. Since not all apps can short-circuit RTL languages to look at
+ // US English resources, we're exposing an appcompat flag for this, to make the
+ // osFallbackArray an empty array, mimicing our V2 behavior. Apps should instead
+ // be using CultureInfo.GetConsoleFallbackUICulture, and then test whether that
+ // culture's code page can be displayed on the console, and if not, they should
+ // set their culture to their neutral resources language.
+ // Note: the app compat switch will omit the OS Preferred fallback culture.
+ // Compat note 2: This feature breaks certain apps dependent on fallback to neutral
+ // resources. See extensive note in GetResourceFallbackArray.
+ CultureInfo[] osFallbackArray = LoadPreferredCultures();
+ if (osFallbackArray != null)
+ {
+ foreach (CultureInfo ci in osFallbackArray)
+ {
+ // only have to check starting culture and immediate parent for now.
+ // in Dev10, revisit this policy.
+ if (m_startingCulture.Name != ci.Name && m_startingCulture.Parent.Name != ci.Name)
+ {
+ yield return ci;
+ }
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ // 3. invariant
+ // Don't return invariant twice though.
+ if (reachedNeutralResourcesCulture)
+ yield break;
+
+ yield return CultureInfo.InvariantCulture;
+ }
+
+// Added but disabled from desktop in .NET 4.0, stayed disabled in .NET 4.5
+#if FEATURE_CORECLR
+ private static CultureInfo[] LoadPreferredCultures()
+ {
+ // The list of preferred cultures includes thread, process, user, and OS
+ // information and may theoretically change every time we call it.
+ // The caching does save us some allocations - this complexity saved about
+ // 7% of the wall clock time on a US English machine, and may save more on non-English
+ // boxes (since the fallback list may be longer).
+ String[] cultureNames = GetResourceFallbackArray();
+ if (cultureNames == null)
+ return null;
+
+ bool useCachedNames = (cachedOsFallbackArray != null && cultureNames.Length == cachedOsFallbackArray.Length);
+ if (useCachedNames)
+ {
+ for (int i = 0; i < cultureNames.Length; i++)
+ {
+ if (!String.Equals(cultureNames[i], cachedOsFallbackArray[i].Name))
+ {
+ useCachedNames = false;
+ break;
+ }
+ }
+ }
+ if (useCachedNames)
+ return cachedOsFallbackArray;
+
+ cachedOsFallbackArray = LoadCulturesFromNames(cultureNames);
+ return cachedOsFallbackArray;
+ }
+
+ private static CultureInfo[] LoadCulturesFromNames(String[] cultureNames)
+ {
+ if (cultureNames == null)
+ return null;
+
+ CultureInfo[] cultures = new CultureInfo[cultureNames.Length];
+ int culturesIndex = 0;
+ for (int i = 0; i < cultureNames.Length; i++)
+ {
+ // get cached, read-only cultures to avoid excess allocations
+ cultures[culturesIndex] = CultureInfo.GetCultureInfo(cultureNames[i]);
+ // Note GetCultureInfo can return null for a culture name that we don't support on the current OS.
+ // Don't leave a null in the middle of the array.
+ if (!Object.ReferenceEquals(cultures[culturesIndex], null))
+ culturesIndex++;
+ }
+
+ // If we couldn't create a culture, return an array of the right length.
+ if (culturesIndex != cultureNames.Length)
+ {
+ CultureInfo[] ret = new CultureInfo[culturesIndex];
+ Array.Copy(cultures, ret, culturesIndex);
+ cultures = ret;
+ }
+
+ return cultures;
+ }
+
+
+ // Note: May return null.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static String[] GetResourceFallbackArray()
+ {
+ // AppCompat note: We've added this feature for desktop V4 but we ripped it out
+ // before shipping V4. It shipped in SL 2 and SL 3. We preserved this behavior in SL 4
+ // for compat with previous Silverlight releases. We considered re-introducing this in .NET
+ // 4.5 for Windows 8 but chose not to because the Windows 8 immersive resources model
+ // has been redesigned from the ground up and we chose to support it (for portable libraries
+ // only) instead of further enhancing support for the classic resources model.
+ // ---------------------------------------------------------------------
+ //
+ // We have an appcompat problem that prevents us from adopting the ideal MUI model for
+ // culture fallback. Up until .NET Framework v4, our fallback was this:
+ //
+ // CurrentUICulture & parents Neutral
+ //
+ // We also had applications that took a dependency on falling back to neutral resources.
+ // IE, say an app is developed by US English developers - they may include English resources
+ // in the main assembly, not ship an "en" satellite assembly, and ship a French satellite.
+ // They may also omit the NeutralResourcesLanguageAttribute.
+ //
+ // Starting with Silverlight v2 and following advice from the MUI team, we wanted to call
+ // the OS's GetThreadPreferredUILanguages, inserting the results like this:
+ //
+ // CurrentUICulture & parents user-preferred fallback OS-preferred fallback Neutral
+ //
+ // This does not fit well for two reasons:
+ // 1) There is no concept of neutral resources in MUI
+ // 2) The user-preferred culture fallbacks make no sense in servers & non-interactive apps
+ // This leads to bad results on certain combinations of OS language installations, user
+ // settings, and applications built in certain styles. The OS-preferred fallback should
+ // be last, and the user-preferred fallback just breaks certain apps no matter where you put it.
+ //
+ // Necessary and sufficient conditions for an AppCompat bug (if we respected user & OS fallbacks):
+ // 1) A French OS (ie, you walk into an Internet café in Paris)
+ // 2) A .NET application whose neutral resources are authored in English.
+ // 3) The application did not provide an English satellite assembly (a common pattern).
+ // 4) The application is localized to French.
+ // 5) The user wants to read English, expressed in either of two ways:
+ // a. Changing Windows’ Display Language in the Regional Options Control Panel
+ // b. The application explicitly ASKS THE USER what language to display.
+ //
+ // Obviously the exact languages above can be interchanged a bit - I’m keeping this concrete.
+ // Also the NeutralResourcesLanguageAttribute will allow this to work, but usually we set it
+ // to en-US for our assemblies, meaning all other English cultures are broken.
+ //
+ // Workarounds:
+ // *) Use the NeutralResourcesLanguageAttribute and tell us that your neutral resources
+ // are in region-neutral English (en).
+ // *) Consider shipping a region-neutral English satellite assembly.
+
+ // Future work:
+ // 2) Consider a mechanism for individual assemblies to opt into wanting user-preferred fallback.
+ // They should ship their neutral resources in a satellite assembly, or use the
+ // NeutralResourcesLanguageAttribute to say their neutral resources are in a REGION-NEUTRAL
+ // language. An appdomain or process-wide flag may not be sufficient.
+ // 3) Ask Windows to clarify the scenario for the OS preferred fallback list, to decide whether
+ // we should probe there before or after looking at the neutral resources. If we move it
+ // to after the neutral resources, ask Windows to return a user-preferred fallback list
+ // without the OS preferred fallback included. This is a feature request for
+ // GetThreadPreferredUILanguages. We can muddle through without it by removing the OS
+ // preferred fallback cultures from end of the combined user + OS preferred fallback list, carefully.
+ // 4) Do not look at user-preferred fallback if Environment.UserInteractive is false. (IE,
+ // the Windows user who launches ASP.NET shouldn't determine how a web page gets
+ // localized - the server itself must respect the remote client's requested languages.)
+ // 6) Figure out what should happen in servers (ASP.NET, SQL, NT Services, etc).
+ //
+ // Done:
+ // 1) Got data from Windows on priority of supporting OS preferred fallback. We need to do it.
+ // Helps with consistency w/ Windows, and may be necessary for a long tail of other languages
+ // (ie, Windows has various degrees of localization support for ~135 languages, and fallbacks
+ // to certain languages is important.)
+ // 5) Revisited guidance for using the NeutralResourcesLanguageAttribute. Our docs should now say
+ // always pick a region-neutral language (ie, "en").
+
+// TODO (matell): I think we actually want to pull this into the PAL on CultureInfo?
+#if FEATURE_COREFX_GLOBALIZATION
+ return null;
+#else
+ return CultureInfo.nativeGetResourceFallbackArray();
+#endif
+ }
+
+#endif // FEATURE_CORECLR
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/ResourceManager.cs b/src/mscorlib/src/System/Resources/ResourceManager.cs
new file mode 100644
index 0000000000..b088e7f492
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ResourceManager.cs
@@ -0,0 +1,1679 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Default way to access String and Object resources
+** from an assembly.
+**
+**
+===========================================================*/
+
+namespace System.Resources {
+ using System;
+ using System.IO;
+ using System.Globalization;
+ using System.Collections;
+ using System.Text;
+ using System.Reflection;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using Microsoft.Win32;
+ using System.Collections.Generic;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_CORECLR
+ using System.Diagnostics.Tracing;
+#endif
+
+#if FEATURE_APPX
+ //
+ // This is implemented in System.Runtime.WindowsRuntime as function System.Resources.WindowsRuntimeResourceManager,
+ // allowing us to ask for a WinRT-specific ResourceManager.
+ // It is important to have WindowsRuntimeResourceManagerBase as regular class with virtual methods and default implementations.
+ // Defining WindowsRuntimeResourceManagerBase as abstract class or interface will cause issues when adding more methods to it
+ // because it’ll create dependency between mscorlib and System.Runtime.WindowsRuntime which will require always shipping both DLLs together.
+ // Also using interface or abstract class will not play nice with FriendAccessAllowed.
+ //
+ [FriendAccessAllowed]
+ [SecurityCritical]
+ internal class WindowsRuntimeResourceManagerBase
+ {
+ [SecurityCritical]
+ public virtual bool Initialize(string libpath, string reswFilename, out PRIExceptionInfo exceptionInfo){exceptionInfo = null; return false;}
+
+ [SecurityCritical]
+ public virtual String GetString(String stringName, String startingCulture, String neutralResourcesCulture){return null;}
+
+ public virtual CultureInfo GlobalResourceContextBestFitCultureInfo {
+ [SecurityCritical]
+ get { return null; }
+ }
+
+ [SecurityCritical]
+ public virtual bool SetGlobalResourceContextDefaultCulture(CultureInfo ci) { return false; }
+ }
+
+ [FriendAccessAllowed]
+ internal class PRIExceptionInfo
+ {
+ public string _PackageSimpleName;
+ public string _ResWFile;
+ }
+#endif // FEATURE_APPX
+
+ // Resource Manager exposes an assembly's resources to an application for
+ // the correct CultureInfo. An example would be localizing text for a
+ // user-visible message. Create a set of resource files listing a name
+ // for a message and its value, compile them using ResGen, put them in
+ // an appropriate place (your assembly manifest(?)), then create a Resource
+ // Manager and query for the name of the message you want. The Resource
+ // Manager will use CultureInfo.GetCurrentUICulture() to look
+ // up a resource for your user's locale settings.
+ //
+ // Users should ideally create a resource file for every culture, or
+ // at least a meaningful subset. The filenames will follow the naming
+ // scheme:
+ //
+ // basename.culture name.resources
+ //
+ // The base name can be the name of your application, or depending on
+ // the granularity desired, possibly the name of each class. The culture
+ // name is determined from CultureInfo's Name property.
+ // An example file name may be MyApp.en-US.resources for
+ // MyApp's US English resources.
+ //
+ // -----------------
+ // Refactoring Notes
+ // -----------------
+ // In Feb 08, began first step of refactoring ResourceManager to improve
+ // maintainability (sd changelist 3012100). This resulted in breaking
+ // apart the InternalGetResourceSet "big loop" so that the file-based
+ // and manifest-based lookup was located in separate methods.
+ // In Apr 08, continued refactoring so that file-based and manifest-based
+ // concerns are encapsulated by separate classes. At construction, the
+ // ResourceManager creates one of these classes based on whether the
+ // RM will need to use file-based or manifest-based resources, and
+ // afterwards refers to this through the interface IResourceGroveler.
+ //
+ // Serialization Compat: Ideally, we could have refactored further but
+ // this would have broken serialization compat. For example, the
+ // ResourceManager member UseManifest and UseSatelliteAssem are no
+ // longer relevant on ResourceManager. Similarly, other members could
+ // ideally be moved to the file-based or manifest-based classes
+ // because they are only relevant for those types of lookup.
+ //
+ // Solution now / in the future:
+ // For now, we simply use a mediator class so that we can keep these
+ // members on ResourceManager but allow the file-based and manifest-
+ // based classes to access/set these members in a uniform way. See
+ // ResourceManagerMediator.
+ // We encapsulate fallback logic in a fallback iterator class, so that
+ // this logic isn't duplicated in several methods.
+ //
+ // In the future, we can look into either breaking serialization if we
+ // decide this doesn't make sense for ResourceManager (i.e. how common
+ // is the scenario), manually make serialization work by providing
+ // appropriate OnSerialization, Deserialization methods. We can also
+ // look into further factoring and better design of IResourceGroveler
+ // interface to accommodate unused parameters that don't make sense
+ // for either file-based or manifest-based lookup paths.
+ //
+ // Benefits of this refactoring:
+ // - Makes it possible to understand what the ResourceManager does,
+ // which is key for maintainability.
+ // - Makes the ResourceManager more extensible by identifying and
+ // encapsulating what varies
+ // - Unearthed a bug that's been lurking a while in file-based
+ // lookup paths for InternalGetResourceSet if createIfNotExists is
+ // false.
+ // - Reuses logic, e.g. by breaking apart the culture fallback into
+ // the fallback iterator class, we don't have to repeat the
+ // sometimes confusing fallback logic across multiple methods
+ // - Fxcop violations reduced to 1/5th of original count. Most
+ // importantly, code complexity violations disappeared.
+ // - Finally, it got rid of dead code paths. Because the big loop was
+ // so confusing, it masked unused chunks of code. Also, dividing
+ // between file-based and manifest-based allowed functionaliy
+ // unused in silverlight to fall out.
+ //
+ // Note: this type is integral to the construction of exception objects,
+ // and sometimes this has to be done in low memory situtations (OOM) or
+ // to create TypeInitializationExceptions due to failure of a static class
+ // constructor. This type needs to be extremely careful and assume that
+ // any type it references may have previously failed to construct, so statics
+ // belonging to that type may not be initialized. FrameworkEventSource.Log
+ // is one such example.
+ //
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ResourceManager
+ {
+
+ internal class CultureNameResourceSetPair {
+ public String lastCultureName;
+ public ResourceSet lastResourceSet;
+ }
+
+ protected String BaseNameField;
+ // Sets is a many-to-one table of CultureInfos mapped to ResourceSets.
+ // Don't synchronize ResourceSets - too fine-grained a lock to be effective
+ [Obsolete("call InternalGetResourceSet instead")]
+ protected Hashtable ResourceSets;
+
+
+ // don't serialize the cache of ResourceSets
+ [NonSerialized]
+ private Dictionary <String,ResourceSet> _resourceSets;
+ private String moduleDir; // For assembly-ignorant directory location
+ protected Assembly MainAssembly; // Need the assembly manifest sometimes.
+ private Type _locationInfo; // For Assembly or type-based directory layout
+ private Type _userResourceSet; // Which ResourceSet instance to create
+ private CultureInfo _neutralResourcesCulture; // For perf optimizations.
+
+ [NonSerialized]
+ private CultureNameResourceSetPair _lastUsedResourceCache;
+
+ private bool _ignoreCase; // Whether case matters in GetString & GetObject
+
+ private bool UseManifest; // Use Assembly manifest, or grovel disk.
+
+ // unused! But need to keep for serialization
+ [OptionalField(VersionAdded = 1)]
+ private bool UseSatelliteAssem; // Are all the .resources files in the
+ // main assembly, or in satellite assemblies for each culture?
+#if RESOURCE_SATELLITE_CONFIG
+ private static volatile Hashtable _installedSatelliteInfo; // Give the user the option
+ // to prevent certain satellite assembly probes via a config file.
+ // Note that config files are per-appdomain, not per-assembly nor process
+ private static volatile bool _checkedConfigFile; // Did we read the app's config file?
+#endif
+
+ // Whether to fall back to the main assembly or a particular
+ // satellite for the neutral resources.
+ [OptionalField]
+ private UltimateResourceFallbackLocation _fallbackLoc;
+ // Version number of satellite assemblies to look for. May be null.
+ [OptionalField]
+ private Version _satelliteContractVersion;
+ [OptionalField]
+ private bool _lookedForSatelliteContractVersion;
+
+ // unused! But need to keep for serialization
+ [OptionalField(VersionAdded = 1)]
+ private Assembly _callingAssembly; // Assembly who created the ResMgr.
+
+ // replaces _callingAssembly
+ [OptionalField(VersionAdded = 4)]
+ private RuntimeAssembly m_callingAssembly; // Assembly who created the ResMgr.
+
+ // no need to serialize this; just create a new one on deserialization
+ [NonSerialized]
+ private IResourceGroveler resourceGroveler;
+
+ public static readonly int MagicNumber = unchecked((int)0xBEEFCACE); // If only hex had a K...
+
+ // Version number so ResMgr can get the ideal set of classes for you.
+ // ResMgr header is:
+ // 1) MagicNumber (little endian Int32)
+ // 2) HeaderVersionNumber (little endian Int32)
+ // 3) Num Bytes to skip past ResMgr header (little endian Int32)
+ // 4) IResourceReader type name for this file (bytelength-prefixed UTF-8 String)
+ // 5) ResourceSet type name for this file (bytelength-prefixed UTF8 String)
+ public static readonly int HeaderVersionNumber = 1;
+
+ //
+ //It would be better if we could use _neutralCulture instead of calling
+ //CultureInfo.InvariantCulture everywhere, but we run into problems with the .cctor. CultureInfo
+ //initializes assembly, which initializes ResourceManager, which tries to get a CultureInfo which isn't
+ //there yet because CultureInfo's class initializer hasn't finished. If we move SystemResMgr off of
+ //Assembly (or at least make it an internal property) we should be able to circumvent this problem.
+ //
+ // private static CultureInfo _neutralCulture = null;
+
+ // This is our min required ResourceSet type.
+ private static readonly Type _minResourceSet = typeof(ResourceSet);
+ // These Strings are used to avoid using Reflection in CreateResourceSet.
+ // The first set are used by ResourceWriter. The second are used by
+ // InternalResGen.
+ internal static readonly String ResReaderTypeName = typeof(ResourceReader).FullName;
+ internal static readonly String ResSetTypeName = typeof(RuntimeResourceSet).FullName;
+ internal static readonly String MscorlibName = typeof(ResourceReader).Assembly.FullName;
+ internal const String ResFileExtension = ".resources";
+ internal const int ResFileExtensionLength = 10;
+
+ // My private debugging aid. Set to 5 or 6 for verbose output. Set to 3
+ // for summary level information.
+ internal static readonly int DEBUG = 0; //Making this const causes C# to consider all of the code that it guards unreachable.
+
+ private static volatile bool s_IsAppXModel;
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private void Init()
+ {
+ m_callingAssembly = (RuntimeAssembly)Assembly.GetCallingAssembly();
+ }
+
+ protected ResourceManager()
+ {
+#if !FEATURE_CORECLR
+ // This constructor is not designed to be used under AppX and is not in the Win8 profile.
+ // However designers may use them even if they are running under AppX since they are
+ // not subject to the restrictions of the Win8 profile.
+ Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode());
+#endif
+
+ Init();
+
+ _lastUsedResourceCache = new CultureNameResourceSetPair();
+ ResourceManagerMediator mediator = new ResourceManagerMediator(this);
+ resourceGroveler = new ManifestBasedResourceGroveler(mediator);
+ }
+
+ // Constructs a Resource Manager for files beginning with
+ // baseName in the directory specified by resourceDir
+ // or in the current directory. This Assembly-ignorant constructor is
+ // mostly useful for testing your own ResourceSet implementation.
+ //
+ // A good example of a baseName might be "Strings". BaseName
+ // should not end in ".resources".
+ //
+ // Note: System.Windows.Forms uses this method at design time.
+ //
+ private ResourceManager(String baseName, String resourceDir, Type usingResourceSet) {
+ if (null==baseName)
+ throw new ArgumentNullException("baseName");
+ if (null==resourceDir)
+ throw new ArgumentNullException("resourceDir");
+ Contract.EndContractBlock();
+
+#if !FEATURE_CORECLR
+ // This constructor is not designed to be used under AppX and is not in the Win8 profile.
+ // However designers may use them even if they are running under AppX since they are
+ // not subject to the restrictions of the Win8 profile.
+ Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode());
+#endif
+
+ BaseNameField = baseName;
+
+ moduleDir = resourceDir;
+ _userResourceSet = usingResourceSet;
+#pragma warning disable 618
+ ResourceSets = new Hashtable(); // for backward compatibility
+#pragma warning restore 618
+ _resourceSets = new Dictionary<String, ResourceSet>();
+ _lastUsedResourceCache = new CultureNameResourceSetPair();
+ UseManifest = false;
+
+ ResourceManagerMediator mediator = new ResourceManagerMediator(this);
+ resourceGroveler = new FileBasedResourceGroveler(mediator);
+
+#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) {
+ CultureInfo culture = CultureInfo.InvariantCulture;
+ String defaultResName = GetResourceFileName(culture);
+
+ if (resourceGroveler.HasNeutralResources(culture, defaultResName)) {
+ FrameworkEventSource.Log.ResourceManagerNeutralResourcesFound(BaseNameField, MainAssembly, defaultResName);
+ }
+ else {
+ FrameworkEventSource.Log.ResourceManagerNeutralResourcesNotFound(BaseNameField, MainAssembly, defaultResName);
+ }
+ }
+#endif
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public ResourceManager(String baseName, Assembly assembly)
+ {
+ if (null==baseName)
+ throw new ArgumentNullException("baseName");
+
+ if (null==assembly)
+ throw new ArgumentNullException("assembly");
+ Contract.EndContractBlock();
+
+ if (!(assembly is RuntimeAssembly))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
+
+ MainAssembly = assembly;
+ BaseNameField = baseName;
+
+ SetAppXConfiguration();
+
+ CommonAssemblyInit();
+
+ m_callingAssembly = (RuntimeAssembly)Assembly.GetCallingAssembly();
+ // Special case for mscorlib - protect mscorlib's private resources.
+ // This isn't for security reasons, but to ensure we can make
+ // breaking changes to mscorlib's internal resources without
+ // assuming users may have taken a dependency on them.
+ if (assembly == typeof(Object).Assembly && m_callingAssembly != assembly)
+ {
+ m_callingAssembly = null;
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ResourceManager(String baseName, Assembly assembly, Type usingResourceSet)
+ {
+ if (null==baseName)
+ throw new ArgumentNullException("baseName");
+ if (null==assembly)
+ throw new ArgumentNullException("assembly");
+ Contract.EndContractBlock();
+
+#if !FEATURE_CORECLR
+ // This constructor is not designed to be used under AppX and is not in the Win8 profile.
+ // However designers may use them even if they are running under AppX since they are
+ // not subject to the restrictions of the Win8 profile.
+ Contract.Assert(!AppDomain.IsAppXModel() || AppDomain.IsAppXDesignMode());
+#endif
+
+ if (!(assembly is RuntimeAssembly))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
+
+ MainAssembly = assembly;
+ BaseNameField = baseName;
+
+ if (usingResourceSet != null && (usingResourceSet != _minResourceSet) && !(usingResourceSet.IsSubclassOf(_minResourceSet)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_ResMgrNotResSet"), "usingResourceSet");
+ _userResourceSet = usingResourceSet;
+
+ CommonAssemblyInit();
+ m_callingAssembly = (RuntimeAssembly)Assembly.GetCallingAssembly();
+ // Special case for mscorlib - protect mscorlib's private resources.
+ // This isn't for security reasons, but to ensure we can make
+ // breaking changes to mscorlib's internal resources without
+ // assuming users may have taken a dependency on them.
+ if (assembly == typeof(Object).Assembly && m_callingAssembly != assembly)
+ m_callingAssembly = null;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public ResourceManager(Type resourceSource)
+ {
+ if (null==resourceSource)
+ throw new ArgumentNullException("resourceSource");
+ Contract.EndContractBlock();
+
+ if (!(resourceSource is RuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ _locationInfo = resourceSource;
+ MainAssembly = _locationInfo.Assembly;
+ BaseNameField = resourceSource.Name;
+
+ SetAppXConfiguration();
+
+ CommonAssemblyInit();
+
+ m_callingAssembly = (RuntimeAssembly)Assembly.GetCallingAssembly();
+ // Special case for mscorlib - protect mscorlib's private resources.
+ if (MainAssembly == typeof(Object).Assembly && m_callingAssembly != MainAssembly)
+ {
+ m_callingAssembly = null;
+ }
+ }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ this._resourceSets = null;
+ this.resourceGroveler = null;
+ this._lastUsedResourceCache = null;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ _resourceSets = new Dictionary<String, ResourceSet>();
+ _lastUsedResourceCache = new CultureNameResourceSetPair();
+ // set up resource groveler, depending on whether this ResourceManager
+ // is looking for files or assemblies
+ ResourceManagerMediator mediator = new ResourceManagerMediator(this);
+ if (UseManifest)
+ {
+ resourceGroveler = new ManifestBasedResourceGroveler(mediator);
+ }
+ else
+ {
+ resourceGroveler = new FileBasedResourceGroveler(mediator);
+ }
+
+ // correct callingAssembly for v2
+ if (this.m_callingAssembly == null)
+ {
+ this.m_callingAssembly = (RuntimeAssembly)_callingAssembly;
+ }
+
+ // v2 does this lazily
+ if (UseManifest && this._neutralResourcesCulture == null)
+ {
+ _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, ref _fallbackLoc);
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ // Initialize the fields Whidbey expects
+ _callingAssembly = m_callingAssembly;
+ UseSatelliteAssem = UseManifest;
+#pragma warning disable 618
+ ResourceSets = new Hashtable(); // for backward compatibility
+#pragma warning restore 618
+ }
+
+
+ // Trying to unify code as much as possible, even though having to do a
+ // security check in each constructor prevents it.
+ [System.Security.SecuritySafeCritical]
+ private void CommonAssemblyInit()
+ {
+ if (_bUsingModernResourceManagement == false)
+ {
+ UseManifest = true;
+
+ _resourceSets = new Dictionary<String,ResourceSet>();
+ _lastUsedResourceCache = new CultureNameResourceSetPair();
+
+ _fallbackLoc = UltimateResourceFallbackLocation.MainAssembly;
+
+ ResourceManagerMediator mediator = new ResourceManagerMediator(this);
+ resourceGroveler = new ManifestBasedResourceGroveler(mediator);
+ }
+
+ _neutralResourcesCulture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(MainAssembly, ref _fallbackLoc);
+
+#if !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile event providers for coreclr
+ if (_bUsingModernResourceManagement == false)
+ {
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) {
+ CultureInfo culture = CultureInfo.InvariantCulture;
+ String defaultResName = GetResourceFileName(culture);
+
+ if (resourceGroveler.HasNeutralResources(culture, defaultResName)) {
+ FrameworkEventSource.Log.ResourceManagerNeutralResourcesFound(BaseNameField, MainAssembly, defaultResName);
+ }
+ else {
+ String outputResName = defaultResName;
+ if (_locationInfo != null && _locationInfo.Namespace != null)
+ outputResName = _locationInfo.Namespace + Type.Delimiter + defaultResName;
+ FrameworkEventSource.Log.ResourceManagerNeutralResourcesNotFound(BaseNameField, MainAssembly, outputResName);
+ }
+ }
+
+#pragma warning disable 618
+ ResourceSets = new Hashtable(); // for backward compatibility
+#pragma warning restore 618
+ }
+#endif
+ }
+
+ // Gets the base name for the ResourceManager.
+ public virtual String BaseName {
+ get { return BaseNameField; }
+ }
+
+ // Whether we should ignore the capitalization of resources when calling
+ // GetString or GetObject.
+ public virtual bool IgnoreCase {
+ get { return _ignoreCase; }
+ set { _ignoreCase = value; }
+ }
+
+ // Returns the Type of the ResourceSet the ResourceManager uses
+ // to construct ResourceSets.
+ public virtual Type ResourceSetType {
+ get { return (_userResourceSet == null) ? typeof(RuntimeResourceSet) : _userResourceSet; }
+ }
+
+ protected UltimateResourceFallbackLocation FallbackLocation
+ {
+ get { return _fallbackLoc; }
+ set { _fallbackLoc = value; }
+ }
+
+ // Tells the ResourceManager to call Close on all ResourceSets and
+ // release all resources. This will shrink your working set by
+ // potentially a substantial amount in a running application. Any
+ // future resource lookups on this ResourceManager will be as
+ // expensive as the very first lookup, since it will need to search
+ // for files and load resources again.
+ //
+ // This may be useful in some complex threading scenarios, where
+ // creating a new ResourceManager isn't quite the correct behavior.
+ public virtual void ReleaseAllResources()
+ {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerReleasingResources(BaseNameField, MainAssembly);
+ }
+#endif
+ Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+
+ // If any calls to Close throw, at least leave ourselves in a
+ // consistent state.
+ _resourceSets = new Dictionary<String,ResourceSet>();
+ _lastUsedResourceCache = new CultureNameResourceSetPair();
+
+ lock(localResourceSets) {
+ IDictionaryEnumerator setEnum = localResourceSets.GetEnumerator();
+
+#if !FEATURE_CORECLR
+ IDictionaryEnumerator setEnum2 = null;
+#pragma warning disable 618
+ if (ResourceSets != null) {
+ setEnum2 = ResourceSets.GetEnumerator();
+ }
+ ResourceSets = new Hashtable(); // for backwards compat
+#pragma warning restore 618
+#endif
+
+ while (setEnum.MoveNext()) {
+ ((ResourceSet)setEnum.Value).Close();
+ }
+
+#if !FEATURE_CORECLR
+ if (setEnum2 != null) {
+ while (setEnum2.MoveNext()) {
+ ((ResourceSet)setEnum2.Value).Close();
+ }
+ }
+#endif
+ }
+ }
+
+ public static ResourceManager CreateFileBasedResourceManager(String baseName, String resourceDir, Type usingResourceSet)
+ {
+ return new ResourceManager(baseName, resourceDir, usingResourceSet);
+ }
+
+ // Given a CultureInfo, GetResourceFileName generates the name for
+ // the binary file for the given CultureInfo. This method uses
+ // CultureInfo's Name property as part of the file name for all cultures
+ // other than the invariant culture. This method does not touch the disk,
+ // and is used only to construct what a resource file name (suitable for
+ // passing to the ResourceReader constructor) or a manifest resource file
+ // name should look like.
+ //
+ // This method can be overriden to look for a different extension,
+ // such as ".ResX", or a completely different format for naming files.
+ protected virtual String GetResourceFileName(CultureInfo culture) {
+ StringBuilder sb = new StringBuilder(255);
+ sb.Append(BaseNameField);
+ // If this is the neutral culture, don't append culture name.
+ if (!culture.HasInvariantCultureName)
+ {
+ CultureInfo.VerifyCultureName(culture.Name, true);
+ sb.Append('.');
+ sb.Append(culture.Name);
+ }
+ sb.Append(ResFileExtension);
+ return sb.ToString();
+ }
+
+ // WARNING: This function must be kept in sync with ResourceFallbackManager.GetEnumerator()
+ // Return the first ResourceSet, based on the first culture ResourceFallbackManager would return
+ internal ResourceSet GetFirstResourceSet(CultureInfo culture)
+ {
+ // Logic from ResourceFallbackManager.GetEnumerator()
+ if (_neutralResourcesCulture != null && culture.Name == _neutralResourcesCulture.Name)
+ {
+ culture = CultureInfo.InvariantCulture;
+ }
+
+ if(_lastUsedResourceCache != null) {
+ lock (_lastUsedResourceCache) {
+ if (culture.Name == _lastUsedResourceCache.lastCultureName)
+ return _lastUsedResourceCache.lastResourceSet;
+ }
+ }
+
+ // Look in the ResourceSet table
+ Dictionary<String,ResourceSet> localResourceSets = _resourceSets;
+ ResourceSet rs = null;
+ if (localResourceSets != null)
+ {
+ lock (localResourceSets)
+ {
+ localResourceSets.TryGetValue(culture.Name, out rs);
+ }
+ }
+
+ if (rs != null)
+ {
+ // update the cache with the most recent ResourceSet
+ if (_lastUsedResourceCache != null) {
+ lock (_lastUsedResourceCache) {
+ _lastUsedResourceCache.lastCultureName = culture.Name;
+ _lastUsedResourceCache.lastResourceSet = rs;
+ }
+ }
+ return rs;
+ }
+
+ return null;
+ }
+
+ // Looks up a set of resources for a particular CultureInfo. This is
+ // not useful for most users of the ResourceManager - call
+ // GetString() or GetObject() instead.
+ //
+ // The parameters let you control whether the ResourceSet is created
+ // if it hasn't yet been loaded and if parent CultureInfos should be
+ // loaded as well for resource inheritance.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public virtual ResourceSet GetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents) {
+ if (null==culture)
+ throw new ArgumentNullException("culture");
+ Contract.EndContractBlock();
+
+ Dictionary<String,ResourceSet> localResourceSets = _resourceSets;
+ ResourceSet rs;
+ if (localResourceSets != null) {
+ lock (localResourceSets) {
+ if (localResourceSets.TryGetValue(culture.Name, out rs))
+ return rs;
+ }
+ }
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ if (UseManifest && culture.HasInvariantCultureName) {
+ string fileName = GetResourceFileName(culture);
+ RuntimeAssembly mainAssembly = (RuntimeAssembly)MainAssembly;
+ Stream stream = mainAssembly.GetManifestResourceStream(_locationInfo, fileName, m_callingAssembly == MainAssembly, ref stackMark);
+ if (createIfNotExists && stream!=null) {
+ rs = ((ManifestBasedResourceGroveler)resourceGroveler).CreateResourceSet(stream, MainAssembly);
+ AddResourceSet(localResourceSets, culture.Name, ref rs);
+ return rs;
+ }
+ }
+
+ // Note: ideally we could plumb through the stack crawl mark here, but we must
+ // call the virtual 3-argument InternalGetResourceSet method for compatibility.
+ // Security-wise, we're not overly interested in protecting access to resources,
+ // since full-trust callers can get them already and most resources are public.
+ // Also, the JIT inliner could always inline a caller into another assembly's
+ // method.
+ // So if we happen to return some resources in cases where we should really be
+ // doing a demand for member access permissions, we're not overly concerned.
+ return InternalGetResourceSet(culture, createIfNotExists, tryParents);
+ }
+
+ // InternalGetResourceSet is a non-threadsafe method where all the logic
+ // for getting a resource set lives. Access to it is controlled by
+ // threadsafe methods such as GetResourceSet, GetString, & GetObject.
+ // This will take a minimal number of locks.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ protected virtual ResourceSet InternalGetResourceSet(CultureInfo culture, bool createIfNotExists, bool tryParents)
+ {
+ Contract.Assert(culture != null, "culture != null");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return InternalGetResourceSet(culture,createIfNotExists,tryParents, ref stackMark);
+ }
+
+ // InternalGetResourceSet is a non-threadsafe method where all the logic
+ // for getting a resource set lives. Access to it is controlled by
+ // threadsafe methods such as GetResourceSet, GetString, & GetObject.
+ // This will take a minimal number of locks.
+ [System.Security.SecurityCritical]
+ private ResourceSet InternalGetResourceSet(CultureInfo requestedCulture, bool createIfNotExists, bool tryParents, ref StackCrawlMark stackMark)
+ {
+ Dictionary<String, ResourceSet> localResourceSets = _resourceSets;
+ ResourceSet rs = null;
+ CultureInfo foundCulture = null;
+ lock (localResourceSets) {
+ if (localResourceSets.TryGetValue(requestedCulture.Name, out rs)) {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized) {
+ FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCache(BaseNameField, MainAssembly, requestedCulture.Name);
+ }
+#endif
+ return rs;
+ }
+ }
+
+ ResourceFallbackManager mgr = new ResourceFallbackManager(requestedCulture, _neutralResourcesCulture, tryParents);
+
+ foreach (CultureInfo currentCultureInfo in mgr)
+ {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerLookingForResourceSet(BaseNameField, MainAssembly, currentCultureInfo.Name);
+ }
+#endif
+ lock(localResourceSets) {
+ if (localResourceSets.TryGetValue(currentCultureInfo.Name, out rs)) {
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerFoundResourceSetInCache(BaseNameField, MainAssembly, currentCultureInfo.Name);
+ }
+#endif
+ // we need to update the cache if we fellback
+ if(requestedCulture != currentCultureInfo) foundCulture = currentCultureInfo;
+ break;
+ }
+ }
+
+ // InternalGetResourceSet will never be threadsafe. However, it must
+ // be protected against reentrancy from the SAME THREAD. (ie, calling
+ // GetSatelliteAssembly may send some window messages or trigger the
+ // Assembly load event, which could fail then call back into the
+ // ResourceManager). It's happened.
+
+ rs = resourceGroveler.GrovelForResourceSet(currentCultureInfo, localResourceSets,
+ tryParents, createIfNotExists, ref stackMark);
+
+ // found a ResourceSet; we're done
+ if (rs != null)
+ {
+ foundCulture = currentCultureInfo;
+ break;
+ }
+
+ }
+
+ if (rs != null && foundCulture != null)
+ {
+ // add entries to the cache for the cultures we have gone through
+
+ // currentCultureInfo now refers to the culture that had resources.
+ // update cultures starting from requested culture up to the culture
+ // that had resources.
+ foreach (CultureInfo updateCultureInfo in mgr)
+ {
+ AddResourceSet(localResourceSets, updateCultureInfo.Name, ref rs);
+
+ // stop when we've added current or reached invariant (top of chain)
+ if (updateCultureInfo == foundCulture)
+ {
+ break;
+ }
+ }
+ }
+
+ return rs;
+ }
+
+ // Simple helper to ease maintenance and improve readability.
+ private static void AddResourceSet(Dictionary<String,ResourceSet> localResourceSets, String cultureName, ref ResourceSet rs)
+ {
+ // InternalGetResourceSet is both recursive and reentrant -
+ // assembly load callbacks in particular are a way we can call
+ // back into the ResourceManager in unexpectedly on the same thread.
+ lock(localResourceSets) {
+ // If another thread added this culture, return that.
+ ResourceSet lostRace;
+ if (localResourceSets.TryGetValue(cultureName, out lostRace)) {
+ if (!Object.ReferenceEquals(lostRace, rs)) {
+ // Note: In certain cases, we can be trying to add a ResourceSet for multiple
+ // cultures on one thread, while a second thread added another ResourceSet for one
+ // of those cultures. If there is a race condition we must make sure our ResourceSet
+ // isn't in our dictionary before closing it.
+ if (!localResourceSets.ContainsValue(rs))
+ rs.Dispose();
+ rs = lostRace;
+ }
+ }
+ else {
+ localResourceSets.Add(cultureName, rs);
+ }
+ }
+ }
+
+ protected static Version GetSatelliteContractVersion(Assembly a)
+ {
+ // Ensure that the assembly reference is not null
+ if (a == null) {
+ throw new ArgumentNullException("a", Environment.GetResourceString("ArgumentNull_Assembly"));
+ }
+ Contract.EndContractBlock();
+
+#if !FEATURE_WINDOWSPHONE
+ String v = null;
+ if (a.ReflectionOnly) {
+ foreach (CustomAttributeData data in CustomAttributeData.GetCustomAttributes(a)) {
+ if (data.Constructor.DeclaringType == typeof(SatelliteContractVersionAttribute)) {
+ v = (String)data.ConstructorArguments[0].Value;
+ break;
+ }
+ }
+
+ if (v == null)
+ return null;
+ }
+ else {
+ Object[] attrs = a.GetCustomAttributes(typeof(SatelliteContractVersionAttribute), false);
+ if (attrs.Length == 0)
+ return null;
+ Contract.Assert(attrs.Length == 1, "Cannot have multiple instances of SatelliteContractVersionAttribute on an assembly!");
+ v = ((SatelliteContractVersionAttribute)attrs[0]).Version;
+ }
+ Version ver;
+ try {
+ ver = new Version(v);
+ }
+ catch(ArgumentOutOfRangeException e) {
+ // Note we are prone to hitting infinite loops if mscorlib's
+ // SatelliteContractVersionAttribute contains bogus values.
+ // If this assert fires, please fix the build process for the
+ // BCL directory.
+ if (a == typeof(Object).Assembly) {
+ Contract.Assert(false, System.CoreLib.Name+"'s SatelliteContractVersionAttribute is a malformed version string!");
+ return null;
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidSatelliteContract_Asm_Ver", a.ToString(), v), e);
+ }
+ return ver;
+#else
+ // On the phone return null. The calling code will use the assembly version instead to avoid potential type
+ // and library loads caused by CA lookup. NetCF uses the assembly version always.
+ return null;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected static CultureInfo GetNeutralResourcesLanguage(Assembly a)
+ {
+ // This method should be obsolete - replace it with the one below.
+ // Unfortunately, we made it protected.
+ UltimateResourceFallbackLocation ignoringUsefulData = UltimateResourceFallbackLocation.MainAssembly;
+ CultureInfo culture = ManifestBasedResourceGroveler.GetNeutralResourcesLanguage(a, ref ignoringUsefulData);
+ return culture;
+ }
+
+ // IGNORES VERSION
+ internal static bool CompareNames(String asmTypeName1,
+ String typeName2,
+ AssemblyName asmName2)
+ {
+ Contract.Assert(asmTypeName1 != null, "asmTypeName1 was unexpectedly null");
+
+ // First, compare type names
+ int comma = asmTypeName1.IndexOf(',');
+ if (((comma == -1) ? asmTypeName1.Length : comma) != typeName2.Length)
+ return false;
+
+ // case sensitive
+ if (String.Compare(asmTypeName1, 0, typeName2, 0, typeName2.Length, StringComparison.Ordinal) != 0)
+ return false;
+ if (comma == -1)
+ return true;
+
+ // Now, compare assembly display names (IGNORES VERSION AND PROCESSORARCHITECTURE)
+ // also, for mscorlib ignores everything, since that's what the binder is going to do
+ while(Char.IsWhiteSpace(asmTypeName1[++comma]));
+
+ // case insensitive
+ AssemblyName an1 = new AssemblyName(asmTypeName1.Substring(comma));
+ if (String.Compare(an1.Name, asmName2.Name, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+
+ // to match IsMscorlib() in VM
+ if (String.Compare(an1.Name, System.CoreLib.Name, StringComparison.OrdinalIgnoreCase) == 0)
+ return true;
+
+
+ if ((an1.CultureInfo != null) && (asmName2.CultureInfo != null) &&
+#if FEATURE_USE_LCID
+ (an1.CultureInfo.LCID != asmName2.CultureInfo.LCID)
+#else
+ (an1.CultureInfo.Name != asmName2.CultureInfo.Name)
+#endif
+ )
+ return false;
+
+ byte[] pkt1 = an1.GetPublicKeyToken();
+ byte[] pkt2 = asmName2.GetPublicKeyToken();
+ if ((pkt1 != null) && (pkt2 != null)) {
+ if (pkt1.Length != pkt2.Length)
+ return false;
+
+ for(int i=0; i < pkt1.Length; i++) {
+ if(pkt1[i] != pkt2[i])
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+#if FEATURE_APPX
+ [SecuritySafeCritical]
+ // Throws WinRT hresults
+ private string GetStringFromPRI(String stringName, String startingCulture, String neutralResourcesCulture) {
+ Contract.Assert(_bUsingModernResourceManagement);
+ Contract.Assert(_WinRTResourceManager != null);
+ Contract.Assert(_PRIonAppXInitialized);
+ Contract.Assert(AppDomain.IsAppXModel());
+
+ if (stringName.Length == 0)
+ return null;
+
+ string resourceString = null;
+
+ // Do not handle exceptions. See the comment in SetAppXConfiguration about throwing
+ // exception types that the ResourceManager class is not documented to throw.
+ resourceString = _WinRTResourceManager.GetString(
+ stringName,
+ String.IsNullOrEmpty(startingCulture) ? null : startingCulture,
+ String.IsNullOrEmpty(neutralResourcesCulture) ? null : neutralResourcesCulture);
+
+ return resourceString;
+ }
+
+ // Since we can't directly reference System.Runtime.WindowsRuntime from mscorlib, we have to get the type via reflection.
+ // It would be better if we could just implement WindowsRuntimeResourceManager in mscorlib, but we can't, because
+ // we can do very little with WinRT in mscorlib.
+ [SecurityCritical]
+ internal static WindowsRuntimeResourceManagerBase GetWinRTResourceManager()
+ {
+ Type WinRTResourceManagerType = Type.GetType("System.Resources.WindowsRuntimeResourceManager, " + AssemblyRef.SystemRuntimeWindowsRuntime, true);
+ return (WindowsRuntimeResourceManagerBase)Activator.CreateInstance(WinRTResourceManagerType, true);
+ }
+#endif
+
+ [NonSerialized]
+ private bool _bUsingModernResourceManagement; // Written only by SetAppXConfiguration
+
+#if FEATURE_APPX
+ [NonSerialized]
+ [SecurityCritical]
+ private WindowsRuntimeResourceManagerBase _WinRTResourceManager; // Written only by SetAppXConfiguration
+
+ [NonSerialized]
+ private bool _PRIonAppXInitialized; // Written only by SetAppXConfiguration
+
+ [NonSerialized]
+ private PRIExceptionInfo _PRIExceptionInfo; // Written only by SetAppXConfiguration
+
+ // When running under AppX, the following rules apply for resource lookup:
+ //
+ // Desktop
+ // -------
+ //
+ // 1) For Framework assemblies, we always use satellite assembly based lookup.
+ // 2) For non-FX assemblies, we use modern resource manager, with the premise being that app package
+ // contains the PRI resources since such assemblies are expected to be application assemblies.
+ //
+ // CoreCLR
+ // -------
+ //
+ // 1) For Framework assemblies, we always use satellite assembly based lookup.
+ // 2) For non-FX assemblies:
+ //
+ // a) If the assembly lives under PLATFORM_RESOURCE_ROOTS (as specified by the host during AppDomain creation),
+ // then we will use satellite assembly based lookup in assemblies like *.resources.dll.
+ //
+ // b) For any other non-FX assembly, we will use the modern resource manager with the premise that app package
+ // contains the PRI resources.
+ [SecuritySafeCritical]
+ private bool ShouldUseSatelliteAssemblyResourceLookupUnderAppX(RuntimeAssembly resourcesAssembly)
+ {
+ bool fUseSatelliteAssemblyResourceLookupUnderAppX = resourcesAssembly.IsFrameworkAssembly();
+
+#if FEATURE_CORECLR
+ if (!fUseSatelliteAssemblyResourceLookupUnderAppX)
+ {
+ // Check to see if the assembly is under PLATFORM_RESOURCE_ROOTS. If it is, then we should use satellite assembly lookup for it.
+ String platformResourceRoots = (String)(AppDomain.CurrentDomain.GetData("PLATFORM_RESOURCE_ROOTS"));
+ if ((platformResourceRoots != null) && (platformResourceRoots != String.Empty))
+ {
+ string resourceAssemblyPath = resourcesAssembly.Location;
+
+ // Loop through the PLATFORM_RESOURCE_ROOTS and see if the assembly is contained in it.
+ foreach(string pathPlatformResourceRoot in platformResourceRoots.Split(Path.PathSeparator))
+ {
+ if (resourceAssemblyPath.StartsWith(pathPlatformResourceRoot, StringComparison.CurrentCultureIgnoreCase))
+ {
+ // Found the resource assembly to be present in one of the PLATFORM_RESOURCE_ROOT, so stop the enumeration loop.
+ fUseSatelliteAssemblyResourceLookupUnderAppX = true;
+ break;
+ }
+ }
+ }
+ }
+#endif // FEATURE_CORECLR
+ return fUseSatelliteAssemblyResourceLookupUnderAppX;
+
+ }
+
+ [SecuritySafeCritical]
+#endif // FEATURE_APPX
+ // Only call SetAppXConfiguration from ResourceManager constructors, and nowhere else.
+ // Throws MissingManifestResourceException and WinRT HResults
+
+ private void SetAppXConfiguration()
+ {
+ Contract.Assert(_bUsingModernResourceManagement == false); // Only this function writes to this member
+#if FEATURE_APPX
+ Contract.Assert(_WinRTResourceManager == null); // Only this function writes to this member
+ Contract.Assert(_PRIonAppXInitialized == false); // Only this function writes to this member
+ Contract.Assert(_PRIExceptionInfo == null); // Only this function writes to this member
+
+ bool bUsingSatelliteAssembliesUnderAppX = false;
+
+ RuntimeAssembly resourcesAssembly = (RuntimeAssembly)MainAssembly;
+
+ if (resourcesAssembly == null)
+ resourcesAssembly = m_callingAssembly;
+
+ if (resourcesAssembly != null)
+ {
+ if (resourcesAssembly != typeof(Object).Assembly) // We are not loading resources for mscorlib
+ {
+ // Cannot load the WindowsRuntimeResourceManager when in a compilation process, since it
+ // lives in System.Runtime.WindowsRuntime and only mscorlib may be loaded for execution.
+ if (AppDomain.IsAppXModel() && !AppDomain.IsAppXNGen)
+ {
+ s_IsAppXModel = true;
+
+ // If we have the type information from the ResourceManager(Type) constructor, we use it. Otherwise, we use BaseNameField.
+ String reswFilename = _locationInfo == null ? BaseNameField : _locationInfo.FullName;
+
+ // The only way this can happen is if a class inherited from ResourceManager and
+ // did not set the BaseNameField before calling the protected ResourceManager() constructor.
+ // For other constructors, we would already have thrown an ArgumentNullException by now.
+ // Throwing an ArgumentNullException now is not the right thing to do because technically
+ // ResourceManager() takes no arguments, and because it is not documented as throwing
+ // any exceptions. Instead, let's go through the rest of the initialization with this set to
+ // an empty string. We may in fact fail earlier for another reason, but otherwise we will
+ // throw a MissingManifestResourceException when GetString is called indicating that a
+ // resW filename called "" could not be found.
+ if (reswFilename == null)
+ reswFilename = String.Empty;
+
+ WindowsRuntimeResourceManagerBase WRRM = null;
+ bool bWRRM_Initialized = false;
+
+ if (AppDomain.IsAppXDesignMode())
+ {
+ WRRM = GetWinRTResourceManager();
+ try {
+ PRIExceptionInfo exceptionInfo; // If the exception info is filled in, we will ignore it.
+ bWRRM_Initialized = WRRM.Initialize(resourcesAssembly.Location, reswFilename, out exceptionInfo);
+ bUsingSatelliteAssembliesUnderAppX = !bWRRM_Initialized;
+ }
+ catch(Exception e)
+ {
+ bUsingSatelliteAssembliesUnderAppX = true;
+ if (e.IsTransient)
+ throw;
+ }
+ }
+
+ if (!bUsingSatelliteAssembliesUnderAppX)
+ {
+ // See AssemblyNative::IsFrameworkAssembly for details on which kinds of assemblies are considered Framework assemblies.
+ // The Modern Resource Manager is not used for such assemblies - they continue to use satellite assemblies (i.e. .resources.dll files).
+ _bUsingModernResourceManagement = !ShouldUseSatelliteAssemblyResourceLookupUnderAppX(resourcesAssembly);
+
+ if (_bUsingModernResourceManagement)
+ {
+ // Only now are we certain that we need the PRI file.
+
+ // Note that if IsAppXDesignMode is false, we haven't checked if the PRI file exists.
+ // This is by design. We will find out in the call to WindowsRuntimeResourceManager.Initialize below.
+
+ // At this point it is important NOT to set _bUsingModernResourceManagement to false
+ // if the PRI file does not exist because we are now certain we need to load PRI
+ // resources. We want to fail by throwing a MissingManifestResourceException
+ // if WindowsRuntimeResourceManager.Initialize fails to locate the PRI file. We do not
+ // want to fall back to using satellite assemblies anymore. Note that we would not throw
+ // the MissingManifestResourceException from this function, but from GetString. See the
+ // comment below on the reason for this.
+
+ if (WRRM != null && bWRRM_Initialized)
+ {
+ // Reuse the one successfully created earlier
+ _WinRTResourceManager = WRRM;
+ _PRIonAppXInitialized = true;
+ }
+ else
+ {
+ _WinRTResourceManager = GetWinRTResourceManager();
+
+ try {
+ _PRIonAppXInitialized = _WinRTResourceManager.Initialize(resourcesAssembly.Location, reswFilename, out _PRIExceptionInfo);
+
+ // Note that _PRIExceptionInfo might be null - this is OK.
+ // In that case we will just throw the generic
+ // MissingManifestResource_NoPRIresources exception.
+ // See the implementation of GetString for more details.
+ }
+ // We would like to be able to throw a MissingManifestResourceException here if PRI resources
+ // could not be loaded for a recognized reason. However, the ResourceManager constructors
+ // that call SetAppXConfiguration are not documented as throwing MissingManifestResourceException,
+ // and since they are part of the portable profile, we cannot start throwing a new exception type
+ // as that would break existing portable libraries. Hence we must save the exception information
+ // now and throw the exception on the first call to GetString.
+ catch(FileNotFoundException)
+ {
+ // We will throw MissingManifestResource_NoPRIresources from GetString
+ // when we see that _PRIonAppXInitialized is false.
+ }
+ catch(Exception e)
+ {
+ // ERROR_MRM_MAP_NOT_FOUND can be thrown by the call to ResourceManager.get_AllResourceMaps
+ // in WindowsRuntimeResourceManager.Initialize.
+ // In this case _PRIExceptionInfo is now null and we will just throw the generic
+ // MissingManifestResource_NoPRIresources exception.
+ // See the implementation of GetString for more details.
+ if (e.HResult != __HResults.ERROR_MRM_MAP_NOT_FOUND)
+ throw; // Unexpected exception code. Bubble it up to the caller.
+ }
+ // Allow all other exception types to bubble up to the caller.
+
+ // Yes, this causes us to potentially throw exception types that are not documented.
+
+ // Ultimately the tradeoff is the following:
+ // -We could ignore unknown exceptions or rethrow them as inner exceptions
+ // of exceptions that the ResourceManager class is already documented as throwing.
+ // This would allow existing portable libraries to gracefully recover if they don't care
+ // too much about the ResourceManager object they are using. However it could
+ // mask potentially fatal errors that we are not aware of, such as a disk drive failing.
+
+
+ // The alternative, which we chose, is to throw unknown exceptions. This may tear
+ // down the process if the portable library and app don't expect this exception type.
+ // On the other hand, this won't mask potentially fatal errors we don't know about.
+ }
+ }
+ }
+ }
+ }
+ }
+ // resourcesAssembly == null should not happen but it can. See the comment on Assembly.GetCallingAssembly.
+ // However for the sake of 100% backwards compatibility on Win7 and below, we must leave
+ // _bUsingModernResourceManagement as false.
+#endif // FEATURE_APPX
+ }
+
+ // Looks up a resource value for a particular name. Looks in the
+ // current thread's CultureInfo, and if not found, all parent CultureInfos.
+ // Returns null if the resource wasn't found.
+ //
+ public virtual String GetString(String name) {
+ return GetString(name, (CultureInfo)null);
+ }
+
+ // Looks up a resource value for a particular name. Looks in the
+ // specified CultureInfo, and if not found, all parent CultureInfos.
+ // Returns null if the resource wasn't found.
+ //
+ public virtual String GetString(String name, CultureInfo culture) {
+ if (null==name)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+#if FEATURE_APPX
+ if(s_IsAppXModel)
+ {
+ // If the caller explictily passed in a culture that was obtained by calling CultureInfo.CurrentUICulture,
+ // null it out, so that we re-compute it. If we use modern resource lookup, we may end up getting a "better"
+ // match, since CultureInfo objects can't represent all the different languages the AppX resource model supports.
+ // For classic resources, this causes us to ignore the languages list and instead use the older Win32 behavior,
+ // which is the design choice we've made. (See the call a little later to GetCurrentUICultureNoAppX()).
+ if(Object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
+ {
+ culture = null;
+ }
+ }
+
+ if (_bUsingModernResourceManagement)
+ {
+ if (_PRIonAppXInitialized == false)
+ {
+ // Always throw if we did not fully succeed in initializing the WinRT Resource Manager.
+
+ if (_PRIExceptionInfo != null && _PRIExceptionInfo._PackageSimpleName != null && _PRIExceptionInfo._ResWFile != null)
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_ResWFileNotLoaded", _PRIExceptionInfo._ResWFile, _PRIExceptionInfo._PackageSimpleName));
+
+ throw new MissingManifestResourceException(Environment.GetResourceString("MissingManifestResource_NoPRIresources"));
+ }
+
+ // Throws WinRT hresults.
+ return GetStringFromPRI(name,
+ culture == null ? null : culture.Name,
+ _neutralResourcesCulture.Name);
+ }
+ else
+#endif // FEATURE_APPX
+ {
+ if (null==culture) {
+ // When running inside AppX we want to ignore the languages list when trying to come up with our CurrentUICulture.
+ // This line behaves the same way as CultureInfo.CurrentUICulture would have in .NET 4
+ culture = Thread.CurrentThread.GetCurrentUICultureNoAppX();
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerLookupStarted(BaseNameField, MainAssembly, culture.Name);
+ }
+#endif
+ ResourceSet last = GetFirstResourceSet(culture);
+
+ if (last != null)
+ {
+ String value = last.GetString(name, _ignoreCase);
+ if (value != null)
+ return value;
+ }
+
+
+ // This is the CultureInfo hierarchy traversal code for resource
+ // lookups, similar but necessarily orthogonal to the ResourceSet
+ // lookup logic.
+ ResourceFallbackManager mgr = new ResourceFallbackManager(culture, _neutralResourcesCulture, true);
+ foreach (CultureInfo currentCultureInfo in mgr) {
+
+ ResourceSet rs = InternalGetResourceSet(currentCultureInfo, true, true);
+ if (rs == null)
+ break;
+
+ if (rs != last) {
+ String value = rs.GetString(name, _ignoreCase);
+ if (value != null)
+ {
+ // update last used ResourceSet
+ if (_lastUsedResourceCache != null) {
+ lock (_lastUsedResourceCache) {
+ _lastUsedResourceCache.lastCultureName = currentCultureInfo.Name;
+ _lastUsedResourceCache.lastResourceSet = rs;
+ }
+ }
+ return value;
+ }
+
+ last = rs;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerLookupFailed(BaseNameField, MainAssembly, culture.Name);
+ }
+#endif
+ }
+
+ return null;
+ }
+
+
+ // Looks up a resource value for a particular name. Looks in the
+ // current thread's CultureInfo, and if not found, all parent CultureInfos.
+ // Returns null if the resource wasn't found.
+ //
+ public virtual Object GetObject(String name) {
+ return GetObject(name, (CultureInfo)null, true);
+ }
+
+ // Looks up a resource value for a particular name. Looks in the
+ // specified CultureInfo, and if not found, all parent CultureInfos.
+ // Returns null if the resource wasn't found.
+ public virtual Object GetObject(String name, CultureInfo culture) {
+ return GetObject(name, culture, true);
+ }
+
+ private Object GetObject(String name, CultureInfo culture, bool wrapUnmanagedMemStream)
+ {
+ if (null==name)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+#if FEATURE_APPX
+ if(s_IsAppXModel)
+ {
+ // If the caller explictily passed in a culture that was obtained by calling CultureInfo.CurrentUICulture,
+ // null it out, so that we re-compute it based on the Win32 value and not the AppX language list value.
+ // (See the call a little later to GetCurrentUICultureNoAppX()).
+ if(Object.ReferenceEquals(culture, CultureInfo.CurrentUICulture))
+ {
+ culture = null;
+ }
+ }
+#endif
+
+ if (null==culture) {
+ // When running inside AppX we want to ignore the languages list when trying to come up with our CurrentUICulture.
+ // This line behaves the same way as CultureInfo.CurrentUICulture would have in .NET 4
+ culture = Thread.CurrentThread.GetCurrentUICultureNoAppX();
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerLookupStarted(BaseNameField, MainAssembly, culture.Name);
+ }
+#endif
+ ResourceSet last = GetFirstResourceSet(culture);
+ if (last != null)
+ {
+ Object value = last.GetObject(name, _ignoreCase);
+
+ if (value != null)
+ {
+ UnmanagedMemoryStream stream = value as UnmanagedMemoryStream;
+ if (stream != null && wrapUnmanagedMemStream)
+ return new UnmanagedMemoryStreamWrapper(stream);
+ else
+ return value;
+ }
+ }
+
+ // This is the CultureInfo hierarchy traversal code for resource
+ // lookups, similar but necessarily orthogonal to the ResourceSet
+ // lookup logic.
+ ResourceFallbackManager mgr = new ResourceFallbackManager(culture, _neutralResourcesCulture, true);
+
+ foreach (CultureInfo currentCultureInfo in mgr) {
+ // Note: Technically this method should be passed in a stack crawl mark that we then pass
+ // to InternalGetResourceSet for ensuring we demand permissions to read your private resources
+ // if you're reading resources from an assembly other than yourself. But, we must call our
+ // three argument overload (without the stack crawl mark) for compatibility. After
+ // consideration, we aren't worried about the security impact.
+ ResourceSet rs = InternalGetResourceSet(currentCultureInfo, true, true);
+ if (rs == null)
+ break;
+
+ if (rs != last) {
+ Object value = rs.GetObject(name, _ignoreCase);
+ if (value != null) {
+ // update the last used ResourceSet
+ if (_lastUsedResourceCache != null) {
+ lock (_lastUsedResourceCache) {
+ _lastUsedResourceCache.lastCultureName = currentCultureInfo.Name;
+ _lastUsedResourceCache.lastResourceSet = rs;
+ }
+ }
+
+ UnmanagedMemoryStream stream = value as UnmanagedMemoryStream;
+ if (stream != null && wrapUnmanagedMemStream)
+ return new UnmanagedMemoryStreamWrapper(stream);
+ else
+ return value;
+ }
+
+ last = rs;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerLookupFailed(BaseNameField, MainAssembly, culture.Name);
+ }
+#endif
+ return null;
+ }
+
+ [ComVisible(false)]
+ public UnmanagedMemoryStream GetStream(String name) {
+ return GetStream(name, (CultureInfo)null);
+ }
+
+ [ComVisible(false)]
+ public UnmanagedMemoryStream GetStream(String name, CultureInfo culture) {
+ Object obj = GetObject(name, culture, false);
+ UnmanagedMemoryStream ums = obj as UnmanagedMemoryStream;
+ if (ums == null && obj != null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotStream_Name", name));
+ return ums;
+ }
+
+#if RESOURCE_SATELLITE_CONFIG
+ // Internal helper method - gives an end user the ability to prevent
+ // satellite assembly probes for certain cultures via a config file.
+ [System.Security.SecurityCritical] // auto-generated
+ private bool TryLookingForSatellite(CultureInfo lookForCulture)
+ {
+ if (!_checkedConfigFile) {
+ lock (this) {
+ if (!_checkedConfigFile) {
+ _checkedConfigFile = true;
+ _installedSatelliteInfo = GetSatelliteAssembliesFromConfig();
+ }
+ }
+ }
+
+ if (_installedSatelliteInfo == null)
+ return true;
+
+ String[] installedSatellites = (String[]) _installedSatelliteInfo[MainAssembly.FullName];
+
+ if (installedSatellites == null)
+ return true;
+
+ // The config file told us what satellites might be installed.
+ int pos = Array.IndexOf(installedSatellites, lookForCulture.Name);
+
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled()) {
+ if (pos < 0) {
+ FrameworkEventSource.Log.ResourceManagerCultureNotFoundInConfigFile(BaseNameField, MainAssembly, lookForCulture.Name);
+ }
+ else {
+ FrameworkEventSource.Log.ResourceManagerCultureFoundInConfigFile(BaseNameField, MainAssembly, lookForCulture.Name);
+ }
+ }
+#endif
+ return pos >= 0;
+ }
+
+ // Note: There is one config file per appdomain. This is not
+ // per-process nor per-assembly.
+ [System.Security.SecurityCritical] // auto-generated
+ private Hashtable GetSatelliteAssembliesFromConfig()
+ {
+#if FEATURE_FUSION
+
+ String fileName = AppDomain.CurrentDomain.FusionStore.ConfigurationFileInternal;
+ if (fileName == null) {
+ return null;
+ }
+
+ // Don't do a security assert. We need to support semi-trusted
+ // scenarios, but asserting here causes infinite resource lookups
+ // while initializing security & looking up mscorlib's config file.
+ // Use internal methods to bypass security checks.
+
+ // If we're dealing with a local file name or a UNC path instead
+ // of a URL, check to see if the file exists here for perf (avoids
+ // throwing a FileNotFoundException).
+ if (fileName.Length >= 2 &&
+ ((fileName[1] == Path.VolumeSeparatorChar) || (fileName[0] == Path.DirectorySeparatorChar && fileName[1] == Path.DirectorySeparatorChar)) &&
+ !File.InternalExists(fileName))
+ return null;
+
+ ConfigTreeParser parser = new ConfigTreeParser();
+ String queryPath = "/configuration/satelliteassemblies";
+ ConfigNode node = null;
+ // Catch exceptions in case a web app doesn't have a config file.
+ try {
+ node = parser.Parse(fileName, queryPath, true);
+ }
+ catch(Exception) {}
+
+ if (node == null) {
+ return null;
+ }
+
+ // The application config file will contain sections like this:
+ // <?xml version="1.0"?>
+ // <configuration>
+ // <satelliteassemblies>
+ // <assembly name="mscorlib, Version=..., PublicKeyToken=...">
+ // <culture>fr</culture>
+ // </assembly>
+ // <assembly name="UserAssembly, ...">
+ // <culture>fr-FR</culture>
+ // <culture>de-CH</culture>
+ // </assembly>
+ // <assembly name="UserAssembly2, ...">
+ // </assembly>
+ // </satelliteassemblies>
+ // </configuration>
+ Hashtable satelliteInfo = new Hashtable(StringComparer.OrdinalIgnoreCase);
+ foreach(ConfigNode assemblyNode in node.Children) {
+ if (!String.Equals(assemblyNode.Name, "assembly"))
+ throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTag", Path.GetFileName(fileName), assemblyNode.Name));
+
+ if (assemblyNode.Attributes.Count == 0)
+ throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTagNoAttr", Path.GetFileName(fileName)));
+
+ DictionaryEntry de = (DictionaryEntry) assemblyNode.Attributes[0];
+ String assemblyName = (String) de.Value;
+ if (!String.Equals(de.Key, "name") || String.IsNullOrEmpty(assemblyName) || assemblyNode.Attributes.Count > 1)
+ throw new ApplicationException(Environment.GetResourceString("XMLSyntax_InvalidSyntaxSatAssemTagBadAttr", Path.GetFileName(fileName), de.Key, de.Value));
+
+ ArrayList list = new ArrayList(5);
+ foreach(ConfigNode child in assemblyNode.Children)
+ if (child.Value != null)
+ list.Add(child.Value);
+
+ String[] satellites = new String[list.Count];
+ for(int i=0; i<satellites.Length; i++) {
+ String cultureName = (String)list[i];
+ satellites[i] = cultureName;
+#if !FEATURE_CORECLR
+ if (FrameworkEventSource.IsInitialized)
+ {
+ FrameworkEventSource.Log.ResourceManagerAddingCultureFromConfigFile(BaseNameField, MainAssembly, cultureName);
+ }
+#endif
+ }
+
+ satelliteInfo.Add(assemblyName, satellites);
+ }
+
+ return satelliteInfo;
+#else
+ return null;
+#endif //FEATURE_FUSION
+
+ }
+#endif // RESOURCE_SATELLITE_CONFIG
+
+ internal class ResourceManagerMediator
+ {
+ private ResourceManager _rm;
+
+ internal ResourceManagerMediator(ResourceManager rm)
+ {
+ if (rm == null)
+ {
+ throw new ArgumentNullException("rm");
+ }
+ _rm = rm;
+ }
+
+ // NEEDED ONLY BY FILE-BASED
+ internal String ModuleDir
+ {
+ get { return _rm.moduleDir; }
+ }
+
+ // NEEDED BOTH BY FILE-BASED AND ASSEMBLY-BASED
+ internal Type LocationInfo
+ {
+ get { return _rm._locationInfo; }
+ }
+
+ internal Type UserResourceSet
+ {
+ get { return _rm._userResourceSet; }
+ }
+
+ internal String BaseNameField
+ {
+ get { return _rm.BaseNameField; }
+ }
+
+ internal CultureInfo NeutralResourcesCulture
+ {
+ get { return _rm._neutralResourcesCulture; }
+ set { _rm._neutralResourcesCulture = value; }
+ }
+
+ internal String GetResourceFileName(CultureInfo culture)
+ {
+ return _rm.GetResourceFileName(culture);
+ }
+
+ // NEEDED ONLY BY ASSEMBLY-BASED
+ internal bool LookedForSatelliteContractVersion
+ {
+ get { return _rm._lookedForSatelliteContractVersion; }
+ set { _rm._lookedForSatelliteContractVersion = value; }
+ }
+
+ internal Version SatelliteContractVersion
+ {
+ get { return _rm._satelliteContractVersion; }
+ set { _rm._satelliteContractVersion = value; }
+ }
+
+ internal Version ObtainSatelliteContractVersion(Assembly a)
+ {
+ return ResourceManager.GetSatelliteContractVersion(a);
+ }
+
+ internal UltimateResourceFallbackLocation FallbackLoc
+ {
+ get { return _rm.FallbackLocation; }
+ set { _rm._fallbackLoc = value; }
+ }
+
+ internal RuntimeAssembly CallingAssembly
+ {
+ get { return _rm.m_callingAssembly; }
+ }
+
+ internal RuntimeAssembly MainAssembly
+ {
+ get { return (RuntimeAssembly)_rm.MainAssembly; }
+ }
+
+ // this is weird because we have BaseNameField accessor above, but we're sticking
+ // with it for compat.
+ internal String BaseName
+ {
+ get { return _rm.BaseName; }
+ }
+
+
+#if RESOURCE_SATELLITE_CONFIG
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool TryLookingForSatellite(CultureInfo lookForCulture)
+ {
+ return _rm.TryLookingForSatellite(lookForCulture);
+ }
+#endif
+
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/ResourceReader.cs b/src/mscorlib/src/System/Resources/ResourceReader.cs
new file mode 100644
index 0000000000..a269d5c5fe
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ResourceReader.cs
@@ -0,0 +1,1424 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Default way to read streams of resources on
+** demand.
+**
+** Version 2 support on October 6, 2003
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.IO;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization;
+ using System.Runtime.Serialization.Formatters;
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using System.Reflection;
+ using System.Security.Permissions;
+ using System.Security;
+ using System.Globalization;
+ using System.Configuration.Assemblies;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // Provides the default implementation of IResourceReader, reading
+ // .resources file from the system default binary format. This class
+ // can be treated as an enumerator once.
+ //
+ // See the RuntimeResourceSet overview for details on the system
+ // default file format.
+ //
+
+ internal struct ResourceLocator
+ {
+ internal Object _value; // Can be null. Consider WeakReference instead?
+ internal int _dataPos;
+
+ internal ResourceLocator(int dataPos, Object value)
+ {
+ _dataPos = dataPos;
+ _value = value;
+ }
+
+ internal int DataPosition {
+ get { return _dataPos; }
+ //set { _dataPos = value; }
+ }
+
+ // Allows adding in profiling data in a future version, or a special
+ // resource profiling build. We could also use WeakReference.
+ internal Object Value {
+ get { return _value; }
+ set { _value = value; }
+ }
+
+ internal static bool CanCache(ResourceTypeCode value)
+ {
+ Contract.Assert(value >= 0, "negative ResourceTypeCode. What?");
+ return value <= ResourceTypeCode.LastPrimitive;
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ResourceReader : IResourceReader
+ {
+ // A reasonable default buffer size for reading from files, especially
+ // when we will likely be seeking frequently. Could be smaller, but does
+ // it make sense to use anything less than one page?
+ private const int DefaultFileStreamBufferSize = 4096;
+
+ private BinaryReader _store; // backing store we're reading from.
+ // Used by RuntimeResourceSet and this class's enumerator. Maps
+ // resource name to a value, a ResourceLocator, or a
+ // LooselyLinkedManifestResource.
+ internal Dictionary<String, ResourceLocator> _resCache;
+ private long _nameSectionOffset; // Offset to name section of file.
+ private long _dataSectionOffset; // Offset to Data section of file.
+
+ // Note this class is tightly coupled with UnmanagedMemoryStream.
+ // At runtime when getting an embedded resource from an assembly,
+ // we're given an UnmanagedMemoryStream referring to the mmap'ed portion
+ // of the assembly. The pointers here are pointers into that block of
+ // memory controlled by the OS's loader.
+ private int[] _nameHashes; // hash values for all names.
+ [SecurityCritical]
+ private unsafe int* _nameHashesPtr; // In case we're using UnmanagedMemoryStream
+ private int[] _namePositions; // relative locations of names
+ [SecurityCritical]
+ private unsafe int* _namePositionsPtr; // If we're using UnmanagedMemoryStream
+ private RuntimeType[] _typeTable; // Lazy array of Types for resource values.
+ private int[] _typeNamePositions; // To delay initialize type table
+#if FEATURE_SERIALIZATION
+ private BinaryFormatter _objFormatter; // Deserialization stuff.
+#endif // FEATURE_SERIALIZATION
+ private int _numResources; // Num of resources files, in case arrays aren't allocated.
+
+ // We'll include a separate code path that uses UnmanagedMemoryStream to
+ // avoid allocating String objects and the like.
+ private UnmanagedMemoryStream _ums;
+
+ // Version number of .resources file, for compatibility
+ private int _version;
+
+#if RESOURCE_FILE_FORMAT_DEBUG
+ private bool _debug; // Whether this file has debugging stuff in it.
+#endif
+
+#if FEATURE_SERIALIZATION
+ private bool[] _safeToDeserialize; // Whether to assert serialization permission
+ private TypeLimitingDeserializationBinder _typeLimitingBinder;
+
+ // One of our goals is to make sure localizable Windows Forms apps
+ // work in semi-trusted scenarios (ie, without serialization permission).
+ // Unfortunate we're serializing out some complex types that currently
+ // require a security check on deserialization. We may fix this
+ // in a next version, but for now just hard-code a list.
+ // Hard-code in the assembly name (minus version) so people can't spoof us.
+ private static readonly String[] TypesSafeForDeserialization = {
+ "System.String[], mscorlib, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.DateTime[], mscorlib, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Bitmap, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Imaging.Metafile, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Point, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.PointF, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Size, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.SizeF, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Font, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Icon, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Drawing.Color, System.Drawing, Culture=neutral, PublicKeyToken=" + AssemblyRef.MicrosoftPublicKeyToken,
+ "System.Windows.Forms.Cursor, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.Padding, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.LinkArea, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.ImageListStreamer, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.ListViewGroup, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.ListViewItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.ListViewItem+ListViewSubItem, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.ListViewItem+ListViewSubItem+SubItemStyle, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.OwnerDrawPropertyBag, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken,
+ "System.Windows.Forms.TreeNode, System.Windows.Forms, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken
+ };
+#endif // FEATURE_SERIALIZATION
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+ public ResourceReader(String fileName)
+ {
+ _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _store = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.RandomAccess, Path.GetFileName(fileName), false), Encoding.UTF8);
+ BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(String). UnmanagedMemoryStream: "+(_ums!=null));
+
+ try {
+ ReadResources();
+ }
+ catch {
+ _store.Close(); // If we threw an exception, close the file.
+ throw;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public ResourceReader(Stream stream)
+ {
+ if (stream==null)
+ throw new ArgumentNullException("stream");
+ if (!stream.CanRead)
+ throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));
+ Contract.EndContractBlock();
+
+ _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _store = new BinaryReader(stream, Encoding.UTF8);
+ // We have a faster code path for reading resource files from an assembly.
+ _ums = stream as UnmanagedMemoryStream;
+
+ BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream). UnmanagedMemoryStream: "+(_ums!=null));
+ ReadResources();
+ }
+
+ // This is the constructor the RuntimeResourceSet calls,
+ // passing in the stream to read from and the RuntimeResourceSet's
+ // internal hash table (hash table of names with file offsets
+ // and values, coupled to this ResourceReader).
+ [System.Security.SecurityCritical] // auto-generated
+ internal ResourceReader(Stream stream, Dictionary<String, ResourceLocator> resCache)
+ {
+ Contract.Requires(stream != null, "Need a stream!");
+ Contract.Requires(stream.CanRead, "Stream should be readable!");
+ Contract.Requires(resCache != null, "Need a Dictionary!");
+
+ _resCache = resCache;
+ _store = new BinaryReader(stream, Encoding.UTF8);
+
+ _ums = stream as UnmanagedMemoryStream;
+
+ BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream, Hashtable). UnmanagedMemoryStream: "+(_ums!=null));
+ ReadResources();
+ }
+
+
+ public void Close()
+ {
+ Dispose(true);
+ }
+
+ public void Dispose()
+ {
+ Close();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void Dispose(bool disposing)
+ {
+ if (_store != null) {
+ _resCache = null;
+ if (disposing) {
+ // Close the stream in a thread-safe way. This fix means
+ // that we may call Close n times, but that's safe.
+ BinaryReader copyOfStore = _store;
+ _store = null;
+ if (copyOfStore != null)
+ copyOfStore.Close();
+ }
+ _store = null;
+ _namePositions = null;
+ _nameHashes = null;
+ _ums = null;
+ _namePositionsPtr = null;
+ _nameHashesPtr = null;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe int ReadUnalignedI4(int* p)
+ {
+ byte* buffer = (byte*)p;
+ // Unaligned, little endian format
+ return buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24);
+ }
+
+ private void SkipInt32() {
+ _store.BaseStream.Seek(4, SeekOrigin.Current);
+ }
+
+
+ private void SkipString() {
+ int stringLength = _store.Read7BitEncodedInt();
+ if (stringLength < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_NegativeStringLength"));
+ }
+ _store.BaseStream.Seek(stringLength, SeekOrigin.Current);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe int GetNameHash(int index)
+ {
+ Contract.Assert(index >=0 && index < _numResources, "Bad index into hash array. index: "+index);
+ Contract.Assert((_ums == null && _nameHashes != null && _nameHashesPtr == null) ||
+ (_ums != null && _nameHashes == null && _nameHashesPtr != null), "Internal state mangled.");
+ if (_ums == null)
+ return _nameHashes[index];
+ else
+ return ReadUnalignedI4(&_nameHashesPtr[index]);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe int GetNamePosition(int index)
+ {
+ Contract.Assert(index >=0 && index < _numResources, "Bad index into name position array. index: "+index);
+ Contract.Assert((_ums == null && _namePositions != null && _namePositionsPtr == null) ||
+ (_ums != null && _namePositions == null && _namePositionsPtr != null), "Internal state mangled.");
+ int r;
+ if (_ums == null)
+ r = _namePositions[index];
+ else
+ r = ReadUnalignedI4(&_namePositionsPtr[index]);
+ if (r < 0 || r > _dataSectionOffset - _nameSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesNameInvalidOffset", r));
+ }
+ return r;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumerator();
+ }
+
+ public IDictionaryEnumerator GetEnumerator()
+ {
+ if (_resCache == null)
+ throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+ return new ResourceEnumerator(this);
+ }
+
+ internal ResourceEnumerator GetEnumeratorInternal()
+ {
+ return new ResourceEnumerator(this);
+ }
+
+ // From a name, finds the associated virtual offset for the data.
+ // To read the data, seek to _dataSectionOffset + dataPos, then
+ // read the resource type & data.
+ // This does a binary search through the names.
+ internal int FindPosForResource(String name)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ int hash = FastResourceComparer.HashFunction(name);
+ BCLDebug.Log("RESMGRFILEFORMAT", "FindPosForResource for "+name+" hash: "+hash.ToString("x", CultureInfo.InvariantCulture));
+ // Binary search over the hashes. Use the _namePositions array to
+ // determine where they exist in the underlying stream.
+ int lo = 0;
+ int hi = _numResources - 1;
+ int index = -1;
+ bool success = false;
+ while (lo <= hi) {
+ index = (lo + hi) >> 1;
+ // Do NOT use subtraction here, since it will wrap for large
+ // negative numbers.
+ int currentHash = GetNameHash(index);
+ int c;
+ if (currentHash == hash)
+ c = 0;
+ else if (currentHash < hash)
+ c = -1;
+ else
+ c = 1;
+ //BCLDebug.Log("RESMGRFILEFORMAT", " Probing index "+index+" lo: "+lo+" hi: "+hi+" c: "+c);
+ if (c == 0) {
+ success = true;
+ break;
+ }
+ if (c < 0)
+ lo = index + 1;
+ else
+ hi = index - 1;
+ }
+ if (!success) {
+#if RESOURCE_FILE_FORMAT_DEBUG
+ String lastReadString;
+ lock(this) {
+ _store.BaseStream.Seek(_nameSectionOffset + GetNamePosition(index), SeekOrigin.Begin);
+ lastReadString = _store.ReadString();
+ }
+ BCLDebug.Log("RESMGRFILEFORMAT", LogLevel.Status, "FindPosForResource for ", name, " failed. i: ", index, " lo: ", lo, " hi: ", hi, " last read string: \"", lastReadString, '\'');
+#endif
+ return -1;
+ }
+
+ // index is the location in our hash array that corresponds with a
+ // value in the namePositions array.
+ // There could be collisions in our hash function. Check on both sides
+ // of index to find the range of hash values that are equal to the
+ // target hash value.
+ if (lo != index) {
+ lo = index;
+ while (lo > 0 && GetNameHash(lo - 1) == hash)
+ lo--;
+ }
+ if (hi != index) {
+ hi = index;
+ while (hi < _numResources - 1 && GetNameHash(hi + 1) == hash)
+ hi++;
+ }
+
+ lock(this) {
+ for(int i = lo; i<=hi; i++) {
+ _store.BaseStream.Seek(_nameSectionOffset + GetNamePosition(i), SeekOrigin.Begin);
+ if (CompareStringEqualsName(name)) {
+ int dataPos = _store.ReadInt32();
+ if (dataPos < 0 || dataPos >= _store.BaseStream.Length - _dataSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesDataInvalidOffset", dataPos));
+ }
+ return dataPos;
+ }
+ }
+ }
+ BCLDebug.Log("RESMGRFILEFORMAT", "FindPosForResource for "+name+": Found a hash collision, HOWEVER, neither of these collided values equaled the given string.");
+ return -1;
+ }
+
+ // This compares the String in the .resources file at the current position
+ // with the string you pass in.
+ // Whoever calls this method should make sure that they take a lock
+ // so no one else can cause us to seek in the stream.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe bool CompareStringEqualsName(String name)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ int byteLen = _store.Read7BitEncodedInt();
+ if (byteLen < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_NegativeStringLength"));
+ }
+ if (_ums != null) {
+ byte* bytes = _ums.PositionPointer;
+ // Skip over the data in the Stream, positioning ourselves right after it.
+ _ums.Seek(byteLen, SeekOrigin.Current);
+ if (_ums.Position > _ums.Length) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesNameTooLong"));
+ }
+
+ // On 64-bit machines, these char*'s may be misaligned. Use a
+ // byte-by-byte comparison instead.
+ //return FastResourceComparer.CompareOrdinal((char*)bytes, byteLen/2, name) == 0;
+ return FastResourceComparer.CompareOrdinal(bytes, byteLen, name) == 0;
+ }
+ else {
+ // This code needs to be fast
+ byte[] bytes = new byte[byteLen];
+ int numBytesToRead = byteLen;
+ while(numBytesToRead > 0) {
+ int n = _store.Read(bytes, byteLen - numBytesToRead, numBytesToRead);
+ if (n == 0)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceNameCorrupted"));
+ numBytesToRead -= n;
+ }
+ return FastResourceComparer.CompareOrdinal(bytes, byteLen/2, name) == 0;
+ }
+ }
+
+ // This is used in the enumerator. The enumerator iterates from 0 to n
+ // of our resources and this returns the resource name for a particular
+ // index. The parameter is NOT a virtual offset.
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe String AllocateStringForNameIndex(int index, out int dataOffset)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ byte[] bytes;
+ int byteLen;
+ long nameVA = GetNamePosition(index);
+ lock (this) {
+ _store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
+ // Can't use _store.ReadString, since it's using UTF-8!
+ byteLen = _store.Read7BitEncodedInt();
+ if (byteLen < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_NegativeStringLength"));
+ }
+
+ if (_ums != null) {
+ if (_ums.Position > _ums.Length - byteLen)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesIndexTooLong", index));
+
+ String s = null;
+ char* charPtr = (char*)_ums.PositionPointer;
+#if IA64
+ if (((int)charPtr & 1) != 0) {
+ char[] destArray = new char[byteLen/2];
+ fixed(char* pDest = destArray) {
+ Buffer.Memcpy((byte*)pDest, (byte*)charPtr, byteLen);
+ }
+ s = new String(destArray);
+ }
+ else {
+#endif //IA64
+ s = new String(charPtr, 0, byteLen/2);
+#if IA64
+ }
+#endif //IA64
+ _ums.Position += byteLen;
+ dataOffset = _store.ReadInt32();
+ if (dataOffset < 0 || dataOffset >= _store.BaseStream.Length - _dataSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesDataInvalidOffset", dataOffset));
+ }
+ return s;
+ }
+
+ bytes = new byte[byteLen];
+ // We must read byteLen bytes, or we have a corrupted file.
+ // Use a blocking read in case the stream doesn't give us back
+ // everything immediately.
+ int count = byteLen;
+ while(count > 0) {
+ int n = _store.Read(bytes, byteLen - count, count);
+ if (n == 0)
+ throw new EndOfStreamException(Environment.GetResourceString("BadImageFormat_ResourceNameCorrupted_NameIndex", index));
+ count -= n;
+ }
+ dataOffset = _store.ReadInt32();
+ if (dataOffset < 0 || dataOffset >= _store.BaseStream.Length - _dataSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesDataInvalidOffset", dataOffset));
+ }
+ }
+ return Encoding.Unicode.GetString(bytes, 0, byteLen);
+ }
+
+ // This is used in the enumerator. The enumerator iterates from 0 to n
+ // of our resources and this returns the resource value for a particular
+ // index. The parameter is NOT a virtual offset.
+ private Object GetValueForNameIndex(int index)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ long nameVA = GetNamePosition(index);
+ lock(this) {
+ _store.BaseStream.Seek(nameVA + _nameSectionOffset, SeekOrigin.Begin);
+ SkipString();
+ //BCLDebug.Log("RESMGRFILEFORMAT", "GetValueForNameIndex for index: "+index+" skip (name length): "+skip);
+ int dataPos = _store.ReadInt32();
+ if (dataPos < 0 || dataPos >= _store.BaseStream.Length - _dataSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesDataInvalidOffset", dataPos));
+ }
+ BCLDebug.Log("RESMGRFILEFORMAT", "GetValueForNameIndex: dataPos: "+dataPos);
+ ResourceTypeCode junk;
+ if (_version == 1)
+ return LoadObjectV1(dataPos);
+ else
+ return LoadObjectV2(dataPos, out junk);
+ }
+ }
+
+ // This takes a virtual offset into the data section and reads a String
+ // from that location.
+ // Anyone who calls LoadObject should make sure they take a lock so
+ // no one can cause us to do a seek in here.
+ internal String LoadString(int pos)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin);
+ String s = null;
+ int typeIndex = _store.Read7BitEncodedInt();
+ if (_version == 1) {
+ if (typeIndex == -1)
+ return null;
+ if (FindType(typeIndex) != typeof(String))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Type", FindType(typeIndex).FullName));
+ s = _store.ReadString();
+ }
+ else {
+ ResourceTypeCode typeCode = (ResourceTypeCode) typeIndex;
+ if (typeCode != ResourceTypeCode.String && typeCode != ResourceTypeCode.Null) {
+ String typeString;
+ if (typeCode < ResourceTypeCode.StartOfUserTypes)
+ typeString = typeCode.ToString();
+ else
+ typeString = FindType(typeCode - ResourceTypeCode.StartOfUserTypes).FullName;
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Type", typeString));
+ }
+ if (typeCode == ResourceTypeCode.String) // ignore Null
+ s = _store.ReadString();
+ }
+ BCLDebug.Log("RESMGRFILEFORMAT", "LoadString("+pos.ToString("x", CultureInfo.InvariantCulture)+" returned "+(s==null ? "[a null string]" : s));
+ return s;
+ }
+
+ // Called from RuntimeResourceSet
+ internal Object LoadObject(int pos)
+ {
+ if (_version == 1)
+ return LoadObjectV1(pos);
+ ResourceTypeCode typeCode;
+ return LoadObjectV2(pos, out typeCode);
+ }
+
+ internal Object LoadObject(int pos, out ResourceTypeCode typeCode)
+ {
+ if (_version == 1) {
+ Object o = LoadObjectV1(pos);
+ typeCode = (o is String) ? ResourceTypeCode.String : ResourceTypeCode.StartOfUserTypes;
+ return o;
+ }
+ return LoadObjectV2(pos, out typeCode);
+ }
+
+ // This takes a virtual offset into the data section and reads an Object
+ // from that location.
+ // Anyone who calls LoadObject should make sure they take a lock so
+ // no one can cause us to do a seek in here.
+ internal Object LoadObjectV1(int pos)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ Contract.Assert(_version == 1, ".resources file was not a V1 .resources file!");
+
+ try {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _LoadObjectV1 and wrap here.
+ return _LoadObjectV1(pos);
+ }
+ catch (EndOfStreamException eof) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_TypeMismatch"), eof);
+ }
+ catch (ArgumentOutOfRangeException e) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_TypeMismatch"), e);
+ }
+ }
+
+#if FEATURE_SERIALIZATION
+ [SecuritySafeCritical]
+#endif
+ private Object _LoadObjectV1(int pos) {
+ _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin);
+ int typeIndex = _store.Read7BitEncodedInt();
+ if (typeIndex == -1)
+ return null;
+ RuntimeType type = FindType(typeIndex);
+ BCLDebug.Log("RESMGRFILEFORMAT", "LoadObject type: "+type.Name+" pos: 0x"+_store.BaseStream.Position.ToString("x", CultureInfo.InvariantCulture));
+ // Consider putting in logic to see if this type is a
+ // primitive or a value type first, so we can reach the
+ // deserialization code faster for arbitrary objects.
+
+ if (type == typeof(String))
+ return _store.ReadString();
+ else if (type == typeof(Int32))
+ return _store.ReadInt32();
+ else if (type == typeof(Byte))
+ return _store.ReadByte();
+ else if (type == typeof(SByte))
+ return _store.ReadSByte();
+ else if (type == typeof(Int16))
+ return _store.ReadInt16();
+ else if (type == typeof(Int64))
+ return _store.ReadInt64();
+ else if (type == typeof(UInt16))
+ return _store.ReadUInt16();
+ else if (type == typeof(UInt32))
+ return _store.ReadUInt32();
+ else if (type == typeof(UInt64))
+ return _store.ReadUInt64();
+ else if (type == typeof(Single))
+ return _store.ReadSingle();
+ else if (type == typeof(Double))
+ return _store.ReadDouble();
+ else if (type == typeof(DateTime)) {
+ // Ideally we should use DateTime's ToBinary & FromBinary,
+ // but we can't for compatibility reasons.
+ return new DateTime(_store.ReadInt64());
+ }
+ else if (type == typeof(TimeSpan))
+ return new TimeSpan(_store.ReadInt64());
+ else if (type == typeof(Decimal)) {
+ int[] bits = new int[4];
+ for(int i=0; i<bits.Length; i++)
+ bits[i] = _store.ReadInt32();
+ return new Decimal(bits);
+ }
+ else {
+#if FEATURE_SERIALIZATION
+ return DeserializeObject(typeIndex);
+#else
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization"));
+#endif // FEATURE_SERIALIZATION
+ }
+ }
+
+ internal Object LoadObjectV2(int pos, out ResourceTypeCode typeCode)
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+ Contract.Assert(_version >= 2, ".resources file was not a V2 (or higher) .resources file!");
+
+ try {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _LoadObjectV2 and wrap here.
+ return _LoadObjectV2(pos, out typeCode);
+ }
+ catch (EndOfStreamException eof) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_TypeMismatch"), eof);
+ }
+ catch (ArgumentOutOfRangeException e) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_TypeMismatch"), e);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private Object _LoadObjectV2(int pos, out ResourceTypeCode typeCode) {
+ _store.BaseStream.Seek(_dataSectionOffset+pos, SeekOrigin.Begin);
+ typeCode = (ResourceTypeCode) _store.Read7BitEncodedInt();
+
+ BCLDebug.Log("RESMGRFILEFORMAT", "LoadObjectV2 type: "+typeCode+" pos: 0x"+_store.BaseStream.Position.ToString("x", CultureInfo.InvariantCulture));
+
+ switch(typeCode) {
+ case ResourceTypeCode.Null:
+ return null;
+
+ case ResourceTypeCode.String:
+ return _store.ReadString();
+
+ case ResourceTypeCode.Boolean:
+ return _store.ReadBoolean();
+
+ case ResourceTypeCode.Char:
+ return (char) _store.ReadUInt16();
+
+ case ResourceTypeCode.Byte:
+ return _store.ReadByte();
+
+ case ResourceTypeCode.SByte:
+ return _store.ReadSByte();
+
+ case ResourceTypeCode.Int16:
+ return _store.ReadInt16();
+
+ case ResourceTypeCode.UInt16:
+ return _store.ReadUInt16();
+
+ case ResourceTypeCode.Int32:
+ return _store.ReadInt32();
+
+ case ResourceTypeCode.UInt32:
+ return _store.ReadUInt32();
+
+ case ResourceTypeCode.Int64:
+ return _store.ReadInt64();
+
+ case ResourceTypeCode.UInt64:
+ return _store.ReadUInt64();
+
+ case ResourceTypeCode.Single:
+ return _store.ReadSingle();
+
+ case ResourceTypeCode.Double:
+ return _store.ReadDouble();
+
+ case ResourceTypeCode.Decimal:
+ return _store.ReadDecimal();
+
+ case ResourceTypeCode.DateTime:
+ // Use DateTime's ToBinary & FromBinary.
+ Int64 data = _store.ReadInt64();
+ return DateTime.FromBinary(data);
+
+ case ResourceTypeCode.TimeSpan:
+ Int64 ticks = _store.ReadInt64();
+ return new TimeSpan(ticks);
+
+ // Special types
+ case ResourceTypeCode.ByteArray: {
+ int len = _store.ReadInt32();
+ if (len < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceDataLengthInvalid", len));
+ }
+
+ if (_ums == null) {
+ if (len > _store.BaseStream.Length) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceDataLengthInvalid", len));
+ }
+ return _store.ReadBytes(len);
+ }
+
+ if (len > _ums.Length - _ums.Position) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceDataLengthInvalid", len));
+ }
+
+ byte[] bytes = new byte[len];
+ int r = _ums.Read(bytes, 0, len);
+ Contract.Assert(r == len, "ResourceReader needs to use a blocking read here. (Call _store.ReadBytes(len)?)");
+ return bytes;
+ }
+
+ case ResourceTypeCode.Stream: {
+ int len = _store.ReadInt32();
+ if (len < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceDataLengthInvalid", len));
+ }
+ if (_ums == null) {
+ byte[] bytes = _store.ReadBytes(len);
+ // Lifetime of memory == lifetime of this stream.
+ return new PinnedBufferMemoryStream(bytes);
+ }
+
+ // make sure we don't create an UnmanagedMemoryStream that is longer than the resource stream.
+ if (len > _ums.Length - _ums.Position) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourceDataLengthInvalid", len));
+ }
+
+ // For the case that we've memory mapped in the .resources
+ // file, just return a Stream pointing to that block of memory.
+ unsafe {
+ return new UnmanagedMemoryStream(_ums.PositionPointer, len, len, FileAccess.Read, true);
+ }
+ }
+
+ default:
+ if (typeCode < ResourceTypeCode.StartOfUserTypes) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_TypeMismatch"));
+ }
+ break;
+ }
+
+ // Normal serialized objects
+#if FEATURE_SERIALIZATION
+ int typeIndex = typeCode - ResourceTypeCode.StartOfUserTypes;
+ return DeserializeObject(typeIndex);
+#else
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization"));
+#endif // FEATURE_SERIALIZATION
+ }
+
+
+#if FEATURE_SERIALIZATION
+ // Helper method to safely deserialize a type, using a type-limiting
+ // deserialization binder to simulate a type-limiting deserializer.
+ // This method handles types that are safe to deserialize, as well as
+ // ensuring we only get back what we expect.
+ [System.Security.SecurityCritical] // auto-generated
+ private Object DeserializeObject(int typeIndex)
+ {
+ RuntimeType type = FindType(typeIndex);
+ // Initialize deserialization permission array, if needed
+ if (_safeToDeserialize == null)
+ InitSafeToDeserializeArray();
+
+ // Ensure that the object we deserialized is exactly the same
+ // type of object we thought we should be deserializing. This
+ // will help prevent malformed .resources files from using our
+ // serialization permission assert to deserialize anything
+ // via a malformed type ID.
+
+ Object graph;
+ if (_safeToDeserialize[typeIndex]) {
+ // Don't assert serialization permission - just ask the binary
+ // formatter to avoid a permission check. This ensures that any
+ // types which do demand serialization permission in their
+ // deserialization .cctors will fail.
+ // Also, use a serialization binder to limit bind requests to
+ // our allowed list of WinForms types.
+ _objFormatter.Binder = _typeLimitingBinder;
+ _typeLimitingBinder.ExpectingToDeserialize(type);
+ graph = _objFormatter.UnsafeDeserialize(_store.BaseStream, null);
+ }
+ else {
+ _objFormatter.Binder = null;
+ graph = _objFormatter.Deserialize(_store.BaseStream);
+ }
+
+ // This check is about correctness, not security at this point.
+ if (graph.GetType() != type)
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResType&SerBlobMismatch", type.FullName, graph.GetType().FullName));
+
+ return graph;
+ }
+#endif // FEATURE_SERIALIZATION
+
+ // Reads in the header information for a .resources file. Verifies some
+ // of the assumptions about this resource set, and builds the class table
+ // for the default resource file format.
+ [System.Security.SecurityCritical] // auto-generated
+ private void ReadResources()
+ {
+ Contract.Assert(_store != null, "ResourceReader is closed!");
+#if FEATURE_SERIALIZATION
+ BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence));
+ _typeLimitingBinder = new TypeLimitingDeserializationBinder();
+ bf.Binder = _typeLimitingBinder;
+ _objFormatter = bf;
+#endif // FEATURE_SERIALIZATION
+
+ try {
+ // mega try-catch performs exceptionally bad on x64; factored out body into
+ // _ReadResources and wrap here.
+ _ReadResources();
+ }
+ catch (EndOfStreamException eof) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"), eof);
+ }
+ catch (IndexOutOfRangeException e) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"), e);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void _ReadResources()
+ {
+ // Read ResourceManager header
+ // Check for magic number
+ int magicNum = _store.ReadInt32();
+ if (magicNum != ResourceManager.MagicNumber)
+ throw new ArgumentException(Environment.GetResourceString("Resources_StreamNotValid"));
+ // Assuming this is ResourceManager header V1 or greater, hopefully
+ // after the version number there is a number of bytes to skip
+ // to bypass the rest of the ResMgr header. For V2 or greater, we
+ // use this to skip to the end of the header
+ int resMgrHeaderVersion = _store.ReadInt32();
+ int numBytesToSkip = _store.ReadInt32();
+ if (numBytesToSkip < 0 || resMgrHeaderVersion < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+ if (resMgrHeaderVersion > 1) {
+ BCLDebug.Log("RESMGRFILEFORMAT", LogLevel.Status, "ReadResources: Unexpected ResMgr header version: {0} Skipping ahead {1} bytes.", resMgrHeaderVersion, numBytesToSkip);
+ _store.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current);
+ }
+ else {
+ BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Parsing ResMgr header v1.");
+ // We don't care about numBytesToSkip; read the rest of the header
+
+ // Read in type name for a suitable ResourceReader
+ // Note ResourceWriter & InternalResGen use different Strings.
+ String readerType = _store.ReadString();
+ readerType = System.CoreLib.FixupCoreLibName(readerType);
+ AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
+
+ if (!ResourceManager.CompareNames(readerType, ResourceManager.ResReaderTypeName, mscorlib))
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_WrongResourceReader_Type", readerType));
+
+ // Skip over type name for a suitable ResourceSet
+ SkipString();
+ }
+
+ // Read RuntimeResourceSet header
+ // Do file version check
+ int version = _store.ReadInt32();
+ if (version != RuntimeResourceSet.Version && version != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ResourceFileUnsupportedVersion", RuntimeResourceSet.Version, version));
+ _version = version;
+
+#if RESOURCE_FILE_FORMAT_DEBUG
+ // Look for ***DEBUG*** to see if this is a debuggable file.
+ long oldPos = _store.BaseStream.Position;
+ _debug = false;
+ try {
+ String debugString = _store.ReadString();
+ _debug = String.Equals("***DEBUG***", debugString);
+ }
+ catch(IOException) {
+ }
+ catch(OutOfMemoryException) {
+ }
+ if (_debug) {
+ Console.WriteLine("ResourceReader is looking at a debuggable .resources file, version {0}", _version);
+ }
+ else {
+ _store.BaseStream.Position = oldPos;
+ }
+#endif
+
+ _numResources = _store.ReadInt32();
+ if (_numResources < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+ BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Expecting " + _numResources + " resources.");
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 4)
+ Console.WriteLine("ResourceReader::ReadResources - Reading in "+_numResources+" resources");
+#endif
+
+ // Read type positions into type positions array.
+ // But delay initialize the type table.
+ int numTypes = _store.ReadInt32();
+ if (numTypes < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+ _typeTable = new RuntimeType[numTypes];
+ _typeNamePositions = new int[numTypes];
+ for (int i=0; i<numTypes; i++) {
+ _typeNamePositions[i] = (int) _store.BaseStream.Position;
+
+ // Skip over the Strings in the file. Don't create types.
+ SkipString();
+ }
+
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 5)
+ Console.WriteLine("ResourceReader::ReadResources - Reading in "+numTypes+" type table entries");
+#endif
+
+ // Prepare to read in the array of name hashes
+ // Note that the name hashes array is aligned to 8 bytes so
+ // we can use pointers into it on 64 bit machines. (4 bytes
+ // may be sufficient, but let's plan for the future)
+ // Skip over alignment stuff. All public .resources files
+ // should be aligned No need to verify the byte values.
+ long pos = _store.BaseStream.Position;
+ int alignBytes = ((int)pos) & 7;
+ if (alignBytes != 0) {
+ for (int i = 0; i < 8 - alignBytes; i++) {
+ _store.ReadByte();
+ }
+ }
+
+ // Read in the array of name hashes
+#if RESOURCE_FILE_FORMAT_DEBUG
+ // Skip over "HASHES->"
+ if (_debug) {
+ _store.BaseStream.Position += 8;
+ }
+#endif
+
+ if (_ums == null) {
+ _nameHashes = new int[_numResources];
+ for (int i = 0; i < _numResources; i++) {
+ _nameHashes[i] = _store.ReadInt32();
+ }
+ }
+ else {
+ int seekPos = unchecked(4 * _numResources);
+ if (seekPos < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+ unsafe {
+ _nameHashesPtr = (int*)_ums.PositionPointer;
+ // Skip over the array of nameHashes.
+ _ums.Seek(seekPos, SeekOrigin.Current);
+ // get the position pointer once more to check that the whole table is within the stream
+ byte* junk = _ums.PositionPointer;
+ }
+ }
+
+ // Read in the array of relative positions for all the names.
+#if RESOURCE_FILE_FORMAT_DEBUG
+ // Skip over "POS---->"
+ if (_debug) {
+ _store.BaseStream.Position += 8;
+ }
+#endif
+ if (_ums == null) {
+ _namePositions = new int[_numResources];
+ for (int i = 0; i < _numResources; i++) {
+ int namePosition = _store.ReadInt32();
+ if (namePosition < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+
+ _namePositions[i] = namePosition;
+ }
+ }
+ else {
+ int seekPos = unchecked(4 * _numResources);
+ if (seekPos < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+ unsafe {
+ _namePositionsPtr = (int*)_ums.PositionPointer;
+ // Skip over the array of namePositions.
+ _ums.Seek(seekPos, SeekOrigin.Current);
+ // get the position pointer once more to check that the whole table is within the stream
+ byte* junk = _ums.PositionPointer;
+ }
+ }
+
+ // Read location of data section.
+ _dataSectionOffset = _store.ReadInt32();
+ if (_dataSectionOffset < 0) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+
+ // Store current location as start of name section
+ _nameSectionOffset = _store.BaseStream.Position;
+
+ // _nameSectionOffset should be <= _dataSectionOffset; if not, it's corrupt
+ if (_dataSectionOffset < _nameSectionOffset) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"));
+ }
+
+ BCLDebug.Log("RESMGRFILEFORMAT", String.Format(CultureInfo.InvariantCulture, "ReadResources: _nameOffset = 0x{0:x} _dataOffset = 0x{1:x}", _nameSectionOffset, _dataSectionOffset));
+ }
+
+ // This allows us to delay-initialize the Type[]. This might be a
+ // good startup time savings, since we might have to load assemblies
+ // and initialize Reflection.
+ private RuntimeType FindType(int typeIndex)
+ {
+ if (typeIndex < 0 || typeIndex >= _typeTable.Length) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_InvalidType"));
+ }
+ if (_typeTable[typeIndex] == null) {
+ long oldPos = _store.BaseStream.Position;
+ try {
+ _store.BaseStream.Position = _typeNamePositions[typeIndex];
+ String typeName = _store.ReadString();
+ _typeTable[typeIndex] = (RuntimeType)Type.GetType(typeName, true);
+ }
+#if !FEATURE_SERIALIZATION
+ // If serialization isn't supported, we convert FileNotFoundException to
+ // NotSupportedException for consistency with v2. This is a corner-case, but the
+ // idea is that we want to give the user a more accurate error message. Even if
+ // the dependency were found, we know it will require serialization since it
+ // can't be one of the types we special case. So if the dependency were found,
+ // it would go down the serialization code path, resulting in NotSupported for
+ // SKUs without serialization.
+ //
+ // We don't want to regress the expected case by checking the type info before
+ // getting to Type.GetType -- this is costly with v1 resource formats.
+ catch (FileNotFoundException)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ResourceObjectSerialization"));
+ }
+#endif // FEATURE_SERIALIZATION
+ finally {
+ _store.BaseStream.Position = oldPos;
+ }
+ }
+ Contract.Assert(_typeTable[typeIndex] != null, "Should have found a type!");
+ return _typeTable[typeIndex];
+ }
+
+#if FEATURE_SERIALIZATION
+ [System.Security.SecurityCritical] // auto-generated
+ private void InitSafeToDeserializeArray()
+ {
+ _safeToDeserialize = new bool[_typeTable.Length];
+ for(int i=0; i<_typeTable.Length; i++) {
+ long oldPos = _store.BaseStream.Position;
+ String typeName;
+ try {
+ _store.BaseStream.Position = _typeNamePositions[i];
+ typeName = _store.ReadString();
+ }
+ finally {
+ _store.BaseStream.Position = oldPos;
+ }
+
+ AssemblyName an;
+ String typePart;
+ RuntimeType resourceType = (RuntimeType)Type.GetType(typeName, false);
+ if (resourceType == null) {
+ an = null;
+ typePart = typeName;
+ }
+ else {
+ // Enums should be safe to deserialize, and this helps out
+ // partially trusted, localized WinForms apps.
+ if (resourceType.BaseType == typeof(Enum)) {
+ _safeToDeserialize[i] = true;
+ continue;
+ }
+
+ // For most types, check our TypesSafeForDeserialization.
+ typePart = resourceType.FullName;
+
+ an = new AssemblyName();
+
+ // resourceType is retrieved via Type.GetType and must be a RuntimeType
+ RuntimeAssembly a = (RuntimeAssembly)resourceType.Assembly;
+ an.Init(a.GetSimpleName(),
+ a.GetPublicKey(),
+ null, // public key token
+ null, // version
+ a.GetLocale(),
+ AssemblyHashAlgorithm.None,
+ AssemblyVersionCompatibility.SameMachine,
+ null, // codebase
+ AssemblyNameFlags.PublicKey,
+ null); // strong name key pair
+ }
+
+ foreach(String safeType in TypesSafeForDeserialization) {
+ if (ResourceManager.CompareNames(safeType, typePart, an)) {
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 7)
+ Console.WriteLine("ResReader: Found a type-safe type to deserialize! Type name: {0}", typeName);
+#endif
+ _safeToDeserialize[i] = true;
+ continue;
+ }
+ }
+
+#if _DEBUG
+ if (ResourceManager.DEBUG >= 7)
+ if (!_safeToDeserialize[i])
+ Console.WriteLine("ResReader: Found a type that wasn't safe to deserialize: {0}", typeName);
+#endif
+ }
+ }
+#endif // FEATURE_SERIALIZATION
+
+ public void GetResourceData(String resourceName, out String resourceType, out byte[] resourceData)
+ {
+ if (resourceName == null)
+ throw new ArgumentNullException("resourceName");
+ Contract.EndContractBlock();
+ if (_resCache == null)
+ throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+
+ // Get the type information from the data section. Also,
+ // sort all of the data section's indexes to compute length of
+ // the serialized data for this type (making sure to subtract
+ // off the length of the type code).
+ int[] sortedDataPositions = new int[_numResources];
+ int dataPos = FindPosForResource(resourceName);
+ if( dataPos == -1) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_ResourceNameNotExist", resourceName));
+ }
+
+ lock(this) {
+ // Read all the positions of data within the data section.
+ for(int i=0; i<_numResources; i++) {
+ _store.BaseStream.Position = _nameSectionOffset + GetNamePosition(i);
+ // Skip over name of resource
+ int numBytesToSkip = _store.Read7BitEncodedInt();
+ if (numBytesToSkip < 0) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesNameInvalidOffset", numBytesToSkip));
+ }
+ _store.BaseStream.Position += numBytesToSkip;
+
+ int dPos = _store.ReadInt32();
+ if (dPos < 0 || dPos >= _store.BaseStream.Length - _dataSectionOffset) {
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourcesDataInvalidOffset", dPos));
+ }
+ sortedDataPositions[i] = dPos;
+ }
+ Array.Sort(sortedDataPositions);
+
+ int index = Array.BinarySearch(sortedDataPositions, dataPos);
+ Contract.Assert(index >= 0 && index < _numResources, "Couldn't find data position within sorted data positions array!");
+ long nextData = (index < _numResources - 1) ? sortedDataPositions[index + 1] + _dataSectionOffset : _store.BaseStream.Length;
+ int len = (int) (nextData - (dataPos + _dataSectionOffset));
+ Contract.Assert(len >= 0 && len <= (int) _store.BaseStream.Length - dataPos + _dataSectionOffset, "Length was negative or outside the bounds of the file!");
+
+ // Read type code then byte[]
+ _store.BaseStream.Position = _dataSectionOffset + dataPos;
+ ResourceTypeCode typeCode = (ResourceTypeCode) _store.Read7BitEncodedInt();
+ if (typeCode < 0 || typeCode >= ResourceTypeCode.StartOfUserTypes + _typeTable.Length) {
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_InvalidType"));
+ }
+ resourceType = TypeNameFromTypeCode(typeCode);
+
+ // The length must be adjusted to subtract off the number
+ // of bytes in the 7 bit encoded type code.
+ len -= (int) (_store.BaseStream.Position - (_dataSectionOffset + dataPos));
+ byte[] bytes = _store.ReadBytes(len);
+ if (bytes.Length != len)
+ throw new FormatException(Environment.GetResourceString("BadImageFormat_ResourceNameCorrupted"));
+ resourceData = bytes;
+ }
+ }
+
+ private String TypeNameFromTypeCode(ResourceTypeCode typeCode)
+ {
+ Contract.Requires(typeCode >= 0, "can't be negative");
+ if (typeCode < ResourceTypeCode.StartOfUserTypes) {
+ Contract.Assert(!String.Equals(typeCode.ToString(), "LastPrimitive"), "Change ResourceTypeCode metadata order so LastPrimitive isn't what Enum.ToString prefers.");
+ return "ResourceTypeCode." + typeCode.ToString();
+ }
+ else {
+ int typeIndex = typeCode - ResourceTypeCode.StartOfUserTypes;
+ Contract.Assert(typeIndex >= 0 && typeIndex < _typeTable.Length, "TypeCode is broken or corrupted!");
+ long oldPos = _store.BaseStream.Position;
+ try {
+ _store.BaseStream.Position = _typeNamePositions[typeIndex];
+ return _store.ReadString();
+ }
+ finally {
+ _store.BaseStream.Position = oldPos;
+ }
+ }
+ }
+
+#if FEATURE_SERIALIZATION
+ // We need to build a type-limiting deserializer. We know exactly which
+ // type we want to deserialize, and if someone tells us we have type X
+ // (which might be safe to deserialize) and they give us a serialized
+ // form of type Y, we don't want to run the deserialization constructor
+ // because we've asserted serialization formatter permission. Instead,
+ // limit the binary formatter's type binding to precisely the type we
+ // expect. If they ever don't match, that's a corrupt .resources file.
+ // We also must check the complete object graph to ensure all of the
+ // graph contains safe objects.
+ // Note this is tightly coupled to the BinaryFormatter, since we use
+ // its internal ObjectReader::FastBindToType method, and we had to
+ // change the ObjectReader to register itself with this type.
+ internal sealed class TypeLimitingDeserializationBinder : SerializationBinder
+ {
+ private RuntimeType _typeToDeserialize;
+ // This is tightly coupled with the binary formatter, because we
+ // want to use exactly the same code found in the ObjectReader
+ // to do the lookup, then just give a thumbs up or down based on
+ // a type equality comparison. In the future, we could consider
+ // some better refactoring of this code.
+ private ObjectReader _objectReader;
+
+ internal ObjectReader ObjectReader {
+ get { return _objectReader; }
+ set { _objectReader = value; }
+ }
+
+ internal void ExpectingToDeserialize(RuntimeType type)
+ {
+ _typeToDeserialize = type;
+ }
+
+ [System.Security.SecuritySafeCritical] // overrides transparent public member
+ public override Type BindToType(string assemblyName, string typeName)
+ {
+ // BinaryObjectReader::Bind tries us first, then its own code.
+ // Returning null means let the default binding rules happen.
+ AssemblyName an = new AssemblyName(assemblyName);
+
+ bool safe = false;
+ foreach(String safeType in TypesSafeForDeserialization) {
+ if (ResourceManager.CompareNames(safeType, typeName, an)) {
+ safe = true;
+ break;
+ }
+ }
+
+ // WinForms types may internally use some enums that aren't
+ // on our safe to deserialize list, like Font using FontStyle.
+ Type t = ObjectReader.FastBindToType(assemblyName, typeName);
+ if (t.IsEnum)
+ safe = true;
+
+ if (safe)
+ return null;
+
+ // Throw instead of returning null.
+ // If you're looking at this in a debugger, you've either
+ // got a malformed .resources file on your hands, or WinForms
+ // types have taken a new dependency on another type. Check
+ // whether assemblyName & typeName refer to a trustworthy type,
+ // & consider adding it to the TypesSafeToDeserialize list.
+ throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResType&SerBlobMismatch", _typeToDeserialize.FullName, typeName));
+ }
+ }
+#endif // FEATURE_SERIALIZATION
+
+
+ internal sealed class ResourceEnumerator : IDictionaryEnumerator
+ {
+ private const int ENUM_DONE = Int32.MinValue;
+ private const int ENUM_NOT_STARTED = -1;
+
+ private ResourceReader _reader;
+ private bool _currentIsValid;
+ private int _currentName;
+ private int _dataPosition; // cached for case-insensitive table
+
+ internal ResourceEnumerator(ResourceReader reader)
+ {
+ _currentName = ENUM_NOT_STARTED;
+ _reader = reader;
+ _dataPosition = -2;
+ }
+
+ public bool MoveNext()
+ {
+ if (_currentName == _reader._numResources - 1 || _currentName == ENUM_DONE) {
+ _currentIsValid = false;
+ _currentName = ENUM_DONE;
+ return false;
+ }
+ _currentIsValid = true;
+ _currentName++;
+ return true;
+ }
+
+ public Object Key {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ if (!_currentIsValid) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_reader._resCache == null) throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+
+ return _reader.AllocateStringForNameIndex(_currentName, out _dataPosition);
+ }
+ }
+
+ public Object Current {
+ get {
+ return Entry;
+ }
+ }
+
+ // Warning: This requires that you call the Key or Entry property FIRST before calling it!
+ internal int DataPosition {
+ get {
+ return _dataPosition;
+ }
+ }
+
+ public DictionaryEntry Entry {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ if (!_currentIsValid) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_reader._resCache == null) throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+
+ String key;
+ Object value = null;
+ lock (_reader) { // locks should be taken in the same order as in RuntimeResourceSet.GetObject to avoid deadlock
+ lock (_reader._resCache) {
+ key = _reader.AllocateStringForNameIndex(_currentName, out _dataPosition); // AllocateStringForNameIndex could lock on _reader
+ ResourceLocator locator;
+ if (_reader._resCache.TryGetValue(key, out locator)) {
+ value = locator.Value;
+ }
+ if (value == null) {
+ if (_dataPosition == -1)
+ value = _reader.GetValueForNameIndex(_currentName);
+ else
+ value = _reader.LoadObject(_dataPosition);
+ // If enumeration and subsequent lookups happen very
+ // frequently in the same process, add a ResourceLocator
+ // to _resCache here. But WinForms enumerates and
+ // just about everyone else does lookups. So caching
+ // here may bloat working set.
+ }
+ }
+ }
+ return new DictionaryEntry(key, value);
+ }
+ }
+
+ public Object Value {
+ get {
+ if (_currentName == ENUM_DONE) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ if (!_currentIsValid) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_reader._resCache == null) throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+
+ // Consider using _resCache here, eventually, if
+ // this proves to be an interesting perf scenario.
+ // But mixing lookups and enumerators shouldn't be
+ // particularly compelling.
+ return _reader.GetValueForNameIndex(_currentName);
+ }
+ }
+
+ public void Reset()
+ {
+ if (_reader._resCache == null) throw new InvalidOperationException(Environment.GetResourceString("ResourceReaderIsClosed"));
+ _currentIsValid = false;
+ _currentName = ENUM_NOT_STARTED;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/ResourceSet.cs b/src/mscorlib/src/System/Resources/ResourceSet.cs
new file mode 100644
index 0000000000..ed40a1237f
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ResourceSet.cs
@@ -0,0 +1,332 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Culture-specific collection of resources.
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.Collections;
+ using System.IO;
+ using System.Globalization;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Reflection;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // A ResourceSet stores all the resources defined in one particular CultureInfo.
+ //
+ // The method used to load resources is straightforward - this class
+ // enumerates over an IResourceReader, loading every name and value, and
+ // stores them in a hash table. Custom IResourceReaders can be used.
+ //
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class ResourceSet : IDisposable, IEnumerable
+ {
+ [NonSerialized] protected IResourceReader Reader;
+#if FEATURE_CORECLR
+ internal Hashtable Table;
+#else
+ protected Hashtable Table;
+#endif
+
+ private Hashtable _caseInsensitiveTable; // For case-insensitive lookups.
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ [OptionalField]
+ private Assembly _assembly; // For LooselyLinkedResourceReferences
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ protected ResourceSet()
+ {
+ // To not inconvenience people subclassing us, we should allocate a new
+ // hashtable here just so that Table is set to something.
+ CommonInit();
+ }
+
+ // For RuntimeResourceSet, ignore the Table parameter - it's a wasted
+ // allocation.
+ internal ResourceSet(bool junk)
+ {
+ }
+
+ // Creates a ResourceSet using the system default ResourceReader
+ // implementation. Use this constructor to open & read from a file
+ // on disk.
+ //
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public ResourceSet(String fileName)
+ {
+ Reader = new ResourceReader(fileName);
+ CommonInit();
+ ReadResources();
+ }
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ public ResourceSet(String fileName, Assembly assembly)
+ {
+ Reader = new ResourceReader(fileName);
+ CommonInit();
+ _assembly = assembly;
+ ReadResources();
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ // Creates a ResourceSet using the system default ResourceReader
+ // implementation. Use this constructor to read from an open stream
+ // of data.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public ResourceSet(Stream stream)
+ {
+ Reader = new ResourceReader(stream);
+ CommonInit();
+ ReadResources();
+ }
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ [System.Security.SecurityCritical] // auto_generated_required
+ public ResourceSet(Stream stream, Assembly assembly)
+ {
+ Reader = new ResourceReader(stream);
+ CommonInit();
+ _assembly = assembly;
+ ReadResources();
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ public ResourceSet(IResourceReader reader)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+ Contract.EndContractBlock();
+ Reader = reader;
+ CommonInit();
+ ReadResources();
+ }
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ public ResourceSet(IResourceReader reader, Assembly assembly)
+ {
+ if (reader == null)
+ throw new ArgumentNullException("reader");
+ Contract.EndContractBlock();
+ Reader = reader;
+ CommonInit();
+ _assembly = assembly;
+ ReadResources();
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ private void CommonInit()
+ {
+ Table = new Hashtable();
+ }
+
+ // Closes and releases any resources used by this ResourceSet, if any.
+ // All calls to methods on the ResourceSet after a call to close may
+ // fail. Close is guaranteed to be safely callable multiple times on a
+ // particular ResourceSet, and all subclasses must support these semantics.
+ public virtual void Close()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing) {
+ // Close the Reader in a thread-safe way.
+ IResourceReader copyOfReader = Reader;
+ Reader = null;
+ if (copyOfReader != null)
+ copyOfReader.Close();
+ }
+ Reader = null;
+ _caseInsensitiveTable = null;
+ Table = null;
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ // Optional - used for resolving assembly manifest resource references.
+ // This can safely be null.
+ [ComVisible(false)]
+ public Assembly Assembly {
+ get { return _assembly; }
+ /*protected*/ set { _assembly = value; }
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ // Returns the preferred IResourceReader class for this kind of ResourceSet.
+ // Subclasses of ResourceSet using their own Readers &; should override
+ // GetDefaultReader and GetDefaultWriter.
+ public virtual Type GetDefaultReader()
+ {
+ return typeof(ResourceReader);
+ }
+
+#if !FEATURE_CORECLR
+ // Returns the preferred IResourceWriter class for this kind of ResourceSet.
+ // Subclasses of ResourceSet using their own Readers &; should override
+ // GetDefaultReader and GetDefaultWriter.
+ public virtual Type GetDefaultWriter()
+ {
+ return typeof(ResourceWriter);
+ }
+#endif // !FEATURE_CORECLR
+
+ [ComVisible(false)]
+ public virtual IDictionaryEnumerator GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ /// <internalonly/>
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ private IDictionaryEnumerator GetEnumeratorHelper()
+ {
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+ return copyOfTable.GetEnumerator();
+ }
+
+ // Look up a string value for a resource given its name.
+ //
+ public virtual String GetString(String name)
+ {
+ Object obj = GetObjectInternal(name);
+ try {
+ return (String)obj;
+ }
+ catch (InvalidCastException) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
+ }
+ }
+
+ public virtual String GetString(String name, bool ignoreCase)
+ {
+ Object obj;
+ String s;
+
+ // Case-sensitive lookup
+ obj = GetObjectInternal(name);
+ try {
+ s = (String)obj;
+ }
+ catch (InvalidCastException) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
+ }
+
+ // case-sensitive lookup succeeded
+ if (s != null || !ignoreCase) {
+ return s;
+ }
+
+ // Try doing a case-insensitive lookup
+ obj = GetCaseInsensitiveObjectInternal(name);
+ try {
+ return (String)obj;
+ }
+ catch (InvalidCastException) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ResourceNotString_Name", name));
+ }
+ }
+
+ // Look up an object value for a resource given its name.
+ //
+ public virtual Object GetObject(String name)
+ {
+ return GetObjectInternal(name);
+ }
+
+ public virtual Object GetObject(String name, bool ignoreCase)
+ {
+ Object obj = GetObjectInternal(name);
+
+ if (obj != null || !ignoreCase)
+ return obj;
+
+ return GetCaseInsensitiveObjectInternal(name);
+ }
+
+ protected virtual void ReadResources()
+ {
+ IDictionaryEnumerator en = Reader.GetEnumerator();
+ while (en.MoveNext()) {
+ Object value = en.Value;
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ if (Assembly != null && value is LooselyLinkedResourceReference) {
+ LooselyLinkedResourceReference assRef = (LooselyLinkedResourceReference) value;
+ value = assRef.Resolve(Assembly);
+ }
+#endif //LOOSELYLINKEDRESOURCEREFERENCE
+ Table.Add(en.Key, value);
+ }
+ // While technically possible to close the Reader here, don't close it
+ // to help with some WinRes lifetime issues.
+ }
+
+ private Object GetObjectInternal(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+
+ return copyOfTable[name];
+ }
+
+ private Object GetCaseInsensitiveObjectInternal(String name)
+ {
+ Hashtable copyOfTable = Table; // Avoid a race with Dispose
+
+ if (copyOfTable == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+
+ Hashtable caseTable = _caseInsensitiveTable; // Avoid a race condition with Close
+ if (caseTable == null)
+ {
+ caseTable = new Hashtable(StringComparer.OrdinalIgnoreCase);
+#if _DEBUG
+ //Console.WriteLine("ResourceSet::GetObject loading up case-insensitive data");
+ BCLDebug.Perf(false, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing "+name+" correctly in your source");
+#endif
+
+ IDictionaryEnumerator en = copyOfTable.GetEnumerator();
+ while (en.MoveNext())
+ {
+ caseTable.Add(en.Key, en.Value);
+ }
+ _caseInsensitiveTable = caseTable;
+ }
+
+ return caseTable[name];
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/ResourceTypeCode.cs b/src/mscorlib/src/System/Resources/ResourceTypeCode.cs
new file mode 100644
index 0000000000..64fb076eb5
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/ResourceTypeCode.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Marker for types in .resources files
+**
+**
+===========================================================*/
+
+namespace System.Resources {
+ /* An internal implementation detail for .resources files, describing
+ what type an object is.
+ Ranges:
+ 0 - 0x1F Primitives and reserved values
+ 0x20 - 0x3F Specially recognized types, like byte[] and Streams
+
+ Note this data must be included in any documentation describing the
+ internals of .resources files.
+ */
+ [Serializable]
+ internal enum ResourceTypeCode {
+ // Primitives
+ Null = 0,
+ String = 1,
+ Boolean = 2,
+ Char = 3,
+ Byte = 4,
+ SByte = 5,
+ Int16 = 6,
+ UInt16 = 7,
+ Int32 = 8,
+ UInt32 = 9,
+ Int64 = 0xa,
+ UInt64 = 0xb,
+ Single = 0xc,
+ Double = 0xd,
+ Decimal = 0xe,
+ DateTime = 0xf,
+ TimeSpan = 0x10,
+
+ // A meta-value - change this if you add new primitives
+ LastPrimitive = TimeSpan,
+
+ // Types with a special representation, like byte[] and Stream
+ ByteArray = 0x20,
+ Stream = 0x21,
+
+ // User types - serialized using the binary formatter.
+ StartOfUserTypes = 0x40
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs b/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs
new file mode 100644
index 0000000000..6b512bcf6a
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/RuntimeResourceSet.cs
@@ -0,0 +1,435 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: CultureInfo-specific collection of resources.
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.IO;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Reflection;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // A RuntimeResourceSet stores all the resources defined in one
+ // particular CultureInfo, with some loading optimizations.
+ //
+ // It is expected that nearly all the runtime's users will be satisfied with the
+ // default resource file format, and it will be more efficient than most simple
+ // implementations. Users who would consider creating their own ResourceSets and/or
+ // ResourceReaders and ResourceWriters are people who have to interop with a
+ // legacy resource file format, are creating their own resource file format
+ // (using XML, for instance), or require doing resource lookups at runtime over
+ // the network. This group will hopefully be small, but all the infrastructure
+ // should be in place to let these users write & plug in their own tools.
+ //
+ // The Default Resource File Format
+ //
+ // The fundamental problems addressed by the resource file format are:
+ //
+ // * Versioning - A ResourceReader could in theory support many different
+ // file format revisions.
+ // * Storing intrinsic datatypes (ie, ints, Strings, DateTimes, etc) in a compact
+ // format
+ // * Support for user-defined classes - Accomplished using Serialization
+ // * Resource lookups should not require loading an entire resource file - If you
+ // look up a resource, we only load the value for that resource, minimizing working set.
+ //
+ //
+ // There are four sections to the default file format. The first
+ // is the Resource Manager header, which consists of a magic number
+ // that identifies this as a Resource file, and a ResourceSet class name.
+ // The class name is written here to allow users to provide their own
+ // implementation of a ResourceSet (and a matching ResourceReader) to
+ // control policy. If objects greater than a certain size or matching a
+ // certain naming scheme shouldn't be stored in memory, users can tweak that
+ // with their own subclass of ResourceSet.
+ //
+ // The second section in the system default file format is the
+ // RuntimeResourceSet specific header. This contains a version number for
+ // the .resources file, the number of resources in this file, the number of
+ // different types contained in the file, followed by a list of fully
+ // qualified type names. After this, we include an array of hash values for
+ // each resource name, then an array of virtual offsets into the name section
+ // of the file. The hashes allow us to do a binary search on an array of
+ // integers to find a resource name very quickly without doing many string
+ // compares (except for once we find the real type, of course). If a hash
+ // matches, the index into the array of hash values is used as the index
+ // into the name position array to find the name of the resource. The type
+ // table allows us to read multiple different classes from the same file,
+ // including user-defined types, in a more efficient way than using
+ // Serialization, at least when your .resources file contains a reasonable
+ // proportion of base data types such as Strings or ints. We use
+ // Serialization for all the non-instrinsic types.
+ //
+ // The third section of the file is the name section. It contains a
+ // series of resource names, written out as byte-length prefixed little
+ // endian Unicode strings (UTF-16). After each name is a four byte virtual
+ // offset into the data section of the file, pointing to the relevant
+ // string or serialized blob for this resource name.
+ //
+ // The fourth section in the file is the data section, which consists
+ // of a type and a blob of bytes for each item in the file. The type is
+ // an integer index into the type table. The data is specific to that type,
+ // but may be a number written in binary format, a String, or a serialized
+ // Object.
+ //
+ // The system default file format (V1) is as follows:
+ //
+ // What Type of Data
+ // ==================================================== ===========
+ //
+ // Resource Manager header
+ // Magic Number (0xBEEFCACE) Int32
+ // Resource Manager header version Int32
+ // Num bytes to skip from here to get past this header Int32
+ // Class name of IResourceReader to parse this file String
+ // Class name of ResourceSet to parse this file String
+ //
+ // RuntimeResourceReader header
+ // ResourceReader version number Int32
+ // [Only in debug V2 builds - "***DEBUG***"] String
+ // Number of resources in the file Int32
+ // Number of types in the type table Int32
+ // Name of each type Set of Strings
+ // Padding bytes for 8-byte alignment (use PAD) Bytes (0-7)
+ // Hash values for each resource name Int32 array, sorted
+ // Virtual offset of each resource name Int32 array, coupled with hash values
+ // Absolute location of Data section Int32
+ //
+ // RuntimeResourceReader Name Section
+ // Name & virtual offset of each resource Set of (UTF-16 String, Int32) pairs
+ //
+ // RuntimeResourceReader Data Section
+ // Type and Value of each resource Set of (Int32, blob of bytes) pairs
+ //
+ // This implementation, when used with the default ResourceReader class,
+ // loads only the strings that you look up for. It can do string comparisons
+ // without having to create a new String instance due to some memory mapped
+ // file optimizations in the ResourceReader and FastResourceComparer
+ // classes. This keeps the memory we touch to a minimum when loading
+ // resources.
+ //
+ // If you use a different IResourceReader class to read a file, or if you
+ // do case-insensitive lookups (and the case-sensitive lookup fails) then
+ // we will load all the names of each resource and each resource value.
+ // This could probably use some optimization.
+ //
+ // In addition, this supports object serialization in a similar fashion.
+ // We build an array of class types contained in this file, and write it
+ // to RuntimeResourceReader header section of the file. Every resource
+ // will contain its type (as an index into the array of classes) with the data
+ // for that resource. We will use the Runtime's serialization support for this.
+ //
+ // All strings in the file format are written with BinaryReader and
+ // BinaryWriter, which writes out the length of the String in bytes as an
+ // Int32 then the contents as Unicode chars encoded in UTF-8. In the name
+ // table though, each resource name is written in UTF-16 so we can do a
+ // string compare byte by byte against the contents of the file, without
+ // allocating objects. Ideally we'd have a way of comparing UTF-8 bytes
+ // directly against a String object, but that may be a lot of work.
+ //
+ // The offsets of each resource string are relative to the beginning
+ // of the Data section of the file. This way, if a tool decided to add
+ // one resource to a file, it would only need to increment the number of
+ // resources, add the hash &amp; location of last byte in the name section
+ // to the array of resource hashes and resource name positions (carefully
+ // keeping these arrays sorted), add the name to the end of the name &amp;
+ // offset list, possibly add the type list of types types (and increase
+ // the number of items in the type table), and add the resource value at
+ // the end of the file. The other offsets wouldn't need to be updated to
+ // reflect the longer header section.
+ //
+ // Resource files are currently limited to 2 gigabytes due to these
+ // design parameters. A future version may raise the limit to 4 gigabytes
+ // by using unsigned integers, or may use negative numbers to load items
+ // out of an assembly manifest. Also, we may try sectioning the resource names
+ // into smaller chunks, each of size sqrt(n), would be substantially better for
+ // resource files containing thousands of resources.
+ //
+ internal sealed class RuntimeResourceSet : ResourceSet, IEnumerable
+ {
+ internal const int Version = 2; // File format version number
+
+ // Cache for resources. Key is the resource name, which can be cached
+ // for arbitrarily long times, since the object is usually a string
+ // literal that will live for the lifetime of the appdomain. The
+ // value is a ResourceLocator instance, which might cache the object.
+ private Dictionary<String, ResourceLocator> _resCache;
+
+
+ // For our special load-on-demand reader, cache the cast. The
+ // RuntimeResourceSet's implementation knows how to treat this reader specially.
+ private ResourceReader _defaultReader;
+
+ // This is a lookup table for case-insensitive lookups, and may be null.
+ // Consider always using a case-insensitive resource cache, as we don't
+ // want to fill this out if we can avoid it. The problem is resource
+ // fallback will somewhat regularly cause us to look up resources that
+ // don't exist.
+ private Dictionary<String, ResourceLocator> _caseInsensitiveTable;
+
+ // If we're not using our custom reader, then enumerate through all
+ // the resources once, adding them into the table.
+ private bool _haveReadFromReader;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeResourceSet(String fileName) : base(false)
+ {
+ BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(String)");
+ _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
+ _defaultReader = new ResourceReader(stream, _resCache);
+ Reader = _defaultReader;
+ }
+
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ internal RuntimeResourceSet(Stream stream, Assembly assembly) : base(false)
+ {
+ BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(Stream)");
+ _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _defaultReader = new ResourceReader(stream, _resCache);
+ Reader = _defaultReader;
+ Assembly = assembly;
+ }
+#else
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeResourceSet(Stream stream) : base(false)
+ {
+ BCLDebug.Log("RESMGRFILEFORMAT", "RuntimeResourceSet .ctor(Stream)");
+ _resCache = new Dictionary<String, ResourceLocator>(FastResourceComparer.Default);
+ _defaultReader = new ResourceReader(stream, _resCache);
+ Reader = _defaultReader;
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ protected override void Dispose(bool disposing)
+ {
+ if (Reader == null)
+ return;
+
+ if (disposing) {
+ lock(Reader) {
+ _resCache = null;
+ if (_defaultReader != null) {
+ _defaultReader.Close();
+ _defaultReader = null;
+ }
+ _caseInsensitiveTable = null;
+ // Set Reader to null to avoid a race in GetObject.
+ base.Dispose(disposing);
+ }
+ }
+ else {
+ // Just to make sure we always clear these fields in the future...
+ _resCache = null;
+ _caseInsensitiveTable = null;
+ _defaultReader = null;
+ base.Dispose(disposing);
+ }
+ }
+
+ public override IDictionaryEnumerator GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return GetEnumeratorHelper();
+ }
+
+ private IDictionaryEnumerator GetEnumeratorHelper()
+ {
+ IResourceReader copyOfReader = Reader;
+ if (copyOfReader == null || _resCache == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+
+ return copyOfReader.GetEnumerator();
+ }
+
+
+ public override String GetString(String key)
+ {
+ Object o = GetObject(key, false, true);
+ return (String) o;
+ }
+
+ public override String GetString(String key, bool ignoreCase)
+ {
+ Object o = GetObject(key, ignoreCase, true);
+ return (String) o;
+ }
+
+ public override Object GetObject(String key)
+ {
+ return GetObject(key, false, false);
+ }
+
+ public override Object GetObject(String key, bool ignoreCase)
+ {
+ return GetObject(key, ignoreCase, false);
+ }
+
+ private Object GetObject(String key, bool ignoreCase, bool isString)
+ {
+ if (key==null)
+ throw new ArgumentNullException("key");
+ if (Reader == null || _resCache == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+ Contract.EndContractBlock();
+
+ Object value = null;
+ ResourceLocator resLocation;
+
+ lock(Reader) {
+ if (Reader == null)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_ResourceSet"));
+
+ if (_defaultReader != null) {
+ BCLDebug.Log("RESMGRFILEFORMAT", "Going down fast path in RuntimeResourceSet::GetObject");
+
+ // Find the offset within the data section
+ int dataPos = -1;
+ if (_resCache.TryGetValue(key, out resLocation)) {
+ value = resLocation.Value;
+ dataPos = resLocation.DataPosition;
+ }
+
+ if (dataPos == -1 && value == null) {
+ dataPos = _defaultReader.FindPosForResource(key);
+ }
+
+ if (dataPos != -1 && value == null) {
+ Contract.Assert(dataPos >= 0, "data section offset cannot be negative!");
+ // Normally calling LoadString or LoadObject requires
+ // taking a lock. Note that in this case, we took a
+ // lock on the entire RuntimeResourceSet, which is
+ // sufficient since we never pass this ResourceReader
+ // to anyone else.
+ ResourceTypeCode typeCode;
+ if (isString) {
+ value = _defaultReader.LoadString(dataPos);
+ typeCode = ResourceTypeCode.String;
+ }
+ else {
+ value = _defaultReader.LoadObject(dataPos, out typeCode);
+ }
+
+ resLocation = new ResourceLocator(dataPos, (ResourceLocator.CanCache(typeCode)) ? value : null);
+ lock(_resCache) {
+ _resCache[key] = resLocation;
+ }
+ }
+
+ if (value != null || !ignoreCase) {
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ if (Assembly != null && (value is LooselyLinkedResourceReference)) {
+ LooselyLinkedResourceReference assRef = (LooselyLinkedResourceReference) value;
+ value = assRef.Resolve(Assembly);
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+
+ return value; // may be null
+ }
+ } // if (_defaultReader != null)
+
+ // At this point, we either don't have our default resource reader
+ // or we haven't found the particular resource we're looking for
+ // and may have to search for it in a case-insensitive way.
+ if (!_haveReadFromReader) {
+ // If necessary, init our case insensitive hash table.
+ if (ignoreCase && _caseInsensitiveTable == null) {
+ _caseInsensitiveTable = new Dictionary<String, ResourceLocator>(StringComparer.OrdinalIgnoreCase);
+ }
+#if _DEBUG
+ BCLDebug.Perf(!ignoreCase, "Using case-insensitive lookups is bad perf-wise. Consider capitalizing "+key+" correctly in your source");
+#endif
+
+ if (_defaultReader == null) {
+ IDictionaryEnumerator en = Reader.GetEnumerator();
+ while (en.MoveNext()) {
+ DictionaryEntry entry = en.Entry;
+ String readKey = (String) entry.Key;
+ ResourceLocator resLoc = new ResourceLocator(-1, entry.Value);
+ _resCache.Add(readKey, resLoc);
+ if (ignoreCase)
+ _caseInsensitiveTable.Add(readKey, resLoc);
+ }
+ // Only close the reader if it is NOT our default one,
+ // since we need it around to resolve ResourceLocators.
+ if (!ignoreCase)
+ Reader.Close();
+ }
+ else {
+ Contract.Assert(ignoreCase, "This should only happen for case-insensitive lookups");
+ ResourceReader.ResourceEnumerator en = _defaultReader.GetEnumeratorInternal();
+ while (en.MoveNext()) {
+ // Note: Always ask for the resource key before the data position.
+ String currentKey = (String) en.Key;
+ int dataPos = en.DataPosition;
+ ResourceLocator resLoc = new ResourceLocator(dataPos, null);
+ _caseInsensitiveTable.Add(currentKey, resLoc);
+ }
+ }
+ _haveReadFromReader = true;
+ }
+ Object obj = null;
+ bool found = false;
+ bool keyInWrongCase = false;
+ if (_defaultReader != null) {
+ if (_resCache.TryGetValue(key, out resLocation)) {
+ found = true;
+ obj = ResolveResourceLocator(resLocation, key, _resCache, keyInWrongCase);
+ }
+ }
+ if (!found && ignoreCase) {
+ if (_caseInsensitiveTable.TryGetValue(key, out resLocation)) {
+ found = true;
+ keyInWrongCase = true;
+ obj = ResolveResourceLocator(resLocation, key, _resCache, keyInWrongCase);
+ }
+ }
+ return obj;
+ } // lock(Reader)
+ }
+
+ // The last parameter indicates whether the lookup required a
+ // case-insensitive lookup to succeed, indicating we shouldn't add
+ // the ResourceLocation to our case-sensitive cache.
+ private Object ResolveResourceLocator(ResourceLocator resLocation, String key, Dictionary<String, ResourceLocator> copyOfCache, bool keyInWrongCase)
+ {
+ // We need to explicitly resolve loosely linked manifest
+ // resources, and we need to resolve ResourceLocators with null objects.
+ Object value = resLocation.Value;
+ if (value == null) {
+ ResourceTypeCode typeCode;
+ lock(Reader) {
+ value = _defaultReader.LoadObject(resLocation.DataPosition, out typeCode);
+ }
+ if (!keyInWrongCase && ResourceLocator.CanCache(typeCode)) {
+ resLocation.Value = value;
+ copyOfCache[key] = resLocation;
+ }
+ }
+#if LOOSELY_LINKED_RESOURCE_REFERENCE
+ if (Assembly != null && value is LooselyLinkedResourceReference) {
+ LooselyLinkedResourceReference assRef = (LooselyLinkedResourceReference) value;
+ value = assRef.Resolve(Assembly);
+ }
+#endif // LOOSELY_LINKED_RESOURCE_REFERENCE
+ return value;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs b/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs
new file mode 100644
index 0000000000..f72e810227
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/SatelliteContractVersionAttribute.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Specifies which version of a satellite assembly
+** the ResourceManager should ask for.
+**
+**
+===========================================================*/
+
+namespace System.Resources {
+ using System;
+ using System.Diagnostics.Contracts;
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SatelliteContractVersionAttribute : Attribute
+ {
+ private String _version;
+
+ public SatelliteContractVersionAttribute(String version)
+ {
+ if (version == null)
+ throw new ArgumentNullException("version");
+ Contract.EndContractBlock();
+ _version = version;
+ }
+
+ public String Version {
+ get { return _version; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/UltimateResourceFallbackLocation.cs b/src/mscorlib/src/System/Resources/UltimateResourceFallbackLocation.cs
new file mode 100644
index 0000000000..5785bfd357
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/UltimateResourceFallbackLocation.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+**
+** Purpose: Tells the ResourceManager where to find the
+** ultimate fallback resources for your assembly.
+**
+**
+===========================================================*/
+
+using System;
+
+namespace System.Resources {
+
+[Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum UltimateResourceFallbackLocation
+ {
+ MainAssembly,
+ Satellite
+ }
+}
diff --git a/src/mscorlib/src/System/Resources/__FastResourceComparer.cs b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs
new file mode 100644
index 0000000000..5bc7333863
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/__FastResourceComparer.cs
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: A collection of quick methods for comparing
+** resource keys (strings)
+**
+**
+===========================================================*/
+namespace System.Resources {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComparer<String>, IEqualityComparer<String>
+ {
+ internal static readonly FastResourceComparer Default = new FastResourceComparer();
+
+ // Implements IHashCodeProvider too, due to Hashtable requirements.
+ public int GetHashCode(Object key)
+ {
+ String s = (String) key;
+ return FastResourceComparer.HashFunction(s);
+ }
+
+ public int GetHashCode(String key)
+ {
+ return FastResourceComparer.HashFunction(key);
+ }
+
+ // This hash function MUST be publically documented with the resource
+ // file format, AND we may NEVER change this hash function's return
+ // value (without changing the file format).
+ internal static int HashFunction(String key)
+ {
+ // Never change this hash function. We must standardize it so that
+ // others can read & write our .resources files. Additionally, we
+ // have a copy of it in InternalResGen as well.
+ uint hash = 5381;
+ for(int i=0; i<key.Length; i++)
+ hash = ((hash << 5) + hash) ^ key[i];
+ return (int) hash;
+ }
+
+ // Compares Strings quickly in a case-sensitive way
+ public int Compare(Object a, Object b)
+ {
+ if (a == b) return 0;
+ String sa = (String)a;
+ String sb = (String)b;
+ return String.CompareOrdinal(sa, sb);
+ }
+
+ public int Compare(String a, String b)
+ {
+ return String.CompareOrdinal(a, b);
+ }
+
+ public bool Equals(String a, String b)
+ {
+ return String.Equals(a, b);
+ }
+
+ public new bool Equals(Object a, Object b)
+ {
+ if (a == b) return true;
+ String sa = (String)a;
+ String sb = (String)b;
+ return String.Equals(sa,sb);
+ }
+
+ // Input is one string to compare with, and a byte[] containing chars in
+ // little endian unicode. Pass in the number of valid chars.
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe static int CompareOrdinal(String a, byte[] bytes, int bCharLength)
+ {
+ Contract.Assert(a != null && bytes != null, "FastResourceComparer::CompareOrdinal must have non-null params");
+ Contract.Assert(bCharLength * 2 <= bytes.Length, "FastResourceComparer::CompareOrdinal - numChars is too big!");
+ // This is a managed version of strcmp, but I can't take advantage
+ // of a terminating 0, unlike strcmp in C.
+ int i = 0;
+ int r = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = a.Length;
+ if (numChars > bCharLength)
+ numChars = bCharLength;
+ if (bCharLength == 0) // Can't use fixed on a 0-element array.
+ return (a.Length == 0) ? 0 : -1;
+ fixed(byte* pb = bytes) {
+
+ byte *pChar = pb;
+ while (i < numChars && r == 0) {
+ // little endian format
+ int b = pChar[0] | pChar[1] << 8;
+ r = a[i++] - b;
+ pChar += sizeof(char);
+ }
+ }
+ if (r != 0) return r;
+ return a.Length - bCharLength;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public static int CompareOrdinal(byte[] bytes, int aCharLength, String b)
+ {
+ return -CompareOrdinal(b, bytes, aCharLength);
+ }
+
+ // This method is to handle potentially misaligned data accesses.
+ // The byte* must point to little endian Unicode characters.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static int CompareOrdinal(byte* a, int byteLen, String b)
+ {
+ Contract.Assert((byteLen & 1) == 0, "CompareOrdinal is expecting a UTF-16 string length, which must be even!");
+ Contract.Assert(a != null && b != null, "Null args not allowed.");
+ Contract.Assert(byteLen >= 0, "byteLen must be non-negative.");
+
+ int r = 0;
+ int i = 0;
+ // Compare the min length # of characters, then return length diffs.
+ int numChars = byteLen >> 1;
+ if (numChars > b.Length)
+ numChars = b.Length;
+ while(i < numChars && r == 0) {
+ // Must compare character by character, not byte by byte.
+ char aCh = (char) (*a++ | (*a++ << 8));
+ r = aCh - b[i++];
+ }
+ if (r != 0) return r;
+ return byteLen - b.Length * 2;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Resources/__HResults.cs b/src/mscorlib/src/System/Resources/__HResults.cs
new file mode 100644
index 0000000000..c1546edc63
--- /dev/null
+++ b/src/mscorlib/src/System/Resources/__HResults.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//=============================================================================
+//
+//
+//
+// Purpose: Define HResult constants returned by the Windows Modern Resource Manager
+// and consumed by System.Resources.ResourceManager.
+//
+//===========================================================================*/
+#if FEATURE_APPX
+namespace System.Resources {
+ using System;
+ // Only static data no need to serialize
+ internal static class __HResults
+ {
+ // From WinError.h
+ public const int ERROR_MRM_MAP_NOT_FOUND = unchecked((int)0x80073B1F);
+ }
+}
+#endif
diff --git a/src/mscorlib/src/System/RtType.cs b/src/mscorlib/src/System/RtType.cs
new file mode 100644
index 0000000000..037576fc33
--- /dev/null
+++ b/src/mscorlib/src/System/RtType.cs
@@ -0,0 +1,5862 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements System.RuntimeType
+//
+// ======================================================================================
+
+
+using System;
+using System.Reflection;
+using System.Runtime.ConstrainedExecution;
+using System.Globalization;
+using System.Threading;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime;
+using System.Runtime.Serialization;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Text;
+using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+using System.Runtime.Remoting.Proxies;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+using System.Runtime.Remoting.Metadata;
+#endif
+using MdSigCallingConvention = System.Signature.MdSigCallingConvention;
+using RuntimeTypeCache = System.RuntimeType.RuntimeTypeCache;
+using System.Runtime.InteropServices;
+using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
+using MdToken = System.Reflection.MetadataToken;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+namespace System
+{
+ // this is a work around to get the concept of a calli. It's not as fast but it would be interesting to
+ // see how it compares to the current implementation.
+ // This delegate will disappear at some point in favor of calli
+
+ internal delegate void CtorDelegate(Object instance);
+
+ // Keep this in sync with FormatFlags defined in typestring.h
+ internal enum TypeNameFormatFlags
+ {
+ FormatBasic = 0x00000000, // Not a bitmask, simply the tersest flag settings possible
+ FormatNamespace = 0x00000001, // Include namespace and/or enclosing class names in type names
+ FormatFullInst = 0x00000002, // Include namespace and assembly in generic types (regardless of other flag settings)
+ FormatAssembly = 0x00000004, // Include assembly display name in type names
+ FormatSignature = 0x00000008, // Include signature in method names
+ FormatNoVersion = 0x00000010, // Suppress version and culture information in all assembly names
+#if _DEBUG
+ FormatDebug = 0x00000020, // For debug printing of types only
+#endif
+ FormatAngleBrackets = 0x00000040, // Whether generic types are C<T> or C[T]
+ FormatStubInfo = 0x00000080, // Include stub info like {unbox-stub}
+ FormatGenericParam = 0x00000100, // Use !name and !!name for generic type and method parameters
+
+ // If we want to be able to distinguish between overloads whose parameter types have the same name but come from different assemblies,
+ // we can add FormatAssembly | FormatNoVersion to FormatSerialization. But we are omitting it because it is not a useful scenario
+ // and including the assembly name will normally increase the size of the serialized data and also decrease the performance.
+ FormatSerialization = FormatNamespace |
+ FormatGenericParam |
+ FormatFullInst
+ }
+
+ internal enum TypeNameKind
+ {
+ Name,
+ ToString,
+ SerializationName,
+ FullName,
+ }
+
+ [Serializable]
+ internal class RuntimeType :
+ System.Reflection.TypeInfo, ISerializable, ICloneable
+ {
+ #region Definitions
+
+ internal enum MemberListType
+ {
+ All,
+ CaseSensitive,
+ CaseInsensitive,
+ HandleToInfo
+ }
+
+ // Helper to build lists of MemberInfos. Special cased to avoid allocations for lists of one element.
+ private struct ListBuilder<T> where T : class
+ {
+ T[] _items;
+ T _item;
+ int _count;
+ int _capacity;
+
+ public ListBuilder(int capacity)
+ {
+ _items = null;
+ _item = null;
+ _count = 0;
+ _capacity = capacity;
+ }
+
+ public T this[int index]
+ {
+ get
+ {
+ Contract.Requires(index < Count);
+ return (_items != null) ? _items[index] : _item;
+ }
+ }
+
+ public T[] ToArray()
+ {
+ if (_count == 0)
+ return EmptyArray<T>.Value;
+ if (_count == 1)
+ return new T[1] { _item };
+
+ Array.Resize(ref _items, _count);
+ _capacity = _count;
+ return _items;
+ }
+
+ public void CopyTo(Object[] array, int index)
+ {
+ if (_count == 0)
+ return;
+
+ if (_count == 1)
+ {
+ array[index] = _item;
+ return;
+ }
+
+ Array.Copy(_items, 0, array, index, _count);
+ }
+
+ public int Count
+ {
+ get
+ {
+ return _count;
+ }
+ }
+
+ public void Add(T item)
+ {
+ if (_count == 0)
+ {
+ _item = item;
+ }
+ else
+ {
+ if (_count == 1)
+ {
+ if (_capacity < 2)
+ _capacity = 4;
+ _items = new T[_capacity];
+ _items[0] = _item;
+ }
+ else
+ if (_capacity == _count)
+ {
+ int newCapacity = 2 * _capacity;
+ Array.Resize(ref _items, newCapacity);
+ _capacity = newCapacity;
+ }
+
+ _items[_count] = item;
+ }
+ _count++;
+ }
+ }
+
+ internal class RuntimeTypeCache
+ {
+ private const int MAXNAMELEN = 1024;
+
+ #region Definitions
+ internal enum CacheType
+ {
+ Method,
+ Constructor,
+ Field,
+ Property,
+ Event,
+ Interface,
+ NestedType
+ }
+
+ private struct Filter
+ {
+ private Utf8String m_name;
+ private MemberListType m_listType;
+ private uint m_nameHash;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe Filter(byte* pUtf8Name, int cUtf8Name, MemberListType listType)
+ {
+ this.m_name = new Utf8String((void*) pUtf8Name, cUtf8Name);
+ this.m_listType = listType;
+ this.m_nameHash = 0;
+
+ if (RequiresStringComparison())
+ {
+ m_nameHash = m_name.HashCaseInsensitive();
+ }
+ }
+
+ public bool Match(Utf8String name)
+ {
+ bool retVal = true;
+
+ if (m_listType == MemberListType.CaseSensitive)
+ retVal = m_name.Equals(name);
+ else if (m_listType == MemberListType.CaseInsensitive)
+ retVal = m_name.EqualsCaseInsensitive(name);
+
+ // Currently the callers of UsesStringComparison assume that if it returns false
+ // then the match always succeeds and can be skipped. Assert that this is maintained.
+ Contract.Assert(retVal || RequiresStringComparison());
+
+ return retVal;
+ }
+
+ // Does the current match type require a string comparison?
+ // If not, we know Match will always return true and the call can be skipped
+ // If so, we know we can have a valid hash to check against from GetHashToMatch
+ public bool RequiresStringComparison()
+ {
+ return (m_listType == MemberListType.CaseSensitive) ||
+ (m_listType == MemberListType.CaseInsensitive);
+ }
+
+ public bool CaseSensitive()
+ {
+ return (m_listType == MemberListType.CaseSensitive);
+ }
+
+ public uint GetHashToMatch()
+ {
+ Contract.Assert(RequiresStringComparison());
+
+ return m_nameHash;
+ }
+ }
+
+ private class MemberInfoCache<T> where T : MemberInfo
+ {
+ #region Private Data Members
+
+ // MemberInfo caches
+ private CerHashtable<string, T[]> m_csMemberInfos;
+ private CerHashtable<string, T[]> m_cisMemberInfos;
+ // List of MemberInfos given out. When m_cacheComplete is false, it may have null entries at the end to avoid
+ // reallocating the list every time a new entry is added.
+ private T[] m_allMembers;
+ private bool m_cacheComplete;
+
+ // This is the strong reference back to the cache
+ private RuntimeTypeCache m_runtimeTypeCache;
+ #endregion
+
+ #region Constructor
+#if MDA_SUPPORTED
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ internal MemberInfoCache(RuntimeTypeCache runtimeTypeCache)
+ {
+#if MDA_SUPPORTED
+ Mda.MemberInfoCacheCreation();
+#endif
+ m_runtimeTypeCache = runtimeTypeCache;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal MethodBase AddMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method, CacheType cacheType)
+ {
+ T[] list = null;
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(method);
+ bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
+ bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
+ bool isInherited = declaringType != ReflectedType;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ switch (cacheType)
+ {
+ case CacheType.Method:
+ list = (T[])(object)new RuntimeMethodInfo[1] {
+ new RuntimeMethodInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null)
+ };
+ break;
+ case CacheType.Constructor:
+ list = (T[])(object)new RuntimeConstructorInfo[1] {
+ new RuntimeConstructorInfo(method, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags)
+ };
+ break;
+ }
+
+ Insert(ref list, null, MemberListType.HandleToInfo);
+
+ return (MethodBase)(object)list[0];
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal FieldInfo AddField(RuntimeFieldHandleInternal field)
+ {
+ // create the runtime field info
+ FieldAttributes fieldAttributes = RuntimeFieldHandle.GetAttributes(field);
+ bool isPublic = (fieldAttributes & FieldAttributes.FieldAccessMask) == FieldAttributes.Public;
+ bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
+ RuntimeType approxDeclaringType = RuntimeFieldHandle.GetApproxDeclaringType(field);
+ bool isInherited = RuntimeFieldHandle.AcquiresContextFromThis(field) ?
+ !RuntimeTypeHandle.CompareCanonicalHandles(approxDeclaringType, ReflectedType) :
+ approxDeclaringType != ReflectedType;
+
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+
+ T[] list = (T[])(object)new RuntimeFieldInfo[1] {
+ new RtFieldInfo(field, ReflectedType, m_runtimeTypeCache, bindingFlags)
+ };
+
+ Insert(ref list, null, MemberListType.HandleToInfo);
+
+ return (FieldInfo)(object)list[0];
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe T[] Populate(string name, MemberListType listType, CacheType cacheType)
+ {
+ T[] list = null;
+
+ if (name == null || name.Length == 0 ||
+ (cacheType == CacheType.Constructor && name.FirstChar != '.' && name.FirstChar != '*'))
+ {
+ list = GetListByName(null, 0, null, 0, listType, cacheType);
+ }
+ else
+ {
+ int cNameLen = name.Length;
+ fixed (char* pName = name)
+ {
+ int cUtf8Name = Encoding.UTF8.GetByteCount(pName, cNameLen);
+ // allocating on the stack is faster than allocating on the GC heap
+ // but we surely don't want to cause a stack overflow
+ // no one should be looking for a member whose name is longer than 1024
+ if (cUtf8Name > MAXNAMELEN)
+ {
+ fixed (byte* pUtf8Name = new byte[cUtf8Name])
+ {
+ list = GetListByName(pName, cNameLen, pUtf8Name, cUtf8Name, listType, cacheType);
+ }
+ }
+ else
+ {
+ byte* pUtf8Name = stackalloc byte[cUtf8Name];
+ list = GetListByName(pName, cNameLen, pUtf8Name, cUtf8Name, listType, cacheType);
+ }
+ }
+ }
+
+ Insert(ref list, name, listType);
+
+ return list;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe T[] GetListByName(char* pName, int cNameLen, byte* pUtf8Name, int cUtf8Name, MemberListType listType, CacheType cacheType)
+ {
+ if (cNameLen != 0)
+ Encoding.UTF8.GetBytes(pName, cNameLen, pUtf8Name, cUtf8Name);
+
+ Filter filter = new Filter(pUtf8Name, cUtf8Name, listType);
+ Object list = null;
+
+ switch (cacheType)
+ {
+ case CacheType.Method:
+ list = PopulateMethods(filter);
+ break;
+ case CacheType.Field:
+ list = PopulateFields(filter);
+ break;
+ case CacheType.Constructor:
+ list = PopulateConstructors(filter);
+ break;
+ case CacheType.Property:
+ list = PopulateProperties(filter);
+ break;
+ case CacheType.Event:
+ list = PopulateEvents(filter);
+ break;
+ case CacheType.NestedType:
+ list = PopulateNestedClasses(filter);
+ break;
+ case CacheType.Interface:
+ list = PopulateInterfaces(filter);
+ break;
+ default:
+ BCLDebug.Assert(false, "Invalid CacheType");
+ break;
+ }
+
+ return (T[])list;
+ }
+
+ // May replace the list with a new one if certain cache
+ // lookups succeed. Also, may modify the contents of the list
+ // after merging these new data structures with cached ones.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal void Insert(ref T[] list, string name, MemberListType listType)
+ {
+ bool lockTaken = false;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref lockTaken);
+
+ switch (listType)
+ {
+ case MemberListType.CaseSensitive:
+ {
+ // Ensure we always return a list that has
+ // been merged with the global list.
+ T[] cachedList = m_csMemberInfos[name];
+ if (cachedList == null)
+ {
+ MergeWithGlobalList(list);
+ m_csMemberInfos[name] = list;
+ }
+ else
+ list = cachedList;
+ }
+ break;
+
+ case MemberListType.CaseInsensitive:
+ {
+ // Ensure we always return a list that has
+ // been merged with the global list.
+ T[] cachedList = m_cisMemberInfos[name];
+ if (cachedList == null)
+ {
+ MergeWithGlobalList(list);
+ m_cisMemberInfos[name] = list;
+ }
+ else
+ list = cachedList;
+ }
+ break;
+
+ case MemberListType.All:
+ if (!m_cacheComplete)
+ {
+ MergeWithGlobalList(list);
+
+ // Trim null entries at the end of m_allMembers array
+ int memberCount = m_allMembers.Length;
+ while (memberCount > 0)
+ {
+ if (m_allMembers[memberCount-1] != null)
+ break;
+ memberCount--;
+ }
+ Array.Resize(ref m_allMembers, memberCount);
+
+ Volatile.Write(ref m_cacheComplete, true);
+ }
+ else
+ list = m_allMembers;
+ break;
+
+ default:
+ MergeWithGlobalList(list);
+ break;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ {
+ Monitor.Exit(this);
+ }
+ }
+ }
+
+ // Modifies the existing list.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private void MergeWithGlobalList(T[] list)
+ {
+ T[] cachedMembers = m_allMembers;
+
+ if (cachedMembers == null)
+ {
+ m_allMembers = list;
+ return;
+ }
+
+ int cachedCount = cachedMembers.Length;
+ int freeSlotIndex = 0;
+
+ for (int i = 0; i < list.Length; i++)
+ {
+ T newMemberInfo = list[i];
+ bool foundInCache = false;
+
+ int cachedIndex;
+ for (cachedIndex = 0; cachedIndex < cachedCount; cachedIndex++)
+ {
+ T cachedMemberInfo = cachedMembers[cachedIndex];
+ if (cachedMemberInfo == null)
+ break;
+
+ if (newMemberInfo.CacheEquals(cachedMemberInfo))
+ {
+ list[i] = cachedMemberInfo;
+ foundInCache = true;
+ break;
+ }
+ }
+
+ if (!foundInCache)
+ {
+ if (freeSlotIndex == 0)
+ freeSlotIndex = cachedIndex;
+
+ if (freeSlotIndex >= cachedMembers.Length)
+ {
+ int newSize;
+ if (m_cacheComplete)
+ {
+ //
+ // In theory, we should never add more elements to the cache when it is complete.
+ //
+ // Unfortunately, we shipped with bugs that cause changes of the complete cache (DevDiv #339308).
+ // Grow the list by exactly one element in this case to avoid null entries at the end.
+ //
+
+ Contract.Assert(false);
+
+ newSize = cachedMembers.Length + 1;
+ }
+ else
+ {
+ newSize = Math.Max(Math.Max(4, 2 * cachedMembers.Length), list.Length);
+ }
+
+ // Use different variable for ref argument to Array.Resize to allow enregistration of cachedMembers by the JIT
+ T[] cachedMembers2 = cachedMembers;
+ Array.Resize(ref cachedMembers2, newSize);
+ cachedMembers = cachedMembers2;
+ }
+
+ Contract.Assert(cachedMembers[freeSlotIndex] == null);
+ cachedMembers[freeSlotIndex] = newMemberInfo;
+ freeSlotIndex++;
+ }
+ }
+
+ m_allMembers = cachedMembers;
+ }
+ #endregion
+
+ #region Population Logic
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeMethodInfo[] PopulateMethods(Filter filter)
+ {
+ ListBuilder<RuntimeMethodInfo> list = new ListBuilder<RuntimeMethodInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+ Contract.Assert(declaringType != null);
+
+ if (RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ #region IsInterface
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ #region Loop through all methods on the interface
+ Contract.Assert(!methodHandle.IsNullHandle());
+ // Except for .ctor, .cctor, IL_STUB*, and static methods, all interface methods should be abstract, virtual, and non-RTSpecialName.
+ // Note that this assumption will become invalid when we add support for non-abstract or static methods on interfaces.
+ Contract.Assert(
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & (MethodAttributes.RTSpecialName | MethodAttributes.Abstract | MethodAttributes.Virtual)) == (MethodAttributes.Abstract | MethodAttributes.Virtual) ||
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.Static) == MethodAttributes.Static ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).StartsWith("IL_STUB", StringComparison.Ordinal));
+
+ #region Calculate Binding Flags
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+ bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
+ bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
+ bool isInherited = false;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ #endregion
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) != 0)
+ continue;
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+
+ list.Add(runtimeMethodInfo);
+ #endregion
+ }
+ #endregion
+ }
+ else
+ {
+ #region IsClass or GenericParameter
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ bool* overrides = stackalloc bool[RuntimeTypeHandle.GetNumVirtuals(declaringType)];
+ bool isValueType = declaringType.IsValueType;
+
+ do
+ {
+ int vtableSlots = RuntimeTypeHandle.GetNumVirtuals(declaringType);
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ #region Loop through all methods on the current type
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+ MethodAttributes methodAccess = methodAttributes & MethodAttributes.MemberAccessMask;
+
+ #region Continue if this is a constructor
+ Contract.Assert(
+ (RuntimeMethodHandle.GetAttributes(methodHandle) & MethodAttributes.RTSpecialName) == 0 ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".ctor") ||
+ RuntimeMethodHandle.GetName(methodHandle).Equals(".cctor"));
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) != 0)
+ continue;
+ #endregion
+
+ #region Continue if this is a private declared on a base type
+ bool isVirtual = false;
+ int methodSlot = 0;
+ if ((methodAttributes & MethodAttributes.Virtual) != 0)
+ {
+ // only virtual if actually in the vtableslot range, but GetSlot will
+ // assert if an EnC method, which can't be virtual, so narrow down first
+ // before calling GetSlot
+ methodSlot = RuntimeMethodHandle.GetSlot(methodHandle);
+ isVirtual = (methodSlot < vtableSlots);
+ }
+
+ bool isInherited = declaringType != ReflectedType;
+
+ bool isPrivate = methodAccess == MethodAttributes.Private;
+ if (isInherited && isPrivate && !isVirtual)
+ continue;
+
+ #endregion
+
+ #region Continue if this is a virtual and is already overridden
+ if (isVirtual)
+ {
+ Contract.Assert(
+ (methodAttributes & MethodAttributes.Abstract) != 0 ||
+ (methodAttributes & MethodAttributes.Virtual) != 0 ||
+ RuntimeMethodHandle.GetDeclaringType(methodHandle) != declaringType);
+
+ if (overrides[methodSlot] == true)
+ continue;
+
+ overrides[methodSlot] = true;
+ }
+ else if (isValueType)
+ {
+ if ((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) != 0)
+ continue;
+ }
+ else
+ {
+ Contract.Assert((methodAttributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) == 0);
+ }
+ #endregion
+
+ #region Calculate Binding Flags
+ bool isPublic = methodAccess == MethodAttributes.Public;
+ bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ #endregion
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeMethodInfo runtimeMethodInfo = new RuntimeMethodInfo(
+ instantiatedHandle, declaringType, m_runtimeTypeCache, methodAttributes, bindingFlags, null);
+
+ list.Add(runtimeMethodInfo);
+ #endregion
+ }
+
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ } while (declaringType != null);
+ #endregion
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private RuntimeConstructorInfo[] PopulateConstructors(Filter filter)
+ {
+ if (ReflectedType.IsGenericParameter)
+ {
+ return EmptyArray<RuntimeConstructorInfo>.Value;
+ }
+
+ ListBuilder<RuntimeConstructorInfo> list = new ListBuilder<RuntimeConstructorInfo>();
+
+ RuntimeType declaringType= ReflectedType;
+
+ foreach (RuntimeMethodHandleInternal methodHandle in RuntimeTypeHandle.GetIntroducedMethods(declaringType))
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeMethodHandle.MatchesNameHash(methodHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeMethodHandle.GetUtf8Name(methodHandle)))
+ continue;
+ }
+
+ MethodAttributes methodAttributes = RuntimeMethodHandle.GetAttributes(methodHandle);
+
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ if ((methodAttributes & MethodAttributes.RTSpecialName) == 0)
+ continue;
+
+ // Constructors should not be virtual or abstract
+ Contract.Assert(
+ (methodAttributes & MethodAttributes.Abstract) == 0 &&
+ (methodAttributes & MethodAttributes.Virtual) == 0);
+
+ #region Calculate Binding Flags
+ bool isPublic = (methodAttributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
+ bool isStatic = (methodAttributes & MethodAttributes.Static) != 0;
+ bool isInherited = false;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ #endregion
+
+ // get the unboxing stub or instantiating stub if needed
+ RuntimeMethodHandleInternal instantiatedHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaringType, null);
+
+ RuntimeConstructorInfo runtimeConstructorInfo =
+ new RuntimeConstructorInfo(instantiatedHandle, ReflectedType, m_runtimeTypeCache, methodAttributes, bindingFlags);
+
+ list.Add(runtimeConstructorInfo);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeFieldInfo[] PopulateFields(Filter filter)
+ {
+ ListBuilder<RuntimeFieldInfo> list = new ListBuilder<RuntimeFieldInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+
+ #region Populate all static, instance and literal fields
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ while(declaringType != null)
+ {
+ PopulateRtFields(filter, declaringType, ref list);
+
+ PopulateLiteralFields(filter, declaringType, ref list);
+
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ }
+ #endregion
+
+ #region Populate Literal Fields on Interfaces
+ if (ReflectedType.IsGenericParameter)
+ {
+ Type[] interfaces = ReflectedType.BaseType.GetInterfaces();
+
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ // Populate literal fields defined on any of the interfaces implemented by the declaring type
+ PopulateLiteralFields(filter, (RuntimeType)interfaces[i], ref list);
+ PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
+ }
+ }
+ else
+ {
+ Type[] interfaces = RuntimeTypeHandle.GetInterfaces(ReflectedType);
+
+ if (interfaces != null)
+ {
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ // Populate literal fields defined on any of the interfaces implemented by the declaring type
+ PopulateLiteralFields(filter, (RuntimeType)interfaces[i], ref list);
+ PopulateRtFields(filter, (RuntimeType)interfaces[i], ref list);
+ }
+ }
+ }
+ #endregion
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateRtFields(Filter filter, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ IntPtr* pResult = stackalloc IntPtr[64];
+ int count = 64;
+
+ if (!RuntimeTypeHandle.GetFields(declaringType, pResult, &count))
+ {
+ fixed(IntPtr* pBigResult = new IntPtr[count])
+ {
+ RuntimeTypeHandle.GetFields(declaringType, pBigResult, &count);
+ PopulateRtFields(filter, pBigResult, count, declaringType, ref list);
+ }
+ }
+ else if (count > 0)
+ {
+ PopulateRtFields(filter, pResult, count, declaringType, ref list);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void PopulateRtFields(Filter filter,
+ IntPtr* ppFieldHandles, int count, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ Contract.Requires(declaringType != null);
+ Contract.Requires(ReflectedType != null);
+
+ bool needsStaticFieldForGeneric = RuntimeTypeHandle.HasInstantiation(declaringType) && !RuntimeTypeHandle.ContainsGenericVariables(declaringType);
+ bool isInherited = declaringType != ReflectedType;
+
+ for(int i = 0; i < count; i ++)
+ {
+ RuntimeFieldHandleInternal runtimeFieldHandle = new RuntimeFieldHandleInternal(ppFieldHandles[i]);
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!RuntimeFieldHandle.MatchesNameHash(runtimeFieldHandle, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle)));
+ continue;
+ }
+
+ if (!filter.Match(RuntimeFieldHandle.GetUtf8Name(runtimeFieldHandle)))
+ continue;
+ }
+
+ Contract.Assert(!runtimeFieldHandle.IsNullHandle());
+
+ FieldAttributes fieldAttributes = RuntimeFieldHandle.GetAttributes(runtimeFieldHandle);
+ FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask;
+
+ if (isInherited)
+ {
+ if (fieldAccess == FieldAttributes.Private)
+ continue;
+ }
+
+ #region Calculate Binding Flags
+ bool isPublic = fieldAccess == FieldAttributes.Public;
+ bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ #endregion
+
+ // correct the FieldDesc if needed
+ if (needsStaticFieldForGeneric && isStatic)
+ runtimeFieldHandle = RuntimeFieldHandle.GetStaticFieldForGenericType(runtimeFieldHandle, declaringType);
+
+ RuntimeFieldInfo runtimeFieldInfo =
+ new RtFieldInfo(runtimeFieldHandle, declaringType, m_runtimeTypeCache, bindingFlags);
+
+ list.Add(runtimeFieldInfo);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateLiteralFields(Filter filter, RuntimeType declaringType, ref ListBuilder<RuntimeFieldInfo> list)
+ {
+ Contract.Requires(declaringType != null);
+ Contract.Requires(ReflectedType != null);
+
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Our policy is that TypeDescs do not have metadata tokens
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkFields;
+ scope.EnumFields(tkDeclaringType, out tkFields);
+
+ for (int i = 0; i < tkFields.Length; i++)
+ {
+ int tkField = tkFields[i];
+ Contract.Assert(MdToken.IsTokenOfType(tkField, MetadataTokenType.FieldDef));
+ Contract.Assert(!MdToken.IsNullToken(tkField));
+
+ FieldAttributes fieldAttributes;
+ scope.GetFieldDefProps(tkField, out fieldAttributes);
+
+ FieldAttributes fieldAccess = fieldAttributes & FieldAttributes.FieldAccessMask;
+
+ if ((fieldAttributes & FieldAttributes.Literal) != 0)
+ {
+ bool isInherited = declaringType != ReflectedType;
+ if (isInherited)
+ {
+ bool isPrivate = fieldAccess == FieldAttributes.Private;
+ if (isPrivate)
+ continue;
+ }
+
+ if (filter.RequiresStringComparison())
+ {
+ Utf8String name;
+ name = scope.GetName(tkField);
+
+ if (!filter.Match(name))
+ continue;
+ }
+
+ #region Calculate Binding Flags
+ bool isPublic = fieldAccess == FieldAttributes.Public;
+ bool isStatic = (fieldAttributes & FieldAttributes.Static) != 0;
+ BindingFlags bindingFlags = RuntimeType.FilterPreCalculate(isPublic, isInherited, isStatic);
+ #endregion
+
+ RuntimeFieldInfo runtimeFieldInfo =
+ new MdFieldInfo(tkField, fieldAttributes, declaringType.GetTypeHandleInternal(), m_runtimeTypeCache, bindingFlags);
+
+ list.Add(runtimeFieldInfo);
+ }
+ }
+ }
+
+ private static void AddElementTypes(Type template, IList<Type> types)
+ {
+ if (!template.HasElementType)
+ return;
+
+ AddElementTypes(template.GetElementType(), types);
+
+ for (int i = 0; i < types.Count; i ++)
+ {
+ if (template.IsArray)
+ {
+ if (template.IsSzArray)
+ types[i] = types[i].MakeArrayType();
+ else
+ types[i] = types[i].MakeArrayType(template.GetArrayRank());
+ }
+ else if (template.IsPointer)
+ {
+ types[i] = types[i].MakePointerType();
+ }
+ }
+ }
+
+ private void AddSpecialInterface(ref ListBuilder<RuntimeType> list, Filter filter, RuntimeType iList, bool addSubInterface)
+ {
+ if (iList.IsAssignableFrom(ReflectedType))
+ {
+ if (filter.Match(RuntimeTypeHandle.GetUtf8Name(iList)))
+ list.Add(iList);
+
+ if (addSubInterface)
+ {
+ Type[] iFaces = iList.GetInterfaces();
+ for (int j = 0; j < iFaces.Length; j++)
+ {
+ RuntimeType iFace = (RuntimeType)iFaces[j];
+ if (iFace.IsGenericType && filter.Match(RuntimeTypeHandle.GetUtf8Name(iFace)))
+ list.Add(iFace);
+ }
+ }
+ }
+
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private RuntimeType[] PopulateInterfaces(Filter filter)
+ {
+ ListBuilder<RuntimeType> list = new ListBuilder<RuntimeType>();
+
+ RuntimeType declaringType = ReflectedType;
+
+ if (!RuntimeTypeHandle.IsGenericVariable(declaringType))
+ {
+ Type[] ifaces = RuntimeTypeHandle.GetInterfaces(declaringType);
+
+ if (ifaces != null)
+ {
+ for (int i = 0; i < ifaces.Length; i++)
+ {
+ RuntimeType interfaceType = (RuntimeType)ifaces[i];
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaceType)))
+ continue;
+ }
+
+ Contract.Assert(interfaceType.IsInterface);
+ list.Add(interfaceType);
+ }
+ }
+
+ if (ReflectedType.IsSzArray)
+ {
+ RuntimeType arrayType = (RuntimeType)ReflectedType.GetElementType();
+
+ if (!arrayType.IsPointer)
+ {
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IList<>).MakeGenericType(arrayType), true);
+
+ // To avoid adding a duplicate IEnumerable<T>, we don't add the sub interfaces of IReadOnlyList.
+ // Instead, we add IReadOnlyCollection<T> separately.
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IReadOnlyList<>).MakeGenericType(arrayType), false);
+ AddSpecialInterface(ref list, filter, (RuntimeType)typeof(IReadOnlyCollection<>).MakeGenericType(arrayType), false);
+ }
+ }
+ }
+ else
+ {
+ List<RuntimeType> al = new List<RuntimeType>();
+
+ // Get all constraints
+ Type[] constraints = declaringType.GetGenericParameterConstraints();
+
+ // Populate transitive closure of all interfaces in constraint set
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ RuntimeType constraint = (RuntimeType)constraints[i];
+ if (constraint.IsInterface)
+ al.Add(constraint);
+
+ Type[] temp = constraint.GetInterfaces();
+ for (int j = 0; j < temp.Length; j++)
+ al.Add(temp[j] as RuntimeType);
+ }
+
+ // Remove duplicates
+ Dictionary<RuntimeType, RuntimeType> ht = new Dictionary<RuntimeType, RuntimeType>();
+ for (int i = 0; i < al.Count; i++)
+ {
+ RuntimeType constraint = al[i];
+ if (!ht.ContainsKey(constraint))
+ ht[constraint] = constraint;
+ }
+
+ RuntimeType[] interfaces = new RuntimeType[ht.Values.Count];
+ ht.Values.CopyTo(interfaces, 0);
+
+ // Populate link-list
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ if (filter.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(interfaces[i])))
+ continue;
+ }
+
+ list.Add(interfaces[i]);
+ }
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeType[] PopulateNestedClasses(Filter filter)
+ {
+ RuntimeType declaringType = ReflectedType;
+
+ while (RuntimeTypeHandle.IsGenericVariable(declaringType))
+ {
+ declaringType = declaringType.GetBaseType();
+ }
+
+ int tkEnclosingType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // For example, TypeDescs do not have metadata tokens
+ if (MdToken.IsNullToken(tkEnclosingType))
+ return EmptyArray<RuntimeType>.Value;
+
+ ListBuilder<RuntimeType> list = new ListBuilder<RuntimeType>();
+
+ RuntimeModule moduleHandle = RuntimeTypeHandle.GetModule(declaringType);
+ MetadataImport scope = ModuleHandle.GetMetadataImport(moduleHandle);
+
+ MetadataEnumResult tkNestedClasses;
+ scope.EnumNestedTypes(tkEnclosingType, out tkNestedClasses);
+
+ for (int i = 0; i < tkNestedClasses.Length; i++)
+ {
+ RuntimeType nestedType = null;
+
+ try
+ {
+ nestedType = ModuleHandle.ResolveTypeHandleInternal(moduleHandle, tkNestedClasses[i], null, null);
+ }
+ catch(System.TypeLoadException)
+ {
+ // In a reflection emit scenario, we may have a token for a class which
+ // has not been baked and hence cannot be loaded.
+ continue;
+ }
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!filter.Match(RuntimeTypeHandle.GetUtf8Name(nestedType)))
+ continue;
+ }
+
+ list.Add(nestedType);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimeEventInfo[] PopulateEvents(Filter filter)
+ {
+ Contract.Requires(ReflectedType != null);
+
+ // Do not create the dictionary if we are filtering the properties by name already
+ Dictionary<String, RuntimeEventInfo> csEventInfos = filter.CaseSensitive() ? null :
+ new Dictionary<String, RuntimeEventInfo>();
+
+ RuntimeType declaringType = ReflectedType;
+ ListBuilder<RuntimeEventInfo> list = new ListBuilder<RuntimeEventInfo>();
+
+ if (!RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ // Populate associates off of the class hierarchy
+ while(declaringType != null)
+ {
+ PopulateEvents(filter, declaringType, csEventInfos, ref list);
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ }
+ }
+ else
+ {
+ // Populate associates for this interface
+ PopulateEvents(filter, declaringType, csEventInfos, ref list);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateEvents(
+ Filter filter, RuntimeType declaringType, Dictionary<String, RuntimeEventInfo> csEventInfos, ref ListBuilder<RuntimeEventInfo> list)
+ {
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens.
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkEvents;
+ scope.EnumEvents(tkDeclaringType, out tkEvents);
+
+ for (int i = 0; i < tkEvents.Length; i++)
+ {
+ int tkEvent = tkEvents[i];
+ bool isPrivate;
+
+ Contract.Assert(!MdToken.IsNullToken(tkEvent));
+ Contract.Assert(MdToken.IsTokenOfType(tkEvent, MetadataTokenType.Event));
+
+ if (filter.RequiresStringComparison())
+ {
+ Utf8String name;
+ name = scope.GetName(tkEvent);
+
+ if (!filter.Match(name))
+ continue;
+ }
+
+ RuntimeEventInfo eventInfo = new RuntimeEventInfo(
+ tkEvent, declaringType, m_runtimeTypeCache, out isPrivate);
+
+ #region Remove Inherited Privates
+ if (declaringType != m_runtimeTypeCache.GetRuntimeType() && isPrivate)
+ continue;
+ #endregion
+
+ #region Remove Duplicates
+ if (csEventInfos != null)
+ {
+ string name = eventInfo.Name;
+
+ if (csEventInfos.GetValueOrDefault(name) != null)
+ continue;
+
+ csEventInfos[name] = eventInfo;
+ }
+ else
+ {
+ if (list.Count > 0)
+ break;
+ }
+ #endregion
+
+ list.Add(eventInfo);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe RuntimePropertyInfo[] PopulateProperties(Filter filter)
+ {
+ Contract.Requires(ReflectedType != null);
+
+ // m_csMemberInfos can be null at this point. It will be initialized when Insert
+ // is called in Populate after this returns.
+
+ RuntimeType declaringType = ReflectedType;
+ Contract.Assert(declaringType != null);
+
+ ListBuilder<RuntimePropertyInfo> list = new ListBuilder<RuntimePropertyInfo>();
+
+ if (!RuntimeTypeHandle.IsInterface(declaringType))
+ {
+ while(RuntimeTypeHandle.IsGenericVariable(declaringType))
+ declaringType = declaringType.GetBaseType();
+
+ // Do not create the dictionary if we are filtering the properties by name already
+ Dictionary<String, List<RuntimePropertyInfo>> csPropertyInfos = filter.CaseSensitive() ? null :
+ new Dictionary<String, List<RuntimePropertyInfo>>();
+
+ // All elements automatically initialized to false.
+ bool[] usedSlots = new bool[RuntimeTypeHandle.GetNumVirtuals(declaringType)];
+
+ // Populate associates off of the class hierarchy
+ do
+ {
+ PopulateProperties(filter, declaringType, csPropertyInfos, usedSlots, ref list);
+ declaringType = RuntimeTypeHandle.GetBaseType(declaringType);
+ } while (declaringType != null);
+ }
+ else
+ {
+ // Populate associates for this interface
+ PopulateProperties(filter, declaringType, null, null, ref list);
+ }
+
+ return list.ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe void PopulateProperties(
+ Filter filter,
+ RuntimeType declaringType,
+ Dictionary<String, List<RuntimePropertyInfo>> csPropertyInfos,
+ bool[] usedSlots,
+ ref ListBuilder<RuntimePropertyInfo> list)
+ {
+ int tkDeclaringType = RuntimeTypeHandle.GetToken(declaringType);
+
+ // Arrays, Pointers, ByRef types and others generated only the fly by the RT do not have tokens.
+ if (MdToken.IsNullToken(tkDeclaringType))
+ return;
+
+ MetadataImport scope = RuntimeTypeHandle.GetMetadataImport(declaringType);
+
+ MetadataEnumResult tkProperties;
+ scope.EnumProperties(tkDeclaringType, out tkProperties);
+
+ RuntimeModule declaringModuleHandle = RuntimeTypeHandle.GetModule(declaringType);
+
+ int numVirtuals = RuntimeTypeHandle.GetNumVirtuals(declaringType);
+
+ Contract.Assert((declaringType.IsInterface && usedSlots == null && csPropertyInfos == null) ||
+ (!declaringType.IsInterface && usedSlots != null && usedSlots.Length >= numVirtuals));
+
+ for (int i = 0; i < tkProperties.Length; i++)
+ {
+ int tkProperty = tkProperties[i];
+ bool isPrivate;
+
+ Contract.Assert(!MdToken.IsNullToken(tkProperty));
+ Contract.Assert(MdToken.IsTokenOfType(tkProperty, MetadataTokenType.Property));
+
+ if (filter.RequiresStringComparison())
+ {
+ if (!ModuleHandle.ContainsPropertyMatchingHash(declaringModuleHandle, tkProperty, filter.GetHashToMatch()))
+ {
+ Contract.Assert(!filter.Match(declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty)));
+ continue;
+ }
+
+ Utf8String name;
+ name = declaringType.GetRuntimeModule().MetadataImport.GetName(tkProperty);
+
+ if (!filter.Match(name))
+ continue;
+ }
+
+ RuntimePropertyInfo propertyInfo =
+ new RuntimePropertyInfo(
+ tkProperty, declaringType, m_runtimeTypeCache, out isPrivate);
+
+ // If this is a class, not an interface
+ if (usedSlots != null)
+ {
+ #region Remove Privates
+ if (declaringType != ReflectedType && isPrivate)
+ continue;
+ #endregion
+
+ #region Duplicate check based on vtable slots
+
+ // The inheritance of properties are defined by the inheritance of their
+ // getters and setters.
+ // A property on a base type is "overriden" by a property on a sub type
+ // if the getter/setter of the latter occupies the same vtable slot as
+ // the getter/setter of the former.
+
+ MethodInfo associateMethod = propertyInfo.GetGetMethod();
+ if (associateMethod == null)
+ {
+ // We only need to examine the setter if a getter doesn't exist.
+ // It is not logical for the getter to be virtual but not the setter.
+ associateMethod = propertyInfo.GetSetMethod();
+ }
+
+ if (associateMethod != null)
+ {
+ int slot = RuntimeMethodHandle.GetSlot((RuntimeMethodInfo)associateMethod);
+
+ if (slot < numVirtuals)
+ {
+ Contract.Assert(associateMethod.IsVirtual);
+ if (usedSlots[slot] == true)
+ continue;
+ else
+ usedSlots[slot] = true;
+ }
+ }
+ #endregion
+
+ #region Duplicate check based on name and signature
+
+ // For backward compatibility, even if the vtable slots don't match, we will still treat
+ // a property as duplicate if the names and signatures match.
+
+ if (csPropertyInfos != null)
+ {
+ string name = propertyInfo.Name;
+
+ List<RuntimePropertyInfo> cache = csPropertyInfos.GetValueOrDefault(name);
+
+ if (cache == null)
+ {
+ cache = new List<RuntimePropertyInfo>(1);
+ csPropertyInfos[name] = cache;
+ }
+
+ for (int j = 0; j < cache.Count; j++)
+ {
+ if (propertyInfo.EqualsSig(cache[j]))
+ {
+ cache = null;
+ break;
+ }
+ }
+
+ if (cache == null)
+ continue;
+
+ cache.Add(propertyInfo);
+ }
+ else
+ {
+ bool duplicate = false;
+
+ for (int j = 0; j < list.Count; j++)
+ {
+ if (propertyInfo.EqualsSig(list[j]))
+ {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (duplicate)
+ continue;
+ }
+ #endregion
+ }
+
+ list.Add(propertyInfo);
+ }
+ }
+ #endregion
+
+ #region NonPrivate Members
+ internal T[] GetMemberList(MemberListType listType, string name, CacheType cacheType)
+ {
+ T[] list = null;
+
+ switch(listType)
+ {
+ case MemberListType.CaseSensitive:
+ list = m_csMemberInfos[name];
+ if (list != null)
+ return list;
+
+ return Populate(name, listType, cacheType);
+
+ case MemberListType.CaseInsensitive:
+ list = m_cisMemberInfos[name];
+ if (list != null)
+ return list;
+
+ return Populate(name, listType, cacheType);
+
+ default:
+ Contract.Assert(listType == MemberListType.All);
+ if (Volatile.Read(ref m_cacheComplete))
+ return m_allMembers;
+
+ return Populate(null, listType, cacheType);
+ }
+ }
+
+ internal RuntimeType ReflectedType
+ {
+ get
+ {
+ return m_runtimeTypeCache.GetRuntimeType();
+ }
+ }
+ #endregion
+ }
+ #endregion
+
+ #region Private Data Members
+ private RuntimeType m_runtimeType;
+ private RuntimeType m_enclosingType;
+ private TypeCode m_typeCode;
+ private string m_name;
+ private string m_fullname;
+ private string m_toString;
+ private string m_namespace;
+ private string m_serializationname;
+ private bool m_isGlobal;
+ private bool m_bIsDomainInitialized;
+ private MemberInfoCache<RuntimeMethodInfo> m_methodInfoCache;
+ private MemberInfoCache<RuntimeConstructorInfo> m_constructorInfoCache;
+ private MemberInfoCache<RuntimeFieldInfo> m_fieldInfoCache;
+ private MemberInfoCache<RuntimeType> m_interfaceCache;
+ private MemberInfoCache<RuntimeType> m_nestedClassesCache;
+ private MemberInfoCache<RuntimePropertyInfo> m_propertyInfoCache;
+ private MemberInfoCache<RuntimeEventInfo> m_eventInfoCache;
+ private static CerHashtable<RuntimeMethodInfo, RuntimeMethodInfo> s_methodInstantiations;
+ private static Object s_methodInstantiationsLock;
+#if !FEATURE_CORECLR
+ private RuntimeConstructorInfo m_serializationCtor;
+#endif
+ private string m_defaultMemberName;
+ private Object m_genericCache; // Generic cache for rare scenario specific data. It is used to cache Enum names and values.
+ #endregion
+
+ #region Constructor
+ internal RuntimeTypeCache(RuntimeType runtimeType)
+ {
+ m_typeCode = TypeCode.Empty;
+ m_runtimeType = runtimeType;
+ m_isGlobal = RuntimeTypeHandle.GetModule(runtimeType).RuntimeType == runtimeType;
+ }
+ #endregion
+
+ #region Private Members
+ private string ConstructName(ref string name, TypeNameFormatFlags formatFlags)
+ {
+ if (name == null)
+ {
+ name = new RuntimeTypeHandle(m_runtimeType).ConstructName(formatFlags);
+ }
+ return name;
+ }
+
+ private T[] GetMemberList<T>(ref MemberInfoCache<T> m_cache, MemberListType listType, string name, CacheType cacheType)
+ where T : MemberInfo
+ {
+ MemberInfoCache<T> existingCache = GetMemberCache<T>(ref m_cache);
+ return existingCache.GetMemberList(listType, name, cacheType);
+ }
+
+ private MemberInfoCache<T> GetMemberCache<T>(ref MemberInfoCache<T> m_cache)
+ where T : MemberInfo
+ {
+ MemberInfoCache<T> existingCache = m_cache;
+
+ if (existingCache == null)
+ {
+ MemberInfoCache<T> newCache = new MemberInfoCache<T>(this);
+ existingCache = Interlocked.CompareExchange(ref m_cache, newCache, null);
+ if (existingCache == null)
+ existingCache = newCache;
+ }
+
+ return existingCache;
+ }
+ #endregion
+
+ #region Internal Members
+
+ internal Object GenericCache
+ {
+ get { return m_genericCache; }
+ set { m_genericCache = value; }
+ }
+
+ internal bool DomainInitialized
+ {
+ get { return m_bIsDomainInitialized; }
+ set { m_bIsDomainInitialized = value; }
+ }
+
+ internal string GetName(TypeNameKind kind)
+ {
+ switch (kind)
+ {
+ case TypeNameKind.Name:
+ // No namespace, full instantiation, and assembly.
+ return ConstructName(ref m_name, TypeNameFormatFlags.FormatBasic);
+
+ case TypeNameKind.FullName:
+ // We exclude the types that contain generic parameters because their names cannot be roundtripped.
+ // We allow generic type definitions (and their refs, ptrs, and arrays) because their names can be roundtriped.
+ // Theoretically generic types instantiated with generic type definitions can be roundtripped, e.g. List`1<Dictionary`2>.
+ // But these kind of types are useless, rare, and hard to identity. We would need to recursively examine all the
+ // generic arguments with the same criteria. We will exclude them unless we see a real user scenario.
+ if (!m_runtimeType.GetRootElementType().IsGenericTypeDefinition && m_runtimeType.ContainsGenericParameters)
+ return null;
+
+ // No assembly.
+ return ConstructName(ref m_fullname, TypeNameFormatFlags.FormatNamespace | TypeNameFormatFlags.FormatFullInst);
+
+ case TypeNameKind.ToString:
+ // No full instantiation and assembly.
+ return ConstructName(ref m_toString, TypeNameFormatFlags.FormatNamespace);
+
+ case TypeNameKind.SerializationName:
+ // Use FormatGenericParam in serialization. Otherwise we won't be able
+ // to distinguish between a generic parameter and a normal type with the same name.
+ // e.g. Foo<T>.Bar(T t), the parameter type T could be !1 or a real type named "T".
+ // Excluding the version number in the assembly name for VTS.
+ return ConstructName(ref m_serializationname, TypeNameFormatFlags.FormatSerialization);
+
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal unsafe string GetNameSpace()
+ {
+ // @Optimization - Use ConstructName to populate m_namespace
+ if (m_namespace == null)
+ {
+ Type type = m_runtimeType;
+ type = type.GetRootElementType();
+
+ while (type.IsNested)
+ type = type.DeclaringType;
+
+ m_namespace = RuntimeTypeHandle.GetMetadataImport((RuntimeType)type).GetNamespace(type.MetadataToken).ToString();
+ }
+
+ return m_namespace;
+ }
+
+ internal TypeCode TypeCode
+ {
+ get { return m_typeCode; }
+ set { m_typeCode = value; }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe RuntimeType GetEnclosingType()
+ {
+ if (m_enclosingType == null)
+ {
+ // Use void as a marker of null enclosing type
+ RuntimeType enclosingType = RuntimeTypeHandle.GetDeclaringType(GetRuntimeType());
+ Contract.Assert(enclosingType != typeof(void));
+ m_enclosingType = enclosingType ?? (RuntimeType)typeof(void);
+ }
+
+ return (m_enclosingType == typeof(void)) ? null : m_enclosingType;
+ }
+
+ internal RuntimeType GetRuntimeType()
+ {
+ return m_runtimeType;
+ }
+
+ internal bool IsGlobal
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return m_isGlobal; }
+ }
+
+ internal void InvalidateCachedNestedType()
+ {
+ m_nestedClassesCache = null;
+ }
+
+#if !FEATURE_CORECLR
+ internal RuntimeConstructorInfo GetSerializationCtor()
+ {
+ if (m_serializationCtor == null)
+ {
+ if (s_SICtorParamTypes == null)
+ s_SICtorParamTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
+
+ m_serializationCtor = m_runtimeType.GetConstructor(
+ BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ CallingConventions.Any,
+ s_SICtorParamTypes,
+ null) as RuntimeConstructorInfo;
+ }
+
+ return m_serializationCtor;
+ }
+#endif //!FEATURE_CORECLR
+
+ internal string GetDefaultMemberName()
+ {
+ if (m_defaultMemberName == null)
+ {
+ CustomAttributeData attr = null;
+ Type DefaultMemberAttrType = typeof(DefaultMemberAttribute);
+ for (RuntimeType t = m_runtimeType; t != null; t = t.GetBaseType())
+ {
+ IList<CustomAttributeData> attrs = CustomAttributeData.GetCustomAttributes(t);
+ for (int i = 0; i < attrs.Count; i++)
+ {
+ if (Object.ReferenceEquals(attrs[i].Constructor.DeclaringType, DefaultMemberAttrType))
+ {
+ attr = attrs[i];
+ break;
+ }
+ }
+
+ if (attr != null)
+ {
+ m_defaultMemberName = attr.ConstructorArguments[0].Value as string;
+ break;
+ }
+ }
+ }
+
+ return m_defaultMemberName;
+ }
+ #endregion
+
+ #region Caches Accessors
+ [System.Security.SecurityCritical] // auto-generated
+ internal MethodInfo GetGenericMethodInfo(RuntimeMethodHandleInternal genericMethod)
+ {
+ LoaderAllocator la = RuntimeMethodHandle.GetLoaderAllocator(genericMethod);
+
+ RuntimeMethodInfo rmi = new RuntimeMethodInfo(
+ genericMethod, RuntimeMethodHandle.GetDeclaringType(genericMethod), this,
+ RuntimeMethodHandle.GetAttributes(genericMethod), (BindingFlags)(-1), la);
+
+ RuntimeMethodInfo crmi;
+ if (la != null)
+ {
+ crmi = la.m_methodInstantiations[rmi];
+ }
+ else
+ {
+ crmi = s_methodInstantiations[rmi];
+ }
+ if (crmi != null)
+ return crmi;
+
+ if (s_methodInstantiationsLock == null)
+ Interlocked.CompareExchange(ref s_methodInstantiationsLock, new Object(), null);
+
+ bool lockTaken = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(s_methodInstantiationsLock, ref lockTaken);
+
+ if (la != null)
+ {
+ crmi = la.m_methodInstantiations[rmi];
+ if (crmi != null)
+ return crmi;
+ la.m_methodInstantiations[rmi] = rmi;
+ }
+ else
+ {
+ crmi = s_methodInstantiations[rmi];
+ if (crmi != null)
+ return crmi;
+ s_methodInstantiations[rmi] = rmi;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ {
+ Monitor.Exit(s_methodInstantiationsLock);
+ }
+ }
+
+ return rmi;
+ }
+
+ internal RuntimeMethodInfo[] GetMethodList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeMethodInfo>(ref m_methodInfoCache, listType, name, CacheType.Method);
+ }
+
+ internal RuntimeConstructorInfo[] GetConstructorList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeConstructorInfo>(ref m_constructorInfoCache, listType, name, CacheType.Constructor);
+ }
+
+ internal RuntimePropertyInfo[] GetPropertyList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimePropertyInfo>(ref m_propertyInfoCache, listType, name, CacheType.Property);
+ }
+
+ internal RuntimeEventInfo[] GetEventList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeEventInfo>(ref m_eventInfoCache, listType, name, CacheType.Event);
+ }
+
+ internal RuntimeFieldInfo[] GetFieldList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeFieldInfo>(ref m_fieldInfoCache, listType, name, CacheType.Field);
+ }
+
+ internal RuntimeType[] GetInterfaceList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeType>(ref m_interfaceCache, listType, name, CacheType.Interface);
+ }
+
+ internal RuntimeType[] GetNestedTypeList(MemberListType listType, string name)
+ {
+ return GetMemberList<RuntimeType>(ref m_nestedClassesCache, listType, name, CacheType.NestedType);
+ }
+
+ internal MethodBase GetMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method)
+ {
+ GetMemberCache<RuntimeMethodInfo>(ref m_methodInfoCache);
+ return m_methodInfoCache.AddMethod(declaringType, method, CacheType.Method);
+ }
+
+ internal MethodBase GetConstructor(RuntimeType declaringType, RuntimeMethodHandleInternal constructor)
+ {
+ GetMemberCache<RuntimeConstructorInfo>(ref m_constructorInfoCache);
+ return m_constructorInfoCache.AddMethod(declaringType, constructor, CacheType.Constructor);
+ }
+
+ internal FieldInfo GetField(RuntimeFieldHandleInternal field)
+ {
+ GetMemberCache<RuntimeFieldInfo>(ref m_fieldInfoCache);
+ return m_fieldInfoCache.AddField(field);
+ }
+
+ #endregion
+ }
+ #endregion
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ // The size of CachedData is accounted for by BaseObjectWithCachedData in object.h.
+ // This member is currently being used by Remoting for caching remoting data. If you
+ // need to cache data here, talk to the Remoting team to work out a mechanism, so that
+ // both caching systems can happily work together.
+ private RemotingTypeCachedData m_cachedData;
+
+ internal RemotingTypeCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingTypeCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingTypeCachedData(this);
+ RemotingTypeCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+
+ #region Static Members
+
+ #region Internal
+ internal static RuntimeType GetType(String typeName, bool throwOnError, bool ignoreCase, bool reflectionOnly,
+ ref StackCrawlMark stackMark)
+ {
+ if (typeName == null)
+ throw new ArgumentNullException("typeName");
+ Contract.EndContractBlock();
+
+ return RuntimeTypeHandle.GetTypeByName(
+ typeName, throwOnError, ignoreCase, reflectionOnly, ref stackMark, false);
+ }
+
+ internal static MethodBase GetMethodBase(RuntimeModule scope, int typeMetadataToken)
+ {
+ return GetMethodBase(ModuleHandle.ResolveMethodHandleInternal(scope, typeMetadataToken));
+ }
+
+ internal static MethodBase GetMethodBase(IRuntimeMethodInfo methodHandle)
+ {
+ return GetMethodBase(null, methodHandle);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static MethodBase GetMethodBase(RuntimeType reflectedType, IRuntimeMethodInfo methodHandle)
+ {
+ MethodBase retval = RuntimeType.GetMethodBase(reflectedType, methodHandle.Value);
+ GC.KeepAlive(methodHandle);
+ return retval;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static MethodBase GetMethodBase(RuntimeType reflectedType, RuntimeMethodHandleInternal methodHandle)
+ {
+ Contract.Assert(!methodHandle.IsNullHandle());
+
+ if (RuntimeMethodHandle.IsDynamicMethod(methodHandle))
+ {
+ Resolver resolver = RuntimeMethodHandle.GetResolver(methodHandle);
+
+ if (resolver != null)
+ return resolver.GetDynamicMethod();
+
+ return null;
+ }
+
+ // verify the type/method relationship
+ RuntimeType declaredType = RuntimeMethodHandle.GetDeclaringType(methodHandle);
+
+ RuntimeType[] methodInstantiation = null;
+
+ if (reflectedType == null)
+ reflectedType = declaredType as RuntimeType;
+
+ if (reflectedType != declaredType && !reflectedType.IsSubclassOf(declaredType))
+ {
+ // object[] is assignable from string[].
+ if (reflectedType.IsArray)
+ {
+ // The whole purpose of this chunk of code is not only for error checking.
+ // GetMember has a side effect of populating the member cache of reflectedType,
+ // doing so will ensure we construct the correct MethodInfo/ConstructorInfo objects.
+ // Without this the reflectedType.Cache.GetMethod call below may return a MethodInfo
+ // object whose ReflectedType is string[] and DeclaringType is object[]. That would
+ // be (arguabally) incorrect because string[] is not a subclass of object[].
+ MethodBase[] methodBases = reflectedType.GetMember(
+ RuntimeMethodHandle.GetName(methodHandle), MemberTypes.Constructor | MemberTypes.Method,
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) as MethodBase[];
+
+ bool loaderAssuredCompatible = false;
+ for (int i = 0; i < methodBases.Length; i++)
+ {
+ IRuntimeMethodInfo rmi = (IRuntimeMethodInfo)methodBases[i];
+ if (rmi.Value.Value == methodHandle.Value)
+ loaderAssuredCompatible = true;
+ }
+
+ if (!loaderAssuredCompatible)
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"),
+ reflectedType.ToString(), declaredType.ToString()));
+ }
+ // Action<in string> is assignable from, but not a subclass of Action<in object>.
+ else if (declaredType.IsGenericType)
+ {
+ // ignoring instantiation is the ReflectedType a subtype of the DeclaringType
+ RuntimeType declaringDefinition = (RuntimeType)declaredType.GetGenericTypeDefinition();
+
+ RuntimeType baseType = reflectedType;
+
+ while (baseType != null)
+ {
+ RuntimeType baseDefinition = baseType;
+
+ if (baseDefinition.IsGenericType && !baseType.IsGenericTypeDefinition)
+ baseDefinition = (RuntimeType)baseDefinition.GetGenericTypeDefinition();
+
+ if (baseDefinition == declaringDefinition)
+ break;
+
+ baseType = baseType.GetBaseType();
+ }
+
+ if (baseType == null)
+ {
+ // ignoring instantiation is the ReflectedType is not a subtype of the DeclaringType
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"),
+ reflectedType.ToString(), declaredType.ToString()));
+ }
+
+ // remap the method to same method on the subclass ReflectedType
+ declaredType = baseType;
+
+ // if the original methodHandle was the definition then we don't need to rebind generic method arguments
+ // because all RuntimeMethodHandles retrieved off of the canonical method table are definitions. That's
+ // why for everything else we need to rebind the generic method arguments.
+ if (!RuntimeMethodHandle.IsGenericMethodDefinition(methodHandle))
+ {
+ methodInstantiation = RuntimeMethodHandle.GetMethodInstantiationInternal(methodHandle);
+ }
+
+ // lookup via v-table slot the RuntimeMethodHandle on the new declaring type
+ methodHandle = RuntimeMethodHandle.GetMethodFromCanonical(methodHandle, declaredType);
+ }
+ else if (!declaredType.IsAssignableFrom(reflectedType))
+ {
+ // declaredType is not Array, not generic, and not assignable from reflectedType
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveMethodHandle"),
+ reflectedType.ToString(), declaredType.ToString()));
+ }
+ }
+
+ // If methodInstantiation is not null, GetStubIfNeeded will rebind the generic method arguments
+ // if declaredType is an instantiated generic type and methodHandle is not generic, get the instantiated MethodDesc (if needed)
+ // if declaredType is a value type, get the unboxing stub (if needed)
+
+ // this is so that our behavior here is consistent with that of Type.GetMethod
+ // See MemberInfoCache<RuntimeConstructorInfo>.PopulateMethods and MemberInfoCache<RuntimeMethodInfoInfo>.PopulateConstructors
+
+ methodHandle = RuntimeMethodHandle.GetStubIfNeeded(methodHandle, declaredType, methodInstantiation);
+ MethodBase retval;
+
+ if (RuntimeMethodHandle.IsConstructor(methodHandle))
+ {
+ // Constructor case: constructors cannot be generic
+ retval = reflectedType.Cache.GetConstructor(declaredType, methodHandle);
+ }
+ else
+ {
+ // Method case
+ if (RuntimeMethodHandle.HasMethodInstantiation(methodHandle) && !RuntimeMethodHandle.IsGenericMethodDefinition(methodHandle))
+ retval = reflectedType.Cache.GetGenericMethodInfo(methodHandle);
+ else
+ retval = reflectedType.Cache.GetMethod(declaredType, methodHandle);
+ }
+
+ GC.KeepAlive(methodInstantiation);
+ return retval;
+ }
+
+ internal Object GenericCache
+ {
+ get { return Cache.GenericCache; }
+ set { Cache.GenericCache = value; }
+ }
+
+ internal bool DomainInitialized
+ {
+ get { return Cache.DomainInitialized; }
+ set { Cache.DomainInitialized = value; }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static FieldInfo GetFieldInfo(IRuntimeFieldInfo fieldHandle)
+ {
+ return GetFieldInfo(RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle), fieldHandle);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static FieldInfo GetFieldInfo(RuntimeType reflectedType, IRuntimeFieldInfo field)
+ {
+ RuntimeFieldHandleInternal fieldHandle = field.Value;
+
+ // verify the type/method relationship
+ if (reflectedType == null)
+ {
+ reflectedType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle);
+ }
+ else
+ {
+ RuntimeType declaredType = RuntimeFieldHandle.GetApproxDeclaringType(fieldHandle);
+ if (reflectedType != declaredType)
+ {
+ if (!RuntimeFieldHandle.AcquiresContextFromThis(fieldHandle) ||
+ !RuntimeTypeHandle.CompareCanonicalHandles(declaredType, reflectedType))
+ {
+ throw new ArgumentException(String.Format(
+ CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ResolveFieldHandle"),
+ reflectedType.ToString(),
+ declaredType.ToString()));
+ }
+ }
+ }
+
+ FieldInfo retVal = reflectedType.Cache.GetField(fieldHandle);
+ GC.KeepAlive(field);
+ return retVal;
+ }
+
+ // Called internally
+ private unsafe static PropertyInfo GetPropertyInfo(RuntimeType reflectedType, int tkProperty)
+ {
+ RuntimePropertyInfo property = null;
+ RuntimePropertyInfo[] candidates =
+ reflectedType.Cache.GetPropertyList(MemberListType.All, null);
+
+ for (int i = 0; i < candidates.Length; i++)
+ {
+ property = candidates[i];
+ if (property.MetadataToken == tkProperty)
+ return property;
+ }
+
+ Contract.Assume(false, "Unreachable code");
+ throw new SystemException();
+ }
+
+ private static void ThrowIfTypeNeverValidGenericArgument(RuntimeType type)
+ {
+ if (type.IsPointer || type.IsByRef || type == typeof(void))
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_NeverValidGenericArgument", type.ToString()));
+ }
+
+
+ internal static void SanityCheckGenericArguments(RuntimeType[] genericArguments, RuntimeType[] genericParamters)
+ {
+ if (genericArguments == null)
+ throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ for(int i = 0; i < genericArguments.Length; i++)
+ {
+ if (genericArguments[i] == null)
+ throw new ArgumentNullException();
+
+ ThrowIfTypeNeverValidGenericArgument(genericArguments[i]);
+ }
+
+ if (genericArguments.Length != genericParamters.Length)
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_NotEnoughGenArguments", genericArguments.Length, genericParamters.Length));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void ValidateGenericArguments(MemberInfo definition, RuntimeType[] genericArguments, Exception e)
+ {
+ RuntimeType[] typeContext = null;
+ RuntimeType[] methodContext = null;
+ RuntimeType[] genericParamters = null;
+
+ if (definition is Type)
+ {
+ RuntimeType genericTypeDefinition = (RuntimeType)definition;
+ genericParamters = genericTypeDefinition.GetGenericArgumentsInternal();
+ typeContext = genericArguments;
+ }
+ else
+ {
+ RuntimeMethodInfo genericMethodDefinition = (RuntimeMethodInfo)definition;
+ genericParamters = genericMethodDefinition.GetGenericArgumentsInternal();
+ methodContext = genericArguments;
+
+ RuntimeType declaringType = (RuntimeType)genericMethodDefinition.DeclaringType;
+ if (declaringType != null)
+ {
+ typeContext = declaringType.GetTypeHandleInternal().GetInstantiationInternal();
+ }
+ }
+
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ Type genericArgument = genericArguments[i];
+ Type genericParameter = genericParamters[i];
+
+ if (!RuntimeTypeHandle.SatisfiesConstraints(genericParameter.GetTypeHandleInternal().GetTypeChecked(),
+ typeContext, methodContext, genericArgument.GetTypeHandleInternal().GetTypeChecked()))
+ {
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_GenConstraintViolation",
+ i.ToString(CultureInfo.CurrentCulture), genericArgument.ToString(), definition.ToString(), genericParameter.ToString()), e);
+ }
+ }
+ }
+
+ private static void SplitName(string fullname, out string name, out string ns)
+ {
+ name = null;
+ ns = null;
+
+ if (fullname == null)
+ return;
+
+ // Get namespace
+ int nsDelimiter = fullname.LastIndexOf(".", StringComparison.Ordinal);
+ if (nsDelimiter != -1 )
+ {
+ ns = fullname.Substring(0, nsDelimiter);
+ int nameLength = fullname.Length - ns.Length - 1;
+ if (nameLength != 0)
+ name = fullname.Substring(nsDelimiter + 1, nameLength);
+ else
+ name = "";
+ Contract.Assert(fullname.Equals(ns + "." + name));
+ }
+ else
+ {
+ name = fullname;
+ }
+
+ }
+ #endregion
+
+ #region Filters
+ internal static BindingFlags FilterPreCalculate(bool isPublic, bool isInherited, bool isStatic)
+ {
+ BindingFlags bindingFlags = isPublic ? BindingFlags.Public : BindingFlags.NonPublic;
+
+ if (isInherited)
+ {
+ // We arrange things so the DeclaredOnly flag means "include inherited members"
+ bindingFlags |= BindingFlags.DeclaredOnly;
+
+ if (isStatic)
+ {
+ bindingFlags |= BindingFlags.Static | BindingFlags.FlattenHierarchy;
+ }
+ else
+ {
+ bindingFlags |= BindingFlags.Instance;
+ }
+ }
+ else
+ {
+ if (isStatic)
+ {
+ bindingFlags |= BindingFlags.Static;
+ }
+ else
+ {
+ bindingFlags |= BindingFlags.Instance;
+ }
+ }
+
+ return bindingFlags;
+ }
+
+ // Calculate prefixLookup, ignoreCase, and listType for use by GetXXXCandidates
+ private static void FilterHelper(
+ BindingFlags bindingFlags, ref string name, bool allowPrefixLookup, out bool prefixLookup,
+ out bool ignoreCase, out MemberListType listType)
+ {
+ prefixLookup = false;
+ ignoreCase = false;
+
+ if (name != null)
+ {
+ if ((bindingFlags & BindingFlags.IgnoreCase) != 0)
+ {
+ name = name.ToLower(CultureInfo.InvariantCulture);
+ ignoreCase = true;
+ listType = MemberListType.CaseInsensitive;
+ }
+ else
+ {
+ listType = MemberListType.CaseSensitive;
+ }
+
+ if (allowPrefixLookup && name.EndsWith("*", StringComparison.Ordinal))
+ {
+ // We set prefixLookup to true if name ends with a "*".
+ // We will also set listType to All so that all members are included in
+ // the candidates which are later filtered by FilterApplyPrefixLookup.
+ name = name.Substring(0, name.Length - 1);
+ prefixLookup = true;
+ listType = MemberListType.All;
+ }
+ }
+ else
+ {
+ listType = MemberListType.All;
+ }
+ }
+
+ // Used by the singular GetXXX APIs (Event, Field, Interface, NestedType) where prefixLookup is not supported.
+ private static void FilterHelper(BindingFlags bindingFlags, ref string name, out bool ignoreCase, out MemberListType listType)
+ {
+ bool prefixLookup;
+ FilterHelper(bindingFlags, ref name, false, out prefixLookup, out ignoreCase, out listType);
+ }
+
+ // Only called by GetXXXCandidates, GetInterfaces, and GetNestedTypes when FilterHelper has set "prefixLookup" to true.
+ // Most of the plural GetXXX methods allow prefix lookups while the singular GetXXX methods mostly do not.
+ private static bool FilterApplyPrefixLookup(MemberInfo memberInfo, string name, bool ignoreCase)
+ {
+ Contract.Assert(name != null);
+
+ if (ignoreCase)
+ {
+ if (!memberInfo.Name.StartsWith(name, StringComparison.OrdinalIgnoreCase))
+ return false;
+ }
+ else
+ {
+ if (!memberInfo.Name.StartsWith(name, StringComparison.Ordinal))
+ return false;
+ }
+
+ return true;
+ }
+
+
+ // Used by FilterApplyType to perform all the filtering based on name and BindingFlags
+ private static bool FilterApplyBase(
+ MemberInfo memberInfo, BindingFlags bindingFlags, bool isPublic, bool isNonProtectedInternal, bool isStatic,
+ string name, bool prefixLookup)
+ {
+ #region Preconditions
+ Contract.Requires(memberInfo != null);
+ Contract.Requires(name == null || (bindingFlags & BindingFlags.IgnoreCase) == 0 || (name.ToLower(CultureInfo.InvariantCulture).Equals(name)));
+ #endregion
+
+ #region Filter by Public & Private
+ if (isPublic)
+ {
+ if ((bindingFlags & BindingFlags.Public) == 0)
+ return false;
+ }
+ else
+ {
+ if ((bindingFlags & BindingFlags.NonPublic) == 0)
+ return false;
+ }
+ #endregion
+
+ bool isInherited = !Object.ReferenceEquals(memberInfo.DeclaringType, memberInfo.ReflectedType);
+
+ #region Filter by DeclaredOnly
+ if ((bindingFlags & BindingFlags.DeclaredOnly) != 0 && isInherited)
+ return false;
+ #endregion
+
+ #region Filter by Static & Instance
+ if (memberInfo.MemberType != MemberTypes.TypeInfo &&
+ memberInfo.MemberType != MemberTypes.NestedType)
+ {
+ if (isStatic)
+ {
+ if ((bindingFlags & BindingFlags.FlattenHierarchy) == 0 && isInherited)
+ return false;
+
+ if ((bindingFlags & BindingFlags.Static) == 0)
+ return false;
+ }
+ else
+ {
+ if ((bindingFlags & BindingFlags.Instance) == 0)
+ return false;
+ }
+ }
+ #endregion
+
+ #region Filter by name wrt prefixLookup and implicitly by case sensitivity
+ if (prefixLookup == true)
+ {
+ if (!FilterApplyPrefixLookup(memberInfo, name, (bindingFlags & BindingFlags.IgnoreCase) != 0))
+ return false;
+ }
+ #endregion
+
+ #region Asymmetries
+ // @Asymmetry - Internal, inherited, instance, non-protected, non-virtual, non-abstract members returned
+ // iff BindingFlags !DeclaredOnly, Instance and Public are present except for fields
+ if (((bindingFlags & BindingFlags.DeclaredOnly) == 0) && // DeclaredOnly not present
+ isInherited && // Is inherited Member
+
+ (isNonProtectedInternal) && // Is non-protected internal member
+ ((bindingFlags & BindingFlags.NonPublic) != 0) && // BindingFlag.NonPublic present
+
+ (!isStatic) && // Is instance member
+ ((bindingFlags & BindingFlags.Instance) != 0)) // BindingFlag.Instance present
+ {
+ MethodInfo methodInfo = memberInfo as MethodInfo;
+
+ if (methodInfo == null)
+ return false;
+
+ if (!methodInfo.IsVirtual && !methodInfo.IsAbstract)
+ return false;
+ }
+ #endregion
+
+ return true;
+ }
+
+
+ // Used by GetInterface and GetNestedType(s) which don't need parameter type filtering.
+ private static bool FilterApplyType(
+ Type type, BindingFlags bindingFlags, string name, bool prefixLookup, string ns)
+ {
+ Contract.Requires((object)type != null);
+ Contract.Assert(type is RuntimeType);
+
+ bool isPublic = type.IsNestedPublic || type.IsPublic;
+ bool isStatic = false;
+
+ if (!RuntimeType.FilterApplyBase(type, bindingFlags, isPublic, type.IsNestedAssembly, isStatic, name, prefixLookup))
+ return false;
+
+ if (ns != null && !type.Namespace.Equals(ns))
+ return false;
+
+ return true;
+ }
+
+
+ private static bool FilterApplyMethodInfo(
+ RuntimeMethodInfo method, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ // Optimization: Pre-Calculate the method binding flags to avoid casting.
+ return FilterApplyMethodBase(method, method.BindingFlags, bindingFlags, callConv, argumentTypes);
+ }
+
+ private static bool FilterApplyConstructorInfo(
+ RuntimeConstructorInfo constructor, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ // Optimization: Pre-Calculate the method binding flags to avoid casting.
+ return FilterApplyMethodBase(constructor, constructor.BindingFlags, bindingFlags, callConv, argumentTypes);
+ }
+
+ // Used by GetMethodCandidates/GetConstructorCandidates, InvokeMember, and CreateInstanceImpl to perform the necessary filtering.
+ // Should only be called by FilterApplyMethodInfo and FilterApplyConstructorInfo.
+ private static bool FilterApplyMethodBase(
+ MethodBase methodBase, BindingFlags methodFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[] argumentTypes)
+ {
+ Contract.Requires(methodBase != null);
+
+ bindingFlags ^= BindingFlags.DeclaredOnly;
+
+ #region Apply Base Filter
+ if ((bindingFlags & methodFlags) != methodFlags)
+ return false;
+ #endregion
+
+ #region Check CallingConvention
+ if ((callConv & CallingConventions.Any) == 0)
+ {
+ if ((callConv & CallingConventions.VarArgs) != 0 &&
+ (methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
+ return false;
+
+ if ((callConv & CallingConventions.Standard) != 0 &&
+ (methodBase.CallingConvention & CallingConventions.Standard) == 0)
+ return false;
+ }
+ #endregion
+
+ #region If argumentTypes supplied
+ if (argumentTypes != null)
+ {
+ ParameterInfo[] parameterInfos = methodBase.GetParametersNoCopy();
+
+ if (argumentTypes.Length != parameterInfos.Length)
+ {
+ #region Invoke Member, Get\Set & Create Instance specific case
+ // If the number of supplied arguments differs than the number in the signature AND
+ // we are not filtering for a dynamic call -- InvokeMethod or CreateInstance -- filter out the method.
+ if ((bindingFlags &
+ (BindingFlags.InvokeMethod | BindingFlags.CreateInstance | BindingFlags.GetProperty | BindingFlags.SetProperty)) == 0)
+ return false;
+
+ bool testForParamArray = false;
+ bool excessSuppliedArguments = argumentTypes.Length > parameterInfos.Length;
+
+ if (excessSuppliedArguments)
+ { // more supplied arguments than parameters, additional arguments could be vararg
+ #region Varargs
+ // If method is not vararg, additional arguments can not be passed as vararg
+ if ((methodBase.CallingConvention & CallingConventions.VarArgs) == 0)
+ {
+ testForParamArray = true;
+ }
+ else
+ {
+ // If Binding flags did not include varargs we would have filtered this vararg method.
+ // This Invariant established during callConv check.
+ Contract.Assert((callConv & CallingConventions.VarArgs) != 0);
+ }
+ #endregion
+ }
+ else
+ {// fewer supplied arguments than parameters, missing arguments could be optional
+ #region OptionalParamBinding
+ if ((bindingFlags & BindingFlags.OptionalParamBinding) == 0)
+ {
+ testForParamArray = true;
+ }
+ else
+ {
+ // From our existing code, our policy here is that if a parameterInfo
+ // is optional then all subsequent parameterInfos shall be optional.
+
+ // Thus, iff the first parameterInfo is not optional then this MethodInfo is no longer a canidate.
+ if (!parameterInfos[argumentTypes.Length].IsOptional)
+ testForParamArray = true;
+ }
+ #endregion
+ }
+
+ #region ParamArray
+ if (testForParamArray)
+ {
+ if (parameterInfos.Length == 0)
+ return false;
+
+ // The last argument of the signature could be a param array.
+ bool shortByMoreThanOneSuppliedArgument = argumentTypes.Length < parameterInfos.Length - 1;
+
+ if (shortByMoreThanOneSuppliedArgument)
+ return false;
+
+ ParameterInfo lastParameter = parameterInfos[parameterInfos.Length - 1];
+
+ if (!lastParameter.ParameterType.IsArray)
+ return false;
+
+ if (!lastParameter.IsDefined(typeof(ParamArrayAttribute), false))
+ return false;
+ }
+ #endregion
+
+ #endregion
+ }
+ else
+ {
+ #region Exact Binding
+ if ((bindingFlags & BindingFlags.ExactBinding) != 0)
+ {
+ // Legacy behavior is to ignore ExactBinding when InvokeMember is specified.
+ // Why filter by InvokeMember? If the answer is we leave this to the binder then why not leave
+ // all the rest of this to the binder too? Further, what other semanitc would the binder
+ // use for BindingFlags.ExactBinding besides this one? Further, why not include CreateInstance
+ // in this if statement? That's just InvokeMethod with a constructor, right?
+ if ((bindingFlags & (BindingFlags.InvokeMethod)) == 0)
+ {
+ for(int i = 0; i < parameterInfos.Length; i ++)
+ {
+ // a null argument type implies a null arg which is always a perfect match
+ if ((object)argumentTypes[i] != null && !Object.ReferenceEquals(parameterInfos[i].ParameterType, argumentTypes[i]))
+ return false;
+ }
+ }
+ }
+ #endregion
+ }
+ }
+ #endregion
+
+ return true;
+ }
+
+ #endregion
+
+ #endregion
+
+ #region Private Data Members
+ private object m_keepalive; // This will be filled with a LoaderAllocator reference when this RuntimeType represents a collectible type
+ private IntPtr m_cache;
+ internal IntPtr m_handle;
+
+#if FEATURE_APPX
+ private INVOCATION_FLAGS m_invocationFlags;
+
+ internal bool IsNonW8PFrameworkAPI()
+ {
+ if (IsGenericParameter)
+ return false;
+
+ if (HasElementType)
+ return ((RuntimeType)GetElementType()).IsNonW8PFrameworkAPI();
+
+ if (IsSimpleTypeNonW8PFrameworkAPI())
+ return true;
+
+ if (IsGenericType && !IsGenericTypeDefinition)
+ {
+ foreach (Type t in GetGenericArguments())
+ {
+ if (((RuntimeType)t).IsNonW8PFrameworkAPI())
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private bool IsSimpleTypeNonW8PFrameworkAPI()
+ {
+ RuntimeAssembly rtAssembly = GetRuntimeAssembly();
+ if (rtAssembly.IsFrameworkAssembly())
+ {
+ int ctorToken = rtAssembly.InvocableAttributeCtorToken;
+ if (System.Reflection.MetadataToken.IsNullToken(ctorToken) ||
+ !CustomAttribute.IsAttributeDefined(GetRuntimeModule(), MetadataToken, ctorToken))
+ return true;
+ }
+
+ return false;
+ }
+
+ internal INVOCATION_FLAGS InvocationFlags
+ {
+ get
+ {
+ if ((m_invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED) == 0)
+ {
+ INVOCATION_FLAGS invocationFlags = INVOCATION_FLAGS.INVOCATION_FLAGS_UNKNOWN;
+
+ if (AppDomain.ProfileAPICheck && IsNonW8PFrameworkAPI())
+ invocationFlags |= INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API;
+
+ m_invocationFlags = invocationFlags | INVOCATION_FLAGS.INVOCATION_FLAGS_INITIALIZED;
+ }
+
+ return m_invocationFlags;
+ }
+ }
+#endif // FEATURE_APPX
+
+ internal static readonly RuntimeType ValueType = (RuntimeType)typeof(System.ValueType);
+ internal static readonly RuntimeType EnumType = (RuntimeType)typeof(System.Enum);
+
+ private static readonly RuntimeType ObjectType = (RuntimeType)typeof(System.Object);
+ private static readonly RuntimeType StringType = (RuntimeType)typeof(System.String);
+ private static readonly RuntimeType DelegateType = (RuntimeType)typeof(System.Delegate);
+
+ private static Type[] s_SICtorParamTypes;
+ #endregion
+
+ #region Constructor
+ internal RuntimeType() { throw new NotSupportedException(); }
+ #endregion
+
+ #region Private\Internal Members
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal override bool CacheEquals(object o)
+ {
+ RuntimeType m = o as RuntimeType;
+
+ if (m == null)
+ return false;
+
+ return m.m_handle.Equals(m_handle);
+ }
+
+ private RuntimeTypeCache Cache
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (m_cache.IsNull())
+ {
+ IntPtr newgcHandle = new RuntimeTypeHandle(this).GetGCHandle(GCHandleType.WeakTrackResurrection);
+ IntPtr gcHandle = Interlocked.CompareExchange(ref m_cache, newgcHandle, (IntPtr)0);
+ // Leak the handle if the type is collectible. It will be reclaimed when
+ // the type goes away.
+ if (!gcHandle.IsNull() && !IsCollectible())
+ GCHandle.InternalFree(newgcHandle);
+ }
+
+ RuntimeTypeCache cache = GCHandle.InternalGet(m_cache) as RuntimeTypeCache;
+ if (cache == null)
+ {
+ cache = new RuntimeTypeCache(this);
+ RuntimeTypeCache existingCache = GCHandle.InternalCompareExchange(m_cache, cache, null, false) as RuntimeTypeCache;
+ if (existingCache != null)
+ cache = existingCache;
+ }
+
+ Contract.Assert(cache != null);
+ return cache;
+ }
+ }
+
+ internal bool IsSpecialSerializableType()
+ {
+ RuntimeType rt = this;
+ do
+ {
+ // In all sane cases we only need to compare the direct level base type with
+ // System.Enum and System.MulticastDelegate. However, a generic argument can
+ // have a base type constraint that is Delegate or even a real delegate type.
+ // Let's maintain compatibility and return true for them.
+ if (rt == RuntimeType.DelegateType || rt == RuntimeType.EnumType)
+ return true;
+
+ rt = rt.GetBaseType();
+ } while (rt != null);
+
+ return false;
+ }
+
+ private string GetDefaultMemberName()
+ {
+ return Cache.GetDefaultMemberName();
+ }
+
+#if !FEATURE_CORECLR
+ internal RuntimeConstructorInfo GetSerializationCtor()
+ {
+ return Cache.GetSerializationCtor();
+ }
+#endif
+ #endregion
+
+ #region Type Overrides
+
+ #region Get XXXInfo Candidates
+ private ListBuilder<MethodInfo> GetMethodCandidates(
+ String name, BindingFlags bindingAttr, CallingConventions callConv,
+ Type[] types, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimeMethodInfo[] cache = Cache.GetMethodList(listType, name);
+
+ ListBuilder<MethodInfo> candidates = new ListBuilder<MethodInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeMethodInfo methodInfo = cache[i];
+ if (FilterApplyMethodInfo(methodInfo, bindingAttr, callConv, types) &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(methodInfo, name, ignoreCase)))
+ {
+ candidates.Add(methodInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<ConstructorInfo> GetConstructorCandidates(
+ string name, BindingFlags bindingAttr, CallingConventions callConv,
+ Type[] types, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimeConstructorInfo[] cache = Cache.GetConstructorList(listType, name);
+
+ ListBuilder<ConstructorInfo> candidates = new ListBuilder<ConstructorInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeConstructorInfo constructorInfo = cache[i];
+ if (FilterApplyConstructorInfo(constructorInfo, bindingAttr, callConv, types) &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(constructorInfo, name, ignoreCase)))
+ {
+ candidates.Add(constructorInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+
+ private ListBuilder<PropertyInfo> GetPropertyCandidates(
+ String name, BindingFlags bindingAttr, Type[] types, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimePropertyInfo[] cache = Cache.GetPropertyList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<PropertyInfo> candidates = new ListBuilder<PropertyInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimePropertyInfo propertyInfo = cache[i];
+ if ((bindingAttr & propertyInfo.BindingFlags) == propertyInfo.BindingFlags &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(propertyInfo, name, ignoreCase)) &&
+ (types == null || (propertyInfo.GetIndexParameters().Length == types.Length)))
+ {
+ candidates.Add(propertyInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<EventInfo> GetEventCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimeEventInfo[] cache = Cache.GetEventList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<EventInfo> candidates = new ListBuilder<EventInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeEventInfo eventInfo = cache[i];
+ if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags &&
+ (!prefixLookup || RuntimeType.FilterApplyPrefixLookup(eventInfo, name, ignoreCase)))
+ {
+ candidates.Add(eventInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<FieldInfo> GetFieldCandidates(String name, BindingFlags bindingAttr, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimeFieldInfo[] cache = Cache.GetFieldList(listType, name);
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ ListBuilder<FieldInfo> candidates = new ListBuilder<FieldInfo>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeFieldInfo fieldInfo = cache[i];
+ if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags &&
+ (!prefixLookup || FilterApplyPrefixLookup(fieldInfo, name, ignoreCase)))
+ {
+ candidates.Add(fieldInfo);
+ }
+ }
+
+ return candidates;
+ }
+
+ private ListBuilder<Type> GetNestedTypeCandidates(String fullname, BindingFlags bindingAttr, bool allowPrefixLookup)
+ {
+ bool prefixLookup, ignoreCase;
+ bindingAttr &= ~BindingFlags.Static;
+ string name, ns;
+ MemberListType listType;
+ SplitName(fullname, out name, out ns);
+ RuntimeType.FilterHelper(bindingAttr, ref name, allowPrefixLookup, out prefixLookup, out ignoreCase, out listType);
+
+ RuntimeType[] cache = Cache.GetNestedTypeList(listType, name);
+
+ ListBuilder<Type> candidates = new ListBuilder<Type>(cache.Length);
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType nestedClass = cache[i];
+ if (RuntimeType.FilterApplyType(nestedClass, bindingAttr, name, prefixLookup, ns))
+ {
+ candidates.Add(nestedClass);
+ }
+ }
+
+ return candidates;
+ }
+ #endregion
+
+ #region Get All XXXInfos
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
+ {
+ return GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray();
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
+ {
+ return GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false).ToArray();
+ }
+
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
+ {
+ return GetPropertyCandidates(null, bindingAttr, null, false).ToArray();
+ }
+
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr)
+ {
+ return GetEventCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr)
+ {
+ return GetFieldCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type[] GetInterfaces()
+ {
+ RuntimeType[] candidates = this.Cache.GetInterfaceList(MemberListType.All, null);
+ Type[] interfaces = new Type[candidates.Length];
+ for (int i = 0; i < candidates.Length; i++)
+ JitHelpers.UnsafeSetArrayElement(interfaces, i, candidates[i]);
+
+ return interfaces;
+ }
+
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr)
+ {
+ return GetNestedTypeCandidates(null, bindingAttr, false).ToArray();
+ }
+
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
+ {
+ ListBuilder<MethodInfo> methods = GetMethodCandidates(null, bindingAttr, CallingConventions.Any, null, false);
+ ListBuilder<ConstructorInfo> constructors = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, null, false);
+ ListBuilder<PropertyInfo> properties = GetPropertyCandidates(null, bindingAttr, null, false);
+ ListBuilder<EventInfo> events = GetEventCandidates(null, bindingAttr, false);
+ ListBuilder<FieldInfo> fields = GetFieldCandidates(null, bindingAttr, false);
+ ListBuilder<Type> nestedTypes = GetNestedTypeCandidates(null, bindingAttr, false);
+ // Interfaces are excluded from the result of GetMembers
+
+ MemberInfo[] members = new MemberInfo[
+ methods.Count +
+ constructors.Count +
+ properties.Count +
+ events.Count +
+ fields.Count +
+ nestedTypes.Count];
+
+ int i = 0;
+ methods.CopyTo(members, i); i += methods.Count;
+ constructors.CopyTo(members, i); i += constructors.Count;
+ properties.CopyTo(members, i); i += properties.Count;
+ events.CopyTo(members, i); i += events.Count;
+ fields.CopyTo(members, i); i += fields.Count;
+ nestedTypes.CopyTo(members, i); i += nestedTypes.Count;
+ Contract.Assert(i == members.Length);
+
+ return members;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override InterfaceMapping GetInterfaceMap(Type ifaceType)
+ {
+ if (IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
+
+ if ((object)ifaceType == null)
+ throw new ArgumentNullException("ifaceType");
+ Contract.EndContractBlock();
+
+ RuntimeType ifaceRtType = ifaceType as RuntimeType;
+
+ if (ifaceRtType == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "ifaceType");
+
+ RuntimeTypeHandle ifaceRtTypeHandle = ifaceRtType.GetTypeHandleInternal();
+
+ GetTypeHandleInternal().VerifyInterfaceIsImplemented(ifaceRtTypeHandle);
+ Contract.Assert(ifaceType.IsInterface); // VerifyInterfaceIsImplemented enforces this invariant
+ Contract.Assert(!IsInterface); // VerifyInterfaceIsImplemented enforces this invariant
+
+ // SZArrays implement the methods on IList`1, IEnumerable`1, and ICollection`1 with
+ // SZArrayHelper and some runtime magic. We don't have accurate interface maps for them.
+ if (IsSzArray && ifaceType.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArrayGetInterfaceMap"));
+
+ int ifaceInstanceMethodCount = RuntimeTypeHandle.GetNumVirtuals(ifaceRtType);
+
+ InterfaceMapping im;
+ im.InterfaceType = ifaceType;
+ im.TargetType = this;
+ im.InterfaceMethods = new MethodInfo[ifaceInstanceMethodCount];
+ im.TargetMethods = new MethodInfo[ifaceInstanceMethodCount];
+
+ for (int i = 0; i < ifaceInstanceMethodCount; i++)
+ {
+ RuntimeMethodHandleInternal ifaceRtMethodHandle = RuntimeTypeHandle.GetMethodAt(ifaceRtType, i);
+
+ // GetMethodBase will convert this to the instantiating/unboxing stub if necessary
+ MethodBase ifaceMethodBase = RuntimeType.GetMethodBase(ifaceRtType, ifaceRtMethodHandle);
+ Contract.Assert(ifaceMethodBase is RuntimeMethodInfo);
+ im.InterfaceMethods[i] = (MethodInfo)ifaceMethodBase;
+
+ // If the slot is -1, then virtual stub dispatch is active.
+ int slot = GetTypeHandleInternal().GetInterfaceMethodImplementationSlot(ifaceRtTypeHandle, ifaceRtMethodHandle);
+
+ if (slot == -1) continue;
+
+ RuntimeMethodHandleInternal classRtMethodHandle = RuntimeTypeHandle.GetMethodAt(this, slot);
+
+ // GetMethodBase will convert this to the instantiating/unboxing stub if necessary
+ MethodBase rtTypeMethodBase = RuntimeType.GetMethodBase(this, classRtMethodHandle);
+ // a class may not implement all the methods of an interface (abstract class) so null is a valid value
+ Contract.Assert(rtTypeMethodBase == null || rtTypeMethodBase is RuntimeMethodInfo);
+ im.TargetMethods[i] = (MethodInfo)rtTypeMethodBase;
+ }
+
+ return im;
+ }
+ #endregion
+
+ #region Find XXXInfo
+ protected override MethodInfo GetMethodImpl(
+ String name, BindingFlags bindingAttr, Binder binder, CallingConventions callConv,
+ Type[] types, ParameterModifier[] modifiers)
+ {
+ ListBuilder<MethodInfo> candidates = GetMethodCandidates(name, bindingAttr, callConv, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types == null || types.Length == 0)
+ {
+ MethodInfo firstCandidate = candidates[0];
+
+ if (candidates.Count == 1)
+ {
+ return firstCandidate;
+ }
+ else if (types == null)
+ {
+ for (int j = 1; j < candidates.Count; j++)
+ {
+ MethodInfo methodInfo = candidates[j];
+ if (!System.DefaultBinder.CompareMethodSigAndName(methodInfo, firstCandidate))
+ {
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ }
+ }
+
+ // All the methods have the exact same name and sig so return the most derived one.
+ return System.DefaultBinder.FindMostDerivedNewSlotMeth(candidates.ToArray(), candidates.Count) as MethodInfo;
+ }
+ }
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as MethodInfo;
+ }
+
+
+ protected override ConstructorInfo GetConstructorImpl(
+ BindingFlags bindingAttr, Binder binder, CallingConventions callConvention,
+ Type[] types, ParameterModifier[] modifiers)
+ {
+ ListBuilder<ConstructorInfo> candidates = GetConstructorCandidates(null, bindingAttr, CallingConventions.Any, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types.Length == 0 && candidates.Count == 1)
+ {
+ ConstructorInfo firstCandidate = candidates[0];
+
+ ParameterInfo[] parameters = firstCandidate.GetParametersNoCopy();
+ if (parameters == null || parameters.Length == 0)
+ {
+ return firstCandidate;
+ }
+ }
+
+ if ((bindingAttr & BindingFlags.ExactBinding) != 0)
+ return System.DefaultBinder.ExactBinding(candidates.ToArray(), types, modifiers) as ConstructorInfo;
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectMethod(bindingAttr, candidates.ToArray(), types, modifiers) as ConstructorInfo;
+ }
+
+
+ protected override PropertyInfo GetPropertyImpl(
+ String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ ListBuilder<PropertyInfo> candidates = GetPropertyCandidates(name, bindingAttr, types, false);
+
+ if (candidates.Count == 0)
+ return null;
+
+ if (types == null || types.Length == 0)
+ {
+ // no arguments
+ if (candidates.Count == 1)
+ {
+ PropertyInfo firstCandidate = candidates[0];
+
+ if ((object)returnType != null && !returnType.IsEquivalentTo(firstCandidate.PropertyType))
+ return null;
+
+ return firstCandidate;
+ }
+ else
+ {
+ if ((object)returnType == null)
+ // if we are here we have no args or property type to select over and we have more than one property with that name
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+ }
+ }
+
+ if ((bindingAttr & BindingFlags.ExactBinding) != 0)
+ return System.DefaultBinder.ExactPropertyBinding(candidates.ToArray(), returnType, types, modifiers);
+
+ if (binder == null)
+ binder = DefaultBinder;
+
+ return binder.SelectProperty(bindingAttr, candidates.ToArray(), returnType, types, modifiers);
+ }
+
+
+ public override EventInfo GetEvent(String name, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ bool ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeEventInfo[] cache = Cache.GetEventList(listType, name);
+ EventInfo match = null;
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeEventInfo eventInfo = cache[i];
+ if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags)
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = eventInfo;
+ }
+ }
+
+ return match;
+ }
+
+ public override FieldInfo GetField(String name, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ bool ignoreCase;
+ MemberListType listType;
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeFieldInfo[] cache = Cache.GetFieldList(listType, name);
+ FieldInfo match = null;
+
+ bindingAttr ^= BindingFlags.DeclaredOnly;
+ bool multipleStaticFieldMatches = false;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeFieldInfo fieldInfo = cache[i];
+ if ((bindingAttr & fieldInfo.BindingFlags) == fieldInfo.BindingFlags)
+ {
+ if (match != null)
+ {
+ if (Object.ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType))
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ if ((match.DeclaringType.IsInterface == true) && (fieldInfo.DeclaringType.IsInterface == true))
+ multipleStaticFieldMatches = true;
+ }
+
+ if (match == null || fieldInfo.DeclaringType.IsSubclassOf(match.DeclaringType) || match.DeclaringType.IsInterface)
+ match = fieldInfo;
+ }
+ }
+
+ if (multipleStaticFieldMatches && match.DeclaringType.IsInterface)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ return match;
+ }
+
+ public override Type GetInterface(String fullname, bool ignoreCase)
+ {
+ if (fullname == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.NonPublic;
+
+ bindingAttr &= ~BindingFlags.Static;
+
+ if (ignoreCase)
+ bindingAttr |= BindingFlags.IgnoreCase;
+
+ string name, ns;
+ MemberListType listType;
+ SplitName(fullname, out name, out ns);
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeType[] cache = Cache.GetInterfaceList(listType, name);
+
+ RuntimeType match = null;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType iface = cache[i];
+ if (RuntimeType.FilterApplyType(iface, bindingAttr, name, false, ns))
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = iface;
+ }
+ }
+
+ return match;
+ }
+
+ public override Type GetNestedType(String fullname, BindingFlags bindingAttr)
+ {
+ if (fullname == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ bool ignoreCase;
+ bindingAttr &= ~BindingFlags.Static;
+ string name, ns;
+ MemberListType listType;
+ SplitName(fullname, out name, out ns);
+ RuntimeType.FilterHelper(bindingAttr, ref name, out ignoreCase, out listType);
+
+ RuntimeType[] cache = Cache.GetNestedTypeList(listType, name);
+
+ RuntimeType match = null;
+
+ for (int i = 0; i < cache.Length; i++)
+ {
+ RuntimeType nestedType = cache[i];
+ if (RuntimeType.FilterApplyType(nestedType, bindingAttr, name, false, ns))
+ {
+ if (match != null)
+ throw new AmbiguousMatchException(Environment.GetResourceString("Arg_AmbiguousMatchException"));
+
+ match = nestedType;
+ }
+ }
+
+ return match;
+ }
+
+ public override MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ if (name == null) throw new ArgumentNullException();
+ Contract.EndContractBlock();
+
+ ListBuilder<MethodInfo> methods = new ListBuilder<MethodInfo>();
+ ListBuilder<ConstructorInfo> constructors = new ListBuilder<ConstructorInfo>();
+ ListBuilder<PropertyInfo> properties = new ListBuilder<PropertyInfo>();
+ ListBuilder<EventInfo> events = new ListBuilder<EventInfo>();
+ ListBuilder<FieldInfo> fields = new ListBuilder<FieldInfo>();
+ ListBuilder<Type> nestedTypes = new ListBuilder<Type>();
+
+ int totalCount = 0;
+
+ // Methods
+ if ((type & MemberTypes.Method) != 0)
+ {
+ methods = GetMethodCandidates(name, bindingAttr, CallingConventions.Any, null, true);
+ if (type == MemberTypes.Method)
+ return methods.ToArray();
+ totalCount += methods.Count;
+ }
+
+ // Constructors
+ if ((type & MemberTypes.Constructor) != 0)
+ {
+ constructors = GetConstructorCandidates(name, bindingAttr, CallingConventions.Any, null, true);
+ if (type == MemberTypes.Constructor)
+ return constructors.ToArray();
+ totalCount += constructors.Count;
+ }
+
+ // Properties
+ if ((type & MemberTypes.Property) != 0)
+ {
+ properties = GetPropertyCandidates(name, bindingAttr, null, true);
+ if (type == MemberTypes.Property)
+ return properties.ToArray();
+ totalCount += properties.Count;
+ }
+
+ // Events
+ if ((type & MemberTypes.Event) != 0)
+ {
+ events = GetEventCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.Event)
+ return events.ToArray();
+ totalCount += events.Count;
+ }
+
+ // Fields
+ if ((type & MemberTypes.Field) != 0)
+ {
+ fields = GetFieldCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.Field)
+ return fields.ToArray();
+ totalCount += fields.Count;
+ }
+
+ // NestedTypes
+ if ((type & (MemberTypes.NestedType | MemberTypes.TypeInfo)) != 0)
+ {
+ nestedTypes = GetNestedTypeCandidates(name, bindingAttr, true);
+ if (type == MemberTypes.NestedType || type == MemberTypes.TypeInfo)
+ return nestedTypes.ToArray();
+ totalCount += nestedTypes.Count;
+ }
+
+ MemberInfo[] compressMembers = (type == (MemberTypes.Method | MemberTypes.Constructor)) ?
+ new MethodBase[totalCount] : new MemberInfo[totalCount];
+
+ int i = 0;
+ methods.CopyTo(compressMembers, i); i += methods.Count;
+ constructors.CopyTo(compressMembers, i); i += constructors.Count;
+ properties.CopyTo(compressMembers, i); i += properties.Count;
+ events.CopyTo(compressMembers, i); i += events.Count;
+ fields.CopyTo(compressMembers, i); i += fields.Count;
+ nestedTypes.CopyTo(compressMembers, i); i += nestedTypes.Count;
+ Contract.Assert(i == compressMembers.Length);
+
+ return compressMembers;
+ }
+ #endregion
+
+ #region Identity
+ public override Module Module
+ {
+ get
+ {
+ return GetRuntimeModule();
+ }
+ }
+
+ internal RuntimeModule GetRuntimeModule()
+ {
+ return RuntimeTypeHandle.GetModule(this);
+ }
+
+ public override Assembly Assembly
+ {
+ get
+ {
+ return GetRuntimeAssembly();
+ }
+ }
+
+ internal RuntimeAssembly GetRuntimeAssembly()
+ {
+ return RuntimeTypeHandle.GetAssembly(this);
+ }
+
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ return new RuntimeTypeHandle(this);
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal sealed override RuntimeTypeHandle GetTypeHandleInternal()
+ {
+ return new RuntimeTypeHandle(this);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal bool IsCollectible()
+ {
+ return RuntimeTypeHandle.IsCollectible(GetTypeHandleInternal());
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override TypeCode GetTypeCodeImpl()
+ {
+ TypeCode typeCode = Cache.TypeCode;
+
+ if (typeCode != TypeCode.Empty)
+ return typeCode;
+
+ CorElementType corElementType = RuntimeTypeHandle.GetCorElementType(this);
+ switch (corElementType)
+ {
+ case CorElementType.Boolean:
+ typeCode = TypeCode.Boolean; break;
+ case CorElementType.Char:
+ typeCode = TypeCode.Char; break;
+ case CorElementType.I1:
+ typeCode = TypeCode.SByte; break;
+ case CorElementType.U1:
+ typeCode = TypeCode.Byte; break;
+ case CorElementType.I2:
+ typeCode = TypeCode.Int16; break;
+ case CorElementType.U2:
+ typeCode = TypeCode.UInt16; break;
+ case CorElementType.I4:
+ typeCode = TypeCode.Int32; break;
+ case CorElementType.U4:
+ typeCode = TypeCode.UInt32; break;
+ case CorElementType.I8:
+ typeCode = TypeCode.Int64; break;
+ case CorElementType.U8:
+ typeCode = TypeCode.UInt64; break;
+ case CorElementType.R4:
+ typeCode = TypeCode.Single; break;
+ case CorElementType.R8:
+ typeCode = TypeCode.Double; break;
+ case CorElementType.String:
+ typeCode = TypeCode.String; break;
+ case CorElementType.ValueType:
+ if (this == Convert.ConvertTypes[(int)TypeCode.Decimal])
+ typeCode = TypeCode.Decimal;
+ else if (this == Convert.ConvertTypes[(int)TypeCode.DateTime])
+ typeCode = TypeCode.DateTime;
+ else if (this.IsEnum)
+ typeCode = Type.GetTypeCode(Enum.GetUnderlyingType(this));
+ else
+ typeCode = TypeCode.Object;
+ break;
+ default:
+ if (this == Convert.ConvertTypes[(int)TypeCode.DBNull])
+ typeCode = TypeCode.DBNull;
+ else if (this == Convert.ConvertTypes[(int)TypeCode.String])
+ typeCode = TypeCode.String;
+ else
+ typeCode = TypeCode.Object;
+ break;
+ }
+
+ Cache.TypeCode = typeCode;
+
+ return typeCode;
+ }
+
+ public override MethodBase DeclaringMethod
+ {
+ get
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ IRuntimeMethodInfo declaringMethod = RuntimeTypeHandle.GetDeclaringMethod(this);
+
+ if (declaringMethod == null)
+ return null;
+
+ return GetMethodBase(RuntimeMethodHandle.GetDeclaringType(declaringMethod), declaringMethod);
+ }
+ }
+ #endregion
+
+ #region Hierarchy
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsInstanceOfType(Object o)
+ {
+ return RuntimeTypeHandle.IsInstanceOfType(this, o);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public override bool IsSubclassOf(Type type)
+ {
+ if ((object)type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ RuntimeType rtType = type as RuntimeType;
+ if (rtType == null)
+ return false;
+
+ RuntimeType baseType = GetBaseType();
+
+ while (baseType != null)
+ {
+ if (baseType == rtType)
+ return true;
+
+ baseType = baseType.GetBaseType();
+ }
+
+ // pretty much everything is a subclass of object, even interfaces
+ // notice that interfaces are really odd because they do not have a BaseType
+ // yet IsSubclassOf(typeof(object)) returns true
+ if (rtType == RuntimeType.ObjectType && rtType != this)
+ return true;
+
+ return false;
+ }
+
+ public override bool IsAssignableFrom(System.Reflection.TypeInfo typeInfo){
+ if(typeInfo==null) return false;
+ return IsAssignableFrom(typeInfo.AsType());
+ }
+
+ public override bool IsAssignableFrom(Type c)
+ {
+ if ((object)c == null)
+ return false;
+
+ if (Object.ReferenceEquals(c, this))
+ return true;
+
+ RuntimeType fromType = c.UnderlyingSystemType as RuntimeType;
+
+ // For runtime type, let the VM decide.
+ if (fromType != null)
+ {
+ // both this and c (or their underlying system types) are runtime types
+ return RuntimeTypeHandle.CanCastTo(fromType, this);
+ }
+
+ // Special case for TypeBuilder to be backward-compatible.
+ if (c is System.Reflection.Emit.TypeBuilder)
+ {
+ // If c is a subclass of this class, then c can be cast to this type.
+ if (c.IsSubclassOf(this))
+ return true;
+
+ if (this.IsInterface)
+ {
+ return c.ImplementInterface(this);
+ }
+ else if (this.IsGenericParameter)
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+ for (int i = 0; i < constraints.Length; i++)
+ if (!constraints[i].IsAssignableFrom(c))
+ return false;
+
+ return true;
+ }
+ }
+
+ // For anything else we return false.
+ return false;
+ }
+
+#if !FEATURE_CORECLR
+ // Reflexive, symmetric, transitive.
+ public override bool IsEquivalentTo(Type other)
+ {
+ RuntimeType otherRtType = other as RuntimeType;
+ if ((object)otherRtType == null)
+ return false;
+
+ if (otherRtType == this)
+ return true;
+
+ // It's not worth trying to perform further checks in managed
+ // as they would lead to FCalls anyway.
+ return RuntimeTypeHandle.IsEquivalentTo(this, otherRtType);
+ }
+#endif // FEATURE_CORECLR
+
+ public override Type BaseType
+ {
+ get
+ {
+ return GetBaseType();
+ }
+ }
+
+ private RuntimeType GetBaseType()
+ {
+ if (IsInterface)
+ return null;
+
+ if (RuntimeTypeHandle.IsGenericVariable(this))
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+
+ RuntimeType baseType = RuntimeType.ObjectType;
+
+ for (int i = 0; i < constraints.Length; i++)
+ {
+ RuntimeType constraint = (RuntimeType)constraints[i];
+
+ if (constraint.IsInterface)
+ continue;
+
+ if (constraint.IsGenericParameter)
+ {
+ GenericParameterAttributes special;
+ special = constraint.GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
+
+ if ((special & GenericParameterAttributes.ReferenceTypeConstraint) == 0 &&
+ (special & GenericParameterAttributes.NotNullableValueTypeConstraint) == 0)
+ continue;
+ }
+
+ baseType = constraint;
+ }
+
+ if (baseType == RuntimeType.ObjectType)
+ {
+ GenericParameterAttributes special;
+ special = GenericParameterAttributes & GenericParameterAttributes.SpecialConstraintMask;
+ if ((special & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0)
+ baseType = RuntimeType.ValueType;
+ }
+
+ return baseType;
+ }
+
+ return RuntimeTypeHandle.GetBaseType(this);
+ }
+
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ return this;
+ }
+ }
+ #endregion
+
+ #region Name
+ public override String FullName
+ {
+ get
+ {
+ return GetCachedName(TypeNameKind.FullName);
+ }
+ }
+
+ public override String AssemblyQualifiedName
+ {
+ get
+ {
+ string fullname = FullName;
+
+ // FullName is null if this type contains generic parameters but is not a generic type definition.
+ if (fullname == null)
+ return null;
+
+ return Assembly.CreateQualifiedName(this.Assembly.FullName, fullname);
+ }
+ }
+
+ public override String Namespace
+ {
+ get
+ {
+ string ns = Cache.GetNameSpace();
+
+ if (ns == null || ns.Length == 0)
+ return null;
+
+ return ns;
+ }
+ }
+ #endregion
+
+ #region Attributes
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override TypeAttributes GetAttributeFlagsImpl()
+ {
+ return RuntimeTypeHandle.GetAttributes(this);
+ }
+
+ public override Guid GUID
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ Guid result = new Guid ();
+ GetGUID(ref result);
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void GetGUID(ref Guid result);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override bool IsContextfulImpl()
+ {
+ return RuntimeTypeHandle.IsContextful(this);
+ }
+
+ /*
+ protected override bool IsMarshalByRefImpl()
+ {
+ return GetTypeHandleInternal().IsMarshalByRef();
+ }
+ */
+
+ protected override bool IsByRefImpl()
+ {
+ return RuntimeTypeHandle.IsByRef(this);
+ }
+
+ protected override bool IsPrimitiveImpl()
+ {
+ return RuntimeTypeHandle.IsPrimitive(this);
+ }
+
+ protected override bool IsPointerImpl()
+ {
+ return RuntimeTypeHandle.IsPointer(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected override bool IsCOMObjectImpl()
+ {
+ return RuntimeTypeHandle.IsComObject(this, false);
+ }
+
+#if FEATURE_COMINTEROP
+ [SecuritySafeCritical]
+ internal override bool IsWindowsRuntimeObjectImpl()
+ {
+ return IsWindowsRuntimeObjectType(this);
+ }
+
+ [SecuritySafeCritical]
+ internal override bool IsExportedToWindowsRuntimeImpl()
+ {
+ return IsTypeExportedToWindowsRuntime(this);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ private static extern bool IsWindowsRuntimeObjectType(RuntimeType type);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ private static extern bool IsTypeExportedToWindowsRuntime(RuntimeType type);
+
+#endif // FEATURE_COMINTEROP
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal override bool HasProxyAttributeImpl()
+ {
+ return RuntimeTypeHandle.HasProxyAttribute(this);
+ }
+
+ internal bool IsDelegate()
+ {
+ return GetBaseType() == typeof(System.MulticastDelegate);
+ }
+
+ protected override bool IsValueTypeImpl()
+ {
+ // We need to return true for generic parameters with the ValueType constraint.
+ // So we cannot use the faster RuntimeTypeHandle.IsValueType because it returns
+ // false for all generic parameters.
+ if (this == typeof(ValueType) || this == typeof(Enum))
+ return false;
+
+ return IsSubclassOf(typeof(ValueType));
+ }
+
+#if !FEATURE_CORECLR
+ public override bool IsEnum
+ {
+ get
+ {
+ return GetBaseType() == RuntimeType.EnumType;
+ }
+ }
+#endif
+
+ protected override bool HasElementTypeImpl()
+ {
+ return RuntimeTypeHandle.HasElementType(this);
+ }
+
+ public override GenericParameterAttributes GenericParameterAttributes
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ GenericParameterAttributes attributes;
+
+ RuntimeTypeHandle.GetMetadataImport(this).GetGenericParamProps(MetadataToken, out attributes);
+
+ return attributes;
+ }
+ }
+
+ public override bool IsSecurityCritical
+ {
+ get { return new RuntimeTypeHandle(this).IsSecurityCritical(); }
+ }
+ public override bool IsSecuritySafeCritical
+ {
+ get { return new RuntimeTypeHandle(this).IsSecuritySafeCritical(); }
+ }
+ public override bool IsSecurityTransparent
+ {
+ get { return new RuntimeTypeHandle(this).IsSecurityTransparent(); }
+ }
+ #endregion
+
+ #region Arrays
+ internal override bool IsSzArray
+ {
+ get
+ {
+ return RuntimeTypeHandle.IsSzArray(this);
+ }
+ }
+
+ protected override bool IsArrayImpl()
+ {
+ return RuntimeTypeHandle.IsArray(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override int GetArrayRank()
+ {
+ if (!IsArrayImpl())
+ throw new ArgumentException(Environment.GetResourceString("Argument_HasToBeArrayClass"));
+
+ return RuntimeTypeHandle.GetArrayRank(this);
+ }
+
+ public override Type GetElementType()
+ {
+ return RuntimeTypeHandle.GetElementType(this);
+ }
+ #endregion
+
+ #region Enums
+ public override string[] GetEnumNames()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ String[] ret = Enum.InternalGetNames(this);
+
+ // Make a copy since we can't hand out the same array since users can modify them
+ String[] retVal = new String[ret.Length];
+
+ Array.Copy(ret, retVal, ret.Length);
+
+ return retVal;
+ }
+
+ [SecuritySafeCritical]
+ public override Array GetEnumValues()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ // Get all of the values
+ ulong[] values = Enum.InternalGetValues(this);
+
+ // Create a generic Array
+ Array ret = Array.UnsafeCreateInstance(this, values.Length);
+
+ for (int i = 0; i < values.Length; i++)
+ {
+ Object val = Enum.ToObject(this, values[i]);
+ ret.SetValue(val, i);
+ }
+
+ return ret;
+ }
+
+ public override Type GetEnumUnderlyingType()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ return Enum.InternalGetUnderlyingType(this);
+ }
+
+ public override bool IsEnumDefined(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Check if both of them are of the same type
+ RuntimeType valueType = (RuntimeType)value.GetType();
+
+ // If the value is an Enum then we need to extract the underlying value from it
+ if (valueType.IsEnum)
+ {
+ if (!valueType.IsEquivalentTo(this))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));
+
+ valueType = (RuntimeType)valueType.GetEnumUnderlyingType();
+ }
+
+ // If a string is passed in
+ if (valueType == RuntimeType.StringType)
+ {
+ // Get all of the Fields, calling GetHashEntry directly to avoid copying
+ string[] names = Enum.InternalGetNames(this);
+ if (Array.IndexOf(names, value) >= 0)
+ return true;
+ else
+ return false;
+ }
+
+ // If an enum or integer value is passed in
+ if (Type.IsIntegerType(valueType))
+ {
+ RuntimeType underlyingType = Enum.InternalGetUnderlyingType(this);
+ if (underlyingType != valueType)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+
+ ulong[] ulValues = Enum.InternalGetValues(this);
+ ulong ulValue = Enum.ToUInt64(value);
+
+ return (Array.BinarySearch(ulValues, ulValue) >= 0);
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+
+ public override string GetEnumName(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ Type valueType = value.GetType();
+
+ if (!(valueType.IsEnum || IsIntegerType(valueType)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+
+ ulong ulValue = Enum.ToUInt64(value);
+
+ return Enum.GetEnumName(this, ulValue);
+ }
+ #endregion
+
+ #region Generics
+ internal RuntimeType[] GetGenericArgumentsInternal()
+ {
+ return GetRootElementType().GetTypeHandleInternal().GetInstantiationInternal();
+ }
+
+ public override Type[] GetGenericArguments()
+ {
+ Type[] types = GetRootElementType().GetTypeHandleInternal().GetInstantiationPublic();
+
+ if (types == null)
+ types = EmptyArray<Type>.Value;
+
+ return types;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type MakeGenericType(Type[] instantiation)
+ {
+ if (instantiation == null)
+ throw new ArgumentNullException("instantiation");
+ Contract.EndContractBlock();
+
+ RuntimeType[] instantiationRuntimeType = new RuntimeType[instantiation.Length];
+
+ if (!IsGenericTypeDefinition)
+ throw new InvalidOperationException(
+ Environment.GetResourceString("Arg_NotGenericTypeDefinition", this));
+
+ if (GetGenericArguments().Length != instantiation.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_GenericArgsCount"), "instantiation");
+
+ for (int i = 0; i < instantiation.Length; i ++)
+ {
+ Type instantiationElem = instantiation[i];
+ if (instantiationElem == null)
+ throw new ArgumentNullException();
+
+ RuntimeType rtInstantiationElem = instantiationElem as RuntimeType;
+
+ if (rtInstantiationElem == null)
+ {
+ Type[] instantiationCopy = new Type[instantiation.Length];
+ for (int iCopy = 0; iCopy < instantiation.Length; iCopy++)
+ instantiationCopy[iCopy] = instantiation[iCopy];
+ instantiation = instantiationCopy;
+ return System.Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, instantiation);
+ }
+
+ instantiationRuntimeType[i] = rtInstantiationElem;
+ }
+
+ RuntimeType[] genericParameters = GetGenericArgumentsInternal();
+
+ SanityCheckGenericArguments(instantiationRuntimeType, genericParameters);
+
+ Type ret = null;
+ try
+ {
+ ret = new RuntimeTypeHandle(this).Instantiate(instantiationRuntimeType);
+ }
+ catch (TypeLoadException e)
+ {
+ ValidateGenericArguments(this, instantiationRuntimeType, e);
+ throw e;
+ }
+
+ return ret;
+ }
+
+ public override bool IsGenericTypeDefinition
+ {
+ get { return RuntimeTypeHandle.IsGenericTypeDefinition(this); }
+ }
+
+ public override bool IsGenericParameter
+ {
+ get { return RuntimeTypeHandle.IsGenericVariable(this); }
+ }
+
+ public override int GenericParameterPosition
+ {
+ get
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ return new RuntimeTypeHandle(this).GetGenericVariableIndex();
+ }
+ }
+
+ public override Type GetGenericTypeDefinition()
+ {
+ if (!IsGenericType)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotGenericType"));
+ Contract.EndContractBlock();
+
+ return RuntimeTypeHandle.GetGenericTypeDefinition(this);
+ }
+
+ public override bool IsGenericType
+ {
+ get { return RuntimeTypeHandle.HasInstantiation(this); }
+ }
+
+ public override bool IsConstructedGenericType
+ {
+ get { return IsGenericType && !IsGenericTypeDefinition; }
+ }
+
+ public override bool ContainsGenericParameters
+ {
+ get { return GetRootElementType().GetTypeHandleInternal().ContainsGenericVariables(); }
+ }
+
+ public override Type[] GetGenericParameterConstraints()
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ Type[] constraints = new RuntimeTypeHandle(this).GetConstraints();
+
+ if (constraints == null)
+ constraints = EmptyArray<Type>.Value;
+
+ return constraints;
+ }
+ #endregion
+
+ #region Misc
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Type MakePointerType() { return new RuntimeTypeHandle(this).MakePointer(); }
+ public override Type MakeByRefType() { return new RuntimeTypeHandle(this).MakeByRef(); }
+ public override Type MakeArrayType() { return new RuntimeTypeHandle(this).MakeSZArray(); }
+ public override Type MakeArrayType(int rank)
+ {
+ if (rank <= 0)
+ throw new IndexOutOfRangeException();
+ Contract.EndContractBlock();
+
+ return new RuntimeTypeHandle(this).MakeArray(rank);
+ }
+ public override StructLayoutAttribute StructLayoutAttribute
+ {
+ [System.Security.SecuritySafeCritical] // overrides transparent public member
+ get
+ {
+ return (StructLayoutAttribute)StructLayoutAttribute.GetCustomAttribute(this);
+ }
+ }
+ #endregion
+
+ #region Invoke Member
+ private const BindingFlags MemberBindingMask = (BindingFlags)0x000000FF;
+ private const BindingFlags InvocationMask = (BindingFlags)0x0000FF00;
+ private const BindingFlags BinderNonCreateInstance = BindingFlags.InvokeMethod | BinderGetSetField | BinderGetSetProperty;
+ private const BindingFlags BinderGetSetProperty = BindingFlags.GetProperty | BindingFlags.SetProperty;
+ private const BindingFlags BinderSetInvokeProperty = BindingFlags.InvokeMethod | BindingFlags.SetProperty;
+ private const BindingFlags BinderGetSetField = BindingFlags.GetField | BindingFlags.SetField;
+ private const BindingFlags BinderSetInvokeField = BindingFlags.SetField | BindingFlags.InvokeMethod;
+ private const BindingFlags BinderNonFieldGetSet = (BindingFlags)0x00FFF300;
+ private const BindingFlags ClassicBindingMask =
+ BindingFlags.InvokeMethod | BindingFlags.GetProperty | BindingFlags.SetProperty |
+ BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty;
+ private static RuntimeType s_typedRef = (RuntimeType)typeof(TypedReference);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static private extern bool CanValueSpecialCast(RuntimeType valueType, RuntimeType targetType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static private extern Object AllocateValueType(RuntimeType type, object value, bool fForceTypeChange);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe Object CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
+ {
+ // this method is used by invocation in reflection to check whether a value can be assigned to type.
+ if (IsInstanceOfType(value))
+ {
+ // Since this cannot be a generic parameter, we use RuntimeTypeHandle.IsValueType here
+ // because it is faster than RuntimeType.IsValueType
+ Contract.Assert(!IsGenericParameter);
+
+ Type type = null;
+
+#if FEATURE_REMOTING
+ // For the remoting objects Object.GetType goes through proxy. Avoid the proxy call and just get
+ // the type directly. It is necessary to support proxies that do not handle GetType.
+ RealProxy realProxy = System.Runtime.Remoting.RemotingServices.GetRealProxy(value);
+
+ if (realProxy != null)
+ {
+ type = realProxy.GetProxiedType();
+ }
+ else
+ {
+ type = value.GetType();
+ }
+#else
+ type = value.GetType();
+#endif
+
+ if (!Object.ReferenceEquals(type, this) && RuntimeTypeHandle.IsValueType(this))
+ {
+ // must be an equivalent type, re-box to the target type
+ return AllocateValueType(this, value, true);
+ }
+ else
+ {
+ return value;
+ }
+ }
+
+ // if this is a ByRef get the element type and check if it's compatible
+ bool isByRef = IsByRef;
+ if (isByRef)
+ {
+ RuntimeType elementType = RuntimeTypeHandle.GetElementType(this);
+ if (elementType.IsInstanceOfType(value) || value == null)
+ {
+ // need to create an instance of the ByRef if null was provided, but only if primitive, enum or value type
+ return AllocateValueType(elementType, value, false);
+ }
+ }
+ else if (value == null)
+ return value;
+ else if (this == s_typedRef)
+ // everything works for a typedref
+ return value;
+
+ // check the strange ones courtesy of reflection:
+ // - implicit cast between primitives
+ // - enum treated as underlying type
+ // - IntPtr and System.Reflection.Pointer to pointer types
+ bool needsSpecialCast = IsPointer || IsEnum || IsPrimitive;
+ if (needsSpecialCast)
+ {
+ RuntimeType valueType;
+ Pointer pointer = value as Pointer;
+ if (pointer != null)
+ valueType = pointer.GetPointerType();
+ else
+ valueType = (RuntimeType)value.GetType();
+
+ if (CanValueSpecialCast(valueType, this))
+ {
+ if (pointer != null)
+ return pointer.GetPointerValue();
+ else
+ return value;
+ }
+ }
+
+ if ((invokeAttr & BindingFlags.ExactBinding) == BindingFlags.ExactBinding)
+ throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
+
+ return TryChangeType(value, binder, culture, needsSpecialCast);
+ }
+
+ // Factored out of CheckValue to reduce code complexity.
+ [System.Security.SecurityCritical]
+ private Object TryChangeType(Object value, Binder binder, CultureInfo culture, bool needsSpecialCast)
+ {
+ if (binder != null && binder != Type.DefaultBinder)
+ {
+ value = binder.ChangeType(value, this, culture);
+ if (IsInstanceOfType(value))
+ return value;
+ // if this is a ByRef get the element type and check if it's compatible
+ if (IsByRef)
+ {
+ RuntimeType elementType = RuntimeTypeHandle.GetElementType(this);
+ if (elementType.IsInstanceOfType(value) || value == null)
+ return AllocateValueType(elementType, value, false);
+ }
+ else if (value == null)
+ return value;
+ if (needsSpecialCast)
+ {
+ RuntimeType valueType;
+ Pointer pointer = value as Pointer;
+ if (pointer != null)
+ valueType = pointer.GetPointerType();
+ else
+ valueType = (RuntimeType)value.GetType();
+
+ if (CanValueSpecialCast(valueType, this))
+ {
+ if (pointer != null)
+ return pointer.GetPointerValue();
+ else
+ return value;
+ }
+ }
+ }
+
+ throw new ArgumentException(String.Format(CultureInfo.CurrentUICulture, Environment.GetResourceString("Arg_ObjObjEx"), value.GetType(), this));
+ }
+
+ // GetDefaultMembers
+ // This will return a MemberInfo that has been marked with the [DefaultMemberAttribute]
+ public override MemberInfo[] GetDefaultMembers()
+ {
+ // See if we have cached the default member name
+ MemberInfo[] members = null;
+
+ String defaultMemberName = GetDefaultMemberName();
+ if (defaultMemberName != null)
+ {
+ members = GetMember(defaultMemberName);
+ }
+
+ if (members == null)
+ members = EmptyArray<MemberInfo>.Value;
+
+ return members;
+ }
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public override Object InvokeMember(
+ String name, BindingFlags bindingFlags, Binder binder, Object target,
+ Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
+ {
+ if (IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_GenericParameter"));
+ Contract.EndContractBlock();
+
+ #region Preconditions
+ if ((bindingFlags & InvocationMask) == 0)
+ // "Must specify binding flags describing the invoke operation required."
+ throw new ArgumentException(Environment.GetResourceString("Arg_NoAccessSpec"),"bindingFlags");
+
+ // Provide a default binding mask if none is provided
+ if ((bindingFlags & MemberBindingMask) == 0)
+ {
+ bindingFlags |= BindingFlags.Instance | BindingFlags.Public;
+
+ if ((bindingFlags & BindingFlags.CreateInstance) == 0)
+ bindingFlags |= BindingFlags.Static;
+ }
+
+ // There must not be more named parameters than provided arguments
+ if (namedParams != null)
+ {
+ if (providedArgs != null)
+ {
+ if (namedParams.Length > providedArgs.Length)
+ // "Named parameter array can not be bigger than argument array."
+ throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams");
+ }
+ else
+ {
+ if (namedParams.Length != 0)
+ // "Named parameter array can not be bigger than argument array."
+ throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamTooBig"), "namedParams");
+ }
+ }
+ #endregion
+
+ #region COM Interop
+#if FEATURE_COMINTEROP && FEATURE_USE_LCID
+ if (target != null && target.GetType().IsCOMObject)
+ {
+ #region Preconditions
+ if ((bindingFlags & ClassicBindingMask) == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_COMAccess"), "bindingFlags");
+
+ if ((bindingFlags & BindingFlags.GetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");
+
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0 && (bindingFlags & ClassicBindingMask & ~(BindingFlags.GetProperty | BindingFlags.InvokeMethod)) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");
+
+ if ((bindingFlags & BindingFlags.SetProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.SetProperty) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");
+
+ if ((bindingFlags & BindingFlags.PutDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutDispProperty) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");
+
+ if ((bindingFlags & BindingFlags.PutRefDispProperty) != 0 && (bindingFlags & ClassicBindingMask & ~BindingFlags.PutRefDispProperty) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_COMPropSetPut"), "bindingFlags");
+ #endregion
+
+#if FEATURE_REMOTING
+ if(!RemotingServices.IsTransparentProxy(target))
+#endif
+ {
+ #region Non-TransparentProxy case
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ bool[] isByRef = modifiers == null ? null : modifiers[0].IsByRefArray;
+
+ // pass LCID_ENGLISH_US if no explicit culture is specified to match the behavior of VB
+ int lcid = (culture == null ? 0x0409 : culture.LCID);
+
+ return InvokeDispMethod(name, bindingFlags, target, providedArgs, isByRef, lcid, namedParams);
+ #endregion
+ }
+#if FEATURE_REMOTING
+ else
+ {
+ #region TransparentProxy case
+ return ((MarshalByRefObject)target).InvokeMember(name, bindingFlags, binder, providedArgs, modifiers, culture, namedParams);
+ #endregion
+ }
+#endif // FEATURE_REMOTING
+ }
+#endif // FEATURE_COMINTEROP && FEATURE_USE_LCID
+ #endregion
+
+ #region Check that any named paramters are not null
+ if (namedParams != null && Array.IndexOf(namedParams, null) != -1)
+ // "Named parameter value must not be null."
+ throw new ArgumentException(Environment.GetResourceString("Arg_NamedParamNull"),"namedParams");
+ #endregion
+
+ int argCnt = (providedArgs != null) ? providedArgs.Length : 0;
+
+ #region Get a Binder
+ if (binder == null)
+ binder = DefaultBinder;
+
+ bool bDefaultBinder = (binder == DefaultBinder);
+ #endregion
+
+ #region Delegate to Activator.CreateInstance
+ if ((bindingFlags & BindingFlags.CreateInstance) != 0)
+ {
+ if ((bindingFlags & BindingFlags.CreateInstance) != 0 && (bindingFlags & BinderNonCreateInstance) != 0)
+ // "Can not specify both CreateInstance and another access type."
+ throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"),"bindingFlags");
+
+ return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture);
+ }
+ #endregion
+
+ // PutDispProperty and\or PutRefDispProperty ==> SetProperty.
+ if ((bindingFlags & (BindingFlags.PutDispProperty | BindingFlags.PutRefDispProperty)) != 0)
+ bindingFlags |= BindingFlags.SetProperty;
+
+ #region Name
+ if (name == null)
+ throw new ArgumentNullException("name");
+
+ if (name.Length == 0 || name.Equals(@"[DISPID=0]"))
+ {
+ name = GetDefaultMemberName();
+
+ if (name == null)
+ {
+ // in InvokeMember we always pretend there is a default member if none is provided and we make it ToString
+ name = "ToString";
+ }
+ }
+ #endregion
+
+ #region GetField or SetField
+ bool IsGetField = (bindingFlags & BindingFlags.GetField) != 0;
+ bool IsSetField = (bindingFlags & BindingFlags.SetField) != 0;
+
+ if (IsGetField || IsSetField)
+ {
+ #region Preconditions
+ if (IsGetField)
+ {
+ if (IsSetField)
+ // "Can not specify both Get and Set on a field."
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldSetGet"),"bindingFlags");
+
+ if ((bindingFlags & BindingFlags.SetProperty) != 0)
+ // "Can not specify both GetField and SetProperty."
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldGetPropSet"),"bindingFlags");
+ }
+ else
+ {
+ Contract.Assert(IsSetField);
+
+ if (providedArgs == null)
+ throw new ArgumentNullException("providedArgs");
+
+ if ((bindingFlags & BindingFlags.GetProperty) != 0)
+ // "Can not specify both SetField and GetProperty."
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldSetPropGet"),"bindingFlags");
+
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
+ // "Can not specify Set on a Field and Invoke on a method."
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldSetInvoke"),"bindingFlags");
+ }
+ #endregion
+
+ #region Lookup Field
+ FieldInfo selFld = null;
+ FieldInfo[] flds = GetMember(name, MemberTypes.Field, bindingFlags) as FieldInfo[];
+
+ Contract.Assert(flds != null);
+
+ if (flds.Length == 1)
+ {
+ selFld = flds[0];
+ }
+ else if (flds.Length > 0)
+ {
+ selFld = binder.BindToField(bindingFlags, flds, IsGetField ? Empty.Value : providedArgs[0], culture);
+ }
+ #endregion
+
+ if (selFld != null)
+ {
+ #region Invocation on a field
+ if (selFld.FieldType.IsArray || Object.ReferenceEquals(selFld.FieldType, typeof(System.Array)))
+ {
+ #region Invocation of an array Field
+ int idxCnt;
+
+ if ((bindingFlags & BindingFlags.GetField) != 0)
+ {
+ idxCnt = argCnt;
+ }
+ else
+ {
+ idxCnt = argCnt - 1;
+ }
+
+ if (idxCnt > 0)
+ {
+ // Verify that all of the index values are ints
+ int[] idx = new int[idxCnt];
+ for (int i=0;i<idxCnt;i++)
+ {
+ try
+ {
+ idx[i] = ((IConvertible)providedArgs[i]).ToInt32(null);
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexMustBeInt"));
+ }
+ }
+
+ // Set or get the value...
+ Array a = (Array) selFld.GetValue(target);
+
+ // Set or get the value in the array
+ if ((bindingFlags & BindingFlags.GetField) != 0)
+ {
+ return a.GetValue(idx);
+ }
+ else
+ {
+ a.SetValue(providedArgs[idxCnt],idx);
+ return null;
+ }
+ }
+ #endregion
+ }
+
+ if (IsGetField)
+ {
+ #region Get the field value
+ if (argCnt != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldGetArgErr"),"bindingFlags");
+
+ return selFld.GetValue(target);
+ #endregion
+ }
+ else
+ {
+ #region Set the field Value
+ if (argCnt != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_FldSetArgErr"),"bindingFlags");
+
+ selFld.SetValue(target,providedArgs[0],bindingFlags,binder,culture);
+
+ return null;
+ #endregion
+ }
+ #endregion
+ }
+
+ if ((bindingFlags & BinderNonFieldGetSet) == 0)
+ throw new MissingFieldException(FullName, name);
+ }
+ #endregion
+
+ #region Caching Logic
+ /*
+ bool useCache = false;
+
+ // Note that when we add something to the cache, we are careful to ensure
+ // that the actual providedArgs matches the parameters of the method. Otherwise,
+ // some default argument processing has occurred. We don't want anyone
+ // else with the same (insufficient) number of actual arguments to get a
+ // cache hit because then they would bypass the default argument processing
+ // and the invocation would fail.
+ if (bDefaultBinder && namedParams == null && argCnt < 6)
+ useCache = true;
+
+ if (useCache)
+ {
+ MethodBase invokeMethod = GetMethodFromCache (name, bindingFlags, argCnt, providedArgs);
+
+ if (invokeMethod != null)
+ return ((MethodInfo) invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
+ }
+ */
+ #endregion
+
+ #region Property PreConditions
+ // @Legacy - This is RTM behavior
+ bool isGetProperty = (bindingFlags & BindingFlags.GetProperty) != 0;
+ bool isSetProperty = (bindingFlags & BindingFlags.SetProperty) != 0;
+
+ if (isGetProperty || isSetProperty)
+ {
+ #region Preconditions
+ if (isGetProperty)
+ {
+ Contract.Assert(!IsSetField);
+
+ if (isSetProperty)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetGet"), "bindingFlags");
+ }
+ else
+ {
+ Contract.Assert(isSetProperty);
+
+ Contract.Assert(!IsGetField);
+
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_PropSetInvoke"), "bindingFlags");
+ }
+ #endregion
+ }
+ #endregion
+
+ MethodInfo[] finalists = null;
+ MethodInfo finalist = null;
+
+ #region BindingFlags.InvokeMethod
+ if ((bindingFlags & BindingFlags.InvokeMethod) != 0)
+ {
+ #region Lookup Methods
+ MethodInfo[] semiFinalists = GetMember(name, MemberTypes.Method, bindingFlags) as MethodInfo[];
+ List<MethodInfo> results = null;
+
+ for(int i = 0; i < semiFinalists.Length; i ++)
+ {
+ MethodInfo semiFinalist = semiFinalists[i];
+ Contract.Assert(semiFinalist != null);
+
+ if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
+ continue;
+
+ if (finalist == null)
+ {
+ finalist = semiFinalist;
+ }
+ else
+ {
+ if (results == null)
+ {
+ results = new List<MethodInfo>(semiFinalists.Length);
+ results.Add(finalist);
+ }
+
+ results.Add(semiFinalist);
+ }
+ }
+
+ if (results != null)
+ {
+ Contract.Assert(results.Count > 1);
+ finalists = new MethodInfo[results.Count];
+ results.CopyTo(finalists);
+ }
+ #endregion
+ }
+ #endregion
+
+ Contract.Assert(finalists == null || finalist != null);
+
+ #region BindingFlags.GetProperty or BindingFlags.SetProperty
+ if (finalist == null && isGetProperty || isSetProperty)
+ {
+ #region Lookup Property
+ PropertyInfo[] semiFinalists = GetMember(name, MemberTypes.Property, bindingFlags) as PropertyInfo[];
+ List<MethodInfo> results = null;
+
+ for(int i = 0; i < semiFinalists.Length; i ++)
+ {
+ MethodInfo semiFinalist = null;
+
+ if (isSetProperty)
+ {
+ semiFinalist = semiFinalists[i].GetSetMethod(true);
+ }
+ else
+ {
+ semiFinalist = semiFinalists[i].GetGetMethod(true);
+ }
+
+ if (semiFinalist == null)
+ continue;
+
+ if (!FilterApplyMethodInfo((RuntimeMethodInfo)semiFinalist, bindingFlags, CallingConventions.Any, new Type[argCnt]))
+ continue;
+
+ if (finalist == null)
+ {
+ finalist = semiFinalist;
+ }
+ else
+ {
+ if (results == null)
+ {
+ results = new List<MethodInfo>(semiFinalists.Length);
+ results.Add(finalist);
+ }
+
+ results.Add(semiFinalist);
+ }
+ }
+
+ if (results != null)
+ {
+ Contract.Assert(results.Count > 1);
+ finalists = new MethodInfo[results.Count];
+ results.CopyTo(finalists);
+ }
+ #endregion
+ }
+ #endregion
+
+ if (finalist != null)
+ {
+ #region Invoke
+ if (finalists == null &&
+ argCnt == 0 &&
+ finalist.GetParametersNoCopy().Length == 0 &&
+ (bindingFlags & BindingFlags.OptionalParamBinding) == 0)
+ {
+ //if (useCache && argCnt == props[0].GetParameters().Length)
+ // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, props[0]);
+
+ return finalist.Invoke(target, bindingFlags, binder, providedArgs, culture);
+ }
+
+ if (finalists == null)
+ finalists = new MethodInfo[] { finalist };
+
+ if (providedArgs == null)
+ providedArgs = EmptyArray<Object>.Value;
+
+ Object state = null;
+
+
+ MethodBase invokeMethod = null;
+
+ try { invokeMethod = binder.BindToMethod(bindingFlags, finalists, ref providedArgs, modifiers, culture, namedParams, out state); }
+ catch(MissingMethodException) { }
+
+ if (invokeMethod == null)
+ throw new MissingMethodException(FullName, name);
+
+ //if (useCache && argCnt == invokeMethod.GetParameters().Length)
+ // AddMethodToCache(name, bindingFlags, argCnt, providedArgs, invokeMethod);
+
+ Object result = ((MethodInfo)invokeMethod).Invoke(target, bindingFlags, binder, providedArgs, culture);
+
+ if (state != null)
+ binder.ReorderArgumentArray(ref providedArgs, state);
+
+ return result;
+ #endregion
+ }
+
+ throw new MissingMethodException(FullName, name);
+ }
+ #endregion
+
+ #endregion
+
+ #region Object Overrides
+ [Pure]
+ public override bool Equals(object obj)
+ {
+ // ComObjects are identified by the instance of the Type object and not the TypeHandle.
+ return obj == (object)this;
+ }
+
+ public override int GetHashCode()
+ {
+ return RuntimeHelpers.GetHashCode(this);
+ }
+
+#if !FEATURE_CORECLR
+ public static bool operator ==(RuntimeType left, RuntimeType right)
+ {
+ return object.ReferenceEquals(left, right);
+ }
+
+ public static bool operator !=(RuntimeType left, RuntimeType right)
+ {
+ return !object.ReferenceEquals(left, right);
+ }
+#endif // !FEATURE_CORECLR
+
+ public override String ToString()
+ {
+ return GetCachedName(TypeNameKind.ToString);
+ }
+ #endregion
+
+ #region ICloneable
+ public Object Clone()
+ {
+ return this;
+ }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ UnitySerializationHolder.GetUnitySerializationInfo(info, this);
+ }
+ #endregion
+
+ #region ICustomAttributeProvider
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(bool inherit)
+ {
+ return CustomAttribute.GetCustomAttributes(this, RuntimeType.ObjectType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit)
+ {
+ if ((object)attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.GetCustomAttributes(this, attributeRuntimeType, inherit);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsDefined(Type attributeType, bool inherit)
+ {
+ if ((object)attributeType == null)
+ throw new ArgumentNullException("attributeType");
+ Contract.EndContractBlock();
+
+ RuntimeType attributeRuntimeType = attributeType.UnderlyingSystemType as RuntimeType;
+
+ if (attributeRuntimeType == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"),"attributeType");
+
+ return CustomAttribute.IsDefined(this, attributeRuntimeType, inherit);
+ }
+
+ public override IList<CustomAttributeData> GetCustomAttributesData()
+ {
+ return CustomAttributeData.GetCustomAttributesInternal(this);
+ }
+ #endregion
+
+ #region MemberInfo Overrides
+ public override String Name
+ {
+ get
+ {
+ return GetCachedName(TypeNameKind.Name);
+ }
+ }
+
+ // This is used by the ToString() overrides of all reflection types. The legacy behavior has the following problems:
+ // 1. Use only Name for nested types, which can be confused with global types and generic parameters of the same name.
+ // 2. Use only Name for generic parameters, which can be confused with nested types and global types of the same name.
+ // 3. Remove the namespace ("System") for all primitive types, which is not language neutral.
+ // 4. MethodBase.ToString() use "ByRef" for byref parameters which is different than Type.ToString().
+ // 5. ConstructorInfo.ToString() outputs "Void" as the return type. Why Void?
+ // Since it could be a breaking changes to fix these legacy behaviors, we only use the better and more unambiguous format
+ // in serialization (MemberInfoSerializationHolder).
+ internal override string FormatTypeName(bool serialization)
+ {
+ if (serialization)
+ {
+ return GetCachedName(TypeNameKind.SerializationName);
+ }
+ else
+ {
+ Type elementType = GetRootElementType();
+
+ // Legacy: this doesn't make sense, why use only Name for nested types but otherwise
+ // ToString() which contains namespace.
+ if (elementType.IsNested)
+ return Name;
+
+ string typeName = ToString();
+
+ // Legacy: why removing "System"? Is it just because C# has keywords for these types?
+ // If so why don't we change it to lower case to match the C# keyword casing?
+ if (elementType.IsPrimitive ||
+ elementType == typeof(void) ||
+ elementType == typeof(TypedReference))
+ {
+ typeName = typeName.Substring(@"System.".Length);
+ }
+
+ return typeName;
+ }
+ }
+
+ private string GetCachedName(TypeNameKind kind)
+ {
+ return Cache.GetName(kind);
+ }
+
+ public override MemberTypes MemberType
+ {
+ get
+ {
+ if (this.IsPublic || this.IsNotPublic)
+ return MemberTypes.TypeInfo;
+ else
+ return MemberTypes.NestedType;
+ }
+ }
+
+ public override Type DeclaringType
+ {
+ get
+ {
+ return Cache.GetEnclosingType();
+ }
+ }
+
+ public override Type ReflectedType
+ {
+ get
+ {
+ return DeclaringType;
+ }
+ }
+
+ public override int MetadataToken
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return RuntimeTypeHandle.GetToken(this);
+ }
+ }
+ #endregion
+
+ #region Legacy Internal
+ private void CreateInstanceCheckThis()
+ {
+ if (this is ReflectionOnlyType)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ReflectionOnlyInvoke"));
+
+ if (ContainsGenericParameters)
+ throw new ArgumentException(
+ Environment.GetResourceString("Acc_CreateGenericEx", this));
+ Contract.EndContractBlock();
+
+ Type elementType = this.GetRootElementType();
+
+ if (Object.ReferenceEquals(elementType, typeof(ArgIterator)))
+ throw new NotSupportedException(Environment.GetResourceString("Acc_CreateArgIterator"));
+
+ if (Object.ReferenceEquals(elementType, typeof(void)))
+ throw new NotSupportedException(Environment.GetResourceString("Acc_CreateVoid"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object CreateInstanceImpl(
+ BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, ref StackCrawlMark stackMark)
+ {
+ CreateInstanceCheckThis();
+
+ Object server = null;
+
+ try
+ {
+ try
+ {
+ // Store the activation attributes in thread local storage.
+ // These attributes are later picked up by specialized
+ // activation services like remote activation services to
+ // influence the activation.
+#if FEATURE_REMOTING
+ if(null != activationAttributes)
+ {
+ ActivationServices.PushActivationAttributes(this, activationAttributes);
+ }
+#endif
+
+ if (args == null)
+ args = EmptyArray<Object>.Value;
+
+ int argCnt = args.Length;
+
+ // Without a binder we need to do use the default binder...
+ if (binder == null)
+ binder = DefaultBinder;
+
+ // deal with the __COMObject case first. It is very special because from a reflection point of view it has no ctors
+ // so a call to GetMemberCons would fail
+ if (argCnt == 0 && (bindingAttr & BindingFlags.Public) != 0 && (bindingAttr & BindingFlags.Instance) != 0
+ && (IsGenericCOMObjectImpl() || IsValueType))
+ {
+ server = CreateInstanceDefaultCtor((bindingAttr & BindingFlags.NonPublic) == 0 , false, true, ref stackMark);
+ }
+ else
+ {
+ ConstructorInfo[] candidates = GetConstructors(bindingAttr);
+ List<MethodBase> matches = new List<MethodBase>(candidates.Length);
+
+ // We cannot use Type.GetTypeArray here because some of the args might be null
+ Type[] argsType = new Type[argCnt];
+ for (int i = 0; i < argCnt; i++)
+ {
+ if (args[i] != null)
+ {
+ argsType[i] = args[i].GetType();
+ }
+ }
+
+ for(int i = 0; i < candidates.Length; i ++)
+ {
+ if (FilterApplyConstructorInfo((RuntimeConstructorInfo)candidates[i], bindingAttr, CallingConventions.Any, argsType))
+ matches.Add(candidates[i]);
+ }
+
+ MethodBase[] cons = new MethodBase[matches.Count];
+ matches.CopyTo(cons);
+ if (cons != null && cons.Length == 0)
+ cons = null;
+
+ if (cons == null)
+ {
+ // Null out activation attributes before throwing exception
+#if FEATURE_REMOTING
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
+ }
+
+ MethodBase invokeMethod;
+ Object state = null;
+
+ try
+ {
+ invokeMethod = binder.BindToMethod(bindingAttr, cons, ref args, null, culture, null, out state);
+ }
+ catch (MissingMethodException) { invokeMethod = null; }
+
+ if (invokeMethod == null)
+ {
+#if FEATURE_REMOTING
+ // Null out activation attributes before throwing exception
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ throw new MissingMethodException(Environment.GetResourceString("MissingConstructor_Name", FullName));
+ }
+
+ // If we're creating a delegate, we're about to call a
+ // constructor taking an integer to represent a target
+ // method. Since this is very difficult (and expensive)
+ // to verify, we're just going to demand UnmanagedCode
+ // permission before allowing this. Partially trusted
+ // clients can instead use Delegate.CreateDelegate,
+ // which allows specification of the target method via
+ // name or MethodInfo.
+ //if (isDelegate)
+ if (RuntimeType.DelegateType.IsAssignableFrom(invokeMethod.DeclaringType))
+ {
+#if FEATURE_CORECLR
+ // In CoreCLR, CAS is not exposed externally. So what we really are looking
+ // for is to see if the external caller of this API is transparent or not.
+ // We get that information from the fact that a Demand will succeed only if
+ // the external caller is not transparent.
+ try
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#pragma warning restore 618
+ }
+ catch
+ {
+ throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_DelegateCreationFromPT")));
+ }
+#else // FEATURE_CORECLR
+ new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+#endif // FEATURE_CORECLR
+ }
+
+ if (invokeMethod.GetParametersNoCopy().Length == 0)
+ {
+ if (args.Length != 0)
+ {
+
+ Contract.Assert((invokeMethod.CallingConvention & CallingConventions.VarArgs) ==
+ CallingConventions.VarArgs);
+ throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture,
+ Environment.GetResourceString("NotSupported_CallToVarArg")));
+ }
+
+ // fast path??
+ server = Activator.CreateInstance(this, true);
+ }
+ else
+ {
+ server = ((ConstructorInfo)invokeMethod).Invoke(bindingAttr, binder, args, culture);
+ if (state != null)
+ binder.ReorderArgumentArray(ref args, state);
+ }
+ }
+ }
+ finally
+ {
+#if FEATURE_REMOTING
+ // Reset the TLS to null
+ if(null != activationAttributes)
+ {
+ ActivationServices.PopActivationAttributes(this);
+ activationAttributes = null;
+ }
+#endif
+ }
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+
+ //Console.WriteLine(server);
+ return server;
+ }
+
+ // the cache entry
+ class ActivatorCacheEntry
+ {
+ // the type to cache
+ internal readonly RuntimeType m_type;
+ // the delegate containing the call to the ctor, will be replaced by an IntPtr to feed a calli with
+ internal volatile CtorDelegate m_ctor;
+ internal readonly RuntimeMethodHandleInternal m_hCtorMethodHandle;
+ internal readonly MethodAttributes m_ctorAttributes;
+ // Is a security check needed before this constructor is invoked?
+ internal readonly bool m_bNeedSecurityCheck;
+ // Lazy initialization was performed
+ internal volatile bool m_bFullyInitialized;
+
+ [System.Security.SecurityCritical]
+ internal ActivatorCacheEntry(RuntimeType t, RuntimeMethodHandleInternal rmh, bool bNeedSecurityCheck)
+ {
+ m_type = t;
+ m_bNeedSecurityCheck = bNeedSecurityCheck;
+ m_hCtorMethodHandle = rmh;
+ if (!m_hCtorMethodHandle.IsNullHandle())
+ m_ctorAttributes = RuntimeMethodHandle.GetAttributes(m_hCtorMethodHandle);
+ }
+ }
+
+ //ActivatorCache
+ class ActivatorCache
+ {
+ const int CACHE_SIZE = 16;
+ volatile int hash_counter; //Counter for wrap around
+ readonly ActivatorCacheEntry[] cache = new ActivatorCacheEntry[CACHE_SIZE];
+
+ volatile ConstructorInfo delegateCtorInfo;
+ volatile PermissionSet delegateCreatePermissions;
+
+ private void InitializeDelegateCreator() {
+ // No synchronization needed here. In the worst case we create extra garbage
+ PermissionSet ps = new PermissionSet(PermissionState.None);
+ ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.MemberAccess));
+#pragma warning disable 618
+ ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.UnmanagedCode));
+#pragma warning restore 618
+ delegateCreatePermissions = ps;
+
+ ConstructorInfo ctorInfo = typeof(CtorDelegate).GetConstructor(new Type[] {typeof(Object), typeof(IntPtr)});
+ delegateCtorInfo = ctorInfo; // this assignment should be last
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void InitializeCacheEntry(ActivatorCacheEntry ace)
+ {
+ if (!ace.m_type.IsValueType)
+ {
+ Contract.Assert(!ace.m_hCtorMethodHandle.IsNullHandle(), "Expected the default ctor method handle for a reference type.");
+
+ if (delegateCtorInfo == null)
+ InitializeDelegateCreator();
+ delegateCreatePermissions.Assert();
+
+ // No synchronization needed here. In the worst case we create extra garbage
+ CtorDelegate ctor = (CtorDelegate)delegateCtorInfo.Invoke(new Object[] { null, RuntimeMethodHandle.GetFunctionPointer(ace.m_hCtorMethodHandle) });
+ ace.m_ctor = ctor;
+ }
+ ace.m_bFullyInitialized = true;
+ }
+
+ internal ActivatorCacheEntry GetEntry(RuntimeType t)
+ {
+ int index = hash_counter;
+ for(int i = 0; i < CACHE_SIZE; i++)
+ {
+ ActivatorCacheEntry ace = Volatile.Read(ref cache[index]);
+ if (ace != null && ace.m_type == t) //check for type match..
+ {
+ if (!ace.m_bFullyInitialized)
+ InitializeCacheEntry(ace);
+ return ace;
+ }
+ index = (index+1)&(ActivatorCache.CACHE_SIZE-1);
+ }
+ return null;
+ }
+
+ internal void SetEntry(ActivatorCacheEntry ace)
+ {
+ // fill the the array backwards to hit the most recently filled entries first in GetEntry
+ int index = (hash_counter-1)&(ActivatorCache.CACHE_SIZE-1);
+ hash_counter = index;
+ Volatile.Write(ref cache[index], ace);
+ }
+ }
+
+ private static volatile ActivatorCache s_ActivatorCache;
+
+ // the slow path of CreateInstanceDefaultCtor
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal Object CreateInstanceSlow(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
+ {
+ RuntimeMethodHandleInternal runtime_ctor = default(RuntimeMethodHandleInternal);
+ bool bNeedSecurityCheck = true;
+ bool bCanBeCached = false;
+ bool bSecurityCheckOff = false;
+
+ if (!skipCheckThis)
+ CreateInstanceCheckThis();
+
+ if (!fillCache)
+ bSecurityCheckOff = true;
+
+#if FEATURE_APPX
+ INVOCATION_FLAGS invocationFlags = InvocationFlags;
+ if ((invocationFlags & INVOCATION_FLAGS.INVOCATION_FLAGS_NON_W8P_FX_API) != 0)
+ {
+ RuntimeAssembly caller = RuntimeAssembly.GetExecutingAssembly(ref stackMark);
+ if (caller != null && !caller.IsSafeForReflection())
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_APIInvalidForCurrentContext", this.FullName));
+
+ // Allow it because the caller is framework code, but don't cache the result
+ // because we need to do the stack walk every time this type is instantiated.
+ bSecurityCheckOff = false;
+ bCanBeCached = false;
+ }
+#endif
+#if FEATURE_CORECLR
+ bSecurityCheckOff = true; // CoreCLR does not use security at all.
+#endif
+
+ Object instance = RuntimeTypeHandle.CreateInstance(this, publicOnly, bSecurityCheckOff, ref bCanBeCached, ref runtime_ctor, ref bNeedSecurityCheck);
+
+ if (bCanBeCached && fillCache)
+ {
+ ActivatorCache activatorCache = s_ActivatorCache;
+ if (activatorCache == null)
+ {
+ // No synchronization needed here. In the worst case we create extra garbage
+ activatorCache = new ActivatorCache();
+ s_ActivatorCache = activatorCache;
+ }
+
+ // cache the ctor
+ ActivatorCacheEntry ace = new ActivatorCacheEntry(this, runtime_ctor, bNeedSecurityCheck);
+ activatorCache.SetEntry(ace);
+ }
+
+ return instance;
+ }
+
+ // Helper to invoke the default (parameterless) ctor.
+ // fillCache is set in the SL2/3 compat mode or when called from Marshal.PtrToStructure.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ internal Object CreateInstanceDefaultCtor(bool publicOnly, bool skipCheckThis, bool fillCache, ref StackCrawlMark stackMark)
+ {
+ if (GetType() == typeof(ReflectionOnlyType))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+
+ ActivatorCache activatorCache = s_ActivatorCache;
+ if (activatorCache != null)
+ {
+ ActivatorCacheEntry ace = activatorCache.GetEntry(this);
+ if (ace != null)
+ {
+ if (publicOnly)
+ {
+ if (ace.m_ctor != null &&
+ (ace.m_ctorAttributes & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
+ {
+ throw new MissingMethodException(Environment.GetResourceString("Arg_NoDefCTor"));
+ }
+ }
+
+ // Allocate empty object
+ Object instance = RuntimeTypeHandle.Allocate(this);
+
+ // if m_ctor is null, this type doesn't have a default ctor
+ Contract.Assert(ace.m_ctor != null || this.IsValueType);
+
+ if (ace.m_ctor != null)
+ {
+#if !FEATURE_CORECLR
+ // Perform security checks if needed
+ if (ace.m_bNeedSecurityCheck)
+ RuntimeMethodHandle.PerformSecurityCheck(instance, ace.m_hCtorMethodHandle, this, (uint)INVOCATION_FLAGS.INVOCATION_FLAGS_CONSTRUCTOR_INVOKE);
+#endif
+
+ // Call ctor (value types wont have any)
+ try
+ {
+ ace.m_ctor(instance);
+ }
+ catch (Exception e)
+ {
+ throw new TargetInvocationException(e);
+ }
+ }
+ return instance;
+ }
+ }
+ return CreateInstanceSlow(publicOnly, skipCheckThis, fillCache, ref stackMark);
+ }
+
+ internal void InvalidateCachedNestedType()
+ {
+ Cache.InvalidateCachedNestedType();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsGenericCOMObjectImpl()
+ {
+ return RuntimeTypeHandle.IsComObject(this, true);
+ }
+ #endregion
+
+ #region Legacy Static Internal
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object _CreateEnum(RuntimeType enumType, long value);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Object CreateEnum(RuntimeType enumType, long value)
+ {
+ return _CreateEnum(enumType, value);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Object InvokeDispMethod(
+ String name, BindingFlags invokeAttr, Object target, Object[] args,
+ bool[] byrefModifiers, int culture, String[] namedParameters);
+
+#if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError);
+#else // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+ internal static Type GetTypeFromProgIDImpl(String progID, String server, bool throwOnError)
+ {
+ throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
+ }
+
+ internal static Type GetTypeFromCLSIDImpl(Guid clsid, String server, bool throwOnError)
+ {
+ throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
+ }
+#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+
+ #endregion
+
+ #region COM
+#if FEATURE_COMINTEROP && FEATURE_REMOTING
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private Object ForwardCallToInvokeMember(String memberName, BindingFlags flags, Object target, int[] aWrapperTypes, ref MessageData msgData)
+ {
+ ParameterModifier[] aParamMod = null;
+ Object ret = null;
+
+ // Allocate a new message
+ Message reqMsg = new Message();
+ reqMsg.InitFields(msgData);
+
+ // Retrieve the required information from the message object.
+ MethodInfo meth = (MethodInfo)reqMsg.GetMethodBase();
+ Object[] aArgs = reqMsg.Args;
+ int cArgs = aArgs.Length;
+
+ // Retrieve information from the method we are invoking on.
+ ParameterInfo[] aParams = meth.GetParametersNoCopy();
+
+ // If we have arguments, then set the byref flags to true for byref arguments.
+ // We also wrap the arguments that require wrapping.
+ if (cArgs > 0)
+ {
+ ParameterModifier paramMod = new ParameterModifier(cArgs);
+ for (int i = 0; i < cArgs; i++)
+ {
+ if (aParams[i].ParameterType.IsByRef)
+ paramMod[i] = true;
+ }
+
+ aParamMod = new ParameterModifier[1];
+ aParamMod[0] = paramMod;
+
+ if (aWrapperTypes != null)
+ WrapArgsForInvokeCall(aArgs, aWrapperTypes);
+ }
+
+ // If the method has a void return type, then set the IgnoreReturn binding flag.
+ if (Object.ReferenceEquals(meth.ReturnType, typeof(void)))
+ flags |= BindingFlags.IgnoreReturn;
+
+ try
+ {
+ // Invoke the method using InvokeMember().
+ ret = InvokeMember(memberName, flags, null, target, aArgs, aParamMod, null, null);
+ }
+ catch (TargetInvocationException e)
+ {
+ // For target invocation exceptions, we need to unwrap the inner exception and
+ // re-throw it.
+ throw e.InnerException;
+ }
+
+ // Convert each byref argument that is not of the proper type to
+ // the parameter type using the OleAutBinder.
+ for (int i = 0; i < cArgs; i++)
+ {
+ if (aParamMod[0][i] && aArgs[i] != null)
+ {
+ // The parameter is byref.
+ Type paramType = aParams[i].ParameterType.GetElementType();
+ if (!Object.ReferenceEquals(paramType, aArgs[i].GetType()))
+ aArgs[i] = ForwardCallBinder.ChangeType(aArgs[i], paramType, null);
+ }
+ }
+
+ // If the return type is not of the proper type, then convert it
+ // to the proper type using the OleAutBinder.
+ if (ret != null)
+ {
+ Type retType = meth.ReturnType;
+ if (!Object.ReferenceEquals(retType, ret.GetType()))
+ ret = ForwardCallBinder.ChangeType(ret, retType, null);
+ }
+
+ // Propagate the out parameters
+ RealProxy.PropagateOutParameters(reqMsg, aArgs, ret);
+
+ // Return the value returned by the InvokeMember call.
+ return ret;
+ }
+
+ [SecuritySafeCritical]
+ private void WrapArgsForInvokeCall(Object[] aArgs, int[] aWrapperTypes)
+ {
+ int cArgs = aArgs.Length;
+ for (int i = 0; i < cArgs; i++)
+ {
+ if (aWrapperTypes[i] == 0)
+ continue;
+
+ if (((DispatchWrapperType)aWrapperTypes[i] & DispatchWrapperType.SafeArray) != 0)
+ {
+ Type wrapperType = null;
+ bool isString = false;
+
+ // Determine the type of wrapper to use.
+ switch ((DispatchWrapperType)aWrapperTypes[i] & ~DispatchWrapperType.SafeArray)
+ {
+ case DispatchWrapperType.Unknown:
+ wrapperType = typeof(UnknownWrapper);
+ break;
+ case DispatchWrapperType.Dispatch:
+ wrapperType = typeof(DispatchWrapper);
+ break;
+ case DispatchWrapperType.Error:
+ wrapperType = typeof(ErrorWrapper);
+ break;
+ case DispatchWrapperType.Currency:
+ wrapperType = typeof(CurrencyWrapper);
+ break;
+ case DispatchWrapperType.BStr:
+ wrapperType = typeof(BStrWrapper);
+ isString = true;
+ break;
+ default:
+ Contract.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid safe array wrapper type specified.");
+ break;
+ }
+
+ // Allocate the new array of wrappers.
+ Array oldArray = (Array)aArgs[i];
+ int numElems = oldArray.Length;
+ Object[] newArray = (Object[])Array.UnsafeCreateInstance(wrapperType, numElems);
+
+ // Retrieve the ConstructorInfo for the wrapper type.
+ ConstructorInfo wrapperCons;
+ if(isString)
+ {
+ wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(String)});
+ }
+ else
+ {
+ wrapperCons = wrapperType.GetConstructor(new Type[] {typeof(Object)});
+ }
+
+ // Wrap each of the elements of the array.
+ for (int currElem = 0; currElem < numElems; currElem++)
+ {
+ if(isString)
+ {
+ newArray[currElem] = wrapperCons.Invoke(new Object[] {(String)oldArray.GetValue(currElem)});
+ }
+ else
+ {
+ newArray[currElem] = wrapperCons.Invoke(new Object[] {oldArray.GetValue(currElem)});
+ }
+ }
+
+ // Update the argument.
+ aArgs[i] = newArray;
+ }
+ else
+ {
+ // Determine the wrapper to use and then wrap the argument.
+ switch ((DispatchWrapperType)aWrapperTypes[i])
+ {
+ case DispatchWrapperType.Unknown:
+ aArgs[i] = new UnknownWrapper(aArgs[i]);
+ break;
+ case DispatchWrapperType.Dispatch:
+ aArgs[i] = new DispatchWrapper(aArgs[i]);
+ break;
+ case DispatchWrapperType.Error:
+ aArgs[i] = new ErrorWrapper(aArgs[i]);
+ break;
+ case DispatchWrapperType.Currency:
+ aArgs[i] = new CurrencyWrapper(aArgs[i]);
+ break;
+ case DispatchWrapperType.BStr:
+ aArgs[i] = new BStrWrapper((String)aArgs[i]);
+ break;
+ default:
+ Contract.Assert(false, "[RuntimeType.WrapArgsForInvokeCall]Invalid wrapper type specified.");
+ break;
+ }
+ }
+ }
+ }
+
+ private OleAutBinder ForwardCallBinder
+ {
+ get
+ {
+ // Synchronization is not required.
+ if (s_ForwardCallBinder == null)
+ s_ForwardCallBinder = new OleAutBinder();
+
+ return s_ForwardCallBinder;
+ }
+ }
+
+ [Flags]
+ private enum DispatchWrapperType : int
+ {
+ // This enum must stay in sync with the DispatchWrapperType enum defined in MLInfo.h
+ Unknown = 0x00000001,
+ Dispatch = 0x00000002,
+ Record = 0x00000004,
+ Error = 0x00000008,
+ Currency = 0x00000010,
+ BStr = 0x00000020,
+ SafeArray = 0x00010000
+ }
+
+ private static volatile OleAutBinder s_ForwardCallBinder;
+#endif // FEATURE_COMINTEROP && FEATURE_REMOTING
+ #endregion
+ }
+
+ // this is the introspection only type. This type overrides all the functions with runtime semantics
+ // and throws an exception.
+ // The idea behind this type is that it relieves RuntimeType from doing honerous checks about ReflectionOnly
+ // context.
+ // This type should not derive from RuntimeType but it's doing so for convinience.
+ // That should not present a security threat though it is risky as a direct call to one of the base method
+ // method (RuntimeType) and an instance of this type will work around the reason to have this type in the
+ // first place. However given RuntimeType is not public all its methods are protected and require full trust
+ // to be accessed
+ [Serializable]
+ internal class ReflectionOnlyType : RuntimeType {
+
+ private ReflectionOnlyType() {}
+
+ // always throw
+ public override RuntimeTypeHandle TypeHandle
+ {
+ get
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAllowedInReflectionOnly"));
+ }
+ }
+
+ }
+
+ #region Library
+ internal unsafe struct Utf8String
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern unsafe bool EqualsCaseSensitive(void* szLhs, void* szRhs, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern unsafe bool EqualsCaseInsensitive(void* szLhs, void* szRhs, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern unsafe uint HashCaseInsensitive(void* sz, int cSz);
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static int GetUtf8StringByteLength(void* pUtf8String)
+ {
+ int len = 0;
+
+ unsafe
+ {
+ byte* pItr = (byte*)pUtf8String;
+
+ while (*pItr != 0)
+ {
+ len++;
+ pItr++;
+ }
+ }
+
+ return len;
+ }
+
+ [SecurityCritical]
+ private void* m_pStringHeap; // This is the raw UTF8 string.
+ private int m_StringHeapByteLength;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Utf8String(void* pStringHeap)
+ {
+ m_pStringHeap = pStringHeap;
+ if (pStringHeap != null)
+ {
+ m_StringHeapByteLength = GetUtf8StringByteLength(pStringHeap);
+ }
+ else
+ {
+ m_StringHeapByteLength = 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe Utf8String(void* pUtf8String, int cUtf8String)
+ {
+ m_pStringHeap = pUtf8String;
+ m_StringHeapByteLength = cUtf8String;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe bool Equals(Utf8String s)
+ {
+ if (m_pStringHeap == null)
+ {
+ return s.m_StringHeapByteLength == 0;
+ }
+ if ((s.m_StringHeapByteLength == m_StringHeapByteLength) && (m_StringHeapByteLength != 0))
+ {
+ return Utf8String.EqualsCaseSensitive(s.m_pStringHeap, m_pStringHeap, m_StringHeapByteLength);
+ }
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe bool EqualsCaseInsensitive(Utf8String s)
+ {
+ if (m_pStringHeap == null)
+ {
+ return s.m_StringHeapByteLength == 0;
+ }
+ if ((s.m_StringHeapByteLength == m_StringHeapByteLength) && (m_StringHeapByteLength != 0))
+ {
+ return Utf8String.EqualsCaseInsensitive(s.m_pStringHeap, m_pStringHeap, m_StringHeapByteLength);
+ }
+ return false;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe uint HashCaseInsensitive()
+ {
+ return Utf8String.HashCaseInsensitive(m_pStringHeap, m_StringHeapByteLength);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override string ToString()
+ {
+ unsafe
+ {
+ byte* buf = stackalloc byte[m_StringHeapByteLength];
+ byte* pItr = (byte*)m_pStringHeap;
+
+ for (int currentPos = 0; currentPos < m_StringHeapByteLength; currentPos++)
+ {
+ buf[currentPos] = *pItr;
+ pItr++;
+ }
+
+ if (m_StringHeapByteLength == 0)
+ return "";
+
+ int cResult = Encoding.UTF8.GetCharCount(buf, m_StringHeapByteLength);
+ char* result = stackalloc char[cResult];
+ Encoding.UTF8.GetChars(buf, m_StringHeapByteLength, result, cResult);
+ return new string(result, 0, cResult);
+ }
+ }
+ }
+ #endregion
+}
+
+namespace System.Reflection
+{
+ // Reliable hashtable thread safe for multiple readers and single writer. Note that the reliability goes together with thread
+ // safety. Thread safety for multiple readers requires atomic update of the state that also makes makes the table
+ // reliable in the presence of asynchronous exceptions.
+ internal struct CerHashtable<K, V> where K : class
+ {
+ private class Table
+ {
+ // Note that m_keys and m_values arrays are immutable to allow lock-free reads. A new instance
+ // of CerHashtable has to be allocated to grow the size of the hashtable.
+ internal K[] m_keys;
+ internal V[] m_values;
+ internal int m_count;
+
+ internal Table(int size)
+ {
+ size = HashHelpers.GetPrime(size);
+ m_keys = new K[size];
+ m_values = new V[size];
+ }
+
+ internal void Insert(K key, V value)
+ {
+
+ int hashcode = GetHashCodeHelper(key);
+ if (hashcode < 0)
+ hashcode = ~hashcode;
+
+ K[] keys = m_keys;
+ int index = hashcode % keys.Length;
+
+ while (true)
+ {
+ K hit = keys[index];
+
+ if (hit == null)
+ {
+ m_count++;
+ m_values[index] = value;
+
+ // This volatile write has to be last. It is going to publish the result atomically.
+ //
+ // Note that incrementing the count or setting the value does not do any harm without setting the key. The inconsistency will be ignored
+ // and it will go away completely during next rehash.
+ Volatile.Write(ref keys[index], key);
+
+ break;
+ }
+ else
+ {
+ Contract.Assert(!hit.Equals(key), "Key was already in CerHashtable! Potential race condition (or bug) in the Reflection cache?");
+
+ index++;
+ if (index >= keys.Length)
+ index -= keys.Length;
+ }
+ }
+ }
+ }
+
+ private Table m_Table;
+
+ private const int MinSize = 7;
+
+ private static int GetHashCodeHelper(K key)
+ {
+ string sKey = key as string;
+
+ // For strings we don't want the key to differ across domains as CerHashtable might be shared.
+ if(sKey == null)
+ {
+ return key.GetHashCode();
+
+ }
+ else
+ {
+ return sKey.GetLegacyNonRandomizedHashCode();
+ }
+ }
+
+ private void Rehash(int newSize)
+ {
+ Table newTable = new Table(newSize);
+
+ Table oldTable = m_Table;
+ if (oldTable != null)
+ {
+ K[] keys = oldTable.m_keys;
+ V[] values = oldTable.m_values;
+
+ for (int i = 0; i < keys.Length; i++)
+ {
+ K key = keys[i];
+
+ if (key != null)
+ {
+ newTable.Insert(key, values[i]);
+ }
+ }
+ }
+
+ // Publish the new table atomically
+ Volatile.Write(ref m_Table, newTable);
+ }
+
+ internal V this[K key]
+ {
+ set
+ {
+ Table table = m_Table;
+
+ if (table != null)
+ {
+ int requiredSize = 2 * (table.m_count + 1);
+ if (requiredSize >= table.m_keys.Length)
+ Rehash(requiredSize);
+ }
+ else
+ {
+ Rehash(MinSize);
+ }
+
+ m_Table.Insert(key, value);
+ }
+ get
+ {
+ Table table = Volatile.Read(ref m_Table);
+ if (table == null)
+ return default(V);
+
+ int hashcode = GetHashCodeHelper(key);
+ if (hashcode < 0)
+ hashcode = ~hashcode;
+
+ K[] keys = table.m_keys;
+ int index = hashcode % keys.Length;
+
+ while (true)
+ {
+ // This volatile read has to be first. It is reading the atomically published result.
+ K hit = Volatile.Read(ref keys[index]);
+
+ if (hit != null)
+ {
+ if (hit.Equals(key))
+ return table.m_values[index];
+
+ index++;
+ if (index >= keys.Length)
+ index -= keys.Length;
+ }
+ else
+ {
+ return default(V);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs
new file mode 100644
index 0000000000..b0010fd7bd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AccessedThroughPropertyAttribute.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+ [AttributeUsage(AttributeTargets.Field)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AccessedThroughPropertyAttribute : Attribute
+ {
+ private readonly string propertyName;
+
+ public AccessedThroughPropertyAttribute(string propertyName)
+ {
+ this.propertyName = propertyName;
+ }
+
+ public string PropertyName
+ {
+ get
+ {
+ return propertyName;
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs
new file mode 100644
index 0000000000..c021353475
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblyAttributesGoHere.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.CompilerServices {
+
+ using System;
+
+ // NOTE TO DEVELOPERS: These classes are used by ALink (the assembly linker).
+ // They're used for metadata tokens for making multi-module assemblies.
+ // Do not randomly touch these classes.
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal sealed class AssemblyAttributesGoHere
+ {
+
+ internal AssemblyAttributesGoHere()
+ {
+ }
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal sealed class AssemblyAttributesGoHereS
+ {
+ internal AssemblyAttributesGoHereS()
+ {
+ }
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal sealed class AssemblyAttributesGoHereM
+ {
+ internal AssemblyAttributesGoHereM()
+ {
+ }
+ }
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal sealed class AssemblyAttributesGoHereSM
+ {
+ internal AssemblyAttributesGoHereSM()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs
new file mode 100644
index 0000000000..5251122629
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AssemblySettingAttributes.cs
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System.Runtime.CompilerServices
+{
+
+ using System;
+ using System.Runtime.InteropServices;
+
+ /*
+ NGenHint is not supported in Whidbey
+
+ [Serializable]
+ public enum NGenHint
+ {
+ Default = 0x0000, // No preference specified
+
+ Eager = 0x0001, // NGen at install time
+ Lazy = 0x0002, // NGen after install time
+ Never = 0x0003, // Assembly should not be ngened
+ }
+ */
+
+ [Serializable]
+ public enum LoadHint
+ {
+ Default = 0x0000, // No preference specified
+
+ Always = 0x0001, // Dependency is always loaded
+ Sometimes = 0x0002, // Dependency is sometimes loaded
+ //Never = 0x0003, // Dependency is never loaded
+ }
+
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Assembly)]
+ public sealed class DefaultDependencyAttribute : Attribute
+ {
+ private LoadHint loadHint;
+
+ public DefaultDependencyAttribute (
+ LoadHint loadHintArgument
+ )
+ {
+ loadHint = loadHintArgument;
+ }
+
+ public LoadHint LoadHint
+ {
+ get
+ {
+ return loadHint;
+ }
+ }
+ }
+
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
+ public sealed class DependencyAttribute : Attribute
+ {
+ private String dependentAssembly;
+ private LoadHint loadHint;
+
+ public DependencyAttribute (
+ String dependentAssemblyArgument,
+ LoadHint loadHintArgument
+ )
+ {
+ dependentAssembly = dependentAssemblyArgument;
+ loadHint = loadHintArgument;
+ }
+
+ public String DependentAssembly
+ {
+ get
+ {
+ return dependentAssembly;
+ }
+ }
+
+ public LoadHint LoadHint
+ {
+ get
+ {
+ return loadHint;
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
new file mode 100644
index 0000000000..05850605b8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
@@ -0,0 +1,1187 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Compiler-targeted types that build tasks for use as the return types of asynchronous methods.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Runtime.ExceptionServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+using System.Threading.Tasks;
+
+#if FEATURE_COMINTEROP
+using System.Runtime.InteropServices.WindowsRuntime;
+#endif // FEATURE_COMINTEROP
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Provides a builder for asynchronous methods that return void.
+ /// This type is intended for compiler use only.
+ /// </summary>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct AsyncVoidMethodBuilder
+ {
+ /// <summary>The synchronization context associated with this operation.</summary>
+ private SynchronizationContext m_synchronizationContext;
+ /// <summary>State related to the IAsyncStateMachine.</summary>
+ private AsyncMethodBuilderCore m_coreState; // mutable struct: must not be readonly
+ /// <summary>Task used for debugging and logging purposes only. Lazily initialized.</summary>
+ private Task m_task;
+
+ /// <summary>Initializes a new <see cref="AsyncVoidMethodBuilder"/>.</summary>
+ /// <returns>The initialized <see cref="AsyncVoidMethodBuilder"/>.</returns>
+ public static AsyncVoidMethodBuilder Create()
+ {
+ // Capture the current sync context. If there isn't one, use the dummy s_noContextCaptured
+ // instance; this allows us to tell the state of no captured context apart from the state
+ // of an improperly constructed builder instance.
+ SynchronizationContext sc = SynchronizationContext.CurrentNoFlow;
+ if (sc != null)
+ sc.OperationStarted();
+ return new AsyncVoidMethodBuilder() { m_synchronizationContext = sc };
+ }
+
+ /// <summary>Initiates the builder's execution with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception>
+ [SecuritySafeCritical]
+ [DebuggerStepThrough]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
+ {
+ // See comment on AsyncMethodBuilderCore.Start
+ // AsyncMethodBuilderCore.Start(ref stateMachine);
+
+ if (stateMachine == null) throw new ArgumentNullException("stateMachine");
+ Contract.EndContractBlock();
+
+ // Run the MoveNext method within a copy-on-write ExecutionContext scope.
+ // This allows us to undo any ExecutionContext changes made in MoveNext,
+ // so that they won't "leak" out of the first await.
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher);
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs);
+ stateMachine.MoveNext();
+ }
+ finally
+ {
+ ecs.Undo(currentThread);
+ }
+ }
+
+ /// <summary>Associates the builder with the state machine it represents.</summary>
+ /// <param name="stateMachine">The heap-allocated state machine object.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception>
+ public void SetStateMachine(IAsyncStateMachine stateMachine)
+ {
+ m_coreState.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ try
+ {
+ AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null;
+ var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize);
+ Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action.");
+
+ // If this is our first await, such that we've not yet boxed the state machine, do so now.
+ if (m_coreState.m_stateMachine == null)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Task.Id, "Async: " + stateMachine.GetType().Name, 0);
+
+ // Box the state machine, then tell the boxed instance to call back into its own builder,
+ // so we can cache the boxed reference. NOTE: The language compiler may choose to use
+ // a class instead of a struct for the state machine for debugging purposes; in such cases,
+ // the stateMachine will already be an object.
+ m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, null);
+ }
+
+ awaiter.OnCompleted(continuation);
+ }
+ catch (Exception exc)
+ {
+ // Prevent exceptions from leaking to the call site, which could
+ // then allow multiple flows of execution through the same async method
+ // if the awaiter had already scheduled the continuation by the time
+ // the exception was thrown. We propagate the exception on the
+ // ThreadPool because we can trust it to not throw, unlike
+ // if we were to go to a user-supplied SynchronizationContext,
+ // whose Post method could easily throw.
+ AsyncMethodBuilderCore.ThrowAsync(exc, targetContext: null);
+ }
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ [SecuritySafeCritical]
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ try
+ {
+ AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null;
+ var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize);
+ Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action.");
+
+ // If this is our first await, such that we've not yet boxed the state machine, do so now.
+ if (m_coreState.m_stateMachine == null)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Task.Id, "Async: " + stateMachine.GetType().Name, 0);
+
+ // Box the state machine, then tell the boxed instance to call back into its own builder,
+ // so we can cache the boxed reference. NOTE: The language compiler may choose to use
+ // a class instead of a struct for the state machine for debugging purposes; in such cases,
+ // the stateMachine will already be an object.
+ m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, null);
+ }
+
+ awaiter.UnsafeOnCompleted(continuation);
+ }
+ catch (Exception e)
+ {
+ AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ }
+ }
+
+ /// <summary>Completes the method builder successfully.</summary>
+ public void SetResult()
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Task.Id, AsyncCausalityStatus.Completed);
+
+ if (m_synchronizationContext != null)
+ {
+ NotifySynchronizationContextOfCompletion();
+ }
+ }
+
+ /// <summary>Faults the method builder with an exception.</summary>
+ /// <param name="exception">The exception that is the cause of this fault.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception>
+ public void SetException(Exception exception)
+ {
+ if (exception == null) throw new ArgumentNullException("exception");
+ Contract.EndContractBlock();
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Task.Id, AsyncCausalityStatus.Error);
+
+ if (m_synchronizationContext != null)
+ {
+ // If we captured a synchronization context, Post the throwing of the exception to it
+ // and decrement its outstanding operation count.
+ try
+ {
+ AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: m_synchronizationContext);
+ }
+ finally
+ {
+ NotifySynchronizationContextOfCompletion();
+ }
+ }
+ else
+ {
+ // Otherwise, queue the exception to be thrown on the ThreadPool. This will
+ // result in a crash unless legacy exception behavior is enabled by a config
+ // file or a CLR host.
+ AsyncMethodBuilderCore.ThrowAsync(exception, targetContext: null);
+ }
+ }
+
+ /// <summary>Notifies the current synchronization context that the operation completed.</summary>
+ private void NotifySynchronizationContextOfCompletion()
+ {
+ Contract.Assert(m_synchronizationContext != null, "Must only be used with a non-null context.");
+ try
+ {
+ m_synchronizationContext.OperationCompleted();
+ }
+ catch (Exception exc)
+ {
+ // If the interaction with the SynchronizationContext goes awry,
+ // fall back to propagating on the ThreadPool.
+ AsyncMethodBuilderCore.ThrowAsync(exc, targetContext: null);
+ }
+ }
+
+ // This property lazily instantiates the Task in a non-thread-safe manner.
+ private Task Task
+ {
+ get
+ {
+ if (m_task == null) m_task = new Task();
+ return m_task;
+ }
+ }
+
+ /// <summary>
+ /// Gets an object that may be used to uniquely identify this builder to the debugger.
+ /// </summary>
+ /// <remarks>
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// It must only be used by the debugger and AsyncCausalityTracer in a single-threaded manner.
+ /// </remarks>
+ private object ObjectIdForDebugger { get { return this.Task; } }
+ }
+
+ /// <summary>
+ /// Provides a builder for asynchronous methods that return <see cref="System.Threading.Tasks.Task"/>.
+ /// This type is intended for compiler use only.
+ /// </summary>
+ /// <remarks>
+ /// AsyncTaskMethodBuilder is a value type, and thus it is copied by value.
+ /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed,
+ /// or else the copies may end up building distinct Task instances.
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct AsyncTaskMethodBuilder
+ {
+ /// <summary>A cached VoidTaskResult task used for builders that complete synchronously.</summary>
+ private readonly static Task<VoidTaskResult> s_cachedCompleted = AsyncTaskMethodBuilder<VoidTaskResult>.s_defaultResultTask;
+
+ /// <summary>The generic builder object to which this non-generic instance delegates.</summary>
+ private AsyncTaskMethodBuilder<VoidTaskResult> m_builder; // mutable struct: must not be readonly
+
+ /// <summary>Initializes a new <see cref="AsyncTaskMethodBuilder"/>.</summary>
+ /// <returns>The initialized <see cref="AsyncTaskMethodBuilder"/>.</returns>
+ public static AsyncTaskMethodBuilder Create()
+ {
+ return default(AsyncTaskMethodBuilder);
+ // Note: If ATMB<T>.Create is modified to do any initialization, this
+ // method needs to be updated to do m_builder = ATMB<T>.Create().
+ }
+
+ /// <summary>Initiates the builder's execution with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ [SecuritySafeCritical]
+ [DebuggerStepThrough]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
+ {
+ // See comment on AsyncMethodBuilderCore.Start
+ // AsyncMethodBuilderCore.Start(ref stateMachine);
+
+ if (stateMachine == null) throw new ArgumentNullException("stateMachine");
+ Contract.EndContractBlock();
+
+ // Run the MoveNext method within a copy-on-write ExecutionContext scope.
+ // This allows us to undo any ExecutionContext changes made in MoveNext,
+ // so that they won't "leak" out of the first await.
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher);
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs);
+ stateMachine.MoveNext();
+ }
+ finally
+ {
+ ecs.Undo(currentThread);
+ }
+ }
+
+ /// <summary>Associates the builder with the state machine it represents.</summary>
+ /// <param name="stateMachine">The heap-allocated state machine object.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception>
+ public void SetStateMachine(IAsyncStateMachine stateMachine)
+ {
+ m_builder.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ m_builder.AwaitOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine);
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ m_builder.AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref awaiter, ref stateMachine);
+ }
+
+ /// <summary>Gets the <see cref="System.Threading.Tasks.Task"/> for this builder.</summary>
+ /// <returns>The <see cref="System.Threading.Tasks.Task"/> representing the builder's asynchronous operation.</returns>
+ /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception>
+ public Task Task { get { return m_builder.Task; } }
+
+ /// <summary>
+ /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
+ /// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state.
+ /// </summary>
+ /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception>
+ /// <exception cref="System.InvalidOperationException">The task has already completed.</exception>
+ public void SetResult()
+ {
+ // Accessing AsyncTaskMethodBuilder.s_cachedCompleted is faster than
+ // accessing AsyncTaskMethodBuilder<T>.s_defaultResultTask.
+ m_builder.SetResult(s_cachedCompleted);
+ }
+
+ /// <summary>
+ /// Completes the <see cref="System.Threading.Tasks.Task"/> in the
+ /// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception.
+ /// </summary>
+ /// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is not initialized.</exception>
+ /// <exception cref="System.InvalidOperationException">The task has already completed.</exception>
+ public void SetException(Exception exception) { m_builder.SetException(exception); }
+
+ /// <summary>
+ /// Called by the debugger to request notification when the first wait operation
+ /// (await, Wait, Result, etc.) on this builder's task completes.
+ /// </summary>
+ /// <param name="enabled">
+ /// true to enable notification; false to disable a previously set notification.
+ /// </param>
+ internal void SetNotificationForWaitCompletion(bool enabled)
+ {
+ m_builder.SetNotificationForWaitCompletion(enabled);
+ }
+
+ /// <summary>
+ /// Gets an object that may be used to uniquely identify this builder to the debugger.
+ /// </summary>
+ /// <remarks>
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// It must only be used by the debugger and tracing pruposes, and only in a single-threaded manner
+ /// when no other threads are in the middle of accessing this property or this.Task.
+ /// </remarks>
+ private object ObjectIdForDebugger { get { return this.Task; } }
+ }
+
+ /// <summary>
+ /// Provides a builder for asynchronous methods that return <see cref="System.Threading.Tasks.Task{TResult}"/>.
+ /// This type is intended for compiler use only.
+ /// </summary>
+ /// <remarks>
+ /// AsyncTaskMethodBuilder{TResult} is a value type, and thus it is copied by value.
+ /// Prior to being copied, one of its Task, SetResult, or SetException members must be accessed,
+ /// or else the copies may end up building distinct Task instances.
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct AsyncTaskMethodBuilder<TResult>
+ {
+ /// <summary>A cached task for default(TResult).</summary>
+ internal readonly static Task<TResult> s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult));
+
+ // WARNING: For performance reasons, the m_task field is lazily initialized.
+ // For correct results, the struct AsyncTaskMethodBuilder<TResult> must
+ // always be used from the same location/copy, at least until m_task is
+ // initialized. If that guarantee is broken, the field could end up being
+ // initialized on the wrong copy.
+
+ /// <summary>State related to the IAsyncStateMachine.</summary>
+ private AsyncMethodBuilderCore m_coreState; // mutable struct: must not be readonly
+ /// <summary>The lazily-initialized built task.</summary>
+ private Task<TResult> m_task; // lazily-initialized: must not be readonly
+
+ /// <summary>Initializes a new <see cref="AsyncTaskMethodBuilder"/>.</summary>
+ /// <returns>The initialized <see cref="AsyncTaskMethodBuilder"/>.</returns>
+ public static AsyncTaskMethodBuilder<TResult> Create()
+ {
+ return default(AsyncTaskMethodBuilder<TResult>);
+ // NOTE: If this method is ever updated to perform more initialization,
+ // ATMB.Create must also be updated to call this Create method.
+ }
+
+ /// <summary>Initiates the builder's execution with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ [SecuritySafeCritical]
+ [DebuggerStepThrough]
+ public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine
+ {
+ // See comment on AsyncMethodBuilderCore.Start
+ // AsyncMethodBuilderCore.Start(ref stateMachine);
+
+ if (stateMachine == null) throw new ArgumentNullException("stateMachine");
+ Contract.EndContractBlock();
+
+ // Run the MoveNext method within a copy-on-write ExecutionContext scope.
+ // This allows us to undo any ExecutionContext changes made in MoveNext,
+ // so that they won't "leak" out of the first await.
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher);
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs);
+ stateMachine.MoveNext();
+ }
+ finally
+ {
+ ecs.Undo(currentThread);
+ }
+ }
+
+ /// <summary>Associates the builder with the state machine it represents.</summary>
+ /// <param name="stateMachine">The heap-allocated state machine object.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception>
+ public void SetStateMachine(IAsyncStateMachine stateMachine)
+ {
+ m_coreState.SetStateMachine(stateMachine); // argument validation handled by AsyncMethodBuilderCore
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ public void AwaitOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : INotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ try
+ {
+ AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null;
+ var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize);
+ Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action.");
+
+ // If this is our first await, such that we've not yet boxed the state machine, do so now.
+ if (m_coreState.m_stateMachine == null)
+ {
+ // Force the Task to be initialized prior to the first suspending await so
+ // that the original stack-based builder has a reference to the right Task.
+ var builtTask = this.Task;
+
+ // Box the state machine, then tell the boxed instance to call back into its own builder,
+ // so we can cache the boxed reference. NOTE: The language compiler may choose to use
+ // a class instead of a struct for the state machine for debugging purposes; in such cases,
+ // the stateMachine will already be an object.
+ m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, builtTask);
+ }
+
+ awaiter.OnCompleted(continuation);
+ }
+ catch (Exception e)
+ {
+ AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ }
+ }
+
+ /// <summary>
+ /// Schedules the specified state machine to be pushed forward when the specified awaiter completes.
+ /// </summary>
+ /// <typeparam name="TAwaiter">Specifies the type of the awaiter.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="awaiter">The awaiter.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ [SecuritySafeCritical]
+ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(
+ ref TAwaiter awaiter, ref TStateMachine stateMachine)
+ where TAwaiter : ICriticalNotifyCompletion
+ where TStateMachine : IAsyncStateMachine
+ {
+ try
+ {
+ AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null;
+ var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize);
+ Contract.Assert(continuation != null, "GetCompletionAction should always return a valid action.");
+
+ // If this is our first await, such that we've not yet boxed the state machine, do so now.
+ if (m_coreState.m_stateMachine == null)
+ {
+ // Force the Task to be initialized prior to the first suspending await so
+ // that the original stack-based builder has a reference to the right Task.
+ var builtTask = this.Task;
+
+ // Box the state machine, then tell the boxed instance to call back into its own builder,
+ // so we can cache the boxed reference. NOTE: The language compiler may choose to use
+ // a class instead of a struct for the state machine for debugging purposes; in such cases,
+ // the stateMachine will already be an object.
+ m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, builtTask);
+ }
+
+ awaiter.UnsafeOnCompleted(continuation);
+ }
+ catch (Exception e)
+ {
+ AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null);
+ }
+ }
+
+ /// <summary>Gets the <see cref="System.Threading.Tasks.Task{TResult}"/> for this builder.</summary>
+ /// <returns>The <see cref="System.Threading.Tasks.Task{TResult}"/> representing the builder's asynchronous operation.</returns>
+ public Task<TResult> Task
+ {
+ get
+ {
+ // Get and return the task. If there isn't one, first create one and store it.
+ var task = m_task;
+ if (task == null) { m_task = task = new Task<TResult>(); }
+ return task;
+ }
+ }
+
+ /// <summary>
+ /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
+ /// <see cref="System.Threading.Tasks.TaskStatus">RanToCompletion</see> state with the specified result.
+ /// </summary>
+ /// <param name="result">The result to use to complete the task.</param>
+ /// <exception cref="System.InvalidOperationException">The task has already completed.</exception>
+ public void SetResult(TResult result)
+ {
+ // Get the currently stored task, which will be non-null if get_Task has already been accessed.
+ // If there isn't one, get a task and store it.
+ var task = m_task;
+ if (task == null)
+ {
+ m_task = GetTaskForResult(result);
+ Contract.Assert(m_task != null, "GetTaskForResult should never return null");
+ }
+ // Slow path: complete the existing task.
+ else
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, task.Id, AsyncCausalityStatus.Completed);
+
+ //only log if we have a real task that was previously created
+ if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled)
+ {
+ System.Threading.Tasks.Task.RemoveFromActiveTasks(task.Id);
+ }
+
+ if (!task.TrySetResult(result))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("TaskT_TransitionToFinal_AlreadyCompleted"));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Completes the builder by using either the supplied completed task, or by completing
+ /// the builder's previously accessed task using default(TResult).
+ /// </summary>
+ /// <param name="completedTask">A task already completed with the value default(TResult).</param>
+ /// <exception cref="System.InvalidOperationException">The task has already completed.</exception>
+ internal void SetResult(Task<TResult> completedTask)
+ {
+ Contract.Requires(completedTask != null, "Expected non-null task");
+ Contract.Requires(completedTask.Status == TaskStatus.RanToCompletion, "Expected a successfully completed task");
+
+ // Get the currently stored task, which will be non-null if get_Task has already been accessed.
+ // If there isn't one, store the supplied completed task.
+ var task = m_task;
+ if (task == null)
+ {
+ m_task = completedTask;
+ }
+ else
+ {
+ // Otherwise, complete the task that's there.
+ SetResult(default(TResult));
+ }
+ }
+
+ /// <summary>
+ /// Completes the <see cref="System.Threading.Tasks.Task{TResult}"/> in the
+ /// <see cref="System.Threading.Tasks.TaskStatus">Faulted</see> state with the specified exception.
+ /// </summary>
+ /// <param name="exception">The <see cref="System.Exception"/> to use to fault the task.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="exception"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The task has already completed.</exception>
+ public void SetException(Exception exception)
+ {
+ if (exception == null) throw new ArgumentNullException("exception");
+ Contract.EndContractBlock();
+
+
+ var task = m_task;
+ if (task == null)
+ {
+ // Get the task, forcing initialization if it hasn't already been initialized.
+ task = this.Task;
+ }
+
+ // If the exception represents cancellation, cancel the task. Otherwise, fault the task.
+ var oce = exception as OperationCanceledException;
+ bool successfullySet = oce != null ?
+ task.TrySetCanceled(oce.CancellationToken, oce) :
+ task.TrySetException(exception);
+
+ // Unlike with TaskCompletionSource, we do not need to spin here until m_task is completed,
+ // since AsyncTaskMethodBuilder.SetException should not be immediately followed by any code
+ // that depends on the task having completely completed. Moreover, with correct usage,
+ // SetResult or SetException should only be called once, so the Try* methods should always
+ // return true, so no spinning would be necessary anyway (the spinning in TCS is only relevant
+ // if another thread completes the task first).
+
+ if (!successfullySet)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("TaskT_TransitionToFinal_AlreadyCompleted"));
+ }
+ }
+
+ /// <summary>
+ /// Called by the debugger to request notification when the first wait operation
+ /// (await, Wait, Result, etc.) on this builder's task completes.
+ /// </summary>
+ /// <param name="enabled">
+ /// true to enable notification; false to disable a previously set notification.
+ /// </param>
+ /// <remarks>
+ /// This should only be invoked from within an asynchronous method,
+ /// and only by the debugger.
+ /// </remarks>
+ internal void SetNotificationForWaitCompletion(bool enabled)
+ {
+ // Get the task (forcing initialization if not already initialized), and set debug notification
+ this.Task.SetNotificationForWaitCompletion(enabled);
+ }
+
+ /// <summary>
+ /// Gets an object that may be used to uniquely identify this builder to the debugger.
+ /// </summary>
+ /// <remarks>
+ /// This property lazily instantiates the ID in a non-thread-safe manner.
+ /// It must only be used by the debugger and tracing purposes, and only in a single-threaded manner
+ /// when no other threads are in the middle of accessing this property or this.Task.
+ /// </remarks>
+ private object ObjectIdForDebugger { get { return this.Task; } }
+
+ /// <summary>
+ /// Gets a task for the specified result. This will either
+ /// be a cached or new task, never null.
+ /// </summary>
+ /// <param name="result">The result for which we need a task.</param>
+ /// <returns>The completed task containing the result.</returns>
+ [SecuritySafeCritical] // for JitHelpers.UnsafeCast
+ private Task<TResult> GetTaskForResult(TResult result)
+ {
+ Contract.Ensures(
+ EqualityComparer<TResult>.Default.Equals(result, Contract.Result<Task<TResult>>().Result),
+ "The returned task's Result must return the same value as the specified result value.");
+
+ // The goal of this function is to be give back a cached task if possible,
+ // or to otherwise give back a new task. To give back a cached task,
+ // we need to be able to evaluate the incoming result value, and we need
+ // to avoid as much overhead as possible when doing so, as this function
+ // is invoked as part of the return path from every async method.
+ // Most tasks won't be cached, and thus we need the checks for those that are
+ // to be as close to free as possible. This requires some trickiness given the
+ // lack of generic specialization in .NET.
+ //
+ // Be very careful when modifying this code. It has been tuned
+ // to comply with patterns recognized by both 32-bit and 64-bit JITs.
+ // If changes are made here, be sure to look at the generated assembly, as
+ // small tweaks can have big consequences for what does and doesn't get optimized away.
+ //
+ // Note that this code only ever accesses a static field when it knows it'll
+ // find a cached value, since static fields (even if readonly and integral types)
+ // require special access helpers in this NGEN'd and domain-neutral.
+
+ if (null != (object)default(TResult)) // help the JIT avoid the value type branches for ref types
+ {
+ // Special case simple value types:
+ // - Boolean
+ // - Byte, SByte
+ // - Char
+ // - Decimal
+ // - Int32, UInt32
+ // - Int64, UInt64
+ // - Int16, UInt16
+ // - IntPtr, UIntPtr
+ // As of .NET 4.5, the (Type)(object)result pattern used below
+ // is recognized and optimized by both 32-bit and 64-bit JITs.
+
+ // For Boolean, we cache all possible values.
+ if (typeof(TResult) == typeof(Boolean)) // only the relevant branches are kept for each value-type generic instantiation
+ {
+ Boolean value = (Boolean)(object)result;
+ Task<Boolean> task = value ? AsyncTaskCache.TrueTask : AsyncTaskCache.FalseTask;
+ return JitHelpers.UnsafeCast<Task<TResult>>(task); // UnsafeCast avoids type check we know will succeed
+ }
+ // For Int32, we cache a range of common values, e.g. [-1,4).
+ else if (typeof(TResult) == typeof(Int32))
+ {
+ // Compare to constants to avoid static field access if outside of cached range.
+ // We compare to the upper bound first, as we're more likely to cache miss on the upper side than on the
+ // lower side, due to positive values being more common than negative as return values.
+ Int32 value = (Int32)(object)result;
+ if (value < AsyncTaskCache.EXCLUSIVE_INT32_MAX &&
+ value >= AsyncTaskCache.INCLUSIVE_INT32_MIN)
+ {
+ Task<Int32> task = AsyncTaskCache.Int32Tasks[value - AsyncTaskCache.INCLUSIVE_INT32_MIN];
+ return JitHelpers.UnsafeCast<Task<TResult>>(task); // UnsafeCast avoids a type check we know will succeed
+ }
+ }
+ // For other known value types, we only special-case 0 / default(TResult).
+ else if (
+ (typeof(TResult) == typeof(UInt32) && default(UInt32) == (UInt32)(object)result) ||
+ (typeof(TResult) == typeof(Byte) && default(Byte) == (Byte)(object)result) ||
+ (typeof(TResult) == typeof(SByte) && default(SByte) == (SByte)(object)result) ||
+ (typeof(TResult) == typeof(Char) && default(Char) == (Char)(object)result) ||
+ (typeof(TResult) == typeof(Decimal) && default(Decimal) == (Decimal)(object)result) ||
+ (typeof(TResult) == typeof(Int64) && default(Int64) == (Int64)(object)result) ||
+ (typeof(TResult) == typeof(UInt64) && default(UInt64) == (UInt64)(object)result) ||
+ (typeof(TResult) == typeof(Int16) && default(Int16) == (Int16)(object)result) ||
+ (typeof(TResult) == typeof(UInt16) && default(UInt16) == (UInt16)(object)result) ||
+ (typeof(TResult) == typeof(IntPtr) && default(IntPtr) == (IntPtr)(object)result) ||
+ (typeof(TResult) == typeof(UIntPtr) && default(UIntPtr) == (UIntPtr)(object)result))
+ {
+ return s_defaultResultTask;
+ }
+ }
+ else if (result == null) // optimized away for value types
+ {
+ return s_defaultResultTask;
+ }
+
+ // No cached task is available. Manufacture a new one for this result.
+ return new Task<TResult>(result);
+ }
+ }
+
+ /// <summary>Provides a cache of closed generic tasks for async methods.</summary>
+ internal static class AsyncTaskCache
+ {
+ // All static members are initialized inline to ensure type is beforefieldinit
+
+ /// <summary>A cached Task{Boolean}.Result == true.</summary>
+ internal readonly static Task<Boolean> TrueTask = CreateCacheableTask(true);
+ /// <summary>A cached Task{Boolean}.Result == false.</summary>
+ internal readonly static Task<Boolean> FalseTask = CreateCacheableTask(false);
+
+ /// <summary>The cache of Task{Int32}.</summary>
+ internal readonly static Task<Int32>[] Int32Tasks = CreateInt32Tasks();
+ /// <summary>The minimum value, inclusive, for which we want a cached task.</summary>
+ internal const Int32 INCLUSIVE_INT32_MIN = -1;
+ /// <summary>The maximum value, exclusive, for which we want a cached task.</summary>
+ internal const Int32 EXCLUSIVE_INT32_MAX = 9;
+ /// <summary>Creates an array of cached tasks for the values in the range [INCLUSIVE_MIN,EXCLUSIVE_MAX).</summary>
+ private static Task<Int32>[] CreateInt32Tasks()
+ {
+ Contract.Assert(EXCLUSIVE_INT32_MAX >= INCLUSIVE_INT32_MIN, "Expected max to be at least min");
+ var tasks = new Task<Int32>[EXCLUSIVE_INT32_MAX - INCLUSIVE_INT32_MIN];
+ for (int i = 0; i < tasks.Length; i++)
+ {
+ tasks[i] = CreateCacheableTask(i + INCLUSIVE_INT32_MIN);
+ }
+ return tasks;
+ }
+
+ /// <summary>Creates a non-disposable task.</summary>
+ /// <typeparam name="TResult">Specifies the result type.</typeparam>
+ /// <param name="result">The result for the task.</param>
+ /// <returns>The cacheable task.</returns>
+ internal static Task<TResult> CreateCacheableTask<TResult>(TResult result)
+ {
+ return new Task<TResult>(false, result, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+ }
+ }
+
+ /// <summary>Holds state related to the builder's IAsyncStateMachine.</summary>
+ /// <remarks>This is a mutable struct. Be very delicate with it.</remarks>
+ internal struct AsyncMethodBuilderCore
+ {
+ /// <summary>A reference to the heap-allocated state machine object associated with this builder.</summary>
+ internal IAsyncStateMachine m_stateMachine;
+ /// <summary>A cached Action delegate used when dealing with a default ExecutionContext.</summary>
+ internal Action m_defaultContextAction;
+
+ // This method is copy&pasted into the public Start methods to avoid size overhead of valuetype generic instantiations.
+ // Ideally, we would build intrinsics to get the raw ref address and raw code address of MoveNext, and just use the shared implementation.
+#if false
+ /// <summary>Initiates the builder's execution with the associated state machine.</summary>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam>
+ /// <param name="stateMachine">The state machine instance, passed by reference.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument is null (Nothing in Visual Basic).</exception>
+ [SecuritySafeCritical]
+ [DebuggerStepThrough]
+ internal static void Start<TStateMachine>(ref TStateMachine stateMachine)
+ where TStateMachine : IAsyncStateMachine
+ {
+ if (stateMachine == null) throw new ArgumentNullException("stateMachine");
+ Contract.EndContractBlock();
+
+ // Run the MoveNext method within a copy-on-write ExecutionContext scope.
+ // This allows us to undo any ExecutionContext changes made in MoveNext,
+ // so that they won't "leak" out of the first await.
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecs = default(ExecutionContextSwitcher);
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ ExecutionContext.EstablishCopyOnWriteScope(currentThread, ref ecs);
+ stateMachine.MoveNext();
+ }
+ finally
+ {
+ ecs.Undo(currentThread);
+ }
+ }
+#endif
+
+ /// <summary>Associates the builder with the state machine it represents.</summary>
+ /// <param name="stateMachine">The heap-allocated state machine object.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="stateMachine"/> argument was null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The builder is incorrectly initialized.</exception>
+ public void SetStateMachine(IAsyncStateMachine stateMachine)
+ {
+ if (stateMachine == null) throw new ArgumentNullException("stateMachine");
+ Contract.EndContractBlock();
+ if (m_stateMachine != null) throw new InvalidOperationException(Environment.GetResourceString("AsyncMethodBuilder_InstanceNotInitialized"));
+ m_stateMachine = stateMachine;
+ }
+
+ /// <summary>
+ /// Gets the Action to use with an awaiter's OnCompleted or UnsafeOnCompleted method.
+ /// On first invocation, the supplied state machine will be boxed.
+ /// </summary>
+ /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
+ /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
+ /// <param name="builder">The builder.</param>
+ /// <param name="stateMachine">The state machine.</param>
+ /// <returns>An Action to provide to the awaiter.</returns>
+ [SecuritySafeCritical]
+ internal Action GetCompletionAction(Task taskForTracing, ref MoveNextRunner runnerToInitialize)
+ {
+ Contract.Assert(m_defaultContextAction == null || m_stateMachine != null,
+ "Expected non-null m_stateMachine on non-null m_defaultContextAction");
+
+ // Alert a listening debugger that we can't make forward progress unless it slips threads.
+ // If we don't do this, and a method that uses "await foo;" is invoked through funceval,
+ // we could end up hooking up a callback to push forward the async method's state machine,
+ // the debugger would then abort the funceval after it takes too long, and then continuing
+ // execution could result in another callback being hooked up. At that point we have
+ // multiple callbacks registered to push the state machine, which could result in bad behavior.
+ Debugger.NotifyOfCrossThreadDependency();
+
+ // The builder needs to flow ExecutionContext, so capture it.
+ var capturedContext = ExecutionContext.FastCapture(); // ok to use FastCapture as we haven't made any permission demands/asserts
+
+ // If the ExecutionContext is the default context, try to use a cached delegate, creating one if necessary.
+ Action action;
+ MoveNextRunner runner;
+ if (capturedContext != null && capturedContext.IsPreAllocatedDefault)
+ {
+ // Get the cached delegate, and if it's non-null, return it.
+ action = m_defaultContextAction;
+ if (action != null)
+ {
+ Contract.Assert(m_stateMachine != null, "If the delegate was set, the state machine should have been as well.");
+ return action;
+ }
+
+ // There wasn't a cached delegate, so create one and cache it.
+ // The delegate won't be usable until we set the MoveNextRunner's target state machine.
+ runner = new MoveNextRunner(m_stateMachine);
+
+ action = new Action(runner.RunWithDefaultContext);
+ if (taskForTracing != null)
+ {
+ action = OutputAsyncCausalityEvents(taskForTracing, action);
+ }
+ m_defaultContextAction = action;
+ }
+ // Otherwise, create an Action that flows this context. The context may be null.
+ // The delegate won't be usable until we set the MoveNextRunner's target state machine.
+ else
+ {
+ var runnerWithContext = new MoveNextRunnerWithContext(capturedContext, m_stateMachine);
+ runner = runnerWithContext;
+ action = new Action(runnerWithContext.RunWithCapturedContext);
+
+ if (taskForTracing != null)
+ {
+ action = OutputAsyncCausalityEvents(taskForTracing, action);
+ }
+
+ // NOTE: If capturedContext is null, we could create the Action to point directly
+ // to m_stateMachine.MoveNext. However, that follows a much more expensive
+ // delegate creation path.
+ }
+
+ if (m_stateMachine == null)
+ runnerToInitialize = runner;
+
+ return action;
+ }
+
+ private Action OutputAsyncCausalityEvents(Task innerTask, Action continuation)
+ {
+ return CreateContinuationWrapper(continuation, () =>
+ {
+ AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, innerTask.Id, CausalitySynchronousWork.Execution);
+
+ // Invoke the original continuation
+ continuation.Invoke();
+
+ AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution);
+ }, innerTask);
+ }
+
+ internal void PostBoxInitialization(IAsyncStateMachine stateMachine, MoveNextRunner runner, Task builtTask)
+ {
+ if (builtTask != null)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, builtTask.Id, "Async: " + stateMachine.GetType().Name, 0);
+
+ if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled)
+ System.Threading.Tasks.Task.AddToActiveTasks(builtTask);
+ }
+
+ m_stateMachine = stateMachine;
+ m_stateMachine.SetStateMachine(m_stateMachine);
+
+ Contract.Assert(runner.m_stateMachine == null, "The runner's state machine should not yet have been populated.");
+ Contract.Assert(m_stateMachine != null, "The builder's state machine field should have been initialized.");
+
+ // Now that we have the state machine, store it into the runner that the action delegate points to.
+ // And return the action.
+ runner.m_stateMachine = m_stateMachine; // only after this line is the Action delegate usable
+ }
+
+ /// <summary>Throws the exception on the ThreadPool.</summary>
+ /// <param name="exception">The exception to propagate.</param>
+ /// <param name="targetContext">The target context on which to propagate the exception. Null to use the ThreadPool.</param>
+ internal static void ThrowAsync(Exception exception, SynchronizationContext targetContext)
+ {
+ // Capture the exception into an ExceptionDispatchInfo so that its
+ // stack trace and Watson bucket info will be preserved
+ var edi = ExceptionDispatchInfo.Capture(exception);
+
+ // If the user supplied a SynchronizationContext...
+ if (targetContext != null)
+ {
+ try
+ {
+ // Post the throwing of the exception to that context, and return.
+ targetContext.Post(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+ return;
+ }
+ catch (Exception postException)
+ {
+ // If something goes horribly wrong in the Post, we'll
+ // propagate both exceptions on the ThreadPool
+ edi = ExceptionDispatchInfo.Capture(new AggregateException(exception, postException));
+ }
+ }
+
+ // If we have the new error reporting APIs, report this error. Otherwise, Propagate the exception(s) on the ThreadPool
+#if FEATURE_COMINTEROP
+ if (!WindowsRuntimeMarshal.ReportUnhandledError(edi.SourceException))
+#endif // FEATURE_COMINTEROP
+ {
+ ThreadPool.QueueUserWorkItem(state => ((ExceptionDispatchInfo)state).Throw(), edi);
+ }
+ }
+
+ /// <summary>Provides the ability to invoke a state machine's MoveNext method under a supplied ExecutionContext.</summary>
+ internal sealed class MoveNextRunnerWithContext : MoveNextRunner
+ {
+ /// <summary>The context with which to run MoveNext.</summary>
+ private readonly ExecutionContext m_context;
+
+ /// <summary>Initializes the runner.</summary>
+ /// <param name="context">The context with which to run MoveNext.</param>
+ [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC
+ internal MoveNextRunnerWithContext(ExecutionContext context, IAsyncStateMachine stateMachine) : base(stateMachine)
+ {
+ m_context = context;
+ }
+
+ /// <summary>Invokes MoveNext under the provided context.</summary>
+ [SecuritySafeCritical]
+ internal void RunWithCapturedContext()
+ {
+ Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run.");
+
+ if (m_context != null)
+ {
+ try
+ {
+ // Use the context and callback to invoke m_stateMachine.MoveNext.
+ ExecutionContext.Run(m_context, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true);
+ }
+ finally { m_context.Dispose(); }
+ }
+ else
+ {
+ m_stateMachine.MoveNext();
+ }
+ }
+ }
+
+ /// <summary>Provides the ability to invoke a state machine's MoveNext method.</summary>
+ internal class MoveNextRunner
+ {
+ /// <summary>The state machine whose MoveNext method should be invoked.</summary>
+ internal IAsyncStateMachine m_stateMachine;
+
+ /// <summary>Initializes the runner.</summary>
+ [SecurityCritical] // Run needs to be SSC to map to Action delegate, so to prevent misuse, we only allow construction through SC
+ internal MoveNextRunner(IAsyncStateMachine stateMachine)
+ {
+ m_stateMachine = stateMachine;
+ }
+
+ /// <summary>Invokes MoveNext under the default context.</summary>
+ [SecuritySafeCritical]
+ internal void RunWithDefaultContext()
+ {
+ Contract.Assert(m_stateMachine != null, "The state machine must have been set before calling Run.");
+ ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, InvokeMoveNextCallback, m_stateMachine, preserveSyncCtx: true);
+ }
+
+ /// <summary>Gets a delegate to the InvokeMoveNext method.</summary>
+ protected static ContextCallback InvokeMoveNextCallback
+ {
+ [SecuritySafeCritical]
+ get { return s_invokeMoveNext ?? (s_invokeMoveNext = InvokeMoveNext); }
+ }
+
+ /// <summary>Cached delegate used with ExecutionContext.Run.</summary>
+ [SecurityCritical]
+ private static ContextCallback s_invokeMoveNext; // lazily-initialized due to SecurityCritical attribution
+
+ /// <summary>Invokes the MoveNext method on the supplied IAsyncStateMachine.</summary>
+ /// <param name="stateMachine">The IAsyncStateMachine machine instance.</param>
+ [SecurityCritical] // necessary for ContextCallback in CoreCLR
+ private static void InvokeMoveNext(object stateMachine)
+ {
+ ((IAsyncStateMachine)stateMachine).MoveNext();
+ }
+ }
+
+ /// <summary>
+ /// Logically we pass just an Action (delegate) to a task for its action to 'ContinueWith' when it completes.
+ /// However debuggers and profilers need more information about what that action is. (In particular what
+ /// the action after that is and after that. To solve this problem we create a 'ContinuationWrapper
+ /// which when invoked just does the original action (the invoke action), but also remembers other information
+ /// (like the action after that (which is also a ContinuationWrapper and thus form a linked list).
+ // We also store that task if the action is associate with at task.
+ /// </summary>
+ private class ContinuationWrapper
+ {
+ internal readonly Action m_continuation; // This is continuation which will happen after m_invokeAction (and is probably a ContinuationWrapper)
+ private readonly Action m_invokeAction; // This wrapper is an action that wraps another action, this is that Action.
+ internal readonly Task m_innerTask; // If the continuation is logically going to invoke a task, this is that task (may be null)
+
+ internal ContinuationWrapper(Action continuation, Action invokeAction, Task innerTask)
+ {
+ Contract.Requires(continuation != null, "Expected non-null continuation");
+
+ // If we don't have a task, see if our continuation is a wrapper and use that.
+ if (innerTask == null)
+ innerTask = TryGetContinuationTask(continuation);
+
+ m_continuation = continuation;
+ m_innerTask = innerTask;
+ m_invokeAction = invokeAction;
+ }
+
+ internal void Invoke()
+ {
+ m_invokeAction();
+ }
+ }
+
+ internal static Action CreateContinuationWrapper(Action continuation, Action invokeAction, Task innerTask = null)
+ {
+ return new ContinuationWrapper(continuation, invokeAction, innerTask).Invoke;
+ }
+
+ internal static Action TryGetStateMachineForDebugger(Action action)
+ {
+ object target = action.Target;
+ var runner = target as AsyncMethodBuilderCore.MoveNextRunner;
+ if (runner != null)
+ {
+ return new Action(runner.m_stateMachine.MoveNext);
+ }
+
+ var continuationWrapper = target as ContinuationWrapper;
+ if (continuationWrapper != null)
+ {
+ return TryGetStateMachineForDebugger(continuationWrapper.m_continuation);
+ }
+
+ return action;
+ }
+
+ ///<summary>
+ /// Given an action, see if it is a contiunation wrapper and has a Task associated with it. If so return it (null otherwise)
+ ///</summary>
+ internal static Task TryGetContinuationTask(Action action)
+ {
+ if (action != null)
+ {
+ var asWrapper = action.Target as ContinuationWrapper;
+ if (asWrapper != null)
+ return asWrapper.m_innerTask;
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs
new file mode 100644
index 0000000000..f1fc9ced82
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/AsyncStateMachineAttribute.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public sealed class AsyncStateMachineAttribute : StateMachineAttribute
+ {
+ public AsyncStateMachineAttribute(Type stateMachineType)
+ : base(stateMachineType)
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs
new file mode 100644
index 0000000000..330934cf95
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerFilePathAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerFilePathAttribute : Attribute
+ {
+ public CallerFilePathAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs
new file mode 100644
index 0000000000..9c87e8e25f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerLineNumberAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerLineNumberAttribute : Attribute
+ {
+ public CallerLineNumberAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs
new file mode 100644
index 0000000000..4fc70908fb
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallerMemberNameAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ public sealed class CallerMemberNameAttribute : Attribute
+ {
+ public CallerMemberNameAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs
new file mode 100644
index 0000000000..f44251d480
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CallingConvention.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.CompilerServices
+{
+ // Types used in Custom Modifier to specify calling conventions.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CallConvCdecl
+ {
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CallConvStdcall
+ {
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CallConvThiscall
+ {
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CallConvFastcall
+ {
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs
new file mode 100644
index 0000000000..5e4f19410b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilationRelaxations.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System.Runtime.CompilerServices
+{
+
+ using System;
+
+ /// IMPORTANT: Keep this in sync with corhdr.h
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum CompilationRelaxations : int
+ {
+ NoStringInterning = 0x0008, // Start in 0x0008, we had other non public flags in this enum before,
+ // so we'll start here just in case somebody used them. This flag is only
+ // valid when set for Assemblies.
+ };
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Method)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class CompilationRelaxationsAttribute : Attribute
+ {
+ private int m_relaxations; // The relaxations.
+
+ public CompilationRelaxationsAttribute (
+ int relaxations)
+ {
+ m_relaxations = relaxations;
+ }
+
+ public CompilationRelaxationsAttribute (
+ CompilationRelaxations relaxations)
+ {
+ m_relaxations = (int) relaxations;
+ }
+
+ public int CompilationRelaxations
+ {
+ get
+ {
+ return m_relaxations;
+ }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs
new file mode 100644
index 0000000000..1778506c7c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGeneratedAttribute.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.CompilerServices {
+
+[Serializable]
+[AttributeUsage(AttributeTargets.All, Inherited = true)]
+ public sealed class CompilerGeneratedAttribute : Attribute
+ {
+ public CompilerGeneratedAttribute () {}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs
new file mode 100644
index 0000000000..65755f6baa
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerGlobalScopeAttribute.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Attribute used to communicate to the VS7 debugger
+** that a class should be treated as if it has
+** global scope.
+**
+**
+===========================================================*/
+
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Class)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class CompilerGlobalScopeAttribute : Attribute
+ {
+ public CompilerGlobalScopeAttribute () {}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs
new file mode 100644
index 0000000000..a7b4aca480
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CompilerMarshalOverride.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // The CLR data marshaler has some behaviors that are incompatible with
+ // C++. Specifically, C++ treats boolean variables as byte size, whereas
+ // the marshaller treats them as 4-byte size. Similarly, C++ treats
+ // wchar_t variables as 4-byte size, whereas the marshaller treats them
+ // as single byte size under certain conditions. In order to work around
+ // such issues, the C++ compiler will emit a type that the marshaller will
+ // marshal using the correct sizes. In addition, the compiler will place
+ // this modopt onto the variables to indicate that the specified type is
+ // not the true type. Any compiler that needed to deal with similar
+ // marshalling incompatibilities could use this attribute as well.
+ //
+ // Indicates that the modified instance differs from its true type for
+ // correct marshalling.
+ public static class CompilerMarshalOverride
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
new file mode 100644
index 0000000000..21d677241d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs
@@ -0,0 +1,795 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Description: Compiler support for runtime-generated "object fields."
+**
+** Lets DLR and other language compilers expose the ability to
+** attach arbitrary "properties" to instanced managed objects at runtime.
+**
+** We expose this support as a dictionary whose keys are the
+** instanced objects and the values are the "properties."
+**
+** Unlike a regular dictionary, ConditionalWeakTables will not
+** keep keys alive.
+**
+**
+** Lifetimes of keys and values:
+**
+** Inserting a key and value into the dictonary will not
+** prevent the key from dying, even if the key is strongly reachable
+** from the value.
+**
+** Prior to ConditionalWeakTable, the CLR did not expose
+** the functionality needed to implement this guarantee.
+**
+** Once the key dies, the dictionary automatically removes
+** the key/value entry.
+**
+**
+** Relationship between ConditionalWeakTable and Dictionary:
+**
+** ConditionalWeakTable mirrors the form and functionality
+** of the IDictionary interface for the sake of api consistency.
+**
+** Unlike Dictionary, ConditionalWeakTable is fully thread-safe
+** and requires no additional locking to be done by callers.
+**
+** ConditionalWeakTable defines equality as Object.ReferenceEquals().
+** ConditionalWeakTable does not invoke GetHashCode() overrides.
+**
+** It is not intended to be a general purpose collection
+** and it does not formally implement IDictionary or
+** expose the full public surface area.
+**
+**
+**
+** Thread safety guarantees:
+**
+** ConditionalWeakTable is fully thread-safe and requires no
+** additional locking to be done by callers.
+**
+**
+** OOM guarantees:
+**
+** Will not corrupt unmanaged handle table on OOM. No guarantees
+** about managed weak table consistency. Native handles reclamation
+** may be delayed until appdomain shutdown.
+===========================================================*/
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Runtime.Versioning;
+ using System.Runtime.InteropServices;
+
+
+ #region ConditionalWeakTable
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public sealed class ConditionalWeakTable<TKey, TValue>
+ where TKey : class
+ where TValue : class
+ {
+
+ #region Constructors
+ [System.Security.SecuritySafeCritical]
+ public ConditionalWeakTable()
+ {
+ _buckets = Array.Empty<int>();
+ _entries = Array.Empty<Entry>();
+ _freeList = -1;
+ _lock = new Object();
+
+ Resize(); // Resize at once (so won't need "if initialized" checks all over)
+ }
+ #endregion
+
+ #region Public Members
+ //--------------------------------------------------------------------------------------------
+ // key: key of the value to find. Cannot be null.
+ // value: if the key is found, contains the value associated with the key upon method return.
+ // if the key is not found, contains default(TValue).
+ //
+ // Method returns "true" if key was found, "false" otherwise.
+ //
+ // Note: The key may get garbaged collected during the TryGetValue operation. If so, TryGetValue
+ // may at its discretion, return "false" and set "value" to the default (as if the key was not present.)
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ if (key == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+ lock(_lock)
+ {
+ VerifyIntegrity();
+ return TryGetValueWorker(key, out value);
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // key: key to add. May not be null.
+ // value: value to associate with key.
+ //
+ // If the key is already entered into the dictionary, this method throws an exception.
+ //
+ // Note: The key may get garbage collected during the Add() operation. If so, Add()
+ // has the right to consider any prior entries successfully removed and add a new entry without
+ // throwing an exception.
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ public void Add(TKey key, TValue value)
+ {
+ if (key == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ lock(_lock)
+ {
+ VerifyIntegrity();
+ _invalid = true;
+
+ int entryIndex = FindEntry(key);
+ if (entryIndex != -1)
+ {
+ _invalid = false;
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
+ }
+
+ CreateEntry(key, value);
+ _invalid = false;
+ }
+
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // key: key to remove. May not be null.
+ //
+ // Returns true if the key is found and removed. Returns false if the key was not in the dictionary.
+ //
+ // Note: The key may get garbage collected during the Remove() operation. If so,
+ // Remove() will not fail or throw, however, the return value can be either true or false
+ // depending on the race condition.
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ public bool Remove(TKey key)
+ {
+ if (key == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ }
+
+ lock(_lock)
+ {
+ VerifyIntegrity();
+ _invalid = true;
+
+ int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
+ int bucket = hashCode % _buckets.Length;
+ int last = -1;
+ for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
+ {
+ if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key)
+ {
+ if (last == -1)
+ {
+ _buckets[bucket] = _entries[entriesIndex].next;
+ }
+ else
+ {
+ _entries[last].next = _entries[entriesIndex].next;
+ }
+
+ _entries[entriesIndex].depHnd.Free();
+ _entries[entriesIndex].next = _freeList;
+
+ _freeList = entriesIndex;
+
+ _invalid = false;
+ return true;
+
+ }
+ last = entriesIndex;
+ }
+ _invalid = false;
+ return false;
+ }
+ }
+
+
+ //--------------------------------------------------------------------------------------------
+ // key: key of the value to find. Cannot be null.
+ // createValueCallback: callback that creates value for key. Cannot be null.
+ //
+ // Atomically tests if key exists in table. If so, returns corresponding value. If not,
+ // invokes createValueCallback() passing it the key. The returned value is bound to the key in the table
+ // and returned as the result of GetValue().
+ //
+ // If multiple threads try to initialize the same key, the table may invoke createValueCallback
+ // multiple times with the same key. Exactly one of these calls will succeed and the returned
+ // value of that call will be the one added to the table and returned by all the racing GetValue() calls.
+ //
+ // This rule permits the table to invoke createValueCallback outside the internal table lock
+ // to prevent deadlocks.
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ public TValue GetValue(TKey key, CreateValueCallback createValueCallback)
+ {
+ // Our call to TryGetValue() validates key so no need for us to.
+ //
+ // if (key == null)
+ // {
+ // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
+ // }
+
+ if (createValueCallback == null)
+ {
+ throw new ArgumentNullException("createValueCallback");
+ }
+
+ TValue existingValue;
+ if (TryGetValue(key, out existingValue))
+ {
+ return existingValue;
+ }
+
+ // If we got here, the key is not currently in table. Invoke the callback (outside the lock)
+ // to generate the new value for the key.
+ TValue newValue = createValueCallback(key);
+
+ lock(_lock)
+ {
+ VerifyIntegrity();
+ _invalid = true;
+
+ // Now that we've retaken the lock, must recheck in case there was a race condition to add the key.
+ if (TryGetValueWorker(key, out existingValue))
+ {
+ _invalid = false;
+ return existingValue;
+ }
+ else
+ {
+ CreateEntry(key, newValue);
+ _invalid = false;
+ return newValue;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // key: key of the value to find. Cannot be null.
+ //
+ // Helper method to call GetValue without passing a creation delegate. Uses Activator.CreateInstance
+ // to create new instances as needed. If TValue does not have a default constructor, this will
+ // throw.
+ //--------------------------------------------------------------------------------------------
+ public TValue GetOrCreateValue(TKey key)
+ {
+ return GetValue(key, k => Activator.CreateInstance<TValue>());
+ }
+
+ public delegate TValue CreateValueCallback(TKey key);
+
+ #endregion
+
+ #region internal members
+
+ //--------------------------------------------------------------------------------------------
+ // Find a key that equals (value equality) with the given key - don't use in perf critical path
+ // Note that it calls out to Object.Equals which may calls the override version of Equals
+ // and that may take locks and leads to deadlock
+ // Currently it is only used by WinRT event code and you should only use this function
+ // if you know for sure that either you won't run into dead locks or you need to live with the
+ // possiblity
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ [FriendAccessAllowed]
+ internal TKey FindEquivalentKeyUnsafe(TKey key, out TValue value)
+ {
+ lock (_lock)
+ {
+ for (int bucket = 0; bucket < _buckets.Length; ++bucket)
+ {
+ for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
+ {
+ object thisKey, thisValue;
+ _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out thisKey, out thisValue);
+ if (Object.Equals(thisKey, key))
+ {
+ value = (TValue) thisValue;
+ return (TKey) thisKey;
+ }
+ }
+ }
+ }
+
+ value = default(TValue);
+ return null;
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // Returns a collection of keys - don't use in perf critical path
+ //--------------------------------------------------------------------------------------------
+ internal ICollection<TKey> Keys
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ List<TKey> list = new List<TKey>();
+ lock (_lock)
+ {
+ for (int bucket = 0; bucket < _buckets.Length; ++bucket)
+ {
+ for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
+ {
+ TKey thisKey = (TKey) _entries[entriesIndex].depHnd.GetPrimary();
+ if (thisKey != null)
+ {
+ list.Add(thisKey);
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // Returns a collection of values - don't use in perf critical path
+ //--------------------------------------------------------------------------------------------
+ internal ICollection<TValue> Values
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ List<TValue> list = new List<TValue>();
+ lock (_lock)
+ {
+ for (int bucket = 0; bucket < _buckets.Length; ++bucket)
+ {
+ for (int entriesIndex = _buckets[bucket]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
+ {
+ Object primary = null;
+ Object secondary = null;
+
+ _entries[entriesIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary);
+
+ // Now that we've secured a strong reference to the secondary, must check the primary again
+ // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an
+ // expired key as a live key with a null value.)
+ if (primary != null)
+ {
+ list.Add((TValue)secondary);
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+ }
+
+ //--------------------------------------------------------------------------------------------
+ // Clear all the key/value pairs
+ //--------------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ internal void Clear()
+ {
+ lock (_lock)
+ {
+ // Clear the buckets
+ for (int bucketIndex = 0; bucketIndex < _buckets.Length; bucketIndex++)
+ {
+ _buckets[bucketIndex] = -1;
+ }
+
+ // Clear the entries and link them backwards together as part of free list
+ int entriesIndex;
+ for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ {
+ if (_entries[entriesIndex].depHnd.IsAllocated)
+ {
+ _entries[entriesIndex].depHnd.Free();
+ }
+
+ // Link back wards as free list
+ _entries[entriesIndex].next = entriesIndex - 1;
+ }
+
+ _freeList = entriesIndex - 1;
+ }
+ }
+
+ #endregion
+
+ #region Private Members
+ [System.Security.SecurityCritical]
+ //----------------------------------------------------------------------------------------
+ // Worker for finding a key/value pair
+ //
+ // Preconditions:
+ // Must hold _lock.
+ // Key already validated as non-null
+ //----------------------------------------------------------------------------------------
+ private bool TryGetValueWorker(TKey key, out TValue value)
+ {
+ int entryIndex = FindEntry(key);
+ if (entryIndex != -1)
+ {
+ Object primary = null;
+ Object secondary = null;
+ _entries[entryIndex].depHnd.GetPrimaryAndSecondary(out primary, out secondary);
+ // Now that we've secured a strong reference to the secondary, must check the primary again
+ // to ensure it didn't expire (otherwise, we open a race condition where TryGetValue misreports an
+ // expired key as a live key with a null value.)
+ if (primary != null)
+ {
+ value = (TValue)secondary;
+ return true;
+ }
+ }
+
+ value = default(TValue);
+ return false;
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Worker for adding a new key/value pair.
+ //
+ // Preconditions:
+ // Must hold _lock.
+ // Key already validated as non-null and not already in table.
+ //----------------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ private void CreateEntry(TKey key, TValue value)
+ {
+ if (_freeList == -1)
+ {
+ Resize();
+ }
+
+ int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
+ int bucket = hashCode % _buckets.Length;
+
+ int newEntry = _freeList;
+ _freeList = _entries[newEntry].next;
+
+ _entries[newEntry].hashCode = hashCode;
+ _entries[newEntry].depHnd = new DependentHandle(key, value);
+ _entries[newEntry].next = _buckets[bucket];
+
+ _buckets[bucket] = newEntry;
+
+ }
+
+ //----------------------------------------------------------------------------------------
+ // This does two things: resize and scrub expired keys off bucket lists.
+ //
+ // Precondition:
+ // Must hold _lock.
+ //
+ // Postcondition:
+ // _freeList is non-empty on exit.
+ //----------------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ private void Resize()
+ {
+ // Start by assuming we won't resize.
+ int newSize = _buckets.Length;
+
+ // If any expired keys exist, we won't resize.
+ bool hasExpiredEntries = false;
+ int entriesIndex;
+ for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ {
+ if ( _entries[entriesIndex].depHnd.IsAllocated && _entries[entriesIndex].depHnd.GetPrimary() == null)
+ {
+ hasExpiredEntries = true;
+ break;
+ }
+ }
+
+ if (!hasExpiredEntries)
+ {
+ newSize = System.Collections.HashHelpers.GetPrime(_buckets.Length == 0 ? _initialCapacity + 1 : _buckets.Length * 2);
+ }
+
+
+ // Reallocate both buckets and entries and rebuild the bucket and freelists from scratch.
+ // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket.
+ int newFreeList = -1;
+ int[] newBuckets = new int[newSize];
+ for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++)
+ {
+ newBuckets[bucketIndex] = -1;
+ }
+ Entry[] newEntries = new Entry[newSize];
+
+ // Migrate existing entries to the new table.
+ for (entriesIndex = 0; entriesIndex < _entries.Length; entriesIndex++)
+ {
+ DependentHandle depHnd = _entries[entriesIndex].depHnd;
+ if (depHnd.IsAllocated && depHnd.GetPrimary() != null)
+ {
+ // Entry is used and has not expired. Link it into the appropriate bucket list.
+ int bucket = _entries[entriesIndex].hashCode % newSize;
+ newEntries[entriesIndex].depHnd = depHnd;
+ newEntries[entriesIndex].hashCode = _entries[entriesIndex].hashCode;
+ newEntries[entriesIndex].next = newBuckets[bucket];
+ newBuckets[bucket] = entriesIndex;
+ }
+ else
+ {
+ // Entry has either expired or was on the freelist to begin with. Either way
+ // insert it on the new freelist.
+ _entries[entriesIndex].depHnd.Free();
+ newEntries[entriesIndex].depHnd = new DependentHandle();
+ newEntries[entriesIndex].next = newFreeList;
+ newFreeList = entriesIndex;
+ }
+ }
+
+ // Add remaining entries to freelist.
+ while (entriesIndex != newEntries.Length)
+ {
+ newEntries[entriesIndex].depHnd = new DependentHandle();
+ newEntries[entriesIndex].next = newFreeList;
+ newFreeList = entriesIndex;
+ entriesIndex++;
+ }
+
+ _buckets = newBuckets;
+ _entries = newEntries;
+ _freeList = newFreeList;
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Returns -1 if not found (if key expires during FindEntry, this can be treated as "not found.")
+ //
+ // Preconditions:
+ // Must hold _lock.
+ // Key already validated as non-null.
+ //----------------------------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ private int FindEntry(TKey key)
+ {
+ int hashCode = RuntimeHelpers.GetHashCode(key) & Int32.MaxValue;
+ for (int entriesIndex = _buckets[hashCode % _buckets.Length]; entriesIndex != -1; entriesIndex = _entries[entriesIndex].next)
+ {
+ if (_entries[entriesIndex].hashCode == hashCode && _entries[entriesIndex].depHnd.GetPrimary() == key)
+ {
+ return entriesIndex;
+ }
+ }
+ return -1;
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Precondition:
+ // Must hold _lock.
+ //----------------------------------------------------------------------------------------
+ private void VerifyIntegrity()
+ {
+ if (_invalid)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("CollectionCorrupted"));
+ }
+ }
+
+ //----------------------------------------------------------------------------------------
+ // Finalizer.
+ //----------------------------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical]
+ ~ConditionalWeakTable()
+ {
+
+ // We're just freeing per-appdomain unmanaged handles here. If we're already shutting down the AD,
+ // don't bother.
+ //
+ // (Despite its name, Environment.HasShutdownStart also returns true if the current AD is finalizing.)
+ if (Environment.HasShutdownStarted)
+ {
+ return;
+ }
+
+ if (_lock != null)
+ {
+ lock(_lock)
+ {
+ if (_invalid)
+ {
+ return;
+ }
+ Entry[] entries = _entries;
+
+ // Make sure anyone sneaking into the table post-resurrection
+ // gets booted before they can damage the native handle table.
+ _invalid = true;
+ _entries = null;
+ _buckets = null;
+
+ for (int entriesIndex = 0; entriesIndex < entries.Length; entriesIndex++)
+ {
+ entries[entriesIndex].depHnd.Free();
+ }
+ }
+ }
+ }
+ #endregion
+
+ #region Private Data Members
+ //--------------------------------------------------------------------------------------------
+ // Entry can be in one of three states:
+ //
+ // - Linked into the freeList (_freeList points to first entry)
+ // depHnd.IsAllocated == false
+ // hashCode == <dontcare>
+ // next links to next Entry on freelist)
+ //
+ // - Used with live key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry)
+ // depHnd.IsAllocated == true, depHnd.GetPrimary() != null
+ // hashCode == RuntimeHelpers.GetHashCode(depHnd.GetPrimary()) & Int32.MaxValue
+ // next links to next Entry in bucket.
+ //
+ // - Used with dead key (linked into a bucket list where _buckets[hashCode % _buckets.Length] points to first entry)
+ // depHnd.IsAllocated == true, depHnd.GetPrimary() == null
+ // hashCode == <notcare>
+ // next links to next Entry in bucket.
+ //
+ // The only difference between "used with live key" and "used with dead key" is that
+ // depHnd.GetPrimary() returns null. The transition from "used with live key" to "used with dead key"
+ // happens asynchronously as a result of normal garbage collection. The dictionary itself
+ // receives no notification when this happens.
+ //
+ // When the dictionary grows the _entries table, it scours it for expired keys and puts those
+ // entries back on the freelist.
+ //--------------------------------------------------------------------------------------------
+ private struct Entry
+ {
+ public DependentHandle depHnd; // Holds key and value using a weak reference for the key and a strong reference
+ // for the value that is traversed only if the key is reachable without going through the value.
+ public int hashCode; // Cached copy of key's hashcode
+ public int next; // Index of next entry, -1 if last
+ }
+
+ private int[] _buckets; // _buckets[hashcode & _buckets.Length] contains index of first entry in bucket (-1 if empty)
+ private Entry[] _entries;
+ private int _freeList; // -1 = empty, else index of first unused Entry
+ private const int _initialCapacity = 5;
+ private readonly Object _lock; // this could be a ReaderWriterLock but CoreCLR does not support RWLocks.
+ private bool _invalid; // flag detects if OOM or other background exception threw us out of the lock.
+ #endregion
+ }
+ #endregion
+
+
+
+
+ #region DependentHandle
+ //=========================================================================================
+ // This struct collects all operations on native DependentHandles. The DependentHandle
+ // merely wraps an IntPtr so this struct serves mainly as a "managed typedef."
+ //
+ // DependentHandles exist in one of two states:
+ //
+ // IsAllocated == false
+ // No actual handle is allocated underneath. Illegal to call GetPrimary
+ // or GetPrimaryAndSecondary(). Ok to call Free().
+ //
+ // Initializing a DependentHandle using the nullary ctor creates a DependentHandle
+ // that's in the !IsAllocated state.
+ // (! Right now, we get this guarantee for free because (IntPtr)0 == NULL unmanaged handle.
+ // ! If that assertion ever becomes false, we'll have to add an _isAllocated field
+ // ! to compensate.)
+ //
+ //
+ // IsAllocated == true
+ // There's a handle allocated underneath. You must call Free() on this eventually
+ // or you cause a native handle table leak.
+ //
+ // This struct intentionally does no self-synchronization. It's up to the caller to
+ // to use DependentHandles in a thread-safe way.
+ //=========================================================================================
+ [ComVisible(false)]
+ struct DependentHandle
+ {
+ #region Constructors
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #else
+ [System.Security.SecurityCritical]
+ #endif
+ public DependentHandle(Object primary, Object secondary)
+ {
+ IntPtr handle = (IntPtr)0;
+ nInitialize(primary, secondary, out handle);
+ // no need to check for null result: nInitialize expected to throw OOM.
+ _handle = handle;
+ }
+ #endregion
+
+ #region Public Members
+ public bool IsAllocated
+ {
+ get
+ {
+ return _handle != (IntPtr)0;
+ }
+ }
+
+ // Getting the secondary object is more expensive than getting the first so
+ // we provide a separate primary-only accessor for those times we only want the
+ // primary.
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #else
+ [System.Security.SecurityCritical]
+ #endif
+ public Object GetPrimary()
+ {
+ Object primary;
+ nGetPrimary(_handle, out primary);
+ return primary;
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #else
+ [System.Security.SecurityCritical]
+ #endif
+ public void GetPrimaryAndSecondary(out Object primary, out Object secondary)
+ {
+ nGetPrimaryAndSecondary(_handle, out primary, out secondary);
+ }
+
+ //----------------------------------------------------------------------
+ // Forces dependentHandle back to non-allocated state (if not already there)
+ // and frees the handle if needed.
+ //----------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ public void Free()
+ {
+ if (_handle != (IntPtr)0)
+ {
+ IntPtr handle = _handle;
+ _handle = (IntPtr)0;
+ nFree(handle);
+ }
+ }
+ #endregion
+
+ #region Private Members
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nInitialize(Object primary, Object secondary, out IntPtr dependentHandle);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nGetPrimary(IntPtr dependentHandle, out Object primary);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nGetPrimaryAndSecondary(IntPtr dependentHandle, out Object primary, out Object secondary);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nFree(IntPtr dependentHandle);
+ #endregion
+
+ #region Private Data Member
+ private IntPtr _handle;
+ #endregion
+
+ } // struct DependentHandle
+ #endregion
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs
new file mode 100644
index 0000000000..c912095bda
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/CustomConstantAttribute.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using System.Collections.Generic;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class CustomConstantAttribute : Attribute
+ {
+ public abstract Object Value { get; }
+
+ internal static object GetRawConstant(CustomAttributeData attr)
+ {
+ foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments)
+ {
+ if (namedArgument.MemberInfo.Name.Equals("Value"))
+ return namedArgument.TypedValue.Value;
+ }
+
+ // Return DBNull to indicate that no default value is available.
+ // Not to be confused with a null return which indicates a null default value.
+ return DBNull.Value;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
new file mode 100644
index 0000000000..4362aa84a1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DateTimeConstantAttribute.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DateTimeConstantAttribute : CustomConstantAttribute
+ {
+ public DateTimeConstantAttribute(long ticks)
+ {
+ date = new System.DateTime(ticks);
+ }
+
+ public override Object Value
+ {
+ get
+ {
+ return date;
+ }
+ }
+
+ internal static DateTime GetRawDateTimeConstant(CustomAttributeData attr)
+ {
+ Contract.Requires(attr.Constructor.DeclaringType == typeof(DateTimeConstantAttribute));
+ Contract.Requires(attr.ConstructorArguments.Count == 1);
+
+ foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments)
+ {
+ if (namedArgument.MemberInfo.Name.Equals("Value"))
+ {
+ return new DateTime((long)namedArgument.TypedValue.Value);
+ }
+ }
+
+ // Look at the ctor argument if the "Value" property was not explicitly defined.
+ return new DateTime((long)attr.ConstructorArguments[0].Value);
+ }
+
+ private System.DateTime date;
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
new file mode 100644
index 0000000000..39a4c86b72
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecimalConstantAttribute.cs
@@ -0,0 +1,98 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// Note: If you add a new ctor overloads you need to update ParameterInfo.RawDefaultValue
+
+using System.Reflection;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DecimalConstantAttribute : Attribute
+ {
+ [CLSCompliant(false)]
+ public DecimalConstantAttribute(
+ byte scale,
+ byte sign,
+ uint hi,
+ uint mid,
+ uint low
+ )
+ {
+ dec = new System.Decimal((int) low, (int)mid, (int)hi, (sign != 0), scale);
+ }
+
+ public DecimalConstantAttribute(
+ byte scale,
+ byte sign,
+ int hi,
+ int mid,
+ int low
+ )
+ {
+ dec = new System.Decimal(low, mid, hi, (sign != 0), scale);
+ }
+
+
+ public System.Decimal Value
+ {
+ get
+ {
+ return dec;
+ }
+ }
+
+ internal static Decimal GetRawDecimalConstant(CustomAttributeData attr)
+ {
+ Contract.Requires(attr.Constructor.DeclaringType == typeof(DecimalConstantAttribute));
+
+ foreach (CustomAttributeNamedArgument namedArgument in attr.NamedArguments)
+ {
+ if (namedArgument.MemberInfo.Name.Equals("Value"))
+ {
+ // This is not possible because Decimal cannot be represented directly in the metadata.
+ Contract.Assert(false, "Decimal cannot be represented directly in the metadata.");
+ return (Decimal)namedArgument.TypedValue.Value;
+ }
+ }
+
+ ParameterInfo[] parameters = attr.Constructor.GetParameters();
+ Contract.Assert(parameters.Length == 5);
+
+ System.Collections.Generic.IList<CustomAttributeTypedArgument> args = attr.ConstructorArguments;
+ Contract.Assert(args.Count == 5);
+
+ if (parameters[2].ParameterType == typeof(uint))
+ {
+ // DecimalConstantAttribute(byte scale, byte sign, uint hi, uint mid, uint low)
+ int low = (int)(UInt32)args[4].Value;
+ int mid = (int)(UInt32)args[3].Value;
+ int hi = (int)(UInt32)args[2].Value;
+ byte sign = (byte)args[1].Value;
+ byte scale = (byte)args[0].Value;
+
+ return new System.Decimal(low, mid, hi, (sign != 0), scale);
+ }
+ else
+ {
+ // DecimalConstantAttribute(byte scale, byte sign, int hi, int mid, int low)
+ int low = (int)args[4].Value;
+ int mid = (int)args[3].Value;
+ int hi = (int)args[2].Value;
+ byte sign = (byte)args[1].Value;
+ byte scale = (byte)args[0].Value;
+
+ return new System.Decimal(low, mid, hi, (sign != 0), scale);
+ }
+ }
+
+ private System.Decimal dec;
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs
new file mode 100644
index 0000000000..75558d4e7e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DecoratedNameAttribute.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.All),
+ ComVisible(false)]
+ internal sealed class DecoratedNameAttribute : Attribute
+ {
+ public DecoratedNameAttribute(string decoratedName)
+ {}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs
new file mode 100644
index 0000000000..46dae10fdd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DisablePrivateReflectionAttribute.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false, Inherited=false)]
+ public sealed class DisablePrivateReflectionAttribute : Attribute
+ {
+ public DisablePrivateReflectionAttribute() {}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs
new file mode 100644
index 0000000000..303151f576
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/DiscardableAttribute.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.CompilerServices {
+
+ using System;
+
+ // Custom attribute to indicating a TypeDef is a discardable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class DiscardableAttribute : Attribute
+ {
+ public DiscardableAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs
new file mode 100644
index 0000000000..6ec8fa04f5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ExtensionAttribute.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Indicates that a method is an extension method, or that a class or assembly contains extension methods.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
+ public sealed class ExtensionAttribute : Attribute { }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs
new file mode 100644
index 0000000000..679e304ad1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/FixedAddressValueTypeAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Field)]
+ sealed public class FixedAddressValueTypeAttribute : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs
new file mode 100644
index 0000000000..a7d01b12c4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/FixedBufferAttribute.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: Used by a compiler for generating value types
+** in-place within other value types containing a certain
+** number of elements of the given (primitive) type. Somewhat
+** similar to P/Invoke's ByValTStr attribute.
+** Used by C# with this syntax: "fixed int buffer[10];"
+**
+===========================================================*/
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Field, Inherited=false)]
+ public sealed class FixedBufferAttribute : Attribute
+ {
+ private Type elementType;
+ private int length;
+
+ public FixedBufferAttribute(Type elementType, int length)
+ {
+ this.elementType = elementType;
+ this.length = length;
+ }
+
+ public Type ElementType {
+ get {
+ return elementType;
+ }
+ }
+
+ public int Length {
+ get {
+ return length;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs
new file mode 100644
index 0000000000..aee3bc2230
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/FormattableStringFactory.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: FormattableStringFactory
+**
+**
+** Purpose: implementation of the FormattableStringFactory
+** class.
+**
+===========================================================*/
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// A factory type used by compilers to create instances of the type <see cref="FormattableString"/>.
+ /// </summary>
+ public static class FormattableStringFactory
+ {
+ /// <summary>
+ /// Create a <see cref="FormattableString"/> from a composite format string and object
+ /// array containing zero or more objects to format.
+ /// </summary>
+ public static FormattableString Create(string format, params object[] arguments)
+ {
+ if (format == null)
+ {
+ throw new ArgumentNullException("format");
+ }
+
+ if (arguments == null)
+ {
+ throw new ArgumentNullException("arguments");
+ }
+
+ return new ConcreteFormattableString(format, arguments);
+ }
+
+ private sealed class ConcreteFormattableString : FormattableString
+ {
+ private readonly string _format;
+ private readonly object[] _arguments;
+
+ internal ConcreteFormattableString(string format, object[] arguments)
+ {
+ _format = format;
+ _arguments = arguments;
+ }
+
+ public override string Format { get { return _format; } }
+ public override object[] GetArguments() { return _arguments; }
+ public override int ArgumentCount { get { return _arguments.Length; } }
+ public override object GetArgument(int index) { return _arguments[index]; }
+ public override string ToString(IFormatProvider formatProvider) { return string.Format(formatProvider, _format, _arguments); }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs
new file mode 100644
index 0000000000..944a2868f2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/HasCopySemanticsAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+[Serializable]
+[AttributeUsage(AttributeTargets.Struct)]
+ public sealed class HasCopySemanticsAttribute : Attribute
+ {
+ public HasCopySemanticsAttribute()
+ {}
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs
new file mode 100644
index 0000000000..7fb7ea5395
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IAsyncStateMachine.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Represents state machines generated for asynchronous methods.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Represents state machines generated for asynchronous methods.
+ /// This type is intended for compiler use only.
+ /// </summary>
+ public interface IAsyncStateMachine
+ {
+ /// <summary>Moves the state machine to its next state.</summary>
+ void MoveNext();
+ /// <summary>Configures the state machine with a heap-allocated replica.</summary>
+ /// <param name="stateMachine">The heap-allocated replica.</param>
+ void SetStateMachine(IAsyncStateMachine stateMachine);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs
new file mode 100644
index 0000000000..7ba9434575
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ICastable.cs
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+
+//
+// Support for dynamic interface casting. Specifically implementing this interface on a type will allow the
+// type to support interfaces (for the purposes of casting and interface dispatch) that do not appear in its
+// interface map.
+//
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ public interface ICastable
+ {
+ // This is called if casting this object to the given interface type would otherwise fail. Casting
+ // here means the IL isinst and castclass instructions in the case where they are given an interface
+ // type as the target type.
+ //
+ // A return value of true indicates the cast is valid.
+ //
+ // If false is returned when this is called as part of a castclass then the usual InvalidCastException
+ // will be thrown unless an alternate exception is assigned to the castError output parameter. This
+ // parameter is ignored on successful casts or during the evaluation of an isinst (which returns null
+ // rather than throwing on error).
+ //
+ // No exception should be thrown from this method (it will cause unpredictable effects, including the
+ // possibility of an immediate failfast).
+ //
+ // The results of this call are not cached, so it is advisable to provide a performant implementation.
+ //
+ // The results of this call should be invariant for the same class, interface type pair. That is
+ // because this is the only guard placed before an interface invocation at runtime. If a type decides
+ // it no longer wants to implement a given interface it has no way to synchronize with callers that
+ // have already cached this relationship and can invoke directly via the interface pointer.
+ bool IsInstanceOfInterface(RuntimeTypeHandle interfaceType, out Exception castError);
+
+ // This is called as part of the interface dispatch mechanism when the dispatcher logic cannot find
+ // the given interface type in the interface map of this object.
+ //
+ // It allows the implementor to return an alternate class type which does implement the interface. The
+ // interface lookup shall be performed again on this type (failure to find the interface this time
+ // resulting in a fail fast) and the corresponding implemented method on that class called instead.
+ //
+ // Naturally, since the call is dispatched to a method on a class which does not match the type of the
+ // this pointer, extreme care must be taken in the implementation of the interface methods of this
+ // surrogate type.
+ //
+ // No exception should be thrown from this method (it will cause unpredictable effects, including the
+ // possibility of an immediate failfast).
+ //
+ // There is no error path defined here. By construction all interface dispatches will already have
+ // been verified via the castclass/isinst mechanism (and thus a call to IsInstanceOfInterface above)
+ // so this method is expected to succeed in all cases. The contract for interface dispatch does not
+ // include any errors from the infrastructure, of which this is a part.
+ //
+ // The results of this lookup are cached so computation of the result is not as perf-sensitive as
+ // IsInstanceOfInterface.
+ RuntimeTypeHandle GetImplType(RuntimeTypeHandle interfaceType);
+ }
+
+ /// <summary>
+ /// Helpers that allows VM to call into ICastable methods without having to deal with RuntimeTypeHandle.
+ /// RuntimeTypeHandle is a struct and is always passed in stack in x86, which our VM call helpers don't
+ /// particularly like.
+ /// </summary>
+ class ICastableHelpers
+ {
+ internal static bool IsInstanceOfInterface(ICastable castable, RuntimeType type, out Exception castError)
+ {
+ return castable.IsInstanceOfInterface(new RuntimeTypeHandle(type), out castError);
+ }
+
+ internal static RuntimeType GetImplType(ICastable castable, RuntimeType interfaceType)
+ {
+ return castable.GetImplType(new RuntimeTypeHandle(interfaceType)).GetRuntimeType();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs
new file mode 100644
index 0000000000..d6dfcbbbb9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IDispatchConstantAttribute.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+[Serializable]
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class IDispatchConstantAttribute : CustomConstantAttribute
+ {
+ public IDispatchConstantAttribute()
+ {
+ }
+
+ public override Object Value
+ {
+ get
+ {
+ return new DispatchWrapper(null);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs
new file mode 100644
index 0000000000..872a79b72b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/INotifyCompletion.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
+//
+//
+//
+// Interfaces used to represent instances that notify listeners of their completion via continuations.
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+using System;
+using System.Security;
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>
+ /// Represents an operation that will schedule continuations when the operation completes.
+ /// </summary>
+ public interface INotifyCompletion
+ {
+ /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary>
+ /// <param name="continuation">The action to invoke when the operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ void OnCompleted(Action continuation);
+ }
+
+ /// <summary>
+ /// Represents an awaiter used to schedule continuations when an await operation completes.
+ /// </summary>
+ public interface ICriticalNotifyCompletion : INotifyCompletion
+ {
+ /// <summary>Schedules the continuation action to be invoked when the instance completes.</summary>
+ /// <param name="continuation">The action to invoke when the operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <remarks>Unlike OnCompleted, UnsafeOnCompleted need not propagate ExecutionContext information.</remarks>
+ [SecurityCritical]
+ void UnsafeOnCompleted(Action continuation);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs
new file mode 100644
index 0000000000..f8717cff52
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IUnknownConstantAttribute.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+[Serializable]
+[AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class IUnknownConstantAttribute : CustomConstantAttribute
+ {
+ public IUnknownConstantAttribute()
+ {
+ }
+
+ public override Object Value
+ {
+ get
+ {
+ return new UnknownWrapper(null);
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs
new file mode 100644
index 0000000000..0323fe0cf6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IndexerNameAttribute.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Property, Inherited = true)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class IndexerNameAttribute: Attribute
+ {
+ public IndexerNameAttribute(String indexerName)
+ {}
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs
new file mode 100644
index 0000000000..ee7807a5dd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/InternalsVisibleToAttribute.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)]
+ public sealed class InternalsVisibleToAttribute : Attribute
+ {
+ private string _assemblyName;
+ private bool _allInternalsVisible = true;
+
+ public InternalsVisibleToAttribute(string assemblyName)
+ {
+ this._assemblyName = assemblyName;
+ }
+
+ public string AssemblyName
+ {
+ get
+ {
+ return _assemblyName;
+ }
+ }
+
+ public bool AllInternalsVisible
+ {
+ get { return _allInternalsVisible; }
+ set { _allInternalsVisible = value; }
+ }
+ }
+
+ /// <summary>
+ /// If AllInternalsVisible is not true for a friend assembly, the FriendAccessAllowed attribute
+ /// indicates which internals are shared with that friend assembly.
+ /// </summary>
+ [AttributeUsage(AttributeTargets.Class |
+ AttributeTargets.Constructor |
+ AttributeTargets.Enum |
+ AttributeTargets.Event |
+ AttributeTargets.Field |
+ AttributeTargets.Interface |
+ AttributeTargets.Method |
+ AttributeTargets.Property |
+ AttributeTargets.Struct,
+ AllowMultiple = false,
+ Inherited = false)]
+ [FriendAccessAllowed]
+ internal sealed class FriendAccessAllowedAttribute : Attribute {
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs
new file mode 100644
index 0000000000..8b6691c09d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsBoxed.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the modified reference type is a boxed valuetype
+ public static class IsBoxed
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs
new file mode 100644
index 0000000000..d16a853597
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsByValue.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the modified method argument is passed by value
+ public static class IsByValue
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs
new file mode 100644
index 0000000000..210e5997a7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsConst.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the modified type is const (i.e. has a const modifier)
+ public static class IsConst
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs
new file mode 100644
index 0000000000..ee40ee7b02
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsCopyConstructed.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static class IsCopyConstructed
+ {}
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs
new file mode 100644
index 0000000000..480a62175d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsExplicitlyDereferenced.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Consider the following C++ method prototypes:
+ // 1) int foo(int ^arg);
+ // 2) int foo(int &arg);
+ //
+ // Both of these methods will have a .NET type signature that looks the
+ // same, but when importing a method from a metadata scope, the compiler
+ // needs to know what the calling syntax should be. This modopt and its
+ // partner "IsImplicitlyDereferenced" disambiguate reference versus
+ // pointer arguments.
+ //
+ // Indicates that the modified GC reference represents a pointer in a
+ // method signature.
+ public static class IsExplicitlyDereferenced
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs
new file mode 100644
index 0000000000..ea81cb8ec5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsImplicitlyDereferenced.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Consider the following C++ method prototypes:
+ // 1) int foo(int ^arg);
+ // 2) int foo(int &arg);
+ //
+ // Both of these methods will have a .NET type signature that looks the
+ // same, but when importing a method from a metadata scope, the compiler
+ // needs to know what the calling syntax should be. This modopt and its
+ // partner "IsExplicitlyDereferenced" disambiguate reference versus
+ // pointer arguments.
+ //
+ // Indicates that the modified GC reference represents a reference in a
+ // method signature.
+ public static class IsImplicitlyDereferenced
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs
new file mode 100644
index 0000000000..013e50f3ea
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsJitIntrinsic.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the modified method is an intrinsic for which the JIT
+ // can perform special code generation.
+ public static class IsJitIntrinsic
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs
new file mode 100644
index 0000000000..e8bebfb2d3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsLong.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // The C++ standard indicates that a long is always 4-bytes, whereas the
+ // size of an integer is system dependent (not exceedign sizeof(long)).
+ // The CLR does not offer a mechanism for encoding this distinction,
+ // but it is critically important for maintaining language level type
+ // safety.
+ //
+ // Indicates that the modified integer is a standard C++ long.
+ // Could also be called IsAlternateIntegerType or something else.
+ public static class IsLong
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs
new file mode 100644
index 0000000000..e796d1a1e7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsPinned.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the modified instance is pinned in memory.
+ public static class IsPinned
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs
new file mode 100644
index 0000000000..e68f4d7751
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsSignUnspecifiedByte.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // C++ recognizes three char types: signed char, unsigned char, and char.
+ // When a char is neither signed nor unsigned, it is a char.
+ // This modopt indicates that the modified instance is a char.
+ //
+ // Any compiler could use this to indicate that the user has not specified
+ // Sign behavior for the given byte.
+ public static class IsSignUnspecifiedByte
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs
new file mode 100644
index 0000000000..dd85914b53
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsUdtReturn.cs
@@ -0,0 +1,11 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ // Indicates that the return type is a user defined type
+ public static class IsUdtReturn
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs
new file mode 100644
index 0000000000..ea2fe032c6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IsVolatile.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+[System.Runtime.InteropServices.ComVisible(true)]
+ public static class IsVolatile
+ {
+ // no instantiation, please!
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs
new file mode 100644
index 0000000000..4bb9b4eb8f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/IteratorStateMachineAttribute.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public sealed class IteratorStateMachineAttribute : StateMachineAttribute
+ {
+ public IteratorStateMachineAttribute(Type stateMachineType)
+ : base(stateMachineType)
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs
new file mode 100644
index 0000000000..d081d70070
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/MethodImplAttribute.cs
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices {
+
+ using System;
+ using System.Reflection;
+
+ // This Enum matchs the miImpl flags defined in corhdr.h. It is used to specify
+ // certain method properties.
+
+ [Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum MethodImplOptions
+ {
+ Unmanaged = System.Reflection.MethodImplAttributes.Unmanaged,
+ ForwardRef = System.Reflection.MethodImplAttributes.ForwardRef,
+ PreserveSig = System.Reflection.MethodImplAttributes.PreserveSig,
+ InternalCall = System.Reflection.MethodImplAttributes.InternalCall,
+ Synchronized = System.Reflection.MethodImplAttributes.Synchronized,
+ NoInlining = System.Reflection.MethodImplAttributes.NoInlining,
+ [System.Runtime.InteropServices.ComVisible(false)]
+ AggressiveInlining = System.Reflection.MethodImplAttributes.AggressiveInlining,
+ NoOptimization = System.Reflection.MethodImplAttributes.NoOptimization,
+ // **** If you add something, update internal MethodImplAttribute(MethodImplAttributes methodImplAttributes)! ****
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum MethodCodeType
+ {
+ IL = System.Reflection.MethodImplAttributes.IL,
+ Native = System.Reflection.MethodImplAttributes.Native,
+ /// <internalonly/>
+ OPTIL = System.Reflection.MethodImplAttributes.OPTIL,
+ Runtime = System.Reflection.MethodImplAttributes.Runtime
+ }
+
+ // Custom attribute to specify additional method properties.
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class MethodImplAttribute : Attribute
+ {
+ internal MethodImplOptions _val;
+ public MethodCodeType MethodCodeType;
+
+ internal MethodImplAttribute(MethodImplAttributes methodImplAttributes)
+ {
+ MethodImplOptions all =
+ MethodImplOptions.Unmanaged | MethodImplOptions.ForwardRef | MethodImplOptions.PreserveSig |
+ MethodImplOptions.InternalCall | MethodImplOptions.Synchronized |
+ MethodImplOptions.NoInlining | MethodImplOptions.AggressiveInlining |
+ MethodImplOptions.NoOptimization;
+ _val = ((MethodImplOptions)methodImplAttributes) & all;
+ }
+
+ public MethodImplAttribute(MethodImplOptions methodImplOptions)
+ {
+ _val = methodImplOptions;
+ }
+
+ public MethodImplAttribute(short value)
+ {
+ _val = (MethodImplOptions)value;
+ }
+
+ public MethodImplAttribute()
+ {
+ }
+
+ public MethodImplOptions Value { get {return _val;} }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs
new file mode 100644
index 0000000000..0d6c759d76
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/NativeCppClassAttribute.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices {
+[Serializable]
+[AttributeUsage(AttributeTargets.Struct, Inherited = true),
+ System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class NativeCppClassAttribute : Attribute
+ {
+ public NativeCppClassAttribute () {}
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
new file mode 100644
index 0000000000..d5e64a1177
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ReferenceAssemblyAttribute.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Attribute: ReferenceAssemblyAttribute
+**
+** Purpose: Identifies an assembly as being a "reference
+** assembly", meaning it contains public surface area but
+** no usable implementation. Reference assemblies
+** should be loadable for introspection, but not execution.
+**
+============================================================*/
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+ [Serializable]
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=false)]
+ public sealed class ReferenceAssemblyAttribute : Attribute
+ {
+ private String _description; // Maybe ".NET FX v4.0 SP1, partial trust"?
+
+ public ReferenceAssemblyAttribute()
+ {
+ }
+
+ public ReferenceAssemblyAttribute(String description)
+ {
+ _description = description;
+ }
+
+ public String Description
+ {
+ get { return _description; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs
new file mode 100644
index 0000000000..f363696ebd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RequiredAttributeAttribute.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+[Serializable]
+[AttributeUsage (AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface,
+ AllowMultiple=true, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class RequiredAttributeAttribute : Attribute
+ {
+ private Type requiredContract;
+
+ public RequiredAttributeAttribute (Type requiredContract)
+ {
+ this.requiredContract= requiredContract;
+ }
+ public Type RequiredContract
+ {
+ get { return this.requiredContract; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs
new file mode 100644
index 0000000000..40a9b7c568
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeCompatibilityAttribute.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+/*=============================================================================
+**
+**
+**
+** Purpose: Mark up the program to indicate various legacy or new opt-in behaviors.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.CompilerServices
+{
+
+ using System;
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Assembly, Inherited=false, AllowMultiple=false)]
+ public sealed class RuntimeCompatibilityAttribute : Attribute
+ {
+ // fields
+ private bool m_wrapNonExceptionThrows;
+
+ // constructors
+ public RuntimeCompatibilityAttribute() {
+ // legacy behavior is the default, and m_wrapNonExceptionThrows is implicitly
+ // false thanks to the CLR's guarantee of zeroed memory.
+ }
+
+ // properties
+
+ // If a non-CLSCompliant exception (i.e. one that doesn't derive from System.Exception) is
+ // thrown, should it be wrapped up in a System.Runtime.CompilerServices.RuntimeWrappedException
+ // instance when presented to catch handlers?
+ public bool WrapNonExceptionThrows {
+ get {
+ return m_wrapNonExceptionThrows;
+ }
+ set {
+ m_wrapNonExceptionThrows = value;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
new file mode 100644
index 0000000000..d20fe0bffd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -0,0 +1,248 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// RuntimeHelpers
+// This class defines a set of static methods that provide support for compilers.
+//
+//
+namespace System.Runtime.CompilerServices {
+
+ using System;
+ using System.Security;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ public static class RuntimeHelpers
+ {
+#if FEATURE_CORECLR
+ // Exposed here as a more appropriate place than on FormatterServices itself,
+ // which is a high level reflection heavy type.
+ public static Object GetUninitializedObject(Type type)
+ {
+ return FormatterServices.GetUninitializedObject(type);
+ }
+#endif // FEATURE_CORECLR
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void InitializeArray(Array array,RuntimeFieldHandle fldHandle);
+
+ // GetObjectValue is intended to allow value classes to be manipulated as 'Object'
+ // but have aliasing behavior of a value class. The intent is that you would use
+ // this function just before an assignment to a variable of type 'Object'. If the
+ // value being assigned is a mutable value class, then a shallow copy is returned
+ // (because value classes have copy semantics), but otherwise the object itself
+ // is returned.
+ //
+ // Note: VB calls this method when they're about to assign to an Object
+ // or pass it as a parameter. The goal is to make sure that boxed
+ // value types work identical to unboxed value types - ie, they get
+ // cloned when you pass them around, and are always passed by value.
+ // Of course, reference types are not cloned.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object GetObjectValue(Object obj);
+
+ // RunClassConstructor causes the class constructor for the given type to be triggered
+ // in the current domain. After this call returns, the class constructor is guaranteed to
+ // have at least been started by some thread. In the absence of class constructor
+ // deadlock conditions, the call is further guaranteed to have completed.
+ //
+ // This call will generate an exception if the specified class constructor threw an
+ // exception when it ran.
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _RunClassConstructor(RuntimeType type);
+
+ public static void RunClassConstructor(RuntimeTypeHandle type)
+ {
+ _RunClassConstructor(type.GetRuntimeType());
+ }
+
+ // RunModuleConstructor causes the module constructor for the given type to be triggered
+ // in the current domain. After this call returns, the module constructor is guaranteed to
+ // have at least been started by some thread. In the absence of module constructor
+ // deadlock conditions, the call is further guaranteed to have completed.
+ //
+ // This call will generate an exception if the specified module constructor threw an
+ // exception when it ran.
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _RunModuleConstructor(System.Reflection.RuntimeModule module);
+
+ public static void RunModuleConstructor(ModuleHandle module)
+ {
+ _RunModuleConstructor(module.GetRuntimeModule());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static unsafe extern void _PrepareMethod(IRuntimeMethodInfo method, IntPtr* pInstantiation, int cInstantiation);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern void _CompileMethod(IRuntimeMethodInfo method);
+
+ // Simple (instantiation not required) method.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void PrepareMethod(RuntimeMethodHandle method)
+ {
+ unsafe
+ {
+ _PrepareMethod(method.GetMethodInfo(), null, 0);
+ }
+ }
+
+ // Generic method or method with generic class with specific instantiation.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void PrepareMethod(RuntimeMethodHandle method, RuntimeTypeHandle[] instantiation)
+ {
+ unsafe
+ {
+ int length;
+ IntPtr[] instantiationHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(instantiation, out length);
+ fixed (IntPtr* pInstantiation = instantiationHandles)
+ {
+ _PrepareMethod(method.GetMethodInfo(), pInstantiation, length);
+ GC.KeepAlive(instantiation);
+ }
+ }
+ }
+
+ // This method triggers a given delegate to be prepared. This involves preparing the
+ // delegate's Invoke method and preparing the target of that Invoke. In the case of
+ // a multi-cast delegate, we rely on the fact that each individual component was prepared
+ // prior to the Combine. In other words, this service does not navigate through the
+ // entire multicasting list.
+ // If our own reliable event sinks perform the Combine (for example AppDomain.DomainUnload),
+ // then the result is fully prepared. But if a client calls Combine himself and then
+ // then adds that combination to e.g. AppDomain.DomainUnload, then the client is responsible
+ // for his own preparation.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void PrepareDelegate(Delegate d);
+
+ // See comment above for PrepareDelegate
+ //
+ // PrepareContractedDelegate weakens this a bit by only assuring that we prepare
+ // delegates which also have a ReliabilityContract. This is useful for services that
+ // want to provide opt-in reliability, generally some random event sink providing
+ // always reliable semantics to random event handlers that are likely to have not
+ // been written with relability in mind is a lost cause anyway.
+ //
+ // NOTE: that for the NGen case you can sidestep the required ReliabilityContract
+ // by using the [PrePrepareMethod] attribute.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void PrepareContractedDelegate(Delegate d);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetHashCode(Object o);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public new static extern bool Equals(Object o1, Object o2);
+
+ public static int OffsetToStringData
+ {
+ // This offset is baked in by string indexer intrinsic, so there is no harm
+ // in getting it baked in here as well.
+ [System.Runtime.Versioning.NonVersionable]
+ get {
+ // Number of bytes from the address pointed to by a reference to
+ // a String to the first 16-bit character in the String. Skip
+ // over the MethodTable pointer, & String
+ // length. Of course, the String reference points to the memory
+ // after the sync block, so don't count that.
+ // This property allows C#'s fixed statement to work on Strings.
+ // On 64 bit platforms, this should be 12 (8+4) and on 32 bit 8 (4+4).
+#if BIT64
+ return 12;
+#else // 32
+ return 8;
+#endif // BIT64
+ }
+ }
+
+ // This method ensures that there is sufficient stack to execute the average Framework function.
+ // If there is not enough stack, then it throws System.InsufficientExecutionStackException.
+ // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
+ // below.
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern void EnsureSufficientExecutionStack();
+
+#if FEATURE_CORECLR
+ // This method ensures that there is sufficient stack to execute the average Framework function.
+ // If there is not enough stack, then it return false.
+ // Note: this method is not part of the CER support, and is not to be confused with ProbeForSufficientStack
+ // below.
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern bool TryEnsureSufficientExecutionStack();
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static extern void ProbeForSufficientStack();
+
+ // This method is a marker placed immediately before a try clause to mark the corresponding catch and finally blocks as
+ // constrained. There's no code here other than the probe because most of the work is done at JIT time when we spot a call to this routine.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static void PrepareConstrainedRegions()
+ {
+ ProbeForSufficientStack();
+ }
+
+ // When we detect a CER with no calls, we can point the JIT to this non-probing version instead
+ // as we don't need to probe.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static void PrepareConstrainedRegionsNoOP()
+ {
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public delegate void TryCode(Object userData);
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public delegate void CleanupCode(Object userData, bool exceptionThrown);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData);
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ [PrePrepareMethod]
+ internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userData, bool exceptionThrown)
+ {
+ ((CleanupCode)backoutCode)(userData, exceptionThrown);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs
new file mode 100644
index 0000000000..2751d61db7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class uses to wrap all non-CLS compliant exceptions.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.CompilerServices {
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.Remoting;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public sealed class RuntimeWrappedException : Exception
+ {
+ private RuntimeWrappedException(Object thrownObject)
+ : base(Environment.GetResourceString("RuntimeWrappedException")) {
+ SetErrorCode(System.__HResults.COR_E_RUNTIMEWRAPPED);
+ m_wrappedException = thrownObject;
+ }
+
+ public Object WrappedException {
+ get { return m_wrappedException; }
+ }
+
+ private Object m_wrappedException;
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ base.GetObjectData(info, context);
+ info.AddValue("WrappedException", m_wrappedException, typeof(Object));
+ }
+
+ internal RuntimeWrappedException(SerializationInfo info, StreamingContext context)
+ : base(info, context) {
+ m_wrappedException = info.GetValue("WrappedException", typeof(Object));
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs
new file mode 100644
index 0000000000..91769187cc
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/ScopelessEnumAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+[Serializable]
+[AttributeUsage(AttributeTargets.Enum)]
+ public sealed class ScopelessEnumAttribute : Attribute
+ {
+ public ScopelessEnumAttribute()
+ {}
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs
new file mode 100644
index 0000000000..38e5538b44
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/SpecialNameAttribute.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Class |
+ AttributeTargets.Method |
+ AttributeTargets.Property |
+ AttributeTargets.Field |
+ AttributeTargets.Event |
+ AttributeTargets.Struct)]
+
+
+ public sealed class SpecialNameAttribute : Attribute
+ {
+ public SpecialNameAttribute() { }
+ }
+}
+
+
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs
new file mode 100644
index 0000000000..7c84009e1f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/StateMachineAttribute.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+
+namespace System.Runtime.CompilerServices
+{
+ [Serializable, AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public class StateMachineAttribute : Attribute
+ {
+ public Type StateMachineType { get; private set; }
+
+ public StateMachineAttribute(Type stateMachineType)
+ {
+ this.StateMachineType = stateMachineType;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs
new file mode 100644
index 0000000000..eb019eecbf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressIldasmAttribute.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module)]
+ public sealed class SuppressIldasmAttribute : Attribute
+ {
+ public SuppressIldasmAttribute()
+ {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs
new file mode 100644
index 0000000000..6bb36c4bf5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/SuppressMergeCheckAttribute.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Class |
+ AttributeTargets.Constructor |
+ AttributeTargets.Method |
+ AttributeTargets.Field |
+ AttributeTargets.Event |
+ AttributeTargets.Property)]
+
+ internal sealed class SuppressMergeCheckAttribute : Attribute
+ {
+ public SuppressMergeCheckAttribute()
+ {}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
new file mode 100644
index 0000000000..ea6bb96e16
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
@@ -0,0 +1,531 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Types for awaiting Task and Task<T>. These types are emitted from Task{<T>}.GetAwaiter
+// and Task{<T>}.ConfigureAwait. They are meant to be used only by the compiler, e.g.
+//
+// await nonGenericTask;
+// =====================
+// var $awaiter = nonGenericTask.GetAwaiter();
+// if (!$awaiter.IsCompleted)
+// {
+// SPILL:
+// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this);
+// return;
+// Label:
+// UNSPILL;
+// }
+// $awaiter.GetResult();
+//
+// result += await genericTask.ConfigureAwait(false);
+// ===================================================================================
+// var $awaiter = genericTask.ConfigureAwait(false).GetAwaiter();
+// if (!$awaiter.IsCompleted)
+// {
+// SPILL;
+// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this);
+// return;
+// Label:
+// UNSPILL;
+// }
+// result += $awaiter.GetResult();
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Security;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Security.Permissions;
+using System.Diagnostics.Tracing;
+
+// NOTE: For performance reasons, initialization is not verified. If a developer
+// incorrectly initializes a task awaiter, which should only be done by the compiler,
+// NullReferenceExceptions may be generated (the alternative would be for us to detect
+// this case and then throw a different exception instead). This is the same tradeoff
+// that's made with other compiler-focused value types like List<T>.Enumerator.
+
+namespace System.Runtime.CompilerServices
+{
+ /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct TaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly Task m_task;
+
+ /// <summary>Initializes the <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to be awaited.</param>
+ internal TaskAwaiter(Task task)
+ {
+ Contract.Requires(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecuritySafeCritical]
+ public void OnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ public void GetResult()
+ {
+ ValidateEnd(m_task);
+ }
+
+ /// <summary>
+ /// Fast checks for the end of an await operation to determine whether more needs to be done
+ /// prior to completing the await.
+ /// </summary>
+ /// <param name="task">The awaited task.</param>
+ internal static void ValidateEnd(Task task)
+ {
+ // Fast checks that can be inlined.
+ if (task.IsWaitNotificationEnabledOrNotRanToCompletion)
+ {
+ // If either the end await bit is set or we're not completed successfully,
+ // fall back to the slower path.
+ HandleNonSuccessAndDebuggerNotification(task);
+ }
+ }
+
+ /// <summary>
+ /// Ensures the task is completed, triggers any necessary debugger breakpoints for completing
+ /// the await on the task, and throws an exception if the task did not complete successfully.
+ /// </summary>
+ /// <param name="task">The awaited task.</param>
+ private static void HandleNonSuccessAndDebuggerNotification(Task task)
+ {
+ // NOTE: The JIT refuses to inline ValidateEnd when it contains the contents
+ // of HandleNonSuccessAndDebuggerNotification, hence the separation.
+
+ // Synchronously wait for the task to complete. When used by the compiler,
+ // the task will already be complete. This code exists only for direct GetResult use,
+ // for cases where the same exception propagation semantics used by "await" are desired,
+ // but where for one reason or another synchronous rather than asynchronous waiting is needed.
+ if (!task.IsCompleted)
+ {
+ bool taskCompleted = task.InternalWait(Timeout.Infinite, default(CancellationToken));
+ Contract.Assert(taskCompleted, "With an infinite timeout, the task should have always completed.");
+ }
+
+ // Now that we're done, alert the debugger if so requested
+ task.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // And throw an exception if the task is faulted or canceled.
+ if (!task.IsRanToCompletion) ThrowForNonSuccess(task);
+ }
+
+ /// <summary>Throws an exception to handle a task that completed in a state other than RanToCompletion.</summary>
+ private static void ThrowForNonSuccess(Task task)
+ {
+ Contract.Requires(task.IsCompleted, "Task must have been completed by now.");
+ Contract.Requires(task.Status != TaskStatus.RanToCompletion, "Task should not be completed successfully.");
+
+ // Handle whether the task has been canceled or faulted
+ switch (task.Status)
+ {
+ // If the task completed in a canceled state, throw an OperationCanceledException.
+ // This will either be the OCE that actually caused the task to cancel, or it will be a new
+ // TaskCanceledException. TCE derives from OCE, and by throwing it we automatically pick up the
+ // completed task's CancellationToken if it has one, including that CT in the OCE.
+ case TaskStatus.Canceled:
+ var oceEdi = task.GetCancellationExceptionDispatchInfo();
+ if (oceEdi != null)
+ {
+ oceEdi.Throw();
+ Contract.Assert(false, "Throw() should have thrown");
+ }
+ throw new TaskCanceledException(task);
+
+ // If the task faulted, throw its first exception,
+ // even if it contained more than one.
+ case TaskStatus.Faulted:
+ var edis = task.GetExceptionDispatchInfos();
+ if (edis.Count > 0)
+ {
+ edis[0].Throw();
+ Contract.Assert(false, "Throw() should have thrown");
+ break; // Necessary to compile: non-reachable, but compiler can't determine that
+ }
+ else
+ {
+ Contract.Assert(false, "There should be exceptions if we're Faulted.");
+ throw task.Exception;
+ }
+ }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ [SecurityCritical]
+ internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext)
+ {
+ if (continuation == null) throw new ArgumentNullException("continuation");
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ // If TaskWait* ETW events are enabled, trace a beginning event for this await
+ // and set up an ending event to be traced when the asynchronous await completes.
+ if ( TplEtwProvider.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
+ {
+ continuation = OutputWaitEtwEvents(task, continuation);
+ }
+
+ // Set the continuation onto the awaited task.
+ task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext, ref stackMark);
+ }
+
+ /// <summary>
+ /// Outputs a WaitBegin ETW event, and augments the continuation action to output a WaitEnd ETW event.
+ /// </summary>
+ /// <param name="task">The task being awaited.</param>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <returns>The action to use as the actual continuation.</returns>
+ private static Action OutputWaitEtwEvents(Task task, Action continuation)
+ {
+ Contract.Requires(task != null, "Need a task to wait on");
+ Contract.Requires(continuation != null, "Need a continuation to invoke when the wait completes");
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(task);
+ }
+
+ var etwLog = TplEtwProvider.Log;
+
+ if (etwLog.IsEnabled())
+ {
+ // ETW event for Task Wait Begin
+ var currentTaskAtBegin = Task.InternalCurrent;
+
+ // If this task's continuation is another task, get it.
+ var continuationTask = AsyncMethodBuilderCore.TryGetContinuationTask(continuation);
+ etwLog.TaskWaitBegin(
+ (currentTaskAtBegin != null ? currentTaskAtBegin.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtBegin != null ? currentTaskAtBegin.Id : 0),
+ task.Id, TplEtwProvider.TaskWaitBehavior.Asynchronous,
+ (continuationTask != null ? continuationTask.Id : 0), System.Threading.Thread.GetDomainID());
+ }
+
+ // Create a continuation action that outputs the end event and then invokes the user
+ // provided delegate. This incurs the allocations for the closure/delegate, but only if the event
+ // is enabled, and in doing so it allows us to pass the awaited task's information into the end event
+ // in a purely pay-for-play manner (the alternatively would be to increase the size of TaskAwaiter
+ // just for this ETW purpose, not pay-for-play, since GetResult would need to know whether a real yield occurred).
+ return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, () =>
+ {
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(task.Id);
+ }
+
+ // ETW event for Task Wait End.
+ Guid prevActivityId = new Guid();
+ bool bEtwLogEnabled = etwLog.IsEnabled();
+ if (bEtwLogEnabled)
+ {
+ var currentTaskAtEnd = Task.InternalCurrent;
+ etwLog.TaskWaitEnd(
+ (currentTaskAtEnd != null ? currentTaskAtEnd.m_taskScheduler.Id : TaskScheduler.Default.Id),
+ (currentTaskAtEnd != null ? currentTaskAtEnd.Id : 0),
+ task.Id);
+
+ // Ensure the continuation runs under the activity ID of the task that completed for the
+ // case the antecendent is a promise (in the other cases this is already the case).
+ if (etwLog.TasksSetActivityIds && (task.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(task.Id), out prevActivityId);
+ }
+ // Invoke the original continuation provided to OnCompleted.
+ continuation();
+
+ if (bEtwLogEnabled)
+ {
+ etwLog.TaskWaitContinuationComplete(task.Id);
+ if (etwLog.TasksSetActivityIds && (task.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ EventSource.SetCurrentThreadActivityId(prevActivityId);
+ }
+ });
+ }
+ }
+
+ /// <summary>Provides an awaiter for awaiting a <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct TaskAwaiter<TResult> : ICriticalNotifyCompletion
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly Task<TResult> m_task;
+
+ /// <summary>Initializes the <see cref="TaskAwaiter{TResult}"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task{TResult}"/> to be awaited.</param>
+ internal TaskAwaiter(Task<TResult> task)
+ {
+ Contract.Requires(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecuritySafeCritical]
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext:true, flowExecutionContext:false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.ResultOnSuccess;
+ }
+ }
+
+ /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public struct ConfiguredTaskAwaitable
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext)
+ {
+ Contract.Requires(task != null, "Constructing an awaitable requires a task to await.");
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// <summary>Gets an awaiter for this awaitable.</summary>
+ /// <returns>The awaiter.</returns>
+ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly Task m_task;
+ /// <summary>Whether to attempt marshaling back to the original context.</summary>
+ private readonly bool m_continueOnCapturedContext;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
+ /// <param name="task">The <see cref="System.Threading.Tasks.Task"/> to await.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured
+ /// when BeginAwait is called; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext)
+ {
+ Contract.Requires(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecuritySafeCritical]
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ public void GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ }
+ }
+ }
+
+ /// <summary>Provides an awaitable object that allows for configured awaits on <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public struct ConfiguredTaskAwaitable<TResult>
+ {
+ /// <summary>The underlying awaitable on whose logic this awaitable relies.</summary>
+ private readonly ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter m_configuredTaskAwaiter;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaitable(Task<TResult> task, bool continueOnCapturedContext)
+ {
+ m_configuredTaskAwaiter = new ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter(task, continueOnCapturedContext);
+ }
+
+ /// <summary>Gets an awaiter for this awaitable.</summary>
+ /// <returns>The awaiter.</returns>
+ public ConfiguredTaskAwaitable<TResult>.ConfiguredTaskAwaiter GetAwaiter()
+ {
+ return m_configuredTaskAwaiter;
+ }
+
+ /// <summary>Provides an awaiter for a <see cref="ConfiguredTaskAwaitable{TResult}"/>.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct ConfiguredTaskAwaiter : ICriticalNotifyCompletion
+ {
+ /// <summary>The task being awaited.</summary>
+ private readonly Task<TResult> m_task;
+ /// <summary>Whether to attempt marshaling back to the original context.</summary>
+ private readonly bool m_continueOnCapturedContext;
+
+ /// <summary>Initializes the <see cref="ConfiguredTaskAwaiter"/>.</summary>
+ /// <param name="task">The awaitable <see cref="System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ internal ConfiguredTaskAwaiter(Task<TResult> task, bool continueOnCapturedContext)
+ {
+ Contract.Requires(task != null, "Constructing an awaiter requires a task to await.");
+ m_task = task;
+ m_continueOnCapturedContext = continueOnCapturedContext;
+ }
+
+ /// <summary>Gets whether the task being awaited is completed.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ public bool IsCompleted
+ {
+ get { return m_task.IsCompleted; }
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecuritySafeCritical]
+ public void OnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:true);
+ }
+
+ /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
+ /// <param name="continuation">The action to invoke when the await operation completes.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext:false);
+ }
+
+ /// <summary>Ends the await on the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <returns>The result of the completed <see cref="System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
+ /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
+ /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+ public TResult GetResult()
+ {
+ TaskAwaiter.ValidateEnd(m_task);
+ return m_task.ResultOnSuccess;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs
new file mode 100644
index 0000000000..db04eb9348
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeDependencyAttribute.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+ using System.Diagnostics.Contracts;
+
+ // We might want to make this inherited someday. But I suspect it shouldn't
+ // be necessary.
+ [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
+ internal sealed class TypeDependencyAttribute: Attribute
+ {
+
+ private string typeName;
+
+ public TypeDependencyAttribute (string typeName)
+ {
+ if(typeName == null) throw new ArgumentNullException("typeName");
+ Contract.EndContractBlock();
+ this.typeName = typeName;
+ }
+ }
+
+}
+
+
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs
new file mode 100644
index 0000000000..c1656dcf99
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedFromAttribute.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Runtime.CompilerServices
+{
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false, AllowMultiple = false)]
+ public sealed class TypeForwardedFromAttribute : Attribute
+ {
+ string assemblyFullName;
+
+ private TypeForwardedFromAttribute()
+ {
+ // Disallow default constructor
+ }
+
+
+ public TypeForwardedFromAttribute(string assemblyFullName)
+ {
+ if (String.IsNullOrEmpty(assemblyFullName))
+ {
+ throw new ArgumentNullException("assemblyFullName");
+ }
+ this.assemblyFullName = assemblyFullName;
+ }
+
+ public string AssemblyFullName
+ {
+ get {
+ return assemblyFullName;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs
new file mode 100644
index 0000000000..034dad1afe
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/TypeForwardedToAttribute.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Reflection;
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple=true, Inherited=false)]
+ public sealed class TypeForwardedToAttribute : Attribute
+ {
+ private Type _destination;
+
+ public TypeForwardedToAttribute(Type destination)
+ {
+ _destination = destination;
+ }
+
+ public Type Destination
+ {
+ get {
+ return _destination;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal static TypeForwardedToAttribute[] GetCustomAttribute(RuntimeAssembly assembly)
+ {
+ Type[] types = null;
+ RuntimeAssembly.GetForwardedTypes(assembly.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types));
+
+ TypeForwardedToAttribute[] attributes = new TypeForwardedToAttribute[types.Length];
+ for (int i = 0; i < types.Length; ++i)
+ attributes[i] = new TypeForwardedToAttribute(types[i]);
+
+ return attributes;
+ }
+
+ }
+}
+
+
+
+
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs b/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs
new file mode 100644
index 0000000000..bc210ccb71
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/UnsafeValueTypeAttribute.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.CompilerServices
+{
+ using System;
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Struct)]
+ sealed public class UnsafeValueTypeAttribute : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
new file mode 100644
index 0000000000..b29b39c5bf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/YieldAwaitable.cs
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Compiler-targeted type for switching back into the current execution context, e.g.
+//
+// await Task.Yield();
+// =====================
+// var $awaiter = Task.Yield().GetAwaiter();
+// if (!$awaiter.IsCompleted)
+// {
+// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this);
+// return;
+// Label:
+// }
+// $awaiter.GetResult();
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Security;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Diagnostics.Tracing;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Security.Permissions;
+
+namespace System.Runtime.CompilerServices
+{
+ // NOTE: YieldAwaitable currently has no state; while developers are encouraged to use Task.Yield() to produce one,
+ // no validation is performed to ensure that the developer isn't doing "await new YieldAwaitable()". Such validation
+ // would require additional, useless state to be stored, and as this is a type in the CompilerServices namespace, and
+ // as the above example isn't harmful, we take the cheaper approach of not validating anything.
+
+ /// <summary>Provides an awaitable context for switching into a target environment.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ public struct YieldAwaitable
+ {
+ /// <summary>Gets an awaiter for this <see cref="YieldAwaitable"/>.</summary>
+ /// <returns>An awaiter for this awaitable.</returns>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public YieldAwaiter GetAwaiter() { return new YieldAwaiter(); }
+
+ /// <summary>Provides an awaiter that switches into a target environment.</summary>
+ /// <remarks>This type is intended for compiler use only.</remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct YieldAwaiter : ICriticalNotifyCompletion
+ {
+ /// <summary>Gets whether a yield is not required.</summary>
+ /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks>
+ public bool IsCompleted { get { return false; } } // yielding is always required for YieldAwaiter, hence false
+
+ /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary>
+ /// <param name="continuation">The action to invoke asynchronously.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ [SecuritySafeCritical]
+ public void OnCompleted(Action continuation)
+ {
+ QueueContinuation(continuation, flowContext: true);
+ }
+
+ /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary>
+ /// <param name="continuation">The action to invoke asynchronously.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation)
+ {
+ QueueContinuation(continuation, flowContext: false);
+ }
+
+ /// <summary>Posts the <paramref name="continuation"/> back to the current context.</summary>
+ /// <param name="continuation">The action to invoke asynchronously.</param>
+ /// <param name="flowContext">true to flow ExecutionContext; false if flowing is not required.</param>
+ /// <exception cref="System.ArgumentNullException">The <paramref name="continuation"/> argument is null (Nothing in Visual Basic).</exception>
+ [SecurityCritical]
+ private static void QueueContinuation(Action continuation, bool flowContext)
+ {
+ // Validate arguments
+ if (continuation == null) throw new ArgumentNullException("continuation");
+ Contract.EndContractBlock();
+
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ continuation = OutputCorrelationEtwEvent(continuation);
+ }
+ // Get the current SynchronizationContext, and if there is one,
+ // post the continuation to it. However, treat the base type
+ // as if there wasn't a SynchronizationContext, since that's what it
+ // logically represents.
+ var syncCtx = SynchronizationContext.CurrentNoFlow;
+ if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
+ {
+ syncCtx.Post(s_sendOrPostCallbackRunAction, continuation);
+ }
+ else
+ {
+ // If we're targeting the default scheduler, queue to the thread pool, so that we go into the global
+ // queue. As we're going into the global queue, we might as well use QUWI, which for the global queue is
+ // just a tad faster than task, due to a smaller object getting allocated and less work on the execution path.
+ TaskScheduler scheduler = TaskScheduler.Current;
+ if (scheduler == TaskScheduler.Default)
+ {
+ if (flowContext)
+ {
+ ThreadPool.QueueUserWorkItem(s_waitCallbackRunAction, continuation);
+ }
+ else
+ {
+ ThreadPool.UnsafeQueueUserWorkItem(s_waitCallbackRunAction, continuation);
+ }
+ }
+ // We're targeting a custom scheduler, so queue a task.
+ else
+ {
+ Task.Factory.StartNew(continuation, default(CancellationToken), TaskCreationOptions.PreferFairness, scheduler);
+ }
+ }
+ }
+
+ private static Action OutputCorrelationEtwEvent(Action continuation)
+ {
+ int continuationId = Task.NewId();
+ Task currentTask = Task.InternalCurrent;
+ // fire the correlation ETW event
+ TplEtwProvider.Log.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, (currentTask != null) ? currentTask.Id : 0, continuationId);
+
+ return AsyncMethodBuilderCore.CreateContinuationWrapper(continuation, () =>
+ {
+ var etwLog = TplEtwProvider.Log;
+ etwLog.TaskWaitContinuationStarted(continuationId);
+
+ // ETW event for Task Wait End.
+ Guid prevActivityId = new Guid();
+ // Ensure the continuation runs under the correlated activity ID generated above
+ if (etwLog.TasksSetActivityIds)
+ EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(continuationId), out prevActivityId);
+
+ // Invoke the original continuation provided to OnCompleted.
+ continuation();
+ // Restore activity ID
+
+ if (etwLog.TasksSetActivityIds)
+ EventSource.SetCurrentThreadActivityId(prevActivityId);
+
+ etwLog.TaskWaitContinuationComplete(continuationId);
+ });
+
+ }
+
+ /// <summary>WaitCallback that invokes the Action supplied as object state.</summary>
+ private static readonly WaitCallback s_waitCallbackRunAction = RunAction;
+ /// <summary>SendOrPostCallback that invokes the Action supplied as object state.</summary>
+ private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction;
+
+ /// <summary>Runs an Action delegate provided as state.</summary>
+ /// <param name="state">The Action delegate to invoke.</param>
+ private static void RunAction(object state) { ((Action)state)(); }
+
+ /// <summary>Ends the await operation.</summary>
+ public void GetResult() {} // Nop. It exists purely because the compiler pattern demands it.
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs
new file mode 100644
index 0000000000..8ee50da290
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/CompilerServices/jithelpers.cs
@@ -0,0 +1,224 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+// JitHelpers
+// Low-level Jit Helpers
+////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Threading;
+using System.Runtime;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Runtime.CompilerServices {
+
+ // Wrapper for address of a string variable on stack
+ internal struct StringHandleOnStack
+ {
+ private IntPtr m_ptr;
+
+ internal StringHandleOnStack(IntPtr pString)
+ {
+ m_ptr = pString;
+ }
+ }
+
+ // Wrapper for address of a object variable on stack
+ internal struct ObjectHandleOnStack
+ {
+ private IntPtr m_ptr;
+
+ internal ObjectHandleOnStack(IntPtr pObject)
+ {
+ m_ptr = pObject;
+ }
+ }
+
+ // Wrapper for StackCrawlMark
+ internal struct StackCrawlMarkHandle
+ {
+ private IntPtr m_ptr;
+
+ internal StackCrawlMarkHandle(IntPtr stackMark)
+ {
+ m_ptr = stackMark;
+ }
+ }
+
+ // Helper class to assist with unsafe pinning of arbitrary objects. The typical usage pattern is:
+ // fixed (byte * pData = &JitHelpers.GetPinningHelper(value).m_data)
+ // {
+ // ... pData is what Object::GetData() returns in VM ...
+ // }
+ internal class PinningHelper
+ {
+ public byte m_data;
+ }
+
+ [FriendAccessAllowed]
+ internal static class JitHelpers
+ {
+ // The special dll name to be used for DllImport of QCalls
+ internal const string QCall = "QCall";
+
+ // Wraps object variable into a handle. Used to return managed strings from QCalls.
+ // s has to be a local variable on the stack.
+ [SecurityCritical]
+ static internal StringHandleOnStack GetStringHandleOnStack(ref string s)
+ {
+ return new StringHandleOnStack(UnsafeCastToStackPointer(ref s));
+ }
+
+ // Wraps object variable into a handle. Used to pass managed object references in and out of QCalls.
+ // o has to be a local variable on the stack.
+ [SecurityCritical]
+ static internal ObjectHandleOnStack GetObjectHandleOnStack<T>(ref T o) where T : class
+ {
+ return new ObjectHandleOnStack(UnsafeCastToStackPointer(ref o));
+ }
+
+ // Wraps StackCrawlMark into a handle. Used to pass StackCrawlMark to QCalls.
+ // stackMark has to be a local variable on the stack.
+ [SecurityCritical]
+ static internal StackCrawlMarkHandle GetStackCrawlMarkHandle(ref StackCrawlMark stackMark)
+ {
+ return new StackCrawlMarkHandle(UnsafeCastToStackPointer(ref stackMark));
+ }
+
+#if _DEBUG
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ static internal T UnsafeCast<T>(Object o) where T : class
+ {
+ T ret = UnsafeCastInternal<T>(o);
+ Contract.Assert(ret == (o as T), "Invalid use of JitHelpers.UnsafeCast!");
+ return ret;
+ }
+
+ // The IL body of this method is not critical, but its body will be replaced with unsafe code, so
+ // this method is effectively critical
+ [SecurityCritical]
+ static private T UnsafeCastInternal<T>(Object o) where T : class
+ {
+ // The body of this function will be replaced by the EE with unsafe code that just returns o!!!
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum
+ {
+ Contract.Assert(typeof(T).IsEnum
+ && (Enum.GetUnderlyingType(typeof(T)) == typeof(int)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(uint)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(short)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(ushort)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(byte)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(sbyte)),
+ "Error, T must be an 4 byte (or less) enum JitHelpers.UnsafeEnumCast!");
+ return UnsafeEnumCastInternal<T>(val);
+ }
+
+ static private int UnsafeEnumCastInternal<T>(T val) where T : struct // Actually T must be 4 (or less) byte enum
+ {
+ // should be return (int) val; but C# does not allow, runtime does this magically
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum
+ {
+ Contract.Assert(typeof(T).IsEnum
+ && (Enum.GetUnderlyingType(typeof(T)) == typeof(long)
+ || Enum.GetUnderlyingType(typeof(T)) == typeof(ulong)),
+ "Error, T must be an 8 byte enum JitHelpers.UnsafeEnumCastLong!");
+ return UnsafeEnumCastLongInternal<T>(val);
+ }
+
+ static private long UnsafeEnumCastLongInternal<T>(T val) where T : struct // Actually T must be 8 byte enum
+ {
+ // should be return (int) val; but C# does not allow, runtime does this magically
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ // Internal method for getting a raw pointer for handles in JitHelpers.
+ // The reference has to point into a local stack variable in order so it can not be moved by the GC.
+ [SecurityCritical]
+ static internal IntPtr UnsafeCastToStackPointer<T>(ref T val)
+ {
+ IntPtr p = UnsafeCastToStackPointerInternal<T>(ref val);
+ Contract.Assert(IsAddressInStack(p), "Pointer not in the stack!");
+ return p;
+ }
+
+ [SecurityCritical]
+ static private IntPtr UnsafeCastToStackPointerInternal<T>(ref T val)
+ {
+ // The body of this function will be replaced by the EE with unsafe code that just returns val!!!
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+#else // _DEBUG
+ // The IL body of this method is not critical, but its body will be replaced with unsafe code, so
+ // this method is effectively critical
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ static internal T UnsafeCast<T>(Object o) where T : class
+ {
+ // The body of this function will be replaced by the EE with unsafe code that just returns o!!!
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ static internal int UnsafeEnumCast<T>(T val) where T : struct // Actually T must be 4 byte (or less) enum
+ {
+ // should be return (int) val; but C# does not allow, runtime does this magically
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ static internal long UnsafeEnumCastLong<T>(T val) where T : struct // Actually T must be 8 byte enum
+ {
+ // should be return (long) val; but C# does not allow, runtime does this magically
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+
+ [SecurityCritical]
+ static internal IntPtr UnsafeCastToStackPointer<T>(ref T val)
+ {
+ // The body of this function will be replaced by the EE with unsafe code that just returns o!!!
+ // See getILIntrinsicImplementation for how this happens.
+ throw new InvalidOperationException();
+ }
+#endif // _DEBUG
+
+ // Set the given element in the array without any type or range checks
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static internal void UnsafeSetArrayElement(Object[] target, int index, Object element);
+
+ // Used for unsafe pinning of arbitrary objects.
+ [System.Security.SecurityCritical] // auto-generated
+ static internal PinningHelper GetPinningHelper(Object o)
+ {
+ // This cast is really unsafe - call the private version that does not assert in debug
+#if _DEBUG
+ return UnsafeCastInternal<PinningHelper>(o);
+#else
+ return UnsafeCast<PinningHelper>(o);
+#endif
+ }
+
+#if _DEBUG
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern static bool IsAddressInStack(IntPtr ptr);
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs
new file mode 100644
index 0000000000..e12df10462
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/ExceptionServices/CorruptingExceptionCommon.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#if FEATURE_CORRUPTING_EXCEPTIONS
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Contains common usage support entities for Corrupting Exceptions
+**
+** Created: 06/20/2008
+**
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.ExceptionServices {
+ using System;
+
+ // This attribute can be applied to methods to indicate that ProcessCorruptedState
+ // Exceptions should be delivered to them.
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ public sealed class HandleProcessCorruptedStateExceptionsAttribute : Attribute
+ {
+ public HandleProcessCorruptedStateExceptionsAttribute()
+ {
+ }
+ }
+}
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
diff --git a/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs
new file mode 100644
index 0000000000..7251d901cd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Contains common usage support entities for advanced exception
+** handling/processing scenarios.
+**
+** Created: 11/2/2010
+**
+**
+**
+=============================================================================*/
+
+#if FEATURE_EXCEPTIONDISPATCHINFO
+namespace System.Runtime.ExceptionServices {
+ using System;
+
+ // This class defines support for seperating the exception dispatch details
+ // (like stack trace, watson buckets, etc) from the actual managed exception
+ // object. This allows us to track error (via the exception object) independent
+ // of the path the error takes.
+ //
+ // This is particularly useful for frameworks like PFX, APM, etc that wish to
+ // propagate exceptions (i.e. errors to be precise) across threads.
+ public sealed class ExceptionDispatchInfo
+ {
+ // Private members that will hold the relevant details.
+ private Exception m_Exception;
+ private string m_remoteStackTrace;
+ private object m_stackTrace;
+ private object m_dynamicMethods;
+ private UIntPtr m_IPForWatsonBuckets;
+ private Object m_WatsonBuckets;
+
+ private ExceptionDispatchInfo(Exception exception)
+ {
+ // Copy over the details we need to save.
+ m_Exception = exception;
+ m_remoteStackTrace = exception.RemoteStackTrace;
+
+ // NOTE: don't be tempted to pass the fields for the out params; the containing object
+ // might be relocated during the call so the pointers will no longer be valid.
+ object stackTrace;
+ object dynamicMethods;
+ m_Exception.GetStackTracesDeepCopy(out stackTrace, out dynamicMethods);
+ m_stackTrace = stackTrace;
+ m_dynamicMethods = dynamicMethods;
+
+ m_IPForWatsonBuckets = exception.IPForWatsonBuckets;
+ m_WatsonBuckets = exception.WatsonBuckets;
+ }
+
+ internal UIntPtr IPForWatsonBuckets
+ {
+ get
+ {
+ return m_IPForWatsonBuckets;
+ }
+ }
+
+ internal object WatsonBuckets
+ {
+ get
+ {
+ return m_WatsonBuckets;
+ }
+ }
+
+ internal object BinaryStackTraceArray
+ {
+ get
+ {
+ return m_stackTrace;
+ }
+ }
+
+ internal object DynamicMethodArray
+ {
+ get
+ {
+ return m_dynamicMethods;
+ }
+ }
+
+ internal string RemoteStackTrace
+ {
+ get
+ {
+ return m_remoteStackTrace;
+ }
+ }
+
+ // This static method is used to create an instance of ExceptionDispatchInfo for
+ // the specified exception object and save all the required details that maybe
+ // needed to be propagated when the exception is "rethrown" on a different thread.
+ public static ExceptionDispatchInfo Capture(Exception source)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source", Environment.GetResourceString("ArgumentNull_Obj"));
+ }
+
+ return new ExceptionDispatchInfo(source);
+ }
+
+ // Return the exception object represented by this ExceptionDispatchInfo instance
+ public Exception SourceException
+ {
+
+ get
+ {
+ return m_Exception;
+ }
+ }
+
+ // When a framework needs to "Rethrow" an exception on a thread different (but not necessarily so) from
+ // where it was thrown, it should invoke this method against the ExceptionDispatchInfo (EDI)
+ // created for the exception in question.
+ //
+ // This method will restore the original stack trace and bucketing details before throwing
+ // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
+ // the original thread.
+ public void Throw()
+ {
+ // Restore the exception dispatch details before throwing the exception.
+ m_Exception.RestoreExceptionDispatchInfo(this);
+ throw m_Exception;
+ }
+ }
+}
+#endif // FEATURE_EXCEPTIONDISPATCHINFO
diff --git a/src/mscorlib/src/System/Runtime/GcSettings.cs b/src/mscorlib/src/System/Runtime/GcSettings.cs
new file mode 100644
index 0000000000..5b4be27757
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/GcSettings.cs
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Runtime {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // These settings are the same format as in clr\src\vm\gcpriv.h
+ // make sure you change that file if you change this file!
+
+ [Serializable]
+ public enum GCLargeObjectHeapCompactionMode
+ {
+ Default = 1,
+ CompactOnce = 2
+ }
+
+ [Serializable]
+ public enum GCLatencyMode
+ {
+ Batch = 0,
+ Interactive = 1,
+ LowLatency = 2,
+ SustainedLowLatency = 3,
+ NoGCRegion = 4
+ }
+
+ public static class GCSettings
+ {
+ enum SetLatencyModeStatus
+ {
+ Succeeded = 0,
+ NoGCInProgress = 1 // NoGCRegion is in progress, can't change pause mode.
+ };
+
+ public static GCLatencyMode LatencyMode
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return (GCLatencyMode)(GC.GetGCLatencyMode());
+ }
+
+ // We don't want to allow this API when hosted.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [HostProtection(MayLeakOnAbort = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ if ((value < GCLatencyMode.Batch) || (value > GCLatencyMode.SustainedLowLatency))
+ {
+ throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ }
+ Contract.EndContractBlock();
+
+ if (GC.SetGCLatencyMode((int)value) == (int)SetLatencyModeStatus.NoGCInProgress)
+ throw new InvalidOperationException("The NoGCRegion mode is in progress. End it and then set a different mode.");
+ }
+ }
+
+ public static GCLargeObjectHeapCompactionMode LargeObjectHeapCompactionMode
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return (GCLargeObjectHeapCompactionMode)(GC.GetLOHCompactionMode());
+ }
+
+ // We don't want to allow this API when hosted.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [HostProtection(MayLeakOnAbort = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ if ((value < GCLargeObjectHeapCompactionMode.Default) ||
+ (value > GCLargeObjectHeapCompactionMode.CompactOnce))
+ {
+ throw new ArgumentOutOfRangeException(Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ }
+ Contract.EndContractBlock();
+
+ GC.SetLOHCompactionMode((int)value);
+ }
+ }
+
+ public static bool IsServerGC
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return GC.IsServerGC();
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs
new file mode 100644
index 0000000000..83eae1c59c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ArrayWithOffset.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct ArrayWithOffset
+ {
+ //private ArrayWithOffset()
+ //{
+ // throw new Exception();
+ //}
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ArrayWithOffset(Object array, int offset)
+ {
+ m_array = array;
+ m_offset = offset;
+ m_count = 0;
+ m_count = CalculateCount();
+ }
+
+ public Object GetArray()
+ {
+ return m_array;
+ }
+
+ public int GetOffset()
+ {
+ return m_offset;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_count + m_offset;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is ArrayWithOffset)
+ return Equals((ArrayWithOffset)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(ArrayWithOffset obj)
+ {
+ return obj.m_array == m_array && obj.m_offset == m_offset && obj.m_count == m_count;
+ }
+
+ public static bool operator ==(ArrayWithOffset a, ArrayWithOffset b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(ArrayWithOffset a, ArrayWithOffset b)
+ {
+ return !(a == b);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int CalculateCount();
+
+ private Object m_array;
+ private int m_offset;
+ private int m_count;
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs
new file mode 100644
index 0000000000..06c963a555
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Attributes.cs
@@ -0,0 +1,1138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices{
+
+ using System;
+ using System.Reflection;
+ using System.Diagnostics.Contracts;
+
+ [AttributeUsage(AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class UnmanagedFunctionPointerAttribute : Attribute
+ {
+ CallingConvention m_callingConvention;
+
+ public UnmanagedFunctionPointerAttribute(CallingConvention callingConvention) { m_callingConvention = callingConvention; }
+
+ public CallingConvention CallingConvention { get { return m_callingConvention; } }
+
+ public CharSet CharSet;
+ public bool BestFitMapping;
+ public bool ThrowOnUnmappableChar;
+
+ // This field is ignored and marshaling behaves as if it was true (for historical reasons).
+ public bool SetLastError;
+
+ // P/Invoke via delegate always preserves signature, HRESULT swapping is not supported.
+ //public bool PreserveSig;
+ }
+
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public sealed class TypeIdentifierAttribute : Attribute
+ {
+ public TypeIdentifierAttribute() { }
+ public TypeIdentifierAttribute(string scope, string identifier) { Scope_ = scope; Identifier_ = identifier; }
+
+ public String Scope { get { return Scope_; } }
+ public String Identifier { get { return Identifier_; } }
+
+ internal String Scope_;
+ internal String Identifier_;
+ }
+
+ // To be used on methods that sink reverse P/Invoke calls.
+ // This attribute is a CoreCLR-only security measure, currently ignored by the desktop CLR.
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ public sealed class AllowReversePInvokeCallsAttribute : Attribute
+ {
+ public AllowReversePInvokeCallsAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Event, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DispIdAttribute : Attribute
+ {
+ internal int _val;
+ public DispIdAttribute(int dispId)
+ {
+ _val = dispId;
+ }
+ public int Value { get { return _val; } }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ComInterfaceType
+ {
+ InterfaceIsDual = 0,
+ InterfaceIsIUnknown = 1,
+ InterfaceIsIDispatch = 2,
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ InterfaceIsIInspectable = 3,
+ }
+
+ [AttributeUsage(AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class InterfaceTypeAttribute : Attribute
+ {
+ internal ComInterfaceType _val;
+ public InterfaceTypeAttribute(ComInterfaceType interfaceType)
+ {
+ _val = interfaceType;
+ }
+ public InterfaceTypeAttribute(short interfaceType)
+ {
+ _val = (ComInterfaceType)interfaceType;
+ }
+ public ComInterfaceType Value { get { return _val; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComDefaultInterfaceAttribute : Attribute
+ {
+ internal Type _val;
+
+ public ComDefaultInterfaceAttribute(Type defaultInterface)
+ {
+ _val = defaultInterface;
+ }
+
+ public Type Value { get { return _val; } }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ClassInterfaceType
+ {
+ None = 0,
+ AutoDispatch = 1,
+ AutoDual = 2
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ClassInterfaceAttribute : Attribute
+ {
+ internal ClassInterfaceType _val;
+ public ClassInterfaceAttribute(ClassInterfaceType classInterfaceType)
+ {
+ _val = classInterfaceType;
+
+ }
+ public ClassInterfaceAttribute(short classInterfaceType)
+ {
+ _val = (ClassInterfaceType)classInterfaceType;
+ }
+ public ClassInterfaceType Value { get { return _val; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Delegate | AttributeTargets.Enum | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComVisibleAttribute : Attribute
+ {
+ internal bool _val;
+ public ComVisibleAttribute(bool visibility)
+ {
+ _val = visibility;
+ }
+ public bool Value { get { return _val; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibImportClassAttribute : Attribute
+ {
+ internal String _importClassName;
+ public TypeLibImportClassAttribute(Type importClass)
+ {
+ _importClassName = importClass.ToString();
+ }
+ public String Value { get { return _importClassName; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class LCIDConversionAttribute : Attribute
+ {
+ internal int _val;
+ public LCIDConversionAttribute(int lcid)
+ {
+ _val = lcid;
+ }
+ public int Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComRegisterFunctionAttribute : Attribute
+ {
+ public ComRegisterFunctionAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComUnregisterFunctionAttribute : Attribute
+ {
+ public ComUnregisterFunctionAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ProgIdAttribute : Attribute
+ {
+ internal String _val;
+ public ProgIdAttribute(String progId)
+ {
+ _val = progId;
+ }
+ public String Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ImportedFromTypeLibAttribute : Attribute
+ {
+ internal String _val;
+ public ImportedFromTypeLibAttribute(String tlbFile)
+ {
+ _val = tlbFile;
+ }
+ public String Value { get {return _val;} }
+ }
+
+ [Obsolete("The IDispatchImplAttribute is deprecated.", false)]
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum IDispatchImplType
+ {
+ SystemDefinedImpl = 0,
+ InternalImpl = 1,
+ CompatibleImpl = 2,
+ }
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, Inherited = false)]
+ [Obsolete("This attribute is deprecated and will be removed in a future version.", false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class IDispatchImplAttribute : Attribute
+ {
+ internal IDispatchImplType _val;
+ public IDispatchImplAttribute(IDispatchImplType implType)
+ {
+ _val = implType;
+ }
+ public IDispatchImplAttribute(short implType)
+ {
+ _val = (IDispatchImplType)implType;
+ }
+ public IDispatchImplType Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Class, Inherited = true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComSourceInterfacesAttribute : Attribute
+ {
+ internal String _val;
+ public ComSourceInterfacesAttribute(String sourceInterfaces)
+ {
+ _val = sourceInterfaces;
+ }
+ public ComSourceInterfacesAttribute(Type sourceInterface)
+ {
+ _val = sourceInterface.FullName;
+ }
+ public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2)
+ {
+ _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName;
+ }
+ public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3)
+ {
+ _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName;
+ }
+ public ComSourceInterfacesAttribute(Type sourceInterface1, Type sourceInterface2, Type sourceInterface3, Type sourceInterface4)
+ {
+ _val = sourceInterface1.FullName + "\0" + sourceInterface2.FullName + "\0" + sourceInterface3.FullName + "\0" + sourceInterface4.FullName;
+ }
+ public String Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.All, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComConversionLossAttribute : Attribute
+ {
+ public ComConversionLossAttribute()
+ {
+ }
+ }
+
+[Serializable]
+[Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeLibTypeFlags
+ {
+ FAppObject = 0x0001,
+ FCanCreate = 0x0002,
+ FLicensed = 0x0004,
+ FPreDeclId = 0x0008,
+ FHidden = 0x0010,
+ FControl = 0x0020,
+ FDual = 0x0040,
+ FNonExtensible = 0x0080,
+ FOleAutomation = 0x0100,
+ FRestricted = 0x0200,
+ FAggregatable = 0x0400,
+ FReplaceable = 0x0800,
+ FDispatchable = 0x1000,
+ FReverseBind = 0x2000,
+ }
+
+[Serializable]
+[Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeLibFuncFlags
+ {
+ FRestricted = 0x0001,
+ FSource = 0x0002,
+ FBindable = 0x0004,
+ FRequestEdit = 0x0008,
+ FDisplayBind = 0x0010,
+ FDefaultBind = 0x0020,
+ FHidden = 0x0040,
+ FUsesGetLastError = 0x0080,
+ FDefaultCollelem = 0x0100,
+ FUiDefault = 0x0200,
+ FNonBrowsable = 0x0400,
+ FReplaceable = 0x0800,
+ FImmediateBind = 0x1000,
+ }
+
+[Serializable]
+[Flags()]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeLibVarFlags
+ {
+ FReadOnly = 0x0001,
+ FSource = 0x0002,
+ FBindable = 0x0004,
+ FRequestEdit = 0x0008,
+ FDisplayBind = 0x0010,
+ FDefaultBind = 0x0020,
+ FHidden = 0x0040,
+ FRestricted = 0x0080,
+ FDefaultCollelem = 0x0100,
+ FUiDefault = 0x0200,
+ FNonBrowsable = 0x0400,
+ FReplaceable = 0x0800,
+ FImmediateBind = 0x1000,
+ }
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibTypeAttribute : Attribute
+ {
+ internal TypeLibTypeFlags _val;
+ public TypeLibTypeAttribute(TypeLibTypeFlags flags)
+ {
+ _val = flags;
+ }
+ public TypeLibTypeAttribute(short flags)
+ {
+ _val = (TypeLibTypeFlags)flags;
+ }
+ public TypeLibTypeFlags Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibFuncAttribute : Attribute
+ {
+ internal TypeLibFuncFlags _val;
+ public TypeLibFuncAttribute(TypeLibFuncFlags flags)
+ {
+ _val = flags;
+ }
+ public TypeLibFuncAttribute(short flags)
+ {
+ _val = (TypeLibFuncFlags)flags;
+ }
+ public TypeLibFuncFlags Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibVarAttribute : Attribute
+ {
+ internal TypeLibVarFlags _val;
+ public TypeLibVarAttribute(TypeLibVarFlags flags)
+ {
+ _val = flags;
+ }
+ public TypeLibVarAttribute(short flags)
+ {
+ _val = (TypeLibVarFlags)flags;
+ }
+ public TypeLibVarFlags Value { get {return _val;} }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum VarEnum
+ {
+ VT_EMPTY = 0,
+ VT_NULL = 1,
+ VT_I2 = 2,
+ VT_I4 = 3,
+ VT_R4 = 4,
+ VT_R8 = 5,
+ VT_CY = 6,
+ VT_DATE = 7,
+ VT_BSTR = 8,
+ VT_DISPATCH = 9,
+ VT_ERROR = 10,
+ VT_BOOL = 11,
+ VT_VARIANT = 12,
+ VT_UNKNOWN = 13,
+ VT_DECIMAL = 14,
+ VT_I1 = 16,
+ VT_UI1 = 17,
+ VT_UI2 = 18,
+ VT_UI4 = 19,
+ VT_I8 = 20,
+ VT_UI8 = 21,
+ VT_INT = 22,
+ VT_UINT = 23,
+ VT_VOID = 24,
+ VT_HRESULT = 25,
+ VT_PTR = 26,
+ VT_SAFEARRAY = 27,
+ VT_CARRAY = 28,
+ VT_USERDEFINED = 29,
+ VT_LPSTR = 30,
+ VT_LPWSTR = 31,
+ VT_RECORD = 36,
+ VT_FILETIME = 64,
+ VT_BLOB = 65,
+ VT_STREAM = 66,
+ VT_STORAGE = 67,
+ VT_STREAMED_OBJECT = 68,
+ VT_STORED_OBJECT = 69,
+ VT_BLOB_OBJECT = 70,
+ VT_CF = 71,
+ VT_CLSID = 72,
+ VT_VECTOR = 0x1000,
+ VT_ARRAY = 0x2000,
+ VT_BYREF = 0x4000
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ // Note that this enum should remain in-sync with the CorNativeType enum in corhdr.h
+ public enum UnmanagedType
+ {
+ Bool = 0x2, // 4 byte boolean value (true != 0, false == 0)
+
+ I1 = 0x3, // 1 byte signed value
+
+ U1 = 0x4, // 1 byte unsigned value
+
+ I2 = 0x5, // 2 byte signed value
+
+ U2 = 0x6, // 2 byte unsigned value
+
+ I4 = 0x7, // 4 byte signed value
+
+ U4 = 0x8, // 4 byte unsigned value
+
+ I8 = 0x9, // 8 byte signed value
+
+ U8 = 0xa, // 8 byte unsigned value
+
+ R4 = 0xb, // 4 byte floating point
+
+ R8 = 0xc, // 8 byte floating point
+
+ Currency = 0xf, // A currency
+
+ BStr = 0x13, // OLE Unicode BSTR
+
+ LPStr = 0x14, // Ptr to SBCS string
+
+ LPWStr = 0x15, // Ptr to Unicode string
+
+ LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string
+
+ ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs)
+
+ IUnknown = 0x19, // COM IUnknown pointer.
+
+ IDispatch = 0x1a, // COM IDispatch pointer
+
+ Struct = 0x1b, // Structure
+
+ Interface = 0x1c, // COM interface
+
+ SafeArray = 0x1d, // OLE SafeArray
+
+ ByValArray = 0x1e, // Array of fixed size (only valid in structs)
+
+ SysInt = 0x1f, // Hardware natural sized signed integer
+
+ SysUInt = 0x20,
+
+ VBByRefStr = 0x22,
+
+ AnsiBStr = 0x23, // OLE BSTR containing SBCS characters
+
+ TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR
+
+ VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0)
+
+ FunctionPtr = 0x26, // Function pointer
+
+ AsAny = 0x28, // Paired with Object type and does runtime marshalling determination
+
+ LPArray = 0x2a, // C style array
+
+ LPStruct = 0x2b, // Pointer to a structure
+
+ CustomMarshaler = 0x2c,
+
+ Error = 0x2d,
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ IInspectable = 0x2e,
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ HString = 0x2f, // Windows Runtime HSTRING
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ LPUTF8Str = 0x30, // UTF8 string
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.ReturnValue, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class MarshalAsAttribute : Attribute
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter)
+ {
+ return GetCustomAttribute(parameter.MetadataToken, parameter.GetRuntimeModule());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeParameterInfo parameter)
+ {
+ return GetCustomAttribute(parameter) != null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(RuntimeFieldInfo field)
+ {
+ return GetCustomAttribute(field.MetadataToken, field.GetRuntimeModule()); ;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeFieldInfo field)
+ {
+ return GetCustomAttribute(field) != null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(int token, RuntimeModule scope)
+ {
+ UnmanagedType unmanagedType, arraySubType;
+ VarEnum safeArraySubType;
+ int sizeParamIndex = 0, sizeConst = 0;
+ string marshalTypeName = null, marshalCookie = null, safeArrayUserDefinedTypeName = null;
+ int iidParamIndex = 0;
+ ConstArray nativeType = ModuleHandle.GetMetadataImport(scope.GetNativeHandle()).GetFieldMarshal(token);
+
+ if (nativeType.Length == 0)
+ return null;
+
+ MetadataImport.GetMarshalAs(nativeType,
+ out unmanagedType, out safeArraySubType, out safeArrayUserDefinedTypeName, out arraySubType, out sizeParamIndex,
+ out sizeConst, out marshalTypeName, out marshalCookie, out iidParamIndex);
+
+ RuntimeType safeArrayUserDefinedType = safeArrayUserDefinedTypeName == null || safeArrayUserDefinedTypeName.Length == 0 ? null :
+ RuntimeTypeHandle.GetTypeByNameUsingCARules(safeArrayUserDefinedTypeName, scope);
+ RuntimeType marshalTypeRef = null;
+
+ try
+ {
+ marshalTypeRef = marshalTypeName == null ? null : RuntimeTypeHandle.GetTypeByNameUsingCARules(marshalTypeName, scope);
+ }
+ catch (System.TypeLoadException)
+ {
+ // The user may have supplied a bad type name string causing this TypeLoadException
+ // Regardless, we return the bad type name
+ Contract.Assert(marshalTypeName != null);
+ }
+
+ return new MarshalAsAttribute(
+ unmanagedType, safeArraySubType, safeArrayUserDefinedType, arraySubType,
+ (short)sizeParamIndex, sizeConst, marshalTypeName, marshalTypeRef, marshalCookie, iidParamIndex);
+ }
+
+ internal MarshalAsAttribute(UnmanagedType val, VarEnum safeArraySubType, RuntimeType safeArrayUserDefinedSubType, UnmanagedType arraySubType,
+ short sizeParamIndex, int sizeConst, string marshalType, RuntimeType marshalTypeRef, string marshalCookie, int iidParamIndex)
+ {
+ _val = val;
+ SafeArraySubType = safeArraySubType;
+ SafeArrayUserDefinedSubType = safeArrayUserDefinedSubType;
+ IidParameterIndex = iidParamIndex;
+ ArraySubType = arraySubType;
+ SizeParamIndex = sizeParamIndex;
+ SizeConst = sizeConst;
+ MarshalType = marshalType;
+ MarshalTypeRef = marshalTypeRef;
+ MarshalCookie = marshalCookie;
+ }
+
+ internal UnmanagedType _val;
+ public MarshalAsAttribute(UnmanagedType unmanagedType)
+ {
+ _val = unmanagedType;
+ }
+ public MarshalAsAttribute(short unmanagedType)
+ {
+ _val = (UnmanagedType)unmanagedType;
+ }
+ public UnmanagedType Value { get { return _val; } }
+
+ // Fields used with SubType = SafeArray.
+ public VarEnum SafeArraySubType;
+ public Type SafeArrayUserDefinedSubType;
+
+ // Field used with iid_is attribute (interface pointers).
+ public int IidParameterIndex;
+
+ // Fields used with SubType = ByValArray and LPArray.
+ // Array size = parameter(PI) * PM + C
+ public UnmanagedType ArraySubType;
+ public short SizeParamIndex; // param index PI
+ public int SizeConst; // constant C
+
+ // Fields used with SubType = CustomMarshaler
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public String MarshalType; // Name of marshaler class
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public Type MarshalTypeRef; // Type of marshaler class
+ public String MarshalCookie; // cookie to pass to marshaler
+ }
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComImportAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeType type)
+ {
+ if ((type.Attributes & TypeAttributes.Import) == 0)
+ return null;
+
+ return new ComImportAttribute();
+ }
+
+ internal static bool IsDefined(RuntimeType type)
+ {
+ return (type.Attributes & TypeAttributes.Import) != 0;
+ }
+
+ public ComImportAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class GuidAttribute : Attribute
+ {
+ internal String _val;
+ public GuidAttribute(String guid)
+ {
+ _val = guid;
+ }
+ public String Value { get { return _val; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class PreserveSigAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeMethodInfo method)
+ {
+ if ((method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) == 0)
+ return null;
+
+ return new PreserveSigAttribute();
+ }
+
+ internal static bool IsDefined(RuntimeMethodInfo method)
+ {
+ return (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0;
+ }
+
+ public PreserveSigAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class InAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsIn ? new InAttribute() : null;
+ }
+ internal static bool IsDefined(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsIn;
+ }
+
+ public InAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OutAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsOut ? new OutAttribute() : null;
+ }
+ internal static bool IsDefined(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsOut;
+ }
+
+ public OutAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OptionalAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsOptional ? new OptionalAttribute() : null;
+ }
+ internal static bool IsDefined(RuntimeParameterInfo parameter)
+ {
+ return parameter.IsOptional;
+ }
+
+ public OptionalAttribute()
+ {
+ }
+ }
+
+ [Flags]
+ public enum DllImportSearchPath
+ {
+ UseDllDirectoryForDependencies = 0x100,
+ ApplicationDirectory = 0x200,
+ UserDirectories = 0x400,
+ System32 = 0x800,
+ SafeDirectories = 0x1000,
+ AssemblyDirectory = 0x2,
+ LegacyBehavior = 0x0
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Method, AllowMultiple = false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public sealed class DefaultDllImportSearchPathsAttribute : Attribute
+ {
+ internal DllImportSearchPath _paths;
+ public DefaultDllImportSearchPathsAttribute(DllImportSearchPath paths)
+ {
+ _paths = paths;
+ }
+
+ public DllImportSearchPath Paths { get { return _paths; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class DllImportAttribute : Attribute
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(RuntimeMethodInfo method)
+ {
+ if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0)
+ return null;
+
+ MetadataImport scope = ModuleHandle.GetMetadataImport(method.Module.ModuleHandle.GetRuntimeModule());
+ string entryPoint, dllName = null;
+ int token = method.MetadataToken;
+ PInvokeAttributes flags = 0;
+
+ scope.GetPInvokeMap(token, out flags, out entryPoint, out dllName);
+
+ CharSet charSet = CharSet.None;
+
+ switch (flags & PInvokeAttributes.CharSetMask)
+ {
+ case PInvokeAttributes.CharSetNotSpec: charSet = CharSet.None; break;
+ case PInvokeAttributes.CharSetAnsi: charSet = CharSet.Ansi; break;
+ case PInvokeAttributes.CharSetUnicode: charSet = CharSet.Unicode; break;
+ case PInvokeAttributes.CharSetAuto: charSet = CharSet.Auto; break;
+
+ // Invalid: default to CharSet.None
+ default: break;
+ }
+
+ CallingConvention callingConvention = CallingConvention.Cdecl;
+
+ switch (flags & PInvokeAttributes.CallConvMask)
+ {
+ case PInvokeAttributes.CallConvWinapi: callingConvention = CallingConvention.Winapi; break;
+ case PInvokeAttributes.CallConvCdecl: callingConvention = CallingConvention.Cdecl; break;
+ case PInvokeAttributes.CallConvStdcall: callingConvention = CallingConvention.StdCall; break;
+ case PInvokeAttributes.CallConvThiscall: callingConvention = CallingConvention.ThisCall; break;
+ case PInvokeAttributes.CallConvFastcall: callingConvention = CallingConvention.FastCall; break;
+
+ // Invalid: default to CallingConvention.Cdecl
+ default: break;
+ }
+
+ bool exactSpelling = (flags & PInvokeAttributes.NoMangle) != 0;
+ bool setLastError = (flags & PInvokeAttributes.SupportsLastError) != 0;
+ bool bestFitMapping = (flags & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled;
+ bool throwOnUnmappableChar = (flags & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled;
+ bool preserveSig = (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0;
+
+ return new DllImportAttribute(
+ dllName, entryPoint, charSet, exactSpelling, setLastError, preserveSig,
+ callingConvention, bestFitMapping, throwOnUnmappableChar);
+ }
+
+ internal static bool IsDefined(RuntimeMethodInfo method)
+ {
+ return (method.Attributes & MethodAttributes.PinvokeImpl) != 0;
+ }
+
+
+ internal DllImportAttribute(
+ string dllName, string entryPoint, CharSet charSet, bool exactSpelling, bool setLastError, bool preserveSig,
+ CallingConvention callingConvention, bool bestFitMapping, bool throwOnUnmappableChar)
+ {
+ _val = dllName;
+ EntryPoint = entryPoint;
+ CharSet = charSet;
+ ExactSpelling = exactSpelling;
+ SetLastError = setLastError;
+ PreserveSig = preserveSig;
+ CallingConvention = callingConvention;
+ BestFitMapping = bestFitMapping;
+ ThrowOnUnmappableChar = throwOnUnmappableChar;
+ }
+
+ internal String _val;
+
+ public DllImportAttribute(String dllName)
+ {
+ _val = dllName;
+ }
+ public String Value { get { return _val; } }
+
+ public String EntryPoint;
+ public CharSet CharSet;
+ public bool SetLastError;
+ public bool ExactSpelling;
+ public bool PreserveSig;
+ public CallingConvention CallingConvention;
+ public bool BestFitMapping;
+ public bool ThrowOnUnmappableChar;
+
+ }
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class StructLayoutAttribute : Attribute
+ {
+ private const int DEFAULT_PACKING_SIZE = 8;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(RuntimeType type)
+ {
+ if (!IsDefined(type))
+ return null;
+
+ int pack = 0, size = 0;
+ LayoutKind layoutKind = LayoutKind.Auto;
+ switch (type.Attributes & TypeAttributes.LayoutMask)
+ {
+ case TypeAttributes.ExplicitLayout: layoutKind = LayoutKind.Explicit; break;
+ case TypeAttributes.AutoLayout: layoutKind = LayoutKind.Auto; break;
+ case TypeAttributes.SequentialLayout: layoutKind = LayoutKind.Sequential; break;
+ default: Contract.Assume(false); break;
+ }
+
+ CharSet charSet = CharSet.None;
+ switch (type.Attributes & TypeAttributes.StringFormatMask)
+ {
+ case TypeAttributes.AnsiClass: charSet = CharSet.Ansi; break;
+ case TypeAttributes.AutoClass: charSet = CharSet.Auto; break;
+ case TypeAttributes.UnicodeClass: charSet = CharSet.Unicode; break;
+ default: Contract.Assume(false); break;
+ }
+ type.GetRuntimeModule().MetadataImport.GetClassLayout(type.MetadataToken, out pack, out size);
+
+ // Metadata parameter checking should not have allowed 0 for packing size.
+ // The runtime later converts a packing size of 0 to 8 so do the same here
+ // because it's more useful from a user perspective.
+ if (pack == 0)
+ pack = DEFAULT_PACKING_SIZE;
+
+ return new StructLayoutAttribute(layoutKind, pack, size, charSet);
+ }
+
+ internal static bool IsDefined(RuntimeType type)
+ {
+ if (type.IsInterface || type.HasElementType || type.IsGenericParameter)
+ return false;
+
+ return true;
+ }
+
+ internal LayoutKind _val;
+
+ internal StructLayoutAttribute(LayoutKind layoutKind, int pack, int size, CharSet charSet)
+ {
+ _val = layoutKind;
+ Pack = pack;
+ Size = size;
+ CharSet = charSet;
+ }
+
+ public StructLayoutAttribute(LayoutKind layoutKind)
+ {
+ _val = layoutKind;
+ }
+ public StructLayoutAttribute(short layoutKind)
+ {
+ _val = (LayoutKind)layoutKind;
+ }
+ public LayoutKind Value { get { return _val; } }
+ public int Pack;
+ public int Size;
+ public CharSet CharSet;
+ }
+
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe sealed class FieldOffsetAttribute : Attribute
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Attribute GetCustomAttribute(RuntimeFieldInfo field)
+ {
+ int fieldOffset;
+
+ if (field.DeclaringType != null &&
+ field.GetRuntimeModule().MetadataImport.GetFieldOffset(field.DeclaringType.MetadataToken, field.MetadataToken, out fieldOffset))
+ return new FieldOffsetAttribute(fieldOffset);
+
+ return null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool IsDefined(RuntimeFieldInfo field)
+ {
+ return GetCustomAttribute(field) != null;
+ }
+
+ internal int _val;
+ public FieldOffsetAttribute(int offset)
+ {
+ _val = offset;
+ }
+ public int Value { get { return _val; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.ReturnValue, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComAliasNameAttribute : Attribute
+ {
+ internal String _val;
+ public ComAliasNameAttribute(String alias)
+ {
+ _val = alias;
+ }
+ public String Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AutomationProxyAttribute : Attribute
+ {
+ internal bool _val;
+ public AutomationProxyAttribute(bool val)
+ {
+ _val = val;
+ }
+ public bool Value { get {return _val;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class PrimaryInteropAssemblyAttribute : Attribute
+ {
+ internal int _major;
+ internal int _minor;
+
+ public PrimaryInteropAssemblyAttribute(int major, int minor)
+ {
+ _major = major;
+ _minor = minor;
+ }
+
+ public int MajorVersion { get {return _major;} }
+ public int MinorVersion { get {return _minor;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class CoClassAttribute : Attribute
+ {
+ internal Type _CoClass;
+
+ public CoClassAttribute(Type coClass)
+ {
+ _CoClass = coClass;
+ }
+
+ public Type CoClass { get { return _CoClass; } }
+ }
+
+ [AttributeUsage(AttributeTargets.Interface, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComEventInterfaceAttribute : Attribute
+ {
+ internal Type _SourceInterface;
+ internal Type _EventProvider;
+
+ public ComEventInterfaceAttribute(Type SourceInterface, Type EventProvider)
+ {
+ _SourceInterface = SourceInterface;
+ _EventProvider = EventProvider;
+ }
+
+ public Type SourceInterface { get {return _SourceInterface;} }
+ public Type EventProvider { get {return _EventProvider;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibVersionAttribute : Attribute
+ {
+ internal int _major;
+ internal int _minor;
+
+ public TypeLibVersionAttribute(int major, int minor)
+ {
+ _major = major;
+ _minor = minor;
+ }
+
+ public int MajorVersion { get {return _major;} }
+ public int MinorVersion { get {return _minor;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ComCompatibleVersionAttribute : Attribute
+ {
+ internal int _major;
+ internal int _minor;
+ internal int _build;
+ internal int _revision;
+
+ public ComCompatibleVersionAttribute(int major, int minor, int build, int revision)
+ {
+ _major = major;
+ _minor = minor;
+ _build = build;
+ _revision = revision;
+ }
+
+ public int MajorVersion { get {return _major;} }
+ public int MinorVersion { get {return _minor;} }
+ public int BuildNumber { get {return _build;} }
+ public int RevisionNumber { get {return _revision;} }
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class BestFitMappingAttribute : Attribute
+ {
+ internal bool _bestFitMapping;
+
+ public BestFitMappingAttribute(bool BestFitMapping)
+ {
+ _bestFitMapping = BestFitMapping;
+ }
+
+ public bool BestFitMapping { get { return _bestFitMapping; } }
+ public bool ThrowOnUnmappableChar;
+ }
+
+ [AttributeUsage(AttributeTargets.Module, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DefaultCharSetAttribute : Attribute
+ {
+ internal CharSet _CharSet;
+
+ public DefaultCharSetAttribute(CharSet charSet)
+ {
+ _CharSet = charSet;
+ }
+
+ public CharSet CharSet { get { return _CharSet; } }
+ }
+
+ [Obsolete("This attribute has been deprecated. Application Domains no longer respect Activation Context boundaries in IDispatch calls.", false)]
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SetWin32ContextInIDispatchAttribute : Attribute
+ {
+ public SetWin32ContextInIDispatchAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public sealed class ManagedToNativeComInteropStubAttribute : Attribute
+ {
+ internal Type _classType;
+ internal String _methodName;
+
+ public ManagedToNativeComInteropStubAttribute(Type classType, String methodName)
+ {
+ _classType = classType;
+ _methodName = methodName;
+ }
+
+ public Type ClassType { get { return _classType; } }
+ public String MethodName { get { return _methodName; } }
+ }
+
+}
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs
new file mode 100644
index 0000000000..58e93a87ea
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/BStrWrapper.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_BSTR.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class BStrWrapper
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public BStrWrapper(String value)
+ {
+ m_WrappedObject = value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public BStrWrapper(Object value)
+ {
+ m_WrappedObject = (String)value;
+ }
+
+ public String WrappedObject
+ {
+ get
+ {
+ return m_WrappedObject;
+ }
+ }
+
+ private String m_WrappedObject;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs
new file mode 100644
index 0000000000..95b925c3f4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/COMException.cs
@@ -0,0 +1,90 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for all errors from COM Interop where we don't
+** recognize the HResult.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security;
+ using Microsoft.Win32;
+
+ // Exception for COM Interop errors where we don't recognize the HResult.
+ //
+ [ComVisible(true)]
+ [Serializable]
+ public class COMException : ExternalException {
+ public COMException()
+ : base(Environment.GetResourceString("Arg_COMException"))
+ {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public COMException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public COMException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public COMException(String message,int errorCode)
+ : base(message) {
+ SetErrorCode(errorCode);
+ }
+
+ [SecuritySafeCritical]
+ internal COMException(int hresult)
+ : base(Win32Native.GetMessage(hresult))
+ {
+ SetErrorCode(hresult);
+ }
+
+ internal COMException(String message, int hresult, Exception inner)
+ : base(message, inner)
+ {
+ SetErrorCode(hresult);
+ }
+
+ protected COMException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public override String ToString() {
+ String message = Message;
+ String s;
+ String _className = GetType().ToString();
+ s = _className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")";
+
+ if (!(message == null || message.Length <= 0)) {
+ s = s + ": " + message;
+ }
+
+ Exception _innerException = InnerException;
+
+ if (_innerException!=null) {
+ s = s + " ---> " + _innerException.ToString();
+ }
+
+
+ if (StackTrace != null)
+ s += Environment.NewLine + StackTrace;
+
+ return s;
+ }
+
+
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs b/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs
new file mode 100644
index 0000000000..cf4eb48af0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CallingConvention.cs
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices {
+
+ using System;
+ // Used for the CallingConvention named argument to the DllImport attribute
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum CallingConvention
+ {
+ Winapi = 1,
+ Cdecl = 2,
+ StdCall = 3,
+ ThisCall = 4,
+ FastCall = 5,
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs b/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs
new file mode 100644
index 0000000000..3c0710a558
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CharSet.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices {
+ using System;
+ // Use this in P/Direct function prototypes to specify
+ // which character set to use when marshalling Strings.
+ // Using Ansi will marshal the strings as 1 byte char*'s.
+ // Using Unicode will marshal the strings as 2 byte wchar*'s.
+ // Generally you probably want to use Auto, which does the
+ // right thing 99% of the time.
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum CharSet
+ {
+ None = 1, // User didn't specify how to marshal strings.
+ Ansi = 2, // Strings should be marshalled as ANSI 1 byte chars.
+ Unicode = 3, // Strings should be marshalled as Unicode 2 byte chars.
+ Auto = 4, // Marshal Strings in the right way for the target system.
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs
new file mode 100644
index 0000000000..0bf616d94c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsHelper.cs
@@ -0,0 +1,202 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+** Purpose: ComEventHelpers APIs allow binding
+** managed delegates to COM's connection point based events.
+**
+**/
+namespace System.Runtime.InteropServices {
+ //
+ // #ComEventsFeature
+ //
+ // code:#ComEventsFeature defines two public methods allowing to add/remove .NET delegates handling
+ // events from COM objects. Those methods are defined as part of code:ComEventsHelper static class
+ // * code:ComEventsHelper.Combine - will create/reuse-an-existing COM event sink and register the
+ // specified delegate to be raised when corresponding COM event is raised
+ // * code:ComEventsHelper.Remove
+ //
+ //
+ // To bind an event handler to the COM object you need to provide the following data:
+ // * rcw - the instance of the COM object you want to bind to
+ // * iid - Guid of the source interface you want the sink to implement
+ // * dispid - dispatch identifier of the event on the source interface you are interested in
+ // * d - delegate to invoked when corresponding COM event is raised.
+ //
+ // #ComEventsArchitecture:
+ // In COM world, events are handled by so-called event sinks. What these are? COM-based Object Models
+ // (OMs) define "source" interfaces that need to be implemented by the COM clients to receive events. So,
+ // event sinks are COM objects implementing a source interfaces. Once an event sink is passed to the COM
+ // server (through a mechanism known as 'binding/advising to connection point'), COM server will be
+ // calling source interface methods to "fire events" (advising, connection points, firing events etc. -
+ // is all COM jargon).
+ //
+ // There are few interesting obervations about source interfaces. Usually source interfaces are defined
+ // as 'dispinterface' - meaning that only late-bound invocations on this interface are allowed. Even
+ // though it is not illegal to use early bound invocations on source interfaces - the practice is
+ // discouraged because of versioning concerns.
+ //
+ // Notice also that each COM server object might define multiple source interfaces and hence have
+ // multiple connection points (each CP handles exactly one source interface). COM objects that want to
+ // fire events are required to implement IConnectionPointContainer interface which is used by the COM
+ // clients to discovery connection poitns - objects implementing IConnectionPoint interface. Once
+ // connection point is found - clients can bind to it using IConnectionPoint::Advise (see
+ // code:ComEventsSink.Advise).
+ //
+ // The idea behind code:#ComEventsFeature is to write a "universal event sink" COM component that is
+ // generic enough to handle all late-bound event firings and invoke corresponding COM delegates (through
+ // reflection).
+ //
+ // When delegate is registered (using code:ComEventsHelper.Combine) we will verify we have corresponding
+ // event sink created and bound.
+ //
+ // But what happens when COM events are fired? code:ComEventsSink.Invoke implements IDispatch::Invoke method
+ // and this is the entry point that is called. Once our event sink is invoked, we need to find the
+ // corresponding delegate to invoke . We need to match the dispid of the call that is coming in to a
+ // dispid of .NET delegate that has been registered for this object. Once this is found we do call the
+ // delegates using reflection (code:ComEventsMethod.Invoke).
+ //
+ // #ComEventsArgsMarshalling
+ // Notice, that we may not have a delegate registered against every method on the source interface. If we
+ // were to marshal all the input parameters for methods that do not reach user code - we would end up
+ // generatic RCWs that are not reachable for user code (the inconvenience it might create is there will
+ // be RCWs that users can not call Marshal.ReleaseComObject on to explicitly manage the lifetime of these
+ // COM objects). The above behavior was one of the shortcoimings of legacy TLBIMP's implementation of COM
+ // event sinking. In our code we will not marshal any data if there is no delegate registered to handle
+ // the event. (code:ComEventsMethod.Invoke)
+ //
+ // #ComEventsFinalization:
+ // Additional area of interest is when COM sink should be unadvised from the connection point. Legacy
+ // TLBIMP's implementation of COM event sinks will unadvises the sink when corresponding RCW is GCed.
+ // This is achieved by rooting the event sinks in a finalizable object stored in RCW's property bag
+ // (using Marshal.SetComObjectData). Hence, once RCW is no longer reachable - the finalizer is called and
+ // it would unadvise all the event sinks. We are employing the same strategy here. See storing an
+ // instance in the RCW at code:ComEventsInfo.FromObject and undadvsing the sinks at
+ // code:ComEventsInfo.~ComEventsInfo
+ //
+ // Classes of interest:
+ // * code:ComEventsHelpers - defines public methods but there are also a number of internal classes that
+ // implement the actual COM event sink:
+ // * code:ComEventsInfo - represents a finalizable container for all event sinks for a particular RCW.
+ // Lifetime of this instance corresponds to the lifetime of the RCW object
+ // * code:ComEventsSink - represents a single event sink. Maintains an internal pointer to the next
+ // instance (in a singly linked list). A collection of code:ComEventsSink is stored at
+ // code:ComEventsInfo._sinks
+ // * code:ComEventsMethod - represents a single method from the source interface which has .NET delegates
+ // attached to it. Maintains an internal pointer to the next instance (in a singly linked list). A
+ // collection of code:ComEventMethod is stored at code:ComEventsSink._methods
+ //
+ // #ComEventsRetValIssue:
+ // Issue: normally, COM events would not return any value. However, it may happen as described in
+ // http://support.microsoft.com/kb/810228. Such design might represent a problem for us - e.g. what is
+ // the return value of a chain of delegates - is it the value of the last call in the chain or the the
+ // first one? As the above KB article indicates, in cases where OM has events returning values, it is
+ // suggested that people implement their event sink by explicitly implementing the source interface. This
+ // means that the problem is already quite complex and we should not be dealing with it - see
+ // code:ComEventsMethod.Invoke
+
+ using System;
+ using System.Runtime.Remoting;
+
+ /// <summary>
+ /// The static methods provided in ComEventsHelper allow using .NET delegates to subscribe to events
+ /// raised COM objects.
+ /// </summary>
+ public static class ComEventsHelper {
+
+ /// <summary>
+ /// Adds a delegate to the invocation list of events originating from the COM object.
+ /// </summary>
+ /// <param name="rcw">COM object firing the events the caller would like to respond to</param>
+ /// <param name="iid">identifier of the source interface used by COM object to fire events</param>
+ /// <param name="dispid">dispatch identifier of the method on the source interface</param>
+ /// <param name="d">delegate to invoke when specifed COM event is fired</param>
+ [System.Security.SecurityCritical]
+ public static void Combine(object rcw, Guid iid, int dispid, System.Delegate d) {
+
+ rcw = UnwrapIfTransparentProxy(rcw);
+
+ lock (rcw) {
+ ComEventsInfo eventsInfo = ComEventsInfo.FromObject(rcw);
+
+ ComEventsSink sink = eventsInfo.FindSink(ref iid);
+ if (sink == null) {
+ sink = eventsInfo.AddSink(ref iid);
+ }
+
+
+ ComEventsMethod method = sink.FindMethod(dispid);
+ if (method == null) {
+ method = sink.AddMethod(dispid);
+ }
+
+ method.AddDelegate(d);
+ }
+ }
+
+ /// <summary>
+ /// Removes a delegate from the invocation list of events originating from the COM object.
+ /// </summary>
+ /// <param name="rcw">COM object the delegate is attached to</param>
+ /// <param name="iid">identifier of the source interface used by COM object to fire events</param>
+ /// <param name="dispid">dispatch identifier of the method on the source interface</param>
+ /// <param name="d">delegate to remove from the invocation list</param>
+ /// <returns></returns>
+ [System.Security.SecurityCritical]
+ public static Delegate Remove(object rcw, Guid iid, int dispid, System.Delegate d) {
+
+ rcw = UnwrapIfTransparentProxy(rcw);
+
+ lock (rcw) {
+
+ ComEventsInfo eventsInfo = ComEventsInfo.Find(rcw);
+ if (eventsInfo == null)
+ return null;
+ ComEventsSink sink = eventsInfo.FindSink(ref iid);
+ if (sink == null)
+ return null;
+ ComEventsMethod method = sink.FindMethod(dispid);
+ if (method == null)
+ return null;
+
+ method.RemoveDelegate(d);
+
+ if (method.Empty) {
+ // removed the last event handler for this dispid - need to remove dispid handler
+ method = sink.RemoveMethod(method);
+ }
+ if (method == null) {
+ // removed last dispid handler for this sink - need to remove the sink
+ sink = eventsInfo.RemoveSink(sink);
+ }
+ if (sink == null) {
+ // removed last sink for this rcw - need to remove all traces of event info
+ Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), null);
+ GC.SuppressFinalize(eventsInfo);
+ }
+
+ return d;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal static object UnwrapIfTransparentProxy(object rcw) {
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(rcw)) {
+ IntPtr punk = Marshal.GetIUnknownForObject(rcw);
+ try {
+ rcw = Marshal.GetObjectForIUnknown(punk);
+ } finally {
+ Marshal.Release(punk);
+ }
+ }
+#endif
+ return rcw;
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs
new file mode 100644
index 0000000000..6feb52445d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsInfo.cs
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+** Purpose: part of ComEventHelpers APIs which allow binding
+** managed delegates to COM's connection point based events.
+**
+**/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+ // see code:ComEventsHelper#ComEventsArchitecture
+ [System.Security.SecurityCritical]
+ internal class ComEventsInfo {
+
+
+#region fields
+
+ private ComEventsSink _sinks;
+ private object _rcw;
+
+#endregion
+
+
+#region ctor/dtor
+
+ ComEventsInfo(object rcw) {
+ _rcw = rcw;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ ~ComEventsInfo() {
+ // see code:ComEventsHelper#ComEventsFinalization
+ _sinks = ComEventsSink.RemoveAll(_sinks);
+ }
+
+#endregion
+
+
+#region static methods
+
+ [System.Security.SecurityCritical]
+ internal static ComEventsInfo Find(object rcw) {
+ return (ComEventsInfo)Marshal.GetComObjectData(rcw, typeof(ComEventsInfo));
+ }
+
+ // it is caller's responsibility to call this method under lock(rcw)
+ [System.Security.SecurityCritical]
+ internal static ComEventsInfo FromObject(object rcw) {
+ ComEventsInfo eventsInfo = Find(rcw);
+ if (eventsInfo == null) {
+ eventsInfo = new ComEventsInfo(rcw);
+ Marshal.SetComObjectData(rcw, typeof(ComEventsInfo), eventsInfo);
+ }
+ return eventsInfo;
+ }
+
+#endregion
+
+
+#region internal methods
+
+ internal ComEventsSink FindSink(ref Guid iid) {
+ return ComEventsSink.Find(_sinks, ref iid);
+ }
+
+ // it is caller's responsibility to call this method under lock(rcw)
+ internal ComEventsSink AddSink(ref Guid iid) {
+ ComEventsSink sink = new ComEventsSink(_rcw, iid);
+ _sinks = ComEventsSink.Add(_sinks, sink);
+
+ return _sinks;
+ }
+
+ // it is caller's responsibility to call this method under lock(rcw)
+ [System.Security.SecurityCritical]
+ internal ComEventsSink RemoveSink(ComEventsSink sink) {
+ _sinks = ComEventsSink.Remove(_sinks, sink);
+ return _sinks;
+ }
+
+#endregion
+
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs
new file mode 100644
index 0000000000..2da0c5eea3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsMethod.cs
@@ -0,0 +1,246 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+** Purpose: part of ComEventHelpers APIs which allow binding
+** managed delegates to COM's connection point based events.
+**
+**/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Reflection;
+
+
+namespace System.Runtime.InteropServices {
+
+ // see code:ComEventsHelper#ComEventsArchitecture
+ internal class ComEventsMethod {
+
+ // This delegate wrapper class handles dynamic invocation of delegates. The reason for the wrapper's
+ // existence is that under certain circumstances we need to coerce arguments to types expected by the
+ // delegates signature. Normally, reflection (Delegate.DynamicInvoke) handles types coercion
+ // correctly but one known case is when the expected signature is 'ref Enum' - in this case
+ // reflection by design does not do the coercion. Since we need to be compatible with COM interop
+ // handling of this scenario - we are pre-processing delegate's signature by looking for 'ref enums'
+ // and cache the types required for such coercion.
+ internal class DelegateWrapper {
+ private Delegate _d;
+
+ private bool _once = false;
+ private int _expectedParamsCount;
+ private Type[] _cachedTargetTypes;
+
+ public DelegateWrapper(Delegate d) {
+ _d = d;
+ }
+
+ public Delegate Delegate {
+ get { return _d; }
+ set { _d = value; }
+ }
+
+ public object Invoke(object[] args) {
+ if (_d == null)
+ return null;
+
+ if (_once == false) {
+ PreProcessSignature();
+ _once = true;
+ }
+
+ if (_cachedTargetTypes != null && _expectedParamsCount == args.Length) {
+ for (int i = 0; i < _expectedParamsCount; i++) {
+ if (_cachedTargetTypes[i] != null) {
+ args[i] = Enum.ToObject(_cachedTargetTypes[i], args[i]);
+ }
+ }
+ }
+
+ return _d.DynamicInvoke(args);
+ }
+
+ private void PreProcessSignature() {
+ ParameterInfo[] parameters = _d.Method.GetParameters();
+ _expectedParamsCount = parameters.Length;
+
+ Type[] enumTypes = new Type[_expectedParamsCount];
+
+ bool needToHandleCoercion = false;
+
+ for (int i = 0; i < _expectedParamsCount; i++) {
+ ParameterInfo pi = parameters[i];
+ // recognize only 'ref Enum' signatures and cache
+ // both enum type and the underlying type.
+ if (pi.ParameterType.IsByRef &&
+ pi.ParameterType.HasElementType &&
+ pi.ParameterType.GetElementType().IsEnum) {
+
+ needToHandleCoercion = true;
+ enumTypes[i] = pi.ParameterType.GetElementType();
+ }
+ }
+
+ if (needToHandleCoercion == true) {
+ _cachedTargetTypes = enumTypes;
+ }
+ }
+ }
+
+ #region private fields
+
+ /// <summary>
+ /// Invoking ComEventsMethod means invoking a multi-cast delegate attached to it.
+ /// Since multicast delegate's built-in chaining supports only chaining instances of the same type,
+ /// we need to complement this design by using an explicit linked list data structure.
+ /// </summary>
+ private DelegateWrapper [] _delegateWrappers;
+
+ private int _dispid;
+ private ComEventsMethod _next;
+
+ #endregion
+
+
+ #region ctor
+
+ internal ComEventsMethod(int dispid) {
+ _delegateWrappers = null;
+ _dispid = dispid;
+ }
+
+ #endregion
+
+
+ #region static internal methods
+
+ internal static ComEventsMethod Find(ComEventsMethod methods, int dispid) {
+ while (methods != null && methods._dispid != dispid) {
+ methods = methods._next;
+ }
+ return methods;
+ }
+
+ internal static ComEventsMethod Add(ComEventsMethod methods, ComEventsMethod method) {
+ method._next = methods;
+ return method;
+ }
+
+ internal static ComEventsMethod Remove(ComEventsMethod methods, ComEventsMethod method) {
+ if (methods == method) {
+ methods = methods._next;
+ } else {
+ ComEventsMethod current = methods;
+ while (current != null && current._next != method)
+ current = current._next;
+ if (current != null)
+ current._next = method._next;
+ }
+
+ return methods;
+ }
+
+ #endregion
+
+
+ #region public properties / methods
+
+ internal int DispId {
+ get { return _dispid; }
+ }
+
+ internal bool Empty {
+ get { return _delegateWrappers == null || _delegateWrappers.Length == 0; }
+ }
+
+ internal void AddDelegate(Delegate d) {
+ int count = 0;
+ if (_delegateWrappers != null) {
+ count = _delegateWrappers.Length;
+ }
+
+ for (int i = 0; i < count; i++) {
+ if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) {
+ _delegateWrappers[i].Delegate = Delegate.Combine(_delegateWrappers[i].Delegate, d);
+ return;
+ }
+ }
+
+ DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count + 1];
+ if (count > 0) {
+ _delegateWrappers.CopyTo(newDelegateWrappers, 0);
+ }
+
+ DelegateWrapper wrapper = new DelegateWrapper(d);
+ newDelegateWrappers[count] = wrapper;
+
+ _delegateWrappers = newDelegateWrappers;
+ }
+
+ internal void RemoveDelegate(Delegate d) {
+
+ int count = _delegateWrappers.Length;
+ int removeIdx = -1;
+
+ for (int i = 0; i < count; i++) {
+ if (_delegateWrappers[i].Delegate.GetType() == d.GetType()) {
+ removeIdx = i;
+ break;
+ }
+ }
+
+ if (removeIdx < 0)
+ return;
+
+ Delegate newDelegate = Delegate.Remove(_delegateWrappers[removeIdx].Delegate, d);
+ if (newDelegate != null) {
+ _delegateWrappers[removeIdx].Delegate = newDelegate;
+ return;
+ }
+
+ // now remove the found entry from the _delegates array
+
+ if (count == 1) {
+ _delegateWrappers = null;
+ return;
+ }
+
+ DelegateWrapper [] newDelegateWrappers = new DelegateWrapper[count - 1];
+ int j = 0;
+ while (j < removeIdx) {
+ newDelegateWrappers[j] = _delegateWrappers[j];
+ j++;
+ }
+ while (j < count-1) {
+ newDelegateWrappers[j] = _delegateWrappers[j + 1];
+ j++;
+ }
+
+ _delegateWrappers = newDelegateWrappers;
+ }
+
+ internal object Invoke(object[] args) {
+ BCLDebug.Assert(Empty == false, "event sink is executed but delegates list is empty");
+
+ // Issue: see code:ComEventsHelper#ComEventsRetValIssue
+ object result = null;
+ DelegateWrapper[] invocationList = _delegateWrappers;
+ foreach (DelegateWrapper wrapper in invocationList) {
+ if (wrapper == null || wrapper.Delegate == null)
+ continue;
+
+ result = wrapper.Invoke(args);
+ }
+
+ return result;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs
new file mode 100644
index 0000000000..a414eff3a1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComEventsSink.cs
@@ -0,0 +1,286 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+** Purpose: part of ComEventHelpers APIs which allow binding
+** managed delegates to COM's connection point based events.
+**
+**/
+
+namespace System.Runtime.InteropServices {
+ using System;
+ using System.Diagnostics;
+
+ // see code:ComEventsHelper#ComEventsArchitecture
+ [System.Security.SecurityCritical]
+ internal class ComEventsSink : NativeMethods.IDispatch, ICustomQueryInterface
+ {
+#region private fields
+
+ private Guid _iidSourceItf;
+ private ComTypes.IConnectionPoint _connectionPoint;
+ private int _cookie;
+ private ComEventsMethod _methods;
+ private ComEventsSink _next;
+
+#endregion
+
+
+#region ctor
+
+ internal ComEventsSink(object rcw, Guid iid) {
+ _iidSourceItf = iid;
+ this.Advise(rcw);
+ }
+
+#endregion
+
+
+#region static members
+
+ internal static ComEventsSink Find(ComEventsSink sinks, ref Guid iid) {
+
+ ComEventsSink sink = sinks;
+ while (sink != null && sink._iidSourceItf != iid) {
+ sink = sink._next;
+ }
+
+ return sink;
+ }
+
+ internal static ComEventsSink Add(ComEventsSink sinks, ComEventsSink sink) {
+ sink._next = sinks;
+ return sink;
+ }
+
+ [System.Security.SecurityCritical]
+ internal static ComEventsSink RemoveAll(ComEventsSink sinks) {
+ while (sinks != null) {
+ sinks.Unadvise();
+ sinks = sinks._next;
+ }
+
+ return null;
+ }
+
+ [System.Security.SecurityCritical]
+ internal static ComEventsSink Remove(ComEventsSink sinks, ComEventsSink sink) {
+ BCLDebug.Assert(sinks != null, "removing event sink from empty sinks collection");
+ BCLDebug.Assert(sink != null, "specify event sink is null");
+
+ if (sink == sinks) {
+ sinks = sinks._next;
+ } else {
+ ComEventsSink current = sinks;
+ while (current != null && current._next != sink)
+ current = current._next;
+
+ if (current != null) {
+ current._next = sink._next;
+ }
+ }
+
+ sink.Unadvise();
+
+ return sinks;
+ }
+
+#endregion
+
+
+#region public methods
+
+ public ComEventsMethod RemoveMethod(ComEventsMethod method) {
+ _methods = ComEventsMethod.Remove(_methods, method);
+ return _methods;
+ }
+
+ public ComEventsMethod FindMethod(int dispid) {
+ return ComEventsMethod.Find(_methods, dispid);
+ }
+
+ public ComEventsMethod AddMethod(int dispid) {
+ ComEventsMethod method = new ComEventsMethod(dispid);
+ _methods = ComEventsMethod.Add(_methods, method);
+ return method;
+ }
+
+#endregion
+
+
+#region IDispatch Members
+
+ [System.Security.SecurityCritical]
+ void NativeMethods.IDispatch.GetTypeInfoCount(out uint pctinfo) {
+ pctinfo = 0;
+ }
+
+ [System.Security.SecurityCritical]
+ void NativeMethods.IDispatch.GetTypeInfo(uint iTInfo, int lcid, out IntPtr info) {
+ throw new NotImplementedException();
+ }
+
+ [System.Security.SecurityCritical]
+ void NativeMethods.IDispatch.GetIDsOfNames(ref Guid iid, string[] names, uint cNames, int lcid, int[] rgDispId) {
+ throw new NotImplementedException();
+ }
+
+ private const VarEnum VT_BYREF_VARIANT = VarEnum.VT_BYREF | VarEnum.VT_VARIANT;
+ private const VarEnum VT_TYPEMASK = (VarEnum) 0x0fff;
+ private const VarEnum VT_BYREF_TYPEMASK = VT_TYPEMASK | VarEnum.VT_BYREF;
+
+ private static unsafe Variant *GetVariant(Variant *pSrc)
+ {
+ if (pSrc->VariantType == VT_BYREF_VARIANT)
+ {
+ // For VB6 compatibility reasons, if the VARIANT is a VT_BYREF | VT_VARIANT that
+ // contains another VARIANT with VT_BYREF | VT_VARIANT, then we need to extract the
+ // inner VARIANT and use it instead of the outer one. Note that if the inner VARIANT
+ // is VT_BYREF | VT_VARIANT | VT_ARRAY, it will pass the below test too.
+ Variant *pByRefVariant = (Variant *)pSrc->AsByRefVariant;
+ if ((pByRefVariant->VariantType & VT_BYREF_TYPEMASK) == VT_BYREF_VARIANT)
+ return (Variant *)pByRefVariant;
+ }
+
+ return pSrc;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe void NativeMethods.IDispatch.Invoke(
+ int dispid,
+ ref Guid riid,
+ int lcid,
+ ComTypes.INVOKEKIND wFlags,
+ ref ComTypes.DISPPARAMS pDispParams,
+ IntPtr pvarResult,
+ IntPtr pExcepInfo,
+ IntPtr puArgErr) {
+
+ ComEventsMethod method = FindMethod(dispid);
+ if (method == null)
+ return;
+
+ // notice the unsafe pointers we are using. This is to avoid unnecessary
+ // arguments marshalling. see code:ComEventsHelper#ComEventsArgsMarshalling
+
+ object [] args = new object[pDispParams.cArgs];
+ int [] byrefsMap = new int[pDispParams.cArgs];
+ bool [] usedArgs = new bool[pDispParams.cArgs];
+
+ Variant* pvars = (Variant*)pDispParams.rgvarg;
+ int* pNamedArgs = (int*)pDispParams.rgdispidNamedArgs;
+
+ // copy the named args (positional) as specified
+ int i;
+ int pos;
+ for (i = 0; i < pDispParams.cNamedArgs; i++) {
+ pos = pNamedArgs[i];
+
+ Variant* pvar = GetVariant(&pvars[i]);
+ args[pos] = pvar->ToObject();
+ usedArgs[pos] = true;
+
+ if (pvar->IsByRef) {
+ byrefsMap[pos] = i;
+ } else {
+ byrefsMap[pos] = -1;
+ }
+ }
+
+ // copy the rest of the arguments in the reverse order
+ pos = 0;
+ for (; i < pDispParams.cArgs; i++) {
+ // find the next unassigned argument
+ while (usedArgs[pos]) {
+ ++pos;
+ }
+
+ Variant* pvar = GetVariant(&pvars[pDispParams.cArgs - 1 - i]);
+ args[pos] = pvar->ToObject();
+
+ if (pvar->IsByRef)
+ byrefsMap[pos] = pDispParams.cArgs - 1 - i;
+ else
+ byrefsMap[pos] = -1;
+
+ pos++;
+ }
+
+ // Do the actual delegate invocation
+ object result;
+ result = method.Invoke(args);
+
+ // convert result to VARIANT
+ if (pvarResult != IntPtr.Zero) {
+ Marshal.GetNativeVariantForObject(result, pvarResult);
+ }
+
+ // Now we need to marshal all the byrefs back
+ for (i = 0; i < pDispParams.cArgs; i++) {
+ int idxToPos = byrefsMap[i];
+ if (idxToPos == -1)
+ continue;
+
+ GetVariant(&pvars[idxToPos])->CopyFromIndirect(args[i]);
+ }
+ }
+
+#endregion
+
+ static Guid IID_IManagedObject = new Guid("{C3FCC19E-A970-11D2-8B5A-00A0C9B7C9C4}");
+
+ [System.Security.SecurityCritical]
+ CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out IntPtr ppv) {
+ ppv = IntPtr.Zero;
+ if (iid == this._iidSourceItf || iid == typeof(NativeMethods.IDispatch).GUID) {
+ ppv = Marshal.GetComInterfaceForObject(this, typeof(NativeMethods.IDispatch), CustomQueryInterfaceMode.Ignore);
+ return CustomQueryInterfaceResult.Handled;
+ }
+ else if (iid == IID_IManagedObject)
+ {
+ return CustomQueryInterfaceResult.Failed;
+ }
+
+ return CustomQueryInterfaceResult.NotHandled;
+ }
+
+#region private methods
+
+
+ private void Advise(object rcw) {
+ BCLDebug.Assert(_connectionPoint == null, "comevent sink is already advised");
+
+ ComTypes.IConnectionPointContainer cpc = (ComTypes.IConnectionPointContainer)rcw;
+ ComTypes.IConnectionPoint cp;
+ cpc.FindConnectionPoint(ref _iidSourceItf, out cp);
+
+ object sinkObject = this;
+
+ cp.Advise(sinkObject, out _cookie);
+
+ _connectionPoint = cp;
+ }
+
+ [System.Security.SecurityCritical]
+ private void Unadvise() {
+ BCLDebug.Assert(_connectionPoint != null, "can not unadvise from empty connection point");
+
+ try {
+ _connectionPoint.Unadvise(_cookie);
+ Marshal.ReleaseComObject(_connectionPoint);
+ } catch (System.Exception) {
+ // swallow all exceptions on unadvise
+ // the host may not be available at this point
+ } finally {
+ _connectionPoint = null;
+ }
+
+ }
+
+#endregion
+ };
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs
new file mode 100644
index 0000000000..3be2a56da5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComMemberType.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ComMemberType
+ {
+ Method = 0,
+ PropGet = 1,
+ PropSet = 2
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs
new file mode 100644
index 0000000000..aac3f59d0f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IBindCtx.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IBindCtx interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct BIND_OPTS
+ {
+ public int cbStruct;
+ public int grfFlags;
+ public int grfMode;
+ public int dwTickCountDeadline;
+ }
+
+ [Guid("0000000e-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IBindCtx
+ {
+ void RegisterObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
+ void RevokeObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
+ void ReleaseBoundObjects();
+ void SetBindOptions([In()] ref BIND_OPTS pbindopts);
+ void GetBindOptions(ref BIND_OPTS pbindopts);
+ void GetRunningObjectTable(out IRunningObjectTable pprot);
+ void RegisterObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] Object punk);
+ void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] out Object ppunk);
+ void EnumObjectParam(out IEnumString ppenum);
+ [PreserveSig]
+ int RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs
new file mode 100644
index 0000000000..f70973e60d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPoint.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IConnectionPoint interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("B196B286-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IConnectionPoint
+ {
+ void GetConnectionInterface(out Guid pIID);
+ void GetConnectionPointContainer(out IConnectionPointContainer ppCPC);
+ void Advise([MarshalAs(UnmanagedType.Interface)] Object pUnkSink, out int pdwCookie);
+ void Unadvise(int dwCookie);
+ void EnumConnections(out IEnumConnections ppEnum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs
new file mode 100644
index 0000000000..fffff3c170
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IConnectionPointContainer.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IConnectionPointContainer interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("B196B284-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IConnectionPointContainer
+ {
+ void EnumConnectionPoints(out IEnumConnectionPoints ppEnum);
+ void FindConnectionPoint([In] ref Guid riid, out IConnectionPoint ppCP);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs
new file mode 100644
index 0000000000..d667925b7e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnectionPoints.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IEnumConnectionPoints interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("B196B285-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IEnumConnectionPoints
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IConnectionPoint[] rgelt, IntPtr pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ void Reset();
+ void Clone(out IEnumConnectionPoints ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs
new file mode 100644
index 0000000000..8a2b4f0e6f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumConnections.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IEnumConnections interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct CONNECTDATA
+ {
+ [MarshalAs(UnmanagedType.Interface)]
+ public Object pUnk;
+ public int dwCookie;
+ }
+
+ [Guid("B196B287-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IEnumConnections
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] CONNECTDATA[] rgelt, IntPtr pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ void Reset();
+ void Clone(out IEnumConnections ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs
new file mode 100644
index 0000000000..57994b66bc
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumMoniker.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IEnumMoniker interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00000102-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IEnumMoniker
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] IMoniker[] rgelt, IntPtr pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ void Reset();
+ void Clone(out IEnumMoniker ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs
new file mode 100644
index 0000000000..f1e9233581
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumString.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IEnumString interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00000101-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IEnumString
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0), Out] String[] rgelt, IntPtr pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ void Reset();
+ void Clone(out IEnumString ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs
new file mode 100644
index 0000000000..ea9b74b7c1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumVARIANT.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IEnumVARIANT interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00020404-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IEnumVARIANT
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0), Out] object[] rgVar, IntPtr pceltFetched);
+
+ [PreserveSig]
+ int Skip(int celt);
+
+ [PreserveSig]
+ int Reset();
+
+ IEnumVARIANT Clone();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs
new file mode 100644
index 0000000000..1a13399a88
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: IEnumerable
+**
+**
+** Purpose:
+** This interface is redefined here since the original IEnumerable interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IEnumerable interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
+ internal interface IEnumerable
+ {
+ [DispId(-4)]
+ System.Collections.IEnumerator GetEnumerator();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs
new file mode 100644
index 0000000000..aea2017b1e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IEnumerator.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: IEnumerator
+**
+**
+** Purpose:
+** This interface is redefined here since the original IEnumerator interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IEnumerator interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
+ internal interface IEnumerator
+ {
+ bool MoveNext();
+
+ Object Current
+ {
+ get;
+ }
+
+ void Reset();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs
new file mode 100644
index 0000000000..ad4ed0b8be
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IExpando.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: IExpando
+**
+**
+** Purpose:
+** This interface is redefined here since the original IExpando interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IExpando interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+ using System.Reflection;
+
+ [Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")]
+ internal interface IExpando : IReflect
+ {
+ FieldInfo AddField(String name);
+ PropertyInfo AddProperty(String name);
+ MethodInfo AddMethod(String name, Delegate method);
+ void RemoveMember(MemberInfo m);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs
new file mode 100644
index 0000000000..caee5e7fa3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IMoniker.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IMoniker interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct FILETIME
+ {
+ public int dwLowDateTime;
+ public int dwHighDateTime;
+ }
+
+ [Guid("0000000f-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IMoniker
+ {
+ // IPersist portion
+ void GetClassID(out Guid pClassID);
+
+ // IPersistStream portion
+ [PreserveSig]
+ int IsDirty();
+ void Load(IStream pStm);
+ void Save(IStream pStm, [MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
+ void GetSizeMax(out Int64 pcbSize);
+
+ // IMoniker portion
+ void BindToObject(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
+ void BindToStorage(IBindCtx pbc, IMoniker pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out Object ppvObj);
+ void Reduce(IBindCtx pbc, int dwReduceHowFar, ref IMoniker ppmkToLeft, out IMoniker ppmkReduced);
+ void ComposeWith(IMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out IMoniker ppmkComposite);
+ void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out IEnumMoniker ppenumMoniker);
+ [PreserveSig]
+ int IsEqual(IMoniker pmkOtherMoniker);
+ void Hash(out int pdwHash);
+ [PreserveSig]
+ int IsRunning(IBindCtx pbc, IMoniker pmkToLeft, IMoniker pmkNewlyRunning);
+ void GetTimeOfLastChange(IBindCtx pbc, IMoniker pmkToLeft, out FILETIME pFileTime);
+ void Inverse(out IMoniker ppmk);
+ void CommonPrefixWith(IMoniker pmkOther, out IMoniker ppmkPrefix);
+ void RelativePathTo(IMoniker pmkOther, out IMoniker ppmkRelPath);
+ void GetDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out String ppszDisplayName);
+ void ParseDisplayName(IBindCtx pbc, IMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] String pszDisplayName, out int pchEaten, out IMoniker ppmkOut);
+ [PreserveSig]
+ int IsSystemMoniker(out int pdwMksys);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs
new file mode 100644
index 0000000000..a9f118a354
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IPersistFile.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IPersistFile interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("0000010b-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IPersistFile
+ {
+ // IPersist portion
+ void GetClassID(out Guid pClassID);
+
+ // IPersistFile portion
+ [PreserveSig]
+ int IsDirty();
+ void Load([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, int dwMode);
+ void Save([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember);
+ void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] String pszFileName);
+ void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out String ppszFileName);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs
new file mode 100644
index 0000000000..c86f961d01
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IReflect.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: IReflect
+**
+**
+** Purpose:
+** This interface is redefined here since the original IReflect interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IReflect interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+ using System.Reflection;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Guid("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")]
+ internal interface IReflect
+ {
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr,Binder binder,
+ Type[] types,ParameterModifier[] modifiers);
+
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr);
+
+ MethodInfo[] GetMethods(
+ BindingFlags bindingAttr);
+
+ FieldInfo GetField(
+ String name,
+ BindingFlags bindingAttr);
+
+ FieldInfo[] GetFields(
+ BindingFlags bindingAttr);
+
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr);
+
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type returnType,
+ Type[] types,
+ ParameterModifier[] modifiers);
+
+ PropertyInfo[] GetProperties(
+ BindingFlags bindingAttr);
+
+ MemberInfo[] GetMember(
+ String name,
+ BindingFlags bindingAttr);
+
+ MemberInfo[] GetMembers(
+ BindingFlags bindingAttr);
+
+ Object InvokeMember(
+ String name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ Object target,
+ Object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ String[] namedParameters);
+
+ Type UnderlyingSystemType
+ {
+ get;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs
new file mode 100644
index 0000000000..bebbdec70c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IRunningObjectTable.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IRunningObjectTable interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00000010-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IRunningObjectTable
+ {
+ int Register(int grfFlags, [MarshalAs(UnmanagedType.Interface)] Object punkObject, IMoniker pmkObjectName);
+ void Revoke(int dwRegister);
+ [PreserveSig]
+ int IsRunning(IMoniker pmkObjectName);
+ [PreserveSig]
+ int GetObject(IMoniker pmkObjectName, [MarshalAs(UnmanagedType.Interface)] out Object ppunkObject);
+ void NoteChangeTime(int dwRegister, ref FILETIME pfiletime);
+ [PreserveSig]
+ int GetTimeOfLastChange(IMoniker pmkObjectName, out FILETIME pfiletime);
+ void EnumRunning(out IEnumMoniker ppenumMoniker);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs
new file mode 100644
index 0000000000..616ecbfa18
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/IStream.cs
@@ -0,0 +1,55 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: IStream interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct STATSTG
+ {
+ public String pwcsName;
+ public int type;
+ public Int64 cbSize;
+ public FILETIME mtime;
+ public FILETIME ctime;
+ public FILETIME atime;
+ public int grfMode;
+ public int grfLocksSupported;
+ public Guid clsid;
+ public int grfStateBits;
+ public int reserved;
+ }
+
+ [Guid("0000000c-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface IStream
+ {
+ // ISequentialStream portion
+ void Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] Byte[] pv, int cb, IntPtr pcbRead);
+ void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] pv, int cb, IntPtr pcbWritten);
+
+ // IStream portion
+ void Seek(Int64 dlibMove, int dwOrigin, IntPtr plibNewPosition);
+ void SetSize(Int64 libNewSize);
+ void CopyTo(IStream pstm, Int64 cb, IntPtr pcbRead, IntPtr pcbWritten);
+ void Commit(int grfCommitFlags);
+ void Revert();
+ void LockRegion(Int64 libOffset, Int64 cb, int dwLockType);
+ void UnlockRegion(Int64 libOffset, Int64 cb, int dwLockType);
+ void Stat(out STATSTG pstatstg, int grfStatFlag);
+ void Clone(out IStream ppstm);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs
new file mode 100644
index 0000000000..f938ba91a7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeComp.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: ITypeComp interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Serializable]
+ public enum DESCKIND
+ {
+ DESCKIND_NONE = 0,
+ DESCKIND_FUNCDESC = DESCKIND_NONE + 1,
+ DESCKIND_VARDESC = DESCKIND_FUNCDESC + 1,
+ DESCKIND_TYPECOMP = DESCKIND_VARDESC + 1,
+ DESCKIND_IMPLICITAPPOBJ = DESCKIND_TYPECOMP + 1,
+ DESCKIND_MAX = DESCKIND_IMPLICITAPPOBJ + 1
+ }
+
+ [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+
+ public struct BINDPTR
+ {
+ [FieldOffset(0)]
+ public IntPtr lpfuncdesc;
+ [FieldOffset(0)]
+ public IntPtr lpvardesc;
+ [FieldOffset(0)]
+ public IntPtr lptcomp;
+ }
+
+ [Guid("00020403-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface ITypeComp
+ {
+ void Bind([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, Int16 wFlags, out ITypeInfo ppTInfo, out DESCKIND pDescKind, out BINDPTR pBindPtr);
+ void BindType([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, out ITypeInfo ppTInfo, out ITypeComp ppTComp);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs
new file mode 100644
index 0000000000..7a12605f20
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo.cs
@@ -0,0 +1,335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: ITypeInfo interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Serializable]
+ public enum TYPEKIND
+ {
+ TKIND_ENUM = 0,
+ TKIND_RECORD = TKIND_ENUM + 1,
+ TKIND_MODULE = TKIND_RECORD + 1,
+ TKIND_INTERFACE = TKIND_MODULE + 1,
+ TKIND_DISPATCH = TKIND_INTERFACE + 1,
+ TKIND_COCLASS = TKIND_DISPATCH + 1,
+ TKIND_ALIAS = TKIND_COCLASS + 1,
+ TKIND_UNION = TKIND_ALIAS + 1,
+ TKIND_MAX = TKIND_UNION + 1
+ }
+
+[Serializable]
+[Flags()]
+ public enum TYPEFLAGS : short
+ {
+ TYPEFLAG_FAPPOBJECT = 0x1,
+ TYPEFLAG_FCANCREATE = 0x2,
+ TYPEFLAG_FLICENSED = 0x4,
+ TYPEFLAG_FPREDECLID = 0x8,
+ TYPEFLAG_FHIDDEN = 0x10,
+ TYPEFLAG_FCONTROL = 0x20,
+ TYPEFLAG_FDUAL = 0x40,
+ TYPEFLAG_FNONEXTENSIBLE = 0x80,
+ TYPEFLAG_FOLEAUTOMATION = 0x100,
+ TYPEFLAG_FRESTRICTED = 0x200,
+ TYPEFLAG_FAGGREGATABLE = 0x400,
+ TYPEFLAG_FREPLACEABLE = 0x800,
+ TYPEFLAG_FDISPATCHABLE = 0x1000,
+ TYPEFLAG_FREVERSEBIND = 0x2000,
+ TYPEFLAG_FPROXY = 0x4000
+ }
+
+[Serializable]
+[Flags()]
+ public enum IMPLTYPEFLAGS
+ {
+ IMPLTYPEFLAG_FDEFAULT = 0x1,
+ IMPLTYPEFLAG_FSOURCE = 0x2,
+ IMPLTYPEFLAG_FRESTRICTED = 0x4,
+ IMPLTYPEFLAG_FDEFAULTVTABLE = 0x8,
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct TYPEATTR
+ {
+ // Constant used with the memid fields.
+ public const int MEMBER_ID_NIL = unchecked((int)0xFFFFFFFF);
+
+ // Actual fields of the TypeAttr struct.
+ public Guid guid;
+ public Int32 lcid;
+ public Int32 dwReserved;
+ public Int32 memidConstructor;
+ public Int32 memidDestructor;
+ public IntPtr lpstrSchema;
+ public Int32 cbSizeInstance;
+ public TYPEKIND typekind;
+ public Int16 cFuncs;
+ public Int16 cVars;
+ public Int16 cImplTypes;
+ public Int16 cbSizeVft;
+ public Int16 cbAlignment;
+ public TYPEFLAGS wTypeFlags;
+ public Int16 wMajorVerNum;
+ public Int16 wMinorVerNum;
+ public TYPEDESC tdescAlias;
+ public IDLDESC idldescType;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct FUNCDESC
+ {
+ public int memid; //MEMBERID memid;
+ public IntPtr lprgscode; // /* [size_is(cScodes)] */ SCODE RPC_FAR *lprgscode;
+ public IntPtr lprgelemdescParam; // /* [size_is(cParams)] */ ELEMDESC __RPC_FAR *lprgelemdescParam;
+ public FUNCKIND funckind; //FUNCKIND funckind;
+ public INVOKEKIND invkind; //INVOKEKIND invkind;
+ public CALLCONV callconv; //CALLCONV callconv;
+ public Int16 cParams; //short cParams;
+ public Int16 cParamsOpt; //short cParamsOpt;
+ public Int16 oVft; //short oVft;
+ public Int16 cScodes; //short cScodes;
+ public ELEMDESC elemdescFunc; //ELEMDESC elemdescFunc;
+ public Int16 wFuncFlags; //WORD wFuncFlags;
+ }
+
+[Serializable]
+[Flags()]
+ public enum IDLFLAG : short
+ {
+ IDLFLAG_NONE = PARAMFLAG.PARAMFLAG_NONE,
+ IDLFLAG_FIN = PARAMFLAG.PARAMFLAG_FIN,
+ IDLFLAG_FOUT = PARAMFLAG.PARAMFLAG_FOUT,
+ IDLFLAG_FLCID = PARAMFLAG.PARAMFLAG_FLCID,
+ IDLFLAG_FRETVAL = PARAMFLAG.PARAMFLAG_FRETVAL
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct IDLDESC
+ {
+ public IntPtr dwReserved;
+ public IDLFLAG wIDLFlags;
+ }
+
+[Serializable]
+[Flags()]
+ public enum PARAMFLAG :short
+ {
+ PARAMFLAG_NONE = 0,
+ PARAMFLAG_FIN = 0x1,
+ PARAMFLAG_FOUT = 0x2,
+ PARAMFLAG_FLCID = 0x4,
+ PARAMFLAG_FRETVAL = 0x8,
+ PARAMFLAG_FOPT = 0x10,
+ PARAMFLAG_FHASDEFAULT = 0x20,
+ PARAMFLAG_FHASCUSTDATA = 0x40
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct PARAMDESC
+ {
+ public IntPtr lpVarValue;
+ public PARAMFLAG wParamFlags;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct TYPEDESC
+ {
+ public IntPtr lpValue;
+ public Int16 vt;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct ELEMDESC
+ {
+ public TYPEDESC tdesc;
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+
+ public struct DESCUNION
+ {
+ [FieldOffset(0)]
+ public IDLDESC idldesc;
+ [FieldOffset(0)]
+ public PARAMDESC paramdesc;
+ };
+ public DESCUNION desc;
+ }
+
+ [Serializable]
+ public enum VARKIND : int
+ {
+ VAR_PERINSTANCE = 0x0,
+ VAR_STATIC = 0x1,
+ VAR_CONST = 0x2,
+ VAR_DISPATCH = 0x3
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct VARDESC
+ {
+ public int memid;
+ public String lpstrSchema;
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+
+ public struct DESCUNION
+ {
+ [FieldOffset(0)]
+ public int oInst;
+ [FieldOffset(0)]
+ public IntPtr lpvarValue;
+ };
+
+ public DESCUNION desc;
+
+ public ELEMDESC elemdescVar;
+ public short wVarFlags;
+ public VARKIND varkind;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct DISPPARAMS
+ {
+ public IntPtr rgvarg;
+ public IntPtr rgdispidNamedArgs;
+ public int cArgs;
+ public int cNamedArgs;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct EXCEPINFO
+ {
+ public Int16 wCode;
+ public Int16 wReserved;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrSource;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrDescription;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrHelpFile;
+ public int dwHelpContext;
+ public IntPtr pvReserved;
+ public IntPtr pfnDeferredFillIn;
+ public Int32 scode;
+ }
+
+ [Serializable]
+ public enum FUNCKIND : int
+ {
+ FUNC_VIRTUAL = 0,
+ FUNC_PUREVIRTUAL = 1,
+ FUNC_NONVIRTUAL = 2,
+ FUNC_STATIC = 3,
+ FUNC_DISPATCH = 4
+ }
+
+[Serializable]
+[Flags]
+ public enum INVOKEKIND : int
+ {
+ INVOKE_FUNC = 0x1,
+ INVOKE_PROPERTYGET = 0x2,
+ INVOKE_PROPERTYPUT = 0x4,
+ INVOKE_PROPERTYPUTREF = 0x8
+ }
+
+ [Serializable]
+ public enum CALLCONV : int
+ {
+ CC_CDECL =1,
+ CC_MSCPASCAL=2,
+ CC_PASCAL =CC_MSCPASCAL,
+ CC_MACPASCAL=3,
+ CC_STDCALL =4,
+ CC_RESERVED =5,
+ CC_SYSCALL =6,
+ CC_MPWCDECL =7,
+ CC_MPWPASCAL=8,
+ CC_MAX =9
+ }
+
+[Serializable]
+[Flags()]
+ public enum FUNCFLAGS : short
+ {
+ FUNCFLAG_FRESTRICTED= 0x1,
+ FUNCFLAG_FSOURCE = 0x2,
+ FUNCFLAG_FBINDABLE = 0x4,
+ FUNCFLAG_FREQUESTEDIT = 0x8,
+ FUNCFLAG_FDISPLAYBIND = 0x10,
+ FUNCFLAG_FDEFAULTBIND = 0x20,
+ FUNCFLAG_FHIDDEN = 0x40,
+ FUNCFLAG_FUSESGETLASTERROR= 0x80,
+ FUNCFLAG_FDEFAULTCOLLELEM= 0x100,
+ FUNCFLAG_FUIDEFAULT = 0x200,
+ FUNCFLAG_FNONBROWSABLE = 0x400,
+ FUNCFLAG_FREPLACEABLE = 0x800,
+ FUNCFLAG_FIMMEDIATEBIND = 0x1000
+ }
+
+[Serializable]
+[Flags()]
+ public enum VARFLAGS : short
+ {
+ VARFLAG_FREADONLY =0x1,
+ VARFLAG_FSOURCE =0x2,
+ VARFLAG_FBINDABLE =0x4,
+ VARFLAG_FREQUESTEDIT =0x8,
+ VARFLAG_FDISPLAYBIND =0x10,
+ VARFLAG_FDEFAULTBIND =0x20,
+ VARFLAG_FHIDDEN =0x40,
+ VARFLAG_FRESTRICTED =0x80,
+ VARFLAG_FDEFAULTCOLLELEM =0x100,
+ VARFLAG_FUIDEFAULT =0x200,
+ VARFLAG_FNONBROWSABLE =0x400,
+ VARFLAG_FREPLACEABLE =0x800,
+ VARFLAG_FIMMEDIATEBIND =0x1000
+ }
+
+ [Guid("00020401-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface ITypeInfo
+ {
+ void GetTypeAttr(out IntPtr ppTypeAttr);
+ void GetTypeComp(out ITypeComp ppTComp);
+ void GetFuncDesc(int index, out IntPtr ppFuncDesc);
+ void GetVarDesc(int index, out IntPtr ppVarDesc);
+ void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames);
+ void GetRefTypeOfImplType(int index, out int href);
+ void GetImplTypeFlags(int index, out IMPLTYPEFLAGS pImplTypeFlags);
+ void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId);
+ void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr);
+ void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal);
+ void GetRefTypeInfo(int hRef, out ITypeInfo ppTI);
+ void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv);
+ void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj);
+ void GetMops(int memid, out String pBstrMops);
+ void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex);
+ [PreserveSig]
+ void ReleaseTypeAttr(IntPtr pTypeAttr);
+ [PreserveSig]
+ void ReleaseFuncDesc(IntPtr pFuncDesc);
+ [PreserveSig]
+ void ReleaseVarDesc(IntPtr pVarDesc);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs
new file mode 100644
index 0000000000..a782b9edd6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeInfo2.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: ITypeInfo2 interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00020412-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface ITypeInfo2 : ITypeInfo
+ {
+ new void GetTypeAttr(out IntPtr ppTypeAttr);
+ new void GetTypeComp(out ITypeComp ppTComp);
+ new void GetFuncDesc(int index, out IntPtr ppFuncDesc);
+ new void GetVarDesc(int index, out IntPtr ppVarDesc);
+ new void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames);
+ new void GetRefTypeOfImplType(int index, out int href);
+ new void GetImplTypeFlags(int index, out IMPLTYPEFLAGS pImplTypeFlags);
+ new void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId);
+ new void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref DISPPARAMS pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, out int puArgErr);
+ new void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ new void GetDllEntry(int memid, INVOKEKIND invKind, IntPtr pBstrDllName, IntPtr pBstrName, IntPtr pwOrdinal);
+ new void GetRefTypeInfo(int hRef, out ITypeInfo ppTI);
+ new void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv);
+ new void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, [In] ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj);
+ new void GetMops(int memid, out String pBstrMops);
+ new void GetContainingTypeLib(out ITypeLib ppTLB, out int pIndex);
+ [PreserveSig]
+ new void ReleaseTypeAttr(IntPtr pTypeAttr);
+ [PreserveSig]
+ new void ReleaseFuncDesc(IntPtr pFuncDesc);
+ [PreserveSig]
+ new void ReleaseVarDesc(IntPtr pVarDesc);
+ void GetTypeKind(out TYPEKIND pTypeKind);
+ void GetTypeFlags(out int pTypeFlags);
+ void GetFuncIndexOfMemId(int memid, INVOKEKIND invKind, out int pFuncIndex);
+ void GetVarIndexOfMemId(int memid, out int pVarIndex);
+ void GetCustData(ref Guid guid, out Object pVarVal);
+ void GetFuncCustData(int index, ref Guid guid, out Object pVarVal);
+ void GetParamCustData(int indexFunc, int indexParam, ref Guid guid, out Object pVarVal);
+ void GetVarCustData(int index, ref Guid guid, out Object pVarVal);
+ void GetImplTypeCustData(int index, ref Guid guid, out Object pVarVal);
+ [LCIDConversionAttribute(1)]
+ void GetDocumentation2(int memid, out String pbstrHelpString, out int pdwHelpStringContext, out String pbstrHelpStringDll);
+ void GetAllCustData(IntPtr pCustData);
+ void GetAllFuncCustData(int index, IntPtr pCustData);
+ void GetAllParamCustData(int indexFunc, int indexParam, IntPtr pCustData);
+ void GetAllVarCustData(int index, IntPtr pCustData);
+ void GetAllImplTypeCustData(int index, IntPtr pCustData);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs
new file mode 100644
index 0000000000..c39b088c0b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: ITypeLib interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Serializable]
+ public enum SYSKIND
+ {
+ SYS_WIN16 = 0,
+ SYS_WIN32 = SYS_WIN16 + 1,
+ SYS_MAC = SYS_WIN32 + 1,
+ SYS_WIN64 = SYS_MAC + 1
+ }
+
+[Serializable]
+[Flags()]
+ public enum LIBFLAGS : short
+ {
+ LIBFLAG_FRESTRICTED = 0x1,
+ LIBFLAG_FCONTROL = 0x2,
+ LIBFLAG_FHIDDEN = 0x4,
+ LIBFLAG_FHASDISKIMAGE = 0x8
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ [Serializable]
+ public struct TYPELIBATTR
+ {
+ public Guid guid;
+ public int lcid;
+ public SYSKIND syskind;
+ public Int16 wMajorVerNum;
+ public Int16 wMinorVerNum;
+ public LIBFLAGS wLibFlags;
+ }
+
+ [Guid("00020402-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface ITypeLib
+ {
+ [PreserveSig]
+ int GetTypeInfoCount();
+ void GetTypeInfo(int index, out ITypeInfo ppTI);
+ void GetTypeInfoType(int index, out TYPEKIND pTKind);
+ void GetTypeInfoOfGuid(ref Guid guid, out ITypeInfo ppTInfo);
+ void GetLibAttr(out IntPtr ppTLibAttr);
+ void GetTypeComp(out ITypeComp ppTComp);
+ void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ [return : MarshalAs(UnmanagedType.Bool)]
+ bool IsName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal);
+ void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] ITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound);
+ [PreserveSig]
+ void ReleaseTLibAttr(IntPtr pTLibAttr);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs
new file mode 100644
index 0000000000..5a7d07c001
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ComTypes/ITypeLib2.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: ITypeLib2 interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices.ComTypes
+{
+ using System;
+
+ [Guid("00020411-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface ITypeLib2 : ITypeLib
+ {
+ [PreserveSig]
+ new int GetTypeInfoCount();
+ new void GetTypeInfo(int index, out ITypeInfo ppTI);
+ new void GetTypeInfoType(int index, out TYPEKIND pTKind);
+ new void GetTypeInfoOfGuid(ref Guid guid, out ITypeInfo ppTInfo);
+ new void GetLibAttr(out IntPtr ppTLibAttr);
+ new void GetTypeComp(out ITypeComp ppTComp);
+ new void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ [return : MarshalAs(UnmanagedType.Bool)]
+ new bool IsName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal);
+ new void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] ITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound);
+ [PreserveSig]
+ new void ReleaseTLibAttr(IntPtr pTLibAttr);
+ void GetCustData(ref Guid guid, out Object pVarVal);
+ [LCIDConversionAttribute(1)]
+ void GetDocumentation2(int index, out String pbstrHelpString, out int pdwHelpStringContext, out String pbstrHelpStringDll);
+ void GetLibStatistics(IntPtr pcUniqueNames, out int pcchUniqueNames);
+ void GetAllCustData(IntPtr pCustData);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs
new file mode 100644
index 0000000000..54fd6b0cdd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CriticalHandle.cs
@@ -0,0 +1,275 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A specially designed handle wrapper to ensure we never leak
+** an OS handle. The runtime treats this class specially during
+** P/Invoke marshaling and finalization. Users should write
+** subclasses of CriticalHandle for each distinct handle type.
+** This class is similar to SafeHandle, but lacks the ref counting
+** behavior on marshaling that prevents handle recycling errors
+** or security holes. This lowers the overhead of using the handle
+** considerably, but leaves the onus on the caller to protect
+** themselves from any recycling effects.
+**
+** **** NOTE ****
+**
+** Since there are no ref counts tracking handle usage there is
+** no thread safety either. Your application must ensure that
+** usages of the handle do not cross with attempts to close the
+** handle (or tolerate such crossings). Normal GC mechanics will
+** prevent finalization until the handle class isn't used any more,
+** but explicit Close or Dispose operations may be initiated at any
+** time.
+**
+** Similarly, multiple calls to Close or Dispose on different
+** threads at the same time may cause the ReleaseHandle method to be
+** called more than once.
+**
+** In general (and as might be inferred from the lack of handle
+** recycle protection) you should be very cautious about exposing
+** CriticalHandle instances directly or indirectly to untrusted users.
+** At a minimum you should restrict their ability to queue multiple
+** operations against a single handle at the same time or block their
+** access to Close and Dispose unless you are very comfortable with the
+** semantics of passing an invalid (or possibly invalidated and
+** reallocated) to the unamanged routines you marshal your handle to
+** (and the effects of closing such a handle while those calls are in
+** progress). The runtime cannot protect you from undefined program
+** behvior that might result from such scenarios. You have been warned.
+**
+**
+===========================================================*/
+
+using System;
+using System.Reflection;
+using System.Threading;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.Runtime.ConstrainedExecution;
+using System.IO;
+
+/*
+ Problems addressed by the CriticalHandle class:
+ 1) Critical finalization - ensure we never leak OS resources in SQL. Done
+ without running truly arbitrary & unbounded amounts of managed code.
+ 2) Reduced graph promotion - during finalization, keep object graph small
+ 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race condition (HandleRef)
+ 4) Enforcement of the above via the type system - Don't use IntPtr anymore.
+
+ Subclasses of CriticalHandle will implement the ReleaseHandle
+ abstract method used to execute any code required to free the
+ handle. This method will be prepared as a constrained execution
+ region at instance construction time (along with all the methods in
+ its statically determinable call graph). This implies that we won't
+ get any inconvenient jit allocation errors or rude thread abort
+ interrupts while releasing the handle but the user must still write
+ careful code to avoid injecting fault paths of their own (see the
+ CER spec for more details). In particular, any sub-methods you call
+ should be decorated with a reliability contract of the appropriate
+ level. In most cases this should be:
+ ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)
+ Also, any P/Invoke methods should use the
+ SuppressUnmanagedCodeSecurity attribute to avoid a runtime security
+ check that can also inject failures (even if the check is guaranteed
+ to pass).
+
+ Subclasses must also implement the IsInvalid property so that the
+ infrastructure can tell when critical finalization is actually required.
+ Again, this method is prepared ahead of time. It's envisioned that direct
+ subclasses of CriticalHandle will provide an IsInvalid implementation that suits
+ the general type of handle they support (null is invalid, -1 is invalid etc.)
+ and then these classes will be further derived for specific handle types.
+
+ Most classes using CriticalHandle should not provide a finalizer. If they do
+ need to do so (ie, for flushing out file buffers, needing to write some data
+ back into memory, etc), then they can provide a finalizer that will be
+ guaranteed to run before the CriticalHandle's critical finalizer.
+
+ Subclasses are expected to be written as follows (note that
+ SuppressUnmanagedCodeSecurity should always be used on any P/Invoke methods
+ invoked as part of ReleaseHandle, in order to switch the security check from
+ runtime to jit time and thus remove a possible failure path from the
+ invocation of the method):
+
+ internal sealed MyCriticalHandleSubclass : CriticalHandle {
+ // Called by P/Invoke when returning CriticalHandles
+ private MyCriticalHandleSubclass() : base(IntPtr.Zero)
+ {
+ }
+
+ // Do not provide a finalizer - CriticalHandle's critical finalizer will
+ // call ReleaseHandle for you.
+
+ public override bool IsInvalid {
+ get { return handle == IntPtr.Zero; }
+ }
+
+ [DllImport(Win32Native.KERNEL32), SuppressUnmanagedCodeSecurity, ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern bool CloseHandle(IntPtr handle);
+
+ override protected bool ReleaseHandle()
+ {
+ return CloseHandle(handle);
+ }
+ }
+
+ Then elsewhere to create one of these CriticalHandles, define a method
+ with the following type of signature (CreateFile follows this model).
+ Note that when returning a CriticalHandle like this, P/Invoke will call your
+ classes default constructor.
+
+ [DllImport(Win32Native.KERNEL32)]
+ private static extern MyCriticalHandleSubclass CreateHandle(int someState);
+
+ */
+
+namespace System.Runtime.InteropServices
+{
+
+// This class should not be serializable - it's a handle. We require unmanaged
+// code permission to subclass CriticalHandle to prevent people from writing a
+// subclass and suddenly being able to run arbitrary native code with the
+// same signature as CloseHandle. This is technically a little redundant, but
+// we'll do this to ensure we've cut off all attack vectors. Similarly, all
+// methods have a link demand to ensure untrusted code cannot directly edit
+// or alter a handle.
+[System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+public abstract class CriticalHandle : CriticalFinalizerObject, IDisposable
+{
+ // ! Do not add or rearrange fields as the EE depends on this layout.
+ //------------------------------------------------------------------
+#if DEBUG
+ private String _stackTrace; // Where we allocated this CriticalHandle.
+#endif
+ protected IntPtr handle; // This must be protected so derived classes can use out params.
+ private bool _isClosed; // Set by SetHandleAsInvalid or Close/Dispose/finalization.
+
+ // Creates a CriticalHandle class. Users must then set the Handle property or allow P/Invoke marshaling to set it implicitly.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalHandle(IntPtr invalidHandleValue)
+ {
+ handle = invalidHandleValue;
+ _isClosed = false;
+
+#if DEBUG
+ if (BCLDebug.SafeHandleStackTracesEnabled)
+ _stackTrace = Environment.GetStackTrace(null, false);
+ else
+ _stackTrace = "For a stack trace showing who allocated this CriticalHandle, set SafeHandleStackTraces to 1 and rerun your app.";
+#endif
+ }
+
+#if FEATURE_CORECLR
+ // Adding an empty default constructor for annotation purposes
+ private CriticalHandle(){}
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ ~CriticalHandle()
+ {
+ Dispose(false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private void Cleanup()
+ {
+ if (IsClosed)
+ return;
+ _isClosed = true;
+
+ if (IsInvalid)
+ return;
+
+ // Save last error from P/Invoke in case the implementation of
+ // ReleaseHandle trashes it (important because this ReleaseHandle could
+ // occur implicitly as part of unmarshaling another P/Invoke).
+ int lastError = Marshal.GetLastWin32Error();
+
+ if (!ReleaseHandle())
+ FireCustomerDebugProbe();
+
+ Marshal.SetLastWin32Error(lastError);
+
+ GC.SuppressFinalize(this);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private extern void FireCustomerDebugProbe();
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected void SetHandle(IntPtr handle) {
+ this.handle = handle;
+ }
+
+ // Returns whether the handle has been explicitly marked as closed
+ // (Close/Dispose) or invalid (SetHandleAsInvalid).
+ public bool IsClosed {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return _isClosed; }
+ }
+
+ // Returns whether the handle looks like an invalid value (i.e. matches one
+ // of the handle's designated illegal values). CriticalHandle itself doesn't
+ // know what an invalid handle looks like, so this method is abstract and
+ // must be provided by a derived type.
+ public abstract bool IsInvalid {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Close() {
+ Dispose(true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected virtual void Dispose(bool disposing)
+ {
+ Cleanup();
+ }
+
+ // This should only be called for cases when you know for a fact that
+ // your handle is invalid and you want to record that information.
+ // An example is calling a syscall and getting back ERROR_INVALID_HANDLE.
+ // This method will normally leak handles!
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void SetHandleAsInvalid()
+ {
+ _isClosed = true;
+ GC.SuppressFinalize(this);
+ }
+
+ // Implement this abstract method in your derived class to specify how to
+ // free the handle. Be careful not write any code that's subject to faults
+ // in this method (the runtime will prepare the infrastructure for you so
+ // that no jit allocations etc. will occur, but don't allocate memory unless
+ // you can deal with the failure and still free the handle).
+ // The boolean returned should be true for success and false if a
+ // catastrophic error occurred and you wish to trigger a diagnostic for
+ // debugging purposes (the SafeHandleCriticalFailure MDA).
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected abstract bool ReleaseHandle();
+}
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs
new file mode 100644
index 0000000000..1f7a9f18bf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/CurrencyWrapper.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_CURRENCY.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class CurrencyWrapper
+ {
+ public CurrencyWrapper(Decimal obj)
+ {
+ m_WrappedObject = obj;
+ }
+
+ public CurrencyWrapper(Object obj)
+ {
+ if (!(obj is Decimal))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal"), "obj");
+ m_WrappedObject = (Decimal)obj;
+ }
+
+ public Decimal WrappedObject
+ {
+ get
+ {
+ return m_WrappedObject;
+ }
+ }
+
+ private Decimal m_WrappedObject;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs
new file mode 100644
index 0000000000..1fc72f74c8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/DispatchWrapper.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_DISPATCH.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class DispatchWrapper
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand,Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public DispatchWrapper(Object obj)
+ {
+ if (obj != null)
+ {
+ // Make sure this guy has an IDispatch
+ IntPtr pdisp = Marshal.GetIDispatchForObject(obj);
+
+ // If we got here without throwing an exception, the QI for IDispatch succeeded.
+ Marshal.Release(pdisp);
+ }
+ m_WrappedObject = obj;
+ }
+
+ public Object WrappedObject
+ {
+ get
+ {
+ return m_WrappedObject;
+ }
+ }
+
+ private Object m_WrappedObject;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs
new file mode 100644
index 0000000000..d63d69cabd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ErrorWrapper.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_ERROR.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Security.Permissions;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ErrorWrapper
+ {
+ public ErrorWrapper(int errorCode)
+ {
+ m_ErrorCode = errorCode;
+ }
+
+ public ErrorWrapper(Object errorCode)
+ {
+ if (!(errorCode is int))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt32"), "errorCode");
+ m_ErrorCode = (int)errorCode;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public ErrorWrapper(Exception e)
+ {
+ m_ErrorCode = Marshal.GetHRForException(e);
+ }
+
+ public int ErrorCode
+ {
+ get
+ {
+ return m_ErrorCode;
+ }
+ }
+
+ private int m_ErrorCode;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs b/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs
new file mode 100644
index 0000000000..62b65d1aff
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Expando/IExpando.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// IExpando is an interface which allows Objects implemeningt this interface
+// support the ability to modify the object by adding and removing members,
+// represented by MemberInfo objects.
+//
+//
+// The IExpando Interface.
+namespace System.Runtime.InteropServices.Expando {
+
+ using System;
+ using System.Reflection;
+
+ [Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IExpando : IReflect
+ {
+ // Add a new Field to the reflection object. The field has
+ // name as its name.
+ FieldInfo AddField(String name);
+
+ // Add a new Property to the reflection object. The property has
+ // name as its name.
+ PropertyInfo AddProperty(String name);
+
+ // Add a new Method to the reflection object. The method has
+ // name as its name and method is a delegate
+ // to the method.
+ MethodInfo AddMethod(String name, Delegate method);
+
+ // Removes the specified member.
+ void RemoveMember(MemberInfo m);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs
new file mode 100644
index 0000000000..62718de757
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ExtensibleClassFactory.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Methods used to customize the creation of managed objects that
+** extend from unmanaged objects.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ using System;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ExtensibleClassFactory
+ {
+
+ // Prevent instantiation.
+ private ExtensibleClassFactory() {}
+
+ // Register a delegate that will be called whenever an instance of a managed
+ // type that extends from an unmanaged type needs to allocate the aggregated
+ // unmanaged object. This delegate is expected to allocate and aggregate the
+ // unmanaged object and is called in place of a CoCreateInstance. This
+ // routine must be called in the context of the static initializer for the
+ // class for which the callbacks will be made.
+ // It is not legal to register this callback from a class that has any
+ // parents that have already registered a callback.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void RegisterObjectCreationCallback(ObjectCreationDelegate callback);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs
new file mode 100644
index 0000000000..417cf94bd4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ExternalException.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception base class for all errors from Interop or Structured
+** Exception Handling code.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ // Base exception for COM Interop errors &; Structured Exception Handler
+ // exceptions.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ExternalException : SystemException {
+ public ExternalException()
+ : base(Environment.GetResourceString("Arg_ExternalException")) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public ExternalException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public ExternalException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public ExternalException(String message,int errorCode)
+ : base(message) {
+ SetErrorCode(errorCode);
+ }
+
+ protected ExternalException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public virtual int ErrorCode {
+ get {
+ return HResult;
+ }
+ }
+
+#if !FEATURE_CORECLR // Breaks the subset-of-Orcas property
+ public override String ToString() {
+ String message = Message;
+ String s;
+ String _className = GetType().ToString();
+ s = _className + " (0x" + HResult.ToString("X8", CultureInfo.InvariantCulture) + ")";
+
+ if (!(String.IsNullOrEmpty(message))) {
+ s = s + ": " + message;
+ }
+
+ Exception _innerException = InnerException;
+
+ if (_innerException!=null) {
+ s = s + " ---> " + _innerException.ToString();
+ }
+
+
+ if (StackTrace != null)
+ s += Environment.NewLine + StackTrace;
+
+ return s;
+ }
+#endif // !FEATURE_CORECLR
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs
new file mode 100644
index 0000000000..304f369879
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/GCHandleCookieTable.cs
@@ -0,0 +1,219 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if MDA_SUPPORTED
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Threading;
+
+ using ObjectHandle = IntPtr;
+ using GCHandleCookie = IntPtr;
+
+ // Internal class used to map a GCHandle to an IntPtr. Instead of handing out the underlying CLR
+ // handle, we now hand out a cookie that can later be converted back to the CLR handle it
+ // is associated with.
+
+ // NOTE:
+ // this implementation uses a single lock between FindOrAddHandle and RemoveHandleIfPresent which
+ // could create some scalability issues when this MDA is turned on. if this is affecting perf
+ // then additional tuning work will be required.
+
+ internal class GCHandleCookieTable
+ {
+ private const int InitialHandleCount = 10;
+ private const int MaxListSize = 0xFFFFFF;
+ private const uint CookieMaskIndex = 0x00FFFFFF;
+ private const uint CookieMaskSentinal = 0xFF000000;
+
+ internal GCHandleCookieTable()
+ {
+ m_HandleList = new ObjectHandle[InitialHandleCount];
+ m_CycleCounts = new byte[InitialHandleCount];
+ m_HandleToCookieMap = new Dictionary<ObjectHandle, GCHandleCookie>(InitialHandleCount);
+ m_syncObject = new object();
+
+ for (int i = 0; i < InitialHandleCount; i++)
+ {
+ m_HandleList[i] = ObjectHandle.Zero;
+ m_CycleCounts[i] = 0;
+ }
+ }
+
+ // Retrieve a cookie for the passed in handle. If no cookie has yet been allocated for
+ // this handle, one will be created. This method is thread safe.
+ internal GCHandleCookie FindOrAddHandle(ObjectHandle handle)
+ {
+ // Don't accept a null object handle
+ if (handle == ObjectHandle.Zero)
+ return GCHandleCookie.Zero;
+
+ GCHandleCookie cookie = GCHandleCookie.Zero;
+
+ lock (m_syncObject)
+ {
+ // First see if we already have a cookie for this handle.
+ if (m_HandleToCookieMap.ContainsKey(handle))
+ return m_HandleToCookieMap[handle];
+
+ if ((m_FreeIndex < m_HandleList.Length) && (Volatile.Read(ref m_HandleList[m_FreeIndex]) == ObjectHandle.Zero))
+ {
+ Volatile.Write(ref m_HandleList[m_FreeIndex], handle);
+ cookie = GetCookieFromData((uint)m_FreeIndex, m_CycleCounts[m_FreeIndex]);
+
+ // Set our next guess just one higher as this index is now in use.
+ // it's ok if this sets m_FreeIndex > m_HandleList.Length as this condition is
+ // checked at the beginning of the if statement.
+ ++m_FreeIndex;
+ }
+ else
+ {
+ for (m_FreeIndex = 0; m_FreeIndex < MaxListSize; ++m_FreeIndex)
+ {
+ if (m_HandleList[m_FreeIndex] == ObjectHandle.Zero)
+ {
+ Volatile.Write(ref m_HandleList[m_FreeIndex], handle);
+ cookie = GetCookieFromData((uint)m_FreeIndex, m_CycleCounts[m_FreeIndex]);
+
+ // this will be our next guess for a free index.
+ // it's ok if this sets m_FreeIndex > m_HandleList.Length
+ // since we check for this condition in the if statement.
+ ++m_FreeIndex;
+ break;
+ }
+
+ if (m_FreeIndex + 1 == m_HandleList.Length)
+ GrowArrays();
+ }
+ }
+
+ if (cookie == GCHandleCookie.Zero)
+ throw new OutOfMemoryException(Environment.GetResourceString("OutOfMemory_GCHandleMDA"));
+
+ // This handle hasn't been added to the map yet so add it.
+ m_HandleToCookieMap.Add(handle, cookie);
+ }
+
+ return cookie;
+ }
+
+ // Get a handle.
+ internal ObjectHandle GetHandle(GCHandleCookie cookie)
+ {
+ ObjectHandle oh = ObjectHandle.Zero;
+
+ if (!ValidateCookie(cookie))
+ return ObjectHandle.Zero;
+
+ oh = Volatile.Read(ref m_HandleList[GetIndexFromCookie(cookie)]);
+
+ return oh;
+ }
+
+ // Remove the handle from the cookie table if it is present.
+ //
+ internal void RemoveHandleIfPresent(ObjectHandle handle)
+ {
+ if (handle == ObjectHandle.Zero)
+ return;
+
+ lock (m_syncObject)
+ {
+ if (m_HandleToCookieMap.ContainsKey(handle))
+ {
+ GCHandleCookie cookie = m_HandleToCookieMap[handle];
+
+ // Remove it from the array first
+ if (!ValidateCookie(cookie))
+ return;
+
+ int index = GetIndexFromCookie(cookie);
+
+ m_CycleCounts[index]++;
+ Volatile.Write(ref m_HandleList[index], ObjectHandle.Zero);
+
+ // Remove it from the hashtable last
+ m_HandleToCookieMap.Remove(handle);
+
+ // Update our guess
+ m_FreeIndex = index;
+ }
+ }
+ }
+
+ private bool ValidateCookie(GCHandleCookie cookie)
+ {
+ int index;
+ byte xorData;
+
+ GetDataFromCookie(cookie, out index, out xorData);
+
+ // Validate the index
+ if (index >= MaxListSize)
+ return false;
+
+ if (index >= m_HandleList.Length)
+ return false;
+
+ if (Volatile.Read(ref m_HandleList[index]) == ObjectHandle.Zero)
+ return false;
+
+ // Validate the xorData byte (this contains the cycle count and appdomain id).
+ byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF);
+ byte goodData = (byte)(Volatile.Read(ref m_CycleCounts[index]) ^ ADID);
+ if (xorData != goodData)
+ return false;
+
+ return true;
+ }
+
+ // Double the size of our arrays - must be called with the lock taken.
+ private void GrowArrays()
+ {
+ int CurrLength = m_HandleList.Length;
+
+ ObjectHandle[] newHandleList = new ObjectHandle[CurrLength * 2];
+ byte[] newCycleCounts = new byte[CurrLength * 2];
+
+ Array.Copy(m_HandleList, newHandleList, CurrLength);
+ Array.Copy(m_CycleCounts, newCycleCounts, CurrLength);
+
+ m_HandleList = newHandleList;
+ m_CycleCounts = newCycleCounts;
+ }
+
+ // Generate a cookie based on the index, cyclecount, and current domain id.
+ private GCHandleCookie GetCookieFromData(uint index, byte cycleCount)
+ {
+ byte ADID = (byte)(AppDomain.CurrentDomain.Id % 0xFF);
+ return (GCHandleCookie)(((cycleCount ^ ADID) << 24) + index + 1);
+ }
+
+ // Break down the cookie into its parts
+ private void GetDataFromCookie(GCHandleCookie cookie, out int index, out byte xorData)
+ {
+ uint intCookie = (uint)cookie;
+ index = (int)(intCookie & CookieMaskIndex) - 1;
+ xorData = (byte)((intCookie & CookieMaskSentinal) >> 24);
+ }
+
+ // Just get the index from the cookie
+ private int GetIndexFromCookie(GCHandleCookie cookie)
+ {
+ uint intCookie = (uint)cookie;
+ return (int)(intCookie & CookieMaskIndex) - 1;
+ }
+
+ private Dictionary<ObjectHandle, GCHandleCookie> m_HandleToCookieMap;
+ private volatile ObjectHandle[] m_HandleList;
+ private volatile byte[] m_CycleCounts;
+ private int m_FreeIndex;
+ private readonly object m_syncObject;
+ }
+}
+
+#endif
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs
new file mode 100644
index 0000000000..58fea97cb8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/GcHandle.cs
@@ -0,0 +1,330 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Threading;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // These are the types of handles used by the EE.
+ // IMPORTANT: These must match the definitions in ObjectHandle.h in the EE.
+ // IMPORTANT: If new values are added to the enum the GCHandle::MaxHandleType
+ // constant must be updated.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum GCHandleType
+ {
+ Weak = 0,
+ WeakTrackResurrection = 1,
+ Normal = 2,
+ Pinned = 3
+ }
+
+ // This class allows you to create an opaque, GC handle to any
+ // COM+ object. A GC handle is used when an object reference must be
+ // reachable from unmanaged memory. There are 3 kinds of roots:
+ // Normal - keeps the object from being collected.
+ // Weak - allows object to be collected and handle contents will be zeroed.
+ // Weak references are zeroed before the finalizer runs, so if the
+ // object is resurrected in the finalizer the weak reference is
+ // still zeroed.
+ // WeakTrackResurrection - Same as weak, but stays until after object is
+ // really gone.
+ // Pinned - same as normal, but allows the address of the actual object
+ // to be taken.
+ //
+
+ [StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct GCHandle
+ {
+ // IMPORTANT: This must be kept in sync with the GCHandleType enum.
+ private const GCHandleType MaxHandleType = GCHandleType.Pinned;
+
+#if MDA_SUPPORTED
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static GCHandle()
+ {
+ s_probeIsActive = Mda.IsInvalidGCHandleCookieProbeEnabled();
+ if (s_probeIsActive)
+ s_cookieTable = new GCHandleCookieTable();
+ }
+#endif
+
+ // Allocate a handle storing the object and the type.
+ [System.Security.SecurityCritical] // auto-generated
+ internal GCHandle(Object value, GCHandleType type)
+ {
+ // Make sure the type parameter is within the valid range for the enum.
+ if ((uint)type > (uint)MaxHandleType)
+ throw new ArgumentOutOfRangeException("type", Environment.GetResourceString("ArgumentOutOfRange_Enum"));
+ Contract.EndContractBlock();
+
+ m_handle = InternalAlloc(value, type);
+
+ // Record if the handle is pinned.
+ if (type == GCHandleType.Pinned)
+ SetIsPinned();
+ }
+
+ // Used in the conversion functions below.
+ [System.Security.SecurityCritical] // auto-generated
+ internal GCHandle(IntPtr handle)
+ {
+ InternalCheckDomain(handle);
+ m_handle = handle;
+ }
+
+ // Creates a new GC handle for an object.
+ //
+ // value - The object that the GC handle is created for.
+ // type - The type of GC handle to create.
+ //
+ // returns a new GC handle that protects the object.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static GCHandle Alloc(Object value)
+ {
+ return new GCHandle(value, GCHandleType.Normal);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static GCHandle Alloc(Object value, GCHandleType type)
+ {
+ return new GCHandle(value, type);
+ }
+
+
+ // Frees a GC handle.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void Free()
+ {
+ // Copy the handle instance member to a local variable. This is required to prevent
+ // race conditions releasing the handle.
+ IntPtr handle = m_handle;
+
+ // Free the handle if it hasn't already been freed.
+ if (handle != IntPtr.Zero && Interlocked.CompareExchange(ref m_handle, IntPtr.Zero, handle) == handle)
+ {
+#if MDA_SUPPORTED
+ // If this handle was passed out to unmanaged code, we need to remove it
+ // from the cookie table.
+ // NOTE: the entry in the cookie table must be released before the
+ // internal handle is freed to prevent a race with reusing GC handles.
+ if (s_probeIsActive)
+ s_cookieTable.RemoveHandleIfPresent(handle);
+#endif
+
+#if BIT64
+ InternalFree((IntPtr)(((long)handle) & ~1L));
+#else // BIT64 (32)
+ InternalFree((IntPtr)(((int)handle) & ~1));
+#endif
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+ }
+ }
+
+ // Target property - allows getting / updating of the handle's referent.
+ public Object Target
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get
+ {
+ // Check if the handle was never initialized or was freed.
+ if (m_handle == IntPtr.Zero)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+
+ return InternalGet(GetHandleValue());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ set
+ {
+ // Check if the handle was never initialized or was freed.
+ if (m_handle == IntPtr.Zero)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+
+ InternalSet(GetHandleValue(), value, IsPinned());
+ }
+ }
+
+ // Retrieve the address of an object in a Pinned handle. This throws
+ // an exception if the handle is any type other than Pinned.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public IntPtr AddrOfPinnedObject()
+ {
+ // Check if the handle was not a pinned handle.
+ if (!IsPinned())
+ {
+ // Check if the handle was never initialized for was freed.
+ if (m_handle == IntPtr.Zero)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+
+ // You can only get the address of pinned handles.
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotPinned"));
+ }
+
+ // Get the address.
+ return InternalAddrOfPinnedObject(GetHandleValue());
+ }
+
+ // Determine whether this handle has been allocated or not.
+ public bool IsAllocated
+ {
+ get
+ {
+ return m_handle != IntPtr.Zero;
+ }
+ }
+
+ // Used to create a GCHandle from an int. This is intended to
+ // be used with the reverse conversion.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static explicit operator GCHandle(IntPtr value)
+ {
+ return FromIntPtr(value);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static GCHandle FromIntPtr(IntPtr value)
+ {
+ if (value == IntPtr.Zero)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_HandleIsNotInitialized"));
+ Contract.EndContractBlock();
+
+ IntPtr handle = value;
+
+#if MDA_SUPPORTED
+ if (s_probeIsActive)
+ {
+ // Make sure this cookie matches up with a GCHandle we've passed out a cookie for.
+ handle = s_cookieTable.GetHandle(value);
+ if (IntPtr.Zero == handle)
+ {
+ // Fire an MDA if we were unable to retrieve the GCHandle.
+ Mda.FireInvalidGCHandleCookieProbe(value);
+ return new GCHandle(IntPtr.Zero);
+ }
+ }
+#endif
+
+ return new GCHandle(handle);
+ }
+
+ // Used to get the internal integer representation of the handle out.
+ public static explicit operator IntPtr(GCHandle value)
+ {
+ return ToIntPtr(value);
+ }
+
+ public static IntPtr ToIntPtr(GCHandle value)
+ {
+#if MDA_SUPPORTED
+ if (s_probeIsActive)
+ {
+ // Remember that we passed this GCHandle out by storing the cookie we returned so we
+ // can later validate.
+ return s_cookieTable.FindOrAddHandle(value.m_handle);
+ }
+#endif
+ return value.m_handle;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_handle.GetHashCode();
+ }
+
+ public override bool Equals(Object o)
+ {
+ GCHandle hnd;
+
+ // Check that o is a GCHandle first
+ if(o == null || !(o is GCHandle))
+ return false;
+ else
+ hnd = (GCHandle) o;
+
+ return m_handle == hnd.m_handle;
+ }
+
+ public static bool operator ==(GCHandle a, GCHandle b)
+ {
+ return a.m_handle == b.m_handle;
+ }
+
+ public static bool operator !=(GCHandle a, GCHandle b)
+ {
+ return a.m_handle != b.m_handle;
+ }
+
+ internal IntPtr GetHandleValue()
+ {
+#if BIT64
+ return new IntPtr(((long)m_handle) & ~1L);
+#else // !BIT64 (32)
+ return new IntPtr(((int)m_handle) & ~1);
+#endif
+ }
+
+ internal bool IsPinned()
+ {
+#if BIT64
+ return (((long)m_handle) & 1) != 0;
+#else // !BIT64 (32)
+ return (((int)m_handle) & 1) != 0;
+#endif
+ }
+
+ internal void SetIsPinned()
+ {
+#if BIT64
+ m_handle = new IntPtr(((long)m_handle) | 1L);
+#else // !BIT64 (32)
+ m_handle = new IntPtr(((int)m_handle) | 1);
+#endif
+ }
+
+ // Internal native calls that this implementation uses.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr InternalAlloc(Object value, GCHandleType type);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InternalFree(IntPtr handle);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object InternalGet(IntPtr handle);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InternalSet(IntPtr handle, Object value, bool isPinned);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object InternalCompareExchange(IntPtr handle, Object value, Object oldValue, bool isPinned);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr InternalAddrOfPinnedObject(IntPtr handle);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InternalCheckDomain(IntPtr handle);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern GCHandleType InternalGetHandleType(IntPtr handle);
+
+ // The actual integer handle value that the EE uses internally.
+ private IntPtr m_handle;
+
+#if MDA_SUPPORTED
+ // The GCHandle cookie table.
+ static private volatile GCHandleCookieTable s_cookieTable = null;
+ static private volatile bool s_probeIsActive = false;
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs b/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs
new file mode 100644
index 0000000000..d76750fdd7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/HandleRef.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+
+ using System;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct HandleRef
+ {
+
+ // ! Do not add or rearrange fields as the EE depends on this layout.
+ //------------------------------------------------------------------
+ internal Object m_wrapper;
+ internal IntPtr m_handle;
+ //------------------------------------------------------------------
+
+
+ public HandleRef(Object wrapper, IntPtr handle)
+ {
+ m_wrapper = wrapper;
+ m_handle = handle;
+ }
+
+ public Object Wrapper {
+ get {
+ return m_wrapper;
+ }
+ }
+
+ public IntPtr Handle {
+ get {
+ return m_handle;
+ }
+ }
+
+
+ public static explicit operator IntPtr(HandleRef value)
+ {
+ return value.m_handle;
+ }
+
+ public static IntPtr ToIntPtr(HandleRef value)
+ {
+ return value.m_handle;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs
new file mode 100644
index 0000000000..00abf7b3bf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomAdapter.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This the base interface that custom adapters can chose to implement
+** when they want to expose the underlying object.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICustomAdapter
+ {
+ [return:MarshalAs(UnmanagedType.IUnknown)] Object GetUnderlyingObject();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs
new file mode 100644
index 0000000000..33d2556bd0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomFactory.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICustomFactory
+ {
+ MarshalByRefObject CreateInstance(Type serverType);
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs
new file mode 100644
index 0000000000..4db4acceeb
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomMarshaler.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This the base interface that must be implemented by all custom
+** marshalers.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ICustomMarshaler
+ {
+ Object MarshalNativeToManaged( IntPtr pNativeData );
+
+ IntPtr MarshalManagedToNative( Object ManagedObj );
+
+ void CleanUpNativeData( IntPtr pNativeData );
+
+ void CleanUpManagedData( Object ManagedObj );
+
+ int GetNativeDataSize();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs
new file mode 100644
index 0000000000..61688b90b4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ICustomQueryInterface.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This the interface that be implemented by class that want to
+** customize the behavior of QueryInterface.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System;
+
+ //====================================================================
+ // The enum of the return value of IQuerable.GetInterface
+ //====================================================================
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public enum CustomQueryInterfaceResult
+ {
+ Handled = 0,
+ NotHandled = 1,
+ Failed = 2,
+ }
+
+ //====================================================================
+ // The interface for customizing IQueryInterface
+ //====================================================================
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public interface ICustomQueryInterface
+ {
+ [System.Security.SecurityCritical]
+ CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IException.cs b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs
new file mode 100644
index 0000000000..2da0a564a2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/IException.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Interface: _Exception
+**
+**
+** Purpose: COM backwards compatibility with v1 Exception
+** object layout.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System;
+ using System.Reflection;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ [GuidAttribute("b36b5c63-42ef-38bc-a07e-0b34c98f164a")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsDual)]
+ [CLSCompliant(false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Exception
+ {
+#if !FEATURE_CORECLR
+ // This contains all of our V1 Exception class's members.
+
+ // From Object
+ String ToString();
+ bool Equals (Object obj);
+ int GetHashCode ();
+ Type GetType ();
+
+ // From V1's Exception class
+ String Message {
+ get;
+ }
+
+ Exception GetBaseException();
+
+ String StackTrace {
+ get;
+ }
+
+ String HelpLink {
+ get;
+ set;
+ }
+
+ String Source {
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ get;
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ set;
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ void GetObjectData(SerializationInfo info, StreamingContext context);
+#endif
+
+ //
+ // This method is intentionally included in CoreCLR to make Exception.get_InnerException "newslot virtual final".
+ // Some phone apps include MEF from desktop Silverlight. MEF's ComposablePartException depends on implicit interface
+ // implementations of get_InnerException to be provided by the base class. It works only if Exception.get_InnerException
+ // is virtual.
+ //
+ Exception InnerException {
+ get;
+ }
+
+#if !FEATURE_CORECLR
+ MethodBase TargetSite {
+ get;
+ }
+#endif
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs
new file mode 100644
index 0000000000..ae330e8652
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/IRegistrationServices.cs
@@ -0,0 +1,56 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This interface provides services for registering and unregistering
+** a managed server for use by COM.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+
+ [Flags()]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum AssemblyRegistrationFlags
+ {
+ None = 0x00000000,
+ SetCodeBase = 0x00000001,
+ }
+
+ [Guid("CCBD682C-73A5-4568-B8B0-C7007E11ABA2")]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IRegistrationServices
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ bool UnregisterAssembly(Assembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ Type[] GetRegistrableTypesInAssembly(Assembly assembly);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ String GetProgIdForType(Type type);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void RegisterTypeForComClients(Type type, ref Guid g);
+
+ Guid GetManagedCategoryGuid();
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ bool TypeRequiresRegistration(Type type);
+
+ bool TypeRepresentsComType(Type type);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs b/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs
new file mode 100644
index 0000000000..a7b6889c55
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ITypeLibConverter.cs
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Methods used to convert a TypeLib to metadata and vice versa.
+**
+**
+=============================================================================*/
+
+// ***************************************************************************
+// *** Note: The following definitions must remain synchronized with the IDL
+// *** in src/inc/TlbImpExp.idl.
+// ***************************************************************************
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+
+[Serializable]
+[Flags()]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeLibImporterFlags
+ {
+ None = 0x00000000,
+ PrimaryInteropAssembly = 0x00000001,
+ UnsafeInterfaces = 0x00000002,
+ SafeArrayAsSystemArray = 0x00000004,
+ TransformDispRetVals = 0x00000008,
+ PreventClassMembers = 0x00000010,
+ SerializableValueClasses = 0x00000020,
+ ImportAsX86 = 0x00000100,
+ ImportAsX64 = 0x00000200,
+ ImportAsItanium = 0x00000400,
+ ImportAsAgnostic = 0x00000800,
+ ReflectionOnlyLoading = 0x00001000,
+ NoDefineVersionResource = 0x00002000,
+ ImportAsArm = 0x00004000,
+ }
+
+[Serializable]
+[Flags()]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeLibExporterFlags
+ {
+ None = 0x00000000,
+ OnlyReferenceRegistered = 0x00000001,
+ CallerResolvedReferences = 0x00000002,
+ OldNames = 0x00000004,
+ ExportAs32Bit = 0x00000010,
+ ExportAs64Bit = 0x00000020,
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ImporterEventKind
+ {
+ NOTIF_TYPECONVERTED = 0,
+ NOTIF_CONVERTWARNING = 1,
+ ERROR_REFTOINVALIDTYPELIB = 2,
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ExporterEventKind
+ {
+ NOTIF_TYPECONVERTED = 0,
+ NOTIF_CONVERTWARNING = 1,
+ ERROR_REFTOINVALIDASSEMBLY = 2
+ }
+
+ [GuidAttribute("F1C3BF76-C3E4-11d3-88E7-00902754C43A")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ITypeLibImporterNotifySink
+ {
+ void ReportEvent(
+ ImporterEventKind eventKind,
+ int eventCode,
+ String eventMsg);
+ Assembly ResolveRef(
+ [MarshalAs(UnmanagedType.Interface)] Object typeLib);
+ }
+
+ [GuidAttribute("F1C3BF77-C3E4-11d3-88E7-00902754C43A")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ITypeLibExporterNotifySink
+ {
+ void ReportEvent(
+ ExporterEventKind eventKind,
+ int eventCode,
+ String eventMsg);
+
+ [return : MarshalAs(UnmanagedType.Interface)]
+ Object ResolveRef(
+ Assembly assembly);
+ }
+
+ [GuidAttribute("F1C3BF78-C3E4-11d3-88E7-00902754C43A")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ITypeLibConverter
+ {
+ AssemblyBuilder ConvertTypeLibToAssembly(
+ [MarshalAs(UnmanagedType.Interface)] Object typeLib,
+ String asmFileName,
+ TypeLibImporterFlags flags,
+ ITypeLibImporterNotifySink notifySink,
+ byte[] publicKey,
+ StrongNameKeyPair keyPair,
+ String asmNamespace,
+ Version asmVersion);
+
+ [return : MarshalAs(UnmanagedType.Interface)]
+ Object ConvertAssemblyToTypeLib(
+ Assembly assembly,
+ String typeLibName,
+ TypeLibExporterFlags flags,
+ ITypeLibExporterNotifySink notifySink);
+
+ bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase);
+
+ AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib,
+ String asmFileName,
+ int flags,
+ ITypeLibImporterNotifySink notifySink,
+ byte[] publicKey,
+ StrongNameKeyPair keyPair,
+ bool unsafeInterfaces);
+ }
+
+ [GuidAttribute("FA1F3615-ACB9-486d-9EAC-1BEF87E36B09")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ITypeLibExporterNameProvider
+ {
+ [return : MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)]
+ String[] GetNames();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs b/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs
new file mode 100644
index 0000000000..ac8258b872
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidComObjectException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: This exception is thrown when an invalid COM object is used. This
+** happens when a the __ComObject type is used directly without
+** having a backing class factory.
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class InvalidComObjectException : SystemException {
+ public InvalidComObjectException()
+ : base(Environment.GetResourceString("Arg_InvalidComObjectException")) {
+ SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT);
+ }
+
+ public InvalidComObjectException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT);
+ }
+
+ public InvalidComObjectException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_INVALIDCOMOBJECT);
+ }
+
+ protected InvalidComObjectException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs b/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs
new file mode 100644
index 0000000000..60c9aa67b4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs
@@ -0,0 +1,39 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: The type of an OLE variant that was passed into the runtime is
+** invalid.
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class InvalidOleVariantTypeException : SystemException {
+ public InvalidOleVariantTypeException()
+ : base(Environment.GetResourceString("Arg_InvalidOleVariantTypeException")) {
+ SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE);
+ }
+
+ public InvalidOleVariantTypeException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE);
+ }
+
+ public InvalidOleVariantTypeException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_INVALIDOLEVARIANTTYPE);
+ }
+
+ protected InvalidOleVariantTypeException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs b/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs
new file mode 100644
index 0000000000..231779872e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/LayoutKind.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+namespace System.Runtime.InteropServices {
+ using System;
+ // Used in the StructLayoutAttribute class
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public enum LayoutKind
+ {
+ Sequential = 0, // 0x00000008,
+ Explicit = 2, // 0x00000010,
+ Auto = 3, // 0x00000000,
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs
new file mode 100644
index 0000000000..86e88306f0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Marshal.cs
@@ -0,0 +1,2806 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This class contains methods that are mainly used to marshal
+** between unmanaged and managed types.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.Remoting;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using Win32Native = Microsoft.Win32.Win32Native;
+ using Microsoft.Win32.SafeHandles;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.InteropServices.ComTypes;
+
+ [Serializable]
+ public enum CustomQueryInterfaceMode
+ {
+ Ignore = 0,
+ Allow = 1
+ }
+
+ //========================================================================
+ // All public methods, including PInvoke, are protected with linkchecks.
+ // Remove the default demands for all PInvoke methods with this global
+ // declaration on the class.
+ //========================================================================
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public static partial class Marshal
+ {
+ //====================================================================
+ // Defines used inside the Marshal class.
+ //====================================================================
+ private const int LMEM_FIXED = 0;
+ private const int LMEM_MOVEABLE = 2;
+#if !FEATURE_PAL
+ private const long HIWORDMASK = unchecked((long)0xffffffffffff0000L);
+#endif //!FEATURE_PAL
+#if FEATURE_COMINTEROP
+ private static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
+#endif //FEATURE_COMINTEROP
+
+ // Win32 has the concept of Atoms, where a pointer can either be a pointer
+ // or an int. If it's less than 64K, this is guaranteed to NOT be a
+ // pointer since the bottom 64K bytes are reserved in a process' page table.
+ // We should be careful about deallocating this stuff. Extracted to
+ // a function to avoid C# problems with lack of support for IntPtr.
+ // We have 2 of these methods for slightly different semantics for NULL.
+ private static bool IsWin32Atom(IntPtr ptr)
+ {
+#if FEATURE_PAL
+ return false;
+#else
+ long lPtr = (long)ptr;
+ return 0 == (lPtr & HIWORDMASK);
+#endif
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static bool IsNotWin32Atom(IntPtr ptr)
+ {
+#if FEATURE_PAL
+ return true;
+#else
+ long lPtr = (long)ptr;
+ return 0 != (lPtr & HIWORDMASK);
+#endif
+ }
+
+ //====================================================================
+ // The default character size for the system. This is always 2 because
+ // the framework only runs on UTF-16 systems.
+ //====================================================================
+ public static readonly int SystemDefaultCharSize = 2;
+
+ //====================================================================
+ // The max DBCS character size for the system.
+ //====================================================================
+ public static readonly int SystemMaxDBCSCharSize = GetSystemMaxDBCSCharSize();
+
+
+ //====================================================================
+ // The name, title and description of the assembly that will contain
+ // the dynamically generated interop types.
+ //====================================================================
+ private const String s_strConvertedTypeInfoAssemblyName = "InteropDynamicTypes";
+ private const String s_strConvertedTypeInfoAssemblyTitle = "Interop Dynamic Types";
+ private const String s_strConvertedTypeInfoAssemblyDesc = "Type dynamically generated from ITypeInfo's";
+ private const String s_strConvertedTypeInfoNameSpace = "InteropDynamicTypes";
+
+
+ //====================================================================
+ // Helper method to retrieve the system's maximum DBCS character size.
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int GetSystemMaxDBCSCharSize();
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringAnsi(IntPtr ptr)
+ {
+ if (IntPtr.Zero == ptr) {
+ return null;
+ }
+ else if (IsWin32Atom(ptr)) {
+ return null;
+ }
+ else {
+ int nb = Win32Native.lstrlenA(ptr);
+ if( nb == 0) {
+ return string.Empty;
+ }
+ else {
+ return new String((sbyte *)ptr);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringAnsi(IntPtr ptr, int len)
+ {
+ if (ptr == IntPtr.Zero)
+ throw new ArgumentNullException("ptr");
+ if (len < 0)
+ throw new ArgumentException("len");
+
+ return new String((sbyte *)ptr, 0, len);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringUni(IntPtr ptr, int len)
+ {
+ if (ptr == IntPtr.Zero)
+ throw new ArgumentNullException("ptr");
+ if (len < 0)
+ throw new ArgumentException("len");
+
+ return new String((char *)ptr, 0, len);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String PtrToStringAuto(IntPtr ptr, int len)
+ {
+ // Ansi platforms are no longer supported
+ return PtrToStringUni(ptr, len);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringUni(IntPtr ptr)
+ {
+ if (IntPtr.Zero == ptr) {
+ return null;
+ }
+ else if (IsWin32Atom(ptr)) {
+ return null;
+ }
+ else {
+ return new String((char *)ptr);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String PtrToStringAuto(IntPtr ptr)
+ {
+ // Ansi platforms are no longer supported
+ return PtrToStringUni(ptr);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringUTF8(IntPtr ptr)
+ {
+ int nbBytes = System.StubHelpers.StubHelpers.strlen((sbyte*)ptr.ToPointer());
+ return PtrToStringUTF8(ptr, nbBytes);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static String PtrToStringUTF8(IntPtr ptr,int byteLen)
+ {
+ if (byteLen < 0)
+ {
+ throw new ArgumentException("byteLen");
+ }
+ else if (IntPtr.Zero == ptr)
+ {
+ return null;
+ }
+ else if (IsWin32Atom(ptr))
+ {
+ return null;
+ }
+ else if (byteLen == 0)
+ {
+ return string.Empty;
+ }
+ else
+ {
+ byte* pByte = (byte*)ptr.ToPointer();
+ return Encoding.UTF8.GetString(pByte, byteLen);
+ }
+ }
+
+ //====================================================================
+ // SizeOf()
+ //====================================================================
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static int SizeOf(Object structure)
+ {
+ if (structure == null)
+ throw new ArgumentNullException("structure");
+ // we never had a check for generics here
+ Contract.EndContractBlock();
+
+ return SizeOfHelper(structure.GetType(), true);
+ }
+
+ public static int SizeOf<T>(T structure)
+ {
+ return SizeOf((object)structure);
+ }
+
+ [Pure]
+ public static int SizeOf(Type t)
+ {
+ if (t == null)
+ throw new ArgumentNullException("t");
+ if (!(t is RuntimeType))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t");
+ if (t.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t");
+ Contract.EndContractBlock();
+
+ return SizeOfHelper(t, true);
+ }
+
+ public static int SizeOf<T>()
+ {
+ return SizeOf(typeof(T));
+ }
+
+ /// <summary>
+ /// Returns the aligned size of an instance of a value type.
+ /// </summary>
+ /// <typeparam name="T">Provide a value type to figure out its size</typeparam>
+ /// <returns>The aligned size of T in bytes.</returns>
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static uint AlignedSizeOf<T>() where T : struct
+ {
+ uint size = SizeOfType(typeof(T));
+ if (size == 1 || size == 2)
+ {
+ return size;
+ }
+ if (IntPtr.Size == 8 && size == 4)
+ {
+ return size;
+ }
+ return AlignedSizeOfType(typeof(T));
+ }
+
+ // Type must be a value type with no object reference fields. We only
+ // assert this, due to the lack of a suitable generic constraint.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern uint SizeOfType(Type type);
+
+ // Type must be a value type with no object reference fields. We only
+ // assert this, due to the lack of a suitable generic constraint.
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern uint AlignedSizeOfType(Type type);
+
+#if !FEATURE_CORECLR // Marshal is critical in CoreCLR, so SafeCritical members trigger Annotator violations
+ [System.Security.SecuritySafeCritical]
+#endif // !FEATURE_CORECLR
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable);
+
+ //====================================================================
+ // OffsetOf()
+ //====================================================================
+ public static IntPtr OffsetOf(Type t, String fieldName)
+ {
+ if (t == null)
+ throw new ArgumentNullException("t");
+ Contract.EndContractBlock();
+
+ FieldInfo f = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ if (f == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_OffsetOfFieldNotFound", t.FullName), "fieldName");
+ RtFieldInfo rtField = f as RtFieldInfo;
+ if (rtField == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"), "fieldName");
+
+ return OffsetOfHelper(rtField);
+ }
+ public static IntPtr OffsetOf<T>(string fieldName)
+ {
+ return OffsetOf(typeof(T), fieldName);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr OffsetOfHelper(IRuntimeFieldInfo f);
+
+ //====================================================================
+ // UnsafeAddrOfPinnedArrayElement()
+ //
+ // IMPORTANT NOTICE: This method does not do any verification on the
+ // array. It must be used with EXTREME CAUTION since passing in
+ // an array that is not pinned or in the fixed heap can cause
+ // unexpected results !
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index);
+
+ [System.Security.SecurityCritical]
+ public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index)
+ {
+ return UnsafeAddrOfPinnedArrayElement((Array)arr, index);
+ }
+
+ //====================================================================
+ // Copy blocks from CLR arrays to native memory.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(int[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(char[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(short[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(long[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(float[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(double[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(byte[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int length)
+ {
+ CopyToNative(source, startIndex, destination, length);
+ }
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void CopyToNative(Object source, int startIndex, IntPtr destination, int length);
+
+ //====================================================================
+ // Copy blocks from native memory to CLR arrays
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, int[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, char[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, short[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, long[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, float[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, double[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, byte[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Copy(IntPtr source, IntPtr[] destination, int startIndex, int length)
+ {
+ CopyToManaged(source, destination, startIndex, length);
+ }
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void CopyToManaged(IntPtr source, Object destination, int startIndex, int length);
+
+ //====================================================================
+ // Read from memory
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RU1")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs);
+#else
+ public static byte ReadByte([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe byte ReadByte(IntPtr ptr, int ofs)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ return *addr;
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static byte ReadByte(IntPtr ptr)
+ {
+ return ReadByte(ptr,0);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI2")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+#else
+ public static short ReadInt16([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe short ReadInt16(IntPtr ptr, int ofs)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x1) == 0)
+ {
+ // aligned read
+ return *((short *)addr);
+ }
+ else
+ {
+ // unaligned read
+ short val;
+ byte *valPtr = (byte *)&val;
+ valPtr[0] = addr[0];
+ valPtr[1] = addr[1];
+ return val;
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static short ReadInt16(IntPtr ptr)
+ {
+ return ReadInt16(ptr, 0);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI4"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+#else
+ public static int ReadInt32([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static unsafe int ReadInt32(IntPtr ptr, int ofs)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x3) == 0)
+ {
+ // aligned read
+ return *((int *)addr);
+ }
+ else
+ {
+ // unaligned read
+ int val;
+ byte *valPtr = (byte *)&val;
+ valPtr[0] = addr[0];
+ valPtr[1] = addr[1];
+ valPtr[2] = addr[2];
+ valPtr[3] = addr[3];
+ return val;
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int ReadInt32(IntPtr ptr)
+ {
+ return ReadInt32(ptr,0);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static IntPtr ReadIntPtr([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs)
+ {
+ #if BIT64
+ return (IntPtr) ReadInt64(ptr, ofs);
+ #else // 32
+ return (IntPtr) ReadInt32(ptr, ofs);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static IntPtr ReadIntPtr(IntPtr ptr, int ofs)
+ {
+ #if BIT64
+ return (IntPtr) ReadInt64(ptr, ofs);
+ #else // 32
+ return (IntPtr) ReadInt32(ptr, ofs);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static IntPtr ReadIntPtr(IntPtr ptr)
+ {
+ #if BIT64
+ return (IntPtr) ReadInt64(ptr, 0);
+ #else // 32
+ return (IntPtr) ReadInt32(ptr, 0);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_RI8"), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs);
+#else
+ public static long ReadInt64([MarshalAs(UnmanagedType.AsAny),In] Object ptr, int ofs)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe long ReadInt64(IntPtr ptr, int ofs)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x7) == 0)
+ {
+ // aligned read
+ return *((long *)addr);
+ }
+ else
+ {
+ // unaligned read
+ long val;
+ byte *valPtr = (byte *)&val;
+ valPtr[0] = addr[0];
+ valPtr[1] = addr[1];
+ valPtr[2] = addr[2];
+ valPtr[3] = addr[3];
+ valPtr[4] = addr[4];
+ valPtr[5] = addr[5];
+ valPtr[6] = addr[6];
+ valPtr[7] = addr[7];
+ return val;
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static long ReadInt64(IntPtr ptr)
+ {
+ return ReadInt64(ptr,0);
+ }
+
+
+ //====================================================================
+ // Write to memory
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe void WriteByte(IntPtr ptr, int ofs, byte val)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ *addr = val;
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WU1")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val);
+#else
+ public static void WriteByte([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, byte val)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteByte(IntPtr ptr, byte val)
+ {
+ WriteByte(ptr, 0, val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe void WriteInt16(IntPtr ptr, int ofs, short val)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x1) == 0)
+ {
+ // aligned write
+ *((short *)addr) = val;
+ }
+ else
+ {
+ // unaligned write
+ byte *valPtr = (byte *)&val;
+ addr[0] = valPtr[0];
+ addr[1] = valPtr[1];
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI2")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val);
+#else
+ public static void WriteInt16([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, short val)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt16(IntPtr ptr, short val)
+ {
+ WriteInt16(ptr, 0, val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt16(IntPtr ptr, int ofs, char val)
+ {
+ WriteInt16(ptr, ofs, (short)val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt16([In,Out]Object ptr, int ofs, char val)
+ {
+ WriteInt16(ptr, ofs, (short)val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt16(IntPtr ptr, char val)
+ {
+ WriteInt16(ptr, 0, (short)val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x3) == 0)
+ {
+ // aligned write
+ *((int *)addr) = val;
+ }
+ else
+ {
+ // unaligned write
+ byte *valPtr = (byte *)&val;
+ addr[0] = valPtr[0];
+ addr[1] = valPtr[1];
+ addr[2] = valPtr[2];
+ addr[3] = valPtr[3];
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI4")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val);
+#else
+ public static void WriteInt32([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, int val)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt32(IntPtr ptr, int val)
+ {
+ WriteInt32(ptr,0,val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val)
+ {
+ #if BIT64
+ WriteInt64(ptr, ofs, (long)val);
+ #else // 32
+ WriteInt32(ptr, ofs, (int)val);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteIntPtr([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, IntPtr val)
+ {
+ #if BIT64
+ WriteInt64(ptr, ofs, (long)val);
+ #else // 32
+ WriteInt32(ptr, ofs, (int)val);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteIntPtr(IntPtr ptr, IntPtr val)
+ {
+ #if BIT64
+ WriteInt64(ptr, 0, (long)val);
+ #else // 32
+ WriteInt32(ptr, 0, (int)val);
+ #endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val)
+ {
+ try
+ {
+ byte *addr = (byte *)ptr + ofs;
+ if ((unchecked((int)addr) & 0x7) == 0)
+ {
+ // aligned write
+ *((long *)addr) = val;
+ }
+ else
+ {
+ // unaligned write
+ byte *valPtr = (byte *)&val;
+ addr[0] = valPtr[0];
+ addr[1] = valPtr[1];
+ addr[2] = valPtr[2];
+ addr[3] = valPtr[3];
+ addr[4] = valPtr[4];
+ addr[5] = valPtr[5];
+ addr[6] = valPtr[6];
+ addr[7] = valPtr[7];
+ }
+ }
+ catch (NullReferenceException)
+ {
+ // this method is documented to throw AccessViolationException on any AV
+ throw new AccessViolationException();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [DllImport(Win32Native.SHIM, EntryPoint="ND_WI8")]
+ [SuppressUnmanagedCodeSecurity]
+ public static extern void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val);
+#else
+ public static void WriteInt64([MarshalAs(UnmanagedType.AsAny),In,Out] Object ptr, int ofs, long val)
+ {
+ throw new PlatformNotSupportedException();
+ }
+#endif // !FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void WriteInt64(IntPtr ptr, long val)
+ {
+ WriteInt64(ptr, 0, val);
+ }
+
+
+ //====================================================================
+ // GetLastWin32Error
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern int GetLastWin32Error();
+
+
+ //====================================================================
+ // SetLastWin32Error
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern void SetLastWin32Error(int error);
+
+
+ //====================================================================
+ // GetHRForLastWin32Error
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int GetHRForLastWin32Error()
+ {
+ int dwLastError = GetLastWin32Error();
+ if ((dwLastError & 0x80000000) == 0x80000000)
+ return dwLastError;
+ else
+ return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
+ }
+
+
+ //====================================================================
+ // Prelink
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Prelink(MethodInfo m)
+ {
+ if (m == null)
+ throw new ArgumentNullException("m");
+ Contract.EndContractBlock();
+
+ RuntimeMethodInfo rmi = m as RuntimeMethodInfo;
+
+ if (rmi == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"));
+
+ InternalPrelink(rmi);
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ [SecurityCritical]
+ private static extern void InternalPrelink(IRuntimeMethodInfo m);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void PrelinkAll(Type c)
+ {
+ if (c == null)
+ throw new ArgumentNullException("c");
+ Contract.EndContractBlock();
+
+ MethodInfo[] mi = c.GetMethods();
+ if (mi != null)
+ {
+ for (int i = 0; i < mi.Length; i++)
+ {
+ Prelink(mi[i]);
+ }
+ }
+ }
+
+ //====================================================================
+ // NumParamBytes
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static int NumParamBytes(MethodInfo m)
+ {
+ if (m == null)
+ throw new ArgumentNullException("m");
+ Contract.EndContractBlock();
+
+ RuntimeMethodInfo rmi = m as RuntimeMethodInfo;
+ if (rmi == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"));
+
+ return InternalNumParamBytes(rmi);
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ [SecurityCritical]
+ private static extern int InternalNumParamBytes(IRuntimeMethodInfo m);
+
+ //====================================================================
+ // Win32 Exception stuff
+ // These are mostly interesting for Structured exception handling,
+ // but need to be exposed for all exceptions (not just SEHException).
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers();
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetExceptionCode();
+
+
+ //====================================================================
+ // Marshals data from a structure class to a native memory block.
+ // If the structure contains pointers to allocated blocks and
+ // "fDeleteOld" is true, this routine will call DestroyStructure() first.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static extern void StructureToPtr(Object structure, IntPtr ptr, bool fDeleteOld);
+
+ [System.Security.SecurityCritical]
+ public static void StructureToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld)
+ {
+ StructureToPtr((object)structure, ptr, fDeleteOld);
+ }
+
+ //====================================================================
+ // Marshals data from a native memory block to a preallocated structure class.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static void PtrToStructure(IntPtr ptr, Object structure)
+ {
+ PtrToStructureHelper(ptr, structure, false);
+ }
+
+ [System.Security.SecurityCritical]
+ public static void PtrToStructure<T>(IntPtr ptr, T structure)
+ {
+ PtrToStructure(ptr, (object)structure);
+ }
+
+ //====================================================================
+ // Creates a new instance of "structuretype" and marshals data from a
+ // native memory block to it.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Object PtrToStructure(IntPtr ptr, Type structureType)
+ {
+ if (ptr == IntPtr.Zero) return null;
+
+ if (structureType == null)
+ throw new ArgumentNullException("structureType");
+
+ if (structureType.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "structureType");
+
+ RuntimeType rt = structureType.UnderlyingSystemType as RuntimeType;
+
+ if (rt == null)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeType"), "type");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ Object structure = rt.CreateInstanceDefaultCtor(false /*publicOnly*/, false /*skipCheckThis*/, false /*fillCache*/, ref stackMark);
+ PtrToStructureHelper(ptr, structure, true);
+ return structure;
+ }
+
+ [System.Security.SecurityCritical]
+ public static T PtrToStructure<T>(IntPtr ptr)
+ {
+ return (T)PtrToStructure(ptr, typeof(T));
+ }
+
+ //====================================================================
+ // Helper function to copy a pointer into a preallocated structure.
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void PtrToStructureHelper(IntPtr ptr, Object structure, bool allowValueClasses);
+
+
+ //====================================================================
+ // Freeds all substructures pointed to by the native memory block.
+ // "structureclass" is used to provide layout information.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static extern void DestroyStructure(IntPtr ptr, Type structuretype);
+
+ [System.Security.SecurityCritical]
+ public static void DestroyStructure<T>(IntPtr ptr)
+ {
+ DestroyStructure(ptr, typeof(T));
+ }
+
+ //====================================================================
+ // Returns the HInstance for this module. Returns -1 if the module
+ // doesn't have an HInstance. In Memory (Dynamic) Modules won't have
+ // an HInstance.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr GetHINSTANCE(Module m)
+ {
+ if (m == null)
+ throw new ArgumentNullException("m");
+ Contract.EndContractBlock();
+
+ RuntimeModule rtModule = m as RuntimeModule;
+ if (rtModule == null)
+ {
+ ModuleBuilder mb = m as ModuleBuilder;
+ if (mb != null)
+ rtModule = mb.InternalModule;
+ }
+
+ if (rtModule == null)
+ throw new ArgumentNullException("m",Environment.GetResourceString("Argument_MustBeRuntimeModule"));
+
+ return GetHINSTANCE(rtModule.GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private extern static IntPtr GetHINSTANCE(RuntimeModule m);
+
+ //====================================================================
+ // Throws a CLR exception based on the HRESULT.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ThrowExceptionForHR(int errorCode)
+ {
+ if (errorCode < 0)
+ ThrowExceptionForHRInternal(errorCode, IntPtr.Zero);
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo)
+ {
+ if (errorCode < 0)
+ ThrowExceptionForHRInternal(errorCode, errorInfo);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ThrowExceptionForHRInternal(int errorCode, IntPtr errorInfo);
+
+
+ //====================================================================
+ // Converts the HRESULT to a CLR exception.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Exception GetExceptionForHR(int errorCode)
+ {
+ if (errorCode < 0)
+ return GetExceptionForHRInternal(errorCode, IntPtr.Zero);
+ else
+ return null;
+ }
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo)
+ {
+ if (errorCode < 0)
+ return GetExceptionForHRInternal(errorCode, errorInfo);
+ else
+ return null;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Exception GetExceptionForHRInternal(int errorCode, IntPtr errorInfo);
+
+
+ //====================================================================
+ // This method is intended for compiler code generators rather
+ // than applications.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ObsoleteAttribute("The GetUnmanagedThunkForManagedMethodPtr method has been deprecated and will be removed in a future release.", false)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern IntPtr GetUnmanagedThunkForManagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature);
+
+ //====================================================================
+ // This method is intended for compiler code generators rather
+ // than applications.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ObsoleteAttribute("The GetManagedThunkForUnmanagedMethodPtr method has been deprecated and will be removed in a future release.", false)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern IntPtr GetManagedThunkForUnmanagedMethodPtr(IntPtr pfnMethodToWrap, IntPtr pbSignature, int cbSignature);
+
+ //====================================================================
+ // The hosting APIs allow a sophisticated host to schedule fibers
+ // onto OS threads, so long as they notify the runtime of this
+ // activity. A fiber cookie can be redeemed for its managed Thread
+ // object by calling the following service.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ObsoleteAttribute("The GetThreadFromFiberCookie method has been deprecated. Use the hosting API to perform this operation.", false)]
+ public static Thread GetThreadFromFiberCookie(int cookie)
+ {
+ if (cookie == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ArgumentZero"), "cookie");
+ Contract.EndContractBlock();
+
+ return InternalGetThreadFromFiberCookie(cookie);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Thread InternalGetThreadFromFiberCookie(int cookie);
+
+
+ //====================================================================
+ // Memory allocation and deallocation.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static IntPtr AllocHGlobal(IntPtr cb)
+ {
+ // For backwards compatibility on 32 bit platforms, ensure we pass values between
+ // Int32.MaxValue and UInt32.MaxValue to Windows. If the binary has had the
+ // LARGEADDRESSAWARE bit set in the PE header, it may get 3 or 4 GB of user mode
+ // address space. It is remotely that those allocations could have succeeded,
+ // though I couldn't reproduce that. In either case, that means we should continue
+ // throwing an OOM instead of an ArgumentOutOfRangeException for "negative" amounts of memory.
+ UIntPtr numBytes;
+#if BIT64
+ numBytes = new UIntPtr(unchecked((ulong)cb.ToInt64()));
+#else // 32
+ numBytes = new UIntPtr(unchecked((uint)cb.ToInt32()));
+#endif
+
+ IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));
+
+ if (pNewMem == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+ return pNewMem;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static IntPtr AllocHGlobal(int cb)
+ {
+ return AllocHGlobal((IntPtr)cb);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void FreeHGlobal(IntPtr hglobal)
+ {
+ if (IsNotWin32Atom(hglobal)) {
+ if (IntPtr.Zero != Win32Native.LocalFree(hglobal)) {
+ ThrowExceptionForHR(GetHRForLastWin32Error());
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb)
+ {
+ IntPtr pNewMem = Win32Native.LocalReAlloc(pv, cb, LMEM_MOVEABLE);
+ if (pNewMem == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+ return pNewMem;
+ }
+
+
+ //====================================================================
+ // String convertions.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static IntPtr StringToHGlobalAnsi(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
+
+ // Overflow checking
+ if (nb < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ UIntPtr len = new UIntPtr((uint)nb);
+ IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
+
+ if (hglobal == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ s.ConvertToAnsi((byte *)hglobal, nb, false, false);
+ return hglobal;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static IntPtr StringToHGlobalUni(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = (s.Length + 1) * 2;
+
+ // Overflow checking
+ if (nb < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ UIntPtr len = new UIntPtr((uint)nb);
+ IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
+
+ if (hglobal == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ fixed (char* firstChar = s)
+ {
+ String.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
+ }
+ return hglobal;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr StringToHGlobalAuto(String s)
+ {
+ // Ansi platforms are no longer supported
+ return StringToHGlobalUni(s);
+ }
+
+#if FEATURE_COMINTEROP
+
+ //====================================================================
+ // Converts the CLR exception to an HRESULT. This function also sets
+ // up an IErrorInfo for the exception.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetHRForException(Exception e);
+
+ //====================================================================
+ // Converts the CLR exception to an HRESULT. This function also sets
+ // up an IErrorInfo for the exception.
+ // This function is only used in WinRT and converts ObjectDisposedException
+ // to RO_E_CLOSED
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetHRForException_WinRT(Exception e);
+
+ internal static readonly Guid ManagedNameGuid = new Guid("{0F21F359-AB84-41E8-9A78-36D110E6D2F9}");
+
+ //====================================================================
+ // Given a managed object that wraps a UCOMITypeLib, return its name
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibName(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)]
+ public static String GetTypeLibName(UCOMITypeLib pTLB)
+ {
+ return GetTypeLibName((ITypeLib)pTLB);
+ }
+
+
+ //====================================================================
+ // Given a managed object that wraps an ITypeLib, return its name
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String GetTypeLibName(ITypeLib typelib)
+ {
+ if (typelib == null)
+ throw new ArgumentNullException("typelib");
+ Contract.EndContractBlock();
+
+ String strTypeLibName = null;
+ String strDocString = null;
+ int dwHelpContext = 0;
+ String strHelpFile = null;
+
+ typelib.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
+
+ return strTypeLibName;
+ }
+
+ //====================================================================
+ // Internal version of GetTypeLibName
+ // Support GUID_ManagedName which aligns with TlbImp
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal static String GetTypeLibNameInternal(ITypeLib typelib)
+ {
+ if (typelib == null)
+ throw new ArgumentNullException("typelib");
+ Contract.EndContractBlock();
+
+ // Try GUID_ManagedName first
+ ITypeLib2 typeLib2 = typelib as ITypeLib2;
+ if (typeLib2 != null)
+ {
+ Guid guid = ManagedNameGuid;
+ object val;
+
+ try
+ {
+ typeLib2.GetCustData(ref guid, out val);
+ }
+ catch(Exception)
+ {
+ val = null;
+ }
+
+ if (val != null && val.GetType() == typeof(string))
+ {
+ string customManagedNamespace = (string)val;
+ customManagedNamespace = customManagedNamespace.Trim();
+ if (customManagedNamespace.EndsWith(".DLL", StringComparison.OrdinalIgnoreCase))
+ customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4);
+ else if (customManagedNamespace.EndsWith(".EXE", StringComparison.OrdinalIgnoreCase))
+ customManagedNamespace = customManagedNamespace.Substring(0, customManagedNamespace.Length - 4);
+ return customManagedNamespace;
+ }
+ }
+
+ return GetTypeLibName(typelib);
+ }
+
+
+ //====================================================================
+ // Given an managed object that wraps an UCOMITypeLib, return its guid
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibGuid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)]
+ public static Guid GetTypeLibGuid(UCOMITypeLib pTLB)
+ {
+ return GetTypeLibGuid((ITypeLib)pTLB);
+ }
+
+ //====================================================================
+ // Given an managed object that wraps an ITypeLib, return its guid
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Guid GetTypeLibGuid(ITypeLib typelib)
+ {
+ Guid result = new Guid ();
+ FCallGetTypeLibGuid (ref result, typelib);
+ return result;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallGetTypeLibGuid(ref Guid result, ITypeLib pTLB);
+
+ //====================================================================
+ // Given a managed object that wraps a UCOMITypeLib, return its lcid
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeLibLcid(ITypeLib pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)]
+ public static int GetTypeLibLcid(UCOMITypeLib pTLB)
+ {
+ return GetTypeLibLcid((ITypeLib)pTLB);
+ }
+
+ //====================================================================
+ // Given a managed object that wraps an ITypeLib, return its lcid
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetTypeLibLcid(ITypeLib typelib);
+
+ //====================================================================
+ // Given a managed object that wraps an ITypeLib, return it's
+ // version information.
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void GetTypeLibVersion(ITypeLib typeLibrary, out int major, out int minor);
+
+ //====================================================================
+ // Given a managed object that wraps an ITypeInfo, return its guid.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Guid GetTypeInfoGuid(ITypeInfo typeInfo)
+ {
+ Guid result = new Guid ();
+ FCallGetTypeInfoGuid (ref result, typeInfo);
+ return result;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallGetTypeInfoGuid(ref Guid result, ITypeInfo typeInfo);
+
+ //====================================================================
+ // Given a assembly, return the TLBID that will be generated for the
+ // typelib exported from the assembly.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Guid GetTypeLibGuidForAssembly(Assembly asm)
+ {
+ if (asm == null)
+ throw new ArgumentNullException("asm");
+ Contract.EndContractBlock();
+
+ RuntimeAssembly rtAssembly = asm as RuntimeAssembly;
+ if (rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "asm");
+
+ Guid result = new Guid();
+ FCallGetTypeLibGuidForAssembly(ref result, rtAssembly);
+ return result;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallGetTypeLibGuidForAssembly(ref Guid result, RuntimeAssembly asm);
+
+ //====================================================================
+ // Given a assembly, return the version number of the type library
+ // that would be exported from the assembly.
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void _GetTypeLibVersionForAssembly(RuntimeAssembly inputAssembly, out int majorVersion, out int minorVersion);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void GetTypeLibVersionForAssembly(Assembly inputAssembly, out int majorVersion, out int minorVersion)
+ {
+ if (inputAssembly == null)
+ throw new ArgumentNullException("inputAssembly");
+ Contract.EndContractBlock();
+
+ RuntimeAssembly rtAssembly = inputAssembly as RuntimeAssembly;
+ if (rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "inputAssembly");
+
+ _GetTypeLibVersionForAssembly(rtAssembly, out majorVersion, out minorVersion);
+ }
+
+ //====================================================================
+ // Given a managed object that wraps an UCOMITypeInfo, return its name
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Use System.Runtime.InteropServices.Marshal.GetTypeInfoName(ITypeInfo pTLB) instead. http://go.microsoft.com/fwlink/?linkid=14202&ID=0000011.", false)]
+ public static String GetTypeInfoName(UCOMITypeInfo pTI)
+ {
+ return GetTypeInfoName((ITypeInfo)pTI);
+ }
+
+ //====================================================================
+ // Given a managed object that wraps an ITypeInfo, return its name
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String GetTypeInfoName(ITypeInfo typeInfo)
+ {
+ if (typeInfo == null)
+ throw new ArgumentNullException("typeInfo");
+ Contract.EndContractBlock();
+
+ String strTypeLibName = null;
+ String strDocString = null;
+ int dwHelpContext = 0;
+ String strHelpFile = null;
+
+ typeInfo.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
+
+ return strTypeLibName;
+ }
+
+ //====================================================================
+ // Internal version of GetTypeInfoName
+ // Support GUID_ManagedName which aligns with TlbImp
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal static String GetTypeInfoNameInternal(ITypeInfo typeInfo, out bool hasManagedName)
+ {
+ if (typeInfo == null)
+ throw new ArgumentNullException("typeInfo");
+ Contract.EndContractBlock();
+
+ // Try ManagedNameGuid first
+ ITypeInfo2 typeInfo2 = typeInfo as ITypeInfo2;
+ if (typeInfo2 != null)
+ {
+ Guid guid = ManagedNameGuid;
+ object val;
+
+ try
+ {
+ typeInfo2.GetCustData(ref guid, out val);
+ }
+ catch(Exception)
+ {
+ val = null;
+ }
+
+ if (val != null && val.GetType() == typeof(string))
+ {
+ hasManagedName = true;
+ return (string)val;
+ }
+ }
+
+ hasManagedName = false;
+ return GetTypeInfoName(typeInfo);
+ }
+
+ //====================================================================
+ // Get the corresponding managed name as converted by TlbImp
+ // Used to get the type using GetType() from imported assemblies
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal static String GetManagedTypeInfoNameInternal(ITypeLib typeLib, ITypeInfo typeInfo)
+ {
+ bool hasManagedName;
+ string name = GetTypeInfoNameInternal(typeInfo, out hasManagedName);
+ if (hasManagedName)
+ return name;
+ else
+ return GetTypeLibNameInternal(typeLib) + "." + name;
+ }
+
+ //====================================================================
+ // If a type with the specified GUID is loaded, this method will
+ // return the reflection type that represents it. Otherwise it returns
+ // NULL.
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Type GetLoadedTypeForGUID(ref Guid guid);
+
+#if !FEATURE_CORECLR // current implementation requires reflection only load
+ //====================================================================
+ // map ITypeInfo* to Type
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeForITypeInfo(IntPtr /* ITypeInfo* */ piTypeInfo)
+ {
+ ITypeInfo pTI = null;
+ ITypeLib pTLB = null;
+ Type TypeObj = null;
+ Assembly AsmBldr = null;
+ TypeLibConverter TlbConverter = null;
+ int Index = 0;
+ Guid clsid;
+
+ // If the input ITypeInfo is NULL then return NULL.
+ if (piTypeInfo == IntPtr.Zero)
+ return null;
+
+ // Wrap the ITypeInfo in a CLR object.
+ pTI = (ITypeInfo)GetObjectForIUnknown(piTypeInfo);
+
+ // Check to see if a class exists with the specified GUID.
+
+ clsid = GetTypeInfoGuid(pTI);
+ TypeObj = GetLoadedTypeForGUID(ref clsid);
+
+ // If we managed to find the type based on the GUID then return it.
+ if (TypeObj != null)
+ return TypeObj;
+
+ // There is no type with the specified GUID in the app domain so lets
+ // try and convert the containing typelib.
+ try
+ {
+ pTI.GetContainingTypeLib(out pTLB, out Index);
+ }
+ catch(COMException)
+ {
+ pTLB = null;
+ }
+
+ // Check to see if we managed to get a containing typelib.
+ if (pTLB != null)
+ {
+ // Get the assembly name from the typelib.
+ AssemblyName AsmName = TypeLibConverter.GetAssemblyNameFromTypelib(pTLB, null, null, null, null, AssemblyNameFlags.None);
+ String AsmNameString = AsmName.FullName;
+
+ // Check to see if the assembly that will contain the type already exists.
+ Assembly[] aAssemblies = Thread.GetDomain().GetAssemblies();
+ int NumAssemblies = aAssemblies.Length;
+ for (int i = 0; i < NumAssemblies; i++)
+ {
+ if (String.Compare(aAssemblies[i].FullName,
+ AsmNameString,StringComparison.Ordinal) == 0)
+ AsmBldr = aAssemblies[i];
+ }
+
+ // If we haven't imported the assembly yet then import it.
+ if (AsmBldr == null)
+ {
+ TlbConverter = new TypeLibConverter();
+ AsmBldr = TlbConverter.ConvertTypeLibToAssembly(pTLB,
+ GetTypeLibName(pTLB) + ".dll", 0, new ImporterCallback(), null, null, null, null);
+ }
+
+ // Load the type object from the imported typelib.
+ // Call GetManagedTypeInfoNameInternal to align with TlbImp behavior
+ TypeObj = AsmBldr.GetType(GetManagedTypeInfoNameInternal(pTLB, pTI), true, false);
+ if (TypeObj != null && !TypeObj.IsVisible)
+ TypeObj = null;
+ }
+ else
+ {
+ // If the ITypeInfo does not have a containing typelib then simply
+ // return Object as the type.
+ TypeObj = typeof(Object);
+ }
+
+ return TypeObj;
+ }
+#endif // #if !FEATURE_CORECLR
+
+ // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it
+ // on Marshal for more consistent API surface.
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif //!FEATURE_CORECLR
+ public static Type GetTypeFromCLSID(Guid clsid)
+ {
+ return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false);
+ }
+
+ //====================================================================
+ // map Type to ITypeInfo*
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern IntPtr /* ITypeInfo* */ GetITypeInfoForType(Type t);
+
+ //====================================================================
+ // return the IUnknown* for an Object if the current context
+ // is the one where the RCW was first seen. Will return null
+ // otherwise.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o)
+ {
+ return GetIUnknownForObjectNative(o, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetIUnknownForObjectInContext(Object o)
+ {
+ return GetIUnknownForObjectNative(o, true);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr /* IUnknown* */ GetIUnknownForObjectNative(Object o, bool onlyInContext);
+
+ //====================================================================
+ // return the raw IUnknown* for a COM Object not related to current
+ // context
+ // Does not call AddRef
+ //====================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr /* IUnknown* */ GetRawIUnknownForComObjectNoAddRef(Object o);
+
+ //====================================================================
+ // return the IDispatch* for an Object
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IDispatch */ GetIDispatchForObject(Object o)
+ {
+ return GetIDispatchForObjectNative(o, false);
+ }
+
+ //====================================================================
+ // return the IDispatch* for an Object if the current context
+ // is the one where the RCW was first seen. Will return null
+ // otherwise.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetIDispatchForObjectInContext(Object o)
+ {
+ return GetIDispatchForObjectNative(o, true);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr /* IUnknown* */ GetIDispatchForObjectNative(Object o, bool onlyInContext);
+
+ //====================================================================
+ // return the IUnknown* representing the interface for the Object
+ // Object o should support Type T
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T)
+ {
+ return GetComInterfaceForObjectNative(o, T, false, true);
+ }
+
+ [System.Security.SecurityCritical]
+ public static IntPtr GetComInterfaceForObject<T, TInterface>(T o)
+ {
+ return GetComInterfaceForObject(o, typeof(TInterface));
+ }
+
+ //====================================================================
+ // return the IUnknown* representing the interface for the Object
+ // Object o should support Type T, it refer the value of mode to
+ // invoke customized QueryInterface or not
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T, CustomQueryInterfaceMode mode)
+ {
+ bool bEnableCustomizedQueryInterface = ((mode == CustomQueryInterfaceMode.Allow) ? true : false);
+ return GetComInterfaceForObjectNative(o, T, false, bEnableCustomizedQueryInterface);
+ }
+
+ //====================================================================
+ // return the IUnknown* representing the interface for the Object
+ // Object o should support Type T if the current context
+ // is the one where the RCW was first seen. Will return null
+ // otherwise.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr /* IUnknown* */ GetComInterfaceForObjectInContext(Object o, Type t)
+ {
+ return GetComInterfaceForObjectNative(o, t, true, true);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr /* IUnknown* */ GetComInterfaceForObjectNative(Object o, Type t, bool onlyInContext, bool fEnalbeCustomizedQueryInterface);
+
+ //====================================================================
+ // return an Object for IUnknown
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk);
+
+ //====================================================================
+ // Return a unique Object given an IUnknown. This ensures that you
+ // receive a fresh object (we will not look in the cache to match up this
+ // IUnknown to an already existing object). This is useful in cases
+ // where you want to be able to call ReleaseComObject on a RCW
+ // and not worry about other active uses of said RCW.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object GetUniqueObjectForIUnknown(IntPtr unknown);
+
+ //====================================================================
+ // return an Object for IUnknown, using the Type T,
+ // NOTE:
+ // Type T should be either a COM imported Type or a sub-type of COM
+ // imported Type
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, Object o);
+
+ [System.Security.SecurityCritical]
+ public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o)
+ {
+ return CreateAggregatedObject(pOuter, (object)o);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void CleanupUnusedObjectsInCurrentContext();
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool AreComObjectsAvailableForCleanup();
+
+ //====================================================================
+ // check if the object is classic COM component
+ //====================================================================
+#if !FEATURE_CORECLR // with FEATURE_CORECLR, the whole type is SecurityCritical
+ [System.Security.SecuritySafeCritical]
+#endif
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool IsComObject(Object o);
+
+#endif // FEATURE_COMINTEROP
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr AllocCoTaskMem(int cb)
+ {
+ IntPtr pNewMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)cb));
+ if (pNewMem == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ return pNewMem;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static IntPtr StringToCoTaskMemUni(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = (s.Length + 1) * 2;
+
+ // Overflow checking
+ if (nb < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
+
+ if (hglobal == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ fixed (char* firstChar = s)
+ {
+ String.wstrcpy((char *)hglobal, firstChar, s.Length + 1);
+ }
+ return hglobal;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static IntPtr StringToCoTaskMemUTF8(String s)
+ {
+ const int MAX_UTF8_CHAR_SIZE = 3;
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = (s.Length + 1) * MAX_UTF8_CHAR_SIZE;
+
+ // Overflow checking
+ if (nb < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ IntPtr pMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb +1));
+
+ if (pMem == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ byte* pbMem = (byte*)pMem;
+ int nbWritten = s.GetBytesFromEncoding(pbMem, nb, Encoding.UTF8);
+ pbMem[nbWritten] = 0;
+ return pMem;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr StringToCoTaskMemAuto(String s)
+ {
+ // Ansi platforms are no longer supported
+ return StringToCoTaskMemUni(s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static IntPtr StringToCoTaskMemAnsi(String s)
+ {
+ if (s == null)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
+
+ // Overflow checking
+ if (nb < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
+
+ if (hglobal == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+ else
+ {
+ s.ConvertToAnsi((byte *)hglobal, nb, false, false);
+ return hglobal;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void FreeCoTaskMem(IntPtr ptr)
+ {
+ if (IsNotWin32Atom(ptr)) {
+ Win32Native.CoTaskMemFree(ptr);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr ReAllocCoTaskMem(IntPtr pv, int cb)
+ {
+ IntPtr pNewMem = Win32Native.CoTaskMemRealloc(pv, new UIntPtr((uint)cb));
+ if (pNewMem == IntPtr.Zero && cb != 0)
+ {
+ throw new OutOfMemoryException();
+ }
+ return pNewMem;
+ }
+
+ //====================================================================
+ // BSTR allocation and dealocation.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void FreeBSTR(IntPtr ptr)
+ {
+ if (IsNotWin32Atom(ptr))
+ {
+ Win32Native.SysFreeString(ptr);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr StringToBSTR(String s)
+ {
+ if (s == null)
+ return IntPtr.Zero;
+
+ // Overflow checking
+ if (s.Length + 1 < s.Length)
+ throw new ArgumentOutOfRangeException("s");
+
+ IntPtr bstr = Win32Native.SysAllocStringLen(s, s.Length);
+ if (bstr == IntPtr.Zero)
+ throw new OutOfMemoryException();
+
+ return bstr;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String PtrToStringBSTR(IntPtr ptr)
+ {
+ return PtrToStringUni(ptr, (int)Win32Native.SysStringLen(ptr));
+ }
+
+#if FEATURE_COMINTEROP
+ //====================================================================
+ // release the COM component and if the reference hits 0 zombie this object
+ // further usage of this Object might throw an exception
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static int ReleaseComObject(Object o)
+ {
+ __ComObject co = null;
+
+ // Make sure the obj is an __ComObject.
+ try
+ {
+ co = (__ComObject)o;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o");
+ }
+
+ return co.ReleaseSelf();
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int InternalReleaseComObject(Object o);
+
+
+ //====================================================================
+ // release the COM component and zombie this object
+ // further usage of this Object might throw an exception
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Int32 FinalReleaseComObject(Object o)
+ {
+ if (o == null)
+ throw new ArgumentNullException("o");
+ Contract.EndContractBlock();
+
+ __ComObject co = null;
+
+ // Make sure the obj is an __ComObject.
+ try
+ {
+ co = (__ComObject)o;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o");
+ }
+
+ co.FinalReleaseSelf();
+
+ return 0;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InternalFinalReleaseComObject(Object o);
+
+ //====================================================================
+ // This method retrieves data from the COM object.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object GetComObjectData(Object obj, Object key)
+ {
+ // Validate that the arguments aren't null.
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+ if (key == null)
+ throw new ArgumentNullException("key");
+ Contract.EndContractBlock();
+
+ __ComObject comObj = null;
+
+ // Make sure the obj is an __ComObject.
+ try
+ {
+ comObj = (__ComObject)obj;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj");
+ }
+
+ if (obj.GetType().IsWindowsRuntimeObject)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj");
+ }
+
+ // Retrieve the data from the __ComObject.
+ return comObj.GetData(key);
+ }
+
+ //====================================================================
+ // This method sets data on the COM object. The data can only be set
+ // once for a given key and cannot be removed. This function returns
+ // true if the data has been added, false if the data could not be
+ // added because there already was data for the specified key.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static bool SetComObjectData(Object obj, Object key, Object data)
+ {
+ // Validate that the arguments aren't null. The data can validly be null.
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+ if (key == null)
+ throw new ArgumentNullException("key");
+ Contract.EndContractBlock();
+
+ __ComObject comObj = null;
+
+ // Make sure the obj is an __ComObject.
+ try
+ {
+ comObj = (__ComObject)obj;
+ }
+ catch (InvalidCastException)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "obj");
+ }
+
+ if (obj.GetType().IsWindowsRuntimeObject)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "obj");
+ }
+
+ // Retrieve the data from the __ComObject.
+ return comObj.SetData(key, data);
+ }
+
+ //====================================================================
+ // This method takes the given COM object and wraps it in an object
+ // of the specified type. The type must be derived from __ComObject.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object CreateWrapperOfType(Object o, Type t)
+ {
+ // Validate the arguments.
+ if (t == null)
+ throw new ArgumentNullException("t");
+ if (!t.IsCOMObject)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotComObject"), "t");
+ if (t.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t");
+ Contract.EndContractBlock();
+
+ if (t.IsWindowsRuntimeObject)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeIsWinRTType"), "t");
+
+ // Check for the null case.
+ if (o == null)
+ return null;
+
+ // Make sure the object is a COM object.
+ if (!o.GetType().IsCOMObject)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjNotComObject"), "o");
+ if (o.GetType().IsWindowsRuntimeObject)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ObjIsWinRTObject"), "o");
+
+ // Check to see if the type of the object is the requested type.
+ if (o.GetType() == t)
+ return o;
+
+ // Check to see if we already have a cached wrapper for this type.
+ Object Wrapper = GetComObjectData(o, t);
+ if (Wrapper == null)
+ {
+ // Create the wrapper for the specified type.
+ Wrapper = InternalCreateWrapperOfType(o, t);
+
+ // Attempt to cache the wrapper on the object.
+ if (!SetComObjectData(o, t, Wrapper))
+ {
+ // Another thead already cached the wrapper so use that one instead.
+ Wrapper = GetComObjectData(o, t);
+ }
+ }
+
+ return Wrapper;
+ }
+
+ [System.Security.SecurityCritical]
+ public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
+ {
+ return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper));
+ }
+
+ //====================================================================
+ // Helper method called from CreateWrapperOfType.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object InternalCreateWrapperOfType(Object o, Type t);
+
+ //====================================================================
+ // There may be a thread-based cache of COM components. This service can
+ // force the aggressive release of the current thread's cache.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("This API did not perform any operation and will be removed in future versions of the CLR.", false)]
+ public static void ReleaseThreadCache()
+ {
+ }
+
+ //====================================================================
+ // check if the type is visible from COM.
+ //====================================================================
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool IsTypeVisibleFromCom(Type t);
+
+ //====================================================================
+ // IUnknown Helpers
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int /* HRESULT */ QueryInterface(IntPtr /* IUnknown */ pUnk, ref Guid iid, out IntPtr ppv);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int /* ULONG */ AddRef(IntPtr /* IUnknown */ pUnk );
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk );
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void GetNativeVariantForObject(Object obj, /* VARIANT * */ IntPtr pDstNativeVariant);
+
+ [System.Security.SecurityCritical]
+ public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant)
+ {
+ GetNativeVariantForObject((object)obj, pDstNativeVariant);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant );
+
+ [System.Security.SecurityCritical]
+ public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant)
+ {
+ return (T)GetObjectForNativeVariant(pSrcNativeVariant);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern Object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars );
+
+ [System.Security.SecurityCritical]
+ public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars)
+ {
+ object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars);
+ T[] result = null;
+
+ if (objects != null)
+ {
+ result = new T[objects.Length];
+ Array.Copy(objects, result, objects.Length);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// <para>Returns the first valid COM slot that GetMethodInfoForSlot will work on
+ /// This will be 3 for IUnknown based interfaces and 7 for IDispatch based interfaces. </para>
+ /// </summary>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetStartComSlot(Type t);
+
+ /// <summary>
+ /// <para>Returns the last valid COM slot that GetMethodInfoForSlot will work on. </para>
+ /// </summary>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern int GetEndComSlot(Type t);
+
+ /// <summary>
+ /// <para>Returns the MemberInfo that COM callers calling through the exposed
+ /// vtable on the given slot will be calling. The slot should take into account
+ /// if the exposed interface is IUnknown based or IDispatch based.
+ /// For classes, the lookup is done on the default interface that will be
+ /// exposed for the class. </para>
+ /// </summary>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern MemberInfo GetMethodInfoForComSlot(Type t, int slot, ref ComMemberType memberType);
+
+ /// <summary>
+ /// <para>Returns the COM slot for a memeber info, taking into account whether
+ /// the exposed interface is IUnknown based or IDispatch based</para>
+ /// </summary>
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static int GetComSlotForMethodInfo(MemberInfo m)
+ {
+ if (m== null)
+ throw new ArgumentNullException("m");
+
+ if (!(m is RuntimeMethodInfo))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"), "m");
+
+ if (!m.DeclaringType.IsInterface)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeInterfaceMethod"), "m");
+ if (m.DeclaringType.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "m");
+ Contract.EndContractBlock();
+
+ return InternalGetComSlotForMethodInfo((IRuntimeMethodInfo)m);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int InternalGetComSlotForMethodInfo(IRuntimeMethodInfo m);
+
+ //====================================================================
+ // This method generates a GUID for the specified type. If the type
+ // has a GUID in the metadata then it is returned otherwise a stable
+ // guid GUID is generated based on the fully qualified name of the
+ // type.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Guid GenerateGuidForType(Type type)
+ {
+ Guid result = new Guid ();
+ FCallGenerateGuidForType (ref result, type);
+ return result;
+ }
+
+ // The full assembly name is used to compute the GUID, so this should be SxS-safe
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void FCallGenerateGuidForType(ref Guid result, Type type);
+
+ //====================================================================
+ // This method generates a PROGID for the specified type. If the type
+ // has a PROGID in the metadata then it is returned otherwise a stable
+ // PROGID is generated based on the fully qualified name of the
+ // type.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static String GenerateProgIdForType(Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+ if (type.IsImport)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustNotBeComImport"), "type");
+ if (type.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "type");
+ Contract.EndContractBlock();
+
+ if (!RegistrationServices.TypeRequiresRegistrationHelper(type))
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"), "type");
+
+ IList<CustomAttributeData> cas = CustomAttributeData.GetCustomAttributes(type);
+ for (int i = 0; i < cas.Count; i ++)
+ {
+ if (cas[i].Constructor.DeclaringType == typeof(ProgIdAttribute))
+ {
+ // Retrieve the PROGID string from the ProgIdAttribute.
+ IList<CustomAttributeTypedArgument> caConstructorArgs = cas[i].ConstructorArguments;
+ Contract.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1");
+
+ CustomAttributeTypedArgument progIdConstructorArg = caConstructorArgs[0];
+ Contract.Assert(progIdConstructorArg.ArgumentType == typeof(String), "progIdConstructorArg.ArgumentType == typeof(String)");
+
+ String strProgId = (String)progIdConstructorArg.Value;
+
+ if (strProgId == null)
+ strProgId = String.Empty;
+
+ return strProgId;
+ }
+ }
+
+ // If there is no prog ID attribute then use the full name of the type as the prog id.
+ return type.FullName;
+ }
+
+ //====================================================================
+ // This method binds to the specified moniker.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object BindToMoniker(String monikerName)
+ {
+ Object obj = null;
+ IBindCtx bindctx = null;
+ CreateBindCtx(0, out bindctx);
+
+ UInt32 cbEaten;
+ IMoniker pmoniker = null;
+ MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker);
+
+ BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj);
+ return obj;
+ }
+
+ //====================================================================
+ // This method gets the currently running object.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object GetActiveObject(String progID)
+ {
+ Object obj = null;
+ Guid clsid;
+
+ // Call CLSIDFromProgIDEx first then fall back on CLSIDFromProgID if
+ // CLSIDFromProgIDEx doesn't exist.
+ try
+ {
+ CLSIDFromProgIDEx(progID, out clsid);
+ }
+// catch
+ catch(Exception)
+ {
+ CLSIDFromProgID(progID, out clsid);
+ }
+
+ GetActiveObject(ref clsid, IntPtr.Zero, out obj);
+ return obj;
+ }
+
+ [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void CLSIDFromProgIDEx([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid);
+
+ [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void CLSIDFromProgID([MarshalAs(UnmanagedType.LPWStr)] String progId, out Guid clsid);
+
+ [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void CreateBindCtx(UInt32 reserved, out IBindCtx ppbc);
+
+ [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] String szUserName, out UInt32 pchEaten, out IMoniker ppmk);
+
+ [DllImport(Microsoft.Win32.Win32Native.OLE32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void BindMoniker(IMoniker pmk, UInt32 grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
+
+ [DllImport(Microsoft.Win32.Win32Native.OLEAUT32, PreserveSig = false)]
+ [SuppressUnmanagedCodeSecurity]
+ [System.Security.SecurityCritical] // auto-generated
+ private static extern void GetActiveObject(ref Guid rclsid, IntPtr reserved, [MarshalAs(UnmanagedType.Interface)] out Object ppunk);
+
+ //========================================================================
+ // Private method called from remoting to support ServicedComponents.
+ //========================================================================
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool InternalSwitchCCW(Object oldtp, Object newtp);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object InternalWrapIUnknownWithComObject(IntPtr i);
+
+ //========================================================================
+ // Private method called from EE upon use of license/ICF2 marshaling.
+ //========================================================================
+ [SecurityCritical]
+ private static IntPtr LoadLicenseManager()
+ {
+ Assembly sys = Assembly.Load("System, Version="+ ThisAssembly.Version +
+ ", Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken);
+ Type t = sys.GetType("System.ComponentModel.LicenseManager");
+ if (t == null || !t.IsVisible)
+ return IntPtr.Zero;
+ return t.TypeHandle.Value;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void ChangeWrapperHandleStrength(Object otp, bool fIsWeak);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk);
+
+#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType);
+#endif
+
+ //========================================================================
+ // Create activation factory and wraps it with a unique RCW
+ //========================================================================
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern object GetNativeActivationFactory(Type type);
+
+ //========================================================================
+ // Methods allowing retrieval of the IIDs exposed by an underlying WinRT
+ // object, as specified by the object's IInspectable::GetIids()
+ //========================================================================
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void _GetInspectableIids(ObjectHandleOnStack obj, ObjectHandleOnStack guids);
+
+ [System.Security.SecurityCritical]
+ internal static System.Guid[] GetInspectableIids(object obj)
+ {
+ System.Guid[] result = null;
+ System.__ComObject comObj = obj as System.__ComObject;
+ if (comObj != null)
+ {
+ _GetInspectableIids(JitHelpers.GetObjectHandleOnStack(ref comObj),
+ JitHelpers.GetObjectHandleOnStack(ref result));
+ }
+
+ return result;
+ }
+
+ //========================================================================
+ // Methods allowing retrieval of the cached WinRT type corresponding to
+ // the specified GUID
+ //========================================================================
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void _GetCachedWinRTTypeByIid(
+ ObjectHandleOnStack appDomainObj,
+ System.Guid iid,
+ out IntPtr rthHandle);
+
+ [System.Security.SecurityCritical]
+ internal static System.Type GetCachedWinRTTypeByIid(
+ System.AppDomain ad,
+ System.Guid iid)
+ {
+ IntPtr rthHandle;
+ _GetCachedWinRTTypeByIid(JitHelpers.GetObjectHandleOnStack(ref ad),
+ iid,
+ out rthHandle);
+ System.Type res = Type.GetTypeFromHandleUnsafe(rthHandle);
+ return res;
+ }
+
+
+ //========================================================================
+ // Methods allowing retrieval of the WinRT types cached in the specified
+ // app domain
+ //========================================================================
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void _GetCachedWinRTTypes(
+ ObjectHandleOnStack appDomainObj,
+ ref int epoch,
+ ObjectHandleOnStack winrtTypes);
+
+ [System.Security.SecurityCritical]
+ internal static System.Type[] GetCachedWinRTTypes(
+ System.AppDomain ad,
+ ref int epoch)
+ {
+ System.IntPtr[] res = null;
+
+ _GetCachedWinRTTypes(JitHelpers.GetObjectHandleOnStack(ref ad),
+ ref epoch,
+ JitHelpers.GetObjectHandleOnStack(ref res));
+
+ System.Type[] result = new System.Type[res.Length];
+ for (int i = 0; i < res.Length; ++i)
+ {
+ result[i] = Type.GetTypeFromHandleUnsafe(res[i]);
+ }
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical]
+ internal static System.Type[] GetCachedWinRTTypes(
+ System.AppDomain ad)
+ {
+ int dummyEpoch = 0;
+ return GetCachedWinRTTypes(ad, ref dummyEpoch);
+ }
+
+
+#endif // FEATURE_COMINTEROP
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t)
+ {
+ // Validate the parameters
+ if (ptr == IntPtr.Zero)
+ throw new ArgumentNullException("ptr");
+
+ if (t == null)
+ throw new ArgumentNullException("t");
+ Contract.EndContractBlock();
+
+ if ((t as RuntimeType) == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"), "t");
+
+ if (t.IsGenericType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_NeedNonGenericType"), "t");
+
+ Type c = t.BaseType;
+ if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDelegate"), "t");
+
+ return GetDelegateForFunctionPointerInternal(ptr, t);
+ }
+
+ [System.Security.SecurityCritical]
+ public static TDelegate GetDelegateForFunctionPointer<TDelegate>(IntPtr ptr)
+ {
+ return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate));
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr GetFunctionPointerForDelegate(Delegate d)
+ {
+ if (d == null)
+ throw new ArgumentNullException("d");
+ Contract.EndContractBlock();
+
+ return GetFunctionPointerForDelegateInternal(d);
+ }
+
+ [System.Security.SecurityCritical]
+ public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d)
+ {
+ return GetFunctionPointerForDelegate((Delegate)(object)d);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d);
+
+#if FEATURE_LEGACYSURFACE
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr SecureStringToBSTR(SecureString s) {
+ if( s == null) {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ return s.ToBSTR();
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s) {
+ if( s == null) {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ return s.ToAnsiStr(false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s)
+ {
+ if (s == null)
+ {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ return s.ToUniStr(false);
+ }
+
+#endif // FEATURE_LEGACYSURFACE
+
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ZeroFreeBSTR(IntPtr s)
+ {
+ Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.SysStringLen(s) * 2));
+ FreeBSTR(s);
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ZeroFreeCoTaskMemAnsi(IntPtr s)
+ {
+ Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
+ FreeCoTaskMem(s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ZeroFreeCoTaskMemUnicode(IntPtr s)
+ {
+ Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
+ FreeCoTaskMem(s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe public static void ZeroFreeCoTaskMemUTF8(IntPtr s)
+ {
+ Win32Native.ZeroMemory(s, (UIntPtr)System.StubHelpers.StubHelpers.strlen((sbyte*)s));
+ FreeCoTaskMem(s);
+ }
+
+#if FEATURE_LEGACYSURFACE
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s) {
+ if( s == null) {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ return s.ToAnsiStr(true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s) {
+ if( s == null) {
+ throw new ArgumentNullException("s");
+ }
+ Contract.EndContractBlock();
+
+ return s.ToUniStr(true);
+ }
+#endif // FEATURE_LEGACYSURFACE
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ZeroFreeGlobalAllocAnsi(IntPtr s) {
+ Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
+ FreeHGlobal(s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void ZeroFreeGlobalAllocUnicode(IntPtr s) {
+ Win32Native.ZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
+ FreeHGlobal(s);
+ }
+ }
+
+#if FEATURE_COMINTEROP && !FEATURE_CORECLR // current implementation requires reflection only load
+ //========================================================================
+ // Typelib importer callback implementation.
+ //========================================================================
+ internal class ImporterCallback : ITypeLibImporterNotifySink
+ {
+ public void ReportEvent(ImporterEventKind EventKind, int EventCode, String EventMsg)
+ {
+ }
+
+ [System.Security.SecuritySafeCritical] // overrides transparent public member
+ public Assembly ResolveRef(Object TypeLib)
+ {
+ try
+ {
+ // Create the TypeLibConverter.
+ ITypeLibConverter TLBConv = new TypeLibConverter();
+
+ // Convert the typelib.
+ return TLBConv.ConvertTypeLibToAssembly(TypeLib,
+ Marshal.GetTypeLibName((ITypeLib)TypeLib) + ".dll",
+ 0,
+ new ImporterCallback(),
+ null,
+ null,
+ null,
+ null);
+ }
+ catch(Exception)
+// catch
+ {
+ return null;
+ }
+ }
+ }
+#endif // FEATURE_COMINTEROP && !FEATURE_CORECLR
+}
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs b/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs
new file mode 100644
index 0000000000..b916778019
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: This exception is thrown when the marshaller encounters a signature
+** that has an invalid MarshalAs CA for a given argument or is not
+** supported.
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class MarshalDirectiveException : SystemException {
+ public MarshalDirectiveException()
+ : base(Environment.GetResourceString("Arg_MarshalDirectiveException")) {
+ SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE);
+ }
+
+ public MarshalDirectiveException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE);
+ }
+
+ public MarshalDirectiveException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_MARSHALDIRECTIVE);
+ }
+
+ protected MarshalDirectiveException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs
new file mode 100644
index 0000000000..94261621c3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NativeBuffer.cs
@@ -0,0 +1,175 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Wrapper for access to the native heap. Dispose to free the memory. Try to use with using statements.
+ /// Does not allocate zero size buffers, and will free the existing native buffer if capacity is dropped to zero.
+ /// </summary>
+ /// <remarks>
+ /// Suggested use through P/Invoke: define DllImport arguments that take a byte buffer as SafeHandle.
+ ///
+ /// Using SafeHandle will ensure that the buffer will not get collected during a P/Invoke.
+ /// (Notably AddRef and ReleaseRef will be called by the interop layer.)
+ ///
+ /// This class is not threadsafe, changing the capacity or disposing on multiple threads risks duplicate heap
+ /// handles or worse.
+ /// </remarks>
+ internal class NativeBuffer : IDisposable
+ {
+ [System.Security.SecurityCritical]
+ private readonly static SafeHandle s_emptyHandle;
+ [System.Security.SecurityCritical]
+ private SafeHeapHandle _handle;
+ private ulong _capacity;
+
+ [System.Security.SecuritySafeCritical]
+ static NativeBuffer()
+ {
+ s_emptyHandle = new EmptySafeHandle();
+ }
+
+ /// <summary>
+ /// Create a buffer with at least the specified initial capacity in bytes.
+ /// </summary>
+ public NativeBuffer(ulong initialMinCapacity = 0)
+ {
+ EnsureByteCapacity(initialMinCapacity);
+ }
+
+ protected unsafe void* VoidPointer
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [System.Security.SecurityCritical]
+ get
+ {
+ return _handle == null ? null : _handle.DangerousGetHandle().ToPointer();
+ }
+ }
+
+ protected unsafe byte* BytePointer
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+ return (byte*)VoidPointer;
+ }
+ }
+
+ /// <summary>
+ /// Get the handle for the buffer.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public SafeHandle GetHandle()
+ {
+ // Marshalling code will throw on null for SafeHandle
+ return _handle ?? s_emptyHandle;
+ }
+
+ /// <summary>
+ /// The capacity of the buffer in bytes.
+ /// </summary>
+ public ulong ByteCapacity
+ {
+ get { return _capacity; }
+ }
+
+ /// <summary>
+ /// Ensure capacity in bytes is at least the given minimum.
+ /// </summary>
+ /// <exception cref="OutOfMemoryException">Thrown if unable to allocate memory when setting.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if attempting to set <paramref name="nameof(minCapacity)"/> to a value that is larger than the maximum addressable memory.</exception>
+ [System.Security.SecuritySafeCritical]
+ public void EnsureByteCapacity(ulong minCapacity)
+ {
+ if (_capacity < minCapacity)
+ {
+ Resize(minCapacity);
+ _capacity = minCapacity;
+ }
+ }
+
+ public unsafe byte this[ulong index]
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if (index >= _capacity) throw new ArgumentOutOfRangeException();
+ return BytePointer[index];
+ }
+ [System.Security.SecuritySafeCritical]
+ set
+ {
+ if (index >= _capacity) throw new ArgumentOutOfRangeException();
+ BytePointer[index] = value;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe void Resize(ulong byteLength)
+ {
+ if (byteLength == 0)
+ {
+ ReleaseHandle();
+ return;
+ }
+
+ if (_handle == null)
+ {
+ _handle = new SafeHeapHandle(byteLength);
+ }
+ else
+ {
+ _handle.Resize(byteLength);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void ReleaseHandle()
+ {
+ if (_handle != null)
+ {
+ _capacity = 0;
+ _handle = null;
+ }
+ }
+
+ /// <summary>
+ /// Release the backing buffer
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public virtual void Free()
+ {
+ ReleaseHandle();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public void Dispose()
+ {
+ Free();
+ }
+
+ [System.Security.SecurityCritical]
+ private sealed class EmptySafeHandle : SafeHandle
+ {
+ public EmptySafeHandle() : base(IntPtr.Zero, true) { }
+
+ public override bool IsInvalid
+ {
+ [System.Security.SecurityCritical]
+ get
+ { return true; }
+ }
+
+ [System.Security.SecurityCritical]
+ protected override bool ReleaseHandle()
+ {
+ return true;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs
new file mode 100644
index 0000000000..706ef80019
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NativeCallableAttribute.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+** Any method marked with NativeCallableAttribute can be directly called from
+** native code.The function token can be loaded to a local variable using LDFTN and
+** passed as a callback to native method.
+=============================================================================*/
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices
+{
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class NativeCallableAttribute : Attribute
+ {
+ public NativeCallableAttribute()
+ {
+ }
+ // Optional. If omitted , compiler will choose one for you.
+ public CallingConvention CallingConvention;
+ // Optional. If omitted, then the method is native callable, but no EAT is emitted.
+ public string EntryPoint;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs
new file mode 100644
index 0000000000..82cd4fa963
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NativeMethods.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+/*============================================================
+**
+**
+** Purpose: part of ComEventHelpers APIs which allow binding
+** managed delegates to COM's connection point based events.
+**
+**/
+#if FEATURE_COMINTEROP
+
+namespace System.Runtime.InteropServices {
+
+ internal static class NativeMethods {
+
+ [
+ System.Security.SuppressUnmanagedCodeSecurity,
+ DllImport("oleaut32.dll", PreserveSig = false),
+ System.Security.SecurityCritical
+ ]
+ internal static extern void VariantClear(IntPtr variant);
+
+ [
+ System.Security.SuppressUnmanagedCodeSecurity,
+ ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("00020400-0000-0000-C000-000000000046")
+ ]
+ internal interface IDispatch {
+
+ [System.Security.SecurityCritical]
+ void GetTypeInfoCount(out uint pctinfo);
+
+ [System.Security.SecurityCritical]
+ void GetTypeInfo(uint iTInfo, int lcid, out IntPtr info);
+
+ [System.Security.SecurityCritical]
+ void GetIDsOfNames(
+ ref Guid iid,
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 2)]
+ string[] names,
+ uint cNames,
+ int lcid,
+ [Out]
+ [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I4, SizeParamIndex = 2)]
+ int[] rgDispId);
+
+ [System.Security.SecurityCritical]
+ void Invoke(
+ int dispIdMember,
+ ref Guid riid,
+ int lcid,
+ ComTypes.INVOKEKIND wFlags,
+ ref ComTypes.DISPPARAMS pDispParams,
+ IntPtr pvarResult,
+ IntPtr pExcepInfo,
+ IntPtr puArgErr);
+ }
+ }
+}
+
+#endif
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs b/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs
new file mode 100644
index 0000000000..408f56c8e2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/NonPortable.cs
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Dummy implementations of non-portable interop methods that just throw PlatformNotSupportedException
+
+namespace System.Runtime.InteropServices
+{
+ public static partial class Marshal
+ {
+ [System.Security.SecurityCritical]
+ public static int GetHRForException(Exception e)
+ {
+ return (e != null) ? e.HResult : 0;
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int AddRef(System.IntPtr pUnk)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static bool AreComObjectsAvailableForCleanup()
+ {
+ return false;
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr CreateAggregatedObject(System.IntPtr pOuter, object o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr CreateAggregatedObject<T>(System.IntPtr pOuter, T o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static object CreateWrapperOfType(object o, System.Type t)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int FinalReleaseComObject(object o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject(object o, System.Type T)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject(object o, System.Type T, System.Runtime.InteropServices.CustomQueryInterfaceMode mode)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetComInterfaceForObject<T, TInterface>(T o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.IntPtr GetIUnknownForObject(object o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static void GetNativeVariantForObject(object obj, System.IntPtr pDstNativeVariant)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static void GetNativeVariantForObject<T>(T obj, System.IntPtr pDstNativeVariant)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static object GetObjectForIUnknown(System.IntPtr pUnk)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static object GetObjectForNativeVariant(System.IntPtr pSrcNativeVariant)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static T GetObjectForNativeVariant<T>(System.IntPtr pSrcNativeVariant)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static object[] GetObjectsForNativeVariants(System.IntPtr aSrcNativeVariant, int cVars)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static T[] GetObjectsForNativeVariants<T>(System.IntPtr aSrcNativeVariant, int cVars)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int GetStartComSlot(System.Type t)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public static System.Type GetTypeFromCLSID(System.Guid clsid)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static string GetTypeInfoName(System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static object GetUniqueObjectForIUnknown(System.IntPtr unknown)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public static bool IsComObject(object o)
+ {
+ return false;
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int QueryInterface(System.IntPtr pUnk, ref System.Guid iid, out System.IntPtr ppv)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int Release(System.IntPtr pUnk)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static int ReleaseComObject(object o)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static void ZeroFreeBSTR(System.IntPtr s)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+
+ public class DispatchWrapper
+ {
+ public DispatchWrapper(object obj)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ public object WrappedObject
+ {
+ get
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+ }
+
+ public static class ComEventsHelper
+ {
+ [System.Security.SecurityCriticalAttribute]
+ public static void Combine(object rcw, System.Guid iid, int dispid, System.Delegate d)
+ {
+ throw new PlatformNotSupportedException();
+ }
+
+ [System.Security.SecurityCriticalAttribute]
+ public static System.Delegate Remove(object rcw, System.Guid iid, int dispid, System.Delegate d)
+ {
+ throw new PlatformNotSupportedException();
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs b/src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs
new file mode 100644
index 0000000000..f011253e1e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/ObjectCreationDelegate.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+** Delegate: ObjectCreationDelegate
+**
+**
+** Purpose: Delegate called to create a classic COM object as an alternative to
+** CoCreateInstance.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ // Delegate called when a managed object wishes to instantiate its unmanaged
+ // portion. The IUnknown of the managed object (the aggregator) is passed as a
+ // parameter and the delegate should return the IUnknown of the unmanaged object
+ // (the aggregatee). Both are passed as int's to avoid any marshalling.
+[System.Runtime.InteropServices.ComVisible(true)]
+ public delegate IntPtr ObjectCreationDelegate(IntPtr aggregator);
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs b/src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs
new file mode 100644
index 0000000000..f47165544a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/PInvokeMap.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// PInvokeMap is an enum that defines the PInvoke attributes. These
+// values are defined in CorHdr.h.
+//
+//
+namespace System.Runtime.InteropServices {
+ using System.Runtime.InteropServices;
+ using System;
+
+ // This Enum matchs the CorPinvokeMap defined in CorHdr.h
+ [Serializable]
+ internal enum PInvokeMap
+ {
+ NoMangle = 0x0001, // Pinvoke is to use the member name as specified.
+ CharSetMask = 0x0006, // Heuristic used in data type & name mapping.
+ CharSetNotSpec = 0x0000,
+ CharSetAnsi = 0x0002,
+ CharSetUnicode = 0x0004,
+ CharSetAuto = 0x0006,
+
+ PinvokeOLE = 0x0020, // Heuristic: pinvoke will return hresult, with return value becoming the retval param. Not relevant for fields.
+ SupportsLastError = 0x0040, // Information about target function. Not relevant for fields.
+
+ BestFitMask = 0x0030,
+ BestFitEnabled = 0x0010,
+ BestFitDisabled = 0x0020,
+ BestFitUseAsm = 0x0030,
+
+ ThrowOnUnmappableCharMask = 0x3000,
+ ThrowOnUnmappableCharEnabled = 0x1000,
+ ThrowOnUnmappableCharDisabled = 0x2000,
+ ThrowOnUnmappableCharUseAsm = 0x3000,
+
+ // None of the calling convention flags is relevant for fields.
+ CallConvMask = 0x0700,
+ CallConvWinapi = 0x0100, // Pinvoke will use native callconv appropriate to target windows platform.
+ CallConvCdecl = 0x0200,
+ CallConvStdcall = 0x0300,
+ CallConvThiscall = 0x0400, // In M9, pinvoke will raise exception.
+ CallConvFastcall = 0x0500,
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs
new file mode 100644
index 0000000000..7d3670d877
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs
@@ -0,0 +1,1087 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: This class provides services for registering and unregistering
+** a managed server for use by COM.
+**
+**
+**
+**
+** Change the way how to register and unregister a managed server
+**
+=============================================================================*/
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Collections;
+ using System.IO;
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Flags]
+ public enum RegistrationClassContext
+ {
+
+
+ InProcessServer = 0x1,
+ InProcessHandler = 0x2,
+ LocalServer = 0x4,
+ InProcessServer16 = 0x8,
+ RemoteServer = 0x10,
+ InProcessHandler16 = 0x20,
+ Reserved1 = 0x40,
+ Reserved2 = 0x80,
+ Reserved3 = 0x100,
+ Reserved4 = 0x200,
+ NoCodeDownload = 0x400,
+ Reserved5 = 0x800,
+ NoCustomMarshal = 0x1000,
+ EnableCodeDownload = 0x2000,
+ NoFailureLog = 0x4000,
+ DisableActivateAsActivator = 0x8000,
+ EnableActivateAsActivator = 0x10000,
+ FromDefaultContext = 0x20000
+ }
+
+
+ [Flags]
+ public enum RegistrationConnectionType
+ {
+ SingleUse = 0,
+ MultipleUse = 1,
+ MultiSeparate = 2,
+ Suspended = 4,
+ Surrogate = 8,
+ }
+
+ [Guid("475E398F-8AFA-43a7-A3BE-F4EF8D6787C9")]
+ [ClassInterface(ClassInterfaceType.None)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class RegistrationServices : IRegistrationServices
+ {
+ #region Constants
+
+ private const String strManagedCategoryGuid = "{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}";
+ private const String strDocStringPrefix = "";
+ private const String strManagedTypeThreadingModel = "Both";
+ private const String strComponentCategorySubKey = "Component Categories";
+ private const String strManagedCategoryDescription = ".NET Category";
+ private const String strImplementedCategoriesSubKey = "Implemented Categories";
+ private const String strMsCorEEFileName = "mscoree.dll";
+ private const String strRecordRootName = "Record";
+ private const String strClsIdRootName = "CLSID";
+ private const String strTlbRootName = "TypeLib";
+ private static Guid s_ManagedCategoryGuid = new Guid(strManagedCategoryGuid);
+
+ #endregion
+
+
+ #region IRegistrationServices
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags)
+ {
+ // Validate the arguments.
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+
+ if (assembly.ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly"));
+ Contract.EndContractBlock();
+
+ RuntimeAssembly rtAssembly = assembly as RuntimeAssembly;
+ if (rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
+
+ // Retrieve the assembly names.
+ String strAsmName = assembly.FullName;
+ if (strAsmName == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmName"));
+
+ // Retrieve the assembly codebase.
+ String strAsmCodeBase = null;
+ if ((flags & AssemblyRegistrationFlags.SetCodeBase) != 0)
+ {
+ strAsmCodeBase = rtAssembly.GetCodeBase(false);
+ if (strAsmCodeBase == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmCodeBase"));
+ }
+
+ // Go through all the registerable types in the assembly and register them.
+ Type[] aTypes = GetRegistrableTypesInAssembly(assembly);
+ int NumTypes = aTypes.Length;
+
+ String strAsmVersion = rtAssembly.GetVersion().ToString();
+
+ // Retrieve the runtime version used to build the assembly.
+ String strRuntimeVersion = assembly.ImageRuntimeVersion;
+
+ for (int cTypes = 0; cTypes < NumTypes; cTypes++)
+ {
+ if (IsRegisteredAsValueType(aTypes[cTypes]))
+ RegisterValueType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
+ else if (TypeRepresentsComType(aTypes[cTypes]))
+ RegisterComImportedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
+ else
+ RegisterManagedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion);
+
+ CallUserDefinedRegistrationMethod(aTypes[cTypes], true);
+ }
+
+ // If this assembly has the PIA attribute, then register it as a PIA.
+ Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute), false);
+ int NumPIAAttrs = aPIAAttrs.Length;
+ for (int cPIAAttrs = 0; cPIAAttrs < NumPIAAttrs; cPIAAttrs++)
+ RegisterPrimaryInteropAssembly(rtAssembly, strAsmCodeBase, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]);
+
+ // Return value indicating if we actually registered any types.
+ if (aTypes.Length > 0 || NumPIAAttrs > 0)
+ return true;
+ else
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual bool UnregisterAssembly(Assembly assembly)
+ {
+ // Validate the arguments.
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+
+ if (assembly.ReflectionOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly"));
+ Contract.EndContractBlock();
+
+ RuntimeAssembly rtAssembly = assembly as RuntimeAssembly;
+ if (rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
+
+ bool bAllVersionsGone = true;
+
+ // Go through all the registrable types in the assembly and register them.
+ Type[] aTypes = GetRegistrableTypesInAssembly(assembly);
+ int NumTypes = aTypes.Length;
+
+ // Retrieve the assembly version
+ String strAsmVersion = rtAssembly.GetVersion().ToString();
+ for (int cTypes = 0;cTypes < NumTypes;cTypes++)
+ {
+ CallUserDefinedRegistrationMethod(aTypes[cTypes], false);
+
+ if (IsRegisteredAsValueType(aTypes[cTypes]))
+ {
+ if (!UnregisterValueType(aTypes[cTypes], strAsmVersion))
+ bAllVersionsGone = false;
+ }
+ else if (TypeRepresentsComType(aTypes[cTypes]))
+ {
+ if (!UnregisterComImportedType(aTypes[cTypes], strAsmVersion))
+ bAllVersionsGone = false;
+ }
+ else
+ {
+ if (!UnregisterManagedType(aTypes[cTypes], strAsmVersion))
+ bAllVersionsGone = false;
+ }
+ }
+
+ // If this assembly has the PIA attribute, then unregister it as a PIA.
+ Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute),false);
+ int NumPIAAttrs = aPIAAttrs.Length;
+ if (bAllVersionsGone)
+ {
+ for (int cPIAAttrs = 0;cPIAAttrs < NumPIAAttrs;cPIAAttrs++)
+ UnregisterPrimaryInteropAssembly(assembly, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]);
+ }
+
+ // Return value indicating if we actually un-registered any types.
+ if (aTypes.Length > 0 || NumPIAAttrs > 0)
+ return true;
+ else
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly)
+ {
+ // Validate the arguments.
+ if (assembly == null)
+ throw new ArgumentNullException("assembly");
+ Contract.EndContractBlock();
+
+ if (!(assembly is RuntimeAssembly))
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly");
+
+ // Retrieve the list of types in the assembly.
+ Type[] aTypes = assembly.GetExportedTypes();
+ int NumTypes = aTypes.Length;
+
+ // Create an array list that will be filled in.
+ ArrayList TypeList = new ArrayList();
+
+ // Register all the types that require registration.
+ for (int cTypes = 0; cTypes < NumTypes; cTypes++)
+ {
+ Type CurrentType = aTypes[cTypes];
+ if (TypeRequiresRegistration(CurrentType))
+ TypeList.Add(CurrentType);
+ }
+
+ // Copy the array list to an array and return it.
+ Type[] RetArray = new Type[TypeList.Count];
+ TypeList.CopyTo(RetArray);
+ return RetArray;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual String GetProgIdForType(Type type)
+ {
+ return Marshal.GenerateProgIdForType(type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual void RegisterTypeForComClients(Type type, ref Guid g)
+ {
+#if FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ if(type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ if((type as RuntimeType) == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type");
+ if(!TypeRequiresRegistration(type))
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type");
+
+ // Call the native method to do CoRegisterClassObject
+ RegisterTypeForComClientsNative(type, ref g);
+#else // FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed");
+#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ }
+
+ public virtual Guid GetManagedCategoryGuid()
+ {
+ return s_ManagedCategoryGuid;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public virtual bool TypeRequiresRegistration(Type type)
+ {
+ return TypeRequiresRegistrationHelper(type);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public virtual bool TypeRepresentsComType(Type type)
+ {
+ // If the type is not a COM import, then it does not represent a COM type.
+ if (!type.IsCOMObject)
+ return false;
+
+ // If it is marked as tdImport, then it represents a COM type directly.
+ if (type.IsImport)
+ return true;
+
+ // If the type is derived from a tdImport class and has the same GUID as the
+ // imported class, then it represents a COM type.
+ Type baseComImportType = GetBaseComImportType(type);
+ Contract.Assert(baseComImportType != null, "baseComImportType != null");
+ if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType))
+ return true;
+
+ return false;
+ }
+
+ #endregion
+
+
+ #region Public methods not on IRegistrationServices
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ComVisible(false)]
+ public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags)
+ {
+#if FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ if (type == null)
+ throw new ArgumentNullException("type");
+ Contract.EndContractBlock();
+ if ((type as RuntimeType) == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type");
+ if (!TypeRequiresRegistration(type))
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"type");
+
+ // Call the native method to do CoRegisterClassObject
+ return RegisterTypeForComClientsExNative(type, classContext, flags);
+#else // FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed");
+#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ComVisible(false)]
+ public virtual void UnregisterTypeForComClients(int cookie)
+ {
+ // Call the native method to do CoRevokeClassObject.
+ CoRevokeClassObject(cookie);
+ }
+
+ #endregion
+
+
+ #region Internal helpers
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ internal static bool TypeRequiresRegistrationHelper(Type type)
+ {
+ // If the type is not a class or a value class, then it does not get registered.
+ if (!type.IsClass && !type.IsValueType)
+ return false;
+
+ // If the type is abstract then it does not get registered.
+ if (type.IsAbstract)
+ return false;
+
+ // If the does not have a public default constructor then is not creatable from COM so
+ // it does not require registration unless it is a value class.
+ if (!type.IsValueType && type.GetConstructor(BindingFlags.Instance | BindingFlags.Public,null,Array.Empty<Type>(),null) == null)
+ return false;
+
+ // All other conditions are met so check to see if the type is visible from COM.
+ return Marshal.IsTypeVisibleFromCom(type);
+ }
+
+ #endregion
+
+
+ #region Private helpers
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void RegisterValueType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
+ {
+ // Retrieve some information that will be used during the registration process.
+ String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+
+ // Create the HKEY_CLASS_ROOT\Record key.
+ using (RegistryKey RecordRootKey = Registry.ClassesRoot.CreateSubKey(strRecordRootName))
+ {
+ // Create the HKEY_CLASS_ROOT\Record\<RecordID> key.
+ using (RegistryKey RecordKey = RecordRootKey.CreateSubKey(strRecordId))
+ {
+ // Create the HKEY_CLASS_ROOT\Record\<RecordId>\<version> key.
+ using (RegistryKey RecordVersionKey = RecordKey.CreateSubKey(strAsmVersion))
+ {
+ // Set the class value.
+ RecordVersionKey.SetValue("Class", type.FullName);
+
+ // Set the assembly value.
+ RecordVersionKey.SetValue("Assembly", strAsmName);
+
+ // Set the runtime version value.
+ RecordVersionKey.SetValue("RuntimeVersion", strRuntimeVersion);
+
+ // Set the assembly code base value if a code base was specified.
+ if (strAsmCodeBase != null)
+ RecordVersionKey.SetValue("CodeBase", strAsmCodeBase);
+ }
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
+ {
+ //
+ // Retrieve some information that will be used during the registration process.
+ //
+
+ String strDocString = strDocStringPrefix + type.FullName;
+ String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ String strProgId = GetProgIdForType(type);
+
+
+ //
+ // Write the actual type information in the registry.
+ //
+
+ if (strProgId != String.Empty)
+ {
+ // Create the HKEY_CLASS_ROOT\<wzProgId> key.
+ using (RegistryKey TypeNameKey = Registry.ClassesRoot.CreateSubKey(strProgId))
+ {
+ TypeNameKey.SetValue("", strDocString);
+
+ // Create the HKEY_CLASS_ROOT\<wzProgId>\CLSID key.
+ using (RegistryKey ProgIdClsIdKey = TypeNameKey.CreateSubKey("CLSID"))
+ {
+ ProgIdClsIdKey.SetValue("", strClsId);
+ }
+ }
+ }
+
+ // Create the HKEY_CLASS_ROOT\CLSID key.
+ using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName))
+ {
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
+ using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
+ {
+ ClsIdKey.SetValue("", strDocString);
+
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key.
+ using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32"))
+ {
+ InProcServerKey.SetValue("", strMsCorEEFileName);
+ InProcServerKey.SetValue("ThreadingModel", strManagedTypeThreadingModel);
+ InProcServerKey.SetValue("Class", type.FullName);
+ InProcServerKey.SetValue("Assembly", strAsmName);
+ InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion);
+ if (strAsmCodeBase != null)
+ InProcServerKey.SetValue("CodeBase", strAsmCodeBase);
+
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey
+ using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion))
+ {
+ VersionSubKey.SetValue("Class", type.FullName);
+ VersionSubKey.SetValue("Assembly", strAsmName);
+ VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion);
+ if (strAsmCodeBase != null)
+ VersionSubKey.SetValue("CodeBase", strAsmCodeBase);
+ }
+
+ if (strProgId != String.Empty)
+ {
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProdId key.
+ using (RegistryKey ProgIdKey = ClsIdKey.CreateSubKey("ProgId"))
+ {
+ ProgIdKey.SetValue("", strProgId);
+ }
+ }
+ }
+
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key.
+ using (RegistryKey CategoryKey = ClsIdKey.CreateSubKey(strImplementedCategoriesSubKey))
+ {
+ using (RegistryKey ManagedCategoryKey = CategoryKey.CreateSubKey(strManagedCategoryGuid)) {}
+ }
+ }
+ }
+
+
+ //
+ // Ensure that the managed category exists.
+ //
+
+ EnsureManagedCategoryExists();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void RegisterComImportedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion)
+ {
+ // Retrieve some information that will be used during the registration process.
+ String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+
+ // Create the HKEY_CLASS_ROOT\CLSID key.
+ using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName))
+ {
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
+ using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
+ {
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key.
+ using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32"))
+ {
+ // Set the class value.
+ InProcServerKey.SetValue("Class", type.FullName);
+
+ // Set the assembly value.
+ InProcServerKey.SetValue("Assembly", strAsmName);
+
+ // Set the runtime version value.
+ InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion);
+
+ // Set the assembly code base value if a code base was specified.
+ if (strAsmCodeBase != null)
+ InProcServerKey.SetValue("CodeBase", strAsmCodeBase);
+
+ // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey
+ using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion))
+ {
+ VersionSubKey.SetValue("Class", type.FullName);
+ VersionSubKey.SetValue("Assembly", strAsmName);
+ VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion);
+ if (strAsmCodeBase != null)
+ VersionSubKey.SetValue("CodeBase", strAsmCodeBase);
+ }
+ }
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool UnregisterValueType(Type type, String strAsmVersion)
+ {
+ bool bAllVersionsGone = true;
+
+ // Try to open the HKEY_CLASS_ROOT\Record key.
+ String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+
+ using (RegistryKey RecordRootKey = Registry.ClassesRoot.OpenSubKey(strRecordRootName, true))
+ {
+ if (RecordRootKey != null)
+ {
+ // Open the HKEY_CLASS_ROOT\Record\{RecordId} key.
+ using (RegistryKey RecordKey = RecordRootKey.OpenSubKey(strRecordId,true))
+ {
+ if (RecordKey != null)
+ {
+ using (RegistryKey VersionSubKey = RecordKey.OpenSubKey(strAsmVersion,true))
+ {
+ if (VersionSubKey != null)
+ {
+ // Delete the values we created.
+ VersionSubKey.DeleteValue("Assembly",false);
+ VersionSubKey.DeleteValue("Class",false);
+ VersionSubKey.DeleteValue("CodeBase",false);
+ VersionSubKey.DeleteValue("RuntimeVersion",false);
+
+ // delete the version sub key if no value or subkeys under it
+ if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
+ RecordKey.DeleteSubKey(strAsmVersion);
+ }
+ }
+
+ // If there are sub keys left then there are versions left.
+ if (RecordKey.SubKeyCount != 0)
+ bAllVersionsGone = false;
+
+ // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record\{RecordId}.
+ if ((RecordKey.SubKeyCount == 0) && (RecordKey.ValueCount == 0))
+ RecordRootKey.DeleteSubKey(strRecordId);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record.
+ if ((RecordRootKey.SubKeyCount == 0) && (RecordRootKey.ValueCount == 0))
+ Registry.ClassesRoot.DeleteSubKey(strRecordRootName);
+ }
+ }
+
+ return bAllVersionsGone;
+ }
+
+ // UnregisterManagedType
+ //
+ // Return :
+ // true: All versions are gone.
+ // false: Some versions are still left in registry
+ [System.Security.SecurityCritical] // auto-generated
+ private bool UnregisterManagedType(Type type,String strAsmVersion)
+ {
+ bool bAllVersionsGone = true;
+
+ //
+ // Create the CLSID string.
+ //
+
+ String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ String strProgId = GetProgIdForType(type);
+
+
+ //
+ // Remove the entries under HKEY_CLASS_ROOT\CLSID key.
+ //
+
+ using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true))
+ {
+ if (ClsIdRootKey != null)
+ {
+ //
+ // Remove the entries under HKEY_CLASS_ROOT\CLSID\<CLSID> key.
+ //
+
+ using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true))
+ {
+ if (ClsIdKey != null)
+ {
+ //
+ // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key.
+ //
+
+ using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true))
+ {
+ if (InProcServerKey != null)
+ {
+ //
+ // Remove the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version>
+ //
+
+ using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion, true))
+ {
+ if (VersionSubKey != null)
+ {
+ // Delete the values we created
+ VersionSubKey.DeleteValue("Assembly",false);
+ VersionSubKey.DeleteValue("Class",false);
+ VersionSubKey.DeleteValue("RuntimeVersion",false);
+ VersionSubKey.DeleteValue("CodeBase",false);
+
+ // If there are no other values or subkeys then we can delete the VersionSubKey.
+ if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
+ InProcServerKey.DeleteSubKey(strAsmVersion);
+ }
+ }
+
+ // If there are sub keys left then there are versions left.
+ if (InProcServerKey.SubKeyCount != 0)
+ bAllVersionsGone = false;
+
+ // If there are no versions left, then delete the threading model and default value.
+ if (bAllVersionsGone)
+ {
+ InProcServerKey.DeleteValue("",false);
+ InProcServerKey.DeleteValue("ThreadingModel",false);
+ }
+
+ InProcServerKey.DeleteValue("Assembly",false);
+ InProcServerKey.DeleteValue("Class",false);
+ InProcServerKey.DeleteValue("RuntimeVersion",false);
+ InProcServerKey.DeleteValue("CodeBase",false);
+
+ // If there are no other values or subkeys then we can delete the InProcServerKey.
+ if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0))
+ ClsIdKey.DeleteSubKey("InprocServer32");
+ }
+ }
+
+ // remove HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId
+ // and HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Category
+ // only when all versions are removed
+ if (bAllVersionsGone)
+ {
+ // Delete the value we created.
+ ClsIdKey.DeleteValue("",false);
+
+ if (strProgId != String.Empty)
+ {
+ //
+ // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId key.
+ //
+
+ using (RegistryKey ProgIdKey = ClsIdKey.OpenSubKey("ProgId", true))
+ {
+ if (ProgIdKey != null)
+ {
+ // Delete the value we created.
+ ProgIdKey.DeleteValue("",false);
+
+ // If there are no other values or subkeys then we can delete the ProgIdSubKey.
+ if ((ProgIdKey.SubKeyCount == 0) && (ProgIdKey.ValueCount == 0))
+ ClsIdKey.DeleteSubKey("ProgId");
+ }
+ }
+ }
+
+
+ //
+ // Remove entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key.
+ //
+
+ using (RegistryKey CategoryKey = ClsIdKey.OpenSubKey(strImplementedCategoriesSubKey, true))
+ {
+ if (CategoryKey != null)
+ {
+ using (RegistryKey ManagedCategoryKey = CategoryKey.OpenSubKey(strManagedCategoryGuid, true))
+ {
+ if (ManagedCategoryKey != null)
+ {
+ // If there are no other values or subkeys then we can delete the ManagedCategoryKey.
+ if ((ManagedCategoryKey.SubKeyCount == 0) && (ManagedCategoryKey.ValueCount == 0))
+ CategoryKey.DeleteSubKey(strManagedCategoryGuid);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the CategoryKey.
+ if ((CategoryKey.SubKeyCount == 0) && (CategoryKey.ValueCount == 0))
+ ClsIdKey.DeleteSubKey(strImplementedCategoriesSubKey);
+ }
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the ClsIdKey.
+ if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0))
+ ClsIdRootKey.DeleteSubKey(strClsId);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the CLSID key.
+ if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0))
+ Registry.ClassesRoot.DeleteSubKey(strClsIdRootName);
+ }
+
+
+ //
+ // Remove the entries under HKEY_CLASS_ROOT\<wzProgId> key.
+ //
+
+ if (bAllVersionsGone)
+ {
+ if (strProgId != String.Empty)
+ {
+ using (RegistryKey TypeNameKey = Registry.ClassesRoot.OpenSubKey(strProgId, true))
+ {
+ if (TypeNameKey != null)
+ {
+ // Delete the values we created.
+ TypeNameKey.DeleteValue("",false);
+
+
+ //
+ // Remove the entries in the HKEY_CLASS_ROOT\<wzProgId>\CLSID key.
+ //
+
+ using (RegistryKey ProgIdClsIdKey = TypeNameKey.OpenSubKey("CLSID", true))
+ {
+ if (ProgIdClsIdKey != null)
+ {
+ // Delete the values we created.
+ ProgIdClsIdKey.DeleteValue("",false);
+
+ // If there are no other values or subkeys then we can delete the ProgIdClsIdKey.
+ if ((ProgIdClsIdKey.SubKeyCount == 0) && (ProgIdClsIdKey.ValueCount == 0))
+ TypeNameKey.DeleteSubKey("CLSID");
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the TypeNameKey.
+ if ((TypeNameKey.SubKeyCount == 0) && (TypeNameKey.ValueCount == 0))
+ Registry.ClassesRoot.DeleteSubKey(strProgId);
+ }
+ }
+ }
+ }
+ }
+
+ return bAllVersionsGone;
+ }
+
+ // UnregisterComImportedType
+ // Return:
+ // true: All version information are gone.
+ // false: There are still some version left in registry
+ [System.Security.SecurityCritical] // auto-generated
+ private bool UnregisterComImportedType(Type type, String strAsmVersion)
+ {
+ bool bAllVersionsGone = true;
+
+ String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+
+ // Try to open the HKEY_CLASS_ROOT\CLSID key.
+ using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true))
+ {
+ if (ClsIdRootKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID> key.
+ using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true))
+ {
+ if (ClsIdKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key.
+ using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true))
+ {
+ if (InProcServerKey != null)
+ {
+ // Delete the values we created.
+ InProcServerKey.DeleteValue("Assembly",false);
+ InProcServerKey.DeleteValue("Class",false);
+ InProcServerKey.DeleteValue("RuntimeVersion",false);
+ InProcServerKey.DeleteValue("CodeBase",false);
+
+ // Try to open the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32\<Version>
+ using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion,true))
+ {
+ if (VersionSubKey != null)
+ {
+ // Delete the value we created
+ VersionSubKey.DeleteValue("Assembly",false);
+ VersionSubKey.DeleteValue("Class",false);
+ VersionSubKey.DeleteValue("RuntimeVersion",false);
+ VersionSubKey.DeleteValue("CodeBase",false);
+
+ // If there are no other values or subkeys then we can delete the VersionSubKey
+ if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
+ InProcServerKey.DeleteSubKey(strAsmVersion);
+ }
+ }
+
+ // If there are sub keys left then there are versions left.
+ if (InProcServerKey.SubKeyCount != 0)
+ bAllVersionsGone = false;
+
+ // If there are no other values or subkeys then we can delete the InProcServerKey.
+ if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0))
+ ClsIdKey.DeleteSubKey("InprocServer32");
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the ClsIdKey.
+ if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0))
+ ClsIdRootKey.DeleteSubKey(strClsId);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the CLSID key.
+ if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0))
+ Registry.ClassesRoot.DeleteSubKey(strClsIdRootName);
+ }
+ }
+
+ return bAllVersionsGone;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void RegisterPrimaryInteropAssembly(RuntimeAssembly assembly, String strAsmCodeBase, PrimaryInteropAssemblyAttribute attr)
+ {
+ // Validate that the PIA has a strong name.
+ if (assembly.GetPublicKey().Length == 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed"));
+
+ String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture);
+
+ // Create the HKEY_CLASS_ROOT\TypeLib key.
+ using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.CreateSubKey(strTlbRootName))
+ {
+ // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID> key.
+ using (RegistryKey TypeLibKey = TypeLibRootKey.CreateSubKey(strTlbId))
+ {
+ // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\<Major.Minor> key.
+ using (RegistryKey VersionSubKey = TypeLibKey.CreateSubKey(strVersion))
+ {
+ // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\PrimaryInteropAssembly key.
+ VersionSubKey.SetValue("PrimaryInteropAssemblyName", assembly.FullName);
+ if (strAsmCodeBase != null)
+ VersionSubKey.SetValue("PrimaryInteropAssemblyCodeBase", strAsmCodeBase);
+ }
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void UnregisterPrimaryInteropAssembly(Assembly assembly, PrimaryInteropAssemblyAttribute attr)
+ {
+ String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture);
+
+ // Try to open the HKEY_CLASS_ROOT\TypeLib key.
+ using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.OpenSubKey(strTlbRootName, true))
+ {
+ if (TypeLibRootKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID> key.
+ using (RegistryKey TypeLibKey = TypeLibRootKey.OpenSubKey(strTlbId, true))
+ {
+ if (TypeLibKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\TypeLib<TLBID>\<Major.Minor> key.
+ using (RegistryKey VersionSubKey = TypeLibKey.OpenSubKey(strVersion, true))
+ {
+ if (VersionSubKey != null)
+ {
+ // Delete the values we created.
+ VersionSubKey.DeleteValue("PrimaryInteropAssemblyName",false);
+ VersionSubKey.DeleteValue("PrimaryInteropAssemblyCodeBase",false);
+
+ // If there are no other values or subkeys then we can delete the VersionKey.
+ if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0))
+ TypeLibKey.DeleteSubKey(strVersion);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the TypeLibKey.
+ if ((TypeLibKey.SubKeyCount == 0) && (TypeLibKey.ValueCount == 0))
+ TypeLibRootKey.DeleteSubKey(strTlbId);
+ }
+ }
+
+ // If there are no other values or subkeys then we can delete the TypeLib key.
+ if ((TypeLibRootKey.SubKeyCount == 0) && (TypeLibRootKey.ValueCount == 0))
+ Registry.ClassesRoot.DeleteSubKey(strTlbRootName);
+ }
+ }
+ }
+
+ private void EnsureManagedCategoryExists()
+ {
+ if (!ManagedCategoryExists())
+ {
+ // Create the HKEY_CLASS_ROOT\Component Category key.
+ using (RegistryKey ComponentCategoryKey = Registry.ClassesRoot.CreateSubKey(strComponentCategorySubKey))
+ {
+ // Create the HKEY_CLASS_ROOT\Component Category\<Managed Category Guid> key.
+ using (RegistryKey ManagedCategoryKey = ComponentCategoryKey.CreateSubKey(strManagedCategoryGuid))
+ {
+ ManagedCategoryKey.SetValue("0", strManagedCategoryDescription);
+ }
+ }
+ }
+ }
+
+ private static bool ManagedCategoryExists()
+ {
+ using (RegistryKey componentCategoryKey = Registry.ClassesRoot.OpenSubKey(strComponentCategorySubKey,
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.ReadSubTree))
+#else
+ false))
+#endif
+ {
+ if (componentCategoryKey == null)
+ return false;
+ using (RegistryKey managedCategoryKey = componentCategoryKey.OpenSubKey(strManagedCategoryGuid,
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.ReadSubTree))
+#else
+ false))
+#endif
+ {
+ if (managedCategoryKey == null)
+ return false;
+ object value = managedCategoryKey.GetValue("0");
+ if (value == null || value.GetType() != typeof(string))
+ return false;
+ string stringValue = (string)value;
+ if (stringValue != strManagedCategoryDescription)
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void CallUserDefinedRegistrationMethod(Type type, bool bRegister)
+ {
+ bool bFunctionCalled = false;
+
+ // Retrieve the attribute type to use to determine if a function is the requested user defined
+ // registration function.
+ Type RegFuncAttrType = null;
+ if(bRegister)
+ RegFuncAttrType = typeof(ComRegisterFunctionAttribute);
+ else
+ RegFuncAttrType = typeof(ComUnregisterFunctionAttribute);
+
+ for(Type currType = type; !bFunctionCalled && currType != null; currType = currType.BaseType)
+ {
+ // Retrieve all the methods.
+ MethodInfo[] aMethods = currType.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static);
+ int NumMethods = aMethods.Length;
+
+ // Go through all the methods and check for the ComRegisterMethod custom attribute.
+ for(int cMethods = 0;cMethods < NumMethods;cMethods++)
+ {
+ MethodInfo CurrentMethod = aMethods[cMethods];
+
+ // Check to see if the method has the custom attribute.
+ if(CurrentMethod.GetCustomAttributes(RegFuncAttrType, true).Length != 0)
+ {
+ // Check to see if the method is static before we call it.
+ if(!CurrentMethod.IsStatic)
+ {
+ if(bRegister)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComRegFunction",CurrentMethod.Name,currType.Name));
+ else
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComUnRegFunction",CurrentMethod.Name,currType.Name));
+ }
+
+ // Finally check that the signature is string ret void.
+ ParameterInfo[] aParams = CurrentMethod.GetParameters();
+ if (CurrentMethod.ReturnType != typeof(void) ||
+ aParams == null ||
+ aParams.Length != 1 ||
+ (aParams[0].ParameterType != typeof(String) && aParams[0].ParameterType != typeof(Type)))
+ {
+ if(bRegister)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComRegFunctionSig",CurrentMethod.Name,currType.Name));
+ else
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComUnRegFunctionSig",CurrentMethod.Name,currType.Name));
+ }
+
+ // There can only be one register and one unregister function per type.
+ if(bFunctionCalled)
+ {
+ if(bRegister)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComRegFunctions",currType.Name));
+ else
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComUnRegFunctions",currType.Name));
+ }
+
+ // The function is valid so set up the arguments to call it.
+ Object[] objs = new Object[1];
+ if(aParams[0].ParameterType == typeof(String))
+ {
+ // We are dealing with the string overload of the function.
+ objs[0] = "HKEY_CLASSES_ROOT\\CLSID\\{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ }
+ else
+ {
+ // We are dealing with the type overload of the function.
+ objs[0] = type;
+ }
+
+ // Invoke the COM register function.
+ CurrentMethod.Invoke(null, objs);
+
+ // Mark the function as having been called.
+ bFunctionCalled = true;
+ }
+ }
+ }
+ }
+
+ private Type GetBaseComImportType(Type type)
+ {
+ for (; type != null && !type.IsImport; type = type.BaseType);
+ return type;
+ }
+
+ private bool IsRegisteredAsValueType(Type type)
+ {
+ if (!type.IsValueType)
+ return false;
+
+ return true;
+ }
+
+ #endregion
+
+
+ #region FCalls and DllImports
+
+#if FEATURE_COMINTEROP_MANAGED_ACTIVATION
+ // GUID versioning can be controlled by using the GuidAttribute or
+ // letting the runtime generate it based on type and assembly strong name.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void RegisterTypeForComClientsNative(Type type,ref Guid g);
+
+ // GUID versioning can be controlled by using the GuidAttribute or
+ // letting the runtime generate it based on type and assembly strong name.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags);
+#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION
+
+ [DllImport(Win32Native.OLE32,CharSet=CharSet.Auto,PreserveSig=false)]
+ private static extern void CoRevokeClassObject(int cookie);
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs b/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs
new file mode 100644
index 0000000000..d722843ae8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/RuntimeEnvironment.cs
@@ -0,0 +1,165 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Runtime information
+**
+**
+=============================================================================*/
+
+using System;
+using System.Text;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Reflection;
+using Microsoft.Win32;
+using System.Runtime.Versioning;
+using StackCrawlMark = System.Threading.StackCrawlMark;
+
+namespace System.Runtime.InteropServices {
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ static
+#endif
+ public class RuntimeEnvironment {
+
+#if !FEATURE_CORECLR
+ // This should have been a static class, but wasn't as of v3.5. Clearly, this is
+ // broken. We'll keep this in V4 for binary compat, but marked obsolete as error
+ // so migrated source code gets fixed. On Silverlight, this type exists but is
+ // not public.
+ [Obsolete("Do not create instances of the RuntimeEnvironment class. Call the static methods directly on this type instead", true)]
+ public RuntimeEnvironment()
+ {
+ // Should not have been instantiable - here for binary compatibility in V4.
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String GetModuleFileName();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String GetDeveloperPath();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String GetHostBindingFile();
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void _GetSystemVersion(StringHandleOnStack retVer);
+#endif //!FEATURE_CORECLR
+
+ public static bool FromGlobalAccessCache(Assembly a)
+ {
+ return a.GlobalAssemblyCache;
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // public member
+#endif
+ [MethodImpl (MethodImplOptions.NoInlining)]
+ public static String GetSystemVersion()
+ {
+#if FEATURE_CORECLR
+
+ return Assembly.GetExecutingAssembly().ImageRuntimeVersion;
+
+#else // FEATURE_CORECLR
+
+ String ver = null;
+ _GetSystemVersion(JitHelpers.GetStringHandleOnStack(ref ver));
+ return ver;
+
+#endif // FEATURE_CORECLR
+
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String GetRuntimeDirectory()
+ {
+ String dir = GetRuntimeDirectoryImpl();
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, dir).Demand();
+ return dir;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String GetRuntimeDirectoryImpl();
+
+ // Returns the system ConfigurationFile
+ public static String SystemConfigurationFile {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ StringBuilder sb = new StringBuilder(Path.MaxPath);
+ sb.Append(GetRuntimeDirectory());
+ sb.Append(AppDomainSetup.RuntimeConfigurationFile);
+ String path = sb.ToString();
+
+ // Do security check
+ new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
+
+ return path;
+ }
+ }
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr GetRuntimeInterfaceImpl(
+ [In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid,
+ [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid);
+
+ //
+ // This function does the equivalent of calling GetInterface(clsid, riid) on the
+ // ICLRRuntimeInfo representing this runtime. See MetaHost.idl for a list of
+ // CLSIDs and IIDs supported by this method.
+ //
+ // Returns unmanaged pointer to requested interface on success. Throws
+ // COMException with failed HR if there is a QI failure.
+ //
+ [System.Security.SecurityCritical] // do not allow partial trust callers
+ [ComVisible(false)]
+ public static IntPtr GetRuntimeInterfaceAsIntPtr(Guid clsid, Guid riid)
+ {
+ return GetRuntimeInterfaceImpl(clsid, riid);
+ }
+
+ //
+ // This function does the equivalent of calling GetInterface(clsid, riid) on the
+ // ICLRRuntimeInfo representing this runtime. See MetaHost.idl for a list of
+ // CLSIDs and IIDs supported by this method.
+ //
+ // Returns an RCW to requested interface on success. Throws
+ // COMException with failed HR if there is a QI failure.
+ //
+ [System.Security.SecurityCritical] // do not allow partial trust callers
+ [ComVisible(false)]
+ public static object GetRuntimeInterfaceAsObject(Guid clsid, Guid riid)
+ {
+ IntPtr p = IntPtr.Zero;
+ try {
+ p = GetRuntimeInterfaceImpl(clsid, riid);
+ return Marshal.GetObjectForIUnknown(p);
+ } finally {
+ if(p != IntPtr.Zero) {
+ Marshal.Release(p);
+ }
+ }
+ }
+
+#endif // FEATURE_COMINTEROP
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs b/src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs
new file mode 100644
index 0000000000..b418d914ed
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SEHException.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for all Structured Exception Handling code.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Runtime.Serialization;
+ // Exception for Structured Exception Handler exceptions.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SEHException : ExternalException {
+ public SEHException()
+ : base() {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public SEHException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ public SEHException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.E_FAIL);
+ }
+
+ protected SEHException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ // Exceptions can be resumable, meaning a filtered exception
+ // handler can correct the problem that caused the exception,
+ // and the code will continue from the point that threw the
+ // exception.
+ //
+ // Resumable exceptions aren't implemented in this version,
+ // but this method exists and always returns false.
+ //
+ public virtual bool CanResume()
+ {
+ return false;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs
new file mode 100644
index 0000000000..0f4caa21a1
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: This exception is thrown when the runtime rank of a safe array
+** is different than the array rank specified in the metadata.
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SafeArrayRankMismatchException : SystemException {
+ public SafeArrayRankMismatchException()
+ : base(Environment.GetResourceString("Arg_SafeArrayRankMismatchException")) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYRANKMISMATCH);
+ }
+
+ public SafeArrayRankMismatchException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYRANKMISMATCH);
+ }
+
+ public SafeArrayRankMismatchException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYRANKMISMATCH);
+ }
+
+ protected SafeArrayRankMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs
new file mode 100644
index 0000000000..a5711c1ade
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+** Purpose: This exception is thrown when the runtime type of an array
+** is different than the safe array sub type specified in the
+** metadata.
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SafeArrayTypeMismatchException : SystemException {
+ public SafeArrayTypeMismatchException()
+ : base(Environment.GetResourceString("Arg_SafeArrayTypeMismatchException")) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYTYPEMISMATCH);
+ }
+
+ public SafeArrayTypeMismatchException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYTYPEMISMATCH);
+ }
+
+ public SafeArrayTypeMismatchException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_SAFEARRAYTYPEMISMATCH);
+ }
+
+ protected SafeArrayTypeMismatchException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs
new file mode 100644
index 0000000000..a659daf2b5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeBuffer.cs
@@ -0,0 +1,415 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Unsafe code that uses pointers should use
+** SafePointer to fix subtle lifetime problems with the
+** underlying resource.
+**
+===========================================================*/
+
+// Design points:
+// *) Avoid handle-recycling problems (including ones triggered via
+// resurrection attacks) for all accesses via pointers. This requires tying
+// together the lifetime of the unmanaged resource with the code that reads
+// from that resource, in a package that uses synchronization to enforce
+// the correct semantics during finalization. We're using SafeHandle's
+// ref count as a gate on whether the pointer can be dereferenced because that
+// controls the lifetime of the resource.
+//
+// *) Keep the penalties for using this class small, both in terms of space
+// and time. Having multiple threads reading from a memory mapped file
+// will already require 2 additional interlocked operations. If we add in
+// a "current position" concept, that requires additional space in memory and
+// synchronization. Since the position in memory is often (but not always)
+// something that can be stored on the stack, we can save some memory by
+// excluding it from this object. However, avoiding the need for
+// synchronization is a more significant win. This design allows multiple
+// threads to read and write memory simultaneously without locks (as long as
+// you don't write to a region of memory that overlaps with what another
+// thread is accessing).
+//
+// *) Space-wise, we use the following memory, including SafeHandle's fields:
+// Object Header MT* handle int bool bool <2 pad bytes> length
+// On 32 bit platforms: 24 bytes. On 64 bit platforms: 40 bytes.
+// (We can safe 4 bytes on x86 only by shrinking SafeHandle)
+//
+// *) Wrapping a SafeHandle would have been a nice solution, but without an
+// ordering between critical finalizable objects, it would have required
+// changes to each SafeHandle subclass to opt in to being usable from a
+// SafeBuffer (or some clever exposure of SafeHandle's state fields and a
+// way of forcing ReleaseHandle to run even after the SafeHandle has been
+// finalized with a ref count > 1). We can use less memory and create fewer
+// objects by simply inserting a SafeBuffer into the class hierarchy.
+//
+// *) In an ideal world, we could get marshaling support for SafeBuffer that
+// would allow us to annotate a P/Invoke declaration, saying this parameter
+// specifies the length of the buffer, and the units of that length are X.
+// P/Invoke would then pass that size parameter to SafeBuffer.
+// [DllImport(...)]
+// static extern SafeMemoryHandle AllocCharBuffer(int numChars);
+// If we could put an attribute on the SafeMemoryHandle saying numChars is
+// the element length, and it must be multiplied by 2 to get to the byte
+// length, we can simplify the usage model for SafeBuffer.
+//
+// *) This class could benefit from a constraint saying T is a value type
+// containing no GC references.
+
+// Implementation notes:
+// *) The Initialize method must be called before you use any instance of
+// a SafeBuffer. To avoid race conditions when storing SafeBuffers in statics,
+// you either need to take a lock when publishing the SafeBuffer, or you
+// need to create a local, initialize the SafeBuffer, then assign to the
+// static variable (perhaps using Interlocked.CompareExchange). Of course,
+// assignments in a static class constructor are under a lock implicitly.
+
+
+namespace System.Runtime.InteropServices
+{
+using System;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using Microsoft.Win32.SafeHandles;
+using System.Diagnostics.Contracts;
+
+
+ [System.Security.SecurityCritical]
+ public abstract unsafe class SafeBuffer : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ // Steal UIntPtr.MaxValue as our uninitialized value.
+ private static readonly UIntPtr Uninitialized = (UIntPtr.Size == 4) ?
+ ((UIntPtr) UInt32.MaxValue) : ((UIntPtr) UInt64.MaxValue);
+
+ private UIntPtr _numBytes;
+
+ protected SafeBuffer(bool ownsHandle) : base(ownsHandle)
+ {
+ _numBytes = Uninitialized;
+ }
+
+ /// <summary>
+ /// Specifies the size of the region of memory, in bytes. Must be
+ /// called before using the SafeBuffer.
+ /// </summary>
+ /// <param name="numBytes">Number of valid bytes in memory.</param>
+ [CLSCompliant(false)]
+ public void Initialize(ulong numBytes)
+ {
+ if (numBytes < 0)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (IntPtr.Size == 4 && numBytes > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_AddressSpace"));
+ Contract.EndContractBlock();
+
+ if (numBytes >= (ulong)Uninitialized)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1"));
+
+ _numBytes = (UIntPtr) numBytes;
+ }
+
+ /// <summary>
+ /// Specifies the the size of the region in memory, as the number of
+ /// elements in an array. Must be called before using the SafeBuffer.
+ /// </summary>
+ [CLSCompliant(false)]
+ public void Initialize(uint numElements, uint sizeOfEachElement)
+ {
+ if (numElements < 0)
+ throw new ArgumentOutOfRangeException("numElements", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (sizeOfEachElement < 0)
+ throw new ArgumentOutOfRangeException("sizeOfEachElement", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (IntPtr.Size == 4 && numElements * sizeOfEachElement > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException("numBytes", Environment.GetResourceString("ArgumentOutOfRange_AddressSpace"));
+ Contract.EndContractBlock();
+
+ if (numElements * sizeOfEachElement >= (ulong)Uninitialized)
+ throw new ArgumentOutOfRangeException("numElements", Environment.GetResourceString("ArgumentOutOfRange_UIntPtrMax-1"));
+
+ _numBytes = checked((UIntPtr) (numElements * sizeOfEachElement));
+ }
+
+ /// <summary>
+ /// Specifies the the size of the region in memory, as the number of
+ /// elements in an array. Must be called before using the SafeBuffer.
+ /// </summary>
+ [CLSCompliant(false)]
+ public void Initialize<T>(uint numElements) where T : struct
+ {
+ Initialize(numElements, Marshal.AlignedSizeOf<T>());
+ }
+
+ // Callers should ensure that they check whether the pointer ref param
+ // is null when AcquirePointer returns. If it is not null, they must
+ // call ReleasePointer in a CER. This method calls DangerousAddRef
+ // & exposes the pointer. Unlike Read, it does not alter the "current
+ // position" of the pointer. Here's how to use it:
+ //
+ // byte* pointer = null;
+ // RuntimeHelpers.PrepareConstrainedRegions();
+ // try {
+ // safeBuffer.AcquirePointer(ref pointer);
+ // // Use pointer here, with your own bounds checking
+ // }
+ // finally {
+ // if (pointer != null)
+ // safeBuffer.ReleasePointer();
+ // }
+ //
+ // Note: If you cast this byte* to a T*, you have to worry about
+ // whether your pointer is aligned. Additionally, you must take
+ // responsibility for all bounds checking with this pointer.
+ /// <summary>
+ /// Obtain the pointer from a SafeBuffer for a block of code,
+ /// with the express responsibility for bounds checking and calling
+ /// ReleasePointer later within a CER to ensure the pointer can be
+ /// freed later. This method either completes successfully or
+ /// throws an exception and returns with pointer set to null.
+ /// </summary>
+ /// <param name="pointer">A byte*, passed by reference, to receive
+ /// the pointer from within the SafeBuffer. You must set
+ /// pointer to null before calling this method.</param>
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public void AcquirePointer(ref byte* pointer)
+ {
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ pointer = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ }
+ finally
+ {
+ bool junk = false;
+ DangerousAddRef(ref junk);
+ pointer = (byte*)handle;
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void ReleasePointer()
+ {
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ DangerousRelease();
+ }
+
+ /// <summary>
+ /// Read a value type from memory at the given offset. This is
+ /// equivalent to: return *(T*)(bytePtr + byteOffset);
+ /// </summary>
+ /// <typeparam name="T">The value type to read</typeparam>
+ /// <param name="byteOffset">Where to start reading from memory. You
+ /// may have to consider alignment.</param>
+ /// <returns>An instance of T read from memory.</returns>
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public T Read<T>(ulong byteOffset) where T : struct {
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ uint sizeofT = Marshal.SizeOfType(typeof(T));
+ byte* ptr = (byte*)handle + byteOffset;
+ SpaceCheck(ptr, sizeofT);
+
+ // return *(T*) (_ptr + byteOffset);
+ T value;
+ bool mustCallRelease = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ DangerousAddRef(ref mustCallRelease);
+
+ GenericPtrToStructure<T>(ptr, out value, sizeofT);
+ }
+ finally
+ {
+ if (mustCallRelease)
+ DangerousRelease();
+ }
+ return value;
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public void ReadArray<T>(ulong byteOffset, T[] array, int index, int count)
+ where T : struct
+ {
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ uint sizeofT = Marshal.SizeOfType(typeof(T));
+ uint alignedSizeofT = Marshal.AlignedSizeOf<T>();
+ byte* ptr = (byte*)handle + byteOffset;
+ SpaceCheck(ptr, checked((ulong)(alignedSizeofT * count)));
+
+ bool mustCallRelease = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ DangerousAddRef(ref mustCallRelease);
+
+ for (int i = 0; i < count; i++)
+ unsafe { GenericPtrToStructure<T>(ptr + alignedSizeofT * i, out array[i + index], sizeofT); }
+ }
+ finally
+ {
+ if (mustCallRelease)
+ DangerousRelease();
+ }
+ }
+
+ /// <summary>
+ /// Write a value type to memory at the given offset. This is
+ /// equivalent to: *(T*)(bytePtr + byteOffset) = value;
+ /// </summary>
+ /// <typeparam name="T">The type of the value type to write to memory.</typeparam>
+ /// <param name="byteOffset">The location in memory to write to. You
+ /// may have to consider alignment.</param>
+ /// <param name="value">The value type to write to memory.</param>
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public void Write<T>(ulong byteOffset, T value) where T : struct {
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ uint sizeofT = Marshal.SizeOfType(typeof(T));
+ byte* ptr = (byte*)handle + byteOffset;
+ SpaceCheck(ptr, sizeofT);
+
+ // *((T*) (_ptr + byteOffset)) = value;
+ bool mustCallRelease = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ DangerousAddRef(ref mustCallRelease);
+ GenericStructureToPtr(ref value, ptr, sizeofT);
+ }
+ finally
+ {
+ if (mustCallRelease)
+ DangerousRelease();
+ }
+ }
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public void WriteArray<T>(ulong byteOffset, T[] array, int index, int count)
+ where T : struct
+ {
+ if (array == null)
+ throw new ArgumentNullException("array", Environment.GetResourceString("ArgumentNull_Buffer"));
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (array.Length - index < count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ uint sizeofT = Marshal.SizeOfType(typeof(T));
+ uint alignedSizeofT = Marshal.AlignedSizeOf<T>();
+ byte* ptr = (byte*)handle + byteOffset;
+ SpaceCheck(ptr, checked((ulong)(alignedSizeofT * count)));
+
+ bool mustCallRelease = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ DangerousAddRef(ref mustCallRelease);
+ for (int i = 0; i < count; i++)
+ unsafe { GenericStructureToPtr(ref array[i + index], ptr + alignedSizeofT * i, sizeofT); }
+ }
+ finally
+ {
+ if (mustCallRelease)
+ DangerousRelease();
+ }
+ }
+
+
+ /// <summary>
+ /// Returns the number of bytes in the memory region.
+ /// </summary>
+ [CLSCompliant(false)]
+ public ulong ByteLength {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get {
+ if (_numBytes == Uninitialized)
+ throw NotInitialized();
+
+ return (ulong) _numBytes;
+ }
+ }
+
+ /* No indexer. The perf would be misleadingly bad. People should use
+ * AcquirePointer and ReleasePointer instead. */
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private void SpaceCheck(byte* ptr, ulong sizeInBytes)
+ {
+ if ((ulong)_numBytes < sizeInBytes)
+ NotEnoughRoom();
+ if ((ulong)(ptr - (byte*) handle) > ((ulong)_numBytes) - sizeInBytes)
+ NotEnoughRoom();
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static void NotEnoughRoom()
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_BufferTooSmall"));
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static InvalidOperationException NotInitialized()
+ {
+ Contract.Assert(false, "Uninitialized SafeBuffer! Someone needs to call Initialize before using this instance!");
+ return new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MustCallInitialize"));
+ }
+
+ // FCALL limitations mean we can't have generic FCALL methods. However, we can pass
+ // TypedReferences to FCALL methods.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static void GenericPtrToStructure<T>(byte* ptr, out T structure, uint sizeofT) where T : struct
+ {
+ structure = default(T); // Dummy assignment to silence the compiler
+ PtrToStructureNative(ptr, __makeref(structure), sizeofT);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern void PtrToStructureNative(byte* ptr, /*out T*/ TypedReference structure, uint sizeofT);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static void GenericStructureToPtr<T>(ref T structure, byte* ptr, uint sizeofT) where T : struct
+ {
+ StructureToPtrNative(__makeref(structure), ptr, sizeofT);
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern void StructureToPtrNative(/*ref T*/ TypedReference structure, byte* ptr, uint sizeofT);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs
new file mode 100644
index 0000000000..c26852874d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeHandle.cs
@@ -0,0 +1,317 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** A specially designed handle wrapper to ensure we never leak
+** an OS handle. The runtime treats this class specially during
+** P/Invoke marshaling and finalization. Users should write
+** subclasses of SafeHandle for each distinct handle type.
+**
+**
+===========================================================*/
+
+namespace System.Runtime.InteropServices {
+
+using System;
+using System.Reflection;
+using System.Threading;
+using System.Security.Permissions;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.IO;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+
+/*
+ Problems addressed by the SafeHandle class:
+ 1) Critical finalization - ensure we never leak OS resources in SQL. Done
+ without running truly arbitrary & unbounded amounts of managed code.
+ 2) Reduced graph promotion - during finalization, keep object graph small
+ 3) GC.KeepAlive behavior - P/Invoke vs. finalizer thread race conditions (HandleRef)
+ 4) Elimination of security race conditions w/ explicit calls to Close (HandleProtector)
+ 5) Enforcement of the above via the type system - Don't use IntPtr anymore.
+ 6) Allows the handle lifetime to be controlled externally via a boolean.
+
+ Subclasses of SafeHandle will implement the ReleaseHandle abstract method
+ used to execute any code required to free the handle. This method will be
+ prepared as a constrained execution region at instance construction time
+ (along with all the methods in its statically determinable call graph). This
+ implies that we won't get any inconvenient jit allocation errors or rude
+ thread abort interrupts while releasing the handle but the user must still
+ write careful code to avoid injecting fault paths of their own (see the CER
+ spec for more details). In particular, any sub-methods you call should be
+ decorated with a reliability contract of the appropriate level. In most cases
+ this should be:
+ ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)
+ Also, any P/Invoke methods should use the SuppressUnmanagedCodeSecurity
+ attribute to avoid a runtime security check that can also inject failures
+ (even if the check is guaranteed to pass).
+
+ The GC will run ReleaseHandle methods after any normal finalizers have been
+ run for objects that were collected at the same time. This ensures classes
+ like FileStream can run a normal finalizer to flush out existing buffered
+ data. This is key - it means adding this class to a class like FileStream does
+ not alter our current semantics w.r.t. finalization today.
+
+ Subclasses must also implement the IsInvalid property so that the
+ infrastructure can tell when critical finalization is actually required.
+ Again, this method is prepared ahead of time. It's envisioned that direct
+ subclasses of SafeHandle will provide an IsInvalid implementation that suits
+ the general type of handle they support (null is invalid, -1 is invalid etc.)
+ and then these classes will be further derived for specific safe handle types.
+
+ Most classes using SafeHandle should not provide a finalizer. If they do
+ need to do so (ie, for flushing out file buffers, needing to write some data
+ back into memory, etc), then they can provide a finalizer that will be
+ guaranteed to run before the SafeHandle's critical finalizer.
+
+ Note that SafeHandle's ReleaseHandle is called from a constrained execution
+ region, and is eagerly prepared before we create your class. This means you
+ should only call methods with an appropriate reliability contract from your
+ ReleaseHandle method.
+
+ Subclasses are expected to be written as follows (note that
+ SuppressUnmanagedCodeSecurity should always be used on any P/Invoke methods
+ invoked as part of ReleaseHandle, in order to switch the security check from
+ runtime to jit time and thus remove a possible failure path from the
+ invocation of the method):
+
+ internal sealed MySafeHandleSubclass : SafeHandle {
+ // Called by P/Invoke when returning SafeHandles
+ private MySafeHandleSubclass() : base(IntPtr.Zero, true)
+ {
+ }
+
+ // If & only if you need to support user-supplied handles
+ internal MySafeHandleSubclass(IntPtr preexistingHandle, bool ownsHandle) : base(IntPtr.Zero, ownsHandle)
+ {
+ SetHandle(preexistingHandle);
+ }
+
+ // Do not provide a finalizer - SafeHandle's critical finalizer will
+ // call ReleaseHandle for you.
+
+ public override bool IsInvalid {
+ get { return handle == IntPtr.Zero; }
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ return MyNativeMethods.CloseHandle(handle);
+ }
+ }
+
+ Then elsewhere to create one of these SafeHandles, define a method
+ with the following type of signature (CreateFile follows this model).
+ Note that when returning a SafeHandle like this, P/Invoke will call your
+ class's default constructor. Also, you probably want to define CloseHandle
+ somewhere, and remember to apply a reliability contract to it.
+
+ [SuppressUnmanagedCodeSecurity]
+ internal static class MyNativeMethods {
+ [DllImport("kernel32")]
+ private static extern MySafeHandleSubclass CreateHandle(int someState);
+
+ [DllImport("kernel32", SetLastError=true), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern bool CloseHandle(IntPtr handle);
+ }
+
+ Drawbacks with this implementation:
+ 1) Requires some magic to run the critical finalizer.
+ 2) Requires more memory than just an IntPtr.
+ 3) If you use DangerousAddRef and forget to call DangerousRelease, you can leak a SafeHandle. Use CER's & don't do that.
+ */
+
+
+// This class should not be serializable - it's a handle. We require unmanaged
+// code permission to subclass SafeHandle to prevent people from writing a
+// subclass and suddenly being able to run arbitrary native code with the
+// same signature as CloseHandle. This is technically a little redundant, but
+// we'll do this to ensure we've cut off all attack vectors. Similarly, all
+// methods have a link demand to ensure untrusted code cannot directly edit
+// or alter a handle.
+[System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+[SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+public abstract class SafeHandle : CriticalFinalizerObject, IDisposable
+{
+ // ! Do not add or rearrange fields as the EE depends on this layout.
+ //------------------------------------------------------------------
+#if DEBUG
+ // FxCop thinks this field is marshaled and so it raises a CA2101 error unless
+ // we specify this. In practice this is never presented to Win32.
+ [MarshalAs(UnmanagedType.LPWStr)]
+ private String _stackTrace; // Where we allocated this SafeHandle.
+#endif
+ protected IntPtr handle; // this must be protected so derived classes can use out params.
+ private int _state; // Combined ref count and closed/disposed flags (so we can atomically modify them).
+ private bool _ownsHandle; // Whether we can release this handle.
+#pragma warning disable 414
+ private bool _fullyInitialized; // Whether constructor completed.
+#pragma warning restore 414
+
+ // Creates a SafeHandle class. Users must then set the Handle property.
+ // To prevent the SafeHandle from being freed, write a subclass that
+ // doesn't define a finalizer.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected SafeHandle(IntPtr invalidHandleValue, bool ownsHandle)
+ {
+ handle = invalidHandleValue;
+ _state = 4; // Ref count 1 and not closed or disposed.
+ _ownsHandle = ownsHandle;
+
+ if (!ownsHandle)
+ GC.SuppressFinalize(this);
+
+#if DEBUG
+ if (BCLDebug.SafeHandleStackTracesEnabled)
+ _stackTrace = Environment.GetStackTrace(null, false);
+ else
+ _stackTrace = "For a stack trace showing who allocated this SafeHandle, set SafeHandleStackTraces to 1 and rerun your app.";
+#endif
+
+ // Set this last to prevent SafeHandle's finalizer from freeing an
+ // invalid handle. This means we don't have to worry about
+ // ThreadAbortExceptions interrupting this constructor or the managed
+ // constructors on subclasses that call this constructor.
+ _fullyInitialized = true;
+ }
+
+#if FEATURE_CORECLR
+ // Migrating InheritanceDemands requires this default ctor, so we can mark it critical
+ protected SafeHandle()
+ {
+ BCLDebug.Assert(false, "SafeHandle's protected default ctor should never be used!");
+ throw new NotImplementedException();
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ ~SafeHandle()
+ {
+ Dispose(false);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ extern void InternalFinalize();
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected void SetHandle(IntPtr handle) {
+ this.handle = handle;
+ }
+
+ // This method is necessary for getting an IntPtr out of a SafeHandle.
+ // Used to tell whether a call to create the handle succeeded by comparing
+ // the handle against a known invalid value, and for backwards
+ // compatibility to support the handle properties returning IntPtrs on
+ // many of our Framework classes.
+ // Note that this method is dangerous for two reasons:
+ // 1) If the handle has been marked invalid with SetHandleasInvalid,
+ // DangerousGetHandle will still return the original handle value.
+ // 2) The handle returned may be recycled at any point. At best this means
+ // the handle might stop working suddenly. At worst, if the handle or
+ // the resource the handle represents is exposed to untrusted code in
+ // any way, this can lead to a handle recycling security attack (i.e. an
+ // untrusted caller can query data on the handle you've just returned
+ // and get back information for an entirely unrelated resource).
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public IntPtr DangerousGetHandle()
+ {
+ return handle;
+ }
+
+ public bool IsClosed {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return (_state & 1) == 1; }
+ }
+
+ public abstract bool IsInvalid {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Close() {
+ Dispose(true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Dispose() {
+ Dispose(true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ InternalDispose();
+ else
+ InternalFinalize();
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void InternalDispose();
+
+ // This should only be called for cases when you know for a fact that
+ // your handle is invalid and you want to record that information.
+ // An example is calling a syscall and getting back ERROR_INVALID_HANDLE.
+ // This method will normally leak handles!
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void SetHandleAsInvalid();
+
+ // Implement this abstract method in your derived class to specify how to
+ // free the handle. Be careful not write any code that's subject to faults
+ // in this method (the runtime will prepare the infrastructure for you so
+ // that no jit allocations etc. will occur, but don't allocate memory unless
+ // you can deal with the failure and still free the handle).
+ // The boolean returned should be true for success and false if the runtime
+ // should fire a SafeHandleCriticalFailure MDA (CustomerDebugProbe) if that
+ // MDA is enabled.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected abstract bool ReleaseHandle();
+
+ // Add a reason why this handle should not be relinquished (i.e. have
+ // ReleaseHandle called on it). This method has dangerous in the name since
+ // it must always be used carefully (e.g. called within a CER) to avoid
+ // leakage of the handle. It returns a boolean indicating whether the
+ // increment was actually performed to make it easy for program logic to
+ // back out in failure cases (i.e. is a call to DangerousRelease needed).
+ // It is passed back via a ref parameter rather than as a direct return so
+ // that callers need not worry about the atomicity of calling the routine
+ // and assigning the return value to a variable (the variable should be
+ // explicitly set to false prior to the call). The only failure cases are
+ // when the method is interrupted prior to processing by a thread abort or
+ // when the handle has already been (or is in the process of being)
+ // released.
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void DangerousAddRef(ref bool success);
+
+ // Partner to DangerousAddRef. This should always be successful when used in
+ // a correct manner (i.e. matching a successful DangerousAddRef and called
+ // from a region such as a CER where a thread abort cannot interrupt
+ // processing). In the same way that unbalanced DangerousAddRef calls can
+ // cause resource leakage, unbalanced DangerousRelease calls may cause
+ // invalid handle states to become visible to other threads. This
+ // constitutes a potential security hole (via handle recycling) as well as a
+ // correctness problem -- so don't ever expose Dangerous* calls out to
+ // untrusted code.
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void DangerousRelease();
+}
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs b/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs
new file mode 100644
index 0000000000..b0c422d0c0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/SafeHeapHandle.cs
@@ -0,0 +1,115 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Handle for heap memory that allows tracking of capacity and reallocating.
+ /// </summary>
+ [System.Security.SecurityCritical]
+ internal sealed class SafeHeapHandle : SafeBuffer
+ {
+ /// <summary>
+ /// Allocate a buffer of the given size if requested.
+ /// </summary>
+ /// <param name="byteLength">Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit.</param>
+ /// <exception cref="OutOfMemoryException">Thrown if the requested memory size cannot be allocated.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if size is greater than the maximum memory size.</exception>
+ public SafeHeapHandle(ulong byteLength) : base(ownsHandle: true)
+ {
+ Resize(byteLength);
+ }
+
+ public override bool IsInvalid
+ {
+ [System.Security.SecurityCritical]
+ get
+ { return handle == IntPtr.Zero; }
+ }
+
+ /// <summary>
+ /// Resize the buffer to the given size if requested.
+ /// </summary>
+ /// <param name="byteLength">Required size in bytes. Must be less than UInt32.MaxValue for 32 bit or UInt64.MaxValue for 64 bit.</param>
+ /// <exception cref="OutOfMemoryException">Thrown if the requested memory size cannot be allocated.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if size is greater than the maximum memory size.</exception>
+ public void Resize(ulong byteLength)
+ {
+ if (IsClosed) throw new ObjectDisposedException("SafeHeapHandle");
+
+ ulong originalLength = 0;
+ if (handle == IntPtr.Zero)
+ {
+ handle = Marshal.AllocHGlobal((IntPtr)byteLength);
+ }
+ else
+ {
+ originalLength = ByteLength;
+
+ // This may or may not be the same handle, may realloc in place. If the
+ // handle changes Windows will deal with the old handle, trying to free it will
+ // cause an error.
+ handle = Marshal.ReAllocHGlobal(pv: handle, cb: (IntPtr)byteLength);
+ }
+
+ if (handle == IntPtr.Zero)
+ {
+ // Only real plausible answer
+ throw new OutOfMemoryException();
+ }
+
+ if (byteLength > originalLength)
+ {
+ // Add pressure
+ ulong addedBytes = byteLength - originalLength;
+ if (addedBytes > long.MaxValue)
+ {
+ GC.AddMemoryPressure(long.MaxValue);
+ GC.AddMemoryPressure((long)(addedBytes - long.MaxValue));
+ }
+ else
+ {
+ GC.AddMemoryPressure((long)addedBytes);
+ }
+ }
+ else
+ {
+ // Shrank or did nothing, release pressure if needed
+ RemoveMemoryPressure(originalLength - byteLength);
+ }
+
+ Initialize(byteLength);
+ }
+
+ private void RemoveMemoryPressure(ulong removedBytes)
+ {
+ if (removedBytes == 0) return;
+
+ if (removedBytes > long.MaxValue)
+ {
+ GC.RemoveMemoryPressure(long.MaxValue);
+ GC.RemoveMemoryPressure((long)(removedBytes - long.MaxValue));
+ }
+ else
+ {
+ GC.RemoveMemoryPressure((long)removedBytes);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ protected override bool ReleaseHandle()
+ {
+ IntPtr handle = this.handle;
+ this.handle = IntPtr.Zero;
+
+ if (handle != IntPtr.Zero)
+ {
+ RemoveMemoryPressure(ByteLength);
+ Marshal.FreeHGlobal(handle);
+ }
+
+ return true;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs b/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs
new file mode 100644
index 0000000000..15b1b6ae8e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/StringBuffer.cs
@@ -0,0 +1,402 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices
+{
+ /// <summary>
+ /// Native buffer that deals in char size increments. Dispose to free memory. Allows buffers larger
+ /// than a maximum size string to enable working with very large string arrays. Always makes ordinal
+ /// comparisons.
+ ///
+ /// A more performant replacement for StringBuilder when performing native interop.
+ /// </summary>
+ /// <remarks>
+ /// Suggested use through P/Invoke: define DllImport arguments that take a character buffer as IntPtr.
+ /// NativeStringBuffer has an implicit conversion to IntPtr.
+ /// </remarks>
+ internal class StringBuffer : NativeBuffer
+ {
+ private uint _length;
+
+ /// <summary>
+ /// Instantiate the buffer with capacity for at least the specified number of characters. Capacity
+ /// includes the trailing null character.
+ /// </summary>
+ public StringBuffer(uint initialCapacity = 0)
+ : base(initialCapacity * (ulong)sizeof(char))
+ {
+ }
+
+ /// <summary>
+ /// Instantiate the buffer with a copy of the specified string.
+ /// </summary>
+ public StringBuffer(string initialContents)
+ : base(0)
+ {
+ // We don't pass the count of bytes to the base constructor, appending will
+ // initialize to the correct size for the specified initial contents.
+ if (initialContents != null)
+ {
+ Append(initialContents);
+ }
+ }
+
+ /// <summary>
+ /// Instantiate the buffer with a copy of the specified StringBuffer.
+ /// </summary>
+ public StringBuffer(StringBuffer initialContents)
+ : base(0)
+ {
+ // We don't pass the count of bytes to the base constructor, appending will
+ // initialize to the correct size for the specified initial contents.
+ if (initialContents != null)
+ {
+ Append(initialContents);
+ }
+ }
+
+ /// <summary>
+ /// Get/set the character at the given index.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if attempting to index outside of the buffer length.</exception>
+ public unsafe char this[uint index]
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ if (index >= _length) throw new ArgumentOutOfRangeException("index");
+ return CharPointer[index];
+ }
+ [System.Security.SecuritySafeCritical]
+ set
+ {
+ if (index >= _length) throw new ArgumentOutOfRangeException("index");
+ CharPointer[index] = value;
+ }
+ }
+
+ /// <summary>
+ /// Character capacity of the buffer. Includes the count for the trailing null character.
+ /// </summary>
+ public uint CharCapacity
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ ulong byteCapacity = ByteCapacity;
+ ulong charCapacity = byteCapacity == 0 ? 0 : byteCapacity / sizeof(char);
+ return charCapacity > uint.MaxValue ? uint.MaxValue : (uint)charCapacity;
+ }
+ }
+
+ /// <summary>
+ /// Ensure capacity in characters is at least the given minimum. Capacity includes space for the trailing
+ /// null, which is not part of the Length.
+ /// </summary>
+ /// <exception cref="OutOfMemoryException">Thrown if unable to allocate memory when setting.</exception>
+ [System.Security.SecuritySafeCritical]
+ public void EnsureCharCapacity(uint minCapacity)
+ {
+ EnsureByteCapacity(minCapacity * (ulong)sizeof(char));
+ }
+
+ /// <summary>
+ /// The logical length of the buffer in characters. (Does not include the final null, which is auto appended.) Will automatically attempt to increase capacity.
+ /// This is where the usable data ends.
+ /// </summary>
+ /// <exception cref="OutOfMemoryException">Thrown if unable to allocate memory when setting.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">Thrown if the set size in bytes is uint.MaxValue (as space is implicitly reservced for the trailing null).</exception>
+ public unsafe uint Length
+ {
+ get { return _length; }
+ [System.Security.SecuritySafeCritical]
+ set
+ {
+ if (value == uint.MaxValue) throw new ArgumentOutOfRangeException("Length");
+
+ // Null terminate
+ EnsureCharCapacity(value + 1);
+ CharPointer[value] = '\0';
+
+ _length = value;
+ }
+ }
+
+ /// <summary>
+ /// For use when the native api null terminates but doesn't return a length.
+ /// If no null is found, the length will not be changed.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public unsafe void SetLengthToFirstNull()
+ {
+ char* buffer = CharPointer;
+ uint capacity = CharCapacity;
+ for (uint i = 0; i < capacity; i++)
+ {
+ if (buffer[i] == '\0')
+ {
+ _length = i;
+ break;
+ }
+ }
+ }
+
+ internal unsafe char* CharPointer
+ {
+ [System.Security.SecurityCritical]
+ get
+ {
+ return (char*)VoidPointer;
+ }
+ }
+
+ /// <summary>
+ /// True if the buffer contains the given character.
+ /// </summary>
+ [System.Security.SecurityCritical]
+ public unsafe bool Contains(char value)
+ {
+ char* start = CharPointer;
+ uint length = _length;
+
+ for (uint i = 0; i < length; i++)
+ {
+ if (*start++ == value) return true;
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if the buffer starts with the given string.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public bool StartsWith(string value)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+ if (_length < (uint)value.Length) return false;
+ return SubstringEquals(value, startIndex: 0, count: value.Length);
+ }
+
+ /// <summary>
+ /// Returns true if the specified StringBuffer substring equals the given value.
+ /// </summary>
+ /// <param name="value">The value to compare against the specified substring.</param>
+ /// <param name="startIndex">Start index of the sub string.</param>
+ /// <param name="count">Length of the substring, or -1 to check all remaining.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="startIndex"/> or <paramref name="count"/> are outside the range
+ /// of the buffer's length.
+ /// </exception>
+ [System.Security.SecuritySafeCritical]
+ public unsafe bool SubstringEquals(string value, uint startIndex = 0, int count = -1)
+ {
+ if (value == null) return false;
+ if (count < -1) throw new ArgumentOutOfRangeException("count");
+ if (startIndex > _length) throw new ArgumentOutOfRangeException("startIndex");
+
+ uint realCount = count == -1 ? _length - startIndex : (uint)count;
+ if (checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException("count");
+
+ int length = value.Length;
+
+ // Check the substring length against the input length
+ if (realCount != (uint)length) return false;
+
+ fixed (char* valueStart = value)
+ {
+ char* bufferStart = CharPointer + startIndex;
+ for (int i = 0; i < length; i++)
+ {
+ // Note that indexing in this case generates faster code than trying to copy the pointer and increment it
+ if (*bufferStart++ != valueStart[i]) return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Append the given string.
+ /// </summary>
+ /// <param name="value">The string to append.</param>
+ /// <param name="startIndex">The index in the input string to start appending from.</param>
+ /// <param name="count">The count of characters to copy from the input string, or -1 for all remaining.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="startIndex"/> or <paramref name="count"/> are outside the range
+ /// of <paramref name="value"/> characters.
+ /// </exception>
+ [System.Security.SecuritySafeCritical]
+ public void Append(string value, int startIndex = 0, int count = -1)
+ {
+ CopyFrom(
+ bufferIndex: _length,
+ source: value,
+ sourceIndex: startIndex,
+ count: count);
+ }
+
+ /// <summary>
+ /// Append the given buffer.
+ /// </summary>
+ /// <param name="value">The buffer to append.</param>
+ /// <param name="startIndex">The index in the input buffer to start appending from.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="startIndex"/> is outside the range of <paramref name="value"/> characters.
+ /// </exception>
+ public void Append(StringBuffer value, uint startIndex = 0)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+ if (value.Length == 0) return;
+ value.CopyTo(
+ bufferIndex: startIndex,
+ destination: this,
+ destinationIndex: _length,
+ count: value.Length);
+ }
+
+ /// <summary>
+ /// Append the given buffer.
+ /// </summary>
+ /// <param name="value">The buffer to append.</param>
+ /// <param name="startIndex">The index in the input buffer to start appending from.</param>
+ /// <param name="count">The count of characters to copy from the buffer string.</param>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="value"/> is null.</exception>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="startIndex"/> or <paramref name="count"/> are outside the range
+ /// of <paramref name="value"/> characters.
+ /// </exception>
+ public void Append(StringBuffer value, uint startIndex, uint count)
+ {
+ if (value == null) throw new ArgumentNullException("value");
+ if (count == 0) return;
+ value.CopyTo(
+ bufferIndex: startIndex,
+ destination: this,
+ destinationIndex: _length,
+ count: count);
+ }
+
+ /// <summary>
+ /// Copy contents to the specified buffer. Destination index must be within current destination length.
+ /// Will grow the destination buffer if needed.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="bufferIndex"/> or <paramref name="destinationIndex"/> or <paramref name="count"/> are outside the range
+ /// of <paramref name="value"/> characters.
+ /// </exception>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="destination"/> is null.</exception>
+ [System.Security.SecuritySafeCritical]
+ public unsafe void CopyTo(uint bufferIndex, StringBuffer destination, uint destinationIndex, uint count)
+ {
+ if (destination == null) throw new ArgumentNullException("destination");
+ if (destinationIndex > destination._length) throw new ArgumentOutOfRangeException("destinationIndex");
+ if (bufferIndex >= _length) throw new ArgumentOutOfRangeException("bufferIndex");
+ if (_length < checked(bufferIndex + count)) throw new ArgumentOutOfRangeException("count");
+
+ if (count == 0) return;
+ uint lastIndex = checked(destinationIndex + count);
+ if (destination._length < lastIndex) destination.Length = lastIndex;
+
+ Buffer.MemoryCopy(
+ source: CharPointer + bufferIndex,
+ destination: destination.CharPointer + destinationIndex,
+ destinationSizeInBytes: checked((long)(destination.ByteCapacity - (destinationIndex * sizeof(char)))),
+ sourceBytesToCopy: checked((long)count * sizeof(char)));
+ }
+
+ /// <summary>
+ /// Copy contents from the specified string into the buffer at the given index. Start index must be within the current length of
+ /// the buffer, will grow as necessary.
+ /// </summary>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="bufferIndex"/> or <paramref name="sourceIndex"/> or <paramref name="count"/> are outside the range
+ /// of <paramref name="value"/> characters.
+ /// </exception>
+ /// <exception cref="ArgumentNullException">Thrown if <paramref name="source"/> is null.</exception>
+ [System.Security.SecuritySafeCritical]
+ public unsafe void CopyFrom(uint bufferIndex, string source, int sourceIndex = 0, int count = -1)
+ {
+ if (source == null) throw new ArgumentNullException("source");
+ if (bufferIndex > _length) throw new ArgumentOutOfRangeException("bufferIndex");
+ if (sourceIndex < 0 || sourceIndex >= source.Length) throw new ArgumentOutOfRangeException("sourceIndex");
+ if (count == -1) count = source.Length - sourceIndex;
+ if (count < 0 || source.Length - count < sourceIndex) throw new ArgumentOutOfRangeException("count");
+
+ if (count == 0) return;
+ uint lastIndex = bufferIndex + (uint)count;
+ if (_length < lastIndex) Length = lastIndex;
+
+ fixed (char* content = source)
+ {
+ Buffer.MemoryCopy(
+ source: content + sourceIndex,
+ destination: CharPointer + bufferIndex,
+ destinationSizeInBytes: checked((long)(ByteCapacity - (bufferIndex * sizeof(char)))),
+ sourceBytesToCopy: (long)count * sizeof(char));
+ }
+ }
+
+ /// <summary>
+ /// Trim the specified values from the end of the buffer. If nothing is specified, nothing is trimmed.
+ /// </summary>
+ [System.Security.SecuritySafeCritical]
+ public unsafe void TrimEnd(char[] values)
+ {
+ if (values == null || values.Length == 0 || _length == 0) return;
+
+ char* end = CharPointer + _length - 1;
+
+ while (_length > 0 && Array.IndexOf(values, *end) >= 0)
+ {
+ Length = _length - 1;
+ end--;
+ }
+ }
+
+ /// <summary>
+ /// String representation of the entire buffer. If the buffer is larger than the maximum size string (int.MaxValue) this will throw.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">Thrown if the buffer is too big to fit into a string.</exception>
+ [System.Security.SecuritySafeCritical]
+ public unsafe override string ToString()
+ {
+ if (_length == 0) return string.Empty;
+ if (_length > int.MaxValue) throw new InvalidOperationException();
+ return new string(CharPointer, startIndex: 0, length: (int)_length);
+ }
+
+ /// <summary>
+ /// Get the given substring in the buffer.
+ /// </summary>
+ /// <param name="count">Count of characters to take, or remaining characters from <paramref name="startIndex"/> if -1.</param>
+ /// <exception cref="ArgumentOutOfRangeException">
+ /// Thrown if <paramref name="startIndex"/> or <paramref name="count"/> are outside the range of the buffer's length
+ /// or count is greater than the maximum string size (int.MaxValue).
+ /// </exception>
+ [System.Security.SecuritySafeCritical]
+ public unsafe string Substring(uint startIndex, int count = -1)
+ {
+ if (startIndex > (_length == 0 ? 0 : _length - 1)) throw new ArgumentOutOfRangeException("startIndex");
+ if (count < -1) throw new ArgumentOutOfRangeException("count");
+
+ uint realCount = count == -1 ? _length - startIndex : (uint)count;
+ if (realCount > int.MaxValue || checked(startIndex + realCount) > _length) throw new ArgumentOutOfRangeException("count");
+ if (realCount == 0) return string.Empty;
+
+ // The buffer could be bigger than will fit into a string, but the substring might fit. As the starting
+ // index might be bigger than int we need to index ourselves.
+ return new string(value: CharPointer + startIndex, startIndex: 0, length: (int)realCount);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override void Free()
+ {
+ base.Free();
+ _length = 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs
new file mode 100644
index 0000000000..29b094c9e8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventItfInfo.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.TCEAdapterGen {
+
+ using System;
+ using System.Reflection;
+ using System.Collections;
+
+ internal class EventItfInfo
+ {
+ public EventItfInfo(String strEventItfName,
+ String strSrcItfName,
+ String strEventProviderName,
+ RuntimeAssembly asmImport,
+ RuntimeAssembly asmSrcItf)
+ {
+ m_strEventItfName = strEventItfName;
+ m_strSrcItfName = strSrcItfName;
+ m_strEventProviderName = strEventProviderName;
+ m_asmImport = asmImport;
+ m_asmSrcItf = asmSrcItf;
+ }
+
+ public Type GetEventItfType()
+ {
+ Type t = m_asmImport.GetType(m_strEventItfName, true, false);
+ if (t != null && !t.IsVisible)
+ t = null;
+ return t;
+ }
+
+ public Type GetSrcItfType()
+ {
+ Type t = m_asmSrcItf.GetType(m_strSrcItfName, true, false);
+ if (t != null && !t.IsVisible)
+ t = null;
+ return t;
+ }
+
+ public String GetEventProviderName()
+ {
+ return m_strEventProviderName;
+ }
+
+ private String m_strEventItfName;
+ private String m_strSrcItfName;
+ private String m_strEventProviderName;
+ private RuntimeAssembly m_asmImport;
+ private RuntimeAssembly m_asmSrcItf;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs
new file mode 100644
index 0000000000..58f70e57b7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventProviderWriter.cs
@@ -0,0 +1,773 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.TCEAdapterGen {
+ using System.Runtime.InteropServices.ComTypes;
+ using ubyte = System.Byte;
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Collections;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ internal class EventProviderWriter
+ {
+ private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
+
+ private readonly Type[] MonitorEnterParamTypes = new Type[] { typeof(Object), Type.GetType("System.Boolean&") };
+
+ public EventProviderWriter( ModuleBuilder OutputModule, String strDestTypeName, Type EventItfType, Type SrcItfType, Type SinkHelperType )
+ {
+ m_OutputModule = OutputModule;
+ m_strDestTypeName = strDestTypeName;
+ m_EventItfType = EventItfType;
+ m_SrcItfType = SrcItfType;
+ m_SinkHelperType = SinkHelperType;
+ }
+
+ public Type Perform()
+ {
+ // Create the event provider class.
+ TypeBuilder OutputTypeBuilder = m_OutputModule.DefineType(
+ m_strDestTypeName,
+ TypeAttributes.Sealed | TypeAttributes.NotPublic,
+ typeof(Object),
+ new Type[]{m_EventItfType, typeof(IDisposable)}
+ );
+
+ // Create the event source field.
+ FieldBuilder fbCPC = OutputTypeBuilder.DefineField(
+ "m_ConnectionPointContainer",
+ typeof(IConnectionPointContainer),
+ FieldAttributes.Private
+ );
+
+ // Create array of event sink helpers.
+ FieldBuilder fbSinkHelper = OutputTypeBuilder.DefineField(
+ "m_aEventSinkHelpers",
+ typeof(ArrayList),
+ FieldAttributes.Private
+ );
+
+ // Define the connection point field.
+ FieldBuilder fbEventCP = OutputTypeBuilder.DefineField(
+ "m_ConnectionPoint",
+ typeof(IConnectionPoint),
+ FieldAttributes.Private
+ );
+
+ // Define the InitXXX method.
+ MethodBuilder InitSrcItfMethodBuilder =
+ DefineInitSrcItfMethod( OutputTypeBuilder, m_SrcItfType, fbSinkHelper, fbEventCP, fbCPC );
+
+ // Process all the methods in the event interface.
+ MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_SrcItfType);
+ for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ )
+ {
+ if ( m_SrcItfType == aMethods[cMethods].DeclaringType )
+ {
+ // Define the add_XXX method.
+ MethodBuilder AddEventMethodBuilder = DefineAddEventMethod(
+ OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP, InitSrcItfMethodBuilder );
+
+ // Define the remove_XXX method.
+ MethodBuilder RemoveEventMethodBuilder = DefineRemoveEventMethod(
+ OutputTypeBuilder, aMethods[cMethods], m_SinkHelperType, fbSinkHelper, fbEventCP );
+ }
+ }
+
+ // Define the constructor.
+ DefineConstructor( OutputTypeBuilder, fbCPC );
+
+ // Define the finalize method.
+ MethodBuilder FinalizeMethod = DefineFinalizeMethod( OutputTypeBuilder, m_SinkHelperType, fbSinkHelper, fbEventCP );
+
+ // Define the Dispose method.
+ DefineDisposeMethod( OutputTypeBuilder, FinalizeMethod);
+
+ return OutputTypeBuilder.CreateType();
+ }
+
+ private MethodBuilder DefineAddEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, MethodBuilder mbInitSrcItf )
+ {
+ Type[] aParamTypes;
+
+ // Find the delegate on the event sink helper.
+ FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" );
+ Contract.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper");
+
+ // Find the cookie on the event sink helper.
+ FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" );
+ Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper");
+
+ // Retrieve the sink helper's constructor.
+ ConstructorInfo SinkHelperCons = SinkHelperClass.GetConstructor(EventProviderWriter.DefaultLookup | BindingFlags.NonPublic, null, Array.Empty<Type>(), null );
+ Contract.Assert(SinkHelperCons != null, "Unable to find the constructor for the sink helper");
+
+ // Retrieve the IConnectionPoint.Advise method.
+ MethodInfo CPAdviseMethod = typeof(IConnectionPoint).GetMethod( "Advise" );
+ Contract.Assert(CPAdviseMethod != null, "Unable to find the method ConnectionPoint.Advise");
+
+ // Retrieve the ArrayList.Add method.
+ aParamTypes = new Type[1];
+ aParamTypes[0] = typeof(Object);
+ MethodInfo ArrayListAddMethod = typeof(ArrayList).GetMethod( "Add", aParamTypes, null );
+ Contract.Assert(ArrayListAddMethod != null, "Unable to find the method ArrayList.Add");
+
+ // Retrieve the Monitor.Enter() method.
+ MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod( "Enter", MonitorEnterParamTypes, null );
+ Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()");
+
+ // Retrieve the Monitor.Exit() method.
+ aParamTypes[0] = typeof(Object);
+ MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null );
+ Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()");
+
+ // Define the add_XXX method.
+ Type[] parameterTypes;
+ parameterTypes = new Type[1];
+ parameterTypes[0] = DelegateField.FieldType;
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod(
+ "add_" + SrcItfMethod.Name,
+ MethodAttributes.Public | MethodAttributes.Virtual,
+ null,
+ parameterTypes );
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Define a label for the m_IFooEventsCP comparision.
+ Label EventCPNonNullLabel = il.DefineLabel();
+
+ // Declare the local variables.
+ LocalBuilder ltSinkHelper = il.DeclareLocal( SinkHelperClass );
+ LocalBuilder ltCookie = il.DeclareLocal( typeof(Int32) );
+ LocalBuilder ltLockTaken = il.DeclareLocal( typeof(bool) );
+
+ // Generate the following code:
+ // try {
+ il.BeginExceptionBlock();
+
+ // Generate the following code:
+ // Monitor.Enter(this, ref lockTaken);
+ il.Emit(OpCodes.Ldarg, (short)0);
+ il.Emit(OpCodes.Ldloca_S, ltLockTaken);
+ il.Emit(OpCodes.Call, MonitorEnterMethod);
+
+ // Generate the following code:
+ // if ( m_IFooEventsCP != null ) goto EventCPNonNullLabel;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Brtrue, EventCPNonNullLabel );
+
+ // Generate the following code:
+ // InitIFooEvents();
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Call, mbInitSrcItf );
+
+ // Mark this as label to jump to if the CP is not null.
+ il.MarkLabel( EventCPNonNullLabel );
+
+ // Generate the following code:
+ // IFooEvents_SinkHelper SinkHelper = new IFooEvents_SinkHelper;
+ il.Emit( OpCodes.Newobj, SinkHelperCons );
+ il.Emit( OpCodes.Stloc, ltSinkHelper );
+
+ // Generate the following code:
+ // dwCookie = 0;
+ il.Emit( OpCodes.Ldc_I4_0 );
+ il.Emit( OpCodes.Stloc, ltCookie );
+
+ // Generate the following code:
+ // m_IFooEventsCP.Advise( SinkHelper, dwCookie );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Ldloc, ltSinkHelper );
+ il.Emit( OpCodes.Castclass, typeof(Object) );
+ il.Emit( OpCodes.Ldloca, ltCookie );
+ il.Emit( OpCodes.Callvirt, CPAdviseMethod );
+
+ // Generate the following code:
+ // SinkHelper.m_dwCookie = dwCookie;
+ il.Emit( OpCodes.Ldloc, ltSinkHelper );
+ il.Emit( OpCodes.Ldloc, ltCookie );
+ il.Emit( OpCodes.Stfld, CookieField );
+
+ // Generate the following code:
+ // SinkHelper.m_FooDelegate = d;
+ il.Emit( OpCodes.Ldloc, ltSinkHelper );
+ il.Emit( OpCodes.Ldarg, (short)1 );
+ il.Emit( OpCodes.Stfld, DelegateField );
+
+ // Generate the following code:
+ // m_aIFooEventsHelpers.Add( SinkHelper );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelperArray );
+ il.Emit( OpCodes.Ldloc, ltSinkHelper );
+ il.Emit( OpCodes.Castclass, typeof(Object) );
+ il.Emit( OpCodes.Callvirt, ArrayListAddMethod );
+ il.Emit( OpCodes.Pop );
+
+ // Generate the following code:
+ // } finally {
+ il.BeginFinallyBlock();
+
+ // Generate the following code:
+ // if (lockTaken)
+ // Monitor.Exit(this);
+ Label skipExit = il.DefineLabel();
+ il.Emit( OpCodes.Ldloc, ltLockTaken );
+ il.Emit( OpCodes.Brfalse_S, skipExit );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Call, MonitorExitMethod );
+ il.MarkLabel(skipExit);
+
+ // Generate the following code:
+ // }
+ il.EndExceptionBlock();
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+
+ return Meth;
+ }
+
+ private MethodBuilder DefineRemoveEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo SrcItfMethod, Type SinkHelperClass, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP )
+ {
+ Type[] aParamTypes;
+
+ // Find the delegate on the event sink helper.
+ FieldInfo DelegateField = SinkHelperClass.GetField( "m_" + SrcItfMethod.Name + "Delegate" );
+ Contract.Assert(DelegateField != null, "Unable to find the field m_" + SrcItfMethod.Name + "Delegate on the sink helper");
+
+ // Find the cookie on the event sink helper.
+ FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" );
+ Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper");
+
+ // Retrieve the ArrayList.RemoveAt method.
+ aParamTypes = new Type[1];
+ aParamTypes[0] = typeof(Int32);
+ MethodInfo ArrayListRemoveMethod = typeof(ArrayList).GetMethod( "RemoveAt", aParamTypes, null );
+ Contract.Assert(ArrayListRemoveMethod != null, "Unable to find the method ArrayList.RemoveAt()");
+
+ // Retrieve the ArrayList.Item property get method.
+ PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" );
+ Contract.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item");
+ MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod();
+ Contract.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item");
+
+ // Retrieve the ArrayList.Count property get method.
+ PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" );
+ Contract.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count");
+ MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod();
+ Contract.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count");
+
+ // Retrieve the Delegate.Equals() method.
+ aParamTypes[0] = typeof(Delegate);
+ MethodInfo DelegateEqualsMethod = typeof(Delegate).GetMethod( "Equals", aParamTypes, null );
+ Contract.Assert(DelegateEqualsMethod != null, "Unable to find the method Delegate.Equlals()");
+
+ // Retrieve the Monitor.Enter() method.
+ MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod("Enter", MonitorEnterParamTypes, null);
+ Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()");
+
+ // Retrieve the Monitor.Exit() method.
+ aParamTypes[0] = typeof(Object);
+ MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null );
+ Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()");
+
+ // Retrieve the ConnectionPoint.Unadvise() method.
+ MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" );
+ Contract.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()");
+
+ // Retrieve the Marshal.ReleaseComObject() method.
+ MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" );
+ Contract.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()");
+
+ // Define the remove_XXX method.
+ Type[] parameterTypes;
+ parameterTypes = new Type[1];
+ parameterTypes[0] = DelegateField.FieldType;
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod(
+ "remove_" + SrcItfMethod.Name,
+ MethodAttributes.Public | MethodAttributes.Virtual,
+ null,
+ parameterTypes );
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Declare the local variables.
+ LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) );
+ LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) );
+ LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass );
+ LocalBuilder ltLockTaken = il.DeclareLocal(typeof(bool));
+
+ // Generate the labels for the for loop.
+ Label ForBeginLabel = il.DefineLabel();
+ Label ForEndLabel = il.DefineLabel();
+ Label FalseIfLabel = il.DefineLabel();
+ Label MonitorExitLabel = il.DefineLabel();
+
+ // Generate the following code:
+ // try {
+ il.BeginExceptionBlock();
+
+ // Generate the following code:
+ // Monitor.Enter(this, ref lockTaken);
+ il.Emit(OpCodes.Ldarg, (short)0);
+ il.Emit(OpCodes.Ldloca_S, ltLockTaken);
+ il.Emit(OpCodes.Call, MonitorEnterMethod);
+
+ // Generate the following code:
+ // if ( m_aIFooEventsHelpers == null ) goto ForEndLabel;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelperArray );
+ il.Emit( OpCodes.Brfalse, ForEndLabel );
+
+ // Generate the following code:
+ // int NumEventHelpers = m_aIFooEventsHelpers.Count;
+ // int cEventHelpers = 0;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelperArray );
+ il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod );
+ il.Emit( OpCodes.Stloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Stloc, ltSinkHelperCounter );
+
+ // Generate the following code:
+ // if ( 0 >= NumEventHelpers ) goto ForEndLabel;
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Ldloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Bge, ForEndLabel );
+
+ // Mark this as the beginning of the for loop's body.
+ il.MarkLabel( ForBeginLabel );
+
+ // Generate the following code:
+ // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelperArray );
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod );
+ il.Emit( OpCodes.Castclass, SinkHelperClass );
+ il.Emit( OpCodes.Stloc, ltCurrSinkHelper );
+
+ // Generate the following code:
+ // if ( CurrentHelper.m_FooDelegate )
+ il.Emit( OpCodes.Ldloc, ltCurrSinkHelper );
+ il.Emit( OpCodes.Ldfld, DelegateField );
+ il.Emit( OpCodes.Ldnull );
+ il.Emit( OpCodes.Beq, FalseIfLabel );
+
+ // Generate the following code:
+ // if ( CurrentHelper.m_FooDelegate.Equals( d ) )
+ il.Emit( OpCodes.Ldloc, ltCurrSinkHelper );
+ il.Emit( OpCodes.Ldfld, DelegateField );
+ il.Emit( OpCodes.Ldarg, (short)1 );
+ il.Emit( OpCodes.Castclass, typeof(Object) );
+ il.Emit( OpCodes.Callvirt, DelegateEqualsMethod );
+ il.Emit( OpCodes.Ldc_I4, 0xff );
+ il.Emit( OpCodes.And );
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Beq, FalseIfLabel );
+
+ // Generate the following code:
+ // m_aIFooEventsHelpers.RemoveAt( cEventHelpers );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelperArray );
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Callvirt, ArrayListRemoveMethod );
+
+ // Generate the following code:
+ // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Ldloc, ltCurrSinkHelper );
+ il.Emit( OpCodes.Ldfld, CookieField );
+ il.Emit( OpCodes.Callvirt, CPUnadviseMethod );
+
+ // Generate the following code:
+ // if ( NumEventHelpers > 1) break;
+ il.Emit( OpCodes.Ldloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Ldc_I4, 1 );
+ il.Emit( OpCodes.Bgt, ForEndLabel );
+
+ // Generate the following code:
+ // Marshal.ReleaseComObject(m_IFooEventsCP);
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Call, ReleaseComObjectMethod );
+ il.Emit( OpCodes.Pop );
+
+ // Generate the following code:
+ // m_IFooEventsCP = null;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldnull );
+ il.Emit( OpCodes.Stfld, fbEventCP );
+
+ // Generate the following code:
+ // m_aIFooEventsHelpers = null;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldnull );
+ il.Emit( OpCodes.Stfld, fbSinkHelperArray );
+
+ // Generate the following code:
+ // break;
+ il.Emit( OpCodes.Br, ForEndLabel );
+
+ // Mark this as the label to jump to when the if statement is false.
+ il.MarkLabel( FalseIfLabel );
+
+ // Generate the following code:
+ // cEventHelpers++;
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Ldc_I4, 1 );
+ il.Emit( OpCodes.Add );
+ il.Emit( OpCodes.Stloc, ltSinkHelperCounter );
+
+ // Generate the following code:
+ // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel;
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Ldloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Blt, ForBeginLabel );
+
+ // Mark this as the end of the for loop's body.
+ il.MarkLabel( ForEndLabel );
+
+ // Generate the following code:
+ // } finally {
+ il.BeginFinallyBlock();
+
+ // Generate the following code:
+ // if (lockTaken)
+ // Monitor.Exit(this);
+ Label skipExit = il.DefineLabel();
+ il.Emit(OpCodes.Ldloc, ltLockTaken);
+ il.Emit(OpCodes.Brfalse_S, skipExit);
+ il.Emit(OpCodes.Ldarg, (short)0);
+ il.Emit(OpCodes.Call, MonitorExitMethod);
+ il.MarkLabel(skipExit);
+
+ // Generate the following code:
+ // }
+ il.EndExceptionBlock();
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+
+ return Meth;
+ }
+
+ private MethodBuilder DefineInitSrcItfMethod( TypeBuilder OutputTypeBuilder, Type SourceInterface, FieldBuilder fbSinkHelperArray, FieldBuilder fbEventCP, FieldBuilder fbCPC )
+ {
+ // Retrieve the constructor info for the array list's default constructor.
+ ConstructorInfo DefaultArrayListCons = typeof(ArrayList).GetConstructor(EventProviderWriter.DefaultLookup, null, Array.Empty<Type>(), null );
+ Contract.Assert(DefaultArrayListCons != null, "Unable to find the constructor for class ArrayList");
+
+ // Temp byte array for Guid
+ ubyte[] rgByteGuid = new ubyte[16];
+
+ // Retrieve the constructor info for the Guid constructor.
+ Type[] aParamTypes = new Type[1];
+ aParamTypes[0] = typeof(Byte[]);
+ ConstructorInfo ByteArrayGUIDCons = typeof(Guid).GetConstructor(EventProviderWriter.DefaultLookup, null, aParamTypes, null );
+ Contract.Assert(ByteArrayGUIDCons != null, "Unable to find the constructor for GUID that accepts a string as argument");
+
+ // Retrieve the IConnectionPointContainer.FindConnectionPoint() method.
+ MethodInfo CPCFindCPMethod = typeof(IConnectionPointContainer).GetMethod( "FindConnectionPoint" );
+ Contract.Assert(CPCFindCPMethod != null, "Unable to find the method ConnectionPointContainer.FindConnectionPoint()");
+
+ // Define the Init method itself.
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod(
+ "Init",
+ MethodAttributes.Private,
+ null,
+ null );
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Declare the local variables.
+ LocalBuilder ltCP = il.DeclareLocal( typeof(IConnectionPoint) );
+ LocalBuilder ltEvGuid = il.DeclareLocal( typeof(Guid) );
+ LocalBuilder ltByteArrayGuid = il.DeclareLocal( typeof(Byte[]) );
+
+ // Generate the following code:
+ // IConnectionPoint CP = NULL;
+ il.Emit( OpCodes.Ldnull );
+ il.Emit( OpCodes.Stloc, ltCP );
+
+ // Get unsigned byte array for the GUID of the event interface.
+ rgByteGuid = SourceInterface.GUID.ToByteArray();
+
+ // Generate the following code:
+ // ubyte rgByteArray[] = new ubyte [16];
+ il.Emit( OpCodes.Ldc_I4, 0x10 );
+ il.Emit( OpCodes.Newarr, typeof(Byte) );
+ il.Emit( OpCodes.Stloc, ltByteArrayGuid );
+
+ // Generate the following code:
+ // rgByteArray[i] = rgByteGuid[i];
+ for (int i = 0; i < 16; i++ )
+ {
+ il.Emit( OpCodes.Ldloc, ltByteArrayGuid );
+ il.Emit( OpCodes.Ldc_I4, i );
+ il.Emit( OpCodes.Ldc_I4, (int) (rgByteGuid[i]) );
+ il.Emit( OpCodes.Stelem_I1);
+ }
+
+ // Generate the following code:
+ // EventItfGuid = Guid( ubyte b[] );
+ il.Emit( OpCodes.Ldloca, ltEvGuid );
+ il.Emit( OpCodes.Ldloc, ltByteArrayGuid );
+ il.Emit( OpCodes.Call, ByteArrayGUIDCons );
+
+ // Generate the following code:
+ // m_ConnectionPointContainer.FindConnectionPoint( EventItfGuid, CP );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbCPC );
+ il.Emit( OpCodes.Ldloca, ltEvGuid );
+ il.Emit( OpCodes.Ldloca, ltCP );
+ il.Emit( OpCodes.Callvirt, CPCFindCPMethod );
+
+ // Generate the following code:
+ // m_ConnectionPoint = (IConnectionPoint)CP;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldloc, ltCP );
+ il.Emit( OpCodes.Castclass, typeof(IConnectionPoint) );
+ il.Emit( OpCodes.Stfld, fbEventCP );
+
+ // Generate the following code:
+ // m_aEventSinkHelpers = new ArrayList;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Newobj, DefaultArrayListCons );
+ il.Emit( OpCodes.Stfld, fbSinkHelperArray );
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+
+ return Meth;
+ }
+
+ private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCPC )
+ {
+ // Retrieve the constructor info for the base class's constructor.
+ ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Public, null, Array.Empty<Type>(), null );
+ Contract.Assert(DefaultBaseClsCons != null, "Unable to find the object's public default constructor");
+
+ // Define the default constructor.
+ MethodAttributes ctorAttributes = MethodAttributes.SpecialName | (DefaultBaseClsCons.Attributes & MethodAttributes.MemberAccessMask);
+ MethodBuilder Cons = OutputTypeBuilder.DefineMethod(
+ ".ctor",
+ ctorAttributes,
+ null,
+ new Type[]{typeof(Object)} );
+
+ ILGenerator il = Cons.GetILGenerator();
+
+ // Generate the call to the base class constructor.
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Call, DefaultBaseClsCons );
+
+ // Generate the following code:
+ // m_ConnectionPointContainer = (IConnectionPointContainer)EventSource;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldarg, (short)1 );
+ il.Emit( OpCodes.Castclass, typeof(IConnectionPointContainer) );
+ il.Emit( OpCodes.Stfld, fbCPC );
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+ }
+
+ private MethodBuilder DefineFinalizeMethod( TypeBuilder OutputTypeBuilder, Type SinkHelperClass, FieldBuilder fbSinkHelper, FieldBuilder fbEventCP )
+ {
+ // Find the cookie on the event sink helper.
+ FieldInfo CookieField = SinkHelperClass.GetField( "m_dwCookie" );
+ Contract.Assert(CookieField != null, "Unable to find the field m_dwCookie on the sink helper");
+
+ // Retrieve the ArrayList.Item property get method.
+ PropertyInfo ArrayListItemProperty = typeof(ArrayList).GetProperty( "Item" );
+ Contract.Assert(ArrayListItemProperty != null, "Unable to find the property ArrayList.Item");
+ MethodInfo ArrayListItemGetMethod = ArrayListItemProperty.GetGetMethod();
+ Contract.Assert(ArrayListItemGetMethod != null, "Unable to find the get method for property ArrayList.Item");
+
+ // Retrieve the ArrayList.Count property get method.
+ PropertyInfo ArrayListSizeProperty = typeof(ArrayList).GetProperty( "Count" );
+ Contract.Assert(ArrayListSizeProperty != null, "Unable to find the property ArrayList.Count");
+ MethodInfo ArrayListSizeGetMethod = ArrayListSizeProperty.GetGetMethod();
+ Contract.Assert(ArrayListSizeGetMethod != null, "Unable to find the get method for property ArrayList.Count");
+
+ // Retrieve the ConnectionPoint.Unadvise() method.
+ MethodInfo CPUnadviseMethod = typeof(IConnectionPoint).GetMethod( "Unadvise" );
+ Contract.Assert(CPUnadviseMethod != null, "Unable to find the method ConnectionPoint.Unadvise()");
+
+ // Retrieve the Marshal.ReleaseComObject() method.
+ MethodInfo ReleaseComObjectMethod = typeof(Marshal).GetMethod( "ReleaseComObject" );
+ Contract.Assert(ReleaseComObjectMethod != null, "Unable to find the method Marshal.ReleaseComObject()");
+
+ // Retrieve the Monitor.Enter() method.
+ MethodInfo MonitorEnterMethod = typeof(Monitor).GetMethod("Enter", MonitorEnterParamTypes, null);
+ Contract.Assert(MonitorEnterMethod != null, "Unable to find the method Monitor.Enter()");
+
+ // Retrieve the Monitor.Exit() method.
+ Type[] aParamTypes = new Type[1];
+ aParamTypes[0] = typeof(Object);
+ MethodInfo MonitorExitMethod = typeof(Monitor).GetMethod( "Exit", aParamTypes, null );
+ Contract.Assert(MonitorExitMethod != null, "Unable to find the method Monitor.Exit()");
+
+ // Define the Finalize method itself.
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Finalize", MethodAttributes.Public | MethodAttributes.Virtual, null, null );
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Declare the local variables.
+ LocalBuilder ltNumSinkHelpers = il.DeclareLocal( typeof(Int32) );
+ LocalBuilder ltSinkHelperCounter = il.DeclareLocal( typeof(Int32) );
+ LocalBuilder ltCurrSinkHelper = il.DeclareLocal( SinkHelperClass );
+ LocalBuilder ltLockTaken = il.DeclareLocal(typeof(bool));
+
+ // Generate the following code:
+ // try {
+ il.BeginExceptionBlock();
+
+ // Generate the following code:
+ // Monitor.Enter(this, ref lockTaken);
+ il.Emit(OpCodes.Ldarg, (short)0);
+ il.Emit(OpCodes.Ldloca_S, ltLockTaken);
+ il.Emit(OpCodes.Call, MonitorEnterMethod);
+
+ // Generate the labels.
+ Label ForBeginLabel = il.DefineLabel();
+ Label ReleaseComObjectLabel = il.DefineLabel();
+ Label AfterReleaseComObjectLabel = il.DefineLabel();
+
+ // Generate the following code:
+ // if ( m_IFooEventsCP == null ) goto AfterReleaseComObjectLabel;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Brfalse, AfterReleaseComObjectLabel );
+
+ // Generate the following code:
+ // int NumEventHelpers = m_aIFooEventsHelpers.Count;
+ // int cEventHelpers = 0;
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelper );
+ il.Emit( OpCodes.Callvirt, ArrayListSizeGetMethod );
+ il.Emit( OpCodes.Stloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Stloc, ltSinkHelperCounter );
+
+ // Generate the following code:
+ // if ( 0 >= NumEventHelpers ) goto ReleaseComObjectLabel;
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Ldloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Bge, ReleaseComObjectLabel );
+
+ // Mark this as the beginning of the for loop's body.
+ il.MarkLabel( ForBeginLabel );
+
+ // Generate the following code:
+ // CurrentHelper = (IFooEvents_SinkHelper)m_aIFooEventsHelpers.Get( cEventHelpers );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbSinkHelper );
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Callvirt, ArrayListItemGetMethod );
+ il.Emit( OpCodes.Castclass, SinkHelperClass );
+ il.Emit( OpCodes.Stloc, ltCurrSinkHelper );
+
+ // Generate the following code:
+ // m_IFooEventsCP.Unadvise( CurrentHelper.m_dwCookie );
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Ldloc, ltCurrSinkHelper );
+ il.Emit( OpCodes.Ldfld, CookieField );
+ il.Emit( OpCodes.Callvirt, CPUnadviseMethod );
+
+ // Generate the following code:
+ // cEventHelpers++;
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Ldc_I4, 1 );
+ il.Emit( OpCodes.Add );
+ il.Emit( OpCodes.Stloc, ltSinkHelperCounter );
+
+ // Generate the following code:
+ // if ( cEventHelpers < NumEventHelpers ) goto ForBeginLabel;
+ il.Emit( OpCodes.Ldloc, ltSinkHelperCounter );
+ il.Emit( OpCodes.Ldloc, ltNumSinkHelpers );
+ il.Emit( OpCodes.Blt, ForBeginLabel );
+
+ // Mark this as the end of the for loop's body.
+ il.MarkLabel( ReleaseComObjectLabel );
+
+ // Generate the following code:
+ // Marshal.ReleaseComObject(m_IFooEventsCP);
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbEventCP );
+ il.Emit( OpCodes.Call, ReleaseComObjectMethod );
+ il.Emit( OpCodes.Pop );
+
+ // Mark this as the end of the for loop's body.
+ il.MarkLabel( AfterReleaseComObjectLabel );
+
+ // Generate the following code:
+ // } catch {
+ il.BeginCatchBlock(typeof(System.Exception));
+ il.Emit( OpCodes.Pop );
+
+ // Generate the following code:
+ // } finally {
+ il.BeginFinallyBlock();
+
+ // Generate the following code:
+ // if (lockTaken)
+ // Monitor.Exit(this);
+ Label skipExit = il.DefineLabel();
+ il.Emit(OpCodes.Ldloc, ltLockTaken);
+ il.Emit(OpCodes.Brfalse_S, skipExit);
+ il.Emit(OpCodes.Ldarg, (short)0);
+ il.Emit(OpCodes.Call, MonitorExitMethod);
+ il.MarkLabel(skipExit);
+
+ // Generate the following code:
+ // }
+ il.EndExceptionBlock();
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+
+ return Meth;
+ }
+
+ private void DefineDisposeMethod( TypeBuilder OutputTypeBuilder, MethodBuilder FinalizeMethod )
+ {
+ // Retrieve the method info for GC.SuppressFinalize().
+ MethodInfo SuppressFinalizeMethod = typeof(GC).GetMethod("SuppressFinalize");
+ Contract.Assert(SuppressFinalizeMethod != null, "Unable to find the GC.SuppressFinalize");
+
+ // Define the Finalize method itself.
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod( "Dispose", MethodAttributes.Public | MethodAttributes.Virtual, null, null );
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Generate the following code:
+ // Finalize()
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Callvirt, FinalizeMethod );
+
+ // Generate the following code:
+ // GC.SuppressFinalize()
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Call, SuppressFinalizeMethod );
+
+ // Generate the return opcode.
+ il.Emit( OpCodes.Ret );
+ }
+
+ private ModuleBuilder m_OutputModule;
+ private String m_strDestTypeName;
+ private Type m_EventItfType;
+ private Type m_SrcItfType;
+ private Type m_SinkHelperType;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs
new file mode 100644
index 0000000000..0367e79bdd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/EventSinkHelperWriter.cs
@@ -0,0 +1,297 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.TCEAdapterGen {
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Collections;
+ using System.Diagnostics.Contracts;
+ internal class EventSinkHelperWriter
+ {
+ public static readonly String GeneratedTypeNamePostfix = "_SinkHelper";
+
+ public EventSinkHelperWriter( ModuleBuilder OutputModule, Type InputType, Type EventItfType )
+ {
+ m_InputType = InputType;
+ m_OutputModule = OutputModule;
+ m_EventItfType = EventItfType;
+ }
+
+ public Type Perform()
+ {
+ // Create the output Type.
+ Type[] aInterfaces = new Type[1];
+ aInterfaces[0] = m_InputType;
+ String strFullName = null;
+ String strNameSpace = NameSpaceExtractor.ExtractNameSpace( m_EventItfType.FullName );
+
+ if (strNameSpace != "")
+ strFullName = strNameSpace + ".";
+
+ strFullName += m_InputType.Name + GeneratedTypeNamePostfix;
+ TypeBuilder OutputTypeBuilder = TCEAdapterGenerator.DefineUniqueType(
+ strFullName,
+ TypeAttributes.Sealed | TypeAttributes.Public,
+ null,
+ aInterfaces,
+ m_OutputModule
+ );
+ // Hide the _SinkProvider interface
+ TCEAdapterGenerator.SetHiddenAttribute(OutputTypeBuilder);
+
+ // Set the class interface to none.
+ TCEAdapterGenerator.SetClassInterfaceTypeToNone(OutputTypeBuilder);
+
+ // Retrieve the property methods on the input interface and give them a dummy implementation.
+ MethodInfo[] pMethods = TCEAdapterGenerator.GetPropertyMethods(m_InputType);
+ foreach (MethodInfo method in pMethods)
+ {
+ DefineBlankMethod(OutputTypeBuilder, method);
+ }
+
+ // Retrieve the non-property methods on the input interface.
+ MethodInfo[] aMethods = TCEAdapterGenerator.GetNonPropertyMethods(m_InputType);
+
+ // Allocate an array to contain the delegate fields.
+ FieldBuilder[] afbDelegates = new FieldBuilder[aMethods.Length];
+ // Process all the methods on the input interface.
+ for ( int cMethods = 0; cMethods < aMethods.Length; cMethods++ )
+ {
+ if ( m_InputType == aMethods[cMethods].DeclaringType )
+ {
+ // Retrieve the delegate type from the add_XXX method.
+ MethodInfo AddMeth = m_EventItfType.GetMethod( "add_" + aMethods[cMethods].Name );
+ ParameterInfo[] aParams = AddMeth.GetParameters();
+ Contract.Assert(aParams.Length == 1, "All event interface methods must take a single delegate derived type and have a void return type");
+ Type DelegateCls = aParams[0].ParameterType;
+
+ // Define the delegate instance field.
+ afbDelegates[cMethods] = OutputTypeBuilder.DefineField(
+ "m_" + aMethods[cMethods].Name + "Delegate",
+ DelegateCls,
+ FieldAttributes.Public
+ );
+
+ // Define the event method itself.
+ DefineEventMethod( OutputTypeBuilder, aMethods[cMethods], DelegateCls, afbDelegates[cMethods] );
+ }
+ }
+
+ // Create the cookie field.
+ FieldBuilder fbCookie = OutputTypeBuilder.DefineField(
+ "m_dwCookie",
+ typeof(Int32),
+ FieldAttributes.Public
+ );
+
+ // Define the constructor.
+ DefineConstructor( OutputTypeBuilder, fbCookie, afbDelegates );
+
+ return OutputTypeBuilder.CreateType();
+ }
+
+ private void DefineBlankMethod(TypeBuilder OutputTypeBuilder, MethodInfo Method)
+ {
+ ParameterInfo[] PIs = Method.GetParameters();
+ Type[] parameters = new Type[PIs.Length];
+ for (int i=0; i < PIs.Length; i++)
+ {
+ parameters[i] = PIs[i].ParameterType;
+ }
+
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod(Method.Name,
+ Method.Attributes & ~MethodAttributes.Abstract,
+ Method.CallingConvention,
+ Method.ReturnType,
+ parameters);
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ AddReturn(Method.ReturnType, il, Meth);
+
+ il.Emit(OpCodes.Ret);
+ }
+
+ private void DefineEventMethod( TypeBuilder OutputTypeBuilder, MethodInfo Method, Type DelegateCls, FieldBuilder fbDelegate )
+ {
+ // Retrieve the method info for the invoke method on the delegate.
+ MethodInfo DelegateInvokeMethod = DelegateCls.GetMethod( "Invoke" );
+ Contract.Assert(DelegateInvokeMethod != null, "Unable to find method Delegate.Invoke()");
+
+ // Retrieve the return type.
+ Type ReturnType = Method.ReturnType;
+
+ // Define the actual event method.
+ ParameterInfo[] paramInfos = Method.GetParameters();
+ Type[] parameterTypes;
+ if (paramInfos != null)
+ {
+ parameterTypes = new Type[paramInfos.Length];
+ for (int i = 0; i < paramInfos.Length; i++)
+ {
+ parameterTypes[i] = paramInfos[i].ParameterType;
+ }
+ }
+ else
+ parameterTypes = null;
+
+ MethodAttributes attr = MethodAttributes.Public | MethodAttributes.Virtual;
+ MethodBuilder Meth = OutputTypeBuilder.DefineMethod( Method.Name,
+ attr,
+ CallingConventions.Standard,
+ ReturnType,
+ parameterTypes);
+
+ // We explicitly do not specify parameter name and attributes since this Type
+ // is not meant to be exposed to the user. It is only used internally to do the
+ // connection point to TCE mapping.
+
+ ILGenerator il = Meth.GetILGenerator();
+
+ // Create the exit branch.
+ Label ExitLabel = il.DefineLabel();
+
+ // Generate the code that verifies that the delegate is not null.
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbDelegate );
+ il.Emit( OpCodes.Brfalse, ExitLabel );
+
+ // The delegate is not NULL so we need to invoke it.
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldfld, fbDelegate );
+
+ // Generate the code to load the arguments before we call invoke.
+ ParameterInfo[] aParams = Method.GetParameters();
+ for ( int cParams = 0; cParams < aParams.Length; cParams++ )
+ {
+ il.Emit( OpCodes.Ldarg, (short)(cParams + 1) );
+ }
+
+ // Generate a tail call to invoke. This will cause the callvirt to return
+ // directly to the caller of the current method instead of actually coming
+ // back to the current method and returning. This will cause the value returned
+ // from the call to the COM server to be returned to the caller of this method.
+
+ il.Emit( OpCodes.Callvirt, DelegateInvokeMethod );
+ il.Emit( OpCodes.Ret );
+
+ // This is the label that will be jumped to if no delegate is present.
+ il.MarkLabel( ExitLabel );
+
+ AddReturn(ReturnType, il, Meth);
+
+ il.Emit( OpCodes.Ret );
+
+ }
+
+ private void AddReturn(Type ReturnType, ILGenerator il, MethodBuilder Meth)
+ {
+ // Place a dummy return value on the stack before we return.
+ if ( ReturnType == typeof(void) )
+ {
+ // There is nothing to place on the stack.
+ }
+ else if ( ReturnType.IsPrimitive )
+ {
+ switch (System.Type.GetTypeCode(ReturnType))
+ {
+ case TypeCode.Boolean:
+ case TypeCode.Char:
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.Int16:
+ case TypeCode.UInt16:
+ case TypeCode.Int32:
+ case TypeCode.UInt32:
+ il.Emit( OpCodes.Ldc_I4_0 );
+ break;
+
+ case TypeCode.Int64:
+ case TypeCode.UInt64:
+ il.Emit( OpCodes.Ldc_I4_0 );
+ il.Emit( OpCodes.Conv_I8 );
+ break;
+
+ case TypeCode.Single:
+ il.Emit( OpCodes.Ldc_R4, 0 );
+ break;
+
+ case TypeCode.Double:
+ il.Emit( OpCodes.Ldc_R4, 0 );
+ il.Emit( OpCodes.Conv_R8 );
+ break;
+
+ default:
+ // "TypeCode" does not include IntPtr, so special case it.
+ if ( ReturnType == typeof(IntPtr) )
+ il.Emit( OpCodes.Ldc_I4_0 );
+ else
+ Contract.Assert(false, "Unexpected type for Primitive type.");
+ break;
+ }
+ }
+ else if ( ReturnType.IsValueType )
+ {
+ // Allocate stack space for the return value type. Zero-init.
+ Meth.InitLocals = true;
+ LocalBuilder ltRetVal = il.DeclareLocal( ReturnType );
+
+ // Load the value class on the stack.
+ il.Emit( OpCodes.Ldloc_S, ltRetVal );
+
+ }
+ else
+ {
+ // The return type is a normal type.
+ il.Emit( OpCodes.Ldnull );
+ }
+ }
+
+ private void DefineConstructor( TypeBuilder OutputTypeBuilder, FieldBuilder fbCookie, FieldBuilder[] afbDelegates )
+ {
+ // Retrieve the constructor info for the base classe's constructor.
+ ConstructorInfo DefaultBaseClsCons = typeof(Object).GetConstructor(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, Array.Empty<Type>(), null );
+ Contract.Assert(DefaultBaseClsCons != null, "Unable to find the constructor for class " + m_InputType.Name);
+
+ // Define the default constructor.
+ MethodBuilder Cons = OutputTypeBuilder.DefineMethod( ".ctor",
+ MethodAttributes.Assembly | MethodAttributes.SpecialName,
+ CallingConventions.Standard,
+ null,
+ null);
+
+ ILGenerator il = Cons.GetILGenerator();
+
+ // Generate the code to call the constructor of the base class.
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Call, DefaultBaseClsCons );
+
+ // Generate the code to set the cookie field to 0.
+ il.Emit( OpCodes.Ldarg, (short)0 );
+ il.Emit( OpCodes.Ldc_I4, 0 );
+ il.Emit( OpCodes.Stfld, fbCookie );
+
+ // Generate the code to set all the delegates to NULL.
+ for ( int cDelegates = 0; cDelegates < afbDelegates.Length; cDelegates++ )
+ {
+ if (afbDelegates[cDelegates] != null)
+ {
+ il.Emit( OpCodes.Ldarg,(short)0 );
+ il.Emit( OpCodes.Ldnull );
+ il.Emit( OpCodes.Stfld, afbDelegates[cDelegates] );
+ }
+ }
+
+ // Emit the return opcode.
+ il.Emit( OpCodes.Ret );
+
+ }
+
+ private Type m_InputType;
+ private Type m_EventItfType;
+ private ModuleBuilder m_OutputModule;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs
new file mode 100644
index 0000000000..8018ad4c66
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/NameSpaceExtractor.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.TCEAdapterGen {
+
+ using System;
+ internal static class NameSpaceExtractor
+ {
+ private static char NameSpaceSeperator = '.';
+
+ public static String ExtractNameSpace(String FullyQualifiedTypeName)
+ {
+ int TypeNameStartPos = FullyQualifiedTypeName.LastIndexOf(NameSpaceSeperator);
+ if (TypeNameStartPos == -1)
+ return "";
+ else
+ return FullyQualifiedTypeName.Substring(0, TypeNameStartPos);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs
new file mode 100644
index 0000000000..c6e4415246
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TCEAdapterGen/TCEAdapterGenerator.cs
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices.TCEAdapterGen {
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Collections;
+ using System.Threading;
+
+ internal class TCEAdapterGenerator
+ {
+ public void Process(ModuleBuilder ModBldr, ArrayList EventItfList)
+ {
+ // Store the input/output module.
+ m_Module = ModBldr;
+
+ // Generate the TCE adapters for all the event sources.
+ int NumEvItfs = EventItfList.Count;
+ for ( int cEventItfs = 0; cEventItfs < NumEvItfs; cEventItfs++ )
+ {
+ // Retrieve the event interface info.
+ EventItfInfo CurrEventItf = (EventItfInfo)EventItfList[cEventItfs];
+
+ // Retrieve the information from the event interface info.
+ Type EventItfType = CurrEventItf.GetEventItfType();
+ Type SrcItfType = CurrEventItf.GetSrcItfType();
+ String EventProviderName = CurrEventItf.GetEventProviderName();
+
+ // Generate the sink interface helper.
+ Type SinkHelperType = new EventSinkHelperWriter( m_Module, SrcItfType, EventItfType ).Perform();
+
+ // Generate the event provider.
+ new EventProviderWriter( m_Module, EventProviderName, EventItfType, SrcItfType, SinkHelperType ).Perform();
+ }
+ }
+
+ internal static void SetClassInterfaceTypeToNone(TypeBuilder tb)
+ {
+ // Create the ClassInterface(ClassInterfaceType.None) CA builder if we haven't created it yet.
+ if (s_NoClassItfCABuilder == null)
+ {
+ Type []aConsParams = new Type[1];
+ aConsParams[0] = typeof(ClassInterfaceType);
+ ConstructorInfo Cons = typeof(ClassInterfaceAttribute).GetConstructor(aConsParams);
+
+ Object[] aArgs = new Object[1];
+ aArgs[0] = ClassInterfaceType.None;
+ s_NoClassItfCABuilder = new CustomAttributeBuilder(Cons, aArgs);
+ }
+
+ // Set the class interface type to none.
+ tb.SetCustomAttribute(s_NoClassItfCABuilder);
+ }
+
+ internal static TypeBuilder DefineUniqueType(String strInitFullName, TypeAttributes attrs, Type BaseType, Type[] aInterfaceTypes, ModuleBuilder mb)
+ {
+ String strFullName = strInitFullName;
+ int PostFix = 2;
+
+ // Find the first unique name for the type.
+ for (; mb.GetType(strFullName) != null; strFullName = strInitFullName + "_" + PostFix, PostFix++);
+
+ // Define a type with the determined unique name.
+ return mb.DefineType(strFullName, attrs, BaseType, aInterfaceTypes);
+ }
+
+ internal static void SetHiddenAttribute(TypeBuilder tb)
+ {
+ if (s_HiddenCABuilder == null)
+ {
+ // Hide the type from Object Browsers
+ Type []aConsParams = new Type[1];
+ aConsParams[0] = typeof(TypeLibTypeFlags);
+ ConstructorInfo Cons = typeof(TypeLibTypeAttribute).GetConstructor(aConsParams);
+
+ Object []aArgs = new Object[1];
+ aArgs[0] = TypeLibTypeFlags.FHidden;
+ s_HiddenCABuilder = new CustomAttributeBuilder(Cons, aArgs);
+ }
+
+ tb.SetCustomAttribute(s_HiddenCABuilder);
+ }
+
+ internal static MethodInfo[] GetNonPropertyMethods(Type type)
+ {
+ MethodInfo[] aMethods = type.GetMethods();
+ ArrayList methods = new ArrayList(aMethods);
+
+ PropertyInfo[] props = type.GetProperties();
+
+ foreach(PropertyInfo prop in props)
+ {
+ MethodInfo[] accessors = prop.GetAccessors();
+ foreach (MethodInfo accessor in accessors)
+ {
+ for (int i=0; i < methods.Count; i++)
+ {
+ if ((MethodInfo)methods[i] == accessor)
+ methods.RemoveAt(i);
+ }
+ }
+ }
+
+ MethodInfo[] retMethods = new MethodInfo[methods.Count];
+ methods.CopyTo(retMethods);
+
+ return retMethods;
+ }
+
+ internal static MethodInfo[] GetPropertyMethods(Type type)
+ {
+ MethodInfo[] aMethods = type.GetMethods();
+ ArrayList methods = new ArrayList();
+
+ PropertyInfo[] props = type.GetProperties();
+
+ foreach(PropertyInfo prop in props)
+ {
+ MethodInfo[] accessors = prop.GetAccessors();
+ foreach (MethodInfo accessor in accessors)
+ {
+ methods.Add(accessor);
+ }
+ }
+
+ MethodInfo[] retMethods = new MethodInfo[methods.Count];
+ methods.CopyTo(retMethods);
+
+ return retMethods;
+ }
+
+
+ private ModuleBuilder m_Module = null;
+ private Hashtable m_SrcItfToSrcItfInfoMap = new Hashtable();
+ private static volatile CustomAttributeBuilder s_NoClassItfCABuilder = null;
+ private static volatile CustomAttributeBuilder s_HiddenCABuilder = null;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs b/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs
new file mode 100644
index 0000000000..e6b148a0a5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/TypeLibConverter.cs
@@ -0,0 +1,595 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Component that implements the ITypeLibConverter interface and
+** does the actual work of converting a typelib to metadata and
+** vice versa.
+**
+**
+=============================================================================*/
+#if !FEATURE_CORECLR // current implementation requires reflection only load
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Runtime.InteropServices.TCEAdapterGen;
+ using System.IO;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Configuration.Assemblies;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Globalization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices.ComTypes;
+ using System.Runtime.Versioning;
+ using WORD = System.UInt16;
+ using DWORD = System.UInt32;
+ using _TYPELIBATTR = System.Runtime.InteropServices.ComTypes.TYPELIBATTR;
+
+ [Guid("F1C3BF79-C3E4-11d3-88E7-00902754C43A")]
+ [ClassInterface(ClassInterfaceType.None)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeLibConverter : ITypeLibConverter
+ {
+ private const String s_strTypeLibAssemblyTitlePrefix = "TypeLib ";
+ private const String s_strTypeLibAssemblyDescPrefix = "Assembly generated from typelib ";
+ private const int MAX_NAMESPACE_LENGTH = 1024;
+
+
+ //
+ // ITypeLibConverter interface.
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+ public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib,
+ String asmFileName,
+ int flags,
+ ITypeLibImporterNotifySink notifySink,
+ byte[] publicKey,
+ StrongNameKeyPair keyPair,
+ bool unsafeInterfaces)
+ {
+ return ConvertTypeLibToAssembly(typeLib,
+ asmFileName,
+ (unsafeInterfaces
+ ? TypeLibImporterFlags.UnsafeInterfaces
+ : 0),
+ notifySink,
+ publicKey,
+ keyPair,
+ null,
+ null);
+ }
+
+
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+ public AssemblyBuilder ConvertTypeLibToAssembly([MarshalAs(UnmanagedType.Interface)] Object typeLib,
+ String asmFileName,
+ TypeLibImporterFlags flags,
+ ITypeLibImporterNotifySink notifySink,
+ byte[] publicKey,
+ StrongNameKeyPair keyPair,
+ String asmNamespace,
+ Version asmVersion)
+ {
+ // Validate the arguments.
+ if (typeLib == null)
+ throw new ArgumentNullException("typeLib");
+ if (asmFileName == null)
+ throw new ArgumentNullException("asmFileName");
+ if (notifySink == null)
+ throw new ArgumentNullException("notifySink");
+ if (String.Empty.Equals(asmFileName))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileName"), "asmFileName");
+ if (asmFileName.Length > Path.MaxPath)
+ throw new ArgumentException(Environment.GetResourceString("IO.PathTooLong"), asmFileName);
+ if ((flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0 && publicKey == null && keyPair == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed"));
+ Contract.EndContractBlock();
+
+ ArrayList eventItfInfoList = null;
+
+ // Determine the AssemblyNameFlags
+ AssemblyNameFlags asmNameFlags = AssemblyNameFlags.None;
+
+ // Retrieve the assembly name from the typelib.
+ AssemblyName asmName = GetAssemblyNameFromTypelib(typeLib, asmFileName, publicKey, keyPair, asmVersion, asmNameFlags);
+
+ // Create the dynamic assembly that will contain the converted typelib types.
+ AssemblyBuilder asmBldr = CreateAssemblyForTypeLib(typeLib, asmFileName, asmName,
+ (flags & TypeLibImporterFlags.PrimaryInteropAssembly) != 0,
+ (flags & TypeLibImporterFlags.ReflectionOnlyLoading) != 0,
+ (flags & TypeLibImporterFlags.NoDefineVersionResource) != 0);
+
+ // Define a dynamic module that will contain the contain the imported types.
+ String strNonQualifiedAsmFileName = Path.GetFileName(asmFileName);
+ ModuleBuilder modBldr = asmBldr.DefineDynamicModule(strNonQualifiedAsmFileName, strNonQualifiedAsmFileName);
+
+ // If the namespace hasn't been specified, then use the assembly name.
+ if (asmNamespace == null)
+ asmNamespace = asmName.Name;
+
+ // Create a type resolve handler that will also intercept resolve ref messages
+ // on the sink interface to build up a list of referenced assemblies.
+ TypeResolveHandler typeResolveHandler = new TypeResolveHandler(modBldr, notifySink);
+
+ // Add a listener for the type resolve events.
+ AppDomain currentDomain = Thread.GetDomain();
+ ResolveEventHandler resolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveEvent);
+ ResolveEventHandler asmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveAsmEvent);
+ ResolveEventHandler ROAsmResolveHandler = new ResolveEventHandler(typeResolveHandler.ResolveROAsmEvent);
+ currentDomain.TypeResolve += resolveHandler;
+ currentDomain.AssemblyResolve += asmResolveHandler;
+ currentDomain.ReflectionOnlyAssemblyResolve += ROAsmResolveHandler;
+
+ // Convert the types contained in the typelib into metadata and add them to the assembly.
+ nConvertTypeLibToMetadata(typeLib, asmBldr.InternalAssembly, modBldr.InternalModule, asmNamespace, flags, typeResolveHandler, out eventItfInfoList);
+
+ // Update the COM types in the assembly.
+ UpdateComTypesInAssembly(asmBldr, modBldr);
+
+ // If there are any event sources then generate the TCE adapters.
+ if (eventItfInfoList.Count > 0)
+ new TCEAdapterGenerator().Process(modBldr, eventItfInfoList);
+
+ // Remove the listener for the type resolve events.
+ currentDomain.TypeResolve -= resolveHandler;
+ currentDomain.AssemblyResolve -= asmResolveHandler;
+ currentDomain.ReflectionOnlyAssemblyResolve -= ROAsmResolveHandler;
+
+ // We have finished converting the typelib and now have a fully formed assembly.
+ return asmBldr;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+ [return : MarshalAs(UnmanagedType.Interface)]
+ public Object ConvertAssemblyToTypeLib(Assembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink)
+ {
+ RuntimeAssembly rtAssembly;
+ AssemblyBuilder ab = assembly as AssemblyBuilder;
+ if (ab != null)
+ rtAssembly = ab.InternalAssembly;
+ else
+ rtAssembly = assembly as RuntimeAssembly;
+
+ return nConvertAssemblyToTypeLib(rtAssembly, strTypeLibName, flags, notifySink);
+ }
+
+ public bool GetPrimaryInteropAssembly(Guid g, Int32 major, Int32 minor, Int32 lcid, out String asmName, out String asmCodeBase)
+ {
+ String strTlbId = "{" + g.ToString().ToUpper(CultureInfo.InvariantCulture) + "}";
+ String strVersion = major.ToString("x", CultureInfo.InvariantCulture) + "." + minor.ToString("x", CultureInfo.InvariantCulture);
+
+ // Set the two out values to null before we start.
+ asmName = null;
+ asmCodeBase = null;
+
+ // Try to open the HKEY_CLASS_ROOT\TypeLib key.
+ using (RegistryKey TypeLibKey = Registry.ClassesRoot.OpenSubKey("TypeLib", false))
+ {
+ if (TypeLibKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID> key.
+ using (RegistryKey TypeLibSubKey = TypeLibKey.OpenSubKey(strTlbId))
+ {
+ if (TypeLibSubKey != null)
+ {
+ // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID>\<Major.Minor> key.
+ using (RegistryKey VersionKey = TypeLibSubKey.OpenSubKey(strVersion, false))
+ {
+ if (VersionKey != null)
+ {
+ // Attempt to retrieve the assembly name and codebase under the version key.
+ asmName = (String)VersionKey.GetValue("PrimaryInteropAssemblyName");
+ asmCodeBase = (String)VersionKey.GetValue("PrimaryInteropAssemblyCodeBase");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // If the assembly name isn't null, then we found an PIA.
+ return asmName != null;
+ }
+
+
+ //
+ // Non native helper methods.
+ //
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private static AssemblyBuilder CreateAssemblyForTypeLib(Object typeLib, String asmFileName, AssemblyName asmName, bool bPrimaryInteropAssembly, bool bReflectionOnly, bool bNoDefineVersionResource)
+ {
+ // Retrieve the current app domain.
+ AppDomain currentDomain = Thread.GetDomain();
+
+ // Retrieve the directory from the assembly file name.
+ String dir = null;
+ if (asmFileName != null)
+ {
+ dir = Path.GetDirectoryName(asmFileName);
+ if (String.IsNullOrEmpty(dir))
+ dir = null;
+ }
+
+ AssemblyBuilderAccess aba;
+ if (bReflectionOnly)
+ {
+ aba = AssemblyBuilderAccess.ReflectionOnly;
+ }
+ else
+ {
+ aba = AssemblyBuilderAccess.RunAndSave;
+ }
+
+ // Create the dynamic assembly itself.
+ AssemblyBuilder asmBldr;
+
+ List<CustomAttributeBuilder> assemblyAttributes = new List<CustomAttributeBuilder>();
+#if !FEATURE_CORECLR
+ // mscorlib.dll must specify the security rules that assemblies it emits are to use, since by
+ // default all assemblies will follow security rule set level 2, and we want to make that an
+ // explicit decision.
+ ConstructorInfo securityRulesCtor = typeof(SecurityRulesAttribute).GetConstructor(new Type[] { typeof(SecurityRuleSet) });
+ CustomAttributeBuilder securityRulesAttribute =
+ new CustomAttributeBuilder(securityRulesCtor, new object[] { SecurityRuleSet.Level2 });
+ assemblyAttributes.Add(securityRulesAttribute);
+#endif // !FEATURE_CORECLR
+
+ asmBldr = currentDomain.DefineDynamicAssembly(asmName, aba, dir, false, assemblyAttributes);
+
+ // Set the Guid custom attribute on the assembly.
+ SetGuidAttributeOnAssembly(asmBldr, typeLib);
+
+ // Set the imported from COM attribute on the assembly and return it.
+ SetImportedFromTypeLibAttrOnAssembly(asmBldr, typeLib);
+
+ // Set the version information on the typelib.
+ if (bNoDefineVersionResource)
+ {
+ SetTypeLibVersionAttribute(asmBldr, typeLib);
+ }
+ else
+ {
+ SetVersionInformation(asmBldr, typeLib, asmName);
+ }
+
+ // If we are generating a PIA, then set the PIA custom attribute.
+ if (bPrimaryInteropAssembly)
+ SetPIAAttributeOnAssembly(asmBldr, typeLib);
+
+ return asmBldr;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static AssemblyName GetAssemblyNameFromTypelib(Object typeLib, String asmFileName, byte[] publicKey, StrongNameKeyPair keyPair, Version asmVersion, AssemblyNameFlags asmNameFlags)
+ {
+ // Extract the name of the typelib.
+ String strTypeLibName = null;
+ String strDocString = null;
+ int dwHelpContext = 0;
+ String strHelpFile = null;
+ ITypeLib pTLB = (ITypeLib)typeLib;
+ pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
+
+ // Retrieve the name to use for the assembly.
+ if (asmFileName == null)
+ {
+ asmFileName = strTypeLibName;
+ }
+ else
+ {
+ Contract.Assert((asmFileName != null) && (asmFileName.Length > 0), "The assembly file name cannot be an empty string!");
+
+ String strFileNameNoPath = Path.GetFileName(asmFileName);
+ String strExtension = Path.GetExtension(asmFileName);
+
+ // Validate that the extension is valid.
+ bool bExtensionValid = ".dll".Equals(strExtension, StringComparison.OrdinalIgnoreCase);
+
+ // If the extension is not valid then tell the user and quit.
+ if (!bExtensionValid)
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidFileExtension"));
+
+ // The assembly cannot contain the path nor the extension.
+ asmFileName = strFileNameNoPath.Substring(0, strFileNameNoPath.Length - ".dll".Length);
+ }
+
+ // If the version information was not specified, then retrieve it from the typelib.
+ if (asmVersion == null)
+ {
+ int major;
+ int minor;
+ Marshal.GetTypeLibVersion(pTLB, out major, out minor);
+ asmVersion = new Version(major, minor, 0, 0);
+ }
+
+ // Create the assembly name for the imported typelib's assembly.
+ AssemblyName AsmName = new AssemblyName();
+ AsmName.Init(
+ asmFileName,
+ publicKey,
+ null,
+ asmVersion,
+ null,
+ AssemblyHashAlgorithm.None,
+ AssemblyVersionCompatibility.SameMachine,
+ null,
+ asmNameFlags,
+ keyPair);
+
+ return AsmName;
+ }
+
+ private static void UpdateComTypesInAssembly(AssemblyBuilder asmBldr, ModuleBuilder modBldr)
+ {
+ // Retrieve the AssemblyBuilderData associated with the assembly builder.
+ AssemblyBuilderData AsmBldrData = asmBldr.m_assemblyData;
+
+ // Go through the types in the module and add them as public COM types.
+ Type[] aTypes = modBldr.GetTypes();
+ int NumTypes = aTypes.Length;
+ for (int cTypes = 0; cTypes < NumTypes; cTypes++)
+ AsmBldrData.AddPublicComType(aTypes[cTypes]);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetGuidAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib)
+ {
+ // Retrieve the GuidAttribute constructor.
+ Type []aConsParams = new Type[1] {typeof(String)};
+ ConstructorInfo GuidAttrCons = typeof(GuidAttribute).GetConstructor(aConsParams);
+
+ // Create an instance of the custom attribute builder.
+ Object[] aArgs = new Object[1] {Marshal.GetTypeLibGuid((ITypeLib)typeLib).ToString()};
+ CustomAttributeBuilder GuidCABuilder = new CustomAttributeBuilder(GuidAttrCons, aArgs);
+
+ // Set the GuidAttribute on the assembly builder.
+ asmBldr.SetCustomAttribute(GuidCABuilder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetImportedFromTypeLibAttrOnAssembly(AssemblyBuilder asmBldr, Object typeLib)
+ {
+ // Retrieve the ImportedFromTypeLibAttribute constructor.
+ Type []aConsParams = new Type[1] {typeof(String)};
+ ConstructorInfo ImpFromComAttrCons = typeof(ImportedFromTypeLibAttribute).GetConstructor(aConsParams);
+
+ // Retrieve the name of the typelib.
+ String strTypeLibName = Marshal.GetTypeLibName((ITypeLib)typeLib);
+
+ // Create an instance of the custom attribute builder.
+ Object[] aArgs = new Object[1] {strTypeLibName};
+ CustomAttributeBuilder ImpFromComCABuilder = new CustomAttributeBuilder(ImpFromComAttrCons, aArgs);
+
+ // Set the ImportedFromTypeLibAttribute on the assembly builder.
+ asmBldr.SetCustomAttribute(ImpFromComCABuilder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetTypeLibVersionAttribute(AssemblyBuilder asmBldr, Object typeLib)
+ {
+ Type []aConsParams = new Type[2] {typeof(int), typeof(int)};
+ ConstructorInfo TypeLibVerCons = typeof(TypeLibVersionAttribute).GetConstructor(aConsParams);
+
+ // Get the typelib version
+ int major;
+ int minor;
+ Marshal.GetTypeLibVersion((ITypeLib)typeLib, out major, out minor);
+
+ // Create an instance of the custom attribute builder.
+ Object[] aArgs = new Object[2] {major, minor};
+ CustomAttributeBuilder TypeLibVerBuilder = new CustomAttributeBuilder(TypeLibVerCons, aArgs);
+
+ // Set the attribute on the assembly builder.
+ asmBldr.SetCustomAttribute(TypeLibVerBuilder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetVersionInformation(AssemblyBuilder asmBldr, Object typeLib, AssemblyName asmName)
+ {
+ // Extract the name of the typelib.
+ String strTypeLibName = null;
+ String strDocString = null;
+ int dwHelpContext = 0;
+ String strHelpFile = null;
+ ITypeLib pTLB = (ITypeLib)typeLib;
+ pTLB.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
+
+ // Generate the product name string from the named of the typelib.
+ String strProductName = String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("TypeLibConverter_ImportedTypeLibProductName"), strTypeLibName);
+
+ // Set the OS version information.
+ asmBldr.DefineVersionInfoResource(strProductName, asmName.Version.ToString(), null, null, null);
+
+ // Set the TypeLibVersion attribute
+ SetTypeLibVersionAttribute(asmBldr, typeLib);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetPIAAttributeOnAssembly(AssemblyBuilder asmBldr, Object typeLib)
+ {
+ IntPtr pAttr = IntPtr.Zero;
+ _TYPELIBATTR Attr;
+ ITypeLib pTLB = (ITypeLib)typeLib;
+ int Major = 0;
+ int Minor = 0;
+
+ // Retrieve the PrimaryInteropAssemblyAttribute constructor.
+ Type []aConsParams = new Type[2] {typeof(int), typeof(int)};
+ ConstructorInfo PIAAttrCons = typeof(PrimaryInteropAssemblyAttribute).GetConstructor(aConsParams);
+
+ // Retrieve the major and minor version from the typelib.
+ try
+ {
+ pTLB.GetLibAttr(out pAttr);
+ Attr = (_TYPELIBATTR)Marshal.PtrToStructure(pAttr, typeof(_TYPELIBATTR));
+ Major = Attr.wMajorVerNum;
+ Minor = Attr.wMinorVerNum;
+ }
+ finally
+ {
+ // Release the typelib attributes.
+ if (pAttr != IntPtr.Zero)
+ pTLB.ReleaseTLibAttr(pAttr);
+ }
+
+ // Create an instance of the custom attribute builder.
+ Object[] aArgs = new Object[2] {Major, Minor};
+ CustomAttributeBuilder PIACABuilder = new CustomAttributeBuilder(PIAAttrCons, aArgs);
+
+ // Set the PrimaryInteropAssemblyAttribute on the assembly builder.
+ asmBldr.SetCustomAttribute(PIACABuilder);
+ }
+
+
+ //
+ // Native helper methods.
+ //
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void nConvertTypeLibToMetadata(Object typeLib, RuntimeAssembly asmBldr, RuntimeModule modBldr, String nameSpace, TypeLibImporterFlags flags, ITypeLibImporterNotifySink notifySink, out ArrayList eventItfInfoList);
+
+ // Must use assembly versioning or GuidAttribute to avoid collisions in typelib export or registration.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object nConvertAssemblyToTypeLib(RuntimeAssembly assembly, String strTypeLibName, TypeLibExporterFlags flags, ITypeLibExporterNotifySink notifySink);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal extern static void LoadInMemoryTypeByName(RuntimeModule module, String className);
+
+ //
+ // Helper class called when a resolve type event is fired.
+ //
+
+ private class TypeResolveHandler : ITypeLibImporterNotifySink
+ {
+ public TypeResolveHandler(ModuleBuilder mod, ITypeLibImporterNotifySink userSink)
+ {
+ m_Module = mod;
+ m_UserSink = userSink;
+ }
+
+ public void ReportEvent(ImporterEventKind eventKind, int eventCode, String eventMsg)
+ {
+ m_UserSink.ReportEvent(eventKind, eventCode, eventMsg);
+ }
+
+ public Assembly ResolveRef(Object typeLib)
+ {
+ Contract.Ensures(Contract.Result<Assembly>() != null && Contract.Result<Assembly>() is RuntimeAssembly);
+ Contract.EndContractBlock();
+
+ // Call the user sink to resolve the reference.
+ Assembly asm = m_UserSink.ResolveRef(typeLib);
+
+ if (asm == null)
+ throw new ArgumentNullException();
+
+ // Return the resolved assembly. We extract the internal assembly because we are called
+ // by the VM which accesses fields of the object directly and does not go via those
+ // delegating properties (the fields are empty if asm is an (external) AssemblyBuilder).
+
+ RuntimeAssembly rtAssembly = asm as RuntimeAssembly;
+ if (rtAssembly == null)
+ {
+ AssemblyBuilder ab = asm as AssemblyBuilder;
+ if (ab != null)
+ rtAssembly = ab.InternalAssembly;
+ }
+
+ if (rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"));
+
+ // Add the assembly to the list of assemblies.
+ m_AsmList.Add(rtAssembly);
+
+ return rtAssembly;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Assembly ResolveEvent(Object sender, ResolveEventArgs args)
+ {
+ // We need to load the type in the resolve event so that we will deal with
+ // cases where we are trying to load the CoClass before the interface has
+ // been loaded.
+ try
+ {
+ LoadInMemoryTypeByName(m_Module.GetNativeHandle(), args.Name);
+ return m_Module.Assembly;
+ }
+ catch (TypeLoadException e)
+ {
+ if (e.ResourceId != System.__HResults.COR_E_TYPELOAD) // type not found
+ throw;
+ }
+
+ foreach (RuntimeAssembly asm in m_AsmList)
+ {
+ try
+ {
+ asm.GetType(args.Name, true, false);
+ return asm;
+ }
+ catch (TypeLoadException e)
+ {
+ if (e._HResult != System.__HResults.COR_E_TYPELOAD) // type not found
+ throw;
+ }
+ }
+
+ return null;
+ }
+
+ public Assembly ResolveAsmEvent(Object sender, ResolveEventArgs args)
+ {
+ foreach (RuntimeAssembly asm in m_AsmList)
+ {
+ if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0)
+ return asm;
+ }
+
+ return null;
+ }
+
+ public Assembly ResolveROAsmEvent(Object sender, ResolveEventArgs args)
+ {
+ foreach (RuntimeAssembly asm in m_AsmList)
+ {
+ if (String.Compare(asm.FullName, args.Name, StringComparison.OrdinalIgnoreCase) == 0)
+ return asm;
+ }
+
+ // We failed to find the referenced assembly in our pre-loaded assemblies, so try to load it based on policy.
+ string asmName = AppDomain.CurrentDomain.ApplyPolicy(args.Name);
+ return Assembly.ReflectionOnlyLoad(asmName);
+ }
+
+ private ModuleBuilder m_Module;
+ private ITypeLibImporterNotifySink m_UserSink;
+ private List<RuntimeAssembly> m_AsmList = new List<RuntimeAssembly>();
+ }
+ }
+}
+#endif // !FEATURE_CORECLR // current implementation requires reflection only load
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs
new file mode 100644
index 0000000000..8c6e1bcd64
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIBindCtx.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIBindCtx interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.BIND_OPTS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct BIND_OPTS
+ {
+ public int cbStruct;
+ public int grfFlags;
+ public int grfMode;
+ public int dwTickCountDeadline;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IBindCtx instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("0000000e-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIBindCtx
+ {
+ void RegisterObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
+ void RevokeObjectBound([MarshalAs(UnmanagedType.Interface)] Object punk);
+ void ReleaseBoundObjects();
+ void SetBindOptions([In()] ref BIND_OPTS pbindopts);
+ void GetBindOptions(ref BIND_OPTS pbindopts);
+ void GetRunningObjectTable(out UCOMIRunningObjectTable pprot);
+ void RegisterObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] Object punk);
+ void GetObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey, [MarshalAs(UnmanagedType.Interface)] out Object ppunk);
+ void EnumObjectParam(out UCOMIEnumString ppenum);
+ void RevokeObjectParam([MarshalAs(UnmanagedType.LPWStr)] String pszKey);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs
new file mode 100644
index 0000000000..b12e1f7a8c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPoint.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIConnectionPoint interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IConnectionPoint instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("B196B286-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIConnectionPoint
+ {
+ void GetConnectionInterface(out Guid pIID);
+ void GetConnectionPointContainer(out UCOMIConnectionPointContainer ppCPC);
+ void Advise([MarshalAs(UnmanagedType.Interface)] Object pUnkSink, out int pdwCookie);
+ void Unadvise(int dwCookie);
+ void EnumConnections(out UCOMIEnumConnections ppEnum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs
new file mode 100644
index 0000000000..212d643e03
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIConnectionPointContainer.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIConnectionPointContainer interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IConnectionPointContainer instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("B196B284-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIConnectionPointContainer
+ {
+ void EnumConnectionPoints(out UCOMIEnumConnectionPoints ppEnum);
+ void FindConnectionPoint(ref Guid riid, out UCOMIConnectionPoint ppCP);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs
new file mode 100644
index 0000000000..5180018088
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnectionPoints.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIEnumConnectionPoints interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("B196B285-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIEnumConnectionPoints
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] UCOMIConnectionPoint[] rgelt, out int pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ [PreserveSig]
+ int Reset();
+ void Clone(out UCOMIEnumConnectionPoints ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs
new file mode 100644
index 0000000000..87273b34f7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumConnections.cs
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIEnumConnections interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.CONNECTDATA instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct CONNECTDATA
+ {
+ [MarshalAs(UnmanagedType.Interface)]
+ public Object pUnk;
+ public int dwCookie;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumConnections instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("B196B287-BAB4-101A-B69C-00AA00341D07")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIEnumConnections
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] CONNECTDATA[] rgelt, out int pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ [PreserveSig]
+ void Reset();
+ void Clone(out UCOMIEnumConnections ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs
new file mode 100644
index 0000000000..40787fcd5c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumMoniker.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIEnumMoniker interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using DWORD = System.UInt32;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumMoniker instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00000102-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIEnumMoniker
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0), Out] UCOMIMoniker[] rgelt, out int pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ [PreserveSig]
+ int Reset();
+ void Clone(out UCOMIEnumMoniker ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs
new file mode 100644
index 0000000000..9d0552a0df
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumString.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIEnumString interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumString instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00000101-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIEnumString
+ {
+ [PreserveSig]
+ int Next(int celt, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 0), Out] String[] rgelt, out int pceltFetched);
+ [PreserveSig]
+ int Skip(int celt);
+ [PreserveSig]
+ int Reset();
+ void Clone(out UCOMIEnumString ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs
new file mode 100644
index 0000000000..0d8585ffdb
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumVARIANT.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIEnumVARIANT interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumVARIANT instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00020404-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIEnumVARIANT
+ {
+ [PreserveSig]
+ int Next(int celt, int rgvar, int pceltFetched);
+
+ [PreserveSig]
+ int Skip(int celt);
+
+ [PreserveSig]
+ int Reset();
+
+ void Clone(int ppenum);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs
new file mode 100644
index 0000000000..81e0133923
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerable.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: UCOMIEnumerable
+**
+**
+** Purpose:
+** This interface is redefined here since the original IEnumerable interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IEnumerable interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using System.Collections;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumerable instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
+ internal interface UCOMIEnumerable
+ {
+ [DispId(-4)]
+ IEnumerator GetEnumerator();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs
new file mode 100644
index 0000000000..af886c46ac
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIEnumerator.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: UCOMIEnumerator
+**
+**
+** Purpose:
+** This interface is redefined here since the original IEnumerator interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IEnumerator interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IEnumerator instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
+ internal interface UCOMIEnumerator
+ {
+ bool MoveNext();
+ Object Current {
+ get;
+ }
+ void Reset();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs
new file mode 100644
index 0000000000..2f85c14bc6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIExpando.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: UCOMIExpando
+**
+**
+** Purpose:
+** This interface is redefined here since the original IExpando interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IExpando interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices
+{
+
+ using System;
+ using System.Reflection;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IExpando instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("AFBF15E6-C37C-11d2-B88E-00A0C9B471B8")]
+ internal interface UCOMIExpando : UCOMIReflect
+ {
+ FieldInfo AddField(String name);
+ PropertyInfo AddProperty(String name);
+ MethodInfo AddMethod(String name, Delegate method);
+ void RemoveMember(MemberInfo m);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs
new file mode 100644
index 0000000000..bd5b6f4916
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIMoniker.cs
@@ -0,0 +1,60 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIMoniker interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.FILETIME instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential)]
+
+ public struct FILETIME
+ {
+ public int dwLowDateTime;
+ public int dwHighDateTime;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IMoniker instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("0000000f-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIMoniker
+ {
+ // IPersist portion
+ void GetClassID(out Guid pClassID);
+
+ // IPersistStream portion
+ [PreserveSig]
+ int IsDirty();
+ void Load(UCOMIStream pStm);
+ void Save(UCOMIStream pStm, [MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
+ void GetSizeMax(out Int64 pcbSize);
+
+ // IMoniker portion
+ void BindToObject(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, [In()] ref Guid riidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
+ void BindToStorage(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, [In()] ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out Object ppvObj);
+ void Reduce(UCOMIBindCtx pbc, int dwReduceHowFar, ref UCOMIMoniker ppmkToLeft, out UCOMIMoniker ppmkReduced);
+ void ComposeWith(UCOMIMoniker pmkRight, [MarshalAs(UnmanagedType.Bool)] bool fOnlyIfNotGeneric, out UCOMIMoniker ppmkComposite);
+ void Enum([MarshalAs(UnmanagedType.Bool)] bool fForward, out UCOMIEnumMoniker ppenumMoniker);
+ void IsEqual(UCOMIMoniker pmkOtherMoniker);
+ void Hash(out int pdwHash);
+ void IsRunning(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, UCOMIMoniker pmkNewlyRunning);
+ void GetTimeOfLastChange(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, out FILETIME pFileTime);
+ void Inverse(out UCOMIMoniker ppmk);
+ void CommonPrefixWith(UCOMIMoniker pmkOther, out UCOMIMoniker ppmkPrefix);
+ void RelativePathTo(UCOMIMoniker pmkOther, out UCOMIMoniker ppmkRelPath);
+ void GetDisplayName(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] out String ppszDisplayName);
+ void ParseDisplayName(UCOMIBindCtx pbc, UCOMIMoniker pmkToLeft, [MarshalAs(UnmanagedType.LPWStr)] String pszDisplayName, out int pchEaten, out UCOMIMoniker ppmkOut);
+ void IsSystemMoniker(out int pdwMksys);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs
new file mode 100644
index 0000000000..ac465e771f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIPersistFile.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIPersistFile interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+ using DWORD = System.UInt32;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IPersistFile instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("0000010b-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIPersistFile
+ {
+ // IPersist portion
+ void GetClassID(out Guid pClassID);
+
+ // IPersistFile portion
+ [PreserveSig]
+ int IsDirty();
+ void Load([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, int dwMode);
+ void Save([MarshalAs(UnmanagedType.LPWStr)] String pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fRemember);
+ void SaveCompleted([MarshalAs(UnmanagedType.LPWStr)] String pszFileName);
+ void GetCurFile([MarshalAs(UnmanagedType.LPWStr)] out String ppszFileName);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs
new file mode 100644
index 0000000000..d6cdd6828e
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIReflect.cs
@@ -0,0 +1,79 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*==========================================================================
+**
+** Interface: UCOMIReflect
+**
+**
+** Purpose:
+** This interface is redefined here since the original IReflect interface
+** has all its methods marked as ecall's since it is a managed standard
+** interface. This interface is used from within the runtime to make a call
+** on the COM server directly when it implements the IReflect interface.
+**
+**
+==========================================================================*/
+namespace System.Runtime.InteropServices
+{
+ using System;
+ using System.Reflection;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IReflect instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("AFBF15E5-C37C-11d2-B88E-00A0C9B471B8")]
+ internal interface UCOMIReflect
+ {
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr,Binder binder,
+ Type[] types,ParameterModifier[] modifiers);
+
+ MethodInfo GetMethod(String name,BindingFlags bindingAttr);
+
+ MethodInfo[] GetMethods(
+ BindingFlags bindingAttr);
+
+ FieldInfo GetField(
+ String name,
+ BindingFlags bindingAttr);
+
+ FieldInfo[] GetFields(
+ BindingFlags bindingAttr);
+
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr);
+
+ PropertyInfo GetProperty(
+ String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type returnType,
+ Type[] types,
+ ParameterModifier[] modifiers);
+
+ PropertyInfo[] GetProperties(
+ BindingFlags bindingAttr);
+
+ MemberInfo[] GetMember(
+ String name,
+ BindingFlags bindingAttr);
+
+ MemberInfo[] GetMembers(
+ BindingFlags bindingAttr);
+
+ Object InvokeMember(
+ String name,
+ BindingFlags invokeAttr,
+ Binder binder,
+ Object target,
+ Object[] args,
+ ParameterModifier[] modifiers,
+ CultureInfo culture,
+ String[] namedParameters);
+
+ Type UnderlyingSystemType {
+ get;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs
new file mode 100644
index 0000000000..8088c0417f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIRunningObjectTable.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIRunningObjectTable interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IRunningObjectTable instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00000010-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIRunningObjectTable
+ {
+ void Register(int grfFlags, [MarshalAs(UnmanagedType.Interface)] Object punkObject, UCOMIMoniker pmkObjectName, out int pdwRegister);
+ void Revoke(int dwRegister);
+ void IsRunning(UCOMIMoniker pmkObjectName);
+ void GetObject(UCOMIMoniker pmkObjectName, [MarshalAs(UnmanagedType.Interface)] out Object ppunkObject);
+ void NoteChangeTime(int dwRegister, ref FILETIME pfiletime);
+ void GetTimeOfLastChange(UCOMIMoniker pmkObjectName, out FILETIME pfiletime);
+ void EnumRunning(out UCOMIEnumMoniker ppenumMoniker);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs
new file mode 100644
index 0000000000..dc2cb53d97
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMIStream.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMIStream interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.STATSTG instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+
+ public struct STATSTG
+ {
+ public String pwcsName;
+ public int type;
+ public Int64 cbSize;
+ public FILETIME mtime;
+ public FILETIME ctime;
+ public FILETIME atime;
+ public int grfMode;
+ public int grfLocksSupported;
+ public Guid clsid;
+ public int grfStateBits;
+ public int reserved;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IStream instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("0000000c-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMIStream
+ {
+ // ISequentialStream portion
+ void Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] Byte[] pv, int cb,IntPtr pcbRead);
+ void Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] Byte[] pv, int cb, IntPtr pcbWritten);
+
+ // IStream portion
+ void Seek(Int64 dlibMove, int dwOrigin, IntPtr plibNewPosition);
+ void SetSize(Int64 libNewSize);
+ void CopyTo(UCOMIStream pstm, Int64 cb, IntPtr pcbRead, IntPtr pcbWritten);
+ void Commit(int grfCommitFlags);
+ void Revert();
+ void LockRegion(Int64 libOffset, Int64 cb, int dwLockType);
+ void UnlockRegion(Int64 libOffset, Int64 cb, int dwLockType);
+ void Stat(out STATSTG pstatstg, int grfStatFlag);
+ void Clone(out UCOMIStream ppstm);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs
new file mode 100644
index 0000000000..0ef1e549a5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeComp.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMITypeComp interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.DESCKIND instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum DESCKIND
+ {
+ DESCKIND_NONE = 0,
+ DESCKIND_FUNCDESC = DESCKIND_NONE + 1,
+ DESCKIND_VARDESC = DESCKIND_FUNCDESC + 1,
+ DESCKIND_TYPECOMP = DESCKIND_VARDESC + 1,
+ DESCKIND_IMPLICITAPPOBJ = DESCKIND_TYPECOMP + 1,
+ DESCKIND_MAX = DESCKIND_IMPLICITAPPOBJ + 1
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.BINDPTR instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+
+ public struct BINDPTR
+ {
+ [FieldOffset(0)]
+ public IntPtr lpfuncdesc;
+ [FieldOffset(0)]
+ public IntPtr lpvardesc;
+ [FieldOffset(0)]
+ public IntPtr lptcomp;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.ITypeComp instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00020403-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMITypeComp
+ {
+ void Bind([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, Int16 wFlags, out UCOMITypeInfo ppTInfo, out DESCKIND pDescKind, out BINDPTR pBindPtr);
+ void BindType([MarshalAs(UnmanagedType.LPWStr)] String szName, int lHashVal, out UCOMITypeInfo ppTInfo, out UCOMITypeComp ppTComp);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs
new file mode 100644
index 0000000000..e26964f5a3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeInfo.cs
@@ -0,0 +1,330 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMITypeInfo interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.TYPEKIND instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum TYPEKIND
+ {
+ TKIND_ENUM = 0,
+ TKIND_RECORD = TKIND_ENUM + 1,
+ TKIND_MODULE = TKIND_RECORD + 1,
+ TKIND_INTERFACE = TKIND_MODULE + 1,
+ TKIND_DISPATCH = TKIND_INTERFACE + 1,
+ TKIND_COCLASS = TKIND_DISPATCH + 1,
+ TKIND_ALIAS = TKIND_COCLASS + 1,
+ TKIND_UNION = TKIND_ALIAS + 1,
+ TKIND_MAX = TKIND_UNION + 1
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.TYPEFLAGS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum TYPEFLAGS : short
+ {
+ TYPEFLAG_FAPPOBJECT = 0x1,
+ TYPEFLAG_FCANCREATE = 0x2,
+ TYPEFLAG_FLICENSED = 0x4,
+ TYPEFLAG_FPREDECLID = 0x8,
+ TYPEFLAG_FHIDDEN = 0x10,
+ TYPEFLAG_FCONTROL = 0x20,
+ TYPEFLAG_FDUAL = 0x40,
+ TYPEFLAG_FNONEXTENSIBLE = 0x80,
+ TYPEFLAG_FOLEAUTOMATION = 0x100,
+ TYPEFLAG_FRESTRICTED = 0x200,
+ TYPEFLAG_FAGGREGATABLE = 0x400,
+ TYPEFLAG_FREPLACEABLE = 0x800,
+ TYPEFLAG_FDISPATCHABLE = 0x1000,
+ TYPEFLAG_FREVERSEBIND = 0x2000,
+ TYPEFLAG_FPROXY = 0x4000
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum IMPLTYPEFLAGS
+ {
+ IMPLTYPEFLAG_FDEFAULT = 0x1,
+ IMPLTYPEFLAG_FSOURCE = 0x2,
+ IMPLTYPEFLAG_FRESTRICTED = 0x4,
+ IMPLTYPEFLAG_FDEFAULTVTABLE = 0x8,
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.TYPEATTR instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct TYPEATTR
+ {
+ // Constant used with the memid fields.
+ public const int MEMBER_ID_NIL = unchecked((int)0xFFFFFFFF);
+
+ // Actual fields of the TypeAttr struct.
+ public Guid guid;
+ public Int32 lcid;
+ public Int32 dwReserved;
+ public Int32 memidConstructor;
+ public Int32 memidDestructor;
+ public IntPtr lpstrSchema;
+ public Int32 cbSizeInstance;
+ public TYPEKIND typekind;
+ public Int16 cFuncs;
+ public Int16 cVars;
+ public Int16 cImplTypes;
+ public Int16 cbSizeVft;
+ public Int16 cbAlignment;
+ public TYPEFLAGS wTypeFlags;
+ public Int16 wMajorVerNum;
+ public Int16 wMinorVerNum;
+ public TYPEDESC tdescAlias;
+ public IDLDESC idldescType;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.FUNCDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FUNCDESC
+ {
+ public int memid; //MEMBERID memid;
+ public IntPtr lprgscode; // /* [size_is(cScodes)] */ SCODE RPC_FAR *lprgscode;
+ public IntPtr lprgelemdescParam; // /* [size_is(cParams)] */ ELEMDESC __RPC_FAR *lprgelemdescParam;
+ public FUNCKIND funckind; //FUNCKIND funckind;
+ public INVOKEKIND invkind; //INVOKEKIND invkind;
+ public CALLCONV callconv; //CALLCONV callconv;
+ public Int16 cParams; //short cParams;
+ public Int16 cParamsOpt; //short cParamsOpt;
+ public Int16 oVft; //short oVft;
+ public Int16 cScodes; //short cScodes;
+ public ELEMDESC elemdescFunc; //ELEMDESC elemdescFunc;
+ public Int16 wFuncFlags; //WORD wFuncFlags;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IDLFLAG instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum IDLFLAG : short
+ {
+ IDLFLAG_NONE = PARAMFLAG.PARAMFLAG_NONE,
+ IDLFLAG_FIN = PARAMFLAG.PARAMFLAG_FIN,
+ IDLFLAG_FOUT = PARAMFLAG.PARAMFLAG_FOUT,
+ IDLFLAG_FLCID = PARAMFLAG.PARAMFLAG_FLCID,
+ IDLFLAG_FRETVAL = PARAMFLAG.PARAMFLAG_FRETVAL
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.IDLDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct IDLDESC
+ {
+ public int dwReserved;
+ public IDLFLAG wIDLFlags;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.PARAMFLAG instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum PARAMFLAG :short
+ {
+ PARAMFLAG_NONE = 0,
+ PARAMFLAG_FIN = 0x1,
+ PARAMFLAG_FOUT = 0x2,
+ PARAMFLAG_FLCID = 0x4,
+ PARAMFLAG_FRETVAL = 0x8,
+ PARAMFLAG_FOPT = 0x10,
+ PARAMFLAG_FHASDEFAULT = 0x20,
+ PARAMFLAG_FHASCUSTDATA = 0x40
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.PARAMDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct PARAMDESC
+ {
+ public IntPtr lpVarValue;
+ public PARAMFLAG wParamFlags;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.TYPEDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct TYPEDESC
+ {
+ public IntPtr lpValue;
+ public Int16 vt;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.ELEMDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct ELEMDESC
+ {
+ public TYPEDESC tdesc;
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+ [ComVisible(false)]
+ public struct DESCUNION
+ {
+ [FieldOffset(0)]
+ public IDLDESC idldesc;
+ [FieldOffset(0)]
+ public PARAMDESC paramdesc;
+ };
+ public DESCUNION desc;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.VARDESC instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct VARDESC
+ {
+ public int memid;
+ public String lpstrSchema;
+
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Explicit, CharSet=CharSet.Unicode)]
+ [ComVisible(false)]
+ public struct DESCUNION
+ {
+ [FieldOffset(0)]
+ public int oInst;
+ [FieldOffset(0)]
+ public IntPtr lpvarValue;
+ };
+
+ public ELEMDESC elemdescVar;
+ public short wVarFlags;
+ public VarEnum varkind;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.DISPPARAMS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct DISPPARAMS
+ {
+ public IntPtr rgvarg;
+ public IntPtr rgdispidNamedArgs;
+ public int cArgs;
+ public int cNamedArgs;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.EXCEPINFO instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ public struct EXCEPINFO
+ {
+ public Int16 wCode;
+ public Int16 wReserved;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrSource;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrDescription;
+ [MarshalAs(UnmanagedType.BStr)] public String bstrHelpFile;
+ public int dwHelpContext;
+ public IntPtr pvReserved;
+ public IntPtr pfnDeferredFillIn;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.FUNCKIND instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum FUNCKIND : int
+ {
+ FUNC_VIRTUAL = 0,
+ FUNC_PUREVIRTUAL = 1,
+ FUNC_NONVIRTUAL = 2,
+ FUNC_STATIC = 3,
+ FUNC_DISPATCH = 4
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.INVOKEKIND instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum INVOKEKIND : int
+ {
+ INVOKE_FUNC = 0x1,
+ INVOKE_PROPERTYGET = 0x2,
+ INVOKE_PROPERTYPUT = 0x4,
+ INVOKE_PROPERTYPUTREF = 0x8
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.CALLCONV instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum CALLCONV : int
+ {
+ CC_CDECL =1,
+ CC_MSCPASCAL=2,
+ CC_PASCAL =CC_MSCPASCAL,
+ CC_MACPASCAL=3,
+ CC_STDCALL =4,
+ CC_RESERVED =5,
+ CC_SYSCALL =6,
+ CC_MPWCDECL =7,
+ CC_MPWPASCAL=8,
+ CC_MAX =9
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.FUNCFLAGS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum FUNCFLAGS : short
+ {
+ FUNCFLAG_FRESTRICTED= 0x1,
+ FUNCFLAG_FSOURCE = 0x2,
+ FUNCFLAG_FBINDABLE = 0x4,
+ FUNCFLAG_FREQUESTEDIT = 0x8,
+ FUNCFLAG_FDISPLAYBIND = 0x10,
+ FUNCFLAG_FDEFAULTBIND = 0x20,
+ FUNCFLAG_FHIDDEN = 0x40,
+ FUNCFLAG_FUSESGETLASTERROR= 0x80,
+ FUNCFLAG_FDEFAULTCOLLELEM= 0x100,
+ FUNCFLAG_FUIDEFAULT = 0x200,
+ FUNCFLAG_FNONBROWSABLE = 0x400,
+ FUNCFLAG_FREPLACEABLE = 0x800,
+ FUNCFLAG_FIMMEDIATEBIND = 0x1000
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.VARFLAGS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum VARFLAGS : short
+ {
+ VARFLAG_FREADONLY =0x1,
+ VARFLAG_FSOURCE =0x2,
+ VARFLAG_FBINDABLE =0x4,
+ VARFLAG_FREQUESTEDIT =0x8,
+ VARFLAG_FDISPLAYBIND =0x10,
+ VARFLAG_FDEFAULTBIND =0x20,
+ VARFLAG_FHIDDEN =0x40,
+ VARFLAG_FRESTRICTED =0x80,
+ VARFLAG_FDEFAULTCOLLELEM =0x100,
+ VARFLAG_FUIDEFAULT =0x200,
+ VARFLAG_FNONBROWSABLE =0x400,
+ VARFLAG_FREPLACEABLE =0x800,
+ VARFLAG_FIMMEDIATEBIND =0x1000
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.ITypeInfo instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00020401-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMITypeInfo
+ {
+ void GetTypeAttr(out IntPtr ppTypeAttr);
+ void GetTypeComp(out UCOMITypeComp ppTComp);
+ void GetFuncDesc(int index, out IntPtr ppFuncDesc);
+ void GetVarDesc(int index, out IntPtr ppVarDesc);
+ void GetNames(int memid, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), Out] String[] rgBstrNames, int cMaxNames, out int pcNames);
+ void GetRefTypeOfImplType(int index, out int href);
+ void GetImplTypeFlags(int index, out int pImplTypeFlags);
+ void GetIDsOfNames([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1), In] String[] rgszNames, int cNames, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[] pMemId);
+ void Invoke([MarshalAs(UnmanagedType.IUnknown)] Object pvInstance, int memid, Int16 wFlags, ref DISPPARAMS pDispParams, out Object pVarResult, out EXCEPINFO pExcepInfo, out int puArgErr);
+ void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ void GetDllEntry(int memid, INVOKEKIND invKind, out String pBstrDllName, out String pBstrName, out Int16 pwOrdinal);
+ void GetRefTypeInfo(int hRef, out UCOMITypeInfo ppTI);
+ void AddressOfMember(int memid, INVOKEKIND invKind, out IntPtr ppv);
+ void CreateInstance([MarshalAs(UnmanagedType.IUnknown)] Object pUnkOuter, ref Guid riid, [MarshalAs(UnmanagedType.IUnknown), Out] out Object ppvObj);
+ void GetMops(int memid, out String pBstrMops);
+ void GetContainingTypeLib(out UCOMITypeLib ppTLB, out int pIndex);
+ void ReleaseTypeAttr(IntPtr pTypeAttr);
+ void ReleaseFuncDesc(IntPtr pFuncDesc);
+ void ReleaseVarDesc(IntPtr pVarDesc);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs
new file mode 100644
index 0000000000..c8b63deff6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UCOMITypeLib.cs
@@ -0,0 +1,71 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: UCOMITypeLib interface definition.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices
+{
+ using System;
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.SYSKIND instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Serializable]
+ public enum SYSKIND
+ {
+ SYS_WIN16 = 0,
+ SYS_WIN32 = SYS_WIN16 + 1,
+ SYS_MAC = SYS_WIN32 + 1
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.LIBFLAGS instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+[Serializable]
+[Flags()]
+ public enum LIBFLAGS : short
+ {
+ LIBFLAG_FRESTRICTED = 0x1,
+ LIBFLAG_FCONTROL = 0x2,
+ LIBFLAG_FHIDDEN = 0x4,
+ LIBFLAG_FHASDISKIMAGE = 0x8
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.TYPELIBATTR instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
+ [Serializable]
+ public struct TYPELIBATTR
+ {
+ public Guid guid;
+ public int lcid;
+ public SYSKIND syskind;
+ public Int16 wMajorVerNum;
+ public Int16 wMinorVerNum;
+ public LIBFLAGS wLibFlags;
+ }
+
+ [Obsolete("Use System.Runtime.InteropServices.ComTypes.ITypeLib instead. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [Guid("00020402-0000-0000-C000-000000000046")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [ComImport]
+ public interface UCOMITypeLib
+ {
+ [PreserveSig]
+ int GetTypeInfoCount();
+ void GetTypeInfo(int index, out UCOMITypeInfo ppTI);
+ void GetTypeInfoType(int index, out TYPEKIND pTKind);
+ void GetTypeInfoOfGuid(ref Guid guid, out UCOMITypeInfo ppTInfo);
+ void GetLibAttr(out IntPtr ppTLibAttr);
+ void GetTypeComp(out UCOMITypeComp ppTComp);
+ void GetDocumentation(int index, out String strName, out String strDocString, out int dwHelpContext, out String strHelpFile);
+ [return : MarshalAs(UnmanagedType.Bool)]
+ bool IsName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal);
+ void FindName([MarshalAs(UnmanagedType.LPWStr)] String szNameBuf, int lHashVal, [MarshalAs(UnmanagedType.LPArray), Out] UCOMITypeInfo[] ppTInfo, [MarshalAs(UnmanagedType.LPArray), Out] int[] rgMemId, ref Int16 pcFound);
+ [PreserveSig]
+ void ReleaseTLibAttr(IntPtr pTLibAttr);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs
new file mode 100644
index 0000000000..69ef2dcc06
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/UnknownWrapper.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_UNKNOWN.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class UnknownWrapper
+ {
+ public UnknownWrapper(Object obj)
+ {
+ m_WrappedObject = obj;
+ }
+
+ public Object WrappedObject
+ {
+ get
+ {
+ return m_WrappedObject;
+ }
+ }
+
+ private Object m_WrappedObject;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs b/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs
new file mode 100644
index 0000000000..9be1588ac0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/Variant.cs
@@ -0,0 +1,659 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Runtime.InteropServices {
+ using System.Diagnostics;
+
+ /// <summary>
+ /// Variant is the basic COM type for late-binding. It can contain any other COM data type.
+ /// This type definition precisely matches the unmanaged data layout so that the struct can be passed
+ /// to and from COM calls.
+ /// </summary>
+ [StructLayout(LayoutKind.Explicit)]
+ [System.Security.SecurityCritical]
+ internal struct Variant {
+
+#if DEBUG
+ static Variant() {
+ // Variant size is the size of 4 pointers (16 bytes) on a 32-bit processor,
+ // and 3 pointers (24 bytes) on a 64-bit processor.
+ int variantSize = Marshal.SizeOf(typeof(Variant));
+ if (IntPtr.Size == 4) {
+ BCLDebug.Assert(variantSize == (4 * IntPtr.Size), "variant");
+ } else {
+ BCLDebug.Assert(IntPtr.Size == 8, "variant");
+ BCLDebug.Assert(variantSize == (3 * IntPtr.Size), "variant");
+ }
+ }
+#endif
+
+ // Most of the data types in the Variant are carried in _typeUnion
+ [FieldOffset(0)] private TypeUnion _typeUnion;
+
+ // Decimal is the largest data type and it needs to use the space that is normally unused in TypeUnion._wReserved1, etc.
+ // Hence, it is declared to completely overlap with TypeUnion. A Decimal does not use the first two bytes, and so
+ // TypeUnion._vt can still be used to encode the type.
+ [FieldOffset(0)] private Decimal _decimal;
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct TypeUnion {
+ internal ushort _vt;
+ internal ushort _wReserved1;
+ internal ushort _wReserved2;
+ internal ushort _wReserved3;
+
+ internal UnionTypes _unionTypes;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct Record {
+ private IntPtr _record;
+ private IntPtr _recordInfo;
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+ [StructLayout(LayoutKind.Explicit)]
+ private struct UnionTypes {
+ #region Generated Variant union types
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_UnionTypes from: generate_comdispatch.py
+
+ [FieldOffset(0)] internal SByte _i1;
+ [FieldOffset(0)] internal Int16 _i2;
+ [FieldOffset(0)] internal Int32 _i4;
+ [FieldOffset(0)] internal Int64 _i8;
+ [FieldOffset(0)] internal Byte _ui1;
+ [FieldOffset(0)] internal UInt16 _ui2;
+ [FieldOffset(0)] internal UInt32 _ui4;
+ [FieldOffset(0)] internal UInt64 _ui8;
+ [FieldOffset(0)] internal Int32 _int;
+ [FieldOffset(0)] internal UInt32 _uint;
+ [FieldOffset(0)] internal Int16 _bool;
+ [FieldOffset(0)] internal Int32 _error;
+ [FieldOffset(0)] internal Single _r4;
+ [FieldOffset(0)] internal Double _r8;
+ [FieldOffset(0)] internal Int64 _cy;
+ [FieldOffset(0)] internal double _date;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _bstr;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _unknown;
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
+ [FieldOffset(0)] internal IntPtr _dispatch;
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ [FieldOffset(0)] internal IntPtr _pvarVal;
+ [FieldOffset(0)] internal IntPtr _byref;
+ [FieldOffset(0)] internal Record _record;
+ }
+
+ /// <summary>
+ /// Primitive types are the basic COM types. It includes valuetypes like ints, but also reference types
+ /// like BStrs. It does not include composite types like arrays and user-defined COM types (IUnknown/IDispatch).
+ /// </summary>
+ internal static bool IsPrimitiveType(VarEnum varEnum) {
+ switch(varEnum) {
+ #region Generated Variant IsPrimitiveType
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_IsPrimitiveType from: generate_comdispatch.py
+
+ case VarEnum.VT_I1:
+ case VarEnum.VT_I2:
+ case VarEnum.VT_I4:
+ case VarEnum.VT_I8:
+ case VarEnum.VT_UI1:
+ case VarEnum.VT_UI2:
+ case VarEnum.VT_UI4:
+ case VarEnum.VT_UI8:
+ case VarEnum.VT_INT:
+ case VarEnum.VT_UINT:
+ case VarEnum.VT_BOOL:
+ case VarEnum.VT_R4:
+ case VarEnum.VT_R8:
+ case VarEnum.VT_DECIMAL:
+ case VarEnum.VT_DATE:
+ case VarEnum.VT_BSTR:
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+ return true;
+ }
+
+ return false;
+ }
+
+ unsafe public void CopyFromIndirect(object value) {
+
+ VarEnum vt = (VarEnum)(((int)this.VariantType) & ~((int)VarEnum.VT_BYREF));
+
+ if (value == null) {
+ if (vt == VarEnum.VT_DISPATCH || vt == VarEnum.VT_UNKNOWN || vt == VarEnum.VT_BSTR) {
+ *(IntPtr*)this._typeUnion._unionTypes._byref = IntPtr.Zero;
+ }
+ return;
+ }
+
+ switch (vt) {
+ case VarEnum.VT_I1:
+ *(sbyte*)this._typeUnion._unionTypes._byref = (sbyte)value;
+ break;
+
+ case VarEnum.VT_UI1:
+ *(byte*)this._typeUnion._unionTypes._byref = (byte)value;
+ break;
+
+ case VarEnum.VT_I2:
+ *(short*)this._typeUnion._unionTypes._byref = (short)value;
+ break;
+
+ case VarEnum.VT_UI2:
+ *(ushort*)this._typeUnion._unionTypes._byref = (ushort)value;
+ break;
+
+ case VarEnum.VT_BOOL:
+ *(short*)this._typeUnion._unionTypes._byref = (bool)value ? (short)-1 : (short)0;
+ break;
+
+ case VarEnum.VT_I4:
+ case VarEnum.VT_INT:
+ *(int*)this._typeUnion._unionTypes._byref = (int)value;
+ break;
+
+ case VarEnum.VT_UI4:
+ case VarEnum.VT_UINT:
+ *(uint*)this._typeUnion._unionTypes._byref = (uint)value;
+ break;
+
+ case VarEnum.VT_ERROR:
+ *(int*)this._typeUnion._unionTypes._byref = ((ErrorWrapper)value).ErrorCode;
+ break;
+
+ case VarEnum.VT_I8:
+ *(Int64*)this._typeUnion._unionTypes._byref = (Int64)value;
+ break;
+
+ case VarEnum.VT_UI8:
+ *(UInt64*)this._typeUnion._unionTypes._byref = (UInt64)value;
+ break;
+
+ case VarEnum.VT_R4:
+ *(float*)this._typeUnion._unionTypes._byref = (float)value;
+ break;
+
+ case VarEnum.VT_R8:
+ *(double*)this._typeUnion._unionTypes._byref = (double)value;
+ break;
+
+ case VarEnum.VT_DATE:
+ *(double*)this._typeUnion._unionTypes._byref = ((DateTime)value).ToOADate();
+ break;
+
+ case VarEnum.VT_UNKNOWN:
+ *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetIUnknownForObject(value);
+ break;
+
+ case VarEnum.VT_DISPATCH:
+ *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.GetIDispatchForObject(value);
+ break;
+
+ case VarEnum.VT_BSTR:
+ *(IntPtr*)this._typeUnion._unionTypes._byref = Marshal.StringToBSTR((string)value);
+ break;
+
+ case VarEnum.VT_CY:
+ *(long*)this._typeUnion._unionTypes._byref = decimal.ToOACurrency((decimal)value);
+ break;
+
+ case VarEnum.VT_DECIMAL:
+ *(decimal*)this._typeUnion._unionTypes._byref = (decimal)value;
+ break;
+
+ case VarEnum.VT_VARIANT:
+ Marshal.GetNativeVariantForObject(value, this._typeUnion._unionTypes._byref);
+ break;
+
+ default:
+ throw new ArgumentException("invalid argument type");
+ }
+ }
+
+ /// <summary>
+ /// Get the managed object representing the Variant.
+ /// </summary>
+ /// <returns></returns>
+ public object ToObject() {
+ // Check the simple case upfront
+ if (IsEmpty) {
+ return null;
+ }
+
+ switch (VariantType) {
+ case VarEnum.VT_NULL: return DBNull.Value;
+
+ #region Generated Variant ToObject
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_ToObject from: generate_comdispatch.py
+
+ case VarEnum.VT_I1: return AsI1;
+ case VarEnum.VT_I2: return AsI2;
+ case VarEnum.VT_I4: return AsI4;
+ case VarEnum.VT_I8: return AsI8;
+ case VarEnum.VT_UI1: return AsUi1;
+ case VarEnum.VT_UI2: return AsUi2;
+ case VarEnum.VT_UI4: return AsUi4;
+ case VarEnum.VT_UI8: return AsUi8;
+ case VarEnum.VT_INT: return AsInt;
+ case VarEnum.VT_UINT: return AsUint;
+ case VarEnum.VT_BOOL: return AsBool;
+ case VarEnum.VT_ERROR: return AsError;
+ case VarEnum.VT_R4: return AsR4;
+ case VarEnum.VT_R8: return AsR8;
+ case VarEnum.VT_DECIMAL: return AsDecimal;
+ case VarEnum.VT_CY: return AsCy;
+ case VarEnum.VT_DATE: return AsDate;
+ case VarEnum.VT_BSTR: return AsBstr;
+ case VarEnum.VT_UNKNOWN: return AsUnknown;
+ case VarEnum.VT_DISPATCH: return AsDispatch;
+ // VarEnum.VT_VARIANT is handled by Marshal.GetObjectForNativeVariant below
+
+ // *** END GENERATED CODE ***
+
+ #endregion
+
+ default:
+ try {
+ unsafe {
+ fixed (void* pThis = &this) {
+ return Marshal.GetObjectForNativeVariant((System.IntPtr)pThis);
+ }
+ }
+ }
+ catch (Exception ex) {
+ throw new NotImplementedException("Variant.ToObject cannot handle" + VariantType, ex);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Release any unmanaged memory associated with the Variant
+ /// </summary>
+ /// <returns></returns>
+ public void Clear() {
+ // We do not need to call OLE32's VariantClear for primitive types or ByRefs
+ // to safe ourselves the cost of interop transition.
+ // ByRef indicates the memory is not owned by the VARIANT itself while
+ // primitive types do not have any resources to free up.
+ // Hence, only safearrays, BSTRs, interfaces and user types are
+ // handled differently.
+ VarEnum vt = VariantType;
+ if ((vt & VarEnum.VT_BYREF) != 0) {
+ VariantType = VarEnum.VT_EMPTY;
+ } else if (
+ ((vt & VarEnum.VT_ARRAY) != 0) ||
+ ((vt) == VarEnum.VT_BSTR) ||
+ ((vt) == VarEnum.VT_UNKNOWN) ||
+ ((vt) == VarEnum.VT_DISPATCH) ||
+ ((vt) == VarEnum.VT_VARIANT) ||
+ ((vt) == VarEnum.VT_RECORD) ||
+ ((vt) == VarEnum.VT_VARIANT)
+ ) {
+ unsafe {
+ fixed (void* pThis = &this) {
+ NativeMethods.VariantClear((IntPtr)pThis);
+ }
+ }
+ BCLDebug.Assert(IsEmpty, "variant");
+ } else {
+ VariantType = VarEnum.VT_EMPTY;
+ }
+ }
+
+ public VarEnum VariantType {
+ get {
+ return (VarEnum)_typeUnion._vt;
+ }
+ set {
+ _typeUnion._vt = (ushort)value;
+ }
+ }
+
+ internal bool IsEmpty {
+ get {
+ return _typeUnion._vt == ((ushort)VarEnum.VT_EMPTY);
+ }
+ }
+
+ internal bool IsByRef {
+ get {
+ return (_typeUnion._vt & ((ushort)VarEnum.VT_BYREF)) != 0;
+ }
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly")]
+ public void SetAsNULL() {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_NULL;
+ }
+
+ #region Generated Variant accessors
+
+ // *** BEGIN GENERATED CODE ***
+ // generated by function: gen_accessors from: generate_comdispatch.py
+
+ // VT_I1
+
+ public SByte AsI1 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_I1, "variant");
+ return _typeUnion._unionTypes._i1;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I1;
+ _typeUnion._unionTypes._i1 = value;
+ }
+ }
+
+ // VT_I2
+
+ public Int16 AsI2 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_I2, "variant");
+ return _typeUnion._unionTypes._i2;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I2;
+ _typeUnion._unionTypes._i2 = value;
+ }
+ }
+
+ // VT_I4
+
+ public Int32 AsI4 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_I4, "variant");
+ return _typeUnion._unionTypes._i4;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I4;
+ _typeUnion._unionTypes._i4 = value;
+ }
+ }
+
+ // VT_I8
+
+ public Int64 AsI8 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_I8, "variant");
+ return _typeUnion._unionTypes._i8;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_I8;
+ _typeUnion._unionTypes._i8 = value;
+ }
+ }
+
+ // VT_UI1
+
+ public Byte AsUi1 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UI1, "variant");
+ return _typeUnion._unionTypes._ui1;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI1;
+ _typeUnion._unionTypes._ui1 = value;
+ }
+ }
+
+ // VT_UI2
+
+ public UInt16 AsUi2 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UI2, "variant");
+ return _typeUnion._unionTypes._ui2;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI2;
+ _typeUnion._unionTypes._ui2 = value;
+ }
+ }
+
+ // VT_UI4
+
+ public UInt32 AsUi4 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UI4, "variant");
+ return _typeUnion._unionTypes._ui4;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI4;
+ _typeUnion._unionTypes._ui4 = value;
+ }
+ }
+
+ // VT_UI8
+
+ public UInt64 AsUi8 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UI8, "variant");
+ return _typeUnion._unionTypes._ui8;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UI8;
+ _typeUnion._unionTypes._ui8 = value;
+ }
+ }
+
+ // VT_INT
+
+ public Int32 AsInt {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_INT, "variant");
+ return _typeUnion._unionTypes._int;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_INT;
+ _typeUnion._unionTypes._int = value;
+ }
+ }
+
+ // VT_UINT
+
+ public UInt32 AsUint {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UINT, "variant");
+ return _typeUnion._unionTypes._uint;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UINT;
+ _typeUnion._unionTypes._uint = value;
+ }
+ }
+
+ // VT_BOOL
+
+ public bool AsBool {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_BOOL, "variant");
+ return _typeUnion._unionTypes._bool != 0;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_BOOL;
+ _typeUnion._unionTypes._bool = value ? (short)-1 : (short)0;
+ }
+ }
+
+ // VT_ERROR
+
+ public Int32 AsError {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_ERROR, "variant");
+ return _typeUnion._unionTypes._error;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_ERROR;
+ _typeUnion._unionTypes._error = value;
+ }
+ }
+
+ // VT_R4
+
+ public Single AsR4 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_R4, "variant");
+ return _typeUnion._unionTypes._r4;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_R4;
+ _typeUnion._unionTypes._r4 = value;
+ }
+ }
+
+ // VT_R8
+
+ public Double AsR8 {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_R8, "variant");
+ return _typeUnion._unionTypes._r8;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_R8;
+ _typeUnion._unionTypes._r8 = value;
+ }
+ }
+
+ // VT_DECIMAL
+
+ public Decimal AsDecimal {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_DECIMAL, "variant");
+ // The first byte of Decimal is unused, but usually set to 0
+ Variant v = this;
+ v._typeUnion._vt = 0;
+ return v._decimal;
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DECIMAL;
+ _decimal = value;
+ // _vt overlaps with _decimal, and should be set after setting _decimal
+ _typeUnion._vt = (ushort)VarEnum.VT_DECIMAL;
+ }
+ }
+
+ // VT_CY
+
+ public Decimal AsCy {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_CY, "variant");
+ return Decimal.FromOACurrency(_typeUnion._unionTypes._cy);
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_CY;
+ _typeUnion._unionTypes._cy = Decimal.ToOACurrency(value);
+ }
+ }
+
+ // VT_DATE
+
+ public DateTime AsDate {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_DATE, "variant");
+ return DateTime.FromOADate(_typeUnion._unionTypes._date);
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DATE;
+ _typeUnion._unionTypes._date = value.ToOADate();
+ }
+ }
+
+ // VT_BSTR
+
+ public String AsBstr {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_BSTR, "variant");
+ return (string)Marshal.PtrToStringBSTR(this._typeUnion._unionTypes._bstr);
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_BSTR;
+ this._typeUnion._unionTypes._bstr = Marshal.StringToBSTR(value);
+ }
+ }
+
+ // VT_UNKNOWN
+
+ public Object AsUnknown {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_UNKNOWN, "variant");
+ if (_typeUnion._unionTypes._unknown == IntPtr.Zero)
+ return null;
+ return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._unknown);
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_UNKNOWN;
+ if (value == null)
+ _typeUnion._unionTypes._unknown = IntPtr.Zero;
+ else
+ _typeUnion._unionTypes._unknown = Marshal.GetIUnknownForObject(value);
+ }
+ }
+
+ // VT_DISPATCH
+
+ public Object AsDispatch {
+ get {
+ BCLDebug.Assert(VariantType == VarEnum.VT_DISPATCH, "variant");
+ if (_typeUnion._unionTypes._dispatch == IntPtr.Zero)
+ return null;
+ return Marshal.GetObjectForIUnknown(_typeUnion._unionTypes._dispatch);
+ }
+ set {
+ BCLDebug.Assert(IsEmpty, "variant"); // The setter can only be called once as VariantClear might be needed otherwise
+ VariantType = VarEnum.VT_DISPATCH;
+ if (value == null)
+ _typeUnion._unionTypes._dispatch = IntPtr.Zero;
+ else
+ _typeUnion._unionTypes._dispatch = Marshal.GetIDispatchForObject(value);
+ }
+ }
+
+
+ // *** END GENERATED CODE ***
+
+ internal IntPtr AsByRefVariant
+ {
+ get {
+ BCLDebug.Assert(VariantType == (VarEnum.VT_BYREF | VarEnum.VT_VARIANT), "variant");
+ return _typeUnion._unionTypes._pvarVal;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs b/src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs
new file mode 100644
index 0000000000..3f5120af39
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/VariantWrapper.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Wrapper that is converted to a variant with VT_BYREF | VT_VARIANT.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.InteropServices {
+
+ using System;
+
+ [Serializable]
+
+ public sealed class VariantWrapper
+ {
+ public VariantWrapper(Object obj)
+ {
+ m_WrappedObject = obj;
+ }
+
+ public Object WrappedObject
+ {
+ get
+ {
+ return m_WrappedObject;
+ }
+ }
+
+ private Object m_WrappedObject;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs
new file mode 100644
index 0000000000..80b24f5529
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/Attributes.cs
@@ -0,0 +1,123 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // DefaultInterfaceAttribute marks a WinRT class (or interface group) that has its default interface specified.
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)]
+ public sealed class DefaultInterfaceAttribute : Attribute
+ {
+ private Type m_defaultInterface;
+
+ public DefaultInterfaceAttribute(Type defaultInterface)
+ {
+ m_defaultInterface = defaultInterface;
+ }
+
+ public Type DefaultInterface
+ {
+ get { return m_defaultInterface; }
+ }
+ }
+
+ // WindowsRuntimeImport is a pseudo custom attribute which causes us to emit the tdWindowsRuntime bit
+ // onto types which are decorated with the attribute. This is needed to mark Windows Runtime types
+ // which are redefined in mscorlib.dll and System.Runtime.WindowsRuntime.dll, as the C# compiler does
+ // not have a built in syntax to mark tdWindowsRuntime. These two assemblies are special as they
+ // implement the CLR's support for WinRT, so this type is internal as marking tdWindowsRuntime should
+ // generally be done via winmdexp for user code.
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Struct | AttributeTargets.Delegate, Inherited = false)]
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal sealed class WindowsRuntimeImportAttribute : Attribute
+ {
+ public WindowsRuntimeImportAttribute()
+ { }
+ }
+
+ // This attribute is applied to class interfaces in a generated projection assembly. It is used by Visual Studio
+ // and other tools to find out what version of a component (eg. Windows) a WinRT class began to implement
+ // a particular interfaces.
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, Inherited = false, AllowMultiple = true)]
+ public sealed class InterfaceImplementedInVersionAttribute : Attribute
+ {
+ public InterfaceImplementedInVersionAttribute(Type interfaceType, byte majorVersion, byte minorVersion, byte buildVersion, byte revisionVersion)
+ {
+ m_interfaceType = interfaceType;
+ m_majorVersion = majorVersion;
+ m_minorVersion = minorVersion;
+ m_buildVersion = buildVersion;
+ m_revisionVersion = revisionVersion;
+ }
+
+ public Type InterfaceType
+ {
+ get { return m_interfaceType; }
+ }
+
+ public byte MajorVersion
+ {
+ get { return m_majorVersion; }
+ }
+
+ public byte MinorVersion
+ {
+ get { return m_minorVersion; }
+ }
+
+ public byte BuildVersion
+ {
+ get { return m_buildVersion; }
+ }
+
+ public byte RevisionVersion
+ {
+ get { return m_revisionVersion; }
+ }
+
+ private Type m_interfaceType;
+ private byte m_majorVersion;
+ private byte m_minorVersion;
+ private byte m_buildVersion;
+ private byte m_revisionVersion;
+ }
+
+ // Applies to read-only array parameters
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ public sealed class ReadOnlyArrayAttribute : Attribute
+ {
+ public ReadOnlyArrayAttribute() {}
+ }
+
+ // Applies to write-only array parameters
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = false, AllowMultiple = false)]
+ public sealed class WriteOnlyArrayAttribute : Attribute
+ {
+ public WriteOnlyArrayAttribute() {}
+ }
+
+
+
+ // This attribute is applied on the return value to specify the name of the return value.
+ // In WindowsRuntime all parameters including return value need to have unique names.
+ // This is essential in JS as one of the ways to get at the results of a method in JavaScript is via a Dictionary object keyed by parameter name.
+ [AttributeUsage(AttributeTargets.ReturnValue | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
+ public sealed class ReturnValueNameAttribute : Attribute
+ {
+ private string m_Name;
+ public ReturnValueNameAttribute(string name)
+ {
+ m_Name = name;
+ }
+
+ public string Name
+ {
+ get { return m_Name; }
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs
new file mode 100644
index 0000000000..5574f3c251
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToCollectionAdapter.cs
@@ -0,0 +1,108 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the ICollection interface on WinRT
+ // objects that support IBindableVector. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not BindableVectorToCollectionAdapter objects. Rather, they are
+ // of type IBindableVector. No actual BindableVectorToCollectionAdapter object is ever instantiated.
+ // Thus, you will see a lot of expressions that cast "this" to "IBindableVector".
+ internal sealed class BindableVectorToCollectionAdapter
+ {
+ private BindableVectorToCollectionAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // int Count { get }
+ [Pure]
+ [SecurityCritical]
+ internal int Count()
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ uint size = _this.Size;
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)size;
+ }
+
+ // bool IsSynchronized { get }
+ [Pure]
+ [SecurityCritical]
+ internal bool IsSynchronized()
+ {
+ return false;
+ }
+
+ // object SyncRoot { get }
+ [Pure]
+ [SecurityCritical]
+ internal object SyncRoot()
+ {
+ return this;
+ }
+
+ // void CopyTo(Array array, int index)
+ [Pure]
+ [SecurityCritical]
+ internal void CopyTo(Array array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ // ICollection expects the destination array to be single-dimensional.
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+
+ int destLB = array.GetLowerBound(0);
+
+ int srcLen = Count();
+ int destLen = array.GetLength(0);
+
+ if (arrayIndex < destLB)
+ throw new ArgumentOutOfRangeException("arrayIndex");
+
+ // Does the dimension in question have sufficient space to copy the expected number of entries?
+ // We perform this check before valid index check to ensure the exception message is in sync with
+ // the following snippet that uses regular framework code:
+ //
+ // ArrayList list = new ArrayList();
+ // list.Add(1);
+ // Array items = Array.CreateInstance(typeof(object), new int[] { 1 }, new int[] { -1 });
+ // list.CopyTo(items, 0);
+
+ if(srcLen > (destLen - (arrayIndex - destLB)))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ if(arrayIndex - destLB > destLen)
+ throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds"));
+
+ // We need to verify the index as we;
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+
+ for (uint i = 0; i < srcLen; i++)
+ {
+ array.SetValue(_this.GetAt(i), i + arrayIndex);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs
new file mode 100644
index 0000000000..73ebf721ee
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/BindableVectorToListAdapter.cs
@@ -0,0 +1,241 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IList interface on WinRT
+ // objects that support IBindableVector. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not BindableVectorToListAdapter objects. Rather, they are
+ // of type IBindableVector. No actual BindableVectorToListAdapter object is ever instantiated.
+ // Thus, you will see a lot of expressions that cast "this" to "IBindableVector".
+ internal sealed class BindableVectorToListAdapter
+ {
+ private BindableVectorToListAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // object this[int index] { get }
+ [SecurityCritical]
+ internal object Indexer_Get(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ return GetAt(_this, (uint)index);
+ }
+
+ // object this[int index] { set }
+ [SecurityCritical]
+ internal void Indexer_Set(int index, object value)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ SetAt(_this, (uint)index, value);
+ }
+
+ // int Add(object value)
+ [SecurityCritical]
+ internal int Add(object value)
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ _this.Append(value);
+
+ uint size = _this.Size;
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)(size - 1);
+ }
+
+ // bool Contains(object item)
+ [SecurityCritical]
+ internal bool Contains(object item)
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+
+ uint index;
+ return _this.IndexOf(item, out index);
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear()
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ _this.Clear();
+ }
+
+ // bool IsFixedSize { get }
+ [Pure]
+ [SecurityCritical]
+ internal bool IsFixedSize()
+ {
+ return false;
+ }
+
+ // bool IsReadOnly { get }
+ [Pure]
+ [SecurityCritical]
+ internal bool IsReadOnly()
+ {
+ return false;
+ }
+
+ // int IndexOf(object item)
+ [SecurityCritical]
+ internal int IndexOf(object item)
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+
+ uint index;
+ bool exists = _this.IndexOf(item, out index);
+
+ if (!exists)
+ return -1;
+
+ if (((uint)Int32.MaxValue) < index)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)index;
+ }
+
+ // void Insert(int index, object item)
+ [SecurityCritical]
+ internal void Insert(int index, object item)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ InsertAtHelper(_this, (uint)index, item);
+ }
+
+ // bool Remove(object item)
+ [SecurityCritical]
+ internal void Remove(object item)
+ {
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+
+ uint index;
+ bool exists = _this.IndexOf(item, out index);
+
+ if (exists)
+ {
+ if (((uint)Int32.MaxValue) < index)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ RemoveAtHelper(_this, index);
+ }
+ }
+
+ // void RemoveAt(int index)
+ [SecurityCritical]
+ internal void RemoveAt(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IBindableVector _this = JitHelpers.UnsafeCast<IBindableVector>(this);
+ RemoveAtHelper(_this, (uint)index);
+ }
+
+ // Helpers:
+
+ private static object GetAt(IBindableVector _this, uint index)
+ {
+ try
+ {
+ return _this.GetAt(index);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ private static void SetAt(IBindableVector _this, uint index, object value)
+ {
+ try
+ {
+ _this.SetAt(index, value);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ private static void InsertAtHelper(IBindableVector _this, uint index, object item)
+ {
+ try
+ {
+ _this.InsertAt(index, item);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ private static void RemoveAtHelper(IBindableVector _this, uint index)
+ {
+ try
+ {
+ _this.RemoveAt(index);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs
new file mode 100644
index 0000000000..3a52d12234
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIKeyValuePairImpl.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // Provides access to a System.Collections.Generic.KeyValuePair<K, V> via the IKeyValuePair<K, V> WinRT interface.
+ internal sealed class CLRIKeyValuePairImpl<K, V> : IKeyValuePair<K, V>,
+ IGetProxyTarget
+ {
+ private readonly KeyValuePair<K, V> _pair;
+
+ public CLRIKeyValuePairImpl([In] ref KeyValuePair<K, V> pair)
+ {
+ _pair = pair;
+ }
+
+ // IKeyValuePair<K, V> implementation
+ [Pure]
+ public K Key
+ {
+ get { return _pair.Key; }
+ }
+
+ [Pure]
+ public V Value
+ {
+ get { return _pair.Value; }
+ }
+
+ // Called from the VM to wrap a boxed KeyValuePair with a CLRIKeyValuePairImpl.
+ internal static object BoxHelper(object pair)
+ {
+ Contract.Requires(pair != null);
+
+ KeyValuePair<K, V> unboxedPair = (KeyValuePair<K, V>)pair;
+ return new CLRIKeyValuePairImpl<K, V>(ref unboxedPair);
+ }
+
+ // Called from the VM to get a boxed KeyValuePair out of a CLRIKeyValuePairImpl.
+ internal static object UnboxHelper(object wrapper)
+ {
+ Contract.Requires(wrapper != null);
+
+ CLRIKeyValuePairImpl<K, V> reference = (CLRIKeyValuePairImpl<K, V>)wrapper;
+ return reference._pair;
+ }
+
+ public override string ToString()
+ {
+ return _pair.ToString();
+ }
+
+ object IGetProxyTarget.GetTarget()
+ {
+ return _pair;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs
new file mode 100644
index 0000000000..c88f13dd0b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIPropertyValueImpl.cs
@@ -0,0 +1,555 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ internal class CLRIPropertyValueImpl : IPropertyValue
+ {
+ private PropertyType _type;
+ private Object _data;
+
+ // Numeric scalar types which participate in coersion
+ private static volatile Tuple<Type, PropertyType>[] s_numericScalarTypes;
+
+ internal CLRIPropertyValueImpl(PropertyType type, Object data)
+ {
+ _type = type;
+ _data = data;
+ }
+
+ private static Tuple<Type, PropertyType>[] NumericScalarTypes {
+ get {
+ if (s_numericScalarTypes == null) {
+ Tuple<Type, PropertyType>[] numericScalarTypes = new Tuple<Type, PropertyType>[] {
+ new Tuple<Type, PropertyType>(typeof(Byte), PropertyType.UInt8),
+ new Tuple<Type, PropertyType>(typeof(Int16), PropertyType.Int16),
+ new Tuple<Type, PropertyType>(typeof(UInt16), PropertyType.UInt16),
+ new Tuple<Type, PropertyType>(typeof(Int32), PropertyType.Int32),
+ new Tuple<Type, PropertyType>(typeof(UInt32), PropertyType.UInt32),
+ new Tuple<Type, PropertyType>(typeof(Int64), PropertyType.Int64),
+ new Tuple<Type, PropertyType>(typeof(UInt64), PropertyType.UInt64),
+ new Tuple<Type, PropertyType>(typeof(Single), PropertyType.Single),
+ new Tuple<Type, PropertyType>(typeof(Double), PropertyType.Double)
+ };
+
+ s_numericScalarTypes = numericScalarTypes;
+ }
+
+ return s_numericScalarTypes;
+ }
+ }
+
+ public PropertyType Type {
+ [Pure]
+ get { return _type; }
+ }
+
+ public bool IsNumericScalar {
+ [Pure]
+ get {
+ return IsNumericScalarImpl(_type, _data);
+ }
+ }
+
+ public override string ToString()
+ {
+ if (_data != null)
+ {
+ return _data.ToString();
+ }
+ else
+ {
+ return base.ToString();
+ }
+ }
+
+ [Pure]
+ public Byte GetUInt8()
+ {
+ return CoerceScalarValue<Byte>(PropertyType.UInt8);
+ }
+
+ [Pure]
+ public Int16 GetInt16()
+ {
+ return CoerceScalarValue<Int16>(PropertyType.Int16);
+ }
+
+ public UInt16 GetUInt16()
+ {
+ return CoerceScalarValue<UInt16>(PropertyType.UInt16);
+ }
+
+ [Pure]
+ public Int32 GetInt32()
+ {
+ return CoerceScalarValue<Int32>(PropertyType.Int32);
+ }
+
+ [Pure]
+ public UInt32 GetUInt32()
+ {
+ return CoerceScalarValue<UInt32>(PropertyType.UInt32);
+ }
+
+ [Pure]
+ public Int64 GetInt64()
+ {
+ return CoerceScalarValue<Int64>(PropertyType.Int64);
+ }
+
+ [Pure]
+ public UInt64 GetUInt64()
+ {
+ return CoerceScalarValue<UInt64>(PropertyType.UInt64);
+ }
+
+ [Pure]
+ public Single GetSingle()
+ {
+ return CoerceScalarValue<Single>(PropertyType.Single);
+ }
+
+ [Pure]
+ public Double GetDouble()
+ {
+ return CoerceScalarValue<Double>(PropertyType.Double);
+ }
+
+ [Pure]
+ public char GetChar16()
+ {
+ if (this.Type != PropertyType.Char16)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Char16"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (char)_data;
+ }
+
+ [Pure]
+ public Boolean GetBoolean()
+ {
+ if (this.Type != PropertyType.Boolean)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Boolean"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (bool)_data;
+ }
+
+ [Pure]
+ public String GetString()
+ {
+ return CoerceScalarValue<String>(PropertyType.String);
+ }
+
+ [Pure]
+ public Object GetInspectable()
+ {
+ if (this.Type != PropertyType.Inspectable)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Inspectable"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return _data;
+ }
+
+
+ [Pure]
+ public Guid GetGuid()
+ {
+ return CoerceScalarValue<Guid>(PropertyType.Guid);
+ }
+
+
+ [Pure]
+ public DateTimeOffset GetDateTime()
+ {
+ if (this.Type != PropertyType.DateTime)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "DateTime"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (DateTimeOffset)_data;
+ }
+
+ [Pure]
+ public TimeSpan GetTimeSpan()
+ {
+ if (this.Type != PropertyType.TimeSpan)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "TimeSpan"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (TimeSpan)_data;
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Point GetPoint()
+ {
+ if (this.Type != PropertyType.Point)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Point"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+ return Unbox<Point>(IReferenceFactory.s_pointType);
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Size GetSize()
+ {
+ if (this.Type != PropertyType.Size)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Size"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+ return Unbox<Size>(IReferenceFactory.s_sizeType);
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Rect GetRect()
+ {
+ if (this.Type != PropertyType.Rect)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Rect"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+ return Unbox<Rect>(IReferenceFactory.s_rectType);
+ }
+
+ [Pure]
+ public Byte[] GetUInt8Array()
+ {
+ return CoerceArrayValue<Byte>(PropertyType.UInt8Array);
+ }
+
+ [Pure]
+ public Int16[] GetInt16Array()
+ {
+ return CoerceArrayValue<Int16>(PropertyType.Int16Array);
+ }
+
+ [Pure]
+ public UInt16[] GetUInt16Array()
+ {
+ return CoerceArrayValue<UInt16>(PropertyType.UInt16Array);
+ }
+
+ [Pure]
+ public Int32[] GetInt32Array()
+ {
+ return CoerceArrayValue<Int32>(PropertyType.Int32Array);
+ }
+
+ [Pure]
+ public UInt32[] GetUInt32Array()
+ {
+ return CoerceArrayValue<UInt32>(PropertyType.UInt32Array);
+ }
+
+ [Pure]
+ public Int64[] GetInt64Array()
+ {
+ return CoerceArrayValue<Int64>(PropertyType.Int64Array);
+ }
+
+ [Pure]
+ public UInt64[] GetUInt64Array()
+ {
+ return CoerceArrayValue<UInt64>(PropertyType.UInt64Array);
+ }
+
+ [Pure]
+ public Single[] GetSingleArray()
+ {
+ return CoerceArrayValue<Single>(PropertyType.SingleArray);
+ }
+
+ [Pure]
+ public Double[] GetDoubleArray()
+ {
+ return CoerceArrayValue<Double>(PropertyType.DoubleArray);
+ }
+
+ [Pure]
+ public char[] GetChar16Array()
+ {
+ if (this.Type != PropertyType.Char16Array)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Char16[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (char[])_data;
+ }
+
+ [Pure]
+ public Boolean[] GetBooleanArray()
+ {
+ if (this.Type != PropertyType.BooleanArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Boolean[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (bool[])_data;
+ }
+
+ [Pure]
+ public String[] GetStringArray()
+ {
+ return CoerceArrayValue<String>(PropertyType.StringArray);
+ }
+
+ [Pure]
+ public Object[] GetInspectableArray()
+ {
+ if (this.Type != PropertyType.InspectableArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Inspectable[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (Object[])_data;
+ }
+
+ [Pure]
+ public Guid[] GetGuidArray()
+ {
+ return CoerceArrayValue<Guid>(PropertyType.GuidArray);
+ }
+
+ [Pure]
+ public DateTimeOffset[] GetDateTimeArray()
+ {
+ if (this.Type != PropertyType.DateTimeArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "DateTimeOffset[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (DateTimeOffset[])_data;
+ }
+
+ [Pure]
+ public TimeSpan[] GetTimeSpanArray()
+ {
+ if (this.Type != PropertyType.TimeSpanArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "TimeSpan[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+ return (TimeSpan[])_data;
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Point[] GetPointArray()
+ {
+ if (this.Type != PropertyType.PointArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Point[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+ return UnboxArray<Point>(IReferenceFactory.s_pointType);
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Size[] GetSizeArray()
+ {
+ if (this.Type != PropertyType.SizeArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Size[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+
+ return UnboxArray<Size>(IReferenceFactory.s_sizeType);
+ }
+
+ [Pure]
+ [SecuritySafeCritical]
+ public Rect[] GetRectArray()
+ {
+ if (this.Type != PropertyType.RectArray)
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, "Rect[]"), __HResults.TYPE_E_TYPEMISMATCH);
+ Contract.EndContractBlock();
+
+ return UnboxArray<Rect>(IReferenceFactory.s_rectType);
+ }
+
+ private T[] CoerceArrayValue<T>(PropertyType unboxType) {
+ // If we contain the type being looked for directly, then take the fast-path
+ if (Type == unboxType) {
+ return (T[])_data;
+ }
+
+ // Make sure we have an array to begin with
+ Array dataArray = _data as Array;
+ if (dataArray == null) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", this.Type, typeof(T).MakeArrayType().Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+
+ // Array types are 1024 larger than their equivilent scalar counterpart
+ BCLDebug.Assert((int)Type > 1024, "Unexpected array PropertyType value");
+ PropertyType scalarType = Type - 1024;
+
+ // If we do not have the correct array type, then we need to convert the array element-by-element
+ // to a new array of the requested type
+ T[] coercedArray = new T[dataArray.Length];
+ for (int i = 0; i < dataArray.Length; ++i) {
+ try {
+ coercedArray[i] = CoerceScalarValue<T>(scalarType, dataArray.GetValue(i));
+ } catch (InvalidCastException elementCastException) {
+ Exception e = new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueArrayCoersion", this.Type, typeof(T).MakeArrayType().Name, i, elementCastException.Message), elementCastException);
+ e.SetErrorCode(elementCastException._HResult);
+ throw e;
+ }
+ }
+
+ return coercedArray;
+ }
+
+ private T CoerceScalarValue<T>(PropertyType unboxType)
+ {
+ // If we are just a boxed version of the requested type, then take the fast path out
+ if (Type == unboxType) {
+ return (T)_data;
+ }
+
+ return CoerceScalarValue<T>(Type, _data);
+ }
+
+ private static T CoerceScalarValue<T>(PropertyType type, object value) {
+ // If the property type is neither one of the coercable numeric types nor IInspectable, we
+ // should not attempt coersion, even if the underlying value is technically convertable
+ if (!IsCoercable(type, value) && type != PropertyType.Inspectable) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", type, typeof(T).Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+
+ try {
+ // Try to coerce:
+ // * String <--> Guid
+ // * Numeric scalars
+ if (type == PropertyType.String && typeof(T) == typeof(Guid)) {
+ return (T)(object)Guid.Parse((string)value);
+ }
+ else if (type == PropertyType.Guid && typeof(T) == typeof(String)) {
+ return (T)(object)((Guid)value).ToString("D", System.Globalization.CultureInfo.InvariantCulture);
+ }
+ else {
+ // Iterate over the numeric scalars, to see if we have a match for one of the known conversions
+ foreach (Tuple<Type, PropertyType> numericScalar in NumericScalarTypes) {
+ if (numericScalar.Item1 == typeof(T)) {
+ return (T)Convert.ChangeType(value, typeof(T), System.Globalization.CultureInfo.InvariantCulture);
+ }
+ }
+ }
+ }
+ catch (FormatException) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", type, typeof(T).Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+ catch (InvalidCastException) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", type, typeof(T).Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+ catch (OverflowException) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueCoersion", type, value, typeof(T).Name), __HResults.DISP_E_OVERFLOW);
+ }
+
+ // If the property type is IInspectable, and we have a nested IPropertyValue, then we need
+ // to pass along the request to coerce the value.
+ IPropertyValue ipv = value as IPropertyValue;
+ if (type == PropertyType.Inspectable && ipv != null) {
+ if (typeof(T) == typeof(Byte)) {
+ return (T)(object)ipv.GetUInt8();
+ }
+ else if (typeof(T) == typeof(Int16)) {
+ return (T)(object)ipv.GetInt16();
+ }
+ else if (typeof(T) == typeof(UInt16)) {
+ return (T)(object)ipv.GetUInt16();
+ }
+ else if (typeof(T) == typeof(Int32)) {
+ return (T)(object)ipv.GetUInt32();
+ }
+ else if (typeof(T) == typeof(UInt32)) {
+ return (T)(object)ipv.GetUInt32();
+ }
+ else if (typeof(T) == typeof(Int64)) {
+ return (T)(object)ipv.GetInt64();
+ }
+ else if (typeof(T) == typeof(UInt64)) {
+ return (T)(object)ipv.GetUInt64();
+ }
+ else if (typeof(T) == typeof(Single)) {
+ return (T)(object)ipv.GetSingle();
+ }
+ else if (typeof(T) == typeof(Double)) {
+ return (T)(object)ipv.GetDouble();
+ }
+ else {
+ BCLDebug.Assert(false, "T in coersion function wasn't understood as a type that can be coerced - make sure that CoerceScalarValue and NumericScalarTypes are in sync");
+ }
+ }
+
+ // Otherwise, this is an invalid coersion
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", type, typeof(T).Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+
+ private static bool IsCoercable(PropertyType type, object data) {
+ // String <--> Guid is allowed
+ if (type == PropertyType.Guid || type == PropertyType.String) {
+ return true;
+ }
+
+ // All numeric scalars can also be coerced
+ return IsNumericScalarImpl(type, data);
+ }
+
+ private static bool IsNumericScalarImpl(PropertyType type, object data) {
+ if (data.GetType().IsEnum) {
+ return true;
+ }
+
+ foreach (Tuple<Type, PropertyType> numericScalar in NumericScalarTypes) {
+ if (numericScalar.Item2 == type) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // Unbox the data stored in the property value to a structurally equivilent type
+ [Pure]
+ [SecurityCritical]
+ private unsafe T Unbox<T>(Type expectedBoxedType) where T : struct {
+ Contract.Requires(expectedBoxedType != null);
+ Contract.Requires(Marshal.SizeOf(expectedBoxedType) == Marshal.SizeOf(typeof(T)));
+
+ if (_data.GetType() != expectedBoxedType) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", _data.GetType(), expectedBoxedType.Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+
+ T unboxed = new T();
+
+ fixed (byte *pData = &JitHelpers.GetPinningHelper(_data).m_data) {
+ byte* pUnboxed = (byte*)JitHelpers.UnsafeCastToStackPointer(ref unboxed);
+ Buffer.Memcpy(pUnboxed, pData, Marshal.SizeOf(unboxed));
+ }
+
+ return unboxed;
+ }
+
+ // Convert the array stored in the property value to a structurally equivilent array type
+ [Pure]
+ [SecurityCritical]
+ private unsafe T[] UnboxArray<T>(Type expectedArrayElementType) where T : struct {
+ Contract.Requires(expectedArrayElementType != null);
+ Contract.Requires(Marshal.SizeOf(expectedArrayElementType) == Marshal.SizeOf(typeof(T)));
+
+ Array dataArray = _data as Array;
+ if (dataArray == null || _data.GetType().GetElementType() != expectedArrayElementType) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_WinRTIPropertyValueElement", _data.GetType(), expectedArrayElementType.MakeArrayType().Name), __HResults.TYPE_E_TYPEMISMATCH);
+ }
+
+ T[] converted = new T[dataArray.Length];
+
+ if (converted.Length > 0) {
+ fixed (byte * dataPin = &JitHelpers.GetPinningHelper(dataArray).m_data) {
+ fixed (byte * convertedPin = &JitHelpers.GetPinningHelper(converted).m_data) {
+ byte *pData = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(dataArray, 0);
+ byte *pConverted = (byte *)Marshal.UnsafeAddrOfPinnedArrayElement(converted, 0);
+
+ Buffer.Memcpy(pConverted, pData, checked(Marshal.SizeOf(typeof(T)) * converted.Length));
+ }
+ }
+ }
+
+ return converted;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs
new file mode 100644
index 0000000000..e379d38cf3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CLRIReferenceImpl.cs
@@ -0,0 +1,406 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections;
+using System.Diagnostics.Contracts;
+using System.Reflection;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ internal sealed class CLRIReferenceImpl<T> : CLRIPropertyValueImpl, IReference<T>, IGetProxyTarget
+ {
+ private T _value;
+
+ public CLRIReferenceImpl(PropertyType type, T obj)
+ : base(type, obj)
+ {
+ BCLDebug.Assert(obj != null, "Must not be null");
+ _value = obj;
+ }
+
+ public T Value {
+ get { return _value; }
+ }
+
+ public override string ToString()
+ {
+ if (_value != null)
+ {
+ return _value.ToString();
+ }
+ else
+ {
+ return base.ToString();
+ }
+ }
+
+ object IGetProxyTarget.GetTarget()
+ {
+ return (object)_value;
+ }
+
+ // We have T in an IReference<T>. Need to QI for IReference<T> with the appropriate GUID, call
+ // the get_Value property, allocate an appropriately-sized managed object, marshal the native object
+ // to the managed object, and free the native method. Also we want the return value boxed (aka normal value type boxing).
+ //
+ // This method is called by VM. Mark the method with FriendAccessAllowed attribute to ensure that the unreferenced method
+ // optimization skips it and the code will be saved into NGen image.
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal static Object UnboxHelper(Object wrapper)
+ {
+ Contract.Requires(wrapper != null);
+ IReference<T> reference = (IReference<T>) wrapper;
+ Contract.Assert(reference != null, "CLRIReferenceImpl::UnboxHelper - QI'ed for IReference<"+typeof(T)+">, but that failed.");
+ return reference.Value;
+ }
+ }
+
+ // T can be any WinRT-compatible type
+ internal sealed class CLRIReferenceArrayImpl<T> : CLRIPropertyValueImpl,
+ IGetProxyTarget,
+ IReferenceArray<T>,
+ IList // Jupiter data binding needs IList/IEnumerable
+ {
+ private T[] _value;
+ private IList _list;
+
+ public CLRIReferenceArrayImpl(PropertyType type, T[] obj)
+ : base(type, obj)
+ {
+ BCLDebug.Assert(obj != null, "Must not be null");
+
+ _value = obj;
+
+ _list = (IList) _value;
+ }
+
+ public T[] Value {
+ get { return _value; }
+ }
+
+ public override string ToString()
+ {
+ if (_value != null)
+ {
+ return _value.ToString();
+ }
+ else
+ {
+ return base.ToString();
+ }
+ }
+
+ //
+ // IEnumerable methods. Used by data-binding in Jupiter when you try to data bind
+ // against a managed array
+ //
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable)_value).GetEnumerator();
+ }
+
+ //
+ // IList & ICollection methods.
+ // This enables two-way data binding and index access in Jupiter
+ //
+ Object IList.this[int index] {
+ get
+ {
+ return _list[index];
+ }
+
+ set
+ {
+ _list[index] = value;
+ }
+ }
+
+ int IList.Add(Object value)
+ {
+ return _list.Add(value);
+ }
+
+ bool IList.Contains(Object value)
+ {
+ return _list.Contains(value);
+ }
+
+ void IList.Clear()
+ {
+ _list.Clear();
+ }
+
+ bool IList.IsReadOnly
+ {
+ get
+ {
+ return _list.IsReadOnly;
+ }
+ }
+
+ bool IList.IsFixedSize
+ {
+ get
+ {
+ return _list.IsFixedSize;
+ }
+ }
+
+ int IList.IndexOf(Object value)
+ {
+ return _list.IndexOf(value);
+ }
+
+ void IList.Insert(int index, Object value)
+ {
+ _list.Insert(index, value);
+ }
+
+ void IList.Remove(Object value)
+ {
+ _list.Remove(value);
+ }
+
+ void IList.RemoveAt(int index)
+ {
+ _list.RemoveAt(index);
+ }
+
+ void ICollection.CopyTo(Array array, int index)
+ {
+ _list.CopyTo(array, index);
+ }
+
+ int ICollection.Count
+ {
+ get
+ {
+ return _list.Count;
+ }
+ }
+
+ Object ICollection.SyncRoot
+ {
+ get
+ {
+ return _list.SyncRoot;
+ }
+ }
+
+ bool ICollection.IsSynchronized
+ {
+ get
+ {
+ return _list.IsSynchronized;
+ }
+ }
+
+ object IGetProxyTarget.GetTarget()
+ {
+ return (object)_value;
+ }
+
+ // We have T in an IReferenceArray<T>. Need to QI for IReferenceArray<T> with the appropriate GUID, call
+ // the get_Value property, allocate an appropriately-sized managed object, marshal the native object
+ // to the managed object, and free the native method.
+ //
+ // This method is called by VM. Mark the method with FriendAccessAllowed attribute to ensure that the unreferenced method
+ // optimization skips it and the code will be saved into NGen image.
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal static Object UnboxHelper(Object wrapper)
+ {
+ Contract.Requires(wrapper != null);
+ IReferenceArray<T> reference = (IReferenceArray<T>)wrapper;
+ Contract.Assert(reference != null, "CLRIReferenceArrayImpl::UnboxHelper - QI'ed for IReferenceArray<" + typeof(T) + ">, but that failed.");
+ T[] marshaled = reference.Value;
+ return marshaled;
+ }
+ }
+
+ // For creating instances of Windows Runtime's IReference<T> and IReferenceArray<T>.
+ internal static class IReferenceFactory
+ {
+ internal static readonly Type s_pointType = Type.GetType("Windows.Foundation.Point, " + AssemblyRef.SystemRuntimeWindowsRuntime);
+ internal static readonly Type s_rectType = Type.GetType("Windows.Foundation.Rect, " + AssemblyRef.SystemRuntimeWindowsRuntime);
+ internal static readonly Type s_sizeType = Type.GetType("Windows.Foundation.Size, " + AssemblyRef.SystemRuntimeWindowsRuntime);
+
+ [SecuritySafeCritical]
+ internal static Object CreateIReference(Object obj)
+ {
+ Contract.Requires(obj != null, "Null should not be boxed.");
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ Type type = obj.GetType();
+
+ if (type.IsArray)
+ return CreateIReferenceArray((Array) obj);
+
+ if (type == typeof(int))
+ return new CLRIReferenceImpl<int>(PropertyType.Int32, (int)obj);
+ if (type == typeof(String))
+ return new CLRIReferenceImpl<String>(PropertyType.String, (String)obj);
+ if (type == typeof(byte))
+ return new CLRIReferenceImpl<byte>(PropertyType.UInt8, (byte)obj);
+ if (type == typeof(short))
+ return new CLRIReferenceImpl<short>(PropertyType.Int16, (short)obj);
+ if (type == typeof(ushort))
+ return new CLRIReferenceImpl<ushort>(PropertyType.UInt16, (ushort)obj);
+ if (type == typeof(uint))
+ return new CLRIReferenceImpl<uint>(PropertyType.UInt32, (uint)obj);
+ if (type == typeof(long))
+ return new CLRIReferenceImpl<long>(PropertyType.Int64, (long)obj);
+ if (type == typeof(ulong))
+ return new CLRIReferenceImpl<ulong>(PropertyType.UInt64, (ulong)obj);
+ if (type == typeof(float))
+ return new CLRIReferenceImpl<float>(PropertyType.Single, (float)obj);
+ if (type == typeof(double))
+ return new CLRIReferenceImpl<double>(PropertyType.Double, (double)obj);
+ if (type == typeof(char))
+ return new CLRIReferenceImpl<char>(PropertyType.Char16, (char)obj);
+ if (type == typeof(bool))
+ return new CLRIReferenceImpl<bool>(PropertyType.Boolean, (bool)obj);
+ if (type == typeof(Guid))
+ return new CLRIReferenceImpl<Guid>(PropertyType.Guid, (Guid)obj);
+ if (type == typeof(DateTimeOffset))
+ return new CLRIReferenceImpl<DateTimeOffset>(PropertyType.DateTime, (DateTimeOffset)obj);
+ if (type == typeof(TimeSpan))
+ return new CLRIReferenceImpl<TimeSpan>(PropertyType.TimeSpan, (TimeSpan)obj);
+ if (type == typeof(Object))
+ return new CLRIReferenceImpl<Object>(PropertyType.Inspectable, (Object)obj);
+ if (type == typeof(RuntimeType))
+ { // If the type is System.RuntimeType, we want to use System.Type marshaler (it's parent of the type)
+ return new CLRIReferenceImpl<Type>(PropertyType.Other, (Type)obj);
+ }
+
+ // Handle arbitrary WinRT-compatible value types, and recognize a few special types.
+ PropertyType? propType = null;
+ if (type == s_pointType)
+ {
+ propType = PropertyType.Point;
+ }
+ else if (type == s_rectType)
+ {
+ propType = PropertyType.Rect;
+ }
+ else if (type == s_sizeType)
+ {
+ propType = PropertyType.Size;
+ }
+ else if (type.IsValueType || obj is Delegate)
+ {
+ propType = PropertyType.Other;
+ }
+
+ if (propType.HasValue)
+ {
+ Type specificType = typeof(CLRIReferenceImpl<>).MakeGenericType(type);
+ return Activator.CreateInstance(specificType, new Object[] { propType.Value, obj });
+ }
+
+ Contract.Assert(false, "We should not see non-WinRT type here");
+ return null;
+ }
+
+ [SecuritySafeCritical]
+ internal static Object CreateIReferenceArray(Array obj)
+ {
+ Contract.Requires(obj != null);
+ Contract.Requires(obj.GetType().IsArray);
+ Contract.Ensures(Contract.Result<Object>() != null);
+
+ Type type = obj.GetType().GetElementType();
+
+ Contract.Assert(obj.Rank == 1 && obj.GetLowerBound(0) == 0 && !type.IsArray);
+
+ if (type == typeof(int))
+ return new CLRIReferenceArrayImpl<int>(PropertyType.Int32Array, (int[])obj);
+ if (type == typeof(String))
+ return new CLRIReferenceArrayImpl<String>(PropertyType.StringArray, (String[])obj);
+ if (type == typeof(byte))
+ return new CLRIReferenceArrayImpl<byte>(PropertyType.UInt8Array, (byte[])obj);
+ if (type == typeof(short))
+ return new CLRIReferenceArrayImpl<short>(PropertyType.Int16Array, (short[])obj);
+ if (type == typeof(ushort))
+ return new CLRIReferenceArrayImpl<ushort>(PropertyType.UInt16Array, (ushort[])obj);
+ if (type == typeof(uint))
+ return new CLRIReferenceArrayImpl<uint>(PropertyType.UInt32Array, (uint[])obj);
+ if (type == typeof(long))
+ return new CLRIReferenceArrayImpl<long>(PropertyType.Int64Array, (long[])obj);
+ if (type == typeof(ulong))
+ return new CLRIReferenceArrayImpl<ulong>(PropertyType.UInt64Array, (ulong[])obj);
+ if (type == typeof(float))
+ return new CLRIReferenceArrayImpl<float>(PropertyType.SingleArray, (float[])obj);
+ if (type == typeof(double))
+ return new CLRIReferenceArrayImpl<double>(PropertyType.DoubleArray, (double[])obj);
+ if (type == typeof(char))
+ return new CLRIReferenceArrayImpl<char>(PropertyType.Char16Array, (char[])obj);
+ if (type == typeof(bool))
+ return new CLRIReferenceArrayImpl<bool>(PropertyType.BooleanArray, (bool[])obj);
+ if (type == typeof(Guid))
+ return new CLRIReferenceArrayImpl<Guid>(PropertyType.GuidArray, (Guid[])obj);
+ if (type == typeof(DateTimeOffset))
+ return new CLRIReferenceArrayImpl<DateTimeOffset>(PropertyType.DateTimeArray, (DateTimeOffset[])obj);
+ if (type == typeof(TimeSpan))
+ return new CLRIReferenceArrayImpl<TimeSpan>(PropertyType.TimeSpanArray, (TimeSpan[])obj);
+ if (type == typeof(Type))
+ { // Note: The array type will be System.Type, not System.RuntimeType
+ return new CLRIReferenceArrayImpl<Type>(PropertyType.OtherArray, (Type[])obj);
+ }
+
+ PropertyType? propType = null;
+ if (type == s_pointType)
+ {
+ propType = PropertyType.PointArray;
+ }
+ else if (type == s_rectType)
+ {
+ propType = PropertyType.RectArray;
+ }
+ else if (type == s_sizeType)
+ {
+ propType = PropertyType.SizeArray;
+ }
+ else if (type.IsValueType)
+ {
+ // note that KeyValuePair`2 is a reference type on the WinRT side so the array
+ // must be wrapped with CLRIReferenceArrayImpl<Object>
+ if (type.IsGenericType &&
+ type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>))
+ {
+ Object[] objArray = new Object[obj.Length];
+ for (int i = 0; i < objArray.Length; i++)
+ {
+ objArray[i] = obj.GetValue(i);
+ }
+ obj = objArray;
+ }
+ else
+ {
+ propType = PropertyType.OtherArray;
+ }
+ }
+ else if (typeof(Delegate).IsAssignableFrom(type))
+ {
+ propType = PropertyType.OtherArray;
+ }
+
+
+ if (propType.HasValue)
+ {
+ // All WinRT value type will be Property.Other
+ Type specificType = typeof(CLRIReferenceArrayImpl<>).MakeGenericType(type);
+ return Activator.CreateInstance(specificType, new Object[] { propType.Value, obj });
+ }
+ else
+ {
+ // All WinRT reference type (including arbitary managed type) will be PropertyType.ObjectArray
+ return new CLRIReferenceArrayImpl<Object>(PropertyType.InspectableArray, (Object[])obj);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs
new file mode 100644
index 0000000000..af1381c366
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ConstantSplittableMap.cs
@@ -0,0 +1,288 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// <summary>
+ /// This is a constant map aimed to efficiently support a Split operation (map decomposition).
+ /// A Split operation returns two non-overlapping, non-empty views of the existing map (or both
+ /// values are set to NULL). The two views returned should contain roughly the same number of elements.
+ /// This map is backed by a sorted array. Thus, split operations are O(1) and enumerations are fast;
+ /// however, look-up in the map are O(log n).
+ /// </summary>
+ /// <typeparam name="TKey">Type of objects that act as keys.</typeparam>
+ /// <typeparam name="TValue">Type of objects that act as entries / values.</typeparam>
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class ConstantSplittableMap<TKey, TValue> : IMapView<TKey, TValue>
+ {
+ private class KeyValuePairComparator : IComparer<KeyValuePair<TKey, TValue>>
+ {
+ private static readonly IComparer<TKey> keyComparator = Comparer<TKey>.Default;
+
+ public Int32 Compare(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
+ {
+ return keyComparator.Compare(x.Key, y.Key);
+ }
+ } // private class KeyValuePairComparator
+
+
+ private static readonly KeyValuePairComparator keyValuePairComparator = new KeyValuePairComparator();
+
+ private readonly KeyValuePair<TKey, TValue>[] items;
+ private readonly int firstItemIndex;
+ private readonly int lastItemIndex;
+
+ internal ConstantSplittableMap(IReadOnlyDictionary<TKey, TValue> data)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+ Contract.EndContractBlock();
+
+ this.firstItemIndex = 0;
+ this.lastItemIndex = data.Count - 1;
+ this.items = CreateKeyValueArray(data.Count, data.GetEnumerator());
+ }
+
+ internal ConstantSplittableMap(IMapView<TKey, TValue> data)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+
+ if (((UInt32)Int32.MaxValue) < data.Size)
+ {
+ Exception e = new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingDictionaryTooLarge"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ int size = (int)data.Size;
+
+ this.firstItemIndex = 0;
+ this.lastItemIndex = size - 1;
+ this.items = CreateKeyValueArray(size, data.GetEnumerator());
+ }
+
+
+ private ConstantSplittableMap(KeyValuePair<TKey, TValue>[] items, Int32 firstItemIndex, Int32 lastItemIndex)
+ {
+ this.items = items;
+ this.firstItemIndex = firstItemIndex;
+ this.lastItemIndex = lastItemIndex;
+ }
+
+
+ private KeyValuePair<TKey, TValue>[] CreateKeyValueArray(Int32 count, IEnumerator<KeyValuePair<TKey, TValue>> data)
+ {
+ KeyValuePair<TKey, TValue>[] kvArray = new KeyValuePair<TKey, TValue>[count];
+
+ Int32 i = 0;
+ while (data.MoveNext())
+ kvArray[i++] = data.Current;
+
+ Array.Sort(kvArray, keyValuePairComparator);
+
+ return kvArray;
+ }
+
+ private KeyValuePair<TKey, TValue>[] CreateKeyValueArray(Int32 count, IEnumerator<IKeyValuePair<TKey, TValue>> data)
+ {
+ KeyValuePair<TKey, TValue>[] kvArray = new KeyValuePair<TKey, TValue>[count];
+
+ Int32 i = 0;
+ while (data.MoveNext())
+ {
+ IKeyValuePair<TKey, TValue> current = data.Current;
+ kvArray[i++] = new KeyValuePair<TKey, TValue>(current.Key, current.Value);
+ }
+
+ Array.Sort(kvArray, keyValuePairComparator);
+
+ return kvArray;
+ }
+
+
+ public int Count {
+ get {
+ return lastItemIndex - firstItemIndex + 1;
+ }
+ }
+
+
+ // [CLSCompliant(false)]
+ public UInt32 Size {
+ get {
+ return (UInt32)(lastItemIndex - firstItemIndex + 1);
+ }
+ }
+
+
+ public TValue Lookup(TKey key)
+ {
+ TValue value;
+ bool found = TryGetValue(key, out value);
+
+ if (!found)
+ {
+ Exception e = new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ return value;
+ }
+
+
+ public bool HasKey(TKey key)
+ {
+ TValue value;
+ bool hasKey = TryGetValue(key, out value);
+ return hasKey;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<IKeyValuePair<TKey, TValue>>)this).GetEnumerator();
+ }
+
+ public IIterator<IKeyValuePair<TKey, TValue>> First()
+ {
+ return new EnumeratorToIteratorAdapter<IKeyValuePair<TKey, TValue>>(GetEnumerator());
+ }
+
+ public IEnumerator<IKeyValuePair<TKey, TValue>> GetEnumerator()
+ {
+ return new IKeyValuePairEnumerator(items, firstItemIndex, lastItemIndex);
+ }
+
+ public void Split(out IMapView<TKey, TValue> firstPartition, out IMapView<TKey, TValue> secondPartition)
+ {
+ if (Count < 2)
+ {
+ firstPartition = null;
+ secondPartition = null;
+ return;
+ }
+
+ int pivot = (Int32)(((Int64)firstItemIndex + (Int64)lastItemIndex) / (Int64)2);
+
+ firstPartition = new ConstantSplittableMap<TKey, TValue>(items, firstItemIndex, pivot);
+ secondPartition = new ConstantSplittableMap<TKey, TValue>(items, pivot + 1, lastItemIndex);
+ }
+
+ #region IReadOnlyDictionary members
+
+ public bool ContainsKey(TKey key)
+ {
+ KeyValuePair<TKey, TValue> searchKey = new KeyValuePair<TKey, TValue>(key, default(TValue));
+ int index = Array.BinarySearch(items, firstItemIndex, Count, searchKey, keyValuePairComparator);
+ return index >= 0;
+ }
+
+ public bool TryGetValue(TKey key, out TValue value)
+ {
+ KeyValuePair<TKey, TValue> searchKey = new KeyValuePair<TKey, TValue>(key, default(TValue));
+ int index = Array.BinarySearch(items, firstItemIndex, Count, searchKey, keyValuePairComparator);
+
+ if (index < 0)
+ {
+ value = default(TValue);
+ return false;
+ }
+
+ value = items[index].Value;
+ return true;
+ }
+
+ public TValue this[TKey key] {
+ get {
+ return Lookup(key);
+ }
+ }
+
+ public IEnumerable<TKey> Keys {
+ get {
+ throw new NotImplementedException("NYI");
+ }
+ }
+
+ public IEnumerable<TValue> Values {
+ get {
+ throw new NotImplementedException("NYI");
+ }
+ }
+
+ #endregion IReadOnlyDictionary members
+
+ #region IKeyValuePair Enumerator
+
+ [Serializable]
+ internal struct IKeyValuePairEnumerator : IEnumerator<IKeyValuePair<TKey, TValue>>
+ {
+ private KeyValuePair<TKey, TValue>[] _array;
+ private int _start;
+ private int _end;
+ private int _current;
+
+ internal IKeyValuePairEnumerator(KeyValuePair<TKey, TValue>[] items, int first, int end)
+ {
+ Contract.Requires(items != null);
+ Contract.Requires(first >= 0);
+ Contract.Requires(end >= 0);
+ Contract.Requires(first < items.Length);
+ Contract.Requires(end < items.Length);
+
+ _array = items;
+ _start = first;
+ _end = end;
+ _current = _start - 1;
+ }
+
+ public bool MoveNext()
+ {
+ if (_current < _end)
+ {
+ _current++;
+ return true;
+ }
+ return false;
+ }
+
+ public IKeyValuePair<TKey, TValue> Current {
+ get {
+ if (_current < _start) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumNotStarted));
+ if (_current > _end) throw new InvalidOperationException(Environment.GetResourceString(ResId.InvalidOperation_EnumEnded));
+ return new CLRIKeyValuePairImpl<TKey, TValue>(ref _array[_current]);
+ }
+ }
+
+ Object IEnumerator.Current {
+ get {
+ return Current;
+ }
+ }
+
+ void IEnumerator.Reset()
+ {
+ _current = _start - 1;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+
+ #endregion IKeyValuePair Enumerator
+
+ } // internal ConstantSplittableMap<TKey, TValue>
+
+} // namespace System.Runtime.InteropServices.WindowsRuntime
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
new file mode 100644
index 0000000000..04fe1bf9b2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/CustomPropertyImpl.cs
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Reflection;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.Serialization;
+using System.StubHelpers;
+using System.Globalization;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ //
+ // ICustomProperty implementation - basically a wrapper of PropertyInfo
+ //
+ internal sealed class CustomPropertyImpl : ICustomProperty
+ {
+ private PropertyInfo m_property;
+
+ //
+ // Constructor
+ //
+ public CustomPropertyImpl(PropertyInfo propertyInfo)
+ {
+ if (propertyInfo == null)
+ throw new ArgumentNullException("propertyInfo");
+
+ m_property = propertyInfo;
+ }
+
+ //
+ // ICustomProperty interface implementation
+ //
+
+ public string Name
+ {
+ get
+ {
+ return m_property.Name;
+ }
+ }
+
+ public bool CanRead
+ {
+ get
+ {
+ // Return false if the getter is not public
+ return m_property.GetGetMethod() != null;
+ }
+ }
+
+ public bool CanWrite
+ {
+ get
+ {
+ // Return false if the setter is not public
+ return m_property.GetSetMethod() != null;
+ }
+ }
+
+ public object GetValue(object target)
+ {
+ return InvokeInternal(target, null, true);
+ }
+
+ // Unlike normal .Net, Jupiter properties can have at most one indexer parameter. A null
+ // indexValue here means that the property has an indexer argument and its value is null.
+ public object GetValue(object target, object indexValue)
+ {
+ return InvokeInternal(target, new object[] { indexValue }, true);
+ }
+
+ public void SetValue(object target, object value)
+ {
+ InvokeInternal(target, new object[] { value }, false);
+ }
+
+ // Unlike normal .Net, Jupiter properties can have at most one indexer parameter. A null
+ // indexValue here means that the property has an indexer argument and its value is null.
+ public void SetValue(object target, object value, object indexValue)
+ {
+ InvokeInternal(target, new object[] { indexValue, value }, false);
+ }
+
+ [SecuritySafeCritical]
+ private object InvokeInternal(object target, object[] args, bool getValue)
+ {
+ // Forward to the right object if we are dealing with a proxy
+ IGetProxyTarget proxy = target as IGetProxyTarget;
+ if (proxy != null)
+ {
+ target = proxy.GetTarget();
+ }
+
+ // You can get PropertyInfo for properties with a private getter/public setter (or vice versa)
+ // even if you pass BindingFlags.Public only. And in this case, passing binding flags to
+ // GetValue/SetValue won't work as the default binder ignores those values
+ // Use GetGetMethod/GetSetMethod instead
+
+ // We get non-public accessors just so that we can throw the correct exception.
+ MethodInfo accessor = getValue ? m_property.GetGetMethod(true) : m_property.GetSetMethod(true);
+
+ if (accessor == null)
+ throw new ArgumentException(System.Environment.GetResourceString(getValue ? "Arg_GetMethNotFnd" : "Arg_SetMethNotFnd"));
+
+ if (!accessor.IsPublic)
+ throw new MethodAccessException(
+ String.Format(
+ CultureInfo.CurrentCulture,
+ Environment.GetResourceString("Arg_MethodAccessException_WithMethodName"),
+ accessor.ToString(),
+ accessor.DeclaringType.FullName));
+
+ RuntimeMethodInfo rtMethod = accessor as RuntimeMethodInfo;
+ if (rtMethod == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeMethodInfo"));
+
+ // We can safely skip access check because this is only used in full trust scenarios.
+ // And we have already verified that the property accessor is public.
+ Contract.Assert(AppDomain.CurrentDomain.PermissionSet.IsUnrestricted());
+ return rtMethod.UnsafeInvoke(target, BindingFlags.Default, null, args, null);
+ }
+
+ public Type Type
+ {
+ get
+ {
+ return m_property.PropertyType;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs
new file mode 100644
index 0000000000..c1586ee9ce
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryKeyCollection.cs
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class DictionaryKeyCollection<TKey, TValue> : ICollection<TKey>
+ {
+ private readonly IDictionary<TKey, TValue> dictionary;
+
+ public DictionaryKeyCollection(IDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ public void CopyTo(TKey[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Key;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ bool ICollection<TKey>.IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<TKey>.Add(TKey item)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_KeyCollectionSet"));
+ }
+
+ void ICollection<TKey>.Clear()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_KeyCollectionSet"));
+ }
+
+ public bool Contains(TKey item)
+ {
+ return dictionary.ContainsKey(item);
+ }
+
+ bool ICollection<TKey>.Remove(TKey item)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_KeyCollectionSet"));
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TKey>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TKey> GetEnumerator()
+ {
+ return new DictionaryKeyEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class DictionaryKeyCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class DictionaryKeyEnumerator<TKey, TValue> : IEnumerator<TKey>
+ {
+ private readonly IDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public DictionaryKeyEnumerator(IDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TKey>)this).Current; }
+ }
+
+ public TKey Current {
+ get { return enumeration.Current.Key; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class DictionaryKeyEnumerator<TKey, TValue>
+}
+
+// DictionaryKeyCollection.cs
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs
new file mode 100644
index 0000000000..fa021b7f3d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryToMapAdapter.cs
@@ -0,0 +1,118 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IMap`2 interface on managed
+ // objects that implement IDictionary`2. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not DictionaryToMapAdapter objects. Rather, they are of type
+ // IDictionary<K, V>. No actual DictionaryToMapAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IDictionary<K, V>".
+ internal sealed class DictionaryToMapAdapter
+ {
+ private DictionaryToMapAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // V Lookup(K key)
+ [SecurityCritical]
+ internal V Lookup<K, V>(K key)
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ V value;
+ bool keyFound = _this.TryGetValue(key, out value);
+
+ if (!keyFound)
+ {
+ Exception e = new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ return value;
+ }
+
+ // uint Size { get }
+ [SecurityCritical]
+ internal uint Size<K, V>()
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ return (uint)_this.Count;
+ }
+
+ // bool HasKey(K key)
+ [SecurityCritical]
+ internal bool HasKey<K, V>(K key)
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ return _this.ContainsKey(key);
+ }
+
+ // IMapView<K, V> GetView()
+ [SecurityCritical]
+ internal IReadOnlyDictionary<K, V> GetView<K, V>()
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ Contract.Assert(_this != null);
+
+ // Note: This dictionary is not really read-only - you could QI for a modifiable
+ // dictionary. We gain some perf by doing this. We believe this is acceptable.
+ IReadOnlyDictionary<K, V> roDictionary = _this as IReadOnlyDictionary<K, V>;
+ if (roDictionary == null)
+ {
+ roDictionary = new ReadOnlyDictionary<K, V>(_this);
+ }
+ return roDictionary;
+ }
+
+ // bool Insert(K key, V value)
+ [SecurityCritical]
+ internal bool Insert<K, V>(K key, V value)
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ bool replacing = _this.ContainsKey(key);
+ _this[key] = value;
+ return replacing;
+ }
+
+ // void Remove(K key)
+ [SecurityCritical]
+ internal void Remove<K, V>(K key)
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ bool removed = _this.Remove(key);
+
+ if (!removed)
+ {
+ Exception e = new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear<K, V>()
+ {
+ IDictionary<K, V> _this = JitHelpers.UnsafeCast<IDictionary<K, V>>(this);
+ _this.Clear();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs
new file mode 100644
index 0000000000..03e897a917
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/DictionaryValueCollection.cs
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+
+namespace System.Runtime.InteropServices.WindowsRuntime {
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class DictionaryValueCollection<TKey, TValue> : ICollection<TValue>
+ {
+ private readonly IDictionary<TKey, TValue> dictionary;
+
+ public DictionaryValueCollection(IDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ public void CopyTo(TValue[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Value;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ bool ICollection<TValue>.IsReadOnly {
+ get { return true; }
+ }
+
+ void ICollection<TValue>.Add(TValue item)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ValueCollectionSet"));
+ }
+
+ void ICollection<TValue>.Clear()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ValueCollectionSet"));
+ }
+
+ public bool Contains(TValue item)
+ {
+ EqualityComparer<TValue> comparer = EqualityComparer<TValue>.Default;
+ foreach (TValue value in this)
+ if (comparer.Equals(item, value))
+ return true;
+ return false;
+ }
+
+ bool ICollection<TValue>.Remove(TValue item)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_ValueCollectionSet"));
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TValue>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TValue> GetEnumerator()
+ {
+ return new DictionaryValueEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class DictionaryValueCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class DictionaryValueEnumerator<TKey, TValue> : IEnumerator<TValue>
+ {
+ private readonly IDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public DictionaryValueEnumerator(IDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TValue>)this).Current; }
+ }
+
+ public TValue Current {
+ get { return enumeration.Current.Value; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class DictionaryValueEnumerator<TKey, TValue>
+}
+
+// DictionaryValueCollection.cs
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs
new file mode 100644
index 0000000000..7329d31ae8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EnumeratorToIteratorAdapter.cs
@@ -0,0 +1,168 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IIterable`1 interface on managed
+ // objects that implement IEnumerable`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not EnumerableToIterableAdapter objects. Rather, they are of type
+ // IEnumerable<T>. No actual EnumerableToIterableAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IEnumerable<T>".
+ internal sealed class EnumerableToIterableAdapter
+ {
+ private EnumerableToIterableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // This method is invoked when First is called on a managed implementation of IIterable<T>.
+ [System.Security.SecurityCritical]
+ internal IIterator<T> First_Stub<T>()
+ {
+ IEnumerable<T> _this = JitHelpers.UnsafeCast<IEnumerable<T>>(this);
+ return new EnumeratorToIteratorAdapter<T>(_this.GetEnumerator());
+ }
+ }
+
+ internal sealed class EnumerableToBindableIterableAdapter
+ {
+ private EnumerableToBindableIterableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ internal sealed class NonGenericToGenericEnumerator : IEnumerator<object>
+ {
+ private IEnumerator enumerator;
+
+ public NonGenericToGenericEnumerator(IEnumerator enumerator)
+ { this.enumerator = enumerator; }
+
+ public object Current { get { return enumerator.Current; } }
+ public bool MoveNext() { return enumerator.MoveNext(); }
+ public void Reset() { enumerator.Reset(); }
+ public void Dispose() { }
+ }
+
+ // This method is invoked when First is called on a managed implementation of IBindableIterable.
+ [System.Security.SecurityCritical]
+ internal IBindableIterator First_Stub()
+ {
+ IEnumerable _this = JitHelpers.UnsafeCast<IEnumerable>(this);
+ return new EnumeratorToIteratorAdapter<object>(new NonGenericToGenericEnumerator(_this.GetEnumerator()) );
+ }
+ }
+
+ // Adapter class which holds a managed IEnumerator<T>, exposing it as a Windows Runtime IIterator<T>
+ internal sealed class EnumeratorToIteratorAdapter<T> : IIterator<T>, IBindableIterator
+ {
+ private IEnumerator<T> m_enumerator;
+ private bool m_firstItem = true;
+ private bool m_hasCurrent;
+
+ internal EnumeratorToIteratorAdapter(IEnumerator<T> enumerator)
+ {
+ Contract.Requires(enumerator != null);
+ m_enumerator = enumerator;
+ }
+
+ public T Current
+ {
+ get
+ {
+ // IEnumerator starts at item -1, while IIterators start at item 0. Therefore, if this is the
+ // first access to the iterator we need to advance to the first item.
+ if (m_firstItem)
+ {
+ m_firstItem = false;
+ MoveNext();
+ }
+
+ if (!m_hasCurrent)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, null);
+ }
+
+ return m_enumerator.Current;
+ }
+ }
+
+ object IBindableIterator.Current
+ {
+ get
+ {
+ return (object)((IIterator<T>)this).Current;
+ }
+ }
+
+ public bool HasCurrent
+ {
+ get
+ {
+ // IEnumerator starts at item -1, while IIterators start at item 0. Therefore, if this is the
+ // first access to the iterator we need to advance to the first item.
+ if (m_firstItem)
+ {
+ m_firstItem = false;
+ MoveNext();
+ }
+
+ return m_hasCurrent;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ try
+ {
+ m_hasCurrent = m_enumerator.MoveNext();
+ }
+ catch (InvalidOperationException e)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_CHANGED_STATE, e);
+ }
+
+ return m_hasCurrent;
+ }
+
+ public int GetMany(T[] items)
+ {
+ if (items == null)
+ {
+ return 0;
+ }
+
+ int index = 0;
+ while (index < items.Length && HasCurrent)
+ {
+ items[index] = Current;
+ MoveNext();
+ ++index;
+ }
+
+ if (typeof(T) == typeof(string))
+ {
+ string[] stringItems = items as string[];
+
+ // Fill the rest of the array with String.Empty to avoid marshaling failure
+ for (int i = index; i < items.Length; ++i)
+ stringItems[i] = String.Empty;
+ }
+
+ return index;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs
new file mode 100644
index 0000000000..e2b53277eb
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationToken.cs
@@ -0,0 +1,53 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // Event registration tokens are 64 bit opaque structures returned from WinRT style event adders, in order
+ // to signify a registration of a particular delegate to an event. The token's only real use is to
+ // unregister the same delgate from the event at a later time.
+ public struct EventRegistrationToken
+ {
+ internal ulong m_value;
+
+ internal EventRegistrationToken(ulong value)
+ {
+ m_value = value;
+ }
+
+ internal ulong Value
+ {
+ get { return m_value; }
+ }
+
+ public static bool operator ==(EventRegistrationToken left, EventRegistrationToken right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(EventRegistrationToken left, EventRegistrationToken right)
+ {
+ return !left.Equals(right);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is EventRegistrationToken))
+ {
+ return false;
+ }
+
+ return ((EventRegistrationToken)obj).Value == Value;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_value.GetHashCode();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
new file mode 100644
index 0000000000..03b17d9261
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/EventRegistrationTokenTable.cs
@@ -0,0 +1,255 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Threading;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // An event registration token table stores mappings from delegates to event tokens, in order to support
+ // sourcing WinRT style events from managed code.
+ public sealed class EventRegistrationTokenTable<T> where T : class
+ {
+ // Note this dictionary is also used as the synchronization object for this table
+ private Dictionary<EventRegistrationToken, T> m_tokens = new Dictionary<EventRegistrationToken, T>();
+
+ // Cached multicast delegate which will invoke all of the currently registered delegates. This
+ // will be accessed frequently in common coding paterns, so we don't want to calculate it repeatedly.
+ private volatile T m_invokeList;
+
+ public EventRegistrationTokenTable()
+ {
+ // T must be a delegate type, but we cannot constrain on being a delegate. Therefore, we'll do a
+ // static check at construction time
+ if (!typeof(Delegate).IsAssignableFrom(typeof(T)))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EventTokenTableRequiresDelegate", typeof(T)));
+ }
+ }
+
+ // The InvocationList property provides access to a delegate which will invoke every registered event handler
+ // in this table. If the property is set, the new value will replace any existing token registrations.
+ public T InvocationList
+ {
+ get
+ {
+ return m_invokeList;
+ }
+
+ set
+ {
+ lock (m_tokens)
+ {
+ // The value being set replaces any of the existing values
+ m_tokens.Clear();
+ m_invokeList = null;
+
+ if (value != null)
+ {
+ AddEventHandlerNoLock(value);
+ }
+ }
+ }
+ }
+
+ public EventRegistrationToken AddEventHandler(T handler)
+ {
+ // Windows Runtime allows null handlers. Assign those a token value of 0 for easy identity
+ if (handler == null)
+ {
+ return new EventRegistrationToken(0);
+ }
+
+ lock (m_tokens)
+ {
+ return AddEventHandlerNoLock(handler);
+ }
+ }
+
+ private EventRegistrationToken AddEventHandlerNoLock(T handler)
+ {
+ Contract.Requires(handler != null);
+
+ // Get a registration token, making sure that we haven't already used the value. This should be quite
+ // rare, but in the case it does happen, just keep trying until we find one that's unused.
+ EventRegistrationToken token = GetPreferredToken(handler);
+ while (m_tokens.ContainsKey(token))
+ {
+ token = new EventRegistrationToken(token.Value + 1);
+ }
+ m_tokens[token] = handler;
+
+ // Update the current invocation list to include the newly added delegate
+ Delegate invokeList = (Delegate)(object)m_invokeList;
+ invokeList = MulticastDelegate.Combine(invokeList, (Delegate)(object)handler);
+ m_invokeList = (T)(object)invokeList;
+
+ return token;
+ }
+
+ // Get the delegate associated with an event registration token if it exists. Additionally,
+ // remove the registration from the table at the same time. If the token is not registered,
+ // Extract returns null and does not modify the table.
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+ internal T ExtractHandler(EventRegistrationToken token)
+ {
+ T handler = null;
+ lock (m_tokens)
+ {
+ if (m_tokens.TryGetValue(token, out handler))
+ {
+ RemoveEventHandlerNoLock(token);
+ }
+ }
+
+ return handler;
+ }
+
+ // Generate a token that may be used for a particular event handler. We will frequently be called
+ // upon to look up a token value given only a delegate to start from. Therefore, we want to make
+ // an initial token value that is easily determined using only the delegate instance itself. Although
+ // in the common case this token value will be used to uniquely identify the handler, it is not
+ // the only possible token that can represent the handler.
+ //
+ // This means that both:
+ // * if there is a handler assigned to the generated initial token value, it is not necessarily
+ // this handler.
+ // * if there is no handler assigned to the generated initial token value, the handler may still
+ // be registered under a different token
+ //
+ // Effectively the only reasonable thing to do with this value is either to:
+ // 1. Use it as a good starting point for generating a token for handler
+ // 2. Use it as a guess to quickly see if the handler was really assigned this token value
+ private static EventRegistrationToken GetPreferredToken(T handler)
+ {
+ Contract.Requires(handler != null);
+
+ // We want to generate a token value that has the following properties:
+ // 1. is quickly obtained from the handler instance
+ // 2. uses bits in the upper 32 bits of the 64 bit value, in order to avoid bugs where code
+ // may assume the value is realy just 32 bits
+ // 3. uses bits in the bottom 32 bits of the 64 bit value, in order to ensure that code doesn't
+ // take a dependency on them always being 0.
+ //
+ // The simple algorithm chosen here is to simply assign the upper 32 bits the metadata token of the
+ // event handler type, and the lower 32 bits the hash code of the handler instance itself. Using the
+ // metadata token for the upper 32 bits gives us at least a small chance of being able to identify a
+ // totally corrupted token if we ever come across one in a minidump or other scenario.
+ //
+ // The hash code of a unicast delegate is not tied to the method being invoked, so in the case
+ // of a unicast delegate, the hash code of the target method is used instead of the full delegate
+ // hash code.
+ //
+ // While calculating this initial value will be somewhat more expensive than just using a counter
+ // for events that have few registrations, it will also gives us a shot at preventing unregistration
+ // from becoming an O(N) operation.
+ //
+ // We should feel free to change this algorithm as other requirements / optimizations become
+ // available. This implementation is sufficiently random that code cannot simply guess the value to
+ // take a dependency upon it. (Simply applying the hash-value algorithm directly won't work in the
+ // case of collisions, where we'll use a different token value).
+
+ uint handlerHashCode = 0;
+ Delegate[] invocationList = ((Delegate)(object)handler).GetInvocationList();
+ if (invocationList.Length == 1)
+ {
+ handlerHashCode = (uint)invocationList[0].Method.GetHashCode();
+ }
+ else
+ {
+ handlerHashCode = (uint)handler.GetHashCode();
+ }
+
+ ulong tokenValue = ((ulong)(uint)typeof(T).MetadataToken << 32) | handlerHashCode;
+ return new EventRegistrationToken(tokenValue);
+ }
+
+ public void RemoveEventHandler(EventRegistrationToken token)
+ {
+ // The 0 token is assigned to null handlers, so there's nothing to do
+ if (token.Value == 0)
+ {
+ return;
+ }
+
+ lock (m_tokens)
+ {
+ RemoveEventHandlerNoLock(token);
+ }
+ }
+
+ public void RemoveEventHandler(T handler)
+ {
+ // To match the Windows Runtime behaivor when adding a null handler, removing one is a no-op
+ if (handler == null)
+ {
+ return;
+ }
+
+ lock (m_tokens)
+ {
+ // Fast path - if the delegate is stored with its preferred token, then there's no need to do
+ // a full search of the table for it. Note that even if we find something stored using the
+ // preferred token value, it's possible we have a collision and another delegate was using that
+ // value. Therefore we need to make sure we really have the handler we want before taking the
+ // fast path.
+ EventRegistrationToken preferredToken = GetPreferredToken(handler);
+ T registeredHandler;
+ if (m_tokens.TryGetValue(preferredToken, out registeredHandler))
+ {
+ if (registeredHandler == handler)
+ {
+ RemoveEventHandlerNoLock(preferredToken);
+ return;
+ }
+ }
+
+ // Slow path - we didn't find the delegate with its preferred token, so we need to fall
+ // back to a search of the table
+ foreach (KeyValuePair<EventRegistrationToken, T> registration in m_tokens)
+ {
+ if (registration.Value == (T)(object)handler)
+ {
+ RemoveEventHandlerNoLock(registration.Key);
+
+ // If a delegate has been added multiple times to handle an event, then it
+ // needs to be removed the same number of times to stop handling the event.
+ // Stop after the first one we find.
+ return;
+ }
+ }
+
+ // Note that falling off the end of the loop is not an error, as removing a registration
+ // for a handler that is not currently registered is simply a no-op
+ }
+ }
+
+ private void RemoveEventHandlerNoLock(EventRegistrationToken token)
+ {
+ T handler;
+ if (m_tokens.TryGetValue(token, out handler))
+ {
+ m_tokens.Remove(token);
+
+ // Update the current invocation list to remove the delegate
+ Delegate invokeList = (Delegate)(object)m_invokeList;
+ invokeList = MulticastDelegate.Remove(invokeList, (Delegate)(object)handler);
+ m_invokeList = (T)(object)invokeList;
+ }
+ }
+
+ public static EventRegistrationTokenTable<T> GetOrCreateEventRegistrationTokenTable(ref EventRegistrationTokenTable<T> refEventTable)
+ {
+ if (refEventTable == null)
+ {
+ Interlocked.CompareExchange(ref refEventTable, new EventRegistrationTokenTable<T>(), null);
+ }
+ return refEventTable;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs
new file mode 100644
index 0000000000..0ce01f8653
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IActivationFactory.cs
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("00000035-0000-0000-C000-000000000046")]
+ [WindowsRuntimeImport]
+ public interface IActivationFactory
+ {
+ object ActivateInstance();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs
new file mode 100644
index 0000000000..847147ade8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IClosable.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+
+ // Local definition of Windows.Foundation.IClosable
+ [ComImport]
+ [Guid("30d5a829-7fa4-4026-83bb-d75bae4ea99e")]
+ [WindowsRuntimeImport]
+ internal interface IClosable
+ {
+ void Close();
+ }
+
+ // Adapter class - converts IClosable.Close calls to Disposable.Dispose
+ internal sealed class IDisposableToIClosableAdapter
+ {
+ private IDisposableToIClosableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ [SecurityCritical]
+ public void Close()
+ {
+ IDisposable _this = JitHelpers.UnsafeCast<IDisposable>(this);
+ _this.Dispose();
+ }
+ }
+
+ // Adapter class which converts IDisposable.Dispose calls into IClosable.Close
+ [SecurityCritical]
+ internal sealed class IClosableToIDisposableAdapter
+ {
+ private IClosableToIDisposableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ [SecurityCritical]
+ private void Dispose()
+ {
+ IClosable _this = JitHelpers.UnsafeCast<IClosable>(this);
+ _this.Close();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs
new file mode 100644
index 0000000000..88472a46b8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomProperty.cs
@@ -0,0 +1,52 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("30DA92C0-23E8-42A0-AE7C-734A0E5D2782")]
+ [WindowsRuntimeImport]
+ internal interface ICustomProperty
+ {
+ Type Type
+ {
+ [Pure]
+ get;
+ }
+
+ string Name
+ {
+ [Pure]
+ get;
+ }
+
+ [Pure]
+ object GetValue(object target);
+
+ void SetValue(object target, object value);
+
+ [Pure]
+ object GetValue(object target, object indexValue);
+
+ void SetValue(object target, object value, object indexValue);
+
+ bool CanWrite
+ {
+ [Pure]
+ get;
+ }
+
+ bool CanRead
+ {
+ [Pure]
+ get;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs
new file mode 100644
index 0000000000..143a33e4c7
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ICustomPropertyProvider.cs
@@ -0,0 +1,553 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.StubHelpers;
+using System.Reflection;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+
+ //
+ // ICustomProperty Implementation helpers
+ //
+ internal static class ICustomPropertyProviderImpl
+ {
+ //
+ // Creates a ICustomProperty implementation for Jupiter
+ // Called from ICustomPropertyProvider_GetProperty from within runtime
+ //
+ static internal ICustomProperty CreateProperty(object target, string propertyName)
+ {
+ Contract.Requires(target != null);
+ Contract.Requires(propertyName != null);
+
+ IGetProxyTarget proxy = target as IGetProxyTarget;
+ if (proxy != null)
+ target = proxy.GetTarget();
+
+ // Only return public instance/static properties
+ PropertyInfo propertyInfo = target.GetType().GetProperty(
+ propertyName,
+ BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);
+
+ if (propertyInfo == null)
+ return null;
+ else
+ return new CustomPropertyImpl(propertyInfo);
+ }
+
+ //
+ // Creates a ICustomProperty implementation for Jupiter
+ // Called from ICustomPropertyProvider_GetIndexedProperty from within runtime
+ //
+ [System.Security.SecurityCritical]
+ static internal unsafe ICustomProperty CreateIndexedProperty(object target, string propertyName, TypeNameNative *pIndexedParamType)
+ {
+ Contract.Requires(target != null);
+ Contract.Requires(propertyName != null);
+
+ Type indexedParamType = null;
+ SystemTypeMarshaler.ConvertToManaged(pIndexedParamType, ref indexedParamType);
+
+ return CreateIndexedProperty(target, propertyName, indexedParamType);
+ }
+
+ static internal ICustomProperty CreateIndexedProperty(object target, string propertyName, Type indexedParamType)
+ {
+ Contract.Requires(target != null);
+ Contract.Requires(propertyName != null);
+
+ IGetProxyTarget proxy = target as IGetProxyTarget;
+ if (proxy != null)
+ target = proxy.GetTarget();
+
+ // Only return public instance/static properties
+ PropertyInfo propertyInfo = target.GetType().GetProperty(
+ propertyName,
+ BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public,
+ null, // default binder
+ null, // ignore return type
+ new Type[] { indexedParamType }, // indexed parameter type
+ null // ignore type modifier
+ );
+
+ if (propertyInfo == null)
+ return null;
+ else
+ return new CustomPropertyImpl(propertyInfo);
+ }
+
+ [System.Security.SecurityCritical]
+ static internal unsafe void GetType(object target, TypeNameNative *pIndexedParamType)
+ {
+ IGetProxyTarget proxy = target as IGetProxyTarget;
+ if (proxy != null)
+ target = proxy.GetTarget();
+
+ SystemTypeMarshaler.ConvertToNative(target.GetType(), pIndexedParamType);
+ }
+ }
+
+ [Flags]
+ enum InterfaceForwardingSupport
+ {
+ None = 0,
+ IBindableVector = 0x1, // IBindableVector -> IBindableVector
+ IVector = 0x2, // IBindableVector -> IVector<T>
+ IBindableVectorView = 0x4, // IBindableVectorView -> IBindableVectorView
+ IVectorView = 0x8, // IBindableVectorView -> IVectorView<T>
+ IBindableIterableOrIIterable= 0x10 // IBindableIterable -> IBindableIterable/IIterable<T>
+ }
+
+ //
+ // Interface for data binding code (CustomPropertyImpl) to retreive the target object
+ // See CustomPropertyImpl.InvokeInternal for details
+ //
+ internal interface IGetProxyTarget
+ {
+ object GetTarget();
+ }
+
+ //
+ // Proxy that supports data binding on another object
+ //
+ // This serves two purposes:
+ //
+ // 1. Delegate data binding interfaces to another object
+ // Note that this proxy implements the native interfaces directly to avoid unnecessary overhead
+ // (such as the adapter code that addresses behavior differences between IBindableVector & List
+ // as well as simplify forwarding code (except for IEnumerable)
+ //
+ // 2. ICLRServices.CreateManagedReference will hand out ICCW* of a new instance of this object
+ // and will hold the other object alive
+ //
+ //
+ internal class ICustomPropertyProviderProxy<T1, T2> : IGetProxyTarget,
+ ICustomQueryInterface,
+ IEnumerable, // IBindableIterable -> IBindableIterable/IIterable<T>
+ IBindableVector, // IBindableVector -> IBindableVector/IVector<T>
+ IBindableVectorView // IBindableVectorView -> IBindableVectorView/IVectorView<T>
+ {
+ private object _target;
+ private InterfaceForwardingSupport _flags;
+
+ internal ICustomPropertyProviderProxy(object target, InterfaceForwardingSupport flags)
+ {
+ _target = target;
+ _flags = flags;
+ }
+
+ //
+ // Creates a new instance of ICustomPropertyProviderProxy<T1, T2> and assign appropriate
+ // flags
+ //
+ internal static object CreateInstance(object target)
+ {
+ InterfaceForwardingSupport supportFlags = InterfaceForwardingSupport.None;
+
+ //
+ // QI and figure out the right flags
+ //
+ if (target as IList != null)
+ supportFlags |= InterfaceForwardingSupport.IBindableVector;
+
+ // NOTE: We need to use the directed type here
+ // If we use IVector_Raw<T1> here, it derives from a different IIterable<T> which the runtime
+ // doesn't recognize, and therefore IEnumerable cast won't be able to take advantage of this QI
+ if (target as IList<T1> != null)
+ supportFlags |= InterfaceForwardingSupport.IVector;
+
+ if (target as IBindableVectorView != null)
+ supportFlags |= InterfaceForwardingSupport.IBindableVectorView;
+
+ // NOTE: We need to use the redirected type here
+ // If we use IVector_Raw<T1> here, it derives from a different IIterable<T> which the runtime
+ // doesn't recognize, and therefore IEnumerable cast won't be able to take advantage of this QI
+ if (target as IReadOnlyList<T2> != null)
+ supportFlags |= InterfaceForwardingSupport.IVectorView;
+
+ // Verify IEnumerable last because the first few QIs might succeed and we need
+ // IEnumerable cast to use that cache (instead of having ICustomPropertyProvider to
+ // forward it manually)
+ // For example, if we try to shoot in the dark by trying IVector<IInspectable> and it
+ // succeeded, IEnumerable needs to know that
+ if (target as IEnumerable != null)
+ supportFlags |= InterfaceForwardingSupport.IBindableIterableOrIIterable;
+
+ return new ICustomPropertyProviderProxy<T1, T2>(target, supportFlags);
+ }
+
+
+ //
+ // override ToString() to make sure callers get correct IStringable.ToString() behavior in native code
+ //
+ public override string ToString()
+ {
+ return WindowsRuntime.IStringableHelper.ToString(_target);
+ }
+
+ //
+ // IGetProxyTarget - unwraps the target object and use it for data binding
+ //
+ object IGetProxyTarget.GetTarget()
+ {
+ return _target;
+ }
+
+ //
+ // ICustomQueryInterface methods
+ //
+ [System.Security.SecurityCritical]
+ public CustomQueryInterfaceResult GetInterface([In]ref Guid iid, out IntPtr ppv)
+ {
+ ppv = IntPtr.Zero;
+
+ if (iid == typeof(IBindableIterable).GUID)
+ {
+ // Reject the QI if target doesn't implement IEnumerable
+ if ((_flags & (InterfaceForwardingSupport.IBindableIterableOrIIterable)) == 0)
+ return CustomQueryInterfaceResult.Failed;
+ }
+
+ if (iid == typeof(IBindableVector).GUID)
+ {
+ // Reject the QI if target doesn't implement IBindableVector/IVector
+ if ((_flags & (InterfaceForwardingSupport.IBindableVector | InterfaceForwardingSupport.IVector)) == 0)
+ return CustomQueryInterfaceResult.Failed;
+ }
+
+ if (iid == typeof(IBindableVectorView).GUID)
+ {
+ // Reject the QI if target doesn't implement IBindableVectorView/IVectorView
+ if ((_flags & (InterfaceForwardingSupport.IBindableVectorView | InterfaceForwardingSupport.IVectorView)) == 0)
+ return CustomQueryInterfaceResult.Failed;
+ }
+
+ return CustomQueryInterfaceResult.NotHandled;
+ }
+
+ //
+ // IEnumerable methods
+ //
+ public IEnumerator GetEnumerator()
+ {
+ return ((IEnumerable)_target).GetEnumerator();
+ }
+
+ //
+ // IBindableVector implementation (forwards to IBindableVector / IVector<T>)
+ //
+ [Pure]
+ object IBindableVector.GetAt(uint index)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ return bindableVector.GetAt(index);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ return GetVectorOfT().GetAt(index);
+ }
+ }
+
+ [Pure]
+ uint IBindableVector.Size
+ {
+ get
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ return bindableVector.Size;
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ return GetVectorOfT().Size;
+ }
+ }
+ }
+
+ [Pure]
+ IBindableVectorView IBindableVector.GetView()
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ return bindableVector.GetView();
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ return new IVectorViewToIBindableVectorViewAdapter<T1>(GetVectorOfT().GetView());
+ }
+ }
+
+ private sealed class IVectorViewToIBindableVectorViewAdapter<T> : IBindableVectorView
+ {
+ private IVectorView<T> _vectorView;
+
+ public IVectorViewToIBindableVectorViewAdapter(IVectorView<T> vectorView)
+ {
+ this._vectorView = vectorView;
+ }
+
+ [Pure]
+ object IBindableVectorView.GetAt(uint index)
+ {
+ return _vectorView.GetAt(index);
+ }
+
+ [Pure]
+ uint IBindableVectorView.Size
+ {
+ get
+ {
+ return _vectorView.Size;
+ }
+ }
+
+ [Pure]
+ bool IBindableVectorView.IndexOf(object value, out uint index)
+ {
+ return _vectorView.IndexOf(ConvertTo<T>(value), out index);
+ }
+
+ IBindableIterator IBindableIterable.First()
+ {
+ return new IteratorOfTToIteratorAdapter<T>(_vectorView.First());
+ }
+
+ }
+
+ [Pure]
+ bool IBindableVector.IndexOf(object value, out uint index)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ return bindableVector.IndexOf(value, out index);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ return GetVectorOfT().IndexOf(ConvertTo<T1>(value), out index);
+ }
+ }
+
+ void IBindableVector.SetAt(uint index, object value)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.SetAt(index, value);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().SetAt(index, ConvertTo<T1>(value));
+ }
+ }
+
+ void IBindableVector.InsertAt(uint index, object value)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.InsertAt(index, value);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().InsertAt(index, ConvertTo<T1>(value));
+ }
+ }
+
+ void IBindableVector.RemoveAt(uint index)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.RemoveAt(index);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().RemoveAt(index);
+ }
+ }
+
+ void IBindableVector.Append(object value)
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.Append(value);
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().Append(ConvertTo<T1>(value));
+ }
+ }
+
+ void IBindableVector.RemoveAtEnd()
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.RemoveAtEnd();
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().RemoveAtEnd();
+ }
+ }
+
+ void IBindableVector.Clear()
+ {
+ IBindableVector bindableVector = GetIBindableVectorNoThrow();
+ if (bindableVector != null)
+ {
+ // IBindableVector -> IBindableVector
+ bindableVector.Clear();
+ }
+ else
+ {
+ // IBindableVector -> IVector<T>
+ GetVectorOfT().Clear();
+ }
+ }
+
+ [SecuritySafeCritical]
+ private IBindableVector GetIBindableVectorNoThrow()
+ {
+ if ((_flags & InterfaceForwardingSupport.IBindableVector) != 0)
+ return JitHelpers.UnsafeCast<IBindableVector>(_target);
+ else
+ return null;
+ }
+
+ [SecuritySafeCritical]
+ private IVector_Raw<T1> GetVectorOfT()
+ {
+ if ((_flags & InterfaceForwardingSupport.IVector) != 0)
+ return JitHelpers.UnsafeCast<IVector_Raw<T1>>(_target);
+ else
+ throw new InvalidOperationException(); // We should not go down this path, unless Jupiter pass this out to managed code
+ // and managed code use reflection to do the cast
+ }
+
+ //
+ // IBindableVectorView implementation (forwarding to IBindableVectorView or IVectorView<T>)
+ //
+ [Pure]
+ object IBindableVectorView.GetAt(uint index)
+ {
+ IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow();
+ if (bindableVectorView != null)
+ return bindableVectorView.GetAt(index);
+ else
+ return GetVectorViewOfT().GetAt(index);
+ }
+
+ [Pure]
+ uint IBindableVectorView.Size
+ {
+ get
+ {
+ IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow();
+ if (bindableVectorView != null)
+ return bindableVectorView.Size;
+ else
+ return GetVectorViewOfT().Size;
+ }
+ }
+
+ [Pure]
+ bool IBindableVectorView.IndexOf(object value, out uint index)
+ {
+ IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow();
+ if (bindableVectorView != null)
+ return bindableVectorView.IndexOf(value, out index);
+ else
+ return GetVectorViewOfT().IndexOf(ConvertTo<T2>(value), out index);
+ }
+
+ IBindableIterator IBindableIterable.First()
+ {
+ IBindableVectorView bindableVectorView = GetIBindableVectorViewNoThrow();
+ if (bindableVectorView != null)
+ return bindableVectorView.First();
+ else
+ return new IteratorOfTToIteratorAdapter<T2>(GetVectorViewOfT().First());
+ }
+
+ private sealed class IteratorOfTToIteratorAdapter<T> : IBindableIterator
+ {
+ private IIterator<T> _iterator;
+
+ public IteratorOfTToIteratorAdapter(IIterator<T> iterator)
+ { this._iterator = iterator; }
+
+ public bool HasCurrent { get { return _iterator.HasCurrent; } }
+ public object Current { get { return (object)_iterator.Current; } }
+ public bool MoveNext() { return _iterator.MoveNext(); }
+ }
+
+ [SecuritySafeCritical]
+ private IBindableVectorView GetIBindableVectorViewNoThrow()
+ {
+ if ((_flags & InterfaceForwardingSupport.IBindableVectorView) != 0)
+ return JitHelpers.UnsafeCast<IBindableVectorView>(_target);
+ else
+ return null;
+ }
+
+ [SecuritySafeCritical]
+ private IVectorView<T2> GetVectorViewOfT()
+ {
+ if ((_flags & InterfaceForwardingSupport.IVectorView) != 0)
+ return JitHelpers.UnsafeCast<IVectorView<T2>>(_target);
+ else
+ throw new InvalidOperationException(); // We should not go down this path, unless Jupiter pass this out to managed code
+ // and managed code use reflection to do the cast
+ }
+
+ //
+ // Convert to type T
+ //
+ private static T ConvertTo<T>(object value)
+ {
+ // Throw ArgumentNullException if value is null (otherwise we'll throw NullReferenceException
+ // when casting value to T)
+ ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+
+ // No coersion support needed. If we need coersion later, this is the place
+ return (T) value;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs
new file mode 100644
index 0000000000..dbf4771cf6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterable.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+// Windows.Foundation.Collections.IIterable`1 cannot be referenced from managed code because it's hidden
+// by the metadata adapter. We redeclare the interface manually to be able to talk to native WinRT objects.
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("faa585ea-6214-4217-afda-7f46de5869b3")]
+ [WindowsRuntimeImport]
+ internal interface IIterable<T> : IEnumerable<T>
+ {
+ [Pure]
+ IIterator<T> First();
+ }
+
+ [ComImport]
+ [Guid("036d2c08-df29-41af-8aa2-d774be62ba6f")]
+ [WindowsRuntimeImport]
+ internal interface IBindableIterable
+ {
+ [Pure]
+ IBindableIterator First();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs
new file mode 100644
index 0000000000..83817494df
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IIterator.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [WindowsRuntimeImport]
+ [Guid("6a79e863-4300-459a-9966-cbb660963ee1")]
+ internal interface IIterator<T>
+ {
+ [Pure]
+ T Current
+ {
+ get;
+ }
+
+ [Pure]
+ bool HasCurrent
+ {
+ get;
+ }
+
+ bool MoveNext();
+
+ [Pure]
+ int GetMany([Out] T[] items);
+ }
+
+ [ComImport]
+ [WindowsRuntimeImport]
+ [Guid("6a1d6c07-076d-49f2-8314-f52c9c9a8331")]
+ internal interface IBindableIterator
+ {
+ [Pure]
+ object Current
+ {
+ get;
+ }
+
+ [Pure]
+ bool HasCurrent
+ {
+ get;
+ }
+
+ bool MoveNext();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs
new file mode 100644
index 0000000000..8160e6afc9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMap.cs
@@ -0,0 +1,59 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+// Windows.Foundation.Collections.IMap`2, IMapView`2, and IKeyValuePair`2 cannot be referenced from
+// managed code because they're hidden by the metadata adapter. We redeclare the interfaces manually
+// to be able to talk to native WinRT objects.
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("3c2925fe-8519-45c1-aa79-197b6718c1c1")]
+ [WindowsRuntimeImport]
+ internal interface IMap<K, V> : IIterable<IKeyValuePair<K, V>>
+ {
+ [Pure]
+ V Lookup(K key);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ bool HasKey(K key);
+ [Pure]
+ IReadOnlyDictionary<K, V> GetView(); // Really an IMapView<K, V>
+ bool Insert(K key, V value);
+ void Remove(K key);
+ void Clear();
+ }
+
+ [ComImport]
+ [Guid("e480ce40-a338-4ada-adcf-272272e48cb9")]
+ [WindowsRuntimeImport]
+ internal interface IMapView<K, V> : IIterable<IKeyValuePair<K, V>>
+ {
+ [Pure]
+ V Lookup(K key);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ bool HasKey(K key);
+ [Pure]
+ void Split(out IMapView<K, V> first, out IMapView<K, V> second);
+ }
+
+ [ComImport]
+ [Guid("02b51929-c1c4-4a7e-8940-0312b5c18500")]
+ [WindowsRuntimeImport]
+ internal interface IKeyValuePair<K, V>
+ {
+ [Pure]
+ K Key { get; }
+ [Pure]
+ V Value { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
new file mode 100644
index 0000000000..3600a3ae70
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IMapViewToIReadOnlyDictionaryAdapter.cs
@@ -0,0 +1,324 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IReadOnlyDictionary`2 interface on WinRT
+ // objects that support IMapView`2. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IMapViewToIReadOnlyDictionaryAdapter objects. Rather, they are of type
+ // IMapView<K, V>. No actual IMapViewToIReadOnlyDictionaryAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IMapView<K, V>".
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class IMapViewToIReadOnlyDictionaryAdapter
+ {
+ private IMapViewToIReadOnlyDictionaryAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // V this[K key] { get }
+ [SecurityCritical]
+ internal V Indexer_Get<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+ Contract.EndContractBlock();
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ return Lookup(_this, key);
+ }
+
+ // IEnumerable<K> Keys { get }
+ [SecurityCritical]
+ internal IEnumerable<K> Keys<K, V>()
+ {
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ IReadOnlyDictionary<K, V> roDictionary = (IReadOnlyDictionary<K, V>)_this;
+ return new ReadOnlyDictionaryKeyCollection<K, V>(roDictionary);
+ }
+
+ // IEnumerable<V> Values { get }
+ [SecurityCritical]
+ internal IEnumerable<V> Values<K, V>()
+ {
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ IReadOnlyDictionary<K, V> roDictionary = (IReadOnlyDictionary<K, V>)_this;
+ return new ReadOnlyDictionaryValueCollection<K, V>(roDictionary);
+ }
+
+ // bool ContainsKey(K key)
+ [Pure]
+ [SecurityCritical]
+ internal bool ContainsKey<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+ return _this.HasKey(key);
+ }
+
+ // bool TryGetValue(TKey key, out TValue value)
+ [SecurityCritical]
+ internal bool TryGetValue<K, V>(K key, out V value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMapView<K, V> _this = JitHelpers.UnsafeCast<IMapView<K, V>>(this);
+
+ // It may be faster to call HasKey then Lookup. On failure, we would otherwise
+ // throw an exception from Lookup.
+ if (!_this.HasKey(key))
+ {
+ value = default(V);
+ return false;
+ }
+
+ try
+ {
+ value = _this.Lookup(key);
+ return true;
+ }
+ catch (Exception ex) // Still may hit this case due to a race condition
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ {
+ value = default(V);
+ return false;
+ }
+ throw;
+ }
+ }
+
+ #region Helpers
+
+ private static V Lookup<K, V>(IMapView<K, V> _this, K key)
+ {
+ Contract.Requires(null != key);
+
+ try
+ {
+ return _this.Lookup(key);
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ throw;
+ }
+ }
+
+ #endregion Helpers
+ }
+
+ // Note: One day we may make these return IReadOnlyCollection<T>
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class ReadOnlyDictionaryKeyCollection<TKey, TValue> : IEnumerable<TKey>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+
+ public ReadOnlyDictionaryKeyCollection(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ /*
+ public void CopyTo(TKey[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Key;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ public bool Contains(TKey item)
+ {
+ return dictionary.ContainsKey(item);
+ }
+ */
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TKey>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TKey> GetEnumerator()
+ {
+ return new ReadOnlyDictionaryKeyEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class ReadOnlyDictionaryKeyCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class ReadOnlyDictionaryKeyEnumerator<TKey, TValue> : IEnumerator<TKey>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public ReadOnlyDictionaryKeyEnumerator(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TKey>)this).Current; }
+ }
+
+ public TKey Current {
+ get { return enumeration.Current.Key; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class ReadOnlyDictionaryKeyEnumerator<TKey, TValue>
+
+
+ [Serializable]
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class ReadOnlyDictionaryValueCollection<TKey, TValue> : IEnumerable<TValue>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+
+ public ReadOnlyDictionaryValueCollection(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ }
+
+ /*
+ public void CopyTo(TValue[] array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+ if (array.Length <= index && this.Count > 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_IndexOutOfRangeException"));
+ if (array.Length - index < dictionary.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ int i = index;
+ foreach (KeyValuePair<TKey, TValue> mapping in dictionary)
+ {
+ array[i++] = mapping.Value;
+ }
+ }
+
+ public int Count {
+ get { return dictionary.Count; }
+ }
+
+ public bool Contains(TValue item)
+ {
+ EqualityComparer<TValue> comparer = EqualityComparer<TValue>.Default;
+ foreach (TValue value in this)
+ if (comparer.Equals(item, value))
+ return true;
+ return false;
+ }
+ */
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ((IEnumerable<TValue>)this).GetEnumerator();
+ }
+
+ public IEnumerator<TValue> GetEnumerator()
+ {
+ return new ReadOnlyDictionaryValueEnumerator<TKey, TValue>(dictionary);
+ }
+ } // public class ReadOnlyDictionaryValueCollection<TKey, TValue>
+
+
+ [Serializable]
+ internal sealed class ReadOnlyDictionaryValueEnumerator<TKey, TValue> : IEnumerator<TValue>
+ {
+ private readonly IReadOnlyDictionary<TKey, TValue> dictionary;
+ private IEnumerator<KeyValuePair<TKey, TValue>> enumeration;
+
+ public ReadOnlyDictionaryValueEnumerator(IReadOnlyDictionary<TKey, TValue> dictionary)
+ {
+ if (dictionary == null)
+ throw new ArgumentNullException("dictionary");
+
+ this.dictionary = dictionary;
+ this.enumeration = dictionary.GetEnumerator();
+ }
+
+ void IDisposable.Dispose()
+ {
+ enumeration.Dispose();
+ }
+
+ public bool MoveNext()
+ {
+ return enumeration.MoveNext();
+ }
+
+ Object IEnumerator.Current {
+ get { return ((IEnumerator<TValue>)this).Current; }
+ }
+
+ public TValue Current {
+ get { return enumeration.Current.Value; }
+ }
+
+ public void Reset()
+ {
+ enumeration = dictionary.GetEnumerator();
+ }
+ } // class ReadOnlyDictionaryValueEnumerator<TKey, TValue>
+
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs
new file mode 100644
index 0000000000..4065406dfa
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IPropertyValue.cs
@@ -0,0 +1,171 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("4bd682dd-7554-40e9-9a9b-82654ede7e62")]
+ [WindowsRuntimeImport]
+ internal interface IPropertyValue
+ {
+ PropertyType Type
+ {
+ [Pure]
+ get;
+ }
+
+ bool IsNumericScalar
+ {
+ [Pure]
+ get;
+ }
+
+ [Pure]
+ Byte GetUInt8();
+
+ [Pure]
+ Int16 GetInt16();
+
+ [Pure]
+ UInt16 GetUInt16();
+
+ [Pure]
+ Int32 GetInt32();
+
+ [Pure]
+ UInt32 GetUInt32();
+
+ [Pure]
+ Int64 GetInt64();
+
+ [Pure]
+ UInt64 GetUInt64();
+
+ [Pure]
+ Single GetSingle();
+
+ [Pure]
+ Double GetDouble();
+
+ [Pure]
+ char GetChar16();
+
+ [Pure]
+ Boolean GetBoolean();
+
+ [Pure]
+ String GetString();
+
+ [Pure]
+ Guid GetGuid();
+
+ [Pure]
+ DateTimeOffset GetDateTime();
+
+ [Pure]
+ TimeSpan GetTimeSpan();
+
+ [Pure]
+ Point GetPoint();
+
+ [Pure]
+ Size GetSize();
+
+ [Pure]
+ Rect GetRect();
+
+ [Pure]
+ Byte[] GetUInt8Array();
+
+ [Pure]
+ Int16[] GetInt16Array();
+
+ [Pure]
+ UInt16[] GetUInt16Array();
+
+ [Pure]
+ Int32[] GetInt32Array();
+
+ [Pure]
+ UInt32[] GetUInt32Array();
+
+ [Pure]
+ Int64[] GetInt64Array();
+
+ [Pure]
+ UInt64[] GetUInt64Array();
+
+ [Pure]
+ Single[] GetSingleArray();
+
+ [Pure]
+ Double[] GetDoubleArray();
+
+ [Pure]
+ char[] GetChar16Array();
+
+ [Pure]
+ Boolean[] GetBooleanArray();
+
+ [Pure]
+ String[] GetStringArray();
+
+ [Pure]
+ object[] GetInspectableArray();
+
+ [Pure]
+ Guid[] GetGuidArray();
+
+ [Pure]
+ DateTimeOffset[] GetDateTimeArray();
+
+ [Pure]
+ TimeSpan[] GetTimeSpanArray();
+
+ [Pure]
+ Point[] GetPointArray();
+
+ [Pure]
+ Size[] GetSizeArray();
+
+ [Pure]
+ Rect[] GetRectArray();
+ }
+
+ // Specify size directly instead of fields to avoid warnings
+ [StructLayoutAttribute(LayoutKind.Sequential, Size=8)]
+ [WindowsRuntimeImport]
+ internal struct Point
+ {
+
+ // float X;
+ // float Y;
+ }
+
+ // Specify size directly instead of fields to avoid warnings
+ [StructLayoutAttribute(LayoutKind.Sequential, Size=8)]
+ [WindowsRuntimeImport]
+ internal struct Size
+ {
+
+ // float Width;
+ // float Height;
+ }
+
+ // Specify size directly instead of fields to avoid warnings
+ [StructLayoutAttribute(LayoutKind.Sequential, Size=16)]
+ [WindowsRuntimeImport]
+ internal struct Rect
+ {
+ // float X;
+ // float Y;
+ // float Width;
+ // float Height;
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs
new file mode 100644
index 0000000000..d57f8f1f46
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyDictionaryToIMapViewAdapter.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IMapView`2 interface on managed
+ // objects that implement IReadOnlyDictionary`2. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IReadOnlyDictionaryToIMapViewAdapter objects. Rather, they are of type
+ // IReadOnlyDictionary<K, V>. No actual IReadOnlyDictionaryToIMapViewAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IReadOnlyDictionary<K, V>".
+ [DebuggerDisplay("Size = {Size}")]
+ internal sealed class IReadOnlyDictionaryToIMapViewAdapter
+ {
+ private IReadOnlyDictionaryToIMapViewAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // V Lookup(K key)
+ [SecurityCritical]
+ internal V Lookup<K, V>(K key)
+ {
+ IReadOnlyDictionary<K, V> _this = JitHelpers.UnsafeCast<IReadOnlyDictionary<K, V>>(this);
+ V value;
+ bool keyFound = _this.TryGetValue(key, out value);
+
+ if (!keyFound)
+ {
+ Exception e = new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ return value;
+ }
+
+ // uint Size { get }
+ [SecurityCritical]
+ internal uint Size<K, V>()
+ {
+ IReadOnlyDictionary<K, V> _this = JitHelpers.UnsafeCast<IReadOnlyDictionary<K, V>>(this);
+ return (uint)_this.Count;
+ }
+
+ // bool HasKey(K key)
+ [SecurityCritical]
+ internal bool HasKey<K, V>(K key)
+ {
+ IReadOnlyDictionary<K, V> _this = JitHelpers.UnsafeCast<IReadOnlyDictionary<K, V>>(this);
+ return _this.ContainsKey(key);
+ }
+
+ // void Split(out IMapView<K, V> first, out IMapView<K, V> second)
+ [SecurityCritical]
+ internal void Split<K, V>(out IMapView<K, V> first, out IMapView<K, V> second)
+ {
+ IReadOnlyDictionary<K, V> _this = JitHelpers.UnsafeCast<IReadOnlyDictionary<K, V>>(this);
+
+ if (_this.Count < 2) {
+ first = null;
+ second = null;
+ return;
+ }
+
+ ConstantSplittableMap<K, V> splittableMap = _this as ConstantSplittableMap<K, V>;
+
+ if (splittableMap == null)
+ splittableMap = new ConstantSplittableMap<K, V>(_this);
+
+ splittableMap.Split(out first, out second);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs
new file mode 100644
index 0000000000..95780bcb13
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReadOnlyListToIVectorViewAdapter.cs
@@ -0,0 +1,141 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IVectorView`1 interface on managed
+ // objects that implement IReadOnlyList`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IReadOnlyListToIVectorViewAdapter objects. Rather, they are of type
+ // IReadOnlyList<T>. No actual IReadOnlyListToIVectorViewAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IReadOnlyList<T>".
+ [DebuggerDisplay("Size = {Size}")]
+ internal sealed class IReadOnlyListToIVectorViewAdapter
+ {
+ private IReadOnlyListToIVectorViewAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // T GetAt(uint index)
+ [SecurityCritical]
+ internal T GetAt<T>(uint index)
+ {
+ IReadOnlyList<T> _this = JitHelpers.UnsafeCast<IReadOnlyList<T>>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ return _this[(int) index];
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ ex.SetErrorCode(__HResults.E_BOUNDS);
+ throw;
+ }
+ }
+
+ // uint Size { get }
+ [SecurityCritical]
+ internal uint Size<T>()
+ {
+ IReadOnlyList<T> _this = JitHelpers.UnsafeCast<IReadOnlyList<T>>(this);
+ return (uint)_this.Count;
+ }
+
+ // bool IndexOf(T value, out uint index)
+ [SecurityCritical]
+ internal bool IndexOf<T>(T value, out uint index)
+ {
+ IReadOnlyList<T> _this = JitHelpers.UnsafeCast<IReadOnlyList<T>>(this);
+
+ int ind = -1;
+ int max = _this.Count;
+ for (int i = 0; i < max; i++)
+ {
+ if (EqualityComparer<T>.Default.Equals(value, _this[i]))
+ {
+ ind = i;
+ break;
+ }
+ }
+
+ if (-1 == ind)
+ {
+ index = 0;
+ return false;
+ }
+
+ index = (uint)ind;
+ return true;
+ }
+
+ // uint GetMany(uint startIndex, T[] items)
+ [SecurityCritical]
+ internal uint GetMany<T>(uint startIndex, T[] items)
+ {
+ IReadOnlyList<T> _this = JitHelpers.UnsafeCast<IReadOnlyList<T>>(this);
+
+ // REX spec says "calling GetMany with startIndex equal to the length of the vector
+ // (last valid index + 1) and any specified capacity will succeed and return zero actual
+ // elements".
+ if (startIndex == _this.Count)
+ return 0;
+
+ EnsureIndexInt32(startIndex, _this.Count);
+
+ if (items == null)
+ {
+ return 0;
+ }
+
+ uint itemCount = Math.Min((uint)items.Length, (uint)_this.Count - startIndex);
+
+ for (uint i = 0; i < itemCount; ++i)
+ {
+ items[i] = _this[(int)(i + startIndex)];
+ }
+
+ if (typeof(T) == typeof(string))
+ {
+ string[] stringItems = items as string[];
+
+ // Fill in the rest of the array with String.Empty to avoid marshaling failure
+ for (uint i = itemCount; i < items.Length; ++i)
+ stringItems[i] = String.Empty;
+ }
+
+ return itemCount;
+ }
+
+ #region Helpers
+
+ private static void EnsureIndexInt32(uint index, int listCapacity)
+ {
+ // We use '<=' and not '<' because Int32.MaxValue == index would imply
+ // that Size > Int32.MaxValue:
+ if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity)
+ {
+ Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+ }
+
+ #endregion Helpers
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs
new file mode 100644
index 0000000000..d0101dafc9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IReference.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("61c17706-2d65-11e0-9ae8-d48564015472")]
+ [WindowsRuntimeImport]
+ // Note that ideally, T should be constrained to be a value type. However, Windows uses IReference<HSTRING>
+ // and the projection may not be exactly pretty.
+ internal interface IReference<T> : IPropertyValue
+ {
+ T Value { get; }
+ }
+
+ [ComImport]
+ [Guid("61c17707-2d65-11e0-9ae8-d48564015472")]
+ [WindowsRuntimeImport]
+ // T can be any WinRT-compatible type, including reference types.
+ internal interface IReferenceArray<T> : IPropertyValue
+ {
+ T[] Value { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs
new file mode 100644
index 0000000000..48bcc4f618
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IRestrictedErrorInfo.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+#if FEATURE_CORECLR
+ [System.Runtime.CompilerServices.FriendAccessAllowed]
+#endif
+ [ComImport]
+ [Guid("82BA7092-4C88-427D-A7BC-16DD93FEB67E")]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ internal interface IRestrictedErrorInfo
+ {
+ void GetErrorDetails([MarshalAs(UnmanagedType.BStr)] out string description,
+ out int error,
+ [MarshalAs(UnmanagedType.BStr)] out string restrictedDescription,
+ [MarshalAs(UnmanagedType.BStr)] out string capabilitySid);
+
+ void GetReference([MarshalAs(UnmanagedType.BStr)] out string reference);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs
new file mode 100644
index 0000000000..a77ff005b9
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVector.cs
@@ -0,0 +1,113 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+// Windows.Foundation.Collections.IVector`1 and IVectorView`1 cannot be referenced from managed
+// code because they're hidden by the metadata adapter. We redeclare the interfaces manually
+// to be able to talk to native WinRT objects.
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("913337e9-11a1-4345-a3a2-4e7f956e222d")]
+ [WindowsRuntimeImport]
+ internal interface IVector<T> : IIterable<T>
+ {
+ [Pure]
+ T GetAt(uint index);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ IReadOnlyList<T> GetView(); // Really an IVectorView<T>.
+ [Pure]
+ bool IndexOf(T value, out uint index);
+ void SetAt(uint index, T value);
+ void InsertAt(uint index, T value);
+ void RemoveAt(uint index);
+ void Append(T value);
+ void RemoveAtEnd();
+ void Clear();
+ [Pure]
+ uint GetMany(uint startIndex, [Out] T[] items);
+ void ReplaceAll(T[] items);
+ }
+
+ // Same as IVector - the only difference is that GetView returns IVectorView<T>
+ [ComImport]
+ [Guid("913337e9-11a1-4345-a3a2-4e7f956e222d")]
+ [WindowsRuntimeImport]
+ internal interface IVector_Raw<T> : IIterable<T>
+ {
+ [Pure]
+ T GetAt(uint index);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ IVectorView<T> GetView();
+ [Pure]
+ bool IndexOf(T value, out uint index);
+ void SetAt(uint index, T value);
+ void InsertAt(uint index, T value);
+ void RemoveAt(uint index);
+ void Append(T value);
+ void RemoveAtEnd();
+ void Clear();
+ [Pure]
+ uint GetMany(uint startIndex, [Out] T[] items);
+ void ReplaceAll(T[] items);
+ }
+
+ [ComImport]
+ [Guid("bbe1fa4c-b0e3-4583-baef-1f1b2e483e56")]
+ [WindowsRuntimeImport]
+ internal interface IVectorView<T> : IIterable<T>
+ {
+ [Pure]
+ T GetAt(uint index);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ bool IndexOf(T value, out uint index);
+ [Pure]
+ uint GetMany(uint startIndex, [Out] T[] items);
+ }
+
+ [ComImport]
+ [Guid("393de7de-6fd0-4c0d-bb71-47244a113e93")]
+ [WindowsRuntimeImport]
+ internal interface IBindableVector : IBindableIterable
+ {
+ [Pure]
+ object GetAt(uint index);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ IBindableVectorView GetView();
+ [Pure]
+ bool IndexOf(object value, out uint index);
+ void SetAt(uint index, object value);
+ void InsertAt(uint index, object value);
+ void RemoveAt(uint index);
+ void Append(object value);
+ void RemoveAtEnd();
+ void Clear();
+ }
+
+ [ComImport]
+ [Guid("346dd6e7-976e-4bc3-815d-ece243bc0f33")]
+ [WindowsRuntimeImport]
+ internal interface IBindableVectorView : IBindableIterable
+ {
+ [Pure]
+ object GetAt(uint index);
+ [Pure]
+ uint Size { get; }
+ [Pure]
+ bool IndexOf(object value, out uint index);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs
new file mode 100644
index 0000000000..72d6fa8cc3
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IVectorViewToIReadOnlyListAdapter.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ internal delegate T Indexer_Get_Delegate<out T>(int index);
+
+ // This is a set of stub methods implementing the support for the IReadOnlyList`1 interface on WinRT
+ // objects that support IVectorView`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IVectorViewToIReadOnlyListAdapter objects. Rather, they are of type
+ // IVectorView<T>. No actual IVectorViewToIReadOnlyListAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IVectorView<T>".
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class IVectorViewToIReadOnlyListAdapter
+ {
+ private IVectorViewToIReadOnlyListAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // T this[int index] { get }
+ [SecurityCritical]
+ internal T Indexer_Get<T>(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IVectorView<T> _this = JitHelpers.UnsafeCast<IVectorView<T>>(this);
+
+ try
+ {
+ return _this.GetAt((uint) index);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ // T this[int index] { get }
+ [SecurityCritical]
+ internal T Indexer_Get_Variance<T>(int index) where T : class
+ {
+ bool fUseString;
+ Delegate target = System.StubHelpers.StubHelpers.GetTargetForAmbiguousVariantCall(
+ this,
+ typeof(IReadOnlyList<T>).TypeHandle.Value,
+ out fUseString);
+
+ if (target != null)
+ {
+ return (JitHelpers.UnsafeCast<Indexer_Get_Delegate<T>>(target))(index);
+ }
+
+ if (fUseString)
+ {
+ return JitHelpers.UnsafeCast<T>(Indexer_Get<string>(index));
+ }
+
+ return Indexer_Get<T>(index);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs
new file mode 100644
index 0000000000..f1b799aa84
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/IteratorToEnumeratorAdapter.cs
@@ -0,0 +1,210 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ internal delegate IEnumerator<T> GetEnumerator_Delegate<out T>();
+
+ // This is a set of stub methods implementing the support for the IEnumerable`1 interface on WinRT
+ // objects that implement IIterable`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not IterableToEnumerableAdapter objects. Rather, they are of type
+ // IIterable<T>. No actual IterableToEnumerableAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IIterable<T>".
+ internal sealed class IterableToEnumerableAdapter
+ {
+ private IterableToEnumerableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable<T>.
+ [SecurityCritical]
+ internal IEnumerator<T> GetEnumerator_Stub<T>()
+ {
+ IIterable<T> _this = JitHelpers.UnsafeCast<IIterable<T>>(this);
+ return new IteratorToEnumeratorAdapter<T>(_this.First());
+ }
+
+ // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable<T>
+ // and it is possible that the implementation supports IEnumerable<Type>/IEnumerable<string>/IEnumerable<Exception>/
+ // IEnumerable<array>/IEnumerable<delegate> rather than IEnumerable<T> because T is assignable from Type/string/
+ // Exception/array/delegate via co-variance.
+ [SecurityCritical]
+ internal IEnumerator<T> GetEnumerator_Variance_Stub<T>() where T : class
+ {
+ bool fUseString;
+ Delegate target = System.StubHelpers.StubHelpers.GetTargetForAmbiguousVariantCall(
+ this,
+ typeof(IEnumerable<T>).TypeHandle.Value,
+ out fUseString);
+
+ if (target != null)
+ {
+ return (JitHelpers.UnsafeCast<GetEnumerator_Delegate<T>>(target))();
+ }
+
+ if (fUseString)
+ {
+ return JitHelpers.UnsafeCast<IEnumerator<T>>(GetEnumerator_Stub<string>());
+ }
+
+ return GetEnumerator_Stub<T>();
+ }
+ }
+
+ internal sealed class BindableIterableToEnumerableAdapter
+ {
+ private BindableIterableToEnumerableAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ private sealed class NonGenericToGenericIterator : IIterator<object>
+ {
+ private IBindableIterator iterator;
+
+ public NonGenericToGenericIterator(IBindableIterator iterator)
+ { this.iterator = iterator; }
+
+ public object Current { get { return iterator.Current; } }
+ public bool HasCurrent { get { return iterator.HasCurrent; } }
+ public bool MoveNext() { return iterator.MoveNext(); }
+ public int GetMany(object[] items) { throw new NotSupportedException(); }
+ }
+
+ // This method is invoked when GetEnumerator is called on a WinRT-backed implementation of IEnumerable.
+ [SecurityCritical]
+ internal IEnumerator GetEnumerator_Stub()
+ {
+ IBindableIterable _this = JitHelpers.UnsafeCast<IBindableIterable>(this);
+ return new IteratorToEnumeratorAdapter<object>(new NonGenericToGenericIterator(_this.First()));
+ }
+ }
+
+ // Adapter class which holds a Windows Runtime IIterator<T>, exposing it as a managed IEnumerator<T>
+
+
+ // There are a few implementation differences between the Iterator and IEnumerator which need to be
+ // addressed. Iterator starts at index 0 while IEnumerator starts at index -1 as a result of which
+ // the first call to IEnumerator.Current is correct only after calling MoveNext().
+ // Also IEnumerator throws an exception when we call Current after reaching the end of collection.
+ internal sealed class IteratorToEnumeratorAdapter<T> : IEnumerator<T>
+ {
+ private IIterator<T> m_iterator;
+ private bool m_hadCurrent;
+ private T m_current;
+ private bool m_isInitialized;
+
+ internal IteratorToEnumeratorAdapter(IIterator<T> iterator)
+ {
+ Contract.Requires(iterator != null);
+ m_iterator = iterator;
+ m_hadCurrent = true;
+ m_isInitialized = false;
+ }
+
+ public T Current
+ {
+ get
+ {
+ // The enumerator has not been advanced to the first element yet.
+ if (!m_isInitialized)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ // The enumerator has reached the end of the collection
+ if (!m_hadCurrent)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return m_current;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ // The enumerator has not been advanced to the first element yet.
+ if (!m_isInitialized)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumNotStarted);
+ // The enumerator has reached the end of the collection
+ if (!m_hadCurrent)
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumEnded);
+ return m_current;
+ }
+ }
+
+ [SecuritySafeCritical]
+ public bool MoveNext()
+ {
+ // If we've passed the end of the iteration, IEnumerable<T> should return false, while
+ // IIterable will fail the interface call
+ if (!m_hadCurrent)
+ {
+ return false;
+ }
+
+ // IIterators start at index 0, rather than -1. If this is the first call, we need to just
+ // check HasCurrent rather than actually moving to the next element
+ try
+ {
+ if (!m_isInitialized)
+ {
+ m_hadCurrent = m_iterator.HasCurrent;
+ m_isInitialized = true;
+ }
+ else
+ {
+ m_hadCurrent = m_iterator.MoveNext();
+ }
+
+ // We want to save away the current value for two reasons:
+ // 1. Accessing .Current is cheap on other iterators, so having it be a property which is a
+ // simple field access preserves the expected performance characteristics (as opposed to
+ // triggering a COM call every time the property is accessed)
+ //
+ // 2. This allows us to preserve the same semantics as generic collection iteration when iterating
+ // beyond the end of the collection - namely that Current continues to return the last value
+ // of the collection
+ if (m_hadCurrent)
+ {
+ m_current = m_iterator.Current;
+ }
+ }
+ catch (Exception e)
+ {
+ // Translate E_CHANGED_STATE into an InvalidOperationException for an updated enumeration
+ if (Marshal.GetHRForException(e) == __HResults.E_CHANGED_STATE)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
+ }
+ else
+ {
+ throw;
+ }
+ }
+
+ return m_hadCurrent;
+ }
+
+ public void Reset()
+ {
+ throw new NotSupportedException();
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs
new file mode 100644
index 0000000000..35dc495d3f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorAdapter.cs
@@ -0,0 +1,188 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IBindableVector interface on managed
+ // objects that implement IList. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not ListToBindableVectorAdapter objects. Rather, they are of type
+ // IList. No actual ListToVectorBindableAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IList".
+ internal sealed class ListToBindableVectorAdapter
+ {
+ private ListToBindableVectorAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // object GetAt(uint index)
+ [SecurityCritical]
+ internal object GetAt(uint index)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ return _this[(Int32)index];
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
+ }
+ }
+
+ // uint Size { get }
+ [SecurityCritical]
+ internal uint Size()
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ return (uint)_this.Count;
+ }
+
+ // IBindableVectorView GetView()
+ [SecurityCritical]
+ internal IBindableVectorView GetView()
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ return new ListToBindableVectorViewAdapter(_this);
+ }
+
+ // bool IndexOf(object value, out uint index)
+ [SecurityCritical]
+ internal bool IndexOf(object value, out uint index)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ int ind = _this.IndexOf(value);
+
+ if (-1 == ind)
+ {
+ index = 0;
+ return false;
+ }
+
+ index = (uint)ind;
+ return true;
+ }
+
+ // void SetAt(uint index, object value)
+ [SecurityCritical]
+ internal void SetAt(uint index, object value)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ _this[(int)index] = value;
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
+ }
+ }
+
+ // void InsertAt(uint index, object value)
+ [SecurityCritical]
+ internal void InsertAt(uint index, object value)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+
+ // Inserting at an index one past the end of the list is equivalent to appending
+ // so we need to ensure that we're within (0, count + 1).
+ EnsureIndexInt32(index, _this.Count + 1);
+
+ try
+ {
+ _this.Insert((int)index, value);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Change error code to match what WinRT expects
+ ex.SetErrorCode(__HResults.E_BOUNDS);
+ throw;
+ }
+ }
+
+ // void RemoveAt(uint index)
+ [SecurityCritical]
+ internal void RemoveAt(uint index)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ _this.RemoveAt((Int32)index);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Change error code to match what WinRT expects
+ ex.SetErrorCode(__HResults.E_BOUNDS);
+ throw;
+ }
+ }
+
+ // void Append(object value)
+ [SecurityCritical]
+ internal void Append(object value)
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ _this.Add(value);
+ }
+
+ // void RemoveAtEnd()
+ [SecurityCritical]
+ internal void RemoveAtEnd()
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ if (_this.Count == 0)
+ {
+ Exception e = new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRemoveLastFromEmptyCollection"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ uint size = (uint)_this.Count;
+ RemoveAt(size - 1);
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear()
+ {
+ IList _this = JitHelpers.UnsafeCast<IList>(this);
+ _this.Clear();
+ }
+
+ // Helpers:
+
+ private static void EnsureIndexInt32(uint index, int listCapacity)
+ {
+ // We use '<=' and not '<' becasue Int32.MaxValue == index would imply
+ // that Size > Int32.MaxValue:
+ if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity)
+ {
+ Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs
new file mode 100644
index 0000000000..f760576aaa
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToBindableVectorViewAdapter.cs
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ /// A Windows Runtime IBindableVectorView implementation that wraps around a managed IList exposing
+ /// it to Windows runtime interop.
+ internal sealed class ListToBindableVectorViewAdapter : IBindableVectorView
+ {
+ private readonly IList list;
+
+ internal ListToBindableVectorViewAdapter(IList list)
+ {
+ if (list == null)
+ throw new ArgumentNullException("list");
+
+ Contract.EndContractBlock();
+
+ this.list = list;
+ }
+
+ private static void EnsureIndexInt32(uint index, int listCapacity)
+ {
+ // We use '<=' and not '<' becasue Int32.MaxValue == index would imply
+ // that Size > Int32.MaxValue:
+ if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity)
+ {
+ Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+ }
+
+ // IBindableIterable implementation:
+
+ public IBindableIterator First()
+ {
+ IEnumerator enumerator = list.GetEnumerator();
+ return new EnumeratorToIteratorAdapter<object>(new EnumerableToBindableIterableAdapter.NonGenericToGenericEnumerator(enumerator));
+ }
+
+ // IBindableVectorView implementation:
+
+ public object GetAt(uint index)
+ {
+ EnsureIndexInt32(index, list.Count);
+
+ try
+ {
+ return list[(int)index];
+
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
+ }
+ }
+
+ public uint Size
+ {
+ get
+ {
+ return (uint)list.Count;
+ }
+ }
+
+ public bool IndexOf(object value, out uint index)
+ {
+ int ind = list.IndexOf(value);
+
+ if (-1 == ind)
+ {
+ index = 0;
+ return false;
+ }
+
+ index = (uint)ind;
+ return true;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs
new file mode 100644
index 0000000000..77f3a9464f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ListToVectorAdapter.cs
@@ -0,0 +1,255 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IVector`1 interface on managed
+ // objects that implement IList`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not ListToVectorAdapter objects. Rather, they are of type
+ // IList<T>. No actual ListToVectorAdapter object is ever instantiated. Thus, you will
+ // see a lot of expressions that cast "this" to "IList<T>".
+ internal sealed class ListToVectorAdapter
+ {
+ private ListToVectorAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // T GetAt(uint index)
+ [SecurityCritical]
+ internal T GetAt<T>(uint index)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ return _this[(Int32)index];
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
+ }
+ }
+
+ // uint Size { get }
+ [SecurityCritical]
+ internal uint Size<T>()
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ return (uint)_this.Count;
+ }
+
+ // IVectorView<T> GetView()
+ [SecurityCritical]
+ internal IReadOnlyList<T> GetView<T>()
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ Contract.Assert(_this != null);
+
+ // Note: This list is not really read-only - you could QI for a modifiable
+ // list. We gain some perf by doing this. We believe this is acceptable.
+ IReadOnlyList<T> roList = _this as IReadOnlyList<T>;
+ if (roList == null)
+ {
+ roList = new ReadOnlyCollection<T>(_this);
+ }
+ return roList;
+ }
+
+ // bool IndexOf(T value, out uint index)
+ [SecurityCritical]
+ internal bool IndexOf<T>(T value, out uint index)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ int ind = _this.IndexOf(value);
+
+ if (-1 == ind)
+ {
+ index = 0;
+ return false;
+ }
+
+ index = (uint)ind;
+ return true;
+ }
+
+ // void SetAt(uint index, T value)
+ [SecurityCritical]
+ internal void SetAt<T>(uint index, T value)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ _this[(int)index] = value;
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ throw WindowsRuntimeMarshal.GetExceptionForHR(__HResults.E_BOUNDS, ex, "ArgumentOutOfRange_IndexOutOfRange");
+ }
+ }
+
+ // void InsertAt(uint index, T value)
+ [SecurityCritical]
+ internal void InsertAt<T>(uint index, T value)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+
+ // Inserting at an index one past the end of the list is equivalent to appending
+ // so we need to ensure that we're within (0, count + 1).
+ EnsureIndexInt32(index, _this.Count + 1);
+
+ try
+ {
+ _this.Insert((int)index, value);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Change error code to match what WinRT expects
+ ex.SetErrorCode(__HResults.E_BOUNDS);
+ throw;
+ }
+ }
+
+ // void RemoveAt(uint index)
+ [SecurityCritical]
+ internal void RemoveAt<T>(uint index)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ EnsureIndexInt32(index, _this.Count);
+
+ try
+ {
+ _this.RemoveAt((Int32)index);
+ }
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Change error code to match what WinRT expects
+ ex.SetErrorCode(__HResults.E_BOUNDS);
+ throw;
+ }
+ }
+
+ // void Append(T value)
+ [SecurityCritical]
+ internal void Append<T>(T value)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ _this.Add(value);
+ }
+
+ // void RemoveAtEnd()
+ [SecurityCritical]
+ internal void RemoveAtEnd<T>()
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ if (_this.Count == 0)
+ {
+ Exception e = new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRemoveLastFromEmptyCollection"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+
+ uint size = (uint)_this.Count;
+ RemoveAt<T>(size - 1);
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear<T>()
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ _this.Clear();
+ }
+
+ // uint GetMany(uint startIndex, T[] items)
+ [SecurityCritical]
+ internal uint GetMany<T>(uint startIndex, T[] items)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ return GetManyHelper<T>(_this, startIndex, items);
+ }
+
+ // void ReplaceAll(T[] items)
+ [SecurityCritical]
+ internal void ReplaceAll<T>(T[] items)
+ {
+ IList<T> _this = JitHelpers.UnsafeCast<IList<T>>(this);
+ _this.Clear();
+
+ if (items != null)
+ {
+ foreach (T item in items)
+ {
+ _this.Add(item);
+ }
+ }
+ }
+
+ // Helpers:
+
+ private static void EnsureIndexInt32(uint index, int listCapacity)
+ {
+ // We use '<=' and not '<' becasue Int32.MaxValue == index would imply
+ // that Size > Int32.MaxValue:
+ if (((uint)Int32.MaxValue) <= index || index >= (uint)listCapacity)
+ {
+ Exception e = new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexLargerThanMaxValue"));
+ e.SetErrorCode(__HResults.E_BOUNDS);
+ throw e;
+ }
+ }
+
+ private static uint GetManyHelper<T>(IList<T> sourceList, uint startIndex, T[] items)
+ {
+ // Calling GetMany with a start index equal to the size of the list should always
+ // return 0 elements, regardless of the input item size
+ if (startIndex == sourceList.Count)
+ {
+ return 0;
+ }
+
+ EnsureIndexInt32(startIndex, sourceList.Count);
+
+ if (items == null)
+ {
+ return 0;
+ }
+
+ uint itemCount = Math.Min((uint)items.Length, (uint)sourceList.Count - startIndex);
+ for (uint i = 0; i < itemCount; ++i)
+ {
+ items[i] = sourceList[(int)(i + startIndex)];
+ }
+
+ if (typeof(T) == typeof(string))
+ {
+ string[] stringItems = items as string[];
+
+ // Fill in rest of the array with String.Empty to avoid marshaling failure
+ for (uint i = itemCount; i < items.Length; ++i)
+ stringItems[i] = String.Empty;
+ }
+
+ return itemCount;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs
new file mode 100644
index 0000000000..3e93428d26
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/ManagedActivationFactory.cs
@@ -0,0 +1,76 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ [ComImport]
+ [Guid("60D27C8D-5F61-4CCE-B751-690FAE66AA53")]
+ [WindowsRuntimeImport]
+ internal interface IManagedActivationFactory
+ {
+ void RunClassConstructor();
+ }
+
+ // A ManangedActivationFactory provides the IActivationFactory implementation for managed types which are
+ // constructable via Windows Runtime. Implementation of specialized factory and static WinRT interfaces is
+ // provided using VM functionality (see Marshal.InitializeWinRTFactoryObject for details).
+ //
+ // In order to be activatable via the ManagedActivationFactory type, the type must be decorated with either
+ // ActivatableAttribute, or StaticAttribute.
+ [ComVisible(true)]
+ [ClassInterface(ClassInterfaceType.None)]
+ internal sealed class ManagedActivationFactory : IActivationFactory, IManagedActivationFactory
+ {
+ private Type m_type;
+
+ [SecurityCritical]
+ internal ManagedActivationFactory(Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ // Check whether the type is "exported to WinRT", i.e. it is declared in a managed .winmd and is decorated
+ // with at least one ActivatableAttribute or StaticAttribute.
+ if (!(type is RuntimeType) || !type.IsExportedToWindowsRuntime)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypeNotActivatableViaWindowsRuntime", type), "type");
+
+ m_type = type;
+ }
+
+ // Activate an instance of the managed type by using its default constructor.
+ public object ActivateInstance()
+ {
+ try
+ {
+ return Activator.CreateInstance(m_type);
+ }
+ catch (MissingMethodException)
+ {
+ // If the type doesn't expose a default constructor, then we fail with E_NOTIMPL
+ throw new NotImplementedException();
+ }
+ catch (TargetInvocationException e)
+ {
+ throw e.InnerException;
+ }
+ }
+
+ // Runs the class constructor
+ // Currently only Jupiter use this to run class constructor in order to
+ // initialize DependencyProperty objects and do necessary work
+ void IManagedActivationFactory.RunClassConstructor()
+ {
+ RuntimeHelpers.RunClassConstructor(m_type.TypeHandle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs
new file mode 100644
index 0000000000..395bef93d5
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToCollectionAdapter.cs
@@ -0,0 +1,192 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // These stubs will be used when a call via ICollection<KeyValuePair<K, V>> is made in managed code.
+ // This can mean two things - either the underlying unmanaged object implements IMap<K, V> or it
+ // implements IVector<IKeyValuePair<K, V>> and we cannot determine this statically in the general
+ // case so we have to cast at run-time. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not MapToCollectionAdapter objects. Rather, they are of type
+ // IVector<KeyValuePair<K, V>> or IMap<K, V>. No actual MapToCollectionAdapter object is ever
+ // instantiated. Thus, you will see a lot of expressions that cast "this" to "IVector<KeyValuePair<K, V>>"
+ // or "IMap<K, V>".
+ internal sealed class MapToCollectionAdapter
+ {
+ private MapToCollectionAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // int Count { get }
+ [Pure]
+ [SecurityCritical]
+ internal int Count<K, V>()
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IMap<K, V> _this_map = _this as IMap<K, V>;
+ if (_this_map != null)
+ {
+ uint size = _this_map.Size;
+
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingDictionaryTooLarge"));
+ }
+
+ return (int)size;
+ }
+ else
+ {
+ IVector<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVector<KeyValuePair<K, V>>>(this);
+ uint size = _this_vector.Size;
+
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)size;
+ }
+ }
+
+ // bool IsReadOnly { get }
+ [SecurityCritical]
+ internal bool IsReadOnly<K, V>()
+ {
+ return false;
+ }
+
+ // void Add(T item)
+ [SecurityCritical]
+ internal void Add<K, V>(KeyValuePair<K, V> item)
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IDictionary<K, V> _this_dictionary = _this as IDictionary<K, V>;
+ if (_this_dictionary != null)
+ {
+ _this_dictionary.Add(item.Key, item.Value);
+ }
+ else
+ {
+ IVector<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVector<KeyValuePair<K, V>>>(this);
+ _this_vector.Append(item);
+ }
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear<K, V>()
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IMap<K, V> _this_map = _this as IMap<K, V>;
+ if (_this_map != null)
+ {
+ _this_map.Clear();
+ }
+ else
+ {
+ IVector<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVector<KeyValuePair<K, V>>>(this);
+ _this_vector.Clear();
+ }
+ }
+
+ // bool Contains(T item)
+ [SecurityCritical]
+ internal bool Contains<K, V>(KeyValuePair<K, V> item)
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IDictionary<K, V> _this_dictionary = _this as IDictionary<K, V>;
+ if (_this_dictionary != null)
+ {
+ V value;
+ bool hasKey = _this_dictionary.TryGetValue(item.Key, out value);
+
+ if (!hasKey)
+ return false;
+
+ return EqualityComparer<V>.Default.Equals(value, item.Value);
+ }
+ else
+ {
+ IVector<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVector<KeyValuePair<K, V>>>(this);
+
+ uint index;
+ return _this_vector.IndexOf(item, out index);
+ }
+ }
+
+ // void CopyTo(T[] array, int arrayIndex)
+ [SecurityCritical]
+ internal void CopyTo<K, V>(KeyValuePair<K, V>[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex");
+
+ if (array.Length <= arrayIndex && Count<K, V>() > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds"));
+
+ if (array.Length - arrayIndex < Count<K, V>())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ Contract.EndContractBlock();
+
+ IIterable<KeyValuePair<K, V>> _this = JitHelpers.UnsafeCast<IIterable<KeyValuePair<K, V>>>(this);
+ foreach (KeyValuePair<K, V> mapping in _this)
+ {
+ array[arrayIndex++] = mapping;
+ }
+ }
+
+ // bool Remove(T item)
+ [SecurityCritical]
+ internal bool Remove<K, V>(KeyValuePair<K, V> item)
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IDictionary<K, V> _this_dictionary = _this as IDictionary<K, V>;
+ if (_this_dictionary != null)
+ {
+ return _this_dictionary.Remove(item.Key);
+ }
+ else
+ {
+ IVector<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVector<KeyValuePair<K, V>>>(this);
+ uint index;
+ bool exists = _this_vector.IndexOf(item, out index);
+
+ if (!exists)
+ return false;
+
+ if (((uint)Int32.MaxValue) < index)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ VectorToListAdapter.RemoveAtHelper<KeyValuePair<K, V>>(_this_vector, index);
+ return true;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs
new file mode 100644
index 0000000000..d7897ced9f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapToDictionaryAdapter.cs
@@ -0,0 +1,183 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IDictionary`2 interface on WinRT
+ // objects that support IMap`2. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not MapToDictionaryAdapter objects. Rather, they are of type
+ // IMap<K, V>. No actual MapToDictionaryAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IMap<K, V>".
+ internal sealed class MapToDictionaryAdapter
+ {
+ private MapToDictionaryAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // V this[K key] { get }
+ [SecurityCritical]
+ internal V Indexer_Get<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ Contract.EndContractBlock();
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ return Lookup(_this, key);
+ }
+
+ // V this[K key] { set }
+ [SecurityCritical]
+ internal void Indexer_Set<K, V>(K key, V value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ Contract.EndContractBlock();
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ Insert(_this, key, value);
+ }
+
+ // ICollection<K> Keys { get }
+ [SecurityCritical]
+ internal ICollection<K> Keys<K, V>()
+ {
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ IDictionary<K, V> dictionary = (IDictionary<K, V>)_this;
+ return new DictionaryKeyCollection<K, V>(dictionary);
+ }
+
+ // ICollection<V> Values { get }
+ [SecurityCritical]
+ internal ICollection<V> Values<K, V>()
+ {
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ IDictionary<K, V> dictionary = (IDictionary<K, V>)_this;
+ return new DictionaryValueCollection<K, V>(dictionary);
+ }
+
+ // bool ContainsKey(K key)
+ [Pure]
+ [SecurityCritical]
+ internal bool ContainsKey<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ return _this.HasKey(key);
+ }
+
+ // void Add(K key, V value)
+ [SecurityCritical]
+ internal void Add<K, V>(K key, V value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ if (ContainsKey<K, V>(key))
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicate"));
+
+ Contract.EndContractBlock();
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ Insert(_this, key, value);
+ }
+
+ // bool Remove(TKey key)
+ [SecurityCritical]
+ internal bool Remove<K, V>(K key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ if (!_this.HasKey(key))
+ return false;
+
+ try
+ {
+ _this.Remove(key);
+ return true;
+
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ return false;
+
+ throw;
+ }
+ }
+
+ // bool TryGetValue(TKey key, out TValue value)
+ [SecurityCritical]
+ internal bool TryGetValue<K, V>(K key, out V value)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ IMap<K, V> _this = JitHelpers.UnsafeCast<IMap<K, V>>(this);
+ if (!_this.HasKey(key))
+ {
+ value = default(V);
+ return false;
+ }
+
+ try
+ {
+ value = Lookup(_this, key);
+ return true;
+ }
+ catch (KeyNotFoundException)
+ {
+ value = default(V);
+ return false;
+ }
+ }
+
+ // Helpers:
+
+ private static V Lookup<K, V>(IMap<K, V> _this, K key)
+ {
+ Contract.Requires(null != key);
+
+ try
+ {
+ return _this.Lookup(key);
+ }
+ catch (Exception ex)
+ {
+
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new KeyNotFoundException(Environment.GetResourceString("Arg_KeyNotFound"));
+ throw;
+ }
+ }
+
+ private static bool Insert<K, V>(IMap<K, V> _this, K key, V value)
+ {
+ Contract.Requires(null != key);
+
+ bool replaced = _this.Insert(key, value);
+ return replaced;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs
new file mode 100644
index 0000000000..58427fbd71
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/MapViewToReadOnlyCollectionAdapter.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // These stubs will be used when a call via IReadOnlyCollection<KeyValuePair<K, V>> is made in managed code.
+ // This can mean two things - either the underlying unmanaged object implements IMapView<K, V> or it
+ // implements IVectorView<IKeyValuePair<K, V>> and we cannot determine this statically in the general
+ // case so we have to cast at run-time. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not MapViewToReadOnlyCollectionAdapter objects. Rather, they are of type
+ // IVectorView<KeyValuePair<K, V>> or IMapView<K, V>. No actual MapViewToReadOnlyCollectionAdapter object is ever
+ // instantiated. Thus, you will see a lot of expressions that cast "this" to "IVectorView<KeyValuePair<K, V>>"
+ // or "IMapView<K, V>".
+ internal sealed class MapViewToReadOnlyCollectionAdapter
+ {
+ private MapViewToReadOnlyCollectionAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // int Count { get }
+ [Pure]
+ [SecurityCritical]
+ internal int Count<K, V>()
+ {
+ object _this = JitHelpers.UnsafeCast<object>(this);
+
+ IMapView<K, V> _this_map = _this as IMapView<K, V>;
+ if (_this_map != null)
+ {
+ uint size = _this_map.Size;
+
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingDictionaryTooLarge"));
+ }
+
+ return (int)size;
+ }
+ else
+ {
+ IVectorView<KeyValuePair<K, V>> _this_vector = JitHelpers.UnsafeCast<IVectorView<KeyValuePair<K, V>>>(this);
+ uint size = _this_vector.Size;
+
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)size;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs
new file mode 100644
index 0000000000..b8cd65efa6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/NativeMethods.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+#if BIT64
+ [StructLayout(LayoutKind.Explicit, Size = 24)]
+#else
+ [StructLayout(LayoutKind.Explicit, Size = 20)]
+#endif
+ internal unsafe struct HSTRING_HEADER
+ {
+ }
+
+ internal static class UnsafeNativeMethods
+ {
+ [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll", PreserveSig = false)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern IRestrictedErrorInfo GetRestrictedErrorInfo();
+
+ [DllImport("api-ms-win-core-winrt-error-l1-1-1.dll")]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ 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]
+ internal static extern void RoReportUnhandledError(IRestrictedErrorInfo error);
+
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static unsafe extern int WindowsCreateString([MarshalAs(UnmanagedType.LPWStr)] string sourceString,
+ int length,
+ [Out] IntPtr *hstring);
+
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static unsafe extern int WindowsCreateStringReference(char *sourceString,
+ int length,
+ [Out] HSTRING_HEADER *hstringHeader,
+ [Out] IntPtr *hstring);
+
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern int WindowsDeleteString(IntPtr hstring);
+
+ [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static unsafe extern char* WindowsGetStringRawBuffer(IntPtr hstring, [Out] uint *length);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs
new file mode 100644
index 0000000000..ad64c9917f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/PropertyValue.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // Note this is a copy of the PropertyType enumeration from Windows.Foundation.winmd
+ internal enum PropertyType
+ {
+ // WARNING: These values have to match enum Windows.Foundation.PropertyType !!!
+ Empty = 0,
+ UInt8 = 1,
+ Int16 = 2,
+ UInt16 = 3,
+ Int32 = 4,
+ UInt32 = 5,
+ Int64 = 6,
+ UInt64 = 7,
+ Single = 8,
+ Double = 9,
+ Char16 = 10,
+ Boolean = 11,
+ String = 12,
+ Inspectable = 13,
+ DateTime = 14,
+ TimeSpan = 15,
+ Guid = 16,
+ Point = 17,
+ Size = 18,
+ Rect = 19,
+
+ Other = 20,
+
+ UInt8Array = UInt8 + 1024,
+ Int16Array = Int16 + 1024,
+ UInt16Array = UInt16 + 1024,
+ Int32Array = Int32 + 1024,
+ UInt32Array = UInt32 + 1024,
+ Int64Array = Int64 + 1024,
+ UInt64Array = UInt64 + 1024,
+ SingleArray = Single + 1024,
+ DoubleArray = Double + 1024,
+ Char16Array = Char16 + 1024,
+ BooleanArray = Boolean + 1024,
+ StringArray = String + 1024,
+ InspectableArray = Inspectable + 1024,
+ DateTimeArray = DateTime + 1024,
+ TimeSpanArray = TimeSpan + 1024,
+ GuidArray = Guid + 1024,
+ PointArray = Point + 1024,
+ SizeArray = Size + 1024,
+ RectArray = Rect + 1024,
+ OtherArray = Other + 1024,
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs
new file mode 100644
index 0000000000..5dd7d00579
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/RuntimeClass.cs
@@ -0,0 +1,122 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** RuntimeClass is the base class of all WinRT types
+**
+**
+===========================================================*/
+namespace System.Runtime.InteropServices.WindowsRuntime {
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.InteropServices.WindowsRuntime;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+
+
+ // Local definition of Windows.Foundation.IStringable
+ [ComImport]
+ [Guid("96369f54-8eb6-48f0-abce-c1b211e627c3")]
+ [WindowsRuntimeImport]
+ internal interface IStringable
+ {
+ string ToString();
+ }
+
+ internal class IStringableHelper
+ {
+ internal static string ToString(object obj)
+ {
+ IGetProxyTarget proxy = obj as IGetProxyTarget;
+ if (proxy != null)
+ obj = proxy.GetTarget();
+
+ // Check whether the type implements IStringable.
+ IStringable stringableType = obj as IStringable;
+ if (stringableType != null)
+ {
+ return stringableType.ToString();
+ }
+
+ return obj.ToString();
+ }
+ }
+
+ //
+ // Base class for every WinRT class
+ // We'll make it a ComImport and WindowsRuntimeImport in the type loader
+ // as C# compiler won't allow putting code in ComImport type
+ //
+ internal abstract class RuntimeClass : __ComObject
+ {
+ //
+ // Support for ToString/GetHashCode/Equals override
+ //
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetRedirectedGetHashCodeMD();
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern int RedirectGetHashCode(IntPtr pMD);
+
+ [System.Security.SecuritySafeCritical]
+ public override int GetHashCode()
+ {
+ IntPtr pMD = GetRedirectedGetHashCodeMD();
+ if (pMD == IntPtr.Zero)
+ return base.GetHashCode();
+ return RedirectGetHashCode(pMD);
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetRedirectedToStringMD();
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern string RedirectToString(IntPtr pMD);
+
+ [System.Security.SecuritySafeCritical]
+ public override string ToString()
+ {
+ // Check whether the type implements IStringable.
+ IStringable stringableType = this as IStringable;
+ if (stringableType != null)
+ {
+ return stringableType.ToString();
+ }
+ else
+ {
+ IntPtr pMD = GetRedirectedToStringMD();
+
+ if (pMD == IntPtr.Zero)
+ return base.ToString();
+
+ return RedirectToString(pMD);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern IntPtr GetRedirectedEqualsMD();
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern bool RedirectEquals(object obj, IntPtr pMD);
+
+ [System.Security.SecuritySafeCritical]
+ public override bool Equals(object obj)
+ {
+ IntPtr pMD = GetRedirectedEqualsMD();
+ if (pMD == IntPtr.Zero)
+ return base.Equals(obj);
+ return RedirectEquals(obj, pMD);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs
new file mode 100644
index 0000000000..5eeb0afcfc
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToCollectionAdapter.cs
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the ICollection`1 interface on WinRT
+ // objects that support IVector`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not VectorToCollectionAdapter objects. Rather, they are of type
+ // IVector<T>. No actual VectorToCollectionAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IVector<T>".
+ internal sealed class VectorToCollectionAdapter
+ {
+ private VectorToCollectionAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // int Count { get }
+ [Pure]
+ [SecurityCritical]
+ internal int Count<T>()
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ uint size = _this.Size;
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)size;
+ }
+
+ // bool IsReadOnly { get }
+ [SecurityCritical]
+ internal bool IsReadOnly<T>()
+ {
+ return false;
+ }
+
+ // void Add(T item)
+ [SecurityCritical]
+ internal void Add<T>(T item)
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ _this.Append(item);
+ }
+
+ // void Clear()
+ [SecurityCritical]
+ internal void Clear<T>()
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ _this.Clear();
+ }
+
+ // bool Contains(T item)
+ [SecurityCritical]
+ internal bool Contains<T>(T item)
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+
+ uint index;
+ return _this.IndexOf(item, out index);
+ }
+
+ // void CopyTo(T[] array, int arrayIndex)
+ [SecurityCritical]
+ internal void CopyTo<T>(T[] array, int arrayIndex)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+
+ if (arrayIndex < 0)
+ throw new ArgumentOutOfRangeException("arrayIndex");
+
+ if (array.Length <= arrayIndex && Count<T>() > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_IndexOutOfArrayBounds"));
+
+ if (array.Length - arrayIndex < Count<T>())
+ throw new ArgumentException(Environment.GetResourceString("Argument_InsufficientSpaceToCopyCollection"));
+
+ Contract.EndContractBlock();
+
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ int count = Count<T>();
+ for (int i = 0; i < count; i++)
+ {
+ array[i + arrayIndex] = VectorToListAdapter.GetAt<T>(_this, (uint)i);
+ }
+ }
+
+ // bool Remove(T item)
+ [SecurityCritical]
+ internal bool Remove<T>(T item)
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+
+ uint index;
+ bool exists = _this.IndexOf(item, out index);
+
+ if (!exists)
+ return false;
+
+ if (((uint)Int32.MaxValue) < index)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ VectorToListAdapter.RemoveAtHelper<T>(_this, index);
+ return true;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs
new file mode 100644
index 0000000000..f27cc95176
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorToListAdapter.cs
@@ -0,0 +1,170 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IList`1 interface on WinRT
+ // objects that support IVector`1. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not VectorToListAdapter objects. Rather, they are of type
+ // IVector<T>. No actual VectorToListAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IVector<T>".
+ internal sealed class VectorToListAdapter
+ {
+ private VectorToListAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // T this[int index] { get }
+ [SecurityCritical]
+ internal T Indexer_Get<T>(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ return GetAt(_this, (uint)index);
+ }
+
+ // T this[int index] { set }
+ [SecurityCritical]
+ internal void Indexer_Set<T>(int index, T value)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ SetAt(_this, (uint)index, value);
+ }
+
+ // int IndexOf(T item)
+ [SecurityCritical]
+ internal int IndexOf<T>(T item)
+ {
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+
+ uint index;
+ bool exists = _this.IndexOf(item, out index);
+
+ if (!exists)
+ return -1;
+
+ if (((uint)Int32.MaxValue) < index)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)index;
+ }
+
+ // void Insert(int index, T item)
+ [SecurityCritical]
+ internal void Insert<T>(int index, T item)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ InsertAtHelper<T>(_this, (uint)index, item);
+ }
+
+ // void RemoveAt(int index)
+ [SecurityCritical]
+ internal void RemoveAt<T>(int index)
+ {
+ if (index < 0)
+ throw new ArgumentOutOfRangeException("index");
+
+ IVector<T> _this = JitHelpers.UnsafeCast<IVector<T>>(this);
+ RemoveAtHelper<T>(_this, (uint)index);
+ }
+
+ // Helpers:
+
+ internal static T GetAt<T>(IVector<T> _this, uint index)
+ {
+ try
+ {
+ return _this.GetAt(index);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ private static void SetAt<T>(IVector<T> _this, UInt32 index, T value)
+ {
+ try
+ {
+ _this.SetAt(index, value);
+
+ // We deligate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ private static void InsertAtHelper<T>(IVector<T> _this, uint index, T item)
+ {
+ try
+ {
+ _this.InsertAt(index, item);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+
+ internal static void RemoveAtHelper<T>(IVector<T> _this, uint index)
+ {
+ try
+ {
+ _this.RemoveAt(index);
+
+ // We delegate bounds checking to the underlying collection and if it detected a fault,
+ // we translate it to the right exception:
+ }
+ catch (Exception ex)
+ {
+ if (__HResults.E_BOUNDS == ex._HResult)
+ throw new ArgumentOutOfRangeException("index");
+
+ throw;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs
new file mode 100644
index 0000000000..4b4ae5d6fc
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/VectorViewToReadOnlyCollectionAdapter.cs
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Security;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // This is a set of stub methods implementing the support for the IReadOnlyCollection<T> interface on WinRT
+ // objects that support IVectorView<T>. Used by the interop mashaling infrastructure.
+ //
+ // The methods on this class must be written VERY carefully to avoid introducing security holes.
+ // That's because they are invoked with special "this"! The "this" object
+ // for all of these methods are not VectorViewToReadOnlyCollectionAdapter objects. Rather, they are of type
+ // IVectorView<T>. No actual VectorViewToReadOnlyCollectionAdapter object is ever instantiated. Thus, you will see
+ // a lot of expressions that cast "this" to "IVectorView<T>".
+ internal sealed class VectorViewToReadOnlyCollectionAdapter
+ {
+ private VectorViewToReadOnlyCollectionAdapter()
+ {
+ Contract.Assert(false, "This class is never instantiated");
+ }
+
+ // int Count { get }
+ [Pure]
+ [SecurityCritical]
+ internal int Count<T>()
+ {
+ IVectorView<T> _this = JitHelpers.UnsafeCast<IVectorView<T>>(this);
+ uint size = _this.Size;
+ if (((uint)Int32.MaxValue) < size)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CollectionBackingListTooLarge"));
+ }
+
+ return (int)size;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs
new file mode 100644
index 0000000000..1f6e373842
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsFoundationEventHandler.cs
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // WindowsFoundationEventHandler<T> a copy of the definition for the Windows.Foundation.EventHandler<T> delegate
+ [Guid("9de1c535-6ae1-11e0-84e1-18a905bcc53f")]
+ [WindowsRuntimeImport]
+ internal delegate void WindowsFoundationEventHandler<T>(object sender, T args);
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs
new file mode 100644
index 0000000000..0d59895bc4
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeBufferHelper.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.Versioning;
+using System.Security;
+using System.Threading;
+
+
+namespace System.Runtime.InteropServices.WindowsRuntime {
+
+/// <summary>
+/// Exposes a helper method that allows <code>WindowsRuntimeBuffer : IBuffer, IBufferInternal</code> which is implemented in
+/// <code>System.Runtime.WindowsRuntime.dll</code> to call into the VM.
+/// </summary>
+[FriendAccessAllowed]
+internal static class WindowsRuntimeBufferHelper {
+
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall)]
+ [SuppressUnmanagedCodeSecurity]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private unsafe extern static void StoreOverlappedPtrInCCW(ObjectHandleOnStack windowsRuntimeBuffer, NativeOverlapped* overlapped);
+
+
+ [FriendAccessAllowed]
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe static void StoreOverlappedInCCW(Object windowsRuntimeBuffer, NativeOverlapped* overlapped) {
+
+ StoreOverlappedPtrInCCW(JitHelpers.GetObjectHandleOnStack(ref windowsRuntimeBuffer), overlapped);
+ }
+
+} // class WindowsRuntimeBufferHelper
+
+} // namespace
+
+// WindowsRuntimeBufferHelper.cs
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
new file mode 100644
index 0000000000..038efd5013
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMarshal.cs
@@ -0,0 +1,1335 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Security;
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ // Helper functions to manually marshal data between .NET and WinRT
+ public static class WindowsRuntimeMarshal
+ {
+ // Add an event handler to a Windows Runtime style event, such that it can be removed via a delegate
+ // lookup at a later time. This method adds the handler to the add method using the supplied
+ // delegate. It then stores the corresponding token in a dictionary for easy access by RemoveEventHandler
+ // later. Note that the dictionary is indexed by the remove method that will be used for RemoveEventHandler
+ // so the removeMethod given here must match the remove method supplied there exactly.
+ [SecurityCritical]
+ public static void AddEventHandler<T>(Func<T, EventRegistrationToken> addMethod,
+ Action<EventRegistrationToken> removeMethod,
+ T handler)
+ {
+ if (addMethod == null)
+ throw new ArgumentNullException("addMethod");
+ if (removeMethod == null)
+ throw new ArgumentNullException("removeMethod");
+ Contract.EndContractBlock();
+
+ // Managed code allows adding a null event handler, the effect is a no-op. To match this behavior
+ // for WinRT events, we simply ignore attempts to add null.
+ if (handler == null)
+ {
+ return;
+ }
+
+ // Delegate to managed event registration implementation or native event registration implementation
+ // They have completely different implementation because native side has its own unique problem to solve -
+ // there could be more than one RCW for the same COM object
+ // it would be more confusing and less-performant if we were to merge them together
+ object target = removeMethod.Target;
+ if (target == null || Marshal.IsComObject(target))
+ NativeOrStaticEventRegistrationImpl.AddEventHandler<T>(addMethod, removeMethod, handler);
+ else
+ ManagedEventRegistrationImpl.AddEventHandler<T>(addMethod, removeMethod, handler);
+ }
+
+ // Remove the delegate handler from the Windows Runtime style event registration by looking for
+ // its token, previously stored via AddEventHandler<T>
+ [SecurityCritical]
+ public static void RemoveEventHandler<T>(Action<EventRegistrationToken> removeMethod, T handler)
+ {
+ if (removeMethod == null)
+ throw new ArgumentNullException("removeMethod");
+ Contract.EndContractBlock();
+
+ // Managed code allows removing a null event handler, the effect is a no-op. To match this behavior
+ // for WinRT events, we simply ignore attempts to remove null.
+ if (handler == null)
+ {
+ return;
+ }
+
+ // Delegate to managed event registration implementation or native event registration implementation
+ // They have completely different implementation because native side has its own unique problem to solve -
+ // there could be more than one RCW for the same COM object
+ // it would be more confusing and less-performant if we were to merge them together
+ object target = removeMethod.Target;
+ if (target == null || Marshal.IsComObject(target))
+ NativeOrStaticEventRegistrationImpl.RemoveEventHandler<T>(removeMethod, handler);
+ else
+ ManagedEventRegistrationImpl.RemoveEventHandler<T>(removeMethod, handler);
+ }
+
+ [SecurityCritical]
+ public static void RemoveAllEventHandlers(Action<EventRegistrationToken> removeMethod)
+ {
+ if (removeMethod == null)
+ throw new ArgumentNullException("removeMethod");
+ Contract.EndContractBlock();
+
+ // Delegate to managed event registration implementation or native event registration implementation
+ // They have completely different implementation because native side has its own unique problem to solve -
+ // there could be more than one RCW for the same COM object
+ // it would be more confusing and less-performant if we were to merge them together
+ object target = removeMethod.Target;
+ if (target == null || Marshal.IsComObject(target))
+ NativeOrStaticEventRegistrationImpl.RemoveAllEventHandlers(removeMethod);
+ else
+ ManagedEventRegistrationImpl.RemoveAllEventHandlers(removeMethod);
+ }
+
+ // Returns the total cache size
+ // Used by test only to verify we don't leak event cache
+ internal static int GetRegistrationTokenCacheSize()
+ {
+ int count = 0;
+
+ if (ManagedEventRegistrationImpl.s_eventRegistrations != null)
+ {
+ lock (ManagedEventRegistrationImpl.s_eventRegistrations)
+ {
+ count += ManagedEventRegistrationImpl.s_eventRegistrations.Keys.Count;
+ }
+ }
+
+ if (NativeOrStaticEventRegistrationImpl.s_eventRegistrations != null)
+ {
+ lock (NativeOrStaticEventRegistrationImpl.s_eventRegistrations)
+ {
+ count += NativeOrStaticEventRegistrationImpl.s_eventRegistrations.Count;
+ }
+ }
+
+ return count;
+ }
+
+ //
+ // Optimized version of List of EventRegistrationToken
+ // It is made a struct to reduce overhead
+ //
+ internal struct EventRegistrationTokenList
+ {
+ private EventRegistrationToken firstToken; // Optimization for common case where there is only one token
+ private List<EventRegistrationToken> restTokens; // Rest of the tokens
+
+ internal EventRegistrationTokenList(EventRegistrationToken token)
+ {
+ firstToken = token;
+ restTokens = null;
+ }
+
+ internal EventRegistrationTokenList(EventRegistrationTokenList list)
+ {
+ firstToken = list.firstToken;
+ restTokens = list.restTokens;
+ }
+
+ // Push a new token into this list
+ // Returns true if you need to copy back this list into the dictionary (so that you
+ // don't lose change outside the dictionary). false otherwise.
+ public bool Push(EventRegistrationToken token)
+ {
+ bool needCopy = false;
+
+ if (restTokens == null)
+ {
+ restTokens = new List<EventRegistrationToken>();
+ needCopy = true;
+ }
+
+ restTokens.Add(token);
+
+ return needCopy;
+ }
+
+ // Pops the last token
+ // Returns false if no more tokens left, true otherwise
+ public bool Pop(out EventRegistrationToken token)
+ {
+ // Only 1 token in this list and we just removed the last token
+ if (restTokens == null || restTokens.Count == 0)
+ {
+ token = firstToken;
+ return false;
+ }
+
+ int last = restTokens.Count - 1;
+ token = restTokens[last];
+ restTokens.RemoveAt(last);
+
+ return true;
+ }
+
+ public void CopyTo(List<EventRegistrationToken> tokens)
+ {
+ tokens.Add(firstToken);
+ if (restTokens != null)
+ tokens.AddRange(restTokens);
+ }
+ }
+
+ //
+ // Event registration support for managed objects events & static events
+ //
+ internal static class ManagedEventRegistrationImpl
+ {
+ // Mappings of delegates registered for events -> their registration tokens.
+ // These mappings are stored indexed by the remove method which can be used to undo the registrations.
+ //
+ // The full structure of this table is:
+ // object the event is being registered on ->
+ // Table [RemoveMethod] ->
+ // Table [Handler] -> Token
+ //
+ // Note: There are a couple of optimizations I didn't do here because they don't make sense for managed events:
+ // 1. Flatten the event cache (see EventCacheKey in native WinRT event implementation below)
+ //
+ // This is because managed events use ConditionalWeakTable to hold Objects->(Event->(Handler->Tokens)),
+ // and when object goes away everything else will be nicely cleaned up. If I flatten it like native WinRT events,
+ // I'll have to use Dictionary (as ConditionalWeakTable won't work - nobody will hold the new key alive anymore)
+ // instead, and that means I'll have to add more code from native WinRT events into managed WinRT event to support
+ // self-cleanup in the finalization, as well as reader/writer lock to protect against race conditions in the finalization,
+ // which adds a lot more complexity and doesn't really worth it.
+ //
+ // 2. Use conditionalWeakTable to hold Handler->Tokens.
+ //
+ // The reason is very simple - managed object use dictionary (see EventRegistrationTokenTable) to hold delegates alive.
+ // If the delegates aren't alive, it means either they have been unsubscribed, or the object itself is gone,
+ // and in either case, they've been already taken care of.
+ //
+ internal volatile static
+ ConditionalWeakTable<object, Dictionary<MethodInfo, Dictionary<object, EventRegistrationTokenList>>> s_eventRegistrations =
+ new ConditionalWeakTable<object, Dictionary<MethodInfo, Dictionary<object, EventRegistrationTokenList>>>();
+
+ [SecurityCritical]
+ internal static void AddEventHandler<T>(Func<T, EventRegistrationToken> addMethod,
+ Action<EventRegistrationToken> removeMethod,
+ T handler)
+ {
+ Contract.Requires(addMethod != null);
+ Contract.Requires(removeMethod != null);
+
+ // Add the method, and make a note of the token -> delegate mapping.
+ object instance = removeMethod.Target;
+ Dictionary<object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);
+ EventRegistrationToken token = addMethod(handler);
+ lock (registrationTokens)
+ {
+ EventRegistrationTokenList tokens;
+ if (!registrationTokens.TryGetValue(handler, out tokens))
+ {
+ tokens = new EventRegistrationTokenList(token);
+ registrationTokens[handler] = tokens;
+ }
+ else
+ {
+ bool needCopy = tokens.Push(token);
+
+ // You need to copy back this list into the dictionary (so that you don't lose change outside dictionary)
+ if (needCopy)
+ registrationTokens[handler] = tokens;
+ }
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event subscribed for managed instance = " + instance + ", handler = " + handler + "\n");
+ }
+ }
+
+ // Get the event registration token table for an event. These are indexed by the remove method of the event.
+ private static Dictionary<object, EventRegistrationTokenList> GetEventRegistrationTokenTable(object instance, Action<EventRegistrationToken> removeMethod)
+ {
+ Contract.Requires(instance != null);
+ Contract.Requires(removeMethod != null);
+ Contract.Requires(s_eventRegistrations != null);
+
+ lock (s_eventRegistrations)
+ {
+ Dictionary<MethodInfo, Dictionary<object, EventRegistrationTokenList>> instanceMap = null;
+ if (!s_eventRegistrations.TryGetValue(instance, out instanceMap))
+ {
+ instanceMap = new Dictionary<MethodInfo, Dictionary<object, EventRegistrationTokenList>>();
+ s_eventRegistrations.Add(instance, instanceMap);
+ }
+
+ Dictionary<object, EventRegistrationTokenList> tokens = null;
+ if (!instanceMap.TryGetValue(removeMethod.Method, out tokens))
+ {
+ tokens = new Dictionary<object, EventRegistrationTokenList>();
+ instanceMap.Add(removeMethod.Method, tokens);
+ }
+
+ return tokens;
+ }
+ }
+
+ [SecurityCritical]
+ internal static void RemoveEventHandler<T>(Action<EventRegistrationToken> removeMethod, T handler)
+ {
+ Contract.Requires(removeMethod != null);
+
+ object instance = removeMethod.Target;
+ Dictionary<object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);
+ EventRegistrationToken token;
+
+ lock (registrationTokens)
+ {
+ EventRegistrationTokenList tokens;
+
+ // Failure to find a registration for a token is not an error - it's simply a no-op.
+ if (!registrationTokens.TryGetValue(handler, out tokens))
+ {
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] no registrationTokens found for instance=" + instance + ", handler= " + handler + "\n");
+
+ return;
+ }
+
+ // Select a registration token to unregister
+ // We don't care which one but I'm returning the last registered token to be consistent
+ // with native event registration implementation
+ bool moreItems = tokens.Pop(out token);
+ if (!moreItems)
+ {
+ // Remove it from cache if this list become empty
+ // This must be done because EventRegistrationTokenList now becomes invalid
+ // (mostly because there is no safe default value for EventRegistrationToken to express 'no token')
+ // NOTE: We should try to remove registrationTokens itself from cache if it is empty, otherwise
+ // we could run into a race condition where one thread removes it from cache and another thread adds
+ // into the empty registrationToken table
+ registrationTokens.Remove(handler);
+ }
+ }
+
+ removeMethod(token);
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for managed instance = " + instance + ", handler = " + handler + ", token = " + token.m_value + "\n");
+ }
+
+ [SecurityCritical]
+ internal static void RemoveAllEventHandlers(Action<EventRegistrationToken> removeMethod)
+ {
+ Contract.Requires(removeMethod != null);
+
+ object instance = removeMethod.Target;
+ Dictionary<object, EventRegistrationTokenList> registrationTokens = GetEventRegistrationTokenTable(instance, removeMethod);
+
+ List<EventRegistrationToken> tokensToRemove = new List<EventRegistrationToken>();
+
+ lock (registrationTokens)
+ {
+ // Copy all tokens to tokensToRemove array which later we'll call removeMethod on
+ // outside this lock
+ foreach (EventRegistrationTokenList tokens in registrationTokens.Values)
+ {
+ tokens.CopyTo(tokensToRemove);
+ }
+
+ // Clear the dictionary - at this point all event handlers are no longer in the cache
+ // but they are not removed yet
+ registrationTokens.Clear();
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Cache cleared for managed instance = " + instance + "\n");
+ }
+
+ //
+ // Remove all handlers outside the lock
+ //
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Start removing all events for instance = " + instance + "\n");
+ CallRemoveMethods(removeMethod, tokensToRemove);
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Finished removing all events for instance = " + instance + "\n");
+ }
+ }
+
+ //
+ // WinRT event registration implementation code
+ //
+ internal static class NativeOrStaticEventRegistrationImpl
+ {
+ //
+ // Key = (target object, event)
+ // We use a key of object+event to save an extra dictionary
+ //
+ internal struct EventCacheKey
+ {
+ internal object target;
+ internal MethodInfo method;
+
+ public override string ToString()
+ {
+ return "(" + target + ", " + method + ")";
+ }
+ }
+
+ internal class EventCacheKeyEqualityComparer : IEqualityComparer<EventCacheKey>
+ {
+ public bool Equals(EventCacheKey lhs, EventCacheKey rhs)
+ {
+ return (Object.Equals(lhs.target, rhs.target) && Object.Equals(lhs.method, rhs.method));
+ }
+
+ public int GetHashCode(EventCacheKey key)
+ {
+ return key.target.GetHashCode() ^ key.method.GetHashCode();
+ }
+ }
+
+ //
+ // EventRegistrationTokenListWithCount
+ //
+ // A list of EventRegistrationTokens that maintains a count
+ //
+ // The reason this needs to be a separate class is that we need a finalizer for this class
+ // If the delegate is collected, it will take this list away with it (due to dependent handles),
+ // and we need to remove the PerInstancEntry from cache
+ // See ~EventRegistrationTokenListWithCount for more details
+ //
+ internal class EventRegistrationTokenListWithCount
+ {
+ private TokenListCount _tokenListCount;
+ EventRegistrationTokenList _tokenList;
+
+ internal EventRegistrationTokenListWithCount(TokenListCount tokenListCount, EventRegistrationToken token)
+ {
+ _tokenListCount = tokenListCount;
+ _tokenListCount.Inc();
+
+ _tokenList = new EventRegistrationTokenList(token);
+ }
+
+ ~EventRegistrationTokenListWithCount()
+ {
+ // Decrement token list count
+ // This is need to correctly keep trace of number of tokens for EventCacheKey
+ // and remove it from cache when the token count drop to 0
+ // we don't need to take locks for decrement the count - we only need to take a global
+ // lock when we decide to destroy cache for the IUnknown */type instance
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Finalizing EventRegistrationTokenList for " + _tokenListCount.Key + "\n");
+ _tokenListCount.Dec();
+ }
+
+ public void Push(EventRegistrationToken token)
+ {
+ // Since EventRegistrationTokenListWithCount is a reference type, there is no need
+ // to copy back. Ignore the return value
+ _tokenList.Push(token);
+ }
+
+ public bool Pop(out EventRegistrationToken token)
+ {
+ return _tokenList.Pop(out token);
+ }
+
+ public void CopyTo(List<EventRegistrationToken> tokens)
+ {
+ _tokenList.CopyTo(tokens);
+ }
+ }
+
+ //
+ // Maintains the number of tokens for a particular EventCacheKey
+ // TokenListCount is a class for two reasons:
+ // 1. Efficient update in the Dictionary to avoid lookup twice to update the value
+ // 2. Update token count without taking a global lock. Only takes a global lock when drop to 0
+ //
+ internal class TokenListCount
+ {
+ private int _count;
+ private EventCacheKey _key;
+
+ internal TokenListCount(EventCacheKey key)
+ {
+ _key = key;
+ }
+
+ internal EventCacheKey Key
+ {
+
+ get { return _key; }
+ }
+
+ internal void Inc()
+ {
+ int newCount = Interlocked.Increment(ref _count);
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Incremented TokenListCount for " + _key + ", Value = " + newCount + "\n");
+ }
+
+ internal void Dec()
+ {
+ // Avoid racing with Add/Remove event entries into the cache
+ // You don't want this removing the key in the middle of a Add/Remove
+ s_eventCacheRWLock.AcquireWriterLock(Timeout.Infinite);
+ try
+ {
+ int newCount = Interlocked.Decrement(ref _count);
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Decremented TokenListCount for " + _key + ", Value = " + newCount + "\n");
+ if (newCount == 0)
+ CleanupCache();
+ }
+ finally
+ {
+ s_eventCacheRWLock.ReleaseWriterLock();
+ }
+ }
+
+ private void CleanupCache()
+ {
+ // Time to destroy cache for this IUnknown */type instance
+ // because the total token list count has dropped to 0 and we don't have any events subscribed
+ Contract.Requires(s_eventRegistrations != null);
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Removing " + _key + " from cache" + "\n");
+ s_eventRegistrations.Remove(_key);
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] s_eventRegistrations size = " + s_eventRegistrations.Count + "\n");
+ }
+ }
+
+ internal struct EventCacheEntry
+ {
+ // [Handler] -> Token
+ internal ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTable;
+
+ // Maintains current total count for the EventRegistrationTokenListWithCount for this event cache key
+ internal TokenListCount tokenListCount;
+ }
+
+ // Mappings of delegates registered for events -> their registration tokens.
+ // These mappings are stored indexed by the remove method which can be used to undo the registrations.
+ //
+ // The full structure of this table is:
+ // EventCacheKey (instanceKey, eventMethod) -> EventCacheEntry (Handler->tokens)
+ //
+ // A InstanceKey is the IUnknown * or static type instance
+ //
+ // Couple of things to note:
+ // 1. We need to use IUnknown* because we want to be able to unscribe to the event for another RCW
+ // based on the same COM object. For example:
+ // m_canvas.GetAt(0).Event += Func;
+ // m_canvas.GetAt(0).Event -= Func; // GetAt(0) might create a new RCW
+ //
+ // 2. Handler->Token is a ConditionalWeakTable because we don't want to keep the delegate alive
+ // and we want EventRegistrationTokenListWithCount to be finalized after the delegate is no longer alive
+ // 3. It is possible another COM object is created at the same address
+ // before the entry in cache is destroyed. More specifically,
+ // a. The same delegate is being unsubscribed. In this case we'll give them a
+ // stale token - unlikely to be a problem
+ // b. The same delegate is subscribed then unsubscribed. We need to make sure give
+ // them the latest token in this case. This is guaranteed by always giving the last token and always use equality to
+ // add/remove event handlers
+ internal volatile static Dictionary<EventCacheKey, EventCacheEntry> s_eventRegistrations =
+ new Dictionary<EventCacheKey, EventCacheEntry>(new EventCacheKeyEqualityComparer());
+
+ // Prevent add/remove handler code to run at the same with with cache cleanup code
+ private volatile static MyReaderWriterLock s_eventCacheRWLock = new MyReaderWriterLock();
+
+ // Get InstanceKey to use in the cache
+ [SecuritySafeCritical]
+ private static object GetInstanceKey(Action<EventRegistrationToken> removeMethod)
+ {
+ object target = removeMethod.Target;
+ Contract.Assert(target == null || Marshal.IsComObject(target), "Must be null or a RCW");
+ if (target == null)
+ return removeMethod.Method.DeclaringType;
+
+ // Need the "Raw" IUnknown pointer for the RCW that is not bound to the current context
+ return (object) Marshal.GetRawIUnknownForComObjectNoAddRef(target);
+ }
+
+ [SecurityCritical]
+ internal static void AddEventHandler<T>(Func<T, EventRegistrationToken> addMethod,
+ Action<EventRegistrationToken> removeMethod,
+ T handler)
+ {
+ // The instanceKey will be IUnknown * of the target object
+ object instanceKey = GetInstanceKey(removeMethod);
+
+ // Call addMethod outside of RW lock
+ // At this point we don't need to worry about race conditions and we can avoid deadlocks
+ // if addMethod waits on finalizer thread
+ // If we later throw we need to remove the method
+ EventRegistrationToken token = addMethod(handler);
+
+ bool tokenAdded = false;
+
+ try
+ {
+ EventRegistrationTokenListWithCount tokens;
+
+ //
+ // The whole add/remove code has to be protected by a reader/writer lock
+ // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
+ //
+ s_eventCacheRWLock.AcquireReaderLock(Timeout.Infinite);
+ try
+ {
+ // Add the method, and make a note of the delegate -> token mapping.
+ TokenListCount tokenListCount;
+ ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTokens = GetOrCreateEventRegistrationTokenTable(instanceKey, removeMethod, out tokenListCount);
+ lock (registrationTokens)
+ {
+ //
+ // We need to find the key that equals to this handler
+ // Suppose we have 3 handlers A, B, C that are equal (refer to the same object and method),
+ // the first handler (let's say A) will be used as the key and holds all the tokens.
+ // We don't need to hold onto B and C, because the COM object itself will keep them alive,
+ // and they won't die anyway unless the COM object dies or they get unsubscribed.
+ // It may appear that it is fine to hold A, B, C, and add them and their corresponding tokens
+ // into registrationTokens table. However, this is very dangerous, because this COM object
+ // may die, but A, B, C might not get collected yet, and another COM object comes into life
+ // with the same IUnknown address, and we subscribe event B. In this case, the right token
+ // will be added into B's token list, but once we unsubscribe B, we might end up removing
+ // the last token in C, and that may lead to crash.
+ //
+ object key = registrationTokens.FindEquivalentKeyUnsafe(handler, out tokens);
+ if (key == null)
+ {
+ tokens = new EventRegistrationTokenListWithCount(tokenListCount, token);
+ registrationTokens.Add(handler, tokens);
+ }
+ else
+ {
+ tokens.Push(token);
+ }
+
+ tokenAdded = true;
+ }
+ }
+ finally
+ {
+ s_eventCacheRWLock.ReleaseReaderLock();
+ }
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event subscribed for instance = " + instanceKey + ", handler = " + handler + "\n");
+ }
+ catch(Exception)
+ {
+ // If we've already added the token and go there, we don't need to "UNDO" anything
+ if (!tokenAdded)
+ {
+ // Otherwise, "Undo" addMethod if any exception occurs
+ // There is no need to cleanup our data structure as we haven't added the token yet
+ removeMethod(token);
+ }
+
+
+ throw;
+ }
+ }
+
+ private static ConditionalWeakTable<object, EventRegistrationTokenListWithCount> GetEventRegistrationTokenTableNoCreate(object instance, Action<EventRegistrationToken> removeMethod, out TokenListCount tokenListCount)
+ {
+ Contract.Requires(instance != null);
+ Contract.Requires(removeMethod != null);
+
+ return GetEventRegistrationTokenTableInternal(instance, removeMethod, out tokenListCount, /* createIfNotFound = */ false);
+ }
+
+ private static ConditionalWeakTable<object, EventRegistrationTokenListWithCount> GetOrCreateEventRegistrationTokenTable(object instance, Action<EventRegistrationToken> removeMethod, out TokenListCount tokenListCount)
+ {
+ Contract.Requires(instance != null);
+ Contract.Requires(removeMethod != null);
+
+ return GetEventRegistrationTokenTableInternal(instance, removeMethod, out tokenListCount, /* createIfNotFound = */ true);
+ }
+
+ // Get the event registration token table for an event. These are indexed by the remove method of the event.
+ private static ConditionalWeakTable<object, EventRegistrationTokenListWithCount> GetEventRegistrationTokenTableInternal(object instance, Action<EventRegistrationToken> removeMethod, out TokenListCount tokenListCount, bool createIfNotFound)
+ {
+ Contract.Requires(instance != null);
+ Contract.Requires(removeMethod != null);
+ Contract.Requires(s_eventRegistrations != null);
+
+ EventCacheKey eventCacheKey;
+ eventCacheKey.target = instance;
+ eventCacheKey.method = removeMethod.Method;
+
+ lock (s_eventRegistrations)
+ {
+ EventCacheEntry eventCacheEntry;
+ if (!s_eventRegistrations.TryGetValue(eventCacheKey, out eventCacheEntry))
+ {
+ if (!createIfNotFound)
+ {
+ // No need to create an entry in this case
+ tokenListCount = null;
+ return null;
+ }
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Adding (" + instance + "," + removeMethod.Method + ") into cache" + "\n");
+
+ eventCacheEntry = new EventCacheEntry();
+ eventCacheEntry.registrationTable = new ConditionalWeakTable<object, EventRegistrationTokenListWithCount>();
+ eventCacheEntry.tokenListCount = new TokenListCount(eventCacheKey);
+
+ s_eventRegistrations.Add(eventCacheKey, eventCacheEntry);
+ }
+
+ tokenListCount = eventCacheEntry.tokenListCount;
+
+ return eventCacheEntry.registrationTable;
+ }
+ }
+
+ [SecurityCritical]
+ internal static void RemoveEventHandler<T>(Action<EventRegistrationToken> removeMethod, T handler)
+ {
+ object instanceKey = GetInstanceKey(removeMethod);
+
+ EventRegistrationToken token;
+
+ //
+ // The whole add/remove code has to be protected by a reader/writer lock
+ // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
+ //
+ s_eventCacheRWLock.AcquireReaderLock(Timeout.Infinite);
+ try
+ {
+ TokenListCount tokenListCount;
+ ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out tokenListCount);
+ if (registrationTokens == null)
+ {
+ // We have no information regarding this particular instance (IUnknown*/type) - just return
+ // This is necessary to avoid leaking empty dictionary/conditionalWeakTables for this instance
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] no registrationTokens found for instance=" + instanceKey + ", handler= " + handler + "\n");
+ return;
+ }
+
+ lock (registrationTokens)
+ {
+ EventRegistrationTokenListWithCount tokens;
+
+ // Note:
+ // When unsubscribing events, we allow subscribing the event using a different delegate
+ // (but with the same object/method), so we need to find the first delegate that matches
+ // and unsubscribe it
+ // It actually doesn't matter which delegate - as long as it matches
+ // Note that inside TryGetValueWithValueEquality we assumes that any delegate
+ // with the same value equality would have the same hash code
+ object key = registrationTokens.FindEquivalentKeyUnsafe(handler, out tokens);
+ Contract.Assert((key != null && tokens != null) || (key == null && tokens == null),
+ "key and tokens must be both null or non-null");
+ if (tokens == null)
+ {
+ // Failure to find a registration for a token is not an error - it's simply a no-op.
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] no token list found for instance=" + instanceKey + ", handler= " + handler + "\n");
+ return;
+ }
+
+ // Select a registration token to unregister
+ // Note that we need to always get the last token just in case another COM object
+ // is created at the same address before the entry for the old one goes away.
+ // See comments above s_eventRegistrations for more details
+ bool moreItems = tokens.Pop(out token);
+
+ // If the last token is removed from token list, we need to remove it from the cache
+ // otherwise FindEquivalentKeyUnsafe may found this empty token list even though there could be other
+ // equivalent keys in there with non-0 token list
+ if (!moreItems)
+ {
+ // Remove it from (handler)->(tokens)
+ // NOTE: We should not check whether registrationTokens has 0 entries and remove it from the cache
+ // (just like managed event implementation), because this might have raced with the finalizer of
+ // EventRegistrationTokenList
+ registrationTokens.Remove(key);
+ }
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for managed instance = " + instanceKey + ", handler = " + handler + ", token = " + token.m_value + "\n");
+ }
+ }
+ finally
+ {
+ s_eventCacheRWLock.ReleaseReaderLock();
+ }
+
+ // Call removeMethod outside of RW lock
+ // At this point we don't need to worry about race conditions and we can avoid deadlocks
+ // if removeMethod waits on finalizer thread
+ removeMethod(token);
+ }
+
+ [SecurityCritical]
+ internal static void RemoveAllEventHandlers(Action<EventRegistrationToken> removeMethod)
+ {
+ object instanceKey = GetInstanceKey(removeMethod);
+
+ List<EventRegistrationToken> tokensToRemove = new List<EventRegistrationToken>();
+
+ //
+ // The whole add/remove code has to be protected by a reader/writer lock
+ // Add/Remove cannot run at the same time with cache cleanup but Add/Remove can run at the same time
+ //
+ s_eventCacheRWLock.AcquireReaderLock(Timeout.Infinite);
+ try
+ {
+ TokenListCount tokenListCount;
+ ConditionalWeakTable<object, EventRegistrationTokenListWithCount> registrationTokens = GetEventRegistrationTokenTableNoCreate(instanceKey, removeMethod, out tokenListCount);
+ if (registrationTokens == null)
+ {
+ // We have no information regarding this particular instance (IUnknown*/type) - just return
+ // This is necessary to avoid leaking empty dictionary/conditionalWeakTables for this instance
+ return;
+ }
+
+ lock (registrationTokens)
+ {
+ // Copy all tokens to tokensToRemove array which later we'll call removeMethod on
+ // outside this lock
+ foreach (EventRegistrationTokenListWithCount tokens in registrationTokens.Values)
+ {
+ tokens.CopyTo(tokensToRemove);
+ }
+
+ // Clear the table - at this point all event handlers are no longer in the cache
+ // but they are not removed yet
+ registrationTokens.Clear();
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Cache cleared for managed instance = " + instanceKey + "\n");
+ }
+ }
+ finally
+ {
+ s_eventCacheRWLock.ReleaseReaderLock();
+ }
+
+ //
+ // Remove all handlers outside the lock
+ //
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Start removing all events for instance = " + instanceKey + "\n");
+ CallRemoveMethods(removeMethod, tokensToRemove);
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Finished removing all events for instance = " + instanceKey + "\n");
+ }
+
+
+ internal class ReaderWriterLockTimedOutException : ApplicationException
+ {
+ }
+
+ /// I borrowed Vance's reader writer lock implementation from his blog as ReaderWriterLockSlim is
+ /// available in System.Core.dll!
+ ///
+ /// <summary>
+ /// A reader-writer lock implementation that is intended to be simple, yet very
+ /// efficient. In particular only 1 interlocked operation is taken for any lock
+ /// operation (we use spin locks to achieve this). The spin lock is never held
+ /// for more than a few instructions (in particular, we never call event APIs
+ /// or in fact any non-trivial API while holding the spin lock).
+ ///
+ /// Currently this ReaderWriterLock does not support recurision, however it is
+ /// not hard to add
+ /// </summary>
+ internal class MyReaderWriterLock
+ {
+ // Lock specifiation for myLock: This lock protects exactly the local fields associted
+ // instance of MyReaderWriterLock. It does NOT protect the memory associted with the
+ // the events that hang off this lock (eg writeEvent, readEvent upgradeEvent).
+ int myLock;
+
+ // Who owns the lock owners > 0 => readers
+ // owners = -1 means there is one writer. Owners must be >= -1.
+ int owners;
+
+ // These variables allow use to avoid Setting events (which is expensive) if we don't have to.
+ uint numWriteWaiters; // maximum number of threads that can be doing a WaitOne on the writeEvent
+ uint numReadWaiters; // maximum number of threads that can be doing a WaitOne on the readEvent
+
+ // conditions we wait on.
+ EventWaitHandle writeEvent; // threads waiting to aquire a write lock go here.
+ EventWaitHandle readEvent; // threads waiting to aquire a read lock go here (will be released in bulk)
+
+ internal MyReaderWriterLock()
+ {
+ // All state can start out zeroed.
+ }
+
+ internal void AcquireReaderLock(int millisecondsTimeout)
+ {
+ EnterMyLock();
+ for (; ; )
+ {
+ // We can enter a read lock if there are only read-locks have been given out
+ // and a writer is not trying to get in.
+ if (owners >= 0 && numWriteWaiters == 0)
+ {
+ // Good case, there is no contention, we are basically done
+ owners++; // Indicate we have another reader
+ break;
+ }
+
+ // Drat, we need to wait. Mark that we have waiters and wait.
+ if (readEvent == null) // Create the needed event
+ {
+ LazyCreateEvent(ref readEvent, false);
+ continue; // since we left the lock, start over.
+ }
+
+ WaitOnEvent(readEvent, ref numReadWaiters, millisecondsTimeout);
+ }
+ ExitMyLock();
+ }
+
+ internal void AcquireWriterLock(int millisecondsTimeout)
+ {
+ EnterMyLock();
+ for (; ; )
+ {
+ if (owners == 0)
+ {
+ // Good case, there is no contention, we are basically done
+ owners = -1; // indicate we have a writer.
+ break;
+ }
+
+ // Drat, we need to wait. Mark that we have waiters and wait.
+ if (writeEvent == null) // create the needed event.
+ {
+ LazyCreateEvent(ref writeEvent, true);
+ continue; // since we left the lock, start over.
+ }
+
+ WaitOnEvent(writeEvent, ref numWriteWaiters, millisecondsTimeout);
+ }
+ ExitMyLock();
+ }
+
+ internal void ReleaseReaderLock()
+ {
+ EnterMyLock();
+ Contract.Assert(owners > 0, "ReleasingReaderLock: releasing lock and no read lock taken");
+ --owners;
+ ExitAndWakeUpAppropriateWaiters();
+ }
+
+ internal void ReleaseWriterLock()
+ {
+ EnterMyLock();
+ Contract.Assert(owners == -1, "Calling ReleaseWriterLock when no write lock is held");
+ owners++;
+ ExitAndWakeUpAppropriateWaiters();
+ }
+
+ /// <summary>
+ /// A routine for lazily creating a event outside the lock (so if errors
+ /// happen they are outside the lock and that we don't do much work
+ /// while holding a spin lock). If all goes well, reenter the lock and
+ /// set 'waitEvent'
+ /// </summary>
+ private void LazyCreateEvent(ref EventWaitHandle waitEvent, bool makeAutoResetEvent) {
+ Contract.Assert(myLock != 0, "Lock must be held");
+ Contract.Assert(waitEvent == null, "Wait event must be null");
+
+ ExitMyLock();
+ EventWaitHandle newEvent;
+ if (makeAutoResetEvent)
+ newEvent = new AutoResetEvent(false);
+ else
+ newEvent = new ManualResetEvent(false);
+ EnterMyLock();
+ if (waitEvent == null) // maybe someone snuck in.
+ waitEvent = newEvent;
+ }
+
+ /// <summary>
+ /// Waits on 'waitEvent' with a timeout of 'millisceondsTimeout.
+ /// Before the wait 'numWaiters' is incremented and is restored before leaving this routine.
+ /// </summary>
+ private void WaitOnEvent(EventWaitHandle waitEvent, ref uint numWaiters, int millisecondsTimeout)
+ {
+ Contract.Assert(myLock != 0, "Lock must be held");
+
+ waitEvent.Reset();
+ numWaiters++;
+
+ bool waitSuccessful = false;
+ ExitMyLock(); // Do the wait outside of any lock
+ try
+ {
+ if (!waitEvent.WaitOne(millisecondsTimeout, false))
+ throw new ReaderWriterLockTimedOutException();
+
+ waitSuccessful = true;
+ }
+ finally
+ {
+ EnterMyLock();
+ --numWaiters;
+ if (!waitSuccessful) // We are going to throw for some reason. Exit myLock.
+ ExitMyLock();
+ }
+ }
+
+ /// <summary>
+ /// Determines the appropriate events to set, leaves the locks, and sets the events.
+ /// </summary>
+ private void ExitAndWakeUpAppropriateWaiters()
+ {
+ Contract.Assert(myLock != 0, "Lock must be held");
+
+ if (owners == 0 && numWriteWaiters > 0)
+ {
+ ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
+ writeEvent.Set(); // release one writer.
+ }
+ else if (owners >= 0 && numReadWaiters != 0)
+ {
+ ExitMyLock(); // Exit before signaling to improve efficiency (wakee will need the lock)
+ readEvent.Set(); // release all readers.
+ }
+ else
+ ExitMyLock();
+ }
+
+ private void EnterMyLock() {
+ if (Interlocked.CompareExchange(ref myLock, 1, 0) != 0)
+ EnterMyLockSpin();
+ }
+
+ private void EnterMyLockSpin()
+ {
+ for (int i = 0; ;i++)
+ {
+ if (i < 3 && Environment.ProcessorCount > 1)
+ Thread.SpinWait(20); // Wait a few dozen instructions to let another processor release lock.
+ else
+ Thread.Sleep(0); // Give up my quantum.
+
+ if (Interlocked.CompareExchange(ref myLock, 1, 0) == 0)
+ return;
+ }
+ }
+ private void ExitMyLock()
+ {
+ Contract.Assert(myLock != 0, "Exiting spin lock that is not held");
+ myLock = 0;
+ }
+ };
+ }
+
+ //
+ // Call removeMethod on each token and aggregate all exceptions thrown from removeMethod into one in case of failure
+ //
+ internal static void CallRemoveMethods(Action<EventRegistrationToken> removeMethod, List<EventRegistrationToken> tokensToRemove)
+ {
+
+ List<Exception> exceptions = new List<Exception>();
+
+ foreach (EventRegistrationToken token in tokensToRemove)
+ {
+ try
+ {
+ removeMethod(token);
+ }
+ catch(Exception ex)
+ {
+ exceptions.Add(ex);
+ }
+
+ BCLDebug.Log("INTEROP", "[WinRT_Eventing] Event unsubscribed for token = " + token.m_value + "\n");
+ }
+
+ if (exceptions.Count > 0)
+ throw new AggregateException(exceptions.ToArray());
+ }
+
+ [SecurityCritical]
+ internal static unsafe string HStringToString(IntPtr hstring)
+ {
+ Contract.Requires(Environment.IsWinRTSupported);
+
+ // There is no difference between a null and empty HSTRING
+ if (hstring == IntPtr.Zero)
+ {
+ return String.Empty;
+ }
+
+ unsafe
+ {
+ uint length;
+ char* rawBuffer = UnsafeNativeMethods.WindowsGetStringRawBuffer(hstring, &length);
+ return new String(rawBuffer, 0, checked((int)length));
+ }
+ }
+
+ internal static Exception GetExceptionForHR(int hresult, Exception innerException, string messageResource)
+ {
+ Exception e = null;
+ if (innerException != null)
+ {
+ string message = innerException.Message;
+ if (message == null && messageResource != null)
+ {
+ message = Environment.GetResourceString(messageResource);
+ }
+ e = new Exception(message, innerException);
+ }
+ else
+ {
+ string message = (messageResource != null ? Environment.GetResourceString(messageResource) : null);
+ e = new Exception(message);
+ }
+
+ e.SetErrorCode(hresult);
+ return e;
+ }
+
+ internal static Exception GetExceptionForHR(int hresult, Exception innerException)
+ {
+ return GetExceptionForHR(hresult, innerException, null);
+ }
+
+ private static bool s_haveBlueErrorApis = true;
+
+ [SecurityCritical]
+ private static bool RoOriginateLanguageException(int error, string message, IntPtr languageException)
+ {
+ if (s_haveBlueErrorApis)
+ {
+ try
+ {
+ return UnsafeNativeMethods.RoOriginateLanguageException(error, message, languageException);
+ }
+ catch (EntryPointNotFoundException)
+ {
+ s_haveBlueErrorApis = false;
+ }
+ }
+
+ return false;
+ }
+
+ [SecurityCritical]
+ private static void RoReportUnhandledError(IRestrictedErrorInfo error)
+ {
+ if (s_haveBlueErrorApis)
+ {
+ try
+ {
+ UnsafeNativeMethods.RoReportUnhandledError(error);
+ }
+ catch (EntryPointNotFoundException)
+ {
+ s_haveBlueErrorApis = false;
+ }
+ }
+ }
+
+ private static Guid s_iidIErrorInfo = new Guid(0x1CF2B120, 0x547D, 0x101B, 0x8E, 0x65, 0x08, 0x00, 0x2B, 0x2B, 0xD1, 0x19);
+
+ /// <summary>
+ /// Report that an exception has occurred which went user unhandled. This allows the global error handler
+ /// for the application to be invoked to process the error.
+ /// </summary>
+ /// <returns>true if the error was reported, false if not (ie running on Win8)</returns>
+ [FriendAccessAllowed]
+ [SecuritySafeCritical]
+ internal static bool ReportUnhandledError(Exception e)
+ {
+ // Only report to the WinRT global exception handler in modern apps
+ if (!AppDomain.IsAppXModel())
+ {
+ return false;
+ }
+
+ // If we don't have the capability to report to the global error handler, early out
+ if (!s_haveBlueErrorApis)
+ {
+ return false;
+ }
+
+ if (e != null)
+ {
+ IntPtr exceptionIUnknown = IntPtr.Zero;
+ IntPtr exceptionIErrorInfo = IntPtr.Zero;
+ try
+ {
+ // Get an IErrorInfo for the current exception and originate it as a langauge error in order to have
+ // Windows generate an IRestrictedErrorInfo corresponding to the exception object. We can then
+ // notify the global error handler that this IRestrictedErrorInfo instance represents an exception that
+ // went unhandled in managed code.
+ //
+ // Note that we need to get an IUnknown for the exception object and then QI for IErrorInfo since Exception
+ // doesn't implement IErrorInfo in managed code - only its CCW does.
+ exceptionIUnknown = Marshal.GetIUnknownForObject(e);
+ if (exceptionIUnknown != IntPtr.Zero)
+ {
+ Marshal.QueryInterface(exceptionIUnknown, ref s_iidIErrorInfo, out exceptionIErrorInfo);
+ if (exceptionIErrorInfo != IntPtr.Zero)
+ {
+ if (RoOriginateLanguageException(Marshal.GetHRForException_WinRT(e), e.Message, exceptionIErrorInfo))
+ {
+ IRestrictedErrorInfo restrictedError = UnsafeNativeMethods.GetRestrictedErrorInfo();
+ if (restrictedError != null)
+ {
+ RoReportUnhandledError(restrictedError);
+ return true;
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ if (exceptionIErrorInfo != IntPtr.Zero)
+ {
+ Marshal.Release(exceptionIErrorInfo);
+ }
+
+ if (exceptionIUnknown != IntPtr.Zero)
+ {
+ Marshal.Release(exceptionIUnknown);
+ }
+ }
+ }
+
+ // If we got here, then some step of the marshaling failed, which means the GEH was not invoked
+ return false;
+ }
+
+#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
+ // Get an IActivationFactory * for a managed type
+ [SecurityCritical]
+ internal static IntPtr GetActivationFactoryForType(Type type)
+ {
+ ManagedActivationFactory activationFactory = GetManagedActivationFactory(type);
+ return Marshal.GetComInterfaceForObject(activationFactory, typeof(IActivationFactory));
+ }
+
+ [SecurityCritical]
+ internal static ManagedActivationFactory GetManagedActivationFactory(Type type)
+ {
+ ManagedActivationFactory activationFactory = new ManagedActivationFactory(type);
+
+ // If the type has any associated factory interfaces (i.e. supports non-default activation
+ // or has statics), the CCW for this instance of ManagedActivationFactory must support them.
+ Marshal.InitializeManagedWinRTFactoryObject(activationFactory, (RuntimeType)type);
+ return activationFactory;
+ }
+
+#if FEATURE_COMINTEROP_WINRT_DESKTOP_HOST
+ // Currently we use only a single class activator since we have a requirement that all class activations come from the same
+ // app base and we haven't sorted through the various code sharing implications of spinning up multiple AppDomains. This
+ // holds the IWinRTClassActivator* that is used for the process
+ private static IntPtr s_pClassActivator = IntPtr.Zero;
+
+ [SecurityCritical]
+ internal static IntPtr GetClassActivatorForApplication(string appBase)
+ {
+ if (s_pClassActivator == IntPtr.Zero)
+ {
+ AppDomainSetup hostDomainSetup = new AppDomainSetup()
+ {
+ ApplicationBase = appBase,
+ };
+
+ AppDomain hostDomain = AppDomain.CreateDomain(Environment.GetResourceString("WinRTHostDomainName", appBase), null, hostDomainSetup);
+ WinRTClassActivator activator = (WinRTClassActivator)hostDomain.CreateInstanceAndUnwrap(typeof(WinRTClassActivator).Assembly.FullName, typeof(WinRTClassActivator).FullName);
+ IntPtr pActivator = activator.GetIWinRTClassActivator();
+
+ if (Interlocked.CompareExchange(ref s_pClassActivator, pActivator, IntPtr.Zero) != IntPtr.Zero)
+ {
+ Marshal.Release(pActivator);
+ activator = null;
+
+ try
+ {
+ AppDomain.Unload(hostDomain);
+ }
+ catch (CannotUnloadAppDomainException) { }
+ }
+ }
+
+ Marshal.AddRef(s_pClassActivator);
+ return s_pClassActivator;
+ }
+#endif // FEATURE_COMINTEROP_WINRT_DESKTOP_HOST
+
+#endif // FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
+
+ //
+ // Get activation factory object for a specified WinRT type
+ // If the WinRT type is a native type, we'll always create a unique RCW for it,
+ // This is necessary because WinRT factories are often implemented as a singleton,
+ // and getting back a RCW for such WinRT factory would usually get back a RCW from
+ // another apartment, even if the interface pointe returned from GetActivationFactory
+ // is a raw pointer. As a result, user would randomly get back RCWs for activation
+ // factories from other apartments and make transiton to those apartments and cause
+ // deadlocks and create objects in incorrect apartments
+ //
+ [SecurityCritical]
+ public static IActivationFactory GetActivationFactory(Type type)
+ {
+ if (type == null)
+ throw new ArgumentNullException("type");
+
+ if (type.IsWindowsRuntimeObject && type.IsImport)
+ {
+ return (IActivationFactory)Marshal.GetNativeActivationFactory(type);
+ }
+ else
+ {
+#if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
+ return GetManagedActivationFactory(type);
+#else
+ // Managed factories are not supported so as to minimize public surface (and test effort)
+ throw new NotSupportedException();
+#endif
+ }
+ }
+
+ // HSTRING marshaling methods:
+
+ [SecurityCritical]
+ public static IntPtr StringToHString(String s)
+ {
+ if (!Environment.IsWinRTSupported)
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+
+ if (s == null)
+ throw new ArgumentNullException("s");
+
+ unsafe
+ {
+ IntPtr hstring;
+ int hrCreate = UnsafeNativeMethods.WindowsCreateString(s, s.Length, &hstring);
+ Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
+ return hstring;
+ }
+ }
+
+ [SecurityCritical]
+ public static String PtrToStringHString(IntPtr ptr)
+ {
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ return HStringToString(ptr);
+ }
+
+ [SecurityCritical]
+ public static void FreeHString(IntPtr ptr)
+ {
+ if (!Environment.IsWinRTSupported)
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+
+ if (ptr != IntPtr.Zero)
+ {
+ UnsafeNativeMethods.WindowsDeleteString(ptr);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs
new file mode 100644
index 0000000000..e2ad203583
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/InteropServices/WindowsRuntime/WindowsRuntimeMetadata.cs
@@ -0,0 +1,216 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Runtime.InteropServices.WindowsRuntime
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Security;
+
+ public static class WindowsRuntimeMetadata
+ {
+ // Wrapper for Win8 API RoResolveNamespace with default Windows SDK path as installed .winmd files in %WINDIR%\system32\WinMetadata.
+ [System.Security.SecurityCritical]
+ public static IEnumerable<string> ResolveNamespace(string namespaceName, IEnumerable<string> packageGraphFilePaths)
+ {
+ return ResolveNamespace(namespaceName, null, packageGraphFilePaths);
+ }
+
+ // Wrapper for Win8 API RoResolveNamespace.
+ [System.Security.SecurityCritical]
+ public static IEnumerable<string> ResolveNamespace(string namespaceName, string windowsSdkFilePath, IEnumerable<string> packageGraphFilePaths)
+ {
+ if (namespaceName == null)
+ throw new ArgumentNullException("namespaceName");
+ Contract.EndContractBlock();
+
+ string[] packageGraphFilePathsArray = null;
+ if (packageGraphFilePaths != null)
+ {
+ List<string> packageGraphFilePathsList = new List<string>(packageGraphFilePaths);
+ packageGraphFilePathsArray = new string[packageGraphFilePathsList.Count];
+
+ int index = 0;
+ foreach (string packageGraphFilePath in packageGraphFilePathsList)
+ {
+ packageGraphFilePathsArray[index] = packageGraphFilePath;
+ index++;
+ }
+ }
+
+ string[] retFileNames = null;
+ nResolveNamespace(
+ namespaceName,
+ windowsSdkFilePath,
+ packageGraphFilePathsArray,
+ ((packageGraphFilePathsArray == null) ? 0 : packageGraphFilePathsArray.Length),
+ JitHelpers.GetObjectHandleOnStack(ref retFileNames));
+
+ return retFileNames;
+ }
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void nResolveNamespace(
+ string namespaceName,
+ string windowsSdkFilePath,
+ string[] packageGraphFilePaths,
+ int cPackageGraphFilePaths,
+ ObjectHandleOnStack retFileNames);
+
+#if FEATURE_REFLECTION_ONLY_LOAD
+ [method: System.Security.SecurityCritical]
+ public static event EventHandler<NamespaceResolveEventArgs> ReflectionOnlyNamespaceResolve;
+
+ internal static RuntimeAssembly[] OnReflectionOnlyNamespaceResolveEvent(AppDomain appDomain, RuntimeAssembly assembly, string namespaceName)
+ {
+ EventHandler<NamespaceResolveEventArgs> eventHandler = ReflectionOnlyNamespaceResolve;
+ if (eventHandler != null)
+ {
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++)
+ {
+ NamespaceResolveEventArgs eventArgs = new NamespaceResolveEventArgs(namespaceName, assembly);
+
+ ((EventHandler<NamespaceResolveEventArgs>)ds[i])(appDomain, eventArgs);
+
+ Collection<Assembly> assembliesCollection = eventArgs.ResolvedAssemblies;
+ if (assembliesCollection.Count > 0)
+ {
+ RuntimeAssembly[] retAssemblies = new RuntimeAssembly[assembliesCollection.Count];
+ int retIndex = 0;
+ foreach (Assembly asm in assembliesCollection)
+ {
+ retAssemblies[retIndex] = AppDomain.GetRuntimeAssembly(asm);
+ retIndex++;
+ }
+ return retAssemblies;
+ }
+ }
+ }
+
+ return null;
+ }
+#endif //FEATURE_REFLECTION_ONLY
+
+ [method: System.Security.SecurityCritical]
+ public static event EventHandler<DesignerNamespaceResolveEventArgs> DesignerNamespaceResolve;
+
+ internal static string[] OnDesignerNamespaceResolveEvent(AppDomain appDomain, string namespaceName)
+ {
+ EventHandler<DesignerNamespaceResolveEventArgs> eventHandler = DesignerNamespaceResolve;
+ if (eventHandler != null)
+ {
+ Delegate[] ds = eventHandler.GetInvocationList();
+ int len = ds.Length;
+ for (int i = 0; i < len; i++)
+ {
+ DesignerNamespaceResolveEventArgs eventArgs = new DesignerNamespaceResolveEventArgs(namespaceName);
+
+ ((EventHandler<DesignerNamespaceResolveEventArgs>)ds[i])(appDomain, eventArgs);
+
+ Collection<string> assemblyFilesCollection = eventArgs.ResolvedAssemblyFiles;
+ if (assemblyFilesCollection.Count > 0)
+ {
+ string[] retAssemblyFiles = new string[assemblyFilesCollection.Count];
+ int retIndex = 0;
+ foreach (string assemblyFile in assemblyFilesCollection)
+ {
+ if (String.IsNullOrEmpty(assemblyFile))
+ { // DesignerNamespaceResolve event returned null or empty file name - that is not allowed
+ throw new ArgumentException(Environment.GetResourceString("Arg_EmptyOrNullString"), "DesignerNamespaceResolveEventArgs.ResolvedAssemblyFiles");
+ }
+ retAssemblyFiles[retIndex] = assemblyFile;
+ retIndex++;
+ }
+
+ return retAssemblyFiles;
+ }
+ }
+ }
+
+ return null;
+ }
+ }
+
+#if FEATURE_REFLECTION_ONLY_LOAD
+ [ComVisible(false)]
+ public class NamespaceResolveEventArgs : EventArgs
+ {
+ private string _NamespaceName;
+ private Assembly _RequestingAssembly;
+ private Collection<Assembly> _ResolvedAssemblies;
+
+ public string NamespaceName
+ {
+ get
+ {
+ return _NamespaceName;
+ }
+ }
+
+ public Assembly RequestingAssembly
+ {
+ get
+ {
+ return _RequestingAssembly;
+ }
+ }
+
+ public Collection<Assembly> ResolvedAssemblies
+ {
+ get
+ {
+ return _ResolvedAssemblies;
+ }
+ }
+
+ public NamespaceResolveEventArgs(string namespaceName, Assembly requestingAssembly)
+ {
+ _NamespaceName = namespaceName;
+ _RequestingAssembly = requestingAssembly;
+ _ResolvedAssemblies = new Collection<Assembly>();
+ }
+ }
+#endif //FEATURE_REFLECTION_ONLY
+
+ [ComVisible(false)]
+ public class DesignerNamespaceResolveEventArgs : EventArgs
+ {
+ private string _NamespaceName;
+ private Collection<string> _ResolvedAssemblyFiles;
+
+ public string NamespaceName
+ {
+ get
+ {
+ return _NamespaceName;
+ }
+ }
+
+ public Collection<string> ResolvedAssemblyFiles
+ {
+ get
+ {
+ return _ResolvedAssemblyFiles;
+ }
+ }
+
+ public DesignerNamespaceResolveEventArgs(string namespaceName)
+ {
+ _NamespaceName = namespaceName;
+ _ResolvedAssemblyFiles = new Collection<string>();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
new file mode 100644
index 0000000000..75529868bd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Loader/AssemblyLoadContext.cs
@@ -0,0 +1,481 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Reflection;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Runtime.Versioning;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Threading;
+
+#if FEATURE_HOST_ASSEMBLY_RESOLVER
+
+namespace System.Runtime.Loader
+{
+ [System.Security.SecuritySafeCritical]
+ public abstract class AssemblyLoadContext
+ {
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern bool OverrideDefaultAssemblyLoadContextForCurrentDomain(IntPtr ptrNativeAssemblyLoadContext);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern bool CanUseAppPathAssemblyLoadContextInCurrentDomain();
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr InitializeAssemblyLoadContext(IntPtr ptrAssemblyLoadContext, bool fRepresentsTPALoadContext);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr LoadFromAssemblyName(IntPtr ptrNativeAssemblyLoadContext, bool fRepresentsTPALoadContext);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr LoadFromStream(IntPtr ptrNativeAssemblyLoadContext, IntPtr ptrAssemblyArray, int iAssemblyArrayLen, IntPtr ptrSymbols, int iSymbolArrayLen, ObjectHandleOnStack retAssembly);
+
+#if FEATURE_MULTICOREJIT
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void InternalSetProfileRoot(string directoryPath);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void InternalStartProfile(string profile, IntPtr ptrNativeAssemblyLoadContext);
+#endif // FEATURE_MULTICOREJIT
+
+ protected AssemblyLoadContext()
+ {
+ // Initialize the ALC representing non-TPA LoadContext
+ InitializeLoadContext(false);
+ }
+
+ internal AssemblyLoadContext(bool fRepresentsTPALoadContext)
+ {
+ // Initialize the ALC representing TPA LoadContext
+ InitializeLoadContext(fRepresentsTPALoadContext);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ void InitializeLoadContext(bool fRepresentsTPALoadContext)
+ {
+ // Initialize the VM side of AssemblyLoadContext if not already done.
+ GCHandle gchALC = GCHandle.Alloc(this);
+ IntPtr ptrALC = GCHandle.ToIntPtr(gchALC);
+ m_pNativeAssemblyLoadContext = InitializeAssemblyLoadContext(ptrALC, fRepresentsTPALoadContext);
+
+ // Initialize event handlers to be null by default
+ Resolving = null;
+ Unloading = null;
+
+ // Since unloading an AssemblyLoadContext is not yet implemented, this is a temporary solution to raise the
+ // Unloading event on process exit. Register for the current AppDomain's ProcessExit event, and the handler will in
+ // turn raise the Unloading event.
+ AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void LoadFromPath(IntPtr ptrNativeAssemblyLoadContext, string ilPath, string niPath, ObjectHandleOnStack retAssembly);
+
+ // These are helpers that can be used by AssemblyLoadContext derivations.
+ // They are used to load assemblies in DefaultContext.
+ public Assembly LoadFromAssemblyPath(string assemblyPath)
+ {
+ if (assemblyPath == null)
+ {
+ throw new ArgumentNullException("assemblyPath");
+ }
+
+ if (Path.IsRelative(assemblyPath))
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), "assemblyPath");
+ }
+
+ RuntimeAssembly loadedAssembly = null;
+ LoadFromPath(m_pNativeAssemblyLoadContext, assemblyPath, null, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly));
+ return loadedAssembly;
+ }
+
+ public Assembly LoadFromNativeImagePath(string nativeImagePath, string assemblyPath)
+ {
+ if (nativeImagePath == null)
+ {
+ throw new ArgumentNullException("nativeImagePath");
+ }
+
+ if (Path.IsRelative(nativeImagePath))
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_AbsolutePathRequired"), "nativeImagePath");
+ }
+
+ if (assemblyPath != null && Path.IsRelative(assemblyPath))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "assemblyPath");
+ }
+
+ // Basic validation has succeeded - lets try to load the NI image.
+ // Ask LoadFile to load the specified assembly in the DefaultContext
+ RuntimeAssembly loadedAssembly = null;
+ LoadFromPath(m_pNativeAssemblyLoadContext, assemblyPath, nativeImagePath, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly));
+ return loadedAssembly;
+ }
+
+ public Assembly LoadFromStream(Stream assembly)
+ {
+ return LoadFromStream(assembly, null);
+ }
+
+ public Assembly LoadFromStream(Stream assembly, Stream assemblySymbols)
+ {
+ if (assembly == null)
+ {
+ throw new ArgumentNullException("assembly");
+ }
+
+ int iAssemblyStreamLength = (int)assembly.Length;
+ int iSymbolLength = 0;
+
+ // Allocate the byte[] to hold the assembly
+ byte[] arrAssembly = new byte[iAssemblyStreamLength];
+
+ // Copy the assembly to the byte array
+ assembly.Read(arrAssembly, 0, iAssemblyStreamLength);
+
+ // Get the symbol stream in byte[] if provided
+ byte[] arrSymbols = null;
+ if (assemblySymbols != null)
+ {
+ iSymbolLength = (int)assemblySymbols.Length;
+ arrSymbols = new byte[iSymbolLength];
+
+ assemblySymbols.Read(arrSymbols, 0, iSymbolLength);
+ }
+
+ RuntimeAssembly loadedAssembly = null;
+ unsafe
+ {
+ fixed(byte *ptrAssembly = arrAssembly, ptrSymbols = arrSymbols)
+ {
+ LoadFromStream(m_pNativeAssemblyLoadContext, new IntPtr(ptrAssembly), iAssemblyStreamLength, new IntPtr(ptrSymbols), iSymbolLength, JitHelpers.GetObjectHandleOnStack(ref loadedAssembly));
+ }
+ }
+
+ return loadedAssembly;
+ }
+
+ // Custom AssemblyLoadContext implementations can override this
+ // method to perform custom processing and use one of the protected
+ // helpers above to load the assembly.
+ protected abstract Assembly Load(AssemblyName assemblyName);
+
+ // This method is invoked by the VM when using the host-provided assembly load context
+ // implementation.
+ private static Assembly Resolve(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName)
+ {
+ AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target);
+
+ return context.ResolveUsingLoad(assemblyName);
+ }
+
+ // This method is invoked by the VM to resolve an assembly reference using the Resolving event
+ // after trying assembly resolution via Load override and TPA load context without success.
+ private static Assembly ResolveUsingResolvingEvent(IntPtr gchManagedAssemblyLoadContext, AssemblyName assemblyName)
+ {
+ AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target);
+
+ // Invoke the AssemblyResolve event callbacks if wired up
+ return context.ResolveUsingEvent(assemblyName);
+ }
+
+ private Assembly GetFirstResolvedAssembly(AssemblyName assemblyName)
+ {
+ Assembly resolvedAssembly = null;
+
+ Func<AssemblyLoadContext, AssemblyName, Assembly> assemblyResolveHandler = Resolving;
+
+ if (assemblyResolveHandler != null)
+ {
+ // Loop through the event subscribers and return the first non-null Assembly instance
+ Delegate [] arrSubscribers = assemblyResolveHandler.GetInvocationList();
+ for(int i = 0; i < arrSubscribers.Length; i++)
+ {
+ resolvedAssembly = ((Func<AssemblyLoadContext, AssemblyName, Assembly>)arrSubscribers[i])(this, assemblyName);
+ if (resolvedAssembly != null)
+ {
+ break;
+ }
+ }
+ }
+
+ return resolvedAssembly;
+ }
+
+ private Assembly ValidateAssemblyNameWithSimpleName(Assembly assembly, string requestedSimpleName)
+ {
+ // Get the name of the loaded assembly
+ string loadedSimpleName = null;
+
+ // Derived type's Load implementation is expected to use one of the LoadFrom* methods to get the assembly
+ // which is a RuntimeAssembly instance. However, since Assembly type can be used build any other artifact (e.g. AssemblyBuilder),
+ // we need to check for RuntimeAssembly.
+ RuntimeAssembly rtLoadedAssembly = assembly as RuntimeAssembly;
+ if (rtLoadedAssembly != null)
+ {
+ loadedSimpleName = rtLoadedAssembly.GetSimpleName();
+ }
+
+ // The simple names should match at the very least
+ if (String.IsNullOrEmpty(loadedSimpleName) || (!requestedSimpleName.Equals(loadedSimpleName, StringComparison.InvariantCultureIgnoreCase)))
+ throw new InvalidOperationException(Environment.GetResourceString("Argument_CustomAssemblyLoadContextRequestedNameMismatch"));
+
+ return assembly;
+
+ }
+
+ private Assembly ResolveUsingLoad(AssemblyName assemblyName)
+ {
+ string simpleName = assemblyName.Name;
+ Assembly assembly = Load(assemblyName);
+
+ if (assembly != null)
+ {
+ assembly = ValidateAssemblyNameWithSimpleName(assembly, simpleName);
+ }
+
+ return assembly;
+ }
+
+ private Assembly ResolveUsingEvent(AssemblyName assemblyName)
+ {
+ string simpleName = assemblyName.Name;
+
+ // Invoke the AssemblyResolve event callbacks if wired up
+ Assembly assembly = GetFirstResolvedAssembly(assemblyName);
+ if (assembly != null)
+ {
+ assembly = ValidateAssemblyNameWithSimpleName(assembly, simpleName);
+ }
+
+ // Since attempt to resolve the assembly via Resolving event is the last option,
+ // throw an exception if we do not find any assembly.
+ if (assembly == null)
+ {
+ throw new FileNotFoundException(Environment.GetResourceString("IO.FileLoad"), simpleName);
+ }
+
+ return assembly;
+ }
+
+ public Assembly LoadFromAssemblyName(AssemblyName assemblyName)
+ {
+ // Attempt to load the assembly, using the same ordering as static load, in the current load context.
+ Assembly loadedAssembly = Assembly.Load(assemblyName, m_pNativeAssemblyLoadContext);
+
+ return loadedAssembly;
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr InternalLoadUnmanagedDllFromPath(string unmanagedDllPath);
+
+ // This method provides a way for overriders of LoadUnmanagedDll() to load an unmanaged DLL from a specific path in a
+ // platform-independent way. The DLL is loaded with default load flags.
+ protected IntPtr LoadUnmanagedDllFromPath(string unmanagedDllPath)
+ {
+ if (unmanagedDllPath == null)
+ {
+ throw new ArgumentNullException("unmanagedDllPath");
+ }
+ if (unmanagedDllPath.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"), "unmanagedDllPath");
+ }
+ if (Path.IsRelative(unmanagedDllPath))
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AbsolutePathRequired"), "unmanagedDllPath");
+ }
+
+ return InternalLoadUnmanagedDllFromPath(unmanagedDllPath);
+ }
+
+ // Custom AssemblyLoadContext implementations can override this
+ // method to perform the load of unmanaged native dll
+ // This function needs to return the HMODULE of the dll it loads
+ protected virtual IntPtr LoadUnmanagedDll(String unmanagedDllName)
+ {
+ //defer to default coreclr policy of loading unmanaged dll
+ return IntPtr.Zero;
+ }
+
+ // This method is invoked by the VM when using the host-provided assembly load context
+ // implementation.
+ private static IntPtr ResolveUnmanagedDll(String unmanagedDllName, IntPtr gchManagedAssemblyLoadContext)
+ {
+ AssemblyLoadContext context = (AssemblyLoadContext)(GCHandle.FromIntPtr(gchManagedAssemblyLoadContext).Target);
+ return context.LoadUnmanagedDll(unmanagedDllName);
+ }
+
+ public static AssemblyLoadContext Default
+ {
+ get
+ {
+ if (s_DefaultAssemblyLoadContext == null)
+ {
+ // Try to initialize the default assembly load context with apppath one if we are allowed to
+ if (AssemblyLoadContext.CanUseAppPathAssemblyLoadContextInCurrentDomain())
+ {
+ // Synchronize access to initializing Default ALC
+ lock(s_initLock)
+ {
+ if (s_DefaultAssemblyLoadContext == null)
+ {
+ s_DefaultAssemblyLoadContext = new AppPathAssemblyLoadContext();
+ }
+ }
+ }
+ }
+
+ return s_DefaultAssemblyLoadContext;
+ }
+ }
+
+ // This will be used to set the AssemblyLoadContext for DefaultContext, for the AppDomain,
+ // by a host. Once set, the runtime will invoke the LoadFromAssemblyName method against it to perform
+ // assembly loads for the DefaultContext.
+ //
+ // This method will throw if the Default AssemblyLoadContext is already set or the Binding model is already locked.
+ public static void InitializeDefaultContext(AssemblyLoadContext context)
+ {
+ if (context == null)
+ {
+ throw new ArgumentNullException("context");
+ }
+
+ // Try to override the default assembly load context
+ if (!AssemblyLoadContext.OverrideDefaultAssemblyLoadContextForCurrentDomain(context.m_pNativeAssemblyLoadContext))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("AppDomain_BindingModelIsLocked"));
+ }
+
+ // Update the managed side as well.
+ s_DefaultAssemblyLoadContext = context;
+ }
+
+ // This call opens and closes the file, but does not add the
+ // assembly to the domain.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern AssemblyName nGetFileInformation(String s);
+
+ // Helper to return AssemblyName corresponding to the path of an IL assembly
+ public static AssemblyName GetAssemblyName(string assemblyPath)
+ {
+ if (assemblyPath == null)
+ {
+ throw new ArgumentNullException("assemblyPath");
+ }
+
+ String fullPath = Path.GetFullPathInternal(assemblyPath);
+ return nGetFileInformation(fullPath);
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern IntPtr GetLoadContextForAssembly(RuntimeAssembly assembly);
+
+ // Returns the load context in which the specified assembly has been loaded
+ public static AssemblyLoadContext GetLoadContext(Assembly assembly)
+ {
+ if (assembly == null)
+ {
+ throw new ArgumentNullException("assembly");
+ }
+
+ AssemblyLoadContext loadContextForAssembly = null;
+
+ RuntimeAssembly rtAsm = assembly as RuntimeAssembly;
+
+ // We only support looking up load context for runtime assemblies.
+ if (rtAsm != null)
+ {
+ IntPtr ptrAssemblyLoadContext = GetLoadContextForAssembly(rtAsm);
+ if (ptrAssemblyLoadContext == IntPtr.Zero)
+ {
+ // If the load context is returned null, then the assembly was bound using the TPA binder
+ // and we shall return reference to the active "Default" binder - which could be the TPA binder
+ // or an overridden CLRPrivBinderAssemblyLoadContext instance.
+ loadContextForAssembly = AssemblyLoadContext.Default;
+ }
+ else
+ {
+ loadContextForAssembly = (AssemblyLoadContext)(GCHandle.FromIntPtr(ptrAssemblyLoadContext).Target);
+ }
+ }
+
+ return loadContextForAssembly;
+ }
+
+ // Set the root directory path for profile optimization.
+ public void SetProfileOptimizationRoot(string directoryPath)
+ {
+#if FEATURE_MULTICOREJIT
+ InternalSetProfileRoot(directoryPath);
+#endif // FEATURE_MULTICOREJIT
+ }
+
+ // Start profile optimization for the specified profile name.
+ public void StartProfileOptimization(string profile)
+ {
+#if FEATURE_MULTICOREJIT
+ InternalStartProfile(profile, m_pNativeAssemblyLoadContext);
+#endif // FEATURE_MULTICOREJI
+ }
+
+ private void OnProcessExit(object sender, EventArgs e)
+ {
+ var unloading = Unloading;
+ if (unloading != null)
+ {
+ unloading(this);
+ }
+ }
+
+ public event Func<AssemblyLoadContext, AssemblyName, Assembly> Resolving;
+ public event Action<AssemblyLoadContext> Unloading;
+
+ // Contains the reference to VM's representation of the AssemblyLoadContext
+ private IntPtr m_pNativeAssemblyLoadContext;
+
+ // Each AppDomain contains the reference to its AssemblyLoadContext instance, if one is
+ // specified by the host. By having the field as a static, we are
+ // making it an AppDomain-wide field.
+ private static volatile AssemblyLoadContext s_DefaultAssemblyLoadContext;
+
+ // Synchronization primitive for controlling initialization of Default load context
+ private static readonly object s_initLock = new Object();
+ }
+
+ [System.Security.SecuritySafeCritical]
+ class AppPathAssemblyLoadContext : AssemblyLoadContext
+ {
+ internal AppPathAssemblyLoadContext() : base(true)
+ {
+ }
+
+ [System.Security.SecuritySafeCritical]
+ protected override Assembly Load(AssemblyName assemblyName)
+ {
+ // We were loading an assembly into TPA ALC that was not found on TPA list. As a result we are here.
+ // Returning null will result in the AssemblyResolve event subscribers to be invoked to help resolve the assembly.
+ return null;
+ }
+ }
+}
+
+#endif // FEATURE_HOST_ASSEMBLY_RESOLVER
diff --git a/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs
new file mode 100644
index 0000000000..6e35568310
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs
@@ -0,0 +1,488 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Provides a way for an app to not start an operation unless
+** there's a reasonable chance there's enough memory
+** available for the operation to succeed.
+**
+**
+===========================================================*/
+
+using System;
+using System.IO;
+using Microsoft.Win32;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Security.Permissions;
+using System.Runtime.Versioning;
+using System.Diagnostics.Contracts;
+
+/*
+ This class allows an application to fail before starting certain
+ activities. The idea is to fail early instead of failing in the middle
+ of some long-running operation to increase the survivability of the
+ application and ensure you don't have to write tricky code to handle an
+ OOM anywhere in your app's code (which implies state corruption, meaning you
+ should unload the appdomain, if you have a transacted environment to ensure
+ rollback of individual transactions). This is an incomplete tool to attempt
+ hoisting all your OOM failures from anywhere in your worker methods to one
+ particular point where it is easier to handle an OOM failure, and you can
+ optionally choose to not start a workitem if it will likely fail. This does
+ not help the performance of your code directly (other than helping to avoid
+ AD unloads). The point is to avoid starting work if it is likely to fail.
+ The Enterprise Services team has used these memory gates effectively in the
+ unmanaged world for a decade.
+
+ In Whidbey, we will simply check to see if there is enough memory available
+ in the OS's page file & attempt to ensure there might be enough space free
+ within the process's address space (checking for address space fragmentation
+ as well). We will not commit or reserve any memory. To avoid race conditions with
+ other threads using MemoryFailPoints, we'll also keep track of a
+ process-wide amount of memory "reserved" via all currently-active
+ MemoryFailPoints. This has two problems:
+ 1) This can account for memory twice. If a thread creates a
+ MemoryFailPoint for 100 MB then allocates 99 MB, we'll see 99 MB
+ less free memory and 100 MB less reserved memory. Yet, subtracting
+ off the 100 MB is necessary because the thread may not have started
+ allocating memory yet. Disposing of this class immediately after
+ front-loaded allocations have completed is a great idea.
+ 2) This is still vulnerable to race conditions with other threads that don't use
+ MemoryFailPoints.
+ So this class is far from perfect. But it may be good enough to
+ meaningfully reduce the frequency of OutOfMemoryExceptions in managed apps.
+
+ In Orcas or later, we might allocate some memory from the OS and add it
+ to a allocation context for this thread. Obviously, at that point we need
+ some way of conveying when we release this block of memory. So, we
+ implemented IDisposable on this type in Whidbey and expect all users to call
+ this from within a using block to provide lexical scope for their memory
+ usage. The call to Dispose (implicit with the using block) will give us an
+ opportunity to release this memory, perhaps. We anticipate this will give
+ us the possibility of a more effective design in a future version.
+
+ In Orcas, we may also need to differentiate between allocations that would
+ go into the normal managed heap vs. the large object heap, or we should
+ consider checking for enough free space in both locations (with any
+ appropriate adjustments to ensure the memory is contiguous).
+*/
+
+namespace System.Runtime
+{
+ public sealed class MemoryFailPoint : CriticalFinalizerObject, IDisposable
+ {
+ // Find the top section of user mode memory. Avoid the last 64K.
+ // Windows reserves that block for the kernel, apparently, and doesn't
+ // let us ask about that memory. But since we ask for memory in 1 MB
+ // chunks, we don't have to special case this. Also, we need to
+ // deal with 32 bit machines in 3 GB mode.
+ // Using Win32's GetSystemInfo should handle all this for us.
+ private static readonly ulong TopOfMemory;
+
+ // Walking the address space is somewhat expensive, taking around half
+ // a millisecond. Doing that per transaction limits us to a max of
+ // ~2000 transactions/second. Instead, let's do this address space
+ // walk once every 10 seconds, or when we will likely fail. This
+ // amortization scheme can reduce the cost of a memory gate by about
+ // a factor of 100.
+ private static long hiddenLastKnownFreeAddressSpace = 0;
+ private static long hiddenLastTimeCheckingAddressSpace = 0;
+ private const int CheckThreshold = 10 * 1000; // 10 seconds
+
+ private static long LastKnownFreeAddressSpace
+ {
+ get { return Volatile.Read(ref hiddenLastKnownFreeAddressSpace); }
+ set { Volatile.Write(ref hiddenLastKnownFreeAddressSpace, value); }
+ }
+
+ private static long AddToLastKnownFreeAddressSpace(long addend)
+ {
+ return Interlocked.Add(ref hiddenLastKnownFreeAddressSpace, addend);
+ }
+
+ private static long LastTimeCheckingAddressSpace
+ {
+ get { return Volatile.Read(ref hiddenLastTimeCheckingAddressSpace); }
+ set { Volatile.Write(ref hiddenLastTimeCheckingAddressSpace, value); }
+ }
+
+ // When allocating memory segment by segment, we've hit some cases
+ // where there are only 22 MB of memory available on the machine,
+ // we need 1 16 MB segment, and the OS does not succeed in giving us
+ // that memory. Reasons for this could include:
+ // 1) The GC does allocate memory when doing a collection.
+ // 2) Another process on the machine could grab that memory.
+ // 3) Some other part of the runtime might grab this memory.
+ // If we build in a little padding, we can help protect
+ // ourselves against some of these cases, and we want to err on the
+ // conservative side with this class.
+ private const int LowMemoryFudgeFactor = 16 << 20;
+
+ // Round requested size to a 16MB multiple to have a better granularity
+ // when checking for available memory.
+ private const int MemoryCheckGranularity = 16;
+
+ // Note: This may become dynamically tunable in the future.
+ // Also note that we can have different segment sizes for the normal vs.
+ // large object heap. We currently use the max of the two.
+ private static readonly ulong GCSegmentSize;
+
+ // For multi-threaded workers, we want to ensure that if two workers
+ // use a MemoryFailPoint at the same time, and they both succeed, that
+ // they don't trample over each other's memory. Keep a process-wide
+ // count of "reserved" memory, and decrement this in Dispose and
+ // in the critical finalizer. See
+ // SharedStatics.MemoryFailPointReservedMemory
+
+ private ulong _reservedMemory; // The size of this request (from user)
+ private bool _mustSubtractReservation; // Did we add data to SharedStatics?
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static MemoryFailPoint()
+ {
+ GetMemorySettings(out GCSegmentSize, out TopOfMemory);
+ }
+
+ // We can remove this link demand in a future version - we will
+ // have scenarios for this in partial trust in the future, but
+ // we're doing this just to restrict this in case the code below
+ // is somehow incorrect.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public MemoryFailPoint(int sizeInMegabytes)
+ {
+ if (sizeInMegabytes <= 0)
+ throw new ArgumentOutOfRangeException("sizeInMegabytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ ulong size = ((ulong)sizeInMegabytes) << 20;
+ _reservedMemory = size;
+
+ // Check to see that we both have enough memory on the system
+ // and that we have enough room within the user section of the
+ // process's address space. Also, we need to use the GC segment
+ // size, not the amount of memory the user wants to allocate.
+ // Consider correcting this to reflect free memory within the GC
+ // heap, and to check both the normal & large object heaps.
+ ulong segmentSize = (ulong) (Math.Ceiling((double)size / GCSegmentSize) * GCSegmentSize);
+ if (segmentSize >= TopOfMemory)
+ throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_TooBig"));
+
+ ulong requestedSizeRounded = (ulong)(Math.Ceiling((double)sizeInMegabytes / MemoryCheckGranularity) * MemoryCheckGranularity);
+ //re-convert into bytes
+ requestedSizeRounded <<= 20;
+
+ ulong availPageFile = 0; // available VM (physical + page file)
+ ulong totalAddressSpaceFree = 0; // non-contiguous free address space
+
+ // Check for available memory, with 2 attempts at getting more
+ // memory.
+ // Stage 0: If we don't have enough, trigger a GC.
+ // Stage 1: If we don't have enough, try growing the swap file.
+ // Stage 2: Update memory state, then fail or leave loop.
+ //
+ // (In the future, we could consider adding another stage after
+ // Stage 0 to run finalizers. However, before doing that make sure
+ // that we could abort this constructor when we call
+ // GC.WaitForPendingFinalizers, noting that this method uses a CER
+ // so it can't be aborted, and we have a critical finalizer. It
+ // would probably work, but do some thinking first.)
+ for(int stage = 0; stage < 3; stage++) {
+ CheckForAvailableMemory(out availPageFile, out totalAddressSpaceFree);
+
+ // If we have enough room, then skip some stages.
+ // Note that multiple threads can still lead to a race condition for our free chunk
+ // of address space, which can't be easily solved.
+ ulong reserved = SharedStatics.MemoryFailPointReservedMemory;
+ ulong segPlusReserved = segmentSize + reserved;
+ bool overflow = segPlusReserved < segmentSize || segPlusReserved < reserved;
+ bool needPageFile = availPageFile < (requestedSizeRounded + reserved + LowMemoryFudgeFactor) || overflow;
+ bool needAddressSpace = totalAddressSpaceFree < segPlusReserved || overflow;
+
+ // Ensure our cached amount of free address space is not stale.
+ long now = Environment.TickCount; // Handle wraparound.
+ if ((now > LastTimeCheckingAddressSpace + CheckThreshold || now < LastTimeCheckingAddressSpace) ||
+ LastKnownFreeAddressSpace < (long) segmentSize) {
+ CheckForFreeAddressSpace(segmentSize, false);
+ }
+ bool needContiguousVASpace = (ulong) LastKnownFreeAddressSpace < segmentSize;
+
+ BCLDebug.Trace("MEMORYFAILPOINT", "MemoryFailPoint: Checking for {0} MB, for allocation size of {1} MB, stage {9}. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved via process's MemoryFailPoints: {8} MB",
+ segmentSize >> 20, sizeInMegabytes, needPageFile,
+ needAddressSpace, needContiguousVASpace,
+ availPageFile >> 20, totalAddressSpaceFree >> 20,
+ LastKnownFreeAddressSpace >> 20, reserved, stage);
+
+ if (!needPageFile && !needAddressSpace && !needContiguousVASpace)
+ break;
+
+ switch(stage) {
+ case 0:
+ // The GC will release empty segments to the OS. This will
+ // relieve us from having to guess whether there's
+ // enough memory in either GC heap, and whether
+ // internal fragmentation will prevent those
+ // allocations from succeeding.
+ GC.Collect();
+ continue;
+
+ case 1:
+ // Do this step if and only if the page file is too small.
+ if (!needPageFile)
+ continue;
+
+ // Attempt to grow the OS's page file. Note that we ignore
+ // any allocation routines from the host intentionally.
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ // This shouldn't overflow due to the if clauses above.
+ UIntPtr numBytes = new UIntPtr(segmentSize);
+ unsafe {
+ void * pMemory = Win32Native.VirtualAlloc(null, numBytes, Win32Native.MEM_COMMIT, Win32Native.PAGE_READWRITE);
+ if (pMemory != null) {
+ bool r = Win32Native.VirtualFree(pMemory, UIntPtr.Zero, Win32Native.MEM_RELEASE);
+ if (!r)
+ __Error.WinIOError();
+ }
+ }
+ }
+ continue;
+
+ case 2:
+ // The call to CheckForAvailableMemory above updated our
+ // state.
+ if (needPageFile || needAddressSpace) {
+ InsufficientMemoryException e = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint"));
+#if _DEBUG
+ e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize,
+ needPageFile, needAddressSpace, needContiguousVASpace,
+ availPageFile >> 20, totalAddressSpaceFree >> 20,
+ LastKnownFreeAddressSpace >> 20, reserved);
+#endif
+ throw e;
+ }
+
+ if (needContiguousVASpace) {
+ InsufficientMemoryException e = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag"));
+#if _DEBUG
+ e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize,
+ needPageFile, needAddressSpace, needContiguousVASpace,
+ availPageFile >> 20, totalAddressSpaceFree >> 20,
+ LastKnownFreeAddressSpace >> 20, reserved);
+#endif
+ throw e;
+ }
+
+ break;
+
+ default:
+ Contract.Assert(false, "Fell through switch statement!");
+ break;
+ }
+ }
+
+ // Success - we have enough room the last time we checked.
+ // Now update our shared state in a somewhat atomic fashion
+ // and handle a simple race condition with other MemoryFailPoint instances.
+ AddToLastKnownFreeAddressSpace(-((long) size));
+ if (LastKnownFreeAddressSpace < 0)
+ CheckForFreeAddressSpace(segmentSize, true);
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ SharedStatics.AddMemoryFailPointReservation((long) size);
+ _mustSubtractReservation = true;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void CheckForAvailableMemory(out ulong availPageFile, out ulong totalAddressSpaceFree)
+ {
+ bool r;
+ Win32Native.MEMORYSTATUSEX memory = new Win32Native.MEMORYSTATUSEX();
+ r = Win32Native.GlobalMemoryStatusEx(ref memory);
+ if (!r)
+ __Error.WinIOError();
+ availPageFile = memory.availPageFile;
+ totalAddressSpaceFree = memory.availVirtual;
+ //Console.WriteLine("Memory gate: Mem load: {0}% Available memory (physical + page file): {1} MB Total free address space: {2} MB GC Heap: {3} MB", memory.memoryLoad, memory.availPageFile >> 20, memory.availVirtual >> 20, GC.GetTotalMemory(true) >> 20);
+ }
+
+ // Based on the shouldThrow parameter, this will throw an exception, or
+ // returns whether there is enough space. In all cases, we update
+ // our last known free address space, hopefully avoiding needing to
+ // probe again.
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe bool CheckForFreeAddressSpace(ulong size, bool shouldThrow)
+ {
+ // Start walking the address space at 0. VirtualAlloc may wrap
+ // around the address space. We don't need to find the exact
+ // pages that VirtualAlloc would return - we just need to
+ // know whether VirtualAlloc could succeed.
+ ulong freeSpaceAfterGCHeap = MemFreeAfterAddress(null, size);
+
+ BCLDebug.Trace("MEMORYFAILPOINT", "MemoryFailPoint: Checked for free VA space. Found enough? {0} Asked for: {1} Found: {2}", (freeSpaceAfterGCHeap >= size), size, freeSpaceAfterGCHeap);
+
+ // We may set these without taking a lock - I don't believe
+ // this will hurt, as long as we never increment this number in
+ // the Dispose method. If we do an extra bit of checking every
+ // once in a while, but we avoid taking a lock, we may win.
+ LastKnownFreeAddressSpace = (long) freeSpaceAfterGCHeap;
+ LastTimeCheckingAddressSpace = Environment.TickCount;
+
+ if (freeSpaceAfterGCHeap < size && shouldThrow)
+ throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag"));
+ return freeSpaceAfterGCHeap >= size;
+ }
+
+ // Returns the amount of consecutive free memory available in a block
+ // of pages. If we didn't have enough address space, we still return
+ // a positive value < size, to help potentially avoid the overhead of
+ // this check if we use a MemoryFailPoint with a smaller size next.
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe ulong MemFreeAfterAddress(void * address, ulong size)
+ {
+ if (size >= TopOfMemory)
+ return 0;
+
+ ulong largestFreeRegion = 0;
+ Win32Native.MEMORY_BASIC_INFORMATION memInfo = new Win32Native.MEMORY_BASIC_INFORMATION();
+ UIntPtr sizeOfMemInfo = (UIntPtr) Marshal.SizeOf(memInfo);
+
+ while (((ulong)address) + size < TopOfMemory) {
+ UIntPtr r = Win32Native.VirtualQuery(address, ref memInfo, sizeOfMemInfo);
+ if (r == UIntPtr.Zero)
+ __Error.WinIOError();
+
+ ulong regionSize = memInfo.RegionSize.ToUInt64();
+ if (memInfo.State == Win32Native.MEM_FREE) {
+ if (regionSize >= size)
+ return regionSize;
+ else
+ largestFreeRegion = Math.Max(largestFreeRegion, regionSize);
+ }
+ address = (void *) ((ulong) address + regionSize);
+ }
+ return largestFreeRegion;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern void GetMemorySettings(out ulong maxGCSegmentSize, out ulong topOfMemory);
+
+ [System.Security.SecuritySafeCritical] // destructors should be safe to call
+ ~MemoryFailPoint()
+ {
+ Dispose(false);
+ }
+
+ // Applications must call Dispose, which conceptually "releases" the
+ // memory that was "reserved" by the MemoryFailPoint. This affects a
+ // global count of reserved memory in this version (helping to throttle
+ // future MemoryFailPoints) in this version. We may in the
+ // future create an allocation context and release it in the Dispose
+ // method. While the finalizer will eventually free this block of
+ // memory, apps will help their performance greatly by calling Dispose.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private void Dispose(bool disposing)
+ {
+ // This is just bookkeeping to ensure multiple threads can really
+ // get enough memory, and this does not actually reserve memory
+ // within the GC heap.
+ if (_mustSubtractReservation) {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ SharedStatics.AddMemoryFailPointReservation(-((long)_reservedMemory));
+ _mustSubtractReservation = false;
+ }
+ }
+
+ /*
+ // Prototype performance
+ // Let's pretend that we returned at least some free memory to
+ // the GC heap. We don't know this is true - the objects could
+ // have a longer lifetime, and the memory could be elsewhere in the
+ // GC heap. Additionally, we subtracted off the segment size, not
+ // this size. That's ok - we don't mind if this slowly degrades
+ // and requires us to refresh the value a little bit sooner.
+ // But releasing the memory here should help us avoid probing for
+ // free address space excessively with large workItem sizes.
+ Interlocked.Add(ref LastKnownFreeAddressSpace, _reservedMemory);
+ */
+ }
+
+#if _DEBUG
+ [Serializable]
+ internal sealed class MemoryFailPointState
+ {
+ private ulong _segmentSize;
+ private int _allocationSizeInMB;
+ private bool _needPageFile;
+ private bool _needAddressSpace;
+ private bool _needContiguousVASpace;
+ private ulong _availPageFile;
+ private ulong _totalFreeAddressSpace;
+ private long _lastKnownFreeAddressSpace;
+ private ulong _reservedMem;
+ private String _stackTrace; // Where did we fail, for additional debugging.
+
+ internal MemoryFailPointState(int allocationSizeInMB, ulong segmentSize, bool needPageFile, bool needAddressSpace, bool needContiguousVASpace, ulong availPageFile, ulong totalFreeAddressSpace, long lastKnownFreeAddressSpace, ulong reservedMem)
+ {
+ _allocationSizeInMB = allocationSizeInMB;
+ _segmentSize = segmentSize;
+ _needPageFile = needPageFile;
+ _needAddressSpace = needAddressSpace;
+ _needContiguousVASpace = needContiguousVASpace;
+ _availPageFile = availPageFile;
+ _totalFreeAddressSpace = totalFreeAddressSpace;
+ _lastKnownFreeAddressSpace = lastKnownFreeAddressSpace;
+ _reservedMem = reservedMem;
+ try
+ {
+ _stackTrace = Environment.StackTrace;
+ }
+ catch (System.Security.SecurityException)
+ {
+ _stackTrace = "no permission";
+ }
+ catch (OutOfMemoryException)
+ {
+ _stackTrace = "out of memory";
+ }
+ }
+
+ public override String ToString()
+ {
+ return String.Format(System.Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB",
+ _segmentSize >> 20, _allocationSizeInMB, _needPageFile,
+ _needAddressSpace, _needContiguousVASpace,
+ _availPageFile >> 20, _totalFreeAddressSpace >> 20,
+ _lastKnownFreeAddressSpace >> 20, _reservedMem);
+ }
+
+ public String StackTrace {
+ get { return _stackTrace; }
+ }
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/ProfileOptimization.cs b/src/mscorlib/src/System/Runtime/ProfileOptimization.cs
new file mode 100644
index 0000000000..c877d2106d
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/ProfileOptimization.cs
@@ -0,0 +1,54 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+//
+// This class defines entry point for multi-core JIT API
+//
+//
+namespace System.Runtime {
+
+ using System;
+
+ using System.Reflection;
+
+ using System.Security;
+ using System.Security.Permissions;
+
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Runtime.CompilerServices;
+
+#if FEATURE_MULTICOREJIT
+
+ public static class ProfileOptimization
+ {
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void InternalSetProfileRoot(string directoryPath);
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void InternalStartProfile(string profile, IntPtr ptrNativeAssemblyLoadContext);
+
+ [SecurityCritical]
+ public static void SetProfileRoot(string directoryPath)
+ {
+ InternalSetProfileRoot(directoryPath);
+ }
+
+ [SecurityCritical]
+ public static void StartProfile(string profile)
+ {
+ InternalStartProfile(profile, IntPtr.Zero);
+ }
+ }
+
+#endif
+}
+
diff --git a/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs b/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs
new file mode 100644
index 0000000000..2524aaaecb
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Reliability/CriticalFinalizerObject.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Deriving from this class will cause any finalizer you define to be critical
+** (i.e. the finalizer is guaranteed to run, won't be aborted by the host and is
+** run after the finalizers of other objects collected at the same time).
+**
+** You must possess UnmanagedCode permission in order to derive from this class.
+**
+**
+===========================================================*/
+
+using System;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+
+namespace System.Runtime.ConstrainedExecution
+{
+#if !FEATURE_CORECLR
+ [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode=true)]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class CriticalFinalizerObject
+ {
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #endif
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected CriticalFinalizerObject()
+ {
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ ~CriticalFinalizerObject()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Reliability/PrePrepareMethodAttribute.cs b/src/mscorlib/src/System/Runtime/Reliability/PrePrepareMethodAttribute.cs
new file mode 100644
index 0000000000..d9774d636b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Reliability/PrePrepareMethodAttribute.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+** Purpose: Serves as a hint to ngen that the decorated method
+** (and its statically determinable call graph) should be
+** prepared (as for Constrained Execution Region use). This
+** is primarily useful in the scenario where the method in
+** question will be prepared explicitly at runtime and the
+** author of the method knows this and wishes to avoid the
+** overhead of runtime preparation.
+**
+**
+===========================================================*/
+namespace System.Runtime.ConstrainedExecution
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
+
+ public sealed class PrePrepareMethodAttribute : Attribute
+ {
+ public PrePrepareMethodAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs b/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs
new file mode 100644
index 0000000000..4a14e5733c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Reliability/ReliabilityContractAttribute.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: Defines a publically documentable contract for
+** reliability between a method and its callers, expressing
+** what state will remain consistent in the presence of
+** failures (ie async exceptions like thread abort) and whether
+** the method needs to be called from within a CER.
+**
+**
+===========================================================*/
+
+namespace System.Runtime.ConstrainedExecution {
+ using System.Runtime.InteropServices;
+ using System;
+
+ // **************************************************************************************************************************
+ //
+ // Note that if you change either of the enums below or the constructors, fields or properties of the custom attribute itself
+ // you must also change the logic and definitions in vm\ConstrainedExecutionRegion.cpp to match.
+ //
+ // **************************************************************************************************************************
+
+ [Serializable]
+ public enum Consistency : int
+ {
+ MayCorruptProcess = 0,
+ MayCorruptAppDomain = 1,
+ MayCorruptInstance = 2,
+ WillNotCorruptState = 3,
+ }
+
+ [Serializable]
+ public enum Cer : int
+ {
+ None = 0,
+ MayFail = 1, // Might fail, but the method will say it failed
+ Success = 2,
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Interface /* | AttributeTargets.Delegate*/, Inherited = false)]
+ public sealed class ReliabilityContractAttribute : Attribute
+ {
+ private Consistency _consistency;
+ private Cer _cer;
+
+ public ReliabilityContractAttribute(Consistency consistencyGuarantee, Cer cer)
+ {
+ _consistency = consistencyGuarantee;
+ _cer = cer;
+ }
+
+ public Consistency ConsistencyGuarantee {
+ get { return _consistency; }
+ }
+
+ public Cer Cer {
+ get { return _cer; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs b/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs
new file mode 100644
index 0000000000..d10df9d57b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Remoting/ObjectHandle.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** ObjectHandle wraps object references. A Handle allows a
+** marshal by value object to be returned through an
+** indirection allowing the caller to control when the
+** object is loaded into their domain.
+**
+**
+===========================================================*/
+
+namespace System.Runtime.Remoting{
+
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Activation;
+ using System.Runtime.Remoting.Lifetime;
+#endif
+
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class ObjectHandle:
+#if FEATURE_REMOTING
+ MarshalByRefObject,
+#endif
+ IObjectHandle
+ {
+ private Object WrappedObject;
+
+ private ObjectHandle()
+ {
+ }
+
+ public ObjectHandle(Object o)
+ {
+ WrappedObject = o;
+ }
+
+ public Object Unwrap()
+ {
+ return WrappedObject;
+ }
+
+ // ObjectHandle has a finite lifetime. For now the default
+ // lifetime is being used, this can be changed in this method to
+ // specify a custom lifetime.
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override Object InitializeLifetimeService()
+ {
+ BCLDebug.Trace("REMOTE", "ObjectHandle.InitializeLifetimeService");
+
+ //
+ // If the wrapped object has implemented InitializeLifetimeService to return null,
+ // we don't want to go to the base class (which will result in a lease being
+ // requested from the MarshalByRefObject, which starts up the LeaseManager,
+ // which starts up the ThreadPool, adding three threads to the process.
+ // We check if the wrapped object is a MarshalByRef object, and call InitializeLifetimeServices on it
+ // and if it returns null, we return null. Otherwise we fall back to the old behavior.
+ //
+
+ MarshalByRefObject mbr = WrappedObject as MarshalByRefObject;
+ if (mbr != null) {
+ Object o = mbr.InitializeLifetimeService();
+ if (o == null)
+ return null;
+ }
+ ILease lease = (ILease)base.InitializeLifetimeService();
+ return lease;
+ }
+#endif // FEATURE_REMOTING
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs b/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs
new file mode 100644
index 0000000000..7df221c9cd
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/FormatterConverter.cs
@@ -0,0 +1,167 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A base implementation of the IFormatterConverter
+** interface that uses the Convert class and the
+** IConvertible interface.
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization {
+ using System;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class FormatterConverter : IFormatterConverter {
+
+ public FormatterConverter() {
+ }
+
+ public Object Convert(Object value, Type type) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
+ }
+
+ public Object Convert(Object value, TypeCode typeCode) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ChangeType(value, typeCode, CultureInfo.InvariantCulture);
+ }
+
+ public bool ToBoolean(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToBoolean(value, CultureInfo.InvariantCulture);
+ }
+
+ public char ToChar(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToChar(value, CultureInfo.InvariantCulture);
+ }
+
+ [CLSCompliant(false)]
+ public sbyte ToSByte(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToSByte(value, CultureInfo.InvariantCulture);
+ }
+
+ public byte ToByte(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToByte(value, CultureInfo.InvariantCulture);
+ }
+
+ public short ToInt16(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToInt16(value, CultureInfo.InvariantCulture);
+ }
+
+ [CLSCompliant(false)]
+ public ushort ToUInt16(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToUInt16(value, CultureInfo.InvariantCulture);
+ }
+
+ public int ToInt32(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToInt32(value, CultureInfo.InvariantCulture);
+ }
+
+ [CLSCompliant(false)]
+ public uint ToUInt32(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToUInt32(value, CultureInfo.InvariantCulture);
+ }
+
+ public long ToInt64(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToInt64(value, CultureInfo.InvariantCulture);
+ }
+
+ [CLSCompliant(false)]
+ public ulong ToUInt64(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToUInt64(value, CultureInfo.InvariantCulture);
+ }
+
+ public float ToSingle(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToSingle(value, CultureInfo.InvariantCulture);
+ }
+
+ public double ToDouble(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToDouble(value, CultureInfo.InvariantCulture);
+ }
+
+ public Decimal ToDecimal(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToDecimal(value, CultureInfo.InvariantCulture);
+ }
+
+ public DateTime ToDateTime(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToDateTime(value, CultureInfo.InvariantCulture);
+ }
+
+ public String ToString(Object value) {
+ if (value==null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return System.Convert.ToString(value, CultureInfo.InvariantCulture);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs b/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs
new file mode 100644
index 0000000000..c6f27b5b2a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/FormatterServices.cs
@@ -0,0 +1,590 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Provides some static methods to aid with the implementation
+** of a Formatter for Serialization.
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization {
+
+ using System;
+ using System.Reflection;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security;
+ using System.Security.Permissions;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization.Formatters;
+#endif
+ using System.Runtime.Remoting;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Threading;
+ using System.IO;
+ using System.Text;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static class FormatterServices {
+#if FEATURE_SERIALIZATION
+ internal static Dictionary<MemberHolder, MemberInfo[]> m_MemberInfoTable = new Dictionary<MemberHolder, MemberInfo[]>(32);
+ [System.Security.SecurityCritical]
+ private static bool unsafeTypeForwardersIsEnabled = false;
+
+ [System.Security.SecurityCritical]
+ private static volatile bool unsafeTypeForwardersIsEnabledInitialized = false;
+
+ private static Object s_FormatterServicesSyncObject = null;
+
+ private static Object formatterServicesSyncObject
+ {
+ get
+ {
+ if (s_FormatterServicesSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_FormatterServicesSyncObject, o, null);
+ }
+ return s_FormatterServicesSyncObject;
+ }
+ }
+
+ [SecuritySafeCritical]
+ static FormatterServices()
+ {
+ // Static initialization touches security critical types, so we need an
+ // explicit static constructor to allow us to mark it safe critical.
+ }
+
+ private static MemberInfo[] GetSerializableMembers(RuntimeType type) {
+ // get the list of all fields
+ FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ int countProper = 0;
+ for (int i = 0; i < fields.Length; i++) {
+ if ((fields[i].Attributes & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized)
+ continue;
+ countProper++;
+ }
+ if (countProper != fields.Length) {
+ FieldInfo[] properFields = new FieldInfo[countProper];
+ countProper = 0;
+ for (int i = 0; i < fields.Length; i++) {
+ if ((fields[i].Attributes & FieldAttributes.NotSerialized) == FieldAttributes.NotSerialized)
+ continue;
+ properFields[countProper] = fields[i];
+ countProper++;
+ }
+ return properFields;
+ }
+ else
+ return fields;
+ }
+
+ private static bool CheckSerializable(RuntimeType type) {
+ if (type.IsSerializable) {
+ return true;
+ }
+ return false;
+ }
+
+ private static MemberInfo[] InternalGetSerializableMembers(RuntimeType type) {
+ List<SerializationFieldInfo> allMembers = null;
+ MemberInfo[] typeMembers;
+ FieldInfo [] typeFields;
+ RuntimeType parentType;
+
+ Contract.Assert((object)type != null, "[GetAllSerializableMembers]type!=null");
+
+ if (type.IsInterface) {
+ return new MemberInfo[0];
+ }
+
+ if (!(CheckSerializable(type))) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_NonSerType", type.FullName, type.Module.Assembly.FullName));
+ }
+
+ //Get all of the serializable members in the class to be serialized.
+ typeMembers = GetSerializableMembers(type);
+
+ //If this class doesn't extend directly from object, walk its hierarchy and
+ //get all of the private and assembly-access fields (e.g. all fields that aren't
+ //virtual) and include them in the list of things to be serialized.
+ parentType = (RuntimeType)(type.BaseType);
+ if (parentType != null && parentType != (RuntimeType)typeof(Object)) {
+ RuntimeType[] parentTypes = null;
+ int parentTypeCount = 0;
+ bool classNamesUnique = GetParentTypes(parentType, out parentTypes, out parentTypeCount);
+ if (parentTypeCount > 0){
+ allMembers = new List<SerializationFieldInfo>();
+ for (int i = 0; i < parentTypeCount;i++){
+ parentType = parentTypes[i];
+ if (!CheckSerializable(parentType)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_NonSerType", parentType.FullName, parentType.Module.Assembly.FullName));
+ }
+
+ typeFields = parentType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
+ String typeName = classNamesUnique ? parentType.Name : parentType.FullName;
+ foreach (FieldInfo field in typeFields) {
+ // Family and Assembly fields will be gathered by the type itself.
+ if (!field.IsNotSerialized) {
+ allMembers.Add(new SerializationFieldInfo((RuntimeFieldInfo)field, typeName));
+ }
+ }
+ }
+ //If we actually found any new MemberInfo's, we need to create a new MemberInfo array and
+ //copy all of the members which we've found so far into that.
+ if (allMembers!=null && allMembers.Count>0) {
+ MemberInfo[] membersTemp = new MemberInfo[allMembers.Count + typeMembers.Length];
+ Array.Copy(typeMembers, membersTemp, typeMembers.Length);
+ ((ICollection)allMembers).CopyTo(membersTemp, typeMembers.Length);
+ typeMembers = membersTemp;
+ }
+ }
+ }
+ return typeMembers;
+ }
+
+ private static bool GetParentTypes(RuntimeType parentType, out RuntimeType[] parentTypes, out int parentTypeCount){
+ //Check if there are any dup class names. Then we need to include as part of
+ //typeName to prefix the Field names in SerializationFieldInfo
+ /*out*/ parentTypes = null;
+ /*out*/ parentTypeCount = 0;
+ bool unique = true;
+ RuntimeType objectType = (RuntimeType)typeof(object);
+ for (RuntimeType t1 = parentType; t1 != objectType; t1 = (RuntimeType)t1.BaseType)
+ {
+ if (t1.IsInterface) continue;
+ string t1Name = t1.Name;
+ for(int i=0;unique && i<parentTypeCount;i++){
+ string t2Name = parentTypes[i].Name;
+ if (t2Name.Length == t1Name.Length && t2Name[0] == t1Name[0] && t1Name == t2Name){
+ unique = false;
+ break;
+ }
+ }
+ //expand array if needed
+ if (parentTypes == null || parentTypeCount == parentTypes.Length){
+ RuntimeType[] tempParentTypes = new RuntimeType[Math.Max(parentTypeCount*2, 12)];
+ if (parentTypes != null)
+ Array.Copy(parentTypes, 0, tempParentTypes, 0, parentTypeCount);
+ parentTypes = tempParentTypes;
+ }
+ parentTypes[parentTypeCount++] = t1;
+ }
+ return unique;
+ }
+
+ // Get all of the Serializable members for a particular class. For all practical intents and
+ // purposes, this is the non-transient, non-static members (fields and properties). In order to
+ // be included, properties must have both a getter and a setter. N.B.: A class
+ // which implements ISerializable or has a serialization surrogate may not use all of these members
+ // (or may have additional members).
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static MemberInfo[] GetSerializableMembers(Type type) {
+ return GetSerializableMembers(type, new StreamingContext(StreamingContextStates.All));
+ }
+
+ // Get all of the Serializable Members for a particular class. If we're not cloning, this is all
+ // non-transient, non-static fields. If we are cloning, include the transient fields as well since
+ // we know that we're going to live inside of the same context.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static MemberInfo[] GetSerializableMembers(Type type, StreamingContext context) {
+ MemberInfo[] members;
+
+ if ((object)type==null) {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ if (!(type is RuntimeType)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidType", type.ToString()));
+ }
+
+ MemberHolder mh = new MemberHolder(type, context);
+
+ //If we've already gathered the members for this type, just return them.
+ if (m_MemberInfoTable.ContainsKey(mh)) {
+ return m_MemberInfoTable[mh];
+ }
+
+ lock (formatterServicesSyncObject) {
+ //If we've already gathered the members for this type, just return them.
+ if (m_MemberInfoTable.ContainsKey(mh)) {
+ return m_MemberInfoTable[mh];
+ }
+
+ members = InternalGetSerializableMembers((RuntimeType)type);
+
+ m_MemberInfoTable[mh] = members;
+ }
+
+ return members;
+ }
+
+ static readonly Type[] advancedTypes = new Type[]{
+ typeof(System.DelegateSerializationHolder),
+#if FEATURE_REMOTING
+ typeof(System.Runtime.Remoting.ObjRef),
+ typeof(System.Runtime.Remoting.IEnvoyInfo),
+ typeof(System.Runtime.Remoting.Lifetime.ISponsor),
+#endif
+ };
+
+ public static void CheckTypeSecurity(Type t, TypeFilterLevel securityLevel) {
+ if (securityLevel == TypeFilterLevel.Low){
+ for(int i=0;i<advancedTypes.Length;i++){
+ if (advancedTypes[i].IsAssignableFrom(t))
+ throw new SecurityException(Environment.GetResourceString("Serialization_TypeSecurity", advancedTypes[i].FullName, t.FullName));
+ }
+ }
+ }
+#endif // FEATURE_SERIALIZATION
+
+ // Gets a new instance of the object. The entire object is initalized to 0 and no
+ // constructors have been run. **THIS MEANS THAT THE OBJECT MAY NOT BE IN A STATE
+ // CONSISTENT WITH ITS INTERNAL REQUIREMENTS** This method should only be used for
+ // deserialization when the user intends to immediately populate all fields. This method
+ // will not create an unitialized string because it is non-sensical to create an empty
+ // instance of an immutable type.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object GetUninitializedObject(Type type) {
+ if ((object)type == null) {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ if (!(type is RuntimeType)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidType", type.ToString()));
+ }
+
+ return nativeGetUninitializedObject((RuntimeType)type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object GetSafeUninitializedObject(Type type) {
+ if ((object)type == null) {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ if (!(type is RuntimeType)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidType", type.ToString()));
+ }
+#if FEATURE_REMOTING
+ if (Object.ReferenceEquals(type, typeof(System.Runtime.Remoting.Messaging.ConstructionCall)) ||
+ Object.ReferenceEquals(type, typeof(System.Runtime.Remoting.Messaging.LogicalCallContext)) ||
+ Object.ReferenceEquals(type, typeof(System.Runtime.Remoting.Contexts.SynchronizationAttribute)))
+ return nativeGetUninitializedObject((RuntimeType)type);
+#endif
+
+ try {
+ return nativeGetSafeUninitializedObject((RuntimeType)type);
+ }
+ catch(SecurityException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_Security", type.FullName), e);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object nativeGetSafeUninitializedObject(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern Object nativeGetUninitializedObject(RuntimeType type);
+#if FEATURE_SERIALIZATION
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool GetEnableUnsafeTypeForwarders();
+
+ [SecuritySafeCritical]
+ internal static bool UnsafeTypeForwardersIsEnabled()
+ {
+ if (!unsafeTypeForwardersIsEnabledInitialized)
+ {
+ unsafeTypeForwardersIsEnabled = GetEnableUnsafeTypeForwarders();
+ unsafeTypeForwardersIsEnabledInitialized = true;
+ }
+
+ return unsafeTypeForwardersIsEnabled;
+ }
+#endif
+ private static Binder s_binder = Type.DefaultBinder;
+ [System.Security.SecurityCritical]
+ internal static void SerializationSetValue(MemberInfo fi, Object target, Object value)
+ {
+ Contract.Requires(fi != null);
+
+ RtFieldInfo rtField = fi as RtFieldInfo;
+
+ if (rtField != null)
+ {
+ rtField.CheckConsistency(target);
+ rtField.UnsafeSetValue(target, value, BindingFlags.Default, s_binder, null);
+ return;
+ }
+
+ SerializationFieldInfo serField = fi as SerializationFieldInfo;
+ if (serField != null)
+ {
+ serField.InternalSetValue(target, value, BindingFlags.Default, s_binder, null);
+ return;
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFieldInfo"));
+ }
+
+ // Fill in the members of obj with the data contained in data.
+ // Returns the number of members populated.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object PopulateObjectMembers(Object obj, MemberInfo[] members, Object[] data) {
+ if (obj==null) {
+ throw new ArgumentNullException("obj");
+ }
+
+ if (members==null) {
+ throw new ArgumentNullException("members");
+ }
+
+ if (data==null) {
+ throw new ArgumentNullException("data");
+ }
+
+ if (members.Length!=data.Length) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DataLengthDifferent"));
+ }
+ Contract.EndContractBlock();
+
+ MemberInfo mi;
+
+ BCLDebug.Trace("SER", "[PopulateObjectMembers]Enter.");
+
+ for (int i=0; i<members.Length; i++) {
+ mi = members[i];
+
+ if (mi==null) {
+ throw new ArgumentNullException("members", Environment.GetResourceString("ArgumentNull_NullMember", i));
+ }
+
+ //If we find an empty, it means that the value was never set during deserialization.
+ //This is either a forward reference or a null. In either case, this may break some of the
+ //invariants mantained by the setter, so we'll do nothing with it for right now.
+ if (data[i]!=null) {
+ if (mi.MemberType==MemberTypes.Field) {
+ SerializationSetValue(mi, obj, data[i]);
+ } else {
+ throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMemberInfo"));
+ }
+
+ BCLDebug.Trace("SER", "[PopulateObjectMembers]\tType:", obj.GetType(), "\tMember:",
+ members[i].Name, " with member type: ", ((FieldInfo)members[i]).FieldType);
+ }
+ //Console.WriteLine("X");
+ }
+
+ BCLDebug.Trace("SER", "[PopulateObjectMembers]Leave.");
+
+ return obj;
+ }
+
+ // Extracts the data from obj. members is the array of members which we wish to
+ // extract (must be FieldInfos or PropertyInfos). For each supplied member, extract the matching value and
+ // return it in a Object[] of the same size.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Object[] GetObjectData(Object obj, MemberInfo[] members) {
+
+ if (obj==null) {
+ throw new ArgumentNullException("obj");
+ }
+
+ if (members==null) {
+ throw new ArgumentNullException("members");
+ }
+ Contract.EndContractBlock();
+
+ int numberOfMembers = members.Length;
+
+ Object[] data = new Object[numberOfMembers];
+ MemberInfo mi;
+
+ for (int i=0; i<numberOfMembers; i++) {
+ mi=members[i];
+
+ if (mi==null) {
+ throw new ArgumentNullException("members", Environment.GetResourceString("ArgumentNull_NullMember", i));
+ }
+
+ if (mi.MemberType==MemberTypes.Field) {
+ Contract.Assert(mi is RuntimeFieldInfo || mi is SerializationFieldInfo,
+ "[FormatterServices.GetObjectData]mi is RuntimeFieldInfo || mi is SerializationFieldInfo.");
+
+ RtFieldInfo rfi = mi as RtFieldInfo;
+ if (rfi != null) {
+ rfi.CheckConsistency(obj);
+ data[i] = rfi.UnsafeGetValue(obj);
+ } else {
+ data[i] = ((SerializationFieldInfo)mi).InternalGetValue(obj);
+ }
+ } else {
+ throw new SerializationException(Environment.GetResourceString("Serialization_UnknownMemberInfo"));
+ }
+ }
+
+ return data;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static ISerializationSurrogate GetSurrogateForCyclicalReference(ISerializationSurrogate innerSurrogate)
+ {
+ if (innerSurrogate == null)
+ throw new ArgumentNullException("innerSurrogate");
+ Contract.EndContractBlock();
+ return new SurrogateForCyclicalReference(innerSurrogate);
+ }
+
+ /*=============================GetTypeFromAssembly==============================
+ **Action:
+ **Returns:
+ **Arguments:
+ **Exceptions:
+ ==============================================================================*/
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeFromAssembly(Assembly assem, String name) {
+ if (assem==null)
+ throw new ArgumentNullException("assem");
+ Contract.EndContractBlock();
+ return assem.GetType(name, false, false);
+ }
+
+ /*============================LoadAssemblyFromString============================
+ **Action: Loads an assembly from a given string. The current assembly loading story
+ ** is quite confusing. If the assembly is in the fusion cache, we can load it
+ ** using the stringized-name which we transmitted over the wire. If that fails,
+ ** we try for a lookup of the assembly using the simple name which is the first
+ ** part of the assembly name. If we can't find it that way, we'll return null
+ ** as our failure result.
+ **Returns: The loaded assembly or null if it can't be found.
+ **Arguments: assemblyName -- The stringized assembly name.
+ **Exceptions: None
+ ==============================================================================*/
+ internal static Assembly LoadAssemblyFromString(String assemblyName) {
+ //
+ // Try using the stringized assembly name to load from the fusion cache.
+ //
+ BCLDebug.Trace("SER", "[LoadAssemblyFromString]Looking for assembly: ", assemblyName);
+ Assembly found = Assembly.Load(assemblyName);
+ return found;
+ }
+
+ internal static Assembly LoadAssemblyFromStringNoThrow(String assemblyName) {
+ try {
+ return LoadAssemblyFromString(assemblyName);
+ }
+ catch (Exception e){
+ BCLDebug.Trace("SER", "[LoadAssemblyFromString]", e.ToString());
+ }
+ return null;
+ }
+
+ internal static string GetClrAssemblyName(Type type, out bool hasTypeForwardedFrom) {
+ if ((object)type == null) {
+ throw new ArgumentNullException("type");
+ }
+
+ object[] typeAttributes = type.GetCustomAttributes(typeof(TypeForwardedFromAttribute), false);
+ if (typeAttributes != null && typeAttributes.Length > 0) {
+ hasTypeForwardedFrom = true;
+ TypeForwardedFromAttribute typeForwardedFromAttribute = (TypeForwardedFromAttribute)typeAttributes[0];
+ return typeForwardedFromAttribute.AssemblyFullName;
+ }
+ else {
+ hasTypeForwardedFrom = false;
+ return type.Assembly.FullName;
+ }
+ }
+
+ internal static string GetClrTypeFullName(Type type) {
+ if (type.IsArray) {
+ return GetClrTypeFullNameForArray(type);
+ }
+ else {
+ return GetClrTypeFullNameForNonArrayTypes(type);
+ }
+ }
+
+ static string GetClrTypeFullNameForArray(Type type) {
+ int rank = type.GetArrayRank();
+ if (rank == 1)
+ {
+ return String.Format(CultureInfo.InvariantCulture, "{0}{1}", GetClrTypeFullName(type.GetElementType()), "[]");
+ }
+ else
+ {
+ StringBuilder builder = new StringBuilder(GetClrTypeFullName(type.GetElementType())).Append("[");
+ for (int commaIndex = 1; commaIndex < rank; commaIndex++)
+ {
+ builder.Append(",");
+ }
+ builder.Append("]");
+ return builder.ToString();
+ }
+ }
+
+ static string GetClrTypeFullNameForNonArrayTypes(Type type) {
+ if (!type.IsGenericType) {
+ return type.FullName;
+ }
+
+ Type[] genericArguments = type.GetGenericArguments();
+ StringBuilder builder = new StringBuilder(type.GetGenericTypeDefinition().FullName).Append("[");
+ bool hasTypeForwardedFrom;
+
+ foreach (Type genericArgument in genericArguments) {
+ builder.Append("[").Append(GetClrTypeFullName(genericArgument)).Append(", ");
+ builder.Append(GetClrAssemblyName(genericArgument, out hasTypeForwardedFrom)).Append("],");
+ }
+
+ //remove the last comma and close typename for generic with a close bracket
+ return builder.Remove(builder.Length - 1, 1).Append("]").ToString();
+ }
+ }
+
+ internal sealed class SurrogateForCyclicalReference : ISerializationSurrogate
+ {
+ ISerializationSurrogate innerSurrogate;
+ internal SurrogateForCyclicalReference(ISerializationSurrogate innerSurrogate)
+ {
+ if (innerSurrogate == null)
+ throw new ArgumentNullException("innerSurrogate");
+ this.innerSurrogate = innerSurrogate;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void GetObjectData(Object obj, SerializationInfo info, StreamingContext context)
+ {
+ innerSurrogate.GetObjectData(obj, info, context);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
+ {
+ return innerSurrogate.SetObjectData(obj, info, context, selector);
+ }
+ }
+}
+
+
+
+
+
diff --git a/src/mscorlib/src/System/Runtime/Serialization/IDeserializationCallback.cs b/src/mscorlib/src/System/Runtime/Serialization/IDeserializationCallback.cs
new file mode 100644
index 0000000000..e2497e5d34
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/IDeserializationCallback.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IDeserializationEventListener
+**
+**
+** Purpose: Implemented by any class that wants to indicate that
+** it wishes to receive deserialization events.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+ using System;
+
+ // Interface does not need to be marked with the serializable attribute
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IDeserializationCallback {
+ void OnDeserialization(Object sender);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/IFormatter.cs b/src/mscorlib/src/System/Runtime/Serialization/IFormatter.cs
new file mode 100644
index 0000000000..8d91d95acf
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/IFormatter.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IFormatter;
+**
+**
+** Purpose: The interface for all formatters.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+ using System.Runtime.Remoting;
+ using System;
+ using System.IO;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IFormatter {
+ Object Deserialize(Stream serializationStream);
+
+ void Serialize(Stream serializationStream, Object graph);
+
+
+ ISurrogateSelector SurrogateSelector {
+ get;
+ set;
+ }
+
+ SerializationBinder Binder {
+ get;
+ set;
+ }
+
+ StreamingContext Context {
+ get;
+ set;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/IFormatterConverter.cs b/src/mscorlib/src/System/Runtime/Serialization/IFormatterConverter.cs
new file mode 100644
index 0000000000..182cc93412
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/IFormatterConverter.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The interface provides the connection between an
+** instance of SerializationInfo and the formatter-provided
+** class which knows how to parse the data inside the
+** SerializationInfo.
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization {
+ using System;
+
+ [CLSCompliant(false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IFormatterConverter {
+ Object Convert(Object value, Type type);
+ Object Convert(Object value, TypeCode typeCode);
+ bool ToBoolean(Object value);
+ char ToChar(Object value);
+ sbyte ToSByte(Object value);
+ byte ToByte(Object value);
+ short ToInt16(Object value);
+ ushort ToUInt16(Object value);
+ int ToInt32(Object value);
+ uint ToUInt32(Object value);
+ long ToInt64(Object value);
+ ulong ToUInt64(Object value);
+ float ToSingle(Object value);
+ double ToDouble(Object value);
+ Decimal ToDecimal(Object value);
+ DateTime ToDateTime(Object value);
+ String ToString(Object value);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/IObjectReference.cs b/src/mscorlib/src/System/Runtime/Serialization/IObjectReference.cs
new file mode 100644
index 0000000000..f1a1bc0590
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/IObjectReference.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: IObjectReference
+**
+**
+** Purpose: Implemented by objects that are actually references
+** to a different object which can't be discovered until
+** this one is completely restored. During the fixup stage,
+** any object implementing IObjectReference is asked for it's
+** "real" object and that object is inserted into the graph.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+
+ using System;
+ using System.Security.Permissions;
+ // Interface does not need to be marked with the serializable attribute
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IObjectReference {
+ [System.Security.SecurityCritical] // auto-generated_required
+ Object GetRealObject(StreamingContext context);
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Runtime/Serialization/ISerializable.cs b/src/mscorlib/src/System/Runtime/Serialization/ISerializable.cs
new file mode 100644
index 0000000000..e59fa65043
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/ISerializable.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ISerializable
+**
+**
+** Purpose: Implemented by any object that needs to control its
+** own serialization.
+**
+**
+===========================================================*/
+
+namespace System.Runtime.Serialization {
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System;
+ using System.Reflection;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISerializable {
+ [System.Security.SecurityCritical] // auto-generated_required
+ void GetObjectData(SerializationInfo info, StreamingContext context);
+ }
+
+}
+
+
+
+
diff --git a/src/mscorlib/src/System/Runtime/Serialization/ISerializationSurrogate.cs b/src/mscorlib/src/System/Runtime/Serialization/ISerializationSurrogate.cs
new file mode 100644
index 0000000000..9bb30d99e0
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/ISerializationSurrogate.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ISurrogate
+**
+**
+** Purpose: The interface implemented by an object which
+** supports surrogates.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System;
+ using System.Reflection;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISerializationSurrogate {
+ // Interface does not need to be marked with the serializable attribute
+ // Returns a SerializationInfo completely populated with all of the data needed to reinstantiate the
+ // the object at the other end of serialization.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ void GetObjectData(Object obj, SerializationInfo info, StreamingContext context);
+
+ // Reinflate the object using all of the information in data. The information in
+ // members is used to find the particular field or property which needs to be set.
+ //
+ [System.Security.SecurityCritical] // auto-generated_required
+ Object SetObjectData(Object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/ISurrogateSelector.cs b/src/mscorlib/src/System/Runtime/Serialization/ISurrogateSelector.cs
new file mode 100644
index 0000000000..01b960f86b
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/ISurrogateSelector.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: ISurrogateSelector
+**
+**
+** Purpose: A user-supplied class for doing the type to surrogate
+** mapping.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+
+ using System.Runtime.Remoting;
+ using System.Security.Permissions;
+ using System;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISurrogateSelector {
+ // Interface does not need to be marked with the serializable attribute
+ // Specifies the next ISurrogateSelector to be examined for surrogates if the current
+ // instance doesn't have a surrogate for the given type and assembly in the given context.
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ChainSelector(ISurrogateSelector selector);
+
+ // Returns the appropriate surrogate for the given type in the given context.
+ [System.Security.SecurityCritical] // auto-generated_required
+ ISerializationSurrogate GetSurrogate(Type type, StreamingContext context, out ISurrogateSelector selector);
+
+
+ // Return the next surrogate in the chain. Returns null if no more exist.
+ [System.Security.SecurityCritical] // auto-generated_required
+ ISurrogateSelector GetNextSelector();
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/MemberHolder.cs b/src/mscorlib/src/System/Runtime/Serialization/MemberHolder.cs
new file mode 100644
index 0000000000..1303e40c27
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/MemberHolder.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This is a lightweight class designed to hold the members
+** and StreamingContext for a particular class.
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization {
+
+ using System.Runtime.Remoting;
+ using System;
+ using System.Reflection;
+ [Serializable]
+ internal class MemberHolder {
+// disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal MemberInfo[] members = null;
+#pragma warning restore 0414
+ internal Type memberType;
+ internal StreamingContext context;
+
+ internal MemberHolder(Type type, StreamingContext ctx) {
+ memberType = type;
+ context = ctx;
+ }
+
+ public override int GetHashCode() {
+ return memberType.GetHashCode();
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is MemberHolder)) {
+ return false;
+ }
+
+ MemberHolder temp = (MemberHolder)obj;
+
+ if (Object.ReferenceEquals(temp.memberType, memberType) && temp.context.State == context.State) {
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationAttributes.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationAttributes.cs
new file mode 100644
index 0000000000..27c5751cc6
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationAttributes.cs
@@ -0,0 +1,64 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Various Attributes for Serialization
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Reflection;
+
+ [AttributeUsage(AttributeTargets.Field, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OptionalFieldAttribute : Attribute
+ {
+ int versionAdded = 1;
+ public OptionalFieldAttribute() { }
+
+ public int VersionAdded
+ {
+ get {
+ return this.versionAdded;
+ }
+ set {
+ if (value < 1)
+ throw new ArgumentException(Environment.GetResourceString("Serialization_OptionalFieldVersionValue"));
+ Contract.EndContractBlock();
+ this.versionAdded = value;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OnSerializingAttribute : Attribute
+ {
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OnSerializedAttribute : Attribute
+ {
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OnDeserializingAttribute : Attribute
+ {
+ }
+
+ [AttributeUsage(AttributeTargets.Method, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class OnDeserializedAttribute : Attribute
+ {
+ }
+
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationBinder.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationBinder.cs
new file mode 100644
index 0000000000..7457991008
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationBinder.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Interface: SerializationBinder
+**
+**
+** Purpose: The base class of serialization binders.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+ using System;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class SerializationBinder {
+
+ public virtual void BindToName(Type serializedType, out String assemblyName, out String typeName)
+ {
+ assemblyName = null;
+ typeName = null;
+ }
+
+ public abstract Type BindToType(String assemblyName, String typeName);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationException.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationException.cs
new file mode 100644
index 0000000000..b88ccfd706
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Thrown when something goes wrong during serialization or
+** deserialization.
+**
+**
+=============================================================================*/
+
+namespace System.Runtime.Serialization {
+
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SerializationException : SystemException {
+
+ private static String _nullMessage = Environment.GetResourceString("Arg_SerializationException");
+
+ // Creates a new SerializationException with its message
+ // string set to a default message.
+ public SerializationException()
+ : base(_nullMessage) {
+ SetErrorCode(__HResults.COR_E_SERIALIZATION);
+ }
+
+ public SerializationException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_SERIALIZATION);
+ }
+
+ public SerializationException(String message, Exception innerException) : base (message, innerException) {
+ SetErrorCode(__HResults.COR_E_SERIALIZATION);
+ }
+
+ protected SerializationException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs
new file mode 100644
index 0000000000..5e7851bc57
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationFieldInfo.cs
@@ -0,0 +1,166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Provides a methods of representing imaginary fields
+** which are unique to serialization. In this case, what we're
+** representing is the private members of parent classes. We
+** aggregate the RuntimeFieldInfo associated with this member
+** and return a managled form of the name. The name that we
+** return is .parentname.fieldname
+**
+**
+============================================================*/
+
+namespace System.Runtime.Serialization {
+
+ using System;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Threading;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Metadata;
+#endif //FEATURE_REMOTING
+
+ internal sealed class SerializationFieldInfo : FieldInfo {
+
+ internal const String FakeNameSeparatorString = "+";
+
+ private RuntimeFieldInfo m_field;
+ private String m_serializationName;
+
+ public override Module Module { get { return m_field.Module; } }
+ public override int MetadataToken { get { return m_field.MetadataToken; } }
+
+ internal SerializationFieldInfo(RuntimeFieldInfo field, String namePrefix) {
+ Contract.Assert(field!=null, "[SerializationFieldInfo.ctor]field!=null");
+ Contract.Assert(namePrefix!=null, "[SerializationFieldInfo.ctor]namePrefix!=null");
+
+ m_field = field;
+ m_serializationName = String.Concat(namePrefix, FakeNameSeparatorString, m_field.Name);
+ }
+
+ //
+ // MemberInfo methods
+ //
+ public override String Name {
+ get {
+ return m_serializationName;
+ }
+ }
+
+ public override Type DeclaringType {
+ get {
+ return m_field.DeclaringType;
+ }
+ }
+
+ public override Type ReflectedType {
+ get {
+ return m_field.ReflectedType;
+ }
+ }
+
+ public override Object[] GetCustomAttributes(bool inherit) {
+ return m_field.GetCustomAttributes(inherit);
+ }
+
+ public override Object[] GetCustomAttributes(Type attributeType, bool inherit) {
+ return m_field.GetCustomAttributes(attributeType, inherit);
+ }
+
+ public override bool IsDefined(Type attributeType, bool inherit) {
+ return m_field.IsDefined(attributeType, inherit);
+ }
+
+ //
+ // FieldInfo methods
+ //
+ public override Type FieldType {
+ get {
+ return m_field.FieldType;
+ }
+ }
+
+ public override Object GetValue(Object obj) {
+ return m_field.GetValue(obj);
+ }
+
+ [System.Security.SecurityCritical]
+ internal Object InternalGetValue(Object obj) {
+ RtFieldInfo field = m_field as RtFieldInfo;
+ if (field != null)
+ {
+ field.CheckConsistency(obj);
+ return field.UnsafeGetValue(obj);
+ }
+ else
+ return m_field.GetValue(obj);
+ }
+
+ public override void SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) {
+ m_field.SetValue(obj, value, invokeAttr, binder, culture);
+ }
+
+ [System.Security.SecurityCritical]
+ internal void InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture) {
+ RtFieldInfo field = m_field as RtFieldInfo;
+ if (field != null)
+ {
+ field.CheckConsistency(obj);
+ field.UnsafeSetValue(obj, value, invokeAttr, binder, culture);
+ }
+ else
+ m_field.SetValue(obj, value, invokeAttr, binder, culture);
+ }
+
+ internal RuntimeFieldInfo FieldInfo {
+ get {
+ return m_field;
+ }
+ }
+
+ public override RuntimeFieldHandle FieldHandle {
+ get {
+ return m_field.FieldHandle;
+ }
+ }
+
+ public override FieldAttributes Attributes {
+ get {
+ return m_field.Attributes;
+ }
+ }
+
+#if FEATURE_REMOTING
+ #region Legacy Remoting Cache
+ private RemotingFieldCachedData m_cachedData;
+
+ internal RemotingFieldCachedData RemotingCache
+ {
+ get
+ {
+ // This grabs an internal copy of m_cachedData and uses
+ // that instead of looking at m_cachedData directly because
+ // the cache may get cleared asynchronously. This prevents
+ // us from having to take a lock.
+ RemotingFieldCachedData cache = m_cachedData;
+ if (cache == null)
+ {
+ cache = new RemotingFieldCachedData(this);
+ RemotingFieldCachedData ret = Interlocked.CompareExchange(ref m_cachedData, cache, null);
+ if (ret != null)
+ cache = ret;
+ }
+ return cache;
+ }
+ }
+ #endregion
+#endif //FEATURE_REMOTING
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs
new file mode 100644
index 0000000000..94e6825b51
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfo.cs
@@ -0,0 +1,798 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The structure for holding all of the data needed
+** for object serialization and deserialization.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization
+{
+
+ using System;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Runtime.Remoting;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Proxies;
+#endif
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+#if FEATURE_CORECLR
+ using System.Runtime.CompilerServices;
+#endif
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SerializationInfo
+ {
+ private const int defaultSize = 4;
+ private const string s_mscorlibAssemblySimpleName = System.CoreLib.Name;
+ private const string s_mscorlibFileName = s_mscorlibAssemblySimpleName + ".dll";
+
+ // Even though we have a dictionary, we're still keeping all the arrays around for back-compat.
+ // Otherwise we may run into potentially breaking behaviors like GetEnumerator() not returning entries in the same order they were added.
+ internal String[] m_members;
+ internal Object[] m_data;
+ internal Type[] m_types;
+ private Dictionary<string, int> m_nameToIndex;
+ internal int m_currMember;
+ internal IFormatterConverter m_converter;
+ private String m_fullTypeName;
+ private String m_assemName;
+ private Type objectType;
+ private bool isFullTypeNameSetExplicit;
+ private bool isAssemblyNameSetExplicit;
+ private bool requireSameTokenInPartialTrust;
+
+ [CLSCompliant(false)]
+ public SerializationInfo(Type type, IFormatterConverter converter)
+ : this(type, converter, false)
+ {
+ }
+
+ [CLSCompliant(false)]
+ public SerializationInfo(Type type, IFormatterConverter converter, bool requireSameTokenInPartialTrust)
+ {
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+
+ if (converter == null)
+ {
+ throw new ArgumentNullException("converter");
+ }
+
+ Contract.EndContractBlock();
+
+ objectType = type;
+ m_fullTypeName = type.FullName;
+ m_assemName = type.Module.Assembly.FullName;
+
+ m_members = new String[defaultSize];
+ m_data = new Object[defaultSize];
+ m_types = new Type[defaultSize];
+
+ m_nameToIndex = new Dictionary<string, int>();
+
+ m_converter = converter;
+
+ this.requireSameTokenInPartialTrust = requireSameTokenInPartialTrust;
+ }
+
+ public String FullTypeName
+ {
+ get
+ {
+ return m_fullTypeName;
+ }
+ set
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ m_fullTypeName = value;
+ isFullTypeNameSetExplicit = true;
+ }
+ }
+
+ public String AssemblyName
+ {
+ get
+ {
+ return m_assemName;
+ }
+ [SecuritySafeCritical]
+ set
+ {
+ if (null == value)
+ {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ if (this.requireSameTokenInPartialTrust)
+ {
+ DemandForUnsafeAssemblyNameAssignments(this.m_assemName, value);
+ }
+ m_assemName = value;
+ isAssemblyNameSetExplicit = true;
+ }
+ }
+
+ [SecuritySafeCritical]
+ public void SetType(Type type)
+ {
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ if (this.requireSameTokenInPartialTrust)
+ {
+ DemandForUnsafeAssemblyNameAssignments(this.ObjectType.Assembly.FullName, type.Assembly.FullName);
+ }
+
+ if (!Object.ReferenceEquals(objectType, type))
+ {
+ objectType = type;
+ m_fullTypeName = type.FullName;
+ m_assemName = type.Module.Assembly.FullName;
+ isFullTypeNameSetExplicit = false;
+ isAssemblyNameSetExplicit = false;
+ }
+ }
+
+ private static bool Compare(byte[] a, byte[] b)
+ {
+ // if either or both assemblies do not have public key token, we should demand, hence, returning false will force a demand
+ if (a == null || b == null || a.Length == 0 || b.Length == 0 || a.Length != b.Length)
+ {
+ return false;
+ }
+ else
+ {
+ for (int i = 0; i < a.Length; i++)
+ {
+ if (a[i] != b[i]) return false;
+ }
+
+ return true;
+ }
+ }
+
+ [SecuritySafeCritical]
+ internal static void DemandForUnsafeAssemblyNameAssignments(string originalAssemblyName, string newAssemblyName)
+ {
+#if !FEATURE_CORECLR
+ if (!IsAssemblyNameAssignmentSafe(originalAssemblyName, newAssemblyName))
+ {
+ CodeAccessPermission.Demand(PermissionType.SecuritySerialization);
+ }
+#endif
+ }
+
+ internal static bool IsAssemblyNameAssignmentSafe(string originalAssemblyName, string newAssemblyName)
+ {
+ if (originalAssemblyName == newAssemblyName)
+ {
+ return true;
+ }
+
+ AssemblyName originalAssembly = new AssemblyName(originalAssemblyName);
+ AssemblyName newAssembly = new AssemblyName(newAssemblyName);
+
+ // mscorlib will get loaded by the runtime regardless of its string casing or its public key token,
+ // so setting the assembly name to mscorlib must always be protected by a demand
+ if (string.Equals(newAssembly.Name, s_mscorlibAssemblySimpleName, StringComparison.OrdinalIgnoreCase) ||
+ string.Equals(newAssembly.Name, s_mscorlibFileName, StringComparison.OrdinalIgnoreCase))
+ {
+ return false;
+ }
+
+ return Compare(originalAssembly.GetPublicKeyToken(), newAssembly.GetPublicKeyToken());
+ }
+
+ public int MemberCount
+ {
+ get
+ {
+ return m_currMember;
+ }
+ }
+
+ public Type ObjectType
+ {
+ get
+ {
+ return objectType;
+ }
+ }
+
+ public bool IsFullTypeNameSetExplicit
+ {
+ get
+ {
+ return isFullTypeNameSetExplicit;
+ }
+ }
+
+ public bool IsAssemblyNameSetExplicit
+ {
+ get
+ {
+ return isAssemblyNameSetExplicit;
+ }
+ }
+
+ public SerializationInfoEnumerator GetEnumerator()
+ {
+ return new SerializationInfoEnumerator(m_members, m_data, m_types, m_currMember);
+ }
+
+ private void ExpandArrays()
+ {
+ int newSize;
+ Contract.Assert(m_members.Length == m_currMember, "[SerializationInfo.ExpandArrays]m_members.Length == m_currMember");
+
+ newSize = (m_currMember * 2);
+
+ //
+ // In the pathological case, we may wrap
+ //
+ if (newSize < m_currMember)
+ {
+ if (Int32.MaxValue > m_currMember)
+ {
+ newSize = Int32.MaxValue;
+ }
+ }
+
+ //
+ // Allocate more space and copy the data
+ //
+ String[] newMembers = new String[newSize];
+ Object[] newData = new Object[newSize];
+ Type[] newTypes = new Type[newSize];
+
+ Array.Copy(m_members, newMembers, m_currMember);
+ Array.Copy(m_data, newData, m_currMember);
+ Array.Copy(m_types, newTypes, m_currMember);
+
+ //
+ // Assign the new arrys back to the member vars.
+ //
+ m_members = newMembers;
+ m_data = newData;
+ m_types = newTypes;
+ }
+
+ public void AddValue(String name, Object value, Type type)
+ {
+ if (null == name)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ AddValueInternal(name, value, type);
+ }
+
+ public void AddValue(String name, Object value)
+ {
+ if (null == value)
+ {
+ AddValue(name, value, typeof(Object));
+ }
+ else
+ {
+ AddValue(name, value, value.GetType());
+ }
+ }
+
+ public void AddValue(String name, bool value)
+ {
+ AddValue(name, (Object)value, typeof(bool));
+ }
+
+ public void AddValue(String name, char value)
+ {
+ AddValue(name, (Object)value, typeof(char));
+ }
+
+
+ [CLSCompliant(false)]
+ public void AddValue(String name, sbyte value)
+ {
+ AddValue(name, (Object)value, typeof(sbyte));
+ }
+
+ public void AddValue(String name, byte value)
+ {
+ AddValue(name, (Object)value, typeof(byte));
+ }
+
+ public void AddValue(String name, short value)
+ {
+ AddValue(name, (Object)value, typeof(short));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(String name, ushort value)
+ {
+ AddValue(name, (Object)value, typeof(ushort));
+ }
+
+ public void AddValue(String name, int value)
+ {
+ AddValue(name, (Object)value, typeof(int));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(String name, uint value)
+ {
+ AddValue(name, (Object)value, typeof(uint));
+ }
+
+ public void AddValue(String name, long value)
+ {
+ AddValue(name, (Object)value, typeof(long));
+ }
+
+ [CLSCompliant(false)]
+ public void AddValue(String name, ulong value)
+ {
+ AddValue(name, (Object)value, typeof(ulong));
+ }
+
+ public void AddValue(String name, float value)
+ {
+ AddValue(name, (Object)value, typeof(float));
+ }
+
+ public void AddValue(String name, double value)
+ {
+ AddValue(name, (Object)value, typeof(double));
+ }
+
+ public void AddValue(String name, decimal value)
+ {
+ AddValue(name, (Object)value, typeof(decimal));
+ }
+
+ public void AddValue(String name, DateTime value)
+ {
+ AddValue(name, (Object)value, typeof(DateTime));
+ }
+
+ internal void AddValueInternal(String name, Object value, Type type)
+ {
+ if (m_nameToIndex.ContainsKey(name))
+ {
+ BCLDebug.Trace("SER", "[SerializationInfo.AddValue]Tried to add ", name, " twice to the SI.");
+ throw new SerializationException(Environment.GetResourceString("Serialization_SameNameTwice"));
+ }
+ m_nameToIndex.Add(name, m_currMember);
+
+ //
+ // If we need to expand the arrays, do so.
+ //
+ if (m_currMember >= m_members.Length)
+ {
+ ExpandArrays();
+ }
+
+ //
+ // Add the data and then advance the counter.
+ //
+ m_members[m_currMember] = name;
+ m_data[m_currMember] = value;
+ m_types[m_currMember] = type;
+ m_currMember++;
+ }
+
+ /*=================================UpdateValue==================================
+ **Action: Finds the value if it exists in the current data. If it does, we replace
+ ** the values, if not, we append it to the end. This is useful to the
+ ** ObjectManager when it's performing fixups.
+ **Returns: void
+ **Arguments: name -- the name of the data to be updated.
+ ** value -- the new value.
+ ** type -- the type of the data being added.
+ **Exceptions: None. All error checking is done with asserts. Although public in coreclr,
+ ** it's not exposed in a contract and is only meant to be used by corefx.
+ ==============================================================================*/
+#if FEATURE_CORECLR
+ // This should not be used by clients: exposing out this functionality would allow children
+ // to overwrite their parent's values. It is public in order to give corefx access to it for
+ // its ObjectManager implementation, but it should not be exposed out of a contract.
+ public
+#else
+ internal
+#endif
+ void UpdateValue(String name, Object value, Type type)
+ {
+ Contract.Assert(null != name, "[SerializationInfo.UpdateValue]name!=null");
+ Contract.Assert(null != value, "[SerializationInfo.UpdateValue]value!=null");
+ Contract.Assert(null != (object)type, "[SerializationInfo.UpdateValue]type!=null");
+
+ int index = FindElement(name);
+ if (index < 0)
+ {
+ AddValueInternal(name, value, type);
+ }
+ else
+ {
+ m_data[index] = value;
+ m_types[index] = type;
+ }
+
+ }
+
+ private int FindElement(String name)
+ {
+ if (null == name)
+ {
+ throw new ArgumentNullException("name");
+ }
+ Contract.EndContractBlock();
+ BCLDebug.Trace("SER", "[SerializationInfo.FindElement]Looking for ", name, " CurrMember is: ", m_currMember);
+ int index;
+ if (m_nameToIndex.TryGetValue(name, out index))
+ {
+ return index;
+ }
+ return -1;
+ }
+
+ /*==================================GetElement==================================
+ **Action: Use FindElement to get the location of a particular member and then return
+ ** the value of the element at that location. The type of the member is
+ ** returned in the foundType field.
+ **Returns: The value of the element at the position associated with name.
+ **Arguments: name -- the name of the element to find.
+ ** foundType -- the type of the element associated with the given name.
+ **Exceptions: None. FindElement does null checking and throws for elements not
+ ** found.
+ ==============================================================================*/
+ private Object GetElement(String name, out Type foundType)
+ {
+ int index = FindElement(name);
+ if (index == -1)
+ {
+ throw new SerializationException(Environment.GetResourceString("Serialization_NotFound", name));
+ }
+
+ Contract.Assert(index < m_data.Length, "[SerializationInfo.GetElement]index<m_data.Length");
+ Contract.Assert(index < m_types.Length, "[SerializationInfo.GetElement]index<m_types.Length");
+
+ foundType = m_types[index];
+ Contract.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
+ return m_data[index];
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ private Object GetElementNoThrow(String name, out Type foundType)
+ {
+ int index = FindElement(name);
+ if (index == -1)
+ {
+ foundType = null;
+ return null;
+ }
+
+ Contract.Assert(index < m_data.Length, "[SerializationInfo.GetElement]index<m_data.Length");
+ Contract.Assert(index < m_types.Length, "[SerializationInfo.GetElement]index<m_types.Length");
+
+ foundType = m_types[index];
+ Contract.Assert((object)foundType != null, "[SerializationInfo.GetElement]foundType!=null");
+ return m_data[index];
+ }
+
+ //
+ // The user should call one of these getters to get the data back in the
+ // form requested.
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Object GetValue(String name, Type type)
+ {
+
+ if ((object)type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ Contract.EndContractBlock();
+
+ RuntimeType rt = type as RuntimeType;
+ if (rt == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"));
+
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(value))
+ {
+ RealProxy proxy = RemotingServices.GetRealProxy(value);
+ if (RemotingServices.ProxyCheckCast(proxy, rt))
+ return value;
+ }
+ else
+#endif
+ if (Object.ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null)
+ {
+ return value;
+ }
+
+ Contract.Assert(m_converter != null, "[SerializationInfo.GetValue]m_converter!=null");
+
+ return m_converter.Convert(value, type);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.InteropServices.ComVisible(true)]
+ internal Object GetValueNoThrow(String name, Type type)
+ {
+ Type foundType;
+ Object value;
+
+ Contract.Assert((object)type != null, "[SerializationInfo.GetValue]type ==null");
+ Contract.Assert(type is RuntimeType, "[SerializationInfo.GetValue]type is not a runtime type");
+
+ value = GetElementNoThrow(name, out foundType);
+ if (value == null)
+ return null;
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(value))
+ {
+ RealProxy proxy = RemotingServices.GetRealProxy(value);
+ if (RemotingServices.ProxyCheckCast(proxy, (RuntimeType)type))
+ return value;
+ }
+ else
+#endif
+ if (Object.ReferenceEquals(foundType, type) || type.IsAssignableFrom(foundType) || value == null)
+ {
+ return value;
+ }
+
+ Contract.Assert(m_converter != null, "[SerializationInfo.GetValue]m_converter!=null");
+
+ return m_converter.Convert(value, type);
+ }
+
+ public bool GetBoolean(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(bool)))
+ {
+ return (bool)value;
+ }
+ return m_converter.ToBoolean(value);
+ }
+
+ public char GetChar(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(char)))
+ {
+ return (char)value;
+ }
+ return m_converter.ToChar(value);
+ }
+
+ [CLSCompliant(false)]
+ public sbyte GetSByte(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(sbyte)))
+ {
+ return (sbyte)value;
+ }
+ return m_converter.ToSByte(value);
+ }
+
+ public byte GetByte(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(byte)))
+ {
+ return (byte)value;
+ }
+ return m_converter.ToByte(value);
+ }
+
+ public short GetInt16(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(short)))
+ {
+ return (short)value;
+ }
+ return m_converter.ToInt16(value);
+ }
+
+ [CLSCompliant(false)]
+ public ushort GetUInt16(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(ushort)))
+ {
+ return (ushort)value;
+ }
+ return m_converter.ToUInt16(value);
+ }
+
+ public int GetInt32(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(int)))
+ {
+ return (int)value;
+ }
+ return m_converter.ToInt32(value);
+ }
+
+ [CLSCompliant(false)]
+ public uint GetUInt32(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(uint)))
+ {
+ return (uint)value;
+ }
+ return m_converter.ToUInt32(value);
+ }
+
+ public long GetInt64(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(long)))
+ {
+ return (long)value;
+ }
+ return m_converter.ToInt64(value);
+ }
+
+ [CLSCompliant(false)]
+ public ulong GetUInt64(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(ulong)))
+ {
+ return (ulong)value;
+ }
+ return m_converter.ToUInt64(value);
+ }
+
+ public float GetSingle(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(float)))
+ {
+ return (float)value;
+ }
+ return m_converter.ToSingle(value);
+ }
+
+
+ public double GetDouble(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(double)))
+ {
+ return (double)value;
+ }
+ return m_converter.ToDouble(value);
+ }
+
+ public decimal GetDecimal(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(decimal)))
+ {
+ return (decimal)value;
+ }
+ return m_converter.ToDecimal(value);
+ }
+
+ public DateTime GetDateTime(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(DateTime)))
+ {
+ return (DateTime)value;
+ }
+ return m_converter.ToDateTime(value);
+ }
+
+ public String GetString(String name)
+ {
+ Type foundType;
+ Object value;
+
+ value = GetElement(name, out foundType);
+ if (Object.ReferenceEquals(foundType, typeof(String)) || value == null)
+ {
+ return (String)value;
+ }
+ return m_converter.ToString(value);
+ }
+
+ internal string[] MemberNames
+ {
+ get
+ {
+ return m_members;
+ }
+
+ }
+
+ internal object[] MemberValues
+ {
+ get
+ {
+ return m_data;
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/SerializationInfoEnumerator.cs b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfoEnumerator.cs
new file mode 100644
index 0000000000..6b256a6e1f
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/SerializationInfoEnumerator.cs
@@ -0,0 +1,146 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A formatter-friendly mechanism for walking all of
+** the data in a SerializationInfo. Follows the IEnumerator
+** mechanism from Collections.
+**
+**
+============================================================*/
+namespace System.Runtime.Serialization {
+ using System;
+ using System.Collections;
+ using System.Diagnostics.Contracts;
+
+ //
+ // The tuple returned by SerializationInfoEnumerator.Current.
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct SerializationEntry {
+ private Type m_type;
+ private Object m_value;
+ private String m_name;
+
+ public Object Value {
+ get {
+ return m_value;
+ }
+ }
+
+ public String Name {
+ get {
+ return m_name;
+ }
+ }
+
+ public Type ObjectType {
+ get {
+ return m_type;
+ }
+ }
+
+ internal SerializationEntry(String entryName, Object entryValue, Type entryType) {
+ m_value = entryValue;
+ m_name = entryName;
+ m_type = entryType;
+ }
+ }
+
+ //
+ // A simple enumerator over the values stored in the SerializationInfo.
+ // This does not snapshot the values, it just keeps pointers to the
+ // member variables of the SerializationInfo that created it.
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SerializationInfoEnumerator : IEnumerator {
+ String[] m_members;
+ Object[] m_data;
+ Type[] m_types;
+ int m_numItems;
+ int m_currItem;
+ bool m_current;
+
+ internal SerializationInfoEnumerator(String[] members, Object[] info, Type[] types, int numItems) {
+ Contract.Assert(members!=null, "[SerializationInfoEnumerator.ctor]members!=null");
+ Contract.Assert(info!=null, "[SerializationInfoEnumerator.ctor]info!=null");
+ Contract.Assert(types!=null, "[SerializationInfoEnumerator.ctor]types!=null");
+ Contract.Assert(numItems>=0, "[SerializationInfoEnumerator.ctor]numItems>=0");
+ Contract.Assert(members.Length>=numItems, "[SerializationInfoEnumerator.ctor]members.Length>=numItems");
+ Contract.Assert(info.Length>=numItems, "[SerializationInfoEnumerator.ctor]info.Length>=numItems");
+ Contract.Assert(types.Length>=numItems, "[SerializationInfoEnumerator.ctor]types.Length>=numItems");
+
+ m_members = members;
+ m_data = info;
+ m_types = types;
+ //The MoveNext semantic is much easier if we enforce that [0..m_numItems] are valid entries
+ //in the enumerator, hence we subtract 1.
+ m_numItems = numItems-1;
+ m_currItem = -1;
+ m_current = false;
+ }
+
+ public bool MoveNext() {
+ if (m_currItem<m_numItems) {
+ m_currItem++;
+ m_current = true;
+ } else {
+ m_current = false;
+ }
+ return m_current;
+ }
+
+ /// <internalonly/>
+ Object IEnumerator.Current { //Actually returns a SerializationEntry
+ get {
+ if (m_current==false) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return (Object)(new SerializationEntry(m_members[m_currItem], m_data[m_currItem], m_types[m_currItem]));
+ }
+ }
+
+ public SerializationEntry Current { //Actually returns a SerializationEntry
+ get {
+ if (m_current==false) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return (new SerializationEntry(m_members[m_currItem], m_data[m_currItem], m_types[m_currItem]));
+ }
+ }
+
+ public void Reset() {
+ m_currItem = -1;
+ m_current = false;
+ }
+
+ public String Name {
+ get {
+ if (m_current==false) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return m_members[m_currItem];
+ }
+ }
+ public Object Value {
+ get {
+ if (m_current==false) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return m_data[m_currItem];
+ }
+ }
+ public Type ObjectType {
+ get {
+ if (m_current==false) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumOpCantHappen"));
+ }
+ return m_types[m_currItem];
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Serialization/StreamingContext.cs b/src/mscorlib/src/System/Runtime/Serialization/StreamingContext.cs
new file mode 100644
index 0000000000..ef4a096a51
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Serialization/StreamingContext.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** ValueType: StreamingContext
+**
+**
+** Purpose: A value type indicating the source or destination of our streaming.
+**
+**
+===========================================================*/
+namespace System.Runtime.Serialization {
+
+ using System.Runtime.Remoting;
+ using System;
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct StreamingContext {
+ internal Object m_additionalContext;
+ internal StreamingContextStates m_state;
+
+ public StreamingContext(StreamingContextStates state)
+ : this (state, null) {
+ }
+
+ public StreamingContext(StreamingContextStates state, Object additional) {
+ m_state = state;
+ m_additionalContext = additional;
+ }
+
+ public Object Context {
+ get { return m_additionalContext; }
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is StreamingContext)) {
+ return false;
+ }
+ if (((StreamingContext)obj).m_additionalContext == m_additionalContext &&
+ ((StreamingContext)obj).m_state == m_state) {
+ return true;
+ }
+ return false;
+ }
+
+ public override int GetHashCode() {
+ return (int)m_state;
+ }
+
+ public StreamingContextStates State {
+ get { return m_state; }
+ }
+ }
+
+ // **********************************************************
+ // Keep these in sync with the version in vm\runtimehandles.h
+ // **********************************************************
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum StreamingContextStates {
+ CrossProcess=0x01,
+ CrossMachine=0x02,
+ File =0x04,
+ Persistence =0x08,
+ Remoting =0x10,
+ Other =0x20,
+ Clone =0x40,
+ CrossAppDomain =0x80,
+ All =0xFF,
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs b/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs
new file mode 100644
index 0000000000..99e30b5488
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/BinaryCompatibility.cs
@@ -0,0 +1,485 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+**
+** Purpose: This class is used to determine which binary compatibility
+** behaviors are enabled at runtime. A type for
+** tracking which target Framework an app was built against, or an
+** appdomain-wide setting from the host telling us which .NET
+** Framework version we should emulate.
+**
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ // Provides a simple way to test whether an application was built against specific .NET Framework
+ // flavors and versions, with the intent of allowing Framework developers to mimic behavior of older
+ // Framework releases. This allows us to make behavioral breaking changes in a binary compatible way,
+ // for an application. This works at the per-AppDomain level, not process nor per-Assembly.
+ //
+ // To opt into newer behavior, applications must specify a TargetFrameworkAttribute on their assembly
+ // saying what version they targeted, or a host must set this when creating an AppDomain. Note
+ // that command line apps don't have this attribute!
+ //
+ // To use this class:
+ // Developers need to figure out whether they're working on the phone, desktop, or Silverlight, and
+ // what version they are introducing a breaking change in. Pick one predicate below, and use that
+ // to decide whether to run the new or old behavior. Example:
+ //
+ // if (BinaryCompatibility.TargetsAtLeast_Phone_V7_1) {
+ // // new behavior for phone 7.1 and other releases where we will integrate this change, like .NET Framework 4.5
+ // }
+ // else {
+ // // Legacy behavior
+ // }
+ //
+ // If you are making a breaking change in one specific branch that won't be integrated normally to
+ // all other branches (ie, say you're making breaking changes to Windows Phone 8 after .NET Framework v4.5
+ // has locked down for release), then add in specific predicates for each relevant platform.
+ //
+ // Maintainers of this class:
+ // Revisit the table once per release, perhaps at the end of the last coding milestone, to verify a
+ // default policy saying whether all quirks from a particular flavor & release should be enabled in
+ // other releases (ie, should all Windows Phone 8.0 quirks be enabled in .NET Framework v5)?
+ //
+ // History:
+ // Here is the order in which releases were made along with some basic integration information. The idea
+ // is to track what set of compatibility features are present in each other.
+ // While we cannot guarantee this list is perfectly linear (ie, a feature could be implemented in the last
+ // few weeks before shipping and make it into only one of three concommittent releases due to triaging),
+ // this is a good high level summary of code flow.
+ //
+ // Desktop Silverlight Windows Phone
+ // .NET Framework 3.0 -> Silverlight 2
+ // .NET Framework 3.5
+ // Silverlight 3
+ // Silverlight 4
+ // .NET Framework 4 Phone 8.0
+ // .NET Framework 4.5 Phone 8.1
+ // .NET Framework 4.5.1 Phone 8.1
+ //
+ // (Note: Windows Phone 7.0 was built using the .NET Compact Framework, which forked around v1 or v1.1)
+ //
+ // Compatibility Policy decisions:
+ // If we cannot determine that an app was built for a newer .NET Framework (ie, the app has no
+ // TargetFrameworkAttribute), then quirks will be enabled to emulate older behavior.
+ // As such, your test code should define the TargetFrameworkAttribute (which VS does for you)
+ // if you want to see the new behavior!
+ [FriendAccessAllowed]
+ internal static class BinaryCompatibility
+ {
+ // Use this for new behavior introduced in the phone branch. It will do the right thing for desktop & SL.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Phone_V7_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V7_1; } }
+
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Phone_V8_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Phone_V8_0; } }
+
+ // Use this for new behavior introduced in the Desktop branch. It will do the right thing for Phone & SL.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_1 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_1; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_2 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_2; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_3 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_3; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V4_5_4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V4_5_4; } }
+
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Desktop_V5_0 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Desktop_V5_0; } }
+
+ // Use this for new behavior introduced in the Silverlight branch. It will do the right thing for desktop & Phone.
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V4 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V4; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V5 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V5; } }
+ [FriendAccessAllowed]
+ internal static bool TargetsAtLeast_Silverlight_V6 { [FriendAccessAllowed] get { return s_map.TargetsAtLeast_Silverlight_V6; } }
+
+ [FriendAccessAllowed]
+ internal static TargetFrameworkId AppWasBuiltForFramework {
+ [FriendAccessAllowed]
+ get {
+ Contract.Ensures(Contract.Result<TargetFrameworkId>() > TargetFrameworkId.NotYetChecked);
+
+ if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked)
+ ReadTargetFrameworkId();
+
+ return s_AppWasBuiltForFramework;
+ }
+ }
+
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ [FriendAccessAllowed]
+ internal static int AppWasBuiltForVersion {
+ [FriendAccessAllowed]
+ get {
+ Contract.Ensures(Contract.Result<int>() > 0 || s_AppWasBuiltForFramework == TargetFrameworkId.Unspecified);
+
+ if (s_AppWasBuiltForFramework == TargetFrameworkId.NotYetChecked)
+ ReadTargetFrameworkId();
+
+ Contract.Assert(s_AppWasBuiltForFramework != TargetFrameworkId.Unrecognized);
+
+ return s_AppWasBuiltForVersion;
+ }
+ }
+
+ #region private
+ private static TargetFrameworkId s_AppWasBuiltForFramework;
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ private static int s_AppWasBuiltForVersion;
+
+ readonly static BinaryCompatibilityMap s_map = new BinaryCompatibilityMap();
+
+ // For parsing a target Framework moniker, from the FrameworkName class
+ private const char c_componentSeparator = ',';
+ private const char c_keyValueSeparator = '=';
+ private const char c_versionValuePrefix = 'v';
+ private const String c_versionKey = "Version";
+ private const String c_profileKey = "Profile";
+
+ /// <summary>
+ /// BinaryCompatibilityMap is basically a bitvector. There is a boolean field for each of the
+ /// properties in BinaryCompatibility
+ /// </summary>
+ private sealed class BinaryCompatibilityMap
+ {
+ // A bit for each property
+ internal bool TargetsAtLeast_Phone_V7_1;
+ internal bool TargetsAtLeast_Phone_V8_0;
+ internal bool TargetsAtLeast_Phone_V8_1;
+ internal bool TargetsAtLeast_Desktop_V4_5;
+ internal bool TargetsAtLeast_Desktop_V4_5_1;
+ internal bool TargetsAtLeast_Desktop_V4_5_2;
+ internal bool TargetsAtLeast_Desktop_V4_5_3;
+ internal bool TargetsAtLeast_Desktop_V4_5_4;
+ internal bool TargetsAtLeast_Desktop_V5_0;
+ internal bool TargetsAtLeast_Silverlight_V4;
+ internal bool TargetsAtLeast_Silverlight_V5;
+ internal bool TargetsAtLeast_Silverlight_V6;
+
+ internal BinaryCompatibilityMap()
+ {
+ AddQuirksForFramework(AppWasBuiltForFramework, AppWasBuiltForVersion);
+ }
+
+ // The purpose of this method is to capture information about integrations & behavioral compatibility
+ // between our multiple different release vehicles. IE, if a behavior shows up in Silverlight version 5,
+ // does it show up in the .NET Framework version 4.5 and Windows Phone 8?
+ // Version number is major * 10000 + minor * 100 + build (ie, 4.5.1.0 would be version 40501).
+ private void AddQuirksForFramework(TargetFrameworkId builtAgainstFramework, int buildAgainstVersion)
+ {
+ Contract.Requires(buildAgainstVersion > 0 || builtAgainstFramework == TargetFrameworkId.Unspecified);
+
+ switch (builtAgainstFramework)
+ {
+ case TargetFrameworkId.NetFramework:
+ case TargetFrameworkId.NetCore: // Treat Windows 8 tailored apps as normal desktop apps - same product
+ if (buildAgainstVersion >= 50000)
+ TargetsAtLeast_Desktop_V5_0 = true;
+
+ // Potential 4.5 servicing releases
+ if (buildAgainstVersion >= 40504)
+ TargetsAtLeast_Desktop_V4_5_4 = true;
+ if (buildAgainstVersion >= 40503)
+ TargetsAtLeast_Desktop_V4_5_3 = true;
+ if (buildAgainstVersion >= 40502)
+ TargetsAtLeast_Desktop_V4_5_2 = true;
+ if (buildAgainstVersion >= 40501)
+ TargetsAtLeast_Desktop_V4_5_1 = true;
+
+ if (buildAgainstVersion >= 40500)
+ {
+ TargetsAtLeast_Desktop_V4_5 = true;
+ // On XX/XX/XX we integrated all changes from the phone V7_1 into the branch from which contains Desktop V4_5, thus
+ // Any application built for V4_5 (or above) should have all the quirks for Phone V7_1 turned on.
+ AddQuirksForFramework(TargetFrameworkId.Phone, 70100);
+ // All Silverlight 5 behavior should be in the .NET Framework version 4.5
+ AddQuirksForFramework(TargetFrameworkId.Silverlight, 50000);
+ }
+ break;
+
+ case TargetFrameworkId.Phone:
+ if (buildAgainstVersion >= 80000)
+ {
+ // This is for Apollo apps. For Apollo apps we don't want to enable any of the 4.5 or 4.5.1 quirks
+ TargetsAtLeast_Phone_V8_0 = true;
+ //TargetsAtLeast_Desktop_V4_5 = true;
+ }
+ if (buildAgainstVersion >= 80100)
+ {
+ // For WindowsPhone 8.1 and SL 8.1 scenarios we want to enable both 4.5 and 4.5.1 quirks.
+ TargetsAtLeast_Desktop_V4_5 = true;
+ TargetsAtLeast_Desktop_V4_5_1 = true;
+ }
+
+ if (buildAgainstVersion >= 710)
+ TargetsAtLeast_Phone_V7_1 = true;
+ break;
+
+ case TargetFrameworkId.Silverlight:
+ if (buildAgainstVersion >= 40000)
+ TargetsAtLeast_Silverlight_V4 = true;
+
+ if (buildAgainstVersion >= 50000)
+ TargetsAtLeast_Silverlight_V5 = true;
+
+ if (buildAgainstVersion >= 60000)
+ {
+ TargetsAtLeast_Silverlight_V6 = true;
+ }
+ break;
+
+ case TargetFrameworkId.Unspecified:
+ break;
+
+ case TargetFrameworkId.NotYetChecked:
+ case TargetFrameworkId.Unrecognized:
+ Contract.Assert(false, "Bad framework kind");
+ break;
+ default:
+ Contract.Assert(false, "Error: we introduced a new Target Framework but did not update our binary compatibility map");
+ break;
+ }
+ }
+ }
+
+ #region String Parsing
+
+ // If this doesn't work, perhaps we could fall back to parsing the metadata version number.
+ private static bool ParseTargetFrameworkMonikerIntoEnum(String targetFrameworkMoniker, out TargetFrameworkId targetFramework, out int targetFrameworkVersion)
+ {
+ Contract.Requires(!String.IsNullOrEmpty(targetFrameworkMoniker));
+
+ targetFramework = TargetFrameworkId.NotYetChecked;
+ targetFrameworkVersion = 0;
+
+ String identifier = null;
+ String profile = null;
+ ParseFrameworkName(targetFrameworkMoniker, out identifier, out targetFrameworkVersion, out profile);
+
+ switch (identifier)
+ {
+ case ".NETFramework":
+ targetFramework = TargetFrameworkId.NetFramework;
+ break;
+
+ case ".NETPortable":
+ targetFramework = TargetFrameworkId.Portable;
+ break;
+
+ case ".NETCore":
+ targetFramework = TargetFrameworkId.NetCore;
+ break;
+
+ case "WindowsPhone":
+ if (targetFrameworkVersion >= 80100)
+ {
+ // A TFM of the form WindowsPhone,Version=v8.1 corresponds to SL 8.1 scenario
+ // and gets the same quirks as WindowsPhoneApp\v8.1 store apps.
+ targetFramework = TargetFrameworkId.Phone;
+ }
+ else
+ {
+ // There is no TFM for Apollo or below and hence we assign the targetFramework to Unspecified.
+ targetFramework = TargetFrameworkId.Unspecified;
+ }
+ break;
+
+ case "WindowsPhoneApp":
+ targetFramework = TargetFrameworkId.Phone;
+ break;
+
+ case "Silverlight":
+ targetFramework = TargetFrameworkId.Silverlight;
+ // Windows Phone 7 is Silverlight,Version=v4.0,Profile=WindowsPhone
+ // Windows Phone 7.1 is Silverlight,Version=v4.0,Profile=WindowsPhone71
+ if (!String.IsNullOrEmpty(profile))
+ {
+ if (profile == "WindowsPhone")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 70000;
+ }
+ else if (profile == "WindowsPhone71")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 70100;
+ }
+ else if (profile == "WindowsPhone8")
+ {
+ targetFramework = TargetFrameworkId.Phone;
+ targetFrameworkVersion = 80000;
+ }
+ else if (profile.StartsWith("WindowsPhone", StringComparison.Ordinal))
+ {
+ Contract.Assert(false, "This is a phone app, but we can't tell what version this is!");
+ targetFramework = TargetFrameworkId.Unrecognized;
+ targetFrameworkVersion = 70100;
+ }
+ else
+ {
+ Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Silverlight profile \"{0}\". What is this, an XBox app?", profile));
+ targetFramework = TargetFrameworkId.Unrecognized;
+ }
+ }
+ break;
+
+ default:
+ Contract.Assert(false, String.Format(CultureInfo.InvariantCulture, "Unrecognized Target Framework Moniker in our Binary Compatibility class. Framework name: \"{0}\"", targetFrameworkMoniker));
+ targetFramework = TargetFrameworkId.Unrecognized;
+ break;
+ }
+
+ return true;
+ }
+
+ // This code was a constructor copied from the FrameworkName class, which is located in System.dll.
+ // Parses strings in the following format: "<identifier>, Version=[v|V]<version>, Profile=<profile>"
+ // - The identifier and version is required, profile is optional
+ // - Only three components are allowed.
+ // - The version string must be in the System.Version format; an optional "v" or "V" prefix is allowed
+ private static void ParseFrameworkName(String frameworkName, out String identifier, out int version, out String profile)
+ {
+ if (frameworkName == null)
+ {
+ throw new ArgumentNullException("frameworkName");
+ }
+ if (frameworkName.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_StringZeroLength"), "frameworkName");
+ }
+ Contract.EndContractBlock();
+
+ String[] components = frameworkName.Split(c_componentSeparator);
+ version = 0;
+
+ // Identifer and Version are required, Profile is optional.
+ if (components.Length < 2 || components.Length > 3)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameTooShort"), "frameworkName");
+ }
+
+ //
+ // 1) Parse the "Identifier", which must come first. Trim any whitespace
+ //
+ identifier = components[0].Trim();
+
+ if (identifier.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+
+ bool versionFound = false;
+ profile = null;
+
+ //
+ // The required "Version" and optional "Profile" component can be in any order
+ //
+ for (int i = 1; i < components.Length; i++)
+ {
+ // Get the key/value pair separated by '='
+ string[] keyValuePair = components[i].Split(c_keyValueSeparator);
+
+ if (keyValuePair.Length != 2)
+ {
+ throw new ArgumentException(Environment.GetResourceString("SR.Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+
+ // Get the key and value, trimming any whitespace
+ string key = keyValuePair[0].Trim();
+ string value = keyValuePair[1].Trim();
+
+ //
+ // 2) Parse the required "Version" key value
+ //
+ if (key.Equals(c_versionKey, StringComparison.OrdinalIgnoreCase))
+ {
+ versionFound = true;
+
+ // Allow the version to include a 'v' or 'V' prefix...
+ if (value.Length > 0 && (value[0] == c_versionValuePrefix || value[0] == 'V'))
+ {
+ value = value.Substring(1);
+ }
+ Version realVersion = new Version(value);
+ // The version class will represent some unset values as -1 internally (instead of 0).
+ version = realVersion.Major * 10000;
+ if (realVersion.Minor > 0)
+ version += realVersion.Minor * 100;
+ if (realVersion.Build > 0)
+ version += realVersion.Build;
+ }
+ //
+ // 3) Parse the optional "Profile" key value
+ //
+ else if (key.Equals(c_profileKey, StringComparison.OrdinalIgnoreCase))
+ {
+ if (!String.IsNullOrEmpty(value))
+ {
+ profile = value;
+ }
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameInvalid"), "frameworkName");
+ }
+ }
+
+ if (!versionFound)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_FrameworkNameMissingVersion"), "frameworkName");
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static void ReadTargetFrameworkId()
+ {
+ String targetFrameworkName = AppDomain.CurrentDomain.GetTargetFrameworkName();
+
+ var overrideValue = System.Runtime.Versioning.CompatibilitySwitch.GetValueInternal("TargetFrameworkMoniker");
+ if (!string.IsNullOrEmpty(overrideValue))
+ {
+ targetFrameworkName = overrideValue;
+ }
+
+ // Write to a local then to _targetFramework, after writing the version number.
+ TargetFrameworkId fxId;
+ int fxVersion = 0;
+ if (targetFrameworkName == null)
+ {
+#if FEATURE_CORECLR
+ // if we don't have a value for targetFrameworkName we need to figure out if we should give the newest behavior or not.
+ if (CompatibilitySwitches.UseLatestBehaviorWhenTFMNotSpecified)
+ {
+ fxId = TargetFrameworkId.NetFramework;
+ fxVersion = 50000; // We are going to default to the latest value for version that we have in our code.
+ }
+ else
+#endif
+ fxId = TargetFrameworkId.Unspecified;
+ }
+ else if (!ParseTargetFrameworkMonikerIntoEnum(targetFrameworkName, out fxId, out fxVersion))
+ fxId = TargetFrameworkId.Unrecognized;
+
+ s_AppWasBuiltForFramework = fxId;
+ s_AppWasBuiltForVersion = fxVersion;
+ }
+ #endregion String Parsing
+
+ #endregion private
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs
new file mode 100644
index 0000000000..b06c42437c
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/CompatibilitySwitch.cs
@@ -0,0 +1,61 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ public static class CompatibilitySwitch
+ {
+ /* This class contains 3 sets of api:
+ * 1. internal apis : These apis are supposed to be used by mscorlib.dll and other assemblies which use the <runtime> section in config
+ * These apis query for the value of quirk not only in windows quirk DB but also in runtime section of config files,
+ * registry and environment vars.
+ * 2. public apis : These apis are supposed to be used by FX assemblies which do not read the runtime section of config files and have
+ * have their own section in config files or do not use configs at all.
+ *
+ * 3. specialized apis: These apis are defined in order to retrieve a specific value defined in CLR Config. That value can have specific look-up rules
+ * for the order and location of the config sources used.
+ *
+ * These apis are for internal use only for FX assmeblies. It has not been decided if they can be used by OOB components due to EULA restrictions
+ */
+ [System.Security.SecurityCritical]
+ public static bool IsEnabled(string compatibilitySwitchName)
+ {
+ return IsEnabledInternalCall(compatibilitySwitchName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ public static string GetValue(string compatibilitySwitchName)
+ {
+ // This is used by AppContext.TryGetSwitch to check switch overrides in the Windows Quirk DB
+ // If this method is updated to check other locations than the DB, please ensure compat with
+ // the AppContext class.
+ return GetValueInternalCall(compatibilitySwitchName, true);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool IsEnabledInternal(string compatibilitySwitchName)
+ {
+ return IsEnabledInternalCall(compatibilitySwitchName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ internal static string GetValueInternal(string compatibilitySwitchName)
+ {
+ return GetValueInternalCall(compatibilitySwitchName, false);
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern string GetAppContextOverridesInternalCall();
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern bool IsEnabledInternalCall(string compatibilitySwitchName, bool onlyDB);
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern string GetValueInternalCall(string compatibilitySwitchName, bool onlyDB);
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs
new file mode 100644
index 0000000000..0f906d518a
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/ComponentGuaranteesAttribute.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Tracking whether a component signs up for a
+** a strong contract spanning multiple versions.
+**
+===========================================================*/
+using System;
+
+namespace System.Runtime.Versioning {
+
+ [Flags]
+ [Serializable]
+ public enum ComponentGuaranteesOptions
+ {
+ None = 0,
+ Exchange = 0x1,
+ Stable = 0x2,
+ SideBySide = 0x4,
+ }
+
+ [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Module | AttributeTargets.Class |
+ AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate |
+ AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property |
+ AttributeTargets.Constructor | AttributeTargets.Event,
+ AllowMultiple = false, Inherited = false)]
+ public sealed class ComponentGuaranteesAttribute : Attribute {
+ private ComponentGuaranteesOptions _guarantees;
+
+ public ComponentGuaranteesAttribute(ComponentGuaranteesOptions guarantees)
+ {
+ _guarantees = guarantees;
+ }
+
+ public ComponentGuaranteesOptions Guarantees {
+ get { return _guarantees; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
new file mode 100644
index 0000000000..0a9845d9c2
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/NonVersionableAttribute.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: NonVersionableAttribute
+**
+**
+** The [NonVersionable] attribute is applied to indicate that the implementation
+** of a particular member or layout of a struct cannot be changed for given platform in incompatible way.
+** This allows cross-module inlining of methods and data structures whose implementation
+** is never changed in ReadyToRun native images. Any changes to such members or types would be
+** breaking changes for ReadyToRun.
+**
+===========================================================*/
+using System;
+using System.Diagnostics;
+
+namespace System.Runtime.Versioning {
+
+ // This Conditional is here to strip the annotations for targets where ReadyToRun is not supported.
+ // If this attribute is ever made public, this Conditional should be removed.
+ [Conditional("FEATURE_READYTORUN")]
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Constructor,
+ AllowMultiple = false, Inherited = false)]
+ sealed class NonVersionableAttribute : Attribute {
+
+ public NonVersionableAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs b/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs
new file mode 100644
index 0000000000..78a9ddbd07
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/ResourceAttributes.cs
@@ -0,0 +1,237 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Resource annotation rules.
+**
+===========================================================*/
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Text;
+using Microsoft.Win32;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.Versioning
+{
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)]
+ [Conditional("RESOURCE_ANNOTATION_WORK")]
+ public sealed class ResourceConsumptionAttribute : Attribute
+ {
+ private ResourceScope _consumptionScope;
+ private ResourceScope _resourceScope;
+
+ public ResourceConsumptionAttribute(ResourceScope resourceScope)
+ {
+ _resourceScope = resourceScope;
+ _consumptionScope = _resourceScope;
+ }
+
+ public ResourceConsumptionAttribute(ResourceScope resourceScope, ResourceScope consumptionScope)
+ {
+ _resourceScope = resourceScope;
+ _consumptionScope = consumptionScope;
+ }
+
+ public ResourceScope ResourceScope {
+ get { return _resourceScope; }
+ }
+
+ public ResourceScope ConsumptionScope {
+ get { return _consumptionScope; }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Constructor, Inherited = false)]
+ [Conditional("RESOURCE_ANNOTATION_WORK")]
+ public sealed class ResourceExposureAttribute : Attribute
+ {
+ private ResourceScope _resourceExposureLevel;
+
+ public ResourceExposureAttribute(ResourceScope exposureLevel)
+ {
+ _resourceExposureLevel = exposureLevel;
+ }
+
+ public ResourceScope ResourceExposureLevel {
+ get { return _resourceExposureLevel; }
+ }
+ }
+
+
+ // Default visibility is Public, which isn't specified in this enum.
+ // Public == the lack of Private or Assembly
+ // Does this actually work? Need to investigate that.
+ [Flags]
+ public enum ResourceScope
+ {
+ None = 0,
+ // Resource type
+ Machine = 0x1,
+ Process = 0x2,
+ AppDomain = 0x4,
+ Library = 0x8,
+ // Visibility
+ Private = 0x10, // Private to this one class.
+ Assembly = 0x20, // Assembly-level, like C#'s "internal"
+ }
+
+
+ [Flags]
+ internal enum SxSRequirements
+ {
+ None = 0,
+ AppDomainID = 0x1,
+ ProcessID = 0x2,
+ CLRInstanceID = 0x4, // for multiple CLR's within the process
+ AssemblyName = 0x8,
+ TypeName = 0x10
+ }
+
+ public static class VersioningHelper
+ {
+ // These depend on the exact values given to members of the ResourceScope enum.
+ private const ResourceScope ResTypeMask = ResourceScope.Machine | ResourceScope.Process | ResourceScope.AppDomain | ResourceScope.Library;
+ private const ResourceScope VisibilityMask = ResourceScope.Private | ResourceScope.Assembly;
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ private static extern int GetRuntimeId();
+
+ public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to)
+ {
+ return MakeVersionSafeName(name, from, to, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String MakeVersionSafeName(String name, ResourceScope from, ResourceScope to, Type type)
+ {
+ ResourceScope fromResType = from & ResTypeMask;
+ ResourceScope toResType = to & ResTypeMask;
+ if (fromResType > toResType)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ResourceScopeWrongDirection", fromResType, toResType), "from");
+
+ SxSRequirements requires = GetRequirements(to, from);
+
+ if ((requires & (SxSRequirements.AssemblyName | SxSRequirements.TypeName)) != 0 && type == null)
+ throw new ArgumentNullException("type", Environment.GetResourceString("ArgumentNull_TypeRequiredByResourceScope"));
+
+ // Add in process ID, CLR base address, and appdomain ID's. Also, use a character identifier
+ // to ensure that these can never accidentally overlap (ie, you create enough appdomains and your
+ // appdomain ID might equal your process ID).
+ StringBuilder safeName = new StringBuilder(name);
+ char separator = '_';
+ if ((requires & SxSRequirements.ProcessID) != 0) {
+ safeName.Append(separator);
+ safeName.Append('p');
+ safeName.Append(Win32Native.GetCurrentProcessId());
+ }
+ if ((requires & SxSRequirements.CLRInstanceID) != 0) {
+ String clrID = GetCLRInstanceString();
+ safeName.Append(separator);
+ safeName.Append('r');
+ safeName.Append(clrID);
+ }
+ if ((requires & SxSRequirements.AppDomainID) != 0) {
+ safeName.Append(separator);
+ safeName.Append("ad");
+ safeName.Append(AppDomain.CurrentDomain.Id);
+ }
+ if ((requires & SxSRequirements.TypeName) != 0) {
+ safeName.Append(separator);
+ safeName.Append(type.Name);
+ }
+ if ((requires & SxSRequirements.AssemblyName) != 0) {
+ safeName.Append(separator);
+ safeName.Append(type.Assembly.FullName);
+ }
+ return safeName.ToString();
+ }
+
+ private static String GetCLRInstanceString()
+ {
+ int id = GetRuntimeId();
+ return id.ToString(CultureInfo.InvariantCulture);
+ }
+
+ private static SxSRequirements GetRequirements(ResourceScope consumeAsScope, ResourceScope calleeScope)
+ {
+ SxSRequirements requires = SxSRequirements.None;
+
+ switch(calleeScope & ResTypeMask) {
+ case ResourceScope.Machine:
+ switch(consumeAsScope & ResTypeMask) {
+ case ResourceScope.Machine:
+ // No work
+ break;
+
+ case ResourceScope.Process:
+ requires |= SxSRequirements.ProcessID;
+ break;
+
+ case ResourceScope.AppDomain:
+ requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID | SxSRequirements.ProcessID;
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", consumeAsScope), "consumeAsScope");
+ }
+ break;
+
+ case ResourceScope.Process:
+ if ((consumeAsScope & ResourceScope.AppDomain) != 0)
+ requires |= SxSRequirements.AppDomainID | SxSRequirements.CLRInstanceID;
+ break;
+
+ case ResourceScope.AppDomain:
+ // No work
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeTypeBits", calleeScope), "calleeScope");
+ }
+
+ switch(calleeScope & VisibilityMask) {
+ case ResourceScope.None: // Public - implied
+ switch(consumeAsScope & VisibilityMask) {
+ case ResourceScope.None: // Public - implied
+ // No work
+ break;
+
+ case ResourceScope.Assembly:
+ requires |= SxSRequirements.AssemblyName;
+ break;
+
+ case ResourceScope.Private:
+ requires |= SxSRequirements.TypeName | SxSRequirements.AssemblyName;
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", consumeAsScope), "consumeAsScope");
+ }
+ break;
+
+ case ResourceScope.Assembly:
+ if ((consumeAsScope & ResourceScope.Private) != 0)
+ requires |= SxSRequirements.TypeName;
+ break;
+
+ case ResourceScope.Private:
+ // No work
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_BadResourceScopeVisibilityBits", calleeScope), "calleeScope");
+ }
+
+ if (consumeAsScope == calleeScope) {
+ Contract.Assert(requires == SxSRequirements.None, "Computed a strange set of required resource scoping. It's probably wrong.");
+ }
+
+ return requires;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs
new file mode 100644
index 0000000000..dbf98c08d8
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkAttribute.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: Identifies which SKU and version of the .NET
+** Framework that a particular library was compiled against.
+** Emitted by VS, and can help catch deployment problems.
+**
+===========================================================*/
+using System;
+using System.Diagnostics.Contracts;
+
+namespace System.Runtime.Versioning {
+
+ [AttributeUsageAttribute(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
+ public sealed class TargetFrameworkAttribute : Attribute {
+ private String _frameworkName; // A target framework moniker
+ private String _frameworkDisplayName;
+
+ // The frameworkName parameter is intended to be the string form of a FrameworkName instance.
+ public TargetFrameworkAttribute(String frameworkName)
+ {
+ if (frameworkName == null)
+ throw new ArgumentNullException("frameworkName");
+ Contract.EndContractBlock();
+ _frameworkName = frameworkName;
+ }
+
+ // The target framework moniker that this assembly was compiled against.
+ // Use the FrameworkName class to interpret target framework monikers.
+ public String FrameworkName {
+ get { return _frameworkName; }
+ }
+
+ public String FrameworkDisplayName {
+ get { return _frameworkDisplayName; }
+ set { _frameworkDisplayName = value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs
new file mode 100644
index 0000000000..0a5e668a92
--- /dev/null
+++ b/src/mscorlib/src/System/Runtime/Versioning/TargetFrameworkId.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Purpose: Describe the target framework of the application or AppDomain.
+**
+===========================================================*/
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.Versioning
+{
+ // What type of .NET Framework was this application compiled against?
+ [FriendAccessAllowed]
+ internal enum TargetFrameworkId
+ {
+ NotYetChecked = 0,
+ Unrecognized = 1, // Unknown type, such as a new SKU (like watches or cars)
+ Unspecified = 2, // The TargetFrameworkAttribute was created in v4.0. And apps compiled outside VS will not have this attribute.
+ NetFramework = 3, // Desktop - Client or Server or ServerCore.
+ Portable = 4, // Portable Library v1 Note: We do not expect people to build executables against portable libraries!
+ NetCore = 5, // .NET Core = Windows 8 Immersive and Portable Library v2+
+ Silverlight = 6, // Silverlight but not the Phone
+ Phone = 7, // Windows Phone 7 or higher
+ }
+}
diff --git a/src/mscorlib/src/System/RuntimeArgumentHandle.cs b/src/mscorlib/src/System/RuntimeArgumentHandle.cs
new file mode 100644
index 0000000000..d1bc86b49a
--- /dev/null
+++ b/src/mscorlib/src/System/RuntimeArgumentHandle.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ // This value type is used for constructing System.ArgIterator.
+ //
+ // SECURITY : m_ptr cannot be set to anything other than null by untrusted
+ // code.
+ //
+ // This corresponds to EE VARARGS cookie.
+
+ // Cannot be serialized
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct RuntimeArgumentHandle
+ {
+ private IntPtr m_ptr;
+
+ internal IntPtr Value { get { return m_ptr; } }
+ }
+
+}
diff --git a/src/mscorlib/src/System/RuntimeHandles.cs b/src/mscorlib/src/System/RuntimeHandles.cs
new file mode 100644
index 0000000000..24ca45e309
--- /dev/null
+++ b/src/mscorlib/src/System/RuntimeHandles.cs
@@ -0,0 +1,2101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System
+{
+ using System;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Runtime;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Threading;
+ using System.Runtime.Versioning;
+ using System.Text;
+ using System.Globalization;
+ using System.Security;
+ using System.Security.Permissions;
+ using Microsoft.Win32.SafeHandles;
+ using System.Diagnostics.Contracts;
+ using StackCrawlMark = System.Threading.StackCrawlMark;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe struct RuntimeTypeHandle : ISerializable
+ {
+ // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+ internal RuntimeTypeHandle GetNativeHandle()
+ {
+ // Create local copy to avoid a race condition
+ RuntimeType type = m_type;
+ if (type == null)
+ throw new ArgumentNullException(null, Environment.GetResourceString("Arg_InvalidHandle"));
+ return new RuntimeTypeHandle(type);
+ }
+
+ // Returns type for interop with EE. The type is guaranteed to be non-null.
+ internal RuntimeType GetTypeChecked()
+ {
+ // Create local copy to avoid a race condition
+ RuntimeType type = m_type;
+ if (type == null)
+ throw new ArgumentNullException(null, Environment.GetResourceString("Arg_InvalidHandle"));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsInstanceOfType(RuntimeType type, Object o);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static Type GetTypeHelper(Type typeStart, Type[] genericArgs, IntPtr pModifiers, int cModifiers)
+ {
+ Type type = typeStart;
+
+ if (genericArgs != null)
+ {
+ type = type.MakeGenericType(genericArgs);
+ }
+
+ if (cModifiers > 0)
+ {
+ int* arModifiers = (int*)pModifiers.ToPointer();
+ for(int i = 0; i < cModifiers; i++)
+ {
+ if ((CorElementType)Marshal.ReadInt32((IntPtr)arModifiers, i * sizeof(int)) == CorElementType.Ptr)
+ type = type.MakePointerType();
+
+ else if ((CorElementType)Marshal.ReadInt32((IntPtr)arModifiers, i * sizeof(int)) == CorElementType.ByRef)
+ type = type.MakeByRefType();
+
+ else if ((CorElementType)Marshal.ReadInt32((IntPtr)arModifiers, i * sizeof(int)) == CorElementType.SzArray)
+ type = type.MakeArrayType();
+
+ else
+ type = type.MakeArrayType(Marshal.ReadInt32((IntPtr)arModifiers, ++i * sizeof(int)));
+ }
+ }
+
+ return type;
+ }
+
+ public static bool operator ==(RuntimeTypeHandle left, object right) { return left.Equals(right); }
+
+ public static bool operator ==(object left, RuntimeTypeHandle right) { return right.Equals(left); }
+
+ public static bool operator !=(RuntimeTypeHandle left, object right) { return !left.Equals(right); }
+
+ public static bool operator !=(object left, RuntimeTypeHandle right) { return !right.Equals(left); }
+
+ internal static RuntimeTypeHandle EmptyHandle
+ {
+ get
+ {
+ return new RuntimeTypeHandle(null);
+ }
+ }
+
+
+ // This is the RuntimeType for the type
+ private RuntimeType m_type;
+
+ public override int GetHashCode()
+ {
+ return m_type != null ? m_type.GetHashCode() : 0;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public override bool Equals(object obj)
+ {
+ if(!(obj is RuntimeTypeHandle))
+ return false;
+
+ RuntimeTypeHandle handle =(RuntimeTypeHandle)obj;
+ return handle.m_type == m_type;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public bool Equals(RuntimeTypeHandle handle)
+ {
+ return handle.m_type == m_type;
+ }
+
+ public IntPtr Value
+ {
+ [SecurityCritical]
+ get
+ {
+ return m_type != null ? m_type.m_handle : IntPtr.Zero;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern IntPtr GetValueInternal(RuntimeTypeHandle handle);
+
+ internal RuntimeTypeHandle(RuntimeType type)
+ {
+ m_type = type;
+ }
+
+ internal bool IsNullHandle()
+ {
+ return m_type == null;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsPrimitive(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+ return (corElemType >= CorElementType.Boolean && corElemType <= CorElementType.R8) ||
+ corElemType == CorElementType.I ||
+ corElemType == CorElementType.U;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsByRef(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+ return (corElemType == CorElementType.ByRef);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsPointer(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+ return (corElemType == CorElementType.Ptr);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsArray(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+ return (corElemType == CorElementType.Array || corElemType == CorElementType.SzArray);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsSzArray(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+ return (corElemType == CorElementType.SzArray);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool HasElementType(RuntimeType type)
+ {
+ CorElementType corElemType = GetCorElementType(type);
+
+ return ((corElemType == CorElementType.Array || corElemType == CorElementType.SzArray) // IsArray
+ || (corElemType == CorElementType.Ptr) // IsPointer
+ || (corElemType == CorElementType.ByRef)); // IsByRef
+ }
+
+ [SecurityCritical]
+ internal static IntPtr[] CopyRuntimeTypeHandles(RuntimeTypeHandle[] inHandles, out int length)
+ {
+ if (inHandles == null || inHandles.Length == 0)
+ {
+ length = 0;
+ return null;
+ }
+
+ IntPtr[] outHandles = new IntPtr[inHandles.Length];
+ for (int i = 0; i < inHandles.Length; i++)
+ {
+ outHandles[i] = inHandles[i].Value;
+ }
+ length = outHandles.Length;
+ return outHandles;
+ }
+
+ [SecurityCritical]
+ internal static IntPtr[] CopyRuntimeTypeHandles(Type[] inHandles, out int length)
+ {
+ if (inHandles == null || inHandles.Length == 0)
+ {
+ length = 0;
+ return null;
+ }
+
+ IntPtr[] outHandles = new IntPtr[inHandles.Length];
+ for (int i = 0; i < inHandles.Length; i++)
+ {
+ outHandles[i] = inHandles[i].GetTypeHandleInternal().Value;
+ }
+ length = outHandles.Length;
+ return outHandles;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object CreateInstance(RuntimeType type, bool publicOnly, bool noCheck, ref bool canBeCached, ref RuntimeMethodHandleInternal ctor, ref bool bNeedSecurityCheck);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object CreateCaInstance(RuntimeType type, IRuntimeMethodInfo ctor);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object Allocate(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object CreateInstanceForAnotherGenericParameter(RuntimeType type, RuntimeType genericParameter);
+
+ internal RuntimeType GetRuntimeType()
+ {
+ return m_type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static CorElementType GetCorElementType(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeAssembly GetAssembly(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern static RuntimeModule GetModule(RuntimeType type);
+
+ [CLSCompliant(false)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public ModuleHandle GetModuleHandle()
+ {
+ return new ModuleHandle(RuntimeTypeHandle.GetModule(m_type));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeType GetBaseType(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static TypeAttributes GetAttributes(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeType GetElementType(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool CompareCanonicalHandles(RuntimeType left, RuntimeType right);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetArrayRank(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetToken(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeMethodHandleInternal GetMethodAt(RuntimeType type, int slot);
+
+ // This is managed wrapper for MethodTable::IntroducedMethodIterator
+ internal struct IntroducedMethodEnumerator
+ {
+ bool _firstCall;
+ RuntimeMethodHandleInternal _handle;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal IntroducedMethodEnumerator(RuntimeType type)
+ {
+ _handle = RuntimeTypeHandle.GetFirstIntroducedMethod(type);
+ _firstCall = true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool MoveNext()
+ {
+ if (_firstCall)
+ {
+ _firstCall = false;
+ }
+ else if (_handle.Value != IntPtr.Zero)
+ {
+ RuntimeTypeHandle.GetNextIntroducedMethod(ref _handle);
+ }
+ return !(_handle.Value == IntPtr.Zero);
+ }
+
+ public RuntimeMethodHandleInternal Current
+ {
+ get {
+ return _handle;
+ }
+ }
+
+ // Glue to make this work nicely with C# foreach statement
+ public IntroducedMethodEnumerator GetEnumerator()
+ {
+ return this;
+ }
+ }
+
+ internal static IntroducedMethodEnumerator GetIntroducedMethods(RuntimeType type)
+ {
+ return new IntroducedMethodEnumerator(type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern RuntimeMethodHandleInternal GetFirstIntroducedMethod(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetNextIntroducedMethod(ref RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool GetFields(RuntimeType type, IntPtr* result, int* count);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static Type[] GetInterfaces(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetConstraints(RuntimeTypeHandle handle, ObjectHandleOnStack types);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal Type[] GetConstraints()
+ {
+ Type[] types = null;
+ GetConstraints(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types));
+
+ return types;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static IntPtr GetGCHandle(RuntimeTypeHandle handle, GCHandleType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal IntPtr GetGCHandle(GCHandleType type)
+ {
+ return GetGCHandle(GetNativeHandle(), type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetNumVirtuals(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void VerifyInterfaceIsImplemented(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal void VerifyInterfaceIsImplemented(RuntimeTypeHandle interfaceHandle)
+ {
+ VerifyInterfaceIsImplemented(GetNativeHandle(), interfaceHandle.GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle handle, RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal int GetInterfaceMethodImplementationSlot(RuntimeTypeHandle interfaceHandle, RuntimeMethodHandleInternal interfaceMethodHandle)
+ {
+ return GetInterfaceMethodImplementationSlot(GetNativeHandle(), interfaceHandle.GetNativeHandle(), interfaceMethodHandle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsComObject(RuntimeType type, bool isGenericCOM);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsContextful(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsInterface(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private extern static bool _IsVisible(RuntimeTypeHandle typeHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsVisible(RuntimeType type)
+ {
+ return _IsVisible(new RuntimeTypeHandle(type));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecurityCritical(RuntimeTypeHandle typeHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecurityCritical()
+ {
+ return IsSecurityCritical(GetNativeHandle());
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecuritySafeCritical(RuntimeTypeHandle typeHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecuritySafeCritical()
+ {
+ return IsSecuritySafeCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecurityTransparent(RuntimeTypeHandle typeHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecurityTransparent()
+ {
+ return IsSecurityTransparent(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool HasProxyAttribute(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsValueType(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void ConstructName(RuntimeTypeHandle handle, TypeNameFormatFlags formatFlags, StringHandleOnStack retString);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal string ConstructName(TypeNameFormatFlags formatFlags)
+ {
+ string name = null;
+ ConstructName(GetNativeHandle(), formatFlags, JitHelpers.GetStringHandleOnStack(ref name));
+ return name;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void* _GetUtf8Name(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Utf8String GetUtf8Name(RuntimeType type)
+ {
+ return new Utf8String(_GetUtf8Name(type));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool CanCastTo(RuntimeType type, RuntimeType target);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeType GetDeclaringType(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static IRuntimeMethodInfo GetDeclaringMethod(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetDefaultConstructor(RuntimeTypeHandle handle, ObjectHandleOnStack method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal IRuntimeMethodInfo GetDefaultConstructor()
+ {
+ IRuntimeMethodInfo ctor = null;
+ GetDefaultConstructor(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref ctor));
+ return ctor;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, StackCrawlMarkHandle stackMark,
+ IntPtr pPrivHostBinder,
+ bool loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive);
+
+ // Wrapper function to reduce the need for ifdefs.
+ internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref StackCrawlMark stackMark, bool loadTypeFromPartialName)
+ {
+ return GetTypeByName(name, throwOnError, ignoreCase, reflectionOnly, ref stackMark, IntPtr.Zero, loadTypeFromPartialName);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetTypeByName(string name, bool throwOnError, bool ignoreCase, bool reflectionOnly, ref StackCrawlMark stackMark,
+ IntPtr pPrivHostBinder,
+ bool loadTypeFromPartialName)
+ {
+ if (name == null || name.Length == 0)
+ {
+ if (throwOnError)
+ throw new TypeLoadException(Environment.GetResourceString("Arg_TypeLoadNullStr"));
+
+ return null;
+ }
+
+ RuntimeType type = null;
+
+ Object keepAlive = null;
+ GetTypeByName(name, throwOnError, ignoreCase, reflectionOnly,
+ JitHelpers.GetStackCrawlMarkHandle(ref stackMark),
+ pPrivHostBinder,
+ loadTypeFromPartialName, JitHelpers.GetObjectHandleOnStack(ref type), JitHelpers.GetObjectHandleOnStack(ref keepAlive));
+ GC.KeepAlive(keepAlive);
+
+ return type;
+ }
+
+ internal static Type GetTypeByName(string name, ref StackCrawlMark stackMark)
+ {
+ return GetTypeByName(name, false, false, false, ref stackMark, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetTypeByNameUsingCARules(string name, RuntimeModule scope, ObjectHandleOnStack type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetTypeByNameUsingCARules(string name, RuntimeModule scope)
+ {
+ if (name == null || name.Length == 0)
+ throw new ArgumentException("name");
+ Contract.EndContractBlock();
+
+ RuntimeType type = null;
+ GetTypeByNameUsingCARules(name, scope.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref type));
+
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static void GetInstantiation(RuntimeTypeHandle type, ObjectHandleOnStack types, bool fAsRuntimeTypeArray);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeType[] GetInstantiationInternal()
+ {
+ RuntimeType[] types = null;
+ GetInstantiation(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types), true);
+ return types;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal Type[] GetInstantiationPublic()
+ {
+ Type[] types = null;
+ GetInstantiation(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref types), false);
+ return types;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeType Instantiate(Type[] inst)
+ {
+ // defensive copy to be sure array is not mutated from the outside during processing
+ int instCount;
+ IntPtr []instHandles = CopyRuntimeTypeHandles(inst, out instCount);
+
+ fixed (IntPtr* pInst = instHandles)
+ {
+ RuntimeType type = null;
+ Instantiate(GetNativeHandle(), pInst, instCount, JitHelpers.GetObjectHandleOnStack(ref type));
+ GC.KeepAlive(inst);
+ return type;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void MakeArray(RuntimeTypeHandle handle, int rank, ObjectHandleOnStack type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeType MakeArray(int rank)
+ {
+ RuntimeType type = null;
+ MakeArray(GetNativeHandle(), rank, JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void MakeSZArray(RuntimeTypeHandle handle, ObjectHandleOnStack type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeType MakeSZArray()
+ {
+ RuntimeType type = null;
+ MakeSZArray(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void MakeByRef(RuntimeTypeHandle handle, ObjectHandleOnStack type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal RuntimeType MakeByRef()
+ {
+ RuntimeType type = null;
+ MakeByRef(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void MakePointer(RuntimeTypeHandle handle, ObjectHandleOnStack type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal RuntimeType MakePointer()
+ {
+ RuntimeType type = null;
+ MakePointer(GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static bool IsCollectible(RuntimeTypeHandle handle);
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool HasInstantiation(RuntimeType type);
+
+ internal bool HasInstantiation()
+ {
+ return HasInstantiation(GetTypeChecked());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetGenericTypeDefinition(RuntimeTypeHandle type, ObjectHandleOnStack retType);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetGenericTypeDefinition(RuntimeType type)
+ {
+ RuntimeType retType = type;
+
+ if (HasInstantiation(retType) && !IsGenericTypeDefinition(retType))
+ GetGenericTypeDefinition(retType.GetTypeHandleInternal(), JitHelpers.GetObjectHandleOnStack(ref retType));
+
+ return retType;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsGenericTypeDefinition(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsGenericVariable(RuntimeType type);
+
+ internal bool IsGenericVariable()
+ {
+ return IsGenericVariable(GetTypeChecked());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static int GetGenericVariableIndex(RuntimeType type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal int GetGenericVariableIndex()
+ {
+ RuntimeType type = GetTypeChecked();
+
+ if (!IsGenericVariable(type))
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+
+ return GetGenericVariableIndex(type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool ContainsGenericVariables(RuntimeType handle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool ContainsGenericVariables()
+ {
+ return ContainsGenericVariables(GetTypeChecked());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static bool SatisfiesConstraints(RuntimeType paramType, IntPtr *pTypeContext, int typeContextLength, IntPtr *pMethodContext, int methodContextLength, RuntimeType toType);
+
+ [System.Security.SecurityCritical]
+ internal static bool SatisfiesConstraints(RuntimeType paramType, RuntimeType[] typeContext, RuntimeType[] methodContext, RuntimeType toType)
+ {
+ int typeContextLength;
+ int methodContextLength;
+ IntPtr[] typeContextHandles = CopyRuntimeTypeHandles(typeContext, out typeContextLength);
+ IntPtr[] methodContextHandles = CopyRuntimeTypeHandles(methodContext, out methodContextLength);
+
+ fixed (IntPtr *pTypeContextHandles = typeContextHandles, pMethodContextHandles = methodContextHandles)
+ {
+ bool result = SatisfiesConstraints(paramType, pTypeContextHandles, typeContextLength, pMethodContextHandles, methodContextLength, toType);
+
+ GC.KeepAlive(typeContext);
+ GC.KeepAlive(methodContext);
+
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static IntPtr _GetMetadataImport(RuntimeType type);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static MetadataImport GetMetadataImport(RuntimeType type)
+ {
+ return new MetadataImport(_GetMetadataImport(type), type);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private RuntimeTypeHandle(SerializationInfo info, StreamingContext context)
+ {
+ if(info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ RuntimeType m = (RuntimeType)info.GetValue("TypeObj", typeof(RuntimeType));
+
+ m_type = m;
+
+ if (m_type == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+
+ [System.Security.SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if(info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ if (m_type == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFieldState"));
+
+ info.AddValue("TypeObj", m_type, typeof(RuntimeType));
+ }
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern bool IsEquivalentTo(RuntimeType rtType1, RuntimeType rtType2);
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern bool IsEquivalentType(RuntimeType type);
+#endif // FEATURE_CORECLR
+ }
+
+ // This type is used to remove the expense of having a managed reference object that is dynamically
+ // created when we can prove that we don't need that object. Use of this type requires code to ensure
+ // that the underlying native resource is not freed.
+ // Cases in which this may be used:
+ // 1. When native code calls managed code passing one of these as a parameter
+ // 2. When managed code acquires one of these from an IRuntimeMethodInfo, and ensure that the IRuntimeMethodInfo is preserved
+ // across the lifetime of the RuntimeMethodHandleInternal instance
+ // 3. When another object is used to keep the RuntimeMethodHandleInternal alive. See delegates, CreateInstance cache, Signature structure
+ // When in doubt, do not use.
+ internal struct RuntimeMethodHandleInternal
+ {
+ internal static RuntimeMethodHandleInternal EmptyHandle
+ {
+ get
+ {
+ return new RuntimeMethodHandleInternal();
+ }
+ }
+
+ internal bool IsNullHandle()
+ {
+ return m_handle.IsNull();
+ }
+
+ internal IntPtr Value
+ {
+ [SecurityCritical]
+ get
+ {
+ return m_handle;
+ }
+ }
+
+ [SecurityCritical]
+ internal RuntimeMethodHandleInternal(IntPtr value)
+ {
+ m_handle = value;
+ }
+
+ internal IntPtr m_handle;
+ }
+
+ internal class RuntimeMethodInfoStub : IRuntimeMethodInfo
+ {
+ public RuntimeMethodInfoStub(RuntimeMethodHandleInternal methodHandleValue, object keepalive)
+ {
+ m_keepalive = keepalive;
+ m_value = methodHandleValue;
+ }
+
+ [SecurityCritical]
+ public RuntimeMethodInfoStub(IntPtr methodHandleValue, object keepalive)
+ {
+ m_keepalive = keepalive;
+ m_value = new RuntimeMethodHandleInternal(methodHandleValue);
+ }
+
+ object m_keepalive;
+
+ // These unused variables are used to ensure that this class has the same layout as RuntimeMethodInfo
+#pragma warning disable 169
+ object m_a;
+ object m_b;
+ object m_c;
+ object m_d;
+ object m_e;
+ object m_f;
+ object m_g;
+#if FEATURE_REMOTING
+ object m_h;
+#endif
+#pragma warning restore 169
+ public RuntimeMethodHandleInternal m_value;
+
+ RuntimeMethodHandleInternal IRuntimeMethodInfo.Value
+ {
+ get
+ {
+ return m_value;
+ }
+ }
+ }
+
+ internal interface IRuntimeMethodInfo
+ {
+ RuntimeMethodHandleInternal Value
+ {
+ get;
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe struct RuntimeMethodHandle : ISerializable
+ {
+ // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+ internal static IRuntimeMethodInfo EnsureNonNullMethodInfo(IRuntimeMethodInfo method)
+ {
+ if (method == null)
+ throw new ArgumentNullException(null, Environment.GetResourceString("Arg_InvalidHandle"));
+ return method;
+ }
+
+ internal static RuntimeMethodHandle EmptyHandle
+ {
+ get { return new RuntimeMethodHandle(); }
+ }
+
+ private IRuntimeMethodInfo m_value;
+
+ internal RuntimeMethodHandle(IRuntimeMethodInfo method)
+ {
+ m_value = method;
+ }
+
+ internal IRuntimeMethodInfo GetMethodInfo()
+ {
+ return m_value;
+ }
+
+ // Used by EE
+ [SecurityCritical]
+ private static IntPtr GetValueInternal(RuntimeMethodHandle rmh)
+ {
+ return rmh.Value;
+ }
+
+ // ISerializable interface
+ [System.Security.SecurityCritical] // auto-generated
+ private RuntimeMethodHandle(SerializationInfo info, StreamingContext context)
+ {
+ if(info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ MethodBase m =(MethodBase)info.GetValue("MethodObj", typeof(MethodBase));
+
+ m_value = m.MethodHandle.m_value;
+
+ if (m_value == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+
+ [System.Security.SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ if (m_value == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFieldState"));
+
+ // This is either a RuntimeMethodInfo or a RuntimeConstructorInfo
+ MethodBase methodInfo = RuntimeType.GetMethodBase(m_value);
+
+ info.AddValue("MethodObj", methodInfo, typeof(MethodBase));
+ }
+
+ public IntPtr Value
+ {
+ [SecurityCritical]
+ get
+ {
+ return m_value != null ? m_value.Value.Value : IntPtr.Zero;
+ }
+ }
+
+ [SecuritySafeCritical]
+ public override int GetHashCode()
+ {
+ return ValueType.GetHashCodeOfPtr(Value);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical]
+ public override bool Equals(object obj)
+ {
+ if (!(obj is RuntimeMethodHandle))
+ return false;
+
+ RuntimeMethodHandle handle = (RuntimeMethodHandle)obj;
+
+ return handle.Value == Value;
+ }
+
+ public static bool operator ==(RuntimeMethodHandle left, RuntimeMethodHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(RuntimeMethodHandle left, RuntimeMethodHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical]
+ public bool Equals(RuntimeMethodHandle handle)
+ {
+ return handle.Value == Value;
+ }
+
+ [Pure]
+ internal bool IsNullHandle()
+ {
+ return m_value == null;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static IntPtr GetFunctionPointer(RuntimeMethodHandleInternal handle);
+
+ [System.Security.SecurityCritical] // auto-generated
+ public IntPtr GetFunctionPointer()
+ {
+ IntPtr ptr = GetFunctionPointer(EnsureNonNullMethodInfo(m_value).Value);
+ GC.KeepAlive(m_value);
+ return ptr;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe extern static void CheckLinktimeDemands(IRuntimeMethodInfo method, RuntimeModule module, bool isDecoratedTargetSecurityTransparent);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static bool IsCAVisibleFromDecoratedType(
+ RuntimeTypeHandle attrTypeHandle,
+ IRuntimeMethodInfo attrCtor,
+ RuntimeTypeHandle sourceTypeHandle,
+ RuntimeModule sourceModule);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IRuntimeMethodInfo _GetCurrentMethod(ref StackCrawlMark stackMark);
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IRuntimeMethodInfo GetCurrentMethod(ref StackCrawlMark stackMark)
+ {
+ return _GetCurrentMethod(ref stackMark);
+ }
+
+ [Pure]
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern MethodAttributes GetAttributes(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static MethodAttributes GetAttributes(IRuntimeMethodInfo method)
+ {
+ MethodAttributes retVal = RuntimeMethodHandle.GetAttributes(method.Value);
+ GC.KeepAlive(method);
+ return retVal;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern MethodImplAttributes GetImplAttributes(IRuntimeMethodInfo method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void ConstructInstantiation(IRuntimeMethodInfo method, TypeNameFormatFlags format, StringHandleOnStack retString);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static string ConstructInstantiation(IRuntimeMethodInfo method, TypeNameFormatFlags format)
+ {
+ string name = null;
+ ConstructInstantiation(EnsureNonNullMethodInfo(method), format, JitHelpers.GetStringHandleOnStack(ref name));
+ return name;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeType GetDeclaringType(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetDeclaringType(IRuntimeMethodInfo method)
+ {
+ RuntimeType type = RuntimeMethodHandle.GetDeclaringType(method.Value);
+ GC.KeepAlive(method);
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetSlot(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static int GetSlot(IRuntimeMethodInfo method)
+ {
+ Contract.Requires(method != null);
+
+ int slot = RuntimeMethodHandle.GetSlot(method.Value);
+ GC.KeepAlive(method);
+ return slot;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetMethodDef(IRuntimeMethodInfo method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static string GetName(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static string GetName(IRuntimeMethodInfo method)
+ {
+ string name = RuntimeMethodHandle.GetName(method.Value);
+ GC.KeepAlive(method);
+ return name;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static void* _GetUtf8Name(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static Utf8String GetUtf8Name(RuntimeMethodHandleInternal method)
+ {
+ return new Utf8String(_GetUtf8Name(method));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool MatchesNameHash(RuntimeMethodHandleInternal method, uint hash);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static object InvokeMethod(object target, object[] arguments, Signature sig, bool constructor);
+
+#region Private Invocation Helpers
+ [System.Security.SecurityCritical] // auto-generated
+ internal static INVOCATION_FLAGS GetSecurityFlags(IRuntimeMethodInfo handle)
+ {
+ return (INVOCATION_FLAGS)RuntimeMethodHandle.GetSpecialSecurityFlags(handle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern internal uint GetSpecialSecurityFlags(IRuntimeMethodInfo method);
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern internal void PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, uint invocationFlags);
+
+ [System.Security.SecurityCritical]
+ static internal void PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, uint invocationFlags)
+ {
+ RuntimeMethodHandle.PerformSecurityCheck(obj, method.Value, parent, invocationFlags);
+ GC.KeepAlive(method);
+ return;
+ }
+#endif //!FEATURE_CORECLR
+#endregion
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static void SerializationInvoke(IRuntimeMethodInfo method,
+ Object target, SerializationInfo info, ref StreamingContext context);
+
+ // This returns true if the token is SecurityTransparent:
+ // just the token - does not consider including module/type etc.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool _IsTokenSecurityTransparent(RuntimeModule module, int metaDataToken);
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#else
+ [System.Security.SecurityCritical]
+#endif
+ internal static bool IsTokenSecurityTransparent(Module module, int metaDataToken)
+ {
+ return _IsTokenSecurityTransparent(module.ModuleHandle.GetRuntimeModule(), metaDataToken);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool _IsSecurityCritical(IRuntimeMethodInfo method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsSecurityCritical(IRuntimeMethodInfo method)
+ {
+ return _IsSecurityCritical(method);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool _IsSecuritySafeCritical(IRuntimeMethodInfo method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsSecuritySafeCritical(IRuntimeMethodInfo method)
+ {
+ return _IsSecuritySafeCritical(method);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool _IsSecurityTransparent(IRuntimeMethodInfo method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsSecurityTransparent(IRuntimeMethodInfo method)
+ {
+ return _IsSecurityTransparent(method);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetMethodInstantiation(RuntimeMethodHandleInternal method, ObjectHandleOnStack types, bool fAsRuntimeTypeArray);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType[] GetMethodInstantiationInternal(IRuntimeMethodInfo method)
+ {
+ RuntimeType[] types = null;
+ GetMethodInstantiation(EnsureNonNullMethodInfo(method).Value, JitHelpers.GetObjectHandleOnStack(ref types), true);
+ GC.KeepAlive(method);
+ return types;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType[] GetMethodInstantiationInternal(RuntimeMethodHandleInternal method)
+ {
+ RuntimeType[] types = null;
+ GetMethodInstantiation(method, JitHelpers.GetObjectHandleOnStack(ref types), true);
+ return types;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static Type[] GetMethodInstantiationPublic(IRuntimeMethodInfo method)
+ {
+ RuntimeType[] types = null;
+ GetMethodInstantiation(EnsureNonNullMethodInfo(method).Value, JitHelpers.GetObjectHandleOnStack(ref types), false);
+ GC.KeepAlive(method);
+ return types;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool HasMethodInstantiation(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool HasMethodInstantiation(IRuntimeMethodInfo method)
+ {
+ bool fRet = RuntimeMethodHandle.HasMethodInstantiation(method.Value);
+ GC.KeepAlive(method);
+ return fRet;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeMethodHandleInternal GetStubIfNeeded(RuntimeMethodHandleInternal method, RuntimeType declaringType, RuntimeType[] methodInstantiation);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static RuntimeMethodHandleInternal GetMethodFromCanonical(RuntimeMethodHandleInternal method, RuntimeType declaringType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsGenericMethodDefinition(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static bool IsGenericMethodDefinition(IRuntimeMethodInfo method)
+ {
+ bool fRet = RuntimeMethodHandle.IsGenericMethodDefinition(method.Value);
+ GC.KeepAlive(method);
+ return fRet;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsTypicalMethodDefinition(IRuntimeMethodInfo method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetTypicalMethodDefinition(IRuntimeMethodInfo method, ObjectHandleOnStack outMethod);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IRuntimeMethodInfo GetTypicalMethodDefinition(IRuntimeMethodInfo method)
+ {
+ if (!IsTypicalMethodDefinition(method))
+ GetTypicalMethodDefinition(method, JitHelpers.GetObjectHandleOnStack(ref method));
+
+ return method;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void StripMethodInstantiation(IRuntimeMethodInfo method, ObjectHandleOnStack outMethod);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IRuntimeMethodInfo StripMethodInstantiation(IRuntimeMethodInfo method)
+ {
+ IRuntimeMethodInfo strippedMethod = method;
+
+ StripMethodInstantiation(method, JitHelpers.GetObjectHandleOnStack(ref strippedMethod));
+
+ return strippedMethod;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static bool IsDynamicMethod(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static void Destroy(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static Resolver GetResolver(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetCallerType(StackCrawlMarkHandle stackMark, ObjectHandleOnStack retType);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetCallerType(ref StackCrawlMark stackMark)
+ {
+ RuntimeType type = null;
+ GetCallerType(JitHelpers.GetStackCrawlMarkHandle(ref stackMark), JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal extern static MethodBody GetMethodBody(IRuntimeMethodInfo method, RuntimeType declaringType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static bool IsConstructor(RuntimeMethodHandleInternal method);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal extern static LoaderAllocator GetLoaderAllocator(RuntimeMethodHandleInternal method);
+ }
+
+ // This type is used to remove the expense of having a managed reference object that is dynamically
+ // created when we can prove that we don't need that object. Use of this type requires code to ensure
+ // that the underlying native resource is not freed.
+ // Cases in which this may be used:
+ // 1. When native code calls managed code passing one of these as a parameter
+ // 2. When managed code acquires one of these from an RtFieldInfo, and ensure that the RtFieldInfo is preserved
+ // across the lifetime of the RuntimeFieldHandleInternal instance
+ // 3. When another object is used to keep the RuntimeFieldHandleInternal alive.
+ // When in doubt, do not use.
+ internal struct RuntimeFieldHandleInternal
+ {
+ internal static RuntimeFieldHandleInternal EmptyHandle
+ {
+ get
+ {
+ return new RuntimeFieldHandleInternal();
+ }
+ }
+
+ internal bool IsNullHandle()
+ {
+ return m_handle.IsNull();
+ }
+
+ internal IntPtr Value
+ {
+ [SecurityCritical]
+ get
+ {
+ return m_handle;
+ }
+ }
+
+ [SecurityCritical]
+ internal RuntimeFieldHandleInternal(IntPtr value)
+ {
+ m_handle = value;
+ }
+
+ internal IntPtr m_handle;
+ }
+
+ internal interface IRuntimeFieldInfo
+ {
+ RuntimeFieldHandleInternal Value
+ {
+ get;
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal class RuntimeFieldInfoStub : IRuntimeFieldInfo
+ {
+ [SecuritySafeCritical]
+ public RuntimeFieldInfoStub(IntPtr methodHandleValue, object keepalive)
+ {
+ m_keepalive = keepalive;
+ m_fieldHandle = new RuntimeFieldHandleInternal(methodHandleValue);
+ }
+
+ // These unused variables are used to ensure that this class has the same layout as RuntimeFieldInfo
+#pragma warning disable 169
+ object m_keepalive;
+ object m_c;
+ object m_d;
+ int m_b;
+ object m_e;
+#if FEATURE_REMOTING
+ object m_f;
+#endif
+ RuntimeFieldHandleInternal m_fieldHandle;
+#pragma warning restore 169
+
+ RuntimeFieldHandleInternal IRuntimeFieldInfo.Value
+ {
+ get
+ {
+ return m_fieldHandle;
+ }
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe struct RuntimeFieldHandle : ISerializable
+ {
+ // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+ internal RuntimeFieldHandle GetNativeHandle()
+ {
+ // Create local copy to avoid a race condition
+ IRuntimeFieldInfo field = m_ptr;
+ if (field == null)
+ throw new ArgumentNullException(null, Environment.GetResourceString("Arg_InvalidHandle"));
+ return new RuntimeFieldHandle(field);
+ }
+
+ private IRuntimeFieldInfo m_ptr;
+
+ internal RuntimeFieldHandle(IRuntimeFieldInfo fieldInfo)
+ {
+ m_ptr = fieldInfo;
+ }
+
+ internal IRuntimeFieldInfo GetRuntimeFieldInfo()
+ {
+ return m_ptr;
+ }
+
+ public IntPtr Value
+ {
+ [SecurityCritical]
+ get
+ {
+ return m_ptr != null ? m_ptr.Value.Value : IntPtr.Zero;
+ }
+ }
+
+ internal bool IsNullHandle()
+ {
+ return m_ptr == null;
+ }
+
+ [SecuritySafeCritical]
+ public override int GetHashCode()
+ {
+ return ValueType.GetHashCodeOfPtr(Value);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical]
+ public override bool Equals(object obj)
+ {
+ if (!(obj is RuntimeFieldHandle))
+ return false;
+
+ RuntimeFieldHandle handle = (RuntimeFieldHandle)obj;
+
+ return handle.Value == Value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical]
+ public unsafe bool Equals(RuntimeFieldHandle handle)
+ {
+ return handle.Value == Value;
+ }
+
+ public static bool operator ==(RuntimeFieldHandle left, RuntimeFieldHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(RuntimeFieldHandle left, RuntimeFieldHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern String GetName(RtFieldInfo field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern unsafe void* _GetUtf8Name(RuntimeFieldHandleInternal field);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static unsafe Utf8String GetUtf8Name(RuntimeFieldHandleInternal field) { return new Utf8String(_GetUtf8Name(field)); }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool MatchesNameHash(RuntimeFieldHandleInternal handle, uint hash);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern FieldAttributes GetAttributes(RuntimeFieldHandleInternal field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeType GetApproxDeclaringType(RuntimeFieldHandleInternal field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeType GetApproxDeclaringType(IRuntimeFieldInfo field)
+ {
+ RuntimeType type = GetApproxDeclaringType(field.Value);
+ GC.KeepAlive(field);
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetToken(RtFieldInfo field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object GetValue(RtFieldInfo field, Object instance, RuntimeType fieldType, RuntimeType declaringType, ref bool domainInitialized);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Object GetValueDirect(RtFieldInfo field, RuntimeType fieldType, void *pTypedRef, RuntimeType contextType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void SetValue(RtFieldInfo field, Object obj, Object value, RuntimeType fieldType, FieldAttributes fieldAttr, RuntimeType declaringType, ref bool domainInitialized);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void SetValueDirect(RtFieldInfo field, RuntimeType fieldType, void* pTypedRef, Object value, RuntimeType contextType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeFieldHandleInternal GetStaticFieldForGenericType(RuntimeFieldHandleInternal field, RuntimeType declaringType);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool AcquiresContextFromThis(RuntimeFieldHandleInternal field);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecurityCritical(RuntimeFieldHandle fieldHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecurityCritical()
+ {
+ return IsSecurityCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecuritySafeCritical(RuntimeFieldHandle fieldHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecuritySafeCritical()
+ {
+ return IsSecuritySafeCritical(GetNativeHandle());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool IsSecurityTransparent(RuntimeFieldHandle fieldHandle);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal bool IsSecurityTransparent()
+ {
+ return IsSecurityTransparent(GetNativeHandle());
+ }
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void CheckAttributeAccess(RuntimeFieldHandle fieldHandle, RuntimeModule decoratedTarget);
+
+ // ISerializable interface
+ [System.Security.SecurityCritical] // auto-generated
+ private RuntimeFieldHandle(SerializationInfo info, StreamingContext context)
+ {
+ if(info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ FieldInfo f =(RuntimeFieldInfo) info.GetValue("FieldObj", typeof(RuntimeFieldInfo));
+
+ if( f == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+
+ m_ptr = f.FieldHandle.m_ptr;
+
+ if (m_ptr == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+
+ [System.Security.SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ if (m_ptr == null)
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidFieldState"));
+
+ RuntimeFieldInfo fldInfo = (RuntimeFieldInfo)RuntimeType.GetFieldInfo(this.GetRuntimeFieldInfo());
+
+ info.AddValue("FieldObj",fldInfo, typeof(RuntimeFieldInfo));
+ }
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public unsafe struct ModuleHandle
+ {
+ // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+#region Public Static Members
+ public static readonly ModuleHandle EmptyHandle = GetEmptyMH();
+#endregion
+
+ unsafe static private ModuleHandle GetEmptyMH()
+ {
+ return new ModuleHandle();
+ }
+
+#region Private Data Members
+ private RuntimeModule m_ptr;
+#endregion
+
+#region Constructor
+ internal ModuleHandle(RuntimeModule module)
+ {
+ m_ptr = module;
+ }
+#endregion
+
+#region Internal FCalls
+
+ internal RuntimeModule GetRuntimeModule()
+ {
+ return m_ptr;
+ }
+
+ internal bool IsNullHandle()
+ {
+ return m_ptr == null;
+ }
+
+ public override int GetHashCode()
+ {
+ return m_ptr != null ? m_ptr.GetHashCode() : 0;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public override bool Equals(object obj)
+ {
+ if (!(obj is ModuleHandle))
+ return false;
+
+ ModuleHandle handle = (ModuleHandle)obj;
+
+ return handle.m_ptr == m_ptr;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public unsafe bool Equals(ModuleHandle handle)
+ {
+ return handle.m_ptr == m_ptr;
+ }
+
+ public static bool operator ==(ModuleHandle left, ModuleHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ public static bool operator !=(ModuleHandle left, ModuleHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern IRuntimeMethodInfo GetDynamicMethod(DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetToken(RuntimeModule module);
+
+ private static void ValidateModulePointer(RuntimeModule module)
+ {
+ // Make sure we have a valid Module to resolve against.
+ if (module == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullModuleHandle"));
+ }
+
+ // SQL-CLR LKG9 Compiler dependency
+ public RuntimeTypeHandle GetRuntimeTypeHandleFromMetadataToken(int typeToken) { return ResolveTypeHandle(typeToken); }
+ public RuntimeTypeHandle ResolveTypeHandle(int typeToken)
+ {
+ return new RuntimeTypeHandle(ResolveTypeHandleInternal(GetRuntimeModule(), typeToken, null, null));
+ }
+ public RuntimeTypeHandle ResolveTypeHandle(int typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ {
+ return new RuntimeTypeHandle(ModuleHandle.ResolveTypeHandleInternal(GetRuntimeModule(), typeToken, typeInstantiationContext, methodInstantiationContext));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType ResolveTypeHandleInternal(RuntimeModule module, int typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ {
+ ValidateModulePointer(module);
+ if (!ModuleHandle.GetMetadataImport(module).IsValidToken(typeToken))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", typeToken, new ModuleHandle(module)));
+
+ int typeInstCount, methodInstCount;
+ IntPtr[] typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out typeInstCount);
+ IntPtr[] methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out methodInstCount);
+
+ fixed (IntPtr* typeInstArgs = typeInstantiationContextHandles, methodInstArgs = methodInstantiationContextHandles)
+ {
+ RuntimeType type = null;
+ ResolveType(module, typeToken, typeInstArgs, typeInstCount, methodInstArgs, methodInstCount, JitHelpers.GetObjectHandleOnStack(ref type));
+ GC.KeepAlive(typeInstantiationContext);
+ GC.KeepAlive(methodInstantiationContext);
+ return type;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void ResolveType(RuntimeModule module,
+ int typeToken,
+ IntPtr* typeInstArgs,
+ int typeInstCount,
+ IntPtr* methodInstArgs,
+ int methodInstCount,
+ ObjectHandleOnStack type);
+
+ // SQL-CLR LKG9 Compiler dependency
+ public RuntimeMethodHandle GetRuntimeMethodHandleFromMetadataToken(int methodToken) { return ResolveMethodHandle(methodToken); }
+ public RuntimeMethodHandle ResolveMethodHandle(int methodToken) { return ResolveMethodHandle(methodToken, null, null); }
+ internal static IRuntimeMethodInfo ResolveMethodHandleInternal(RuntimeModule module, int methodToken) { return ModuleHandle.ResolveMethodHandleInternal(module, methodToken, null, null); }
+ public RuntimeMethodHandle ResolveMethodHandle(int methodToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ {
+ return new RuntimeMethodHandle(ResolveMethodHandleInternal(GetRuntimeModule(), methodToken, typeInstantiationContext, methodInstantiationContext));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IRuntimeMethodInfo ResolveMethodHandleInternal(RuntimeModule module, int methodToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ {
+ int typeInstCount, methodInstCount;
+
+ IntPtr[] typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out typeInstCount);
+ IntPtr[] methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out methodInstCount);
+
+ RuntimeMethodHandleInternal handle = ResolveMethodHandleInternalCore(module, methodToken, typeInstantiationContextHandles, typeInstCount, methodInstantiationContextHandles, methodInstCount);
+ IRuntimeMethodInfo retVal = new RuntimeMethodInfoStub(handle, RuntimeMethodHandle.GetLoaderAllocator(handle));
+ GC.KeepAlive(typeInstantiationContext);
+ GC.KeepAlive(methodInstantiationContext);
+ return retVal;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static RuntimeMethodHandleInternal ResolveMethodHandleInternalCore(RuntimeModule module, int methodToken, IntPtr[] typeInstantiationContext, int typeInstCount, IntPtr[] methodInstantiationContext, int methodInstCount)
+ {
+ ValidateModulePointer(module);
+ if (!ModuleHandle.GetMetadataImport(module.GetNativeHandle()).IsValidToken(methodToken))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", methodToken, new ModuleHandle(module)));
+
+ fixed (IntPtr* typeInstArgs = typeInstantiationContext, methodInstArgs = methodInstantiationContext)
+ {
+ return ResolveMethod(module.GetNativeHandle(), methodToken, typeInstArgs, typeInstCount, methodInstArgs, methodInstCount);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static RuntimeMethodHandleInternal ResolveMethod(RuntimeModule module,
+ int methodToken,
+ IntPtr* typeInstArgs,
+ int typeInstCount,
+ IntPtr* methodInstArgs,
+ int methodInstCount);
+
+ // SQL-CLR LKG9 Compiler dependency
+ public RuntimeFieldHandle GetRuntimeFieldHandleFromMetadataToken(int fieldToken) { return ResolveFieldHandle(fieldToken); }
+ public RuntimeFieldHandle ResolveFieldHandle(int fieldToken) { return new RuntimeFieldHandle(ResolveFieldHandleInternal(GetRuntimeModule(), fieldToken, null, null)); }
+ public RuntimeFieldHandle ResolveFieldHandle(int fieldToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ { return new RuntimeFieldHandle(ResolveFieldHandleInternal(GetRuntimeModule(), fieldToken, typeInstantiationContext, methodInstantiationContext)); }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static IRuntimeFieldInfo ResolveFieldHandleInternal(RuntimeModule module, int fieldToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
+ {
+ ValidateModulePointer(module);
+ if (!ModuleHandle.GetMetadataImport(module.GetNativeHandle()).IsValidToken(fieldToken))
+ throw new ArgumentOutOfRangeException("metadataToken",
+ Environment.GetResourceString("Argument_InvalidToken", fieldToken, new ModuleHandle(module)));
+
+ // defensive copy to be sure array is not mutated from the outside during processing
+ int typeInstCount, methodInstCount;
+ IntPtr [] typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out typeInstCount);
+ IntPtr [] methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out methodInstCount);
+
+ fixed (IntPtr* typeInstArgs = typeInstantiationContextHandles, methodInstArgs = methodInstantiationContextHandles)
+ {
+ IRuntimeFieldInfo field = null;
+ ResolveField(module.GetNativeHandle(), fieldToken, typeInstArgs, typeInstCount, methodInstArgs, methodInstCount, JitHelpers.GetObjectHandleOnStack(ref field));
+ GC.KeepAlive(typeInstantiationContext);
+ GC.KeepAlive(methodInstantiationContext);
+ return field;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void ResolveField(RuntimeModule module,
+ int fieldToken,
+ IntPtr* typeInstArgs,
+ int typeInstCount,
+ IntPtr* methodInstArgs,
+ int methodInstCount,
+ ObjectHandleOnStack retField);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static bool _ContainsPropertyMatchingHash(RuntimeModule module, int propertyToken, uint hash);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool ContainsPropertyMatchingHash(RuntimeModule module, int propertyToken, uint hash)
+ {
+ return _ContainsPropertyMatchingHash(module.GetNativeHandle(), propertyToken, hash);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetAssembly(RuntimeModule handle, ObjectHandleOnStack retAssembly);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeAssembly GetAssembly(RuntimeModule module)
+ {
+ RuntimeAssembly retAssembly = null;
+ GetAssembly(module.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref retAssembly));
+ return retAssembly;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal extern static void GetModuleType(RuntimeModule handle, ObjectHandleOnStack type);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static RuntimeType GetModuleType(RuntimeModule module)
+ {
+ RuntimeType type = null;
+ GetModuleType(module.GetNativeHandle(), JitHelpers.GetObjectHandleOnStack(ref type));
+ return type;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static void GetPEKind(RuntimeModule handle, out int peKind, out int machine);
+
+ // making this internal, used by Module.GetPEKind
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void GetPEKind(RuntimeModule module, out PortableExecutableKinds peKind, out ImageFileMachine machine)
+ {
+ int lKind, lMachine;
+ GetPEKind(module.GetNativeHandle(), out lKind, out lMachine);
+ peKind = (PortableExecutableKinds)lKind;
+ machine = (ImageFileMachine)lMachine;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static int GetMDStreamVersion(RuntimeModule module);
+
+ public int MDStreamVersion
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return GetMDStreamVersion(GetRuntimeModule().GetNativeHandle()); }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern static IntPtr _GetMetadataImport(RuntimeModule module);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static MetadataImport GetMetadataImport(RuntimeModule module)
+ {
+ return new MetadataImport(_GetMetadataImport(module.GetNativeHandle()), module);
+ }
+#endregion
+ }
+
+ internal unsafe class Signature
+ {
+#region Definitions
+ internal enum MdSigCallingConvention : byte
+ {
+ Generics = 0x10,
+ HasThis = 0x20,
+ ExplicitThis = 0x40,
+ CallConvMask = 0x0F,
+ Default = 0x00,
+ C = 0x01,
+ StdCall = 0x02,
+ ThisCall = 0x03,
+ FastCall = 0x04,
+ Vararg = 0x05,
+ Field = 0x06,
+ LocalSig = 0x07,
+ Property = 0x08,
+ Unmgd = 0x09,
+ GenericInst = 0x0A,
+ Max = 0x0B,
+ }
+#endregion
+
+#region FCalls
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void GetSignature(
+ void* pCorSig, int cCorSig,
+ RuntimeFieldHandleInternal fieldHandle, IRuntimeMethodInfo methodHandle, RuntimeType declaringType);
+
+#endregion
+
+#region Private Data Members
+ //
+ // Keep the layout in sync with SignatureNative in the VM
+ //
+ internal RuntimeType[] m_arguments;
+ internal RuntimeType m_declaringType;
+ internal RuntimeType m_returnTypeORfieldType;
+ internal object m_keepalive;
+ [SecurityCritical]
+ internal void* m_sig;
+ internal int m_managedCallingConventionAndArgIteratorFlags; // lowest byte is CallingConvention, upper 3 bytes are ArgIterator flags
+ internal int m_nSizeOfArgStack;
+ internal int m_csig;
+ internal RuntimeMethodHandleInternal m_pMethod;
+#endregion
+
+#region Constructors
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Signature (
+ IRuntimeMethodInfo method,
+ RuntimeType[] arguments,
+ RuntimeType returnType,
+ CallingConventions callingConvention)
+ {
+ m_pMethod = method.Value;
+ m_arguments = arguments;
+ m_returnTypeORfieldType = returnType;
+ m_managedCallingConventionAndArgIteratorFlags = (byte)callingConvention;
+
+ GetSignature(null, 0, new RuntimeFieldHandleInternal(), method, null);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Signature(IRuntimeMethodInfo methodHandle, RuntimeType declaringType)
+ {
+ GetSignature(null, 0, new RuntimeFieldHandleInternal(), methodHandle, declaringType);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Signature(IRuntimeFieldInfo fieldHandle, RuntimeType declaringType)
+ {
+ GetSignature(null, 0, fieldHandle.Value, null, declaringType);
+ GC.KeepAlive(fieldHandle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Signature(void* pCorSig, int cCorSig, RuntimeType declaringType)
+ {
+ GetSignature(pCorSig, cCorSig, new RuntimeFieldHandleInternal(), null, declaringType);
+ }
+#endregion
+
+#region Internal Members
+ internal CallingConventions CallingConvention { get { return (CallingConventions)(byte)m_managedCallingConventionAndArgIteratorFlags; } }
+ internal RuntimeType[] Arguments { get { return m_arguments; } }
+ internal RuntimeType ReturnType { get { return m_returnTypeORfieldType; } }
+ internal RuntimeType FieldType { get { return m_returnTypeORfieldType; } }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool CompareSig(Signature sig1, Signature sig2);
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern Type[] GetCustomModifiers(int position, bool required);
+#endregion
+ }
+
+
+ internal abstract class Resolver
+ {
+ internal struct CORINFO_EH_CLAUSE
+ {
+ internal int Flags;
+ internal int TryOffset;
+ internal int TryLength;
+ internal int HandlerOffset;
+ internal int HandlerLength;
+ internal int ClassTokenOrFilterOffset;
+ }
+
+ // ILHeader info
+ internal abstract RuntimeType GetJitContext(ref int securityControlFlags);
+ internal abstract byte[] GetCodeInfo(ref int stackSize, ref int initLocals, ref int EHCount);
+ internal abstract byte[] GetLocalsSignature();
+ [System.Security.SecurityCritical] // takes a pointer parameter
+ internal abstract unsafe void GetEHInfo(int EHNumber, void* exception);
+ internal abstract unsafe byte[] GetRawEHInfo();
+ // token resolution
+ internal abstract String GetStringLiteral(int token);
+ [System.Security.SecurityCritical] // passes a pointer out
+ internal abstract void ResolveToken(int token, out IntPtr typeHandle, out IntPtr methodHandle, out IntPtr fieldHandle);
+ internal abstract byte[] ResolveSignature(int token, int fromMethod);
+ //
+ internal abstract MethodInfo GetDynamicMethod();
+#if FEATURE_COMPRESSEDSTACK
+ internal abstract CompressedStack GetSecurityContext();
+#endif
+ }
+
+}
diff --git a/src/mscorlib/src/System/SByte.cs b/src/mscorlib/src/System/SByte.cs
new file mode 100644
index 0000000000..a9ec9cf298
--- /dev/null
+++ b/src/mscorlib/src/System/SByte.cs
@@ -0,0 +1,274 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+namespace System {
+ using System.Globalization;
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // A place holder class for signed bytes.
+[Serializable]
+[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct SByte : IComparable, IFormattable, IConvertible
+ , IComparable<SByte>, IEquatable<SByte>
+ {
+ private sbyte m_value;
+
+ // The maximum value that a Byte may represent: 127.
+ public const sbyte MaxValue = (sbyte)0x7F;
+
+ // The minimum value that a Byte may represent: -128.
+ public const sbyte MinValue = unchecked((sbyte)0x80);
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type SByte, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object obj) {
+ if (obj == null) {
+ return 1;
+ }
+ if (!(obj is SByte)) {
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeSByte"));
+ }
+ return m_value - ((SByte)obj).m_value;
+ }
+
+ public int CompareTo(SByte value) {
+ return m_value - value;
+ }
+
+ // Determines whether two Byte objects are equal.
+ public override bool Equals(Object obj) {
+ if (!(obj is SByte)) {
+ return false;
+ }
+ return m_value == ((SByte)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(SByte obj)
+ {
+ return m_value == obj;
+ }
+
+ // Gets a hash code for this instance.
+ public override int GetHashCode() {
+ return ((int)m_value ^ (int)m_value << 8);
+ }
+
+
+ // Provides a string representation of a byte.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.CurrentInfo);
+ }
+
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return ToString(format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String ToString(String format, NumberFormatInfo info) {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ if (m_value<0 && format!=null && format.Length>0 && (format[0]=='X' || format[0]=='x')) {
+ uint temp = (uint)(m_value & 0x000000FF);
+ return Number.FormatUInt32(temp, format, info);
+ }
+ return Number.FormatInt32(m_value, format, info);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a signed byte from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ [CLSCompliant(false)]
+ public static sbyte Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static sbyte Parse(String s, NumberStyles style, NumberFormatInfo info) {
+
+ int i = 0;
+ try {
+ i = Number.ParseInt32(s, style, info);
+ }
+ catch(OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_SByte"), e);
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // We are parsing a hexadecimal number
+ if ((i < 0) || i > Byte.MaxValue) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_SByte"));
+ }
+ return (sbyte)i;
+ }
+
+ if (i < MinValue || i > MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_SByte"));
+ return (sbyte)i;
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out SByte result) {
+ return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out SByte result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out SByte result) {
+
+ result = 0;
+ int i;
+ if (!Number.TryParseInt32(s, style, info, out i)) {
+ return false;
+ }
+
+ if ((style & NumberStyles.AllowHexSpecifier) != 0) { // We are parsing a hexadecimal number
+ if ((i < 0) || i > Byte.MaxValue) {
+ return false;
+ }
+ result = (sbyte)i;
+ return true;
+ }
+
+ if (i < MinValue || i > MaxValue) {
+ return false;
+ }
+ result = (sbyte) i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.SByte;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "SByte", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/AccessControl/Enums.cs b/src/mscorlib/src/System/Security/AccessControl/Enums.cs
new file mode 100644
index 0000000000..c52176a29b
--- /dev/null
+++ b/src/mscorlib/src/System/Security/AccessControl/Enums.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Security.AccessControl
+{
+ [Flags]
+ public enum InheritanceFlags
+ {
+ None = 0x00,
+ ContainerInherit = 0x01,
+ ObjectInherit = 0x02,
+ }
+
+ [Flags]
+ public enum PropagationFlags
+ {
+ None = 0x00,
+ NoPropagateInherit = 0x01,
+ InheritOnly = 0x02,
+ }
+
+ [Flags]
+ public enum AuditFlags
+ {
+ None = 0x00,
+ Success = 0x01,
+ Failure = 0x02,
+ }
+
+ [Flags]
+ public enum SecurityInfos
+ {
+ Owner = 0x00000001,
+ Group = 0x00000002,
+ DiscretionaryAcl = 0x00000004,
+ SystemAcl = 0x00000008,
+
+ }
+
+
+ public enum ResourceType
+ {
+ Unknown = 0x00,
+ FileObject = 0x01,
+ Service = 0x02,
+ Printer = 0x03,
+ RegistryKey = 0x04,
+ LMShare = 0x05,
+ KernelObject = 0x06,
+ WindowObject = 0x07,
+ DSObject = 0x08,
+ DSObjectAll = 0x09,
+ ProviderDefined = 0x0A,
+ WmiGuidObject = 0x0B,
+ RegistryWow6432Key = 0x0C,
+ }
+
+ [Flags]
+ public enum AccessControlSections {
+ None = 0,
+ Audit = 0x1,
+ Access = 0x2,
+ Owner = 0x4,
+ Group = 0x8,
+ All = 0xF
+ }
+
+ [Flags]
+ public enum AccessControlActions {
+#if FEATURE_MACL
+ None = 0,
+ View = 1,
+ Change = 2
+#else
+ None = 0
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Attributes.cs b/src/mscorlib/src/System/Security/Attributes.cs
new file mode 100644
index 0000000000..d2229227a5
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Attributes.cs
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System.Security
+{
+ // DynamicSecurityMethodAttribute:
+ // Indicates that calling the target method requires space for a security
+ // object to be allocated on the callers stack. This attribute is only ever
+ // set on certain security methods defined within mscorlib.
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false )]
+ sealed internal class DynamicSecurityMethodAttribute : System.Attribute
+ {
+ }
+
+ // SuppressUnmanagedCodeSecurityAttribute:
+ // Indicates that the target P/Invoke method(s) should skip the per-call
+ // security checked for unmanaged code permission.
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false )]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class SuppressUnmanagedCodeSecurityAttribute : System.Attribute
+ {
+ }
+
+ // UnverifiableCodeAttribute:
+ // Indicates that the target module contains unverifiable code.
+ [AttributeUsage(AttributeTargets.Module, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class UnverifiableCodeAttribute : System.Attribute
+ {
+ }
+
+ // AllowPartiallyTrustedCallersAttribute:
+ // Indicates that the Assembly is secure and can be used by untrusted
+ // and semitrusted clients
+ // For v.1, this is valid only on Assemblies, but could be expanded to
+ // include Module, Method, class
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false )]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class AllowPartiallyTrustedCallersAttribute : System.Attribute
+ {
+ private PartialTrustVisibilityLevel _visibilityLevel;
+ public AllowPartiallyTrustedCallersAttribute () { }
+
+ public PartialTrustVisibilityLevel PartialTrustVisibilityLevel
+ {
+ get { return _visibilityLevel; }
+ set { _visibilityLevel = value; }
+ }
+ }
+
+ public enum PartialTrustVisibilityLevel
+ {
+ VisibleToAllHosts = 0,
+ NotVisibleByDefault = 1
+ }
+
+#if !FEATURE_CORECLR
+ [Obsolete("SecurityCriticalScope is only used for .NET 2.0 transparency compatibility.")]
+ public enum SecurityCriticalScope
+ {
+ Explicit = 0,
+ Everything = 0x1
+ }
+#endif // FEATURE_CORECLR
+
+ // SecurityCriticalAttribute
+ // Indicates that the decorated code or assembly performs security critical operations (e.g. Assert, "unsafe", LinkDemand, etc.)
+ // The attribute can be placed on most targets, except on arguments/return values.
+ [AttributeUsage(AttributeTargets.Assembly |
+ AttributeTargets.Class |
+ AttributeTargets.Struct |
+ AttributeTargets.Enum |
+ AttributeTargets.Constructor |
+ AttributeTargets.Method |
+ AttributeTargets.Field |
+ AttributeTargets.Interface |
+ AttributeTargets.Delegate,
+ AllowMultiple = false,
+ Inherited = false )]
+ sealed public class SecurityCriticalAttribute : System.Attribute
+ {
+#pragma warning disable 618 // We still use SecurityCriticalScope for v2 compat
+
+#if !FEATURE_CORECLR
+ private SecurityCriticalScope _val;
+#endif // FEATURE_CORECLR
+ public SecurityCriticalAttribute () {}
+
+#if !FEATURE_CORECLR
+ public SecurityCriticalAttribute(SecurityCriticalScope scope)
+ {
+ _val = scope;
+ }
+
+ [Obsolete("SecurityCriticalScope is only used for .NET 2.0 transparency compatibility.")]
+ public SecurityCriticalScope Scope {
+ get {
+ return _val;
+ }
+ }
+#endif // FEATURE_CORECLR
+
+#pragma warning restore 618
+ }
+
+ // SecurityTreatAsSafeAttribute:
+ // Indicates that the code may contain violations to the security critical rules (e.g. transitions from
+ // critical to non-public transparent, transparent to non-public critical, etc.), has been audited for
+ // security concerns and is considered security clean.
+ // At assembly-scope, all rule checks will be suppressed within the assembly and for calls made against the assembly.
+ // At type-scope, all rule checks will be suppressed for members within the type and for calls made against the type.
+ // At member level (e.g. field and method) the code will be treated as public - i.e. no rule checks for the members.
+
+ [AttributeUsage(AttributeTargets.Assembly |
+ AttributeTargets.Class |
+ AttributeTargets.Struct |
+ AttributeTargets.Enum |
+ AttributeTargets.Constructor |
+ AttributeTargets.Method |
+ AttributeTargets.Field |
+ AttributeTargets.Interface |
+ AttributeTargets.Delegate,
+ AllowMultiple = false,
+ Inherited = false )]
+ [Obsolete("SecurityTreatAsSafe is only used for .NET 2.0 transparency compatibility. Please use the SecuritySafeCriticalAttribute instead.")]
+ sealed public class SecurityTreatAsSafeAttribute : System.Attribute
+ {
+ public SecurityTreatAsSafeAttribute () { }
+ }
+
+ // SecuritySafeCriticalAttribute:
+ // Indicates that the code may contain violations to the security critical rules (e.g. transitions from
+ // critical to non-public transparent, transparent to non-public critical, etc.), has been audited for
+ // security concerns and is considered security clean. Also indicates that the code is considered SecurityCritical.
+ // The effect of this attribute is as if the code was marked [SecurityCritical][SecurityTreatAsSafe].
+ // At assembly-scope, all rule checks will be suppressed within the assembly and for calls made against the assembly.
+ // At type-scope, all rule checks will be suppressed for members within the type and for calls made against the type.
+ // At member level (e.g. field and method) the code will be treated as public - i.e. no rule checks for the members.
+
+ [AttributeUsage(AttributeTargets.Class |
+ AttributeTargets.Struct |
+ AttributeTargets.Enum |
+ AttributeTargets.Constructor |
+ AttributeTargets.Method |
+ AttributeTargets.Field |
+ AttributeTargets.Interface |
+ AttributeTargets.Delegate,
+ AllowMultiple = false,
+ Inherited = false )]
+ sealed public class SecuritySafeCriticalAttribute : System.Attribute
+ {
+ public SecuritySafeCriticalAttribute () { }
+ }
+
+ // SecurityTransparentAttribute:
+ // Indicates the assembly contains only transparent code.
+ // Security critical actions will be restricted or converted into less critical actions. For example,
+ // Assert will be restricted, SuppressUnmanagedCode, LinkDemand, unsafe, and unverifiable code will be converted
+ // into Full-Demands.
+
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false )]
+ sealed public class SecurityTransparentAttribute : System.Attribute
+ {
+ public SecurityTransparentAttribute () {}
+ }
+
+#if !FEATURE_CORECLR
+ public enum SecurityRuleSet : byte
+ {
+ None = 0,
+ Level1 = 1, // v2.0 transparency model
+ Level2 = 2, // v4.0 transparency model
+ }
+
+ // SecurityRulesAttribute
+ //
+ // Indicates which set of security rules an assembly was authored against, and therefore which set of
+ // rules the runtime should enforce on the assembly. For instance, an assembly marked with
+ // [SecurityRules(SecurityRuleSet.Level1)] will follow the v2.0 transparency rules, where transparent code
+ // can call a LinkDemand by converting it to a full demand, public critical methods are implicitly
+ // treat as safe, and the remainder of the v2.0 rules apply.
+ [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
+ public sealed class SecurityRulesAttribute : Attribute
+ {
+ private SecurityRuleSet m_ruleSet;
+ private bool m_skipVerificationInFullTrust = false;
+
+ public SecurityRulesAttribute(SecurityRuleSet ruleSet)
+ {
+ m_ruleSet = ruleSet;
+ }
+
+ // Should fully trusted transparent code skip IL verification
+ public bool SkipVerificationInFullTrust
+ {
+ get { return m_skipVerificationInFullTrust; }
+ set { m_skipVerificationInFullTrust = value; }
+ }
+
+ public SecurityRuleSet RuleSet
+ {
+ get { return m_ruleSet; }
+ }
+ }
+#endif // !FEATURE_CORECLR
+}
diff --git a/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs b/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs
new file mode 100644
index 0000000000..e29dec3b06
--- /dev/null
+++ b/src/mscorlib/src/System/Security/BuiltInPermissionSets.cs
@@ -0,0 +1,342 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Security.Permissions;
+using Microsoft.Win32;
+
+namespace System.Security
+{
+ internal static class BuiltInPermissionSets
+ {
+ //
+ // Raw PermissionSet XML - the built in permission sets are expressed in XML form since they contain
+ // permissions from assemblies other than mscorlib.
+ //
+
+ private static readonly string s_everythingXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""Everything""
+ Description = """ + Environment.GetResourceString("Policy_PS_Everything") + @"""
+ <IPermission class = ""System.Data.OleDb.OleDbPermission, " + AssemblyRef.SystemData + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Data.SqlClient.SqlClientPermission, " + AssemblyRef.SystemData + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Diagnostics.PerformanceCounterPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Net.DnsPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Net.SocketPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Net.WebPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.DataProtectionPermission, " + AssemblyRef.SystemSecurity + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.EnvironmentPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Diagnostics.EventLogPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.FileDialogPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.FileIOPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.IsolatedStorageFilePermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.KeyContainerPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Drawing.Printing.PrintingPermission, " + AssemblyRef.SystemDrawing + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.ReflectionPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.RegistryPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.SecurityPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""Assertion, UnmanagedCode, Execution, ControlThread, ControlEvidence, ControlPolicy, ControlAppDomain, SerializationFormatter, ControlDomainPolicy, ControlPrincipal, RemotingConfiguration, Infrastructure, BindingRedirects"" />
+ <IPermission class = ""System.Security.Permissions.UIPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.StorePermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.TypeDescriptorPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ </PermissionSet>";
+
+ private static readonly string s_executionXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""Execution""
+ Description = """ + Environment.GetResourceString("Policy_PS_Execution") + @""">
+ <IPermission class = ""System.Security.Permissions.SecurityPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""Execution"" />
+ </PermissionSet>";
+
+ private static readonly string s_fullTrustXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Unrestricted = ""true""
+ Name = ""FullTrust""
+ Description = """ + Environment.GetResourceString("Policy_PS_FullTrust") + @""" />";
+
+ private static readonly string s_internetXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""Internet""
+ Description = """ + Environment.GetResourceString("Policy_PS_Internet") + @""">
+ <IPermission class = ""System.Drawing.Printing.PrintingPermission, " + AssemblyRef.SystemDrawing + @"""
+ version = ""1""
+ Level = ""SafePrinting"" />
+ <IPermission class = ""System.Security.Permissions.FileDialogPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Access = ""Open"" />
+ <IPermission class = ""System.Security.Permissions.IsolatedStorageFilePermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ UserQuota = ""1024000""
+ Allowed = ""ApplicationIsolationByUser"" />
+ <IPermission class = ""System.Security.Permissions.SecurityPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""Execution"" />
+ <IPermission class = ""System.Security.Permissions.UIPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Window = ""SafeTopLevelWindows""
+ Clipboard = ""OwnClipboard"" />
+ </PermissionSet>";
+
+ private static readonly string s_localIntranetXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""LocalIntranet""
+ Description = """ + Environment.GetResourceString("Policy_PS_LocalIntranet") + @""" >
+ <IPermission class = ""System.Drawing.Printing.PrintingPermission, " + AssemblyRef.SystemDrawing + @"""
+ version = ""1""
+ Level = ""DefaultPrinting"" />
+ <IPermission class = ""System.Net.DnsPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.EnvironmentPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Read = ""USERNAME"" />
+ <IPermission class = ""System.Security.Permissions.FileDialogPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.IsolatedStorageFilePermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Allowed = ""AssemblyIsolationByUser""
+ UserQuota = ""9223372036854775807""
+ Expiry = ""9223372036854775807""
+ Permanent = ""true"" />
+ <IPermission class = ""System.Security.Permissions.ReflectionPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""ReflectionEmit, RestrictedMemberAccess"" />
+ <IPermission class = ""System.Security.Permissions.SecurityPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""Execution, Assertion, BindingRedirects "" />
+ <IPermission class = ""System.Security.Permissions.TypeDescriptorPermission, " + AssemblyRef.System + @"""
+ version = ""1""
+ Flags = ""RestrictedRegistrationAccess"" />
+ <IPermission class = ""System.Security.Permissions.UIPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ </PermissionSet>";
+
+ private static readonly string s_nothingXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""Nothing""
+ Description = """ + Environment.GetResourceString("Policy_PS_Nothing") + @""" />";
+
+ private static readonly string s_skipVerificationXml =
+ @"<PermissionSet class = ""System.Security.NamedPermissionSet""
+ version = ""1""
+ Name = ""SkipVerification""
+ Description = """ + Environment.GetResourceString("Policy_PS_SkipVerification") + @""">
+ <IPermission class = ""System.Security.Permissions.SecurityPermission, " + AssemblyRef.Mscorlib + @"""
+ version = ""1""
+ Flags = ""SkipVerification"" />
+ </PermissionSet>";
+
+#if FEATURE_CAS_POLICY
+ private const string s_wpfExtensionXml =
+ @"<PermissionSet class = ""System.Security.PermissionSet""
+ version = ""1"">
+ <IPermission class = ""System.Security.Permissions.MediaPermission, " + AssemblyRef.WindowsBase + @"""
+ version = ""1""
+ Audio=""SafeAudio"" Video=""SafeVideo"" Image=""SafeImage"" />
+ <IPermission class = ""System.Security.Permissions.WebBrowserPermission, " + AssemblyRef.WindowsBase + @"""
+ version = ""1""
+ Level=""Safe"" />
+ </PermissionSet>";
+
+ private const string s_wpfExtensionUnrestrictedXml =
+ @"<PermissionSet class = ""System.Security.PermissionSet""
+ version = ""1"">
+ <IPermission class = ""System.Security.Permissions.MediaPermission, " + AssemblyRef.WindowsBase + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ <IPermission class = ""System.Security.Permissions.WebBrowserPermission, " + AssemblyRef.WindowsBase + @"""
+ version = ""1""
+ Unrestricted = ""true"" />
+ </PermissionSet>";
+#endif //FEATURE_CAS_POLICY
+
+ //
+ // Built in permission set objects
+ //
+
+ private static NamedPermissionSet s_everything;
+ private static NamedPermissionSet s_execution;
+ private static NamedPermissionSet s_fullTrust;
+ private static NamedPermissionSet s_internet;
+ private static NamedPermissionSet s_localIntranet;
+ private static NamedPermissionSet s_nothing;
+ private static NamedPermissionSet s_skipVerification;
+
+ //
+ // Standard permission sets
+ //
+
+ internal static NamedPermissionSet Everything
+ {
+ get { return GetOrDeserializeExtendablePermissionSet(ref s_everything, s_everythingXml
+#if FEATURE_CAS_POLICY
+ , s_wpfExtensionUnrestrictedXml
+#endif // FEATURE_CAS_POLICY
+ ); }
+ }
+
+ internal static NamedPermissionSet Execution
+ {
+ get { return GetOrDeserializePermissionSet(ref s_execution, s_executionXml); }
+ }
+
+ internal static NamedPermissionSet FullTrust
+ {
+ get { return GetOrDeserializePermissionSet(ref s_fullTrust, s_fullTrustXml); }
+ }
+
+ internal static NamedPermissionSet Internet
+ {
+ get { return GetOrDeserializeExtendablePermissionSet(ref s_internet, s_internetXml
+#if FEATURE_CAS_POLICY
+ , s_wpfExtensionXml
+#endif // FEATURE_CAS_POLICY
+ ); }
+ }
+
+ internal static NamedPermissionSet LocalIntranet
+ {
+ get { return GetOrDeserializeExtendablePermissionSet(ref s_localIntranet, s_localIntranetXml
+#if FEATURE_CAS_POLICY
+ , s_wpfExtensionXml
+#endif // FEATURE_CAS_POLICY
+ ); }
+ }
+
+ internal static NamedPermissionSet Nothing
+ {
+ get { return GetOrDeserializePermissionSet(ref s_nothing, s_nothingXml); }
+ }
+
+ internal static NamedPermissionSet SkipVerification
+ {
+ get { return GetOrDeserializePermissionSet(ref s_skipVerification, s_skipVerificationXml); }
+ }
+
+ //
+ // Utility methods to construct the permission set objects from the well known XML and any permission
+ // set extensions if necessary
+ //
+
+ private static NamedPermissionSet GetOrDeserializeExtendablePermissionSet(ref NamedPermissionSet permissionSet,
+ string permissionSetXml
+#if FEATURE_CAS_POLICY
+ ,string extensionXml
+#endif // FEATURE_CAS_POLICY
+ )
+ {
+ Contract.Requires(!String.IsNullOrEmpty(permissionSetXml));
+#if FEATURE_CAS_POLICY
+ Contract.Requires(!String.IsNullOrEmpty(extensionXml));
+#endif // FEATURE_CAS_POLICY
+
+ if (permissionSet == null)
+ {
+#if FEATURE_CAS_POLICY
+ SecurityElement securityElement = SecurityElement.FromString(permissionSetXml);
+ NamedPermissionSet deserializedPermissionSet = new NamedPermissionSet(securityElement);
+
+ PermissionSet extensions = GetPermissionSetExtensions(extensionXml);
+ deserializedPermissionSet.InplaceUnion(extensions);
+
+ permissionSet = deserializedPermissionSet;
+#endif // FEATURE_CAS_POLICY
+ }
+
+ return permissionSet.Copy() as NamedPermissionSet;
+ }
+
+ private static NamedPermissionSet GetOrDeserializePermissionSet(ref NamedPermissionSet permissionSet,
+ string permissionSetXml)
+ {
+ Contract.Assert(!String.IsNullOrEmpty(permissionSetXml));
+
+#if FEATURE_CAS_POLICY
+ if (permissionSet == null)
+ {
+ SecurityElement securityElement = SecurityElement.FromString(permissionSetXml);
+ NamedPermissionSet deserializedPermissionSet = new NamedPermissionSet(securityElement);
+
+ permissionSet = deserializedPermissionSet;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ return permissionSet.Copy() as NamedPermissionSet;
+ }
+
+#if FEATURE_CAS_POLICY
+ private static PermissionSet GetPermissionSetExtensions(string extensionXml)
+ {
+ Contract.Requires(!String.IsNullOrEmpty(extensionXml));
+
+ SecurityElement se = SecurityElement.FromString(extensionXml);
+
+ // Return the permission set extension only if WPF is in the present framework profile.
+ // XMLUtil.GetClassFromElement() helps do the quickest check, with no exception thrown and
+ // minimal parsing.
+ SecurityElement firstPermission = (SecurityElement)se.Children[0];
+ if (System.Security.Util.XMLUtil.GetClassFromElement(firstPermission, /*ignoreTypeLoadFailures*/true) != null)
+ {
+ PermissionSet extensions = new NamedPermissionSet(se);
+ return extensions;
+ }
+
+ return null;
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+}
diff --git a/src/mscorlib/src/System/Security/CodeAccessPermission.cs b/src/mscorlib/src/System/Security/CodeAccessPermission.cs
new file mode 100644
index 0000000000..61334c22bd
--- /dev/null
+++ b/src/mscorlib/src/System/Security/CodeAccessPermission.cs
@@ -0,0 +1,284 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security
+{
+ using System.IO;
+ using System.Threading;
+ using System.Security;
+ using System.Security.Util;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Collections;
+ using System.Text;
+ using System;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using IUnrestrictedPermission = System.Security.Permissions.IUnrestrictedPermission;
+
+ [Serializable]
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute( SecurityAction.InheritanceDemand, ControlEvidence = true, ControlPolicy = true )]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ abstract public class CodeAccessPermission
+ : IPermission, ISecurityEncodable, IStackWalk
+ {
+ // Static methods for manipulation of stack
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static void RevertAssert()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.RevertAssert(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static void RevertDeny()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.RevertDeny(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static void RevertPermitOnly()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.RevertPermitOnly(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static void RevertAll()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.RevertAll(ref stackMark);
+ }
+
+ //
+ // Standard implementation of IPermission methods for
+ // code-access permissions.
+ //
+
+ // Mark this method as requiring a security object on the caller's frame
+ // so the caller won't be inlined (which would mess up stack crawling).
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Demand()
+ {
+ if (!this.CheckDemand( null ))
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
+ CodeAccessSecurityEngine.Check(this, ref stackMark);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static void Demand(PermissionType permissionType)
+ {
+ // The intent of the method is to be an internal mscorlib helper that Demands a specific permissiontype
+ // without having to create objects.
+ // The security annotation fxcop rule that flags all methods with a Demand() has logic
+ // which checks for methods named Demand in types that implement IPermission or IStackWalk.
+ Contract.Assert(new StackFrame().GetMethod().Name.Equals("Demand"), "This method needs to be named Demand");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
+ CodeAccessSecurityEngine.SpecialDemand(permissionType, ref stackMark);
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Assert()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ CodeAccessSecurityEngine.Assert(this, ref stackMark);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static internal void Assert(bool allPossible)
+ {
+ // The intent of the method is to be an internal mscorlib helper that easily asserts for all possible permissions
+ // without having to new a PermissionSet.
+ // The security annotation fxcop rule that flags all methods with an Assert() has logic
+ // which checks for methods named Assert in types that implement IPermission or IStackWalk.
+ Contract.Assert(new StackFrame().GetMethod().Name.Equals("Assert"), "This method needs to be named Assert");
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.AssertAllPossible(ref stackMark);
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public void Deny()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ CodeAccessSecurityEngine.Deny(this, ref stackMark);
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void PermitOnly()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ CodeAccessSecurityEngine.PermitOnly(this, ref stackMark);
+ }
+
+ // IPermission interfaces
+
+ // We provide a default implementation of Union here.
+ // Any permission that doesn't provide its own representation
+ // of Union will get this one and trigger CompoundPermission
+ // We can take care of simple cases here...
+
+ public virtual IPermission Union(IPermission other) {
+ // The other guy could be null
+ if (other == null) return(this.Copy());
+
+ // otherwise we don't support it.
+ throw new NotSupportedException(Environment.GetResourceString( "NotSupported_SecurityPermissionUnion" ));
+ }
+
+#if FEATURE_CAS_POLICY
+ static internal SecurityElement CreatePermissionElement( IPermission perm, String permname )
+ {
+ SecurityElement root = new SecurityElement( "IPermission" );
+ XMLUtil.AddClassAttribute( root, perm.GetType(), permname );
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( perm.GetType().FullName.Equals( permname ), "Incorrect class name passed in! Was: " + permname + " Should be " + perm.GetType().FullName);
+
+ root.AddAttribute( "version", "1" );
+ return root;
+ }
+
+ static internal void ValidateElement( SecurityElement elem, IPermission perm )
+ {
+ if (elem == null)
+ throw new ArgumentNullException( "elem" );
+ Contract.EndContractBlock();
+
+ if (!XMLUtil.IsPermissionElement( perm, elem ))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_NotAPermissionElement"));
+
+ String version = elem.Attribute( "version" );
+
+ if (version != null && !version.Equals( "1" ))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXMLBadVersion") );
+ }
+
+ abstract public SecurityElement ToXml();
+ abstract public void FromXml( SecurityElement elem );
+
+ //
+ // Unimplemented interface methods
+ // (as a reminder only)
+ //
+
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ //
+ // HELPERS FOR IMPLEMENTING ABSTRACT METHODS
+ //
+
+ //
+ // Protected helper
+ //
+
+ internal bool VerifyType(IPermission perm)
+ {
+ // if perm is null, then obviously not of the same type
+ if ((perm == null) || (perm.GetType() != this.GetType())) {
+ return(false);
+ } else {
+ return(true);
+ }
+ }
+
+ // The IPermission Interface
+ public abstract IPermission Copy();
+ public abstract IPermission Intersect(IPermission target);
+ public abstract bool IsSubsetOf(IPermission target);
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals(Object obj)
+ {
+ IPermission perm = obj as IPermission;
+ if(obj != null && perm == null)
+ return false;
+ try {
+ if(!this.IsSubsetOf(perm))
+ return false;
+ if(perm != null && !perm.IsSubsetOf(this))
+ return false;
+ }
+ catch (ArgumentException)
+ {
+ // Any argument exception implies inequality
+ // Note that we require a try/catch block here because we have to deal with
+ // custom permissions that may throw exceptions indiscriminately.
+ return false;
+ }
+ return true;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ // This implementation is only to silence a compiler warning.
+ return base.GetHashCode();
+ }
+
+
+ internal bool CheckDemand(CodeAccessPermission grant)
+ {
+ Contract.Assert( grant == null || grant.GetType().Equals( this.GetType() ), "CheckDemand not defined for permissions of different type" );
+ return IsSubsetOf( grant );
+ }
+
+ internal bool CheckPermitOnly(CodeAccessPermission permitted)
+ {
+ Contract.Assert( permitted == null || permitted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" );
+ return IsSubsetOf( permitted );
+ }
+
+ internal bool CheckDeny(CodeAccessPermission denied)
+ {
+ Contract.Assert( denied == null || denied.GetType().Equals( this.GetType() ), "CheckDeny not defined for permissions of different type" );
+ IPermission intersectPerm = Intersect(denied);
+ return (intersectPerm == null || intersectPerm.IsSubsetOf(null));
+ }
+
+ internal bool CheckAssert(CodeAccessPermission asserted)
+ {
+ Contract.Assert( asserted == null || asserted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" );
+ return IsSubsetOf( asserted );
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs b/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs
new file mode 100644
index 0000000000..2a1cf9a0ea
--- /dev/null
+++ b/src/mscorlib/src/System/Security/CodeAccessSecurityEngine.cs
@@ -0,0 +1,842 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security {
+ using System;
+ using System.Threading;
+ using System.Security.Util;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Security.Policy;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // Used in DemandInternal, to remember the result of previous demands
+ // KEEP IN SYNC WITH DEFINITIONS IN SECURITYPOLICY.H
+ [Serializable]
+ internal enum PermissionType
+ {
+ // special flags
+ SecurityUnmngdCodeAccess = 0,
+ SecuritySkipVerification = 1,
+ ReflectionTypeInfo = 2,
+ SecurityAssert = 3,
+ ReflectionMemberAccess = 4,
+ SecuritySerialization = 5,
+ ReflectionRestrictedMemberAccess = 6,
+ FullTrust = 7,
+ SecurityBindingRedirects = 8,
+
+ // special permissions
+ UIPermission = 9,
+ EnvironmentPermission = 10,
+ FileDialogPermission = 11,
+ FileIOPermission = 12,
+ ReflectionPermission = 13,
+ SecurityPermission = 14,
+
+ // additional special flags
+ SecurityControlEvidence = 16,
+ SecurityControlPrincipal = 17
+ }
+
+ internal static class CodeAccessSecurityEngine
+ {
+
+ internal static SecurityPermission AssertPermission;
+ internal static PermissionToken AssertPermissionToken;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void SpecialDemand(PermissionType whatPermission, ref StackCrawlMark stackMark);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [System.Diagnostics.Conditional( "_DEBUG" )]
+ private static void DEBUG_OUT( String str )
+ {
+#if _DEBUG
+ if (debug)
+ {
+#if !FEATURE_CORECLR
+ if (to_file)
+ {
+ System.Text.StringBuilder sb = new System.Text.StringBuilder();
+ sb.Append( str );
+ sb.Append ((char)13) ;
+ sb.Append ((char)10) ;
+ PolicyManager.DebugOut( file, sb.ToString() );
+ }
+ else
+#endif
+ Console.WriteLine( str );
+ }
+#endif
+ }
+
+#if _DEBUG
+ private static bool debug = false;
+#if !FEATURE_CORECLR
+ private static readonly bool to_file = false;
+#endif
+ private const String file = "d:\\foo\\debug.txt";
+#endif
+
+ // static default constructor. This will be called before any of the static members are accessed.
+ static CodeAccessSecurityEngine()
+ {
+#pragma warning disable 618
+ AssertPermission = new SecurityPermission(SecurityPermissionFlag.Assertion);
+#pragma warning restore 618
+ AssertPermissionToken = PermissionToken.GetToken(AssertPermission);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#pragma warning disable 618
+ private static void ThrowSecurityException(RuntimeAssembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed)
+#pragma warning restore 618
+ {
+ AssemblyName asmName = null;
+ Evidence asmEvidence = null;
+ if (asm != null)
+ {
+ // Assert here because reflection will check grants and if we fail the check,
+ // there will be an infinite recursion that overflows the stack.
+ PermissionSet.s_fullTrust.Assert();
+ asmName = asm.GetName();
+#if FEATURE_CAS_POLICY
+ if(asm != Assembly.GetExecutingAssembly()) // this condition is to avoid having to marshal mscorlib's evidence (which is always in teh default domain) to the current domain
+ asmEvidence = asm.Evidence;
+#endif // FEATURE_CAS_POLICY
+ }
+ throw SecurityException.MakeSecurityException(asmName, asmEvidence, granted, refused, rmh, action, demand, permThatFailed);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#pragma warning disable 618
+ private static void ThrowSecurityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed)
+#pragma warning restore 618
+ {
+ Contract.Assert((assemblyOrString == null || assemblyOrString is RuntimeAssembly || assemblyOrString is String), "Must pass in an Assembly object or String object here");
+
+ if (assemblyOrString == null || assemblyOrString is RuntimeAssembly)
+ ThrowSecurityException((RuntimeAssembly)assemblyOrString, granted, refused, rmh, action, demand, permThatFailed);
+ else
+ {
+ AssemblyName asmName = new AssemblyName((String)assemblyOrString);
+ throw SecurityException.MakeSecurityException(asmName, null, granted, refused, rmh, action, demand, permThatFailed);
+ }
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void CheckSetHelper(CompressedStack cs,
+ PermissionSet grants,
+ PermissionSet refused,
+ PermissionSet demands,
+ RuntimeMethodHandleInternal rmh,
+ RuntimeAssembly asm,
+ SecurityAction action)
+ {
+ if (cs != null)
+ cs.CheckSetDemand(demands, rmh);
+ else
+ CheckSetHelper(grants, refused, demands, rmh, (Object)asm, action, true);
+ }
+#else // FEATURE_COMPRESSEDSTACK
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+#pragma warning disable 618
+ internal static void CheckSetHelper(Object notUsed,
+ PermissionSet grants,
+ PermissionSet refused,
+ PermissionSet demands,
+ RuntimeMethodHandleInternal rmh,
+ RuntimeAssembly asm,
+ SecurityAction action)
+#pragma warning restore 618
+ {
+ // To reduce the amount of ifdef-code-churn, a dummy arg is used for the first parameter - instead of a CompressedStack object,
+ // we use a System.Object that should always be null. If we tried to change the signature of the function, there will need to be
+ // corresponding changes in VM (metasig.h, mscorlib.h, securitystackwalk.cpp, number of elements in the arg array, etc.)
+ Contract.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack");
+
+ CheckSetHelper(grants, refused, demands, rmh, (Object)asm, action, true);
+ }
+
+#endif // FEATURE_COMPRESSEDSTACK
+
+ [System.Security.SecurityCritical] // auto-generated
+#pragma warning disable 618
+ internal static bool CheckSetHelper(PermissionSet grants,
+ PermissionSet refused,
+ PermissionSet demands,
+ RuntimeMethodHandleInternal rmh,
+ Object assemblyOrString,
+ SecurityAction action,
+ bool throwException)
+#pragma warning restore 618
+ {
+
+ Contract.Assert(demands != null, "Should not reach here with a null demand set");
+#if _DEBUG && FEATURE_CAS_POLICY
+ if (debug)
+ {
+ DEBUG_OUT("Granted: ");
+ DEBUG_OUT(grants.ToXml().ToString());
+ DEBUG_OUT("Refused: ");
+ DEBUG_OUT(refused != null ? refused.ToXml().ToString() : "<null>");
+ DEBUG_OUT("Demanded: ");
+ DEBUG_OUT(demands!=null ? demands.ToXml().ToString() : "<null>");
+ }
+#endif // _DEBUG && FEATURE_CAS_POLICY
+
+ IPermission permThatFailed = null;
+ if (grants != null)
+ grants.CheckDecoded(demands);
+ if (refused != null)
+ refused.CheckDecoded(demands);
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ try
+ {
+
+ // Check grant set
+ if (!demands.CheckDemand(grants, out permThatFailed))
+ {
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grants, refused, rmh, action, demands, permThatFailed);
+ else
+ return false;
+ }
+
+ // Check refused set
+ if (!demands.CheckDeny(refused, out permThatFailed))
+ {
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grants, refused, rmh, action, demands, permThatFailed);
+ else
+ return false;
+ }
+ }
+ catch (SecurityException)
+ {
+ throw;
+ }
+ catch (Exception)
+ {
+ // Any exception besides a security exception in this code means that
+ // a permission was unable to properly handle what we asked of it.
+ // We will define this to mean that the demand failed.
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grants, refused, rmh, action, demands, permThatFailed);
+ else
+ return false;
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+ return true;
+ }
+#if FEATURE_COMPRESSEDSTACK
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void CheckHelper(CompressedStack cs,
+ PermissionSet grantedSet,
+ PermissionSet refusedSet,
+ CodeAccessPermission demand,
+ PermissionToken permToken,
+ RuntimeMethodHandleInternal rmh,
+ RuntimeAssembly asm,
+ SecurityAction action)
+ {
+ if (cs != null)
+ cs.CheckDemand(demand, permToken, rmh);
+ else
+ CheckHelper(grantedSet, refusedSet, demand, permToken, rmh, (Object)asm, action, true);
+ }
+#else // FEATURE_COMPRESSEDSTACK
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+#pragma warning disable 618
+ internal static void CheckHelper(Object notUsed,
+ PermissionSet grantedSet,
+ PermissionSet refusedSet,
+ CodeAccessPermission demand,
+ PermissionToken permToken,
+ RuntimeMethodHandleInternal rmh,
+ RuntimeAssembly asm,
+ SecurityAction action)
+#pragma warning restore 618
+ {
+ // To reduce the amount of ifdef-code-churn, a dummy arg is used for the first parameter - instead of a CompressedStack object,
+ // we use a System.Object that should always be null. If we tried to change the signature of the function, there will need to be
+ // corresponding changes in VM (metasig.h, mscorlib.h, securitystackwalk.cpp, number of elements in the arg array, etc.)
+ Contract.Assert(notUsed == null, "Should not reach here with a non-null first arg which is the CompressedStack");
+ CheckHelper(grantedSet, refusedSet, demand, permToken, rmh, (Object)asm, action, true);
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+ [System.Security.SecurityCritical] // auto-generated
+#pragma warning disable 618
+ internal static bool CheckHelper(PermissionSet grantedSet,
+ PermissionSet refusedSet,
+ CodeAccessPermission demand,
+ PermissionToken permToken,
+ RuntimeMethodHandleInternal rmh,
+ Object assemblyOrString,
+ SecurityAction action,
+ bool throwException)
+#pragma warning restore 618
+ {
+ // We should never get here with a null demand
+ Contract.Assert(demand != null, "Should not reach here with a null demand");
+
+#if _DEBUG && FEATURE_CAS_POLICY
+ if (debug)
+ {
+ DEBUG_OUT("Granted: ");
+ DEBUG_OUT(grantedSet.ToXml().ToString());
+ DEBUG_OUT("Refused: ");
+ DEBUG_OUT(refusedSet != null ? refusedSet.ToXml().ToString() : "<null>");
+ DEBUG_OUT("Demanded: ");
+ DEBUG_OUT(demand.ToString());
+ }
+#endif // _DEBUG && FEATURE_CAS_POLICY
+
+ if (permToken == null)
+ permToken = PermissionToken.GetToken(demand);
+
+ if (grantedSet != null)
+ grantedSet.CheckDecoded(permToken.m_index);
+ if (refusedSet != null)
+ refusedSet.CheckDecoded(permToken.m_index);
+
+ // If PermissionSet is null, then module does not have Permissions... Fail check.
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ try
+ {
+ if (grantedSet == null)
+ {
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grantedSet, refusedSet, rmh, action, demand, demand);
+ else
+ return false;
+ }
+
+ else if (!grantedSet.IsUnrestricted())
+ {
+ // If we aren't unrestricted, there is a refused set, or our permission is not of the unrestricted
+ // variety, we need to do the proper callback.
+
+ Contract.Assert(demand != null,"demand != null");
+
+ // Find the permission of matching type in the permission set.
+
+ CodeAccessPermission grantedPerm =
+ (CodeAccessPermission)grantedSet.GetPermission(permToken);
+
+ // Make sure the demand has been granted
+ if (!demand.CheckDemand( grantedPerm ))
+ {
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grantedSet, refusedSet, rmh, action, demand, demand);
+ else
+ return false;
+ }
+ }
+
+ // Make the sure the permission is not refused.
+
+ if (refusedSet != null)
+ {
+ CodeAccessPermission refusedPerm =
+ (CodeAccessPermission)refusedSet.GetPermission(permToken);
+ if (refusedPerm != null)
+ {
+ if (!refusedPerm.CheckDeny(demand))
+ {
+ #if _DEBUG
+ if (debug)
+ DEBUG_OUT( "Permission found in refused set" );
+ #endif
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grantedSet, refusedSet, rmh, action, demand, demand);
+ else
+ return false;
+
+ }
+ }
+
+ if (refusedSet.IsUnrestricted())
+ {
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grantedSet, refusedSet, rmh, action, demand, demand);
+ else
+ return false;
+ }
+ }
+ }
+ catch (SecurityException)
+ {
+ throw;
+ }
+ catch (Exception)
+ {
+ // Any exception besides a security exception in this code means that
+ // a permission was unable to properly handle what we asked of it.
+ // We will define this to mean that the demand failed.
+ if (throwException)
+ ThrowSecurityException(assemblyOrString, grantedSet, refusedSet, rmh, action, demand, demand);
+ else
+ return false;
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+
+ DEBUG_OUT( "Check passed" );
+ return true;
+ }
+
+#if FEATURE_CAS_POLICY
+ /// <summary>
+ /// Demand for the grant set of an assembly
+ /// </summary>
+ /// <remarks>
+ /// Managed half of SecurityStackWalk::DemandGrantSet.
+ /// </remarks>
+ [System.Security.SecurityCritical] // auto-generated
+ private static void CheckGrantSetHelper(PermissionSet grantSet)
+ {
+ Contract.Assert(grantSet != null, "Missing grant set");
+ grantSet.CopyWithNoIdentityPermissions().Demand();
+ }
+
+ /// <summary>
+ /// Perform a security demand which succeeds if either a compatibilty permission is granted to the
+ /// call stack, or restricted member access and the grant set of the target of the reflection
+ /// operation is granted.
+ /// </summary>
+ /// <param name="permission">compatibility permission to check</param>
+ /// <param name="targetGrant">grant set of the reflection target</param>
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void ReflectionTargetDemandHelper(PermissionType permission, PermissionSet targetGrant)
+ {
+ ReflectionTargetDemandHelper((int)permission, targetGrant);
+ }
+
+ /// <summary>
+ /// Perform a security demand which succeeds if either a compatibilty permission is granted to the
+ /// call stack, or restricted member access and the grant set of the target of the reflection
+ /// operation is granted.
+ /// </summary>
+ /// <remarks>
+ /// Managed half of SecurityStackWalk::ReflectionTargetDemand.
+ /// </remarks>
+ /// <param name="permission">compatibility permission to check (See PermissionType)</param>
+ /// <param name="targetGrant">grant set of the reflection target</param>
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private static void ReflectionTargetDemandHelper(int permission, PermissionSet targetGrant)
+ {
+ // Capture a compressed stack so that we can make both permission checks without walking the stack
+ // multiple times.
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ CompressedStack cs = CompressedStack.GetCompressedStack(ref stackMark);
+
+ ReflectionTargetDemandHelper(permission, targetGrant, cs);
+ }
+
+ /// <summary>
+ /// Perform a reflection target demand against a given access context
+ /// </summary>
+ /// <remarks>
+ /// Managed half of SecurityStackWalk::ReflectionTargetDemand
+ /// </remarks>
+ /// <param name="permission">compatibility permission to check (See PermissionType)</param>
+ /// <param name="targetGrant">grant set of the reflection target</param>
+ /// <param name="accessContext">access context to do the demand against</param>
+ [System.Security.SecurityCritical] // auto-generated
+ private static void ReflectionTargetDemandHelper(int permission,
+ PermissionSet targetGrant,
+ Resolver accessContext)
+ {
+ ReflectionTargetDemandHelper(permission, targetGrant, accessContext.GetSecurityContext());
+ }
+
+ /// <summary>
+ /// Perform a reflection target demand against a given compressed stack
+ /// </summary>
+ /// <remarks>
+ /// Managed half of SecurityStackWalk::ReflectionTargetDemand
+ /// </remarks>
+ /// <param name="permission">compatibility permission to check (See PermissionType)</param>
+ /// <param name="targetGrant">grant set of the reflection target</param>
+ /// <param name="securityContext">compressed stack to do the demand against</param>
+ [System.Security.SecurityCritical] // auto-generated
+ private static void ReflectionTargetDemandHelper(int permission,
+ PermissionSet targetGrant,
+ CompressedStack securityContext)
+ {
+ Contract.Assert(securityContext != null, "securityContext != null");
+
+ // We need to remove all identity permissions from the grant set of the target, otherwise the
+ // disjunctive demand will fail unless we're reflecting on the same assembly.
+ PermissionSet demandSet = null;
+ if (targetGrant == null)
+ {
+ demandSet = new PermissionSet(PermissionState.Unrestricted);
+ }
+ else
+ {
+ demandSet = targetGrant.CopyWithNoIdentityPermissions();
+ demandSet.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
+ }
+
+ securityContext.DemandFlagsOrGrantSet((1 << (int)permission), demandSet);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void GetZoneAndOriginHelper( CompressedStack cs, PermissionSet grantSet, PermissionSet refusedSet, ArrayList zoneList, ArrayList originList )
+ {
+ if (cs != null)
+ cs.GetZoneAndOrigin(zoneList, originList, PermissionToken.GetToken(typeof(ZoneIdentityPermission)), PermissionToken.GetToken(typeof(UrlIdentityPermission)));
+ else
+ {
+ ZoneIdentityPermission zone = (ZoneIdentityPermission)grantSet.GetPermission( typeof( ZoneIdentityPermission ) );
+ UrlIdentityPermission url = (UrlIdentityPermission)grantSet.GetPermission( typeof( UrlIdentityPermission ) );
+
+ if (zone != null)
+ zoneList.Add( zone.SecurityZone );
+
+ if (url != null)
+ originList.Add( url.Url );
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void GetZoneAndOrigin( ref StackCrawlMark mark, out ArrayList zone, out ArrayList origin )
+ {
+ zone = new ArrayList();
+ origin = new ArrayList();
+
+ GetZoneAndOriginInternal( zone, origin, ref mark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetZoneAndOriginInternal(ArrayList zoneList,
+ ArrayList originList,
+ ref StackCrawlMark stackMark);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void CheckAssembly(RuntimeAssembly asm, CodeAccessPermission demand )
+ {
+ Contract.Assert( asm != null, "Must pass in a good assembly" );
+ Contract.Assert( demand != null, "Must pass in a good demand" );
+
+ PermissionSet granted, refused;
+ asm.GetGrantSet( out granted, out refused );
+#pragma warning disable 618
+ CheckHelper( granted, refused, demand, PermissionToken.GetToken(demand), RuntimeMethodHandleInternal.EmptyHandle, asm, SecurityAction.Demand, true );
+#pragma warning restore 618
+ }
+
+ // Check - Used to initiate a code-access security check.
+ // This method invokes a stack walk after skipping to the frame
+ // referenced by stackMark.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void Check (Object demand,
+ ref StackCrawlMark stackMark,
+ bool isPermSet);
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool QuickCheckForAllDemands();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool AllDomainsHomogeneousWithNoStackModifiers();
+#endif // FEATURE_CAS_POLICY
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Check(CodeAccessPermission cap, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ Check(cap,
+ ref stackMark,
+ false);
+#endif // FEATURE_CAS_POLICY
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Check(PermissionSet permSet, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ Check(permSet,
+ ref stackMark,
+ true);
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern FrameSecurityDescriptor CheckNReturnSO(PermissionToken permToken,
+ CodeAccessPermission demand,
+ ref StackCrawlMark stackMark,
+ int create );
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Assert(CodeAccessPermission cap, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ // Make sure the caller of assert has the permission to assert
+ //WARNING: The placement of the call here is just right to check
+ // the appropriate frame.
+
+ // Note: if the "AssertPermission" is not a permission that implements IUnrestrictedPermission
+ // you need to change the last parameter to a zero.
+ Contract.Assert(AssertPermissionToken != null && AssertPermission != null, "Assert Permission not setup correctly");
+ FrameSecurityDescriptor secObj = CheckNReturnSO(AssertPermissionToken,
+ AssertPermission,
+ ref stackMark,
+ 1 );
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ // This can happen when you create delegates over functions that need the REQ_SQ
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeAsserts())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetAssert(cap);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Deny(CodeAccessPermission cap, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ // Deny is only valid in legacy mode
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CasDeny"));
+ }
+
+ FrameSecurityDescriptor secObj =
+ SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ // This can happen when you create delegates over functions that need the REQ_SQ
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeDenials())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetDeny(cap);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void PermitOnly(CodeAccessPermission cap, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj =
+ SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ // This can happen when you create delegates over functions that need the REQ_SQ
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeRestrictions())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetPermitOnly(cap);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+#if FEATURE_CAS_POLICY
+ // Called from the VM to do a pre-domain initialization check of the security state of the
+ // AppDomain. This method looks at the state of the security of an AppDomain before it is
+ // completely initialized - so the output of this method does not always match what will be true
+ // when the domain is completely initialized. Instead, it is used to read what the input parameters
+ // to the domain setup say about the domain.
+ private static void PreResolve(out bool isFullyTrusted, out bool isHomogeneous)
+ {
+ //
+ // There are three main cases:
+ // 1. The AppDomain has an explict ApplicationTrust - we can use this to read the input state
+ // of the AppDomain.
+ // 2. The AppDomain is using legacy CAS policy - this means we can't tell much about the
+ // domain itself without a full policy resolution.
+ // 3. The domain is a standard v4+ AppDomain - these are always full trust and homogenous by
+ // default.
+ //
+
+ // If the AppDomain is setup with an ApplicationTrust then it is always homogenous and we can
+ // tell its grant set right from the ApplicaitonTrust
+ ApplicationTrust domainTrust = AppDomain.CurrentDomain.SetupInformation.ApplicationTrust;
+ if (domainTrust != null)
+ {
+ isFullyTrusted = domainTrust.DefaultGrantSet.PermissionSet.IsUnrestricted();
+ isHomogeneous = true;
+ return;
+ }
+
+ // Otherwise, see if the domain is being configured on input to use legacy CAS policy
+ if (CompatibilitySwitches.IsNetFx40LegacySecurityPolicy || AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ isFullyTrusted = false;
+ isHomogeneous = false;
+ return;
+ }
+
+ // If none of the above is true, then we must be a standard AppDomain
+ isFullyTrusted = true;
+ isHomogeneous = true;
+ }
+
+ // Called from the VM when either a HostSecurityManager or simple sandbox domain can determine the
+ // grant set of an assembly
+ private static PermissionSet ResolveGrantSet(Evidence evidence, out int specialFlags, bool checkExecutionPermission)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled); // This API does not do CAS policy resolution
+
+ PermissionSet grantSet = null;
+ if (!TryResolveGrantSet(evidence, out grantSet))
+ {
+ // If we couldn't figure out a grant set from the domain or the host, then we treat the
+ // assembly as fully trusted.
+ grantSet = new PermissionSet(PermissionState.Unrestricted);
+ }
+
+ // Make sure the grant set includes the ability to execute code if that has been requested.
+ if (checkExecutionPermission)
+ {
+ SecurityPermission executionPermission = new SecurityPermission(SecurityPermissionFlag.Execution);
+ if (!grantSet.Contains(executionPermission))
+ {
+ throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"),
+ System.__HResults.CORSEC_E_NO_EXEC_PERM);
+ }
+ }
+
+ specialFlags = SecurityManager.GetSpecialFlags(grantSet, null);
+ return grantSet;
+ }
+
+ // Consult the host and the current AppDomain if it is homogenous to determine what the grant set
+ // of an assembly is. This API returns true if it was able to determine a grant set for the evidence,
+ // false if it cannot and other policy needs to be applied.
+ [SecuritySafeCritical]
+ internal static bool TryResolveGrantSet(Evidence evidence, out PermissionSet grantSet)
+ {
+ Contract.Assert(evidence != null);
+
+ HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager;
+
+ // GAC assemblies always are fully trusted
+ if (evidence.GetHostEvidence<GacInstalled>() != null)
+ {
+ grantSet = new PermissionSet(PermissionState.Unrestricted);
+ return true;
+ }
+ // If the host wants to participate in policy resolution, then our next option is to ask it for
+ // a grant set
+ else if ((securityManager.Flags & HostSecurityManagerOptions.HostResolvePolicy) == HostSecurityManagerOptions.HostResolvePolicy)
+ {
+ PermissionSet hostGrantSet = securityManager.ResolvePolicy(evidence);
+
+ if (hostGrantSet == null)
+ {
+ throw new PolicyException(Environment.GetResourceString("Policy_NullHostGrantSet", securityManager.GetType().FullName));
+ }
+
+ // If we're in a homogenous domain, we don't want to allow the host to create multiple
+ // levels of permissions within the domain. So, if we see the host return something other
+ // than full trust or the homogenous grant set, we reject the grant set.
+ if (AppDomain.CurrentDomain.IsHomogenous)
+ {
+ // Some hosts, such as ASP.NET, return Nothing as a way of saying that the assembly should
+ // not be allowed to run in the AppDomain. Reject that with a specific
+ // no-execution-allowed-here exception message, rather than the return value validation
+ // exception message we'd hit below.
+ if (hostGrantSet.IsEmpty())
+ {
+ throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"));
+ }
+
+ PermissionSet homogenousGrantSet = AppDomain.CurrentDomain.ApplicationTrust.DefaultGrantSet.PermissionSet;
+ bool isValidGrantSet = hostGrantSet.IsUnrestricted() ||
+ (hostGrantSet.IsSubsetOf(homogenousGrantSet) && homogenousGrantSet.IsSubsetOf(hostGrantSet));
+
+ if (!isValidGrantSet)
+ {
+ throw new PolicyException(Environment.GetResourceString("Policy_GrantSetDoesNotMatchDomain", securityManager.GetType().FullName));
+ }
+ }
+
+ grantSet = hostGrantSet;
+ return true;
+ }
+ // If we're in a homogenous domain, we can get the grant set directly from the application trust
+ else if (AppDomain.CurrentDomain.IsHomogenous)
+ {
+ grantSet = AppDomain.CurrentDomain.GetHomogenousGrantSet(evidence);
+ return true;
+ }
+ // Otherwise we have no way to figure out what the grant set is
+ else
+ {
+ grantSet = null;
+ return false;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_PLS
+ // Update the PLS used for optimization in the AppDomain: called from the VM
+ [System.Security.SecurityCritical] // auto-generated
+ private static PermissionListSet UpdateAppDomainPLS(PermissionListSet adPLS, PermissionSet grantedPerms, PermissionSet refusedPerms) {
+ if (adPLS == null) {
+ adPLS = new PermissionListSet();
+ adPLS.UpdateDomainPLS(grantedPerms, refusedPerms);
+ return adPLS;
+ } else {
+ PermissionListSet newPLS = new PermissionListSet();
+ newPLS.UpdateDomainPLS(adPLS);
+ newPLS.UpdateDomainPLS(grantedPerms, refusedPerms);
+ return newPLS;
+ }
+ }
+#endif //FEATURE_PLS
+ }
+}
diff --git a/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs
new file mode 100644
index 0000000000..8f25bda617
--- /dev/null
+++ b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs
@@ -0,0 +1,564 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security {
+ using System.Text;
+ using System.Runtime.CompilerServices;
+ using System.Threading;
+ using System;
+ using System.Collections;
+ using System.Security.Permissions;
+ using System.Globalization;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_PAL
+ using Microsoft.Win32.SafeHandles;
+#endif
+ //FrameSecurityDescriptor.cs
+ //
+ // Internal use only.
+ // DO NOT DOCUMENT
+ //
+
+ [Serializable]
+ internal class FrameSecurityDescriptor
+ {
+
+ /* EE has native FrameSecurityDescriptorObject definition in object.h
+ Make sure to update that structure as well, if you make any changes here.
+ */
+ private PermissionSet m_assertions; // imperative asserts
+ private PermissionSet m_denials; // imperative denials
+ private PermissionSet m_restriction; // imperative permitonlys
+ private PermissionSet m_DeclarativeAssertions;
+ private PermissionSet m_DeclarativeDenials;
+ private PermissionSet m_DeclarativeRestrictions;
+
+#if !FEATURE_PAL
+ // if this frame contains a call to any WindowsIdentity.Impersonate(),
+ // we save the previous SafeTokenHandles here (in the next two fields)
+ // Used during exceptionstackwalks to revert impersonation before calling filters
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ private SafeAccessTokenHandle m_callerToken;
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ private SafeAccessTokenHandle m_impToken;
+#endif
+
+ private bool m_AssertFT;
+ private bool m_assertAllPossible;
+#pragma warning disable 169
+ private bool m_declSecComputed; // set from the VM to indicate that the declarative A/PO/D on this frame has been populated
+#pragma warning restore 169
+
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void IncrementOverridesCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void DecrementOverridesCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void IncrementAssertCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void DecrementAssertCount();
+
+
+ // Default constructor.
+ internal FrameSecurityDescriptor()
+ {
+ //m_flags = 0;
+ }
+ //-----------------------------------------------------------+
+ // H E L P E R
+ //-----------------------------------------------------------+
+
+ private PermissionSet CreateSingletonSet(IPermission perm)
+ {
+ PermissionSet permSet = new PermissionSet(false);
+ permSet.AddPermission(perm.Copy());
+ return permSet;
+ }
+
+ //-----------------------------------------------------------+
+ // A S S E R T
+ //-----------------------------------------------------------+
+
+ internal bool HasImperativeAsserts()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_assertions != null);
+ }
+ internal bool HasImperativeDenials()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_denials != null);
+ }
+ internal bool HasImperativeRestrictions()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_restriction != null);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssert(IPermission perm)
+ {
+ m_assertions = CreateSingletonSet(perm);
+ IncrementAssertCount();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssert(PermissionSet permSet)
+ {
+ m_assertions = permSet.Copy();
+ m_AssertFT = m_AssertFT || m_assertions.IsUnrestricted();
+ IncrementAssertCount();
+ }
+
+ internal PermissionSet GetAssertions(bool fDeclarative)
+ {
+ return (fDeclarative) ? m_DeclarativeAssertions : m_assertions;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssertAllPossible()
+ {
+ m_assertAllPossible = true;
+ IncrementAssertCount();
+ }
+
+ internal bool GetAssertAllPossible()
+ {
+ return m_assertAllPossible;
+ }
+
+ //-----------------------------------------------------------+
+ // D E N Y
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetDeny(IPermission perm)
+ {
+#if FEATURE_CAS_POLICY
+ BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Deny is only valid in legacy CAS mode");
+#endif // FEATURE_CAS_POLICY
+
+ m_denials = CreateSingletonSet(perm);
+ IncrementOverridesCount();
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetDeny(PermissionSet permSet)
+ {
+ m_denials = permSet.Copy();
+ IncrementOverridesCount();
+ }
+
+ internal PermissionSet GetDenials(bool fDeclarative)
+ {
+ return (fDeclarative) ? m_DeclarativeDenials: m_denials;
+ }
+
+ //-----------------------------------------------------------+
+ // R E S T R I C T
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetPermitOnly(IPermission perm)
+ {
+ m_restriction = CreateSingletonSet(perm);
+ IncrementOverridesCount();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetPermitOnly(PermissionSet permSet)
+ {
+ // permSet must not be null
+ m_restriction = permSet.Copy();
+ IncrementOverridesCount();
+ }
+
+ internal PermissionSet GetPermitOnly(bool fDeclarative)
+ {
+
+ return (fDeclarative) ? m_DeclarativeRestrictions : m_restriction;
+ }
+#if !FEATURE_PAL
+ //-----------------------------------------------------------+
+ // SafeAccessTokenHandle (Impersonation + EH purposes)
+ //-----------------------------------------------------------+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetTokenHandles (SafeAccessTokenHandle callerToken, SafeAccessTokenHandle impToken)
+ {
+ m_callerToken = callerToken;
+ m_impToken = impToken;
+ }
+#endif
+ //-----------------------------------------------------------+
+ // R E V E R T
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAssert()
+ {
+ if (m_assertions != null)
+ {
+ m_assertions = null;
+ DecrementAssertCount();
+ }
+
+
+ if (m_DeclarativeAssertions != null)
+ {
+ m_AssertFT = m_DeclarativeAssertions.IsUnrestricted();
+ }
+ else
+ {
+ m_AssertFT = false;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAssertAllPossible()
+ {
+ if (m_assertAllPossible)
+ {
+ m_assertAllPossible = false;
+ DecrementAssertCount();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertDeny()
+ {
+ if (HasImperativeDenials())
+ {
+ DecrementOverridesCount();
+ m_denials = null;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertPermitOnly()
+ {
+ if (HasImperativeRestrictions())
+ {
+ DecrementOverridesCount();
+ m_restriction= null;;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAll()
+ {
+ RevertAssert();
+ RevertAssertAllPossible();
+ RevertDeny();
+ RevertPermitOnly();
+ }
+
+
+ //-----------------------------------------------------------+
+ // Demand Evaluation
+ //-----------------------------------------------------------+
+
+
+ // This will get called when we hit a FSD while evaluating a demand on the call stack or compressedstack
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
+ {
+ // imperative security
+ bool fContinue = CheckDemand2(demand, permToken, rmh, false);
+ if (fContinue == SecurityRuntime.StackContinue)
+ {
+ // declarative security
+ fContinue = CheckDemand2(demand, permToken, rmh, true);
+ }
+ return fContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand2(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh, bool fDeclarative)
+ {
+ PermissionSet permSet;
+
+ // If the demand is null, there is no need to continue
+ Contract.Assert(demand != null && !demand.CheckDemand(null), "Empty demands should have been filtered out by this point");
+
+ // decode imperative
+ if (GetPermitOnly(fDeclarative) != null)
+ GetPermitOnly(fDeclarative).CheckDecoded(demand, permToken);
+
+ if (GetDenials(fDeclarative) != null)
+ GetDenials(fDeclarative).CheckDecoded(demand, permToken);
+
+ if (GetAssertions(fDeclarative) != null)
+ GetAssertions(fDeclarative).CheckDecoded(demand, permToken);
+
+ // NOTE: See notes about exceptions and exception handling in FrameDescSetHelper
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ // Check Reduction
+
+ try
+ {
+ permSet = GetPermitOnly(fDeclarative);
+ if (permSet != null)
+ {
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If the permit only set does not contain the demanded permission, throw a security exception
+ if (perm == null)
+ {
+ if (!permSet.IsUnrestricted())
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+ else
+ {
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demand.CheckPermitOnly(perm);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (bNeedToThrow)
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+ }
+
+ // Check Denials
+
+ permSet = GetDenials(fDeclarative);
+ if (permSet != null)
+ {
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If an unrestricted set was denied and the demand implements IUnrestricted
+ if (permSet.IsUnrestricted())
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+
+ // If the deny set does contain the demanded permission, throw a security exception
+ bool bNeedToThrow = true;
+ try
+ {
+ bNeedToThrow = !demand.CheckDeny(perm);
+ }
+ catch (ArgumentException)
+ {
+ }
+ if (bNeedToThrow)
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+
+ if (GetAssertAllPossible())
+ {
+ return SecurityRuntime.StackHalt;
+ }
+
+ permSet = GetAssertions(fDeclarative);
+ // Check Assertions
+ if (permSet != null)
+ {
+
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If the assert set does contain the demanded permission, halt the stackwalk
+
+ try
+ {
+ if (permSet.IsUnrestricted() || demand.CheckAssert(perm))
+ {
+ return SecurityRuntime.StackHalt;
+ }
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+
+ return SecurityRuntime.StackContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand(PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh)
+ {
+ // imperative security
+ PermissionSet altPset1 = null, altPset2 = null;
+ bool fContinue = CheckSetDemand2(demandSet, out altPset1, rmh, false);
+ if (altPset1 != null)
+ {
+ demandSet = altPset1;
+ }
+
+ if (fContinue == SecurityRuntime.StackContinue)
+ {
+ // declarative security
+ fContinue = CheckSetDemand2(demandSet, out altPset2, rmh, true);
+ }
+ // Return the most recent altered set
+ // If both declarative and imperative asserts modified the demand set: return altPset2
+ // Else if imperative asserts modified the demand set: return altPset1
+ // else no alteration: return null
+ if (altPset2 != null)
+ alteredDemandSet = altPset2;
+ else if (altPset1 != null)
+ alteredDemandSet = altPset1;
+ else
+ alteredDemandSet = null;
+
+ return fContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand2(PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh, bool fDeclarative)
+ {
+ PermissionSet permSet;
+
+ // In the common case we are not going to alter the demand set, so just to
+ // be safe we'll set it to null up front.
+ alteredDemandSet = null;
+
+ // There's some oddness in here to deal with exceptions. The general idea behind
+ // this is that we need some way of dealing with custom permissions that may not
+ // handle all possible scenarios of Union(), Intersect(), and IsSubsetOf() properly
+ // (they don't support it, throw null reference exceptions, etc.).
+
+ // An empty demand always succeeds.
+ if (demandSet == null || demandSet.IsEmpty())
+ return SecurityRuntime.StackHalt;
+
+ if (GetPermitOnly(fDeclarative) != null)
+ GetPermitOnly(fDeclarative).CheckDecoded( demandSet );
+ if (GetDenials(fDeclarative) != null)
+ GetDenials(fDeclarative).CheckDecoded( demandSet );
+ if (GetAssertions(fDeclarative) != null)
+ GetAssertions(fDeclarative).CheckDecoded( demandSet );
+
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ try
+ {
+ // In the case of permit only, we define an exception to be failure of the check
+ // and therefore we throw a security exception.
+
+ permSet = GetPermitOnly(fDeclarative);
+ if (permSet != null)
+ {
+ IPermission permFailed = null;
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demandSet.CheckPermitOnly(permSet, out permFailed);
+ }
+ catch (ArgumentException)
+ {
+ }
+ if (bNeedToThrow)
+ throw new SecurityException(Environment.GetResourceString("Security_GenericNoType"), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demandSet, permFailed);
+ }
+
+ // In the case of denial, we define an exception to be failure of the check
+ // and therefore we throw a security exception.
+
+ permSet = GetDenials(fDeclarative);
+
+
+ if (permSet != null)
+ {
+ IPermission permFailed = null;
+
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demandSet.CheckDeny(permSet, out permFailed);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (bNeedToThrow)
+ throw new SecurityException(Environment.GetResourceString("Security_GenericNoType"), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demandSet, permFailed);
+ }
+
+ // The assert case is more complex. Since asserts have the ability to "bleed through"
+ // (where part of a demand is handled by an assertion, but the rest is passed on to
+ // continue the stackwalk), we need to be more careful in handling the "failure" case.
+ // Therefore, if an exception is thrown in performing any operation, we make sure to keep
+ // that permission in the demand set thereby continuing the demand for that permission
+ // walking down the stack.
+
+ if (GetAssertAllPossible())
+ {
+ return SecurityRuntime.StackHalt;
+ }
+
+ permSet = GetAssertions(fDeclarative);
+ if (permSet != null)
+ {
+ // If this frame asserts a superset of the demand set we're done
+
+ if (demandSet.CheckAssertion( permSet ))
+ return SecurityRuntime.StackHalt;
+
+ // Determine whether any of the demand set asserted. We do this by
+ // copying the demand set and removing anything in it that is asserted.
+
+ if (!permSet.IsUnrestricted())
+ {
+ PermissionSet.RemoveAssertedPermissionSet(demandSet, permSet, out alteredDemandSet);
+ }
+ }
+
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+
+ return SecurityRuntime.StackContinue;
+ }
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ // Used by the stack compressor to communicate a DynamicResolver to managed code during a stackwalk.
+ // The JIT will not actually place these on frames.
+ internal class FrameSecurityDescriptorWithResolver : FrameSecurityDescriptor
+ {
+ private System.Reflection.Emit.DynamicResolver m_resolver;
+
+ public System.Reflection.Emit.DynamicResolver Resolver
+ {
+ get
+ {
+ return m_resolver;
+ }
+ }
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+}
diff --git a/src/mscorlib/src/System/Security/HostProtectionException.cs b/src/mscorlib/src/System/Security/HostProtectionException.cs
new file mode 100644
index 0000000000..83f005fe9b
--- /dev/null
+++ b/src/mscorlib/src/System/Security/HostProtectionException.cs
@@ -0,0 +1,136 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+/*=============================================================================
+**
+**
+** Purpose: Exception class for HostProtection
+**
+**
+=============================================================================*/
+
+namespace System.Security
+{
+ using System.Security;
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using System.Text;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class HostProtectionException : SystemException
+ {
+ private HostProtectionResource m_protected;
+ private HostProtectionResource m_demanded;
+
+ private const String ProtectedResourcesName = "ProtectedResources";
+ private const String DemandedResourcesName = "DemandedResources";
+
+ public HostProtectionException() : base()
+ {
+ m_protected = HostProtectionResource.None;
+ m_demanded = HostProtectionResource.None;
+ }
+
+ public HostProtectionException(string message) : base(message)
+ {
+ m_protected = HostProtectionResource.None;
+ m_demanded = HostProtectionResource.None;
+ }
+
+ public HostProtectionException(string message, Exception e) : base(message, e)
+ {
+ m_protected = HostProtectionResource.None;
+ m_demanded = HostProtectionResource.None;
+ }
+
+ protected HostProtectionException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ m_protected = (HostProtectionResource)info.GetValue(ProtectedResourcesName, typeof(HostProtectionResource));
+ m_demanded = (HostProtectionResource)info.GetValue(DemandedResourcesName, typeof(HostProtectionResource));
+ }
+
+ public HostProtectionException(string message, HostProtectionResource protectedResources, HostProtectionResource demandedResources)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_HOSTPROTECTION);
+ m_protected = protectedResources;
+ m_demanded = demandedResources;
+ }
+
+ // Called from the VM to create a HP Exception
+ private HostProtectionException(HostProtectionResource protectedResources, HostProtectionResource demandedResources)
+ : base(SecurityException.GetResString("HostProtection_HostProtection"))
+ {
+ SetErrorCode(__HResults.COR_E_HOSTPROTECTION);
+ m_protected = protectedResources;
+ m_demanded = demandedResources;
+ }
+
+
+ public HostProtectionResource ProtectedResources
+ {
+ get
+ {
+ return m_protected;
+ }
+ }
+
+ public HostProtectionResource DemandedResources
+ {
+ get
+ {
+ return m_demanded;
+ }
+ }
+
+ private String ToStringHelper(String resourceString, Object attr)
+ {
+ if (attr == null)
+ return String.Empty;
+ StringBuilder sb = new StringBuilder();
+ sb.Append(Environment.NewLine);
+ sb.Append(Environment.NewLine);
+ sb.Append(Environment.GetResourceString( resourceString ));
+ sb.Append(Environment.NewLine);
+ sb.Append(attr);
+ return sb.ToString();
+ }
+
+ public override String ToString()
+ {
+ String protectedResStrValue = ToStringHelper("HostProtection_ProtectedResources", ProtectedResources);
+ StringBuilder sb = new StringBuilder();
+ sb.Append(base.ToString());
+
+ sb.Append(protectedResStrValue);
+ sb.Append(ToStringHelper("HostProtection_DemandedResources", DemandedResources));
+
+ return sb.ToString();
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ base.GetObjectData( info, context );
+
+ info.AddValue(ProtectedResourcesName, ProtectedResources, typeof(HostProtectionResource));
+ info.AddValue(DemandedResourcesName, DemandedResources, typeof(HostProtectionResource));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/HostSecurityManager.cs b/src/mscorlib/src/System/Security/HostSecurityManager.cs
new file mode 100644
index 0000000000..46d5552478
--- /dev/null
+++ b/src/mscorlib/src/System/Security/HostSecurityManager.cs
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+// A HostSecurityManager gives a hosting application the chance to
+// participate in the security decisions in the AppDomain.
+//
+
+namespace System.Security {
+ using System.Collections;
+#if FEATURE_CLICKONCE
+ using System.Deployment.Internal.Isolation;
+ using System.Deployment.Internal.Isolation.Manifest;
+ using System.Runtime.Hosting;
+#endif
+ using System.Reflection;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Security.Policy;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum HostSecurityManagerOptions {
+ None = 0x0000,
+ HostAppDomainEvidence = 0x0001,
+ [Obsolete("AppDomain policy levels are obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ HostPolicyLevel = 0x0002,
+ HostAssemblyEvidence = 0x0004,
+ HostDetermineApplicationTrust = 0x0008,
+ HostResolvePolicy = 0x0010,
+ AllFlags = 0x001F
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Serializable]
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.Infrastructure)]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class HostSecurityManager {
+ public HostSecurityManager () {}
+
+ // The host can choose which events he wants to participate in. This property can be set when
+ // the host only cares about a subset of the capabilities exposed through the HostSecurityManager.
+ public virtual HostSecurityManagerOptions Flags {
+ get {
+ // We use AllFlags as the default.
+ return HostSecurityManagerOptions.AllFlags;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ // provide policy for the AppDomain.
+ [Obsolete("AppDomain policy levels are obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public virtual PolicyLevel DomainPolicy {
+ get {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ return null;
+ }
+ }
+#endif
+ public virtual Evidence ProvideAppDomainEvidence (Evidence inputEvidence) {
+ // The default implementation does not modify the input evidence.
+ return inputEvidence;
+ }
+
+ public virtual Evidence ProvideAssemblyEvidence (Assembly loadedAssembly, Evidence inputEvidence) {
+ // The default implementation does not modify the input evidence.
+ return inputEvidence;
+ }
+
+#if FEATURE_CLICKONCE
+ [System.Security.SecurityCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Assert, Unrestricted=true)]
+ public virtual ApplicationTrust DetermineApplicationTrust(Evidence applicationEvidence, Evidence activatorEvidence, TrustManagerContext context)
+ {
+ if (applicationEvidence == null)
+ throw new ArgumentNullException("applicationEvidence");
+ Contract.EndContractBlock();
+
+ // This method looks for a trust decision for the ActivationContext in three locations, in order
+ // of preference:
+ //
+ // 1. Supplied by the host in the AppDomainSetup. If the host supplied a decision this way, it
+ // will be in the applicationEvidence.
+ // 2. Reuse the ApplicationTrust from the current AppDomain
+ // 3. Ask the TrustManager for a trust decision
+
+ // get the activation context from the application evidence.
+ // The default HostSecurityManager does not examine the activatorEvidence
+ // but other security managers could use it to figure out the
+ // evidence of the domain attempting to activate the application.
+
+ ActivationArguments activationArgs = applicationEvidence.GetHostEvidence<ActivationArguments>();
+ if (activationArgs == null)
+ throw new ArgumentException(Environment.GetResourceString("Policy_MissingActivationContextInAppEvidence"));
+
+ ActivationContext actCtx = activationArgs.ActivationContext;
+ if (actCtx == null)
+ throw new ArgumentException(Environment.GetResourceString("Policy_MissingActivationContextInAppEvidence"));
+
+ // Make sure that any ApplicationTrust we find applies to the ActivationContext we're
+ // creating the new AppDomain for.
+ ApplicationTrust appTrust = applicationEvidence.GetHostEvidence<ApplicationTrust>();
+ if (appTrust != null &&
+ !CmsUtils.CompareIdentities(appTrust.ApplicationIdentity, activationArgs.ApplicationIdentity, ApplicationVersionMatch.MatchExactVersion))
+ {
+ appTrust = null;
+ }
+
+ // If there was not a trust decision supplied in the Evidence, we can reuse the existing trust
+ // decision from this domain if its identity matches the ActivationContext of the new domain.
+ // Otherwise consult the TrustManager for a trust decision
+ if (appTrust == null)
+ {
+ if (AppDomain.CurrentDomain.ApplicationTrust != null &&
+ CmsUtils.CompareIdentities(AppDomain.CurrentDomain.ApplicationTrust.ApplicationIdentity, activationArgs.ApplicationIdentity, ApplicationVersionMatch.MatchExactVersion))
+ {
+ appTrust = AppDomain.CurrentDomain.ApplicationTrust;
+ }
+ else
+ {
+ appTrust = ApplicationSecurityManager.DetermineApplicationTrustInternal(actCtx, context);
+ }
+ }
+
+ // If the trust decision allows the application to run, then it should also have a permission set
+ // which is at least the permission set the application requested.
+ ApplicationSecurityInfo appRequest = new ApplicationSecurityInfo(actCtx);
+ if (appTrust != null &&
+ appTrust.IsApplicationTrustedToRun &&
+ !appRequest.DefaultRequestSet.IsSubsetOf(appTrust.DefaultGrantSet.PermissionSet))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Policy_AppTrustMustGrantAppRequest"));
+ }
+
+ return appTrust;
+ }
+#endif // FEATURE_CLICKONCE
+
+#if FEATURE_CAS_POLICY
+ // Query the CLR to see what it would have granted a specific set of evidence
+ public virtual PermissionSet ResolvePolicy(Evidence evidence)
+ {
+ if (evidence == null)
+ throw new ArgumentNullException("evidence");
+ Contract.EndContractBlock();
+
+ //
+ // If the evidence is from the GAC then the result is full trust.
+ // In a homogenous domain, then the application trust object provides the grant set.
+ // When CAS policy is disabled, the result is full trust.
+ // Otherwise, the result comes from evaluating CAS policy.
+ //
+
+ if (evidence.GetHostEvidence<GacInstalled>() != null)
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ else if (AppDomain.CurrentDomain.IsHomogenous)
+ {
+ return AppDomain.CurrentDomain.GetHomogenousGrantSet(evidence);
+ }
+ else if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ else
+ {
+ return SecurityManager.PolicyManager.CodeGroupResolve(evidence, false);
+ }
+ }
+#endif
+
+ /// <summary>
+ /// Determine what types of evidence the host might be able to supply for the AppDomain if requested
+ /// </summary>
+ /// <returns></returns>
+ public virtual Type[] GetHostSuppliedAppDomainEvidenceTypes() {
+ return null;
+ }
+
+ /// <summary>
+ /// Determine what types of evidence the host might be able to supply for an assembly if requested
+ /// </summary>
+ public virtual Type[] GetHostSuppliedAssemblyEvidenceTypes(Assembly assembly) {
+ return null;
+ }
+
+ /// <summary>
+ /// Ask the host to supply a specific type of evidence for the AppDomain
+ /// </summary>
+ public virtual EvidenceBase GenerateAppDomainEvidence(Type evidenceType) {
+ return null;
+ }
+
+ /// <summary>
+ /// Ask the host to supply a specific type of evidence for an assembly
+ /// </summary>
+ public virtual EvidenceBase GenerateAssemblyEvidence(Type evidenceType, Assembly assembly) {
+ return null;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/IEvidenceFactory.cs b/src/mscorlib/src/System/Security/IEvidenceFactory.cs
new file mode 100644
index 0000000000..93f82a6420
--- /dev/null
+++ b/src/mscorlib/src/System/Security/IEvidenceFactory.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security {
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Policy;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IEvidenceFactory
+ {
+#if FEATURE_CAS_POLICY
+ Evidence Evidence
+ {
+ get;
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/IPermission.cs b/src/mscorlib/src/System/Security/IPermission.cs
new file mode 100644
index 0000000000..5477261fd7
--- /dev/null
+++ b/src/mscorlib/src/System/Security/IPermission.cs
@@ -0,0 +1,84 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// Defines the interface that all Permission objects must support.
+//
+
+namespace System.Security
+{
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IPermission : ISecurityEncodable
+ {
+ // NOTE: The constants that used to be defined here were moved to
+ // PermissionsEnum.cs due to CLS restrictions.
+
+ // The integrity of the security system depends on a means to
+ // copy objects so that references to sensitive objects are not
+ // exposed outside of the runtime. Thus, all permissions must
+ // implement Copy.
+ //
+ // Makes an exact copy of the Permission.
+ IPermission Copy();
+
+ /*
+ * Methods to support the Installation, Registration, others... PolicyEngine
+ */
+
+ // Policy decisions and runtime mechanisms (for example, Deny)
+ // require a means to retrieve shared state between two
+ // permissions. If there is no shared state between two
+ // instances, then the method should return null.
+ //
+ // Could think of the method as GetCommonState,
+ // but leave it as Intersect to avoid gratuitous name changes.
+ //
+ // Returns a new permission with the permission-defined intersection
+ // of the two permissions. The intersection is generally defined as
+ // privilege parameters that are included by both 'this' and 'target'.
+ // Returns null if 'target' is null or is of wrong type.
+ //
+ IPermission Intersect(IPermission target);
+
+ // The runtime policy manager also requires a means of combining the
+ // state contained within two permissions of the same type in a logical OR
+ // construct. (The Union of two permission of different type is not defined,
+ // except when one of the two is a CompoundPermission of internal type equal
+ // to the type of the other permission.)
+ //
+
+ IPermission Union(IPermission target);
+
+ // IsSubsetOf defines a standard mechanism for determining
+ // relative safety between two permission demands of the same type.
+ // If one demand x demands no more than some other demand y, then
+ // x.IsSubsetOf(y) should return true. In this case, if the
+ // demand for y is satisfied, then it is possible to assume that
+ // the demand for x would also be satisfied under the same
+ // circumstances. On the other hand, if x demands something that y
+ // does not, then x.IsSubsetOf(y) should return false; the fact
+ // that x is satisfied by the current security context does not
+ // also imply that the demand for y will also be satisfied.
+ //
+ // Returns true if 'this' Permission allows no more access than the
+ // argument.
+ //
+ bool IsSubsetOf(IPermission target);
+
+ // The Demand method is the fundamental part of the IPermission
+ // interface from a component developer's perspective. The
+ // permission represents the demand that the developer wants
+ // satisfied, and Demand is the means to invoke the demand.
+ // For each type of permission, the mechanism to verify the
+ // demand will be different. However, to the developer, all
+ // permissions invoke that mechanism through the Demand interface.
+ // Mark this method as requiring a security object on the caller's frame
+ // so the caller won't be inlined (which would mess up stack crawling).
+ [DynamicSecurityMethodAttribute()]
+ void Demand();
+
+ }
+}
diff --git a/src/mscorlib/src/System/Security/ISecurityEncodable.cs b/src/mscorlib/src/System/Security/ISecurityEncodable.cs
new file mode 100644
index 0000000000..9915da3696
--- /dev/null
+++ b/src/mscorlib/src/System/Security/ISecurityEncodable.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// All encodable security classes that support encoding need to
+// implement this interface
+//
+
+namespace System.Security {
+
+ using System;
+ using System.Security.Util;
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISecurityEncodable
+ {
+#if FEATURE_CAS_POLICY
+ SecurityElement ToXml();
+
+ void FromXml( SecurityElement e );
+#endif // FEATURE_CAS_POLICY
+ }
+
+}
+
+
diff --git a/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs b/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs
new file mode 100644
index 0000000000..b1c8d1654f
--- /dev/null
+++ b/src/mscorlib/src/System/Security/ISecurityPolicyEncodable.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// All encodable security classes that support encoding need to
+// implement this interface
+//
+
+namespace System.Security {
+
+ using System;
+ using System.Security.Util;
+ using System.Security.Policy;
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface ISecurityPolicyEncodable
+ {
+#if FEATURE_CAS_POLICY
+ SecurityElement ToXml( PolicyLevel level );
+
+ void FromXml( SecurityElement e, PolicyLevel level );
+#endif // FEATURE_CAS_POLICY
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/IStackWalk.cs b/src/mscorlib/src/System/Security/IStackWalk.cs
new file mode 100644
index 0000000000..902fc35b61
--- /dev/null
+++ b/src/mscorlib/src/System/Security/IStackWalk.cs
@@ -0,0 +1,23 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security
+{
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IStackWalk
+ {
+ [DynamicSecurityMethodAttribute()]
+ void Assert();
+
+ [DynamicSecurityMethodAttribute()]
+ void Demand();
+
+ [DynamicSecurityMethodAttribute()]
+ void Deny();
+
+ [DynamicSecurityMethodAttribute()]
+ void PermitOnly();
+ }
+}
diff --git a/src/mscorlib/src/System/Security/NamedPermissionSet.cs b/src/mscorlib/src/System/Security/NamedPermissionSet.cs
new file mode 100644
index 0000000000..fba76749a1
--- /dev/null
+++ b/src/mscorlib/src/System/Security/NamedPermissionSet.cs
@@ -0,0 +1,269 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// Extends PermissionSet to allow an associated name and description
+//
+
+namespace System.Security {
+
+ using System;
+ using System.Security.Util;
+ using System.Security.Permissions;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+#if !FEATURE_CAS_POLICY
+ using Microsoft.Win32;
+ using System.Collections;
+ using System.Globalization;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.Runtime.Versioning;
+ using System.Text;
+
+#else // FEATURE_CAS_POLICY
+
+ using System.Threading;
+
+#endif // FEATURE_CAS_POLICY
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class NamedPermissionSet : PermissionSet
+ {
+#if FEATURE_CAS_POLICY
+ // The name of this PermissionSet
+ private String m_name;
+
+ // The description of this PermissionSet
+ private String m_description;
+ [OptionalField(VersionAdded = 2)]
+ internal String m_descrResource;
+
+ internal NamedPermissionSet()
+ : base()
+ {
+ }
+
+ public NamedPermissionSet( String name )
+ : base()
+ {
+ CheckName( name );
+ m_name = name;
+ }
+
+ public NamedPermissionSet( String name, PermissionState state)
+ : base( state )
+ {
+ CheckName( name );
+ m_name = name;
+ }
+
+
+ public NamedPermissionSet( String name, PermissionSet permSet )
+ : base( permSet )
+ {
+ CheckName( name );
+ m_name = name;
+ }
+
+ public NamedPermissionSet( NamedPermissionSet permSet )
+ : base( permSet )
+ {
+ m_name = permSet.m_name;
+ m_description = permSet.Description;
+ }
+
+ internal NamedPermissionSet(SecurityElement permissionSetXml)
+ : base(PermissionState.None)
+ {
+ Contract.Assert(permissionSetXml != null);
+ FromXml(permissionSetXml);
+ }
+
+ public String Name {
+ get { return m_name; }
+ set { CheckName( value ); m_name = value; }
+ }
+
+ private static void CheckName( String name )
+ {
+ if (name == null || name.Equals( "" ))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_NPMSInvalidName" ));
+ Contract.EndContractBlock();
+ }
+
+ public String Description {
+ get
+ {
+ if(m_descrResource != null)
+ {
+ m_description = Environment.GetResourceString(m_descrResource);
+ m_descrResource = null;
+ }
+ return m_description;
+ }
+
+ set
+ {
+ m_description = value;
+ m_descrResource = null;
+ }
+ }
+
+ public override PermissionSet Copy()
+ {
+ return new NamedPermissionSet( this );
+ }
+
+ public NamedPermissionSet Copy( String name )
+ {
+ NamedPermissionSet set = new NamedPermissionSet( this );
+ set.Name = name;
+ return set;
+ }
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement elem = base.ToXml("System.Security.NamedPermissionSet");
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( this.GetType().FullName.Equals( "System.Security.NamedPermissionSet" ), "Class name changed!" );
+
+ if (m_name != null && !m_name.Equals( "" ))
+ {
+ elem.AddAttribute( "Name", SecurityElement.Escape( m_name ) );
+ }
+
+ if (Description != null && !Description.Equals( "" ))
+ {
+ elem.AddAttribute( "Description", SecurityElement.Escape( Description ) );
+ }
+
+ return elem;
+ }
+
+ public override void FromXml( SecurityElement et )
+ {
+ FromXml( et, false, false );
+ }
+
+ internal override void FromXml( SecurityElement et, bool allowInternalOnly, bool ignoreTypeLoadFailures )
+ {
+ if (et == null)
+ throw new ArgumentNullException( "et" );
+ Contract.EndContractBlock();
+
+ String elem;
+
+ elem = et.Attribute( "Name" );
+ m_name = elem == null ? null : elem;
+
+ elem = et.Attribute( "Description" );
+ m_description = (elem == null ? "" : elem);
+ m_descrResource = null;
+
+ base.FromXml( et, allowInternalOnly, ignoreTypeLoadFailures );
+ }
+
+ internal void FromXmlNameOnly( SecurityElement et )
+ {
+ // This function gets only the name for the permission set, ignoring all other info.
+
+ String elem;
+
+ elem = et.Attribute( "Name" );
+ m_name = (elem == null ? null : elem);
+ }
+
+ // NamedPermissionSet Equals should have the exact semantic as PermissionSet.
+ // We explicitly override them here to make sure that no one accidently
+ // changes this.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals( Object obj )
+ {
+ return base.Equals( obj );
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject {
+ get {
+ if (s_InternalSyncObject == null) {
+ Object o = new Object();
+ Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+#else // FEATURE_CAS_POLICY
+
+ internal static PermissionSet GetBuiltInSet(string name) {
+ // Used by PermissionSetAttribute to create one of the built-in,
+ // immutable permission sets.
+
+ if (name == null)
+ return null;
+ else if (name.Equals("FullTrust"))
+ return CreateFullTrustSet();
+ else if (name.Equals("Nothing"))
+ return CreateNothingSet();
+ else if (name.Equals("Execution"))
+ return CreateExecutionSet();
+ else if (name.Equals("SkipVerification"))
+ return CreateSkipVerificationSet();
+ else if (name.Equals("Internet"))
+ return CreateInternetSet();
+ else
+ return null;
+ }
+
+ private static PermissionSet CreateFullTrustSet() {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+
+ private static PermissionSet CreateNothingSet() {
+ return new PermissionSet(PermissionState.None);
+ }
+
+ private static PermissionSet CreateExecutionSet() {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+#pragma warning disable 618
+ permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
+#pragma warning restore 618
+ return permSet;
+ }
+
+ private static PermissionSet CreateSkipVerificationSet() {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+#pragma warning disable 618
+ permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SkipVerification));
+#pragma warning restore 618
+ return permSet;
+ }
+
+ private static PermissionSet CreateInternetSet() {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new FileDialogPermission(FileDialogPermissionAccess.Open));
+#pragma warning disable 618
+ permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
+#pragma warning restore 618
+ permSet.AddPermission(new UIPermission(UIPermissionWindow.SafeTopLevelWindows, UIPermissionClipboard.OwnClipboard));
+ return permSet;
+
+
+ }
+#endif // !FEATURE_CAS_POLICY
+ }
+}
diff --git a/src/mscorlib/src/System/Security/PermissionListSet.cs b/src/mscorlib/src/System/Security/PermissionListSet.cs
new file mode 100644
index 0000000000..7eb13a72cf
--- /dev/null
+++ b/src/mscorlib/src/System/Security/PermissionListSet.cs
@@ -0,0 +1,554 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: Holds state about A/G/R permissionsets in a callstack or appdomain
+** (Replacement for PermissionListSet)
+**
+=============================================================================*/
+
+namespace System.Security
+{
+ using System.Globalization;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ sealed internal class PermissionListSet
+ {
+ // Only internal (public) methods are creation methods and demand evaluation methods.
+ // Scroll down to the end to see them.
+ private PermissionSetTriple m_firstPermSetTriple;
+ private ArrayList m_permSetTriples;
+#if FEATURE_COMPRESSEDSTACK
+ private ArrayList m_zoneList;
+ private ArrayList m_originList;
+#endif // FEATURE_COMPRESSEDSTACK
+
+ internal PermissionListSet() {}
+
+ private void EnsureTriplesListCreated()
+ {
+ if (m_permSetTriples == null)
+ {
+ m_permSetTriples = new ArrayList();
+ if (m_firstPermSetTriple != null)
+ {
+ m_permSetTriples.Add(m_firstPermSetTriple);
+ m_firstPermSetTriple = null;
+ }
+ }
+ }
+
+#if FEATURE_PLS
+ [System.Security.SecurityCritical] // auto-generated
+ internal void UpdateDomainPLS (PermissionListSet adPLS) {
+ if (adPLS != null && adPLS.m_firstPermSetTriple != null)
+ UpdateDomainPLS(adPLS.m_firstPermSetTriple.GrantSet, adPLS.m_firstPermSetTriple.RefusedSet);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void UpdateDomainPLS (PermissionSet grantSet, PermissionSet deniedSet) {
+ Contract.Assert(m_permSetTriples == null, "m_permSetTriples != null");
+ if (m_firstPermSetTriple == null)
+ m_firstPermSetTriple = new PermissionSetTriple();
+
+ // update the grant and denied sets
+ m_firstPermSetTriple.UpdateGrant(grantSet);
+ m_firstPermSetTriple.UpdateRefused(deniedSet);
+ }
+#endif // FEATURE_PLS
+
+ private void Terminate(PermissionSetTriple currentTriple)
+ {
+ UpdateTripleListAndCreateNewTriple(currentTriple, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls)
+ {
+#if FEATURE_COMPRESSEDSTACK
+ this.UpdateZoneAndOrigin(pls);
+#endif // FEATURE_COMPRESSEDSTACK
+ this.UpdatePermissions(currentTriple, pls);
+ this.UpdateTripleListAndCreateNewTriple(currentTriple, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls)
+ {
+#if FEATURE_COMPRESSEDSTACK
+ this.UpdateZoneAndOrigin(pls);
+#endif // FEATURE_COMPRESSEDSTACK
+ return this.UpdatePermissions(currentTriple, pls);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd)
+ {
+#if FEATURE_COMPRESSEDSTACK
+ FrameSecurityDescriptorWithResolver fsdWithResolver = fsd as FrameSecurityDescriptorWithResolver;
+ if (fsdWithResolver != null)
+ {
+ return Update2(currentTriple, fsdWithResolver);
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+
+ // check imperative
+ bool fHalt = Update2(currentTriple, fsd, false);
+ if (!fHalt)
+ {
+ // then declarative
+ fHalt = Update2(currentTriple, fsd, true);
+ }
+ return fHalt;
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ [System.Security.SecurityCritical]
+ private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptorWithResolver fsdWithResolver)
+ {
+ System.Reflection.Emit.DynamicResolver resolver = fsdWithResolver.Resolver;
+ CompressedStack dynamicCompressedStack = resolver.GetSecurityContext();
+ dynamicCompressedStack.CompleteConstruction(null);
+ return this.Update(currentTriple, dynamicCompressedStack.PLS);
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative)
+ {
+ // Deny
+ PermissionSet deniedPset = fsd.GetDenials(fDeclarative);
+ if (deniedPset != null)
+ {
+ currentTriple.UpdateRefused(deniedPset);
+ }
+
+ // permit only
+ PermissionSet permitOnlyPset = fsd.GetPermitOnly(fDeclarative);
+ if (permitOnlyPset != null)
+ {
+ currentTriple.UpdateGrant(permitOnlyPset);
+ }
+
+ // Assert all possible
+ if (fsd.GetAssertAllPossible())
+ {
+ // If we have no grant set, it means that the only assembly we've seen on the stack so
+ // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the
+ // compressed stack is also FullTrust.
+ if (currentTriple.GrantSet == null)
+ currentTriple.GrantSet = PermissionSet.s_fullTrust;
+
+ UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
+ currentTriple.GrantSet = PermissionSet.s_fullTrust;
+ currentTriple.UpdateAssert(fsd.GetAssertions(fDeclarative));
+ return true;
+ }
+
+ // Assert
+ PermissionSet assertPset = fsd.GetAssertions(fDeclarative);
+ if (assertPset != null)
+ {
+ if (assertPset.IsUnrestricted())
+ {
+ // If we have no grant set, it means that the only assembly we've seen on the stack so
+ // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the
+ // compressed stack is also FullTrust.
+ if (currentTriple.GrantSet == null)
+ currentTriple.GrantSet = PermissionSet.s_fullTrust;
+
+ UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
+ currentTriple.GrantSet = PermissionSet.s_fullTrust;
+ currentTriple.UpdateAssert(assertPset);
+ return true;
+ }
+
+ PermissionSetTriple retTriple = currentTriple.UpdateAssert(assertPset);
+ if (retTriple != null)
+ {
+ EnsureTriplesListCreated();
+ m_permSetTriples.Add(retTriple);
+ }
+ }
+
+ return false;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r)
+ {
+#if FEATURE_COMPRESSEDSTACK
+ ZoneIdentityPermission z;
+ UrlIdentityPermission u;
+ currentTriple.UpdateGrant(in_g, out z, out u);
+ currentTriple.UpdateRefused(in_r);
+ AppendZoneOrigin(z, u);
+#else // !FEATURE_COMPRESEDSTACK
+ currentTriple.UpdateGrant(in_g);
+ currentTriple.UpdateRefused(in_r);
+#endif // FEATURE_COMPRESSEDSTACK
+ }
+
+ // Called from the VM for HG CS construction
+ [System.Security.SecurityCritical] // auto-generated
+ private void Update(PermissionSet in_g)
+ {
+ if (m_firstPermSetTriple == null)
+ m_firstPermSetTriple = new PermissionSetTriple();
+ Update(m_firstPermSetTriple, in_g, null);
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ private void UpdateZoneAndOrigin(PermissionListSet pls)
+ {
+ if (pls != null)
+ {
+ if (this.m_zoneList == null && pls.m_zoneList != null && pls.m_zoneList.Count > 0)
+ this.m_zoneList = new ArrayList();
+ UpdateArrayList(this.m_zoneList, pls.m_zoneList);
+ if (this.m_originList == null && pls.m_originList != null && pls.m_originList.Count > 0)
+ this.m_originList = new ArrayList();
+ UpdateArrayList(this.m_originList, pls.m_originList);
+ }
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls)
+ {
+ if (pls != null)
+ {
+ if (pls.m_permSetTriples != null)
+ {
+ // DCS has an AGR List. So we need to add the AGR List
+ UpdateTripleListAndCreateNewTriple(currentTriple,pls.m_permSetTriples);
+ }
+ else
+ {
+ // Common case: One AGR set
+
+ PermissionSetTriple tmp_psTriple = pls.m_firstPermSetTriple;
+ PermissionSetTriple retTriple;
+ // First try and update currentTriple. Return value indicates if we can stop construction
+ if (currentTriple.Update(tmp_psTriple, out retTriple))
+ return true;
+ // If we got a non-null retTriple, what it means is that compression failed,
+ // and we now have 2 triples to deal with: retTriple and currentTriple.
+ // retTriple has to be appended first. then currentTriple.
+ if (retTriple != null)
+ {
+ EnsureTriplesListCreated();
+ // we just created a new triple...add the previous one (returned) to the list
+ m_permSetTriples.Add(retTriple);
+ }
+ }
+ }
+ else
+ {
+ // pls can be null only outside the loop in CreateCompressedState
+ UpdateTripleListAndCreateNewTriple(currentTriple, null);
+ }
+
+
+ return false;
+
+ }
+
+
+ private void UpdateTripleListAndCreateNewTriple(PermissionSetTriple currentTriple, ArrayList tripleList)
+ {
+ if (!currentTriple.IsEmpty())
+ {
+ if (m_firstPermSetTriple == null && m_permSetTriples == null)
+ {
+ m_firstPermSetTriple = new PermissionSetTriple(currentTriple);
+ }
+ else
+ {
+ EnsureTriplesListCreated();
+ m_permSetTriples.Add(new PermissionSetTriple(currentTriple));
+ }
+ currentTriple.Reset();
+ }
+ if (tripleList != null)
+ {
+ EnsureTriplesListCreated();
+ m_permSetTriples.AddRange(tripleList);
+ }
+ }
+
+ private static void UpdateArrayList(ArrayList current, ArrayList newList)
+ {
+ if (newList == null)
+ return;
+
+ for(int i=0;i < newList.Count; i++)
+ {
+ if (!current.Contains(newList[i]))
+ current.Add(newList[i]);
+ }
+
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ private void AppendZoneOrigin(ZoneIdentityPermission z, UrlIdentityPermission u)
+ {
+
+ if (z != null)
+ {
+ if (m_zoneList == null)
+ m_zoneList = new ArrayList();
+ z.AppendZones(m_zoneList);
+ }
+
+ if (u != null)
+ {
+ if (m_originList == null)
+ m_originList = new ArrayList();
+ u.AppendOrigin(m_originList);
+ }
+ }
+
+[System.Security.SecurityCritical] // auto-generated
+[System.Runtime.InteropServices.ComVisible(true)]
+ // public(internal) interface begins...
+ // Creation functions
+ static internal PermissionListSet CreateCompressedState(CompressedStack cs, CompressedStack innerCS)
+ {
+ // function that completes the construction of the compressed stack if not done so already (bottom half for demand evaluation)
+
+ bool bHaltConstruction = false;
+ if (cs.CompressedStackHandle == null)
+ return null; // FT case or Security off
+
+ PermissionListSet pls = new PermissionListSet();
+ PermissionSetTriple currentTriple = new PermissionSetTriple();
+ int numDomains = CompressedStack.GetDCSCount(cs.CompressedStackHandle);
+ for (int i=numDomains-1; (i >= 0 && !bHaltConstruction) ; i--)
+ {
+ DomainCompressedStack dcs = CompressedStack.GetDomainCompressedStack(cs.CompressedStackHandle, i);
+ if (dcs == null)
+ continue; // we hit a FT Domain
+ if (dcs.PLS == null)
+ {
+ // We failed on some DCS
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic")));
+ }
+ pls.UpdateZoneAndOrigin(dcs.PLS);
+ pls.Update(currentTriple, dcs.PLS);
+ bHaltConstruction = dcs.ConstructionHalted;
+ }
+ if (!bHaltConstruction)
+ {
+ PermissionListSet tmp_pls = null;
+ // Construction did not halt.
+ if (innerCS != null)
+ {
+ innerCS.CompleteConstruction(null);
+ tmp_pls = innerCS.PLS;
+ }
+ pls.Terminate(currentTriple, tmp_pls);
+ }
+ else
+ {
+ pls.Terminate(currentTriple);
+ }
+
+ return pls;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction)
+ {
+ PermissionListSet pls = new PermissionListSet();
+ PermissionSetTriple currentTriple = new PermissionSetTriple();
+
+ PermissionSet tmp_g, tmp_r;
+ // Construct the descriptor list
+ int descCount = DomainCompressedStack.GetDescCount(unmanagedDCS);
+ bHaltConstruction = false;
+ for(int i=0; (i < descCount && !bHaltConstruction); i++)
+ {
+ FrameSecurityDescriptor fsd;
+ Assembly assembly;
+ if (DomainCompressedStack.GetDescriptorInfo(unmanagedDCS, i, out tmp_g, out tmp_r, out assembly, out fsd))
+ {
+ // Got an FSD
+ bHaltConstruction = pls.Update(currentTriple, fsd);
+ }
+ else
+ {
+ pls.Update(currentTriple, tmp_g, tmp_r);
+ }
+
+ }
+ if (!bHaltConstruction)
+ {
+ // domain
+ if (!DomainCompressedStack.IgnoreDomain(unmanagedDCS))
+ {
+ DomainCompressedStack.GetDomainPermissionSets(unmanagedDCS, out tmp_g, out tmp_r);
+ pls.Update(currentTriple, tmp_g, tmp_r);
+ }
+ }
+ pls.Terminate(currentTriple);
+
+
+ // return the created object
+ return pls;
+
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ static internal PermissionListSet CreateCompressedState_HG()
+ {
+ PermissionListSet pls = new PermissionListSet();
+ CompressedStack.GetHomogeneousPLS(pls);
+ return pls;
+ }
+#endif // #if FEATURE_COMPRESSEDSTACK
+ // Private Demand evaluation functions - only called from the VM
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemandNoThrow(CodeAccessPermission demand)
+ {
+ // AppDomain permissions - no asserts. So there should only be one triple to work with
+ Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
+
+
+
+ PermissionToken permToken = null;
+ if (demand != null)
+ permToken = PermissionToken.GetToken(demand);
+
+ return m_firstPermSetTriple.CheckDemandNoThrow(demand, permToken);
+
+
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemandNoThrow(PermissionSet pSet)
+ {
+ // AppDomain permissions - no asserts. So there should only be one triple to work with
+ Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
+
+
+ return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet);
+ }
+
+ // Demand evauation functions
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
+ {
+ bool bRet = SecurityRuntime.StackContinue;
+ if (m_permSetTriples != null)
+ {
+ for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
+ {
+ PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
+ bRet = psTriple.CheckDemand(demand, permToken, rmh);
+ }
+ }
+ else if (m_firstPermSetTriple != null)
+ {
+ bRet = m_firstPermSetTriple.CheckDemand(demand, permToken, rmh);
+ }
+
+ return bRet;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand(PermissionSet pset , RuntimeMethodHandleInternal rmh)
+ {
+ PermissionSet unused;
+ CheckSetDemandWithModification(pset, out unused, rmh);
+ return SecurityRuntime.StackHalt; // CS demand check always terminates the stackwalk
+ }
+
+ [System.Security.SecurityCritical]
+ internal bool CheckSetDemandWithModification(PermissionSet pset, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh)
+ {
+ bool bRet = SecurityRuntime.StackContinue;
+ PermissionSet demandSet = pset;
+ alteredDemandSet = null;
+ if (m_permSetTriples != null)
+ {
+ for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
+ {
+ PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
+ bRet = psTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
+ if (alteredDemandSet != null)
+ demandSet = alteredDemandSet;
+ }
+ }
+ else if (m_firstPermSetTriple != null)
+ {
+ bRet = m_firstPermSetTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
+ }
+
+ return bRet;
+ }
+
+ /// <summary>
+ /// Check to see if the PLS satisfies a demand for the special permissions encoded in flags
+ /// </summary>
+ /// <param name="flags">set of flags to check (See PermissionType)</param>
+ [System.Security.SecurityCritical] // auto-generated
+ private bool CheckFlags(int flags)
+ {
+ Contract.Assert(flags != 0, "Invalid permission flag demand");
+
+ bool check = true;
+
+ if (m_permSetTriples != null)
+ {
+ for (int i = 0; i < m_permSetTriples.Count && check && flags != 0; i++)
+ {
+ check &= ((PermissionSetTriple)m_permSetTriples[i]).CheckFlags(ref flags);
+ }
+ }
+ else if (m_firstPermSetTriple != null)
+ {
+ check = m_firstPermSetTriple.CheckFlags(ref flags);
+ }
+
+ return check;
+ }
+
+ /// <summary>
+ /// Demand which succeeds if either a set of special permissions or a permission set is granted
+ /// to the call stack
+ /// </summary>
+ /// <param name="flags">set of flags to check (See PermissionType)</param>
+ /// <param name="grantSet">alternate permission set to check</param>
+ [System.Security.SecurityCritical] // auto-generated
+ internal void DemandFlagsOrGrantSet(int flags, PermissionSet grantSet)
+ {
+ if (CheckFlags(flags))
+ return;
+
+ CheckSetDemand(grantSet, RuntimeMethodHandleInternal.EmptyHandle);
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList, PermissionToken zoneToken, PermissionToken originToken)
+ {
+ if (m_zoneList != null)
+ zoneList.AddRange(m_zoneList);
+ if (m_originList != null)
+ originList.AddRange(m_originList);
+ }
+#endif
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/PermissionSet.cs b/src/mscorlib/src/System/Security/PermissionSet.cs
new file mode 100644
index 0000000000..e36f0752ad
--- /dev/null
+++ b/src/mscorlib/src/System/Security/PermissionSet.cs
@@ -0,0 +1,2641 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security {
+ using System;
+ using System.Threading;
+ using System.Security.Util;
+ using System.Collections;
+ using System.IO;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Security.Policy;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using BindingFlags = System.Reflection.BindingFlags;
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal enum SpecialPermissionSetFlag
+ {
+ // These also appear in clr/src/vm/permset.h
+ Regular = 0,
+ NoSet = 1,
+ EmptySet = 2,
+ SkipVerification = 3
+ }
+
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+#if !FEATURE_CORECLR
+ [StrongNameIdentityPermissionAttribute(SecurityAction.InheritanceDemand, Name = "mscorlib", PublicKey = "0x" + AssemblyRef.EcmaPublicKeyFull)]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class PermissionSet : ISecurityEncodable, ICollection, IStackWalk
+#if FEATURE_SERIALIZATION
+ , IDeserializationCallback
+#endif
+ {
+#if _DEBUG
+ internal static readonly bool debug;
+#endif
+
+ [System.Diagnostics.Conditional( "_DEBUG" )]
+ private static void DEBUG_WRITE(String str) {
+ #if _DEBUG
+ if (debug) Console.WriteLine(str);
+ #endif
+ }
+
+ [System.Diagnostics.Conditional( "_DEBUG" )]
+ private static void DEBUG_COND_WRITE(bool exp, String str)
+ {
+ #if _DEBUG
+ if (debug && (exp)) Console.WriteLine(str);
+ #endif
+ }
+
+ [System.Diagnostics.Conditional( "_DEBUG" )]
+ private static void DEBUG_PRINTSTACK(Exception e)
+ {
+ #if _DEBUG
+ if (debug) Console.WriteLine((e).StackTrace);
+ #endif
+ }
+
+ // These members are accessed from EE using their hardcoded offset.
+ // Please update the PermissionSetObject in object.h if you make any changes
+ // to the fields here. !dumpobj will show the field layout
+
+ // First the fields that are serialized x-appdomain (for perf reasons)
+ private bool m_Unrestricted;
+ [OptionalField(VersionAdded = 2)]
+ private bool m_allPermissionsDecoded = false;
+
+ [OptionalField(VersionAdded = 2)]
+ internal TokenBasedSet m_permSet = null;
+
+ // This is a workaround so that SQL can operate under default policy without actually
+ // granting permissions in assemblies that they disallow.
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_ignoreTypeLoadFailures = false;
+
+ // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the PermissionSet
+ [OptionalField(VersionAdded = 2)]
+ private String m_serializedPermissionSet;
+
+ [NonSerialized] private bool m_CheckedForNonCas;
+ [NonSerialized] private bool m_ContainsCas;
+ [NonSerialized] private bool m_ContainsNonCas;
+
+ // only used during non X-AD serialization to save the m_permSet value (which we dont want serialized)
+ [NonSerialized] private TokenBasedSet m_permSetSaved;
+
+ // Following 4 fields are used only for serialization compat purposes: DO NOT USE THESE EVER!
+#pragma warning disable 169
+ private bool readableonly;
+ private TokenBasedSet m_unrestrictedPermSet;
+ private TokenBasedSet m_normalPermSet;
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_canUnrestrictedOverride;
+#pragma warning restore 169
+ // END: Serialization-only fields
+
+ internal static readonly PermissionSet s_fullTrust = new PermissionSet( true );
+
+#if FEATURE_REMOTING
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ Reset();
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if (m_serializedPermissionSet != null)
+ {
+ // Whidbey non X-AD case
+ FromXml(SecurityElement.FromString(m_serializedPermissionSet));
+ }
+ else if (m_normalPermSet != null)
+ {
+ // Everett non X-AD case
+ m_permSet = m_normalPermSet.SpecialUnion(m_unrestrictedPermSet);
+ }
+ else if (m_unrestrictedPermSet != null)
+ {
+ // Everett non X-AD case
+ m_permSet = m_unrestrictedPermSet.SpecialUnion(m_normalPermSet);
+ }
+
+ m_serializedPermissionSet = null;
+ m_normalPermSet = null;
+ m_unrestrictedPermSet = null;
+
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermissionSet = ToString(); // For v2.x and beyond
+ if (m_permSet != null)
+ m_permSet.SpecialSplit(ref m_unrestrictedPermSet, ref m_normalPermSet, m_ignoreTypeLoadFailures);
+ m_permSetSaved = m_permSet;
+ m_permSet = null;
+ }
+ }
+#endif // !FEATURE_REMOTING
+
+#if FEATURE_REMOTING || _DEBUG
+ [OnSerialized]
+ private void OnSerialized(StreamingContext context)
+ {
+#if FEATURE_REMOTING
+ if ((context.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermissionSet = null;
+ m_permSet = m_permSetSaved;
+ m_permSetSaved = null;
+ m_unrestrictedPermSet = null;
+ m_normalPermSet = null;
+ }
+#else // !FEATURE_REMOTING
+ Contract.Assert(false, "PermissionSet does not support serialization on CoreCLR");
+#endif // !FEATURE_REMOTING
+ }
+#endif // FEATURE_REMOTING || _DEBUG
+
+ internal PermissionSet()
+ {
+ Reset();
+ m_Unrestricted = true;
+ }
+
+ internal PermissionSet(bool fUnrestricted)
+ : this()
+ {
+ SetUnrestricted(fUnrestricted);
+ }
+
+ public PermissionSet(PermissionState state)
+ : this()
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ SetUnrestricted( true );
+ }
+ else if (state == PermissionState.None)
+ {
+ SetUnrestricted( false );
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public PermissionSet(PermissionSet permSet)
+ : this()
+ {
+ if (permSet == null)
+ {
+ Reset();
+ return;
+ }
+
+ m_Unrestricted = permSet.m_Unrestricted;
+ m_CheckedForNonCas = permSet.m_CheckedForNonCas;
+ m_ContainsCas = permSet.m_ContainsCas;
+ m_ContainsNonCas = permSet.m_ContainsNonCas;
+ m_ignoreTypeLoadFailures = permSet.m_ignoreTypeLoadFailures;
+
+ if (permSet.m_permSet != null)
+ {
+ m_permSet = new TokenBasedSet(permSet.m_permSet);
+
+ // now deep copy all permissions in set
+ for (int i = m_permSet.GetStartingIndex(); i <= m_permSet.GetMaxUsedIndex(); i++)
+ {
+ Object obj = m_permSet.GetItem(i);
+ IPermission perm = obj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory elem = obj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+ if (perm != null)
+ {
+ m_permSet.SetItem(i, perm.Copy());
+ }
+#if FEATURE_CAS_POLICY
+ else if (elem != null)
+ {
+ m_permSet.SetItem(i, elem.Copy());
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+ }
+ }
+
+ public virtual void CopyTo(Array array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException( "array" );
+ Contract.EndContractBlock();
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this);
+
+ while (enumerator.MoveNext())
+ {
+ array.SetValue(enumerator.Current , index++ );
+ }
+ }
+
+
+ // private constructor that doesn't create any token based sets
+ private PermissionSet( Object trash, Object junk )
+ {
+ m_Unrestricted = false;
+ }
+
+
+ // Returns an object appropriate for synchronizing access to this
+ // Array.
+ public virtual Object SyncRoot
+ { get { return this; } }
+
+ // Is this Array synchronized (i.e., thread-safe)? If you want a synchronized
+ // collection, you can use SyncRoot as an object to synchronize your
+ // collection with. You could also call GetSynchronized()
+ // to get a synchronized wrapper around the Array.
+ public virtual bool IsSynchronized
+ { get { return false; } }
+
+ // Is this Collection ReadOnly?
+ public virtual bool IsReadOnly
+ { get {return false; } }
+
+ // Reinitializes all state in PermissionSet - DO NOT null-out m_serializedPermissionSet
+ internal void Reset()
+ {
+ m_Unrestricted = false;
+ m_allPermissionsDecoded = true;
+ m_permSet = null;
+
+ m_ignoreTypeLoadFailures = false;
+
+ m_CheckedForNonCas = false;
+ m_ContainsCas = false;
+ m_ContainsNonCas = false;
+ m_permSetSaved = null;
+
+
+ }
+
+ internal void CheckSet()
+ {
+ if (this.m_permSet == null)
+ this.m_permSet = new TokenBasedSet();
+ }
+
+ public bool IsEmpty()
+ {
+ if (m_Unrestricted)
+ return false;
+
+ if (m_permSet == null || m_permSet.FastIsEmpty())
+ return true;
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this);
+
+ while (enumerator.MoveNext())
+ {
+ IPermission perm = (IPermission)enumerator.Current;
+
+ if (!perm.IsSubsetOf( null ))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ internal bool FastIsEmpty()
+ {
+ if (m_Unrestricted)
+ return false;
+
+ if (m_permSet == null || m_permSet.FastIsEmpty())
+ return true;
+
+ return false;
+ }
+
+ public virtual int Count
+ {
+ get
+ {
+ int count = 0;
+
+ if (m_permSet != null)
+ count += m_permSet.GetCount();
+
+ return count;
+ }
+ }
+
+ internal IPermission GetPermission(int index)
+ {
+ if (m_permSet == null)
+ return null;
+ Object obj = m_permSet.GetItem( index );
+ if (obj == null)
+ return null;
+ IPermission perm = obj as IPermission;
+ if (perm != null)
+ return perm;
+#if FEATURE_CAS_POLICY
+ perm = CreatePermission(obj, index);
+#endif // FEATURE_CAS_POLICY
+ if (perm == null)
+ return null;
+ Contract.Assert( PermissionToken.IsTokenProperlyAssigned( perm, PermissionToken.GetToken( perm ) ),
+ "PermissionToken was improperly assigned" );
+ Contract.Assert( PermissionToken.GetToken( perm ).m_index == index,
+ "Assigning permission to incorrect index in tokenbasedset" );
+ return perm;
+ }
+
+ internal IPermission GetPermission(PermissionToken permToken)
+ {
+ if (permToken == null)
+ return null;
+
+ return GetPermission( permToken.m_index );
+ }
+
+ internal IPermission GetPermission( IPermission perm )
+ {
+ if (perm == null)
+ return null;
+
+ return GetPermission(PermissionToken.GetToken( perm ));
+ }
+
+#if FEATURE_CAS_POLICY
+ public IPermission GetPermission(Type permClass)
+ {
+ return GetPermissionImpl(permClass);
+ }
+
+ protected virtual IPermission GetPermissionImpl(Type permClass)
+ {
+ if (permClass == null)
+ return null;
+
+ return GetPermission(PermissionToken.FindToken(permClass));
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public IPermission SetPermission(IPermission perm)
+ {
+ return SetPermissionImpl(perm);
+ }
+
+ // SetPermission overwrites a permission in a permissionset.
+ protected virtual IPermission SetPermissionImpl(IPermission perm)
+ {
+ // can't get token if perm is null
+ if (perm == null)
+ return null;
+
+ PermissionToken permToken = PermissionToken.GetToken(perm);
+
+ if ((permToken.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ // SetPermission Makes the Permission "Restricted"
+ m_Unrestricted = false;
+ }
+
+ CheckSet();
+
+ IPermission currPerm = GetPermission( permToken.m_index );
+
+ m_CheckedForNonCas = false;
+
+ // Should we copy here?
+ m_permSet.SetItem( permToken.m_index, perm );
+ return perm;
+ }
+
+ public IPermission AddPermission(IPermission perm)
+ {
+ return AddPermissionImpl(perm);
+ }
+
+ protected virtual IPermission AddPermissionImpl(IPermission perm)
+ {
+ // can't get token if perm is null
+ if (perm == null)
+ return null;
+
+ m_CheckedForNonCas = false;
+
+ // If the permission set is unrestricted, then return an unrestricted instance
+ // of perm.
+
+ PermissionToken permToken = PermissionToken.GetToken(perm);
+
+ if (this.IsUnrestricted() && ((permToken.m_type & PermissionTokenType.IUnrestricted) != 0))
+ {
+ Type perm_type = perm.GetType();
+ Object[] objs = new Object[1];
+ objs[0] = PermissionState.Unrestricted;
+ return (IPermission) Activator.CreateInstance(perm_type, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, objs, null );
+ }
+
+ CheckSet();
+ IPermission currPerm = GetPermission(permToken.m_index);
+
+ // If a Permission exists in this slot, then union it with perm
+ // Otherwise, just add perm.
+
+ if (currPerm != null) {
+ IPermission ip_union = currPerm.Union(perm);
+ m_permSet.SetItem( permToken.m_index, ip_union );
+ return ip_union;
+ } else {
+ // Should we copy here?
+ m_permSet.SetItem( permToken.m_index, perm );
+ return perm;
+ }
+
+ }
+
+ private IPermission RemovePermission( int index )
+ {
+ IPermission perm = GetPermission(index);
+ if (perm == null)
+ return null;
+ return (IPermission)m_permSet.RemoveItem( index ); // this cast is safe because the call to GetPermission will guarantee it is an IPermission
+ }
+
+#if FEATURE_CAS_POLICY
+ public IPermission RemovePermission(Type permClass)
+ {
+ return RemovePermissionImpl(permClass);
+ }
+
+ protected virtual IPermission RemovePermissionImpl(Type permClass)
+ {
+ if (permClass == null)
+ {
+ return null;
+ }
+
+ PermissionToken permToken = PermissionToken.FindToken(permClass);
+ if (permToken == null)
+ {
+ return null;
+ }
+
+ return RemovePermission(permToken.m_index);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // Make this internal soon.
+ internal void SetUnrestricted(bool unrestricted)
+ {
+ m_Unrestricted = unrestricted;
+ if (unrestricted)
+ {
+ // if this is to be an unrestricted permset, null the m_permSet member
+ m_permSet = null;
+ }
+ }
+
+ public bool IsUnrestricted()
+ {
+ return m_Unrestricted;
+ }
+
+ internal enum IsSubsetOfType
+ {
+ Normal,
+ CheckDemand,
+ CheckPermitOnly,
+ CheckAssertion,
+ }
+
+ internal bool IsSubsetOfHelper(PermissionSet target, IsSubsetOfType type, out IPermission firstPermThatFailed, bool ignoreNonCas)
+ {
+ #if _DEBUG
+ if (debug)
+ DEBUG_WRITE("IsSubsetOf\n" +
+ "Other:\n" +
+ (target == null ? "<null>" : target.ToString()) +
+ "\nMe:\n" +
+ ToString());
+ #endif
+
+ firstPermThatFailed = null;
+ if (target == null || target.FastIsEmpty())
+ {
+ if(this.IsEmpty())
+ return true;
+ else
+ {
+ firstPermThatFailed = GetFirstPerm();
+ return false;
+ }
+ }
+ else if (this.IsUnrestricted() && !target.IsUnrestricted())
+ return false;
+ else if (this.m_permSet == null)
+ return true;
+ else
+ {
+ target.CheckSet();
+
+ for (int i = m_permSet.GetStartingIndex(); i <= this.m_permSet.GetMaxUsedIndex(); ++i)
+ {
+ IPermission thisPerm = this.GetPermission(i);
+ if (thisPerm == null || thisPerm.IsSubsetOf(null))
+ continue;
+
+ IPermission targetPerm = target.GetPermission(i);
+#if _DEBUG
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ Contract.Assert(targetPerm == null || (token.m_type & PermissionTokenType.DontKnow) == 0, "Token not properly initialized");
+#endif
+
+ if (target.m_Unrestricted)
+ continue;
+
+ // targetPerm can be null here, but that is fine since it thisPerm is a subset
+ // of empty/null then we can continue in the loop.
+ CodeAccessPermission cap = thisPerm as CodeAccessPermission;
+ if(cap == null)
+ {
+ if (!ignoreNonCas && !thisPerm.IsSubsetOf( targetPerm ))
+ {
+ firstPermThatFailed = thisPerm;
+ return false;
+ }
+ }
+ else
+ {
+ firstPermThatFailed = thisPerm;
+ switch(type)
+ {
+ case IsSubsetOfType.Normal:
+ if (!thisPerm.IsSubsetOf( targetPerm ))
+ return false;
+ break;
+ case IsSubsetOfType.CheckDemand:
+ if (!cap.CheckDemand( (CodeAccessPermission)targetPerm ))
+ return false;
+ break;
+ case IsSubsetOfType.CheckPermitOnly:
+ if (!cap.CheckPermitOnly( (CodeAccessPermission)targetPerm ))
+ return false;
+ break;
+ case IsSubsetOfType.CheckAssertion:
+ if (!cap.CheckAssert( (CodeAccessPermission)targetPerm ))
+ return false;
+ break;
+ }
+ firstPermThatFailed = null;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ public bool IsSubsetOf(PermissionSet target)
+ {
+ IPermission perm;
+ return IsSubsetOfHelper(target, IsSubsetOfType.Normal, out perm, false);
+ }
+
+ internal bool CheckDemand(PermissionSet target, out IPermission firstPermThatFailed)
+ {
+ return IsSubsetOfHelper(target, IsSubsetOfType.CheckDemand, out firstPermThatFailed, true);
+ }
+
+ internal bool CheckPermitOnly(PermissionSet target, out IPermission firstPermThatFailed)
+ {
+ return IsSubsetOfHelper(target, IsSubsetOfType.CheckPermitOnly, out firstPermThatFailed, true);
+ }
+
+ internal bool CheckAssertion(PermissionSet target)
+ {
+ IPermission perm;
+ return IsSubsetOfHelper(target, IsSubsetOfType.CheckAssertion, out perm, true);
+ }
+
+ internal bool CheckDeny(PermissionSet deniedSet, out IPermission firstPermThatFailed)
+ {
+ firstPermThatFailed = null;
+ if (deniedSet == null || deniedSet.FastIsEmpty() || this.FastIsEmpty())
+ return true;
+
+ if(this.m_Unrestricted && deniedSet.m_Unrestricted)
+ return false;
+
+ CodeAccessPermission permThis, permThat;
+ PermissionSetEnumeratorInternal enumThis = new PermissionSetEnumeratorInternal(this);
+
+ while (enumThis.MoveNext())
+ {
+ permThis = enumThis.Current as CodeAccessPermission;
+ if(permThis == null || permThis.IsSubsetOf(null))
+ continue; // ignore non-CAS permissions in the grant set.
+ if (deniedSet.m_Unrestricted)
+ {
+ firstPermThatFailed = permThis;
+ return false;
+ }
+ permThat = (CodeAccessPermission)deniedSet.GetPermission(enumThis.GetCurrentIndex());
+ if (!permThis.CheckDeny(permThat))
+ {
+ firstPermThatFailed = permThis;
+ return false;
+ }
+ }
+ if(this.m_Unrestricted)
+ {
+ PermissionSetEnumeratorInternal enumThat = new PermissionSetEnumeratorInternal(deniedSet);
+ while (enumThat.MoveNext())
+ {
+ if(enumThat.Current is IPermission)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ internal void CheckDecoded( CodeAccessPermission demandedPerm, PermissionToken tokenDemandedPerm )
+ {
+ Contract.Assert( demandedPerm != null, "Expected non-null value" );
+
+ if (this.m_allPermissionsDecoded || this.m_permSet == null)
+ return;
+
+ if (tokenDemandedPerm == null)
+ tokenDemandedPerm = PermissionToken.GetToken( demandedPerm );
+
+ Contract.Assert( tokenDemandedPerm != null, "Unable to find token for demanded permission" );
+
+ CheckDecoded( tokenDemandedPerm.m_index );
+ }
+
+ internal void CheckDecoded( int index )
+ {
+ if (this.m_allPermissionsDecoded || this.m_permSet == null)
+ return;
+
+ GetPermission(index);
+ }
+
+ internal void CheckDecoded(PermissionSet demandedSet)
+ {
+ Contract.Assert(demandedSet != null, "Expected non-null value");
+
+ if (this.m_allPermissionsDecoded || this.m_permSet == null)
+ return;
+
+ PermissionSetEnumeratorInternal enumerator = demandedSet.GetEnumeratorInternal();
+
+ while (enumerator.MoveNext())
+ {
+ CheckDecoded(enumerator.GetCurrentIndex());
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ static internal void SafeChildAdd( SecurityElement parent, ISecurityElementFactory child, bool copy )
+ {
+ if (child == parent)
+ return;
+ if (child.GetTag().Equals( "IPermission" ) || child.GetTag().Equals( "Permission" ))
+ {
+ parent.AddChild( child );
+ }
+ else if (parent.Tag.Equals( child.GetTag() ))
+ {
+ Contract.Assert( child is SecurityElement, "SecurityElement expected" );
+ SecurityElement elChild = (SecurityElement)child;
+ Contract.Assert( elChild.InternalChildren != null,
+ "Non-permission elements should have children" );
+
+ for (int i = 0; i < elChild.InternalChildren.Count; ++i)
+ {
+ ISecurityElementFactory current = (ISecurityElementFactory)elChild.InternalChildren[i];
+ Contract.Assert( !current.GetTag().Equals( parent.Tag ),
+ "Illegal to insert a like-typed element" );
+ parent.AddChildNoDuplicates( current );
+ }
+ }
+ else
+ {
+ parent.AddChild( (ISecurityElementFactory)(copy ? child.Copy() : child) );
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ internal void InplaceIntersect( PermissionSet other )
+ {
+ Exception savedException = null;
+
+ m_CheckedForNonCas = false;
+
+ if (this == other)
+ return;
+
+ if (other == null || other.FastIsEmpty())
+ {
+ // If the other is empty or null, make this empty.
+ Reset();
+ return;
+ }
+
+ if (this.FastIsEmpty())
+ return;
+
+ int maxMax = this.m_permSet == null ? -1 : this.m_permSet.GetMaxUsedIndex();
+ int otherMax = other.m_permSet == null ? -1 : other.m_permSet.GetMaxUsedIndex();
+
+ if (this.IsUnrestricted() && maxMax < otherMax)
+ {
+ maxMax = otherMax;
+ this.CheckSet();
+ }
+
+ if (other.IsUnrestricted())
+ {
+ other.CheckSet();
+ }
+
+ for (int i = 0; i <= maxMax; ++i)
+ {
+ Object thisObj = this.m_permSet.GetItem( i );
+ IPermission thisPerm = thisObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ Object otherObj = other.m_permSet.GetItem( i );
+ IPermission otherPerm = otherObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ if (thisObj == null && otherObj == null)
+ continue;
+
+#if FEATURE_CAS_POLICY
+ if (thisElem != null && otherElem != null)
+ {
+ // If we already have an intersection node, just add another child
+ if (thisElem.GetTag().Equals( s_str_PermissionIntersection ) ||
+ thisElem.GetTag().Equals( s_str_PermissionUnrestrictedIntersection ))
+ {
+ Contract.Assert( thisElem is SecurityElement, "SecurityElement expected" );
+ SafeChildAdd( (SecurityElement)thisElem, otherElem, true );
+ }
+ // If either set is unrestricted, intersect the nodes unrestricted
+ else
+ {
+ bool copyOther = true;
+ if (this.IsUnrestricted())
+ {
+ SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ newElemUU.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElemUU, thisElem, false );
+ thisElem = newElemUU;
+ }
+ if (other.IsUnrestricted())
+ {
+ SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ newElemUU.AddAttribute( "class", otherElem.Attribute( "class" ) );
+ SafeChildAdd( newElemUU, otherElem, true );
+ otherElem = newElemUU;
+ copyOther = false;
+ }
+
+ SecurityElement newElem = new SecurityElement( s_str_PermissionIntersection );
+ newElem.AddAttribute( "class", thisElem.Attribute( "class" ) );
+
+ SafeChildAdd( newElem, thisElem, false );
+ SafeChildAdd( newElem, otherElem, copyOther );
+ this.m_permSet.SetItem( i, newElem );
+ }
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisObj == null)
+ {
+ // There is no object in <this>, so intersection is empty except for IUnrestrictedPermissions
+ if (this.IsUnrestricted())
+ {
+#if FEATURE_CAS_POLICY
+ if (otherElem != null)
+ {
+ SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection );
+ newElem.AddAttribute( "class", otherElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, otherElem, true );
+ this.m_permSet.SetItem( i, newElem );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if ((token.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ this.m_permSet.SetItem( i, otherPerm.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+ }
+ }
+ else if (otherObj == null)
+ {
+ if (other.IsUnrestricted())
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ {
+ SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection );
+ newElem.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, thisElem, false );
+ this.m_permSet.SetItem( i, newElem );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if ((token.m_type & PermissionTokenType.IUnrestricted) == 0)
+ this.m_permSet.SetItem( i, null );
+ }
+ }
+ else
+ {
+ this.m_permSet.SetItem( i, null );
+ }
+ }
+ else
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ thisPerm = this.CreatePermission(thisElem, i);
+ if (otherElem != null)
+ otherPerm = other.CreatePermission(otherElem, i);
+#endif // FEATURE_CAS_POLICY
+
+ try
+ {
+ IPermission intersectPerm;
+ if (thisPerm == null)
+ intersectPerm = otherPerm;
+ else if(otherPerm == null)
+ intersectPerm = thisPerm;
+ else
+ intersectPerm = thisPerm.Intersect( otherPerm );
+ this.m_permSet.SetItem( i, intersectPerm );
+ }
+ catch (Exception e)
+ {
+ if (savedException == null)
+ savedException = e;
+ }
+ }
+ }
+
+ this.m_Unrestricted = this.m_Unrestricted && other.m_Unrestricted;
+
+ if (savedException != null)
+ throw savedException;
+ }
+
+ public PermissionSet Intersect(PermissionSet other)
+ {
+ if (other == null || other.FastIsEmpty() || this.FastIsEmpty())
+ {
+ return null;
+ }
+
+ int thisMax = this.m_permSet == null ? -1 : this.m_permSet.GetMaxUsedIndex();
+ int otherMax = other.m_permSet == null ? -1 : other.m_permSet.GetMaxUsedIndex();
+ int minMax = thisMax < otherMax ? thisMax : otherMax;
+
+ if (this.IsUnrestricted() && minMax < otherMax)
+ {
+ minMax = otherMax;
+ this.CheckSet();
+ }
+
+ if (other.IsUnrestricted() && minMax < thisMax)
+ {
+ minMax = thisMax;
+ other.CheckSet();
+ }
+
+ PermissionSet pset = new PermissionSet( false );
+
+ if (minMax > -1)
+ {
+ pset.m_permSet = new TokenBasedSet();
+ }
+
+ for (int i = 0; i <= minMax; ++i)
+ {
+ Object thisObj = this.m_permSet.GetItem( i );
+ IPermission thisPerm = thisObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ Object otherObj = other.m_permSet.GetItem( i );
+ IPermission otherPerm = otherObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ if (thisObj == null && otherObj == null)
+ continue;
+
+#if FEATURE_CAS_POLICY
+ if (thisElem != null && otherElem != null)
+ {
+ bool copyOther = true;
+ bool copyThis = true;
+ SecurityElement newElem = new SecurityElement( s_str_PermissionIntersection );
+ newElem.AddAttribute( "class", otherElem.Attribute( "class" ) );
+ if (this.IsUnrestricted())
+ {
+ SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ newElemUU.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElemUU, thisElem, true );
+ copyThis = false;
+ thisElem = newElemUU;
+ }
+ if (other.IsUnrestricted())
+ {
+ SecurityElement newElemUU = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ newElemUU.AddAttribute( "class", otherElem.Attribute( "class" ) );
+ SafeChildAdd( newElemUU, otherElem, true );
+ copyOther = false;
+ otherElem = newElemUU;
+ }
+
+ SafeChildAdd( newElem, otherElem, copyOther );
+ SafeChildAdd( newElem, thisElem, copyThis );
+ pset.m_permSet.SetItem( i, newElem );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisObj == null)
+ {
+ if (this.m_Unrestricted)
+ {
+#if FEATURE_CAS_POLICY
+ if (otherElem != null)
+ {
+ SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection );
+ newElem.AddAttribute( "class", otherElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, otherElem, true );
+ pset.m_permSet.SetItem( i, newElem );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (otherPerm != null)
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if ((token.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ pset.m_permSet.SetItem( i, otherPerm.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+ }
+ }
+ else if (otherObj == null)
+ {
+ if (other.m_Unrestricted)
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ {
+ SecurityElement newElem = new SecurityElement( s_str_PermissionUnrestrictedIntersection );
+ newElem.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, thisElem, true );
+ pset.m_permSet.SetItem( i, newElem );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisPerm != null)
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if ((token.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ pset.m_permSet.SetItem( i, thisPerm.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+ }
+ }
+ else
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ thisPerm = this.CreatePermission(thisElem, i);
+ if (otherElem != null)
+ otherPerm = other.CreatePermission(otherElem, i);
+#endif // FEATURE_CAS_POLICY
+
+ IPermission intersectPerm;
+ if (thisPerm == null)
+ intersectPerm = otherPerm;
+ else if(otherPerm == null)
+ intersectPerm = thisPerm;
+ else
+ intersectPerm = thisPerm.Intersect( otherPerm );
+ pset.m_permSet.SetItem( i, intersectPerm );
+ Contract.Assert( intersectPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+
+ pset.m_Unrestricted = this.m_Unrestricted && other.m_Unrestricted;
+ if (pset.FastIsEmpty())
+ return null;
+ else
+ return pset;
+ }
+
+ internal void InplaceUnion( PermissionSet other )
+ {
+ // Unions the "other" PermissionSet into this one. It can be optimized to do less copies than
+ // need be done by the traditional union (and we don't have to create a new PermissionSet).
+
+ if (this == other)
+ return;
+
+ // Quick out conditions, union doesn't change this PermissionSet
+ if (other == null || other.FastIsEmpty())
+ return;
+
+
+ m_CheckedForNonCas = false;
+
+
+
+
+ this.m_Unrestricted = this.m_Unrestricted || other.m_Unrestricted;
+
+ if (this.m_Unrestricted)
+ {
+ // if the result of Union is unrestricted permset, null the m_permSet member
+ this.m_permSet = null;
+ return;
+ }
+
+
+ // If we reach here, result of Union is not unrestricted
+ // We have to union "normal" permission no matter what now.
+ int maxMax = -1;
+ if (other.m_permSet != null)
+ {
+ maxMax = other.m_permSet.GetMaxUsedIndex();
+ this.CheckSet();
+ }
+ // Save exceptions until the end
+ Exception savedException = null;
+
+ for (int i = 0; i <= maxMax; ++i)
+ {
+ Object thisObj = this.m_permSet.GetItem( i );
+ IPermission thisPerm = thisObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ Object otherObj = other.m_permSet.GetItem( i );
+ IPermission otherPerm = otherObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ if (thisObj == null && otherObj == null)
+ continue;
+
+#if FEATURE_CAS_POLICY
+ if (thisElem != null && otherElem != null)
+ {
+ if (thisElem.GetTag().Equals( s_str_PermissionUnion ) ||
+ thisElem.GetTag().Equals( s_str_PermissionUnrestrictedUnion ))
+ {
+ Contract.Assert( thisElem is SecurityElement, "SecurityElement expected" );
+ SafeChildAdd( (SecurityElement)thisElem, otherElem, true );
+ }
+ else
+ {
+ SecurityElement newElem;
+ if (this.IsUnrestricted() || other.IsUnrestricted())
+ newElem = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ else
+ newElem = new SecurityElement( s_str_PermissionUnion );
+ newElem.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, thisElem, false );
+ SafeChildAdd( newElem, otherElem, true );
+ this.m_permSet.SetItem( i, newElem );
+ }
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisObj == null)
+ {
+#if FEATURE_CAS_POLICY
+ if (otherElem != null)
+ {
+ this.m_permSet.SetItem( i, otherElem.Copy() );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (otherPerm != null)
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if (((token.m_type & PermissionTokenType.IUnrestricted) == 0) || !this.m_Unrestricted)
+ {
+ this.m_permSet.SetItem( i, otherPerm.Copy() );
+ }
+ }
+ }
+ else if (otherObj == null)
+ {
+ continue;
+ }
+ else
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ thisPerm = this.CreatePermission(thisElem, i);
+ if (otherElem != null)
+ otherPerm = other.CreatePermission(otherElem, i);
+#endif // FEATURE_CAS_POLICY
+
+ try
+ {
+ IPermission unionPerm;
+ if(thisPerm == null)
+ unionPerm = otherPerm;
+ else if(otherPerm == null)
+ unionPerm = thisPerm;
+ else
+ unionPerm = thisPerm.Union( otherPerm );
+ this.m_permSet.SetItem( i, unionPerm );
+ }
+ catch (Exception e)
+ {
+ if (savedException == null)
+ savedException = e;
+ }
+ }
+ }
+
+ if (savedException != null)
+ throw savedException;
+ }
+
+ public PermissionSet Union(PermissionSet other)
+ {
+ // if other is null or empty, return a clone of myself
+ if (other == null || other.FastIsEmpty())
+ {
+ return this.Copy();
+ }
+
+ if (this.FastIsEmpty())
+ {
+ return other.Copy();
+ }
+
+ int maxMax = -1;
+
+ PermissionSet pset = new PermissionSet();
+ pset.m_Unrestricted = this.m_Unrestricted || other.m_Unrestricted;
+ if (pset.m_Unrestricted)
+ {
+ // if the result of Union is unrestricted permset, just return
+ return pset;
+ }
+
+ // degenerate case where we look at both this.m_permSet and other.m_permSet
+ this.CheckSet();
+ other.CheckSet();
+ maxMax = this.m_permSet.GetMaxUsedIndex() > other.m_permSet.GetMaxUsedIndex() ? this.m_permSet.GetMaxUsedIndex() : other.m_permSet.GetMaxUsedIndex();
+ pset.m_permSet = new TokenBasedSet();
+
+
+
+ for (int i = 0; i <= maxMax; ++i)
+ {
+ Object thisObj = this.m_permSet.GetItem( i );
+ IPermission thisPerm = thisObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ Object otherObj = other.m_permSet.GetItem( i );
+ IPermission otherPerm = otherObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ if (thisObj == null && otherObj == null)
+ continue;
+
+#if FEATURE_CAS_POLICY
+ if (thisElem != null && otherElem != null)
+ {
+ SecurityElement newElem;
+ if (this.IsUnrestricted() || other.IsUnrestricted())
+ newElem = new SecurityElement( s_str_PermissionUnrestrictedUnion );
+ else
+ newElem = new SecurityElement( s_str_PermissionUnion );
+ newElem.AddAttribute( "class", thisElem.Attribute( "class" ) );
+ SafeChildAdd( newElem, thisElem, true );
+ SafeChildAdd( newElem, otherElem, true );
+ pset.m_permSet.SetItem( i, newElem );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisObj == null)
+ {
+#if FEATURE_CAS_POLICY
+ if (otherElem != null)
+ {
+ pset.m_permSet.SetItem( i, otherElem.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (otherPerm != null)
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if (((token.m_type & PermissionTokenType.IUnrestricted) == 0) || !pset.m_Unrestricted)
+ {
+ pset.m_permSet.SetItem( i, otherPerm.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+ }
+ else if (otherObj == null)
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ {
+ pset.m_permSet.SetItem( i, thisElem.Copy() );
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ if (thisPerm != null)
+ {
+ PermissionToken token = (PermissionToken)PermissionToken.s_tokenSet.GetItem( i );
+ if (((token.m_type & PermissionTokenType.IUnrestricted) == 0) || !pset.m_Unrestricted)
+ {
+ pset.m_permSet.SetItem( i, thisPerm.Copy() );
+ Contract.Assert( PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+ }
+ else
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ thisPerm = this.CreatePermission(thisElem, i);
+ if (otherElem != null)
+ otherPerm = other.CreatePermission(otherElem, i);
+#endif // FEATURE_CAS_POLICY
+
+ IPermission unionPerm;
+ if(thisPerm == null)
+ unionPerm = otherPerm;
+ else if(otherPerm == null)
+ unionPerm = thisPerm;
+ else
+ unionPerm = thisPerm.Union( otherPerm );
+ pset.m_permSet.SetItem( i, unionPerm );
+ Contract.Assert( unionPerm == null || PermissionToken.s_tokenSet.GetItem( i ) != null, "PermissionToken should already be assigned" );
+ }
+ }
+
+ return pset;
+ }
+
+ // Treating the current permission set as a grant set, and the input set as
+ // a set of permissions to be denied, try to cancel out as many permissions
+ // from both sets as possible. For a first cut, any granted permission that
+ // is a safe subset of the corresponding denied permission can result in
+ // that permission being removed from both sides.
+
+ internal void MergeDeniedSet(PermissionSet denied)
+ {
+ if (denied == null || denied.FastIsEmpty() || this.FastIsEmpty())
+ return;
+
+ m_CheckedForNonCas = false;
+
+ // Check for the unrestricted case: FastIsEmpty() will return false if the PSet is unrestricted, but has no items
+ if (this.m_permSet == null || denied.m_permSet == null)
+ return; //nothing can be removed
+
+ int maxIndex = denied.m_permSet.GetMaxUsedIndex() > this.m_permSet.GetMaxUsedIndex() ? this.m_permSet.GetMaxUsedIndex() : denied.m_permSet.GetMaxUsedIndex();
+ for (int i = 0; i <= maxIndex; ++i) {
+ IPermission deniedPerm = denied.m_permSet.GetItem(i) as IPermission;
+ if (deniedPerm == null)
+ continue;
+
+ IPermission thisPerm = this.m_permSet.GetItem(i) as IPermission;
+
+ if (thisPerm == null && !this.m_Unrestricted) {
+ denied.m_permSet.SetItem(i, null);
+ continue;
+ }
+
+ if (thisPerm != null && deniedPerm != null) {
+ if (thisPerm.IsSubsetOf(deniedPerm)) {
+ this.m_permSet.SetItem(i, null);
+ denied.m_permSet.SetItem(i, null);
+ }
+ }
+ }
+ }
+
+ // Returns true if perm is contained in this
+ internal bool Contains(IPermission perm)
+ {
+ if (perm == null)
+ return true;
+ if (m_Unrestricted)
+ return true;
+ if (FastIsEmpty())
+ return false;
+
+ PermissionToken token = PermissionToken.GetToken(perm);
+ Object thisObj = this.m_permSet.GetItem( token.m_index );
+ if (thisObj == null)
+ return perm.IsSubsetOf( null );
+
+ IPermission thisPerm = GetPermission(token.m_index);
+ if (thisPerm != null)
+ return perm.IsSubsetOf( thisPerm );
+ else
+ return perm.IsSubsetOf( null );
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals( Object obj )
+ {
+ // Note: this method is designed to accept both PermissionSet and NamedPermissionSets.
+ // It will compare them based on the values in the base type, thereby ignoring the
+ // name and description of the named permission set.
+
+ PermissionSet other = obj as PermissionSet;
+
+ if (other == null)
+ return false;
+
+ if (this.m_Unrestricted != other.m_Unrestricted)
+ return false;
+
+ CheckSet();
+ other.CheckSet();
+
+ DecodeAllPermissions();
+ other.DecodeAllPermissions();
+
+ int maxIndex = Math.Max( this.m_permSet.GetMaxUsedIndex(), other.m_permSet.GetMaxUsedIndex() );
+
+ for (int i = 0; i <= maxIndex; ++i)
+ {
+ IPermission thisPerm = (IPermission)this.m_permSet.GetItem( i );
+ IPermission otherPerm = (IPermission)other.m_permSet.GetItem( i );
+
+ if (thisPerm == null && otherPerm == null)
+ {
+ continue;
+ }
+ else if (thisPerm == null)
+ {
+ if (!otherPerm.IsSubsetOf( null ))
+ return false;
+ }
+ else if (otherPerm == null)
+ {
+ if (!thisPerm.IsSubsetOf( null ))
+ return false;
+ }
+ else
+ {
+ if (!thisPerm.Equals( otherPerm ))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ int accumulator;
+
+ accumulator = this.m_Unrestricted ? -1 : 0;
+
+ if (this.m_permSet != null)
+ {
+ DecodeAllPermissions();
+
+ int maxIndex = this.m_permSet.GetMaxUsedIndex();
+
+ for (int i = m_permSet.GetStartingIndex(); i <= maxIndex; ++i)
+ {
+ IPermission perm = (IPermission)this.m_permSet.GetItem( i );
+ if (perm != null)
+ {
+ accumulator = accumulator ^ perm.GetHashCode();
+ }
+ }
+ }
+
+ return accumulator;
+ }
+
+ // Mark this method as requiring a security object on the caller's frame
+ // so the caller won't be inlined (which would mess up stack crawling).
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Demand()
+ {
+ if (this.FastIsEmpty())
+ return; // demanding the empty set always passes.
+
+ ContainsNonCodeAccessPermissions();
+
+ if (m_ContainsCas)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
+ CodeAccessSecurityEngine.Check(GetCasOnlySet(), ref stackMark);
+ }
+ if (m_ContainsNonCas)
+ {
+ DemandNonCAS();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void DemandNonCAS()
+ {
+ ContainsNonCodeAccessPermissions();
+
+ if (m_ContainsNonCas)
+ {
+ if (this.m_permSet != null)
+ {
+ CheckSet();
+ for (int i = m_permSet.GetStartingIndex(); i <= this.m_permSet.GetMaxUsedIndex(); ++i)
+ {
+ IPermission currPerm = GetPermission(i);
+ if (currPerm != null && !(currPerm is CodeAccessPermission))
+ currPerm.Demand();
+ }
+ }
+ }
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Assert()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.Assert(this, ref stackMark);
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public void Deny()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.Deny(this, ref stackMark);
+ }
+
+ // Metadata for this method should be flaged with REQ_SQ so that
+ // EE can allocate space on the stack frame for FrameSecurityDescriptor
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void PermitOnly()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.PermitOnly(this, ref stackMark);
+ }
+
+ internal IPermission GetFirstPerm()
+ {
+ IEnumerator enumerator = GetEnumerator();
+ if(!enumerator.MoveNext())
+ return null;
+ return enumerator.Current as IPermission;
+ }
+
+ // Returns a deep copy
+ public virtual PermissionSet Copy()
+ {
+ return new PermissionSet(this);
+ }
+
+ internal PermissionSet CopyWithNoIdentityPermissions()
+ {
+ // Explicitly make a new PermissionSet, rather than copying, since we may have a
+ // ReadOnlyPermissionSet which cannot have identity permissions removed from it in a true copy.
+ PermissionSet copy = new PermissionSet(this);
+
+ // There's no easy way to distinguish an identity permission from any other CodeAccessPermission,
+ // so remove them directly.
+#if FEATURE_CAS_POLICY
+ copy.RemovePermission(typeof(GacIdentityPermission));
+#if FEATURE_X509
+ copy.RemovePermission(typeof(PublisherIdentityPermission));
+#endif
+ copy.RemovePermission(typeof(StrongNameIdentityPermission));
+ copy.RemovePermission(typeof(UrlIdentityPermission));
+ copy.RemovePermission(typeof(ZoneIdentityPermission));
+#endif // FEATURE_CAS_POLICY
+
+ return copy;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return GetEnumeratorImpl();
+ }
+
+ protected virtual IEnumerator GetEnumeratorImpl()
+ {
+ return new PermissionSetEnumerator(this);
+ }
+
+ internal PermissionSetEnumeratorInternal GetEnumeratorInternal()
+ {
+ return new PermissionSetEnumeratorInternal(this);
+ }
+
+#if FEATURE_CAS_POLICY
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ private void NormalizePermissionSet()
+ {
+ // This function guarantees that all the permissions are placed at
+ // the proper index within the token based sets. This becomes necessary
+ // since these indices are dynamically allocated based on usage order.
+
+ PermissionSet permSetTemp = new PermissionSet(false);
+
+ permSetTemp.m_Unrestricted = this.m_Unrestricted;
+
+ // Move all the normal permissions to the new permission set
+
+ if (this.m_permSet != null)
+ {
+ for (int i = m_permSet.GetStartingIndex(); i <= this.m_permSet.GetMaxUsedIndex(); ++i)
+ {
+ Object obj = this.m_permSet.GetItem(i);
+ IPermission perm = obj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory elem = obj as ISecurityElementFactory;
+
+ if (elem != null)
+ perm = CreatePerm( elem );
+#endif // FEATURE_CAS_POLICY
+ if (perm != null)
+ permSetTemp.SetPermission( perm );
+ }
+ }
+
+ this.m_permSet = permSetTemp.m_permSet;
+ }
+
+#if FEATURE_CAS_POLICY
+ private bool DecodeXml(byte[] data, HostProtectionResource fullTrustOnlyResources, HostProtectionResource inaccessibleResources )
+ {
+ if (data != null && data.Length > 0)
+ {
+ FromXml( new Parser( data, Tokenizer.ByteTokenEncoding.UnicodeTokens ).GetTopElement() );
+ }
+
+ FilterHostProtectionPermissions(fullTrustOnlyResources, inaccessibleResources);
+
+ // We call this method from unmanaged to code a set we are going to use declaratively. In
+ // this case, all the lazy evaluation for partial policy resolution is wasted since we'll
+ // need to decode all of these shortly to make the demand for whatever. Therefore, we
+ // pay that price now so that we can calculate whether all the permissions in the set
+ // implement the IUnrestrictedPermission interface (the common case) for use in some
+ // unmanaged optimizations.
+
+ DecodeAllPermissions();
+
+ return true;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ private void DecodeAllPermissions()
+ {
+ if (m_permSet == null)
+ {
+ m_allPermissionsDecoded = true;
+ return;
+ }
+
+ int maxIndex = m_permSet.GetMaxUsedIndex();
+ for (int i = 0; i <= maxIndex; ++i)
+ {
+ // GetPermission has the side-effect of decoding the permission in the slot
+ GetPermission(i);
+ }
+
+ m_allPermissionsDecoded = true;
+ }
+
+ internal void FilterHostProtectionPermissions(HostProtectionResource fullTrustOnly, HostProtectionResource inaccessible)
+ {
+ HostProtectionPermission.protectedResources = fullTrustOnly;
+ HostProtectionPermission hpp = (HostProtectionPermission)GetPermission(HostProtectionPermission.GetTokenIndex());
+ if(hpp == null)
+ return;
+
+ HostProtectionPermission newHpp = (HostProtectionPermission)hpp.Intersect(new HostProtectionPermission(fullTrustOnly));
+ if (newHpp == null)
+ {
+#if FEATURE_CAS_POLICY
+ RemovePermission(typeof(HostProtectionPermission));
+#else // !FEATURE_CAS_POLICY
+ RemovePermission(HostProtectionPermission.GetTokenIndex());
+#endif // FEATURE_CAS_POLICY
+ }
+ else if (newHpp.Resources != hpp.Resources)
+ {
+ SetPermission(newHpp);
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ public virtual void FromXml( SecurityElement et )
+ {
+ FromXml( et, false, false );
+ }
+
+ internal static bool IsPermissionTag( String tag, bool allowInternalOnly )
+ {
+ if (tag.Equals( s_str_Permission ) ||
+ tag.Equals( s_str_IPermission ))
+ {
+ return true;
+ }
+
+ if (allowInternalOnly &&
+ (tag.Equals( s_str_PermissionUnion ) ||
+ tag.Equals( s_str_PermissionIntersection ) ||
+ tag.Equals( s_str_PermissionUnrestrictedIntersection ) ||
+ tag.Equals( s_str_PermissionUnrestrictedUnion)))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ internal virtual void FromXml( SecurityElement et, bool allowInternalOnly, bool ignoreTypeLoadFailures )
+ {
+ if (et == null)
+ throw new ArgumentNullException("et");
+
+ if (!et.Tag.Equals(s_str_PermissionSet))
+ throw new ArgumentException(String.Format( null, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PermissionSet", this.GetType().FullName) );
+ Contract.EndContractBlock();
+
+ Reset();
+ m_ignoreTypeLoadFailures = ignoreTypeLoadFailures;
+ m_allPermissionsDecoded = false;
+ m_Unrestricted = XMLUtil.IsUnrestricted( et );
+
+ if (et.InternalChildren != null)
+ {
+ int childCount = et.InternalChildren.Count;
+ for (int i = 0; i < childCount; ++i)
+ {
+ SecurityElement elem = (SecurityElement)et.Children[i];
+
+ if (IsPermissionTag( elem.Tag, allowInternalOnly ))
+ {
+ String className = elem.Attribute( "class" );
+
+ PermissionToken token;
+ Object objectToInsert;
+
+ if (className != null)
+ {
+ token = PermissionToken.GetToken( className );
+ if (token == null)
+ {
+ objectToInsert = CreatePerm( elem );
+#if _DEBUG
+ PermissionToken tokenDebug = PermissionToken.GetToken( (IPermission)objectToInsert );
+ Contract.Assert( tokenDebug != null && (tokenDebug.m_type & PermissionTokenType.BuiltIn) != 0, "This should only be called for built-ins" );
+#endif
+ if (objectToInsert != null)
+ {
+ Contract.Assert( objectToInsert.GetType().Module.Assembly == System.Reflection.Assembly.GetExecutingAssembly(),
+ "PermissionToken.GetToken returned null for non-mscorlib permission" );
+ token = PermissionToken.GetToken( (IPermission)objectToInsert );
+ Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should always know the permission type when getting a token from an instance" );
+ }
+ }
+ else
+ {
+ objectToInsert = elem;
+ }
+ }
+ else
+ {
+ IPermission ip = CreatePerm( elem );
+ if (ip == null)
+ {
+ token = null;
+ objectToInsert = null;
+ }
+ else
+ {
+ token = PermissionToken.GetToken( ip );
+ Contract.Assert( PermissionToken.IsTokenProperlyAssigned( ip, token ),
+ "PermissionToken was improperly assigned" );
+ objectToInsert = ip;
+ }
+ }
+
+ if (token != null && objectToInsert != null)
+ {
+ if (m_permSet == null)
+ m_permSet = new TokenBasedSet();
+
+ if (this.m_permSet.GetItem( token.m_index ) != null)
+ {
+ // If there is already something in that slot, let's union them
+ // together.
+
+ IPermission permInSlot;
+
+ if (this.m_permSet.GetItem( token.m_index ) is IPermission)
+ permInSlot = (IPermission)this.m_permSet.GetItem( token.m_index );
+ else
+ permInSlot = CreatePerm( (SecurityElement)this.m_permSet.GetItem( token.m_index ) );
+
+ if (objectToInsert is IPermission)
+ objectToInsert = ((IPermission)objectToInsert).Union( permInSlot );
+ else
+ objectToInsert = CreatePerm( (SecurityElement)objectToInsert ).Union( permInSlot );
+ }
+
+ if(m_Unrestricted && objectToInsert is IPermission)
+ objectToInsert = null;
+
+ this.m_permSet.SetItem( token.m_index, objectToInsert );
+ }
+ }
+ }
+ }
+ }
+
+ internal virtual void FromXml( SecurityDocument doc, int position, bool allowInternalOnly )
+ {
+ if (doc == null)
+ throw new ArgumentNullException("doc");
+ Contract.EndContractBlock();
+
+ if (!doc.GetTagForElement( position ).Equals(s_str_PermissionSet))
+ throw new ArgumentException(String.Format( null, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PermissionSet", this.GetType().FullName) );
+
+ Reset();
+ m_allPermissionsDecoded = false;
+ Exception savedException = null;
+ String strUnrestricted = doc.GetAttributeForElement( position, "Unrestricted" );
+ if (strUnrestricted != null)
+ m_Unrestricted = strUnrestricted.Equals( "True" ) || strUnrestricted.Equals( "true" ) || strUnrestricted.Equals( "TRUE" );
+ else
+ m_Unrestricted = false;
+
+ ArrayList childrenIndices = doc.GetChildrenPositionForElement( position );
+ int childCount = childrenIndices.Count;
+ for (int i = 0; i < childCount; ++i)
+ {
+ int childIndex = (int)childrenIndices[i];
+ if (IsPermissionTag( doc.GetTagForElement( childIndex ), allowInternalOnly ))
+ {
+ try
+ {
+ String className = doc.GetAttributeForElement( childIndex, "class" );
+
+ PermissionToken token;
+ Object objectToInsert;
+
+ if (className != null)
+ {
+ token = PermissionToken.GetToken( className );
+ if (token == null)
+ {
+ objectToInsert = CreatePerm( doc.GetElement( childIndex, true ) );
+
+ if (objectToInsert != null)
+ {
+#if _DEBUG
+ PermissionToken tokenDebug = PermissionToken.GetToken( (IPermission)objectToInsert );
+ Contract.Assert((tokenDebug != null), "PermissionToken.GetToken returned null ");
+ Contract.Assert( (tokenDebug.m_type & PermissionTokenType.BuiltIn) != 0, "This should only be called for built-ins" );
+#endif
+ Contract.Assert( objectToInsert.GetType().Module.Assembly == System.Reflection.Assembly.GetExecutingAssembly(),
+ "PermissionToken.GetToken returned null for non-mscorlib permission" );
+ token = PermissionToken.GetToken( (IPermission)objectToInsert );
+ Contract.Assert((token != null), "PermissionToken.GetToken returned null ");
+ Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should always know the permission type when getting a token from an instance" );
+ }
+ }
+ else
+ {
+ objectToInsert = ((ISecurityElementFactory)new SecurityDocumentElement(doc, childIndex)).CreateSecurityElement();
+ }
+ }
+ else
+ {
+ IPermission ip = CreatePerm( doc.GetElement( childIndex, true ) );
+ if (ip == null)
+ {
+ token = null;
+ objectToInsert = null;
+ }
+ else
+ {
+ token = PermissionToken.GetToken( ip );
+ Contract.Assert( PermissionToken.IsTokenProperlyAssigned( ip, token ),
+ "PermissionToken was improperly assigned" );
+ objectToInsert = ip;
+ }
+ }
+
+ if (token != null && objectToInsert != null)
+ {
+ if (m_permSet == null)
+ m_permSet = new TokenBasedSet();
+
+ IPermission permInSlot = null;
+ if (this.m_permSet.GetItem( token.m_index ) != null)
+ {
+ // If there is already something in that slot, let's union them
+ // together.
+
+ if (this.m_permSet.GetItem( token.m_index ) is IPermission)
+ permInSlot = (IPermission)this.m_permSet.GetItem( token.m_index );
+ else
+ permInSlot = CreatePerm( this.m_permSet.GetItem( token.m_index ) );
+ }
+
+ if (permInSlot != null)
+ {
+ if (objectToInsert is IPermission)
+ objectToInsert = permInSlot.Union((IPermission)objectToInsert);
+ else
+ objectToInsert = permInSlot.Union(CreatePerm( objectToInsert ));
+ }
+
+ if(m_Unrestricted && objectToInsert is IPermission)
+ objectToInsert = null;
+
+ this.m_permSet.SetItem( token.m_index, objectToInsert );
+ }
+ }
+ catch (Exception e)
+ {
+#if _DEBUG
+ if (debug)
+ DEBUG_WRITE( "error while decoding permission set =\n" + e.ToString() );
+#endif
+ if (savedException == null)
+ savedException = e;
+
+ }
+ }
+ }
+
+ if (savedException != null)
+ throw savedException;
+
+ }
+
+ private IPermission CreatePerm(Object obj)
+ {
+ return CreatePerm(obj, m_ignoreTypeLoadFailures);
+ }
+
+ internal static IPermission CreatePerm(Object obj, bool ignoreTypeLoadFailures)
+ {
+ SecurityElement el = obj as SecurityElement;
+ ISecurityElementFactory isf = obj as ISecurityElementFactory;
+ if (el == null && isf != null)
+ {
+ el = isf.CreateSecurityElement();
+ }
+
+ IEnumerator enumerator;
+ IPermission finalPerm = null;
+
+ switch (el.Tag)
+ {
+ case s_str_PermissionUnion:
+ enumerator = el.Children.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures);
+
+ if (finalPerm != null)
+ finalPerm = finalPerm.Union( tempPerm );
+ else
+ finalPerm = tempPerm;
+ }
+ break;
+
+ case s_str_PermissionIntersection:
+ enumerator = el.Children.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures);
+
+ if (finalPerm != null)
+ finalPerm = finalPerm.Intersect( tempPerm );
+ else
+ finalPerm = tempPerm;
+
+ if (finalPerm == null)
+ return null;
+ }
+ break;
+
+ case s_str_PermissionUnrestrictedUnion:
+ enumerator = el.Children.GetEnumerator();
+ bool first = true;
+ while (enumerator.MoveNext())
+ {
+ IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures );
+
+ if (tempPerm == null)
+ continue;
+
+ PermissionToken token = PermissionToken.GetToken( tempPerm );
+
+ Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should know the permission type already" );
+
+ if ((token.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ finalPerm = XMLUtil.CreatePermission( GetPermissionElement((SecurityElement)enumerator.Current), PermissionState.Unrestricted, ignoreTypeLoadFailures );
+ first = false;
+ break;
+ }
+ else
+ {
+ Contract.Assert( tempPerm != null, "We should only come here if we have a real permission" );
+ if (first)
+ finalPerm = tempPerm;
+ else
+ finalPerm = tempPerm.Union( finalPerm );
+ first = false;
+ }
+ }
+ break;
+
+ case s_str_PermissionUnrestrictedIntersection:
+ enumerator = el.Children.GetEnumerator();
+ while (enumerator.MoveNext())
+ {
+ IPermission tempPerm = CreatePerm( (SecurityElement)enumerator.Current, ignoreTypeLoadFailures );
+
+ if (tempPerm == null)
+ return null;
+
+ PermissionToken token = PermissionToken.GetToken( tempPerm );
+
+ Contract.Assert( (token.m_type & PermissionTokenType.DontKnow) == 0, "We should know the permission type already" );
+
+ if ((token.m_type & PermissionTokenType.IUnrestricted) != 0)
+ {
+ if (finalPerm != null)
+ finalPerm = tempPerm.Intersect( finalPerm );
+ else
+ finalPerm = tempPerm;
+ }
+ else
+ {
+ finalPerm = null;
+ }
+
+ if (finalPerm == null)
+ return null;
+ }
+ break;
+
+ case "IPermission":
+ case "Permission":
+ finalPerm = el.ToPermission(ignoreTypeLoadFailures);
+ break;
+
+ default:
+ Contract.Assert( false, "Unrecognized case found during permission creation" );
+ break;
+ }
+
+ return finalPerm;
+ }
+
+ internal IPermission CreatePermission(Object obj, int index)
+ {
+ IPermission perm = CreatePerm(obj);
+ if(perm == null)
+ return null;
+
+ // See if the PermissionSet.m_Unrestricted flag covers this permission
+ if(m_Unrestricted)
+ perm = null;
+
+ // Store the decoded result
+ CheckSet();
+ m_permSet.SetItem(index, perm);
+
+ // Do some consistency checks
+ Contract.Assert(perm == null || PermissionToken.IsTokenProperlyAssigned( perm, PermissionToken.GetToken( perm ) ), "PermissionToken was improperly assigned");
+ if (perm != null)
+ {
+ PermissionToken permToken = PermissionToken.GetToken(perm);
+ if (permToken != null && permToken.m_index != index)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_UnableToGeneratePermissionSet"));
+ }
+
+
+ return perm;
+ }
+
+ private static SecurityElement GetPermissionElement( SecurityElement el )
+ {
+ switch (el.Tag)
+ {
+ case "IPermission":
+ case "Permission":
+ return el;
+ }
+ IEnumerator enumerator = el.Children.GetEnumerator();
+ if (enumerator.MoveNext())
+ return GetPermissionElement((SecurityElement)enumerator.Current);
+ Contract.Assert( false, "No Permission or IPermission tag found" );
+ return null;
+ }
+
+ internal static SecurityElement CreateEmptyPermissionSetXml()
+ {
+
+ SecurityElement elTrunk = new SecurityElement("PermissionSet");
+ elTrunk.AddAttribute( "class", "System.Security.PermissionSet" );
+
+ elTrunk.AddAttribute( "version", "1" );
+ return elTrunk;
+
+ }
+ // internal helper which takes in the hardcoded permission name to avoid lookup at runtime
+ // can be called from classes that derive from PermissionSet
+ internal SecurityElement ToXml(String permName)
+ {
+ SecurityElement elTrunk = new SecurityElement("PermissionSet");
+ elTrunk.AddAttribute( "class", permName );
+
+ elTrunk.AddAttribute( "version", "1" );
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this);
+
+ if (m_Unrestricted)
+ {
+ elTrunk.AddAttribute(s_str_Unrestricted, "true" );
+ }
+
+ while (enumerator.MoveNext())
+ {
+ IPermission perm = (IPermission)enumerator.Current;
+
+ if (!m_Unrestricted)
+ elTrunk.AddChild( perm.ToXml() );
+ }
+ return elTrunk;
+ }
+
+ internal SecurityElement InternalToXml()
+ {
+ SecurityElement elTrunk = new SecurityElement("PermissionSet");
+ elTrunk.AddAttribute( "class", this.GetType().FullName);
+ elTrunk.AddAttribute( "version", "1" );
+
+ if (m_Unrestricted)
+ {
+ elTrunk.AddAttribute(s_str_Unrestricted, "true" );
+ }
+
+ if (this.m_permSet != null)
+ {
+ int maxIndex = this.m_permSet.GetMaxUsedIndex();
+
+ for (int i = m_permSet.GetStartingIndex(); i <= maxIndex; ++i)
+ {
+ Object obj = this.m_permSet.GetItem( i );
+ if (obj != null)
+ {
+ if (obj is IPermission)
+ {
+ if (!m_Unrestricted)
+ elTrunk.AddChild( ((IPermission)obj).ToXml() );
+ }
+ else
+ {
+ elTrunk.AddChild( (SecurityElement)obj );
+ }
+ }
+
+ }
+ }
+ return elTrunk ;
+ }
+
+ public virtual SecurityElement ToXml()
+ {
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( this.GetType().FullName.Equals( "System.Security.PermissionSet" ), "Class name changed! Was: System.Security.PermissionSet Should be:" + this.GetType().FullName);
+
+ return ToXml("System.Security.PermissionSet");
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CAS_POLICY && FEATURE_SERIALIZATION
+ internal
+ byte[] EncodeXml()
+ {
+ MemoryStream ms = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter( ms, Encoding.Unicode );
+ writer.Write( this.ToXml().ToString() );
+ writer.Flush();
+
+ // The BinaryWriter is going to place
+ // two bytes indicating a Unicode stream.
+ // We want to chop those off before returning
+ // the bytes out.
+
+ ms.Position = 2;
+ int countBytes = (int)ms.Length - 2;
+ byte[] retval = new byte[countBytes];
+ ms.Read( retval, 0, retval.Length );
+ return retval;
+ }
+
+ /// <internalonly/>
+ [Obsolete("This method is obsolete and shoud no longer be used.")]
+ public static byte[] ConvertPermissionSet(String inFormat, byte[] inData, String outFormat)
+ {
+ // Since this method has shipped and is public, we cannot remove it without being a breaking change
+ throw new NotImplementedException();
+ }
+#endif
+
+ // Determines whether the permission set contains any non-code access
+ // security permissions.
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ public bool ContainsNonCodeAccessPermissions()
+ {
+ if (m_CheckedForNonCas)
+ return m_ContainsNonCas;
+
+ lock (this)
+ {
+ if (m_CheckedForNonCas)
+ return m_ContainsNonCas;
+
+ m_ContainsCas = false;
+ m_ContainsNonCas = false;
+
+ if (IsUnrestricted())
+ m_ContainsCas = true;
+
+ if (this.m_permSet != null)
+ {
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this);
+
+ while (enumerator.MoveNext() && (!m_ContainsCas || !m_ContainsNonCas))
+ {
+ IPermission perm = enumerator.Current as IPermission;
+
+ if (perm != null)
+ {
+ if (perm is CodeAccessPermission)
+ m_ContainsCas = true;
+ else
+ m_ContainsNonCas = true;
+ }
+ }
+ }
+
+ m_CheckedForNonCas = true;
+ }
+
+ return m_ContainsNonCas;
+ }
+
+ // Returns a permission set containing only CAS-permissions. If possible
+ // this is just the input set, otherwise a new set is allocated.
+ private PermissionSet GetCasOnlySet()
+ {
+ if (!m_ContainsNonCas)
+ return this;
+
+ if (IsUnrestricted())
+ return this;
+
+ PermissionSet pset = new PermissionSet(false);
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(this);
+
+ while (enumerator.MoveNext())
+ {
+ IPermission perm = (IPermission)enumerator.Current;
+
+ if (perm is CodeAccessPermission)
+ pset.AddPermission(perm);
+ }
+
+ pset.m_CheckedForNonCas = true;
+ pset.m_ContainsCas = !pset.IsEmpty();
+ pset.m_ContainsNonCas = false;
+
+ return pset;
+ }
+
+#if FEATURE_CAS_POLICY
+ private const String s_str_PermissionSet = "PermissionSet";
+ private const String s_str_Permission = "Permission";
+ private const String s_str_IPermission = "IPermission";
+ private const String s_str_Unrestricted = "Unrestricted";
+ private const String s_str_PermissionUnion = "PermissionUnion";
+ private const String s_str_PermissionIntersection = "PermissionIntersection";
+ private const String s_str_PermissionUnrestrictedUnion = "PermissionUnrestrictedUnion";
+ private const String s_str_PermissionUnrestrictedIntersection = "PermissionUnrestrictedIntersection";
+
+ // This method supports v1.x security attrbutes only - we'll require legacy CAS policy mode
+ // to be enabled for that to work.
+#pragma warning disable 618
+ // Internal routine used to setup a special security context
+ // for creating and manipulated security custom attributes
+ // that we use when the Runtime is hosted.
+ [System.Security.SecurityCritical] // auto-generated
+ private static void SetupSecurity()
+ {
+ PolicyLevel level = PolicyLevel.CreateAppDomainLevel();
+
+ CodeGroup rootGroup = new UnionCodeGroup( new AllMembershipCondition(), level.GetNamedPermissionSet( "Execution" ) );
+
+ StrongNamePublicKeyBlob microsoftBlob = new StrongNamePublicKeyBlob( AssemblyRef.MicrosoftPublicKeyFull );
+ CodeGroup microsoftGroup = new UnionCodeGroup( new StrongNameMembershipCondition( microsoftBlob, null, null ), level.GetNamedPermissionSet( "FullTrust" ) );
+
+ StrongNamePublicKeyBlob ecmaBlob = new StrongNamePublicKeyBlob( AssemblyRef.EcmaPublicKeyFull );
+ CodeGroup ecmaGroup = new UnionCodeGroup( new StrongNameMembershipCondition( ecmaBlob, null, null ), level.GetNamedPermissionSet( "FullTrust" ) );
+
+ CodeGroup gacGroup = new UnionCodeGroup( new GacMembershipCondition(), level.GetNamedPermissionSet( "FullTrust" ) );
+
+ rootGroup.AddChild( microsoftGroup );
+ rootGroup.AddChild( ecmaGroup );
+ rootGroup.AddChild( gacGroup );
+
+ level.RootCodeGroup = rootGroup;
+
+ try
+ {
+ AppDomain.CurrentDomain.SetAppDomainPolicy( level );
+ }
+ catch (PolicyException)
+ {
+ }
+ }
+#endif
+#pragma warning restore 618
+
+ // Internal routine used by CreateSerialized to add a permission to the set
+ private static void MergePermission(IPermission perm, bool separateCasFromNonCas, ref PermissionSet casPset, ref PermissionSet nonCasPset)
+ {
+ Contract.Assert(casPset == null || !casPset.IsReadOnly);
+ Contract.Assert(nonCasPset == null || !nonCasPset.IsReadOnly);
+
+ if (perm == null)
+ return;
+
+ if (!separateCasFromNonCas || perm is CodeAccessPermission)
+ {
+ if(casPset == null)
+ casPset = new PermissionSet(false);
+ IPermission oldPerm = casPset.GetPermission(perm);
+ IPermission unionPerm = casPset.AddPermission(perm);
+ if (oldPerm != null && !oldPerm.IsSubsetOf( unionPerm ))
+ throw new NotSupportedException( Environment.GetResourceString( "NotSupported_DeclarativeUnion" ) );
+ }
+ else
+ {
+ if(nonCasPset == null)
+ nonCasPset = new PermissionSet(false);
+ IPermission oldPerm = nonCasPset.GetPermission(perm);
+ IPermission unionPerm = nonCasPset.AddPermission( perm );
+ if (oldPerm != null && !oldPerm.IsSubsetOf( unionPerm ))
+ throw new NotSupportedException( Environment.GetResourceString( "NotSupported_DeclarativeUnion" ) );
+ }
+ }
+
+ // Converts an array of SecurityAttributes to a PermissionSet
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ private static byte[] CreateSerialized(Object[] attrs,
+ bool serialize,
+ ref byte[] nonCasBlob,
+ out PermissionSet casPset,
+ HostProtectionResource fullTrustOnlyResources,
+ bool allowEmptyPermissionSets)
+ {
+ // Create two new (empty) sets.
+ casPset = null;
+ PermissionSet nonCasPset = null;
+
+ // Most security attributes generate a single permission. The
+ // PermissionSetAttribute class generates an entire permission set we
+ // need to merge, however.
+ for (int i = 0; i < attrs.Length; i++)
+ {
+#pragma warning disable 618
+ Contract.Assert(i == 0 || ((SecurityAttribute)attrs[i]).m_action == ((SecurityAttribute)attrs[i - 1]).m_action, "Mixed SecurityActions");
+#pragma warning restore 618
+ if (attrs[i] is PermissionSetAttribute)
+ {
+ PermissionSet pset = ((PermissionSetAttribute)attrs[i]).CreatePermissionSet();
+ if (pset == null)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_UnableToGeneratePermissionSet" ) );
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(pset);
+
+ while (enumerator.MoveNext())
+ {
+ IPermission perm = (IPermission)enumerator.Current;
+ MergePermission(perm, serialize, ref casPset, ref nonCasPset);
+ }
+
+ if(casPset == null)
+ casPset = new PermissionSet(false);
+ if (pset.IsUnrestricted())
+ casPset.SetUnrestricted(true);
+ }
+ else
+ {
+#pragma warning disable 618
+ IPermission perm = ((SecurityAttribute)attrs[i]).CreatePermission();
+#pragma warning restore 618
+ MergePermission(perm, serialize, ref casPset, ref nonCasPset);
+ }
+ }
+ Contract.Assert(serialize || nonCasPset == null, "We shouldn't separate nonCAS permissions unless fSerialize is true");
+
+ //
+ // Filter HostProtection permission. In the VM, some optimizations are done based upon these
+ // declarative permission sets being NULL if they do not exist. When filtering the permission
+ // set if we end up with an empty set, we can the permission set NULL rather than returning the
+ // empty set in order to enable those optimizations.
+ //
+
+ if(casPset != null)
+ {
+ casPset.FilterHostProtectionPermissions(fullTrustOnlyResources, HostProtectionResource.None);
+ casPset.ContainsNonCodeAccessPermissions(); // make sure all declarative PermissionSets are checked for non-CAS so we can just check the flag from native code
+ if (allowEmptyPermissionSets && casPset.IsEmpty())
+ casPset = null;
+ }
+ if(nonCasPset != null)
+ {
+ nonCasPset.FilterHostProtectionPermissions(fullTrustOnlyResources, HostProtectionResource.None);
+ nonCasPset.ContainsNonCodeAccessPermissions(); // make sure all declarative PermissionSets are checked for non-CAS so we can just check the flag from native code
+ if (allowEmptyPermissionSets && nonCasPset.IsEmpty())
+ nonCasPset = null;
+ }
+
+ // Serialize the set(s).
+ byte[] casBlob = null;
+ nonCasBlob = null;
+#if FEATURE_CAS_POLICY
+ if(serialize)
+ {
+ if(casPset != null)
+ casBlob = casPset.EncodeXml();
+ if(nonCasPset != null)
+ nonCasBlob = nonCasPset.EncodeXml();
+ }
+#else // FEATURE_CAS_POLICY
+ Contract.Assert(!serialize, "Cannot serialize permission sets on CoreCLR");
+#endif // FEATURE_CAS_POLICY
+
+ return casBlob;
+ }
+
+#if FEATURE_SERIALIZATION
+ /// <internalonly/>
+ void IDeserializationCallback.OnDeserialization(Object sender)
+ {
+ NormalizePermissionSet();
+ m_CheckedForNonCas = false;
+ }
+#endif
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static void RevertAssert()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ SecurityRuntime.RevertAssert(ref stackMark);
+ }
+
+ internal static PermissionSet RemoveRefusedPermissionSet(PermissionSet assertSet, PermissionSet refusedSet, out bool bFailedToCompress)
+ {
+ Contract.Assert((assertSet == null || !assertSet.IsUnrestricted()), "Cannot be unrestricted here");
+ PermissionSet retPs = null;
+ bFailedToCompress = false;
+ if (assertSet == null)
+ return null;
+ if (refusedSet != null)
+ {
+ if (refusedSet.IsUnrestricted())
+ return null; // we're refusing everything...cannot assert anything now.
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(refusedSet);
+ while (enumerator.MoveNext())
+ {
+ CodeAccessPermission refusedPerm = (CodeAccessPermission)enumerator.Current;
+ int i = enumerator.GetCurrentIndex();
+ if (refusedPerm != null)
+ {
+ CodeAccessPermission perm
+ = (CodeAccessPermission)assertSet.GetPermission(i);
+ try
+ {
+ if (refusedPerm.Intersect(perm) != null)
+ {
+ if (refusedPerm.Equals(perm))
+ {
+ if (retPs == null)
+ retPs = assertSet.Copy();
+
+ retPs.RemovePermission(i);
+ }
+ else
+ {
+ // Asserting a permission, part of which is already denied/refused
+ // cannot compress this assert
+ bFailedToCompress = true;
+ return assertSet;
+ }
+ }
+ }
+ catch (ArgumentException)
+ {
+ // Any exception during removing a refused set from assert set => we play it safe and not assert that perm
+ if (retPs == null)
+ retPs = assertSet.Copy();
+ retPs.RemovePermission(i);
+ }
+ }
+ }
+ }
+ if (retPs != null)
+ return retPs;
+ return assertSet;
+ }
+
+ internal static void RemoveAssertedPermissionSet(PermissionSet demandSet, PermissionSet assertSet, out PermissionSet alteredDemandSet)
+ {
+ Contract.Assert(!assertSet.IsUnrestricted(), "Cannot call this function if assertSet is unrestricted");
+ alteredDemandSet = null;
+
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(demandSet);
+ while (enumerator.MoveNext())
+ {
+ CodeAccessPermission demandDerm = (CodeAccessPermission)enumerator.Current;
+ int i = enumerator.GetCurrentIndex();
+ if (demandDerm != null)
+ {
+ CodeAccessPermission assertPerm
+ = (CodeAccessPermission)assertSet.GetPermission(i);
+ try
+ {
+ if (demandDerm.CheckAssert(assertPerm))
+ {
+ if (alteredDemandSet == null)
+ alteredDemandSet = demandSet.Copy();
+
+ alteredDemandSet.RemovePermission(i);
+ }
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+ }
+ return;
+ }
+
+ internal static bool IsIntersectingAssertedPermissions(PermissionSet assertSet1, PermissionSet assertSet2)
+ {
+ bool isIntersecting = false;
+ if (assertSet1 != null && assertSet2 != null)
+ {
+ PermissionSetEnumeratorInternal enumerator = new PermissionSetEnumeratorInternal(assertSet2);
+ while (enumerator.MoveNext())
+ {
+ CodeAccessPermission perm2 = (CodeAccessPermission)enumerator.Current;
+ int i = enumerator.GetCurrentIndex();
+ if (perm2 != null)
+ {
+ CodeAccessPermission perm1
+ = (CodeAccessPermission)assertSet1.GetPermission(i);
+ try
+ {
+ if (perm1 != null && !perm1.Equals(perm2))
+ {
+ isIntersecting = true; // Same type of permission, but with different flags or something - cannot union them
+ }
+ }
+ catch (ArgumentException)
+ {
+ isIntersecting = true; //assume worst case
+ }
+ }
+ }
+ }
+ return isIntersecting;
+
+ }
+
+ // This is a workaround so that SQL can operate under default policy without actually
+ // granting permissions in assemblies that they disallow.
+
+ internal bool IgnoreTypeLoadFailures
+ {
+ set { m_ignoreTypeLoadFailures = value; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs b/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs
new file mode 100644
index 0000000000..55b56cb570
--- /dev/null
+++ b/src/mscorlib/src/System/Security/PermissionSetEnumerator.cs
@@ -0,0 +1,103 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security
+{
+ //PermissionSetEnumerator.cs
+
+ using System;
+ using System.Collections;
+ using TokenBasedSetEnumerator = System.Security.Util.TokenBasedSetEnumerator;
+ using TokenBasedSet = System.Security.Util.TokenBasedSet;
+
+ internal class PermissionSetEnumerator : IEnumerator
+ {
+ PermissionSetEnumeratorInternal enm;
+
+ public Object Current
+ {
+ get
+ {
+ return enm.Current;
+ }
+ }
+
+ public bool MoveNext()
+ {
+ return enm.MoveNext();
+ }
+
+ public void Reset()
+ {
+ enm.Reset();
+ }
+
+ internal PermissionSetEnumerator(PermissionSet permSet)
+ {
+ enm = new PermissionSetEnumeratorInternal(permSet);
+ }
+ }
+
+ internal struct PermissionSetEnumeratorInternal
+ {
+ private PermissionSet m_permSet;
+ private TokenBasedSetEnumerator enm;
+
+ public Object Current
+ {
+ get
+ {
+ return enm.Current;
+ }
+ }
+
+ internal PermissionSetEnumeratorInternal(PermissionSet permSet)
+ {
+ m_permSet = permSet;
+ enm = new TokenBasedSetEnumerator(permSet.m_permSet);
+ }
+
+ public int GetCurrentIndex()
+ {
+ return enm.Index;
+ }
+
+ public void Reset()
+ {
+ enm.Reset();
+ }
+
+ public bool MoveNext()
+ {
+ while (enm.MoveNext())
+ {
+ Object obj = enm.Current;
+ IPermission perm = obj as IPermission;
+ if (perm != null)
+ {
+ enm.Current = perm;
+ return true;
+ }
+
+#if FEATURE_CAS_POLICY
+ SecurityElement elem = obj as SecurityElement;
+
+ if (elem != null)
+ {
+ perm = m_permSet.CreatePermission(elem, enm.Index);
+ if (perm != null)
+ {
+ enm.Current = perm;
+ return true;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+ return false;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Security/PermissionSetTriple.cs b/src/mscorlib/src/System/Security/PermissionSetTriple.cs
new file mode 100644
index 0000000000..f1527ac4b1
--- /dev/null
+++ b/src/mscorlib/src/System/Security/PermissionSetTriple.cs
@@ -0,0 +1,282 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+** Purpose: Container class for holding an AppDomain's Grantset and Refused sets.
+** Also used for CompressedStacks which brings in the third PermissionSet.
+** Hence, the name PermissionSetTriple.
+**
+=============================================================================*/
+
+namespace System.Security
+{
+ using IEnumerator = System.Collections.IEnumerator;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ sealed internal class PermissionSetTriple
+ {
+ static private volatile PermissionToken s_zoneToken;
+ static private volatile PermissionToken s_urlToken;
+ internal PermissionSet AssertSet;
+ internal PermissionSet GrantSet;
+ internal PermissionSet RefusedSet;
+ internal PermissionSetTriple()
+ {
+ Reset();
+ }
+ internal PermissionSetTriple(PermissionSetTriple triple)
+ {
+ this.AssertSet = triple.AssertSet;
+ this.GrantSet = triple.GrantSet;
+ this.RefusedSet = triple.RefusedSet;
+ }
+ internal void Reset()
+ {
+ AssertSet = null;
+ GrantSet = null;
+ RefusedSet = null;
+ }
+ internal bool IsEmpty()
+ {
+ return (AssertSet == null && GrantSet == null && RefusedSet == null);
+ }
+
+ private PermissionToken ZoneToken
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (s_zoneToken == null)
+ s_zoneToken = PermissionToken.GetToken(typeof(ZoneIdentityPermission));
+ return s_zoneToken;
+ }
+ }
+ private PermissionToken UrlToken
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (s_urlToken == null)
+ s_urlToken = PermissionToken.GetToken(typeof(UrlIdentityPermission));
+ return s_urlToken;
+ }
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool Update(PermissionSetTriple psTriple, out PermissionSetTriple retTriple)
+ {
+ retTriple = null;
+ retTriple = UpdateAssert(psTriple.AssertSet);
+ // Special case: unrestricted assert. Note: dcs.Assert.IsUnrestricted => dcs.Grant.IsUnrestricted
+ if (psTriple.AssertSet != null && psTriple.AssertSet.IsUnrestricted())
+ {
+ return true; // stop construction
+ }
+ UpdateGrant(psTriple.GrantSet);
+ UpdateRefused(psTriple.RefusedSet);
+ return false;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal PermissionSetTriple UpdateAssert(PermissionSet in_a)
+ {
+ PermissionSetTriple retTriple = null;
+ if (in_a != null)
+ {
+ Contract.Assert((!in_a.IsUnrestricted() || RefusedSet == null), "Cannot be unrestricted or refused must be null");
+ // if we're already asserting in_a, nothing to do
+ if (in_a.IsSubsetOf(AssertSet))
+ return null;
+
+ PermissionSet retPs;
+ if (GrantSet != null)
+ retPs = in_a.Intersect(GrantSet); // Restrict the assert to what we've already been granted
+ else
+ {
+ GrantSet = new PermissionSet(true);
+ retPs = in_a.Copy(); // Currently unrestricted Grant: assert the whole assert set
+ }
+ bool bFailedToCompress = false;
+ // removes anything that is already in the refused set from the assert set
+ if (RefusedSet != null)
+ {
+ retPs = PermissionSet.RemoveRefusedPermissionSet(retPs, RefusedSet, out bFailedToCompress);
+ }
+ if (!bFailedToCompress)
+ bFailedToCompress = PermissionSet.IsIntersectingAssertedPermissions(retPs, AssertSet);
+ if (bFailedToCompress)
+ {
+ retTriple = new PermissionSetTriple(this);
+ this.Reset();
+ this.GrantSet = retTriple.GrantSet.Copy();
+ }
+
+ if (AssertSet == null)
+ AssertSet = retPs;
+ else
+ AssertSet.InplaceUnion(retPs);
+
+ }
+ return retTriple;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal void UpdateGrant(PermissionSet in_g, out ZoneIdentityPermission z,out UrlIdentityPermission u)
+ {
+ z = null;
+ u = null;
+ if (in_g != null)
+ {
+ if (GrantSet == null)
+ GrantSet = in_g.Copy();
+ else
+ GrantSet.InplaceIntersect(in_g);
+
+ z = (ZoneIdentityPermission)in_g.GetPermission(ZoneToken);
+ u = (UrlIdentityPermission)in_g.GetPermission(UrlToken);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void UpdateGrant(PermissionSet in_g)
+ {
+ if (in_g != null)
+ {
+ if (GrantSet == null)
+ GrantSet = in_g.Copy();
+ else
+ GrantSet.InplaceIntersect(in_g);
+ }
+ }
+ internal void UpdateRefused(PermissionSet in_r)
+ {
+ if (in_r != null)
+ {
+ if (RefusedSet == null)
+ RefusedSet = in_r.Copy();
+ else
+ RefusedSet.InplaceUnion(in_r);
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ static bool CheckAssert(PermissionSet pSet, CodeAccessPermission demand, PermissionToken permToken)
+ {
+ if (pSet != null)
+ {
+ pSet.CheckDecoded(demand, permToken);
+
+ CodeAccessPermission perm = (CodeAccessPermission)pSet.GetPermission(demand);
+
+ // If the assert set does contain the demanded permission, halt the stackwalk
+
+ try
+ {
+ if (pSet.IsUnrestricted() || demand.CheckAssert(perm))
+ {
+ return SecurityRuntime.StackHalt;
+ }
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+ return SecurityRuntime.StackContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static bool CheckAssert(PermissionSet assertPset, PermissionSet demandSet, out PermissionSet newDemandSet)
+ {
+ newDemandSet = null;
+ if (assertPset!= null)
+ {
+ assertPset.CheckDecoded(demandSet);
+ // If this frame asserts a superset of the demand set we're done
+
+ if (demandSet.CheckAssertion(assertPset))
+ return SecurityRuntime.StackHalt;
+ PermissionSet.RemoveAssertedPermissionSet(demandSet, assertPset, out newDemandSet);
+ }
+ return SecurityRuntime.StackContinue;
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
+ {
+ if (CheckAssert(AssertSet, demand, permToken) == SecurityRuntime.StackHalt)
+ return SecurityRuntime.StackHalt;
+
+#pragma warning disable 618
+ CodeAccessSecurityEngine.CheckHelper(GrantSet, RefusedSet, demand, permToken, rmh, null, SecurityAction.Demand, true);
+#pragma warning restore 618
+
+ return SecurityRuntime.StackContinue;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand(PermissionSet demandSet , out PermissionSet alteredDemandset, RuntimeMethodHandleInternal rmh)
+ {
+ alteredDemandset = null;
+
+ if (CheckAssert(AssertSet, demandSet, out alteredDemandset) == SecurityRuntime.StackHalt)
+ return SecurityRuntime.StackHalt;
+ if (alteredDemandset != null)
+ demandSet = alteredDemandset; // note that this does not modify demandSet external to this function.
+#pragma warning disable 618
+ CodeAccessSecurityEngine.CheckSetHelper(GrantSet, RefusedSet, demandSet, rmh, null, SecurityAction.Demand, true);
+#pragma warning restore 618
+
+ return SecurityRuntime.StackContinue;
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemandNoThrow(CodeAccessPermission demand, PermissionToken permToken)
+ {
+ Contract.Assert(AssertSet == null, "AssertSet not null");
+#pragma warning disable 618
+ return CodeAccessSecurityEngine.CheckHelper(GrantSet, RefusedSet, demand, permToken, RuntimeMethodHandleInternal.EmptyHandle, null, SecurityAction.Demand, false);
+#pragma warning restore 618
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemandNoThrow(PermissionSet demandSet)
+ {
+ Contract.Assert(AssertSet == null, "AssertSet not null");
+
+#pragma warning disable 618
+ return CodeAccessSecurityEngine.CheckSetHelper(GrantSet, RefusedSet, demandSet, RuntimeMethodHandleInternal.EmptyHandle, null, SecurityAction.Demand, false);
+#pragma warning restore 618
+ }
+ /// <summary>
+ /// Check to see if the triple satisfies a demand for the permission represented by the flag.
+ /// </summary>
+ /// <remarks>
+ /// If the triple asserts for one of the bits in the flags, it is zeroed out.
+ /// </remarks>
+ /// <param name="flags">set of flags to check (See PermissionType)</param>
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckFlags(ref int flags)
+ {
+ if (AssertSet != null)
+ {
+ // remove any permissions which were asserted for
+ int assertFlags = SecurityManager.GetSpecialFlags(AssertSet, null);
+ if ((flags & assertFlags) != 0)
+ flags = flags & ~assertFlags;
+ }
+
+ return (SecurityManager.GetSpecialFlags(GrantSet, RefusedSet) & flags) == flags;
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Security/PermissionToken.cs b/src/mscorlib/src/System/Security/PermissionToken.cs
new file mode 100644
index 0000000000..e78c0f1a93
--- /dev/null
+++ b/src/mscorlib/src/System/Security/PermissionToken.cs
@@ -0,0 +1,563 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security {
+ using System;
+ using System.Security.Util;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using System.Collections;
+ using System.Threading;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ [Flags]
+ internal enum PermissionTokenType
+ {
+ Normal = 0x1,
+ IUnrestricted = 0x2,
+ DontKnow = 0x4,
+ BuiltIn = 0x8
+ }
+
+ [Serializable]
+ internal sealed class PermissionTokenKeyComparer : IEqualityComparer
+ {
+ private Comparer _caseSensitiveComparer;
+ private TextInfo _info;
+
+ public PermissionTokenKeyComparer()
+ {
+ _caseSensitiveComparer = new Comparer(CultureInfo.InvariantCulture);
+ _info = CultureInfo.InvariantCulture.TextInfo;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public int Compare(Object a, Object b)
+ {
+ String strA = a as String;
+ String strB = b as String;
+
+ // if it's not a string then we just call the object comparer
+ if (strA == null || strB == null)
+ return _caseSensitiveComparer.Compare(a, b);
+
+ int i = _caseSensitiveComparer.Compare(a,b);
+ if (i == 0)
+ return 0;
+
+ if (SecurityManager.IsSameType(strA, strB))
+ return 0;
+
+ return i;
+ }
+
+ public new bool Equals( Object a, Object b )
+ {
+ if (a == b) return true;
+ if (a == null || b == null) return false;
+ return Compare( a, b ) == 0;
+ }
+
+ // The data structure consuming this will be responsible for dealing with null objects as keys.
+ public int GetHashCode(Object obj)
+ {
+ if (obj == null) throw new ArgumentNullException("obj");
+ Contract.EndContractBlock();
+
+ String str = obj as String;
+
+ if (str == null)
+ return obj.GetHashCode();
+
+ int iComma = str.IndexOf( ',' );
+ if (iComma == -1)
+ iComma = str.Length;
+
+ int accumulator = 0;
+ for (int i = 0; i < iComma; ++i)
+ {
+ accumulator = (accumulator << 7) ^ str[i] ^ (accumulator >> 25);
+ }
+
+ return accumulator;
+ }
+ }
+
+ [Serializable]
+ internal sealed class PermissionToken : ISecurityEncodable
+ {
+ private static readonly PermissionTokenFactory s_theTokenFactory;
+#if FEATURE_CAS_POLICY
+ private static volatile ReflectionPermission s_reflectPerm = null;
+#endif // FEATURE_CAS_POLICY
+
+ private const string c_mscorlibName = System.CoreLib.Name;
+ internal int m_index;
+ internal volatile PermissionTokenType m_type;
+#if FEATURE_CAS_POLICY
+ internal String m_strTypeName;
+#endif // FEATURE_CAS_POLICY
+ static internal TokenBasedSet s_tokenSet = new TokenBasedSet();
+
+ internal static bool IsMscorlibClassName (string className) {
+ Contract.Assert( c_mscorlibName == ((RuntimeAssembly)Assembly.GetExecutingAssembly()).GetSimpleName(),
+ System.CoreLib.Name+" name mismatch" );
+
+ // If the class name does not look like a fully qualified name, we cannot simply determine if it's
+ // an mscorlib.dll type so we should return true so the type can be matched with the
+ // right index in the TokenBasedSet.
+ int index = className.IndexOf(',');
+ if (index == -1)
+ return true;
+
+ index = className.LastIndexOf(']');
+ if (index == -1)
+ index = 0;
+
+ // Search for the string 'mscorlib' in the classname. If we find it, we will conservatively assume it's an mscorlib.dll type and load it.
+ for (int i = index; i < className.Length; i++) {
+#if FEATURE_CORECLR
+ if (className[i] == 's' || className[i] == 'S')
+#else
+ if (className[i] == 'm' || className[i] == 'M')
+#endif
+ {
+ if (String.Compare(className, i, c_mscorlibName, 0, c_mscorlibName.Length, StringComparison.OrdinalIgnoreCase) == 0)
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static PermissionToken()
+ {
+ s_theTokenFactory = new PermissionTokenFactory( 4 );
+ }
+
+ internal PermissionToken()
+ {
+ }
+
+ internal PermissionToken(int index, PermissionTokenType type, String strTypeName)
+ {
+ m_index = index;
+ m_type = type;
+#if FEATURE_CAS_POLICY
+ m_strTypeName = strTypeName;
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public static PermissionToken GetToken(Type cls)
+ {
+ if (cls == null)
+ return null;
+
+#if FEATURE_CAS_POLICY
+ if (cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) != null)
+ {
+ if (s_reflectPerm == null)
+ s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted);
+ s_reflectPerm.Assert();
+ MethodInfo method = cls.GetMethod( "GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic );
+ Contract.Assert( method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'" );
+
+ // GetTokenIndex needs to be invoked without any security checks, since doing a security check
+ // will involve a ReflectionTargetDemand which creates a CompressedStack and attempts to get the
+ // token.
+ RuntimeMethodInfo getTokenIndex = method as RuntimeMethodInfo;
+ Contract.Assert(getTokenIndex != null, "method is not a RuntimeMethodInfo");
+ int token = (int)getTokenIndex.UnsafeInvoke(null, BindingFlags.Default, null, null, null);
+ return s_theTokenFactory.BuiltInGetToken(token, null, cls);
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ {
+ return s_theTokenFactory.GetToken(cls, null);
+ }
+ }
+
+ public static PermissionToken GetToken(IPermission perm)
+ {
+ if (perm == null)
+ return null;
+
+ IBuiltInPermission ibPerm = perm as IBuiltInPermission;
+
+ if (ibPerm != null)
+ return s_theTokenFactory.BuiltInGetToken( ibPerm.GetTokenIndex(), perm, null );
+ else
+ return s_theTokenFactory.GetToken(perm.GetType(), perm);
+ }
+
+#if FEATURE_CAS_POLICY
+ public static PermissionToken GetToken(String typeStr)
+ {
+ return GetToken( typeStr, false );
+ }
+
+#if _DEBUG
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ private static void GetTokenHelper(String typeStr)
+ {
+ new PermissionSet(PermissionState.Unrestricted).Assert();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Type type = RuntimeTypeHandle.GetTypeByName( typeStr.Trim().Replace( '\'', '\"' ), ref stackMark);
+ Contract.Assert( (type == null) || (type.Module.Assembly != System.Reflection.Assembly.GetExecutingAssembly()) || (typeStr.IndexOf("mscorlib", StringComparison.Ordinal) < 0),
+ "We should not go through this path for mscorlib based permissions" );
+ }
+#endif
+
+ public static PermissionToken GetToken(String typeStr, bool bCreateMscorlib)
+ {
+ if (typeStr == null)
+ return null;
+
+ if (IsMscorlibClassName( typeStr ))
+ {
+ if (!bCreateMscorlib)
+ {
+ return null;
+ }
+ else
+ {
+ return FindToken( Type.GetType( typeStr ) );
+ }
+ }
+ else
+ {
+ PermissionToken token = s_theTokenFactory.GetToken(typeStr);
+#if _DEBUG
+ GetTokenHelper(typeStr);
+#endif
+ return token;
+ }
+ }
+
+ [SecuritySafeCritical]
+ public static PermissionToken FindToken( Type cls )
+ {
+ if (cls == null)
+ return null;
+
+#if FEATURE_CAS_POLICY
+ if (cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) != null)
+ {
+ if (s_reflectPerm == null)
+ s_reflectPerm = new ReflectionPermission(PermissionState.Unrestricted);
+ s_reflectPerm.Assert();
+ MethodInfo method = cls.GetMethod( "GetTokenIndex", BindingFlags.Static | BindingFlags.NonPublic );
+ Contract.Assert( method != null, "IBuiltInPermission types should have a static method called 'GetTokenIndex'" );
+
+ // GetTokenIndex needs to be invoked without any security checks, since doing a security check
+ // will involve a ReflectionTargetDemand which creates a CompressedStack and attempts to get the
+ // token.
+ RuntimeMethodInfo getTokenIndex = method as RuntimeMethodInfo;
+ Contract.Assert(getTokenIndex != null, "method is not a RuntimeMethodInfo");
+ int token = (int)getTokenIndex.UnsafeInvoke(null, BindingFlags.Default, null, null, null);
+ return s_theTokenFactory.BuiltInGetToken(token, null, cls);
+ }
+ else
+#endif // FEATURE_CAS_POLICY
+ {
+ return s_theTokenFactory.FindToken( cls );
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public static PermissionToken FindTokenByIndex( int i )
+ {
+ return s_theTokenFactory.FindTokenByIndex( i );
+ }
+
+ public static bool IsTokenProperlyAssigned( IPermission perm, PermissionToken token )
+ {
+ PermissionToken heldToken = GetToken( perm );
+ if (heldToken.m_index != token.m_index)
+ return false;
+
+ if (token.m_type != heldToken.m_type)
+ return false;
+
+ if (perm.GetType().Module.Assembly == Assembly.GetExecutingAssembly() &&
+ heldToken.m_index >= BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED)
+ return false;
+
+ return true;
+ }
+
+#if FEATURE_CAS_POLICY
+ public SecurityElement ToXml()
+ {
+ Contract.Assert( (m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when ToXml is called" );
+ SecurityElement elRoot = new SecurityElement( "PermissionToken" );
+ if ((m_type & PermissionTokenType.BuiltIn) != 0)
+ elRoot.AddAttribute( "Index", "" + this.m_index );
+ else
+ elRoot.AddAttribute( "Name", SecurityElement.Escape( m_strTypeName ) );
+ elRoot.AddAttribute("Type", m_type.ToString("F"));
+ return elRoot;
+ }
+
+ public void FromXml(SecurityElement elRoot)
+ {
+ // For the most part there is no parameter checking here since this is an
+ // internal class and the serialization/deserialization path is controlled.
+
+ if (!elRoot.Tag.Equals( "PermissionToken" ))
+ Contract.Assert( false, "Tried to deserialize non-PermissionToken element here" );
+
+ String strName = elRoot.Attribute( "Name" );
+ PermissionToken realToken;
+ if (strName != null)
+ realToken = GetToken( strName, true );
+ else
+ realToken = FindTokenByIndex( Int32.Parse( elRoot.Attribute( "Index" ), CultureInfo.InvariantCulture ) );
+
+ this.m_index = realToken.m_index;
+ this.m_type = (PermissionTokenType) Enum.Parse(typeof(PermissionTokenType), elRoot.Attribute("Type"));
+ Contract.Assert((this.m_type & PermissionTokenType.DontKnow) == 0, "Should have valid token type when FromXml is called.");
+ this.m_strTypeName = realToken.m_strTypeName;
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ // Package access only
+ internal class PermissionTokenFactory
+ {
+ private volatile int m_size;
+ private volatile int m_index;
+ private volatile Hashtable m_tokenTable; // Cache of tokens by class string name
+ private volatile Hashtable m_handleTable; // Cache of tokens by type handle (IntPtr)
+ private volatile Hashtable m_indexTable; // Cache of tokens by index
+
+
+ // We keep an array of tokens for our built-in permissions.
+ // This is ordered in terms of unrestricted perms first, normals
+ // second. Of course, all the ordering is based on the individual
+ // permissions sticking to the deal, so we do some simple boundary
+ // checking but mainly leave it to faith.
+
+ private volatile PermissionToken[] m_builtIn;
+
+ private const String s_unrestrictedPermissionInferfaceName = "System.Security.Permissions.IUnrestrictedPermission";
+
+ internal PermissionTokenFactory( int size )
+ {
+ m_builtIn = new PermissionToken[BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED];
+
+ m_size = size;
+ m_index = BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED;
+ m_tokenTable = null;
+ m_handleTable = new Hashtable(size);
+ m_indexTable = new Hashtable(size);
+ }
+
+#if FEATURE_CAS_POLICY
+ [SecuritySafeCritical]
+ internal PermissionToken FindToken( Type cls )
+ {
+ IntPtr typePtr = cls.TypeHandle.Value;
+ PermissionToken tok = (PermissionToken)m_handleTable[typePtr];
+
+ if (tok != null)
+ return tok;
+
+ if (m_tokenTable == null)
+ return null;
+
+ tok = (PermissionToken)m_tokenTable[cls.AssemblyQualifiedName];
+
+ if (tok != null)
+ {
+ lock (this)
+ {
+ m_handleTable.Add(typePtr, tok);
+ }
+ }
+
+ return tok;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ internal PermissionToken FindTokenByIndex( int i )
+ {
+ PermissionToken token;
+
+ if (i < BuiltInPermissionIndex.NUM_BUILTIN_NORMAL + BuiltInPermissionIndex.NUM_BUILTIN_UNRESTRICTED)
+ {
+ token = BuiltInGetToken( i, null, null );
+ }
+ else
+ {
+ token = (PermissionToken)m_indexTable[i];
+ }
+
+ return token;
+ }
+
+ [SecuritySafeCritical]
+ internal PermissionToken GetToken(Type cls, IPermission perm)
+ {
+ Contract.Assert( cls != null, "Must pass in valid type" );
+
+ IntPtr typePtr = cls.TypeHandle.Value;
+ object tok = m_handleTable[typePtr];
+ if (tok == null)
+ {
+ String typeStr = cls.AssemblyQualifiedName;
+ tok = m_tokenTable != null ? m_tokenTable[typeStr] : null; // Assumes asynchronous lookups are safe
+
+ if (tok == null)
+ {
+ lock (this)
+ {
+ if (m_tokenTable != null)
+ {
+ tok = m_tokenTable[typeStr]; // Make sure it wasn't just added
+ }
+ else
+ m_tokenTable = new Hashtable(m_size, 1.0f, new PermissionTokenKeyComparer());
+
+ if (tok == null)
+ {
+ if (perm != null)
+ {
+ tok = new PermissionToken( m_index++, PermissionTokenType.IUnrestricted, typeStr );
+ }
+ else
+ {
+ if (cls.GetInterface(s_unrestrictedPermissionInferfaceName) != null)
+ tok = new PermissionToken( m_index++, PermissionTokenType.IUnrestricted, typeStr );
+ else
+ tok = new PermissionToken( m_index++, PermissionTokenType.Normal, typeStr );
+ }
+ m_tokenTable.Add(typeStr, tok);
+ m_indexTable.Add(m_index - 1, tok);
+ PermissionToken.s_tokenSet.SetItem( ((PermissionToken)tok).m_index, tok );
+ }
+
+ if (!m_handleTable.Contains(typePtr))
+ m_handleTable.Add( typePtr, tok );
+ }
+ }
+ else
+ {
+ lock (this)
+ {
+ if (!m_handleTable.Contains(typePtr))
+ m_handleTable.Add( typePtr, tok );
+ }
+ }
+ }
+
+ if ((((PermissionToken)tok).m_type & PermissionTokenType.DontKnow) != 0)
+ {
+ if (perm != null)
+ {
+ Contract.Assert( !(perm is IBuiltInPermission), "This should not be called for built-ins" );
+ ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted;
+#if FEATURE_CAS_POLICY
+ ((PermissionToken)tok).m_strTypeName = perm.GetType().AssemblyQualifiedName;
+#endif // FEATURE_CAS_POLICY
+ }
+ else
+ {
+ Contract.Assert( cls.GetInterface( "System.Security.Permissions.IBuiltInPermission" ) == null, "This shoudl not be called for built-ins" );
+ if (cls.GetInterface(s_unrestrictedPermissionInferfaceName) != null)
+ ((PermissionToken)tok).m_type = PermissionTokenType.IUnrestricted;
+ else
+ ((PermissionToken)tok).m_type = PermissionTokenType.Normal;
+#if FEATURE_CAS_POLICY
+ ((PermissionToken)tok).m_strTypeName = cls.AssemblyQualifiedName;
+#endif // FEATURE_CAS_POLICY
+ }
+ }
+
+ return (PermissionToken)tok;
+ }
+
+ internal PermissionToken GetToken(String typeStr)
+ {
+ Object tok = null;
+ tok = m_tokenTable != null ? m_tokenTable[typeStr] : null; // Assumes asynchronous lookups are safe
+ if (tok == null)
+ {
+ lock (this)
+ {
+ if (m_tokenTable != null)
+ {
+ tok = m_tokenTable[typeStr]; // Make sure it wasn't just added
+ }
+ else
+ m_tokenTable = new Hashtable(m_size, 1.0f, new PermissionTokenKeyComparer());
+
+ if (tok == null)
+ {
+ tok = new PermissionToken( m_index++, PermissionTokenType.DontKnow, typeStr );
+ m_tokenTable.Add(typeStr, tok);
+ m_indexTable.Add(m_index - 1, tok);
+ PermissionToken.s_tokenSet.SetItem(((PermissionToken)tok).m_index, tok);
+ }
+ }
+ }
+
+ return (PermissionToken)tok;
+ }
+
+ internal PermissionToken BuiltInGetToken( int index, IPermission perm, Type cls )
+ {
+ PermissionToken token = Volatile.Read(ref m_builtIn[index]);
+
+ if (token == null)
+ {
+ lock (this)
+ {
+ token = m_builtIn[index];
+
+ if (token == null)
+ {
+ PermissionTokenType permType = PermissionTokenType.DontKnow;
+
+ if (perm != null)
+ {
+ permType = PermissionTokenType.IUnrestricted;
+ }
+ else if (cls != null)
+ {
+ permType = PermissionTokenType.IUnrestricted;
+ }
+
+ token = new PermissionToken( index, permType | PermissionTokenType.BuiltIn, null );
+ Volatile.Write(ref m_builtIn[index], token);
+ PermissionToken.s_tokenSet.SetItem( token.m_index, token );
+ }
+ }
+ }
+
+ if ((token.m_type & PermissionTokenType.DontKnow) != 0)
+ {
+ token.m_type = PermissionTokenType.BuiltIn;
+
+ if (perm != null)
+ {
+ token.m_type |= PermissionTokenType.IUnrestricted;
+ }
+ else if (cls != null)
+ {
+ token.m_type |= PermissionTokenType.IUnrestricted;
+ }
+ else
+ {
+ token.m_type |= PermissionTokenType.DontKnow;
+ }
+ }
+
+ return token;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs b/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs
new file mode 100644
index 0000000000..8208ed3fb0
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/EnvironmentPermission.cs
@@ -0,0 +1,405 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions {
+ using System.Security;
+ using System;
+ using SecurityElement = System.Security.SecurityElement;
+ using System.Security.Util;
+ using System.IO;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum EnvironmentPermissionAccess
+ {
+ NoAccess = 0x00,
+ Read = 0x01,
+ Write = 0x02,
+ AllAccess = 0x03,
+ }
+
+ [Serializable]
+ internal class EnvironmentStringExpressionSet : StringExpressionSet
+ {
+ public EnvironmentStringExpressionSet()
+ : base( true, null, false )
+ {
+ }
+
+ public EnvironmentStringExpressionSet( String str )
+ : base( true, str, false )
+ {
+ }
+
+ protected override StringExpressionSet CreateNewEmpty()
+ {
+ return new EnvironmentStringExpressionSet();
+ }
+
+ protected override bool StringSubsetString( String left, String right, bool ignoreCase )
+ {
+ return (ignoreCase?(String.Compare( left, right, StringComparison.OrdinalIgnoreCase) == 0):
+ (String.Compare( left, right, StringComparison.Ordinal) == 0));
+ }
+
+ protected override String ProcessWholeString( String str )
+ {
+ return str;
+ }
+
+ protected override String ProcessSingleString( String str )
+ {
+ return str;
+ }
+
+ [SecuritySafeCritical]
+ public override string ToString()
+ {
+ // SafeCritical: we're not storing path information in the strings, so exposing them out is fine ...
+ // they're just the same strings that came in to the .ctor.
+ return base.UnsafeToString();
+ }
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class EnvironmentPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ private StringExpressionSet m_read;
+ private StringExpressionSet m_write;
+ private bool m_unrestricted;
+
+ public EnvironmentPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ m_unrestricted = true;
+ else if (state == PermissionState.None)
+ m_unrestricted = false;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+
+ public EnvironmentPermission( EnvironmentPermissionAccess flag, String pathList )
+ {
+ SetPathList( flag, pathList );
+ }
+
+ public void SetPathList( EnvironmentPermissionAccess flag, String pathList )
+ {
+ VerifyFlag( flag );
+
+ m_unrestricted = false;
+
+ if ((flag & EnvironmentPermissionAccess.Read) != 0)
+ m_read = null;
+
+ if ((flag & EnvironmentPermissionAccess.Write) != 0)
+ m_write = null;
+
+ AddPathList( flag, pathList );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddPathList( EnvironmentPermissionAccess flag, String pathList )
+ {
+ VerifyFlag( flag );
+
+ if (FlagIsSet( flag, EnvironmentPermissionAccess.Read ))
+ {
+ if (m_read == null)
+ m_read = new EnvironmentStringExpressionSet();
+ m_read.AddExpressions( pathList );
+ }
+
+ if (FlagIsSet( flag, EnvironmentPermissionAccess.Write ))
+ {
+ if (m_write == null)
+ m_write = new EnvironmentStringExpressionSet();
+ m_write.AddExpressions( pathList );
+ }
+
+ }
+
+ public String GetPathList( EnvironmentPermissionAccess flag )
+ {
+ VerifyFlag( flag );
+ ExclusiveFlag( flag );
+
+ if (FlagIsSet( flag, EnvironmentPermissionAccess.Read ))
+ {
+ if (m_read == null)
+ {
+ return "";
+ }
+ return m_read.ToString();
+ }
+
+ if (FlagIsSet( flag, EnvironmentPermissionAccess.Write ))
+ {
+ if (m_write == null)
+ {
+ return "";
+ }
+ return m_write.ToString();
+ }
+
+ /* not reached */
+
+ return "";
+ }
+
+
+ private void VerifyFlag( EnvironmentPermissionAccess flag )
+ {
+ if ((flag & ~EnvironmentPermissionAccess.AllAccess) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flag));
+ Contract.EndContractBlock();
+ }
+
+ private void ExclusiveFlag( EnvironmentPermissionAccess flag )
+ {
+ if (flag == EnvironmentPermissionAccess.NoAccess)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+
+ if (((int)flag & ((int)flag-1)) != 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+ Contract.EndContractBlock();
+ }
+
+
+ private bool FlagIsSet( EnvironmentPermissionAccess flag, EnvironmentPermissionAccess question )
+ {
+ return (flag & question) != 0;
+ }
+
+ private bool IsEmpty()
+ {
+ return (!m_unrestricted &&
+ (this.m_read == null || this.m_read.IsEmpty()) &&
+ (this.m_write == null || this.m_write.IsEmpty()));
+ }
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ public bool IsUnrestricted()
+ {
+ return m_unrestricted;
+ }
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ return this.IsEmpty();
+ }
+
+ try
+ {
+ EnvironmentPermission operand = (EnvironmentPermission)target;
+ if (operand.IsUnrestricted())
+ return true;
+ 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 )));
+ }
+ catch (InvalidCastException)
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ {
+ return null;
+ }
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+ else if (this.IsUnrestricted())
+ {
+ return target.Copy();
+ }
+
+ EnvironmentPermission operand = (EnvironmentPermission)target;
+
+ if (operand.IsUnrestricted())
+ {
+ return this.Copy();
+ }
+
+ StringExpressionSet intersectRead = this.m_read == null ? null : this.m_read.Intersect( operand.m_read );
+ StringExpressionSet intersectWrite = this.m_write == null ? null : this.m_write.Intersect( operand.m_write );
+
+ if ((intersectRead == null || intersectRead.IsEmpty()) &&
+ (intersectWrite == null || intersectWrite.IsEmpty()))
+ {
+ return null;
+ }
+
+ EnvironmentPermission intersectPermission = new EnvironmentPermission(PermissionState.None);
+ intersectPermission.m_unrestricted = false;
+ intersectPermission.m_read = intersectRead;
+ intersectPermission.m_write = intersectWrite;
+
+ return intersectPermission;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override IPermission Union(IPermission other)
+ {
+ if (other == null)
+ {
+ return this.Copy();
+ }
+ else if (!VerifyType(other))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ EnvironmentPermission operand = (EnvironmentPermission)other;
+
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ {
+ return new EnvironmentPermission( PermissionState.Unrestricted );
+ }
+
+ StringExpressionSet unionRead = this.m_read == null ? operand.m_read : this.m_read.Union( operand.m_read );
+ StringExpressionSet unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union( operand.m_write );
+
+ if ((unionRead == null || unionRead.IsEmpty()) &&
+ (unionWrite == null || unionWrite.IsEmpty()))
+ {
+ return null;
+ }
+
+ EnvironmentPermission unionPermission = new EnvironmentPermission(PermissionState.None);
+ unionPermission.m_unrestricted = false;
+ unionPermission.m_read = unionRead;
+ unionPermission.m_write = unionWrite;
+
+ return unionPermission;
+ }
+
+ public override IPermission Copy()
+ {
+ EnvironmentPermission copy = new EnvironmentPermission(PermissionState.None);
+ if (this.m_unrestricted)
+ {
+ copy.m_unrestricted = true;
+ }
+ else
+ {
+ copy.m_unrestricted = false;
+ if (this.m_read != null)
+ {
+ copy.m_read = this.m_read.Copy();
+ }
+ if (this.m_write != null)
+ {
+ copy.m_write = this.m_write.Copy();
+ }
+
+ }
+ return copy;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.EnvironmentPermission" );
+ if (!IsUnrestricted())
+ {
+ if (this.m_read != null && !this.m_read.IsEmpty())
+ {
+ 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() ) );
+ }
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+
+ String et;
+
+ if (XMLUtil.IsUnrestricted(esd))
+ {
+ m_unrestricted = true;
+ return;
+ }
+
+ m_unrestricted = false;
+ m_read = null;
+ m_write = null;
+
+ et = esd.Attribute( "Read" );
+ if (et != null)
+ {
+ m_read = new EnvironmentStringExpressionSet( et );
+ }
+
+ et = esd.Attribute( "Write" );
+ if (et != null)
+ {
+ m_write = new EnvironmentStringExpressionSet( et );
+ }
+
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return EnvironmentPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.EnvironmentPermissionIndex;
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs b/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs
new file mode 100644
index 0000000000..6d6c221cc9
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/FileDialogPermission.cs
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions {
+ using System;
+ using System.Text;
+ using System.Security;
+ using System.Security.Util;
+ using System.IO;
+ using System.Runtime.Serialization;
+ using System.Reflection;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileDialogPermissionAccess {
+ None = 0x00,
+
+ Open = 0x01,
+
+ Save = 0x02,
+
+ OpenSave = Open | Save
+
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class FileDialogPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
+ FileDialogPermissionAccess access;
+
+ public FileDialogPermission(PermissionState state) {
+ if (state == PermissionState.Unrestricted) {
+ SetUnrestricted(true);
+ }
+ else if (state == PermissionState.None) {
+ SetUnrestricted(false);
+ Reset();
+ }
+ else {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public FileDialogPermission(FileDialogPermissionAccess access) {
+ VerifyAccess(access);
+ this.access = access;
+ }
+
+ public FileDialogPermissionAccess Access {
+ get {
+ return access;
+ }
+
+ set {
+ VerifyAccess(value);
+ access = value;
+ }
+ }
+
+ public override IPermission Copy() {
+ return new FileDialogPermission(this.access);
+ }
+
+#if FEATURE_CAS_POLICY
+ public override void FromXml(SecurityElement esd) {
+ CodeAccessPermission.ValidateElement(esd, this);
+ if (XMLUtil.IsUnrestricted(esd)) {
+ SetUnrestricted(true);
+ return;
+ }
+
+ access = FileDialogPermissionAccess.None;
+
+ string accessXml = esd.Attribute("Access");
+ if (accessXml != null)
+ access = (FileDialogPermissionAccess)Enum.Parse(typeof(FileDialogPermissionAccess), accessXml);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex() {
+ return FileDialogPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex() {
+ return BuiltInPermissionIndex.FileDialogPermissionIndex;
+ }
+
+ public override IPermission Intersect(IPermission target) {
+ if (target == null) {
+ return null;
+ }
+ else if (!VerifyType(target)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ }
+
+ FileDialogPermission operand = (FileDialogPermission)target;
+
+ FileDialogPermissionAccess intersectAccess = access & operand.Access;
+
+ if (intersectAccess == FileDialogPermissionAccess.None)
+ return null;
+ else
+ return new FileDialogPermission(intersectAccess);
+ }
+
+ public override bool IsSubsetOf(IPermission target) {
+ if (target == null) {
+ // Only safe subset if this is empty
+ return access == FileDialogPermissionAccess.None;
+ }
+
+ try {
+ FileDialogPermission operand = (FileDialogPermission)target;
+ if (operand.IsUnrestricted()) {
+ return true;
+ }
+ else if (this.IsUnrestricted()) {
+ return false;
+ }
+ else {
+ int open = (int)(access & FileDialogPermissionAccess.Open);
+ int save = (int)(access & FileDialogPermissionAccess.Save);
+ int openTarget = (int)(operand.Access & FileDialogPermissionAccess.Open);
+ int saveTarget = (int)(operand.Access & FileDialogPermissionAccess.Save);
+
+ return open <= openTarget && save <= saveTarget;
+ }
+ }
+ catch (InvalidCastException) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ }
+
+ }
+
+ public bool IsUnrestricted() {
+ return access == FileDialogPermissionAccess.OpenSave;
+ }
+
+ void Reset() {
+ access = FileDialogPermissionAccess.None;
+ }
+
+ void SetUnrestricted( bool unrestricted ) {
+ if (unrestricted) {
+ access = FileDialogPermissionAccess.OpenSave;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml() {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.FileDialogPermission" );
+ if (!IsUnrestricted()) {
+ if (access != FileDialogPermissionAccess.None) {
+ esd.AddAttribute("Access", Enum.GetName(typeof(FileDialogPermissionAccess), access));
+ }
+ }
+ else {
+ esd.AddAttribute("Unrestricted", "true");
+ }
+ return esd;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public override IPermission Union(IPermission target) {
+ if (target == null) {
+ return this.Copy();
+ }
+ else if (!VerifyType(target)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ }
+
+ FileDialogPermission operand = (FileDialogPermission)target;
+ return new FileDialogPermission(access | operand.Access);
+ }
+
+ static void VerifyAccess(FileDialogPermissionAccess access) {
+ if ((access & ~FileDialogPermissionAccess.OpenSave) != 0 ) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access));
+ }
+ Contract.EndContractBlock();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs b/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs
new file mode 100644
index 0000000000..b4d4141f82
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/FileIOPermission.cs
@@ -0,0 +1,1478 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using System.Security.AccessControl;
+ using System.Security.Util;
+ using System.IO;
+ using System.Collections;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum FileIOPermissionAccess
+ {
+ NoAccess = 0x00,
+ Read = 0x01,
+ Write = 0x02,
+ Append = 0x04,
+ PathDiscovery = 0x08,
+ AllAccess = 0x0F,
+ }
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class FileIOPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ private FileIOAccess m_read;
+ private FileIOAccess m_write;
+ private FileIOAccess m_append;
+ private FileIOAccess m_pathDiscovery;
+ [OptionalField(VersionAdded = 2)]
+ private FileIOAccess m_viewAcl;
+ [OptionalField(VersionAdded = 2)]
+ private FileIOAccess m_changeAcl;
+ private bool m_unrestricted;
+
+ public FileIOPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_unrestricted = true;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_unrestricted = false;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileIOPermission( FileIOPermissionAccess access, String path )
+ {
+ VerifyAccess( access );
+
+ String[] pathList = new String[] { path };
+ AddPathList( access, pathList, false, true, false );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileIOPermission( FileIOPermissionAccess access, String[] pathList )
+ {
+ VerifyAccess( access );
+
+ AddPathList( access, pathList, false, true, false );
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileIOPermission( FileIOPermissionAccess access, AccessControlActions control, String path )
+ {
+ VerifyAccess( access );
+
+ String[] pathList = new String[] { path };
+ 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 )
+ {
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal FileIOPermission( FileIOPermissionAccess access, String[] pathList, bool checkForDuplicates, bool needFullPath )
+ {
+ 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 )
+ {
+ VerifyAccess( access );
+
+ AddPathList( access, control, pathList, checkForDuplicates, needFullPath, true );
+ }
+#endif
+
+ public void SetPathList( FileIOPermissionAccess access, String path )
+ {
+ String[] pathList;
+ if(path == null)
+ pathList = new String[] {};
+ else
+ pathList = new String[] { path };
+ SetPathList( access, pathList, false );
+ }
+
+ public void SetPathList( FileIOPermissionAccess access, String[] pathList )
+ {
+ SetPathList( access, pathList, true );
+ }
+
+ internal void SetPathList( FileIOPermissionAccess access,
+ String[] pathList, bool checkForDuplicates )
+ {
+ SetPathList( access, AccessControlActions.None, pathList, checkForDuplicates );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal void SetPathList( FileIOPermissionAccess access, AccessControlActions control, String[] pathList, bool checkForDuplicates )
+ {
+ 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;
+
+ if ((access & FileIOPermissionAccess.PathDiscovery) != 0)
+ m_pathDiscovery = null;
+
+#if FEATURE_MACL
+ if ((control & AccessControlActions.View) != 0)
+ m_viewAcl = null;
+
+ if ((control & AccessControlActions.Change) != 0)
+ m_changeAcl = null;
+#else
+ m_viewAcl = null;
+ m_changeAcl = null;
+#endif
+
+ m_unrestricted = false;
+#if FEATURE_MACL
+ 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 )
+ {
+ String[] pathList;
+ if(path == null)
+ pathList = new String[] {};
+ else
+ pathList = new String[] { path };
+ AddPathList( access, pathList, false, true, false );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddPathList( FileIOPermissionAccess access, String[] pathList )
+ {
+ AddPathList( access, pathList, true, true, true );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void AddPathList( FileIOPermissionAccess access, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList )
+ {
+ AddPathList( access, AccessControlActions.None, pathListOrig, checkForDuplicates, needFullPath, copyPathList );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void AddPathList(FileIOPermissionAccess access, AccessControlActions control, String[] pathListOrig, bool checkForDuplicates, bool needFullPath, bool copyPathList)
+ {
+ if (pathListOrig == null)
+ {
+ throw new ArgumentNullException( "pathList" );
+ }
+ if (pathListOrig.Length == 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_EmptyPath" ));
+ }
+ Contract.EndContractBlock();
+
+ VerifyAccess(access);
+
+ if (m_unrestricted)
+ return;
+
+ String[] pathList = pathListOrig;
+ 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);
+ }
+
+ ArrayList pathArrayList = StringExpressionSet.CreateListFromExpressions(pathList, needFullPath);
+
+ // 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.
+
+ if ((access & FileIOPermissionAccess.Read) != 0)
+ {
+ if (m_read == null)
+ {
+ m_read = new FileIOAccess();
+ }
+ m_read.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+
+ if ((access & FileIOPermissionAccess.Write) != 0)
+ {
+ if (m_write == null)
+ {
+ m_write = new FileIOAccess();
+ }
+ m_write.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+
+ if ((access & FileIOPermissionAccess.Append) != 0)
+ {
+ if (m_append == null)
+ {
+ m_append = new FileIOAccess();
+ }
+ m_append.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+
+ if ((access & FileIOPermissionAccess.PathDiscovery) != 0)
+ {
+ if (m_pathDiscovery == null)
+ {
+ m_pathDiscovery = new FileIOAccess( true );
+ }
+ m_pathDiscovery.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+
+#if FEATURE_MACL
+ if ((control & AccessControlActions.View) != 0)
+ {
+ if (m_viewAcl == null)
+ {
+ m_viewAcl = new FileIOAccess();
+ }
+ m_viewAcl.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+
+ if ((control & AccessControlActions.Change) != 0)
+ {
+ if (m_changeAcl == null)
+ {
+ m_changeAcl = new FileIOAccess();
+ }
+ m_changeAcl.AddExpressions( pathArrayList, checkForDuplicates);
+ }
+#endif
+ }
+
+ [SecuritySafeCritical]
+ public String[] GetPathList( FileIOPermissionAccess access )
+ {
+ VerifyAccess( access );
+ ExclusiveAccess( access );
+
+ if (AccessIsSet( access, FileIOPermissionAccess.Read ))
+ {
+ if (m_read == null)
+ {
+ return null;
+ }
+ return m_read.ToStringArray();
+ }
+
+ if (AccessIsSet( access, FileIOPermissionAccess.Write ))
+ {
+ if (m_write == null)
+ {
+ return null;
+ }
+ return m_write.ToStringArray();
+ }
+
+ if (AccessIsSet( access, FileIOPermissionAccess.Append ))
+ {
+ if (m_append == null)
+ {
+ return null;
+ }
+ return m_append.ToStringArray();
+ }
+
+ if (AccessIsSet( access, FileIOPermissionAccess.PathDiscovery ))
+ {
+ if (m_pathDiscovery == null)
+ {
+ return null;
+ }
+ return m_pathDiscovery.ToStringArray();
+ }
+
+ // not reached
+
+ return null;
+ }
+
+
+ public FileIOPermissionAccess AllLocalFiles
+ {
+ get
+ {
+ 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;
+ }
+
+ if (m_pathDiscovery != null && m_pathDiscovery.AllLocalFiles)
+ {
+ access |= FileIOPermissionAccess.PathDiscovery;
+ }
+
+ return access;
+ }
+
+ set
+ {
+ if ((value & FileIOPermissionAccess.Read) != 0)
+ {
+ if (m_read == null)
+ m_read = new FileIOAccess();
+
+ m_read.AllLocalFiles = true;
+ }
+ else
+ {
+ 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
+ {
+ 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
+ {
+ if (m_append != null)
+ m_append.AllLocalFiles = false;
+ }
+
+ if ((value & FileIOPermissionAccess.PathDiscovery) != 0)
+ {
+ if (m_pathDiscovery == null)
+ m_pathDiscovery = new FileIOAccess( true );
+
+ m_pathDiscovery.AllLocalFiles = true;
+ }
+ else
+ {
+ if (m_pathDiscovery != null)
+ m_pathDiscovery.AllLocalFiles = false;
+ }
+
+ }
+ }
+
+ 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;
+ }
+
+ return access;
+ }
+
+ set
+ {
+ if (value == FileIOPermissionAccess.AllAccess)
+ {
+ m_unrestricted = true;
+ return;
+ }
+
+ if ((value & FileIOPermissionAccess.Read) != 0)
+ {
+ if (m_read == null)
+ m_read = new FileIOAccess();
+
+ m_read.AllFiles = true;
+ }
+ else
+ {
+ 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
+ {
+ 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
+ {
+ if (m_append != null)
+ m_append.AllFiles = false;
+ }
+
+ if ((value & FileIOPermissionAccess.PathDiscovery) != 0)
+ {
+ if (m_pathDiscovery == null)
+ m_pathDiscovery = new FileIOAccess( true );
+
+ m_pathDiscovery.AllFiles = true;
+ }
+ else
+ {
+ if (m_pathDiscovery != null)
+ m_pathDiscovery.AllFiles = false;
+ }
+
+ }
+ }
+
+ [Pure]
+ 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 )
+ {
+ if (access == FileIOPermissionAccess.NoAccess)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+
+ if (((int) access & ((int)access-1)) != 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+ }
+
+ private static void CheckIllegalCharacters(String[] str, bool onlyCheckExtras)
+ {
+#if !PLATFORM_UNIX
+ for (int i = 0; i < str.Length; ++i)
+ {
+ // 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]);
+ }
+#else
+ // There are no "extras" on Unix
+ if (onlyCheckExtras)
+ return;
+
+ for (int i = 0; i < str.Length; ++i)
+ {
+ Path.CheckInvalidPathChars(str[i]);
+ }
+#endif
+ }
+
+#if !PLATFORM_UNIX
+ /// <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;
+ }
+#endif
+
+ private static bool AccessIsSet( FileIOPermissionAccess access, FileIOPermissionAccess question )
+ {
+ return (access & question) != 0;
+ }
+
+ private bool IsEmpty()
+ {
+ return (!m_unrestricted &&
+ (this.m_read == null || this.m_read.IsEmpty()) &&
+ (this.m_write == null || this.m_write.IsEmpty()) &&
+ (this.m_append == null || this.m_append.IsEmpty()) &&
+ (this.m_pathDiscovery == null || this.m_pathDiscovery.IsEmpty()) &&
+ (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)
+ {
+ return this.IsEmpty();
+ }
+
+ FileIOPermission operand = target as FileIOPermission;
+ if (operand == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+
+ if (operand.IsUnrestricted())
+ return true;
+ 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 )));
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ {
+ return null;
+ }
+
+ FileIOPermission operand = target as FileIOPermission;
+
+ if (operand == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ }
+ else if (this.IsUnrestricted())
+ {
+ 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 );
+
+ if ((intersectRead == null || intersectRead.IsEmpty()) &&
+ (intersectWrite == null || intersectWrite.IsEmpty()) &&
+ (intersectAppend == null || intersectAppend.IsEmpty()) &&
+ (intersectPathDiscovery == null || intersectPathDiscovery.IsEmpty()) &&
+ (intersectViewAcl == null || intersectViewAcl.IsEmpty()) &&
+ (intersectChangeAcl == null || intersectChangeAcl.IsEmpty()))
+ {
+ return null;
+ }
+
+ FileIOPermission intersectPermission = new FileIOPermission(PermissionState.None);
+ intersectPermission.m_unrestricted = false;
+ intersectPermission.m_read = intersectRead;
+ intersectPermission.m_write = intersectWrite;
+ intersectPermission.m_append = intersectAppend;
+ intersectPermission.m_pathDiscovery = intersectPathDiscovery;
+ intersectPermission.m_viewAcl = intersectViewAcl;
+ intersectPermission.m_changeAcl = intersectChangeAcl;
+
+ return intersectPermission;
+ }
+
+ public override IPermission Union(IPermission other)
+ {
+ if (other == null)
+ {
+ return this.Copy();
+ }
+
+ FileIOPermission operand = other as FileIOPermission;
+
+ if (operand == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ }
+
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ {
+ 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 );
+
+ if ((unionRead == null || unionRead.IsEmpty()) &&
+ (unionWrite == null || unionWrite.IsEmpty()) &&
+ (unionAppend == null || unionAppend.IsEmpty()) &&
+ (unionPathDiscovery == null || unionPathDiscovery.IsEmpty()) &&
+ (unionViewAcl == null || unionViewAcl.IsEmpty()) &&
+ (unionChangeAcl == null || unionChangeAcl.IsEmpty()))
+ {
+ return null;
+ }
+
+ FileIOPermission unionPermission = new FileIOPermission(PermissionState.None);
+ unionPermission.m_unrestricted = false;
+ unionPermission.m_read = unionRead;
+ unionPermission.m_write = unionWrite;
+ unionPermission.m_append = unionAppend;
+ unionPermission.m_pathDiscovery = unionPathDiscovery;
+ unionPermission.m_viewAcl = unionViewAcl;
+ unionPermission.m_changeAcl = unionChangeAcl;
+
+ return unionPermission;
+ }
+
+ public override IPermission Copy()
+ {
+ FileIOPermission copy = new FileIOPermission(PermissionState.None);
+ if (this.m_unrestricted)
+ {
+ copy.m_unrestricted = true;
+ }
+ else
+ {
+ copy.m_unrestricted = false;
+ if (this.m_read != null)
+ {
+ copy.m_read = this.m_read.Copy();
+ }
+ if (this.m_write != null)
+ {
+ copy.m_write = this.m_write.Copy();
+ }
+ if (this.m_append != null)
+ {
+ copy.m_append = this.m_append.Copy();
+ }
+ if (this.m_pathDiscovery != null)
+ {
+ copy.m_pathDiscovery = this.m_pathDiscovery.Copy();
+ }
+ if (this.m_viewAcl != null)
+ {
+ copy.m_viewAcl = this.m_viewAcl.Copy();
+ }
+ if (this.m_changeAcl != null)
+ {
+ copy.m_changeAcl = this.m_changeAcl.Copy();
+ }
+ }
+ return copy;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml()
+ {
+ 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() ) );
+ }
+ if (this.m_write != null && !this.m_write.IsEmpty())
+ {
+ 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() ) );
+ }
+ if (this.m_pathDiscovery != null && !this.m_pathDiscovery.IsEmpty())
+ {
+ 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() ) );
+ }
+ if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty())
+ {
+ esd.AddAttribute( "ChangeAcl", SecurityElement.Escape( m_changeAcl.ToString() ) );
+ }
+
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ String et;
+
+ if (XMLUtil.IsUnrestricted(esd))
+ {
+ m_unrestricted = true;
+ return;
+ }
+
+
+ m_unrestricted = false;
+
+ et = esd.Attribute( "Read" );
+ if (et != null)
+ {
+ m_read = new FileIOAccess( et );
+ }
+ else
+ {
+ m_read = null;
+ }
+
+ et = esd.Attribute( "Write" );
+ if (et != null)
+ {
+ m_write = new FileIOAccess( et );
+ }
+ else
+ {
+ m_write = null;
+ }
+
+ et = esd.Attribute( "Append" );
+ if (et != null)
+ {
+ m_append = new FileIOAccess( et );
+ }
+ else
+ {
+ m_append = null;
+ }
+
+ et = esd.Attribute( "PathDiscovery" );
+ if (et != null)
+ {
+ m_pathDiscovery = new FileIOAccess( et );
+ m_pathDiscovery.PathDiscovery = true;
+ }
+ else
+ {
+ m_pathDiscovery = null;
+ }
+
+ et = esd.Attribute( "ViewAcl" );
+ if (et != null)
+ {
+ m_viewAcl = new FileIOAccess( et );
+ }
+ else
+ {
+ m_viewAcl = null;
+ }
+
+ et = esd.Attribute( "ChangeAcl" );
+ if (et != null)
+ {
+ m_changeAcl = new FileIOAccess( et );
+ }
+ else
+ {
+ m_changeAcl = null;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return FileIOPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.FileIOPermissionIndex;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals(Object obj)
+ {
+ FileIOPermission perm = obj as FileIOPermission;
+ if(perm == null)
+ return false;
+
+ if(m_unrestricted && perm.m_unrestricted)
+ return true;
+ if(m_unrestricted != perm.m_unrestricted)
+ return false;
+
+ if(m_read == null)
+ {
+ if(perm.m_read != null && !perm.m_read.IsEmpty())
+ return false;
+ }
+ else if(!m_read.Equals(perm.m_read))
+ return false;
+
+ if(m_write == null)
+ {
+ if(perm.m_write != null && !perm.m_write.IsEmpty())
+ return false;
+ }
+ else if(!m_write.Equals(perm.m_write))
+ return false;
+
+ if(m_append == null)
+ {
+ if(perm.m_append != null && !perm.m_append.IsEmpty())
+ return false;
+ }
+ else if(!m_append.Equals(perm.m_append))
+ return false;
+
+ if(m_pathDiscovery == null)
+ {
+ if(perm.m_pathDiscovery != null && !perm.m_pathDiscovery.IsEmpty())
+ return false;
+ }
+ else if(!m_pathDiscovery.Equals(perm.m_pathDiscovery))
+ return false;
+
+ if(m_viewAcl == null)
+ {
+ if(perm.m_viewAcl != null && !perm.m_viewAcl.IsEmpty())
+ return false;
+ }
+ else if(!m_viewAcl.Equals(perm.m_viewAcl))
+ return false;
+
+ if(m_changeAcl == null)
+ {
+ if(perm.m_changeAcl != null && !perm.m_changeAcl.IsEmpty())
+ return false;
+ }
+ else if(!m_changeAcl.Equals(perm.m_changeAcl))
+ return false;
+
+ return true;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ // This implementation is only to silence a compiler warning.
+ return base.GetHashCode();
+ }
+
+ /// <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 fullPath, bool checkForDuplicates = false, bool needFullPath = false)
+ {
+#if FEATURE_CAS_POLICY
+ if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+ {
+ new FileIOPermission(access, new string[] { fullPath }, checkForDuplicates, needFullPath).Demand();
+ }
+ else
+#endif
+ {
+ 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 FEATURE_CAS_POLICY
+ if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+ {
+ new FileIOPermission(access, fullPathList, checkForDuplicates, needFullPath).Demand();
+ }
+ else
+#endif
+ {
+ foreach (string fullPath in fullPathList)
+ {
+ EmulateFileIOPermissionChecks(fullPath);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal static void QuickDemand(PermissionState state)
+ {
+ // Should be a no-op without CAS
+#if FEATURE_CAS_POLICY
+ if (!CodeAccessSecurityEngine.QuickCheckForAllDemands())
+ {
+ new FileIOPermission(state).Demand();
+ }
+#endif
+ }
+
+#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)
+ {
+ 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 (
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.UseLegacyPathHandling ||
+#endif
+ !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
+ {
+#if !FEATURE_CASE_SENSITIVE_FILESYSTEM
+ private bool m_ignoreCase = true;
+#else
+ private bool m_ignoreCase = false;
+#endif // !FEATURE_CASE_SENSITIVE_FILESYSTEM
+
+ private StringExpressionSet m_set;
+ private bool m_allFiles;
+ private bool m_allLocalFiles;
+ private bool m_pathDiscovery;
+
+ private const String m_strAllFiles = "*AllFiles*";
+ private const String m_strAllLocalFiles = "*AllLocalFiles*";
+
+ public FileIOAccess()
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, true );
+ m_allFiles = false;
+ m_allLocalFiles = false;
+ m_pathDiscovery = false;
+ }
+
+ public FileIOAccess( bool pathDiscovery )
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, true );
+ m_allFiles = false;
+ m_allLocalFiles = false;
+ m_pathDiscovery = pathDiscovery;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public FileIOAccess( String value )
+ {
+ if (value == null)
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, true );
+ m_allFiles = false;
+ m_allLocalFiles = false;
+ }
+ else if (value.Length >= m_strAllFiles.Length && String.Compare( m_strAllFiles, value, StringComparison.Ordinal) == 0)
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, true );
+ m_allFiles = true;
+ m_allLocalFiles = false;
+ }
+ else if (value.Length >= m_strAllLocalFiles.Length && String.Compare( m_strAllLocalFiles, 0, value, 0, m_strAllLocalFiles.Length, StringComparison.Ordinal) == 0)
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, value.Substring( m_strAllLocalFiles.Length ), true );
+ m_allFiles = false;
+ m_allLocalFiles = true;
+ }
+ else
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, value, true );
+ m_allFiles = false;
+ m_allLocalFiles = false;
+ }
+ m_pathDiscovery = false;
+ }
+
+ public FileIOAccess( bool allFiles, bool allLocalFiles, bool pathDiscovery )
+ {
+ m_set = new StringExpressionSet( m_ignoreCase, true );
+ m_allFiles = allFiles;
+ m_allLocalFiles = allLocalFiles;
+ m_pathDiscovery = pathDiscovery;
+ }
+
+ public FileIOAccess( StringExpressionSet set, bool allFiles, bool allLocalFiles, bool pathDiscovery )
+ {
+ m_set = set;
+ m_set.SetThrowOnRelative( true );
+ m_allFiles = allFiles;
+ m_allLocalFiles = allLocalFiles;
+ m_pathDiscovery = pathDiscovery;
+ }
+
+ private FileIOAccess( FileIOAccess operand )
+ {
+ m_set = operand.m_set.Copy();
+ m_allFiles = operand.m_allFiles;
+ m_allLocalFiles = operand.m_allLocalFiles;
+ m_pathDiscovery = operand.m_pathDiscovery;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddExpressions(ArrayList values, bool checkForDuplicates)
+ {
+ m_allFiles = false;
+ m_set.AddExpressions(values, checkForDuplicates);
+ }
+
+ public bool AllFiles
+ {
+ get
+ {
+ return m_allFiles;
+ }
+
+ set
+ {
+ m_allFiles = value;
+ }
+ }
+
+ public bool AllLocalFiles
+ {
+ get
+ {
+ return m_allLocalFiles;
+ }
+
+ set
+ {
+ m_allLocalFiles = value;
+ }
+ }
+
+ public bool PathDiscovery
+ {
+ set
+ {
+ m_pathDiscovery = value;
+ }
+ }
+
+ public bool IsEmpty()
+ {
+ return !m_allFiles && !m_allLocalFiles && (m_set == null || m_set.IsEmpty());
+ }
+
+ public FileIOAccess Copy()
+ {
+ return new FileIOAccess( this );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileIOAccess Union( FileIOAccess operand )
+ {
+ if (operand == null)
+ {
+ return this.IsEmpty() ? null : this.Copy();
+ }
+
+ Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" );
+
+ if (this.m_allFiles || operand.m_allFiles)
+ {
+ return new FileIOAccess( true, false, this.m_pathDiscovery );
+ }
+
+ return new FileIOAccess( this.m_set.Union( operand.m_set ), false, this.m_allLocalFiles || operand.m_allLocalFiles, this.m_pathDiscovery );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public FileIOAccess Intersect( FileIOAccess operand )
+ {
+ if (operand == null)
+ {
+ return null;
+ }
+
+ Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" );
+
+ if (this.m_allFiles)
+ {
+ if (operand.m_allFiles)
+ {
+ return new FileIOAccess( true, false, this.m_pathDiscovery );
+ }
+ else
+ {
+ return new FileIOAccess( operand.m_set.Copy(), false, operand.m_allLocalFiles, this.m_pathDiscovery );
+ }
+ }
+ else if (operand.m_allFiles)
+ {
+ return new FileIOAccess( this.m_set.Copy(), false, this.m_allLocalFiles, this.m_pathDiscovery );
+ }
+
+ StringExpressionSet intersectionSet = new StringExpressionSet( m_ignoreCase, true );
+
+ if (this.m_allLocalFiles)
+ {
+ String[] expressions = operand.m_set.UnsafeToStringArray();
+
+ if (expressions != null)
+ {
+ for (int i = 0; i < expressions.Length; ++i)
+ {
+ String root = GetRoot( expressions[i] );
+ if (root != null && IsLocalDrive( GetRoot( root ) ) )
+ {
+ intersectionSet.AddExpressions( new String[] { expressions[i] }, true, false );
+ }
+ }
+ }
+ }
+
+ if (operand.m_allLocalFiles)
+ {
+ String[] expressions = this.m_set.UnsafeToStringArray();
+
+ if (expressions != null)
+ {
+ for (int i = 0; i < expressions.Length; ++i)
+ {
+ String root = GetRoot( expressions[i] );
+ if (root != null && IsLocalDrive(GetRoot(root)))
+ {
+ intersectionSet.AddExpressions( new String[] { expressions[i] }, true, false );
+ }
+ }
+ }
+ }
+
+ String[] regularIntersection = this.m_set.Intersect( operand.m_set ).UnsafeToStringArray();
+
+ if (regularIntersection != null)
+ intersectionSet.AddExpressions( regularIntersection, !intersectionSet.IsEmpty(), false );
+
+ return new FileIOAccess( intersectionSet, false, this.m_allLocalFiles && operand.m_allLocalFiles, this.m_pathDiscovery );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool IsSubsetOf( FileIOAccess operand )
+ {
+ if (operand == null)
+ {
+ return this.IsEmpty();
+ }
+
+ if (operand.m_allFiles)
+ {
+ return true;
+ }
+
+ Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" );
+
+ if (!((m_pathDiscovery && this.m_set.IsSubsetOfPathDiscovery( operand.m_set )) || this.m_set.IsSubsetOf( operand.m_set )))
+ {
+ if (operand.m_allLocalFiles)
+ {
+ String[] expressions = m_set.UnsafeToStringArray();
+
+ for (int i = 0; i < expressions.Length; ++i)
+ {
+ String root = GetRoot( expressions[i] );
+ if (root == null || !IsLocalDrive(GetRoot(root)))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static String GetRoot( String path )
+ {
+#if !PLATFORM_UNIX
+ String str = path.Substring( 0, 3 );
+ if (str.EndsWith( ":\\", StringComparison.Ordinal))
+#else
+ String str = path.Substring( 0, 1 );
+ if(str == "/")
+#endif // !PLATFORM_UNIX
+ {
+ return str;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ [SecuritySafeCritical]
+ public override String ToString()
+ {
+ // SafeCritical: all string expression sets are constructed with the throwOnRelative bit set, so
+ // we're only exposing out the same paths that we took as input.
+ if (m_allFiles)
+ {
+ return m_strAllFiles;
+ }
+ else
+ {
+ if (m_allLocalFiles)
+ {
+ String retstr = m_strAllLocalFiles;
+
+ String tempStr = m_set.UnsafeToString();
+
+ if (tempStr != null && tempStr.Length > 0)
+ retstr += ";" + tempStr;
+
+ return retstr;
+ }
+ else
+ {
+ return m_set.UnsafeToString();
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ public String[] ToStringArray()
+ {
+ // SafeCritical: all string expression sets are constructed with the throwOnRelative bit set, so
+ // we're only exposing out the same paths that we took as input.
+ return m_set.UnsafeToStringArray();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern bool IsLocalDrive(String path);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool Equals(Object obj)
+ {
+ FileIOAccess operand = obj as FileIOAccess;
+ if(operand == null)
+ return (IsEmpty() && obj == null);
+ Contract.Assert( this.m_pathDiscovery == operand.m_pathDiscovery, "Path discovery settings must match" );
+ if(m_pathDiscovery)
+ {
+ if(this.m_allFiles && operand.m_allFiles)
+ return true;
+ if(this.m_allLocalFiles == operand.m_allLocalFiles &&
+ m_set.IsSubsetOf(operand.m_set) &&
+ operand.m_set.IsSubsetOf(m_set)) // Watch Out: This calls StringExpressionSet.IsSubsetOf, unlike below
+ return true;
+ return false;
+ }
+ else
+ {
+ if(!this.IsSubsetOf(operand)) // Watch Out: This calls FileIOAccess.IsSubsetOf, unlike above
+ return false;
+ if(!operand.IsSubsetOf(this))
+ return false;
+ return true;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ // This implementation is only to silence a compiler warning.
+ return base.GetHashCode();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs
new file mode 100644
index 0000000000..5c209afb9d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/GACIdentityPermission.cs
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using System.Globalization;
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class GacIdentityPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+#pragma warning disable 618
+ public GacIdentityPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public override IPermission CreatePermission()
+ {
+ return new GacIdentityPermission();
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class GacIdentityPermission : CodeAccessPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ public GacIdentityPermission(PermissionState state)
+ {
+ if (state != PermissionState.Unrestricted && state != PermissionState.None)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public GacIdentityPermission()
+ {
+ }
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+
+ public override IPermission Copy()
+ {
+ return new GacIdentityPermission();
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ return false;
+ if (!(target is GacIdentityPermission))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ return true;
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ if (!(target is GacIdentityPermission))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ return this.Copy();
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ return this.Copy();
+ if (!(target is GacIdentityPermission))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ return this.Copy();
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml()
+ {
+ SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.GacIdentityPermission" );
+ return securityElement;
+ }
+
+ public override void FromXml(SecurityElement securityElement)
+ {
+ CodeAccessPermission.ValidateElement(securityElement, this);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return GacIdentityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.GacIdentityPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs b/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs
new file mode 100644
index 0000000000..85be61a00d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/HostProtectionPermission.cs
@@ -0,0 +1,299 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using System.IO;
+ using System.Security.Util;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.Remoting;
+ using System.Security;
+ using System.Runtime.Serialization;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ // Keep this enum in sync with tools\ngen\ngen.cpp and inc\mscoree.idl
+
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum HostProtectionResource
+ {
+ None = 0x0,
+ //--------------------------------
+ Synchronization = 0x1,
+ SharedState = 0x2,
+ ExternalProcessMgmt = 0x4,
+ SelfAffectingProcessMgmt = 0x8,
+ ExternalThreading = 0x10,
+ SelfAffectingThreading = 0x20,
+ SecurityInfrastructure = 0x40,
+ UI = 0x80,
+ MayLeakOnAbort = 0x100,
+ //---------------------------------
+ All = 0x1ff,
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly | AttributeTargets.Delegate, AllowMultiple = true, Inherited = false )]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#if FEATURE_CORECLR
+ // This needs to be in the asmmeta to enable SecAnnotate to successfully resolve and run the security rules. It gets marked
+ // as internal by BCLRewriter so we are simply marking it as FriendAccessAllowed so it stays in the asmmeta.
+ [System.Runtime.CompilerServices.FriendAccessAllowedAttribute]
+#endif // FEATURE_CORECLR
+#pragma warning disable 618
+ sealed public class HostProtectionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private HostProtectionResource m_resources = HostProtectionResource.None;
+
+ public HostProtectionAttribute()
+#pragma warning disable 618
+ : base( SecurityAction.LinkDemand )
+#pragma warning restore 618
+ {
+ }
+
+#pragma warning disable 618
+ public HostProtectionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+#pragma warning disable 618
+ if (action != SecurityAction.LinkDemand)
+#pragma warning restore 618
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"));
+ Contract.EndContractBlock();
+ }
+
+ public HostProtectionResource Resources {
+ get { return m_resources; }
+ set { m_resources = value; }
+ }
+
+ public bool Synchronization {
+ get { return (m_resources & HostProtectionResource.Synchronization) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.Synchronization : m_resources & ~HostProtectionResource.Synchronization); }
+ }
+
+ public bool SharedState {
+ get { return (m_resources & HostProtectionResource.SharedState) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.SharedState : m_resources & ~HostProtectionResource.SharedState); }
+ }
+
+ public bool ExternalProcessMgmt {
+ get { return (m_resources & HostProtectionResource.ExternalProcessMgmt) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.ExternalProcessMgmt : m_resources & ~HostProtectionResource.ExternalProcessMgmt); }
+ }
+
+ public bool SelfAffectingProcessMgmt {
+ get { return (m_resources & HostProtectionResource.SelfAffectingProcessMgmt) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.SelfAffectingProcessMgmt : m_resources & ~HostProtectionResource.SelfAffectingProcessMgmt); }
+ }
+
+ public bool ExternalThreading {
+ get { return (m_resources & HostProtectionResource.ExternalThreading) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.ExternalThreading : m_resources & ~HostProtectionResource.ExternalThreading); }
+ }
+
+ public bool SelfAffectingThreading {
+ get { return (m_resources & HostProtectionResource.SelfAffectingThreading) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.SelfAffectingThreading : m_resources & ~HostProtectionResource.SelfAffectingThreading); }
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public bool SecurityInfrastructure {
+ get { return (m_resources & HostProtectionResource.SecurityInfrastructure) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.SecurityInfrastructure : m_resources & ~HostProtectionResource.SecurityInfrastructure); }
+ }
+
+ public bool UI {
+ get { return (m_resources & HostProtectionResource.UI) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.UI : m_resources & ~HostProtectionResource.UI); }
+ }
+
+ public bool MayLeakOnAbort {
+ get { return (m_resources & HostProtectionResource.MayLeakOnAbort) != 0; }
+ set { m_resources = (value ? m_resources | HostProtectionResource.MayLeakOnAbort : m_resources & ~HostProtectionResource.MayLeakOnAbort); }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new HostProtectionPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new HostProtectionPermission( m_resources );
+ }
+ }
+ }
+
+ [Serializable]
+ sealed internal class HostProtectionPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // GLOBALS
+ //
+ //------------------------------------------------------
+
+ // This value is set by PermissionSet.FilterHostProtectionPermissions. It is only used for
+ // constructing a HostProtectionException object. Changing it will not affect HostProtection.
+ internal static volatile HostProtectionResource protectedResources = HostProtectionResource.None;
+
+ //------------------------------------------------------
+ //
+ // MEMBERS
+ //
+ //------------------------------------------------------
+ private HostProtectionResource m_resources;
+
+ //------------------------------------------------------
+ //
+ // CONSTRUCTORS
+ //
+ //------------------------------------------------------
+ public HostProtectionPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ Resources = HostProtectionResource.All;
+ else if (state == PermissionState.None)
+ Resources = HostProtectionResource.None;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+
+ public HostProtectionPermission(HostProtectionResource resources)
+ {
+ Resources = resources;
+ }
+
+ //------------------------------------------------------
+ //
+ // IPermission interface implementation
+ //
+ //------------------------------------------------------
+ public bool IsUnrestricted()
+ {
+ return Resources == HostProtectionResource.All;
+ }
+
+ //------------------------------------------------------
+ //
+ // Properties
+ //
+ //------------------------------------------------------
+ public HostProtectionResource Resources
+ {
+ set
+ {
+ if(value < HostProtectionResource.None || value > HostProtectionResource.All)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)value));
+ Contract.EndContractBlock();
+ m_resources = value;
+ }
+
+ get
+ {
+ return m_resources;
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // IPermission interface implementation
+ //
+ //------------------------------------------------------
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ return m_resources == HostProtectionResource.None;
+ if(this.GetType() != target.GetType())
+ throw new ArgumentException( Environment.GetResourceString("Argument_WrongType", this.GetType().FullName) );
+ return ((uint)this.m_resources & (uint)((HostProtectionPermission)target).m_resources) == (uint)this.m_resources;
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ return(this.Copy());
+ if(this.GetType() != target.GetType())
+ throw new ArgumentException( Environment.GetResourceString("Argument_WrongType", this.GetType().FullName) );
+ HostProtectionResource newResources = (HostProtectionResource)((uint)this.m_resources | (uint)((HostProtectionPermission)target).m_resources);
+ return new HostProtectionPermission(newResources);
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ if(this.GetType() != target.GetType())
+ throw new ArgumentException( Environment.GetResourceString("Argument_WrongType", this.GetType().FullName) );
+ HostProtectionResource newResources = (HostProtectionResource)((uint)this.m_resources & (uint)((HostProtectionPermission)target).m_resources);
+ if(newResources == HostProtectionResource.None)
+ return null;
+ return new HostProtectionPermission(newResources);
+ }
+
+ public override IPermission Copy()
+ {
+ return new HostProtectionPermission(m_resources);
+ }
+
+#if FEATURE_CAS_POLICY
+ //------------------------------------------------------
+ //
+ // XML
+ //
+ //------------------------------------------------------
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, this.GetType().FullName );
+ if(IsUnrestricted())
+ esd.AddAttribute( "Unrestricted", "true" );
+ else
+ esd.AddAttribute( "Resources", XMLUtil.BitFieldEnumToString( typeof( HostProtectionResource ), Resources ) );
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ if (XMLUtil.IsUnrestricted( esd ))
+ Resources = HostProtectionResource.All;
+ else
+ {
+ String resources = esd.Attribute( "Resources" );
+ if (resources == null)
+ Resources = HostProtectionResource.None;
+ else
+ Resources = (HostProtectionResource)Enum.Parse( typeof( HostProtectionResource ), resources );
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ //------------------------------------------------------
+ //
+ // OBJECT OVERRIDES
+ //
+ //------------------------------------------------------
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return HostProtectionPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.HostProtectionPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/IBuiltInPermission.cs b/src/mscorlib/src/System/Security/Permissions/IBuiltInPermission.cs
new file mode 100644
index 0000000000..58b26bd9c4
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/IBuiltInPermission.cs
@@ -0,0 +1,63 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ internal interface IBuiltInPermission
+ {
+ int GetTokenIndex();
+ }
+
+ internal static class BuiltInPermissionIndex
+ {
+ internal const int NUM_BUILTIN_UNRESTRICTED = 10;
+ internal const int NUM_BUILTIN_NORMAL = 7;
+
+ // Unrestricted permissions
+
+ internal const int EnvironmentPermissionIndex = 0;
+ internal const int FileDialogPermissionIndex = 1;
+ internal const int FileIOPermissionIndex = 2;
+ internal const int IsolatedStorageFilePermissionIndex = 3;
+ internal const int ReflectionPermissionIndex = 4;
+ internal const int RegistryPermissionIndex = 5;
+ internal const int SecurityPermissionIndex = 6;
+ internal const int UIPermissionIndex = 7;
+ internal const int PrincipalPermissionIndex = 8;
+ internal const int HostProtectionPermissionIndex = 9;
+
+ // Normal permissions
+ internal const int PublisherIdentityPermissionIndex = 0 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int SiteIdentityPermissionIndex = 1 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int StrongNameIdentityPermissionIndex = 2 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int UrlIdentityPermissionIndex = 3 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int ZoneIdentityPermissionIndex = 4 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int GacIdentityPermissionIndex = 5 + NUM_BUILTIN_UNRESTRICTED;
+ internal const int KeyContainerPermissionIndex = 6 + NUM_BUILTIN_UNRESTRICTED;
+ }
+
+ [Serializable]
+ internal enum BuiltInPermissionFlag
+ {
+ // Unrestricted permissions
+
+ EnvironmentPermission = 0x1,
+ FileDialogPermission = 0x2,
+ FileIOPermission = 0x4,
+ IsolatedStorageFilePermission = 0x8,
+ ReflectionPermission = 0x10,
+ RegistryPermission = 0x20,
+ SecurityPermission = 0x40,
+ UIPermission = 0x80,
+ PrincipalPermission = 0x100,
+
+ // Normal permissions
+ PublisherIdentityPermission = 0x200,
+ SiteIdentityPermission = 0x400,
+ StrongNameIdentityPermission = 0x800,
+ UrlIdentityPermission = 0x1000,
+ ZoneIdentityPermission = 0x2000,
+ KeyContainerPermission = 0x4000,
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/IUnrestrictedPermission.cs b/src/mscorlib/src/System/Security/Permissions/IUnrestrictedPermission.cs
new file mode 100644
index 0000000000..782df8012c
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/IUnrestrictedPermission.cs
@@ -0,0 +1,13 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions {
+
+ using System;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IUnrestrictedPermission
+ {
+ bool IsUnrestricted();
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs b/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs
new file mode 100644
index 0000000000..1e11b4aa7f
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/IsolatedStorageFilePermission.cs
@@ -0,0 +1,176 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// Purpose : This permission is used to controls/administer access to
+// IsolatedStorageFile
+//
+
+namespace System.Security.Permissions {
+
+ using System.Globalization;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class IsolatedStorageFilePermission : IsolatedStoragePermission, IBuiltInPermission
+ {
+ public IsolatedStorageFilePermission(PermissionState state)
+ : base(state) { }
+
+ internal IsolatedStorageFilePermission(IsolatedStorageContainment UsageAllowed,
+ long ExpirationDays, bool PermanentData)
+ : base(UsageAllowed, ExpirationDays, PermanentData) { }
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ return this.Copy();
+ }
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ IsolatedStorageFilePermission operand = (IsolatedStorageFilePermission)target;
+
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ {
+ return new IsolatedStorageFilePermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ IsolatedStorageFilePermission union;
+ union = new IsolatedStorageFilePermission( PermissionState.None );
+ union.m_userQuota = max(m_userQuota,operand.m_userQuota);
+ union.m_machineQuota = max(m_machineQuota,operand.m_machineQuota);
+ union.m_expirationDays = max(m_expirationDays,operand.m_expirationDays);
+ union.m_permanentData = m_permanentData || operand.m_permanentData;
+ union.m_allowed = (IsolatedStorageContainment)max((long)m_allowed,(long)operand.m_allowed);
+ return union;
+ }
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ return ((m_userQuota == 0) &&
+ (m_machineQuota == 0) &&
+ (m_expirationDays == 0) &&
+ (m_permanentData == false) &&
+ (m_allowed == IsolatedStorageContainment.None));
+ }
+
+ try
+ {
+ IsolatedStorageFilePermission operand = (IsolatedStorageFilePermission)target;
+
+ if (operand.IsUnrestricted())
+ return true;
+
+ return ((operand.m_userQuota >= m_userQuota) &&
+ (operand.m_machineQuota >= m_machineQuota) &&
+ (operand.m_expirationDays >= m_expirationDays) &&
+ (operand.m_permanentData || !m_permanentData) &&
+ (operand.m_allowed >= m_allowed));
+ }
+ catch (InvalidCastException)
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ IsolatedStorageFilePermission operand = (IsolatedStorageFilePermission)target;
+
+ if(operand.IsUnrestricted())
+ return Copy();
+ else if(IsUnrestricted())
+ return target.Copy();
+
+ IsolatedStorageFilePermission intersection;
+ intersection = new IsolatedStorageFilePermission( PermissionState.None );
+ intersection.m_userQuota = min(m_userQuota,operand.m_userQuota);
+ intersection.m_machineQuota = min(m_machineQuota,operand.m_machineQuota);
+ intersection.m_expirationDays = min(m_expirationDays,operand.m_expirationDays);
+ intersection.m_permanentData = m_permanentData && operand.m_permanentData;
+ intersection.m_allowed = (IsolatedStorageContainment)min((long)m_allowed,(long)operand.m_allowed);
+
+ if ((intersection.m_userQuota == 0) &&
+ (intersection.m_machineQuota == 0) &&
+ (intersection.m_expirationDays == 0) &&
+ (intersection.m_permanentData == false) &&
+ (intersection.m_allowed == IsolatedStorageContainment.None))
+ return null;
+
+ return intersection;
+ }
+
+ public override IPermission Copy()
+ {
+ IsolatedStorageFilePermission copy ;
+ copy = new IsolatedStorageFilePermission(PermissionState.Unrestricted);
+ if(!IsUnrestricted()){
+ copy.m_userQuota = m_userQuota;
+ copy.m_machineQuota = m_machineQuota;
+ copy.m_expirationDays = m_expirationDays;
+ copy.m_permanentData = m_permanentData;
+ copy.m_allowed = m_allowed;
+ }
+ return copy;
+ }
+
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return IsolatedStorageFilePermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.IsolatedStorageFilePermissionIndex;
+ }
+
+ //------------------------------------------------------
+ //
+ // IsolatedStoragePermission OVERRIDES
+ //
+ //------------------------------------------------------
+#if FEATURE_CAS_POLICY
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override SecurityElement ToXml()
+ {
+ return base.ToXml( "System.Security.Permissions.IsolatedStorageFilePermission" );
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+}
+
diff --git a/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs b/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs
new file mode 100644
index 0000000000..308adbdab3
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/IsolatedStoragePermission.cs
@@ -0,0 +1,274 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security.Permissions {
+
+ using System;
+ using System.IO;
+ using System.Security;
+ using System.Security.Util;
+ using System.Globalization;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum IsolatedStorageContainment {
+ None = 0x00,
+ DomainIsolationByUser = 0x10,
+ ApplicationIsolationByUser = 0x15,
+ AssemblyIsolationByUser = 0x20,
+ DomainIsolationByMachine = 0x30,
+ AssemblyIsolationByMachine = 0x40,
+ ApplicationIsolationByMachine = 0x45,
+ DomainIsolationByRoamingUser = 0x50,
+ AssemblyIsolationByRoamingUser = 0x60,
+ ApplicationIsolationByRoamingUser = 0x65,
+ AdministerIsolatedStorageByUser = 0x70,
+ //AdministerIsolatedStorageByMachine = 0x80,
+ UnrestrictedIsolatedStorage = 0xF0
+ };
+
+
+ [Serializable]
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute( SecurityAction.InheritanceDemand, ControlEvidence = true, ControlPolicy = true )]
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ abstract public class IsolatedStoragePermission
+ : CodeAccessPermission, IUnrestrictedPermission
+ {
+
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+
+ /// <internalonly/>
+ internal long m_userQuota;
+ /// <internalonly/>
+ internal long m_machineQuota;
+ /// <internalonly/>
+ internal long m_expirationDays;
+ /// <internalonly/>
+ internal bool m_permanentData;
+ /// <internalonly/>
+ internal IsolatedStorageContainment m_allowed;
+
+ //------------------------------------------------------
+ //
+ // CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ protected IsolatedStoragePermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_userQuota = Int64.MaxValue;
+ m_machineQuota = Int64.MaxValue;
+ m_expirationDays = Int64.MaxValue ;
+ m_permanentData = true;
+ m_allowed = IsolatedStorageContainment.UnrestrictedIsolatedStorage;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_userQuota = 0;
+ m_machineQuota = 0;
+ m_expirationDays = 0;
+ m_permanentData = false;
+ m_allowed = IsolatedStorageContainment.None;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ internal IsolatedStoragePermission(IsolatedStorageContainment UsageAllowed,
+ long ExpirationDays, bool PermanentData)
+
+ {
+ m_userQuota = 0; // typical demand won't include quota
+ m_machineQuota = 0; // typical demand won't include quota
+ m_expirationDays = ExpirationDays;
+ m_permanentData = PermanentData;
+ m_allowed = UsageAllowed;
+ }
+
+ internal IsolatedStoragePermission(IsolatedStorageContainment UsageAllowed,
+ long ExpirationDays, bool PermanentData, long UserQuota)
+
+ {
+ m_machineQuota = 0;
+ m_userQuota = UserQuota;
+ m_expirationDays = ExpirationDays;
+ m_permanentData = PermanentData;
+ m_allowed = UsageAllowed;
+ }
+
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ // properties
+ public long UserQuota {
+ set{
+ m_userQuota = value;
+ }
+ get{
+ return m_userQuota;
+ }
+ }
+
+#if false
+ internal long MachineQuota {
+ set{
+ m_machineQuota = value;
+ }
+ get{
+ return m_machineQuota;
+ }
+ }
+ internal long ExpirationDays {
+ set{
+ m_expirationDays = value;
+ }
+ get{
+ return m_expirationDays;
+ }
+ }
+ internal bool PermanentData {
+ set{
+ m_permanentData = value;
+ }
+ get{
+ return m_permanentData;
+ }
+ }
+#endif
+
+ public IsolatedStorageContainment UsageAllowed {
+ set{
+ m_allowed = value;
+ }
+ get{
+ return m_allowed;
+ }
+ }
+
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ public bool IsUnrestricted()
+ {
+ return m_allowed == IsolatedStorageContainment.UnrestrictedIsolatedStorage;
+ }
+
+
+ //------------------------------------------------------
+ //
+ // INTERNAL METHODS
+ //
+ //------------------------------------------------------
+ internal static long min(long x,long y) {return x>y?y:x;}
+ internal static long max(long x,long y) {return x<y?y:x;}
+
+#if FEATURE_CAS_POLICY
+ //------------------------------------------------------
+ //
+ // PUBLIC ENCODING METHODS
+ //
+ //------------------------------------------------------
+
+ private const String _strUserQuota = "UserQuota";
+ private const String _strMachineQuota = "MachineQuota";
+ private const String _strExpiry = "Expiry";
+ private const String _strPermDat = "Permanent";
+
+ public override SecurityElement ToXml()
+ {
+ return ToXml ( this.GetType().FullName );
+ }
+
+ internal SecurityElement ToXml(String permName)
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, permName );
+ if (!IsUnrestricted())
+ {
+ esd.AddAttribute( "Allowed", Enum.GetName( typeof( IsolatedStorageContainment ), m_allowed ) );
+ if (m_userQuota>0)
+ {
+ esd.AddAttribute(_strUserQuota, (m_userQuota).ToString(CultureInfo.InvariantCulture)) ;
+ }
+ if (m_machineQuota>0)
+ {
+ esd.AddAttribute(_strMachineQuota, (m_machineQuota).ToString(CultureInfo.InvariantCulture)) ;
+ }
+ if (m_expirationDays>0)
+ {
+ esd.AddAttribute( _strExpiry, (m_expirationDays).ToString(CultureInfo.InvariantCulture)) ;
+ }
+ if (m_permanentData)
+ {
+ esd.AddAttribute(_strPermDat, (m_permanentData).ToString()) ;
+ }
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+
+ m_allowed = IsolatedStorageContainment.None; // default if no match
+
+ if (XMLUtil.IsUnrestricted(esd))
+ {
+ m_allowed = IsolatedStorageContainment.UnrestrictedIsolatedStorage;
+ }
+ else
+ {
+ String allowed = esd.Attribute( "Allowed" );
+
+ if (allowed != null)
+ m_allowed = (IsolatedStorageContainment)Enum.Parse( typeof( IsolatedStorageContainment ), allowed );
+ }
+
+ if (m_allowed == IsolatedStorageContainment.UnrestrictedIsolatedStorage)
+ {
+ m_userQuota = Int64.MaxValue;
+ m_machineQuota = Int64.MaxValue;
+ m_expirationDays = Int64.MaxValue ;
+ m_permanentData = true;
+ }
+ else
+ {
+ String param;
+ param = esd.Attribute (_strUserQuota) ;
+ m_userQuota = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ;
+ param = esd.Attribute (_strMachineQuota) ;
+ m_machineQuota = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ;
+ param = esd.Attribute (_strExpiry) ;
+ m_expirationDays = param != null ? Int64.Parse(param, CultureInfo.InvariantCulture) : 0 ;
+ param = esd.Attribute (_strPermDat) ;
+ m_permanentData = param != null ? (Boolean.Parse(param)) : false ;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs b/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs
new file mode 100644
index 0000000000..f14fb0d1b3
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/PermissionAttributes.cs
@@ -0,0 +1,1176 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+
+ using System.Security.Util;
+ using System.IO;
+ using System.Security.Policy;
+#if FEATURE_MACL
+ using System.Security.AccessControl;
+#endif
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+#if FEATURE_X509
+ using System.Security.Cryptography.X509Certificates;
+#endif
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CAS_POLICY
+ // The csharp compiler requires these types to be public, but they are not used elsewhere.
+ [Obsolete("SecurityAction is no longer accessible to application code.")]
+#endif
+ public enum SecurityAction
+ {
+ // Demand permission of all caller
+ Demand = 2,
+
+ // Assert permission so callers don't need
+ Assert = 3,
+
+ // Deny permissions so checks will fail
+ [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ Deny = 4,
+
+ // Reduce permissions so check will fail
+ PermitOnly = 5,
+
+ // Demand permission of caller
+ LinkDemand = 6,
+
+ // Demand permission of a subclass
+ InheritanceDemand = 7,
+
+ // Request minimum permissions to run
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestMinimum = 8,
+
+ // Request optional additional permissions
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestOptional = 9,
+
+ // Refuse to be granted these permissions
+ [Obsolete("Assembly level declarative security is obsolete and is no longer enforced by the CLR by default. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ RequestRefuse = 10,
+ }
+
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CAS_POLICY
+ // The csharp compiler requires these types to be public, but they are not used elsewhere.
+ [Obsolete("SecurityAttribute is no longer accessible to application code.")]
+#endif
+ public abstract class SecurityAttribute : System.Attribute
+ {
+ /// <internalonly/>
+ internal SecurityAction m_action;
+ /// <internalonly/>
+ internal bool m_unrestricted;
+
+ protected SecurityAttribute( SecurityAction action )
+ {
+ m_action = action;
+ }
+
+ public SecurityAction Action
+ {
+ get { return m_action; }
+ set { m_action = value; }
+ }
+
+ public bool Unrestricted
+ {
+ get { return m_unrestricted; }
+ set { m_unrestricted = value; }
+ }
+
+ abstract public IPermission CreatePermission();
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe IntPtr FindSecurityAttributeTypeHandle(String typeName)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ Type t = Type.GetType(typeName, false, false);
+ if(t == null)
+ return IntPtr.Zero;
+ IntPtr typeHandle = t.TypeHandle.Value;
+ return typeHandle;
+ }
+ }
+
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CAS_POLICY
+ // The csharp compiler requires these types to be public, but they are not used elsewhere.
+ [Obsolete("CodeAccessSecurityAttribute is no longer accessible to application code.")]
+#endif
+ public abstract class CodeAccessSecurityAttribute : SecurityAttribute
+ {
+ protected CodeAccessSecurityAttribute( SecurityAction action )
+ : base( action )
+ {
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class EnvironmentPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_read = null;
+ private String m_write = null;
+
+#pragma warning disable 618
+ public EnvironmentPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Read {
+ get { return m_read; }
+ set { m_read = value; }
+ }
+
+ public String Write {
+ get { return m_write; }
+ set { m_write = value; }
+ }
+
+ public String All {
+ get { throw new NotSupportedException( Environment.GetResourceString( "NotSupported_GetMethod" ) ); }
+ set { m_write = value; m_read = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new EnvironmentPermission(PermissionState.Unrestricted);
+ }
+ else
+ {
+ EnvironmentPermission perm = new EnvironmentPermission(PermissionState.None);
+ if (m_read != null)
+ perm.SetPathList( EnvironmentPermissionAccess.Read, m_read );
+ if (m_write != null)
+ perm.SetPathList( EnvironmentPermissionAccess.Write, m_write );
+ return perm;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class FileDialogPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private FileDialogPermissionAccess m_access;
+
+#pragma warning disable 618
+ public FileDialogPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public bool Open
+ {
+ get { return (m_access & FileDialogPermissionAccess.Open) != 0; }
+ set { m_access = value ? m_access | FileDialogPermissionAccess.Open : m_access & ~FileDialogPermissionAccess.Open; }
+ }
+
+ public bool Save
+ {
+ get { return (m_access & FileDialogPermissionAccess.Save) != 0; }
+ set { m_access = value ? m_access | FileDialogPermissionAccess.Save : m_access & ~FileDialogPermissionAccess.Save; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new FileDialogPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new FileDialogPermission( m_access );
+ }
+ }
+ }
+
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class FileIOPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_read = null;
+ private String m_write = null;
+ private String m_append = null;
+ private String m_pathDiscovery = null;
+ private String m_viewAccess = null;
+ private String m_changeAccess = null;
+ [OptionalField(VersionAdded = 2)] private FileIOPermissionAccess m_allLocalFiles = FileIOPermissionAccess.NoAccess;
+ [OptionalField(VersionAdded = 2)] private FileIOPermissionAccess m_allFiles = FileIOPermissionAccess.NoAccess;
+
+#pragma warning disable 618
+ public FileIOPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Read {
+ get { return m_read; }
+ set { m_read = value; }
+ }
+
+ public String Write {
+ get { return m_write; }
+ set { m_write = value; }
+ }
+
+ public String Append {
+ get { return m_append; }
+ set { m_append = value; }
+ }
+
+ public String PathDiscovery {
+ get { return m_pathDiscovery; }
+ set { m_pathDiscovery = value; }
+ }
+
+ public String ViewAccessControl {
+ get { return m_viewAccess; }
+ set { m_viewAccess = value; }
+ }
+
+ public String ChangeAccessControl {
+ get { return m_changeAccess; }
+ set { m_changeAccess = value; }
+ }
+
+ [Obsolete("Please use the ViewAndModify property instead.")]
+ public String All {
+ set { m_read = value; m_write = value; m_append = value; m_pathDiscovery = value; }
+ get { throw new NotSupportedException( Environment.GetResourceString( "NotSupported_GetMethod" ) ); }
+ }
+
+ // Read, Write, Append, PathDiscovery, but no ACL-related permissions
+ public String ViewAndModify {
+ get { throw new NotSupportedException( Environment.GetResourceString( "NotSupported_GetMethod" ) ); }
+ set { m_read = value; m_write = value; m_append = value; m_pathDiscovery = value; }
+ }
+
+ public FileIOPermissionAccess AllFiles {
+ get { return m_allFiles; }
+ set { m_allFiles = value; }
+ }
+
+ public FileIOPermissionAccess AllLocalFiles {
+ get { return m_allLocalFiles; }
+ set { m_allLocalFiles = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new FileIOPermission(PermissionState.Unrestricted);
+ }
+ else
+ {
+ FileIOPermission perm = new FileIOPermission(PermissionState.None);
+ if (m_read != null)
+ perm.SetPathList( FileIOPermissionAccess.Read, m_read );
+ if (m_write != null)
+ perm.SetPathList( FileIOPermissionAccess.Write, m_write );
+ if (m_append != null)
+ perm.SetPathList( FileIOPermissionAccess.Append, m_append );
+ if (m_pathDiscovery != null)
+ perm.SetPathList( FileIOPermissionAccess.PathDiscovery, m_pathDiscovery );
+#if FEATURE_MACL
+ if (m_viewAccess != null)
+ perm.SetPathList( FileIOPermissionAccess.NoAccess, AccessControlActions.View, new String[] { m_viewAccess }, false );
+ if (m_changeAccess != null)
+ perm.SetPathList( FileIOPermissionAccess.NoAccess, AccessControlActions.Change, new String[] { m_changeAccess }, false );
+#endif
+
+ perm.AllFiles = m_allFiles;
+ perm.AllLocalFiles = m_allLocalFiles;
+ return perm;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+#pragma warning disable 618
+ public sealed class KeyContainerPermissionAttribute : CodeAccessSecurityAttribute {
+#pragma warning restore 618
+ KeyContainerPermissionFlags m_flags = KeyContainerPermissionFlags.NoFlags;
+ private string m_keyStore;
+ private string m_providerName;
+ private int m_providerType = -1;
+ private string m_keyContainerName;
+ private int m_keySpec = -1;
+
+#pragma warning disable 618
+ public KeyContainerPermissionAttribute(SecurityAction action) : base(action) {}
+#pragma warning restore 618
+
+ public string KeyStore {
+ get { return m_keyStore; }
+ set { m_keyStore = value; }
+ }
+
+ public string ProviderName {
+ get { return m_providerName; }
+ set { m_providerName = value; }
+ }
+
+ public int ProviderType {
+ get { return m_providerType; }
+ set { m_providerType = value; }
+ }
+
+ public string KeyContainerName {
+ get { return m_keyContainerName; }
+ set { m_keyContainerName = value; }
+ }
+
+ public int KeySpec {
+ get { return m_keySpec; }
+ set { m_keySpec = value; }
+ }
+
+ public KeyContainerPermissionFlags Flags {
+ get { return m_flags; }
+ set { m_flags = value; }
+ }
+
+ public override IPermission CreatePermission() {
+ if (m_unrestricted) {
+ return new KeyContainerPermission(PermissionState.Unrestricted);
+ } else {
+ if (KeyContainerPermissionAccessEntry.IsUnrestrictedEntry(m_keyStore, m_providerName, m_providerType, m_keyContainerName, m_keySpec))
+ return new KeyContainerPermission(m_flags);
+
+ // create a KeyContainerPermission with a single access entry.
+ KeyContainerPermission cp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags);
+ KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(m_keyStore, m_providerName, m_providerType, m_keyContainerName, m_keySpec, m_flags);
+ cp.AccessEntries.Add(accessEntry);
+ return cp;
+ }
+ }
+ }
+
+#if !FEATURE_CORECLR
+ // PrincipalPermissionAttribute currently derives from
+ // CodeAccessSecurityAttribute, even though it's not related to code access
+ // security. This is because compilers are currently looking for
+ // CodeAccessSecurityAttribute as a direct parent class rather than
+ // SecurityAttribute as the root class.
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class PrincipalPermissionAttribute : CodeAccessSecurityAttribute
+ {
+ private String m_name = null;
+ private String m_role = null;
+ private bool m_authenticated = true;
+
+ public PrincipalPermissionAttribute( SecurityAction action )
+ : base( action )
+ {
+ }
+
+ public String Name
+ {
+ get { return m_name; }
+ set { m_name = value; }
+ }
+
+ public String Role
+ {
+ get { return m_role; }
+ set { m_role = value; }
+ }
+
+ public bool Authenticated
+ {
+ get { return m_authenticated; }
+ set { m_authenticated = value; }
+ }
+
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new PrincipalPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new PrincipalPermission( m_name, m_role, m_authenticated );
+ }
+ }
+ }
+#endif // !FEATURE_CORECLR
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class ReflectionPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private ReflectionPermissionFlag m_flag = ReflectionPermissionFlag.NoFlags;
+
+#pragma warning disable 618
+ public ReflectionPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public ReflectionPermissionFlag Flags {
+ get { return m_flag; }
+ set { m_flag = value; }
+ }
+
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public bool TypeInformation {
+#pragma warning disable 618
+ get { return (m_flag & ReflectionPermissionFlag.TypeInformation) != 0; }
+ set { m_flag = value ? m_flag | ReflectionPermissionFlag.TypeInformation : m_flag & ~ReflectionPermissionFlag.TypeInformation; }
+#pragma warning restore 618
+ }
+
+ public bool MemberAccess {
+ get { return (m_flag & ReflectionPermissionFlag.MemberAccess) != 0; }
+ set { m_flag = value ? m_flag | ReflectionPermissionFlag.MemberAccess : m_flag & ~ReflectionPermissionFlag.MemberAccess; }
+ }
+
+ [Obsolete("This permission is no longer used by the CLR.")]
+ public bool ReflectionEmit {
+#pragma warning disable 618
+ get { return (m_flag & ReflectionPermissionFlag.ReflectionEmit) != 0; }
+ set { m_flag = value ? m_flag | ReflectionPermissionFlag.ReflectionEmit : m_flag & ~ReflectionPermissionFlag.ReflectionEmit; }
+#pragma warning restore 618
+ }
+
+ public bool RestrictedMemberAccess
+ {
+ get { return (m_flag & ReflectionPermissionFlag.RestrictedMemberAccess) != 0; }
+ set { m_flag = value ? m_flag | ReflectionPermissionFlag.RestrictedMemberAccess : m_flag & ~ReflectionPermissionFlag.RestrictedMemberAccess; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new ReflectionPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new ReflectionPermission( m_flag );
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class RegistryPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_read = null;
+ private String m_write = null;
+ private String m_create = null;
+ private String m_viewAcl = null;
+ private String m_changeAcl = null;
+
+#pragma warning disable 618
+ public RegistryPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Read {
+ get { return m_read; }
+ set { m_read = value; }
+ }
+
+ public String Write {
+ get { return m_write; }
+ set { m_write = value; }
+ }
+
+ public String Create {
+ get { return m_create; }
+ set { m_create = value; }
+ }
+
+ public String ViewAccessControl {
+ get { return m_viewAcl; }
+ set { m_viewAcl = value; }
+ }
+
+ public String ChangeAccessControl {
+ get { return m_changeAcl; }
+ set { m_changeAcl = value; }
+ }
+
+ // Read, Write, & Create, but no ACL's
+ public String ViewAndModify {
+ get { throw new NotSupportedException( Environment.GetResourceString( "NotSupported_GetMethod" ) ); }
+ set { m_read = value; m_write = value; m_create = value; }
+ }
+
+ [Obsolete("Please use the ViewAndModify property instead.")]
+ public String All {
+ get { throw new NotSupportedException( Environment.GetResourceString( "NotSupported_GetMethod" ) ); }
+ set { m_read = value; m_write = value; m_create = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new RegistryPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ RegistryPermission perm = new RegistryPermission(PermissionState.None);
+ if (m_read != null)
+ perm.SetPathList( RegistryPermissionAccess.Read, m_read );
+ if (m_write != null)
+ perm.SetPathList( RegistryPermissionAccess.Write, m_write );
+ if (m_create != null)
+ perm.SetPathList( RegistryPermissionAccess.Create, m_create );
+#if FEATURE_MACL
+ if (m_viewAcl != null)
+ perm.SetPathList( AccessControlActions.View, m_viewAcl );
+ if (m_changeAcl != null)
+ perm.SetPathList( AccessControlActions.Change, m_changeAcl );
+#endif
+ return perm;
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#if !FEATURE_CAS_POLICY
+ // The csharp compiler requires these types to be public, but they are not used elsewhere.
+ [Obsolete("SecurityPermissionAttribute is no longer accessible to application code.")]
+#endif
+ sealed public class SecurityPermissionAttribute : CodeAccessSecurityAttribute
+ {
+ private SecurityPermissionFlag m_flag = SecurityPermissionFlag.NoFlags;
+
+ public SecurityPermissionAttribute( SecurityAction action )
+ : base( action )
+ {
+ }
+
+ public SecurityPermissionFlag Flags {
+ get { return m_flag; }
+ set { m_flag = value; }
+ }
+
+ public bool Assertion {
+ get { return (m_flag & SecurityPermissionFlag.Assertion) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.Assertion : m_flag & ~SecurityPermissionFlag.Assertion; }
+ }
+
+ public bool UnmanagedCode {
+ get { return (m_flag & SecurityPermissionFlag.UnmanagedCode) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.UnmanagedCode : m_flag & ~SecurityPermissionFlag.UnmanagedCode; }
+ }
+
+ public bool SkipVerification {
+ get { return (m_flag & SecurityPermissionFlag.SkipVerification) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.SkipVerification : m_flag & ~SecurityPermissionFlag.SkipVerification; }
+ }
+
+ public bool Execution {
+ get { return (m_flag & SecurityPermissionFlag.Execution) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.Execution : m_flag & ~SecurityPermissionFlag.Execution; }
+ }
+
+ public bool ControlThread {
+ get { return (m_flag & SecurityPermissionFlag.ControlThread) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlThread : m_flag & ~SecurityPermissionFlag.ControlThread; }
+ }
+
+ public bool ControlEvidence {
+ get { return (m_flag & SecurityPermissionFlag.ControlEvidence) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlEvidence : m_flag & ~SecurityPermissionFlag.ControlEvidence; }
+ }
+
+ public bool ControlPolicy {
+ get { return (m_flag & SecurityPermissionFlag.ControlPolicy) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlPolicy : m_flag & ~SecurityPermissionFlag.ControlPolicy; }
+ }
+
+ public bool SerializationFormatter {
+ get { return (m_flag & SecurityPermissionFlag.SerializationFormatter) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.SerializationFormatter : m_flag & ~SecurityPermissionFlag.SerializationFormatter; }
+ }
+
+ public bool ControlDomainPolicy {
+ get { return (m_flag & SecurityPermissionFlag.ControlDomainPolicy) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlDomainPolicy : m_flag & ~SecurityPermissionFlag.ControlDomainPolicy; }
+ }
+
+ public bool ControlPrincipal {
+ get { return (m_flag & SecurityPermissionFlag.ControlPrincipal) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlPrincipal : m_flag & ~SecurityPermissionFlag.ControlPrincipal; }
+ }
+
+ public bool ControlAppDomain {
+ get { return (m_flag & SecurityPermissionFlag.ControlAppDomain) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.ControlAppDomain : m_flag & ~SecurityPermissionFlag.ControlAppDomain; }
+ }
+
+ public bool RemotingConfiguration {
+ get { return (m_flag & SecurityPermissionFlag.RemotingConfiguration) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.RemotingConfiguration : m_flag & ~SecurityPermissionFlag.RemotingConfiguration; }
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public bool Infrastructure {
+ get { return (m_flag & SecurityPermissionFlag.Infrastructure) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.Infrastructure : m_flag & ~SecurityPermissionFlag.Infrastructure; }
+ }
+
+ public bool BindingRedirects {
+ get { return (m_flag & SecurityPermissionFlag.BindingRedirects) != 0; }
+ set { m_flag = value ? m_flag | SecurityPermissionFlag.BindingRedirects : m_flag & ~SecurityPermissionFlag.BindingRedirects; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new SecurityPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new SecurityPermission( m_flag );
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class UIPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private UIPermissionWindow m_windowFlag = UIPermissionWindow.NoWindows;
+ private UIPermissionClipboard m_clipboardFlag = UIPermissionClipboard.NoClipboard;
+
+#pragma warning disable 618
+ public UIPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public UIPermissionWindow Window {
+ get { return m_windowFlag; }
+ set { m_windowFlag = value; }
+ }
+
+ public UIPermissionClipboard Clipboard {
+ get { return m_clipboardFlag; }
+ set { m_clipboardFlag = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new UIPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ return new UIPermission( m_windowFlag, m_clipboardFlag );
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class ZoneIdentityPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private SecurityZone m_flag = SecurityZone.NoZone;
+
+#pragma warning disable 618
+ public ZoneIdentityPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public SecurityZone Zone {
+ get { return m_flag; }
+ set { m_flag = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new ZoneIdentityPermission(PermissionState.Unrestricted);
+ }
+ else
+ {
+ return new ZoneIdentityPermission( m_flag );
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class StrongNameIdentityPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_name = null;
+ private String m_version = null;
+ private String m_blob = null;
+
+#pragma warning disable 618
+ public StrongNameIdentityPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Name
+ {
+ get { return m_name; }
+ set { m_name = value; }
+ }
+
+ public String Version
+ {
+ get { return m_version; }
+ set { m_version = value; }
+ }
+
+ public String PublicKey
+ {
+ get { return m_blob; }
+ set { m_blob = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new StrongNameIdentityPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ if (m_blob == null && m_name == null && m_version == null)
+ return new StrongNameIdentityPermission( PermissionState.None );
+
+ if (m_blob == null)
+ throw new ArgumentException( Environment.GetResourceString("ArgumentNull_Key"));
+
+ StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob( m_blob );
+
+ if (m_version == null || m_version.Equals(String.Empty))
+ return new StrongNameIdentityPermission( blob, m_name, null );
+ else
+ return new StrongNameIdentityPermission( blob, m_name, new Version( m_version ) );
+ }
+ }
+ }
+
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class SiteIdentityPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_site = null;
+
+#pragma warning disable 618
+ public SiteIdentityPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Site {
+ get { return m_site; }
+ set { m_site = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new SiteIdentityPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ if (m_site == null)
+ return new SiteIdentityPermission( PermissionState.None );
+
+ return new SiteIdentityPermission( m_site );
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+#pragma warning disable 618
+ [Serializable] sealed public class UrlIdentityPermissionAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_url = null;
+
+#pragma warning disable 618
+ public UrlIdentityPermissionAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ }
+
+ public String Url {
+ get { return m_url; }
+ set { m_url = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new UrlIdentityPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ if (m_url == null)
+ return new UrlIdentityPermission( PermissionState.None );
+
+ return new UrlIdentityPermission( m_url );
+ }
+ }
+ }
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class PublisherIdentityPermissionAttribute : CodeAccessSecurityAttribute
+ {
+ private String m_x509cert = null;
+ private String m_certFile = null;
+ private String m_signedFile = null;
+
+ public PublisherIdentityPermissionAttribute( SecurityAction action )
+ : base( action )
+ {
+ m_x509cert = null;
+ m_certFile = null;
+ m_signedFile = null;
+ }
+
+ public String X509Certificate {
+ get { return m_x509cert; }
+ set { m_x509cert = value; }
+ }
+
+ public String CertFile {
+ get { return m_certFile; }
+ set { m_certFile = value; }
+ }
+
+ public String SignedFile {
+ get { return m_signedFile; }
+ set { m_signedFile = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ if (m_unrestricted)
+ {
+ return new PublisherIdentityPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ if (m_x509cert != null)
+ {
+ return new PublisherIdentityPermission( new X509Certificate( System.Security.Util.Hex.DecodeHexString( m_x509cert ) ) );
+ }
+ else if (m_certFile != null)
+ {
+ return new PublisherIdentityPermission( System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile( m_certFile ) );
+ }
+ else if (m_signedFile != null)
+ {
+ return new PublisherIdentityPermission( System.Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile( m_signedFile ) );
+ }
+ else
+ {
+ return new PublisherIdentityPermission( PermissionState.None );
+ }
+ }
+ }
+ }
+#endif // #if FEATURE_X509 && FEATURE_CAS_POLICY
+
+#if !FEATURE_CORECLR
+[Serializable]
+[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor
+ | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly,
+ AllowMultiple=true, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class IsolatedStoragePermissionAttribute : CodeAccessSecurityAttribute
+ {
+ /// <internalonly/>
+ internal long m_userQuota;
+#if false
+ /// <internalonly/>
+ internal long m_machineQuota;
+ /// <internalonly/>
+ internal long m_expirationDays;
+ /// <internalonly/>
+ internal bool m_permanentData;
+#endif
+ /// <internalonly/>
+ internal IsolatedStorageContainment m_allowed;
+ protected IsolatedStoragePermissionAttribute(SecurityAction action) : base(action)
+ {
+ }
+
+ // properties
+ public long UserQuota {
+ set{
+ m_userQuota = value;
+ }
+ get{
+ return m_userQuota;
+ }
+ }
+#if false
+ internal long MachineQuota {
+ set{
+ m_machineQuota = value;
+ }
+ get{
+ return m_machineQuota;
+ }
+ }
+ internal long ExpirationDays {
+ set{
+ m_expirationDays = value;
+ }
+ get{
+ return m_expirationDays;
+ }
+ }
+ internal bool PermanentData {
+ set{
+ m_permanentData = value;
+ }
+ get{
+ return m_permanentData;
+ }
+ }
+#endif
+ public IsolatedStorageContainment UsageAllowed {
+ set{
+ m_allowed = value;
+ }
+ get{
+ return m_allowed;
+ }
+ }
+
+ }
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor
+ | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly,
+ AllowMultiple=true, Inherited=false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class IsolatedStorageFilePermissionAttribute : IsolatedStoragePermissionAttribute
+ {
+ public IsolatedStorageFilePermissionAttribute(SecurityAction action) : base(action)
+ {
+
+ }
+ public override IPermission CreatePermission()
+ {
+ IsolatedStorageFilePermission p;
+ if (m_unrestricted) {
+ p = new IsolatedStorageFilePermission
+ (PermissionState.Unrestricted);
+ } else {
+ p = new IsolatedStorageFilePermission(PermissionState.None);
+ p.UserQuota = m_userQuota;
+ p.UsageAllowed = m_allowed;
+#if false
+ p.PermanentData = m_permanentData;
+ p.MachineQuota = m_machineQuota;
+ p.ExpirationDays = m_expirationDays;
+#endif
+ }
+ return p;
+ }
+ }
+#endif // FEATURE_CORECLR
+
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Assembly, AllowMultiple = true, Inherited = false )]
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ sealed public class PermissionSetAttribute : CodeAccessSecurityAttribute
+#pragma warning restore 618
+ {
+ private String m_file;
+ private String m_name;
+ private bool m_unicode;
+ private String m_xml;
+ private String m_hex;
+
+#pragma warning disable 618
+ public PermissionSetAttribute( SecurityAction action )
+#pragma warning restore 618
+ : base( action )
+ {
+ m_unicode = false;
+ }
+
+ public String File {
+ get { return m_file; }
+ set { m_file = value; }
+ }
+
+ public bool UnicodeEncoded {
+ get { return m_unicode; }
+ set { m_unicode = value; }
+ }
+
+ public String Name {
+ get { return m_name; }
+ set { m_name = value; }
+ }
+
+ public String XML {
+ get { return m_xml; }
+ set { m_xml = value; }
+ }
+
+ public String Hex {
+ get { return m_hex; }
+ set { m_hex = value; }
+ }
+
+ public override IPermission CreatePermission()
+ {
+ return null;
+ }
+
+#if FEATURE_CAS_POLICY
+ private PermissionSet BruteForceParseStream(Stream stream)
+ {
+ Encoding[] encodings = new Encoding[] { Encoding.UTF8,
+ Encoding.ASCII,
+ Encoding.Unicode };
+
+ StreamReader reader = null;
+ Exception exception = null;
+
+ for (int i = 0; reader == null && i < encodings.Length; ++i)
+ {
+ try
+ {
+ stream.Position = 0;
+ reader = new StreamReader( stream, encodings[i] );
+
+ return ParsePermissionSet( new Parser(reader) );
+ }
+ catch (Exception e1)
+ {
+ if (exception == null)
+ exception = e1;
+ }
+ }
+
+ throw exception;
+ }
+
+ private PermissionSet ParsePermissionSet(Parser parser)
+ {
+ SecurityElement e = parser.GetTopElement();
+ PermissionSet permSet = new PermissionSet( PermissionState.None );
+ permSet.FromXml( e );
+
+ return permSet;
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ public PermissionSet CreatePermissionSet()
+ {
+ if (m_unrestricted)
+ return new PermissionSet( PermissionState.Unrestricted );
+ else if (m_name != null)
+#if FEATURE_CAS_POLICY
+ return PolicyLevel.GetBuiltInSet( m_name );
+#else
+ return NamedPermissionSet.GetBuiltInSet( m_name );
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_CAS_POLICY
+ else if (m_xml != null)
+ return ParsePermissionSet( new Parser(m_xml.ToCharArray()) );
+ else if (m_hex != null)
+ return BruteForceParseStream( new MemoryStream(Util.Hex.DecodeHexString(m_hex)) );
+ else if (m_file != null)
+ return BruteForceParseStream( new FileStream( m_file, FileMode.Open, FileAccess.Read) );
+#endif // FEATURE_CAS_POLICY
+ else
+ return new PermissionSet( PermissionState.None );
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/PermissionState.cs b/src/mscorlib/src/System/Security/Permissions/PermissionState.cs
new file mode 100644
index 0000000000..ea0f1a0ac2
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/PermissionState.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// The Runtime policy manager. Maintains a set of IdentityMapper objects that map
+// inbound evidence to groups. Resolves an identity into a set of permissions
+//
+
+namespace System.Security.Permissions {
+
+ using System;
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum PermissionState
+ {
+ Unrestricted = 1,
+ None = 0,
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs b/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs
new file mode 100644
index 0000000000..2bc3c08ff9
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/ReflectionPermission.cs
@@ -0,0 +1,313 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using System.IO;
+ using System.Security.Util;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.Security;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [ComVisible(true)]
+ [Flags]
+ [Serializable]
+ public enum ReflectionPermissionFlag
+ {
+ NoFlags = 0x00,
+ [Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
+ TypeInformation = 0x01,
+ MemberAccess = 0x02,
+ [Obsolete("This permission is no longer used by the CLR.")]
+ ReflectionEmit = 0x04,
+ [ComVisible(false)]
+ RestrictedMemberAccess = 0x08,
+ [Obsolete("This permission has been deprecated. Use PermissionState.Unrestricted to get full access.")]
+ AllFlags = 0x07
+ }
+
+ [ComVisible(true)]
+ [Serializable]
+ sealed public class ReflectionPermission
+ : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ // ReflectionPermissionFlag.AllFlags doesn't contain the new value RestrictedMemberAccess,
+ // but we cannot change its value now because that will break apps that have that old value baked in.
+ // We should use this const that truely contains "all" flags instead of ReflectionPermissionFlag.AllFlags.
+#pragma warning disable 618
+ internal const ReflectionPermissionFlag AllFlagsAndMore = ReflectionPermissionFlag.AllFlags | ReflectionPermissionFlag.RestrictedMemberAccess;
+#pragma warning restore 618
+
+ private ReflectionPermissionFlag m_flags;
+
+ //
+ // Public Constructors
+ //
+
+ public ReflectionPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ SetUnrestricted( true );
+ }
+ else if (state == PermissionState.None)
+ {
+ SetUnrestricted( false );
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ // Parameters:
+ //
+ public ReflectionPermission(ReflectionPermissionFlag flag)
+ {
+ VerifyAccess(flag);
+
+ SetUnrestricted(false);
+ m_flags = flag;
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED MODIFIERS
+ //
+ //------------------------------------------------------
+
+
+ private void SetUnrestricted(bool unrestricted)
+ {
+ if (unrestricted)
+ {
+ m_flags = ReflectionPermission.AllFlagsAndMore;
+ }
+ else
+ {
+ Reset();
+ }
+ }
+
+
+ private void Reset()
+ {
+ m_flags = ReflectionPermissionFlag.NoFlags;
+ }
+
+
+ public ReflectionPermissionFlag Flags
+ {
+ set
+ {
+ VerifyAccess(value);
+
+ m_flags = value;
+ }
+
+ get
+ {
+ return m_flags;
+ }
+ }
+
+
+ #if ZERO // Do not remove this code, useful for debugging
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("ReflectionPermission(");
+ if (IsUnrestricted())
+ {
+ sb.Append("Unrestricted");
+ }
+ else
+ {
+ if (GetFlag(ReflectionPermissionFlag.TypeInformation))
+ sb.Append("TypeInformation; ");
+ if (GetFlag(ReflectionPermissionFlag.MemberAccess))
+ sb.Append("MemberAccess; ");
+#pragma warning disable 618
+ if (GetFlag(ReflectionPermissionFlag.ReflectionEmit))
+ sb.Append("ReflectionEmit; ");
+#pragma warning restore 618
+ }
+
+ sb.Append(")");
+ return sb.ToString();
+ }
+ #endif
+
+
+ //
+ // CodeAccessPermission implementation
+ //
+
+ public bool IsUnrestricted()
+ {
+ return m_flags == ReflectionPermission.AllFlagsAndMore;
+ }
+
+ //
+ // IPermission implementation
+ //
+
+ public override IPermission Union(IPermission other)
+ {
+ if (other == null)
+ {
+ return this.Copy();
+ }
+ else if (!VerifyType(other))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ ReflectionPermission operand = (ReflectionPermission)other;
+
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ {
+ return new ReflectionPermission( PermissionState.Unrestricted );
+ }
+ else
+ {
+ ReflectionPermissionFlag flag_union = (ReflectionPermissionFlag)(m_flags | operand.m_flags);
+ return(new ReflectionPermission(flag_union));
+ }
+ }
+
+
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ return m_flags == ReflectionPermissionFlag.NoFlags;
+ }
+
+ try
+ {
+ ReflectionPermission operand = (ReflectionPermission)target;
+ if (operand.IsUnrestricted())
+ return true;
+ else if (this.IsUnrestricted())
+ return false;
+ else
+ return (((int)this.m_flags) & ~((int)operand.m_flags)) == 0;
+ }
+ catch (InvalidCastException)
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ ReflectionPermission operand = (ReflectionPermission)target;
+
+ ReflectionPermissionFlag newFlags = operand.m_flags & this.m_flags;
+
+ if (newFlags == ReflectionPermissionFlag.NoFlags)
+ return null;
+ else
+ return new ReflectionPermission( newFlags );
+ }
+
+ public override IPermission Copy()
+ {
+ if (this.IsUnrestricted())
+ {
+ return new ReflectionPermission(PermissionState.Unrestricted);
+ }
+ else
+ {
+ return new ReflectionPermission((ReflectionPermissionFlag)m_flags);
+ }
+ }
+
+
+ //
+ // IEncodable Interface
+
+ private
+ void VerifyAccess(ReflectionPermissionFlag type)
+ {
+ if ((type & ~ReflectionPermission.AllFlagsAndMore) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)type));
+ Contract.EndContractBlock();
+ }
+
+#if FEATURE_CAS_POLICY
+ //------------------------------------------------------
+ //
+ // PUBLIC ENCODING METHODS
+ //
+ //------------------------------------------------------
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.ReflectionPermission" );
+ if (!IsUnrestricted())
+ {
+ esd.AddAttribute( "Flags", XMLUtil.BitFieldEnumToString( typeof( ReflectionPermissionFlag ), m_flags ) );
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ if (XMLUtil.IsUnrestricted( esd ))
+ {
+ m_flags = ReflectionPermission.AllFlagsAndMore;
+ return;
+ }
+
+ Reset () ;
+ SetUnrestricted (false) ;
+
+ String flags = esd.Attribute( "Flags" );
+ if (flags != null)
+ m_flags = (ReflectionPermissionFlag)Enum.Parse( typeof( ReflectionPermissionFlag ), flags );
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return ReflectionPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.ReflectionPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs b/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs
new file mode 100644
index 0000000000..bf801d625b
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/RegistryPermission.cs
@@ -0,0 +1,494 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using SecurityElement = System.Security.SecurityElement;
+ using System.Security.AccessControl;
+ using System.Security.Util;
+ using System.IO;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum RegistryPermissionAccess
+ {
+ NoAccess = 0x00,
+ Read = 0x01,
+ Write = 0x02,
+ Create = 0x04,
+ AllAccess = 0x07,
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class RegistryPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ private StringExpressionSet m_read;
+ private StringExpressionSet m_write;
+ private StringExpressionSet m_create;
+ [OptionalField(VersionAdded = 2)]
+ private StringExpressionSet m_viewAcl;
+ [OptionalField(VersionAdded = 2)]
+ private StringExpressionSet m_changeAcl;
+ private bool m_unrestricted;
+
+
+ public RegistryPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_unrestricted = true;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_unrestricted = false;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public RegistryPermission( RegistryPermissionAccess access, String pathList )
+ {
+ SetPathList( access, pathList );
+ }
+
+#if FEATURE_MACL
+ public RegistryPermission( RegistryPermissionAccess access, AccessControlActions control, String pathList )
+ {
+ m_unrestricted = false;
+ AddPathList( access, control, pathList );
+ }
+#endif
+
+ public void SetPathList( RegistryPermissionAccess access, String pathList )
+ {
+ VerifyAccess( access );
+
+ m_unrestricted = false;
+
+ if ((access & RegistryPermissionAccess.Read) != 0)
+ m_read = null;
+
+ if ((access & RegistryPermissionAccess.Write) != 0)
+ m_write = null;
+
+ if ((access & RegistryPermissionAccess.Create) != 0)
+ m_create = null;
+
+ AddPathList( access, pathList );
+ }
+
+#if FEATURE_MACL
+ internal void SetPathList( AccessControlActions control, String pathList )
+ {
+ m_unrestricted = false;
+
+ if ((control & AccessControlActions.View) != 0)
+ m_viewAcl = null;
+
+ if ((control & AccessControlActions.Change) != 0)
+ m_changeAcl = null;
+
+ AddPathList( RegistryPermissionAccess.NoAccess, control, pathList );
+ }
+#endif
+
+ public void AddPathList( RegistryPermissionAccess access, String pathList )
+ {
+ AddPathList( access, AccessControlActions.None, pathList );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AddPathList( RegistryPermissionAccess access, AccessControlActions control, String pathList )
+ {
+ VerifyAccess( access );
+
+ if ((access & RegistryPermissionAccess.Read) != 0)
+ {
+ if (m_read == null)
+ m_read = new StringExpressionSet();
+ m_read.AddExpressions( pathList );
+ }
+
+ if ((access & RegistryPermissionAccess.Write) != 0)
+ {
+ if (m_write == null)
+ m_write = new StringExpressionSet();
+ m_write.AddExpressions( pathList );
+ }
+
+ if ((access & RegistryPermissionAccess.Create) != 0)
+ {
+ if (m_create == null)
+ m_create = new StringExpressionSet();
+ m_create.AddExpressions( pathList );
+ }
+
+#if FEATURE_MACL
+ if ((control & AccessControlActions.View) != 0)
+ {
+ if (m_viewAcl == null)
+ m_viewAcl = new StringExpressionSet();
+ m_viewAcl.AddExpressions( pathList );
+ }
+
+ if ((control & AccessControlActions.Change) != 0)
+ {
+ if (m_changeAcl == null)
+ m_changeAcl = new StringExpressionSet();
+ m_changeAcl.AddExpressions( pathList );
+ }
+#endif
+ }
+
+ [SecuritySafeCritical]
+ public String GetPathList( RegistryPermissionAccess access )
+ {
+ // SafeCritical: these are registry paths, which means we're not leaking file system information here
+ VerifyAccess( access );
+ ExclusiveAccess( access );
+
+ if ((access & RegistryPermissionAccess.Read) != 0)
+ {
+ if (m_read == null)
+ {
+ return "";
+ }
+ return m_read.UnsafeToString();
+ }
+
+ if ((access & RegistryPermissionAccess.Write) != 0)
+ {
+ if (m_write == null)
+ {
+ return "";
+ }
+ return m_write.UnsafeToString();
+ }
+
+ if ((access & RegistryPermissionAccess.Create) != 0)
+ {
+ if (m_create == null)
+ {
+ return "";
+ }
+ return m_create.UnsafeToString();
+ }
+
+ /* not reached */
+
+ return "";
+ }
+
+ private void VerifyAccess( RegistryPermissionAccess access )
+ {
+ if ((access & ~RegistryPermissionAccess.AllAccess) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)access));
+ }
+
+ private void ExclusiveAccess( RegistryPermissionAccess access )
+ {
+ if (access == RegistryPermissionAccess.NoAccess)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+
+ if (((int) access & ((int)access-1)) != 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Arg_EnumNotSingleFlag") );
+ }
+ }
+
+ private bool IsEmpty()
+ {
+ return (!m_unrestricted &&
+ (this.m_read == null || this.m_read.IsEmpty()) &&
+ (this.m_write == null || this.m_write.IsEmpty()) &&
+ (this.m_create == null || this.m_create.IsEmpty()) &&
+ (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
+ //
+ //------------------------------------------------------
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ return this.IsEmpty();
+ }
+
+ RegistryPermission operand = target as RegistryPermission;
+ if (operand == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+
+ if (operand.IsUnrestricted())
+ return true;
+ 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_create == null || this.m_create.IsSubsetOf( operand.m_create )) &&
+ (this.m_viewAcl == null || this.m_viewAcl.IsSubsetOf( operand.m_viewAcl )) &&
+ (this.m_changeAcl == null || this.m_changeAcl.IsSubsetOf( operand.m_changeAcl )));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ {
+ return null;
+ }
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+ else if (this.IsUnrestricted())
+ {
+ return target.Copy();
+ }
+
+ RegistryPermission operand = (RegistryPermission)target;
+ if (operand.IsUnrestricted())
+ {
+ return this.Copy();
+ }
+
+
+ StringExpressionSet intersectRead = this.m_read == null ? null : this.m_read.Intersect( operand.m_read );
+ StringExpressionSet intersectWrite = this.m_write == null ? null : this.m_write.Intersect( operand.m_write );
+ StringExpressionSet intersectCreate = this.m_create == null ? null : this.m_create.Intersect( operand.m_create );
+ StringExpressionSet intersectViewAcl = this.m_viewAcl == null ? null : this.m_viewAcl.Intersect( operand.m_viewAcl );
+ StringExpressionSet intersectChangeAcl = this.m_changeAcl == null ? null : this.m_changeAcl.Intersect( operand.m_changeAcl );
+
+ if ((intersectRead == null || intersectRead.IsEmpty()) &&
+ (intersectWrite == null || intersectWrite.IsEmpty()) &&
+ (intersectCreate == null || intersectCreate.IsEmpty()) &&
+ (intersectViewAcl == null || intersectViewAcl.IsEmpty()) &&
+ (intersectChangeAcl == null || intersectChangeAcl.IsEmpty()))
+ {
+ return null;
+ }
+
+ RegistryPermission intersectPermission = new RegistryPermission(PermissionState.None);
+ intersectPermission.m_unrestricted = false;
+ intersectPermission.m_read = intersectRead;
+ intersectPermission.m_write = intersectWrite;
+ intersectPermission.m_create = intersectCreate;
+ intersectPermission.m_viewAcl = intersectViewAcl;
+ intersectPermission.m_changeAcl = intersectChangeAcl;
+
+ return intersectPermission;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override IPermission Union(IPermission other)
+ {
+ if (other == null)
+ {
+ return this.Copy();
+ }
+ else if (!VerifyType(other))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ RegistryPermission operand = (RegistryPermission)other;
+
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ {
+ return new RegistryPermission( PermissionState.Unrestricted );
+ }
+
+ StringExpressionSet unionRead = this.m_read == null ? operand.m_read : this.m_read.Union( operand.m_read );
+ StringExpressionSet unionWrite = this.m_write == null ? operand.m_write : this.m_write.Union( operand.m_write );
+ StringExpressionSet unionCreate = this.m_create == null ? operand.m_create : this.m_create.Union( operand.m_create );
+ StringExpressionSet unionViewAcl = this.m_viewAcl == null ? operand.m_viewAcl : this.m_viewAcl.Union( operand.m_viewAcl );
+ StringExpressionSet unionChangeAcl = this.m_changeAcl == null ? operand.m_changeAcl : this.m_changeAcl.Union( operand.m_changeAcl );
+
+ if ((unionRead == null || unionRead.IsEmpty()) &&
+ (unionWrite == null || unionWrite.IsEmpty()) &&
+ (unionCreate == null || unionCreate.IsEmpty()) &&
+ (unionViewAcl == null || unionViewAcl.IsEmpty()) &&
+ (unionChangeAcl == null || unionChangeAcl.IsEmpty()))
+ {
+ return null;
+ }
+
+ RegistryPermission unionPermission = new RegistryPermission(PermissionState.None);
+ unionPermission.m_unrestricted = false;
+ unionPermission.m_read = unionRead;
+ unionPermission.m_write = unionWrite;
+ unionPermission.m_create = unionCreate;
+ unionPermission.m_viewAcl = unionViewAcl;
+ unionPermission.m_changeAcl = unionChangeAcl;
+
+ return unionPermission;
+ }
+
+
+ public override IPermission Copy()
+ {
+ RegistryPermission copy = new RegistryPermission(PermissionState.None);
+ if (this.m_unrestricted)
+ {
+ copy.m_unrestricted = true;
+ }
+ else
+ {
+ copy.m_unrestricted = false;
+ if (this.m_read != null)
+ {
+ copy.m_read = this.m_read.Copy();
+ }
+ if (this.m_write != null)
+ {
+ copy.m_write = this.m_write.Copy();
+ }
+ if (this.m_create != null)
+ {
+ copy.m_create = this.m_create.Copy();
+ }
+ if (this.m_viewAcl != null)
+ {
+ copy.m_viewAcl = this.m_viewAcl.Copy();
+ }
+ if (this.m_changeAcl != null)
+ {
+ copy.m_changeAcl = this.m_changeAcl.Copy();
+ }
+ }
+ return copy;
+ }
+
+#if FEATURE_CAS_POLICY
+ [SecuritySafeCritical]
+ public override SecurityElement ToXml()
+ {
+ // SafeCritical: our string expression sets don't contain paths, so there's no information that
+ // needs to be guarded in them.
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.RegistryPermission" );
+ if (!IsUnrestricted())
+ {
+ if (this.m_read != null && !this.m_read.IsEmpty())
+ {
+ esd.AddAttribute( "Read", SecurityElement.Escape( m_read.UnsafeToString() ) );
+ }
+ if (this.m_write != null && !this.m_write.IsEmpty())
+ {
+ esd.AddAttribute( "Write", SecurityElement.Escape( m_write.UnsafeToString() ) );
+ }
+ if (this.m_create != null && !this.m_create.IsEmpty())
+ {
+ esd.AddAttribute( "Create", SecurityElement.Escape( m_create.UnsafeToString() ) );
+ }
+ if (this.m_viewAcl != null && !this.m_viewAcl.IsEmpty())
+ {
+ esd.AddAttribute( "ViewAccessControl", SecurityElement.Escape( m_viewAcl.UnsafeToString() ) );
+ }
+ if (this.m_changeAcl != null && !this.m_changeAcl.IsEmpty())
+ {
+ esd.AddAttribute( "ChangeAccessControl", SecurityElement.Escape( m_changeAcl.UnsafeToString() ) );
+ }
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ String et;
+
+ if (XMLUtil.IsUnrestricted( esd ))
+ {
+ m_unrestricted = true;
+ return;
+ }
+
+ m_unrestricted = false;
+ m_read = null;
+ m_write = null;
+ m_create = null;
+ m_viewAcl = null;
+ m_changeAcl = null;
+
+ et = esd.Attribute( "Read" );
+ if (et != null)
+ {
+ m_read = new StringExpressionSet( et );
+ }
+
+ et = esd.Attribute( "Write" );
+ if (et != null)
+ {
+ m_write = new StringExpressionSet( et );
+ }
+
+ et = esd.Attribute( "Create" );
+ if (et != null)
+ {
+ m_create = new StringExpressionSet( et );
+ }
+
+ et = esd.Attribute( "ViewAccessControl" );
+ if (et != null)
+ {
+ m_viewAcl = new StringExpressionSet( et );
+ }
+
+ et = esd.Attribute( "ChangeAccessControl" );
+ if (et != null)
+ {
+ m_changeAcl = new StringExpressionSet( et );
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return RegistryPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.RegistryPermissionIndex;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs b/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs
new file mode 100644
index 0000000000..b359cc530d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/SecurityPermission.cs
@@ -0,0 +1,362 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using System.IO;
+ using System.Security.Util;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.Remoting;
+ using System.Security;
+ using System.Runtime.Serialization;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CAS_POLICY
+ // The csharp compiler requires these types to be public, but they are not used elsewhere.
+ [Obsolete("SecurityPermissionFlag is no longer accessible to application code.")]
+#endif
+ public enum SecurityPermissionFlag
+ {
+ NoFlags = 0x00,
+ /* The following enum value is used in the EE (ASSERT_PERMISSION in security.cpp)
+ * Should this value change, make corresponding changes there
+ */
+ Assertion = 0x01,
+ UnmanagedCode = 0x02, // Update vm\Security.h if you change this !
+ SkipVerification = 0x04, // Update vm\Security.h if you change this !
+ Execution = 0x08,
+ ControlThread = 0x10,
+ ControlEvidence = 0x20,
+ ControlPolicy = 0x40,
+ SerializationFormatter = 0x80,
+ ControlDomainPolicy = 0x100,
+ ControlPrincipal = 0x200,
+ ControlAppDomain = 0x400,
+ RemotingConfiguration = 0x800,
+ Infrastructure = 0x1000,
+ BindingRedirects = 0x2000,
+ AllFlags = 0x3fff,
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class SecurityPermission
+ : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+#pragma warning disable 618
+ private SecurityPermissionFlag m_flags;
+#pragma warning restore 618
+
+ //
+ // Public Constructors
+ //
+
+ public SecurityPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ SetUnrestricted( true );
+ }
+ else if (state == PermissionState.None)
+ {
+ SetUnrestricted( false );
+ Reset();
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+
+ // SecurityPermission
+ //
+#pragma warning disable 618
+ public SecurityPermission(SecurityPermissionFlag flag)
+#pragma warning restore 618
+ {
+ VerifyAccess(flag);
+
+ SetUnrestricted(false);
+ m_flags = flag;
+ }
+
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED MODIFIERS
+ //
+ //------------------------------------------------------
+
+
+ private void SetUnrestricted(bool unrestricted)
+ {
+ if (unrestricted)
+ {
+#pragma warning disable 618
+ m_flags = SecurityPermissionFlag.AllFlags;
+#pragma warning restore 618
+ }
+ }
+
+ private void Reset()
+ {
+#pragma warning disable 618
+ m_flags = SecurityPermissionFlag.NoFlags;
+#pragma warning restore 618
+ }
+
+
+#pragma warning disable 618
+ public SecurityPermissionFlag Flags
+#pragma warning restore 618
+ {
+ set
+ {
+ VerifyAccess(value);
+
+ m_flags = value;
+ }
+
+ get
+ {
+ return m_flags;
+ }
+ }
+
+ //
+ // CodeAccessPermission methods
+ //
+
+ /*
+ * IPermission interface implementation
+ */
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ return m_flags == 0;
+ }
+
+ SecurityPermission operand = target as SecurityPermission;
+ if (operand != null)
+ {
+ return (((int)this.m_flags) & ~((int)operand.m_flags)) == 0;
+ }
+ else
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ }
+
+ public override IPermission Union(IPermission target) {
+ if (target == null) return(this.Copy());
+ if (!VerifyType(target)) {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+ SecurityPermission sp_target = (SecurityPermission) target;
+ if (sp_target.IsUnrestricted() || IsUnrestricted()) {
+ return(new SecurityPermission(PermissionState.Unrestricted));
+ }
+#pragma warning disable 618
+ SecurityPermissionFlag flag_union = (SecurityPermissionFlag)(m_flags | sp_target.m_flags);
+#pragma warning restore 618
+ return(new SecurityPermission(flag_union));
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ SecurityPermission operand = (SecurityPermission)target;
+#pragma warning disable 618
+ SecurityPermissionFlag isectFlags = SecurityPermissionFlag.NoFlags;
+#pragma warning restore 618
+
+ if (operand.IsUnrestricted())
+ {
+ if (this.IsUnrestricted())
+ return new SecurityPermission(PermissionState.Unrestricted);
+ else
+#pragma warning disable 618
+ isectFlags = (SecurityPermissionFlag)this.m_flags;
+#pragma warning restore 618
+ }
+ else if (this.IsUnrestricted())
+ {
+#pragma warning disable 618
+ isectFlags = (SecurityPermissionFlag)operand.m_flags;
+#pragma warning restore 618
+ }
+ else
+ {
+#pragma warning disable 618
+ isectFlags = (SecurityPermissionFlag)m_flags & (SecurityPermissionFlag)operand.m_flags;
+#pragma warning restore 618
+ }
+
+ if (isectFlags == 0)
+ return null;
+ else
+ return new SecurityPermission(isectFlags);
+ }
+
+ public override IPermission Copy()
+ {
+ if (IsUnrestricted())
+ return new SecurityPermission(PermissionState.Unrestricted);
+ else
+#pragma warning disable 618
+ return new SecurityPermission((SecurityPermissionFlag)m_flags);
+#pragma warning restore 618
+ }
+
+ public bool IsUnrestricted()
+ {
+#pragma warning disable 618
+ return m_flags == SecurityPermissionFlag.AllFlags;
+#pragma warning restore 618
+ }
+
+ private
+#pragma warning disable 618
+ void VerifyAccess(SecurityPermissionFlag type)
+#pragma warning restore 618
+ {
+#pragma warning disable 618
+ if ((type & ~SecurityPermissionFlag.AllFlags) != 0)
+#pragma warning restore 618
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)type));
+ Contract.EndContractBlock();
+ }
+
+#if FEATURE_CAS_POLICY
+ //------------------------------------------------------
+ //
+ // PUBLIC ENCODING METHODS
+ //
+ //------------------------------------------------------
+
+ private const String _strHeaderAssertion = "Assertion";
+ private const String _strHeaderUnmanagedCode = "UnmanagedCode";
+ private const String _strHeaderExecution = "Execution";
+ private const String _strHeaderSkipVerification = "SkipVerification";
+ private const String _strHeaderControlThread = "ControlThread";
+ private const String _strHeaderControlEvidence = "ControlEvidence";
+ private const String _strHeaderControlPolicy = "ControlPolicy";
+ private const String _strHeaderSerializationFormatter = "SerializationFormatter";
+ private const String _strHeaderControlDomainPolicy = "ControlDomainPolicy";
+ private const String _strHeaderControlPrincipal = "ControlPrincipal";
+ private const String _strHeaderControlAppDomain = "ControlAppDomain";
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.SecurityPermission" );
+ if (!IsUnrestricted())
+ {
+ esd.AddAttribute( "Flags", XMLUtil.BitFieldEnumToString( typeof( SecurityPermissionFlag ), m_flags ) );
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ if (XMLUtil.IsUnrestricted( esd ))
+ {
+ m_flags = SecurityPermissionFlag.AllFlags;
+ return;
+ }
+
+ Reset () ;
+ SetUnrestricted (false) ;
+
+ String flags = esd.Attribute( "Flags" );
+
+ if (flags != null)
+ m_flags = (SecurityPermissionFlag)Enum.Parse( typeof( SecurityPermissionFlag ), flags );
+ }
+#endif // FEATURE_CAS_POLICY
+
+ //
+ // Object Overrides
+ //
+
+ #if ZERO // Do not remove this code, usefull for debugging
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("SecurityPermission(");
+ if (IsUnrestricted())
+ {
+ sb.Append("Unrestricted");
+ }
+ else
+ {
+ if (GetFlag(SecurityPermissionFlag.Assertion))
+ sb.Append("Assertion; ");
+ if (GetFlag(SecurityPermissionFlag.UnmanagedCode))
+ sb.Append("UnmangedCode; ");
+ if (GetFlag(SecurityPermissionFlag.SkipVerification))
+ sb.Append("SkipVerification; ");
+ if (GetFlag(SecurityPermissionFlag.Execution))
+ sb.Append("Execution; ");
+ if (GetFlag(SecurityPermissionFlag.ControlThread))
+ sb.Append("ControlThread; ");
+ if (GetFlag(SecurityPermissionFlag.ControlEvidence))
+ sb.Append("ControlEvidence; ");
+ if (GetFlag(SecurityPermissionFlag.ControlPolicy))
+ sb.Append("ControlPolicy; ");
+ if (GetFlag(SecurityPermissionFlag.SerializationFormatter))
+ sb.Append("SerializationFormatter; ");
+ if (GetFlag(SecurityPermissionFlag.ControlDomainPolicy))
+ sb.Append("ControlDomainPolicy; ");
+ if (GetFlag(SecurityPermissionFlag.ControlPrincipal))
+ sb.Append("ControlPrincipal; ");
+ }
+
+ sb.Append(")");
+ return sb.ToString();
+ }
+ #endif
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return SecurityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.SecurityPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs
new file mode 100644
index 0000000000..6050b580df
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/SiteIdentityPermission.cs
@@ -0,0 +1,359 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using SiteString = System.Security.Util.SiteString;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ sealed public class SiteIdentityPermission : CodeAccessPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+ [OptionalField(VersionAdded = 2)]
+ private bool m_unrestricted;
+ [OptionalField(VersionAdded = 2)]
+ private SiteString[] m_sites;
+
+#if FEATURE_REMOTING
+ // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission
+ [OptionalField(VersionAdded = 2)]
+ private String m_serializedPermission;
+
+ // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes
+ private SiteString m_site;
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ // v2.0 and beyond XML case
+ if (m_serializedPermission != null)
+ {
+ FromXml(SecurityElement.FromString(m_serializedPermission));
+ m_serializedPermission = null;
+ }
+ else if (m_site != null) //v1.x case where we read the m_site value
+ {
+ m_unrestricted = false;
+ m_sites = new SiteString[1];
+ m_sites[0] = m_site;
+ m_site = null;
+ }
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case
+ if (m_sites != null && m_sites.Length == 1) // for the v1.x case
+ m_site = m_sites[0];
+
+ }
+ }
+ [OnSerialized]
+ private void OnSerialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = null;
+ m_site = null;
+ }
+ }
+#endif // FEATURE_REMOTING
+
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+
+ public SiteIdentityPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_unrestricted = true;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_unrestricted = false;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public SiteIdentityPermission( String site )
+ {
+ Site = site;
+ }
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ public String Site
+ {
+ set
+ {
+ m_unrestricted = false;
+ m_sites = new SiteString[1];
+ m_sites[0] = new SiteString( value );
+ }
+
+ get
+ {
+ if(m_sites == null)
+ return "";
+ if(m_sites.Length == 1)
+ return m_sites[0].ToString();
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+
+ public override IPermission Copy()
+ {
+ SiteIdentityPermission perm = new SiteIdentityPermission( PermissionState.None );
+ perm.m_unrestricted = this.m_unrestricted;
+ if (this.m_sites != null)
+ {
+ perm.m_sites = new SiteString[this.m_sites.Length];
+ int n;
+ for(n = 0; n < this.m_sites.Length; n++)
+ perm.m_sites[n] = (SiteString)this.m_sites[n].Copy();
+ }
+ return perm;
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ if(m_unrestricted)
+ return false;
+ if(m_sites == null)
+ return true;
+ if(m_sites.Length == 0)
+ return true;
+ return false;
+ }
+ SiteIdentityPermission that = target as SiteIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(that.m_unrestricted)
+ return true;
+ if(m_unrestricted)
+ return false;
+ if(this.m_sites != null)
+ {
+ foreach(SiteString ssThis in this.m_sites)
+ {
+ bool bOK = false;
+ if(that.m_sites != null)
+ {
+ foreach(SiteString ssThat in that.m_sites)
+ {
+ if(ssThis.IsSubsetOf(ssThat))
+ {
+ bOK = true;
+ break;
+ }
+ }
+ }
+ if(!bOK)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ SiteIdentityPermission that = target as SiteIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted && that.m_unrestricted)
+ {
+ SiteIdentityPermission res = new SiteIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if(this.m_unrestricted)
+ return that.Copy();
+ if(that.m_unrestricted)
+ return this.Copy();
+ if(this.m_sites == null || that.m_sites == null || this.m_sites.Length == 0 || that.m_sites.Length == 0)
+ return null;
+ List<SiteString> alSites = new List<SiteString>();
+ foreach(SiteString ssThis in this.m_sites)
+ {
+ foreach(SiteString ssThat in that.m_sites)
+ {
+ SiteString ssInt = (SiteString)ssThis.Intersect(ssThat);
+ if(ssInt != null)
+ alSites.Add(ssInt);
+ }
+ }
+ if(alSites.Count == 0)
+ return null;
+ SiteIdentityPermission result = new SiteIdentityPermission(PermissionState.None);
+ result.m_sites = alSites.ToArray();
+ return result;
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ if((this.m_sites == null || this.m_sites.Length == 0) && !this.m_unrestricted)
+ return null;
+ return this.Copy();
+ }
+ SiteIdentityPermission that = target as SiteIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted || that.m_unrestricted)
+ {
+ SiteIdentityPermission res = new SiteIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if (this.m_sites == null || this.m_sites.Length == 0)
+ {
+ if(that.m_sites == null || that.m_sites.Length == 0)
+ return null;
+ return that.Copy();
+ }
+ if(that.m_sites == null || that.m_sites.Length == 0)
+ return this.Copy();
+ List<SiteString> alSites = new List<SiteString>();
+ foreach(SiteString ssThis in this.m_sites)
+ alSites.Add(ssThis);
+ foreach(SiteString ssThat in that.m_sites)
+ {
+ bool bDupe = false;
+ foreach(SiteString ss in alSites)
+ {
+ if(ssThat.Equals(ss))
+ {
+ bDupe = true;
+ break;
+ }
+ }
+ if(!bDupe)
+ alSites.Add(ssThat);
+ }
+ SiteIdentityPermission result = new SiteIdentityPermission(PermissionState.None);
+ result.m_sites = alSites.ToArray();
+ return result;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override void FromXml(SecurityElement esd)
+ {
+ m_unrestricted = false;
+ m_sites = null;
+ CodeAccessPermission.ValidateElement( esd, this );
+ String unr = esd.Attribute( "Unrestricted" );
+ if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ m_unrestricted = true;
+ return;
+ }
+ String elem = esd.Attribute( "Site" );
+ List<SiteString> al = new List<SiteString>();
+ if(elem != null)
+ al.Add(new SiteString( elem ));
+ ArrayList alChildren = esd.Children;
+ if(alChildren != null)
+ {
+ foreach(SecurityElement child in alChildren)
+ {
+ elem = child.Attribute( "Site" );
+ if(elem != null)
+ al.Add(new SiteString( elem ));
+ }
+ }
+ if(al.Count != 0)
+ m_sites = al.ToArray();
+ }
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.SiteIdentityPermission" );
+ if (m_unrestricted)
+ esd.AddAttribute( "Unrestricted", "true" );
+ else if (m_sites != null)
+ {
+ if (m_sites.Length == 1)
+ esd.AddAttribute( "Site", m_sites[0].ToString() );
+ else
+ {
+ int n;
+ for(n = 0; n < m_sites.Length; n++)
+ {
+ SecurityElement child = new SecurityElement("Site");
+ child.AddAttribute( "Site", m_sites[n].ToString() );
+ esd.AddChild(child);
+ }
+ }
+ }
+ return esd;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return SiteIdentityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.SiteIdentityPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs
new file mode 100644
index 0000000000..5f5de0ef80
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/StrongNameIdentityPermission.cs
@@ -0,0 +1,487 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using System.Security.Util;
+ using System.IO;
+ using String = System.String;
+ using Version = System.Version;
+ using System.Security.Policy;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ // The only difference between this class and System.Security.Policy.StrongName is that this one
+ // allows m_name to be null. We should merge this class with System.Security.Policy.StrongName
+ [Serializable]
+ sealed internal class StrongName2
+ {
+ public StrongNamePublicKeyBlob m_publicKeyBlob;
+ public String m_name;
+ public Version m_version;
+
+ public StrongName2(StrongNamePublicKeyBlob publicKeyBlob, String name, Version version)
+ {
+ m_publicKeyBlob = publicKeyBlob;
+ m_name = name;
+ m_version = version;
+ }
+
+ public StrongName2 Copy()
+ {
+ return new StrongName2(m_publicKeyBlob, m_name, m_version);
+ }
+
+ public bool IsSubsetOf(StrongName2 target)
+ {
+ // This StrongName2 is a subset of the target if it's public key blob is null no matter what
+ if (this.m_publicKeyBlob == null)
+ return true;
+
+ // Subsets are always false if the public key blobs do not match
+ if (!this.m_publicKeyBlob.Equals( target.m_publicKeyBlob ))
+ return false;
+
+ // We use null in strings to represent the "Anything" state.
+ // Therefore, the logic to detect an individual subset is:
+ //
+ // 1. If the this string is null ("Anything" is a subset of any other).
+ // 2. If the this string and target string are the same (equality is sufficient for a subset).
+ //
+ // The logic is reversed here to discover things that are not subsets.
+ if (this.m_name != null)
+ {
+ if (target.m_name == null || !System.Security.Policy.StrongName.CompareNames( target.m_name, this.m_name ))
+ return false;
+ }
+
+ if ((Object) this.m_version != null)
+ {
+ if ((Object) target.m_version == null ||
+ target.m_version.CompareTo( this.m_version ) != 0)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public StrongName2 Intersect(StrongName2 target)
+ {
+ if (target.IsSubsetOf( this ))
+ return target.Copy();
+ else if (this.IsSubsetOf( target ))
+ return this.Copy();
+ else
+ return null;
+ }
+
+ public bool Equals(StrongName2 target)
+ {
+ if (!target.IsSubsetOf(this))
+ return false;
+ if (!this.IsSubsetOf(target))
+ return false;
+ return true;
+ }
+ }
+
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+
+ private bool m_unrestricted;
+ private StrongName2[] m_strongNames;
+
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+
+ public StrongNameIdentityPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_unrestricted = true;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_unrestricted = false;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public StrongNameIdentityPermission( StrongNamePublicKeyBlob blob, String name, Version version )
+ {
+ if (blob == null)
+ throw new ArgumentNullException( "blob" );
+ if (name != null && name.Equals( "" ))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_EmptyStrongName" ) );
+ Contract.EndContractBlock();
+ m_unrestricted = false;
+ m_strongNames = new StrongName2[1];
+ m_strongNames[0] = new StrongName2(blob, name, version);
+ }
+
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ public StrongNamePublicKeyBlob PublicKey
+ {
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException( "PublicKey" );
+ Contract.EndContractBlock();
+ m_unrestricted = false;
+ if(m_strongNames != null && m_strongNames.Length == 1)
+ m_strongNames[0].m_publicKeyBlob = value;
+ else
+ {
+ m_strongNames = new StrongName2[1];
+ m_strongNames[0] = new StrongName2(value, "", new Version());
+ }
+ }
+
+ get
+ {
+ if(m_strongNames == null || m_strongNames.Length == 0)
+ return null;
+ if(m_strongNames.Length > 1)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
+ return m_strongNames[0].m_publicKeyBlob;
+ }
+ }
+
+ public String Name
+ {
+ set
+ {
+ if (value != null && value.Length == 0)
+ throw new ArgumentException( Environment.GetResourceString("Argument_EmptyName" ));
+ Contract.EndContractBlock();
+ m_unrestricted = false;
+ if(m_strongNames != null && m_strongNames.Length == 1)
+ m_strongNames[0].m_name = value;
+ else
+ {
+ m_strongNames = new StrongName2[1];
+ m_strongNames[0] = new StrongName2(null, value, new Version());
+ }
+ }
+
+ get
+ {
+ if(m_strongNames == null || m_strongNames.Length == 0)
+ return "";
+ if(m_strongNames.Length > 1)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
+ return m_strongNames[0].m_name;
+ }
+ }
+
+ public Version Version
+ {
+ set
+ {
+ m_unrestricted = false;
+ if(m_strongNames != null && m_strongNames.Length == 1)
+ m_strongNames[0].m_version = value;
+ else
+ {
+ m_strongNames = new StrongName2[1];
+ m_strongNames[0] = new StrongName2(null, "", value);
+ }
+ }
+
+ get
+ {
+ if(m_strongNames == null || m_strongNames.Length == 0)
+ return new Version();
+ if(m_strongNames.Length > 1)
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
+ return m_strongNames[0].m_version;
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+
+ public override IPermission Copy()
+ {
+ StrongNameIdentityPermission perm = new StrongNameIdentityPermission(PermissionState.None);
+ perm.m_unrestricted = this.m_unrestricted;
+ if(this.m_strongNames != null)
+ {
+ perm.m_strongNames = new StrongName2[this.m_strongNames.Length];
+ int n;
+ for(n = 0; n < this.m_strongNames.Length; n++)
+ perm.m_strongNames[n] = this.m_strongNames[n].Copy();
+ }
+ return perm;
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ if(m_unrestricted)
+ return false;
+ if(m_strongNames == null)
+ return true;
+ if(m_strongNames.Length == 0)
+ return true;
+ return false;
+ }
+ StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(that.m_unrestricted)
+ return true;
+ if(m_unrestricted)
+ return false;
+ if(this.m_strongNames != null)
+ {
+ foreach(StrongName2 snThis in m_strongNames)
+ {
+ bool bOK = false;
+ if(that.m_strongNames != null)
+ {
+ foreach(StrongName2 snThat in that.m_strongNames)
+ {
+ if(snThis.IsSubsetOf(snThat))
+ {
+ bOK = true;
+ break;
+ }
+ }
+ }
+ if(!bOK)
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted && that.m_unrestricted)
+ {
+ StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if(this.m_unrestricted)
+ return that.Copy();
+ if(that.m_unrestricted)
+ return this.Copy();
+ if(this.m_strongNames == null || that.m_strongNames == null || this.m_strongNames.Length == 0 || that.m_strongNames.Length == 0)
+ return null;
+ List<StrongName2> alStrongNames = new List<StrongName2>();
+ foreach(StrongName2 snThis in this.m_strongNames)
+ {
+ foreach(StrongName2 snThat in that.m_strongNames)
+ {
+ StrongName2 snInt = (StrongName2)snThis.Intersect(snThat);
+ if(snInt != null)
+ alStrongNames.Add(snInt);
+ }
+ }
+ if(alStrongNames.Count == 0)
+ return null;
+ StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
+ result.m_strongNames = alStrongNames.ToArray();
+ return result;
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ if((this.m_strongNames == null || this.m_strongNames.Length == 0) && !this.m_unrestricted)
+ return null;
+ return this.Copy();
+ }
+ StrongNameIdentityPermission that = target as StrongNameIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted || that.m_unrestricted)
+ {
+ StrongNameIdentityPermission res = new StrongNameIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if (this.m_strongNames == null || this.m_strongNames.Length == 0)
+ {
+ if(that.m_strongNames == null || that.m_strongNames.Length == 0)
+ return null;
+ return that.Copy();
+ }
+ if(that.m_strongNames == null || that.m_strongNames.Length == 0)
+ return this.Copy();
+ List<StrongName2> alStrongNames = new List<StrongName2>();
+ foreach(StrongName2 snThis in this.m_strongNames)
+ alStrongNames.Add(snThis);
+ foreach(StrongName2 snThat in that.m_strongNames)
+ {
+ bool bDupe = false;
+ foreach(StrongName2 sn in alStrongNames)
+ {
+ if(snThat.Equals(sn))
+ {
+ bDupe = true;
+ break;
+ }
+ }
+ if(!bDupe)
+ alStrongNames.Add(snThat);
+ }
+ StrongNameIdentityPermission result = new StrongNameIdentityPermission(PermissionState.None);
+ result.m_strongNames = alStrongNames.ToArray();
+ return result;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override void FromXml(SecurityElement e)
+ {
+ m_unrestricted = false;
+ m_strongNames = null;
+ CodeAccessPermission.ValidateElement( e, this );
+ String unr = e.Attribute( "Unrestricted" );
+ if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ m_unrestricted = true;
+ return;
+ }
+ String elBlob = e.Attribute("PublicKeyBlob");
+ String elName = e.Attribute("Name");
+ String elVersion = e.Attribute("AssemblyVersion");
+ StrongName2 sn;
+ List<StrongName2> al = new List<StrongName2>();
+ if(elBlob != null || elName != null || elVersion != null)
+ {
+ sn = new StrongName2(
+ (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)),
+ elName,
+ (elVersion == null ? null : new Version(elVersion)));
+ al.Add(sn);
+ }
+ ArrayList alChildren = e.Children;
+ if(alChildren != null)
+ {
+ foreach(SecurityElement child in alChildren)
+ {
+ elBlob = child.Attribute("PublicKeyBlob");
+ elName = child.Attribute("Name");
+ elVersion = child.Attribute("AssemblyVersion");
+ if(elBlob != null || elName != null || elVersion != null)
+ {
+ sn = new StrongName2(
+ (elBlob == null ? null : new StrongNamePublicKeyBlob(elBlob)),
+ elName,
+ (elVersion == null ? null : new Version(elVersion)));
+ al.Add(sn);
+ }
+ }
+ }
+ if(al.Count != 0)
+ m_strongNames = al.ToArray();
+ }
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.StrongNameIdentityPermission" );
+ if (m_unrestricted)
+ esd.AddAttribute( "Unrestricted", "true" );
+ else if (m_strongNames != null)
+ {
+ if (m_strongNames.Length == 1)
+ {
+ if (m_strongNames[0].m_publicKeyBlob != null)
+ esd.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[0].m_publicKeyBlob.PublicKey));
+ if (m_strongNames[0].m_name != null)
+ esd.AddAttribute("Name", m_strongNames[0].m_name);
+ if ((Object)m_strongNames[0].m_version != null)
+ esd.AddAttribute("AssemblyVersion", m_strongNames[0].m_version.ToString());
+ }
+ else
+ {
+ int n;
+ for(n = 0; n < m_strongNames.Length; n++)
+ {
+ SecurityElement child = new SecurityElement("StrongName");
+ if (m_strongNames[n].m_publicKeyBlob != null)
+ child.AddAttribute("PublicKeyBlob", Hex.EncodeHexString(m_strongNames[n].m_publicKeyBlob.PublicKey));
+ if (m_strongNames[n].m_name != null)
+ child.AddAttribute("Name", m_strongNames[n].m_name);
+ if ((Object)m_strongNames[n].m_version != null)
+ child.AddAttribute("AssemblyVersion", m_strongNames[n].m_version.ToString());
+ esd.AddChild(child);
+ }
+ }
+ }
+ return esd;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return StrongNameIdentityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.StrongNameIdentityPermissionIndex;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs b/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs
new file mode 100644
index 0000000000..e0aacaf80c
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/StrongNamePublicKeyBlob.cs
@@ -0,0 +1,94 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using System.Security.Util;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable] sealed public class StrongNamePublicKeyBlob
+ {
+ internal byte[] PublicKey;
+
+ internal StrongNamePublicKeyBlob()
+ {
+ }
+
+ public StrongNamePublicKeyBlob( byte[] publicKey )
+ {
+ if (publicKey == null)
+ throw new ArgumentNullException( "PublicKey" );
+ Contract.EndContractBlock();
+
+ this.PublicKey = new byte[publicKey.Length];
+ Array.Copy( publicKey, 0, this.PublicKey, 0, publicKey.Length );
+ }
+
+ internal StrongNamePublicKeyBlob( String publicKey )
+ {
+ this.PublicKey = Hex.DecodeHexString( publicKey );
+ }
+
+ private static bool CompareArrays( byte[] first, byte[] second )
+ {
+ if (first.Length != second.Length)
+ {
+ return false;
+ }
+
+ int count = first.Length;
+ for (int i = 0; i < count; ++i)
+ {
+ if (first[i] != second[i])
+ return false;
+ }
+
+ return true;
+ }
+
+
+ internal bool Equals( StrongNamePublicKeyBlob blob )
+ {
+ if (blob == null)
+ return false;
+ else
+ return CompareArrays( this.PublicKey, blob.PublicKey );
+ }
+
+ public override bool Equals( Object obj )
+ {
+ if (obj == null || !(obj is StrongNamePublicKeyBlob))
+ return false;
+
+ return this.Equals( (StrongNamePublicKeyBlob)obj );
+ }
+
+ static private int GetByteArrayHashCode( byte[] baData )
+ {
+ if (baData == null)
+ return 0;
+
+ int accumulator = 0;
+
+ for (int i = 0; i < baData.Length; ++i)
+ {
+ accumulator = (accumulator << 8) ^ (int)baData[i] ^ (accumulator >> 24);
+ }
+
+ return accumulator;
+ }
+
+ public override int GetHashCode()
+ {
+ return GetByteArrayHashCode( PublicKey );
+ }
+
+ public override String ToString()
+ {
+ return Hex.EncodeHexString( PublicKey );
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/UIPermission.cs b/src/mscorlib/src/System/Security/Permissions/UIPermission.cs
new file mode 100644
index 0000000000..bb122b734c
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/UIPermission.cs
@@ -0,0 +1,371 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+ using System.Security;
+ using System.Security.Util;
+ using System.IO;
+ using System.Runtime.Serialization;
+ using System.Reflection;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum UIPermissionWindow
+ {
+ // No window use allowed at all.
+ NoWindows = 0x0,
+
+ // Only allow safe subwindow use (for embedded components).
+ SafeSubWindows = 0x01,
+
+ // Safe top-level window use only (see specification for details).
+ SafeTopLevelWindows = 0x02,
+
+ // All windows and all event may be used.
+ AllWindows = 0x03,
+
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum UIPermissionClipboard
+ {
+ // No clipboard access is allowed.
+ NoClipboard = 0x0,
+
+ // Paste from the same app domain only.
+ OwnClipboard = 0x1,
+
+ // Any clipboard access is allowed.
+ AllClipboard = 0x2,
+
+ }
+
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ sealed public class UIPermission
+ : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+
+ private UIPermissionWindow m_windowFlag;
+ private UIPermissionClipboard m_clipboardFlag;
+
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ public UIPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ SetUnrestricted( true );
+ }
+ else if (state == PermissionState.None)
+ {
+ SetUnrestricted( false );
+ Reset();
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public UIPermission(UIPermissionWindow windowFlag, UIPermissionClipboard clipboardFlag )
+ {
+ VerifyWindowFlag( windowFlag );
+ VerifyClipboardFlag( clipboardFlag );
+
+ m_windowFlag = windowFlag;
+ m_clipboardFlag = clipboardFlag;
+ }
+
+ public UIPermission(UIPermissionWindow windowFlag )
+ {
+ VerifyWindowFlag( windowFlag );
+
+ m_windowFlag = windowFlag;
+ }
+
+ public UIPermission(UIPermissionClipboard clipboardFlag )
+ {
+ VerifyClipboardFlag( clipboardFlag );
+
+ m_clipboardFlag = clipboardFlag;
+ }
+
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ public UIPermissionWindow Window
+ {
+ set
+ {
+ VerifyWindowFlag(value);
+
+ m_windowFlag = value;
+ }
+
+ get
+ {
+ return m_windowFlag;
+ }
+ }
+
+ public UIPermissionClipboard Clipboard
+ {
+ set
+ {
+ VerifyClipboardFlag(value);
+
+ m_clipboardFlag = value;
+ }
+
+ get
+ {
+ return m_clipboardFlag;
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ private static void VerifyWindowFlag(UIPermissionWindow flag)
+ {
+ if (flag < UIPermissionWindow.NoWindows || flag > UIPermissionWindow.AllWindows)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flag));
+ }
+ Contract.EndContractBlock();
+ }
+
+ private static void VerifyClipboardFlag(UIPermissionClipboard flag)
+ {
+ if (flag < UIPermissionClipboard.NoClipboard || flag > UIPermissionClipboard.AllClipboard)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flag));
+ }
+ Contract.EndContractBlock();
+ }
+
+ private void Reset()
+ {
+ m_windowFlag = UIPermissionWindow.NoWindows;
+ m_clipboardFlag = UIPermissionClipboard.NoClipboard;
+ }
+
+ private void SetUnrestricted( bool unrestricted )
+ {
+ if (unrestricted)
+ {
+ m_windowFlag = UIPermissionWindow.AllWindows;
+ m_clipboardFlag = UIPermissionClipboard.AllClipboard;
+ }
+ }
+
+#if false
+ //------------------------------------------------------
+ //
+ // OBJECT METHOD OVERRIDES
+ //
+ //------------------------------------------------------
+ public String ToString()
+ {
+ #if _DEBUG
+ StringBuilder sb = new StringBuilder();
+ sb.Append("UIPermission(");
+ if (IsUnrestricted())
+ {
+ sb.Append("Unrestricted");
+ }
+ else
+ {
+ sb.Append(m_stateNameTableWindow[m_windowFlag]);
+ sb.Append(", ");
+ sb.Append(m_stateNameTableClipboard[m_clipboardFlag]);
+ }
+
+ sb.Append(")");
+ return sb.ToString();
+ #else
+ return super.ToString();
+ #endif
+ }
+#endif
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ public bool IsUnrestricted()
+ {
+ return m_windowFlag == UIPermissionWindow.AllWindows && m_clipboardFlag == UIPermissionClipboard.AllClipboard;
+ }
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ // Only safe subset if this is empty
+ return m_windowFlag == UIPermissionWindow.NoWindows && m_clipboardFlag == UIPermissionClipboard.NoClipboard;
+ }
+
+ try
+ {
+ UIPermission operand = (UIPermission)target;
+ if (operand.IsUnrestricted())
+ return true;
+ else if (this.IsUnrestricted())
+ return false;
+ else
+ return this.m_windowFlag <= operand.m_windowFlag && this.m_clipboardFlag <= operand.m_clipboardFlag;
+ }
+ catch (InvalidCastException)
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ {
+ return null;
+ }
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ UIPermission operand = (UIPermission)target;
+ UIPermissionWindow isectWindowFlags = m_windowFlag < operand.m_windowFlag ? m_windowFlag : operand.m_windowFlag;
+ UIPermissionClipboard isectClipboardFlags = m_clipboardFlag < operand.m_clipboardFlag ? m_clipboardFlag : operand.m_clipboardFlag;
+ if (isectWindowFlags == UIPermissionWindow.NoWindows && isectClipboardFlags == UIPermissionClipboard.NoClipboard)
+ return null;
+ else
+ return new UIPermission(isectWindowFlags, isectClipboardFlags);
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ return this.Copy();
+ }
+ else if (!VerifyType(target))
+ {
+ throw new
+ ArgumentException(
+ Environment.GetResourceString("Argument_WrongType", this.GetType().FullName)
+ );
+ }
+
+ UIPermission operand = (UIPermission)target;
+ UIPermissionWindow isectWindowFlags = m_windowFlag > operand.m_windowFlag ? m_windowFlag : operand.m_windowFlag;
+ UIPermissionClipboard isectClipboardFlags = m_clipboardFlag > operand.m_clipboardFlag ? m_clipboardFlag : operand.m_clipboardFlag;
+ if (isectWindowFlags == UIPermissionWindow.NoWindows && isectClipboardFlags == UIPermissionClipboard.NoClipboard)
+ return null;
+ else
+ return new UIPermission(isectWindowFlags, isectClipboardFlags);
+ }
+
+ public override IPermission Copy()
+ {
+ return new UIPermission(this.m_windowFlag, this.m_clipboardFlag);
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.UIPermission" );
+ if (!IsUnrestricted())
+ {
+ if (m_windowFlag != UIPermissionWindow.NoWindows)
+ {
+ esd.AddAttribute( "Window", Enum.GetName( typeof( UIPermissionWindow ), m_windowFlag ) );
+ }
+ if (m_clipboardFlag != UIPermissionClipboard.NoClipboard)
+ {
+ esd.AddAttribute( "Clipboard", Enum.GetName( typeof( UIPermissionClipboard ), m_clipboardFlag ) );
+ }
+ }
+ else
+ {
+ esd.AddAttribute( "Unrestricted", "true" );
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ CodeAccessPermission.ValidateElement( esd, this );
+ if (XMLUtil.IsUnrestricted( esd ))
+ {
+ SetUnrestricted( true );
+ return;
+ }
+
+ m_windowFlag = UIPermissionWindow.NoWindows;
+ m_clipboardFlag = UIPermissionClipboard.NoClipboard;
+
+ String window = esd.Attribute( "Window" );
+ if (window != null)
+ m_windowFlag = (UIPermissionWindow)Enum.Parse( typeof( UIPermissionWindow ), window );
+
+ String clipboard = esd.Attribute( "Clipboard" );
+ if (clipboard != null)
+ m_clipboardFlag = (UIPermissionClipboard)Enum.Parse( typeof( UIPermissionClipboard ), clipboard );
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return UIPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.UIPermissionIndex;
+ }
+
+ }
+
+
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs
new file mode 100644
index 0000000000..e62449cf3e
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/URLIdentityPermission.cs
@@ -0,0 +1,391 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions
+{
+ using System;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using System.Security.Util;
+ using System.IO;
+ using System.Text;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ sealed public class UrlIdentityPermission : CodeAccessPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_unrestricted;
+ [OptionalField(VersionAdded = 2)]
+ private URLString[] m_urls;
+
+#if FEATURE_REMOTING
+ // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission
+ [OptionalField(VersionAdded = 2)]
+ private String m_serializedPermission;
+
+ // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes
+ private URLString m_url;
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ // v2.0 and beyond XML case
+ if (m_serializedPermission != null)
+ {
+ FromXml(SecurityElement.FromString(m_serializedPermission));
+ m_serializedPermission = null;
+ }
+ else if (m_url != null) //v1.x case where we read the m_site value
+ {
+ m_unrestricted = false;
+ m_urls = new URLString[1];
+ m_urls[0] = m_url;
+ m_url = null;
+ }
+
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case
+ if (m_urls != null && m_urls.Length == 1) // for the v1.x case
+ m_url = m_urls[0];
+
+ }
+ }
+ [OnSerialized]
+ private void OnSerialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = null;
+ m_url = null;
+ }
+ }
+#endif // FEATURE_REMOTING
+
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+
+ public UrlIdentityPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_unrestricted = true;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_unrestricted = false;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public UrlIdentityPermission( String site )
+ {
+ if (site == null)
+ throw new ArgumentNullException( "site" );
+ Contract.EndContractBlock();
+ Url = site;
+ }
+
+ internal UrlIdentityPermission( URLString site )
+ {
+ m_unrestricted = false;
+ m_urls = new URLString[1];
+ m_urls[0] = site;
+ }
+
+ // Internal function to append all the urls in m_urls to the input originList
+ internal void AppendOrigin(ArrayList originList)
+ {
+ if (m_urls == null)
+ originList.Add("");
+ else
+ {
+ int n;
+ for(n = 0; n < this.m_urls.Length; n++)
+ originList.Add(m_urls[n].ToString());
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ public String Url
+ {
+ set
+ {
+ m_unrestricted = false;
+ if(value == null || value.Length == 0)
+ m_urls = null;
+ else
+ {
+ m_urls = new URLString[1];
+ m_urls[0] = new URLString( value );
+ }
+ }
+
+ get
+ {
+ if(m_urls == null)
+ return "";
+ if(m_urls.Length == 1)
+ return m_urls[0].ToString();
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_AmbiguousIdentity"));
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+
+ public override IPermission Copy()
+ {
+ UrlIdentityPermission perm = new UrlIdentityPermission( PermissionState.None );
+ perm.m_unrestricted = this.m_unrestricted;
+ if (this.m_urls != null)
+ {
+ perm.m_urls = new URLString[this.m_urls.Length];
+ int n;
+ for(n = 0; n < this.m_urls.Length; n++)
+ perm.m_urls[n] = (URLString)this.m_urls[n].Copy();
+ }
+ return perm;
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ {
+ if(m_unrestricted)
+ return false;
+ if(m_urls == null)
+ return true;
+ if(m_urls.Length == 0)
+ return true;
+ return false;
+ }
+ UrlIdentityPermission that = target as UrlIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(that.m_unrestricted)
+ return true;
+ if(m_unrestricted)
+ return false;
+ if(this.m_urls != null)
+ {
+ foreach(URLString usThis in this.m_urls)
+ {
+ bool bOK = false;
+ if(that.m_urls != null)
+ {
+ foreach(URLString usThat in that.m_urls)
+ {
+ if(usThis.IsSubsetOf(usThat))
+ {
+ bOK = true;
+ break;
+ }
+ }
+ }
+ if(!bOK)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+ UrlIdentityPermission that = target as UrlIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted && that.m_unrestricted)
+ {
+ UrlIdentityPermission res = new UrlIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if(this.m_unrestricted)
+ return that.Copy();
+ if(that.m_unrestricted)
+ return this.Copy();
+ if(this.m_urls == null || that.m_urls == null || this.m_urls.Length == 0 || that.m_urls.Length == 0)
+ return null;
+ List<URLString> alUrls = new List<URLString>();
+ foreach(URLString usThis in this.m_urls)
+ {
+ foreach(URLString usThat in that.m_urls)
+ {
+ URLString usInt = (URLString)usThis.Intersect(usThat);
+ if(usInt != null)
+ alUrls.Add(usInt);
+ }
+ }
+ if(alUrls.Count == 0)
+ return null;
+ UrlIdentityPermission result = new UrlIdentityPermission(PermissionState.None);
+ result.m_urls = alUrls.ToArray();
+ return result;
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ {
+ if((this.m_urls == null || this.m_urls.Length == 0) && !this.m_unrestricted)
+ return null;
+ return this.Copy();
+ }
+ UrlIdentityPermission that = target as UrlIdentityPermission;
+ if(that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ if(this.m_unrestricted || that.m_unrestricted)
+ {
+ UrlIdentityPermission res = new UrlIdentityPermission(PermissionState.None);
+ res.m_unrestricted = true;
+ return res;
+ }
+ if (this.m_urls == null || this.m_urls.Length == 0)
+ {
+ if(that.m_urls == null || that.m_urls.Length == 0)
+ return null;
+ return that.Copy();
+ }
+ if(that.m_urls == null || that.m_urls.Length == 0)
+ return this.Copy();
+ List<URLString> alUrls = new List<URLString>();
+ foreach(URLString usThis in this.m_urls)
+ alUrls.Add(usThis);
+ foreach(URLString usThat in that.m_urls)
+ {
+ bool bDupe = false;
+ foreach(URLString us in alUrls)
+ {
+ if(usThat.Equals(us))
+ {
+ bDupe = true;
+ break;
+ }
+ }
+ if(!bDupe)
+ alUrls.Add(usThat);
+ }
+ UrlIdentityPermission result = new UrlIdentityPermission(PermissionState.None);
+ result.m_urls = alUrls.ToArray();
+ return result;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override void FromXml(SecurityElement esd)
+ {
+ m_unrestricted = false;
+ m_urls = null;
+ CodeAccessPermission.ValidateElement( esd, this );
+ String unr = esd.Attribute( "Unrestricted" );
+ if(unr != null && String.Compare(unr, "true", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ m_unrestricted = true;
+ return;
+ }
+ String elem = esd.Attribute( "Url" );
+ List<URLString> al = new List<URLString>();
+ if(elem != null)
+ al.Add(new URLString( elem, true ));
+ ArrayList alChildren = esd.Children;
+ if(alChildren != null)
+ {
+ foreach(SecurityElement child in alChildren)
+ {
+ elem = child.Attribute( "Url" );
+ if(elem != null)
+ al.Add(new URLString( elem, true ));
+ }
+ }
+ if(al.Count != 0)
+ m_urls = al.ToArray();
+ }
+
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.UrlIdentityPermission" );
+ if (m_unrestricted)
+ esd.AddAttribute( "Unrestricted", "true" );
+ else if (m_urls != null)
+ {
+ if (m_urls.Length == 1)
+ esd.AddAttribute( "Url", m_urls[0].ToString() );
+ else
+ {
+ int n;
+ for(n = 0; n < m_urls.Length; n++)
+ {
+ SecurityElement child = new SecurityElement("Url");
+ child.AddAttribute( "Url", m_urls[n].ToString() );
+ esd.AddChild(child);
+ }
+ }
+ }
+ return esd;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return UrlIdentityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.UrlIdentityPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs b/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs
new file mode 100644
index 0000000000..803bd34cf1
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/ZoneIdentityPermission.cs
@@ -0,0 +1,309 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+
+namespace System.Security.Permissions
+{
+ using System;
+#if FEATURE_CAS_POLICY
+ using SecurityElement = System.Security.SecurityElement;
+#endif // FEATURE_CAS_POLICY
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ sealed public class ZoneIdentityPermission : CodeAccessPermission, IBuiltInPermission
+ {
+ //------------------------------------------------------
+ //
+ // PRIVATE STATE DATA
+ //
+ //------------------------------------------------------
+
+ // Zone Enum Flag
+ // ----- ----- -----
+ // NoZone -1 0x00
+ // MyComputer 0 0x01 (1 << 0)
+ // Intranet 1 0x02 (1 << 1)
+ // Trusted 2 0x04 (1 << 2)
+ // Internet 3 0x08 (1 << 3)
+ // Untrusted 4 0x10 (1 << 4)
+
+ private const uint AllZones = 0x1f;
+ [OptionalField(VersionAdded = 2)]
+ private uint m_zones;
+
+#if FEATURE_REMOTING
+ // This field will be populated only for non X-AD scenarios where we create a XML-ised string of the Permission
+ [OptionalField(VersionAdded = 2)]
+ private String m_serializedPermission;
+
+ // This field is legacy info from v1.x and is never used in v2.0 and beyond: purely for serialization purposes
+ private SecurityZone m_zone = SecurityZone.NoZone;
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ // v2.0 and beyond XML case
+ if (m_serializedPermission != null)
+ {
+ FromXml(SecurityElement.FromString(m_serializedPermission));
+ m_serializedPermission = null;
+ }
+ else //v1.x case where we read the m_zone value
+ {
+ SecurityZone = m_zone;
+ m_zone = SecurityZone.NoZone;
+ }
+ }
+
+
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = ToXml().ToString(); //for the v2 and beyond case
+ m_zone = SecurityZone;
+
+ }
+ }
+ [OnSerialized]
+ private void OnSerialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_serializedPermission = null;
+ m_zone = SecurityZone.NoZone;
+ }
+ }
+#endif // FEATURE_REMOTING
+
+ //------------------------------------------------------
+ //
+ // PUBLIC CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ public ZoneIdentityPermission(PermissionState state)
+ {
+ if (state == PermissionState.Unrestricted)
+ {
+ m_zones = AllZones;
+ }
+ else if (state == PermissionState.None)
+ {
+ m_zones = 0;
+ }
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ }
+ }
+
+ public ZoneIdentityPermission( SecurityZone zone )
+ {
+ this.SecurityZone = zone;
+ }
+
+ internal ZoneIdentityPermission( uint zones )
+ {
+ m_zones = (zones & AllZones);
+ }
+
+ // Internal function to append all the Zone in this permission to the input ArrayList
+ internal void AppendZones(ArrayList zoneList)
+ {
+ int nEnum = 0;
+ uint nFlag;
+ for(nFlag = 1; nFlag < AllZones; nFlag <<= 1)
+ {
+ if((m_zones & nFlag) != 0)
+ {
+ zoneList.Add((SecurityZone)nEnum);
+ }
+ nEnum++;
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PUBLIC ACCESSOR METHODS
+ //
+ //------------------------------------------------------
+
+ public SecurityZone SecurityZone
+ {
+ set
+ {
+ VerifyZone( value );
+ if(value == SecurityZone.NoZone)
+ m_zones = 0;
+ else
+ m_zones = (uint)1 << (int)value;
+ }
+
+ get
+ {
+ SecurityZone z = SecurityZone.NoZone;
+ int nEnum = 0;
+ uint nFlag;
+ for(nFlag = 1; nFlag < AllZones; nFlag <<= 1)
+ {
+ if((m_zones & nFlag) != 0)
+ {
+ if(z == SecurityZone.NoZone)
+ z = (SecurityZone)nEnum;
+ else
+ return SecurityZone.NoZone;
+ }
+ nEnum++;
+ }
+ return z;
+ }
+ }
+
+ //------------------------------------------------------
+ //
+ // PRIVATE AND PROTECTED HELPERS FOR ACCESSORS AND CONSTRUCTORS
+ //
+ //------------------------------------------------------
+
+ private static void VerifyZone( SecurityZone zone )
+ {
+ if (zone < SecurityZone.NoZone || zone > SecurityZone.Untrusted)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_IllegalZone") );
+ }
+ Contract.EndContractBlock();
+ }
+
+
+ //------------------------------------------------------
+ //
+ // CODEACCESSPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+ //------------------------------------------------------
+ //
+ // IPERMISSION IMPLEMENTATION
+ //
+ //------------------------------------------------------
+
+
+ public override IPermission Copy()
+ {
+ return new ZoneIdentityPermission(this.m_zones);
+ }
+
+ public override bool IsSubsetOf(IPermission target)
+ {
+ if (target == null)
+ return this.m_zones == 0;
+
+ ZoneIdentityPermission that = target as ZoneIdentityPermission;
+ if (that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ return (this.m_zones & that.m_zones) == this.m_zones;
+ }
+
+ public override IPermission Intersect(IPermission target)
+ {
+ if (target == null)
+ return null;
+
+ ZoneIdentityPermission that = target as ZoneIdentityPermission;
+ if (that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ uint newZones = this.m_zones & that.m_zones;
+ if(newZones == 0)
+ return null;
+ return new ZoneIdentityPermission(newZones);
+ }
+
+ public override IPermission Union(IPermission target)
+ {
+ if (target == null)
+ return this.m_zones != 0 ? this.Copy() : null;
+
+ ZoneIdentityPermission that = target as ZoneIdentityPermission;
+ if (that == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+ return new ZoneIdentityPermission(this.m_zones | that.m_zones);
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml()
+ {
+ SecurityElement esd = CodeAccessPermission.CreatePermissionElement( this, "System.Security.Permissions.ZoneIdentityPermission" );
+ if (SecurityZone != SecurityZone.NoZone)
+ {
+ esd.AddAttribute( "Zone", Enum.GetName( typeof( SecurityZone ), this.SecurityZone ) );
+ }
+ else
+ {
+ int nEnum = 0;
+ uint nFlag;
+ for(nFlag = 1; nFlag < AllZones; nFlag <<= 1)
+ {
+ if((m_zones & nFlag) != 0)
+ {
+ SecurityElement child = new SecurityElement("Zone");
+ child.AddAttribute( "Zone", Enum.GetName( typeof( SecurityZone ), (SecurityZone)nEnum ) );
+ esd.AddChild(child);
+ }
+ nEnum++;
+ }
+ }
+ return esd;
+ }
+
+ public override void FromXml(SecurityElement esd)
+ {
+ m_zones = 0;
+ CodeAccessPermission.ValidateElement( esd, this );
+ String eZone = esd.Attribute( "Zone" );
+ if (eZone != null)
+ SecurityZone = (SecurityZone)Enum.Parse( typeof( SecurityZone ), eZone );
+ if(esd.Children != null)
+ {
+ foreach(SecurityElement child in esd.Children)
+ {
+ eZone = child.Attribute( "Zone" );
+ int enm = (int)Enum.Parse( typeof( SecurityZone ), eZone );
+ if(enm == (int)SecurityZone.NoZone)
+ continue;
+ m_zones |= ((uint)1 << enm);
+ }
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex()
+ {
+ return ZoneIdentityPermission.GetTokenIndex();
+ }
+
+ internal static int GetTokenIndex()
+ {
+ return BuiltInPermissionIndex.ZoneIdentityPermissionIndex;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs b/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs
new file mode 100644
index 0000000000..9691c03da3
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Permissions/keycontainerpermission.cs
@@ -0,0 +1,688 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Permissions {
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+#if FEATURE_CRYPTO
+ using System.Security.Cryptography;
+#endif
+ using System.Security.Util;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+ [Flags]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum KeyContainerPermissionFlags {
+ NoFlags = 0x0000,
+
+ Create = 0x0001,
+ Open = 0x0002,
+ Delete = 0x0004,
+
+ Import = 0x0010,
+ Export = 0x0020,
+
+ Sign = 0x0100,
+ Decrypt = 0x0200,
+
+ ViewAcl = 0x1000,
+ ChangeAcl = 0x2000,
+
+ AllFlags = 0x3337
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class KeyContainerPermissionAccessEntry {
+ private string m_keyStore;
+ private string m_providerName;
+ private int m_providerType;
+ private string m_keyContainerName;
+ private int m_keySpec;
+ private KeyContainerPermissionFlags m_flags;
+
+ internal KeyContainerPermissionAccessEntry(KeyContainerPermissionAccessEntry accessEntry) :
+ this (accessEntry.KeyStore, accessEntry.ProviderName, accessEntry.ProviderType, accessEntry.KeyContainerName,
+ accessEntry.KeySpec, accessEntry.Flags) {
+ }
+
+ public KeyContainerPermissionAccessEntry(string keyContainerName, KeyContainerPermissionFlags flags) :
+ this (null, null, -1, keyContainerName, -1, flags) {
+ }
+
+#if FEATURE_CRYPTO
+ public KeyContainerPermissionAccessEntry(CspParameters parameters, KeyContainerPermissionFlags flags) :
+ this((parameters.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore ? "Machine" : "User",
+ parameters.ProviderName,
+ parameters.ProviderType,
+ parameters.KeyContainerName,
+ parameters.KeyNumber,
+ flags) {
+ }
+#endif
+
+ public KeyContainerPermissionAccessEntry(string keyStore, string providerName, int providerType,
+ string keyContainerName, int keySpec, KeyContainerPermissionFlags flags) {
+ m_providerName = (providerName == null ? "*" : providerName);
+ m_providerType = providerType;
+ m_keyContainerName = (keyContainerName == null ? "*" : keyContainerName);
+ m_keySpec = keySpec;
+ KeyStore = keyStore;
+ Flags = flags;
+ }
+
+ public string KeyStore {
+ get {
+ return m_keyStore;
+ }
+ set {
+ // Unrestricted entries are invalid; they should not be allowed.
+ if (IsUnrestrictedEntry(value, this.ProviderName, this.ProviderType, this.KeyContainerName, this.KeySpec))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
+
+ if (value == null) {
+ m_keyStore = "*";
+ } else {
+ if (value != "User" && value != "Machine" && value != "*")
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidKeyStore", value), "value");
+ m_keyStore = value;
+ }
+ }
+ }
+
+ public string ProviderName {
+ get {
+ return m_providerName;
+ }
+ set {
+ // Unrestricted entries are invalid; they should not be allowed.
+ if (IsUnrestrictedEntry(this.KeyStore, value, this.ProviderType, this.KeyContainerName, this.KeySpec))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
+
+ if (value == null)
+ m_providerName = "*";
+ else
+ m_providerName = value;
+ }
+ }
+
+ public int ProviderType {
+ get {
+ return m_providerType;
+ }
+ set {
+ // Unrestricted entries are invalid; they should not be allowed.
+ if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, value, this.KeyContainerName, this.KeySpec))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
+
+ m_providerType = value;
+ }
+ }
+
+ public string KeyContainerName {
+ get {
+ return m_keyContainerName;
+ }
+ set {
+ // Unrestricted entries are invalid; they should not be allowed.
+ if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, value, this.KeySpec))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
+
+ if (value == null)
+ m_keyContainerName = "*";
+ else
+ m_keyContainerName = value;
+ }
+ }
+
+ public int KeySpec {
+ get {
+ return m_keySpec;
+ }
+ set {
+ // Unrestricted entries are invalid; they should not be allowed.
+ if (IsUnrestrictedEntry(this.KeyStore, this.ProviderName, this.ProviderType, this.KeyContainerName, value))
+ throw new ArgumentException(Environment.GetResourceString("Arg_InvalidAccessEntry"));
+
+ m_keySpec = value;
+ }
+ }
+
+ public KeyContainerPermissionFlags Flags {
+ get {
+ return m_flags;
+ }
+ set {
+ KeyContainerPermission.VerifyFlags(value);
+ m_flags = value;
+ }
+ }
+
+ public override bool Equals (Object o) {
+ KeyContainerPermissionAccessEntry accessEntry = o as KeyContainerPermissionAccessEntry;
+ if (accessEntry == null)
+ return false;
+
+ if (accessEntry.m_keyStore != m_keyStore) return false;
+ if (accessEntry.m_providerName != m_providerName) return false;
+ if (accessEntry.m_providerType != m_providerType) return false;
+ if (accessEntry.m_keyContainerName != m_keyContainerName) return false;
+ if (accessEntry.m_keySpec != m_keySpec) return false;
+
+ return true;
+ }
+
+ public override int GetHashCode () {
+ int hash = 0;
+
+ hash |= (this.m_keyStore.GetHashCode() & 0x000000FF) << 24;
+ hash |= (this.m_providerName.GetHashCode() & 0x000000FF) << 16;
+ hash |= (this.m_providerType & 0x0000000F) << 12;
+ hash |= (this.m_keyContainerName.GetHashCode() & 0x000000FF) << 4;
+ hash |= (this.m_keySpec & 0x0000000F);
+
+ return hash;
+ }
+
+ internal bool IsSubsetOf (KeyContainerPermissionAccessEntry target) {
+ if (target.m_keyStore != "*" && this.m_keyStore != target.m_keyStore)
+ return false;
+ if (target.m_providerName != "*" && this.m_providerName != target.m_providerName)
+ return false;
+ if (target.m_providerType != -1 && this.m_providerType != target.m_providerType)
+ return false;
+ if (target.m_keyContainerName != "*" && this.m_keyContainerName != target.m_keyContainerName)
+ return false;
+ if (target.m_keySpec != -1 && this.m_keySpec != target.m_keySpec)
+ return false;
+
+ return true;
+ }
+
+ internal static bool IsUnrestrictedEntry (string keyStore, string providerName, int providerType,
+ string keyContainerName, int keySpec) {
+ if (keyStore != "*" && keyStore != null) return false;
+ if (providerName != "*" && providerName != null) return false;
+ if (providerType != -1) return false;
+ if (keyContainerName != "*" && keyContainerName != null) return false;
+ if (keySpec != -1) return false;
+
+ return true;
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class KeyContainerPermissionAccessEntryCollection : ICollection {
+ private ArrayList m_list;
+ private KeyContainerPermissionFlags m_globalFlags;
+
+ private KeyContainerPermissionAccessEntryCollection () {}
+ internal KeyContainerPermissionAccessEntryCollection (KeyContainerPermissionFlags globalFlags) {
+ m_list = new ArrayList();
+ m_globalFlags = globalFlags;
+ }
+
+ public KeyContainerPermissionAccessEntry this[int index] {
+ get {
+ if (index < 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumNotStarted"));
+ if (index >= Count)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ return (KeyContainerPermissionAccessEntry)m_list[index];
+ }
+ }
+
+ public int Count {
+ get {
+ return m_list.Count;
+ }
+ }
+
+ public int Add (KeyContainerPermissionAccessEntry accessEntry) {
+ if (accessEntry == null)
+ throw new ArgumentNullException("accessEntry");
+ Contract.EndContractBlock();
+
+ int index = m_list.IndexOf(accessEntry);
+ if (index == -1) {
+ if (accessEntry.Flags != m_globalFlags) {
+ return m_list.Add(accessEntry);
+ }
+ else
+ return -1;
+ } else {
+ // We pick up the intersection of the 2 flags. This is the secure choice
+ // so we are opting for it.
+ ((KeyContainerPermissionAccessEntry)m_list[index]).Flags &= accessEntry.Flags;
+ return index;
+ }
+ }
+
+ public void Clear () {
+ m_list.Clear();
+ }
+
+ public int IndexOf (KeyContainerPermissionAccessEntry accessEntry) {
+ return m_list.IndexOf(accessEntry);
+ }
+
+ public void Remove (KeyContainerPermissionAccessEntry accessEntry) {
+ if (accessEntry == null)
+ throw new ArgumentNullException("accessEntry");
+ Contract.EndContractBlock();
+ m_list.Remove(accessEntry);
+ }
+
+ public KeyContainerPermissionAccessEntryEnumerator GetEnumerator () {
+ return new KeyContainerPermissionAccessEntryEnumerator(this);
+ }
+
+ /// <internalonly/>
+ IEnumerator IEnumerable.GetEnumerator () {
+ return new KeyContainerPermissionAccessEntryEnumerator(this);
+ }
+
+ /// <internalonly/>
+ void ICollection.CopyTo (Array array, int index) {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0 || index >= array.Length)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (index + this.Count > array.Length)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ for (int i=0; i < this.Count; i++) {
+ array.SetValue(this[i], index);
+ index++;
+ }
+ }
+
+ public void CopyTo (KeyContainerPermissionAccessEntry[] array, int index) {
+ ((ICollection)this).CopyTo(array, index);
+ }
+
+ public bool IsSynchronized {
+ get {
+ return false;
+ }
+ }
+
+ public Object SyncRoot {
+ get {
+ return this;
+ }
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class KeyContainerPermissionAccessEntryEnumerator : IEnumerator {
+ private KeyContainerPermissionAccessEntryCollection m_entries;
+ private int m_current;
+
+ private KeyContainerPermissionAccessEntryEnumerator () {}
+ internal KeyContainerPermissionAccessEntryEnumerator (KeyContainerPermissionAccessEntryCollection entries) {
+ m_entries = entries;
+ m_current = -1;
+ }
+
+ public KeyContainerPermissionAccessEntry Current {
+ get {
+ return m_entries[m_current];
+ }
+ }
+
+ /// <internalonly/>
+ Object IEnumerator.Current {
+ get {
+ return (Object) m_entries[m_current];
+ }
+ }
+
+ public bool MoveNext() {
+ if (m_current == ((int) m_entries.Count - 1))
+ return false;
+ m_current++;
+ return true;
+ }
+
+ public void Reset() {
+ m_current = -1;
+ }
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class KeyContainerPermission : CodeAccessPermission, IUnrestrictedPermission, IBuiltInPermission {
+ private KeyContainerPermissionFlags m_flags;
+ private KeyContainerPermissionAccessEntryCollection m_accessEntries;
+
+ public KeyContainerPermission (PermissionState state) {
+ if (state == PermissionState.Unrestricted)
+ m_flags = KeyContainerPermissionFlags.AllFlags;
+ else if (state == PermissionState.None)
+ m_flags = KeyContainerPermissionFlags.NoFlags;
+ else
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidPermissionState"));
+ m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
+ }
+
+ public KeyContainerPermission (KeyContainerPermissionFlags flags) {
+ VerifyFlags(flags);
+ m_flags = flags;
+ m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
+ }
+
+ public KeyContainerPermission (KeyContainerPermissionFlags flags, KeyContainerPermissionAccessEntry[] accessList) {
+ if (accessList == null)
+ throw new ArgumentNullException("accessList");
+ Contract.EndContractBlock();
+
+ VerifyFlags(flags);
+ m_flags = flags;
+ m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
+ for (int index = 0; index < accessList.Length; index++) {
+ m_accessEntries.Add(accessList[index]);
+ }
+ }
+
+ public KeyContainerPermissionFlags Flags {
+ get {
+ return m_flags;
+ }
+ }
+
+ public KeyContainerPermissionAccessEntryCollection AccessEntries {
+ get {
+ return m_accessEntries;
+ }
+ }
+
+ public bool IsUnrestricted () {
+ if (m_flags != KeyContainerPermissionFlags.AllFlags)
+ return false;
+
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ if ((accessEntry.Flags & KeyContainerPermissionFlags.AllFlags) != KeyContainerPermissionFlags.AllFlags)
+ return false;
+ }
+
+ return true;
+ }
+
+ private bool IsEmpty () {
+ if (this.Flags == KeyContainerPermissionFlags.NoFlags) {
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ if (accessEntry.Flags != KeyContainerPermissionFlags.NoFlags)
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ //
+ // IPermission implementation
+ //
+
+ public override bool IsSubsetOf (IPermission target) {
+ if (target == null)
+ return IsEmpty();
+
+ if (!VerifyType(target))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+
+ KeyContainerPermission operand = (KeyContainerPermission) target;
+
+ // since there are containers that are neither in the access list of the source, nor in the
+ // access list of the target, the source flags must be a subset of the target flags.
+ if ((this.m_flags & operand.m_flags) != this.m_flags)
+ return false;
+
+ // Any entry in the source should have "applicable" flags in the destination that actually
+ // are less restrictive than the flags in the source.
+
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ KeyContainerPermissionFlags targetFlags = GetApplicableFlags(accessEntry, operand);
+ if ((accessEntry.Flags & targetFlags) != accessEntry.Flags)
+ return false;
+ }
+
+ // Any entry in the target should have "applicable" flags in the source that actually
+ // are more restrictive than the flags in the target.
+
+ foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
+ KeyContainerPermissionFlags sourceFlags = GetApplicableFlags(accessEntry, this);
+ if ((sourceFlags & accessEntry.Flags) != sourceFlags)
+ return false;
+ }
+
+ return true;
+ }
+
+ public override IPermission Intersect (IPermission target) {
+ if (target == null)
+ return null;
+
+ if (!VerifyType(target))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+
+ KeyContainerPermission operand = (KeyContainerPermission) target;
+ if (this.IsEmpty() || operand.IsEmpty())
+ return null;
+
+ KeyContainerPermissionFlags flags_intersect = operand.m_flags & this.m_flags;
+ KeyContainerPermission cp = new KeyContainerPermission(flags_intersect);
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ cp.AddAccessEntryAndIntersect(accessEntry, operand);
+ }
+ foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
+ cp.AddAccessEntryAndIntersect(accessEntry, this);
+ }
+ return cp.IsEmpty() ? null : cp;
+ }
+
+ public override IPermission Union (IPermission target) {
+ if (target == null)
+ return this.Copy();
+
+ if (!VerifyType(target))
+ throw new ArgumentException(Environment.GetResourceString("Argument_WrongType", this.GetType().FullName));
+
+ KeyContainerPermission operand = (KeyContainerPermission) target;
+ if (this.IsUnrestricted() || operand.IsUnrestricted())
+ return new KeyContainerPermission(PermissionState.Unrestricted);
+
+ KeyContainerPermissionFlags flags_union = (KeyContainerPermissionFlags) (m_flags | operand.m_flags);
+ KeyContainerPermission cp = new KeyContainerPermission(flags_union);
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ cp.AddAccessEntryAndUnion(accessEntry, operand);
+ }
+ foreach (KeyContainerPermissionAccessEntry accessEntry in operand.AccessEntries) {
+ cp.AddAccessEntryAndUnion(accessEntry, this);
+ }
+ return cp.IsEmpty() ? null : cp;
+ }
+
+ public override IPermission Copy () {
+ if (this.IsEmpty())
+ return null;
+
+ KeyContainerPermission cp = new KeyContainerPermission((KeyContainerPermissionFlags)m_flags);
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ cp.AccessEntries.Add(accessEntry);
+ }
+ return cp;
+ }
+
+#if FEATURE_CAS_POLICY
+ public override SecurityElement ToXml () {
+ SecurityElement securityElement = CodeAccessPermission.CreatePermissionElement(this, "System.Security.Permissions.KeyContainerPermission");
+ if (!IsUnrestricted()) {
+ securityElement.AddAttribute("Flags", m_flags.ToString());
+ if (AccessEntries.Count > 0) {
+ SecurityElement al = new SecurityElement("AccessList");
+ foreach (KeyContainerPermissionAccessEntry accessEntry in AccessEntries) {
+ SecurityElement entryElem = new SecurityElement("AccessEntry");
+ entryElem.AddAttribute("KeyStore", accessEntry.KeyStore);
+ entryElem.AddAttribute("ProviderName", accessEntry.ProviderName);
+ entryElem.AddAttribute("ProviderType", accessEntry.ProviderType.ToString(null, null));
+ entryElem.AddAttribute("KeyContainerName", accessEntry.KeyContainerName);
+ entryElem.AddAttribute("KeySpec", accessEntry.KeySpec.ToString(null, null));
+ entryElem.AddAttribute("Flags", accessEntry.Flags.ToString());
+ al.AddChild(entryElem);
+ }
+ securityElement.AddChild(al);
+ }
+ } else
+ securityElement.AddAttribute("Unrestricted", "true");
+
+ return securityElement;
+ }
+
+ public override void FromXml (SecurityElement securityElement) {
+ CodeAccessPermission.ValidateElement(securityElement, this);
+ if (XMLUtil.IsUnrestricted(securityElement)) {
+ m_flags = KeyContainerPermissionFlags.AllFlags;
+ m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
+ return;
+ }
+
+ m_flags = KeyContainerPermissionFlags.NoFlags;
+ string strFlags = securityElement.Attribute("Flags");
+ if (strFlags != null) {
+ KeyContainerPermissionFlags flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strFlags);
+ VerifyFlags(flags);
+ m_flags = flags;
+ }
+ m_accessEntries = new KeyContainerPermissionAccessEntryCollection(m_flags);
+
+ if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
+ IEnumerator enumerator = securityElement.Children.GetEnumerator();
+ while (enumerator.MoveNext()) {
+ SecurityElement current = (SecurityElement) enumerator.Current;
+ if (current != null) {
+ if (String.Equals(current.Tag, "AccessList"))
+ AddAccessEntries(current);
+ }
+ }
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <internalonly/>
+ int IBuiltInPermission.GetTokenIndex () {
+ return KeyContainerPermission.GetTokenIndex();
+ }
+
+ //
+ // private methods
+ //
+
+ private void AddAccessEntries(SecurityElement securityElement) {
+ if (securityElement.InternalChildren != null && securityElement.InternalChildren.Count != 0) {
+ IEnumerator elemEnumerator = securityElement.Children.GetEnumerator();
+ while (elemEnumerator.MoveNext()) {
+ SecurityElement current = (SecurityElement) elemEnumerator.Current;
+ if (current != null) {
+ if (String.Equals(current.Tag, "AccessEntry")) {
+ int iMax = current.m_lAttributes.Count;
+ Contract.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
+ string keyStore = null;
+ string providerName = null;
+ int providerType = -1;
+ string keyContainerName = null;
+ int keySpec = -1;
+ KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
+ for (int i = 0; i < iMax; i += 2) {
+ String strAttrName = (String) current.m_lAttributes[i];
+ String strAttrValue = (String) current.m_lAttributes[i+1];
+ if (String.Equals(strAttrName, "KeyStore"))
+ keyStore = strAttrValue;
+ if (String.Equals(strAttrName, "ProviderName"))
+ providerName = strAttrValue;
+ else if (String.Equals(strAttrName, "ProviderType"))
+ providerType = Convert.ToInt32(strAttrValue, null);
+ else if (String.Equals(strAttrName, "KeyContainerName"))
+ keyContainerName = strAttrValue;
+ else if (String.Equals(strAttrName, "KeySpec"))
+ keySpec = Convert.ToInt32(strAttrValue, null);
+ else if (String.Equals(strAttrName, "Flags")) {
+ flags = (KeyContainerPermissionFlags) Enum.Parse(typeof(KeyContainerPermissionFlags), strAttrValue);
+ }
+ }
+ KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(keyStore, providerName, providerType, keyContainerName, keySpec, flags);
+ AccessEntries.Add(accessEntry);
+ }
+ }
+ }
+ }
+ }
+
+ private void AddAccessEntryAndUnion (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
+ KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
+ newAccessEntry.Flags |= GetApplicableFlags(accessEntry, target);
+ AccessEntries.Add(newAccessEntry);
+ }
+
+ private void AddAccessEntryAndIntersect (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
+ KeyContainerPermissionAccessEntry newAccessEntry = new KeyContainerPermissionAccessEntry(accessEntry);
+ newAccessEntry.Flags &= GetApplicableFlags(accessEntry, target);
+ AccessEntries.Add(newAccessEntry);
+ }
+
+ //
+ // private/internal static methods.
+ //
+
+ internal static void VerifyFlags (KeyContainerPermissionFlags flags) {
+ if ((flags & ~KeyContainerPermissionFlags.AllFlags) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)flags));
+ Contract.EndContractBlock();
+ }
+
+ private static KeyContainerPermissionFlags GetApplicableFlags (KeyContainerPermissionAccessEntry accessEntry, KeyContainerPermission target) {
+ KeyContainerPermissionFlags flags = KeyContainerPermissionFlags.NoFlags;
+ bool applyDefaultFlags = true;
+
+ // If the entry exists in the target, return the flag of the target entry.
+ int index = target.AccessEntries.IndexOf(accessEntry);
+ if (index != -1) {
+ flags = ((KeyContainerPermissionAccessEntry)target.AccessEntries[index]).Flags;
+ return flags;
+ }
+
+ // Intersect the flags in all the target entries that apply to the current access entry,
+ foreach (KeyContainerPermissionAccessEntry targetAccessEntry in target.AccessEntries) {
+ if (accessEntry.IsSubsetOf(targetAccessEntry)) {
+ if (applyDefaultFlags == false) {
+ flags &= targetAccessEntry.Flags;
+ } else {
+ flags = targetAccessEntry.Flags;
+ applyDefaultFlags = false;
+ }
+ }
+ }
+
+ // If no target entry applies to the current entry, the default global flag applies.
+ if (applyDefaultFlags)
+ flags = target.Flags;
+
+ return flags;
+ }
+
+ private static int GetTokenIndex() {
+ return BuiltInPermissionIndex.KeyContainerPermissionIndex;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs b/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs
new file mode 100644
index 0000000000..57b216e462
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/ApplicationTrust.cs
@@ -0,0 +1,689 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// This class encapsulates security decisions about an application.
+//
+
+namespace System.Security.Policy {
+ using System.Collections;
+ using System.Collections.Generic;
+#if FEATURE_CLICKONCE
+ using System.Deployment.Internal.Isolation;
+ using System.Deployment.Internal.Isolation.Manifest;
+#endif
+ using System.Globalization;
+ using System.IO;
+ using System.Runtime.InteropServices;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization;
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using System.Security.Util;
+ using System.Text;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum ApplicationVersionMatch {
+ MatchExactVersion,
+ MatchAllVersions
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class ApplicationTrust : EvidenceBase, ISecurityEncodable
+ {
+#if FEATURE_CLICKONCE
+ private ApplicationIdentity m_appId;
+ private bool m_appTrustedToRun;
+ private bool m_persist;
+
+ private object m_extraInfo;
+ private SecurityElement m_elExtraInfo;
+#endif
+ private PolicyStatement m_psDefaultGrant;
+ private IList<StrongName> m_fullTrustAssemblies;
+
+ // Permission special flags for the default grant set in this ApplicationTrust. This should be
+ // updated in sync with any updates to the default grant set.
+ //
+ // In the general case, these values cannot be trusted - we only store a reference to the
+ // DefaultGrantSet, and return the reference directly, which means that code can update the
+ // permission set without our knowledge. That would lead to the flags getting out of sync with the
+ // grant set.
+ //
+ // However, we only care about these flags when we're creating a homogenous AppDomain, and in that
+ // case we control the ApplicationTrust object end-to-end, and know that the permission set will not
+ // change after the flags are calculated.
+ [NonSerialized]
+ private int m_grantSetSpecialFlags;
+
+#if FEATURE_CLICKONCE
+ public ApplicationTrust (ApplicationIdentity applicationIdentity) : this () {
+ ApplicationIdentity = applicationIdentity;
+ }
+#endif
+ public ApplicationTrust () : this (new PermissionSet(PermissionState.None))
+ {
+ }
+
+ internal ApplicationTrust (PermissionSet defaultGrantSet)
+ {
+ InitDefaultGrantSet(defaultGrantSet);
+
+ m_fullTrustAssemblies = new List<StrongName>().AsReadOnly();
+ }
+
+ public ApplicationTrust(PermissionSet defaultGrantSet, IEnumerable<StrongName> fullTrustAssemblies) {
+ if (fullTrustAssemblies == null) {
+ throw new ArgumentNullException("fullTrustAssemblies");
+ }
+
+ InitDefaultGrantSet(defaultGrantSet);
+
+ List<StrongName> fullTrustList = new List<StrongName>();
+ foreach (StrongName strongName in fullTrustAssemblies) {
+ if (strongName == null) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_NullFullTrustAssembly"), "fullTrustAssemblies");
+ }
+
+ fullTrustList.Add(new StrongName(strongName.PublicKey, strongName.Name, strongName.Version));
+ }
+
+ m_fullTrustAssemblies = fullTrustList.AsReadOnly();
+ }
+
+ // Sets up the default grant set for all constructors. Extracted to avoid the cost of
+ // IEnumerable virtual dispatches on startup when there are no fullTrustAssemblies (CoreCLR)
+ private void InitDefaultGrantSet(PermissionSet defaultGrantSet) {
+ if (defaultGrantSet == null) {
+ throw new ArgumentNullException("defaultGrantSet");
+ }
+
+ // Creating a PolicyStatement copies the incoming permission set, so we don't have to worry
+ // about the PermissionSet parameter changing underneath us after we've calculated the
+ // permisison flags in the DefaultGrantSet setter.
+ DefaultGrantSet = new PolicyStatement(defaultGrantSet);
+ }
+
+#if FEATURE_CLICKONCE
+ public ApplicationIdentity ApplicationIdentity {
+ get {
+ return m_appId;
+ }
+ set {
+ if (value == null)
+ throw new ArgumentNullException("value", Environment.GetResourceString("Argument_InvalidAppId"));
+ Contract.EndContractBlock();
+ m_appId = value;
+ }
+ }
+#endif
+ public PolicyStatement DefaultGrantSet {
+ get {
+ if (m_psDefaultGrant == null)
+ return new PolicyStatement(new PermissionSet(PermissionState.None));
+ return m_psDefaultGrant;
+ }
+ set {
+ if (value == null) {
+ m_psDefaultGrant = null;
+ m_grantSetSpecialFlags = 0;
+ }
+ else {
+ m_psDefaultGrant = value;
+ m_grantSetSpecialFlags = SecurityManager.GetSpecialFlags(m_psDefaultGrant.PermissionSet, null);
+ }
+ }
+ }
+
+ public IList<StrongName> FullTrustAssemblies {
+ get {
+ return m_fullTrustAssemblies;
+ }
+ }
+#if FEATURE_CLICKONCE
+ public bool IsApplicationTrustedToRun {
+ get {
+ return m_appTrustedToRun;
+ }
+ set {
+ m_appTrustedToRun = value;
+ }
+ }
+
+ public bool Persist {
+ get {
+ return m_persist;
+ }
+ set {
+ m_persist = value;
+ }
+ }
+
+ public object ExtraInfo {
+ get {
+ if (m_elExtraInfo != null) {
+ m_extraInfo = ObjectFromXml(m_elExtraInfo);
+ m_elExtraInfo = null;
+ }
+ return m_extraInfo;
+ }
+ set {
+ m_elExtraInfo = null;
+ m_extraInfo = value;
+ }
+ }
+#endif //FEATURE_CLICKONCE
+
+#if FEATURE_CAS_POLICY
+ public SecurityElement ToXml () {
+ SecurityElement elRoot = new SecurityElement("ApplicationTrust");
+ elRoot.AddAttribute("version", "1");
+
+#if FEATURE_CLICKONCE
+ if (m_appId != null) {
+ elRoot.AddAttribute("FullName", SecurityElement.Escape(m_appId.FullName));
+ }
+ if (m_appTrustedToRun) {
+ elRoot.AddAttribute("TrustedToRun", "true");
+ }
+ if (m_persist) {
+ elRoot.AddAttribute("Persist", "true");
+ }
+#endif // FEATURE_CLICKONCE
+
+ if (m_psDefaultGrant != null) {
+ SecurityElement elDefaultGrant = new SecurityElement("DefaultGrant");
+ elDefaultGrant.AddChild(m_psDefaultGrant.ToXml());
+ elRoot.AddChild(elDefaultGrant);
+ }
+ if (m_fullTrustAssemblies.Count > 0) {
+ SecurityElement elFullTrustAssemblies = new SecurityElement("FullTrustAssemblies");
+ foreach (StrongName fullTrustAssembly in m_fullTrustAssemblies) {
+ elFullTrustAssemblies.AddChild(fullTrustAssembly.ToXml());
+ }
+ elRoot.AddChild(elFullTrustAssemblies);
+ }
+
+#if FEATURE_CLICKONCE
+ if (ExtraInfo != null) {
+ elRoot.AddChild(ObjectToXml("ExtraInfo", ExtraInfo));
+ }
+#endif // FEATURE_CLICKONCE
+ return elRoot;
+ }
+
+ public void FromXml (SecurityElement element) {
+ if (element == null)
+ throw new ArgumentNullException("element");
+ if (String.Compare(element.Tag, "ApplicationTrust", StringComparison.Ordinal) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML"));
+
+#if FEATURE_CLICKONCE
+ m_appTrustedToRun = false;
+ string isAppTrustedToRun = element.Attribute("TrustedToRun");
+ if (isAppTrustedToRun != null && String.Compare(isAppTrustedToRun, "true", StringComparison.Ordinal) == 0) {
+ m_appTrustedToRun = true;
+ }
+
+ m_persist = false;
+ string persist = element.Attribute("Persist");
+ if (persist != null && String.Compare(persist, "true", StringComparison.Ordinal) == 0) {
+ m_persist = true;
+ }
+
+ m_appId = null;
+ string fullName = element.Attribute("FullName");
+ if (fullName != null && fullName.Length > 0) {
+ m_appId = new ApplicationIdentity(fullName);
+ }
+#endif // FEATURE_CLICKONCE
+
+ m_psDefaultGrant = null;
+ m_grantSetSpecialFlags = 0;
+ SecurityElement elDefaultGrant = element.SearchForChildByTag("DefaultGrant");
+ if (elDefaultGrant != null) {
+ SecurityElement elDefaultGrantPS = elDefaultGrant.SearchForChildByTag("PolicyStatement");
+ if (elDefaultGrantPS != null) {
+ PolicyStatement ps = new PolicyStatement(null);
+ ps.FromXml(elDefaultGrantPS);
+ m_psDefaultGrant = ps;
+ m_grantSetSpecialFlags = SecurityManager.GetSpecialFlags(ps.PermissionSet, null);
+ }
+ }
+
+ List<StrongName> fullTrustAssemblies = new List<StrongName>();
+ SecurityElement elFullTrustAssemblies = element.SearchForChildByTag("FullTrustAssemblies");
+ if (elFullTrustAssemblies != null && elFullTrustAssemblies.InternalChildren != null) {
+ IEnumerator enumerator = elFullTrustAssemblies.Children.GetEnumerator();
+ while (enumerator.MoveNext()) {
+ StrongName fullTrustAssembly = new StrongName();
+ fullTrustAssembly.FromXml(enumerator.Current as SecurityElement);
+ fullTrustAssemblies.Add(fullTrustAssembly);
+ }
+ }
+
+ m_fullTrustAssemblies = fullTrustAssemblies.AsReadOnly();
+
+#if FEATURE_CLICKONCE
+ m_elExtraInfo = element.SearchForChildByTag("ExtraInfo");
+#endif // FEATURE_CLICKONCE
+ }
+
+#if FEATURE_CLICKONCE
+ private static SecurityElement ObjectToXml (string tag, Object obj) {
+ BCLDebug.Assert(obj != null, "You need to pass in an object");
+
+ ISecurityEncodable encodableObj = obj as ISecurityEncodable;
+
+ SecurityElement elObject;
+ if (encodableObj != null) {
+ elObject = encodableObj.ToXml();
+ if (!elObject.Tag.Equals(tag))
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML"));
+ }
+
+ MemoryStream stream = new MemoryStream();
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(stream, obj);
+ byte[] array = stream.ToArray();
+
+ elObject = new SecurityElement(tag);
+ elObject.AddAttribute("Data", Hex.EncodeHexString(array));
+ return elObject;
+ }
+
+ private static Object ObjectFromXml (SecurityElement elObject) {
+ BCLDebug.Assert(elObject != null, "You need to pass in a security element");
+
+ if (elObject.Attribute("class") != null) {
+ ISecurityEncodable encodableObj = XMLUtil.CreateCodeGroup(elObject) as ISecurityEncodable;
+ if (encodableObj != null) {
+ encodableObj.FromXml(elObject);
+ return encodableObj;
+ }
+ }
+
+ string objectData = elObject.Attribute("Data");
+ MemoryStream stream = new MemoryStream(Hex.DecodeHexString(objectData));
+ BinaryFormatter formatter = new BinaryFormatter();
+ return formatter.Deserialize(stream);
+ }
+#endif // FEATURE_CLICKONCE
+#endif // FEATURE_CAS_POLICY
+
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+#pragma warning restore 618
+ [SecuritySafeCritical]
+ public override EvidenceBase Clone()
+ {
+ return base.Clone();
+ }
+ }
+
+#if FEATURE_CLICKONCE
+ [System.Security.SecurityCritical] // auto-generated_required
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ApplicationTrustCollection : ICollection {
+ private const string ApplicationTrustProperty = "ApplicationTrust";
+ private const string InstallerIdentifier = "{60051b8f-4f12-400a-8e50-dd05ebd438d1}";
+ private static Guid ClrPropertySet = new Guid("c989bb7a-8385-4715-98cf-a741a8edb823");
+
+ // The CLR specific constant install reference.
+ private static object s_installReference = null;
+ private static StoreApplicationReference InstallReference {
+ get {
+ if (s_installReference == null) {
+ Interlocked.CompareExchange(ref s_installReference,
+ new StoreApplicationReference(
+ IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING,
+ InstallerIdentifier,
+ null),
+ null);
+ }
+ return (StoreApplicationReference) s_installReference;
+ }
+ }
+
+ private object m_appTrusts = null;
+ private ArrayList AppTrusts {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ if (m_appTrusts == null) {
+ ArrayList appTrusts = new ArrayList();
+ if (m_storeBounded) {
+ RefreshStorePointer();
+ // enumerate the user store and populate the collection
+ StoreDeploymentMetadataEnumeration deplEnum = m_pStore.EnumInstallerDeployments(IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING, InstallerIdentifier, ApplicationTrustProperty, null);
+ foreach (IDefinitionAppId defAppId in deplEnum) {
+ StoreDeploymentMetadataPropertyEnumeration metadataEnum = m_pStore.EnumInstallerDeploymentProperties(IsolationInterop.GUID_SXS_INSTALL_REFERENCE_SCHEME_OPAQUESTRING, InstallerIdentifier, ApplicationTrustProperty, defAppId);
+ foreach (StoreOperationMetadataProperty appTrustProperty in metadataEnum) {
+ string appTrustXml = appTrustProperty.Value;
+ if (appTrustXml != null && appTrustXml.Length > 0) {
+ SecurityElement seTrust = SecurityElement.FromString(appTrustXml);
+ ApplicationTrust appTrust = new ApplicationTrust();
+ appTrust.FromXml(seTrust);
+ appTrusts.Add(appTrust);
+ }
+ }
+ }
+ }
+ Interlocked.CompareExchange(ref m_appTrusts, appTrusts, null);
+ }
+ return m_appTrusts as ArrayList;
+ }
+ }
+
+ private bool m_storeBounded = false;
+ private Store m_pStore = null; // Component store interface pointer.
+
+ // Only internal constructors are exposed.
+ [System.Security.SecurityCritical] // auto-generated
+ internal ApplicationTrustCollection () : this(false) {}
+ internal ApplicationTrustCollection (bool storeBounded) {
+ m_storeBounded = storeBounded;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void RefreshStorePointer () {
+ // Refresh store pointer.
+ if (m_pStore != null)
+ Marshal.ReleaseComObject(m_pStore.InternalStore);
+ m_pStore = IsolationInterop.GetUserStore();
+ }
+
+ public int Count
+ {
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ get {
+ return AppTrusts.Count;
+ }
+ }
+
+ public ApplicationTrust this[int index] {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ return AppTrusts[index] as ApplicationTrust;
+ }
+ }
+
+ public ApplicationTrust this[string appFullName] {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ ApplicationIdentity identity = new ApplicationIdentity(appFullName);
+ ApplicationTrustCollection appTrusts = Find(identity, ApplicationVersionMatch.MatchExactVersion);
+ if (appTrusts.Count > 0)
+ return appTrusts[0];
+ return null;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void CommitApplicationTrust(ApplicationIdentity applicationIdentity, string trustXml) {
+ StoreOperationMetadataProperty[] properties = new StoreOperationMetadataProperty[] {
+ new StoreOperationMetadataProperty(ClrPropertySet, ApplicationTrustProperty, trustXml)
+ };
+
+ IEnumDefinitionIdentity idenum = applicationIdentity.Identity.EnumAppPath();
+ IDefinitionIdentity[] asbId = new IDefinitionIdentity[1];
+ IDefinitionIdentity deplId = null;
+ if (idenum.Next(1, asbId) == 1)
+ deplId = asbId[0];
+
+ IDefinitionAppId defAppId = IsolationInterop.AppIdAuthority.CreateDefinition();
+ defAppId.SetAppPath(1, new IDefinitionIdentity[] {deplId});
+ defAppId.put_Codebase(applicationIdentity.CodeBase);
+
+ using (StoreTransaction storeTxn = new StoreTransaction()) {
+ storeTxn.Add(new StoreOperationSetDeploymentMetadata(defAppId, InstallReference, properties));
+ RefreshStorePointer();
+ m_pStore.Transact(storeTxn.Operations);
+ }
+
+ m_appTrusts = null; // reset the app trusts in the collection.
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public int Add (ApplicationTrust trust) {
+ if (trust == null)
+ throw new ArgumentNullException("trust");
+ if (trust.ApplicationIdentity == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ApplicationTrustShouldHaveIdentity"));
+ Contract.EndContractBlock();
+
+ // Add the trust decision of the application to the fusion store.
+ if (m_storeBounded) {
+ CommitApplicationTrust(trust.ApplicationIdentity, trust.ToXml().ToString());
+ return -1;
+ } else {
+ return AppTrusts.Add(trust);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddRange (ApplicationTrust[] trusts) {
+ if (trusts == null)
+ throw new ArgumentNullException("trusts");
+ Contract.EndContractBlock();
+
+ int i=0;
+ try {
+ for (; i<trusts.Length; i++) {
+ Add(trusts[i]);
+ }
+ } catch {
+ for (int j=0; j<i; j++) {
+ Remove(trusts[j]);
+ }
+ throw;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddRange (ApplicationTrustCollection trusts) {
+ if (trusts == null)
+ throw new ArgumentNullException("trusts");
+ Contract.EndContractBlock();
+
+ int i = 0;
+ try {
+ foreach (ApplicationTrust trust in trusts) {
+ Add(trust);
+ i++;
+ }
+ } catch {
+ for (int j=0; j<i; j++) {
+ Remove(trusts[j]);
+ }
+ throw;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public ApplicationTrustCollection Find (ApplicationIdentity applicationIdentity, ApplicationVersionMatch versionMatch) {
+ ApplicationTrustCollection collection = new ApplicationTrustCollection(false);
+ foreach (ApplicationTrust trust in this) {
+ if (CmsUtils.CompareIdentities(trust.ApplicationIdentity, applicationIdentity, versionMatch))
+ collection.Add(trust);
+ }
+ return collection;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void Remove (ApplicationIdentity applicationIdentity, ApplicationVersionMatch versionMatch) {
+ ApplicationTrustCollection collection = Find(applicationIdentity, versionMatch);
+ RemoveRange(collection);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void Remove (ApplicationTrust trust) {
+ if (trust == null)
+ throw new ArgumentNullException("trust");
+ if (trust.ApplicationIdentity == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ApplicationTrustShouldHaveIdentity"));
+ Contract.EndContractBlock();
+
+ // Remove the trust decision of the application from the fusion store.
+ if (m_storeBounded) {
+ CommitApplicationTrust(trust.ApplicationIdentity, null);
+ } else {
+ AppTrusts.Remove(trust);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void RemoveRange (ApplicationTrust[] trusts) {
+ if (trusts == null)
+ throw new ArgumentNullException("trusts");
+ Contract.EndContractBlock();
+
+ int i=0;
+ try {
+ for (; i<trusts.Length; i++) {
+ Remove(trusts[i]);
+ }
+ } catch {
+ for (int j=0; j<i; j++) {
+ Add(trusts[j]);
+ }
+ throw;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void RemoveRange (ApplicationTrustCollection trusts) {
+ if (trusts == null)
+ throw new ArgumentNullException("trusts");
+ Contract.EndContractBlock();
+
+ int i = 0;
+ try {
+ foreach (ApplicationTrust trust in trusts) {
+ Remove(trust);
+ i++;
+ }
+ } catch {
+ for (int j=0; j<i; j++) {
+ Add(trusts[j]);
+ }
+ throw;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void Clear() {
+ // remove all trust decisions in the collection.
+ ArrayList trusts = this.AppTrusts;
+ if (m_storeBounded) {
+ foreach (ApplicationTrust trust in trusts) {
+ if (trust.ApplicationIdentity == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ApplicationTrustShouldHaveIdentity"));
+
+ // Remove the trust decision of the application from the fusion store.
+ CommitApplicationTrust(trust.ApplicationIdentity, null);
+ }
+ }
+ trusts.Clear();
+ }
+
+ public ApplicationTrustEnumerator GetEnumerator() {
+ return new ApplicationTrustEnumerator(this);
+ }
+
+ /// <internalonly/>
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return new ApplicationTrustEnumerator(this);
+ }
+
+ /// <internalonly/>
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ void ICollection.CopyTo(Array array, int index) {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (array.Rank != 1)
+ throw new ArgumentException(Environment.GetResourceString("Arg_RankMultiDimNotSupported"));
+ if (index < 0 || index >= array.Length)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (array.Length - index < this.Count)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen"));
+ Contract.EndContractBlock();
+
+ for (int i=0; i < this.Count; i++) {
+ array.SetValue(this[i], index++);
+ }
+ }
+
+ public void CopyTo (ApplicationTrust[] array, int index) {
+ ((ICollection)this).CopyTo(array, index);
+ }
+
+ public bool IsSynchronized {
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ get
+ {
+ return false;
+ }
+ }
+
+ public object SyncRoot {
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ get
+ {
+ return this;
+ }
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ApplicationTrustEnumerator : IEnumerator {
+ [System.Security.SecurityCritical] // auto-generated
+ private ApplicationTrustCollection m_trusts;
+ private int m_current;
+
+ private ApplicationTrustEnumerator() {}
+ [System.Security.SecurityCritical] // auto-generated
+ internal ApplicationTrustEnumerator(ApplicationTrustCollection trusts) {
+ m_trusts = trusts;
+ m_current = -1;
+ }
+
+ public ApplicationTrust Current {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return m_trusts[m_current];
+ }
+ }
+
+ /// <internalonly/>
+ object IEnumerator.Current {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return (object) m_trusts[m_current];
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool MoveNext() {
+ if (m_current == ((int) m_trusts.Count - 1))
+ return false;
+ m_current++;
+ return true;
+ }
+
+ public void Reset() {
+ m_current = -1;
+ }
+ }
+#endif // FEATURE_CLICKONCE
+}
diff --git a/src/mscorlib/src/System/Security/Policy/Evidence.cs b/src/mscorlib/src/System/Security/Policy/Evidence.cs
new file mode 100644
index 0000000000..8bf8aa7e92
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/Evidence.cs
@@ -0,0 +1,1903 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security.Policy
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Configuration.Assemblies;
+ using System.Diagnostics.Contracts;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization;
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using System.Security.Permissions;
+ using System.Security.Util;
+ using System.Threading;
+ using Microsoft.Win32.SafeHandles;
+
+ /// <summary>
+ /// The Evidence class keeps track of information that can be used to make security decisions about
+ /// an assembly or an AppDomain. There are two types of evidence, one is supplied by the CLR or a
+ /// host, the other supplied by the assembly itself.
+ ///
+ /// We keep a dictionary that maps each type of possbile evidence to an EvidenceTypeDescriptor which
+ /// contains the evidence objects themselves if they exist as well as some extra metadata about that
+ /// type of evidence. This dictionary is fully populated with keys for host evidence at all times and
+ /// for assembly evidence the first time the application evidence is touched. This means that if a
+ /// Type key does not exist in the dictionary, then that particular type of evidence will never be
+ /// given to the assembly or AppDomain in question as host evidence. The only exception is if the
+ /// user later manually adds host evidence via the AddHostEvidence API.
+ ///
+ /// Assembly supplied evidence is created up front, however host supplied evidence may be lazily
+ /// created. In the lazy creation case, the Type will map to either an EvidenceTypeDescriptor that does
+ /// not contain any evidence data or null. As requests come in for that evidence, we'll populate the
+ /// EvidenceTypeDescriptor appropriately.
+ /// </summary>
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ [ComVisible(true)]
+ public sealed class Evidence
+#if FEATURE_CAS_POLICY
+ : ICollection
+#endif // FEATURE_CAS_POLICY
+ {
+#if !FEATURE_CORECLR && FEATURE_RWLOCK
+#if FEATURE_SERIALIZATION
+ [OptionalField(VersionAdded = 4)]
+ private Dictionary<Type, EvidenceTypeDescriptor> m_evidence;
+
+ [OptionalField(VersionAdded = 4)]
+ private bool m_deserializedTargetEvidence;
+
+ // These fields are only used to deserialize v2.0 serialized versions of Evidence. It will be null
+ // after the seriailzation process is complete, and should not be used.
+#pragma warning disable 414
+ private volatile ArrayList m_hostList;
+ private volatile ArrayList m_assemblyList;
+#pragma warning restore 414
+#else // !FEATURE_SERIALIZATION
+ private Dictionary<Type, EvidenceTypeDescriptor> m_evidence;
+#endif // FEATURE_SERIALIZATION
+
+ [NonSerialized]
+ private ReaderWriterLock m_evidenceLock;
+
+ [NonSerialized]
+ private uint m_version;
+
+ [NonSerialized]
+ private IRuntimeEvidenceFactory m_target;
+
+ private bool m_locked;
+
+ // If this evidence collection is a clone where we may need to backpatch to the original, this will
+ // reference the collection it was cloned from. See
+ // code:System.Security.Policy.Evidence#BackpatchGeneratedEvidence
+ [NonSerialized]
+ private WeakReference m_cloneOrigin;
+
+ private static volatile Type[] s_runtimeEvidenceTypes;
+
+ /// <summary>
+ /// Set of actions that we could perform if we detect that we are attempting to add evidence
+ /// when we already have evidence of that type stored.
+ /// </summary>
+ private enum DuplicateEvidenceAction
+ {
+ Throw, // Throw an exception
+ Merge, // Create a list of all the evidence objects
+ SelectNewObject // The newly added object wins
+ }
+
+#if FEATURE_CAS_POLICY
+ public Evidence()
+ {
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+ m_evidenceLock = new ReaderWriterLock();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <summary>
+ /// Create a deep copy of an evidence object
+ /// </summary>
+ public Evidence(Evidence evidence)
+ {
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+
+ if (evidence != null)
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(evidence, EvidenceLockHolder.LockType.Reader))
+ {
+ foreach (KeyValuePair<Type, EvidenceTypeDescriptor> evidenceType in evidence.m_evidence)
+ {
+ EvidenceTypeDescriptor cloneDescriptor = evidenceType.Value;
+ if (cloneDescriptor != null)
+ {
+ cloneDescriptor = cloneDescriptor.Clone();
+ }
+
+ m_evidence[evidenceType.Key] = cloneDescriptor;
+ }
+
+ m_target = evidence.m_target;
+ m_locked = evidence.m_locked;
+#if FEATURE_SERIALIZATION
+ m_deserializedTargetEvidence = evidence.m_deserializedTargetEvidence;
+#endif // FEATURE_SERIALIZATION
+
+ // see code:System.Security.Policy.Evidence#BackpatchGeneratedEvidence
+ if (evidence.Target != null)
+ {
+ m_cloneOrigin = new WeakReference(evidence);
+ }
+ }
+ }
+
+ // see code:System.Security.Policy.Evidence#EvidenceLock
+ m_evidenceLock = new ReaderWriterLock();
+ }
+
+ [Obsolete("This constructor is obsolete. Please use the constructor which takes arrays of EvidenceBase instead.")]
+ public Evidence(object[] hostEvidence, object[] assemblyEvidence)
+ {
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+
+ // This is a legacy evidence entry point, so we add through the legacy add APIs in order to get
+ // proper legacy wrapping and merge behavior.
+#pragma warning disable 618
+ if (hostEvidence != null)
+ {
+ foreach (object hostEvidenceObject in hostEvidence)
+ {
+ AddHost(hostEvidenceObject);
+ }
+ }
+
+ if (assemblyEvidence != null)
+ {
+ foreach (object assemblyEvidenceObject in assemblyEvidence)
+ {
+ AddAssembly(assemblyEvidenceObject);
+ }
+ }
+#pragma warning restore 618
+
+ // see code:System.Security.Policy.Evidence#EvidenceLock
+ m_evidenceLock = new ReaderWriterLock();
+ }
+
+ public Evidence(EvidenceBase[] hostEvidence, EvidenceBase[] assemblyEvidence)
+ {
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+
+ if (hostEvidence != null)
+ {
+ foreach (EvidenceBase hostEvidenceObject in hostEvidence)
+ {
+ AddHostEvidence(hostEvidenceObject, GetEvidenceIndexType(hostEvidenceObject), DuplicateEvidenceAction.Throw);
+ }
+ }
+
+ if (assemblyEvidence != null)
+ {
+ foreach (EvidenceBase assemblyEvidenceObject in assemblyEvidence)
+ {
+ AddAssemblyEvidence(assemblyEvidenceObject, GetEvidenceIndexType(assemblyEvidenceObject), DuplicateEvidenceAction.Throw);
+ }
+ }
+
+ // see code:System.Security.Policy.Evidence#EvidenceLock
+ m_evidenceLock = new ReaderWriterLock();
+ }
+
+ /// <summary>
+ /// Create an empty evidence collection which will contain evidence for a specific assembly or
+ /// AppDomain
+ /// </summary>
+ [SecuritySafeCritical]
+ internal Evidence(IRuntimeEvidenceFactory target)
+ {
+ Contract.Assert(target != null);
+
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+ m_target = target;
+
+ // Setup the types of evidence that the CLR can generate for a target as keys in the dictionary
+ foreach (Type runtimeEvidenceType in RuntimeEvidenceTypes)
+ {
+ BCLDebug.Assert(typeof(EvidenceBase).IsAssignableFrom(runtimeEvidenceType), "All runtime evidence types should be EvidenceBases");
+ m_evidence[runtimeEvidenceType] = null;
+ }
+
+ QueryHostForPossibleEvidenceTypes();
+
+ // see code:System.Security.Policy.Evidence#EvidenceLock
+ m_evidenceLock = new ReaderWriterLock();
+ }
+
+ internal static Type[] RuntimeEvidenceTypes
+ {
+ get
+ {
+ if (s_runtimeEvidenceTypes == null)
+ {
+ Type[] runtimeEvidenceTypes = new Type[]
+ {
+#if FEATURE_CLICKONCE
+ typeof(System.Runtime.Hosting.ActivationArguments),
+#endif // FEATURE_CLICKONCE
+#if FEATURE_CAS_POLICY
+ typeof(ApplicationDirectory),
+#endif // FEATURE_CAS_POLICY
+ typeof(ApplicationTrust),
+#if FEATURE_CAS_POLICY
+ typeof(GacInstalled),
+ typeof(Hash),
+ typeof(Publisher),
+#endif // FEATURE_CAS_POLICY
+ typeof(Site),
+ typeof(StrongName),
+ typeof(Url),
+ typeof(Zone)
+ };
+
+#if FEATURE_CAS_POLICY
+ // We only supply permission request evidence in legacy CAS mode
+ if (AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+#pragma warning disable 618 // We need to generate PermissionRequestEvidence in compatibility mode
+ int l = runtimeEvidenceTypes.Length;
+ Array.Resize(ref runtimeEvidenceTypes, l+1);
+ runtimeEvidenceTypes[l] = typeof(PermissionRequestEvidence);
+#pragma warning restore 618
+ }
+#endif // FEATURE_CAS_POLICY
+
+ s_runtimeEvidenceTypes = runtimeEvidenceTypes;
+ }
+
+ return s_runtimeEvidenceTypes;
+ }
+ }
+
+ //
+ // #EvidenceLock
+ //
+ // Evidence synchronization locking wrappers. In the case where the lock has not yet been created,
+ // we know that we're in the process of constructing the evidence collection and therefore we can
+ // act as though the evidence is locked. If there is a lock in place, then just delegate back to it.
+ //
+ // The nested EvidenceLockHolder and EvidenceUpgradeLockHolder utility classes can be used to wrap
+ // these methods when acquiring and releasing the evidence lock.
+ //
+
+ // Millisecond timeout when waiting to acquire the evidence lock
+ private const int LockTimeout = 5000;
+
+ private bool IsReaderLockHeld
+ {
+ get { return m_evidenceLock == null || m_evidenceLock.IsReaderLockHeld; }
+ }
+
+ private bool IsWriterLockHeld
+ {
+ get { return m_evidenceLock == null || m_evidenceLock.IsWriterLockHeld; }
+ }
+
+ private void AcquireReaderLock()
+ {
+ Contract.Assert(m_evidenceLock == null || !IsReaderLockHeld);
+
+ if (m_evidenceLock != null)
+ {
+ m_evidenceLock.AcquireReaderLock(LockTimeout);
+ }
+ }
+
+ private void AcquireWriterlock()
+ {
+ Contract.Assert(m_evidenceLock == null || !IsWriterLockHeld);
+
+ if (m_evidenceLock != null)
+ {
+ m_evidenceLock.AcquireWriterLock(LockTimeout);
+ }
+ }
+
+ private void DowngradeFromWriterLock(ref LockCookie lockCookie)
+ {
+ Contract.Assert(IsWriterLockHeld);
+ if (m_evidenceLock != null)
+ {
+ m_evidenceLock.DowngradeFromWriterLock(ref lockCookie);
+ }
+ }
+
+ private LockCookie UpgradeToWriterLock()
+ {
+ Contract.Assert(IsReaderLockHeld);
+ return m_evidenceLock != null ? m_evidenceLock.UpgradeToWriterLock(LockTimeout) : new LockCookie();
+ }
+
+ private void ReleaseReaderLock()
+ {
+ Contract.Assert(IsReaderLockHeld);
+
+ if (m_evidenceLock != null)
+ {
+ m_evidenceLock.ReleaseReaderLock();
+ }
+ }
+
+ private void ReleaseWriterLock()
+ {
+ Contract.Assert(IsWriterLockHeld);
+
+ if (m_evidenceLock != null)
+ {
+ m_evidenceLock.ReleaseWriterLock();
+ }
+ }
+
+ [Obsolete("This method is obsolete. Please use AddHostEvidence instead.")]
+ [SecuritySafeCritical]
+ public void AddHost(object id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+ if (!id.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Policy_EvidenceMustBeSerializable"), "id");
+ Contract.EndContractBlock();
+
+ if (m_locked)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ }
+
+ EvidenceBase evidence = WrapLegacyEvidence(id);
+ Type evidenceIndex = GetEvidenceIndexType(evidence);
+
+ // Whidbey allowed for multiple types of the same evidence, so if we're being called via the Whidbey
+ // APIs, then allow the evidences to merge together.
+ AddHostEvidence(evidence, evidenceIndex, DuplicateEvidenceAction.Merge);
+ }
+
+ [Obsolete("This method is obsolete. Please use AddAssemblyEvidence instead.")]
+ public void AddAssembly(object id)
+ {
+ if (id == null)
+ throw new ArgumentNullException("id");
+ if (!id.GetType().IsSerializable)
+ throw new ArgumentException(Environment.GetResourceString("Policy_EvidenceMustBeSerializable"), "id");
+ Contract.EndContractBlock();
+
+ EvidenceBase evidence = WrapLegacyEvidence(id);
+ Type evidenceIndex = GetEvidenceIndexType(evidence);
+
+ // Whidbey allowed for multiple types of the same evidence, so if we're being called via the Whidbey
+ // APIs, then allow the evidences to merge together.
+ AddAssemblyEvidence(evidence, evidenceIndex, DuplicateEvidenceAction.Merge);
+ }
+
+ /// <summary>
+ /// Add a piece of evidence to the assembly supplied evidence list. This method will disallow adding
+ /// evidence if there is already evidence of that type in the assembly list.
+ /// </summary>
+ [ComVisible(false)]
+ public void AddAssemblyEvidence<T>(T evidence) where T : EvidenceBase
+ {
+ if (evidence == null)
+ throw new ArgumentNullException("evidence");
+ Contract.EndContractBlock();
+
+ // Index the evidence under the type that the Add function was called with, unless we were given
+ // a plain EvidenceBase or a wrapped legacy evidence. In that case, we need to index under a
+ // more specific type.
+ Type evidenceType = typeof(T);
+ if (typeof(T) == typeof(EvidenceBase) || evidence is ILegacyEvidenceAdapter)
+ {
+ evidenceType = GetEvidenceIndexType(evidence);
+ }
+
+ AddAssemblyEvidence(evidence, evidenceType, DuplicateEvidenceAction.Throw);
+ }
+
+ private void AddAssemblyEvidence(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction)
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ AddAssemblyEvidenceNoLock(evidence, evidenceType, duplicateAction);
+ }
+ }
+
+ private void AddAssemblyEvidenceNoLock(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction)
+ {
+ Contract.Assert(IsWriterLockHeld);
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidenceType != null);
+
+ // We need to make sure that any target supplied evidence is deserialized before adding to the
+ // Assembly collection in order to preserve the semantics that the evidence objects supplied by
+ // the target are the original versions and evidence objects added via the APIs are the duplicates.
+ DeserializeTargetEvidence();
+
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType, true);
+
+ ++m_version;
+ if (descriptor.AssemblyEvidence == null)
+ {
+ descriptor.AssemblyEvidence = evidence;
+ }
+ else
+ {
+ descriptor.AssemblyEvidence = HandleDuplicateEvidence(descriptor.AssemblyEvidence,
+ evidence,
+ duplicateAction);
+ }
+ }
+
+ /// <summary>
+ /// Add a piece of evidence to the host supplied evidence list. This method will disallow adding
+ /// evidence if there is already evidence of that type in the host list.
+ /// </summary>
+ [ComVisible(false)]
+ public void AddHostEvidence<T>(T evidence) where T : EvidenceBase
+ {
+ if (evidence == null)
+ throw new ArgumentNullException("evidence");
+ Contract.EndContractBlock();
+
+ // Index the evidence under the type that the Add function was called with, unless we were given
+ // a plain EvidenceBase or a wrapped legacy evidence. In that case, we need to index under a
+ // more specific type.
+ Type evidenceType = typeof(T);
+ if (typeof(T) == typeof(EvidenceBase) || evidence is ILegacyEvidenceAdapter)
+ {
+ evidenceType = GetEvidenceIndexType(evidence);
+ }
+
+ AddHostEvidence(evidence, evidenceType, DuplicateEvidenceAction.Throw);
+ }
+
+ [SecuritySafeCritical]
+ private void AddHostEvidence(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidenceType != null);
+
+ if (Locked)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ }
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ AddHostEvidenceNoLock(evidence, evidenceType, duplicateAction);
+ }
+ }
+
+ /// <summary>
+ /// Add evidence to the host supplied evidence collection without acquiring the evidence lock or
+ /// checking to make sure that the caller has permission to bypass locked evidence.
+ /// </summary>
+ private void AddHostEvidenceNoLock(EvidenceBase evidence, Type evidenceType, DuplicateEvidenceAction duplicateAction)
+ {
+ Contract.Assert(IsWriterLockHeld);
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidenceType != null);
+
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType, true);
+
+ ++m_version;
+ if (descriptor.HostEvidence == null)
+ {
+ descriptor.HostEvidence = evidence;
+ }
+ else
+ {
+ descriptor.HostEvidence = HandleDuplicateEvidence(descriptor.HostEvidence,
+ evidence,
+ duplicateAction);
+ }
+ }
+
+ /// <summary>
+ /// Ask the host for the types of evidence that it might provide if it is asked.
+ ///
+ /// This should only be called when setting up the Evidence collection to interact with the
+ /// host, and should not be used once that connection is established and the evidence has been
+ /// made available to user code.
+ /// </summary>
+ [SecurityCritical]
+ private void QueryHostForPossibleEvidenceTypes()
+ {
+#if FEATURE_CAS_POLICY
+ Contract.Assert(IsWriterLockHeld);
+
+ // First check to see if we have a HostSecurityManager
+ if (AppDomain.CurrentDomain.DomainManager != null)
+ {
+ HostSecurityManager hsm = AppDomain.CurrentDomain.DomainManager.HostSecurityManager;
+ if (hsm != null)
+ {
+ Type[] hostSuppliedTypes = null;
+
+ AppDomain targetDomain = m_target.Target as AppDomain;
+ Assembly targetAssembly = m_target.Target as Assembly;
+
+ //
+ // If the HostSecurityManager wants to supply evidence for the type of target that we have,
+ // then ask it what types of evidence it might supply.
+ //
+
+ if (targetAssembly != null &&
+ (hsm.Flags & HostSecurityManagerOptions.HostAssemblyEvidence) == HostSecurityManagerOptions.HostAssemblyEvidence)
+ {
+ hostSuppliedTypes = hsm.GetHostSuppliedAssemblyEvidenceTypes(targetAssembly);
+ }
+ else if (targetDomain != null &&
+ (hsm.Flags & HostSecurityManagerOptions.HostAppDomainEvidence) == HostSecurityManagerOptions.HostAppDomainEvidence)
+ {
+ hostSuppliedTypes = hsm.GetHostSuppliedAppDomainEvidenceTypes();
+ }
+
+ //
+ // Finally, mark the descriptor for each of the types that the host can supply to indicate
+ // we should ask the host to generate them if we're asked.
+ //
+
+ if (hostSuppliedTypes != null)
+ {
+ foreach (Type hostEvidenceType in hostSuppliedTypes)
+ {
+ EvidenceTypeDescriptor evidenceDescriptor = GetEvidenceTypeDescriptor(hostEvidenceType, true);
+ evidenceDescriptor.HostCanGenerate = true;
+ }
+ }
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ internal bool IsUnmodified
+ {
+ get { return m_version == 0; }
+ }
+
+ /// <summary>
+ /// Set or check to see if the evidence is locked. Locked evidence cannot have its host supplied
+ /// evidence list be modified without a successful demand for ControlEvidence. Any code can lock
+ /// evidence, but only code with ControlEvidence may unlock it.
+ ///
+ /// This lock is not the same as the synchronization lock that gates access to the evidence collection.
+ /// </summary>
+ public bool Locked
+ {
+ get
+ {
+ return m_locked;
+ }
+
+ [SecuritySafeCritical]
+ set
+ {
+ if (!value)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+
+ m_locked = false;
+ }
+ else
+ {
+ m_locked = true;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Target of any delay generated evidence objects
+ /// </summary>
+ internal IRuntimeEvidenceFactory Target
+ {
+ get { return m_target; }
+
+ //
+ // There are two retargeting scenarios supported:
+ //
+ // 1. A PEFileEvidenceFactory is being upgraded to an AssemblyEvidenceFactory and we don't want
+ // to throw away any already generated evidence.
+ // 2. A detached evidence collection is being applied to an AppDomain and that domain has a
+ // HostSecurityManager. In that case, we want to attach the target to the AppDomain to
+ // allow the HostSecurityManager to get callbacks for delay generated evidence.
+ //
+
+ [SecurityCritical]
+ set
+ {
+#if FEATURE_CAS_POLICY
+ Contract.Assert((m_target != null && m_target is PEFileEvidenceFactory && value != null && value is AssemblyEvidenceFactory) ||
+ (m_target == null && value != null && value is AppDomainEvidenceFactory),
+ "Evidence retargeting should only be from PEFile -> Assembly or detached -> AppDomain.");
+#endif // FEATURE_CAS_POLICY
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ m_target = value;
+
+ // Since we've updated what we're pointing at, we need to query the host to determine what
+ // types of evidence that it can generate for this new target.
+ QueryHostForPossibleEvidenceTypes();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the type that would be used to index into the evidence dictionary for this object
+ /// </summary>
+ private static Type GetEvidenceIndexType(EvidenceBase evidence)
+ {
+ Contract.Assert(evidence != null);
+
+ //
+ // Legacy wrapper evidence types should be indexed via the type of evidence that they're wrapping
+ // so check to see if we have one of those; otherwise just return the type itself.
+ //
+
+ ILegacyEvidenceAdapter adapter = evidence as ILegacyEvidenceAdapter;
+ return adapter == null ? evidence.GetType() : adapter.EvidenceType;
+ }
+
+ /// <summary>
+ /// Get the type descriptor for a specific type of evidence. This method should be used instead
+ /// of accessing the dictionary directly as it will handle the case where a new descriptor needs
+ /// to be created.
+ /// </summary>
+ internal EvidenceTypeDescriptor GetEvidenceTypeDescriptor(Type evidenceType)
+ {
+ return GetEvidenceTypeDescriptor(evidenceType, false);
+ }
+
+ /// <summary>
+ /// Get the type descriptor for a specific type of evidence, optionally creating a descriptor if
+ /// we did not yet know about this type of evidence. This method should be used instead of
+ /// accessing the dictionary directly as it will handle the case where a new descriptor needs
+ /// to be created.
+ /// </summary>
+ private EvidenceTypeDescriptor GetEvidenceTypeDescriptor(Type evidenceType, bool addIfNotExist)
+ {
+ Contract.Assert(IsReaderLockHeld || IsWriterLockHeld);
+ Contract.Assert(evidenceType != null);
+
+ // If we don't know about the type being indexed and we don't want to add it then exit out
+ EvidenceTypeDescriptor descriptor = null;
+ if (!m_evidence.TryGetValue(evidenceType, out descriptor) && !addIfNotExist)
+ {
+ return null;
+ }
+
+ // If we haven't yet created a descriptor for this type then create one now
+ if (descriptor == null)
+ {
+ descriptor = new EvidenceTypeDescriptor();
+#if _DEBUG
+ descriptor.SetEvidenceType(evidenceType);
+#endif // _DEBUG
+
+ bool upgradedLock = false;
+ LockCookie upgradeCookie = new LockCookie();
+ try
+ {
+ if (!IsWriterLockHeld)
+ {
+ upgradeCookie = UpgradeToWriterLock();
+ upgradedLock = true;
+ }
+
+ m_evidence[evidenceType] = descriptor;
+ }
+ finally
+ {
+ if (upgradedLock)
+ DowngradeFromWriterLock(ref upgradeCookie);
+ }
+ }
+
+ return descriptor;
+ }
+
+ /// <summary>
+ /// This method is called if a piece of evidence is added but another piece of evidence of the same
+ /// type already existed. We have different strategies depending on compatibility concerns of the
+ /// calling code.
+ /// </summary>
+ private static EvidenceBase HandleDuplicateEvidence(EvidenceBase original,
+ EvidenceBase duplicate,
+ DuplicateEvidenceAction action)
+ {
+ Contract.Assert(original != null);
+ Contract.Assert(duplicate != null);
+ Contract.Assert(original.GetType() == duplicate.GetType() || original.GetType() == typeof(LegacyEvidenceList));
+
+ switch (action)
+ {
+ // Throw - duplicate evidence is not allowed (Arrowhead behavior), so throw an exception
+ case DuplicateEvidenceAction.Throw:
+ throw new InvalidOperationException(Environment.GetResourceString("Policy_DuplicateEvidence", duplicate.GetType().FullName));
+
+ // SelectNewObject - MergeWithNoDuplicates behavior - the duplicate object wins
+ case DuplicateEvidenceAction.SelectNewObject:
+ return duplicate;
+
+ // Merge - compat behavior. Merge the old and new evidence into a list so that both may exist
+ case DuplicateEvidenceAction.Merge:
+
+ LegacyEvidenceList list = original as LegacyEvidenceList;
+ if (list == null)
+ {
+ list = new LegacyEvidenceList();
+ list.Add(original);
+ }
+
+ list.Add(duplicate);
+ return list;
+
+ default:
+ BCLDebug.Assert(false, "Uknown DuplicateEvidenceAction");
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Wrap evidence we recieved through a legacy API to ensure that it is stored in an EvidenceBase
+ /// </summary>
+ private static EvidenceBase WrapLegacyEvidence(object evidence)
+ {
+ Contract.Assert(evidence != null);
+
+ EvidenceBase wrappedEvidence = evidence as EvidenceBase;
+ if (wrappedEvidence == null)
+ {
+ wrappedEvidence = new LegacyEvidenceWrapper(evidence);
+ }
+
+ return wrappedEvidence;
+ }
+
+ /// <summary>
+ /// Upwrap evidence stored in a legacy adapter.
+ ///
+ /// This is only necessary for the case where multiple objects derived from EvidenceBase is
+ /// are added via the legacy APIs and are then retrieved via GetHostEvidence. This may occur if
+ /// a legacy application adds CLR supplied evidence types via the old APIs and a new application
+ /// consumes the resulting evidence.
+ /// </summary>
+ private static object UnwrapEvidence(EvidenceBase evidence)
+ {
+ ILegacyEvidenceAdapter adapter = evidence as ILegacyEvidenceAdapter;
+ return adapter == null ? evidence : adapter.EvidenceObject;
+ }
+
+ /// <summary>
+ /// Merge two evidence collections together. Note that this will cause all of the lazily
+ /// generated evidence for the input collection to be generated, as well as causing any lazily
+ /// generated evidence that both collections share to be generated in the target.
+ /// </summary>
+ [SecuritySafeCritical]
+ public void Merge(Evidence evidence)
+ {
+ if (evidence == null)
+ {
+ return;
+ }
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ bool checkedLock = false;
+ IEnumerator hostEnumerator = evidence.GetHostEnumerator();
+ while (hostEnumerator.MoveNext())
+ {
+ if (Locked && !checkedLock)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ checkedLock = true;
+ }
+
+ // If we could potentially have evidence of the type about to be merged into our host list,
+ // then make sure that we generate that evidence before merging. This will prevent the
+ // newly merged evidence from masking the value that we would have generated on our own.
+ Type hostEvidenceType = hostEnumerator.Current.GetType();
+ if (m_evidence.ContainsKey(hostEvidenceType))
+ {
+ GetHostEvidenceNoLock(hostEvidenceType);
+ }
+
+ EvidenceBase hostEvidence = WrapLegacyEvidence(hostEnumerator.Current);
+ AddHostEvidenceNoLock(hostEvidence,
+ GetEvidenceIndexType(hostEvidence),
+ DuplicateEvidenceAction.Merge);
+ }
+
+ // Add each piece of assembly evidence. We don't need to deserialize our copy of the
+ // evidence because AddAssemblyEvidenceNoLock will do this for us.
+ IEnumerator assemblyEnumerator = evidence.GetAssemblyEnumerator();
+ while (assemblyEnumerator.MoveNext())
+ {
+ EvidenceBase assemblyEvidence = WrapLegacyEvidence(assemblyEnumerator.Current);
+ AddAssemblyEvidenceNoLock(assemblyEvidence,
+ GetEvidenceIndexType(assemblyEvidence),
+ DuplicateEvidenceAction.Merge);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Same as merge, except only one instance of any one evidence type is allowed. When duplicates
+ /// are found, the evidence in the input argument will have priority. Note this will force the
+ /// entire input evidence to be generated, and does not check for locked evidence
+ /// </summary>
+ internal void MergeWithNoDuplicates(Evidence evidence)
+ {
+ if (evidence == null)
+ {
+ return;
+ }
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ IEnumerator hostEnumerator = evidence.GetHostEnumerator();
+ while (hostEnumerator.MoveNext())
+ {
+ EvidenceBase hostEvidence = WrapLegacyEvidence(hostEnumerator.Current);
+ AddHostEvidenceNoLock(hostEvidence,
+ GetEvidenceIndexType(hostEvidence),
+ DuplicateEvidenceAction.SelectNewObject);
+ }
+
+ IEnumerator assemblyEnumerator = evidence.GetAssemblyEnumerator();
+ while (assemblyEnumerator.MoveNext())
+ {
+ EvidenceBase assemblyEvidence = WrapLegacyEvidence(assemblyEnumerator.Current);
+ AddAssemblyEvidenceNoLock(assemblyEvidence,
+ GetEvidenceIndexType(assemblyEvidence),
+ DuplicateEvidenceAction.SelectNewObject);
+ }
+ }
+ }
+
+#if FEATURE_SERIALIZATION
+ /// <summary>
+ /// Do a full serialization of the evidence, which requires that we generate all of the evidence
+ /// we can and disconnect ourselves from the host and source assembly.
+ /// </summary>
+ [ComVisible(false)]
+ [OnSerializing]
+ [SecurityCritical]
+ [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
+ private void OnSerializing(StreamingContext context)
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ // First, force all of the host evidence that might be lazily generated to be created
+ foreach (Type evidenceType in new List<Type>(m_evidence.Keys))
+ {
+ GetHostEvidenceNoLock(evidenceType);
+ }
+
+ // Also ensure that all serialized assembly evidence has been created
+ DeserializeTargetEvidence();
+ }
+
+ // Fill in legacy evidence lists. We can't guarantee thread-safety here using locks
+ // because we can't put a lock in the serialization code that will read the lists.
+ // The best we can do is prevent another thread from seeing a half-populated list.
+ // Therefore, we assign the lists after we've populated them fully (and declare them volatile.)
+ ArrayList hostList = new ArrayList();
+ IEnumerator hostEnumerator = GetHostEnumerator();
+ while (hostEnumerator.MoveNext())
+ {
+ hostList.Add(hostEnumerator.Current);
+ }
+ m_hostList = hostList;
+
+ ArrayList assemblyList = new ArrayList();
+ IEnumerator assemblyEnumerator = GetAssemblyEnumerator();
+ while (assemblyEnumerator.MoveNext())
+ {
+ assemblyList.Add(assemblyEnumerator.Current);
+ }
+ m_assemblyList = assemblyList;
+ }
+
+ /// <summary>
+ /// Finish deserializing legacy evidence
+ /// </summary>
+ [ComVisible(false)]
+ [OnDeserialized]
+ [SecurityCritical]
+ private void OnDeserialized(StreamingContext context)
+ {
+ // Look at host and assembly evidence lists only if we serialized using Whidbey.
+ if (m_evidence == null)
+ {
+ m_evidence = new Dictionary<Type, EvidenceTypeDescriptor>();
+
+ // Whidbey evidence may need to be wrapped or added to a LegacyEvidenceList, so we go
+ // through the legacy APIs to add them.
+#pragma warning disable 618
+ if (m_hostList != null)
+ {
+ foreach (object evidenceObject in m_hostList)
+ {
+ if (evidenceObject != null)
+ {
+ AddHost(evidenceObject);
+ }
+ }
+
+ m_hostList = null;
+ }
+
+ if (m_assemblyList != null)
+ {
+ foreach (object evidenceObject in m_assemblyList)
+ {
+ if (evidenceObject != null)
+ {
+ AddAssembly(evidenceObject);
+ }
+ }
+
+ m_assemblyList = null;
+ }
+#pragma warning restore 618
+ }
+
+ // see code:System.Security.Policy.Evidence#EvidenceLock
+ m_evidenceLock = new ReaderWriterLock();
+ }
+#endif // FEATURE_SERIALIZATION
+
+ /// <summary>
+ /// Load any serialized evidence out of the target assembly into our evidence collection.
+ ///
+ /// We allow entry to this method with only a reader lock held, since most of the time we will
+ /// not need to write to the evidence dictionary. If we haven't yet deserialized the target
+ /// evidence, then we will upgrade to a writer lock at that point.
+ /// </summary>
+ private void DeserializeTargetEvidence()
+ {
+#if FEATURE_SERIALIZATION
+ Contract.Assert(IsReaderLockHeld || IsWriterLockHeld);
+
+ if (m_target != null && !m_deserializedTargetEvidence)
+ {
+ bool upgradedLock = false;
+ LockCookie lockCookie = new LockCookie();
+ try
+ {
+ if (!IsWriterLockHeld)
+ {
+ lockCookie = UpgradeToWriterLock();
+ upgradedLock = true;
+ }
+
+ // Set this to true here because AddAssemblyEvidenceNoLock will attempt to reenter this
+ // method creating possible infinite recursion.
+ m_deserializedTargetEvidence = true;
+
+ foreach (EvidenceBase targetEvidence in m_target.GetFactorySuppliedEvidence())
+ {
+ AddAssemblyEvidenceNoLock(targetEvidence, GetEvidenceIndexType(targetEvidence), DuplicateEvidenceAction.Throw);
+ }
+ }
+ finally
+ {
+ if (upgradedLock)
+ DowngradeFromWriterLock(ref lockCookie);
+ }
+ }
+#endif // FEATURE_SERIALIZATION
+ }
+
+#if FEATURE_SERIALIZATION
+ /// <summary>
+ /// Serialize out raw evidence objects which have already been generated, ignoring any evidence
+ /// which might be present but has not yet been created for this assembly.
+ ///
+ /// This is used for indexing into the security policy cache, since we know that once policy is
+ /// resolved, the relevent membership conditions will have checked for any applicable evidence
+ /// and therefore after poliyc resolution this evidence collection will contain any evidence
+ /// objects necessary to arrive at its grant set.
+ /// </summary>
+ [SecurityCritical]
+ internal byte[] RawSerialize()
+ {
+ try
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ // Filter out any evidence which is not yet generated
+ Dictionary<Type, EvidenceBase> generatedEvidence = new Dictionary<Type, EvidenceBase>();
+ foreach (KeyValuePair<Type, EvidenceTypeDescriptor> evidenceType in m_evidence)
+ {
+ if (evidenceType.Value != null && evidenceType.Value.HostEvidence != null)
+ {
+ generatedEvidence[evidenceType.Key] = evidenceType.Value.HostEvidence;
+ }
+ }
+
+ using (MemoryStream serializationStream = new MemoryStream())
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(serializationStream, generatedEvidence);
+ return serializationStream.ToArray();
+ }
+ }
+ }
+ catch (SecurityException)
+ {
+ // We're running in a context where it's not safe to serialize the evidence out. In this case
+ // Simply decline to cache the result of the policy evaluation
+ return null;
+ }
+ }
+#endif // FEATURE_SERIALIZATION
+
+ //
+ // ICollection implementation. All ICollection interface members are potentially much more
+ // expensive in Arrowhead then they were downlevel. They should not be used if the standard Get and
+ // Add methods will work instead.
+ //
+
+ [Obsolete("Evidence should not be treated as an ICollection. Please use the GetHostEnumerator and GetAssemblyEnumerator methods rather than using CopyTo.")]
+ public void CopyTo(Array array, int index)
+ {
+ if (array == null)
+ throw new ArgumentNullException("array");
+ if (index < 0 || index > array.Length - Count)
+ throw new ArgumentOutOfRangeException("index");
+ Contract.EndContractBlock();
+
+ int currentIndex = index;
+
+ IEnumerator hostEnumerator = GetHostEnumerator();
+ while (hostEnumerator.MoveNext())
+ {
+ array.SetValue(hostEnumerator.Current, currentIndex);
+ ++currentIndex;
+ }
+
+ IEnumerator assemblyEnumerator = GetAssemblyEnumerator();
+ while (assemblyEnumerator.MoveNext())
+ {
+ array.SetValue(assemblyEnumerator.Current, currentIndex);
+ ++currentIndex;
+ }
+ }
+
+ public IEnumerator GetHostEnumerator()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Host);
+ }
+ }
+
+ public IEnumerator GetAssemblyEnumerator()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ DeserializeTargetEvidence();
+ return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Assembly);
+ }
+ }
+
+ /// <summary>
+ /// Get an enumerator that can iterate over the raw evidence objects stored for the assembly
+ /// </summary>
+ internal RawEvidenceEnumerator GetRawAssemblyEvidenceEnumerator()
+ {
+ Contract.Assert(IsReaderLockHeld);
+ DeserializeTargetEvidence();
+ return new RawEvidenceEnumerator(this, new List<Type>(m_evidence.Keys), false);
+ }
+
+ /// <summary>
+ /// Get an enumerator that can iterate over the raw evidence objects stored for the host
+ /// </summary>
+ /// <returns></returns>
+ internal RawEvidenceEnumerator GetRawHostEvidenceEnumerator()
+ {
+ Contract.Assert(IsReaderLockHeld);
+ return new RawEvidenceEnumerator(this, new List<Type>(m_evidence.Keys), true);
+ }
+
+ [Obsolete("GetEnumerator is obsolete. Please use GetAssemblyEnumerator and GetHostEnumerator instead.")]
+ public IEnumerator GetEnumerator()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ return new EvidenceEnumerator(this, EvidenceEnumerator.Category.Host | EvidenceEnumerator.Category.Assembly);
+ }
+ }
+
+ /// <summary>
+ /// Get a specific type of assembly supplied evidence
+ /// </summary>
+ [ComVisible(false)]
+ public T GetAssemblyEvidence<T>() where T : EvidenceBase
+ {
+ return UnwrapEvidence(GetAssemblyEvidence(typeof(T))) as T;
+ }
+
+ internal EvidenceBase GetAssemblyEvidence(Type type)
+ {
+ Contract.Assert(type != null);
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ return GetAssemblyEvidenceNoLock(type);
+ }
+ }
+
+ private EvidenceBase GetAssemblyEvidenceNoLock(Type type)
+ {
+ Contract.Assert(IsReaderLockHeld || IsWriterLockHeld);
+ Contract.Assert(type != null);
+
+ DeserializeTargetEvidence();
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(type);
+ if (descriptor != null)
+ {
+ return descriptor.AssemblyEvidence;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Get a specific type of host supplied evidence
+ /// </summary>
+ [ComVisible(false)]
+ public T GetHostEvidence<T>() where T : EvidenceBase
+ {
+ return UnwrapEvidence(GetHostEvidence(typeof(T))) as T;
+ }
+
+ /// <summary>
+ /// Get a specific type of evidence from the host which may not have been verified yet. If the
+ /// evidence was not verified, then don't mark it as being used yet.
+ /// </summary>
+ internal T GetDelayEvaluatedHostEvidence<T>() where T : EvidenceBase, IDelayEvaluatedEvidence
+ {
+ return UnwrapEvidence(GetHostEvidence(typeof(T), false)) as T;
+ }
+
+ internal EvidenceBase GetHostEvidence(Type type)
+ {
+ Contract.Assert(type != null);
+
+ return GetHostEvidence(type, true);
+ }
+
+ [SecuritySafeCritical]
+ private EvidenceBase GetHostEvidence(Type type, bool markDelayEvaluatedEvidenceUsed)
+ {
+ Contract.Assert(type != null);
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ EvidenceBase evidence = GetHostEvidenceNoLock(type);
+
+ if (markDelayEvaluatedEvidenceUsed)
+ {
+ IDelayEvaluatedEvidence delayEvidence = evidence as IDelayEvaluatedEvidence;
+ if (delayEvidence != null)
+ {
+ delayEvidence.MarkUsed();
+ }
+ }
+
+ return evidence;
+ }
+ }
+
+ /// <summary>
+ /// Get host supplied evidence from the collection
+ ///
+ /// We attempt to find host evdience in the following order:
+ ///
+ /// 1. Already generated or explicitly supplied evidence
+ /// 2. Evidence supplied by the CLR host
+ /// 3. Evidence supplied by the CLR itself
+ /// </summary>
+ [SecurityCritical]
+ private EvidenceBase GetHostEvidenceNoLock(Type type)
+ {
+ Contract.Assert(IsReaderLockHeld || IsWriterLockHeld);
+ Contract.Assert(type != null);
+
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(type);
+
+ // If the evidence descriptor doesn't exist for the host evidence type than the evidence doesn't
+ // exist and neither the host nor the runtime can produce it.
+ if (descriptor == null)
+ {
+ return null;
+ }
+
+ // If the evidence has already been generated or if it was explicitly provided then return that
+ if (descriptor.HostEvidence != null)
+ {
+ return descriptor.HostEvidence;
+ }
+
+ // If we have a target, then the host or the runtime might be able to generate this type of
+ // evidence on demand.
+ if (m_target != null && !descriptor.Generated)
+ {
+ using (EvidenceUpgradeLockHolder lockHolder = new EvidenceUpgradeLockHolder(this))
+ {
+ // Make sure that we don't attempt to generate this type of evidencea again if we fail to
+ // generate it now.
+ descriptor.Generated = true;
+
+ EvidenceBase generatedEvidence = GenerateHostEvidence(type, descriptor.HostCanGenerate);
+ if (generatedEvidence != null)
+ {
+ descriptor.HostEvidence = generatedEvidence;
+
+ //
+ // #BackpatchGeneratedEvidence
+ //
+ // If we were cloned from another evidence collection propigate any generated evidence
+ // back to the original collection. Since Assembly and AppDomain both clone their
+ // evidence before giving it to users, this prevents us from having to regenerate
+ // evidence types on each clone that gets created. Note that we do not want to do this
+ // backpatching if the origin already has evidence of this type or if it has had
+ // this type of evidence removed from its collection.
+ //
+
+ Evidence cloneOrigin = m_cloneOrigin != null ? m_cloneOrigin.Target as Evidence : null;
+ if (cloneOrigin != null)
+ {
+ BCLDebug.Assert(cloneOrigin.Target != null && cloneOrigin.Target == Target,
+ "Attempt to backpatch evidence to a collection with a different target.");
+
+ using (EvidenceLockHolder cloneLockHolder = new EvidenceLockHolder(cloneOrigin, EvidenceLockHolder.LockType.Writer))
+ {
+ EvidenceTypeDescriptor cloneDescriptor = cloneOrigin.GetEvidenceTypeDescriptor(type);
+ if (cloneDescriptor != null && cloneDescriptor.HostEvidence == null)
+ {
+ cloneDescriptor.HostEvidence = generatedEvidence.Clone() as EvidenceBase;
+ }
+ }
+ }
+
+ }
+
+ return generatedEvidence;
+ }
+ }
+
+ // The evidence could not be generated and was not found
+ return null;
+ }
+
+ /// <summary>
+ /// Attempt to generate host evidence on demand via calls to the runtime host or the evidence facotry
+ /// </summary>
+ [SecurityCritical]
+ private EvidenceBase GenerateHostEvidence(Type type, bool hostCanGenerate)
+ {
+ Contract.Assert(type != null);
+ Contract.Assert(IsWriterLockHeld);
+
+#if FEATURE_CAS_POLICY
+ // First let the host generate the evidence if it can.
+ if (hostCanGenerate)
+ {
+ AppDomain targetDomain = m_target.Target as AppDomain;
+ Assembly targetAssembly = m_target.Target as Assembly;
+
+ EvidenceBase hostEvidence = null;
+ if (targetDomain != null)
+ {
+ hostEvidence = AppDomain.CurrentDomain.HostSecurityManager.GenerateAppDomainEvidence(type);
+ }
+ else if (targetAssembly != null)
+ {
+ hostEvidence = AppDomain.CurrentDomain.HostSecurityManager.GenerateAssemblyEvidence(type, targetAssembly);
+ }
+
+ // If the host generated the evidence, verify that it generated the evidence we expected
+ // and use that.
+ if (hostEvidence != null)
+ {
+ if (!type.IsAssignableFrom(hostEvidence.GetType()))
+ {
+ string hostType = AppDomain.CurrentDomain.HostSecurityManager.GetType().FullName;
+ string recievedType = hostEvidence.GetType().FullName;
+ string requestedType = type.FullName;
+
+ throw new InvalidOperationException(Environment.GetResourceString("Policy_IncorrectHostEvidence", hostType, recievedType, requestedType));
+ }
+
+ return hostEvidence;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // Finally, check to see if the CLR can generate the evidence
+ return m_target.GenerateEvidence(type);
+ }
+
+ [Obsolete("Evidence should not be treated as an ICollection. Please use GetHostEnumerator and GetAssemblyEnumerator to iterate over the evidence to collect a count.")]
+ public int Count
+ {
+ get
+ {
+ int count = 0;
+
+ IEnumerator hostEvidence = GetHostEnumerator();
+ while (hostEvidence.MoveNext())
+ {
+ ++count;
+ }
+
+ IEnumerator assemblyEvidence = GetAssemblyEnumerator();
+ while (assemblyEvidence.MoveNext())
+ {
+ ++count;
+ }
+
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Get the number of pieces of evidence which are currently generated, without causing any
+ /// lazily generated evidence to be created.
+ /// </summary>
+ [ComVisible(false)]
+ internal int RawCount
+ {
+ get
+ {
+ int count = 0;
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ foreach (Type evidenceType in new List<Type>(m_evidence.Keys))
+ {
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(evidenceType);
+
+ if (descriptor != null)
+ {
+ if (descriptor.AssemblyEvidence != null)
+ {
+ ++count;
+ }
+ if (descriptor.HostEvidence != null)
+ {
+ ++count;
+ }
+ }
+ }
+ }
+
+ return count;
+ }
+ }
+
+ public Object SyncRoot
+ {
+ get { return this; }
+ }
+
+ public bool IsSynchronized
+ {
+ get { return true; }
+ }
+
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+#if FEATURE_CAS_POLICY
+ [ComVisible(false)]
+ public Evidence Clone()
+ {
+ return new Evidence(this);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ [ComVisible(false)]
+ [SecuritySafeCritical]
+ public void Clear()
+ {
+ if (Locked)
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ }
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ ++m_version;
+ m_evidence.Clear();
+ }
+ }
+
+ [ComVisible(false)]
+ [SecuritySafeCritical]
+ public void RemoveType(Type t)
+ {
+ if (t == null)
+ throw new ArgumentNullException("t");
+ Contract.EndContractBlock();
+
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Writer))
+ {
+ EvidenceTypeDescriptor descriptor = GetEvidenceTypeDescriptor(t);
+ if (descriptor != null)
+ {
+ ++m_version;
+
+ // If we've locked this evidence collection, we need to do the lock check in the case that
+ // either we have host evidence, or that the host might generate it, since removing the
+ // evidence will cause us to bypass the host's ability to ever generate the evidence.
+ if (Locked && (descriptor.HostEvidence != null || descriptor.HostCanGenerate))
+ {
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence).Demand();
+ }
+
+ m_evidence.Remove(t);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Mark all of the already generated evidence in the collection as having been used during a
+ /// policy evaluation.
+ /// </summary>
+ internal void MarkAllEvidenceAsUsed()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ foreach (KeyValuePair<Type, EvidenceTypeDescriptor> evidenceType in m_evidence)
+ {
+ if (evidenceType.Value != null)
+ {
+ IDelayEvaluatedEvidence hostEvidence = evidenceType.Value.HostEvidence as IDelayEvaluatedEvidence;
+ if (hostEvidence != null)
+ {
+ hostEvidence.MarkUsed();
+ }
+
+ IDelayEvaluatedEvidence assemblyEvidence = evidenceType.Value.AssemblyEvidence as IDelayEvaluatedEvidence;
+ if (assemblyEvidence != null)
+ {
+ assemblyEvidence.MarkUsed();
+ }
+ }
+ }
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ /// <summary>
+ /// Determine if delay evaluated strong name evidence is contained in this collection, and if so
+ /// if it was used during policy evaluation.
+ ///
+ /// This method is called from the VM in SecurityPolicy::WasStrongNameEvidenceUsed
+ /// This class should be used as an adapter layer to allow the public facing EvidenceEnumerator to
+ /// be able to get the evidence values out of an Evidence class. It is tightly coupled with the
+ /// internal data structures holding the evidence objects in the Evidence class.
+ /// </summary>
+ private bool WasStrongNameEvidenceUsed()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(this, EvidenceLockHolder.LockType.Reader))
+ {
+ EvidenceTypeDescriptor snTypeDescriptor = GetEvidenceTypeDescriptor(typeof(StrongName));
+ if (snTypeDescriptor != null)
+ {
+ IDelayEvaluatedEvidence snEvidence = snTypeDescriptor.HostEvidence as IDelayEvaluatedEvidence;
+ return snEvidence != null && snEvidence.WasUsed;
+ }
+
+ return false;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ /// <summary>
+ /// Utility class to wrap acquiring a lock onto the evidence collection
+ /// </summary>
+ private class EvidenceLockHolder : IDisposable
+ {
+ private Evidence m_target;
+ private LockType m_lockType;
+
+ public enum LockType
+ {
+ Reader,
+ Writer
+ }
+
+ public EvidenceLockHolder(Evidence target, LockType lockType)
+ {
+ Contract.Assert(target != null);
+ Contract.Assert(lockType == LockType.Reader || lockType == LockType.Writer);
+
+ m_target = target;
+ m_lockType = lockType;
+
+ if (m_lockType == LockType.Reader)
+ {
+ m_target.AcquireReaderLock();
+ }
+ else
+ {
+ m_target.AcquireWriterlock();
+ }
+ }
+
+ public void Dispose()
+ {
+ if (m_lockType == LockType.Reader && m_target.IsReaderLockHeld)
+ {
+ m_target.ReleaseReaderLock();
+ }
+ else if (m_lockType == LockType.Writer && m_target.IsWriterLockHeld)
+ {
+ m_target.ReleaseWriterLock();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Utility class to wrap upgrading an acquired reader lock to a writer lock and then
+ /// downgrading it back to a reader lock.
+ /// </summary>
+ private class EvidenceUpgradeLockHolder : IDisposable
+ {
+ private Evidence m_target;
+ private LockCookie m_cookie;
+
+ public EvidenceUpgradeLockHolder(Evidence target)
+ {
+ Contract.Assert(target != null);
+
+ m_target = target;
+ m_cookie = m_target.UpgradeToWriterLock();
+ }
+
+ public void Dispose()
+ {
+ if (m_target.IsWriterLockHeld)
+ {
+ m_target.DowngradeFromWriterLock(ref m_cookie);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Enumerator that iterates directly over the evidence type map, returning back the evidence objects
+ /// that are contained in it. This enumerator will generate any lazy evaluated evidence it finds,
+ /// but it does not attempt to deal with legacy evidence adapters.
+ ///
+ /// This class should be used as an adapter layer to allow the public facing EvidenceEnumerator to
+ /// be able to get the evidence values out of an Evidence class. It is tightly coupled with the
+ /// internal data structures holding the evidence objects in the Evidence class.
+ /// </summary>
+ internal sealed class RawEvidenceEnumerator : IEnumerator<EvidenceBase>
+ {
+ private Evidence m_evidence;
+ private bool m_hostEnumerator; // true to enumerate host evidence, false to enumerate assembly evidence
+ private uint m_evidenceVersion;
+
+ private Type[] m_evidenceTypes;
+ private int m_typeIndex;
+ private EvidenceBase m_currentEvidence;
+
+ private static volatile List<Type> s_expensiveEvidence;
+
+ public RawEvidenceEnumerator(Evidence evidence, IEnumerable<Type> evidenceTypes, bool hostEnumerator)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidenceTypes != null);
+
+ m_evidence = evidence;
+ m_hostEnumerator = hostEnumerator;
+ m_evidenceTypes = GenerateEvidenceTypes(evidence, evidenceTypes, hostEnumerator);
+ m_evidenceVersion = evidence.m_version;
+
+ Reset();
+ }
+
+ public EvidenceBase Current
+ {
+ get
+ {
+ if (m_evidence.m_version != m_evidenceVersion)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+
+ return m_currentEvidence;
+ }
+ }
+
+ object IEnumerator.Current
+ {
+ get
+ {
+ if (m_evidence.m_version != m_evidenceVersion)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+
+ return m_currentEvidence;
+ }
+ }
+
+ /// <summary>
+ /// List of types of evidence that we would like to avoid generating if possible
+ /// </summary>
+ private static List<Type> ExpensiveEvidence
+ {
+ get
+ {
+ if (s_expensiveEvidence == null)
+ {
+ List<Type> expensiveEvidence = new List<Type>();
+#if FEATURE_CAS_POLICY
+ expensiveEvidence.Add(typeof(Hash));
+ expensiveEvidence.Add(typeof(Publisher));
+#endif // FEATURE_CAS_POLICY
+ s_expensiveEvidence = expensiveEvidence;
+
+#if _DEBUG
+ List<Type> runtimeTypes = new List<Type>(Evidence.RuntimeEvidenceTypes);
+ foreach (Type expensiveType in s_expensiveEvidence)
+ {
+ BCLDebug.Assert(runtimeTypes.Contains(expensiveType),
+ "Evidence type not generated by the runtime found in expensive evidence type list");
+ }
+#endif // _DEBUG
+ }
+
+ return s_expensiveEvidence;
+ }
+ }
+
+ public void Dispose()
+ {
+ return;
+ }
+
+ /// <summary>
+ /// Generate the array of types of evidence that could have values for
+ /// </summary>
+ private static Type[] GenerateEvidenceTypes(Evidence evidence,
+ IEnumerable<Type> evidenceTypes,
+ bool hostEvidence)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidenceTypes != null);
+
+ //
+ // Sort the evidence being generated into three categories, which we enumerate in order:
+ // 1. Evidence which has already been generated
+ // 2. Evidence which is relatively inexpensive to generate
+ // 3. Evidence which is expensive to generate.
+ //
+ // This allows us to be as efficient as possible in case the user of the enumerator stops the
+ // enumeration before we step up to the next more expensive category.
+ //
+
+ List<Type> alreadyGeneratedList = new List<Type>();
+ List<Type> inexpensiveList = new List<Type>();
+ List<Type> expensiveList = new List<Type>(ExpensiveEvidence.Count);
+
+ // Iterate over the evidence types classifying into the three groups. We need to copy the list
+ // here since GetEvidenceTypeDescriptor will potentially update the evidence dictionary, which
+ // evidenceTypes iterates over.
+ foreach (Type evidenceType in evidenceTypes)
+ {
+ EvidenceTypeDescriptor descriptor = evidence.GetEvidenceTypeDescriptor(evidenceType);
+ BCLDebug.Assert(descriptor != null, "descriptor != null");
+
+ bool alreadyGenerated = (hostEvidence && descriptor.HostEvidence != null) ||
+ (!hostEvidence && descriptor.AssemblyEvidence != null);
+
+ if (alreadyGenerated)
+ {
+ alreadyGeneratedList.Add(evidenceType);
+ }
+ else if (ExpensiveEvidence.Contains(evidenceType))
+ {
+ expensiveList.Add(evidenceType);
+ }
+ else
+ {
+ inexpensiveList.Add(evidenceType);
+ }
+ }
+
+ Type[] enumerationTypes = new Type[alreadyGeneratedList.Count + inexpensiveList.Count + expensiveList.Count];
+ alreadyGeneratedList.CopyTo(enumerationTypes, 0);
+ inexpensiveList.CopyTo(enumerationTypes, alreadyGeneratedList.Count);
+ expensiveList.CopyTo(enumerationTypes, alreadyGeneratedList.Count + inexpensiveList.Count);
+
+ return enumerationTypes;
+ }
+
+ [SecuritySafeCritical]
+ public bool MoveNext()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(m_evidence, EvidenceLockHolder.LockType.Reader))
+ {
+ if (m_evidence.m_version != m_evidenceVersion)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+
+ m_currentEvidence = null;
+
+ // Iterate over the possible types of evidence that we could have until we find one that
+ // really exists, or we run out of posibilities.
+ do
+ {
+ ++m_typeIndex;
+
+ if (m_typeIndex < m_evidenceTypes.Length)
+ {
+ if (m_hostEnumerator)
+ {
+ m_currentEvidence = m_evidence.GetHostEvidenceNoLock(m_evidenceTypes[m_typeIndex]);
+ }
+ else
+ {
+ m_currentEvidence = m_evidence.GetAssemblyEvidenceNoLock(m_evidenceTypes[m_typeIndex]);
+ }
+ }
+ }
+ while (m_typeIndex < m_evidenceTypes.Length && m_currentEvidence == null);
+ }
+
+ return m_currentEvidence != null;
+ }
+
+ public void Reset()
+ {
+ if (m_evidence.m_version != m_evidenceVersion)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EnumFailedVersion"));
+
+ m_typeIndex = -1;
+ m_currentEvidence = null;
+ }
+ }
+
+ private sealed class EvidenceEnumerator : IEnumerator
+ {
+ private Evidence m_evidence;
+ private Category m_category;
+ private Stack m_enumerators;
+
+ private object m_currentEvidence;
+
+ [Flags]
+ internal enum Category
+ {
+ Host = 0x1, // Enumerate only host supplied evidence
+ Assembly = 0x2 // Enumerate only assembly supplied evidence
+ }
+
+ internal EvidenceEnumerator(Evidence evidence, Category category)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(evidence.IsReaderLockHeld);
+
+ m_evidence = evidence;
+ m_category = category;
+ ResetNoLock();
+ }
+
+ public bool MoveNext()
+ {
+ IEnumerator currentEnumerator = CurrentEnumerator;
+
+ // No more enumerators means we can't go any further
+ if (currentEnumerator == null)
+ {
+ m_currentEvidence = null;
+ return false;
+ }
+
+ // See if the current enumerator can continue
+ if (currentEnumerator.MoveNext())
+ {
+ //
+ // If we've found an adapter for legacy evidence, we need to unwrap it for it to be the
+ // current enumerator's value. For wrapped evidence, this is a simple unwrap, for a list of
+ // evidence, we need to make that the current enumerator and get its first value.
+ //
+
+ LegacyEvidenceWrapper legacyWrapper = currentEnumerator.Current as LegacyEvidenceWrapper;
+ LegacyEvidenceList legacyList = currentEnumerator.Current as LegacyEvidenceList;
+
+ if (legacyWrapper != null)
+ {
+ m_currentEvidence = legacyWrapper.EvidenceObject;
+ }
+ else if (legacyList != null)
+ {
+ IEnumerator legacyListEnumerator = legacyList.GetEnumerator();
+ m_enumerators.Push(legacyListEnumerator);
+ MoveNext();
+ }
+ else
+ {
+ m_currentEvidence = currentEnumerator.Current;
+ }
+
+ BCLDebug.Assert(m_currentEvidence != null, "m_currentEvidence != null");
+ return true;
+ }
+ else
+ {
+ // If we've reached the end of the current enumerator, move to the next one and try again
+ m_enumerators.Pop();
+ return MoveNext();
+ }
+ }
+
+ public object Current
+ {
+ get { return m_currentEvidence; }
+ }
+
+ private IEnumerator CurrentEnumerator
+ {
+ get
+ {
+ return m_enumerators.Count > 0 ? m_enumerators.Peek() as IEnumerator : null;
+ }
+ }
+
+ public void Reset()
+ {
+ using (EvidenceLockHolder lockHolder = new EvidenceLockHolder(m_evidence, EvidenceLockHolder.LockType.Reader))
+ {
+ ResetNoLock();
+ }
+ }
+
+ private void ResetNoLock()
+ {
+ Contract.Assert(m_evidence != null);
+ Contract.Assert(m_evidence.IsReaderLockHeld);
+
+ m_currentEvidence = null;
+ m_enumerators = new Stack();
+
+ if ((m_category & Category.Host) == Category.Host)
+ {
+ m_enumerators.Push(m_evidence.GetRawHostEvidenceEnumerator());
+ }
+ if ((m_category & Category.Assembly) == Category.Assembly)
+ {
+ m_enumerators.Push(m_evidence.GetRawAssemblyEvidenceEnumerator());
+ }
+ }
+ }
+#endif //!FEATURE_CORECLR && FEATURE_RWLOCK
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs b/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs
new file mode 100644
index 0000000000..f142ebea2a
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/EvidenceBase.cs
@@ -0,0 +1,193 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Runtime.InteropServices;
+#if FEATURE_SERIALIZATION
+using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+using System.Security.Permissions;
+
+namespace System.Security.Policy
+{
+ /// <summary>
+ /// Base class from which all objects to be used as Evidence must derive
+ /// </summary>
+ [ComVisible(true)]
+ [Serializable]
+#pragma warning disable 618
+ [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ public abstract class EvidenceBase
+ {
+ protected EvidenceBase()
+ {
+#if FEATURE_SERIALIZATION
+ // All objects to be used as evidence must be serializable. Make sure that any derived types
+ // are marked serializable to enforce this, since the attribute does not inherit down to derived
+ // classes.
+ if (!GetType().IsSerializable)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Policy_EvidenceMustBeSerializable"));
+ }
+#endif // FEATURE_SERIALIZATION
+ }
+
+ /// <remarks>
+ /// Since legacy evidence objects would be cloned by being serialized, the default implementation
+ /// of EvidenceBase will do the same.
+ /// </remarks>
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Assert, SerializationFormatter = true)]
+ [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ [SecuritySafeCritical]
+ public virtual EvidenceBase Clone()
+ {
+#if FEATURE_SERIALIZATION
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ BinaryFormatter formatter = new BinaryFormatter();
+ formatter.Serialize(memoryStream, this);
+
+ memoryStream.Position = 0;
+ return formatter.Deserialize(memoryStream) as EvidenceBase;
+ }
+#else // !FEATURE_SERIALIZATION
+ throw new NotImplementedException();
+#endif // FEATURE_SERIALIZATION
+ }
+ }
+
+ /// <summary>
+ /// Interface for types which wrap Whidbey evidence objects for compatibility with v4 evidence rules
+ /// </summary>
+ internal interface ILegacyEvidenceAdapter
+ {
+ object EvidenceObject { get; }
+ Type EvidenceType { get; }
+ }
+
+ /// <summary>
+ /// Wrapper class to hold legacy evidence objects which do not derive from EvidenceBase, and allow
+ /// them to be held in the Evidence collection which expects to maintain lists of EvidenceBase only
+ /// </summary>
+ [Serializable]
+ internal sealed class LegacyEvidenceWrapper : EvidenceBase, ILegacyEvidenceAdapter
+ {
+ private object m_legacyEvidence;
+
+ internal LegacyEvidenceWrapper(object legacyEvidence)
+ {
+ Contract.Assert(legacyEvidence != null);
+ Contract.Assert(legacyEvidence.GetType() != typeof(EvidenceBase), "Attempt to wrap an EvidenceBase in a LegacyEvidenceWrapper");
+ Contract.Assert(legacyEvidence.GetType().IsSerializable, "legacyEvidence.GetType().IsSerializable");
+
+ m_legacyEvidence = legacyEvidence;
+ }
+
+ public object EvidenceObject
+ {
+ get { return m_legacyEvidence; }
+ }
+
+ public Type EvidenceType
+ {
+ get { return m_legacyEvidence.GetType(); }
+ }
+
+ public override bool Equals(object obj)
+ {
+ return m_legacyEvidence.Equals(obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return m_legacyEvidence.GetHashCode();
+ }
+
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+#pragma warning restore 618
+ [SecuritySafeCritical]
+ public override EvidenceBase Clone()
+ {
+ return base.Clone();
+ }
+ }
+
+ /// <summary>
+ /// Pre-v4 versions of the runtime allow multiple pieces of evidence that all have the same type.
+ /// This type wraps those evidence objects into a single type of list, allowing legacy code to continue
+ /// to work with the Evidence collection that does not expect multiple evidences of the same type.
+ ///
+ /// This may not be limited to LegacyEvidenceWrappers, since it's valid for legacy code to add multiple
+ /// objects of built-in evidence to an Evidence collection. The built-in evidence now derives from
+ /// EvienceObject, so when the legacy code runs on v4, it may end up attempting to add multiple
+ /// Hash evidences for intsance.
+ /// </summary>
+ [Serializable]
+ internal sealed class LegacyEvidenceList : EvidenceBase, IEnumerable<EvidenceBase>, ILegacyEvidenceAdapter
+ {
+ private List<EvidenceBase> m_legacyEvidenceList = new List<EvidenceBase>();
+
+ public object EvidenceObject
+ {
+ get
+ {
+ // We'll choose the first item in the list to represent us if we're forced to return only
+ // one object. This can occur if multiple pieces of evidence are added via the legacy APIs,
+ // and then the new APIs are used to retrieve that evidence.
+ return m_legacyEvidenceList.Count > 0 ? m_legacyEvidenceList[0] : null;
+ }
+ }
+
+ public Type EvidenceType
+ {
+ get
+ {
+ Contract.Assert(m_legacyEvidenceList.Count > 0, "No items in LegacyEvidenceList, cannot tell what type they are");
+
+ ILegacyEvidenceAdapter adapter = m_legacyEvidenceList[0] as ILegacyEvidenceAdapter;
+ return adapter == null ? m_legacyEvidenceList[0].GetType() : adapter.EvidenceType;
+ }
+ }
+
+ public void Add(EvidenceBase evidence)
+ {
+ Contract.Assert(evidence != null);
+ Contract.Assert(m_legacyEvidenceList.Count == 0 || EvidenceType == evidence.GetType() || (evidence is LegacyEvidenceWrapper && (evidence as LegacyEvidenceWrapper).EvidenceType == EvidenceType),
+ "LegacyEvidenceList must be homogeonous");
+ Contract.Assert(evidence.GetType() != typeof(LegacyEvidenceList),
+ "Attempt to add a legacy evidence list to another legacy evidence list");
+
+ m_legacyEvidenceList.Add(evidence);
+ }
+
+ public IEnumerator<EvidenceBase> GetEnumerator()
+ {
+ return m_legacyEvidenceList.GetEnumerator();
+ }
+
+ IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return m_legacyEvidenceList.GetEnumerator();
+ }
+
+#pragma warning disable 618
+ [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
+#pragma warning restore 618
+ [SecuritySafeCritical]
+ public override EvidenceBase Clone()
+ {
+ return base.Clone();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs b/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs
new file mode 100644
index 0000000000..bccf39218b
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/EvidenceTypeDescriptor.cs
@@ -0,0 +1,160 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.Serialization;
+
+namespace System.Security.Policy
+{
+ /// <summary>
+ /// Descriptor stored in the Evidence collection to detail the information we have about a type of
+ /// evidence. This descriptor also stores any evidence that's been generated of the specific type.
+ /// </summary>
+ [Serializable]
+ internal sealed class EvidenceTypeDescriptor
+ {
+ [NonSerialized]
+ private bool m_hostCanGenerate;
+
+ [NonSerialized]
+ private bool m_generated;
+
+ private EvidenceBase m_hostEvidence;
+ private EvidenceBase m_assemblyEvidence;
+
+ // EvidenceTypeDescriptors are stored in Evidence indexed by the type they describe, so this
+ // information is redundant. We keep it around in checked builds to help debugging, but we can drop
+ // it from retial builds.
+#if _DEBUG
+ [NonSerialized]
+ private Type m_evidenceType;
+#endif // _DEBUG
+
+ public EvidenceTypeDescriptor()
+ {
+ }
+
+ /// <summary>
+ /// Make a deep copy of a type descriptor
+ /// </summary>
+ private EvidenceTypeDescriptor(EvidenceTypeDescriptor descriptor)
+ {
+ Contract.Assert(descriptor != null);
+
+ m_hostCanGenerate = descriptor.m_hostCanGenerate;
+
+ if (descriptor.m_assemblyEvidence != null)
+ {
+ m_assemblyEvidence = descriptor.m_assemblyEvidence.Clone() as EvidenceBase;
+ }
+ if (descriptor.m_hostEvidence != null)
+ {
+ m_hostEvidence = descriptor.m_hostEvidence.Clone() as EvidenceBase;
+ }
+
+#if _DEBUG
+ m_evidenceType = descriptor.m_evidenceType;
+#endif // _DEBUG
+ }
+
+ /// <summary>
+ /// Evidence of this type supplied by the assembly
+ /// </summary>
+ public EvidenceBase AssemblyEvidence
+ {
+ get { return m_assemblyEvidence; }
+
+ set
+ {
+ Contract.Assert(value != null);
+#if _DEBUG
+ Contract.Assert(CheckEvidenceType(value), "Incorrect type of AssemblyEvidence set");
+#endif
+ m_assemblyEvidence = value;
+ }
+ }
+
+ /// <summary>
+ /// Flag indicating that we've already attempted to generate this type of evidence
+ /// </summary>
+ public bool Generated
+ {
+ get { return m_generated; }
+
+ set
+ {
+ Contract.Assert(value, "Attempt to clear the Generated flag");
+ m_generated = value;
+ }
+ }
+
+ /// <summary>
+ /// Has the HostSecurityManager has told us that it can potentially generate evidence of this type
+ /// </summary>
+ public bool HostCanGenerate
+ {
+ get { return m_hostCanGenerate; }
+
+ set
+ {
+ Contract.Assert(value, "Attempt to clear HostCanGenerate flag");
+ m_hostCanGenerate = value;
+ }
+ }
+
+ /// <summary>
+ /// Evidence of this type supplied by the CLR or the host
+ /// </summary>
+ public EvidenceBase HostEvidence
+ {
+ get { return m_hostEvidence; }
+
+ set
+ {
+ Contract.Assert(value != null);
+#if _DEBUG
+ Contract.Assert(CheckEvidenceType(value), "Incorrect type of HostEvidence set");
+#endif
+ m_hostEvidence = value;
+ }
+ }
+
+#if _DEBUG
+ /// <summary>
+ /// Verify that evidence being stored in this descriptor is of the correct type
+ /// </summary>
+ private bool CheckEvidenceType(EvidenceBase evidence)
+ {
+ Contract.Assert(evidence != null);
+
+ ILegacyEvidenceAdapter legacyAdapter = evidence as ILegacyEvidenceAdapter;
+ Type storedType = legacyAdapter == null ? evidence.GetType() : legacyAdapter.EvidenceType;
+
+ return m_evidenceType == null || m_evidenceType.IsAssignableFrom(storedType);
+ }
+#endif // _DEBUG
+
+ /// <summary>
+ /// Make a deep copy of this descriptor
+ /// </summary>
+ public EvidenceTypeDescriptor Clone()
+ {
+ return new EvidenceTypeDescriptor(this);
+ }
+
+#if _DEBUG
+ /// <summary>
+ /// Set the type that this evidence descriptor refers to.
+ /// </summary>
+ internal void SetEvidenceType(Type evidenceType)
+ {
+ Contract.Assert(evidenceType != null);
+ Contract.Assert(m_evidenceType == null, "Attempt to reset evidence type");
+
+ m_evidenceType = evidenceType;
+ }
+#endif // _DEBUG
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs b/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs
new file mode 100644
index 0000000000..5bd36485db
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/IDelayEvaluatedEvidence.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.Security.Policy {
+ /// <summary>
+ /// Interface for evidence objects that support being "unverified". For instance, StrongName
+ /// evidence for a strong name signature which was not yet verified. This interface is used to
+ /// keep track of weather or not the evidence object was needed to compute a grant set. If it was,
+ /// then we can force verificaiton of the evidence object -- if not we can save time by not doing
+ /// any verification on it. (Since we didn't use it for policy resolution, it wouldn't have
+ /// mattered if the evidence was not present in the first place).
+ /// </summary>
+ internal interface IDelayEvaluatedEvidence {
+ /// <summary>
+ /// Is this evidence object verified yet?
+ /// </summary>
+ bool IsVerified
+ {
+ [System.Security.SecurityCritical]
+ get;
+ }
+
+ /// <summary>
+ /// Was this evidence object used during the course of policy evaluation?
+ /// </summary>
+ bool WasUsed { get; }
+
+ /// <summary>
+ /// Mark the object as used
+ /// </summary>
+ void MarkUsed();
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/IIdentityPermissionFactory.cs b/src/mscorlib/src/System/Security/Policy/IIdentityPermissionFactory.cs
new file mode 100644
index 0000000000..a46f39602d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/IIdentityPermissionFactory.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// All Identities will implement this interface.
+//
+
+namespace System.Security.Policy {
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Util;
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IIdentityPermissionFactory
+ {
+ IPermission CreateIdentityPermission( Evidence evidence );
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/Policy/IRuntimeEvidenceFactory.cs b/src/mscorlib/src/System/Security/Policy/IRuntimeEvidenceFactory.cs
new file mode 100644
index 0000000000..98467fe367
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/IRuntimeEvidenceFactory.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Security.Policy
+{
+ /// <summary>
+ /// IRuntimeEvidenceFactory is implemented by runtime types which the CLR knows how to delay
+ /// generate evidence for. It is used by the Evidence class to get evidence on demand when we first
+ /// need it.
+ /// </summary>
+ internal interface IRuntimeEvidenceFactory
+ {
+ /// <summary>
+ /// Object which the evidence generated by this factory is used for
+ /// </summary>
+ IEvidenceFactory Target { get; }
+
+ /// <summary>
+ /// Get the collection of evidence objects supplied by the factory itself, rather than by the
+ /// runtime.
+ /// </summary>
+ IEnumerable<EvidenceBase> GetFactorySuppliedEvidence();
+
+ /// <summary>
+ /// Generate a specific type of evidence for this object, returning null if the specified type of
+ /// evidence cannot be generated.
+ /// </summary>
+ EvidenceBase GenerateEvidence(Type evidenceType);
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/PolicyException.cs b/src/mscorlib/src/System/Security/Policy/PolicyException.cs
new file mode 100644
index 0000000000..68e87f780d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/PolicyException.cs
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// Use this class to throw a PolicyException
+//
+
+namespace System.Security.Policy {
+
+ using System;
+ using System.Runtime.Serialization;
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class PolicyException : SystemException
+ {
+ public PolicyException()
+
+ : base(Environment.GetResourceString( "Policy_Default" )) {
+ HResult = __HResults.CORSEC_E_POLICY_EXCEPTION;
+ }
+
+ public PolicyException(String message)
+
+ : base(message) {
+ HResult = __HResults.CORSEC_E_POLICY_EXCEPTION;
+ }
+
+ public PolicyException(String message, Exception exception)
+
+ : base(message, exception) {
+ HResult = __HResults.CORSEC_E_POLICY_EXCEPTION;
+ }
+
+ protected PolicyException(SerializationInfo info, StreamingContext context) : base (info, context) {}
+
+ internal PolicyException(String message, int hresult) : base (message)
+ {
+ HResult = hresult;
+ }
+
+ internal PolicyException(String message, int hresult, Exception exception) : base (message, exception)
+ {
+ HResult = hresult;
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs b/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs
new file mode 100644
index 0000000000..72c07d1246
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/PolicyStatement.cs
@@ -0,0 +1,540 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Represents the policy associated with some piece of evidence
+//
+using System.Diagnostics.Contracts;
+namespace System.Security.Policy {
+
+ using System;
+ using System.Security;
+ using System.Security.Util;
+ using Math = System.Math;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Globalization;
+[Serializable]
+ [Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum PolicyStatementAttribute
+ {
+ Nothing = 0x0,
+ Exclusive = 0x01,
+ LevelFinal = 0x02,
+ All = 0x03,
+ }
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class PolicyStatement : ISecurityPolicyEncodable, ISecurityEncodable
+ {
+ // The PermissionSet associated with this policy
+ internal PermissionSet m_permSet;
+
+#if FEATURE_CAS_POLICY
+ // Evidence which was not verified but which was required to generate this policy statement.
+ // This is not serialized, since once we serialize we lose the ability to verify the evidence,
+ // meaning that restoring this state is meaningless.
+ [NonSerialized]
+ private List<IDelayEvaluatedEvidence> m_dependentEvidence;
+#endif
+
+ // The bitfield of inheritance properties associated with this policy
+ internal PolicyStatementAttribute m_attributes;
+
+ internal PolicyStatement()
+ {
+ m_permSet = null;
+ m_attributes = PolicyStatementAttribute.Nothing;
+ }
+
+ public PolicyStatement( PermissionSet permSet )
+ : this( permSet, PolicyStatementAttribute.Nothing )
+ {
+ }
+
+ public PolicyStatement( PermissionSet permSet, PolicyStatementAttribute attributes )
+ {
+ if (permSet == null)
+ {
+ m_permSet = new PermissionSet( false );
+ }
+ else
+ {
+ m_permSet = permSet.Copy();
+ }
+ if (ValidProperties( attributes ))
+ {
+ m_attributes = attributes;
+ }
+ }
+
+ private PolicyStatement( PermissionSet permSet, PolicyStatementAttribute attributes, bool copy )
+ {
+ if (permSet != null)
+ {
+ if (copy)
+ m_permSet = permSet.Copy();
+ else
+ m_permSet = permSet;
+ }
+ else
+ {
+ m_permSet = new PermissionSet( false );
+ }
+
+ m_attributes = attributes;
+ }
+
+ public PermissionSet PermissionSet
+ {
+ get
+ {
+ lock (this)
+ {
+ return m_permSet.Copy();
+ }
+ }
+
+ set
+ {
+ lock (this)
+ {
+ if (value == null)
+ {
+ m_permSet = new PermissionSet( false );
+ }
+ else
+ {
+ m_permSet = value.Copy();
+ }
+ }
+ }
+ }
+
+ internal void SetPermissionSetNoCopy( PermissionSet permSet )
+ {
+ m_permSet = permSet;
+ }
+
+ internal PermissionSet GetPermissionSetNoCopy()
+ {
+ lock (this)
+ {
+ return m_permSet;
+ }
+ }
+
+ public PolicyStatementAttribute Attributes
+ {
+ get
+ {
+ return m_attributes;
+ }
+
+ set
+ {
+ if (ValidProperties( value ))
+ {
+ m_attributes = value;
+ }
+ }
+ }
+
+ public PolicyStatement Copy()
+ {
+ PolicyStatement copy = new PolicyStatement(m_permSet, Attributes, true); // The PolicyStatement .ctor will copy the permission set
+#if FEATURE_CAS_POLICY
+ if (HasDependentEvidence)
+ {
+ copy.m_dependentEvidence = new List<IDelayEvaluatedEvidence>(m_dependentEvidence);
+ }
+#endif
+
+ return copy;
+ }
+
+ public String AttributeString
+ {
+ get
+ {
+ StringBuilder sb = new StringBuilder();
+
+ bool first = true;
+
+ if (GetFlag((int) PolicyStatementAttribute.Exclusive ))
+ {
+ sb.Append( "Exclusive" );
+ first = false;
+ }
+ if (GetFlag((int) PolicyStatementAttribute.LevelFinal ))
+ {
+ if (!first)
+ sb.Append( " " );
+ sb.Append( "LevelFinal" );
+ }
+
+ return sb.ToString();
+ }
+ }
+
+ private static bool ValidProperties( PolicyStatementAttribute attributes )
+ {
+ if ((attributes & ~(PolicyStatementAttribute.All)) == 0)
+ {
+ return true;
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidFlag" ) );
+ }
+ }
+
+ private bool GetFlag( int flag )
+ {
+ return (flag & (int)m_attributes) != 0;
+ }
+
+#if FEATURE_CAS_POLICY
+ /// <summary>
+ /// Gets all of the delay evaluated evidence which needs to be verified before this policy can
+ /// be used.
+ /// </summary>
+ internal IEnumerable<IDelayEvaluatedEvidence> DependentEvidence
+ {
+ get
+ {
+ BCLDebug.Assert(HasDependentEvidence, "HasDependentEvidence");
+ return m_dependentEvidence.AsReadOnly();
+ }
+ }
+
+ /// <summary>
+ /// Determine if this policy dependent upon the evaluation of any delay evaluated evidence
+ /// </summary>
+ internal bool HasDependentEvidence
+ {
+ get { return m_dependentEvidence != null && m_dependentEvidence.Count > 0; }
+ }
+
+ /// <summary>
+ /// Add evidence which this policy statement is depending upon being verified to be valid.
+ /// </summary>
+ internal void AddDependentEvidence(IDelayEvaluatedEvidence dependentEvidence)
+ {
+ BCLDebug.Assert(dependentEvidence != null, "dependentEvidence != null");
+
+ if (m_dependentEvidence == null)
+ {
+ m_dependentEvidence = new List<IDelayEvaluatedEvidence>();
+ }
+
+ m_dependentEvidence.Add(dependentEvidence);
+ }
+#endif
+
+ /// <summary>
+ /// Union a child policy statement into this policy statement
+ /// </summary>
+ internal void InplaceUnion(PolicyStatement childPolicy)
+ {
+ BCLDebug.Assert(childPolicy != null, "childPolicy != null");
+
+ if (((Attributes & childPolicy.Attributes) & PolicyStatementAttribute.Exclusive) == PolicyStatementAttribute.Exclusive)
+ {
+ throw new PolicyException(Environment.GetResourceString( "Policy_MultipleExclusive" ));
+ }
+
+#if FEATURE_CAS_POLICY
+ // If our code group generated a grant set based upon unverified evidence, or it generated a grant
+ // set strictly less than that of a child group based upon unverified evidence, we need to keep
+ // track of any unverified evidence our child group has.
+ if (childPolicy.HasDependentEvidence)
+ {
+ bool childEvidenceNeedsVerification = m_permSet.IsSubsetOf(childPolicy.GetPermissionSetNoCopy()) &&
+ !childPolicy.GetPermissionSetNoCopy().IsSubsetOf(m_permSet);
+
+ if (HasDependentEvidence || childEvidenceNeedsVerification)
+ {
+ if (m_dependentEvidence == null)
+ {
+ m_dependentEvidence = new List<IDelayEvaluatedEvidence>();
+ }
+
+ m_dependentEvidence.AddRange(childPolicy.DependentEvidence);
+ }
+ }
+#endif
+
+ // We need to merge together our grant set and attributes. The result of this merge is
+ // dependent upon if we're merging a child marked exclusive or not. If the child is not
+ // exclusive, we need to union in its grant set and or in its attributes. However, if the child
+ // is exclusive then it is the only code group which should have an effect on the resulting
+ // grant set and therefore our grant should be ignored.
+ if ((childPolicy.Attributes & PolicyStatementAttribute.Exclusive) == PolicyStatementAttribute.Exclusive)
+ {
+ m_permSet = childPolicy.GetPermissionSetNoCopy();
+ Attributes = childPolicy.Attributes;
+ }
+ else
+ {
+ m_permSet.InplaceUnion(childPolicy.GetPermissionSetNoCopy());
+ Attributes = Attributes | childPolicy.Attributes;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+
+ public SecurityElement ToXml()
+ {
+ return ToXml( null );
+ }
+
+ public void FromXml( SecurityElement et )
+ {
+ FromXml( et, null );
+ }
+
+ public SecurityElement ToXml( PolicyLevel level )
+ {
+ return ToXml( level, false );
+ }
+
+ internal SecurityElement ToXml( PolicyLevel level, bool useInternal )
+ {
+ SecurityElement e = new SecurityElement( "PolicyStatement" );
+ e.AddAttribute( "version", "1" );
+ if (m_attributes != PolicyStatementAttribute.Nothing)
+ e.AddAttribute( "Attributes", XMLUtil.BitFieldEnumToString( typeof( PolicyStatementAttribute ), m_attributes ) );
+
+ lock (this)
+ {
+ if (m_permSet != null)
+ {
+ if (m_permSet is NamedPermissionSet)
+ {
+ // If the named permission set exists in the parent level of this
+ // policy struct, then just save the name of the permission set.
+ // Otherwise, serialize it like normal.
+
+ NamedPermissionSet namedPermSet = (NamedPermissionSet)m_permSet;
+ if (level != null && level.GetNamedPermissionSet( namedPermSet.Name ) != null)
+ {
+ e.AddAttribute( "PermissionSetName", namedPermSet.Name );
+ }
+ else
+ {
+ if (useInternal)
+ e.AddChild( namedPermSet.InternalToXml() );
+ else
+ e.AddChild( namedPermSet.ToXml() );
+ }
+ }
+ else
+ {
+ if (useInternal)
+ e.AddChild( m_permSet.InternalToXml() );
+ else
+ e.AddChild( m_permSet.ToXml() );
+ }
+ }
+ }
+
+ return e;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void FromXml( SecurityElement et, PolicyLevel level )
+ {
+ FromXml( et, level, false );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void FromXml( SecurityElement et, PolicyLevel level, bool allowInternalOnly )
+ {
+ if (et == null)
+ throw new ArgumentNullException( "et" );
+
+ if (!et.Tag.Equals( "PolicyStatement" ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PolicyStatement", this.GetType().FullName ) );
+ Contract.EndContractBlock();
+
+ m_attributes = (PolicyStatementAttribute) 0;
+
+ String strAttributes = et.Attribute( "Attributes" );
+
+ if (strAttributes != null)
+ m_attributes = (PolicyStatementAttribute)Enum.Parse( typeof( PolicyStatementAttribute ), strAttributes );
+
+ lock (this)
+ {
+ m_permSet = null;
+
+ if (level != null)
+ {
+ String permSetName = et.Attribute( "PermissionSetName" );
+
+ if (permSetName != null)
+ {
+ m_permSet = level.GetNamedPermissionSetInternal( permSetName );
+
+ if (m_permSet == null)
+ m_permSet = new PermissionSet( PermissionState.None );
+ }
+ }
+
+
+ if (m_permSet == null)
+ {
+ // There is no provided level, it is not a named permission set, or
+ // the named permission set doesn't exist in the provided level,
+ // so just create the class through reflection and decode normally.
+
+ SecurityElement e = et.SearchForChildByTag( "PermissionSet" );
+
+ if (e != null)
+ {
+ String className = e.Attribute( "class" );
+
+ if (className != null && (className.Equals( "NamedPermissionSet" ) ||
+ className.Equals( "System.Security.NamedPermissionSet" )))
+ m_permSet = new NamedPermissionSet( "DefaultName", PermissionState.None );
+ else
+ m_permSet = new PermissionSet( PermissionState.None );
+
+ try
+ {
+ m_permSet.FromXml( e, allowInternalOnly, true );
+ }
+ catch
+ {
+ // ignore any exceptions from the decode process.
+ // Note: we go ahead and use the permission set anyway. This should be safe since
+ // the decode process should never give permission beyond what a proper decode would have
+ // given.
+ }
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXML" ) );
+ }
+ }
+
+ if (m_permSet == null)
+ m_permSet = new PermissionSet( PermissionState.None );
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void FromXml( SecurityDocument doc, int position, PolicyLevel level, bool allowInternalOnly )
+ {
+ if (doc == null)
+ throw new ArgumentNullException( "doc" );
+ Contract.EndContractBlock();
+
+ if (!doc.GetTagForElement( position ).Equals( "PolicyStatement" ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidXMLElement" ), "PolicyStatement", this.GetType().FullName ) );
+
+ m_attributes = (PolicyStatementAttribute) 0;
+
+ String strAttributes = doc.GetAttributeForElement( position, "Attributes" );
+
+ if (strAttributes != null)
+ m_attributes = (PolicyStatementAttribute)Enum.Parse( typeof( PolicyStatementAttribute ), strAttributes );
+
+ lock (this)
+ {
+ m_permSet = null;
+
+ if (level != null)
+ {
+ String permSetName = doc.GetAttributeForElement( position, "PermissionSetName" );
+
+ if (permSetName != null)
+ {
+ m_permSet = level.GetNamedPermissionSetInternal( permSetName );
+
+ if (m_permSet == null)
+ m_permSet = new PermissionSet( PermissionState.None );
+ }
+ }
+
+
+ if (m_permSet == null)
+ {
+ // There is no provided level, it is not a named permission set, or
+ // the named permission set doesn't exist in the provided level,
+ // so just create the class through reflection and decode normally.
+
+ ArrayList childPositions = doc.GetChildrenPositionForElement( position );
+ int positionPermissionSet = -1;
+
+ for (int i = 0; i < childPositions.Count; ++i)
+ {
+ if (doc.GetTagForElement( (int)childPositions[i] ).Equals( "PermissionSet" ))
+ {
+ positionPermissionSet = (int)childPositions[i];
+ }
+ }
+
+ if (positionPermissionSet != -1)
+ {
+ String className = doc.GetAttributeForElement( positionPermissionSet, "class" );
+
+ if (className != null && (className.Equals( "NamedPermissionSet" ) ||
+ className.Equals( "System.Security.NamedPermissionSet" )))
+ m_permSet = new NamedPermissionSet( "DefaultName", PermissionState.None );
+ else
+ m_permSet = new PermissionSet( PermissionState.None );
+
+ m_permSet.FromXml( doc, positionPermissionSet, allowInternalOnly );
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidXML" ) );
+ }
+ }
+
+ if (m_permSet == null)
+ m_permSet = new PermissionSet( PermissionState.None );
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals( Object obj )
+ {
+ PolicyStatement other = obj as PolicyStatement;
+
+ if (other == null)
+ return false;
+
+ if (this.m_attributes != other.m_attributes)
+ return false;
+
+ if (!Object.Equals( this.m_permSet, other.m_permSet ))
+ return false;
+
+ return true;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ int accumulator = (int)this.m_attributes;
+
+ if (m_permSet != null)
+ accumulator = accumulator ^ m_permSet.GetHashCode();
+
+ return accumulator;
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Security/Policy/Site.cs b/src/mscorlib/src/System/Security/Policy/Site.cs
new file mode 100644
index 0000000000..e7c6cd3d83
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/Site.cs
@@ -0,0 +1,128 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// Site is an IIdentity representing internet sites.
+//
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Security.Permissions;
+using System.Security.Util;
+
+namespace System.Security.Policy
+{
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Site : EvidenceBase, IIdentityPermissionFactory
+ {
+ private SiteString m_name;
+
+ public Site(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+
+ m_name = new SiteString( name );
+ }
+
+ private Site(SiteString name)
+ {
+ Contract.Assert(name != null);
+ m_name = name;
+ }
+
+ public static Site CreateFromUrl( String url )
+ {
+ return new Site(ParseSiteFromUrl(url));
+ }
+
+ private static SiteString ParseSiteFromUrl( String name )
+ {
+ URLString urlString = new URLString( name );
+
+ if (String.Compare( urlString.Scheme, "file", StringComparison.OrdinalIgnoreCase) == 0)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidSite" ) );
+
+ return new SiteString( new URLString( name ).Host );
+ }
+
+ public String Name
+ {
+ get { return m_name.ToString(); }
+ }
+
+ internal SiteString GetSiteString()
+ {
+ return m_name;
+ }
+
+ public IPermission CreateIdentityPermission( Evidence evidence )
+ {
+ return new SiteIdentityPermission( Name );
+ }
+
+ public override bool Equals(Object o)
+ {
+ Site other = o as Site;
+ if (other == null)
+ {
+ return false;
+ }
+
+ return String.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
+ }
+
+ public override int GetHashCode()
+ {
+ return Name.GetHashCode();
+ }
+
+ public override EvidenceBase Clone()
+ {
+ return new Site(m_name);
+ }
+
+ public Object Copy()
+ {
+ return Clone();
+ }
+
+#if FEATURE_CAS_POLICY
+ internal SecurityElement ToXml()
+ {
+ SecurityElement elem = new SecurityElement( "System.Security.Policy.Site" );
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Site" ), "Class name changed!" );
+
+ elem.AddAttribute( "version", "1" );
+
+ if(m_name != null)
+ elem.AddChild( new SecurityElement( "Name", m_name.ToString() ) );
+
+ return elem;
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CAS_POLICY
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // INormalizeForIsolatedStorage is not implemented for startup perf
+ // equivalent to INormalizeForIsolatedStorage.Normalize()
+ internal Object Normalize()
+ {
+ return m_name.ToString().ToUpper(CultureInfo.InvariantCulture);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/StrongName.cs b/src/mscorlib/src/System/Security/Policy/StrongName.cs
new file mode 100644
index 0000000000..c49f2b0674
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/StrongName.cs
@@ -0,0 +1,222 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// StrongName is an IIdentity representing strong names.
+//
+
+namespace System.Security.Policy {
+ using System.IO;
+ using System.Reflection;
+ using System.Security.Util;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class StrongName : EvidenceBase, IIdentityPermissionFactory, IDelayEvaluatedEvidence
+ {
+ private StrongNamePublicKeyBlob m_publicKeyBlob;
+ private String m_name;
+ private Version m_version;
+
+ // Delay evaluated evidence is for policy resolution only, so it doesn't make sense to save that
+ // state away and then try to evaluate the strong name later.
+ [NonSerialized]
+ private RuntimeAssembly m_assembly = null;
+
+ [NonSerialized]
+ private bool m_wasUsed = false;
+
+ internal StrongName() {}
+
+ public StrongName( StrongNamePublicKeyBlob blob, String name, Version version ) : this(blob, name, version, null)
+ {
+ }
+
+ internal StrongName(StrongNamePublicKeyBlob blob, String name, Version version, Assembly assembly)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (String.IsNullOrEmpty(name))
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyStrongName"));
+
+ if (blob == null)
+ throw new ArgumentNullException("blob");
+
+ if (version == null)
+ throw new ArgumentNullException("version");
+ Contract.EndContractBlock();
+
+ RuntimeAssembly rtAssembly = assembly as RuntimeAssembly;
+ if (assembly != null && rtAssembly == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "assembly");
+
+ m_publicKeyBlob = blob;
+ m_name = name;
+ m_version = version;
+ m_assembly = rtAssembly;
+ }
+
+ public StrongNamePublicKeyBlob PublicKey
+ {
+ get
+ {
+ return m_publicKeyBlob;
+ }
+ }
+
+ public String Name
+ {
+ get
+ {
+ return m_name;
+ }
+ }
+
+ public Version Version
+ {
+ get
+ {
+ return m_version;
+ }
+ }
+
+ bool IDelayEvaluatedEvidence.IsVerified
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+#if FEATURE_CAS_POLICY
+ return m_assembly != null ? m_assembly.IsStrongNameVerified : true;
+#else // !FEATURE_CAS_POLICY
+ return true;
+#endif // FEATURE_CAS_POLICY
+ }
+ }
+
+ bool IDelayEvaluatedEvidence.WasUsed
+ {
+ get { return m_wasUsed; }
+ }
+
+ void IDelayEvaluatedEvidence.MarkUsed()
+ {
+ m_wasUsed = true;
+ }
+
+ internal static bool CompareNames( String asmName, String mcName )
+ {
+ if (mcName.Length > 0 && mcName[mcName.Length-1] == '*' && mcName.Length - 1 <= asmName.Length)
+ return String.Compare( mcName, 0, asmName, 0, mcName.Length - 1, StringComparison.OrdinalIgnoreCase) == 0;
+ else
+ return String.Compare( mcName, asmName, StringComparison.OrdinalIgnoreCase) == 0;
+ }
+
+ public IPermission CreateIdentityPermission( Evidence evidence )
+ {
+ return new StrongNameIdentityPermission( m_publicKeyBlob, m_name, m_version );
+ }
+
+ public override EvidenceBase Clone()
+ {
+ return new StrongName(m_publicKeyBlob, m_name, m_version);
+ }
+
+ public Object Copy()
+ {
+ return Clone();
+ }
+
+#if FEATURE_CAS_POLICY
+ internal SecurityElement ToXml()
+ {
+ SecurityElement root = new SecurityElement( "StrongName" );
+ root.AddAttribute( "version", "1" );
+
+ if (m_publicKeyBlob != null)
+ root.AddAttribute( "Key", System.Security.Util.Hex.EncodeHexString( m_publicKeyBlob.PublicKey ) );
+
+ if (m_name != null)
+ root.AddAttribute( "Name", m_name );
+
+ if (m_version != null)
+ root.AddAttribute( "Version", m_version.ToString() );
+
+ return root;
+ }
+
+ internal void FromXml (SecurityElement element)
+ {
+ if (element == null)
+ throw new ArgumentNullException("element");
+ if (String.Compare(element.Tag, "StrongName", StringComparison.Ordinal) != 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidXML"));
+ Contract.EndContractBlock();
+
+ m_publicKeyBlob = null;
+ m_version = null;
+
+ string key = element.Attribute("Key");
+ if (key != null)
+ m_publicKeyBlob = new StrongNamePublicKeyBlob(System.Security.Util.Hex.DecodeHexString(key));
+
+ m_name = element.Attribute("Name");
+
+ string version = element.Attribute("Version");
+ if (version != null)
+ m_version = new Version(version);
+ }
+
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public override bool Equals( Object o )
+ {
+ StrongName that = (o as StrongName);
+ return (that != null) &&
+ Equals( this.m_publicKeyBlob, that.m_publicKeyBlob ) &&
+ Equals( this.m_name, that.m_name ) &&
+ Equals( this.m_version, that.m_version );
+ }
+
+ public override int GetHashCode()
+ {
+ if (m_publicKeyBlob != null)
+ {
+ return m_publicKeyBlob.GetHashCode();
+ }
+ else if (m_name != null || m_version != null)
+ {
+ return (m_name == null ? 0 : m_name.GetHashCode()) + (m_version == null ? 0 : m_version.GetHashCode());
+ }
+ else
+ {
+ return typeof( StrongName ).GetHashCode();
+ }
+ }
+
+ // INormalizeForIsolatedStorage is not implemented for startup perf
+ // equivalent to INormalizeForIsolatedStorage.Normalize()
+ internal Object Normalize()
+ {
+ MemoryStream ms = new MemoryStream();
+ BinaryWriter bw = new BinaryWriter(ms);
+
+ bw.Write(m_publicKeyBlob.PublicKey);
+ bw.Write(m_version.Major);
+ bw.Write(m_name);
+
+ ms.Position = 0;
+ return ms;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/URL.cs b/src/mscorlib/src/System/Security/Policy/URL.cs
new file mode 100644
index 0000000000..d3ad4f8724
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/URL.cs
@@ -0,0 +1,119 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// Url is an IIdentity representing url internet sites.
+//
+
+namespace System.Security.Policy {
+ using System.IO;
+ using System.Security.Util;
+ using UrlIdentityPermission = System.Security.Permissions.UrlIdentityPermission;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Url : EvidenceBase, IIdentityPermissionFactory
+ {
+ private URLString m_url;
+
+ internal Url( String name, bool parsed )
+ {
+ if (name == null)
+ throw new ArgumentNullException( "name" );
+ Contract.EndContractBlock();
+
+ m_url = new URLString( name, parsed );
+ }
+
+ public Url( String name )
+ {
+ if (name == null)
+ throw new ArgumentNullException( "name" );
+ Contract.EndContractBlock();
+
+ m_url = new URLString( name );
+ }
+
+ private Url(Url url)
+ {
+ Contract.Assert(url != null);
+ m_url = url.m_url;
+ }
+
+ public String Value
+ {
+ get { return m_url.ToString(); }
+ }
+
+ internal URLString GetURLString()
+ {
+ return m_url;
+ }
+
+ public IPermission CreateIdentityPermission( Evidence evidence )
+ {
+ return new UrlIdentityPermission( m_url );
+ }
+
+ public override bool Equals(Object o)
+ {
+ Url other = o as Url;
+ if (other == null)
+ {
+ return false;
+ }
+
+ return other.m_url.Equals(m_url);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.m_url.GetHashCode();
+ }
+
+ public override EvidenceBase Clone()
+ {
+ return new Url(this);
+ }
+
+ public Object Copy()
+ {
+ return Clone();
+ }
+
+#if FEATURE_CAS_POLICY
+ internal SecurityElement ToXml()
+ {
+ SecurityElement root = new SecurityElement( "System.Security.Policy.Url" );
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Url" ), "Class name changed!" );
+
+ root.AddAttribute( "version", "1" );
+
+ if (m_url != null)
+ root.AddChild( new SecurityElement( "Url", m_url.ToString() ) );
+
+ return root;
+ }
+
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // INormalizeForIsolatedStorage is not implemented for startup perf
+ // equivalent to INormalizeForIsolatedStorage.Normalize()
+ internal Object Normalize()
+ {
+ return m_url.NormalizeUrl();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Policy/Zone.cs b/src/mscorlib/src/System/Security/Policy/Zone.cs
new file mode 100644
index 0000000000..c999abe340
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Policy/Zone.cs
@@ -0,0 +1,151 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// Zone is an IIdentity representing Internet/Intranet/MyComputer etc.
+//
+
+namespace System.Security.Policy {
+ using System.Security.Util;
+ using ZoneIdentityPermission = System.Security.Permissions.ZoneIdentityPermission;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Zone : EvidenceBase, IIdentityPermissionFactory
+ {
+#if FEATURE_CAS_POLICY
+ [OptionalField(VersionAdded = 2)]
+ private String m_url;
+#endif // FEATURE_CAS_POLICY
+ private SecurityZone m_zone;
+
+ private static readonly String[] s_names =
+ {"MyComputer", "Intranet", "Trusted", "Internet", "Untrusted", "NoZone"};
+
+ public Zone(SecurityZone zone)
+ {
+ if (zone < SecurityZone.NoZone || zone > SecurityZone.Untrusted)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_IllegalZone" ) );
+ Contract.EndContractBlock();
+
+ m_zone = zone;
+ }
+
+ private Zone(Zone zone)
+ {
+ Contract.Assert(zone != null);
+
+#if FEATURE_CAS_POLICY
+ m_url = zone.m_url;
+#endif // FEATURE_CAS_POLICY
+ m_zone = zone.m_zone;
+ }
+
+#if FEATURE_CAS_POLICY
+ private Zone(String url)
+ {
+ m_url = url;
+ m_zone = SecurityZone.NoZone;
+ }
+
+ public static Zone CreateFromUrl( String url )
+ {
+ if (url == null)
+ throw new ArgumentNullException( "url" );
+ Contract.EndContractBlock();
+
+ return new Zone( url );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private extern static SecurityZone _CreateFromUrl( String url );
+#endif // FEATURE_CAS_POLICY
+
+ public IPermission CreateIdentityPermission( Evidence evidence )
+ {
+ return new ZoneIdentityPermission( SecurityZone );
+ }
+
+ public SecurityZone SecurityZone
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+#if FEATURE_CAS_POLICY
+ if (m_url != null)
+ m_zone = _CreateFromUrl( m_url );
+#endif // FEATURE_CAS_POLICY
+
+ return m_zone;
+ }
+ }
+
+ public override bool Equals(Object o)
+ {
+ Zone other = o as Zone;
+ if (other == null)
+ {
+ return false;
+ }
+
+ return SecurityZone == other.SecurityZone;
+ }
+
+ public override int GetHashCode()
+ {
+ return (int)SecurityZone;
+ }
+
+ public override EvidenceBase Clone()
+ {
+ return new Zone(this);
+ }
+
+ public Object Copy()
+ {
+ return Clone();
+ }
+
+#if FEATURE_CAS_POLICY
+ internal SecurityElement ToXml()
+ {
+ SecurityElement elem = new SecurityElement( "System.Security.Policy.Zone" );
+ // If you hit this assert then most likely you are trying to change the name of this class.
+ // This is ok as long as you change the hard coded string above and change the assert below.
+ Contract.Assert( this.GetType().FullName.Equals( "System.Security.Policy.Zone" ), "Class name changed!" );
+
+ elem.AddAttribute( "version", "1" );
+ if (SecurityZone != SecurityZone.NoZone)
+ elem.AddChild( new SecurityElement( "Zone", s_names[(int)SecurityZone] ) );
+ else
+ elem.AddChild( new SecurityElement( "Zone", s_names[s_names.Length-1] ) );
+ return elem;
+ }
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_CAS_POLICY
+ public override String ToString()
+ {
+ return ToXml().ToString();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // INormalizeForIsolatedStorage is not implemented for startup perf
+ // equivalent to INormalizeForIsolatedStorage.Normalize()
+ internal Object Normalize()
+ {
+ return s_names[(int)SecurityZone];
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Principal/IIdentity.cs b/src/mscorlib/src/System/Security/Principal/IIdentity.cs
new file mode 100644
index 0000000000..2bda6c6e3d
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Principal/IIdentity.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// All identities will implement this interface
+//
+
+namespace System.Security.Principal
+{
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Util;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IIdentity {
+ // Access to the name string
+ string Name { get; }
+
+ // Access to Authentication 'type' info
+ string AuthenticationType { get; }
+
+ // Determine if this represents the unauthenticated identity
+ bool IsAuthenticated { get; }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Principal/IPrincipal.cs b/src/mscorlib/src/System/Security/Principal/IPrincipal.cs
new file mode 100644
index 0000000000..449cfb50b2
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Principal/IPrincipal.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// All roles will implement this interface
+//
+
+namespace System.Security.Principal
+{
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Util;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface IPrincipal {
+ // Retrieve the identity object
+ IIdentity Identity { get; }
+
+ // Perform a check for a specific role
+ bool IsInRole (string role);
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs b/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs
new file mode 100644
index 0000000000..fa77ac50f9
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Principal/TokenImpersonationLevel.cs
@@ -0,0 +1,20 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security.Principal
+{
+#if !FEATURE_CORECLR
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#endif
+ public enum TokenImpersonationLevel {
+ None = 0,
+ Anonymous = 1,
+ Identification = 2,
+ Impersonation = 3,
+ Delegation = 4
+ }
+}
diff --git a/src/mscorlib/src/System/Security/SafeSecurityHandles.cs b/src/mscorlib/src/System/Security/SafeSecurityHandles.cs
new file mode 100644
index 0000000000..ea9cd4be0f
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SafeSecurityHandles.cs
@@ -0,0 +1,164 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace Microsoft.Win32.SafeHandles {
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Security;
+
+ // Introduce this handle to replace internal SafeTokenHandle,
+ // which is mainly used to hold Windows thread or process access token
+ [SecurityCritical]
+ public sealed class SafeAccessTokenHandle : SafeHandle
+ {
+ private SafeAccessTokenHandle()
+ : base(IntPtr.Zero, true)
+ { }
+
+ // 0 is an Invalid Handle
+ public SafeAccessTokenHandle(IntPtr handle)
+ : base(IntPtr.Zero, true)
+ {
+ SetHandle(handle);
+ }
+
+ public static SafeAccessTokenHandle InvalidHandle
+ {
+ [SecurityCritical]
+ get { return new SafeAccessTokenHandle(IntPtr.Zero); }
+ }
+
+ public override bool IsInvalid
+ {
+ [SecurityCritical]
+ get { return handle == IntPtr.Zero || handle == new IntPtr(-1); }
+ }
+
+ [SecurityCritical]
+ protected override bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLsaLogonProcessHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ private SafeLsaLogonProcessHandle() : base (true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLsaLogonProcessHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLsaLogonProcessHandle InvalidHandle {
+ get { return new SafeLsaLogonProcessHandle(IntPtr.Zero); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ // LsaDeregisterLogonProcess returns an NTSTATUS
+ return Win32Native.LsaDeregisterLogonProcess(handle) >= 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLsaMemoryHandle : SafeBuffer {
+ private SafeLsaMemoryHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLsaMemoryHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLsaMemoryHandle InvalidHandle {
+ get { return new SafeLsaMemoryHandle( IntPtr.Zero ); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.LsaFreeMemory(handle) == 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLsaPolicyHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ private SafeLsaPolicyHandle() : base(true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLsaPolicyHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLsaPolicyHandle InvalidHandle {
+ get { return new SafeLsaPolicyHandle( IntPtr.Zero ); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.LsaClose(handle) == 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeLsaReturnBufferHandle : SafeBuffer {
+ private SafeLsaReturnBufferHandle() : base (true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeLsaReturnBufferHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeLsaReturnBufferHandle InvalidHandle {
+ get { return new SafeLsaReturnBufferHandle(IntPtr.Zero); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ // LsaFreeReturnBuffer returns an NTSTATUS
+ return Win32Native.LsaFreeReturnBuffer(handle) >= 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeProcessHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ private SafeProcessHandle() : base (true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeProcessHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ internal static SafeProcessHandle InvalidHandle {
+ get { return new SafeProcessHandle(IntPtr.Zero); }
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal sealed class SafeThreadHandle : SafeHandleZeroOrMinusOneIsInvalid {
+ private SafeThreadHandle() : base (true) {}
+
+ // 0 is an Invalid Handle
+ internal SafeThreadHandle(IntPtr handle) : base (true) {
+ SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ return Win32Native.CloseHandle(handle);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/SecurityContext.cs b/src/mscorlib/src/System/Security/SecurityContext.cs
new file mode 100644
index 0000000000..e422a312df
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityContext.cs
@@ -0,0 +1,702 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+**
+**
+** Purpose: Capture security context for a thread
+**
+**
+===========================================================*/
+namespace System.Security
+{
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System.Threading;
+ using System.Runtime.Remoting;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Collections;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Runtime.ExceptionServices;
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // This enum must be kept in sync with the SecurityContextSource enum in the VM
+ public enum SecurityContextSource
+ {
+ CurrentAppDomain = 0,
+ CurrentAssembly
+ }
+
+ internal enum SecurityContextDisableFlow
+ {
+ Nothing = 0,
+ WI = 0x1,
+ All = 0x3FFF
+ }
+
+#if FEATURE_IMPERSONATION
+ internal enum WindowsImpersonationFlowMode {
+ IMP_FASTFLOW = 0,
+ IMP_NOFLOW = 1,
+ IMP_ALWAYSFLOW = 2,
+ IMP_DEFAULT = IMP_FASTFLOW
+ }
+#endif
+
+#if FEATURE_COMPRESSEDSTACK
+ internal struct SecurityContextSwitcher: IDisposable
+ {
+ internal SecurityContext.Reader prevSC; // prev SC that we restore on an Undo
+ internal SecurityContext currSC; //current SC - SetSecurityContext that created the switcher set this on the Thread
+ internal ExecutionContext currEC; // current ExecutionContext on Thread
+ internal CompressedStackSwitcher cssw;
+#if FEATURE_IMPERSONATION
+ internal WindowsImpersonationContext wic;
+#endif
+
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ public void Dispose()
+ {
+ Undo();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal bool UndoNoThrow()
+ {
+ try
+ {
+ Undo();
+ }
+ catch
+ {
+ return false;
+ }
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ public void Undo()
+ {
+ if (currSC == null)
+ {
+ return; // mutiple Undo()s called on this switcher object
+ }
+
+ if (currEC != null)
+ {
+ Contract.Assert(currEC == Thread.CurrentThread.GetMutableExecutionContext(), "SecurityContextSwitcher used from another thread");
+ Contract.Assert(currSC == currEC.SecurityContext, "SecurityContextSwitcher context mismatch");
+
+ // restore the saved security context
+ currEC.SecurityContext = prevSC.DangerousGetRawSecurityContext();
+ }
+ else
+ {
+ // caller must have already restored the ExecutionContext
+ Contract.Assert(Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(prevSC));
+ }
+
+ currSC = null; // this will prevent the switcher object being used again
+
+ bool bNoException = true;
+#if FEATURE_IMPERSONATION
+ try
+ {
+ if (wic != null)
+ bNoException &= wic.UndoNoThrow();
+ }
+ catch
+ {
+ // Failfast since we can't continue safely...
+ bNoException &= cssw.UndoNoThrow();
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed"));
+
+ }
+#endif
+ bNoException &= cssw.UndoNoThrow();
+
+
+ if (!bNoException)
+ {
+ // Failfast since we can't continue safely...
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed"));
+ }
+
+ }
+ }
+
+
+ public sealed class SecurityContext : IDisposable
+ {
+#if FEATURE_IMPERSONATION
+ // Note that only one of the following variables will be true. The way we set up the flow mode in the g_pConfig guarantees this.
+ static bool _LegacyImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_NOFLOW);
+ static bool _alwaysFlowImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_ALWAYSFLOW);
+#endif
+ /*=========================================================================
+ ** Data accessed from managed code that needs to be defined in
+ ** SecurityContextObject to maintain alignment between the two classes.
+ ** DON'T CHANGE THESE UNLESS YOU MODIFY SecurityContextObject in vm\object.h
+ =========================================================================*/
+
+ private ExecutionContext _executionContext;
+#if FEATURE_IMPERSONATION
+ private volatile WindowsIdentity _windowsIdentity;
+#endif
+ private volatile CompressedStack _compressedStack;
+ static private volatile SecurityContext _fullTrustSC;
+
+ internal volatile bool isNewCapture = false;
+ internal volatile SecurityContextDisableFlow _disableFlow = SecurityContextDisableFlow.Nothing;
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal SecurityContext()
+ {
+ }
+
+ internal struct Reader
+ {
+ SecurityContext m_sc;
+
+ public Reader(SecurityContext sc) { m_sc = sc; }
+
+ public SecurityContext DangerousGetRawSecurityContext() { return m_sc; }
+
+ public bool IsNull { get { return m_sc == null; } }
+ public bool IsSame(SecurityContext sc) { return m_sc == sc; }
+ public bool IsSame(SecurityContext.Reader sc) { return m_sc == sc.m_sc; }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsFlowSuppressed(SecurityContextDisableFlow flags)
+ {
+ return (m_sc == null) ? false : ((m_sc._disableFlow & flags) == flags);
+ }
+
+ public CompressedStack CompressedStack { get { return IsNull ? null : m_sc.CompressedStack; } }
+
+ public WindowsIdentity WindowsIdentity
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get { return IsNull ? null : m_sc.WindowsIdentity; }
+ }
+ }
+
+
+ static internal SecurityContext FullTrustSecurityContext
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (_fullTrustSC == null)
+ _fullTrustSC = CreateFullTrustSecurityContext();
+ return _fullTrustSC;
+ }
+ }
+
+ // link the security context to an ExecutionContext
+ internal ExecutionContext ExecutionContext
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ _executionContext = value;
+ }
+ }
+
+#if FEATURE_IMPERSONATION
+
+
+ internal WindowsIdentity WindowsIdentity
+ {
+ get
+ {
+ return _windowsIdentity;
+ }
+ set
+ {
+ // Note, we do not dispose of the existing windows identity, since some code such as remoting
+ // relies on reusing that identity. If you are not going to reuse the existing identity, then
+ // you should dispose of the existing identity before resetting it.
+ _windowsIdentity = value;
+ }
+ }
+#endif // FEATURE_IMPERSONATION
+
+
+ internal CompressedStack CompressedStack
+ {
+ get
+ {
+ return _compressedStack;
+ }
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ _compressedStack = value;
+ }
+ }
+
+ public void Dispose()
+ {
+#if FEATURE_IMPERSONATION
+ if (_windowsIdentity != null)
+ _windowsIdentity.Dispose();
+#endif // FEATURE_IMPERSONATION
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static AsyncFlowControl SuppressFlow()
+ {
+ return SuppressFlow(SecurityContextDisableFlow.All);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static AsyncFlowControl SuppressFlowWindowsIdentity()
+ {
+ return SuppressFlow(SecurityContextDisableFlow.WI);
+ }
+
+ [SecurityCritical]
+ internal static AsyncFlowControl SuppressFlow(SecurityContextDisableFlow flags)
+ {
+ if (IsFlowSuppressed(flags))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
+ }
+
+ ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext();
+ if (ec.SecurityContext == null)
+ ec.SecurityContext = new SecurityContext();
+ AsyncFlowControl afc = new AsyncFlowControl();
+ afc.Setup(flags);
+ return afc;
+ }
+
+ [SecuritySafeCritical]
+ public static void RestoreFlow()
+ {
+ SecurityContext sc = Thread.CurrentThread.GetMutableExecutionContext().SecurityContext;
+ if (sc == null || sc._disableFlow == SecurityContextDisableFlow.Nothing)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow"));
+ }
+ sc._disableFlow = SecurityContextDisableFlow.Nothing;
+ }
+
+ public static bool IsFlowSuppressed()
+ {
+ return SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All);
+ }
+#if FEATURE_IMPERSONATION
+ public static bool IsWindowsIdentityFlowSuppressed()
+ {
+ return (_LegacyImpersonationPolicy|| SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.WI));
+ }
+#endif
+ [SecuritySafeCritical]
+ internal static bool IsFlowSuppressed(SecurityContextDisableFlow flags)
+ {
+ return Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsFlowSuppressed(flags);
+ }
+
+ // This method is special from a security perspective - the VM will not allow a stack walk to
+ // continue past the call to SecurityContext.Run. If you change the signature to this method, or
+ // provide an alternate way to do a SecurityContext.Run make sure to update
+ // SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new method.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static void Run(SecurityContext securityContext, ContextCallback callback, Object state)
+ {
+ if (securityContext == null )
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
+ }
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMe;
+
+ if (!securityContext.isNewCapture)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
+ }
+
+ securityContext.isNewCapture = false;
+
+ ExecutionContext.Reader ec = Thread.CurrentThread.GetExecutionContextReader();
+
+ // Optimization: do the callback directly if both the current and target contexts are equal to the
+ // default full-trust security context
+ if ( SecurityContext.CurrentlyInDefaultFTSecurityContext(ec)
+ && securityContext.IsDefaultFTSecurityContext())
+ {
+ callback(state);
+
+ if (GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) != null)
+ {
+ // If we enter here it means the callback did an impersonation
+ // that we need to revert.
+ // We don't need to revert any other security state since it is stack-based
+ // and automatically goes away when the callback returns.
+ WindowsIdentity.SafeRevertToSelf(ref stackMark);
+ // Ensure we have reverted to the state we entered in.
+ Contract.Assert(GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) == null);
+ }
+ }
+ else
+ {
+ RunInternal(securityContext, callback, state);
+ }
+
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, Object state)
+ {
+ if (cleanupCode == null)
+ {
+ tryCode = new RuntimeHelpers.TryCode(runTryCode);
+ cleanupCode = new RuntimeHelpers.CleanupCode(runFinallyCode);
+ }
+ SecurityContextRunData runData = new SecurityContextRunData(securityContext, callBack, state);
+ RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, runData);
+
+ }
+
+ internal class SecurityContextRunData
+ {
+ internal SecurityContext sc;
+ internal ContextCallback callBack;
+ internal Object state;
+ internal SecurityContextSwitcher scsw;
+ internal SecurityContextRunData(SecurityContext securityContext, ContextCallback cb, Object state)
+ {
+ this.sc = securityContext;
+ this.callBack = cb;
+ this.state = state;
+ this.scsw = new SecurityContextSwitcher();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal void runTryCode(Object userData)
+ {
+ SecurityContextRunData rData = (SecurityContextRunData) userData;
+ rData.scsw = SetSecurityContext(rData.sc, Thread.CurrentThread.GetExecutionContextReader().SecurityContext, modifyCurrentExecutionContext: true);
+ rData.callBack(rData.state);
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [PrePrepareMethod]
+ static internal void runFinallyCode(Object userData, bool exceptionThrown)
+ {
+ SecurityContextRunData rData = (SecurityContextRunData) userData;
+ rData.scsw.Undo();
+ }
+
+ static volatile internal RuntimeHelpers.TryCode tryCode;
+ static volatile internal RuntimeHelpers.CleanupCode cleanupCode;
+
+
+
+ // Internal API that gets called from public SetSecurityContext and from SetExecutionContext
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [System.Security.SecurityCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, SecurityContext.Reader prevSecurityContext, bool modifyCurrentExecutionContext)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return SetSecurityContext(sc, prevSecurityContext, modifyCurrentExecutionContext, ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, SecurityContext.Reader prevSecurityContext, bool modifyCurrentExecutionContext, ref StackCrawlMark stackMark)
+ {
+ // Save the flow state at capture and reset it in the SC.
+ SecurityContextDisableFlow _capturedFlowState = sc._disableFlow;
+ sc._disableFlow = SecurityContextDisableFlow.Nothing;
+
+ //Set up the switcher object
+ SecurityContextSwitcher scsw = new SecurityContextSwitcher();
+ scsw.currSC = sc;
+ scsw.prevSC = prevSecurityContext;
+
+ if (modifyCurrentExecutionContext)
+ {
+ // save the current Execution Context
+ ExecutionContext currEC = Thread.CurrentThread.GetMutableExecutionContext();
+ scsw.currEC = currEC;
+ currEC.SecurityContext = sc;
+ }
+
+ if (sc != null)
+ {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+#if FEATURE_IMPERSONATION
+ scsw.wic = null;
+ if (!_LegacyImpersonationPolicy)
+ {
+ if (sc.WindowsIdentity != null)
+ {
+ scsw.wic = sc.WindowsIdentity.Impersonate(ref stackMark);
+ }
+ else if ( ((_capturedFlowState & SecurityContextDisableFlow.WI) == 0)
+ && prevSecurityContext.WindowsIdentity != null)
+ {
+ // revert impersonation if there was no WI flow supression at capture and we're currently impersonating
+ scsw.wic = WindowsIdentity.SafeRevertToSelf(ref stackMark);
+ }
+ }
+#endif
+ scsw.cssw = CompressedStack.SetCompressedStack(sc.CompressedStack, prevSecurityContext.CompressedStack);
+ }
+ catch
+ {
+ scsw.UndoNoThrow();
+ throw;
+ }
+ }
+ return scsw;
+ }
+
+ /// <internalonly/>
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecurityContext CreateCopy()
+ {
+ if (!isNewCapture)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
+ }
+
+ SecurityContext sc = new SecurityContext();
+ sc.isNewCapture = true;
+ sc._disableFlow = _disableFlow;
+
+#if FEATURE_IMPERSONATION
+ if (WindowsIdentity != null)
+ sc._windowsIdentity = new WindowsIdentity(WindowsIdentity.AccessToken);
+#endif //FEATURE_IMPERSONATION
+
+ if (_compressedStack != null)
+ sc._compressedStack = _compressedStack.CreateCopy();
+
+ return sc;
+ }
+
+ /// <internalonly/>
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal SecurityContext CreateMutableCopy()
+ {
+ Contract.Assert(!this.isNewCapture);
+
+ SecurityContext sc = new SecurityContext();
+ sc._disableFlow = this._disableFlow;
+
+#if FEATURE_IMPERSONATION
+ if (this.WindowsIdentity != null)
+ sc._windowsIdentity = new WindowsIdentity(this.WindowsIdentity.AccessToken);
+#endif //FEATURE_IMPERSONATION
+
+ if (this._compressedStack != null)
+ sc._compressedStack = this._compressedStack.CreateCopy();
+
+ return sc;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static SecurityContext Capture( )
+ {
+ // check to see if Flow is suppressed
+ if (IsFlowSuppressed())
+ return null;
+
+ StackCrawlMark stackMark= StackCrawlMark.LookForMyCaller;
+ SecurityContext sc = SecurityContext.Capture(Thread.CurrentThread.GetExecutionContextReader(), ref stackMark);
+ if (sc == null)
+ sc = CreateFullTrustSecurityContext();
+ return sc;
+ }
+
+ // create a clone from a non-existing SecurityContext
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static internal SecurityContext Capture(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
+ {
+ // check to see if Flow is suppressed
+ if (currThreadEC.SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All))
+ return null;
+
+ // If we're in FT right now, return null
+ if (CurrentlyInDefaultFTSecurityContext(currThreadEC))
+ return null;
+
+ return CaptureCore(currThreadEC, ref stackMark);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private SecurityContext CaptureCore(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
+ {
+ SecurityContext sc = new SecurityContext();
+ sc.isNewCapture = true;
+
+#if FEATURE_IMPERSONATION
+ // Force create WindowsIdentity
+ if (!IsWindowsIdentityFlowSuppressed())
+ {
+ WindowsIdentity currentIdentity = GetCurrentWI(currThreadEC);
+ if (currentIdentity != null)
+ sc._windowsIdentity = new WindowsIdentity(currentIdentity.AccessToken);
+ }
+ else
+ {
+ sc._disableFlow = SecurityContextDisableFlow.WI;
+ }
+#endif // FEATURE_IMPERSONATION
+
+ // Force create CompressedStack
+ sc.CompressedStack = CompressedStack.GetCompressedStack(ref stackMark);
+ return sc;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ static internal SecurityContext CreateFullTrustSecurityContext()
+ {
+ SecurityContext sc = new SecurityContext();
+ sc.isNewCapture = true;
+
+#if FEATURE_IMPERSONATION
+ if (IsWindowsIdentityFlowSuppressed())
+ {
+ sc._disableFlow = SecurityContextDisableFlow.WI;
+ }
+#endif // FEATURE_IMPERSONATION
+
+
+ // Force create CompressedStack
+ sc.CompressedStack = new CompressedStack(null);
+ return sc;
+ }
+
+#if FEATURE_IMPERSONATION
+
+ static internal bool AlwaysFlowImpersonationPolicy { get { return _alwaysFlowImpersonationPolicy; } }
+
+ // Check to see if we have a WI on the thread and return if we do
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC)
+ {
+ return GetCurrentWI(threadEC, _alwaysFlowImpersonationPolicy);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC, bool cachedAlwaysFlowImpersonationPolicy)
+ {
+ Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy);
+ if (cachedAlwaysFlowImpersonationPolicy)
+ {
+ // Examine the threadtoken at the cost of a kernel call if the user has set the IMP_ALWAYSFLOW mode
+ return WindowsIdentity.GetCurrentInternal(TokenAccessLevels.MaximumAllowed, true);
+ }
+
+ return threadEC.SecurityContext.WindowsIdentity;
+ }
+
+ [System.Security.SecurityCritical]
+ static internal void RestoreCurrentWI(ExecutionContext.Reader currentEC, ExecutionContext.Reader prevEC, WindowsIdentity targetWI, bool cachedAlwaysFlowImpersonationPolicy)
+ {
+ Contract.Assert(currentEC.IsSame(Thread.CurrentThread.GetExecutionContextReader()));
+ Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy);
+
+ // NOTE: cachedAlwaysFlowImpersonationPolicy is a perf optimization to avoid always having to access a static variable here.
+ if (cachedAlwaysFlowImpersonationPolicy || prevEC.SecurityContext.WindowsIdentity != targetWI)
+ {
+ //
+ // Either we're always flowing, or the target WI was obtained from the current EC in the first place.
+ //
+ Contract.Assert(_alwaysFlowImpersonationPolicy || currentEC.SecurityContext.WindowsIdentity == targetWI);
+
+ RestoreCurrentWIInternal(targetWI);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ static private void RestoreCurrentWIInternal(WindowsIdentity targetWI)
+ {
+ int hr = Win32.RevertToSelf();
+ if (hr < 0)
+ Environment.FailFast(Win32Native.GetMessage(hr));
+
+ if (targetWI != null)
+ {
+ SafeAccessTokenHandle tokenHandle = targetWI.AccessToken;
+ if (tokenHandle != null && !tokenHandle.IsInvalid)
+ {
+ hr = Win32.ImpersonateLoggedOnUser(tokenHandle);
+ if (hr < 0)
+ Environment.FailFast(Win32Native.GetMessage(hr));
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool IsDefaultFTSecurityContext()
+ {
+ return (WindowsIdentity == null && (CompressedStack == null || CompressedStack.CompressedStackHandle == null));
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ static internal bool CurrentlyInDefaultFTSecurityContext(ExecutionContext.Reader threadEC)
+ {
+ return (IsDefaultThreadSecurityInfo() && GetCurrentWI(threadEC) == null);
+ }
+#else
+
+ internal bool IsDefaultFTSecurityContext()
+ {
+ return (CompressedStack == null || CompressedStack.CompressedStackHandle == null);
+ }
+ static internal bool CurrentlyInDefaultFTSecurityContext(ExecutionContext threadEC)
+ {
+ return (IsDefaultThreadSecurityInfo());
+ }
+#endif
+#if FEATURE_IMPERSONATION
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern static WindowsImpersonationFlowMode GetImpersonationFlowMode();
+#endif
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern static bool IsDefaultThreadSecurityInfo();
+
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+}
diff --git a/src/mscorlib/src/System/Security/SecurityElement.cs b/src/mscorlib/src/System/Security/SecurityElement.cs
new file mode 100644
index 0000000000..aa63029422
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityElement.cs
@@ -0,0 +1,929 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Security.Util;
+ using System.Text;
+ using System.Globalization;
+ using System.IO;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ internal enum SecurityElementType
+ {
+ Regular = 0,
+ Format = 1,
+ Comment = 2
+ }
+
+
+ internal interface ISecurityElementFactory
+ {
+ SecurityElement CreateSecurityElement();
+
+ Object Copy();
+
+ String GetTag();
+
+ String Attribute( String attributeName );
+ }
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ sealed public class SecurityElement : ISecurityElementFactory
+ {
+ internal String m_strTag;
+ internal String m_strText;
+ private ArrayList m_lChildren;
+ internal ArrayList m_lAttributes;
+ internal SecurityElementType m_type = SecurityElementType.Regular;
+
+ private static readonly char[] s_tagIllegalCharacters = new char[] { ' ', '<', '>' };
+ private static readonly char[] s_textIllegalCharacters = new char[] { '<', '>' };
+ private static readonly char[] s_valueIllegalCharacters = new char[] { '<', '>', '\"' };
+ private const String s_strIndent = " ";
+
+ private const int c_AttributesTypical = 4 * 2; // 4 attributes, times 2 strings per attribute
+ private const int c_ChildrenTypical = 1;
+
+ private static readonly String[] s_escapeStringPairs = new String[]
+ {
+ // these must be all once character escape sequences or a new escaping algorithm is needed
+ "<", "&lt;",
+ ">", "&gt;",
+ "\"", "&quot;",
+ "\'", "&apos;",
+ "&", "&amp;"
+ };
+
+ private static readonly char[] s_escapeChars = new char[] { '<', '>', '\"', '\'', '&' };
+
+ //-------------------------- Constructors ---------------------------
+
+ internal SecurityElement()
+ {
+ }
+
+////// ISecurityElementFactory implementation
+
+ SecurityElement ISecurityElementFactory.CreateSecurityElement()
+ {
+ return this;
+ }
+
+ String ISecurityElementFactory.GetTag()
+ {
+ return ((SecurityElement)this).Tag;
+ }
+
+ Object ISecurityElementFactory.Copy()
+ {
+ return ((SecurityElement)this).Copy();
+ }
+
+ String ISecurityElementFactory.Attribute( String attributeName )
+ {
+ return ((SecurityElement)this).Attribute( attributeName );
+ }
+
+//////////////
+
+#if FEATURE_CAS_POLICY
+ public static SecurityElement FromString( String xml )
+ {
+ if (xml == null)
+ throw new ArgumentNullException( "xml" );
+ Contract.EndContractBlock();
+
+ return new Parser( xml ).GetTopElement();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public SecurityElement( String tag )
+ {
+ if (tag == null)
+ throw new ArgumentNullException( "tag" );
+
+ if (!IsValidTag( tag ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) );
+ Contract.EndContractBlock();
+
+ m_strTag = tag;
+ m_strText = null;
+ }
+
+ public SecurityElement( String tag, String text )
+ {
+ if (tag == null)
+ throw new ArgumentNullException( "tag" );
+
+ if (!IsValidTag( tag ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), tag ) );
+
+ if (text != null && !IsValidText( text ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementText" ), text ) );
+ Contract.EndContractBlock();
+
+ m_strTag = tag;
+ m_strText = text;
+ }
+
+ //-------------------------- Properties -----------------------------
+
+ public String Tag
+ {
+ [Pure]
+ get
+ {
+ return m_strTag;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException( "Tag" );
+
+ if (!IsValidTag( value ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), value ) );
+ Contract.EndContractBlock();
+
+ m_strTag = value;
+ }
+ }
+
+ public Hashtable Attributes
+ {
+ get
+ {
+ if (m_lAttributes == null || m_lAttributes.Count == 0)
+ {
+ return null;
+ }
+ else
+ {
+ Hashtable hashtable = new Hashtable( m_lAttributes.Count/2 );
+
+ int iMax = m_lAttributes.Count;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ hashtable.Add( m_lAttributes[i], m_lAttributes[i+1]);
+ }
+
+ return hashtable;
+ }
+ }
+
+ set
+ {
+ if (value == null || value.Count == 0)
+ {
+ m_lAttributes = null;
+ }
+ else
+ {
+ ArrayList list = new ArrayList(value.Count);
+
+ System.Collections.IDictionaryEnumerator enumerator = (System.Collections.IDictionaryEnumerator)value.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ String attrName = (String)enumerator.Key;
+ String attrValue = (String)enumerator.Value;
+
+ if (!IsValidAttributeName( attrName ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementName" ), (String)enumerator.Current ) );
+
+ if (!IsValidAttributeValue( attrValue ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementValue" ), (String)enumerator.Value ) );
+
+ list.Add(attrName);
+ list.Add(attrValue);
+ }
+
+ m_lAttributes = list;
+ }
+ }
+ }
+
+ public String Text
+ {
+ get
+ {
+ return Unescape( m_strText );
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ m_strText = null;
+ }
+ else
+ {
+ if (!IsValidText( value ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementTag" ), value ) );
+
+ m_strText = value;
+ }
+ }
+ }
+
+ public ArrayList Children
+ {
+ get
+ {
+ ConvertSecurityElementFactories();
+ return m_lChildren;
+ }
+
+ set
+ {
+ if (value != null)
+ {
+ IEnumerator enumerator = value.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ if (enumerator.Current == null)
+ throw new ArgumentException( Environment.GetResourceString( "ArgumentNull_Child" ) );
+ }
+ }
+
+ m_lChildren = value;
+ }
+ }
+
+ internal void ConvertSecurityElementFactories()
+ {
+ if (m_lChildren == null)
+ return;
+
+ for (int i = 0; i < m_lChildren.Count; ++i)
+ {
+ ISecurityElementFactory iseFactory = m_lChildren[i] as ISecurityElementFactory;
+ if (iseFactory != null && !(m_lChildren[i] is SecurityElement))
+ m_lChildren[i] = iseFactory.CreateSecurityElement();
+ }
+ }
+
+ internal ArrayList InternalChildren
+ {
+ get
+ {
+ // Beware! This array list can contain SecurityElements and other ISecurityElementFactories.
+ // If you want to get a consistent SecurityElement view, call get_Children.
+ return m_lChildren;
+ }
+ }
+
+ //-------------------------- Public Methods -----------------------------
+
+ internal void AddAttributeSafe( String name, String value )
+ {
+ if (m_lAttributes == null)
+ {
+ m_lAttributes = new ArrayList( c_AttributesTypical );
+ }
+ else
+ {
+ int iMax = m_lAttributes.Count;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ String strAttrName = (String)m_lAttributes[i];
+
+ if (String.Equals(strAttrName, name))
+ throw new ArgumentException( Environment.GetResourceString( "Argument_AttributeNamesMustBeUnique" ) );
+ }
+ }
+
+ m_lAttributes.Add(name);
+ m_lAttributes.Add(value);
+ }
+
+ public void AddAttribute( String name, String value )
+ {
+ if (name == null)
+ throw new ArgumentNullException( "name" );
+
+ if (value == null)
+ throw new ArgumentNullException( "value" );
+
+ if (!IsValidAttributeName( name ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementName" ), name ) );
+
+ if (!IsValidAttributeValue( value ))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_InvalidElementValue" ), value ) );
+ Contract.EndContractBlock();
+
+ AddAttributeSafe( name, value );
+ }
+
+ public void AddChild( SecurityElement child )
+ {
+ if (child == null)
+ throw new ArgumentNullException( "child" );
+ Contract.EndContractBlock();
+
+ if (m_lChildren == null)
+ m_lChildren = new ArrayList( c_ChildrenTypical );
+
+ m_lChildren.Add( child );
+ }
+
+ internal void AddChild( ISecurityElementFactory child )
+ {
+ if (child == null)
+ throw new ArgumentNullException( "child" );
+ Contract.EndContractBlock();
+
+ if (m_lChildren == null)
+ m_lChildren = new ArrayList( c_ChildrenTypical );
+
+ m_lChildren.Add( child );
+ }
+
+ internal void AddChildNoDuplicates( ISecurityElementFactory child )
+ {
+ if (child == null)
+ throw new ArgumentNullException( "child" );
+ Contract.EndContractBlock();
+
+ if (m_lChildren == null)
+ {
+ m_lChildren = new ArrayList( c_ChildrenTypical );
+ m_lChildren.Add( child );
+ }
+ else
+ {
+ for (int i = 0; i < m_lChildren.Count; ++i)
+ {
+ if (m_lChildren[i] == child)
+ return;
+ }
+ m_lChildren.Add( child );
+ }
+ }
+
+ public bool Equal( SecurityElement other )
+ {
+ if (other == null)
+ return false;
+
+ // Check if the tags are the same
+ if (!String.Equals(m_strTag, other.m_strTag))
+ return false;
+
+ // Check if the text is the same
+ if (!String.Equals(m_strText, other.m_strText))
+ return false;
+
+ // Check if the attributes are the same and appear in the same
+ // order.
+
+ // Maybe we can get away by only checking the number of attributes
+ if (m_lAttributes == null || other.m_lAttributes == null)
+ {
+ if (m_lAttributes != other.m_lAttributes)
+ return false;
+ }
+ else
+ {
+ int iMax = m_lAttributes.Count;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ if (iMax != other.m_lAttributes.Count)
+ return false;
+
+ for (int i = 0; i < iMax; i++)
+ {
+ String lhs = (String)m_lAttributes[i];
+ String rhs = (String)other.m_lAttributes[i];
+
+ if (!String.Equals(lhs, rhs))
+ return false;
+ }
+ }
+
+ // Finally we must check the child and make sure they are
+ // equal and in the same order
+
+ // Maybe we can get away by only checking the number of children
+ if (m_lChildren == null || other.m_lChildren == null)
+ {
+ if (m_lChildren != other.m_lChildren)
+ return false;
+ }
+ else
+ {
+ if (m_lChildren.Count != other.m_lChildren.Count)
+ return false;
+
+ this.ConvertSecurityElementFactories();
+ other.ConvertSecurityElementFactories();
+
+ // Okay, we'll need to go through each one of them
+ IEnumerator lhs = m_lChildren.GetEnumerator();
+ IEnumerator rhs = other.m_lChildren.GetEnumerator();
+
+ SecurityElement e1, e2;
+ while (lhs.MoveNext())
+ {
+ rhs.MoveNext();
+ e1 = (SecurityElement)lhs.Current;
+ e2 = (SecurityElement)rhs.Current;
+ if (e1 == null || !e1.Equal(e2))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public SecurityElement Copy()
+ {
+ SecurityElement element = new SecurityElement( this.m_strTag, this.m_strText );
+ element.m_lChildren = this.m_lChildren == null ? null : new ArrayList( this.m_lChildren );
+ element.m_lAttributes = this.m_lAttributes == null ? null : new ArrayList(this.m_lAttributes);
+
+ return element;
+ }
+
+ [Pure]
+ public static bool IsValidTag( String tag )
+ {
+ if (tag == null)
+ return false;
+
+ return tag.IndexOfAny( s_tagIllegalCharacters ) == -1;
+ }
+
+ [Pure]
+ public static bool IsValidText( String text )
+ {
+ if (text == null)
+ return false;
+
+ return text.IndexOfAny( s_textIllegalCharacters ) == -1;
+ }
+
+ [Pure]
+ public static bool IsValidAttributeName( String name )
+ {
+ return IsValidTag( name );
+ }
+
+ [Pure]
+ public static bool IsValidAttributeValue( String value )
+ {
+ if (value == null)
+ return false;
+
+ return value.IndexOfAny( s_valueIllegalCharacters ) == -1;
+ }
+
+ private static String GetEscapeSequence( char c )
+ {
+ int iMax = s_escapeStringPairs.Length;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ String strEscSeq = s_escapeStringPairs[i];
+ String strEscValue = s_escapeStringPairs[i+1];
+
+ if (strEscSeq[0] == c)
+ return strEscValue;
+ }
+
+ Contract.Assert( false, "Unable to find escape sequence for this character" );
+ return c.ToString();
+ }
+
+ public static String Escape( String str )
+ {
+ if (str == null)
+ return null;
+
+ StringBuilder sb = null;
+
+ int strLen = str.Length;
+ int index; // Pointer into the string that indicates the location of the current '&' character
+ int newIndex = 0; // Pointer into the string that indicates the start index of the "remaining" string (that still needs to be processed).
+
+
+ do
+ {
+ index = str.IndexOfAny( s_escapeChars, newIndex );
+
+ if (index == -1)
+ {
+ if (sb == null)
+ return str;
+ else
+ {
+ sb.Append( str, newIndex, strLen - newIndex );
+ return sb.ToString();
+ }
+ }
+ else
+ {
+ if (sb == null)
+ sb = new StringBuilder();
+
+ sb.Append( str, newIndex, index - newIndex );
+ sb.Append( GetEscapeSequence( str[index] ) );
+
+ newIndex = ( index + 1 );
+ }
+ }
+ while (true);
+
+ // no normal exit is possible
+ }
+
+ private static String GetUnescapeSequence( String str, int index, out int newIndex )
+ {
+ int maxCompareLength = str.Length - index;
+
+ int iMax = s_escapeStringPairs.Length;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ String strEscSeq = s_escapeStringPairs[i];
+ String strEscValue = s_escapeStringPairs[i+1];
+
+ int length = strEscValue.Length;
+
+ if (length <= maxCompareLength && String.Compare( strEscValue, 0, str, index, length, StringComparison.Ordinal) == 0)
+ {
+ newIndex = index + strEscValue.Length;
+ return strEscSeq;
+ }
+ }
+
+ newIndex = index + 1;
+ return str[index].ToString();
+ }
+
+
+ private static String Unescape( String str )
+ {
+ if (str == null)
+ return null;
+
+ StringBuilder sb = null;
+
+ int strLen = str.Length;
+ int index; // Pointer into the string that indicates the location of the current '&' character
+ int newIndex = 0; // Pointer into the string that indicates the start index of the "remainging" string (that still needs to be processed).
+
+ do
+ {
+ index = str.IndexOf( '&', newIndex );
+
+ if (index == -1)
+ {
+ if (sb == null)
+ return str;
+ else
+ {
+ sb.Append( str, newIndex, strLen - newIndex );
+ return sb.ToString();
+ }
+ }
+ else
+ {
+ if (sb == null)
+ sb = new StringBuilder();
+
+ sb.Append(str, newIndex, index - newIndex);
+ sb.Append( GetUnescapeSequence( str, index, out newIndex ) ); // updates the newIndex too
+
+ }
+ }
+ while (true);
+
+ // C# reports a warning if I leave this in, but I still kinda want to just in case.
+ // Contract.Assert( false, "If you got here, the execution engine or compiler is really confused" );
+ // return str;
+ }
+
+ private delegate void ToStringHelperFunc( Object obj, String str );
+
+ private static void ToStringHelperStringBuilder( Object obj, String str )
+ {
+ ((StringBuilder)obj).Append( str );
+ }
+
+ private static void ToStringHelperStreamWriter( Object obj, String str )
+ {
+ ((StreamWriter)obj).Write( str );
+ }
+
+ public override String ToString ()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ ToString( "", sb, new ToStringHelperFunc( ToStringHelperStringBuilder ) );
+
+ return sb.ToString();
+ }
+
+ internal void ToWriter( StreamWriter writer )
+ {
+ ToString( "", writer, new ToStringHelperFunc( ToStringHelperStreamWriter ) );
+ }
+
+ private void ToString( String indent, Object obj, ToStringHelperFunc func )
+ {
+ // First add the indent
+
+ // func( obj, indent );
+
+ // Add in the opening bracket and the tag.
+
+ func( obj, "<" );
+
+ switch (m_type)
+ {
+ case SecurityElementType.Format:
+ func( obj, "?" );
+ break;
+
+ case SecurityElementType.Comment:
+ func( obj, "!" );
+ break;
+
+ default:
+ break;
+ }
+
+ func( obj, m_strTag );
+
+ // If there are any attributes, plop those in.
+
+ if (m_lAttributes != null && m_lAttributes.Count > 0)
+ {
+ func( obj, " " );
+
+ int iMax = m_lAttributes.Count;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ String strAttrName = (String)m_lAttributes[i];
+ String strAttrValue = (String)m_lAttributes[i+1];
+
+ func( obj, strAttrName );
+ func( obj, "=\"" );
+ func( obj, strAttrValue );
+ func( obj, "\"" );
+
+ if (i != m_lAttributes.Count - 2)
+ {
+ if (m_type == SecurityElementType.Regular)
+ {
+ func( obj, Environment.NewLine );
+ }
+ else
+ {
+ func( obj, " " );
+ }
+ }
+ }
+ }
+
+ if (m_strText == null && (m_lChildren == null || m_lChildren.Count == 0))
+ {
+ // If we are a single tag with no children, just add the end of tag text.
+
+ switch (m_type)
+ {
+ case SecurityElementType.Comment:
+ func( obj, ">" );
+ break;
+
+ case SecurityElementType.Format:
+ func( obj, " ?>" );
+ break;
+
+ default:
+ func( obj, "/>" );
+ break;
+ }
+ func( obj, Environment.NewLine );
+ }
+ else
+ {
+ // Close the current tag.
+
+ func( obj, ">" );
+
+ // Output the text
+
+ func( obj, m_strText );
+
+ // Output any children.
+
+ if (m_lChildren != null)
+ {
+ this.ConvertSecurityElementFactories();
+
+ func( obj, Environment.NewLine );
+
+ // String childIndent = indent + s_strIndent;
+
+ for (int i = 0; i < m_lChildren.Count; ++i)
+ {
+ ((SecurityElement)m_lChildren[i]).ToString( "", obj, func );
+ }
+
+ // In the case where we have children, the close tag will not be on the same line as the
+ // opening tag, so we need to indent.
+
+ // func( obj, indent );
+ }
+
+ // Output the closing tag
+
+ func( obj, "</" );
+ func( obj, m_strTag );
+ func( obj, ">" );
+ func( obj, Environment.NewLine );
+ }
+ }
+
+
+
+ public String Attribute( String name )
+ {
+ if (name == null)
+ throw new ArgumentNullException( "name" );
+ Contract.EndContractBlock();
+
+ // Note: we don't check for validity here because an
+ // if an invalid name is passed we simply won't find it.
+
+ if (m_lAttributes == null)
+ return null;
+
+ // Go through all the attribute and see if we know about
+ // the one we are asked for
+
+ int iMax = m_lAttributes.Count;
+ Contract.Assert( iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly" );
+
+ for (int i = 0; i < iMax; i += 2)
+ {
+ String strAttrName = (String)m_lAttributes[i];
+
+ if (String.Equals(strAttrName, name))
+ {
+ String strAttrValue = (String)m_lAttributes[i+1];
+
+ return Unescape(strAttrValue);
+ }
+ }
+
+ // In the case where we didn't find it, we are expected to
+ // return null
+ return null;
+ }
+
+ public SecurityElement SearchForChildByTag( String tag )
+ {
+ // Go through all the children and see if we can
+ // find the one are are asked for (matching tags)
+
+ if (tag == null)
+ throw new ArgumentNullException( "tag" );
+ Contract.EndContractBlock();
+
+ // Note: we don't check for a valid tag here because
+ // an invalid tag simply won't be found.
+
+ if (m_lChildren == null)
+ return null;
+
+ IEnumerator enumerator = m_lChildren.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ SecurityElement current = (SecurityElement)enumerator.Current;
+
+ if (current != null && String.Equals(current.Tag, tag))
+ return current;
+ }
+ return null;
+ }
+
+#if FEATURE_CAS_POLICY
+ internal IPermission ToPermission(bool ignoreTypeLoadFailures)
+ {
+ IPermission ip = XMLUtil.CreatePermission( this, PermissionState.None, ignoreTypeLoadFailures );
+ if (ip == null)
+ return null;
+ ip.FromXml(this);
+
+ // Get the permission token here to ensure that the token
+ // type is updated appropriately now that we've loaded the type.
+ PermissionToken token = PermissionToken.GetToken( ip );
+ Contract.Assert((token.m_type & PermissionTokenType.DontKnow) == 0, "Token type not properly assigned");
+
+ return ip;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object ToSecurityObject()
+ {
+ switch (m_strTag)
+ {
+ case "PermissionSet":
+ PermissionSet pset = new PermissionSet(PermissionState.None);
+ pset.FromXml(this);
+ return pset;
+
+ default:
+ return ToPermission(false);
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ internal String SearchForTextOfLocalName(String strLocalName)
+ {
+ // Search on each child in order and each
+ // child's child, depth-first
+
+ if (strLocalName == null)
+ throw new ArgumentNullException( "strLocalName" );
+ Contract.EndContractBlock();
+
+ // Note: we don't check for a valid tag here because
+ // an invalid tag simply won't be found.
+
+ // First we check this.
+
+ if (m_strTag == null) return null;
+ if (m_strTag.Equals( strLocalName ) || m_strTag.EndsWith( ":" + strLocalName, StringComparison.Ordinal ))
+ return Unescape( m_strText );
+ if (m_lChildren == null)
+ return null;
+
+ IEnumerator enumerator = m_lChildren.GetEnumerator();
+
+ while (enumerator.MoveNext())
+ {
+ String current = ((SecurityElement)enumerator.Current).SearchForTextOfLocalName( strLocalName );
+
+ if (current != null)
+ return current;
+ }
+ return null;
+ }
+
+ public String SearchForTextOfTag( String tag )
+ {
+ // Search on each child in order and each
+ // child's child, depth-first
+
+ if (tag == null)
+ throw new ArgumentNullException( "tag" );
+ Contract.EndContractBlock();
+
+ // Note: we don't check for a valid tag here because
+ // an invalid tag simply won't be found.
+
+ // First we check this.
+
+ if (String.Equals(m_strTag, tag))
+ return Unescape( m_strText );
+ if (m_lChildren == null)
+ return null;
+
+ IEnumerator enumerator = m_lChildren.GetEnumerator();
+
+ this.ConvertSecurityElementFactories();
+
+ while (enumerator.MoveNext())
+ {
+ String current = ((SecurityElement)enumerator.Current).SearchForTextOfTag( tag );
+
+ if (current != null)
+ return current;
+ }
+ return null;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/SecurityException.cs b/src/mscorlib/src/System/Security/SecurityException.cs
new file mode 100644
index 0000000000..9fbd8023d2
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityException.cs
@@ -0,0 +1,667 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+**
+**
+** Purpose: Exception class for security
+**
+**
+=============================================================================*/
+
+namespace System.Security
+{
+ using System.Security;
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Reflection;
+ using System.Text;
+ using System.Security.Policy;
+ using System.IO;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using System.Globalization;
+ using System.Security.Util;
+ using System.Diagnostics.Contracts;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SecurityException : SystemException
+ {
+#if FEATURE_CAS_POLICY
+ private String m_debugString; // NOTE: If you change the name of this field, you'll have to update SOS as well!
+ private SecurityAction m_action;
+ [NonSerialized] private Type m_typeOfPermissionThatFailed;
+ private String m_permissionThatFailed;
+ private String m_demanded;
+ private String m_granted;
+ private String m_refused;
+ private String m_denied;
+ private String m_permitOnly;
+ private AssemblyName m_assemblyName;
+ private byte[] m_serializedMethodInfo;
+ private String m_strMethodInfo;
+ private SecurityZone m_zone;
+ private String m_url;
+
+ private const String ActionName = "Action";
+ private const String FirstPermissionThatFailedName = "FirstPermissionThatFailed";
+ private const String DemandedName = "Demanded";
+ private const String GrantedSetName = "GrantedSet";
+ private const String RefusedSetName = "RefusedSet";
+ private const String DeniedName = "Denied";
+ private const String PermitOnlyName = "PermitOnly";
+ private const String Assembly_Name = "Assembly";
+ private const String MethodName_Serialized = "Method";
+ private const String MethodName_String = "Method_String";
+ private const String ZoneName = "Zone";
+ private const String UrlName = "Url";
+#endif // #if FEATURE_CAS_POLICY
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static string GetResString(string sResourceName)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ return Environment.GetResourceString(sResourceName);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#pragma warning disable 618
+ internal static Exception MakeSecurityException(AssemblyName asmName, Evidence asmEvidence, PermissionSet granted, PermissionSet refused, RuntimeMethodHandleInternal rmh, SecurityAction action, Object demand, IPermission permThatFailed)
+#pragma warning restore 618
+ {
+#if FEATURE_CAS_POLICY
+ // See if we need to throw a HostProtectionException instead
+ HostProtectionPermission hostProtectionPerm = permThatFailed as HostProtectionPermission;
+ if(hostProtectionPerm != null)
+ return new HostProtectionException(GetResString("HostProtection_HostProtection"), HostProtectionPermission.protectedResources, hostProtectionPerm.Resources);
+
+ // Produce relevant strings
+ String message = "";
+ MethodInfo method = null;
+ try
+ {
+ if(granted == null && refused == null && demand == null)
+ {
+ message = GetResString("Security_NoAPTCA");
+ }
+ else
+ {
+ if(demand != null && demand is IPermission)
+ message = String.Format(CultureInfo.InvariantCulture, GetResString("Security_Generic"), demand.GetType().AssemblyQualifiedName );
+ else if (permThatFailed != null)
+ message = String.Format(CultureInfo.InvariantCulture, GetResString("Security_Generic"), permThatFailed.GetType().AssemblyQualifiedName);
+ else
+ message = GetResString("Security_GenericNoType");
+ }
+
+ method = SecurityRuntime.GetMethodInfo(rmh);
+ }
+ catch(Exception e)
+ {
+ // Environment.GetResourceString will throw if we are ReadyForAbort (thread abort). (We shouldn't do a Contract.Assert in this case or it will lock up the thread.)
+ if(e is System.Threading.ThreadAbortException)
+ throw;
+ }
+
+/* catch(System.Threading.ThreadAbortException)
+ {
+ // Environment.GetResourceString will throw if we are ReadyForAbort (thread abort). (We shouldn't do a BCLDebug.Assert in this case or it will lock up the thread.)
+ throw;
+ }
+ catch
+ {
+ }
+*/
+ // make the exception object
+ return new SecurityException(message, asmName, granted, refused, method, action, demand, permThatFailed, asmEvidence);
+#else
+ return new SecurityException(GetResString("Arg_SecurityException"));
+#endif
+
+ }
+
+#if FEATURE_CAS_POLICY
+ private static byte[] ObjectToByteArray(Object obj)
+ {
+ if(obj == null)
+ return null;
+ MemoryStream stream = new MemoryStream();
+ BinaryFormatter formatter = new BinaryFormatter();
+ try {
+ formatter.Serialize(stream, obj);
+ byte[] array = stream.ToArray();
+ return array;
+ } catch (NotSupportedException) {
+ // Serialization of certain methods is not supported (namely
+ // global methods, since they have no representation outside of
+ // a module scope).
+ return null;
+ }
+ }
+
+ private static Object ByteArrayToObject(byte[] array)
+ {
+ if(array == null || array.Length == 0)
+ return null;
+ MemoryStream stream = new MemoryStream(array);
+ BinaryFormatter formatter = new BinaryFormatter();
+ Object obj = formatter.Deserialize(stream);
+ return obj;
+ }
+#endif // FEATURE_CAS_POLICY
+
+ public SecurityException()
+ : base(GetResString("Arg_SecurityException"))
+ {
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ }
+
+ public SecurityException(String message)
+ : base(message)
+ {
+ // This is the constructor that gets called if you Assert but don't have permission to Assert. (So don't assert in here.)
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecurityException(String message, Type type )
+ : base(message)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ m_typeOfPermissionThatFailed = type;
+ }
+
+ // *** Don't use this constructor internally ***
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecurityException(String message, Type type, String state )
+ : base(message)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ m_typeOfPermissionThatFailed = type;
+ m_demanded = state;
+ }
+#endif //FEATURE_CAS_POLICY
+
+ public SecurityException(String message, Exception inner)
+ : base(message, inner)
+ {
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ }
+
+#if FEATURE_CAS_POLICY
+ // *** Don't use this constructor internally ***
+ [System.Security.SecurityCritical] // auto-generated
+ internal SecurityException( PermissionSet grantedSetObj, PermissionSet refusedSetObj )
+ : base(GetResString("Arg_SecurityException"))
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ if (grantedSetObj != null)
+ m_granted = grantedSetObj.ToXml().ToString();
+ if (refusedSetObj != null)
+ m_refused = refusedSetObj.ToXml().ToString();
+ }
+
+ // *** Don't use this constructor internally ***
+ [System.Security.SecurityCritical] // auto-generated
+ internal SecurityException( String message, PermissionSet grantedSetObj, PermissionSet refusedSetObj )
+ : base(message)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ if (grantedSetObj != null)
+ m_granted = grantedSetObj.ToXml().ToString();
+ if (refusedSetObj != null)
+ m_refused = refusedSetObj.ToXml().ToString();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected SecurityException(SerializationInfo info, StreamingContext context) : base (info, context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ try
+ {
+ m_action = (SecurityAction)info.GetValue(ActionName, typeof(SecurityAction));
+ m_permissionThatFailed = (String)info.GetValueNoThrow(FirstPermissionThatFailedName, typeof(String));
+ m_demanded = (String)info.GetValueNoThrow(DemandedName, typeof(String));
+ m_granted = (String)info.GetValueNoThrow(GrantedSetName, typeof(String));
+ m_refused = (String)info.GetValueNoThrow(RefusedSetName, typeof(String));
+ m_denied = (String)info.GetValueNoThrow(DeniedName, typeof(String));
+ m_permitOnly = (String)info.GetValueNoThrow(PermitOnlyName, typeof(String));
+ m_assemblyName = (AssemblyName)info.GetValueNoThrow(Assembly_Name, typeof(AssemblyName));
+ m_serializedMethodInfo = (byte[])info.GetValueNoThrow(MethodName_Serialized, typeof(byte[]));
+ m_strMethodInfo = (String)info.GetValueNoThrow(MethodName_String, typeof(String));
+ m_zone = (SecurityZone)info.GetValue(ZoneName, typeof(SecurityZone));
+ m_url = (String)info.GetValueNoThrow(UrlName, typeof(String));
+ }
+ catch
+ {
+ m_action = 0;
+ m_permissionThatFailed = "";
+ m_demanded = "";
+ m_granted = "";
+ m_refused = "";
+ m_denied = "";
+ m_permitOnly = "";
+ m_assemblyName = null;
+ m_serializedMethodInfo = null;
+ m_strMethodInfo = null;
+ m_zone = SecurityZone.NoZone;
+ m_url = "";
+ }
+ }
+
+ // ------------------------------------------
+ // | For failures due to insufficient grant |
+ // ------------------------------------------
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecurityException(string message, AssemblyName assemblyName, PermissionSet grant, PermissionSet refused, MethodInfo method, SecurityAction action, Object demanded, IPermission permThatFailed, Evidence evidence)
+ : base(message)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ Action = action;
+ if(permThatFailed != null)
+ m_typeOfPermissionThatFailed = permThatFailed.GetType();
+ FirstPermissionThatFailed = permThatFailed;
+ Demanded = demanded;
+ m_granted = (grant == null ? "" : grant.ToXml().ToString());
+ m_refused = (refused == null ? "" : refused.ToXml().ToString());
+ m_denied = "";
+ m_permitOnly = "";
+ m_assemblyName = assemblyName;
+ Method = method;
+ m_url = "";
+ m_zone = SecurityZone.NoZone;
+ if(evidence != null)
+ {
+ Url url = evidence.GetHostEvidence<Url>();
+ if(url != null)
+ m_url = url.GetURLString().ToString();
+ Zone zone = evidence.GetHostEvidence<Zone>();
+ if(zone != null)
+ m_zone = zone.SecurityZone;
+ }
+ m_debugString = this.ToString(true, false);
+ }
+
+ // ------------------------------------------
+ // | For failures due to deny or PermitOnly |
+ // ------------------------------------------
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecurityException(string message, Object deny, Object permitOnly, MethodInfo method, Object demanded, IPermission permThatFailed)
+ : base(message)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ SetErrorCode(System.__HResults.COR_E_SECURITY);
+ Action = SecurityAction.Demand;
+ if(permThatFailed != null)
+ m_typeOfPermissionThatFailed = permThatFailed.GetType();
+ FirstPermissionThatFailed = permThatFailed;
+ Demanded = demanded;
+ m_granted = "";
+ m_refused = "";
+ DenySetInstance = deny;
+ PermitOnlySetInstance = permitOnly;
+ m_assemblyName = null;
+ Method = method;
+ m_zone = SecurityZone.NoZone;
+ m_url = "";
+ m_debugString = this.ToString(true, false);
+ }
+
+
+
+
+
+
+
+
+
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public SecurityAction Action
+ {
+ get
+ {
+ return m_action;
+ }
+
+ set
+ {
+ m_action = value;
+ }
+ }
+
+ public Type PermissionType
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if(m_typeOfPermissionThatFailed == null)
+ {
+ Object ob = XMLUtil.XmlStringToSecurityObject(m_permissionThatFailed);
+ if(ob == null)
+ ob = XMLUtil.XmlStringToSecurityObject(m_demanded);
+ if(ob != null)
+ m_typeOfPermissionThatFailed = ob.GetType();
+ }
+ return m_typeOfPermissionThatFailed;
+ }
+
+ set
+ {
+ m_typeOfPermissionThatFailed = value;
+ }
+ }
+
+ public IPermission FirstPermissionThatFailed
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return (IPermission)XMLUtil.XmlStringToSecurityObject(m_permissionThatFailed);
+ }
+
+ set
+ {
+ m_permissionThatFailed = XMLUtil.SecurityObjectToXmlString(value);
+ }
+ }
+
+ public String PermissionState
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return m_demanded;
+ }
+
+ set
+ {
+ m_demanded = value;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public Object Demanded
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return XMLUtil.XmlStringToSecurityObject(m_demanded);
+ }
+
+ set
+ {
+ m_demanded = XMLUtil.SecurityObjectToXmlString(value);
+ }
+ }
+
+ public String GrantedSet
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return m_granted;
+ }
+
+ set
+ {
+ m_granted = value;
+ }
+ }
+
+ public String RefusedSet
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return m_refused;
+ }
+
+ set
+ {
+ m_refused = value;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public Object DenySetInstance
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return XMLUtil.XmlStringToSecurityObject(m_denied);
+ }
+
+ set
+ {
+ m_denied = XMLUtil.SecurityObjectToXmlString(value);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public Object PermitOnlySetInstance
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return XMLUtil.XmlStringToSecurityObject(m_permitOnly);
+ }
+
+ set
+ {
+ m_permitOnly = XMLUtil.SecurityObjectToXmlString(value);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public AssemblyName FailedAssemblyInfo
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return m_assemblyName;
+ }
+
+ set
+ {
+ m_assemblyName = value;
+ }
+ }
+
+ private MethodInfo getMethod()
+ {
+ return (MethodInfo)ByteArrayToObject(m_serializedMethodInfo);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public MethodInfo Method
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return getMethod();
+ }
+
+ set
+ {
+ RuntimeMethodInfo m = value as RuntimeMethodInfo;
+ m_serializedMethodInfo = ObjectToByteArray(m);
+ if (m != null)
+ {
+ m_strMethodInfo = m.ToString();
+ }
+ }
+ }
+
+ public SecurityZone Zone
+ {
+ get
+ {
+ return m_zone;
+ }
+
+ set
+ {
+ m_zone = value;
+ }
+ }
+
+ public String Url
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy)]
+ get
+ {
+ return m_url;
+ }
+
+ set
+ {
+ m_url = value;
+ }
+ }
+
+ private void ToStringHelper(StringBuilder sb, String resourceString, Object attr)
+ {
+ if (attr == null)
+ return;
+ String attrString = attr as String;
+ if (attrString == null)
+ attrString = attr.ToString();
+ if (attrString.Length == 0)
+ return;
+ sb.Append(Environment.NewLine);
+ sb.Append(GetResString(resourceString));
+ sb.Append(Environment.NewLine);
+ sb.Append(attrString);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private String ToString(bool includeSensitiveInfo, bool includeBaseInfo)
+ {
+ PermissionSet.s_fullTrust.Assert();
+ StringBuilder sb = new StringBuilder();
+
+ if(includeBaseInfo)
+ sb.Append(base.ToString());
+ if(Action > 0)
+ ToStringHelper(sb, "Security_Action", Action);
+ ToStringHelper(sb, "Security_TypeFirstPermThatFailed", PermissionType);
+ if(includeSensitiveInfo)
+ {
+ ToStringHelper(sb, "Security_FirstPermThatFailed", m_permissionThatFailed);
+ ToStringHelper(sb, "Security_Demanded", m_demanded);
+ ToStringHelper(sb, "Security_GrantedSet", m_granted);
+ ToStringHelper(sb, "Security_RefusedSet", m_refused);
+ ToStringHelper(sb, "Security_Denied", m_denied);
+ ToStringHelper(sb, "Security_PermitOnly", m_permitOnly);
+ ToStringHelper(sb, "Security_Assembly", m_assemblyName);
+ ToStringHelper(sb, "Security_Method", m_strMethodInfo);
+ }
+ if(m_zone != SecurityZone.NoZone)
+ ToStringHelper(sb, "Security_Zone", m_zone);
+ if(includeSensitiveInfo)
+ ToStringHelper(sb, "Security_Url", m_url);
+ return sb.ToString();
+ }
+#else // FEATURE_CAS_POLICY
+ internal SecurityException( PermissionSet grantedSetObj, PermissionSet refusedSetObj )
+ : this(){}
+#pragma warning disable 618
+ internal SecurityException(string message, AssemblyName assemblyName, PermissionSet grant, PermissionSet refused, MethodInfo method, SecurityAction action, Object demanded, IPermission permThatFailed, Evidence evidence)
+#pragma warning restore 618
+ : this(){}
+
+ internal SecurityException(string message, Object deny, Object permitOnly, MethodInfo method, Object demanded, IPermission permThatFailed)
+ : this(){}
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected SecurityException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+ }
+
+ public override String ToString()
+ {
+ return base.ToString();
+ }
+
+#endif // FEATURE_CAS_POLICY
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool CanAccessSensitiveInfo()
+ {
+ bool retVal = false;
+ try
+ {
+#pragma warning disable 618
+ new SecurityPermission(SecurityPermissionFlag.ControlEvidence | SecurityPermissionFlag.ControlPolicy).Demand();
+#pragma warning restore 618
+ retVal = true;
+ }
+ catch(SecurityException)
+ {
+ }
+ return retVal;
+ }
+#if FEATURE_CAS_POLICY
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString()
+ {
+ return ToString(CanAccessSensitiveInfo(), true);
+ }
+#endif //FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ base.GetObjectData( info, context );
+#if FEATURE_CAS_POLICY
+
+ info.AddValue(ActionName, m_action, typeof(SecurityAction));
+ info.AddValue(FirstPermissionThatFailedName, m_permissionThatFailed, typeof(String));
+ info.AddValue(DemandedName, m_demanded, typeof(String));
+ info.AddValue(GrantedSetName, m_granted, typeof(String));
+ info.AddValue(RefusedSetName, m_refused, typeof(String));
+ info.AddValue(DeniedName, m_denied, typeof(String));
+ info.AddValue(PermitOnlyName, m_permitOnly, typeof(String));
+ info.AddValue(Assembly_Name, m_assemblyName, typeof(AssemblyName));
+ info.AddValue(MethodName_Serialized, m_serializedMethodInfo, typeof(byte[]));
+ info.AddValue(MethodName_String, m_strMethodInfo, typeof(String));
+ info.AddValue(ZoneName, m_zone, typeof(SecurityZone));
+ info.AddValue(UrlName, m_url, typeof(String));
+#endif // FEATURE_CAS_POLICY
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/SecurityManager.cs b/src/mscorlib/src/System/Security/SecurityManager.cs
new file mode 100644
index 0000000000..5c46dfcbfc
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityManager.cs
@@ -0,0 +1,671 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+//
+//
+// The SecurityManager class provides a general purpose API for interacting
+// with the security system.
+//
+
+namespace System.Security {
+ using System;
+ using System.Security.Util;
+ using System.Security.Policy;
+ using System.Security.Permissions;
+ using System.Collections;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+#if FEATURE_CLICKONCE
+ using System.Runtime.Hosting;
+#endif // FEATURE_CLICKONCE
+ using System.Text;
+ using System.Threading;
+ using System.Reflection;
+ using System.IO;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum PolicyLevelType
+ {
+ User = 0,
+ Machine = 1,
+ Enterprise = 2,
+ AppDomain = 3
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ static public class SecurityManager {
+#if FEATURE_CAS_POLICY
+ private static volatile SecurityPermission executionSecurityPermission = null;
+
+ private static PolicyManager polmgr = new PolicyManager();
+ internal static PolicyManager PolicyManager {
+ get {
+ return polmgr;
+ }
+ }
+
+ //
+ // Public APIs
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [Obsolete("IsGranted is obsolete and will be removed in a future release of the .NET Framework. Please use the PermissionSet property of either AppDomain or Assembly instead.")]
+ public static bool IsGranted( IPermission perm )
+ {
+ if (perm == null)
+ return true;
+
+ PermissionSet granted = null, denied = null;
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ GetGrantedPermissions( JitHelpers.GetObjectHandleOnStack(ref granted),
+ JitHelpers.GetObjectHandleOnStack(ref denied),
+ JitHelpers.GetStackCrawlMarkHandle(ref stackMark) );
+ return granted.Contains( perm ) && (denied == null || !denied.Contains( perm ));
+ }
+
+ // Get a sandbox permission set that the CLR considers safe to grant an application with the given
+ // evidence. Note that this API is not a policy API, but rather a host helper API so that a host can
+ // determine if an application's requested permission set is reasonable. This is esentially just a
+ // hard coded mapping of Zone -> Sandbox and is not configurable in any way.
+ public static PermissionSet GetStandardSandbox(Evidence evidence)
+ {
+ if (evidence == null)
+ throw new ArgumentNullException("evidence");
+ Contract.EndContractBlock();
+
+ //
+ // The top-level switch for grant set is based upon Zone
+ // MyComputer -> FullTrust
+ // Intranet -> LocalIntranet
+ // Trusted -> Internet
+ // Internet -> Internet
+ // All else -> Nothing
+ //
+ // Both the Internet and LocalIntranet zones can have permission set extensions applied to them
+ // if there is Activation.
+ //
+
+ Zone zone = evidence.GetHostEvidence<Zone>();
+ if (zone == null)
+ {
+ return new PermissionSet(PermissionState.None);
+ }
+#if FEATURE_CAS_POLICY
+ else if (zone.SecurityZone == SecurityZone.MyComputer)
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+ else if (zone.SecurityZone == SecurityZone.Intranet)
+ {
+ PermissionSet intranetGrantSet = BuiltInPermissionSets.LocalIntranet;
+
+ // We also need to add in same site web and file IO permission
+ PolicyStatement webPolicy =
+ new NetCodeGroup(new AllMembershipCondition()).Resolve(evidence);
+ PolicyStatement filePolicy =
+ new FileCodeGroup(new AllMembershipCondition(), FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery).Resolve(evidence);
+
+ if (webPolicy != null)
+ {
+ intranetGrantSet.InplaceUnion(webPolicy.PermissionSet);
+ }
+ if (filePolicy != null)
+ {
+ intranetGrantSet.InplaceUnion(filePolicy.PermissionSet);
+ }
+
+ return intranetGrantSet;
+ }
+ else if (zone.SecurityZone == SecurityZone.Internet ||
+ zone.SecurityZone == SecurityZone.Trusted)
+ {
+ PermissionSet internetGrantSet = BuiltInPermissionSets.Internet;
+
+ // We also need to add in same site web permission
+ PolicyStatement webPolicy =
+ new NetCodeGroup(new AllMembershipCondition()).Resolve(evidence);
+
+ if (webPolicy != null)
+ {
+ internetGrantSet.InplaceUnion(webPolicy.PermissionSet);
+ }
+
+ return internetGrantSet;
+ }
+#endif // FEATURE_CAS_POLICY
+ else
+ {
+ return new PermissionSet(PermissionState.None);
+ }
+ }
+
+ /// <internalonly/>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ static public void GetZoneAndOrigin( out ArrayList zone, out ArrayList origin )
+ {
+ StackCrawlMark mark = StackCrawlMark.LookForMyCaller;
+ CodeAccessSecurityEngine.GetZoneAndOrigin( ref mark, out zone, out origin );
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )]
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public PolicyLevel LoadPolicyLevelFromFile(string path, PolicyLevelType type)
+ {
+ if (path == null)
+ throw new ArgumentNullException( "path" );
+ Contract.EndContractBlock();
+
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ // We need to retain V1.x compatibility by throwing the same exception type.
+ if (!File.InternalExists(path))
+ throw new ArgumentException( Environment.GetResourceString("Argument_PolicyFileDoesNotExist"));
+
+ String fullPath = Path.GetFullPath( path );
+
+ FileIOPermission perm = new FileIOPermission( PermissionState.None );
+ perm.AddPathList( FileIOPermissionAccess.Read, fullPath );
+ perm.AddPathList( FileIOPermissionAccess.Write, fullPath );
+ perm.Demand();
+
+ using (FileStream stream = new FileStream(path, FileMode.Open, FileAccess.Read)) {
+ using (StreamReader reader = new StreamReader(stream)) {
+ return LoadPolicyLevelFromStringHelper(reader.ReadToEnd(), path, type);
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )]
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public PolicyLevel LoadPolicyLevelFromString(string str, PolicyLevelType type)
+ {
+ return LoadPolicyLevelFromStringHelper(str, null, type);
+ }
+
+ private static PolicyLevel LoadPolicyLevelFromStringHelper (string str, string path, PolicyLevelType type)
+ {
+ if (str == null)
+ throw new ArgumentNullException( "str" );
+ Contract.EndContractBlock();
+
+ PolicyLevel level = new PolicyLevel(type, path);
+
+ Parser parser = new Parser( str );
+ SecurityElement elRoot = parser.GetTopElement();
+ if (elRoot == null)
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "configuration" ) );
+
+ SecurityElement elMscorlib = elRoot.SearchForChildByTag( "mscorlib" );
+ if (elMscorlib == null)
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "mscorlib" ) );
+
+ SecurityElement elSecurity = elMscorlib.SearchForChildByTag( "security" );
+ if (elSecurity == null)
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "security" ) );
+
+ SecurityElement elPolicy = elSecurity.SearchForChildByTag( "policy" );
+ if (elPolicy == null)
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "policy" ) );
+
+ SecurityElement elPolicyLevel = elPolicy.SearchForChildByTag( "PolicyLevel" );
+ if (elPolicyLevel != null)
+ level.FromXml( elPolicyLevel );
+ else
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Policy_BadXml" ), "PolicyLevel" ) );
+
+ return level;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )]
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public void SavePolicyLevel( PolicyLevel level )
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ PolicyManager.EncodeLevel( level );
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public PermissionSet ResolvePolicy(Evidence evidence,
+ PermissionSet reqdPset,
+ PermissionSet optPset,
+ PermissionSet denyPset,
+ out PermissionSet denied)
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ return ResolvePolicy(evidence, reqdPset, optPset, denyPset, out denied, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public PermissionSet ResolvePolicy(Evidence evidence)
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ // If we aren't passed any evidence, just make an empty object
+ if (evidence == null)
+ {
+ evidence = new Evidence();
+ }
+
+ return polmgr.Resolve(evidence);
+ }
+
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public PermissionSet ResolvePolicy( Evidence[] evidences )
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ if (evidences == null || evidences.Length == 0)
+ evidences = new Evidence[] { null };
+
+ PermissionSet retval = ResolvePolicy( evidences[0] );
+ if (retval == null)
+ return null;
+
+ for (int i = 1; i < evidences.Length; ++i)
+ {
+ retval = retval.Intersect( ResolvePolicy( evidences[i] ) );
+ if (retval == null || retval.IsEmpty())
+ return retval;
+ }
+
+ return retval;
+ }
+
+#if FEATURE_CAS_POLICY
+ // Determine if the current thread would require a security context capture if the security state of
+ // the thread needs to be re-created at a later point in time. This can be used, for instance, if
+ // sensitive data is being obtained after security demands succeed, and that data is to be cached.
+ // If there is an Assert up the stack, then we wouldn't want to cache the data without capturing the
+ // corresponding security context to go along with it - otherwise we risk leaking data obtained
+ // under an assert to code which may no longer be running with that assert in place.
+ //
+ // A return value of false indicates that the CLR guarantees all of the following conditions are true:
+ // 1. No partial trust AppDomains are on the stack
+ // 2. No partial trust assemblies are on the stack
+ // 3. There are no currently active PermitOnly or Deny modifiers on the stack
+ //
+ // A return value of true means only that the CLR cannot guarantee that all of the conditions are
+ // true, and not that one of the conditions really is false.
+ //
+ // IMPORTANT: The above means is only reliable in the false return case. If we say that the thread
+ // does not require a context capture, then that answer is guaranteed to be correct. However, we may
+ // say that the thread does require a capture when it does not actually strictly need to capture the
+ // state. This is fine, as being overly conservative when capturing context will not lead to
+ // security holes; being overly agresssive in avoding the capture could lead to holes however.
+ //
+ // This API is SecurityCritical because its main use is to optimize away unnecessary security
+ // context captures, which means that the code using it is security sensitive and needs to be audited.
+ [SecurityCritical]
+ public static bool CurrentThreadRequiresSecurityContextCapture()
+ {
+ // If we know that the thread is not made up of entirely full trust code, and that there are no
+ // security stack modifiers on the thread, then there is no need to capture a security context.
+ return !CodeAccessSecurityEngine.QuickCheckForAllDemands();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ //
+ // This method resolves the policy for the specified evidence, but it
+ // ignores the AppDomain level even when one is available in the current policy.
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static PermissionSet ResolveSystemPolicy (Evidence evidence)
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ if (PolicyManager.IsGacAssembly(evidence))
+ {
+ return new PermissionSet(PermissionState.Unrestricted);
+ }
+
+ return polmgr.CodeGroupResolve(evidence, true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ static public IEnumerator ResolvePolicyGroups(Evidence evidence)
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ return polmgr.ResolveCodeGroups(evidence);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static IEnumerator PolicyHierarchy()
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ return polmgr.PolicyHierarchy();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy )]
+ [Obsolete("This method is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
+ public static void SavePolicy()
+ {
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_RequiresCasPolicyExplicit"));
+ }
+
+ polmgr.Save();
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static PermissionSet ResolveCasPolicy(Evidence evidence,
+ PermissionSet reqdPset,
+ PermissionSet optPset,
+ PermissionSet denyPset,
+ out PermissionSet denied,
+ out int securitySpecialFlags,
+ bool checkExecutionPermission)
+ {
+ Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled);
+
+ CodeAccessPermission.Assert(true);
+
+ PermissionSet granted = ResolvePolicy(evidence,
+ reqdPset,
+ optPset,
+ denyPset,
+ out denied,
+ checkExecutionPermission);
+
+ securitySpecialFlags = SecurityManager.GetSpecialFlags(granted, denied);
+ return granted;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private PermissionSet ResolvePolicy(Evidence evidence,
+ PermissionSet reqdPset,
+ PermissionSet optPset,
+ PermissionSet denyPset,
+ out PermissionSet denied,
+ bool checkExecutionPermission)
+ {
+ Contract.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled);
+
+ if (executionSecurityPermission == null)
+ executionSecurityPermission = new SecurityPermission(SecurityPermissionFlag.Execution);
+
+ PermissionSet requested = null;
+ PermissionSet optional;
+ PermissionSet allowed;
+
+ Exception savedException = null;
+
+ // We don't want to recurse back into here as a result of a
+ // stackwalk during resolution. So simply assert full trust (this
+ // implies that custom permissions cannot use any permissions that
+ // don't implement IUnrestrictedPermission.
+ // PermissionSet.s_fullTrust.Assert();
+
+ // The requested set is the union of the minimal request and the
+ // optional request. Minimal request defaults to empty, optional
+ // is "AllPossible" (includes any permission that can be defined)
+ // which is symbolized by null.
+ optional = optPset;
+
+ if (reqdPset == null)
+ requested = optional;
+ else
+ // If optional is null, the requested set becomes null/"AllPossible".
+ requested = optional == null ? null : reqdPset.Union(optional);
+
+ // Make sure that the right to execute is requested (if this feature is
+ // enabled).
+
+ if (requested != null && !requested.IsUnrestricted())
+ requested.AddPermission( executionSecurityPermission );
+
+ // If we aren't passed any evidence, just make an empty object
+ if (evidence == null)
+ {
+ evidence = new Evidence();
+ }
+
+ allowed = polmgr.Resolve(evidence);
+ // Intersect the grant with the RequestOptional
+ if (requested != null)
+ allowed.InplaceIntersect(requested);
+
+ // Check that we were granted the right to execute.
+ if (checkExecutionPermission)
+ {
+ if (!allowed.Contains(executionSecurityPermission) ||
+ (denyPset != null && denyPset.Contains(executionSecurityPermission)))
+ {
+ throw new PolicyException(Environment.GetResourceString("Policy_NoExecutionPermission"),
+ System.__HResults.CORSEC_E_NO_EXEC_PERM,
+ savedException);
+ }
+ }
+
+ // Check that we were granted at least the minimal set we asked for. Do
+ // this before pruning away any overlap with the refused set so that
+ // users have the flexability of defining minimal permissions that are
+ // only expressable as set differences (e.g. allow access to "C:\" but
+ // disallow "C:\Windows").
+ if (reqdPset != null && !reqdPset.IsSubsetOf(allowed))
+ {
+ BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Evaluating assembly level declarative security without legacy CAS policy enabled");
+ throw new PolicyException(Environment.GetResourceString( "Policy_NoRequiredPermission" ),
+ System.__HResults.CORSEC_E_MIN_GRANT_FAIL,
+ savedException );
+ }
+
+ // Remove any granted permissions that are safe subsets of some denied
+ // permission. The remaining denied permissions (if any) are returned
+ // along with the modified grant set for use in checks.
+ if (denyPset != null)
+ {
+ BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Evaluating assembly level declarative security without legacy CAS policy enabled");
+ denied = denyPset.Copy();
+ allowed.MergeDeniedSet(denied);
+ if (denied.IsEmpty())
+ denied = null;
+ }
+ else
+ denied = null;
+
+ allowed.IgnoreTypeLoadFailures = true;
+
+ return allowed;
+ }
+
+ [Obsolete("Because execution permission checks can no longer be turned off, the CheckExecutionRights property no longer has any effect.")]
+ static public bool CheckExecutionRights
+ {
+ get { return true; }
+
+ set
+ {
+ // The setter for this property is a no-op since execution checking can no longer be turned off
+ }
+ }
+
+ [Obsolete("Because security can no longer be turned off, the SecurityEnabled property no longer has any effect.")]
+ public static bool SecurityEnabled
+ {
+ get { return true; }
+
+ set
+ {
+ // The setter for this property is a no-op since security cannot be turned off
+ }
+ }
+#endif // #if FEATURE_CAS_POLICY
+
+ private static int[][] s_BuiltInPermissionIndexMap = {
+ new int[] { BuiltInPermissionIndex.EnvironmentPermissionIndex, (int) PermissionType.EnvironmentPermission },
+ new int[] { BuiltInPermissionIndex.FileDialogPermissionIndex, (int) PermissionType.FileDialogPermission },
+ new int[] { BuiltInPermissionIndex.FileIOPermissionIndex, (int) PermissionType.FileIOPermission },
+ new int[] { BuiltInPermissionIndex.ReflectionPermissionIndex, (int) PermissionType.ReflectionPermission },
+ new int[] { BuiltInPermissionIndex.SecurityPermissionIndex, (int) PermissionType.SecurityPermission },
+ new int[] { BuiltInPermissionIndex.UIPermissionIndex, (int) PermissionType.UIPermission }
+ };
+
+ private static CodeAccessPermission[] s_UnrestrictedSpecialPermissionMap = {
+ new EnvironmentPermission(PermissionState.Unrestricted),
+ new FileDialogPermission(PermissionState.Unrestricted),
+ new FileIOPermission(PermissionState.Unrestricted),
+ new ReflectionPermission(PermissionState.Unrestricted),
+ new SecurityPermission(PermissionState.Unrestricted),
+ new UIPermission(PermissionState.Unrestricted)
+ };
+
+ internal static int GetSpecialFlags (PermissionSet grantSet, PermissionSet deniedSet) {
+ if ((grantSet != null && grantSet.IsUnrestricted()) && (deniedSet == null || deniedSet.IsEmpty())) {
+ return -1;
+ }
+ else {
+ SecurityPermission securityPermission = null;
+#pragma warning disable 618
+ SecurityPermissionFlag securityPermissionFlags = SecurityPermissionFlag.NoFlags;
+#pragma warning restore 618
+ ReflectionPermission reflectionPermission = null;
+ ReflectionPermissionFlag reflectionPermissionFlags = ReflectionPermissionFlag.NoFlags;
+
+ CodeAccessPermission[] specialPermissions = new CodeAccessPermission[6];
+ if (grantSet != null) {
+ if (grantSet.IsUnrestricted()) {
+#pragma warning disable 618
+ securityPermissionFlags = SecurityPermissionFlag.AllFlags;
+#pragma warning restore 618
+ reflectionPermissionFlags = ReflectionPermission.AllFlagsAndMore;
+ for (int i = 0; i < specialPermissions.Length; i++) {
+ specialPermissions[i] = s_UnrestrictedSpecialPermissionMap[i];
+ }
+ }
+ else {
+ securityPermission = grantSet.GetPermission(BuiltInPermissionIndex.SecurityPermissionIndex) as SecurityPermission;
+ if (securityPermission != null)
+ securityPermissionFlags = securityPermission.Flags;
+ reflectionPermission = grantSet.GetPermission(BuiltInPermissionIndex.ReflectionPermissionIndex) as ReflectionPermission;
+ if (reflectionPermission != null)
+ reflectionPermissionFlags = reflectionPermission.Flags;
+ for (int i = 0; i < specialPermissions.Length; i++) {
+ specialPermissions[i] = grantSet.GetPermission(s_BuiltInPermissionIndexMap[i][0]) as CodeAccessPermission;
+ }
+ }
+ }
+
+ if (deniedSet != null) {
+ if (deniedSet.IsUnrestricted()) {
+#pragma warning disable 618
+ securityPermissionFlags = SecurityPermissionFlag.NoFlags;
+#pragma warning restore 618
+ reflectionPermissionFlags = ReflectionPermissionFlag.NoFlags;
+ for (int i = 0; i < s_BuiltInPermissionIndexMap.Length; i++) {
+ specialPermissions[i] = null;
+ }
+ }
+ else {
+ securityPermission = deniedSet.GetPermission(BuiltInPermissionIndex.SecurityPermissionIndex) as SecurityPermission;
+ if (securityPermission != null)
+ securityPermissionFlags &= ~securityPermission.Flags;
+ reflectionPermission = deniedSet.GetPermission(BuiltInPermissionIndex.ReflectionPermissionIndex) as ReflectionPermission;
+ if (reflectionPermission != null)
+ reflectionPermissionFlags &= ~reflectionPermission.Flags;
+ for (int i = 0; i < s_BuiltInPermissionIndexMap.Length; i++) {
+ CodeAccessPermission deniedSpecialPermission = deniedSet.GetPermission(s_BuiltInPermissionIndexMap[i][0]) as CodeAccessPermission;
+ if (deniedSpecialPermission != null && !deniedSpecialPermission.IsSubsetOf(null))
+ specialPermissions[i] = null; // we don't care about the exact value here.
+ }
+ }
+ }
+ int flags = MapToSpecialFlags(securityPermissionFlags, reflectionPermissionFlags);
+ if (flags != -1) {
+ for (int i = 0; i < specialPermissions.Length; i++) {
+ if (specialPermissions[i] != null && ((IUnrestrictedPermission) specialPermissions[i]).IsUnrestricted())
+ flags |= (1 << (int) s_BuiltInPermissionIndexMap[i][1]);
+ }
+ }
+ return flags;
+ }
+ }
+
+#pragma warning disable 618
+ private static int MapToSpecialFlags (SecurityPermissionFlag securityPermissionFlags, ReflectionPermissionFlag reflectionPermissionFlags) {
+ int flags = 0;
+ if ((securityPermissionFlags & SecurityPermissionFlag.UnmanagedCode) == SecurityPermissionFlag.UnmanagedCode)
+ flags |= (1 << (int) PermissionType.SecurityUnmngdCodeAccess);
+ if ((securityPermissionFlags & SecurityPermissionFlag.SkipVerification) == SecurityPermissionFlag.SkipVerification)
+ flags |= (1 << (int) PermissionType.SecuritySkipVerification);
+ if ((securityPermissionFlags & SecurityPermissionFlag.Assertion) == SecurityPermissionFlag.Assertion)
+ flags |= (1 << (int) PermissionType.SecurityAssert);
+ if ((securityPermissionFlags & SecurityPermissionFlag.SerializationFormatter) == SecurityPermissionFlag.SerializationFormatter)
+ flags |= (1 << (int) PermissionType.SecuritySerialization);
+ if ((securityPermissionFlags & SecurityPermissionFlag.BindingRedirects) == SecurityPermissionFlag.BindingRedirects)
+ flags |= (1 << (int) PermissionType.SecurityBindingRedirects);
+ if ((securityPermissionFlags & SecurityPermissionFlag.ControlEvidence) == SecurityPermissionFlag.ControlEvidence)
+ flags |= (1 << (int) PermissionType.SecurityControlEvidence);
+ if ((securityPermissionFlags & SecurityPermissionFlag.ControlPrincipal) == SecurityPermissionFlag.ControlPrincipal)
+ flags |= (1 << (int) PermissionType.SecurityControlPrincipal);
+
+ if ((reflectionPermissionFlags & ReflectionPermissionFlag.RestrictedMemberAccess) == ReflectionPermissionFlag.RestrictedMemberAccess)
+ flags |= (1 << (int)PermissionType.ReflectionRestrictedMemberAccess);
+ if ((reflectionPermissionFlags & ReflectionPermissionFlag.MemberAccess) == ReflectionPermissionFlag.MemberAccess)
+ flags |= (1 << (int) PermissionType.ReflectionMemberAccess);
+
+ return flags;
+ }
+#pragma warning restore 618
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern bool IsSameType(String strLeft, String strRight);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool _SetThreadSecurity(bool bThreadSecurity);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void GetGrantedPermissions(ObjectHandleOnStack retGranted, ObjectHandleOnStack retDenied, StackCrawlMarkHandle stackMark);
+ }
+}
diff --git a/src/mscorlib/src/System/Security/SecurityRuntime.cs b/src/mscorlib/src/System/Security/SecurityRuntime.cs
new file mode 100644
index 0000000000..9d776affd3
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityRuntime.cs
@@ -0,0 +1,299 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security {
+ using System;
+ using System.Globalization;
+ using System.Threading;
+ using System.Reflection;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ internal class SecurityRuntime
+ {
+ private SecurityRuntime(){}
+
+ // Returns the security object for the caller of the method containing
+ // 'stackMark' on its frame.
+ //
+ // THE RETURNED OBJECT IS THE LIVE RUNTIME OBJECT. BE CAREFUL WITH IT!
+ //
+ // Internal only, do not doc.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern
+ FrameSecurityDescriptor GetSecurityObjectForFrame(ref StackCrawlMark stackMark,
+ bool create);
+
+ // Constants used to return status to native
+ internal const bool StackContinue = true;
+ internal const bool StackHalt = false;
+
+ // this method is a big perf hit, so don't call unnecessarily
+ [System.Security.SecurityCritical] // auto-generated
+ internal static MethodInfo GetMethodInfo(RuntimeMethodHandleInternal rmh)
+ {
+ if (rmh.IsNullHandle())
+ return null;
+
+#if _DEBUG
+ try
+ {
+#endif
+ // Assert here because reflection will check grants and if we fail the check,
+ // there will be an infinite recursion that overflows the stack.
+ PermissionSet.s_fullTrust.Assert();
+ return (System.RuntimeType.GetMethodBase(RuntimeMethodHandle.GetDeclaringType(rmh), rmh) as MethodInfo);
+#if _DEBUG
+ }
+ catch(Exception)
+ {
+ return null;
+ }
+#endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool FrameDescSetHelper(FrameSecurityDescriptor secDesc,
+ PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh)
+ {
+ return secDesc.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool FrameDescHelper(FrameSecurityDescriptor secDesc,
+ IPermission demandIn,
+ PermissionToken permToken,
+ RuntimeMethodHandleInternal rmh)
+ {
+ return secDesc.CheckDemand((CodeAccessPermission) demandIn, permToken, rmh);
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ [System.Security.SecurityCritical]
+ private static bool CheckDynamicMethodSetHelper(System.Reflection.Emit.DynamicResolver dynamicResolver,
+ PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh)
+ {
+ System.Threading.CompressedStack creationStack = dynamicResolver.GetSecurityContext();
+ bool result;
+ try
+ {
+ result = creationStack.CheckSetDemandWithModificationNoHalt(demandSet, out alteredDemandSet, rmh);
+ }
+ catch (SecurityException ex)
+ {
+ throw new SecurityException(Environment.GetResourceString("Security_AnonymouslyHostedDynamicMethodCheckFailed"), ex);
+ }
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical]
+ private static bool CheckDynamicMethodHelper(System.Reflection.Emit.DynamicResolver dynamicResolver,
+ IPermission demandIn,
+ PermissionToken permToken,
+ RuntimeMethodHandleInternal rmh)
+ {
+ System.Threading.CompressedStack creationStack = dynamicResolver.GetSecurityContext();
+ bool result;
+ try
+ {
+ result = creationStack.CheckDemandNoHalt((CodeAccessPermission)demandIn, permToken, rmh);
+ }
+ catch (SecurityException ex)
+ {
+ throw new SecurityException(Environment.GetResourceString("Security_AnonymouslyHostedDynamicMethodCheckFailed"), ex);
+ }
+ return result;
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+
+ //
+ // API for PermissionSets
+ //
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Assert(PermissionSet permSet, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ // Note: if the "AssertPermission" is not a permission that implements IUnrestrictedPermission
+ // you need to change the fourth parameter to a zero.
+ FrameSecurityDescriptor secObj = CodeAccessSecurityEngine.CheckNReturnSO(
+ CodeAccessSecurityEngine.AssertPermissionToken,
+ CodeAccessSecurityEngine.AssertPermission,
+ ref stackMark,
+ 1 );
+
+ Contract.Assert(secObj != null,"Failure in SecurityRuntime.Assert() - secObj != null");
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeAsserts())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetAssert(permSet);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void AssertAllPossible(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj =
+ SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
+
+ Contract.Assert(secObj != null, "Failure in SecurityRuntime.AssertAllPossible() - secObj != null");
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.GetAssertAllPossible())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetAssertAllPossible();
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void Deny(PermissionSet permSet, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ // Deny is only valid in legacy mode
+ if (!AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CasDeny"));
+ }
+
+ FrameSecurityDescriptor secObj =
+ SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
+
+ Contract.Assert(secObj != null, "Failure in SecurityRuntime.Deny() - secObj != null");
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeDenials())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetDeny(permSet);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void PermitOnly(PermissionSet permSet, ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj =
+ SecurityRuntime.GetSecurityObjectForFrame(ref stackMark, true);
+
+ Contract.Assert(secObj != null, "Failure in SecurityRuntime.PermitOnly() - secObj != null");
+ if (secObj == null)
+ {
+ // Security: REQ_SQ flag is missing. Bad compiler ?
+ System.Environment.FailFast(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+ else
+ {
+ if (secObj.HasImperativeRestrictions())
+ throw new SecurityException( Environment.GetResourceString( "Security_MustRevertOverride" ) );
+
+ secObj.SetPermitOnly(permSet);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ //
+ // Revert API
+ //
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void RevertAssert(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false);
+ if (secObj != null)
+ {
+ secObj.RevertAssert();
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void RevertDeny(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false);
+ if (secObj != null)
+ {
+ secObj.RevertDeny();
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void RevertPermitOnly(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false);
+ if (secObj != null)
+ {
+ secObj.RevertPermitOnly();
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void RevertAll(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_CAS_POLICY
+ FrameSecurityDescriptor secObj = GetSecurityObjectForFrame(ref stackMark, false);
+ if (secObj != null)
+ {
+ secObj.RevertAll();
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ExecutionEngine_MissingSecurityDescriptor"));
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Security/SecurityState.cs b/src/mscorlib/src/System/Security/SecurityState.cs
new file mode 100644
index 0000000000..bd23acd813
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityState.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Security;
+using System.Security.Permissions;
+
+namespace System.Security
+{
+ [System.Security.SecurityCritical] // auto-generated_required
+#pragma warning disable 618
+ [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ public abstract class SecurityState
+ {
+ protected SecurityState(){}
+
+ [System.Security.SecurityCritical] // auto-generated
+ public bool IsStateAvailable()
+ {
+ AppDomainManager domainManager = AppDomainManager.CurrentAppDomainManager;
+#if FEATURE_CORECLR
+ // CheckSecuritySettings only when appdomainManager is present. So if there is no
+ // appDomain Manager return true as by default coreclr runs in fulltrust.
+ return domainManager != null ? domainManager.CheckSecuritySettings(this) : true;
+#else
+ return domainManager != null ? domainManager.CheckSecuritySettings(this) : false;
+#endif
+ }
+ // override this function and throw the appropriate
+ public abstract void EnsureState();
+ }
+
+}
diff --git a/src/mscorlib/src/System/Security/SecurityZone.cs b/src/mscorlib/src/System/Security/SecurityZone.cs
new file mode 100644
index 0000000000..a74b637846
--- /dev/null
+++ b/src/mscorlib/src/System/Security/SecurityZone.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// Enumeration of the zones code can come from
+//
+
+namespace System.Security
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ // The quick cache code depends on the values in this enumeration. Any change to this enumeration should
+ // be reflected in PolicyManager.GenerateQuickCache as well.
+ [ComVisible(true)]
+ [Serializable]
+ public enum SecurityZone
+ {
+ MyComputer = 0,
+ Intranet = 1,
+ Trusted = 2,
+ Internet = 3,
+ Untrusted = 4,
+
+ NoZone = -1, // No Zone Information
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/Config.cs b/src/mscorlib/src/System/Security/Util/Config.cs
new file mode 100644
index 0000000000..988a39a9d6
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/Config.cs
@@ -0,0 +1,131 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Util {
+ using System;
+ using System.Security.Util;
+ using System.Security.Policy;
+ using System.Security.Permissions;
+ using System.Collections;
+ using System.IO;
+ using System.Reflection;
+ using System.Globalization;
+ using System.Text;
+#if FEATURE_SERIALIZATION
+ using System.Runtime.Serialization.Formatters.Binary;
+#endif // FEATURE_SERIALIZATION
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+
+ // Duplicated in vm\COMSecurityConfig.h
+[Serializable]
+[Flags]
+ internal enum QuickCacheEntryType
+ {
+ FullTrustZoneMyComputer = 0x1000000,
+ FullTrustZoneIntranet = 0x2000000,
+ FullTrustZoneInternet = 0x4000000,
+ FullTrustZoneTrusted = 0x8000000,
+ FullTrustZoneUntrusted = 0x10000000,
+ FullTrustAll = 0x20000000,
+ }
+
+ internal static class Config {
+ private static volatile string m_machineConfig;
+ private static volatile string m_userConfig;
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static void GetFileLocales()
+ {
+ if (m_machineConfig == null)
+ {
+ string machineConfig = null;
+ GetMachineDirectory(JitHelpers.GetStringHandleOnStack(ref machineConfig));
+ m_machineConfig = machineConfig;
+ }
+ if (m_userConfig == null)
+ {
+ string userConfig = null;
+ GetUserDirectory(JitHelpers.GetStringHandleOnStack(ref userConfig));
+ m_userConfig = userConfig;
+ }
+ }
+
+ internal static string MachineDirectory
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ GetFileLocales();
+ return m_machineConfig;
+ }
+ }
+
+ internal static string UserDirectory
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ GetFileLocales();
+ return m_userConfig;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern int SaveDataByte(string path, [In] byte[] data, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern bool RecoverData(ConfigId id);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern void SetQuickCache(ConfigId id, QuickCacheEntryType quickCacheFlags);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern bool GetCacheEntry(ConfigId id, int numKey, [In] byte[] key, int keyLength, ObjectHandleOnStack retData);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool GetCacheEntry(ConfigId id, int numKey, byte[] key, out byte[] data)
+ {
+ byte[] retData = null;
+ bool ret = GetCacheEntry(id, numKey, key, key.Length, JitHelpers.GetObjectHandleOnStack(ref retData));
+
+ data = retData;
+ return ret;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void AddCacheEntry(ConfigId id, int numKey, [In] byte[] key, int keyLength, byte[] data, int dataLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void AddCacheEntry(ConfigId id, int numKey, byte[] key, byte[] data)
+ {
+ AddCacheEntry(id, numKey, key, key.Length, data, data.Length);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern void ResetCacheData(ConfigId id);
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void GetMachineDirectory(StringHandleOnStack retDirectory);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ private static extern void GetUserDirectory(StringHandleOnStack retDirectory);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode), SuppressUnmanagedCodeSecurity]
+ internal static extern bool WriteToEventLog(string message);
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/Hex.cs b/src/mscorlib/src/System/Security/Util/Hex.cs
new file mode 100644
index 0000000000..709744f2a2
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/Hex.cs
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*
+ *
+ * Operations to convert to and from Hex
+ *
+ */
+
+namespace System.Security.Util
+{
+ using System;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+ internal static class Hex
+ {
+ // converts number to hex digit. Does not do any range checks.
+ static char HexDigit(int num) {
+ return (char)((num < 10) ? (num + '0') : (num + ('A' - 10)));
+ }
+
+ public static String EncodeHexString(byte[] sArray)
+ {
+ String result = null;
+
+ if(sArray != null) {
+ char[] hexOrder = new char[sArray.Length * 2];
+
+ int digit;
+ for(int i = 0, j = 0; i < sArray.Length; i++) {
+ digit = (int)((sArray[i] & 0xf0) >> 4);
+ hexOrder[j++] = HexDigit(digit);
+ digit = (int)(sArray[i] & 0x0f);
+ hexOrder[j++] = HexDigit(digit);
+ }
+ result = new String(hexOrder);
+ }
+ return result;
+ }
+
+ internal static string EncodeHexStringFromInt(byte[] sArray) {
+ String result = null;
+ if(sArray != null) {
+ char[] hexOrder = new char[sArray.Length * 2];
+
+ int i = sArray.Length;
+ int digit, j=0;
+ while (i-- > 0) {
+ digit = (sArray[i] & 0xf0) >> 4;
+ hexOrder[j++] = HexDigit(digit);
+ digit = sArray[i] & 0x0f;
+ hexOrder[j++] = HexDigit(digit);
+ }
+ result = new String(hexOrder);
+ }
+ return result;
+ }
+
+ public static int ConvertHexDigit(Char val)
+ {
+ if (val <= '9' && val >= '0')
+ return (val - '0');
+ else if (val >= 'a' && val <= 'f')
+ return ((val - 'a') + 10);
+ else if (val >= 'A' && val <= 'F')
+ return ((val - 'A') + 10);
+ else
+ throw new ArgumentException( Environment.GetResourceString( "ArgumentOutOfRange_Index" ) );
+ }
+
+
+ public static byte[] DecodeHexString(String hexString)
+ {
+ if (hexString == null)
+ throw new ArgumentNullException( "hexString" );
+ Contract.EndContractBlock();
+
+ bool spaceSkippingMode = false;
+
+ int i = 0;
+ int length = hexString.Length;
+
+ if ((length >= 2) &&
+ (hexString[0] == '0') &&
+ ( (hexString[1] == 'x') || (hexString[1] == 'X') ))
+ {
+ length = hexString.Length - 2;
+ i = 2;
+ }
+
+ // Hex strings must always have 2N or (3N - 1) entries.
+
+ if (length % 2 != 0 && length % 3 != 2)
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidHexFormat" ) );
+ }
+
+ byte[] sArray;
+
+ if (length >=3 && hexString[i + 2] == ' ')
+ {
+ spaceSkippingMode = true;
+
+ // Each hex digit will take three spaces, except the first (hence the plus 1).
+ sArray = new byte[length / 3 + 1];
+ }
+ else
+ {
+ // Each hex digit will take two spaces
+ sArray = new byte[length / 2];
+ }
+
+ int digit;
+ int rawdigit;
+ for (int j = 0; i < hexString.Length; i += 2, j++) {
+ rawdigit = ConvertHexDigit(hexString[i]);
+ digit = ConvertHexDigit(hexString[i+1]);
+ sArray[j] = (byte) (digit | (rawdigit << 4));
+ if (spaceSkippingMode)
+ i++;
+ }
+ return(sArray);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs b/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs
new file mode 100644
index 0000000000..19937f5ae6
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs
@@ -0,0 +1,777 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Util {
+ using System.Text;
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+ using System.Runtime.Versioning;
+ using System.IO;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal class StringExpressionSet
+ {
+ // This field, as well as the expressions fields below are critical since they may contain
+ // canonicalized full path data potentially built out of relative data passed as input to the
+ // StringExpressionSet. Full trust code using the string expression set needs to ensure that before
+ // exposing this data out to partial trust, they protect against this. Possibilities include:
+ //
+ // 1. Using the throwOnRelative flag
+ // 2. Ensuring that the partial trust code has permission to see full path data
+ // 3. Not using this set for paths (eg EnvironmentStringExpressionSet)
+ //
+ [SecurityCritical]
+ protected ArrayList m_list;
+ protected bool m_ignoreCase;
+ [SecurityCritical]
+ protected String m_expressions;
+ [SecurityCritical]
+ protected String[] m_expressionsArray;
+
+ protected bool m_throwOnRelative;
+
+ protected static readonly char[] m_separators = { ';' };
+ protected static readonly char[] m_trimChars = { ' ' };
+#if !PLATFORM_UNIX
+ protected static readonly char m_directorySeparator = '\\';
+ protected static readonly char m_alternateDirectorySeparator = '/';
+#else
+ protected static readonly char m_directorySeparator = '/';
+ protected static readonly char m_alternateDirectorySeparator = '\\';
+#endif // !PLATFORM_UNIX
+
+ public StringExpressionSet()
+ : this( true, null, false )
+ {
+ }
+
+ public StringExpressionSet( String str )
+ : this( true, str, false )
+ {
+ }
+
+ public StringExpressionSet( bool ignoreCase, bool throwOnRelative )
+ : this( ignoreCase, null, throwOnRelative )
+ {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringExpressionSet( bool ignoreCase, String str, bool throwOnRelative )
+ {
+ m_list = null;
+ m_ignoreCase = ignoreCase;
+ m_throwOnRelative = throwOnRelative;
+ if (str == null)
+ m_expressions = null;
+ else
+ AddExpressions( str );
+ }
+
+ protected virtual StringExpressionSet CreateNewEmpty()
+ {
+ return new StringExpressionSet();
+ }
+
+ [SecuritySafeCritical]
+ public virtual StringExpressionSet Copy()
+ {
+ // SafeCritical: just copying this value around, not leaking it
+
+ StringExpressionSet copy = CreateNewEmpty();
+ if (this.m_list != null)
+ copy.m_list = new ArrayList(this.m_list);
+
+ copy.m_expressions = this.m_expressions;
+ copy.m_ignoreCase = this.m_ignoreCase;
+ copy.m_throwOnRelative = this.m_throwOnRelative;
+ return copy;
+ }
+
+ public void SetThrowOnRelative( bool throwOnRelative )
+ {
+ this.m_throwOnRelative = throwOnRelative;
+ }
+
+ private static String StaticProcessWholeString( String str )
+ {
+ return str.Replace( m_alternateDirectorySeparator, m_directorySeparator );
+ }
+
+ private static String StaticProcessSingleString( String str )
+ {
+ return str.Trim( m_trimChars );
+ }
+
+ protected virtual String ProcessWholeString( String str )
+ {
+ return StaticProcessWholeString(str);
+ }
+
+ protected virtual String ProcessSingleString( String str )
+ {
+ return StaticProcessSingleString(str);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddExpressions( String str )
+ {
+ if (str == null)
+ throw new ArgumentNullException( "str" );
+ Contract.EndContractBlock();
+ if (str.Length == 0)
+ return;
+
+ str = ProcessWholeString( str );
+
+ if (m_expressions == null)
+ m_expressions = str;
+ else
+ m_expressions = m_expressions + m_separators[0] + str;
+
+ m_expressionsArray = null;
+
+ // We have to parse the string and compute the list here.
+ // The logic in this class tries to delay this parsing but
+ // since operations like IsSubsetOf are called during
+ // demand evaluation, it is not safe to delay this step
+ // as that would cause concurring threads to update the object
+ // at the same time. The CheckList operation should ideally be
+ // removed from this class, but for the sake of keeping the
+ // changes to a minimum here, we simply make sure m_list
+ // cannot be null by parsing m_expressions eagerly.
+
+ String[] arystr = Split( str );
+
+ if (m_list == null)
+ m_list = new ArrayList();
+
+ for (int index = 0; index < arystr.Length; ++index)
+ {
+ if (arystr[index] != null && !arystr[index].Equals( "" ))
+ {
+ String temp = ProcessSingleString( arystr[index] );
+ int indexOfNull = temp.IndexOf( '\0' );
+
+ if (indexOfNull != -1)
+ temp = temp.Substring( 0, indexOfNull );
+
+ if (temp != null && !temp.Equals( "" ))
+ {
+ if (m_throwOnRelative)
+ {
+ if (Path.IsRelative(temp))
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+ }
+
+ temp = CanonicalizePath( temp );
+ }
+
+ m_list.Add( temp );
+ }
+ }
+ }
+
+ Reduce();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddExpressions( String[] str, bool checkForDuplicates, bool needFullPath )
+ {
+ AddExpressions(CreateListFromExpressions(str, needFullPath), checkForDuplicates);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public void AddExpressions( ArrayList exprArrayList, bool checkForDuplicates)
+ {
+ Contract.Assert( m_throwOnRelative, "This should only be called when throw on relative is set" );
+
+ m_expressionsArray = null;
+ m_expressions = null;
+
+ if (m_list != null)
+ m_list.AddRange(exprArrayList);
+ else
+ m_list = new ArrayList(exprArrayList);
+
+ if (checkForDuplicates)
+ Reduce();
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static ArrayList CreateListFromExpressions(String[] str, bool needFullPath)
+ {
+ if (str == null)
+ {
+ 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)
+ {
+ // Trim leading and trailing spaces
+ String temp = StaticProcessSingleString( oneString);
+
+ int indexOfNull = temp.IndexOf( '\0' );
+
+ if (indexOfNull != -1)
+ temp = temp.Substring( 0, indexOfNull );
+
+ if (temp != null && temp.Length != 0)
+ {
+ if (PathInternal.IsPartiallyQualified(temp))
+ {
+ throw new ArgumentException(Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+ }
+
+ temp = CanonicalizePath( temp, needFullPath );
+
+ retArrayList.Add( temp );
+ }
+ }
+ }
+
+ return retArrayList;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected void CheckList()
+ {
+ if (m_list == null && m_expressions != null)
+ {
+ CreateList();
+ }
+ }
+
+ protected String[] Split( String expressions )
+ {
+ if (m_throwOnRelative)
+ {
+ List<String> tempList = new List<String>();
+
+ String[] quoteSplit = expressions.Split( '\"' );
+
+ for (int i = 0; i < quoteSplit.Length; ++i)
+ {
+ if (i % 2 == 0)
+ {
+ String[] semiSplit = quoteSplit[i].Split( ';' );
+
+ for (int j = 0; j < semiSplit.Length; ++j)
+ {
+ if (semiSplit[j] != null && !semiSplit[j].Equals( "" ))
+ tempList.Add( semiSplit[j] );
+ }
+ }
+ else
+ {
+ tempList.Add( quoteSplit[i] );
+ }
+ }
+
+ String[] finalArray = new String[tempList.Count];
+
+ IEnumerator enumerator = tempList.GetEnumerator();
+
+ int index = 0;
+ while (enumerator.MoveNext())
+ {
+ finalArray[index++] = (String)enumerator.Current;
+ }
+
+ return finalArray;
+ }
+ else
+ {
+ return expressions.Split( m_separators );
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected void CreateList()
+ {
+ String[] expressionsArray = Split( m_expressions );
+
+ m_list = new ArrayList();
+
+ for (int index = 0; index < expressionsArray.Length; ++index)
+ {
+ if (expressionsArray[index] != null && !expressionsArray[index].Equals( "" ))
+ {
+ String temp = ProcessSingleString( expressionsArray[index] );
+
+ int indexOfNull = temp.IndexOf( '\0' );
+
+ if (indexOfNull != -1)
+ temp = temp.Substring( 0, indexOfNull );
+
+ if (temp != null && !temp.Equals( "" ))
+ {
+ if (m_throwOnRelative)
+ {
+ if (Path.IsRelative(temp))
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) );
+ }
+
+ temp = CanonicalizePath( temp );
+ }
+
+ m_list.Add( temp );
+ }
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ public bool IsEmpty()
+ {
+ // SafeCritical: we're just showing that the expressions are empty, the sensitive portion is their
+ // contents - not the existence of the contents
+ if (m_list == null)
+ {
+ return m_expressions == null;
+ }
+ else
+ {
+ return m_list.Count == 0;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public bool IsSubsetOf( StringExpressionSet ses )
+ {
+ if (this.IsEmpty())
+ return true;
+
+ if (ses == null || ses.IsEmpty())
+ return false;
+
+ CheckList();
+ ses.CheckList();
+
+ for (int index = 0; index < this.m_list.Count; ++index)
+ {
+ if (!StringSubsetStringExpression( (String)this.m_list[index], ses, m_ignoreCase ))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public bool IsSubsetOfPathDiscovery( StringExpressionSet ses )
+ {
+ if (this.IsEmpty())
+ return true;
+
+ if (ses == null || ses.IsEmpty())
+ return false;
+
+ CheckList();
+ ses.CheckList();
+
+ for (int index = 0; index < this.m_list.Count; ++index)
+ {
+ if (!StringSubsetStringExpressionPathDiscovery( (String)this.m_list[index], ses, m_ignoreCase ))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ public StringExpressionSet Union( StringExpressionSet ses )
+ {
+ // If either set is empty, the union represents a copy of the other.
+
+ if (ses == null || ses.IsEmpty())
+ return this.Copy();
+
+ if (this.IsEmpty())
+ return ses.Copy();
+
+ CheckList();
+ ses.CheckList();
+
+ // Perform the union
+ // note: insert smaller set into bigger set to reduce needed comparisons
+
+ StringExpressionSet bigger = ses.m_list.Count > this.m_list.Count ? ses : this;
+ StringExpressionSet smaller = ses.m_list.Count <= this.m_list.Count ? ses : this;
+
+ StringExpressionSet unionSet = bigger.Copy();
+
+ unionSet.Reduce();
+
+ for (int index = 0; index < smaller.m_list.Count; ++index)
+ {
+ unionSet.AddSingleExpressionNoDuplicates( (String)smaller.m_list[index] );
+ }
+
+ unionSet.GenerateString();
+
+ return unionSet;
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ public StringExpressionSet Intersect( StringExpressionSet ses )
+ {
+ // If either set is empty, the intersection is empty
+
+ if (this.IsEmpty() || ses == null || ses.IsEmpty())
+ return CreateNewEmpty();
+
+ CheckList();
+ ses.CheckList();
+
+ // Do the intersection for real
+
+ StringExpressionSet intersectSet = CreateNewEmpty();
+
+ for (int this_index = 0; this_index < this.m_list.Count; ++this_index)
+ {
+ for (int ses_index = 0; ses_index < ses.m_list.Count; ++ses_index)
+ {
+ if (StringSubsetString( (String)this.m_list[this_index], (String)ses.m_list[ses_index], m_ignoreCase ))
+ {
+ if (intersectSet.m_list == null)
+ {
+ intersectSet.m_list = new ArrayList();
+ }
+ intersectSet.AddSingleExpressionNoDuplicates( (String)this.m_list[this_index] );
+ }
+ else if (StringSubsetString( (String)ses.m_list[ses_index], (String)this.m_list[this_index], m_ignoreCase ))
+ {
+ if (intersectSet.m_list == null)
+ {
+ intersectSet.m_list = new ArrayList();
+ }
+ intersectSet.AddSingleExpressionNoDuplicates( (String)ses.m_list[ses_index] );
+ }
+ }
+ }
+
+ intersectSet.GenerateString();
+
+ return intersectSet;
+ }
+
+ [SecuritySafeCritical]
+ protected void GenerateString()
+ {
+ // SafeCritical - moves critical data around, but doesn't expose it out
+ if (m_list != null)
+ {
+ StringBuilder sb = new StringBuilder();
+
+ IEnumerator enumerator = this.m_list.GetEnumerator();
+ bool first = true;
+
+ while (enumerator.MoveNext())
+ {
+ if (!first)
+ sb.Append( m_separators[0] );
+ else
+ first = false;
+
+ String currentString = (String)enumerator.Current;
+ if (currentString != null)
+ {
+ int indexOfSeparator = currentString.IndexOf( m_separators[0] );
+
+ if (indexOfSeparator != -1)
+ sb.Append( '\"' );
+
+ sb.Append( currentString );
+
+ if (indexOfSeparator != -1)
+ sb.Append( '\"' );
+ }
+ }
+
+ m_expressions = sb.ToString();
+ }
+ else
+ {
+ m_expressions = null;
+ }
+ }
+
+ // We don't override ToString since that API must be either transparent or safe citical. If the
+ // expressions contain paths that were canonicalized and expanded from the input that would cause
+ // information disclosure, so we instead only expose this out to trusted code that can ensure they
+ // either don't leak the information or required full path information.
+ [SecurityCritical]
+ public string UnsafeToString()
+ {
+ CheckList();
+
+ Reduce();
+
+ GenerateString();
+
+ return m_expressions;
+ }
+
+ [SecurityCritical]
+ public String[] UnsafeToStringArray()
+ {
+ if (m_expressionsArray == null && m_list != null)
+ {
+ m_expressionsArray = (String[])m_list.ToArray(typeof(String));
+ }
+
+ return m_expressionsArray;
+ }
+
+
+ //-------------------------------
+ // protected static helper functions
+ //-------------------------------
+
+ [SecurityCritical]
+ private bool StringSubsetStringExpression( String left, StringExpressionSet right, bool ignoreCase )
+ {
+ for (int index = 0; index < right.m_list.Count; ++index)
+ {
+ if (StringSubsetString( left, (String)right.m_list[index], ignoreCase ))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ [SecurityCritical]
+ private static bool StringSubsetStringExpressionPathDiscovery( String left, StringExpressionSet right, bool ignoreCase )
+ {
+ for (int index = 0; index < right.m_list.Count; ++index)
+ {
+ if (StringSubsetStringPathDiscovery( left, (String)right.m_list[index], ignoreCase ))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ protected virtual bool StringSubsetString( String left, String right, bool ignoreCase )
+ {
+ StringComparison strComp = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
+ if (right == null || left == null || right.Length == 0 || left.Length == 0 ||
+ right.Length > left.Length)
+ {
+ return false;
+ }
+ else if (right.Length == left.Length)
+ {
+ // if they are equal in length, just do a normal compare
+ return String.Compare( right, left, strComp) == 0;
+ }
+ else if (left.Length - right.Length == 1 && left[left.Length-1] == m_directorySeparator)
+ {
+ return String.Compare( left, 0, right, 0, right.Length, strComp) == 0;
+ }
+ else if (right[right.Length-1] == m_directorySeparator)
+ {
+ // right is definitely a directory, just do a substring compare
+ return String.Compare( right, 0, left, 0, right.Length, strComp) == 0;
+ }
+ else if (left[right.Length] == m_directorySeparator)
+ {
+ // left is hinting at being a subdirectory on right, do substring compare to make find out
+ return String.Compare( right, 0, left, 0, right.Length, strComp) == 0;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ protected static bool StringSubsetStringPathDiscovery( String left, String right, bool ignoreCase )
+ {
+ StringComparison strComp = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
+ if (right == null || left == null || right.Length == 0 || left.Length == 0)
+ {
+ return false;
+ }
+ else if (right.Length == left.Length)
+ {
+ // if they are equal in length, just do a normal compare
+ return String.Compare( right, left, strComp) == 0;
+ }
+ else
+ {
+ String shortString, longString;
+
+ if (right.Length < left.Length)
+ {
+ shortString = right;
+ longString = left;
+ }
+ else
+ {
+ shortString = left;
+ longString = right;
+ }
+
+ if (String.Compare( shortString, 0, longString, 0, shortString.Length, strComp) != 0)
+ {
+ return false;
+ }
+
+#if !PLATFORM_UNIX
+ if (shortString.Length == 3 &&
+ shortString.EndsWith( ":\\", StringComparison.Ordinal ) &&
+ ((shortString[0] >= 'A' && shortString[0] <= 'Z') ||
+ (shortString[0] >= 'a' && shortString[0] <= 'z')))
+#else
+ if (shortString.Length == 1 && shortString[0]== m_directorySeparator)
+#endif // !PLATFORM_UNIX
+ return true;
+
+ return longString[shortString.Length] == m_directorySeparator;
+ }
+ }
+
+
+ //-------------------------------
+ // protected helper functions
+ //-------------------------------
+
+ [SecuritySafeCritical]
+ protected void AddSingleExpressionNoDuplicates( String expression )
+ {
+ // SafeCritical: We're not exposing out the string sets, just allowing modification of them
+ int index = 0;
+
+ m_expressionsArray = null;
+ m_expressions = null;
+
+ if (this.m_list == null)
+ this.m_list = new ArrayList();
+
+ while (index < this.m_list.Count)
+ {
+ if (StringSubsetString( (String)this.m_list[index], expression, m_ignoreCase ))
+ {
+ this.m_list.RemoveAt( index );
+ }
+ else if (StringSubsetString( expression, (String)this.m_list[index], m_ignoreCase ))
+ {
+ return;
+ }
+ else
+ {
+ index++;
+ }
+ }
+ this.m_list.Add( expression );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected void Reduce()
+ {
+ CheckList();
+
+ if (this.m_list == null)
+ return;
+
+ int j;
+
+ for (int i = 0; i < this.m_list.Count - 1; i++)
+ {
+ j = i + 1;
+
+ while (j < this.m_list.Count)
+ {
+ if (StringSubsetString( (String)this.m_list[j], (String)this.m_list[i], m_ignoreCase ))
+ {
+ this.m_list.RemoveAt( j );
+ }
+ else if (StringSubsetString( (String)this.m_list[i], (String)this.m_list[j], m_ignoreCase ))
+ {
+ // write the value at j into position i, delete the value at position j and keep going.
+ this.m_list[i] = this.m_list[j];
+ this.m_list.RemoveAt( j );
+ j = i + 1;
+ }
+ else
+ {
+ j++;
+ }
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern void GetLongPathName( String path, StringHandleOnStack retLongPath );
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static String CanonicalizePath( String path )
+ {
+ return CanonicalizePath( path, true );
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static string CanonicalizePath(string path, bool needFullPath)
+ {
+ if (needFullPath)
+ {
+ string newPath = Path.GetFullPathInternal(path);
+ if (path.EndsWith(m_directorySeparator + ".", StringComparison.Ordinal))
+ {
+ if (newPath.EndsWith(m_directorySeparator))
+ {
+ newPath += ".";
+ }
+ else
+ {
+ newPath += m_directorySeparator + ".";
+ }
+ }
+ path = newPath;
+ }
+#if !PLATFORM_UNIX
+ 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"));
+#endif // !PLATFORM_UNIX
+
+ return path;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs b/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs
new file mode 100644
index 0000000000..590a909662
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/TokenBasedSet.cs
@@ -0,0 +1,467 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Util
+{
+ using System;
+ using System.Collections;
+ using System.Security.Permissions;
+ using System.Runtime.Serialization;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ internal class TokenBasedSet
+ {
+
+
+ // Following 3 fields are used only for serialization compat purposes: DO NOT USE THESE EVER!
+#pragma warning disable 414
+ private int m_initSize = 24;
+ private int m_increment = 8;
+#pragma warning restore 414
+ private Object[] m_objSet;
+ // END -> Serialization only fields
+
+ [OptionalField(VersionAdded = 2)]
+ private volatile Object m_Obj;
+ [OptionalField(VersionAdded = 2)]
+ private volatile Object[] m_Set;
+
+ private int m_cElt;
+ private volatile int m_maxIndex;
+
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserializedInternal();
+ }
+ private void OnDeserializedInternal()
+ {
+ if (m_objSet != null) //v1.x case
+ {
+ if (m_cElt == 1)
+ m_Obj = m_objSet[m_maxIndex];
+ else
+ m_Set = m_objSet;
+ m_objSet = null;
+ }
+ // Nothing to do for the v2.0 and beyond case
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ //Nothing special for the v2 and beyond case
+
+ // for the v1.x case, we need to create m_objSet if necessary
+ if (m_cElt == 1)
+ {
+ m_objSet = new Object[m_maxIndex+1];
+ m_objSet[m_maxIndex] = m_Obj;
+ }
+ else if (m_cElt > 0)
+ {
+ // Array case:
+ m_objSet = m_Set;
+ }
+
+ }
+ }
+ [OnSerialized]
+ private void OnSerialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_objSet = null;
+
+ }
+ }
+
+
+ internal bool MoveNext(ref TokenBasedSetEnumerator e)
+ {
+ switch (m_cElt)
+ {
+ case 0:
+ return false;
+
+ case 1:
+ if (e.Index == -1)
+ {
+ e.Index = m_maxIndex;
+ e.Current = m_Obj;
+ return true;
+ }
+ else
+ {
+ e.Index = (short)(m_maxIndex+1);
+ e.Current = null;
+ return false;
+ }
+
+ default:
+ while (++e.Index <= m_maxIndex)
+ {
+ e.Current = Volatile.Read(ref m_Set[e.Index]);
+
+ if (e.Current != null)
+ return true;
+ }
+
+ e.Current = null;
+ return false;
+ }
+ }
+
+ internal TokenBasedSet()
+ {
+ Reset();
+ }
+
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ internal TokenBasedSet(TokenBasedSet tbSet)
+ {
+ if (tbSet == null)
+ {
+ Reset();
+ return;
+ }
+
+ if (tbSet.m_cElt > 1)
+ {
+ Object[] aObj = tbSet.m_Set;
+ int aLen = aObj.Length;
+
+ Object[] aNew = new Object[aLen];
+ System.Array.Copy(aObj, 0, aNew, 0, aLen);
+
+ m_Set = aNew;
+ }
+ else
+ {
+ m_Obj = tbSet.m_Obj;
+ }
+
+ m_cElt = tbSet.m_cElt;
+ m_maxIndex = tbSet.m_maxIndex;
+ }
+
+ internal void Reset()
+ {
+ m_Obj = null;
+ m_Set = null;
+ m_cElt = 0;
+ m_maxIndex = -1;
+ }
+
+ internal void SetItem(int index, Object item)
+ {
+ Object[] aObj = null;
+
+ if (item == null)
+ {
+ RemoveItem(index);
+ return;
+ }
+
+ switch (m_cElt)
+ {
+ case 0:
+ // on the first item, we don't create an array, we merely remember it's index and value
+ // this this the 99% case
+ m_cElt = 1;
+ m_maxIndex = (short)index;
+ m_Obj = item;
+ break;
+
+ case 1:
+ // we have to decide if a 2nd item has indeed been added and create the array
+ // if it has
+ if (index == m_maxIndex)
+ {
+ // replacing the one existing item
+ m_Obj = item;
+ }
+ else
+ {
+ // adding a second distinct permission
+ Object objSaved = m_Obj;
+ int iMax = Math.Max(m_maxIndex, index);
+
+ aObj = new Object[iMax+1];
+ aObj[m_maxIndex] = objSaved;
+ aObj[index] = item;
+ m_maxIndex = (short)iMax;
+ m_cElt = 2;
+ m_Set = aObj;
+ m_Obj = null;
+ }
+ break;
+
+ default:
+ // this is the general case code for when there is really an array
+
+ aObj = m_Set;
+
+ // we are now adding an item, check if we need to grow
+
+ if (index >= aObj.Length)
+ {
+ Object[] newset = new Object[index+1];
+ System.Array.Copy(aObj, 0, newset, 0, m_maxIndex+1);
+ m_maxIndex = (short)index;
+ newset[index] = item;
+ m_Set = newset;
+ m_cElt++;
+ }
+ else
+ {
+ if (aObj[index] == null)
+ m_cElt++;
+
+ aObj[index] = item;
+
+ if (index > m_maxIndex)
+ m_maxIndex = (short)index;
+ }
+ break;
+ }
+ }
+
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety")]
+ internal Object GetItem(int index)
+ {
+ switch (m_cElt)
+ {
+ case 0:
+ return null;
+
+ case 1:
+ if (index == m_maxIndex)
+ return m_Obj;
+ else
+ return null;
+ default:
+ if (index < m_Set.Length)
+ return Volatile.Read(ref m_Set[index]);
+ else
+ return null;
+ }
+ }
+
+ internal Object RemoveItem(int index)
+ {
+ Object ret = null;
+
+ switch (m_cElt)
+ {
+ case 0:
+ ret = null;
+ break;
+
+ case 1:
+ if (index != m_maxIndex)
+ {
+ // removing a permission we don't have ignore it
+ ret = null;
+ }
+ else
+ {
+ // removing the permission we have at the moment
+ ret = m_Obj;
+ Reset();
+ }
+ break;
+
+ default:
+ // this is the general case code for when there is really an array
+
+ // we are removing an item
+ if (index < m_Set.Length && (ret = Volatile.Read(ref m_Set[index])) != null)
+ {
+ // ok we really deleted something at this point
+
+ Volatile.Write(ref m_Set[index], null);
+ m_cElt--;
+
+ if (index == m_maxIndex)
+ ResetMaxIndex(m_Set);
+
+ // collapse the array
+ if (m_cElt == 1)
+ {
+ m_Obj = Volatile.Read(ref m_Set[m_maxIndex]);
+ m_Set = null;
+ }
+ }
+ break;
+ }
+
+ return ret;
+ }
+
+ private void ResetMaxIndex(Object[] aObj)
+ {
+ int i;
+
+ // Start at the end of the array, and
+ // scan backwards for the first non-null
+ // slot. That is the new maxIndex.
+ for (i = aObj.Length - 1; i >= 0; i--)
+ {
+ if (aObj[i] != null)
+ {
+ m_maxIndex = (short)i;
+ return;
+ }
+ }
+
+ m_maxIndex = -1;
+ }
+ internal int GetStartingIndex()
+ {
+ if (m_cElt <= 1)
+ return m_maxIndex;
+ return 0;
+ }
+ internal int GetCount()
+ {
+ return m_cElt;
+ }
+
+ internal int GetMaxUsedIndex()
+ {
+ return m_maxIndex;
+ }
+
+ internal bool FastIsEmpty()
+ {
+ return m_cElt == 0;
+ }
+
+ // Used to merge two distinct TokenBasedSets (used currently only in PermissionSet Deserialization)
+ internal TokenBasedSet SpecialUnion(TokenBasedSet other)
+ {
+ // This gets called from PermissionSet.OnDeserialized and it's possible that the TokenBasedSets have
+ // not been subjected to VTS callbacks yet
+ OnDeserializedInternal();
+ TokenBasedSet unionSet = new TokenBasedSet();
+ int maxMax;
+ if (other != null)
+ {
+ other.OnDeserializedInternal();
+ maxMax = this.GetMaxUsedIndex() > other.GetMaxUsedIndex() ? this.GetMaxUsedIndex() : other.GetMaxUsedIndex();
+ }
+ else
+ maxMax = this.GetMaxUsedIndex();
+
+ for (int i = 0; i <= maxMax; ++i)
+ {
+ Object thisObj = this.GetItem( i );
+ IPermission thisPerm = thisObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory thisElem = thisObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ Object otherObj = (other != null)?other.GetItem( i ):null;
+ IPermission otherPerm = otherObj as IPermission;
+#if FEATURE_CAS_POLICY
+ ISecurityElementFactory otherElem = otherObj as ISecurityElementFactory;
+#endif // FEATURE_CAS_POLICY
+
+ if (thisObj == null && otherObj == null)
+ continue;
+
+
+ if (thisObj == null)
+ {
+#if FEATURE_CAS_POLICY
+ if (otherElem != null)
+ {
+ otherPerm = PermissionSet.CreatePerm(otherElem, false);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ PermissionToken token = PermissionToken.GetToken(otherPerm);
+
+ if (token == null)
+ {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+
+ unionSet.SetItem(token.m_index, otherPerm);
+ }
+ else if (otherObj == null)
+ {
+#if FEATURE_CAS_POLICY
+ if (thisElem != null)
+ {
+ thisPerm = PermissionSet.CreatePerm(thisElem, false);
+ }
+#endif // FEATURE_CAS_POLICY
+
+ PermissionToken token = PermissionToken.GetToken(thisPerm);
+ if (token == null)
+ {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
+ }
+ unionSet.SetItem( token.m_index, thisPerm);
+ }
+ else
+ {
+ Contract.Assert( (thisObj == null || otherObj == null), "Permission cannot be in both TokenBasedSets" );
+ }
+ }
+ return unionSet;
+ }
+
+ internal void SpecialSplit(ref TokenBasedSet unrestrictedPermSet, ref TokenBasedSet normalPermSet, bool ignoreTypeLoadFailures)
+ {
+ int maxIndex = GetMaxUsedIndex();
+
+ for (int i = GetStartingIndex(); i <= maxIndex; ++i)
+ {
+ Object obj = GetItem( i );
+ if (obj != null)
+ {
+ IPermission perm = obj as IPermission;
+#if FEATURE_CAS_POLICY
+ if (perm == null)
+ perm = PermissionSet.CreatePerm(obj, ignoreTypeLoadFailures);
+#endif // FEATURE_CAS_POLICY
+ PermissionToken token = PermissionToken.GetToken(perm);
+
+ if (perm == null || token == null)
+ continue;
+
+ if (perm is IUnrestrictedPermission)
+ {
+ // Add to unrestrictedPermSet
+ if (unrestrictedPermSet == null)
+ unrestrictedPermSet = new TokenBasedSet();
+ unrestrictedPermSet.SetItem(token.m_index, perm);
+ }
+ else
+ {
+ // Add to normalPermSet
+ if (normalPermSet == null)
+ normalPermSet = new TokenBasedSet();
+ normalPermSet.SetItem(token.m_index, perm);
+ }
+
+ }
+
+ }
+
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/TokenBasedSetEnumerator.cs b/src/mscorlib/src/System/Security/Util/TokenBasedSetEnumerator.cs
new file mode 100644
index 0000000000..9c868d3c53
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/TokenBasedSetEnumerator.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Util
+{
+ using System;
+ using System.Collections;
+
+ internal struct TokenBasedSetEnumerator
+ {
+ public Object Current;
+ public int Index;
+
+ private TokenBasedSet _tb;
+
+ public bool MoveNext()
+ {
+ return _tb != null ? _tb.MoveNext(ref this) : false;
+ }
+
+ public void Reset()
+ {
+ Index = -1;
+ Current = null;
+ }
+
+ public TokenBasedSetEnumerator(TokenBasedSet tb)
+ {
+ Index = -1;
+ Current = null;
+ _tb = tb;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Security/Util/URLString.cs b/src/mscorlib/src/System/Security/Util/URLString.cs
new file mode 100644
index 0000000000..51ae24cf4a
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/URLString.cs
@@ -0,0 +1,1366 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// URLString
+//
+//
+// Implementation of membership condition for zones
+//
+
+namespace System.Security.Util {
+
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Text;
+ using System.IO;
+ using System.Diagnostics.Contracts;
+
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ internal sealed class URLString : SiteString
+ {
+ private String m_protocol;
+ [OptionalField(VersionAdded = 2)]
+ private String m_userpass;
+ private SiteString m_siteString;
+ private int m_port;
+#if !PLATFORM_UNIX
+ private LocalSiteString m_localSite;
+#endif // !PLATFORM_UNIX
+ private DirectoryString m_directory;
+
+ private const String m_defaultProtocol = "file";
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_parseDeferred;
+ [OptionalField(VersionAdded = 2)]
+ private String m_urlOriginal;
+ [OptionalField(VersionAdded = 2)]
+ private bool m_parsedOriginal;
+
+ [OptionalField(VersionAdded = 3)]
+ private bool m_isUncShare;
+
+ // legacy field from v1.x, not used in v2 and beyond. Retained purely for serialization compatibility.
+ private String m_fullurl;
+
+
+ [OnDeserialized]
+ public void OnDeserialized(StreamingContext ctx)
+ {
+
+ if (m_urlOriginal == null)
+ {
+ // pre-v2 deserialization. Need to fix-up fields here
+ m_parseDeferred = false;
+ m_parsedOriginal = false; // Dont care what this value is - never used
+ m_userpass = "";
+ m_urlOriginal = m_fullurl;
+ m_fullurl = null;
+ }
+ }
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ DoDeferredParse();
+ m_fullurl = m_urlOriginal;
+ }
+ }
+ [OnSerialized]
+ private void OnSerialized(StreamingContext ctx)
+ {
+ if ((ctx.State & ~(StreamingContextStates.Clone|StreamingContextStates.CrossAppDomain)) != 0)
+ {
+ m_fullurl = null;
+ }
+ }
+
+ public URLString()
+ {
+ m_protocol = "";
+ m_userpass = "";
+ m_siteString = new SiteString();
+ m_port = -1;
+#if !PLATFORM_UNIX
+ m_localSite = null;
+#endif // !PLATFORM_UNIX
+ m_directory = new DirectoryString();
+ m_parseDeferred = false;
+ }
+
+ private void DoDeferredParse()
+ {
+ if (m_parseDeferred)
+ {
+ ParseString(m_urlOriginal, m_parsedOriginal);
+ m_parseDeferred = false;
+ }
+ }
+
+ public URLString(string url) : this(url, false, false) {}
+ public URLString(string url, bool parsed) : this(url, parsed, false) {}
+
+ internal URLString(string url, bool parsed, bool doDeferredParsing)
+ {
+ m_port = -1;
+ m_userpass = "";
+ DoFastChecks(url);
+ m_urlOriginal = url;
+ m_parsedOriginal = parsed;
+ m_parseDeferred = true;
+ if (doDeferredParsing)
+ DoDeferredParse();
+ }
+
+ // Converts %XX and %uYYYY to the actual characters (I.e. Unesacpes any escape characters present in the URL)
+ private String UnescapeURL(String url)
+ {
+ StringBuilder intermediate = StringBuilderCache.Acquire(url.Length);
+ int Rindex = 0; // index into temp that gives the rest of the string to be processed
+ int index;
+ int braIndex = -1;
+ int ketIndex = -1;
+ braIndex = url.IndexOf('[',Rindex);
+ if (braIndex != -1)
+ ketIndex = url.IndexOf(']', braIndex);
+
+ do
+ {
+ index = url.IndexOf( '%', Rindex);
+
+ if (index == -1)
+ {
+ intermediate = intermediate.Append(url, Rindex, (url.Length - Rindex));
+ break;
+ }
+ // if we hit a '%' in the middle of an IPv6 address, dont process that
+ if (index > braIndex && index < ketIndex)
+ {
+ intermediate = intermediate.Append(url, Rindex, (ketIndex - Rindex+1));
+ Rindex = ketIndex+1;
+ continue;
+ }
+
+ if (url.Length - index < 2) // Check that there is at least 1 char after the '%'
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+
+ if (url[index+1] == 'u' || url[index+1] == 'U')
+ {
+ if (url.Length - index < 6) // example: "%u004d" is 6 chars long
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+
+ // We have a unicode character specified in hex
+
+ try
+ {
+ char c = (char)(Hex.ConvertHexDigit( url[index+2] ) << 12 |
+ Hex.ConvertHexDigit( url[index+3] ) << 8 |
+ Hex.ConvertHexDigit( url[index+4] ) << 4 |
+ Hex.ConvertHexDigit( url[index+5] ));
+ intermediate = intermediate.Append(url, Rindex, index - Rindex);
+ intermediate = intermediate.Append(c);
+ }
+ catch(ArgumentException) // Hex.ConvertHexDigit can throw an "out of range" ArgumentException
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+
+ Rindex = index + 6 ; //update the 'seen' length
+ }
+ else
+ {
+ // we have a hex character.
+
+ if (url.Length - index < 3) // example: "%4d" is 3 chars long
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+
+ try
+ {
+ char c = (char)(Hex.ConvertHexDigit( url[index+1] ) << 4 | Hex.ConvertHexDigit( url[index+2] ));
+
+ intermediate = intermediate.Append(url, Rindex, index - Rindex);
+ intermediate = intermediate.Append(c);
+ }
+ catch(ArgumentException) // Hex.ConvertHexDigit can throw an "out of range" ArgumentException
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+
+ Rindex = index + 3; // update the 'seen' length
+ }
+
+ }
+ while (true);
+ return StringBuilderCache.GetStringAndRelease(intermediate);
+ }
+
+ // Helper Function for ParseString:
+ // Search for the end of the protocol info and grab the actual protocol string
+ // ex. http://www.microsoft.com/complus would have a protocol string of http
+ private String ParseProtocol(String url)
+ {
+ String temp;
+ int index = url.IndexOf( ':' );
+
+ if (index == 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+ else if (index == -1)
+ {
+ m_protocol = m_defaultProtocol;
+ temp = url;
+ }
+ else if (url.Length > index + 1)
+ {
+ if (index == m_defaultProtocol.Length &&
+ String.Compare(url, 0, m_defaultProtocol, 0, index, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ m_protocol = m_defaultProtocol;
+ temp = url.Substring( index + 1 );
+
+ // Since an explicit file:// URL could be immediately followed by a host name, we will be
+ // conservative and assume that it is on a share rather than a potentally relative local
+ // URL.
+ m_isUncShare = true;
+ }
+ else if (url[index+1] != '\\')
+ {
+#if !PLATFORM_UNIX
+ if (url.Length > index + 2 &&
+ url[index+1] == '/' &&
+ url[index+2] == '/')
+#else
+ if (url.Length > index + 1 &&
+ url[index+1] == '/' ) // UNIX style "file:/home/me" is allowed, so account for that
+#endif // !PLATFORM_UNIX
+ {
+ m_protocol = url.Substring( 0, index );
+
+ for (int i = 0; i < m_protocol.Length; ++i)
+ {
+ char c = m_protocol[i];
+
+ if ((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ (c == '+') ||
+ (c == '.') ||
+ (c == '-'))
+ {
+ continue;
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+ }
+#if !PLATFORM_UNIX
+ temp = url.Substring( index + 3 );
+#else
+ // In UNIX, we don't know how many characters we'll have to skip past.
+ // Skip past \, /, and :
+ //
+ for ( int j=index ; j<url.Length ; j++ )
+ {
+ if ( url[j] != '\\' && url[j] != '/' && url[j] != ':' )
+ {
+ index = j;
+ break;
+ }
+ }
+
+ temp = url.Substring( index );
+#endif // !PLATFORM_UNIX
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+ }
+ else
+ {
+ m_protocol = m_defaultProtocol;
+ temp = url;
+ }
+ }
+ else
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+
+ return temp;
+ }
+
+ private String ParsePort(String url)
+ {
+ String temp = url;
+ char[] separators = new char[] { ':', '/' };
+ int Rindex = 0;
+ int userpassIndex = temp.IndexOf('@');
+ if (userpassIndex != -1) {
+ if (temp.IndexOf('/',0,userpassIndex) == -1) {
+ // this is a user:pass type of string
+ m_userpass = temp.Substring(0,userpassIndex);
+ Rindex = userpassIndex + 1;
+ }
+ }
+
+ int braIndex = -1;
+ int ketIndex = -1;
+ int portIndex = -1;
+ braIndex = url.IndexOf('[',Rindex);
+ if (braIndex != -1)
+ ketIndex = url.IndexOf(']', braIndex);
+ if (ketIndex != -1)
+ {
+ // IPv6 address...ignore the IPv6 block when searching for the port
+ portIndex = temp.IndexOfAny(separators,ketIndex);
+ }
+ else
+ {
+ portIndex = temp.IndexOfAny(separators,Rindex);
+ }
+
+
+
+ if (portIndex != -1 && temp[portIndex] == ':')
+ {
+ // make sure it really is a port, and has a number after the :
+ if ( temp[portIndex+1] >= '0' && temp[portIndex+1] <= '9' )
+ {
+ int tempIndex = temp.IndexOf( '/', Rindex);
+
+ if (tempIndex == -1)
+ {
+ m_port = Int32.Parse( temp.Substring(portIndex + 1), CultureInfo.InvariantCulture );
+
+ if (m_port < 0)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+
+ temp = temp.Substring( Rindex, portIndex - Rindex );
+ }
+ else if (tempIndex > portIndex)
+ {
+ m_port = Int32.Parse( temp.Substring(portIndex + 1, tempIndex - portIndex - 1), CultureInfo.InvariantCulture );
+ temp = temp.Substring( Rindex, portIndex - Rindex ) + temp.Substring( tempIndex );
+ }
+ else
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+ else
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+ }
+ else {
+ // Chop of the user/pass portion if any
+ temp = temp.Substring(Rindex);
+ }
+
+ return temp;
+ }
+
+ // This does three things:
+ // 1. It makes the following modifications to the start of the string:
+ // a. \\?\ and \\?/ => <empty>
+ // b. \\.\ and \\./ => <empty>
+ // 2. If isFileUrl is true, converts all slashes to front slashes and strips leading
+ // front slashes. See comment by code.
+ // 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)
+ {
+ return PreProcessForExtendedPathRemoval(checkPathLength: true, url: url, isFileUrl: isFileUrl);
+ }
+
+ 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);
+
+ // ITEM 1 - remove extended path characters.
+ {
+ // Keep track of where we are in both the comparison and altered strings.
+ int curCmpIdx = 0;
+ int curModIdx = 0;
+
+ // If all the '\' have already been converted to '/', just check for //?/ or //./
+ if ((url.Length - curCmpIdx) >= 4 &&
+ (String.Compare(url, curCmpIdx, "//?/", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(url, curCmpIdx, "//./", 0, 4, StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ modifiedUrl.Remove(curModIdx, 4);
+ curCmpIdx += 4;
+ }
+ else
+ {
+ if (isFileUrl) {
+ // We need to handle an indefinite number of leading front slashes for file URLs since we could
+ // get something like:
+ // file://\\?\
+ // file:/\\?\
+ // file:\\?\
+ // etc...
+ while (url[curCmpIdx] == '/')
+ {
+ curCmpIdx++;
+ curModIdx++;
+ }
+ }
+
+ // Remove the extended path characters
+ if ((url.Length - curCmpIdx) >= 4 &&
+ (String.Compare(url, curCmpIdx, "\\\\?\\", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(url, curCmpIdx, "\\\\?/", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(url, curCmpIdx, "\\\\.\\", 0, 4, StringComparison.OrdinalIgnoreCase) == 0 ||
+ String.Compare(url, curCmpIdx, "\\\\./", 0, 4, StringComparison.OrdinalIgnoreCase) == 0))
+ {
+ modifiedUrl.Remove(curModIdx, 4);
+ curCmpIdx += 4;
+ }
+ }
+ }
+
+ // ITEM 2 - convert all slashes to forward slashes, and strip leading slashes.
+ if (isFileUrl)
+ {
+ int slashCount = 0;
+ bool seenFirstBackslash = false;
+
+ while (slashCount < modifiedUrl.Length && (modifiedUrl[slashCount] == '/' || modifiedUrl[slashCount] == '\\'))
+ {
+ // Look for sets of consecutive backslashes. We can't just look for these at the start
+ // of the string, since file:// might come first. Instead, once we see the first \, look
+ // for a second one following it.
+ if (!seenFirstBackslash && modifiedUrl[slashCount] == '\\')
+ {
+ seenFirstBackslash = true;
+ if (slashCount + 1 < modifiedUrl.Length && modifiedUrl[slashCount + 1] == '\\')
+ isUncShare = true;
+ }
+
+ slashCount++;
+ }
+
+ modifiedUrl.Remove(0, slashCount);
+ modifiedUrl.Replace('\\', '/');
+ }
+
+ // ITEM 3 - If the path is greater than or equal (due to terminating NULL in windows) MAX_PATH, we throw.
+ if (checkPathLength)
+ {
+ // 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 >= (
+#if FEATURE_PATHCOMPAT
+ AppContextSwitches.BlockLongPaths ? PathInternal.MaxShortPath :
+#endif
+ 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)
+ {
+
+#if !PLATFORM_UNIX
+ if (isFileURL) {
+ // Remove when the Path class supports "\\?\"
+ url = PreProcessForExtendedPathRemoval(url, true, ref m_isUncShare);
+ }
+ else {
+ url = url.Replace('\\', '/');
+ }
+ return url;
+#else
+ // Remove superfluous '/'
+ // For UNIX, the file path would look something like:
+ // file:///home/johndoe/here
+ // file:/home/johndoe/here
+ // file:../johndoe/here
+ // file:~/johndoe/here
+ String temp = url;
+ int nbSlashes = 0;
+ while(nbSlashes<temp.Length && '/'==temp[nbSlashes])
+ nbSlashes++;
+
+ // if we get a path like file:///directory/name we need to convert
+ // this to /directory/name.
+ if(nbSlashes > 2)
+ temp = temp.Substring(nbSlashes-1, temp.Length - (nbSlashes-1));
+ else if (2 == nbSlashes) /* it's a relative path */
+ temp = temp.Substring(nbSlashes, temp.Length - nbSlashes);
+ return temp;
+#endif // !PLATFORM_UNIX
+
+ }
+
+ private void ParseFileURL(String url)
+ {
+
+ String temp = url;
+#if !PLATFORM_UNIX
+ int index = temp.IndexOf( '/');
+
+ if (index != -1 &&
+ ((index == 2 &&
+ temp[index-1] != ':' &&
+ temp[index-1] != '|') ||
+ index != 2) &&
+ index != temp.Length - 1)
+ {
+ // Also, if it is a UNC share, we want m_localSite to
+ // be of the form "computername/share", so if the first
+ // fileEnd character found is a slash, do some more parsing
+ // to find the proper end character.
+
+ int tempIndex = temp.IndexOf( '/', index+1);
+
+ if (tempIndex != -1)
+ index = tempIndex;
+ else
+ index = -1;
+ }
+
+ String localSite;
+ if (index == -1)
+ localSite = temp;
+ else
+ localSite = temp.Substring(0,index);
+
+ if (localSite.Length == 0)
+ throw new ArgumentException( Environment.GetResourceString( "Argument_InvalidUrl" ) );
+
+ int i;
+ bool spacesAllowed;
+
+ if (localSite[0] == '\\' && localSite[1] == '\\')
+ {
+ spacesAllowed = true;
+ i = 2;
+ }
+ else
+ {
+ i = 0;
+ spacesAllowed = false;
+ }
+
+ bool useSmallCharToUpper = true;
+
+ for (; i < localSite.Length; ++i)
+ {
+ char c = localSite[i];
+
+ if ((c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ (c >= '0' && c <= '9') ||
+ (c == '-') || (c == '/') ||
+ (c == ':') || (c == '|') ||
+ (c == '.') || (c == '*') ||
+ (c == '$') || (spacesAllowed && c == ' '))
+ {
+ continue;
+ }
+ else
+ {
+ useSmallCharToUpper = false;
+ break;
+ }
+ }
+
+ if (useSmallCharToUpper)
+ localSite = String.SmallCharToUpper( localSite );
+ else
+ localSite = localSite.ToUpper(CultureInfo.InvariantCulture);
+
+ m_localSite = new LocalSiteString( localSite );
+
+ if (index == -1)
+ {
+ if (localSite[localSite.Length-1] == '*')
+ m_directory = new DirectoryString( "*", false );
+ else
+ m_directory = new DirectoryString();
+ }
+ else
+ {
+ String directoryString = temp.Substring( index + 1 );
+ if (directoryString.Length == 0)
+ {
+ m_directory = new DirectoryString();
+ }
+ else
+ {
+ m_directory = new DirectoryString( directoryString, true);
+ }
+ }
+#else // !PLATFORM_UNIX
+ m_directory = new DirectoryString( temp, true);
+#endif // !PLATFORM_UNIX
+
+ m_siteString = null;
+ return;
+ }
+
+ private void ParseNonFileURL(String url)
+ {
+ String temp = url;
+ int index = temp.IndexOf('/');
+
+ if (index == -1)
+ {
+#if !PLATFORM_UNIX
+ m_localSite = null; // for drive letter
+#endif // !PLATFORM_UNIX
+ m_siteString = new SiteString( temp );
+ m_directory = new DirectoryString();
+ }
+ else
+ {
+#if !PLATFORM_UNIX
+ String site = temp.Substring( 0, index );
+ m_localSite = null;
+ m_siteString = new SiteString( site );
+
+ String directoryString = temp.Substring( index + 1 );
+
+ if (directoryString.Length == 0)
+ {
+ m_directory = new DirectoryString();
+ }
+ else
+ {
+ m_directory = new DirectoryString( directoryString, false );
+ }
+#else
+ String directoryString = temp.Substring( index + 1 );
+ String site = temp.Substring( 0, index );
+ m_directory = new DirectoryString( directoryString, false );
+ m_siteString = new SiteString( site );
+#endif //!PLATFORM_UNIX
+ }
+ return;
+ }
+
+ void DoFastChecks( String url )
+ {
+ if (url == null)
+ {
+ throw new ArgumentNullException( "url" );
+ }
+ Contract.EndContractBlock();
+
+ if (url.Length == 0)
+ {
+ throw new FormatException(Environment.GetResourceString("Format_StringZeroLength"));
+ }
+ }
+
+ // NOTE:
+ // 1. We support URLs that follow the common Internet scheme syntax
+ // (<scheme>://user:pass@<host>:<port>/<url-path>) and all windows file URLs.
+ // 2. In the general case we parse of the site and create a SiteString out of it
+ // (which supports our wildcarding scheme). In the case of files we don't support
+ // wildcarding and furthermore SiteString doesn't like ':' and '|' which can appear
+ // in file urls so we just keep that info in a separate string and set the
+ // SiteString to null.
+ //
+ // ex. http://www.microsoft.com/complus -> m_siteString = "www.microsoft.com" m_localSite = null
+ // ex. file:///c:/complus/mscorlib.dll -> m_siteString = null m_localSite = "c:"
+ // ex. file:///c|/complus/mscorlib.dll -> m_siteString = null m_localSite = "c:"
+ void ParseString( String url, bool parsed )
+ {
+ // If there are any escaped hex or unicode characters in the url, translate those
+ // into the proper character.
+
+ if (!parsed)
+ {
+ url = UnescapeURL(url);
+ }
+
+ // Identify the protocol and strip the protocol info from the string, if present.
+ String temp = ParseProtocol(url);
+
+ bool fileProtocol = (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0);
+
+ // handle any special preocessing...removing extra characters, etc.
+ temp = PreProcessURL(temp, fileProtocol);
+
+ if (fileProtocol)
+ {
+ ParseFileURL(temp);
+ }
+ else
+ {
+ // Check if there is a port number and parse that out.
+ temp = ParsePort(temp);
+ ParseNonFileURL(temp);
+ // Note: that we allow DNS and Netbios names for non-file protocols (since sitestring will check
+ // that the hostname satisfies these two protocols. DNS-only checking can theoretically be added
+ // here but that would break all the programs that use '_' (which is fairly common, yet illegal).
+ // If this needs to be done at any point, add a call to m_siteString.IsLegalDNSName().
+ }
+
+
+ }
+
+ public String Scheme
+ {
+ get
+ {
+ DoDeferredParse();
+
+ return m_protocol;
+ }
+ }
+
+ public String Host
+ {
+ get
+ {
+ DoDeferredParse();
+
+ if (m_siteString != null)
+ {
+ return m_siteString.ToString();
+ }
+ else
+ {
+#if !PLATFORM_UNIX
+ return m_localSite.ToString();
+#else
+ return "";
+#endif // !PLATFORM_UNIX
+ }
+ }
+ }
+
+ public String Port
+ {
+ get
+ {
+ DoDeferredParse();
+
+ if (m_port == -1)
+ return null;
+ else
+ return m_port.ToString(CultureInfo.InvariantCulture);
+ }
+ }
+
+ public String Directory
+ {
+ get
+ {
+ DoDeferredParse();
+
+ return m_directory.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Make a best guess at determining if this is URL refers to a file with a relative path. Since
+ /// this is a guess to help out users of UrlMembershipCondition who may accidentally supply a
+ /// relative URL, we'd rather err on the side of absolute than relative. (We'd rather accept some
+ /// meaningless membership conditions rather than reject meaningful ones).
+ ///
+ /// In order to be a relative file URL, the URL needs to have a protocol of file, and not be on a
+ /// UNC share.
+ ///
+ /// If both of the above are true, then the heuristics we'll use to detect an absolute URL are:
+ /// 1. A host name which is:
+ /// a. greater than one character and ends in a colon (representing the drive letter) OR
+ /// b. ends with a * (so we match any file with the given prefix if any)
+ /// 2. Has a directory name (cannot be simply file://c:)
+ /// </summary>
+ public bool IsRelativeFileUrl
+ {
+ get
+ {
+ DoDeferredParse();
+
+ if (String.Equals(m_protocol, "file", StringComparison.OrdinalIgnoreCase) && !m_isUncShare)
+ {
+#if !PLATFORM_UNIX
+ string host = m_localSite != null ? m_localSite.ToString() : null;
+ // If the host name ends with the * character, treat this as an absolute URL since the *
+ // could represent the rest of the full path.
+ if (host.EndsWith('*'))
+ return false;
+#endif // !PLATFORM_UNIX
+ string directory = m_directory != null ? m_directory.ToString() : null;
+
+#if !PLATFORM_UNIX
+ return host == null || host.Length < 2 || !host.EndsWith(':') ||
+ String.IsNullOrEmpty(directory);
+#else
+ return String.IsNullOrEmpty(directory);
+#endif // !PLATFORM_UNIX
+
+ }
+
+ // Since this is not a local URL, it cannot be relative
+ return false;
+ }
+ }
+
+ public String GetFileName()
+ {
+ DoDeferredParse();
+
+#if !PLATFORM_UNIX
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0)
+ return null;
+
+ String intermediateDirectory = this.Directory.Replace( '/', '\\' );
+
+ String directory = this.Host.Replace( '/', '\\' );
+
+ int directorySlashIndex = directory.IndexOf( '\\' );
+ if (directorySlashIndex == -1)
+ {
+ if (directory.Length != 2 ||
+ !(directory[1] == ':' || directory[1] == '|'))
+ {
+ directory = "\\\\" + directory;
+ }
+ }
+ else if (directorySlashIndex != 2 ||
+ (directorySlashIndex == 2 && directory[1] != ':' && directory[1] != '|'))
+ {
+ directory = "\\\\" + directory;
+ }
+
+ directory += "\\" + intermediateDirectory;
+
+ return directory;
+#else
+ // In Unix, directory contains the full pathname
+ // (this is what we get in Win32)
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase ) != 0)
+ return null;
+
+ return this.Directory;
+#endif // !PLATFORM_UNIX
+ }
+
+
+ public String GetDirectoryName()
+ {
+ DoDeferredParse();
+
+#if !PLATFORM_UNIX
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase ) != 0)
+ return null;
+
+ String intermediateDirectory = this.Directory.Replace( '/', '\\' );
+
+ int slashIndex = 0;
+ for (int i = intermediateDirectory.Length; i > 0; i--)
+ {
+ if (intermediateDirectory[i-1] == '\\')
+ {
+ slashIndex = i;
+ break;
+ }
+ }
+
+ String directory = this.Host.Replace( '/', '\\' );
+
+ int directorySlashIndex = directory.IndexOf( '\\' );
+ if (directorySlashIndex == -1)
+ {
+ if (directory.Length != 2 ||
+ !(directory[1] == ':' || directory[1] == '|'))
+ {
+ directory = "\\\\" + directory;
+ }
+ }
+ else if (directorySlashIndex > 2 ||
+ (directorySlashIndex == 2 && directory[1] != ':' && directory[1] != '|'))
+ {
+ directory = "\\\\" + directory;
+ }
+
+ directory += "\\";
+
+ if (slashIndex > 0)
+ {
+ directory += intermediateDirectory.Substring( 0, slashIndex );
+ }
+
+ return directory;
+#else
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0)
+ return null;
+
+ String directory = this.Directory.ToString();
+ int slashIndex = 0;
+ for (int i = directory.Length; i > 0; i--)
+ {
+ if (directory[i-1] == '/')
+ {
+ slashIndex = i;
+ break;
+ }
+ }
+
+ if (slashIndex > 0)
+ {
+ directory = directory.Substring( 0, slashIndex );
+ }
+
+ return directory;
+#endif // !PLATFORM_UNIX
+ }
+
+ public override SiteString Copy()
+ {
+ return new URLString( m_urlOriginal, m_parsedOriginal );
+ }
+
+ public override bool IsSubsetOf( SiteString site )
+ {
+ if (site == null)
+ {
+ return false;
+ }
+
+ URLString url = site as URLString;
+
+ if (url == null)
+ {
+ return false;
+ }
+
+ DoDeferredParse();
+ url.DoDeferredParse();
+
+ URLString normalUrl1 = this.SpecialNormalizeUrl();
+ URLString normalUrl2 = url.SpecialNormalizeUrl();
+
+ if (String.Compare( normalUrl1.m_protocol, normalUrl2.m_protocol, StringComparison.OrdinalIgnoreCase) == 0 &&
+ normalUrl1.m_directory.IsSubsetOf( normalUrl2.m_directory ))
+ {
+#if !PLATFORM_UNIX
+ if (normalUrl1.m_localSite != null)
+ {
+ // We do a little extra processing in here for local files since we allow
+ // both <drive_letter>: and <drive_letter>| forms of urls.
+
+ return normalUrl1.m_localSite.IsSubsetOf( normalUrl2.m_localSite );
+ }
+ else
+#endif // !PLATFORM_UNIX
+ {
+ if (normalUrl1.m_port != normalUrl2.m_port)
+ return false;
+
+ return normalUrl2.m_siteString != null && normalUrl1.m_siteString.IsSubsetOf( normalUrl2.m_siteString );
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ public override String ToString()
+ {
+ return m_urlOriginal;
+ }
+
+ public override bool Equals(Object o)
+ {
+ DoDeferredParse();
+
+ if (o == null || !(o is URLString))
+ return false;
+ else
+ return this.Equals( (URLString)o );
+ }
+
+ public override int GetHashCode()
+ {
+ DoDeferredParse();
+
+ TextInfo info = CultureInfo.InvariantCulture.TextInfo;
+ int accumulator = 0;
+
+ if (this.m_protocol != null)
+ accumulator = info.GetCaseInsensitiveHashCode( this.m_protocol );
+
+#if !PLATFORM_UNIX
+ if (this.m_localSite != null)
+ {
+ accumulator = accumulator ^ this.m_localSite.GetHashCode();
+ }
+ else
+ {
+ accumulator = accumulator ^ this.m_siteString.GetHashCode();
+ }
+ accumulator = accumulator ^ this.m_directory.GetHashCode();
+#else
+ accumulator = accumulator ^ info.GetCaseInsensitiveHashCode(this.m_urlOriginal);
+#endif // !PLATFORM_UNIX
+
+
+
+ return accumulator;
+ }
+
+ public bool Equals( URLString url )
+ {
+ return CompareUrls( this, url );
+ }
+
+ public static bool CompareUrls( URLString url1, URLString url2 )
+ {
+ if (url1 == null && url2 == null)
+ return true;
+
+ if (url1 == null || url2 == null)
+ return false;
+
+ url1.DoDeferredParse();
+ url2.DoDeferredParse();
+
+ URLString normalUrl1 = url1.SpecialNormalizeUrl();
+ URLString normalUrl2 = url2.SpecialNormalizeUrl();
+
+ // Compare protocol (case insensitive)
+
+ if (String.Compare( normalUrl1.m_protocol, normalUrl2.m_protocol, StringComparison.OrdinalIgnoreCase) != 0)
+ return false;
+
+ // Do special processing for file urls
+
+ if (String.Compare( normalUrl1.m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+#if !PLATFORM_UNIX
+ if (!normalUrl1.m_localSite.IsSubsetOf( normalUrl2.m_localSite ) ||
+ !normalUrl2.m_localSite.IsSubsetOf( normalUrl1.m_localSite ))
+ return false;
+#else
+ return url1.IsSubsetOf( url2 ) &&
+ url2.IsSubsetOf( url1 );
+#endif // !PLATFORM_UNIX
+ }
+ else
+ {
+ if (String.Compare( normalUrl1.m_userpass, normalUrl2.m_userpass, StringComparison.Ordinal) != 0)
+ return false;
+
+ if (!normalUrl1.m_siteString.IsSubsetOf( normalUrl2.m_siteString ) ||
+ !normalUrl2.m_siteString.IsSubsetOf( normalUrl1.m_siteString ))
+ return false;
+
+ if (url1.m_port != url2.m_port)
+ return false;
+ }
+
+ if (!normalUrl1.m_directory.IsSubsetOf( normalUrl2.m_directory ) ||
+ !normalUrl2.m_directory.IsSubsetOf( normalUrl1.m_directory ))
+ return false;
+
+ return true;
+ }
+
+ internal String NormalizeUrl()
+ {
+ DoDeferredParse();
+ StringBuilder builtUrl = StringBuilderCache.Acquire();
+
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+#if !PLATFORM_UNIX
+ builtUrl = builtUrl.AppendFormat("FILE:///{0}/{1}", m_localSite.ToString(), m_directory.ToString());
+#else
+ builtUrl = builtUrl.AppendFormat("FILE:///{0}", m_directory.ToString());
+#endif // !PLATFORM_UNIX
+ }
+ else
+ {
+ builtUrl = builtUrl.AppendFormat("{0}://{1}{2}", m_protocol, m_userpass, m_siteString.ToString());
+
+ if (m_port != -1)
+ builtUrl = builtUrl.AppendFormat("{0}",m_port);
+
+ builtUrl = builtUrl.AppendFormat("/{0}", m_directory.ToString());
+ }
+
+ return StringBuilderCache.GetStringAndRelease(builtUrl).ToUpper(CultureInfo.InvariantCulture);
+ }
+
+#if !PLATFORM_UNIX
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal URLString SpecialNormalizeUrl()
+ {
+ // Under WinXP, file protocol urls can be mapped to
+ // drives that aren't actually file protocol underneath
+ // due to drive mounting. This code attempts to figure
+ // out what a drive is mounted to and create the
+ // url is maps to.
+
+ DoDeferredParse();
+ if (String.Compare( m_protocol, "file", StringComparison.OrdinalIgnoreCase) != 0)
+ {
+ return this;
+ }
+ else
+ {
+ String localSite = m_localSite.ToString();
+
+ if (localSite.Length == 2 &&
+ (localSite[1] == '|' ||
+ localSite[1] == ':'))
+ {
+ String deviceName = null;
+ GetDeviceName(localSite, JitHelpers.GetStringHandleOnStack(ref deviceName));
+
+ if (deviceName != null)
+ {
+ if (deviceName.IndexOf( "://", StringComparison.Ordinal ) != -1)
+ {
+ URLString u = new URLString( deviceName + "/" + this.m_directory.ToString() );
+ u.DoDeferredParse(); // Presumably the caller of SpecialNormalizeUrl wants a fully parsed URL
+ return u;
+ }
+ else
+ {
+ URLString u = new URLString( "file://" + deviceName + "/" + this.m_directory.ToString() );
+ u.DoDeferredParse();// Presumably the caller of SpecialNormalizeUrl wants a fully parsed URL
+ return u;
+ }
+ }
+ else
+ return this;
+ }
+ else
+ {
+ return this;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetDeviceName( String driveLetter, StringHandleOnStack retDeviceName );
+
+#else
+ internal URLString SpecialNormalizeUrl()
+ {
+ return this;
+ }
+#endif // !PLATFORM_UNIX
+
+ }
+
+
+ [Serializable]
+ internal class DirectoryString : SiteString
+ {
+ private bool m_checkForIllegalChars;
+
+ private new static char[] m_separators = { '/' };
+
+ // From KB #Q177506, file/folder illegal characters are \ / : * ? " < > |
+ protected static char[] m_illegalDirectoryCharacters = { '\\', ':', '*', '?', '"', '<', '>', '|' };
+
+ public DirectoryString()
+ {
+ m_site = "";
+ m_separatedSite = new ArrayList();
+ }
+
+ public DirectoryString( String directory, bool checkForIllegalChars )
+ {
+ m_site = directory;
+ m_checkForIllegalChars = checkForIllegalChars;
+ m_separatedSite = CreateSeparatedString(directory);
+ }
+
+ private ArrayList CreateSeparatedString(String directory)
+ {
+ if (directory == null || directory.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ Contract.EndContractBlock();
+
+ ArrayList list = new ArrayList();
+ String[] separatedArray = directory.Split(m_separators);
+
+ for (int index = 0; index < separatedArray.Length; ++index)
+ {
+ if (separatedArray[index] == null || separatedArray[index].Equals( "" ))
+ {
+ // this case is fine, we just ignore it the extra separators.
+ }
+ else if (separatedArray[index].Equals( "*" ))
+ {
+ if (index != separatedArray.Length-1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ list.Add( separatedArray[index] );
+ }
+ else if (m_checkForIllegalChars && separatedArray[index].IndexOfAny( m_illegalDirectoryCharacters ) != -1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ else
+ {
+ list.Add( separatedArray[index] );
+ }
+ }
+
+ return list;
+ }
+
+ public virtual bool IsSubsetOf( DirectoryString operand )
+ {
+ return this.IsSubsetOf( operand, true );
+ }
+
+ public virtual bool IsSubsetOf( DirectoryString operand, bool ignoreCase )
+ {
+ if (operand == null)
+ {
+ return false;
+ }
+ else if (operand.m_separatedSite.Count == 0)
+ {
+ return this.m_separatedSite.Count == 0 || this.m_separatedSite.Count > 0 && String.Compare((String)this.m_separatedSite[0], "*", StringComparison.Ordinal) == 0;
+ }
+ else if (this.m_separatedSite.Count == 0)
+ {
+ return String.Compare((String)operand.m_separatedSite[0], "*", StringComparison.Ordinal) == 0;
+ }
+ else
+ {
+ return base.IsSubsetOf( operand, ignoreCase );
+ }
+ }
+ }
+
+#if !PLATFORM_UNIX
+ [Serializable]
+ internal class LocalSiteString : SiteString
+ {
+ private new static char[] m_separators = { '/' };
+
+ public LocalSiteString( String site )
+ {
+ m_site = site.Replace( '|', ':');
+
+ if (m_site.Length > 2 && m_site.IndexOf( ':' ) != -1)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+
+ m_separatedSite = CreateSeparatedString(m_site);
+ }
+
+ private ArrayList CreateSeparatedString(String directory)
+ {
+ if (directory == null || directory.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ Contract.EndContractBlock();
+
+ ArrayList list = new ArrayList();
+ String[] separatedArray = directory.Split(m_separators);
+
+ for (int index = 0; index < separatedArray.Length; ++index)
+ {
+ if (separatedArray[index] == null || separatedArray[index].Equals( "" ))
+ {
+ if (index < 2 &&
+ directory[index] == '/')
+ {
+ list.Add( "//" );
+ }
+ else if (index != separatedArray.Length-1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ }
+ else if (separatedArray[index].Equals( "*" ))
+ {
+ if (index != separatedArray.Length-1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDirectoryOnUrl"));
+ }
+ list.Add( separatedArray[index] );
+ }
+ else
+ {
+ list.Add( separatedArray[index] );
+ }
+ }
+
+ return list;
+ }
+
+ public virtual bool IsSubsetOf( LocalSiteString operand )
+ {
+ return this.IsSubsetOf( operand, true );
+ }
+
+ public virtual bool IsSubsetOf( LocalSiteString operand, bool ignoreCase )
+ {
+ if (operand == null)
+ {
+ return false;
+ }
+ else if (operand.m_separatedSite.Count == 0)
+ {
+ return this.m_separatedSite.Count == 0 || this.m_separatedSite.Count > 0 && String.Compare((String)this.m_separatedSite[0], "*", StringComparison.Ordinal) == 0;
+ }
+ else if (this.m_separatedSite.Count == 0)
+ {
+ return String.Compare((String)operand.m_separatedSite[0], "*", StringComparison.Ordinal) == 0;
+ }
+ else
+ {
+ return base.IsSubsetOf( operand, ignoreCase );
+ }
+ }
+ }
+#endif // !PLATFORM_UNIX
+}
diff --git a/src/mscorlib/src/System/Security/Util/XMLUtil.cs b/src/mscorlib/src/System/Security/Util/XMLUtil.cs
new file mode 100644
index 0000000000..df8f0c4670
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/XMLUtil.cs
@@ -0,0 +1,695 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** PURPOSE: Helpers for XML input & output
+**
+===========================================================*/
+namespace System.Security.Util {
+
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Security.Policy;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Remoting;
+ using System.IO;
+ using System.Text;
+ using System.Runtime.CompilerServices;
+ using PermissionState = System.Security.Permissions.PermissionState;
+ using BindingFlags = System.Reflection.BindingFlags;
+ using Assembly = System.Reflection.Assembly;
+ using System.Threading;
+ using System.Globalization;
+ using System.Reflection;
+ using System.Diagnostics.Contracts;
+
+ internal static class XMLUtil
+ {
+ //
+ // Warning: Element constructors have side-effects on their
+ // third argument.
+ //
+
+ private const String BuiltInPermission = "System.Security.Permissions.";
+#if FEATURE_CAS_POLICY
+ private const String BuiltInMembershipCondition = "System.Security.Policy.";
+ private const String BuiltInCodeGroup = "System.Security.Policy.";
+ private const String BuiltInApplicationSecurityManager = "System.Security.Policy.";
+ private static readonly char[] sepChar = {',', ' '};
+#endif
+ public static SecurityElement
+ NewPermissionElement (IPermission ip)
+ {
+ return NewPermissionElement (ip.GetType ().FullName) ;
+ }
+
+ public static SecurityElement
+ NewPermissionElement (String name)
+ {
+ SecurityElement ecr = new SecurityElement( "Permission" );
+ ecr.AddAttribute( "class", name );
+ return ecr;
+ }
+
+ public static void
+ AddClassAttribute( SecurityElement element, Type type, String typename )
+ {
+ // Replace any quotes with apostrophes so that we can include quoted materials
+ // within classnames. Notably the assembly name member 'loc' uses a quoted string.
+
+ // NOTE: this makes assumptions as to what reflection is expecting for a type string
+ // it will need to be updated if reflection changes what it wants.
+
+ if ( typename == null )
+ typename = type.FullName;
+ Contract.Assert( type.FullName.Equals( typename ), "Incorrect class name passed! Was : " + typename + " Shoule be: " + type.FullName);
+ element.AddAttribute( "class", typename + ", " + type.Module.Assembly.FullName.Replace( '\"', '\'' ) );
+ }
+
+ internal static bool ParseElementForAssemblyIdentification(SecurityElement el,
+ out String className,
+ out String assemblyName, // for example "WindowsBase"
+ out String assemblyVersion)
+ {
+
+ className = null;
+ assemblyName = null;
+ assemblyVersion = null;
+
+ String fullClassName = el.Attribute( "class" );
+
+ if (fullClassName == null)
+ {
+ return false;
+ }
+ if (fullClassName.IndexOf('\'') >= 0)
+ {
+ fullClassName = fullClassName.Replace( '\'', '\"' );
+ }
+
+ int commaIndex = fullClassName.IndexOf( ',' );
+ int namespaceClassNameLength;
+
+ // If the classname is tagged with assembly information, find where
+ // the assembly information begins.
+
+ if (commaIndex == -1)
+ {
+ return false;
+ }
+
+ namespaceClassNameLength = commaIndex;
+ className = fullClassName.Substring(0, namespaceClassNameLength);
+ String assemblyFullName = fullClassName.Substring(commaIndex + 1);
+ AssemblyName an = new AssemblyName(assemblyFullName);
+ assemblyName = an.Name;
+ assemblyVersion = an.Version.ToString();
+ return true;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool
+ ParseElementForObjectCreation( SecurityElement el,
+ String requiredNamespace,
+ out String className,
+ out int classNameStart,
+ out int classNameLength )
+ {
+ className = null;
+ classNameStart = 0;
+ classNameLength = 0;
+
+ int requiredNamespaceLength = requiredNamespace.Length;
+
+ String fullClassName = el.Attribute( "class" );
+
+ if (fullClassName == null)
+ {
+ throw new ArgumentException( Environment.GetResourceString( "Argument_NoClass" ) );
+ }
+
+ if (fullClassName.IndexOf('\'') >= 0)
+ {
+ fullClassName = fullClassName.Replace( '\'', '\"' );
+ }
+
+ if (!PermissionToken.IsMscorlibClassName( fullClassName ))
+ {
+ return false;
+ }
+
+ int commaIndex = fullClassName.IndexOf( ',' );
+ int namespaceClassNameLength;
+
+ // If the classname is tagged with assembly information, find where
+ // the assembly information begins.
+
+ if (commaIndex == -1)
+ {
+ namespaceClassNameLength = fullClassName.Length;
+ }
+ else
+ {
+ namespaceClassNameLength = commaIndex;
+ }
+
+ // Only if the length of the class name is greater than the namespace info
+ // on our requiredNamespace do we continue
+ // with our check.
+
+ if (namespaceClassNameLength > requiredNamespaceLength)
+ {
+ // Make sure we are in the required namespace.
+ if (fullClassName.StartsWith(requiredNamespace, StringComparison.Ordinal))
+ {
+ className = fullClassName;
+ classNameLength = namespaceClassNameLength - requiredNamespaceLength;
+ classNameStart = requiredNamespaceLength;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+#if FEATURE_CAS_POLICY
+ public static String SecurityObjectToXmlString(Object ob)
+ {
+ if(ob == null)
+ return "";
+ PermissionSet pset = ob as PermissionSet;
+ if(pset != null)
+ return pset.ToXml().ToString();
+ return ((IPermission)ob).ToXml().ToString();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public static Object XmlStringToSecurityObject(String s)
+ {
+ if(s == null)
+ return null;
+ if(s.Length < 1)
+ return null;
+ return SecurityElement.FromString(s).ToSecurityObject();
+ }
+#endif // FEATURE_CAS_POLICY
+
+ [SecuritySafeCritical]
+ public static IPermission
+ CreatePermission (SecurityElement el, PermissionState permState, bool ignoreTypeLoadFailures)
+ {
+ if (el == null || !(el.Tag.Equals("Permission") || el.Tag.Equals("IPermission")) )
+ throw new ArgumentException( String.Format( null, Environment.GetResourceString( "Argument_WrongElementType" ), "<Permission>" ) ) ;
+ Contract.EndContractBlock();
+
+ String className;
+ int classNameLength;
+ int classNameStart;
+
+ if (!ParseElementForObjectCreation( el,
+ BuiltInPermission,
+ out className,
+ out classNameStart,
+ out classNameLength ))
+ {
+ goto USEREFLECTION;
+ }
+
+ // We have a built in permission, figure out which it is.
+
+ // UIPermission
+ // FileIOPermission
+ // SecurityPermission
+ // PrincipalPermission
+ // ReflectionPermission
+ // FileDialogPermission
+ // EnvironmentPermission
+ // GacIdentityPermission
+ // UrlIdentityPermission
+ // SiteIdentityPermission
+ // ZoneIdentityPermission
+ // KeyContainerPermission
+ // UnsafeForHostPermission
+ // HostProtectionPermission
+ // StrongNameIdentityPermission
+#if !FEATURE_CORECLR
+ // IsolatedStorageFilePermission
+#endif
+ // RegistryPermission
+ // PublisherIdentityPermission
+
+ switch (classNameLength)
+ {
+ case 12:
+ // UIPermission
+ if (String.Compare(className, classNameStart, "UIPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new UIPermission( permState );
+ else
+ goto USEREFLECTION;
+
+ case 16:
+ // FileIOPermission
+ if (String.Compare(className, classNameStart, "FileIOPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new FileIOPermission( permState );
+ else
+ goto USEREFLECTION;
+
+ case 18:
+ // RegistryPermission
+ // SecurityPermission
+ if (className[classNameStart] == 'R')
+ {
+ if (String.Compare(className, classNameStart, "RegistryPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new RegistryPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "SecurityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new SecurityPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+
+#if !FEATURE_CORECLR
+ case 19:
+ // PrincipalPermission
+ if (String.Compare(className, classNameStart, "PrincipalPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new PrincipalPermission( permState );
+ else
+ goto USEREFLECTION;
+#endif // !FEATURE_CORECLR
+ case 20:
+ // ReflectionPermission
+ // FileDialogPermission
+ if (className[classNameStart] == 'R')
+ {
+ if (String.Compare(className, classNameStart, "ReflectionPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new ReflectionPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "FileDialogPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new FileDialogPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+
+ case 21:
+ // EnvironmentPermission
+ // UrlIdentityPermission
+ // GacIdentityPermission
+ if (className[classNameStart] == 'E')
+ {
+ if (String.Compare(className, classNameStart, "EnvironmentPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new EnvironmentPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else if (className[classNameStart] == 'U')
+ {
+ if (String.Compare(className, classNameStart, "UrlIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new UrlIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "GacIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new GacIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+
+
+ case 22:
+ // SiteIdentityPermission
+ // ZoneIdentityPermission
+ // KeyContainerPermission
+ if (className[classNameStart] == 'S')
+ {
+ if (String.Compare(className, classNameStart, "SiteIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new SiteIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else if (className[classNameStart] == 'Z')
+ {
+ if (String.Compare(className, classNameStart, "ZoneIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new ZoneIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "KeyContainerPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new KeyContainerPermission( permState );
+ else
+ goto USEREFLECTION;
+ }
+
+
+ case 24:
+ // HostProtectionPermission
+ if (String.Compare(className, classNameStart, "HostProtectionPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new HostProtectionPermission( permState );
+ else
+ goto USEREFLECTION;
+
+#if FEATURE_X509 && FEATURE_CAS_POLICY
+ case 27:
+ // PublisherIdentityPermission
+ if (String.Compare(className, classNameStart, "PublisherIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new PublisherIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+#endif // FEATURE_X509 && FEATURE_CAS_POLICY
+
+ case 28:
+ // StrongNameIdentityPermission
+ if (String.Compare(className, classNameStart, "StrongNameIdentityPermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new StrongNameIdentityPermission( permState );
+ else
+ goto USEREFLECTION;
+#if !FEATURE_CORECLR
+ case 29:
+ // IsolatedStorageFilePermission
+ if (String.Compare(className, classNameStart, "IsolatedStorageFilePermission", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new IsolatedStorageFilePermission( permState );
+ else
+ goto USEREFLECTION;
+#endif
+ default:
+ goto USEREFLECTION;
+ }
+
+USEREFLECTION:
+
+ Object[] objs = new Object[1];
+ objs[0] = permState;
+
+ Type permClass = null;
+ IPermission perm = null;
+
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
+ permClass = GetClassFromElement(el, ignoreTypeLoadFailures);
+ if (permClass == null)
+ return null;
+ if (!(typeof(IPermission).IsAssignableFrom(permClass)))
+ throw new ArgumentException( Environment.GetResourceString("Argument_NotAPermissionType") );
+
+ perm = (IPermission) Activator.CreateInstance(permClass, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public, null, objs, null );
+
+ return perm;
+ }
+
+#if FEATURE_CAS_POLICY
+#pragma warning disable 618 // CodeGroups are obsolete
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static CodeGroup
+ CreateCodeGroup (SecurityElement el)
+ {
+ if (el == null || !el.Tag.Equals("CodeGroup"))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_WrongElementType" ), "<CodeGroup>" ) ) ;
+ Contract.EndContractBlock();
+
+ String className;
+ int classNameLength;
+ int classNameStart;
+
+ if (!ParseElementForObjectCreation( el,
+ BuiltInCodeGroup,
+ out className,
+ out classNameStart,
+ out classNameLength ))
+ {
+ goto USEREFLECTION;
+ }
+
+ switch (classNameLength)
+ {
+ case 12:
+ // NetCodeGroup
+ if (String.Compare(className, classNameStart, "NetCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new NetCodeGroup();
+ else
+ goto USEREFLECTION;
+
+ case 13:
+ // FileCodeGroup
+ if (String.Compare(className, classNameStart, "FileCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new FileCodeGroup();
+ else
+ goto USEREFLECTION;
+ case 14:
+ // UnionCodeGroup
+ if (String.Compare(className, classNameStart, "UnionCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new UnionCodeGroup();
+ else
+ goto USEREFLECTION;
+
+ case 19:
+ // FirstMatchCodeGroup
+ if (String.Compare(className, classNameStart, "FirstMatchCodeGroup", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new FirstMatchCodeGroup();
+ else
+ goto USEREFLECTION;
+
+ default:
+ goto USEREFLECTION;
+ }
+
+USEREFLECTION:
+ Type groupClass = null;
+ CodeGroup group = null;
+
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
+ groupClass = GetClassFromElement(el, true);
+ if (groupClass == null)
+ return null;
+ if (!(typeof(CodeGroup).IsAssignableFrom(groupClass)))
+ throw new ArgumentException( Environment.GetResourceString("Argument_NotACodeGroupType") );
+
+ group = (CodeGroup) Activator.CreateInstance(groupClass, true);
+
+ Contract.Assert( groupClass.Module.Assembly != Assembly.GetExecutingAssembly(),
+ "This path should not get called for mscorlib based classes" );
+
+ return group;
+ }
+#pragma warning restore 618
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static IMembershipCondition
+ CreateMembershipCondition( SecurityElement el )
+ {
+ if (el == null || !el.Tag.Equals("IMembershipCondition"))
+ throw new ArgumentException( String.Format( CultureInfo.CurrentCulture, Environment.GetResourceString( "Argument_WrongElementType" ), "<IMembershipCondition>" ) ) ;
+ Contract.EndContractBlock();
+
+ String className;
+ int classNameStart;
+ int classNameLength;
+
+ if (!ParseElementForObjectCreation( el,
+ BuiltInMembershipCondition,
+ out className,
+ out classNameStart,
+ out classNameLength ))
+ {
+ goto USEREFLECTION;
+ }
+
+ // We have a built in membership condition, figure out which it is.
+
+ // Here's the list of built in membership conditions as of 9/17/2002
+ // System.Security.Policy.AllMembershipCondition
+ // System.Security.Policy.URLMembershipCondition
+ // System.Security.Policy.SHA1MembershipCondition
+ // System.Security.Policy.SiteMembershipCondition
+ // System.Security.Policy.ZoneMembershipCondition
+ // System.Security.Policy.PublisherMembershipCondition
+ // System.Security.Policy.StrongNameMembershipCondition
+ // System.Security.Policy.ApplicationMembershipCondition
+ // System.Security.Policy.DomainApplicationMembershipCondition
+ // System.Security.Policy.ApplicationDirectoryMembershipCondition
+
+ switch (classNameLength)
+ {
+ case 22:
+ // AllMembershipCondition
+ // URLMembershipCondition
+ if (className[classNameStart] == 'A')
+ {
+ if (String.Compare(className, classNameStart, "AllMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new AllMembershipCondition();
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "UrlMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new UrlMembershipCondition();
+ else
+ goto USEREFLECTION;
+ }
+
+ case 23:
+ // HashMembershipCondition
+ // SiteMembershipCondition
+ // ZoneMembershipCondition
+ if (className[classNameStart] == 'H')
+ {
+ if (String.Compare(className, classNameStart, "HashMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new HashMembershipCondition();
+ else
+ goto USEREFLECTION;
+ }
+ else if (className[classNameStart] == 'S')
+ {
+ if (String.Compare(className, classNameStart, "SiteMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new SiteMembershipCondition();
+ else
+ goto USEREFLECTION;
+ }
+ else
+ {
+ if (String.Compare(className, classNameStart, "ZoneMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new ZoneMembershipCondition();
+ else
+ goto USEREFLECTION;
+ }
+
+ case 28:
+ // PublisherMembershipCondition
+ if (String.Compare(className, classNameStart, "PublisherMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new PublisherMembershipCondition();
+ else
+ goto USEREFLECTION;
+
+ case 29:
+ // StrongNameMembershipCondition
+ if (String.Compare(className, classNameStart, "StrongNameMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new StrongNameMembershipCondition();
+ else
+ goto USEREFLECTION;
+
+ case 39:
+ // ApplicationDirectoryMembershipCondition
+ if (String.Compare(className, classNameStart, "ApplicationDirectoryMembershipCondition", 0, classNameLength, StringComparison.Ordinal) == 0)
+ return new ApplicationDirectoryMembershipCondition();
+ else
+ goto USEREFLECTION;
+
+ default:
+ goto USEREFLECTION;
+ }
+
+USEREFLECTION:
+ Type condClass = null;
+ IMembershipCondition cond = null;
+
+ new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Assert();
+ condClass = GetClassFromElement(el, true);
+ if (condClass == null)
+ return null;
+ if (!(typeof(IMembershipCondition).IsAssignableFrom(condClass)))
+ throw new ArgumentException( Environment.GetResourceString("Argument_NotAMembershipCondition") );
+
+ cond = (IMembershipCondition) Activator.CreateInstance(condClass, true);
+
+ return cond;
+ }
+#endif //#if FEATURE_CAS_POLICY
+ internal static Type
+ GetClassFromElement (SecurityElement el, bool ignoreTypeLoadFailures)
+ {
+ String className = el.Attribute( "class" );
+
+ if (className == null)
+ {
+ if (ignoreTypeLoadFailures)
+ return null;
+ else
+ throw new ArgumentException( String.Format( null, Environment.GetResourceString("Argument_InvalidXMLMissingAttr"), "class") );
+ }
+
+ if (ignoreTypeLoadFailures)
+ {
+ try
+ {
+ return Type.GetType(className, false, false);
+ }
+ catch (SecurityException)
+ {
+ return null;
+ }
+ }
+ else
+ return Type.GetType(className, true, false);
+ }
+
+ public static bool
+ IsPermissionElement (IPermission ip,
+ SecurityElement el)
+ {
+ if (!el.Tag.Equals ("Permission") && !el.Tag.Equals ("IPermission"))
+ return false;
+
+ return true;
+ }
+
+ public static bool
+ IsUnrestricted (SecurityElement el)
+ {
+ String sUnrestricted = el.Attribute( "Unrestricted" );
+
+ if (sUnrestricted == null)
+ return false;
+
+ return sUnrestricted.Equals( "true" ) || sUnrestricted.Equals( "TRUE" ) || sUnrestricted.Equals( "True" );
+ }
+
+
+ public static String BitFieldEnumToString( Type type, Object value )
+ {
+ int iValue = (int)value;
+
+ if (iValue == 0)
+ return Enum.GetName( type, 0 );
+
+ StringBuilder result = StringBuilderCache.Acquire();
+ bool first = true;
+ int flag = 0x1;
+
+ for (int i = 1; i < 32; ++i)
+ {
+ if ((flag & iValue) != 0)
+ {
+ String sFlag = Enum.GetName( type, flag );
+
+ if (sFlag == null)
+ continue;
+
+ if (!first)
+ {
+ result.Append( ", " );
+ }
+
+ result.Append( sFlag );
+ first = false;
+ }
+
+ flag = flag << 1;
+ }
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/Util/sitestring.cs b/src/mscorlib/src/System/Security/Util/sitestring.cs
new file mode 100644
index 0000000000..28f23742ec
--- /dev/null
+++ b/src/mscorlib/src/System/Security/Util/sitestring.cs
@@ -0,0 +1,289 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security.Util {
+ using System;
+ using System.Collections;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal class SiteString
+ {
+ protected String m_site;
+ protected ArrayList m_separatedSite;
+
+ protected static char[] m_separators = { '.' };
+
+ protected internal SiteString()
+ {
+ // Only call this in derived classes when you know what you're doing.
+ }
+
+ public SiteString( String site )
+ {
+ m_separatedSite = CreateSeparatedSite( site );
+ m_site = site;
+ }
+
+ private SiteString(String site, ArrayList separatedSite)
+ {
+ m_separatedSite = separatedSite;
+ m_site = site;
+ }
+
+ private static ArrayList CreateSeparatedSite(String site)
+ {
+ if (site == null || site.Length == 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
+ }
+ Contract.EndContractBlock();
+
+ ArrayList list = new ArrayList();
+ int braIndex = -1;
+ int ketIndex = -1;
+ braIndex = site.IndexOf('[');
+ if (braIndex == 0)
+ ketIndex = site.IndexOf(']', braIndex+1);
+
+ if (ketIndex != -1)
+ {
+ // Found an IPv6 address. Special case that
+ String ipv6Addr = site.Substring(braIndex+1, ketIndex-braIndex-1);
+ list.Add(ipv6Addr);
+ return list;
+ }
+
+ // Regular hostnames or IPv4 addresses
+ // We dont need to do this for IPv4 addresses, but it's easier to do it anyway
+ String[] separatedArray = site.Split( m_separators );
+
+ for (int index = separatedArray.Length-1; index > -1; --index)
+ {
+ if (separatedArray[index] == null)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
+ }
+ else if (separatedArray[index].Equals( "" ))
+ {
+ if (index != separatedArray.Length-1)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
+ }
+ }
+ else if (separatedArray[index].Equals( "*" ))
+ {
+ if (index != 0)
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
+ }
+ list.Add( separatedArray[index] );
+ }
+ else if (!AllLegalCharacters( separatedArray[index] ))
+ {
+ throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
+ }
+ else
+ {
+ list.Add( separatedArray[index] );
+ }
+ }
+
+ return list;
+ }
+
+ // KB# Q188997 - http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q188997& gives the list of allowed characters in
+ // a NETBIOS name. DNS names are a subset of that (alphanumeric or '-').
+ private static bool AllLegalCharacters( String str )
+ {
+ for (int i = 0; i < str.Length; ++i)
+ {
+ char c = str[i];
+
+ if (IsLegalDNSChar(c) ||
+ IsNetbiosSplChar(c))
+ {
+ continue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static bool IsLegalDNSChar(char c)
+ {
+ if ((c >= 'a' && c <= 'z') ||
+ (c >= 'A' && c <= 'Z') ||
+ (c >= '0' && c <= '9') ||
+ (c == '-'))
+ return true;
+ else
+ return false;
+ }
+ private static bool IsNetbiosSplChar(char c)
+ {
+ // ! @ # $ % ^ & ( ) - _ ' { } . ~ are OK
+ switch (c) {
+ case '-':
+ case '_':
+ case '@':
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '^':
+ case '&':
+ case '(':
+ case ')':
+ case '\'':
+ case '{':
+ case '}':
+ case '.':
+ case '~':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public override String ToString()
+ {
+ return m_site;
+ }
+
+ public override bool Equals(Object o)
+ {
+ if (o == null || !(o is SiteString))
+ return false;
+ else
+ return this.Equals( (SiteString)o, true );
+ }
+
+ public override int GetHashCode()
+ {
+ TextInfo info = CultureInfo.InvariantCulture.TextInfo;
+
+ return info.GetCaseInsensitiveHashCode( this.m_site );
+ }
+
+ internal bool Equals( SiteString ss, bool ignoreCase )
+ {
+ if (this.m_site == null)
+ return ss.m_site == null;
+ if (ss.m_site == null)
+ return false;
+ return this.IsSubsetOf(ss, ignoreCase) && ss.IsSubsetOf(this, ignoreCase);
+ }
+
+
+ public virtual SiteString Copy()
+ {
+ return new SiteString( m_site, m_separatedSite );
+ }
+
+ public virtual bool IsSubsetOf( SiteString operand )
+ {
+ return this.IsSubsetOf( operand, true );
+ }
+
+ public virtual bool IsSubsetOf( SiteString operand, bool ignoreCase )
+ {
+ StringComparison strComp = (ignoreCase? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
+ if (operand == null)
+ {
+ return false;
+ }
+ else if (this.m_separatedSite.Count == operand.m_separatedSite.Count &&
+ this.m_separatedSite.Count == 0)
+ {
+ return true;
+ }
+ else if (this.m_separatedSite.Count < operand.m_separatedSite.Count - 1)
+ {
+ return false;
+ }
+ else if (this.m_separatedSite.Count > operand.m_separatedSite.Count &&
+ operand.m_separatedSite.Count > 0 &&
+ !operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*"))
+ {
+ return false;
+ }
+ else if (String.Compare( this.m_site, operand.m_site, strComp) == 0)
+ {
+ return true;
+ }
+
+ for (int index = 0; index < operand.m_separatedSite.Count - 1; ++index)
+ {
+ if (String.Compare((String)this.m_separatedSite[index], (String)operand.m_separatedSite[index], strComp) != 0)
+ {
+ return false;
+ }
+ }
+
+ if (this.m_separatedSite.Count < operand.m_separatedSite.Count)
+ {
+ return operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*");
+ }
+ else if (this.m_separatedSite.Count == operand.m_separatedSite.Count)
+ {
+ // last item must be the same or operand must have a * in its last item
+ return (String.Compare((String)this.m_separatedSite[this.m_separatedSite.Count - 1],
+ (String)operand.m_separatedSite[this.m_separatedSite.Count - 1],
+ strComp ) == 0 ||
+ operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*"));
+
+ }
+ else
+ return true;
+ }
+
+
+
+ public virtual SiteString Intersect( SiteString operand )
+ {
+ if (operand == null)
+ {
+ return null;
+ }
+ else if (this.IsSubsetOf( operand ))
+ {
+ return this.Copy();
+ }
+ else if (operand.IsSubsetOf( this ))
+ {
+ return operand.Copy();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public virtual SiteString Union( SiteString operand )
+ {
+ if (operand == null)
+ {
+ return this;
+ }
+ else if (this.IsSubsetOf( operand ))
+ {
+ return operand.Copy();
+ }
+ else if (operand.IsSubsetOf( this ))
+ {
+ return this.Copy();
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/VerificationException.cs b/src/mscorlib/src/System/Security/VerificationException.cs
new file mode 100644
index 0000000000..b0823cac01
--- /dev/null
+++ b/src/mscorlib/src/System/Security/VerificationException.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Security {
+ using System.Security;
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class VerificationException : SystemException {
+ public VerificationException()
+ : base(Environment.GetResourceString("Verification_Exception")) {
+ SetErrorCode(__HResults.COR_E_VERIFICATION);
+ }
+
+ public VerificationException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_VERIFICATION);
+ }
+
+ public VerificationException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_VERIFICATION);
+ }
+
+ protected VerificationException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Security/securestring.cs b/src/mscorlib/src/System/Security/securestring.cs
new file mode 100644
index 0000000000..b53d0db5b4
--- /dev/null
+++ b/src/mscorlib/src/System/Security/securestring.cs
@@ -0,0 +1,750 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+namespace System.Security {
+ using System.Security.Cryptography;
+ using System.Runtime.InteropServices;
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Runtime.ExceptionServices;
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Text;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using Microsoft.Win32.SafeHandles;
+ using System.Diagnostics.Contracts;
+
+ public sealed class SecureString: IDisposable {
+ [System.Security.SecurityCritical] // auto-generated
+ private SafeBSTRHandle m_buffer;
+ [ContractPublicPropertyName("Length")]
+ private int m_length;
+ private bool m_readOnly;
+ private bool m_encrypted;
+
+ static bool supportedOnCurrentPlatform = EncryptionSupported();
+
+ const int BlockSize = (int)Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE /2; // a char is two bytes
+ const int MaxLength = 65536;
+ const uint ProtectionScope = Win32Native.CRYPTPROTECTMEMORY_SAME_PROCESS;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static SecureString()
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe static bool EncryptionSupported() {
+ // check if the enrypt/decrypt function is supported on current OS
+ bool supported = true;
+ try {
+ Win32Native.SystemFunction041(
+ SafeBSTRHandle.Allocate(null , (int)Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE),
+ Win32Native.CRYPTPROTECTMEMORY_BLOCK_SIZE,
+ Win32Native.CRYPTPROTECTMEMORY_SAME_PROCESS);
+ }
+ catch (EntryPointNotFoundException) {
+ supported = false;
+ }
+ return supported;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal SecureString(SecureString str) {
+ AllocateBuffer(str.BufferLength);
+ SafeBSTRHandle.Copy(str.m_buffer, this.m_buffer);
+ m_length = str.m_length;
+ m_encrypted = str.m_encrypted;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public SecureString() {
+ CheckSupportedOnCurrentPlatform();
+
+ // allocate the minimum block size for calling protectMemory
+ AllocateBuffer(BlockSize);
+ m_length = 0;
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ private unsafe void InitializeSecureString(char* value, int length)
+ {
+ CheckSupportedOnCurrentPlatform();
+
+ AllocateBuffer(length);
+ m_length = length;
+
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ m_buffer.AcquirePointer(ref bufferPtr);
+ Buffer.Memcpy(bufferPtr, (byte*)value, length * 2);
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally
+ {
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+
+ ProtectMemory();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe SecureString(char* value, int length) {
+ if( value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if( length < 0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if( length > MaxLength) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Length"));
+ }
+ Contract.EndContractBlock();
+
+ // Refactored since HandleProcessCorruptedStateExceptionsAttribute applies to methods only (yet).
+ InitializeSecureString(value, length);
+ }
+
+ public int Length {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ get {
+ EnsureNotDisposed();
+ return m_length;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ public void AppendChar(char c) {
+ EnsureNotDisposed();
+ EnsureNotReadOnly();
+
+ EnsureCapacity(m_length + 1);
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ UnProtectMemory();
+ m_buffer.Write<char>((uint)m_length * sizeof(char), c);
+ m_length++;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+ }
+ }
+
+ // clears the current contents. Only available if writable
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public void Clear() {
+ EnsureNotDisposed();
+ EnsureNotReadOnly();
+
+ m_length = 0;
+ m_buffer.ClearBuffer();
+ m_encrypted = false;
+ }
+
+ // Do a deep-copy of the SecureString
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public SecureString Copy() {
+ EnsureNotDisposed();
+ return new SecureString(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public void Dispose() {
+ if(m_buffer != null && !m_buffer.IsInvalid) {
+ m_buffer.Close();
+ m_buffer = null;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ public void InsertAt( int index, char c ) {
+ if( index < 0 || index > m_length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
+ }
+ Contract.EndContractBlock();
+
+ EnsureNotDisposed();
+ EnsureNotReadOnly();
+
+ EnsureCapacity(m_length + 1);
+
+ unsafe {
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ UnProtectMemory();
+ m_buffer.AcquirePointer(ref bufferPtr);
+ char* pBuffer = (char*)bufferPtr;
+
+ for (int i = m_length; i > index; i--) {
+ pBuffer[i] = pBuffer[i - 1];
+ }
+ pBuffer[index] = c;
+ ++m_length;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public bool IsReadOnly() {
+ EnsureNotDisposed();
+ return m_readOnly;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+ public void MakeReadOnly() {
+ EnsureNotDisposed();
+ m_readOnly = true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ public void RemoveAt( int index ) {
+ EnsureNotDisposed();
+ EnsureNotReadOnly();
+
+ if( index < 0 || index >= m_length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
+ }
+
+ unsafe
+ {
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ UnProtectMemory();
+ m_buffer.AcquirePointer(ref bufferPtr);
+ char* pBuffer = (char*)bufferPtr;
+
+ for (int i = index; i < m_length - 1; i++)
+ {
+ pBuffer[i] = pBuffer[i + 1];
+ }
+ pBuffer[--m_length] = (char)0;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally
+ {
+ ProtectMemory();
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ public void SetAt( int index, char c ) {
+ if( index < 0 || index >= m_length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_IndexString"));
+ }
+ Contract.EndContractBlock();
+ Contract.Assert(index <= Int32.MaxValue / sizeof(char));
+
+ EnsureNotDisposed();
+ EnsureNotReadOnly();
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ UnProtectMemory();
+ m_buffer.Write<char>((uint)index * sizeof(char), c);
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+ }
+ }
+
+ private int BufferLength {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ Contract.Assert(m_buffer != null, "Buffer is not initialized!");
+ return m_buffer.Length;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private void AllocateBuffer(int size) {
+ uint alignedSize = GetAlignedSize(size);
+
+ m_buffer = SafeBSTRHandle.Allocate(null, alignedSize);
+ if (m_buffer.IsInvalid) {
+ throw new OutOfMemoryException();
+ }
+ }
+
+ private void CheckSupportedOnCurrentPlatform() {
+ if( !supportedOnCurrentPlatform) {
+ throw new NotSupportedException(Environment.GetResourceString("Arg_PlatformSecureString"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureCapacity(int capacity) {
+ if( capacity > MaxLength) {
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity"));
+ }
+ Contract.EndContractBlock();
+
+ if( capacity <= m_buffer.Length) {
+ return;
+ }
+
+ SafeBSTRHandle newBuffer = SafeBSTRHandle.Allocate(null, GetAlignedSize(capacity));
+
+ if (newBuffer.IsInvalid) {
+ throw new OutOfMemoryException();
+ }
+
+ SafeBSTRHandle.Copy(m_buffer, newBuffer);
+ m_buffer.Close();
+ m_buffer = newBuffer;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void EnsureNotDisposed() {
+ if( m_buffer == null) {
+ throw new ObjectDisposedException(null);
+ }
+ Contract.EndContractBlock();
+ }
+
+ private void EnsureNotReadOnly() {
+ if( m_readOnly) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+ }
+ Contract.EndContractBlock();
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static uint GetAlignedSize( int size) {
+ Contract.Assert(size >= 0, "size must be non-negative");
+
+ uint alignedSize = ((uint)size / BlockSize) * BlockSize;
+ if( (size % BlockSize != 0) || size == 0) { // if size is 0, set allocated size to blocksize
+ alignedSize += BlockSize;
+ }
+ return alignedSize;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetAnsiByteCount() {
+ const uint CP_ACP = 0;
+ const uint WC_NO_BEST_FIT_CHARS = 0x00000400;
+
+ uint flgs = WC_NO_BEST_FIT_CHARS;
+ uint DefaultCharUsed = (uint)'?';
+
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ m_buffer.AcquirePointer(ref bufferPtr);
+
+ return Win32Native.WideCharToMultiByte(
+ CP_ACP,
+ flgs,
+ (char*) bufferPtr,
+ m_length,
+ null,
+ 0,
+ IntPtr.Zero,
+ new IntPtr((void*)&DefaultCharUsed));
+ }
+ finally {
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void GetAnsiBytes( byte * ansiStrPtr, int byteCount) {
+ const uint CP_ACP = 0;
+ const uint WC_NO_BEST_FIT_CHARS = 0x00000400;
+
+ uint flgs = WC_NO_BEST_FIT_CHARS;
+ uint DefaultCharUsed = (uint)'?';
+
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ m_buffer.AcquirePointer(ref bufferPtr);
+
+ Win32Native.WideCharToMultiByte(
+ CP_ACP,
+ flgs,
+ (char*) bufferPtr,
+ m_length,
+ ansiStrPtr,
+ byteCount - 1,
+ IntPtr.Zero,
+ new IntPtr((void*)&DefaultCharUsed));
+
+ *(ansiStrPtr + byteCount - 1) = (byte)0;
+ }
+ finally {
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
+ private void ProtectMemory() {
+ Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!");
+ Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!");
+
+ if( m_length == 0 || m_encrypted) {
+ return;
+ }
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ // RtlEncryptMemory return an NTSTATUS
+ int status = Win32Native.SystemFunction040(m_buffer, (uint)m_buffer.Length * 2, ProtectionScope);
+ if (status < 0) { // non-negative numbers indicate success
+#if FEATURE_CORECLR
+ throw new CryptographicException(Win32Native.RtlNtStatusToDosError(status));
+#else
+ throw new CryptographicException(Win32Native.LsaNtStatusToWinError(status));
+#endif
+ }
+ m_encrypted = true;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal unsafe IntPtr ToBSTR() {
+ EnsureNotDisposed();
+ int length = m_length;
+ IntPtr ptr = IntPtr.Zero;
+ IntPtr result = IntPtr.Zero;
+ byte* bufferPtr = null;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ ptr = Win32Native.SysAllocStringLen(null, length);
+ }
+
+ if (ptr == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ UnProtectMemory();
+ m_buffer.AcquirePointer(ref bufferPtr);
+ Buffer.Memcpy((byte*) ptr.ToPointer(), bufferPtr, length *2);
+ result = ptr;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+ if( result == IntPtr.Zero) {
+ // If we failed for any reason, free the new buffer
+ if (ptr != IntPtr.Zero) {
+ Win32Native.ZeroMemory(ptr, (UIntPtr)(length * 2));
+ Win32Native.SysFreeString(ptr);
+ }
+ }
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal unsafe IntPtr ToUniStr(bool allocateFromHeap) {
+ EnsureNotDisposed();
+ int length = m_length;
+ IntPtr ptr = IntPtr.Zero;
+ IntPtr result = IntPtr.Zero;
+ byte* bufferPtr = null;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ if( allocateFromHeap) {
+ ptr = Marshal.AllocHGlobal((length + 1) * 2);
+ }
+ else {
+ ptr = Marshal.AllocCoTaskMem((length + 1) * 2);
+ }
+ }
+
+ if (ptr == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ UnProtectMemory();
+ m_buffer.AcquirePointer(ref bufferPtr);
+ Buffer.Memcpy((byte*) ptr.ToPointer(), bufferPtr, length *2);
+ char * endptr = (char *) ptr.ToPointer();
+ *(endptr + length) = '\0';
+ result = ptr;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+
+ if( result == IntPtr.Zero) {
+ // If we failed for any reason, free the new buffer
+ if (ptr != IntPtr.Zero) {
+ Win32Native.ZeroMemory(ptr, (UIntPtr)(length * 2));
+ if( allocateFromHeap) {
+ Marshal.FreeHGlobal(ptr);
+ }
+ else {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+
+ if (bufferPtr != null)
+ m_buffer.ReleasePointer();
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal unsafe IntPtr ToAnsiStr(bool allocateFromHeap) {
+ EnsureNotDisposed();
+
+ IntPtr ptr = IntPtr.Zero;
+ IntPtr result = IntPtr.Zero;
+ int byteCount = 0;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ // GetAnsiByteCount uses the string data, so the calculation must happen after we are decrypted.
+ UnProtectMemory();
+
+ // allocating an extra char for terminating zero
+ byteCount = GetAnsiByteCount() + 1;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ if( allocateFromHeap) {
+ ptr = Marshal.AllocHGlobal(byteCount);
+ }
+ else {
+ ptr = Marshal.AllocCoTaskMem(byteCount);
+ }
+ }
+
+ if (ptr == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ GetAnsiBytes((byte *)ptr.ToPointer(), byteCount);
+ result = ptr;
+ }
+ catch (Exception) {
+ ProtectMemory();
+ throw;
+ }
+ finally {
+ ProtectMemory();
+ if( result == IntPtr.Zero) {
+ // If we failed for any reason, free the new buffer
+ if (ptr != IntPtr.Zero) {
+ Win32Native.ZeroMemory(ptr, (UIntPtr)byteCount);
+ if( allocateFromHeap) {
+ Marshal.FreeHGlobal(ptr);
+ }
+ else {
+ Marshal.FreeCoTaskMem(ptr);
+ }
+ }
+ }
+
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private void UnProtectMemory() {
+ Contract.Assert(!m_buffer.IsInvalid && m_buffer.Length != 0, "Invalid buffer!");
+ Contract.Assert(m_buffer.Length % BlockSize == 0, "buffer length must be multiple of blocksize!");
+
+ if( m_length == 0) {
+ return;
+ }
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ }
+ finally {
+ if (m_encrypted) {
+ // RtlEncryptMemory return an NTSTATUS
+ int status = Win32Native.SystemFunction041(m_buffer, (uint)m_buffer.Length * 2, ProtectionScope);
+ if (status < 0)
+ { // non-negative numbers indicate success
+#if FEATURE_CORECLR
+ throw new CryptographicException(Win32Native.RtlNtStatusToDosError(status));
+#else
+ throw new CryptographicException(Win32Native.LsaNtStatusToWinError(status));
+#endif
+ }
+ m_encrypted = false;
+ }
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal sealed class SafeBSTRHandle : SafeBuffer {
+ internal SafeBSTRHandle () : base(true) {}
+
+ internal static SafeBSTRHandle Allocate(String src, uint len)
+ {
+ SafeBSTRHandle bstr = SysAllocStringLen(src, len);
+ bstr.Initialize(len * sizeof(char));
+ return bstr;
+ }
+
+ [DllImport(Win32Native.OLEAUT32, CharSet = CharSet.Unicode)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern SafeBSTRHandle SysAllocStringLen(String src, uint len); // BSTR
+
+ [System.Security.SecurityCritical]
+ override protected bool ReleaseHandle()
+ {
+ Win32Native.ZeroMemory(handle, (UIntPtr) (Win32Native.SysStringLen(handle) * 2));
+ Win32Native.SysFreeString(handle);
+ return true;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal unsafe void ClearBuffer() {
+ byte* bufferPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ AcquirePointer(ref bufferPtr);
+ Win32Native.ZeroMemory((IntPtr)bufferPtr, (UIntPtr) (Win32Native.SysStringLen((IntPtr)bufferPtr) * 2));
+ }
+ finally
+ {
+ if (bufferPtr != null)
+ ReleasePointer();
+ }
+ }
+
+
+ internal unsafe int Length {
+ get {
+ return (int) Win32Native.SysStringLen(this);
+ }
+ }
+
+ internal unsafe static void Copy(SafeBSTRHandle source, SafeBSTRHandle target) {
+ byte* sourcePtr = null, targetPtr = null;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ source.AcquirePointer(ref sourcePtr);
+ target.AcquirePointer(ref targetPtr);
+
+ Contract.Assert(Win32Native.SysStringLen((IntPtr)targetPtr) >= Win32Native.SysStringLen((IntPtr)sourcePtr), "Target buffer is not large enough!");
+
+ Buffer.Memcpy(targetPtr, sourcePtr, (int) Win32Native.SysStringLen((IntPtr)sourcePtr) * 2);
+ }
+ finally
+ {
+ if (sourcePtr != null)
+ source.ReleasePointer();
+ if (targetPtr != null)
+ target.ReleasePointer();
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/SerializableAttribute.cs b/src/mscorlib/src/System/SerializableAttribute.cs
new file mode 100644
index 0000000000..bceca6800a
--- /dev/null
+++ b/src/mscorlib/src/System/SerializableAttribute.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Used to mark a class as being serializable
+**
+**
+============================================================*/
+namespace System {
+
+ using System;
+ using System.Reflection;
+
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate, Inherited = false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class SerializableAttribute : Attribute
+ {
+ internal static Attribute GetCustomAttribute(RuntimeType type)
+ {
+ return (type.Attributes & TypeAttributes.Serializable) == TypeAttributes.Serializable ? new SerializableAttribute() : null;
+ }
+ internal static bool IsDefined(RuntimeType type)
+ {
+ return type.IsSerializable;
+ }
+
+ public SerializableAttribute() {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/SharedStatics.cs b/src/mscorlib/src/System/SharedStatics.cs
new file mode 100644
index 0000000000..ec63a0ec25
--- /dev/null
+++ b/src/mscorlib/src/System/SharedStatics.cs
@@ -0,0 +1,148 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Container for statics that are shared across AppDomains.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Threading;
+ using System.Runtime.Remoting;
+ using System.Security;
+ using System.Security.Util;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+#if FEATURE_CAS_POLICY
+ using StringMaker = System.Security.Util.Tokenizer.StringMaker;
+#endif // FEATURE_CAS_POLICY
+
+ internal sealed class SharedStatics
+ {
+ // this is declared static but is actually forced to be the same object
+ // for each AppDomain at AppDomain create time.
+ private static SharedStatics _sharedStatics;
+
+ // Note: Do not add any code in this ctor because it is not called
+ // when we set up _sharedStatics via AppDomain::SetupSharedStatics
+ private SharedStatics()
+ {
+ BCLDebug.Assert(false, "SharedStatics..ctor() is never called.");
+ }
+
+ private volatile String _Remoting_Identity_IDGuid;
+ public static String Remoting_Identity_IDGuid
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ if (_sharedStatics._Remoting_Identity_IDGuid == null)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ Monitor.Enter(_sharedStatics, ref tookLock);
+
+ if (_sharedStatics._Remoting_Identity_IDGuid == null)
+ {
+ _sharedStatics._Remoting_Identity_IDGuid = Guid.NewGuid().ToString().Replace('-', '_');
+ }
+ }
+ finally {
+ if (tookLock)
+ Monitor.Exit(_sharedStatics);
+ }
+ }
+
+ Contract.Assert(_sharedStatics._Remoting_Identity_IDGuid != null,
+ "_sharedStatics._Remoting_Identity_IDGuid != null");
+ return _sharedStatics._Remoting_Identity_IDGuid;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ private StringMaker _maker;
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static public StringMaker GetSharedStringMaker()
+ {
+ StringMaker maker = null;
+
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ Monitor.Enter(_sharedStatics, ref tookLock);
+
+ if (_sharedStatics._maker != null)
+ {
+ maker = _sharedStatics._maker;
+ _sharedStatics._maker = null;
+ }
+ }
+ finally {
+ if (tookLock)
+ Monitor.Exit(_sharedStatics);
+ }
+
+ if (maker == null)
+ {
+ maker = new StringMaker();
+ }
+
+ return maker;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static public void ReleaseSharedStringMaker(ref StringMaker maker)
+ {
+ // save this stringmaker so someone else can use it
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(_sharedStatics, ref tookLock);
+
+ _sharedStatics._maker = maker;
+ maker = null;
+ }
+ finally {
+ if (tookLock)
+ Monitor.Exit(_sharedStatics);
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+
+ // Note this may not need to be process-wide.
+ private int _Remoting_Identity_IDSeqNum;
+ internal static int Remoting_Identity_GetNextSeqNum()
+ {
+ return Interlocked.Increment(ref _sharedStatics._Remoting_Identity_IDSeqNum);
+ }
+
+
+ // This is the total amount of memory currently "reserved" via
+ // all MemoryFailPoints allocated within the process.
+ // Stored as a long because we need to use Interlocked.Add.
+ private long _memFailPointReservedMemory;
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static long AddMemoryFailPointReservation(long size)
+ {
+ // Size can legitimately be negative - see Dispose.
+ return Interlocked.Add(ref _sharedStatics._memFailPointReservedMemory, (long) size);
+ }
+
+ internal static ulong MemoryFailPointReservedMemory {
+ get {
+ Contract.Assert(Volatile.Read(ref _sharedStatics._memFailPointReservedMemory) >= 0, "Process-wide MemoryFailPoint reserved memory was negative!");
+ return (ulong) Volatile.Read(ref _sharedStatics._memFailPointReservedMemory);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Single.cs b/src/mscorlib/src/System/Single.cs
new file mode 100644
index 0000000000..6a77f086b5
--- /dev/null
+++ b/src/mscorlib/src/System/Single.cs
@@ -0,0 +1,337 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: A wrapper class for the primitive type float.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System.Globalization;
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+
+[Serializable]
+[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct Single : IComparable, IFormattable, IConvertible
+ , IComparable<Single>, IEquatable<Single>
+ {
+ internal float m_value;
+
+ //
+ // Public constants
+ //
+ public const float MinValue = (float)-3.40282346638528859e+38;
+ public const float Epsilon = (float)1.4e-45;
+ public const float MaxValue = (float)3.40282346638528859e+38;
+ public const float PositiveInfinity = (float)1.0 / (float)0.0;
+ public const float NegativeInfinity = (float)-1.0 / (float)0.0;
+ public const float NaN = (float)0.0 / (float)0.0;
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsInfinity(float f) {
+ return (*(int*)(&f) & 0x7FFFFFFF) == 0x7F800000;
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsPositiveInfinity(float f) {
+ return *(int*)(&f) == 0x7F800000;
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsNegativeInfinity(float f) {
+ return *(int*)(&f) == unchecked((int)0xFF800000);
+ }
+
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool IsNaN(float f) {
+ return (*(int*)(&f) & 0x7FFFFFFF) > 0x7F800000;
+ }
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type Single, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is Single) {
+ float f = (float)value;
+ if (m_value < f) return -1;
+ if (m_value > f) return 1;
+ if (m_value == f) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(f) ? 0 : -1);
+ else // f is NaN.
+ return 1;
+ }
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeSingle"));
+ }
+
+
+ public int CompareTo(Single value) {
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ if (m_value == value) return 0;
+
+ // At least one of the values is NaN.
+ if (IsNaN(m_value))
+ return (IsNaN(value) ? 0 : -1);
+ else // f is NaN.
+ return 1;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator ==(Single left, Single right) {
+ return left == right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator !=(Single left, Single right) {
+ return left != right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator <(Single left, Single right) {
+ return left < right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator >(Single left, Single right) {
+ return left > right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator <=(Single left, Single right) {
+ return left <= right;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool operator >=(Single left, Single right) {
+ return left >= right;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is Single)) {
+ return false;
+ }
+ float temp = ((Single)obj).m_value;
+ if (temp == m_value) {
+ return true;
+ }
+
+ return IsNaN(temp) && IsNaN(m_value);
+ }
+
+ public bool Equals(Single obj)
+ {
+ if (obj == m_value) {
+ return true;
+ }
+
+ return IsNaN(obj) && IsNaN(m_value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override int GetHashCode() {
+ float f = m_value;
+ if (f == 0) {
+ // Ensure that 0 and -0 have the same hash code
+ return 0;
+ }
+ int v = *(int*)(&f);
+ return v;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatSingle(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ // Parses a float from a String in the given style. If
+ // a NumberFormatInfo isn't specified, the current culture's
+ // NumberFormatInfo is assumed.
+ //
+ // This method will not throw an OverflowException, but will return
+ // PositiveInfinity or NegativeInfinity for a number that is too
+ // large or too small.
+ //
+ public static float Parse(String s) {
+ return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static float Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ public static float Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
+ }
+
+ public static float Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static float Parse(String s, NumberStyles style, NumberFormatInfo info) {
+ return Number.ParseSingle(s, style, info);
+ }
+
+ public static Boolean TryParse(String s, out Single result) {
+ return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Single result) {
+ NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static Boolean TryParse(String s, NumberStyles style, NumberFormatInfo info, out Single result) {
+ if (s == null) {
+ result = 0;
+ return false;
+ }
+ bool success = Number.TryParseSingle(s, style, info, out result);
+ if (!success) {
+ String sTrim = s.Trim();
+ if (sTrim.Equals(info.PositiveInfinitySymbol)) {
+ result = PositiveInfinity;
+ } else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
+ result = NegativeInfinity;
+ } else if (sTrim.Equals(info.NaNSymbol)) {
+ result = NaN;
+ } else
+ return false; // We really failed
+ }
+ return true;
+
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.Single;
+ }
+
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Single", "Char"));
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Single", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/StackOverflowException.cs b/src/mscorlib/src/System/StackOverflowException.cs
new file mode 100644
index 0000000000..4a20527f61
--- /dev/null
+++ b/src/mscorlib/src/System/StackOverflowException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for stack overflow.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class StackOverflowException : SystemException {
+ public StackOverflowException()
+ : base(Environment.GetResourceString("Arg_StackOverflowException")) {
+ SetErrorCode(__HResults.COR_E_STACKOVERFLOW);
+ }
+
+ public StackOverflowException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_STACKOVERFLOW);
+ }
+
+ public StackOverflowException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_STACKOVERFLOW);
+ }
+
+ internal StackOverflowException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/String.Comparison.cs b/src/mscorlib/src/System/String.Comparison.cs
new file mode 100644
index 0000000000..a05f9f201a
--- /dev/null
+++ b/src/mscorlib/src/System/String.Comparison.cs
@@ -0,0 +1,1160 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ public partial class String
+ {
+ //
+ //Native Static Methods
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static int CompareOrdinalIgnoreCaseHelper(String strA, String strB)
+ {
+ Contract.Requires(strA != null);
+ Contract.Requires(strB != null);
+ Contract.EndContractBlock();
+ int length = Math.Min(strA.Length, strB.Length);
+
+ fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+ while (length != 0)
+ {
+ int charA = *a;
+ int charB = *b;
+
+ Contract.Assert((charA | charB) <= 0x7F, "strings have to be ASCII");
+
+ // uppercase both chars - notice that we need just one compare per char
+ if ((uint)(charA - 'a') <= (uint)('z' - 'a')) charA -= 0x20;
+ if ((uint)(charB - 'a') <= (uint)('z' - 'a')) charB -= 0x20;
+
+ //Return the (case-insensitive) difference between them.
+ if (charA != charB)
+ return charA - charB;
+
+ // Next char
+ a++; b++;
+ length--;
+ }
+
+ return strA.Length - strB.Length;
+ }
+ }
+
+ // native call to COMString::CompareOrdinalEx
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int CompareOrdinalHelper(String strA, int indexA, int countA, String strB, int indexB, int countB);
+
+ //This will not work in case-insensitive mode for any character greater than 0x80.
+ //We'll throw an ArgumentException.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe internal static extern int nativeCompareOrdinalIgnoreCaseWC(String strA, sbyte *strBBytes);
+
+ //
+ //
+ // NATIVE INSTANCE METHODS
+ //
+ //
+
+ //
+ // Search/Query methods
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private unsafe static bool EqualsHelper(String strA, String strB)
+ {
+ Contract.Requires(strA != null);
+ Contract.Requires(strB != null);
+ Contract.Requires(strA.Length == strB.Length);
+
+ int length = strA.Length;
+
+ fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+#if BIT64
+ // Single int read aligns pointers for the following long reads
+ // PERF: No length check needed as there is always an int32 worth of string allocated
+ // This read can also include the null terminator which both strings will have
+ if (*(int*)a != *(int*)b) return false;
+ length -= 2; a += 2; b += 2;
+
+ // for AMD64 bit platform we unroll by 12 and
+ // check 3 qword at a time. This is less code
+ // than the 32 bit case and is a shorter path length.
+
+ while (length >= 12)
+ {
+ if (*(long*)a != *(long*)b) goto ReturnFalse;
+ if (*(long*)(a + 4) != *(long*)(b + 4)) goto ReturnFalse;
+ if (*(long*)(a + 8) != *(long*)(b + 8)) goto ReturnFalse;
+ length -= 12; a += 12; b += 12;
+ }
+#else
+ while (length >= 10)
+ {
+ if (*(int*)a != *(int*)b) goto ReturnFalse;
+ if (*(int*)(a + 2) != *(int*)(b + 2)) goto ReturnFalse;
+ if (*(int*)(a + 4) != *(int*)(b + 4)) goto ReturnFalse;
+ if (*(int*)(a + 6) != *(int*)(b + 6)) goto ReturnFalse;
+ if (*(int*)(a + 8) != *(int*)(b + 8)) goto ReturnFalse;
+ length -= 10; a += 10; b += 10;
+ }
+#endif
+
+ // This depends on the fact that the String objects are
+ // always zero terminated and that the terminating zero is not included
+ // in the length. For odd string sizes, the last compare will include
+ // the zero terminator.
+ while (length > 0)
+ {
+ if (*(int*)a != *(int*)b) goto ReturnFalse;
+ length -= 2; a += 2; b += 2;
+ }
+
+ return true;
+
+ ReturnFalse:
+ return false;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private unsafe static bool StartsWithOrdinalHelper(String str, String startsWith)
+ {
+ Contract.Requires(str != null);
+ Contract.Requires(startsWith != null);
+ Contract.Requires(str.Length >= startsWith.Length);
+
+ int length = startsWith.Length;
+
+ fixed (char* ap = &str.m_firstChar) fixed (char* bp = &startsWith.m_firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+#if BIT64
+ // Single int read aligns pointers for the following long reads
+ // No length check needed as this method is called when length >= 2
+ Contract.Assert(length >= 2);
+ if (*(int*)a != *(int*)b) goto ReturnFalse;
+ length -= 2; a += 2; b += 2;
+
+ while (length >= 12)
+ {
+ if (*(long*)a != *(long*)b) goto ReturnFalse;
+ if (*(long*)(a + 4) != *(long*)(b + 4)) goto ReturnFalse;
+ if (*(long*)(a + 8) != *(long*)(b + 8)) goto ReturnFalse;
+ length -= 12; a += 12; b += 12;
+ }
+#else
+ while (length >= 10)
+ {
+ if (*(int*)a != *(int*)b) goto ReturnFalse;
+ if (*(int*)(a+2) != *(int*)(b+2)) goto ReturnFalse;
+ if (*(int*)(a+4) != *(int*)(b+4)) goto ReturnFalse;
+ if (*(int*)(a+6) != *(int*)(b+6)) goto ReturnFalse;
+ if (*(int*)(a+8) != *(int*)(b+8)) goto ReturnFalse;
+ length -= 10; a += 10; b += 10;
+ }
+#endif
+
+ while (length >= 2)
+ {
+ if (*(int*)a != *(int*)b) goto ReturnFalse;
+ length -= 2; a += 2; b += 2;
+ }
+
+ // PERF: This depends on the fact that the String objects are always zero terminated
+ // and that the terminating zero is not included in the length. For even string sizes
+ // this compare can include the zero terminator. Bitwise OR avoids a branch.
+ return length == 0 | *a == *b;
+
+ ReturnFalse:
+ return false;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe static int CompareOrdinalHelper(String strA, String strB)
+ {
+ Contract.Requires(strA != null);
+ Contract.Requires(strB != null);
+
+ // NOTE: This may be subject to change if eliminating the check
+ // in the callers makes them small enough to be inlined by the JIT
+ Contract.Assert(strA.m_firstChar == strB.m_firstChar,
+ "For performance reasons, callers of this method should " +
+ "check/short-circuit beforehand if the first char is the same.");
+
+ int length = Math.Min(strA.Length, strB.Length);
+
+ fixed (char* ap = &strA.m_firstChar) fixed (char* bp = &strB.m_firstChar)
+ {
+ char* a = ap;
+ char* b = bp;
+
+ // Check if the second chars are different here
+ // The reason we check if m_firstChar is different is because
+ // it's the most common case and allows us to avoid a method call
+ // to here.
+ // The reason we check if the second char is different is because
+ // if the first two chars the same we can increment by 4 bytes,
+ // leaving us word-aligned on both 32-bit (12 bytes into the string)
+ // and 64-bit (16 bytes) platforms.
+
+ // For empty strings, the second char will be null due to padding.
+ // The start of the string (not including sync block pointer)
+ // is the method table pointer + string length, which takes up
+ // 8 bytes on 32-bit, 12 on x64. For empty strings the null
+ // terminator immediately follows, leaving us with an object
+ // 10/14 bytes in size. Since everything needs to be a multiple
+ // of 4/8, this will get padded and zeroed out.
+
+ // For one-char strings the second char will be the null terminator.
+
+ // NOTE: If in the future there is a way to read the second char
+ // without pinning the string (e.g. System.Runtime.CompilerServices.Unsafe
+ // is exposed to mscorlib, or a future version of C# allows inline IL),
+ // then do that and short-circuit before the fixed.
+
+ if (*(a + 1) != *(b + 1)) goto DiffOffset1;
+
+ // Since we know that the first two chars are the same,
+ // we can increment by 2 here and skip 4 bytes.
+ // This leaves us 8-byte aligned, which results
+ // on better perf for 64-bit platforms.
+ length -= 2; a += 2; b += 2;
+
+ // unroll the loop
+#if BIT64
+ while (length >= 12)
+ {
+ if (*(long*)a != *(long*)b) goto DiffOffset0;
+ if (*(long*)(a + 4) != *(long*)(b + 4)) goto DiffOffset4;
+ if (*(long*)(a + 8) != *(long*)(b + 8)) goto DiffOffset8;
+ length -= 12; a += 12; b += 12;
+ }
+#else // BIT64
+ while (length >= 10)
+ {
+ if (*(int*)a != *(int*)b) goto DiffOffset0;
+ if (*(int*)(a + 2) != *(int*)(b + 2)) goto DiffOffset2;
+ if (*(int*)(a + 4) != *(int*)(b + 4)) goto DiffOffset4;
+ if (*(int*)(a + 6) != *(int*)(b + 6)) goto DiffOffset6;
+ if (*(int*)(a + 8) != *(int*)(b + 8)) goto DiffOffset8;
+ length -= 10; a += 10; b += 10;
+ }
+#endif // BIT64
+
+ // Fallback loop:
+ // go back to slower code path and do comparison on 4 bytes at a time.
+ // This depends on the fact that the String objects are
+ // always zero terminated and that the terminating zero is not included
+ // in the length. For odd string sizes, the last compare will include
+ // the zero terminator.
+ while (length > 0)
+ {
+ if (*(int*)a != *(int*)b) goto DiffNextInt;
+ length -= 2;
+ a += 2;
+ b += 2;
+ }
+
+ // At this point, we have compared all the characters in at least one string.
+ // The longer string will be larger.
+ return strA.Length - strB.Length;
+
+#if BIT64
+ DiffOffset8: a += 4; b += 4;
+ DiffOffset4: a += 4; b += 4;
+#else // BIT64
+ // Use jumps instead of falling through, since
+ // otherwise going to DiffOffset8 will involve
+ // 8 add instructions before getting to DiffNextInt
+ DiffOffset8: a += 8; b += 8; goto DiffOffset0;
+ DiffOffset6: a += 6; b += 6; goto DiffOffset0;
+ DiffOffset4: a += 2; b += 2;
+ DiffOffset2: a += 2; b += 2;
+#endif // BIT64
+
+ DiffOffset0:
+ // If we reached here, we already see a difference in the unrolled loop above
+#if BIT64
+ if (*(int*)a == *(int*)b)
+ {
+ a += 2; b += 2;
+ }
+#endif // BIT64
+
+ DiffNextInt:
+ if (*a != *b) return *a - *b;
+
+ DiffOffset1:
+ Contract.Assert(*(a + 1) != *(b + 1), "This char must be different if we reach here!");
+ return *(a + 1) - *(b + 1);
+ }
+ }
+
+ // Provides a culture-correct string comparison. StrA is compared to StrB
+ // to determine whether it is lexicographically less, equal, or greater, and then returns
+ // either a negative integer, 0, or a positive integer; respectively.
+ //
+ [Pure]
+ public static int Compare(String strA, String strB)
+ {
+ return Compare(strA, strB, StringComparison.CurrentCulture);
+ }
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ // The case-sensitive option is set by ignoreCase
+ //
+ [Pure]
+ public static int Compare(String strA, String strB, bool ignoreCase)
+ {
+ var comparisonType = ignoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;
+ return Compare(strA, strB, comparisonType);
+ }
+
+
+ // Provides a more flexible function for string comparision. See StringComparison
+ // for meaning of different comparisonType.
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int Compare(String strA, String strB, StringComparison comparisonType)
+ {
+ // Single comparison to check if comparisonType is within [CurrentCulture .. OrdinalIgnoreCase]
+ if ((uint)(comparisonType - StringComparison.CurrentCulture) > (uint)(StringComparison.OrdinalIgnoreCase - StringComparison.CurrentCulture))
+ {
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ Contract.EndContractBlock();
+
+ if (object.ReferenceEquals(strA, strB))
+ {
+ return 0;
+ }
+
+ // They can't both be null at this point.
+ if (strA == null)
+ {
+ return -1;
+ }
+ if (strB == null)
+ {
+ return 1;
+ }
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, strB, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ // Most common case: first character is different.
+ // Returns false for empty strings.
+ if (strA.m_firstChar != strB.m_firstChar)
+ {
+ return strA.m_firstChar - strB.m_firstChar;
+ }
+
+ return CompareOrdinalHelper(strA, strB);
+
+ case StringComparison.OrdinalIgnoreCase:
+ // If both strings are ASCII strings, we can take the fast path.
+ if (strA.IsAscii() && strB.IsAscii()) {
+ return (CompareOrdinalIgnoreCaseHelper(strA, strB));
+ }
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return CompareInfo.CompareOrdinalIgnoreCase(strA, 0, strA.Length, strB, 0, strB.Length);
+#else
+ // Take the slow path.
+ return TextInfo.CompareOrdinalIgnoreCase(strA, strB);
+#endif
+
+ default:
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_StringComparison"));
+ }
+ }
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ //
+ [Pure]
+ public static int Compare(String strA, String strB, CultureInfo culture, CompareOptions options) {
+ if (culture == null)
+ {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.EndContractBlock();
+
+ return culture.CompareInfo.Compare(strA, strB, options);
+ }
+
+
+
+ // Provides a culture-correct string comparison. strA is compared to strB
+ // to determine whether it is lexicographically less, equal, or greater, and then a
+ // negative integer, 0, or a positive integer is returned; respectively.
+ // The case-sensitive option is set by ignoreCase, and the culture is set
+ // by culture
+ //
+ [Pure]
+ public static int Compare(String strA, String strB, bool ignoreCase, CultureInfo culture)
+ {
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return Compare(strA, strB, culture, options);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length count is compared with the substring of strB
+ // beginning at indexB of the same length.
+ //
+ [Pure]
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length)
+ {
+ // NOTE: It's important we call the boolean overload, and not the StringComparison
+ // one. The two have some subtly different behavior (see notes in the former).
+ return Compare(strA, indexA, strB, indexB, length, ignoreCase: false);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length count is compared with the substring of strB
+ // beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean.
+ //
+ [Pure]
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length, bool ignoreCase)
+ {
+ // Ideally we would just forward to the string.Compare overload that takes
+ // a StringComparison parameter, and just pass in CurrentCulture/CurrentCultureIgnoreCase.
+ // That function will return early if an optimization can be applied, e.g. if
+ // (object)strA == strB && indexA == indexB then it will return 0 straightaway.
+ // There are a couple of subtle behavior differences that prevent us from doing so
+ // however:
+ // - string.Compare(null, -1, null, -1, -1, StringComparison.CurrentCulture) works
+ // since that method also returns early for nulls before validation. It shouldn't
+ // for this overload.
+ // - Since we originally forwarded to CompareInfo.Compare for all of the argument
+ // validation logic, the ArgumentOutOfRangeExceptions thrown will contain different
+ // parameter names.
+ // Therefore, we have to duplicate some of the logic here.
+
+ int lengthA = length;
+ int lengthB = length;
+
+ if (strA != null)
+ {
+ lengthA = Math.Min(lengthA, strA.Length - indexA);
+ }
+
+ if (strB != null)
+ {
+ lengthB = Math.Min(lengthB, strB.Length - indexB);
+ }
+
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
+ }
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length length is compared with the substring of strB
+ // beginning at indexB of the same length. Case sensitivity is determined by the ignoreCase boolean,
+ // and the culture is set by culture.
+ //
+ [Pure]
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length, bool ignoreCase, CultureInfo culture)
+ {
+ var options = ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None;
+ return Compare(strA, indexA, strB, indexB, length, culture, options);
+ }
+
+
+ // Determines whether two string regions match. The substring of strA beginning
+ // at indexA of length length is compared with the substring of strB
+ // beginning at indexB of the same length.
+ //
+ [Pure]
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length, CultureInfo culture, CompareOptions options)
+ {
+ if (culture == null)
+ {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.EndContractBlock();
+
+ int lengthA = length;
+ int lengthB = length;
+
+ if (strA != null)
+ {
+ lengthA = Math.Min(lengthA, strA.Length - indexA);
+ }
+
+ if (strB != null)
+ {
+ lengthB = Math.Min(lengthB, strB.Length - indexB);
+ }
+
+ return culture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, options);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int Compare(String strA, int indexA, String strB, int indexB, int length, StringComparison comparisonType) {
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ Contract.EndContractBlock();
+
+ if (strA == null || strB == null)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ // They're both null
+ return 0;
+ }
+
+ return strA == null ? -1 : 1;
+ }
+
+ if (length < 0)
+ {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+
+ if (indexA < 0 || indexB < 0)
+ {
+ string paramName = indexA < 0 ? "indexA" : "indexB";
+ throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (strA.Length - indexA < 0 || strB.Length - indexB < 0)
+ {
+ string paramName = strA.Length - indexA < 0 ? "indexA" : "indexB";
+ throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
+ {
+ return 0;
+ }
+
+ int lengthA = Math.Min(length, strA.Length - indexA);
+ int lengthB = Math.Min(length, strB.Length - indexB);
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.Compare(strA, indexA, lengthA, strB, indexB, lengthB, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
+
+ case StringComparison.OrdinalIgnoreCase:
+#if FEATURE_COREFX_GLOBALIZATION
+ return (CompareInfo.CompareOrdinalIgnoreCase(strA, indexA, lengthA, strB, indexB, lengthB));
+#else
+ return (TextInfo.CompareOrdinalIgnoreCaseEx(strA, indexA, strB, indexB, lengthA, lengthB));
+#endif
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"));
+ }
+
+ }
+
+ // Compares strA and strB using an ordinal (code-point) comparison.
+ //
+ [Pure]
+ public static int CompareOrdinal(String strA, String strB)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ return 0;
+ }
+
+ // They can't both be null at this point.
+ if (strA == null)
+ {
+ return -1;
+ }
+ if (strB == null)
+ {
+ return 1;
+ }
+
+ // Most common case, first character is different.
+ // This will return false for empty strings.
+ if (strA.m_firstChar != strB.m_firstChar)
+ {
+ return strA.m_firstChar - strB.m_firstChar;
+ }
+
+ return CompareOrdinalHelper(strA, strB);
+ }
+
+
+ // Compares strA and strB using an ordinal (code-point) comparison.
+ //
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static int CompareOrdinal(String strA, int indexA, String strB, int indexB, int length)
+ {
+ if (strA == null || strB == null)
+ {
+ if (object.ReferenceEquals(strA, strB))
+ {
+ // They're both null
+ return 0;
+ }
+
+ return strA == null ? -1 : 1;
+ }
+
+ // COMPAT: Checking for nulls should become before the arguments are validated,
+ // but other optimizations which allow us to return early should come after.
+
+ if (length < 0)
+ {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ }
+
+ if (indexA < 0 || indexB < 0)
+ {
+ string paramName = indexA < 0 ? "indexA" : "indexB";
+ throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ int lengthA = Math.Min(length, strA.Length - indexA);
+ int lengthB = Math.Min(length, strB.Length - indexB);
+
+ if (lengthA < 0 || lengthB < 0)
+ {
+ string paramName = lengthA < 0 ? "indexA" : "indexB";
+ throw new ArgumentOutOfRangeException(paramName, Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB))
+ {
+ return 0;
+ }
+
+ return CompareOrdinalHelper(strA, indexA, lengthA, strB, indexB, lengthB);
+ }
+
+ // Compares this String to another String (cast as object), returning an integer that
+ // indicates the relationship. This method returns a value less than 0 if this is less than value, 0
+ // if this is equal to value, or a value greater than 0 if this is greater than value.
+ //
+ [Pure]
+ public int CompareTo(Object value)
+ {
+ if (value == null)
+ {
+ return 1;
+ }
+
+ string other = value as string;
+
+ if (other == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeString"));
+ }
+
+ return CompareTo(other); // will call the string-based overload
+ }
+
+ // Determines the sorting relation of StrB to the current instance.
+ //
+ [Pure]
+ public int CompareTo(String strB)
+ {
+ return string.Compare(this, strB, StringComparison.CurrentCulture);
+ }
+
+ // Determines whether a specified string is a suffix of the the current instance.
+ //
+ // The case-sensitive and culture-sensitive option is set by options,
+ // and the default culture is used.
+ //
+ [Pure]
+ public Boolean EndsWith(String value) {
+ return EndsWith(value, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public Boolean EndsWith(String value, StringComparison comparisonType) {
+ if( (Object)value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ Contract.EndContractBlock();
+
+ if( (Object)this == (Object)value) {
+ return true;
+ }
+
+ if( value.Length == 0) {
+ return true;
+ }
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.IsSuffix(this, value, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ return this.Length < value.Length ? false : (CompareOrdinalHelper(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
+
+ case StringComparison.OrdinalIgnoreCase:
+#if FEATURE_COREFX_GLOBALIZATION
+ return this.Length < value.Length ? false : (CompareInfo.CompareOrdinalIgnoreCase(this, this.Length - value.Length, value.Length, value, 0, value.Length) == 0);
+#else
+ return this.Length < value.Length ? false : (TextInfo.CompareOrdinalIgnoreCaseEx(this, this.Length - value.Length, value, 0, value.Length, value.Length) == 0);
+#endif
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+
+ [Pure]
+ public Boolean EndsWith(String value, Boolean ignoreCase, CultureInfo culture) {
+ if (null==value) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ if((object)this == (object)value) {
+ return true;
+ }
+
+ CultureInfo referenceCulture;
+ if (culture == null)
+ referenceCulture = CultureInfo.CurrentCulture;
+ else
+ referenceCulture = culture;
+
+ return referenceCulture.CompareInfo.IsSuffix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ [Pure]
+ internal bool EndsWith(char value) {
+ int thisLen = this.Length;
+ if (thisLen != 0) {
+ if (this[thisLen - 1] == value)
+ return true;
+ }
+ return false;
+ }
+
+ // Determines whether two strings match.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public override bool Equals(Object obj)
+ {
+ if (this == null) // this is necessary to guard against reverse-pinvokes and
+ throw new NullReferenceException(); // other callers who do not use the callvirt instruction
+
+ if (object.ReferenceEquals(this, obj))
+ return true;
+
+ string str = obj as string;
+ if (str == null)
+ return false;
+
+ if (this.Length != str.Length)
+ return false;
+
+ return EqualsHelper(this, str);
+ }
+
+ // Determines whether two strings match.
+ [Pure]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public bool Equals(String value)
+ {
+ if (this == null) // this is necessary to guard against reverse-pinvokes and
+ throw new NullReferenceException(); // other callers who do not use the callvirt instruction
+
+ if (object.ReferenceEquals(this, value))
+ return true;
+
+ // NOTE: No need to worry about casting to object here.
+ // If either side of an == comparison between strings
+ // is null, Roslyn generates a simple ceq instruction
+ // instead of calling string.op_Equality.
+ if (value == null)
+ return false;
+
+ if (this.Length != value.Length)
+ return false;
+
+ return EqualsHelper(this, value);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool Equals(String value, StringComparison comparisonType) {
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ Contract.EndContractBlock();
+
+ if ((Object)this == (Object)value) {
+ return true;
+ }
+
+ if ((Object)value == null) {
+ return false;
+ }
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);
+
+ case StringComparison.InvariantCulture:
+ return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.None) == 0);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CultureInfo.InvariantCulture.CompareInfo.Compare(this, value, CompareOptions.IgnoreCase) == 0);
+
+ case StringComparison.Ordinal:
+ if (this.Length != value.Length)
+ return false;
+ return EqualsHelper(this, value);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (this.Length != value.Length)
+ return false;
+
+ // If both strings are ASCII strings, we can take the fast path.
+ if (this.IsAscii() && value.IsAscii()) {
+ return (CompareOrdinalIgnoreCaseHelper(this, value) == 0);
+ }
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, this.Length, value, 0, value.Length) == 0);
+#else
+ // Take the slow path.
+ return (TextInfo.CompareOrdinalIgnoreCase(this, value) == 0);
+#endif
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+
+
+ // Determines whether two Strings match.
+ [Pure]
+ public static bool Equals(String a, String b) {
+ if ((Object)a==(Object)b) {
+ return true;
+ }
+
+ if ((Object)a == null || (Object)b == null || a.Length != b.Length) {
+ return false;
+ }
+
+ return EqualsHelper(a, b);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool Equals(String a, String b, StringComparison comparisonType) {
+ if (comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase)
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ Contract.EndContractBlock();
+
+ if ((Object)a==(Object)b) {
+ return true;
+ }
+
+ if ((Object)a==null || (Object)b==null) {
+ return false;
+ }
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return (CultureInfo.CurrentCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);
+
+ case StringComparison.InvariantCulture:
+ return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.None) == 0);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return (CultureInfo.InvariantCulture.CompareInfo.Compare(a, b, CompareOptions.IgnoreCase) == 0);
+
+ case StringComparison.Ordinal:
+ if (a.Length != b.Length)
+ return false;
+
+ return EqualsHelper(a, b);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (a.Length != b.Length)
+ return false;
+ else {
+ // If both strings are ASCII strings, we can take the fast path.
+ if (a.IsAscii() && b.IsAscii()) {
+ return (CompareOrdinalIgnoreCaseHelper(a, b) == 0);
+ }
+ // Take the slow path.
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return (CompareInfo.CompareOrdinalIgnoreCase(a, 0, a.Length, b, 0, b.Length) == 0);
+#else
+ return (TextInfo.CompareOrdinalIgnoreCase(a, b) == 0);
+#endif
+ }
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+
+ public static bool operator == (String a, String b) {
+ return String.Equals(a, b);
+ }
+
+ public static bool operator != (String a, String b) {
+ return !String.Equals(a, b);
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ // Do not remove!
+ // This method is called by reflection in System.Xml
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int InternalMarvin32HashString(string s, int strLen, long additionalEntropy);
+
+ [System.Security.SecuritySafeCritical]
+ internal static bool UseRandomizedHashing() {
+ return InternalUseRandomizedHashing();
+ }
+
+ [System.Security.SecurityCritical]
+ [System.Security.SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern bool InternalUseRandomizedHashing();
+#endif
+
+ // Gets a hash code for this string. If strings A and B are such that A.Equals(B), then
+ // they will return the same hash code.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public override int GetHashCode()
+ {
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ if (HashHelpers.s_UseRandomizedStringHashing)
+ {
+ return InternalMarvin32HashString(this, this.Length, 0);
+ }
+#endif // FEATURE_RANDOMIZED_STRING_HASHING
+
+ return GetLegacyNonRandomizedHashCode();
+ }
+
+ // Use this if and only if you need the hashcode to not change across app domains (e.g. you have an app domain agile
+ // hash table).
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal int GetLegacyNonRandomizedHashCode() {
+ unsafe {
+ fixed (char* src = &m_firstChar) {
+ Contract.Assert(src[this.Length] == '\0', "src[this.Length] == '\\0'");
+ Contract.Assert( ((int)src)%4 == 0, "Managed string should start at 4 bytes boundary");
+#if BIT64
+ int hash1 = 5381;
+#else // !BIT64 (32)
+ int hash1 = (5381<<16) + 5381;
+#endif
+ int hash2 = hash1;
+
+#if BIT64
+ int c;
+ char *s = src;
+ while ((c = s[0]) != 0) {
+ hash1 = ((hash1 << 5) + hash1) ^ c;
+ c = s[1];
+ if (c == 0)
+ break;
+ hash2 = ((hash2 << 5) + hash2) ^ c;
+ s += 2;
+ }
+#else // !BIT64 (32)
+ // 32 bit machines.
+ int* pint = (int *)src;
+ int len = this.Length;
+ while (len > 2)
+ {
+ hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
+ hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ pint[1];
+ pint += 2;
+ len -= 4;
+ }
+
+ if (len > 0)
+ {
+ hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ pint[0];
+ }
+#endif
+#if DEBUG
+ // We want to ensure we can change our hash function daily.
+ // This is perfectly fine as long as you don't persist the
+ // value from GetHashCode to disk or count on String A
+ // hashing before string B. Those are bugs in your code.
+ hash1 ^= ThisAssembly.DailyBuildNumber;
+#endif
+ return hash1 + (hash2 * 1566083941);
+ }
+ }
+ }
+
+ // Determines whether a specified string is a prefix of the current instance
+ //
+ [Pure]
+ public Boolean StartsWith(String value) {
+ if ((Object)value == null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+ return StartsWith(value, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ComVisible(false)]
+ public Boolean StartsWith(String value, StringComparison comparisonType) {
+ if( (Object)value == null) {
+ throw new ArgumentNullException("value");
+ }
+
+ if( comparisonType < StringComparison.CurrentCulture || comparisonType > StringComparison.OrdinalIgnoreCase) {
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ Contract.EndContractBlock();
+
+ if( (Object)this == (Object)value) {
+ return true;
+ }
+
+ if( value.Length == 0) {
+ return true;
+ }
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.IsPrefix(this, value, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ if( this.Length < value.Length || m_firstChar != value.m_firstChar) {
+ return false;
+ }
+ return (value.Length == 1) ?
+ true : // First char is the same and thats all there is to compare
+ StartsWithOrdinalHelper(this, value);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if( this.Length < value.Length) {
+ return false;
+ }
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return (CompareInfo.CompareOrdinalIgnoreCase(this, 0, value.Length, value, 0, value.Length) == 0);
+#else
+ return (TextInfo.CompareOrdinalIgnoreCaseEx(this, 0, value, 0, value.Length, value.Length) == 0);
+#endif
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+
+ [Pure]
+ public Boolean StartsWith(String value, Boolean ignoreCase, CultureInfo culture) {
+ if (null==value) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ if((object)this == (object)value) {
+ return true;
+ }
+
+ CultureInfo referenceCulture;
+ if (culture == null)
+ referenceCulture = CultureInfo.CurrentCulture;
+ else
+ referenceCulture = culture;
+
+ return referenceCulture.CompareInfo.IsPrefix(this, value, ignoreCase ? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/mscorlib/src/System/String.Manipulation.cs b/src/mscorlib/src/System/String.Manipulation.cs
new file mode 100644
index 0000000000..e9568a6d03
--- /dev/null
+++ b/src/mscorlib/src/System/String.Manipulation.cs
@@ -0,0 +1,1596 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace System
+{
+ public partial class String
+ {
+ private const int TrimHead = 0;
+ private const int TrimTail = 1;
+ private const int TrimBoth = 2;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe private static void FillStringChecked(String dest, int destPos, String src)
+ {
+ Contract.Requires(dest != null);
+ Contract.Requires(src != null);
+ if (src.Length > dest.Length - destPos) {
+ throw new IndexOutOfRangeException();
+ }
+ Contract.EndContractBlock();
+
+ fixed(char *pDest = &dest.m_firstChar)
+ fixed (char *pSrc = &src.m_firstChar) {
+ wstrcpy(pDest + destPos, pSrc, src.Length);
+ }
+ }
+
+ public static String Concat(Object arg0) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ if (arg0 == null)
+ {
+ return String.Empty;
+ }
+ return arg0.ToString();
+ }
+
+ public static String Concat(Object arg0, Object arg1) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ if (arg0 == null)
+ {
+ arg0 = String.Empty;
+ }
+
+ if (arg1==null) {
+ arg1 = String.Empty;
+ }
+ return Concat(arg0.ToString(), arg1.ToString());
+ }
+
+ public static String Concat(Object arg0, Object arg1, Object arg2) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ if (arg0 == null)
+ {
+ arg0 = String.Empty;
+ }
+
+ if (arg1==null) {
+ arg1 = String.Empty;
+ }
+
+ if (arg2==null) {
+ arg2 = String.Empty;
+ }
+
+ return Concat(arg0.ToString(), arg1.ToString(), arg2.ToString());
+ }
+
+ [CLSCompliant(false)]
+ public static String Concat(Object arg0, Object arg1, Object arg2, Object arg3, __arglist)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ Object[] objArgs;
+ int argCount;
+
+ ArgIterator args = new ArgIterator(__arglist);
+
+ //+4 to account for the 4 hard-coded arguments at the beginning of the list.
+ argCount = args.GetRemainingCount() + 4;
+
+ objArgs = new Object[argCount];
+
+ //Handle the hard-coded arguments
+ objArgs[0] = arg0;
+ objArgs[1] = arg1;
+ objArgs[2] = arg2;
+ objArgs[3] = arg3;
+
+ //Walk all of the args in the variable part of the argument list.
+ for (int i=4; i<argCount; i++) {
+ objArgs[i] = TypedReference.ToObject(args.GetNextArg());
+ }
+
+ return Concat(objArgs);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static string Concat(params object[] args)
+ {
+ if (args == null)
+ {
+ throw new ArgumentNullException("args");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ if (args.Length <= 1)
+ {
+ return args.Length == 0 ?
+ string.Empty :
+ args[0]?.ToString() ?? string.Empty;
+ }
+
+ // We need to get an intermediary string array
+ // to fill with each of the args' ToString(),
+ // and then just concat that in one operation.
+
+ // This way we avoid any intermediary string representations,
+ // or buffer resizing if we use StringBuilder (although the
+ // latter case is partially alleviated due to StringBuilder's
+ // linked-list style implementation)
+
+ var strings = new string[args.Length];
+
+ int totalLength = 0;
+
+ for (int i = 0; i < args.Length; i++)
+ {
+ object value = args[i];
+
+ string toString = value?.ToString() ?? string.Empty; // We need to handle both the cases when value or value.ToString() is null
+ strings[i] = toString;
+
+ totalLength += toString.Length;
+
+ if (totalLength < 0) // Check for a positive overflow
+ {
+ throw new OutOfMemoryException();
+ }
+ }
+
+ // If all of the ToStrings are null/empty, just return string.Empty
+ if (totalLength == 0)
+ {
+ return string.Empty;
+ }
+
+ string result = FastAllocateString(totalLength);
+ int position = 0; // How many characters we've copied so far
+
+ for (int i = 0; i < strings.Length; i++)
+ {
+ string s = strings[i];
+
+ Contract.Assert(s != null);
+ Contract.Assert(position <= totalLength - s.Length, "We didn't allocate enough space for the result string!");
+
+ FillStringChecked(result, position, s);
+ position += s.Length;
+ }
+
+ return result;
+ }
+
+ [ComVisible(false)]
+ public static string Concat<T>(IEnumerable<T> values)
+ {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ using (IEnumerator<T> en = values.GetEnumerator())
+ {
+ if (!en.MoveNext())
+ return string.Empty;
+
+ // We called MoveNext once, so this will be the first item
+ T currentValue = en.Current;
+
+ // Call ToString before calling MoveNext again, since
+ // we want to stay consistent with the below loop
+ // Everything should be called in the order
+ // MoveNext-Current-ToString, unless further optimizations
+ // can be made, to avoid breaking changes
+ string firstString = currentValue?.ToString();
+
+ // If there's only 1 item, simply call ToString on that
+ if (!en.MoveNext())
+ {
+ // We have to handle the case of either currentValue
+ // or its ToString being null
+ return firstString ?? string.Empty;
+ }
+
+ StringBuilder result = StringBuilderCache.Acquire();
+
+ result.Append(firstString);
+
+ do
+ {
+ currentValue = en.Current;
+
+ if (currentValue != null)
+ {
+ result.Append(currentValue.ToString());
+ }
+ }
+ while (en.MoveNext());
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+ }
+
+
+ [ComVisible(false)]
+ public static string Concat(IEnumerable<string> values)
+ {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ using (IEnumerator<string> en = values.GetEnumerator())
+ {
+ if (!en.MoveNext())
+ return string.Empty;
+
+ string firstValue = en.Current;
+
+ if (!en.MoveNext())
+ {
+ return firstValue ?? string.Empty;
+ }
+
+ StringBuilder result = StringBuilderCache.Acquire();
+ result.Append(firstValue);
+
+ do
+ {
+ result.Append(en.Current);
+ }
+ while (en.MoveNext());
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String Concat(String str0, String str1) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length ==
+ (str0 == null ? 0 : str0.Length) +
+ (str1 == null ? 0 : str1.Length));
+ Contract.EndContractBlock();
+
+ if (IsNullOrEmpty(str0)) {
+ if (IsNullOrEmpty(str1)) {
+ return String.Empty;
+ }
+ return str1;
+ }
+
+ if (IsNullOrEmpty(str1)) {
+ return str0;
+ }
+
+ int str0Length = str0.Length;
+
+ String result = FastAllocateString(str0Length + str1.Length);
+
+ FillStringChecked(result, 0, str0);
+ FillStringChecked(result, str0Length, str1);
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String Concat(String str0, String str1, String str2) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length ==
+ (str0 == null ? 0 : str0.Length) +
+ (str1 == null ? 0 : str1.Length) +
+ (str2 == null ? 0 : str2.Length));
+ Contract.EndContractBlock();
+
+ if (IsNullOrEmpty(str0))
+ {
+ return Concat(str1, str2);
+ }
+
+ if (IsNullOrEmpty(str1))
+ {
+ return Concat(str0, str2);
+ }
+
+ if (IsNullOrEmpty(str2))
+ {
+ return Concat(str0, str1);
+ }
+
+ int totalLength = str0.Length + str1.Length + str2.Length;
+
+ String result = FastAllocateString(totalLength);
+ FillStringChecked(result, 0, str0);
+ FillStringChecked(result, str0.Length, str1);
+ FillStringChecked(result, str0.Length + str1.Length, str2);
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String Concat(String str0, String str1, String str2, String str3) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length ==
+ (str0 == null ? 0 : str0.Length) +
+ (str1 == null ? 0 : str1.Length) +
+ (str2 == null ? 0 : str2.Length) +
+ (str3 == null ? 0 : str3.Length));
+ Contract.EndContractBlock();
+
+ if (IsNullOrEmpty(str0))
+ {
+ return Concat(str1, str2, str3);
+ }
+
+ if (IsNullOrEmpty(str1))
+ {
+ return Concat(str0, str2, str3);
+ }
+
+ if (IsNullOrEmpty(str2))
+ {
+ return Concat(str0, str1, str3);
+ }
+
+ if (IsNullOrEmpty(str3))
+ {
+ return Concat(str0, str1, str2);
+ }
+
+ int totalLength = str0.Length + str1.Length + str2.Length + str3.Length;
+
+ String result = FastAllocateString(totalLength);
+ FillStringChecked(result, 0, str0);
+ FillStringChecked(result, str0.Length, str1);
+ FillStringChecked(result, str0.Length + str1.Length, str2);
+ FillStringChecked(result, str0.Length + str1.Length + str2.Length, str3);
+
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public static String Concat(params String[] values) {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ if (values.Length <= 1)
+ {
+ return values.Length == 0 ?
+ string.Empty :
+ values[0] ?? string.Empty;
+ }
+
+ // It's possible that the input values array could be changed concurrently on another
+ // thread, such that we can't trust that each read of values[i] will be equivalent.
+ // Worst case, we can make a defensive copy of the array and use that, but we first
+ // optimistically try the allocation and copies assuming that the array isn't changing,
+ // which represents the 99.999% case, in particular since string.Concat is used for
+ // string concatenation by the languages, with the input array being a params array.
+
+ // Sum the lengths of all input strings
+ long totalLengthLong = 0;
+ for (int i = 0; i < values.Length; i++)
+ {
+ string value = values[i];
+ if (value != null)
+ {
+ totalLengthLong += value.Length;
+ }
+ }
+
+ // If it's too long, fail, or if it's empty, return an empty string.
+ if (totalLengthLong > int.MaxValue)
+ {
+ throw new OutOfMemoryException();
+ }
+ int totalLength = (int)totalLengthLong;
+ if (totalLength == 0)
+ {
+ return string.Empty;
+ }
+
+ // Allocate a new string and copy each input string into it
+ string result = FastAllocateString(totalLength);
+ int copiedLength = 0;
+ for (int i = 0; i < values.Length; i++)
+ {
+ string value = values[i];
+ if (!string.IsNullOrEmpty(value))
+ {
+ int valueLen = value.Length;
+ if (valueLen > totalLength - copiedLength)
+ {
+ copiedLength = -1;
+ break;
+ }
+
+ FillStringChecked(result, copiedLength, value);
+ copiedLength += valueLen;
+ }
+ }
+
+ // If we copied exactly the right amount, return the new string. Otherwise,
+ // something changed concurrently to mutate the input array: fall back to
+ // doing the concatenation again, but this time with a defensive copy. This
+ // fall back should be extremely rare.
+ return copiedLength == totalLength ? result : Concat((string[])values.Clone());
+ }
+
+ public static String Format(String format, Object arg0) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(null, format, new ParamsArray(arg0));
+ }
+
+ public static String Format(String format, Object arg0, Object arg1) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(null, format, new ParamsArray(arg0, arg1));
+ }
+
+ public static String Format(String format, Object arg0, Object arg1, Object arg2) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
+ }
+
+ public static String Format(String format, params Object[] args) {
+ if (args == null)
+ {
+ // To preserve the original exception behavior, throw an exception about format if both
+ // args and format are null. The actual null check for format is in FormatHelper.
+ throw new ArgumentNullException((format == null) ? "format" : "args");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return FormatHelper(null, format, new ParamsArray(args));
+ }
+
+ public static String Format(IFormatProvider provider, String format, Object arg0) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(provider, format, new ParamsArray(arg0));
+ }
+
+ public static String Format(IFormatProvider provider, String format, Object arg0, Object arg1) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(provider, format, new ParamsArray(arg0, arg1));
+ }
+
+ public static String Format(IFormatProvider provider, String format, Object arg0, Object arg1, Object arg2) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return FormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
+ }
+
+ public static String Format(IFormatProvider provider, String format, params Object[] args) {
+ if (args == null)
+ {
+ // To preserve the original exception behavior, throw an exception about format if both
+ // args and format are null. The actual null check for format is in FormatHelper.
+ throw new ArgumentNullException((format == null) ? "format" : "args");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return FormatHelper(provider, format, new ParamsArray(args));
+ }
+
+ private static String FormatHelper(IFormatProvider provider, String format, ParamsArray args) {
+ if (format == null)
+ throw new ArgumentNullException("format");
+
+ return StringBuilderCache.GetStringAndRelease(
+ StringBuilderCache
+ .Acquire(format.Length + args.Length * 8)
+ .AppendFormatHelper(provider, format, args));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String Insert(int startIndex, String value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ if (startIndex < 0 || startIndex > this.Length)
+ throw new ArgumentOutOfRangeException("startIndex");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length == this.Length + value.Length);
+ Contract.EndContractBlock();
+
+ int oldLength = Length;
+ int insertLength = value.Length;
+
+ if (oldLength == 0)
+ return value;
+ if (insertLength == 0)
+ return this;
+
+ // In case this computation overflows, newLength will be negative and FastAllocateString throws OutOfMemoryException
+ int newLength = oldLength + insertLength;
+ String result = FastAllocateString(newLength);
+ unsafe
+ {
+ fixed (char* srcThis = &m_firstChar)
+ {
+ fixed (char* srcInsert = &value.m_firstChar)
+ {
+ fixed (char* dst = &result.m_firstChar)
+ {
+ wstrcpy(dst, srcThis, startIndex);
+ wstrcpy(dst + startIndex, srcInsert, insertLength);
+ wstrcpy(dst + startIndex + insertLength, srcThis + startIndex, oldLength - startIndex);
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ // Joins an array of strings together as one string with a separator between each original string.
+ //
+ public static String Join(String separator, params String[] value) {
+ if (value==null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+ return Join(separator, value, 0, value.Length);
+ }
+
+ [ComVisible(false)]
+ public static string Join(string separator, params object[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.EndContractBlock();
+
+ if (values.Length == 0 || values[0] == null)
+ return string.Empty;
+
+ string firstString = values[0].ToString();
+
+ if (values.Length == 1)
+ {
+ return firstString ?? string.Empty;
+ }
+
+ StringBuilder result = StringBuilderCache.Acquire();
+ result.Append(firstString);
+
+ for (int i = 1; i < values.Length; i++)
+ {
+ result.Append(separator);
+ object value = values[i];
+ if (value != null)
+ {
+ result.Append(value.ToString());
+ }
+ }
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+
+ [ComVisible(false)]
+ public static String Join<T>(String separator, IEnumerable<T> values)
+ {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ using (IEnumerator<T> en = values.GetEnumerator())
+ {
+ if (!en.MoveNext())
+ return string.Empty;
+
+ // We called MoveNext once, so this will be the first item
+ T currentValue = en.Current;
+
+ // Call ToString before calling MoveNext again, since
+ // we want to stay consistent with the below loop
+ // Everything should be called in the order
+ // MoveNext-Current-ToString, unless further optimizations
+ // can be made, to avoid breaking changes
+ string firstString = currentValue?.ToString();
+
+ // If there's only 1 item, simply call ToString on that
+ if (!en.MoveNext())
+ {
+ // We have to handle the case of either currentValue
+ // or its ToString being null
+ return firstString ?? string.Empty;
+ }
+
+ StringBuilder result = StringBuilderCache.Acquire();
+
+ result.Append(firstString);
+
+ do
+ {
+ currentValue = en.Current;
+
+ result.Append(separator);
+ if (currentValue != null)
+ {
+ result.Append(currentValue.ToString());
+ }
+ }
+ while (en.MoveNext());
+
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+ }
+
+ [ComVisible(false)]
+ public static String Join(String separator, IEnumerable<String> values) {
+ if (values == null)
+ throw new ArgumentNullException("values");
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ using(IEnumerator<String> en = values.GetEnumerator()) {
+ if (!en.MoveNext())
+ return String.Empty;
+
+ String firstValue = en.Current;
+
+ if (!en.MoveNext()) {
+ // Only one value available
+ return firstValue ?? String.Empty;
+ }
+
+ // Null separator and values are handled by the StringBuilder
+ StringBuilder result = StringBuilderCache.Acquire();
+ result.Append(firstValue);
+
+ do {
+ result.Append(separator);
+ result.Append(en.Current);
+ } while (en.MoveNext());
+ return StringBuilderCache.GetStringAndRelease(result);
+ }
+ }
+
+ // Joins an array of strings together as one string with a separator between each original string.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static String Join(String separator, String[] value, int startIndex, int count) {
+ //Range check the array
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+
+ if (startIndex > value.Length - count)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ Contract.EndContractBlock();
+
+ //Treat null as empty string.
+ if (separator == null) {
+ separator = String.Empty;
+ }
+
+ //If count is 0, that skews a whole bunch of the calculations below, so just special case that.
+ if (count == 0) {
+ return String.Empty;
+ }
+
+ if (count == 1) {
+ return value[startIndex] ?? String.Empty;
+ }
+
+ int jointLength = 0;
+ //Figure out the total length of the strings in value
+ int endIndex = startIndex + count - 1;
+ for (int stringToJoinIndex = startIndex; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
+ string currentValue = value[stringToJoinIndex];
+
+ if (currentValue != null) {
+ jointLength += currentValue.Length;
+ }
+ }
+
+ //Add enough room for the separator.
+ jointLength += (count - 1) * separator.Length;
+
+ // Note that we may not catch all overflows with this check (since we could have wrapped around the 4gb range any number of times
+ // and landed back in the positive range.) The input array might be modifed from other threads,
+ // so we have to do an overflow check before each append below anyway. Those overflows will get caught down there.
+ if ((jointLength < 0) || ((jointLength + 1) < 0) ) {
+ throw new OutOfMemoryException();
+ }
+
+ //If this is an empty string, just return.
+ if (jointLength == 0) {
+ return String.Empty;
+ }
+
+ string jointString = FastAllocateString( jointLength );
+ fixed (char * pointerToJointString = &jointString.m_firstChar) {
+ UnSafeCharBuffer charBuffer = new UnSafeCharBuffer( pointerToJointString, jointLength);
+
+ // Append the first string first and then append each following string prefixed by the separator.
+ charBuffer.AppendString( value[startIndex] );
+ for (int stringToJoinIndex = startIndex + 1; stringToJoinIndex <= endIndex; stringToJoinIndex++) {
+ charBuffer.AppendString( separator );
+ charBuffer.AppendString( value[stringToJoinIndex] );
+ }
+ Contract.Assert(*(pointerToJointString + charBuffer.Length) == '\0', "String must be null-terminated!");
+ }
+
+ return jointString;
+ }
+
+ //
+ //
+ [Pure]
+ public String PadLeft(int totalWidth) {
+ return PadLeft(totalWidth, ' ');
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String PadLeft(int totalWidth, char paddingChar) {
+ if (totalWidth < 0)
+ throw new ArgumentOutOfRangeException("totalWidth", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ int oldLength = Length;
+ int count = totalWidth - oldLength;
+ if (count <= 0)
+ return this;
+ String result = FastAllocateString(totalWidth);
+ unsafe
+ {
+ fixed (char* dst = &result.m_firstChar)
+ {
+ for (int i = 0; i < count; i++)
+ dst[i] = paddingChar;
+ fixed (char* src = &m_firstChar)
+ {
+ wstrcpy(dst + count, src, oldLength);
+ }
+ }
+ }
+ return result;
+ }
+
+ [Pure]
+ public String PadRight(int totalWidth) {
+ return PadRight(totalWidth, ' ');
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String PadRight(int totalWidth, char paddingChar) {
+ if (totalWidth < 0)
+ throw new ArgumentOutOfRangeException("totalWidth", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ int oldLength = Length;
+ int count = totalWidth - oldLength;
+ if (count <= 0)
+ return this;
+ String result = FastAllocateString(totalWidth);
+ unsafe
+ {
+ fixed (char* dst = &result.m_firstChar)
+ {
+ fixed (char* src = &m_firstChar)
+ {
+ wstrcpy(dst, src, oldLength);
+ }
+ for (int i = 0; i < count; i++)
+ dst[oldLength + i] = paddingChar;
+ }
+ }
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String Remove(int startIndex, int count)
+ {
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ if (count > Length - startIndex)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length == this.Length - count);
+ Contract.EndContractBlock();
+
+ if (count == 0)
+ return this;
+ int newLength = Length - count;
+ if (newLength == 0)
+ return String.Empty;
+
+ String result = FastAllocateString(newLength);
+ unsafe
+ {
+ fixed (char* src = &m_firstChar)
+ {
+ fixed (char* dst = &result.m_firstChar)
+ {
+ wstrcpy(dst, src, startIndex);
+ wstrcpy(dst + startIndex, src + startIndex + count, newLength - startIndex);
+ }
+ }
+ }
+ return result;
+ }
+
+ // a remove that just takes a startindex.
+ public string Remove( int startIndex ) {
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+
+ if (startIndex >= Length) {
+ throw new ArgumentOutOfRangeException("startIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_StartIndexLessThanLength"));
+ }
+
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return Substring(0, startIndex);
+ }
+
+ // Replaces all instances of oldChar with newChar.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String Replace(char oldChar, char newChar)
+ {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.Ensures(Contract.Result<String>().Length == this.Length);
+ Contract.EndContractBlock();
+
+ if (oldChar == newChar)
+ return this;
+
+ unsafe
+ {
+ int remainingLength = Length;
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ char* pSrc = pChars;
+
+ while (remainingLength > 0)
+ {
+ if (*pSrc == oldChar)
+ {
+ break;
+ }
+
+ remainingLength--;
+ pSrc++;
+ }
+ }
+
+ if (remainingLength == 0)
+ return this;
+
+ String result = FastAllocateString(Length);
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ fixed (char* pResult = &result.m_firstChar)
+ {
+ int copyLength = Length - remainingLength;
+
+ //Copy the characters already proven not to match.
+ if (copyLength > 0)
+ {
+ wstrcpy(pResult, pChars, copyLength);
+ }
+
+ //Copy the remaining characters, doing the replacement as we go.
+ char* pSrc = pChars + copyLength;
+ char* pDst = pResult + copyLength;
+
+ do
+ {
+ char currentChar = *pSrc;
+ if (currentChar == oldChar)
+ currentChar = newChar;
+ *pDst = currentChar;
+
+ remainingLength--;
+ pSrc++;
+ pDst++;
+ } while (remainingLength > 0);
+ }
+ }
+
+ return result;
+ }
+ }
+
+ // This method contains the same functionality as StringBuilder Replace. The only difference is that
+ // a new String has to be allocated since Strings are immutable
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern String ReplaceInternal(String oldValue, String newValue);
+
+ public String Replace(String oldValue, String newValue)
+ {
+ if (oldValue == null)
+ throw new ArgumentNullException("oldValue");
+ // Note that if newValue is null, we treat it like String.Empty.
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return ReplaceInternal(oldValue, newValue);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(char separator) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, Int32.MaxValue, StringSplitOptions.None);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(char separator, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, Int32.MaxValue, options);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(char separator, int count, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, count, options);
+ }
+
+ // Creates an array of strings by splitting this string at each
+ // occurrence of a separator. The separator is searched for, and if found,
+ // the substring preceding the occurrence is stored as the first element in
+ // the array of strings. We then continue in this manner by searching
+ // the substring that follows the occurrence. On the other hand, if the separator
+ // is not found, the array of strings will contain this instance as its only element.
+ // If the separator is null
+ // whitespace (i.e., Character.IsWhitespace) is used as the separator.
+ //
+ public String [] Split(params char [] separator) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, Int32.MaxValue, StringSplitOptions.None);
+ }
+
+ // Creates an array of strings by splitting this string at each
+ // occurrence of a separator. The separator is searched for, and if found,
+ // the substring preceding the occurrence is stored as the first element in
+ // the array of strings. We then continue in this manner by searching
+ // the substring that follows the occurrence. On the other hand, if the separator
+ // is not found, the array of strings will contain this instance as its only element.
+ // If the separator is the empty string (i.e., String.Empty), then
+ // whitespace (i.e., Character.IsWhitespace) is used as the separator.
+ // If there are more than count different strings, the last n-(count-1)
+ // elements are concatenated and added as the last String.
+ //
+ public string[] Split(char[] separator, int count) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, count, StringSplitOptions.None);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(char[] separator, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, Int32.MaxValue, options);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(char[] separator, int count, StringSplitOptions options)
+ {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator, count, options);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private unsafe String[] SplitInternal(char separator, int count, StringSplitOptions options)
+ {
+ char* pSeparators = stackalloc char[1];
+ pSeparators[0] = separator;
+ return SplitInternal(pSeparators, /*separatorsLength*/ 1, count, options);
+ }
+
+ [ComVisible(false)]
+ [System.Security.SecuritySafeCritical]
+ internal String[] SplitInternal(char[] separator, int count, StringSplitOptions options)
+ {
+ unsafe
+ {
+ fixed (char* pSeparators = separator)
+ {
+ int separatorsLength = separator == null ? 0 : separator.Length;
+ return SplitInternal(pSeparators, separatorsLength, count, options);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe String[] SplitInternal(char* separators, int separatorsLength, int count, StringSplitOptions options)
+ {
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+
+ if (options < StringSplitOptions.None || options > StringSplitOptions.RemoveEmptyEntries)
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", options));
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ Contract.EndContractBlock();
+
+ bool omitEmptyEntries = (options == StringSplitOptions.RemoveEmptyEntries);
+
+ if ((count == 0) || (omitEmptyEntries && this.Length == 0))
+ {
+#if FEATURE_CORECLR
+ return EmptyArray<String>.Value;
+#else
+ // Keep the old behavior of returning a new empty array
+ // to mitigate any potential compat risk.
+ return new String[0];
+#endif
+ }
+
+ if (count == 1)
+ {
+ return new String[] { this };
+ }
+
+ int[] sepList = new int[Length];
+ int numReplaces = MakeSeparatorList(separators, separatorsLength, sepList);
+
+ // Handle the special case of no replaces.
+ if (0 == numReplaces) {
+ return new String[] { this };
+ }
+
+ if(omitEmptyEntries)
+ {
+ return InternalSplitOmitEmptyEntries(sepList, null, 1, numReplaces, count);
+ }
+ else
+ {
+ return InternalSplitKeepEmptyEntries(sepList, null, 1, numReplaces, count);
+ }
+ }
+
+ [ComVisible(false)]
+ public String[] Split(String separator) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator ?? String.Empty, null, Int32.MaxValue, StringSplitOptions.None);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(String separator, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator ?? String.Empty, null, Int32.MaxValue, options);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(String separator, Int32 count, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(separator ?? String.Empty, null, count, options);
+ }
+
+ [ComVisible(false)]
+ public String [] Split(String[] separator, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(null, separator, Int32.MaxValue, options);
+ }
+
+ [ComVisible(false)]
+ public String[] Split(String[] separator, Int32 count, StringSplitOptions options) {
+ Contract.Ensures(Contract.Result<String[]>() != null);
+ return SplitInternal(null, separator, count, options);
+ }
+
+ private String[] SplitInternal(String separator, String[] separators, Int32 count, StringSplitOptions options)
+ {
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ }
+
+ if (options < StringSplitOptions.None || options > StringSplitOptions.RemoveEmptyEntries) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumIllegalVal", (int)options));
+ }
+ Contract.EndContractBlock();
+
+ bool omitEmptyEntries = (options == StringSplitOptions.RemoveEmptyEntries);
+
+ bool singleSeparator = separator != null;
+
+ if (!singleSeparator && (separators == null || separators.Length == 0)) {
+ return SplitInternal((char[]) null, count, options);
+ }
+
+ if ((count == 0) || (omitEmptyEntries && this.Length ==0)) {
+#if FEATURE_CORECLR
+ return EmptyArray<String>.Value;
+#else
+ // Keep the old behavior of returning a new empty array
+ // to mitigate any potential compat risk.
+ return new String[0];
+#endif
+ }
+
+ if (count == 1) {
+ return new String[] { this };
+ }
+
+ if (singleSeparator && separator.Length == 0) {
+ return new[] { this };
+ }
+
+ int[] sepList = new int[Length];
+ int[] lengthList;
+ int defaultLength;
+ int numReplaces;
+
+ if (singleSeparator) {
+ lengthList = null;
+ defaultLength = separator.Length;
+ numReplaces = MakeSeparatorList(separator, sepList);
+ }
+ else {
+ lengthList = new int[Length];
+ defaultLength = 0;
+ numReplaces = MakeSeparatorList(separators, sepList, lengthList);
+ }
+
+ // Handle the special case of no replaces.
+ if (0 == numReplaces) {
+ return new String[] { this };
+ }
+
+ if (omitEmptyEntries) {
+ return InternalSplitOmitEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count);
+ }
+ else {
+ return InternalSplitKeepEmptyEntries(sepList, lengthList, defaultLength, numReplaces, count);
+ }
+ }
+
+ // Note a special case in this function:
+ // If there is no separator in the string, a string array which only contains
+ // the original string will be returned regardless of the count.
+ //
+
+ private String[] InternalSplitKeepEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) {
+ Contract.Requires(numReplaces >= 0);
+ Contract.Requires(count >= 2);
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+ int currIndex = 0;
+ int arrIndex = 0;
+
+ count--;
+ int numActualReplaces = (numReplaces < count) ? numReplaces : count;
+
+ //Allocate space for the new array.
+ //+1 for the string from the end of the last replace to the end of the String.
+ String[] splitStrings = new String[numActualReplaces+1];
+
+ for (int i = 0; i < numActualReplaces && currIndex < Length; i++) {
+ splitStrings[arrIndex++] = Substring(currIndex, sepList[i]-currIndex );
+ currIndex=sepList[i] + ((lengthList == null) ? defaultLength : lengthList[i]);
+ }
+
+ //Handle the last string at the end of the array if there is one.
+ if (currIndex < Length && numActualReplaces >= 0) {
+ splitStrings[arrIndex] = Substring(currIndex);
+ }
+ else if (arrIndex==numActualReplaces) {
+ //We had a separator character at the end of a string. Rather than just allowing
+ //a null character, we'll replace the last element in the array with an empty string.
+ splitStrings[arrIndex] = String.Empty;
+
+ }
+
+ return splitStrings;
+ }
+
+
+ // This function will not keep the Empty String
+ private String[] InternalSplitOmitEmptyEntries(Int32[] sepList, Int32[] lengthList, Int32 defaultLength, Int32 numReplaces, int count) {
+ Contract.Requires(numReplaces >= 0);
+ Contract.Requires(count >= 2);
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+ // Allocate array to hold items. This array may not be
+ // filled completely in this function, we will create a
+ // new array and copy string references to that new array.
+
+ int maxItems = (numReplaces < count) ? (numReplaces+1): count ;
+ String[] splitStrings = new String[maxItems];
+
+ int currIndex = 0;
+ int arrIndex = 0;
+
+ for(int i=0; i< numReplaces && currIndex < Length; i++) {
+ if( sepList[i]-currIndex > 0) {
+ splitStrings[arrIndex++] = Substring(currIndex, sepList[i]-currIndex );
+ }
+ currIndex=sepList[i] + ((lengthList == null) ? defaultLength : lengthList[i]);
+ if( arrIndex == count -1 ) {
+ // If all the remaining entries at the end are empty, skip them
+ while( i < numReplaces - 1 && currIndex == sepList[++i]) {
+ currIndex += ((lengthList == null) ? defaultLength : lengthList[i]);
+ }
+ break;
+ }
+ }
+
+ // we must have at least one slot left to fill in the last string.
+ Contract.Assert(arrIndex < maxItems);
+
+ //Handle the last string at the end of the array if there is one.
+ if (currIndex< Length) {
+ splitStrings[arrIndex++] = Substring(currIndex);
+ }
+
+ String[] stringArray = splitStrings;
+ if( arrIndex!= maxItems) {
+ stringArray = new String[arrIndex];
+ for( int j = 0; j < arrIndex; j++) {
+ stringArray[j] = splitStrings[j];
+ }
+ }
+ return stringArray;
+ }
+
+ //--------------------------------------------------------------------
+ // This function returns the number of the places within this instance where
+ // characters in Separator occur.
+ // Args: separator -- A string containing all of the split characters.
+ // sepList -- an array of ints for split char indicies.
+ //--------------------------------------------------------------------
+ [System.Security.SecurityCritical]
+ private unsafe int MakeSeparatorList(char* separators, int separatorsLength, int[] sepList) {
+ Contract.Assert(separatorsLength >= 0, "separatorsLength >= 0");
+ int foundCount=0;
+
+ if (separators == null || separatorsLength == 0) {
+ fixed (char* pwzChars = &this.m_firstChar) {
+ //If they passed null or an empty string, look for whitespace.
+ for (int i=0; i < Length && foundCount < sepList.Length; i++) {
+ if (Char.IsWhiteSpace(pwzChars[i])) {
+ sepList[foundCount++]=i;
+ }
+ }
+ }
+ }
+ else {
+ int sepListCount = sepList.Length;
+ //If they passed in a string of chars, actually look for those chars.
+ fixed (char* pwzChars = &this.m_firstChar) {
+ for (int i=0; i< Length && foundCount < sepListCount; i++) {
+ char* pSep = separators;
+ for (int j = 0; j < separatorsLength; j++, pSep++) {
+ if ( pwzChars[i] == *pSep) {
+ sepList[foundCount++]=i;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return foundCount;
+ }
+
+ //--------------------------------------------------------------------
+ // This function returns number of the places within baseString where
+ // instances of the separator string occurs.
+ // Args: separator -- the separator
+ // sepList -- an array of ints for split string indicies.
+ //--------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe int MakeSeparatorList(string separator, int[] sepList) {
+ Contract.Assert(!string.IsNullOrEmpty(separator), "!string.IsNullOrEmpty(separator)");
+
+ int foundCount = 0;
+ int sepListCount = sepList.Length;
+ int currentSepLength = separator.Length;
+
+ fixed (char* pwzChars = &this.m_firstChar) {
+ for (int i = 0; i < Length && foundCount < sepListCount; i++) {
+ if (pwzChars[i] == separator[0] && currentSepLength <= Length - i) {
+ if (currentSepLength == 1
+ || String.CompareOrdinal(this, i, separator, 0, currentSepLength) == 0) {
+ sepList[foundCount] = i;
+ foundCount++;
+ i += currentSepLength - 1;
+ }
+ }
+ }
+ }
+ return foundCount;
+ }
+
+ //--------------------------------------------------------------------
+ // This function returns the number of the places within this instance where
+ // instances of separator strings occur.
+ // Args: separators -- An array containing all of the split strings.
+ // sepList -- an array of ints for split string indicies.
+ // lengthList -- an array of ints for split string lengths.
+ //--------------------------------------------------------------------
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private unsafe int MakeSeparatorList(String[] separators, int[] sepList, int[] lengthList) {
+ Contract.Assert(separators != null && separators.Length > 0, "separators != null && separators.Length > 0");
+
+ int foundCount = 0;
+ int sepListCount = sepList.Length;
+ int sepCount = separators.Length;
+
+ fixed (char* pwzChars = &this.m_firstChar) {
+ for (int i=0; i< Length && foundCount < sepListCount; i++) {
+ for( int j =0; j < separators.Length; j++) {
+ String separator = separators[j];
+ if (String.IsNullOrEmpty(separator)) {
+ continue;
+ }
+ Int32 currentSepLength = separator.Length;
+ if ( pwzChars[i] == separator[0] && currentSepLength <= Length - i) {
+ if (currentSepLength == 1
+ || String.CompareOrdinal(this, i, separator, 0, currentSepLength) == 0) {
+ sepList[foundCount] = i;
+ lengthList[foundCount] = currentSepLength;
+ foundCount++;
+ i += currentSepLength - 1;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return foundCount;
+ }
+
+ // Returns a substring of this string.
+ //
+ public String Substring (int startIndex) {
+ return this.Substring (startIndex, Length-startIndex);
+ }
+
+ // Returns a substring of this string.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String Substring(int startIndex, int length) {
+
+ //Bounds Checking.
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+
+ if (startIndex > Length) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength"));
+ }
+
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+
+ if (startIndex > Length - length) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength"));
+ }
+ Contract.EndContractBlock();
+
+ if( length == 0) {
+ return String.Empty;
+ }
+
+ if( startIndex == 0 && length == this.Length) {
+ return this;
+ }
+
+ return InternalSubString(startIndex, length);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe string InternalSubString(int startIndex, int length) {
+ Contract.Assert( startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!");
+ Contract.Assert( length >= 0 && startIndex <= this.Length - length, "length is out of range!");
+
+ String result = FastAllocateString(length);
+
+ fixed(char* dest = &result.m_firstChar)
+ fixed(char* src = &this.m_firstChar) {
+ wstrcpy(dest, src + startIndex, length);
+ }
+
+ return result;
+ }
+
+ // Creates a copy of this string in lower case.
+ [Pure]
+ public String ToLower() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this.ToLower(CultureInfo.CurrentCulture);
+ }
+
+ // Creates a copy of this string in lower case. The culture is set by culture.
+ [Pure]
+ public String ToLower(CultureInfo culture) {
+ if (culture == null)
+ {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return culture.TextInfo.ToLower(this);
+ }
+
+ // Creates a copy of this string in lower case based on invariant culture.
+ [Pure]
+ public String ToLowerInvariant() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this.ToLower(CultureInfo.InvariantCulture);
+ }
+
+ // Creates a copy of this string in upper case.
+ [Pure]
+ public String ToUpper() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this.ToUpper(CultureInfo.CurrentCulture);
+ }
+
+
+ // Creates a copy of this string in upper case. The culture is set by culture.
+ [Pure]
+ public String ToUpper(CultureInfo culture) {
+ if (culture == null)
+ {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return culture.TextInfo.ToUpper(this);
+ }
+
+
+ //Creates a copy of this string in upper case based on invariant culture.
+ [Pure]
+ public String ToUpperInvariant() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this.ToUpper(CultureInfo.InvariantCulture);
+ }
+
+ // Removes a set of characters from the end of this string.
+ [Pure]
+ public String Trim(params char[] trimChars) {
+ if (null==trimChars || trimChars.Length == 0) {
+ return TrimHelper(TrimBoth);
+ }
+ return TrimHelper(trimChars,TrimBoth);
+ }
+
+ // Removes a set of characters from the beginning of this string.
+ public String TrimStart(params char[] trimChars) {
+ if (null==trimChars || trimChars.Length == 0) {
+ return TrimHelper(TrimHead);
+ }
+ return TrimHelper(trimChars,TrimHead);
+ }
+
+
+ // Removes a set of characters from the end of this string.
+ public String TrimEnd(params char[] trimChars) {
+ if (null==trimChars || trimChars.Length == 0) {
+ return TrimHelper(TrimTail);
+ }
+ return TrimHelper(trimChars,TrimTail);
+ }
+
+ // Trims the whitespace from both ends of the string. Whitespace is defined by
+ // Char.IsWhiteSpace.
+ //
+ [Pure]
+ public String Trim() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return TrimHelper(TrimBoth);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String TrimHelper(int trimType) {
+ //end will point to the first non-trimmed character on the right
+ //start will point to the first non-trimmed character on the Left
+ int end = this.Length-1;
+ int start=0;
+
+ //Trim specified characters.
+ if (trimType !=TrimTail) {
+ for (start=0; start < this.Length; start++) {
+ if (!Char.IsWhiteSpace(this[start])) break;
+ }
+ }
+
+ if (trimType !=TrimHead) {
+ for (end= Length -1; end >= start; end--) {
+ if (!Char.IsWhiteSpace(this[end])) break;
+ }
+ }
+
+ return CreateTrimmedString(start, end);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String TrimHelper(char[] trimChars, int trimType) {
+ //end will point to the first non-trimmed character on the right
+ //start will point to the first non-trimmed character on the Left
+ int end = this.Length-1;
+ int start=0;
+
+ //Trim specified characters.
+ if (trimType !=TrimTail) {
+ for (start=0; start < this.Length; start++) {
+ int i = 0;
+ char ch = this[start];
+ for( i = 0; i < trimChars.Length; i++) {
+ if( trimChars[i] == ch) break;
+ }
+ if( i == trimChars.Length) { // the character is not white space
+ break;
+ }
+ }
+ }
+
+ if (trimType !=TrimHead) {
+ for (end= Length -1; end >= start; end--) {
+ int i = 0;
+ char ch = this[end];
+ for(i = 0; i < trimChars.Length; i++) {
+ if( trimChars[i] == ch) break;
+ }
+ if( i == trimChars.Length) { // the character is not white space
+ break;
+ }
+ }
+ }
+
+ return CreateTrimmedString(start, end);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ private String CreateTrimmedString(int start, int end) {
+ int len = end -start + 1;
+ if (len == this.Length) {
+ // Don't allocate a new string as the trimmed string has not changed.
+ return this;
+ }
+
+ if( len == 0) {
+ return String.Empty;
+ }
+ return InternalSubString(start, len);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/String.Searching.cs b/src/mscorlib/src/System/String.Searching.cs
new file mode 100644
index 0000000000..b972529694
--- /dev/null
+++ b/src/mscorlib/src/System/String.Searching.cs
@@ -0,0 +1,358 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Globalization;
+using System.Runtime.CompilerServices;
+
+namespace System
+{
+ public partial class String
+ {
+ [Pure]
+ public bool Contains( string value ) {
+ return ( IndexOf(value, StringComparison.Ordinal) >=0 );
+ }
+
+ // Returns the index of the first occurrence of a specified character in the current instance.
+ // The search starts at startIndex and runs thorough the next count characters.
+ //
+ [Pure]
+ public int IndexOf(char value) {
+ return IndexOf(value, 0, this.Length);
+ }
+
+ [Pure]
+ public int IndexOf(char value, int startIndex) {
+ return IndexOf(value, startIndex, this.Length - startIndex);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe int IndexOf(char value, int startIndex, int count) {
+ if (startIndex < 0 || startIndex > Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count < 0 || count > Length - startIndex)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ char* pCh = pChars + startIndex;
+
+ while (count >= 4)
+ {
+ if (*pCh == value) goto ReturnIndex;
+ if (*(pCh + 1) == value) goto ReturnIndex1;
+ if (*(pCh + 2) == value) goto ReturnIndex2;
+ if (*(pCh + 3) == value) goto ReturnIndex3;
+
+ count -= 4;
+ pCh += 4;
+ }
+
+ while (count > 0)
+ {
+ if (*pCh == value)
+ goto ReturnIndex;
+
+ count--;
+ pCh++;
+ }
+
+ return -1;
+
+ ReturnIndex3: pCh++;
+ ReturnIndex2: pCh++;
+ ReturnIndex1: pCh++;
+ ReturnIndex:
+ return (int)(pCh - pChars);
+ }
+ }
+
+ // Returns the index of the first occurrence of any specified character in the current instance.
+ // The search starts at startIndex and runs to startIndex + count -1.
+ //
+ [Pure]
+ public int IndexOfAny(char [] anyOf) {
+ return IndexOfAny(anyOf,0, this.Length);
+ }
+
+ [Pure]
+ public int IndexOfAny(char [] anyOf, int startIndex) {
+ return IndexOfAny(anyOf, startIndex, this.Length - startIndex);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern int IndexOfAny(char [] anyOf, int startIndex, int count);
+
+
+ // Determines the position within this string of the first occurrence of the specified
+ // string, according to the specified search criteria. The search begins at
+ // the first character of this string, it is case-sensitive and the current culture
+ // comparison is used.
+ //
+ [Pure]
+ public int IndexOf(String value) {
+ return IndexOf(value, StringComparison.CurrentCulture);
+ }
+
+ // Determines the position within this string of the first occurrence of the specified
+ // string, according to the specified search criteria. The search begins at
+ // startIndex, it is case-sensitive and the current culture comparison is used.
+ //
+ [Pure]
+ public int IndexOf(String value, int startIndex) {
+ return IndexOf(value, startIndex, StringComparison.CurrentCulture);
+ }
+
+ // Determines the position within this string of the first occurrence of the specified
+ // string, according to the specified search criteria. The search begins at
+ // startIndex, ends at endIndex and the current culture comparison is used.
+ //
+ [Pure]
+ public int IndexOf(String value, int startIndex, int count) {
+ if (startIndex < 0 || startIndex > this.Length) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (count < 0 || count > this.Length - startIndex) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ }
+ Contract.EndContractBlock();
+
+ return IndexOf(value, startIndex, count, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ public int IndexOf(String value, StringComparison comparisonType) {
+ return IndexOf(value, 0, this.Length, comparisonType);
+ }
+
+ [Pure]
+ public int IndexOf(String value, int startIndex, StringComparison comparisonType) {
+ return IndexOf(value, startIndex, this.Length - startIndex, comparisonType);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical]
+ public int IndexOf(String value, int startIndex, int count, StringComparison comparisonType) {
+ // Validate inputs
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (startIndex < 0 || startIndex > this.Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count < 0 || startIndex > this.Length - count)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ Contract.EndContractBlock();
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+
+ case StringComparison.Ordinal:
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (value.IsAscii() && this.IsAscii())
+ return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ else
+ return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count);
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+
+ // Returns the index of the last occurrence of a specified character in the current instance.
+ // The search starts at startIndex and runs backwards to startIndex - count + 1.
+ // The character at position startIndex is included in the search. startIndex is the larger
+ // index within the string.
+ //
+ [Pure]
+ public int LastIndexOf(char value) {
+ return LastIndexOf(value, this.Length-1, this.Length);
+ }
+
+ [Pure]
+ public int LastIndexOf(char value, int startIndex){
+ return LastIndexOf(value,startIndex,startIndex + 1);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe int LastIndexOf(char value, int startIndex, int count) {
+ if (Length == 0)
+ return -1;
+
+ if (startIndex < 0 || startIndex >= Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ if (count < 0 || count - 1 > startIndex)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+ fixed (char* pChars = &m_firstChar)
+ {
+ char* pCh = pChars + startIndex;
+
+ //We search [startIndex..EndIndex]
+ while (count >= 4)
+ {
+ if (*pCh == value) goto ReturnIndex;
+ if (*(pCh - 1) == value) goto ReturnIndex1;
+ if (*(pCh - 2) == value) goto ReturnIndex2;
+ if (*(pCh - 3) == value) goto ReturnIndex3;
+
+ count -= 4;
+ pCh -= 4;
+ }
+
+ while (count > 0)
+ {
+ if (*pCh == value)
+ goto ReturnIndex;
+
+ count--;
+ pCh--;
+ }
+
+ return -1;
+
+ ReturnIndex3: pCh--;
+ ReturnIndex2: pCh--;
+ ReturnIndex1: pCh--;
+ ReturnIndex:
+ return (int)(pCh - pChars);
+ }
+ }
+
+ // Returns the index of the last occurrence of any specified character in the current instance.
+ // The search starts at startIndex and runs backwards to startIndex - count + 1.
+ // The character at position startIndex is included in the search. startIndex is the larger
+ // index within the string.
+ //
+
+ //ForceInline ... Jit can't recognize String.get_Length to determine that this is "fluff"
+ [Pure]
+ public int LastIndexOfAny(char [] anyOf) {
+ return LastIndexOfAny(anyOf,this.Length-1,this.Length);
+ }
+
+ [Pure]
+ public int LastIndexOfAny(char [] anyOf, int startIndex) {
+ return LastIndexOfAny(anyOf,startIndex,startIndex + 1);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern int LastIndexOfAny(char [] anyOf, int startIndex, int count);
+
+
+ // Returns the index of the last occurrence of any character in value in the current instance.
+ // The search starts at startIndex and runs backwards to startIndex - count + 1.
+ // The character at position startIndex is included in the search. startIndex is the larger
+ // index within the string.
+ //
+ [Pure]
+ public int LastIndexOf(String value) {
+ return LastIndexOf(value, this.Length-1,this.Length, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ public int LastIndexOf(String value, int startIndex) {
+ return LastIndexOf(value, startIndex, startIndex + 1, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ public int LastIndexOf(String value, int startIndex, int count) {
+ if (count<0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+ }
+ Contract.EndContractBlock();
+
+ return LastIndexOf(value, startIndex, count, StringComparison.CurrentCulture);
+ }
+
+ [Pure]
+ public int LastIndexOf(String value, StringComparison comparisonType) {
+ return LastIndexOf(value, this.Length-1, this.Length, comparisonType);
+ }
+
+ [Pure]
+ public int LastIndexOf(String value, int startIndex, StringComparison comparisonType) {
+ return LastIndexOf(value, startIndex, startIndex + 1, comparisonType);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical]
+ public int LastIndexOf(String value, int startIndex, int count, StringComparison comparisonType) {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Special case for 0 length input strings
+ if (this.Length == 0 && (startIndex == -1 || startIndex == 0))
+ return (value.Length == 0) ? 0 : -1;
+
+ // Now after handling empty strings, make sure we're not out of range
+ if (startIndex < 0 || startIndex > this.Length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ // Make sure that we allow startIndex == this.Length
+ if (startIndex == this.Length)
+ {
+ startIndex--;
+ if (count > 0)
+ count--;
+
+ // If we are looking for nothing, just return 0
+ if (value.Length == 0 && count >= 0 && startIndex - count + 1 >= 0)
+ return startIndex;
+ }
+
+ // 2nd half of this also catches when startIndex == MAXINT, so MAXINT - 0 + 1 == -1, which is < 0.
+ if (count < 0 || startIndex - count + 1 < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count"));
+
+
+ switch (comparisonType) {
+ case StringComparison.CurrentCulture:
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
+
+ case StringComparison.CurrentCultureIgnoreCase:
+ return CultureInfo.CurrentCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+
+ case StringComparison.InvariantCulture:
+ return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.None);
+
+ case StringComparison.InvariantCultureIgnoreCase:
+ return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ case StringComparison.Ordinal:
+ return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.Ordinal);
+
+ case StringComparison.OrdinalIgnoreCase:
+ if (value.IsAscii() && this.IsAscii())
+ return CultureInfo.InvariantCulture.CompareInfo.LastIndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase);
+ else
+ return TextInfo.LastIndexOfStringOrdinalIgnoreCase(this, value, startIndex, count);
+ default:
+ throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType");
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/String.cs b/src/mscorlib/src/System/String.cs
new file mode 100644
index 0000000000..d406fd09b3
--- /dev/null
+++ b/src/mscorlib/src/System/String.cs
@@ -0,0 +1,891 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Your favorite String class. Native methods
+** are implemented in StringNative.cpp
+**
+**
+===========================================================*/
+namespace System {
+ using System.Text;
+ using System;
+ using System.Runtime;
+ using System.Runtime.ConstrainedExecution;
+ using System.Globalization;
+ using System.Threading;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using Microsoft.Win32;
+ using System.Diagnostics.Contracts;
+ using System.Security;
+
+ //
+ // For Information on these methods, please see COMString.cpp
+ //
+ // The String class represents a static string of characters. Many of
+ // the String methods perform some type of transformation on the current
+ // instance and return the result as a new String. All comparison methods are
+ // implemented as a part of String. As with arrays, character positions
+ // (indices) are zero-based.
+
+ [ComVisible(true)]
+ [Serializable]
+ public sealed partial class String : IComparable, ICloneable, IConvertible, IEnumerable
+ , IComparable<String>, IEnumerable<char>, IEquatable<String>
+ {
+
+ //
+ //NOTE NOTE NOTE NOTE
+ //These fields map directly onto the fields in an EE StringObject. See object.h for the layout.
+ //
+ [NonSerialized] private int m_stringLength;
+
+ // For empty strings, this will be '\0' since
+ // strings are both null-terminated and length prefixed
+ [NonSerialized] private char m_firstChar;
+
+ // The Empty constant holds the empty string value. It is initialized by the EE during startup.
+ // It is treated as intrinsic by the JIT as so the static constructor would never run.
+ // Leaving it uninitialized would confuse debuggers.
+ //
+ //We need to call the String constructor so that the compiler doesn't mark this as a literal.
+ //Marking this as a literal would mean that it doesn't show up as a field which we can access
+ //from native.
+ public static readonly String Empty;
+
+ internal char FirstChar { get { return m_firstChar; } }
+ //
+ // This is a helper method for the security team. They need to uppercase some strings (guaranteed to be less
+ // than 0x80) before security is fully initialized. Without security initialized, we can't grab resources (the nlp's)
+ // from the assembly. This provides a workaround for that problem and should NOT be used anywhere else.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal unsafe static string SmallCharToUpper(string strIn) {
+ Contract.Requires(strIn != null);
+ Contract.EndContractBlock();
+ //
+ // Get the length and pointers to each of the buffers. Walk the length
+ // of the string and copy the characters from the inBuffer to the outBuffer,
+ // capitalizing it if necessary. We assert that all of our characters are
+ // less than 0x80.
+ //
+ int length = strIn.Length;
+ String strOut = FastAllocateString(length);
+ fixed (char * inBuff = &strIn.m_firstChar, outBuff = &strOut.m_firstChar) {
+
+ for(int i = 0; i < length; i++) {
+ int c = inBuff[i];
+ Contract.Assert(c <= 0x7F, "string has to be ASCII");
+
+ // uppercase - notice that we need just one compare
+ if ((uint)(c - 'a') <= (uint)('z' - 'a')) c -= 0x20;
+
+ outBuff[i] = (char)c;
+ }
+
+ Contract.Assert(outBuff[length]=='\0', "outBuff[length]=='\0'");
+ }
+ return strOut;
+ }
+
+ // Gets the character at a specified position.
+ //
+ // Spec#: Apply the precondition here using a contract assembly. Potential perf issue.
+ [System.Runtime.CompilerServices.IndexerName("Chars")]
+ public extern char this[int index] {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical] // public member
+ get;
+ }
+
+ // Converts a substring of this string to an array of characters. Copies the
+ // characters of this string beginning at position sourceIndex and ending at
+ // sourceIndex + count - 1 to the character array buffer, beginning
+ // at destinationIndex.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count)
+ {
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ if (sourceIndex < 0)
+ throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (count > Length - sourceIndex)
+ throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
+ if (destinationIndex > destination.Length - count || destinationIndex < 0)
+ throw new ArgumentOutOfRangeException("destinationIndex", Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
+ Contract.EndContractBlock();
+
+ // Note: fixed does not like empty arrays
+ if (count > 0)
+ {
+ fixed (char* src = &this.m_firstChar)
+ fixed (char* dest = destination)
+ wstrcpy(dest + destinationIndex, src + sourceIndex, count);
+ }
+ }
+
+ // Returns the entire string as an array of characters.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public char[] ToCharArray() {
+ int length = Length;
+ if (length > 0)
+ {
+ char[] chars = new char[length];
+ fixed (char* src = &this.m_firstChar) fixed (char* dest = chars)
+ {
+ wstrcpy(dest, src, length);
+ }
+ return chars;
+ }
+
+#if FEATURE_CORECLR
+ return Array.Empty<char>();
+#else
+ return new char[0];
+#endif
+ }
+
+ // Returns a substring of this string as an array of characters.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public char[] ToCharArray(int startIndex, int length)
+ {
+ // Range check everything.
+ if (startIndex < 0 || startIndex > Length || startIndex > Length - length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ if (length < 0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ if (length > 0)
+ {
+ char[] chars = new char[length];
+ fixed (char* src = &this.m_firstChar) fixed (char* dest = chars)
+ {
+ wstrcpy(dest, src + startIndex, length);
+ }
+ return chars;
+ }
+
+#if FEATURE_CORECLR
+ return Array.Empty<char>();
+#else
+ return new char[0];
+#endif
+ }
+
+ [Pure]
+ public static bool IsNullOrEmpty(String value) {
+ return (value == null || value.Length == 0);
+ }
+
+ [Pure]
+ public static bool IsNullOrWhiteSpace(String value) {
+ if (value == null) return true;
+
+ for(int i = 0; i < value.Length; i++) {
+ if(!Char.IsWhiteSpace(value[i])) return false;
+ }
+
+ return true;
+ }
+
+ // Gets the length of this string
+ //
+ /// This is a EE implemented function so that the JIT can recognise is specially
+ /// and eliminate checks on character fetchs in a loop like:
+ /// for(int i = 0; i < str.Length; i++) str[i]
+ /// The actually code generated for this will be one instruction and will be inlined.
+ //
+ // Spec#: Add postcondition in a contract assembly. Potential perf problem.
+ public extern int Length {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ // Creates a new string with the characters copied in from ptr. If
+ // ptr is null, a 0-length string (like String.Empty) is returned.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe public extern String(char *value);
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe public extern String(char *value, int startIndex, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe public extern String(sbyte *value);
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe public extern String(sbyte *value, int startIndex, int length);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false), MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe public extern String(sbyte *value, int startIndex, int length, Encoding enc);
+
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe static private String CreateString(sbyte *value, int startIndex, int length, Encoding enc) {
+ if (enc == null)
+ return new String(value, startIndex, length); // default to ANSI
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ if ((value + startIndex) < value) {
+ // overflow check
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR"));
+ }
+
+ byte [] b = new byte[length];
+
+ try {
+ Buffer.Memcpy(b, 0, (byte*)value, startIndex, length);
+ }
+ catch(NullReferenceException) {
+ // If we got a NullReferencException. It means the pointer or
+ // the index is out of range
+ throw new ArgumentOutOfRangeException("value",
+ Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR"));
+ }
+
+ return enc.GetString(b);
+ }
+
+ // Helper for encodings so they can talk to our buffer directly
+ // stringLength must be the exact size we'll expect
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe static internal String CreateStringFromEncoding(
+ byte* bytes, int byteLength, Encoding encoding)
+ {
+ Contract.Requires(bytes != null);
+ Contract.Requires(byteLength >= 0);
+
+ // Get our string length
+ int stringLength = encoding.GetCharCount(bytes, byteLength, null);
+ Contract.Assert(stringLength >= 0, "stringLength >= 0");
+
+ // They gave us an empty string if they needed one
+ // 0 bytelength might be possible if there's something in an encoder
+ if (stringLength == 0)
+ return String.Empty;
+
+ String s = FastAllocateString(stringLength);
+ fixed(char* pTempChars = &s.m_firstChar)
+ {
+ int doubleCheck = encoding.GetChars(bytes, byteLength, pTempChars, stringLength, null);
+ Contract.Assert(stringLength == doubleCheck,
+ "Expected encoding.GetChars to return same length as encoding.GetCharCount");
+ }
+
+ return s;
+ }
+
+ // This is only intended to be used by char.ToString.
+ // It is necessary to put the code in this class instead of Char, since m_firstChar is a private member.
+ // Making m_firstChar internal would be dangerous since it would make it much easier to break String's immutability.
+ [SecuritySafeCritical]
+ internal static string CreateFromChar(char c)
+ {
+ string result = FastAllocateString(1);
+ result.m_firstChar = c;
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe internal int GetBytesFromEncoding(byte* pbNativeBuffer, int cbNativeBuffer,Encoding encoding)
+ {
+ // encoding == Encoding.UTF8
+ fixed (char* pwzChar = &this.m_firstChar)
+ {
+ return encoding.GetBytes(pwzChar, m_stringLength, pbNativeBuffer, cbNativeBuffer);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe internal int ConvertToAnsi(byte *pbNativeBuffer, int cbNativeBuffer, bool fBestFit, bool fThrowOnUnmappableChar)
+ {
+ Contract.Assert(cbNativeBuffer >= (Length + 1) * Marshal.SystemMaxDBCSCharSize, "Insufficient buffer length passed to ConvertToAnsi");
+
+ const uint CP_ACP = 0;
+ int nb;
+
+ const uint WC_NO_BEST_FIT_CHARS = 0x00000400;
+
+ uint flgs = (fBestFit ? 0 : WC_NO_BEST_FIT_CHARS);
+ uint DefaultCharUsed = 0;
+
+ fixed (char* pwzChar = &this.m_firstChar)
+ {
+ nb = Win32Native.WideCharToMultiByte(
+ CP_ACP,
+ flgs,
+ pwzChar,
+ this.Length,
+ pbNativeBuffer,
+ cbNativeBuffer,
+ IntPtr.Zero,
+ (fThrowOnUnmappableChar ? new IntPtr(&DefaultCharUsed) : IntPtr.Zero));
+ }
+
+ if (0 != DefaultCharUsed)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Interop_Marshal_Unmappable_Char"));
+ }
+
+ pbNativeBuffer[nb] = 0;
+ return nb;
+ }
+
+ // Normalization Methods
+ // These just wrap calls to Normalization class
+ public bool IsNormalized()
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ // Default to Form C
+ return IsNormalized(NormalizationForm.FormC);
+#else
+ // Default to Form IDNA
+ return IsNormalized((NormalizationForm)ExtendedNormalizationForms.FormIdna);
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool IsNormalized(NormalizationForm normalizationForm)
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ if (this.IsFastSort())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if( normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD )
+ return true;
+ }
+#endif // !FEATURE_NORM_IDNA_ONLY
+ return Normalization.IsNormalized(this, normalizationForm);
+ }
+
+ public String Normalize()
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ // Default to Form C
+ return Normalize(NormalizationForm.FormC);
+#else
+ // Default to Form IDNA
+ return Normalize((NormalizationForm)ExtendedNormalizationForms.FormIdna);
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String Normalize(NormalizationForm normalizationForm)
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ if (this.IsAscii())
+ {
+ // If its FastSort && one of the 4 main forms, then its already normalized
+ if( normalizationForm == NormalizationForm.FormC ||
+ normalizationForm == NormalizationForm.FormKC ||
+ normalizationForm == NormalizationForm.FormD ||
+ normalizationForm == NormalizationForm.FormKD )
+ return this;
+ }
+#endif // !FEATURE_NORM_IDNA_ONLY
+ return Normalization.Normalize(this, normalizationForm);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static String FastAllocateString(int length);
+
+ // Creates a new string from the characters in a subarray. The new string will
+ // be created from the characters in value between startIndex and
+ // startIndex + length - 1.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern String(char [] value, int startIndex, int length);
+
+ // Creates a new string from the characters in a subarray. The new string will be
+ // created from the characters in value.
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern String(char [] value);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe void wstrcpy(char *dmem, char *smem, int charCount)
+ {
+ Buffer.Memcpy((byte*)dmem, (byte*)smem, charCount * 2); // 2 used everywhere instead of sizeof(char)
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String CtorCharArray(char [] value)
+ {
+ if (value != null && value.Length != 0) {
+ String result = FastAllocateString(value.Length);
+
+ unsafe {
+ fixed (char* dest = &result.m_firstChar, source = value) {
+ wstrcpy(dest, source, value.Length);
+ }
+ }
+ return result;
+ }
+ else
+ return String.Empty;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String CtorCharArrayStartLength(char [] value, int startIndex, int length)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (startIndex < 0)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+
+ if (length < 0)
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+
+ if (startIndex > value.Length - length)
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ if (length > 0) {
+ String result = FastAllocateString(length);
+
+ unsafe {
+ fixed (char* dest = &result.m_firstChar, source = value) {
+ wstrcpy(dest, source + startIndex, length);
+ }
+ }
+ return result;
+ }
+ else
+ return String.Empty;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private String CtorCharCount(char c, int count)
+ {
+ if (count > 0) {
+ String result = FastAllocateString(count);
+ if (c != 0)
+ {
+ unsafe {
+ fixed (char* dest = &result.m_firstChar) {
+ char *dmem = dest;
+ while (((uint)dmem & 3) != 0 && count > 0) {
+ *dmem++ = c;
+ count--;
+ }
+ uint cc = (uint)((c << 16) | c);
+ if (count >= 4) {
+ count -= 4;
+ do{
+ ((uint *)dmem)[0] = cc;
+ ((uint *)dmem)[1] = cc;
+ dmem += 4;
+ count -= 4;
+ } while (count >= 0);
+ }
+ if ((count & 2) != 0) {
+ ((uint *)dmem)[0] = cc;
+ dmem += 2;
+ }
+ if ((count & 1) != 0)
+ dmem[0] = c;
+ }
+ }
+ }
+ return result;
+ }
+ else if (count == 0)
+ return String.Empty;
+ else
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "count"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe int wcslen(char *ptr)
+ {
+ char *end = ptr;
+
+ // First make sure our pointer is aligned on a word boundary
+ int alignment = IntPtr.Size - 1;
+
+ // If ptr is at an odd address (e.g. 0x5), this loop will simply iterate all the way
+ while (((uint)end & (uint)alignment) != 0)
+ {
+ if (*end == 0) goto FoundZero;
+ end++;
+ }
+
+#if !BIT64
+ // The following code is (somewhat surprisingly!) significantly faster than a naive loop,
+ // at least on x86 and the current jit.
+
+ // The loop condition below works because if "end[0] & end[1]" is non-zero, that means
+ // neither operand can have been zero. If is zero, we have to look at the operands individually,
+ // but we hope this going to fairly rare.
+
+ // In general, it would be incorrect to access end[1] if we haven't made sure
+ // end[0] is non-zero. However, we know the ptr has been aligned by the loop above
+ // so end[0] and end[1] must be in the same word (and therefore page), so they're either both accessible, or both not.
+
+ while ((end[0] & end[1]) != 0 || (end[0] != 0 && end[1] != 0)) {
+ end += 2;
+ }
+
+ Contract.Assert(end[0] == 0 || end[1] == 0);
+ if (end[0] != 0) end++;
+#else // !BIT64
+ // Based on https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
+
+ // 64-bit implementation: process 1 ulong (word) at a time
+
+ // What we do here is add 0x7fff from each of the
+ // 4 individual chars within the ulong, using MagicMask.
+ // If the char > 0 and < 0x8001, it will have its high bit set.
+ // We then OR with MagicMask, to set all the other bits.
+ // This will result in all bits set (ulong.MaxValue) for any
+ // char that fits the above criteria, and something else otherwise.
+
+ // Note that for any char > 0x8000, this will be a false
+ // positive and we will fallback to the slow path and
+ // check each char individually. This is OK though, since
+ // we optimize for the common case (ASCII chars, which are < 0x80).
+
+ // NOTE: We can access a ulong a time since the ptr is aligned,
+ // and therefore we're only accessing the same word/page. (See notes
+ // for the 32-bit version above.)
+
+ const ulong MagicMask = 0x7fff7fff7fff7fff;
+
+ while (true)
+ {
+ ulong word = *(ulong*)end;
+ word += MagicMask; // cause high bit to be set if not zero, and <= 0x8000
+ word |= MagicMask; // set everything besides the high bits
+
+ if (word == ulong.MaxValue) // 0xffff...
+ {
+ // all of the chars have their bits set (and therefore none can be 0)
+ end += 4;
+ continue;
+ }
+
+ // at least one of them didn't have their high bit set!
+ // go through each char and check for 0.
+
+ if (end[0] == 0) goto EndAt0;
+ if (end[1] == 0) goto EndAt1;
+ if (end[2] == 0) goto EndAt2;
+ if (end[3] == 0) goto EndAt3;
+
+ // if we reached here, it was a false positive-- just continue
+ end += 4;
+ }
+
+ EndAt3: end++;
+ EndAt2: end++;
+ EndAt1: end++;
+ EndAt0:
+#endif // !BIT64
+
+ FoundZero:
+ Contract.Assert(*end == 0);
+
+ int count = (int)(end - ptr);
+
+ return count;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe String CtorCharPtr(char *ptr)
+ {
+ if (ptr == null)
+ return String.Empty;
+
+#if !FEATURE_PAL
+ if (ptr < (char*)64000)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeStringPtrNotAtom"));
+#endif // FEATURE_PAL
+
+ Contract.Assert(this == null, "this == null"); // this is the string constructor, we allocate it
+
+ try {
+ int count = wcslen(ptr);
+ if (count == 0)
+ return String.Empty;
+
+ String result = FastAllocateString(count);
+ fixed (char* dest = &result.m_firstChar)
+ wstrcpy(dest, ptr, count);
+ return result;
+ }
+ catch (NullReferenceException) {
+ throw new ArgumentOutOfRangeException("ptr", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR"));
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe String CtorCharPtrStartLength(char *ptr, int startIndex, int length)
+ {
+ if (length < 0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+ Contract.EndContractBlock();
+ Contract.Assert(this == null, "this == null"); // this is the string constructor, we allocate it
+
+ char *pFrom = ptr + startIndex;
+ if (pFrom < ptr) {
+ // This means that the pointer operation has had an overflow
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR"));
+ }
+
+ if (length == 0)
+ return String.Empty;
+
+ String result = FastAllocateString(length);
+
+ try {
+ fixed (char* dest = &result.m_firstChar)
+ wstrcpy(dest, pFrom, length);
+ return result;
+ }
+ catch (NullReferenceException) {
+ throw new ArgumentOutOfRangeException("ptr", Environment.GetResourceString("ArgumentOutOfRange_PartialWCHAR"));
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern String(char c, int count);
+
+
+ // Returns this string.
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this;
+ }
+
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+ return this;
+ }
+
+ // Method required for the ICloneable interface.
+ // There's no point in cloning a string since they're immutable, so we simply return this.
+ public Object Clone() {
+ Contract.Ensures(Contract.Result<Object>() != null);
+ Contract.EndContractBlock();
+ return this;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ unsafe public static String Copy (String str) {
+ if (str==null) {
+ throw new ArgumentNullException("str");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ int length = str.Length;
+
+ String result = FastAllocateString(length);
+
+ fixed(char* dest = &result.m_firstChar)
+ fixed(char* src = &str.m_firstChar) {
+ wstrcpy(dest, src, length);
+ }
+ return result;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String Intern(String str) {
+ if (str==null) {
+ throw new ArgumentNullException("str");
+ }
+ Contract.Ensures(Contract.Result<String>().Length == str.Length);
+ Contract.Ensures(str.Equals(Contract.Result<String>()));
+ Contract.EndContractBlock();
+
+ return Thread.GetDomain().GetOrInternString(str);
+ }
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static String IsInterned(String str) {
+ if (str==null) {
+ throw new ArgumentNullException("str");
+ }
+ Contract.Ensures(Contract.Result<String>() == null || Contract.Result<String>().Length == str.Length);
+ Contract.EndContractBlock();
+
+ return Thread.GetDomain().IsStringInterned(str);
+ }
+
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.String;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(this, provider);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(this, provider);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(this, provider);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(this, provider);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(this, provider);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(this, provider);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(this, provider);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(this, provider);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(this, provider);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(this, provider);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(this, provider);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(this, provider);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(this, provider);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ return Convert.ToDateTime(this, provider);
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+
+ // Is this a string that can be compared quickly (that is it has only characters > 0x80
+ // and not a - or '
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern bool IsFastSort();
+ // Is this a string that only contains characters < 0x80.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern bool IsAscii();
+
+ // Set extra byte for odd-sized strings that came from interop as BSTR.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void SetTrailByte(byte data);
+ // Try to retrieve the extra byte - returns false if not present.
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern bool TryGetTrailByte(out byte data);
+
+#if !FEATURE_CORECLR
+ public CharEnumerator GetEnumerator() {
+ Contract.Ensures(Contract.Result<CharEnumerator>() != null);
+ Contract.EndContractBlock();
+ BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead.");
+ return new CharEnumerator(this);
+ }
+#endif // !FEATURE_CORECLR
+
+ IEnumerator<char> IEnumerable<char>.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator<char>>() != null);
+ Contract.EndContractBlock();
+ BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead.");
+ return new CharEnumerator(this);
+ }
+
+ /// <internalonly/>
+ IEnumerator IEnumerable.GetEnumerator() {
+ Contract.Ensures(Contract.Result<IEnumerator>() != null);
+ Contract.EndContractBlock();
+ BCLDebug.Perf(false, "Avoid using String's CharEnumerator until C# special cases foreach on String - use the indexed property on String instead.");
+ return new CharEnumerator(this);
+ }
+
+ // Copies the source String (byte buffer) to the destination IntPtr memory allocated with len bytes.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe static void InternalCopy(String src, IntPtr dest,int len)
+ {
+ if (len == 0)
+ return;
+ fixed(char* charPtr = &src.m_firstChar) {
+ byte* srcPtr = (byte*) charPtr;
+ byte* dstPtr = (byte*) dest;
+ Buffer.Memcpy(dstPtr, srcPtr, len);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/StringComparer.cs b/src/mscorlib/src/System/StringComparer.cs
new file mode 100644
index 0000000000..57bdf4c6b2
--- /dev/null
+++ b/src/mscorlib/src/System/StringComparer.cs
@@ -0,0 +1,440 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System {
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class StringComparer : IComparer, IEqualityComparer, IComparer<string>, IEqualityComparer<string>{
+ private static readonly StringComparer _invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);
+ private static readonly StringComparer _invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true);
+ private static readonly StringComparer _ordinal = new OrdinalComparer(false);
+ private static readonly StringComparer _ordinalIgnoreCase = new OrdinalComparer(true);
+
+ public static StringComparer InvariantCulture {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return _invariantCulture;
+ }
+ }
+
+ public static StringComparer InvariantCultureIgnoreCase {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return _invariantCultureIgnoreCase;
+ }
+ }
+
+ public static StringComparer CurrentCulture {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return new CultureAwareComparer(CultureInfo.CurrentCulture, false);
+ }
+ }
+
+ public static StringComparer CurrentCultureIgnoreCase {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return new CultureAwareComparer(CultureInfo.CurrentCulture, true);
+ }
+ }
+
+ public static StringComparer Ordinal {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return _ordinal;
+ }
+ }
+
+ public static StringComparer OrdinalIgnoreCase {
+ get {
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ return _ordinalIgnoreCase;
+ }
+ }
+
+ public static StringComparer Create(CultureInfo culture, bool ignoreCase) {
+ if( culture == null) {
+ throw new ArgumentNullException("culture");
+ }
+ Contract.Ensures(Contract.Result<StringComparer>() != null);
+ Contract.EndContractBlock();
+
+ return new CultureAwareComparer(culture, ignoreCase);
+ }
+
+ public int Compare(object x, object y) {
+ if (x == y) return 0;
+ if (x == null) return -1;
+ if (y == null) return 1;
+
+ String sa = x as String;
+ if (sa != null) {
+ String sb = y as String;
+ if( sb != null) {
+ return Compare(sa, sb);
+ }
+ }
+
+ IComparable ia = x as IComparable;
+ if (ia != null) {
+ return ia.CompareTo(y);
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("Argument_ImplementIComparable"));
+ }
+
+
+ public new bool Equals(Object x, Object y) {
+ if (x == y) return true;
+ if (x == null || y == null) return false;
+
+ String sa = x as String;
+ if (sa != null) {
+ String sb = y as String;
+ if( sb != null) {
+ return Equals(sa, sb);
+ }
+ }
+ return x.Equals(y);
+ }
+
+ public int GetHashCode(object obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ string s = obj as string;
+ if( s != null) {
+ return GetHashCode(s);
+ }
+ return obj.GetHashCode();
+ }
+
+ public abstract int Compare(String x, String y);
+ public abstract bool Equals(String x, String y);
+ public abstract int GetHashCode(string obj);
+ }
+
+ [Serializable]
+ internal sealed class CultureAwareComparer : StringComparer
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ , IWellKnownStringEqualityComparer
+#endif
+ {
+ private CompareInfo _compareInfo;
+ private bool _ignoreCase;
+
+ internal CultureAwareComparer(CultureInfo culture, bool ignoreCase) {
+ _compareInfo = culture.CompareInfo;
+ _ignoreCase = ignoreCase;
+ }
+
+ internal CultureAwareComparer(CompareInfo compareInfo, bool ignoreCase) {
+ _compareInfo = compareInfo;
+ _ignoreCase = ignoreCase;
+ }
+
+ public override int Compare(string x, string y) {
+ if (Object.ReferenceEquals(x, y)) return 0;
+ if (x == null) return -1;
+ if (y == null) return 1;
+ return _compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ public override bool Equals(string x, string y) {
+ if (Object.ReferenceEquals(x ,y)) return true;
+ if (x == null || y == null) return false;
+
+ return (_compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None) == 0);
+ }
+
+ public override int GetHashCode(string obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ CompareOptions options = CompareOptions.None;
+
+ if( _ignoreCase) {
+ options |= CompareOptions.IgnoreCase;
+ }
+
+ return _compareInfo.GetHashCodeOfString(obj, options);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ CultureAwareComparer comparer = obj as CultureAwareComparer;
+ if( comparer == null) {
+ return false;
+ }
+ return (this._ignoreCase == comparer._ignoreCase) && (this._compareInfo.Equals(comparer._compareInfo));
+ }
+
+ public override int GetHashCode() {
+ int hashCode = _compareInfo.GetHashCode() ;
+ return _ignoreCase ? (~hashCode) : hashCode;
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new CultureAwareRandomizedComparer(_compareInfo, _ignoreCase);
+ }
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return this;
+ }
+#endif
+
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ internal sealed class CultureAwareRandomizedComparer : StringComparer, IWellKnownStringEqualityComparer {
+
+ private CompareInfo _compareInfo;
+ private bool _ignoreCase;
+ private long _entropy;
+
+ internal CultureAwareRandomizedComparer(CompareInfo compareInfo, bool ignoreCase) {
+ _compareInfo = compareInfo;
+ _ignoreCase = ignoreCase;
+ _entropy = HashHelpers.GetEntropy();
+ }
+
+ public override int Compare(string x, string y) {
+ if (Object.ReferenceEquals(x, y)) return 0;
+ if (x == null) return -1;
+ if (y == null) return 1;
+ return _compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None);
+ }
+
+ public override bool Equals(string x, string y) {
+ if (Object.ReferenceEquals(x ,y)) return true;
+ if (x == null || y == null) return false;
+
+ return (_compareInfo.Compare(x, y, _ignoreCase? CompareOptions.IgnoreCase : CompareOptions.None) == 0);
+ }
+
+ public override int GetHashCode(string obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ CompareOptions options = CompareOptions.None;
+
+ if( _ignoreCase) {
+ options |= CompareOptions.IgnoreCase;
+ }
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return _compareInfo.GetHashCodeOfStringCore(obj, options, true, _entropy);
+#else
+ return _compareInfo.GetHashCodeOfString(obj, options, true, _entropy);
+#endif
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ CultureAwareRandomizedComparer comparer = obj as CultureAwareRandomizedComparer;
+ if( comparer == null) {
+ return false;
+ }
+ return (this._ignoreCase == comparer._ignoreCase) && (this._compareInfo.Equals(comparer._compareInfo)) && (this._entropy == comparer._entropy);
+ }
+
+ public override int GetHashCode() {
+ int hashCode = _compareInfo.GetHashCode() ;
+ return ((_ignoreCase ? (~hashCode) : hashCode) ^ ((int) (_entropy & 0x7FFFFFFF)));
+ }
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new CultureAwareRandomizedComparer(_compareInfo, _ignoreCase);
+ }
+
+ // We want to serialize the old comparer.
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return new CultureAwareComparer(_compareInfo, _ignoreCase);
+ }
+ }
+#endif
+
+ // Provide x more optimal implementation of ordinal comparison.
+ [Serializable]
+ internal sealed class OrdinalComparer : StringComparer
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ , IWellKnownStringEqualityComparer
+#endif
+ {
+ private bool _ignoreCase;
+
+ internal OrdinalComparer(bool ignoreCase) {
+ _ignoreCase = ignoreCase;
+ }
+
+ public override int Compare(string x, string y) {
+ if (Object.ReferenceEquals(x, y)) return 0;
+ if (x == null) return -1;
+ if (y == null) return 1;
+
+ if( _ignoreCase) {
+ return String.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+ }
+
+ return String.CompareOrdinal(x, y);
+ }
+
+ public override bool Equals(string x, string y) {
+ if (Object.ReferenceEquals(x ,y)) return true;
+ if (x == null || y == null) return false;
+
+ if( _ignoreCase) {
+ if( x.Length != y.Length) {
+ return false;
+ }
+ return (String.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+ return x.Equals(y);
+ }
+
+ public override int GetHashCode(string obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ if( _ignoreCase) {
+ return TextInfo.GetHashCodeOrdinalIgnoreCase(obj);
+ }
+
+ return obj.GetHashCode();
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ OrdinalComparer comparer = obj as OrdinalComparer;
+ if( comparer == null) {
+ return false;
+ }
+ return (this._ignoreCase == comparer._ignoreCase);
+ }
+
+ public override int GetHashCode() {
+ string name = "OrdinalComparer";
+ int hashCode = name.GetHashCode();
+ return _ignoreCase ? (~hashCode) : hashCode;
+ }
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new OrdinalRandomizedComparer(_ignoreCase);
+ }
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return this;
+ }
+#endif
+
+ }
+
+
+#if FEATURE_RANDOMIZED_STRING_HASHING
+ internal sealed class OrdinalRandomizedComparer : StringComparer, IWellKnownStringEqualityComparer {
+ private bool _ignoreCase;
+ private long _entropy;
+
+ internal OrdinalRandomizedComparer(bool ignoreCase) {
+ _ignoreCase = ignoreCase;
+ _entropy = HashHelpers.GetEntropy();
+ }
+
+ public override int Compare(string x, string y) {
+ if (Object.ReferenceEquals(x, y)) return 0;
+ if (x == null) return -1;
+ if (y == null) return 1;
+
+ if( _ignoreCase) {
+ return String.Compare(x, y, StringComparison.OrdinalIgnoreCase);
+ }
+
+ return String.CompareOrdinal(x, y);
+ }
+
+ public override bool Equals(string x, string y) {
+ if (Object.ReferenceEquals(x ,y)) return true;
+ if (x == null || y == null) return false;
+
+ if( _ignoreCase) {
+ if( x.Length != y.Length) {
+ return false;
+ }
+ return (String.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+ return x.Equals(y);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ public override int GetHashCode(string obj) {
+ if( obj == null) {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ if( _ignoreCase) {
+#if FEATURE_COREFX_GLOBALIZATION
+ return CultureInfo.InvariantCulture.CompareInfo.GetHashCodeOfStringCore(obj, CompareOptions.IgnoreCase, true, _entropy);
+#else
+ return TextInfo.GetHashCodeOrdinalIgnoreCase(obj, true, _entropy);
+#endif
+ }
+
+ return String.InternalMarvin32HashString(obj, obj.Length, _entropy);
+ }
+
+ // Equals method for the comparer itself.
+ public override bool Equals(Object obj){
+ OrdinalRandomizedComparer comparer = obj as OrdinalRandomizedComparer;
+ if( comparer == null) {
+ return false;
+ }
+ return (this._ignoreCase == comparer._ignoreCase) && (this._entropy == comparer._entropy);
+ }
+
+ public override int GetHashCode() {
+ string name = "OrdinalRandomizedComparer";
+ int hashCode = name.GetHashCode();
+ return ((_ignoreCase ? (~hashCode) : hashCode) ^ ((int) (_entropy & 0x7FFFFFFF)));
+ }
+
+ IEqualityComparer IWellKnownStringEqualityComparer.GetRandomizedEqualityComparer() {
+ return new OrdinalRandomizedComparer(_ignoreCase);
+ }
+
+ // We want to serialize the old comparer.
+ IEqualityComparer IWellKnownStringEqualityComparer.GetEqualityComparerForSerialization() {
+ return new OrdinalComparer(_ignoreCase);
+ }
+ }
+
+ // This interface is implemented by string comparers in the framework that can opt into
+ // randomized hashing behaviors.
+ internal interface IWellKnownStringEqualityComparer {
+ // Get an IEqualityComparer that has the same equality comparision rules as "this" but uses Randomized Hashing.
+ IEqualityComparer GetRandomizedEqualityComparer();
+ // Get an IEqaulityComparer that can be serailzied (e.g., it exists in older versions).
+ IEqualityComparer GetEqualityComparerForSerialization();
+ }
+#endif
+}
diff --git a/src/mscorlib/src/System/StringComparison.cs b/src/mscorlib/src/System/StringComparison.cs
new file mode 100644
index 0000000000..aa83e396b6
--- /dev/null
+++ b/src/mscorlib/src/System/StringComparison.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Enum: StringComparison
+**
+**
+** Purpose: A mechanism to expose a simplified infrastructure for
+** Comparing strings. This enum lets you choose of the custom
+** implementations provided by the runtime for the user.
+**
+**
+===========================================================*/
+namespace System{
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum StringComparison {
+ CurrentCulture = 0,
+ CurrentCultureIgnoreCase = 1,
+ InvariantCulture = 2,
+ InvariantCultureIgnoreCase = 3,
+ Ordinal = 4,
+ OrdinalIgnoreCase = 5,
+ }
+}
diff --git a/src/mscorlib/src/System/StringFreezingAttribute.cs b/src/mscorlib/src/System/StringFreezingAttribute.cs
new file mode 100644
index 0000000000..d488a88445
--- /dev/null
+++ b/src/mscorlib/src/System/StringFreezingAttribute.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Custom attribute to indicate that strings should be frozen
+**
+**
+===========================================================*/
+
+namespace System.Runtime.CompilerServices
+{
+
+[Serializable]
+ [AttributeUsage(AttributeTargets.Assembly, Inherited = false)]
+ public sealed class StringFreezingAttribute : Attribute
+ {
+ public StringFreezingAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/StringSplitOptions.cs b/src/mscorlib/src/System/StringSplitOptions.cs
new file mode 100644
index 0000000000..ae95aae9f8
--- /dev/null
+++ b/src/mscorlib/src/System/StringSplitOptions.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Runtime.InteropServices;
+
+namespace System
+{
+ [ComVisible(false)]
+ [Flags]
+ public enum StringSplitOptions
+ {
+ None = 0,
+ RemoveEmptyEntries = 1
+ }
+}
diff --git a/src/mscorlib/src/System/StubHelpers.cs b/src/mscorlib/src/System/StubHelpers.cs
new file mode 100644
index 0000000000..a9c584e9fc
--- /dev/null
+++ b/src/mscorlib/src/System/StubHelpers.cs
@@ -0,0 +1,1957 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System.StubHelpers {
+
+ using System.Text;
+ using Microsoft.Win32;
+ using System.Security;
+ using System.Collections.Generic;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+#if FEATURE_COMINTEROP
+ using System.Runtime.InteropServices.WindowsRuntime;
+#endif // FEATURE_COMINTEROP
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class AnsiCharMarshaler
+ {
+ // The length of the returned array is an approximation based on the length of the input string and the system
+ // character set. It is only guaranteed to be larger or equal to cbLength, don't depend on the exact value.
+ [System.Security.SecurityCritical]
+ unsafe static internal byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
+ {
+ byte[] buffer = new byte[(str.Length + 1) * Marshal.SystemMaxDBCSCharSize];
+ fixed (byte *bufferPtr = buffer)
+ {
+ cbLength = str.ConvertToAnsi(bufferPtr, buffer.Length, fBestFit, fThrowOnUnmappableChar);
+ }
+ return buffer;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe static internal byte ConvertToNative(char managedChar, bool fBestFit, bool fThrowOnUnmappableChar)
+ {
+ int cbAllocLength = (1 + 1) * Marshal.SystemMaxDBCSCharSize;
+ byte* bufferPtr = stackalloc byte[cbAllocLength];
+
+ int cbLength = managedChar.ToString().ConvertToAnsi(bufferPtr, cbAllocLength, fBestFit, fThrowOnUnmappableChar);
+
+ BCLDebug.Assert(cbLength > 0, "Zero bytes returned from DoAnsiConversion in AnsiCharMarshaler.ConvertToNative");
+ return bufferPtr[0];
+ }
+
+ static internal char ConvertToManaged(byte nativeChar)
+ {
+ byte[] bytes = new byte[1] { nativeChar };
+ string str = Encoding.Default.GetString(bytes);
+ return str[0];
+ }
+ } // class AnsiCharMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class CSTRMarshaler
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
+ {
+ if (null == strManaged)
+ {
+ return IntPtr.Zero;
+ }
+
+ StubHelpers.CheckStringLength(strManaged.Length);
+
+ int nb;
+ byte *pbNativeBuffer = (byte *)pNativeBuffer;
+
+ if (pbNativeBuffer != null || Marshal.SystemMaxDBCSCharSize == 1)
+ {
+ // If we are marshaling into a stack buffer or we can accurately estimate the size of the required heap
+ // space, we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.
+
+ // + 1 for the null character from the user
+ nb = (strManaged.Length + 1) * Marshal.SystemMaxDBCSCharSize;
+
+ // Use the pre-allocated buffer (allocated by localloc IL instruction) if not NULL,
+ // otherwise fallback to AllocCoTaskMem
+ if (pbNativeBuffer == null)
+ {
+ // + 1 for the null character we put in
+ pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
+ }
+
+ nb = strManaged.ConvertToAnsi(pbNativeBuffer, nb + 1, 0 != (flags & 0xFF), 0 != (flags >> 8));
+ }
+ else
+ {
+ // Otherwise we use a slower "2-pass" mode where we first marshal the string into an intermediate buffer
+ // (managed byte array) and then allocate exactly the right amount of unmanaged memory. This is to avoid
+ // wasting memory on systems with multibyte character sets where the buffer we end up with is often much
+ // smaller than the upper bound for the given managed string.
+
+ byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
+
+ // + 1 for the null character from the user. + 1 for the null character we put in.
+ pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 2);
+
+ Buffer.Memcpy(pbNativeBuffer, 0, bytes, 0, nb);
+ }
+
+ pbNativeBuffer[nb] = 0x00;
+ pbNativeBuffer[nb + 1] = 0x00;
+
+ return (IntPtr)pbNativeBuffer;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe string ConvertToManaged(IntPtr cstr)
+ {
+ if (IntPtr.Zero == cstr)
+ return null;
+ else
+ return new String((sbyte*)cstr);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal void ClearNative(IntPtr pNative)
+ {
+ Win32Native.CoTaskMemFree(pNative);
+ }
+ } // class CSTRMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class UTF8Marshaler
+ {
+ const int MAX_UTF8_CHAR_SIZE = 3;
+ [System.Security.SecurityCritical]
+ static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
+ {
+ if (null == strManaged)
+ {
+ return IntPtr.Zero;
+ }
+ StubHelpers.CheckStringLength(strManaged.Length);
+
+ int nb;
+ byte* pbNativeBuffer = (byte*)pNativeBuffer;
+
+ // If we are marshaling into a stack buffer allocated by the ILStub
+ // we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.
+ // else we will allocate the precise native heap memory.
+ if (pbNativeBuffer != null)
+ {
+ // this is the number of bytes allocated by the ILStub.
+ nb = (strManaged.Length + 1) * MAX_UTF8_CHAR_SIZE;
+
+ // nb is the actual number of bytes written by Encoding.GetBytes.
+ // use nb to de-limit the string since we are allocating more than
+ // required on stack
+ nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+ }
+ // required bytes > 260 , allocate required bytes on heap
+ else
+ {
+ nb = Encoding.UTF8.GetByteCount(strManaged);
+ // + 1 for the null character.
+ pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
+ strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+ }
+ pbNativeBuffer[nb] = 0x0;
+ return (IntPtr)pbNativeBuffer;
+ }
+
+ [System.Security.SecurityCritical]
+ static internal unsafe string ConvertToManaged(IntPtr cstr)
+ {
+ if (IntPtr.Zero == cstr)
+ return null;
+ int nbBytes = StubHelpers.strlen((sbyte*)cstr);
+ return String.CreateStringFromEncoding((byte*)cstr, nbBytes, Encoding.UTF8);
+ }
+
+ [System.Security.SecurityCritical]
+ static internal void ClearNative(IntPtr pNative)
+ {
+ if (pNative != IntPtr.Zero)
+ {
+ Win32Native.CoTaskMemFree(pNative);
+ }
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class UTF8BufferMarshaler
+ {
+ [System.Security.SecurityCritical]
+ static internal unsafe IntPtr ConvertToNative(StringBuilder sb, IntPtr pNativeBuffer, int flags)
+ {
+ if (null == sb)
+ {
+ return IntPtr.Zero;
+ }
+
+ // Convert to string first
+ string strManaged = sb.ToString();
+
+ // Get byte count
+ int nb = Encoding.UTF8.GetByteCount(strManaged);
+
+ // EmitConvertSpaceCLRToNative allocates memory
+ byte* pbNativeBuffer = (byte*)pNativeBuffer;
+ nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
+
+ pbNativeBuffer[nb] = 0x0;
+ return (IntPtr)pbNativeBuffer;
+ }
+
+ [System.Security.SecurityCritical]
+ static internal unsafe void ConvertToManaged(StringBuilder sb, IntPtr pNative)
+ {
+ if (pNative == null)
+ return;
+
+ int nbBytes = StubHelpers.strlen((sbyte*)pNative);
+ int numChar = Encoding.UTF8.GetCharCount((byte*)pNative, nbBytes);
+
+ // +1 GetCharCount return 0 if the pNative points to a
+ // an empty buffer.We still need to allocate an empty
+ // buffer with a '\0' to distingiush it from null.
+ // Note that pinning on (char *pinned = new char[0])
+ // return null and Encoding.UTF8.GetChars do not like
+ // null argument.
+ char[] cCharBuffer = new char[numChar + 1];
+ cCharBuffer[numChar] = '\0';
+ fixed (char* pBuffer = cCharBuffer)
+ {
+ numChar = Encoding.UTF8.GetChars((byte*)pNative, nbBytes, pBuffer, numChar);
+ // replace string builder internal buffer
+ sb.ReplaceBufferInternal(pBuffer, numChar);
+ }
+ }
+ }
+
+#if FEATURE_COMINTEROP
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class BSTRMarshaler
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeBuffer)
+ {
+ if (null == strManaged)
+ {
+ return IntPtr.Zero;
+ }
+ else
+ {
+ StubHelpers.CheckStringLength(strManaged.Length);
+
+ byte trailByte;
+ bool hasTrailByte = strManaged.TryGetTrailByte(out trailByte);
+
+ uint lengthInBytes = (uint)strManaged.Length * 2;
+
+ if (hasTrailByte)
+ {
+ // this is an odd-sized string with a trailing byte stored in its sync block
+ lengthInBytes++;
+ }
+
+ byte *ptrToFirstChar;
+
+ if (pNativeBuffer != IntPtr.Zero)
+ {
+ // If caller provided a buffer, construct the BSTR manually. The size
+ // of the buffer must be at least (lengthInBytes + 6) bytes.
+#if _DEBUG
+ uint length = *((uint *)pNativeBuffer.ToPointer());
+ BCLDebug.Assert(length >= lengthInBytes + 6, "BSTR localloc'ed buffer is too small");
+#endif // _DEBUG
+
+ // set length
+ *((uint *)pNativeBuffer.ToPointer()) = lengthInBytes;
+
+ ptrToFirstChar = (byte *)pNativeBuffer.ToPointer() + 4;
+ }
+ else
+ {
+ // If not provided, allocate the buffer using SysAllocStringByteLen so
+ // that odd-sized strings will be handled as well.
+ ptrToFirstChar = (byte *)Win32Native.SysAllocStringByteLen(null, lengthInBytes).ToPointer();
+
+ if (ptrToFirstChar == null)
+ {
+ throw new OutOfMemoryException();
+ }
+ }
+
+ // copy characters from the managed string
+ fixed (char* ch = strManaged)
+ {
+ Buffer.Memcpy(
+ ptrToFirstChar,
+ (byte *)ch,
+ (strManaged.Length + 1) * 2);
+ }
+
+ // copy the trail byte if present
+ if (hasTrailByte)
+ {
+ ptrToFirstChar[lengthInBytes - 1] = trailByte;
+ }
+
+ // return ptr to first character
+ return (IntPtr)ptrToFirstChar;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe string ConvertToManaged(IntPtr bstr)
+ {
+ if (IntPtr.Zero == bstr)
+ {
+ return null;
+ }
+ else
+ {
+ uint length = Win32Native.SysStringByteLen(bstr);
+
+ // Intentionally checking the number of bytes not characters to match the behavior
+ // of ML marshalers. This prevents roundtripping of very large strings as the check
+ // in the managed->native direction is done on String length but considering that
+ // it's completely moot on 32-bit and not expected to be important on 64-bit either,
+ // the ability to catch random garbage in the BSTR's length field outweighs this
+ // restriction. If an ordinary null-terminated string is passed instead of a BSTR,
+ // chances are that the length field - possibly being unallocated memory - contains
+ // a heap fill pattern that will have the highest bit set, caught by the check.
+ StubHelpers.CheckStringLength(length);
+
+ string ret;
+ if (length == 1)
+ {
+ // In the empty string case, we need to use FastAllocateString rather than the
+ // String .ctor, since newing up a 0 sized string will always return String.Emtpy.
+ // When we marshal that out as a bstr, it can wind up getting modified which
+ // corrupts String.Empty.
+ ret = String.FastAllocateString(0);
+ }
+ else
+ {
+ ret = new String((char*)bstr, 0, (int)(length / 2));
+ }
+
+ if ((length & 1) == 1)
+ {
+ // odd-sized strings need to have the trailing byte saved in their sync block
+ ret.SetTrailByte(((byte *)bstr.ToPointer())[length - 1]);
+ }
+
+ return ret;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal void ClearNative(IntPtr pNative)
+ {
+ if (IntPtr.Zero != pNative)
+ {
+ Win32Native.SysFreeString(pNative);
+ }
+ }
+ } // class BSTRMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class VBByValStrMarshaler
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
+ {
+ if (null == strManaged)
+ {
+ return IntPtr.Zero;
+ }
+
+ byte* pNative;
+
+ cch = strManaged.Length;
+
+ StubHelpers.CheckStringLength(cch);
+
+ // length field at negative offset + (# of characters incl. the terminator) * max ANSI char size
+ int nbytes = sizeof(uint) + ((cch + 1) * Marshal.SystemMaxDBCSCharSize);
+
+ pNative = (byte*)Marshal.AllocCoTaskMem(nbytes);
+ int* pLength = (int*)pNative;
+
+ pNative = pNative + sizeof(uint);
+
+ if (0 == cch)
+ {
+ *pNative = 0;
+ *pLength = 0;
+ }
+ else
+ {
+ int nbytesused;
+ byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, fBestFit, fThrowOnUnmappableChar, out nbytesused);
+
+ BCLDebug.Assert(nbytesused < nbytes, "Insufficient buffer allocated in VBByValStrMarshaler.ConvertToNative");
+ Buffer.Memcpy(pNative, 0, bytes, 0, nbytesused);
+
+ pNative[nbytesused] = 0;
+ *pLength = nbytesused;
+ }
+
+ return new IntPtr(pNative);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe string ConvertToManaged(IntPtr pNative, int cch)
+ {
+ if (IntPtr.Zero == pNative)
+ {
+ return null;
+ }
+
+ return new String((sbyte*)pNative, 0, cch);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe void ClearNative(IntPtr pNative)
+ {
+ if (IntPtr.Zero != pNative)
+ {
+ Win32Native.CoTaskMemFree((IntPtr)(((long)pNative) - sizeof(uint)));
+ }
+ }
+ } // class VBByValStrMarshaler
+
+
+#if FEATURE_COMINTEROP
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class AnsiBSTRMarshaler
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe IntPtr ConvertToNative(int flags, string strManaged)
+ {
+ if (null == strManaged)
+ {
+ return IntPtr.Zero;
+ }
+
+ int length = strManaged.Length;
+
+ StubHelpers.CheckStringLength(length);
+
+ byte[] bytes = null;
+ int nb = 0;
+
+ if (length > 0)
+ {
+ bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
+ }
+
+ return Win32Native.SysAllocStringByteLen(bytes, (uint)nb);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe string ConvertToManaged(IntPtr bstr)
+ {
+ if (IntPtr.Zero == bstr)
+ {
+ return null;
+ }
+ else
+ {
+ // We intentionally ignore the length field of the BSTR for back compat reasons.
+ // Unfortunately VB.NET uses Ansi BSTR marshaling when a string is passed ByRef
+ // and we cannot afford to break this common scenario.
+ return new String((sbyte*)bstr);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static internal unsafe void ClearNative(IntPtr pNative)
+ {
+ if (IntPtr.Zero != pNative)
+ {
+ Win32Native.SysFreeString(pNative);
+ }
+ }
+ } // class AnsiBSTRMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class WSTRBufferMarshaler
+ {
+ static internal IntPtr ConvertToNative(string strManaged)
+ {
+ Contract.Assert(false, "NYI");
+ return IntPtr.Zero;
+ }
+
+ static internal unsafe string ConvertToManaged(IntPtr bstr)
+ {
+ Contract.Assert(false, "NYI");
+ return null;
+ }
+
+ static internal void ClearNative(IntPtr pNative)
+ {
+ Contract.Assert(false, "NYI");
+ }
+ } // class WSTRBufferMarshaler
+
+
+#if FEATURE_COMINTEROP
+
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct DateTimeNative
+ {
+ public Int64 UniversalTime;
+ };
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class DateTimeOffsetMarshaler {
+
+ // Numer of ticks counted between 0001-01-01, 00:00:00 and 1601-01-01, 00:00:00.
+ // You can get this through: (new DateTimeOffset(1601, 1, 1, 0, 0, 1, TimeSpan.Zero)).Ticks;
+ private const Int64 ManagedUtcTicksAtNativeZero = 504911232000000000;
+
+ [SecurityCritical]
+ internal static void ConvertToNative(ref DateTimeOffset managedDTO, out DateTimeNative dateTime) {
+
+ Int64 managedUtcTicks = managedDTO.UtcTicks;
+ dateTime.UniversalTime = managedUtcTicks - ManagedUtcTicksAtNativeZero;
+ }
+
+ [SecurityCritical]
+ internal static void ConvertToManaged(out DateTimeOffset managedLocalDTO, ref DateTimeNative nativeTicks) {
+
+ Int64 managedUtcTicks = ManagedUtcTicksAtNativeZero + nativeTicks.UniversalTime;
+ DateTimeOffset managedUtcDTO = new DateTimeOffset(managedUtcTicks, TimeSpan.Zero);
+
+ // Some Utc times cannot be represented in local time in certain timezones. E.g. 0001-01-01 12:00:00 AM cannot
+ // be represented in any timezones with a negative offset from Utc. We throw an ArgumentException in that case.
+ managedLocalDTO = managedUtcDTO.ToLocalTime(true);
+ }
+ } // class DateTimeOffsetMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+
+#if FEATURE_COMINTEROP
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class HStringMarshaler
+ {
+ // Slow-path, which requires making a copy of the managed string into the resulting HSTRING
+ [SecurityCritical]
+ internal static unsafe IntPtr ConvertToNative(string managed)
+ {
+ if (!Environment.IsWinRTSupported)
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ if (managed == null)
+ throw new ArgumentNullException(); // We don't have enough information to get the argument name
+
+ IntPtr hstring;
+ int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(managed, managed.Length, &hstring);
+ Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
+ return hstring;
+ }
+
+ // Fast-path, which creates a reference over a pinned managed string. This may only be used if the
+ // pinned string and HSTRING_HEADER will outlive the HSTRING produced (for instance, as an in parameter).
+ //
+ // Note that the managed string input to this method MUST be pinned, and stay pinned for the lifetime of
+ // the returned HSTRING object. If the string is not pinned, or becomes unpinned before the HSTRING's
+ // lifetime ends, the HSTRING instance will be corrupted.
+ [SecurityCritical]
+ internal static unsafe IntPtr ConvertToNativeReference(string managed,
+ [Out] HSTRING_HEADER *hstringHeader)
+ {
+ if (!Environment.IsWinRTSupported)
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ if (managed == null)
+ throw new ArgumentNullException(); // We don't have enough information to get the argument name
+
+ // The string must also be pinned by the caller to ConvertToNativeReference, which also owns
+ // the HSTRING_HEADER.
+ fixed (char *pManaged = managed)
+ {
+ IntPtr hstring;
+ int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateStringReference(pManaged, managed.Length, hstringHeader, &hstring);
+ Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
+ return hstring;
+ }
+ }
+
+ [SecurityCritical]
+ internal static string ConvertToManaged(IntPtr hstring)
+ {
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ return WindowsRuntimeMarshal.HStringToString(hstring);
+ }
+
+ [SecurityCritical]
+ internal static void ClearNative(IntPtr hstring)
+ {
+ Contract.Assert(Environment.IsWinRTSupported);
+
+ if (hstring != IntPtr.Zero)
+ {
+ System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(hstring);
+ }
+ }
+ } // class HStringMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class ObjectMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertToNative(object objSrc, IntPtr pDstVariant);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern object ConvertToManaged(IntPtr pSrcVariant);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNative(IntPtr pVariant);
+ } // class ObjectMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class ValueClassMarshaler
+ {
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkList pCleanupWorkList);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNative(IntPtr dst, IntPtr pMT);
+ } // class ValueClassMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class DateMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern double ConvertToNative(DateTime managedDate);
+
+ // The return type is really DateTime but we use long to avoid the pain associated with returning structures.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern long ConvertToManaged(double nativeDate);
+ } // class DateMarshaler
+
+#if FEATURE_COMINTEROP
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [FriendAccessAllowed]
+ internal static class InterfaceMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
+ static internal extern void ClearNative(IntPtr pUnk);
+
+ [FriendAccessAllowed]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern object ConvertToManagedWithoutUnboxing(IntPtr pNative);
+ } // class InterfaceMarshaler
+#endif // FEATURE_COMINTEROP
+
+#if FEATURE_COMINTEROP
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class UriMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern string GetRawUriFromNative(IntPtr pUri);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecurityCritical]
+ static unsafe internal extern IntPtr CreateNativeUriInstanceHelper(char* rawUri, int strLen);
+
+ [System.Security.SecurityCritical]
+ static unsafe internal IntPtr CreateNativeUriInstance(string rawUri)
+ {
+ fixed(char* pManaged = rawUri)
+ {
+ return CreateNativeUriInstanceHelper(pManaged, rawUri.Length);
+ }
+ }
+
+ } // class InterfaceMarshaler
+
+ [FriendAccessAllowed]
+ internal static class EventArgsMarshaler
+ {
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ static internal IntPtr CreateNativeNCCEventArgsInstance(int action, object newItems, object oldItems, int newIndex, int oldIndex)
+ {
+ IntPtr newItemsIP = IntPtr.Zero;
+ IntPtr oldItemsIP = IntPtr.Zero;
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ if (newItems != null)
+ newItemsIP = Marshal.GetComInterfaceForObject(newItems, typeof(IBindableVector));
+ if (oldItems != null)
+ oldItemsIP = Marshal.GetComInterfaceForObject(oldItems, typeof(IBindableVector));
+
+ return CreateNativeNCCEventArgsInstanceHelper(action, newItemsIP, oldItemsIP, newIndex, oldIndex);
+ }
+ finally
+ {
+ if (!oldItemsIP.IsNull())
+ Marshal.Release(oldItemsIP);
+ if (!newItemsIP.IsNull())
+ Marshal.Release(newItemsIP);
+ }
+ }
+
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
+ static extern internal IntPtr CreateNativePCEventArgsInstance([MarshalAs(UnmanagedType.HString)]string name);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
+ static extern internal IntPtr CreateNativeNCCEventArgsInstanceHelper(int action, IntPtr newItem, IntPtr oldItem, int newIndex, int oldIndex);
+ }
+#endif // FEATURE_COMINTEROP
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class MngdNativeArrayMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome,
+ int cElements);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNative(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
+ } // class MngdNativeArrayMarshaler
+
+#if FEATURE_COMINTEROP
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class MngdSafeArrayMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, object pOriginalManaged);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+ } // class MngdSafeArrayMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class MngdHiddenLengthArrayMarshaler
+ {
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt);
+
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ DateTimeNative *nativeBuffer = *(DateTimeNative **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ DateTimeOffsetMarshaler.ConvertToNative(ref managedArray[i], out nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ TypeNameNative *nativeBuffer = *(TypeNameNative **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ SystemTypeMarshaler.ConvertToNative(managedArray[i], &nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ Int32 *nativeBuffer = *(Int32 **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ nativeBuffer[i] = HResultExceptionMarshaler.ConvertToNative(managedArray[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToNative_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
+ where T : struct
+ {
+ if (managedArray != null)
+ {
+ IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ nativeBuffer[i] = NullableMarshaler.ConvertToNative<T>(ref managedArray[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToNative_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ nativeBuffer[i] = KeyValuePairMarshaler.ConvertToNative<K, V>(ref managedArray[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int elementCount);
+
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ DateTimeNative *nativeBuffer = *(DateTimeNative **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ DateTimeOffsetMarshaler.ConvertToManaged(out managedArray[i], ref nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ TypeNameNative *nativeBuffer = *(TypeNameNative **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ SystemTypeMarshaler.ConvertToManaged(&nativeBuffer[i], ref managedArray[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ Int32 *nativeBuffer = *(Int32 **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ managedArray[i] = HResultExceptionMarshaler.ConvertToManaged(nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToManaged_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
+ where T : struct
+ {
+ if (managedArray != null)
+ {
+ IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ managedArray[i] = NullableMarshaler.ConvertToManaged<T>(nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertContentsToManaged_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
+ {
+ if (managedArray != null)
+ {
+ IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
+ for (int i = 0; i < managedArray.Length; i++)
+ {
+ managedArray[i] = KeyValuePairMarshaler.ConvertToManaged<K, V>(nativeBuffer[i]);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
+
+ [SecurityCritical]
+ internal static unsafe void ClearNativeContents_Type(IntPtr pNativeHome, int cElements)
+ {
+ Contract.Assert(Environment.IsWinRTSupported);
+
+ TypeNameNative *pNativeTypeArray = *(TypeNameNative **)pNativeHome;
+ if (pNativeTypeArray != null)
+ {
+ for (int i = 0; i < cElements; ++i)
+ {
+ SystemTypeMarshaler.ClearNative(pNativeTypeArray);
+ pNativeTypeArray++;
+ }
+ }
+ }
+ } // class MngdHiddenLengthArrayMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class MngdRefCustomMarshaler
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pCMHelper);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
+ } // class MngdRefCustomMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [System.Security.SecurityCritical]
+ internal struct AsAnyMarshaler
+ {
+ private const ushort VTHACK_ANSICHAR = 253;
+ private const ushort VTHACK_WINBOOL = 254;
+
+ private enum BackPropAction
+ {
+ None,
+ Array,
+ Layout,
+ StringBuilderAnsi,
+ StringBuilderUnicode
+ }
+
+ // Pointer to MngdNativeArrayMarshaler, ownership not assumed.
+ private IntPtr pvArrayMarshaler;
+
+ // Type of action to perform after the CLR-to-unmanaged call.
+ private BackPropAction backPropAction;
+
+ // The managed layout type for BackPropAction.Layout.
+ private Type layoutType;
+
+ // Cleanup list to be destroyed when clearing the native view (for layouts with SafeHandles).
+ private CleanupWorkList cleanupWorkList;
+
+ private static bool IsIn(int dwFlags) { return ((dwFlags & 0x10000000) != 0); }
+ private static bool IsOut(int dwFlags) { return ((dwFlags & 0x20000000) != 0); }
+ private static bool IsAnsi(int dwFlags) { return ((dwFlags & 0x00FF0000) != 0); }
+ private static bool IsThrowOn(int dwFlags) { return ((dwFlags & 0x0000FF00) != 0); }
+ private static bool IsBestFit(int dwFlags) { return ((dwFlags & 0x000000FF) != 0); }
+
+ internal AsAnyMarshaler(IntPtr pvArrayMarshaler)
+ {
+ // we need this in case the value being marshaled turns out to be array
+ BCLDebug.Assert(pvArrayMarshaler != IntPtr.Zero, "pvArrayMarshaler must not be null");
+
+ this.pvArrayMarshaler = pvArrayMarshaler;
+ this.backPropAction = BackPropAction.None;
+ this.layoutType = null;
+ this.cleanupWorkList = null;
+ }
+
+ #region ConvertToNative helpers
+
+ [System.Security.SecurityCritical]
+ private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags)
+ {
+ Type elementType = pManagedHome.GetType().GetElementType();
+ VarEnum vt = VarEnum.VT_EMPTY;
+
+ switch (Type.GetTypeCode(elementType))
+ {
+ case TypeCode.SByte: vt = VarEnum.VT_I1; break;
+ case TypeCode.Byte: vt = VarEnum.VT_UI1; break;
+ case TypeCode.Int16: vt = VarEnum.VT_I2; break;
+ case TypeCode.UInt16: vt = VarEnum.VT_UI2; break;
+ case TypeCode.Int32: vt = VarEnum.VT_I4; break;
+ case TypeCode.UInt32: vt = VarEnum.VT_UI4; break;
+ case TypeCode.Int64: vt = VarEnum.VT_I8; break;
+ case TypeCode.UInt64: vt = VarEnum.VT_UI8; break;
+ case TypeCode.Single: vt = VarEnum.VT_R4; break;
+ case TypeCode.Double: vt = VarEnum.VT_R8; break;
+ case TypeCode.Char: vt = (IsAnsi(dwFlags) ? (VarEnum)VTHACK_ANSICHAR : VarEnum.VT_UI2); break;
+ case TypeCode.Boolean: vt = (VarEnum)VTHACK_WINBOOL; break;
+
+ case TypeCode.Object:
+ {
+ if (elementType == typeof(IntPtr))
+ {
+ vt = (IntPtr.Size == 4 ? VarEnum.VT_I4 : VarEnum.VT_I8);
+ }
+ else if (elementType == typeof(UIntPtr))
+ {
+ vt = (IntPtr.Size == 4 ? VarEnum.VT_UI4 : VarEnum.VT_UI8);
+ }
+ else goto default;
+ break;
+ }
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Arg_NDirectBadObject"));
+ }
+
+ // marshal the object as C-style array (UnmanagedType.LPArray)
+ int dwArrayMarshalerFlags = (int)vt;
+ if (IsBestFit(dwFlags)) dwArrayMarshalerFlags |= (1 << 16);
+ if (IsThrowOn(dwFlags)) dwArrayMarshalerFlags |= (1 << 24);
+
+ MngdNativeArrayMarshaler.CreateMarshaler(
+ pvArrayMarshaler,
+ IntPtr.Zero, // not needed as we marshal primitive VTs only
+ dwArrayMarshalerFlags);
+
+ IntPtr pNativeHome;
+ IntPtr pNativeHomeAddr = new IntPtr(&pNativeHome);
+
+ MngdNativeArrayMarshaler.ConvertSpaceToNative(
+ pvArrayMarshaler,
+ ref pManagedHome,
+ pNativeHomeAddr);
+
+ if (IsIn(dwFlags))
+ {
+ MngdNativeArrayMarshaler.ConvertContentsToNative(
+ pvArrayMarshaler,
+ ref pManagedHome,
+ pNativeHomeAddr);
+ }
+ if (IsOut(dwFlags))
+ {
+ backPropAction = BackPropAction.Array;
+ }
+
+ return pNativeHome;
+ }
+
+ [System.Security.SecurityCritical]
+ private static IntPtr ConvertStringToNative(string pManagedHome, int dwFlags)
+ {
+ IntPtr pNativeHome;
+
+ // IsIn, IsOut are ignored for strings - they're always in-only
+ if (IsAnsi(dwFlags))
+ {
+ // marshal the object as Ansi string (UnmanagedType.LPStr)
+ pNativeHome = CSTRMarshaler.ConvertToNative(
+ dwFlags & 0xFFFF, // (throw on unmappable char << 8 | best fit)
+ pManagedHome, //
+ IntPtr.Zero); // unmanaged buffer will be allocated
+ }
+ else
+ {
+ // marshal the object as Unicode string (UnmanagedType.LPWStr)
+ StubHelpers.CheckStringLength(pManagedHome.Length);
+
+ int allocSize = (pManagedHome.Length + 1) * 2;
+ pNativeHome = Marshal.AllocCoTaskMem(allocSize);
+
+ String.InternalCopy(pManagedHome, pNativeHome, allocSize);
+ }
+
+ return pNativeHome;
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe IntPtr ConvertStringBuilderToNative(StringBuilder pManagedHome, int dwFlags)
+ {
+ IntPtr pNativeHome;
+
+ // P/Invoke can be used to call Win32 apis that don't strictly follow CLR in/out semantics and thus may
+ // leave garbage in the buffer in circumstances that we can't detect. To prevent us from crashing when
+ // converting the contents back to managed, put a hidden NULL terminator past the end of the official buffer.
+
+ // Unmanaged layout:
+ // +====================================+
+ // | Extra hidden NULL |
+ // +====================================+ \
+ // | | |
+ // | [Converted] NULL-terminated string | |- buffer that the target may change
+ // | | |
+ // +====================================+ / <-- native home
+
+ // Note that StringBuilder.Capacity is the number of characters NOT including any terminators.
+
+ if (IsAnsi(dwFlags))
+ {
+ StubHelpers.CheckStringLength(pManagedHome.Capacity);
+
+ // marshal the object as Ansi string (UnmanagedType.LPStr)
+ int allocSize = (pManagedHome.Capacity * Marshal.SystemMaxDBCSCharSize) + 4;
+ pNativeHome = Marshal.AllocCoTaskMem(allocSize);
+
+ byte* ptr = (byte*)pNativeHome;
+ *(ptr + allocSize - 3) = 0;
+ *(ptr + allocSize - 2) = 0;
+ *(ptr + allocSize - 1) = 0;
+
+ if (IsIn(dwFlags))
+ {
+ int length = pManagedHome.ToString().ConvertToAnsi(
+ ptr, allocSize,
+ IsBestFit(dwFlags),
+ IsThrowOn(dwFlags));
+ Contract.Assert(length < allocSize, "Expected a length less than the allocated size");
+ }
+ if (IsOut(dwFlags))
+ {
+ backPropAction = BackPropAction.StringBuilderAnsi;
+ }
+ }
+ else
+ {
+ // marshal the object as Unicode string (UnmanagedType.LPWStr)
+ int allocSize = (pManagedHome.Capacity * 2) + 4;
+ pNativeHome = Marshal.AllocCoTaskMem(allocSize);
+
+ byte* ptr = (byte*)pNativeHome;
+ *(ptr + allocSize - 1) = 0;
+ *(ptr + allocSize - 2) = 0;
+
+ if (IsIn(dwFlags))
+ {
+ int length = pManagedHome.Length * 2;
+ pManagedHome.InternalCopy(pNativeHome, length);
+
+ // null-terminate the native string
+ *(ptr + length + 0) = 0;
+ *(ptr + length + 1) = 0;
+ }
+ if (IsOut(dwFlags))
+ {
+ backPropAction = BackPropAction.StringBuilderUnicode;
+ }
+ }
+
+ return pNativeHome;
+ }
+
+ [System.Security.SecurityCritical]
+ private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags)
+ {
+ // Note that the following call will not throw exception if the type
+ // of pManagedHome is not marshalable. That's intentional because we
+ // want to maintain the original behavior where this was indicated
+ // by TypeLoadException during the actual field marshaling.
+ int allocSize = Marshal.SizeOfHelper(pManagedHome.GetType(), false);
+ IntPtr pNativeHome = Marshal.AllocCoTaskMem(allocSize);
+
+ // marshal the object as class with layout (UnmanagedType.LPStruct)
+ if (IsIn(dwFlags))
+ {
+ StubHelpers.FmtClassUpdateNativeInternal(pManagedHome, (byte *)pNativeHome.ToPointer(), ref cleanupWorkList);
+ }
+ if (IsOut(dwFlags))
+ {
+ backPropAction = BackPropAction.Layout;
+ }
+ layoutType = pManagedHome.GetType();
+
+ return pNativeHome;
+ }
+
+ #endregion
+
+ [System.Security.SecurityCritical]
+ internal IntPtr ConvertToNative(object pManagedHome, int dwFlags)
+ {
+ if (pManagedHome == null)
+ return IntPtr.Zero;
+
+ if (pManagedHome is ArrayWithOffset)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MarshalAsAnyRestriction"));
+
+ IntPtr pNativeHome;
+
+ if (pManagedHome.GetType().IsArray)
+ {
+ // array (LPArray)
+ pNativeHome = ConvertArrayToNative(pManagedHome, dwFlags);
+ }
+ else
+ {
+ string strValue;
+ StringBuilder sbValue;
+
+ if ((strValue = pManagedHome as string) != null)
+ {
+ // string (LPStr or LPWStr)
+ pNativeHome = ConvertStringToNative(strValue, dwFlags);
+ }
+ else if ((sbValue = pManagedHome as StringBuilder) != null)
+ {
+ // StringBuilder (LPStr or LPWStr)
+ pNativeHome = ConvertStringBuilderToNative(sbValue, dwFlags);
+ }
+ else if (pManagedHome.GetType().IsLayoutSequential || pManagedHome.GetType().IsExplicitLayout)
+ {
+ // layout (LPStruct)
+ pNativeHome = ConvertLayoutToNative(pManagedHome, dwFlags);
+ }
+ else
+ {
+ // this type is not supported for AsAny marshaling
+ throw new ArgumentException(Environment.GetResourceString("Arg_NDirectBadObject"));
+ }
+ }
+
+ return pNativeHome;
+ }
+
+ [System.Security.SecurityCritical]
+ internal unsafe void ConvertToManaged(object pManagedHome, IntPtr pNativeHome)
+ {
+ switch (backPropAction)
+ {
+ case BackPropAction.Array:
+ {
+ MngdNativeArrayMarshaler.ConvertContentsToManaged(
+ pvArrayMarshaler,
+ ref pManagedHome,
+ new IntPtr(&pNativeHome));
+ break;
+ }
+
+ case BackPropAction.Layout:
+ {
+ StubHelpers.FmtClassUpdateCLRInternal(pManagedHome, (byte *)pNativeHome.ToPointer());
+ break;
+ }
+
+ case BackPropAction.StringBuilderAnsi:
+ {
+ sbyte* ptr = (sbyte*)pNativeHome.ToPointer();
+ ((StringBuilder)pManagedHome).ReplaceBufferAnsiInternal(ptr, Win32Native.lstrlenA(pNativeHome));
+ break;
+ }
+
+ case BackPropAction.StringBuilderUnicode:
+ {
+ char* ptr = (char*)pNativeHome.ToPointer();
+ ((StringBuilder)pManagedHome).ReplaceBufferInternal(ptr, Win32Native.lstrlenW(pNativeHome));
+ break;
+ }
+
+ // nothing to do for BackPropAction.None
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal void ClearNative(IntPtr pNativeHome)
+ {
+ if (pNativeHome != IntPtr.Zero)
+ {
+ if (layoutType != null)
+ {
+ // this must happen regardless of BackPropAction
+ Marshal.DestroyStructure(pNativeHome, layoutType);
+ }
+ Win32Native.CoTaskMemFree(pNativeHome);
+ }
+ StubHelpers.DestroyCleanupList(ref cleanupWorkList);
+ }
+ } // struct AsAnyMarshaler
+
+#if FEATURE_COMINTEROP
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class NullableMarshaler
+ {
+ [SecurityCritical]
+ static internal IntPtr ConvertToNative<T>(ref Nullable<T> pManaged) where T : struct
+ {
+ if (pManaged.HasValue)
+ {
+ object impl = IReferenceFactory.CreateIReference(pManaged);
+ return Marshal.GetComInterfaceForObject(impl, typeof(IReference<T>));
+ }
+ else
+ {
+ return IntPtr.Zero;
+ }
+ }
+
+ [SecurityCritical]
+ static internal void ConvertToManagedRetVoid<T>(IntPtr pNative, ref Nullable<T> retObj) where T : struct
+ {
+ retObj = ConvertToManaged<T>(pNative);
+ }
+
+
+ [SecurityCritical]
+ static internal Nullable<T> ConvertToManaged<T>(IntPtr pNative) where T : struct
+ {
+ if (pNative != IntPtr.Zero)
+ {
+ object wrapper = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pNative);
+ return (Nullable<T>)CLRIReferenceImpl<T>.UnboxHelper(wrapper);
+ }
+ else
+ {
+ return new Nullable<T>();
+ }
+ }
+ } // class NullableMarshaler
+
+ // Corresponds to Windows.UI.Xaml.Interop.TypeName
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct TypeNameNative
+ {
+
+ internal IntPtr typeName; // HSTRING
+ internal TypeKind typeKind; // TypeKind enum
+ }
+
+ // Corresponds to Windows.UI.Xaml.TypeSource
+ internal enum TypeKind
+ {
+ Primitive,
+ Metadata,
+ Projection
+ };
+
+ internal static class WinRTTypeNameConverter
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern string ConvertToWinRTTypeName(System.Type managedType, out bool isPrimitive);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern System.Type GetTypeFromWinRTTypeName(string typeName, out bool isPrimitive);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class SystemTypeMarshaler
+ {
+ [SecurityCritical]
+ internal static unsafe void ConvertToNative(System.Type managedType, TypeNameNative *pNativeType)
+ {
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ string typeName;
+ if (managedType != null)
+ {
+ if (managedType.GetType() != typeof(System.RuntimeType))
+ { // The type should be exactly System.RuntimeType (and not its child System.ReflectionOnlyType, or other System.Type children)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WinRTSystemRuntimeType", managedType.GetType().ToString()));
+ }
+
+ bool isPrimitive;
+ string winrtTypeName = WinRTTypeNameConverter.ConvertToWinRTTypeName(managedType, out isPrimitive);
+ if (winrtTypeName != null)
+ {
+ // Must be a WinRT type, either in a WinMD or a Primitive
+ typeName = winrtTypeName;
+ if (isPrimitive)
+ pNativeType->typeKind = TypeKind.Primitive;
+ else
+ pNativeType->typeKind = TypeKind.Metadata;
+ }
+ else
+ {
+ // Custom .NET type
+ typeName = managedType.AssemblyQualifiedName;
+ pNativeType->typeKind = TypeKind.Projection;
+ }
+ }
+ else
+ { // Marshal null as empty string + Projection
+ typeName = "";
+ pNativeType->typeKind = TypeKind.Projection;
+ }
+
+ int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(typeName, typeName.Length, &pNativeType->typeName);
+ Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ConvertToManaged(TypeNameNative *pNativeType, ref System.Type managedType)
+ {
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ string typeName = WindowsRuntimeMarshal.HStringToString(pNativeType->typeName);
+ if (String.IsNullOrEmpty(typeName))
+ {
+ managedType = null;
+ return;
+ }
+
+ if (pNativeType->typeKind == TypeKind.Projection)
+ {
+ managedType = Type.GetType(typeName, /* throwOnError = */ true);
+ }
+ else
+ {
+ bool isPrimitive;
+ managedType = WinRTTypeNameConverter.GetTypeFromWinRTTypeName(typeName, out isPrimitive);
+
+ // TypeSource must match
+ if (isPrimitive != (pNativeType->typeKind == TypeKind.Primitive))
+ throw new ArgumentException(Environment.GetResourceString("Argument_Unexpected_TypeSource"));
+ }
+ }
+
+ [SecurityCritical]
+ internal static unsafe void ClearNative(TypeNameNative *pNativeType)
+ {
+ Contract.Assert(Environment.IsWinRTSupported);
+
+ if (pNativeType->typeName != IntPtr.Zero)
+ {
+ System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(pNativeType->typeName);
+ }
+ }
+ } // class SystemTypeMarshaler
+
+ // For converting WinRT's Windows.Foundation.HResult into System.Exception and vice versa.
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class HResultExceptionMarshaler
+ {
+ static internal unsafe int ConvertToNative(Exception ex)
+ {
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ if (ex == null)
+ return 0; // S_OK;
+
+ return ex._HResult;
+ }
+
+ [SecuritySafeCritical]
+ static internal unsafe Exception ConvertToManaged(int hr)
+ {
+ Contract.Ensures(Contract.Result<Exception>() != null || hr >= 0);
+
+ if (!Environment.IsWinRTSupported)
+ {
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
+ }
+
+ Exception e = null;
+ if (hr < 0)
+ {
+ e = StubHelpers.InternalGetCOMHRExceptionObject(hr, IntPtr.Zero, null, /* fForWinRT */ true);
+ }
+
+ // S_OK should be marshaled as null. WinRT API's should not return S_FALSE by convention.
+ // We've chosen to treat S_FALSE as success and return null.
+ Contract.Assert(e != null || hr == 0 || hr == 1, "Unexpected HRESULT - it is a success HRESULT (without the high bit set) other than S_OK & S_FALSE.");
+ return e;
+ }
+ } // class HResultExceptionMarshaler
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal static class KeyValuePairMarshaler
+ {
+ [SecurityCritical]
+ internal static IntPtr ConvertToNative<K, V>([In] ref KeyValuePair<K, V> pair)
+ {
+ IKeyValuePair<K, V> impl = new CLRIKeyValuePairImpl<K, V>(ref pair);
+ return Marshal.GetComInterfaceForObject(impl, typeof(IKeyValuePair<K, V>));
+ }
+
+ [SecurityCritical]
+ internal static KeyValuePair<K, V> ConvertToManaged<K, V>(IntPtr pInsp)
+ {
+ object obj = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pInsp);
+
+ IKeyValuePair<K, V> pair = (IKeyValuePair<K, V>)obj;
+ return new KeyValuePair<K, V>(pair.Key, pair.Value);
+ }
+
+ // Called from COMInterfaceMarshaler
+ [SecurityCritical]
+ internal static object ConvertToManagedBox<K, V>(IntPtr pInsp)
+ {
+ return (object)ConvertToManaged<K, V>(pInsp);
+ }
+ } // class KeyValuePairMarshaler
+
+#endif // FEATURE_COMINTEROP
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct NativeVariant
+ {
+ ushort vt;
+ ushort wReserved1;
+ ushort wReserved2;
+ ushort wReserved3;
+
+ // The union portion of the structure contains at least one 64-bit type that on some 32-bit platforms
+ // (notably ARM) requires 64-bit alignment. So on 32-bit platforms we'll actually size the variant
+ // portion of the struct with an Int64 so the type loader notices this requirement (a no-op on x86,
+ // but on ARM it will allow us to correctly determine the layout of native argument lists containing
+ // VARIANTs). Note that the field names here don't matter: none of the code refers to these fields,
+ // the structure just exists to provide size information to the IL marshaler.
+#if BIT64
+ IntPtr data1;
+ IntPtr data2;
+#else
+ Int64 data1;
+#endif
+ } // struct NativeVariant
+
+#if !BIT64 && !FEATURE_CORECLR
+ // Structure filled by IL stubs if copy constructor(s) and destructor(s) need to be called
+ // on value types pushed on the stack. The structure is stored in s_copyCtorStubDesc by
+ // SetCopyCtorCookieChain and fetched by CopyCtorCallStubWorker. Must be stack-allocated.
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe internal struct CopyCtorStubCookie
+ {
+ public void SetData(IntPtr srcInstancePtr, uint dstStackOffset, IntPtr ctorPtr, IntPtr dtorPtr)
+ {
+ m_srcInstancePtr = srcInstancePtr;
+ m_dstStackOffset = dstStackOffset;
+ m_ctorPtr = ctorPtr;
+ m_dtorPtr = dtorPtr;
+ }
+
+ public void SetNext(IntPtr pNext)
+ {
+ m_pNext = pNext;
+ }
+
+ public IntPtr m_srcInstancePtr; // pointer to the source instance
+ public uint m_dstStackOffset; // offset from the start of stack arguments of the pushed 'this' instance
+
+ public IntPtr m_ctorPtr; // fnptr to the managed copy constructor, result of ldftn
+ public IntPtr m_dtorPtr; // fnptr to the managed destructor, result of ldftn
+
+ public IntPtr m_pNext; // pointer to next cookie in the chain or IntPtr.Zero
+ } // struct CopyCtorStubCookie
+
+ // Aggregates pointer to CopyCtorStubCookie and the target of the interop call.
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe internal struct CopyCtorStubDesc
+ {
+ public IntPtr m_pCookie;
+ public IntPtr m_pTarget;
+ } // struct CopyCtorStubDes
+#endif // !BIT64 && !FEATURE_CORECLR
+
+ // Aggregates SafeHandle and the "owned" bit which indicates whether the SafeHandle
+ // has been successfully AddRef'ed. This allows us to do realiable cleanup (Release)
+ // if and only if it is needed.
+ [System.Security.SecurityCritical]
+ internal sealed class CleanupWorkListElement
+ {
+ public CleanupWorkListElement(SafeHandle handle)
+ {
+ m_handle = handle;
+ }
+
+ public SafeHandle m_handle;
+
+ // This field is passed by-ref to SafeHandle.DangerousAddRef.
+ // CleanupWorkList.Destroy ignores this element if m_owned is not set to true.
+ public bool m_owned;
+ } // class CleanupWorkListElement
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [System.Security.SecurityCritical]
+ internal sealed class CleanupWorkList
+ {
+ private List<CleanupWorkListElement> m_list = new List<CleanupWorkListElement>();
+
+ public void Add(CleanupWorkListElement elem)
+ {
+ BCLDebug.Assert(elem.m_owned == false, "m_owned is supposed to be false and set later by DangerousAddRef");
+ m_list.Add(elem);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Destroy()
+ {
+ for (int i = m_list.Count - 1; i >= 0; i--)
+ {
+ if (m_list[i].m_owned)
+ StubHelpers.SafeHandleRelease(m_list[i].m_handle);
+ }
+ }
+ } // class CleanupWorkList
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ [SuppressUnmanagedCodeSecurityAttribute()]
+ internal static class StubHelpers
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern bool IsQCall(IntPtr pMD);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void InitDeclaringType(IntPtr pMD);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetNDirectTarget(IntPtr pMD);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetDelegateTarget(Delegate pThis, ref IntPtr pStubArg);
+
+#if !BIT64 && !FEATURE_CORECLR
+ // Written to by a managed stub helper, read by CopyCtorCallStubWorker in VM.
+ [ThreadStatic]
+ static CopyCtorStubDesc s_copyCtorStubDesc;
+
+ static internal void SetCopyCtorCookieChain(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags, IntPtr pCookie)
+ {
+ // we store both the cookie chain head and the target of the copy ctor stub to a thread
+ // static field to be accessed by the copy ctor (see code:CopyCtorCallStubWorker)
+ s_copyCtorStubDesc.m_pCookie = pCookie;
+ s_copyCtorStubDesc.m_pTarget = GetFinalStubTarget(pStubArg, pUnmngThis, dwStubFlags);
+ }
+
+ // Returns the final unmanaged stub target, ignores interceptors.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetFinalStubTarget(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags);
+#endif // !FEATURE_CORECLR && !BIT64
+
+#if !FEATURE_CORECLR
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void DemandPermission(IntPtr pNMD);
+#endif // !FEATURE_CORECLR
+
+#if FEATURE_CORECLR
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ClearLastError();
+#endif
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void SetLastError();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ThrowInteropParamException(int resID, int paramIdx);
+
+ [System.Security.SecurityCritical]
+ static internal IntPtr AddToCleanupList(ref CleanupWorkList pCleanupWorkList, SafeHandle handle)
+ {
+ if (pCleanupWorkList == null)
+ pCleanupWorkList = new CleanupWorkList();
+
+ CleanupWorkListElement element = new CleanupWorkListElement(handle);
+ pCleanupWorkList.Add(element);
+
+ // element.m_owned will be true iff the AddRef succeeded
+ return SafeHandleAddRef(handle, ref element.m_owned);
+ }
+
+ [System.Security.SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ static internal void DestroyCleanupList(ref CleanupWorkList pCleanupWorkList)
+ {
+ if (pCleanupWorkList != null)
+ {
+ pCleanupWorkList.Destroy();
+ pCleanupWorkList = null;
+ }
+ }
+
+ static internal Exception GetHRExceptionObject(int hr)
+ {
+ Exception ex = InternalGetHRExceptionObject(hr);
+ ex.InternalPreserveStackTrace();
+ return ex;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern Exception InternalGetHRExceptionObject(int hr);
+
+#if FEATURE_COMINTEROP
+ static internal Exception GetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis)
+ {
+ Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, false);
+ ex.InternalPreserveStackTrace();
+ return ex;
+ }
+
+ static internal Exception GetCOMHRExceptionObject_WinRT(int hr, IntPtr pCPCMD, object pThis)
+ {
+ Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, true);
+ ex.InternalPreserveStackTrace();
+ return ex;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern Exception InternalGetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis, bool fForWinRT);
+
+#endif // FEATURE_COMINTEROP
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType);
+
+ //-------------------------------------------------------
+ // SafeHandle Helpers
+ //-------------------------------------------------------
+
+ // AddRefs the SH and returns the underlying unmanaged handle.
+ [System.Security.SecurityCritical] // auto-generated
+ static internal IntPtr SafeHandleAddRef(SafeHandle pHandle, ref bool success)
+ {
+ if (pHandle == null)
+ {
+ throw new ArgumentNullException("pHandle", Environment.GetResourceString("ArgumentNull_SafeHandle"));
+ }
+ Contract.EndContractBlock();
+
+ pHandle.DangerousAddRef(ref success);
+
+ return (success ? pHandle.DangerousGetHandle() : IntPtr.Zero);
+ }
+
+ // Releases the SH (to be called from finally block).
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ static internal void SafeHandleRelease(SafeHandle pHandle)
+ {
+ if (pHandle == null)
+ {
+ throw new ArgumentNullException("pHandle", Environment.GetResourceString("ArgumentNull_SafeHandle"));
+ }
+ Contract.EndContractBlock();
+
+ try
+ {
+ pHandle.DangerousRelease();
+ }
+#if MDA_SUPPORTED
+ catch (Exception ex)
+ {
+ Mda.ReportErrorSafeHandleRelease(ex);
+ }
+#else // MDA_SUPPORTED
+ catch (Exception)
+ { }
+#endif // MDA_SUPPORTED
+ }
+
+#if FEATURE_COMINTEROP
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetCOMIPFromRCW(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget, out bool pfNeedsRelease);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetCOMIPFromRCW_WinRT(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetCOMIPFromRCW_WinRTSharedGeneric(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetCOMIPFromRCW_WinRTDelegate(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern bool ShouldCallWinRTInterface(object objSrc, IntPtr pCPCMD);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern Delegate GetTargetForAmbiguousVariantCall(object objSrc, IntPtr pMT, out bool fUseString);
+
+ //-------------------------------------------------------
+ // Helper for the MDA RaceOnRCWCleanup
+ //-------------------------------------------------------
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void StubRegisterRCW(object pThis);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void StubUnregisterRCW(object pThis);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetDelegateInvokeMethod(Delegate pThis);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecurityCritical]
+ static internal extern object GetWinRTFactoryObject(IntPtr pCPCMD);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecurityCritical]
+ static internal extern IntPtr GetWinRTFactoryReturnValue(object pThis, IntPtr pCtorEntry);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecurityCritical]
+ static internal extern IntPtr GetOuterInspectable(object pThis, IntPtr pCtorMD);
+
+#if MDA_SUPPORTED
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern Exception TriggerExceptionSwallowedMDA(Exception ex, IntPtr pManagedTarget);
+#endif // MDA_SUPPORTED
+
+#endif // FEATURE_COMINTEROP
+
+#if MDA_SUPPORTED
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void CheckCollectedDelegateMDA(IntPtr pEntryThunk);
+#endif // MDA_SUPPORTED
+
+ //-------------------------------------------------------
+ // Profiler helpers
+ //-------------------------------------------------------
+#if PROFILING_SUPPORTED
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr ProfilerBeginTransitionCallback(IntPtr pSecretParam, IntPtr pThread, object pThis);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ProfilerEndTransitionCallback(IntPtr pMD, IntPtr pThread);
+#endif // PROFILING_SUPPORTED
+
+ //------------------------------------------------------
+ // misc
+ //------------------------------------------------------
+ static internal void CheckStringLength(int length)
+ {
+ CheckStringLength((uint)length);
+ }
+
+ static internal void CheckStringLength(uint length)
+ {
+ if (length > 0x7ffffff0)
+ {
+ throw new MarshalDirectiveException(Environment.GetResourceString("Marshaler_StringTooLong"));
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal unsafe extern int strlen(sbyte* ptr);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void DecimalCanonicalizeInternal(ref Decimal dec);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal unsafe extern void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkList pCleanupWorkList);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal unsafe extern void FmtClassUpdateCLRInternal(object obj, byte* pNative);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal unsafe extern void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern object AllocateInternal(IntPtr typeHandle);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void MarshalToUnmanagedVaListInternal(IntPtr va_list, uint vaListSize, IntPtr pArgIterator);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void MarshalToManagedVaListInternal(IntPtr va_list, IntPtr pArgIterator);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern uint CalcVaListSize(IntPtr va_list);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ValidateObject(object obj, IntPtr pMD, object pThis);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void LogPinnedArgument(IntPtr localDesc, IntPtr nativeArg);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void ValidateByref(IntPtr byref, IntPtr pMD, object pThis); // the byref is pinned so we can safely "cast" it to IntPtr
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetStubContext();
+
+#if BIT64
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern IntPtr GetStubContextAddr();
+#endif // BIT64
+
+#if MDA_SUPPORTED
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static internal extern void TriggerGCForMDA();
+#endif // MDA_SUPPORTED
+
+#if FEATURE_ARRAYSTUB_AS_IL
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ArrayTypeCheck(object o, Object[] arr);
+#endif
+
+#if FEATURE_STUBS_AS_IL
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void MulticastDebuggerTraceHelper(object o, Int32 count);
+#endif
+ } // class StubHelpers
+}
diff --git a/src/mscorlib/src/System/SystemException.cs b/src/mscorlib/src/System/SystemException.cs
new file mode 100644
index 0000000000..8a54124e3e
--- /dev/null
+++ b/src/mscorlib/src/System/SystemException.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class SystemException : Exception
+ {
+ public SystemException()
+ : base(Environment.GetResourceString("Arg_SystemException")) {
+ SetErrorCode(__HResults.COR_E_SYSTEM);
+ }
+
+ public SystemException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_SYSTEM);
+ }
+
+ public SystemException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_SYSTEM);
+ }
+
+ protected SystemException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/ASCIIEncoding.cs b/src/mscorlib/src/System/Text/ASCIIEncoding.cs
new file mode 100644
index 0000000000..bf1a62df55
--- /dev/null
+++ b/src/mscorlib/src/System/Text/ASCIIEncoding.cs
@@ -0,0 +1,773 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // ASCIIEncoding
+ //
+ // Note that ASCIIEncoding is optomized with no best fit and ? for fallback.
+ // It doesn't come in other flavors.
+ //
+ // Note: ASCIIEncoding is the only encoding that doesn't do best fit (windows has best fit).
+ //
+ // Note: IsAlwaysNormalized remains false because 1/2 the code points are unassigned, so they'd
+ // use fallbacks, and we cannot guarantee that fallbacks are normalized.
+ //
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class ASCIIEncoding : Encoding
+ {
+ // Used by Encoding.ASCII for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly ASCIIEncoding s_default = new ASCIIEncoding();
+
+ public ASCIIEncoding() : base(Encoding.CodePageASCII)
+ {
+ }
+
+ internal override void SetDefaultFallbacks()
+ {
+ // For ASCIIEncoding we just use default replacement fallback
+ this.encoderFallback = EncoderFallback.ReplacementFallback;
+ this.decoderFallback = DecoderFallback.ReplacementFallback;
+ }
+
+ // WARNING: GetByteCount(string chars), GetBytes(string chars,...), and GetString(byte[] byteIndex...)
+ // WARNING: have different variable names than EncodingNLS.cs, so this can't just be cut & pasted,
+ // WARNING: or it'll break VB's way of calling these.
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ public override int GetByteCount(String chars)
+ {
+ return EncodingForwarder.GetByteCount(this, chars);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ public override int GetBytes(String chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ public override String GetString(byte[] bytes, int byteIndex, int byteCount)
+ {
+ return EncodingForwarder.GetString(this, bytes, byteIndex, byteCount);
+ }
+
+ // End of overridden methods which use EncodingForwarder
+
+ // GetByteCount
+ // Note: We start by assuming that the output will be the same as count. Having
+ // an encoder or fallback may change that assumption
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
+ Contract.Assert(chars != null, "[ASCIIEncoding.GetByteCount]chars is null");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetByteCount]Attempting to use null fallback encoder");
+
+ char charLeftOver = (char)0;
+ EncoderReplacementFallback fallback = null;
+
+ // Start by assuming default count, then +/- for fallback characters
+ char* charEnd = chars + charCount;
+
+ // For fallback we may need a fallback buffer, we know we aren't default fallback.
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
+
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
+ }
+
+ // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[ASCIICodePageEncoding.GetByteCount]Expected empty fallback buffer");
+// if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0)
+// throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+// this.EncodingName, encoder.Fallback.GetType()));
+ }
+ else
+ {
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+ }
+
+ // If we have an encoder AND we aren't using default fallback,
+ // then we may have a complicated count.
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always
+ // same as input size.
+ // Note that no existing SBCS code pages map code points to supplimentary characters, so this is easy.
+
+ // We could however have 1 extra byte if the last call had an encoder and a funky fallback and
+ // if we don't use the funky fallback this time.
+
+ // Do we have an extra char left over from last time?
+ if (charLeftOver > 0)
+ charCount++;
+
+ return (charCount);
+ }
+
+ // Count is more complicated if you have a funky fallback
+ // For fallback we may need a fallback buffer, we know we're not default fallback
+ int byteCount = 0;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
+ Contract.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
+
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+
+ // Now we may have fallback char[] already from the encoder
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ // no chars >= 0x80 are allowed.
+ if (ch > 0x7f)
+ {
+ if (fallbackBuffer == null)
+ {
+ // Initialize the buffer
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // We'll use this one
+ byteCount++;
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[ASCIIEncoding.GetByteCount]Expected Empty fallback buffer");
+
+ return byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
+ Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetBytes]byteCount is negative");
+ Contract.Assert(chars != null, "[ASCIIEncoding.GetBytes]chars is null");
+ Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[ASCIIEncoding.GetBytes]Attempting to use null encoder fallback");
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ EncoderReplacementFallback fallback = null;
+
+ // For fallback we may need a fallback buffer, we know we aren't default fallback.
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // prepare our end
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+ }
+
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
+
+ // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[ASCIICodePageEncoding.GetBytes]Expected empty fallback buffer");
+// if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
+// encoder.FallbackBuffer.Remaining > 0)
+// throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+// this.EncodingName, encoder.Fallback.GetType()));
+ }
+ else
+ {
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+ }
+
+
+ // See if we do the fast default or slightly slower fallback
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Fast version
+ char cReplacement = fallback.DefaultString[0];
+
+ // Check for replacements in range, otherwise fall back to slow version.
+ if (cReplacement <= (char)0x7f)
+ {
+ // We should have exactly as many output bytes as input bytes, unless there's a left
+ // over character, in which case we may need one more.
+ // If we had a left over character will have to add a ? (This happens if they had a funky
+ // fallback last time, but not this time.) (We can't spit any out though
+ // because with fallback encoder each surrogate is treated as a seperate code point)
+ if (charLeftOver > 0)
+ {
+ // Have to have room
+ // Throw even if doing no throw version because this is just 1 char,
+ // so buffer will never be big enough
+ if (byteCount == 0)
+ ThrowBytesOverflow(encoder, true);
+
+ // This'll make sure we still have more room and also make sure our return value is correct.
+ *(bytes++) = (byte)cReplacement;
+ byteCount--; // We used one of the ones we were counting.
+ }
+
+ // This keeps us from overrunning our output buffer
+ if (byteCount < charCount)
+ {
+ // Throw or make buffer smaller?
+ ThrowBytesOverflow(encoder, byteCount < 1);
+
+ // Just use what we can
+ charEnd = chars + byteCount;
+ }
+
+ // We just do a quick copy
+ while (chars < charEnd)
+ {
+ char ch2 = *(chars++);
+ if (ch2 >= 0x0080) *(bytes++) = (byte)cReplacement;
+ else *(bytes++) = unchecked((byte)(ch2));
+ }
+
+ // Clear encoder
+ if (encoder != null)
+ {
+ encoder.charLeftOver = (char)0;
+ encoder.m_charsUsed = (int)(chars-charStart);
+ }
+
+ return (int)(bytes - byteStart);
+ }
+ }
+
+ // Slower version, have to do real fallback.
+
+ // prepare our end
+ byte* byteEnd = bytes + byteCount;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ // Initialize the buffer
+ Contract.Assert(encoder != null,
+ "[ASCIIEncoding.GetBytes]Expected non null encoder if we have surrogate left over");
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+
+ // Now we may have fallback char[] already from the encoder
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ // All characters >= 0x80 must fall back.
+ if (ch > 0x7f)
+ {
+ // Initialize the buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+
+ // Go ahead & continue (& do the fallback)
+ continue;
+ }
+
+ // We'll use this one
+ // Bounds check
+ if (bytes >= byteEnd)
+ {
+ // didn't use this char, we'll throw or use buffer
+ if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
+ {
+ Contract.Assert(chars > charStart || bytes == byteStart,
+ "[ASCIIEncoding.GetBytes]Expected chars to have advanced already.");
+ chars--; // don't use last char
+ }
+ else
+ fallbackBuffer.MovePrevious();
+
+ // Are we throwing or using buffer?
+ ThrowBytesOverflow(encoder, bytes == byteStart); // throw?
+ break; // don't throw, stop
+ }
+
+ // Go ahead and add it
+ *bytes = unchecked((byte)ch);
+ bytes++;
+ }
+
+ // Need to do encoder stuff
+ if (encoder != null)
+ {
+ // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
+ if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
+ // Clear it in case of MustFlush
+ encoder.charLeftOver = (char)0;
+
+ // Set our chars used count
+ encoder.m_charsUsed = (int)(chars - charStart);
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
+ (encoder != null && !encoder.m_throwOnOverflow ),
+ "[ASCIIEncoding.GetBytes]Expected Empty fallback buffer at end");
+
+ return (int)(bytes - byteStart);
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ {
+ // Just assert, we're called internally so these should be safe, checked already
+ Contract.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null");
+ Contract.Assert(count >= 0, "[ASCIIEncoding.GetCharCount]byteCount is negative");
+
+ // ASCII doesn't do best fit, so don't have to check for it, find out which decoder fallback we're using
+ DecoderReplacementFallback fallback = null;
+
+ if (decoder == null)
+ fallback = this.DecoderFallback as DecoderReplacementFallback;
+ else
+ {
+ fallback = decoder.Fallback as DecoderReplacementFallback;
+ Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
+ decoder.FallbackBuffer.Remaining == 0,
+ "[ASCIICodePageEncoding.GetCharCount]Expected empty fallback buffer");
+ }
+
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ // pairs and we don't have a decoder fallback.
+
+ return count;
+ }
+
+ // Only need decoder fallback buffer if not using default replacement fallback, no best fit for ASCII
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // Have to do it the hard way.
+ // Assume charCount will be == count
+ int charCount = count;
+ byte[] byteBuffer = new byte[1];
+
+ // Do it our fast way
+ byte* byteEnd = bytes + count;
+
+ // Quick loop
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ byte b = *bytes;
+ bytes++;
+
+ // If unknown we have to do fallback count
+ if (b >= 0x80)
+ {
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - count, null);
+ }
+
+ // Use fallback buffer
+ byteBuffer[0] = b;
+ charCount--; // Have to unreserve the one we already allocated for b
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+ }
+
+ // Fallback buffer must be empty
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[ASCIIEncoding.GetCharCount]Expected Empty fallback buffer");
+
+ // Converted sequence is same length as input
+ return charCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS decoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[ASCIIEncoding.GetChars]byteCount is negative");
+ Contract.Assert(chars != null, "[ASCIIEncoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[ASCIIEncoding.GetChars]charCount is negative");
+
+ // Do it fast way if using ? replacement fallback
+ byte* byteEnd = bytes + byteCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ // Note: ASCII doesn't do best fit, but we have to fallback if they use something > 0x7f
+ // Only need decoder fallback buffer if not using ? fallback.
+ // ASCII doesn't do best fit, so don't have to check for it, find out which decoder fallback we're using
+ DecoderReplacementFallback fallback = null;
+
+ if (decoder == null)
+ fallback = this.DecoderFallback as DecoderReplacementFallback;
+ else
+ {
+ fallback = decoder.Fallback as DecoderReplacementFallback;
+ Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
+ decoder.FallbackBuffer.Remaining == 0,
+ "[ASCIICodePageEncoding.GetChars]Expected empty fallback buffer");
+ }
+
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Try it the fast way
+ char replacementChar = fallback.DefaultString[0];
+
+ // Need byteCount chars, otherwise too small buffer
+ if (charCount < byteCount)
+ {
+ // Need at least 1 output byte, throw if must throw
+ ThrowCharsOverflow(decoder, charCount < 1);
+
+ // Not throwing, use what we can
+ byteEnd = bytes + charCount;
+ }
+
+ // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
+ while (bytes < byteEnd)
+ {
+ byte b = *(bytes++);
+ if (b >= 0x80)
+ // This is an invalid byte in the ASCII encoding.
+ *(chars++) = replacementChar;
+ else
+ *(chars++) = unchecked((char)b);
+ }
+
+ // bytes & chars used are the same
+ if (decoder != null)
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+ return (int)(chars - charStart);
+ }
+
+ // Slower way's going to need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+ byte[] byteBuffer = new byte[1];
+ char* charEnd = chars + charCount;
+
+ // Not quite so fast loop
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ byte b = *(bytes);
+ bytes++;
+
+ if (b >= 0x80)
+ {
+ // This is an invalid byte in the ASCII encoding.
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
+ }
+
+ // Use fallback buffer
+ byteBuffer[0] = b;
+
+ // Note that chars won't get updated unless this succeeds
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // May or may not throw, but we didn't get this byte
+ Contract.Assert(bytes > byteStart || chars == charStart,
+ "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (fallback case)");
+ bytes--; // unused byte
+ fallbackBuffer.InternalReset(); // Didn't fall this back
+ ThrowCharsOverflow(decoder, chars == charStart); // throw?
+ break; // don't throw, but stop loop
+ }
+ }
+ else
+ {
+ // Make sure we have buffer space
+ if (chars >= charEnd)
+ {
+ Contract.Assert(bytes > byteStart || chars == charStart,
+ "[ASCIIEncoding.GetChars]Expected bytes to have advanced already (normal case)");
+ bytes--; // unused byte
+ ThrowCharsOverflow(decoder, chars == charStart); // throw?
+ break; // don't throw, but stop loop
+ }
+
+ *(chars) = unchecked((char)b);
+ chars++;
+ }
+ }
+
+ // Might have had decoder fallback stuff.
+ if (decoder != null)
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+
+ // Expect Empty fallback buffer for GetChars
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[ASCIIEncoding.GetChars]Expected Empty fallback buffer");
+
+ return (int)(chars - charStart);
+ }
+
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less.
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+ return (int)byteCount;
+ }
+
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ long charCount = (long)byteCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less, unknown fallbacks could be longer.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool IsSingleByte
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override Decoder GetDecoder()
+ {
+ return new DecoderNLS(this);
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override Encoder GetEncoder()
+ {
+ return new EncoderNLS(this);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs b/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs
new file mode 100644
index 0000000000..4c9ca6eaaf
--- /dev/null
+++ b/src/mscorlib/src/System/Text/BaseCodePageEncoding.cs
@@ -0,0 +1,350 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if FEATURE_CODEPAGES_FILE
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using Microsoft.Win32.SafeHandles;
+
+ // Our input file data structures look like:
+ //
+ // Header Structure Looks Like:
+ // struct NLSPlusHeader
+ // {
+ // WORD[16] filename; // 32 bytes
+ // WORD[4] version; // 8 bytes = 40 // I.e: 3, 2, 0, 0
+ // WORD count; // 2 bytes = 42 // Number of code page index's that'll follow
+ // }
+ //
+ // Each code page section looks like:
+ // struct NLSCodePageIndex
+ // {
+ // WORD[16] codePageName; // 32 bytes
+ // WORD codePage; // +2 bytes = 34
+ // WORD byteCount; // +2 bytes = 36
+ // DWORD offset; // +4 bytes = 40 // Bytes from beginning of FILE.
+ // }
+ //
+ // Each code page then has its own header
+ // struct NLSCodePage
+ // {
+ // WORD[16] codePageName; // 32 bytes
+ // WORD[4] version; // 8 bytes = 40 // I.e: 3.2.0.0
+ // WORD codePage; // 2 bytes = 42
+ // WORD byteCount; // 2 bytes = 44 // 1 or 2 byte code page (SBCS or DBCS)
+ // WORD unicodeReplace; // 2 bytes = 46 // default replacement unicode character
+ // WORD byteReplace; // 2 bytes = 48 // default replacement byte(s)
+ // BYTE[] data; // data section
+ // }
+
+ [Serializable]
+ internal abstract class BaseCodePageEncoding : EncodingNLS, ISerializable
+ {
+ // Static & Const stuff
+ internal const String CODE_PAGE_DATA_FILE_NAME = "codepages.nlp";
+ [NonSerialized]
+ protected int dataTableCodePage;
+
+ // Variables to help us allocate/mark our memory section correctly
+ [NonSerialized]
+ protected bool bFlagDataTable = true;
+ [NonSerialized]
+ protected int iExtraBytes = 0;
+
+ // Our private unicode to bytes best fit array and visa versa.
+ [NonSerialized]
+ protected char[] arrayUnicodeBestFit = null;
+ [NonSerialized]
+ protected char[] arrayBytesBestFit = null;
+
+ // This is used to help ISCII, EUCJP and ISO2022 figure out they're MlangEncodings
+ [NonSerialized]
+ protected bool m_bUseMlangTypeForSerialization = false;
+
+ [System.Security.SecuritySafeCritical] // static constructors should be safe to call
+ static BaseCodePageEncoding()
+ {
+ }
+
+ //
+ // This is the header for the native data table that we load from CODE_PAGE_DATA_FILE_NAME.
+ //
+ // Explicit layout is used here since a syntax like char[16] can not be used in sequential layout.
+ [StructLayout(LayoutKind.Explicit)]
+ internal unsafe struct CodePageDataFileHeader
+ {
+ [FieldOffset(0)]
+ internal char TableName; // WORD[16]
+ [FieldOffset(0x20)]
+ internal ushort Version; // WORD[4]
+ [FieldOffset(0x28)]
+ internal short CodePageCount; // WORD
+ [FieldOffset(0x2A)]
+ internal short unused1; // Add a unused WORD so that CodePages is aligned with DWORD boundary.
+ // Otherwise, 64-bit version will fail.
+ [FieldOffset(0x2C)]
+ internal CodePageIndex CodePages; // Start of code page index
+ }
+
+ [StructLayout(LayoutKind.Explicit, Pack=2)]
+ internal unsafe struct CodePageIndex
+ {
+ [FieldOffset(0)]
+ internal char CodePageName; // WORD[16]
+ [FieldOffset(0x20)]
+ internal short CodePage; // WORD
+ [FieldOffset(0x22)]
+ internal short ByteCount; // WORD
+ [FieldOffset(0x24)]
+ internal int Offset; // DWORD
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ internal unsafe struct CodePageHeader
+ {
+ [FieldOffset(0)]
+ internal char CodePageName; // WORD[16]
+ [FieldOffset(0x20)]
+ internal ushort VersionMajor; // WORD
+ [FieldOffset(0x22)]
+ internal ushort VersionMinor; // WORD
+ [FieldOffset(0x24)]
+ internal ushort VersionRevision;// WORD
+ [FieldOffset(0x26)]
+ internal ushort VersionBuild; // WORD
+ [FieldOffset(0x28)]
+ internal short CodePage; // WORD
+ [FieldOffset(0x2a)]
+ internal short ByteCount; // WORD // 1 or 2 byte code page (SBCS or DBCS)
+ [FieldOffset(0x2c)]
+ internal char UnicodeReplace; // WORD // default replacement unicode character
+ [FieldOffset(0x2e)]
+ internal ushort ByteReplace; // WORD // default replacement bytes
+ [FieldOffset(0x30)]
+ internal short FirstDataWord; // WORD[]
+ }
+
+ // Initialize our global stuff
+ [SecurityCritical]
+ unsafe static CodePageDataFileHeader* m_pCodePageFileHeader =
+ (CodePageDataFileHeader*)GlobalizationAssembly.GetGlobalizationResourceBytePtr(
+ typeof(CharUnicodeInfo).Assembly, CODE_PAGE_DATA_FILE_NAME);
+
+ // Real variables
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe protected CodePageHeader* pCodePage = null;
+
+ // Safe handle wrapper around section map view
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ protected SafeViewOfFileHandle safeMemorySectionHandle = null;
+
+ // Safe handle wrapper around mapped file handle
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ protected SafeFileMappingHandle safeFileMappingHandle = null;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal BaseCodePageEncoding(int codepage) : this(codepage, codepage)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal BaseCodePageEncoding(int codepage, int dataCodePage) :
+ base(codepage == 0? Microsoft.Win32.Win32Native.GetACP(): codepage)
+ {
+ // Remember number of code page that we'll be using the table for.
+ dataTableCodePage = dataCodePage;
+ LoadCodePageTables();
+ }
+
+ // Constructor called by serialization.
+ [System.Security.SecurityCritical] // auto-generated
+ internal BaseCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0)
+ {
+ // We cannot ever call this, we've proxied ourselved to CodePageEncoding
+ throw new ArgumentNullException("this");
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Make sure to get the base stuff too This throws if info is null
+ SerializeEncoding(info, context);
+ Contract.Assert(info!=null, "[BaseCodePageEncoding.GetObjectData] Expected null info to throw");
+
+ // Just need Everett maxCharSize (BaseCodePageEncoding) or m_maxByteSize (MLangBaseCodePageEncoding)
+ info.AddValue(m_bUseMlangTypeForSerialization ? "m_maxByteSize" : "maxCharSize",
+ this.IsSingleByte ? 1 : 2);
+
+ // Use this class or MLangBaseCodePageEncoding as our deserializer.
+ info.SetType(m_bUseMlangTypeForSerialization ? typeof(MLangCodePageEncoding) :
+ typeof(CodePageEncoding));
+ }
+
+ // We need to load tables for our code page
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe void LoadCodePageTables()
+ {
+ CodePageHeader* pCodePage = FindCodePage(dataTableCodePage);
+
+ // Make sure we have one
+ if (pCodePage == null)
+ {
+ // Didn't have one
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", CodePage));
+ }
+
+ // Remember our code page
+ this.pCodePage = pCodePage;
+
+ // We had it, so load it
+ LoadManagedCodePage();
+ }
+
+ // Look up the code page pointer
+ [System.Security.SecurityCritical] // auto-generated
+ private static unsafe CodePageHeader* FindCodePage(int codePage)
+ {
+ // We'll have to loop through all of the m_pCodePageIndex[] items to find our code page, this isn't
+ // binary or anything so its not monsterously fast.
+ for (int i = 0; i < m_pCodePageFileHeader->CodePageCount; i++)
+ {
+ CodePageIndex* pCodePageIndex = (&(m_pCodePageFileHeader->CodePages)) + i;
+
+ if (pCodePageIndex->CodePage == codePage)
+ {
+ // Found it!
+ CodePageHeader* pCodePage =
+ (CodePageHeader*)((byte*)m_pCodePageFileHeader + pCodePageIndex->Offset);
+ return pCodePage;
+ }
+ }
+
+ // Couldn't find it
+ return null;
+ }
+
+ // Get our code page byte count
+ [System.Security.SecurityCritical] // auto-generated
+ internal static unsafe int GetCodePageByteSize(int codePage)
+ {
+ // Get our code page info
+ CodePageHeader* pCodePage = FindCodePage(codePage);
+
+ // If null return 0
+ if (pCodePage == null)
+ return 0;
+
+ Contract.Assert(pCodePage->ByteCount == 1 || pCodePage->ByteCount == 2,
+ "[BaseCodePageEncoding] Code page (" + codePage + ") has invalid byte size (" + pCodePage->ByteCount + ") in table");
+ // Return what it says for byte count
+ return pCodePage->ByteCount;
+ }
+
+ // We have a managed code page entry, so load our tables
+ [System.Security.SecurityCritical]
+ protected abstract unsafe void LoadManagedCodePage();
+
+ // Allocate memory to load our code page
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe byte* GetSharedMemory(int iSize)
+ {
+ // Build our name
+ String strName = GetMemorySectionName();
+
+ IntPtr mappedFileHandle;
+
+ // This gets shared memory for our map. If its can't, it gives us clean memory.
+ Byte *pMemorySection = EncodingTable.nativeCreateOpenFileMapping(strName, iSize, out mappedFileHandle);
+ Contract.Assert(pMemorySection != null,
+ "[BaseCodePageEncoding.GetSharedMemory] Expected non-null memory section to be opened");
+
+ // If that failed, we have to die.
+ if (pMemorySection == null)
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+
+ // if we have null file handle. this means memory was allocated after
+ // failing to open the mapped file.
+
+ if (mappedFileHandle != IntPtr.Zero)
+ {
+ safeMemorySectionHandle = new SafeViewOfFileHandle((IntPtr) pMemorySection, true);
+ safeFileMappingHandle = new SafeFileMappingHandle(mappedFileHandle, true);
+ }
+
+ return pMemorySection;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe virtual String GetMemorySectionName()
+ {
+ int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage;
+
+ String strName = String.Format(CultureInfo.InvariantCulture, "NLS_CodePage_{0}_{1}_{2}_{3}_{4}",
+ iUseCodePage, this.pCodePage->VersionMajor, this.pCodePage->VersionMinor,
+ this.pCodePage->VersionRevision, this.pCodePage->VersionBuild);
+
+ return strName;
+ }
+
+ [System.Security.SecurityCritical]
+ protected abstract unsafe void ReadBestFitTable();
+
+ [System.Security.SecuritySafeCritical]
+ internal override char[] GetBestFitUnicodeToBytesData()
+ {
+ // Read in our best fit table if necessary
+ if (arrayUnicodeBestFit == null) ReadBestFitTable();
+
+ Contract.Assert(arrayUnicodeBestFit != null,
+ "[BaseCodePageEncoding.GetBestFitUnicodeToBytesData]Expected non-null arrayUnicodeBestFit");
+
+ // Normally we don't have any best fit data.
+ return arrayUnicodeBestFit;
+ }
+
+ [System.Security.SecuritySafeCritical]
+ internal override char[] GetBestFitBytesToUnicodeData()
+ {
+ // Read in our best fit table if necessary
+ if (arrayBytesBestFit == null) ReadBestFitTable();
+
+ Contract.Assert(arrayBytesBestFit != null,
+ "[BaseCodePageEncoding.GetBestFitBytesToUnicodeData]Expected non-null arrayBytesBestFit");
+
+ // Normally we don't have any best fit data.
+ return arrayBytesBestFit;
+ }
+
+ // During the AppDomain shutdown the Encoding class may already finalized and the memory section
+ // is invalid. so we detect that by validating the memory section handle then re-initialize the memory
+ // section by calling LoadManagedCodePage() method and eventually the mapped file handle and
+ // the memory section pointer will get finalized one more time.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void CheckMemorySection()
+ {
+ if (safeMemorySectionHandle != null && safeMemorySectionHandle.DangerousGetHandle() == IntPtr.Zero)
+ {
+ LoadManagedCodePage();
+ }
+ }
+ }
+}
+
+#endif // FEATURE_CODEPAGES_FILE
diff --git a/src/mscorlib/src/System/Text/CodePageEncoding.cs b/src/mscorlib/src/System/Text/CodePageEncoding.cs
new file mode 100644
index 0000000000..9f1b2d2620
--- /dev/null
+++ b/src/mscorlib/src/System/Text/CodePageEncoding.cs
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// WARNING:
+//
+// This is just an IObjectReference proxy for the Code Page Encodings.
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ /*=================================CodePageEncoding==================================
+ ** This class is here only to deserialize the Code Page classes from Everett (V1.1) into
+ ** Appropriate Whidbey (V2.0) objects. We also serialize the Whidbey classes
+ ** using this proxy since we pretty much need one anyway and that solves Whidbey
+ ** to Everett compatibility as well.
+ ==============================================================================*/
+
+ [Serializable]
+ internal sealed class CodePageEncoding : IObjectReference, ISerializable
+ {
+ // Temp stuff
+ [NonSerialized]
+ private int m_codePage;
+ [NonSerialized]
+ private bool m_isReadOnly;
+ [NonSerialized]
+ private bool m_deserializedFromEverett = false;
+
+ [NonSerialized]
+ private EncoderFallback encoderFallback = null;
+ [NonSerialized]
+ private DecoderFallback decoderFallback = null;
+
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization.
+ internal CodePageEncoding(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All versions have a code page
+ this.m_codePage = (int)info.GetValue("m_codePage", typeof(int));
+
+ // See if we have a code page
+ try
+ {
+ //
+ // Try Whidbey V2.0 Fields
+ //
+ this.m_isReadOnly = (bool)info.GetValue("m_isReadOnly", typeof(bool));
+
+ this.encoderFallback = (EncoderFallback)info.GetValue("encoderFallback", typeof(EncoderFallback));
+ this.decoderFallback = (DecoderFallback)info.GetValue("decoderFallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ //
+ // Didn't have Whidbey things, must be Everett
+ //
+ this.m_deserializedFromEverett = true;
+
+ // May as well be read only
+ this.m_isReadOnly = true;
+ }
+ }
+
+ // Just get it from GetEncoding
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ // Get our encoding (Note: This has default fallbacks for readonly and everett cases)
+ this.realEncoding = Encoding.GetEncoding(this.m_codePage);
+
+ // If its read only then it uses default fallbacks, otherwise pick up the new ones
+ // Otherwise we want to leave the new one read only
+ if (!this.m_deserializedFromEverett && !this.m_isReadOnly)
+ {
+ this.realEncoding = (Encoding)this.realEncoding.Clone();
+ this.realEncoding.EncoderFallback = this.encoderFallback;
+ this.realEncoding.DecoderFallback = this.decoderFallback;
+ }
+
+ return this.realEncoding;
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to CodePageEncoding ISerializable.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+
+ // Same problem with the Decoder, this only happens with Everett Decoders
+ [Serializable]
+ internal sealed class Decoder : IObjectReference, ISerializable
+ {
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal Decoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ this.realEncoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+ }
+
+ // Just get it from GetDecider
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ return this.realEncoding.GetDecoder();
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to CodePageEncoding.Decoder.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs b/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs
new file mode 100644
index 0000000000..c103d7898f
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DBCSCodePageEncoding.cs
@@ -0,0 +1,1206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if FEATURE_CODEPAGES_FILE // requires BaseCodePageEncooding
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using System.Threading;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+
+ // DBCSCodePageEncoding
+ //
+ [Serializable]
+ internal class DBCSCodePageEncoding : BaseCodePageEncoding, ISerializable
+ {
+ // Pointers to our memory section parts
+ [NonSerialized]
+ [SecurityCritical]
+ protected unsafe char* mapBytesToUnicode = null; // char 65536
+ [NonSerialized]
+ [SecurityCritical]
+ protected unsafe ushort* mapUnicodeToBytes = null; // byte 65536
+ [NonSerialized]
+ [SecurityCritical]
+ protected unsafe int* mapCodePageCached = null; // to remember which CP is cached
+
+ [NonSerialized]
+ protected const char UNKNOWN_CHAR_FLAG=(char)0x0;
+ [NonSerialized]
+ protected const char UNICODE_REPLACEMENT_CHAR=(char)0xFFFD;
+ [NonSerialized]
+ protected const char LEAD_BYTE_CHAR=(char)0xFFFE; // For lead bytes
+
+ // Note that even though we provide bytesUnknown and byteCountUnknown,
+ // They aren't actually used because of the fallback mechanism. (char is though)
+ [NonSerialized]
+ ushort bytesUnknown;
+ [NonSerialized]
+ int byteCountUnknown;
+ [NonSerialized]
+ protected char charUnknown = (char)0;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public DBCSCodePageEncoding(int codePage) : this(codePage, codePage)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal DBCSCodePageEncoding(int codePage, int dataCodePage) : base(codePage, dataCodePage)
+ {
+ }
+
+ // Constructor called by serialization.
+ // Note: We use the base GetObjectData however
+ [System.Security.SecurityCritical] // auto-generated
+ internal DBCSCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0)
+ {
+ // Actually this can't ever get called, CodePageEncoding is our proxy
+ Contract.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor");
+ throw new ArgumentNullException("this");
+ }
+
+ // MBCS data section:
+ //
+ // We treat each multibyte pattern as 2 bytes in our table. If its a single byte, then the high byte
+ // for that position will be 0. When the table is loaded, leading bytes are flagged with 0xFFFE, so
+ // when reading the table look up with each byte. If the result is 0xFFFE, then use 2 bytes to read
+ // further data. FFFF is a special value indicating that the unicode code is the same as the
+ // character code (this helps us support code points < 0x20). FFFD is used as replacement character.
+ //
+ // Normal table:
+ // WCHAR* - Starting with MB code point 0.
+ // FFFF indicates we are to use the multibyte value for our code point.
+ // FFFE is the lead byte mark. (This should only appear in positions < 0x100)
+ // FFFD is the replacement (unknown character) mark.
+ // 2-20 means to advance the pointer 2-0x20 characters.
+ // 1 means that to advance to the multibyte position contained in the next char.
+ // 0 nothing special (I don't think its possible.)
+ //
+ // Table ends when multibyte position has advanced to 0xFFFF.
+ //
+ // Bytes->Unicode Best Fit table:
+ // WCHAR* - Same as normal table, except first wchar is byte position to start at.
+ //
+ // Unicode->Bytes Best Fit Table:
+ // WCHAR* - Same as normal table, except first wchar is char position to start at and
+ // we loop through unicode code points and the table has the byte points that
+ // corrospond to those unicode code points.
+ // We have a managed code page entry, so load our tables
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ protected override unsafe void LoadManagedCodePage()
+ {
+ // Should be loading OUR code page
+ Contract.Assert(pCodePage->CodePage == this.dataTableCodePage,
+ "[DBCSCodePageEncoding.LoadManagedCodePage]Expected to load data table code page");
+
+ // Make sure we're really a 1 byte code page
+ if (pCodePage->ByteCount != 2)
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", CodePage));
+ // Remember our unknown bytes & chars
+ bytesUnknown = pCodePage->ByteReplace;
+ charUnknown = pCodePage->UnicodeReplace;
+
+ // Need to make sure the fallback buffer's fallback char is correct
+ if (this.DecoderFallback.IsMicrosoftBestFitFallback)
+ {
+ ((InternalDecoderBestFitFallback)(this.DecoderFallback)).cReplacement = charUnknown;
+ }
+
+ // Is our replacement bytesUnknown a single or double byte character?
+ byteCountUnknown = 1;
+ if (bytesUnknown > 0xff)
+ byteCountUnknown++;
+
+ // We use fallback encoder, which uses ?, which so far all of our tables do as well
+ Contract.Assert(bytesUnknown == 0x3f,
+ "[DBCSCodePageEncoding.LoadManagedCodePage]Expected 0x3f (?) as unknown byte character");
+
+ // Get our mapped section (bytes to allocate = 2 bytes per 65536 Unicode chars + 2 bytes per 65536 DBCS chars)
+ // Plus 4 byte to remember CP # when done loading it. (Don't want to get IA64 or anything out of alignment)
+ byte *pMemorySection = GetSharedMemory(65536 * 2 * 2 + 4 + this.iExtraBytes);
+
+ mapBytesToUnicode = (char*)pMemorySection;
+ mapUnicodeToBytes = (ushort*)(pMemorySection + 65536 * 2);
+ mapCodePageCached = (int*)(pMemorySection + 65536 * 2 * 2 + this.iExtraBytes);
+
+ // If its cached (& filled in) we don't have to do anything else
+ if (*mapCodePageCached != 0)
+ {
+ Contract.Assert(((*mapCodePageCached == this.dataTableCodePage && this.bFlagDataTable) ||
+ (*mapCodePageCached == this.CodePage && !this.bFlagDataTable)),
+ "[DBCSCodePageEncoding.LoadManagedCodePage]Expected mapped section cached page flag to be set to data table or regular code page.");
+
+ // Special case for GB18030 because it mangles its own code page after this function
+ if ((*mapCodePageCached != this.dataTableCodePage && this.bFlagDataTable) ||
+ (*mapCodePageCached != this.CodePage && !this.bFlagDataTable))
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+
+ // If its cached (& filled in) we don't have to do anything else
+ return;
+ }
+
+ // Need to read our data file and fill in our section.
+ // WARNING: Multiple code pieces could do this at once (so we don't have to lock machine-wide)
+ // so be careful here. Only stick legal values in here, don't stick temporary values.
+
+ // Move to the beginning of the data section
+ char* pData = (char*)&(pCodePage->FirstDataWord);
+
+ // We start at bytes position 0
+ int bytePosition = 0;
+ int useBytes = 0;
+
+ while (bytePosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ bytePosition = (int)(*pData);
+ pData++;
+ continue;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ bytePosition += input;
+ continue;
+ }
+ else if (input == 0xFFFF)
+ {
+ // Same as our bytePosition
+ useBytes = bytePosition;
+ input = unchecked((char)bytePosition);
+ }
+ else if (input == LEAD_BYTE_CHAR) // 0xfffe
+ {
+ // Lead byte mark
+ Contract.Assert(bytePosition < 0x100, "[DBCSCodePageEncoding.LoadManagedCodePage]expected lead byte to be < 0x100");
+ useBytes = bytePosition;
+ // input stays 0xFFFE
+ }
+ else if (input == UNICODE_REPLACEMENT_CHAR)
+ {
+ // Replacement char is already done
+ bytePosition++;
+ continue;
+ }
+ else
+ {
+ // Use this character
+ useBytes = bytePosition;
+ // input == input;
+ }
+
+ // We may need to clean up the selected character & position
+ if (CleanUpBytes(ref useBytes))
+ {
+ // Use this selected character at the selected position, don't do this if not supposed to.
+ if (input != LEAD_BYTE_CHAR)
+ {
+ // Don't do this for lead byte marks.
+ mapUnicodeToBytes[input] = unchecked((ushort)useBytes);
+ }
+ mapBytesToUnicode[useBytes] = input;
+ }
+ bytePosition++;
+ }
+
+ // See if we have any clean up junk to do
+ CleanUpEndBytes(mapBytesToUnicode);
+
+ // We're done with our mapped section, set our flag so others don't have to rebuild table.
+ // We only do this if we're flagging(using) the data table as our primary mechanism
+ if (this.bFlagDataTable)
+ *mapCodePageCached = this.dataTableCodePage;
+ }
+
+ // Any special processing for this code page
+ protected virtual bool CleanUpBytes(ref int bytes)
+ {
+ return true;
+ }
+
+ // Any special processing for this code page
+ [System.Security.SecurityCritical] // auto-generated
+ protected virtual unsafe void CleanUpEndBytes(char* chars)
+ {
+ }
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Read in our best fit table
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe override void ReadBestFitTable()
+ {
+ // Lock so we don't confuse ourselves.
+ lock(InternalSyncObject)
+ {
+ // If we got a best fit array already then don't do this
+ if (arrayUnicodeBestFit == null)
+ {
+ //
+ // Read in Best Fit table.
+ //
+
+ // First we have to advance past original character mapping table
+ // Move to the beginning of the data section
+ char* pData = (char*)&(pCodePage->FirstDataWord);
+
+ // We start at bytes position 0
+ int bytesPosition = 0;
+
+ while (bytesPosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ bytesPosition = (int)(*pData);
+ pData++;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ bytesPosition += input;
+ }
+ else
+ {
+ // All other cases add 1 to bytes position
+ bytesPosition++;
+ }
+ }
+
+ // Now bytesPosition is at start of bytes->unicode best fit table
+ char* pBytes2Unicode = pData;
+
+ // Now pData should be pointing to first word of bytes -> unicode best fit table
+ // (which we're also not using at the moment)
+ int iBestFitCount = 0;
+ bytesPosition = *pData;
+ pData++;
+
+ while (bytesPosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ bytesPosition = (int)(*pData);
+ pData++;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ bytesPosition += input;
+ }
+ else
+ {
+ // Use this character (unless its unknown, unk just skips 1)
+ if (input != UNICODE_REPLACEMENT_CHAR)
+ {
+ int correctedChar = bytesPosition;
+ if (CleanUpBytes(ref correctedChar))
+ {
+ // Sometimes correction makes them same as no best fit, skip those.
+ if (mapBytesToUnicode[correctedChar] != input)
+ {
+ iBestFitCount++;
+ }
+ }
+ }
+
+ // Position gets incremented in any case.
+ bytesPosition++;
+ }
+
+ }
+
+ // Now we know how big the best fit table has to be
+ char[] arrayTemp = new char[iBestFitCount * 2];
+
+ // Now we know how many best fits we have, so go back & read them in
+ iBestFitCount = 0;
+ pData = pBytes2Unicode;
+ bytesPosition = *pData;
+ pData++;
+ bool bOutOfOrder = false;
+
+ // Read it all in again
+ while (bytesPosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ bytesPosition = (int)(*pData);
+ pData++;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ bytesPosition += input;
+ }
+ else
+ {
+ // Use this character (unless its unknown, unk just skips 1)
+ if (input != UNICODE_REPLACEMENT_CHAR)
+ {
+ int correctedChar = bytesPosition;
+ if (CleanUpBytes(ref correctedChar))
+ {
+ // Sometimes correction makes them same as no best fit, skip those.
+ if (mapBytesToUnicode[correctedChar] != input)
+ {
+ if (correctedChar != bytesPosition)
+ bOutOfOrder = true;
+
+ arrayTemp[iBestFitCount++] = unchecked((char)correctedChar);
+ arrayTemp[iBestFitCount++] = input;
+ }
+ }
+ }
+
+ // Position gets incremented in any case.
+ bytesPosition++;
+ }
+ }
+
+ // If they're out of order we need to sort them.
+ if (bOutOfOrder)
+ {
+ Contract.Assert((arrayTemp.Length / 2) < 20,
+ "[DBCSCodePageEncoding.ReadBestFitTable]Expected small best fit table < 20 for code page " + CodePage + ", not " + arrayTemp.Length / 2);
+
+ for (int i = 0; i < arrayTemp.Length - 2; i+=2)
+ {
+ int iSmallest = i;
+ char cSmallest = arrayTemp[i];
+
+ for (int j = i + 2; j < arrayTemp.Length; j+=2)
+ {
+ // Find smallest one for front
+ if (cSmallest > arrayTemp[j])
+ {
+ cSmallest = arrayTemp[j];
+ iSmallest = j;
+ }
+ }
+
+ // If smallest one is something else, switch them
+ if (iSmallest != i)
+ {
+ char temp = arrayTemp[iSmallest];
+ arrayTemp[iSmallest] = arrayTemp[i];
+ arrayTemp[i] = temp;
+ temp = arrayTemp[iSmallest+1];
+ arrayTemp[iSmallest+1] = arrayTemp[i+1];
+ arrayTemp[i+1] = temp;
+ }
+ }
+ }
+
+ // Remember our array
+ arrayBytesBestFit = arrayTemp;
+
+ // Now were at beginning of Unicode -> Bytes best fit table, need to count them
+ char* pUnicode2Bytes = pData;
+ int unicodePosition = *(pData++);
+ iBestFitCount = 0;
+
+ while (unicodePosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ unicodePosition = (int)*pData;
+ pData++;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ unicodePosition += input;
+ }
+ else
+ {
+ // Same as our unicodePosition or use this character
+ if (input > 0)
+ iBestFitCount++;
+ unicodePosition++;
+ }
+ }
+
+ // Allocate our table
+ arrayTemp = new char[iBestFitCount*2];
+
+ // Now do it again to fill the array with real values
+ pData = pUnicode2Bytes;
+ unicodePosition = *(pData++);
+ iBestFitCount = 0;
+
+ while (unicodePosition < 0x10000)
+ {
+ // Get the next byte
+ char input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next data as our byte position
+ unicodePosition = (int)*pData;
+ pData++;
+ }
+ else if (input < 0x20 && input > 0)
+ {
+ // Advance input characters
+ unicodePosition += input;
+ }
+ else
+ {
+ if (input > 0)
+ {
+ // Use this character, may need to clean it up
+ int correctedChar = (int)input;
+ if (CleanUpBytes(ref correctedChar))
+ {
+ arrayTemp[iBestFitCount++] = unchecked((char)unicodePosition);
+ // Have to map it to Unicode because best fit will need unicode value of best fit char.
+ arrayTemp[iBestFitCount++] = mapBytesToUnicode[correctedChar];
+
+ // This won't work if it won't round trip.
+ // We can't do this assert for CP 51932 & 50220 because they aren't
+ // calling CleanUpBytes() for best fit. All the string stuff here
+ // also makes this assert slow.
+ // Contract.Assert(arrayTemp[iBestFitCount-1] != (char)0xFFFD, String.Format(
+ // "[DBCSCodePageEncoding.ReadBestFitTable] No valid Unicode value {0:X4} for round trip bytes {1:X4}, encoding {2}",
+ // (int)mapBytesToUnicode[input], (int)input, CodePage));
+ }
+ }
+ unicodePosition++;
+ }
+ }
+
+ // Remember our array
+ arrayUnicodeBestFit = arrayTemp;
+ }
+
+ }
+ }
+
+ // GetByteCount
+ // Note: We start by assuming that the output will be the same as count. Having
+ // an encoder or fallback may change that assumption
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(count >= 0, "[DBCSCodePageEncoding.GetByteCount]count is negative");
+ Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetByteCount]chars is null");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetByteCount]Attempting to use null fallback");
+
+ CheckMemorySection();
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+
+ // Only count if encoder.m_throwOnOverflow
+ if (encoder.InternalHasFallbackBuffer && encoder.FallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+ }
+
+ // prepare our end
+ int byteCount = 0;
+ char* charEnd = chars + count;
+
+ // For fallback we will need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[DBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate");
+ Contract.Assert(encoder != null,
+ "[DBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver");
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+
+ // Now we may have fallback char[] already (from the encoder)
+
+ // We have to use fallback method.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // get byte for this char
+ ushort sTemp = mapUnicodeToBytes[ch];
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ if (sTemp == 0 && ch != (char)0)
+ {
+ if (fallbackBuffer == null)
+ {
+ // Initialize the buffer
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(charEnd - count, charEnd, encoder, false);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // We'll use this one
+ byteCount++;
+ if (sTemp >= 0x100)
+ byteCount++;
+ }
+
+ return (int)byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetBytes]bytes is null");
+ Contract.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetBytes]byteCount is negative");
+ Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetBytes]chars is null");
+ Contract.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[DBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback");
+
+ CheckMemorySection();
+
+ // For fallback we will need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // prepare our end
+ char* charEnd = chars + charCount;
+ char* charStart = chars;
+ byte* byteStart = bytes;
+ byte* byteEnd = bytes + byteCount;
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[DBCSCodePageEncoding.GetBytes]leftover character should be high surrogate");
+
+ // Go ahead and get the fallback buffer (need leftover fallback if converting)
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
+
+ // If we're not converting we must not have a fallback buffer
+ if (encoder.m_throwOnOverflow && fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(encoder != null,
+ "[DBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver");
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+ }
+
+ // Now we may have fallback char[] already from the encoder
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // get byte for this char
+ ushort sTemp = mapUnicodeToBytes[ch];
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ if (sTemp == 0 && ch != (char)0)
+ {
+ if (fallbackBuffer == null)
+ {
+ // Initialize the buffer
+ Contract.Assert(encoder == null,
+ "[DBCSCodePageEncoding.GetBytes]Expected delayed create fallback only if no encoder.");
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // We'll use this one (or two)
+ // Bounds check
+
+ // Go ahead and add it, lead byte 1st if necessary
+ if (sTemp >= 0x100)
+ {
+ if (bytes + 1 >= byteEnd)
+ {
+ // didn't use this char, we'll throw or use buffer
+ if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
+ {
+ Contract.Assert(chars > charStart,
+ "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (double byte case)");
+ chars--; // don't use last char
+ }
+ else
+ fallbackBuffer.MovePrevious(); // don't use last fallback
+ ThrowBytesOverflow(encoder, chars == charStart); // throw ?
+ break; // don't throw, stop
+ }
+
+ *bytes = unchecked((byte)(sTemp >> 8));
+ bytes++;
+ }
+ // Single byte
+ else if (bytes >= byteEnd)
+ {
+ // didn't use this char, we'll throw or use buffer
+ if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
+ {
+ Contract.Assert(chars > charStart,
+ "[DBCSCodePageEncoding.GetBytes]Expected chars to have advanced (single byte case)");
+ chars--; // don't use last char
+ }
+ else
+ fallbackBuffer.MovePrevious(); // don't use last fallback
+ ThrowBytesOverflow(encoder, chars == charStart); // throw ?
+ break; // don't throw, stop
+ }
+
+ *bytes = unchecked((byte)(sTemp & 0xff));
+ bytes++;
+ }
+
+ // encoder stuff if we have one
+ if (encoder != null)
+ {
+ // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
+ if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
+ // Clear it in case of MustFlush
+ encoder.charLeftOver = (char)0;
+
+ // Set our chars used count
+ encoder.m_charsUsed = (int)(chars - charStart);
+ }
+
+ // If we're not converting we must not have a fallback buffer
+ // (We don't really have a way to clear none-encoder using fallbacks however)
+// Contract.Assert((encoder == null || encoder.m_throwOnOverflow) &&
+// (fallbackBuffer == null || fallbackBuffer.Remaining == 0),
+// "[DBCSEncoding.GetBytes]Expected empty fallback buffer at end if not converting");
+
+ return (int)(bytes - byteStart);
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ // Just assert, we're called internally so these should be safe, checked already
+ Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetCharCount]bytes is null");
+ Contract.Assert(count >= 0, "[DBCSCodePageEncoding.GetCharCount]byteCount is negative");
+
+ CheckMemorySection();
+
+ // Fix our decoder
+ DBCSDecoder decoder = (DBCSDecoder)baseDecoder;
+
+ // Get our fallback
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // We'll need to know where the end is
+ byte* byteEnd = bytes + count;
+ int charCount = count; // Assume 1 char / byte
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(decoder == null ||
+ !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at start");
+
+ // If we have a left over byte, use it
+ if (decoder != null && decoder.bLeftOver > 0)
+ {
+ // We have a left over byte?
+ if (count == 0)
+ {
+ // No input though
+ if (!decoder.MustFlush)
+ {
+ // Don't have to flush
+ return 0;
+ }
+
+
+ Contract.Assert(fallbackBuffer == null,
+ "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer");
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(bytes, null);
+
+ byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) };
+ return fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+
+ // Get our full info
+ int iBytes = decoder.bLeftOver << 8;
+ iBytes |= (*bytes);
+ bytes++;
+
+ // This is either 1 known char or fallback
+ // Already counted 1 char
+ // Look up our bytes
+ char cDecoder = mapBytesToUnicode[iBytes];
+ if (cDecoder == 0 && iBytes != 0)
+ {
+ // Deallocate preallocated one
+ charCount--;
+
+ // We'll need a fallback
+ Contract.Assert(fallbackBuffer == null,
+ "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer for unknown pair");
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - count, null);
+
+ // Do fallback, we know there're 2 bytes
+ byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+ // else we already reserved space for this one.
+ }
+
+ // Loop, watch out for fallbacks
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ int iBytes = *bytes;
+ bytes++;
+ char c = mapBytesToUnicode[iBytes];
+
+ // See if it was a double byte character
+ if (c == LEAD_BYTE_CHAR)
+ {
+ // Its a lead byte
+ charCount--; // deallocate preallocated lead byte
+ if (bytes < byteEnd)
+ {
+ // Have another to use, so use it
+ iBytes <<= 8;
+ iBytes |= *bytes;
+ bytes++;
+ c = mapBytesToUnicode[iBytes];
+ }
+ else
+ {
+ // No input left
+ if (decoder == null || decoder.MustFlush)
+ {
+ // have to flush anyway, set to unknown so we use fallback in a 'sec
+ charCount++; // reallocate deallocated lead byte
+ c = UNKNOWN_CHAR_FLAG;
+ }
+ else
+ {
+ // We'll stick it in decoder
+ break;
+ }
+ }
+ }
+
+ // See if it was unknown.
+ // Unknown and known chars already allocated, but fallbacks aren't
+ if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - count, null);
+ }
+
+ // Do fallback
+ charCount--; // Get rid of preallocated extra char
+ byte[] byteBuffer = null;
+ if (iBytes < 0x100)
+ byteBuffer = new byte[] { unchecked((byte)iBytes) };
+ else
+ byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+ }
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ Contract.Assert(decoder == null || !decoder.m_throwOnOverflow ||
+ !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[DBCSCodePageEncoding.GetCharCount]Expected empty fallback buffer at end");
+
+ // Return our count
+ return charCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[DBCSCodePageEncoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[DBCSCodePageEncoding.GetChars]byteCount is negative");
+ Contract.Assert(chars != null, "[DBCSCodePageEncoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[DBCSCodePageEncoding.GetChars]charCount is negative");
+
+ CheckMemorySection();
+
+ // Fix our decoder
+ DBCSDecoder decoder = (DBCSDecoder)baseDecoder;
+
+ // We'll need to know where the end is
+ byte* byteStart = bytes;
+ byte* byteEnd = bytes + byteCount;
+ char* charStart = chars;
+ char* charEnd = chars + charCount;
+ bool bUsedDecoder = false;
+
+ // Get our fallback
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ Contract.Assert(decoder == null || !decoder.m_throwOnOverflow ||
+ !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
+
+ // If we have a left over byte, use it
+ if (decoder != null && decoder.bLeftOver > 0)
+ {
+ // We have a left over byte?
+ if (byteCount == 0)
+ {
+ // No input though
+ if (!decoder.MustFlush)
+ {
+ // Don't have to flush
+ return 0;
+ }
+
+ // Well, we're flushing, so use '?' or fallback
+ // fallback leftover byte
+ Contract.Assert(fallbackBuffer == null,
+ "[DBCSCodePageEncoding.GetChars]Expected empty fallback");
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(bytes, charEnd);
+
+ // If no room its hopeless, this was 1st fallback
+ byte[] byteBuffer = new byte[] { unchecked((byte)decoder.bLeftOver) };
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ ThrowCharsOverflow(decoder, true);
+
+ decoder.bLeftOver = 0;
+
+ // Done, return it
+ return (int)(chars-charStart);
+ }
+
+ // Get our full info
+ int iBytes = decoder.bLeftOver << 8;
+ iBytes |= (*bytes);
+ bytes++;
+
+ // Look up our bytes
+ char cDecoder = mapBytesToUnicode[iBytes];
+ if (cDecoder == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ Contract.Assert(fallbackBuffer == null,
+ "[DBCSCodePageEncoding.GetChars]Expected empty fallback for two bytes");
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
+
+ byte[] byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ ThrowCharsOverflow(decoder, true);
+ }
+ else
+ {
+ // Do we have output room?, hopeless if not, this is first char
+ if (chars >= charEnd)
+ ThrowCharsOverflow(decoder, true);
+
+ *(chars++) = cDecoder;
+ }
+ }
+
+ // Loop, paying attention to our fallbacks.
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ int iBytes = *bytes;
+ bytes++;
+ char c = mapBytesToUnicode[iBytes];
+
+ // See if it was a double byte character
+ if (c == LEAD_BYTE_CHAR)
+ {
+ // Its a lead byte
+ if (bytes < byteEnd)
+ {
+ // Have another to use, so use it
+ iBytes <<= 8;
+ iBytes |= *bytes;
+ bytes++;
+ c = mapBytesToUnicode[iBytes];
+ }
+ else
+ {
+ // No input left
+ if (decoder == null || decoder.MustFlush)
+ {
+ // have to flush anyway, set to unknown so we use fallback in a 'sec
+ c = UNKNOWN_CHAR_FLAG;
+ }
+ else
+ {
+ // Stick it in decoder
+ bUsedDecoder = true;
+ decoder.bLeftOver = (byte)iBytes;
+ break;
+ }
+ }
+ }
+
+ // See if it was unknown
+ if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
+ }
+
+ // Do fallback
+ byte[] byteBuffer = null;
+ if (iBytes < 0x100)
+ byteBuffer = new byte[] { unchecked((byte)iBytes) };
+ else
+ byteBuffer = new byte[] { unchecked((byte)(iBytes >> 8)), unchecked((byte)iBytes) };
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // May or may not throw, but we didn't get these byte(s)
+ Contract.Assert(bytes >= byteStart + byteBuffer.Length,
+ "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for fallback");
+ bytes-=byteBuffer.Length; // didn't use these byte(s)
+ fallbackBuffer.InternalReset(); // Didn't fall this back
+ ThrowCharsOverflow(decoder, bytes == byteStart); // throw?
+ break; // don't throw, but stop loop
+ }
+ }
+ else
+ {
+ // Do we have buffer room?
+ if (chars >= charEnd)
+ {
+ // May or may not throw, but we didn't get these byte(s)
+ Contract.Assert(bytes > byteStart,
+ "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for lead byte");
+ bytes--; // unused byte
+ if (iBytes >= 0x100)
+ {
+ Contract.Assert(bytes > byteStart,
+ "[DBCSCodePageEncoding.GetChars]Expected bytes to have advanced for trail byte");
+ bytes--; // 2nd unused byte
+ }
+ ThrowCharsOverflow(decoder, bytes == byteStart); // throw?
+ break; // don't throw, but stop loop
+ }
+
+ *(chars++) = c;
+ }
+ }
+
+ // We already stuck it in encoder if necessary, but we have to clear cases where nothing new got into decoder
+ if (decoder != null)
+ {
+ // Clear it in case of MustFlush
+ if (bUsedDecoder == false)
+ {
+ decoder.bLeftOver = 0;
+ }
+
+ // Remember our count
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+ }
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ Contract.Assert(decoder == null || !decoder.m_throwOnOverflow ||
+ !decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[DBCSCodePageEncoding.GetChars]Expected empty fallback buffer at end");
+
+ // Return length of our output
+ return (int)(chars - charStart);
+ }
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 2 to 1 is worst case. Already considered surrogate fallback
+ byteCount *= 2;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // DBCS is pretty much the same, but could have hanging high byte making extra ? and fallback for unknown
+ long charCount = ((long)byteCount + 1);
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less, unknown fallbacks could be longer.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ public override Decoder GetDecoder()
+ {
+ return new DBCSDecoder(this);
+ }
+
+ [Serializable]
+ internal class DBCSDecoder : DecoderNLS
+ {
+ // Need a place for the last left over byte
+ internal byte bLeftOver = 0;
+
+ public DBCSDecoder(DBCSCodePageEncoding encoding) : base(encoding)
+ {
+ // Base calls reset
+ }
+
+ public override void Reset()
+ {
+ this.bLeftOver = 0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.bLeftOver != 0);
+ }
+ }
+ }
+ }
+}
+#endif // FEATURE_CODEPAGES_FILE
+
diff --git a/src/mscorlib/src/System/Text/Decoder.cs b/src/mscorlib/src/System/Text/Decoder.cs
new file mode 100644
index 0000000000..f794dc4dce
--- /dev/null
+++ b/src/mscorlib/src/System/Text/Decoder.cs
@@ -0,0 +1,349 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ // A Decoder is used to decode a sequence of blocks of bytes into a
+ // sequence of blocks of characters. Following instantiation of a decoder,
+ // sequential blocks of bytes are converted into blocks of characters through
+ // calls to the GetChars method. The decoder maintains state between the
+ // conversions, allowing it to correctly decode byte sequences that span
+ // adjacent blocks.
+ //
+ // Instances of specific implementations of the Decoder abstract base
+ // class are typically obtained through calls to the GetDecoder method
+ // of Encoding objects.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public abstract class Decoder
+ {
+ internal DecoderFallback m_fallback = null;
+
+ [NonSerialized]
+ internal DecoderFallbackBuffer m_fallbackBuffer = null;
+
+ internal void SerializeDecoder(SerializationInfo info)
+ {
+ info.AddValue("m_fallback", this.m_fallback);
+ }
+
+ protected Decoder( )
+ {
+ // We don't call default reset because default reset probably isn't good if we aren't initialized.
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public DecoderFallback Fallback
+ {
+ get
+ {
+ return m_fallback;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Can't change fallback if buffer is wrong
+ if (m_fallbackBuffer != null && m_fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), "value");
+
+ m_fallback = value;
+ m_fallbackBuffer = null;
+ }
+ }
+
+ // Note: we don't test for threading here because async access to Encoders and Decoders
+ // doesn't work anyway.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public DecoderFallbackBuffer FallbackBuffer
+ {
+ get
+ {
+ if (m_fallbackBuffer == null)
+ {
+ if (m_fallback != null)
+ m_fallbackBuffer = m_fallback.CreateFallbackBuffer();
+ else
+ m_fallbackBuffer = DecoderFallback.ReplacementFallback.CreateFallbackBuffer();
+ }
+
+ return m_fallbackBuffer;
+ }
+ }
+
+ internal bool InternalHasFallbackBuffer
+ {
+ get
+ {
+ return m_fallbackBuffer != null;
+ }
+ }
+
+ // Reset the Decoder
+ //
+ // Normally if we call GetChars() and an error is thrown we don't change the state of the Decoder. This
+ // would allow the caller to correct the error condition and try again (such as if they need a bigger buffer.)
+ //
+ // If the caller doesn't want to try again after GetChars() throws an error, then they need to call Reset().
+ //
+ // Virtual implimentation has to call GetChars with flush and a big enough buffer to clear a 0 byte string
+ // We avoid GetMaxCharCount() because a) we can't call the base encoder and b) it might be really big.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual void Reset()
+ {
+ byte[] byteTemp = Array.Empty<byte>();
+ char[] charTemp = new char[GetCharCount(byteTemp, 0, 0, true)];
+ GetChars(byteTemp, 0, 0, charTemp, 0, true);
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Returns the number of characters the next call to GetChars will
+ // produce if presented with the given range of bytes. The returned value
+ // takes into account the state in which the decoder was left following the
+ // last call to GetChars. The state of the decoder is not affected
+ // by a call to this method.
+ //
+ public abstract int GetCharCount(byte[] bytes, int index, int count);
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual int GetCharCount(byte[] bytes, int index, int count, bool flush)
+ {
+ return GetCharCount(bytes, index, count);
+ }
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetCharCount(byte* bytes, int count, bool flush)
+ {
+ // Validate input parameters
+ if (bytes == null)
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ byte[] arrbyte = new byte[count];
+ int index;
+
+ for (index = 0; index < count; index++)
+ arrbyte[index] = bytes[index];
+
+ return GetCharCount(arrbyte, 0, count);
+ }
+
+ // Decodes a range of bytes in a byte array into a range of characters
+ // in a character array. The method decodes byteCount bytes from
+ // bytes starting at index byteIndex, storing the resulting
+ // characters in chars starting at index charIndex. The
+ // decoding takes into account the state in which the decoder was left
+ // following the last call to this method.
+ //
+ // An exception occurs if the character array is not large enough to
+ // hold the complete decoding of the bytes. The GetCharCount method
+ // can be used to determine the exact number of characters that will be
+ // produced for a given range of bytes. Alternatively, the
+ // GetMaxCharCount method of the Encoding that produced this
+ // decoder can be used to determine the maximum number of characters that
+ // will be produced for a given number of bytes, regardless of the actual
+ // byte values.
+ //
+ public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex);
+
+ public virtual int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, bool flush)
+ {
+ return GetChars(bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: If this breaks it could be a security threat. Obviously we
+ // call this internally, so you need to make sure that your pointers, counts
+ // and indexes are correct when you call this method.
+ //
+ // In addition, we have internal code, which will be marked as "safe" calling
+ // this code. However this code is dependent upon the implimentation of an
+ // external GetChars() method, which could be overridden by a third party and
+ // the results of which cannot be guaranteed. We use that result to copy
+ // the char[] to our char* output buffer. If the result count was wrong, we
+ // could easily overflow our output buffer. Therefore we do an extra test
+ // when we copy the buffer so that we don't overflow charCount either.
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush)
+ {
+ // Validate input parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? "chars" : "bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get the byte array to convert
+ byte[] arrByte = new byte[byteCount];
+
+ int index;
+ for (index = 0; index < byteCount; index++)
+ arrByte[index] = bytes[index];
+
+ // Get the char array to fill
+ char[] arrChar = new char[charCount];
+
+ // Do the work
+ int result = GetChars(arrByte, 0, byteCount, arrChar, 0, flush);
+
+ Contract.Assert(result <= charCount, "Returned more chars than we have space for");
+
+ // Copy the char array
+ // WARNING: We MUST make sure that we don't copy too many chars. We can't
+ // rely on result because it could be a 3rd party implimentation. We need
+ // to make sure we never copy more than charCount chars no matter the value
+ // of result
+ if (result < charCount)
+ charCount = result;
+
+ // We check both result and charCount so that we don't accidentally overrun
+ // our pointer buffer just because of an issue in GetChars
+ for (index = 0; index < charCount; index++)
+ chars[index] = arrChar[index];
+
+ return charCount;
+ }
+
+ // This method is used when the output buffer might not be large enough.
+ // It will decode until it runs out of bytes, and then it will return
+ // true if it the entire input was converted. In either case it
+ // will also return the number of converted bytes and output characters used.
+ // It will only throw a buffer overflow exception if the entire lenght of chars[] is
+ // too small to store the next char. (like 0 or maybe 1 or 4 for some encodings)
+ // We're done processing this buffer only if completed returns true.
+ //
+ // Might consider checking Max...Count to avoid the extra counting step.
+ //
+ // Note that if all of the input bytes are not consumed, then we'll do a /2, which means
+ // that its likely that we didn't consume as many bytes as we could have. For some
+ // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream)
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual void Convert(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ // Validate parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException((bytes == null ? "bytes" : "chars"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ Contract.EndContractBlock();
+
+ bytesUsed = byteCount;
+
+ // Its easy to do if it won't overrun our buffer.
+ while (bytesUsed > 0)
+ {
+ if (GetCharCount(bytes, byteIndex, bytesUsed, flush) <= charCount)
+ {
+ charsUsed = GetChars(bytes, byteIndex, bytesUsed, chars, charIndex, flush);
+ completed = (bytesUsed == byteCount &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0));
+ return;
+ }
+
+ // Try again with 1/2 the count, won't flush then 'cause won't read it all
+ flush = false;
+ bytesUsed /= 2;
+ }
+
+ // Oops, we didn't have anything, we'll have to throw an overflow
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConversionOverflow"));
+ }
+
+ // This is the version that uses *.
+ // We're done processing this buffer only if completed returns true.
+ //
+ // Might consider checking Max...Count to avoid the extra counting step.
+ //
+ // Note that if all of the input bytes are not consumed, then we'll do a /2, which means
+ // that its likely that we didn't consume as many bytes as we could have. For some
+ // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream)
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe void Convert(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ // Validate input parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? "chars" : "bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get ready to do it
+ bytesUsed = byteCount;
+
+ // Its easy to do if it won't overrun our buffer.
+ while (bytesUsed > 0)
+ {
+ if (GetCharCount(bytes, bytesUsed, flush) <= charCount)
+ {
+ charsUsed = GetChars(bytes, bytesUsed, chars, charCount, flush);
+ completed = (bytesUsed == byteCount &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0));
+ return;
+ }
+
+ // Try again with 1/2 the count, won't flush then 'cause won't read it all
+ flush = false;
+ bytesUsed /= 2;
+ }
+
+ // Oops, we didn't have anything, we'll have to throw an overflow
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConversionOverflow"));
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs b/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs
new file mode 100644
index 0000000000..5c1dcd9682
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DecoderBestFitFallback.cs
@@ -0,0 +1,247 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// This is used internally to create best fit behavior as per the original windows best fit behavior.
+//
+namespace System.Text
+{
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal sealed class InternalDecoderBestFitFallback : DecoderFallback
+ {
+ // Our variables
+ internal Encoding encoding = null;
+ internal char[] arrayBestFit = null;
+ internal char cReplacement = '?';
+
+ internal InternalDecoderBestFitFallback(Encoding encoding)
+ {
+ // Need to load our replacement characters table.
+ this.encoding = encoding;
+ this.bIsMicrosoftBestFitFallback = true;
+ }
+
+ public override DecoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new InternalDecoderBestFitFallbackBuffer(this);
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ InternalDecoderBestFitFallback that = value as InternalDecoderBestFitFallback;
+ if (that != null)
+ {
+ return (this.encoding.CodePage == that.encoding.CodePage);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.encoding.CodePage;
+ }
+ }
+
+ internal sealed class InternalDecoderBestFitFallbackBuffer : DecoderFallbackBuffer
+ {
+ // Our variables
+ internal char cBestFit = '\0';
+ internal int iCount = -1;
+ internal int iSize;
+ private InternalDecoderBestFitFallback oFallback;
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Constructor
+ public InternalDecoderBestFitFallbackBuffer(InternalDecoderBestFitFallback fallback)
+ {
+ this.oFallback = fallback;
+
+ if (oFallback.arrayBestFit == null)
+ {
+ // Lock so we don't confuse ourselves.
+ lock(InternalSyncObject)
+ {
+ // Double check before we do it again.
+ if (oFallback.arrayBestFit == null)
+ oFallback.arrayBestFit = fallback.encoding.GetBestFitBytesToUnicodeData();
+ }
+ }
+ }
+
+ // Fallback methods
+ public override bool Fallback(byte[] bytesUnknown, int index)
+ {
+ // We expect no previous fallback in our buffer
+ Contract.Assert(iCount < 1, "[DecoderReplacementFallbackBuffer.Fallback] Calling fallback without a previously empty buffer");
+
+ cBestFit = TryBestFit(bytesUnknown);
+ if (cBestFit == '\0')
+ cBestFit = oFallback.cReplacement;
+
+ iCount = iSize = 1;
+
+ return true;
+ }
+
+ // Default version is overridden in DecoderReplacementFallback.cs
+ public override char GetNextChar()
+ {
+ // We want it to get < 0 because == 0 means that the current/last character is a fallback
+ // and we need to detect recursion. We could have a flag but we already have this counter.
+ iCount--;
+
+ // Do we have anything left? 0 is now last fallback char, negative is nothing left
+ if (iCount < 0)
+ return '\0';
+
+ // Need to get it out of the buffer.
+ // Make sure it didn't wrap from the fast count-- path
+ if (iCount == int.MaxValue)
+ {
+ iCount = -1;
+ return '\0';
+ }
+
+ // Return the best fit character
+ return cBestFit;
+ }
+
+ public override bool MovePrevious()
+ {
+ // Exception fallback doesn't have anywhere to back up to.
+ if (iCount >= 0)
+ iCount++;
+
+ // Return true if we could do it.
+ return (iCount >= 0 && iCount <= iSize);
+ }
+
+ // How many characters left to output?
+ public override int Remaining
+ {
+ get
+ {
+ return (iCount > 0) ? iCount : 0;
+ }
+ }
+
+ // Clear the buffer
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ public override unsafe void Reset()
+ {
+ iCount = -1;
+ byteStart = null;
+ }
+
+ // This version just counts the fallback and doesn't actually copy anything.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes)
+ // Right now this has both bytes and bytes[], since we might have extra bytes, hence the
+ // array, and we might need the index, hence the byte*
+ {
+ // return our replacement string Length (always 1 for InternalDecoderBestFitFallback, either
+ // a best fit char or ?
+ return 1;
+ }
+
+ // private helper methods
+ private char TryBestFit(byte[] bytesCheck)
+ {
+ // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array
+ int lowBound = 0;
+ int highBound = oFallback.arrayBestFit.Length;
+ int index;
+ char cCheck;
+
+ // Check trivial case first (no best fit)
+ if (highBound == 0)
+ return '\0';
+
+ // If our array is too small or too big we can't check
+ if (bytesCheck.Length == 0 || bytesCheck.Length > 2)
+ return '\0';
+
+ if (bytesCheck.Length == 1)
+ cCheck = unchecked((char)bytesCheck[0]);
+ else
+ cCheck = unchecked((char)((bytesCheck[0] << 8) + bytesCheck[1]));
+
+ // Check trivial out of range case
+ if (cCheck < oFallback.arrayBestFit[0] || cCheck > oFallback.arrayBestFit[highBound - 2])
+ return '\0';
+
+ // Binary search the array
+ int iDiff;
+ while ((iDiff = (highBound - lowBound)) > 6)
+ {
+ // Look in the middle, which is complicated by the fact that we have 2 #s for each pair,
+ // so we don't want index to be odd because it must be word aligned.
+ // Also note that index can never == highBound (because diff is rounded down)
+ index = ((iDiff / 2) + lowBound) & 0xFFFE;
+
+ char cTest = oFallback.arrayBestFit[index];
+ if (cTest == cCheck)
+ {
+ // We found it
+ Contract.Assert(index + 1 < oFallback.arrayBestFit.Length,
+ "[InternalDecoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array");
+ return oFallback.arrayBestFit[index + 1];
+ }
+ else if (cTest < cCheck)
+ {
+ // We weren't high enough
+ lowBound = index;
+ }
+ else
+ {
+ // We weren't low enough
+ highBound = index;
+ }
+ }
+
+ for (index = lowBound; index < highBound; index += 2)
+ {
+ if (oFallback.arrayBestFit[index] == cCheck)
+ {
+ // We found it
+ Contract.Assert(index + 1 < oFallback.arrayBestFit.Length,
+ "[InternalDecoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array");
+ return oFallback.arrayBestFit[index + 1];
+ }
+ }
+
+ // Char wasn't in our table
+ return '\0';
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/DecoderExceptionFallback.cs b/src/mscorlib/src/System/Text/DecoderExceptionFallback.cs
new file mode 100644
index 0000000000..7a0478de20
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DecoderExceptionFallback.cs
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+
+ [Serializable]
+ public sealed class DecoderExceptionFallback : DecoderFallback
+ {
+ // Construction
+ public DecoderExceptionFallback()
+ {
+ }
+
+ public override DecoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new DecoderExceptionFallbackBuffer();
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ DecoderExceptionFallback that = value as DecoderExceptionFallback;
+ if (that != null)
+ {
+ return (true);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return 879;
+ }
+ }
+
+
+ public sealed class DecoderExceptionFallbackBuffer : DecoderFallbackBuffer
+ {
+ public override bool Fallback(byte[] bytesUnknown, int index)
+ {
+ Throw(bytesUnknown, index);
+ return true;
+ }
+
+ public override char GetNextChar()
+ {
+ return (char)0;
+ }
+
+ public override bool MovePrevious()
+ {
+ // Exception fallback doesn't have anywhere to back up to.
+ return false;
+ }
+
+ // Exceptions are always empty
+ public override int Remaining
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ private void Throw(byte[] bytesUnknown, int index)
+ {
+ // Create a string representation of our bytes.
+ StringBuilder strBytes = new StringBuilder(bytesUnknown.Length * 3);
+
+ int i;
+ for (i = 0; i < bytesUnknown.Length && i < 20; i++)
+ {
+ strBytes.Append("[");
+ strBytes.Append(bytesUnknown[i].ToString("X2", CultureInfo.InvariantCulture));
+ strBytes.Append("]");
+ }
+
+ // In case the string's really long
+ if (i == 20)
+ strBytes.Append(" ...");
+
+ // Known index
+ throw new DecoderFallbackException(
+ Environment.GetResourceString("Argument_InvalidCodePageBytesIndex",
+ strBytes, index), bytesUnknown, index);
+ }
+
+ }
+
+ // Exception for decoding unknown byte sequences.
+ [Serializable]
+ public sealed class DecoderFallbackException : ArgumentException
+ {
+ byte[] bytesUnknown = null;
+ int index = 0;
+
+ public DecoderFallbackException()
+ : base(Environment.GetResourceString("Arg_ArgumentException"))
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public DecoderFallbackException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public DecoderFallbackException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ internal DecoderFallbackException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ public DecoderFallbackException(
+ String message, byte[] bytesUnknown, int index) : base(message)
+ {
+ this.bytesUnknown = bytesUnknown;
+ this.index = index;
+ }
+
+ public byte[] BytesUnknown
+ {
+ get
+ {
+ return (bytesUnknown);
+ }
+ }
+
+ public int Index
+ {
+ get
+ {
+ return this.index;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/DecoderFallback.cs b/src/mscorlib/src/System/Text/DecoderFallback.cs
new file mode 100644
index 0000000000..1698fd37ab
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DecoderFallback.cs
@@ -0,0 +1,284 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+using System;
+using System.Security;
+using System.Threading;
+using System.Globalization;
+using System.Diagnostics.Contracts;
+
+namespace System.Text
+{
+ [Serializable]
+ public abstract class DecoderFallback
+ {
+ internal bool bIsMicrosoftBestFitFallback = false;
+
+ private static volatile DecoderFallback replacementFallback; // Default fallback, uses no best fit & "?"
+ private static volatile DecoderFallback exceptionFallback;
+
+ // Private object for locking instead of locking on a internal type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Get each of our generic fallbacks.
+
+ public static DecoderFallback ReplacementFallback
+ {
+ get
+ {
+ if (replacementFallback == null)
+ lock(InternalSyncObject)
+ if (replacementFallback == null)
+ replacementFallback = new DecoderReplacementFallback();
+
+ return replacementFallback;
+ }
+ }
+
+
+ public static DecoderFallback ExceptionFallback
+ {
+ get
+ {
+ if (exceptionFallback == null)
+ lock(InternalSyncObject)
+ if (exceptionFallback == null)
+ exceptionFallback = new DecoderExceptionFallback();
+
+ return exceptionFallback;
+ }
+ }
+
+ // Fallback
+ //
+ // Return the appropriate unicode string alternative to the character that need to fall back.
+ // Most implimentations will be:
+ // return new MyCustomDecoderFallbackBuffer(this);
+
+ public abstract DecoderFallbackBuffer CreateFallbackBuffer();
+
+ // Maximum number of characters that this instance of this fallback could return
+
+ public abstract int MaxCharCount { get; }
+
+ internal bool IsMicrosoftBestFitFallback
+ {
+ get
+ {
+ return bIsMicrosoftBestFitFallback;
+ }
+ }
+ }
+
+
+ public abstract class DecoderFallbackBuffer
+ {
+ // Most implimentations will probably need an implimenation-specific constructor
+
+ // internal methods that cannot be overriden that let us do our fallback thing
+ // These wrap the internal methods so that we can check for people doing stuff that's incorrect
+
+ public abstract bool Fallback(byte[] bytesUnknown, int index);
+
+ // Get next character
+
+ public abstract char GetNextChar();
+
+ // Back up a character
+
+ public abstract bool MovePrevious();
+
+ // How many chars left in this fallback?
+
+ public abstract int Remaining { get; }
+
+ // Clear the buffer
+
+ public virtual void Reset()
+ {
+ while (GetNextChar() != (char)0);
+ }
+
+ // Internal items to help us figure out what we're doing as far as error messages, etc.
+ // These help us with our performance and messages internally
+ [SecurityCritical]
+ internal unsafe byte* byteStart;
+ [SecurityCritical]
+ internal unsafe char* charEnd;
+
+ // Internal Reset
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void InternalReset()
+ {
+ byteStart = null;
+ Reset();
+ }
+
+ // Set the above values
+ // This can't be part of the constructor because DecoderFallbacks would have to know how to impliment these.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void InternalInitialize(byte* byteStart, char* charEnd)
+ {
+ this.byteStart = byteStart;
+ this.charEnd = charEnd;
+ }
+
+ // Fallback the current byte by sticking it into the remaining char buffer.
+ // This can only be called by our encodings (other have to use the public fallback methods), so
+ // we can use our DecoderNLS here too (except we don't).
+ // Returns true if we are successful, false if we can't fallback the character (no buffer space)
+ // So caller needs to throw buffer space if return false.
+ // Right now this has both bytes and bytes[], since we might have extra bytes, hence the
+ // array, and we might need the index, hence the byte*
+ // Don't touch ref chars unless we succeed
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe virtual bool InternalFallback(byte[] bytes, byte* pBytes, ref char* chars)
+ {
+ // Copy bytes to array (slow, but right now that's what we get to do.
+ // byte[] bytesUnknown = new byte[count];
+// for (int i = 0; i < count; i++)
+// bytesUnknown[i] = *(bytes++);
+
+ Contract.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize");
+
+ // See if there's a fallback character and we have an output buffer then copy our string.
+ if (this.Fallback(bytes, (int)(pBytes - byteStart - bytes.Length)))
+ {
+ // Copy the chars to our output
+ char ch;
+ char* charTemp = chars;
+ bool bHighSurrogate = false;
+ while ((ch = GetNextChar()) != 0)
+ {
+ // Make sure no mixed up surrogates
+ if (Char.IsSurrogate(ch))
+ {
+ if (Char.IsHighSurrogate(ch))
+ {
+ // High Surrogate
+ if (bHighSurrogate)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+ bHighSurrogate = true;
+ }
+ else
+ {
+ // Low surrogate
+ if (bHighSurrogate == false)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+ bHighSurrogate = false;
+ }
+ }
+
+ if (charTemp >= charEnd)
+ {
+ // No buffer space
+ return false;
+ }
+
+ *(charTemp++) = ch;
+ }
+
+ // Need to make sure that bHighSurrogate isn't true
+ if (bHighSurrogate)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+
+ // Now we aren't going to be false, so its OK to update chars
+ chars = charTemp;
+ }
+
+ return true;
+ }
+
+ // This version just counts the fallback and doesn't actually copy anything.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe virtual int InternalFallback(byte[] bytes, byte* pBytes)
+ // Right now this has both bytes and bytes[], since we might have extra bytes, hence the
+ // array, and we might need the index, hence the byte*
+ {
+ // Copy bytes to array (slow, but right now that's what we get to do.
+// byte[] bytesUnknown = new byte[count];
+// for (int i = 0; i < count; i++)
+ // bytesUnknown[i] = *(bytes++);
+
+ Contract.Assert(byteStart != null, "[DecoderFallback.InternalFallback]Used InternalFallback without calling InternalInitialize");
+
+ // See if there's a fallback character and we have an output buffer then copy our string.
+ if (this.Fallback(bytes, (int)(pBytes - byteStart - bytes.Length)))
+ {
+ int count = 0;
+
+ char ch;
+ bool bHighSurrogate = false;
+ while ((ch = GetNextChar()) != 0)
+ {
+ // Make sure no mixed up surrogates
+ if (Char.IsSurrogate(ch))
+ {
+ if (Char.IsHighSurrogate(ch))
+ {
+ // High Surrogate
+ if (bHighSurrogate)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+ bHighSurrogate = true;
+ }
+ else
+ {
+ // Low surrogate
+ if (bHighSurrogate == false)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+ bHighSurrogate = false;
+ }
+ }
+
+ count++;
+ }
+
+ // Need to make sure that bHighSurrogate isn't true
+ if (bHighSurrogate)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+
+ return count;
+ }
+
+ // If no fallback return 0
+ return 0;
+ }
+
+ // private helper methods
+ internal void ThrowLastBytesRecursive(byte[] bytesUnknown)
+ {
+ // Create a string representation of our bytes.
+ StringBuilder strBytes = new StringBuilder(bytesUnknown.Length * 3);
+ int i;
+ for (i = 0; i < bytesUnknown.Length && i < 20; i++)
+ {
+ if (strBytes.Length > 0)
+ strBytes.Append(" ");
+ strBytes.Append(String.Format(CultureInfo.InvariantCulture, "\\x{0:X2}", bytesUnknown[i]));
+ }
+ // In case the string's really long
+ if (i == 20)
+ strBytes.Append(" ...");
+
+ // Throw it, using our complete bytes
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_RecursiveFallbackBytes",
+ strBytes.ToString()), "bytesUnknown");
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Text/DecoderNLS.cs b/src/mscorlib/src/System/Text/DecoderNLS.cs
new file mode 100644
index 0000000000..c2e82dd250
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DecoderNLS.cs
@@ -0,0 +1,298 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ // A Decoder is used to decode a sequence of blocks of bytes into a
+ // sequence of blocks of characters. Following instantiation of a decoder,
+ // sequential blocks of bytes are converted into blocks of characters through
+ // calls to the GetChars method. The decoder maintains state between the
+ // conversions, allowing it to correctly decode byte sequences that span
+ // adjacent blocks.
+ //
+ // Instances of specific implementations of the Decoder abstract base
+ // class are typically obtained through calls to the GetDecoder method
+ // of Encoding objects.
+ //
+
+ [Serializable]
+ internal class DecoderNLS : Decoder, ISerializable
+ {
+ // Remember our encoding
+ protected Encoding m_encoding;
+ [NonSerialized] protected bool m_mustFlush;
+ [NonSerialized] internal bool m_throwOnOverflow;
+ [NonSerialized] internal int m_bytesUsed;
+
+#region Serialization
+
+ // Constructor called by serialization. called during deserialization.
+ internal DecoderNLS(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(
+ String.Format(
+ System.Globalization.CultureInfo.CurrentCulture,
+ Environment.GetResourceString("NotSupported_TypeCannotDeserialized"), this.GetType()));
+ }
+
+ // ISerializable implementation. called during serialization.
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ SerializeDecoder(info);
+ info.AddValue("encoding", this.m_encoding);
+ info.SetType(typeof(Encoding.DefaultDecoder));
+ }
+
+#endregion Serialization
+
+ internal DecoderNLS( Encoding encoding )
+ {
+ this.m_encoding = encoding;
+ this.m_fallback = this.m_encoding.DecoderFallback;
+ this.Reset();
+ }
+
+ // This is used by our child deserializers
+ internal DecoderNLS( )
+ {
+ this.m_encoding = null;
+ this.Reset();
+ }
+
+ public override void Reset()
+ {
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ public override unsafe int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return GetCharCount(bytes, index, count, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe int GetCharCount(byte[] bytes, int index, int count, bool flush)
+ {
+ // Validate Parameters
+ if (bytes == null)
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (bytes.Length - index < count)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ Contract.EndContractBlock();
+
+ // Avoid null fixed problem
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ // Just call pointer version
+ fixed (byte* pBytes = bytes)
+ return GetCharCount(pBytes + index, count, flush);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override int GetCharCount(byte* bytes, int count, bool flush)
+ {
+ // Validate parameters
+ if (bytes == null)
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Remember the flush
+ this.m_mustFlush = flush;
+ this.m_throwOnOverflow = true;
+
+ // By default just call the encoding version, no flush by default
+ return m_encoding.GetCharCount(bytes, count, this);
+ }
+
+ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, bool flush)
+ {
+ // Validate Parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if ( bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (charIndex < 0 || charIndex > chars.Length)
+ throw new ArgumentOutOfRangeException("charIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_Index"));
+
+ Contract.EndContractBlock();
+
+ // Avoid empty input fixed problem
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ int charCount = chars.Length - charIndex;
+ if (chars.Length == 0)
+ chars = new char[1];
+
+ // Just call pointer version
+ fixed (byte* pBytes = bytes)
+ fixed (char* pChars = chars)
+ // Remember that charCount is # to decode, not size of array
+ return GetChars(pBytes + byteIndex, byteCount,
+ pChars + charIndex, charCount, flush);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush)
+ {
+ // Validate parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Remember our flush
+ m_mustFlush = flush;
+ m_throwOnOverflow = true;
+
+ // By default just call the encoding's version
+ return m_encoding.GetChars(bytes, byteCount, chars, charCount, this);
+ }
+
+ // This method is used when the output buffer might not be big enough.
+ // Just call the pointer version. (This gets chars)
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe void Convert(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ // Validate parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException((bytes == null ? "bytes" : "chars"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ Contract.EndContractBlock();
+
+ // Avoid empty input problem
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+ if (chars.Length == 0)
+ chars = new char[1];
+
+ // Just call the pointer version (public overrides can't do this)
+ fixed (byte* pBytes = bytes)
+ {
+ fixed (char* pChars = chars)
+ {
+ Convert(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, flush,
+ out bytesUsed, out charsUsed, out completed);
+ }
+ }
+ }
+
+ // This is the version that used pointers. We call the base encoding worker function
+ // after setting our appropriate internal variables. This is getting chars
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override void Convert(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush,
+ out int bytesUsed, out int charsUsed, out bool completed)
+ {
+ // Validate input parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? "chars" : "bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // We don't want to throw
+ this.m_mustFlush = flush;
+ this.m_throwOnOverflow = false;
+ this.m_bytesUsed = 0;
+
+ // Do conversion
+ charsUsed = this.m_encoding.GetChars(bytes, byteCount, chars, charCount, this);
+ bytesUsed = this.m_bytesUsed;
+
+ // Its completed if they've used what they wanted AND if they didn't want flush or if we are flushed
+ completed = (bytesUsed == byteCount) && (!flush || !this.HasState) &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0);
+
+ // Our data thingys are now full, we can return
+ }
+
+ public bool MustFlush
+ {
+ get
+ {
+ return m_mustFlush;
+ }
+ }
+
+ // Anything left in our decoder?
+ internal virtual bool HasState
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ // Allow encoding to clear our must flush instead of throwing (in ThrowCharsOverflow)
+ internal void ClearMustFlush()
+ {
+ m_mustFlush = false;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs
new file mode 100644
index 0000000000..c732d15816
--- /dev/null
+++ b/src/mscorlib/src/System/Text/DecoderReplacementFallback.cs
@@ -0,0 +1,209 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public sealed class DecoderReplacementFallback : DecoderFallback
+ {
+ // Our variables
+ private String strDefault;
+
+ // Construction. Default replacement fallback uses no best fit and ? replacement string
+ public DecoderReplacementFallback() : this("?")
+ {
+ }
+
+ public DecoderReplacementFallback(String replacement)
+ {
+ if (replacement == null)
+ throw new ArgumentNullException("replacement");
+ Contract.EndContractBlock();
+
+ // Make sure it doesn't have bad surrogate pairs
+ bool bFoundHigh=false;
+ for (int i = 0; i < replacement.Length; i++)
+ {
+ // Found a surrogate?
+ if (Char.IsSurrogate(replacement,i))
+ {
+ // High or Low?
+ if (Char.IsHighSurrogate(replacement, i))
+ {
+ // if already had a high one, stop
+ if (bFoundHigh)
+ break; // break & throw at the bFoundHIgh below
+ bFoundHigh = true;
+ }
+ else
+ {
+ // Low, did we have a high?
+ if (!bFoundHigh)
+ {
+ // Didn't have one, make if fail when we stop
+ bFoundHigh = true;
+ break;
+ }
+
+ // Clear flag
+ bFoundHigh = false;
+ }
+ }
+ // If last was high we're in trouble (not surrogate so not low surrogate, so break)
+ else if (bFoundHigh)
+ break;
+ }
+ if (bFoundHigh)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement"));
+
+ strDefault = replacement;
+ }
+
+ public String DefaultString
+ {
+ get
+ {
+ return strDefault;
+ }
+ }
+
+ public override DecoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new DecoderReplacementFallbackBuffer(this);
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return strDefault.Length;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ DecoderReplacementFallback that = value as DecoderReplacementFallback;
+ if (that != null)
+ {
+ return (this.strDefault == that.strDefault);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return strDefault.GetHashCode();
+ }
+ }
+
+
+
+ public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
+ {
+ // Store our default string
+ private String strDefault;
+ int fallbackCount = -1;
+ int fallbackIndex = -1;
+
+ // Construction
+ public DecoderReplacementFallbackBuffer(DecoderReplacementFallback fallback)
+ {
+ this.strDefault = fallback.DefaultString;
+ }
+
+ // Fallback Methods
+ public override bool Fallback(byte[] bytesUnknown, int index)
+ {
+ // We expect no previous fallback in our buffer
+ // We can't call recursively but others might (note, we don't test on last char!!!)
+ if (fallbackCount >= 1)
+ {
+ ThrowLastBytesRecursive(bytesUnknown);
+ }
+
+ // Go ahead and get our fallback
+ if (strDefault.Length == 0)
+ return false;
+
+ fallbackCount = strDefault.Length;
+ fallbackIndex = -1;
+
+ return true;
+ }
+
+ public override char GetNextChar()
+ {
+ // We want it to get < 0 because == 0 means that the current/last character is a fallback
+ // and we need to detect recursion. We could have a flag but we already have this counter.
+ fallbackCount--;
+ fallbackIndex++;
+
+ // Do we have anything left? 0 is now last fallback char, negative is nothing left
+ if (fallbackCount < 0)
+ return '\0';
+
+ // Need to get it out of the buffer.
+ // Make sure it didn't wrap from the fast count-- path
+ if (fallbackCount == int.MaxValue)
+ {
+ fallbackCount = -1;
+ return '\0';
+ }
+
+ // Now make sure its in the expected range
+ Contract.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0,
+ "Index exceeds buffer range");
+
+ return strDefault[fallbackIndex];
+ }
+
+ public override bool MovePrevious()
+ {
+ // Back up one, only if we just processed the last character (or earlier)
+ if (fallbackCount >= -1 && fallbackIndex >= 0)
+ {
+ fallbackIndex--;
+ fallbackCount++;
+ return true;
+ }
+
+ // Return false 'cause we couldn't do it.
+ return false;
+ }
+
+ // How many characters left to output?
+ public override int Remaining
+ {
+ get
+ {
+ // Our count is 0 for 1 character left.
+ return (fallbackCount < 0) ? 0 : fallbackCount;
+ }
+ }
+
+ // Clear the buffer
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe void Reset()
+ {
+ fallbackCount = -1;
+ fallbackIndex = -1;
+ byteStart = null;
+ }
+
+ // This version just counts the fallback and doesn't actually copy anything.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes)
+ // Right now this has both bytes and bytes[], since we might have extra bytes, hence the
+ // array, and we might need the index, hence the byte*
+ {
+ // return our replacement string Length
+ return strDefault.Length;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/EUCJPEncoding.cs b/src/mscorlib/src/System/Text/EUCJPEncoding.cs
new file mode 100644
index 0000000000..7c90caec0b
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EUCJPEncoding.cs
@@ -0,0 +1,186 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if FEATURE_CODEPAGES_FILE // requires BaseCodePageEncooding
+namespace System.Text
+{
+ using System.Text;
+ using System.Globalization;
+
+ // EUCJPEncoding
+ //
+ // EUC-JP Encoding (51932)
+ //
+ // EUC-JP has the following code points:
+ // 00-7F - ASCII
+ // 80-8D & 90-9F - Control. (Like Unicode, except for 8e and 8f)
+ // A1-FE, A1-FE - 2 byte JIS X 0208 range.
+ // 8E, A1-DF - 2 byte half-width Katakana
+ // 8F, A1-FE, A1-FE - 3 byte JIX X 0212 range. WE DON'T USE JIS 0212!!!
+ //
+ // New thoughts:
+ // Fixing windows 20932 code page so that all characters can be looked up there.
+ //
+ // Old thoughts:
+ // Windows NLS uses a special CP20932 for EUC-JP, but it is not used by mlang. Windows
+ // Maps the 3 byte ranges to the 2 byte CP20932 by masking the 2nd byte with & 0x7F.
+ // MLang uses the native windows 932 code page, which is more reliable, however the code points
+ // don't line up as nicely as the 20932 code page, however it doesn't have JIS X 0212 support.
+ //
+ // So what we do is:
+ // 1. For ASCII, leave it alone
+ // 2. For half-width Katakana, use the leading byte and convert with 20936 code page.
+ // 3. For JIS X 0208, Use the leading & trailing bytes with 20936 code page
+ // 4. For JIS X 0212, Remove the lead byte, & 0xFF7F, and use the CP20936 table to convert.
+ //
+ // Regarding Normalization:
+ // Forms KC & KD are precluded because of things like halfwidth Katakana that has compatibility mappings
+ // Form D is precluded because of 0x00a8, which changes to space + dierises.
+ //
+ // I think that IsAlwaysNormalized should probably return true for form C (but not certain)
+ //
+ // NOTE: We don't use JIS 0212 so we are basically a DBCS code page, we just have to modify
+ // the 932 table we're basing this on.
+ //
+
+ using System;
+
+ [Serializable]
+ internal class EUCJPEncoding : DBCSCodePageEncoding
+ {
+ // This pretends to be CP 932 as far as memory tables are concerned.
+ [System.Security.SecurityCritical] // auto-generated
+ public EUCJPEncoding() : base(51932, 932)
+ {
+ this.m_bUseMlangTypeForSerialization = true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe override String GetMemorySectionName()
+ {
+ int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage;
+
+ String strName = String.Format(CultureInfo.InvariantCulture, "CodePage_{0}_{1}_{2}_{3}_{4}_EUCJP",
+ iUseCodePage, this.pCodePage->VersionMajor, this.pCodePage->VersionMinor,
+ this.pCodePage->VersionRevision, this.pCodePage->VersionBuild);
+
+ return strName;
+ }
+
+ // Clean up characters for EUC-JP code pages, etc.
+ protected override bool CleanUpBytes(ref int bytes)
+ {
+ if (bytes >= 0x100)
+ {
+ // map extended char (0xfa40-0xfc4b) to a special range
+ // (ported from mlang)
+ if (bytes >= 0xfa40 && bytes <= 0xfc4b)
+ {
+ if ( bytes >= 0xfa40 && bytes <= 0xfa5b )
+ {
+ if ( bytes <= 0xfa49 )
+ bytes = bytes - 0x0b51 ;
+ else if ( bytes >= 0xfa4a && bytes <= 0xfa53 )
+ bytes = bytes - 0x072f6 ;
+ else if ( bytes >= 0xfa54 && bytes <= 0xfa57 )
+ bytes = bytes - 0x0b5b ;
+ else if ( bytes == 0xfa58 )
+ bytes = 0x878a ;
+ else if ( bytes == 0xfa59 )
+ bytes = 0x8782 ;
+ else if ( bytes == 0xfa5a )
+ bytes = 0x8784 ;
+ else if ( bytes == 0xfa5b )
+ bytes = 0x879a ;
+ }
+ else if ( bytes >= 0xfa5c && bytes <= 0xfc4b )
+ {
+ byte tc = unchecked((byte)bytes);
+ if ( tc < 0x5c )
+ bytes = bytes - 0x0d5f;
+ else if ( tc >= 0x80 && tc <= 0x9B )
+ bytes = bytes - 0x0d1d;
+ else
+ bytes = bytes - 0x0d1c;
+ }
+ }
+
+ // Convert 932 code page to 20932 like code page range
+ // (also ported from mlang)
+ byte bLead = unchecked((byte)(bytes >> 8));
+ byte bTrail = unchecked((byte)bytes);
+
+ bLead -= ((bLead > (byte)0x9f) ? (byte)0xb1 : (byte)0x71);
+ bLead = (byte)((bLead << 1) + 1);
+ if (bTrail > (byte)0x9e)
+ {
+ bTrail -= (byte)0x7e;
+ bLead++;
+ }
+ else
+ {
+ if (bTrail > (byte)0x7e)
+ bTrail--;
+ bTrail -= (byte)0x1f;
+ }
+
+ bytes = ((int)bLead) << 8 | (int)bTrail | 0x8080;
+
+ // // Don't step on our katakana special plane, if katakana space return false.
+ // if (bytes >= 0x8E00 && bytes <= 0x8EFF)
+ // return false;
+
+ // Don't step out of our allocated lead byte area.
+ // All DBCS lead and trail bytes should be >= 0xa1 and <= 0xfe
+ if ((bytes & 0xFF00) < 0xa100 || (bytes & 0xFF00) > 0xfe00 ||
+ (bytes & 0xFF) < 0xa1 || (bytes & 0xFF) > 0xfe)
+ return false;
+
+ // WARNING: Our funky mapping allows illegal values, which we continue to use
+ // so that we're compatible with Everett.
+ }
+ else
+ {
+ // For 51932 1/2 Katakana gets a 0x8E lead byte
+ // Adjust 1/2 Katakana
+ if (bytes >= 0xa1 && bytes <= 0xdf)
+ {
+ bytes |= 0x8E00;
+ return true;
+ }
+
+ // 0x81-0x9f and 0xe0-0xfc CP 932
+ // 0x8e and 0xa1-0xfe CP 20932 (we don't use 8e though)
+ // b0-df is 1/2 Katakana
+ // So 81-9f & e0-fc are 932 lead bytes, a1-fe are our lead bytes
+ // so ignore everything above 0x80 except 0xa0 and 0xff
+ if (bytes >= 0x81 && bytes != 0xa0 && bytes != 0xff)
+ {
+ // We set diffent lead bytes later, so just return false
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected override unsafe void CleanUpEndBytes(char* chars)
+ {
+ // Need to special case CP 51932
+ // 0x81-0x9f and 0xe0-0xfc CP 932
+ // 0x8e and 0xa1-0xfe CP 20932
+ // 0x10 and 0x21-0x9? Us (remapping 932)
+ // b0-df is 1/2 Katakana (trail byte)
+
+ // A1-FE are DBCS code points
+ for (int i = 0xA1; i <= 0xFE; i++)
+ chars[i] = LEAD_BYTE_CHAR;
+
+ // And 8E is lead byte for Katakana (already set)
+ chars[0x8e] = LEAD_BYTE_CHAR;
+ }
+ }
+}
+#endif // FEATURE_CODEPAGES_FILE
diff --git a/src/mscorlib/src/System/Text/Encoder.cs b/src/mscorlib/src/System/Text/Encoder.cs
new file mode 100644
index 0000000000..d223dd9d46
--- /dev/null
+++ b/src/mscorlib/src/System/Text/Encoder.cs
@@ -0,0 +1,342 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System.Runtime.Serialization;
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ // An Encoder is used to encode a sequence of blocks of characters into
+ // a sequence of blocks of bytes. Following instantiation of an encoder,
+ // sequential blocks of characters are converted into blocks of bytes through
+ // calls to the GetBytes method. The encoder maintains state between the
+ // conversions, allowing it to correctly encode character sequences that span
+ // adjacent blocks.
+ //
+ // Instances of specific implementations of the Encoder abstract base
+ // class are typically obtained through calls to the GetEncoder method
+ // of Encoding objects.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public abstract class Encoder
+ {
+ internal EncoderFallback m_fallback = null;
+
+ [NonSerialized]
+ internal EncoderFallbackBuffer m_fallbackBuffer = null;
+
+ internal void SerializeEncoder(SerializationInfo info)
+ {
+ info.AddValue("m_fallback", this.m_fallback);
+ }
+
+ protected Encoder()
+ {
+ // We don't call default reset because default reset probably isn't good if we aren't initialized.
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public EncoderFallback Fallback
+ {
+ get
+ {
+ return m_fallback;
+ }
+
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ // Can't change fallback if buffer is wrong
+ if (m_fallbackBuffer != null && m_fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_FallbackBufferNotEmpty"), "value");
+
+ m_fallback = value;
+ m_fallbackBuffer = null;
+ }
+ }
+
+ // Note: we don't test for threading here because async access to Encoders and Decoders
+ // doesn't work anyway.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public EncoderFallbackBuffer FallbackBuffer
+ {
+ get
+ {
+ if (m_fallbackBuffer == null)
+ {
+ if (m_fallback != null)
+ m_fallbackBuffer = m_fallback.CreateFallbackBuffer();
+ else
+ m_fallbackBuffer = EncoderFallback.ReplacementFallback.CreateFallbackBuffer();
+ }
+
+ return m_fallbackBuffer;
+ }
+ }
+
+ internal bool InternalHasFallbackBuffer
+ {
+ get
+ {
+ return m_fallbackBuffer != null;
+ }
+ }
+
+ // Reset the Encoder
+ //
+ // Normally if we call GetBytes() and an error is thrown we don't change the state of the encoder. This
+ // would allow the caller to correct the error condition and try again (such as if they need a bigger buffer.)
+ //
+ // If the caller doesn't want to try again after GetBytes() throws an error, then they need to call Reset().
+ //
+ // Virtual implimentation has to call GetBytes with flush and a big enough buffer to clear a 0 char string
+ // We avoid GetMaxByteCount() because a) we can't call the base encoder and b) it might be really big.
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual void Reset()
+ {
+ char[] charTemp = {};
+ byte[] byteTemp = new byte[GetByteCount(charTemp, 0, 0, true)];
+ GetBytes(charTemp, 0, 0, byteTemp, 0, true);
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Returns the number of bytes the next call to GetBytes will
+ // produce if presented with the given range of characters and the given
+ // value of the flush parameter. The returned value takes into
+ // account the state in which the encoder was left following the last call
+ // to GetBytes. The state of the encoder is not affected by a call
+ // to this method.
+ //
+ public abstract int GetByteCount(char[] chars, int index, int count, bool flush);
+
+ // We expect this to be the workhorse for NLS encodings
+ // unfortunately for existing overrides, it has to call the [] version,
+ // which is really slow, so avoid this method if you might be calling external encodings.
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetByteCount(char* chars, int count, bool flush)
+ {
+ // Validate input parameters
+ if (chars == null)
+ throw new ArgumentNullException("chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ char[] arrChar = new char[count];
+ int index;
+
+ for (index = 0; index < count; index++)
+ arrChar[index] = chars[index];
+
+ return GetByteCount(arrChar, 0, count, flush);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. The method encodes charCount characters from
+ // chars starting at index charIndex, storing the resulting
+ // bytes in bytes starting at index byteIndex. The encoding
+ // takes into account the state in which the encoder was left following the
+ // last call to this method. The flush parameter indicates whether
+ // the encoder should flush any shift-states and partial characters at the
+ // end of the conversion. To ensure correct termination of a sequence of
+ // blocks of encoded bytes, the last call to GetBytes should specify
+ // a value of true for the flush parameter.
+ //
+ // An exception occurs if the byte array is not large enough to hold the
+ // complete encoding of the characters. The GetByteCount method can
+ // be used to determine the exact number of bytes that will be produced for
+ // a given range of characters. Alternatively, the GetMaxByteCount
+ // method of the Encoding that produced this encoder can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+ //
+ public abstract int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, bool flush);
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: If this breaks it could be a security threat. Obviously we
+ // call this internally, so you need to make sure that your pointers, counts
+ // and indexes are correct when you call this method.
+ //
+ // In addition, we have internal code, which will be marked as "safe" calling
+ // this code. However this code is dependent upon the implimentation of an
+ // external GetBytes() method, which could be overridden by a third party and
+ // the results of which cannot be guaranteed. We use that result to copy
+ // the byte[] to our byte* output buffer. If the result count was wrong, we
+ // could easily overflow our output buffer. Therefore we do an extra test
+ // when we copy the buffer so that we don't overflow byteCount either.
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, bool flush)
+ {
+ // Validate input parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get the char array to convert
+ char[] arrChar = new char[charCount];
+
+ int index;
+ for (index = 0; index < charCount; index++)
+ arrChar[index] = chars[index];
+
+ // Get the byte array to fill
+ byte[] arrByte = new byte[byteCount];
+
+ // Do the work
+ int result = GetBytes(arrChar, 0, charCount, arrByte, 0, flush);
+
+ Contract.Assert(result <= byteCount, "Returned more bytes than we have space for");
+
+ // Copy the byte array
+ // WARNING: We MUST make sure that we don't copy too many bytes. We can't
+ // rely on result because it could be a 3rd party implimentation. We need
+ // to make sure we never copy more than byteCount bytes no matter the value
+ // of result
+ if (result < byteCount)
+ byteCount = result;
+
+ // Don't copy too many bytes!
+ for (index = 0; index < byteCount; index++)
+ bytes[index] = arrByte[index];
+
+ return byteCount;
+ }
+
+ // This method is used to avoid running out of output buffer space.
+ // It will encode until it runs out of chars, and then it will return
+ // true if it the entire input was converted. In either case it
+ // will also return the number of converted chars and output bytes used.
+ // It will only throw a buffer overflow exception if the entire lenght of bytes[] is
+ // too small to store the next byte. (like 0 or maybe 1 or 4 for some encodings)
+ // We're done processing this buffer only if completed returns true.
+ //
+ // Might consider checking Max...Count to avoid the extra counting step.
+ //
+ // Note that if all of the input chars are not consumed, then we'll do a /2, which means
+ // that its likely that we didn't consume as many chars as we could have. For some
+ // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream)
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual void Convert(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ // Validate parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ Contract.EndContractBlock();
+
+ charsUsed = charCount;
+
+ // Its easy to do if it won't overrun our buffer.
+ // Note: We don't want to call unsafe version because that might be an untrusted version
+ // which could be really unsafe and we don't want to mix it up.
+ while (charsUsed > 0)
+ {
+ if (GetByteCount(chars, charIndex, charsUsed, flush) <= byteCount)
+ {
+ bytesUsed = GetBytes(chars, charIndex, charsUsed, bytes, byteIndex, flush);
+ completed = (charsUsed == charCount &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0));
+ return;
+ }
+
+ // Try again with 1/2 the count, won't flush then 'cause won't read it all
+ flush = false;
+ charsUsed /= 2;
+ }
+
+ // Oops, we didn't have anything, we'll have to throw an overflow
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConversionOverflow"));
+ }
+
+ // Same thing, but using pointers
+ //
+ // Might consider checking Max...Count to avoid the extra counting step.
+ //
+ // Note that if all of the input chars are not consumed, then we'll do a /2, which means
+ // that its likely that we didn't consume as many chars as we could have. For some
+ // applications this could be slow. (Like trying to exactly fill an output buffer from a bigger stream)
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe void Convert(char* chars, int charCount,
+ byte* bytes, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ // Validate input parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get ready to do it
+ charsUsed = charCount;
+
+ // Its easy to do if it won't overrun our buffer.
+ while (charsUsed > 0)
+ {
+ if (GetByteCount(chars, charsUsed, flush) <= byteCount)
+ {
+ bytesUsed = GetBytes(chars, charsUsed, bytes, byteCount, flush);
+ completed = (charsUsed == charCount &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0));
+ return;
+ }
+
+ // Try again with 1/2 the count, won't flush then 'cause won't read it all
+ flush = false;
+ charsUsed /= 2;
+ }
+
+ // Oops, we didn't have anything, we'll have to throw an overflow
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConversionOverflow"));
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs b/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs
new file mode 100644
index 0000000000..352e9695cf
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncoderBestFitFallback.cs
@@ -0,0 +1,247 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// This is used internally to create best fit behavior as per the original windows best fit behavior.
+//
+namespace System.Text
+{
+ using System;
+ using System.Globalization;
+ using System.Text;
+ using System.Threading;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ internal class InternalEncoderBestFitFallback : EncoderFallback
+ {
+ // Our variables
+ internal Encoding encoding = null;
+ internal char[] arrayBestFit = null;
+
+ internal InternalEncoderBestFitFallback(Encoding encoding)
+ {
+ // Need to load our replacement characters table.
+ this.encoding = encoding;
+ this.bIsMicrosoftBestFitFallback = true;
+ }
+
+ public override EncoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new InternalEncoderBestFitFallbackBuffer(this);
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ InternalEncoderBestFitFallback that = value as InternalEncoderBestFitFallback;
+ if (that != null)
+ {
+ return (this.encoding.CodePage == that.encoding.CodePage);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.encoding.CodePage;
+ }
+ }
+
+ internal sealed class InternalEncoderBestFitFallbackBuffer : EncoderFallbackBuffer
+ {
+ // Our variables
+ private char cBestFit = '\0';
+ private InternalEncoderBestFitFallback oFallback;
+ private int iCount = -1;
+ private int iSize;
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Constructor
+ public InternalEncoderBestFitFallbackBuffer(InternalEncoderBestFitFallback fallback)
+ {
+ this.oFallback = fallback;
+
+ if (oFallback.arrayBestFit == null)
+ {
+ // Lock so we don't confuse ourselves.
+ lock(InternalSyncObject)
+ {
+ // Double check before we do it again.
+ if (oFallback.arrayBestFit == null)
+ oFallback.arrayBestFit = fallback.encoding.GetBestFitUnicodeToBytesData();
+ }
+ }
+ }
+
+ // Fallback methods
+ public override bool Fallback(char charUnknown, int index)
+ {
+ // If we had a buffer already we're being recursive, throw, it's probably at the suspect
+ // character in our array.
+ // Shouldn't be able to get here for all of our code pages, table would have to be messed up.
+ Contract.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(non surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback");
+
+ iCount = iSize = 1;
+ cBestFit = TryBestFit(charUnknown);
+ if (cBestFit == '\0')
+ cBestFit = '?';
+
+ return true;
+ }
+
+ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
+ {
+ // Double check input surrogate pair
+ if (!Char.IsHighSurrogate(charUnknownHigh))
+ throw new ArgumentOutOfRangeException("charUnknownHigh",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xD800, 0xDBFF));
+
+ if (!Char.IsLowSurrogate(charUnknownLow))
+ throw new ArgumentOutOfRangeException("CharUnknownLow",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xDC00, 0xDFFF));
+ Contract.EndContractBlock();
+
+ // If we had a buffer already we're being recursive, throw, it's probably at the suspect
+ // character in our array. 0 is processing last character, < 0 is not falling back
+ // Shouldn't be able to get here, table would have to be messed up.
+ Contract.Assert(iCount < 1, "[InternalEncoderBestFitFallbackBuffer.Fallback(surrogate)] Fallback char " + ((int)cBestFit).ToString("X4", CultureInfo.InvariantCulture) + " caused recursive fallback");
+
+ // Go ahead and get our fallback, surrogates don't have best fit
+ cBestFit = '?';
+ iCount = iSize = 2;
+
+ return true;
+ }
+
+ // Default version is overridden in EncoderReplacementFallback.cs
+ public override char GetNextChar()
+ {
+ // We want it to get < 0 because == 0 means that the current/last character is a fallback
+ // and we need to detect recursion. We could have a flag but we already have this counter.
+ iCount--;
+
+ // Do we have anything left? 0 is now last fallback char, negative is nothing left
+ if (iCount < 0)
+ return '\0';
+
+ // Need to get it out of the buffer.
+ // Make sure it didn't wrap from the fast count-- path
+ if (iCount == int.MaxValue)
+ {
+ iCount = -1;
+ return '\0';
+ }
+
+ // Return the best fit character
+ return cBestFit;
+ }
+
+ public override bool MovePrevious()
+ {
+ // Exception fallback doesn't have anywhere to back up to.
+ if (iCount >= 0)
+ iCount++;
+
+ // Return true if we could do it.
+ return (iCount >= 0 && iCount <= iSize);
+ }
+
+
+ // How many characters left to output?
+ public override int Remaining
+ {
+ get
+ {
+ return (iCount > 0) ? iCount : 0;
+ }
+ }
+
+ // Clear the buffer
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ public override unsafe void Reset()
+ {
+ iCount = -1;
+ charStart = null;
+ bFallingBack = false;
+ }
+
+ // private helper methods
+ private char TryBestFit(char cUnknown)
+ {
+ // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array
+ int lowBound = 0;
+ int highBound = oFallback.arrayBestFit.Length;
+ int index;
+
+ // Binary search the array
+ int iDiff;
+ while ((iDiff = (highBound - lowBound)) > 6)
+ {
+ // Look in the middle, which is complicated by the fact that we have 2 #s for each pair,
+ // so we don't want index to be odd because we want to be on word boundaries.
+ // Also note that index can never == highBound (because diff is rounded down)
+ index = ((iDiff / 2) + lowBound) & 0xFFFE;
+
+ char cTest = oFallback.arrayBestFit[index];
+ if (cTest == cUnknown)
+ {
+ // We found it
+ Contract.Assert(index + 1 < oFallback.arrayBestFit.Length,
+ "[InternalEncoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array");
+ return oFallback.arrayBestFit[index + 1];
+ }
+ else if (cTest < cUnknown)
+ {
+ // We weren't high enough
+ lowBound = index;
+ }
+ else
+ {
+ // We weren't low enough
+ highBound = index;
+ }
+ }
+
+ for (index = lowBound; index < highBound; index += 2)
+ {
+ if (oFallback.arrayBestFit[index] == cUnknown)
+ {
+ // We found it
+ Contract.Assert(index + 1 < oFallback.arrayBestFit.Length,
+ "[InternalEncoderBestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array");
+ return oFallback.arrayBestFit[index + 1];
+ }
+ }
+
+ // Char wasn't in our table
+ return '\0';
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs b/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs
new file mode 100644
index 0000000000..5ab51cb6dd
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncoderExceptionFallback.cs
@@ -0,0 +1,203 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public sealed class EncoderExceptionFallback : EncoderFallback
+ {
+ // Construction
+ public EncoderExceptionFallback()
+ {
+ }
+
+ public override EncoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new EncoderExceptionFallbackBuffer();
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return 0;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ EncoderExceptionFallback that = value as EncoderExceptionFallback;
+ if (that != null)
+ {
+ return (true);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return 654;
+ }
+ }
+
+
+ public sealed class EncoderExceptionFallbackBuffer : EncoderFallbackBuffer
+ {
+ public EncoderExceptionFallbackBuffer(){}
+ public override bool Fallback(char charUnknown, int index)
+ {
+ // Fall back our char
+ throw new EncoderFallbackException(
+ Environment.GetResourceString("Argument_InvalidCodePageConversionIndex",
+ (int)charUnknown, index), charUnknown, index);
+ }
+
+ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
+ {
+ if (!Char.IsHighSurrogate(charUnknownHigh))
+ {
+ throw new ArgumentOutOfRangeException("charUnknownHigh",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xD800, 0xDBFF));
+ }
+ if (!Char.IsLowSurrogate(charUnknownLow))
+ {
+ throw new ArgumentOutOfRangeException("CharUnknownLow",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xDC00, 0xDFFF));
+ }
+ Contract.EndContractBlock();
+
+ int iTemp = Char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
+
+ // Fall back our char
+ throw new EncoderFallbackException(
+ Environment.GetResourceString("Argument_InvalidCodePageConversionIndex",
+ iTemp, index), charUnknownHigh, charUnknownLow, index);
+ }
+
+ public override char GetNextChar()
+ {
+ return (char)0;
+ }
+
+ public override bool MovePrevious()
+ {
+ // Exception fallback doesn't have anywhere to back up to.
+ return false;
+ }
+
+ // Exceptions are always empty
+ public override int Remaining
+ {
+ get
+ {
+ return 0;
+ }
+ }
+ }
+
+ [Serializable]
+ public sealed class EncoderFallbackException : ArgumentException
+ {
+ char charUnknown;
+ char charUnknownHigh;
+ char charUnknownLow;
+ int index;
+
+ public EncoderFallbackException()
+ : base(Environment.GetResourceString("Arg_ArgumentException"))
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public EncoderFallbackException(String message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ public EncoderFallbackException(String message, Exception innerException)
+ : base(message, innerException)
+ {
+ SetErrorCode(__HResults.COR_E_ARGUMENT);
+ }
+
+ internal EncoderFallbackException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ internal EncoderFallbackException(
+ String message, char charUnknown, int index) : base(message)
+ {
+ this.charUnknown = charUnknown;
+ this.index = index;
+ }
+
+ internal EncoderFallbackException(
+ String message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
+ {
+ if (!Char.IsHighSurrogate(charUnknownHigh))
+ {
+ throw new ArgumentOutOfRangeException("charUnknownHigh",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xD800, 0xDBFF));
+ }
+ if (!Char.IsLowSurrogate(charUnknownLow))
+ {
+ throw new ArgumentOutOfRangeException("CharUnknownLow",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xDC00, 0xDFFF));
+ }
+ Contract.EndContractBlock();
+
+ this.charUnknownHigh = charUnknownHigh;
+ this.charUnknownLow = charUnknownLow;
+ this.index = index;
+ }
+
+ public char CharUnknown
+ {
+ get
+ {
+ return (charUnknown);
+ }
+ }
+
+ public char CharUnknownHigh
+ {
+ get
+ {
+ return (charUnknownHigh);
+ }
+ }
+
+ public char CharUnknownLow
+ {
+ get
+ {
+ return (charUnknownLow);
+ }
+ }
+
+ public int Index
+ {
+ get
+ {
+ return index;
+ }
+ }
+
+ // Return true if the unknown character is a surrogate pair.
+ public bool IsUnknownSurrogate()
+ {
+ return (this.charUnknownHigh != '\0');
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncoderFallback.cs b/src/mscorlib/src/System/Text/EncoderFallback.cs
new file mode 100644
index 0000000000..4b170414d5
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncoderFallback.cs
@@ -0,0 +1,236 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Security;
+using System.Threading;
+using System.Diagnostics.Contracts;
+
+namespace System.Text
+{
+ [Serializable]
+ public abstract class EncoderFallback
+ {
+// disable csharp compiler warning #0414: field assigned unused value
+#pragma warning disable 0414
+ internal bool bIsMicrosoftBestFitFallback = false;
+#pragma warning restore 0414
+
+ private static volatile EncoderFallback replacementFallback; // Default fallback, uses no best fit & "?"
+ private static volatile EncoderFallback exceptionFallback;
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Get each of our generic fallbacks.
+
+ public static EncoderFallback ReplacementFallback
+ {
+ get
+ {
+ if (replacementFallback == null)
+ lock(InternalSyncObject)
+ if (replacementFallback == null)
+ replacementFallback = new EncoderReplacementFallback();
+
+ return replacementFallback;
+ }
+ }
+
+
+ public static EncoderFallback ExceptionFallback
+ {
+ get
+ {
+ if (exceptionFallback == null)
+ lock(InternalSyncObject)
+ if (exceptionFallback == null)
+ exceptionFallback = new EncoderExceptionFallback();
+
+ return exceptionFallback;
+ }
+ }
+
+ // Fallback
+ //
+ // Return the appropriate unicode string alternative to the character that need to fall back.
+ // Most implimentations will be:
+ // return new MyCustomEncoderFallbackBuffer(this);
+
+ public abstract EncoderFallbackBuffer CreateFallbackBuffer();
+
+ // Maximum number of characters that this instance of this fallback could return
+
+ public abstract int MaxCharCount { get; }
+ }
+
+
+ public abstract class EncoderFallbackBuffer
+ {
+ // Most implementations will probably need an implemenation-specific constructor
+
+ // Public methods that cannot be overriden that let us do our fallback thing
+ // These wrap the internal methods so that we can check for people doing stuff that is incorrect
+
+ public abstract bool Fallback(char charUnknown, int index);
+
+ public abstract bool Fallback(char charUnknownHigh, char charUnknownLow, int index);
+
+ // Get next character
+
+ public abstract char GetNextChar();
+
+ // Back up a character
+
+ public abstract bool MovePrevious();
+
+ // How many chars left in this fallback?
+
+ public abstract int Remaining { get; }
+
+ // Not sure if this should be public or not.
+ // Clear the buffer
+
+ public virtual void Reset()
+ {
+ while (GetNextChar() != (char)0);
+ }
+
+ // Internal items to help us figure out what we're doing as far as error messages, etc.
+ // These help us with our performance and messages internally
+ [SecurityCritical]
+ internal unsafe char* charStart;
+ [SecurityCritical]
+ internal unsafe char* charEnd;
+ internal EncoderNLS encoder;
+ internal bool setEncoder;
+ internal bool bUsedEncoder;
+ internal bool bFallingBack = false;
+ internal int iRecursionCount = 0;
+ private const int iMaxRecursion = 250;
+
+ // Internal Reset
+ // For example, what if someone fails a conversion and wants to reset one of our fallback buffers?
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void InternalReset()
+ {
+ charStart = null;
+ bFallingBack = false;
+ iRecursionCount = 0;
+ Reset();
+ }
+
+ // Set the above values
+ // This can't be part of the constructor because EncoderFallbacks would have to know how to impliment these.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void InternalInitialize(char* charStart, char* charEnd, EncoderNLS encoder, bool setEncoder)
+ {
+ this.charStart = charStart;
+ this.charEnd = charEnd;
+ this.encoder = encoder;
+ this.setEncoder = setEncoder;
+ this.bUsedEncoder = false;
+ this.bFallingBack = false;
+ this.iRecursionCount = 0;
+ }
+
+ internal char InternalGetNextChar()
+ {
+ char ch = GetNextChar();
+ bFallingBack = (ch != 0);
+ if (ch == 0) iRecursionCount = 0;
+ return ch;
+ }
+
+ // Fallback the current character using the remaining buffer and encoder if necessary
+ // This can only be called by our encodings (other have to use the public fallback methods), so
+ // we can use our EncoderNLS here too.
+ // setEncoder is true if we're calling from a GetBytes method, false if we're calling from a GetByteCount
+ //
+ // Note that this could also change the contents of this.encoder, which is the same
+ // object that the caller is using, so the caller could mess up the encoder for us
+ // if they aren't careful.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe virtual bool InternalFallback(char ch, ref char* chars)
+ {
+ // Shouldn't have null charStart
+ Contract.Assert(charStart != null,
+ "[EncoderFallback.InternalFallbackBuffer]Fallback buffer is not initialized");
+
+ // Get our index, remember chars was preincremented to point at next char, so have to -1
+ int index = (int)(chars - charStart) - 1;
+
+ // See if it was a high surrogate
+ if (Char.IsHighSurrogate(ch))
+ {
+ // See if there's a low surrogate to go with it
+ if (chars >= this.charEnd)
+ {
+ // Nothing left in input buffer
+ // No input, return 0 if mustflush is false
+ if (this.encoder != null && !this.encoder.MustFlush)
+ {
+ // Done, nothing to fallback
+ if (this.setEncoder)
+ {
+ bUsedEncoder = true;
+ this.encoder.charLeftOver = ch;
+ }
+ bFallingBack = false;
+ return false;
+ }
+ }
+ else
+ {
+ // Might have a low surrogate
+ char cNext = *chars;
+ if (Char.IsLowSurrogate(cNext))
+ {
+ // If already falling back then fail
+ if (bFallingBack && iRecursionCount++ > iMaxRecursion)
+ ThrowLastCharRecursive(Char.ConvertToUtf32(ch, cNext));
+
+ // Next is a surrogate, add it as surrogate pair, and increment chars
+ chars++;
+ bFallingBack = Fallback(ch, cNext, index);
+ return bFallingBack;
+ }
+
+ // Next isn't a low surrogate, just fallback the high surrogate
+ }
+ }
+
+ // If already falling back then fail
+ if (bFallingBack && iRecursionCount++ > iMaxRecursion)
+ ThrowLastCharRecursive((int)ch);
+
+ // Fall back our char
+ bFallingBack = Fallback(ch, index);
+
+ return bFallingBack;
+ }
+
+ // private helper methods
+ internal void ThrowLastCharRecursive(int charRecursive)
+ {
+ // Throw it, using our complete character
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_RecursiveFallback",
+ charRecursive), "chars");
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncoderNLS.cs b/src/mscorlib/src/System/Text/EncoderNLS.cs
new file mode 100644
index 0000000000..d5c52f48d8
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncoderNLS.cs
@@ -0,0 +1,296 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Text;
+ using System;
+ using System.Diagnostics.Contracts;
+ // An Encoder is used to encode a sequence of blocks of characters into
+ // a sequence of blocks of bytes. Following instantiation of an encoder,
+ // sequential blocks of characters are converted into blocks of bytes through
+ // calls to the GetBytes method. The encoder maintains state between the
+ // conversions, allowing it to correctly encode character sequences that span
+ // adjacent blocks.
+ //
+ // Instances of specific implementations of the Encoder abstract base
+ // class are typically obtained through calls to the GetEncoder method
+ // of Encoding objects.
+ //
+
+ [Serializable]
+ internal class EncoderNLS : Encoder, ISerializable
+ {
+ // Need a place for the last left over character, most of our encodings use this
+ internal char charLeftOver;
+
+ protected Encoding m_encoding;
+
+ [NonSerialized] protected bool m_mustFlush;
+ [NonSerialized] internal bool m_throwOnOverflow;
+ [NonSerialized] internal int m_charsUsed;
+
+#region Serialization
+
+ // Constructor called by serialization. called during deserialization.
+ internal EncoderNLS(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(
+ String.Format(
+ System.Globalization.CultureInfo.CurrentCulture,
+ Environment.GetResourceString("NotSupported_TypeCannotDeserialized"), this.GetType()));
+ }
+
+ // ISerializable implementation. called during serialization.
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ SerializeEncoder(info);
+ info.AddValue("encoding", this.m_encoding);
+ info.AddValue("charLeftOver", this.charLeftOver);
+ info.SetType(typeof(Encoding.DefaultEncoder));
+ }
+
+#endregion Serialization
+
+ internal EncoderNLS(Encoding encoding)
+ {
+ this.m_encoding = encoding;
+ this.m_fallback = this.m_encoding.EncoderFallback;
+ this.Reset();
+ }
+
+ // This one is used when deserializing (like UTF7Encoding.Encoder)
+ internal EncoderNLS()
+ {
+ this.m_encoding = null;
+ this.Reset();
+ }
+
+ public override void Reset()
+ {
+ this.charLeftOver = (char)0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe int GetByteCount(char[] chars, int index, int count, bool flush)
+ {
+ // Validate input parameters
+ if (chars == null)
+ throw new ArgumentNullException( "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (index < 0 || count < 0)
+ throw new ArgumentOutOfRangeException((index<0 ? "index" : "count"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (chars.Length - index < count)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ Contract.EndContractBlock();
+
+ // Avoid empty input problem
+ if (chars.Length == 0)
+ chars = new char[1];
+
+ // Just call the pointer version
+ int result = -1;
+ fixed (char* pChars = chars)
+ {
+ result = GetByteCount(pChars + index, count, flush);
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override int GetByteCount(char* chars, int count, bool flush)
+ {
+ // Validate input parameters
+ if (chars == null)
+ throw new ArgumentNullException( "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ this.m_mustFlush = flush;
+ this.m_throwOnOverflow = true;
+ return m_encoding.GetByteCount(chars, count, this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, bool flush)
+ {
+ // Validate parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ throw new ArgumentOutOfRangeException("byteIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ Contract.EndContractBlock();
+
+ if (chars.Length == 0)
+ chars = new char[1];
+
+ int byteCount = bytes.Length - byteIndex;
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ // Just call pointer version
+ fixed (char* pChars = chars)
+ fixed (byte* pBytes = bytes)
+
+ // Remember that charCount is # to decode, not size of array.
+ return GetBytes(pChars + charIndex, charCount,
+ pBytes + byteIndex, byteCount, flush);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override int GetBytes(char* chars, int charCount, byte* bytes, int byteCount, bool flush)
+ {
+ // Validate parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ this.m_mustFlush = flush;
+ this.m_throwOnOverflow = true;
+ return m_encoding.GetBytes(chars, charCount, bytes, byteCount, this);
+ }
+
+ // This method is used when your output buffer might not be large enough for the entire result.
+ // Just call the pointer version. (This gets bytes)
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe void Convert(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ // Validate parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException((chars == null ? "chars" : "bytes"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (charIndex < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((charIndex<0 ? "charIndex" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (byteIndex < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((byteIndex<0 ? "byteIndex" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+
+ if (chars.Length - charIndex < charCount)
+ throw new ArgumentOutOfRangeException("chars",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ if (bytes.Length - byteIndex < byteCount)
+ throw new ArgumentOutOfRangeException("bytes",
+ Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+
+ Contract.EndContractBlock();
+
+ // Avoid empty input problem
+ if (chars.Length == 0)
+ chars = new char[1];
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ // Just call the pointer version (can't do this for non-msft encoders)
+ fixed (char* pChars = chars)
+ {
+ fixed (byte* pBytes = bytes)
+ {
+ Convert(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, flush,
+ out charsUsed, out bytesUsed, out completed);
+ }
+ }
+ }
+
+ // This is the version that uses pointers. We call the base encoding worker function
+ // after setting our appropriate internal variables. This is getting bytes
+ [System.Security.SecurityCritical] // auto-generated
+ public override unsafe void Convert(char* chars, int charCount,
+ byte* bytes, int byteCount, bool flush,
+ out int charsUsed, out int bytesUsed, out bool completed)
+ {
+ // Validate input parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // We don't want to throw
+ this.m_mustFlush = flush;
+ this.m_throwOnOverflow = false;
+ this.m_charsUsed = 0;
+
+ // Do conversion
+ bytesUsed = this.m_encoding.GetBytes(chars, charCount, bytes, byteCount, this);
+ charsUsed = this.m_charsUsed;
+
+ // Its completed if they've used what they wanted AND if they didn't want flush or if we are flushed
+ completed = (charsUsed == charCount) && (!flush || !this.HasState) &&
+ (m_fallbackBuffer == null || m_fallbackBuffer.Remaining == 0);
+
+ // Our data thingys are now full, we can return
+ }
+
+ public Encoding Encoding
+ {
+ get
+ {
+ return m_encoding;
+ }
+ }
+
+ public bool MustFlush
+ {
+ get
+ {
+ return m_mustFlush;
+ }
+ }
+
+
+ // Anything left in our encoder?
+ internal virtual bool HasState
+ {
+ get
+ {
+ return (this.charLeftOver != (char)0);
+ }
+ }
+
+ // Allow encoding to clear our must flush instead of throwing (in ThrowBytesOverflow)
+ internal void ClearMustFlush()
+ {
+ m_mustFlush = false;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs b/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs
new file mode 100644
index 0000000000..15dfee8912
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncoderReplacementFallback.cs
@@ -0,0 +1,233 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Runtime;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ public sealed class EncoderReplacementFallback : EncoderFallback
+ {
+ // Our variables
+ private String strDefault;
+
+ // Construction. Default replacement fallback uses no best fit and ? replacement string
+ public EncoderReplacementFallback() : this("?")
+ {
+ }
+
+ public EncoderReplacementFallback(String replacement)
+ {
+ // Must not be null
+ if (replacement == null)
+ throw new ArgumentNullException("replacement");
+ Contract.EndContractBlock();
+
+ // Make sure it doesn't have bad surrogate pairs
+ bool bFoundHigh=false;
+ for (int i = 0; i < replacement.Length; i++)
+ {
+ // Found a surrogate?
+ if (Char.IsSurrogate(replacement,i))
+ {
+ // High or Low?
+ if (Char.IsHighSurrogate(replacement, i))
+ {
+ // if already had a high one, stop
+ if (bFoundHigh)
+ break; // break & throw at the bFoundHIgh below
+ bFoundHigh = true;
+ }
+ else
+ {
+ // Low, did we have a high?
+ if (!bFoundHigh)
+ {
+ // Didn't have one, make if fail when we stop
+ bFoundHigh = true;
+ break;
+ }
+
+ // Clear flag
+ bFoundHigh = false;
+ }
+ }
+ // If last was high we're in trouble (not surrogate so not low surrogate, so break)
+ else if (bFoundHigh)
+ break;
+ }
+ if (bFoundHigh)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex", "replacement"));
+
+ strDefault = replacement;
+ }
+
+ public String DefaultString
+ {
+ get
+ {
+ return strDefault;
+ }
+ }
+
+ public override EncoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new EncoderReplacementFallbackBuffer(this);
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ return strDefault.Length;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ EncoderReplacementFallback that = value as EncoderReplacementFallback;
+ if (that != null)
+ {
+ return (this.strDefault == that.strDefault);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return strDefault.GetHashCode();
+ }
+ }
+
+
+
+ public sealed class EncoderReplacementFallbackBuffer : EncoderFallbackBuffer
+ {
+ // Store our default string
+ private String strDefault;
+ int fallbackCount = -1;
+ int fallbackIndex = -1;
+
+ // Construction
+ public EncoderReplacementFallbackBuffer(EncoderReplacementFallback fallback)
+ {
+ // 2X in case we're a surrogate pair
+ this.strDefault = fallback.DefaultString + fallback.DefaultString;
+ }
+
+ // Fallback Methods
+ public override bool Fallback(char charUnknown, int index)
+ {
+ // If we had a buffer already we're being recursive, throw, it's probably at the suspect
+ // character in our array.
+ if (fallbackCount >= 1)
+ {
+ // If we're recursive we may still have something in our buffer that makes this a surrogate
+ if (char.IsHighSurrogate(charUnknown) && fallbackCount >= 0 &&
+ char.IsLowSurrogate(strDefault[fallbackIndex+1]))
+ ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknown, strDefault[fallbackIndex+1]));
+
+ // Nope, just one character
+ ThrowLastCharRecursive(unchecked((int)charUnknown));
+ }
+
+ // Go ahead and get our fallback
+ // Divide by 2 because we aren't a surrogate pair
+ fallbackCount = strDefault.Length/2;
+ fallbackIndex = -1;
+
+ return fallbackCount != 0;
+ }
+
+ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
+ {
+ // Double check input surrogate pair
+ if (!Char.IsHighSurrogate(charUnknownHigh))
+ throw new ArgumentOutOfRangeException("charUnknownHigh",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xD800, 0xDBFF));
+
+ if (!Char.IsLowSurrogate(charUnknownLow))
+ throw new ArgumentOutOfRangeException("CharUnknownLow",
+ Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0xDC00, 0xDFFF));
+ Contract.EndContractBlock();
+
+ // If we had a buffer already we're being recursive, throw, it's probably at the suspect
+ // character in our array.
+ if (fallbackCount >= 1)
+ ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
+
+ // Go ahead and get our fallback
+ fallbackCount = strDefault.Length;
+ fallbackIndex = -1;
+
+ return fallbackCount != 0;
+ }
+
+ public override char GetNextChar()
+ {
+ // We want it to get < 0 because == 0 means that the current/last character is a fallback
+ // and we need to detect recursion. We could have a flag but we already have this counter.
+ fallbackCount--;
+ fallbackIndex++;
+
+ // Do we have anything left? 0 is now last fallback char, negative is nothing left
+ if (fallbackCount < 0)
+ return '\0';
+
+ // Need to get it out of the buffer.
+ // Make sure it didn't wrap from the fast count-- path
+ if (fallbackCount == int.MaxValue)
+ {
+ fallbackCount = -1;
+ return '\0';
+ }
+
+ // Now make sure its in the expected range
+ Contract.Assert(fallbackIndex < strDefault.Length && fallbackIndex >= 0,
+ "Index exceeds buffer range");
+
+ return strDefault[fallbackIndex];
+ }
+
+ public override bool MovePrevious()
+ {
+ // Back up one, only if we just processed the last character (or earlier)
+ if (fallbackCount >= -1 && fallbackIndex >= 0)
+ {
+ fallbackIndex--;
+ fallbackCount++;
+ return true;
+ }
+
+ // Return false 'cause we couldn't do it.
+ return false;
+ }
+
+ // How many characters left to output?
+ public override int Remaining
+ {
+ get
+ {
+ // Our count is 0 for 1 character left.
+ return (fallbackCount < 0) ? 0 : fallbackCount;
+ }
+ }
+
+ // Clear the buffer
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override unsafe void Reset()
+ {
+ fallbackCount = -1;
+ fallbackIndex = 0;
+ charStart = null;
+ bFallingBack = false;
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/Encoding.cs b/src/mscorlib/src/System/Text/Encoding.cs
new file mode 100644
index 0000000000..8533016293
--- /dev/null
+++ b/src/mscorlib/src/System/Text/Encoding.cs
@@ -0,0 +1,2152 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Globalization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Text;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Contracts;
+ using Win32Native = Microsoft.Win32.Win32Native;
+
+ // This abstract base class represents a character encoding. The class provides
+ // methods to convert arrays and strings of Unicode characters to and from
+ // arrays of bytes. A number of Encoding implementations are provided in
+ // the System.Text package, including:
+ //
+ // ASCIIEncoding, which encodes Unicode characters as single 7-bit
+ // ASCII characters. This encoding only supports character values between 0x00
+ // and 0x7F.
+ // BaseCodePageEncoding, which encapsulates a Windows code page. Any
+ // installed code page can be accessed through this encoding, and conversions
+ // are performed using the WideCharToMultiByte and
+ // MultiByteToWideChar Windows API functions.
+ // UnicodeEncoding, which encodes each Unicode character as two
+ // consecutive bytes. Both little-endian (code page 1200) and big-endian (code
+ // page 1201) encodings are recognized.
+ // UTF7Encoding, which encodes Unicode characters using the UTF-7
+ // encoding (UTF-7 stands for UCS Transformation Format, 7-bit form). This
+ // encoding supports all Unicode character values, and can also be accessed
+ // as code page 65000.
+ // UTF8Encoding, which encodes Unicode characters using the UTF-8
+ // encoding (UTF-8 stands for UCS Transformation Format, 8-bit form). This
+ // encoding supports all Unicode character values, and can also be accessed
+ // as code page 65001.
+ // UTF32Encoding, both 12000 (little endian) & 12001 (big endian)
+ //
+ // In addition to directly instantiating Encoding objects, an
+ // application can use the ForCodePage, GetASCII,
+ // GetDefault, GetUnicode, GetUTF7, and GetUTF8
+ // methods in this class to obtain encodings.
+ //
+ // Through an encoding, the GetBytes method is used to convert arrays
+ // of characters to arrays of bytes, and the GetChars method is used to
+ // convert arrays of bytes to arrays of characters. The GetBytes and
+ // GetChars methods maintain no state between conversions, and are
+ // generally intended for conversions of complete blocks of bytes and
+ // characters in one operation. When the data to be converted is only available
+ // in sequential blocks (such as data read from a stream) or when the amount of
+ // data is so large that it needs to be divided into smaller blocks, an
+ // application may choose to use a Decoder or an Encoder to
+ // perform the conversion. Decoders and encoders allow sequential blocks of
+ // data to be converted and they maintain the state required to support
+ // conversions of data that spans adjacent blocks. Decoders and encoders are
+ // obtained using the GetDecoder and GetEncoder methods.
+ //
+ // The core GetBytes and GetChars methods require the caller
+ // to provide the destination buffer and ensure that the buffer is large enough
+ // to hold the entire result of the conversion. When using these methods,
+ // either directly on an Encoding object or on an associated
+ // Decoder or Encoder, an application can use one of two methods
+ // to allocate destination buffers.
+ //
+ // The GetByteCount and GetCharCount methods can be used to
+ // compute the exact size of the result of a particular conversion, and an
+ // appropriately sized buffer for that conversion can then be allocated.
+ // The GetMaxByteCount and GetMaxCharCount methods can be
+ // be used to compute the maximum possible size of a conversion of a given
+ // number of bytes or characters, and a buffer of that size can then be reused
+ // for multiple conversions.
+ //
+ // The first method generally uses less memory, whereas the second method
+ // generally executes faster.
+ //
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public abstract class Encoding : ICloneable
+ {
+ private static Encoding defaultEncoding;
+
+ //
+ // The following values are from mlang.idl. These values
+ // should be in sync with those in mlang.idl.
+ //
+ internal const int MIMECONTF_MAILNEWS = 0x00000001;
+ internal const int MIMECONTF_BROWSER = 0x00000002;
+ internal const int MIMECONTF_SAVABLE_MAILNEWS = 0x00000100;
+ internal const int MIMECONTF_SAVABLE_BROWSER = 0x00000200;
+
+ // Special Case Code Pages
+ private const int CodePageDefault = 0;
+ private const int CodePageNoOEM = 1; // OEM Code page not supported
+ private const int CodePageNoMac = 2; // MAC code page not supported
+ private const int CodePageNoThread = 3; // Thread code page not supported
+ private const int CodePageNoSymbol = 42; // Symbol code page not supported
+ private const int CodePageUnicode = 1200; // Unicode
+ private const int CodePageBigEndian = 1201; // Big Endian Unicode
+ private const int CodePageWindows1252 = 1252; // Windows 1252 code page
+
+ // 20936 has same code page as 10008, so we'll special case it
+ private const int CodePageMacGB2312 = 10008;
+ private const int CodePageGB2312 = 20936;
+ private const int CodePageMacKorean = 10003;
+ private const int CodePageDLLKorean = 20949;
+
+ // ISO 2022 Code Pages
+ private const int ISO2022JP = 50220;
+ private const int ISO2022JPESC = 50221;
+ private const int ISO2022JPSISO = 50222;
+ private const int ISOKorean = 50225;
+ private const int ISOSimplifiedCN = 50227;
+ private const int EUCJP = 51932;
+ private const int ChineseHZ = 52936; // HZ has ~}~{~~ sequences
+
+ // 51936 is the same as 936
+ private const int DuplicateEUCCN = 51936;
+ private const int EUCCN = 936;
+
+ private const int EUCKR = 51949;
+
+ // Latin 1 & ASCII Code Pages
+ internal const int CodePageASCII = 20127; // ASCII
+ internal const int ISO_8859_1 = 28591; // Latin1
+
+ // ISCII
+ private const int ISCIIAssemese = 57006;
+ private const int ISCIIBengali = 57003;
+ private const int ISCIIDevanagari = 57002;
+ private const int ISCIIGujarathi = 57010;
+ private const int ISCIIKannada = 57008;
+ private const int ISCIIMalayalam = 57009;
+ private const int ISCIIOriya = 57007;
+ private const int ISCIIPanjabi = 57011;
+ private const int ISCIITamil = 57004;
+ private const int ISCIITelugu = 57005;
+
+ // GB18030
+ private const int GB18030 = 54936;
+
+ // Other
+ private const int ISO_8859_8I = 38598;
+ private const int ISO_8859_8_Visual = 28598;
+
+ // 50229 is currently unsupported // "Chinese Traditional (ISO-2022)"
+ private const int ENC50229 = 50229;
+
+ // Special code pages
+ private const int CodePageUTF7 = 65000;
+ private const int CodePageUTF8 = 65001;
+ private const int CodePageUTF32 = 12000;
+ private const int CodePageUTF32BE = 12001;
+
+ internal int m_codePage = 0;
+
+ // dataItem should be internal (not private). otherwise it will break during the deserialization
+ // of the data came from Everett
+ internal CodePageDataItem dataItem = null;
+
+ [NonSerialized]
+ internal bool m_deserializedFromEverett = false;
+
+ // Because of encoders we may be read only
+ [OptionalField(VersionAdded = 2)]
+ private bool m_isReadOnly = true;
+
+ // Encoding (encoder) fallback
+ [OptionalField(VersionAdded = 2)]
+ internal EncoderFallback encoderFallback = null;
+ [OptionalField(VersionAdded = 2)]
+ internal DecoderFallback decoderFallback = null;
+
+ protected Encoding() : this(0)
+ {
+ }
+
+
+ protected Encoding(int codePage)
+ {
+ // Validate code page
+ if (codePage < 0)
+ {
+ throw new ArgumentOutOfRangeException("codePage");
+ }
+ Contract.EndContractBlock();
+
+ // Remember code page
+ m_codePage = codePage;
+
+ // Use default encoder/decoder fallbacks
+ this.SetDefaultFallbacks();
+ }
+
+ // This constructor is needed to allow any sub-classing implementation to provide encoder/decoder fallback objects
+ // because the encoding object is always created as read-only object and don't allow setting encoder/decoder fallback
+ // after the creation is done.
+ protected Encoding(int codePage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
+ {
+ // Validate code page
+ if (codePage < 0)
+ {
+ throw new ArgumentOutOfRangeException("codePage");
+ }
+ Contract.EndContractBlock();
+
+ // Remember code page
+ m_codePage = codePage;
+
+ this.encoderFallback = encoderFallback ?? new InternalEncoderBestFitFallback(this);
+ this.decoderFallback = decoderFallback ?? new InternalDecoderBestFitFallback(this);
+ }
+
+ // Default fallback that we'll use.
+ internal virtual void SetDefaultFallbacks()
+ {
+ // For UTF-X encodings, we use a replacement fallback with an "\xFFFD" string,
+ // For ASCII we use "?" replacement fallback, etc.
+ this.encoderFallback = new InternalEncoderBestFitFallback(this);
+ this.decoderFallback = new InternalDecoderBestFitFallback(this);
+ }
+
+
+#region Serialization
+ internal void OnDeserializing()
+ {
+ // intialize the optional Whidbey fields
+ encoderFallback = null;
+ decoderFallback = null;
+ m_isReadOnly = true;
+ }
+
+ internal void OnDeserialized()
+ {
+ if (encoderFallback == null || decoderFallback == null)
+ {
+ m_deserializedFromEverett = true;
+ SetDefaultFallbacks();
+ }
+
+ // dataItem is always recalculated from the code page #
+ dataItem = null;
+ }
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ OnDeserializing();
+ }
+
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ OnDeserialized();
+ }
+
+ [OnSerializing]
+ private void OnSerializing(StreamingContext ctx)
+ {
+ // to be consistent with SerializeEncoding
+ dataItem = null;
+ }
+
+ // the following two methods are used for the inherited classes which implemented ISerializable
+ // Deserialization Helper
+ internal void DeserializeEncoding(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All versions have a code page
+ this.m_codePage = (int)info.GetValue("m_codePage", typeof(int));
+
+ // We can get dataItem on the fly if needed, and the index is different between versions
+ // so ignore whatever dataItem data we get from Everett.
+ this.dataItem = null;
+
+ // See if we have a code page
+ try
+ {
+ //
+ // Try Whidbey V2.0 Fields
+ //
+
+ this.m_isReadOnly = (bool)info.GetValue("m_isReadOnly", typeof(bool));
+
+ this.encoderFallback = (EncoderFallback)info.GetValue("encoderFallback", typeof(EncoderFallback));
+ this.decoderFallback = (DecoderFallback)info.GetValue("decoderFallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ //
+ // Didn't have Whidbey things, must be Everett
+ //
+ this.m_deserializedFromEverett = true;
+
+ // May as well be read only
+ this.m_isReadOnly = true;
+ SetDefaultFallbacks();
+ }
+ }
+
+ // Serialization Helper
+ internal void SerializeEncoding(SerializationInfo info, StreamingContext context)
+ {
+ // Any Info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // These are new V2.0 Whidbey stuff
+ info.AddValue("m_isReadOnly", this.m_isReadOnly);
+ info.AddValue("encoderFallback", this.EncoderFallback);
+ info.AddValue("decoderFallback", this.DecoderFallback);
+
+ // These were in Everett V1.1 as well
+ info.AddValue("m_codePage", this.m_codePage);
+
+ // This was unique to Everett V1.1
+ info.AddValue("dataItem", null);
+
+ // Everett duplicated these fields, so these are needed for portability
+ info.AddValue("Encoding+m_codePage", this.m_codePage);
+ info.AddValue("Encoding+dataItem", null);
+ }
+
+#endregion Serialization
+
+ // Converts a byte array from one encoding to another. The bytes in the
+ // bytes array are converted from srcEncoding to
+ // dstEncoding, and the returned value is a new byte array
+ // containing the result of the conversion.
+ //
+ [Pure]
+ public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding,
+ byte[] bytes) {
+ if (bytes==null)
+ throw new ArgumentNullException("bytes");
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+
+ return Convert(srcEncoding, dstEncoding, bytes, 0, bytes.Length);
+ }
+
+ // Converts a range of bytes in a byte array from one encoding to another.
+ // This method converts count bytes from bytes starting at
+ // index index from srcEncoding to dstEncoding, and
+ // returns a new byte array containing the result of the conversion.
+ //
+ [Pure]
+ public static byte[] Convert(Encoding srcEncoding, Encoding dstEncoding,
+ byte[] bytes, int index, int count) {
+ if (srcEncoding == null || dstEncoding == null) {
+ throw new ArgumentNullException((srcEncoding == null ? "srcEncoding" : "dstEncoding"),
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (bytes == null) {
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ Contract.Ensures(Contract.Result<byte[]>() != null);
+
+ return dstEncoding.GetBytes(srcEncoding.GetChars(bytes, index, count));
+ }
+
+#if FEATURE_CODEPAGES_FILE
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject {
+ get {
+ if (s_InternalSyncObject == null) {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // On Desktop, encoding instances that aren't cached in a static field are cached in
+ // a hash table by codepage.
+ private static volatile Hashtable encodings;
+#endif
+
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+#endif
+ public static void RegisterProvider(EncodingProvider provider)
+ {
+ // Parameters validated inside EncodingProvider
+ EncodingProvider.AddProvider(provider);
+ }
+
+ [Pure]
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ public static Encoding GetEncoding(int codepage)
+ {
+ Encoding result = EncodingProvider.GetEncodingFromProvider(codepage);
+ if (result != null)
+ return result;
+
+ //
+ // NOTE: If you add a new encoding that can be get by codepage, be sure to
+ // add the corresponding item in EncodingTable.
+ // Otherwise, the code below will throw exception when trying to call
+ // EncodingTable.GetDataItem().
+ //
+ if (codepage < 0 || codepage > 65535) {
+ throw new ArgumentOutOfRangeException(
+ "codepage", Environment.GetResourceString("ArgumentOutOfRange_Range",
+ 0, 65535));
+ }
+
+ Contract.EndContractBlock();
+
+ // Our Encoding
+
+ // See if the encoding is cached in a static field.
+ switch (codepage)
+ {
+ case CodePageDefault: return Default; // 0
+ case CodePageUnicode: return Unicode; // 1200
+ case CodePageBigEndian: return BigEndianUnicode; // 1201
+ case CodePageUTF32: return UTF32; // 12000
+ case CodePageUTF32BE: return BigEndianUTF32; // 12001
+ case CodePageUTF7: return UTF7; // 65000
+ case CodePageUTF8: return UTF8; // 65001
+ case CodePageASCII: return ASCII; // 20127
+ case ISO_8859_1: return Latin1; // 28591
+
+ // We don't allow the following special code page values that Win32 allows.
+ case CodePageNoOEM: // 1 CP_OEMCP
+ case CodePageNoMac: // 2 CP_MACCP
+ case CodePageNoThread: // 3 CP_THREAD_ACP
+ case CodePageNoSymbol: // 42 CP_SYMBOL
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_CodepageNotSupported", codepage), "codepage");
+ }
+
+#if FEATURE_CODEPAGES_FILE
+ object key = codepage; // Box once
+
+ // See if we have a hash table with our encoding in it already.
+ if (encodings != null) {
+ result = (Encoding)encodings[key];
+ }
+
+ if (result == null)
+ {
+ // Don't conflict with ourselves
+ lock (InternalSyncObject)
+ {
+ // Need a new hash table
+ // in case another thread beat us to creating the Dictionary
+ if (encodings == null) {
+ encodings = new Hashtable();
+ }
+
+ // Double check that we don't have one in the table (in case another thread beat us here)
+ if ((result = (Encoding)encodings[key]) != null)
+ return result;
+
+ if (codepage == CodePageWindows1252)
+ {
+ result = new SBCSCodePageEncoding(codepage);
+ }
+ else
+ {
+ result = GetEncodingCodePage(codepage) ?? GetEncodingRare(codepage);
+ }
+
+ Contract.Assert(result != null, "result != null");
+
+ encodings.Add(key, result);
+ }
+ }
+ return result;
+#else
+ // Is it a valid code page?
+ if (EncodingTable.GetCodePageDataItem(codepage) == null)
+ {
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", codepage));
+ }
+
+ return UTF8;
+#endif // FEATURE_CODEPAGES_FILE
+ }
+
+ [Pure]
+ public static Encoding GetEncoding(int codepage,
+ EncoderFallback encoderFallback, DecoderFallback decoderFallback)
+ {
+ Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(codepage, encoderFallback, decoderFallback);
+
+ if (baseEncoding != null)
+ return baseEncoding;
+
+ // Get the default encoding (which is cached and read only)
+ baseEncoding = GetEncoding(codepage);
+
+ // Clone it and set the fallback
+ Encoding fallbackEncoding = (Encoding)baseEncoding.Clone();
+ fallbackEncoding.EncoderFallback = encoderFallback;
+ fallbackEncoding.DecoderFallback = decoderFallback;
+
+ return fallbackEncoding;
+ }
+#if FEATURE_CODEPAGES_FILE
+ [System.Security.SecurityCritical] // auto-generated
+ private static Encoding GetEncodingRare(int codepage)
+ {
+ Contract.Assert(codepage != 0 && codepage != 1200 && codepage != 1201 && codepage != 65001,
+ "[Encoding.GetEncodingRare]This code page (" + codepage + ") isn't supported by GetEncodingRare!");
+ Encoding result;
+ switch (codepage)
+ {
+ case ISCIIAssemese:
+ case ISCIIBengali:
+ case ISCIIDevanagari:
+ case ISCIIGujarathi:
+ case ISCIIKannada:
+ case ISCIIMalayalam:
+ case ISCIIOriya:
+ case ISCIIPanjabi:
+ case ISCIITamil:
+ case ISCIITelugu:
+ result = new ISCIIEncoding(codepage);
+ break;
+ // GB2312-80 uses same code page for 20936 and mac 10008
+ case CodePageMacGB2312:
+ // case CodePageGB2312:
+ // result = new DBCSCodePageEncoding(codepage, EUCCN);
+ result = new DBCSCodePageEncoding(CodePageMacGB2312, CodePageGB2312);
+ break;
+
+ // Mac Korean 10003 and 20949 are the same
+ case CodePageMacKorean:
+ result = new DBCSCodePageEncoding(CodePageMacKorean, CodePageDLLKorean);
+ break;
+ // GB18030 Code Pages
+ case GB18030:
+ result = new GB18030Encoding();
+ break;
+ // ISO2022 Code Pages
+ case ISOKorean:
+ // case ISOSimplifiedCN
+ case ChineseHZ:
+ case ISO2022JP: // JIS JP, full-width Katakana mode (no half-width Katakana)
+ case ISO2022JPESC: // JIS JP, esc sequence to do Katakana.
+ case ISO2022JPSISO: // JIS JP with Shift In/ Shift Out Katakana support
+ result = new ISO2022Encoding(codepage);
+ break;
+ // Duplicate EUC-CN (51936) just calls a base code page 936,
+ // so does ISOSimplifiedCN (50227), which's gotta be broken
+ case DuplicateEUCCN:
+ case ISOSimplifiedCN:
+ result = new DBCSCodePageEncoding(codepage, EUCCN); // Just maps to 936
+ break;
+ case EUCJP:
+ result = new EUCJPEncoding();
+ break;
+ case EUCKR:
+ result = new DBCSCodePageEncoding(codepage, CodePageDLLKorean); // Maps to 20949
+ break;
+ case ENC50229:
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CodePage50229"));
+ case ISO_8859_8I:
+ result = new SBCSCodePageEncoding(codepage, ISO_8859_8_Visual); // Hebrew maps to a different code page
+ break;
+ default:
+ // Not found, already tried codepage table code pages in GetEncoding()
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", codepage));
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static Encoding GetEncodingCodePage(int CodePage)
+ {
+ // Single Byte or Double Byte Code Page? (0 if not found)
+ int i = BaseCodePageEncoding.GetCodePageByteSize(CodePage);
+ if (i == 1) return new SBCSCodePageEncoding(CodePage);
+ else if (i == 2) return new DBCSCodePageEncoding(CodePage);
+
+ // Return null if we didn't find one.
+ return null;
+ }
+#endif // FEATURE_CODEPAGES_FILE
+ // Returns an Encoding object for a given name or a given code page value.
+ //
+ [Pure]
+ public static Encoding GetEncoding(String name)
+ {
+ Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name);
+ if (baseEncoding != null)
+ return baseEncoding;
+
+ //
+ // NOTE: If you add a new encoding that can be requested by name, be sure to
+ // add the corresponding item in EncodingTable.
+ // Otherwise, the code below will throw exception when trying to call
+ // EncodingTable.GetCodePageFromName().
+ //
+ return (GetEncoding(EncodingTable.GetCodePageFromName(name)));
+ }
+
+ // Returns an Encoding object for a given name or a given code page value.
+ //
+ [Pure]
+ public static Encoding GetEncoding(String name,
+ EncoderFallback encoderFallback, DecoderFallback decoderFallback)
+ {
+ Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback);
+ if (baseEncoding != null)
+ return baseEncoding;
+
+ //
+ // NOTE: If you add a new encoding that can be requested by name, be sure to
+ // add the corresponding item in EncodingTable.
+ // Otherwise, the code below will throw exception when trying to call
+ // EncodingTable.GetCodePageFromName().
+ //
+ return (GetEncoding(EncodingTable.GetCodePageFromName(name), encoderFallback, decoderFallback));
+ }
+
+ // Return a list of all EncodingInfo objects describing all of our encodings
+ [Pure]
+ public static EncodingInfo[] GetEncodings()
+ {
+ return EncodingTable.GetEncodings();
+ }
+
+ [Pure]
+ public virtual byte[] GetPreamble()
+ {
+ return EmptyArray<Byte>.Value;
+ }
+
+ private void GetDataItem() {
+ if (dataItem==null) {
+ dataItem = EncodingTable.GetCodePageDataItem(m_codePage);
+ if(dataItem==null) {
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", m_codePage));
+ }
+ }
+ }
+
+ // Returns the name for this encoding that can be used with mail agent body tags.
+ // If the encoding may not be used, the string is empty.
+
+ public virtual String BodyName
+ {
+ get
+ {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return (dataItem.BodyName);
+ }
+ }
+
+ // Returns the human-readable description of the encoding ( e.g. Hebrew (DOS)).
+
+ public virtual String EncodingName
+ {
+ get
+ {
+ return Environment.GetResourceString("Globalization.cp_" + m_codePage.ToString());
+ }
+ }
+
+ // Returns the name for this encoding that can be used with mail agent header
+ // tags. If the encoding may not be used, the string is empty.
+
+ public virtual String HeaderName
+ {
+ get
+ {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return (dataItem.HeaderName);
+ }
+ }
+
+ // Returns the array of IANA-registered names for this encoding. If there is an
+ // IANA preferred name, it is the first name in the array.
+
+ public virtual String WebName
+ {
+ get
+ {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return (dataItem.WebName);
+ }
+ }
+
+ // Returns the windows code page that most closely corresponds to this encoding.
+
+ public virtual int WindowsCodePage
+ {
+ get
+ {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return (dataItem.UIFamilyCodePage);
+ }
+ }
+
+
+ // True if and only if the encoding is used for display by browsers clients.
+
+ public virtual bool IsBrowserDisplay {
+ get {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return ((dataItem.Flags & MIMECONTF_BROWSER) != 0);
+ }
+ }
+
+ // True if and only if the encoding is used for saving by browsers clients.
+
+ public virtual bool IsBrowserSave {
+ get {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return ((dataItem.Flags & MIMECONTF_SAVABLE_BROWSER) != 0);
+ }
+ }
+
+ // True if and only if the encoding is used for display by mail and news clients.
+
+ public virtual bool IsMailNewsDisplay {
+ get {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return ((dataItem.Flags & MIMECONTF_MAILNEWS) != 0);
+ }
+ }
+
+
+ // True if and only if the encoding is used for saving documents by mail and
+ // news clients
+
+ public virtual bool IsMailNewsSave {
+ get {
+ if (dataItem==null) {
+ GetDataItem();
+ }
+ return ((dataItem.Flags & MIMECONTF_SAVABLE_MAILNEWS) != 0);
+ }
+ }
+
+ // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual bool IsSingleByte
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public EncoderFallback EncoderFallback
+ {
+ get
+ {
+ return encoderFallback;
+ }
+
+ set
+ {
+ if (this.IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ encoderFallback = value;
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public DecoderFallback DecoderFallback
+ {
+ get
+ {
+ return decoderFallback;
+ }
+
+ set
+ {
+ if (this.IsReadOnly)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ReadOnly"));
+
+ if (value == null)
+ throw new ArgumentNullException("value");
+ Contract.EndContractBlock();
+
+ decoderFallback = value;
+ }
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual Object Clone()
+ {
+ Encoding newEncoding = (Encoding)this.MemberwiseClone();
+
+ // New one should be readable
+ newEncoding.m_isReadOnly = false;
+ return newEncoding;
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsReadOnly
+ {
+ get
+ {
+ return (m_isReadOnly);
+ }
+ }
+
+
+ // Returns an encoding for the ASCII character set. The returned encoding
+ // will be an instance of the ASCIIEncoding class.
+
+ public static Encoding ASCII => ASCIIEncoding.s_default;
+
+ // Returns an encoding for the Latin1 character set. The returned encoding
+ // will be an instance of the Latin1Encoding class.
+ //
+ // This is for our optimizations
+ private static Encoding Latin1 => Latin1Encoding.s_default;
+
+ // Returns the number of bytes required to encode the given character
+ // array.
+ //
+ [Pure]
+ public virtual int GetByteCount(char[] chars)
+ {
+ if (chars == null)
+ {
+ throw new ArgumentNullException("chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ Contract.EndContractBlock();
+
+ return GetByteCount(chars, 0, chars.Length);
+ }
+
+ [Pure]
+ public virtual int GetByteCount(String s)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ Contract.EndContractBlock();
+
+ char[] chars = s.ToCharArray();
+ return GetByteCount(chars, 0, chars.Length);
+
+ }
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+ //
+ [Pure]
+ public abstract int GetByteCount(char[] chars, int index, int count);
+
+ // We expect this to be the workhorse for NLS encodings
+ // unfortunately for existing overrides, it has to call the [] version,
+ // which is really slow, so this method should be avoided if you're calling
+ // a 3rd party encoding.
+ [Pure]
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetByteCount(char* chars, int count)
+ {
+ // Validate input parameters
+ if (chars == null)
+ throw new ArgumentNullException("chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ char[] arrChar = new char[count];
+ int index;
+
+ for (index = 0; index < count; index++)
+ arrChar[index] = chars[index];
+
+ return GetByteCount(arrChar, 0, count);
+ }
+
+ // For NLS Encodings, workhorse takes an encoder (may be null)
+ // Always validate parameters before calling internal version, which will only assert.
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ {
+ Contract.Requires(chars != null);
+ Contract.Requires(count >= 0);
+
+ return GetByteCount(chars, count);
+ }
+
+ // Returns a byte array containing the encoded representation of the given
+ // character array.
+ //
+ [Pure]
+ public virtual byte[] GetBytes(char[] chars)
+ {
+ if (chars == null)
+ {
+ throw new ArgumentNullException("chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ Contract.EndContractBlock();
+ return GetBytes(chars, 0, chars.Length);
+ }
+
+ // Returns a byte array containing the encoded representation of a range
+ // of characters in a character array.
+ //
+ [Pure]
+ public virtual byte[] GetBytes(char[] chars, int index, int count)
+ {
+ byte[] result = new byte[GetByteCount(chars, index, count)];
+ GetBytes(chars, index, count, result, 0);
+ return result;
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+ //
+ public abstract int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex);
+
+ // Returns a byte array containing the encoded representation of the given
+ // string.
+ //
+ [Pure]
+ public virtual byte[] GetBytes(String s)
+ {
+ if (s == null)
+ throw new ArgumentNullException("s",
+ Environment.GetResourceString("ArgumentNull_String"));
+ Contract.EndContractBlock();
+
+ int byteCount = GetByteCount(s);
+ byte[] bytes = new byte[byteCount];
+ int bytesReceived = GetBytes(s, 0, s.Length, bytes, 0);
+ Contract.Assert(byteCount == bytesReceived);
+ return bytes;
+ }
+
+ public virtual int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ if (s==null)
+ throw new ArgumentNullException("s");
+ Contract.EndContractBlock();
+ return GetBytes(s.ToCharArray(), charIndex, charCount, bytes, byteIndex);
+ }
+
+ // This is our internal workhorse
+ // Always validate parameters before calling internal version, which will only assert.
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ return GetBytes(chars, charCount, bytes, byteCount);
+ }
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: If this breaks it could be a security threat. Obviously we
+ // call this internally, so you need to make sure that your pointers, counts
+ // and indexes are correct when you call this method.
+ //
+ // In addition, we have internal code, which will be marked as "safe" calling
+ // this code. However this code is dependent upon the implimentation of an
+ // external GetBytes() method, which could be overridden by a third party and
+ // the results of which cannot be guaranteed. We use that result to copy
+ // the byte[] to our byte* output buffer. If the result count was wrong, we
+ // could easily overflow our output buffer. Therefore we do an extra test
+ // when we copy the buffer so that we don't overflow byteCount either.
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount)
+ {
+ // Validate input parameters
+ if (bytes == null || chars == null)
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (charCount < 0 || byteCount < 0)
+ throw new ArgumentOutOfRangeException((charCount<0 ? "charCount" : "byteCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get the char array to convert
+ char[] arrChar = new char[charCount];
+
+ int index;
+ for (index = 0; index < charCount; index++)
+ arrChar[index] = chars[index];
+
+ // Get the byte array to fill
+ byte[] arrByte = new byte[byteCount];
+
+ // Do the work
+ int result = GetBytes(arrChar, 0, charCount, arrByte, 0);
+
+ Contract.Assert(result <= byteCount, "[Encoding.GetBytes]Returned more bytes than we have space for");
+
+ // Copy the byte array
+ // WARNING: We MUST make sure that we don't copy too many bytes. We can't
+ // rely on result because it could be a 3rd party implimentation. We need
+ // to make sure we never copy more than byteCount bytes no matter the value
+ // of result
+ if (result < byteCount)
+ byteCount = result;
+
+ // Copy the data, don't overrun our array!
+ for (index = 0; index < byteCount; index++)
+ bytes[index] = arrByte[index];
+
+ return byteCount;
+ }
+
+ // Returns the number of characters produced by decoding the given byte
+ // array.
+ //
+ [Pure]
+ public virtual int GetCharCount(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ Contract.EndContractBlock();
+ return GetCharCount(bytes, 0, bytes.Length);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+ //
+ [Pure]
+ public abstract int GetCharCount(byte[] bytes, int index, int count);
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ [Pure]
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetCharCount(byte* bytes, int count)
+ {
+ // Validate input parameters
+ if (bytes == null)
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (count < 0)
+ throw new ArgumentOutOfRangeException("count",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ byte[] arrbyte = new byte[count];
+ int index;
+
+ for (index = 0; index < count; index++)
+ arrbyte[index] = bytes[index];
+
+ return GetCharCount(arrbyte, 0, count);
+ }
+
+ // This is our internal workhorse
+ // Always validate parameters before calling internal version, which will only assert.
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ {
+ return GetCharCount(bytes, count);
+ }
+
+ // Returns a character array containing the decoded representation of a
+ // given byte array.
+ //
+ [Pure]
+ public virtual char[] GetChars(byte[] bytes)
+ {
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ Contract.EndContractBlock();
+ return GetChars(bytes, 0, bytes.Length);
+ }
+
+ // Returns a character array containing the decoded representation of a
+ // range of bytes in a byte array.
+ //
+ [Pure]
+ public virtual char[] GetChars(byte[] bytes, int index, int count)
+ {
+ char[] result = new char[GetCharCount(bytes, index, count)];
+ GetChars(bytes, index, count, result, 0);
+ return result;
+ }
+
+ // Decodes a range of bytes in a byte array into a range of characters in a
+ // character array. An exception occurs if the character array is not large
+ // enough to hold the complete decoding of the bytes. The
+ // GetCharCount method can be used to determine the exact number of
+ // characters that will be produced for a given range of bytes.
+ // Alternatively, the GetMaxCharCount method can be used to
+ // determine the maximum number of characterss that will be produced for a
+ // given number of bytes, regardless of the actual byte values.
+ //
+
+ public abstract int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex);
+
+
+ // We expect this to be the workhorse for NLS Encodings, but for existing
+ // ones we need a working (if slow) default implimentation)
+ //
+ // WARNING WARNING WARNING
+ //
+ // WARNING: If this breaks it could be a security threat. Obviously we
+ // call this internally, so you need to make sure that your pointers, counts
+ // and indexes are correct when you call this method.
+ //
+ // In addition, we have internal code, which will be marked as "safe" calling
+ // this code. However this code is dependent upon the implimentation of an
+ // external GetChars() method, which could be overridden by a third party and
+ // the results of which cannot be guaranteed. We use that result to copy
+ // the char[] to our char* output buffer. If the result count was wrong, we
+ // could easily overflow our output buffer. Therefore we do an extra test
+ // when we copy the buffer so that we don't overflow charCount either.
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount)
+ {
+ // Validate input parameters
+ if (chars == null || bytes == null)
+ throw new ArgumentNullException(chars == null ? "chars" : "bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0 || charCount < 0)
+ throw new ArgumentOutOfRangeException((byteCount<0 ? "byteCount" : "charCount"),
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Get the byte array to convert
+ byte[] arrByte = new byte[byteCount];
+
+ int index;
+ for (index = 0; index < byteCount; index++)
+ arrByte[index] = bytes[index];
+
+ // Get the char array to fill
+ char[] arrChar = new char[charCount];
+
+ // Do the work
+ int result = GetChars(arrByte, 0, byteCount, arrChar, 0);
+
+ Contract.Assert(result <= charCount, "[Encoding.GetChars]Returned more chars than we have space for");
+
+ // Copy the char array
+ // WARNING: We MUST make sure that we don't copy too many chars. We can't
+ // rely on result because it could be a 3rd party implimentation. We need
+ // to make sure we never copy more than charCount chars no matter the value
+ // of result
+ if (result < charCount)
+ charCount = result;
+
+ // Copy the data, don't overrun our array!
+ for (index = 0; index < charCount; index++)
+ chars[index] = arrChar[index];
+
+ return charCount;
+ }
+
+
+ // This is our internal workhorse
+ // Always validate parameters before calling internal version, which will only assert.
+ [System.Security.SecurityCritical] // auto-generated
+ internal virtual unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS decoder)
+ {
+ return GetChars(bytes, byteCount, chars, charCount);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public unsafe string GetString(byte* bytes, int byteCount)
+ {
+ if (bytes == null)
+ throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
+
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ return String.CreateStringFromEncoding(bytes, byteCount, this);
+ }
+
+ // Returns the code page identifier of this encoding. The returned value is
+ // an integer between 0 and 65535 if the encoding has a code page
+ // identifier, or -1 if the encoding does not represent a code page.
+ //
+
+ public virtual int CodePage
+ {
+ get
+ {
+ return m_codePage;
+ }
+ }
+
+ // IsAlwaysNormalized
+ // Returns true if the encoding is always normalized for the specified encoding form
+ [Pure]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public bool IsAlwaysNormalized()
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ return this.IsAlwaysNormalized(NormalizationForm.FormC);
+#else
+ return this.IsAlwaysNormalized((NormalizationForm)ExtendedNormalizationForms.FormIdna);
+#endif
+ }
+
+ [Pure]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public virtual bool IsAlwaysNormalized(NormalizationForm form)
+ {
+ // Assume false unless the encoding knows otherwise
+ return false;
+ }
+
+ // Returns a Decoder object for this encoding. The returned object
+ // can be used to decode a sequence of bytes into a sequence of characters.
+ // Contrary to the GetChars family of methods, a Decoder can
+ // convert partial sequences of bytes into partial sequences of characters
+ // by maintaining the appropriate state between the conversions.
+ //
+ // This default implementation returns a Decoder that simply
+ // forwards calls to the GetCharCount and GetChars methods to
+ // the corresponding methods of this encoding. Encodings that require state
+ // to be maintained between successive conversions should override this
+ // method and return an instance of an appropriate Decoder
+ // implementation.
+ //
+
+ public virtual Decoder GetDecoder()
+ {
+ return new DefaultDecoder(this);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private static Encoding CreateDefaultEncoding()
+ {
+ // defaultEncoding should be null if we get here, but we can't
+ // assert that in case another thread beat us to the initialization
+
+ Encoding enc;
+
+#if FEATURE_CODEPAGES_FILE
+ int codePage = Win32Native.GetACP();
+
+ // For US English, we can save some startup working set by not calling
+ // GetEncoding(int codePage) since JITting GetEncoding will force us to load
+ // all the Encoding classes for ASCII, UTF7 & UTF8, & UnicodeEncoding.
+
+ if (codePage == 1252)
+ enc = new SBCSCodePageEncoding(codePage);
+ else
+ enc = GetEncoding(codePage);
+#else // FEATURE_CODEPAGES_FILE
+
+ // For silverlight we use UTF8 since ANSI isn't available
+ enc = UTF8;
+
+#endif // FEATURE_CODEPAGES_FILE
+
+ // This method should only ever return one Encoding instance
+ return Interlocked.CompareExchange(ref defaultEncoding, enc, null) ?? enc;
+ }
+
+ // Returns an encoding for the system's current ANSI code page.
+
+ public static Encoding Default => defaultEncoding ?? CreateDefaultEncoding();
+
+ // Returns an Encoder object for this encoding. The returned object
+ // can be used to encode a sequence of characters into a sequence of bytes.
+ // Contrary to the GetBytes family of methods, an Encoder can
+ // convert partial sequences of characters into partial sequences of bytes
+ // by maintaining the appropriate state between the conversions.
+ //
+ // This default implementation returns an Encoder that simply
+ // forwards calls to the GetByteCount and GetBytes methods to
+ // the corresponding methods of this encoding. Encodings that require state
+ // to be maintained between successive conversions should override this
+ // method and return an instance of an appropriate Encoder
+ // implementation.
+ //
+
+ public virtual Encoder GetEncoder()
+ {
+ return new DefaultEncoder(this);
+ }
+
+ // Returns the maximum number of bytes required to encode a given number of
+ // characters. This method can be used to determine an appropriate buffer
+ // size for byte arrays passed to the GetBytes method of this
+ // encoding or the GetBytes method of an Encoder for this
+ // encoding. All encodings must guarantee that no buffer overflow
+ // exceptions will occur if buffers are sized according to the results of
+ // this method.
+ //
+ // WARNING: If you're using something besides the default replacement encoder fallback,
+ // then you could have more bytes than this returned from an actual call to GetBytes().
+ //
+ [Pure]
+ public abstract int GetMaxByteCount(int charCount);
+
+ // Returns the maximum number of characters produced by decoding a given
+ // number of bytes. This method can be used to determine an appropriate
+ // buffer size for character arrays passed to the GetChars method of
+ // this encoding or the GetChars method of a Decoder for this
+ // encoding. All encodings must guarantee that no buffer overflow
+ // exceptions will occur if buffers are sized according to the results of
+ // this method.
+ //
+ [Pure]
+ public abstract int GetMaxCharCount(int byteCount);
+
+ // Returns a string containing the decoded representation of a given byte
+ // array.
+ //
+ [Pure]
+ public virtual String GetString(byte[] bytes)
+ {
+ if (bytes == null)
+ throw new ArgumentNullException("bytes",
+ Environment.GetResourceString("ArgumentNull_Array"));
+ Contract.EndContractBlock();
+
+ return GetString(bytes, 0, bytes.Length);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+ //
+ // Internally we override this for performance
+ //
+ [Pure]
+ public virtual String GetString(byte[] bytes, int index, int count)
+ {
+ return new String(GetChars(bytes, index, count));
+ }
+
+ // Returns an encoding for Unicode format. The returned encoding will be
+ // an instance of the UnicodeEncoding class.
+ //
+ // It will use little endian byte order, but will detect
+ // input in big endian if it finds a byte order mark per Unicode 2.0.
+
+ public static Encoding Unicode => UnicodeEncoding.s_littleEndianDefault;
+
+ // Returns an encoding for Unicode format. The returned encoding will be
+ // an instance of the UnicodeEncoding class.
+ //
+ // It will use big endian byte order, but will detect
+ // input in little endian if it finds a byte order mark per Unicode 2.0.
+
+ public static Encoding BigEndianUnicode => UnicodeEncoding.s_bigEndianDefault;
+
+ // Returns an encoding for the UTF-7 format. The returned encoding will be
+ // an instance of the UTF7Encoding class.
+
+ public static Encoding UTF7 => UTF7Encoding.s_default;
+
+ // Returns an encoding for the UTF-8 format. The returned encoding will be
+ // an instance of the UTF8Encoding class.
+
+ public static Encoding UTF8 => UTF8Encoding.s_default;
+
+ // Returns an encoding for the UTF-32 format. The returned encoding will be
+ // an instance of the UTF32Encoding class.
+
+ public static Encoding UTF32 => UTF32Encoding.s_default;
+
+ // Returns an encoding for the UTF-32 format. The returned encoding will be
+ // an instance of the UTF32Encoding class.
+ //
+ // It will use big endian byte order.
+
+ private static Encoding BigEndianUTF32 => UTF32Encoding.s_bigEndianDefault;
+
+ public override bool Equals(Object value) {
+ Encoding that = value as Encoding;
+ if (that != null)
+ return (m_codePage == that.m_codePage) &&
+ (EncoderFallback.Equals(that.EncoderFallback)) &&
+ (DecoderFallback.Equals(that.DecoderFallback));
+ return (false);
+ }
+
+
+ public override int GetHashCode() {
+ return m_codePage + this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode();
+ }
+
+ internal virtual char[] GetBestFitUnicodeToBytesData()
+ {
+ // Normally we don't have any best fit data.
+ return EmptyArray<Char>.Value;
+ }
+
+ internal virtual char[] GetBestFitBytesToUnicodeData()
+ {
+ // Normally we don't have any best fit data.
+ return EmptyArray<Char>.Value;
+ }
+
+ internal void ThrowBytesOverflow()
+ {
+ // Special message to include fallback type in case fallback's GetMaxCharCount is broken
+ // This happens if user has implimented an encoder fallback with a broken GetMaxCharCount
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_EncodingConversionOverflowBytes",
+ EncodingName, EncoderFallback.GetType()), "bytes");
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void ThrowBytesOverflow(EncoderNLS encoder, bool nothingEncoded)
+ {
+ if (encoder == null || encoder.m_throwOnOverflow || nothingEncoded)
+ {
+ if (encoder != null && encoder.InternalHasFallbackBuffer)
+ encoder.FallbackBuffer.InternalReset();
+ // Special message to include fallback type in case fallback's GetMaxCharCount is broken
+ // This happens if user has implimented an encoder fallback with a broken GetMaxCharCount
+ ThrowBytesOverflow();
+ }
+
+ // If we didn't throw, we are in convert and have to remember our flushing
+ encoder.ClearMustFlush();
+ }
+
+ internal void ThrowCharsOverflow()
+ {
+ // Special message to include fallback type in case fallback's GetMaxCharCount is broken
+ // This happens if user has implimented a decoder fallback with a broken GetMaxCharCount
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_EncodingConversionOverflowChars",
+ EncodingName, DecoderFallback.GetType()), "chars");
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void ThrowCharsOverflow(DecoderNLS decoder, bool nothingDecoded)
+ {
+ if (decoder == null || decoder.m_throwOnOverflow || nothingDecoded)
+ {
+ if (decoder != null && decoder.InternalHasFallbackBuffer)
+ decoder.FallbackBuffer.InternalReset();
+
+ // Special message to include fallback type in case fallback's GetMaxCharCount is broken
+ // This happens if user has implimented a decoder fallback with a broken GetMaxCharCount
+ ThrowCharsOverflow();
+ }
+
+ // If we didn't throw, we are in convert and have to remember our flushing
+ decoder.ClearMustFlush();
+ }
+
+ [Serializable]
+ internal class DefaultEncoder : Encoder, IObjectReference, ISerializable
+ {
+ private Encoding m_encoding;
+ [NonSerialized] private bool m_hasInitializedEncoding;
+
+ [NonSerialized] internal char charLeftOver;
+
+ public DefaultEncoder(Encoding encoding)
+ {
+ m_encoding = encoding;
+ m_hasInitializedEncoding = true;
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal DefaultEncoder(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All we have is our encoding
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+
+ try
+ {
+ this.m_fallback = (EncoderFallback) info.GetValue("m_fallback", typeof(EncoderFallback));
+ this.charLeftOver = (Char) info.GetValue("charLeftOver", typeof(Char));
+ }
+ catch (SerializationException)
+ {
+ }
+ }
+
+ // Just get it from GetEncoding
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ // upon deserialization since the DefaultEncoder implement IObjectReference the
+ // serialization code tries to do the fixup. The fixup returns another
+ // IObjectReference (the DefaultEncoder) class and hence so on and on.
+ // Finally the deserialization logics fails after following maximum references
+ // unless we short circuit with the following
+ if (m_hasInitializedEncoding)
+ {
+ return this;
+ }
+
+ Encoder encoder = m_encoding.GetEncoder();
+ if (m_fallback != null)
+ encoder.m_fallback = m_fallback;
+ if (charLeftOver != (char) 0)
+ {
+ EncoderNLS encoderNls = encoder as EncoderNLS;
+ if (encoderNls != null)
+ encoderNls.charLeftOver = charLeftOver;
+ }
+ return encoder;
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All we have is our encoding
+ info.AddValue("encoding", this.m_encoding);
+ }
+
+ // Returns the number of bytes the next call to GetBytes will
+ // produce if presented with the given range of characters and the given
+ // value of the flush parameter. The returned value takes into
+ // account the state in which the encoder was left following the last call
+ // to GetBytes. The state of the encoder is not affected by a call
+ // to this method.
+ //
+
+ public override int GetByteCount(char[] chars, int index, int count, bool flush)
+ {
+ return m_encoding.GetByteCount(chars, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public unsafe override int GetByteCount(char* chars, int count, bool flush)
+ {
+ return m_encoding.GetByteCount(chars, count);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. The method encodes charCount characters from
+ // chars starting at index charIndex, storing the resulting
+ // bytes in bytes starting at index byteIndex. The encoding
+ // takes into account the state in which the encoder was left following the
+ // last call to this method. The flush parameter indicates whether
+ // the encoder should flush any shift-states and partial characters at the
+ // end of the conversion. To ensure correct termination of a sequence of
+ // blocks of encoded bytes, the last call to GetBytes should specify
+ // a value of true for the flush parameter.
+ //
+ // An exception occurs if the byte array is not large enough to hold the
+ // complete encoding of the characters. The GetByteCount method can
+ // be used to determine the exact number of bytes that will be produced for
+ // a given range of characters. Alternatively, the GetMaxByteCount
+ // method of the Encoding that produced this encoder can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+ //
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex, bool flush)
+ {
+ return m_encoding.GetBytes(chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public unsafe override int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, bool flush)
+ {
+ return m_encoding.GetBytes(chars, charCount, bytes, byteCount);
+ }
+ }
+
+ [Serializable]
+ internal class DefaultDecoder : Decoder, IObjectReference, ISerializable
+ {
+ private Encoding m_encoding;
+ [NonSerialized]
+ private bool m_hasInitializedEncoding;
+
+ public DefaultDecoder(Encoding encoding)
+ {
+ m_encoding = encoding;
+ m_hasInitializedEncoding = true;
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal DefaultDecoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All we have is our encoding
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+
+ try
+ {
+ this.m_fallback = (DecoderFallback) info.GetValue("m_fallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ m_fallback = null;
+ }
+ }
+
+ // Just get it from GetEncoding
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ // upon deserialization since the DefaultEncoder implement IObjectReference the
+ // serialization code tries to do the fixup. The fixup returns another
+ // IObjectReference (the DefaultEncoder) class and hence so on and on.
+ // Finally the deserialization logics fails after following maximum references
+ // unless we short circuit with the following
+ if (m_hasInitializedEncoding)
+ {
+ return this;
+ }
+
+ Decoder decoder = m_encoding.GetDecoder();
+ if (m_fallback != null)
+ decoder.m_fallback = m_fallback;
+
+ return decoder;
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All we have is our encoding
+ info.AddValue("encoding", this.m_encoding);
+ }
+
+ // Returns the number of characters the next call to GetChars will
+ // produce if presented with the given range of bytes. The returned value
+ // takes into account the state in which the decoder was left following the
+ // last call to GetChars. The state of the decoder is not affected
+ // by a call to this method.
+ //
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return GetCharCount(bytes, index, count, false);
+ }
+
+ public override int GetCharCount(byte[] bytes, int index, int count, bool flush)
+ {
+ return m_encoding.GetCharCount(bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public unsafe override int GetCharCount(byte* bytes, int count, bool flush)
+ {
+ // By default just call the encoding version, no flush by default
+ return m_encoding.GetCharCount(bytes, count);
+ }
+
+ // Decodes a range of bytes in a byte array into a range of characters
+ // in a character array. The method decodes byteCount bytes from
+ // bytes starting at index byteIndex, storing the resulting
+ // characters in chars starting at index charIndex. The
+ // decoding takes into account the state in which the decoder was left
+ // following the last call to this method.
+ //
+ // An exception occurs if the character array is not large enough to
+ // hold the complete decoding of the bytes. The GetCharCount method
+ // can be used to determine the exact number of characters that will be
+ // produced for a given range of bytes. Alternatively, the
+ // GetMaxCharCount method of the Encoding that produced this
+ // decoder can be used to determine the maximum number of characters that
+ // will be produced for a given number of bytes, regardless of the actual
+ // byte values.
+ //
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return GetChars(bytes, byteIndex, byteCount, chars, charIndex, false);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex, bool flush)
+ {
+ return m_encoding.GetChars(bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressMessage("Microsoft.Contracts", "CC1055")] // Skip extra error checking to avoid *potential* AppCompat problems.
+ public unsafe override int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, bool flush)
+ {
+ // By default just call the encoding's version
+ return m_encoding.GetChars(bytes, byteCount, chars, charCount);
+ }
+ }
+
+ internal class EncodingCharBuffer
+ {
+ [SecurityCritical]
+ unsafe char* chars;
+ [SecurityCritical]
+ unsafe char* charStart;
+ [SecurityCritical]
+ unsafe char* charEnd;
+ int charCountResult = 0;
+ Encoding enc;
+ DecoderNLS decoder;
+ [SecurityCritical]
+ unsafe byte* byteStart;
+ [SecurityCritical]
+ unsafe byte* byteEnd;
+ [SecurityCritical]
+ unsafe byte* bytes;
+ DecoderFallbackBuffer fallbackBuffer;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe EncodingCharBuffer(Encoding enc, DecoderNLS decoder, char* charStart, int charCount,
+ byte* byteStart, int byteCount)
+ {
+ this.enc = enc;
+ this.decoder = decoder;
+
+ this.chars = charStart;
+ this.charStart = charStart;
+ this.charEnd = charStart + charCount;
+
+ this.byteStart = byteStart;
+ this.bytes = byteStart;
+ this.byteEnd = byteStart + byteCount;
+
+ if (this.decoder == null)
+ this.fallbackBuffer = enc.DecoderFallback.CreateFallbackBuffer();
+ else
+ this.fallbackBuffer = this.decoder.FallbackBuffer;
+
+ // If we're getting chars or getting char count we don't expect to have
+ // to remember fallbacks between calls (so it should be empty)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[Encoding.EncodingCharBuffer.EncodingCharBuffer]Expected empty fallback buffer for getchars/charcount");
+ fallbackBuffer.InternalInitialize(bytes, charEnd);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddChar(char ch, int numBytes)
+ {
+ if (chars != null)
+ {
+ if (chars >= charEnd)
+ {
+ // Throw maybe
+ bytes-=numBytes; // Didn't encode these bytes
+ enc.ThrowCharsOverflow(decoder, bytes <= byteStart); // Throw?
+ return false; // No throw, but no store either
+ }
+
+ *(chars++) = ch;
+ }
+ charCountResult++;
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddChar(char ch)
+ {
+ return AddChar(ch,1);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddChar(char ch1, char ch2, int numBytes)
+ {
+ // Need room for 2 chars
+ if (chars >= charEnd - 1)
+ {
+ // Throw maybe
+ bytes-=numBytes; // Didn't encode these bytes
+ enc.ThrowCharsOverflow(decoder, bytes <= byteStart); // Throw?
+ return false; // No throw, but no store either
+ }
+ return AddChar(ch1, numBytes) && AddChar(ch2, numBytes);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void AdjustBytes(int count)
+ {
+ bytes += count;
+ }
+
+ internal unsafe bool MoreData
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ return bytes < byteEnd;
+ }
+ }
+
+ // Do we have count more bytes?
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool EvenMoreData(int count)
+ {
+ return (bytes <= byteEnd - count);
+ }
+
+ // GetNextByte shouldn't be called unless the caller's already checked more data or even more data,
+ // but we'll double check just to make sure.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe byte GetNextByte()
+ {
+ Contract.Assert(bytes < byteEnd, "[EncodingCharBuffer.GetNextByte]Expected more date");
+ if (bytes >= byteEnd)
+ return 0;
+ return *(bytes++);
+ }
+
+ internal unsafe int BytesUsed
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ return (int)(bytes - byteStart);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Fallback(byte fallbackByte)
+ {
+ // Build our buffer
+ byte[] byteBuffer = new byte[] { fallbackByte };
+
+ // Do the fallback and add the data.
+ return Fallback(byteBuffer);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Fallback(byte byte1, byte byte2)
+ {
+ // Build our buffer
+ byte[] byteBuffer = new byte[] { byte1, byte2 };
+
+ // Do the fallback and add the data.
+ return Fallback(byteBuffer);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Fallback(byte byte1, byte byte2, byte byte3, byte byte4)
+ {
+ // Build our buffer
+ byte[] byteBuffer = new byte[] { byte1, byte2, byte3, byte4 };
+
+ // Do the fallback and add the data.
+ return Fallback(byteBuffer);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Fallback(byte[] byteBuffer)
+ {
+ // Do the fallback and add the data.
+ if (chars != null)
+ {
+ char* pTemp = chars;
+ if (fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars) == false)
+ {
+ // Throw maybe
+ bytes -= byteBuffer.Length; // Didn't use how many ever bytes we're falling back
+ fallbackBuffer.InternalReset(); // We didn't use this fallback.
+ enc.ThrowCharsOverflow(decoder, chars == charStart); // Throw?
+ return false; // No throw, but no store either
+ }
+ charCountResult += unchecked((int)(chars - pTemp));
+ }
+ else
+ {
+ charCountResult += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+
+ return true;
+ }
+
+ internal unsafe int Count
+ {
+ get
+ {
+ return charCountResult;
+ }
+ }
+ }
+
+ internal class EncodingByteBuffer
+ {
+ [SecurityCritical]
+ unsafe byte* bytes;
+ [SecurityCritical]
+ unsafe byte* byteStart;
+ [SecurityCritical]
+ unsafe byte* byteEnd;
+ [SecurityCritical]
+ unsafe char* chars;
+ [SecurityCritical]
+ unsafe char* charStart;
+ [SecurityCritical]
+ unsafe char* charEnd;
+ int byteCountResult = 0;
+ Encoding enc;
+ EncoderNLS encoder;
+ internal EncoderFallbackBuffer fallbackBuffer;
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe EncodingByteBuffer(Encoding inEncoding, EncoderNLS inEncoder,
+ byte* inByteStart, int inByteCount, char* inCharStart, int inCharCount)
+ {
+ this.enc = inEncoding;
+ this.encoder = inEncoder;
+
+ this.charStart = inCharStart;
+ this.chars = inCharStart;
+ this.charEnd = inCharStart + inCharCount;
+
+ this.bytes = inByteStart;
+ this.byteStart = inByteStart;
+ this.byteEnd = inByteStart + inByteCount;
+
+ if (this.encoder == null)
+ this.fallbackBuffer = enc.EncoderFallback.CreateFallbackBuffer();
+ else
+ {
+ this.fallbackBuffer = this.encoder.FallbackBuffer;
+ // If we're not converting we must not have data in our fallback buffer
+ if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
+ this.fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ encoder.Encoding.EncodingName, encoder.Fallback.GetType()));
+ }
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, bytes != null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b, int moreBytesExpected)
+ {
+ Contract.Assert(moreBytesExpected >= 0, "[EncodingByteBuffer.AddByte]expected non-negative moreBytesExpected");
+ if (bytes != null)
+ {
+ if (bytes >= byteEnd - moreBytesExpected)
+ {
+ // Throw maybe. Check which buffer to back up (only matters if Converting)
+ this.MovePrevious(true); // Throw if necessary
+ return false; // No throw, but no store either
+ }
+
+ *(bytes++) = b;
+ }
+ byteCountResult++;
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1)
+ {
+ return (AddByte(b1, 0));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1, byte b2)
+ {
+ return (AddByte(b1, b2, 0));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1, byte b2, int moreBytesExpected)
+ {
+ return (AddByte(b1, 1 + moreBytesExpected) && AddByte(b2, moreBytesExpected));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1, byte b2, byte b3)
+ {
+ return AddByte(b1, b2, b3, (int)0);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1, byte b2, byte b3, int moreBytesExpected)
+ {
+ return (AddByte(b1, 2 + moreBytesExpected) &&
+ AddByte(b2, 1 + moreBytesExpected) &&
+ AddByte(b3, moreBytesExpected));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool AddByte(byte b1, byte b2, byte b3, byte b4)
+ {
+ return (AddByte(b1, 3) &&
+ AddByte(b2, 2) &&
+ AddByte(b3, 1) &&
+ AddByte(b4, 0));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void MovePrevious(bool bThrow)
+ {
+ if (fallbackBuffer.bFallingBack)
+ fallbackBuffer.MovePrevious(); // don't use last fallback
+ else
+ {
+ Contract.Assert(chars > charStart ||
+ ((bThrow == true) && (bytes == byteStart)),
+ "[EncodingByteBuffer.MovePrevious]expected previous data or throw");
+ if (chars > charStart)
+ chars--; // don't use last char
+ }
+
+ if (bThrow)
+ enc.ThrowBytesOverflow(encoder, bytes == byteStart); // Throw? (and reset fallback if not converting)
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Fallback(char charFallback)
+ {
+ // Do the fallback
+ return fallbackBuffer.InternalFallback(charFallback, ref chars);
+ }
+
+ internal unsafe bool MoreData
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ // See if fallbackBuffer is not empty or if there's data left in chars buffer.
+ return ((fallbackBuffer.Remaining > 0) || (chars < charEnd));
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe char GetNextChar()
+ {
+ // See if there's something in our fallback buffer
+ char cReturn = fallbackBuffer.InternalGetNextChar();
+
+ // Nothing in the fallback buffer, return our normal data.
+ if (cReturn == 0)
+ {
+ if (chars < charEnd)
+ cReturn = *(chars++);
+ }
+
+ return cReturn;
+ }
+
+ internal unsafe int CharsUsed
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ return (int)(chars - charStart);
+ }
+ }
+
+ internal unsafe int Count
+ {
+ get
+ {
+ return byteCountResult;
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncodingForwarder.cs b/src/mscorlib/src/System/Text/EncodingForwarder.cs
new file mode 100644
index 0000000000..d4bcf800e3
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncodingForwarder.cs
@@ -0,0 +1,339 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics.Contracts;
+using System.Security;
+
+namespace System.Text
+{
+ // Shared implementations for commonly overriden Encoding methods
+
+ internal static class EncodingForwarder
+ {
+ // We normally have to duplicate a lot of code between UTF8Encoding,
+ // UTF7Encoding, EncodingNLS, etc. because we want to override many
+ // of the methods in all of those classes to just forward to the unsafe
+ // version. (e.g. GetBytes(char[]))
+ // Ideally, everything would just derive from EncodingNLS, but that's
+ // not exposed in the public API, and C# prohibits a public class from
+ // inheriting from an internal one. So, we have to override each of the
+ // methods in question and repeat the argument validation/logic.
+
+ // These set of methods exist so instead of duplicating code, we can
+ // simply have those overriden methods call here to do the actual work.
+
+ // NOTE: This class should ONLY be called from Encodings that override
+ // the internal methods which accept an Encoder/DecoderNLS. The reason
+ // for this is that by default, those methods just call the same overload
+ // except without the encoder/decoder parameter. If an overriden method
+ // without that parameter calls this class, which calls the overload with
+ // the parameter, it will call the same method again, which will eventually
+ // lead to a StackOverflowException.
+
+ [SecuritySafeCritical]
+ public unsafe static int GetByteCount(Encoding encoding, char[] chars, int index, int count)
+ {
+ // Validate parameters
+
+ Contract.Assert(encoding != null); // this parameter should only be affected internally, so just do a debug check here
+ if (chars == null)
+ {
+ throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (index < 0 || count < 0)
+ {
+ throw new ArgumentOutOfRangeException(index < 0 ? "index" : "count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (chars.Length - index < count)
+ {
+ throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ }
+ Contract.EndContractBlock();
+
+ // If no input, return 0, avoid fixed empty array problem
+ if (count == 0)
+ return 0;
+
+ // Just call the (internal) pointer version
+ fixed (char* pChars = chars)
+ return encoding.GetByteCount(pChars + index, count, encoder: null);
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static int GetByteCount(Encoding encoding, string s)
+ {
+ Contract.Assert(encoding != null);
+ if (s == null)
+ {
+ string paramName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the string chars
+ // UTF8Encoding does this as well, but it originally threw an ArgumentNull for "s" so don't check for that
+ throw new ArgumentNullException(paramName);
+ }
+ Contract.EndContractBlock();
+
+ // NOTE: The behavior of fixed *is* defined by
+ // the spec for empty strings, although not for
+ // null strings/empty char arrays. See
+ // http://stackoverflow.com/q/37757751/4077294
+ // Regardless, we may still want to check
+ // for if (s.Length == 0) in the future
+ // and short-circuit as an optimization (TODO).
+
+ fixed (char* pChars = s)
+ return encoding.GetByteCount(pChars, s.Length, encoder: null);
+ }
+
+ [SecurityCritical]
+ public unsafe static int GetByteCount(Encoding encoding, char* chars, int count)
+ {
+ Contract.Assert(encoding != null);
+ if (chars == null)
+ {
+ throw new ArgumentNullException("chars", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ // Call the internal version, with an empty encoder
+ return encoding.GetByteCount(chars, count, encoder: null);
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static int GetBytes(Encoding encoding, string s, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ Contract.Assert(encoding != null);
+ if (s == null || bytes == null)
+ {
+ string stringName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the first parameter chars
+ throw new ArgumentNullException(s == null ? stringName : "bytes", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (charIndex < 0 || charCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? "charIndex" : "charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (s.Length - charIndex < charCount)
+ {
+ string stringName = encoding is ASCIIEncoding ? "chars" : "s"; // ASCIIEncoding calls the first parameter chars
+ // Duplicate the above check since we don't want the overhead of a type check on the general path
+ throw new ArgumentOutOfRangeException(stringName, Environment.GetResourceString("ArgumentOutOfRange_IndexCount"));
+ }
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ {
+ throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ int byteCount = bytes.Length - byteIndex;
+
+ // Fixed doesn't like empty arrays
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ fixed (char* pChars = s) fixed (byte* pBytes = bytes)
+ {
+ return encoding.GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, encoder: null);
+ }
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static int GetBytes(Encoding encoding, char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ Contract.Assert(encoding != null);
+ if (chars == null || bytes == null)
+ {
+ throw new ArgumentNullException(chars == null ? "chars" : "bytes", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (charIndex < 0 || charCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(charIndex < 0 ? "charIndex" : "charCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (chars.Length - charIndex < charCount)
+ {
+ throw new ArgumentOutOfRangeException("chars", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ }
+ if (byteIndex < 0 || byteIndex > bytes.Length)
+ {
+ throw new ArgumentOutOfRangeException("byteIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ // If nothing to encode return 0, avoid fixed problem
+ if (charCount == 0)
+ return 0;
+
+ // Note that this is the # of bytes to decode,
+ // not the size of the array
+ int byteCount = bytes.Length - byteIndex;
+
+ // Fixed doesn't like 0 length arrays.
+ if (bytes.Length == 0)
+ bytes = new byte[1];
+
+ // Just call the (internal) pointer version
+ fixed (char* pChars = chars) fixed (byte* pBytes = bytes)
+ {
+ return encoding.GetBytes(pChars + charIndex, charCount, pBytes + byteIndex, byteCount, encoder: null);
+ }
+ }
+
+ [SecurityCritical]
+ public unsafe static int GetBytes(Encoding encoding, char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null || chars == null)
+ {
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (charCount < 0 || byteCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(charCount < 0 ? "charCount" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ return encoding.GetBytes(chars, charCount, bytes, byteCount, encoder: null);
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static int GetCharCount(Encoding encoding, byte[] bytes, int index, int count)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (index < 0 || count < 0)
+ {
+ throw new ArgumentOutOfRangeException(index < 0 ? "index" : "count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (bytes.Length - index < count)
+ {
+ throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ }
+ Contract.EndContractBlock();
+
+ // If no input just return 0, fixed doesn't like 0 length arrays.
+ if (count == 0)
+ return 0;
+
+ // Just call pointer version
+ fixed (byte* pBytes = bytes)
+ return encoding.GetCharCount(pBytes + index, count, decoder: null);
+ }
+
+ [SecurityCritical]
+ public unsafe static int GetCharCount(Encoding encoding, byte* bytes, int count)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ return encoding.GetCharCount(bytes, count, decoder: null);
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static int GetChars(Encoding encoding, byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null || chars == null)
+ {
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (byteIndex < 0 || byteCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(byteIndex < 0 ? "byteIndex" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (bytes.Length - byteIndex < byteCount)
+ {
+ throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ }
+ if (charIndex < 0 || charIndex > chars.Length)
+ {
+ throw new ArgumentOutOfRangeException("charIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.EndContractBlock();
+
+ if (byteCount == 0)
+ return 0;
+
+ // NOTE: This is the # of chars we can decode,
+ // not the size of the array
+ int charCount = chars.Length - charIndex;
+
+ // Fixed doesn't like 0 length arrays.
+ if (chars.Length == 0)
+ chars = new char[1];
+
+ fixed (byte* pBytes = bytes) fixed (char* pChars = chars)
+ {
+ return encoding.GetChars(pBytes + byteIndex, byteCount, pChars + charIndex, charCount, decoder: null);
+ }
+ }
+
+ [SecurityCritical]
+ public unsafe static int GetChars(Encoding encoding, byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null || chars == null)
+ {
+ throw new ArgumentNullException(bytes == null ? "bytes" : "chars", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (charCount < 0 || byteCount < 0)
+ {
+ throw new ArgumentOutOfRangeException(charCount < 0 ? "charCount" : "byteCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.EndContractBlock();
+
+ return encoding.GetChars(bytes, byteCount, chars, charCount, decoder: null);
+ }
+
+ [SecuritySafeCritical]
+ public unsafe static string GetString(Encoding encoding, byte[] bytes, int index, int count)
+ {
+ Contract.Assert(encoding != null);
+ if (bytes == null)
+ {
+ throw new ArgumentNullException("bytes", Environment.GetResourceString("ArgumentNull_Array"));
+ }
+ if (index < 0 || count < 0)
+ {
+ // ASCIIEncoding has different names for its parameters here (byteIndex, byteCount)
+ bool ascii = encoding is ASCIIEncoding;
+ string indexName = ascii ? "byteIndex" : "index";
+ string countName = ascii ? "byteCount" : "count";
+ throw new ArgumentOutOfRangeException(index < 0 ? indexName : countName, Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ if (bytes.Length - index < count)
+ {
+ throw new ArgumentOutOfRangeException("bytes", Environment.GetResourceString("ArgumentOutOfRange_IndexCountBuffer"));
+ }
+ Contract.EndContractBlock();
+
+ // Avoid problems with empty input buffer
+ if (count == 0)
+ return string.Empty;
+
+ // Call string.CreateStringFromEncoding here, which
+ // allocates a string and lets the Encoding modify
+ // it in place. This way, we don't have to allocate
+ // an intermediary char[] to decode into and then
+ // call the string constructor; instead we decode
+ // directly into the string.
+
+ fixed (byte* pBytes = bytes)
+ {
+ return string.CreateStringFromEncoding(pBytes + index, count, encoding);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncodingInfo.cs b/src/mscorlib/src/System/Text/EncodingInfo.cs
new file mode 100644
index 0000000000..26ad3344c6
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncodingInfo.cs
@@ -0,0 +1,74 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Text;
+
+
+ [Serializable]
+ public sealed class EncodingInfo
+ {
+ int iCodePage; // Code Page #
+ String strEncodingName; // Short name (web name)
+ String strDisplayName; // Full localized name
+
+ internal EncodingInfo(int codePage, string name, string displayName)
+ {
+ this.iCodePage = codePage;
+ this.strEncodingName = name;
+ this.strDisplayName = displayName;
+ }
+
+
+ public int CodePage
+ {
+ get
+ {
+ return iCodePage;
+ }
+ }
+
+
+ public String Name
+ {
+ get
+ {
+ return strEncodingName;
+ }
+ }
+
+
+ public String DisplayName
+ {
+ get
+ {
+ return strDisplayName;
+ }
+ }
+
+
+ public Encoding GetEncoding()
+ {
+ return Encoding.GetEncoding(this.iCodePage);
+ }
+
+ public override bool Equals(Object value)
+ {
+ EncodingInfo that = value as EncodingInfo;
+ if (that != null)
+ {
+ return (this.CodePage == that.CodePage);
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return this.CodePage;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncodingNLS.cs b/src/mscorlib/src/System/Text/EncodingNLS.cs
new file mode 100644
index 0000000000..d670d6daa7
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncodingNLS.cs
@@ -0,0 +1,130 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Collections;
+ using System.Runtime.Remoting;
+ using System.Globalization;
+ using System.Threading;
+ using Win32Native = Microsoft.Win32.Win32Native;
+
+ // This class overrides Encoding with the things we need for our NLS Encodings
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ internal abstract class EncodingNLS : Encoding
+ {
+ protected EncodingNLS(int codePage) : base(codePage)
+ {
+ }
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ public override int GetByteCount(String s)
+ {
+ return EncodingForwarder.GetByteCount(this, s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ public override int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, s, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ public override String GetString(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetString(this, bytes, index, count);
+ }
+
+ public override Decoder GetDecoder()
+ {
+ return new DecoderNLS(this);
+ }
+
+ public override Encoder GetEncoder()
+ {
+ return new EncoderNLS(this);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/EncodingProvider.cs b/src/mscorlib/src/System/Text/EncodingProvider.cs
new file mode 100644
index 0000000000..b1dea2cd3c
--- /dev/null
+++ b/src/mscorlib/src/System/Text/EncodingProvider.cs
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class EncodingProvider
+ {
+ public EncodingProvider() { }
+ public abstract Encoding GetEncoding(string name);
+ public abstract Encoding GetEncoding(int codepage);
+
+ // GetEncoding should return either valid encoding or null. shouldn't throw any exception except on null name
+ public virtual Encoding GetEncoding(string name, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
+ {
+ Encoding enc = GetEncoding(name);
+ if (enc != null)
+ {
+ enc = (Encoding)GetEncoding(name).Clone();
+ enc.EncoderFallback = encoderFallback;
+ enc.DecoderFallback = decoderFallback;
+ }
+
+ return enc;
+ }
+
+ public virtual Encoding GetEncoding(int codepage, EncoderFallback encoderFallback, DecoderFallback decoderFallback)
+ {
+ Encoding enc = GetEncoding(codepage);
+ if (enc != null)
+ {
+ enc = (Encoding)GetEncoding(codepage).Clone();
+ enc.EncoderFallback = encoderFallback;
+ enc.DecoderFallback = decoderFallback;
+ }
+
+ return enc;
+ }
+
+ internal static void AddProvider(EncodingProvider provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException("provider");
+
+ lock (s_InternalSyncObject)
+ {
+ if (s_providers == null)
+ {
+ s_providers = new EncodingProvider[1] { provider };
+ return;
+ }
+
+ if (Array.IndexOf(s_providers, provider) >= 0)
+ {
+ return;
+ }
+
+ var providers = new EncodingProvider[s_providers.Length + 1];
+ Array.Copy(s_providers, providers, s_providers.Length);
+ providers[providers.Length - 1] = provider;
+ s_providers = providers;
+ }
+ }
+
+ internal static Encoding GetEncodingFromProvider(int codepage)
+ {
+ if (s_providers == null)
+ return null;
+
+ var providers = s_providers;
+ foreach (EncodingProvider provider in providers)
+ {
+ Encoding enc = provider.GetEncoding(codepage);
+ if (enc != null)
+ return enc;
+ }
+
+ return null;
+ }
+
+ internal static Encoding GetEncodingFromProvider(string encodingName)
+ {
+ if (s_providers == null)
+ return null;
+
+ var providers = s_providers;
+ foreach (EncodingProvider provider in providers)
+ {
+ Encoding enc = provider.GetEncoding(encodingName);
+ if (enc != null)
+ return enc;
+ }
+
+ return null;
+ }
+
+ internal static Encoding GetEncodingFromProvider(int codepage, EncoderFallback enc, DecoderFallback dec)
+ {
+ if (s_providers == null)
+ return null;
+
+ var providers = s_providers;
+ foreach (EncodingProvider provider in providers)
+ {
+ Encoding encing = provider.GetEncoding(codepage, enc, dec);
+ if (encing != null)
+ return encing;
+ }
+
+ return null;
+ }
+
+ internal static Encoding GetEncodingFromProvider(string encodingName, EncoderFallback enc, DecoderFallback dec)
+ {
+ if (s_providers == null)
+ return null;
+
+ var providers = s_providers;
+ foreach (EncodingProvider provider in providers)
+ {
+ Encoding encoding = provider.GetEncoding(encodingName, enc, dec);
+ if (encoding != null)
+ return encoding;
+ }
+
+ return null;
+ }
+
+ private static Object s_InternalSyncObject = new Object();
+ private static volatile EncodingProvider[] s_providers;
+ }
+}
diff --git a/src/mscorlib/src/System/Text/GB18030Encoding.cs b/src/mscorlib/src/System/Text/GB18030Encoding.cs
new file mode 100644
index 0000000000..98746fcdb0
--- /dev/null
+++ b/src/mscorlib/src/System/Text/GB18030Encoding.cs
@@ -0,0 +1,1377 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+// Ported to managed code from c_gb18030.c and related gb18030 dll files
+//
+//
+// Abstract:
+//
+// Managed implementation of GB18030-2000 (code page 54936) ported from implimentation in c_g18030.dll
+// This file contains functions to convert GB18030-2000 (code page 54936) into Unicode, and vice versa.
+//
+// Notes:
+// GB18030-2000 (aka GBK2K) is designed to be mostly compatible with GBK (codepage 936),
+// while supports the full range of Unicode code points (BMP + 16 supplementary planes).
+//
+// The structure for GB18030 is:
+// * Single byte:
+// 0x00 ~ 0x7f
+// * Two-byte:
+// 0x81 ~ 0xfe, 0x40 ~ 0x7e (leading byte, trailing byte)
+// 0x81 ~ 0xfe, 0x80 ~ 0xfe (leading byte, trailing byte)
+// * Four-byte:
+// 0x81 ~ 0xfe, 0x30 ~ 0x39, 0x81 ~ 0xfe, 0x30 ~ 0x39.
+// The surrogare pair will be encoded from 0x90, 0x30, 0x81, 0x30
+//
+// The BMP range is fully supported in GB18030 using 1-byte, 2-byte and 4-byte sequences.
+// In valid 4-byte GB18030, there are two gaps that can not be mapped to Unicode characters.
+// 0x84, 0x31, 0xa5, 0x30 (just after the GB18030 bytes for U+FFFF(*)) ~ 0x8f, 0x39, 0xfe, 0x39 (just before the first GB18030 bytes for U+D800,U+DC00)
+// 0xe3, 0x32, 0x9a, 0x36 (just after the GB18030 bytes for U+DBFF U+DFFF(**)) ~ 0xfe, 0x39, 0xfe, 0x39
+//
+//
+// Note1: U+FFFF = 0x84, 0x31, 0xa4, 0x39
+// Note2: U+DBFF U+DFFF = 0xe3, 0x32, 0x9a, 0x35
+//
+// Tables used in GB18030Encoding:
+//
+// Our data is similar to the 936 Code Page, so we start from there to build our tables. We build the
+// normal double byte mapUnicodeToBytes and mapBytesToUnicode tables by applying differences from 936.
+// We also build a map4BytesToUnicode table and a mapUnicodeTo4BytesFlags
+//
+// * mapUnicodeTo4BytesFlags
+// This is an array of bytes, so we have to do a / 8 and << %8 to check the appropriate bit (see Is4Byte())
+// If the bit is set its true.
+//
+// true - If set/true this is a 4 byte code. The value in mapUnicodeToBytes will be the 4 byte offset
+// false - If cleared/false this is a 1 or 2 byte code. The value in mapUnicodeToBytes will be the 2 bytes.
+//
+// * mapUnicodeToBytes
+// Contains either the 2 byte value of double byte GB18030 or the 4 byte offset for 4 byte GB18030,
+// depending on the value of the flag in mapUnicodeTo4BytesFlags
+//
+// * mapBytesToUnicode
+// mapBytesToUnicode maps 2 byte GB 18030 to Unicode like other DBCS code pages.
+//
+// * map4BytesToUnicode
+// map4BytesToUnicode is indexed by the 4 byte offset and contains the unicode value for each 4 byte offset
+//
+//
+// 4 Byte sequences
+// We generally use the offset for the 4 byte sequence, such as:
+//
+// The index value is the offset of the 4-byte GB18030.
+//
+// 4-byte GB18030 Index value
+// ============== ===========
+// 81,30,81,30 0
+// 81,30,81,31 1
+// 81,30,81,32 2
+// ... ...
+//
+// The value of map4BytesToUnicode cotains the Unicode codepoint for the offset of the
+// corresponding 4-byte GB18030.
+//
+// E.g. map4BytesToUnicode[0] = 0x0080. This means that GB18030 0x81, 0x30, 0x81, 0x30 will be converted to Unicode U+0800.
+//
+// 4 Byte Surrogate Sequences
+// Those work similarly to the normal 4 byte sequences, but start at a different offset
+//
+// We don't override IsAlwaysNormalized because GB18030 covers all of the unicode space, so isn't guaranteed to be normal.
+//
+#if FEATURE_CODEPAGES_FILE // requires BaseCodePageEncooding
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security.Permissions;
+ using System.Globalization;
+
+ /*=================================GB18030Encoding============================
+ **
+ ** This is used to support GB18030-2000 encoding (code page 54936).
+ **
+ ==============================================================================*/
+
+ [Serializable]
+ internal sealed class GB18030Encoding : DBCSCodePageEncoding, ISerializable
+ {
+ // This is the table of 4 byte conversions.
+ private const int GBLast4ByteCode = 0x99FB;
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe internal char* map4BytesToUnicode = null; // new char[GBLast4ByteCode + 1]; // Need to map all 4 byte sequences to Unicode
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe internal byte* mapUnicodeTo4BytesFlags = null; // new byte[0x10000 / 8]; // Need 1 bit for each code point to say if its 4 byte or not
+
+ private const int GB18030 = 54936;
+
+ // First and last character of surrogate range as offset from 4 byte GB18030 GB81308130
+ private const int GBSurrogateOffset = 0x2E248; // GB90308130
+ private const int GBLastSurrogateOffset = 0x12E247; // GBE3329A35
+
+ // We have to load the 936 code page tables, so impersonate 936 as our base
+ [System.Security.SecurityCritical] // auto-generated
+ internal GB18030Encoding() : base(GB18030, 936)
+ {
+ }
+
+ // Constructor called by serialization.
+ [System.Security.SecurityCritical] // auto-generated
+ internal GB18030Encoding(SerializationInfo info, StreamingContext context) :
+ base(GB18030, 936)
+ {
+ // Set up our base, also throws if info was empty
+ DeserializeEncoding(info, context);
+ Contract.Assert(info!=null, "[GB18030Encoding(Serialization...)] Expected null info to throw");
+
+ // Already build our code page, fallbacks & read only, so we're good to go!
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Make sure to get the base stuff too This throws if info is null
+ SerializeEncoding(info, context);
+ Contract.Assert(info!=null, "[GB18030.GetObjectData] Expected null info to throw");
+
+ // Everett doesn't need more than the basics
+ }
+
+ // This loads our base 936 code page and then applys the changes from the tableUnicodeToGBDiffs table.
+ // See table comments for table format.
+ [System.Security.SecurityCritical] // auto-generated
+ protected override unsafe void LoadManagedCodePage()
+ {
+ // Use base code page loading algorithm.
+ // We need to use our main CP as our flag.
+ this.bFlagDataTable = false;
+ this.iExtraBytes = (GBLast4ByteCode + 1) * 2 + 0x10000 / 8;
+
+ // Load most of our code page
+ base.LoadManagedCodePage();
+
+ // Point to our new data sections
+ byte *pMemorySection = (byte *) safeMemorySectionHandle.DangerousGetHandle();
+ mapUnicodeTo4BytesFlags = pMemorySection + 65536 * 2 * 2;
+ map4BytesToUnicode = (char*)(pMemorySection + 65536 * 2 * 2 + 0x10000 / 8);
+
+ // Need to check our pointer to see if we're loaded, return if we're built already
+ if (*mapCodePageCached == this.CodePage)
+ return;
+
+ // Once we've done our base LoadManagedCodePage, we'll have to add our fixes
+ char unicodeCount = (char)0;
+ ushort count4Byte = 0;
+ for (int index = 0; index < tableUnicodeToGBDiffs.Length; index++)
+ {
+ ushort data = tableUnicodeToGBDiffs[index];
+
+ // Check high bit
+ if ((data & 0x8000) != 0)
+ {
+ // Make be exact value
+ if (data > 0x9000 && data != 0xD1A6)
+ {
+ // It was an exact value (gb18040[data] = unicode)
+ mapBytesToUnicode[data] = unicodeCount;
+ mapUnicodeToBytes[unicodeCount] = data;
+ unicodeCount++;
+ }
+ else
+ {
+ // It was a CP 936 compatible data, that table's already loaded, just increment our pointer
+ unicodeCount += unchecked((char)(data & 0x7FFF));
+ }
+ }
+ else
+ {
+ // It was GB 18030 4 byte data, next <data> characters are 4 byte sequences.
+ while (data > 0)
+ {
+ Contract.Assert(count4Byte <= GBLast4ByteCode,
+ "[GB18030Encoding.LoadManagedCodePage] Found too many 4 byte codes in data table.");
+
+ // Set the 4 byte -> Unicode value
+ map4BytesToUnicode[count4Byte] = unicodeCount;
+ // Set the unicode -> 4 bytes value, including flag that its a 4 byte sequence
+ mapUnicodeToBytes[unicodeCount] = count4Byte;
+ // Set the flag saying its a 4 byte sequence
+ mapUnicodeTo4BytesFlags[unicodeCount / 8] |= unchecked((byte)(1 << (unicodeCount % 8)));
+ unicodeCount++;
+ count4Byte++;
+ data--;
+ }
+
+ }
+ }
+
+ // unicodeCount should've wrapped back to 0
+ Contract.Assert(unicodeCount == 0,
+ "[GB18030Encoding.LoadManagedCodePage] Expected unicodeCount to wrap around to 0 as all chars were processed");
+
+ // We should've read in GBLast4ByteCode 4 byte sequences
+ Contract.Assert(count4Byte == GBLast4ByteCode + 1,
+ "[GB18030Encoding.LoadManagedCodePage] Expected 0x99FB to be last 4 byte offset, found 0x" + count4Byte.ToString("X4", CultureInfo.InvariantCulture));
+
+ // Need to flag ourselves saying we've built this CP.
+ *mapCodePageCached = this.CodePage;
+ }
+
+ internal override void SetDefaultFallbacks()
+ {
+ // For GB18030Encoding just use default replacement fallbacks because its only for bad surrogates
+ this.encoderFallback = EncoderFallback.ReplacementFallback;
+ this.decoderFallback = DecoderFallback.ReplacementFallback;
+ }
+
+ // Is4Byte
+ // Checks the 4 byte table and returns true if this is a 4 byte code.
+ // Its a 4 byte code if the flag is set in mapUnicodeTo4BytesFlags
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe bool Is4Byte(char charTest)
+ {
+ // See what kind it is
+ byte b4Byte = mapUnicodeTo4BytesFlags[charTest / 8];
+ return (b4Byte != 0 && (b4Byte & (1 << (charTest % 8))) != 0);
+ }
+
+ // GetByteCount
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ {
+ // Just call GetBytes() with null bytes
+ return GetBytes(chars, count, null, 0, encoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ // We'll allow null bytes as a count
+// Contract.Assert(bytes != null, "[GB18030Encoding.GetBytes]bytes is null");
+ Contract.Assert(byteCount >= 0, "[GB18030Encoding.GetBytes]byteCount is negative");
+ Contract.Assert(chars != null, "[GB18030Encoding.GetBytes]chars is null");
+ Contract.Assert(charCount >= 0, "[GB18030Encoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[GB18030Encoding.GetBytes]Attempting to use null encoder fallback");
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ if (encoder != null)
+ charLeftOver = encoder.charLeftOver;
+
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ // Try again if we were MustFlush
+ TryAgain:
+
+ // Go ahead and do it, including the fallback.
+ while (buffer.MoreData)
+ {
+ // Get next char
+ char ch = buffer.GetNextChar();
+
+ // Have to check for charLeftOver
+ if (charLeftOver != 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver),
+ "[GB18030Encoding.GetBytes] leftover character should be high surrogate, not 0x" + ((int)charLeftOver).ToString("X4", CultureInfo.InvariantCulture));
+
+ // If our next char isn't a low surrogate, then we need to do fallback.
+ if (!Char.IsLowSurrogate(ch))
+ {
+ // No low surrogate, fallback high surrogate & try this one again
+ buffer.MovePrevious(false); // (Ignoring this character, don't thow)
+ if (!buffer.Fallback(charLeftOver))
+ {
+ charLeftOver = (char)0;
+ break;
+ }
+ charLeftOver = (char)0;
+ continue;
+ }
+ else
+ {
+ // Next is a surrogate, add it as surrogate pair
+
+ // Need 4 bytes for surrogates
+ // Get our offset
+ int offset = ((charLeftOver - 0xd800) << 10) + (ch - 0xdc00);
+
+ byte byte4 = (byte)((offset % 0x0a) + 0x30);
+ offset /= 0x0a;
+ byte byte3 = (byte)((offset % 0x7e) + 0x81);
+ offset /= 0x7e;
+ byte byte2 = (byte)((offset % 0x0a) + 0x30);
+ offset /= 0x0a;
+ Contract.Assert(offset < 0x6f,
+ "[GB18030Encoding.GetBytes](1) Expected offset < 0x6f, not 0x" + offset.ToString("X2", CultureInfo.InvariantCulture));
+
+ charLeftOver = (char)0;
+ if (!buffer.AddByte((byte)(offset + 0x90),byte2,byte3,byte4))
+ {
+ // Didn't work, need to back up for both surrogates (AddByte already backed up one)
+ buffer.MovePrevious(false); // (don't throw)
+ break;
+ }
+ }
+ charLeftOver = '\0';
+ }
+ // ASCII's easiest
+ else if (ch <= 0x7f)
+ {
+ // Need a byte
+ if (!buffer.AddByte((byte)ch))
+ break;
+ }
+ // See if its a surrogate pair
+ else if (Char.IsHighSurrogate(ch))
+ {
+ // Remember it for next time
+ charLeftOver = ch;
+ }
+ else if (Char.IsLowSurrogate(ch))
+ {
+ // Low surrogates should've been found already
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ else
+ {
+ // Not surrogate or ASCII, get value
+ ushort iBytes = mapUnicodeToBytes[ch];
+
+ // See what kind it is
+ if (Is4Byte(ch))
+ {
+ //
+ // This Unicode character will be converted to four-byte GB18030.
+ //
+ // Need 4 bytes
+ byte byte4 = (byte)((iBytes % 0x0a) + 0x30);
+ iBytes /= 0x0a;
+ byte byte3 = (byte)((iBytes % 0x7e) + 0x81);
+ iBytes /= 0x7e;
+ byte byte2 = (byte)((iBytes % 0x0a) + 0x30);
+ iBytes /= 0x0a;
+ Contract.Assert(iBytes < 0x7e,
+ "[GB18030Encoding.GetBytes]Expected iBytes < 0x7e, not 0x" + iBytes.ToString("X2", CultureInfo.InvariantCulture));
+ if (!buffer.AddByte((byte)(iBytes + 0x81), byte2, byte3, byte4))
+ break;
+ }
+ else
+ {
+ // Its 2 byte, use it
+ if (!buffer.AddByte(unchecked((byte)(iBytes >> 8)), unchecked((byte)(iBytes & 0xff))))
+ break;
+ }
+ }
+ }
+
+ // Do we need to flush our charLeftOver?
+ if ((encoder == null || encoder.MustFlush) && (charLeftOver > 0))
+ {
+ // Fall it back
+ buffer.Fallback(charLeftOver);
+ charLeftOver = (char)0;
+ goto TryAgain;
+ }
+
+ // Fallback stuck it in encoder if necessary, but we have to clear MustFlash cases
+ // (Check bytes != null, don't clear it if we're just counting)
+ if (encoder != null)
+ {
+ // Remember our charLeftOver
+ if (bytes != null)
+ encoder.charLeftOver = charLeftOver;
+
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ // Return our length
+ return buffer.Count;
+ }
+
+ // Helper methods
+ internal bool IsGBLeadByte(short ch)
+ {
+ // return true if we're in the lead byte range
+ return ((ch) >= 0x81 && (ch) <= 0xfe);
+ }
+
+ internal bool IsGBTwoByteTrailing(short ch)
+ {
+ // Return true if we are in range for the trailing byte of a 2 byte sequence
+ return (((ch) >= 0x40 && (ch) <= 0x7e) ||
+ ((ch) >= 0x80 && (ch) <= 0xfe));
+ }
+
+ internal bool IsGBFourByteTrailing(short ch)
+ {
+ // Return true if we are in range for the trailing byte of a 4 byte sequence
+ return ((ch) >= 0x30 && (ch) <= 0x39);
+ }
+
+ internal int GetFourBytesOffset(short offset1, short offset2, short offset3, short offset4)
+ {
+ return ((offset1 - 0x81) * 0x0a * 0x7e * 0x0a +
+ (offset2 - 0x30) * 0x7e * 0x0a +
+ (offset3 - 0x81) * 0x0a +
+ offset4 - 0x30);
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ // Just call GetChars() with null chars to count
+ return GetChars(bytes, count, null, 0, baseDecoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ // We'll allow null chars as a count
+ Contract.Assert(bytes != null, "[GB18030Encoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[GB18030Encoding.GetChars]byteCount is negative");
+// Contract.Assert(chars != null, "[GB18030Encoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[GB18030Encoding.GetChars]charCount is negative");
+
+ // Fix our decoder
+ GB18030Decoder decoder = (GB18030Decoder)baseDecoder;
+
+ // Get our info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ // Need temp bytes because we can't muss up decoder
+ short byte1 = -1;
+ short byte2 = -1;
+ short byte3 = -1;
+ short byte4 = -1;
+
+ // See if there was anything to get out of the decoder
+ if (decoder != null && decoder.bLeftOver1 != -1)
+ {
+ // Need temp bytes because we can't muss up decoder
+ byte1 = decoder.bLeftOver1;
+ byte2 = decoder.bLeftOver2;
+ byte3 = decoder.bLeftOver3;
+ byte4 = decoder.bLeftOver4;
+
+ // Loop because we might have too many in buffer
+ // This could happen if we are working on a 4 byte sequence, but it isn't valid.
+ while (byte1 != -1)
+ {
+ // If its not a lead byte, use ? or its value, then scoot them down & try again
+ // This could happen if we previously had a bad 4 byte sequence and this is a trail byte
+ if (!IsGBLeadByte(byte1))
+ {
+ // This is either a ? or ASCII, need 1 char output
+ if (byte1 <= 0x7f)
+ {
+ if (!buffer.AddChar((char)byte1)) // Its ASCII
+ break;
+ }
+ else
+ {
+ if (!buffer.Fallback((byte)byte1)) // Not a valid byte
+ break;
+ }
+
+ byte1 = byte2;
+ byte2 = byte3;
+ byte3 = byte4;
+ byte4 = -1;
+ continue;
+ }
+
+ // Read in more bytes as needed
+ while (byte2 == -1 ||
+ (IsGBFourByteTrailing(byte2) && byte4 == -1))
+ {
+ // Do we have room?
+ if (!buffer.MoreData)
+ {
+ // No input left to read, do we have to flush?
+ if (!decoder.MustFlush)
+ {
+ // Don't stick stuff in decoder when counting
+ if (chars != null)
+ {
+ // Don't have to flush, won't have any chars
+ // Decoder is correct, just return
+ decoder.bLeftOver1 = byte1;
+ decoder.bLeftOver2 = byte2;
+ decoder.bLeftOver3 = byte3;
+ decoder.bLeftOver4 = byte4;
+ }
+
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ return buffer.Count;
+ }
+
+ // We'll have to flush, add a ? and scoot them down to try again
+ // We could be trying for a 4 byte sequence but byte 3 could be ascii and should be spit out
+ // Breaking will do this because we have zeros
+ break;
+ }
+
+ // Read them in
+ if (byte2 == -1) byte2 = buffer.GetNextByte();
+ else if (byte3 == -1) byte3 = buffer.GetNextByte();
+ else byte4 = buffer.GetNextByte();
+ }
+
+ // Now we have our 2 or 4 bytes
+ if (IsGBTwoByteTrailing(byte2))
+ {
+ //
+ // The trailing byte is a GB18030 two-byte sequence trailing byte.
+ //
+ int iTwoBytes = byte1 << 8;
+ iTwoBytes |= unchecked((byte)byte2);
+ if (!buffer.AddChar(this.mapBytesToUnicode[iTwoBytes], 2))
+ break;
+
+ // We're done with it
+ byte1 = -1;
+ byte2 = -1;
+ }
+ else if (IsGBFourByteTrailing(byte2) &&
+ IsGBLeadByte(byte3) &&
+ IsGBFourByteTrailing(byte4))
+ {
+ //
+ // Four-byte GB18030
+ //
+
+ int sFourBytesOffset = GetFourBytesOffset(
+ byte1, byte2, byte3, byte4);
+
+ // What kind is it?
+ if (sFourBytesOffset <= GBLast4ByteCode)
+ {
+ //
+ // The Unicode will be in the BMP range.
+ //
+ if (!buffer.AddChar(map4BytesToUnicode[sFourBytesOffset], 4))
+ break;
+ }
+ else if (sFourBytesOffset >= GBSurrogateOffset &&
+ sFourBytesOffset <= GBLastSurrogateOffset)
+ {
+ //
+ // This will be converted to a surrogate pair, need another char
+ //
+
+ // Use our surrogate
+ sFourBytesOffset -= GBSurrogateOffset;
+ if (!buffer.AddChar(unchecked((char)(0xd800 + (sFourBytesOffset / 0x400))),
+ unchecked((char)(0xdc00 + (sFourBytesOffset % 0x400))), 4))
+ break;
+ }
+ else
+ {
+ // Real GB18030 codepoint, but can't be mapped to unicode
+ // We already checked our buffer space.
+ // Do fallback here if we impliment decoderfallbacks.
+ if (!buffer.Fallback((byte)byte1, (byte)byte2, (byte)byte3, (byte)byte4))
+ break;
+ }
+
+ // We're done with this one
+ byte1 = -1;
+ byte2 = -1;
+ byte3 = -1;
+ byte4 = -1;
+ }
+ else
+ {
+ // Not a valid sequence, use '?' for 1st byte & scoot them all down 1
+ if (!buffer.Fallback((byte)byte1))
+ break;
+
+ // Move all bytes down 1
+ byte1 = byte2;
+ byte2 = byte3;
+ byte3 = byte4;
+ byte4 = -1;
+ }
+ }
+ }
+
+ // Loop, just do '?' replacement because we don't have fallbacks for decodings.
+ while (buffer.MoreData)
+ {
+ byte ch = buffer.GetNextByte();
+
+ // ASCII case is easy
+ if (ch <= 0x7f)
+ {
+ // ASCII, have room?
+ if (!buffer.AddChar((char)ch))
+ break; // No room in convert buffer, so stop
+ }
+ // See if its a lead byte
+ else if (IsGBLeadByte(ch))
+ {
+ // ch is a lead byte, have room for more?
+ if (buffer.MoreData)
+ {
+ byte ch2 = buffer.GetNextByte();
+ if (IsGBTwoByteTrailing(ch2))
+ {
+ //
+ // The trailing byte is a GB18030 two-byte sequence trailing byte.
+ //
+
+ //
+ // Two-byte GB18030
+ //
+ int iTwoBytes = ch << 8;
+ iTwoBytes |= ch2;
+ if (!buffer.AddChar(this.mapBytesToUnicode[iTwoBytes], 2))
+ break;
+ }
+ else if (IsGBFourByteTrailing(ch2))
+ {
+ // Do we have room for Four Byte Sequence? (already have 1 byte)
+ if (buffer.EvenMoreData(2))
+ {
+ // Is it a valid 4 byte sequence?
+ byte ch3 = buffer.GetNextByte();
+ byte ch4 = buffer.GetNextByte();
+ if (IsGBLeadByte(ch3) &&
+ IsGBFourByteTrailing(ch4))
+ {
+ //
+ // Four-byte GB18030
+ //
+ int sFourBytesOffset = GetFourBytesOffset(ch, ch2, ch3, ch4);
+
+ // What kind is it?
+ // We'll be at least 1 BMP char or a '?' char.
+
+ if (sFourBytesOffset <= GBLast4ByteCode)
+ {
+ //
+ // The Unicode will be in the BMP range.
+ //
+ if (!buffer.AddChar(map4BytesToUnicode[sFourBytesOffset],4))
+ break;
+ }
+ else if (sFourBytesOffset >= GBSurrogateOffset &&
+ sFourBytesOffset <= GBLastSurrogateOffset)
+ {
+ //
+ // This will be converted to a surrogate pair, need another char
+ //
+
+ // Use our surrogate
+ sFourBytesOffset -= GBSurrogateOffset;
+ if (!buffer.AddChar(unchecked((char)(0xd800 + (sFourBytesOffset / 0x400))),
+ unchecked((char)(0xdc00 + (sFourBytesOffset % 0x400))),4))
+ break;
+ }
+ else
+ {
+ // Real GB18030 codepoint, but can't be mapped to unicode
+ if (!buffer.Fallback(ch, ch2, ch3, ch4))
+ break;
+ }
+ }
+ else
+ {
+ // Not a valid 2 or 4 byte sequence, use '?' for ch and try other 3 again
+ buffer.AdjustBytes(-3);
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+ else
+ {
+ // No room for 4 bytes, have 2 already, may be one more
+ // Lead byte but no place to stick it
+ if (decoder != null && !decoder.MustFlush)
+ {
+ // (make sure not to set decoder if counting, so check chars)
+ if (chars != null)
+ {
+ // We'll be able to stick the remainder in the decoder
+ byte1 = ch;
+ byte2 = ch2;
+
+ if (buffer.MoreData)
+ byte3 = buffer.GetNextByte();
+ else
+ byte3 = -1;
+
+ byte4=-1;
+ }
+ break;
+ }
+
+ // Won't go in decoder, we'll use '?' for it.
+ if (!buffer.Fallback(ch, ch2))
+ break;
+ }
+ }
+ else
+ {
+ // Unknown byte sequence, fall back lead byte and try 2nd one again
+ buffer.AdjustBytes(-1);
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+ else
+ {
+ // Lead byte but don't know about trail byte
+ // (make sure not to set decoder if counting, so check bytes)
+ if (decoder != null && !decoder.MustFlush)
+ {
+ // We'll be able to stick it in the decoder
+ // (don't actually do it when counting though)
+ if (chars != null)
+ {
+ byte1 = ch;
+ byte2 = -1;
+ byte3 = -1;
+ byte4 = -1;
+ }
+ break;
+ }
+
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+ else
+ {
+ // Not ASCII and not a lead byte, we'll use '?' for it if we have room
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+
+ // Need to flush the decoder if necessary
+ // (make sure not to set decoder if counting, so check bytes)
+ if (decoder != null)
+ {
+ if (chars != null)
+ {
+ decoder.bLeftOver1 = byte1;
+ decoder.bLeftOver2 = byte2;
+ decoder.bLeftOver3 = byte3;
+ decoder.bLeftOver4 = byte4;
+ }
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+
+ // Return the # of characters we found
+ return buffer.Count;
+ }
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // We could have 4 bytes for each char, no extra for surrogates because 18030 can do whole unicode range.
+ byteCount *= 4;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Just return length, we could have a single char for each byte + whatever extra our decoder could do to us.
+ // If decoder is messed up it could spit out 3 ?s.
+ long charCount = ((long)byteCount) + 3;
+
+ // Take fallback size into consideration
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ public override Decoder GetDecoder()
+ {
+ return new GB18030Decoder(this);
+ }
+
+ [Serializable]
+ internal sealed class GB18030Decoder : System.Text.DecoderNLS, ISerializable
+ {
+ internal short bLeftOver1 = -1;
+ internal short bLeftOver2 = -1;
+ internal short bLeftOver3 = -1;
+ internal short bLeftOver4 = -1;
+
+ internal GB18030Decoder(EncodingNLS encoding) : base(encoding)
+ {
+ // DecoderNLS Calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ [System.Security.SecurityCritical] // auto-generated
+ internal GB18030Decoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ try
+ {
+ //
+ // Try Whidbey V2.0 Fields
+ //
+ this.m_encoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding));
+ this.m_fallback = (DecoderFallback)info.GetValue("m_fallback", typeof(DecoderFallback));
+ this.bLeftOver1 = (short)info.GetValue("bLeftOver1", typeof(short));
+ this.bLeftOver2 = (short)info.GetValue("bLeftOver2", typeof(short));
+ this.bLeftOver3 = (short)info.GetValue("bLeftOver3", typeof(short));
+ this.bLeftOver4 = (short)info.GetValue("bLeftOver4", typeof(short));
+ }
+ catch (SerializationException)
+ {
+ // Didn't have Whidbey stuff, try Everett (DecoderNLS already called Reset())
+ this.m_encoding = new GB18030Encoding();
+ }
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save Whidbey data
+ // Just need Everett maxCharSize (BaseCodePageEncoding) or m_maxByteSize (MLangBaseCodePageEncoding)
+ info.AddValue("m_encoding", this.m_encoding);
+ info.AddValue("m_fallback", this.m_fallback);
+ info.AddValue("bLeftOver1", this.bLeftOver1);
+ info.AddValue("bLeftOver2", this.bLeftOver2);
+ info.AddValue("bLeftOver3", this.bLeftOver3);
+ info.AddValue("bLeftOver4", this.bLeftOver4);
+
+ // Everett needs different data (this is just empty for Everett)
+ info.AddValue("m_leftOverBytes", (int)0);
+ info.AddValue("leftOver", new byte[8]);
+ }
+
+ public override void Reset()
+ {
+ bLeftOver1 = -1;
+ bLeftOver2 = -1;
+ bLeftOver3 = -1;
+ bLeftOver4 = -1;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.bLeftOver1 >= 0);
+ }
+ }
+ }
+
+ // tableUnicodeToGBDiffs
+ //
+ // This compressed data enumerates the differences between gb18030 and the 936 code page as follows:
+ //
+ // <count> & 0x8000 == 0x8000 The next count <count> characters are identical to 936 characters.
+ // <count> & 0x8000 == 0x0000 The next count <count> characters are 4 byte gb18030 characters.
+ // Except for:
+ // <count> >= 0x9000 && <count> != 0xD1A6 This character is this 2 byte GB18030 value.
+ //
+ readonly ushort[] tableUnicodeToGBDiffs =
+ {
+ 0x8080, // U+0000 - U+007F ( 128 chars) use CP 936 conversion.
+ 0x0024, // U+0080 - U+00A3 ( 36 chars) are GB18030 81 30 81 30 - 81 30 84 35 (offset 0000 - 0023)
+ 0x8001, // U+00A4 - U+00A4 ( 1 chars) use CP 936 conversion.
+ 0x0002, // U+00A5 - U+00A6 ( 2 chars) are GB18030 81 30 84 36 - 81 30 84 37 (offset 0024 - 0025)
+ 0x8002, // U+00A7 - U+00A8 ( 2 chars) use CP 936 conversion.
+ 0x0007, // U+00A9 - U+00AF ( 7 chars) are GB18030 81 30 84 38 - 81 30 85 34 (offset 0026 - 002C)
+ 0x8002, // U+00B0 - U+00B1 ( 2 chars) use CP 936 conversion.
+ 0x0005, // U+00B2 - U+00B6 ( 5 chars) are GB18030 81 30 85 35 - 81 30 85 39 (offset 002D - 0031)
+ 0x8001, // U+00B7 - U+00B7 ( 1 chars) use CP 936 conversion.
+ 0x001F, // U+00B8 - U+00D6 ( 31 chars) are GB18030 81 30 86 30 - 81 30 89 30 (offset 0032 - 0050)
+ 0x8001, // U+00D7 - U+00D7 ( 1 chars) use CP 936 conversion.
+ 0x0008, // U+00D8 - U+00DF ( 8 chars) are GB18030 81 30 89 31 - 81 30 89 38 (offset 0051 - 0058)
+ 0x8002, // U+00E0 - U+00E1 ( 2 chars) use CP 936 conversion.
+ 0x0006, // U+00E2 - U+00E7 ( 6 chars) are GB18030 81 30 89 39 - 81 30 8A 34 (offset 0059 - 005E)
+ 0x8003, // U+00E8 - U+00EA ( 3 chars) use CP 936 conversion.
+ 0x0001, // U+00EB - U+00EB ( 1 chars) are GB18030 81 30 8A 35 - 81 30 8A 35 (offset 005F - 005F)
+ 0x8002, // U+00EC - U+00ED ( 2 chars) use CP 936 conversion.
+ 0x0004, // U+00EE - U+00F1 ( 4 chars) are GB18030 81 30 8A 36 - 81 30 8A 39 (offset 0060 - 0063)
+ 0x8002, // U+00F2 - U+00F3 ( 2 chars) use CP 936 conversion.
+ 0x0003, // U+00F4 - U+00F6 ( 3 chars) are GB18030 81 30 8B 30 - 81 30 8B 32 (offset 0064 - 0066)
+ 0x8001, // U+00F7 - U+00F7 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+00F8 - U+00F8 ( 1 chars) are GB18030 81 30 8B 33 - 81 30 8B 33 (offset 0067 - 0067)
+ 0x8002, // U+00F9 - U+00FA ( 2 chars) use CP 936 conversion.
+ 0x0001, // U+00FB - U+00FB ( 1 chars) are GB18030 81 30 8B 34 - 81 30 8B 34 (offset 0068 - 0068)
+ 0x8001, // U+00FC - U+00FC ( 1 chars) use CP 936 conversion.
+ 0x0004, // U+00FD - U+0100 ( 4 chars) are GB18030 81 30 8B 35 - 81 30 8B 38 (offset 0069 - 006C)
+ 0x8001, // U+0101 - U+0101 ( 1 chars) use CP 936 conversion.
+ 0x0011, // U+0102 - U+0112 ( 17 chars) are GB18030 81 30 8B 39 - 81 30 8D 35 (offset 006D - 007D)
+ 0x8001, // U+0113 - U+0113 ( 1 chars) use CP 936 conversion.
+ 0x0007, // U+0114 - U+011A ( 7 chars) are GB18030 81 30 8D 36 - 81 30 8E 32 (offset 007E - 0084)
+ 0x8001, // U+011B - U+011B ( 1 chars) use CP 936 conversion.
+ 0x000F, // U+011C - U+012A ( 15 chars) are GB18030 81 30 8E 33 - 81 30 8F 37 (offset 0085 - 0093)
+ 0x8001, // U+012B - U+012B ( 1 chars) use CP 936 conversion.
+ 0x0018, // U+012C - U+0143 ( 24 chars) are GB18030 81 30 8F 38 - 81 30 92 31 (offset 0094 - 00AB)
+ 0x8001, // U+0144 - U+0144 ( 1 chars) use CP 936 conversion.
+ 0x0003, // U+0145 - U+0147 ( 3 chars) are GB18030 81 30 92 32 - 81 30 92 34 (offset 00AC - 00AE)
+ 0x8001, // U+0148 - U+0148 ( 1 chars) use CP 936 conversion.
+ 0x0004, // U+0149 - U+014C ( 4 chars) are GB18030 81 30 92 35 - 81 30 92 38 (offset 00AF - 00B2)
+ 0x8001, // U+014D - U+014D ( 1 chars) use CP 936 conversion.
+ 0x001D, // U+014E - U+016A ( 29 chars) are GB18030 81 30 92 39 - 81 30 95 37 (offset 00B3 - 00CF)
+ 0x8001, // U+016B - U+016B ( 1 chars) use CP 936 conversion.
+ 0x0062, // U+016C - U+01CD ( 98 chars) are GB18030 81 30 95 38 - 81 30 9F 35 (offset 00D0 - 0131)
+ 0x8001, // U+01CE - U+01CE ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01CF - U+01CF ( 1 chars) are GB18030 81 30 9F 36 - 81 30 9F 36 (offset 0132 - 0132)
+ 0x8001, // U+01D0 - U+01D0 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01D1 - U+01D1 ( 1 chars) are GB18030 81 30 9F 37 - 81 30 9F 37 (offset 0133 - 0133)
+ 0x8001, // U+01D2 - U+01D2 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01D3 - U+01D3 ( 1 chars) are GB18030 81 30 9F 38 - 81 30 9F 38 (offset 0134 - 0134)
+ 0x8001, // U+01D4 - U+01D4 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01D5 - U+01D5 ( 1 chars) are GB18030 81 30 9F 39 - 81 30 9F 39 (offset 0135 - 0135)
+ 0x8001, // U+01D6 - U+01D6 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01D7 - U+01D7 ( 1 chars) are GB18030 81 30 A0 30 - 81 30 A0 30 (offset 0136 - 0136)
+ 0x8001, // U+01D8 - U+01D8 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01D9 - U+01D9 ( 1 chars) are GB18030 81 30 A0 31 - 81 30 A0 31 (offset 0137 - 0137)
+ 0x8001, // U+01DA - U+01DA ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+01DB - U+01DB ( 1 chars) are GB18030 81 30 A0 32 - 81 30 A0 32 (offset 0138 - 0138)
+ 0x8001, // U+01DC - U+01DC ( 1 chars) use CP 936 conversion.
+ 0x001C, // U+01DD - U+01F8 ( 28 chars) are GB18030 81 30 A0 33 - 81 30 A3 30 (offset 0139 - 0154)
+ 0xA8BF, // U+01F9 is non-936 GB18030 value A8 BF.
+ 0x0057, // U+01FA - U+0250 ( 87 chars) are GB18030 81 30 A3 31 - 81 30 AB 37 (offset 0155 - 01AB)
+ 0x8001, // U+0251 - U+0251 ( 1 chars) use CP 936 conversion.
+ 0x000F, // U+0252 - U+0260 ( 15 chars) are GB18030 81 30 AB 38 - 81 30 AD 32 (offset 01AC - 01BA)
+ 0x8001, // U+0261 - U+0261 ( 1 chars) use CP 936 conversion.
+ 0x0065, // U+0262 - U+02C6 ( 101 chars) are GB18030 81 30 AD 33 - 81 30 B7 33 (offset 01BB - 021F)
+ 0x8001, // U+02C7 - U+02C7 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+02C8 - U+02C8 ( 1 chars) are GB18030 81 30 B7 34 - 81 30 B7 34 (offset 0220 - 0220)
+ 0x8003, // U+02C9 - U+02CB ( 3 chars) use CP 936 conversion.
+ 0x000D, // U+02CC - U+02D8 ( 13 chars) are GB18030 81 30 B7 35 - 81 30 B8 37 (offset 0221 - 022D)
+ 0x8001, // U+02D9 - U+02D9 ( 1 chars) use CP 936 conversion.
+ 0x00B7, // U+02DA - U+0390 ( 183 chars) are GB18030 81 30 B8 38 - 81 30 CB 30 (offset 022E - 02E4)
+ 0x8011, // U+0391 - U+03A1 ( 17 chars) use CP 936 conversion.
+ 0x0001, // U+03A2 - U+03A2 ( 1 chars) are GB18030 81 30 CB 31 - 81 30 CB 31 (offset 02E5 - 02E5)
+ 0x8007, // U+03A3 - U+03A9 ( 7 chars) use CP 936 conversion.
+ 0x0007, // U+03AA - U+03B0 ( 7 chars) are GB18030 81 30 CB 32 - 81 30 CB 38 (offset 02E6 - 02EC)
+ 0x8011, // U+03B1 - U+03C1 ( 17 chars) use CP 936 conversion.
+ 0x0001, // U+03C2 - U+03C2 ( 1 chars) are GB18030 81 30 CB 39 - 81 30 CB 39 (offset 02ED - 02ED)
+ 0x8007, // U+03C3 - U+03C9 ( 7 chars) use CP 936 conversion.
+ 0x0037, // U+03CA - U+0400 ( 55 chars) are GB18030 81 30 CC 30 - 81 30 D1 34 (offset 02EE - 0324)
+ 0x8001, // U+0401 - U+0401 ( 1 chars) use CP 936 conversion.
+ 0x000E, // U+0402 - U+040F ( 14 chars) are GB18030 81 30 D1 35 - 81 30 D2 38 (offset 0325 - 0332)
+ 0x8040, // U+0410 - U+044F ( 64 chars) use CP 936 conversion.
+ 0x0001, // U+0450 - U+0450 ( 1 chars) are GB18030 81 30 D2 39 - 81 30 D2 39 (offset 0333 - 0333)
+ 0x8001, // U+0451 - U+0451 ( 1 chars) use CP 936 conversion.
+ 0x1BBE, // U+0452 - U+200F ( 7102 chars) are GB18030 81 30 D3 30 - 81 36 A5 31 (offset 0334 - 1EF1)
+ 0x8001, // U+2010 - U+2010 ( 1 chars) use CP 936 conversion.
+ 0x0002, // U+2011 - U+2012 ( 2 chars) are GB18030 81 36 A5 32 - 81 36 A5 33 (offset 1EF2 - 1EF3)
+ 0x8004, // U+2013 - U+2016 ( 4 chars) use CP 936 conversion.
+ 0x0001, // U+2017 - U+2017 ( 1 chars) are GB18030 81 36 A5 34 - 81 36 A5 34 (offset 1EF4 - 1EF4)
+ 0x8002, // U+2018 - U+2019 ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+201A - U+201B ( 2 chars) are GB18030 81 36 A5 35 - 81 36 A5 36 (offset 1EF5 - 1EF6)
+ 0x8002, // U+201C - U+201D ( 2 chars) use CP 936 conversion.
+ 0x0007, // U+201E - U+2024 ( 7 chars) are GB18030 81 36 A5 37 - 81 36 A6 33 (offset 1EF7 - 1EFD)
+ 0x8002, // U+2025 - U+2026 ( 2 chars) use CP 936 conversion.
+ 0x0009, // U+2027 - U+202F ( 9 chars) are GB18030 81 36 A6 34 - 81 36 A7 32 (offset 1EFE - 1F06)
+ 0x8001, // U+2030 - U+2030 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2031 - U+2031 ( 1 chars) are GB18030 81 36 A7 33 - 81 36 A7 33 (offset 1F07 - 1F07)
+ 0x8002, // U+2032 - U+2033 ( 2 chars) use CP 936 conversion.
+ 0x0001, // U+2034 - U+2034 ( 1 chars) are GB18030 81 36 A7 34 - 81 36 A7 34 (offset 1F08 - 1F08)
+ 0x8001, // U+2035 - U+2035 ( 1 chars) use CP 936 conversion.
+ 0x0005, // U+2036 - U+203A ( 5 chars) are GB18030 81 36 A7 35 - 81 36 A7 39 (offset 1F09 - 1F0D)
+ 0x8001, // U+203B - U+203B ( 1 chars) use CP 936 conversion.
+ 0x0070, // U+203C - U+20AB ( 112 chars) are GB18030 81 36 A8 30 - 81 36 B3 31 (offset 1F0E - 1F7D)
+ 0xA2E3, // U+20AC is non-936 GB18030 value A2 E3.
+ 0x0056, // U+20AD - U+2102 ( 86 chars) are GB18030 81 36 B3 32 - 81 36 BB 37 (offset 1F7E - 1FD3)
+ 0x8001, // U+2103 - U+2103 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2104 - U+2104 ( 1 chars) are GB18030 81 36 BB 38 - 81 36 BB 38 (offset 1FD4 - 1FD4)
+ 0x8001, // U+2105 - U+2105 ( 1 chars) use CP 936 conversion.
+ 0x0003, // U+2106 - U+2108 ( 3 chars) are GB18030 81 36 BB 39 - 81 36 BC 31 (offset 1FD5 - 1FD7)
+ 0x8001, // U+2109 - U+2109 ( 1 chars) use CP 936 conversion.
+ 0x000C, // U+210A - U+2115 ( 12 chars) are GB18030 81 36 BC 32 - 81 36 BD 33 (offset 1FD8 - 1FE3)
+ 0x8001, // U+2116 - U+2116 ( 1 chars) use CP 936 conversion.
+ 0x000A, // U+2117 - U+2120 ( 10 chars) are GB18030 81 36 BD 34 - 81 36 BE 33 (offset 1FE4 - 1FED)
+ 0x8001, // U+2121 - U+2121 ( 1 chars) use CP 936 conversion.
+ 0x003E, // U+2122 - U+215F ( 62 chars) are GB18030 81 36 BE 34 - 81 36 C4 35 (offset 1FEE - 202B)
+ 0x800C, // U+2160 - U+216B ( 12 chars) use CP 936 conversion.
+ 0x0004, // U+216C - U+216F ( 4 chars) are GB18030 81 36 C4 36 - 81 36 C4 39 (offset 202C - 202F)
+ 0x800A, // U+2170 - U+2179 ( 10 chars) use CP 936 conversion.
+ 0x0016, // U+217A - U+218F ( 22 chars) are GB18030 81 36 C5 30 - 81 36 C7 31 (offset 2030 - 2045)
+ 0x8004, // U+2190 - U+2193 ( 4 chars) use CP 936 conversion.
+ 0x0002, // U+2194 - U+2195 ( 2 chars) are GB18030 81 36 C7 32 - 81 36 C7 33 (offset 2046 - 2047)
+ 0x8004, // U+2196 - U+2199 ( 4 chars) use CP 936 conversion.
+ 0x006E, // U+219A - U+2207 ( 110 chars) are GB18030 81 36 C7 34 - 81 36 D2 33 (offset 2048 - 20B5)
+ 0x8001, // U+2208 - U+2208 ( 1 chars) use CP 936 conversion.
+ 0x0006, // U+2209 - U+220E ( 6 chars) are GB18030 81 36 D2 34 - 81 36 D2 39 (offset 20B6 - 20BB)
+ 0x8001, // U+220F - U+220F ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2210 - U+2210 ( 1 chars) are GB18030 81 36 D3 30 - 81 36 D3 30 (offset 20BC - 20BC)
+ 0x8001, // U+2211 - U+2211 ( 1 chars) use CP 936 conversion.
+ 0x0003, // U+2212 - U+2214 ( 3 chars) are GB18030 81 36 D3 31 - 81 36 D3 33 (offset 20BD - 20BF)
+ 0x8001, // U+2215 - U+2215 ( 1 chars) use CP 936 conversion.
+ 0x0004, // U+2216 - U+2219 ( 4 chars) are GB18030 81 36 D3 34 - 81 36 D3 37 (offset 20C0 - 20C3)
+ 0x8001, // U+221A - U+221A ( 1 chars) use CP 936 conversion.
+ 0x0002, // U+221B - U+221C ( 2 chars) are GB18030 81 36 D3 38 - 81 36 D3 39 (offset 20C4 - 20C5)
+ 0x8004, // U+221D - U+2220 ( 4 chars) use CP 936 conversion.
+ 0x0002, // U+2221 - U+2222 ( 2 chars) are GB18030 81 36 D4 30 - 81 36 D4 31 (offset 20C6 - 20C7)
+ 0x8001, // U+2223 - U+2223 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2224 - U+2224 ( 1 chars) are GB18030 81 36 D4 32 - 81 36 D4 32 (offset 20C8 - 20C8)
+ 0x8001, // U+2225 - U+2225 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2226 - U+2226 ( 1 chars) are GB18030 81 36 D4 33 - 81 36 D4 33 (offset 20C9 - 20C9)
+ 0x8005, // U+2227 - U+222B ( 5 chars) use CP 936 conversion.
+ 0x0002, // U+222C - U+222D ( 2 chars) are GB18030 81 36 D4 34 - 81 36 D4 35 (offset 20CA - 20CB)
+ 0x8001, // U+222E - U+222E ( 1 chars) use CP 936 conversion.
+ 0x0005, // U+222F - U+2233 ( 5 chars) are GB18030 81 36 D4 36 - 81 36 D5 30 (offset 20CC - 20D0)
+ 0x8004, // U+2234 - U+2237 ( 4 chars) use CP 936 conversion.
+ 0x0005, // U+2238 - U+223C ( 5 chars) are GB18030 81 36 D5 31 - 81 36 D5 35 (offset 20D1 - 20D5)
+ 0x8001, // U+223D - U+223D ( 1 chars) use CP 936 conversion.
+ 0x000A, // U+223E - U+2247 ( 10 chars) are GB18030 81 36 D5 36 - 81 36 D6 35 (offset 20D6 - 20DF)
+ 0x8001, // U+2248 - U+2248 ( 1 chars) use CP 936 conversion.
+ 0x0003, // U+2249 - U+224B ( 3 chars) are GB18030 81 36 D6 36 - 81 36 D6 38 (offset 20E0 - 20E2)
+ 0x8001, // U+224C - U+224C ( 1 chars) use CP 936 conversion.
+ 0x0005, // U+224D - U+2251 ( 5 chars) are GB18030 81 36 D6 39 - 81 36 D7 33 (offset 20E3 - 20E7)
+ 0x8001, // U+2252 - U+2252 ( 1 chars) use CP 936 conversion.
+ 0x000D, // U+2253 - U+225F ( 13 chars) are GB18030 81 36 D7 34 - 81 36 D8 36 (offset 20E8 - 20F4)
+ 0x8002, // U+2260 - U+2261 ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+2262 - U+2263 ( 2 chars) are GB18030 81 36 D8 37 - 81 36 D8 38 (offset 20F5 - 20F6)
+ 0x8004, // U+2264 - U+2267 ( 4 chars) use CP 936 conversion.
+ 0x0006, // U+2268 - U+226D ( 6 chars) are GB18030 81 36 D8 39 - 81 36 D9 34 (offset 20F7 - 20FC)
+ 0x8002, // U+226E - U+226F ( 2 chars) use CP 936 conversion.
+ 0x0025, // U+2270 - U+2294 ( 37 chars) are GB18030 81 36 D9 35 - 81 36 DD 31 (offset 20FD - 2121)
+ 0x8001, // U+2295 - U+2295 ( 1 chars) use CP 936 conversion.
+ 0x0003, // U+2296 - U+2298 ( 3 chars) are GB18030 81 36 DD 32 - 81 36 DD 34 (offset 2122 - 2124)
+ 0x8001, // U+2299 - U+2299 ( 1 chars) use CP 936 conversion.
+ 0x000B, // U+229A - U+22A4 ( 11 chars) are GB18030 81 36 DD 35 - 81 36 DE 35 (offset 2125 - 212F)
+ 0x8001, // U+22A5 - U+22A5 ( 1 chars) use CP 936 conversion.
+ 0x0019, // U+22A6 - U+22BE ( 25 chars) are GB18030 81 36 DE 36 - 81 36 E1 30 (offset 2130 - 2148)
+ 0x8001, // U+22BF - U+22BF ( 1 chars) use CP 936 conversion.
+ 0x0052, // U+22C0 - U+2311 ( 82 chars) are GB18030 81 36 E1 31 - 81 36 E9 32 (offset 2149 - 219A)
+ 0x8001, // U+2312 - U+2312 ( 1 chars) use CP 936 conversion.
+ 0x014D, // U+2313 - U+245F ( 333 chars) are GB18030 81 36 E9 33 - 81 37 8C 35 (offset 219B - 22E7)
+ 0x800A, // U+2460 - U+2469 ( 10 chars) use CP 936 conversion.
+ 0x000A, // U+246A - U+2473 ( 10 chars) are GB18030 81 37 8C 36 - 81 37 8D 35 (offset 22E8 - 22F1)
+ 0x8028, // U+2474 - U+249B ( 40 chars) use CP 936 conversion.
+ 0x0064, // U+249C - U+24FF ( 100 chars) are GB18030 81 37 8D 36 - 81 37 97 35 (offset 22F2 - 2355)
+ 0x804C, // U+2500 - U+254B ( 76 chars) use CP 936 conversion.
+ 0x0004, // U+254C - U+254F ( 4 chars) are GB18030 81 37 97 36 - 81 37 97 39 (offset 2356 - 2359)
+ 0x8024, // U+2550 - U+2573 ( 36 chars) use CP 936 conversion.
+ 0x000D, // U+2574 - U+2580 ( 13 chars) are GB18030 81 37 98 30 - 81 37 99 32 (offset 235A - 2366)
+ 0x800F, // U+2581 - U+258F ( 15 chars) use CP 936 conversion.
+ 0x0003, // U+2590 - U+2592 ( 3 chars) are GB18030 81 37 99 33 - 81 37 99 35 (offset 2367 - 2369)
+ 0x8003, // U+2593 - U+2595 ( 3 chars) use CP 936 conversion.
+ 0x000A, // U+2596 - U+259F ( 10 chars) are GB18030 81 37 99 36 - 81 37 9A 35 (offset 236A - 2373)
+ 0x8002, // U+25A0 - U+25A1 ( 2 chars) use CP 936 conversion.
+ 0x0010, // U+25A2 - U+25B1 ( 16 chars) are GB18030 81 37 9A 36 - 81 37 9C 31 (offset 2374 - 2383)
+ 0x8002, // U+25B2 - U+25B3 ( 2 chars) use CP 936 conversion.
+ 0x0008, // U+25B4 - U+25BB ( 8 chars) are GB18030 81 37 9C 32 - 81 37 9C 39 (offset 2384 - 238B)
+ 0x8002, // U+25BC - U+25BD ( 2 chars) use CP 936 conversion.
+ 0x0008, // U+25BE - U+25C5 ( 8 chars) are GB18030 81 37 9D 30 - 81 37 9D 37 (offset 238C - 2393)
+ 0x8002, // U+25C6 - U+25C7 ( 2 chars) use CP 936 conversion.
+ 0x0003, // U+25C8 - U+25CA ( 3 chars) are GB18030 81 37 9D 38 - 81 37 9E 30 (offset 2394 - 2396)
+ 0x8001, // U+25CB - U+25CB ( 1 chars) use CP 936 conversion.
+ 0x0002, // U+25CC - U+25CD ( 2 chars) are GB18030 81 37 9E 31 - 81 37 9E 32 (offset 2397 - 2398)
+ 0x8002, // U+25CE - U+25CF ( 2 chars) use CP 936 conversion.
+ 0x0012, // U+25D0 - U+25E1 ( 18 chars) are GB18030 81 37 9E 33 - 81 37 A0 30 (offset 2399 - 23AA)
+ 0x8004, // U+25E2 - U+25E5 ( 4 chars) use CP 936 conversion.
+ 0x001F, // U+25E6 - U+2604 ( 31 chars) are GB18030 81 37 A0 31 - 81 37 A3 31 (offset 23AB - 23C9)
+ 0x8002, // U+2605 - U+2606 ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+2607 - U+2608 ( 2 chars) are GB18030 81 37 A3 32 - 81 37 A3 33 (offset 23CA - 23CB)
+ 0x8001, // U+2609 - U+2609 ( 1 chars) use CP 936 conversion.
+ 0x0036, // U+260A - U+263F ( 54 chars) are GB18030 81 37 A3 34 - 81 37 A8 37 (offset 23CC - 2401)
+ 0x8001, // U+2640 - U+2640 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+2641 - U+2641 ( 1 chars) are GB18030 81 37 A8 38 - 81 37 A8 38 (offset 2402 - 2402)
+ 0x8001, // U+2642 - U+2642 ( 1 chars) use CP 936 conversion.
+ 0x083E, // U+2643 - U+2E80 ( 2110 chars) are GB18030 81 37 A8 39 - 81 38 FD 38 (offset 2403 - 2C40)
+ 0xFE50, // U+2E81 is non-936 GB18030 value FE 50.
+ 0x0002, // U+2E82 - U+2E83 ( 2 chars) are GB18030 81 38 FD 39 - 81 38 FE 30 (offset 2C41 - 2C42)
+ 0xFE54, // U+2E84 is non-936 GB18030 value FE 54.
+ 0x0003, // U+2E85 - U+2E87 ( 3 chars) are GB18030 81 38 FE 31 - 81 38 FE 33 (offset 2C43 - 2C45)
+ 0xFE57, // U+2E88 is non-936 GB18030 value FE 57.
+ 0x0002, // U+2E89 - U+2E8A ( 2 chars) are GB18030 81 38 FE 34 - 81 38 FE 35 (offset 2C46 - 2C47)
+ 0xFE58, // U+2E8B is non-936 GB18030 value FE 58.
+ 0xFE5D, // U+2E8C is non-936 GB18030 value FE 5D.
+ 0x000A, // U+2E8D - U+2E96 ( 10 chars) are GB18030 81 38 FE 36 - 81 39 81 35 (offset 2C48 - 2C51)
+ 0xFE5E, // U+2E97 is non-936 GB18030 value FE 5E.
+ 0x000F, // U+2E98 - U+2EA6 ( 15 chars) are GB18030 81 39 81 36 - 81 39 83 30 (offset 2C52 - 2C60)
+ 0xFE6B, // U+2EA7 is non-936 GB18030 value FE 6B.
+ 0x0002, // U+2EA8 - U+2EA9 ( 2 chars) are GB18030 81 39 83 31 - 81 39 83 32 (offset 2C61 - 2C62)
+ 0xFE6E, // U+2EAA is non-936 GB18030 value FE 6E.
+ 0x0003, // U+2EAB - U+2EAD ( 3 chars) are GB18030 81 39 83 33 - 81 39 83 35 (offset 2C63 - 2C65)
+ 0xFE71, // U+2EAE is non-936 GB18030 value FE 71.
+ 0x0004, // U+2EAF - U+2EB2 ( 4 chars) are GB18030 81 39 83 36 - 81 39 83 39 (offset 2C66 - 2C69)
+ 0xFE73, // U+2EB3 is non-936 GB18030 value FE 73.
+ 0x0002, // U+2EB4 - U+2EB5 ( 2 chars) are GB18030 81 39 84 30 - 81 39 84 31 (offset 2C6A - 2C6B)
+ 0xFE74, // U+2EB6 is non-936 GB18030 value FE 74.
+ 0xFE75, // U+2EB7 is non-936 GB18030 value FE 75.
+ 0x0003, // U+2EB8 - U+2EBA ( 3 chars) are GB18030 81 39 84 32 - 81 39 84 34 (offset 2C6C - 2C6E)
+ 0xFE79, // U+2EBB is non-936 GB18030 value FE 79.
+ 0x000E, // U+2EBC - U+2EC9 ( 14 chars) are GB18030 81 39 84 35 - 81 39 85 38 (offset 2C6F - 2C7C)
+ 0xFE84, // U+2ECA is non-936 GB18030 value FE 84.
+ 0x0125, // U+2ECB - U+2FEF ( 293 chars) are GB18030 81 39 85 39 - 81 39 A3 31 (offset 2C7D - 2DA1)
+ 0xA98A, // U+2FF0 is non-936 GB18030 value A9 8A.
+ 0xA98B, // U+2FF1 is non-936 GB18030 value A9 8B.
+ 0xA98C, // U+2FF2 is non-936 GB18030 value A9 8C.
+ 0xA98D, // U+2FF3 is non-936 GB18030 value A9 8D.
+ 0xA98E, // U+2FF4 is non-936 GB18030 value A9 8E.
+ 0xA98F, // U+2FF5 is non-936 GB18030 value A9 8F.
+ 0xA990, // U+2FF6 is non-936 GB18030 value A9 90.
+ 0xA991, // U+2FF7 is non-936 GB18030 value A9 91.
+ 0xA992, // U+2FF8 is non-936 GB18030 value A9 92.
+ 0xA993, // U+2FF9 is non-936 GB18030 value A9 93.
+ 0xA994, // U+2FFA is non-936 GB18030 value A9 94.
+ 0xA995, // U+2FFB is non-936 GB18030 value A9 95.
+ 0x0004, // U+2FFC - U+2FFF ( 4 chars) are GB18030 81 39 A3 32 - 81 39 A3 35 (offset 2DA2 - 2DA5)
+ 0x8004, // U+3000 - U+3003 ( 4 chars) use CP 936 conversion.
+ 0x0001, // U+3004 - U+3004 ( 1 chars) are GB18030 81 39 A3 36 - 81 39 A3 36 (offset 2DA6 - 2DA6)
+ 0x8013, // U+3005 - U+3017 ( 19 chars) use CP 936 conversion.
+ 0x0005, // U+3018 - U+301C ( 5 chars) are GB18030 81 39 A3 37 - 81 39 A4 31 (offset 2DA7 - 2DAB)
+ 0x8002, // U+301D - U+301E ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+301F - U+3020 ( 2 chars) are GB18030 81 39 A4 32 - 81 39 A4 33 (offset 2DAC - 2DAD)
+ 0x8009, // U+3021 - U+3029 ( 9 chars) use CP 936 conversion.
+ 0x0014, // U+302A - U+303D ( 20 chars) are GB18030 81 39 A4 34 - 81 39 A6 33 (offset 2DAE - 2DC1)
+ 0xA989, // U+303E is non-936 GB18030 value A9 89.
+ 0x0002, // U+303F - U+3040 ( 2 chars) are GB18030 81 39 A6 34 - 81 39 A6 35 (offset 2DC2 - 2DC3)
+ 0x8053, // U+3041 - U+3093 ( 83 chars) use CP 936 conversion.
+ 0x0007, // U+3094 - U+309A ( 7 chars) are GB18030 81 39 A6 36 - 81 39 A7 32 (offset 2DC4 - 2DCA)
+ 0x8004, // U+309B - U+309E ( 4 chars) use CP 936 conversion.
+ 0x0002, // U+309F - U+30A0 ( 2 chars) are GB18030 81 39 A7 33 - 81 39 A7 34 (offset 2DCB - 2DCC)
+ 0x8056, // U+30A1 - U+30F6 ( 86 chars) use CP 936 conversion.
+ 0x0005, // U+30F7 - U+30FB ( 5 chars) are GB18030 81 39 A7 35 - 81 39 A7 39 (offset 2DCD - 2DD1)
+ 0x8003, // U+30FC - U+30FE ( 3 chars) use CP 936 conversion.
+ 0x0006, // U+30FF - U+3104 ( 6 chars) are GB18030 81 39 A8 30 - 81 39 A8 35 (offset 2DD2 - 2DD7)
+ 0x8025, // U+3105 - U+3129 ( 37 chars) use CP 936 conversion.
+ 0x00F6, // U+312A - U+321F ( 246 chars) are GB18030 81 39 A8 36 - 81 39 C1 31 (offset 2DD8 - 2ECD)
+ 0x800A, // U+3220 - U+3229 ( 10 chars) use CP 936 conversion.
+ 0x0007, // U+322A - U+3230 ( 7 chars) are GB18030 81 39 C1 32 - 81 39 C1 38 (offset 2ECE - 2ED4)
+ 0x8001, // U+3231 - U+3231 ( 1 chars) use CP 936 conversion.
+ 0x0071, // U+3232 - U+32A2 ( 113 chars) are GB18030 81 39 C1 39 - 81 39 CD 31 (offset 2ED5 - 2F45)
+ 0x8001, // U+32A3 - U+32A3 ( 1 chars) use CP 936 conversion.
+ 0x00EA, // U+32A4 - U+338D ( 234 chars) are GB18030 81 39 CD 32 - 81 39 E4 35 (offset 2F46 - 302F)
+ 0x8002, // U+338E - U+338F ( 2 chars) use CP 936 conversion.
+ 0x000C, // U+3390 - U+339B ( 12 chars) are GB18030 81 39 E4 36 - 81 39 E5 37 (offset 3030 - 303B)
+ 0x8003, // U+339C - U+339E ( 3 chars) use CP 936 conversion.
+ 0x0002, // U+339F - U+33A0 ( 2 chars) are GB18030 81 39 E5 38 - 81 39 E5 39 (offset 303C - 303D)
+ 0x8001, // U+33A1 - U+33A1 ( 1 chars) use CP 936 conversion.
+ 0x0022, // U+33A2 - U+33C3 ( 34 chars) are GB18030 81 39 E6 30 - 81 39 E9 33 (offset 303E - 305F)
+ 0x8001, // U+33C4 - U+33C4 ( 1 chars) use CP 936 conversion.
+ 0x0009, // U+33C5 - U+33CD ( 9 chars) are GB18030 81 39 E9 34 - 81 39 EA 32 (offset 3060 - 3068)
+ 0x8001, // U+33CE - U+33CE ( 1 chars) use CP 936 conversion.
+ 0x0002, // U+33CF - U+33D0 ( 2 chars) are GB18030 81 39 EA 33 - 81 39 EA 34 (offset 3069 - 306A)
+ 0x8002, // U+33D1 - U+33D2 ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+33D3 - U+33D4 ( 2 chars) are GB18030 81 39 EA 35 - 81 39 EA 36 (offset 306B - 306C)
+ 0x8001, // U+33D5 - U+33D5 ( 1 chars) use CP 936 conversion.
+ 0x0071, // U+33D6 - U+3446 ( 113 chars) are GB18030 81 39 EA 37 - 81 39 F5 39 (offset 306D - 30DD)
+ 0xFE56, // U+3447 is non-936 GB18030 value FE 56.
+ 0x002B, // U+3448 - U+3472 ( 43 chars) are GB18030 81 39 F6 30 - 81 39 FA 32 (offset 30DE - 3108)
+ 0xFE55, // U+3473 is non-936 GB18030 value FE 55.
+ 0x012A, // U+3474 - U+359D ( 298 chars) are GB18030 81 39 FA 33 - 82 30 9A 30 (offset 3109 - 3232)
+ 0xFE5A, // U+359E is non-936 GB18030 value FE 5A.
+ 0x006F, // U+359F - U+360D ( 111 chars) are GB18030 82 30 9A 31 - 82 30 A5 31 (offset 3233 - 32A1)
+ 0xFE5C, // U+360E is non-936 GB18030 value FE 5C.
+ 0x000B, // U+360F - U+3619 ( 11 chars) are GB18030 82 30 A5 32 - 82 30 A6 32 (offset 32A2 - 32AC)
+ 0xFE5B, // U+361A is non-936 GB18030 value FE 5B.
+ 0x02FD, // U+361B - U+3917 ( 765 chars) are GB18030 82 30 A6 33 - 82 30 F2 37 (offset 32AD - 35A9)
+ 0xFE60, // U+3918 is non-936 GB18030 value FE 60.
+ 0x0055, // U+3919 - U+396D ( 85 chars) are GB18030 82 30 F2 38 - 82 30 FB 32 (offset 35AA - 35FE)
+ 0xFE5F, // U+396E is non-936 GB18030 value FE 5F.
+ 0x0060, // U+396F - U+39CE ( 96 chars) are GB18030 82 30 FB 33 - 82 31 86 38 (offset 35FF - 365E)
+ 0xFE62, // U+39CF is non-936 GB18030 value FE 62.
+ 0xFE65, // U+39D0 is non-936 GB18030 value FE 65.
+ 0x000E, // U+39D1 - U+39DE ( 14 chars) are GB18030 82 31 86 39 - 82 31 88 32 (offset 365F - 366C)
+ 0xFE63, // U+39DF is non-936 GB18030 value FE 63.
+ 0x0093, // U+39E0 - U+3A72 ( 147 chars) are GB18030 82 31 88 33 - 82 31 96 39 (offset 366D - 36FF)
+ 0xFE64, // U+3A73 is non-936 GB18030 value FE 64.
+ 0x00DA, // U+3A74 - U+3B4D ( 218 chars) are GB18030 82 31 97 30 - 82 31 AC 37 (offset 3700 - 37D9)
+ 0xFE68, // U+3B4E is non-936 GB18030 value FE 68.
+ 0x011F, // U+3B4F - U+3C6D ( 287 chars) are GB18030 82 31 AC 38 - 82 31 C9 34 (offset 37DA - 38F8)
+ 0xFE69, // U+3C6E is non-936 GB18030 value FE 69.
+ 0x0071, // U+3C6F - U+3CDF ( 113 chars) are GB18030 82 31 C9 35 - 82 31 D4 37 (offset 38F9 - 3969)
+ 0xFE6A, // U+3CE0 is non-936 GB18030 value FE 6A.
+ 0x0375, // U+3CE1 - U+4055 ( 885 chars) are GB18030 82 31 D4 38 - 82 32 AF 32 (offset 396A - 3CDE)
+ 0xFE6F, // U+4056 is non-936 GB18030 value FE 6F.
+ 0x0108, // U+4057 - U+415E ( 264 chars) are GB18030 82 32 AF 33 - 82 32 C9 36 (offset 3CDF - 3DE6)
+ 0xFE70, // U+415F is non-936 GB18030 value FE 70.
+ 0x01D7, // U+4160 - U+4336 ( 471 chars) are GB18030 82 32 C9 37 - 82 32 F8 37 (offset 3DE7 - 3FBD)
+ 0xFE72, // U+4337 is non-936 GB18030 value FE 72.
+ 0x0074, // U+4338 - U+43AB ( 116 chars) are GB18030 82 32 F8 38 - 82 33 86 33 (offset 3FBE - 4031)
+ 0xFE78, // U+43AC is non-936 GB18030 value FE 78.
+ 0x0004, // U+43AD - U+43B0 ( 4 chars) are GB18030 82 33 86 34 - 82 33 86 37 (offset 4032 - 4035)
+ 0xFE77, // U+43B1 is non-936 GB18030 value FE 77.
+ 0x002B, // U+43B2 - U+43DC ( 43 chars) are GB18030 82 33 86 38 - 82 33 8B 30 (offset 4036 - 4060)
+ 0xFE7A, // U+43DD is non-936 GB18030 value FE 7A.
+ 0x00F8, // U+43DE - U+44D5 ( 248 chars) are GB18030 82 33 8B 31 - 82 33 A3 38 (offset 4061 - 4158)
+ 0xFE7B, // U+44D6 is non-936 GB18030 value FE 7B.
+ 0x0175, // U+44D7 - U+464B ( 373 chars) are GB18030 82 33 A3 39 - 82 33 C9 31 (offset 4159 - 42CD)
+ 0xFE7D, // U+464C is non-936 GB18030 value FE 7D.
+ 0x0014, // U+464D - U+4660 ( 20 chars) are GB18030 82 33 C9 32 - 82 33 CB 31 (offset 42CE - 42E1)
+ 0xFE7C, // U+4661 is non-936 GB18030 value FE 7C.
+ 0x00C1, // U+4662 - U+4722 ( 193 chars) are GB18030 82 33 CB 32 - 82 33 DE 34 (offset 42E2 - 43A2)
+ 0xFE80, // U+4723 is non-936 GB18030 value FE 80.
+ 0x0005, // U+4724 - U+4728 ( 5 chars) are GB18030 82 33 DE 35 - 82 33 DE 39 (offset 43A3 - 43A7)
+ 0xFE81, // U+4729 is non-936 GB18030 value FE 81.
+ 0x0052, // U+472A - U+477B ( 82 chars) are GB18030 82 33 DF 30 - 82 33 E7 31 (offset 43A8 - 43F9)
+ 0xFE82, // U+477C is non-936 GB18030 value FE 82.
+ 0x0010, // U+477D - U+478C ( 16 chars) are GB18030 82 33 E7 32 - 82 33 E8 37 (offset 43FA - 4409)
+ 0xFE83, // U+478D is non-936 GB18030 value FE 83.
+ 0x01B9, // U+478E - U+4946 ( 441 chars) are GB18030 82 33 E8 38 - 82 34 96 38 (offset 440A - 45C2)
+ 0xFE85, // U+4947 is non-936 GB18030 value FE 85.
+ 0x0032, // U+4948 - U+4979 ( 50 chars) are GB18030 82 34 96 39 - 82 34 9B 38 (offset 45C3 - 45F4)
+ 0xFE86, // U+497A is non-936 GB18030 value FE 86.
+ 0x0002, // U+497B - U+497C ( 2 chars) are GB18030 82 34 9B 39 - 82 34 9C 30 (offset 45F5 - 45F6)
+ 0xFE87, // U+497D is non-936 GB18030 value FE 87.
+ 0x0004, // U+497E - U+4981 ( 4 chars) are GB18030 82 34 9C 31 - 82 34 9C 34 (offset 45F7 - 45FA)
+ 0xFE88, // U+4982 is non-936 GB18030 value FE 88.
+ 0xFE89, // U+4983 is non-936 GB18030 value FE 89.
+ 0x0001, // U+4984 - U+4984 ( 1 chars) are GB18030 82 34 9C 35 - 82 34 9C 35 (offset 45FB - 45FB)
+ 0xFE8A, // U+4985 is non-936 GB18030 value FE 8A.
+ 0xFE8B, // U+4986 is non-936 GB18030 value FE 8B.
+ 0x0014, // U+4987 - U+499A ( 20 chars) are GB18030 82 34 9C 36 - 82 34 9E 35 (offset 45FC - 460F)
+ 0xFE8D, // U+499B is non-936 GB18030 value FE 8D.
+ 0x0003, // U+499C - U+499E ( 3 chars) are GB18030 82 34 9E 36 - 82 34 9E 38 (offset 4610 - 4612)
+ 0xFE8C, // U+499F is non-936 GB18030 value FE 8C.
+ 0x0016, // U+49A0 - U+49B5 ( 22 chars) are GB18030 82 34 9E 39 - 82 34 A1 30 (offset 4613 - 4628)
+ 0xFE8F, // U+49B6 is non-936 GB18030 value FE 8F.
+ 0xFE8E, // U+49B7 is non-936 GB18030 value FE 8E.
+ 0x02BF, // U+49B8 - U+4C76 ( 703 chars) are GB18030 82 34 A1 31 - 82 34 E7 33 (offset 4629 - 48E7)
+ 0xFE96, // U+4C77 is non-936 GB18030 value FE 96.
+ 0x0027, // U+4C78 - U+4C9E ( 39 chars) are GB18030 82 34 E7 34 - 82 34 EB 32 (offset 48E8 - 490E)
+ 0xFE93, // U+4C9F is non-936 GB18030 value FE 93.
+ 0xFE94, // U+4CA0 is non-936 GB18030 value FE 94.
+ 0xFE95, // U+4CA1 is non-936 GB18030 value FE 95.
+ 0xFE97, // U+4CA2 is non-936 GB18030 value FE 97.
+ 0xFE92, // U+4CA3 is non-936 GB18030 value FE 92.
+ 0x006F, // U+4CA4 - U+4D12 ( 111 chars) are GB18030 82 34 EB 33 - 82 34 F6 33 (offset 490F - 497D)
+ 0xFE98, // U+4D13 is non-936 GB18030 value FE 98.
+ 0xFE99, // U+4D14 is non-936 GB18030 value FE 99.
+ 0xFE9A, // U+4D15 is non-936 GB18030 value FE 9A.
+ 0xFE9B, // U+4D16 is non-936 GB18030 value FE 9B.
+ 0xFE9C, // U+4D17 is non-936 GB18030 value FE 9C.
+ 0xFE9D, // U+4D18 is non-936 GB18030 value FE 9D.
+ 0xFE9E, // U+4D19 is non-936 GB18030 value FE 9E.
+ 0x0094, // U+4D1A - U+4DAD ( 148 chars) are GB18030 82 34 F6 34 - 82 35 87 31 (offset 497E - 4A11)
+ 0xFE9F, // U+4DAE is non-936 GB18030 value FE 9F.
+ 0x0051, // U+4DAF - U+4DFF ( 81 chars) are GB18030 82 35 87 32 - 82 35 8F 32 (offset 4A12 - 4A62)
+ 0xD1A6, // U+4E00 - U+9FA5 (20902 chars) use CP 936 conversion.
+ 0x385A, // U+9FA6 - U+D7FF (14426 chars) are GB18030 82 35 8F 33 - 83 36 C7 38 (offset 4A63 - 82BC)
+ 0x8F6C, // U+D800 - U+E76B ( 3948 chars) use CP 936 conversion.
+ 0x0001, // U+E76C - U+E76C ( 1 chars) are GB18030 83 36 C7 39 - 83 36 C7 39 (offset 82BD - 82BD)
+ 0x805B, // U+E76D - U+E7C7 ( 91 chars) use CP 936 conversion.
+ 0x0001, // U+E7C8 - U+E7C8 ( 1 chars) are GB18030 83 36 C8 30 - 83 36 C8 30 (offset 82BE - 82BE)
+ 0x801E, // U+E7C9 - U+E7E6 ( 30 chars) use CP 936 conversion.
+ 0x000D, // U+E7E7 - U+E7F3 ( 13 chars) are GB18030 83 36 C8 31 - 83 36 C9 33 (offset 82BF - 82CB)
+ 0x8021, // U+E7F4 - U+E814 ( 33 chars) use CP 936 conversion.
+ 0x0001, // U+E815 - U+E815 ( 1 chars) are GB18030 83 36 C9 34 - 83 36 C9 34 (offset 82CC - 82CC)
+ 0x8003, // U+E816 - U+E818 ( 3 chars) use CP 936 conversion.
+ 0x0005, // U+E819 - U+E81D ( 5 chars) are GB18030 83 36 C9 35 - 83 36 C9 39 (offset 82CD - 82D1)
+ 0x8001, // U+E81E - U+E81E ( 1 chars) use CP 936 conversion.
+ 0x0007, // U+E81F - U+E825 ( 7 chars) are GB18030 83 36 CA 30 - 83 36 CA 36 (offset 82D2 - 82D8)
+ 0x8001, // U+E826 - U+E826 ( 1 chars) use CP 936 conversion.
+ 0x0004, // U+E827 - U+E82A ( 4 chars) are GB18030 83 36 CA 37 - 83 36 CB 30 (offset 82D9 - 82DC)
+ 0x8002, // U+E82B - U+E82C ( 2 chars) use CP 936 conversion.
+ 0x0004, // U+E82D - U+E830 ( 4 chars) are GB18030 83 36 CB 31 - 83 36 CB 34 (offset 82DD - 82E0)
+ 0x8002, // U+E831 - U+E832 ( 2 chars) use CP 936 conversion.
+ 0x0008, // U+E833 - U+E83A ( 8 chars) are GB18030 83 36 CB 35 - 83 36 CC 32 (offset 82E1 - 82E8)
+ 0x8001, // U+E83B - U+E83B ( 1 chars) use CP 936 conversion.
+ 0x0007, // U+E83C - U+E842 ( 7 chars) are GB18030 83 36 CC 33 - 83 36 CC 39 (offset 82E9 - 82EF)
+ 0x8001, // U+E843 - U+E843 ( 1 chars) use CP 936 conversion.
+ 0x0010, // U+E844 - U+E853 ( 16 chars) are GB18030 83 36 CD 30 - 83 36 CE 35 (offset 82F0 - 82FF)
+ 0x8002, // U+E854 - U+E855 ( 2 chars) use CP 936 conversion.
+ 0x000E, // U+E856 - U+E863 ( 14 chars) are GB18030 83 36 CE 36 - 83 36 CF 39 (offset 8300 - 830D)
+ 0x8001, // U+E864 - U+E864 ( 1 chars) use CP 936 conversion.
+ 0x10C7, // U+E865 - U+F92B ( 4295 chars) are GB18030 83 36 D0 30 - 84 30 85 34 (offset 830E - 93D4)
+ 0x8001, // U+F92C - U+F92C ( 1 chars) use CP 936 conversion.
+ 0x004C, // U+F92D - U+F978 ( 76 chars) are GB18030 84 30 85 35 - 84 30 8D 30 (offset 93D5 - 9420)
+ 0x8001, // U+F979 - U+F979 ( 1 chars) use CP 936 conversion.
+ 0x001B, // U+F97A - U+F994 ( 27 chars) are GB18030 84 30 8D 31 - 84 30 8F 37 (offset 9421 - 943B)
+ 0x8001, // U+F995 - U+F995 ( 1 chars) use CP 936 conversion.
+ 0x0051, // U+F996 - U+F9E6 ( 81 chars) are GB18030 84 30 8F 38 - 84 30 97 38 (offset 943C - 948C)
+ 0x8001, // U+F9E7 - U+F9E7 ( 1 chars) use CP 936 conversion.
+ 0x0009, // U+F9E8 - U+F9F0 ( 9 chars) are GB18030 84 30 97 39 - 84 30 98 37 (offset 948D - 9495)
+ 0x8001, // U+F9F1 - U+F9F1 ( 1 chars) use CP 936 conversion.
+ 0x001A, // U+F9F2 - U+FA0B ( 26 chars) are GB18030 84 30 98 38 - 84 30 9B 33 (offset 9496 - 94AF)
+ 0x8004, // U+FA0C - U+FA0F ( 4 chars) use CP 936 conversion.
+ 0x0001, // U+FA10 - U+FA10 ( 1 chars) are GB18030 84 30 9B 34 - 84 30 9B 34 (offset 94B0 - 94B0)
+ 0x8001, // U+FA11 - U+FA11 ( 1 chars) use CP 936 conversion.
+ 0x0001, // U+FA12 - U+FA12 ( 1 chars) are GB18030 84 30 9B 35 - 84 30 9B 35 (offset 94B1 - 94B1)
+ 0x8002, // U+FA13 - U+FA14 ( 2 chars) use CP 936 conversion.
+ 0x0003, // U+FA15 - U+FA17 ( 3 chars) are GB18030 84 30 9B 36 - 84 30 9B 38 (offset 94B2 - 94B4)
+ 0x8001, // U+FA18 - U+FA18 ( 1 chars) use CP 936 conversion.
+ 0x0006, // U+FA19 - U+FA1E ( 6 chars) are GB18030 84 30 9B 39 - 84 30 9C 34 (offset 94B5 - 94BA)
+ 0x8003, // U+FA1F - U+FA21 ( 3 chars) use CP 936 conversion.
+ 0x0001, // U+FA22 - U+FA22 ( 1 chars) are GB18030 84 30 9C 35 - 84 30 9C 35 (offset 94BB - 94BB)
+ 0x8002, // U+FA23 - U+FA24 ( 2 chars) use CP 936 conversion.
+ 0x0002, // U+FA25 - U+FA26 ( 2 chars) are GB18030 84 30 9C 36 - 84 30 9C 37 (offset 94BC - 94BD)
+ 0x8003, // U+FA27 - U+FA29 ( 3 chars) use CP 936 conversion.
+ 0x0406, // U+FA2A - U+FE2F ( 1030 chars) are GB18030 84 30 9C 38 - 84 31 85 37 (offset 94BE - 98C3)
+ 0x8002, // U+FE30 - U+FE31 ( 2 chars) use CP 936 conversion.
+ 0x0001, // U+FE32 - U+FE32 ( 1 chars) are GB18030 84 31 85 38 - 84 31 85 38 (offset 98C4 - 98C4)
+ 0x8012, // U+FE33 - U+FE44 ( 18 chars) use CP 936 conversion.
+ 0x0004, // U+FE45 - U+FE48 ( 4 chars) are GB18030 84 31 85 39 - 84 31 86 32 (offset 98C5 - 98C8)
+ 0x800A, // U+FE49 - U+FE52 ( 10 chars) use CP 936 conversion.
+ 0x0001, // U+FE53 - U+FE53 ( 1 chars) are GB18030 84 31 86 33 - 84 31 86 33 (offset 98C9 - 98C9)
+ 0x8004, // U+FE54 - U+FE57 ( 4 chars) use CP 936 conversion.
+ 0x0001, // U+FE58 - U+FE58 ( 1 chars) are GB18030 84 31 86 34 - 84 31 86 34 (offset 98CA - 98CA)
+ 0x800E, // U+FE59 - U+FE66 ( 14 chars) use CP 936 conversion.
+ 0x0001, // U+FE67 - U+FE67 ( 1 chars) are GB18030 84 31 86 35 - 84 31 86 35 (offset 98CB - 98CB)
+ 0x8004, // U+FE68 - U+FE6B ( 4 chars) use CP 936 conversion.
+ 0x0095, // U+FE6C - U+FF00 ( 149 chars) are GB18030 84 31 86 36 - 84 31 95 34 (offset 98CC - 9960)
+ 0x805E, // U+FF01 - U+FF5E ( 94 chars) use CP 936 conversion.
+ 0x0081, // U+FF5F - U+FFDF ( 129 chars) are GB18030 84 31 95 35 - 84 31 A2 33 (offset 9961 - 99E1)
+ 0x8006, // U+FFE0 - U+FFE5 ( 6 chars) use CP 936 conversion.
+ 0x001A, // U+FFE6 - U+FFFF ( 26 chars) are GB18030 84 31 A2 34 - 84 31 A4 39 (offset 99E2 - 99FB)
+ };
+ }
+}
+#endif // FEATURE_CODEPAGES_FILE
+
diff --git a/src/mscorlib/src/System/Text/ISCIIEncoding.cs b/src/mscorlib/src/System/Text/ISCIIEncoding.cs
new file mode 100644
index 0000000000..89d9c9953a
--- /dev/null
+++ b/src/mscorlib/src/System/Text/ISCIIEncoding.cs
@@ -0,0 +1,2625 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// ISCIIEncoding
+//
+// Ported from windows c_iscii. If you find bugs here, there're likely similar
+// bugs in the windows version
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+ // Encodes text into and out of the ISCII encodings.
+ // ISCII contains characters to encode indic scripts by mapping indic scripts
+ // to the same code page. This works because they are all related scripts.
+ // ISCII provides a "font" selection method to switch between the appropriate
+ // fonts to display the other scripts. All ISCII characters are above the
+ // ASCII range to provide ASCII compatibility.
+ //
+ // IsAlwaysNormalized() isn't overridden
+ // We don't override IsAlwaysNormalized() because it is false for all forms (like base implimentation)
+ // Forms C & KC have things like 0933 + 093C == composed 0934, so they aren't normalized
+ // Forms D & KD have things like 0934, which decomposes to 0933 + 093C, so not normal.
+ // Form IDNA has the above problems plus case mapping, so false (like most encodings)
+ //
+
+ [Serializable]
+ internal class ISCIIEncoding : EncodingNLS, ISerializable
+ {
+ // Constants
+ private const int CodeDefault = 0; // 0x40 Default
+ private const int CodeRoman = 1; // 0x41 Roman Transliteration (not supported)
+ private const int CodeDevanagari = 2; // 0x42 57002
+ private const int CodeBengali = 3; // 0x43 57003
+ private const int CodeTamil = 4; // 0x44 57004
+ private const int CodeTelugu = 5; // 0x45 57005
+ private const int CodeAssamese = 6; // 0x46 57006 Assamese (Bengali)
+ private const int CodeOriya = 7; // 0x47 57007
+ private const int CodeKannada = 8; // 0x48 57008
+ private const int CodeMalayalam = 9; // 0x49 57009
+ private const int CodeGujarati = 10; // 0x4a 57010
+ private const int CodePunjabi = 11; // 0x4b 57011 Punjabi (Gurmukhi)
+
+ // Ranges
+ private const int MultiByteBegin = 0xa0; // Beginning of MultiByte space in ISCII
+ private const int IndicBegin = 0x0901; // Beginining of Unicode Indic script code points
+ private const int IndicEnd = 0x0d6f; // End of Unicode Indic Script code points
+
+ // ISCII Control Values
+ private const byte ControlATR = 0xef; // Attribute (ATR) code
+ private const byte ControlCodePageStart = 0x40; // Start of code page range
+
+ // Interesting ISCII characters
+ private const byte Virama = 0xe8;
+ private const byte Nukta = 0xe9;
+ private const byte DevenagariExt = 0xf0;
+
+ // Interesting Unicode characters
+ private const char ZWNJ = (char)0x200c;
+ private const char ZWJ = (char)0x200d;
+
+ // Code Page
+ private int defaultCodePage;
+
+ public ISCIIEncoding(int codePage) : base(codePage)
+ {
+ // Set our code page (subtracting windows code page # offset)
+ defaultCodePage = codePage - 57000;
+
+ // Legal windows code pages are between Devanagari and Punjabi
+ Contract.Assert(defaultCodePage >= CodeDevanagari && defaultCodePage <= CodePunjabi,
+ "[ISCIIEncoding] Code page (" + codePage + " isn't supported by ISCIIEncoding!");
+
+ // This shouldn't really be possible
+ if (defaultCodePage < CodeDevanagari || defaultCodePage > CodePunjabi)
+ throw new ArgumentException(Environment.GetResourceString(
+ "Argument_CodepageNotSupported", codePage), "codePage");
+ }
+
+ // Constructor called by serialization.
+ internal ISCIIEncoding(SerializationInfo info, StreamingContext context) : base(0)
+ {
+ // Actually this can't ever get called, MLangCodePageEncoding is our proxy
+ // (In Everett this was done by MLang)
+ Contract.Assert(false, "Didn't expect to make it to ISCIIEncoding serialization constructor");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Make sure to get the base stuff too This throws if info is null
+ SerializeEncoding(info, context);
+ Contract.Assert(info!=null, "[ISCIIEncoding.GetObjectData] Expected null info to throw");
+
+ // Just need Everett MLangCodePageEncoding maxCharSize
+ info.AddValue("m_maxByteSize", 2);
+
+ // Always have this as our helper
+ info.SetType(typeof(MLangCodePageEncoding));
+ }
+
+ // Our MaxByteCount is 4 times the input size. That could be because
+ // the first input character could be in the wrong code page ("font") and
+ // then that character could also be encoded in 2 code points
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 4 Time input because 1st input could require code page change and also that char could require 2 code points
+ byteCount *= 4;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+ // Our MaxCharCount is the same as the byteCount. There are a few sequences
+ // where 2 (or more) bytes could become 2 chars, but thats still 1 to 1.
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Our MaxCharCount is the same as the byteCount. There are a few sequences
+ // where 2 (or more) bytes could become 2 chars, but thats still 1 to 1.
+ // Also could have 1 in decoder if we're waiting to see if next char's a nukta.
+ long charCount = ((long)byteCount + 1);
+
+ // Some code points are undefined so we could fall back.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ // Our workhorse version
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ {
+ // Use null pointer to ask GetBytes for count
+ return GetBytes(chars, count, null, 0, baseEncoder);
+ }
+
+ // Workhorse
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char *chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ {
+ // Allow null bytes for counting
+ Contract.Assert(chars != null, "[ISCIIEncoding.GetBytes]chars!=null");
+// Contract.Assert(bytes != null, "[ISCIIEncoding.GetBytes]bytes!=null");
+ Contract.Assert(charCount >=0, "[ISCIIEncoding.GetBytes]charCount >=0");
+ Contract.Assert(byteCount >=0, "[ISCIIEncoding.GetBytes]byteCount >=0");
+
+ // Need the ISCII Encoder
+ ISCIIEncoder encoder = (ISCIIEncoder) baseEncoder;
+
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ int currentCodePage = this.defaultCodePage;
+ bool bLastVirama = false;
+
+ // Use encoder info if available
+ if (encoder != null)
+ {
+ // Remember our old state
+ currentCodePage = encoder.currentCodePage;
+ bLastVirama = encoder.bLastVirama;
+
+ // If we have a high surrogate left over, then fall it back
+ if (encoder.charLeftOver > 0)
+ {
+ buffer.Fallback(encoder.charLeftOver);
+ bLastVirama = false; // Redundant
+ }
+ }
+
+ while (buffer.MoreData)
+ {
+ // Get our data
+ char ch = buffer.GetNextChar();
+
+ // See if its a Multi Byte Character
+ if (ch < MultiByteBegin)
+ {
+ // Its a boring low character, add it.
+ if (!buffer.AddByte((byte)ch))
+ break;
+ bLastVirama = false;
+ continue;
+ }
+
+ // See if its outside of the Indic script Range range
+ if ((ch < IndicBegin) || (ch > IndicEnd))
+ {
+ // See if its a ZWJ or ZWNJ and if we has bLastVirama;
+ if (bLastVirama && (ch == ZWNJ || ch == ZWJ))
+ {
+ // It was a bLastVirama and ZWNJ || ZWJ
+ if (ch == ZWNJ)
+ {
+ if (!buffer.AddByte(Virama))
+ break;
+ }
+ else // ZWJ
+ {
+ if (!buffer.AddByte(Nukta))
+ break;
+ }
+
+ // bLastVirama now counts as false
+ bLastVirama = false;
+ continue;
+ }
+
+ // Have to do our fallback
+ //
+ // Note that this will fallback 2 chars if this is a high surrogate.
+ // Throws if recursive (knows because we called InternalGetNextChar)
+ buffer.Fallback(ch);
+ bLastVirama = false;
+ continue;
+ }
+
+ // Its in the Unicode Indic script range
+ int indicInfo = UnicodeToIndicChar[ch - IndicBegin];
+ byte byteIndic = (byte)indicInfo;
+ int indicScript = (0x000f & (indicInfo >> 8));
+ int indicTwoBytes = (0xf000 & indicInfo);
+
+ // If IndicInfo is 0 then have to do fallback
+ if (indicInfo == 0)
+ {
+ // Its some Unicode character we don't have indic for.
+ // Have to do our fallback
+ // Add Fallback Count
+ // Note that chars was preincremented, and GetEncoderFallbackString might add an extra
+ // if chars != charEnd and there's a surrogate.
+ // Throws if recursive (knows because we called InternalGetNextChar)
+ buffer.Fallback(ch);
+
+ bLastVirama = false;
+ continue;
+ }
+
+ // See if our code page ("font" in ISCII spec) has to change
+ // (This if doesn't add character, just changes character set)
+ Contract.Assert(indicScript!=0, "[ISCIIEncoding.GetBytes]expected an indic script value");
+ if (indicScript != currentCodePage)
+ {
+ // It changed, spit out the ATR
+ if (!buffer.AddByte(ControlATR, (byte)(indicScript | ControlCodePageStart)))
+ break;
+
+ // Now spit out the new code page (& remember it) (do this afterwards in case AddByte failed)
+ currentCodePage = indicScript;
+
+ // We only know how to map from Unicode to pages from Devanagari to Punjabi (2 to 11)
+ Contract.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi,
+ "[ISCIIEncoding.GetBytes]Code page (" + currentCodePage + " shouldn't appear in ISCII from Unicode table!");
+ }
+
+ // Safe to add our byte now
+ if (!buffer.AddByte(byteIndic, indicTwoBytes != 0 ? 1:0))
+ break;
+
+ // Remember if this one was a Virama
+ bLastVirama = (byteIndic == Virama);
+
+ // Some characters need extra bytes
+ if (indicTwoBytes != 0)
+ {
+ // This one needs another byte
+ Contract.Assert((indicTwoBytes >> 12) > 0 && (indicTwoBytes >> 12) <= 3,
+ "[ISCIIEncoding.GetBytes]Expected indicTwoBytes from 1-3, not " + (indicTwoBytes >> 12));
+
+ // Already did buffer checking, but...
+ if (!buffer.AddByte(SecondIndicByte[indicTwoBytes >> 12]))
+ break;
+ }
+ }
+
+ // May need to switch back to our default code page
+ if (currentCodePage != defaultCodePage && (encoder == null || encoder.MustFlush))
+ {
+ // It changed, spit out the ATR
+ if (buffer.AddByte(ControlATR, (byte)(defaultCodePage | ControlCodePageStart)))
+ currentCodePage = defaultCodePage;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ bLastVirama = false;
+ }
+
+ // Make sure we remember our state if necessary
+ // Note that we don't care about flush because Virama and code page
+ // changes are legal at the end.
+ // Don't set encoder if we're just counting
+ if (encoder != null && bytes != null)
+ {
+ // Clear Encoder if necessary.
+ if (!buffer.fallbackBuffer.bUsedEncoder)
+ {
+ encoder.charLeftOver = (char)0;
+ }
+
+ // Remember our code page/virama state
+ encoder.currentCodePage = currentCodePage;
+ encoder.bLastVirama = bLastVirama;
+
+ // How many chars were used?
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ // Return our length
+ return buffer.Count;
+ }
+
+ // Workhorse
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ // Just call GetChars with null chars saying we want count
+ return GetChars(bytes, count, null, 0, baseDecoder);
+ }
+
+ // For decoding, the following interesting rules apply:
+ // Virama followed by another Virama or Nukta becomes Virama + ZWNJ or Virama + ZWJ
+ // ATR is followed by a byte to switch code pages ("fonts")
+ // Devenagari F0, B8 -> \u0952
+ // Devenagari F0, BF -> \u0970
+ // Some characters followed by E9 become a different character instead.
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ // Allow null chars for counting
+ Contract.Assert(bytes != null, "[ISCIIEncoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[ISCIIEncoding.GetChars]byteCount is negative");
+// Contract.Assert(chars != null, "[ISCIIEncoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[ISCIIEncoding.GetChars]charCount is negative");
+
+ // Need the ISCII Decoder
+ ISCIIDecoder decoder = (ISCIIDecoder) baseDecoder;
+
+ // Get our info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ int currentCodePage = this.defaultCodePage;
+ bool bLastATR = false;
+ bool bLastVirama = false;
+ bool bLastDevenagariStressAbbr = false;
+ char cLastCharForNextNukta = '\0';
+ char cLastCharForNoNextNukta = '\0';
+
+ // See if there's anything in our decoder
+ if (decoder != null)
+ {
+ currentCodePage = decoder.currentCodePage;
+ bLastATR = decoder.bLastATR;
+ bLastVirama = decoder.bLastVirama;
+ bLastDevenagariStressAbbr = decoder.bLastDevenagariStressAbbr;
+ cLastCharForNextNukta = decoder.cLastCharForNextNukta;
+ cLastCharForNoNextNukta = decoder.cLastCharForNoNextNukta;
+ }
+
+ bool bLastSpecial = bLastVirama | bLastATR | bLastDevenagariStressAbbr |
+ (cLastCharForNextNukta != '\0');
+
+ // Get our current code page index (some code pages are dups)
+ int currentCodePageIndex = -1;
+ Contract.Assert(currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi,
+ "[ISCIIEncoding.GetChars]Decoder code page must be >= Devanagari and <= Punjabi, not " + currentCodePage);
+
+ if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi)
+ {
+ currentCodePageIndex = IndicMappingIndex[currentCodePage];
+ }
+
+ // Loop through our input
+ while (buffer.MoreData)
+ {
+ byte b = buffer.GetNextByte();
+
+ // See if last one was special
+ if (bLastSpecial)
+ {
+ // Now it won't be
+ bLastSpecial = false;
+
+ // One and only one of our flags should be set
+ Contract.Assert(((bLastVirama ? 1 : 0) + (bLastATR ? 1 : 0) +
+ (bLastDevenagariStressAbbr ? 1 : 0) +
+ ((cLastCharForNextNukta > 0) ? 1 : 0)) == 1,
+ String.Format(CultureInfo.InvariantCulture,
+ "[ISCIIEncoding.GetChars]Special cases require 1 and only 1 special case flag: LastATR {0} Dev. {1} Nukta {2}",
+ bLastATR, bLastDevenagariStressAbbr, cLastCharForNextNukta));
+ // If the last one was an ATR, then we'll have to do ATR stuff
+ if (bLastATR)
+ {
+ // We only support Devanagari - Punjabi
+ if (b >= (0x40 | CodeDevanagari) && b <= (0x40 | CodePunjabi))
+ {
+ // Remember the code page
+ currentCodePage = b & 0xf;
+ currentCodePageIndex = IndicMappingIndex[currentCodePage];
+ // No longer last ATR
+ bLastATR = false;
+ continue;
+ }
+
+ // Change back to default?
+ if (b == 0x40)
+ {
+ currentCodePage = this.defaultCodePage;
+ currentCodePageIndex = -1;
+
+ if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi)
+ {
+ currentCodePageIndex = IndicMappingIndex[currentCodePage];
+ }
+ // No longer last ATR
+ bLastATR = false;
+ continue;
+ }
+
+ // We don't support Roman
+ if (b == 0x41)
+ {
+ currentCodePage = this.defaultCodePage;
+ currentCodePageIndex = -1;
+
+ if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi)
+ {
+ currentCodePageIndex = IndicMappingIndex[currentCodePage];
+ }
+
+ // Even though we don't know how to support Roman, windows didn't add a ? so we don't either.
+ // No longer last ATR
+ bLastATR = false;
+ continue;
+ }
+
+ // Other code pages & ATR codes not supported, fallback the ATR
+ // If fails, decrements the buffer, which is OK, we remember ATR state.
+ if (!buffer.Fallback(ControlATR))
+ break;
+
+ // No longer last ATR (fell back)
+ bLastATR = false;
+
+ // we know we can't have any of these other modes
+ Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastATR mode");
+ Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastATR mode");
+ Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastATR mode");
+ Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastATR mode");
+
+ // Keep processing this byte
+ }
+ else if (bLastVirama)
+ {
+ // If last was Virama, then we might need ZWNJ or ZWJ instead
+ if (b == Virama)
+ {
+ // If no room, then stop
+ if (!buffer.AddChar(ZWNJ))
+ break;
+ bLastVirama = false;
+ continue;
+ }
+ if (b == Nukta)
+ {
+ // If no room, then stop
+ if (!buffer.AddChar(ZWJ))
+ break;
+ bLastVirama = false;
+ continue;
+ }
+
+ // No longer in this mode, fall through to handle character
+ // (Virama itself was added when flag was set last iteration)
+ bLastVirama = false;
+
+ // We know we can't have any of these other modes
+ Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastVirama mode");
+ Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in bLastVirama mode");
+ Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastVirama mode");
+ Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastVirama mode");
+ }
+ else if (bLastDevenagariStressAbbr)
+ {
+ // Last byte was an 0xf0 (ext).
+ // If current is b8 or bf, then we have 952 or 970. Otherwise fallback
+ if (b == 0xb8)
+ {
+ // It was a 0xb8
+ if (!buffer.AddChar('\x0952')) // Devanagari stress sign anudatta
+ break;
+ bLastDevenagariStressAbbr = false;
+ continue;
+ }
+
+ if (b == 0xbf)
+ {
+ // It was a 0xbf
+ if (!buffer.AddChar('\x0970')) // Devanagari abbr. sign
+ break;
+ bLastDevenagariStressAbbr = false;
+ continue;
+ }
+
+ // Wasn't an expected pattern, do fallback for f0 (ext)
+ // if fails, fallback will back up our buffer
+ if (!buffer.Fallback(DevenagariExt))
+ break;
+
+ // Keep processing this byte (turn off mode)
+ // (last character was added when mode was set)
+ bLastDevenagariStressAbbr = false;
+
+ Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in bLastDevenagariStressAbbr mode");
+ Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in bLastDevenagariStressAbbr mode");
+ Contract.Assert(cLastCharForNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNextNukta in bLastDevenagariStressAbbr mode");
+ Contract.Assert(cLastCharForNoNextNukta == (char)0, "[ISCIIEncoding.GetChars] Expected no cLastCharForNoNextNukta in bLastDevenagariStressAbbr mode");
+ }
+ else
+ {
+ // We were checking for next char being a nukta
+ Contract.Assert(cLastCharForNextNukta > 0 && cLastCharForNoNextNukta > 0,
+ "[ISCIIEncoding.GetChars]No other special case found, but cLastCharFor(No)NextNukta variable(s) aren't set.");
+
+ // We'll either add combined char or last char
+ if (b == Nukta)
+ {
+ // We combine nukta with previous char
+ if (!buffer.AddChar(cLastCharForNextNukta))
+ break;
+
+ // Done already
+ cLastCharForNextNukta = cLastCharForNoNextNukta = '\0';
+ continue;
+ }
+
+ // No Nukta, just add last character and keep processing current byte
+ if (!buffer.AddChar(cLastCharForNoNextNukta))
+ break;
+
+ // Keep processing this byte, turn off mode.
+ cLastCharForNextNukta = cLastCharForNoNextNukta = '\0';
+
+ Contract.Assert(bLastATR == false, "[ISCIIEncoding.GetChars] Expected no bLastATR in cLastCharForNextNukta mode");
+ Contract.Assert(bLastVirama == false, "[ISCIIEncoding.GetChars] Expected no bLastVirama in cLastCharForNextNukta mode");
+ Contract.Assert(bLastDevenagariStressAbbr == false, "[ISCIIEncoding.GetChars] Expected no bLastDevenagariStressAbbr in cLastCharForNextNukta mode");
+ }
+ }
+
+ // Now bLastSpecial should be false and all flags false.
+ Contract.Assert (!bLastSpecial && !bLastDevenagariStressAbbr && !bLastVirama && !bLastATR &&
+ cLastCharForNextNukta == '\0',
+ "[ISCIIEncoding.GetChars]No special state for last code point should exist at this point.");
+
+ // If its a simple byte, just add it
+ if (b < MultiByteBegin)
+ {
+ if (!buffer.AddChar((char)b))
+ break;
+ continue;
+ }
+
+ // See if its an ATR marker
+ if (b == ControlATR)
+ {
+ bLastATR = bLastSpecial = true;
+ continue;
+ }
+
+ Contract.Assert (currentCodePageIndex != -1, "[ISCIIEncoding.GetChars]Expected valid currentCodePageIndex != -1");
+ char ch = IndicMapping[currentCodePageIndex, 0, b - MultiByteBegin];
+ char cAlt = IndicMapping[currentCodePageIndex, 1, b - MultiByteBegin];
+
+ // If no 2nd char, just add it, also lonely Nuktas get added as well.
+ if (cAlt == 0 || b == Nukta)
+ {
+ // If it was an unknown character do fallback
+
+ // ? if not known.
+ if (ch == 0)
+ {
+ // Fallback the unknown byte
+ if (!buffer.Fallback(b))
+ break;
+ }
+ else
+ {
+ // Add the known character
+ if (!buffer.AddChar(ch))
+ break;
+ }
+ continue;
+ }
+
+ // if b == Virama set last Virama so we can do ZWJ or ZWNJ next time if needed.
+ if (b == Virama)
+ {
+ // Add Virama
+ if (!buffer.AddChar(ch))
+ break;
+ bLastVirama = bLastSpecial = true;
+ continue;
+ }
+
+ // See if its one that changes with a Nukta
+ if ((cAlt & 0xF000) == 0)
+ {
+ // It could change if next char is a nukta
+ bLastSpecial = true;
+ cLastCharForNextNukta = cAlt;
+ cLastCharForNoNextNukta = ch;
+ continue;
+ }
+
+ // We must be the Devenagari special case for F0, B8 & F0, BF
+ Contract.Assert(currentCodePage == CodeDevanagari && b == DevenagariExt,
+ String.Format(CultureInfo.InvariantCulture,
+ "[ISCIIEncoding.GetChars] Devenagari special case must {0} not {1} or in Devanagari code page {2} not {3}.",
+ DevenagariExt, b, CodeDevanagari, currentCodePage));
+ bLastDevenagariStressAbbr = bLastSpecial = true;
+
+ }
+
+ // If we don't have a decoder, or if we had to flush, then we need to get rid
+ // of last ATR, LastNoNextNukta and LastDevenagariExt.
+ if (decoder == null || decoder.MustFlush)
+ {
+ // If these fail (because of Convert with insufficient buffer), then they'll turn off MustFlush as well.
+ if (bLastATR)
+ {
+ // Have to add ATR fallback
+ if (buffer.Fallback(ControlATR))
+ bLastATR = false;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddChar will have decremented our byte count, however we need it to remain the same
+ buffer.GetNextByte();
+ }
+ else if (bLastDevenagariStressAbbr)
+ {
+ // Have to do fallback for DevenagariExt
+ if (buffer.Fallback(DevenagariExt))
+ bLastDevenagariStressAbbr = false;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddChar will have decremented our byte count, however we need it to remain the same
+ buffer.GetNextByte();
+ }
+ else if (cLastCharForNoNextNukta != '\0')
+ {
+ // Have to add our last char because there was no next nukta
+ if (buffer.AddChar(cLastCharForNoNextNukta))
+ cLastCharForNoNextNukta = cLastCharForNextNukta = '\0';
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddChar will have decremented our byte count, however we need it to remain the same
+ buffer.GetNextByte();
+ }
+ // LastVirama is unimportant for flushing decoder.
+ }
+
+ // Remember any left over stuff
+ // (only remember if we aren't counting)
+ if (decoder != null && chars != null)
+ {
+ // If not flushing or have state (from convert) then need to remember state
+ if (!decoder.MustFlush ||
+ cLastCharForNoNextNukta != '\0' || bLastATR || bLastDevenagariStressAbbr)
+ {
+ // Either not flushing or had state (from convert)
+ Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow,
+ "[ISCIIEncoding.GetChars]Expected no state or not converting or not flushing");
+ decoder.currentCodePage = currentCodePage;
+ decoder.bLastVirama = bLastVirama;
+ decoder.bLastATR = bLastATR;
+ decoder.bLastDevenagariStressAbbr = bLastDevenagariStressAbbr;
+ decoder.cLastCharForNextNukta = cLastCharForNextNukta;
+ decoder.cLastCharForNoNextNukta = cLastCharForNoNextNukta;
+ }
+ else
+ {
+ decoder.currentCodePage = this.defaultCodePage;
+ decoder.bLastVirama = false;
+ decoder.bLastATR = false;
+ decoder.bLastDevenagariStressAbbr = false;
+ decoder.cLastCharForNextNukta = '\0';
+ decoder.cLastCharForNoNextNukta = '\0';
+ }
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+ // Otherwise we already did fallback and added extra things
+
+ // Return the # of characters we found
+ return buffer.Count;
+ }
+
+ public override Decoder GetDecoder()
+ {
+ return new ISCIIDecoder(this);
+ }
+
+ public override Encoder GetEncoder()
+ {
+ return new ISCIIEncoder(this);
+ }
+
+ public override int GetHashCode()
+ {
+ //Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
+ return defaultCodePage + this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode();
+ }
+
+ [Serializable]
+ internal class ISCIIEncoder : EncoderNLS
+ {
+ // Need to remember the default code page (for HasState)
+ internal int defaultCodePage = 0;
+
+ // Need a place for the current code page
+ internal int currentCodePage = 0;
+
+ // Was the last character a virama? (Because ZWJ and ZWNJ are different then)
+ internal bool bLastVirama = false;
+
+ public ISCIIEncoder(Encoding encoding) : base(encoding)
+ {
+ this.currentCodePage = this.defaultCodePage = encoding.CodePage - 57000;
+
+ // base calls reset
+ }
+
+ // Warning: If you're decoding mixed encoding files or something, this could be confusing
+ // We don't always force back to base encoding mapping, so if you reset where do you restart?
+ public override void Reset()
+ {
+ bLastVirama = false;
+ charLeftOver = (char)0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our encoder?
+ // Encoder not only has to get rid of left over characters, but it has to switch back to the current code page.
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.charLeftOver != (char)0 || this.currentCodePage != this.defaultCodePage);
+ }
+ }
+ }
+
+ [Serializable]
+ internal class ISCIIDecoder : DecoderNLS
+ {
+ // Need a place to store any our current code page and last ATR flag
+ internal int currentCodePage = 0;
+ internal bool bLastATR = false;
+ internal bool bLastVirama = false;
+ internal bool bLastDevenagariStressAbbr = false;
+ internal char cLastCharForNextNukta = '\0';
+ internal char cLastCharForNoNextNukta = '\0';
+
+ public ISCIIDecoder(Encoding encoding) : base(encoding)
+ {
+ this.currentCodePage = encoding.CodePage - 57000;
+
+ // base calls reset
+ }
+
+ // Warning: If you're decoding mixed encoding files or something, this could be confusing
+ // We don't always force back to base encoding mapping, so if you reset where do you restart?
+ public override void Reset()
+ {
+ bLastATR = false;
+ bLastVirama = false;
+ bLastDevenagariStressAbbr = false;
+ cLastCharForNextNukta = '\0';
+ cLastCharForNoNextNukta = '\0';
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.cLastCharForNextNukta != '\0' || this.cLastCharForNoNextNukta != '\0' ||
+ this.bLastATR || this.bLastDevenagariStressAbbr);
+ }
+ }
+ }
+
+ //
+ // ISCII Tables
+ //
+ // From Windows ISCII\tables.c
+ //
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Char to Byte
+ //
+ // 0xXYZZ Where Y is the code page "font" part and ZZ is the byte character
+ // The high X bits also reference the SecondIndicByte table if an
+ // extra byte is needed.
+ // 0x0000 For undefined characters
+ //
+ // This is valid for values IndicBegin to IndicEnd
+ //
+ // WARNING: When this was copied from windows, the ? characters (0x003F) were
+ // searched/replaced with 0x0000.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ static int[] UnicodeToIndicChar =
+ {
+ 0x02a1, // U+0901 : Devanagari Sign Candrabindu
+ 0x02a2, // U+0902 : Devanagari Sign Anusvara
+ 0x02a3, // U+0903 : Devanagari Sign Visarga
+ 0x0000, // U+0904 : Undefined
+ 0x02a4, // U+0905 : Devanagari Letter A
+ 0x02a5, // U+0906 : Devanagari Letter Aa
+ 0x02a6, // U+0907 : Devanagari Letter I
+ 0x02a7, // U+0908 : Devanagari Letter Ii
+ 0x02a8, // U+0909 : Devanagari Letter U
+ 0x02a9, // U+090a : Devanagari Letter Uu
+ 0x02aa, // U+090b : Devanagari Letter Vocalic R
+ 0x12a6, // U+090c : Devanagari Letter Vocalic L
+ 0x02ae, // U+090d : Devanagari Letter Candra E
+ 0x02ab, // U+090e : Devanagari Letter Short E
+ 0x02ac, // U+090f : Devanagari Letter E
+ 0x02ad, // U+0910 : Devanagari Letter Ai
+ 0x02b2, // U+0911 : Devanagari Letter Candra O
+ 0x02af, // U+0912 : Devanagari Letter Short O
+ 0x02b0, // U+0913 : Devanagari Letter O
+ 0x02b1, // U+0914 : Devanagari Letter Au
+ 0x02b3, // U+0915 : Devanagari Letter Ka
+ 0x02b4, // U+0916 : Devanagari Letter Kha
+ 0x02b5, // U+0917 : Devanagari Letter Ga
+ 0x02b6, // U+0918 : Devanagari Letter Gha
+ 0x02b7, // U+0919 : Devanagari Letter Nga
+ 0x02b8, // U+091a : Devanagari Letter Ca
+ 0x02b9, // U+091b : Devanagari Letter Cha
+ 0x02ba, // U+091c : Devanagari Letter Ja
+ 0x02bb, // U+091d : Devanagari Letter Jha
+ 0x02bc, // U+091e : Devanagari Letter Nya
+ 0x02bd, // U+091f : Devanagari Letter Tta
+ 0x02be, // U+0920 : Devanagari Letter Ttha
+ 0x02bf, // U+0921 : Devanagari Letter Dda
+ 0x02c0, // U+0922 : Devanagari Letter Ddha
+ 0x02c1, // U+0923 : Devanagari Letter Nna
+ 0x02c2, // U+0924 : Devanagari Letter Ta
+ 0x02c3, // U+0925 : Devanagari Letter Tha
+ 0x02c4, // U+0926 : Devanagari Letter Da
+ 0x02c5, // U+0927 : Devanagari Letter Dha
+ 0x02c6, // U+0928 : Devanagari Letter Na
+ 0x02c7, // U+0929 : Devanagari Letter Nnna
+ 0x02c8, // U+092a : Devanagari Letter Pa
+ 0x02c9, // U+092b : Devanagari Letter Pha
+ 0x02ca, // U+092c : Devanagari Letter Ba
+ 0x02cb, // U+092d : Devanagari Letter Bha
+ 0x02cc, // U+092e : Devanagari Letter Ma
+ 0x02cd, // U+092f : Devanagari Letter Ya
+ 0x02cf, // U+0930 : Devanagari Letter Ra
+ 0x02d0, // U+0931 : Devanagari Letter Rra
+ 0x02d1, // U+0932 : Devanagari Letter La
+ 0x02d2, // U+0933 : Devanagari Letter Lla
+ 0x02d3, // U+0934 : Devanagari Letter Llla
+ 0x02d4, // U+0935 : Devanagari Letter Va
+ 0x02d5, // U+0936 : Devanagari Letter Sha
+ 0x02d6, // U+0937 : Devanagari Letter Ssa
+ 0x02d7, // U+0938 : Devanagari Letter Sa
+ 0x02d8, // U+0939 : Devanagari Letter Ha
+ 0x0000, // U+093a : Undefined
+ 0x0000, // U+093b : Undefined
+ 0x02e9, // U+093c : Devanagari Sign Nukta
+ 0x12ea, // U+093d : Devanagari Sign Avagraha
+ 0x02da, // U+093e : Devanagari Vowel Sign Aa
+ 0x02db, // U+093f : Devanagari Vowel Sign I
+ 0x02dc, // U+0940 : Devanagari Vowel Sign Ii
+ 0x02dd, // U+0941 : Devanagari Vowel Sign U
+ 0x02de, // U+0942 : Devanagari Vowel Sign Uu
+ 0x02df, // U+0943 : Devanagari Vowel Sign Vocalic R
+ 0x12df, // U+0944 : Devanagari Vowel Sign Vocalic Rr
+ 0x02e3, // U+0945 : Devanagari Vowel Sign Candra E
+ 0x02e0, // U+0946 : Devanagari Vowel Sign Short E
+ 0x02e1, // U+0947 : Devanagari Vowel Sign E
+ 0x02e2, // U+0948 : Devanagari Vowel Sign Ai
+ 0x02e7, // U+0949 : Devanagari Vowel Sign Candra O
+ 0x02e4, // U+094a : Devanagari Vowel Sign Short O
+ 0x02e5, // U+094b : Devanagari Vowel Sign O
+ 0x02e6, // U+094c : Devanagari Vowel Sign Au
+ 0x02e8, // U+094d : Devanagari Sign Virama
+ 0x0000, // U+094e : Undefined
+ 0x0000, // U+094f : Undefined
+ 0x12a1, // U+0950 : Devanagari Om
+ 0x0000, // U+0951 : Devanagari Stress Sign Udatta
+ 0x22f0, // U+0952 : Devanagari Stress Sign Anudatta
+ 0x0000, // U+0953 : Devanagari Grave Accent
+ 0x0000, // U+0954 : Devanagari Acute Accent
+ 0x0000, // U+0955 : Undefined
+ 0x0000, // U+0956 : Undefined
+ 0x0000, // U+0957 : Undefined
+ 0x12b3, // U+0958 : Devanagari Letter Qa
+ 0x12b4, // U+0959 : Devanagari Letter Khha
+ 0x12b5, // U+095a : Devanagari Letter Ghha
+ 0x12ba, // U+095b : Devanagari Letter Za
+ 0x12bf, // U+095c : Devanagari Letter Dddha
+ 0x12c0, // U+095d : Devanagari Letter Rha
+ 0x12c9, // U+095e : Devanagari Letter Fa
+ 0x02ce, // U+095f : Devanagari Letter Yya
+ 0x12aa, // U+0960 : Devanagari Letter Vocalic Rr
+ 0x12a7, // U+0961 : Devanagari Letter Vocalic Ll
+ 0x12db, // U+0962 : Devanagari Vowel Sign Vocalic L
+ 0x12dc, // U+0963 : Devanagari Vowel Sign Vocalic Ll
+ 0x02ea, // U+0964 : Devanagari Danda
+ 0x0000, // U+0965 : Devanagari Double Danda
+ 0x02f1, // U+0966 : Devanagari Digit Zero
+ 0x02f2, // U+0967 : Devanagari Digit One
+ 0x02f3, // U+0968 : Devanagari Digit Two
+ 0x02f4, // U+0969 : Devanagari Digit Three
+ 0x02f5, // U+096a : Devanagari Digit Four
+ 0x02f6, // U+096b : Devanagari Digit Five
+ 0x02f7, // U+096c : Devanagari Digit Six
+ 0x02f8, // U+096d : Devanagari Digit Seven
+ 0x02f9, // U+096e : Devanagari Digit Eight
+ 0x02fa, // U+096f : Devanagari Digit Nine
+ 0x32f0, // U+0970 : Devanagari Abbreviation Sign
+ 0x0000, // U+0971 : Undefined
+ 0x0000, // U+0972 : Undefined
+ 0x0000, // U+0973 : Undefined
+ 0x0000, // U+0974 : Undefined
+ 0x0000, // U+0975 : Undefined
+ 0x0000, // U+0976 : Undefined
+ 0x0000, // U+0977 : Undefined
+ 0x0000, // U+0978 : Undefined
+ 0x0000, // U+0979 : Undefined
+ 0x0000, // U+097a : Undefined
+ 0x0000, // U+097b : Undefined
+ 0x0000, // U+097c : Undefined
+ 0x0000, // U+097d : Undefined
+ 0x0000, // U+097e : Undefined
+ 0x0000, // U+097f : Undefined
+ 0x0000, // U+0980 : Undefined
+ 0x03a1, // U+0981 : Bengali Sign Candrabindu
+ 0x03a2, // U+0982 : Bengali Sign Anusvara
+ 0x03a3, // U+0983 : Bengali Sign Visarga
+ 0x0000, // U+0984 : Undefined
+ 0x03a4, // U+0985 : Bengali Letter A
+ 0x03a5, // U+0986 : Bengali Letter Aa
+ 0x03a6, // U+0987 : Bengali Letter I
+ 0x03a7, // U+0988 : Bengali Letter Ii
+ 0x03a8, // U+0989 : Bengali Letter U
+ 0x03a9, // U+098a : Bengali Letter Uu
+ 0x03aa, // U+098b : Bengali Letter Vocalic R
+ 0x13a6, // U+098c : Bengali Letter Vocalic L
+ 0x0000, // U+098d : Undefined
+ 0x0000, // U+098e : Undefined
+ 0x03ab, // U+098f : Bengali Letter E
+ 0x03ad, // U+0990 : Bengali Letter Ai
+ 0x0000, // U+0991 : Undefined
+ 0x0000, // U+0992 : Undefined
+ 0x03af, // U+0993 : Bengali Letter O
+ 0x03b1, // U+0994 : Bengali Letter Au
+ 0x03b3, // U+0995 : Bengali Letter Ka
+ 0x03b4, // U+0996 : Bengali Letter Kha
+ 0x03b5, // U+0997 : Bengali Letter Ga
+ 0x03b6, // U+0998 : Bengali Letter Gha
+ 0x03b7, // U+0999 : Bengali Letter Nga
+ 0x03b8, // U+099a : Bengali Letter Ca
+ 0x03b9, // U+099b : Bengali Letter Cha
+ 0x03ba, // U+099c : Bengali Letter Ja
+ 0x03bb, // U+099d : Bengali Letter Jha
+ 0x03bc, // U+099e : Bengali Letter Nya
+ 0x03bd, // U+099f : Bengali Letter Tta
+ 0x03be, // U+09a0 : Bengali Letter Ttha
+ 0x03bf, // U+09a1 : Bengali Letter Dda
+ 0x03c0, // U+09a2 : Bengali Letter Ddha
+ 0x03c1, // U+09a3 : Bengali Letter Nna
+ 0x03c2, // U+09a4 : Bengali Letter Ta
+ 0x03c3, // U+09a5 : Bengali Letter Tha
+ 0x03c4, // U+09a6 : Bengali Letter Da
+ 0x03c5, // U+09a7 : Bengali Letter Dha
+ 0x03c6, // U+09a8 : Bengali Letter Na
+ 0x0000, // U+09a9 : Undefined
+ 0x03c8, // U+09aa : Bengali Letter Pa
+ 0x03c9, // U+09ab : Bengali Letter Pha
+ 0x03ca, // U+09ac : Bengali Letter Ba
+ 0x03cb, // U+09ad : Bengali Letter Bha
+ 0x03cc, // U+09ae : Bengali Letter Ma
+ 0x03cd, // U+09af : Bengali Letter Ya
+ 0x03cf, // U+09b0 : Bengali Letter Ra
+ 0x0000, // U+09b1 : Undefined
+ 0x03d1, // U+09b2 : Bengali Letter La
+ 0x0000, // U+09b3 : Undefined
+ 0x0000, // U+09b4 : Undefined
+ 0x0000, // U+09b5 : Undefined
+ 0x03d5, // U+09b6 : Bengali Letter Sha
+ 0x03d6, // U+09b7 : Bengali Letter Ssa
+ 0x03d7, // U+09b8 : Bengali Letter Sa
+ 0x03d8, // U+09b9 : Bengali Letter Ha
+ 0x0000, // U+09ba : Undefined
+ 0x0000, // U+09bb : Undefined
+ 0x03e9, // U+09bc : Bengali Sign Nukta
+ 0x0000, // U+09bd : Undefined
+ 0x03da, // U+09be : Bengali Vowel Sign Aa
+ 0x03db, // U+09bf : Bengali Vowel Sign I
+ 0x03dc, // U+09c0 : Bengali Vowel Sign Ii
+ 0x03dd, // U+09c1 : Bengali Vowel Sign U
+ 0x03de, // U+09c2 : Bengali Vowel Sign Uu
+ 0x03df, // U+09c3 : Bengali Vowel Sign Vocalic R
+ 0x13df, // U+09c4 : Bengali Vowel Sign Vocalic Rr
+ 0x0000, // U+09c5 : Undefined
+ 0x0000, // U+09c6 : Undefined
+ 0x03e0, // U+09c7 : Bengali Vowel Sign E
+ 0x03e2, // U+09c8 : Bengali Vowel Sign Ai
+ 0x0000, // U+09c9 : Undefined
+ 0x0000, // U+09ca : Undefined
+ 0x03e4, // U+09cb : Bengali Vowel Sign O
+ 0x03e6, // U+09cc : Bengali Vowel Sign Au
+ 0x03e8, // U+09cd : Bengali Sign Virama
+ 0x0000, // U+09ce : Undefined
+ 0x0000, // U+09cf : Undefined
+ 0x0000, // U+09d0 : Undefined
+ 0x0000, // U+09d1 : Undefined
+ 0x0000, // U+09d2 : Undefined
+ 0x0000, // U+09d3 : Undefined
+ 0x0000, // U+09d4 : Undefined
+ 0x0000, // U+09d5 : Undefined
+ 0x0000, // U+09d6 : Undefined
+ 0x0000, // U+09d7 : Bengali Au Length Mark
+ 0x0000, // U+09d8 : Undefined
+ 0x0000, // U+09d9 : Undefined
+ 0x0000, // U+09da : Undefined
+ 0x0000, // U+09db : Undefined
+ 0x13bf, // U+09dc : Bengali Letter Rra
+ 0x13c0, // U+09dd : Bengali Letter Rha
+ 0x0000, // U+09de : Undefined
+ 0x03ce, // U+09df : Bengali Letter Yya
+ 0x13aa, // U+09e0 : Bengali Letter Vocalic Rr
+ 0x13a7, // U+09e1 : Bengali Letter Vocalic Ll
+ 0x13db, // U+09e2 : Bengali Vowel Sign Vocalic L
+ 0x13dc, // U+09e3 : Bengali Vowel Sign Vocalic Ll
+ 0x0000, // U+09e4 : Undefined
+ 0x0000, // U+09e5 : Undefined
+ 0x03f1, // U+09e6 : Bengali Digit Zero
+ 0x03f2, // U+09e7 : Bengali Digit One
+ 0x03f3, // U+09e8 : Bengali Digit Two
+ 0x03f4, // U+09e9 : Bengali Digit Three
+ 0x03f5, // U+09ea : Bengali Digit Four
+ 0x03f6, // U+09eb : Bengali Digit Five
+ 0x03f7, // U+09ec : Bengali Digit Six
+ 0x03f8, // U+09ed : Bengali Digit Seven
+ 0x03f9, // U+09ee : Bengali Digit Eight
+ 0x03fa, // U+09ef : Bengali Digit Nine
+ 0x0000, // U+09f0 : Bengali Letter Ra With Middle Diagonal
+ 0x0000, // U+09f1 : Bengali Letter Ra With Lower Diagonal
+ 0x0000, // U+09f2 : Bengali Rupee Mark
+ 0x0000, // U+09f3 : Bengali Rupee Sign
+ 0x0000, // U+09f4 : Bengali Currency Numerator One
+ 0x0000, // U+09f5 : Bengali Currency Numerator Two
+ 0x0000, // U+09f6 : Bengali Currency Numerator Three
+ 0x0000, // U+09f7 : Bengali Currency Numerator Four
+ 0x0000, // U+09f8 : Bengali Currency Numerator One Less Than The Denominator
+ 0x0000, // U+09f9 : Bengali Currency Denominator Sixteen
+ 0x0000, // U+09fa : Bengali Isshar
+ 0x0000, // U+09fb : Undefined
+ 0x0000, // U+09fc : Undefined
+ 0x0000, // U+09fd : Undefined
+ 0x0000, // U+09fe : Undefined
+ 0x0000, // U+09ff : Undefined
+ 0x0000, // U+0a00 : Undefined
+ 0x0000, // U+0a01 : Undefined
+ 0x0ba2, // U+0a02 : Gurmukhi Sign Bindi
+ 0x0000, // U+0a03 : Undefined
+ 0x0000, // U+0a04 : Undefined
+ 0x0ba4, // U+0a05 : Gurmukhi Letter A
+ 0x0ba5, // U+0a06 : Gurmukhi Letter Aa
+ 0x0ba6, // U+0a07 : Gurmukhi Letter I
+ 0x0ba7, // U+0a08 : Gurmukhi Letter Ii
+ 0x0ba8, // U+0a09 : Gurmukhi Letter U
+ 0x0ba9, // U+0a0a : Gurmukhi Letter Uu
+ 0x0000, // U+0a0b : Undefined
+ 0x0000, // U+0a0c : Undefined
+ 0x0000, // U+0a0d : Undefined
+ 0x0000, // U+0a0e : Undefined
+ 0x0bab, // U+0a0f : Gurmukhi Letter Ee
+ 0x0bad, // U+0a10 : Gurmukhi Letter Ai
+ 0x0000, // U+0a11 : Undefined
+ 0x0000, // U+0a12 : Undefined
+ 0x0bb0, // U+0a13 : Gurmukhi Letter Oo
+ 0x0bb1, // U+0a14 : Gurmukhi Letter Au
+ 0x0bb3, // U+0a15 : Gurmukhi Letter Ka
+ 0x0bb4, // U+0a16 : Gurmukhi Letter Kha
+ 0x0bb5, // U+0a17 : Gurmukhi Letter Ga
+ 0x0bb6, // U+0a18 : Gurmukhi Letter Gha
+ 0x0bb7, // U+0a19 : Gurmukhi Letter Nga
+ 0x0bb8, // U+0a1a : Gurmukhi Letter Ca
+ 0x0bb9, // U+0a1b : Gurmukhi Letter Cha
+ 0x0bba, // U+0a1c : Gurmukhi Letter Ja
+ 0x0bbb, // U+0a1d : Gurmukhi Letter Jha
+ 0x0bbc, // U+0a1e : Gurmukhi Letter Nya
+ 0x0bbd, // U+0a1f : Gurmukhi Letter Tta
+ 0x0bbe, // U+0a20 : Gurmukhi Letter Ttha
+ 0x0bbf, // U+0a21 : Gurmukhi Letter Dda
+ 0x0bc0, // U+0a22 : Gurmukhi Letter Ddha
+ 0x0bc1, // U+0a23 : Gurmukhi Letter Nna
+ 0x0bc2, // U+0a24 : Gurmukhi Letter Ta
+ 0x0bc3, // U+0a25 : Gurmukhi Letter Tha
+ 0x0bc4, // U+0a26 : Gurmukhi Letter Da
+ 0x0bc5, // U+0a27 : Gurmukhi Letter Dha
+ 0x0bc6, // U+0a28 : Gurmukhi Letter Na
+ 0x0000, // U+0a29 : Undefined
+ 0x0bc8, // U+0a2a : Gurmukhi Letter Pa
+ 0x0bc9, // U+0a2b : Gurmukhi Letter Pha
+ 0x0bca, // U+0a2c : Gurmukhi Letter Ba
+ 0x0bcb, // U+0a2d : Gurmukhi Letter Bha
+ 0x0bcc, // U+0a2e : Gurmukhi Letter Ma
+ 0x0bcd, // U+0a2f : Gurmukhi Letter Ya
+ 0x0bcf, // U+0a30 : Gurmukhi Letter Ra
+ 0x0000, // U+0a31 : Undefined
+ 0x0bd1, // U+0a32 : Gurmukhi Letter La
+ 0x0bd2, // U+0a33 : Gurmukhi Letter Lla
+ 0x0000, // U+0a34 : Undefined
+ 0x0bd4, // U+0a35 : Gurmukhi Letter Va
+ 0x0bd5, // U+0a36 : Gurmukhi Letter Sha
+ 0x0000, // U+0a37 : Undefined
+ 0x0bd7, // U+0a38 : Gurmukhi Letter Sa
+ 0x0bd8, // U+0a39 : Gurmukhi Letter Ha
+ 0x0000, // U+0a3a : Undefined
+ 0x0000, // U+0a3b : Undefined
+ 0x0be9, // U+0a3c : Gurmukhi Sign Nukta
+ 0x0000, // U+0a3d : Undefined
+ 0x0bda, // U+0a3e : Gurmukhi Vowel Sign Aa
+ 0x0bdb, // U+0a3f : Gurmukhi Vowel Sign I
+ 0x0bdc, // U+0a40 : Gurmukhi Vowel Sign Ii
+ 0x0bdd, // U+0a41 : Gurmukhi Vowel Sign U
+ 0x0bde, // U+0a42 : Gurmukhi Vowel Sign Uu
+ 0x0000, // U+0a43 : Undefined
+ 0x0000, // U+0a44 : Undefined
+ 0x0000, // U+0a45 : Undefined
+ 0x0000, // U+0a46 : Undefined
+ 0x0be0, // U+0a47 : Gurmukhi Vowel Sign Ee
+ 0x0be2, // U+0a48 : Gurmukhi Vowel Sign Ai
+ 0x0000, // U+0a49 : Undefined
+ 0x0000, // U+0a4a : Undefined
+ 0x0be4, // U+0a4b : Gurmukhi Vowel Sign Oo
+ 0x0be6, // U+0a4c : Gurmukhi Vowel Sign Au
+ 0x0be8, // U+0a4d : Gurmukhi Sign Virama
+ 0x0000, // U+0a4e : Undefined
+ 0x0000, // U+0a4f : Undefined
+ 0x0000, // U+0a50 : Undefined
+ 0x0000, // U+0a51 : Undefined
+ 0x0000, // U+0a52 : Undefined
+ 0x0000, // U+0a53 : Undefined
+ 0x0000, // U+0a54 : Undefined
+ 0x0000, // U+0a55 : Undefined
+ 0x0000, // U+0a56 : Undefined
+ 0x0000, // U+0a57 : Undefined
+ 0x0000, // U+0a58 : Undefined
+ 0x1bb4, // U+0a59 : Gurmukhi Letter Khha
+ 0x1bb5, // U+0a5a : Gurmukhi Letter Ghha
+ 0x1bba, // U+0a5b : Gurmukhi Letter Za
+ 0x1bc0, // U+0a5c : Gurmukhi Letter Rra
+ 0x0000, // U+0a5d : Undefined
+ 0x1bc9, // U+0a5e : Gurmukhi Letter Fa
+ 0x0000, // U+0a5f : Undefined
+ 0x0000, // U+0a60 : Undefined
+ 0x0000, // U+0a61 : Undefined
+ 0x0000, // U+0a62 : Undefined
+ 0x0000, // U+0a63 : Undefined
+ 0x0000, // U+0a64 : Undefined
+ 0x0000, // U+0a65 : Undefined
+ 0x0bf1, // U+0a66 : Gurmukhi Digit Zero
+ 0x0bf2, // U+0a67 : Gurmukhi Digit One
+ 0x0bf3, // U+0a68 : Gurmukhi Digit Two
+ 0x0bf4, // U+0a69 : Gurmukhi Digit Three
+ 0x0bf5, // U+0a6a : Gurmukhi Digit Four
+ 0x0bf6, // U+0a6b : Gurmukhi Digit Five
+ 0x0bf7, // U+0a6c : Gurmukhi Digit Six
+ 0x0bf8, // U+0a6d : Gurmukhi Digit Seven
+ 0x0bf9, // U+0a6e : Gurmukhi Digit Eight
+ 0x0bfa, // U+0a6f : Gurmukhi Digit Nine
+ 0x0000, // U+0a70 : Gurmukhi Tippi
+ 0x0000, // U+0a71 : Gurmukhi Addak
+ 0x0000, // U+0a72 : Gurmukhi Iri
+ 0x0000, // U+0a73 : Gurmukhi Ura
+ 0x0000, // U+0a74 : Gurmukhi Ek Onkar
+ 0x0000, // U+0a75 : Undefined
+ 0x0000, // U+0a76 : Undefined
+ 0x0000, // U+0a77 : Undefined
+ 0x0000, // U+0a78 : Undefined
+ 0x0000, // U+0a79 : Undefined
+ 0x0000, // U+0a7a : Undefined
+ 0x0000, // U+0a7b : Undefined
+ 0x0000, // U+0a7c : Undefined
+ 0x0000, // U+0a7d : Undefined
+ 0x0000, // U+0a7e : Undefined
+ 0x0000, // U+0a7f : Undefined
+ 0x0000, // U+0a80 : Undefined
+ 0x0aa1, // U+0a81 : Gujarati Sign Candrabindu
+ 0x0aa2, // U+0a82 : Gujarati Sign Anusvara
+ 0x0aa3, // U+0a83 : Gujarati Sign Visarga
+ 0x0000, // U+0a84 : Undefined
+ 0x0aa4, // U+0a85 : Gujarati Letter A
+ 0x0aa5, // U+0a86 : Gujarati Letter Aa
+ 0x0aa6, // U+0a87 : Gujarati Letter I
+ 0x0aa7, // U+0a88 : Gujarati Letter Ii
+ 0x0aa8, // U+0a89 : Gujarati Letter U
+ 0x0aa9, // U+0a8a : Gujarati Letter Uu
+ 0x0aaa, // U+0a8b : Gujarati Letter Vocalic R
+ 0x0000, // U+0a8c : Undefined
+ 0x0aae, // U+0a8d : Gujarati Vowel Candra E
+ 0x0000, // U+0a8e : Undefined
+ 0x0aab, // U+0a8f : Gujarati Letter E
+ 0x0aad, // U+0a90 : Gujarati Letter Ai
+ 0x0ab2, // U+0a91 : Gujarati Vowel Candra O
+ 0x0000, // U+0a92 : Undefined
+ 0x0ab0, // U+0a93 : Gujarati Letter O
+ 0x0ab1, // U+0a94 : Gujarati Letter Au
+ 0x0ab3, // U+0a95 : Gujarati Letter Ka
+ 0x0ab4, // U+0a96 : Gujarati Letter Kha
+ 0x0ab5, // U+0a97 : Gujarati Letter Ga
+ 0x0ab6, // U+0a98 : Gujarati Letter Gha
+ 0x0ab7, // U+0a99 : Gujarati Letter Nga
+ 0x0ab8, // U+0a9a : Gujarati Letter Ca
+ 0x0ab9, // U+0a9b : Gujarati Letter Cha
+ 0x0aba, // U+0a9c : Gujarati Letter Ja
+ 0x0abb, // U+0a9d : Gujarati Letter Jha
+ 0x0abc, // U+0a9e : Gujarati Letter Nya
+ 0x0abd, // U+0a9f : Gujarati Letter Tta
+ 0x0abe, // U+0aa0 : Gujarati Letter Ttha
+ 0x0abf, // U+0aa1 : Gujarati Letter Dda
+ 0x0ac0, // U+0aa2 : Gujarati Letter Ddha
+ 0x0ac1, // U+0aa3 : Gujarati Letter Nna
+ 0x0ac2, // U+0aa4 : Gujarati Letter Ta
+ 0x0ac3, // U+0aa5 : Gujarati Letter Tha
+ 0x0ac4, // U+0aa6 : Gujarati Letter Da
+ 0x0ac5, // U+0aa7 : Gujarati Letter Dha
+ 0x0ac6, // U+0aa8 : Gujarati Letter Na
+ 0x0000, // U+0aa9 : Undefined
+ 0x0ac8, // U+0aaa : Gujarati Letter Pa
+ 0x0ac9, // U+0aab : Gujarati Letter Pha
+ 0x0aca, // U+0aac : Gujarati Letter Ba
+ 0x0acb, // U+0aad : Gujarati Letter Bha
+ 0x0acc, // U+0aae : Gujarati Letter Ma
+ 0x0acd, // U+0aaf : Gujarati Letter Ya
+ 0x0acf, // U+0ab0 : Gujarati Letter Ra
+ 0x0000, // U+0ab1 : Undefined
+ 0x0ad1, // U+0ab2 : Gujarati Letter La
+ 0x0ad2, // U+0ab3 : Gujarati Letter Lla
+ 0x0000, // U+0ab4 : Undefined
+ 0x0ad4, // U+0ab5 : Gujarati Letter Va
+ 0x0ad5, // U+0ab6 : Gujarati Letter Sha
+ 0x0ad6, // U+0ab7 : Gujarati Letter Ssa
+ 0x0ad7, // U+0ab8 : Gujarati Letter Sa
+ 0x0ad8, // U+0ab9 : Gujarati Letter Ha
+ 0x0000, // U+0aba : Undefined
+ 0x0000, // U+0abb : Undefined
+ 0x0ae9, // U+0abc : Gujarati Sign Nukta
+ 0x1aea, // U+0abd : Gujarati Sign Avagraha
+ 0x0ada, // U+0abe : Gujarati Vowel Sign Aa
+ 0x0adb, // U+0abf : Gujarati Vowel Sign I
+ 0x0adc, // U+0ac0 : Gujarati Vowel Sign Ii
+ 0x0add, // U+0ac1 : Gujarati Vowel Sign U
+ 0x0ade, // U+0ac2 : Gujarati Vowel Sign Uu
+ 0x0adf, // U+0ac3 : Gujarati Vowel Sign Vocalic R
+ 0x1adf, // U+0ac4 : Gujarati Vowel Sign Vocalic Rr
+ 0x0ae3, // U+0ac5 : Gujarati Vowel Sign Candra E
+ 0x0000, // U+0ac6 : Undefined
+ 0x0ae0, // U+0ac7 : Gujarati Vowel Sign E
+ 0x0ae2, // U+0ac8 : Gujarati Vowel Sign Ai
+ 0x0ae7, // U+0ac9 : Gujarati Vowel Sign Candra O
+ 0x0000, // U+0aca : Undefined
+ 0x0ae4, // U+0acb : Gujarati Vowel Sign O
+ 0x0ae6, // U+0acc : Gujarati Vowel Sign Au
+ 0x0ae8, // U+0acd : Gujarati Sign Virama
+ 0x0000, // U+0ace : Undefined
+ 0x0000, // U+0acf : Undefined
+ 0x1aa1, // U+0ad0 : Gujarati Om
+ 0x0000, // U+0ad1 : Undefined
+ 0x0000, // U+0ad2 : Undefined
+ 0x0000, // U+0ad3 : Undefined
+ 0x0000, // U+0ad4 : Undefined
+ 0x0000, // U+0ad5 : Undefined
+ 0x0000, // U+0ad6 : Undefined
+ 0x0000, // U+0ad7 : Undefined
+ 0x0000, // U+0ad8 : Undefined
+ 0x0000, // U+0ad9 : Undefined
+ 0x0000, // U+0ada : Undefined
+ 0x0000, // U+0adb : Undefined
+ 0x0000, // U+0adc : Undefined
+ 0x0000, // U+0add : Undefined
+ 0x0000, // U+0ade : Undefined
+ 0x0000, // U+0adf : Undefined
+ 0x1aaa, // U+0ae0 : Gujarati Letter Vocalic Rr
+ 0x0000, // U+0ae1 : Undefined
+ 0x0000, // U+0ae2 : Undefined
+ 0x0000, // U+0ae3 : Undefined
+ 0x0000, // U+0ae4 : Undefined
+ 0x0000, // U+0ae5 : Undefined
+ 0x0af1, // U+0ae6 : Gujarati Digit Zero
+ 0x0af2, // U+0ae7 : Gujarati Digit One
+ 0x0af3, // U+0ae8 : Gujarati Digit Two
+ 0x0af4, // U+0ae9 : Gujarati Digit Three
+ 0x0af5, // U+0aea : Gujarati Digit Four
+ 0x0af6, // U+0aeb : Gujarati Digit Five
+ 0x0af7, // U+0aec : Gujarati Digit Six
+ 0x0af8, // U+0aed : Gujarati Digit Seven
+ 0x0af9, // U+0aee : Gujarati Digit Eight
+ 0x0afa, // U+0aef : Gujarati Digit Nine
+ 0x0000, // U+0af0 : Undefined
+ 0x0000, // U+0af1 : Undefined
+ 0x0000, // U+0af2 : Undefined
+ 0x0000, // U+0af3 : Undefined
+ 0x0000, // U+0af4 : Undefined
+ 0x0000, // U+0af5 : Undefined
+ 0x0000, // U+0af6 : Undefined
+ 0x0000, // U+0af7 : Undefined
+ 0x0000, // U+0af8 : Undefined
+ 0x0000, // U+0af9 : Undefined
+ 0x0000, // U+0afa : Undefined
+ 0x0000, // U+0afb : Undefined
+ 0x0000, // U+0afc : Undefined
+ 0x0000, // U+0afd : Undefined
+ 0x0000, // U+0afe : Undefined
+ 0x0000, // U+0aff : Undefined
+ 0x0000, // U+0b00 : Undefined
+ 0x07a1, // U+0b01 : Oriya Sign Candrabindu
+ 0x07a2, // U+0b02 : Oriya Sign Anusvara
+ 0x07a3, // U+0b03 : Oriya Sign Visarga
+ 0x0000, // U+0b04 : Undefined
+ 0x07a4, // U+0b05 : Oriya Letter A
+ 0x07a5, // U+0b06 : Oriya Letter Aa
+ 0x07a6, // U+0b07 : Oriya Letter I
+ 0x07a7, // U+0b08 : Oriya Letter Ii
+ 0x07a8, // U+0b09 : Oriya Letter U
+ 0x07a9, // U+0b0a : Oriya Letter Uu
+ 0x07aa, // U+0b0b : Oriya Letter Vocalic R
+ 0x17a6, // U+0b0c : Oriya Letter Vocalic L
+ 0x0000, // U+0b0d : Undefined
+ 0x0000, // U+0b0e : Undefined
+ 0x07ab, // U+0b0f : Oriya Letter E
+ 0x07ad, // U+0b10 : Oriya Letter Ai
+ 0x0000, // U+0b11 : Undefined
+ 0x0000, // U+0b12 : Undefined
+ 0x07b0, // U+0b13 : Oriya Letter O
+ 0x07b1, // U+0b14 : Oriya Letter Au
+ 0x07b3, // U+0b15 : Oriya Letter Ka
+ 0x07b4, // U+0b16 : Oriya Letter Kha
+ 0x07b5, // U+0b17 : Oriya Letter Ga
+ 0x07b6, // U+0b18 : Oriya Letter Gha
+ 0x07b7, // U+0b19 : Oriya Letter Nga
+ 0x07b8, // U+0b1a : Oriya Letter Ca
+ 0x07b9, // U+0b1b : Oriya Letter Cha
+ 0x07ba, // U+0b1c : Oriya Letter Ja
+ 0x07bb, // U+0b1d : Oriya Letter Jha
+ 0x07bc, // U+0b1e : Oriya Letter Nya
+ 0x07bd, // U+0b1f : Oriya Letter Tta
+ 0x07be, // U+0b20 : Oriya Letter Ttha
+ 0x07bf, // U+0b21 : Oriya Letter Dda
+ 0x07c0, // U+0b22 : Oriya Letter Ddha
+ 0x07c1, // U+0b23 : Oriya Letter Nna
+ 0x07c2, // U+0b24 : Oriya Letter Ta
+ 0x07c3, // U+0b25 : Oriya Letter Tha
+ 0x07c4, // U+0b26 : Oriya Letter Da
+ 0x07c5, // U+0b27 : Oriya Letter Dha
+ 0x07c6, // U+0b28 : Oriya Letter Na
+ 0x0000, // U+0b29 : Undefined
+ 0x07c8, // U+0b2a : Oriya Letter Pa
+ 0x07c9, // U+0b2b : Oriya Letter Pha
+ 0x07ca, // U+0b2c : Oriya Letter Ba
+ 0x07cb, // U+0b2d : Oriya Letter Bha
+ 0x07cc, // U+0b2e : Oriya Letter Ma
+ 0x07cd, // U+0b2f : Oriya Letter Ya
+ 0x07cf, // U+0b30 : Oriya Letter Ra
+ 0x0000, // U+0b31 : Undefined
+ 0x07d1, // U+0b32 : Oriya Letter La
+ 0x07d2, // U+0b33 : Oriya Letter Lla
+ 0x0000, // U+0b34 : Undefined
+ 0x0000, // U+0b35 : Undefined
+ 0x07d5, // U+0b36 : Oriya Letter Sha
+ 0x07d6, // U+0b37 : Oriya Letter Ssa
+ 0x07d7, // U+0b38 : Oriya Letter Sa
+ 0x07d8, // U+0b39 : Oriya Letter Ha
+ 0x0000, // U+0b3a : Undefined
+ 0x0000, // U+0b3b : Undefined
+ 0x07e9, // U+0b3c : Oriya Sign Nukta
+ 0x17ea, // U+0b3d : Oriya Sign Avagraha
+ 0x07da, // U+0b3e : Oriya Vowel Sign Aa
+ 0x07db, // U+0b3f : Oriya Vowel Sign I
+ 0x07dc, // U+0b40 : Oriya Vowel Sign Ii
+ 0x07dd, // U+0b41 : Oriya Vowel Sign U
+ 0x07de, // U+0b42 : Oriya Vowel Sign Uu
+ 0x07df, // U+0b43 : Oriya Vowel Sign Vocalic R
+ 0x0000, // U+0b44 : Undefined
+ 0x0000, // U+0b45 : Undefined
+ 0x0000, // U+0b46 : Undefined
+ 0x07e0, // U+0b47 : Oriya Vowel Sign E
+ 0x07e2, // U+0b48 : Oriya Vowel Sign Ai
+ 0x0000, // U+0b49 : Undefined
+ 0x0000, // U+0b4a : Undefined
+ 0x07e4, // U+0b4b : Oriya Vowel Sign O
+ 0x07e6, // U+0b4c : Oriya Vowel Sign Au
+ 0x07e8, // U+0b4d : Oriya Sign Virama
+ 0x0000, // U+0b4e : Undefined
+ 0x0000, // U+0b4f : Undefined
+ 0x0000, // U+0b50 : Undefined
+ 0x0000, // U+0b51 : Undefined
+ 0x0000, // U+0b52 : Undefined
+ 0x0000, // U+0b53 : Undefined
+ 0x0000, // U+0b54 : Undefined
+ 0x0000, // U+0b55 : Undefined
+ 0x0000, // U+0b56 : Oriya Ai Length Mark
+ 0x0000, // U+0b57 : Oriya Au Length Mark
+ 0x0000, // U+0b58 : Undefined
+ 0x0000, // U+0b59 : Undefined
+ 0x0000, // U+0b5a : Undefined
+ 0x0000, // U+0b5b : Undefined
+ 0x17bf, // U+0b5c : Oriya Letter Rra
+ 0x17c0, // U+0b5d : Oriya Letter Rha
+ 0x0000, // U+0b5e : Undefined
+ 0x07ce, // U+0b5f : Oriya Letter Yya
+ 0x17aa, // U+0b60 : Oriya Letter Vocalic Rr
+ 0x17a7, // U+0b61 : Oriya Letter Vocalic Ll
+ 0x0000, // U+0b62 : Undefined
+ 0x0000, // U+0b63 : Undefined
+ 0x0000, // U+0b64 : Undefined
+ 0x0000, // U+0b65 : Undefined
+ 0x07f1, // U+0b66 : Oriya Digit Zero
+ 0x07f2, // U+0b67 : Oriya Digit One
+ 0x07f3, // U+0b68 : Oriya Digit Two
+ 0x07f4, // U+0b69 : Oriya Digit Three
+ 0x07f5, // U+0b6a : Oriya Digit Four
+ 0x07f6, // U+0b6b : Oriya Digit Five
+ 0x07f7, // U+0b6c : Oriya Digit Six
+ 0x07f8, // U+0b6d : Oriya Digit Seven
+ 0x07f9, // U+0b6e : Oriya Digit Eight
+ 0x07fa, // U+0b6f : Oriya Digit Nine
+ 0x0000, // U+0b70 : Oriya Isshar
+ 0x0000, // U+0b71 : Undefined
+ 0x0000, // U+0b72 : Undefined
+ 0x0000, // U+0b73 : Undefined
+ 0x0000, // U+0b74 : Undefined
+ 0x0000, // U+0b75 : Undefined
+ 0x0000, // U+0b76 : Undefined
+ 0x0000, // U+0b77 : Undefined
+ 0x0000, // U+0b78 : Undefined
+ 0x0000, // U+0b79 : Undefined
+ 0x0000, // U+0b7a : Undefined
+ 0x0000, // U+0b7b : Undefined
+ 0x0000, // U+0b7c : Undefined
+ 0x0000, // U+0b7d : Undefined
+ 0x0000, // U+0b7e : Undefined
+ 0x0000, // U+0b7f : Undefined
+ 0x0000, // U+0b80 : Undefined
+ 0x0000, // U+0b81 : Undefined
+ 0x04a2, // U+0b82 : Tamil Sign Anusvara
+ 0x04a3, // U+0b83 : Tamil Sign Visarga
+ 0x0000, // U+0b84 : Undefined
+ 0x04a4, // U+0b85 : Tamil Letter A
+ 0x04a5, // U+0b86 : Tamil Letter Aa
+ 0x04a6, // U+0b87 : Tamil Letter I
+ 0x04a7, // U+0b88 : Tamil Letter Ii
+ 0x04a8, // U+0b89 : Tamil Letter U
+ 0x04a9, // U+0b8a : Tamil Letter Uu
+ 0x0000, // U+0b8b : Undefined
+ 0x0000, // U+0b8c : Undefined
+ 0x0000, // U+0b8d : Undefined
+ 0x0000, // U+0b8e : Tamil Letter E
+ 0x04ab, // U+0b8f : Tamil Letter Ee
+ 0x04ad, // U+0b90 : Tamil Letter Ai
+ 0x0000, // U+0b91 : Undefined
+ 0x04af, // U+0b92 : Tamil Letter O
+ 0x04b0, // U+0b93 : Tamil Letter Oo
+ 0x04b1, // U+0b94 : Tamil Letter Au
+ 0x04b3, // U+0b95 : Tamil Letter Ka
+ 0x0000, // U+0b96 : Undefined
+ 0x0000, // U+0b97 : Undefined
+ 0x0000, // U+0b98 : Undefined
+ 0x04b7, // U+0b99 : Tamil Letter Nga
+ 0x04b8, // U+0b9a : Tamil Letter Ca
+ 0x0000, // U+0b9b : Undefined
+ 0x04ba, // U+0b9c : Tamil Letter Ja
+ 0x0000, // U+0b9d : Undefined
+ 0x04bc, // U+0b9e : Tamil Letter Nya
+ 0x04bd, // U+0b9f : Tamil Letter Tta
+ 0x0000, // U+0ba0 : Undefined
+ 0x0000, // U+0ba1 : Undefined
+ 0x0000, // U+0ba2 : Undefined
+ 0x04c1, // U+0ba3 : Tamil Letter Nna
+ 0x04c2, // U+0ba4 : Tamil Letter Ta
+ 0x0000, // U+0ba5 : Undefined
+ 0x0000, // U+0ba6 : Undefined
+ 0x0000, // U+0ba7 : Undefined
+ 0x04c6, // U+0ba8 : Tamil Letter Na
+ 0x04c7, // U+0ba9 : Tamil Letter Nnna
+ 0x04c8, // U+0baa : Tamil Letter Pa
+ 0x0000, // U+0bab : Undefined
+ 0x0000, // U+0bac : Undefined
+ 0x0000, // U+0bad : Undefined
+ 0x04cc, // U+0bae : Tamil Letter Ma
+ 0x04cd, // U+0baf : Tamil Letter Ya
+ 0x04cf, // U+0bb0 : Tamil Letter Ra
+ 0x04d0, // U+0bb1 : Tamil Letter Rra
+ 0x04d1, // U+0bb2 : Tamil Letter La
+ 0x04d2, // U+0bb3 : Tamil Letter Lla
+ 0x04d3, // U+0bb4 : Tamil Letter Llla
+ 0x04d4, // U+0bb5 : Tamil Letter Va
+ 0x0000, // U+0bb6 : Undefined
+ 0x04d5, // U+0bb7 : Tamil Letter Ssa
+ 0x04d7, // U+0bb8 : Tamil Letter Sa
+ 0x04d8, // U+0bb9 : Tamil Letter Ha
+ 0x0000, // U+0bba : Undefined
+ 0x0000, // U+0bbb : Undefined
+ 0x0000, // U+0bbc : Undefined
+ 0x0000, // U+0bbd : Undefined
+ 0x04da, // U+0bbe : Tamil Vowel Sign Aa
+ 0x04db, // U+0bbf : Tamil Vowel Sign I
+ 0x04dc, // U+0bc0 : Tamil Vowel Sign Ii
+ 0x04dd, // U+0bc1 : Tamil Vowel Sign U
+ 0x04de, // U+0bc2 : Tamil Vowel Sign Uu
+ 0x0000, // U+0bc3 : Undefined
+ 0x0000, // U+0bc4 : Undefined
+ 0x0000, // U+0bc5 : Undefined
+ 0x04e0, // U+0bc6 : Tamil Vowel Sign E
+ 0x04e1, // U+0bc7 : Tamil Vowel Sign Ee
+ 0x04e2, // U+0bc8 : Tamil Vowel Sign Ai
+ 0x0000, // U+0bc9 : Undefined
+ 0x04e4, // U+0bca : Tamil Vowel Sign O
+ 0x04e5, // U+0bcb : Tamil Vowel Sign Oo
+ 0x04e6, // U+0bcc : Tamil Vowel Sign Au
+ 0x04e8, // U+0bcd : Tamil Sign Virama
+ 0x0000, // U+0bce : Undefined
+ 0x0000, // U+0bcf : Undefined
+ 0x0000, // U+0bd0 : Undefined
+ 0x0000, // U+0bd1 : Undefined
+ 0x0000, // U+0bd2 : Undefined
+ 0x0000, // U+0bd3 : Undefined
+ 0x0000, // U+0bd4 : Undefined
+ 0x0000, // U+0bd5 : Undefined
+ 0x0000, // U+0bd6 : Undefined
+ 0x0000, // U+0bd7 : Tamil Au Length Mark
+ 0x0000, // U+0bd8 : Undefined
+ 0x0000, // U+0bd9 : Undefined
+ 0x0000, // U+0bda : Undefined
+ 0x0000, // U+0bdb : Undefined
+ 0x0000, // U+0bdc : Undefined
+ 0x0000, // U+0bdd : Undefined
+ 0x0000, // U+0bde : Undefined
+ 0x0000, // U+0bdf : Undefined
+ 0x0000, // U+0be0 : Undefined
+ 0x0000, // U+0be1 : Undefined
+ 0x0000, // U+0be2 : Undefined
+ 0x0000, // U+0be3 : Undefined
+ 0x0000, // U+0be4 : Undefined
+ 0x0000, // U+0be5 : Undefined
+ 0x0000, // U+0be6 : Undefined
+ 0x04f2, // U+0be7 : Tamil Digit One
+ 0x04f3, // U+0be8 : Tamil Digit Two
+ 0x04f4, // U+0be9 : Tamil Digit Three
+ 0x04f5, // U+0bea : Tamil Digit Four
+ 0x04f6, // U+0beb : Tamil Digit Five
+ 0x04f7, // U+0bec : Tamil Digit Six
+ 0x04f8, // U+0bed : Tamil Digit Seven
+ 0x04f9, // U+0bee : Tamil Digit Eight
+ 0x04fa, // U+0bef : Tamil Digit Nine
+ 0x0000, // U+0bf0 : Tamil Number Ten
+ 0x0000, // U+0bf1 : Tamil Number One Hundred
+ 0x0000, // U+0bf2 : Tamil Number One Thousand
+ 0x0000, // U+0bf3 : Undefined
+ 0x0000, // U+0bf4 : Undefined
+ 0x0000, // U+0bf5 : Undefined
+ 0x0000, // U+0bf6 : Undefined
+ 0x0000, // U+0bf7 : Undefined
+ 0x0000, // U+0bf8 : Undefined
+ 0x0000, // U+0bf9 : Undefined
+ 0x0000, // U+0bfa : Undefined
+ 0x0000, // U+0bfb : Undefined
+ 0x0000, // U+0bfc : Undefined
+ 0x0000, // U+0bfd : Undefined
+ 0x0000, // U+0bfe : Undefined
+ 0x0000, // U+0bff : Undefined
+ 0x0000, // U+0c00 : Undefined
+ 0x05a1, // U+0c01 : Telugu Sign Candrabindu
+ 0x05a2, // U+0c02 : Telugu Sign Anusvara
+ 0x05a3, // U+0c03 : Telugu Sign Visarga
+ 0x0000, // U+0c04 : Undefined
+ 0x05a4, // U+0c05 : Telugu Letter A
+ 0x05a5, // U+0c06 : Telugu Letter Aa
+ 0x05a6, // U+0c07 : Telugu Letter I
+ 0x05a7, // U+0c08 : Telugu Letter Ii
+ 0x05a8, // U+0c09 : Telugu Letter U
+ 0x05a9, // U+0c0a : Telugu Letter Uu
+ 0x05aa, // U+0c0b : Telugu Letter Vocalic R
+ 0x15a6, // U+0c0c : Telugu Letter Vocalic L
+ 0x0000, // U+0c0d : Undefined
+ 0x05ab, // U+0c0e : Telugu Letter E
+ 0x05ac, // U+0c0f : Telugu Letter Ee
+ 0x05ad, // U+0c10 : Telugu Letter Ai
+ 0x0000, // U+0c11 : Undefined
+ 0x05af, // U+0c12 : Telugu Letter O
+ 0x05b0, // U+0c13 : Telugu Letter Oo
+ 0x05b1, // U+0c14 : Telugu Letter Au
+ 0x05b3, // U+0c15 : Telugu Letter Ka
+ 0x05b4, // U+0c16 : Telugu Letter Kha
+ 0x05b5, // U+0c17 : Telugu Letter Ga
+ 0x05b6, // U+0c18 : Telugu Letter Gha
+ 0x05b7, // U+0c19 : Telugu Letter Nga
+ 0x05b8, // U+0c1a : Telugu Letter Ca
+ 0x05b9, // U+0c1b : Telugu Letter Cha
+ 0x05ba, // U+0c1c : Telugu Letter Ja
+ 0x05bb, // U+0c1d : Telugu Letter Jha
+ 0x05bc, // U+0c1e : Telugu Letter Nya
+ 0x05bd, // U+0c1f : Telugu Letter Tta
+ 0x05be, // U+0c20 : Telugu Letter Ttha
+ 0x05bf, // U+0c21 : Telugu Letter Dda
+ 0x05c0, // U+0c22 : Telugu Letter Ddha
+ 0x05c1, // U+0c23 : Telugu Letter Nna
+ 0x05c2, // U+0c24 : Telugu Letter Ta
+ 0x05c3, // U+0c25 : Telugu Letter Tha
+ 0x05c4, // U+0c26 : Telugu Letter Da
+ 0x05c5, // U+0c27 : Telugu Letter Dha
+ 0x05c6, // U+0c28 : Telugu Letter Na
+ 0x0000, // U+0c29 : Undefined
+ 0x05c8, // U+0c2a : Telugu Letter Pa
+ 0x05c9, // U+0c2b : Telugu Letter Pha
+ 0x05ca, // U+0c2c : Telugu Letter Ba
+ 0x05cb, // U+0c2d : Telugu Letter Bha
+ 0x05cc, // U+0c2e : Telugu Letter Ma
+ 0x05cd, // U+0c2f : Telugu Letter Ya
+ 0x05cf, // U+0c30 : Telugu Letter Ra
+ 0x05d0, // U+0c31 : Telugu Letter Rra
+ 0x05d1, // U+0c32 : Telugu Letter La
+ 0x05d2, // U+0c33 : Telugu Letter Lla
+ 0x0000, // U+0c34 : Undefined
+ 0x05d4, // U+0c35 : Telugu Letter Va
+ 0x05d5, // U+0c36 : Telugu Letter Sha
+ 0x05d6, // U+0c37 : Telugu Letter Ssa
+ 0x05d7, // U+0c38 : Telugu Letter Sa
+ 0x05d8, // U+0c39 : Telugu Letter Ha
+ 0x0000, // U+0c3a : Undefined
+ 0x0000, // U+0c3b : Undefined
+ 0x0000, // U+0c3c : Undefined
+ 0x0000, // U+0c3d : Undefined
+ 0x05da, // U+0c3e : Telugu Vowel Sign Aa
+ 0x05db, // U+0c3f : Telugu Vowel Sign I
+ 0x05dc, // U+0c40 : Telugu Vowel Sign Ii
+ 0x05dd, // U+0c41 : Telugu Vowel Sign U
+ 0x05de, // U+0c42 : Telugu Vowel Sign Uu
+ 0x05df, // U+0c43 : Telugu Vowel Sign Vocalic R
+ 0x15df, // U+0c44 : Telugu Vowel Sign Vocalic Rr
+ 0x0000, // U+0c45 : Undefined
+ 0x05e0, // U+0c46 : Telugu Vowel Sign E
+ 0x05e1, // U+0c47 : Telugu Vowel Sign Ee
+ 0x05e2, // U+0c48 : Telugu Vowel Sign Ai
+ 0x0000, // U+0c49 : Undefined
+ 0x05e4, // U+0c4a : Telugu Vowel Sign O
+ 0x05e5, // U+0c4b : Telugu Vowel Sign Oo
+ 0x05e6, // U+0c4c : Telugu Vowel Sign Au
+ 0x05e8, // U+0c4d : Telugu Sign Virama
+ 0x0000, // U+0c4e : Undefined
+ 0x0000, // U+0c4f : Undefined
+ 0x0000, // U+0c50 : Undefined
+ 0x0000, // U+0c51 : Undefined
+ 0x0000, // U+0c52 : Undefined
+ 0x0000, // U+0c53 : Undefined
+ 0x0000, // U+0c54 : Undefined
+ 0x0000, // U+0c55 : Telugu Length Mark
+ 0x0000, // U+0c56 : Telugu Ai Length Mark
+ 0x0000, // U+0c57 : Undefined
+ 0x0000, // U+0c58 : Undefined
+ 0x0000, // U+0c59 : Undefined
+ 0x0000, // U+0c5a : Undefined
+ 0x0000, // U+0c5b : Undefined
+ 0x0000, // U+0c5c : Undefined
+ 0x0000, // U+0c5d : Undefined
+ 0x0000, // U+0c5e : Undefined
+ 0x0000, // U+0c5f : Undefined
+ 0x15aa, // U+0c60 : Telugu Letter Vocalic Rr
+ 0x15a7, // U+0c61 : Telugu Letter Vocalic Ll
+ 0x0000, // U+0c62 : Undefined
+ 0x0000, // U+0c63 : Undefined
+ 0x0000, // U+0c64 : Undefined
+ 0x0000, // U+0c65 : Undefined
+ 0x05f1, // U+0c66 : Telugu Digit Zero
+ 0x05f2, // U+0c67 : Telugu Digit One
+ 0x05f3, // U+0c68 : Telugu Digit Two
+ 0x05f4, // U+0c69 : Telugu Digit Three
+ 0x05f5, // U+0c6a : Telugu Digit Four
+ 0x05f6, // U+0c6b : Telugu Digit Five
+ 0x05f7, // U+0c6c : Telugu Digit Six
+ 0x05f8, // U+0c6d : Telugu Digit Seven
+ 0x05f9, // U+0c6e : Telugu Digit Eight
+ 0x05fa, // U+0c6f : Telugu Digit Nine
+ 0x0000, // U+0c70 : Undefined
+ 0x0000, // U+0c71 : Undefined
+ 0x0000, // U+0c72 : Undefined
+ 0x0000, // U+0c73 : Undefined
+ 0x0000, // U+0c74 : Undefined
+ 0x0000, // U+0c75 : Undefined
+ 0x0000, // U+0c76 : Undefined
+ 0x0000, // U+0c77 : Undefined
+ 0x0000, // U+0c78 : Undefined
+ 0x0000, // U+0c79 : Undefined
+ 0x0000, // U+0c7a : Undefined
+ 0x0000, // U+0c7b : Undefined
+ 0x0000, // U+0c7c : Undefined
+ 0x0000, // U+0c7d : Undefined
+ 0x0000, // U+0c7e : Undefined
+ 0x0000, // U+0c7f : Undefined
+ 0x0000, // U+0c80 : Undefined
+ 0x0000, // U+0c81 : Undefined
+ 0x08a2, // U+0c82 : Kannada Sign Anusvara
+ 0x08a3, // U+0c83 : Kannada Sign Visarga
+ 0x0000, // U+0c84 : Undefined
+ 0x08a4, // U+0c85 : Kannada Letter A
+ 0x08a5, // U+0c86 : Kannada Letter Aa
+ 0x08a6, // U+0c87 : Kannada Letter I
+ 0x08a7, // U+0c88 : Kannada Letter Ii
+ 0x08a8, // U+0c89 : Kannada Letter U
+ 0x08a9, // U+0c8a : Kannada Letter Uu
+ 0x08aa, // U+0c8b : Kannada Letter Vocalic R
+ 0x18a6, // U+0c8c : Kannada Letter Vocalic L
+ 0x0000, // U+0c8d : Undefined
+ 0x08ab, // U+0c8e : Kannada Letter E
+ 0x08ac, // U+0c8f : Kannada Letter Ee
+ 0x08ad, // U+0c90 : Kannada Letter Ai
+ 0x0000, // U+0c91 : Undefined
+ 0x08af, // U+0c92 : Kannada Letter O
+ 0x08b0, // U+0c93 : Kannada Letter Oo
+ 0x08b1, // U+0c94 : Kannada Letter Au
+ 0x08b3, // U+0c95 : Kannada Letter Ka
+ 0x08b4, // U+0c96 : Kannada Letter Kha
+ 0x08b5, // U+0c97 : Kannada Letter Ga
+ 0x08b6, // U+0c98 : Kannada Letter Gha
+ 0x08b7, // U+0c99 : Kannada Letter Nga
+ 0x08b8, // U+0c9a : Kannada Letter Ca
+ 0x08b9, // U+0c9b : Kannada Letter Cha
+ 0x08ba, // U+0c9c : Kannada Letter Ja
+ 0x08bb, // U+0c9d : Kannada Letter Jha
+ 0x08bc, // U+0c9e : Kannada Letter Nya
+ 0x08bd, // U+0c9f : Kannada Letter Tta
+ 0x08be, // U+0ca0 : Kannada Letter Ttha
+ 0x08bf, // U+0ca1 : Kannada Letter Dda
+ 0x08c0, // U+0ca2 : Kannada Letter Ddha
+ 0x08c1, // U+0ca3 : Kannada Letter Nna
+ 0x08c2, // U+0ca4 : Kannada Letter Ta
+ 0x08c3, // U+0ca5 : Kannada Letter Tha
+ 0x08c4, // U+0ca6 : Kannada Letter Da
+ 0x08c5, // U+0ca7 : Kannada Letter Dha
+ 0x08c6, // U+0ca8 : Kannada Letter Na
+ 0x0000, // U+0ca9 : Undefined
+ 0x08c8, // U+0caa : Kannada Letter Pa
+ 0x08c9, // U+0cab : Kannada Letter Pha
+ 0x08ca, // U+0cac : Kannada Letter Ba
+ 0x08cb, // U+0cad : Kannada Letter Bha
+ 0x08cc, // U+0cae : Kannada Letter Ma
+ 0x08cd, // U+0caf : Kannada Letter Ya
+ 0x08cf, // U+0cb0 : Kannada Letter Ra
+ 0x08d0, // U+0cb1 : Kannada Letter Rra
+ 0x08d1, // U+0cb2 : Kannada Letter La
+ 0x08d2, // U+0cb3 : Kannada Letter Lla
+ 0x0000, // U+0cb4 : Undefined
+ 0x08d4, // U+0cb5 : Kannada Letter Va
+ 0x08d5, // U+0cb6 : Kannada Letter Sha
+ 0x08d6, // U+0cb7 : Kannada Letter Ssa
+ 0x08d7, // U+0cb8 : Kannada Letter Sa
+ 0x08d8, // U+0cb9 : Kannada Letter Ha
+ 0x0000, // U+0cba : Undefined
+ 0x0000, // U+0cbb : Undefined
+ 0x0000, // U+0cbc : Undefined
+ 0x0000, // U+0cbd : Undefined
+ 0x08da, // U+0cbe : Kannada Vowel Sign Aa
+ 0x08db, // U+0cbf : Kannada Vowel Sign I
+ 0x08dc, // U+0cc0 : Kannada Vowel Sign Ii
+ 0x08dd, // U+0cc1 : Kannada Vowel Sign U
+ 0x08de, // U+0cc2 : Kannada Vowel Sign Uu
+ 0x08df, // U+0cc3 : Kannada Vowel Sign Vocalic R
+ 0x18df, // U+0cc4 : Kannada Vowel Sign Vocalic Rr
+ 0x0000, // U+0cc5 : Undefined
+ 0x08e0, // U+0cc6 : Kannada Vowel Sign E
+ 0x08e1, // U+0cc7 : Kannada Vowel Sign Ee
+ 0x08e2, // U+0cc8 : Kannada Vowel Sign Ai
+ 0x0000, // U+0cc9 : Undefined
+ 0x08e4, // U+0cca : Kannada Vowel Sign O
+ 0x08e5, // U+0ccb : Kannada Vowel Sign Oo
+ 0x08e6, // U+0ccc : Kannada Vowel Sign Au
+ 0x08e8, // U+0ccd : Kannada Sign Virama
+ 0x0000, // U+0cce : Undefined
+ 0x0000, // U+0ccf : Undefined
+ 0x0000, // U+0cd0 : Undefined
+ 0x0000, // U+0cd1 : Undefined
+ 0x0000, // U+0cd2 : Undefined
+ 0x0000, // U+0cd3 : Undefined
+ 0x0000, // U+0cd4 : Undefined
+ 0x0000, // U+0cd5 : Kannada Length Mark
+ 0x0000, // U+0cd6 : Kannada Ai Length Mark
+ 0x0000, // U+0cd7 : Undefined
+ 0x0000, // U+0cd8 : Undefined
+ 0x0000, // U+0cd9 : Undefined
+ 0x0000, // U+0cda : Undefined
+ 0x0000, // U+0cdb : Undefined
+ 0x0000, // U+0cdc : Undefined
+ 0x0000, // U+0cdd : Undefined
+ 0x18c9, // U+0cde : Kannada Letter Fa
+ 0x0000, // U+0cdf : Undefined
+ 0x18aa, // U+0ce0 : Kannada Letter Vocalic Rr
+ 0x18a7, // U+0ce1 : Kannada Letter Vocalic Ll
+ 0x0000, // U+0ce2 : Undefined
+ 0x0000, // U+0ce3 : Undefined
+ 0x0000, // U+0ce4 : Undefined
+ 0x0000, // U+0ce5 : Undefined
+ 0x08f1, // U+0ce6 : Kannada Digit Zero
+ 0x08f2, // U+0ce7 : Kannada Digit One
+ 0x08f3, // U+0ce8 : Kannada Digit Two
+ 0x08f4, // U+0ce9 : Kannada Digit Three
+ 0x08f5, // U+0cea : Kannada Digit Four
+ 0x08f6, // U+0ceb : Kannada Digit Five
+ 0x08f7, // U+0cec : Kannada Digit Six
+ 0x08f8, // U+0ced : Kannada Digit Seven
+ 0x08f9, // U+0cee : Kannada Digit Eight
+ 0x08fa, // U+0cef : Kannada Digit Nine
+ 0x0000, // U+0cf0 : Undefined
+ 0x0000, // U+0cf1 : Undefined
+ 0x0000, // U+0cf2 : Undefined
+ 0x0000, // U+0cf3 : Undefined
+ 0x0000, // U+0cf4 : Undefined
+ 0x0000, // U+0cf5 : Undefined
+ 0x0000, // U+0cf6 : Undefined
+ 0x0000, // U+0cf7 : Undefined
+ 0x0000, // U+0cf8 : Undefined
+ 0x0000, // U+0cf9 : Undefined
+ 0x0000, // U+0cfa : Undefined
+ 0x0000, // U+0cfb : Undefined
+ 0x0000, // U+0cfc : Undefined
+ 0x0000, // U+0cfd : Undefined
+ 0x0000, // U+0cfe : Undefined
+ 0x0000, // U+0cff : Undefined
+ 0x0000, // U+0d00 : Undefined
+ 0x0000, // U+0d01 : Undefined
+ 0x09a2, // U+0d02 : Malayalam Sign Anusvara
+ 0x09a3, // U+0d03 : Malayalam Sign Visarga
+ 0x0000, // U+0d04 : Undefined
+ 0x09a4, // U+0d05 : Malayalam Letter A
+ 0x09a5, // U+0d06 : Malayalam Letter Aa
+ 0x09a6, // U+0d07 : Malayalam Letter I
+ 0x09a7, // U+0d08 : Malayalam Letter Ii
+ 0x09a8, // U+0d09 : Malayalam Letter U
+ 0x09a9, // U+0d0a : Malayalam Letter Uu
+ 0x09aa, // U+0d0b : Malayalam Letter Vocalic R
+ 0x19a6, // U+0d0c : Malayalam Letter Vocalic L
+ 0x0000, // U+0d0d : Undefined
+ 0x09ab, // U+0d0e : Malayalam Letter E
+ 0x09ac, // U+0d0f : Malayalam Letter Ee
+ 0x09ad, // U+0d10 : Malayalam Letter Ai
+ 0x0000, // U+0d11 : Undefined
+ 0x09af, // U+0d12 : Malayalam Letter O
+ 0x09b0, // U+0d13 : Malayalam Letter Oo
+ 0x09b1, // U+0d14 : Malayalam Letter Au
+ 0x09b3, // U+0d15 : Malayalam Letter Ka
+ 0x09b4, // U+0d16 : Malayalam Letter Kha
+ 0x09b5, // U+0d17 : Malayalam Letter Ga
+ 0x09b6, // U+0d18 : Malayalam Letter Gha
+ 0x09b7, // U+0d19 : Malayalam Letter Nga
+ 0x09b8, // U+0d1a : Malayalam Letter Ca
+ 0x09b9, // U+0d1b : Malayalam Letter Cha
+ 0x09ba, // U+0d1c : Malayalam Letter Ja
+ 0x09bb, // U+0d1d : Malayalam Letter Jha
+ 0x09bc, // U+0d1e : Malayalam Letter Nya
+ 0x09bd, // U+0d1f : Malayalam Letter Tta
+ 0x09be, // U+0d20 : Malayalam Letter Ttha
+ 0x09bf, // U+0d21 : Malayalam Letter Dda
+ 0x09c0, // U+0d22 : Malayalam Letter Ddha
+ 0x09c1, // U+0d23 : Malayalam Letter Nna
+ 0x09c2, // U+0d24 : Malayalam Letter Ta
+ 0x09c3, // U+0d25 : Malayalam Letter Tha
+ 0x09c4, // U+0d26 : Malayalam Letter Da
+ 0x09c5, // U+0d27 : Malayalam Letter Dha
+ 0x09c6, // U+0d28 : Malayalam Letter Na
+ 0x0000, // U+0d29 : Undefined
+ 0x09c8, // U+0d2a : Malayalam Letter Pa
+ 0x09c9, // U+0d2b : Malayalam Letter Pha
+ 0x09ca, // U+0d2c : Malayalam Letter Ba
+ 0x09cb, // U+0d2d : Malayalam Letter Bha
+ 0x09cc, // U+0d2e : Malayalam Letter Ma
+ 0x09cd, // U+0d2f : Malayalam Letter Ya
+ 0x09cf, // U+0d30 : Malayalam Letter Ra
+ 0x09d0, // U+0d31 : Malayalam Letter Rra
+ 0x09d1, // U+0d32 : Malayalam Letter La
+ 0x09d2, // U+0d33 : Malayalam Letter Lla
+ 0x09d3, // U+0d34 : Malayalam Letter Llla
+ 0x09d4, // U+0d35 : Malayalam Letter Va
+ 0x09d5, // U+0d36 : Malayalam Letter Sha
+ 0x09d6, // U+0d37 : Malayalam Letter Ssa
+ 0x09d7, // U+0d38 : Malayalam Letter Sa
+ 0x09d8, // U+0d39 : Malayalam Letter Ha
+ 0x0000, // U+0d3a : Undefined
+ 0x0000, // U+0d3b : Undefined
+ 0x0000, // U+0d3c : Undefined
+ 0x0000, // U+0d3d : Undefined
+ 0x09da, // U+0d3e : Malayalam Vowel Sign Aa
+ 0x09db, // U+0d3f : Malayalam Vowel Sign I
+ 0x09dc, // U+0d40 : Malayalam Vowel Sign Ii
+ 0x09dd, // U+0d41 : Malayalam Vowel Sign U
+ 0x09de, // U+0d42 : Malayalam Vowel Sign Uu
+ 0x09df, // U+0d43 : Malayalam Vowel Sign Vocalic R
+ 0x0000, // U+0d44 : Undefined
+ 0x0000, // U+0d45 : Undefined
+ 0x09e0, // U+0d46 : Malayalam Vowel Sign E
+ 0x09e1, // U+0d47 : Malayalam Vowel Sign Ee
+ 0x09e2, // U+0d48 : Malayalam Vowel Sign Ai
+ 0x0000, // U+0d49 : Undefined
+ 0x09e4, // U+0d4a : Malayalam Vowel Sign O
+ 0x09e5, // U+0d4b : Malayalam Vowel Sign Oo
+ 0x09e6, // U+0d4c : Malayalam Vowel Sign Au
+ 0x09e8, // U+0d4d : Malayalam Sign Virama
+ 0x0000, // U+0d4e : Undefined
+ 0x0000, // U+0d4f : Undefined
+ 0x0000, // U+0d50 : Undefined
+ 0x0000, // U+0d51 : Undefined
+ 0x0000, // U+0d52 : Undefined
+ 0x0000, // U+0d53 : Undefined
+ 0x0000, // U+0d54 : Undefined
+ 0x0000, // U+0d55 : Undefined
+ 0x0000, // U+0d56 : Undefined
+ 0x0000, // U+0d57 : Malayalam Au Length Mark
+ 0x0000, // U+0d58 : Undefined
+ 0x0000, // U+0d59 : Undefined
+ 0x0000, // U+0d5a : Undefined
+ 0x0000, // U+0d5b : Undefined
+ 0x0000, // U+0d5c : Undefined
+ 0x0000, // U+0d5d : Undefined
+ 0x0000, // U+0d5e : Undefined
+ 0x0000, // U+0d5f : Undefined
+ 0x19aa, // U+0d60 : Malayalam Letter Vocalic Rr
+ 0x19a7, // U+0d61 : Malayalam Letter Vocalic Ll
+ 0x0000, // U+0d62 : Undefined
+ 0x0000, // U+0d63 : Undefined
+ 0x0000, // U+0d64 : Undefined
+ 0x0000, // U+0d65 : Undefined
+ 0x09f1, // U+0d66 : Malayalam Digit Zero
+ 0x09f2, // U+0d67 : Malayalam Digit One
+ 0x09f3, // U+0d68 : Malayalam Digit Two
+ 0x09f4, // U+0d69 : Malayalam Digit Three
+ 0x09f5, // U+0d6a : Malayalam Digit Four
+ 0x09f6, // U+0d6b : Malayalam Digit Five
+ 0x09f7, // U+0d6c : Malayalam Digit Six
+ 0x09f8, // U+0d6d : Malayalam Digit Seven
+ 0x09f9, // U+0d6e : Malayalam Digit Eight
+ 0x09fa // U+0d6f : Malayalam Digit Nine
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // SecondIndicByte
+ //
+ // This is used if the UnicodeToIndic table 4 high bits are set, this is
+ // the value of the second Indic byte when applicable.
+ ////////////////////////////////////////////////////////////////////////////
+ static byte[] SecondIndicByte =
+ {
+ 0x00,
+ 0xe9,
+ 0xb8, // U+0952 == 0xf0_0xb8
+ 0xbf // U+0970 == 0xf0_0xbf
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // IndicMapping
+ //
+ // This table maps the 10 indic code pages to their unicode counterparts.
+ // There are 0x60 characters in each table. The tables are in pairs of 2
+ // (1st char, 2nd char) and there are 10 tables (1 for each code page "font")
+ ////////////////////////////////////////////////////////////////////////////
+ static int[] IndicMappingIndex =
+ {
+ -1, // 0 DEF 0X40 Default // Not a real code page
+ -1, // 1 RMN 0X41 Roman // Transliteration not supported
+ 0, // 2 DEV 0X42 Devanagari
+ 1, // 3 BNG 0X43 Bengali
+ 2, // 4 TML 0X44 Tamil
+ 3, // 5 TLG 0X45 Telugu
+ 1, // 6 ASM 0X46 Assamese (Bengali) - Reuses table 1
+ 4, // 7 ORI 0X47 Oriya
+ 5, // 8 KND 0X48 Kannada
+ 6, // 9 MLM 0X49 Malayalam
+ 7, // 10 GJR 0X4A Gujarati
+ 8 // 11 PNJ 0X4B Punjabi (Gurmukhi)
+ };
+
+ ////////////////////////////////////////////////////////////////////////////
+ // IndicMapping
+ //
+ // This table contains 9 tables for the 10 indic code pages to their unicode counterparts.
+ // There are 0x60 characters in each table. The tables are in pairs of 2
+ // (1st char, 2nd char) and there are 10 tables (1 for each code page "font")
+ //
+ // The first index is the table index (from the IndicMappingIndex table),
+ // the 2nd the byte index, the third the character index.
+ //
+ // For byte 0 a 0x0000 value indicates an unknown character
+ // For byte 1 a 0 value indicates no special attributes.
+ // For byte 1, 200C & 200D are Virama, Nukta special cases
+ // For byte 1, B8BF is Devanagari stress & abbreviation sign special cases
+ //
+ // WARNING: When copying these from windows, ? 0x003F were changed to 0x0000.
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ // char[codePageMapIndex][byte][character]
+ static char[,,] IndicMapping =
+ {
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Devanagari Table 0, Code Page (2, 0x42, 57002)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0901', '\x0902', '\x0903', '\x0905', '\x0906', '\x0907', '\x0908',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0909', '\x090a', '\x090b', '\x090e', '\x090f', '\x0910', '\x090d', '\x0912',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0913', '\x0914', '\x0911', '\x0915', '\x0916', '\x0917', '\x0918', '\x0919',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x091a', '\x091b', '\x091c', '\x091d', '\x091e', '\x091f', '\x0920', '\x0921',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0922', '\x0923', '\x0924', '\x0925', '\x0926', '\x0927', '\x0928', '\x0929',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x092a', '\x092b', '\x092c', '\x092d', '\x092e', '\x092f', '\x095f', '\x0930',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0931', '\x0932', '\x0933', '\x0934', '\x0935', '\x0936', '\x0937', '\x0938',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0939', '\x0000', '\x093e', '\x093f', '\x0940', '\x0941', '\x0942', '\x0943',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0946', '\x0947', '\x0948', '\x0945', '\x094a', '\x094b', '\x094c', '\x0949',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x094d', '\x093c', '\x0964', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0966', '\x0967', '\x0968', '\x0969', '\x096a', '\x096b', '\x096c',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x096d', '\x096e', '\x096f', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0950', '\x0', '\x0', '\x0', '\x0', '\x090c', '\x0961',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0960', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0958', '\x0959', '\x095a', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x095b', '\x0', '\x0', '\x0', '\x0', '\x095c',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x095d', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x095e', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0962', '\x0963', '\x0', '\x0', '\x0944',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x093d', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\xB8BF', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Bengali & Assemese Table 1', Code Pages (3, '43', 57003 & 6', '46', 57006)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0981', '\x0982', '\x0983', '\x0985', '\x0986', '\x0987', '\x0988',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0989', '\x098a', '\x098b', '\x098f', '\x098f', '\x0990', '\x0990', '\x0993',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0993', '\x0994', '\x0994', '\x0995', '\x0996', '\x0997', '\x0998', '\x0999',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x099a', '\x099b', '\x099c', '\x099d', '\x099e', '\x099f', '\x09a0', '\x09a1',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x09a2', '\x09a3', '\x09a4', '\x09a5', '\x09a6', '\x09a7', '\x09a8', '\x09a8',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x09aa', '\x09ab', '\x09ac', '\x09ad', '\x09ae', '\x09af', '\x09df', '\x09b0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x09b0', '\x09b2', '\x09b2', '\x09b2', '\x09ac', '\x09b6', '\x09b7', '\x09b8',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x09b9', '\x0000', '\x09be', '\x09bf', '\x09c0', '\x09c1', '\x09c2', '\x09c3',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x09c7', '\x09c7', '\x09c8', '\x09c8', '\x09cb', '\x09cb', '\x09cc', '\x09cc',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x09cd', '\x09bc', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x09e6', '\x09e7', '\x09e8', '\x09e9', '\x09ea', '\x09eb', '\x09ec',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x09ed', '\x09ee', '\x09ef', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x098c', '\x09e1',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x09e0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x09dc',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x09dd', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x09e2', '\x09e3', '\x0', '\x0', '\x09c4',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Tamil Table 2', Code Page (4, '44', 57004)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0000', '\x0b82', '\x0b83', '\x0b85', '\x0b86', '\x0b87', '\x0b88',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0b89', '\x0b8a', '\x0000', '\x0b8f', '\x0b8f', '\x0b90', '\x0b90', '\x0b92',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0b93', '\x0b94', '\x0b94', '\x0b95', '\x0b95', '\x0b95', '\x0b95', '\x0b99',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0b9a', '\x0b9a', '\x0b9c', '\x0b9c', '\x0b9e', '\x0b9f', '\x0b9f', '\x0b9f',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0b9f', '\x0ba3', '\x0ba4', '\x0ba4', '\x0ba4', '\x0ba4', '\x0ba8', '\x0ba9',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0baa', '\x0baa', '\x0baa', '\x0baa', '\x0bae', '\x0baf', '\x0baf', '\x0bb0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0bb1', '\x0bb2', '\x0bb3', '\x0bb4', '\x0bb5', '\x0bb7', '\x0bb7', '\x0bb8',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0bb9', '\x0000', '\x0bbe', '\x0bbf', '\x0bc0', '\x0bc1', '\x0bc2', '\x0000',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0bc6', '\x0bc7', '\x0bc8', '\x0bc8', '\x0bca', '\x0bcb', '\x0bcc', '\x0bcc',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0bcd', '\x0000', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0030', '\x0be7', '\x0be8', '\x0be9', '\x0bea', '\x0beb', '\x0bec',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0bed', '\x0bee', '\x0bef', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Telugu Table 3', Code Page (5, '45', 57005)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0c01', '\x0c02', '\x0c03', '\x0c05', '\x0c06', '\x0c07', '\x0c08',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0c09', '\x0c0a', '\x0c0b', '\x0c0e', '\x0c0f', '\x0c10', '\x0c10', '\x0c12',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0c13', '\x0c14', '\x0c14', '\x0c15', '\x0c16', '\x0c17', '\x0c18', '\x0c19',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0c1a', '\x0c1b', '\x0c1c', '\x0c1d', '\x0c1e', '\x0c1f', '\x0c20', '\x0c21',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0c22', '\x0c23', '\x0c24', '\x0c25', '\x0c26', '\x0c27', '\x0c28', '\x0c28',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0c2a', '\x0c2b', '\x0c2c', '\x0c2d', '\x0c2e', '\x0c2f', '\x0c2f', '\x0c30',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0c31', '\x0c32', '\x0c33', '\x0c33', '\x0c35', '\x0c36', '\x0c37', '\x0c38',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0c39', '\x0000', '\x0c3e', '\x0c3f', '\x0c40', '\x0c41', '\x0c42', '\x0c43',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0c46', '\x0c47', '\x0c48', '\x0c48', '\x0c4a', '\x0c4b', '\x0c4c', '\x0c4c',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0c4d', '\x0000', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0c66', '\x0c67', '\x0c68', '\x0c69', '\x0c6a', '\x0c6b', '\x0c6c',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0c6d', '\x0c6e', '\x0c6f', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0c0c', '\x0c61',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0c60', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0c44',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Oriya Table 4', Code Page (7, '47', 57007)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0b01', '\x0b02', '\x0b03', '\x0b05', '\x0b06', '\x0b07', '\x0b08',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0b09', '\x0b0a', '\x0b0b', '\x0b0f', '\x0b0f', '\x0b10', '\x0b10', '\x0b10',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0b13', '\x0b14', '\x0b14', '\x0b15', '\x0b16', '\x0b17', '\x0b18', '\x0b19',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0b1a', '\x0b1b', '\x0b1c', '\x0b1d', '\x0b1e', '\x0b1f', '\x0b20', '\x0b21',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0b22', '\x0b23', '\x0b24', '\x0b25', '\x0b26', '\x0b27', '\x0b28', '\x0b28',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0b2a', '\x0b2b', '\x0b2c', '\x0b2d', '\x0b2e', '\x0b2f', '\x0b5f', '\x0b30',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0b30', '\x0b32', '\x0b33', '\x0b33', '\x0b2c', '\x0b36', '\x0b37', '\x0b38',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0b39', '\x0000', '\x0b3e', '\x0b3f', '\x0b40', '\x0b41', '\x0b42', '\x0b43',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0b47', '\x0b47', '\x0b48', '\x0b48', '\x0b4b', '\x0b4b', '\x0b4c', '\x0b4c',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0b4d', '\x0b3c', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0b66', '\x0b67', '\x0b68', '\x0b69', '\x0b6a', '\x0b6b', '\x0b6c',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0b6d', '\x0b6e', '\x0b6f', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0c0c', '\x0c61',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0c60', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0b5c',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0b5d', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0c44',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0b3d', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Kannada Table 5', Code Page (8, '48', 57008)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0000', '\x0c82', '\x0c83', '\x0c85', '\x0c86', '\x0c87', '\x0c88',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0c89', '\x0c8a', '\x0c8b', '\x0c8e', '\x0c8f', '\x0c90', '\x0c90', '\x0c92',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0c93', '\x0c94', '\x0c94', '\x0c95', '\x0c96', '\x0c97', '\x0c98', '\x0c99',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0c9a', '\x0c9b', '\x0c9c', '\x0c9d', '\x0c9e', '\x0c9f', '\x0ca0', '\x0ca1',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0ca2', '\x0ca3', '\x0ca4', '\x0ca5', '\x0ca6', '\x0ca7', '\x0ca8', '\x0ca8',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0caa', '\x0cab', '\x0cac', '\x0cad', '\x0cae', '\x0caf', '\x0caf', '\x0cb0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0cb1', '\x0cb2', '\x0cb3', '\x0cb3', '\x0cb5', '\x0cb6', '\x0cb7', '\x0cb8',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0cb9', '\x0000', '\x0cbe', '\x0cbf', '\x0cc0', '\x0cc1', '\x0cc2', '\x0cc3',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0cc6', '\x0cc7', '\x0cc8', '\x0cc8', '\x0cca', '\x0ccb', '\x0ccc', '\x0ccc',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0ccd', '\x0000', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0ce6', '\x0ce7', '\x0ce8', '\x0ce9', '\x0cea', '\x0ceb', '\x0cec',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0ced', '\x0cee', '\x0cef', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0c8c', '\x0ce1',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0ce0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0cde', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0cc4',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Malayalam Table 6', Code Page (9, '49', 57009)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0000', '\x0d02', '\x0d03', '\x0d05', '\x0d06', '\x0d07', '\x0d08',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0d09', '\x0d0a', '\x0d0b', '\x0d0e', '\x0d0f', '\x0d10', '\x0d10', '\x0d12',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0d13', '\x0d14', '\x0d14', '\x0d15', '\x0d16', '\x0d17', '\x0d18', '\x0d19',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0d1a', '\x0d1b', '\x0d1c', '\x0d1d', '\x0d1e', '\x0d1f', '\x0d20', '\x0d21',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0d22', '\x0d23', '\x0d24', '\x0d25', '\x0d26', '\x0d27', '\x0d28', '\x0d28',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0d2a', '\x0d2b', '\x0d2c', '\x0d2d', '\x0d2e', '\x0d2f', '\x0d2f', '\x0d30',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0d31', '\x0d32', '\x0d33', '\x0d34', '\x0d35', '\x0d36', '\x0d37', '\x0d38',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0d39', '\x0000', '\x0d3e', '\x0d3f', '\x0d40', '\x0d41', '\x0d42', '\x0d43',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0d46', '\x0d47', '\x0d48', '\x0d48', '\x0d4a', '\x0d4b', '\x0d4c', '\x0d4c',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0d4d', '\x0000', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0d66', '\x0d67', '\x0d68', '\x0d69', '\x0d6a', '\x0d6b', '\x0d6c',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0d6d', '\x0d6e', '\x0d6f', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0d0c', '\x0d61',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0d60', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Gujarati Table 7', Code Page (10', '4a', 57010)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0a81', '\x0a82', '\x0a83', '\x0a85', '\x0a86', '\x0a87', '\x0a88',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0a89', '\x0a8a', '\x0a8b', '\x0a8f', '\x0a8f', '\x0a90', '\x0a8d', '\x0a8d',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0a93', '\x0a94', '\x0a91', '\x0a95', '\x0a96', '\x0a97', '\x0a98', '\x0a99',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0a9a', '\x0a9b', '\x0a9c', '\x0a9d', '\x0a9e', '\x0a9f', '\x0aa0', '\x0aa1',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0aa2', '\x0aa3', '\x0aa4', '\x0aa5', '\x0aa6', '\x0aa7', '\x0aa8', '\x0aa8',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0aaa', '\x0aab', '\x0aac', '\x0aad', '\x0aae', '\x0aaf', '\x0aaf', '\x0ab0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0ab0', '\x0ab2', '\x0ab3', '\x0ab3', '\x0ab5', '\x0ab6', '\x0ab7', '\x0ab8',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0ab9', '\x0000', '\x0abe', '\x0abf', '\x0ac0', '\x0ac1', '\x0ac2', '\x0ac3',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0ac7', '\x0ac7', '\x0ac8', '\x0ac5', '\x0acb', '\x0acb', '\x0acc', '\x0ac9',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0acd', '\x0abc', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0ae6', '\x0ae7', '\x0ae8', '\x0ae9', '\x0aea', '\x0aeb', '\x0aec',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0aed', '\x0aee', '\x0aef', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0ad0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0ae0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0ac4',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0abd', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ },
+
+ {
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Punjabi (Gurmukhi) Table 8', Code Page (11', '4b', 57011)
+ //
+ ////////////////////////////////////////////////////////////////////////////
+
+ // Default Unicode Char
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0000', '\x0000', '\x0a02', '\x0000', '\x0a05', '\x0a06', '\x0a07', '\x0a08',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0a09', '\x0a0a', '\x0000', '\x0a0f', '\x0a0f', '\x0a10', '\x0a10', '\x0a10',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0a13', '\x0a14', '\x0a14', '\x0a15', '\x0a16', '\x0a17', '\x0a18', '\x0a19',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0a1a', '\x0a1b', '\x0a1c', '\x0a1d', '\x0a1e', '\x0a1f', '\x0a20', '\x0a21',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0a22', '\x0a23', '\x0a24', '\x0a25', '\x0a26', '\x0a27', '\x0a28', '\x0a28',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0a2a', '\x0a2b', '\x0a2c', '\x0a2d', '\x0a2e', '\x0a2f', '\x0a2f', '\x0a30',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0a30', '\x0a32', '\x0a33', '\x0a33', '\x0a35', '\x0a36', '\x0a36', '\x0a38',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0a39', '\x0000', '\x0a3e', '\x0a3f', '\x0a40', '\x0a41', '\x0a42', '\x0000',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0a47', '\x0a47', '\x0a48', '\x0a48', '\x0a4b', '\x0a4b', '\x0a4c', '\x0a4c',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x0a4d', '\x0a3c', '\x002e', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0000', '\x0a66', '\x0a67', '\x0a68', '\x0a69', '\x0a6a', '\x0a6b', '\x0a6c',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0a6d', '\x0a6e', '\x0a6f', '\x0000', '\x0000', '\x0000', '\x0000', '\x0000'
+ },
+
+ // Alternate Unicode Char & Flags
+ {
+ // a0, a1, a2, a3, a4, a5, a6, a7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // a8, a9, aa, ab, ac, ad, ae, af,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // b0, b1, b2, b3, b4, b5, b6, b7,
+ '\x0', '\x0', '\x0', '\x0', '\x0a59', '\x0a5a', '\x0', '\x0',
+ // b8, b9, ba, bb, bc, bd, be, bf,
+ '\x0', '\x0', '\x0a5b', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c0, c1, c2, c3, c4, c5, c6, c7,
+ '\x0a5c', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // c8, c9, ca, cb, cc, cd, ce, cf,
+ '\x0', '\x0a5e', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d0, d1, d2, d3, d4, d5, d6, d7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // d8, d9, da, db, dc, dd, de, df,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e0, e1, e2, e3, e4, e5, e6, e7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // e8, e9, ea, eb, ec, ed, ee, ef,
+ '\x200C', '\x200D', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f0, f1, f2, f3, f4, f5, f6, f7,
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0',
+ // f8, f9, fa, fb, fc, fd, fe, ff
+ '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0', '\x0'
+ }
+ }
+ };
+ }
+
+}
diff --git a/src/mscorlib/src/System/Text/ISO2022Encoding.cs b/src/mscorlib/src/System/Text/ISO2022Encoding.cs
new file mode 100644
index 0000000000..fe57e7cc57
--- /dev/null
+++ b/src/mscorlib/src/System/Text/ISO2022Encoding.cs
@@ -0,0 +1,1995 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//
+//
+// Notes:
+//
+// IsAlwaysNormalized ???
+// Regarding Normalization for ISO-2022-JP (50220, 50221, 50222), its the same rules as EUCJP
+// Forms KC & KD are precluded because of things like halfwidth Katakana that has compatibility mappings
+// Form D is precluded because of 0x00a8, which changes to space + dierises.
+//
+// Note: I think that IsAlwaysNormalized should probably return true for form C for Japanese 20932 based CPs.
+//
+// For ISO-2022-KR
+// Never normalized, C & D (& therefore KC & KD) are precluded because of Hangul syllables and combined characters.
+//
+// IsAlwaysNormalized ???
+// Regarding Normalization for ISO-2022-CN (50227, 50229) & HZ-GB2312 (52936) I think is similar to the Japanese case.
+// Forms KC & KD are precluded because of things like halfwidth Katakana that has compatibility mappings
+// Form D is precluded because of 0x00a8, which changes to space + dierises.
+//
+// Note: I think that IsAlwaysNormalized should probably return true for form C for Chinese 20936 based CPs.
+//
+#if FEATURE_CODEPAGES_FILE // requires BaseCodePageEncooding
+namespace System.Text
+{
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using System.Runtime.InteropServices;
+ using System;
+ using System.Security;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+
+
+ /*=================================ISO2022Encoding============================
+ **
+ ** This is used to support ISO 2022 encodings that use shift/escape sequences.
+ **
+ ==============================================================================*/
+
+ [Serializable]
+ internal class ISO2022Encoding : DBCSCodePageEncoding
+ {
+ const byte SHIFT_OUT = (byte)0x0E;
+ const byte SHIFT_IN = (byte)0x0F;
+ const byte ESCAPE = 0x1B;
+ const byte LEADBYTE_HALFWIDTH = 0x10;
+
+ // We have to load the 936 code page tables, so impersonate 936 as our base
+ // This pretends to be other code pages as far as memory sections are concerned.
+ [System.Security.SecurityCritical] // auto-generated
+ internal ISO2022Encoding(int codePage) : base(codePage, tableBaseCodePages[codePage % 10])
+ {
+ this.m_bUseMlangTypeForSerialization = true;
+ }
+
+ // Constructor called by serialization.
+ // Note: We use the base GetObjectData however
+ [System.Security.SecurityCritical] // auto-generated
+ internal ISO2022Encoding(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ // Actually this can't ever get called, CodePageEncoding is our proxy
+ Contract.Assert(false, "Didn't expect to make it to DBCSCodePageEncoding serialization constructor");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+
+ static int[] tableBaseCodePages =
+ {
+ 932, // 50220 ISO-2022-JP, No halfwidth Katakana, convert to full width
+ 932, // 50221 ISO-2022-JP, Use escape sequence for half width Katakana
+ 932, // 50222 ISO-2022-JP, Use shift-in/shift-out for half width Katakana
+ 0,
+ 0,
+ 949, // 50225 ISO-2022-KR, Korean
+ 936, // 52936 HZ-GB2312, 936 might be better source
+ 0, //20936, // 50227 ISO-2022-CN, Note: This is just the same as CP 936 in Everett.
+ 0,
+ // 50229 is currently unsupported, CP 20000 is currently not built in .nlp file
+ 0, //20000, // 50229 ISO-2022-CN, ModeCNS11643_1
+ 0, //20000, // 50229 ISO-2022-CN, ModeCNS11643_2
+ 0 // ModeASCII
+ };
+
+ internal enum ISO2022Modes
+ {
+ ModeHalfwidthKatakana = 0,
+ ModeJIS0208 = 1,
+ ModeKR = 5,
+ ModeHZ = 6,
+ ModeGB2312 = 7,
+ ModeCNS11643_1 = 9,
+ ModeCNS11643_2 = 10,
+ ModeASCII = 11,
+
+ ModeIncompleteEscape = -1,
+ ModeInvalidEscape = -2,
+ ModeNOOP = -3
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe override String GetMemorySectionName()
+ {
+ int iUseCodePage = this.bFlagDataTable ? dataTableCodePage : CodePage;
+
+ String strFormat;
+
+ switch (this.CodePage)
+ {
+ case 50220:
+ case 50221:
+ case 50222:
+ strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}_ISO2022JP";
+ break;
+ case 50225:
+ strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}_ISO2022KR";
+ break;
+ case 52936:
+ strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}_HZ";
+ break;
+ default:
+ Contract.Assert(false, "[ISO2022Encoding.GetMemorySectionName] Don't expect to get here for code page " + this.CodePage);
+ strFormat = "CodePage_{0}_{1}_{2}_{3}_{4}";
+ break;
+ }
+
+ String strName = String.Format(CultureInfo.InvariantCulture, strFormat,
+ iUseCodePage, this.pCodePage->VersionMajor, this.pCodePage->VersionMinor,
+ this.pCodePage->VersionRevision, this.pCodePage->VersionBuild);
+
+ return strName;
+ }
+
+ // Clean up characters for ISO2022 code pages, etc.
+ // ISO2022 (50220, 50221, 50222)
+ // GB-HZ (52936)
+ protected override bool CleanUpBytes(ref int bytes)
+ {
+ switch (this.CodePage)
+ {
+ // 932 based code pages
+ case 50220:
+ case 50221:
+ case 50222:
+ {
+ if (bytes >= 0x100)
+ {
+ // map extended char (0xfa40-0xfc4b) to a special range
+ // (ported from mlang)
+ if (bytes >= 0xfa40 && bytes <= 0xfc4b)
+ {
+ if ( bytes >= 0xfa40 && bytes <= 0xfa5b )
+ {
+ if ( bytes <= 0xfa49 )
+ bytes = bytes - 0x0b51 ;
+ else if ( bytes >= 0xfa4a && bytes <= 0xfa53 )
+ bytes = bytes - 0x072f6 ;
+ else if ( bytes >= 0xfa54 && bytes <= 0xfa57 )
+ bytes = bytes - 0x0b5b ;
+ else if ( bytes == 0xfa58 )
+ bytes = 0x878a ;
+ else if ( bytes == 0xfa59 )
+ bytes = 0x8782 ;
+ else if ( bytes == 0xfa5a )
+ bytes = 0x8784 ;
+ else if ( bytes == 0xfa5b )
+ bytes = 0x879a ;
+ }
+ else if ( bytes >= 0xfa5c && bytes <= 0xfc4b )
+ {
+ byte tc = unchecked((byte)bytes);
+ if ( tc < 0x5c )
+ bytes = bytes - 0x0d5f;
+ else if ( tc >= 0x80 && tc <= 0x9B )
+ bytes = bytes - 0x0d1d;
+ else
+ bytes = bytes - 0x0d1c;
+ }
+ }
+
+ // Convert 932 code page to 20932 like code page range
+ // (also ported from mlang)
+ byte bLead = unchecked((byte)(bytes >> 8));
+ byte bTrail = unchecked((byte)bytes);
+
+ bLead -= ((bLead > (byte)0x9f) ? (byte)0xb1 : (byte)0x71);
+ bLead = (byte)((bLead << 1) + 1);
+ if (bTrail > (byte)0x9e)
+ {
+ bTrail -= (byte)0x7e;
+ bLead++;
+ }
+ else
+ {
+ if (bTrail > (byte)0x7e)
+ bTrail--;
+ bTrail -= (byte)0x1f;
+ }
+
+ bytes = ((int)bLead) << 8 | (int)bTrail;
+
+ // Don't step out of our allocated lead byte area.
+ // All DBCS lead and trail bytes should be >= 0x21 and <= 0x7e
+ // This is commented out because Everett/Mlang had illegal PUA
+ // mappings to ISO2022 code pages that we're maintaining.
+// if ((bytes & 0xFF00) < 0x2100 || (bytes & 0xFF00) > 0x7e00 ||
+ // (bytes & 0xFF) < 0x21 || (bytes & 0xFF) > 0x7e)
+ // return false;
+ }
+ else
+ {
+ // Adjust 1/2 Katakana
+ if (bytes >= 0xa1 && bytes <= 0xdf)
+ bytes += (LEADBYTE_HALFWIDTH << 8) - 0x80;
+
+ // 0x81-0x9f and 0xe0-0xfc CP 932
+ // 0x8e and 0xa1-0xfe CP 20932 (we don't use 8e though)
+ // b0-df is 1/2 Katakana
+ if (bytes >= 0x81 &&
+ (bytes <= 0x9f ||
+ (bytes >= 0xe0 && bytes <= 0xfc)))
+ {
+ // Don't do lead bytes, we use escape sequences instead.
+ return false;
+ }
+ }
+ break;
+ }
+ case 50225:
+ {
+ // For 50225 since we don't rely on lead byte marks, return false and don't add them,
+ // esp. since we're only a 7 bit code page.
+ if (bytes >= 0x80 && bytes <= 0xff)
+ return false;
+
+ // Ignore characters out of range (a1-7f)
+ if (bytes >= 0x100 &&
+ ((bytes & 0xff) < 0xa1 || (bytes & 0xff) == 0xff ||
+ (bytes & 0xff00) < 0xa100 || (bytes & 0xff00) == 0xff00))
+ return false;
+
+ // May as well get them into our 7 bit range
+ bytes &= 0x7f7f;
+
+ break;
+ }
+ case 52936:
+ {
+ // Since we don't rely on lead byte marks for 52936, get rid of them so we
+ // don't end up with extra wierd fffe mappings.
+ if (bytes >= 0x81 && bytes <= 0xfe)
+ return false;
+
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ // GetByteCount
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(count >= 0, "[ISO2022Encoding.GetByteCount]count is negative");
+ Contract.Assert(chars != null, "[ISO2022Encoding.GetByteCount]chars is null");
+
+ // Just call GetBytes with null byte* to get count
+ return GetBytes(chars, count, null, 0, baseEncoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(chars != null, "[ISO2022Encoding.GetBytes]chars is null");
+ Contract.Assert(byteCount >= 0, "[ISO2022Encoding.GetBytes]byteCount is negative");
+ Contract.Assert(charCount >= 0, "[ISO2022Encoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[ISO2022Encoding.GetBytes]Attempting to use null encoder fallback");
+
+ // Fix our encoder
+ ISO2022Encoder encoder = (ISO2022Encoder)baseEncoder;
+
+ // Our return value
+ int iCount = 0;
+
+ switch(CodePage)
+ {
+ case 50220:
+ case 50221:
+ case 50222:
+ iCount = GetBytesCP5022xJP( chars, charCount, bytes, byteCount, encoder );
+ break;
+ case 50225:
+ iCount = GetBytesCP50225KR( chars, charCount, bytes, byteCount, encoder );
+ break;
+// Everett had 50227 the same as 936
+/* case 50227:
+ iCount = GetBytesCP50227CN( chars, charCount, bytes, byteCount, encoder );
+ break;
+*/
+ case 52936:
+ iCount = GetBytesCP52936( chars, charCount, bytes, byteCount, encoder );
+ break;
+ }
+
+ return iCount;
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ // Just assert, we're called internally so these should be safe, checked already
+ Contract.Assert(bytes != null, "[ISO2022Encoding.GetCharCount]bytes is null");
+ Contract.Assert(count >= 0, "[ISO2022Encoding.GetCharCount]byteCount is negative");
+
+ // Just call getChars with null char* to get count
+ return GetChars(bytes, count, null, 0, baseDecoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[ISO2022Encoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[ISO2022Encoding.GetChars]byteCount is negative");
+ Contract.Assert(charCount >= 0, "[ISO2022Encoding.GetChars]charCount is negative");
+
+ // Fix our decoder
+ ISO2022Decoder decoder = (ISO2022Decoder)baseDecoder;
+ int iCount = 0;
+
+ switch (CodePage)
+ {
+ case 50220:
+ case 50221:
+ case 50222:
+ iCount = GetCharsCP5022xJP( bytes, byteCount, chars, charCount, decoder);
+ break;
+ case 50225:
+ iCount = GetCharsCP50225KR( bytes, byteCount, chars, charCount, decoder);
+ break;
+ // Currently 50227 is the same as 936
+// case 50227:
+ // iCount = GetCharsCP50227CN( bytes, byteCount, chars, charCount, decoder);
+ // break;
+ case 52936:
+ iCount = GetCharsCP52936( bytes, byteCount, chars, charCount, decoder);
+ break;
+ default:
+ Contract.Assert(false, "[ISO2022Encoding.GetChars] had unexpected code page");
+ break;
+ }
+
+ return iCount;
+ }
+
+ // ISO 2022 Code pages for JP.
+ // 50220 - No halfwidth Katakana, convert to full width
+ // 50221 - Use escape sequence for half width Katakana
+ // 50222 - Use shift-in/shift-out for half width Katakana
+ //
+ // These are the JIS code pages, superset of ISO-2022 / ISO-2022-JP-1
+ // 0E Shift Out (following bytes are Katakana)
+ // 0F Shift In (back to "normal" behavior)
+ // 21-7E Byte ranges (1 or 2 bytes)
+ // <ESC> $ @ To Double Byte 0208 Mode (actually older code page, but subset of 0208)
+ // <ESC> $ B To Double Byte 0208 Mode (duplicate)
+ // <ESC> $ ( D To Double Byte 0212 Mode (previously we misinterpreted this)
+ // <ESC> $ I To half width Katakana
+ // <ESC> ( J To JIS-Roman
+ // <ESC> ( H To JIS-Roman (swedish character set)
+ // <ESC> ( B To ASCII
+ // <ESC> & @ Alternate lead in to <ESC> $ B so just ignore it.
+ //
+ // So in Katakana mode we add 0x8e as a lead byte and use CP 20932 to convert it
+ // In ASCII mode we just spit out the single byte.
+ // In Roman mode we should change 0x5c (\) -> Yen sign and 0x7e (~) to Overline, however
+ // we didn't in mLang, otherwise roman is like ASCII.
+ // In 0208 double byte mode we have to |= with 0x8080 and use CP 20932 to convert it.
+ // In 0212 double byte mode we have to |= with 0x8000 and use CP 20932 to convert it.
+ //
+ // Note that JIS Shift In/Shift Out is different than the other ISO2022 encodings. For JIS
+ // Shift out always shifts to half-width Katakana. Chinese encodings use designator sequences
+ // instead of escape sequences and shift out to the designated sequence or back in to ASCII.
+ //
+ // When decoding JIS 0208, MLang used a '*' (0x2a) character in JIS 0208 mode to map the trailing byte
+ // to halfwidth katakana. I found no description of that behavior, however that block of 0208 is
+ // undefined, so we maintain that behavior when decoding. We will never generate characters using
+ // that technique, but the decoder will process them.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetBytesCP5022xJP(char* chars, int charCount,
+ byte* bytes, int byteCount, ISO2022Encoder encoder)
+ {
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ // Get our mode
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Mode
+ ISO2022Modes shiftInMode = ISO2022Modes.ModeASCII; // Mode that shift in will go back to (only used by CP 50222)
+
+ // Check our encoder
+ if (encoder != null)
+ {
+ char charLeftOver = encoder.charLeftOver;
+
+ currentMode = encoder.currentMode;
+ shiftInMode = encoder.shiftInOutMode;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP5022xJP]leftover character should be high surrogate");
+
+ // It has to be a high surrogate, which we don't support, so it has to be a fallback
+ buffer.Fallback(charLeftOver);
+ }
+ }
+
+ while (buffer.MoreData)
+ {
+ // Get our char
+ char ch = buffer.GetNextChar();
+
+ // Get our bytes
+ ushort iBytes = mapUnicodeToBytes[ch];
+
+ StartConvert:
+ // Check for halfwidth bytes
+ byte bLeadByte = (byte)(iBytes >> 8);
+ byte bTrailByte = (byte)(iBytes & 0xff);
+
+ if (bLeadByte == LEADBYTE_HALFWIDTH)
+ {
+ // Its Halfwidth Katakana
+ if (CodePage == 50220)
+ {
+ // CodePage 50220 doesn't use halfwidth Katakana, convert to fullwidth
+ // See if its out of range, fallback if so, throws if recursive fallback
+ if (bTrailByte < 0x21 || bTrailByte >= 0x21 + HalfToFullWidthKanaTable.Length)
+ {
+ buffer.Fallback(ch);
+ continue;
+ }
+
+ // Get the full width katakana char to use.
+ iBytes = unchecked((ushort)(HalfToFullWidthKanaTable[bTrailByte - 0x21] & 0x7F7F));
+
+ // May have to do all sorts of fun stuff for mode, go back to start convert
+ goto StartConvert;
+ }
+
+ // Can use halfwidth Katakana, make sure we're in right mode
+
+ // Make sure we're in right mode
+ if (currentMode != ISO2022Modes.ModeHalfwidthKatakana)
+ {
+ // 50222 or 50221, either shift in/out or escape to get to Katakana mode
+ if (CodePage == 50222)
+ {
+ // Shift Out
+ if (!buffer.AddByte(SHIFT_OUT))
+ break; // convert out of space, stop
+
+ // Don't change modes until after AddByte in case it fails for convert
+ // We get to shift out to Katakana, make sure we'll go back to the right mode
+ // (This ends up always being ASCII)
+ shiftInMode = currentMode;
+ currentMode = ISO2022Modes.ModeHalfwidthKatakana;
+ }
+ else
+ {
+ // 50221 does halfwidth katakana by escape sequence
+ Contract.Assert(CodePage == 50221, "[ISO2022Encoding.GetBytesCP5022xJP]Expected Code Page 50221");
+
+ // Add our escape sequence
+ if (!buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'I')))
+ break; // convert out of space, stop
+
+ currentMode = ISO2022Modes.ModeHalfwidthKatakana;
+ }
+ }
+
+ // We know we're in Katakana mode now, so add it.
+ // Go ahead and add the Katakana byte. Our table tail bytes are 0x80 too big.
+ if (!buffer.AddByte(unchecked((byte)(bTrailByte & 0x7F))))
+ break; // convert out of space, stop
+
+ // Done with this one
+ continue;
+ }
+ else if (bLeadByte != 0)
+ {
+ //
+ // It's a double byte character.
+ //
+
+ // If we're CP 50222 we may have to shift in from Katakana mode first
+ if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
+ {
+ // Shift In
+ if (!buffer.AddByte(SHIFT_IN))
+ break; // convert out of space, stop
+
+ // Need to shift in from katakana. (Still might not be right, but won't be shifted out anyway)
+ currentMode = shiftInMode;
+ }
+
+ // Make sure we're in the right mode (JIS 0208 or JIS 0212)
+ // Note: Right now we don't use JIS 0212. Also this table'd be wrong
+
+ // Its JIS extension 0208
+ if (currentMode != ISO2022Modes.ModeJIS0208)
+ {
+ // Escape sequence, we can fail after this, mode will be correct for convert
+ if (!buffer.AddByte(ESCAPE, unchecked((byte)'$'), unchecked((byte)'B')))
+ break; // Convert out of space, stop
+
+ currentMode = ISO2022Modes.ModeJIS0208;
+ }
+
+ // Add our double bytes
+ if (!buffer.AddByte(unchecked((byte)(bLeadByte)), unchecked((byte)(bTrailByte))))
+ break; // Convert out of space, stop
+ continue;
+ }
+ else if (iBytes != 0 || ch == 0)
+ {
+ // Single byte Char
+ // If we're CP 50222 we may have to shift in from Katakana mode first
+ if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
+ {
+ // Shift IN
+ if (!buffer.AddByte(SHIFT_IN))
+ break; // convert ran out of room
+
+ // Need to shift in from katakana. (Still might not be right, but won't be shifted out anyway)
+ currentMode = shiftInMode;
+ }
+
+ // Its a single byte character, switch to ASCII if we have to
+ if (currentMode != ISO2022Modes.ModeASCII)
+ {
+ if (!buffer.AddByte(ESCAPE,unchecked((byte)'('), unchecked((byte)'B')))
+ break; // convert ran out of room
+
+ currentMode = ISO2022Modes.ModeASCII;
+ }
+
+ // Add the ASCII char
+ if (!buffer.AddByte(bTrailByte))
+ break; // convert had no room left
+ continue;
+ }
+
+ // Its unknown, do fallback, throws if recursive (knows because we called InternalGetNextChar)
+ buffer.Fallback(ch);
+ }
+
+ // Switch back to ASCII if MustFlush or no encoder
+ if (currentMode != ISO2022Modes.ModeASCII &&
+ (encoder == null || encoder.MustFlush))
+ {
+ // If we're CP 50222 we may have to shift in from Katakana mode first
+ if (CodePage == 50222 && currentMode == ISO2022Modes.ModeHalfwidthKatakana)
+ {
+ // Shift IN, only shift mode if necessary.
+ if (buffer.AddByte(SHIFT_IN))
+ // Need to shift in from katakana. (Still might not be right, but won't be shifted out anyway)
+ currentMode = shiftInMode;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ }
+
+ // switch back to ASCII to finish neatly
+ if (currentMode != ISO2022Modes.ModeASCII &&
+ (CodePage != 50222 || currentMode != ISO2022Modes.ModeHalfwidthKatakana))
+ {
+ // only shift if it was successful
+ if (buffer.AddByte(ESCAPE, unchecked((byte)'('), unchecked((byte)'B')))
+ currentMode = ISO2022Modes.ModeASCII;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ }
+ }
+
+ // Remember our encoder state
+ if (bytes != null && encoder != null)
+ {
+ // This is ASCII if we had to flush
+ encoder.currentMode = currentMode;
+ encoder.shiftInOutMode = shiftInMode;
+
+ if (!buffer.fallbackBuffer.bUsedEncoder)
+ {
+ encoder.charLeftOver = (char)0;
+ }
+
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ // Return our length
+ return buffer.Count;
+ }
+
+ // ISO 2022 Code pages for Korean - CP 50225
+ //
+ // CP 50225 has Shift In/Shift Out codes, and a single designator sequence that is supposed
+ // to appear once in the file, at the beginning of a line, before any multibyte code points.
+ // So we stick the designator at the beginning of the output.
+ //
+ // These are the KR code page codes for ISO-2022-KR
+ // 0E Shift Out (following bytes are double byte)
+ // 0F Shift In (back to ASCII behavior)
+ // 21-7E Byte ranges (1 or 2 bytes)
+ // <ESC> $)C Double byte ISO-2022-KR designator
+ //
+ // Note that this encoding is a little different than other encodings. The <esc>$)C sequence
+ // should only appear once per file. (Actually I saw another spec/rfc that said at the beginning
+ // of each line, but it shouldn't really matter.)
+ //
+ // During decoding Mlang accepted ' ', '\t, and '\n' as their respective characters, even if
+ // it was in double byte mode. We maintain that behavior, although I couldn't find a reference or
+ // reason for that behavior. We never generate data using that shortcut.
+ //
+ // Also Mlang always assumed KR mode, even if the designator wasn't found yet, so we do that as
+ // well. So basically we just ignore <ESC>$)C when decoding.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetBytesCP50225KR(char* chars, int charCount,
+ byte* bytes, int byteCount, ISO2022Encoder encoder)
+ {
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ // Get our mode
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Mode
+ ISO2022Modes shiftOutMode = ISO2022Modes.ModeASCII; // ModeKR if already stamped lead bytes
+
+ // Check our encoder
+ if (encoder != null)
+ {
+ // May have leftover stuff
+ char charLeftOver = encoder.charLeftOver;
+ currentMode = encoder.currentMode;
+ shiftOutMode = encoder.shiftInOutMode;
+
+ // We may have a l left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP50225KR]leftover character should be high surrogate");
+
+ // It has to be a high surrogate, which we don't support, so it has to be a fallback
+ buffer.Fallback(charLeftOver);
+ }
+ }
+
+ while (buffer.MoreData)
+ {
+ // Get our data
+ char ch = buffer.GetNextChar();
+
+ // Get our bytes
+ ushort iBytes = mapUnicodeToBytes[ch];
+
+ // Check for double byte bytes
+ byte bLeadByte = (byte)(iBytes >> 8);
+ byte bTrailByte = (byte)(iBytes & 0xff);
+
+ if (bLeadByte != 0)
+ {
+ //
+ // It's a double byte character.
+ //
+
+ // If we haven't done our Korean designator, then do so, if we have any input
+ if (shiftOutMode != ISO2022Modes.ModeKR)
+ {
+ // Add our code page designator sequence
+ if (!buffer.AddByte(ESCAPE, unchecked((byte)'$'), unchecked((byte)')'), unchecked((byte)'C')))
+ break; // No room during convert.
+
+ shiftOutMode = ISO2022Modes.ModeKR;
+ }
+
+ // May have to switch to ModeKR first
+ if (currentMode != ISO2022Modes.ModeKR)
+ {
+ if (!buffer.AddByte(SHIFT_OUT))
+ break; // No convert room
+
+ currentMode = ISO2022Modes.ModeKR;
+ }
+
+ // Add the bytes
+ if (!buffer.AddByte(bLeadByte, bTrailByte))
+ break; // no convert room
+ continue;
+ }
+ else if (iBytes != 0 || ch == 0)
+ {
+ // Its a single byte character, switch to ASCII if we have to
+ if (currentMode != ISO2022Modes.ModeASCII)
+ {
+ if (!buffer.AddByte(SHIFT_IN))
+ break;
+
+ currentMode = ISO2022Modes.ModeASCII;
+ }
+
+ // Add the ASCII char
+ if (!buffer.AddByte(bTrailByte))
+ break;
+ continue;
+ }
+
+ // Its unknown, do fallback, throws if recursive (knows because we called InternalGetNextChar)
+ buffer.Fallback(ch);
+ }
+
+ // Switch back to ASCII if MustFlush or no encoder
+ if (currentMode != ISO2022Modes.ModeASCII &&
+ (encoder == null || encoder.MustFlush))
+ {
+ // Get back to ASCII to be safe. Only do it if it success.
+ if (buffer.AddByte(SHIFT_IN))
+ currentMode = ISO2022Modes.ModeASCII;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ }
+
+ // Remember our encoder state
+ if (bytes != null && encoder != null)
+ {
+ // If we didn't use the encoder, then there's no chars left over
+ if (!buffer.fallbackBuffer.bUsedEncoder)
+ {
+ encoder.charLeftOver = (char)0;
+ }
+
+ // This is ASCII if we had to flush
+ encoder.currentMode = currentMode;
+
+ // We don't use shift out mode, but if we've flushed we need to reset it so it doesn't
+ // get output again.
+ if (!encoder.MustFlush || encoder.charLeftOver != (char)0)
+ {
+ // We should be not flushing or converting
+ Contract.Assert(!encoder.MustFlush || !encoder.m_throwOnOverflow,
+ "[ISO2022Encoding.GetBytesCP50225KR]Expected no left over data or not flushing or not converting");
+ encoder.shiftInOutMode = shiftOutMode;
+ }
+ else
+ encoder.shiftInOutMode = ISO2022Modes.ModeASCII;
+
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ // Return our length
+ return buffer.Count;
+ }
+
+ // CP52936 is HZ Encoding
+ // HZ Encoding has 4 shift sequences:
+ // ~~ '~' (\u7e)
+ // ~} shift into 1 byte mode,
+ // ~{ shift into 2 byte GB 2312-80
+ // ~<NL> Maintain 2 byte mode across new lines (ignore both ~ and <NL> characters)
+ // (This is for mailers that restrict to 70 or 80 or whatever character lines)
+ //
+ // According to comment in mlang, lead & trail byte ranges are described in RFC 1843
+ // RFC 1843 => valid HZ code range: leading byte 0x21 - 0x77, 2nd byte 0x21 - 0x7e
+ // Our 936 code points are or'd with 0x8080, so lead byte 0xa1 - 0xf7, trail byte 0xa1 - 0xfe
+ //
+ // This encoding is designed for transmission by e-mail and news. No bytes should have high bit set.
+ // (all bytes <= 0x7f)
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetBytesCP52936(char* chars, int charCount,
+ byte* bytes, int byteCount, ISO2022Encoder encoder)
+ {
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ // Mode
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII;
+
+ // Check our encoder
+ if (encoder != null)
+ {
+ char charLeftOver = encoder.charLeftOver;
+ currentMode = encoder.currentMode;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ Contract.Assert(Char.IsHighSurrogate(charLeftOver), "[ISO2022Encoding.GetBytesCP52936]leftover character should be high surrogate");
+
+ // It has to be a high surrogate, which we don't support, so it has to be a fallback
+ buffer.Fallback(charLeftOver);
+ }
+ }
+
+ while (buffer.MoreData)
+ {
+ // Get our char
+ char ch = buffer.GetNextChar();
+
+ // Get our bytes
+ ushort sChar = mapUnicodeToBytes[ch];
+ if (sChar == 0 && ch != 0)
+ {
+ // Wasn't a legal byte sequence, its a surrogate or fallback
+ // Throws if recursive (knows because we called InternalGetNextChar)
+ buffer.Fallback(ch);
+
+ // Done with our char, now process fallback
+ continue;
+ }
+
+ // Check for halfwidth bytes
+ byte bLeadByte = (byte)(sChar >> 8);
+ byte bTrailByte = (byte)(sChar & 0xff);
+
+ // If its a double byte, it has to fit in the lead byte 0xa1 - 0xf7, trail byte 0xa1 - 0xfe range
+ // (including the 0x8080 that our codepage or's to the value)
+ if ((bLeadByte != 0 &&
+ (bLeadByte < 0xa1 || bLeadByte > 0xf7 || bTrailByte < 0xa1 || bTrailByte > 0xfe)) ||
+ (bLeadByte == 0 && bTrailByte > 0x80 && bTrailByte != 0xff))
+ {
+ // Illegal character, in 936 code page, but not in HZ subset, get fallback for it
+ buffer.Fallback(ch);
+ continue;
+ }
+
+ // sChar is now either ASCII or has an 0x8080 mask
+ if (bLeadByte != 0)
+ {
+ // Its a double byte mode
+ if (currentMode != ISO2022Modes.ModeHZ)
+ {
+ // Need to add the double byte mode marker
+ if (!buffer.AddByte((byte)'~', (byte)'{', 2))
+ break; // Stop if no buffer space in convert
+
+ currentMode = ISO2022Modes.ModeHZ;
+ }
+
+ // Go ahead and add the 2 bytes
+ if (!buffer.AddByte(unchecked((byte)(bLeadByte & 0x7f)), unchecked((byte)(bTrailByte & 0x7f))))
+ break; // Stop if no buffer space in convert
+ }
+ else
+ {
+ // Its supposed to be ASCII
+ if (currentMode != ISO2022Modes.ModeASCII)
+ {
+ // Need to add the ASCII mode marker
+ // Will have 1 more byte (or 2 if ~)
+ if (!buffer.AddByte((byte)'~', (byte)'}', bTrailByte == '~' ? 2:1))
+ break;
+
+ currentMode = ISO2022Modes.ModeASCII;
+ }
+
+ // If its a '~' we'll need an extra one
+ if (bTrailByte == '~')
+ {
+ // Need to add the extra ~
+ if (!buffer.AddByte((byte)'~', 1))
+ break;
+ }
+
+ // Need to add the character
+ if (!buffer.AddByte(bTrailByte))
+ break;
+ }
+ }
+
+ // Add ASCII shift out if we're at end of decoder
+ if (currentMode != ISO2022Modes.ModeASCII &&
+ (encoder == null || encoder.MustFlush))
+ {
+ // Need to add the ASCII mode marker
+ // Only turn off other mode if this works
+ if (buffer.AddByte((byte)'~',(byte)'}'))
+ currentMode = ISO2022Modes.ModeASCII;
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ }
+
+ // Need to remember our mode
+ if (encoder != null && bytes != null)
+ {
+ // This is ASCII if we had to flush
+ encoder.currentMode = currentMode;
+
+ if (!buffer.fallbackBuffer.bUsedEncoder)
+ {
+ encoder.charLeftOver = (char)0;
+ }
+
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ // Return our length
+ return buffer.Count;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetCharsCP5022xJP(byte* bytes, int byteCount,
+ char* chars, int charCount, ISO2022Decoder decoder)
+ {
+ // Get our info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ // No mode information yet
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Our current Mode
+ ISO2022Modes shiftInMode = ISO2022Modes.ModeASCII; // Mode that we'll shift in to
+ byte[] escapeBytes = new byte[4];
+ int escapeCount = 0;
+
+ if (decoder != null)
+ {
+ currentMode = decoder.currentMode;
+ shiftInMode = decoder.shiftInOutMode;
+
+ // See if we have leftover decoder buffer to use
+ // Load our bytesLeftOver
+ escapeCount = decoder.bytesLeftOverCount;
+
+ // Don't want to mess up decoder if we're counting or throw an exception
+ for (int i = 0; i < escapeCount; i++)
+ escapeBytes[i] = decoder.bytesLeftOver[i];
+ }
+
+ // Do this until the end
+ while (buffer.MoreData || escapeCount > 0)
+ {
+ byte ch;
+
+ if (escapeCount > 0)
+ {
+ // Get more escape sequences if necessary
+ if (escapeBytes[0] == ESCAPE)
+ {
+ // Stop if no more input
+ if (!buffer.MoreData)
+ {
+ if (decoder != null && !decoder.MustFlush)
+ break;
+ }
+ else
+ {
+ // Add it to the sequence we can check
+ escapeBytes[escapeCount++] = buffer.GetNextByte();
+
+ // We have an escape sequence
+ ISO2022Modes modeReturn =
+ CheckEscapeSequenceJP(escapeBytes, escapeCount);
+
+ if (modeReturn != ISO2022Modes.ModeInvalidEscape)
+ {
+ if (modeReturn != ISO2022Modes.ModeIncompleteEscape)
+ {
+ // Processed escape correctly
+ escapeCount = 0;
+
+ // We're now this mode
+ currentMode = shiftInMode = modeReturn;
+ }
+
+ // Either way, continue to get next escape or real byte
+ continue;
+ }
+ }
+
+ // If ModeInvalidEscape, or no input & must flush, then fall through to add escape.
+ }
+
+ // Read next escape byte and move them down one.
+ ch = DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
+ }
+ else
+ {
+ // Get our next byte
+ ch = buffer.GetNextByte();
+
+ if (ch == ESCAPE)
+ {
+ // We'll have an escape sequence, use it if we don't have one buffered already
+ if (escapeCount == 0)
+ {
+ // Start this new escape sequence
+ escapeBytes[0] = ch;
+ escapeCount = 1;
+ continue;
+ }
+
+ // Flush the previous escape sequence, then reuse this escape byte
+ buffer.AdjustBytes(-1);
+ }
+ }
+
+ if (ch == SHIFT_OUT)
+ {
+ shiftInMode = currentMode;
+ currentMode = ISO2022Modes.ModeHalfwidthKatakana;
+ continue;
+ }
+ else if (ch == SHIFT_IN)
+ {
+ currentMode = shiftInMode;
+ continue;
+ }
+
+ // Get our full character
+ ushort iBytes = ch;
+ bool b2Bytes = false;
+
+ if (currentMode == ISO2022Modes.ModeJIS0208)
+ {
+ //
+ // To handle errors, we need to check:
+ // 1. if trailbyte is there
+ // 2. if code is valid
+ //
+ if (escapeCount > 0)
+ {
+ // Let another escape fall through
+ if (escapeBytes[0] != ESCAPE)
+ {
+ // Move them down one & get the next data
+ iBytes <<= 8;
+ iBytes |= DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
+ b2Bytes = true;
+ }
+ }
+ else if (buffer.MoreData)
+ {
+ iBytes <<= 8;
+ iBytes |= buffer.GetNextByte();
+ b2Bytes = true;
+ }
+ else
+ {
+ // Not enough input, use decoder if possible
+ if (decoder == null || decoder.MustFlush)
+ {
+ // No decoder, do fallback for this byte
+ buffer.Fallback(ch);
+ break;
+ }
+
+ // Stick it in the decoder if we're not counting
+ if (chars != null)
+ {
+ escapeBytes[0] = ch;
+ escapeCount = 1;
+ }
+ break;
+ }
+
+ // MLang treated JIS 0208 '*' lead byte like a single halfwidth katakana
+ // escape, so use 0x8e00 as katakana lead byte and keep same trail byte.
+ // 0x2a lead byte range is normally unused in JIS 0208, so shouldn't have
+ // any wierd compatibility issues.
+ if ((b2Bytes == true) && ((iBytes & 0xff00) == 0x2a00))
+ {
+ iBytes = (ushort)(iBytes & 0xff);
+ iBytes |= (LEADBYTE_HALFWIDTH << 8); // Put us in the halfwidth katakana range
+ }
+ }
+ else if (iBytes >= 0xA1 && iBytes <= 0xDF)
+ {
+ // Everett accidentally mapped Katakana like shift-jis (932),
+ // even though this is a 7 bit code page. We keep that mapping
+ iBytes |= (LEADBYTE_HALFWIDTH << 8); // Map to halfwidth katakana range
+ iBytes &= 0xff7f; // remove extra 0x80
+ }
+ else if (currentMode == ISO2022Modes.ModeHalfwidthKatakana )
+ {
+ // Add 0x10 lead byte that our encoding expects for Katakana:
+ iBytes |= (LEADBYTE_HALFWIDTH << 8);
+ }
+
+ // We have an iBytes to try to convert.
+ char c = mapBytesToUnicode[iBytes];
+
+ // See if it was unknown
+ if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ // Have to do fallback
+ if (b2Bytes)
+ {
+ if (!buffer.Fallback((byte)(iBytes >> 8), (byte)iBytes))
+ break;
+ }
+ else
+ {
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+ else
+ {
+ // If we were JIS 0208, then we consumed an extra byte
+ if (!buffer.AddChar(c, b2Bytes ? 2:1))
+ break;
+ }
+ }
+
+ // Make sure our decoder state matches our mode, if not counting
+ if (chars != null && decoder != null)
+ {
+ // Remember it if we don't flush
+ if (!decoder.MustFlush || escapeCount != 0)
+ {
+ // Either not flushing or had state (from convert)
+ Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow,
+ "[ISO2022Encoding.GetCharsCP5022xJP]Expected no state or not converting or not flushing");
+
+ decoder.currentMode = currentMode;
+ decoder.shiftInOutMode = shiftInMode;
+
+ // Remember escape buffer
+ decoder.bytesLeftOverCount = escapeCount;
+ decoder.bytesLeftOver = escapeBytes;
+ }
+ else
+ {
+ // We flush, clear buffer
+ decoder.currentMode = ISO2022Modes.ModeASCII;
+ decoder.shiftInOutMode = ISO2022Modes.ModeASCII;
+ decoder.bytesLeftOverCount = 0;
+ // Slightly different if counting/not counting
+ }
+
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+
+ // Return # of characters we found
+ return buffer.Count;
+ }
+
+ // We know we have an escape sequence, so check it starting with the byte after the escape
+ private ISO2022Modes CheckEscapeSequenceJP( byte[] bytes, int escapeCount )
+ {
+ // Have an escape sequence
+ if (bytes[0] != ESCAPE)
+ return ISO2022Modes.ModeInvalidEscape;
+
+ if (escapeCount < 3)
+ return ISO2022Modes.ModeIncompleteEscape;
+
+ if (bytes[1] == '(')
+ {
+ if (bytes[2] == 'B') // <esc>(B
+ {
+ return ISO2022Modes.ModeASCII;
+ }
+ else if (bytes[2] == 'H') // <esc>(H
+ {
+ // Actually this is supposed to be Swedish
+ // We treat it like ASCII though.
+ return ISO2022Modes.ModeASCII;
+ }
+ else if (bytes[2] == 'J') // <esc>(J
+ {
+ // Actually this is supposed to be Roman
+ // 2 characters are different, but historically we treat it as ascii
+ return ISO2022Modes.ModeASCII;
+ }
+ else if (bytes[2] == 'I') // <esc>(I
+ {
+ return ISO2022Modes.ModeHalfwidthKatakana;
+ }
+ }
+ else if (bytes[1] == '$')
+ {
+ if (bytes[2] == '@' || // <esc>$@
+ bytes[2] == 'B') // <esc>$B
+ {
+ return ISO2022Modes.ModeJIS0208;
+ }
+ else
+ {
+ // Looking for <esc>$(D
+ if (escapeCount < 4)
+ return ISO2022Modes.ModeIncompleteEscape;
+
+ if (bytes[2] == '(' && bytes[3] == 'D') // <esc>$(D
+ {
+ // Mlang treated 0208 like 0212 even though that's wrong
+ return ISO2022Modes.ModeJIS0208;
+ }
+ }
+ }
+ else if (bytes[1] == '&')
+ {
+ if (bytes[2] == '@') // <esc>&@
+ {
+ // Ignore ESC & @ (prefix to <esc>$B)
+ return ISO2022Modes.ModeNOOP;
+ }
+ }
+
+ // If we get here we fell through and have an invalid/unknown escape sequence
+ return ISO2022Modes.ModeInvalidEscape;
+ }
+
+ private byte DecrementEscapeBytes(ref byte[] bytes, ref int count)
+ {
+ Contract.Assert(count > 0, "[ISO2022Encoding.DecrementEscapeBytes]count > 0");
+
+ // Decrement our count
+ count--;
+
+ // Remember the first one
+ byte returnValue = bytes[0];
+
+ // Move them down one.
+ for (int i = 0; i < count; i++)
+ {
+ bytes[i] = bytes[i+1];
+ }
+
+ // Clear out the last byte
+ bytes[count] = 0;
+
+ // Return the old 1st byte
+ return returnValue;
+ }
+
+ // Note that in DBCS mode mlang passed through ' ', '\t' and '\n' as SBCS characters
+ // probably to allow mailer formatting without too much extra work.
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetCharsCP50225KR(byte* bytes, int byteCount,
+ char* chars, int charCount, ISO2022Decoder decoder)
+ {
+ // Get our info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ // No mode information yet
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII; // Our current Mode
+
+ byte[] escapeBytes = new byte[4];
+ int escapeCount = 0;
+
+ if (decoder != null)
+ {
+ currentMode = decoder.currentMode;
+
+ // See if we have leftover decoder buffer to use
+ // Load our bytesLeftOver
+ escapeCount = decoder.bytesLeftOverCount;
+
+ // Don't want to mess up decoder if we're counting or throw an exception
+ for (int i = 0; i < escapeCount; i++)
+ escapeBytes[i] = decoder.bytesLeftOver[i];
+ }
+
+ // Do this until the end, just do '?' replacement because we don't have fallbacks for decodings.
+ while (buffer.MoreData || escapeCount > 0)
+ {
+ byte ch;
+
+ if (escapeCount > 0)
+ {
+ // Get more escape sequences if necessary
+ if (escapeBytes[0] == ESCAPE)
+ {
+ // Stop if no more input
+ if (!buffer.MoreData)
+ {
+ if (decoder != null && !decoder.MustFlush)
+ break;
+ }
+ else
+ {
+ // Add it to the sequence we can check
+ escapeBytes[escapeCount++] = buffer.GetNextByte();
+
+ // We have an escape sequence
+ ISO2022Modes modeReturn =
+ CheckEscapeSequenceKR(escapeBytes, escapeCount);
+
+ if (modeReturn != ISO2022Modes.ModeInvalidEscape)
+ {
+ if (modeReturn != ISO2022Modes.ModeIncompleteEscape)
+ {
+ // Processed escape correctly, no effect (we know about KR mode)
+ escapeCount = 0;
+ }
+
+ // Either way, continue to get next escape or real byte
+ continue;
+ }
+ }
+
+ // If ModeInvalidEscape, or no input & must flush, then fall through to add escape.
+ }
+
+ // Still have something left over in escape buffer
+ // Get it and move them down one
+ ch = DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
+ }
+ else
+ {
+ // Get our next byte
+ ch = buffer.GetNextByte();
+
+ if (ch == ESCAPE)
+ {
+ // We'll have an escape sequence, use it if we don't have one buffered already
+ if (escapeCount == 0)
+ {
+ // Start this new escape sequence
+ escapeBytes[0] = ch;
+ escapeCount = 1;
+ continue;
+ }
+
+ // Flush previous escape sequence, then reuse this escape byte
+ buffer.AdjustBytes(-1);
+ }
+ }
+
+ if (ch == SHIFT_OUT)
+ {
+ currentMode = ISO2022Modes.ModeKR;
+ continue;
+ }
+ else if (ch == SHIFT_IN)
+ {
+ currentMode = ISO2022Modes.ModeASCII;
+ continue;
+ }
+
+ // Get our full character
+ ushort iBytes = ch;
+ bool b2Bytes = false;
+
+ // MLANG was passing through ' ', '\t' and '\n', so we do so as well, but I don't see that in the RFC.
+ if (currentMode == ISO2022Modes.ModeKR && ch != ' ' && ch != '\t' && ch != '\n')
+ {
+ //
+ // To handle errors, we need to check:
+ // 1. if trailbyte is there
+ // 2. if code is valid
+ //
+ if (escapeCount > 0)
+ {
+ // Let another escape fall through
+ if (escapeBytes[0] != ESCAPE)
+ {
+ // Move them down one & get the next data
+ iBytes <<= 8;
+ iBytes |= DecrementEscapeBytes(ref escapeBytes, ref escapeCount);
+ b2Bytes = true;
+ }
+ }
+ else if (buffer.MoreData)
+ {
+ iBytes <<= 8;
+ iBytes |= buffer.GetNextByte();
+ b2Bytes = true;
+ }
+ else
+ {
+ // Not enough input, use decoder if possible
+ if (decoder == null || decoder.MustFlush)
+ {
+ // No decoder, do fallback for lonely 1st byte
+ buffer.Fallback(ch);
+ break;
+ }
+
+ // Stick it in the decoder if we're not counting
+ if (chars != null)
+ {
+ escapeBytes[0] = ch;
+ escapeCount = 1;
+ }
+ break;
+ }
+ }
+
+ // We have a iBytes to try to convert.
+ char c = mapBytesToUnicode[iBytes];
+
+ // See if it was unknown
+ if (c == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ // Have to do fallback
+ if (b2Bytes)
+ {
+ if (!buffer.Fallback((byte)(iBytes >> 8), (byte)iBytes))
+ break;
+ }
+ else
+ {
+ if (!buffer.Fallback(ch))
+ break;
+ }
+ }
+ else
+ {
+ if (!buffer.AddChar(c, b2Bytes ? 2:1))
+ break;
+ }
+ }
+
+ // Make sure our decoder state matches our mode, if not counting
+ if (chars != null && decoder != null)
+ {
+ // Remember it if we don't flush
+ if (!decoder.MustFlush || escapeCount != 0)
+ {
+ // Either not flushing or had state (from convert)
+ Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow,
+ "[ISO2022Encoding.GetCharsCP50225KR]Expected no state or not converting or not flushing");
+
+ decoder.currentMode = currentMode;
+
+ // Remember escape buffer
+ decoder.bytesLeftOverCount = escapeCount;
+ decoder.bytesLeftOver = escapeBytes;
+ }
+ else
+ {
+ // We flush, clear buffer
+ decoder.currentMode = ISO2022Modes.ModeASCII;
+ decoder.shiftInOutMode = ISO2022Modes.ModeASCII;
+ decoder.bytesLeftOverCount = 0;
+ }
+
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+
+ // Return # of characters we found
+ return buffer.Count;
+ }
+
+ // We know we have an escape sequence, so check it starting with the byte after the escape
+ private ISO2022Modes CheckEscapeSequenceKR( byte[] bytes, int escapeCount )
+ {
+ // Have an escape sequence
+ if (bytes[0] != ESCAPE)
+ return ISO2022Modes.ModeInvalidEscape;
+
+ if (escapeCount < 4)
+ return ISO2022Modes.ModeIncompleteEscape;
+
+ if (bytes[1] == '$' && bytes[2] == ')' && bytes[3] == 'C') // <esc>$)C
+ return ISO2022Modes.ModeKR;
+
+ // If we get here we fell through and have an invalid/unknown escape sequence
+ return ISO2022Modes.ModeInvalidEscape;
+ }
+
+ // CP52936 is HZ Encoding
+ // HZ Encoding has 4 shift sequences:
+ // ~~ '~' (\u7e)
+ // ~} shift into 1 byte mode,
+ // ~{ shift into 2 byte GB 2312-80
+ // ~<NL> Maintain 2 byte mode across new lines (ignore both ~ and <NL> characters)
+ // (This is for mailers that restrict to 70 or 80 or whatever character lines)
+ //
+ // According to comment in mlang, lead & trail byte ranges are described in RFC 1843
+ // RFC 1843 => valid HZ code range: leading byte 0x21 - 0x77, 2nd byte 0x21 - 0x7e
+ // Our 936 code points are or'd with 0x8080, so lead byte 0xa1 - 0xf7, trail byte 0xa1 - 0xfe
+ //
+ // This encoding is designed for transmission by e-mail and news. No bytes should have high bit set.
+ // (all bytes <= 0x7f)
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int GetCharsCP52936(byte* bytes, int byteCount,
+ char* chars, int charCount, ISO2022Decoder decoder)
+ {
+ Contract.Assert(byteCount >=0, "[ISO2022Encoding.GetCharsCP52936]count >=0");
+ Contract.Assert(bytes!=null, "[ISO2022Encoding.GetCharsCP52936]bytes!=null");
+
+ // Get our info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ // No mode information yet
+ ISO2022Modes currentMode = ISO2022Modes.ModeASCII;
+ int byteLeftOver = -1;
+ bool bUsedDecoder = false;
+
+ if (decoder != null)
+ {
+ currentMode = decoder.currentMode;
+ // See if we have leftover decoder buffer to use
+ // Don't want to mess up decoder if we're counting or throw an exception
+ if (decoder.bytesLeftOverCount != 0 )
+ {
+ // Load our bytesLeftOver
+ byteLeftOver = decoder.bytesLeftOver[0];
+ }
+ }
+
+ // Do this until the end, just do '?' replacement because we don't have fallbacks for decodings.
+ while (buffer.MoreData || byteLeftOver >= 0)
+ {
+ byte ch;
+
+ // May have a left over byte
+ if (byteLeftOver >= 0)
+ {
+ ch = (byte)byteLeftOver;
+ byteLeftOver = -1;
+ }
+ else
+ {
+ ch = buffer.GetNextByte();
+ }
+
+ // We're in escape mode
+ if (ch == '~')
+ {
+ // Next char is type of switch
+ if (!buffer.MoreData)
+ {
+ // We don't have anything left, it'll be in decoder or a ?
+ // don't fail if we are allowing overflows
+ if (decoder == null || decoder.MustFlush)
+ {
+ // We'll be a '?'
+ buffer.Fallback(ch);
+ // break if we fail & break if we don't (because !MoreData)
+ // Add succeeded, continue
+ break;
+ }
+
+ // Stick it in decoder
+ if (decoder != null)
+ decoder.ClearMustFlush();
+
+ if (chars != null)
+ {
+ decoder.bytesLeftOverCount = 1;
+ decoder.bytesLeftOver[0] = (byte)'~';
+ bUsedDecoder = true;
+ }
+ break;
+ }
+
+ // What type is it?, get 2nd byte
+ ch = buffer.GetNextByte();
+
+ if (ch == '~' && currentMode == ISO2022Modes.ModeASCII)
+ {
+ // Its just a ~~ replacement for ~, add it
+ if (!buffer.AddChar((char)ch, 2))
+ // Add failed, break for converting
+ break;
+
+ // Add succeeded, continue
+ continue;
+ }
+ else if (ch == '{')
+ {
+ // Switching to Double Byte mode
+ currentMode = ISO2022Modes.ModeHZ;
+ continue;
+ }
+ else if (ch == '}')
+ {
+ // Switching to ASCII mode
+ currentMode = ISO2022Modes.ModeASCII;
+ continue;
+ }
+ else if (ch == '\n')
+ {
+ // Ignore ~\n sequence
+ continue;
+ }
+ else
+ {
+ // Unknown escape, back up and try the '~' as a "normal" byte or lead byte
+ buffer.AdjustBytes(-1);
+ ch = (byte)'~';
+ }
+ }
+
+ // go ahead and add our data
+ if (currentMode != ISO2022Modes.ModeASCII)
+ {
+ // Should be ModeHZ
+ Contract.Assert(currentMode == ISO2022Modes.ModeHZ, "[ISO2022Encoding.GetCharsCP52936]Expected ModeHZ");
+ char cm;
+
+ // Everett allowed characters < 0x20 to be passed as if they were ASCII
+ if (ch < 0x20)
+ {
+ // Emit it as ASCII
+ goto STOREASCII;
+ }
+
+ // Its multibyte, should have another byte
+ if (!buffer.MoreData)
+ {
+ // No bytes left
+ // don't fail if we are allowing overflows
+ if (decoder == null || decoder.MustFlush)
+ {
+ // Not enough bytes, fallback lead byte
+ buffer.Fallback(ch);
+
+ // Break if we fail & break because !MoreData
+ break;
+ }
+
+ if (decoder != null)
+ decoder.ClearMustFlush();
+
+ // Stick it in decoder
+ if (chars != null)
+ {
+ decoder.bytesLeftOverCount = 1;
+ decoder.bytesLeftOver[0] = ch;
+ bUsedDecoder = true;
+ }
+ break;
+ }
+
+ // Everett uses space as an escape character for single SBCS bytes
+ byte ch2 = buffer.GetNextByte();
+ ushort iBytes = (ushort)(ch << 8 | ch2);
+
+ if (ch == ' ' && ch2 != 0)
+ {
+ // Get next char and treat it like ASCII (Everett treated space like an escape
+ // allowing the next char to be just ascii)
+ cm = (char)ch2;
+ goto STOREMULTIBYTE;
+ }
+
+ // Bytes should be in range: lead byte 0x21-0x77, trail byte: 0x21 - 0x7e
+ if ((ch < 0x21 || ch > 0x77 || ch2 < 0x21 || ch2 > 0x7e) &&
+ // Everett allowed high bit mappings for same characters (but only if both bits set)
+ (ch < 0xa1 || ch > 0xf7 || ch2 < 0xa1 || ch2 > 0xfe))
+ {
+ // For some reason Everett allowed XX20 to become unicode 3000... (ideo sp)
+ if (ch2 == 0x20 && 0x21 <= ch && ch <= 0x7d)
+ {
+ iBytes = 0x2121;
+ goto MULTIBYTE;
+ }
+
+ // Illegal char, use fallback. If lead byte is 0 have to do it special and do it first
+ if (!buffer.Fallback((byte)(iBytes>>8), (byte)(iBytes)))
+ break;
+ continue;
+ }
+
+ MULTIBYTE:
+ iBytes |= 0x8080;
+ // Look up the multibyte char to stick it in our data
+
+ // We have a iBytes to try to convert.
+ cm = mapBytesToUnicode[iBytes];
+
+ STOREMULTIBYTE:
+
+ // See if it was unknown
+ if (cm == UNKNOWN_CHAR_FLAG && iBytes != 0)
+ {
+ // Fall back the unknown stuff
+ if (!buffer.Fallback((byte)(iBytes>>8), (byte)(iBytes)))
+ break;
+ continue;
+ }
+
+ if (!buffer.AddChar(cm, 2))
+ break; // convert ran out of buffer, stop
+ continue;
+ }
+
+ // Just ASCII
+ // We allow some chars > 7f because everett did, so we have to look them up.
+ STOREASCII:
+ char c = mapBytesToUnicode[ch];
+
+ // Check if it was unknown
+ if ((c == UNKNOWN_CHAR_FLAG || c == 0) && (ch != 0))
+ {
+ // fallback the unkown bytes
+ if (!buffer.Fallback((byte)ch))
+ break;
+ continue;
+ }
+
+ // Go ahead and add our ASCII character
+ if (!buffer.AddChar(c))
+ break; // convert ran out of buffer, stop
+ }
+
+ // Need to remember our state, IF we're not counting
+ if (chars != null && decoder != null)
+ {
+ if (!bUsedDecoder)
+ {
+ // If we didn't use it, clear the byte left over
+ decoder.bytesLeftOverCount = 0;
+ }
+
+ if (decoder.MustFlush && decoder.bytesLeftOverCount == 0)
+ {
+ decoder.currentMode = ISO2022Modes.ModeASCII;
+ }
+ else
+ {
+ // Either not flushing or had state (from convert)
+ Contract.Assert(!decoder.MustFlush || !decoder.m_throwOnOverflow,
+ "[ISO2022Encoding.GetCharsCP52936]Expected no state or not converting or not flushing");
+
+ decoder.currentMode = currentMode;
+ }
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+
+ // Return # of characters we found
+ return buffer.Count;
+ }
+
+ // Note: These all end up with 1/2 bytes of average byte count, so unless we're 1 we're always
+ // charCount/2 bytes too big.
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // Start with just generic DBCS values (sort of).
+ int perChar = 2;
+ int extraStart = 0;
+ int extraEnd = 0;
+
+ switch (CodePage)
+ {
+ case 50220:
+ case 50221:
+ // 2 bytes per char + 3 bytes switch to JIS 0208 or 1 byte + 3 bytes switch to 1 byte CP
+ perChar = 5; // 5 max (4.5 average)
+ extraEnd = 3; // 3 bytes to shift back to ASCII
+ break;
+ case 50222:
+ // 2 bytes per char + 3 bytes switch to JIS 0208 or 1 byte + 3 bytes switch to 1 byte CP
+ perChar = 5; // 5 max (4.5 average)
+ extraEnd = 4; // 1 byte to shift from Katakana -> DBCS, 3 bytes to shift back to ASCII from DBCS
+ break;
+ case 50225:
+ // 2 bytes per char + 1 byte SO, or 1 byte per char + 1 byte SI.
+ perChar = 3; // 3 max, (2.5 average)
+ extraStart = 4; // EUC-KR marker appears at beginning of file.
+ extraEnd = 1; // 1 byte to shift back to ascii if necessary.
+ break;
+ case 52936:
+ // 2 bytes per char + 2 byte shift, or 1 byte + 1 byte shift
+ // Worst case: left over surrogate with no low surrogate is extra ?, could have to switch to ASCII, then could have HZ and flush to ASCII mode
+ perChar = 4; // 4 max, (3.5 average if every other char is HZ/ASCII)
+ extraEnd = 2; // 2 if we have to shift back to ASCII
+ break;
+ }
+
+ // Return our surrogate and End plus perChar for each char.
+ byteCount *= perChar;
+ byteCount += extraStart + extraEnd;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ int perChar = 1;
+ int extraDecoder = 1;
+
+ switch (CodePage)
+ {
+ case 50220:
+ case 50221:
+ case 50222:
+ case 50225:
+ perChar = 1; // Worst case all ASCII
+ extraDecoder = 3; // Could have left over 3 chars of 4 char escape sequence, that all become ?
+ break;
+ case 52936:
+ perChar = 1; // Worst case all ASCII
+ extraDecoder = 1; // sequences are 2 chars, so if next one is illegal, then previous 1 could be ?
+ break;
+ }
+
+ // Figure out our length, perchar * char + whatever extra our decoder could do to us.
+ long charCount = ((long)byteCount * perChar) + extraDecoder;
+
+ // Just in case we have to fall back unknown ones.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ public override Encoder GetEncoder()
+ {
+ return new ISO2022Encoder(this);
+ }
+
+ public override Decoder GetDecoder()
+ {
+ return new ISO2022Decoder(this);
+ }
+
+ [Serializable]
+ internal class ISO2022Encoder : System.Text.EncoderNLS
+ {
+ internal ISO2022Modes currentMode;
+ internal ISO2022Modes shiftInOutMode;
+
+ internal ISO2022Encoder(EncodingNLS encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ public override void Reset()
+ {
+ // Reset
+ currentMode = ISO2022Modes.ModeASCII;
+ shiftInOutMode = ISO2022Modes.ModeASCII;
+ charLeftOver = (char)0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our encoder?
+ internal override bool HasState
+ {
+ get
+ {
+ // Don't check shift-out mode, it may be ascii (JP) or not (KR)
+ return (this.charLeftOver != (char)0 ||
+ currentMode != ISO2022Modes.ModeASCII);
+ }
+ }
+ }
+
+ [Serializable]
+ internal class ISO2022Decoder : System.Text.DecoderNLS
+ {
+ internal byte[] bytesLeftOver;
+ internal int bytesLeftOverCount;
+ internal ISO2022Modes currentMode;
+ internal ISO2022Modes shiftInOutMode;
+
+ internal ISO2022Decoder(EncodingNLS encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ public override void Reset()
+ {
+ // Reset
+ bytesLeftOverCount = 0;
+ bytesLeftOver = new byte[4];
+ currentMode = ISO2022Modes.ModeASCII;
+ shiftInOutMode = ISO2022Modes.ModeASCII;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ // If have bytes left over or not shifted back to ASCII then have problem
+ return (this.bytesLeftOverCount != 0 ||
+ currentMode != ISO2022Modes.ModeASCII);
+ }
+ }
+ }
+
+ static ushort[] HalfToFullWidthKanaTable =
+ {
+ 0xa1a3, // 0x8ea1 : Halfwidth Ideographic Period
+ 0xa1d6, // 0x8ea2 : Halfwidth Opening Corner Bracket
+ 0xa1d7, // 0x8ea3 : Halfwidth Closing Corner Bracket
+ 0xa1a2, // 0x8ea4 : Halfwidth Ideographic Comma
+ 0xa1a6, // 0x8ea5 : Halfwidth Katakana Middle Dot
+ 0xa5f2, // 0x8ea6 : Halfwidth Katakana Wo
+ 0xa5a1, // 0x8ea7 : Halfwidth Katakana Small A
+ 0xa5a3, // 0x8ea8 : Halfwidth Katakana Small I
+ 0xa5a5, // 0x8ea9 : Halfwidth Katakana Small U
+ 0xa5a7, // 0x8eaa : Halfwidth Katakana Small E
+ 0xa5a9, // 0x8eab : Halfwidth Katakana Small O
+ 0xa5e3, // 0x8eac : Halfwidth Katakana Small Ya
+ 0xa5e5, // 0x8ead : Halfwidth Katakana Small Yu
+ 0xa5e7, // 0x8eae : Halfwidth Katakana Small Yo
+ 0xa5c3, // 0x8eaf : Halfwidth Katakana Small Tu
+ 0xa1bc, // 0x8eb0 : Halfwidth Katakana-Hiragana Prolonged Sound Mark
+ 0xa5a2, // 0x8eb1 : Halfwidth Katakana A
+ 0xa5a4, // 0x8eb2 : Halfwidth Katakana I
+ 0xa5a6, // 0x8eb3 : Halfwidth Katakana U
+ 0xa5a8, // 0x8eb4 : Halfwidth Katakana E
+ 0xa5aa, // 0x8eb5 : Halfwidth Katakana O
+ 0xa5ab, // 0x8eb6 : Halfwidth Katakana Ka
+ 0xa5ad, // 0x8eb7 : Halfwidth Katakana Ki
+ 0xa5af, // 0x8eb8 : Halfwidth Katakana Ku
+ 0xa5b1, // 0x8eb9 : Halfwidth Katakana Ke
+ 0xa5b3, // 0x8eba : Halfwidth Katakana Ko
+ 0xa5b5, // 0x8ebb : Halfwidth Katakana Sa
+ 0xa5b7, // 0x8ebc : Halfwidth Katakana Si
+ 0xa5b9, // 0x8ebd : Halfwidth Katakana Su
+ 0xa5bb, // 0x8ebe : Halfwidth Katakana Se
+ 0xa5bd, // 0x8ebf : Halfwidth Katakana So
+ 0xa5bf, // 0x8ec0 : Halfwidth Katakana Ta
+ 0xa5c1, // 0x8ec1 : Halfwidth Katakana Ti
+ 0xa5c4, // 0x8ec2 : Halfwidth Katakana Tu
+ 0xa5c6, // 0x8ec3 : Halfwidth Katakana Te
+ 0xa5c8, // 0x8ec4 : Halfwidth Katakana To
+ 0xa5ca, // 0x8ec5 : Halfwidth Katakana Na
+ 0xa5cb, // 0x8ec6 : Halfwidth Katakana Ni
+ 0xa5cc, // 0x8ec7 : Halfwidth Katakana Nu
+ 0xa5cd, // 0x8ec8 : Halfwidth Katakana Ne
+ 0xa5ce, // 0x8ec9 : Halfwidth Katakana No
+ 0xa5cf, // 0x8eca : Halfwidth Katakana Ha
+ 0xa5d2, // 0x8ecb : Halfwidth Katakana Hi
+ 0xa5d5, // 0x8ecc : Halfwidth Katakana Hu
+ 0xa5d8, // 0x8ecd : Halfwidth Katakana He
+ 0xa5db, // 0x8ece : Halfwidth Katakana Ho
+ 0xa5de, // 0x8ecf : Halfwidth Katakana Ma
+ 0xa5df, // 0x8ed0 : Halfwidth Katakana Mi
+ 0xa5e0, // 0x8ed1 : Halfwidth Katakana Mu
+ 0xa5e1, // 0x8ed2 : Halfwidth Katakana Me
+ 0xa5e2, // 0x8ed3 : Halfwidth Katakana Mo
+ 0xa5e4, // 0x8ed4 : Halfwidth Katakana Ya
+ 0xa5e6, // 0x8ed5 : Halfwidth Katakana Yu
+ 0xa5e8, // 0x8ed6 : Halfwidth Katakana Yo
+ 0xa5e9, // 0x8ed7 : Halfwidth Katakana Ra
+ 0xa5ea, // 0x8ed8 : Halfwidth Katakana Ri
+ 0xa5eb, // 0x8ed9 : Halfwidth Katakana Ru
+ 0xa5ec, // 0x8eda : Halfwidth Katakana Re
+ 0xa5ed, // 0x8edb : Halfwidth Katakana Ro
+ 0xa5ef, // 0x8edc : Halfwidth Katakana Wa
+ 0xa5f3, // 0x8edd : Halfwidth Katakana N
+ 0xa1ab, // 0x8ede : Halfwidth Katakana Voiced Sound Mark
+ 0xa1ac // 0x8edf : Halfwidth Katakana Semi-Voiced Sound Mark
+ };
+ }
+}
+#endif // FEATURE_CODEPAGES_FILE
+
diff --git a/src/mscorlib/src/System/Text/Latin1Encoding.cs b/src/mscorlib/src/System/Text/Latin1Encoding.cs
new file mode 100644
index 0000000000..a24f9c00ae
--- /dev/null
+++ b/src/mscorlib/src/System/Text/Latin1Encoding.cs
@@ -0,0 +1,917 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.Runtime.InteropServices;
+ using System.Security;
+ using System.Collections;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+
+
+ //
+ // Latin1Encoding is a simple override to optimize the GetString version of Latin1Encoding.
+ // because of the best fit cases we can't do this when encoding the string, only when decoding
+ //
+ [Serializable]
+ internal class Latin1Encoding : EncodingNLS, ISerializable
+ {
+ // Used by Encoding.Latin1 for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly Latin1Encoding s_default = new Latin1Encoding();
+
+ // We only use the best-fit table, of which ASCII is a superset for us.
+ public Latin1Encoding() : base(Encoding.ISO_8859_1)
+ {
+ }
+
+ // Constructor called by serialization.
+ // Note: We use the base GetObjectData however
+ internal Latin1Encoding(SerializationInfo info, StreamingContext context) :
+ base(Encoding.ISO_8859_1)
+ {
+ // Set up our base, also throws if info was empty
+ DeserializeEncoding(info, context);
+
+ // Nothing unique to Whidbey for Latin1
+ }
+
+ // ISerializable implementation, serialize it as a CodePageEncoding
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Make sure to get the base stuff too This throws if info is null
+ SerializeEncoding(info, context);
+ Contract.Assert(info!=null, "[Latin1Encoding.GetObjectData] Expected null info to throw");
+
+ // In Everett this is a CodePageEncoding, so it needs maxCharSize
+ info.AddValue("CodePageEncoding+maxCharSize", 1);
+
+ // And extras for Everett's wierdness
+ info.AddValue("CodePageEncoding+m_codePage", this.CodePage);
+ info.AddValue("CodePageEncoding+dataItem", null);
+ }
+
+ // GetByteCount
+ // Note: We start by assuming that the output will be the same as count. Having
+ // an encoder or fallback may change that assumption
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(charCount >= 0, "[Latin1Encoding.GetByteCount]count is negative");
+ Contract.Assert(chars != null, "[Latin1Encoding.GetByteCount]chars is null");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[Latin1Encoding.GetByteCount]Attempting to use null fallback encoder");
+
+ char charLeftOver = (char)0;
+
+ // If we have an encoder AND we aren't using default fallback,
+ // then we may have a complicated count.
+ EncoderReplacementFallback fallback;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[Latin1Encoding.GetByteCount]leftover character should be high surrogate");
+
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+
+ // Verify that we have no fallbackbuffer, for Latin1 its always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[Latin1CodePageEncoding.GetByteCount]Expected empty fallback buffer");
+ }
+ else
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+
+ if ((fallback != null && fallback.MaxCharCount == 1)/* || bIsBestFit*/)
+ {
+ // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always
+ // same as input size.
+ // Note that no existing SBCS code pages map code points to supplimentary characters, so this is easy.
+
+ // We could however have 1 extra byte if the last call had an encoder and a funky fallback and
+ // if we don't use the funky fallback this time.
+
+ // Do we have an extra char left over from last time?
+ if (charLeftOver > 0)
+ charCount++;
+
+ return (charCount);
+ }
+
+ // Count is more complicated if you have a funky fallback
+ // For fallback we may need a fallback buffer, we know we're not default fallback
+ int byteCount = 0;
+
+ // Start by assuming default count, then +/- for fallback characters
+ char* charEnd = chars + charCount;
+
+ // For fallback we may need a fallback buffer, we know we aren't default fallback.
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ // Initialize the buffer
+ Contract.Assert(encoder != null,
+ "[Latin1Encoding.GetByteCount]Expected encoder if we have charLeftOver");
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+
+ // Now we may have fallback char[] already from the encoder
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ // no chars >= 0x100 are allowed.
+ if (ch > 0xff)
+ {
+ // Initialize the buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, false);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // We'll use this one
+ byteCount++;
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[Latin1Encoding.GetByteCount]Expected Empty fallback buffer");
+
+ return byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[Latin1Encoding.GetBytes]bytes is null");
+ Contract.Assert(byteCount >= 0, "[Latin1Encoding.GetBytes]byteCount is negative");
+ Contract.Assert(chars != null, "[Latin1Encoding.GetBytes]chars is null");
+ Contract.Assert(charCount >= 0, "[Latin1Encoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[Latin1Encoding.GetBytes]Attempting to use null encoder fallback");
+
+ // Get any left over characters & check fast or slower fallback type
+ char charLeftOver = (char)0;
+ EncoderReplacementFallback fallback = null;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[Latin1Encoding.GetBytes]leftover character should be high surrogate");
+
+ // Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[Latin1CodePageEncoding.GetBytes]Expected empty fallback buffer");
+ }
+ else
+ {
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+ }
+
+ // prepare our end
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ // See if we do the fast default or slightly slower fallback
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Fast version
+ char cReplacement=fallback.DefaultString[0];
+
+ // Check for replacements in range, otherwise fall back to slow version.
+ if (cReplacement <= (char)0xff)
+ {
+ // We should have exactly as many output bytes as input bytes, unless there's a left
+ // over character, in which case we may need one more.
+
+ // If we had a left over character will have to add a ? (This happens if they had a funky
+ // fallback last time, but not this time.) (We can't spit any out though
+ // because with fallback encoder each surrogate is treated as a seperate code point)
+ if (charLeftOver > 0)
+ {
+ // Have to have room
+ // Throw even if doing no throw version because this is just 1 char,
+ // so buffer will never be big enough
+ if (byteCount == 0)
+ ThrowBytesOverflow(encoder, true);
+
+ // This'll make sure we still have more room and also make sure our return value is correct.
+ *(bytes++) = (byte)cReplacement;
+ byteCount--; // We used one of the ones we were counting.
+ }
+
+ // This keeps us from overrunning our output buffer
+ if (byteCount < charCount)
+ {
+ // Throw or make buffer smaller?
+ ThrowBytesOverflow(encoder, byteCount < 1);
+
+ // Just use what we can
+ charEnd = chars + byteCount;
+ }
+
+ // We just do a quick copy
+ while (chars < charEnd)
+ {
+ char ch2 = *(chars++);
+ if (ch2 > 0x00ff) *(bytes++) = (byte)cReplacement;
+ else *(bytes++) = (byte)ch2;
+ }
+
+ // Clear encoder
+ if (encoder != null)
+ {
+ encoder.charLeftOver = (char)0;
+ encoder.m_charsUsed = (int)(chars-charStart);
+ }
+ return (int)(bytes - byteStart);
+ }
+ }
+
+ // Slower version, have to do real fallback.
+
+ // prepare our end
+ byte* byteEnd = bytes + byteCount;
+
+ // For fallback we may need a fallback buffer, we know we aren't default fallback, create & init it
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ Contract.Assert(encoder != null,
+ "[Latin1Encoding.GetBytes]Expected encoder if we have charLeftOver");
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
+
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ if (fallbackBuffer.Remaining > byteEnd - bytes)
+ {
+ // Throw it, if we don't have enough for this we never will
+ ThrowBytesOverflow(encoder, true);
+ }
+ }
+
+ // Now we may have fallback char[] already from the encoder fallback above
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ // All characters >= 0x100 must fall back.
+ if (ch > 0xff)
+ {
+ // Initialize the buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+
+ // Make sure we have enough room. Each fallback char will be 1 output char
+ // (or else cause a recursion exception)
+ if (fallbackBuffer.Remaining > byteEnd - bytes)
+ {
+ // Didn't use this char, throw it. Chars should've advanced by now
+ // If we had encoder fallback data it would've thrown before the loop
+ Contract.Assert(chars > charStart,
+ "[Latin1Encoding.GetBytes]Expected chars to have advanced (fallback case)");
+ chars--;
+ fallbackBuffer.InternalReset();
+
+ // Throw it
+ ThrowBytesOverflow(encoder, chars == charStart);
+ break;
+ }
+
+ continue;
+ }
+
+ // We'll use this one
+ // Bounds check
+ if (bytes >= byteEnd)
+ {
+ // didn't use this char, we'll throw or use buffer
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false,
+ "[Latin1Encoding.GetBytes]Expected fallback to have throw initially if insufficient space");
+ if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
+ {
+ Contract.Assert(chars > charStart,
+ "[Latin1Encoding.GetBytes]Expected chars to have advanced (fallback case)");
+ chars--; // don't use last char
+ }
+ ThrowBytesOverflow(encoder, chars == charStart); // throw ?
+ break; // don't throw, stop
+ }
+
+ // Go ahead and add it
+ *bytes = unchecked((byte)ch);
+ bytes++;
+ }
+
+ // Need to do encoder stuff
+ if (encoder != null)
+ {
+ // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
+ if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
+ // Clear it in case of MustFlush
+ encoder.charLeftOver = (char)0;
+
+ // Set our chars used count
+ encoder.m_charsUsed = (int)(chars - charStart);
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[Latin1Encoding.GetBytes]Expected Empty fallback buffer");
+
+ return (int)(bytes - byteStart);
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ {
+ // Just assert, we're called internally so these should be safe, checked already
+ Contract.Assert(bytes != null, "[Latin1Encoding.GetCharCount]bytes is null");
+ Contract.Assert(count >= 0, "[Latin1Encoding.GetCharCount]byteCount is negative");
+
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ // pairs and we don't have to fallback because all latin1Encoding code points are unicode
+ return count;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS decoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[Latin1Encoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[Latin1Encoding.GetChars]byteCount is negative");
+ Contract.Assert(chars != null, "[Latin1Encoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[Latin1Encoding.GetChars]charCount is negative");
+
+ // Need byteCount chars, otherwise too small buffer
+ if (charCount < byteCount)
+ {
+ // Buffer too small. Do we throw?
+ ThrowCharsOverflow(decoder, charCount < 1);
+
+ // Don't throw, correct buffer size
+ byteCount = charCount;
+ }
+
+ // Do it our fast way
+ byte* byteEnd = bytes + byteCount;
+
+ // Quick loop, all bytes are the same as chars, so no fallbacks for latin1
+ while (bytes < byteEnd)
+ {
+ *(chars) = unchecked((char)*(bytes));
+ chars++;
+ bytes++;
+ }
+
+ // Might need to know input bytes used
+ if (decoder != null)
+ decoder.m_bytesUsed = byteCount;
+
+ // Converted sequence is same length as input, so output charsUsed is same as byteCount;
+ return byteCount;
+ }
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less.
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ long charCount = (long)byteCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less, unknown fallbacks could be longer.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
+ public override bool IsSingleByte
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+#if !FEATURE_NORM_IDNA_ONLY
+ public override bool IsAlwaysNormalized(NormalizationForm form)
+ {
+ // Latin-1 contains precomposed characters, so normal for Form C.
+ // Since some are composed, not normal for D & KD.
+ // Also some letters like 0x00A8 (spacing diarisis) have compatibility decompositions, so false for KD & KC.
+
+ // Only true for form C.
+ return (form == NormalizationForm.FormC);
+ }
+#endif // !FEATURE_NORM_IDNA_ONLY
+ // Since our best fit table is small we'll hard code it
+ internal override char[] GetBestFitUnicodeToBytesData()
+ {
+ // Get our best fit data
+ return Latin1Encoding.arrayCharBestFit;
+ }
+
+ // Best fit for ASCII, and since it works for ASCII, we use it for latin1 as well.
+ private static readonly char[] arrayCharBestFit =
+ {
+// The first many are in case you wanted to use this for ASCIIEncoding, which we don't need to do any more.
+// (char)0x00a0, (char)0x0020, // No-Break Space -> Space
+// (char)0x00a1, (char)0x0021, // Inverted Exclamation Mark -> !
+// (char)0x00a2, (char)0x0063, // Cent Sign -> c
+// (char)0x00a3, (char)0x003f, // Pound Sign
+// (char)0x00a4, (char)0x0024, // Currency Sign -> $
+// (char)0x00a5, (char)0x0059, // Yen Sign -> Y
+// (char)0x00a6, (char)0x007c, // Broken Bar -> |
+// (char)0x00a7, (char)0x003f, // Section Sign
+// (char)0x00a8, (char)0x003f, // Diaeresis
+// (char)0x00a9, (char)0x0043, // Copyright Sign -> C
+// (char)0x00aa, (char)0x0061, // Feminine Ordinal Indicator -> a
+// (char)0x00ab, (char)0x003c, // Left-Pointing Double Angle Quotation Mark -> <
+// (char)0x00ac, (char)0x003f, // Not Sign
+// (char)0x00ad, (char)0x002d, // Soft Hyphen -> -
+// (char)0x00ae, (char)0x0052, // Registered Sign -> R
+// (char)0x00af, (char)0x003f, // Macron
+// (char)0x00b0, (char)0x003f, // Degree Sign
+// (char)0x00b1, (char)0x003f, // Plus-Minus Sign
+// (char)0x00b2, (char)0x0032, // Superscript Two -> 2
+// (char)0x00b3, (char)0x0033, // Superscript Three -> 3
+// (char)0x00b4, (char)0x003f, // Acute Accent
+// (char)0x00b5, (char)0x003f, // Micro Sign
+// (char)0x00b6, (char)0x003f, // Pilcrow Sign
+// (char)0x00b7, (char)0x002e, // Middle Dot -> .
+// (char)0x00b8, (char)0x002c, // Cedilla -> ,
+// (char)0x00b9, (char)0x0031, // Superscript One -> 1
+// (char)0x00ba, (char)0x006f, // Masculine Ordinal Indicator -> o
+// (char)0x00bb, (char)0x003e, // Right-Pointing Double Angle Quotation Mark -> >
+// (char)0x00bc, (char)0x003f, // Vulgar Fraction One Quarter
+// (char)0x00bd, (char)0x003f, // Vulgar Fraction One Half
+// (char)0x00be, (char)0x003f, // Vulgar Fraction Three Quarters
+// (char)0x00bf, (char)0x003f, // Inverted Question Mark
+// (char)0x00c0, (char)0x0041, // Latin Capital Letter A With Grave -> A
+// (char)0x00c1, (char)0x0041, // Latin Capital Letter A With Acute -> A
+// (char)0x00c2, (char)0x0041, // Latin Capital Letter A With Circumflex -> A
+// (char)0x00c3, (char)0x0041, // Latin Capital Letter A With Tilde -> A
+// (char)0x00c4, (char)0x0041, // Latin Capital Letter A With Diaeresis -> A
+// (char)0x00c5, (char)0x0041, // Latin Capital Letter A With Ring Above -> A
+// (char)0x00c6, (char)0x0041, // Latin Capital Ligature Ae -> A
+// (char)0x00c7, (char)0x0043, // Latin Capital Letter C With Cedilla -> C
+// (char)0x00c8, (char)0x0045, // Latin Capital Letter E With Grave -> E
+// (char)0x00c9, (char)0x0045, // Latin Capital Letter E With Acute -> E
+// (char)0x00ca, (char)0x0045, // Latin Capital Letter E With Circumflex -> E
+// (char)0x00cb, (char)0x0045, // Latin Capital Letter E With Diaeresis -> E
+// (char)0x00cc, (char)0x0049, // Latin Capital Letter I With Grave -> I
+// (char)0x00cd, (char)0x0049, // Latin Capital Letter I With Acute -> I
+// (char)0x00ce, (char)0x0049, // Latin Capital Letter I With Circumflex -> I
+// (char)0x00cf, (char)0x0049, // Latin Capital Letter I With Diaeresis -> I
+// (char)0x00d0, (char)0x0044, // Latin Capital Letter Eth -> D
+// (char)0x00d1, (char)0x004e, // Latin Capital Letter N With Tilde -> N
+// (char)0x00d2, (char)0x004f, // Latin Capital Letter O With Grave -> O
+// (char)0x00d3, (char)0x004f, // Latin Capital Letter O With Acute -> O
+// (char)0x00d4, (char)0x004f, // Latin Capital Letter O With Circumflex -> O
+// (char)0x00d5, (char)0x004f, // Latin Capital Letter O With Tilde -> O
+// (char)0x00d6, (char)0x004f, // Latin Capital Letter O With Diaeresis -> O
+// (char)0x00d7, (char)0x003f, // Multiplication Sign
+// (char)0x00d8, (char)0x004f, // Latin Capital Letter O With Stroke -> O
+// (char)0x00d9, (char)0x0055, // Latin Capital Letter U With Grave -> U
+// (char)0x00da, (char)0x0055, // Latin Capital Letter U With Acute -> U
+// (char)0x00db, (char)0x0055, // Latin Capital Letter U With Circumflex -> U
+// (char)0x00dc, (char)0x0055, // Latin Capital Letter U With Diaeresis -> U
+// (char)0x00dd, (char)0x0059, // Latin Capital Letter Y With Acute -> Y
+// (char)0x00de, (char)0x003f, // Latin Capital Letter Thorn
+// (char)0x00df, (char)0x003f, // Latin Small Letter Sharp S
+// (char)0x00e0, (char)0x0061, // Latin Small Letter A With Grave -> a
+// (char)0x00e1, (char)0x0061, // Latin Small Letter A With Acute -> a
+// (char)0x00e2, (char)0x0061, // Latin Small Letter A With Circumflex -> a
+// (char)0x00e3, (char)0x0061, // Latin Small Letter A With Tilde -> a
+// (char)0x00e4, (char)0x0061, // Latin Small Letter A With Diaeresis -> a
+// (char)0x00e5, (char)0x0061, // Latin Small Letter A With Ring Above -> a
+// (char)0x00e6, (char)0x0061, // Latin Small Ligature Ae -> a
+// (char)0x00e7, (char)0x0063, // Latin Small Letter C With Cedilla -> c
+// (char)0x00e8, (char)0x0065, // Latin Small Letter E With Grave -> e
+// (char)0x00e9, (char)0x0065, // Latin Small Letter E With Acute -> e
+// (char)0x00ea, (char)0x0065, // Latin Small Letter E With Circumflex -> e
+// (char)0x00eb, (char)0x0065, // Latin Small Letter E With Diaeresis -> e
+// (char)0x00ec, (char)0x0069, // Latin Small Letter I With Grave -> i
+// (char)0x00ed, (char)0x0069, // Latin Small Letter I With Acute -> i
+// (char)0x00ee, (char)0x0069, // Latin Small Letter I With Circumflex -> i
+// (char)0x00ef, (char)0x0069, // Latin Small Letter I With Diaeresis -> i
+// (char)0x00f0, (char)0x003f, // Latin Small Letter Eth
+// (char)0x00f1, (char)0x006e, // Latin Small Letter N With Tilde -> n
+// (char)0x00f2, (char)0x006f, // Latin Small Letter O With Grave -> o
+// (char)0x00f3, (char)0x006f, // Latin Small Letter O With Acute -> o
+// (char)0x00f4, (char)0x006f, // Latin Small Letter O With Circumflex -> o
+// (char)0x00f5, (char)0x006f, // Latin Small Letter O With Tilde -> o
+// (char)0x00f6, (char)0x006f, // Latin Small Letter O With Diaeresis -> o
+// (char)0x00f7, (char)0x003f, // Division Sign
+// (char)0x00f8, (char)0x006f, // Latin Small Letter O With Stroke -> o
+// (char)0x00f9, (char)0x0075, // Latin Small Letter U With Grave -> u
+// (char)0x00fa, (char)0x0075, // Latin Small Letter U With Acute -> u
+// (char)0x00fb, (char)0x0075, // Latin Small Letter U With Circumflex -> u
+// (char)0x00fc, (char)0x0075, // Latin Small Letter U With Diaeresis -> u
+// (char)0x00fd, (char)0x0079, // Latin Small Letter Y With Acute -> y
+// (char)0x00fe, (char)0x003f, // Latin Small Letter Thorn
+// (char)0x00ff, (char)0x0079, // Latin Small Letter Y With Diaeresis -> y
+ (char)0x0100, (char)0x0041, // Latin Capital Letter A With Macron -> A
+ (char)0x0101, (char)0x0061, // Latin Small Letter A With Macron -> a
+ (char)0x0102, (char)0x0041, // Latin Capital Letter A With Breve -> A
+ (char)0x0103, (char)0x0061, // Latin Small Letter A With Breve -> a
+ (char)0x0104, (char)0x0041, // Latin Capital Letter A With Ogonek -> A
+ (char)0x0105, (char)0x0061, // Latin Small Letter A With Ogonek -> a
+ (char)0x0106, (char)0x0043, // Latin Capital Letter C With Acute -> C
+ (char)0x0107, (char)0x0063, // Latin Small Letter C With Acute -> c
+ (char)0x0108, (char)0x0043, // Latin Capital Letter C With Circumflex -> C
+ (char)0x0109, (char)0x0063, // Latin Small Letter C With Circumflex -> c
+ (char)0x010a, (char)0x0043, // Latin Capital Letter C With Dot Above -> C
+ (char)0x010b, (char)0x0063, // Latin Small Letter C With Dot Above -> c
+ (char)0x010c, (char)0x0043, // Latin Capital Letter C With Caron -> C
+ (char)0x010d, (char)0x0063, // Latin Small Letter C With Caron -> c
+ (char)0x010e, (char)0x0044, // Latin Capital Letter D With Caron -> D
+ (char)0x010f, (char)0x0064, // Latin Small Letter D With Caron -> d
+ (char)0x0110, (char)0x0044, // Latin Capital Letter D With Stroke -> D
+ (char)0x0111, (char)0x0064, // Latin Small Letter D With Stroke -> d
+ (char)0x0112, (char)0x0045, // Latin Capital Letter E With Macron -> E
+ (char)0x0113, (char)0x0065, // Latin Small Letter E With Macron -> e
+ (char)0x0114, (char)0x0045, // Latin Capital Letter E With Breve -> E
+ (char)0x0115, (char)0x0065, // Latin Small Letter E With Breve -> e
+ (char)0x0116, (char)0x0045, // Latin Capital Letter E With Dot Above -> E
+ (char)0x0117, (char)0x0065, // Latin Small Letter E With Dot Above -> e
+ (char)0x0118, (char)0x0045, // Latin Capital Letter E With Ogonek -> E
+ (char)0x0119, (char)0x0065, // Latin Small Letter E With Ogonek -> e
+ (char)0x011a, (char)0x0045, // Latin Capital Letter E With Caron -> E
+ (char)0x011b, (char)0x0065, // Latin Small Letter E With Caron -> e
+ (char)0x011c, (char)0x0047, // Latin Capital Letter G With Circumflex -> G
+ (char)0x011d, (char)0x0067, // Latin Small Letter G With Circumflex -> g
+ (char)0x011e, (char)0x0047, // Latin Capital Letter G With Breve -> G
+ (char)0x011f, (char)0x0067, // Latin Small Letter G With Breve -> g
+ (char)0x0120, (char)0x0047, // Latin Capital Letter G With Dot Above -> G
+ (char)0x0121, (char)0x0067, // Latin Small Letter G With Dot Above -> g
+ (char)0x0122, (char)0x0047, // Latin Capital Letter G With Cedilla -> G
+ (char)0x0123, (char)0x0067, // Latin Small Letter G With Cedilla -> g
+ (char)0x0124, (char)0x0048, // Latin Capital Letter H With Circumflex -> H
+ (char)0x0125, (char)0x0068, // Latin Small Letter H With Circumflex -> h
+ (char)0x0126, (char)0x0048, // Latin Capital Letter H With Stroke -> H
+ (char)0x0127, (char)0x0068, // Latin Small Letter H With Stroke -> h
+ (char)0x0128, (char)0x0049, // Latin Capital Letter I With Tilde -> I
+ (char)0x0129, (char)0x0069, // Latin Small Letter I With Tilde -> i
+ (char)0x012a, (char)0x0049, // Latin Capital Letter I With Macron -> I
+ (char)0x012b, (char)0x0069, // Latin Small Letter I With Macron -> i
+ (char)0x012c, (char)0x0049, // Latin Capital Letter I With Breve -> I
+ (char)0x012d, (char)0x0069, // Latin Small Letter I With Breve -> i
+ (char)0x012e, (char)0x0049, // Latin Capital Letter I With Ogonek -> I
+ (char)0x012f, (char)0x0069, // Latin Small Letter I With Ogonek -> i
+ (char)0x0130, (char)0x0049, // Latin Capital Letter I With Dot Above -> I
+ (char)0x0131, (char)0x0069, // Latin Small Letter Dotless I -> i
+ (char)0x0134, (char)0x004a, // Latin Capital Letter J With Circumflex -> J
+ (char)0x0135, (char)0x006a, // Latin Small Letter J With Circumflex -> j
+ (char)0x0136, (char)0x004b, // Latin Capital Letter K With Cedilla -> K
+ (char)0x0137, (char)0x006b, // Latin Small Letter K With Cedilla -> k
+ (char)0x0139, (char)0x004c, // Latin Capital Letter L With Acute -> L
+ (char)0x013a, (char)0x006c, // Latin Small Letter L With Acute -> l
+ (char)0x013b, (char)0x004c, // Latin Capital Letter L With Cedilla -> L
+ (char)0x013c, (char)0x006c, // Latin Small Letter L With Cedilla -> l
+ (char)0x013d, (char)0x004c, // Latin Capital Letter L With Caron -> L
+ (char)0x013e, (char)0x006c, // Latin Small Letter L With Caron -> l
+ (char)0x0141, (char)0x004c, // Latin Capital Letter L With Stroke -> L
+ (char)0x0142, (char)0x006c, // Latin Small Letter L With Stroke -> l
+ (char)0x0143, (char)0x004e, // Latin Capital Letter N With Acute -> N
+ (char)0x0144, (char)0x006e, // Latin Small Letter N With Acute -> n
+ (char)0x0145, (char)0x004e, // Latin Capital Letter N With Cedilla -> N
+ (char)0x0146, (char)0x006e, // Latin Small Letter N With Cedilla -> n
+ (char)0x0147, (char)0x004e, // Latin Capital Letter N With Caron -> N
+ (char)0x0148, (char)0x006e, // Latin Small Letter N With Caron -> n
+ (char)0x014c, (char)0x004f, // Latin Capital Letter O With Macron -> O
+ (char)0x014d, (char)0x006f, // Latin Small Letter O With Macron -> o
+ (char)0x014e, (char)0x004f, // Latin Capital Letter O With Breve -> O
+ (char)0x014f, (char)0x006f, // Latin Small Letter O With Breve -> o
+ (char)0x0150, (char)0x004f, // Latin Capital Letter O With Double Acute -> O
+ (char)0x0151, (char)0x006f, // Latin Small Letter O With Double Acute -> o
+ (char)0x0152, (char)0x004f, // Latin Capital Ligature Oe -> O
+ (char)0x0153, (char)0x006f, // Latin Small Ligature Oe -> o
+ (char)0x0154, (char)0x0052, // Latin Capital Letter R With Acute -> R
+ (char)0x0155, (char)0x0072, // Latin Small Letter R With Acute -> r
+ (char)0x0156, (char)0x0052, // Latin Capital Letter R With Cedilla -> R
+ (char)0x0157, (char)0x0072, // Latin Small Letter R With Cedilla -> r
+ (char)0x0158, (char)0x0052, // Latin Capital Letter R With Caron -> R
+ (char)0x0159, (char)0x0072, // Latin Small Letter R With Caron -> r
+ (char)0x015a, (char)0x0053, // Latin Capital Letter S With Acute -> S
+ (char)0x015b, (char)0x0073, // Latin Small Letter S With Acute -> s
+ (char)0x015c, (char)0x0053, // Latin Capital Letter S With Circumflex -> S
+ (char)0x015d, (char)0x0073, // Latin Small Letter S With Circumflex -> s
+ (char)0x015e, (char)0x0053, // Latin Capital Letter S With Cedilla -> S
+ (char)0x015f, (char)0x0073, // Latin Small Letter S With Cedilla -> s
+ (char)0x0160, (char)0x0053, // Latin Capital Letter S With Caron -> S
+ (char)0x0161, (char)0x0073, // Latin Small Letter S With Caron -> s
+ (char)0x0162, (char)0x0054, // Latin Capital Letter T With Cedilla -> T
+ (char)0x0163, (char)0x0074, // Latin Small Letter T With Cedilla -> t
+ (char)0x0164, (char)0x0054, // Latin Capital Letter T With Caron -> T
+ (char)0x0165, (char)0x0074, // Latin Small Letter T With Caron -> t
+ (char)0x0166, (char)0x0054, // Latin Capital Letter T With Stroke -> T
+ (char)0x0167, (char)0x0074, // Latin Small Letter T With Stroke -> t
+ (char)0x0168, (char)0x0055, // Latin Capital Letter U With Tilde -> U
+ (char)0x0169, (char)0x0075, // Latin Small Letter U With Tilde -> u
+ (char)0x016a, (char)0x0055, // Latin Capital Letter U With Macron -> U
+ (char)0x016b, (char)0x0075, // Latin Small Letter U With Macron -> u
+ (char)0x016c, (char)0x0055, // Latin Capital Letter U With Breve -> U
+ (char)0x016d, (char)0x0075, // Latin Small Letter U With Breve -> u
+ (char)0x016e, (char)0x0055, // Latin Capital Letter U With Ring Above -> U
+ (char)0x016f, (char)0x0075, // Latin Small Letter U With Ring Above -> u
+ (char)0x0170, (char)0x0055, // Latin Capital Letter U With Double Acute -> U
+ (char)0x0171, (char)0x0075, // Latin Small Letter U With Double Acute -> u
+ (char)0x0172, (char)0x0055, // Latin Capital Letter U With Ogonek -> U
+ (char)0x0173, (char)0x0075, // Latin Small Letter U With Ogonek -> u
+ (char)0x0174, (char)0x0057, // Latin Capital Letter W With Circumflex -> W
+ (char)0x0175, (char)0x0077, // Latin Small Letter W With Circumflex -> w
+ (char)0x0176, (char)0x0059, // Latin Capital Letter Y With Circumflex -> Y
+ (char)0x0177, (char)0x0079, // Latin Small Letter Y With Circumflex -> y
+ (char)0x0178, (char)0x0059, // Latin Capital Letter Y With Diaeresis -> Y
+ (char)0x0179, (char)0x005a, // Latin Capital Letter Z With Acute -> Z
+ (char)0x017a, (char)0x007a, // Latin Small Letter Z With Acute -> z
+ (char)0x017b, (char)0x005a, // Latin Capital Letter Z With Dot Above -> Z
+ (char)0x017c, (char)0x007a, // Latin Small Letter Z With Dot Above -> z
+ (char)0x017d, (char)0x005a, // Latin Capital Letter Z With Caron -> Z
+ (char)0x017e, (char)0x007a, // Latin Small Letter Z With Caron -> z
+ (char)0x0180, (char)0x0062, // Latin Small Letter B With Stroke -> b
+ (char)0x0189, (char)0x0044, // Latin Capital Letter African D -> D
+ (char)0x0191, (char)0x0046, // Latin Capital Letter F With Hook -> F
+ (char)0x0192, (char)0x0066, // Latin Small Letter F With Hook -> f
+ (char)0x0197, (char)0x0049, // Latin Capital Letter I With Stroke -> I
+ (char)0x019a, (char)0x006c, // Latin Small Letter L With Bar -> l
+ (char)0x019f, (char)0x004f, // Latin Capital Letter O With Middle Tilde -> O
+ (char)0x01a0, (char)0x004f, // Latin Capital Letter O With Horn -> O
+ (char)0x01a1, (char)0x006f, // Latin Small Letter O With Horn -> o
+ (char)0x01ab, (char)0x0074, // Latin Small Letter T With Palatal Hook -> t
+ (char)0x01ae, (char)0x0054, // Latin Capital Letter T With Retroflex Hook -> T
+ (char)0x01af, (char)0x0055, // Latin Capital Letter U With Horn -> U
+ (char)0x01b0, (char)0x0075, // Latin Small Letter U With Horn -> u
+ (char)0x01b6, (char)0x007a, // Latin Small Letter Z With Stroke -> z
+ (char)0x01cd, (char)0x0041, // Latin Capital Letter A With Caron -> A
+ (char)0x01ce, (char)0x0061, // Latin Small Letter A With Caron -> a
+ (char)0x01cf, (char)0x0049, // Latin Capital Letter I With Caron -> I
+ (char)0x01d0, (char)0x0069, // Latin Small Letter I With Caron -> i
+ (char)0x01d1, (char)0x004f, // Latin Capital Letter O With Caron -> O
+ (char)0x01d2, (char)0x006f, // Latin Small Letter O With Caron -> o
+ (char)0x01d3, (char)0x0055, // Latin Capital Letter U With Caron -> U
+ (char)0x01d4, (char)0x0075, // Latin Small Letter U With Caron -> u
+ (char)0x01d5, (char)0x0055, // Latin Capital Letter U With Diaeresis And Macron -> U
+ (char)0x01d6, (char)0x0075, // Latin Small Letter U With Diaeresis And Macron -> u
+ (char)0x01d7, (char)0x0055, // Latin Capital Letter U With Diaeresis And Acute -> U
+ (char)0x01d8, (char)0x0075, // Latin Small Letter U With Diaeresis And Acute -> u
+ (char)0x01d9, (char)0x0055, // Latin Capital Letter U With Diaeresis And Caron -> U
+ (char)0x01da, (char)0x0075, // Latin Small Letter U With Diaeresis And Caron -> u
+ (char)0x01db, (char)0x0055, // Latin Capital Letter U With Diaeresis And Grave -> U
+ (char)0x01dc, (char)0x0075, // Latin Small Letter U With Diaeresis And Grave -> u
+ (char)0x01de, (char)0x0041, // Latin Capital Letter A With Diaeresis And Macron -> A
+ (char)0x01df, (char)0x0061, // Latin Small Letter A With Diaeresis And Macron -> a
+ (char)0x01e4, (char)0x0047, // Latin Capital Letter G With Stroke -> G
+ (char)0x01e5, (char)0x0067, // Latin Small Letter G With Stroke -> g
+ (char)0x01e6, (char)0x0047, // Latin Capital Letter G With Caron -> G
+ (char)0x01e7, (char)0x0067, // Latin Small Letter G With Caron -> g
+ (char)0x01e8, (char)0x004b, // Latin Capital Letter K With Caron -> K
+ (char)0x01e9, (char)0x006b, // Latin Small Letter K With Caron -> k
+ (char)0x01ea, (char)0x004f, // Latin Capital Letter O With Ogonek -> O
+ (char)0x01eb, (char)0x006f, // Latin Small Letter O With Ogonek -> o
+ (char)0x01ec, (char)0x004f, // Latin Capital Letter O With Ogonek And Macron -> O
+ (char)0x01ed, (char)0x006f, // Latin Small Letter O With Ogonek And Macron -> o
+ (char)0x01f0, (char)0x006a, // Latin Small Letter J With Caron -> j
+ (char)0x0261, (char)0x0067, // Latin Small Letter Script G -> g
+ (char)0x02b9, (char)0x0027, // Modifier Letter Prime -> '
+ (char)0x02ba, (char)0x0022, // Modifier Letter Double Prime -> "
+ (char)0x02bc, (char)0x0027, // Modifier Letter Apostrophe -> '
+ (char)0x02c4, (char)0x005e, // Modifier Letter Up Arrowhead -> ^
+ (char)0x02c6, (char)0x005e, // Modifier Letter Circumflex Accent -> ^
+ (char)0x02c8, (char)0x0027, // Modifier Letter Vertical Line -> '
+ (char)0x02c9, (char)0x003f, // Modifier Letter Macron
+ (char)0x02ca, (char)0x003f, // Modifier Letter Acute Accent
+ (char)0x02cb, (char)0x0060, // Modifier Letter Grave Accent -> `
+ (char)0x02cd, (char)0x005f, // Modifier Letter Low Macron -> _
+ (char)0x02da, (char)0x003f, // Ring Above
+ (char)0x02dc, (char)0x007e, // Small Tilde -> ~
+ (char)0x0300, (char)0x0060, // Combining Grave Accent -> `
+ (char)0x0302, (char)0x005e, // Combining Circumflex Accent -> ^
+ (char)0x0303, (char)0x007e, // Combining Tilde -> ~
+ (char)0x030e, (char)0x0022, // Combining Double Vertical Line Above -> "
+ (char)0x0331, (char)0x005f, // Combining Macron Below -> _
+ (char)0x0332, (char)0x005f, // Combining Low Line -> _
+ (char)0x2000, (char)0x0020, // En Quad
+ (char)0x2001, (char)0x0020, // Em Quad
+ (char)0x2002, (char)0x0020, // En Space
+ (char)0x2003, (char)0x0020, // Em Space
+ (char)0x2004, (char)0x0020, // Three-Per-Em Space
+ (char)0x2005, (char)0x0020, // Four-Per-Em Space
+ (char)0x2006, (char)0x0020, // Six-Per-Em Space
+ (char)0x2010, (char)0x002d, // Hyphen -> -
+ (char)0x2011, (char)0x002d, // Non-Breaking Hyphen -> -
+ (char)0x2013, (char)0x002d, // En Dash -> -
+ (char)0x2014, (char)0x002d, // Em Dash -> -
+ (char)0x2018, (char)0x0027, // Left Single Quotation Mark -> '
+ (char)0x2019, (char)0x0027, // Right Single Quotation Mark -> '
+ (char)0x201a, (char)0x002c, // Single Low-9 Quotation Mark -> ,
+ (char)0x201c, (char)0x0022, // Left Double Quotation Mark -> "
+ (char)0x201d, (char)0x0022, // Right Double Quotation Mark -> "
+ (char)0x201e, (char)0x0022, // Double Low-9 Quotation Mark -> "
+ (char)0x2020, (char)0x003f, // Dagger
+ (char)0x2021, (char)0x003f, // Double Dagger
+ (char)0x2022, (char)0x002e, // Bullet -> .
+ (char)0x2026, (char)0x002e, // Horizontal Ellipsis -> .
+ (char)0x2030, (char)0x003f, // Per Mille Sign
+ (char)0x2032, (char)0x0027, // Prime -> '
+ (char)0x2035, (char)0x0060, // Reversed Prime -> `
+ (char)0x2039, (char)0x003c, // Single Left-Pointing Angle Quotation Mark -> <
+ (char)0x203a, (char)0x003e, // Single Right-Pointing Angle Quotation Mark -> >
+ (char)0x2122, (char)0x0054, // Trade Mark Sign -> T
+ (char)0xff01, (char)0x0021, // Fullwidth Exclamation Mark -> !
+ (char)0xff02, (char)0x0022, // Fullwidth Quotation Mark -> "
+ (char)0xff03, (char)0x0023, // Fullwidth Number Sign -> #
+ (char)0xff04, (char)0x0024, // Fullwidth Dollar Sign -> $
+ (char)0xff05, (char)0x0025, // Fullwidth Percent Sign -> %
+ (char)0xff06, (char)0x0026, // Fullwidth Ampersand -> &
+ (char)0xff07, (char)0x0027, // Fullwidth Apostrophe -> '
+ (char)0xff08, (char)0x0028, // Fullwidth Left Parenthesis -> (
+ (char)0xff09, (char)0x0029, // Fullwidth Right Parenthesis -> )
+ (char)0xff0a, (char)0x002a, // Fullwidth Asterisk -> *
+ (char)0xff0b, (char)0x002b, // Fullwidth Plus Sign -> +
+ (char)0xff0c, (char)0x002c, // Fullwidth Comma -> ,
+ (char)0xff0d, (char)0x002d, // Fullwidth Hyphen-Minus -> -
+ (char)0xff0e, (char)0x002e, // Fullwidth Full Stop -> .
+ (char)0xff0f, (char)0x002f, // Fullwidth Solidus -> /
+ (char)0xff10, (char)0x0030, // Fullwidth Digit Zero -> 0
+ (char)0xff11, (char)0x0031, // Fullwidth Digit One -> 1
+ (char)0xff12, (char)0x0032, // Fullwidth Digit Two -> 2
+ (char)0xff13, (char)0x0033, // Fullwidth Digit Three -> 3
+ (char)0xff14, (char)0x0034, // Fullwidth Digit Four -> 4
+ (char)0xff15, (char)0x0035, // Fullwidth Digit Five -> 5
+ (char)0xff16, (char)0x0036, // Fullwidth Digit Six -> 6
+ (char)0xff17, (char)0x0037, // Fullwidth Digit Seven -> 7
+ (char)0xff18, (char)0x0038, // Fullwidth Digit Eight -> 8
+ (char)0xff19, (char)0x0039, // Fullwidth Digit Nine -> 9
+ (char)0xff1a, (char)0x003a, // Fullwidth Colon -> :
+ (char)0xff1b, (char)0x003b, // Fullwidth Semicolon -> ;
+ (char)0xff1c, (char)0x003c, // Fullwidth Less-Than Sign -> <
+ (char)0xff1d, (char)0x003d, // Fullwidth Equals Sign -> =
+ (char)0xff1e, (char)0x003e, // Fullwidth Greater-Than Sign -> >
+ (char)0xff1f, (char)0x003f, // Fullwidth Question Mark
+ (char)0xff20, (char)0x0040, // Fullwidth Commercial At -> @
+ (char)0xff21, (char)0x0041, // Fullwidth Latin Capital Letter A -> A
+ (char)0xff22, (char)0x0042, // Fullwidth Latin Capital Letter B -> B
+ (char)0xff23, (char)0x0043, // Fullwidth Latin Capital Letter C -> C
+ (char)0xff24, (char)0x0044, // Fullwidth Latin Capital Letter D -> D
+ (char)0xff25, (char)0x0045, // Fullwidth Latin Capital Letter E -> E
+ (char)0xff26, (char)0x0046, // Fullwidth Latin Capital Letter F -> F
+ (char)0xff27, (char)0x0047, // Fullwidth Latin Capital Letter G -> G
+ (char)0xff28, (char)0x0048, // Fullwidth Latin Capital Letter H -> H
+ (char)0xff29, (char)0x0049, // Fullwidth Latin Capital Letter I -> I
+ (char)0xff2a, (char)0x004a, // Fullwidth Latin Capital Letter J -> J
+ (char)0xff2b, (char)0x004b, // Fullwidth Latin Capital Letter K -> K
+ (char)0xff2c, (char)0x004c, // Fullwidth Latin Capital Letter L -> L
+ (char)0xff2d, (char)0x004d, // Fullwidth Latin Capital Letter M -> M
+ (char)0xff2e, (char)0x004e, // Fullwidth Latin Capital Letter N -> N
+ (char)0xff2f, (char)0x004f, // Fullwidth Latin Capital Letter O -> O
+ (char)0xff30, (char)0x0050, // Fullwidth Latin Capital Letter P -> P
+ (char)0xff31, (char)0x0051, // Fullwidth Latin Capital Letter Q -> Q
+ (char)0xff32, (char)0x0052, // Fullwidth Latin Capital Letter R -> R
+ (char)0xff33, (char)0x0053, // Fullwidth Latin Capital Letter S -> S
+ (char)0xff34, (char)0x0054, // Fullwidth Latin Capital Letter T -> T
+ (char)0xff35, (char)0x0055, // Fullwidth Latin Capital Letter U -> U
+ (char)0xff36, (char)0x0056, // Fullwidth Latin Capital Letter V -> V
+ (char)0xff37, (char)0x0057, // Fullwidth Latin Capital Letter W -> W
+ (char)0xff38, (char)0x0058, // Fullwidth Latin Capital Letter X -> X
+ (char)0xff39, (char)0x0059, // Fullwidth Latin Capital Letter Y -> Y
+ (char)0xff3a, (char)0x005a, // Fullwidth Latin Capital Letter Z -> Z
+ (char)0xff3b, (char)0x005b, // Fullwidth Left Square Bracket -> [
+ (char)0xff3c, (char)0x005c, // Fullwidth Reverse Solidus -> \
+ (char)0xff3d, (char)0x005d, // Fullwidth Right Square Bracket -> ]
+ (char)0xff3e, (char)0x005e, // Fullwidth Circumflex Accent -> ^
+ (char)0xff3f, (char)0x005f, // Fullwidth Low Line -> _
+ (char)0xff40, (char)0x0060, // Fullwidth Grave Accent -> `
+ (char)0xff41, (char)0x0061, // Fullwidth Latin Small Letter A -> a
+ (char)0xff42, (char)0x0062, // Fullwidth Latin Small Letter B -> b
+ (char)0xff43, (char)0x0063, // Fullwidth Latin Small Letter C -> c
+ (char)0xff44, (char)0x0064, // Fullwidth Latin Small Letter D -> d
+ (char)0xff45, (char)0x0065, // Fullwidth Latin Small Letter E -> e
+ (char)0xff46, (char)0x0066, // Fullwidth Latin Small Letter F -> f
+ (char)0xff47, (char)0x0067, // Fullwidth Latin Small Letter G -> g
+ (char)0xff48, (char)0x0068, // Fullwidth Latin Small Letter H -> h
+ (char)0xff49, (char)0x0069, // Fullwidth Latin Small Letter I -> i
+ (char)0xff4a, (char)0x006a, // Fullwidth Latin Small Letter J -> j
+ (char)0xff4b, (char)0x006b, // Fullwidth Latin Small Letter K -> k
+ (char)0xff4c, (char)0x006c, // Fullwidth Latin Small Letter L -> l
+ (char)0xff4d, (char)0x006d, // Fullwidth Latin Small Letter M -> m
+ (char)0xff4e, (char)0x006e, // Fullwidth Latin Small Letter N -> n
+ (char)0xff4f, (char)0x006f, // Fullwidth Latin Small Letter O -> o
+ (char)0xff50, (char)0x0070, // Fullwidth Latin Small Letter P -> p
+ (char)0xff51, (char)0x0071, // Fullwidth Latin Small Letter Q -> q
+ (char)0xff52, (char)0x0072, // Fullwidth Latin Small Letter R -> r
+ (char)0xff53, (char)0x0073, // Fullwidth Latin Small Letter S -> s
+ (char)0xff54, (char)0x0074, // Fullwidth Latin Small Letter T -> t
+ (char)0xff55, (char)0x0075, // Fullwidth Latin Small Letter U -> u
+ (char)0xff56, (char)0x0076, // Fullwidth Latin Small Letter V -> v
+ (char)0xff57, (char)0x0077, // Fullwidth Latin Small Letter W -> w
+ (char)0xff58, (char)0x0078, // Fullwidth Latin Small Letter X -> x
+ (char)0xff59, (char)0x0079, // Fullwidth Latin Small Letter Y -> y
+ (char)0xff5a, (char)0x007a, // Fullwidth Latin Small Letter Z -> z
+ (char)0xff5b, (char)0x007b, // Fullwidth Left Curly Bracket -> {
+ (char)0xff5c, (char)0x007c, // Fullwidth Vertical Line -> |
+ (char)0xff5d, (char)0x007d, // Fullwidth Right Curly Bracket -> }
+ (char)0xff5e, (char)0x007e // Fullwidth Tilde -> ~
+ };
+ }
+}
diff --git a/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs b/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs
new file mode 100644
index 0000000000..53924a936d
--- /dev/null
+++ b/src/mscorlib/src/System/Text/MLangCodePageEncoding.cs
@@ -0,0 +1,177 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// WARNING:
+//
+// This is just an IObjectReference proxy for the former MLang Encodings (V1.1)
+// We keep the old name now even for the Whidbey V2.0 IObjectReference because it also
+// works with the Everett V1.1 version.
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ /*=================================MLangCodePageEncoding==================================
+ ** This class is here only to deserialize the MLang classes from Everett (V1.1) into
+ ** Appropriate Whidbey (V2.0) objects. We also serialize the Whidbey classes
+ ** using this proxy since we pretty much need one anyway and that solves Whidbey
+ ** to Everett compatibility as well.
+ ==============================================================================*/
+
+ [Serializable]
+ internal sealed class MLangCodePageEncoding : IObjectReference, ISerializable
+ {
+ // Temp stuff
+ [NonSerialized]
+ private int m_codePage;
+ [NonSerialized]
+ private bool m_isReadOnly;
+ [NonSerialized]
+ private bool m_deserializedFromEverett = false;
+
+ [NonSerialized]
+ private EncoderFallback encoderFallback = null;
+ [NonSerialized]
+ private DecoderFallback decoderFallback = null;
+
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization.
+ internal MLangCodePageEncoding(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All versions have a code page
+ this.m_codePage = (int)info.GetValue("m_codePage", typeof(int));
+
+ // See if we have a code page
+ try
+ {
+ //
+ // Try Whidbey V2.0 Fields
+ //
+ this.m_isReadOnly = (bool)info.GetValue("m_isReadOnly", typeof(bool));
+
+ this.encoderFallback = (EncoderFallback)info.GetValue("encoderFallback", typeof(EncoderFallback));
+ this.decoderFallback = (DecoderFallback)info.GetValue("decoderFallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ //
+ // Didn't have Whidbey things, must be Everett
+ //
+ this.m_deserializedFromEverett = true;
+
+ // May as well be read only
+ this.m_isReadOnly = true;
+ }
+ }
+
+ // Just get it from GetEncoding
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ // Get our encoding (Note: This has default fallbacks for readonly and everett cases)
+ this.realEncoding = Encoding.GetEncoding(this.m_codePage);
+
+ // If its read only then it uses default fallbacks, otherwise pick up the new ones
+ // Otherwise we want to leave the new one read only
+ if (!this.m_deserializedFromEverett && !this.m_isReadOnly)
+ {
+ this.realEncoding = (Encoding)this.realEncoding.Clone();
+ this.realEncoding.EncoderFallback = this.encoderFallback;
+ this.realEncoding.DecoderFallback = this.decoderFallback;
+ }
+
+ return this.realEncoding;
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding ISerializable.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+
+// Same problem with the Encoder, this only happens with Everett Encoders
+ [Serializable]
+ internal sealed class MLangEncoder : IObjectReference, ISerializable
+ {
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal MLangEncoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ this.realEncoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding));
+ }
+
+ // Just get it from GetEncoder
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ return this.realEncoding.GetEncoder();
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangEncoder.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+ }
+
+
+ // Same problem with the Decoder, this only happens with Everett Decoders
+ [Serializable]
+ internal sealed class MLangDecoder : IObjectReference, ISerializable
+ {
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal MLangDecoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ this.realEncoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding));
+ }
+
+ // Just get it from GetDecoder
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ return this.realEncoding.GetDecoder();
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to MLangCodePageEncoding.MLangDecoder.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/Normalization.cs b/src/mscorlib/src/System/Text/Normalization.cs
new file mode 100644
index 0000000000..ce3c0c8e32
--- /dev/null
+++ b/src/mscorlib/src/System/Text/Normalization.cs
@@ -0,0 +1,350 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ using System;
+ using System.Security;
+ using System.Globalization;
+ using System.Text;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ // This is the enumeration for Normalization Forms
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum NormalizationForm
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ FormC = 1,
+ FormD = 2,
+ FormKC = 5,
+ FormKD = 6
+#endif // !FEATURE_NORM_IDNA_ONLY
+ }
+
+ internal enum ExtendedNormalizationForms
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ FormC = 1,
+ FormD = 2,
+ FormKC = 5,
+ FormKD = 6,
+#endif // !FEATURE_NORM_IDNA_ONLY
+ FormIdna = 0xd,
+#if !FEATURE_NORM_IDNA_ONLY
+ FormCDisallowUnassigned = 0x101,
+ FormDDisallowUnassigned = 0x102,
+ FormKCDisallowUnassigned = 0x105,
+ FormKDDisallowUnassigned = 0x106,
+#endif // !FEATURE_NORM_IDNA_ONLY
+ FormIdnaDisallowUnassigned = 0x10d
+ }
+
+ // This internal class wraps up our normalization behavior
+
+ internal class Normalization
+ {
+ //
+ // Flags that track whether given normalization form was initialized
+ //
+#if !FEATURE_NORM_IDNA_ONLY
+ private static volatile bool NFC;
+ private static volatile bool NFD;
+ private static volatile bool NFKC;
+ private static volatile bool NFKD;
+#endif // !FEATURE_NORM_IDNA_ONLY
+ private static volatile bool IDNA;
+#if !FEATURE_NORM_IDNA_ONLY
+ private static volatile bool NFCDisallowUnassigned;
+ private static volatile bool NFDDisallowUnassigned;
+ private static volatile bool NFKCDisallowUnassigned;
+ private static volatile bool NFKDDisallowUnassigned;
+#endif // !FEATURE_NORM_IDNA_ONLY
+ private static volatile bool IDNADisallowUnassigned;
+ private static volatile bool Other;
+
+ // These are error codes we get back from the Normalization DLL
+ private const int ERROR_SUCCESS = 0;
+ private const int ERROR_NOT_ENOUGH_MEMORY = 8;
+ private const int ERROR_INVALID_PARAMETER = 87;
+ private const int ERROR_INSUFFICIENT_BUFFER = 122;
+ private const int ERROR_NO_UNICODE_TRANSLATION = 1113;
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private unsafe void InitializeForm(NormalizationForm form, String strDataFile)
+ {
+#if FEATURE_COREFX_GLOBALIZATION
+ //TODO: Implement this fully. We might need a PAL here.
+ throw new NotImplementedException();
+#else
+ byte* pTables = null;
+
+ // Normalization uses OS on Win8
+ if (!Environment.IsWindows8OrAbove)
+ {
+ if (strDataFile == null)
+ {
+ // They were supposed to have a form that we know about!
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidNormalizationForm"));
+ }
+
+ // Tell the DLL where to find our data
+ pTables = GlobalizationAssembly.GetGlobalizationResourceBytePtr(
+ typeof(Normalization).Assembly, strDataFile);
+ if (pTables == null)
+ {
+ // Unable to load the specified normalizationForm,
+ // tables not loaded from file
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidNormalizationForm"));
+ }
+ }
+
+ nativeNormalizationInitNormalization(form, pTables);
+#endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ static private void EnsureInitialized(NormalizationForm form)
+ {
+ switch ((ExtendedNormalizationForms)form)
+ {
+#if !FEATURE_NORM_IDNA_ONLY
+ case ExtendedNormalizationForms.FormC:
+ if (NFC) return;
+ InitializeForm(form, "normnfc.nlp");
+ NFC = true;
+ break;
+
+ case ExtendedNormalizationForms.FormD:
+ if (NFD) return;
+ InitializeForm(form, "normnfd.nlp");
+ NFD = true;
+ break;
+
+ case ExtendedNormalizationForms.FormKC:
+ if (NFKC) return;
+ InitializeForm(form, "normnfkc.nlp");
+ NFKC = true;
+ break;
+
+ case ExtendedNormalizationForms.FormKD:
+ if (NFKD) return;
+ InitializeForm(form, "normnfkd.nlp");
+ NFKD = true;
+ break;
+#endif // !FEATURE_NORM_IDNA_ONLY
+
+ case ExtendedNormalizationForms.FormIdna:
+ if (IDNA) return;
+ InitializeForm(form, "normidna.nlp");
+ IDNA = true;
+ break;
+
+#if !FEATURE_NORM_IDNA_ONLY
+ case ExtendedNormalizationForms.FormCDisallowUnassigned:
+ if (NFCDisallowUnassigned) return;
+ InitializeForm(form, "normnfc.nlp");
+ NFCDisallowUnassigned = true;
+ break;
+
+ case ExtendedNormalizationForms.FormDDisallowUnassigned:
+ if (NFDDisallowUnassigned) return;
+ InitializeForm(form, "normnfd.nlp");
+ NFDDisallowUnassigned = true;
+ break;
+
+ case ExtendedNormalizationForms.FormKCDisallowUnassigned:
+ if (NFKCDisallowUnassigned) return;
+ InitializeForm(form, "normnfkc.nlp");
+ NFKCDisallowUnassigned = true;
+ break;
+
+ case ExtendedNormalizationForms.FormKDDisallowUnassigned:
+ if (NFKDDisallowUnassigned) return;
+ InitializeForm(form, "normnfkd.nlp");
+ NFKDDisallowUnassigned = true;
+ break;
+#endif // !FEATURE_NORM_IDNA_ONLY
+
+ case ExtendedNormalizationForms.FormIdnaDisallowUnassigned:
+ if (IDNADisallowUnassigned) return;
+ InitializeForm(form, "normidna.nlp");
+ IDNADisallowUnassigned = true;
+ break;
+
+ default:
+ if (Other) return;
+ InitializeForm(form, null);
+ Other = true;
+ break;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ internal static bool IsNormalized(String strInput, NormalizationForm normForm)
+ {
+ Contract.Requires(strInput != null);
+
+ EnsureInitialized(normForm);
+
+ int iError = ERROR_SUCCESS;
+ bool result = nativeNormalizationIsNormalizedString(
+ normForm,
+ ref iError,
+ strInput,
+ strInput.Length);
+
+ switch(iError)
+ {
+ // Success doesn't need to do anything
+ case ERROR_SUCCESS:
+ break;
+
+ // Do appropriate stuff for the individual errors:
+ case ERROR_INVALID_PARAMETER:
+ case ERROR_NO_UNICODE_TRANSLATION:
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ),
+ "strInput");
+ case ERROR_NOT_ENOUGH_MEMORY:
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+ default:
+ throw new InvalidOperationException(
+ Environment.GetResourceString("UnknownError_Num", iError));
+ }
+
+ return result;
+ }
+
+ [System.Security.SecurityCritical]
+ internal static String Normalize(String strInput, NormalizationForm normForm)
+ {
+ Contract.Requires(strInput != null);
+
+ EnsureInitialized(normForm);
+
+ int iError = ERROR_SUCCESS;
+
+ // Guess our buffer size first
+ int iLength = nativeNormalizationNormalizeString(normForm, ref iError, strInput, strInput.Length, null, 0);
+
+ // Could have an error (actually it'd be quite hard to have an error here)
+ if (iError != ERROR_SUCCESS)
+ {
+ if (iError == ERROR_INVALID_PARAMETER)
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex" ),
+ "strInput");
+
+ // We shouldn't really be able to get here..., guessing length is
+ // a trivial math function...
+ // Can't really be Out of Memory, but just in case:
+ if (iError == ERROR_NOT_ENOUGH_MEMORY)
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+
+ // Who knows what happened? Not us!
+ throw new InvalidOperationException(
+ Environment.GetResourceString("UnknownError_Num", iError));
+ }
+
+ // Don't break for empty strings (only possible for D & KD and not really possible at that)
+ if (iLength == 0) return String.Empty;
+
+ // Someplace to stick our buffer
+ char[] cBuffer = null;
+
+ for (;;)
+ {
+ // (re)allocation buffer and normalize string
+ cBuffer = new char[iLength];
+
+ iLength = nativeNormalizationNormalizeString(
+ normForm,
+ ref iError,
+ strInput,
+ strInput.Length,
+ cBuffer,
+ cBuffer.Length);
+
+ if (iError == ERROR_SUCCESS)
+ break;
+
+ // Could have an error (actually it'd be quite hard to have an error here)
+ switch(iError)
+ {
+ // Do appropriate stuff for the individual errors:
+ case ERROR_INSUFFICIENT_BUFFER:
+ Contract.Assert(iLength > cBuffer.Length, "Buffer overflow should have iLength > cBuffer.Length");
+ continue;
+
+ case ERROR_INVALID_PARAMETER:
+ case ERROR_NO_UNICODE_TRANSLATION:
+ // Illegal code point or order found. Ie: FFFE or D800 D800, etc.
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_InvalidCharSequence", iLength ),
+ "strInput");
+ case ERROR_NOT_ENOUGH_MEMORY:
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+
+ default:
+ // We shouldn't get here...
+ throw new InvalidOperationException(
+ Environment.GetResourceString("UnknownError_Num", iError));
+ }
+ }
+
+ // Copy our buffer into our new string, which will be the appropriate size
+ return new String(cBuffer, 0, iLength);
+ }
+
+#if !FEATURE_COREFX_GLOBALIZATION
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe private static extern int nativeNormalizationNormalizeString(
+ NormalizationForm normForm, ref int iError,
+ String lpSrcString, int cwSrcLength,
+ char[] lpDstString, int cwDstLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe private static extern bool nativeNormalizationIsNormalizedString(
+ NormalizationForm normForm, ref int iError,
+ String lpString, int cwLength);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [SuppressUnmanagedCodeSecurity]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ unsafe private static extern void nativeNormalizationInitNormalization(
+ NormalizationForm normForm, byte* pTableData);
+#else
+ unsafe private static int nativeNormalizationNormalizeString(
+ NormalizationForm normForm, ref int iError,
+ String lpSrcString, int cwSrcLength,
+ char[] lpDstString, int cwDstLength)
+ {
+ throw new NotImplementedException();
+ }
+
+ unsafe private static bool nativeNormalizationIsNormalizedString(
+ NormalizationForm normForm, ref int iError,
+ String lpString, int cwLength)
+ {
+ throw new NotImplementedException();
+ }
+
+ unsafe private static void nativeNormalizationInitNormalization(
+ NormalizationForm normForm, byte* pTableData)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs b/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs
new file mode 100644
index 0000000000..ce611d8b1f
--- /dev/null
+++ b/src/mscorlib/src/System/Text/SBCSCodePageEncoding.cs
@@ -0,0 +1,1020 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#if FEATURE_CODEPAGES_FILE // requires BaseCodePageEncooding
+namespace System.Text
+{
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using System.Threading;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+
+ // SBCSCodePageEncoding
+ [Serializable]
+ internal class SBCSCodePageEncoding : BaseCodePageEncoding, ISerializable
+ {
+ // Pointers to our memory section parts
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe char* mapBytesToUnicode = null; // char 256
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe byte* mapUnicodeToBytes = null; // byte 65536
+ [NonSerialized]
+ [SecurityCritical]
+ unsafe int* mapCodePageCached = null; // to remember which CP is cached
+
+ const char UNKNOWN_CHAR=(char)0xFFFD;
+
+ // byteUnknown is used for default fallback only
+ [NonSerialized]
+ byte byteUnknown;
+ [NonSerialized]
+ char charUnknown;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public SBCSCodePageEncoding(int codePage) : this(codePage, codePage)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal SBCSCodePageEncoding(int codePage, int dataCodePage) : base(codePage, dataCodePage)
+ {
+ }
+
+ // Constructor called by serialization.
+ // Note: We use the base GetObjectData however
+ [System.Security.SecurityCritical] // auto-generated
+ internal SBCSCodePageEncoding(SerializationInfo info, StreamingContext context) : base(0)
+ {
+ // Actually this can't ever get called, CodePageEncoding is our proxy
+ Contract.Assert(false, "Didn't expect to make it to SBCSCodePageEncoding serialization constructor");
+ throw new ArgumentNullException("this");
+ }
+
+ // We have a managed code page entry, so load our tables
+ // SBCS data section looks like:
+ //
+ // char[256] - what each byte maps to in unicode. No support for surrogates. 0 is undefined code point
+ // (except 0 for byte 0 is expected to be a real 0)
+ //
+ // byte/char* - Data for best fit (unicode->bytes), again no best fit for Unicode
+ // 1st WORD is Unicode // of 1st character position
+ // Next bytes are best fit byte for that position. Position is incremented after each byte
+ // byte < 0x20 means skip the next n positions. (Where n is the byte #)
+ // byte == 1 means that next word is another unicode code point #
+ // byte == 0 is unknown. (doesn't override initial WCHAR[256] table!
+ [System.Security.SecurityCritical] // auto-generated
+ protected override unsafe void LoadManagedCodePage()
+ {
+ // Should be loading OUR code page
+ Contract.Assert(pCodePage->CodePage == this.dataTableCodePage,
+ "[SBCSCodePageEncoding.LoadManagedCodePage]Expected to load data table code page");
+
+ // Make sure we're really a 1 byte code page
+ if (pCodePage->ByteCount != 1)
+ throw new NotSupportedException(
+ Environment.GetResourceString("NotSupported_NoCodepageData", CodePage));
+
+ // Remember our unknown bytes & chars
+ byteUnknown = (byte)pCodePage->ByteReplace;
+ charUnknown = pCodePage->UnicodeReplace;
+
+ // Get our mapped section 65536 bytes for unicode->bytes, 256 * 2 bytes for bytes->unicode
+ // Plus 4 byte to remember CP # when done loading it. (Don't want to get IA64 or anything out of alignment)
+ byte *pMemorySection = GetSharedMemory(65536*1 + 256*2 + 4 + iExtraBytes);
+
+ mapBytesToUnicode = (char*)pMemorySection;
+ mapUnicodeToBytes = (byte*)(pMemorySection + 256 * 2);
+ mapCodePageCached = (int*)(pMemorySection + 256 * 2 + 65536 * 1 + iExtraBytes);
+
+ // If its cached (& filled in) we don't have to do anything else
+ if (*mapCodePageCached != 0)
+ {
+ Contract.Assert(*mapCodePageCached == this.dataTableCodePage,
+ "[DBCSCodePageEncoding.LoadManagedCodePage]Expected mapped section cached page to be same as data table code page. Cached : " +
+ *mapCodePageCached + " Expected:" + this.dataTableCodePage);
+
+ if (*mapCodePageCached != this.dataTableCodePage)
+ throw new OutOfMemoryException(
+ Environment.GetResourceString("Arg_OutOfMemoryException"));
+
+ // If its cached (& filled in) we don't have to do anything else
+ return;
+ }
+
+ // Need to read our data file and fill in our section.
+ // WARNING: Multiple code pieces could do this at once (so we don't have to lock machine-wide)
+ // so be careful here. Only stick legal values in here, don't stick temporary values.
+
+ // Read our data file and set mapBytesToUnicode and mapUnicodeToBytes appropriately
+ // First table is just all 256 mappings
+ char* pTemp = (char*)&(pCodePage->FirstDataWord);
+ for (int b = 0; b < 256; b++)
+ {
+ // Don't want to force 0's to map Unicode wrong. 0 byte == 0 unicode already taken care of
+ if (pTemp[b] != 0 || b == 0)
+ {
+ mapBytesToUnicode[b] = pTemp[b];
+
+ if (pTemp[b] != UNKNOWN_CHAR)
+ mapUnicodeToBytes[pTemp[b]] = (byte)b;
+ }
+ else
+ {
+ mapBytesToUnicode[b] = UNKNOWN_CHAR;
+ }
+ }
+
+ // We're done with our mapped section, set our flag so others don't have to rebuild table.
+ *mapCodePageCached = this.dataTableCodePage;
+ }
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject
+ {
+ get
+ {
+ if (s_InternalSyncObject == null)
+ {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+ // Read in our best fit table
+ [System.Security.SecurityCritical] // auto-generated
+ protected unsafe override void ReadBestFitTable()
+ {
+ // Lock so we don't confuse ourselves.
+ lock(InternalSyncObject)
+ {
+ // If we got a best fit array already, then don't do this
+ if (arrayUnicodeBestFit == null)
+ {
+ //
+ // Read in Best Fit table.
+ //
+
+ // First check the SBCS->Unicode best fit table, which starts right after the
+ // 256 word data table. This table looks like word, word where 1st word is byte and 2nd
+ // word is replacement for that word. It ends when byte == 0.
+ byte* pData = (byte*)&(pCodePage->FirstDataWord);
+ pData += 512;
+
+ // Need new best fit array
+ char[] arrayTemp = new char[256];
+ for (int i = 0; i < 256; i++)
+ arrayTemp[i] = mapBytesToUnicode[i];
+
+ // See if our words are zero
+ ushort byteTemp;
+ while ((byteTemp = *((ushort*)pData)) != 0)
+ {
+
+ Contract.Assert(arrayTemp[byteTemp] == UNKNOWN_CHAR, String.Format(CultureInfo.InvariantCulture,
+ "[SBCSCodePageEncoding::ReadBestFitTable] Expected unallocated byte (not 0x{2:X2}) for best fit byte at 0x{0:X2} for code page {1}",
+ byteTemp, CodePage, (int)arrayTemp[byteTemp]));
+ pData += 2;
+
+ arrayTemp[byteTemp] = *((char*)pData);
+ pData += 2;
+ }
+
+ // Remember our new array
+ arrayBytesBestFit = arrayTemp;
+
+ // It was on 0, it needs to be on next byte
+ pData+=2;
+ byte* pUnicodeToSBCS = pData;
+
+ // Now count our characters from our Unicode->SBCS best fit table,
+ // which is right after our 256 byte data table
+ int iBestFitCount = 0;
+
+ // Now do the UnicodeToBytes Best Fit mapping (this is the one we normally think of when we say "best fit")
+ // pData should be pointing at the first data point for Bytes->Unicode table
+ int unicodePosition = *((ushort*)pData);
+ pData += 2;
+
+ while (unicodePosition < 0x10000)
+ {
+ // Get the next byte
+ byte input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next 2 bytes as our byte position
+ unicodePosition = *((ushort*)pData);
+ pData+=2;
+ }
+ else if (input < 0x20 && input > 0 && input != 0x1e)
+ {
+ // Advance input characters
+ unicodePosition += input;
+ }
+ else
+ {
+ // Use this character if it isn't zero
+ if (input > 0)
+ iBestFitCount++;
+
+ // skip this unicode position in any case
+ unicodePosition++;
+ }
+ }
+
+ // Make an array for our best fit data
+ arrayTemp = new char[iBestFitCount*2];
+
+ // Now actually read in the data
+ // reset pData should be pointing at the first data point for Bytes->Unicode table
+ pData = pUnicodeToSBCS;
+ unicodePosition = *((ushort*)pData);
+ pData += 2;
+ iBestFitCount = 0;
+
+ while (unicodePosition < 0x10000)
+ {
+ // Get the next byte
+ byte input = *pData;
+ pData++;
+
+ // build our table:
+ if (input == 1)
+ {
+ // Use next 2 bytes as our byte position
+ unicodePosition = *((ushort*)pData);
+ pData+=2;
+ }
+ else if (input < 0x20 && input > 0 && input != 0x1e)
+ {
+ // Advance input characters
+ unicodePosition += input;
+ }
+ else
+ {
+ // Check for escape for glyph range
+ if (input == 0x1e)
+ {
+ // Its an escape, so just read next byte directly
+ input = *pData;
+ pData++;
+ }
+
+ // 0 means just skip me
+ if (input > 0)
+ {
+ // Use this character
+ arrayTemp[iBestFitCount++] = (char)unicodePosition;
+ // Have to map it to Unicode because best fit will need unicode value of best fit char.
+ arrayTemp[iBestFitCount++] = mapBytesToUnicode[input];
+
+ // This won't work if it won't round trip.
+ Contract.Assert(arrayTemp[iBestFitCount-1] != (char)0,
+ String.Format(CultureInfo.InvariantCulture,
+ "[SBCSCodePageEncoding.ReadBestFitTable] No valid Unicode value {0:X4} for round trip bytes {1:X4}, encoding {2}",
+ (int)mapBytesToUnicode[input], (int)input, CodePage));
+ }
+ unicodePosition++;
+ }
+ }
+
+ // Remember it
+ arrayUnicodeBestFit = arrayTemp;
+ }
+ }
+ }
+
+ // GetByteCount
+ // Note: We start by assuming that the output will be the same as count. Having
+ // an encoder or fallback may change that assumption
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(count >= 0, "[SBCSCodePageEncoding.GetByteCount]count is negative");
+ Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetByteCount]chars is null");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetByteCount]Attempting to use null fallback");
+
+ CheckMemorySection();
+
+ // Need to test fallback
+ EncoderReplacementFallback fallback = null;
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[SBCSCodePageEncoding.GetByteCount]leftover character should be high surrogate");
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+
+ // Verify that we have no fallbackbuffer, actually for SBCS this is always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[SBCSCodePageEncoding.GetByteCount]Expected empty fallback buffer at start");
+ }
+ else
+ {
+ // If we aren't using default fallback then we may have a complicated count.
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+ }
+
+ if ((fallback != null && fallback.MaxCharCount == 1)/* || bIsBestFit*/)
+ {
+ // Replacement fallback encodes surrogate pairs as two ?? (or two whatever), so return size is always
+ // same as input size.
+ // Note that no existing SBCS code pages map code points to supplimentary characters, so this is easy.
+
+ // We could however have 1 extra byte if the last call had an encoder and a funky fallback and
+ // if we don't use the funky fallback this time.
+
+ // Do we have an extra char left over from last time?
+ if (charLeftOver > 0)
+ count++;
+
+ return (count);
+ }
+
+ // It had a funky fallback, so its more complicated
+ // Need buffer maybe later
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // prepare our end
+ int byteCount = 0;
+ char* charEnd = chars + count;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetByteCount]Expect to have encoder if we have a charLeftOver");
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, false);
+
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ }
+
+ // Now we may have fallback char[] already from the encoder
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // get byte for this char
+ byte bTemp = mapUnicodeToBytes[ch];
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ if (bTemp == 0 && ch != (char)0)
+ {
+ if (fallbackBuffer == null)
+ {
+ // Create & init fallback buffer
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // chars has moved so we need to remember figure it out so Exception fallback
+ // index will be correct
+ fallbackBuffer.InternalInitialize(charEnd - count, charEnd, encoder, false);
+ }
+
+ // Get Fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // We'll use this one
+ byteCount++;
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[SBCSEncoding.GetByteCount]Expected Empty fallback buffer at end");
+
+ return (int)byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetBytes]bytes is null");
+ Contract.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetBytes]byteCount is negative");
+ Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetBytes]chars is null");
+ Contract.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetBytes]charCount is negative");
+
+ // Assert because we shouldn't be able to have a null encoder.
+ Contract.Assert(encoderFallback != null, "[SBCSCodePageEncoding.GetBytes]Attempting to use null encoder fallback");
+
+ CheckMemorySection();
+
+ // Need to test fallback
+ EncoderReplacementFallback fallback = null;
+
+ // Get any left over characters
+ char charLeftOver = (char)0;
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+ Contract.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ "[SBCSCodePageEncoding.GetBytes]leftover character should be high surrogate");
+ fallback = encoder.Fallback as EncoderReplacementFallback;
+
+ // Verify that we have no fallbackbuffer, for SBCS its always empty, so just assert
+ Contract.Assert(!encoder.m_throwOnOverflow || !encoder.InternalHasFallbackBuffer ||
+ encoder.FallbackBuffer.Remaining == 0,
+ "[SBCSCodePageEncoding.GetBytes]Expected empty fallback buffer at start");
+// if (encoder.m_throwOnOverflow && encoder.InternalHasFallbackBuffer &&
+// encoder.FallbackBuffer.Remaining > 0)
+// throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+// this.EncodingName, encoder.Fallback.GetType()));
+ }
+ else
+ {
+ // If we aren't using default fallback then we may have a complicated count.
+ fallback = this.EncoderFallback as EncoderReplacementFallback;
+ }
+
+ // prepare our end
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ // See if we do the fast default or slightly slower fallback
+ if (fallback != null && fallback.MaxCharCount == 1)
+ {
+ // Make sure our fallback character is valid first
+ byte bReplacement = mapUnicodeToBytes[fallback.DefaultString[0]];
+
+ // Check for replacements in range, otherwise fall back to slow version.
+ if (bReplacement != 0)
+ {
+ // We should have exactly as many output bytes as input bytes, unless there's a left
+ // over character, in which case we may need one more.
+
+ // If we had a left over character will have to add a ? (This happens if they had a funky
+ // fallback last time, but not this time.) (We can't spit any out though
+ // because with fallback encoder each surrogate is treated as a seperate code point)
+ if (charLeftOver > 0)
+ {
+ // Have to have room
+ // Throw even if doing no throw version because this is just 1 char,
+ // so buffer will never be big enough
+ if (byteCount == 0)
+ ThrowBytesOverflow(encoder, true);
+
+ // This'll make sure we still have more room and also make sure our return value is correct.
+ *(bytes++) = bReplacement;
+ byteCount--; // We used one of the ones we were counting.
+ }
+
+ // This keeps us from overrunning our output buffer
+ if (byteCount < charCount)
+ {
+ // Throw or make buffer smaller?
+ ThrowBytesOverflow(encoder, byteCount < 1);
+
+ // Just use what we can
+ charEnd = chars + byteCount;
+ }
+
+ // Simple way
+ while (chars < charEnd)
+ {
+ char ch2 = *chars;
+ chars++;
+
+ byte bTemp = mapUnicodeToBytes[ch2];
+
+ // Check for fallback
+ if (bTemp == 0 && ch2 != (char)0)
+ *bytes = bReplacement;
+ else
+ *bytes = bTemp;
+
+ bytes++;
+ }
+
+ // Clear encoder
+ if (encoder != null)
+ {
+ encoder.charLeftOver = (char)0;
+ encoder.m_charsUsed = (int)(chars-charStart);
+ }
+ return (int)(bytes - byteStart);
+ }
+ }
+
+ // Slower version, have to do real fallback.
+
+ // For fallback we may need a fallback buffer, we know we aren't default fallback
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // prepare our end
+ byte* byteEnd = bytes + byteCount;
+
+ // We may have a left over character from last time, try and process it.
+ if (charLeftOver > 0)
+ {
+ // Since left over char was a surrogate, it'll have to be fallen back.
+ // Get Fallback
+ Contract.Assert(encoder != null, "[SBCSCodePageEncoding.GetBytes]Expect to have encoder if we have a charLeftOver");
+ fallbackBuffer = encoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(chars, charEnd, encoder, true);
+
+ // This will fallback a pair if *chars is a low surrogate
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ if (fallbackBuffer.Remaining > byteEnd - bytes)
+ {
+ // Throw it, if we don't have enough for this we never will
+ ThrowBytesOverflow(encoder, true);
+ }
+ }
+
+ // Now we may have fallback char[] already from the encoder fallback above
+
+ // Go ahead and do it, including the fallback.
+ char ch;
+ while ((ch = (fallbackBuffer == null) ? '\0' : fallbackBuffer.InternalGetNextChar()) != 0 ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // get byte for this char
+ byte bTemp = mapUnicodeToBytes[ch];
+
+ // Check for fallback, this'll catch surrogate pairs too.
+ if (bTemp == 0 && ch != (char)0)
+ {
+ // Get Fallback
+ if ( fallbackBuffer == null )
+ {
+ // Create & init fallback buffer
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+ // chars has moved so we need to remember figure it out so Exception fallback
+ // index will be correct
+ fallbackBuffer.InternalInitialize(charEnd - charCount, charEnd, encoder, true);
+ }
+
+ // Make sure we have enough room. Each fallback char will be 1 output char
+ // (or recursion exception will be thrown)
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ if (fallbackBuffer.Remaining > byteEnd - bytes)
+ {
+ // Didn't use this char, reset it
+ Contract.Assert(chars > charStart,
+ "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (fallback)");
+ chars--;
+ fallbackBuffer.InternalReset();
+
+ // Throw it & drop this data
+ ThrowBytesOverflow(encoder, chars == charStart);
+ break;
+ }
+ continue;
+ }
+
+ // We'll use this one
+ // Bounds check
+ if (bytes >= byteEnd)
+ {
+ // didn't use this char, we'll throw or use buffer
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.bFallingBack == false,
+ "[SBCSCodePageEncoding.GetBytes]Expected to NOT be falling back");
+ if (fallbackBuffer == null || fallbackBuffer.bFallingBack == false)
+ {
+ Contract.Assert(chars > charStart,
+ "[SBCSCodePageEncoding.GetBytes]Expected chars to have advanced (normal)");
+ chars--; // don't use last char
+ }
+ ThrowBytesOverflow(encoder, chars == charStart); // throw ?
+ break; // don't throw, stop
+ }
+
+ // Go ahead and add it
+ *bytes = bTemp;
+ bytes++;
+ }
+
+ // encoder stuff if we have one
+ if (encoder != null)
+ {
+ // Fallback stuck it in encoder if necessary, but we have to clear MustFlush cases
+ if (fallbackBuffer != null && !fallbackBuffer.bUsedEncoder)
+ // Clear it in case of MustFlush
+ encoder.charLeftOver = (char)0;
+
+ // Set our chars used count
+ encoder.m_charsUsed = (int)(chars - charStart);
+ }
+
+ // Expect Empty fallback buffer for SBCS
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[SBCSEncoding.GetBytes]Expected Empty fallback buffer at end");
+
+ return (int)(bytes - byteStart);
+ }
+
+ // This is internal and called by something else,
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ {
+ // Just assert, we're called internally so these should be safe, checked already
+ Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetCharCount]bytes is null");
+ Contract.Assert(count >= 0, "[SBCSCodePageEncoding.GetCharCount]byteCount is negative");
+
+ CheckMemorySection();
+
+ // See if we have best fit
+ bool bUseBestFit = false;
+
+ // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
+ DecoderReplacementFallback fallback = null;
+
+ if (decoder == null)
+ {
+ fallback = this.DecoderFallback as DecoderReplacementFallback;
+ bUseBestFit = this.DecoderFallback.IsMicrosoftBestFitFallback;
+ }
+ else
+ {
+ fallback = decoder.Fallback as DecoderReplacementFallback;
+ bUseBestFit = decoder.Fallback.IsMicrosoftBestFitFallback;
+ Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
+ decoder.FallbackBuffer.Remaining == 0,
+ "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
+ }
+
+ if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
+ {
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ // pairs and we don't have a decoder fallback.
+ return count;
+ }
+
+ // Might need one of these later
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // Have to do it the hard way.
+ // Assume charCount will be == count
+ int charCount = count;
+ byte[] byteBuffer = new byte[1];
+
+ // Do it our fast way
+ byte* byteEnd = bytes + count;
+
+ // Quick loop
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ char c;
+ c = mapBytesToUnicode[*bytes];
+ bytes++;
+
+ // If unknown we have to do fallback count
+ if (c == UNKNOWN_CHAR)
+ {
+ // Must have a fallback buffer
+ if (fallbackBuffer == null)
+ {
+ // Need to adjust count so we get real start
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - count, null);
+ }
+
+ // Use fallback buffer
+ byteBuffer[0] = *(bytes - 1);
+ charCount--; // We'd already reserved one for *(bytes-1)
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+ }
+
+ // Fallback buffer must be empty
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[SBCSEncoding.GetCharCount]Expected Empty fallback buffer at end");
+
+ // Converted sequence is same length as input
+ return charCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS decoder)
+ {
+ // Just need to ASSERT, this is called by something else internal that checked parameters already
+ Contract.Assert(bytes != null, "[SBCSCodePageEncoding.GetChars]bytes is null");
+ Contract.Assert(byteCount >= 0, "[SBCSCodePageEncoding.GetChars]byteCount is negative");
+ Contract.Assert(chars != null, "[SBCSCodePageEncoding.GetChars]chars is null");
+ Contract.Assert(charCount >= 0, "[SBCSCodePageEncoding.GetChars]charCount is negative");
+
+ CheckMemorySection();
+
+ // See if we have best fit
+ bool bUseBestFit = false;
+
+ // Do it fast way if using ? replacement or best fit fallbacks
+ byte* byteEnd = bytes + byteCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ // Only need decoder fallback buffer if not using default replacement fallback or best fit fallback.
+ DecoderReplacementFallback fallback = null;
+
+ if (decoder == null)
+ {
+ fallback = this.DecoderFallback as DecoderReplacementFallback;
+ bUseBestFit = this.DecoderFallback.IsMicrosoftBestFitFallback;
+ }
+ else
+ {
+ fallback = decoder.Fallback as DecoderReplacementFallback;
+ bUseBestFit = decoder.Fallback.IsMicrosoftBestFitFallback;
+ Contract.Assert(!decoder.m_throwOnOverflow || !decoder.InternalHasFallbackBuffer ||
+ decoder.FallbackBuffer.Remaining == 0,
+ "[SBCSCodePageEncoding.GetChars]Expected empty fallback buffer at start");
+ }
+
+ if (bUseBestFit || (fallback != null && fallback.MaxCharCount == 1))
+ {
+ // Try it the fast way
+ char replacementChar;
+ if (fallback == null)
+ replacementChar = '?'; // Best fit alwasy has ? for fallback for SBCS
+ else
+ replacementChar = fallback.DefaultString[0];
+
+ // Need byteCount chars, otherwise too small buffer
+ if (charCount < byteCount)
+ {
+ // Need at least 1 output byte, throw if must throw
+ ThrowCharsOverflow(decoder, charCount < 1);
+
+ // Not throwing, use what we can
+ byteEnd = bytes + charCount;
+ }
+
+ // Quick loop, just do '?' replacement because we don't have fallbacks for decodings.
+ while (bytes < byteEnd)
+ {
+ char c;
+ if (bUseBestFit)
+ {
+ if (arrayBytesBestFit == null)
+ {
+ ReadBestFitTable();
+ }
+ c = arrayBytesBestFit[*bytes];
+ }
+ else
+ c = mapBytesToUnicode[*bytes];
+ bytes++;
+
+ if (c == UNKNOWN_CHAR)
+ // This is an invalid byte in the ASCII encoding.
+ *chars = replacementChar;
+ else
+ *chars = c;
+ chars++;
+ }
+
+ // bytes & chars used are the same
+ if (decoder != null)
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+ return (int)(chars - charStart);
+ }
+
+ // Slower way's going to need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+ byte[] byteBuffer = new byte[1];
+ char* charEnd = chars + charCount;
+
+ // Not quite so fast loop
+ while (bytes < byteEnd)
+ {
+ // Faster if don't use *bytes++;
+ char c = mapBytesToUnicode[*bytes];
+ bytes++;
+
+ // See if it was unknown
+ if (c == UNKNOWN_CHAR)
+ {
+ // Make sure we have a fallback buffer
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.DecoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+ fallbackBuffer.InternalInitialize(byteEnd - byteCount, charEnd);
+ }
+
+ // Use fallback buffer
+ Contract.Assert(bytes > byteStart,
+ "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (unknown byte)");
+ byteBuffer[0] = *(bytes - 1);
+ // Fallback adds fallback to chars, but doesn't increment chars unless the whole thing fits.
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // May or may not throw, but we didn't get this byte
+ bytes--; // unused byte
+ fallbackBuffer.InternalReset(); // Didn't fall this back
+ ThrowCharsOverflow(decoder, bytes == byteStart); // throw?
+ break; // don't throw, but stop loop
+ }
+ }
+ else
+ {
+ // Make sure we have buffer space
+ if (chars >= charEnd)
+ {
+ Contract.Assert(bytes > byteStart,
+ "[SBCSCodePageEncoding.GetChars]Expected bytes to have advanced already (known byte)");
+ bytes--; // unused byte
+ ThrowCharsOverflow(decoder, bytes == byteStart); // throw?
+ break; // don't throw, but stop loop
+ }
+
+ *(chars) = c;
+ chars++;
+ }
+ }
+
+ // Might have had decoder fallback stuff.
+ if (decoder != null)
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+
+ // Expect Empty fallback buffer for GetChars
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[SBCSEncoding.GetChars]Expected Empty fallback buffer at end");
+
+ return (int)(chars - charStart);
+ }
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less.
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+ return (int)byteCount;
+ }
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Just return length, SBCS stay the same length because they don't map to surrogate
+ long charCount = (long)byteCount;
+
+ // 1 to 1 for most characters. Only surrogates with fallbacks have less, unknown fallbacks could be longer.
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+ // True if and only if the encoding only uses single byte code points. (Ie, ASCII, 1252, etc)
+ public override bool IsSingleByte
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool IsAlwaysNormalized(NormalizationForm form)
+ {
+ // Most of these code pages could be decomposed or have compatibility mappings for KC, KD, & D
+ // additionally the allow unassigned forms and IDNA wouldn't work either, so C is our choice.
+ if (form == NormalizationForm.FormC)
+ {
+ // Form C is only true for some code pages. They have to have all 256 code points assigned
+ // and not map to unassigned or combinable code points.
+ switch (CodePage)
+ {
+ // Return true for some code pages.
+ case 1252: // (Latin I - ANSI)
+ case 1250: // (Eastern Europe - ANSI)
+ case 1251: // (Cyrillic - ANSI)
+ case 1254: // (Turkish - ANSI)
+ case 1256: // (Arabic - ANSI)
+ case 28591: // (ISO 8859-1 Latin I)
+ case 437: // (United States - OEM)
+ case 737: // (Greek (aka 437G) - OEM)
+ case 775: // (Baltic - OEM)
+ case 850: // (Multilingual (Latin I) - OEM)
+ case 852: // (Slovak (Latin II) - OEM)
+ case 855: // (Cyrillic - OEM)
+ case 858: // (Multilingual (Latin I) - OEM + Euro)
+ case 860: // (Portuguese - OEM)
+ case 861: // (Icelandic - OEM)
+ case 862: // (Hebrew - OEM)
+ case 863: // (Canadian French - OEM)
+ case 865: // (Nordic - OEM)
+ case 866: // (Russian - OEM)
+ case 869: // (Modern Greek - OEM)
+ case 10007: // (Cyrillic - MAC)
+ case 10017: // (Ukraine - MAC)
+ case 10029: // (Latin II - MAC)
+ case 28592: // (ISO 8859-2 Eastern Europe)
+ case 28594: // (ISO 8859-4 Baltic)
+ case 28595: // (ISO 8859-5 Cyrillic)
+ case 28599: // (ISO 8859-9 Latin Alphabet No.5)
+ case 28603: // (ISO/IEC 8859-13:1998 (Lithuanian))
+ case 28605: // (ISO 8859-15 Latin 9 (IBM923=IBM819+Euro))
+ case 037: // (IBM EBCDIC U.S./Canada)
+ case 500: // (IBM EBCDIC International)
+ case 870: // (IBM EBCDIC Latin-2 Multilingual/ROECE)
+ case 1026: // (IBM EBCDIC Latin-5 Turkey)
+ case 1047: // (IBM Latin-1/Open System)
+ case 1140: // (IBM EBCDIC U.S./Canada (037+Euro))
+ case 1141: // (IBM EBCDIC Germany (20273(IBM273)+Euro))
+ case 1142: // (IBM EBCDIC Denmark/Norway (20277(IBM277+Euro))
+ case 1143: // (IBM EBCDIC Finland/Sweden (20278(IBM278)+Euro))
+ case 1144: // (IBM EBCDIC Italy (20280(IBM280)+Euro))
+ case 1145: // (IBM EBCDIC Latin America/Spain (20284(IBM284)+Euro))
+ case 1146: // (IBM EBCDIC United Kingdom (20285(IBM285)+Euro))
+ case 1147: // (IBM EBCDIC France (20297(IBM297+Euro))
+ case 1148: // (IBM EBCDIC International (500+Euro))
+ case 1149: // (IBM EBCDIC Icelandic (20871(IBM871+Euro))
+ case 20273: // (IBM EBCDIC Germany)
+ case 20277: // (IBM EBCDIC Denmark/Norway)
+ case 20278: // (IBM EBCDIC Finland/Sweden)
+ case 20280: // (IBM EBCDIC Italy)
+ case 20284: // (IBM EBCDIC Latin America/Spain)
+ case 20285: // (IBM EBCDIC United Kingdom)
+ case 20297: // (IBM EBCDIC France)
+ case 20871: // (IBM EBCDIC Icelandic)
+ case 20880: // (IBM EBCDIC Cyrillic)
+ case 20924: // (IBM Latin-1/Open System (IBM924=IBM1047+Euro))
+ case 21025: // (IBM EBCDIC Cyrillic (Serbian, Bulgarian))
+ case 720: // (Arabic - Transparent ASMO)
+ case 20866: // (Russian - KOI8)
+ case 21866: // (Ukrainian - KOI8-U)
+ return true;
+ }
+ }
+
+ // False for IDNA and unknown
+ return false;
+ }
+ }
+}
+#endif // FEATURE_CODEPAGES_FILE
diff --git a/src/mscorlib/src/System/Text/StringBuilder.cs b/src/mscorlib/src/System/Text/StringBuilder.cs
new file mode 100644
index 0000000000..8026c98e78
--- /dev/null
+++ b/src/mscorlib/src/System/Text/StringBuilder.cs
@@ -0,0 +1,2217 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: implementation of the StringBuilder
+** class.
+**
+===========================================================*/
+namespace System.Text {
+ using System.Text;
+ using System.Runtime;
+ using System.Runtime.Serialization;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Threading;
+ using System.Globalization;
+ using System.Diagnostics.Contracts;
+
+ // This class represents a mutable string. It is convenient for situations in
+ // which it is desirable to modify a string, perhaps by removing, replacing, or
+ // inserting characters, without creating a new String subsequent to
+ // each modification.
+ //
+ // The methods contained within this class do not return a new StringBuilder
+ // object unless specified otherwise. This class may be used in conjunction with the String
+ // class to carry out modifications upon strings.
+ //
+ // When passing null into a constructor in VJ and VC, the null
+ // should be explicitly type cast.
+ // For Example:
+ // StringBuilder sb1 = new StringBuilder((StringBuilder)null);
+ // StringBuilder sb2 = new StringBuilder((String)null);
+ // Console.WriteLine(sb1);
+ // Console.WriteLine(sb2);
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class StringBuilder : ISerializable
+ {
+ // A StringBuilder is internally represented as a linked list of blocks each of which holds
+ // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
+ // so that is what we do.
+
+ //
+ //
+ // CLASS VARIABLES
+ //
+ //
+ internal char[] m_ChunkChars; // The characters in this block
+ internal StringBuilder m_ChunkPrevious; // Link to the block logically before this block
+ internal int m_ChunkLength; // The index in m_ChunkChars that represent the end of the block
+ internal int m_ChunkOffset; // The logial offset (sum of all characters in previous blocks)
+ internal int m_MaxCapacity = 0;
+
+ //
+ //
+ // STATIC CONSTANTS
+ //
+ //
+ internal const int DefaultCapacity = 16;
+ private const String CapacityField = "Capacity";
+ private const String MaxCapacityField = "m_MaxCapacity";
+ private const String StringValueField = "m_StringValue";
+ private const String ThreadIDField = "m_currentThread";
+ // We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
+ // Making the maximum chunk size big means less allocation code called, but also more waste
+ // in unused characters and slower inserts / replaces (since you do need to slide characters over
+ // within a buffer).
+ internal const int MaxChunkSize = 8000;
+
+ //
+ //
+ //CONSTRUCTORS
+ //
+ //
+
+ // Creates a new empty string builder (i.e., it represents String.Empty)
+ // with the default capacity (16 characters).
+ public StringBuilder()
+ {
+ m_MaxCapacity = int.MaxValue;
+ m_ChunkChars = new char[DefaultCapacity];
+ }
+
+ // Create a new empty string builder (i.e., it represents String.Empty)
+ // with the specified capacity.
+ public StringBuilder(int capacity)
+ : this(capacity, int.MaxValue)
+ {
+ }
+
+ // Creates a new string builder from the specified string. If value
+ // is a null String (i.e., if it represents String.NullString)
+ // then the new string builder will also be null (i.e., it will also represent
+ // String.NullString).
+ //
+ public StringBuilder(String value)
+ : this(value, DefaultCapacity) {
+ }
+
+ // Creates a new string builder from the specified string with the specified
+ // capacity. If value is a null String (i.e., if it represents
+ // String.NullString) then the new string builder will also be null
+ // (i.e., it will also represent String.NullString).
+ // The maximum number of characters this string may contain is set by capacity.
+ //
+ public StringBuilder(String value, int capacity)
+ : this(value, 0, ((value != null) ? value.Length : 0), capacity) {
+ }
+
+ // Creates a new string builder from the specifed substring with the specified
+ // capacity. The maximum number of characters is set by capacity.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder(String value, int startIndex, int length, int capacity) {
+ if (capacity<0) {
+ throw new ArgumentOutOfRangeException("capacity",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "capacity"));
+ }
+ if (length<0) {
+ throw new ArgumentOutOfRangeException("length",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "length"));
+ }
+ if (startIndex<0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+ Contract.EndContractBlock();
+
+ if (value == null) {
+ value = String.Empty;
+ }
+ if (startIndex > value.Length - length) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength"));
+ }
+ m_MaxCapacity = Int32.MaxValue;
+ if (capacity == 0) {
+ capacity = DefaultCapacity;
+ }
+ if (capacity < length)
+ capacity = length;
+
+ m_ChunkChars = new char[capacity];
+ m_ChunkLength = length;
+
+ unsafe {
+ fixed (char* sourcePtr = value)
+ ThreadSafeCopy(sourcePtr + startIndex, m_ChunkChars, 0, length);
+ }
+ }
+
+ // Creates an empty StringBuilder with a minimum capacity of capacity
+ // and a maximum capacity of maxCapacity.
+ public StringBuilder(int capacity, int maxCapacity) {
+ if (capacity>maxCapacity) {
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_Capacity"));
+ }
+ if (maxCapacity<1) {
+ throw new ArgumentOutOfRangeException("maxCapacity", Environment.GetResourceString("ArgumentOutOfRange_SmallMaxCapacity"));
+ }
+ if (capacity<0) {
+ throw new ArgumentOutOfRangeException("capacity",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBePositive", "capacity"));
+ }
+ Contract.EndContractBlock();
+
+ if (capacity == 0) {
+ capacity = Math.Min(DefaultCapacity, maxCapacity);
+ }
+
+ m_MaxCapacity = maxCapacity;
+ m_ChunkChars = new char[capacity];
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private StringBuilder(SerializationInfo info, StreamingContext context) {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ int persistedCapacity = 0;
+ string persistedString = null;
+ int persistedMaxCapacity = Int32.MaxValue;
+ bool capacityPresent = false;
+
+ // Get the data
+ SerializationInfoEnumerator enumerator = info.GetEnumerator();
+ while (enumerator.MoveNext()) {
+ switch (enumerator.Name) {
+ case MaxCapacityField:
+ persistedMaxCapacity = info.GetInt32(MaxCapacityField);
+ break;
+ case StringValueField:
+ persistedString = info.GetString(StringValueField);
+ break;
+ case CapacityField:
+ persistedCapacity = info.GetInt32(CapacityField);
+ capacityPresent = true;
+ break;
+ default:
+ // Ignore other fields for forward compatibility.
+ break;
+ }
+
+ }
+
+ // Check values and set defaults
+ if (persistedString == null) {
+ persistedString = String.Empty;
+ }
+ if (persistedMaxCapacity < 1 || persistedString.Length > persistedMaxCapacity) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_StringBuilderMaxCapacity"));
+ }
+
+ if (!capacityPresent) {
+ // StringBuilder in V1.X did not persist the Capacity, so this is a valid legacy code path.
+ persistedCapacity = DefaultCapacity;
+ if (persistedCapacity < persistedString.Length) {
+ persistedCapacity = persistedString.Length;
+ }
+ if (persistedCapacity > persistedMaxCapacity) {
+ persistedCapacity = persistedMaxCapacity;
+ }
+ }
+ if (persistedCapacity < 0 || persistedCapacity < persistedString.Length || persistedCapacity > persistedMaxCapacity) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_StringBuilderCapacity"));
+ }
+
+ // Assign
+ m_MaxCapacity = persistedMaxCapacity;
+ m_ChunkChars = new char[persistedCapacity];
+ persistedString.CopyTo(0, m_ChunkChars, 0, persistedString.Length);
+ m_ChunkLength = persistedString.Length;
+ m_ChunkPrevious = null;
+ VerifyClassInvariant();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ VerifyClassInvariant();
+ info.AddValue(MaxCapacityField, m_MaxCapacity);
+ info.AddValue(CapacityField, Capacity);
+ info.AddValue(StringValueField, ToString());
+ // Note: persist "m_currentThread" to be compatible with old versions
+ info.AddValue(ThreadIDField, 0);
+ }
+
+ [System.Diagnostics.Conditional("_DEBUG")]
+ private void VerifyClassInvariant() {
+ BCLDebug.Correctness((uint)(m_ChunkOffset + m_ChunkChars.Length) >= m_ChunkOffset, "Integer Overflow");
+ StringBuilder currentBlock = this;
+ int maxCapacity = this.m_MaxCapacity;
+ for (; ; )
+ {
+ // All blocks have copy of the maxCapacity.
+ Contract.Assert(currentBlock.m_MaxCapacity == maxCapacity, "Bad maxCapacity");
+ Contract.Assert(currentBlock.m_ChunkChars != null, "Empty Buffer");
+
+ Contract.Assert(currentBlock.m_ChunkLength <= currentBlock.m_ChunkChars.Length, "Out of range length");
+ Contract.Assert(currentBlock.m_ChunkLength >= 0, "Negative length");
+ Contract.Assert(currentBlock.m_ChunkOffset >= 0, "Negative offset");
+
+ StringBuilder prevBlock = currentBlock.m_ChunkPrevious;
+ if (prevBlock == null)
+ {
+ Contract.Assert(currentBlock.m_ChunkOffset == 0, "First chunk's offset is not 0");
+ break;
+ }
+ // There are no gaps in the blocks.
+ Contract.Assert(currentBlock.m_ChunkOffset == prevBlock.m_ChunkOffset + prevBlock.m_ChunkLength, "There is a gap between chunks!");
+ currentBlock = prevBlock;
+ }
+ }
+
+ public int Capacity {
+ get { return m_ChunkChars.Length + m_ChunkOffset; }
+ set {
+ if (value < 0) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity"));
+ }
+ if (value > MaxCapacity) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_Capacity"));
+ }
+ if (value < Length) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ if (Capacity != value) {
+ int newLen = value - m_ChunkOffset;
+ char[] newArray = new char[newLen];
+ Array.Copy(m_ChunkChars, newArray, m_ChunkLength);
+ m_ChunkChars = newArray;
+ }
+ }
+ }
+
+ public int MaxCapacity {
+ get { return m_MaxCapacity; }
+ }
+
+ // Read-Only Property
+ // Ensures that the capacity of this string builder is at least the specified value.
+ // If capacity is greater than the capacity of this string builder, then the capacity
+ // is set to capacity; otherwise the capacity is unchanged.
+ //
+ public int EnsureCapacity(int capacity) {
+ if (capacity < 0) {
+ throw new ArgumentOutOfRangeException("capacity", Environment.GetResourceString("ArgumentOutOfRange_NegativeCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ if (Capacity < capacity)
+ Capacity = capacity;
+ return Capacity;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ VerifyClassInvariant();
+
+ if (Length == 0)
+ return String.Empty;
+
+ string ret = string.FastAllocateString(Length);
+ StringBuilder chunk = this;
+ unsafe {
+ fixed (char* destinationPtr = ret)
+ {
+ do
+ {
+ if (chunk.m_ChunkLength > 0)
+ {
+ // Copy these into local variables so that they are stable even in the presence of race conditions
+ char[] sourceArray = chunk.m_ChunkChars;
+ int chunkOffset = chunk.m_ChunkOffset;
+ int chunkLength = chunk.m_ChunkLength;
+
+ // Check that we will not overrun our boundaries.
+ if ((uint)(chunkLength + chunkOffset) <= (uint)ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
+ {
+ fixed (char* sourcePtr = &sourceArray[0])
+ string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ }
+ chunk = chunk.m_ChunkPrevious;
+ } while (chunk != null);
+
+ return ret;
+ }
+ }
+ }
+
+
+ // Converts a substring of this string builder to a String.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(int startIndex, int length) {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+ int currentLength = this.Length;
+ if (startIndex < 0)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+ if (startIndex > currentLength)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndexLargerThanLength"));
+ }
+ if (length < 0)
+ {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+ if (startIndex > (currentLength - length))
+ {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_IndexLength"));
+ }
+
+ VerifyClassInvariant();
+
+ StringBuilder chunk = this;
+ int sourceEndIndex = startIndex + length;
+
+ string ret = string.FastAllocateString(length);
+ int curDestIndex = length;
+ unsafe {
+ fixed (char* destinationPtr = ret)
+ {
+ while (curDestIndex > 0)
+ {
+ int chunkEndIndex = sourceEndIndex - chunk.m_ChunkOffset;
+ if (chunkEndIndex >= 0)
+ {
+ if (chunkEndIndex > chunk.m_ChunkLength)
+ chunkEndIndex = chunk.m_ChunkLength;
+
+ int countLeft = curDestIndex;
+ int chunkCount = countLeft;
+ int chunkStartIndex = chunkEndIndex - countLeft;
+ if (chunkStartIndex < 0)
+ {
+ chunkCount += chunkStartIndex;
+ chunkStartIndex = 0;
+ }
+ curDestIndex -= chunkCount;
+
+ if (chunkCount > 0)
+ {
+ // work off of local variables so that they are stable even in the presence of race conditions
+ char[] sourceArray = chunk.m_ChunkChars;
+
+ // Check that we will not overrun our boundaries.
+ if ((uint)(chunkCount + curDestIndex) <= (uint)length && (uint)(chunkCount + chunkStartIndex) <= (uint)sourceArray.Length)
+ {
+ fixed (char* sourcePtr = &sourceArray[chunkStartIndex])
+ string.wstrcpy(destinationPtr + curDestIndex, sourcePtr, chunkCount);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("chunkCount", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ }
+ }
+ chunk = chunk.m_ChunkPrevious;
+ }
+
+ return ret;
+ }
+ }
+ }
+
+ // Convenience method for sb.Length=0;
+ public StringBuilder Clear() {
+ this.Length = 0;
+ return this;
+ }
+
+ // Sets the length of the String in this buffer. If length is less than the current
+ // instance, the StringBuilder is truncated. If length is greater than the current
+ // instance, nulls are appended. The capacity is adjusted to be the same as the length.
+
+ public int Length {
+ get {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ return m_ChunkOffset + m_ChunkLength;
+ }
+ set {
+ //If the new length is less than 0 or greater than our Maximum capacity, bail.
+ if (value<0) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+
+ if (value>MaxCapacity) {
+ throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+ }
+ Contract.EndContractBlock();
+
+ int originalCapacity = Capacity;
+
+ if (value == 0 && m_ChunkPrevious == null)
+ {
+ m_ChunkLength = 0;
+ m_ChunkOffset = 0;
+ Contract.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity");
+ return;
+ }
+
+ int delta = value - Length;
+ // if the specified length is greater than the current length
+ if (delta > 0)
+ {
+ // the end of the string value of the current StringBuilder object is padded with the Unicode NULL character
+ Append('\0', delta); // We could improve on this, but who does this anyway?
+ }
+ // if the specified length is less than or equal to the current length
+ else
+ {
+ StringBuilder chunk = FindChunkForIndex(value);
+ if (chunk != this)
+ {
+ // we crossed a chunk boundary when reducing the Length, we must replace this middle-chunk with a new
+ // larger chunk to ensure the original capacity is preserved
+ int newLen = originalCapacity - chunk.m_ChunkOffset;
+ char[] newArray = new char[newLen];
+
+ Contract.Assert(newLen > chunk.m_ChunkChars.Length, "the new chunk should be larger than the one it is replacing");
+ Array.Copy(chunk.m_ChunkChars, newArray, chunk.m_ChunkLength);
+
+ m_ChunkChars = newArray;
+ m_ChunkPrevious = chunk.m_ChunkPrevious;
+ m_ChunkOffset = chunk.m_ChunkOffset;
+ }
+ m_ChunkLength = value - chunk.m_ChunkOffset;
+ VerifyClassInvariant();
+ }
+ Contract.Assert(Capacity >= originalCapacity, "setting the Length should never decrease the Capacity");
+ }
+ }
+
+ [System.Runtime.CompilerServices.IndexerName("Chars")]
+ public char this[int index] {
+ get {
+ StringBuilder chunk = this;
+ for (; ; )
+ {
+ int indexInBlock = index - chunk.m_ChunkOffset;
+ if (indexInBlock >= 0)
+ {
+ if (indexInBlock >= chunk.m_ChunkLength)
+ throw new IndexOutOfRangeException();
+ return chunk.m_ChunkChars[indexInBlock];
+ }
+ chunk = chunk.m_ChunkPrevious;
+ if (chunk == null)
+ throw new IndexOutOfRangeException();
+ }
+ }
+ set {
+ StringBuilder chunk = this;
+ for (; ; )
+ {
+ int indexInBlock = index - chunk.m_ChunkOffset;
+ if (indexInBlock >= 0)
+ {
+ if (indexInBlock >= chunk.m_ChunkLength)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ chunk.m_ChunkChars[indexInBlock] = value;
+ return;
+ }
+ chunk = chunk.m_ChunkPrevious;
+ if (chunk == null)
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ }
+ }
+
+ // Appends a character at the end of this string builder. The capacity is adjusted as needed.
+ public StringBuilder Append(char value, int repeatCount) {
+ if (repeatCount<0) {
+ throw new ArgumentOutOfRangeException("repeatCount", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if (repeatCount==0) {
+ return this;
+ }
+ int idx = m_ChunkLength;
+ while (repeatCount > 0)
+ {
+ if (idx < m_ChunkChars.Length)
+ {
+ m_ChunkChars[idx++] = value;
+ --repeatCount;
+ }
+ else
+ {
+ m_ChunkLength = idx;
+ ExpandByABlock(repeatCount);
+ Contract.Assert(m_ChunkLength == 0, "Expand should create a new block");
+ idx = 0;
+ }
+ }
+ m_ChunkLength = idx;
+ VerifyClassInvariant();
+ return this;
+ }
+
+ // Appends an array of characters at the end of this string builder. The capacity is adjusted as needed.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Append(char[] value, int startIndex, int charCount) {
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+ if (charCount<0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if (value == null) {
+ if (startIndex == 0 && charCount == 0) {
+ return this;
+ }
+ throw new ArgumentNullException("value");
+ }
+ if (charCount > value.Length - startIndex) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (charCount==0) {
+ return this;
+ }
+ unsafe
+ {
+ fixed (char* valueChars = &value[startIndex])
+ {
+ Append(valueChars, charCount);
+
+ return this;
+ }
+ }
+ }
+
+
+ // Appends a copy of this string at the end of this string builder.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Append(String value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ if (value != null) {
+ // This is a hand specialization of the 'AppendHelper' code below.
+ // We could have just called AppendHelper.
+ char[] chunkChars = m_ChunkChars;
+ int chunkLength = m_ChunkLength;
+ int valueLen = value.Length;
+ int newCurrentIndex = chunkLength + valueLen;
+ if (newCurrentIndex < chunkChars.Length) // Use strictly < to avoid issue if count == 0, newIndex == length
+ {
+ if (valueLen <= 2)
+ {
+ if (valueLen > 0)
+ chunkChars[chunkLength] = value[0];
+ if (valueLen > 1)
+ chunkChars[chunkLength + 1] = value[1];
+ }
+ else
+ {
+ unsafe {
+ fixed (char* valuePtr = value)
+ fixed (char* destPtr = &chunkChars[chunkLength])
+ string.wstrcpy(destPtr, valuePtr, valueLen);
+ }
+ }
+ m_ChunkLength = newCurrentIndex;
+ }
+ else
+ AppendHelper(value);
+ }
+ return this;
+ }
+
+
+ // We put this fixed in its own helper to avoid the cost zero initing valueChars in the
+ // case we don't actually use it.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void AppendHelper(string value) {
+ unsafe {
+ fixed (char* valueChars = value)
+ Append(valueChars, value.Length);
+ }
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ internal unsafe extern void ReplaceBufferInternal(char* newBuffer, int newLength);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecurityCritical]
+ internal unsafe extern void ReplaceBufferAnsiInternal(sbyte* newBuffer, int newLength);
+
+ // Appends a copy of the characters in value from startIndex to startIndex +
+ // count at the end of this string builder.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Append(String value, int startIndex, int count) {
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ //If the value being added is null, eat the null
+ //and return.
+ if (value == null) {
+ if (startIndex == 0 && count == 0) {
+ return this;
+ }
+ throw new ArgumentNullException("value");
+ }
+
+ if (count == 0) {
+ return this;
+ }
+
+ if (startIndex > value.Length - count) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ unsafe
+ {
+ fixed (char* valueChars = value)
+ {
+ Append(valueChars + startIndex, count);
+
+ return this;
+ }
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public StringBuilder AppendLine() {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(Environment.NewLine);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public StringBuilder AppendLine(string value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Append(value);
+ return Append(Environment.NewLine);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [SecuritySafeCritical]
+ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) {
+ if (destination == null) {
+ throw new ArgumentNullException("destination");
+ }
+
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("Arg_NegativeArgCount"));
+ }
+
+ if (destinationIndex < 0) {
+ throw new ArgumentOutOfRangeException("destinationIndex",
+ Environment.GetResourceString("ArgumentOutOfRange_MustBeNonNegNum", "destinationIndex"));
+ }
+
+ if (destinationIndex > destination.Length - count) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_OffsetOut"));
+ }
+
+ if ((uint)sourceIndex > (uint)Length) {
+ throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (sourceIndex > Length - count) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_LongerThanSrcString"));
+ }
+ Contract.EndContractBlock();
+
+ VerifyClassInvariant();
+
+ StringBuilder chunk = this;
+ int sourceEndIndex = sourceIndex + count;
+ int curDestIndex = destinationIndex + count;
+ while (count > 0)
+ {
+ int chunkEndIndex = sourceEndIndex - chunk.m_ChunkOffset;
+ if (chunkEndIndex >= 0)
+ {
+ if (chunkEndIndex > chunk.m_ChunkLength)
+ chunkEndIndex = chunk.m_ChunkLength;
+
+ int chunkCount = count;
+ int chunkStartIndex = chunkEndIndex - count;
+ if (chunkStartIndex < 0)
+ {
+ chunkCount += chunkStartIndex;
+ chunkStartIndex = 0;
+ }
+ curDestIndex -= chunkCount;
+ count -= chunkCount;
+
+ // SafeCritical: we ensure that chunkStartIndex + chunkCount are within range of m_chunkChars
+ // as well as ensuring that curDestIndex + chunkCount are within range of destination
+ ThreadSafeCopy(chunk.m_ChunkChars, chunkStartIndex, destination, curDestIndex, chunkCount);
+ }
+ chunk = chunk.m_ChunkPrevious;
+ }
+ }
+
+ // Inserts multiple copies of a string into this string builder at the specified position.
+ // Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, this
+ // string builder is not changed.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Insert(int index, String value, int count) {
+ if (count < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ //Range check the index.
+ int currentLength = Length;
+ if ((uint)index > (uint)currentLength) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ //If value is null, empty or count is 0, do nothing. This is ECMA standard.
+ if (value == null || value.Length == 0 || count == 0) {
+ return this;
+ }
+
+ //Ensure we don't insert more chars than we can hold, and we don't
+ //have any integer overflow in our inserted characters.
+ long insertingChars = (long) value.Length * count;
+ if (insertingChars > MaxCapacity - this.Length) {
+ throw new OutOfMemoryException();
+ }
+ Contract.Assert(insertingChars + this.Length < Int32.MaxValue);
+
+ StringBuilder chunk;
+ int indexInChunk;
+ MakeRoom(index, (int) insertingChars, out chunk, out indexInChunk, false);
+ unsafe {
+ fixed (char* valuePtr = value) {
+ while (count > 0)
+ {
+ ReplaceInPlaceAtChunk(ref chunk, ref indexInChunk, valuePtr, value.Length);
+ --count;
+ }
+
+ return this;
+ }
+ }
+ }
+
+ // Removes the specified characters from this string builder.
+ // The length of this string builder is reduced by
+ // length, but the capacity is unaffected.
+ //
+ public StringBuilder Remove(int startIndex, int length) {
+ if (length<0) {
+ throw new ArgumentOutOfRangeException("length", Environment.GetResourceString("ArgumentOutOfRange_NegativeLength"));
+ }
+
+ if (startIndex<0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+
+ if (length > Length - startIndex) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if (Length == length && startIndex == 0) {
+ // Optimization. If we are deleting everything
+ Length = 0;
+ return this;
+ }
+
+ if (length > 0)
+ {
+ StringBuilder chunk;
+ int indexInChunk;
+ Remove(startIndex, length, out chunk, out indexInChunk);
+ }
+ return this;
+ }
+
+ //
+ // PUBLIC INSTANCE FUNCTIONS
+ //
+ //
+
+ /*====================================Append====================================
+ **
+ ==============================================================================*/
+ // Appends a boolean to the end of this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(bool value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString());
+ }
+
+ // Appends an sbyte to this string builder.
+ // The capacity is adjusted as needed.
+ [CLSCompliant(false)]
+ public StringBuilder Append(sbyte value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends a ubyte to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(byte value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends a character at the end of this string builder. The capacity is adjusted as needed.
+ public StringBuilder Append(char value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ if (m_ChunkLength < m_ChunkChars.Length)
+ m_ChunkChars[m_ChunkLength++] = value;
+ else
+ Append(value, 1);
+ return this;
+ }
+
+ // Appends a short to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(short value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends an int to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(int value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends a long to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(long value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends a float to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(float value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends a double to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(double value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ public StringBuilder Append(decimal value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends an ushort to this string builder.
+ // The capacity is adjusted as needed.
+ [CLSCompliant(false)]
+ public StringBuilder Append(ushort value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends an uint to this string builder.
+ // The capacity is adjusted as needed.
+ [CLSCompliant(false)]
+ public StringBuilder Append(uint value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends an unsigned long to this string builder.
+ // The capacity is adjusted as needed.
+ [CLSCompliant(false)]
+ public StringBuilder Append(ulong value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Append(value.ToString(CultureInfo.CurrentCulture));
+ }
+
+ // Appends an Object to this string builder.
+ // The capacity is adjusted as needed.
+ public StringBuilder Append(Object value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ if (null==value) {
+ //Appending null is now a no-op.
+ return this;
+ }
+ return Append(value.ToString());
+ }
+
+ // Appends all of the characters in value to the current instance.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Append(char[] value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ if (null != value && value.Length > 0)
+ {
+ unsafe {
+ fixed (char* valueChars = &value[0])
+ Append(valueChars, value.Length);
+ }
+ }
+ return this;
+ }
+
+ /*====================================Insert====================================
+ **
+ ==============================================================================*/
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Insert(int index, String value) {
+ if ((uint)index > (uint)Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if (value != null)
+ {
+ unsafe {
+ fixed (char* sourcePtr = value)
+ Insert(index, sourcePtr, value.Length);
+ }
+ }
+ return this;
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert( int index, bool value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ [CLSCompliant(false)]
+ public StringBuilder Insert(int index, sbyte value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, byte value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, short value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ [SecuritySafeCritical]
+ public StringBuilder Insert(int index, char value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ unsafe {
+ Insert(index, &value, 1);
+ }
+ return this;
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, char[] value) {
+ if ((uint)index > (uint)Length) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ if (value != null)
+ Insert(index, value, 0, value.Length);
+ return this;
+ }
+
+ // Returns a reference to the StringBuilder with charCount characters from
+ // value inserted into the buffer at index. Existing characters are shifted
+ // to make room for the new text and capacity is adjusted as required. If value is null, the StringBuilder
+ // is unchanged. Characters are taken from value starting at position startIndex.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public StringBuilder Insert(int index, char[] value, int startIndex, int charCount) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ int currentLength = Length;
+ if ((uint)index > (uint)currentLength) {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ //If they passed in a null char array, just jump out quickly.
+ if (value == null) {
+ if (startIndex == 0 && charCount == 0)
+ {
+ return this;
+ }
+ throw new ArgumentNullException("value", Environment.GetResourceString("ArgumentNull_String"));
+ }
+
+ //Range check the array.
+ if (startIndex < 0) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_StartIndex"));
+ }
+
+ if (charCount < 0) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GenericPositive"));
+ }
+
+ if (startIndex > value.Length - charCount) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (charCount > 0)
+ {
+ unsafe {
+ fixed (char* sourcePtr = &value[startIndex])
+ Insert(index, sourcePtr, charCount);
+ }
+ }
+ return this;
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, int value){
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, long value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, float value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with ; value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed.
+ //
+ public StringBuilder Insert(int index, double value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ public StringBuilder Insert(int index, decimal value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed.
+ //
+ [CLSCompliant(false)]
+ public StringBuilder Insert(int index, ushort value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed.
+ //
+ [CLSCompliant(false)]
+ public StringBuilder Insert(int index, uint value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to the StringBuilder with value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the new text.
+ // The capacity is adjusted as needed.
+ //
+ [CLSCompliant(false)]
+ public StringBuilder Insert(int index, ulong value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Insert(index, value.ToString(CultureInfo.CurrentCulture), 1);
+ }
+
+ // Returns a reference to this string builder with value inserted into
+ // the buffer at index. Existing characters are shifted to make room for the
+ // new text. The capacity is adjusted as needed. If value equals String.Empty, the
+ // StringBuilder is not changed. No changes are made if value is null.
+ //
+ public StringBuilder Insert(int index, Object value) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ if (null == value) {
+ return this;
+ }
+ return Insert(index, value.ToString(), 1);
+ }
+
+ public StringBuilder AppendFormat(String format, Object arg0) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(null, format, new ParamsArray(arg0));
+ }
+
+ public StringBuilder AppendFormat(String format, Object arg0, Object arg1) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
+ }
+
+ public StringBuilder AppendFormat(String format, Object arg0, Object arg1, Object arg2) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
+ }
+
+ public StringBuilder AppendFormat(String format, params Object[] args) {
+ if (args == null)
+ {
+ // To preserve the original exception behavior, throw an exception about format if both
+ // args and format are null. The actual null check for format is in AppendFormatHelper.
+ throw new ArgumentNullException((format == null) ? "format" : "args");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return AppendFormatHelper(null, format, new ParamsArray(args));
+ }
+
+ public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(provider, format, new ParamsArray(arg0));
+ }
+
+ public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
+ }
+
+ public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1, Object arg2) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
+ }
+
+ public StringBuilder AppendFormat(IFormatProvider provider, String format, params Object[] args) {
+ if (args == null)
+ {
+ // To preserve the original exception behavior, throw an exception about format if both
+ // args and format are null. The actual null check for format is in AppendFormatHelper.
+ throw new ArgumentNullException((format == null) ? "format" : "args");
+ }
+ Contract.Ensures(Contract.Result<String>() != null);
+ Contract.EndContractBlock();
+
+ return AppendFormatHelper(provider, format, new ParamsArray(args));
+ }
+
+ private static void FormatError() {
+ throw new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ }
+
+ // undocumented exclusive limits on the range for Argument Hole Index and Argument Hole Alignment.
+ private const int Index_Limit = 1000000; // Note: 0 <= ArgIndex < Index_Limit
+ private const int Width_Limit = 1000000; // Note: -Width_Limit < ArgAlign < Width_Limit
+
+ internal StringBuilder AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args) {
+ if (format == null) {
+ throw new ArgumentNullException("format");
+ }
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ Contract.EndContractBlock();
+
+ int pos = 0;
+ int len = format.Length;
+ char ch = '\x0';
+ StringBuilder unescapedItemFormat = null;
+
+ ICustomFormatter cf = null;
+ if (provider != null) {
+ cf = (ICustomFormatter)provider.GetFormat(typeof(ICustomFormatter));
+ }
+
+ while (true) {
+ while (pos < len) {
+ ch = format[pos];
+
+ pos++;
+ // Is it a closing brace?
+ if (ch == '}')
+ {
+ // Check next character (if there is one) to see if it is escaped. eg }}
+ if (pos < len && format[pos] == '}')
+ pos++;
+ else
+ // Otherwise treat it as an error (Mismatched closing brace)
+ FormatError();
+ }
+ // Is it a opening brace?
+ if (ch == '{')
+ {
+ // Check next character (if there is one) to see if it is escaped. eg {{
+ if (pos < len && format[pos] == '{')
+ pos++;
+ else
+ {
+ // Otherwise treat it as the opening brace of an Argument Hole.
+ pos--;
+ break;
+ }
+ }
+ // If it neither then treat the character as just text.
+ Append(ch);
+ }
+
+ //
+ // Start of parsing of Argument Hole.
+ // Argument Hole ::= { Index (, WS* Alignment WS*)? (: Formatting)? }
+ //
+ if (pos == len) break;
+
+ //
+ // Start of parsing required Index parameter.
+ // Index ::= ('0'-'9')+ WS*
+ //
+ pos++;
+ // If reached end of text then error (Unexpected end of text)
+ // or character is not a digit then error (Unexpected Character)
+ if (pos == len || (ch = format[pos]) < '0' || ch > '9') FormatError();
+ int index = 0;
+ do {
+ index = index * 10 + ch - '0';
+ pos++;
+ // If reached end of text then error (Unexpected end of text)
+ if (pos == len) FormatError();
+ ch = format[pos];
+ // so long as character is digit and value of the index is less than 1000000 ( index limit )
+ } while (ch >= '0' && ch <= '9' && index < Index_Limit);
+
+ // If value of index is not within the range of the arguments passed in then error (Index out of range)
+ if (index >= args.Length) throw new FormatException(Environment.GetResourceString("Format_IndexOutOfRange"));
+
+ // Consume optional whitespace.
+ while (pos < len && (ch = format[pos]) == ' ') pos++;
+ // End of parsing index parameter.
+
+ //
+ // Start of parsing of optional Alignment
+ // Alignment ::= comma WS* minus? ('0'-'9')+ WS*
+ //
+ bool leftJustify = false;
+ int width = 0;
+ // Is the character a comma, which indicates the start of alignment parameter.
+ if (ch == ',') {
+ pos++;
+
+ // Consume Optional whitespace
+ while (pos < len && format[pos] == ' ') pos++;
+
+ // If reached the end of the text then error (Unexpected end of text)
+ if (pos == len) FormatError();
+
+ // Is there a minus sign?
+ ch = format[pos];
+ if (ch == '-') {
+ // Yes, then alignment is left justified.
+ leftJustify = true;
+ pos++;
+ // If reached end of text then error (Unexpected end of text)
+ if (pos == len) FormatError();
+ ch = format[pos];
+ }
+
+ // If current character is not a digit then error (Unexpected character)
+ if (ch < '0' || ch > '9') FormatError();
+ // Parse alignment digits.
+ do {
+ width = width * 10 + ch - '0';
+ pos++;
+ // If reached end of text then error. (Unexpected end of text)
+ if (pos == len) FormatError();
+ ch = format[pos];
+ // So long a current character is a digit and the value of width is less than 100000 ( width limit )
+ } while (ch >= '0' && ch <= '9' && width < Width_Limit);
+ // end of parsing Argument Alignment
+ }
+
+ // Consume optional whitespace
+ while (pos < len && (ch = format[pos]) == ' ') pos++;
+
+ //
+ // Start of parsing of optional formatting parameter.
+ //
+ Object arg = args[index];
+ String itemFormat = null;
+ // Is current character a colon? which indicates start of formatting parameter.
+ if (ch == ':') {
+ pos++;
+ int startPos = pos;
+
+ while (true) {
+ // If reached end of text then error. (Unexpected end of text)
+ if (pos == len) FormatError();
+ ch = format[pos];
+ pos++;
+
+ // Is character a opening or closing brace?
+ if (ch == '}' || ch == '{')
+ {
+ if (ch == '{')
+ {
+ // Yes, is next character also a opening brace, then treat as escaped. eg {{
+ if (pos < len && format[pos] == '{')
+ pos++;
+ else
+ // Error Argument Holes can not be nested.
+ FormatError();
+ }
+ else
+ {
+ // Yes, is next character also a closing brace, then treat as escaped. eg }}
+ if (pos < len && format[pos] == '}')
+ pos++;
+ else
+ {
+ // No, then treat it as the closing brace of an Arg Hole.
+ pos--;
+ break;
+ }
+ }
+
+ // Reaching here means the brace has been escaped
+ // so we need to build up the format string in segments
+ if (unescapedItemFormat == null)
+ {
+ unescapedItemFormat = new StringBuilder();
+ }
+ unescapedItemFormat.Append(format, startPos, pos - startPos - 1);
+ startPos = pos;
+ }
+ }
+
+ if (unescapedItemFormat == null || unescapedItemFormat.Length == 0)
+ {
+ if (startPos != pos)
+ {
+ // There was no brace escaping, extract the item format as a single string
+ itemFormat = format.Substring(startPos, pos - startPos);
+ }
+ }
+ else
+ {
+ unescapedItemFormat.Append(format, startPos, pos - startPos);
+ itemFormat = unescapedItemFormat.ToString();
+ unescapedItemFormat.Clear();
+ }
+ }
+ // If current character is not a closing brace then error. (Unexpected Character)
+ if (ch != '}') FormatError();
+ // Construct the output for this arg hole.
+ pos++;
+ String s = null;
+ if (cf != null) {
+ s = cf.Format(itemFormat, arg, provider);
+ }
+
+ if (s == null) {
+ IFormattable formattableArg = arg as IFormattable;
+
+ if (formattableArg != null) {
+ s = formattableArg.ToString(itemFormat, provider);
+ } else if (arg != null) {
+ s = arg.ToString();
+ }
+ }
+ // Append it to the final output of the Format String.
+ if (s == null) s = String.Empty;
+ int pad = width - s.Length;
+ if (!leftJustify && pad > 0) Append(' ', pad);
+ Append(s);
+ if (leftJustify && pad > 0) Append(' ', pad);
+ // Continue to parse other characters.
+ }
+ return this;
+ }
+
+ // Returns a reference to the current StringBuilder with all instances of oldString
+ // replaced with newString. If startIndex and count are specified,
+ // we only replace strings completely contained in the range of startIndex to startIndex +
+ // count. The strings to be replaced are checked on an ordinal basis (e.g. not culture aware). If
+ // newValue is null, instances of oldValue are removed (e.g. replaced with nothing.).
+ //
+ public StringBuilder Replace(String oldValue, String newValue) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+ return Replace(oldValue, newValue, 0, Length);
+ }
+
+ public bool Equals(StringBuilder sb)
+ {
+ if (sb == null)
+ return false;
+ if (Capacity != sb.Capacity || MaxCapacity != sb.MaxCapacity || Length != sb.Length)
+ return false;
+ if (sb == this)
+ return true;
+
+ StringBuilder thisChunk = this;
+ int thisChunkIndex = thisChunk.m_ChunkLength;
+ StringBuilder sbChunk = sb;
+ int sbChunkIndex = sbChunk.m_ChunkLength;
+ for (; ; )
+ {
+ // Decrement the pointer to the 'this' StringBuilder
+ --thisChunkIndex;
+ --sbChunkIndex;
+
+ while (thisChunkIndex < 0)
+ {
+ thisChunk = thisChunk.m_ChunkPrevious;
+ if (thisChunk == null)
+ break;
+ thisChunkIndex = thisChunk.m_ChunkLength + thisChunkIndex;
+ }
+
+ // Decrement the pointer to the 'this' StringBuilder
+ while (sbChunkIndex < 0)
+ {
+ sbChunk = sbChunk.m_ChunkPrevious;
+ if (sbChunk == null)
+ break;
+ sbChunkIndex = sbChunk.m_ChunkLength + sbChunkIndex;
+ }
+
+ if (thisChunkIndex < 0)
+ return sbChunkIndex < 0;
+ if (sbChunkIndex < 0)
+ return false;
+ if (thisChunk.m_ChunkChars[thisChunkIndex] != sbChunk.m_ChunkChars[sbChunkIndex])
+ return false;
+ }
+ }
+
+ public StringBuilder Replace(String oldValue, String newValue, int startIndex, int count)
+ {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ int currentLength = Length;
+ if ((uint)startIndex > (uint)currentLength)
+ {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ if (count < 0 || startIndex > currentLength - count)
+ {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ if (oldValue == null)
+ {
+ throw new ArgumentNullException("oldValue");
+ }
+ if (oldValue.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "oldValue");
+ }
+
+ if (newValue == null)
+ newValue = "";
+
+ int deltaLength = newValue.Length - oldValue.Length;
+
+ int[] replacements = null; // A list of replacement positions in a chunk to apply
+ int replacementsCount = 0;
+
+ // Find the chunk, indexInChunk for the starting point
+ StringBuilder chunk = FindChunkForIndex(startIndex);
+ int indexInChunk = startIndex - chunk.m_ChunkOffset;
+ while (count > 0)
+ {
+ // Look for a match in the chunk,indexInChunk pointer
+ if (StartsWith(chunk, indexInChunk, count, oldValue))
+ {
+ // Push it on my replacements array (with growth), we will do all replacements in a
+ // given chunk in one operation below (see ReplaceAllInChunk) so we don't have to slide
+ // many times.
+ if (replacements == null)
+ replacements = new int[5];
+ else if (replacementsCount >= replacements.Length)
+ {
+ int[] newArray = new int[replacements.Length * 3 / 2 + 4]; // grow by 1.5X but more in the begining
+ Array.Copy(replacements, newArray, replacements.Length);
+ replacements = newArray;
+ }
+ replacements[replacementsCount++] = indexInChunk;
+ indexInChunk += oldValue.Length;
+ count -= oldValue.Length;
+ }
+ else
+ {
+ indexInChunk++;
+ --count;
+ }
+
+ if (indexInChunk >= chunk.m_ChunkLength || count == 0) // Have we moved out of the current chunk
+ {
+ // Replacing mutates the blocks, so we need to convert to logical index and back afterward.
+ int index = indexInChunk + chunk.m_ChunkOffset;
+ int indexBeforeAdjustment = index;
+
+ // See if we accumulated any replacements, if so apply them
+ ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
+ // The replacement has affected the logical index. Adjust it.
+ index += ((newValue.Length - oldValue.Length) * replacementsCount);
+ replacementsCount = 0;
+
+ chunk = FindChunkForIndex(index);
+ indexInChunk = index - chunk.m_ChunkOffset;
+ Contract.Assert(chunk != null || count == 0, "Chunks ended prematurely");
+ }
+ }
+ VerifyClassInvariant();
+ return this;
+ }
+
+ // Returns a StringBuilder with all instances of oldChar replaced with
+ // newChar. The size of the StringBuilder is unchanged because we're only
+ // replacing characters. If startIndex and count are specified, we
+ // only replace characters in the range from startIndex to startIndex+count
+ //
+ public StringBuilder Replace(char oldChar, char newChar) {
+ return Replace(oldChar, newChar, 0, Length);
+ }
+ public StringBuilder Replace(char oldChar, char newChar, int startIndex, int count) {
+ Contract.Ensures(Contract.Result<StringBuilder>() != null);
+
+ int currentLength = Length;
+ if ((uint)startIndex > (uint)currentLength) {
+ throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (count < 0 || startIndex > currentLength - count) {
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ int endIndex = startIndex + count;
+ StringBuilder chunk = this;
+ for (; ; )
+ {
+ int endIndexInChunk = endIndex - chunk.m_ChunkOffset;
+ int startIndexInChunk = startIndex - chunk.m_ChunkOffset;
+ if (endIndexInChunk >= 0)
+ {
+ int curInChunk = Math.Max(startIndexInChunk, 0);
+ int endInChunk = Math.Min(chunk.m_ChunkLength, endIndexInChunk);
+ while (curInChunk < endInChunk)
+ {
+ if (chunk.m_ChunkChars[curInChunk] == oldChar)
+ chunk.m_ChunkChars[curInChunk] = newChar;
+ curInChunk++;
+ }
+ }
+ if (startIndexInChunk >= 0)
+ break;
+ chunk = chunk.m_ChunkPrevious;
+ }
+ return this;
+ }
+
+ /// <summary>
+ /// Appends 'value' of length 'count' to the stringBuilder.
+ /// </summary>
+ [SecurityCritical]
+ [System.CLSCompliantAttribute(false)]
+ public unsafe StringBuilder Append(char* value, int valueCount)
+ {
+ // We don't check null value as this case will throw null reference exception anyway
+ if (valueCount < 0)
+ {
+ throw new ArgumentOutOfRangeException("valueCount", Environment.GetResourceString("ArgumentOutOfRange_NegativeCount"));
+ }
+
+ // This case is so common we want to optimize for it heavily.
+ int newIndex = valueCount + m_ChunkLength;
+ if (newIndex <= m_ChunkChars.Length)
+ {
+ ThreadSafeCopy(value, m_ChunkChars, m_ChunkLength, valueCount);
+ m_ChunkLength = newIndex;
+ }
+ else
+ {
+ // Copy the first chunk
+ int firstLength = m_ChunkChars.Length - m_ChunkLength;
+ if (firstLength > 0)
+ {
+ ThreadSafeCopy(value, m_ChunkChars, m_ChunkLength, firstLength);
+ m_ChunkLength = m_ChunkChars.Length;
+ }
+
+ // Expand the builder to add another chunk.
+ int restLength = valueCount - firstLength;
+ ExpandByABlock(restLength);
+ Contract.Assert(m_ChunkLength == 0, "Expand did not make a new block");
+
+ // Copy the second chunk
+ ThreadSafeCopy(value + firstLength, m_ChunkChars, 0, restLength);
+ m_ChunkLength = restLength;
+ }
+ VerifyClassInvariant();
+ return this;
+ }
+
+ /// <summary>
+ /// Inserts 'value' of length 'cou
+ /// </summary>
+ [SecurityCritical]
+ unsafe private void Insert(int index, char* value, int valueCount)
+ {
+ if ((uint)index > (uint)Length)
+ {
+ throw new ArgumentOutOfRangeException("index", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+
+ if (valueCount > 0)
+ {
+ StringBuilder chunk;
+ int indexInChunk;
+ MakeRoom(index, valueCount, out chunk, out indexInChunk, false);
+ ReplaceInPlaceAtChunk(ref chunk, ref indexInChunk, value, valueCount);
+ }
+ }
+
+ /// <summary>
+ /// 'replacements' is a list of index (relative to the begining of the 'chunk' to remove
+ /// 'removeCount' characters and replace them with 'value'. This routine does all those
+ /// replacements in bulk (and therefore very efficiently.
+ /// with the string 'value'.
+ /// </summary>
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void ReplaceAllInChunk(int[] replacements, int replacementsCount, StringBuilder sourceChunk, int removeCount, string value)
+ {
+ if (replacementsCount <= 0)
+ return;
+
+ unsafe {
+ fixed (char* valuePtr = value)
+ {
+ // calculate the total amount of extra space or space needed for all the replacements.
+ int delta = (value.Length - removeCount) * replacementsCount;
+
+ StringBuilder targetChunk = sourceChunk; // the target as we copy chars down
+ int targetIndexInChunk = replacements[0];
+
+ // Make the room needed for all the new characters if needed.
+ if (delta > 0)
+ MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
+ // We made certain that characters after the insertion point are not moved,
+ int i = 0;
+ for (; ; )
+ {
+ // Copy in the new string for the ith replacement
+ ReplaceInPlaceAtChunk(ref targetChunk, ref targetIndexInChunk, valuePtr, value.Length);
+ int gapStart = replacements[i] + removeCount;
+ i++;
+ if (i >= replacementsCount)
+ break;
+
+ int gapEnd = replacements[i];
+ Contract.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen");
+ Contract.Assert(gapStart <= gapEnd, "negative gap size");
+ Contract.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
+ if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
+ {
+ // Copy the gap data between the current replacement and the the next replacement
+ fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
+ ReplaceInPlaceAtChunk(ref targetChunk, ref targetIndexInChunk, sourcePtr, gapEnd - gapStart);
+ }
+ else
+ {
+ targetIndexInChunk += gapEnd - gapStart;
+ Contract.Assert(targetIndexInChunk <= targetChunk.m_ChunkLength, "gap not in chunk");
+ }
+ }
+
+ // Remove extra space if necessary.
+ if (delta < 0)
+ Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Returns true if the string that is starts at 'chunk' and 'indexInChunk, and has a logical
+ /// length of 'count' starts with the string 'value'.
+ /// </summary>
+ private bool StartsWith(StringBuilder chunk, int indexInChunk, int count, string value)
+ {
+ for (int i = 0; i < value.Length; i++)
+ {
+ if (count == 0)
+ return false;
+ if (indexInChunk >= chunk.m_ChunkLength)
+ {
+ chunk = Next(chunk);
+ if (chunk == null)
+ return false;
+ indexInChunk = 0;
+ }
+
+ // See if there no match, break out of the inner for loop
+ if (value[i] != chunk.m_ChunkChars[indexInChunk])
+ return false;
+
+ indexInChunk++;
+ --count;
+ }
+ return true;
+ }
+
+ /// <summary>
+ /// ReplaceInPlaceAtChunk is the logical equivalent of 'memcpy'. Given a chunk and ann index in
+ /// that chunk, it copies in 'count' characters from 'value' and updates 'chunk, and indexInChunk to
+ /// point at the end of the characters just copyied (thus you can splice in strings from multiple
+ /// places by calling this mulitple times.
+ /// </summary>
+ [SecurityCritical]
+ unsafe private void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
+ {
+ if (count != 0)
+ {
+ for (; ; )
+ {
+ int lengthInChunk = chunk.m_ChunkLength - indexInChunk;
+ Contract.Assert(lengthInChunk >= 0, "index not in chunk");
+
+ int lengthToCopy = Math.Min(lengthInChunk, count);
+ ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy);
+
+ // Advance the index.
+ indexInChunk += lengthToCopy;
+ if (indexInChunk >= chunk.m_ChunkLength)
+ {
+ chunk = Next(chunk);
+ indexInChunk = 0;
+ }
+ count -= lengthToCopy;
+ if (count == 0)
+ break;
+ value += lengthToCopy;
+ }
+ }
+ }
+
+ /// <summary>
+ /// We have to prevent modification off the end of an array.
+ /// The only way to do this is to copy all interesting variables out of the heap and then do the
+ /// bounds check. This is what we do here.
+ /// </summary>
+ [SecurityCritical]
+ unsafe private static void ThreadSafeCopy(char* sourcePtr, char[] destination, int destinationIndex, int count)
+ {
+ if (count > 0)
+ {
+ if ((uint)destinationIndex <= (uint)destination.Length && (destinationIndex + count) <= destination.Length)
+ {
+ fixed (char* destinationPtr = &destination[destinationIndex])
+ string.wstrcpy(destinationPtr, sourcePtr, count);
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("destinationIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ }
+ }
+ [SecurityCritical]
+ private static void ThreadSafeCopy(char[] source, int sourceIndex, char[] destination, int destinationIndex, int count)
+ {
+ if (count > 0)
+ {
+ if ((uint)sourceIndex <= (uint)source.Length && (sourceIndex + count) <= source.Length)
+ {
+ unsafe {
+ fixed (char* sourcePtr = &source[sourceIndex])
+ ThreadSafeCopy(sourcePtr, destination, destinationIndex, count);
+ }
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("sourceIndex", Environment.GetResourceString("ArgumentOutOfRange_Index"));
+ }
+ }
+ }
+
+ // Copies the source StringBuilder to the destination IntPtr memory allocated with len bytes.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe void InternalCopy(IntPtr dest, int len) {
+ if(len ==0)
+ return;
+
+ bool isLastChunk = true;
+ byte* dstPtr = (byte*) dest.ToPointer();
+ StringBuilder currentSrc = FindChunkForByte(len);
+
+ do {
+ int chunkOffsetInBytes = currentSrc.m_ChunkOffset*sizeof(char);
+ int chunkLengthInBytes = currentSrc.m_ChunkLength*sizeof(char);
+ fixed(char* charPtr = &currentSrc.m_ChunkChars[0]) {
+ byte* srcPtr = (byte*) charPtr;
+ if(isLastChunk) {
+ isLastChunk= false;
+ Buffer.Memcpy(dstPtr + chunkOffsetInBytes, srcPtr, len - chunkOffsetInBytes);
+ } else {
+ Buffer.Memcpy(dstPtr + chunkOffsetInBytes, srcPtr, chunkLengthInBytes);
+ }
+ }
+ currentSrc = currentSrc.m_ChunkPrevious;
+ } while(currentSrc != null);
+ }
+
+ /// <summary>
+ /// Finds the chunk for the logical index (number of characters in the whole stringbuilder) 'index'
+ /// YOu can then get the offset in this chunk by subtracting the m_BlockOffset field from 'index'
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ private StringBuilder FindChunkForIndex(int index)
+ {
+ Contract.Assert(0 <= index && index <= Length, "index not in string");
+
+ StringBuilder ret = this;
+ while (ret.m_ChunkOffset > index)
+ ret = ret.m_ChunkPrevious;
+
+ Contract.Assert(ret != null, "index not in string");
+ return ret;
+ }
+
+ /// <summary>
+ /// Finds the chunk for the logical byte index 'byteIndex'
+ /// </summary>
+ /// <param name="index"></param>
+ /// <returns></returns>
+ private StringBuilder FindChunkForByte(int byteIndex)
+ {
+ Contract.Assert(0 <= byteIndex && byteIndex <= Length*sizeof(char), "Byte Index not in string");
+
+ StringBuilder ret = this;
+ while (ret.m_ChunkOffset*sizeof(char) > byteIndex)
+ ret = ret.m_ChunkPrevious;
+
+ Contract.Assert(ret != null, "Byte Index not in string");
+ return ret;
+ }
+
+ /// <summary>
+ /// Finds the chunk that logically follows the 'chunk' chunk. Chunks only persist the pointer to
+ /// the chunk that is logically before it, so this routine has to start at the this pointer (which
+ /// is a assumed to point at the chunk representing the whole stringbuilder) and search
+ /// until it finds the current chunk (thus is O(n)). So it is more expensive than a field fetch!
+ /// </summary>
+ private StringBuilder Next(StringBuilder chunk)
+ {
+ if (chunk == this)
+ return null;
+ return FindChunkForIndex(chunk.m_ChunkOffset + chunk.m_ChunkLength);
+ }
+
+ /// <summary>
+ /// Assumes that 'this' is the last chunk in the list and that it is full. Upon return the 'this'
+ /// block is updated so that it is a new block that has at least 'minBlockCharCount' characters.
+ /// that can be used to copy characters into it.
+ /// </summary>
+ private void ExpandByABlock(int minBlockCharCount)
+ {
+ Contract.Requires(Capacity == Length, "Expand expect to be called only when there is no space left"); // We are currently full
+ Contract.Requires(minBlockCharCount > 0, "Expansion request must be positive");
+
+ VerifyClassInvariant();
+
+ if ((minBlockCharCount + Length) > m_MaxCapacity || minBlockCharCount + Length < minBlockCharCount)
+ throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+
+ // Compute the length of the new block we need
+ // We make the new chunk at least big enough for the current need (minBlockCharCount)
+ // But also as big as the current length (thus doubling capacity), up to a maximum
+ // (so we stay in the small object heap, and never allocate really big chunks even if
+ // the string gets really big.
+ int newBlockLength = Math.Max(minBlockCharCount, Math.Min(Length, MaxChunkSize));
+
+ // Copy the current block to the new block, and initialize this to point at the new buffer.
+ m_ChunkPrevious = new StringBuilder(this);
+ m_ChunkOffset += m_ChunkLength;
+ m_ChunkLength = 0;
+
+ // Check for integer overflow (logical buffer size > int.MaxInt)
+ if (m_ChunkOffset + newBlockLength < newBlockLength)
+ {
+ m_ChunkChars = null;
+ throw new OutOfMemoryException();
+ }
+ m_ChunkChars = new char[newBlockLength];
+
+ VerifyClassInvariant();
+ }
+
+ /// <summary>
+ /// Used by ExpandByABlock to create a new chunk. The new chunk is a copied from 'from'
+ /// In particular the buffer is shared. It is expected that 'from' chunk (which represents
+ /// the whole list, is then updated to point to point to this new chunk.
+ /// </summary>
+ private StringBuilder(StringBuilder from)
+ {
+ m_ChunkLength = from.m_ChunkLength;
+ m_ChunkOffset = from.m_ChunkOffset;
+ m_ChunkChars = from.m_ChunkChars;
+ m_ChunkPrevious = from.m_ChunkPrevious;
+ m_MaxCapacity = from.m_MaxCapacity;
+ VerifyClassInvariant();
+ }
+
+ /// <summary>
+ /// Creates a gap of size 'count' at the logical offset (count of characters in the whole string
+ /// builder) 'index'. It returns the 'chunk' and 'indexInChunk' which represents a pointer to
+ /// this gap that was just created. You can then use 'ReplaceInPlaceAtChunk' to fill in the
+ /// chunk
+ ///
+ /// ReplaceAllChunks relies on the fact that indexes above 'index' are NOT moved outside 'chunk'
+ /// by this process (because we make the space by creating the cap BEFORE the chunk). If we
+ /// change this ReplaceAllChunks needs to be updated.
+ ///
+ /// If dontMoveFollowingChars is true, then the room must be made by inserting a chunk BEFORE the
+ /// current chunk (this is what it does most of the time anyway)
+ /// </summary>
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void MakeRoom(int index, int count, out StringBuilder chunk, out int indexInChunk, bool doneMoveFollowingChars)
+ {
+ VerifyClassInvariant();
+ Contract.Assert(count > 0, "Count must be strictly positive");
+ Contract.Assert(index >= 0, "Index can't be negative");
+ if (count + Length > m_MaxCapacity || count + Length < count)
+ throw new ArgumentOutOfRangeException("requiredLength", Environment.GetResourceString("ArgumentOutOfRange_SmallCapacity"));
+
+ chunk = this;
+ while (chunk.m_ChunkOffset > index)
+ {
+ chunk.m_ChunkOffset += count;
+ chunk = chunk.m_ChunkPrevious;
+ }
+ indexInChunk = index - chunk.m_ChunkOffset;
+
+ // Cool, we have some space in this block, and you don't have to copy much to get it, go ahead
+ // and use it. This happens typically when you repeatedly insert small strings at a spot
+ // (typically the absolute front) of the buffer.
+ if (!doneMoveFollowingChars && chunk.m_ChunkLength <= DefaultCapacity * 2 && chunk.m_ChunkChars.Length - chunk.m_ChunkLength >= count)
+ {
+ for (int i = chunk.m_ChunkLength; i > indexInChunk; )
+ {
+ --i;
+ chunk.m_ChunkChars[i + count] = chunk.m_ChunkChars[i];
+ }
+ chunk.m_ChunkLength += count;
+ return;
+ }
+
+ // Allocate space for the new chunk (will go before this one)
+ StringBuilder newChunk = new StringBuilder(Math.Max(count, DefaultCapacity), chunk.m_MaxCapacity, chunk.m_ChunkPrevious);
+ newChunk.m_ChunkLength = count;
+
+ // Copy the head of the buffer to the new buffer.
+ int copyCount1 = Math.Min(count, indexInChunk);
+ if (copyCount1 > 0)
+ {
+ unsafe {
+ fixed (char* chunkCharsPtr = &chunk.m_ChunkChars[0]) {
+ ThreadSafeCopy(chunkCharsPtr, newChunk.m_ChunkChars, 0, copyCount1);
+
+ // Slide characters in the current buffer over to make room.
+ int copyCount2 = indexInChunk - copyCount1;
+ if (copyCount2 >= 0)
+ {
+ ThreadSafeCopy(chunkCharsPtr + copyCount1, chunk.m_ChunkChars, 0, copyCount2);
+ indexInChunk = copyCount2;
+ }
+ }
+ }
+ }
+
+ chunk.m_ChunkPrevious = newChunk; // Wire in the new chunk
+ chunk.m_ChunkOffset += count;
+ if (copyCount1 < count)
+ {
+ chunk = newChunk;
+ indexInChunk = copyCount1;
+ }
+
+ VerifyClassInvariant();
+ }
+
+ /// <summary>
+ /// Used by MakeRoom to allocate another chunk.
+ /// </summary>
+ private StringBuilder(int size, int maxCapacity, StringBuilder previousBlock)
+ {
+ Contract.Assert(size > 0, "size not positive");
+ Contract.Assert(maxCapacity > 0, "maxCapacity not positive");
+ m_ChunkChars = new char[size];
+ m_MaxCapacity = maxCapacity;
+ m_ChunkPrevious = previousBlock;
+ if (previousBlock != null)
+ m_ChunkOffset = previousBlock.m_ChunkOffset + previousBlock.m_ChunkLength;
+ VerifyClassInvariant();
+ }
+
+ /// <summary>
+ /// Removes 'count' characters from the logical index 'startIndex' and returns the chunk and
+ /// index in the chunk of that logical index in the out parameters.
+ /// </summary>
+ [SecuritySafeCritical]
+ private void Remove(int startIndex, int count, out StringBuilder chunk, out int indexInChunk)
+ {
+ VerifyClassInvariant();
+ Contract.Assert(startIndex >= 0 && startIndex < Length, "startIndex not in string");
+
+ int endIndex = startIndex + count;
+
+ // Find the chunks for the start and end of the block to delete.
+ chunk = this;
+ StringBuilder endChunk = null;
+ int endIndexInChunk = 0;
+ for (; ; )
+ {
+ if (endIndex - chunk.m_ChunkOffset >= 0)
+ {
+ if (endChunk == null)
+ {
+ endChunk = chunk;
+ endIndexInChunk = endIndex - endChunk.m_ChunkOffset;
+ }
+ if (startIndex - chunk.m_ChunkOffset >= 0)
+ {
+ indexInChunk = startIndex - chunk.m_ChunkOffset;
+ break;
+ }
+ }
+ else
+ {
+ chunk.m_ChunkOffset -= count;
+ }
+ chunk = chunk.m_ChunkPrevious;
+ }
+ Contract.Assert(chunk != null, "fell off beginning of string!");
+
+ int copyTargetIndexInChunk = indexInChunk;
+ int copyCount = endChunk.m_ChunkLength - endIndexInChunk;
+ if (endChunk != chunk)
+ {
+ copyTargetIndexInChunk = 0;
+ // Remove the characters after startIndex to end of the chunk
+ chunk.m_ChunkLength = indexInChunk;
+
+ // Remove the characters in chunks between start and end chunk
+ endChunk.m_ChunkPrevious = chunk;
+ endChunk.m_ChunkOffset = chunk.m_ChunkOffset + chunk.m_ChunkLength;
+
+ // If the start is 0 then we can throw away the whole start chunk
+ if (indexInChunk == 0)
+ {
+ endChunk.m_ChunkPrevious = chunk.m_ChunkPrevious;
+ chunk = endChunk;
+ }
+ }
+ endChunk.m_ChunkLength -= (endIndexInChunk - copyTargetIndexInChunk);
+
+ // SafeCritical: We ensure that endIndexInChunk + copyCount is within range of m_ChunkChars and
+ // also ensure that copyTargetIndexInChunk + copyCount is within the chunk
+ //
+ // Remove any characters in the end chunk, by sliding the characters down.
+ if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary
+ ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount);
+
+ Contract.Assert(chunk != null, "fell off beginning of string!");
+ VerifyClassInvariant();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/StringBuilderCache.cs b/src/mscorlib/src/System/Text/StringBuilderCache.cs
new file mode 100644
index 0000000000..16a786d54e
--- /dev/null
+++ b/src/mscorlib/src/System/Text/StringBuilderCache.cs
@@ -0,0 +1,83 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: provide a cached reusable instance of stringbuilder
+** per thread it's an optimisation that reduces the
+** number of instances constructed and collected.
+**
+** Acquire - is used to get a string builder to use of a
+** particular size. It can be called any number of
+** times, if a stringbuilder is in the cache then
+** it will be returned and the cache emptied.
+** subsequent calls will return a new stringbuilder.
+**
+** A StringBuilder instance is cached in
+** Thread Local Storage and so there is one per thread
+**
+** Release - Place the specified builder in the cache if it is
+** not too big.
+** The stringbuilder should not be used after it has
+** been released.
+** Unbalanced Releases are perfectly acceptable. It
+** will merely cause the runtime to create a new
+** stringbuilder next time Acquire is called.
+**
+** GetStringAndRelease
+** - ToString() the stringbuilder, Release it to the
+** cache and return the resulting string
+**
+===========================================================*/
+using System.Threading;
+
+namespace System.Text
+{
+ internal static class StringBuilderCache
+ {
+ // The value 360 was chosen in discussion with performance experts as a compromise between using
+ // as litle memory (per thread) as possible and still covering a large part of short-lived
+ // StringBuilder creations on the startup path of VS designers.
+ private const int MAX_BUILDER_SIZE = 360;
+
+ [ThreadStatic]
+ private static StringBuilder CachedInstance;
+
+ public static StringBuilder Acquire(int capacity = StringBuilder.DefaultCapacity)
+ {
+ if(capacity <= MAX_BUILDER_SIZE)
+ {
+ StringBuilder sb = StringBuilderCache.CachedInstance;
+ if (sb != null)
+ {
+ // Avoid stringbuilder block fragmentation by getting a new StringBuilder
+ // when the requested size is larger than the current capacity
+ if(capacity <= sb.Capacity)
+ {
+ StringBuilderCache.CachedInstance = null;
+ sb.Clear();
+ return sb;
+ }
+ }
+ }
+ return new StringBuilder(capacity);
+ }
+
+ public static void Release(StringBuilder sb)
+ {
+ if (sb.Capacity <= MAX_BUILDER_SIZE)
+ {
+ StringBuilderCache.CachedInstance = sb;
+ }
+ }
+
+ public static string GetStringAndRelease(StringBuilder sb)
+ {
+ string result = sb.ToString();
+ Release(sb);
+ return result;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/SurrogateEncoder.cs b/src/mscorlib/src/System/Text/SurrogateEncoder.cs
new file mode 100644
index 0000000000..409e8a34aa
--- /dev/null
+++ b/src/mscorlib/src/System/Text/SurrogateEncoder.cs
@@ -0,0 +1,58 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// WARNING:
+//
+// This is just an IObjectReference proxy for the former V1.1 Surrogate Encoder
+// All this does is make an encoder of the correct type, it DOES NOT maintain state.
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ /*=================================SurrogateEncoder==================================
+ ** This class is here only to deserialize the SurrogateEncoder class from Everett (V1.1) into
+ ** Appropriate Whidbey (V2.0) objects.
+ ==============================================================================*/
+
+ [Serializable]
+ internal sealed class SurrogateEncoder : IObjectReference, ISerializable
+ {
+ // Might need this when GetRealObjecting
+ [NonSerialized]
+ private Encoding realEncoding = null;
+
+ // Constructor called by serialization.
+ internal SurrogateEncoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // All versions have a code page
+ this.realEncoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding));
+ }
+
+ // Just get it from GetEncoding
+ [System.Security.SecurityCritical] // auto-generated
+ public Object GetRealObject(StreamingContext context)
+ {
+ // Need to get our Encoding's Encoder
+ return this.realEncoding.GetEncoder();
+ }
+
+ // ISerializable implementation
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // We cannot ever call this.
+ Contract.Assert(false, "Didn't expect to make it to SurrogateEncoder.GetObjectData");
+ throw new ArgumentException(Environment.GetResourceString("Arg_ExecutionEngineException"));
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Text/UTF32Encoding.cs b/src/mscorlib/src/System/Text/UTF32Encoding.cs
new file mode 100644
index 0000000000..0bdbaefbf2
--- /dev/null
+++ b/src/mscorlib/src/System/Text/UTF32Encoding.cs
@@ -0,0 +1,1010 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
+//
+
+namespace System.Text
+{
+
+ using System;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ // Encodes text into and out of UTF-32. UTF-32 is a way of writing
+ // Unicode characters with a single storage unit (32 bits) per character,
+ //
+ // The UTF-32 byte order mark is simply the Unicode byte order mark
+ // (0x00FEFF) written in UTF-32 (0x0000FEFF or 0xFFFE0000). The byte order
+ // mark is used mostly to distinguish UTF-32 text from other encodings, and doesn't
+ // switch the byte orderings.
+
+ [Serializable]
+ public sealed class UTF32Encoding : Encoding
+ {
+ /*
+ words bits UTF-32 representation
+ ----- ---- -----------------------------------
+ 1 16 00000000 00000000 xxxxxxxx xxxxxxxx
+ 2 21 00000000 000xxxxx hhhhhhll llllllll
+ ----- ---- -----------------------------------
+
+ Surrogate:
+ Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
+ */
+
+ // Used by Encoding.UTF32/BigEndianUTF32 for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly UTF32Encoding s_default = new UTF32Encoding(bigEndian: false, byteOrderMark: true);
+ internal static readonly UTF32Encoding s_bigEndianDefault = new UTF32Encoding(bigEndian: true, byteOrderMark: true);
+
+ private bool emitUTF32ByteOrderMark = false;
+ private bool isThrowException = false;
+ private bool bigEndian = false;
+
+
+ public UTF32Encoding(): this(false, true, false)
+ {
+ }
+
+
+ public UTF32Encoding(bool bigEndian, bool byteOrderMark):
+ this(bigEndian, byteOrderMark, false)
+ {
+ }
+
+
+ public UTF32Encoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidCharacters):
+ base(bigEndian ? 12001 : 12000)
+ {
+ this.bigEndian = bigEndian;
+ this.emitUTF32ByteOrderMark = byteOrderMark;
+ this.isThrowException = throwOnInvalidCharacters;
+
+ // Encoding's constructor already did this, but it'll be wrong if we're throwing exceptions
+ if (this.isThrowException)
+ SetDefaultFallbacks();
+ }
+
+ internal override void SetDefaultFallbacks()
+ {
+ // For UTF-X encodings, we use a replacement fallback with an empty string
+ if (this.isThrowException)
+ {
+ this.encoderFallback = EncoderFallback.ExceptionFallback;
+ this.decoderFallback = DecoderFallback.ExceptionFallback;
+ }
+ else
+ {
+ this.encoderFallback = new EncoderReplacementFallback("\xFFFD");
+ this.decoderFallback = new DecoderReplacementFallback("\xFFFD");
+ }
+ }
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ public override int GetByteCount(String s)
+ {
+ return EncodingForwarder.GetByteCount(this, s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ public override int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, s, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ public override String GetString(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetString(this, bytes, index, count);
+ }
+
+ // End of overridden methods which use EncodingForwarder
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS encoder)
+ {
+ Contract.Assert(chars!=null, "[UTF32Encoding.GetByteCount]chars!=null");
+ Contract.Assert(count >=0, "[UTF32Encoding.GetByteCount]count >=0");
+
+ char* end = chars + count;
+ char* charStart = chars;
+ int byteCount = 0;
+
+ char highSurrogate = '\0';
+
+ // For fallback we may need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+ if (encoder != null)
+ {
+ highSurrogate = encoder.charLeftOver;
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // We mustn't have left over fallback data when counting
+ if (fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+ }
+ else
+ {
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ }
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, end, encoder, false);
+
+ char ch;
+ TryAgain:
+
+ while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < end)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Do we need a low surrogate?
+ if (highSurrogate != '\0')
+ {
+ //
+ // In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
+ //
+ if (Char.IsLowSurrogate(ch))
+ {
+ // They're all legal
+ highSurrogate = '\0';
+
+ //
+ // One surrogate pair will be translated into 4 bytes UTF32.
+ //
+
+ byteCount += 4;
+ continue;
+ }
+
+ // We are missing our low surrogate, decrement chars and fallback the high surrogate
+ // The high surrogate may have come from the encoder, but nothing else did.
+ Contract.Assert(chars > charStart,
+ "[UTF32Encoding.GetByteCount]Expected chars to have advanced if no low surrogate");
+ chars--;
+
+ // Do the fallback
+ fallbackBuffer.InternalFallback(highSurrogate, ref chars);
+
+ // We're going to fallback the old high surrogate.
+ highSurrogate = '\0';
+ continue;
+
+ }
+
+ // Do we have another high surrogate?
+ if (Char.IsHighSurrogate(ch))
+ {
+ //
+ // We'll have a high surrogate to check next time.
+ //
+ highSurrogate = ch;
+ continue;
+ }
+
+ // Check for illegal characters
+ if (Char.IsLowSurrogate(ch))
+ {
+ // We have a leading low surrogate, do the fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+
+ // Try again with fallback buffer
+ continue;
+ }
+
+ // We get to add the character (4 bytes UTF32)
+ byteCount += 4;
+ }
+
+ // May have to do our last surrogate
+ if ((encoder == null || encoder.MustFlush) && highSurrogate > 0)
+ {
+ // We have to do the fallback for the lonely high surrogate
+ fallbackBuffer.InternalFallback(highSurrogate, ref chars);
+ highSurrogate = (char)0;
+ goto TryAgain;
+ }
+
+ // Check for overflows.
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString(
+ "ArgumentOutOfRange_GetByteCountOverflow"));
+
+ // Shouldn't have anything in fallback buffer for GetByteCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[UTF32Encoding.GetByteCount]Expected empty fallback buffer at end");
+
+ // Return our count
+ return byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char *chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ Contract.Assert(chars!=null, "[UTF32Encoding.GetBytes]chars!=null");
+ Contract.Assert(bytes!=null, "[UTF32Encoding.GetBytes]bytes!=null");
+ Contract.Assert(byteCount >=0, "[UTF32Encoding.GetBytes]byteCount >=0");
+ Contract.Assert(charCount >=0, "[UTF32Encoding.GetBytes]charCount >=0");
+
+ char* charStart = chars;
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ byte* byteEnd = bytes + byteCount;
+
+ char highSurrogate = '\0';
+
+ // For fallback we may need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+ if (encoder != null)
+ {
+ highSurrogate = encoder.charLeftOver;
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // We mustn't have left over fallback data when not converting
+ if (encoder.m_throwOnOverflow && fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+ }
+ else
+ {
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ }
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+
+ char ch;
+ TryAgain:
+
+ while (((ch = fallbackBuffer.InternalGetNextChar()) != 0) || chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Do we need a low surrogate?
+ if (highSurrogate != '\0')
+ {
+ //
+ // In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
+ //
+ if (Char.IsLowSurrogate(ch))
+ {
+ // Is it a legal one?
+ uint iTemp = GetSurrogate(highSurrogate, ch);
+ highSurrogate = '\0';
+
+ //
+ // One surrogate pair will be translated into 4 bytes UTF32.
+ //
+ if (bytes+3 >= byteEnd)
+ {
+ // Don't have 4 bytes
+ if (fallbackBuffer.bFallingBack)
+ {
+ fallbackBuffer.MovePrevious(); // Aren't using these 2 fallback chars
+ fallbackBuffer.MovePrevious();
+ }
+ else
+ {
+ // If we don't have enough room, then either we should've advanced a while
+ // or we should have bytes==byteStart and throw below
+ Contract.Assert(chars > charStart + 1 || bytes == byteStart,
+ "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair");
+ chars-=2; // Aren't using those 2 chars
+ }
+ ThrowBytesOverflow(encoder, bytes == byteStart); // Throw maybe (if no bytes written)
+ highSurrogate = (char)0; // Nothing left over (we backed up to start of pair if supplimentary)
+ break;
+ }
+
+ if (bigEndian)
+ {
+ *(bytes++) = (byte)(0x00);
+ *(bytes++) = (byte)(iTemp >> 16); // Implies & 0xFF, which isn't needed cause high are all 0
+ *(bytes++) = (byte)(iTemp >> 8); // Implies & 0xFF
+ *(bytes++) = (byte)(iTemp); // Implies & 0xFF
+ }
+ else
+ {
+ *(bytes++) = (byte)(iTemp); // Implies & 0xFF
+ *(bytes++) = (byte)(iTemp >> 8); // Implies & 0xFF
+ *(bytes++) = (byte)(iTemp >> 16); // Implies & 0xFF, which isn't needed cause high are all 0
+ *(bytes++) = (byte)(0x00);
+ }
+ continue;
+ }
+
+ // We are missing our low surrogate, decrement chars and fallback the high surrogate
+ // The high surrogate may have come from the encoder, but nothing else did.
+ Contract.Assert(chars > charStart,
+ "[UTF32Encoding.GetBytes]Expected chars to have advanced if no low surrogate");
+ chars--;
+
+ // Do the fallback
+ fallbackBuffer.InternalFallback(highSurrogate, ref chars);
+
+ // We're going to fallback the old high surrogate.
+ highSurrogate = '\0';
+ continue;
+ }
+
+ // Do we have another high surrogate?, if so remember it
+ if (Char.IsHighSurrogate(ch))
+ {
+ //
+ // We'll have a high surrogate to check next time.
+ //
+ highSurrogate = ch;
+ continue;
+ }
+
+ // Check for illegal characters (low surrogate)
+ if (Char.IsLowSurrogate(ch))
+ {
+ // We have a leading low surrogate, do the fallback
+ fallbackBuffer.InternalFallback(ch, ref chars);
+
+ // Try again with fallback buffer
+ continue;
+ }
+
+ // We get to add the character, yippee.
+ if (bytes+3 >= byteEnd)
+ {
+ // Don't have 4 bytes
+ if (fallbackBuffer.bFallingBack)
+ fallbackBuffer.MovePrevious(); // Aren't using this fallback char
+ else
+ {
+ // Must've advanced already
+ Contract.Assert(chars > charStart,
+ "[UTF32Encoding.GetBytes]Expected chars to have advanced if normal character");
+ chars--; // Aren't using this char
+ }
+ ThrowBytesOverflow(encoder, bytes == byteStart); // Throw maybe (if no bytes written)
+ break; // Didn't throw, stop
+ }
+
+ if (bigEndian)
+ {
+ *(bytes++) = (byte)(0x00);
+ *(bytes++) = (byte)(0x00);
+ *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
+ *(bytes++) = (byte)(ch); // Implies & 0xFF
+ }
+ else
+ {
+ *(bytes++) = (byte)(ch); // Implies & 0xFF
+ *(bytes++) = (byte)((uint)ch >> 8); // Implies & 0xFF
+ *(bytes++) = (byte)(0x00);
+ *(bytes++) = (byte)(0x00);
+ }
+ }
+
+ // May have to do our last surrogate
+ if ((encoder == null || encoder.MustFlush) && highSurrogate > 0)
+ {
+ // We have to do the fallback for the lonely high surrogate
+ fallbackBuffer.InternalFallback(highSurrogate, ref chars);
+ highSurrogate = (char)0;
+ goto TryAgain;
+ }
+
+ // Fix our encoder if we have one
+ Contract.Assert(highSurrogate == 0 || (encoder != null && !encoder.MustFlush),
+ "[UTF32Encoding.GetBytes]Expected encoder to be flushed.");
+
+ if (encoder != null)
+ {
+ // Remember our left over surrogate (or 0 if flushing)
+ encoder.charLeftOver = highSurrogate;
+
+ // Need # chars used
+ encoder.m_charsUsed = (int)(chars-charStart);
+ }
+
+ // return the new length
+ return (int)(bytes - byteStart);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(bytes!=null, "[UTF32Encoding.GetCharCount]bytes!=null");
+ Contract.Assert(count >=0, "[UTF32Encoding.GetCharCount]count >=0");
+
+ UTF32Decoder decoder = (UTF32Decoder)baseDecoder;
+
+ // None so far!
+ int charCount = 0;
+ byte* end = bytes + count;
+ byte* byteStart = bytes;
+
+ // Set up decoder
+ int readCount = 0;
+ uint iChar = 0;
+
+ // For fallback we may need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // See if there's anything in our decoder
+ if (decoder != null)
+ {
+ readCount = decoder.readByteCount;
+ iChar = (uint)decoder.iChar;
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for chars or count)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at start");
+ }
+ else
+ {
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ }
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+
+ // Loop through our input, 4 characters at a time!
+ while (bytes < end && charCount >= 0)
+ {
+ // Get our next character
+ if(bigEndian)
+ {
+ // Scoot left and add it to the bottom
+ iChar <<= 8;
+ iChar += *(bytes++);
+ }
+ else
+ {
+ // Scoot right and add it to the top
+ iChar >>= 8;
+ iChar += (uint)(*(bytes++)) << 24;
+ }
+
+ readCount++;
+
+ // See if we have all the bytes yet
+ if (readCount < 4)
+ continue;
+
+ // Have the bytes
+ readCount = 0;
+
+ // See if its valid to encode
+ if ( iChar > 0x10FFFF || (iChar >= 0xD800 && iChar <= 0xDFFF))
+ {
+ // Need to fall back these 4 bytes
+ byte[] fallbackBytes;
+ if (this.bigEndian)
+ {
+ fallbackBytes = new byte[] {
+ unchecked((byte)(iChar>>24)), unchecked((byte)(iChar>>16)),
+ unchecked((byte)(iChar>>8)), unchecked((byte)(iChar)) };
+ }
+ else
+ {
+ fallbackBytes = new byte[] {
+ unchecked((byte)(iChar)), unchecked((byte)(iChar>>8)),
+ unchecked((byte)(iChar>>16)), unchecked((byte)(iChar>>24)) };
+ }
+
+ charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
+
+ // Ignore the illegal character
+ iChar = 0;
+ continue;
+ }
+
+ // Ok, we have something we can add to our output
+ if (iChar >= 0x10000)
+ {
+ // Surrogates take 2
+ charCount++;
+ }
+
+ // Add the rest of the surrogate or our normal character
+ charCount++;
+
+ // iChar is back to 0
+ iChar = 0;
+ }
+
+ // See if we have something left over that has to be decoded
+ if (readCount > 0 && (decoder == null || decoder.MustFlush))
+ {
+ // Oops, there's something left over with no place to go.
+ byte[] fallbackBytes = new byte[readCount];
+ if (this.bigEndian)
+ {
+ while(readCount > 0)
+ {
+ fallbackBytes[--readCount] = unchecked((byte)iChar);
+ iChar >>= 8;
+ }
+ }
+ else
+ {
+ while (readCount > 0)
+ {
+ fallbackBytes[--readCount] = unchecked((byte)(iChar>>24));
+ iChar <<= 8;
+ }
+ }
+
+ charCount += fallbackBuffer.InternalFallback(fallbackBytes, bytes);
+ }
+
+ // Check for overflows.
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for chars or count)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[UTF32Encoding.GetCharCount]Expected empty fallback buffer at end");
+
+ // Return our count
+ return charCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(chars!=null, "[UTF32Encoding.GetChars]chars!=null");
+ Contract.Assert(bytes!=null, "[UTF32Encoding.GetChars]bytes!=null");
+ Contract.Assert(byteCount >=0, "[UTF32Encoding.GetChars]byteCount >=0");
+ Contract.Assert(charCount >=0, "[UTF32Encoding.GetChars]charCount >=0");
+
+ UTF32Decoder decoder = (UTF32Decoder)baseDecoder;
+
+ // None so far!
+ char* charStart = chars;
+ char* charEnd = chars + charCount;
+
+ byte* byteStart = bytes;
+ byte* byteEnd = bytes + byteCount;
+
+ // See if there's anything in our decoder (but don't clear it yet)
+ int readCount = 0;
+ uint iChar = 0;
+
+ // For fallback we may need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ // See if there's anything in our decoder
+ if (decoder != null)
+ {
+ readCount = decoder.readByteCount;
+ iChar = (uint)decoder.iChar;
+ fallbackBuffer = baseDecoder.FallbackBuffer;
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for chars)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[UTF32Encoding.GetChars]Expected empty fallback buffer at start");
+ }
+ else
+ {
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ }
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(bytes, chars + charCount);
+
+ // Loop through our input, 4 characters at a time!
+ while (bytes < byteEnd)
+ {
+ // Get our next character
+ if(bigEndian)
+ {
+ // Scoot left and add it to the bottom
+ iChar <<= 8;
+ iChar += *(bytes++);
+ }
+ else
+ {
+ // Scoot right and add it to the top
+ iChar >>= 8;
+ iChar += (uint)(*(bytes++)) << 24;
+ }
+
+ readCount++;
+
+ // See if we have all the bytes yet
+ if (readCount < 4)
+ continue;
+
+ // Have the bytes
+ readCount = 0;
+
+ // See if its valid to encode
+ if ( iChar > 0x10FFFF || (iChar >= 0xD800 && iChar <= 0xDFFF))
+ {
+ // Need to fall back these 4 bytes
+ byte[] fallbackBytes;
+ if (this.bigEndian)
+ {
+ fallbackBytes = new byte[] {
+ unchecked((byte)(iChar>>24)), unchecked((byte)(iChar>>16)),
+ unchecked((byte)(iChar>>8)), unchecked((byte)(iChar)) };
+ }
+ else
+ {
+ fallbackBytes = new byte[] {
+ unchecked((byte)(iChar)), unchecked((byte)(iChar>>8)),
+ unchecked((byte)(iChar>>16)), unchecked((byte)(iChar>>24)) };
+ }
+
+ // Chars won't be updated unless this works.
+ if (!fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref chars))
+ {
+ // Couldn't fallback, throw or wait til next time
+ // We either read enough bytes for bytes-=4 to work, or we're
+ // going to throw in ThrowCharsOverflow because chars == charStart
+ Contract.Assert(bytes >= byteStart + 4 || chars == charStart,
+ "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (bad surrogate)");
+ bytes-=4; // get back to where we were
+ iChar=0; // Remembering nothing
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // Stop here, didn't throw
+ }
+
+ // Ignore the illegal character
+ iChar = 0;
+ continue;
+ }
+
+
+ // Ok, we have something we can add to our output
+ if (iChar >= 0x10000)
+ {
+ // Surrogates take 2
+ if (chars >= charEnd - 1)
+ {
+ // Throwing or stopping
+ // We either read enough bytes for bytes-=4 to work, or we're
+ // going to throw in ThrowCharsOverflow because chars == charStart
+ Contract.Assert(bytes >= byteStart + 4 || chars == charStart,
+ "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (surrogate)");
+ bytes-=4; // get back to where we were
+ iChar=0; // Remembering nothing
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // Stop here, didn't throw
+ }
+
+ *(chars++) = GetHighSurrogate(iChar);
+ iChar = GetLowSurrogate(iChar);
+ }
+ // Bounds check for normal character
+ else if (chars >= charEnd)
+ {
+ // Throwing or stopping
+ // We either read enough bytes for bytes-=4 to work, or we're
+ // going to throw in ThrowCharsOverflow because chars == charStart
+ Contract.Assert(bytes >= byteStart + 4 || chars == charStart,
+ "[UTF32Encoding.GetChars]Expected to have consumed bytes or throw (normal char)");
+ bytes-=4; // get back to where we were
+ iChar=0; // Remembering nothing
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // Stop here, didn't throw
+ }
+
+ // Add the rest of the surrogate or our normal character
+ *(chars++) = (char)iChar;
+
+ // iChar is back to 0
+ iChar = 0;
+ }
+
+ // See if we have something left over that has to be decoded
+ if (readCount > 0 && (decoder == null || decoder.MustFlush))
+ {
+ // Oops, there's something left over with no place to go.
+ byte[] fallbackBytes = new byte[readCount];
+ int tempCount = readCount;
+ if (this.bigEndian)
+ {
+ while(tempCount > 0)
+ {
+ fallbackBytes[--tempCount] = unchecked((byte)iChar);
+ iChar >>= 8;
+ }
+ }
+ else
+ {
+ while (tempCount > 0)
+ {
+ fallbackBytes[--tempCount] = unchecked((byte)(iChar>>24));
+ iChar <<= 8;
+ }
+ }
+
+ if (!fallbackBuffer.InternalFallback(fallbackBytes, bytes, ref chars))
+ {
+ // Couldn't fallback.
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ // Stop here, didn't throw, backed up, so still nothing in buffer
+ }
+ else
+ {
+ // Don't clear our decoder unless we could fall it back.
+ // If we caught the if above, then we're a convert() and will catch this next time.
+ readCount = 0;
+ iChar = 0;
+ }
+ }
+
+ // Remember any left over stuff, clearing buffer as well for MustFlush
+ if (decoder != null)
+ {
+ decoder.iChar = (int)iChar;
+ decoder.readByteCount = readCount;
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+ }
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for chars)
+ Contract.Assert(fallbackBuffer.Remaining == 0,
+ "[UTF32Encoding.GetChars]Expected empty fallback buffer at end");
+
+ // Return our count
+ return (int)(chars - charStart);
+ }
+
+
+ private uint GetSurrogate(char cHigh, char cLow)
+ {
+ return (((uint)cHigh - 0xD800) * 0x400) + ((uint)cLow - 0xDC00) + 0x10000;
+ }
+
+ private char GetHighSurrogate(uint iChar)
+ {
+ return (char)((iChar - 0x10000) / 0x400 + 0xD800);
+ }
+
+ private char GetLowSurrogate(uint iChar)
+ {
+ return (char)((iChar - 0x10000) % 0x400 + 0xDC00);
+ }
+
+
+ public override Decoder GetDecoder()
+ {
+ return new UTF32Decoder(this);
+ }
+
+
+ public override Encoder GetEncoder()
+ {
+ return new EncoderNLS(this);
+ }
+
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 4 bytes per char
+ byteCount *= 4;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // A supplementary character becomes 2 surrogate characters, so 4 input bytes becomes 2 chars,
+ // plus we may have 1 surrogate char left over if the decoder has 3 bytes in it already for a non-bmp char.
+ // Have to add another one because 1/2 == 0, but 3 bytes left over could be 2 char surrogate pair
+ int charCount = (byteCount / 2) + 2;
+
+ // Also consider fallback because our input bytes could be out of range of unicode.
+ // Since fallback would fallback 4 bytes at a time, we'll only fall back 1/2 of MaxCharCount.
+ if (DecoderFallback.MaxCharCount > 2)
+ {
+ // Multiply time fallback size
+ charCount *= DecoderFallback.MaxCharCount;
+
+ // We were already figuring 2 chars per 4 bytes, but fallback will be different #
+ charCount /= 2;
+ }
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+
+ public override byte[] GetPreamble()
+ {
+ if (emitUTF32ByteOrderMark)
+ {
+ // Allocate new array to prevent users from modifying it.
+ if (bigEndian)
+ {
+ return new byte[4] { 0x00, 0x00, 0xFE, 0xFF };
+ }
+ else
+ {
+ return new byte[4] { 0xFF, 0xFE, 0x00, 0x00 }; // 00 00 FE FF
+ }
+ }
+ else
+ return EmptyArray<Byte>.Value;
+ }
+
+
+ public override bool Equals(Object value)
+ {
+ UTF32Encoding that = value as UTF32Encoding;
+ if (that != null)
+ {
+ return (emitUTF32ByteOrderMark == that.emitUTF32ByteOrderMark) &&
+ (bigEndian == that.bigEndian) &&
+// (isThrowException == that.isThrowException) && // same as encoder/decoderfallback being exceptions
+ (EncoderFallback.Equals(that.EncoderFallback)) &&
+ (DecoderFallback.Equals(that.DecoderFallback));
+ }
+ return (false);
+ }
+
+
+ public override int GetHashCode()
+ {
+ //Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
+ return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() +
+ CodePage + (emitUTF32ByteOrderMark?4:0) + (bigEndian?8:0);
+ }
+
+ [Serializable]
+ internal class UTF32Decoder : DecoderNLS
+ {
+ // Need a place to store any extra bytes we may have picked up
+ internal int iChar = 0;
+ internal int readByteCount = 0;
+
+ public UTF32Decoder(UTF32Encoding encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ public override void Reset()
+ {
+ this.iChar = 0;
+ this.readByteCount = 0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ // ReadByteCount is our flag. (iChar==0 doesn't mean much).
+ return (this.readByteCount != 0);
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/UTF7Encoding.cs b/src/mscorlib/src/System/Text/UTF7Encoding.cs
new file mode 100644
index 0000000000..654fb8b80f
--- /dev/null
+++ b/src/mscorlib/src/System/Text/UTF7Encoding.cs
@@ -0,0 +1,901 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
+//
+
+namespace System.Text
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class UTF7Encoding : Encoding
+ {
+ private const String base64Chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ // 0123456789111111111122222222223333333333444444444455555555556666
+ // 012345678901234567890123456789012345678901234567890123
+
+ // These are the characters that can be directly encoded in UTF7.
+ private const String directChars =
+ "\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ // These are the characters that can be optionally directly encoded in UTF7.
+ private const String optionalChars =
+ "!\"#$%&*;<=>@[]^_`{|}";
+
+ // Used by Encoding.UTF7 for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly UTF7Encoding s_default = new UTF7Encoding();
+
+ // The set of base 64 characters.
+ private byte[] base64Bytes;
+ // The decoded bits for every base64 values. This array has a size of 128 elements.
+ // The index is the code point value of the base 64 characters. The value is -1 if
+ // the code point is not a valid base 64 character. Otherwise, the value is a value
+ // from 0 ~ 63.
+ private sbyte[] base64Values;
+ // The array to decide if a Unicode code point below 0x80 can be directly encoded in UTF7.
+ // This array has a size of 128.
+ private bool[] directEncode;
+
+ [OptionalField(VersionAdded = 2)]
+ private bool m_allowOptionals;
+
+ private const int UTF7_CODEPAGE=65000;
+
+
+ public UTF7Encoding()
+ : this(false)
+ {
+ }
+
+ public UTF7Encoding(bool allowOptionals)
+ : base(UTF7_CODEPAGE) //Set the data item.
+ {
+ // Allowing optionals?
+ this.m_allowOptionals = allowOptionals;
+
+ // Make our tables
+ MakeTables();
+ }
+
+ private void MakeTables()
+ {
+ // Build our tables
+ base64Bytes = new byte[64];
+ for (int i = 0; i < 64; i++) base64Bytes[i] = (byte)base64Chars[i];
+ base64Values = new sbyte[128];
+ for (int i = 0; i < 128; i++) base64Values[i] = -1;
+ for (int i = 0; i < 64; i++) base64Values[base64Bytes[i]] = (sbyte)i;
+ directEncode = new bool[128];
+ int count = directChars.Length;
+ for (int i = 0; i < count; i++)
+ {
+ directEncode[directChars[i]] = true;
+ }
+
+ if (this.m_allowOptionals)
+ {
+ count = optionalChars.Length;
+ for (int i = 0; i < count; i++)
+ {
+ directEncode[optionalChars[i]] = true;
+ }
+ }
+ }
+
+ // We go ahead and set this because Encoding expects it, however nothing can fall back in UTF7.
+ internal override void SetDefaultFallbacks()
+ {
+ // UTF7 had an odd decoderFallback behavior, and the Encoder fallback
+ // is irrelevent because we encode surrogates individually and never check for unmatched ones
+ // (so nothing can fallback during encoding)
+ this.encoderFallback = new EncoderReplacementFallback(String.Empty);
+ this.decoderFallback = new DecoderUTF7Fallback();
+ }
+
+
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ // make sure the optional fields initialized correctly.
+ base.OnDeserializing();
+ }
+
+ [OnDeserialized]
+ private void OnDeserialized(StreamingContext ctx)
+ {
+ base.OnDeserialized();
+
+ if (m_deserializedFromEverett)
+ {
+ // If 1st optional char is encoded we're allowing optionals
+ m_allowOptionals = directEncode[optionalChars[0]];
+ }
+
+ MakeTables();
+ }
+
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override bool Equals(Object value)
+ {
+ UTF7Encoding that = value as UTF7Encoding;
+ if (that != null)
+ {
+ return (m_allowOptionals == that.m_allowOptionals) &&
+ (EncoderFallback.Equals(that.EncoderFallback)) &&
+ (DecoderFallback.Equals(that.DecoderFallback));
+ }
+ return (false);
+ }
+
+ // Compared to all the other encodings, variations of UTF7 are unlikely
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetHashCode()
+ {
+ return this.CodePage + this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode();
+ }
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetByteCount(String s)
+ {
+ return EncodingForwarder.GetByteCount(this, s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, s, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override String GetString(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetString(this, bytes, index, count);
+ }
+
+ // End of overridden methods which use EncodingForwarder
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ {
+ Contract.Assert(chars!=null, "[UTF7Encoding.GetByteCount]chars!=null");
+ Contract.Assert(count >=0, "[UTF7Encoding.GetByteCount]count >=0");
+
+ // Just call GetBytes with bytes == null
+ return GetBytes(chars, count, null, 0, baseEncoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ {
+ Contract.Assert(byteCount >=0, "[UTF7Encoding.GetBytes]byteCount >=0");
+ Contract.Assert(chars!=null, "[UTF7Encoding.GetBytes]chars!=null");
+ Contract.Assert(charCount >=0, "[UTF7Encoding.GetBytes]charCount >=0");
+
+ // Get encoder info
+ UTF7Encoding.Encoder encoder = (UTF7Encoding.Encoder)baseEncoder;
+
+ // Default bits & count
+ int bits = 0;
+ int bitCount = -1;
+
+ // prepare our helpers
+ Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer(
+ this, encoder, bytes, byteCount, chars, charCount);
+
+ if (encoder != null)
+ {
+ bits = encoder.bits;
+ bitCount = encoder.bitCount;
+
+ // May have had too many left over
+ while (bitCount >= 6)
+ {
+ bitCount -= 6;
+ // If we fail we'll never really have enough room
+ if (!buffer.AddByte(base64Bytes[(bits >> bitCount) & 0x3F]))
+ ThrowBytesOverflow(encoder, buffer.Count == 0);
+ }
+ }
+
+ while (buffer.MoreData)
+ {
+ char currentChar = buffer.GetNextChar();
+
+ if (currentChar < 0x80 && directEncode[currentChar])
+ {
+ if (bitCount >= 0)
+ {
+ if (bitCount > 0)
+ {
+ // Try to add the next byte
+ if (!buffer.AddByte(base64Bytes[bits << 6 - bitCount & 0x3F]))
+ break; // Stop here, didn't throw
+
+ bitCount = 0;
+ }
+
+ // Need to get emit '-' and our char, 2 bytes total
+ if (!buffer.AddByte((byte)'-'))
+ break; // Stop here, didn't throw
+
+ bitCount = -1;
+ }
+
+ // Need to emit our char
+ if (!buffer.AddByte((byte)currentChar))
+ break; // Stop here, didn't throw
+ }
+ else if (bitCount < 0 && currentChar == '+')
+ {
+ if (!buffer.AddByte((byte)'+', (byte)'-'))
+ break; // Stop here, didn't throw
+ }
+ else
+ {
+ if (bitCount < 0)
+ {
+ // Need to emit a + and 12 bits (3 bytes)
+ // Only 12 of the 16 bits will be emitted this time, the other 4 wait 'til next time
+ if (!buffer.AddByte((byte)'+'))
+ break; // Stop here, didn't throw
+
+ // We're now in bit mode, but haven't stored data yet
+ bitCount = 0;
+ }
+
+ // Add our bits
+ bits = bits << 16 | currentChar;
+ bitCount += 16;
+
+ while (bitCount >= 6)
+ {
+ bitCount -= 6;
+ if (!buffer.AddByte(base64Bytes[(bits >> bitCount) & 0x3F]))
+ {
+ bitCount += 6; // We didn't use these bits
+ currentChar = buffer.GetNextChar(); // We're processing this char still, but AddByte
+ // --'d it when we ran out of space
+ break; // Stop here, not enough room for bytes
+ }
+ }
+
+ if (bitCount >= 6)
+ break; // Didn't have room to encode enough bits
+ }
+ }
+
+ // Now if we have bits left over we have to encode them.
+ // MustFlush may have been cleared by encoding.ThrowBytesOverflow earlier if converting
+ if (bitCount >= 0 && (encoder == null || encoder.MustFlush))
+ {
+ // Do we have bits we have to stick in?
+ if (bitCount > 0)
+ {
+ if (buffer.AddByte(base64Bytes[(bits << (6 - bitCount)) & 0x3F]))
+ {
+ // Emitted spare bits, 0 bits left
+ bitCount = 0;
+ }
+ }
+
+ // If converting and failed bitCount above, then we'll fail this too
+ if (buffer.AddByte((byte)'-'))
+ {
+ // turned off bit mode';
+ bits = 0;
+ bitCount = -1;
+ }
+ else
+ // If not successful, convert will maintain state for next time, also
+ // AddByte will have decremented our char count, however we need it to remain the same
+ buffer.GetNextChar();
+ }
+
+ // Do we have an encoder we're allowed to use?
+ // bytes == null if counting, so don't use encoder then
+ if (bytes != null && encoder != null)
+ {
+ // We already cleared bits & bitcount for mustflush case
+ encoder.bits = bits;
+ encoder.bitCount = bitCount;
+ encoder.m_charsUsed = buffer.CharsUsed;
+ }
+
+ return buffer.Count;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(count >=0, "[UTF7Encoding.GetCharCount]count >=0");
+ Contract.Assert(bytes!=null, "[UTF7Encoding.GetCharCount]bytes!=null");
+
+ // Just call GetChars with null char* to do counting
+ return GetChars(bytes, count, null, 0, baseDecoder);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(byteCount >=0, "[UTF7Encoding.GetChars]byteCount >=0");
+ Contract.Assert(bytes!=null, "[UTF7Encoding.GetChars]bytes!=null");
+ Contract.Assert(charCount >=0, "[UTF7Encoding.GetChars]charCount >=0");
+
+ // Might use a decoder
+ UTF7Encoding.Decoder decoder = (UTF7Encoding.Decoder) baseDecoder;
+
+ // Get our output buffer info.
+ Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer(
+ this, decoder, chars, charCount, bytes, byteCount);
+
+ // Get decoder info
+ int bits = 0;
+ int bitCount = -1;
+ bool firstByte = false;
+ if (decoder != null)
+ {
+ bits = decoder.bits;
+ bitCount = decoder.bitCount;
+ firstByte = decoder.firstByte;
+
+ Contract.Assert(firstByte == false || decoder.bitCount <= 0,
+ "[UTF7Encoding.GetChars]If remembered bits, then first byte flag shouldn't be set");
+ }
+
+ // We may have had bits in the decoder that we couldn't output last time, so do so now
+ if (bitCount >= 16)
+ {
+ // Check our decoder buffer
+ if (!buffer.AddChar((char)((bits >> (bitCount - 16)) & 0xFFFF)))
+ ThrowCharsOverflow(decoder, true); // Always throw, they need at least 1 char even in Convert
+
+ // Used this one, clean up extra bits
+ bitCount -= 16;
+ }
+
+ // Loop through the input
+ while (buffer.MoreData)
+ {
+ byte currentByte = buffer.GetNextByte();
+ int c;
+
+ if (bitCount >= 0)
+ {
+ //
+ // Modified base 64 encoding.
+ //
+ sbyte v;
+ if (currentByte < 0x80 && ((v = base64Values[currentByte]) >=0))
+ {
+ firstByte = false;
+ bits = (bits << 6) | ((byte)v);
+ bitCount += 6;
+ if (bitCount >= 16)
+ {
+ c = (bits >> (bitCount - 16)) & 0xFFFF;
+ bitCount -= 16;
+ }
+ // If not enough bits just continue
+ else continue;
+ }
+ else
+ {
+ // If it wasn't a base 64 byte, everything's going to turn off base 64 mode
+ bitCount = -1;
+
+ if (currentByte != '-')
+ {
+ // >= 0x80 (because of 1st if statemtn)
+ // We need this check since the base64Values[b] check below need b <= 0x7f.
+ // This is not a valid base 64 byte. Terminate the shifted-sequence and
+ // emit this byte.
+
+ // not in base 64 table
+ // According to the RFC 1642 and the example code of UTF-7
+ // in Unicode 2.0, we should just zero-extend the invalid UTF7 byte
+
+ // Chars won't be updated unless this works, try to fallback
+ if (!buffer.Fallback(currentByte))
+ break; // Stop here, didn't throw
+
+ // Used that byte, we're done with it
+ continue;
+ }
+
+ //
+ // The encoding for '+' is "+-".
+ //
+ if (firstByte) c = '+';
+ // We just turn it off if not emitting a +, so we're done.
+ else continue;
+ }
+ //
+ // End of modified base 64 encoding block.
+ //
+ }
+ else if (currentByte == '+')
+ {
+ //
+ // Found the start of a modified base 64 encoding block or a plus sign.
+ //
+ bitCount = 0;
+ firstByte = true;
+ continue;
+ }
+ else
+ {
+ // Normal character
+ if (currentByte >= 0x80)
+ {
+ // Try to fallback
+ if (!buffer.Fallback(currentByte))
+ break; // Stop here, didn't throw
+
+ // Done falling back
+ continue;
+ }
+
+ // Use the normal character
+ c = currentByte;
+ }
+
+ if (c >= 0)
+ {
+ // Check our buffer
+ if (!buffer.AddChar((char)c))
+ {
+ // No room. If it was a plain char we'll try again later.
+ // Note, we'll consume this byte and stick it in decoder, even if we can't output it
+ if (bitCount >= 0) // Can we rememmber this byte (char)
+ {
+ buffer.AdjustBytes(+1); // Need to readd the byte that AddChar subtracted when it failed
+ bitCount += 16; // We'll still need that char we have in our bits
+ }
+ break; // didn't throw, stop
+ }
+ }
+ }
+
+ // Stick stuff in the decoder if we can (chars == null if counting, so don't store decoder)
+ if (chars != null && decoder != null)
+ {
+ // MustFlush? (Could've been cleared by ThrowCharsOverflow if Convert & didn't reach end of buffer)
+ if (decoder.MustFlush)
+ {
+ // RFC doesn't specify what would happen if we have non-0 leftover bits, we just drop them
+ decoder.bits = 0;
+ decoder.bitCount = -1;
+ decoder.firstByte = false;
+ }
+ else
+ {
+ decoder.bits = bits;
+ decoder.bitCount = bitCount;
+ decoder.firstByte = firstByte;
+ }
+ decoder.m_bytesUsed = buffer.BytesUsed;
+ }
+ // else ignore any hanging bits.
+
+ // Return our count
+ return buffer.Count;
+ }
+
+
+ public override System.Text.Decoder GetDecoder()
+ {
+ return new UTF7Encoding.Decoder(this);
+ }
+
+
+ public override System.Text.Encoder GetEncoder()
+ {
+ return new UTF7Encoding.Encoder(this);
+ }
+
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Suppose that every char can not be direct-encoded, we know that
+ // a byte can encode 6 bits of the Unicode character. And we will
+ // also need two extra bytes for the shift-in ('+') and shift-out ('-') mark.
+ // Therefore, the max byte should be:
+ // byteCount = 2 + Math.Ceiling((double)charCount * 16 / 6);
+ // That is always <= 2 + 3 * charCount;
+ // Longest case is alternating encoded, direct, encoded data for 5 + 1 + 5... bytes per char.
+ // UTF7 doesn't have left over surrogates, but if no input we may need an output - to turn off
+ // encoding if MustFlush is true.
+
+ // Its easiest to think of this as 2 bytes to turn on/off the base64 mode, then 3 bytes per char.
+ // 3 bytes is 18 bits of encoding, which is more than we need, but if its direct encoded then 3
+ // bytes allows us to turn off and then back on base64 mode if necessary.
+
+ // Note that UTF7 encoded surrogates individually and isn't worried about mismatches, so all
+ // code points are encodable int UTF7.
+ long byteCount = (long)charCount * 3 + 2;
+
+ // check for overflow
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Worst case is 1 char per byte. Minimum 1 for left over bits in case decoder is being flushed
+ // Also note that we ignore extra bits (per spec), so UTF7 doesn't have unknown in this direction.
+ int charCount = byteCount;
+ if (charCount == 0) charCount = 1;
+
+ return charCount;
+ }
+
+ [Serializable]
+ // Of all the amazing things... This MUST be Decoder so that our com name
+ // for System.Text.Decoder doesn't change
+ private class Decoder : DecoderNLS, ISerializable
+ {
+ /*private*/
+ internal int bits;
+ /*private*/ internal int bitCount;
+ /*private*/ internal bool firstByte;
+
+ public Decoder(UTF7Encoding encoding) : base (encoding)
+ {
+ // base calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal Decoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Get common info
+ this.bits = (int)info.GetValue("bits", typeof(int));
+ this.bitCount = (int)info.GetValue("bitCount", typeof(int));
+ this.firstByte = (bool)info.GetValue("firstByte", typeof(bool));
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save Whidbey data
+ info.AddValue("encoding", this.m_encoding);
+ info.AddValue("bits", this.bits);
+ info.AddValue("bitCount", this.bitCount);
+ info.AddValue("firstByte", this.firstByte);
+ }
+
+ public override void Reset()
+ {
+ this.bits = 0;
+ this.bitCount = -1;
+ this.firstByte = false;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our encoder?
+ internal override bool HasState
+ {
+ get
+ {
+ // NOTE: This forces the last -, which some encoder might not encode. If we
+ // don't see it we don't think we're done reading.
+ return (this.bitCount != -1);
+ }
+ }
+ }
+
+ [Serializable]
+ // Of all the amazing things... This MUST be Encoder so that our com name
+ // for System.Text.Encoder doesn't change
+ private class Encoder : EncoderNLS, ISerializable
+ {
+ /*private*/
+ internal int bits;
+ /*private*/ internal int bitCount;
+
+ public Encoder(UTF7Encoding encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal Encoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Get common info
+ this.bits = (int)info.GetValue("bits", typeof(int));
+ this.bitCount = (int)info.GetValue("bitCount", typeof(int));
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save Whidbey data
+ info.AddValue("encoding", this.m_encoding);
+ info.AddValue("bits", this.bits);
+ info.AddValue("bitCount", this.bitCount);
+ }
+
+ public override void Reset()
+ {
+ this.bitCount = -1;
+ this.bits = 0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our encoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.bits != 0 || this.bitCount != -1);
+ }
+ }
+ }
+
+ // Preexisting UTF7 behavior for bad bytes was just to spit out the byte as the next char
+ // and turn off base64 mode if it was in that mode. We still exit the mode, but now we fallback.
+ [Serializable]
+ internal sealed class DecoderUTF7Fallback : DecoderFallback
+ {
+ // Construction. Default replacement fallback uses no best fit and ? replacement string
+ public DecoderUTF7Fallback()
+ {
+ }
+
+ public override DecoderFallbackBuffer CreateFallbackBuffer()
+ {
+ return new DecoderUTF7FallbackBuffer(this);
+ }
+
+ // Maximum number of characters that this instance of this fallback could return
+ public override int MaxCharCount
+ {
+ get
+ {
+ // returns 1 char per bad byte
+ return 1;
+ }
+ }
+
+ public override bool Equals(Object value)
+ {
+ DecoderUTF7Fallback that = value as DecoderUTF7Fallback;
+ if (that != null)
+ {
+ return true;
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return 984;
+ }
+ }
+
+ internal sealed class DecoderUTF7FallbackBuffer : DecoderFallbackBuffer
+ {
+ // Store our default string
+ char cFallback = (char)0;
+ int iCount = -1;
+ int iSize;
+
+ // Construction
+ public DecoderUTF7FallbackBuffer(DecoderUTF7Fallback fallback)
+ {
+ }
+
+ // Fallback Methods
+ public override bool Fallback(byte[] bytesUnknown, int index)
+ {
+ // We expect no previous fallback in our buffer
+ Contract.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.Fallback] Can't have recursive fallbacks");
+ Contract.Assert(bytesUnknown.Length == 1, "[DecoderUTF7FallbackBuffer.Fallback] Only possible fallback case should be 1 unknown byte");
+
+ // Go ahead and get our fallback
+ cFallback = (char)bytesUnknown[0];
+
+ // Any of the fallback characters can be handled except for 0
+ if (cFallback == 0)
+ {
+ return false;
+ }
+
+ iCount = iSize = 1;
+
+ return true;
+ }
+
+ public override char GetNextChar()
+ {
+ if (iCount-- > 0)
+ return cFallback;
+
+ // Note: this means that 0 in UTF7 stream will never be emitted.
+ return (char)0;
+ }
+
+ public override bool MovePrevious()
+ {
+ if (iCount >= 0)
+ {
+ iCount++;
+ }
+
+ // return true if we were allowed to do this
+ return (iCount >= 0 && iCount <= iSize);
+ }
+
+ // Return # of chars left in this fallback
+ public override int Remaining
+ {
+ get
+ {
+ return (iCount > 0) ? iCount : 0;
+ }
+ }
+
+ // Clear the buffer
+ [System.Security.SecuritySafeCritical] // overrides public transparent member
+ public override unsafe void Reset()
+ {
+ iCount = -1;
+ byteStart = null;
+ }
+
+ // This version just counts the fallback and doesn't actually copy anything.
+ [System.Security.SecurityCritical] // auto-generated
+ internal unsafe override int InternalFallback(byte[] bytes, byte* pBytes)
+ // Right now this has both bytes and bytes[], since we might have extra bytes, hence the
+ // array, and we might need the index, hence the byte*
+ {
+ // We expect no previous fallback in our buffer
+ Contract.Assert(iCount < 0, "[DecoderUTF7FallbackBuffer.InternalFallback] Can't have recursive fallbacks");
+ if (bytes.Length != 1)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidCharSequenceNoIndex"));
+ }
+
+ // Can't fallback a byte 0, so return for that case, 1 otherwise.
+ return bytes[0] == 0 ? 0 : 1;
+ }
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Text/UTF8Encoding.cs b/src/mscorlib/src/System/Text/UTF8Encoding.cs
new file mode 100644
index 0000000000..a527de7b61
--- /dev/null
+++ b/src/mscorlib/src/System/Text/UTF8Encoding.cs
@@ -0,0 +1,2307 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+// The worker functions in this file was optimized for performance. If you make changes
+// you should use care to consider all of the interesting cases.
+
+// The code of all worker functions in this file is written twice: Once as as a slow loop, and the
+// second time as a fast loop. The slow loops handles all special cases, throws exceptions, etc.
+// The fast loops attempts to blaze through as fast as possible with optimistic range checks,
+// processing multiple characters at a time, and falling back to the slow loop for all special cases.
+
+// This define can be used to turn off the fast loops. Useful for finding whether
+// the problem is fastloop-specific.
+#define FASTLOOP
+
+namespace System.Text
+{
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ // Encodes text into and out of UTF-8. UTF-8 is a way of writing
+ // Unicode characters with variable numbers of bytes per character,
+ // optimized for the lower 127 ASCII characters. It's an efficient way
+ // of encoding US English in an internationalizable way.
+ //
+ // Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
+ //
+ // The UTF-8 byte order mark is simply the Unicode byte order mark
+ // (0xFEFF) written in UTF-8 (0xEF 0xBB 0xBF). The byte order mark is
+ // used mostly to distinguish UTF-8 text from other encodings, and doesn't
+ // switch the byte orderings.
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class UTF8Encoding : Encoding
+ {
+ /*
+ bytes bits UTF-8 representation
+ ----- ---- -----------------------------------
+ 1 7 0vvvvvvv
+ 2 11 110vvvvv 10vvvvvv
+ 3 16 1110vvvv 10vvvvvv 10vvvvvv
+ 4 21 11110vvv 10vvvvvv 10vvvvvv 10vvvvvv
+ ----- ---- -----------------------------------
+
+ Surrogate:
+ Real Unicode value = (HighSurrogate - 0xD800) * 0x400 + (LowSurrogate - 0xDC00) + 0x10000
+ */
+
+ private const int UTF8_CODEPAGE=65001;
+
+ // Used by Encoding.UTF8 for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly UTF8Encoding s_default = new UTF8Encoding(encoderShouldEmitUTF8Identifier: true);
+
+ // Yes, the idea of emitting U+FEFF as a UTF-8 identifier has made it into
+ // the standard.
+ private bool emitUTF8Identifier = false;
+
+ private bool isThrowException = false;
+
+
+ public UTF8Encoding(): this(false)
+ {
+ }
+
+
+ public UTF8Encoding(bool encoderShouldEmitUTF8Identifier):
+ this(encoderShouldEmitUTF8Identifier, false)
+ {
+ }
+
+
+ public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes):
+ base(UTF8_CODEPAGE)
+ {
+ this.emitUTF8Identifier = encoderShouldEmitUTF8Identifier;
+ this.isThrowException = throwOnInvalidBytes;
+
+ // Encoding's constructor already did this, but it'll be wrong if we're throwing exceptions
+ if (this.isThrowException)
+ SetDefaultFallbacks();
+ }
+
+ internal override void SetDefaultFallbacks()
+ {
+ // For UTF-X encodings, we use a replacement fallback with an empty string
+ if (this.isThrowException)
+ {
+ this.encoderFallback = EncoderFallback.ExceptionFallback;
+ this.decoderFallback = DecoderFallback.ExceptionFallback;
+ }
+ else
+ {
+ this.encoderFallback = new EncoderReplacementFallback("\xFFFD");
+ this.decoderFallback = new DecoderReplacementFallback("\xFFFD");
+ }
+ }
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ public override int GetByteCount(String chars)
+ {
+ return EncodingForwarder.GetByteCount(this, chars);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ public override int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, s, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override String GetString(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetString(this, bytes, index, count);
+ }
+
+ // End of overridden methods which use EncodingForwarder
+
+ // To simplify maintenance, the structure of GetByteCount and GetBytes should be
+ // kept the same as much as possible
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char *chars, int count, EncoderNLS baseEncoder)
+ {
+ // For fallback we may need a fallback buffer.
+ // We wait to initialize it though in case we don't have any broken input unicode
+ EncoderFallbackBuffer fallbackBuffer = null;
+ char *pSrc = chars;
+ char *pEnd = pSrc+count;
+
+ // Start by assuming we have as many as count
+ int byteCount = count;
+
+ int ch = 0;
+
+ if (baseEncoder != null) {
+ UTF8Encoder encoder = (UTF8Encoder)baseEncoder;
+ ch = encoder.surrogateChar;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(chars, pEnd, encoder, false);
+ }
+ }
+
+ for (;;) {
+ // SLOWLOOP: does all range checks, handles all special cases, but it is slow
+ if (pSrc >= pEnd) {
+
+ if (ch == 0) {
+ // Unroll any fallback that happens at the end
+ ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0;
+ if (ch > 0) {
+ byteCount++;
+ goto ProcessChar;
+ }
+ } else {
+ // Case of surrogates in the fallback.
+ if (fallbackBuffer != null && fallbackBuffer.bFallingBack) {
+ Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF,
+ "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
+
+ ch = fallbackBuffer.InternalGetNextChar();
+ byteCount++;
+
+ if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ ch = 0xfffd;
+ byteCount++;
+ goto EncodeChar;
+ } else if (ch > 0){
+ goto ProcessChar;
+ } else {
+ byteCount--; // ignore last one.
+ break;
+ }
+ }
+ }
+
+ if (ch <= 0) {
+ break;
+ }
+ if (baseEncoder != null && !baseEncoder.MustFlush) {
+ break;
+ }
+
+ // attempt to encode the partial surrogate (will fallback or ignore it), it'll also subtract 1.
+ byteCount++;
+ goto EncodeChar;
+ }
+
+ if (ch > 0) {
+ Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF,
+ "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
+
+ // use separate helper variables for local contexts so that the jit optimizations
+ // won't get confused about the variable lifetimes
+ int cha = *pSrc;
+
+ // count the pending surrogate
+ byteCount++;
+
+ // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
+ // if (IsLowSurrogate(cha)) {
+ if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ // Don't need a real # because we're just counting, anything > 0x7ff ('cept surrogate) will do.
+ ch = 0xfffd;
+// ch = cha + (ch << 10) +
+// (0x10000
+// - CharUnicodeInfo.LOW_SURROGATE_START
+// - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) );
+
+ // Use this next char
+ pSrc++;
+ }
+ // else ch is still high surrogate and encoding will fail (so don't add count)
+
+ // attempt to encode the surrogate or partial surrogate
+ goto EncodeChar;
+ }
+
+ // If we've used a fallback, then we have to check for it
+ if (fallbackBuffer != null)
+ {
+ ch = fallbackBuffer.InternalGetNextChar();
+ if (ch > 0)
+ {
+ // We have an extra byte we weren't expecting.
+ byteCount++;
+ goto ProcessChar;
+ }
+ }
+
+ // read next char. The JIT optimization seems to be getting confused when
+ // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
+ ch = *pSrc;
+ pSrc++;
+
+ ProcessChar:
+ // if (IsHighSurrogate(ch)) {
+ if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) {
+ // we will count this surrogate next time around
+ byteCount--;
+ continue;
+ }
+ // either good char or partial surrogate
+
+ EncodeChar:
+ // throw exception on partial surrogate if necessary
+ // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
+ if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END))
+ {
+ // Lone surrogates aren't allowed
+ // Have to make a fallback buffer if we don't have one
+ if (fallbackBuffer == null)
+ {
+ // wait on fallbacks if we can
+ // For fallback we may need a fallback buffer
+ if (baseEncoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = baseEncoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(chars, chars + count, baseEncoder, false);
+ }
+
+ // Do our fallback. Actually we already know its a mixed up surrogate,
+ // so the ref pSrc isn't gonna do anything.
+ fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrc);
+
+ // Ignore it if we don't throw (we had preallocated this ch)
+ byteCount--;
+ ch = 0;
+ continue;
+ }
+
+ // Count them
+ if (ch > 0x7F) {
+ if (ch > 0x7FF) {
+ // the extra surrogate byte was compensated by the second surrogate character
+ // (2 surrogates make 4 bytes. We've already counted 2 bytes, 1 per char)
+ byteCount++;
+ }
+ byteCount++;
+ }
+
+#if BIT64
+ // check for overflow
+ if (byteCount < 0) {
+ break;
+ }
+#endif
+
+#if FASTLOOP
+ // If still have fallback don't do fast loop
+ if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0)
+ {
+ // We're reserving 1 byte for each char by default
+ byteCount++;
+ goto ProcessChar;
+ }
+
+ int availableChars = PtrDiff(pEnd, pSrc);
+
+ // don't fall into the fast decoding loop if we don't have enough characters
+ if (availableChars <= 13) {
+ // try to get over the remainder of the ascii characters fast though
+ char* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
+ while (pSrc < pLocalEnd) {
+ ch = *pSrc;
+ pSrc++;
+ if (ch > 0x7F)
+ goto ProcessChar;
+ }
+
+ // we are done
+ break;
+ }
+
+#if BIT64
+ // make sure that we won't get a silent overflow inside the fast loop
+ // (Fall out to slow loop if we have this many characters)
+ availableChars &= 0x0FFFFFFF;
+#endif
+
+ // To compute the upper bound, assume that all characters are ASCII characters at this point,
+ // the boundary will be decreased for every non-ASCII character we encounter
+ // Also, we need 3 + 4 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
+ char *pStop = pSrc + availableChars - (3 + 4);
+
+ while (pSrc < pStop) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F) // Not ASCII
+ {
+ if (ch > 0x7FF) // Not 2 Byte
+ {
+ if ((ch & 0xF800) == 0xD800) // See if its a Surrogate
+ goto LongCode;
+ byteCount++;
+ }
+ byteCount ++;
+ }
+
+ // get pSrc aligned
+ if ((unchecked((int)pSrc) & 0x2) != 0) {
+ ch = *pSrc;
+ pSrc++;
+ if (ch > 0x7F) // Not ASCII
+ {
+ if (ch > 0x7FF) // Not 2 Byte
+ {
+ if ((ch & 0xF800) == 0xD800) // See if its a Surrogate
+ goto LongCode;
+ byteCount++;
+ }
+ byteCount ++;
+ }
+ }
+
+ // Run 2 * 4 characters at a time!
+ while (pSrc < pStop) {
+ ch = *(int*)pSrc;
+ int chc = *(int*)(pSrc+2);
+ if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) // See if not ASCII
+ {
+ if (((ch | chc) & unchecked((int)0xF800F800)) != 0) // See if not 2 Byte
+ {
+ goto LongCodeWithMask;
+ }
+
+
+ if ((ch & unchecked((int)0xFF800000)) != 0) // Actually 0x07800780 is all we care about (4 bits)
+ byteCount++;
+ if ((ch & unchecked((int)0xFF80)) != 0)
+ byteCount++;
+ if ((chc & unchecked((int)0xFF800000)) != 0)
+ byteCount++;
+ if ((chc & unchecked((int)0xFF80)) != 0)
+ byteCount++;
+ }
+ pSrc += 4;
+
+ ch = *(int*)pSrc;
+ chc = *(int*)(pSrc+2);
+ if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) // See if not ASCII
+ {
+ if (((ch | chc) & unchecked((int)0xF800F800)) != 0) // See if not 2 Byte
+ {
+ goto LongCodeWithMask;
+ }
+
+ if ((ch & unchecked((int)0xFF800000)) != 0)
+ byteCount++;
+ if ((ch & unchecked((int)0xFF80)) != 0)
+ byteCount++;
+ if ((chc & unchecked((int)0xFF800000)) != 0)
+ byteCount++;
+ if ((chc & unchecked((int)0xFF80)) != 0)
+ byteCount++;
+ }
+ pSrc += 4;
+ }
+ break;
+
+ LongCodeWithMask:
+#if BIGENDIAN
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+#else // BIGENDIAN
+ ch = (char)ch;
+#endif // BIGENDIAN
+ pSrc++;
+
+ if (ch <= 0x7F) {
+ continue;
+ }
+
+ LongCode:
+ // use separate helper variables for slow and fast loop so that the jit optimizations
+ // won't get confused about the variable lifetimes
+ if (ch > 0x7FF) {
+ // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
+ if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ // 4 byte encoding - high surrogate + low surrogate
+
+ int chd = *pSrc;
+ if (
+ // !IsHighSurrogate(ch) // low without high -> bad
+ ch > CharUnicodeInfo.HIGH_SURROGATE_END ||
+ // !IsLowSurrogate(chd) // high not followed by low -> bad
+ !InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END) )
+ {
+ // Back up and drop out to slow loop to figure out error
+ pSrc--;
+ break;
+ }
+ pSrc++;
+
+ // byteCount - this byte is compensated by the second surrogate character
+ }
+ byteCount++;
+ }
+ byteCount++;
+
+ // byteCount - the last byte is already included
+ }
+#endif // FASTLOOP
+
+ // no pending char at this point
+ ch = 0;
+ }
+
+#if BIT64
+ // check for overflow
+ if (byteCount < 0) {
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_ConversionOverflow"));
+ }
+#endif
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[UTF8Encoding.GetByteCount]Expected Empty fallback buffer");
+
+ return byteCount;
+ }
+
+ // diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
+ // is good enough for us, and it tends to generate better code than the signed
+ // arithmetic generated by default
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe private static int PtrDiff(char *a, char* b)
+ {
+ return (int)(((uint)((byte*)a - (byte*)b)) >> 1);
+ }
+
+ // byte* flavor just for parity
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe private static int PtrDiff(byte* a, byte* b)
+ {
+ return (int)(a - b);
+ }
+
+ private static bool InRange(int ch, int start, int end)
+ {
+ return (uint)(ch - start) <= (uint)(end - start);
+ }
+
+ // Our workhorse
+ // Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ {
+ Contract.Assert(chars!=null, "[UTF8Encoding.GetBytes]chars!=null");
+ Contract.Assert(byteCount >=0, "[UTF8Encoding.GetBytes]byteCount >=0");
+ Contract.Assert(charCount >=0, "[UTF8Encoding.GetBytes]charCount >=0");
+ Contract.Assert(bytes!=null, "[UTF8Encoding.GetBytes]bytes!=null");
+
+ UTF8Encoder encoder = null;
+
+ // For fallback we may need a fallback buffer.
+ // We wait to initialize it though in case we don't have any broken input unicode
+ EncoderFallbackBuffer fallbackBuffer = null;
+ char *pSrc = chars;
+ byte *pTarget = bytes;
+
+ char *pEnd = pSrc+charCount;
+ byte *pAllocatedBufferEnd = pTarget+byteCount;
+
+ int ch = 0;
+
+ // assume that JIT will enregister pSrc, pTarget and ch
+
+ if (baseEncoder != null) {
+ encoder = (UTF8Encoder)baseEncoder;
+ ch = encoder.surrogateChar;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(chars, pEnd, encoder, true);
+ }
+ }
+
+ for (;;) {
+ // SLOWLOOP: does all range checks, handles all special cases, but it is slow
+
+ if (pSrc >= pEnd) {
+
+ if (ch == 0) {
+ // Check if there's anthing left to get out of the fallback buffer
+ ch = fallbackBuffer != null ? fallbackBuffer.InternalGetNextChar() : 0;
+ if (ch > 0) {
+ goto ProcessChar;
+ }
+ } else {
+ // Case of leftover surrogates in the fallback buffer
+ if (fallbackBuffer != null && fallbackBuffer.bFallingBack) {
+ Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF,
+ "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
+
+ int cha = ch;
+
+ ch = fallbackBuffer.InternalGetNextChar();
+
+ if (InRange(ch, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ ch = ch + (cha << 10) + (0x10000 - CharUnicodeInfo.LOW_SURROGATE_START - (CharUnicodeInfo.HIGH_SURROGATE_START << 10));
+ goto EncodeChar;
+ } else if (ch > 0){
+ goto ProcessChar;
+ } else {
+ break;
+ }
+ }
+ }
+
+ // attempt to encode the partial surrogate (will fail or ignore)
+ if (ch > 0 && (encoder == null || encoder.MustFlush))
+ goto EncodeChar;
+
+ // We're done
+ break;
+ }
+
+ if (ch > 0) {
+ // We have a high surrogate left over from a previous loop.
+ Contract.Assert(ch >= 0xD800 && ch <= 0xDBFF,
+ "[UTF8Encoding.GetBytes]expected high surrogate, not 0x" + ((int)ch).ToString("X4", CultureInfo.InvariantCulture));
+
+ // use separate helper variables for local contexts so that the jit optimizations
+ // won't get confused about the variable lifetimes
+ int cha = *pSrc;
+
+ // In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
+ // if (IsLowSurrogate(cha)) {
+ if (InRange(cha, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ ch = cha + (ch << 10) +
+ (0x10000
+ - CharUnicodeInfo.LOW_SURROGATE_START
+ - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) );
+
+ pSrc++;
+ }
+ // else ch is still high surrogate and encoding will fail
+
+ // attempt to encode the surrogate or partial surrogate
+ goto EncodeChar;
+ }
+
+ // If we've used a fallback, then we have to check for it
+ if (fallbackBuffer != null)
+ {
+ ch = fallbackBuffer.InternalGetNextChar();
+ if (ch > 0) goto ProcessChar;
+ }
+
+ // read next char. The JIT optimization seems to be getting confused when
+ // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
+ ch = *pSrc;
+ pSrc++;
+
+ ProcessChar:
+ // if (IsHighSurrogate(ch)) {
+ if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.HIGH_SURROGATE_END)) {
+ continue;
+ }
+ // either good char or partial surrogate
+
+ EncodeChar:
+ // throw exception on partial surrogate if necessary
+ // if (IsLowSurrogate(ch) || IsHighSurrogate(ch))
+ if (InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END))
+ {
+ // Lone surrogates aren't allowed, we have to do fallback for them
+ // Have to make a fallback buffer if we don't have one
+ if (fallbackBuffer == null)
+ {
+ // wait on fallbacks if we can
+ // For fallback we may need a fallback buffer
+ if (baseEncoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = baseEncoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(chars, pEnd, baseEncoder, true);
+ }
+
+ // Do our fallback. Actually we already know its a mixed up surrogate,
+ // so the ref pSrc isn't gonna do anything.
+ fallbackBuffer.InternalFallback(unchecked((char)ch), ref pSrc);
+
+ // Ignore it if we don't throw
+ ch = 0;
+ continue;
+ }
+
+ // Count bytes needed
+ int bytesNeeded = 1;
+ if (ch > 0x7F) {
+ if (ch > 0x7FF) {
+ if (ch > 0xFFFF) {
+ bytesNeeded++; // 4 bytes (surrogate pair)
+ }
+ bytesNeeded++; // 3 bytes (800-FFFF)
+ }
+ bytesNeeded++; // 2 bytes (80-7FF)
+ }
+
+ if (pTarget > pAllocatedBufferEnd - bytesNeeded) {
+ // Left over surrogate from last time will cause pSrc == chars, so we'll throw
+ if (fallbackBuffer != null && fallbackBuffer.bFallingBack)
+ {
+ fallbackBuffer.MovePrevious(); // Didn't use this fallback char
+ if (ch > 0xFFFF)
+ fallbackBuffer.MovePrevious(); // Was surrogate, didn't use 2nd part either
+ }
+ else
+ {
+ pSrc--; // Didn't use this char
+ if (ch > 0xFFFF)
+ pSrc--; // Was surrogate, didn't use 2nd part either
+ }
+ Contract.Assert(pSrc >= chars || pTarget == bytes,
+ "[UTF8Encoding.GetBytes]Expected pSrc to be within buffer or to throw with insufficient room.");
+ ThrowBytesOverflow(encoder, pTarget == bytes); // Throw if we must
+ ch = 0; // Nothing left over (we backed up to start of pair if supplimentary)
+ break;
+ }
+
+ if (ch <= 0x7F) {
+ *pTarget = (byte)ch;
+ }
+ else {
+ // use separate helper variables for local contexts so that the jit optimizations
+ // won't get confused about the variable lifetimes
+ int chb;
+ if (ch <= 0x7FF) {
+ // 2 byte encoding
+ chb = (byte)(unchecked((sbyte)0xC0) | (ch >> 6));
+ }
+ else
+ {
+ if (ch <= 0xFFFF) {
+ chb = (byte)(unchecked((sbyte)0xE0) | (ch >> 12));
+ }
+ else
+ {
+ *pTarget = (byte)(unchecked((sbyte)0xF0) | (ch >> 18));
+ pTarget++;
+
+ chb = unchecked((sbyte)0x80) | (ch >> 12) & 0x3F;
+ }
+ *pTarget = (byte)chb;
+ pTarget++;
+
+ chb = unchecked((sbyte)0x80) | (ch >> 6) & 0x3F;
+ }
+ *pTarget = (byte)chb;
+ pTarget++;
+
+ *pTarget = (byte)(unchecked((sbyte)0x80) | ch & 0x3F);
+ }
+ pTarget++;
+
+
+#if FASTLOOP
+ // If still have fallback don't do fast loop
+ if (fallbackBuffer != null && (ch = fallbackBuffer.InternalGetNextChar()) != 0)
+ goto ProcessChar;
+
+ int availableChars = PtrDiff(pEnd, pSrc);
+ int availableBytes = PtrDiff(pAllocatedBufferEnd, pTarget);
+
+ // don't fall into the fast decoding loop if we don't have enough characters
+ // Note that if we don't have enough bytes, pStop will prevent us from entering the fast loop.
+ if (availableChars <= 13) {
+ // we are hoping for 1 byte per char
+ if (availableBytes < availableChars) {
+ // not enough output room. no pending bits at this point
+ ch = 0;
+ continue;
+ }
+
+ // try to get over the remainder of the ascii characters fast though
+ char* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
+ while (pSrc < pLocalEnd) {
+ ch = *pSrc;
+ pSrc++;
+
+ // Not ASCII, need more than 1 byte per char
+ if (ch > 0x7F)
+ goto ProcessChar;
+
+ *pTarget = (byte)ch;
+ pTarget++;
+ }
+ // we are done, let ch be 0 to clear encoder
+ ch = 0;
+ break;
+ }
+
+ // we need at least 1 byte per character, but Convert might allow us to convert
+ // only part of the input, so try as much as we can. Reduce charCount if necessary
+ if (availableBytes < availableChars)
+ {
+ availableChars = availableBytes;
+ }
+
+ // FASTLOOP:
+ // - optimistic range checks
+ // - fallbacks to the slow loop for all special cases, exception throwing, etc.
+
+ // To compute the upper bound, assume that all characters are ASCII characters at this point,
+ // the boundary will be decreased for every non-ASCII character we encounter
+ // Also, we need 5 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
+ // If there aren't enough bytes for the output, then pStop will be <= pSrc and will bypass the loop.
+ char *pStop = pSrc + availableChars - 5;
+
+ while (pSrc < pStop) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ *pTarget = (byte)ch;
+ pTarget++;
+
+ // get pSrc aligned
+ if ((unchecked((int)pSrc) & 0x2) != 0) {
+ ch = *pSrc;
+ pSrc++;
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ *pTarget = (byte)ch;
+ pTarget++;
+ }
+
+ // Run 4 characters at a time!
+ while (pSrc < pStop) {
+ ch = *(int*)pSrc;
+ int chc = *(int*)(pSrc+2);
+ if (((ch | chc) & unchecked((int)0xFF80FF80)) != 0) {
+ goto LongCodeWithMask;
+ }
+
+ // Unfortunately, this is endianess sensitive
+#if BIGENDIAN
+ *pTarget = (byte)(ch>>16);
+ *(pTarget+1) = (byte)ch;
+ pSrc += 4;
+ *(pTarget+2) = (byte)(chc>>16);
+ *(pTarget+3) = (byte)chc;
+ pTarget += 4;
+#else // BIGENDIAN
+ *pTarget = (byte)ch;
+ *(pTarget+1) = (byte)(ch>>16);
+ pSrc += 4;
+ *(pTarget+2) = (byte)chc;
+ *(pTarget+3) = (byte)(chc>>16);
+ pTarget += 4;
+#endif // BIGENDIAN
+ }
+ continue;
+
+ LongCodeWithMask:
+#if BIGENDIAN
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+#else // BIGENDIAN
+ ch = (char)ch;
+#endif // BIGENDIAN
+ pSrc++;
+
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ *pTarget = (byte)ch;
+ pTarget++;
+ continue;
+
+ LongCode:
+ // use separate helper variables for slow and fast loop so that the jit optimizations
+ // won't get confused about the variable lifetimes
+ int chd;
+ if (ch <= 0x7FF) {
+ // 2 byte encoding
+ chd = unchecked((sbyte)0xC0) | (ch >> 6);
+ }
+ else {
+ // if (!IsLowSurrogate(ch) && !IsHighSurrogate(ch))
+ if (!InRange(ch, CharUnicodeInfo.HIGH_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ // 3 byte encoding
+ chd = unchecked((sbyte)0xE0) | (ch >> 12);
+ }
+ else
+ {
+ // 4 byte encoding - high surrogate + low surrogate
+ // if (!IsHighSurrogate(ch))
+ if (ch > CharUnicodeInfo.HIGH_SURROGATE_END) {
+ // low without high -> bad, try again in slow loop
+ pSrc -= 1;
+ break;
+ }
+
+ chd = *pSrc;
+ pSrc++;
+
+ // if (!IsLowSurrogate(chd)) {
+ if (!InRange(chd, CharUnicodeInfo.LOW_SURROGATE_START, CharUnicodeInfo.LOW_SURROGATE_END)) {
+ // high not followed by low -> bad, try again in slow loop
+ pSrc -= 2;
+ break;
+ }
+
+ ch = chd + (ch << 10) +
+ (0x10000
+ - CharUnicodeInfo.LOW_SURROGATE_START
+ - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) );
+
+ *pTarget = (byte)(unchecked((sbyte)0xF0) | (ch >> 18));
+ // pStop - this byte is compensated by the second surrogate character
+ // 2 input chars require 4 output bytes. 2 have been anticipated already
+ // and 2 more will be accounted for by the 2 pStop-- calls below.
+ pTarget++;
+
+ chd = unchecked((sbyte)0x80) | (ch >> 12) & 0x3F;
+ }
+ *pTarget = (byte)chd;
+ pStop--; // 3 byte sequence for 1 char, so need pStop-- and the one below too.
+ pTarget++;
+
+ chd = unchecked((sbyte)0x80) | (ch >> 6) & 0x3F;
+ }
+ *pTarget = (byte)chd;
+ pStop--; // 2 byte sequence for 1 char so need pStop--.
+ pTarget++;
+
+ *pTarget = (byte)(unchecked((sbyte)0x80) | ch & 0x3F);
+ // pStop - this byte is already included
+ pTarget++;
+ }
+
+ Contract.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetBytes]pTarget <= pAllocatedBufferEnd");
+
+#endif // FASTLOOP
+
+ // no pending char at this point
+ ch = 0;
+ }
+
+ // Do we have to set the encoder bytes?
+ if (encoder != null)
+ {
+ Contract.Assert(!encoder.MustFlush || ch == 0,
+ "[UTF8Encoding.GetBytes] Expected no mustflush or 0 leftover ch " + ch.ToString("X2", CultureInfo.InvariantCulture));
+
+ encoder.surrogateChar = ch;
+ encoder.m_charsUsed = (int)(pSrc - chars);
+ }
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
+ baseEncoder == null || !baseEncoder.m_throwOnOverflow,
+ "[UTF8Encoding.GetBytes]Expected empty fallback buffer if not converting");
+
+ return (int)(pTarget - bytes);
+ }
+
+
+ // These are bitmasks used to maintain the state in the decoder. They occupy the higher bits
+ // while the actual character is being built in the lower bits. They are shifted together
+ // with the actual bits of the character.
+
+ // bits 30 & 31 are used for pending bits fixup
+ private const int FinalByte = 1 << 29;
+ private const int SupplimentarySeq = 1 << 28;
+ private const int ThreeByteSeq = 1 << 27;
+
+ // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms.
+ // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates.
+ //
+ // To simplify maintenance, the structure of GetCharCount and GetChars should be
+ // kept the same as much as possible
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(count >=0, "[UTF8Encoding.GetCharCount]count >=0");
+ Contract.Assert(bytes!=null, "[UTF8Encoding.GetCharCount]bytes!=null");
+
+ // Initialize stuff
+ byte *pSrc = bytes;
+ byte *pEnd = pSrc+count;
+
+ // Start by assuming we have as many as count, charCount always includes the adjustment
+ // for the character being decoded
+ int charCount = count;
+ int ch = 0;
+ DecoderFallbackBuffer fallback = null;
+
+ if (baseDecoder != null) {
+ UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
+ ch = decoder.bits;
+ charCount -= (ch >> 30); // Adjust char count for # of expected bytes and expected output chars.
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at start");
+ }
+
+ for (;;)
+ {
+ // SLOWLOOP: does all range checks, handles all special cases, but it is slow
+
+ if (pSrc >= pEnd) {
+ break;
+ }
+
+ if (ch == 0) {
+ // no pending bits
+ goto ReadChar;
+ }
+
+ // read next byte. The JIT optimization seems to be getting confused when
+ // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
+ int cha = *pSrc;
+ pSrc++;
+
+ // we are expecting to see trailing bytes like 10vvvvvv
+ if ((cha & unchecked((sbyte)0xC0)) != 0x80) {
+ // This can be a valid starting byte for another UTF8 byte sequence, so let's put
+ // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
+ pSrc--;
+ charCount += (ch >> 30);
+ goto InvalidByteSequence;
+ }
+
+ // fold in the new byte
+ ch = (ch << 6) | (cha & 0x3F);
+
+ if ((ch & FinalByte) == 0) {
+ Contract.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0,
+ "[UTF8Encoding.GetChars]Invariant volation");
+
+ if ((ch & SupplimentarySeq) != 0) {
+ if ((ch & (FinalByte >> 6)) != 0) {
+ // this is 3rd byte (of 4 byte supplimentary) - nothing to do
+ continue;
+ }
+
+ // 2nd byte, check for non-shortest form of supplimentary char and the valid
+ // supplimentary characters in range 0x010000 - 0x10FFFF at the same time
+ if (!InRange(ch & 0x1F0, 0x10, 0x100)) {
+ goto InvalidByteSequence;
+ }
+ }
+ else {
+ // Must be 2nd byte of a 3-byte sequence
+ // check for non-shortest form of 3 byte seq
+ if ((ch & (0x1F << 5)) == 0 || // non-shortest form
+ (ch & (0xF800 >> 6) ) == (0xD800 >> 6)) // illegal individually encoded surrogate
+ {
+ goto InvalidByteSequence;
+ }
+ }
+ continue;
+ }
+
+ // ready to punch
+
+ // adjust for surrogates in non-shortest form
+ if ((ch & (SupplimentarySeq | 0x1F0000)) == SupplimentarySeq) {
+ charCount--;
+ }
+ goto EncodeChar;
+
+ InvalidByteSequence:
+ // this code fragment should be close to the gotos referencing it
+ // Have to do fallback for invalid bytes
+ if (fallback == null)
+ {
+ if (baseDecoder == null)
+ fallback = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallback = baseDecoder.FallbackBuffer;
+ fallback.InternalInitialize(bytes, null);
+ }
+ charCount += FallbackInvalidByteSequence(pSrc, ch, fallback);
+
+ ch = 0;
+ continue;
+
+ ReadChar:
+ ch = *pSrc;
+ pSrc++;
+
+ ProcessChar:
+ if (ch > 0x7F) {
+ // If its > 0x7F, its start of a new multi-byte sequence
+
+ // Long sequence, so unreserve our char.
+ charCount--;
+
+ // bit 6 has to be non-zero for start of multibyte chars.
+ if ((ch & 0x40) == 0) {
+ // Unexpected trail byte
+ goto InvalidByteSequence;
+ }
+
+ // start a new long code
+ if ((ch & 0x20) != 0) {
+ if ((ch & 0x10) != 0) {
+ // 4 byte encoding - supplimentary character (2 surrogates)
+
+ ch &= 0x0F;
+
+ // check that bit 4 is zero and the valid supplimentary character
+ // range 0x000000 - 0x10FFFF at the same time
+ if (ch > 0x04) {
+ ch |= 0xf0;
+ goto InvalidByteSequence;
+ }
+
+ // Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
+ // Final byte flag, count fix if we don't make final byte & supplimentary sequence flag.
+ ch |= (FinalByte >> 3*6) | // Final byte is 3 more bytes from now
+ (1 << 30) | // If it dies on next byte we'll need an extra char
+ (3 << (30-2*6)) | // If it dies on last byte we'll need to subtract a char
+ (SupplimentarySeq) | (SupplimentarySeq >> 6) |
+ (SupplimentarySeq >> 2*6) | (SupplimentarySeq >> 3*6);
+
+ // Our character count will be 2 characters for these 4 bytes, so subtract another char
+ charCount--;
+ }
+ else {
+ // 3 byte encoding
+ // Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
+ ch = (ch & 0x0F) | ( (FinalByte >> 2*6) | (1 << 30) |
+ (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2*6) );
+
+ // We'll expect 1 character for these 3 bytes, so subtract another char.
+ charCount--;
+ }
+ }
+ else {
+ // 2 byte encoding
+
+ ch &= 0x1F;
+
+ // check for non-shortest form
+ if (ch <= 1) {
+ ch |= 0xc0;
+ goto InvalidByteSequence;
+ }
+
+ // Add bit flags so we'll be flagged correctly
+ ch |= (FinalByte >> 6);
+ }
+ continue;
+ }
+
+ EncodeChar:
+
+#if FASTLOOP
+ int availableBytes = PtrDiff(pEnd, pSrc);
+
+ // don't fall into the fast decoding loop if we don't have enough bytes
+ if (availableBytes <= 13) {
+ // try to get over the remainder of the ascii characters fast though
+ byte* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
+ while (pSrc < pLocalEnd) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F)
+ goto ProcessChar;
+ }
+ // we are done
+ ch = 0;
+ break;
+ }
+
+ // To compute the upper bound, assume that all characters are ASCII characters at this point,
+ // the boundary will be decreased for every non-ASCII character we encounter
+ // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
+ byte *pStop = pSrc + availableBytes - 7;
+
+ while (pSrc < pStop) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+
+ // get pSrc 2-byte aligned
+ if ((unchecked((int)pSrc) & 0x1) != 0) {
+ ch = *pSrc;
+ pSrc++;
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ }
+
+ // get pSrc 4-byte aligned
+ if ((unchecked((int)pSrc) & 0x2) != 0) {
+ ch = *(ushort*)pSrc;
+ if ((ch & 0x8080) != 0) {
+ goto LongCodeWithMask16;
+ }
+ pSrc += 2;
+ }
+
+ // Run 8 + 8 characters at a time!
+ while (pSrc < pStop) {
+ ch = *(int*)pSrc;
+ int chb = *(int*)(pSrc+4);
+ if (((ch | chb) & unchecked((int)0x80808080)) != 0) {
+ goto LongCodeWithMask32;
+ }
+ pSrc += 8;
+
+ // This is a really small loop - unroll it
+ if (pSrc >= pStop)
+ break;
+
+ ch = *(int*)pSrc;
+ chb = *(int*)(pSrc+4);
+ if (((ch | chb) & unchecked((int)0x80808080)) != 0) {
+ goto LongCodeWithMask32;
+ }
+ pSrc += 8;
+ }
+ break;
+
+#if BIGENDIAN
+ LongCodeWithMask32:
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ LongCodeWithMask16:
+ ch = (int)(((uint)ch) >> 8);
+#else // BIGENDIAN
+ LongCodeWithMask32:
+ LongCodeWithMask16:
+ ch &= 0xFF;
+#endif // BIGENDIAN
+ pSrc++;
+ if (ch <= 0x7F) {
+ continue;
+ }
+
+ LongCode:
+ int chc = *pSrc;
+ pSrc++;
+
+ if (
+ // bit 6 has to be zero
+ (ch & 0x40) == 0 ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (chc & unchecked((sbyte)0xC0)) != 0x80)
+ {
+ goto BadLongCode;
+ }
+
+ chc &= 0x3F;
+
+ // start a new long code
+ if ((ch & 0x20) != 0) {
+
+ // fold the first two bytes together
+ chc |= (ch & 0x0F) << 6;
+
+ if ((ch & 0x10) != 0) {
+ // 4 byte encoding - surrogate
+ ch = *pSrc;
+ if (
+ // check that bit 4 is zero, the non-shortest form of surrogate
+ // and the valid surrogate range 0x000000 - 0x10FFFF at the same time
+ !InRange(chc >> 4, 0x01, 0x10) ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (ch & unchecked((sbyte)0xC0)) != 0x80 )
+ {
+ goto BadLongCode;
+ }
+
+ chc = (chc << 6) | (ch & 0x3F);
+
+ ch = *(pSrc+1);
+ // we are expecting to see trailing bytes like 10vvvvvv
+ if ((ch & unchecked((sbyte)0xC0)) != 0x80) {
+ goto BadLongCode;
+ }
+ pSrc += 2;
+
+ // extra byte
+ charCount--;
+ }
+ else {
+ // 3 byte encoding
+ ch = *pSrc;
+ if (
+ // check for non-shortest form of 3 byte seq
+ (chc & (0x1F << 5)) == 0 ||
+ // Can't have surrogates here.
+ (chc & (0xF800 >> 6) ) == (0xD800 >> 6) ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (ch & unchecked((sbyte)0xC0)) != 0x80 )
+ {
+ goto BadLongCode;
+ }
+ pSrc++;
+
+ // extra byte
+ charCount--;
+ }
+ }
+ else {
+ // 2 byte encoding
+
+ // check for non-shortest form
+ if ((ch & 0x1E) == 0) {
+ goto BadLongCode;
+ }
+ }
+
+ // extra byte
+ charCount--;
+ }
+#endif // FASTLOOP
+
+ // no pending bits at this point
+ ch = 0;
+ continue;
+
+ BadLongCode:
+ pSrc -= 2;
+ ch = 0;
+ continue;
+ }
+
+ // May have a problem if we have to flush
+ if (ch != 0)
+ {
+ // We were already adjusting for these, so need to unadjust
+ charCount += (ch >> 30);
+ if (baseDecoder == null || baseDecoder.MustFlush)
+ {
+ // Have to do fallback for invalid bytes
+ if (fallback == null)
+ {
+ if (baseDecoder == null)
+ fallback = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallback = baseDecoder.FallbackBuffer;
+ fallback.InternalInitialize(bytes, null);
+ }
+ charCount += FallbackInvalidByteSequence(pSrc, ch, fallback);
+ }
+ }
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(fallback == null || fallback.Remaining == 0,
+ "[UTF8Encoding.GetCharCount]Expected empty fallback buffer at end");
+
+ return charCount;
+ }
+
+ // WARNING: If we throw an error, then System.Resources.ResourceReader calls this method.
+ // So if we're really broken, then that could also throw an error... recursively.
+ // So try to make sure GetChars can at least process all uses by
+ // System.Resources.ResourceReader!
+ //
+ // Note: We throw exceptions on individually encoded surrogates and other non-shortest forms.
+ // If exceptions aren't turned on, then we drop all non-shortest &individual surrogates.
+ //
+ // To simplify maintenance, the structure of GetCharCount and GetChars should be
+ // kept the same as much as possible
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(chars!=null, "[UTF8Encoding.GetChars]chars!=null");
+ Contract.Assert(byteCount >=0, "[UTF8Encoding.GetChars]count >=0");
+ Contract.Assert(charCount >=0, "[UTF8Encoding.GetChars]charCount >=0");
+ Contract.Assert(bytes!=null, "[UTF8Encoding.GetChars]bytes!=null");
+
+ byte *pSrc = bytes;
+ char *pTarget = chars;
+
+ byte *pEnd = pSrc+byteCount;
+ char *pAllocatedBufferEnd = pTarget+charCount;
+
+ int ch = 0;
+
+ DecoderFallbackBuffer fallback = null;
+ if (baseDecoder != null) {
+ UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
+ ch = decoder.bits;
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for chars, we always use all or none so always should be empty)
+ Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[UTF8Encoding.GetChars]Expected empty fallback buffer at start");
+ }
+
+ for (;;)
+ {
+ // SLOWLOOP: does all range checks, handles all special cases, but it is slow
+
+ if (pSrc >= pEnd) {
+ break;
+ }
+
+ if (ch == 0) {
+ // no pending bits
+ goto ReadChar;
+ }
+
+ // read next byte. The JIT optimization seems to be getting confused when
+ // compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
+ int cha = *pSrc;
+ pSrc++;
+
+ // we are expecting to see trailing bytes like 10vvvvvv
+ if ((cha & unchecked((sbyte)0xC0)) != 0x80) {
+ // This can be a valid starting byte for another UTF8 byte sequence, so let's put
+ // the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
+ pSrc--;
+ goto InvalidByteSequence;
+ }
+
+ // fold in the new byte
+ ch = (ch << 6) | (cha & 0x3F);
+
+ if ((ch & FinalByte) == 0) {
+ // Not at last byte yet
+ Contract.Assert( (ch & (SupplimentarySeq | ThreeByteSeq)) != 0,
+ "[UTF8Encoding.GetChars]Invariant volation");
+
+ if ((ch & SupplimentarySeq) != 0) {
+ // Its a 4-byte supplimentary sequence
+ if ((ch & (FinalByte >> 6)) != 0) {
+ // this is 3rd byte of 4 byte sequence - nothing to do
+ continue;
+ }
+
+ // 2nd byte of 4 bytes
+ // check for non-shortest form of surrogate and the valid surrogate
+ // range 0x000000 - 0x10FFFF at the same time
+ if (!InRange(ch & 0x1F0, 0x10, 0x100)) {
+ goto InvalidByteSequence;
+ }
+ }
+ else {
+ // Must be 2nd byte of a 3-byte sequence
+ // check for non-shortest form of 3 byte seq
+ if ((ch & (0x1F << 5)) == 0 || // non-shortest form
+ (ch & (0xF800 >> 6) ) == (0xD800 >> 6)) // illegal individually encoded surrogate
+ {
+ goto InvalidByteSequence;
+ }
+ }
+ continue;
+ }
+
+ // ready to punch
+
+ // surrogate in shortest form?
+ // Might be possible to get rid of this? Already did non-shortest check for 4-byte sequence when reading 2nd byte?
+ if ((ch & (SupplimentarySeq | 0x1F0000)) > SupplimentarySeq) {
+ // let the range check for the second char throw the exception
+ if (pTarget < pAllocatedBufferEnd) {
+ *pTarget = (char)( ((ch >> 10) & 0x7FF) +
+ unchecked((short)((CharUnicodeInfo.HIGH_SURROGATE_START - (0x10000 >> 10)))) );
+ pTarget++;
+
+ ch = (ch & 0x3FF) +
+ unchecked((int)(CharUnicodeInfo.LOW_SURROGATE_START));
+ }
+ }
+
+ goto EncodeChar;
+
+ InvalidByteSequence:
+ // this code fragment should be close to the gotos referencing it
+ // Have to do fallback for invalid bytes
+ if (fallback == null)
+ {
+ if (baseDecoder == null)
+ fallback = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallback = baseDecoder.FallbackBuffer;
+ fallback.InternalInitialize(bytes, pAllocatedBufferEnd);
+ }
+ // This'll back us up the appropriate # of bytes if we didn't get anywhere
+ if (!FallbackInvalidByteSequence(ref pSrc, ch, fallback, ref pTarget))
+ {
+ // Ran out of buffer space
+ // Need to throw an exception?
+ Contract.Assert(pSrc >= bytes || pTarget == chars,
+ "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer after fallback");
+ fallback.InternalReset();
+ ThrowCharsOverflow(baseDecoder, pTarget == chars);
+ ch = 0;
+ break;
+ }
+ Contract.Assert(pSrc >= bytes,
+ "[UTF8Encoding.GetChars]Expected invalid byte sequence to have remained within the byte array");
+ ch = 0;
+ continue;
+
+ ReadChar:
+ ch = *pSrc;
+ pSrc++;
+
+ ProcessChar:
+ if (ch > 0x7F) {
+ // If its > 0x7F, its start of a new multi-byte sequence
+
+ // bit 6 has to be non-zero
+ if ((ch & 0x40) == 0) {
+ goto InvalidByteSequence;
+ }
+
+ // start a new long code
+ if ((ch & 0x20) != 0) {
+ if ((ch & 0x10) != 0) {
+ // 4 byte encoding - supplimentary character (2 surrogates)
+
+ ch &= 0x0F;
+
+ // check that bit 4 is zero and the valid supplimentary character
+ // range 0x000000 - 0x10FFFF at the same time
+ if (ch > 0x04) {
+ ch |= 0xf0;
+ goto InvalidByteSequence;
+ }
+
+ ch |= (FinalByte >> 3*6) | (1 << 30) | (3 << (30-2*6)) |
+ (SupplimentarySeq) | (SupplimentarySeq >> 6) |
+ (SupplimentarySeq >> 2*6) | (SupplimentarySeq >> 3*6);
+ }
+ else {
+ // 3 byte encoding
+ ch = (ch & 0x0F) | ( (FinalByte >> 2*6) | (1 << 30) |
+ (ThreeByteSeq) | (ThreeByteSeq >> 6) | (ThreeByteSeq >> 2*6) );
+ }
+ }
+ else {
+ // 2 byte encoding
+
+ ch &= 0x1F;
+
+ // check for non-shortest form
+ if (ch <= 1) {
+ ch |= 0xc0;
+ goto InvalidByteSequence;
+ }
+
+ ch |= (FinalByte >> 6);
+ }
+ continue;
+ }
+
+ EncodeChar:
+ // write the pending character
+ if (pTarget >= pAllocatedBufferEnd)
+ {
+ // Fix chars so we make sure to throw if we didn't output anything
+ ch &= 0x1fffff;
+ if (ch > 0x7f)
+ {
+ if (ch > 0x7ff)
+ {
+ if (ch >= CharUnicodeInfo.LOW_SURROGATE_START &&
+ ch <= CharUnicodeInfo.LOW_SURROGATE_END)
+ {
+ pSrc--; // It was 4 bytes
+ pTarget--; // 1 was stored already, but we can't remember 1/2, so back up
+ }
+ else if (ch > 0xffff)
+ {
+ pSrc--; // It was 4 bytes, nothing was stored
+ }
+ pSrc--; // It was at least 3 bytes
+ }
+ pSrc--; // It was at least 2 bytes
+ }
+ pSrc--;
+
+ // Throw that we don't have enough room (pSrc could be < chars if we had started to process
+ // a 4 byte sequence alredy)
+ Contract.Assert(pSrc >= bytes || pTarget == chars,
+ "[UTF8Encoding.GetChars]Expected pSrc to be within input buffer or throw due to no output]");
+ ThrowCharsOverflow(baseDecoder, pTarget == chars);
+
+ // Don't store ch in decoder, we already backed up to its start
+ ch = 0;
+
+ // Didn't throw, just use this buffer size.
+ break;
+ }
+ *pTarget = (char)ch;
+ pTarget++;
+
+#if FASTLOOP
+ int availableChars = PtrDiff(pAllocatedBufferEnd, pTarget);
+ int availableBytes = PtrDiff(pEnd, pSrc);
+
+ // don't fall into the fast decoding loop if we don't have enough bytes
+ // Test for availableChars is done because pStop would be <= pTarget.
+ if (availableBytes <= 13) {
+ // we may need as many as 1 character per byte
+ if (availableChars < availableBytes) {
+ // not enough output room. no pending bits at this point
+ ch = 0;
+ continue;
+ }
+
+ // try to get over the remainder of the ascii characters fast though
+ byte* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
+ while (pSrc < pLocalEnd) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F)
+ goto ProcessChar;
+
+ *pTarget = (char)ch;
+ pTarget++;
+ }
+ // we are done
+ ch = 0;
+ break;
+ }
+
+ // we may need as many as 1 character per byte, so reduce the byte count if necessary.
+ // If availableChars is too small, pStop will be before pTarget and we won't do fast loop.
+ if (availableChars < availableBytes) {
+ availableBytes = availableChars;
+ }
+
+ // To compute the upper bound, assume that all characters are ASCII characters at this point,
+ // the boundary will be decreased for every non-ASCII character we encounter
+ // Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
+ char *pStop = pTarget + availableBytes - 7;
+
+ while (pTarget < pStop) {
+ ch = *pSrc;
+ pSrc++;
+
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ *pTarget = (char)ch;
+ pTarget++;
+
+ // get pSrc to be 2-byte aligned
+ if ((unchecked((int)pSrc) & 0x1) != 0) {
+ ch = *pSrc;
+ pSrc++;
+ if (ch > 0x7F) {
+ goto LongCode;
+ }
+ *pTarget = (char)ch;
+ pTarget++;
+ }
+
+ // get pSrc to be 4-byte aligned
+ if ((unchecked((int)pSrc) & 0x2) != 0) {
+ ch = *(ushort*)pSrc;
+ if ((ch & 0x8080) != 0) {
+ goto LongCodeWithMask16;
+ }
+
+ // Unfortunately, this is endianess sensitive
+#if BIGENDIAN
+ *pTarget = (char)((ch >> 8) & 0x7F);
+ pSrc += 2;
+ *(pTarget+1) = (char)(ch & 0x7F);
+ pTarget += 2;
+#else // BIGENDIAN
+ *pTarget = (char)(ch & 0x7F);
+ pSrc += 2;
+ *(pTarget+1) = (char)((ch >> 8) & 0x7F);
+ pTarget += 2;
+#endif // BIGENDIAN
+ }
+
+ // Run 8 characters at a time!
+ while (pTarget < pStop) {
+ ch = *(int*)pSrc;
+ int chb = *(int*)(pSrc+4);
+ if (((ch | chb) & unchecked((int)0x80808080)) != 0) {
+ goto LongCodeWithMask32;
+ }
+
+ // Unfortunately, this is endianess sensitive
+#if BIGENDIAN
+ *pTarget = (char)((ch >> 24) & 0x7F);
+ *(pTarget+1) = (char)((ch >> 16) & 0x7F);
+ *(pTarget+2) = (char)((ch >> 8) & 0x7F);
+ *(pTarget+3) = (char)(ch & 0x7F);
+ pSrc += 8;
+ *(pTarget+4) = (char)((chb >> 24) & 0x7F);
+ *(pTarget+5) = (char)((chb >> 16) & 0x7F);
+ *(pTarget+6) = (char)((chb >> 8) & 0x7F);
+ *(pTarget+7) = (char)(chb & 0x7F);
+ pTarget += 8;
+#else // BIGENDIAN
+ *pTarget = (char)(ch & 0x7F);
+ *(pTarget+1) = (char)((ch >> 8) & 0x7F);
+ *(pTarget+2) = (char)((ch >> 16) & 0x7F);
+ *(pTarget+3) = (char)((ch >> 24) & 0x7F);
+ pSrc += 8;
+ *(pTarget+4) = (char)(chb & 0x7F);
+ *(pTarget+5) = (char)((chb >> 8) & 0x7F);
+ *(pTarget+6) = (char)((chb >> 16) & 0x7F);
+ *(pTarget+7) = (char)((chb >> 24) & 0x7F);
+ pTarget += 8;
+#endif // BIGENDIAN
+ }
+ break;
+
+#if BIGENDIAN
+ LongCodeWithMask32:
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ LongCodeWithMask16:
+ ch = (int)(((uint)ch) >> 8);
+#else // BIGENDIAN
+ LongCodeWithMask32:
+ LongCodeWithMask16:
+ ch &= 0xFF;
+#endif // BIGENDIAN
+ pSrc++;
+ if (ch <= 0x7F) {
+ *pTarget = (char)ch;
+ pTarget++;
+ continue;
+ }
+
+ LongCode:
+ int chc = *pSrc;
+ pSrc++;
+
+ if (
+ // bit 6 has to be zero
+ (ch & 0x40) == 0 ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (chc & unchecked((sbyte)0xC0)) != 0x80)
+ {
+ goto BadLongCode;
+ }
+
+ chc &= 0x3F;
+
+ // start a new long code
+ if ((ch & 0x20) != 0) {
+
+ // fold the first two bytes together
+ chc |= (ch & 0x0F) << 6;
+
+ if ((ch & 0x10) != 0) {
+ // 4 byte encoding - surrogate
+ ch = *pSrc;
+ if (
+ // check that bit 4 is zero, the non-shortest form of surrogate
+ // and the valid surrogate range 0x000000 - 0x10FFFF at the same time
+ !InRange(chc >> 4, 0x01, 0x10) ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (ch & unchecked((sbyte)0xC0)) != 0x80 )
+ {
+ goto BadLongCode;
+ }
+
+ chc = (chc << 6) | (ch & 0x3F);
+
+ ch = *(pSrc+1);
+ // we are expecting to see trailing bytes like 10vvvvvv
+ if ((ch & unchecked((sbyte)0xC0)) != 0x80) {
+ goto BadLongCode;
+ }
+ pSrc += 2;
+
+ ch = (chc << 6) | (ch & 0x3F);
+
+ *pTarget = (char)( ((ch >> 10) & 0x7FF) +
+ unchecked((short)(CharUnicodeInfo.HIGH_SURROGATE_START - (0x10000 >> 10))) );
+ pTarget++;
+
+ ch = (ch & 0x3FF) +
+ unchecked((short)(CharUnicodeInfo.LOW_SURROGATE_START));
+
+ // extra byte, we're already planning 2 chars for 2 of these bytes,
+ // but the big loop is testing the target against pStop, so we need
+ // to subtract 2 more or we risk overrunning the input. Subtract
+ // one here and one below.
+ pStop--;
+ }
+ else {
+ // 3 byte encoding
+ ch = *pSrc;
+ if (
+ // check for non-shortest form of 3 byte seq
+ (chc & (0x1F << 5)) == 0 ||
+ // Can't have surrogates here.
+ (chc & (0xF800 >> 6) ) == (0xD800 >> 6) ||
+ // we are expecting to see trailing bytes like 10vvvvvv
+ (ch & unchecked((sbyte)0xC0)) != 0x80 )
+ {
+ goto BadLongCode;
+ }
+ pSrc++;
+
+ ch = (chc << 6) | (ch & 0x3F);
+
+ // extra byte, we're only expecting 1 char for each of these 3 bytes,
+ // but the loop is testing the target (not source) against pStop, so
+ // we need to subtract 2 more or we risk overrunning the input.
+ // Subtract 1 here and one more below
+ pStop--;
+ }
+ }
+ else {
+ // 2 byte encoding
+
+ ch &= 0x1F;
+
+ // check for non-shortest form
+ if (ch <= 1) {
+ goto BadLongCode;
+ }
+ ch = (ch << 6) | chc;
+ }
+
+ *pTarget = (char)ch;
+ pTarget++;
+
+ // extra byte, we're only expecting 1 char for each of these 2 bytes,
+ // but the loop is testing the target (not source) against pStop.
+ // subtract an extra count from pStop so that we don't overrun the input.
+ pStop--;
+ }
+#endif // FASTLOOP
+
+ Contract.Assert(pTarget <= pAllocatedBufferEnd, "[UTF8Encoding.GetChars]pTarget <= pAllocatedBufferEnd");
+
+ // no pending bits at this point
+ ch = 0;
+ continue;
+
+ BadLongCode:
+ pSrc -= 2;
+ ch = 0;
+ continue;
+ }
+
+ if (ch != 0 && (baseDecoder == null || baseDecoder.MustFlush))
+ {
+ // Have to do fallback for invalid bytes
+ if (fallback == null)
+ {
+ if (baseDecoder == null)
+ fallback = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallback = baseDecoder.FallbackBuffer;
+ fallback.InternalInitialize(bytes, pAllocatedBufferEnd);
+ }
+
+ // This'll back us up the appropriate # of bytes if we didn't get anywhere
+ if (!FallbackInvalidByteSequence(ref pSrc, ch, fallback, ref pTarget))
+ {
+ Contract.Assert(pSrc >= bytes || pTarget == chars,
+ "[UTF8Encoding.GetChars]Expected to throw or remain in byte buffer while flushing");
+
+ // Ran out of buffer space
+ // Need to throw an exception?
+ fallback.InternalReset();
+ ThrowCharsOverflow(baseDecoder, pTarget == chars);
+ }
+ Contract.Assert(pSrc >= bytes,
+ "[UTF8Encoding.GetChars]Expected flushing invalid byte sequence to have remained within the byte array");
+ ch = 0;
+ }
+
+ if (baseDecoder != null)
+ {
+ UTF8Decoder decoder = (UTF8Decoder)baseDecoder;
+
+ // If we're storing flush data we expect all bits to be used or else
+ // we're stuck in the middle of a conversion
+ Contract.Assert(!baseDecoder.MustFlush || ch == 0 || !baseDecoder.m_throwOnOverflow,
+ "[UTF8Encoding.GetChars]Expected no must flush or no left over bits or no throw on overflow.");
+
+ // Remember our leftover bits.
+ decoder.bits = ch;
+
+ baseDecoder.m_bytesUsed = (int)(pSrc - bytes);
+ }
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for chars)
+ Contract.Assert(fallback == null || fallback.Remaining == 0,
+ "[UTF8Encoding.GetChars]Expected empty fallback buffer at end");
+
+ return PtrDiff(pTarget, chars);
+ }
+
+ // During GetChars we had an invalid byte sequence
+ // pSrc is backed up to the start of the bad sequence if we didn't have room to
+ // fall it back. Otherwise pSrc remains wher it is.
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe bool FallbackInvalidByteSequence(
+ ref byte* pSrc, int ch, DecoderFallbackBuffer fallback, ref char* pTarget)
+ {
+ // Get our byte[]
+ byte *pStart = pSrc;
+ byte[] bytesUnknown = GetBytesUnknown(ref pStart, ch);
+
+ // Do the actual fallback
+ if (!fallback.InternalFallback(bytesUnknown, pSrc, ref pTarget))
+ {
+ // Oops, it failed, back up to pStart
+ pSrc = pStart;
+ return false;
+ }
+
+ // It worked
+ return true;
+ }
+
+ // During GetCharCount we had an invalid byte sequence
+ // pSrc is used to find the index that points to the invalid bytes,
+ // however the byte[] contains the fallback bytes (in case the index is -1)
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe int FallbackInvalidByteSequence(
+ byte* pSrc, int ch, DecoderFallbackBuffer fallback)
+ {
+ // Get our byte[]
+ byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch);
+
+ // Do the actual fallback
+ int count = fallback.InternalFallback(bytesUnknown, pSrc);
+
+ // # of fallback chars expected.
+ // Note that we only get here for "long" sequences, and have already unreserved
+ // the count that we prereserved for the input bytes
+ return count;
+ }
+
+ // Note that some of these bytes may have come from a previous fallback, so we cannot
+ // just decrement the pointer and use the values we read. In those cases we have
+ // to regenerate the original values.
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch)
+ {
+ // Get our byte[]
+ byte[] bytesUnknown = null;
+
+ // See if it was a plain char
+ // (have to check >= 0 because we have all sorts of wierd bit flags)
+ if (ch < 0x100 && ch >= 0)
+ {
+ pSrc--;
+ bytesUnknown = new byte[] { unchecked((byte)ch) };
+ }
+ // See if its an unfinished 2 byte sequence
+ else if ((ch & (SupplimentarySeq | ThreeByteSeq)) == 0)
+ {
+ pSrc--;
+ bytesUnknown = new byte[] { unchecked((byte)((ch & 0x1F )| 0xc0)) };
+ }
+ // So now we're either 2nd byte of 3 or 4 byte sequence or
+ // we hit a non-trail byte or we ran out of space for 3rd byte of 4 byte sequence
+ // 1st check if its a 4 byte sequence
+ else if ((ch & SupplimentarySeq) != 0)
+ {
+ // 3rd byte of 4 byte sequence?
+ if ((ch & (FinalByte >> 6)) != 0)
+ {
+ // 3rd byte of 4 byte sequence
+ pSrc-=3;
+ bytesUnknown = new byte[] {
+ unchecked((byte)(((ch >> 12) & 0x07) | 0xF0)),
+ unchecked((byte)(((ch >> 6) & 0x3F) | 0x80)),
+ unchecked((byte)(((ch) & 0x3F) | 0x80)) };
+ }
+ else if ((ch & (FinalByte >> 12)) != 0)
+ {
+ // 2nd byte of a 4 byte sequence
+ pSrc-=2;
+ bytesUnknown = new byte[] {
+ unchecked((byte)(((ch >> 6) & 0x07) | 0xF0)),
+ unchecked((byte)(((ch) & 0x3F) | 0x80)) };
+ }
+ else
+ {
+ // 4th byte of a 4 byte sequence
+ pSrc--;
+ bytesUnknown = new byte[] { unchecked((byte)(((ch) & 0x07) | 0xF0))};
+ }
+ }
+ else
+ {
+ // 2nd byte of 3 byte sequence?
+ if ((ch & (FinalByte >> 6)) != 0)
+ {
+ // So its 2nd byte of a 3 byte sequence
+ pSrc-=2;
+ bytesUnknown = new byte[] {
+ unchecked((byte)(((ch >> 6) & 0x0F) | 0xE0)), unchecked ((byte)(((ch) & 0x3F) | 0x80)) };
+ }
+ else
+ {
+ // 1st byte of a 3 byte sequence
+ pSrc--;
+ bytesUnknown = new byte[] { unchecked((byte)(((ch) & 0x0F) | 0xE0))};
+ }
+ }
+
+ return bytesUnknown;
+ }
+
+
+ public override Decoder GetDecoder() {
+ return new UTF8Decoder(this);
+ }
+
+
+ public override Encoder GetEncoder() {
+ return new UTF8Encoder(this);
+ }
+
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // Max 3 bytes per char. (4 bytes per 2 chars for surrogates)
+ byteCount *= 3;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Figure out our length, 1 char per input byte + 1 char if 1st byte is last byte of 4 byte surrogate pair
+ long charCount = ((long)byteCount + 1);
+
+ // Non-shortest form would fall back, so get max count from fallback.
+ // So would 11... followed by 11..., so you could fall back every byte
+ if (DecoderFallback.MaxCharCount > 1)
+ {
+ charCount *= DecoderFallback.MaxCharCount;
+ }
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+
+ public override byte[] GetPreamble()
+ {
+ if (emitUTF8Identifier) {
+ // Allocate new array to prevent users from modifying it.
+ return new byte[3] { 0xEF, 0xBB, 0xBF };
+ }
+ else
+ return EmptyArray<Byte>.Value;
+ }
+
+
+ public override bool Equals(Object value) {
+ UTF8Encoding that = value as UTF8Encoding;
+ if (that != null) {
+ return (emitUTF8Identifier == that.emitUTF8Identifier) &&
+// (isThrowException == that.isThrowException) && // Same as encoder/decoderfallbacks being exception
+ (EncoderFallback.Equals(that.EncoderFallback)) &&
+ (DecoderFallback.Equals(that.DecoderFallback));
+ }
+ return (false);
+ }
+
+
+ public override int GetHashCode() {
+ //Not great distribution, but this is relatively unlikely to be used as the key in a hashtable.
+ return this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() +
+ UTF8_CODEPAGE + (emitUTF8Identifier?1:0);
+ }
+
+ [Serializable]
+ internal class UTF8Encoder : EncoderNLS, ISerializable
+ {
+ // We must save a high surrogate value until the next call, looking
+ // for a low surrogate value.
+ internal int surrogateChar;
+
+ public UTF8Encoder(UTF8Encoding encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal UTF8Encoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Get common info
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+
+ // SurrogateChar happens to mean the same thing
+ this.surrogateChar = (int)info.GetValue("surrogateChar", typeof(int));
+
+ try
+ {
+ this.m_fallback = (EncoderFallback) info.GetValue("m_fallback", typeof(EncoderFallback));
+ }
+ catch (SerializationException)
+ {
+ this.m_fallback = null;
+ }
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save Whidbey data
+ // Just need Everett maxCharSize (BaseCodePageEncoding) or m_maxByteSize (MLangBaseCodePageEncoding)
+ info.AddValue("encoding", this.m_encoding);
+ info.AddValue("surrogateChar", this.surrogateChar);
+
+ info.AddValue("m_fallback", this.m_fallback);
+
+ // Extra stuff for Everett that Whidbey doesn't use
+ info.AddValue("storedSurrogate", this.surrogateChar > 0 ? true : false);
+ info.AddValue("mustFlush", false); // Everett doesn't actually use this either, but it accidently serialized it!
+ }
+
+ public override void Reset()
+
+ {
+ this.surrogateChar = 0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our encoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.surrogateChar != 0);
+ }
+ }
+ }
+
+ [Serializable]
+ internal class UTF8Decoder : DecoderNLS, ISerializable
+ {
+ // We'll need to remember the previous information. See the comments around definition
+ // of FinalByte for details.
+ internal int bits;
+
+ public UTF8Decoder(UTF8Encoding encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal UTF8Decoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Get common info
+ this.m_encoding = (Encoding)info.GetValue("encoding", typeof(Encoding));
+
+ try
+ {
+ // Get whidbey version of bits
+ this.bits = (int)info.GetValue("wbits", typeof(int));
+ this.m_fallback = (DecoderFallback) info.GetValue("m_fallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ // Everett calls bits bits instead of wbits, so this is Everett
+ this.bits = 0;
+ this.m_fallback = null;
+ }
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save new Whidbey data
+ info.AddValue("encoding", this.m_encoding);
+ info.AddValue("wbits", this.bits); // Special whidbey bits name
+ info.AddValue("m_fallback", this.m_fallback);
+
+ // Everett has extra stuff, we set it all to 0 in case this deserializes in Everett
+ info.AddValue("bits", (int)0);
+ info.AddValue("trailCount", (int)0);
+ info.AddValue("isSurrogate", false);
+ info.AddValue("byteSequence", (int)0);
+ }
+
+ public override void Reset()
+ {
+ this.bits = 0;
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.bits != 0);
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Text/UnicodeEncoding.cs b/src/mscorlib/src/System/Text/UnicodeEncoding.cs
new file mode 100644
index 0000000000..41d4f3b5ea
--- /dev/null
+++ b/src/mscorlib/src/System/Text/UnicodeEncoding.cs
@@ -0,0 +1,1842 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
+//
+
+namespace System.Text
+{
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class UnicodeEncoding : Encoding
+ {
+ // Used by Encoding.BigEndianUnicode/Unicode for lazy initialization
+ // The initialization code will not be run until a static member of the class is referenced
+ internal static readonly UnicodeEncoding s_bigEndianDefault = new UnicodeEncoding(bigEndian: true, byteOrderMark: true);
+ internal static readonly UnicodeEncoding s_littleEndianDefault = new UnicodeEncoding(bigEndian: false, byteOrderMark: true);
+
+ [OptionalField(VersionAdded = 2)]
+ internal bool isThrowException = false;
+
+ internal bool bigEndian = false;
+ internal bool byteOrderMark = true;
+
+ // Unicode version 2.0 character size in bytes
+ public const int CharSize = 2;
+
+
+ public UnicodeEncoding()
+ : this(false, true)
+ {
+ }
+
+
+ public UnicodeEncoding(bool bigEndian, bool byteOrderMark)
+ : this(bigEndian, byteOrderMark, false)
+ {
+ }
+
+
+ public UnicodeEncoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidBytes)
+ : base(bigEndian ? 1201 : 1200) //Set the data item.
+ {
+ this.isThrowException = throwOnInvalidBytes;
+ this.bigEndian = bigEndian;
+ this.byteOrderMark = byteOrderMark;
+
+ // Encoding's constructor already did this, but it'll be wrong if we're throwing exceptions
+ if (this.isThrowException)
+ SetDefaultFallbacks();
+ }
+
+#region Serialization
+ [OnDeserializing]
+ private void OnDeserializing(StreamingContext ctx)
+ {
+ // In Everett it is false. Whidbey will overwrite this value.
+ isThrowException = false;
+ }
+#endregion Serialization
+
+ internal override void SetDefaultFallbacks()
+ {
+ // For UTF-X encodings, we use a replacement fallback with an empty string
+ if (this.isThrowException)
+ {
+ this.encoderFallback = EncoderFallback.ExceptionFallback;
+ this.decoderFallback = DecoderFallback.ExceptionFallback;
+ }
+ else
+ {
+ this.encoderFallback = new EncoderReplacementFallback("\xFFFD");
+ this.decoderFallback = new DecoderReplacementFallback("\xFFFD");
+ }
+ }
+
+ // NOTE: Many methods in this class forward to EncodingForwarder for
+ // validating arguments/wrapping the unsafe methods in this class
+ // which do the actual work. That class contains
+ // shared logic for doing this which is used by
+ // ASCIIEncoding, EncodingNLS, UnicodeEncoding, UTF32Encoding,
+ // UTF7Encoding, and UTF8Encoding.
+ // The reason the code is separated out into a static class, rather
+ // than a base class which overrides all of these methods for us
+ // (which is what EncodingNLS is for internal Encodings) is because
+ // that's really more of an implementation detail so it's internal.
+ // At the same time, C# doesn't allow a public class subclassing an
+ // internal/private one, so we end up having to re-override these
+ // methods in all of the public Encodings + EncodingNLS.
+
+ // Returns the number of bytes required to encode a range of characters in
+ // a character array.
+
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, index, count);
+ }
+
+ public override int GetByteCount(String s)
+ {
+ return EncodingForwarder.GetByteCount(this, s);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetByteCount(char* chars, int count)
+ {
+ return EncodingForwarder.GetByteCount(this, chars, count);
+ }
+
+ public override int GetBytes(String s, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, s, charIndex, charCount, bytes, byteIndex);
+ }
+
+ // Encodes a range of characters in a character array into a range of bytes
+ // in a byte array. An exception occurs if the byte array is not large
+ // enough to hold the complete encoding of the characters. The
+ // GetByteCount method can be used to determine the exact number of
+ // bytes that will be produced for a given range of characters.
+ // Alternatively, the GetMaxByteCount method can be used to
+ // determine the maximum number of bytes that will be produced for a given
+ // number of characters, regardless of the actual character values.
+
+ public override int GetBytes(char[] chars, int charIndex, int charCount,
+ byte[] bytes, int byteIndex)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charIndex, charCount, bytes, byteIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int byteCount)
+ {
+ return EncodingForwarder.GetBytes(this, chars, charCount, bytes, byteCount);
+ }
+
+ // Returns the number of characters produced by decoding a range of bytes
+ // in a byte array.
+
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, index, count);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override unsafe int GetCharCount(byte* bytes, int count)
+ {
+ return EncodingForwarder.GetCharCount(this, bytes, count);
+ }
+
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount,
+ char[] chars, int charIndex)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteIndex, byteCount, chars, charIndex);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public unsafe override int GetChars(byte* bytes, int byteCount, char* chars, int charCount)
+ {
+ return EncodingForwarder.GetChars(this, bytes, byteCount, chars, charCount);
+ }
+
+ // Returns a string containing the decoded representation of a range of
+ // bytes in a byte array.
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override String GetString(byte[] bytes, int index, int count)
+ {
+ return EncodingForwarder.GetString(this, bytes, index, count);
+ }
+
+ // End of overridden methods which use EncodingForwarder
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ {
+ Contract.Assert(chars!=null, "[UnicodeEncoding.GetByteCount]chars!=null");
+ Contract.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0");
+
+ // Start by assuming each char gets 2 bytes
+ int byteCount = count << 1;
+
+ // Check for overflow in byteCount
+ // (If they were all invalid chars, this would actually be wrong,
+ // but that's a ridiculously large # so we're not concerned about that case)
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ char* charStart = chars;
+ char* charEnd = chars + count;
+ char charLeftOver = (char)0;
+
+ bool wasHereBefore = false;
+
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(charEnd - 3);
+
+ // For fallback we may need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+
+ // Assume extra bytes to encode charLeftOver if it existed
+ if (charLeftOver > 0)
+ byteCount+=2;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+ }
+
+ char ch;
+ TryAgain:
+
+ while (((ch = (fallbackBuffer == null) ? (char)0 :fallbackBuffer.InternalGetNextChar()) != 0) || chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, maybe we can do it fast
+#if !NO_FAST_UNICODE_LOOP
+#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
+ if ( bigEndian &&
+#else
+ if ( !bigEndian &&
+#endif // BIGENDIAN
+
+#if BIT64 // 64 bit CPU needs to be long aligned for this to work.
+ charLeftOver == 0 && (unchecked((long)chars) & 7) == 0)
+#else
+ charLeftOver == 0 && (unchecked((int)chars) & 3) == 0)
+#endif
+ {
+ // Need new char* so we can check 4 at a time
+ ulong* longChars = (ulong*)chars;
+
+ while (longChars < longEnd)
+ {
+ // See if we potentially have surrogates (0x8000 bit set)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so this'll work)
+ if ((0x8000800080008000 & *longChars) != 0)
+ {
+ // See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
+ // 5 bits looks like 11011, then its a high or low surrogate.
+ // We do the & f800 to filter the 5 bits, then ^ d800 to ensure the 0 isn't set.
+ // Note that we expect BMP characters to be more common than surrogates
+ // & each char with 11111... then ^ with 11011. Zeroes then indicate surrogates
+ ulong uTemp = (0xf800f800f800f800 & *longChars) ^ 0xd800d800d800d800;
+
+ // Check each of the 4 chars. 0 for those 16 bits means it was a surrogate
+ // but no clue if they're high or low.
+ // If each of the 4 characters are non-zero, then none are surrogates.
+ if ((uTemp & 0xFFFF000000000000) == 0 ||
+ (uTemp & 0x0000FFFF00000000) == 0 ||
+ (uTemp & 0x00000000FFFF0000) == 0 ||
+ (uTemp & 0x000000000000FFFF) == 0)
+ {
+ // It has at least 1 surrogate, but we don't know if they're high or low surrogates,
+ // or if there's 1 or 4 surrogates
+
+ // If they happen to be high/low/high/low, we may as well continue. Check the next
+ // bit to see if its set (low) or not (high) in the right pattern
+#if BIGENDIAN
+ if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
+#else
+ if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
+#endif
+ {
+ // Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
+ // was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
+
+ // Drop out to the slow loop to resolve the surrogates
+ break;
+ }
+ // else they are all surrogates in High/Low/High/Low order, so we can use them.
+ }
+ // else none are surrogates, so we can use them.
+ }
+ // else all < 0x8000 so we can use them
+
+ // We already counted these four chars, go to next long.
+ longChars++;
+ }
+
+ chars = (char*)longChars;
+
+ if (chars >= charEnd)
+ break;
+ }
+#endif // !NO_FAST_UNICODE_LOOP
+
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+ else
+ {
+ // We weren't preallocating fallback space.
+ byteCount+=2;
+ }
+
+ // Check for high or low surrogates
+ if (ch >= 0xd800 && ch <= 0xdfff)
+ {
+ // Was it a high surrogate?
+ if (ch <= 0xdbff)
+ {
+ // Its a high surrogate, if we already had a high surrogate do its fallback
+ if (charLeftOver > 0)
+ {
+ // Unwind the current character, this should be safe because we
+ // don't have leftover data in the fallback, so chars must have
+ // advanced already.
+ Contract.Assert(chars > charStart,
+ "[UnicodeEncoding.GetByteCount]Expected chars to have advanced in unexpected high surrogate");
+ chars--;
+
+ // If previous high surrogate deallocate 2 bytes
+ byteCount -= 2;
+
+ // Fallback the previous surrogate
+ // Need to initialize fallback buffer?
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+
+ // Now no high surrogate left over
+ charLeftOver = (char)0;
+ continue;
+ }
+
+ // Remember this high surrogate
+ charLeftOver = ch;
+ continue;
+ }
+
+
+ // Its a low surrogate
+ if (charLeftOver == 0)
+ {
+ // Expected a previous high surrogate.
+ // Don't count this one (we'll count its fallback if necessary)
+ byteCount -= 2;
+
+ // fallback this one
+ // Need to initialize fallback buffer?
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // Valid surrogate pair, add our charLeftOver
+ charLeftOver = (char)0;
+ continue;
+ }
+ else if (charLeftOver > 0)
+ {
+ // Expected a low surrogate, but this char is normal
+
+ // Rewind the current character, fallback previous character.
+ // this should be safe because we don't have leftover data in the
+ // fallback, so chars must have advanced already.
+ Contract.Assert(chars > charStart,
+ "[UnicodeEncoding.GetByteCount]Expected chars to have advanced when expected low surrogate");
+ chars--;
+
+ // fallback previous chars
+ // Need to initialize fallback buffer?
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+
+ // Ignore charLeftOver or throw
+ byteCount-=2;
+ charLeftOver = (char)0;
+
+ continue;
+ }
+
+ // Ok we had something to add (already counted)
+ }
+
+ // Don't allocate space for left over char
+ if (charLeftOver > 0)
+ {
+ byteCount -= 2;
+
+ // If we have to flush, stick it in fallback and try again
+ if (encoder == null || encoder.MustFlush)
+ {
+ if (wasHereBefore)
+ {
+ // Throw it, using our complete character
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_RecursiveFallback",
+ charLeftOver), "chars");
+ }
+ else
+ {
+ // Need to initialize fallback buffer?
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+ charLeftOver = (char)0;
+ wasHereBefore = true;
+ goto TryAgain;
+ }
+ }
+ }
+
+ // Shouldn't have anything in fallback buffer for GetByteCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[UnicodeEncoding.GetByteCount]Expected empty fallback buffer at end");
+
+ // Don't remember fallbackBuffer.encoder for counting
+ return byteCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetBytes(char* chars, int charCount,
+ byte* bytes, int byteCount, EncoderNLS encoder)
+ {
+ Contract.Assert(chars!=null, "[UnicodeEncoding.GetBytes]chars!=null");
+ Contract.Assert(byteCount >=0, "[UnicodeEncoding.GetBytes]byteCount >=0");
+ Contract.Assert(charCount >=0, "[UnicodeEncoding.GetBytes]charCount >=0");
+ Contract.Assert(bytes!=null, "[UnicodeEncoding.GetBytes]bytes!=null");
+
+ char charLeftOver = (char)0;
+ char ch;
+ bool wasHereBefore = false;
+
+
+ byte* byteEnd = bytes + byteCount;
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ // For fallback we may need a fallback buffer
+ EncoderFallbackBuffer fallbackBuffer = null;
+
+ // Get our encoder, but don't clear it yet.
+ if (encoder != null)
+ {
+ charLeftOver = encoder.charLeftOver;
+
+ // We mustn't have left over fallback data when counting
+ if (encoder.InternalHasFallbackBuffer)
+ {
+ // We always need the fallback buffer in get bytes so we can flush any remaining ones if necessary
+ fallbackBuffer = encoder.FallbackBuffer;
+ if (fallbackBuffer.Remaining > 0 && encoder.m_throwOnOverflow)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EncoderFallbackNotEmpty",
+ this.EncodingName, encoder.Fallback.GetType()));
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, false);
+ }
+ }
+
+ TryAgain:
+ while (((ch = (fallbackBuffer == null) ?
+ (char)0 : fallbackBuffer.InternalGetNextChar()) != 0) ||
+ chars < charEnd)
+ {
+ // First unwind any fallback
+ if (ch == 0)
+ {
+ // No fallback, maybe we can do it fast
+#if !NO_FAST_UNICODE_LOOP
+#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
+ if ( bigEndian &&
+#else
+ if ( !bigEndian &&
+#endif // BIGENDIAN
+#if BIT64 // 64 bit CPU needs to be long aligned for this to work, 32 bit CPU needs to be 32 bit aligned
+ (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#else
+ (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
+#endif // BIT64
+ charLeftOver == 0)
+ {
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ // We can only go iCount units (limited by shorter of char or byte buffers.
+ ulong* longEnd = (ulong*)(chars - 3 +
+ (((byteEnd - bytes) >> 1 < charEnd - chars) ?
+ (byteEnd - bytes) >> 1 : charEnd - chars));
+
+ // Need new char* so we can check 4 at a time
+ ulong* longChars = (ulong*)chars;
+ ulong* longBytes = (ulong*)bytes;
+
+ while (longChars < longEnd)
+ {
+ // See if we potentially have surrogates (0x8000 bit set)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so this'll work)
+ if ((0x8000800080008000 & *longChars) != 0)
+ {
+ // See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
+ // 5 bits looks like 11011, then its a high or low surrogate.
+ // We do the & f800 to filter the 5 bits, then ^ d800 to ensure the 0 isn't set.
+ // Note that we expect BMP characters to be more common than surrogates
+ // & each char with 11111... then ^ with 11011. Zeroes then indicate surrogates
+ ulong uTemp = (0xf800f800f800f800 & *longChars) ^ 0xd800d800d800d800;
+
+ // Check each of the 4 chars. 0 for those 16 bits means it was a surrogate
+ // but no clue if they're high or low.
+ // If each of the 4 characters are non-zero, then none are surrogates.
+ if ((uTemp & 0xFFFF000000000000) == 0 ||
+ (uTemp & 0x0000FFFF00000000) == 0 ||
+ (uTemp & 0x00000000FFFF0000) == 0 ||
+ (uTemp & 0x000000000000FFFF) == 0)
+ {
+ // It has at least 1 surrogate, but we don't know if they're high or low surrogates,
+ // or if there's 1 or 4 surrogates
+
+ // If they happen to be high/low/high/low, we may as well continue. Check the next
+ // bit to see if its set (low) or not (high) in the right pattern
+#if BIGENDIAN
+ if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
+#else
+ if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
+#endif
+ {
+ // Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
+ // was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
+
+ // Drop out to the slow loop to resolve the surrogates
+ break;
+ }
+ // else they are all surrogates in High/Low/High/Low order, so we can use them.
+ }
+ // else none are surrogates, so we can use them.
+ }
+ // else all < 0x8000 so we can use them
+
+ // We can use these 4 chars.
+ *longBytes = *longChars;
+ longChars++;
+ longBytes++;
+ }
+
+ chars = (char*)longChars;
+ bytes = (byte*)longBytes;
+
+ if (chars >= charEnd)
+ break;
+ }
+ // Not aligned, but maybe we can still be somewhat faster
+ // Also somehow this optimizes the above loop? It seems to cause something above
+ // to get enregistered, but I haven't figured out how to make that happen without this loop.
+ else if ((charLeftOver == 0) &&
+#if BIGENDIAN
+ bigEndian &&
+#else
+ !bigEndian &&
+#endif // BIGENDIAN
+
+#if BIT64
+ (unchecked((long)chars) & 7) != (unchecked((long)bytes) & 7) && // Only do this if chars & bytes are out of line, otherwise faster loop'll be faster next time
+#else
+ (unchecked((int)chars) & 3) != (unchecked((int)bytes) & 3) && // Only do this if chars & bytes are out of line, otherwise faster loop'll be faster next time
+#endif // BIT64
+ (unchecked((int)(bytes)) & 1) == 0 )
+ {
+ // # to use
+ long iCount = ((byteEnd - bytes) >> 1 < charEnd - chars) ?
+ (byteEnd - bytes) >> 1 : charEnd - chars;
+
+ // Need new char*
+ char* charOut = ((char*)bytes); // a char* for our output
+ char* tempEnd = chars + iCount - 1; // Our end pointer
+
+ while (chars < tempEnd)
+ {
+ if (*chars >= (char)0xd800 && *chars <= (char)0xdfff)
+ {
+ // break for fallback for low surrogate
+ if (*chars >= 0xdc00)
+ break;
+
+ // break if next one's not a low surrogate (will do fallback)
+ if (*(chars+1) < 0xdc00 || *(chars+1) > 0xdfff)
+ break;
+
+ // They both exist, use them
+ }
+ // If 2nd char is surrogate & this one isn't then only add one
+ else if (*(chars+1) >= (char)0xd800 && *(chars+1) <= 0xdfff)
+ {
+ *charOut = *chars;
+ charOut++;
+ chars++;
+ continue;
+ }
+
+ *charOut = *chars;
+ *(charOut+1) = *(chars+1);
+ charOut+=2;
+ chars+=2;
+
+ }
+
+ bytes=(byte*)charOut;
+
+ if (chars >= charEnd)
+ break;
+ }
+#endif // !NO_FAST_UNICODE_LOOP
+
+ // No fallback, just get next char
+ ch = *chars;
+ chars++;
+ }
+
+ // Check for high or low surrogates
+ if (ch >= 0xd800 && ch <= 0xdfff)
+ {
+ // Was it a high surrogate?
+ if (ch <= 0xdbff)
+ {
+ // Its a high surrogate, see if we already had a high surrogate
+ if (charLeftOver > 0)
+ {
+ // Unwind the current character, this should be safe because we
+ // don't have leftover data in the fallback, so chars must have
+ // advanced already.
+ Contract.Assert(chars > charStart,
+ "[UnicodeEncoding.GetBytes]Expected chars to have advanced in unexpected high surrogate");
+ chars--;
+
+ // Fallback the previous surrogate
+ // Might need to create our fallback buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+ }
+
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+
+ charLeftOver = (char)0;
+ continue;
+ }
+
+ // Remember this high surrogate
+ charLeftOver = ch;
+ continue;
+ }
+
+ // Its a low surrogate
+ if (charLeftOver == 0)
+ {
+ // We'll fall back this one
+ // Might need to create our fallback buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+ }
+
+ fallbackBuffer.InternalFallback(ch, ref chars);
+ continue;
+ }
+
+ // Valid surrogate pair, add our charLeftOver
+ if (bytes + 3 >= byteEnd)
+ {
+ // Not enough room to add this surrogate pair
+ if (fallbackBuffer != null && fallbackBuffer.bFallingBack)
+ {
+ // These must have both been from the fallbacks.
+ // Both of these MUST have been from a fallback because if the 1st wasn't
+ // from a fallback, then a high surrogate followed by an illegal char
+ // would've caused the high surrogate to fall back. If a high surrogate
+ // fell back, then it was consumed and both chars came from the fallback.
+ fallbackBuffer.MovePrevious(); // Didn't use either fallback surrogate
+ fallbackBuffer.MovePrevious();
+ }
+ else
+ {
+ // If we don't have enough room, then either we should've advanced a while
+ // or we should have bytes==byteStart and throw below
+ Contract.Assert(chars > charStart + 1 || bytes == byteStart,
+ "[UnicodeEncoding.GetBytes]Expected chars to have when no room to add surrogate pair");
+ chars-=2; // Didn't use either surrogate
+ }
+ ThrowBytesOverflow(encoder, bytes == byteStart); // Throw maybe (if no bytes written)
+ charLeftOver = (char)0; // we'll retry it later
+ break; // Didn't throw, but stop 'til next time.
+ }
+
+ if (bigEndian)
+ {
+ *(bytes++) = (byte)(charLeftOver >> 8);
+ *(bytes++) = (byte)charLeftOver;
+ }
+ else
+ {
+ *(bytes++) = (byte)charLeftOver;
+ *(bytes++) = (byte)(charLeftOver >> 8);
+ }
+
+ charLeftOver = (char)0;
+ }
+ else if (charLeftOver > 0)
+ {
+ // Expected a low surrogate, but this char is normal
+
+ // Rewind the current character, fallback previous character.
+ // this should be safe because we don't have leftover data in the
+ // fallback, so chars must have advanced already.
+ Contract.Assert(chars > charStart,
+ "[UnicodeEncoding.GetBytes]Expected chars to have advanced after expecting low surrogate");
+ chars--;
+
+ // fallback previous chars
+ // Might need to create our fallback buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+ }
+
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+
+ // Ignore charLeftOver or throw
+ charLeftOver = (char)0;
+ continue;
+ }
+
+ // Ok, we have a char to add
+ if (bytes + 1 >= byteEnd)
+ {
+ // Couldn't add this char
+ if (fallbackBuffer != null && fallbackBuffer.bFallingBack)
+ fallbackBuffer.MovePrevious(); // Not using this fallback char
+ else
+ {
+ // Lonely charLeftOver (from previous call) would've been caught up above,
+ // so this must be a case where we've already read an input char.
+ Contract.Assert(chars > charStart,
+ "[UnicodeEncoding.GetBytes]Expected chars to have advanced for failed fallback");
+ chars--; // Not using this char
+ }
+ ThrowBytesOverflow(encoder, bytes == byteStart); // Throw maybe (if no bytes written)
+ break; // didn't throw, just stop
+ }
+
+ if (bigEndian)
+ {
+ *(bytes++) = (byte)(ch >> 8);
+ *(bytes++) = (byte)ch;
+ }
+ else
+ {
+ *(bytes++) = (byte)ch;
+ *(bytes++) = (byte)(ch >> 8);
+ }
+ }
+
+ // Don't allocate space for left over char
+ if (charLeftOver > 0)
+ {
+ // If we aren't flushing we need to fall this back
+ if (encoder == null || encoder.MustFlush)
+ {
+ if (wasHereBefore)
+ {
+ // Throw it, using our complete character
+ throw new ArgumentException(
+ Environment.GetResourceString("Argument_RecursiveFallback",
+ charLeftOver), "chars");
+ }
+ else
+ {
+ // If we have to flush, stick it in fallback and try again
+ // Might need to create our fallback buffer
+ if (fallbackBuffer == null)
+ {
+ if (encoder == null)
+ fallbackBuffer = this.encoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = encoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
+ }
+
+ // If we're not flushing, this'll remember the left over character.
+ fallbackBuffer.InternalFallback(charLeftOver, ref chars);
+
+ charLeftOver = (char)0;
+ wasHereBefore = true;
+ goto TryAgain;
+ }
+ }
+
+ }
+
+ // Not flushing, remember it in the encoder
+ if (encoder != null)
+ {
+ encoder.charLeftOver = charLeftOver;
+ encoder.m_charsUsed = (int)(chars - charStart);
+ }
+
+ // Remember charLeftOver if we must, or clear it if we're flushing
+ // (charLeftOver should be 0 if we're flushing)
+ Contract.Assert((encoder != null && !encoder.MustFlush) || charLeftOver == (char)0,
+ "[UnicodeEncoding.GetBytes] Expected no left over characters if flushing");
+
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0 ||
+ encoder == null || !encoder.m_throwOnOverflow,
+ "[UnicodeEncoding.GetBytes]Expected empty fallback buffer if not converting");
+
+ // We used to copy it fast, but this doesn't check for surrogates
+ // System.IO.__UnmanagedMemoryStream.memcpyimpl(bytes, (byte*)chars, usedByteCount);
+
+ return (int)(bytes - byteStart);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ {
+ Contract.Assert(bytes!=null, "[UnicodeEncoding.GetCharCount]bytes!=null");
+ Contract.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0");
+
+ UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder;
+
+ byte* byteEnd = bytes + count;
+ byte* byteStart = bytes;
+
+ // Need last vars
+ int lastByte = -1;
+ char lastChar = (char)0;
+
+ // Start by assuming same # of chars as bytes
+ int charCount = count >> 1;
+
+ // Need -1 to check 2 at a time. If we have an even #, longBytes will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(byteEnd - 7);
+
+ // For fallback we may need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ if (decoder != null)
+ {
+ lastByte = decoder.lastByte;
+ lastChar = decoder.lastChar;
+
+ // Assume extra char if last char was around
+ if (lastChar > 0)
+ charCount++;
+
+ // Assume extra char if extra last byte makes up odd # of input bytes
+ if (lastByte >= 0 && (count & 1) == 1)
+ {
+ charCount++;
+ }
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[UnicodeEncoding.GetCharCount]Expected empty fallback buffer at start");
+ }
+
+ while (bytes < byteEnd)
+ {
+ // If we're aligned then maybe we can do it fast
+ // This'll hurt if we're unaligned because we'll always test but never be aligned
+#if !NO_FAST_UNICODE_LOOP
+#if BIGENDIAN
+ if (bigEndian &&
+#else // BIGENDIAN
+ if (!bigEndian &&
+#endif // BIGENDIAN
+#if BIT64 // win64 has to be long aligned
+ (unchecked((long)bytes) & 7) == 0 &&
+#else
+ (unchecked((int)bytes) & 3) == 0 &&
+#endif // BIT64
+ lastByte == -1 && lastChar == 0)
+ {
+ // Need new char* so we can check 4 at a time
+ ulong* longBytes = (ulong*)bytes;
+
+ while (longBytes < longEnd)
+ {
+ // See if we potentially have surrogates (0x8000 bit set)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so this'll work)
+ if ((0x8000800080008000 & *longBytes) != 0)
+ {
+ // See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
+ // 5 bits looks like 11011, then its a high or low surrogate.
+ // We do the & f800 to filter the 5 bits, then ^ d800 to ensure the 0 isn't set.
+ // Note that we expect BMP characters to be more common than surrogates
+ // & each char with 11111... then ^ with 11011. Zeroes then indicate surrogates
+ ulong uTemp = (0xf800f800f800f800 & *longBytes) ^ 0xd800d800d800d800;
+
+ // Check each of the 4 chars. 0 for those 16 bits means it was a surrogate
+ // but no clue if they're high or low.
+ // If each of the 4 characters are non-zero, then none are surrogates.
+ if ((uTemp & 0xFFFF000000000000) == 0 ||
+ (uTemp & 0x0000FFFF00000000) == 0 ||
+ (uTemp & 0x00000000FFFF0000) == 0 ||
+ (uTemp & 0x000000000000FFFF) == 0)
+ {
+ // It has at least 1 surrogate, but we don't know if they're high or low surrogates,
+ // or if there's 1 or 4 surrogates
+
+ // If they happen to be high/low/high/low, we may as well continue. Check the next
+ // bit to see if its set (low) or not (high) in the right pattern
+#if BIGENDIAN
+ if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
+#else
+ if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
+#endif
+ {
+ // Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
+ // was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
+
+ // Drop out to the slow loop to resolve the surrogates
+ break;
+ }
+ // else they are all surrogates in High/Low/High/Low order, so we can use them.
+ }
+ // else none are surrogates, so we can use them.
+ }
+ // else all < 0x8000 so we can use them
+
+ // We can use these 4 chars.
+ longBytes++;
+ }
+
+ bytes = (byte*)longBytes;
+
+ if (bytes >= byteEnd)
+ break;
+ }
+#endif // !NO_FAST_UNICODE_LOOP
+
+ // Get 1st byte
+ if (lastByte < 0)
+ {
+ lastByte = *bytes++;
+ if (bytes >= byteEnd) break;
+ }
+
+ // Get full char
+ char ch;
+ if (bigEndian)
+ {
+ ch = (char)(lastByte << 8 | *(bytes++));
+ }
+ else
+ {
+ ch = (char)(*(bytes++) << 8 | lastByte);
+ }
+ lastByte = -1;
+
+ // See if the char's valid
+ if (ch >= 0xd800 && ch <= 0xdfff)
+ {
+ // Was it a high surrogate?
+ if (ch <= 0xdbff)
+ {
+ // Its a high surrogate, if we had one then do fallback for previous one
+ if (lastChar > 0)
+ {
+ // Ignore previous bad high surrogate
+ charCount--;
+
+ // Get fallback for previous high surrogate
+ // Note we have to reconstruct bytes because some may have been in decoder
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+ }
+
+ // Get fallback.
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+ }
+
+ // Ignore the last one which fell back already,
+ // and remember the new high surrogate
+ lastChar = ch;
+ continue;
+ }
+
+ // Its a low surrogate
+ if (lastChar == 0)
+ {
+ // Expected a previous high surrogate
+ charCount--;
+
+ // Get fallback for this low surrogate
+ // Note we have to reconstruct bytes because some may have been in decoder
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(ch >> 8)), unchecked((byte)ch) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)ch), unchecked((byte)(ch >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+ }
+
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+
+ // Ignore this one (we already did its fallback)
+ continue;
+ }
+
+ // Valid surrogate pair, already counted.
+ lastChar = (char)0;
+ }
+ else if (lastChar > 0)
+ {
+ // Had a high surrogate, expected a low surrogate
+ // Uncount the last high surrogate
+ charCount--;
+
+ // fall back the high surrogate.
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+ }
+
+ // Already subtracted high surrogate
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+
+ // Not left over now, clear previous high surrogate and continue to add current char
+ lastChar = (char)0;
+ }
+
+ // Valid char, already counted
+ }
+
+ // Extra space if we can't use decoder
+ if (decoder == null || decoder.MustFlush)
+ {
+ if (lastChar > 0)
+ {
+ // No hanging high surrogates allowed, do fallback and remove count for it
+ charCount--;
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+ }
+
+ charCount += fallbackBuffer.InternalFallback(byteBuffer, bytes);
+
+ lastChar = (char)0;
+ }
+
+ if (lastByte >= 0)
+ {
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, null);
+ }
+
+ // No hanging odd bytes allowed if must flush
+ charCount += fallbackBuffer.InternalFallback( new byte[] { unchecked((byte)lastByte) }, bytes);
+ lastByte = -1;
+ }
+ }
+
+ // If we had a high surrogate left over, we can't count it
+ if (lastChar > 0)
+ charCount--;
+
+ // Shouldn't have anything in fallback buffer for GetCharCount
+ // (don't have to check m_throwOnOverflow for count)
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[UnicodeEncoding.GetCharCount]Expected empty fallback buffer at end");
+
+ return charCount;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal override unsafe int GetChars(byte* bytes, int byteCount,
+ char* chars, int charCount, DecoderNLS baseDecoder )
+ {
+ Contract.Assert(chars!=null, "[UnicodeEncoding.GetChars]chars!=null");
+ Contract.Assert(byteCount >=0, "[UnicodeEncoding.GetChars]byteCount >=0");
+ Contract.Assert(charCount >=0, "[UnicodeEncoding.GetChars]charCount >=0");
+ Contract.Assert(bytes!=null, "[UnicodeEncoding.GetChars]bytes!=null");
+
+ UnicodeEncoding.Decoder decoder = (UnicodeEncoding.Decoder)baseDecoder;
+
+ // Need last vars
+ int lastByte = -1;
+ char lastChar = (char)0;
+
+ // Get our decoder (but don't clear it yet)
+ if (decoder != null)
+ {
+ lastByte = decoder.lastByte;
+ lastChar = decoder.lastChar;
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for chars)
+ Contract.Assert(!decoder.InternalHasFallbackBuffer || decoder.FallbackBuffer.Remaining == 0,
+ "[UnicodeEncoding.GetChars]Expected empty fallback buffer at start");
+ }
+
+ // For fallback we may need a fallback buffer
+ DecoderFallbackBuffer fallbackBuffer = null;
+
+ byte* byteEnd = bytes + byteCount;
+ char* charEnd = chars + charCount;
+ byte* byteStart = bytes;
+ char* charStart = chars;
+
+ while (bytes < byteEnd)
+ {
+ // If we're aligned then maybe we can do it fast
+ // This'll hurt if we're unaligned because we'll always test but never be aligned
+#if !NO_FAST_UNICODE_LOOP
+#if BIGENDIAN
+ if (bigEndian &&
+#else // BIGENDIAN
+ if (!bigEndian &&
+#endif // BIGENDIAN
+#if BIT64 // win64 has to be long aligned
+ (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#else
+ (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
+#endif // BIT64
+ lastByte == -1 && lastChar == 0)
+ {
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ // We can only go iCount units (limited by shorter of char or byte buffers.
+ ulong* longEnd = (ulong*)(bytes - 7 +
+ (((byteEnd - bytes) >> 1 < charEnd - chars) ?
+ (byteEnd - bytes) : (charEnd - chars) << 1));
+
+ // Need new char* so we can check 4 at a time
+ ulong* longBytes = (ulong*)bytes;
+ ulong* longChars = (ulong*)chars;
+
+ while (longBytes < longEnd)
+ {
+ // See if we potentially have surrogates (0x8000 bit set)
+ // (We're either big endian on a big endian machine or little endian on
+ // a little endian machine so this'll work)
+ if ((0x8000800080008000 & *longBytes) != 0)
+ {
+ // See if any of these are high or low surrogates (0xd800 - 0xdfff). If the high
+ // 5 bits looks like 11011, then its a high or low surrogate.
+ // We do the & f800 to filter the 5 bits, then ^ d800 to ensure the 0 isn't set.
+ // Note that we expect BMP characters to be more common than surrogates
+ // & each char with 11111... then ^ with 11011. Zeroes then indicate surrogates
+ ulong uTemp = (0xf800f800f800f800 & *longBytes) ^ 0xd800d800d800d800;
+
+ // Check each of the 4 chars. 0 for those 16 bits means it was a surrogate
+ // but no clue if they're high or low.
+ // If each of the 4 characters are non-zero, then none are surrogates.
+ if ((uTemp & 0xFFFF000000000000) == 0 ||
+ (uTemp & 0x0000FFFF00000000) == 0 ||
+ (uTemp & 0x00000000FFFF0000) == 0 ||
+ (uTemp & 0x000000000000FFFF) == 0)
+ {
+ // It has at least 1 surrogate, but we don't know if they're high or low surrogates,
+ // or if there's 1 or 4 surrogates
+
+ // If they happen to be high/low/high/low, we may as well continue. Check the next
+ // bit to see if its set (low) or not (high) in the right pattern
+#if BIGENDIAN
+ if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
+#else
+ if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
+#endif
+ {
+ // Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
+ // was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
+
+ // Drop out to the slow loop to resolve the surrogates
+ break;
+ }
+ // else they are all surrogates in High/Low/High/Low order, so we can use them.
+ }
+ // else none are surrogates, so we can use them.
+ }
+ // else all < 0x8000 so we can use them
+
+ // We can use these 4 chars.
+ *longChars = *longBytes;
+ longBytes++;
+ longChars++;
+ }
+
+ chars = (char*)longChars;
+ bytes = (byte*)longBytes;
+
+ if (bytes >= byteEnd)
+ break;
+ }
+#endif // !NO_FAST_UNICODE_LOOP
+
+ // Get 1st byte
+ if (lastByte < 0)
+ {
+ lastByte = *bytes++;
+ continue;
+ }
+
+ // Get full char
+ char ch;
+ if (bigEndian)
+ {
+ ch = (char)(lastByte << 8 | *(bytes++));
+ }
+ else
+ {
+ ch = (char)(*(bytes++) << 8 | lastByte);
+ }
+ lastByte = -1;
+
+ // See if the char's valid
+ if (ch >= 0xd800 && ch <= 0xdfff)
+ {
+ // Was it a high surrogate?
+ if (ch <= 0xdbff)
+ {
+ // Its a high surrogate, if we had one then do fallback for previous one
+ if (lastChar > 0)
+ {
+ // Get fallback for previous high surrogate
+ // Note we have to reconstruct bytes because some may have been in decoder
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, charEnd);
+ }
+
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // couldn't fall back lonely surrogate
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (bad surrogate)");
+ bytes-=2; // didn't use these 2 bytes
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // couldn't fallback but didn't throw
+ }
+ }
+
+ // Ignore the previous high surrogate which fell back already,
+ // yet remember the current high surrogate for next time.
+ lastChar = ch;
+ continue;
+ }
+
+ // Its a low surrogate
+ if (lastChar == 0)
+ {
+ // Expected a previous high surrogate
+ // Get fallback for this low surrogate
+ // Note we have to reconstruct bytes because some may have been in decoder
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(ch >> 8)), unchecked((byte)ch) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)ch), unchecked((byte)(ch >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, charEnd);
+ }
+
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // couldn't fall back lonely surrogate
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (lonely surrogate)");
+ bytes-=2; // didn't use these 2 bytes
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // couldn't fallback but didn't throw
+ }
+
+ // Didn't throw, ignore this one (we already did its fallback)
+ continue;
+ }
+
+ // Valid surrogate pair, add our lastChar (will need 2 chars)
+ if (chars >= charEnd - 1)
+ {
+ // couldn't find room for this surrogate pair
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (surrogate pair)");
+ bytes-=2; // didn't use these 2 bytes
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ // Leave lastChar for next call to Convert()
+ break; // couldn't fallback but didn't throw
+ }
+
+ *chars++ = lastChar;
+ lastChar = (char)0;
+ }
+ else if (lastChar > 0)
+ {
+ // Had a high surrogate, expected a low surrogate, fall back the high surrogate.
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, charEnd);
+ }
+
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // couldn't fall back high surrogate, or char that would be next
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (no low surrogate)");
+ bytes-=2; // didn't use these 2 bytes
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // couldn't fallback but didn't throw
+ }
+
+ // Not left over now, clear previous high surrogate and continue to add current char
+ lastChar = (char)0;
+ }
+
+ // Valid char, room for it?
+ if (chars >= charEnd)
+ {
+ // 2 bytes couldn't fall back
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (normal)");
+ bytes-=2; // didn't use these bytes
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ break; // couldn't fallback but didn't throw
+ }
+
+ // add it
+ *chars++ = ch;
+ }
+
+ // Remember our decoder if we must
+ if (decoder == null || decoder.MustFlush)
+ {
+ if (lastChar > 0)
+ {
+ // No hanging high surrogates allowed, do fallback and remove count for it
+ byte[] byteBuffer = null;
+ if (bigEndian)
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)(lastChar >> 8)), unchecked((byte)lastChar) };
+ }
+ else
+ {
+ byteBuffer = new byte[]
+ { unchecked((byte)lastChar), unchecked((byte)(lastChar >> 8)) };
+
+ }
+
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, charEnd);
+ }
+
+ if (!fallbackBuffer.InternalFallback(byteBuffer, bytes, ref chars))
+ {
+ // 2 bytes couldn't fall back
+ // We either advanced bytes or chars should == charStart and throw below
+ Contract.Assert(bytes >= byteStart + 2 || chars == charStart,
+ "[UnicodeEncoding.GetChars]Expected bytes to have advanced or no output (decoder)");
+ bytes-=2; // didn't use these bytes
+ if (lastByte >= 0)
+ bytes--; // had an extra last byte hanging around
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ // We'll remember these in our decoder though
+ bytes+=2;
+ if (lastByte >= 0)
+ bytes++;
+ goto End;
+ }
+
+ // done with this one
+ lastChar = (char)0;
+ }
+
+ if (lastByte >= 0)
+ {
+ if (fallbackBuffer == null)
+ {
+ if (decoder == null)
+ fallbackBuffer = this.decoderFallback.CreateFallbackBuffer();
+ else
+ fallbackBuffer = decoder.FallbackBuffer;
+
+ // Set our internal fallback interesting things.
+ fallbackBuffer.InternalInitialize(byteStart, charEnd);
+ }
+
+ // No hanging odd bytes allowed if must flush
+ if (!fallbackBuffer.InternalFallback( new byte[] { unchecked((byte)lastByte) }, bytes, ref chars ))
+ {
+ // odd byte couldn't fall back
+ bytes--; // didn't use this byte
+ fallbackBuffer.InternalReset();
+ ThrowCharsOverflow(decoder, chars == charStart);// Might throw, if no chars output
+ // didn't throw, but we'll remember it in the decoder
+ bytes++;
+ goto End;
+ }
+
+ // Didn't fail, clear buffer
+ lastByte = -1;
+ }
+ }
+
+ End:
+
+ // Remember our decoder if we must
+ if (decoder != null)
+ {
+ Contract.Assert((decoder.MustFlush == false) || ((lastChar == (char)0) && (lastByte == -1)),
+ "[UnicodeEncoding.GetChars] Expected no left over chars or bytes if flushing"
+// + " " + ((int)lastChar).ToString("X4") + " " + lastByte.ToString("X2")
+ );
+
+ decoder.m_bytesUsed = (int)(bytes - byteStart);
+ decoder.lastChar = lastChar;
+ decoder.lastByte = lastByte;
+ }
+
+ // Used to do this the old way
+ // System.IO.__UnmanagedMemoryStream.memcpyimpl((byte*)chars, bytes, byteCount);
+
+ // Shouldn't have anything in fallback buffer for GetChars
+ // (don't have to check m_throwOnOverflow for count or chars)
+ Contract.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
+ "[UnicodeEncoding.GetChars]Expected empty fallback buffer at end");
+
+ return (int)(chars - charStart);
+ }
+
+
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public override System.Text.Encoder GetEncoder()
+ {
+ return new EncoderNLS(this);
+ }
+
+
+ public override System.Text.Decoder GetDecoder()
+ {
+ return new UnicodeEncoding.Decoder(this);
+ }
+
+
+ public override byte[] GetPreamble()
+ {
+ if (byteOrderMark)
+ {
+ // Note - we must allocate new byte[]'s here to prevent someone
+ // from modifying a cached byte[].
+ if (bigEndian)
+ return new byte[2] { 0xfe, 0xff };
+ else
+ return new byte[2] { 0xff, 0xfe };
+ }
+ return EmptyArray<Byte>.Value;
+ }
+
+
+ public override int GetMaxByteCount(int charCount)
+ {
+ if (charCount < 0)
+ throw new ArgumentOutOfRangeException("charCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
+ long byteCount = (long)charCount + 1;
+
+ if (EncoderFallback.MaxCharCount > 1)
+ byteCount *= EncoderFallback.MaxCharCount;
+
+ // 2 bytes per char
+ byteCount <<= 1;
+
+ if (byteCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("charCount", Environment.GetResourceString("ArgumentOutOfRange_GetByteCountOverflow"));
+
+ return (int)byteCount;
+ }
+
+
+ public override int GetMaxCharCount(int byteCount)
+ {
+ if (byteCount < 0)
+ throw new ArgumentOutOfRangeException("byteCount",
+ Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+
+ // long because byteCount could be biggest int.
+ // 1 char per 2 bytes. Round up in case 1 left over in decoder.
+ // Round up using &1 in case byteCount is max size
+ // Might also need an extra 1 if there's a left over high surrogate in the decoder.
+ long charCount = (long)(byteCount >> 1) + (byteCount & 1) + 1;
+
+ // Don't forget fallback (in case they have a bunch of lonely surrogates or something bizzare like that)
+ if (DecoderFallback.MaxCharCount > 1)
+ charCount *= DecoderFallback.MaxCharCount;
+
+ if (charCount > 0x7fffffff)
+ throw new ArgumentOutOfRangeException("byteCount", Environment.GetResourceString("ArgumentOutOfRange_GetCharCountOverflow"));
+
+ return (int)charCount;
+ }
+
+
+ public override bool Equals(Object value)
+ {
+ UnicodeEncoding that = value as UnicodeEncoding;
+ if (that != null)
+ {
+ //
+ // Big Endian Unicode has different code page (1201) than small Endian one (1200),
+ // so we still have to check m_codePage here.
+ //
+ return (CodePage == that.CodePage) &&
+ byteOrderMark == that.byteOrderMark &&
+// isThrowException == that.isThrowException && // Same as Encoder/Decoder being exception fallbacks
+ bigEndian == that.bigEndian &&
+ (EncoderFallback.Equals(that.EncoderFallback)) &&
+ (DecoderFallback.Equals(that.DecoderFallback));
+ }
+ return (false);
+ }
+
+ public override int GetHashCode()
+ {
+ return CodePage + this.EncoderFallback.GetHashCode() + this.DecoderFallback.GetHashCode() +
+ (byteOrderMark?4:0) + (bigEndian?8:0);
+ }
+
+ [Serializable]
+ private class Decoder : System.Text.DecoderNLS, ISerializable
+ {
+ internal int lastByte = -1;
+ internal char lastChar = '\0';
+
+ public Decoder(UnicodeEncoding encoding) : base(encoding)
+ {
+ // base calls reset
+ }
+
+ // Constructor called by serialization, have to handle deserializing from Everett
+ internal Decoder(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Get Common Info
+ this.lastByte = (int)info.GetValue("lastByte", typeof(int));
+
+ try
+ {
+ // Try the encoding, which is only serialized in Whidbey
+ this.m_encoding = (Encoding)info.GetValue("m_encoding", typeof(Encoding));
+ this.lastChar = (char)info.GetValue("lastChar", typeof(char));
+ this.m_fallback = (DecoderFallback)info.GetValue("m_fallback", typeof(DecoderFallback));
+ }
+ catch (SerializationException)
+ {
+ // Everett didn't serialize the UnicodeEncoding, get the default one
+ bool bigEndian = (bool)info.GetValue("bigEndian", typeof(bool));
+ this.m_encoding = new UnicodeEncoding(bigEndian, false);
+ }
+ }
+
+ // ISerializable implementation, get data for this object
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // Any info?
+ if (info==null) throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ // Save Whidbey data
+ info.AddValue("m_encoding", this.m_encoding);
+ info.AddValue("m_fallback", this.m_fallback);
+ info.AddValue("lastChar", this.lastChar); // Unused by everett so it'll probably get lost
+ info.AddValue("lastByte", this.lastByte);
+
+ // Everett Only
+ info.AddValue("bigEndian", ((UnicodeEncoding)(this.m_encoding)).bigEndian);
+ }
+
+ public override void Reset()
+ {
+ lastByte = -1;
+ lastChar = '\0';
+ if (m_fallbackBuffer != null)
+ m_fallbackBuffer.Reset();
+ }
+
+ // Anything left in our decoder?
+ internal override bool HasState
+ {
+ get
+ {
+ return (this.lastByte != -1 || this.lastChar != '\0');
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/ThreadAttributes.cs b/src/mscorlib/src/System/ThreadAttributes.cs
new file mode 100644
index 0000000000..bbd859c3af
--- /dev/null
+++ b/src/mscorlib/src/System/ThreadAttributes.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: For Threads-related custom attributes.
+**
+**
+=============================================================================*/
+
+namespace System {
+ [AttributeUsage (AttributeTargets.Method)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class STAThreadAttribute : Attribute
+ {
+ public STAThreadAttribute()
+ {
+ }
+ }
+
+ [AttributeUsage (AttributeTargets.Method)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class MTAThreadAttribute : Attribute
+ {
+ public MTAThreadAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ThreadStaticAttribute.cs b/src/mscorlib/src/System/ThreadStaticAttribute.cs
new file mode 100644
index 0000000000..58842eef0b
--- /dev/null
+++ b/src/mscorlib/src/System/ThreadStaticAttribute.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Custom attribute to indicate that the field should be treated
+** as a static relative to a thread.
+**
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+
+[Serializable]
+ [AttributeUsage(AttributeTargets.Field, Inherited = false)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class ThreadStaticAttribute : Attribute
+ {
+ public ThreadStaticAttribute()
+ {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/AbandonedMutexException.cs b/src/mscorlib/src/System/Threading/AbandonedMutexException.cs
new file mode 100644
index 0000000000..6b4977fbc5
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/AbandonedMutexException.cs
@@ -0,0 +1,85 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+// AbandonedMutexException
+// Thrown when a wait completes because one or more mutexes was abandoned.
+// AbandonedMutexs indicate serious error in user code or machine state.
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System.Threading {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+
+ [Serializable]
+ [ComVisibleAttribute(false)]
+ public class AbandonedMutexException : SystemException {
+
+ private int m_MutexIndex = -1;
+ private Mutex m_Mutex = null;
+
+ public AbandonedMutexException()
+ : base(Environment.GetResourceString("Threading.AbandonedMutexException")) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ }
+
+ public AbandonedMutexException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ }
+
+ public AbandonedMutexException(String message, Exception inner )
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ }
+
+ public AbandonedMutexException(int location, WaitHandle handle)
+ : base(Environment.GetResourceString("Threading.AbandonedMutexException")) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ SetupException(location,handle);
+ }
+
+ public AbandonedMutexException(String message,int location, WaitHandle handle)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ SetupException(location,handle);
+ }
+
+ public AbandonedMutexException(String message, Exception inner,int location, WaitHandle handle )
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_ABANDONEDMUTEX);
+ SetupException(location,handle);
+ }
+
+ private void SetupException(int location, WaitHandle handle)
+ {
+ m_MutexIndex = location;
+ if(handle != null)
+ m_Mutex = handle as Mutex;
+ }
+
+ protected AbandonedMutexException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+
+ public Mutex Mutex
+ {
+ get {
+ return m_Mutex;
+ }
+ }
+
+ public int MutexIndex
+ {
+ get{
+ return m_MutexIndex;
+ }
+ }
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/ApartmentState.cs b/src/mscorlib/src/System/Threading/ApartmentState.cs
new file mode 100644
index 0000000000..844f85e9e7
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ApartmentState.cs
@@ -0,0 +1,28 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Enum to represent the different threading models
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ApartmentState
+ {
+ /*=========================================================================
+ ** Constants for thread apartment states.
+ =========================================================================*/
+ STA = 0,
+ MTA = 1,
+ Unknown = 2
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/AsyncLocal.cs b/src/mscorlib/src/System/Threading/AsyncLocal.cs
new file mode 100644
index 0000000000..264f2a6ff7
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/AsyncLocal.cs
@@ -0,0 +1,116 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using System.Security;
+
+namespace System.Threading
+{
+ //
+ // AsyncLocal<T> represents "ambient" data that is local to a given asynchronous control flow, such as an
+ // async method. For example, say you want to associate a culture with a given async flow:
+ //
+ // static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>();
+ //
+ // static async Task SomeOperationAsync(Culture culture)
+ // {
+ // s_currentCulture.Value = culture;
+ //
+ // await FooAsync();
+ // }
+ //
+ // static async Task FooAsync()
+ // {
+ // PrintStringWithCulture(s_currentCulture.Value);
+ // }
+ //
+ // AsyncLocal<T> also provides optional notifications when the value associated with the current thread
+ // changes, either because it was explicitly changed by setting the Value property, or implicitly changed
+ // when the thread encountered an "await" or other context transition. For example, we might want our
+ // current culture to be communicated to the OS as well:
+ //
+ // static AsyncLocal<Culture> s_currentCulture = new AsyncLocal<Culture>(
+ // args =>
+ // {
+ // NativeMethods.SetThreadCulture(args.CurrentValue.LCID);
+ // });
+ //
+ public sealed class AsyncLocal<T> : IAsyncLocal
+ {
+ [SecurityCritical] // critical because this action will terminate the process if it throws.
+ private readonly Action<AsyncLocalValueChangedArgs<T>> m_valueChangedHandler;
+
+ //
+ // Constructs an AsyncLocal<T> that does not receive change notifications.
+ //
+ public AsyncLocal()
+ {
+ }
+
+ //
+ // Constructs an AsyncLocal<T> with a delegate that is called whenever the current value changes
+ // on any thread.
+ //
+ [SecurityCritical]
+ public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
+ {
+ m_valueChangedHandler = valueChangedHandler;
+ }
+
+ public T Value
+ {
+ [SecuritySafeCritical]
+ get
+ {
+ object obj = ExecutionContext.GetLocalValue(this);
+ return (obj == null) ? default(T) : (T)obj;
+ }
+ [SecuritySafeCritical]
+ set
+ {
+ ExecutionContext.SetLocalValue(this, value, m_valueChangedHandler != null);
+ }
+ }
+
+ [SecurityCritical]
+ void IAsyncLocal.OnValueChanged(object previousValueObj, object currentValueObj, bool contextChanged)
+ {
+ Contract.Assert(m_valueChangedHandler != null);
+ T previousValue = previousValueObj == null ? default(T) : (T)previousValueObj;
+ T currentValue = currentValueObj == null ? default(T) : (T)currentValueObj;
+ m_valueChangedHandler(new AsyncLocalValueChangedArgs<T>(previousValue, currentValue, contextChanged));
+ }
+ }
+
+ //
+ // Interface to allow non-generic code in ExecutionContext to call into the generic AsyncLocal<T> type.
+ //
+ internal interface IAsyncLocal
+ {
+ [SecurityCritical]
+ void OnValueChanged(object previousValue, object currentValue, bool contextChanged);
+ }
+
+ public struct AsyncLocalValueChangedArgs<T>
+ {
+ public T PreviousValue { get; private set; }
+ public T CurrentValue { get; private set; }
+
+ //
+ // If the value changed because we changed to a different ExecutionContext, this is true. If it changed
+ // because someone set the Value property, this is false.
+ //
+ public bool ThreadContextChanged { get; private set; }
+
+ internal AsyncLocalValueChangedArgs(T previousValue, T currentValue, bool contextChanged)
+ : this()
+ {
+ PreviousValue = previousValue;
+ CurrentValue = currentValue;
+ ThreadContextChanged = contextChanged;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/AutoResetEvent.cs b/src/mscorlib/src/System/Threading/AutoResetEvent.cs
new file mode 100644
index 0000000000..6fe6c06232
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/AutoResetEvent.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: An example of a WaitHandle class
+**
+**
+=============================================================================*/
+namespace System.Threading {
+
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class AutoResetEvent : EventWaitHandle
+ {
+ public AutoResetEvent(bool initialState) : base(initialState,EventResetMode.AutoReset){ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/CancellationToken.cs b/src/mscorlib/src/System/Threading/CancellationToken.cs
new file mode 100644
index 0000000000..48a2344c31
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/CancellationToken.cs
@@ -0,0 +1,499 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+////////////////////////////////////////////////////////////////////////////////
+
+#pragma warning disable 0420 // turn off 'a reference to a volatile field will not be treated as volatile' during CAS.
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Propagates notification that operations should be canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A <see cref="CancellationToken"/> may be created directly in an unchangeable canceled or non-canceled state
+ /// using the CancellationToken's constructors. However, to have a CancellationToken that can change
+ /// from a non-canceled to a canceled state,
+ /// <see cref="System.Threading.CancellationTokenSource">CancellationTokenSource</see> must be used.
+ /// CancellationTokenSource exposes the associated CancellationToken that may be canceled by the source through its
+ /// <see cref="System.Threading.CancellationTokenSource.Token">Token</see> property.
+ /// </para>
+ /// <para>
+ /// Once canceled, a token may not transition to a non-canceled state, and a token whose
+ /// <see cref="CanBeCanceled"/> is false will never change to one that can be canceled.
+ /// </para>
+ /// <para>
+ /// All members of this struct are thread-safe and may be used concurrently from multiple threads.
+ /// </para>
+ /// </remarks>
+ [ComVisible(false)]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerDisplay("IsCancellationRequested = {IsCancellationRequested}")]
+ public struct CancellationToken
+ {
+ // The backing TokenSource.
+ // if null, it implicitly represents the same thing as new CancellationToken(false).
+ // When required, it will be instantiated to reflect this.
+ private CancellationTokenSource m_source;
+ //!! warning. If more fields are added, the assumptions in CreateLinkedToken may no longer be valid
+
+ /* Properties */
+
+ /// <summary>
+ /// Returns an empty CancellationToken value.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="CancellationToken"/> value returned by this property will be non-cancelable by default.
+ /// </remarks>
+ public static CancellationToken None
+ {
+ get { return default(CancellationToken); }
+ }
+
+ /// <summary>
+ /// Gets whether cancellation has been requested for this token.
+ /// </summary>
+ /// <value>Whether cancellation has been requested for this token.</value>
+ /// <remarks>
+ /// <para>
+ /// This property indicates whether cancellation has been requested for this token,
+ /// either through the token initially being construted in a canceled state, or through
+ /// calling <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
+ /// on the token's associated <see cref="CancellationTokenSource"/>.
+ /// </para>
+ /// <para>
+ /// If this property is true, it only guarantees that cancellation has been requested.
+ /// It does not guarantee that every registered handler
+ /// has finished executing, nor that cancellation requests have finished propagating
+ /// to all registered handlers. Additional synchronization may be required,
+ /// particularly in situations where related objects are being canceled concurrently.
+ /// </para>
+ /// </remarks>
+ public bool IsCancellationRequested
+ {
+ get
+ {
+ return m_source != null && m_source.IsCancellationRequested;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this token is capable of being in the canceled state.
+ /// </summary>
+ /// <remarks>
+ /// If CanBeCanceled returns false, it is guaranteed that the token will never transition
+ /// into a canceled state, meaning that <see cref="IsCancellationRequested"/> will never
+ /// return true.
+ /// </remarks>
+ public bool CanBeCanceled
+ {
+ get
+ {
+ return m_source != null && m_source.CanBeCanceled;
+ }
+ }
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is signaled when the token is canceled.</summary>
+ /// <remarks>
+ /// Accessing this property causes a <see cref="T:System.Threading.WaitHandle">WaitHandle</see>
+ /// to be instantiated. It is preferable to only use this property when necessary, and to then
+ /// dispose the associated <see cref="CancellationTokenSource"/> instance at the earliest opportunity (disposing
+ /// the source will dispose of this allocated handle). The handle should not be closed or disposed directly.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public WaitHandle WaitHandle
+ {
+ get
+ {
+ if (m_source == null)
+ {
+ InitializeDefaultSource();
+ }
+
+ return m_source.WaitHandle;
+ }
+ }
+
+ // public CancellationToken()
+ // this constructor is implicit for structs
+ // -> this should behaves exactly as for new CancellationToken(false)
+
+ /// <summary>
+ /// Internal constructor only a CancellationTokenSource should create a CancellationToken
+ /// </summary>
+ internal CancellationToken(CancellationTokenSource source)
+ {
+ m_source = source;
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <param name="canceled">
+ /// The canceled state for the token.
+ /// </param>
+ /// <remarks>
+ /// Tokens created with this constructor will remain in the canceled state specified
+ /// by the <paramref name="canceled"/> parameter. If <paramref name="canceled"/> is false,
+ /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be false.
+ /// If <paramref name="canceled"/> is true,
+ /// both <see cref="CanBeCanceled"/> and <see cref="IsCancellationRequested"/> will be true.
+ /// </remarks>
+ public CancellationToken(bool canceled) :
+ this()
+ {
+ if(canceled)
+ m_source = CancellationTokenSource.InternalGetStaticSource(canceled);
+ }
+
+ /* Methods */
+
+
+ private readonly static Action<Object> s_ActionToActionObjShunt = new Action<Object>(ActionToActionObjShunt);
+ private static void ActionToActionObjShunt(object obj)
+ {
+ Action action = obj as Action;
+ Contract.Assert(action != null, "Expected an Action here");
+ action();
+ }
+
+ /// <summary>
+ /// Registers a delegate that will be called when this <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to deregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action callback)
+ {
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ return Register(
+ s_ActionToActionObjShunt,
+ callback,
+ false, // useSync=false
+ true // useExecutionContext=true
+ );
+ }
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to deregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext)
+ {
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ return Register(
+ s_ActionToActionObjShunt,
+ callback,
+ useSynchronizationContext,
+ true // useExecutionContext=true
+ );
+ }
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists, will be captured
+ /// along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to deregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ public CancellationTokenRegistration Register(Action<Object> callback, Object state)
+ {
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ return Register(
+ callback,
+ state,
+ false, // useSync=false
+ true // useExecutionContext=true
+ );
+ }
+
+ /// <summary>
+ /// Registers a delegate that will be called when this
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// If this token is already in the canceled state, the
+ /// delegate will be run immediately and synchronously. Any exception the delegate generates will be
+ /// propagated out of this method call.
+ /// </para>
+ /// <para>
+ /// The current <see cref="System.Threading.ExecutionContext">ExecutionContext</see>, if one exists,
+ /// will be captured along with the delegate and will be used when executing it.
+ /// </para>
+ /// </remarks>
+ /// <param name="callback">The delegate to be executed when the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> is canceled.</param>
+ /// <param name="state">The state to pass to the <paramref name="callback"/> when the delegate is invoked. This may be null.</param>
+ /// <param name="useSynchronizationContext">A Boolean value that indicates whether to capture
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see> and use it
+ /// when invoking the <paramref name="callback"/>.</param>
+ /// <returns>The <see cref="T:System.Threading.CancellationTokenRegistration"/> instance that can
+ /// be used to deregister the callback.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="callback"/> is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public CancellationTokenRegistration Register(Action<Object> callback, Object state, bool useSynchronizationContext)
+ {
+ return Register(
+ callback,
+ state,
+ useSynchronizationContext,
+ true // useExecutionContext=true
+ );
+ }
+
+ // helper for internal registration needs that don't require an EC capture (e.g. creating linked token sources, or registering unstarted TPL tasks)
+ // has a handy signature, and skips capturing execution context.
+ internal CancellationTokenRegistration InternalRegisterWithoutEC(Action<object> callback, Object state)
+ {
+ return Register(
+ callback,
+ state,
+ false, // useSyncContext=false
+ false // useExecutionContext=false
+ );
+ }
+
+ // the real work..
+ [SecuritySafeCritical]
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private CancellationTokenRegistration Register(Action<Object> callback, Object state, bool useSynchronizationContext, bool useExecutionContext)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ if (callback == null)
+ throw new ArgumentNullException("callback");
+
+ if (CanBeCanceled == false)
+ {
+ return new CancellationTokenRegistration(); // nothing to do for tokens than can never reach the canceled state. Give them a dummy registration.
+ }
+
+ // Capture sync/execution contexts if required.
+ // Note: Only capture sync/execution contexts if IsCancellationRequested = false
+ // as we know that if it is true that the callback will just be called synchronously.
+
+ SynchronizationContext capturedSyncContext = null;
+ ExecutionContext capturedExecutionContext = null;
+ if (!IsCancellationRequested)
+ {
+ if (useSynchronizationContext)
+ capturedSyncContext = SynchronizationContext.Current;
+ if (useExecutionContext)
+ capturedExecutionContext = ExecutionContext.Capture(
+ ref stackMark, ExecutionContext.CaptureOptions.OptimizeDefaultCase); // ideally we'd also use IgnoreSyncCtx, but that could break compat
+ }
+
+ // Register the callback with the source.
+ return m_source.InternalRegister(callback, state, capturedSyncContext, capturedExecutionContext);
+ }
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// specified token.
+ /// </summary>
+ /// <param name="other">The other <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to which to compare this
+ /// instance.</param>
+ /// <returns>True if the instances are equal; otherwise, false. Two tokens are equal if they are associated
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
+ public bool Equals(CancellationToken other)
+ {
+ //if both sources are null, then both tokens represent the Empty token.
+ if (m_source == null && other.m_source == null)
+ {
+ return true;
+ }
+
+ // one is null but other has inflated the default source
+ // these are only equal if the inflated one is the staticSource(false)
+ if (m_source == null)
+ {
+ return other.m_source == CancellationTokenSource.InternalGetStaticSource(false);
+ }
+
+ if (other.m_source == null)
+ {
+ return m_source == CancellationTokenSource.InternalGetStaticSource(false);
+ }
+
+ // general case, we check if the sources are identical
+
+ return m_source == other.m_source;
+ }
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// specified <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="other">The other object to which to compare this instance.</param>
+ /// <returns>True if <paramref name="other"/> is a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
+ /// and if the two instances are equal; otherwise, false. Two tokens are equal if they are associated
+ /// with the same <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> or if they were both constructed
+ /// from public CancellationToken constructors and their <see cref="IsCancellationRequested"/> values are equal.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public override bool Equals(Object other)
+ {
+ if (other is CancellationToken)
+ {
+ return Equals((CancellationToken) other);
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <returns>A hash code for the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance.</returns>
+ public override Int32 GetHashCode()
+ {
+ if (m_source == null)
+ {
+ // link to the common source so that we have a source to interrogate.
+ return CancellationTokenSource.InternalGetStaticSource(false).GetHashCode();
+ }
+
+ return m_source.GetHashCode();
+ }
+
+ /// <summary>
+ /// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are equal; otherwise, false.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public static bool operator ==(CancellationToken left, CancellationToken right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Determines whether two <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances are not equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are not equal; otherwise, false.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">An associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public static bool operator !=(CancellationToken left, CancellationToken right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Throws a <see cref="T:System.OperationCanceledException">OperationCanceledException</see> if
+ /// this token has had cancellation requested.
+ /// </summary>
+ /// <remarks>
+ /// This method provides functionality equivalent to:
+ /// <code>
+ /// if (token.IsCancellationRequested)
+ /// throw new OperationCanceledException(token);
+ /// </code>
+ /// </remarks>
+ /// <exception cref="System.OperationCanceledException">The token has had cancellation requested.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The associated <see
+ /// cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> has been disposed.</exception>
+ public void ThrowIfCancellationRequested()
+ {
+ if (IsCancellationRequested)
+ ThrowOperationCanceledException();
+ }
+
+ // Throw an ODE if this CancellationToken's source is disposed.
+ internal void ThrowIfSourceDisposed()
+ {
+ if ((m_source != null) && m_source.IsDisposed)
+ ThrowObjectDisposedException();
+ }
+
+ // Throws an OCE; separated out to enable better inlining of ThrowIfCancellationRequested
+ private void ThrowOperationCanceledException()
+ {
+ throw new OperationCanceledException(Environment.GetResourceString("OperationCanceled"), this);
+ }
+
+ private static void ThrowObjectDisposedException()
+ {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("CancellationToken_SourceDisposed"));
+ }
+
+ // -----------------------------------
+ // Private helpers
+
+ private void InitializeDefaultSource()
+ {
+ // Lazy is slower, and although multiple threads may try and set m_source repeatedly, the race condition is benign.
+ // Alternative: LazyInititalizer.EnsureInitialized(ref m_source, ()=>CancellationTokenSource.InternalGetStaticSource(false));
+
+ m_source = CancellationTokenSource.InternalGetStaticSource(false);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs b/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs
new file mode 100644
index 0000000000..34e0bb0aba
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/CancellationTokenRegistration.cs
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+////////////////////////////////////////////////////////////////////////////////
+
+using System.Diagnostics.Contracts;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Represents a callback delegate that has been registered with a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <remarks>
+ /// To unregister a callback, dispose the corresponding Registration instance.
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct CancellationTokenRegistration : IEquatable<CancellationTokenRegistration>, IDisposable
+ {
+ private readonly CancellationCallbackInfo m_callbackInfo;
+ private readonly SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> m_registrationInfo;
+
+ internal CancellationTokenRegistration(
+ CancellationCallbackInfo callbackInfo,
+ SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> registrationInfo)
+ {
+ m_callbackInfo = callbackInfo;
+ m_registrationInfo = registrationInfo;
+ }
+
+ /// <summary>
+ /// Attempts to deregister the item. If it's already being run, this may fail.
+ /// Entails a full memory fence.
+ /// </summary>
+ /// <returns>True if the callback was found and deregistered, false otherwise.</returns>
+ [FriendAccessAllowed]
+ internal bool TryDeregister()
+ {
+ if (m_registrationInfo.Source == null) //can be null for dummy registrations.
+ return false;
+
+ // Try to remove the callback info from the array.
+ // It is possible the callback info is missing (removed for run, or removed by someone else)
+ // It is also possible there is info in the array but it doesn't match our current registration's callback info.
+ CancellationCallbackInfo prevailingCallbackInfoInSlot = m_registrationInfo.Source.SafeAtomicRemove(m_registrationInfo.Index, m_callbackInfo);
+
+ if (prevailingCallbackInfoInSlot != m_callbackInfo)
+ return false; //the callback in the slot wasn't us.
+
+ return true;
+ }
+
+ /// <summary>
+ /// Disposes of the registration and unregisters the target callback from the associated
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// If the target callback is currently executing this method will wait until it completes, except
+ /// in the degenerate cases where a callback method deregisters itself.
+ /// </summary>
+ public void Dispose()
+ {
+ // Remove the entry from the array.
+ // This call includes a full memory fence which prevents potential reorderings of the reads below
+ bool deregisterOccurred = TryDeregister();
+
+ // We guarantee that we will not return if the callback is being executed (assuming we are not currently called by the callback itself)
+ // We achieve this by the following rules:
+ // 1. if we are called in the context of an executing callback, no need to wait (determined by tracking callback-executor threadID)
+ // - if the currently executing callback is this CTR, then waiting would deadlock. (We choose to return rather than deadlock)
+ // - if not, then this CTR cannot be the one executing, hence no need to wait
+ //
+ // 2. if deregistration failed, and we are on a different thread, then the callback may be running under control of cts.Cancel()
+ // => poll until cts.ExecutingCallback is not the one we are trying to deregister.
+
+ var callbackInfo = m_callbackInfo;
+ if (callbackInfo != null)
+ {
+ var tokenSource = callbackInfo.CancellationTokenSource;
+ if (tokenSource.IsCancellationRequested && //running callbacks has commenced.
+ !tokenSource.IsCancellationCompleted && //running callbacks hasn't finished
+ !deregisterOccurred && //deregistration failed (ie the callback is missing from the list)
+ tokenSource.ThreadIDExecutingCallbacks != Thread.CurrentThread.ManagedThreadId) //the executingThreadID is not this threadID.
+ {
+ // Callback execution is in progress, the executing thread is different to us and has taken the callback for execution
+ // so observe and wait until this target callback is no longer the executing callback.
+ tokenSource.WaitForCallbackToComplete(m_callbackInfo);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Determines whether two <see
+ /// cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see>
+ /// instances are equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are equal; otherwise, false.</returns>
+ public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right)
+ {
+ return left.Equals(right);
+ }
+
+ /// <summary>
+ /// Determines whether two <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instances are not equal.
+ /// </summary>
+ /// <param name="left">The first instance.</param>
+ /// <param name="right">The second instance.</param>
+ /// <returns>True if the instances are not equal; otherwise, false.</returns>
+ public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right)
+ {
+ return !left.Equals(right);
+ }
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instance is equal to the
+ /// specified <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="obj">The other object to which to compare this instance.</param>
+ /// <returns>True, if both this and <paramref name="obj"/> are equal. False, otherwise.
+ /// Two <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instances are equal if
+ /// they both refer to the output of a single call to the same Register method of a
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </returns>
+ public override bool Equals(object obj)
+ {
+ return ((obj is CancellationTokenRegistration) && Equals((CancellationTokenRegistration) obj));
+ }
+
+ /// <summary>
+ /// Determines whether the current <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instance is equal to the
+ /// specified <see cref="T:System.Object"/>.
+ /// </summary>
+ /// <param name="other">The other <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> to which to compare this instance.</param>
+ /// <returns>True, if both this and <paramref name="other"/> are equal. False, otherwise.
+ /// Two <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instances are equal if
+ /// they both refer to the output of a single call to the same Register method of a
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see>.
+ /// </returns>
+ public bool Equals(CancellationTokenRegistration other)
+ {
+ return m_callbackInfo == other.m_callbackInfo &&
+ m_registrationInfo.Source == other.m_registrationInfo.Source &&
+ m_registrationInfo.Index == other.m_registrationInfo.Index;
+ }
+
+ /// <summary>
+ /// Serves as a hash function for a <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration.</see>.
+ /// </summary>
+ /// <returns>A hash code for the current <see cref="T:System.Threading.CancellationTokenRegistration">CancellationTokenRegistration</see> instance.</returns>
+ public override int GetHashCode()
+ {
+ if (m_registrationInfo.Source != null)
+ return m_registrationInfo.Source.GetHashCode() ^ m_registrationInfo.Index.GetHashCode();
+
+ return m_registrationInfo.Index.GetHashCode();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/CancellationTokenSource.cs b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs
new file mode 100644
index 0000000000..954cd38344
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/CancellationTokenSource.cs
@@ -0,0 +1,1269 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+//
+////////////////////////////////////////////////////////////////////////////////
+
+using System;
+using System.Security;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+using System.Runtime;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Signals to a <see cref="System.Threading.CancellationToken"/> that it should be canceled.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// <see cref="T:System.Threading.CancellationTokenSource"/> is used to instantiate a <see
+ /// cref="T:System.Threading.CancellationToken"/>
+ /// (via the source's <see cref="System.Threading.CancellationTokenSource.Token">Token</see> property)
+ /// that can be handed to operations that wish to be notified of cancellation or that can be used to
+ /// register asynchronous operations for cancellation. That token may have cancellation requested by
+ /// calling to the source's <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see>
+ /// method.
+ /// </para>
+ /// <para>
+ /// All members of this class, except <see cref="Dispose">Dispose</see>, are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </para>
+ /// </remarks>
+ [ComVisible(false)]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+
+ public class CancellationTokenSource : IDisposable
+ {
+ //static sources that can be used as the backing source for 'fixed' CancellationTokens that never change state.
+ private static readonly CancellationTokenSource _staticSource_Set = new CancellationTokenSource(true);
+ private static readonly CancellationTokenSource _staticSource_NotCancelable = new CancellationTokenSource(false);
+
+ //Note: the callback lists array is only created on first registration.
+ // the actual callback lists are only created on demand.
+ // Storing a registered callback costs around >60bytes, hence some overhead for the lists array is OK
+ // At most 24 lists seems reasonable, and caps the cost of the listsArray to 96bytes(32-bit,24-way) or 192bytes(64-bit,24-way).
+ private static readonly int s_nLists = (PlatformHelper.ProcessorCount > 24) ? 24 : PlatformHelper.ProcessorCount;
+
+ private volatile ManualResetEvent m_kernelEvent; //lazily initialized if required.
+
+ private volatile SparselyPopulatedArray<CancellationCallbackInfo>[] m_registeredCallbacksLists;
+
+ // legal values for m_state
+ private const int CANNOT_BE_CANCELED = 0;
+ private const int NOT_CANCELED = 1;
+ private const int NOTIFYING = 2;
+ private const int NOTIFYINGCOMPLETE = 3;
+
+ //m_state uses the pattern "volatile int32 reads, with cmpxch writes" which is safe for updates and cannot suffer torn reads.
+ private volatile int m_state;
+
+
+ /// The ID of the thread currently executing the main body of CTS.Cancel()
+ /// this helps us to know if a call to ctr.Dispose() is running 'within' a cancellation callback.
+ /// This is updated as we move between the main thread calling cts.Cancel() and any syncContexts that are used to
+ /// actually run the callbacks.
+ private volatile int m_threadIDExecutingCallbacks = -1;
+
+ private bool m_disposed;
+
+ // we track the running callback to assist ctr.Dispose() to wait for the target callback to complete.
+ private volatile CancellationCallbackInfo m_executingCallback;
+
+ // provided for CancelAfter and timer-related constructors
+ private volatile Timer m_timer;
+
+ // ----------------------
+ // ** public properties
+
+ /// <summary>
+ /// Gets whether cancellation has been requested for this <see
+ /// cref="System.Threading.CancellationTokenSource">CancellationTokenSource</see>.
+ /// </summary>
+ /// <value>Whether cancellation has been requested for this <see
+ /// cref="System.Threading.CancellationTokenSource">CancellationTokenSource</see>.</value>
+ /// <remarks>
+ /// <para>
+ /// This property indicates whether cancellation has been requested for this token source, such as
+ /// due to a call to its
+ /// <see cref="System.Threading.CancellationTokenSource.Cancel()">Cancel</see> method.
+ /// </para>
+ /// <para>
+ /// If this property returns true, it only guarantees that cancellation has been requested. It does not
+ /// guarantee that every handler registered with the corresponding token has finished executing, nor
+ /// that cancellation requests have finished propagating to all registered handlers. Additional
+ /// synchronization may be required, particularly in situations where related objects are being
+ /// canceled concurrently.
+ /// </para>
+ /// </remarks>
+ public bool IsCancellationRequested
+ {
+ get { return m_state >= NOTIFYING; }
+ }
+
+ /// <summary>
+ /// A simple helper to determine whether cancellation has finished.
+ /// </summary>
+ internal bool IsCancellationCompleted
+ {
+ get { return m_state == NOTIFYINGCOMPLETE; }
+ }
+
+ /// <summary>
+ /// A simple helper to determine whether disposal has occurred.
+ /// </summary>
+ internal bool IsDisposed
+ {
+ get { return m_disposed; }
+ }
+
+ /// <summary>
+ /// The ID of the thread that is running callbacks.
+ /// </summary>
+ internal int ThreadIDExecutingCallbacks
+ {
+ set { m_threadIDExecutingCallbacks = value; }
+ get { return m_threadIDExecutingCallbacks; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// associated with this <see cref="CancellationTokenSource"/>.
+ /// </summary>
+ /// <value>The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// associated with this <see cref="CancellationTokenSource"/>.</value>
+ /// <exception cref="T:System.ObjectDisposedException">The token source has been
+ /// disposed.</exception>
+ public CancellationToken Token
+ {
+ get
+ {
+ ThrowIfDisposed();
+ return new CancellationToken(this);
+ }
+ }
+
+ // ----------------------
+ // ** internal and private properties.
+
+ /// <summary>
+ ///
+ /// </summary>
+ internal bool CanBeCanceled
+ {
+ get { return m_state != CANNOT_BE_CANCELED; }
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ internal WaitHandle WaitHandle
+ {
+ get
+ {
+ ThrowIfDisposed();
+
+ // fast path if already allocated.
+ if (m_kernelEvent != null)
+ return m_kernelEvent;
+
+ // lazy-init the mre.
+ ManualResetEvent mre = new ManualResetEvent(false);
+ if (Interlocked.CompareExchange(ref m_kernelEvent, mre, null) != null)
+ {
+ ((IDisposable)mre).Dispose();
+ }
+
+ // There is a race condition between checking IsCancellationRequested and setting the event.
+ // However, at this point, the kernel object definitely exists and the cases are:
+ // 1. if IsCancellationRequested = true, then we will call Set()
+ // 2. if IsCancellationRequested = false, then NotifyCancellation will see that the event exists, and will call Set().
+ if (IsCancellationRequested)
+ m_kernelEvent.Set();
+
+ return m_kernelEvent;
+ }
+ }
+
+
+ /// <summary>
+ /// The currently executing callback
+ /// </summary>
+ internal CancellationCallbackInfo ExecutingCallback
+ {
+ get { return m_executingCallback; }
+ }
+
+#if DEBUG
+ /// <summary>
+ /// Used by the dev unit tests to check the number of outstanding registrations.
+ /// They use private reflection to gain access. Because this would be dead retail
+ /// code, however, it is ifdef'd out to work only in debug builds.
+ /// </summary>
+ private int CallbackCount
+ {
+ get
+ {
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+ if (callbackLists == null)
+ return 0;
+
+ int count = 0;
+ foreach(SparselyPopulatedArray<CancellationCallbackInfo> sparseArray in callbackLists)
+ {
+ if(sparseArray != null)
+ {
+ SparselyPopulatedArrayFragment<CancellationCallbackInfo> currCallbacks = sparseArray.Head;
+ while (currCallbacks != null)
+ {
+ for (int i = 0; i < currCallbacks.Length; i++)
+ if (currCallbacks[i] != null)
+ count++;
+
+ currCallbacks = currCallbacks.Next;
+ }
+ }
+ }
+ return count;
+ }
+ }
+#endif
+
+ // ** Public Constructors
+
+ /// <summary>
+ /// Initializes the <see cref="T:System.Threading.CancellationTokenSource"/>.
+ /// </summary>
+ public CancellationTokenSource()
+ {
+ m_state = NOT_CANCELED;
+ }
+
+ // ** Private constructors for static sources.
+ // set=false ==> cannot be canceled.
+ // set=true ==> is canceled.
+ private CancellationTokenSource(bool set)
+ {
+ m_state = set ? NOTIFYINGCOMPLETE : CANNOT_BE_CANCELED;
+ }
+
+ /// <summary>
+ /// Constructs a <see cref="T:System.Threading.CancellationTokenSource"/> that will be canceled after a specified time span.
+ /// </summary>
+ /// <param name="delay">The time span to wait before canceling this <see cref="T:System.Threading.CancellationTokenSource"/></param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when <paramref name="delay"/> is less than -1 or greater than Int32.MaxValue.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// The countdown for the delay starts during the call to the constructor. When the delay expires,
+ /// the constructed <see cref="T:System.Threading.CancellationTokenSource"/> is canceled, if it has
+ /// not been canceled already.
+ /// </para>
+ /// <para>
+ /// Subsequent calls to CancelAfter will reset the delay for the constructed
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
+ /// canceled already.
+ /// </para>
+ /// </remarks>
+ public CancellationTokenSource(TimeSpan delay)
+ {
+ long totalMilliseconds = (long)delay.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("delay");
+ }
+
+ InitializeWithTimer((int)totalMilliseconds);
+ }
+
+ /// <summary>
+ /// Constructs a <see cref="T:System.Threading.CancellationTokenSource"/> that will be canceled after a specified time span.
+ /// </summary>
+ /// <param name="millisecondsDelay">The time span to wait before canceling this <see cref="T:System.Threading.CancellationTokenSource"/></param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when <paramref name="millisecondsDelay"/> is less than -1.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// The countdown for the millisecondsDelay starts during the call to the constructor. When the millisecondsDelay expires,
+ /// the constructed <see cref="T:System.Threading.CancellationTokenSource"/> is canceled (if it has
+ /// not been canceled already).
+ /// </para>
+ /// <para>
+ /// Subsequent calls to CancelAfter will reset the millisecondsDelay for the constructed
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
+ /// canceled already.
+ /// </para>
+ /// </remarks>
+ public CancellationTokenSource(Int32 millisecondsDelay)
+ {
+ if (millisecondsDelay < -1)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsDelay");
+ }
+
+ InitializeWithTimer(millisecondsDelay);
+ }
+
+ // Common initialization logic when constructing a CTS with a delay parameter
+ private void InitializeWithTimer(Int32 millisecondsDelay)
+ {
+ m_state = NOT_CANCELED;
+ m_timer = new Timer(s_timerCallback, this, millisecondsDelay, -1);
+ }
+
+ // ** Public Methods
+
+ /// <summary>
+ /// Communicates a request for cancellation.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The associated <see cref="T:System.Threading.CancellationToken" /> will be
+ /// notified of the cancellation and will transition to a state where
+ /// <see cref="System.Threading.CancellationToken.IsCancellationRequested">IsCancellationRequested</see> returns true.
+ /// Any callbacks or cancelable operations
+ /// registered with the <see cref="T:System.Threading.CancellationToken"/> will be executed.
+ /// </para>
+ /// <para>
+ /// Cancelable operations and callbacks registered with the token should not throw exceptions.
+ /// However, this overload of Cancel will aggregate any exceptions thrown into a <see cref="System.AggregateException"/>,
+ /// such that one callback throwing an exception will not prevent other registered callbacks from being executed.
+ /// </para>
+ /// <para>
+ /// The <see cref="T:System.Threading.ExecutionContext"/> that was captured when each callback was registered
+ /// will be reestablished when the callback is invoked.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.AggregateException">An aggregate exception containing all the exceptions thrown
+ /// by the registered callbacks on the associated <see cref="T:System.Threading.CancellationToken"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">This <see
+ /// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.</exception>
+ public void Cancel()
+ {
+ Cancel(false);
+ }
+
+ /// <summary>
+ /// Communicates a request for cancellation.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The associated <see cref="T:System.Threading.CancellationToken" /> will be
+ /// notified of the cancellation and will transition to a state where
+ /// <see cref="System.Threading.CancellationToken.IsCancellationRequested">IsCancellationRequested</see> returns true.
+ /// Any callbacks or cancelable operations
+ /// registered with the <see cref="T:System.Threading.CancellationToken"/> will be executed.
+ /// </para>
+ /// <para>
+ /// Cancelable operations and callbacks registered with the token should not throw exceptions.
+ /// If <paramref name="throwOnFirstException"/> is true, an exception will immediately propagate out of the
+ /// call to Cancel, preventing the remaining callbacks and cancelable operations from being processed.
+ /// If <paramref name="throwOnFirstException"/> is false, this overload will aggregate any
+ /// exceptions thrown into a <see cref="System.AggregateException"/>,
+ /// such that one callback throwing an exception will not prevent other registered callbacks from being executed.
+ /// </para>
+ /// <para>
+ /// The <see cref="T:System.Threading.ExecutionContext"/> that was captured when each callback was registered
+ /// will be reestablished when the callback is invoked.
+ /// </para>
+ /// </remarks>
+ /// <param name="throwOnFirstException">Specifies whether exceptions should immediately propagate.</param>
+ /// <exception cref="T:System.AggregateException">An aggregate exception containing all the exceptions thrown
+ /// by the registered callbacks on the associated <see cref="T:System.Threading.CancellationToken"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">This <see
+ /// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.</exception>
+ public void Cancel(bool throwOnFirstException)
+ {
+ ThrowIfDisposed();
+ NotifyCancellation(throwOnFirstException);
+ }
+
+ /// <summary>
+ /// Schedules a Cancel operation on this <see cref="T:System.Threading.CancellationTokenSource"/>.
+ /// </summary>
+ /// <param name="delay">The time span to wait before canceling this <see
+ /// cref="T:System.Threading.CancellationTokenSource"/>.
+ /// </param>
+ /// <exception cref="T:System.ObjectDisposedException">The exception thrown when this <see
+ /// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception thrown when <paramref name="delay"/> is less than -1 or
+ /// greater than Int32.MaxValue.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// The countdown for the delay starts during this call. When the delay expires,
+ /// this <see cref="T:System.Threading.CancellationTokenSource"/> is canceled, if it has
+ /// not been canceled already.
+ /// </para>
+ /// <para>
+ /// Subsequent calls to CancelAfter will reset the delay for this
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
+ /// canceled already.
+ /// </para>
+ /// </remarks>
+ public void CancelAfter(TimeSpan delay)
+ {
+ long totalMilliseconds = (long)delay.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("delay");
+ }
+
+ CancelAfter((int)totalMilliseconds);
+ }
+
+ /// <summary>
+ /// Schedules a Cancel operation on this <see cref="T:System.Threading.CancellationTokenSource"/>.
+ /// </summary>
+ /// <param name="millisecondsDelay">The time span to wait before canceling this <see
+ /// cref="T:System.Threading.CancellationTokenSource"/>.
+ /// </param>
+ /// <exception cref="T:System.ObjectDisposedException">The exception thrown when this <see
+ /// cref="T:System.Threading.CancellationTokenSource"/> has been disposed.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception thrown when <paramref name="millisecondsDelay"/> is less than -1.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// The countdown for the millisecondsDelay starts during this call. When the millisecondsDelay expires,
+ /// this <see cref="T:System.Threading.CancellationTokenSource"/> is canceled, if it has
+ /// not been canceled already.
+ /// </para>
+ /// <para>
+ /// Subsequent calls to CancelAfter will reset the millisecondsDelay for this
+ /// <see cref="T:System.Threading.CancellationTokenSource"/>, if it has not been
+ /// canceled already.
+ /// </para>
+ /// </remarks>
+ public void CancelAfter(Int32 millisecondsDelay)
+ {
+ ThrowIfDisposed();
+
+ if (millisecondsDelay < -1)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsDelay");
+ }
+
+ if (IsCancellationRequested) return;
+
+ // There is a race condition here as a Cancel could occur between the check of
+ // IsCancellationRequested and the creation of the timer. This is benign; in the
+ // worst case, a timer will be created that has no effect when it expires.
+
+ // Also, if Dispose() is called right here (after ThrowIfDisposed(), before timer
+ // creation), it would result in a leaked Timer object (at least until the timer
+ // expired and Disposed itself). But this would be considered bad behavior, as
+ // Dispose() is not thread-safe and should not be called concurrently with CancelAfter().
+
+ if (m_timer == null)
+ {
+ // Lazily initialize the timer in a thread-safe fashion.
+ // Initially set to "never go off" because we don't want to take a
+ // chance on a timer "losing" the initialization and then
+ // cancelling the token before it (the timer) can be disposed.
+ Timer newTimer = new Timer(s_timerCallback, this, -1, -1);
+ if (Interlocked.CompareExchange(ref m_timer, newTimer, null) != null)
+ {
+ // We did not initialize the timer. Dispose the new timer.
+ newTimer.Dispose();
+ }
+ }
+
+
+ // It is possible that m_timer has already been disposed, so we must do
+ // the following in a try/catch block.
+ try
+ {
+ m_timer.Change(millisecondsDelay, -1);
+ }
+ catch (ObjectDisposedException)
+ {
+ // Just eat the exception. There is no other way to tell that
+ // the timer has been disposed, and even if there were, there
+ // would not be a good way to deal with the observe/dispose
+ // race condition.
+ }
+
+ }
+
+ private static readonly TimerCallback s_timerCallback = new TimerCallback(TimerCallbackLogic);
+
+ // Common logic for a timer delegate
+ private static void TimerCallbackLogic(object obj)
+ {
+ CancellationTokenSource cts = (CancellationTokenSource)obj;
+
+ // Cancel the source; handle a race condition with cts.Dispose()
+ if (!cts.IsDisposed)
+ {
+ // There is a small window for a race condition where a cts.Dispose can sneak
+ // in right here. I'll wrap the cts.Cancel() in a try/catch to proof us
+ // against this race condition.
+ try
+ {
+ cts.Cancel(); // will take care of disposing of m_timer
+ }
+ catch (ObjectDisposedException)
+ {
+ // If the ODE was not due to the target cts being disposed, then propagate the ODE.
+ if (!cts.IsDisposed) throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.CancellationTokenSource" />.
+ /// </summary>
+ /// <remarks>
+ /// This method is not thread-safe for any other concurrent calls.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases the unmanaged resources used by the <see cref="T:System.Threading.CancellationTokenSource" /> class and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool disposing)
+ {
+ // There is nothing to do if disposing=false because the CancellationTokenSource holds no unmanaged resources.
+
+ if (disposing && !m_disposed)
+ {
+ //NOTE: We specifically tolerate that a callback can be deregistered
+ // after the CTS has been disposed and/or concurrently with cts.Dispose().
+ // This is safe without locks because the reg.Dispose() only
+ // mutates a sparseArrayFragment and then reads from properties of the CTS that are not
+ // invalidated by cts.Dispose().
+ //
+ // We also tolerate that a callback can be registered after the CTS has been
+ // disposed. This is safe without locks because InternalRegister is tolerant
+ // of m_registeredCallbacksLists becoming null during its execution. However,
+ // we run the acceptable risk of m_registeredCallbacksLists getting reinitialized
+ // to non-null if there is a race between Dispose and Register, in which case this
+ // instance may unnecessarily hold onto a registered callback. But that's no worse
+ // than if Dispose wasn't safe to use concurrently, as Dispose would never be called,
+ // and thus no handlers would be dropped.
+ //
+ // And, we tolerate Dispose being used concurrently with Cancel. This is necessary
+ // to properly support LinkedCancellationTokenSource, where, due to common usage patterns,
+ // it's possible for this pairing to occur with valid usage (e.g. a component accepts
+ // an external CancellationToken and uses CreateLinkedTokenSource to combine it with an
+ // internal source of cancellation, then Disposes of that linked source, which could
+ // happen at the same time the external entity is requesting cancellation).
+
+ m_timer?.Dispose(); // Timer.Dispose is thread-safe
+
+ // registered callbacks are now either complete or will never run, due to guarantees made by ctr.Dispose()
+ // so we can now perform main disposal work without risk of linking callbacks trying to use this CTS.
+
+ m_registeredCallbacksLists = null; // free for GC; Cancel correctly handles a null field
+
+ // If a kernel event was created via WaitHandle, we'd like to Dispose of it. However,
+ // we only want to do so if it's not being used by Cancel concurrently. First, we
+ // interlocked exchange it to be null, and then we check whether cancellation is currently
+ // in progress. NotifyCancellation will only try to set the event if it exists after it's
+ // transitioned to and while it's in the NOTIFYING state.
+ if (m_kernelEvent != null)
+ {
+ ManualResetEvent mre = Interlocked.Exchange(ref m_kernelEvent, null);
+ if (mre != null && m_state != NOTIFYING)
+ {
+ mre.Dispose();
+ }
+ }
+
+ m_disposed = true;
+ }
+ }
+
+ // -- Internal methods.
+
+ /// <summary>
+ /// Throws an exception if the source has been disposed.
+ /// </summary>
+ internal void ThrowIfDisposed()
+ {
+ if (m_disposed)
+ ThrowObjectDisposedException();
+ }
+
+ // separation enables inlining of ThrowIfDisposed
+ private static void ThrowObjectDisposedException()
+ {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("CancellationTokenSource_Disposed"));
+ }
+
+ /// <summary>
+ /// InternalGetStaticSource()
+ /// </summary>
+ /// <param name="set">Whether the source should be set.</param>
+ /// <returns>A static source to be shared among multiple tokens.</returns>
+ internal static CancellationTokenSource InternalGetStaticSource(bool set)
+ {
+ return set ? _staticSource_Set : _staticSource_NotCancelable;
+ }
+
+ /// <summary>
+ /// Registers a callback object. If cancellation has already occurred, the
+ /// callback will have been run by the time this method returns.
+ /// </summary>
+ internal CancellationTokenRegistration InternalRegister(
+ Action<object> callback, object stateForCallback, SynchronizationContext targetSyncContext, ExecutionContext executionContext)
+ {
+ if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ {
+ ThrowIfDisposed();
+ }
+
+ // the CancellationToken has already checked that the token is cancelable before calling this method.
+ Contract.Assert(CanBeCanceled, "Cannot register for uncancelable token src");
+
+ // if not canceled, register the event handlers
+ // if canceled already, run the callback synchronously
+ // Apart from the semantics of late-enlistment, this also ensures that during ExecuteCallbackHandlers() there
+ // will be no mutation of the _registeredCallbacks list
+
+ if (!IsCancellationRequested)
+ {
+ // In order to enable code to not leak too many handlers, we allow Dispose to be called concurrently
+ // with Register. While this is not a recommended practice, consumers can and do use it this way.
+ // We don't make any guarantees about whether the CTS will hold onto the supplied callback
+ // if the CTS has already been disposed when the callback is registered, but we try not to
+ // while at the same time not paying any non-negligible overhead. The simple compromise
+ // is to check whether we're disposed (not volatile), and if we see we are, to return an empty
+ // registration, just as if CanBeCanceled was false for the check made in CancellationToken.Register.
+ // If there's a race and m_disposed is false even though it's been disposed, or if the disposal request
+ // comes in after this line, we simply run the minor risk of having m_registeredCallbacksLists reinitialized
+ // (after it was cleared to null during Dispose).
+
+ if (m_disposed && !AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ return new CancellationTokenRegistration();
+
+ int myIndex = Thread.CurrentThread.ManagedThreadId % s_nLists;
+
+ CancellationCallbackInfo callbackInfo = targetSyncContext != null ?
+ new CancellationCallbackInfo.WithSyncContext(callback, stateForCallback, executionContext, this, targetSyncContext) :
+ new CancellationCallbackInfo(callback, stateForCallback, executionContext, this);
+
+ //allocate the callback list array
+ var registeredCallbacksLists = m_registeredCallbacksLists;
+ if (registeredCallbacksLists == null)
+ {
+ SparselyPopulatedArray<CancellationCallbackInfo>[] list = new SparselyPopulatedArray<CancellationCallbackInfo>[s_nLists];
+ registeredCallbacksLists = Interlocked.CompareExchange(ref m_registeredCallbacksLists, list, null);
+ if (registeredCallbacksLists == null) registeredCallbacksLists = list;
+ }
+
+ //allocate the actual lists on-demand to save mem in low-use situations, and to avoid false-sharing.
+ var callbacks = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref registeredCallbacksLists[myIndex]);
+ if (callbacks == null)
+ {
+ SparselyPopulatedArray<CancellationCallbackInfo> callBackArray = new SparselyPopulatedArray<CancellationCallbackInfo>(4);
+ Interlocked.CompareExchange(ref (registeredCallbacksLists[myIndex]), callBackArray, null);
+ callbacks = registeredCallbacksLists[myIndex];
+ }
+
+ // Now add the registration to the list.
+ SparselyPopulatedArrayAddInfo<CancellationCallbackInfo> addInfo = callbacks.Add(callbackInfo);
+ CancellationTokenRegistration registration = new CancellationTokenRegistration(callbackInfo, addInfo);
+
+ if (!IsCancellationRequested)
+ return registration;
+
+ // If a cancellation has since come in, we will try to undo the registration and run the callback ourselves.
+ // (this avoids leaving the callback orphaned)
+ bool deregisterOccurred = registration.TryDeregister();
+
+ if (!deregisterOccurred)
+ {
+ // The thread that is running Cancel() snagged our callback for execution.
+ // So we don't need to run it, but we do return the registration so that
+ // ctr.Dispose() will wait for callback completion.
+ return registration;
+ }
+ }
+
+ // If cancellation already occurred, we run the callback on this thread and return an empty registration.
+ callback(stateForCallback);
+ return new CancellationTokenRegistration();
+ }
+
+ /// <summary>
+ ///
+ /// </summary>
+ private void NotifyCancellation(bool throwOnFirstException)
+ {
+ // fast-path test to check if Notify has been called previously
+ if (IsCancellationRequested)
+ return;
+
+ // If we're the first to signal cancellation, do the main extra work.
+ if (Interlocked.CompareExchange(ref m_state, NOTIFYING, NOT_CANCELED) == NOT_CANCELED)
+ {
+ // Dispose of the timer, if any. Dispose may be running concurrently here, but Timer.Dispose is thread-safe.
+ m_timer?.Dispose();
+
+ // Record the threadID being used for running the callbacks.
+ ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
+
+ // Set the event if it's been lazily initialized and hasn't yet been disposed of. Dispose may
+ // be running concurrently, in which case either it'll have set m_kernelEvent back to null and
+ // we won't see it here, or it'll see that we've transitioned to NOTIFYING and will skip disposing it,
+ // leaving cleanup to finalization.
+ m_kernelEvent?.Set(); // update the MRE value.
+
+ // - late enlisters to the Canceled event will have their callbacks called immediately in the Register() methods.
+ // - Callbacks are not called inside a lock.
+ // - After transition, no more delegates will be added to the
+ // - list of handlers, and hence it can be consumed and cleared at leisure by ExecuteCallbackHandlers.
+ ExecuteCallbackHandlers(throwOnFirstException);
+ Contract.Assert(IsCancellationCompleted, "Expected cancellation to have finished");
+ }
+ }
+
+ /// <summary>
+ /// Invoke the Canceled event.
+ /// </summary>
+ /// <remarks>
+ /// The handlers are invoked synchronously in LIFO order.
+ /// </remarks>
+ private void ExecuteCallbackHandlers(bool throwOnFirstException)
+ {
+ Contract.Assert(IsCancellationRequested, "ExecuteCallbackHandlers should only be called after setting IsCancellationRequested->true");
+ Contract.Assert(ThreadIDExecutingCallbacks != -1, "ThreadIDExecutingCallbacks should have been set.");
+
+ // Design decision: call the delegates in LIFO order so that callbacks fire 'deepest first'.
+ // This is intended to help with nesting scenarios so that child enlisters cancel before their parents.
+ List<Exception> exceptionList = null;
+ SparselyPopulatedArray<CancellationCallbackInfo>[] callbackLists = m_registeredCallbacksLists;
+
+ // If there are no callbacks to run, we can safely exit. Any race conditions to lazy initialize it
+ // will see IsCancellationRequested and will then run the callback themselves.
+ if (callbackLists == null)
+ {
+ Interlocked.Exchange(ref m_state, NOTIFYINGCOMPLETE);
+ return;
+ }
+
+ try
+ {
+ for (int index = 0; index < callbackLists.Length; index++)
+ {
+ SparselyPopulatedArray<CancellationCallbackInfo> list = Volatile.Read<SparselyPopulatedArray<CancellationCallbackInfo>>(ref callbackLists[index]);
+ if (list != null)
+ {
+ SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment = list.Tail;
+
+ while (currArrayFragment != null)
+ {
+ for (int i = currArrayFragment.Length - 1; i >= 0; i--)
+ {
+ // 1a. publish the indended callback, to ensure ctr.Dipose can tell if a wait is necessary.
+ // 1b. transition to the target syncContext and continue there..
+ // On the target SyncContext.
+ // 2. actually remove the callback
+ // 3. execute the callback
+ // re:#2 we do the remove on the syncCtx so that we can be sure we have control of the syncCtx before
+ // grabbing the callback. This prevents a deadlock if ctr.Dispose() might run on the syncCtx too.
+ m_executingCallback = currArrayFragment[i];
+ if (m_executingCallback != null)
+ {
+ //Transition to the target sync context (if necessary), and continue our work there.
+ CancellationCallbackCoreWorkArguments args = new CancellationCallbackCoreWorkArguments(currArrayFragment, i);
+
+ // marshal exceptions: either aggregate or perform an immediate rethrow
+ // We assume that syncCtx.Send() has forwarded on user exceptions when appropriate.
+ try
+ {
+ var wsc = m_executingCallback as CancellationCallbackInfo.WithSyncContext;
+ if (wsc != null)
+ {
+ Contract.Assert(wsc.TargetSyncContext != null, "Should only have derived CCI if non-null SyncCtx");
+ wsc.TargetSyncContext.Send(CancellationCallbackCoreWork_OnSyncContext, args);
+ // CancellationCallbackCoreWork_OnSyncContext may have altered ThreadIDExecutingCallbacks, so reset it.
+ ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
+ }
+ else
+ {
+ CancellationCallbackCoreWork(args);
+ }
+ }
+ catch(Exception ex)
+ {
+ if (throwOnFirstException)
+ throw;
+
+ // Otherwise, log it and proceed.
+ if(exceptionList == null)
+ exceptionList = new List<Exception>();
+ exceptionList.Add(ex);
+ }
+ }
+ }
+
+ currArrayFragment = currArrayFragment.Prev;
+ }
+ }
+ }
+ }
+ finally
+ {
+ m_state = NOTIFYINGCOMPLETE;
+ m_executingCallback = null;
+ Thread.MemoryBarrier(); // for safety, prevent reorderings crossing this point and seeing inconsistent state.
+ }
+
+ if (exceptionList != null)
+ {
+ Contract.Assert(exceptionList.Count > 0, "Expected exception count > 0");
+ throw new AggregateException(exceptionList);
+ }
+ }
+
+ // The main callback work that executes on the target synchronization context
+ private void CancellationCallbackCoreWork_OnSyncContext(object obj)
+ {
+ CancellationCallbackCoreWork((CancellationCallbackCoreWorkArguments)obj);
+ }
+
+ private void CancellationCallbackCoreWork(CancellationCallbackCoreWorkArguments args)
+ {
+ // remove the intended callback..and ensure that it worked.
+ // otherwise the callback has disappeared in the interim and we can immediately return.
+ CancellationCallbackInfo callback = args.m_currArrayFragment.SafeAtomicRemove(args.m_currArrayIndex, m_executingCallback);
+ if (callback == m_executingCallback)
+ {
+ if (callback.TargetExecutionContext != null)
+ {
+ // we are running via a custom sync context, so update the executing threadID
+ callback.CancellationTokenSource.ThreadIDExecutingCallbacks = Thread.CurrentThread.ManagedThreadId;
+ }
+ callback.ExecuteCallback();
+ }
+ }
+
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that will be in the canceled state
+ /// when any of the source tokens are in the canceled state.
+ /// </summary>
+ /// <param name="token1">The first <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to observe.</param>
+ /// <param name="token2">The second <see cref="T:System.Threading.CancellationToken">CancellationToken</see> to observe.</param>
+ /// <returns>A <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that is linked
+ /// to the source tokens.</returns>
+ public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken token1, CancellationToken token2)
+ {
+ return token1.CanBeCanceled || token2.CanBeCanceled ?
+ new LinkedCancellationTokenSource(token1, token2) :
+ new CancellationTokenSource();
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that will be in the canceled state
+ /// when any of the source tokens are in the canceled state.
+ /// </summary>
+ /// <param name="tokens">The <see cref="T:System.Threading.CancellationToken">CancellationToken</see> instances to observe.</param>
+ /// <returns>A <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> that is linked
+ /// to the source tokens.</returns>
+ /// <exception cref="T:System.ArgumentNullException"><paramref name="tokens"/> is null.</exception>
+ public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens)
+ {
+ if (tokens == null)
+ throw new ArgumentNullException("tokens");
+
+ if (tokens.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("CancellationToken_CreateLinkedToken_TokensIsEmpty"));
+
+ // a defensive copy is not required as the array has value-items that have only a single IntPtr field,
+ // hence each item cannot be null itself, and reads of the payloads cannot be torn.
+ Contract.EndContractBlock();
+
+ return new LinkedCancellationTokenSource(tokens);
+ }
+
+
+ // Wait for a single callback to complete (or, more specifically, to not be running).
+ // It is ok to call this method if the callback has already finished.
+ // Calling this method before the target callback has been selected for execution would be an error.
+ internal void WaitForCallbackToComplete(CancellationCallbackInfo callbackInfo)
+ {
+ SpinWait sw = new SpinWait();
+ while (ExecutingCallback == callbackInfo)
+ {
+ sw.SpinOnce(); //spin as we assume callback execution is fast and that this situation is rare.
+ }
+ }
+
+ private sealed class LinkedCancellationTokenSource : CancellationTokenSource
+ {
+ private static readonly Action<object> s_linkedTokenCancelDelegate =
+ s => ((CancellationTokenSource)s).NotifyCancellation(throwOnFirstException: false); // skip ThrowIfDisposed() check in Cancel()
+ private CancellationTokenRegistration[] m_linkingRegistrations;
+
+ internal LinkedCancellationTokenSource(CancellationToken token1, CancellationToken token2)
+ {
+ bool token2CanBeCanceled = token2.CanBeCanceled;
+
+ if (token1.CanBeCanceled)
+ {
+ m_linkingRegistrations = new CancellationTokenRegistration[token2CanBeCanceled ? 2 : 1]; // there will be at least 1 and at most 2 linkings
+ m_linkingRegistrations[0] = token1.InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ }
+
+ if (token2CanBeCanceled)
+ {
+ int index = 1;
+ if (m_linkingRegistrations == null)
+ {
+ m_linkingRegistrations = new CancellationTokenRegistration[1]; // this will be the only linking
+ index = 0;
+ }
+ m_linkingRegistrations[index] = token2.InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ }
+ }
+
+ internal LinkedCancellationTokenSource(params CancellationToken[] tokens)
+ {
+ m_linkingRegistrations = new CancellationTokenRegistration[tokens.Length];
+
+ for (int i = 0; i < tokens.Length; i++)
+ {
+ if (tokens[i].CanBeCanceled)
+ {
+ m_linkingRegistrations[i] = tokens[i].InternalRegisterWithoutEC(s_linkedTokenCancelDelegate, this);
+ }
+ // Empty slots in the array will be default(CancellationTokenRegistration), which are nops to Dispose.
+ // Based on usage patterns, such occurrences should also be rare, such that it's not worth resizing
+ // the array and incurring the related costs.
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (!disposing || m_disposed)
+ return;
+
+ CancellationTokenRegistration[] linkingRegistrations = m_linkingRegistrations;
+ if (linkingRegistrations != null)
+ {
+ m_linkingRegistrations = null; // release for GC once we're done enumerating
+ for (int i = 0; i < linkingRegistrations.Length; i++)
+ {
+ linkingRegistrations[i].Dispose();
+ }
+ }
+
+ base.Dispose(disposing);
+ }
+
+ }
+ }
+
+ // ----------------------------------------------------------
+ // -- CancellationCallbackCoreWorkArguments --
+ // ----------------------------------------------------------
+ // Helper struct for passing data to the target sync context
+ internal struct CancellationCallbackCoreWorkArguments
+ {
+ internal SparselyPopulatedArrayFragment<CancellationCallbackInfo> m_currArrayFragment;
+ internal int m_currArrayIndex;
+
+ public CancellationCallbackCoreWorkArguments(SparselyPopulatedArrayFragment<CancellationCallbackInfo> currArrayFragment, int currArrayIndex)
+ {
+ m_currArrayFragment = currArrayFragment;
+ m_currArrayIndex = currArrayIndex;
+ }
+ }
+
+ // ----------------------------------------------------------
+ // -- CancellationCallbackInfo --
+ // ----------------------------------------------------------
+
+ /// <summary>
+ /// A helper class for collating the various bits of information required to execute
+ /// cancellation callbacks.
+ /// </summary>
+ internal class CancellationCallbackInfo
+ {
+ internal readonly Action<object> Callback;
+ internal readonly object StateForCallback;
+ internal readonly ExecutionContext TargetExecutionContext;
+ internal readonly CancellationTokenSource CancellationTokenSource;
+
+ internal sealed class WithSyncContext : CancellationCallbackInfo
+ {
+ // Very rarely used, and as such it is separated out into a
+ // a derived type so that the space for it is pay-for-play.
+ internal readonly SynchronizationContext TargetSyncContext;
+
+ internal WithSyncContext(
+ Action<object> callback, object stateForCallback, ExecutionContext targetExecutionContext, CancellationTokenSource cancellationTokenSource,
+ SynchronizationContext targetSyncContext) :
+ base(callback, stateForCallback, targetExecutionContext, cancellationTokenSource)
+ {
+ TargetSyncContext = targetSyncContext;
+ }
+
+ }
+
+ internal CancellationCallbackInfo(
+ Action<object> callback, object stateForCallback, ExecutionContext targetExecutionContext, CancellationTokenSource cancellationTokenSource)
+ {
+ Callback = callback;
+ StateForCallback = stateForCallback;
+ TargetExecutionContext = targetExecutionContext;
+ CancellationTokenSource = cancellationTokenSource;
+ }
+
+ // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical
+ [SecurityCritical]
+ private static ContextCallback s_executionContextCallback;
+
+ /// <summary>
+ /// InternalExecuteCallbackSynchronously_GeneralPath
+ /// This will be called on the target synchronization context, however, we still need to restore the required execution context
+ /// </summary>
+ [SecuritySafeCritical]
+ internal void ExecuteCallback()
+ {
+ if (TargetExecutionContext != null)
+ {
+ // Lazily initialize the callback delegate; benign race condition
+ var callback = s_executionContextCallback;
+ if (callback == null) s_executionContextCallback = callback = new ContextCallback(ExecutionContextCallback);
+
+ ExecutionContext.Run(
+ TargetExecutionContext,
+ callback,
+ this);
+ }
+ else
+ {
+ //otherwise run directly
+ ExecutionContextCallback(this);
+ }
+ }
+
+ // the worker method to actually run the callback
+ // The signature is such that it can be used as a 'ContextCallback'
+ [SecurityCritical]
+ private static void ExecutionContextCallback(object obj)
+ {
+ CancellationCallbackInfo callbackInfo = obj as CancellationCallbackInfo;
+ Contract.Assert(callbackInfo != null);
+ callbackInfo.Callback(callbackInfo.StateForCallback);
+ }
+ }
+
+
+ // ----------------------------------------------------------
+ // -- SparselyPopulatedArray --
+ // ----------------------------------------------------------
+
+ /// <summary>
+ /// A sparsely populated array. Elements can be sparse and some null, but this allows for
+ /// lock-free additions and growth, and also for constant time removal (by nulling out).
+ /// </summary>
+ /// <typeparam name="T">The kind of elements contained within.</typeparam>
+ internal class SparselyPopulatedArray<T> where T : class
+ {
+ private readonly SparselyPopulatedArrayFragment<T> m_head;
+ private volatile SparselyPopulatedArrayFragment<T> m_tail;
+
+ /// <summary>
+ /// Allocates a new array with the given initial size.
+ /// </summary>
+ /// <param name="initialSize">How many array slots to pre-allocate.</param>
+ internal SparselyPopulatedArray(int initialSize)
+ {
+ m_head = m_tail = new SparselyPopulatedArrayFragment<T>(initialSize);
+ }
+
+#if DEBUG
+ // Used in DEBUG mode by CancellationTokenSource.CallbackCount
+ /// <summary>
+ /// The head of the doubly linked list.
+ /// </summary>
+ internal SparselyPopulatedArrayFragment<T> Head
+ {
+ get { return m_head; }
+ }
+#endif
+
+ /// <summary>
+ /// The tail of the doubly linked list.
+ /// </summary>
+ internal SparselyPopulatedArrayFragment<T> Tail
+ {
+ get { return m_tail; }
+ }
+
+ /// <summary>
+ /// Adds an element in the first available slot, beginning the search from the tail-to-head.
+ /// If no slots are available, the array is grown. The method doesn't return until successful.
+ /// </summary>
+ /// <param name="element">The element to add.</param>
+ /// <returns>Information about where the add happened, to enable O(1) deregistration.</returns>
+ internal SparselyPopulatedArrayAddInfo<T> Add(T element)
+ {
+ while (true)
+ {
+ // Get the tail, and ensure it's up to date.
+ SparselyPopulatedArrayFragment<T> tail = m_tail;
+ while (tail.m_next != null)
+ m_tail = (tail = tail.m_next);
+
+ // Search for a free index, starting from the tail.
+ SparselyPopulatedArrayFragment<T> curr = tail;
+ while (curr != null)
+ {
+ const int RE_SEARCH_THRESHOLD = -10; // Every 10 skips, force a search.
+ if (curr.m_freeCount < 1)
+ --curr.m_freeCount;
+
+ if (curr.m_freeCount > 0 || curr.m_freeCount < RE_SEARCH_THRESHOLD)
+ {
+ int c = curr.Length;
+
+ // We'll compute a start offset based on how many free slots we think there
+ // are. This optimizes for ordinary the LIFO deregistration pattern, and is
+ // far from perfect due to the non-threadsafe ++ and -- of the free counter.
+ int start = ((c - curr.m_freeCount) % c);
+ if (start < 0)
+ {
+ start = 0;
+ curr.m_freeCount--; // Too many free elements; fix up.
+ }
+ Contract.Assert(start >= 0 && start < c, "start is outside of bounds");
+
+ // Now walk the array until we find a free slot (or reach the end).
+ for (int i = 0; i < c; i++)
+ {
+ // If the slot is null, try to CAS our element into it.
+ int tryIndex = (start + i) % c;
+ Contract.Assert(tryIndex >= 0 && tryIndex < curr.m_elements.Length, "tryIndex is outside of bounds");
+
+ if (curr.m_elements[tryIndex] == null && Interlocked.CompareExchange(ref curr.m_elements[tryIndex], element, null) == null)
+ {
+ // We adjust the free count by --. Note: if this drops to 0, we will skip
+ // the fragment on the next search iteration. Searching threads will -- the
+ // count and force a search every so often, just in case fragmentation occurs.
+ int newFreeCount = curr.m_freeCount - 1;
+ curr.m_freeCount = newFreeCount > 0 ? newFreeCount : 0;
+ return new SparselyPopulatedArrayAddInfo<T>(curr, tryIndex);
+ }
+ }
+ }
+
+ curr = curr.m_prev;
+ }
+
+ // If we got here, we need to add a new chunk to the tail and try again.
+ SparselyPopulatedArrayFragment<T> newTail = new SparselyPopulatedArrayFragment<T>(
+ tail.m_elements.Length == 4096 ? 4096 : tail.m_elements.Length * 2, tail);
+ if (Interlocked.CompareExchange(ref tail.m_next, newTail, null) == null)
+ {
+ m_tail = newTail;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// A struct to hold a link to the exact spot in an array an element was inserted, enabling
+ /// constant time removal later on.
+ /// </summary>
+ internal struct SparselyPopulatedArrayAddInfo<T> where T : class
+ {
+ private SparselyPopulatedArrayFragment<T> m_source;
+ private int m_index;
+
+ internal SparselyPopulatedArrayAddInfo(SparselyPopulatedArrayFragment<T> source, int index)
+ {
+ Contract.Assert(source != null);
+ Contract.Assert(index >= 0 && index < source.Length);
+ m_source = source;
+ m_index = index;
+ }
+
+ internal SparselyPopulatedArrayFragment<T> Source
+ {
+ get { return m_source; }
+ }
+
+ internal int Index
+ {
+ get { return m_index; }
+ }
+ }
+
+ /// <summary>
+ /// A fragment of a sparsely populated array, doubly linked.
+ /// </summary>
+ /// <typeparam name="T">The kind of elements contained within.</typeparam>
+ internal class SparselyPopulatedArrayFragment<T> where T : class
+ {
+ internal readonly T[] m_elements; // The contents, sparsely populated (with nulls).
+ internal volatile int m_freeCount; // A hint of the number of free elements.
+ internal volatile SparselyPopulatedArrayFragment<T> m_next; // The next fragment in the chain.
+ internal volatile SparselyPopulatedArrayFragment<T> m_prev; // The previous fragment in the chain.
+
+ internal SparselyPopulatedArrayFragment(int size) : this(size, null)
+ {
+ }
+
+ internal SparselyPopulatedArrayFragment(int size, SparselyPopulatedArrayFragment<T> prev)
+ {
+ m_elements = new T[size];
+ m_freeCount = size;
+ m_prev = prev;
+ }
+
+ internal T this[int index]
+ {
+ get { return Volatile.Read<T>(ref m_elements[index]); }
+ }
+
+ internal int Length
+ {
+ get { return m_elements.Length; }
+ }
+
+#if DEBUG
+ // Used in DEBUG mode by CancellationTokenSource.CallbackCount
+ internal SparselyPopulatedArrayFragment<T> Next
+ {
+ get { return m_next; }
+ }
+#endif
+ internal SparselyPopulatedArrayFragment<T> Prev
+ {
+ get { return m_prev; }
+ }
+
+ // only removes the item at the specified index if it is still the expected one.
+ // Returns the prevailing value.
+ // The remove occurred successfully if the return value == expected element
+ // otherwise the remove did not occur.
+ internal T SafeAtomicRemove(int index, T expectedElement)
+ {
+ T prevailingValue = Interlocked.CompareExchange(ref m_elements[index], null, expectedElement);
+ if (prevailingValue != null)
+ ++m_freeCount;
+ return prevailingValue;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/CountdownEvent.cs b/src/mscorlib/src/System/Threading/CountdownEvent.cs
new file mode 100644
index 0000000000..1374766863
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/CountdownEvent.cs
@@ -0,0 +1,592 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A simple coordination data structure that we use for fork/join style parallelism.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading
+{
+
+ /// <summary>
+ /// Represents a synchronization primitive that is signaled when its count reaches zero.
+ /// </summary>
+ /// <remarks>
+ /// All public and protected members of <see cref="CountdownEvent"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="CountdownEvent"/> have
+ /// completed, and Reset, which should only be used when no other threads are
+ /// accessing the event.
+ /// </remarks>
+ [ComVisible(false)]
+ [DebuggerDisplay("Initial Count={InitialCount}, Current Count={CurrentCount}")]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class CountdownEvent : IDisposable
+ {
+ // CountdownEvent is a simple synchronization primitive used for fork/join parallelism. We create a
+ // latch with a count of N; threads then signal the latch, which decrements N by 1; other threads can
+ // wait on the latch at any point; when the latch count reaches 0, all threads are woken and
+ // subsequent waiters return without waiting. The implementation internally lazily creates a true
+ // Win32 event as needed. We also use some amount of spinning on MP machines before falling back to a
+ // wait.
+
+ private int m_initialCount; // The original # of signals the latch was instantiated with.
+ private volatile int m_currentCount; // The # of outstanding signals before the latch transitions to a signaled state.
+ private ManualResetEventSlim m_event; // An event used to manage blocking and signaling.
+ private volatile bool m_disposed; // Whether the latch has been disposed.
+
+ /// <summary>
+ /// Initializes a new instance of <see cref="T:System.Threading.CountdownEvent"/> class with the
+ /// specified count.
+ /// </summary>
+ /// <param name="initialCount">The number of signals required to set the <see
+ /// cref="T:System.Threading.CountdownEvent"/>.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="initialCount"/> is less
+ /// than 0.</exception>
+ public CountdownEvent(int initialCount)
+ {
+ if (initialCount < 0)
+ {
+ throw new ArgumentOutOfRangeException("initialCount");
+ }
+
+ m_initialCount = initialCount;
+ m_currentCount = initialCount;
+
+ // Allocate a thin event, which internally defers creation of an actual Win32 event.
+ m_event = new ManualResetEventSlim();
+
+ // If the latch was created with a count of 0, then it's already in the signaled state.
+ if (initialCount == 0)
+ {
+ m_event.Set();
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of remaining signals required to set the event.
+ /// </summary>
+ /// <value>
+ /// The number of remaining signals required to set the event.
+ /// </value>
+ public int CurrentCount
+ {
+ get
+ {
+ int observedCount = m_currentCount;
+ return observedCount < 0 ? 0 : observedCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets the numbers of signals initially required to set the event.
+ /// </summary>
+ /// <value>
+ /// The number of signals initially required to set the event.
+ /// </value>
+ public int InitialCount
+ {
+ get { return m_initialCount; }
+ }
+
+ /// <summary>
+ /// Determines whether the event is set.
+ /// </summary>
+ /// <value>true if the event is set; otherwise, false.</value>
+ public bool IsSet
+ {
+ get
+ {
+ // The latch is "completed" if its current count has reached 0. Note that this is NOT
+ // the same thing is checking the event's IsCompleted property. There is a tiny window
+ // of time, after the final decrement of the current count to 0 and before setting the
+ // event, where the two values are out of sync.
+ return (m_currentCount <= 0);
+ }
+ }
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Threading.WaitHandle"/> that is used to wait for the event to be set.
+ /// </summary>
+ /// <value>A <see cref="T:System.Threading.WaitHandle"/> that is used to wait for the event to be set.</value>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been disposed.</exception>
+ /// <remarks>
+ /// <see cref="WaitHandle"/> should only be used if it's needed for integration with code bases
+ /// that rely on having a WaitHandle. If all that's needed is to wait for the <see cref="CountdownEvent"/>
+ /// to be set, the <see cref="Wait()"/> method should be preferred.
+ /// </remarks>
+ public WaitHandle WaitHandle
+ {
+ get
+ {
+ ThrowIfDisposed();
+ return m_event.WaitHandle;
+ }
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see cref="T:System.Threading.CountdownEvent"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="CountdownEvent"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ // Gets rid of this latch's associated resources. This can consist of a Win32 event
+ // which is (lazily) allocated by the underlying thin event. This method is not safe to
+ // call concurrently -- i.e. a caller must coordinate to ensure only one thread is using
+ // the latch at the time of the call to Dispose.
+
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="T:System.Threading.CountdownEvent"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources; false to release
+ /// only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="CountdownEvent"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ m_event.Dispose();
+ m_disposed = true;
+ }
+ }
+
+ /// <summary>
+ /// Registers a signal with the <see cref="T:System.Threading.CountdownEvent"/>, decrementing its
+ /// count.
+ /// </summary>
+ /// <returns>true if the signal caused the count to reach zero and the event was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.InvalidOperationException">The current instance is already set.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool Signal()
+ {
+ ThrowIfDisposed();
+ Contract.Assert(m_event != null);
+
+ if (m_currentCount <= 0)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Decrement_BelowZero"));
+ }
+#pragma warning disable 0420
+ int newCount = Interlocked.Decrement(ref m_currentCount);
+#pragma warning restore 0420
+ if (newCount == 0)
+ {
+ m_event.Set();
+ return true;
+ }
+ else if (newCount < 0)
+ {
+ //if the count is decremented below zero, then throw, it's OK to keep the count negative, and we shouldn't set the event here
+ //because there was a thread already which decremented it to zero and set the event
+ throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Decrement_BelowZero"));
+ }
+
+ return false;
+ }
+
+ /// <summary>
+ /// Registers multiple signals with the <see cref="T:System.Threading.CountdownEvent"/>,
+ /// decrementing its count by the specified amount.
+ /// </summary>
+ /// <param name="signalCount">The number of signals to register.</param>
+ /// <returns>true if the signals caused the count to reach zero and the event was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The current instance is already set. -or- Or <paramref name="signalCount"/> is greater than <see
+ /// cref="CurrentCount"/>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="signalCount"/> is less
+ /// than 1.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool Signal(int signalCount)
+ {
+ if (signalCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("signalCount");
+ }
+
+ ThrowIfDisposed();
+ Contract.Assert(m_event != null);
+
+ int observedCount;
+ SpinWait spin = new SpinWait();
+ while (true)
+ {
+ observedCount = m_currentCount;
+
+ // If the latch is already signaled, we will fail.
+ if (observedCount < signalCount)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Decrement_BelowZero"));
+ }
+
+ // This disables the "CS0420: a reference to a volatile field will not be treated as volatile" warning
+ // for this statement. This warning is clearly senseless for Interlocked operations.
+#pragma warning disable 0420
+ if (Interlocked.CompareExchange(ref m_currentCount, observedCount - signalCount, observedCount) == observedCount)
+#pragma warning restore 0420
+ {
+ break;
+ }
+
+ // The CAS failed. Spin briefly and try again.
+ spin.SpinOnce();
+ }
+
+ // If we were the last to signal, set the event.
+ if (observedCount == signalCount)
+ {
+ m_event.Set();
+ return true;
+ }
+
+ Contract.Assert(m_currentCount >= 0, "latch was decremented below zero");
+ return false;
+ }
+
+ /// <summary>
+ /// Increments the <see cref="T:System.Threading.CountdownEvent"/>'s current count by one.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">The current instance is already
+ /// set.</exception>
+ /// <exception cref="T:System.InvalidOperationException"><see cref="CurrentCount"/> is equal to <see
+ /// cref="T:System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The current instance has already been disposed.
+ /// </exception>
+ public void AddCount()
+ {
+ AddCount(1);
+ }
+
+ /// <summary>
+ /// Attempts to increment the <see cref="T:System.Threading.CountdownEvent"/>'s current count by one.
+ /// </summary>
+ /// <returns>true if the increment succeeded; otherwise, false. If <see cref="CurrentCount"/> is
+ /// already at zero. this will return false.</returns>
+ /// <exception cref="T:System.InvalidOperationException"><see cref="CurrentCount"/> is equal to <see
+ /// cref="T:System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool TryAddCount()
+ {
+ return TryAddCount(1);
+ }
+
+ /// <summary>
+ /// Increments the <see cref="T:System.Threading.CountdownEvent"/>'s current count by a specified
+ /// value.
+ /// </summary>
+ /// <param name="signalCount">The value by which to increase <see cref="CurrentCount"/>.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="signalCount"/> is less than
+ /// 0.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The current instance is already
+ /// set.</exception>
+ /// <exception cref="T:System.InvalidOperationException"><see cref="CurrentCount"/> is equal to <see
+ /// cref="T:System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void AddCount(int signalCount)
+ {
+ if (!TryAddCount(signalCount))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Increment_AlreadyZero"));
+ }
+ }
+
+ /// <summary>
+ /// Attempts to increment the <see cref="T:System.Threading.CountdownEvent"/>'s current count by a
+ /// specified value.
+ /// </summary>
+ /// <param name="signalCount">The value by which to increase <see cref="CurrentCount"/>.</param>
+ /// <returns>true if the increment succeeded; otherwise, false. If <see cref="CurrentCount"/> is
+ /// already at zero this will return false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="signalCount"/> is less
+ /// than 0.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The current instance is already
+ /// set.</exception>
+ /// <exception cref="T:System.InvalidOperationException"><see cref="CurrentCount"/> is equal to <see
+ /// cref="T:System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool TryAddCount(int signalCount)
+ {
+ if (signalCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("signalCount");
+ }
+
+ ThrowIfDisposed();
+
+ // Loop around until we successfully increment the count.
+ int observedCount;
+ SpinWait spin = new SpinWait();
+ while (true)
+ {
+ observedCount = m_currentCount;
+
+ if (observedCount <= 0)
+ {
+ return false;
+ }
+ else if (observedCount > (Int32.MaxValue - signalCount))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("CountdownEvent_Increment_AlreadyMax"));
+ }
+
+ // This disables the "CS0420: a reference to a volatile field will not be treated as volatile" warning
+ // for this statement. This warning is clearly senseless for Interlocked operations.
+#pragma warning disable 0420
+ if (Interlocked.CompareExchange(ref m_currentCount, observedCount + signalCount, observedCount) == observedCount)
+#pragma warning restore 0420
+ {
+ break;
+ }
+
+ // The CAS failed. Spin briefly and try again.
+ spin.SpinOnce();
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Resets the <see cref="CurrentCount"/> to the value of <see cref="InitialCount"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="CountdownEvent"/>, Reset is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed..</exception>
+ public void Reset()
+ {
+ Reset(m_initialCount);
+ }
+
+ /// <summary>
+ /// Resets the <see cref="CurrentCount"/> to a specified value.
+ /// </summary>
+ /// <param name="count">The number of signals required to set the <see
+ /// cref="T:System.Threading.CountdownEvent"/>.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="CountdownEvent"/>, Reset is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="count"/> is
+ /// less than 0.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has alread been disposed.</exception>
+ public void Reset(int count)
+ {
+ ThrowIfDisposed();
+
+ if (count < 0)
+ {
+ throw new ArgumentOutOfRangeException("count");
+ }
+
+ m_currentCount = count;
+ m_initialCount = count;
+
+ if (count == 0)
+ {
+ m_event.Set();
+ }
+ else
+ {
+ m_event.Reset();
+ }
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set.
+ /// </summary>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait()
+ {
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set, while
+ /// observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state. If the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> being observed
+ /// is canceled during the wait operation, an <see cref="T:System.OperationCanceledException"/>
+ /// will be thrown.
+ /// </remarks>
+ /// <exception cref="T:System.OperationCanceledException"><paramref name="cancellationToken"/> has been
+ /// canceled.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="T:System.TimeSpan"/> that represents the number of
+ /// milliseconds to wait, or a <see cref="T:System.TimeSpan"/> that represents -1 milliseconds to
+ /// wait indefinitely.</param>
+ /// <returns>true if the <see cref="System.Threading.CountdownEvent"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("timeout");
+ }
+
+ return Wait((int)totalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set, using
+ /// a <see cref="T:System.TimeSpan"/> to measure the time interval, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="T:System.TimeSpan"/> that represents the number of
+ /// milliseconds to wait, or a <see cref="T:System.TimeSpan"/> that represents -1 milliseconds to
+ /// wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.CountdownEvent"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="T:System.OperationCanceledException"><paramref name="cancellationToken"/> has
+ /// been canceled.</exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("timeout");
+ }
+
+ return Wait((int)totalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set, using a
+ /// 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the <see cref="System.Threading.CountdownEvent"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the <see cref="T:System.Threading.CountdownEvent"/> is set, using a
+ /// 32-bit signed integer to measure the time interval, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.CountdownEvent"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="T:System.OperationCanceledException"><paramref name="cancellationToken"/> has
+ /// been canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout");
+ }
+
+ ThrowIfDisposed();
+ cancellationToken.ThrowIfCancellationRequested();
+
+ bool returnValue = IsSet;
+
+ // If not completed yet, wait on the event.
+ if (!returnValue)
+ {
+ // ** the actual wait
+ returnValue = m_event.Wait(millisecondsTimeout, cancellationToken);
+ //the Wait will throw OCE itself if the token is canceled.
+ }
+
+ return returnValue;
+ }
+
+ // --------------------------------------
+ // Private methods
+
+
+ /// <summary>
+ /// Throws an exception if the latch has been disposed.
+ /// </summary>
+ private void ThrowIfDisposed()
+ {
+ if (m_disposed)
+ {
+ throw new ObjectDisposedException("CountdownEvent");
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/EventResetMode.cs b/src/mscorlib/src/System/Threading/EventResetMode.cs
new file mode 100644
index 0000000000..edafab9bb5
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/EventResetMode.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+** Enum: EventResetMode
+**
+**
+** Purpose: Enum to determine the Event type to create
+**
+**
+=============================================================================*/
+
+
+namespace System.Threading
+{
+ using System.Runtime.InteropServices;
+ [ComVisibleAttribute(false)]
+ public enum EventResetMode
+ {
+ AutoReset = 0,
+ ManualReset = 1
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/EventWaitHandle.cs b/src/mscorlib/src/System/Threading/EventWaitHandle.cs
new file mode 100644
index 0000000000..f56da1fa26
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/EventWaitHandle.cs
@@ -0,0 +1,297 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Base class for representing Events
+**
+**
+=============================================================================*/
+
+
+#if !FEATURE_MACL
+namespace System.Security.AccessControl
+{
+ public class EventWaitHandleSecurity
+ {
+ }
+ public enum EventWaitHandleRights
+ {
+ }
+}
+#endif
+
+namespace System.Threading
+{
+ using System;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.IO;
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Security.AccessControl;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [ComVisibleAttribute(true)]
+ public class EventWaitHandle : WaitHandle
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public EventWaitHandle(bool initialState, EventResetMode mode) : this(initialState,mode,null) { }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name)
+ {
+ if(name != null)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives"));
+#else
+ if (System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+#endif
+ }
+ Contract.EndContractBlock();
+
+ SafeWaitHandle _handle = null;
+ switch(mode)
+ {
+ case EventResetMode.ManualReset:
+ _handle = Win32Native.CreateEvent(null, true, initialState, name);
+ break;
+ case EventResetMode.AutoReset:
+ _handle = Win32Native.CreateEvent(null, false, initialState, name);
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag",name));
+ };
+
+ if (_handle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ _handle.SetHandleAsInvalid();
+ if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle",name));
+
+ __Error.WinIOError(errorCode, name);
+ }
+ SetHandleInternal(_handle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew)
+ : this(initialState, mode, name, out createdNew, null)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public unsafe EventWaitHandle(bool initialState, EventResetMode mode, string name, out bool createdNew, EventWaitHandleSecurity eventSecurity)
+ {
+ if(name != null)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives"));
+#else
+ if (System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+#endif
+ }
+ Contract.EndContractBlock();
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if FEATURE_MACL
+ // For ACL's, get the security descriptor from the EventWaitHandleSecurity.
+ if (eventSecurity != null) {
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ byte[] sd = eventSecurity.GetSecurityDescriptorBinaryForm();
+ byte* pSecDescriptor = stackalloc byte[sd.Length];
+ Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length);
+ secAttrs.pSecurityDescriptor = pSecDescriptor;
+ }
+#endif
+
+ SafeWaitHandle _handle = null;
+ Boolean isManualReset;
+ switch(mode)
+ {
+ case EventResetMode.ManualReset:
+ isManualReset = true;
+ break;
+ case EventResetMode.AutoReset:
+ isManualReset = false;
+ break;
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag",name));
+ };
+
+ _handle = Win32Native.CreateEvent(secAttrs, isManualReset, initialState, name);
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (_handle.IsInvalid)
+ {
+
+ _handle.SetHandleAsInvalid();
+ if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle",name));
+
+ __Error.WinIOError(errorCode, name);
+ }
+ createdNew = errorCode != Win32Native.ERROR_ALREADY_EXISTS;
+ SetHandleInternal(_handle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private EventWaitHandle(SafeWaitHandle handle)
+ {
+ SetHandleInternal(handle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static EventWaitHandle OpenExisting(string name)
+ {
+#if !FEATURE_MACL
+ return OpenExisting(name, (EventWaitHandleRights)0);
+#else
+ return OpenExisting(name, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize);
+#endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static EventWaitHandle OpenExisting(string name, EventWaitHandleRights rights)
+ {
+ EventWaitHandle result;
+ switch (OpenExistingWorker(name, rights, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
+
+ case OpenExistingResult.PathNotFound:
+ __Error.WinIOError(Win32Native.ERROR_PATH_NOT_FOUND, "");
+ return result; //never executes
+
+ default:
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static bool TryOpenExisting(string name, out EventWaitHandle result)
+ {
+#if !FEATURE_MACL
+ return OpenExistingWorker(name, (EventWaitHandleRights)0, out result) == OpenExistingResult.Success;
+#else
+ return OpenExistingWorker(name, EventWaitHandleRights.Modify | EventWaitHandleRights.Synchronize, out result) == OpenExistingResult.Success;
+#endif
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static bool TryOpenExisting(string name, EventWaitHandleRights rights, out EventWaitHandle result)
+ {
+ return OpenExistingWorker(name, rights, out result) == OpenExistingResult.Success;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ private static OpenExistingResult OpenExistingWorker(string name, EventWaitHandleRights rights, out EventWaitHandle result)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives"));
+#else
+ if (name == null)
+ {
+ throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName"));
+ }
+
+ if(name.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ }
+
+ if(null != name && System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+
+ Contract.EndContractBlock();
+
+ result = null;
+
+#if FEATURE_MACL
+ SafeWaitHandle myHandle = Win32Native.OpenEvent((int) rights, false, name);
+#else
+ SafeWaitHandle myHandle = Win32Native.OpenEvent(Win32Native.EVENT_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);
+#endif
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode)
+ return OpenExistingResult.NameNotFound;
+ if (Win32Native.ERROR_PATH_NOT_FOUND == errorCode)
+ return OpenExistingResult.PathNotFound;
+ if(null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ return OpenExistingResult.NameInvalid;
+ //this is for passed through Win32Native Errors
+ __Error.WinIOError(errorCode,"");
+ }
+ result = new EventWaitHandle(myHandle);
+ return OpenExistingResult.Success;
+#endif
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool Reset()
+ {
+ bool res = Win32Native.ResetEvent(safeWaitHandle);
+ if (!res)
+ __Error.WinIOError();
+ return res;
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public bool Set()
+ {
+ bool res = Win32Native.SetEvent(safeWaitHandle);
+
+ if (!res)
+ __Error.WinIOError();
+
+ return res;
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public EventWaitHandleSecurity GetAccessControl()
+ {
+ return new EventWaitHandleSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAccessControl(EventWaitHandleSecurity eventSecurity)
+ {
+ if (eventSecurity == null)
+ throw new ArgumentNullException("eventSecurity");
+ Contract.EndContractBlock();
+
+ eventSecurity.Persist(safeWaitHandle);
+ }
+#endif
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/ExecutionContext.cs b/src/mscorlib/src/System/Threading/ExecutionContext.cs
new file mode 100644
index 0000000000..0440368608
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ExecutionContext.cs
@@ -0,0 +1,1398 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+** Purpose: Capture execution context for a thread
+**
+**
+===========================================================*/
+namespace System.Threading
+{
+ using System;
+ using System.Security;
+ using System.Runtime.Remoting;
+#if FEATURE_IMPERSONATION
+ using System.Security.Principal;
+#endif
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Runtime.ExceptionServices;
+ using System.Runtime.Serialization;
+ using System.Security.Permissions;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Messaging;
+#endif // FEATURE_REMOTING
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void ContextCallback(Object state);
+
+#if FEATURE_CORECLR
+
+ [SecurityCritical]
+ internal struct ExecutionContextSwitcher
+ {
+ internal ExecutionContext m_ec;
+ internal SynchronizationContext m_sc;
+
+ internal void Undo(Thread currentThread)
+ {
+ Contract.Assert(currentThread == Thread.CurrentThread);
+
+ // The common case is that these have not changed, so avoid the cost of a write if not needed.
+ if (currentThread.SynchronizationContext != m_sc)
+ {
+ currentThread.SynchronizationContext = m_sc;
+ }
+
+ if (currentThread.ExecutionContext != m_ec)
+ {
+ ExecutionContext.Restore(currentThread, m_ec);
+ }
+ }
+ }
+
+ public sealed class ExecutionContext : IDisposable
+ {
+ private static readonly ExecutionContext Default = new ExecutionContext();
+
+ private readonly Dictionary<IAsyncLocal, object> m_localValues;
+ private readonly IAsyncLocal[] m_localChangeNotifications;
+
+ private ExecutionContext()
+ {
+ m_localValues = new Dictionary<IAsyncLocal, object>();
+ m_localChangeNotifications = Array.Empty<IAsyncLocal>();
+ }
+
+ private ExecutionContext(Dictionary<IAsyncLocal, object> localValues, IAsyncLocal[] localChangeNotifications)
+ {
+ m_localValues = localValues;
+ m_localChangeNotifications = localChangeNotifications;
+ }
+
+ [SecuritySafeCritical]
+ public static ExecutionContext Capture()
+ {
+ return Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default;
+ }
+
+ [SecurityCritical]
+ [HandleProcessCorruptedStateExceptions]
+ public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
+ {
+ if (executionContext == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher);
+ try
+ {
+ EstablishCopyOnWriteScope(currentThread, ref ecsw);
+ ExecutionContext.Restore(currentThread, executionContext);
+ callback(state);
+ }
+ catch
+ {
+ // Note: we have a "catch" rather than a "finally" because we want
+ // to stop the first pass of EH here. That way we can restore the previous
+ // context before any of our callers' EH filters run. That means we need to
+ // end the scope separately in the non-exceptional case below.
+ ecsw.Undo(currentThread);
+ throw;
+ }
+ ecsw.Undo(currentThread);
+ }
+
+ [SecurityCritical]
+ internal static void Restore(Thread currentThread, ExecutionContext executionContext)
+ {
+ Contract.Assert(currentThread == Thread.CurrentThread);
+
+ ExecutionContext previous = currentThread.ExecutionContext ?? Default;
+ currentThread.ExecutionContext = executionContext;
+
+ // New EC could be null if that's what ECS.Undo saved off.
+ // For the purposes of dealing with context change, treat this as the default EC
+ executionContext = executionContext ?? Default;
+
+ if (previous != executionContext)
+ {
+ OnContextChanged(previous, executionContext);
+ }
+ }
+
+ [SecurityCritical]
+ static internal void EstablishCopyOnWriteScope(Thread currentThread, ref ExecutionContextSwitcher ecsw)
+ {
+ Contract.Assert(currentThread == Thread.CurrentThread);
+
+ ecsw.m_ec = currentThread.ExecutionContext;
+ ecsw.m_sc = currentThread.SynchronizationContext;
+ }
+
+ [SecurityCritical]
+ [HandleProcessCorruptedStateExceptions]
+ private static void OnContextChanged(ExecutionContext previous, ExecutionContext current)
+ {
+ Contract.Assert(previous != null);
+ Contract.Assert(current != null);
+ Contract.Assert(previous != current);
+
+ foreach (IAsyncLocal local in previous.m_localChangeNotifications)
+ {
+ object previousValue;
+ object currentValue;
+ previous.m_localValues.TryGetValue(local, out previousValue);
+ current.m_localValues.TryGetValue(local, out currentValue);
+
+ if (previousValue != currentValue)
+ local.OnValueChanged(previousValue, currentValue, true);
+ }
+
+ if (current.m_localChangeNotifications != previous.m_localChangeNotifications)
+ {
+ try
+ {
+ foreach (IAsyncLocal local in current.m_localChangeNotifications)
+ {
+ // If the local has a value in the previous context, we already fired the event for that local
+ // in the code above.
+ object previousValue;
+ if (!previous.m_localValues.TryGetValue(local, out previousValue))
+ {
+ object currentValue;
+ current.m_localValues.TryGetValue(local, out currentValue);
+
+ if (previousValue != currentValue)
+ local.OnValueChanged(previousValue, currentValue, true);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Environment.FailFast(
+ Environment.GetResourceString("ExecutionContext_ExceptionInAsyncLocalNotification"),
+ ex);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static object GetLocalValue(IAsyncLocal local)
+ {
+ ExecutionContext current = Thread.CurrentThread.ExecutionContext;
+ if (current == null)
+ return null;
+
+ object value;
+ current.m_localValues.TryGetValue(local, out value);
+ return value;
+ }
+
+ [SecurityCritical]
+ internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
+ {
+ ExecutionContext current = Thread.CurrentThread.ExecutionContext ?? ExecutionContext.Default;
+
+ object previousValue;
+ bool hadPreviousValue = current.m_localValues.TryGetValue(local, out previousValue);
+
+ if (previousValue == newValue)
+ return;
+
+ //
+ // Allocate a new Dictionary containing a copy of the old values, plus the new value. We have to do this manually to
+ // minimize allocations of IEnumerators, etc.
+ //
+ Dictionary<IAsyncLocal, object> newValues = new Dictionary<IAsyncLocal, object>(current.m_localValues.Count + (hadPreviousValue ? 0 : 1));
+
+ foreach (KeyValuePair<IAsyncLocal, object> pair in current.m_localValues)
+ newValues.Add(pair.Key, pair.Value);
+
+ newValues[local] = newValue;
+
+ //
+ // Either copy the change notification array, or create a new one, depending on whether we need to add a new item.
+ //
+ IAsyncLocal[] newChangeNotifications = current.m_localChangeNotifications;
+ if (needChangeNotifications)
+ {
+ if (hadPreviousValue)
+ {
+ Contract.Assert(Array.IndexOf(newChangeNotifications, local) >= 0);
+ }
+ else
+ {
+ int newNotificationIndex = newChangeNotifications.Length;
+ Array.Resize(ref newChangeNotifications, newNotificationIndex + 1);
+ newChangeNotifications[newNotificationIndex] = local;
+ }
+ }
+
+ Thread.CurrentThread.ExecutionContext = new ExecutionContext(newValues, newChangeNotifications);
+
+ if (needChangeNotifications)
+ {
+ local.OnValueChanged(previousValue, newValue, false);
+ }
+ }
+
+ #region Wrappers for CLR compat, to avoid ifdefs all over the BCL
+
+ [Flags]
+ internal enum CaptureOptions
+ {
+ None = 0x00,
+ IgnoreSyncCtx = 0x01,
+ OptimizeDefaultCase = 0x02,
+ }
+
+ [SecurityCritical]
+ internal static ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions captureOptions)
+ {
+ return Capture();
+ }
+
+ [SecuritySafeCritical]
+ [FriendAccessAllowed]
+ internal static ExecutionContext FastCapture()
+ {
+ return Capture();
+ }
+
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx)
+ {
+ Run(executionContext, callback, state);
+ }
+
+ [SecurityCritical]
+ internal bool IsDefaultFTContext(bool ignoreSyncCtx)
+ {
+ return this == Default;
+ }
+
+ [SecuritySafeCritical]
+ public ExecutionContext CreateCopy()
+ {
+ return this; // since CoreCLR's ExecutionContext is immutable, we don't need to create copies.
+ }
+
+ public void Dispose()
+ {
+ // For CLR compat only
+ }
+
+ public static bool IsFlowSuppressed()
+ {
+ return false;
+ }
+
+ internal static ExecutionContext PreAllocatedDefault
+ {
+ [SecuritySafeCritical]
+ get { return ExecutionContext.Default; }
+ }
+
+ internal bool IsPreAllocatedDefault
+ {
+ get { return this == ExecutionContext.Default; }
+ }
+
+ #endregion
+ }
+
+#else // FEATURE_CORECLR
+
+ // Legacy desktop ExecutionContext implementation
+
+ internal struct ExecutionContextSwitcher
+ {
+ internal ExecutionContext.Reader outerEC; // previous EC we need to restore on Undo
+ internal bool outerECBelongsToScope;
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ internal SecurityContextSwitcher scsw;
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ internal Object hecsw;
+#if FEATURE_IMPERSONATION
+ internal WindowsIdentity wi;
+ internal bool cachedAlwaysFlowImpersonationPolicy;
+ internal bool wiIsValid;
+#endif
+ internal Thread thread;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal bool UndoNoThrow(Thread currentThread)
+ {
+ try
+ {
+ Undo(currentThread);
+ }
+ catch
+ {
+ return false;
+ }
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal void Undo(Thread currentThread)
+ {
+ //
+ // Don't use an uninitialized switcher, or one that's already been used.
+ //
+ if (thread == null)
+ return; // Don't do anything
+
+ Contract.Assert(Thread.CurrentThread == this.thread);
+
+ //
+ // Restore the HostExecutionContext before restoring the ExecutionContext.
+ //
+#if FEATURE_CAS_POLICY
+ if (hecsw != null)
+ HostExecutionContextSwitcher.Undo(hecsw);
+#endif // FEATURE_CAS_POLICY
+
+ //
+ // restore the saved Execution Context. Note that this will also restore the
+ // SynchronizationContext, Logical/IllogicalCallContext, etc.
+ //
+ ExecutionContext.Reader innerEC = currentThread.GetExecutionContextReader();
+ currentThread.SetExecutionContext(outerEC, outerECBelongsToScope);
+
+#if DEBUG
+ try
+ {
+ currentThread.ForbidExecutionContextMutation = true;
+#endif
+
+ //
+ // Tell the SecurityContext to do the side-effects of restoration.
+ //
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ if (scsw.currSC != null)
+ {
+ // Any critical failure inside scsw will cause FailFast
+ scsw.Undo();
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+
+#if FEATURE_IMPERSONATION
+ if (wiIsValid)
+ SecurityContext.RestoreCurrentWI(outerEC, innerEC, wi, cachedAlwaysFlowImpersonationPolicy);
+#endif
+
+ thread = null; // this will prevent the switcher object being used again
+#if DEBUG
+ }
+ finally
+ {
+ currentThread.ForbidExecutionContextMutation = false;
+ }
+#endif
+ ExecutionContext.OnAsyncLocalContextChanged(innerEC.DangerousGetRawExecutionContext(), outerEC.DangerousGetRawExecutionContext());
+ }
+ }
+
+
+ public struct AsyncFlowControl: IDisposable
+ {
+ private bool useEC;
+ private ExecutionContext _ec;
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ private SecurityContext _sc;
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ private Thread _thread;
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ [SecurityCritical]
+ internal void Setup(SecurityContextDisableFlow flags)
+ {
+ useEC = false;
+ Thread currentThread = Thread.CurrentThread;
+ _sc = currentThread.GetMutableExecutionContext().SecurityContext;
+ _sc._disableFlow = flags;
+ _thread = currentThread;
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ [SecurityCritical]
+ internal void Setup()
+ {
+ useEC = true;
+ Thread currentThread = Thread.CurrentThread;
+ _ec = currentThread.GetMutableExecutionContext();
+ _ec.isFlowSuppressed = true;
+ _thread = currentThread;
+ }
+
+ public void Dispose()
+ {
+ Undo();
+ }
+
+ [SecuritySafeCritical]
+ public void Undo()
+ {
+ if (_thread == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCMultiple"));
+ }
+ if (_thread != Thread.CurrentThread)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotUseAFCOtherThread"));
+ }
+ if (useEC)
+ {
+ if (Thread.CurrentThread.GetMutableExecutionContext() != _ec)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch"));
+ }
+ ExecutionContext.RestoreFlow();
+ }
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ else
+ {
+ if (!Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(_sc))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncFlowCtrlCtxMismatch"));
+ }
+ SecurityContext.RestoreFlow();
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ _thread = null;
+ }
+
+ public override int GetHashCode()
+ {
+ return _thread == null ? ToString().GetHashCode() : _thread.GetHashCode();
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is AsyncFlowControl)
+ return Equals((AsyncFlowControl)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(AsyncFlowControl obj)
+ {
+ return obj.useEC == useEC && obj._ec == _ec &&
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ obj._sc == _sc &&
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ obj._thread == _thread;
+ }
+
+ public static bool operator ==(AsyncFlowControl a, AsyncFlowControl b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(AsyncFlowControl a, AsyncFlowControl b)
+ {
+ return !(a == b);
+ }
+
+ }
+
+
+#if FEATURE_SERIALIZATION
+ [Serializable]
+#endif
+ public sealed class ExecutionContext : IDisposable, ISerializable
+ {
+ /*=========================================================================
+ ** Data accessed from managed code that needs to be defined in
+ ** ExecutionContextObject to maintain alignment between the two classes.
+ ** DON'T CHANGE THESE UNLESS YOU MODIFY ExecutionContextObject in vm\object.h
+ =========================================================================*/
+#if FEATURE_CAS_POLICY
+ private HostExecutionContext _hostExecutionContext;
+#endif // FEATURE_CAS_POLICY
+ private SynchronizationContext _syncContext;
+ private SynchronizationContext _syncContextNoFlow;
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ private SecurityContext _securityContext;
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+#if FEATURE_REMOTING
+ [System.Security.SecurityCritical] // auto-generated
+ private LogicalCallContext _logicalCallContext;
+ private IllogicalCallContext _illogicalCallContext; // this call context follows the physical thread
+#endif // #if FEATURE_REMOTING
+
+ enum Flags
+ {
+ None = 0x0,
+ IsNewCapture = 0x1,
+ IsFlowSuppressed = 0x2,
+ IsPreAllocatedDefault = 0x4
+ }
+ private Flags _flags;
+
+ private Dictionary<IAsyncLocal, object> _localValues;
+ private List<IAsyncLocal> _localChangeNotifications;
+
+ internal bool isNewCapture
+ {
+ get
+ {
+ return (_flags & (Flags.IsNewCapture | Flags.IsPreAllocatedDefault)) != Flags.None;
+ }
+ set
+ {
+ Contract.Assert(!IsPreAllocatedDefault);
+ if (value)
+ _flags |= Flags.IsNewCapture;
+ else
+ _flags &= ~Flags.IsNewCapture;
+ }
+ }
+ internal bool isFlowSuppressed
+ {
+ get
+ {
+ return (_flags & Flags.IsFlowSuppressed) != Flags.None;
+ }
+ set
+ {
+ Contract.Assert(!IsPreAllocatedDefault);
+ if (value)
+ _flags |= Flags.IsFlowSuppressed;
+ else
+ _flags &= ~Flags.IsFlowSuppressed;
+ }
+ }
+
+
+ private static readonly ExecutionContext s_dummyDefaultEC = new ExecutionContext(isPreAllocatedDefault: true);
+
+ static internal ExecutionContext PreAllocatedDefault
+ {
+ [SecuritySafeCritical]
+ get { return s_dummyDefaultEC; }
+ }
+
+ internal bool IsPreAllocatedDefault
+ {
+ get
+ {
+ // we use _flags instead of a direct comparison w/ s_dummyDefaultEC to avoid the static access on
+ // hot code paths.
+ if ((_flags & Flags.IsPreAllocatedDefault) != Flags.None)
+ {
+ Contract.Assert(this == s_dummyDefaultEC);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal ExecutionContext()
+ {
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal ExecutionContext(bool isPreAllocatedDefault)
+ {
+ if (isPreAllocatedDefault)
+ _flags = Flags.IsPreAllocatedDefault;
+ }
+
+ // Read-only wrapper around ExecutionContext. This enables safe reading of an ExecutionContext without accidentally modifying it.
+ internal struct Reader
+ {
+ ExecutionContext m_ec;
+
+ public Reader(ExecutionContext ec) { m_ec = ec; }
+
+ public ExecutionContext DangerousGetRawExecutionContext() { return m_ec; }
+
+ public bool IsNull { get { return m_ec == null; } }
+ [SecurityCritical]
+ public bool IsDefaultFTContext(bool ignoreSyncCtx) { return m_ec.IsDefaultFTContext(ignoreSyncCtx); }
+ public bool IsFlowSuppressed
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get { return IsNull ? false : m_ec.isFlowSuppressed; }
+ }
+ //public Thread Thread { get { return m_ec._thread; } }
+ public bool IsSame(ExecutionContext.Reader other) { return m_ec == other.m_ec; }
+
+ public SynchronizationContext SynchronizationContext { get { return IsNull ? null : m_ec.SynchronizationContext; } }
+ public SynchronizationContext SynchronizationContextNoFlow { get { return IsNull ? null : m_ec.SynchronizationContextNoFlow; } }
+
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ public SecurityContext.Reader SecurityContext
+ {
+ [SecurityCritical]
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get { return new SecurityContext.Reader(IsNull ? null : m_ec.SecurityContext); }
+ }
+#endif
+
+#if FEATURE_REMOTING
+ public LogicalCallContext.Reader LogicalCallContext
+ {
+ [SecurityCritical]
+ get { return new LogicalCallContext.Reader(IsNull ? null : m_ec.LogicalCallContext); }
+ }
+
+ public IllogicalCallContext.Reader IllogicalCallContext
+ {
+ [SecurityCritical]
+ get { return new IllogicalCallContext.Reader(IsNull ? null : m_ec.IllogicalCallContext); }
+ }
+#endif
+
+ [SecurityCritical]
+ public object GetLocalValue(IAsyncLocal local)
+ {
+ if (IsNull)
+ return null;
+
+ if (m_ec._localValues == null)
+ return null;
+
+ object value;
+ m_ec._localValues.TryGetValue(local, out value);
+ return value;
+ }
+
+ [SecurityCritical]
+ public bool HasSameLocalValues(ExecutionContext other)
+ {
+ var thisLocalValues = IsNull ? null : m_ec._localValues;
+ var otherLocalValues = other == null ? null : other._localValues;
+ return thisLocalValues == otherLocalValues;
+ }
+
+ [SecurityCritical]
+ public bool HasLocalValues()
+ {
+ return !this.IsNull && m_ec._localValues != null;
+ }
+ }
+
+ [SecurityCritical]
+ internal static object GetLocalValue(IAsyncLocal local)
+ {
+ return Thread.CurrentThread.GetExecutionContextReader().GetLocalValue(local);
+ }
+
+ [SecurityCritical]
+ internal static void SetLocalValue(IAsyncLocal local, object newValue, bool needChangeNotifications)
+ {
+ ExecutionContext current = Thread.CurrentThread.GetMutableExecutionContext();
+
+ object previousValue = null;
+ bool hadPreviousValue = current._localValues != null && current._localValues.TryGetValue(local, out previousValue);
+
+ if (previousValue == newValue)
+ return;
+
+ if (current._localValues == null)
+ current._localValues = new Dictionary<IAsyncLocal, object>();
+ else
+ current._localValues = new Dictionary<IAsyncLocal, object>(current._localValues);
+
+ current._localValues[local] = newValue;
+
+ if (needChangeNotifications)
+ {
+ if (hadPreviousValue)
+ {
+ Contract.Assert(current._localChangeNotifications != null);
+ Contract.Assert(current._localChangeNotifications.Contains(local));
+ }
+ else
+ {
+ if (current._localChangeNotifications == null)
+ current._localChangeNotifications = new List<IAsyncLocal>();
+ else
+ current._localChangeNotifications = new List<IAsyncLocal>(current._localChangeNotifications);
+
+ current._localChangeNotifications.Add(local);
+ }
+
+ local.OnValueChanged(previousValue, newValue, false);
+ }
+ }
+
+ [SecurityCritical]
+ [HandleProcessCorruptedStateExceptions]
+ internal static void OnAsyncLocalContextChanged(ExecutionContext previous, ExecutionContext current)
+ {
+ List<IAsyncLocal> previousLocalChangeNotifications = (previous == null) ? null : previous._localChangeNotifications;
+ if (previousLocalChangeNotifications != null)
+ {
+ foreach (IAsyncLocal local in previousLocalChangeNotifications)
+ {
+ object previousValue = null;
+ if (previous != null && previous._localValues != null)
+ previous._localValues.TryGetValue(local, out previousValue);
+
+ object currentValue = null;
+ if (current != null && current._localValues != null)
+ current._localValues.TryGetValue(local, out currentValue);
+
+ if (previousValue != currentValue)
+ local.OnValueChanged(previousValue, currentValue, true);
+ }
+ }
+
+ List<IAsyncLocal> currentLocalChangeNotifications = (current == null) ? null : current._localChangeNotifications;
+ if (currentLocalChangeNotifications != null && currentLocalChangeNotifications != previousLocalChangeNotifications)
+ {
+ try
+ {
+ foreach (IAsyncLocal local in currentLocalChangeNotifications)
+ {
+ // If the local has a value in the previous context, we already fired the event for that local
+ // in the code above.
+ object previousValue = null;
+ if (previous == null ||
+ previous._localValues == null ||
+ !previous._localValues.TryGetValue(local, out previousValue))
+ {
+ object currentValue = null;
+ if (current != null && current._localValues != null)
+ current._localValues.TryGetValue(local, out currentValue);
+
+ if (previousValue != currentValue)
+ local.OnValueChanged(previousValue, currentValue, true);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Environment.FailFast(
+ Environment.GetResourceString("ExecutionContext_ExceptionInAsyncLocalNotification"),
+ ex);
+ }
+ }
+ }
+
+
+#if FEATURE_REMOTING
+ internal LogicalCallContext LogicalCallContext
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ get
+ {
+ if (_logicalCallContext == null)
+ {
+ _logicalCallContext = new LogicalCallContext();
+ }
+ return _logicalCallContext;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ _logicalCallContext = value;
+ }
+ }
+
+ internal IllogicalCallContext IllogicalCallContext
+ {
+ get
+ {
+ if (_illogicalCallContext == null)
+ {
+ _illogicalCallContext = new IllogicalCallContext();
+ }
+ return _illogicalCallContext;
+ }
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ _illogicalCallContext = value;
+ }
+ }
+#endif // #if FEATURE_REMOTING
+
+ internal SynchronizationContext SynchronizationContext
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return _syncContext;
+ }
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ _syncContext = value;
+ }
+ }
+
+ internal SynchronizationContext SynchronizationContextNoFlow
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return _syncContextNoFlow;
+ }
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ _syncContextNoFlow = value;
+ }
+ }
+
+#if FEATURE_CAS_POLICY
+ internal HostExecutionContext HostExecutionContext
+ {
+ get
+ {
+ return _hostExecutionContext;
+ }
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ _hostExecutionContext = value;
+ }
+ }
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ internal SecurityContext SecurityContext
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ return _securityContext;
+ }
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ Contract.Assert(this != s_dummyDefaultEC);
+ // store the new security context
+ _securityContext = value;
+ // perform the reverse link too
+ if (value != null)
+ _securityContext.ExecutionContext = this;
+ }
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+
+
+ public void Dispose()
+ {
+ if(this.IsPreAllocatedDefault)
+ return; //Do nothing if this is the default context
+#if FEATURE_CAS_POLICY
+ if (_hostExecutionContext != null)
+ _hostExecutionContext.Dispose();
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ if (_securityContext != null)
+ _securityContext.Dispose();
+#endif //FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ }
+
+ [DynamicSecurityMethod]
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void Run(ExecutionContext executionContext, ContextCallback callback, Object state)
+ {
+ if (executionContext == null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
+ if (!executionContext.isNewCapture)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
+
+ Run(executionContext, callback, state, false);
+ }
+
+ // This method is special from a security perspective - the VM will not allow a stack walk to
+ // continue past the call to ExecutionContext.Run. If you change the signature to this method, make
+ // sure to update SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new signature.
+ [DynamicSecurityMethod]
+ [SecurityCritical]
+ [FriendAccessAllowed]
+ internal static void Run(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx)
+ {
+ RunInternal(executionContext, callback, state, preserveSyncCtx);
+ }
+
+ // Actual implementation of Run is here, in a non-DynamicSecurityMethod, because the JIT seems to refuse to inline callees into
+ // a DynamicSecurityMethod.
+ [SecurityCritical]
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ [HandleProcessCorruptedStateExceptions]
+ internal static void RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, bool preserveSyncCtx)
+ {
+ Contract.Assert(executionContext != null);
+ if (executionContext.IsPreAllocatedDefault)
+ {
+ Contract.Assert(executionContext.IsDefaultFTContext(preserveSyncCtx));
+ }
+ else
+ {
+ Contract.Assert(executionContext.isNewCapture);
+ executionContext.isNewCapture = false;
+ }
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContextSwitcher ecsw = default(ExecutionContextSwitcher);
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ ExecutionContext.Reader ec = currentThread.GetExecutionContextReader();
+ if ( (ec.IsNull || ec.IsDefaultFTContext(preserveSyncCtx)) &&
+ #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ SecurityContext.CurrentlyInDefaultFTSecurityContext(ec) &&
+ #endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ executionContext.IsDefaultFTContext(preserveSyncCtx) &&
+ ec.HasSameLocalValues(executionContext)
+ )
+ {
+ // Neither context is interesting, so we don't need to set the context.
+ // We do need to reset any changes made by the user's callback,
+ // so here we establish a "copy-on-write scope". Any changes will
+ // result in a copy of the context being made, preserving the original
+ // context.
+ EstablishCopyOnWriteScope(currentThread, true, ref ecsw);
+ }
+ else
+ {
+ if (executionContext.IsPreAllocatedDefault)
+ executionContext = new ExecutionContext();
+ ecsw = SetExecutionContext(executionContext, preserveSyncCtx);
+ }
+
+ //
+ // Call the user's callback
+ //
+ callback(state);
+ }
+ finally
+ {
+ ecsw.Undo(currentThread);
+ }
+ }
+
+ [SecurityCritical]
+ static internal void EstablishCopyOnWriteScope(Thread currentThread, ref ExecutionContextSwitcher ecsw)
+ {
+ EstablishCopyOnWriteScope(currentThread, false, ref ecsw);
+ }
+
+ [SecurityCritical]
+ static private void EstablishCopyOnWriteScope(Thread currentThread, bool knownNullWindowsIdentity, ref ExecutionContextSwitcher ecsw)
+ {
+ Contract.Assert(currentThread == Thread.CurrentThread);
+
+ ecsw.outerEC = currentThread.GetExecutionContextReader();
+ ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope;
+
+#if FEATURE_IMPERSONATION
+ ecsw.cachedAlwaysFlowImpersonationPolicy = SecurityContext.AlwaysFlowImpersonationPolicy;
+ if (knownNullWindowsIdentity)
+ Contract.Assert(SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy) == null);
+ else
+ ecsw.wi = SecurityContext.GetCurrentWI(ecsw.outerEC, ecsw.cachedAlwaysFlowImpersonationPolicy);
+ ecsw.wiIsValid = true;
+#endif
+ currentThread.ExecutionContextBelongsToCurrentScope = false;
+ ecsw.thread = currentThread;
+ }
+
+
+ // Sets the given execution context object on the thread.
+ // Returns the previous one.
+ [System.Security.SecurityCritical] // auto-generated
+ [DynamicSecurityMethodAttribute()]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ [HandleProcessCorruptedStateExceptions]
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ internal static ExecutionContextSwitcher SetExecutionContext(ExecutionContext executionContext, bool preserveSyncCtx)
+ {
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+
+ Contract.Assert(executionContext != null);
+ Contract.Assert(executionContext != s_dummyDefaultEC);
+
+ // Set up the switcher object to return;
+ ExecutionContextSwitcher ecsw = new ExecutionContextSwitcher();
+
+ Thread currentThread = Thread.CurrentThread;
+ ExecutionContext.Reader outerEC = currentThread.GetExecutionContextReader();
+
+ ecsw.thread = currentThread;
+ ecsw.outerEC = outerEC;
+ ecsw.outerECBelongsToScope = currentThread.ExecutionContextBelongsToCurrentScope;
+
+ if (preserveSyncCtx)
+ executionContext.SynchronizationContext = outerEC.SynchronizationContext;
+ executionContext.SynchronizationContextNoFlow = outerEC.SynchronizationContextNoFlow;
+
+ currentThread.SetExecutionContext(executionContext, belongsToCurrentScope: true);
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ OnAsyncLocalContextChanged(outerEC.DangerousGetRawExecutionContext(), executionContext);
+
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ //set the security context
+ SecurityContext sc = executionContext.SecurityContext;
+ if (sc != null)
+ {
+ // non-null SC: needs to be set
+ SecurityContext.Reader prevSeC = outerEC.SecurityContext;
+ ecsw.scsw = SecurityContext.SetSecurityContext(sc, prevSeC, false, ref stackMark);
+ }
+ else if (!SecurityContext.CurrentlyInDefaultFTSecurityContext(ecsw.outerEC))
+ {
+ // null incoming SC, but we're currently not in FT: use static FTSC to set
+ SecurityContext.Reader prevSeC = outerEC.SecurityContext;
+ ecsw.scsw = SecurityContext.SetSecurityContext(SecurityContext.FullTrustSecurityContext, prevSeC, false, ref stackMark);
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+#if FEATURE_CAS_POLICY
+ // set the Host Context
+ HostExecutionContext hostContext = executionContext.HostExecutionContext;
+ if (hostContext != null)
+ {
+ ecsw.hecsw = HostExecutionContextManager.SetHostExecutionContextInternal(hostContext);
+ }
+#endif // FEATURE_CAS_POLICY
+ }
+ catch
+ {
+ ecsw.UndoNoThrow(currentThread);
+ throw;
+ }
+ return ecsw;
+ }
+
+ //
+ // Public CreateCopy. Used to copy captured ExecutionContexts so they can be reused multiple times.
+ // This should only copy the portion of the context that we actually capture.
+ //
+ [SecuritySafeCritical]
+ public ExecutionContext CreateCopy()
+ {
+ if (!isNewCapture)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotCopyUsedContext"));
+ }
+ ExecutionContext ec = new ExecutionContext();
+ ec.isNewCapture = true;
+ ec._syncContext = _syncContext == null ? null : _syncContext.CreateCopy();
+ ec._localValues = _localValues;
+ ec._localChangeNotifications = _localChangeNotifications;
+#if FEATURE_CAS_POLICY
+ // capture the host execution context
+ ec._hostExecutionContext = _hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy();
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ if (_securityContext != null)
+ {
+ ec._securityContext = _securityContext.CreateCopy();
+ ec._securityContext.ExecutionContext = ec;
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+
+#if FEATURE_REMOTING
+ if (this._logicalCallContext != null)
+ ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone();
+
+ Contract.Assert(this._illogicalCallContext == null);
+#endif // #if FEATURE_REMOTING
+
+ return ec;
+ }
+
+ //
+ // Creates a complete copy, used for copy-on-write.
+ //
+ [SecuritySafeCritical]
+ internal ExecutionContext CreateMutableCopy()
+ {
+ Contract.Assert(!this.isNewCapture);
+
+ ExecutionContext ec = new ExecutionContext();
+
+ // We don't deep-copy the SyncCtx, since we're still in the same context after copy-on-write.
+ ec._syncContext = this._syncContext;
+ ec._syncContextNoFlow = this._syncContextNoFlow;
+
+#if FEATURE_CAS_POLICY
+ // capture the host execution context
+ ec._hostExecutionContext = this._hostExecutionContext == null ? null : _hostExecutionContext.CreateCopy();
+#endif // FEATURE_CAS_POLICY
+
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ if (_securityContext != null)
+ {
+ ec._securityContext = this._securityContext.CreateMutableCopy();
+ ec._securityContext.ExecutionContext = ec;
+ }
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+
+#if FEATURE_REMOTING
+ if (this._logicalCallContext != null)
+ ec.LogicalCallContext = (LogicalCallContext)this.LogicalCallContext.Clone();
+
+ if (this._illogicalCallContext != null)
+ ec.IllogicalCallContext = (IllogicalCallContext)this.IllogicalCallContext.CreateCopy();
+#endif // #if FEATURE_REMOTING
+
+ ec._localValues = this._localValues;
+ ec._localChangeNotifications = this._localChangeNotifications;
+ ec.isFlowSuppressed = this.isFlowSuppressed;
+
+ return ec;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static AsyncFlowControl SuppressFlow()
+ {
+ if (IsFlowSuppressed())
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
+ }
+ Contract.EndContractBlock();
+ AsyncFlowControl afc = new AsyncFlowControl();
+ afc.Setup();
+ return afc;
+ }
+
+ [SecuritySafeCritical]
+ public static void RestoreFlow()
+ {
+ ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext();
+ if (!ec.isFlowSuppressed)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow"));
+ }
+ ec.isFlowSuppressed = false;
+ }
+
+ [Pure]
+ public static bool IsFlowSuppressed()
+ {
+ return Thread.CurrentThread.GetExecutionContextReader().IsFlowSuppressed;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static ExecutionContext Capture()
+ {
+ // set up a stack mark for finding the caller
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ExecutionContext.Capture(ref stackMark, CaptureOptions.None);
+ }
+
+ //
+ // Captures an ExecutionContext with optimization for the "default" case, and captures a "null" synchronization context.
+ // When calling ExecutionContext.Run on the returned context, specify ignoreSyncCtx = true
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ [FriendAccessAllowed]
+ internal static ExecutionContext FastCapture()
+ {
+ // set up a stack mark for finding the caller
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ExecutionContext.Capture(ref stackMark, CaptureOptions.IgnoreSyncCtx | CaptureOptions.OptimizeDefaultCase);
+ }
+
+
+ [Flags]
+ internal enum CaptureOptions
+ {
+ None = 0x00,
+
+ IgnoreSyncCtx = 0x01, //Don't flow SynchronizationContext
+
+ OptimizeDefaultCase = 0x02, //Faster in the typical case, but can't show the result to users
+ // because they could modify the shared default EC.
+ // Use this only if you won't be exposing the captured EC to users.
+ }
+
+ // internal helper to capture the current execution context using a passed in stack mark
+ [System.Security.SecurityCritical] // auto-generated
+ static internal ExecutionContext Capture(ref StackCrawlMark stackMark, CaptureOptions options)
+ {
+ ExecutionContext.Reader ecCurrent = Thread.CurrentThread.GetExecutionContextReader();
+
+ // check to see if Flow is suppressed
+ if (ecCurrent.IsFlowSuppressed)
+ return null;
+
+ //
+ // Attempt to capture context. There may be nothing to capture...
+ //
+
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ // capture the security context
+ SecurityContext secCtxNew = SecurityContext.Capture(ecCurrent, ref stackMark);
+#endif // #if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+#if FEATURE_CAS_POLICY
+ // capture the host execution context
+ HostExecutionContext hostCtxNew = HostExecutionContextManager.CaptureHostExecutionContext();
+#endif // FEATURE_CAS_POLICY
+
+ SynchronizationContext syncCtxNew = null;
+
+#if FEATURE_REMOTING
+ LogicalCallContext logCtxNew = null;
+#endif
+
+ if (!ecCurrent.IsNull)
+ {
+ // capture the sync context
+ if (0 == (options & CaptureOptions.IgnoreSyncCtx))
+ syncCtxNew = (ecCurrent.SynchronizationContext == null) ? null : ecCurrent.SynchronizationContext.CreateCopy();
+
+#if FEATURE_REMOTING
+ // copy over the Logical Call Context
+ if (ecCurrent.LogicalCallContext.HasInfo)
+ logCtxNew = ecCurrent.LogicalCallContext.Clone();
+#endif // #if FEATURE_REMOTING
+ }
+
+ Dictionary<IAsyncLocal, object> localValues = null;
+ List<IAsyncLocal> localChangeNotifications = null;
+ if (!ecCurrent.IsNull)
+ {
+ localValues = ecCurrent.DangerousGetRawExecutionContext()._localValues;
+ localChangeNotifications = ecCurrent.DangerousGetRawExecutionContext()._localChangeNotifications;
+ }
+
+ //
+ // If we didn't get anything but defaults, and we're allowed to return the
+ // dummy default EC, don't bother allocating a new context.
+ //
+ if (0 != (options & CaptureOptions.OptimizeDefaultCase) &&
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ secCtxNew == null &&
+#endif
+#if FEATURE_CAS_POLICY
+ hostCtxNew == null &&
+#endif // FEATURE_CAS_POLICY
+ syncCtxNew == null &&
+#if FEATURE_REMOTING
+ (logCtxNew == null || !logCtxNew.HasInfo) &&
+#endif // #if FEATURE_REMOTING
+ localValues == null &&
+ localChangeNotifications == null
+ )
+ {
+ return s_dummyDefaultEC;
+ }
+
+ //
+ // Allocate the new context, and fill it in.
+ //
+ ExecutionContext ecNew = new ExecutionContext();
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ ecNew.SecurityContext = secCtxNew;
+ if (ecNew.SecurityContext != null)
+ ecNew.SecurityContext.ExecutionContext = ecNew;
+#endif
+#if FEATURE_CAS_POLICY
+ ecNew._hostExecutionContext = hostCtxNew;
+#endif // FEATURE_CAS_POLICY
+ ecNew._syncContext = syncCtxNew;
+#if FEATURE_REMOTING
+ ecNew.LogicalCallContext = logCtxNew;
+#endif // #if FEATURE_REMOTING
+ ecNew._localValues = localValues;
+ ecNew._localChangeNotifications = localChangeNotifications;
+ ecNew.isNewCapture = true;
+
+ return ecNew;
+ }
+
+ //
+ // Implementation of ISerializable
+ //
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+#if FEATURE_REMOTING
+ if (_logicalCallContext != null)
+ {
+ info.AddValue("LogicalCallContext", _logicalCallContext, typeof(LogicalCallContext));
+ }
+#endif // #if FEATURE_REMOTING
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private ExecutionContext(SerializationInfo info, StreamingContext context)
+ {
+ SerializationInfoEnumerator e = info.GetEnumerator();
+ while (e.MoveNext())
+ {
+#if FEATURE_REMOTING
+ if (e.Name.Equals("LogicalCallContext"))
+ {
+ _logicalCallContext = (LogicalCallContext) e.Value;
+ }
+#endif // #if FEATURE_REMOTING
+ }
+ } // ObjRef .ctor
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool IsDefaultFTContext(bool ignoreSyncCtx)
+ {
+#if FEATURE_CAS_POLICY
+ if (_hostExecutionContext != null)
+ return false;
+#endif // FEATURE_CAS_POLICY
+ if (!ignoreSyncCtx && _syncContext != null)
+ return false;
+#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+ if (_securityContext != null && !_securityContext.IsDefaultFTSecurityContext())
+ return false;
+#endif //#if FEATURE_IMPERSONATION || FEATURE_COMPRESSEDSTACK
+#if FEATURE_REMOTING
+ if (_logicalCallContext != null && _logicalCallContext.HasInfo)
+ return false;
+ if (_illogicalCallContext != null && _illogicalCallContext.HasUserData)
+ return false;
+#endif //#if FEATURE_REMOTING
+ return true;
+ }
+ } // class ExecutionContext
+
+#endif //FEATURE_CORECLR
+}
+
+
diff --git a/src/mscorlib/src/System/Threading/IObjectHandle.cs b/src/mscorlib/src/System/Threading/IObjectHandle.cs
new file mode 100644
index 0000000000..464f06e52d
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/IObjectHandle.cs
@@ -0,0 +1,31 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** IObjectHandle defines the interface for unwrapping objects.
+** Objects that are marshal by value object can be returned through
+** an indirection allowing the caller to control when the
+** object is loaded into their domain. The caller can unwrap
+** the object from the indirection through this interface.
+**
+**
+===========================================================*/
+namespace System.Runtime.Remoting {
+
+ using System;
+ using System.Runtime.InteropServices;
+
+ [ InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown),
+ GuidAttribute("C460E2B4-E199-412a-8456-84DC3E4838C3") ]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public interface IObjectHandle {
+ // Unwrap the object. Implementers of this interface
+ // typically have an indirect referece to another object.
+ Object Unwrap();
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/Interlocked.cs b/src/mscorlib/src/System/Threading/Interlocked.cs
new file mode 100644
index 0000000000..50cc766d61
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Interlocked.cs
@@ -0,0 +1,233 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+namespace System.Threading
+{
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Runtime;
+
+ // After much discussion, we decided the Interlocked class doesn't need
+ // any HPA's for synchronization or external threading. They hurt C#'s
+ // codegen for the yield keyword, and arguably they didn't protect much.
+ // Instead, they penalized people (and compilers) for writing threadsafe
+ // code.
+ public static class Interlocked
+ {
+ /******************************
+ * Increment
+ * Implemented: int
+ * long
+ *****************************/
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int Increment(ref int location)
+ {
+ return Add(ref location, 1);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static long Increment(ref long location)
+ {
+ return Add(ref location, 1);
+ }
+
+ /******************************
+ * Decrement
+ * Implemented: int
+ * long
+ *****************************/
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int Decrement(ref int location)
+ {
+ return Add(ref location, -1);
+ }
+
+ public static long Decrement(ref long location)
+ {
+ return Add(ref location, -1);
+ }
+
+ /******************************
+ * Exchange
+ * Implemented: int
+ * long
+ * float
+ * double
+ * Object
+ * IntPtr
+ *****************************/
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern int Exchange(ref int location1, int value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern long Exchange(ref long location1, long value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern float Exchange(ref float location1, float value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern double Exchange(ref double location1, double value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern Object Exchange(ref Object location1, Object value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern IntPtr Exchange(ref IntPtr location1, IntPtr value);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [System.Security.SecuritySafeCritical]
+ public static T Exchange<T>(ref T location1, T value) where T : class
+ {
+ _Exchange(__makeref(location1), __makeref(value));
+ //Since value is a local we use trash its data on return
+ // The Exchange replaces the data with new data
+ // so after the return "value" contains the original location1
+ //See ExchangeGeneric for more details
+ return value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ private static extern void _Exchange(TypedReference location1, TypedReference value);
+
+ /******************************
+ * CompareExchange
+ * Implemented: int
+ * long
+ * float
+ * double
+ * Object
+ * IntPtr
+ *****************************/
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern int CompareExchange(ref int location1, int value, int comparand);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern long CompareExchange(ref long location1, long value, long comparand);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern float CompareExchange(ref float location1, float value, float comparand);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical]
+ public static extern double CompareExchange(ref double location1, double value, double comparand);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern Object CompareExchange(ref Object location1, Object value, Object comparand);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ public static extern IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand);
+
+ /*****************************************************************
+ * CompareExchange<T>
+ *
+ * Notice how CompareExchange<T>() uses the __makeref keyword
+ * to create two TypedReferences before calling _CompareExchange().
+ * This is horribly slow. Ideally we would like CompareExchange<T>()
+ * to simply call CompareExchange(ref Object, Object, Object);
+ * however, this would require casting a "ref T" into a "ref Object",
+ * which is not legal in C#.
+ *
+ * Thus we opted to implement this in the JIT so that when it reads
+ * the method body for CompareExchange<T>() it gets back the
+ * following IL:
+ *
+ * ldarg.0
+ * ldarg.1
+ * ldarg.2
+ * call System.Threading.Interlocked::CompareExchange(ref Object, Object, Object)
+ * ret
+ *
+ * See getILIntrinsicImplementationForInterlocked() in VM\JitInterface.cpp
+ * for details.
+ *****************************************************************/
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.InteropServices.ComVisible(false)]
+ [System.Security.SecuritySafeCritical]
+ public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class
+ {
+ // _CompareExchange() passes back the value read from location1 via local named 'value'
+ _CompareExchange(__makeref(location1), __makeref(value), comparand);
+ return value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ private static extern void _CompareExchange(TypedReference location1, TypedReference value, Object comparand);
+
+ // BCL-internal overload that returns success via a ref bool param, useful for reliable spin locks.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Security.SecuritySafeCritical]
+ internal static extern int CompareExchange(ref int location1, int value, int comparand, ref bool succeeded);
+
+ /******************************
+ * Add
+ * Implemented: int
+ * long
+ *****************************/
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal static extern int ExchangeAdd(ref int location1, int value);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern long ExchangeAdd(ref long location1, long value);
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static int Add(ref int location1, int value)
+ {
+ return ExchangeAdd(ref location1, value) + value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static long Add(ref long location1, long value)
+ {
+ return ExchangeAdd(ref location1, value) + value;
+ }
+
+ /******************************
+ * Read
+ *****************************/
+ public static long Read(ref long location)
+ {
+ return Interlocked.CompareExchange(ref location,0,0);
+ }
+
+
+ public static void MemoryBarrier()
+ {
+ Thread.MemoryBarrier();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/LazyInitializer.cs b/src/mscorlib/src/System/Threading/LazyInitializer.cs
new file mode 100644
index 0000000000..c8e74e30e3
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/LazyInitializer.cs
@@ -0,0 +1,265 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// a set of lightweight static helpers for lazy initialization.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+namespace System.Threading
+{
+
+ /// <summary>
+ /// Specifies how a <see cref="T:System.Threading.Lazy{T}"/> instance should synchronize access among multiple threads.
+ /// </summary>
+ public enum LazyThreadSafetyMode
+ {
+ /// <summary>
+ /// This mode makes no guarantees around the thread-safety of the <see cref="T:System.Threading.Lazy{T}"/> instance. If used from multiple threads, the behavior of the <see cref="T:System.Threading.Lazy{T}"/> is undefined.
+ /// This mode should be used when a <see cref="T:System.Threading.Lazy{T}"/> is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial.
+ /// If valueFactory throws an exception when the <see cref="T:System.Threading.Lazy{T}"/> is initialized, the exception will be cached and returned on subsequent accesses to Value. Also, if valueFactory recursively
+ /// accesses Value on this <see cref="T:System.Threading.Lazy{T}"/> instance, a <see cref="T:System.InvalidOperationException"/> will be thrown.
+ /// </summary>
+ None,
+
+ /// <summary>
+ /// When multiple threads attempt to simultaneously initialize a <see cref="T:System.Threading.Lazy{T}"/> instance, this mode allows each thread to execute the
+ /// valueFactory but only the first thread to complete initialization will be allowed to set the final value of the <see cref="T:System.Threading.Lazy{T}"/>.
+ /// Once initialized successfully, any future calls to Value will return the cached result. If valueFactory throws an exception on any thread, that exception will be
+ /// propagated out of Value. If any thread executes valueFactory without throwing an exception and, therefore, successfully sets the value, that value will be returned on
+ /// subsequent accesses to Value from any thread. If no thread succeeds in setting the value, IsValueCreated will remain false and subsequent accesses to Value will result in
+ /// the valueFactory delegate re-executing. Also, if valueFactory recursively accesses Value on this <see cref="T:System.Threading.Lazy{T}"/> instance, an exception will NOT be thrown.
+ /// </summary>
+ PublicationOnly,
+
+ /// <summary>
+ /// This mode uses locks to ensure that only a single thread can initialize a <see cref="T:System.Threading.Lazy{T}"/> instance in a thread-safe manner. In general,
+ /// taken if this mode is used in conjunction with a <see cref="T:System.Threading.Lazy{T}"/> valueFactory delegate that uses locks internally, a deadlock can occur if not
+ /// handled carefully. If valueFactory throws an exception when the<see cref="T:System.Threading.Lazy{T}"/> is initialized, the exception will be cached and returned on
+ /// subsequent accesses to Value. Also, if valueFactory recursively accesses Value on this <see cref="T:System.Threading.Lazy{T}"/> instance, a <see cref="T:System.InvalidOperationException"/> will be thrown.
+ /// </summary>
+ ExecutionAndPublication
+ }
+ /// <summary>
+ /// Provides lazy initialization routines.
+ /// </summary>
+ /// <remarks>
+ /// These routines avoid needing to allocate a dedicated, lazy-initialization instance, instead using
+ /// references to ensure targets have been initialized as they are accessed.
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public static class LazyInitializer
+ {
+ /// <summary>
+ /// Initializes a target reference type with the type's default constructor if the target has not
+ /// already been initialized.
+ /// </summary>
+ /// <typeparam name="T">The refence type of the reference to be initialized.</typeparam>
+ /// <param name="target">A reference of type <typeparamref name="T"/> to initialize if it has not
+ /// already been initialized.</param>
+ /// <returns>The initialized reference of type <typeparamref name="T"/>.</returns>
+ /// <exception cref="T:System.MissingMemberException">Type <typeparamref name="T"/> does not have a default
+ /// constructor.</exception>
+ /// <exception cref="T:System.MemberAccessException">
+ /// Permissions to access the constructor of type <typeparamref name="T"/> were missing.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// This method may only be used on reference types. To ensure initialization of value
+ /// types, see other overloads of EnsureInitialized.
+ /// </para>
+ /// <para>
+ /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
+ /// In the event that multiple threads access this method concurrently, multiple instances of <typeparamref name="T"/>
+ /// may be created, but only one will be stored into <paramref name="target"/>. In such an occurrence, this method will not dispose of the
+ /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
+ /// if an object was not used and to then dispose of the object appropriately.
+ /// </para>
+ /// </remarks>
+ public static T EnsureInitialized<T>(ref T target) where T : class
+ {
+ // Fast path.
+ if (Volatile.Read<T>(ref target) != null)
+ {
+ return target;
+ }
+
+ return EnsureInitializedCore<T>(ref target, LazyHelpers<T>.s_activatorFactorySelector);
+ }
+
+ /// <summary>
+ /// Initializes a target reference type using the specified function if it has not already been
+ /// initialized.
+ /// </summary>
+ /// <typeparam name="T">The reference type of the reference to be initialized.</typeparam>
+ /// <param name="target">The reference of type <typeparamref name="T"/> to initialize if it has not
+ /// already been initialized.</param>
+ /// <param name="valueFactory">The <see cref="T:System.Func{T}"/> invoked to initialize the
+ /// reference.</param>
+ /// <returns>The initialized reference of type <typeparamref name="T"/>.</returns>
+ /// <exception cref="T:System.MissingMemberException">Type <typeparamref name="T"/> does not have a
+ /// default constructor.</exception>
+ /// <exception cref="T:System.InvalidOperationException"><paramref name="valueFactory"/> returned
+ /// null.</exception>
+ /// <remarks>
+ /// <para>
+ /// This method may only be used on reference types, and <paramref name="valueFactory"/> may
+ /// not return a null reference (Nothing in Visual Basic). To ensure initialization of value types or
+ /// to allow null reference types, see other overloads of EnsureInitialized.
+ /// </para>
+ /// <para>
+ /// This method may be used concurrently by multiple threads to initialize <paramref name="target"/>.
+ /// In the event that multiple threads access this method concurrently, multiple instances of <typeparamref name="T"/>
+ /// may be created, but only one will be stored into <paramref name="target"/>. In such an occurrence, this method will not dispose of the
+ /// objects that were not stored. If such objects must be disposed, it is up to the caller to determine
+ /// if an object was not used and to then dispose of the object appropriately.
+ /// </para>
+ /// </remarks>
+ public static T EnsureInitialized<T>(ref T target, Func<T> valueFactory) where T : class
+ {
+ // Fast path.
+ if (Volatile.Read<T>(ref target) != null)
+ {
+ return target;
+ }
+
+ return EnsureInitializedCore<T>(ref target, valueFactory);
+ }
+
+ /// <summary>
+ /// Initialize the target using the given delegate (slow path).
+ /// </summary>
+ /// <typeparam name="T">The reference type of the reference to be initialized.</typeparam>
+ /// <param name="target">The variable that need to be initialized</param>
+ /// <param name="valueFactory">The delegate that will be executed to initialize the target</param>
+ /// <returns>The initialized variable</returns>
+ private static T EnsureInitializedCore<T>(ref T target, Func<T> valueFactory) where T : class
+ {
+ T value = valueFactory();
+ if (value == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Lazy_StaticInit_InvalidOperation"));
+ }
+
+ Interlocked.CompareExchange(ref target, value, null);
+ Contract.Assert(target != null);
+ return target;
+ }
+
+
+ /// <summary>
+ /// Initializes a target reference or value type with its default constructor if it has not already
+ /// been initialized.
+ /// </summary>
+ /// <typeparam name="T">The type of the reference to be initialized.</typeparam>
+ /// <param name="target">A reference or value of type <typeparamref name="T"/> to initialize if it
+ /// has not already been initialized.</param>
+ /// <param name="initialized">A reference to a boolean that determines whether the target has already
+ /// been initialized.</param>
+ /// <param name="syncLock">A reference to an object used as the mutually exclusive lock for initializing
+ /// <paramref name="target"/>. If <paramref name="syncLock"/> is null, a new object will be instantiated.</param>
+ /// <returns>The initialized value of type <typeparamref name="T"/>.</returns>
+ public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock)
+ {
+ // Fast path.
+ if (Volatile.Read(ref initialized))
+ {
+ return target;
+ }
+
+ return EnsureInitializedCore<T>(ref target, ref initialized, ref syncLock, LazyHelpers<T>.s_activatorFactorySelector);
+ }
+
+ /// <summary>
+ /// Initializes a target reference or value type with a specified function if it has not already been
+ /// initialized.
+ /// </summary>
+ /// <typeparam name="T">The type of the reference to be initialized.</typeparam>
+ /// <param name="target">A reference or value of type <typeparamref name="T"/> to initialize if it
+ /// has not already been initialized.</param>
+ /// <param name="initialized">A reference to a boolean that determines whether the target has already
+ /// been initialized.</param>
+ /// <param name="syncLock">A reference to an object used as the mutually exclusive lock for initializing
+ /// <paramref name="target"/>. If <paramref name="syncLock"/> is null, a new object will be instantiated.</param>
+ /// <param name="valueFactory">The <see cref="T:System.Func{T}"/> invoked to initialize the
+ /// reference or value.</param>
+ /// <returns>The initialized value of type <typeparamref name="T"/>.</returns>
+ public static T EnsureInitialized<T>(ref T target, ref bool initialized, ref object syncLock, Func<T> valueFactory)
+ {
+ // Fast path.
+ if (Volatile.Read(ref initialized))
+ {
+ return target;
+ }
+
+
+ return EnsureInitializedCore<T>(ref target, ref initialized, ref syncLock, valueFactory);
+ }
+
+ /// <summary>
+ /// Ensure the target is initialized and return the value (slow path). This overload permits nulls
+ /// and also works for value type targets. Uses the supplied function to create the value.
+ /// </summary>
+ /// <typeparam name="T">The type of target.</typeparam>
+ /// <param name="target">A reference to the target to be initialized.</param>
+ /// <param name="initialized">A reference to a location tracking whether the target has been initialized.</param>
+ /// <param name="syncLock">A reference to a location containing a mutual exclusive lock. If <paramref name="syncLock"/> is null,
+ /// a new object will be instantiated.</param>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> to invoke in order to produce the lazily-initialized value.
+ /// </param>
+ /// <returns>The initialized object.</returns>
+ private static T EnsureInitializedCore<T>(ref T target, ref bool initialized, ref object syncLock, Func<T> valueFactory)
+ {
+ // Lazily initialize the lock if necessary.
+ object slock = syncLock;
+ if (slock == null)
+ {
+ object newLock = new object();
+ slock = Interlocked.CompareExchange(ref syncLock, newLock, null);
+ if (slock == null)
+ {
+ slock = newLock;
+ }
+ }
+
+ // Now double check that initialization is still required.
+ lock (slock)
+ {
+ if (!Volatile.Read(ref initialized))
+ {
+ target = valueFactory();
+ Volatile.Write(ref initialized, true);
+ }
+ }
+
+ return target;
+ }
+
+ }
+
+ // Caches the activation selector function to avoid delegate allocations.
+ static class LazyHelpers<T>
+ {
+ internal static Func<T> s_activatorFactorySelector = new Func<T>(ActivatorFactorySelector);
+
+ private static T ActivatorFactorySelector()
+ {
+ try
+ {
+ return (T)Activator.CreateInstance(typeof(T));
+ }
+ catch (MissingMethodException)
+ {
+ throw new MissingMemberException(Environment.GetResourceString("Lazy_CreateValue_NoParameterlessCtorForT"));
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/LockCookie.cs b/src/mscorlib/src/System/Threading/LockCookie.cs
new file mode 100644
index 0000000000..c1fbfd828e
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/LockCookie.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: Defines the lock that implements
+** single-writer/multiple-reader semantics
+**
+**
+===========================================================*/
+
+namespace System.Threading {
+
+ using System;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct LockCookie
+ {
+ private int _dwFlags;
+ private int _dwWriterSeqNum;
+ private int _wReaderAndWriterLevel;
+ private int _dwThreadID;
+
+ public override int GetHashCode()
+ {
+ return _dwFlags + _dwWriterSeqNum + _wReaderAndWriterLevel + _dwThreadID;
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj is LockCookie)
+ return Equals((LockCookie)obj);
+ else
+ return false;
+ }
+
+ public bool Equals(LockCookie obj)
+ {
+ return obj._dwFlags == _dwFlags && obj._dwWriterSeqNum == _dwWriterSeqNum &&
+ obj._wReaderAndWriterLevel == _wReaderAndWriterLevel && obj._dwThreadID == _dwThreadID;
+ }
+
+ public static bool operator ==(LockCookie a, LockCookie b)
+ {
+ return a.Equals(b);
+ }
+
+ public static bool operator !=(LockCookie a, LockCookie b)
+ {
+ return !(a == b);
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/LockRecursionException.cs b/src/mscorlib/src/System/Threading/LockRecursionException.cs
new file mode 100644
index 0000000000..c5e3146cbc
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/LockRecursionException.cs
@@ -0,0 +1,34 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+//
+//
+//
+// Purpose:
+// This exception represents a failed attempt to recursively
+// acquire a lock, because the particular lock kind doesn't
+// support it in its current state.
+============================================================*/
+
+namespace System.Threading
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+
+ [Serializable]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class LockRecursionException : System.Exception
+ {
+ public LockRecursionException() { }
+ public LockRecursionException(string message) : base(message) { }
+ protected LockRecursionException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+ public LockRecursionException(string message, Exception innerException) : base(message, innerException) { }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/ManualResetEvent.cs b/src/mscorlib/src/System/Threading/ManualResetEvent.cs
new file mode 100644
index 0000000000..504cfb423c
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ManualResetEvent.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: An example of a WaitHandle class
+**
+**
+=============================================================================*/
+namespace System.Threading {
+
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class ManualResetEvent : EventWaitHandle
+ {
+ public ManualResetEvent(bool initialState) : base(initialState,EventResetMode.ManualReset){}
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs b/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs
new file mode 100644
index 0000000000..b6114ef917
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ManualResetEventSlim.cs
@@ -0,0 +1,813 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// SlimManualResetEvent.cs
+//
+//
+// An manual-reset event that mixes a little spinning with a true Win32 event.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Threading;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading
+{
+
+ // ManualResetEventSlim wraps a manual-reset event internally with a little bit of
+ // spinning. When an event will be set imminently, it is often advantageous to avoid
+ // a 4k+ cycle context switch in favor of briefly spinning. Therefore we layer on to
+ // a brief amount of spinning that should, on the average, make using the slim event
+ // cheaper than using Win32 events directly. This can be reset manually, much like
+ // a Win32 manual-reset would be.
+ //
+ // Notes:
+ // We lazily allocate the Win32 event internally. Therefore, the caller should
+ // always call Dispose to clean it up, just in case. This API is a no-op of the
+ // event wasn't allocated, but if it was, ensures that the event goes away
+ // eagerly, instead of waiting for finalization.
+
+ /// <summary>
+ /// Provides a slimmed down version of <see cref="T:System.Threading.ManualResetEvent"/>.
+ /// </summary>
+ /// <remarks>
+ /// All public and protected members of <see cref="ManualResetEventSlim"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="ManualResetEventSlim"/> have
+ /// completed, and Reset, which should only be used when no other threads are
+ /// accessing the event.
+ /// </remarks>
+ [ComVisible(false)]
+ [DebuggerDisplay("Set = {IsSet}")]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class ManualResetEventSlim : IDisposable
+ {
+ // These are the default spin counts we use on single-proc and MP machines.
+ private const int DEFAULT_SPIN_SP = 1;
+ private const int DEFAULT_SPIN_MP = SpinWait.YIELD_THRESHOLD;
+
+ private volatile object m_lock;
+ // A lock used for waiting and pulsing. Lazily initialized via EnsureLockObjectCreated()
+
+ private volatile ManualResetEvent m_eventObj; // A true Win32 event used for waiting.
+
+ // -- State -- //
+ //For a packed word a uint would seem better, but Interlocked.* doesn't support them as uint isn't CLS-compliant.
+ private volatile int m_combinedState; //ie a UInt32. Used for the state items listed below.
+
+ //1-bit for signalled state
+ private const int SignalledState_BitMask = unchecked((int)0x80000000);//1000 0000 0000 0000 0000 0000 0000 0000
+ private const int SignalledState_ShiftCount = 31;
+
+ //1-bit for disposed state
+ private const int Dispose_BitMask = unchecked((int)0x40000000);//0100 0000 0000 0000 0000 0000 0000 0000
+
+ //11-bits for m_spinCount
+ private const int SpinCountState_BitMask = unchecked((int)0x3FF80000); //0011 1111 1111 1000 0000 0000 0000 0000
+ private const int SpinCountState_ShiftCount = 19;
+ private const int SpinCountState_MaxValue = (1 << 11) - 1; //2047
+
+ //19-bits for m_waiters. This allows support of 512K threads waiting which should be ample
+ private const int NumWaitersState_BitMask = unchecked((int)0x0007FFFF); // 0000 0000 0000 0111 1111 1111 1111 1111
+ private const int NumWaitersState_ShiftCount = 0;
+ private const int NumWaitersState_MaxValue = (1 << 19) - 1; //512K-1
+ // ----------- //
+
+#if DEBUG
+ private static int s_nextId; // The next id that will be given out.
+ private int m_id = Interlocked.Increment(ref s_nextId); // A unique id for debugging purposes only.
+ private long m_lastSetTime;
+ private long m_lastResetTime;
+#endif
+
+ /// <summary>
+ /// Gets the underlying <see cref="T:System.Threading.WaitHandle"/> object for this <see
+ /// cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <value>The underlying <see cref="T:System.Threading.WaitHandle"/> event object fore this <see
+ /// cref="ManualResetEventSlim"/>.</value>
+ /// <remarks>
+ /// Accessing this property forces initialization of an underlying event object if one hasn't
+ /// already been created. To simply wait on this <see cref="ManualResetEventSlim"/>,
+ /// the public Wait methods should be preferred.
+ /// </remarks>
+ public WaitHandle WaitHandle
+ {
+
+ get
+ {
+ ThrowIfDisposed();
+ if (m_eventObj == null)
+ {
+ // Lazily initialize the event object if needed.
+ LazyInitializeEvent();
+ }
+
+ return m_eventObj;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the event is set.
+ /// </summary>
+ /// <value>true if the event has is set; otherwise, false.</value>
+ public bool IsSet
+ {
+ get
+ {
+ return 0 != ExtractStatePortion(m_combinedState, SignalledState_BitMask);
+ }
+
+ private set
+ {
+ UpdateStateAtomically(((value) ? 1 : 0) << SignalledState_ShiftCount, SignalledState_BitMask);
+ }
+ }
+
+ /// <summary>
+ /// Gets the number of spin waits that will be occur before falling back to a true wait.
+ /// </summary>
+ public int SpinCount
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, SpinCountState_BitMask, SpinCountState_ShiftCount);
+ }
+
+ private set
+ {
+ Contract.Assert(value >= 0, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ Contract.Assert(value <= SpinCountState_MaxValue, "SpinCount is a restricted-width integer. The value supplied is outside the legal range.");
+ // Don't worry about thread safety because it's set one time from the constructor
+ m_combinedState = (m_combinedState & ~SpinCountState_BitMask) | (value << SpinCountState_ShiftCount);
+ }
+ }
+
+ /// <summary>
+ /// How many threads are waiting.
+ /// </summary>
+ private int Waiters
+ {
+ get
+ {
+ return ExtractStatePortionAndShiftRight(m_combinedState, NumWaitersState_BitMask, NumWaitersState_ShiftCount);
+ }
+
+ set
+ {
+ //setting to <0 would indicate an internal flaw, hence Assert is appropriate.
+ Contract.Assert(value >= 0, "NumWaiters should never be less than zero. This indicates an internal error.");
+
+ // it is possible for the max number of waiters to be exceeded via user-code, hence we use a real exception here.
+ if (value >= NumWaitersState_MaxValue)
+ throw new InvalidOperationException(String.Format(Environment.GetResourceString("ManualResetEventSlim_ctor_TooManyWaiters"), NumWaitersState_MaxValue));
+
+ UpdateStateAtomically(value << NumWaitersState_ShiftCount, NumWaitersState_BitMask);
+ }
+
+ }
+
+ //-----------------------------------------------------------------------------------
+ // Constructs a new event, optionally specifying the initial state and spin count.
+ // The defaults are that the event is unsignaled and some reasonable default spin.
+ //
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with an initial state of nonsignaled.
+ /// </summary>
+ public ManualResetEventSlim()
+ : this(false)
+ {
+
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a Boolen value indicating whether to set the intial state to signaled.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ public ManualResetEventSlim(bool initialState)
+ {
+ // Specify the defualt spin count, and use default spin if we're
+ // on a multi-processor machine. Otherwise, we won't.
+ Initialize(initialState, DEFAULT_SPIN_MP);
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ManualResetEventSlim"/>
+ /// class with a Boolen value indicating whether to set the intial state to signaled and a specified
+ /// spin count.
+ /// </summary>
+ /// <param name="initialState">true to set the initial state to signaled; false to set the initial state
+ /// to nonsignaled.</param>
+ /// <param name="spinCount">The number of spin waits that will occur before falling back to a true
+ /// wait.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="spinCount"/> is less than
+ /// 0 or greater than the maximum allowed value.</exception>
+ public ManualResetEventSlim(bool initialState, int spinCount)
+ {
+ if (spinCount < 0)
+ {
+ throw new ArgumentOutOfRangeException("spinCount");
+ }
+
+ if (spinCount > SpinCountState_MaxValue)
+ {
+ throw new ArgumentOutOfRangeException(
+ "spinCount",
+ String.Format(Environment.GetResourceString("ManualResetEventSlim_ctor_SpinCountOutOfRange"), SpinCountState_MaxValue));
+ }
+
+ // We will suppress default spin because the user specified a count.
+ Initialize(initialState, spinCount);
+ }
+
+ /// <summary>
+ /// Initializes the internal state of the event.
+ /// </summary>
+ /// <param name="initialState">Whether the event is set initially or not.</param>
+ /// <param name="spinCount">The spin count that decides when the event will block.</param>
+ private void Initialize(bool initialState, int spinCount)
+ {
+ this.m_combinedState = initialState ? (1 << SignalledState_ShiftCount) : 0;
+ //the spinCount argument has been validated by the ctors.
+ //but we now sanity check our predefined constants.
+ Contract.Assert(DEFAULT_SPIN_SP >= 0, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+ Contract.Assert(DEFAULT_SPIN_SP <= SpinCountState_MaxValue, "Internal error - DEFAULT_SPIN_SP is outside the legal range.");
+
+ SpinCount = PlatformHelper.IsSingleProcessor ? DEFAULT_SPIN_SP : spinCount;
+
+ }
+
+ /// <summary>
+ /// Helper to ensure the lock object is created before first use.
+ /// </summary>
+ private void EnsureLockObjectCreated()
+ {
+ Contract.Ensures(m_lock != null);
+
+ if (m_lock != null)
+ return;
+
+ object newObj = new object();
+ Interlocked.CompareExchange(ref m_lock, newObj, null); // failure is benign. Someone else set the value.
+ }
+
+ /// <summary>
+ /// This method lazily initializes the event object. It uses CAS to guarantee that
+ /// many threads racing to call this at once don't result in more than one event
+ /// being stored and used. The event will be signaled or unsignaled depending on
+ /// the state of the thin-event itself, with synchronization taken into account.
+ /// </summary>
+ /// <returns>True if a new event was created and stored, false otherwise.</returns>
+ private bool LazyInitializeEvent()
+ {
+ bool preInitializeIsSet = IsSet;
+ ManualResetEvent newEventObj = new ManualResetEvent(preInitializeIsSet);
+
+ // We have to CAS this in case we are racing with another thread. We must
+ // guarantee only one event is actually stored in this field.
+ if (Interlocked.CompareExchange(ref m_eventObj, newEventObj, null) != null)
+ {
+ // Someone else set the value due to a race condition. Destroy the garbage event.
+ newEventObj.Close();
+
+ return false;
+ }
+ else
+ {
+
+ // Now that the event is published, verify that the state hasn't changed since
+ // we snapped the preInitializeState. Another thread could have done that
+ // between our initial observation above and here. The barrier incurred from
+ // the CAS above (in addition to m_state being volatile) prevents this read
+ // from moving earlier and being collapsed with our original one.
+ bool currentIsSet = IsSet;
+ if (currentIsSet != preInitializeIsSet)
+ {
+ Contract.Assert(currentIsSet,
+ "The only safe concurrent transition is from unset->set: detected set->unset.");
+
+ // We saw it as unsignaled, but it has since become set.
+ lock (newEventObj)
+ {
+ // If our event hasn't already been disposed of, we must set it.
+ if (m_eventObj == newEventObj)
+ {
+ newEventObj.Set();
+ }
+ }
+ }
+
+ return true;
+ }
+ }
+
+ /// <summary>
+ /// Sets the state of the event to signaled, which allows one or more threads waiting on the event to
+ /// proceed.
+ /// </summary>
+ public void Set()
+ {
+ Set(false);
+ }
+
+ /// <summary>
+ /// Private helper to actually perform the Set.
+ /// </summary>
+ /// <param name="duringCancellation">Indicates whether we are calling Set() during cancellation.</param>
+ /// <exception cref="T:System.OperationCanceledException">The object has been canceled.</exception>
+ private void Set(bool duringCancellation)
+ {
+ // We need to ensure that IsSet=true does not get reordered past the read of m_eventObj
+ // This would be a legal movement according to the .NET memory model.
+ // The code is safe as IsSet involves an Interlocked.CompareExchange which provides a full memory barrier.
+ IsSet = true;
+
+ // If there are waiting threads, we need to pulse them.
+ if (Waiters > 0)
+ {
+ Contract.Assert(m_lock != null); //if waiters>0, then m_lock has already been created.
+ lock (m_lock)
+ {
+
+ Monitor.PulseAll(m_lock);
+ }
+ }
+
+ ManualResetEvent eventObj = m_eventObj;
+
+ //Design-decision: do not set the event if we are in cancellation -> better to deadlock than to wake up waiters incorrectly
+ //It would be preferable to wake up the event and have it throw OCE. This requires MRE to implement cancellation logic
+
+ if (eventObj != null && !duringCancellation)
+ {
+ // We must surround this call to Set in a lock. The reason is fairly subtle.
+ // Sometimes a thread will issue a Wait and wake up after we have set m_state,
+ // but before we have gotten around to setting m_eventObj (just below). That's
+ // because Wait first checks m_state and will only access the event if absolutely
+ // necessary. However, the coding pattern { event.Wait(); event.Dispose() } is
+ // quite common, and we must support it. If the waiter woke up and disposed of
+ // the event object before the setter has finished, however, we would try to set a
+ // now-disposed Win32 event. Crash! To deal with this race condition, we use a lock to
+ // protect access to the event object when setting and disposing of it. We also
+ // double-check that the event has not become null in the meantime when in the lock.
+
+ lock (eventObj)
+ {
+ if (m_eventObj != null)
+ {
+ // If somebody is waiting, we must set the event.
+ m_eventObj.Set();
+ }
+ }
+ }
+
+#if DEBUG
+ m_lastSetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Sets the state of the event to nonsignaled, which causes threads to block.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Reset()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Reset()
+ {
+ ThrowIfDisposed();
+ // If there's an event, reset it.
+ if (m_eventObj != null)
+ {
+ m_eventObj.Reset();
+ }
+
+ // There is a race condition here. If another thread Sets the event, we will get into a state
+ // where m_state will be unsignaled, yet the Win32 event object will have been signaled.
+ // This could cause waiting threads to wake up even though the event is in an
+ // unsignaled state. This is fine -- those that are calling Reset concurrently are
+ // responsible for doing "the right thing" -- e.g. rechecking the condition and
+ // resetting the event manually.
+
+ // And finally set our state back to unsignaled.
+ IsSet = false;
+
+#if DEBUG
+ m_lastResetTime = DateTime.UtcNow.Ticks;
+#endif
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait()
+ {
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> receives a signal,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledExcepton"><paramref name="cancellationToken"/> was
+ /// canceled.</exception>
+ /// <remarks>
+ /// The caller of this method blocks indefinitely until the current instance is set. The caller will
+ /// return immediately if the event is currently in a set state.
+ /// </remarks>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("timeout");
+ }
+
+ return Wait((int)totalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// <see cref="T:System.TimeSpan"/> to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new ArgumentOutOfRangeException("timeout");
+ }
+
+ return Wait((int)totalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until the current <see cref="ManualResetEventSlim"/> is set, using a
+ /// 32-bit signed integer to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the <see cref="System.Threading.ManualResetEventSlim"/> was set; otherwise,
+ /// false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The maximum number of waiters has been exceeded.
+ /// </exception>
+ /// <exception cref="T:System.Threading.OperationCanceledException"><paramref
+ /// name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ ThrowIfDisposed();
+ cancellationToken.ThrowIfCancellationRequested(); // an early convenience check
+
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout");
+ }
+
+ if (!IsSet)
+ {
+ if (millisecondsTimeout == 0)
+ {
+ // For 0-timeouts, we just return immediately.
+ return false;
+ }
+
+
+ // We spin briefly before falling back to allocating and/or waiting on a true event.
+ uint startTime = 0;
+ bool bNeedTimeoutAdjustment = false;
+ int realMillisecondsTimeout = millisecondsTimeout; //this will be adjusted if necessary.
+
+ if (millisecondsTimeout != Timeout.Infinite)
+ {
+ // We will account for time spent spinning, so that we can decrement it from our
+ // timeout. In most cases the time spent in this section will be negligible. But
+ // we can't discount the possibility of our thread being switched out for a lengthy
+ // period of time. The timeout adjustments only take effect when and if we actually
+ // decide to block in the kernel below.
+
+ startTime = TimeoutHelper.GetTime();
+ bNeedTimeoutAdjustment = true;
+ }
+
+ //spin
+ int HOW_MANY_SPIN_BEFORE_YIELD = 10;
+ int HOW_MANY_YIELD_EVERY_SLEEP_0 = 5;
+ int HOW_MANY_YIELD_EVERY_SLEEP_1 = 20;
+
+ int spinCount = SpinCount;
+ for (int i = 0; i < spinCount; i++)
+ {
+ if (IsSet)
+ {
+ return true;
+ }
+
+ else if (i < HOW_MANY_SPIN_BEFORE_YIELD)
+ {
+ if (i == HOW_MANY_SPIN_BEFORE_YIELD / 2)
+ {
+ Thread.Yield();
+ }
+ else
+ {
+ Thread.SpinWait(PlatformHelper.ProcessorCount * (4 << i));
+ }
+ }
+ else if (i % HOW_MANY_YIELD_EVERY_SLEEP_1 == 0)
+ {
+ Thread.Sleep(1);
+ }
+ else if (i % HOW_MANY_YIELD_EVERY_SLEEP_0 == 0)
+ {
+ Thread.Sleep(0);
+ }
+ else
+ {
+ Thread.Yield();
+ }
+
+ if (i >= 100 && i % 10 == 0) // check the cancellation token if the user passed a very large spin count
+ cancellationToken.ThrowIfCancellationRequested();
+ }
+
+ // Now enter the lock and wait.
+ EnsureLockObjectCreated();
+
+ // We must register and deregister the token outside of the lock, to avoid deadlocks.
+ using (cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCallback, this))
+ {
+ lock (m_lock)
+ {
+ // Loop to cope with spurious wakeups from other waits being canceled
+ while (!IsSet)
+ {
+ // If our token was canceled, we must throw and exit.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ //update timeout (delays in wait commencement are due to spinning and/or spurious wakeups from other waits being canceled)
+ if (bNeedTimeoutAdjustment)
+ {
+ realMillisecondsTimeout = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
+ if (realMillisecondsTimeout <= 0)
+ return false;
+ }
+
+ // There is a race condition that Set will fail to see that there are waiters as Set does not take the lock,
+ // so after updating waiters, we must check IsSet again.
+ // Also, we must ensure there cannot be any reordering of the assignment to Waiters and the
+ // read from IsSet. This is guaranteed as Waiters{set;} involves an Interlocked.CompareExchange
+ // operation which provides a full memory barrier.
+ // If we see IsSet=false, then we are guaranteed that Set() will see that we are
+ // waiting and will pulse the monitor correctly.
+
+ Waiters = Waiters + 1;
+
+ if (IsSet) //This check must occur after updating Waiters.
+ {
+ Waiters--; //revert the increment.
+ return true;
+ }
+
+ // Now finally perform the wait.
+ try
+ {
+ // ** the actual wait **
+ if (!Monitor.Wait(m_lock, realMillisecondsTimeout))
+ return false; //return immediately if the timeout has expired.
+ }
+ finally
+ {
+ // Clean up: we're done waiting.
+ Waiters = Waiters - 1;
+ }
+
+ // Now just loop back around, and the right thing will happen. Either:
+ // 1. We had a spurious wake-up due to some other wait being canceled via a different cancellationToken (rewait)
+ // or 2. the wait was successful. (the loop will break)
+
+ }
+ }
+ }
+ } // automatically disposes (and deregisters) the callback
+
+ return true; //done. The wait was satisfied.
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see cref="ManualResetEventSlim"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="ManualResetEventSlim"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="ManualResetEventSlim"/>, <see cref="Dispose(Boolean)"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ return; // already disposed
+
+ m_combinedState |= Dispose_BitMask; //set the dispose bit
+ if (disposing)
+ {
+ // We will dispose of the event object. We do this under a lock to protect
+ // against the race condition outlined in the Set method above.
+ ManualResetEvent eventObj = m_eventObj;
+ if (eventObj != null)
+ {
+ lock (eventObj)
+ {
+ eventObj.Close();
+ m_eventObj = null;
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Throw ObjectDisposedException if the MRES is disposed
+ /// </summary>
+ private void ThrowIfDisposed()
+ {
+ if ((m_combinedState & Dispose_BitMask) != 0)
+ throw new ObjectDisposedException(Environment.GetResourceString("ManualResetEventSlim_Disposed"));
+ }
+
+ /// <summary>
+ /// Private helper method to wake up waiters when a cancellationToken gets canceled.
+ /// </summary>
+ private static Action<object> s_cancellationTokenCallback = new Action<object>(CancellationTokenCallback);
+ private static void CancellationTokenCallback(object obj)
+ {
+ ManualResetEventSlim mre = obj as ManualResetEventSlim;
+ Contract.Assert(mre != null, "Expected a ManualResetEventSlim");
+ Contract.Assert(mre.m_lock != null); //the lock should have been created before this callback is registered for use.
+ lock (mre.m_lock)
+ {
+ Monitor.PulseAll(mre.m_lock); // awaken all waiters
+ }
+ }
+
+ /// <summary>
+ /// Private helper method for updating parts of a bit-string state value.
+ /// Mainly called from the IsSet and Waiters properties setters
+ /// </summary>
+ /// <remarks>
+ /// Note: the parameter types must be int as CompareExchange cannot take a Uint
+ /// </remarks>
+ /// <param name="newBits">The new value</param>
+ /// <param name="updateBitsMask">The mask used to set the bits</param>
+ private void UpdateStateAtomically(int newBits, int updateBitsMask)
+ {
+ SpinWait sw = new SpinWait();
+
+ Contract.Assert((newBits | updateBitsMask) == updateBitsMask, "newBits do not fall within the updateBitsMask.");
+
+ do
+ {
+ int oldState = m_combinedState; // cache the old value for testing in CAS
+
+ // Procedure:(1) zero the updateBits. eg oldState = [11111111] flag= [00111000] newState = [11000111]
+ // then (2) map in the newBits. eg [11000111] newBits=00101000, newState=[11101111]
+ int newState = (oldState & ~updateBitsMask) | newBits;
+
+ if (Interlocked.CompareExchange(ref m_combinedState, newState, oldState) == oldState)
+ {
+ return;
+ }
+
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ /// <summary>
+ /// Private helper method - performs Mask and shift, particular helpful to extract a field from a packed word.
+ /// eg ExtractStatePortionAndShiftRight(0x12345678, 0xFF000000, 24) => 0x12, ie extracting the top 8-bits as a simple integer
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ /// <param name="rightBitShiftCount"></param>
+ /// <returns></returns>
+ private static int ExtractStatePortionAndShiftRight(int state, int mask, int rightBitShiftCount)
+ {
+ //convert to uint before shifting so that right-shift does not replicate the sign-bit,
+ //then convert back to int.
+ return unchecked((int)(((uint)(state & mask)) >> rightBitShiftCount));
+ }
+
+ /// <summary>
+ /// Performs a Mask operation, but does not perform the shift.
+ /// This is acceptable for boolean values for which the shift is unnecessary
+ /// eg (val &amp; Mask) != 0 is an appropriate way to extract a boolean rather than using
+ /// ((val &amp; Mask) &gt;&gt; shiftAmount) == 1
+ ///
+ /// ?? is there a common place to put this rather than being private to MRES?
+ /// </summary>
+ /// <param name="state"></param>
+ /// <param name="mask"></param>
+ private static int ExtractStatePortion(int state, int mask)
+ {
+ return state & mask;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Monitor.cs b/src/mscorlib/src/System/Threading/Monitor.cs
new file mode 100644
index 0000000000..415948b425
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Monitor.cs
@@ -0,0 +1,256 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Synchronizes access to a shared resource or region of code in a multi-threaded
+** program.
+**
+**
+=============================================================================*/
+
+
+namespace System.Threading {
+
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime;
+ using System.Runtime.Remoting;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static class Monitor
+ {
+ /*=========================================================================
+ ** Obtain the monitor lock of obj. Will block if another thread holds the lock
+ ** Will not block if the current thread holds the lock,
+ ** however the caller must ensure that the same number of Exit
+ ** calls are made as there were Enter calls.
+ **
+ ** Exceptions: ArgumentNullException if object is null.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void Enter(Object obj);
+
+
+ // Use a ref bool instead of out to ensure that unverifiable code must
+ // initialize this value to something. If we used out, the value
+ // could be uninitialized if we threw an exception in our prolog.
+ // The JIT should inline this method to allow check of lockTaken argument to be optimized out
+ // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
+ public static void Enter(Object obj, ref bool lockTaken)
+ {
+ if (lockTaken)
+ ThrowLockTakenException();
+
+ ReliableEnter(obj, ref lockTaken);
+ Contract.Assert(lockTaken);
+ }
+
+ private static void ThrowLockTakenException()
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeFalse"), "lockTaken");
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ReliableEnter(Object obj, ref bool lockTaken);
+
+
+
+ /*=========================================================================
+ ** Release the monitor lock. If one or more threads are waiting to acquire the
+ ** lock, and the current thread has executed as many Exits as
+ ** Enters, one of the threads will be unblocked and allowed to proceed.
+ **
+ ** Exceptions: ArgumentNullException if object is null.
+ ** SynchronizationLockException if the current thread does not
+ ** own the lock.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern void Exit(Object obj);
+
+ /*=========================================================================
+ ** Similar to Enter, but will never block. That is, if the current thread can
+ ** acquire the monitor lock without blocking, it will do so and TRUE will
+ ** be returned. Otherwise FALSE will be returned.
+ **
+ ** Exceptions: ArgumentNullException if object is null.
+ =========================================================================*/
+ public static bool TryEnter(Object obj)
+ {
+ bool lockTaken = false;
+ TryEnter(obj, 0, ref lockTaken);
+ return lockTaken;
+ }
+
+ // The JIT should inline this method to allow check of lockTaken argument to be optimized out
+ // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
+ public static void TryEnter(Object obj, ref bool lockTaken)
+ {
+ if (lockTaken)
+ ThrowLockTakenException();
+
+ ReliableEnterTimeout(obj, 0, ref lockTaken);
+ }
+
+ /*=========================================================================
+ ** Version of TryEnter that will block, but only up to a timeout period
+ ** expressed in milliseconds. If timeout == Timeout.Infinite the method
+ ** becomes equivalent to Enter.
+ **
+ ** Exceptions: ArgumentNullException if object is null.
+ ** ArgumentException if timeout < 0.
+ =========================================================================*/
+ // The JIT should inline this method to allow check of lockTaken argument to be optimized out
+ // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
+ public static bool TryEnter(Object obj, int millisecondsTimeout)
+ {
+ bool lockTaken = false;
+ TryEnter(obj, millisecondsTimeout, ref lockTaken);
+ return lockTaken;
+ }
+
+ private static int MillisecondsTimeoutFromTimeSpan(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long)Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ return (int)tm;
+ }
+
+ public static bool TryEnter(Object obj, TimeSpan timeout)
+ {
+ return TryEnter(obj, MillisecondsTimeoutFromTimeSpan(timeout));
+ }
+
+ // The JIT should inline this method to allow check of lockTaken argument to be optimized out
+ // in the typical case. Note that the method has to be transparent for inlining to be allowed by the VM.
+ public static void TryEnter(Object obj, int millisecondsTimeout, ref bool lockTaken)
+ {
+ if (lockTaken)
+ ThrowLockTakenException();
+
+ ReliableEnterTimeout(obj, millisecondsTimeout, ref lockTaken);
+ }
+
+ public static void TryEnter(Object obj, TimeSpan timeout, ref bool lockTaken)
+ {
+ if (lockTaken)
+ ThrowLockTakenException();
+
+ ReliableEnterTimeout(obj, MillisecondsTimeoutFromTimeSpan(timeout), ref lockTaken);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ReliableEnterTimeout(Object obj, int timeout, ref bool lockTaken);
+
+ [System.Security.SecuritySafeCritical]
+ public static bool IsEntered(object obj)
+ {
+ if (obj == null)
+ throw new ArgumentNullException("obj");
+
+ return IsEnteredNative(obj);
+ }
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool IsEnteredNative(Object obj);
+
+ /*========================================================================
+ ** Waits for notification from the object (via a Pulse/PulseAll).
+ ** timeout indicates how long to wait before the method returns.
+ ** This method acquires the monitor waithandle for the object
+ ** If this thread holds the monitor lock for the object, it releases it.
+ ** On exit from the method, it obtains the monitor lock back.
+ ** If exitContext is true then the synchronization domain for the context
+ ** (if in a synchronized context) is exited before the wait and reacquired
+ **
+ ** Exceptions: ArgumentNullException if object is null.
+ ========================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool ObjWait(bool exitContext, int millisecondsTimeout, Object obj);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool Wait(Object obj, int millisecondsTimeout, bool exitContext)
+ {
+ if (obj == null)
+ throw (new ArgumentNullException("obj"));
+ return ObjWait(exitContext, millisecondsTimeout, obj);
+ }
+
+ public static bool Wait(Object obj, TimeSpan timeout, bool exitContext)
+ {
+ return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), exitContext);
+ }
+
+ public static bool Wait(Object obj, int millisecondsTimeout)
+ {
+ return Wait(obj, millisecondsTimeout, false);
+ }
+
+ public static bool Wait(Object obj, TimeSpan timeout)
+ {
+ return Wait(obj, MillisecondsTimeoutFromTimeSpan(timeout), false);
+ }
+
+ public static bool Wait(Object obj)
+ {
+ return Wait(obj, Timeout.Infinite, false);
+ }
+
+ /*========================================================================
+ ** Sends a notification to a single waiting object.
+ * Exceptions: SynchronizationLockException if this method is not called inside
+ * a synchronized block of code.
+ ========================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ObjPulse(Object obj);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Pulse(Object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ ObjPulse(obj);
+ }
+ /*========================================================================
+ ** Sends a notification to all waiting objects.
+ ========================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void ObjPulseAll(Object obj);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void PulseAll(Object obj)
+ {
+ if (obj == null)
+ {
+ throw new ArgumentNullException("obj");
+ }
+ Contract.EndContractBlock();
+
+ ObjPulseAll(obj);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Mutex.cs b/src/mscorlib/src/System/Threading/Mutex.cs
new file mode 100644
index 0000000000..2e9b68176d
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Mutex.cs
@@ -0,0 +1,488 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: synchronization primitive that can also be used for interprocess synchronization
+**
+**
+=============================================================================*/
+namespace System.Threading
+{
+ using System;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Security.Permissions;
+ using System.IO;
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+#if FEATURE_MACL
+ using System.Security.AccessControl;
+#endif
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [ComVisible(true)]
+ public sealed class Mutex : WaitHandle
+ {
+ static bool dummyBool;
+
+#if !FEATURE_MACL
+ public class MutexSecurity {
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public Mutex(bool initiallyOwned, String name, out bool createdNew)
+ : this(initiallyOwned, name, out createdNew, (MutexSecurity)null)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public unsafe Mutex(bool initiallyOwned, String name, out bool createdNew, MutexSecurity mutexSecurity)
+ {
+ if (name == string.Empty)
+ {
+ // Empty name is treated as an unnamed mutex. Set to null, and we will check for null from now on.
+ name = null;
+ }
+#if !PLATFORM_UNIX
+ if (name != null && System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+#endif
+ Contract.EndContractBlock();
+ Win32Native.SECURITY_ATTRIBUTES secAttrs = null;
+#if FEATURE_MACL
+ // For ACL's, get the security descriptor from the MutexSecurity.
+ if (mutexSecurity != null) {
+
+ secAttrs = new Win32Native.SECURITY_ATTRIBUTES();
+ secAttrs.nLength = (int)Marshal.SizeOf(secAttrs);
+
+ byte[] sd = mutexSecurity.GetSecurityDescriptorBinaryForm();
+ byte* pSecDescriptor = stackalloc byte[sd.Length];
+ Buffer.Memcpy(pSecDescriptor, 0, sd, 0, sd.Length);
+ secAttrs.pSecurityDescriptor = pSecDescriptor;
+ }
+#endif
+
+ CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, secAttrs);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal Mutex(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs)
+ {
+ if (name == string.Empty)
+ {
+ // Empty name is treated as an unnamed mutex. Set to null, and we will check for null from now on.
+ name = null;
+ }
+#if !PLATFORM_UNIX
+ if (name != null && System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+#endif
+ Contract.EndContractBlock();
+
+ CreateMutexWithGuaranteedCleanup(initiallyOwned, name, out createdNew, secAttrs);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal void CreateMutexWithGuaranteedCleanup(bool initiallyOwned, String name, out bool createdNew, Win32Native.SECURITY_ATTRIBUTES secAttrs)
+ {
+ RuntimeHelpers.CleanupCode cleanupCode = new RuntimeHelpers.CleanupCode(MutexCleanupCode);
+ MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(null, false);
+ MutexTryCodeHelper tryCodeHelper = new MutexTryCodeHelper(initiallyOwned, cleanupInfo, name, secAttrs, this);
+ RuntimeHelpers.TryCode tryCode = new RuntimeHelpers.TryCode(tryCodeHelper.MutexTryCode);
+ RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(
+ tryCode,
+ cleanupCode,
+ cleanupInfo);
+ createdNew = tryCodeHelper.m_newMutex;
+ }
+
+ internal class MutexTryCodeHelper
+ {
+ bool m_initiallyOwned;
+ MutexCleanupInfo m_cleanupInfo;
+ internal bool m_newMutex;
+ String m_name;
+ [System.Security.SecurityCritical] // auto-generated
+ Win32Native.SECURITY_ATTRIBUTES m_secAttrs;
+ Mutex m_mutex;
+
+ [System.Security.SecurityCritical] // auto-generated
+ [PrePrepareMethod]
+ internal MutexTryCodeHelper(bool initiallyOwned,MutexCleanupInfo cleanupInfo, String name, Win32Native.SECURITY_ATTRIBUTES secAttrs, Mutex mutex)
+ {
+ Contract.Assert(name == null || name.Length != 0);
+
+ m_initiallyOwned = initiallyOwned;
+ m_cleanupInfo = cleanupInfo;
+ m_name = name;
+ m_secAttrs = secAttrs;
+ m_mutex = mutex;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [PrePrepareMethod]
+ internal void MutexTryCode(object userData)
+ {
+ SafeWaitHandle mutexHandle = null;
+ // try block
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ }
+ finally
+ {
+ if (m_initiallyOwned)
+ {
+ m_cleanupInfo.inCriticalRegion = true;
+#if !FEATURE_CORECLR
+ Thread.BeginThreadAffinity();
+ Thread.BeginCriticalRegion();
+#endif //!FEATURE_CORECLR
+ }
+ }
+
+ int errorCode = 0;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ }
+ finally
+ {
+ errorCode = CreateMutexHandle(m_initiallyOwned, m_name, m_secAttrs, out mutexHandle);
+ }
+
+ if (mutexHandle.IsInvalid)
+ {
+ mutexHandle.SetHandleAsInvalid();
+ if (m_name != null)
+ {
+ switch (errorCode)
+ {
+#if PLATFORM_UNIX
+ case Win32Native.ERROR_FILENAME_EXCED_RANGE:
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPathComponentLength), "name");
+#endif
+
+ case Win32Native.ERROR_INVALID_HANDLE:
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", m_name));
+ }
+ }
+ __Error.WinIOError(errorCode, m_name);
+ }
+ m_newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS;
+ m_mutex.SetHandleInternal(mutexHandle);
+
+ m_mutex.hasThreadAffinity = true;
+
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [PrePrepareMethod]
+ private void MutexCleanupCode(Object userData, bool exceptionThrown)
+ {
+ MutexCleanupInfo cleanupInfo = (MutexCleanupInfo) userData;
+
+ // If hasThreadAffinity isn't true, we've thrown an exception in the above try, and we must free the mutex
+ // on this OS thread before ending our thread affninity.
+ if(!hasThreadAffinity) {
+ if (cleanupInfo.mutexHandle != null && !cleanupInfo.mutexHandle.IsInvalid) {
+ if( cleanupInfo.inCriticalRegion) {
+ Win32Native.ReleaseMutex(cleanupInfo.mutexHandle);
+ }
+ cleanupInfo.mutexHandle.Dispose();
+
+ }
+
+ if( cleanupInfo.inCriticalRegion) {
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+ Thread.EndThreadAffinity();
+#endif
+ }
+ }
+ }
+
+ internal class MutexCleanupInfo
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ internal SafeWaitHandle mutexHandle;
+ internal bool inCriticalRegion;
+ [System.Security.SecurityCritical] // auto-generated
+ internal MutexCleanupInfo(SafeWaitHandle mutexHandle, bool inCriticalRegion)
+ {
+ this.mutexHandle = mutexHandle;
+ this.inCriticalRegion = inCriticalRegion;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public Mutex(bool initiallyOwned, String name) : this(initiallyOwned, name, out dummyBool) {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public Mutex(bool initiallyOwned) : this(initiallyOwned, null, out dummyBool)
+ {
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public Mutex() : this(false, null, out dummyBool)
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private Mutex(SafeWaitHandle handle)
+ {
+ SetHandleInternal(handle);
+ hasThreadAffinity = true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Mutex OpenExisting(string name)
+ {
+#if !FEATURE_MACL
+ return OpenExisting(name, (MutexRights) 0);
+#else // FEATURE_MACL
+ return OpenExisting(name, MutexRights.Modify | MutexRights.Synchronize);
+#endif // FEATURE_MACL
+ }
+
+#if !FEATURE_MACL
+ public enum MutexRights
+ {
+ }
+#endif
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Mutex OpenExisting(string name, MutexRights rights)
+ {
+ Mutex result;
+ switch (OpenExistingWorker(name, rights, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
+
+ case OpenExistingResult.PathNotFound:
+ __Error.WinIOError(Win32Native.ERROR_PATH_NOT_FOUND, name);
+ return result; //never executes
+
+ default:
+ return result;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static bool TryOpenExisting(string name, out Mutex result)
+ {
+#if !FEATURE_MACL
+ return OpenExistingWorker(name, (MutexRights)0, out result) == OpenExistingResult.Success;
+#else // FEATURE_MACL
+ return OpenExistingWorker(name, MutexRights.Modify | MutexRights.Synchronize, out result) == OpenExistingResult.Success;
+#endif // FEATURE_MACL
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static bool TryOpenExisting(string name, MutexRights rights, out Mutex result)
+ {
+ return OpenExistingWorker(name, rights, out result) == OpenExistingResult.Success;
+ }
+
+ [System.Security.SecurityCritical]
+ private static OpenExistingResult OpenExistingWorker(string name, MutexRights rights, out Mutex result)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName"));
+ }
+
+ if(name.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ }
+#if !PLATFORM_UNIX
+ if(System.IO.Path.MaxPath < name.Length)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+ }
+#endif
+ Contract.EndContractBlock();
+
+ result = null;
+
+ // To allow users to view & edit the ACL's, call OpenMutex
+ // with parameters to allow us to view & edit the ACL. This will
+ // fail if we don't have permission to view or edit the ACL's.
+ // If that happens, ask for less permissions.
+#if FEATURE_MACL
+ SafeWaitHandle myHandle = Win32Native.OpenMutex((int) rights, false, name);
+#else
+ SafeWaitHandle myHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);
+#endif
+
+ int errorCode = 0;
+ if (myHandle.IsInvalid)
+ {
+ errorCode = Marshal.GetLastWin32Error();
+
+#if PLATFORM_UNIX
+ if (name != null && errorCode == Win32Native.ERROR_FILENAME_EXCED_RANGE)
+ {
+ // On Unix, length validation is done by CoreCLR's PAL after converting to utf-8
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPathComponentLength), "name");
+ }
+#endif
+
+ if(Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode)
+ return OpenExistingResult.NameNotFound;
+ if (Win32Native.ERROR_PATH_NOT_FOUND == errorCode)
+ return OpenExistingResult.PathNotFound;
+ if (null != name && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ return OpenExistingResult.NameInvalid;
+
+ // this is for passed through Win32Native Errors
+ __Error.WinIOError(errorCode,name);
+ }
+
+ result = new Mutex(myHandle);
+ return OpenExistingResult.Success;
+ }
+
+ // Note: To call ReleaseMutex, you must have an ACL granting you
+ // MUTEX_MODIFY_STATE rights (0x0001). The other interesting value
+ // in a Mutex's ACL is MUTEX_ALL_ACCESS (0x1F0001).
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public void ReleaseMutex()
+ {
+ if (Win32Native.ReleaseMutex(safeWaitHandle))
+ {
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+ Thread.EndThreadAffinity();
+#endif
+ }
+ else
+ {
+#if FEATURE_CORECLR
+ throw new Exception(Environment.GetResourceString("Arg_SynchronizationLockException"));
+#else
+ throw new ApplicationException(Environment.GetResourceString("Arg_SynchronizationLockException"));
+#endif // FEATURE_CORECLR
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ static int CreateMutexHandle(bool initiallyOwned, String name, Win32Native.SECURITY_ATTRIBUTES securityAttribute, out SafeWaitHandle mutexHandle) {
+ int errorCode;
+ bool fAffinity = false;
+
+ while(true) {
+ mutexHandle = Win32Native.CreateMutex(securityAttribute, initiallyOwned, name);
+ errorCode = Marshal.GetLastWin32Error();
+ if( !mutexHandle.IsInvalid) {
+ break;
+ }
+
+ if( errorCode == Win32Native.ERROR_ACCESS_DENIED) {
+ // If a mutex with the name already exists, OS will try to open it with FullAccess.
+ // It might fail if we don't have enough access. In that case, we try to open the mutex will modify and synchronize access.
+ //
+
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ try
+ {
+ }
+ finally
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginThreadAffinity();
+#endif
+ fAffinity = true;
+ }
+ mutexHandle = Win32Native.OpenMutex(Win32Native.MUTEX_MODIFY_STATE | Win32Native.SYNCHRONIZE, false, name);
+ if(!mutexHandle.IsInvalid)
+ {
+ errorCode = Win32Native.ERROR_ALREADY_EXISTS;
+ }
+ else
+ {
+ errorCode = Marshal.GetLastWin32Error();
+ }
+ }
+ finally
+ {
+ if (fAffinity) {
+#if !FEATURE_CORECLR
+ Thread.EndThreadAffinity();
+#endif
+ }
+ }
+
+ // There could be a race condition here, the other owner of the mutex can free the mutex,
+ // We need to retry creation in that case.
+ if( errorCode != Win32Native.ERROR_FILE_NOT_FOUND) {
+ if( errorCode == Win32Native.ERROR_SUCCESS) {
+ errorCode = Win32Native.ERROR_ALREADY_EXISTS;
+ }
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+ return errorCode;
+ }
+
+#if FEATURE_MACL
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public MutexSecurity GetAccessControl()
+ {
+ return new MutexSecurity(safeWaitHandle, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void SetAccessControl(MutexSecurity mutexSecurity)
+ {
+ if (mutexSecurity == null)
+ throw new ArgumentNullException("mutexSecurity");
+ Contract.EndContractBlock();
+
+ mutexSecurity.Persist(safeWaitHandle);
+ }
+#endif
+
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Overlapped.cs b/src/mscorlib/src/System/Threading/Overlapped.cs
new file mode 100644
index 0000000000..3f9fbc4989
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Overlapped.cs
@@ -0,0 +1,423 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+/*
+ * This files defines the following types:
+ * - NativeOverlapped
+ * - _IOCompletionCallback
+ * - OverlappedData
+ * - Overlapped
+ * - OverlappedDataCache
+ */
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Class for converting information to and from the native
+** overlapped structure used in asynchronous file i/o
+**
+**
+=============================================================================*/
+
+
+namespace System.Threading
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+ using System.Collections.Concurrent;
+
+ #region struct NativeOverlapped
+
+ // Valuetype that represents the (unmanaged) Win32 OVERLAPPED structure
+ // the layout of this structure must be identical to OVERLAPPED.
+ // The first five matches OVERLAPPED structure.
+ // The remaining are reserved at the end
+ [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct NativeOverlapped
+ {
+ public IntPtr InternalLow;
+ public IntPtr InternalHigh;
+ public int OffsetLow;
+ public int OffsetHigh;
+ public IntPtr EventHandle;
+ }
+
+ #endregion struct NativeOverlapped
+
+
+ #region class _IOCompletionCallback
+
+ unsafe internal class _IOCompletionCallback
+ {
+ [System.Security.SecurityCritical] // auto-generated
+ IOCompletionCallback _ioCompletionCallback;
+ ExecutionContext _executionContext;
+ uint _errorCode; // Error code
+ uint _numBytes; // No. of bytes transferred
+ [SecurityCritical]
+ NativeOverlapped* _pOVERLAP;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static _IOCompletionCallback()
+ {
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal _IOCompletionCallback(IOCompletionCallback ioCompletionCallback, ref StackCrawlMark stackMark)
+ {
+ _ioCompletionCallback = ioCompletionCallback;
+ // clone the exection context
+ _executionContext = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
+ }
+ // Context callback: same sig for SendOrPostCallback and ContextCallback
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #endif
+ static internal ContextCallback _ccb = new ContextCallback(IOCompletionCallback_Context);
+ [System.Security.SecurityCritical]
+ static internal void IOCompletionCallback_Context(Object state)
+ {
+ _IOCompletionCallback helper = (_IOCompletionCallback)state;
+ Contract.Assert(helper != null,"_IOCompletionCallback cannot be null");
+ helper._ioCompletionCallback(helper._errorCode, helper._numBytes, helper._pOVERLAP);
+ }
+
+
+ // call back helper
+ [System.Security.SecurityCritical] // auto-generated
+ static unsafe internal void PerformIOCompletionCallback(uint errorCode, // Error code
+ uint numBytes, // No. of bytes transferred
+ NativeOverlapped* pOVERLAP // ptr to OVERLAP structure
+ )
+ {
+ Overlapped overlapped;
+ _IOCompletionCallback helper;
+
+ do
+ {
+ overlapped = OverlappedData.GetOverlappedFromNative(pOVERLAP).m_overlapped;
+ helper = overlapped.iocbHelper;
+
+ if (helper == null || helper._executionContext == null || helper._executionContext.IsDefaultFTContext(true))
+ {
+ // We got here because of UnsafePack (or) Pack with EC flow supressed
+ IOCompletionCallback callback = overlapped.UserCallback;
+ callback( errorCode, numBytes, pOVERLAP);
+ }
+ else
+ {
+ // We got here because of Pack
+ helper._errorCode = errorCode;
+ helper._numBytes = numBytes;
+ helper._pOVERLAP = pOVERLAP;
+ using (ExecutionContext executionContext = helper._executionContext.CreateCopy())
+ ExecutionContext.Run(executionContext, _ccb, helper, true);
+ }
+
+ //Quickly check the VM again, to see if a packet has arrived.
+
+ OverlappedData.CheckVMForIOPacket(out pOVERLAP, out errorCode, out numBytes);
+
+ } while (pOVERLAP != null);
+
+ }
+ }
+
+ #endregion class _IOCompletionCallback
+
+
+ #region class OverlappedData
+
+ sealed internal class OverlappedData
+ {
+ // ! If you make any change to the layout here, you need to make matching change
+ // ! to OverlappedObject in vm\nativeoverlapped.h
+ internal IAsyncResult m_asyncResult;
+ [System.Security.SecurityCritical] // auto-generated
+ internal IOCompletionCallback m_iocb;
+ internal _IOCompletionCallback m_iocbHelper;
+ internal Overlapped m_overlapped;
+ private Object m_userObject;
+ private IntPtr m_pinSelf;
+ private IntPtr m_userObjectInternal;
+ private int m_AppDomainId;
+#pragma warning disable 414 // Field is not used from managed.
+#pragma warning disable 169
+ private byte m_isArray;
+ private byte m_toBeCleaned;
+#pragma warning restore 414
+#pragma warning restore 169
+ internal NativeOverlapped m_nativeOverlapped;
+
+#if FEATURE_CORECLR
+ // Adding an empty default ctor for annotation purposes
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal OverlappedData(){}
+#endif // FEATURE_CORECLR
+
+
+ [System.Security.SecurityCritical]
+ internal void ReInitialize()
+ {
+ m_asyncResult = null;
+ m_iocb = null;
+ m_iocbHelper = null;
+ m_overlapped = null;
+ m_userObject = null;
+ Contract.Assert(m_pinSelf.IsNull(), "OverlappedData has not been freed: m_pinSelf");
+ m_pinSelf = (IntPtr)0;
+ m_userObjectInternal = (IntPtr)0;
+ Contract.Assert(m_AppDomainId == 0 || m_AppDomainId == AppDomain.CurrentDomain.Id, "OverlappedData is not in the current domain");
+ m_AppDomainId = 0;
+ m_nativeOverlapped.EventHandle = (IntPtr)0;
+ m_isArray = 0;
+ m_nativeOverlapped.InternalLow = (IntPtr)0;
+ m_nativeOverlapped.InternalHigh = (IntPtr)0;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ unsafe internal NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
+ {
+ if (!m_pinSelf.IsNull()) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack"));
+ }
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ if (iocb != null)
+ {
+ m_iocbHelper = new _IOCompletionCallback(iocb, ref stackMark);
+ m_iocb = iocb;
+ }
+ else
+ {
+ m_iocbHelper = null;
+ m_iocb = null;
+ }
+ m_userObject = userData;
+ if (m_userObject != null)
+ {
+ if (m_userObject.GetType() == typeof(Object[]))
+ {
+ m_isArray = 1;
+ }
+ else
+ {
+ m_isArray = 0;
+ }
+ }
+ return AllocateNativeOverlapped();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ unsafe internal NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
+ {
+ if (!m_pinSelf.IsNull()) {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_Overlapped_Pack"));
+ }
+ m_userObject = userData;
+ if (m_userObject != null)
+ {
+ if (m_userObject.GetType() == typeof(Object[]))
+ {
+ m_isArray = 1;
+ }
+ else
+ {
+ m_isArray = 0;
+ }
+ }
+ m_iocb = iocb;
+ m_iocbHelper = null;
+ return AllocateNativeOverlapped();
+ }
+
+ [ComVisible(false)]
+ internal IntPtr UserHandle
+ {
+ get { return m_nativeOverlapped.EventHandle; }
+ set { m_nativeOverlapped.EventHandle = value; }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe private extern NativeOverlapped* AllocateNativeOverlapped();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe internal static extern void FreeNativeOverlapped(NativeOverlapped* nativeOverlappedPtr);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe internal static extern OverlappedData GetOverlappedFromNative(NativeOverlapped* nativeOverlappedPtr);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe internal static extern void CheckVMForIOPacket(out NativeOverlapped* pOVERLAP, out uint errorCode, out uint numBytes);
+ }
+
+ #endregion class OverlappedData
+
+
+ #region class Overlapped
+
+ /// <internalonly/>
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class Overlapped
+ {
+ private OverlappedData m_overlappedData;
+ private static PinnableBufferCache s_overlappedDataCache = new PinnableBufferCache("System.Threading.OverlappedData", ()=> new OverlappedData());
+
+#if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ public Overlapped()
+ {
+ m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate();
+ m_overlappedData.m_overlapped = this;
+ }
+
+ public Overlapped(int offsetLo, int offsetHi, IntPtr hEvent, IAsyncResult ar)
+ {
+ m_overlappedData = (OverlappedData) s_overlappedDataCache.Allocate();
+ m_overlappedData.m_overlapped = this;
+ m_overlappedData.m_nativeOverlapped.OffsetLow = offsetLo;
+ m_overlappedData.m_nativeOverlapped.OffsetHigh = offsetHi;
+ m_overlappedData.UserHandle = hEvent;
+ m_overlappedData.m_asyncResult = ar;
+ }
+
+ [Obsolete("This constructor is not 64-bit compatible. Use the constructor that takes an IntPtr for the event handle. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public Overlapped(int offsetLo, int offsetHi, int hEvent, IAsyncResult ar) : this(offsetLo, offsetHi, new IntPtr(hEvent), ar)
+ {
+ }
+
+ public IAsyncResult AsyncResult
+ {
+ get { return m_overlappedData.m_asyncResult; }
+ set { m_overlappedData.m_asyncResult = value; }
+ }
+
+ public int OffsetLow
+ {
+ get { return m_overlappedData.m_nativeOverlapped.OffsetLow; }
+ set { m_overlappedData.m_nativeOverlapped.OffsetLow = value; }
+ }
+
+ public int OffsetHigh
+ {
+ get { return m_overlappedData.m_nativeOverlapped.OffsetHigh; }
+ set { m_overlappedData.m_nativeOverlapped.OffsetHigh = value; }
+ }
+
+ [Obsolete("This property is not 64-bit compatible. Use EventHandleIntPtr instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ public int EventHandle
+ {
+ get { return m_overlappedData.UserHandle.ToInt32(); }
+ set { m_overlappedData.UserHandle = new IntPtr(value); }
+ }
+
+ [ComVisible(false)]
+ public IntPtr EventHandleIntPtr
+ {
+ get { return m_overlappedData.UserHandle; }
+ set { m_overlappedData.UserHandle = value; }
+ }
+
+ internal _IOCompletionCallback iocbHelper
+ {
+ get { return m_overlappedData.m_iocbHelper; }
+ }
+
+ internal IOCompletionCallback UserCallback
+ {
+ [System.Security.SecurityCritical]
+ get { return m_overlappedData.m_iocb; }
+ }
+
+ /*====================================================================
+ * Packs a managed overlapped class into native Overlapped struct.
+ * Roots the iocb and stores it in the ReservedCOR field of native Overlapped
+ * Pins the native Overlapped struct and returns the pinned index.
+ ====================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [Obsolete("This method is not safe. Use Pack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [CLSCompliant(false)]
+ unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb)
+ {
+ return Pack (iocb, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false),ComVisible(false)]
+ unsafe public NativeOverlapped* Pack(IOCompletionCallback iocb, Object userData)
+ {
+ return m_overlappedData.Pack(iocb, userData);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("This method is not safe. Use UnsafePack (iocb, userData) instead. http://go.microsoft.com/fwlink/?linkid=14202")]
+ [CLSCompliant(false)]
+ unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb)
+ {
+ return UnsafePack (iocb, null);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false), ComVisible(false)]
+ unsafe public NativeOverlapped* UnsafePack(IOCompletionCallback iocb, Object userData)
+ {
+ return m_overlappedData.UnsafePack(iocb, userData);
+ }
+
+ /*====================================================================
+ * Unpacks an unmanaged native Overlapped struct.
+ * Unpins the native Overlapped struct
+ ====================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ unsafe public static Overlapped Unpack(NativeOverlapped* nativeOverlappedPtr)
+ {
+ if (nativeOverlappedPtr == null)
+ throw new ArgumentNullException("nativeOverlappedPtr");
+ Contract.EndContractBlock();
+
+ Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
+
+ return overlapped;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [CLSCompliant(false)]
+ unsafe public static void Free(NativeOverlapped* nativeOverlappedPtr)
+ {
+ if (nativeOverlappedPtr == null)
+ throw new ArgumentNullException("nativeOverlappedPtr");
+ Contract.EndContractBlock();
+
+ Overlapped overlapped = OverlappedData.GetOverlappedFromNative(nativeOverlappedPtr).m_overlapped;
+ OverlappedData.FreeNativeOverlapped(nativeOverlappedPtr);
+ OverlappedData overlappedData = overlapped.m_overlappedData;
+ overlapped.m_overlappedData = null;
+ overlappedData.ReInitialize();
+ s_overlappedDataCache.Free(overlappedData);
+ }
+
+ }
+
+ #endregion class Overlapped
+
+} // namespace
diff --git a/src/mscorlib/src/System/Threading/ParameterizedThreadStart.cs b/src/mscorlib/src/System/Threading/ParameterizedThreadStart.cs
new file mode 100644
index 0000000000..45d24fef49
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ParameterizedThreadStart.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: This class is a Delegate which defines the start method
+** for starting a thread. That method must match this delegate.
+**
+**
+=============================================================================*/
+
+
+namespace System.Threading {
+ using System.Security.Permissions;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+
+ [ComVisibleAttribute(false)]
+ public delegate void ParameterizedThreadStart(object obj);
+}
diff --git a/src/mscorlib/src/System/Threading/ReaderWriterLock.cs b/src/mscorlib/src/System/Threading/ReaderWriterLock.cs
new file mode 100644
index 0000000000..8cead1a87a
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ReaderWriterLock.cs
@@ -0,0 +1,306 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*============================================================
+**
+**
+**
+** Purpose: Defines the lock that implements
+** single-writer/multiple-reader semantics
+**
+**
+===========================================================*/
+
+#if FEATURE_RWLOCK
+namespace System.Threading {
+ using System.Threading;
+ using System.Security.Permissions;
+ using System.Runtime.Remoting;
+ using System;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [ComVisible(true)]
+ public sealed class ReaderWriterLock: CriticalFinalizerObject
+ {
+ /*
+ * Constructor
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ReaderWriterLock()
+ {
+ PrivateInitialize();
+ }
+
+ /*
+ * Destructor
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ ~ReaderWriterLock()
+ {
+ PrivateDestruct();
+ }
+
+ /*
+ * Property that returns TRUE if the reader lock is held
+ * by the current thread
+ */
+ public bool IsReaderLockHeld {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get {
+ return(PrivateGetIsReaderLockHeld());
+ }
+ }
+
+ /*
+ * Property that returns TRUE if the writer lock is held
+ * by the current thread
+ */
+ public bool IsWriterLockHeld {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get {
+ return(PrivateGetIsWriterLockHeld());
+ }
+ }
+
+ /*
+ * Property that returns the current writer sequence number.
+ * The caller should be a reader or writer for getting
+ * meaningful results
+ */
+ public int WriterSeqNum {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ return(PrivateGetWriterSeqNum());
+ }
+ }
+
+ /*
+ * Acquires reader lock. The thread will block if a different
+ * thread has writer lock.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void AcquireReaderLockInternal(int millisecondsTimeout);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AcquireReaderLock(int millisecondsTimeout)
+ {
+ AcquireReaderLockInternal(millisecondsTimeout);
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AcquireReaderLock(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ AcquireReaderLockInternal((int)tm);
+ }
+
+ /*
+ * Acquires writer lock. The thread will block if a different
+ * thread has reader lock. It will dead lock if this thread
+ * has reader lock. Use UpgardeToWriterLock when you are not
+ * sure if the thread has reader lock
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void AcquireWriterLockInternal(int millisecondsTimeout);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AcquireWriterLock(int millisecondsTimeout)
+ {
+ AcquireWriterLockInternal(millisecondsTimeout);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AcquireWriterLock(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ AcquireWriterLockInternal((int)tm);
+ }
+
+
+ /*
+ * Releases reader lock.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private extern void ReleaseReaderLockInternal();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void ReleaseReaderLock()
+ {
+ ReleaseReaderLockInternal();
+ }
+
+ /*
+ * Releases writer lock.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private extern void ReleaseWriterLockInternal();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void ReleaseWriterLock()
+ {
+ ReleaseWriterLockInternal();
+ }
+
+ /*
+ * Upgardes the thread to a writer. If the thread has is a
+ * reader, it is possible that the reader lock was
+ * released before writer lock was acquired.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LockCookie UpgradeToWriterLock(int millisecondsTimeout)
+ {
+ LockCookie result = new LockCookie ();
+ FCallUpgradeToWriterLock (ref result, millisecondsTimeout);
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void FCallUpgradeToWriterLock(ref LockCookie result, int millisecondsTimeout);
+
+ public LockCookie UpgradeToWriterLock(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ return UpgradeToWriterLock((int)tm);
+ }
+
+ /*
+ * Restores the lock status of the thread to the one it was
+ * in when it called UpgradeToWriterLock.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void DowngradeFromWriterLockInternal(ref LockCookie lockCookie);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DowngradeFromWriterLock(ref LockCookie lockCookie)
+ {
+ DowngradeFromWriterLockInternal(ref lockCookie);
+ }
+
+ /*
+ * Releases the lock irrespective of the number of times the thread
+ * acquired the lock
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LockCookie ReleaseLock()
+ {
+ LockCookie result = new LockCookie ();
+ FCallReleaseLock (ref result);
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void FCallReleaseLock(ref LockCookie result);
+
+ /*
+ * Restores the lock status of the thread to the one it was
+ * in when it called ReleaseLock.
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void RestoreLockInternal(ref LockCookie lockCookie);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void RestoreLock(ref LockCookie lockCookie)
+ {
+ RestoreLockInternal(ref lockCookie);
+ }
+
+ /*
+ * Internal helper that returns TRUE if the reader lock is held
+ * by the current thread
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private extern bool PrivateGetIsReaderLockHeld();
+
+ /*
+ * Internal helper that returns TRUE if the writer lock is held
+ * by the current thread
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private extern bool PrivateGetIsWriterLockHeld();
+
+ /*
+ * Internal helper that returns the current writer sequence
+ * number. The caller should be a reader or writer for getting
+ * meaningful results
+ */
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int PrivateGetWriterSeqNum();
+
+ /*
+ * Returns true if there were intermediate writes since the
+ * sequence number was obtained. The caller should be
+ * a reader or writer for getting meaningful results
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern bool AnyWritersSince(int seqNum);
+
+ // Initialize state kept inside the lock
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void PrivateInitialize();
+
+ // Destruct resource associated with the lock
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void PrivateDestruct();
+
+ // State
+#pragma warning disable 169
+#pragma warning disable 414 // These fields are not used from managed.
+ private IntPtr _hWriterEvent;
+ private IntPtr _hReaderEvent;
+ private IntPtr _hObjectHandle;
+ private int _dwState = 0;
+ private int _dwULockID = 0;
+ private int _dwLLockID = 0;
+ private int _dwWriterID = 0;
+ private int _dwWriterSeqNum = 0;
+ private short _wWriterLevel;
+#if RWLOCK_STATISTICS
+ // WARNING: You must explicitly #define RWLOCK_STATISTICS when you
+ // build in both the VM and BCL directories if you want this.
+ private int _dwReaderEntryCount = 0;
+ private int _dwReaderContentionCount = 0;
+ private int _dwWriterEntryCount = 0;
+ private int _dwWriterContentionCount = 0;
+ private int _dwEventsReleasedCount = 0;
+#endif // RWLOCK_STATISTICS
+#pragma warning restore 414
+#pragma warning restore 169
+ }
+}
+#endif //FEATURE_RWLOCK
diff --git a/src/mscorlib/src/System/Threading/Semaphore.cs b/src/mscorlib/src/System/Threading/Semaphore.cs
new file mode 100644
index 0000000000..303593b776
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Semaphore.cs
@@ -0,0 +1,201 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Security;
+
+namespace System.Threading
+{
+ public sealed partial class Semaphore : WaitHandle
+ {
+ [SecuritySafeCritical]
+ public Semaphore(int initialCount, int maximumCount) : this(initialCount, maximumCount, null) { }
+
+ [SecurityCritical]
+ public Semaphore(int initialCount, int maximumCount, string name)
+ {
+ if (initialCount < 0)
+ {
+ throw new ArgumentOutOfRangeException("initialCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (maximumCount < 1)
+ {
+ throw new ArgumentOutOfRangeException("maximumCount", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
+ }
+
+ if (initialCount > maximumCount)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_SemaphoreInitialMaximum"));
+ }
+
+ SafeWaitHandle myHandle = CreateSemaphone(initialCount, maximumCount, name);
+
+ if (myHandle.IsInvalid)
+ {
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ throw new WaitHandleCannotBeOpenedException(
+ Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
+
+ __Error.WinIOError();
+ }
+ this.SafeWaitHandle = myHandle;
+ }
+
+ [SecurityCritical]
+ public Semaphore(int initialCount, int maximumCount, string name, out bool createdNew)
+ {
+ if (initialCount < 0)
+ {
+ throw new ArgumentOutOfRangeException("initialCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (maximumCount < 1)
+ {
+ throw new ArgumentOutOfRangeException("maximumCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ if (initialCount > maximumCount)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_SemaphoreInitialMaximum"));
+ }
+
+ SafeWaitHandle myHandle = CreateSemaphone(initialCount, maximumCount, name);
+
+ int errorCode = Marshal.GetLastWin32Error();
+ if (myHandle.IsInvalid)
+ {
+ if (null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ throw new WaitHandleCannotBeOpenedException(
+ Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
+ __Error.WinIOError();
+ }
+ createdNew = errorCode != Win32Native.ERROR_ALREADY_EXISTS;
+ this.SafeWaitHandle = myHandle;
+ }
+
+ [SecurityCritical]
+ private Semaphore(SafeWaitHandle handle)
+ {
+ this.SafeWaitHandle = handle;
+ }
+
+ [SecurityCritical]
+ private static SafeWaitHandle CreateSemaphone(int initialCount, int maximumCount, string name)
+ {
+ if (name != null)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives"));
+#else
+ if (name.Length > Path.MaxPath)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+#endif
+ }
+
+ Contract.Assert(initialCount >= 0);
+ Contract.Assert(maximumCount >= 1);
+ Contract.Assert(initialCount <= maximumCount);
+
+ return Win32Native.CreateSemaphore(null, initialCount, maximumCount, name);
+ }
+
+ [SecurityCritical]
+
+ public static Semaphore OpenExisting(string name)
+ {
+ Semaphore result;
+ switch (OpenExistingWorker(name, out result))
+ {
+ case OpenExistingResult.NameNotFound:
+ throw new WaitHandleCannotBeOpenedException();
+ case OpenExistingResult.NameInvalid:
+ throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", name));
+ case OpenExistingResult.PathNotFound:
+ throw new IOException(Win32Native.GetMessage(Win32Native.ERROR_PATH_NOT_FOUND));
+ default:
+ return result;
+ }
+ }
+
+ [SecurityCritical]
+ public static bool TryOpenExisting(string name, out Semaphore result)
+ {
+ return OpenExistingWorker(name, out result) == OpenExistingResult.Success;
+ }
+
+ [SecurityCritical]
+ private static OpenExistingResult OpenExistingWorker(string name, out Semaphore result)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_NamedSynchronizationPrimitives"));
+#else
+ if (name == null)
+ throw new ArgumentNullException("name", Environment.GetResourceString("ArgumentNull_WithParamName"));
+ if (name.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "name");
+ if (name.Length > Path.MaxPath)
+ throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", Path.MaxPath), "name");
+
+ const int SYNCHRONIZE = 0x00100000;
+ const int SEMAPHORE_MODIFY_STATE = 0x00000002;
+
+ //Pass false to OpenSemaphore to prevent inheritedHandles
+ SafeWaitHandle myHandle = Win32Native.OpenSemaphore(SEMAPHORE_MODIFY_STATE | SYNCHRONIZE, false, name);
+
+ if (myHandle.IsInvalid)
+ {
+ result = null;
+
+ int errorCode = Marshal.GetLastWin32Error();
+
+ if (Win32Native.ERROR_FILE_NOT_FOUND == errorCode || Win32Native.ERROR_INVALID_NAME == errorCode)
+ return OpenExistingResult.NameNotFound;
+ if (Win32Native.ERROR_PATH_NOT_FOUND == errorCode)
+ return OpenExistingResult.PathNotFound;
+ if (null != name && 0 != name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode)
+ return OpenExistingResult.NameInvalid;
+ //this is for passed through NativeMethods Errors
+ __Error.WinIOError();
+ }
+
+ result = new Semaphore(myHandle);
+ return OpenExistingResult.Success;
+#endif
+ }
+
+ public int Release()
+ {
+ return Release(1);
+ }
+
+ // increase the count on a semaphore, returns previous count
+ [SecuritySafeCritical]
+ public int Release(int releaseCount)
+ {
+ if (releaseCount < 1)
+ {
+ throw new ArgumentOutOfRangeException("releaseCount", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ }
+
+ //If ReleaseSempahore returns false when the specified value would cause
+ // the semaphore's count to exceed the maximum count set when Semaphore was created
+ //Non-Zero return
+
+ int previousCount;
+ if (!Win32Native.ReleaseSemaphore(SafeWaitHandle, releaseCount, out previousCount))
+ {
+ throw new SemaphoreFullException();
+ }
+
+ return previousCount;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/SemaphoreFullException.cs b/src/mscorlib/src/System/Threading/SemaphoreFullException.cs
new file mode 100644
index 0000000000..e1928e05de
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SemaphoreFullException.cs
@@ -0,0 +1,30 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Threading {
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.InteropServices;
+
+ [Serializable]
+ [ComVisibleAttribute(false)]
+#if !FEATURE_CORECLR
+ [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=2.0.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public class SemaphoreFullException : SystemException {
+
+ public SemaphoreFullException() : base(Environment.GetResourceString("Threading_SemaphoreFullException")){
+ }
+
+ public SemaphoreFullException(String message) : base(message) {
+ }
+
+ public SemaphoreFullException(String message, Exception innerException) : base(message, innerException) {
+ }
+
+ protected SemaphoreFullException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/SemaphoreSlim.cs b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs
new file mode 100644
index 0000000000..c2dcbb3451
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SemaphoreSlim.cs
@@ -0,0 +1,930 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A lightweight semahore class that contains the basic semaphore functions plus some useful functions like interrupt
+// and wait handle exposing to allow waiting on multiple semaphores.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Diagnostics.Contracts;
+using System.Threading.Tasks;
+
+// The class will be part of the current System.Threading namespace
+namespace System.Threading
+{
+ /// <summary>
+ /// Limits the number of threads that can access a resource or pool of resources concurrently.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="SemaphoreSlim"/> provides a lightweight semaphore class that doesn't
+ /// use Windows kernel semaphores.
+ /// </para>
+ /// <para>
+ /// All public and protected members of <see cref="SemaphoreSlim"/> are thread-safe and may be used
+ /// concurrently from multiple threads, with the exception of Dispose, which
+ /// must only be used when all other operations on the <see cref="SemaphoreSlim"/> have
+ /// completed.
+ /// </para>
+ /// </remarks>
+ [ComVisible(false)]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerDisplay("Current Count = {m_currentCount}")]
+ public class SemaphoreSlim : IDisposable
+ {
+ #region Private Fields
+
+ // The semaphore count, initialized in the constructor to the initial value, every release call incremetns it
+ // and every wait call decrements it as long as its value is positive otherwise the wait will block.
+ // Its value must be between the maximum semaphore value and zero
+ private volatile int m_currentCount;
+
+ // The maximum semaphore value, it is initialized to Int.MaxValue if the client didn't specify it. it is used
+ // to check if the count excceeded the maxi value or not.
+ private readonly int m_maxCount;
+
+ // The number of synchronously waiting threads, it is set to zero in the constructor and increments before blocking the
+ // threading and decrements it back after that. It is used as flag for the release call to know if there are
+ // waiting threads in the monitor or not.
+ private volatile int m_waitCount;
+
+ // Dummy object used to in lock statements to protect the semaphore count, wait handle and cancelation
+ private object m_lockObj;
+
+ // Act as the semaphore wait handle, it's lazily initialized if needed, the first WaitHandle call initialize it
+ // and wait an release sets and resets it respectively as long as it is not null
+ private volatile ManualResetEvent m_waitHandle;
+
+ // Head of list representing asynchronous waits on the semaphore.
+ private TaskNode m_asyncHead;
+
+ // Tail of list representing asynchronous waits on the semaphore.
+ private TaskNode m_asyncTail;
+
+ // A pre-completed task with Result==true
+ private readonly static Task<bool> s_trueTask =
+ new Task<bool>(false, true, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+ // A pre-completed task with Result==false
+ private readonly static Task<bool> s_falseTask =
+ new Task<bool>(false, false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken));
+
+ // No maximum constant
+ private const int NO_MAXIMUM = Int32.MaxValue;
+
+ // Task in a linked list of asynchronous waiters
+ private sealed class TaskNode : Task<bool>, IThreadPoolWorkItem
+ {
+ internal TaskNode Prev, Next;
+ internal TaskNode() : base() {}
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+ bool setSuccessfully = TrySetResult(true);
+ Contract.Assert(setSuccessfully, "Should have been able to complete task");
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+ }
+ #endregion
+
+ #region Public properties
+
+ /// <summary>
+ /// Gets the current count of the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <value>The current count of the <see cref="SemaphoreSlim"/>.</value>
+ public int CurrentCount
+ {
+ get { return m_currentCount; }
+ }
+
+ /// <summary>
+ /// Returns a <see cref="T:System.Threading.WaitHandle"/> that can be used to wait on the semaphore.
+ /// </summary>
+ /// <value>A <see cref="T:System.Threading.WaitHandle"/> that can be used to wait on the
+ /// semaphore.</value>
+ /// <remarks>
+ /// A successful wait on the <see cref="AvailableWaitHandle"/> does not imply a successful wait on
+ /// the <see cref="SemaphoreSlim"/> itself, nor does it decrement the semaphore's
+ /// count. <see cref="AvailableWaitHandle"/> exists to allow a thread to block waiting on multiple
+ /// semaphores, but such a wait should be followed by a true wait on the target semaphore.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The <see
+ /// cref="SemaphoreSlim"/> has been disposed.</exception>
+ public WaitHandle AvailableWaitHandle
+ {
+ get
+ {
+ CheckDispose();
+
+ // Return it directly if it is not null
+ if (m_waitHandle != null)
+ return m_waitHandle;
+
+ //lock the count to avoid multiple threads initializing the handle if it is null
+ lock (m_lockObj)
+ {
+ if (m_waitHandle == null)
+ {
+ // The initial state for the wait handle is true if the count is greater than zero
+ // false otherwise
+ m_waitHandle = new ManualResetEvent(m_currentCount != 0);
+ }
+ }
+ return m_waitHandle;
+ }
+ }
+
+ #endregion
+
+ #region Constructors
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SemaphoreSlim"/> class, specifying
+ /// the initial number of requests that can be granted concurrently.
+ /// </summary>
+ /// <param name="initialCount">The initial number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="initialCount"/>
+ /// is less than 0.</exception>
+ public SemaphoreSlim(int initialCount)
+ : this(initialCount, NO_MAXIMUM)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SemaphoreSlim"/> class, specifying
+ /// the initial and maximum number of requests that can be granted concurrently.
+ /// </summary>
+ /// <param name="initialCount">The initial number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <param name="maxCount">The maximum number of requests for the semaphore that can be granted
+ /// concurrently.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"> <paramref name="initialCount"/>
+ /// is less than 0. -or-
+ /// <paramref name="initialCount"/> is greater than <paramref name="maxCount"/>. -or-
+ /// <paramref name="maxCount"/> is less than 0.</exception>
+ public SemaphoreSlim(int initialCount, int maxCount)
+ {
+ if (initialCount < 0 || initialCount > maxCount)
+ {
+ throw new ArgumentOutOfRangeException(
+ "initialCount", initialCount, GetResourceString("SemaphoreSlim_ctor_InitialCountWrong"));
+ }
+
+ //validate input
+ if (maxCount <= 0)
+ {
+ throw new ArgumentOutOfRangeException("maxCount", maxCount, GetResourceString("SemaphoreSlim_ctor_MaxCountWrong"));
+ }
+
+ m_maxCount = maxCount;
+ m_lockObj = new object();
+ m_currentCount = initialCount;
+ }
+
+ #endregion
+
+ #region Methods
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait()
+ {
+ // Call wait with infinite timeout
+ Wait(Timeout.Infinite, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> token to
+ /// observe.</param>
+ /// <exception cref="T:System.OperationCanceledException"><paramref name="cancellationToken"/> was
+ /// canceled.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ // Call wait with infinite timeout
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ // Validate the timeout
+ Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
+ }
+
+ // Call wait with the timeout milliseconds
+ return Wait((int)timeout.TotalMilliseconds, new CancellationToken());
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval, while observing a <see
+ /// cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to
+ /// observe.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/>.</exception>
+ /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ // Validate the timeout
+ Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
+ }
+
+ // Call wait with the timeout milliseconds
+ return Wait((int)timeout.TotalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>, using a 32-bit
+ /// signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="Timeout.Infinite"/>(-1) to wait indefinitely.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>;
+ /// otherwise, false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, new CancellationToken());
+ }
+
+
+ /// <summary>
+ /// Blocks the current thread until it can enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to
+ /// wait indefinitely.</param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
+ /// <returns>true if the current thread successfully entered the <see cref="SemaphoreSlim"/>; otherwise, false.</returns>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.</exception>
+ /// <exception cref="System.OperationCanceledException"><paramref name="cancellationToken"/> was canceled.</exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ "totalMilliSeconds", millisecondsTimeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ // Perf: Check the stack timeout parameter before checking the volatile count
+ if (millisecondsTimeout == 0 && m_currentCount == 0)
+ {
+ // Pessimistic fail fast, check volatile count outside lock (only when timeout is zero!)
+ return false;
+ }
+
+ uint startTime = 0;
+ if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout > 0)
+ {
+ startTime = TimeoutHelper.GetTime();
+ }
+
+ bool waitSuccessful = false;
+ Task<bool> asyncWaitTask = null;
+ bool lockTaken = false;
+
+ //Register for cancellation outside of the main lock.
+ //NOTE: Register/deregister inside the lock can deadlock as different lock acquisition orders could
+ // occur for (1)this.m_lockObj and (2)cts.internalLock
+ CancellationTokenRegistration cancellationTokenRegistration = cancellationToken.InternalRegisterWithoutEC(s_cancellationTokenCanceledEventHandler, this);
+ try
+ {
+ // Perf: first spin wait for the count to be positive, but only up to the first planned yield.
+ // This additional amount of spinwaiting in addition
+ // to Monitor.Enter()’s spinwaiting has shown measurable perf gains in test scenarios.
+ //
+ SpinWait spin = new SpinWait();
+ while (m_currentCount == 0 && !spin.NextSpinWillYield)
+ {
+ spin.SpinOnce();
+ }
+ // entering the lock and incrementing waiters must not suffer a thread-abort, else we cannot
+ // clean up m_waitCount correctly, which may lead to deadlock due to non-woken waiters.
+ try { }
+ finally
+ {
+ Monitor.Enter(m_lockObj, ref lockTaken);
+ if (lockTaken)
+ {
+ m_waitCount++;
+ }
+ }
+
+ // If there are any async waiters, for fairness we'll get in line behind
+ // then by translating our synchronous wait into an asynchronous one that we
+ // then block on (once we've released the lock).
+ if (m_asyncHead != null)
+ {
+ Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't");
+ asyncWaitTask = WaitAsync(millisecondsTimeout, cancellationToken);
+ }
+ // There are no async waiters, so we can proceed with normal synchronous waiting.
+ else
+ {
+ // If the count > 0 we are good to move on.
+ // If not, then wait if we were given allowed some wait duration
+
+ OperationCanceledException oce = null;
+
+ if (m_currentCount == 0)
+ {
+ if (millisecondsTimeout == 0)
+ {
+ return false;
+ }
+
+ // Prepare for the main wait...
+ // wait until the count become greater than zero or the timeout is expired
+ try
+ {
+ waitSuccessful = WaitUntilCountOrTimeout(millisecondsTimeout, startTime, cancellationToken);
+ }
+ catch (OperationCanceledException e) { oce = e; }
+ }
+
+ // Now try to acquire. We prioritize acquisition over cancellation/timeout so that we don't
+ // lose any counts when there are asynchronous waiters in the mix. Asynchronous waiters
+ // defer to synchronous waiters in priority, which means that if it's possible an asynchronous
+ // waiter didn't get released because a synchronous waiter was present, we need to ensure
+ // that synchronous waiter succeeds so that they have a chance to release.
+ Contract.Assert(!waitSuccessful || m_currentCount > 0,
+ "If the wait was successful, there should be count available.");
+ if (m_currentCount > 0)
+ {
+ waitSuccessful = true;
+ m_currentCount--;
+ }
+ else if (oce != null)
+ {
+ throw oce;
+ }
+
+ // Exposing wait handle which is lazily initialized if needed
+ if (m_waitHandle != null && m_currentCount == 0)
+ {
+ m_waitHandle.Reset();
+ }
+ }
+ }
+ finally
+ {
+ // Release the lock
+ if (lockTaken)
+ {
+ m_waitCount--;
+ Monitor.Exit(m_lockObj);
+ }
+
+ // Unregister the cancellation callback.
+ cancellationTokenRegistration.Dispose();
+ }
+
+ // If we had to fall back to asynchronous waiting, block on it
+ // here now that we've released the lock, and return its
+ // result when available. Otherwise, this was a synchronous
+ // wait, and whether we successfully acquired the semaphore is
+ // stored in waitSuccessful.
+
+ return (asyncWaitTask != null) ? asyncWaitTask.GetAwaiter().GetResult() : waitSuccessful;
+ }
+
+ /// <summary>
+ /// Local helper function, waits on the monitor until the monitor recieves signal or the
+ /// timeout is expired
+ /// </summary>
+ /// <param name="millisecondsTimeout">The maximum timeout</param>
+ /// <param name="startTime">The start ticks to calculate the elapsed time</param>
+ /// <param name="cancellationToken">The CancellationToken to observe.</param>
+ /// <returns>true if the monitor recieved a signal, false if the timeout expired</returns>
+ private bool WaitUntilCountOrTimeout(int millisecondsTimeout, uint startTime, CancellationToken cancellationToken)
+ {
+ int remainingWaitMilliseconds = Timeout.Infinite;
+
+ //Wait on the monitor as long as the count is zero
+ while (m_currentCount == 0)
+ {
+ // If cancelled, we throw. Trying to wait could lead to deadlock.
+ cancellationToken.ThrowIfCancellationRequested();
+
+ if (millisecondsTimeout != Timeout.Infinite)
+ {
+ remainingWaitMilliseconds = TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout);
+ if (remainingWaitMilliseconds <= 0)
+ {
+ // The thread has expires its timeout
+ return false;
+ }
+ }
+ // ** the actual wait **
+ if (!Monitor.Wait(m_lockObj, remainingWaitMilliseconds))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <returns>A task that will complete when the semaphore has been entered.</returns>
+ public Task WaitAsync()
+ {
+ return WaitAsync(Timeout.Infinite, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <returns>A task that will complete when the semaphore has been entered.</returns>
+ /// <param name="cancellationToken">
+ /// The <see cref="T:System.Threading.CancellationToken"/> token to observe.
+ /// </param>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The current instance has already been disposed.
+ /// </exception>
+ public Task WaitAsync(CancellationToken cancellationToken)
+ {
+ return WaitAsync(Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.
+ /// </exception>
+ public Task<bool> WaitAsync(int millisecondsTimeout)
+ {
+ return WaitAsync(millisecondsTimeout, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval, while observing a
+ /// <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// The <see cref="T:System.Threading.CancellationToken"/> token to observe.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The current instance has already been disposed.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ public Task<bool> WaitAsync(TimeSpan timeout)
+ {
+ return WaitAsync(timeout, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>, using a <see
+ /// cref="T:System.TimeSpan"/> to measure the time interval.
+ /// </summary>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents
+ /// an infinite time-out -or- timeout is greater than <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ public Task<bool> WaitAsync(TimeSpan timeout, CancellationToken cancellationToken)
+ {
+ // Validate the timeout
+ Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ "timeout", timeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
+ }
+
+ // Call wait with the timeout milliseconds
+ return WaitAsync((int)timeout.TotalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Asynchronously waits to enter the <see cref="SemaphoreSlim"/>,
+ /// using a 32-bit signed integer to measure the time interval,
+ /// while observing a <see cref="T:System.Threading.CancellationToken"/>.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="Timeout.Infinite"/>(-1) to wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> to observe.</param>
+ /// <returns>
+ /// A task that will complete with a result of true if the current thread successfully entered
+ /// the <see cref="SemaphoreSlim"/>, otherwise with a result of false.
+ /// </returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ /// <exception cref="ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a negative number other than -1,
+ /// which represents an infinite time-out.
+ /// </exception>
+ public Task<bool> WaitAsync(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ "totalMilliSeconds", millisecondsTimeout, GetResourceString("SemaphoreSlim_Wait_TimeoutWrong"));
+ }
+
+ // Bail early for cancellation
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<bool>(cancellationToken);
+
+ lock (m_lockObj)
+ {
+ // If there are counts available, allow this waiter to succeed.
+ if (m_currentCount > 0)
+ {
+ --m_currentCount;
+ if (m_waitHandle != null && m_currentCount == 0) m_waitHandle.Reset();
+ return s_trueTask;
+ }
+ else if (millisecondsTimeout == 0)
+ {
+ // No counts, if timeout is zero fail fast
+ return s_falseTask;
+ }
+ // If there aren't, create and return a task to the caller.
+ // The task will be completed either when they've successfully acquired
+ // the semaphore or when the timeout expired or cancellation was requested.
+ else
+ {
+ Contract.Assert(m_currentCount == 0, "m_currentCount should never be negative");
+ var asyncWaiter = CreateAndAddAsyncWaiter();
+ return (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled) ?
+ asyncWaiter :
+ WaitUntilCountOrTimeoutAsync(asyncWaiter, millisecondsTimeout, cancellationToken);
+ }
+ }
+ }
+
+ /// <summary>Creates a new task and stores it into the async waiters list.</summary>
+ /// <returns>The created task.</returns>
+ private TaskNode CreateAndAddAsyncWaiter()
+ {
+ Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Create the task
+ var task = new TaskNode();
+
+ // Add it to the linked list
+ if (m_asyncHead == null)
+ {
+ Contract.Assert(m_asyncTail == null, "If head is null, so too should be tail");
+ m_asyncHead = task;
+ m_asyncTail = task;
+ }
+ else
+ {
+ Contract.Assert(m_asyncTail != null, "If head is not null, neither should be tail");
+ m_asyncTail.Next = task;
+ task.Prev = m_asyncTail;
+ m_asyncTail = task;
+ }
+
+ // Hand it back
+ return task;
+ }
+
+ /// <summary>Removes the waiter task from the linked list.</summary>
+ /// <param name="task">The task to remove.</param>
+ /// <returns>true if the waiter was in the list; otherwise, false.</returns>
+ private bool RemoveAsyncWaiter(TaskNode task)
+ {
+ Contract.Requires(task != null, "Expected non-null task");
+ Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Is the task in the list? To be in the list, either it's the head or it has a predecessor that's in the list.
+ bool wasInList = m_asyncHead == task || task.Prev != null;
+
+ // Remove it from the linked list
+ if (task.Next != null) task.Next.Prev = task.Prev;
+ if (task.Prev != null) task.Prev.Next = task.Next;
+ if (m_asyncHead == task) m_asyncHead = task.Next;
+ if (m_asyncTail == task) m_asyncTail = task.Prev;
+ Contract.Assert((m_asyncHead == null) == (m_asyncTail == null), "Head is null iff tail is null");
+
+ // Make sure not to leak
+ task.Next = task.Prev = null;
+
+ // Return whether the task was in the list
+ return wasInList;
+ }
+
+ /// <summary>Performs the asynchronous wait.</summary>
+ /// <param name="millisecondsTimeout">The timeout.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>The task to return to the caller.</returns>
+ private async Task<bool> WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ Contract.Assert(asyncWaiter != null, "Waiter should have been constructed");
+ Contract.Assert(Monitor.IsEntered(m_lockObj), "Requires the lock be held");
+
+ // Wait until either the task is completed, timeout occurs, or cancellation is requested.
+ // We need to ensure that the Task.Delay task is appropriately cleaned up if the await
+ // completes due to the asyncWaiter completing, so we use our own token that we can explicitly
+ // cancel, and we chain the caller's supplied token into it.
+ using (var cts = cancellationToken.CanBeCanceled ?
+ CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, default(CancellationToken)) :
+ new CancellationTokenSource())
+ {
+ var waitCompleted = Task.WhenAny(asyncWaiter, Task.Delay(millisecondsTimeout, cts.Token));
+ if (asyncWaiter == await waitCompleted.ConfigureAwait(false))
+ {
+ cts.Cancel(); // ensure that the Task.Delay task is cleaned up
+ return true; // successfully acquired
+ }
+ }
+
+ // If we get here, the wait has timed out or been canceled.
+
+ // If the await completed synchronously, we still hold the lock. If it didn't,
+ // we no longer hold the lock. As such, acquire it.
+ lock (m_lockObj)
+ {
+ // Remove the task from the list. If we're successful in doing so,
+ // we know that no one else has tried to complete this waiter yet,
+ // so we can safely cancel or timeout.
+ if (RemoveAsyncWaiter(asyncWaiter))
+ {
+ cancellationToken.ThrowIfCancellationRequested(); // cancellation occurred
+ return false; // timeout occurred
+ }
+ }
+
+ // The waiter had already been removed, which means it's already completed or is about to
+ // complete, so let it, and don't return until it does.
+ return await asyncWaiter.ConfigureAwait(false);
+ }
+
+ /// <summary>
+ /// Exits the <see cref="SemaphoreSlim"/> once.
+ /// </summary>
+ /// <returns>The previous count of the <see cref="SemaphoreSlim"/>.</returns>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public int Release()
+ {
+ return Release(1);
+ }
+
+ /// <summary>
+ /// Exits the <see cref="SemaphoreSlim"/> a specified number of times.
+ /// </summary>
+ /// <param name="releaseCount">The number of times to exit the semaphore.</param>
+ /// <returns>The previous count of the <see cref="SemaphoreSlim"/>.</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="releaseCount"/> is less
+ /// than 1.</exception>
+ /// <exception cref="T:System.Threading.SemaphoreFullException">The <see cref="SemaphoreSlim"/> has
+ /// already reached its maximum size.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The current instance has already been
+ /// disposed.</exception>
+ public int Release(int releaseCount)
+ {
+ CheckDispose();
+
+ // Validate input
+ if (releaseCount < 1)
+ {
+ throw new ArgumentOutOfRangeException(
+ "releaseCount", releaseCount, GetResourceString("SemaphoreSlim_Release_CountWrong"));
+ }
+ int returnCount;
+
+ lock (m_lockObj)
+ {
+ // Read the m_currentCount into a local variable to avoid unnecessary volatile accesses inside the lock.
+ int currentCount = m_currentCount;
+ returnCount = currentCount;
+
+ // If the release count would result exceeding the maximum count, throw SemaphoreFullException.
+ if (m_maxCount - currentCount < releaseCount)
+ {
+ throw new SemaphoreFullException();
+ }
+
+ // Increment the count by the actual release count
+ currentCount += releaseCount;
+
+ // Signal to any synchronous waiters
+ int waitCount = m_waitCount;
+ if (currentCount == 1 || waitCount == 1)
+ {
+ Monitor.Pulse(m_lockObj);
+ }
+ else if (waitCount > 1)
+ {
+ Monitor.PulseAll(m_lockObj);
+ }
+
+ // Now signal to any asynchronous waiters, if there are any. While we've already
+ // signaled the synchronous waiters, we still hold the lock, and thus
+ // they won't have had an opportunity to acquire this yet. So, when releasing
+ // asynchronous waiters, we assume that all synchronous waiters will eventually
+ // acquire the semaphore. That could be a faulty assumption if those synchronous
+ // waits are canceled, but the wait code path will handle that.
+ if (m_asyncHead != null)
+ {
+ Contract.Assert(m_asyncTail != null, "tail should not be null if head isn't null");
+ int maxAsyncToRelease = currentCount - waitCount;
+ while (maxAsyncToRelease > 0 && m_asyncHead != null)
+ {
+ --currentCount;
+ --maxAsyncToRelease;
+
+ // Get the next async waiter to release and queue it to be completed
+ var waiterTask = m_asyncHead;
+ RemoveAsyncWaiter(waiterTask); // ensures waiterTask.Next/Prev are null
+ QueueWaiterTask(waiterTask);
+ }
+ }
+ m_currentCount = currentCount;
+
+ // Exposing wait handle if it is not null
+ if (m_waitHandle != null && returnCount == 0 && currentCount > 0)
+ {
+ m_waitHandle.Set();
+ }
+ }
+
+ // And return the count
+ return returnCount;
+ }
+
+ /// <summary>
+ /// Queues a waiter task to the ThreadPool. We use this small helper method so that
+ /// the larger Release(count) method does not need to be SecuritySafeCritical.
+ /// </summary>
+ [SecuritySafeCritical] // for ThreadPool.UnsafeQueueCustomWorkItem
+ private static void QueueWaiterTask(TaskNode waiterTask)
+ {
+ ThreadPool.UnsafeQueueCustomWorkItem(waiterTask, forceGlobal: false);
+ }
+
+ /// <summary>
+ /// Releases all resources used by the current instance of <see
+ /// cref="SemaphoreSlim"/>.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose()"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// When overridden in a derived class, releases the unmanaged resources used by the
+ /// <see cref="T:System.Threading.ManualResetEventSlim"/>, and optionally releases the managed resources.
+ /// </summary>
+ /// <param name="disposing">true to release both managed and unmanaged resources;
+ /// false to release only unmanaged resources.</param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="SemaphoreSlim"/>, <see cref="Dispose(Boolean)"/> is not
+ /// thread-safe and may not be used concurrently with other members of this instance.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (m_waitHandle != null)
+ {
+ m_waitHandle.Close();
+ m_waitHandle = null;
+ }
+ m_lockObj = null;
+ m_asyncHead = null;
+ m_asyncTail = null;
+ }
+ }
+
+
+
+ /// <summary>
+ /// Private helper method to wake up waiters when a cancellationToken gets canceled.
+ /// </summary>
+ private static Action<object> s_cancellationTokenCanceledEventHandler = new Action<object>(CancellationTokenCanceledEventHandler);
+ private static void CancellationTokenCanceledEventHandler(object obj)
+ {
+ SemaphoreSlim semaphore = obj as SemaphoreSlim;
+ Contract.Assert(semaphore != null, "Expected a SemaphoreSlim");
+ lock (semaphore.m_lockObj)
+ {
+ Monitor.PulseAll(semaphore.m_lockObj); //wake up all waiters.
+ }
+ }
+
+ /// <summary>
+ /// Checks the dispose status by checking the lock object, if it is null means that object
+ /// has been disposed and throw ObjectDisposedException
+ /// </summary>
+ private void CheckDispose()
+ {
+ if (m_lockObj == null)
+ {
+ throw new ObjectDisposedException(null, GetResourceString("SemaphoreSlim_Disposed"));
+ }
+ }
+
+ /// <summary>
+ /// local helper function to retrieve the exception string message from the resource file
+ /// </summary>
+ /// <param name="str">The key string</param>
+ private static string GetResourceString(string str)
+ {
+ return Environment.GetResourceString(str);
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/SendOrPostCallback.cs b/src/mscorlib/src/System/Threading/SendOrPostCallback.cs
new file mode 100644
index 0000000000..b81d2bff64
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SendOrPostCallback.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+** Purpose: Represents a method to be called when a message is to be dispatched to a synchronization context.
+**
+**
+===========================================================*/
+
+namespace System.Threading
+{
+ public delegate void SendOrPostCallback(Object state);
+}
diff --git a/src/mscorlib/src/System/Threading/SpinLock.cs b/src/mscorlib/src/System/Threading/SpinLock.cs
new file mode 100644
index 0000000000..dea87435a7
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SpinLock.cs
@@ -0,0 +1,750 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// A spin lock is a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop ("spins")
+// repeatedly checking until the lock becomes available. As the thread remains active performing a non-useful task,
+// the use of such a lock is a kind of busy waiting and consumes CPU resources without performing real work.
+//
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+using System;
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Runtime.ConstrainedExecution;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading
+{
+
+ /// <summary>
+ /// Provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop
+ /// repeatedly checking until the lock becomes available.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Spin locks can be used for leaf-level locks where the object allocation implied by using a <see
+ /// cref="System.Threading.Monitor"/>, in size or due to garbage collection pressure, is overly
+ /// expensive. Avoiding blocking is another reason that a spin lock can be useful, however if you expect
+ /// any significant amount of blocking, you are probably best not using spin locks due to excessive
+ /// spinning. Spinning can be beneficial when locks are fine grained and large in number (for example, a
+ /// lock per node in a linked list) as well as when lock hold times are always extremely short. In
+ /// general, while holding a spin lock, one should avoid blocking, calling anything that itself may
+ /// block, holding more than one spin lock at once, making dynamically dispatched calls (interface and
+ /// virtuals), making statically dispatched calls into any code one doesn't own, or allocating memory.
+ /// </para>
+ /// <para>
+ /// <see cref="SpinLock"/> should only be used when it's been determined that doing so will improve an
+ /// application's performance. It's also important to note that <see cref="SpinLock"/> is a value type,
+ /// for performance reasons. As such, one must be very careful not to accidentally copy a SpinLock
+ /// instance, as the two instances (the original and the copy) would then be completely independent of
+ /// one another, which would likely lead to erroneous behavior of the application. If a SpinLock instance
+ /// must be passed around, it should be passed by reference rather than by value.
+ /// </para>
+ /// <para>
+ /// Do not store <see cref="SpinLock"/> instances in readonly fields.
+ /// </para>
+ /// <para>
+ /// All members of <see cref="SpinLock"/> are thread-safe and may be used from multiple threads
+ /// concurrently.
+ /// </para>
+ /// </remarks>
+ [ComVisible(false)]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerTypeProxy(typeof(SystemThreading_SpinLockDebugView))]
+ [DebuggerDisplay("IsHeld = {IsHeld}")]
+ public struct SpinLock
+ {
+ // The current ownership state is a single signed int. There are two modes:
+ //
+ // 1) Ownership tracking enabled: the high bit is 0, and the remaining bits
+ // store the managed thread ID of the current owner. When the 31 low bits
+ // are 0, the lock is available.
+ // 2) Performance mode: when the high bit is 1, lock availability is indicated by the low bit.
+ // When the low bit is 1 -- the lock is held; 0 -- the lock is available.
+ //
+ // There are several masks and constants below for convenience.
+
+ private volatile int m_owner;
+
+ // The multiplier factor for the each spinning iteration
+ // This number has been chosen after trying different numbers on different CPUs (4, 8 and 16 ) and this provided the best results
+ private const int SPINNING_FACTOR = 100;
+
+ // After how many yields, call Sleep(1)
+ private const int SLEEP_ONE_FREQUENCY = 40;
+
+ // After how many yields, call Sleep(0)
+ private const int SLEEP_ZERO_FREQUENCY = 10;
+
+ // After how many yields, check the timeout
+ private const int TIMEOUT_CHECK_FREQUENCY = 10;
+
+ // Thr thread tracking disabled mask
+ private const int LOCK_ID_DISABLE_MASK = unchecked((int)0x80000000); //1000 0000 0000 0000 0000 0000 0000 0000
+
+ //the lock is held by some thread, but we don't know which
+ private const int LOCK_ANONYMOUS_OWNED = 0x1; //0000 0000 0000 0000 0000 0000 0000 0001
+
+ // Waiters mask if the thread tracking is disabled
+ private const int WAITERS_MASK = ~(LOCK_ID_DISABLE_MASK | 1); //0111 1111 1111 1111 1111 1111 1111 1110
+
+ // The Thread tacking is disabled and the lock bit is set, used in Enter fast path to make sure the id is disabled and lock is available
+ private const int ID_DISABLED_AND_ANONYMOUS_OWNED = unchecked((int)0x80000001); //1000 0000 0000 0000 0000 0000 0000 0001
+
+ // If the thread is unowned if:
+ // m_owner zero and the threa tracking is enabled
+ // m_owner & LOCK_ANONYMOUS_OWNED = zero and the thread tracking is disabled
+ private const int LOCK_UNOWNED = 0;
+
+ // The maximum number of waiters (only used if the thread tracking is disabled)
+ // The actual maximum waiters count is this number divided by two because each waiter increments the waiters count by 2
+ // The waiters count is calculated by m_owner & WAITERS_MASK 01111....110
+ private static int MAXIMUM_WAITERS = WAITERS_MASK;
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/>
+ /// structure with the option to track thread IDs to improve debugging.
+ /// </summary>
+ /// <remarks>
+ /// The default constructor for <see cref="SpinLock"/> tracks thread ownership.
+ /// </remarks>
+ /// <param name="enableThreadOwnerTracking">Whether to capture and use thread IDs for debugging
+ /// purposes.</param>
+ public SpinLock(bool enableThreadOwnerTracking)
+ {
+ m_owner = LOCK_UNOWNED;
+ if (!enableThreadOwnerTracking)
+ {
+ m_owner |= LOCK_ID_DISABLE_MASK;
+ Contract.Assert(!IsThreadOwnerTrackingEnabled, "property should be false by now");
+ }
+ }
+
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/>
+ /// structure with the option to track thread IDs to improve debugging.
+ /// </summary>
+ /// <remarks>
+ /// The default constructor for <see cref="SpinLock"/> tracks thread ownership.
+ /// </remarks>
+ /// <summary>
+ /// Acquires the lock in a reliable manner, such that even if an exception occurs within the method
+ /// call, <paramref name="lockTaken"/> can be examined reliably to determine whether the lock was
+ /// acquired.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="SpinLock"/> is a non-reentrant lock, meaning that if a thread holds the lock, it is
+ /// not allowed to enter the lock again. If thread ownership tracking is enabled (whether it's
+ /// enabled is available through <see cref="IsThreadOwnerTrackingEnabled"/>), an exception will be
+ /// thrown when a thread tries to re-enter a lock it already holds. However, if thread ownership
+ /// tracking is disabled, attempting to enter a lock already held will result in deadlock.
+ /// </remarks>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling Enter.
+ /// </exception>
+ public void Enter(ref bool lockTaken)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ //Try to keep the code and branching in this method as small as possible in order to inline the method
+ int observedOwner = m_owner;
+ if (lockTaken || //invalid parameter
+ (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
+ Interlocked.CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
+ ContinueTryEnter(Timeout.Infinite, ref lockTaken); // Then try the slow path if any of the above conditions is met
+
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block waiting for the lock to be available. If the
+ /// lock is not available when TryEnter is called, it will return immediately without any further
+ /// spinning.
+ /// </remarks>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ public void TryEnter(ref bool lockTaken)
+ {
+ TryEnter(0, ref lockTaken);
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block indefinitely waiting for the lock to be
+ /// available. It will block until either the lock is available or until the <paramref
+ /// name="timeout"/>
+ /// has expired.
+ /// </remarks>
+ /// <param name="timeout">A <see cref="System.TimeSpan"/> that represents the number of milliseconds
+ /// to wait, or a <see cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative
+ /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater
+ /// than <see cref="System.Int32.MaxValue"/> milliseconds.
+ /// </exception>
+ public void TryEnter(TimeSpan timeout, ref bool lockTaken)
+ {
+ // Validate the timeout
+ Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ "timeout", timeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange"));
+ }
+
+ // Call reliable enter with the int-based timeout milliseconds
+ TryEnter((int)timeout.TotalMilliseconds, ref lockTaken);
+ }
+
+ /// <summary>
+ /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within
+ /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the
+ /// lock was acquired.
+ /// </summary>
+ /// <remarks>
+ /// Unlike <see cref="Enter"/>, TryEnter will not block indefinitely waiting for the lock to be
+ /// available. It will block until either the lock is available or until the <paramref
+ /// name="millisecondsTimeout"/> has expired.
+ /// </remarks>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
+ /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref
+ /// name="lockTaken"/> must be initialized to false prior to calling this method.</param>
+ /// <exception cref="T:System.Threading.LockRecursionException">
+ /// Thread ownership tracking is enabled, and the current thread has already acquired this lock.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is
+ /// a negative number other than -1, which represents an infinite time-out.</exception>
+ public void TryEnter(int millisecondsTimeout, ref bool lockTaken)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+
+ int observedOwner = m_owner;
+ if (millisecondsTimeout < -1 || //invalid parameter
+ lockTaken || //invalid parameter
+ (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
+ Interlocked.CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
+ ContinueTryEnter(millisecondsTimeout, ref lockTaken); // The call the slow pth
+ }
+
+ /// <summary>
+ /// Try acquire the lock with long path, this is usually called after the first path in Enter and
+ /// TryEnter failed The reason for short path is to make it inline in the run time which improves the
+ /// performance. This method assumed that the parameter are validated in Enter ir TryENter method
+ /// </summary>
+ /// <param name="millisecondsTimeout">The timeout milliseconds</param>
+ /// <param name="lockTaken">The lockTaken param</param>
+ private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken)
+ {
+ //Leave the critical region which is entered by the fast path
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ // The fast path doesn't throw any exception, so we have to validate the parameters here
+ if (lockTaken)
+ {
+ lockTaken = false;
+ throw new System.ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException"));
+ }
+
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException(
+ "millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange"));
+ }
+
+
+ uint startTime = 0;
+ if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0)
+ {
+ startTime = TimeoutHelper.GetTime();
+ }
+
+#if !FEATURE_CORECLR
+ if (CdsSyncEtwBCLProvider.Log.IsEnabled())
+ {
+ CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(m_owner);
+ }
+#endif
+
+ if (IsThreadOwnerTrackingEnabled)
+ {
+ // Slow path for enabled thread tracking mode
+ ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTime, ref lockTaken);
+ return;
+ }
+
+ // then thread tracking is disabled
+ // In this case there are three ways to acquire the lock
+ // 1- the first way the thread either tries to get the lock if it's free or updates the waiters, if the turn >= the processors count then go to 3 else go to 2
+ // 2- In this step the waiter threads spins and tries to acquire the lock, the number of spin iterations and spin count is dependent on the thread turn
+ // the late the thread arrives the more it spins and less frequent it check the lock avilability
+ // Also the spins count is increases each iteration
+ // If the spins iterations finished and failed to acquire the lock, go to step 3
+ // 3- This is the yielding step, there are two ways of yielding Thread.Yield and Sleep(1)
+ // If the timeout is expired in after step 1, we need to decrement the waiters count before returning
+
+ int observedOwner;
+ int turn = int.MaxValue;
+ //***Step 1, take the lock or update the waiters
+
+ // try to acquire the lock directly if possible or update the waiters count
+ observedOwner = m_owner;
+ if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+
+ if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
+ {
+ return;
+ }
+
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ }
+ else //failed to acquire the lock,then try to update the waiters. If the waiters count reached the maximum, jsut break the loop to avoid overflow
+ {
+ if ((observedOwner & WAITERS_MASK) != MAXIMUM_WAITERS)
+ turn = (Interlocked.Add(ref m_owner, 2) & WAITERS_MASK) >> 1 ;
+ }
+
+
+
+ // Check the timeout.
+ if (millisecondsTimeout == 0 ||
+ (millisecondsTimeout != Timeout.Infinite &&
+ TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0))
+ {
+ DecrementWaiters();
+ return;
+ }
+
+ //***Step 2. Spinning
+ //lock acquired failed and waiters updated
+ int processorCount = PlatformHelper.ProcessorCount;
+ if (turn < processorCount)
+ {
+ int processFactor = 1;
+ for (int i = 1; i <= turn * SPINNING_FACTOR; i++)
+ {
+ Thread.SpinWait((turn + i) * SPINNING_FACTOR * processFactor);
+ if (processFactor < processorCount)
+ processFactor++;
+ observedOwner = m_owner;
+ if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+
+ int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero
+ observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters
+ : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
+ Contract.Assert((newOwner & WAITERS_MASK) >= 0);
+
+ if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+ {
+ return;
+ }
+
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ }
+ }
+ }
+
+ // Check the timeout.
+ if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)
+ {
+ DecrementWaiters();
+ return;
+ }
+
+ //*** Step 3, Yielding
+ //Sleep(1) every 50 yields
+ int yieldsoFar = 0;
+ while (true)
+ {
+ observedOwner = m_owner;
+ if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero
+ observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters
+ : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
+ Contract.Assert((newOwner & WAITERS_MASK) >= 0);
+
+ if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+ {
+ return;
+ }
+
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ }
+
+ if (yieldsoFar % SLEEP_ONE_FREQUENCY == 0)
+ {
+ Thread.Sleep(1);
+ }
+ else if (yieldsoFar % SLEEP_ZERO_FREQUENCY == 0)
+ {
+ Thread.Sleep(0);
+ }
+ else
+ {
+ Thread.Yield();
+ }
+
+ if (yieldsoFar % TIMEOUT_CHECK_FREQUENCY == 0)
+ {
+ //Check the timeout.
+ if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)
+ {
+ DecrementWaiters();
+ return;
+ }
+ }
+
+ yieldsoFar++;
+ }
+ }
+
+ /// <summary>
+ /// decrements the waiters, in case of the timeout is expired
+ /// </summary>
+ private void DecrementWaiters()
+ {
+ SpinWait spinner = new SpinWait();
+ while (true)
+ {
+ int observedOwner = m_owner;
+ if ((observedOwner & WAITERS_MASK) == 0) return; // don't decrement the waiters if it's corrupted by previous call of Exit(false)
+ if (Interlocked.CompareExchange(ref m_owner, observedOwner - 2, observedOwner) == observedOwner)
+ {
+ Contract.Assert(!IsThreadOwnerTrackingEnabled); // Make sure the waiters never be negative which will cause the thread tracking bit to be flipped
+ break;
+ }
+ spinner.SpinOnce();
+ }
+
+ }
+
+ /// <summary>
+ /// ContinueTryEnter for the thread tracking mode enabled
+ /// </summary>
+ private void ContinueTryEnterWithThreadTracking(int millisecondsTimeout, uint startTime, ref bool lockTaken)
+ {
+ Contract.Assert(IsThreadOwnerTrackingEnabled);
+
+ int lockUnowned = 0;
+ // We are using thread IDs to mark ownership. Snap the thread ID and check for recursion.
+ // We also must or the ID enablement bit, to ensure we propagate when we CAS it in.
+ int m_newOwner = Thread.CurrentThread.ManagedThreadId;
+ if (m_owner == m_newOwner)
+ {
+ // We don't allow lock recursion.
+ throw new LockRecursionException(Environment.GetResourceString("SpinLock_TryEnter_LockRecursionException"));
+ }
+
+
+ SpinWait spinner = new SpinWait();
+
+ // Loop until the lock has been successfully acquired or, if specified, the timeout expires.
+ do
+ {
+
+ // We failed to get the lock, either from the fast route or the last iteration
+ // and the timeout hasn't expired; spin once and try again.
+ spinner.SpinOnce();
+
+ // Test before trying to CAS, to avoid acquiring the line exclusively unnecessarily.
+
+ if (m_owner == lockUnowned)
+ {
+#if !FEATURE_CORECLR
+ Thread.BeginCriticalRegion();
+#endif
+ if (Interlocked.CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned)
+ {
+ return;
+ }
+#if !FEATURE_CORECLR
+ // The thread failed to get the lock, so we don't need to remain in a critical region.
+ Thread.EndCriticalRegion();
+#endif
+ }
+ // Check the timeout. We only RDTSC if the next spin will yield, to amortize the cost.
+ if (millisecondsTimeout == 0 ||
+ (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield &&
+ TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0))
+ {
+ return;
+ }
+ } while (true);
+ }
+
+ /// <summary>
+ /// Releases the lock.
+ /// </summary>
+ /// <remarks>
+ /// The default overload of <see cref="Exit()"/> provides the same behavior as if calling <see
+ /// cref="Exit(Boolean)"/> using true as the argument, but Exit() could be slightly faster than Exit(true).
+ /// </remarks>
+ /// <exception cref="SynchronizationLockException">
+ /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
+ /// </exception>
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Exit()
+ {
+ //This is the fast path for the thread tracking is disabled, otherwise go to the slow path
+ if ((m_owner & LOCK_ID_DISABLE_MASK) == 0)
+ ExitSlowPath(true);
+ else
+ Interlocked.Decrement(ref m_owner);
+
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+
+ }
+
+ /// <summary>
+ /// Releases the lock.
+ /// </summary>
+ /// <param name="useMemoryBarrier">
+ /// A Boolean value that indicates whether a memory fence should be issued in order to immediately
+ /// publish the exit operation to other threads.
+ /// </param>
+ /// <remarks>
+ /// Calling <see cref="Exit(Boolean)"/> with the <paramref name="useMemoryBarrier"/> argument set to
+ /// true will improve the fairness of the lock at the expense of some performance. The default <see
+ /// cref="Enter"/>
+ /// overload behaves as if specifying true for <paramref name="useMemoryBarrier"/>.
+ /// </remarks>
+ /// <exception cref="SynchronizationLockException">
+ /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
+ /// </exception>
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public void Exit(bool useMemoryBarrier)
+ {
+ // This is the fast path for the thread tracking is diabled and not to use memory barrier, otherwise go to the slow path
+ // The reason not to add else statement if the usememorybarrier is that it will add more barnching in the code and will prevent
+ // method inlining, so this is optimized for useMemoryBarrier=false and Exit() overload optimized for useMemoryBarrier=true
+ if ((m_owner & LOCK_ID_DISABLE_MASK) != 0 && !useMemoryBarrier)
+ {
+ int tmpOwner = m_owner;
+ m_owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ }
+ else
+ ExitSlowPath(useMemoryBarrier);
+
+#if !FEATURE_CORECLR
+ Thread.EndCriticalRegion();
+#endif
+ }
+
+ /// <summary>
+ /// The slow path for exit method if the fast path failed
+ /// </summary>
+ /// <param name="useMemoryBarrier">
+ /// A Boolean value that indicates whether a memory fence should be issued in order to immediately
+ /// publish the exit operation to other threads
+ /// </param>
+ private void ExitSlowPath(bool useMemoryBarrier)
+ {
+ bool threadTrackingEnabled = (m_owner & LOCK_ID_DISABLE_MASK) == 0;
+ if (threadTrackingEnabled && !IsHeldByCurrentThread)
+ {
+ throw new System.Threading.SynchronizationLockException(
+ Environment.GetResourceString("SpinLock_Exit_SynchronizationLockException"));
+ }
+
+ if (useMemoryBarrier)
+ {
+ if (threadTrackingEnabled)
+ Interlocked.Exchange(ref m_owner, LOCK_UNOWNED);
+ else
+ Interlocked.Decrement(ref m_owner);
+
+ }
+ else
+ {
+ if (threadTrackingEnabled)
+ m_owner = LOCK_UNOWNED;
+ else
+ {
+ int tmpOwner = m_owner;
+ m_owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
+ }
+
+ }
+
+ }
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread.
+ /// </summary>
+ public bool IsHeld
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ if (IsThreadOwnerTrackingEnabled)
+ return m_owner != LOCK_UNOWNED;
+
+ return (m_owner & LOCK_ANONYMOUS_OWNED) != LOCK_UNOWNED;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread.
+ /// </summary>
+ /// <summary>
+ /// Gets whether the lock is held by the current thread.
+ /// </summary>
+ /// <remarks>
+ /// If the lock was initialized to track owner threads, this will return whether the lock is acquired
+ /// by the current thread. It is invalid to use this property when the lock was initialized to not
+ /// track thread ownership.
+ /// </remarks>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// Thread ownership tracking is disabled.
+ /// </exception>
+ public bool IsHeldByCurrentThread
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get
+ {
+ if (!IsThreadOwnerTrackingEnabled)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("SpinLock_IsHeldByCurrentThread"));
+ }
+ return ((m_owner & (~LOCK_ID_DISABLE_MASK)) == Thread.CurrentThread.ManagedThreadId);
+ }
+ }
+
+ /// <summary>Gets whether thread ownership tracking is enabled for this instance.</summary>
+ public bool IsThreadOwnerTrackingEnabled
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return (m_owner & LOCK_ID_DISABLE_MASK) == 0; }
+ }
+
+ #region Debugger proxy class
+ /// <summary>
+ /// Internal class used by debug type proxy attribute to display the owner thread ID
+ /// </summary>
+ internal class SystemThreading_SpinLockDebugView
+ {
+ // SpinLock object
+ private SpinLock m_spinLock;
+
+ /// <summary>
+ /// SystemThreading_SpinLockDebugView constructor
+ /// </summary>
+ /// <param name="spinLock">The SpinLock to be proxied.</param>
+ public SystemThreading_SpinLockDebugView(SpinLock spinLock)
+ {
+ // Note that this makes a copy of the SpinLock (struct). It doesn't hold a reference to it.
+ m_spinLock = spinLock;
+ }
+
+ /// <summary>
+ /// Checks if the lock is held by the current thread or not
+ /// </summary>
+ public bool? IsHeldByCurrentThread
+ {
+ get
+ {
+ try
+ {
+ return m_spinLock.IsHeldByCurrentThread;
+ }
+ catch (InvalidOperationException)
+ {
+ return null;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the current owner thread, zero if it is released
+ /// </summary>
+ public int? OwnerThreadID
+ {
+ get
+ {
+ if (m_spinLock.IsThreadOwnerTrackingEnabled)
+ {
+ return m_spinLock.m_owner;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Gets whether the lock is currently held by any thread or not.
+ /// </summary>
+ public bool IsHeld
+ {
+ get { return m_spinLock.IsHeld; }
+ }
+ }
+ #endregion
+
+ }
+}
+#pragma warning restore 0420
diff --git a/src/mscorlib/src/System/Threading/SpinWait.cs b/src/mscorlib/src/System/Threading/SpinWait.cs
new file mode 100644
index 0000000000..c2cd0b6203
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SpinWait.cs
@@ -0,0 +1,369 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Central spin logic used across the entire code-base.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Runtime.ConstrainedExecution;
+using System.Security.Permissions;
+using System.Threading;
+using System.Diagnostics.Contracts;
+using System.Diagnostics.CodeAnalysis;
+
+namespace System.Threading
+{
+ // SpinWait is just a little value type that encapsulates some common spinning
+ // logic. It ensures we always yield on single-proc machines (instead of using busy
+ // waits), and that we work well on HT. It encapsulates a good mixture of spinning
+ // and real yielding. It's a value type so that various areas of the engine can use
+ // one by allocating it on the stack w/out unnecessary GC allocation overhead, e.g.:
+ //
+ // void f() {
+ // SpinWait wait = new SpinWait();
+ // while (!p) { wait.SpinOnce(); }
+ // ...
+ // }
+ //
+ // Internally it just maintains a counter that is used to decide when to yield, etc.
+ //
+ // A common usage is to spin before blocking. In those cases, the NextSpinWillYield
+ // property allows a user to decide to fall back to waiting once it returns true:
+ //
+ // void f() {
+ // SpinWait wait = new SpinWait();
+ // while (!p) {
+ // if (wait.NextSpinWillYield) { /* block! */ }
+ // else { wait.SpinOnce(); }
+ // }
+ // ...
+ // }
+
+ /// <summary>
+ /// Provides support for spin-based waiting.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// <see cref="SpinWait"/> encapsulates common spinning logic. On single-processor machines, yields are
+ /// always used instead of busy waits, and on computers with Intel™ processors employing Hyper-Threading™
+ /// technology, it helps to prevent hardware thread starvation. SpinWait encapsulates a good mixture of
+ /// spinning and true yielding.
+ /// </para>
+ /// <para>
+ /// <see cref="SpinWait"/> is a value type, which means that low-level code can utilize SpinWait without
+ /// fear of unnecessary allocation overheads. SpinWait is not generally useful for ordinary applications.
+ /// In most cases, you should use the synchronization classes provided by the .NET Framework, such as
+ /// <see cref="System.Threading.Monitor"/>. For most purposes where spin waiting is required, however,
+ /// the <see cref="SpinWait"/> type should be preferred over the <see
+ /// cref="System.Threading.Thread.SpinWait"/> method.
+ /// </para>
+ /// <para>
+ /// While SpinWait is designed to be used in concurrent applications, it is not designed to be
+ /// used from multiple threads concurrently. SpinWait's members are not thread-safe. If multiple
+ /// threads must spin, each should use its own instance of SpinWait.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public struct SpinWait
+ {
+
+ // These constants determine the frequency of yields versus spinning. The
+ // numbers may seem fairly arbitrary, but were derived with at least some
+ // thought in the design document. I fully expect they will need to change
+ // over time as we gain more experience with performance.
+ internal const int YIELD_THRESHOLD = 10; // When to switch over to a true yield.
+ internal const int SLEEP_0_EVERY_HOW_MANY_TIMES = 5; // After how many yields should we Sleep(0)?
+ internal const int SLEEP_1_EVERY_HOW_MANY_TIMES = 20; // After how many yields should we Sleep(1)?
+
+ // The number of times we've spun already.
+ private int m_count;
+
+ /// <summary>
+ /// Gets the number of times <see cref="SpinOnce"/> has been called on this instance.
+ /// </summary>
+ public int Count
+ {
+ get { return m_count; }
+ }
+
+ /// <summary>
+ /// Gets whether the next call to <see cref="SpinOnce"/> will yield the processor, triggering a
+ /// forced context switch.
+ /// </summary>
+ /// <value>Whether the next call to <see cref="SpinOnce"/> will yield the processor, triggering a
+ /// forced context switch.</value>
+ /// <remarks>
+ /// On a single-CPU machine, <see cref="SpinOnce"/> always yields the processor. On machines with
+ /// multiple CPUs, <see cref="SpinOnce"/> may yield after an unspecified number of calls.
+ /// </remarks>
+ public bool NextSpinWillYield
+ {
+ get { return m_count > YIELD_THRESHOLD || PlatformHelper.IsSingleProcessor; }
+ }
+
+ /// <summary>
+ /// Performs a single spin.
+ /// </summary>
+ /// <remarks>
+ /// This is typically called in a loop, and may change in behavior based on the number of times a
+ /// <see cref="SpinOnce"/> has been called thus far on this instance.
+ /// </remarks>
+ public void SpinOnce()
+ {
+ if (NextSpinWillYield)
+ {
+ //
+ // We must yield.
+ //
+ // We prefer to call Thread.Yield first, triggering a SwitchToThread. This
+ // unfortunately doesn't consider all runnable threads on all OS SKUs. In
+ // some cases, it may only consult the runnable threads whose ideal processor
+ // is the one currently executing code. Thus we occasionally issue a call to
+ // Sleep(0), which considers all runnable threads at equal priority. Even this
+ // is insufficient since we may be spin waiting for lower priority threads to
+ // execute; we therefore must call Sleep(1) once in a while too, which considers
+ // all runnable threads, regardless of ideal processor and priority, but may
+ // remove the thread from the scheduler's queue for 10+ms, if the system is
+ // configured to use the (default) coarse-grained system timer.
+ //
+
+#if !FEATURE_CORECLR
+ CdsSyncEtwBCLProvider.Log.SpinWait_NextSpinWillYield();
+#endif
+ int yieldsSoFar = (m_count >= YIELD_THRESHOLD ? m_count - YIELD_THRESHOLD : m_count);
+
+ if ((yieldsSoFar % SLEEP_1_EVERY_HOW_MANY_TIMES) == (SLEEP_1_EVERY_HOW_MANY_TIMES - 1))
+ {
+ Thread.Sleep(1);
+ }
+ else if ((yieldsSoFar % SLEEP_0_EVERY_HOW_MANY_TIMES) == (SLEEP_0_EVERY_HOW_MANY_TIMES - 1))
+ {
+ Thread.Sleep(0);
+ }
+ else
+ {
+ Thread.Yield();
+ }
+ }
+ else
+ {
+ //
+ // Otherwise, we will spin.
+ //
+ // We do this using the CLR's SpinWait API, which is just a busy loop that
+ // issues YIELD/PAUSE instructions to ensure multi-threaded CPUs can react
+ // intelligently to avoid starving. (These are NOOPs on other CPUs.) We
+ // choose a number for the loop iteration count such that each successive
+ // call spins for longer, to reduce cache contention. We cap the total
+ // number of spins we are willing to tolerate to reduce delay to the caller,
+ // since we expect most callers will eventually block anyway.
+ //
+ Thread.SpinWait(4 << m_count);
+ }
+
+ // Finally, increment our spin counter.
+ m_count = (m_count == int.MaxValue ? YIELD_THRESHOLD : m_count + 1);
+ }
+
+ /// <summary>
+ /// Resets the spin counter.
+ /// </summary>
+ /// <remarks>
+ /// This makes <see cref="SpinOnce"/> and <see cref="NextSpinWillYield"/> behave as though no calls
+ /// to <see cref="SpinOnce"/> had been issued on this instance. If a <see cref="SpinWait"/> instance
+ /// is reused many times, it may be useful to reset it to avoid yielding too soon.
+ /// </remarks>
+ public void Reset()
+ {
+ m_count = 0;
+ }
+
+ #region Static Methods
+ /// <summary>
+ /// Spins until the specified condition is satisfied.
+ /// </summary>
+ /// <param name="condition">A delegate to be executed over and over until it returns true.</param>
+ /// <exception cref="ArgumentNullException">The <paramref name="condition"/> argument is null.</exception>
+ public static void SpinUntil(Func<bool> condition)
+ {
+#if DEBUG
+ bool result =
+#endif
+ SpinUntil(condition, Timeout.Infinite);
+#if DEBUG
+ Contract.Assert(result);
+#endif
+ }
+
+ /// <summary>
+ /// Spins until the specified condition is satisfied or until the specified timeout is expired.
+ /// </summary>
+ /// <param name="condition">A delegate to be executed over and over until it returns true.</param>
+ /// <param name="timeout">
+ /// A <see cref="TimeSpan"/> that represents the number of milliseconds to wait,
+ /// or a TimeSpan that represents -1 milliseconds to wait indefinitely.</param>
+ /// <returns>True if the condition is satisfied within the timeout; otherwise, false</returns>
+ /// <exception cref="ArgumentNullException">The <paramref name="condition"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="timeout"/> is a negative number
+ /// other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater than
+ /// <see cref="System.Int32.MaxValue"/>.</exception>
+ public static bool SpinUntil(Func<bool> condition, TimeSpan timeout)
+ {
+ // Validate the timeout
+ Int64 totalMilliseconds = (Int64)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ throw new System.ArgumentOutOfRangeException(
+ "timeout", timeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong"));
+ }
+
+ // Call wait with the timeout milliseconds
+ return SpinUntil(condition, (int)timeout.TotalMilliseconds);
+ }
+
+ /// <summary>
+ /// Spins until the specified condition is satisfied or until the specified timeout is expired.
+ /// </summary>
+ /// <param name="condition">A delegate to be executed over and over until it returns true.</param>
+ /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see
+ /// cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param>
+ /// <returns>True if the condition is satisfied within the timeout; otherwise, false</returns>
+ /// <exception cref="ArgumentNullException">The <paramref name="condition"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is a
+ /// negative number other than -1, which represents an infinite time-out.</exception>
+ public static bool SpinUntil(Func<bool> condition, int millisecondsTimeout)
+ {
+ if (millisecondsTimeout < Timeout.Infinite)
+ {
+ throw new ArgumentOutOfRangeException(
+ "millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinWait_SpinUntil_TimeoutWrong"));
+ }
+ if (condition == null)
+ {
+ throw new ArgumentNullException("condition", Environment.GetResourceString("SpinWait_SpinUntil_ArgumentNull"));
+ }
+ uint startTime = 0;
+ if (millisecondsTimeout != 0 && millisecondsTimeout != Timeout.Infinite)
+ {
+ startTime = TimeoutHelper.GetTime();
+ }
+ SpinWait spinner = new SpinWait();
+ while (!condition())
+ {
+ if (millisecondsTimeout == 0)
+ {
+ return false;
+ }
+
+ spinner.SpinOnce();
+
+ if (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield)
+ {
+ if (millisecondsTimeout <= (TimeoutHelper.GetTime() - startTime))
+ {
+ return false;
+ }
+ }
+ }
+ return true;
+
+ }
+ #endregion
+
+ }
+
+
+ /// <summary>
+ /// A helper class to get the number of processors, it updates the numbers of processors every sampling interval.
+ /// </summary>
+ internal static class PlatformHelper
+ {
+ private const int PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 30000; // How often to refresh the count, in milliseconds.
+ private static volatile int s_processorCount; // The last count seen.
+ private static volatile int s_lastProcessorCountRefreshTicks; // The last time we refreshed.
+
+ /// <summary>
+ /// Gets the number of available processors
+ /// </summary>
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ internal static int ProcessorCount
+ {
+ get
+ {
+ int now = Environment.TickCount;
+ int procCount = s_processorCount;
+ if (procCount == 0 || (now - s_lastProcessorCountRefreshTicks) >= PROCESSOR_COUNT_REFRESH_INTERVAL_MS)
+ {
+ s_processorCount = procCount = Environment.ProcessorCount;
+ s_lastProcessorCountRefreshTicks = now;
+ }
+
+ Contract.Assert(procCount > 0 && procCount <= 64,
+ "Processor count not within the expected range (1 - 64).");
+
+ return procCount;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the current machine has only a single processor.
+ /// </summary>
+ internal static bool IsSingleProcessor
+ {
+ get { return ProcessorCount == 1; }
+ }
+ }
+
+ /// <summary>
+ /// A helper class to capture a start time using Environment.TickCout as a time in milliseconds, also updates a given timeout bu subtracting the current time from
+ /// the start time
+ /// </summary>
+ internal static class TimeoutHelper
+ {
+ /// <summary>
+ /// Returns the Environment.TickCount as a start time in milliseconds as a uint, TickCount tools over from postive to negative every ~ 25 days
+ /// then ~25 days to back to positive again, uint is sued to ignore the sign and double the range to 50 days
+ /// </summary>
+ /// <returns></returns>
+ public static uint GetTime()
+ {
+ return (uint)Environment.TickCount;
+ }
+
+ /// <summary>
+ /// Helper function to measure and update the elapsed time
+ /// </summary>
+ /// <param name="startTime"> The first time (in milliseconds) observed when the wait started</param>
+ /// <param name="originalWaitMillisecondsTimeout">The orginal wait timeoutout in milliseconds</param>
+ /// <returns>The new wait time in milliseconds, -1 if the time expired</returns>
+ public static int UpdateTimeOut(uint startTime, int originalWaitMillisecondsTimeout)
+ {
+ // The function must be called in case the time out is not infinite
+ Contract.Assert(originalWaitMillisecondsTimeout != Timeout.Infinite);
+
+ uint elapsedMilliseconds = (GetTime() - startTime);
+
+ // Check the elapsed milliseconds is greater than max int because this property is uint
+ if (elapsedMilliseconds > int.MaxValue)
+ {
+ return 0;
+ }
+
+ // Subtract the elapsed time from the current wait time
+ int currentWaitTimeout = originalWaitMillisecondsTimeout - (int)elapsedMilliseconds; ;
+ if (currentWaitTimeout <= 0)
+ {
+ return 0;
+ }
+
+ return currentWaitTimeout;
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/SynchronizationContext.cs b/src/mscorlib/src/System/Threading/SynchronizationContext.cs
new file mode 100644
index 0000000000..a3f28d1d73
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SynchronizationContext.cs
@@ -0,0 +1,320 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+/*============================================================
+**
+**
+**
+** Purpose: Capture synchronization semantics for asynchronous callbacks
+**
+**
+===========================================================*/
+
+namespace System.Threading
+{
+ using Microsoft.Win32.SafeHandles;
+ using System.Security.Permissions;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+#if FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Runtime.ExceptionServices;
+#endif // FEATURE_CORRUPTING_EXCEPTIONS
+ using System.Runtime;
+ using System.Runtime.Versioning;
+ using System.Runtime.ConstrainedExecution;
+ using System.Reflection;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+
+
+#if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+ [Flags]
+ enum SynchronizationContextProperties
+ {
+ None = 0,
+ RequireWaitNotification = 0x1
+ };
+#endif
+
+#if FEATURE_COMINTEROP && FEATURE_APPX
+ //
+ // This is implemented in System.Runtime.WindowsRuntime, allowing us to ask that assembly for a WinRT-specific SyncCtx.
+ // I'd like this to be an interface, or at least an abstract class - but neither seems to play nice with FriendAccessAllowed.
+ //
+ [FriendAccessAllowed]
+ [SecurityCritical]
+ internal class WinRTSynchronizationContextFactoryBase
+ {
+ [SecurityCritical]
+ public virtual SynchronizationContext Create(object coreDispatcher) {return null;}
+ }
+#endif //FEATURE_COMINTEROP
+
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags =SecurityPermissionFlag.ControlPolicy|SecurityPermissionFlag.ControlEvidence)]
+#endif
+ public class SynchronizationContext
+ {
+#if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+ SynchronizationContextProperties _props = SynchronizationContextProperties.None;
+#endif
+
+ public SynchronizationContext()
+ {
+ }
+
+#if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+
+ // helper delegate to statically bind to Wait method
+ private delegate int WaitDelegate(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
+
+ static Type s_cachedPreparedType1;
+ static Type s_cachedPreparedType2;
+ static Type s_cachedPreparedType3;
+ static Type s_cachedPreparedType4;
+ static Type s_cachedPreparedType5;
+
+ // protected so that only the derived sync context class can enable these flags
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "We never dereference s_cachedPreparedType*, so ordering is unimportant")]
+ protected void SetWaitNotificationRequired()
+ {
+ //
+ // Prepare the method so that it can be called in a reliable fashion when a wait is needed.
+ // This will obviously only make the Wait reliable if the Wait method is itself reliable. The only thing
+ // preparing the method here does is to ensure there is no failure point before the method execution begins.
+ //
+ // Preparing the method in this way is quite expensive, but only needs to be done once per type, per AppDomain.
+ // So we keep track of a few types we've already prepared in this AD. It is uncommon to have more than
+ // a few SynchronizationContext implementations, so we only cache the first five we encounter; this lets
+ // our cache be much faster than a more general cache might be. This is important, because this
+ // is a *very* hot code path for many WPF and WinForms apps.
+ //
+ Type type = this.GetType();
+ if (s_cachedPreparedType1 != type &&
+ s_cachedPreparedType2 != type &&
+ s_cachedPreparedType3 != type &&
+ s_cachedPreparedType4 != type &&
+ s_cachedPreparedType5 != type)
+ {
+ RuntimeHelpers.PrepareDelegate(new WaitDelegate(this.Wait));
+
+ if (s_cachedPreparedType1 == null) s_cachedPreparedType1 = type;
+ else if (s_cachedPreparedType2 == null) s_cachedPreparedType2 = type;
+ else if (s_cachedPreparedType3 == null) s_cachedPreparedType3 = type;
+ else if (s_cachedPreparedType4 == null) s_cachedPreparedType4 = type;
+ else if (s_cachedPreparedType5 == null) s_cachedPreparedType5 = type;
+ }
+
+ _props |= SynchronizationContextProperties.RequireWaitNotification;
+ }
+
+ public bool IsWaitNotificationRequired()
+ {
+ return ((_props & SynchronizationContextProperties.RequireWaitNotification) != 0);
+ }
+#endif
+
+
+ public virtual void Send(SendOrPostCallback d, Object state)
+ {
+ d(state);
+ }
+
+ public virtual void Post(SendOrPostCallback d, Object state)
+ {
+ ThreadPool.QueueUserWorkItem(new WaitCallback(d), state);
+ }
+
+
+ /// <summary>
+ /// Optional override for subclasses, for responding to notification that operation is starting.
+ /// </summary>
+ public virtual void OperationStarted()
+ {
+ }
+
+ /// <summary>
+ /// Optional override for subclasses, for responding to notification that operation has completed.
+ /// </summary>
+ public virtual void OperationCompleted()
+ {
+ }
+
+#if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+ // Method called when the CLR does a wait operation
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false)]
+ [PrePrepareMethod]
+ public virtual int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+ {
+ if (waitHandles == null)
+ {
+ throw new ArgumentNullException("waitHandles");
+ }
+ Contract.EndContractBlock();
+ return WaitHelper(waitHandles, waitAll, millisecondsTimeout);
+ }
+
+ // Static helper to which the above method can delegate to in order to get the default
+ // COM behavior.
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false)]
+ [PrePrepareMethod]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ protected static extern int WaitHelper(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout);
+#endif
+
+#if FEATURE_CORECLR
+
+ [System.Security.SecurityCritical]
+ public static void SetSynchronizationContext(SynchronizationContext syncContext)
+ {
+ Thread.CurrentThread.SynchronizationContext = syncContext;
+ }
+
+ [System.Security.SecurityCritical]
+ public static void SetThreadStaticContext(SynchronizationContext syncContext)
+ {
+ Thread.CurrentThread.SynchronizationContext = syncContext;
+ }
+
+ public static SynchronizationContext Current
+ {
+ get
+ {
+ SynchronizationContext context = Thread.CurrentThread.SynchronizationContext;
+
+#if FEATURE_APPX
+ if (context == null && AppDomain.IsAppXModel())
+ context = GetWinRTContext();
+#endif
+
+ return context;
+ }
+ }
+
+ // Get the last SynchronizationContext that was set explicitly (not flowed via ExecutionContext.Capture/Run)
+ internal static SynchronizationContext CurrentNoFlow
+ {
+ [FriendAccessAllowed]
+ get
+ {
+ return Current; // SC never flows
+ }
+ }
+
+#else //FEATURE_CORECLR
+
+ // set SynchronizationContext on the current thread
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static void SetSynchronizationContext(SynchronizationContext syncContext)
+ {
+ ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext();
+ ec.SynchronizationContext = syncContext;
+ ec.SynchronizationContextNoFlow = syncContext;
+ }
+
+ // Get the current SynchronizationContext on the current thread
+ public static SynchronizationContext Current
+ {
+ get
+ {
+ return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContext ?? GetThreadLocalContext();
+ }
+ }
+
+ // Get the last SynchronizationContext that was set explicitly (not flowed via ExecutionContext.Capture/Run)
+ internal static SynchronizationContext CurrentNoFlow
+ {
+ [FriendAccessAllowed]
+ get
+ {
+ return Thread.CurrentThread.GetExecutionContextReader().SynchronizationContextNoFlow ?? GetThreadLocalContext();
+ }
+ }
+
+ private static SynchronizationContext GetThreadLocalContext()
+ {
+ SynchronizationContext context = null;
+
+#if FEATURE_APPX
+ if (context == null && AppDomain.IsAppXModel())
+ context = GetWinRTContext();
+#endif
+
+ return context;
+ }
+
+#endif //FEATURE_CORECLR
+
+#if FEATURE_APPX
+ [SecuritySafeCritical]
+ private static SynchronizationContext GetWinRTContext()
+ {
+ Contract.Assert(Environment.IsWinRTSupported);
+ Contract.Assert(AppDomain.IsAppXModel());
+
+ //
+ // We call into the VM to get the dispatcher. This is because:
+ //
+ // a) We cannot call the WinRT APIs directly from mscorlib, because we don't have the fancy projections here.
+ // b) We cannot call into System.Runtime.WindowsRuntime here, because we don't want to load that assembly
+ // into processes that don't need it (for performance reasons).
+ //
+ // So, we check the VM to see if the current thread has a dispatcher; if it does, we pass that along to
+ // System.Runtime.WindowsRuntime to get a corresponding SynchronizationContext.
+ //
+ object dispatcher = GetWinRTDispatcherForCurrentThread();
+ if (dispatcher != null)
+ return GetWinRTSynchronizationContextFactory().Create(dispatcher);
+
+ return null;
+ }
+
+ [SecurityCritical]
+ static WinRTSynchronizationContextFactoryBase s_winRTContextFactory;
+
+ [SecurityCritical]
+ private static WinRTSynchronizationContextFactoryBase GetWinRTSynchronizationContextFactory()
+ {
+ //
+ // Since we can't directly reference System.Runtime.WindowsRuntime from mscorlib, we have to get the factory via reflection.
+ // It would be better if we could just implement WinRTSynchronizationContextFactory in mscorlib, but we can't, because
+ // we can do very little with WinRT stuff in mscorlib.
+ //
+ WinRTSynchronizationContextFactoryBase factory = s_winRTContextFactory;
+ if (factory == null)
+ {
+ Type factoryType = Type.GetType("System.Threading.WinRTSynchronizationContextFactory, " + AssemblyRef.SystemRuntimeWindowsRuntime, true);
+ s_winRTContextFactory = factory = (WinRTSynchronizationContextFactoryBase)Activator.CreateInstance(factoryType, true);
+ }
+ return factory;
+ }
+
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SecurityCritical]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Interface)]
+ private static extern object GetWinRTDispatcherForCurrentThread();
+#endif //FEATURE_APPX
+
+
+ // helper to Clone this SynchronizationContext,
+ public virtual SynchronizationContext CreateCopy()
+ {
+ // the CLR dummy has an empty clone function - no member data
+ return new SynchronizationContext();
+ }
+
+#if FEATURE_SYNCHRONIZATIONCONTEXT_WAIT
+ [System.Security.SecurityCritical] // auto-generated
+ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
+ {
+ return syncContext.Wait(waitHandles, waitAll, millisecondsTimeout);
+ }
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/SynchronizationLockException.cs b/src/mscorlib/src/System/Threading/SynchronizationLockException.cs
new file mode 100644
index 0000000000..0610a6063d
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/SynchronizationLockException.cs
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Wait(), Notify() or NotifyAll() was called from an unsynchronized
+** block of code.
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class SynchronizationLockException : SystemException {
+ public SynchronizationLockException()
+ : base(Environment.GetResourceString("Arg_SynchronizationLockException")) {
+ SetErrorCode(__HResults.COR_E_SYNCHRONIZATIONLOCK);
+ }
+
+ public SynchronizationLockException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_SYNCHRONIZATIONLOCK);
+ }
+
+ public SynchronizationLockException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_SYNCHRONIZATIONLOCK);
+ }
+
+ protected SynchronizationLockException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+
+}
+
+
diff --git a/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs b/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
new file mode 100644
index 0000000000..c29b11a922
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/AsyncCausalityTracer.cs
@@ -0,0 +1,295 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+
+using System;
+using System.Security;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+#if FEATURE_COMINTEROP
+using System.Runtime.InteropServices.WindowsRuntime;
+
+using WFD = Windows.Foundation.Diagnostics;
+#endif
+
+
+namespace System.Threading.Tasks
+{
+
+ [FriendAccessAllowed]
+ internal enum CausalityTraceLevel
+ {
+#if FEATURE_COMINTEROP
+ Required = WFD.CausalityTraceLevel.Required,
+ Important = WFD.CausalityTraceLevel.Important,
+ Verbose = WFD.CausalityTraceLevel.Verbose
+#else
+ Required,
+ Important,
+ Verbose
+#endif
+ }
+
+ [FriendAccessAllowed]
+ internal enum AsyncCausalityStatus
+ {
+#if FEATURE_COMINTEROP
+ Canceled = WFD.AsyncCausalityStatus.Canceled,
+ Completed = WFD.AsyncCausalityStatus.Completed,
+ Error = WFD.AsyncCausalityStatus.Error,
+ Started = WFD.AsyncCausalityStatus.Started
+#else
+ Started,
+ Completed,
+ Canceled,
+ Error
+#endif
+ }
+
+ internal enum CausalityRelation
+ {
+#if FEATURE_COMINTEROP
+ AssignDelegate = WFD.CausalityRelation.AssignDelegate,
+ Join = WFD.CausalityRelation.Join,
+ Choice = WFD.CausalityRelation.Choice,
+ Cancel = WFD.CausalityRelation.Cancel,
+ Error = WFD.CausalityRelation.Error
+#else
+ AssignDelegate,
+ Join,
+ Choice,
+ Cancel,
+ Error
+#endif
+ }
+
+ internal enum CausalitySynchronousWork
+ {
+#if FEATURE_COMINTEROP
+ CompletionNotification = WFD.CausalitySynchronousWork.CompletionNotification,
+ ProgressNotification = WFD.CausalitySynchronousWork.ProgressNotification,
+ Execution = WFD.CausalitySynchronousWork.Execution
+#else
+ CompletionNotification,
+ ProgressNotification,
+ Execution
+#endif
+ }
+
+ [FriendAccessAllowed]
+ internal static class AsyncCausalityTracer
+ {
+ static internal void EnableToETW(bool enabled)
+ {
+#if FEATURE_COMINTEROP
+ if (enabled)
+ f_LoggingOn |= Loggers.ETW;
+ else
+ f_LoggingOn &= ~Loggers.ETW;
+#endif
+ }
+
+ [FriendAccessAllowed]
+ internal static bool LoggingOn
+ {
+ [FriendAccessAllowed]
+ get
+ {
+#if FEATURE_COMINTEROP
+ return f_LoggingOn != 0;
+#else
+ return false;
+#endif
+ }
+ }
+
+#if FEATURE_COMINTEROP
+ //s_PlatformId = {4B0171A6-F3D0-41A0-9B33-02550652B995}
+ private static readonly Guid s_PlatformId = new Guid(0x4B0171A6, 0xF3D0, 0x41A0, 0x9B, 0x33, 0x02, 0x55, 0x06, 0x52, 0xB9, 0x95);
+
+ //Indicates this information comes from the BCL Library
+ private const WFD.CausalitySource s_CausalitySource = WFD.CausalitySource.Library;
+
+ //Lazy initialize the actual factory
+ private static WFD.IAsyncCausalityTracerStatics s_TracerFactory;
+
+ // The loggers that this Tracer knows about.
+ [Flags]
+ private enum Loggers : byte {
+ CausalityTracer = 1,
+ ETW = 2
+ }
+
+
+ //We receive the actual value for these as a callback
+ private static Loggers f_LoggingOn; //assumes false by default
+
+ // The precise static constructor will run first time somebody attempts to access this class
+ [SecuritySafeCritical]
+ static AsyncCausalityTracer()
+ {
+ if (!Environment.IsWinRTSupported) return;
+
+ //COM Class Id
+ string ClassId = "Windows.Foundation.Diagnostics.AsyncCausalityTracer";
+
+ //COM Interface GUID {50850B26-267E-451B-A890-AB6A370245EE}
+ Guid guid = new Guid(0x50850B26, 0x267E, 0x451B, 0xA8, 0x90, 0XAB, 0x6A, 0x37, 0x02, 0x45, 0xEE);
+
+ Object factory = null;
+
+ try
+ {
+ int hresult = Microsoft.Win32.UnsafeNativeMethods.RoGetActivationFactory(ClassId, ref guid, out factory);
+
+ if (hresult < 0 || factory == null) return; //This prevents having an exception thrown in case IAsyncCausalityTracerStatics isn't registered.
+
+ s_TracerFactory = (WFD.IAsyncCausalityTracerStatics)factory;
+
+ EventRegistrationToken token = s_TracerFactory.add_TracingStatusChanged(new EventHandler<WFD.TracingStatusChangedEventArgs>(TracingStatusChangedHandler));
+ Contract.Assert(token != default(EventRegistrationToken), "EventRegistrationToken is null");
+ }
+ catch (Exception ex)
+ {
+ // Although catching generic Exception is not recommended, this file is one exception
+ // since we don't want to propagate any kind of exception to the user since all we are
+ // doing here depends on internal state.
+ LogAndDisable(ex);
+ }
+
+ }
+
+ [SecuritySafeCritical]
+ private static void TracingStatusChangedHandler(Object sender, WFD.TracingStatusChangedEventArgs args)
+ {
+ if (args.Enabled)
+ f_LoggingOn |= Loggers.CausalityTracer;
+ else
+ f_LoggingOn &= ~Loggers.CausalityTracer;
+ }
+#endif
+
+ //
+ // The TraceXXX methods should be called only if LoggingOn property returned true
+ //
+
+ [FriendAccessAllowed]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Tracking is slow path. Disable inlining for it.
+ internal static void TraceOperationCreation(CausalityTraceLevel traceLevel, int taskId, string operationName, ulong relatedContext)
+ {
+#if FEATURE_COMINTEROP
+ try
+ {
+ if ((f_LoggingOn & Loggers.ETW) != 0)
+ TplEtwProvider.Log.TraceOperationBegin(taskId, operationName, (long) relatedContext);
+ if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
+ s_TracerFactory.TraceOperationCreation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), operationName, relatedContext);
+ }
+ catch(Exception ex)
+ {
+ //view function comment
+ LogAndDisable(ex);
+ }
+#endif
+ }
+
+ [FriendAccessAllowed]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ internal static void TraceOperationCompletion(CausalityTraceLevel traceLevel, int taskId, AsyncCausalityStatus status)
+ {
+#if FEATURE_COMINTEROP
+ try
+ {
+ if ((f_LoggingOn & Loggers.ETW) != 0)
+ TplEtwProvider.Log.TraceOperationEnd(taskId, status);
+ if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
+ s_TracerFactory.TraceOperationCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.AsyncCausalityStatus)status);
+ }
+ catch(Exception ex)
+ {
+ //view function comment
+ LogAndDisable(ex);
+ }
+#endif
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ internal static void TraceOperationRelation(CausalityTraceLevel traceLevel, int taskId, CausalityRelation relation)
+ {
+#if FEATURE_COMINTEROP
+ try
+ {
+ if ((f_LoggingOn & Loggers.ETW) != 0)
+ TplEtwProvider.Log.TraceOperationRelation(taskId, relation);
+ if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
+ s_TracerFactory.TraceOperationRelation((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalityRelation)relation);
+ }
+ catch(Exception ex)
+ {
+ //view function comment
+ LogAndDisable(ex);
+ }
+#endif
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ internal static void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, int taskId, CausalitySynchronousWork work)
+ {
+#if FEATURE_COMINTEROP
+ try
+ {
+ if ((f_LoggingOn & Loggers.ETW) != 0)
+ TplEtwProvider.Log.TraceSynchronousWorkBegin(taskId, work);
+ if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
+ s_TracerFactory.TraceSynchronousWorkStart((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, s_PlatformId, GetOperationId((uint)taskId), (WFD.CausalitySynchronousWork)work);
+ }
+ catch(Exception ex)
+ {
+ //view function comment
+ LogAndDisable(ex);
+ }
+#endif
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)]
+ internal static void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySynchronousWork work)
+ {
+#if FEATURE_COMINTEROP
+ try
+ {
+ if ((f_LoggingOn & Loggers.ETW) != 0)
+ TplEtwProvider.Log.TraceSynchronousWorkEnd(work);
+ if ((f_LoggingOn & Loggers.CausalityTracer) != 0)
+ s_TracerFactory.TraceSynchronousWorkCompletion((WFD.CausalityTraceLevel)traceLevel, s_CausalitySource, (WFD.CausalitySynchronousWork)work);
+ }
+ catch(Exception ex)
+ {
+ //view function comment
+ LogAndDisable(ex);
+ }
+#endif
+ }
+
+#if FEATURE_COMINTEROP
+ //fix for 796185: leaking internal exceptions to customers,
+ //we should catch and log exceptions but never propagate them.
+ private static void LogAndDisable(Exception ex)
+ {
+ f_LoggingOn = 0;
+ Debugger.Log(0, "AsyncCausalityTracer", ex.ToString());
+ }
+#endif
+
+ private static ulong GetOperationId(uint taskId)
+ {
+ return (((ulong)AppDomain.CurrentDomain.Id) << 32) + taskId;
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
new file mode 100644
index 0000000000..05e6dbf1a9
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/BeginEndAwaitableAdapter.cs
@@ -0,0 +1,157 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Runtime.CompilerServices;
+using System.Security;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Threading.Tasks {
+
+/// <summary>
+/// Provides an adapter to make Begin/End pairs awaitable.
+/// In general, Task.Factory.FromAsync should be used for this purpose.
+/// However, for cases where absolute minimal overhead is required, this type
+/// may be used to making APM pairs awaitable while minimizing overhead.
+/// (APM = Asynchronous Programming Model or the Begin/End pattern.)
+/// </summary>
+/// <remarks>
+/// This instance may be reused repeatedly. However, it must only be used
+/// by a single APM invocation at a time. It's state will automatically be reset
+/// when the await completes.
+/// </remarks>
+/// <example>
+/// Usage sample:
+/// <code>
+/// static async Task CopyStreamAsync(Stream source, Stream dest) {
+///
+/// BeginEndAwaitableAdapter adapter = new BeginEndAwaitableAdapter();
+/// Byte[] buffer = new Byte[0x1000];
+///
+/// while (true) {
+///
+/// source.BeginRead(buffer, 0, buffer.Length, BeginEndAwaitableAdapter.Callback, adapter);
+/// Int32 numRead = source.EndRead(await adapter);
+/// if (numRead == 0)
+/// break;
+///
+/// dest.BeginWrite(buffer, 0, numRead, BeginEndAwaitableAdapter.Callback, adapter);
+/// dest.EndWrite(await adapter);
+/// }
+/// }
+/// </code>
+/// </example>
+internal sealed class BeginEndAwaitableAdapter : ICriticalNotifyCompletion {
+
+ /// <summary>A sentinel marker used to communicate between OnCompleted and the APM callback
+ /// that the callback has already run, and thus OnCompleted needs to execute the callback.</summary>
+ private readonly static Action CALLBACK_RAN = () => { };
+
+ /// <summary>The IAsyncResult for the APM operation.</summary>
+ private IAsyncResult _asyncResult;
+
+ /// <summary>The continuation delegate provided to the awaiter.</summary>
+ private Action _continuation;
+
+
+ /// <summary>A callback to be passed as the AsyncCallback to an APM pair.
+ /// It expects that an BeginEndAwaitableAdapter instance was supplied to the APM Begin method as the object state.</summary>
+ public readonly static AsyncCallback Callback = (asyncResult) => {
+
+ Contract.Assert(asyncResult != null);
+ Contract.Assert(asyncResult.IsCompleted);
+ Contract.Assert(asyncResult.AsyncState is BeginEndAwaitableAdapter);
+
+ // Get the adapter object supplied as the "object state" to the Begin method
+ BeginEndAwaitableAdapter adapter = (BeginEndAwaitableAdapter) asyncResult.AsyncState;
+
+ // Store the IAsyncResult into it so that it's available to the awaiter
+ adapter._asyncResult = asyncResult;
+
+ // If the _continuation has already been set to the actual continuation by OnCompleted, then invoke the continuation.
+ // Set _continuation to the CALLBACK_RAN sentinel so that IsCompleted returns true and OnCompleted sees the sentinel
+ // and knows to invoke the callback.
+ // Due to some known incorrect implementations of IAsyncResult in the Framework where CompletedSynchronously is lazily
+ // set to true if it is first invoked after IsCompleted is true, we cannot rely here on CompletedSynchronously for
+ // synchronization between the caller and the callback, and thus do not use CompletedSynchronously at all.
+ Action continuation = Interlocked.Exchange(ref adapter._continuation, CALLBACK_RAN);
+ if (continuation != null) {
+
+ Contract.Assert(continuation != CALLBACK_RAN);
+ continuation();
+ }
+ };
+
+
+ /// <summary>Gets an awaiter.</summary>
+ /// <returns>Returns itself as the awaiter.</returns>
+ public BeginEndAwaitableAdapter GetAwaiter() {
+
+ return this;
+ }
+
+
+ /// <summary>Gets whether the awaited APM operation completed.</summary>
+ public bool IsCompleted {
+ get {
+
+ // We are completed if the callback was called and it set the continuation to the CALLBACK_RAN sentinel.
+ // If the operation completes asynchronously, there's still a chance we'll see CALLBACK_RAN here, in which
+ // case we're still good to keep running synchronously.
+ return (_continuation == CALLBACK_RAN);
+ }
+ }
+
+ /// <summary>Schedules the continuation to run when the operation completes.</summary>
+ /// <param name="continuation">The continuation.</param>
+ [SecurityCritical]
+ public void UnsafeOnCompleted(Action continuation) {
+
+ Contract.Assert(continuation != null);
+ OnCompleted(continuation);
+ }
+
+
+ /// <summary>Schedules the continuation to run when the operation completes.</summary>
+ /// <param name="continuation">The continuation.</param>
+ public void OnCompleted(Action continuation) {
+
+ Contract.Assert(continuation != null);
+
+ // If the continuation field is null, then set it to be the target continuation
+ // so that when the operation completes, it'll invoke the continuation. If it's non-null,
+ // it was already set to the CALLBACK_RAN-sentinel by the Callback, in which case we hit a very rare race condition
+ // where the operation didn't complete synchronously but completed asynchronously between our
+ // calls to IsCompleted and OnCompleted... in that case, just schedule a task to run the continuation.
+ if (_continuation == CALLBACK_RAN
+ || Interlocked.CompareExchange(ref _continuation, continuation, null) == CALLBACK_RAN) {
+
+ Task.Run(continuation); // must run async at this point, or else we'd risk stack diving
+ }
+ }
+
+
+ /// <summary>Gets the IAsyncResult for the APM operation after the operation completes, and then resets the adapter.</summary>
+ /// <returns>The IAsyncResult for the operation.</returns>
+ public IAsyncResult GetResult() {
+
+ Contract.Assert(_asyncResult != null && _asyncResult.IsCompleted);
+
+ // Get the IAsyncResult
+ IAsyncResult result = _asyncResult;
+
+ // Reset the adapter
+ _asyncResult = null;
+ _continuation = null;
+
+ // Return the result
+ return result;
+ }
+
+} // class BeginEndAwaitableAdapter
+
+} // namespace
diff --git a/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
new file mode 100644
index 0000000000..cb4a22bb2b
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs
@@ -0,0 +1,795 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A pair of schedulers that together support concurrent (reader) / exclusive (writer)
+// task scheduling. Using just the exclusive scheduler can be used to simulate a serial
+// processing queue, and using just the concurrent scheduler with a specified
+// MaximumConcurrentlyLevel can be used to achieve a MaxDegreeOfParallelism across
+// a bunch of tasks, parallel loops, dataflow blocks, etc.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Contracts;
+using System.Security;
+using System.Security.Permissions;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides concurrent and exclusive task schedulers that coordinate to execute
+ /// tasks while ensuring that concurrent tasks may run concurrently and exclusive tasks never do.
+ /// </summary>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerDisplay("Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger}")]
+ [DebuggerTypeProxy(typeof(ConcurrentExclusiveSchedulerPair.DebugView))]
+ public class ConcurrentExclusiveSchedulerPair
+ {
+ /// <summary>A dictionary mapping thread ID to a processing mode to denote what kinds of tasks are currently being processed on this thread.</summary>
+ private readonly ConcurrentDictionary<int, ProcessingMode> m_threadProcessingMapping = new ConcurrentDictionary<int, ProcessingMode>();
+ /// <summary>The scheduler used to queue and execute "concurrent" tasks that may run concurrently with other concurrent tasks.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_concurrentTaskScheduler;
+ /// <summary>The scheduler used to queue and execute "exclusive" tasks that must run exclusively while no other tasks for this pair are running.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_exclusiveTaskScheduler;
+ /// <summary>The underlying task scheduler to which all work should be scheduled.</summary>
+ private readonly TaskScheduler m_underlyingTaskScheduler;
+ /// <summary>
+ /// The maximum number of tasks allowed to run concurrently. This only applies to concurrent tasks,
+ /// since exlusive tasks are inherently limited to 1.
+ /// </summary>
+ private readonly int m_maxConcurrencyLevel;
+ /// <summary>The maximum number of tasks we can process before recyling our runner tasks.</summary>
+ private readonly int m_maxItemsPerTask;
+ /// <summary>
+ /// If positive, it represents the number of concurrently running concurrent tasks.
+ /// If negative, it means an exclusive task has been scheduled.
+ /// If 0, nothing has been scheduled.
+ /// </summary>
+ private int m_processingCount;
+ /// <summary>Completion state for a task representing the completion of this pair.</summary>
+ /// <remarks>Lazily-initialized only if the scheduler pair is shutting down or if the Completion is requested.</remarks>
+ private CompletionState m_completionState;
+
+ /// <summary>A constant value used to signal unlimited processing.</summary>
+ private const int UNLIMITED_PROCESSING = -1;
+ /// <summary>Constant used for m_processingCount to indicate that an exclusive task is being processed.</summary>
+ private const int EXCLUSIVE_PROCESSING_SENTINEL = -1;
+ /// <summary>Default MaxItemsPerTask to use for processing if none is specified.</summary>
+ private const int DEFAULT_MAXITEMSPERTASK = UNLIMITED_PROCESSING;
+ /// <summary>Default MaxConcurrencyLevel is the processor count if not otherwise specified.</summary>
+ private static Int32 DefaultMaxConcurrencyLevel { get { return Environment.ProcessorCount; } }
+
+ /// <summary>Gets the sync obj used to protect all state on this instance.</summary>
+ private object ValueLock { get { return m_threadProcessingMapping; } }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair.
+ /// </summary>
+ public ConcurrentExclusiveSchedulerPair() :
+ this(TaskScheduler.Default, DefaultMaxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK) { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler) :
+ this(taskScheduler, DefaultMaxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK) { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum concurrency level.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ /// <param name="maxConcurrencyLevel">The maximum number of tasks to run concurrently.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler, int maxConcurrencyLevel) :
+ this(taskScheduler, maxConcurrencyLevel, DEFAULT_MAXITEMSPERTASK) { }
+
+ /// <summary>
+ /// Initializes the ConcurrentExclusiveSchedulerPair to target the specified scheduler with a maximum
+ /// concurrency level and a maximum number of scheduled tasks that may be processed as a unit.
+ /// </summary>
+ /// <param name="taskScheduler">The target scheduler on which this pair should execute.</param>
+ /// <param name="maxConcurrencyLevel">The maximum number of tasks to run concurrently.</param>
+ /// <param name="maxItemsPerTask">The maximum number of tasks to process for each underlying scheduled task used by the pair.</param>
+ public ConcurrentExclusiveSchedulerPair(TaskScheduler taskScheduler, int maxConcurrencyLevel, int maxItemsPerTask)
+ {
+ // Validate arguments
+ if (taskScheduler == null) throw new ArgumentNullException("taskScheduler");
+ if (maxConcurrencyLevel == 0 || maxConcurrencyLevel < -1) throw new ArgumentOutOfRangeException("maxConcurrencyLevel");
+ if (maxItemsPerTask == 0 || maxItemsPerTask < -1) throw new ArgumentOutOfRangeException("maxItemsPerTask");
+ Contract.EndContractBlock();
+
+ // Store configuration
+ m_underlyingTaskScheduler = taskScheduler;
+ m_maxConcurrencyLevel = maxConcurrencyLevel;
+ m_maxItemsPerTask = maxItemsPerTask;
+
+ // Downgrade to the underlying scheduler's max degree of parallelism if it's lower than the user-supplied level
+ int mcl = taskScheduler.MaximumConcurrencyLevel;
+ if (mcl > 0 && mcl < m_maxConcurrencyLevel) m_maxConcurrencyLevel = mcl;
+
+ // Treat UNLIMITED_PROCESSING/-1 for both MCL and MIPT as the biggest possible value so that we don't
+ // have to special case UNLIMITED_PROCESSING later on in processing.
+ if (m_maxConcurrencyLevel == UNLIMITED_PROCESSING) m_maxConcurrencyLevel = Int32.MaxValue;
+ if (m_maxItemsPerTask == UNLIMITED_PROCESSING) m_maxItemsPerTask = Int32.MaxValue;
+
+ // Create the concurrent/exclusive schedulers for this pair
+ m_exclusiveTaskScheduler = new ConcurrentExclusiveTaskScheduler(this, 1, ProcessingMode.ProcessingExclusiveTask);
+ m_concurrentTaskScheduler = new ConcurrentExclusiveTaskScheduler(this, m_maxConcurrencyLevel, ProcessingMode.ProcessingConcurrentTasks);
+ }
+
+ /// <summary>Informs the scheduler pair that it should not accept any more tasks.</summary>
+ /// <remarks>
+ /// Calling <see cref="Complete"/> is optional, and it's only necessary if the <see cref="Completion"/>
+ /// will be relied on for notification of all processing being completed.
+ /// </remarks>
+ public void Complete()
+ {
+ lock (ValueLock)
+ {
+ if (!CompletionRequested)
+ {
+ RequestCompletion();
+ CleanupStateIfCompletingAndQuiesced();
+ }
+ }
+ }
+
+ /// <summary>Gets a <see cref="System.Threading.Tasks.Task"/> that will complete when the scheduler has completed processing.</summary>
+ public Task Completion
+ {
+ // ValueLock not needed, but it's ok if it's held
+ get { return EnsureCompletionStateInitialized().Task; }
+ }
+
+ /// <summary>Gets the lazily-initialized completion state.</summary>
+ private CompletionState EnsureCompletionStateInitialized()
+ {
+ // ValueLock not needed, but it's ok if it's held
+ return LazyInitializer.EnsureInitialized(ref m_completionState, () => new CompletionState());
+ }
+
+ /// <summary>Gets whether completion has been requested.</summary>
+ private bool CompletionRequested
+ {
+ // ValueLock not needed, but it's ok if it's held
+ get { return m_completionState != null && Volatile.Read(ref m_completionState.m_completionRequested); }
+ }
+
+ /// <summary>Sets that completion has been requested.</summary>
+ private void RequestCompletion()
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+ EnsureCompletionStateInitialized().m_completionRequested = true;
+ }
+
+ /// <summary>
+ /// Cleans up state if and only if there's no processing currently happening
+ /// and no more to be done later.
+ /// </summary>
+ private void CleanupStateIfCompletingAndQuiesced()
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+ if (ReadyToComplete) CompleteTaskAsync();
+ }
+
+ /// <summary>Gets whether the pair is ready to complete.</summary>
+ private bool ReadyToComplete
+ {
+ get
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // We can only complete if completion has been requested and no processing is currently happening.
+ if (!CompletionRequested || m_processingCount != 0) return false;
+
+ // Now, only allow shutdown if an exception occurred or if there are no more tasks to process.
+ var cs = EnsureCompletionStateInitialized();
+ return
+ (cs.m_exceptions != null && cs.m_exceptions.Count > 0) ||
+ (m_concurrentTaskScheduler.m_tasks.IsEmpty && m_exclusiveTaskScheduler.m_tasks.IsEmpty);
+ }
+ }
+
+ /// <summary>Completes the completion task asynchronously.</summary>
+ private void CompleteTaskAsync()
+ {
+ Contract.Requires(ReadyToComplete, "The block must be ready to complete to be here.");
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // Ensure we only try to complete once, then schedule completion
+ // in order to escape held locks and the caller's context
+ var cs = EnsureCompletionStateInitialized();
+ if (!cs.m_completionQueued)
+ {
+ cs.m_completionQueued = true;
+ ThreadPool.QueueUserWorkItem(state =>
+ {
+ var localCs = (CompletionState)state; // don't use 'cs', as it'll force a closure
+ Contract.Assert(!localCs.Task.IsCompleted, "Completion should only happen once.");
+
+ var exceptions = localCs.m_exceptions;
+ bool success = (exceptions != null && exceptions.Count > 0) ?
+ localCs.TrySetException(exceptions) :
+ localCs.TrySetResult(default(VoidTaskResult));
+ Contract.Assert(success, "Expected to complete completion task.");
+ }, cs);
+ }
+ }
+
+ /// <summary>Initiatites scheduler shutdown due to a worker task faulting..</summary>
+ /// <param name="faultedTask">The faulted worker task that's initiating the shutdown.</param>
+ private void FaultWithTask(Task faultedTask)
+ {
+ Contract.Requires(faultedTask != null && faultedTask.IsFaulted && faultedTask.Exception.InnerExceptions.Count > 0,
+ "Needs a task in the faulted state and thus with exceptions.");
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // Store the faulted task's exceptions
+ var cs = EnsureCompletionStateInitialized();
+ if (cs.m_exceptions == null) cs.m_exceptions = new List<Exception>();
+ cs.m_exceptions.AddRange(faultedTask.Exception.InnerExceptions);
+
+ // Now that we're doomed, request completion
+ RequestCompletion();
+ }
+
+ /// <summary>
+ /// Gets a TaskScheduler that can be used to schedule tasks to this pair
+ /// that may run concurrently with other tasks on this pair.
+ /// </summary>
+ public TaskScheduler ConcurrentScheduler { get { return m_concurrentTaskScheduler; } }
+ /// <summary>
+ /// Gets a TaskScheduler that can be used to schedule tasks to this pair
+ /// that must run exclusively with regards to other tasks on this pair.
+ /// </summary>
+ public TaskScheduler ExclusiveScheduler { get { return m_exclusiveTaskScheduler; } }
+
+ /// <summary>Gets the number of tasks waiting to run concurrently.</summary>
+ /// <remarks>This does not take the necessary lock, as it's only called from under the debugger.</remarks>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int ConcurrentTaskCountForDebugger { get { return m_concurrentTaskScheduler.m_tasks.Count; } }
+
+ /// <summary>Gets the number of tasks waiting to run exclusively.</summary>
+ /// <remarks>This does not take the necessary lock, as it's only called from under the debugger.</remarks>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int ExclusiveTaskCountForDebugger { get { return m_exclusiveTaskScheduler.m_tasks.Count; } }
+
+ /// <summary>Notifies the pair that new work has arrived to be processed.</summary>
+ /// <param name="fairly">Whether tasks should be scheduled fairly with regards to other tasks.</param>
+ /// <remarks>Must only be called while holding the lock.</remarks>
+ [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+ [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals")]
+ [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
+ private void ProcessAsyncIfNecessary(bool fairly = false)
+ {
+ ContractAssertMonitorStatus(ValueLock, held: true);
+
+ // If the current processing count is >= 0, we can potentially launch further processing.
+ if (m_processingCount >= 0)
+ {
+ // We snap whether there are any exclusive tasks or concurrent tasks waiting.
+ // (We grab the concurrent count below only once we know we need it.)
+ // With processing happening concurrent to this operation, this data may
+ // immediately be out of date, but it can only go from non-empty
+ // to empty and not the other way around. As such, this is safe,
+ // as worst case is we'll schedule an extra task when we didn't
+ // otherwise need to, and we'll just eat its overhead.
+ bool exclusiveTasksAreWaiting = !m_exclusiveTaskScheduler.m_tasks.IsEmpty;
+
+ // If there's no processing currently happening but there are waiting exclusive tasks,
+ // let's start processing those exclusive tasks.
+ Task processingTask = null;
+ if (m_processingCount == 0 && exclusiveTasksAreWaiting)
+ {
+ // Launch exclusive task processing
+ m_processingCount = EXCLUSIVE_PROCESSING_SENTINEL; // -1
+ try
+ {
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessExclusiveTasks(), this,
+ default(CancellationToken), GetCreationOptionsForTask(fairly));
+ processingTask.Start(m_underlyingTaskScheduler);
+ // When we call Start, if the underlying scheduler throws in QueueTask, TPL will fault the task and rethrow
+ // the exception. To deal with that, we need a reference to the task object, so that we can observe its exception.
+ // Hence, we separate creation and starting, so that we can store a reference to the task before we attempt QueueTask.
+ }
+ catch
+ {
+ m_processingCount = 0;
+ FaultWithTask(processingTask);
+ }
+ }
+ // If there are no waiting exclusive tasks, there are concurrent tasks, and we haven't reached our maximum
+ // concurrency level for processing, let's start processing more concurrent tasks.
+ else
+ {
+ int concurrentTasksWaitingCount = m_concurrentTaskScheduler.m_tasks.Count;
+
+ if (concurrentTasksWaitingCount > 0 && !exclusiveTasksAreWaiting && m_processingCount < m_maxConcurrencyLevel)
+ {
+ // Launch concurrent task processing, up to the allowed limit
+ for (int i = 0; i < concurrentTasksWaitingCount && m_processingCount < m_maxConcurrencyLevel; ++i)
+ {
+ ++m_processingCount;
+ try
+ {
+ processingTask = new Task(thisPair => ((ConcurrentExclusiveSchedulerPair)thisPair).ProcessConcurrentTasks(), this,
+ default(CancellationToken), GetCreationOptionsForTask(fairly));
+ processingTask.Start(m_underlyingTaskScheduler); // See above logic for why we use new + Start rather than StartNew
+ }
+ catch
+ {
+ --m_processingCount;
+ FaultWithTask(processingTask);
+ }
+ }
+ }
+ }
+
+ // Check to see if all tasks have completed and if completion has been requested.
+ CleanupStateIfCompletingAndQuiesced();
+ }
+ else Contract.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing count must be the sentinel if it's not >= 0.");
+ }
+
+ /// <summary>
+ /// Processes exclusive tasks serially until either there are no more to process
+ /// or we've reached our user-specified maximum limit.
+ /// </summary>
+ private void ProcessExclusiveTasks()
+ {
+ Contract.Requires(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "Processing exclusive tasks requires being in exclusive mode.");
+ Contract.Requires(!m_exclusiveTaskScheduler.m_tasks.IsEmpty, "Processing exclusive tasks requires tasks to be processed.");
+ ContractAssertMonitorStatus(ValueLock, held: false);
+ try
+ {
+ // Note that we're processing exclusive tasks on the current thread
+ Contract.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId),
+ "This thread should not yet be involved in this pair's processing.");
+ m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingExclusiveTask;
+
+ // Process up to the maximum number of items per task allowed
+ for (int i = 0; i < m_maxItemsPerTask; i++)
+ {
+ // Get the next available exclusive task. If we can't find one, bail.
+ Task exclusiveTask;
+ if (!m_exclusiveTaskScheduler.m_tasks.TryDequeue(out exclusiveTask)) break;
+
+ // Execute the task. If the scheduler was previously faulted,
+ // this task could have been faulted when it was queued; ignore such tasks.
+ if (!exclusiveTask.IsFaulted) m_exclusiveTaskScheduler.ExecuteTask(exclusiveTask);
+ }
+ }
+ finally
+ {
+ // We're no longer processing exclusive tasks on the current thread
+ ProcessingMode currentMode;
+ m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode);
+ Contract.Assert(currentMode == ProcessingMode.ProcessingExclusiveTask,
+ "Somehow we ended up escaping exclusive mode.");
+
+ lock (ValueLock)
+ {
+ // When this task was launched, we tracked it by setting m_processingCount to WRITER_IN_PROGRESS.
+ // now reset it to 0. Then check to see whether there's more processing to be done.
+ // There might be more concurrent tasks available, for example, if concurrent tasks arrived
+ // after we exited the loop, or if we exited the loop while concurrent tasks were still
+ // available but we hit our maxItemsPerTask limit.
+ Contract.Assert(m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL, "The processing mode should not have deviated from exclusive.");
+ m_processingCount = 0;
+ ProcessAsyncIfNecessary(true);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Processes concurrent tasks serially until either there are no more to process,
+ /// we've reached our user-specified maximum limit, or exclusive tasks have arrived.
+ /// </summary>
+ private void ProcessConcurrentTasks()
+ {
+ Contract.Requires(m_processingCount > 0, "Processing concurrent tasks requires us to be in concurrent mode.");
+ ContractAssertMonitorStatus(ValueLock, held: false);
+ try
+ {
+ // Note that we're processing concurrent tasks on the current thread
+ Contract.Assert(!m_threadProcessingMapping.ContainsKey(Thread.CurrentThread.ManagedThreadId),
+ "This thread should not yet be involved in this pair's processing.");
+ m_threadProcessingMapping[Thread.CurrentThread.ManagedThreadId] = ProcessingMode.ProcessingConcurrentTasks;
+
+ // Process up to the maximum number of items per task allowed
+ for (int i = 0; i < m_maxItemsPerTask; i++)
+ {
+ // Get the next available concurrent task. If we can't find one, bail.
+ Task concurrentTask;
+ if (!m_concurrentTaskScheduler.m_tasks.TryDequeue(out concurrentTask)) break;
+
+ // Execute the task. If the scheduler was previously faulted,
+ // this task could have been faulted when it was queued; ignore such tasks.
+ if (!concurrentTask.IsFaulted) m_concurrentTaskScheduler.ExecuteTask(concurrentTask);
+
+ // Now check to see if exclusive tasks have arrived; if any have, they take priority
+ // so we'll bail out here. Note that we could have checked this condition
+ // in the for loop's condition, but that could lead to extra overhead
+ // in the case where a concurrent task arrives, this task is launched, and then
+ // before entering the loop an exclusive task arrives. If we didn't execute at
+ // least one task, we would have spent all of the overhead to launch a
+ // task but with none of the benefit. There's of course also an inherent
+ // race condition here with regards to exclusive tasks arriving, and we're ok with
+ // executing one more concurrent task than we should before giving priority to exclusive tasks.
+ if (!m_exclusiveTaskScheduler.m_tasks.IsEmpty) break;
+ }
+ }
+ finally
+ {
+ // We're no longer processing concurrent tasks on the current thread
+ ProcessingMode currentMode;
+ m_threadProcessingMapping.TryRemove(Thread.CurrentThread.ManagedThreadId, out currentMode);
+ Contract.Assert(currentMode == ProcessingMode.ProcessingConcurrentTasks,
+ "Somehow we ended up escaping concurrent mode.");
+
+ lock (ValueLock)
+ {
+ // When this task was launched, we tracked it with a positive processing count;
+ // decrement that count. Then check to see whether there's more processing to be done.
+ // There might be more concurrent tasks available, for example, if concurrent tasks arrived
+ // after we exited the loop, or if we exited the loop while concurrent tasks were still
+ // available but we hit our maxItemsPerTask limit.
+ Contract.Assert(m_processingCount > 0, "The procesing mode should not have deviated from concurrent.");
+ if (m_processingCount > 0) --m_processingCount;
+ ProcessAsyncIfNecessary(true);
+ }
+ }
+ }
+
+#if PRENET45
+ /// <summary>
+ /// Type used with TaskCompletionSource(Of TResult) as the TResult
+ /// to ensure that the resulting task can't be upcast to something
+ /// that in the future could lead to compat problems.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
+ [DebuggerNonUserCode]
+ private struct VoidTaskResult { }
+#endif
+
+ /// <summary>
+ /// Holder for lazily-initialized state about the completion of a scheduler pair.
+ /// Completion is only triggered either by rare exceptional conditions or by
+ /// the user calling Complete, and as such we only lazily initialize this
+ /// state in one of those conditions or if the user explicitly asks for
+ /// the Completion.
+ /// </summary>
+ [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
+ private sealed class CompletionState : TaskCompletionSource<VoidTaskResult>
+ {
+ /// <summary>Whether the scheduler has had completion requested.</summary>
+ /// <remarks>This variable is not volatile, so to gurantee safe reading reads, Volatile.Read is used in TryExecuteTaskInline.</remarks>
+ internal bool m_completionRequested;
+ /// <summary>Whether completion processing has been queued.</summary>
+ internal bool m_completionQueued;
+ /// <summary>Unrecoverable exceptions incurred while processing.</summary>
+ internal List<Exception> m_exceptions;
+ }
+
+ /// <summary>
+ /// A scheduler shim used to queue tasks to the pair and execute those tasks on request of the pair.
+ /// </summary>
+ [DebuggerDisplay("Count={CountForDebugger}, MaxConcurrencyLevel={m_maxConcurrencyLevel}, Id={Id}")]
+ [DebuggerTypeProxy(typeof(ConcurrentExclusiveTaskScheduler.DebugView))]
+ private sealed class ConcurrentExclusiveTaskScheduler : TaskScheduler
+ {
+ /// <summary>Cached delegate for invoking TryExecuteTaskShim.</summary>
+ private static readonly Func<object, bool> s_tryExecuteTaskShim = new Func<object, bool>(TryExecuteTaskShim);
+ /// <summary>The parent pair.</summary>
+ private readonly ConcurrentExclusiveSchedulerPair m_pair;
+ /// <summary>The maximum concurrency level for the scheduler.</summary>
+ private readonly int m_maxConcurrencyLevel;
+ /// <summary>The processing mode of this scheduler, exclusive or concurrent.</summary>
+ private readonly ProcessingMode m_processingMode;
+ /// <summary>Gets the queue of tasks for this scheduler.</summary>
+ internal readonly IProducerConsumerQueue<Task> m_tasks;
+
+ /// <summary>Initializes the scheduler.</summary>
+ /// <param name="pair">The parent pair.</param>
+ /// <param name="maxConcurrencyLevel">The maximum degree of concurrency this scheduler may use.</param>
+ /// <param name="processingMode">The processing mode of this scheduler.</param>
+ internal ConcurrentExclusiveTaskScheduler(ConcurrentExclusiveSchedulerPair pair, int maxConcurrencyLevel, ProcessingMode processingMode)
+ {
+ Contract.Requires(pair != null, "Scheduler must be associated with a valid pair.");
+ Contract.Requires(processingMode == ProcessingMode.ProcessingConcurrentTasks || processingMode == ProcessingMode.ProcessingExclusiveTask,
+ "Scheduler must be for concurrent or exclusive processing.");
+ Contract.Requires(
+ (processingMode == ProcessingMode.ProcessingConcurrentTasks && (maxConcurrencyLevel >= 1 || maxConcurrencyLevel == UNLIMITED_PROCESSING)) ||
+ (processingMode == ProcessingMode.ProcessingExclusiveTask && maxConcurrencyLevel == 1),
+ "If we're in concurrent mode, our concurrency level should be positive or unlimited. If exclusive, it should be 1.");
+
+ m_pair = pair;
+ m_maxConcurrencyLevel = maxConcurrencyLevel;
+ m_processingMode = processingMode;
+ m_tasks = (processingMode == ProcessingMode.ProcessingExclusiveTask) ?
+ (IProducerConsumerQueue<Task>)new SingleProducerSingleConsumerQueue<Task>() :
+ (IProducerConsumerQueue<Task>)new MultiProducerMultiConsumerQueue<Task>();
+ }
+
+ /// <summary>Gets the maximum concurrency level this scheduler is able to support.</summary>
+ public override int MaximumConcurrencyLevel { get { return m_maxConcurrencyLevel; } }
+
+ /// <summary>Queues a task to the scheduler.</summary>
+ /// <param name="task">The task to be queued.</param>
+ [SecurityCritical]
+ protected internal override void QueueTask(Task task)
+ {
+ Contract.Assert(task != null, "Infrastructure should have provided a non-null task.");
+ lock (m_pair.ValueLock)
+ {
+ // If the scheduler has already had completion requested, no new work is allowed to be scheduled
+ if (m_pair.CompletionRequested) throw new InvalidOperationException(GetType().Name);
+
+ // Queue the task, and then let the pair know that more work is now available to be scheduled
+ m_tasks.Enqueue(task);
+ m_pair.ProcessAsyncIfNecessary();
+ }
+ }
+
+ /// <summary>Executes a task on this scheduler.</summary>
+ /// <param name="task">The task to be executed.</param>
+ [SecuritySafeCritical]
+ internal void ExecuteTask(Task task)
+ {
+ Contract.Assert(task != null, "Infrastructure should have provided a non-null task.");
+ base.TryExecuteTask(task);
+ }
+
+ /// <summary>Tries to execute the task synchronously on this scheduler.</summary>
+ /// <param name="task">The task to execute.</param>
+ /// <param name="taskWasPreviouslyQueued">Whether the task was previously queued to the scheduler.</param>
+ /// <returns>true if the task could be executed; otherwise, false.</returns>
+ [SecurityCritical]
+ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ Contract.Assert(task != null, "Infrastructure should have provided a non-null task.");
+
+ // If the scheduler has had completion requested, no new work is allowed to be scheduled.
+ // A non-locked read on m_completionRequested (in CompletionRequested) is acceptable here because:
+ // a) we don't need to be exact... a Complete call could come in later in the function anyway
+ // b) this is only a fast path escape hatch. To actually inline the task,
+ // we need to be inside of an already executing task, and in such a case,
+ // while completion may have been requested, we can't have shutdown yet.
+ if (!taskWasPreviouslyQueued && m_pair.CompletionRequested) return false;
+
+ // We know the implementation of the default scheduler and how it will behave.
+ // As it's the most common underlying scheduler, we optimize for it.
+ bool isDefaultScheduler = m_pair.m_underlyingTaskScheduler == TaskScheduler.Default;
+
+ // If we're targeting the default scheduler and taskWasPreviouslyQueued is true,
+ // we know that the default scheduler will only allow it to be inlined
+ // if we're on a thread pool thread (but it won't always allow it in that case,
+ // since it'll only allow inlining if it can find the task in the local queue).
+ // As such, if we're not on a thread pool thread, we know for sure the
+ // task won't be inlined, so let's not even try.
+ if (isDefaultScheduler && taskWasPreviouslyQueued && !Thread.CurrentThread.IsThreadPoolThread)
+ {
+ return false;
+ }
+ else
+ {
+ // If a task is already running on this thread, allow inline execution to proceed.
+ // If there's already a task from this scheduler running on the current thread, we know it's safe
+ // to run this task, in effect temporarily taking that task's count allocation.
+ ProcessingMode currentThreadMode;
+ if (m_pair.m_threadProcessingMapping.TryGetValue(Thread.CurrentThread.ManagedThreadId, out currentThreadMode) &&
+ currentThreadMode == m_processingMode)
+ {
+ // If we're targeting the default scheduler and taskWasPreviouslyQueued is false,
+ // we know the default scheduler will allow it, so we can just execute it here.
+ // Otherwise, delegate to the target scheduler's inlining.
+ return (isDefaultScheduler && !taskWasPreviouslyQueued) ?
+ TryExecuteTask(task) :
+ TryExecuteTaskInlineOnTargetScheduler(task);
+ }
+ }
+
+ // We're not in the context of a task already executing on this scheduler. Bail.
+ return false;
+ }
+
+ /// <summary>
+ /// Implements a reasonable approximation for TryExecuteTaskInline on the underlying scheduler,
+ /// which we can't call directly on the underlying scheduler.
+ /// </summary>
+ /// <param name="task">The task to execute inline if possible.</param>
+ /// <returns>true if the task was inlined successfully; otherwise, false.</returns>
+ [SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "ignored")]
+ private bool TryExecuteTaskInlineOnTargetScheduler(Task task)
+ {
+ // We'd like to simply call TryExecuteTaskInline here, but we can't.
+ // As there's no built-in API for this, a workaround is to create a new task that,
+ // when executed, will simply call TryExecuteTask to run the real task, and then
+ // we run our new shim task synchronously on the target scheduler. If all goes well,
+ // our synchronous invocation will succeed in running the shim task on the current thread,
+ // which will in turn run the real task on the current thread. If the scheduler
+ // doesn't allow that execution, RunSynchronously will block until the underlying scheduler
+ // is able to invoke the task, which might account for an additional but unavoidable delay.
+ // Once it's done, we can return whether the task executed by returning the
+ // shim task's Result, which is in turn the result of TryExecuteTask.
+ var t = new Task<bool>(s_tryExecuteTaskShim, Tuple.Create(this, task));
+ try
+ {
+ t.RunSynchronously(m_pair.m_underlyingTaskScheduler);
+ return t.Result;
+ }
+ catch
+ {
+ Contract.Assert(t.IsFaulted, "Task should be faulted due to the scheduler faulting it and throwing the exception.");
+ var ignored = t.Exception;
+ throw;
+ }
+ finally { t.Dispose(); }
+ }
+
+ /// <summary>Shim used to invoke this.TryExecuteTask(task).</summary>
+ /// <param name="state">A tuple of the ConcurrentExclusiveTaskScheduler and the task to execute.</param>
+ /// <returns>true if the task was successfully inlined; otherwise, false.</returns>
+ /// <remarks>
+ /// This method is separated out not because of performance reasons but so that
+ /// the SecuritySafeCritical attribute may be employed.
+ /// </remarks>
+ [SecuritySafeCritical]
+ private static bool TryExecuteTaskShim(object state)
+ {
+ var tuple = (Tuple<ConcurrentExclusiveTaskScheduler, Task>)state;
+ return tuple.Item1.TryExecuteTask(tuple.Item2);
+ }
+
+ /// <summary>Gets for debugging purposes the tasks scheduled to this scheduler.</summary>
+ /// <returns>An enumerable of the tasks queued.</returns>
+ [SecurityCritical]
+ protected override IEnumerable<Task> GetScheduledTasks() { return m_tasks; }
+
+ /// <summary>Gets the number of tasks queued to this scheduler.</summary>
+ [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private int CountForDebugger { get { return m_tasks.Count; } }
+
+ /// <summary>Provides a debug view for ConcurrentExclusiveTaskScheduler.</summary>
+ private sealed class DebugView
+ {
+ /// <summary>The scheduler being debugged.</summary>
+ private readonly ConcurrentExclusiveTaskScheduler m_taskScheduler;
+
+ /// <summary>Initializes the debug view.</summary>
+ /// <param name="scheduler">The scheduler being debugged.</param>
+ public DebugView(ConcurrentExclusiveTaskScheduler scheduler)
+ {
+ Contract.Requires(scheduler != null, "Need a scheduler with which to construct the debug view.");
+ m_taskScheduler = scheduler;
+ }
+
+ /// <summary>Gets this pair's maximum allowed concurrency level.</summary>
+ public int MaximumConcurrencyLevel { get { return m_taskScheduler.m_maxConcurrencyLevel; } }
+ /// <summary>Gets the tasks scheduled to this scheduler.</summary>
+ public IEnumerable<Task> ScheduledTasks { get { return m_taskScheduler.m_tasks; } }
+ /// <summary>Gets the scheduler pair with which this scheduler is associated.</summary>
+ public ConcurrentExclusiveSchedulerPair SchedulerPair { get { return m_taskScheduler.m_pair; } }
+ }
+ }
+
+ /// <summary>Provides a debug view for ConcurrentExclusiveSchedulerPair.</summary>
+ private sealed class DebugView
+ {
+ /// <summary>The pair being debugged.</summary>
+ private readonly ConcurrentExclusiveSchedulerPair m_pair;
+
+ /// <summary>Initializes the debug view.</summary>
+ /// <param name="pair">The pair being debugged.</param>
+ public DebugView(ConcurrentExclusiveSchedulerPair pair)
+ {
+ Contract.Requires(pair != null, "Need a pair with which to construct the debug view.");
+ m_pair = pair;
+ }
+
+ /// <summary>Gets a representation of the execution state of the pair.</summary>
+ public ProcessingMode Mode { get { return m_pair.ModeForDebugger; } }
+ /// <summary>Gets the number of tasks waiting to run exclusively.</summary>
+ public IEnumerable<Task> ScheduledExclusive { get { return m_pair.m_exclusiveTaskScheduler.m_tasks; } }
+ /// <summary>Gets the number of tasks waiting to run concurrently.</summary>
+ public IEnumerable<Task> ScheduledConcurrent { get { return m_pair.m_concurrentTaskScheduler.m_tasks; } }
+ /// <summary>Gets the number of tasks currently being executed.</summary>
+ public int CurrentlyExecutingTaskCount
+ {
+ get { return (m_pair.m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL) ? 1 : m_pair.m_processingCount; }
+ }
+ /// <summary>Gets the underlying task scheduler that actually executes the tasks.</summary>
+ public TaskScheduler TargetScheduler { get { return m_pair.m_underlyingTaskScheduler; } }
+ }
+
+ /// <summary>Gets an enumeration for debugging that represents the current state of the scheduler pair.</summary>
+ /// <remarks>This is only for debugging. It does not take the necessary locks to be useful for runtime usage.</remarks>
+ private ProcessingMode ModeForDebugger
+ {
+ get
+ {
+ // If our completion task is done, so are we.
+ if (m_completionState != null && m_completionState.Task.IsCompleted) return ProcessingMode.Completed;
+
+ // Otherwise, summarize our current state.
+ var mode = ProcessingMode.NotCurrentlyProcessing;
+ if (m_processingCount == EXCLUSIVE_PROCESSING_SENTINEL) mode |= ProcessingMode.ProcessingExclusiveTask;
+ if (m_processingCount >= 1) mode |= ProcessingMode.ProcessingConcurrentTasks;
+ if (CompletionRequested) mode |= ProcessingMode.Completing;
+ return mode;
+ }
+ }
+
+ /// <summary>Asserts that a given synchronization object is either held or not held.</summary>
+ /// <param name="syncObj">The monitor to check.</param>
+ /// <param name="held">Whether we want to assert that it's currently held or not held.</param>
+ [Conditional("DEBUG")]
+ internal static void ContractAssertMonitorStatus(object syncObj, bool held)
+ {
+ Contract.Requires(syncObj != null, "The monitor object to check must be provided.");
+#if PRENET45
+#if DEBUG
+ // This check is expensive,
+ // which is why it's protected by ShouldCheckMonitorStatus and controlled by an environment variable DEBUGSYNC.
+ if (ShouldCheckMonitorStatus)
+ {
+ bool exceptionThrown;
+ try
+ {
+ Monitor.Pulse(syncObj); // throws a SynchronizationLockException if the monitor isn't held by this thread
+ exceptionThrown = false;
+ }
+ catch (SynchronizationLockException) { exceptionThrown = true; }
+ Contract.Assert(held == !exceptionThrown, "The locking scheme was not correctly followed.");
+ }
+#endif
+#else
+ Contract.Assert(Monitor.IsEntered(syncObj) == held, "The locking scheme was not correctly followed.");
+#endif
+ }
+
+ /// <summary>Gets the options to use for tasks.</summary>
+ /// <param name="isReplacementReplica">If this task is being created to replace another.</param>
+ /// <remarks>
+ /// These options should be used for all tasks that have the potential to run user code or
+ /// that are repeatedly spawned and thus need a modicum of fair treatment.
+ /// </remarks>
+ /// <returns>The options to use.</returns>
+ internal static TaskCreationOptions GetCreationOptionsForTask(bool isReplacementReplica = false)
+ {
+ TaskCreationOptions options =
+#if PRENET45
+ TaskCreationOptions.None;
+#else
+ TaskCreationOptions.DenyChildAttach;
+#endif
+ if (isReplacementReplica) options |= TaskCreationOptions.PreferFairness;
+ return options;
+ }
+
+ /// <summary>Provides an enumeration that represents the current state of the scheduler pair.</summary>
+ [Flags]
+ private enum ProcessingMode : byte
+ {
+ /// <summary>The scheduler pair is currently dormant, with no work scheduled.</summary>
+ NotCurrentlyProcessing = 0x0,
+ /// <summary>The scheduler pair has queued processing for exclusive tasks.</summary>
+ ProcessingExclusiveTask = 0x1,
+ /// <summary>The scheduler pair has queued processing for concurrent tasks.</summary>
+ ProcessingConcurrentTasks = 0x2,
+ /// <summary>Completion has been requested.</summary>
+ Completing = 0x4,
+ /// <summary>The scheduler pair is finished processing.</summary>
+ Completed = 0x8
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs
new file mode 100644
index 0000000000..b1f634c707
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/FutureFactory.cs
@@ -0,0 +1,2303 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// As with TaskFactory, TaskFactory<TResult> encodes common factory patterns into helper methods.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Diagnostics.Contracts;
+using System.Runtime.Versioning;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides support for creating and scheduling
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the results that are available though
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}">Task{TResult}</see> objects that are associated with
+ /// the methods in this class.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// There are many common patterns for which tasks are relevant. The <see cref="TaskFactory{TResult}"/>
+ /// class encodes some of these patterns into methods that pick up default settings, which are
+ /// configurable through its constructors.
+ /// </para>
+ /// <para>
+ /// A default instance of <see cref="TaskFactory{TResult}"/> is available through the
+ /// <see cref="System.Threading.Tasks.Task{TResult}.Factory">Task{TResult}.Factory</see> property.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class TaskFactory<TResult>
+ {
+ // Member variables, DefaultScheduler, other properties and ctors
+ // copied right out of TaskFactory... Lots of duplication here...
+ // Should we be thinking about a TaskFactoryBase class?
+
+ // member variables
+ private CancellationToken m_defaultCancellationToken;
+ private TaskScheduler m_defaultScheduler;
+ private TaskCreationOptions m_defaultCreationOptions;
+ private TaskContinuationOptions m_defaultContinuationOptions;
+
+ private TaskScheduler DefaultScheduler
+ {
+ get
+ {
+ if (m_defaultScheduler == null) return TaskScheduler.Current;
+ else return m_defaultScheduler;
+ }
+ }
+
+ // sister method to above property -- avoids a TLS lookup
+ private TaskScheduler GetDefaultScheduler(Task currTask)
+ {
+ if (m_defaultScheduler != null) return m_defaultScheduler;
+ else if ((currTask != null)
+ && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
+ )
+ return currTask.ExecutingTaskScheduler;
+ else return TaskScheduler.Default;
+ }
+
+ /* Constructors */
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
+ /// </summary>
+ /// <remarks>
+ /// This constructor creates a <see cref="TaskFactory{TResult}"/> instance with a default configuration. The
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory()
+ : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the default configuration.
+ /// </summary>
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// while calling the factory methods.</param>
+ /// <remarks>
+ /// This constructor creates a <see cref="TaskFactory{TResult}"/> instance with a default configuration. The
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(CancellationToken cancellationToken)
+ : this(cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="scheduler">
+ /// The <see cref="System.Threading.Tasks.TaskScheduler">
+ /// TaskScheduler</see> to use to schedule any tasks created with this TaskFactory{TResult}. A null value
+ /// indicates that the current TaskScheduler should be used.
+ /// </param>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to <paramref name="scheduler"/>, unless it's null, in which case the property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
+ : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="creationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
+ /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory{TResult}.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory{TResult}.
+ /// </param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
+ /// argument specifies an invalid value.
+ /// </exception>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
+ /// the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
+ /// name="continuationOptions"/>, and the <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to the
+ /// current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
+ : this(default(CancellationToken), creationOptions, continuationOptions, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory{TResult}"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// while calling the factory methods.</param>
+ /// <param name="creationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
+ /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory{TResult}.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory{TResult}.
+ /// </param>
+ /// <param name="scheduler">
+ /// The default <see cref="System.Threading.Tasks.TaskScheduler">
+ /// TaskScheduler</see> to use to schedule any Tasks created with this TaskFactory{TResult}. A null value
+ /// indicates that TaskScheduler.Current should be used.
+ /// </param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
+ /// argumentspecifies an invalid value.
+ /// </exception>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
+ /// the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
+ /// name="continuationOptions"/>, and the <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to
+ /// <paramref name="scheduler"/>, unless it's null, in which case the property is initialized to the
+ /// current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
+ TaskFactory.CheckCreationOptions(creationOptions);
+
+ m_defaultCancellationToken = cancellationToken;
+ m_defaultScheduler = scheduler;
+ m_defaultCreationOptions = creationOptions;
+ m_defaultContinuationOptions = continuationOptions;
+ }
+
+ /* Properties */
+
+ /// <summary>
+ /// Gets the default <see cref="System.Threading.CancellationToken">CancellationToken</see> of this
+ /// TaskFactory.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
+ /// tasks created by this factory unless another CancellationToken value is explicitly specified
+ /// during the call to the factory methods.
+ /// </remarks>
+ public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> of this
+ /// TaskFactory{TResult}.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default scheduler for this factory. It will be used to schedule all
+ /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
+ /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
+ /// will be used.
+ /// </remarks>
+ public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
+ /// </see> value of this TaskFactory{TResult}.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default creation options for this factory. They will be used to create all
+ /// tasks unless other options are explicitly specified during calls to this factory's methods.
+ /// </remarks>
+ public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskContinuationOptions
+ /// </see> value of this TaskFactory{TResult}.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default continuation options for this factory. They will be used to create
+ /// all continuation tasks unless other options are explicitly specified during calls to this factory's methods.
+ /// </remarks>
+ public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
+
+
+ /* StartNew */
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<TResult> function)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, cancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<TResult> function, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
+ /// Task{TResult}</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(
+ Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
+ creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<Object, TResult> function, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
+ /// Task{TResult}</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew(Func<Object, TResult> function, Object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
+ creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ }
+
+ //
+ // APM Factory methods
+ //
+
+ // Common core logic for FromAsync calls. This minimizes the chance of "drift" between overload implementations.
+ private static void FromAsyncCoreLogic(
+ IAsyncResult iar,
+ Func<IAsyncResult, TResult> endFunction,
+ Action<IAsyncResult> endAction,
+ Task<TResult> promise,
+ bool requiresSynchronization)
+ {
+ Contract.Requires((endFunction != null) != (endAction != null), "Expected exactly one of endFunction/endAction to be non-null");
+
+ Exception ex = null;
+ OperationCanceledException oce = null;
+ TResult result = default(TResult);
+
+ try
+ {
+ if (endFunction != null)
+ {
+ result = endFunction(iar);
+ }
+ else
+ {
+ endAction(iar);
+ }
+ }
+ catch (OperationCanceledException _oce) { oce = _oce; }
+ catch (Exception e) { ex = e; }
+ finally
+ {
+ if (oce != null)
+ {
+ promise.TrySetCanceled(oce.CancellationToken, oce);
+ }
+ else if (ex != null)
+ {
+ bool bWonSetException = promise.TrySetException(ex);
+ if (bWonSetException && ex is ThreadAbortException)
+ {
+ promise.m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
+ }
+ }
+ else
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(promise.Id);
+ }
+ if (requiresSynchronization)
+ {
+ promise.TrySetResult(result);
+ }
+ else
+ {
+ promise.DangerousSetResult(result);
+ }
+ }
+
+
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync(IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync(
+ IAsyncResult asyncResult,
+ Func<IAsyncResult, TResult> endMethod,
+ TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
+ }
+
+
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the task that executes the end method.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync(
+ IAsyncResult asyncResult,
+ Func<IAsyncResult, TResult> endMethod,
+ TaskCreationOptions creationOptions,
+ TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
+ }
+
+ // internal overload that supports StackCrawlMark
+ // We also need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // method can access the logic w/o declaring a TaskFactory<TResult> instance.
+ internal static Task<TResult> FromAsyncImpl(
+ IAsyncResult asyncResult,
+ Func<IAsyncResult, TResult> endFunction,
+ Action<IAsyncResult> endAction,
+ TaskCreationOptions creationOptions,
+ TaskScheduler scheduler,
+ ref StackCrawlMark stackMark)
+ {
+ if (asyncResult == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
+
+ if (endFunction == null && endAction == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endMethod);
+
+ Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
+
+ if (scheduler == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ Contract.EndContractBlock();
+
+ TaskFactory.CheckFromAsyncOptions(creationOptions, false);
+
+ Task<TResult> promise = new Task<TResult>((object)null, creationOptions);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(promise);
+ }
+
+ // Just specify this task as detached. No matter what happens, we want endMethod
+ // to be called -- even if the parent is canceled. So we don't want to flow
+ // RespectParentCancellation.
+ Task t = new Task(delegate
+ {
+ FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization:true);
+ },
+ (object)null, null,
+ default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null, ref stackMark);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Verbose, t.Id, "TaskFactory.FromAsync Callback", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(t);
+ }
+
+ if (asyncResult.IsCompleted)
+ {
+ try { t.InternalRunSynchronously(scheduler, waitForCompletion:false); }
+ catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
+ }
+ else
+ {
+ ThreadPool.RegisterWaitForSingleObject(
+ asyncResult.AsyncWaitHandle,
+ delegate
+ {
+ try { t.InternalRunSynchronously(scheduler, waitForCompletion: false); }
+ catch (Exception e) { promise.TrySetException(e); } // catch and log any scheduler exceptions
+ },
+ null,
+ Timeout.Infinite,
+ true);
+ }
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object state)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
+ }
+
+ // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // method can access the logic w/o declaring a TaskFactory<TResult> instance.
+ internal static Task<TResult> FromAsyncImpl(Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
+ object state, TaskCreationOptions creationOptions)
+ {
+ if (beginMethod == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
+
+ if (endFunction == null && endAction == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endMethod);
+
+ Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
+
+ TaskFactory.CheckFromAsyncOptions(creationOptions, true);
+
+ Task<TResult> promise = new Task<TResult>(state, creationOptions);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(promise);
+ }
+
+ try
+ {
+ // Do NOT change the code below.
+ // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
+ // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
+ // change will likely brake 4.5 behavior so if possible never touch this code again.
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ //This is 4.5 behaviour
+ //if we don't require synchronization, a faster set result path is taken
+ var asyncResult = beginMethod(iar =>
+ {
+ if (!iar.CompletedSynchronously)
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ if (asyncResult.CompletedSynchronously)
+ {
+ Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
+ FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
+ }
+ }
+ else
+ {
+ //This is the original 4.0 behaviour
+ var asyncResult = beginMethod(iar =>
+ {
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ }
+ }
+ catch
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(promise.Id);
+ }
+
+ // Make sure we don't leave promise "dangling".
+ promise.TrySetResult(default(TResult));
+ throw;
+ }
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1>(
+ Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, object state)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1>(
+ Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
+ }
+
+ // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // method can access the logic w/o declaring a TaskFactory<TResult> instance.
+ internal static Task<TResult> FromAsyncImpl<TArg1>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
+ TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ {
+ if (beginMethod == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
+
+ if (endFunction == null && endAction == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endFunction);
+
+ Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
+
+ TaskFactory.CheckFromAsyncOptions(creationOptions, true);
+
+ Task<TResult> promise = new Task<TResult>(state, creationOptions);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(promise);
+ }
+
+ try
+ {
+ // Do NOT change the code below.
+ // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
+ // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
+ // change will likely brake 4.5 behavior so if possible never touch this code again.
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ //if we don't require synchronization, a faster set result path is taken
+ var asyncResult = beginMethod(arg1, iar =>
+ {
+ if (!iar.CompletedSynchronously)
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ if (asyncResult.CompletedSynchronously)
+ {
+ Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
+ FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
+ }
+ }
+ else
+ {
+ //quirk for previous versions
+ var asyncResult = beginMethod(arg1, iar =>
+ {
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ }
+ }
+ catch
+ {
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(promise.Id);
+ }
+
+ // Make sure we don't leave promise "dangling".
+ promise.TrySetResult(default(TResult));
+ throw;
+ }
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2>(
+ Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, TArg2 arg2, object state)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2>(
+ Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
+ }
+
+ // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // method can access the logic w/o declaring a TaskFactory<TResult> instance.
+ internal static Task<TResult> FromAsyncImpl<TArg1, TArg2>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
+ TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ {
+ if (beginMethod == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
+
+ if (endFunction == null && endAction == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endMethod);
+
+ Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
+
+ TaskFactory.CheckFromAsyncOptions(creationOptions, true);
+
+ Task<TResult> promise = new Task<TResult>(state, creationOptions);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(promise);
+ }
+
+ try
+ {
+ // Do NOT change the code below.
+ // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
+ // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
+ // change will likely brake 4.5 behavior so if possible never touch this code again.
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ //if we don't require synchronization, a faster set result path is taken
+ var asyncResult = beginMethod(arg1, arg2, iar =>
+ {
+ if (!iar.CompletedSynchronously)
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ if (asyncResult.CompletedSynchronously)
+ {
+ Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
+ FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
+ }
+ }
+ else
+ {
+ //quirk for previous versions
+ var asyncResult = beginMethod(arg1, arg2, iar =>
+ {
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ }
+ }
+ catch
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(promise.Id);
+ }
+
+ // Make sure we don't leave promise "dangling".
+ promise.TrySetResult(default(TResult));
+ throw;
+ }
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TArg3>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ {
+ return FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
+ }
+
+ // We need this logic broken out into a static method so that the similar TaskFactory.FromAsync()
+ // method can access the logic w/o declaring a TaskFactory<TResult> instance.
+ internal static Task<TResult> FromAsyncImpl<TArg1, TArg2, TArg3>(Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endFunction, Action<IAsyncResult> endAction,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ {
+ if (beginMethod == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.beginMethod);
+
+ if (endFunction == null && endAction == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.endMethod);
+
+ Contract.Requires((endFunction != null) != (endAction != null), "Both endFunction and endAction were non-null");
+
+ TaskFactory.CheckFromAsyncOptions(creationOptions, true);
+
+ Task<TResult> promise = new Task<TResult>(state, creationOptions);
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, promise.Id, "TaskFactory.FromAsync: " + beginMethod.Method.Name, 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(promise);
+ }
+
+ try
+ {
+ // Do NOT change the code below.
+ // 4.5 relies on the fact that IAsyncResult CompletedSynchronously flag needs to be set correctly,
+ // sadly this has not been the case that is why the behaviour from 4.5 broke 4.0 buggy apps. Any other
+ // change will likely brake 4.5 behavior so if possible never touch this code again.
+ if (BinaryCompatibility.TargetsAtLeast_Desktop_V4_5)
+ {
+ //if we don't require synchronization, a faster set result path is taken
+ var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
+ {
+ if (!iar.CompletedSynchronously)
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ if (asyncResult.CompletedSynchronously)
+ {
+ Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
+ FromAsyncCoreLogic(asyncResult, endFunction, endAction, promise, requiresSynchronization: false);
+ }
+ }
+ else
+ {
+ //quirk for previous versions
+ var asyncResult = beginMethod(arg1, arg2, arg3, iar =>
+ {
+ FromAsyncCoreLogic(iar, endFunction, endAction, promise, requiresSynchronization: true);
+ }, state);
+ }
+ }
+ catch
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, promise.Id, AsyncCausalityStatus.Error);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.RemoveFromActiveTasks(promise.Id);
+ }
+
+ // Make sure we don't leave the promise "dangling".
+ promise.TrySetResult(default(TResult));
+ throw;
+ }
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Special internal-only FromAsync support used by System.IO to wrap
+ /// APM implementations with minimal overhead, avoiding unnecessary closure
+ /// and delegate allocations.
+ /// </summary>
+ /// <typeparam name="TInstance">Specifies the type of the instance on which the APM implementation lives.</typeparam>
+ /// <typeparam name="TArg1">Specifies the type containing the arguments.</typeparam>
+ /// <param name="thisRef">The instance from which the begin and end methods are invoked.</param>
+ /// <param name="beginMethod">The begin method.</param>
+ /// <param name="endMethod">The end method.</param>
+ /// <param name="args">The arguments.</param>
+ /// <returns>A task representing the asynchronous operation.</returns>
+ internal static Task<TResult> FromAsyncTrim<TInstance, TArgs>(
+ TInstance thisRef, TArgs args,
+ Func<TInstance, TArgs, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<TInstance, IAsyncResult, TResult> endMethod)
+ where TInstance : class
+ {
+ // Validate arguments, but only with asserts, as this is an internal only implementation.
+ Contract.Assert(thisRef != null, "Expected a non-null thisRef");
+ Contract.Assert(beginMethod != null, "Expected a non-null beginMethod");
+ Contract.Assert(endMethod != null, "Expected a non-null endMethod");
+
+ // Create the promise and start the operation.
+ // No try/catch is necessary here as we want exceptions to bubble out, and because
+ // the task doesn't have AttachedToParent set on it, there's no need to complete it in
+ // case of an exception occurring... we can just let it go unresolved.
+ var promise = new FromAsyncTrimPromise<TInstance>(thisRef, endMethod);
+ var asyncResult = beginMethod(thisRef, args, FromAsyncTrimPromise<TInstance>.s_completeFromAsyncResult, promise);
+
+ // If the IAsyncResult completed asynchronously, completing the promise will be handled by the callback.
+ // If it completed synchronously, we'll handle that here.
+ if (asyncResult.CompletedSynchronously)
+ {
+ Contract.Assert(asyncResult.IsCompleted, "If the operation completed synchronously, it must be completed.");
+ promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization: false);
+ }
+
+ // Return the promise
+ return promise;
+ }
+
+ /// <summary>
+ /// A specialized task used by FromAsyncTrim. Stores relevant information as instance
+ /// state so that we can avoid unnecessary closure/delegate allocations.
+ /// </summary>
+ /// <typeparam name="TInstance">Specifies the type of the instance on which the APM implementation lives.</typeparam>
+ private sealed class FromAsyncTrimPromise<TInstance> : Task<TResult> where TInstance : class
+ {
+ /// <summary>A cached delegate used as the callback for the BeginXx method.</summary>
+ internal readonly static AsyncCallback s_completeFromAsyncResult = CompleteFromAsyncResult;
+
+ /// <summary>A reference to the object on which the begin/end methods are invoked.</summary>
+ private TInstance m_thisRef;
+ /// <summary>The end method.</summary>
+ private Func<TInstance, IAsyncResult, TResult> m_endMethod;
+
+ /// <summary>Initializes the promise.</summary>
+ /// <param name="thisRef">A reference to the object on which the begin/end methods are invoked.</param>
+ /// <param name="endMethod">The end method.</param>
+ internal FromAsyncTrimPromise(TInstance thisRef, Func<TInstance, IAsyncResult, TResult> endMethod) : base()
+ {
+ Contract.Requires(thisRef != null, "Expected a non-null thisRef");
+ Contract.Requires(endMethod != null, "Expected a non-null endMethod");
+ m_thisRef = thisRef;
+ m_endMethod = endMethod;
+ }
+
+ /// <summary>
+ /// Completes the asynchronous operation using information in the IAsyncResult.
+ /// IAsyncResult.AsyncState neeeds to be the FromAsyncTrimPromise to complete.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult for the async operation.</param>
+ internal static void CompleteFromAsyncResult(IAsyncResult asyncResult)
+ {
+ // Validate argument
+ if (asyncResult == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.asyncResult);
+ Contract.EndContractBlock();
+
+ var promise = asyncResult.AsyncState as FromAsyncTrimPromise<TInstance>;
+ if (promise == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
+
+ // Grab the relevant state and then null it out so that the task doesn't hold onto the state unnecessarily
+ var thisRef = promise.m_thisRef;
+ var endMethod = promise.m_endMethod;
+ promise.m_thisRef = default(TInstance);
+ promise.m_endMethod = null;
+ if (endMethod == null) ThrowHelper.ThrowArgumentException(ExceptionResource.InvalidOperation_WrongAsyncResultOrEndCalledMultiple, ExceptionArgument.asyncResult);
+
+ // Complete the promise. If the IAsyncResult completed synchronously,
+ // we'll instead complete the promise at the call site.
+ if (!asyncResult.CompletedSynchronously)
+ {
+ promise.Complete(thisRef, endMethod, asyncResult, requiresSynchronization:true);
+ }
+ }
+
+ /// <summary>Completes the promise.</summary>
+ /// <param name="requiresSynchronization">
+ /// true if synchronization is needed to completed the task;
+ /// false if the task may be completed without synchronization
+ /// because it hasn't been handed out.
+ /// </param>
+ /// <param name="thisRef">The target instance on which the end method should be called.</param>
+ /// <param name="endMethod">The end method to call to retrieve the result.</param>
+ /// <param name="asyncResult">The IAsyncResult for the async operation.</param>
+ /// <permission cref="requiresSynchronization">
+ /// Whether completing the task requires synchronization. This should be true
+ /// unless absolutely sure that the task has not yet been handed out to any consumers.
+ /// </permission>
+ internal void Complete(
+ TInstance thisRef, Func<TInstance, IAsyncResult, TResult> endMethod, IAsyncResult asyncResult,
+ bool requiresSynchronization)
+ {
+ Contract.Assert(!IsCompleted, "The task should not have been completed yet.");
+
+ // Run the end method and complete the task
+ bool successfullySet = false;
+ try
+ {
+ var result = endMethod(thisRef, asyncResult);
+ if (requiresSynchronization)
+ {
+ successfullySet = TrySetResult(result);
+ }
+ else
+ {
+ // If requiresSynchronization is false, we can use the DangerousSetResult
+ // method, which uses no synchronization to complete the task. This is
+ // only valid when the operation is completing synchronously such
+ // that the task has not yet been handed out to any consumers.
+ DangerousSetResult(result);
+ successfullySet = true;
+ }
+ }
+ catch (OperationCanceledException oce)
+ {
+ successfullySet = TrySetCanceled(oce.CancellationToken, oce);
+ }
+ catch (Exception exc)
+ {
+ successfullySet = TrySetException(exc);
+ }
+ Contract.Assert(successfullySet, "Expected the task to not yet be completed");
+ }
+ }
+
+ // Utility method to create a canceled future-style task.
+ // Used by ContinueWhenAll/Any to bail out early on a pre-canceled token.
+ private static Task<TResult> CreateCanceledTask(TaskContinuationOptions continuationOptions, CancellationToken ct)
+ {
+ TaskCreationOptions tco;
+ InternalTaskOptions dontcare;
+ Task.CreationOptionsFromContinuationOptions(continuationOptions, out tco, out dontcare);
+ return new Task<TResult>(true, default(TResult), tco, ct);
+ }
+
+ //
+ // ContinueWhenAll() methods
+ //
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll(Task[] tasks, Func<Task[], TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+
+ // Core implementation of ContinueWhenAll -- the generic version
+ // Note: if you make any changes to this method, please do the same to the non-generic version too.
+ internal static Task<TResult> ContinueWhenAllImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
+ Func<Task<TAntecedentResult>[], TResult> continuationFunction, Action<Task<TAntecedentResult>[]> continuationAction,
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ // check arguments
+ TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
+ Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
+ if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ Contract.EndContractBlock();
+
+ // Check tasks array and make defensive copy
+ Task<TAntecedentResult>[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy<TAntecedentResult>(tasks);
+
+ // Bail early if cancellation has been requested.
+ if (cancellationToken.IsCancellationRequested
+ && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
+ )
+ {
+ return CreateCanceledTask(continuationOptions, cancellationToken);
+ }
+
+ // Call common ContinueWhenAll() setup logic, extract starter task.
+ var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
+
+ // returned continuation task, off of starter
+ if (continuationFunction != null)
+ {
+ return starter.ContinueWith<TResult>(
+ // use a cached delegate
+ GenericDelegateCache<TAntecedentResult, TResult>.CWAllFuncDelegate,
+ continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ else
+ {
+ Contract.Assert(continuationAction != null);
+
+ return starter.ContinueWith<TResult>(
+ // use a cached delegate
+ GenericDelegateCache<TAntecedentResult, TResult>.CWAllActionDelegate,
+ continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ }
+
+ // Core implementation of ContinueWhenAll -- the non-generic version
+ // Note: if you make any changes to this method, please do the same to the generic version too.
+ internal static Task<TResult> ContinueWhenAllImpl(Task[] tasks,
+ Func<Task[], TResult> continuationFunction, Action<Task[]> continuationAction,
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ // check arguments
+ TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
+ Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
+ if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ Contract.EndContractBlock();
+
+ // Check tasks array and make defensive copy
+ Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks);
+
+ // Bail early if cancellation has been requested.
+ if (cancellationToken.IsCancellationRequested
+ && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
+ )
+ {
+ return CreateCanceledTask(continuationOptions, cancellationToken);
+ }
+
+ // Perform common ContinueWhenAll() setup logic, extract starter task
+ var starter = TaskFactory.CommonCWAllLogic(tasksCopy);
+
+ // returned continuation task, off of starter
+ if (continuationFunction != null)
+ {
+ return starter.ContinueWith(
+ //the following delegate avoids closure capture as much as possible
+ //completedTasks.Result == tasksCopy;
+ //state == continuationFunction
+ (completedTasks, state) =>
+ {
+ completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
+ return ((Func<Task[], TResult>)state)(completedTasks.Result);
+ },
+ continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ else
+ {
+ Contract.Assert(continuationAction != null);
+ return starter.ContinueWith<TResult>(
+ //the following delegate avoids closure capture as much as possible
+ //completedTasks.Result == tasksCopy;
+ //state == continuationAction
+ (completedTasks, state) =>
+ {
+ completedTasks.NotifyDebuggerOfWaitCompletionIfNecessary();
+ ((Action<Task[]>)state)(completedTasks.Result); return default(TResult);
+ },
+ continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ }
+
+ //
+ // ContinueWhenAny() methods
+ //
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny(Task[] tasks, Func<Task, TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ // Core implementation of ContinueWhenAny, non-generic version
+ // Note: if you make any changes to this method, be sure to do the same to the generic version
+ internal static Task<TResult> ContinueWhenAnyImpl(Task[] tasks,
+ Func<Task, TResult> continuationFunction, Action<Task> continuationAction,
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ // check arguments
+ TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ if(tasks.Length == 0) ThrowHelper.ThrowArgumentException( ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+
+ //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
+ Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
+ if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ Contract.EndContractBlock();
+
+ // Call common ContinueWhenAny() setup logic, extract starter
+ Task<Task> starter = TaskFactory.CommonCWAnyLogic(tasks);
+
+ // Bail early if cancellation has been requested.
+ if (cancellationToken.IsCancellationRequested
+ && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
+ )
+ {
+ return CreateCanceledTask(continuationOptions, cancellationToken);
+ }
+
+ // returned continuation task, off of starter
+ if (continuationFunction != null)
+ {
+ return starter.ContinueWith(
+ //the following delegate avoids closure capture as much as possible
+ //completedTask.Result is the winning task; state == continuationAction
+ (completedTask, state) => { return ((Func<Task, TResult>)state)(completedTask.Result); },
+ continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ else
+ {
+ Contract.Assert(continuationAction != null);
+ return starter.ContinueWith<TResult>(
+ //the following delegate avoids closure capture as much as possible
+ //completedTask.Result is the winning task; state == continuationAction
+ (completedTask, state) => { ((Action<Task>)state)(completedTask.Result); return default(TResult); },
+ continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ }
+
+
+ // Core implementation of ContinueWhenAny, generic version
+ // Note: if you make any changes to this method, be sure to do the same to the non-generic version
+ internal static Task<TResult> ContinueWhenAnyImpl<TAntecedentResult>(Task<TAntecedentResult>[] tasks,
+ Func<Task<TAntecedentResult>, TResult> continuationFunction, Action<Task<TAntecedentResult>> continuationAction,
+ TaskContinuationOptions continuationOptions, CancellationToken cancellationToken, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ // check arguments
+ TaskFactory.CheckMultiTaskContinuationOptions(continuationOptions);
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ if (tasks.Length == 0) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+ //ArgumentNullException of continuationFunction or continuationAction is checked by the caller
+ Contract.Requires((continuationFunction != null) != (continuationAction != null), "Expected exactly one of endFunction/endAction to be non-null");
+ if (scheduler == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ Contract.EndContractBlock();
+
+ // Call common ContinueWhenAny setup logic, extract starter
+ var starter = TaskFactory.CommonCWAnyLogic(tasks);
+
+ // Bail early if cancellation has been requested.
+ if (cancellationToken.IsCancellationRequested
+ && ((continuationOptions & TaskContinuationOptions.LazyCancellation) == 0)
+ )
+ {
+ return CreateCanceledTask(continuationOptions, cancellationToken);
+ }
+
+ // returned continuation task, off of starter
+ if (continuationFunction != null)
+ {
+ return starter.ContinueWith<TResult>(
+ // Use a cached delegate
+ GenericDelegateCache<TAntecedentResult, TResult>.CWAnyFuncDelegate,
+ continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ else
+ {
+ Contract.Assert(continuationAction != null);
+ return starter.ContinueWith<TResult>(
+ // Use a cached delegate
+ GenericDelegateCache<TAntecedentResult,TResult>.CWAnyActionDelegate,
+ continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+ }
+ }
+
+ // For the ContinueWhenAnyImpl/ContinueWhenAllImpl methods that are generic on TAntecedentResult,
+ // the compiler won't cache the internal ContinueWith delegate because it is generic on both
+ // TAntecedentResult and TResult. The GenericDelegateCache serves as a cache for those delegates.
+ internal static class GenericDelegateCache<TAntecedentResult, TResult>
+ {
+ // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationFunction)
+ internal static Func<Task<Task>, object, TResult> CWAnyFuncDelegate =
+ (Task<Task> wrappedWinner, object state) =>
+ {
+ var func = (Func<Task<TAntecedentResult>, TResult>)state;
+ var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
+ return func(arg);
+ };
+
+ // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(non-null continuationAction)
+ internal static Func<Task<Task>, object, TResult> CWAnyActionDelegate =
+ (Task<Task> wrappedWinner, object state) =>
+ {
+ var action = (Action<Task<TAntecedentResult>>)state;
+ var arg = (Task<TAntecedentResult>)wrappedWinner.Result;
+ action(arg);
+ return default(TResult);
+ };
+
+ // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationFunction)
+ internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllFuncDelegate =
+ (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+ {
+ wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+ var func = (Func<Task<TAntecedentResult>[], TResult>)state;
+ return func(wrappedAntecedents.Result);
+ };
+
+ // ContinueWith delegate for TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(non-null continuationAction)
+ internal static Func<Task<Task<TAntecedentResult>[]>, object, TResult> CWAllActionDelegate =
+ (Task<Task<TAntecedentResult>[]> wrappedAntecedents, object state) =>
+ {
+ wrappedAntecedents.NotifyDebuggerOfWaitCompletionIfNecessary();
+ var action = (Action<Task<TAntecedentResult>[]>)state;
+ action(wrappedAntecedents.Result);
+ return default(TResult);
+ };
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs b/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
new file mode 100644
index 0000000000..b8155d017e
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/IAsyncCausalityTracerStatics.cs
@@ -0,0 +1,101 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.WindowsRuntime;
+
+// Windows.Foundation.Diagnostics cannot be referenced from managed code because
+// they're hidden by the metadata adapter. We redeclare the interfaces manually
+// to be able to talk to native WinRT objects.
+namespace Windows.Foundation.Diagnostics
+{
+ [ComImport]
+ [Guid("50850B26-267E-451B-A890-AB6A370245EE")]
+ [WindowsRuntimeImport]
+ internal interface IAsyncCausalityTracerStatics
+ {
+ void TraceOperationCreation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, string operationName, ulong relatedContext);
+ void TraceOperationCompletion(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, AsyncCausalityStatus status);
+ void TraceOperationRelation(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalityRelation relation);
+ void TraceSynchronousWorkStart(CausalityTraceLevel traceLevel, CausalitySource source, Guid platformId, ulong operationId, CausalitySynchronousWork work);
+ void TraceSynchronousWorkCompletion(CausalityTraceLevel traceLevel, CausalitySource source, CausalitySynchronousWork work);
+ //These next 2 functions could've been represented as an event except that the EventRegistrationToken wasn't being propagated to WinRT
+ EventRegistrationToken add_TracingStatusChanged(System.EventHandler<TracingStatusChangedEventArgs> eventHandler);
+ void remove_TracingStatusChanged(EventRegistrationToken token);
+ }
+
+ [ComImport]
+ [Guid("410B7711-FF3B-477F-9C9A-D2EFDA302DC3")]
+ [WindowsRuntimeImport]
+ internal interface ITracingStatusChangedEventArgs
+ {
+ bool Enabled { get; }
+ CausalityTraceLevel TraceLevel { get; }
+ }
+
+ // We need this dummy class to satisfy a QI when the TracingStatusChangedHandler
+ // after being stored in a GIT cookie and then called by the WinRT API. This usually
+ // happens when calling a MAnaged WinMD which access this feature.
+ [ComImport]
+ [Guid("410B7711-FF3B-477F-9C9A-D2EFDA302DC3")]
+ [WindowsRuntimeImport]
+ internal sealed class TracingStatusChangedEventArgs : ITracingStatusChangedEventArgs
+ {
+ public extern bool Enabled
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ public extern CausalityTraceLevel TraceLevel
+ {
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+ }
+
+ internal enum CausalityRelation
+ {
+ AssignDelegate,
+ Join,
+ Choice,
+ Cancel,
+ Error
+ }
+
+ internal enum CausalitySource
+ {
+ Application,
+ Library,
+ System
+ }
+
+ internal enum CausalitySynchronousWork
+ {
+ CompletionNotification,
+ ProgressNotification,
+ Execution
+ }
+
+ internal enum CausalityTraceLevel
+ {
+ Required,
+ Important,
+ Verbose
+ }
+
+ internal enum AsyncCausalityStatus
+ {
+ Canceled = 2,
+ Completed = 1,
+ Error = 3,
+ Started = 0
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/Parallel.cs b/src/mscorlib/src/System/Threading/Tasks/Parallel.cs
new file mode 100644
index 0000000000..5ec2ae33c0
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/Parallel.cs
@@ -0,0 +1,3594 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A helper class that contains parallel versions of various looping constructs. This
+// internally uses the task parallel library, but takes care to expose very little
+// evidence of this infrastructure being used.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Security.Permissions;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Diagnostics.Contracts;
+
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Stores options that configure the operation of methods on the
+ /// <see cref="T:System.Threading.Tasks.Parallel">Parallel</see> class.
+ /// </summary>
+ /// <remarks>
+ /// By default, methods on the Parallel class attempt to utilize all available processors, are non-cancelable, and target
+ /// the default TaskScheduler (TaskScheduler.Default). <see cref="ParallelOptions"/> enables
+ /// overriding these defaults.
+ /// </remarks>
+ public class ParallelOptions
+ {
+ private TaskScheduler m_scheduler;
+ private int m_maxDegreeOfParallelism;
+ private CancellationToken m_cancellationToken;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ParallelOptions"/> class.
+ /// </summary>
+ /// <remarks>
+ /// This constructor initializes the instance with default values. <see cref="MaxDegreeOfParallelism"/>
+ /// is initialized to -1, signifying that there is no upper bound set on how much parallelism should
+ /// be employed. <see cref="CancellationToken"/> is initialized to a non-cancelable token,
+ /// and <see cref="TaskScheduler"/> is initialized to the default scheduler (TaskScheduler.Default).
+ /// All of these defaults may be overwritten using the property set accessors on the instance.
+ /// </remarks>
+ public ParallelOptions()
+ {
+ m_scheduler = TaskScheduler.Default;
+ m_maxDegreeOfParallelism = -1;
+ m_cancellationToken = CancellationToken.None;
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// associated with this <see cref="ParallelOptions"/> instance. Setting this property to null
+ /// indicates that the current scheduler should be used.
+ /// </summary>
+ public TaskScheduler TaskScheduler
+ {
+ get { return m_scheduler; }
+ set { m_scheduler = value; }
+ }
+
+ // Convenience property used by TPL logic
+ internal TaskScheduler EffectiveTaskScheduler
+ {
+ get
+ {
+ if (m_scheduler == null) return TaskScheduler.Current;
+ else return m_scheduler;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the maximum degree of parallelism enabled by this ParallelOptions instance.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="MaxDegreeOfParallelism"/> limits the number of concurrent operations run by <see
+ /// cref="T:System.Threading.Tasks.Parallel">Parallel</see> method calls that are passed this
+ /// ParallelOptions instance to the set value, if it is positive. If <see
+ /// cref="MaxDegreeOfParallelism"/> is -1, then there is no limit placed on the number of concurrently
+ /// running operations.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when this <see cref="MaxDegreeOfParallelism"/> is set to 0 or some
+ /// value less than -1.
+ /// </exception>
+ public int MaxDegreeOfParallelism
+ {
+ get { return m_maxDegreeOfParallelism; }
+ set
+ {
+ if ((value == 0) || (value < -1))
+ throw new ArgumentOutOfRangeException("MaxDegreeOfParallelism");
+ m_maxDegreeOfParallelism = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
+ /// associated with this <see cref="ParallelOptions"/> instance.
+ /// </summary>
+ /// <remarks>
+ /// Providing a <see cref="T:System.Threading.CancellationToken">CancellationToken</see>
+ /// to a <see cref="T:System.Threading.Tasks.Parallel">Parallel</see> method enables the operation to be
+ /// exited early. Code external to the operation may cancel the token, and if the operation observes the
+ /// token being set, it may exit early by throwing an
+ /// <see cref="T:System.OperationCanceledException"/>.
+ /// </remarks>
+ public CancellationToken CancellationToken
+ {
+ get { return m_cancellationToken; }
+ set { m_cancellationToken = value; }
+ }
+
+ internal int EffectiveMaxConcurrencyLevel
+ {
+ get
+ {
+ int rval = MaxDegreeOfParallelism;
+ int schedulerMax = EffectiveTaskScheduler.MaximumConcurrencyLevel;
+ if ((schedulerMax > 0) && (schedulerMax != Int32.MaxValue))
+ {
+ rval = (rval == -1) ? schedulerMax : Math.Min(schedulerMax, rval);
+ }
+ return rval;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides support for parallel loops and regions.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="T:System.Threading.Tasks.Parallel"/> class provides library-based data parallel replacements
+ /// for common operations such as for loops, for each loops, and execution of a set of statements.
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public static class Parallel
+ {
+ // static counter for generating unique Fork/Join Context IDs to be used in ETW events
+ internal static int s_forkJoinContextID;
+
+ // We use a stride for loops to amortize the frequency of interlocked operations.
+ internal const int DEFAULT_LOOP_STRIDE = 16;
+
+ // Static variable to hold default parallel options
+ internal static ParallelOptions s_defaultParallelOptions = new ParallelOptions();
+
+ /// <summary>
+ /// Executes each of the provided actions, possibly in parallel.
+ /// </summary>
+ /// <param name="actions">An array of <see cref="T:System.Action">Actions</see> to execute.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="actions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="actions"/> array contains a null element.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown when any
+ /// action in the <paramref name="actions"/> array throws an exception.</exception>
+ /// <remarks>
+ /// This method can be used to execute a set of operations, potentially in parallel.
+ /// No guarantees are made about the order in which the operations execute or whether
+ /// they execute in parallel. This method does not return until each of the
+ /// provided operations has completed, regardless of whether completion
+ /// occurs due to normal or exceptional termination.
+ /// </remarks>
+ public static void Invoke(params Action[] actions)
+ {
+ Invoke(s_defaultParallelOptions, actions);
+ }
+
+ /// <summary>
+ /// Executes each of the provided actions, possibly in parallel.
+ /// </summary>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="actions">An array of <see cref="T:System.Action">Actions</see> to execute.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="actions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="actions"/> array contains a null element.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown when any
+ /// action in the <paramref name="actions"/> array throws an exception.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <remarks>
+ /// This method can be used to execute a set of operations, potentially in parallel.
+ /// No guarantees are made about the order in which the operations execute or whether
+ /// the they execute in parallel. This method does not return until each of the
+ /// provided operations has completed, regardless of whether completion
+ /// occurs due to normal or exceptional termination.
+ /// </remarks>
+ public static void Invoke(ParallelOptions parallelOptions, params Action[] actions)
+ {
+ if (actions == null)
+ {
+ throw new ArgumentNullException("actions");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ // Throw an ODE if we're passed a disposed CancellationToken.
+ if (parallelOptions.CancellationToken.CanBeCanceled
+ && AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ {
+ parallelOptions.CancellationToken.ThrowIfSourceDisposed();
+ }
+ // Quit early if we're already canceled -- avoid a bunch of work.
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+
+ // We must validate that the actions array contains no null elements, and also
+ // make a defensive copy of the actions array.
+ Action[] actionsCopy = new Action[actions.Length];
+ for (int i = 0; i < actionsCopy.Length; i++)
+ {
+ actionsCopy[i] = actions[i];
+ if (actionsCopy[i] == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Parallel_Invoke_ActionNull"));
+ }
+ }
+
+ // ETW event for Parallel Invoke Begin
+ int forkJoinContextID = 0;
+ Task callerTask = null;
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
+ callerTask = Task.InternalCurrent;
+ TplEtwProvider.Log.ParallelInvokeBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelInvoke,
+ actionsCopy.Length);
+ }
+
+#if DEBUG
+ actions = null; // Ensure we don't accidentally use this below.
+#endif
+
+ // If we have no work to do, we are done.
+ if (actionsCopy.Length < 1) return;
+
+ // In the algorithm below, if the number of actions is greater than this, we automatically
+ // use Parallel.For() to handle the actions, rather than the Task-per-Action strategy.
+ const int SMALL_ACTIONCOUNT_LIMIT = 10;
+
+ try
+ {
+ // If we've gotten this far, it's time to process the actions.
+ if ((actionsCopy.Length > SMALL_ACTIONCOUNT_LIMIT) ||
+ (parallelOptions.MaxDegreeOfParallelism != -1 && parallelOptions.MaxDegreeOfParallelism < actionsCopy.Length))
+ {
+ // Used to hold any exceptions encountered during action processing
+ ConcurrentQueue<Exception> exceptionQ = null; // will be lazily initialized if necessary
+
+ // This is more efficient for a large number of actions, or for enforcing MaxDegreeOfParallelism.
+ try
+ {
+ // Launch a self-replicating task to handle the execution of all actions.
+ // The use of a self-replicating task allows us to use as many cores
+ // as are available, and no more. The exception to this rule is
+ // that, in the case of a blocked action, the ThreadPool may inject
+ // extra threads, which means extra tasks can run.
+ int actionIndex = 0;
+ ParallelForReplicatingTask rootTask = new ParallelForReplicatingTask(parallelOptions, delegate
+ {
+ // Each for-task will pull an action at a time from the list
+ int myIndex = Interlocked.Increment(ref actionIndex); // = index to use + 1
+ while (myIndex <= actionsCopy.Length)
+ {
+ // Catch and store any exceptions. If we don't catch them, the self-replicating
+ // task will exit, and that may cause other SR-tasks to exit.
+ // And (absent cancellation) we want all actions to execute.
+ try
+ {
+ actionsCopy[myIndex - 1]();
+ }
+ catch (Exception e)
+ {
+ LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => { return new ConcurrentQueue<Exception>(); });
+ exceptionQ.Enqueue(e);
+ }
+
+ // Check for cancellation. If it is encountered, then exit the delegate.
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+
+ // You're still in the game. Grab your next action index.
+ myIndex = Interlocked.Increment(ref actionIndex);
+ }
+ }, TaskCreationOptions.None, InternalTaskOptions.SelfReplicating);
+
+ rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler);
+ rootTask.Wait();
+ }
+ catch (Exception e)
+ {
+ LazyInitializer.EnsureInitialized<ConcurrentQueue<Exception>>(ref exceptionQ, () => { return new ConcurrentQueue<Exception>(); });
+
+ // Since we're consuming all action exceptions, there are very few reasons that
+ // we would see an exception here. Two that come to mind:
+ // (1) An OCE thrown by one or more actions (AggregateException thrown)
+ // (2) An exception thrown from the ParallelForReplicatingTask constructor
+ // (regular exception thrown).
+ // We'll need to cover them both.
+ AggregateException ae = e as AggregateException;
+ if (ae != null)
+ {
+ // Strip off outer container of an AggregateException, because downstream
+ // logic needs OCEs to be at the top level.
+ foreach (Exception exc in ae.InnerExceptions) exceptionQ.Enqueue(exc);
+ }
+ else
+ {
+ exceptionQ.Enqueue(e);
+ }
+ }
+
+ // If we have encountered any exceptions, then throw.
+ if ((exceptionQ != null) && (exceptionQ.Count > 0))
+ {
+ ThrowIfReducableToSingleOCE(exceptionQ, parallelOptions.CancellationToken);
+ throw new AggregateException(exceptionQ);
+ }
+ }
+ else
+ {
+ // This is more efficient for a small number of actions and no DOP support
+
+ // Initialize our array of tasks, one per action.
+ Task[] tasks = new Task[actionsCopy.Length];
+
+ // One more check before we begin...
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+
+ // Launch all actions as tasks
+ for (int i = 1; i < tasks.Length; i++)
+ {
+ tasks[i] = Task.Factory.StartNew(actionsCopy[i], parallelOptions.CancellationToken, TaskCreationOptions.None,
+ InternalTaskOptions.None, parallelOptions.EffectiveTaskScheduler);
+ }
+
+ // Optimization: Use current thread to run something before we block waiting for all tasks.
+ tasks[0] = new Task(actionsCopy[0]);
+ tasks[0].RunSynchronously(parallelOptions.EffectiveTaskScheduler);
+
+ // Now wait for the tasks to complete. This will not unblock until all of
+ // them complete, and it will throw an exception if one or more of them also
+ // threw an exception. We let such exceptions go completely unhandled.
+ try
+ {
+ if (tasks.Length <= 4)
+ {
+ // for 4 or less tasks, the sequential waitall version is faster
+ Task.FastWaitAll(tasks);
+ }
+ else
+ {
+ // otherwise we revert to the regular WaitAll which delegates the multiple wait to the cooperative event.
+ Task.WaitAll(tasks);
+ }
+ }
+ catch (AggregateException aggExp)
+ {
+ // see if we can combine it into a single OCE. If not propagate the original exception
+ ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
+ throw;
+ }
+ finally
+ {
+ for (int i = 0; i < tasks.Length; i++)
+ {
+ if (tasks[i].IsCompleted) tasks[i].Dispose();
+ }
+ }
+ }
+ }
+ finally
+ {
+ // ETW event for Parallel Invoke End
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelInvokeEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int32) as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForWorker<object>(
+ fromInclusive, toExclusive,
+ s_defaultParallelOptions,
+ body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int64) as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForWorker64<object>(
+ fromInclusive, toExclusive, s_defaultParallelOptions,
+ body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int32) as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForWorker<object>(
+ fromInclusive, toExclusive, parallelOptions,
+ body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the iteration count (an Int64) as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions, Action<long> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForWorker64<object>(
+ fromInclusive, toExclusive, parallelOptions,
+ body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </para>
+ /// <para>
+ /// Calling <see cref="System.Threading.Tasks.ParallelLoopState.Break()">ParallelLoopState.Break()</see>
+ /// informs the For operation that iterations after the current one need not
+ /// execute. However, all iterations before the current one will still need to be executed if they have not already.
+ /// Therefore, calling Break is similar to using a break operation within a
+ /// conventional for loop in a language like C#, but it is not a perfect substitute: for example, there is no guarantee that iterations
+ /// after the current one will definitely not execute.
+ /// </para>
+ /// <para>
+ /// If executing all iterations before the current one is not necessary,
+ /// <see cref="System.Threading.Tasks.ParallelLoopState.Stop()">ParallelLoopState.Stop()</see>
+ /// should be preferred to using Break. Calling Stop informs the For loop that it may abandon all remaining
+ /// iterations, regardless of whether they're for interations above or below the current,
+ /// since all required work has already been completed. As with Break, however, there are no guarantees regarding
+ /// which other iterations will not execute.
+ /// </para>
+ /// <para>
+ /// When a loop is ended prematurely, the <see cref="T:ParallelLoopState"/> that's returned will contain
+ /// relevant information about the loop's completion.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int, ParallelLoopState> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForWorker<object>(
+ fromInclusive, toExclusive, s_defaultParallelOptions,
+ null, body, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </remarks>
+ public static ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long, ParallelLoopState> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForWorker64<object>(
+ fromInclusive, toExclusive, s_defaultParallelOptions,
+ null, body, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </remarks>
+ public static ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int, ParallelLoopState> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForWorker<object>(
+ fromInclusive, toExclusive, parallelOptions,
+ null, body, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </remarks>
+ public static ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions,
+ Action<long, ParallelLoopState> body)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForWorker64<object>(
+ fromInclusive, toExclusive, parallelOptions,
+ null, body, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult For<TLocal>(
+ int fromInclusive, int toExclusive,
+ Func<TLocal> localInit,
+ Func<int, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ return ForWorker(
+ fromInclusive, toExclusive, s_defaultParallelOptions,
+ null, null, body, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel. Supports 64-bit indices.
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult For<TLocal>(
+ long fromInclusive, long toExclusive,
+ Func<TLocal> localInit,
+ Func<long, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ return ForWorker64(
+ fromInclusive, toExclusive, s_defaultParallelOptions,
+ null, null, body, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int32),
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult For<TLocal>(
+ int fromInclusive, int toExclusive, ParallelOptions parallelOptions,
+ Func<TLocal> localInit,
+ Func<int, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForWorker(
+ fromInclusive, toExclusive, parallelOptions,
+ null, null, body, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for loop in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="fromInclusive">The start index, inclusive.</param>
+ /// <param name="toExclusive">The end index, exclusive.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each value in the iteration range:
+ /// [fromInclusive, toExclusive). It is provided with the following parameters: the iteration count (an Int64),
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult For<TLocal>(
+ long fromInclusive, long toExclusive, ParallelOptions parallelOptions,
+ Func<TLocal> localInit,
+ Func<long, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+
+ return ForWorker64(
+ fromInclusive, toExclusive, parallelOptions,
+ null, null, body, localInit, localFinally);
+ }
+
+
+
+
+
+
+
+ /// <summary>
+ /// Performs the major work of the parallel for loop. It assumes that argument validation has already
+ /// been performed by the caller. This function's whole purpose in life is to enable as much reuse of
+ /// common implementation details for the various For overloads we offer. Without it, we'd end up
+ /// with lots of duplicate code. It handles: (1) simple for loops, (2) for loops that depend on
+ /// ParallelState, and (3) for loops with thread local data.
+ ///
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the local data.</typeparam>
+ /// <param name="fromInclusive">The loop's start index, inclusive.</param>
+ /// <param name="toExclusive">The loop's end index, exclusive.</param>
+ /// <param name="parallelOptions">A ParallelOptions instance.</param>
+ /// <param name="body">The simple loop body.</param>
+ /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
+ /// <param name="bodyWithLocal">The loop body for thread local state overloads.</param>
+ /// <param name="localInit">A selector function that returns new thread local state.</param>
+ /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
+ /// <remarks>Only one of the body arguments may be supplied (i.e. they are exclusive).</remarks>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
+ private static ParallelLoopResult ForWorker<TLocal>(
+ int fromInclusive, int toExclusive,
+ ParallelOptions parallelOptions,
+ Action<int> body,
+ Action<int, ParallelLoopState> bodyWithState,
+ Func<int, ParallelLoopState, TLocal, TLocal> bodyWithLocal,
+ Func<TLocal> localInit, Action<TLocal> localFinally)
+ {
+ Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1,
+ "expected exactly one body function to be supplied");
+ Contract.Assert(bodyWithLocal != null || (localInit == null && localFinally == null),
+ "thread local functions should only be supplied for loops w/ thread local bodies");
+
+ // Instantiate our result. Specifics will be filled in later.
+ ParallelLoopResult result = new ParallelLoopResult();
+
+ // We just return immediately if 'to' is smaller (or equal to) 'from'.
+ if (toExclusive <= fromInclusive)
+ {
+ result.m_completed = true;
+ return result;
+ }
+
+ // For all loops we need a shared flag even though we don't have a body with state,
+ // because the shared flag contains the exceptional bool, which triggers other workers
+ // to exit their loops if one worker catches an exception
+ ParallelLoopStateFlags32 sharedPStateFlags = new ParallelLoopStateFlags32();
+
+ TaskCreationOptions creationOptions = TaskCreationOptions.None;
+ InternalTaskOptions internalOptions = InternalTaskOptions.SelfReplicating;
+
+ // Before getting started, do a quick peek to see if we have been canceled already
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+ }
+
+ // initialize ranges with passed in loop arguments and expected number of workers
+ int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ?
+ PlatformHelper.ProcessorCount :
+ parallelOptions.EffectiveMaxConcurrencyLevel;
+ RangeManager rangeManager = new RangeManager(fromInclusive, toExclusive, 1, numExpectedWorkers);
+
+ // Keep track of any cancellations
+ OperationCanceledException oce = null;
+
+ CancellationTokenRegistration ctr = new CancellationTokenRegistration();
+
+ // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
+ {
+ // Cause processing to stop
+ sharedPStateFlags.Cancel();
+ // Record our cancellation
+ oce = new OperationCanceledException(parallelOptions.CancellationToken);
+ }, null);
+ }
+
+ // ETW event for Parallel For begin
+ int forkJoinContextID = 0;
+ Task callingTask = null;
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
+ callingTask = Task.InternalCurrent;
+ TplEtwProvider.Log.ParallelLoopBegin((callingTask != null ? callingTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callingTask != null ? callingTask.Id : 0),
+ forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelFor,
+ fromInclusive, toExclusive);
+ }
+
+ ParallelForReplicatingTask rootTask = null;
+
+ try
+ {
+ // this needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
+ rootTask = new ParallelForReplicatingTask(
+ parallelOptions,
+ delegate
+ {
+ //
+ // first thing we do upon enterying the task is to register as a new "RangeWorker" with the
+ // shared RangeManager instance.
+ //
+ // If this call returns a RangeWorker struct which wraps the state needed by this task
+ //
+ // We need to call FindNewWork32() on it to see whether there's a chunk available.
+ //
+
+
+ // Cache some information about the current task
+ Task currentWorkerTask = Task.InternalCurrent;
+ bool bIsRootTask = (currentWorkerTask == rootTask);
+
+ RangeWorker currentWorker = new RangeWorker();
+ Object savedStateFromPreviousReplica = currentWorkerTask.SavedStateFromPreviousReplica;
+
+ if (savedStateFromPreviousReplica is RangeWorker)
+ currentWorker = (RangeWorker)savedStateFromPreviousReplica;
+ else
+ currentWorker = rangeManager.RegisterNewWorker();
+
+
+
+ // These are the local index values to be used in the sequential loop.
+ // Their values filled in by FindNewWork32
+ int nFromInclusiveLocal;
+ int nToExclusiveLocal;
+
+ if (currentWorker.FindNewWork32(out nFromInclusiveLocal, out nToExclusiveLocal) == false ||
+ sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal) == true)
+ {
+ return; // no need to run
+ }
+
+ // ETW event for ParallelFor Worker Fork
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+
+ TLocal localValue = default(TLocal);
+ bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
+
+ try
+ {
+ // Create a new state object that references the shared "stopped" and "exceptional" flags
+ // If needed, it will contain a new instance of thread-local state by invoking the selector.
+ ParallelLoopState32 state = null;
+
+ if (bodyWithState != null)
+ {
+ Contract.Assert(sharedPStateFlags != null);
+ state = new ParallelLoopState32(sharedPStateFlags);
+ }
+ else if (bodyWithLocal != null)
+ {
+ Contract.Assert(sharedPStateFlags != null);
+ state = new ParallelLoopState32(sharedPStateFlags);
+ if (localInit != null)
+ {
+ localValue = localInit();
+ bLocalValueInitialized = true;
+ }
+ }
+
+ // initialize a loop timer which will help us decide whether we should exit early
+ LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
+
+ // Now perform the loop itself.
+ do
+ {
+ if (body != null)
+ {
+ for (int j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop()); // the no-arg version is used since we have no state
+ j += 1)
+ {
+
+ body(j);
+ }
+ }
+ else if (bodyWithState != null)
+ {
+ for (int j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop(j));
+ j += 1)
+ {
+
+ state.CurrentIteration = j;
+ bodyWithState(j, state);
+ }
+ }
+ else
+ {
+ for (int j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop(j));
+ j += 1)
+ {
+ state.CurrentIteration = j;
+ localValue = bodyWithLocal(j, state, localValue);
+ }
+ }
+
+ // Cooperative multitasking workaround for AppDomain fairness.
+ // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
+ // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
+ if (!bIsRootTask && loopTimer.LimitExceeded())
+ {
+ currentWorkerTask.SavedStateForNextReplica = (object)currentWorker;
+ break;
+ }
+
+ }
+ // Exit if we can't find new work, or if the loop was stoppped.
+ while (currentWorker.FindNewWork32(out nFromInclusiveLocal, out nToExclusiveLocal) &&
+ ((sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE) ||
+ !sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal)));
+ }
+ catch
+ {
+ // if we catch an exception in a worker, we signal the other workers to exit the loop, and we rethrow
+ sharedPStateFlags.SetExceptional();
+ throw;
+ }
+ finally
+ {
+ // If a cleanup function was specified, call it. Otherwise, if the type is
+ // IDisposable, we will invoke Dispose on behalf of the user.
+ if (localFinally != null && bLocalValueInitialized)
+ {
+ localFinally(localValue);
+ }
+
+ // ETW event for ParallelFor Worker Join
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+ }
+ },
+ creationOptions, internalOptions);
+
+ rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler); // might throw TSE
+ rootTask.Wait();
+
+ // If we made a cancellation registration, we need to clean it up now before observing the OCE
+ // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // If we got through that with no exceptions, and we were canceled, then
+ // throw our cancellation exception
+ if (oce != null) throw oce;
+ }
+ catch (AggregateException aggExp)
+ {
+ // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // see if we can combine it into a single OCE. If not propagate the original exception
+ ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
+ throw;
+ }
+ catch (TaskSchedulerException)
+ {
+ // if we made a cancellation registration, and rootTask.RunSynchronously threw, we need to clean it up here
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+ throw;
+ }
+ finally
+ {
+ int sb_status = sharedPStateFlags.LoopStateFlags;
+ result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
+ if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
+ {
+ result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
+ }
+
+ if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
+
+ // ETW event for Parallel For End
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ int nTotalIterations = 0;
+
+ // calculate how many iterations we ran in total
+ if (sb_status == ParallelLoopStateFlags.PLS_NONE)
+ nTotalIterations = toExclusive - fromInclusive;
+ else if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
+ nTotalIterations = sharedPStateFlags.LowestBreakIteration - fromInclusive;
+ else
+ nTotalIterations = -1; //PLS_STOPPED! We can't determine this if we were stopped..
+
+ TplEtwProvider.Log.ParallelLoopEnd((callingTask != null ? callingTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callingTask != null ? callingTask.Id : 0),
+ forkJoinContextID, nTotalIterations);
+ }
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Performs the major work of the 64-bit parallel for loop. It assumes that argument validation has already
+ /// been performed by the caller. This function's whole purpose in life is to enable as much reuse of
+ /// common implementation details for the various For overloads we offer. Without it, we'd end up
+ /// with lots of duplicate code. It handles: (1) simple for loops, (2) for loops that depend on
+ /// ParallelState, and (3) for loops with thread local data.
+ ///
+ /// </summary>
+ /// <typeparam name="TLocal">The type of the local data.</typeparam>
+ /// <param name="fromInclusive">The loop's start index, inclusive.</param>
+ /// <param name="toExclusive">The loop's end index, exclusive.</param>
+ /// <param name="parallelOptions">A ParallelOptions instance.</param>
+ /// <param name="body">The simple loop body.</param>
+ /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
+ /// <param name="bodyWithLocal">The loop body for thread local state overloads.</param>
+ /// <param name="localInit">A selector function that returns new thread local state.</param>
+ /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
+ /// <remarks>Only one of the body arguments may be supplied (i.e. they are exclusive).</remarks>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
+ private static ParallelLoopResult ForWorker64<TLocal>(
+ long fromInclusive, long toExclusive,
+ ParallelOptions parallelOptions,
+ Action<long> body,
+ Action<long, ParallelLoopState> bodyWithState,
+ Func<long, ParallelLoopState, TLocal, TLocal> bodyWithLocal,
+ Func<TLocal> localInit, Action<TLocal> localFinally)
+ {
+ Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) + (bodyWithLocal == null ? 0 : 1)) == 1,
+ "expected exactly one body function to be supplied");
+ Contract.Assert(bodyWithLocal != null || (localInit == null && localFinally == null),
+ "thread local functions should only be supplied for loops w/ thread local bodies");
+
+ // Instantiate our result. Specifics will be filled in later.
+ ParallelLoopResult result = new ParallelLoopResult();
+
+ // We just return immediately if 'to' is smaller (or equal to) 'from'.
+ if (toExclusive <= fromInclusive)
+ {
+ result.m_completed = true;
+ return result;
+ }
+
+ // For all loops we need a shared flag even though we don't have a body with state,
+ // because the shared flag contains the exceptional bool, which triggers other workers
+ // to exit their loops if one worker catches an exception
+ ParallelLoopStateFlags64 sharedPStateFlags = new ParallelLoopStateFlags64();
+
+ TaskCreationOptions creationOptions = TaskCreationOptions.None;
+ InternalTaskOptions internalOptions = InternalTaskOptions.SelfReplicating;
+
+ // Before getting started, do a quick peek to see if we have been canceled already
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+ }
+
+ // initialize ranges with passed in loop arguments and expected number of workers
+ int numExpectedWorkers = (parallelOptions.EffectiveMaxConcurrencyLevel == -1) ?
+ PlatformHelper.ProcessorCount :
+ parallelOptions.EffectiveMaxConcurrencyLevel;
+ RangeManager rangeManager = new RangeManager(fromInclusive, toExclusive, 1, numExpectedWorkers);
+
+ // Keep track of any cancellations
+ OperationCanceledException oce = null;
+
+ CancellationTokenRegistration ctr = new CancellationTokenRegistration();
+
+ // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
+ {
+ // Cause processing to stop
+ sharedPStateFlags.Cancel();
+ // Record our cancellation
+ oce = new OperationCanceledException(parallelOptions.CancellationToken);
+ }, null);
+ }
+
+ // ETW event for Parallel For begin
+ Task callerTask = null;
+ int forkJoinContextID = 0;
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
+ callerTask = Task.InternalCurrent;
+ TplEtwProvider.Log.ParallelLoopBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelFor,
+ fromInclusive, toExclusive);
+ }
+
+ ParallelForReplicatingTask rootTask = null;
+
+ try
+ {
+ // this needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
+ rootTask = new ParallelForReplicatingTask(
+ parallelOptions,
+ delegate
+ {
+ //
+ // first thing we do upon enterying the task is to register as a new "RangeWorker" with the
+ // shared RangeManager instance.
+ //
+ // If this call returns a RangeWorker struct which wraps the state needed by this task
+ //
+ // We need to call FindNewWork() on it to see whether there's a chunk available.
+ //
+
+ // Cache some information about the current task
+ Task currentWorkerTask = Task.InternalCurrent;
+ bool bIsRootTask = (currentWorkerTask == rootTask);
+
+ RangeWorker currentWorker = new RangeWorker();
+ Object savedStateFromPreviousReplica = currentWorkerTask.SavedStateFromPreviousReplica;
+
+ if (savedStateFromPreviousReplica is RangeWorker)
+ currentWorker = (RangeWorker)savedStateFromPreviousReplica;
+ else
+ currentWorker = rangeManager.RegisterNewWorker();
+
+
+ // These are the local index values to be used in the sequential loop.
+ // Their values filled in by FindNewWork
+ long nFromInclusiveLocal;
+ long nToExclusiveLocal;
+
+ if (currentWorker.FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal) == false ||
+ sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal) == true)
+ {
+ return; // no need to run
+ }
+
+ // ETW event for ParallelFor Worker Fork
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+
+ TLocal localValue = default(TLocal);
+ bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
+
+ try
+ {
+
+ // Create a new state object that references the shared "stopped" and "exceptional" flags
+ // If needed, it will contain a new instance of thread-local state by invoking the selector.
+ ParallelLoopState64 state = null;
+
+ if (bodyWithState != null)
+ {
+ Contract.Assert(sharedPStateFlags != null);
+ state = new ParallelLoopState64(sharedPStateFlags);
+ }
+ else if (bodyWithLocal != null)
+ {
+ Contract.Assert(sharedPStateFlags != null);
+ state = new ParallelLoopState64(sharedPStateFlags);
+
+ // If a thread-local selector was supplied, invoke it. Otherwise, use the default.
+ if (localInit != null)
+ {
+ localValue = localInit();
+ bLocalValueInitialized = true;
+ }
+ }
+
+ // initialize a loop timer which will help us decide whether we should exit early
+ LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
+
+ // Now perform the loop itself.
+ do
+ {
+ if (body != null)
+ {
+ for (long j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop()); // the no-arg version is used since we have no state
+ j += 1)
+ {
+ body(j);
+ }
+ }
+ else if (bodyWithState != null)
+ {
+ for (long j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop(j));
+ j += 1)
+ {
+ state.CurrentIteration = j;
+ bodyWithState(j, state);
+ }
+ }
+ else
+ {
+ for (long j = nFromInclusiveLocal;
+ j < nToExclusiveLocal && (sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE // fast path check as SEL() doesn't inline
+ || !sharedPStateFlags.ShouldExitLoop(j));
+ j += 1)
+ {
+ state.CurrentIteration = j;
+ localValue = bodyWithLocal(j, state, localValue);
+ }
+ }
+
+ // Cooperative multitasking workaround for AppDomain fairness.
+ // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
+ // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
+ if (!bIsRootTask && loopTimer.LimitExceeded())
+ {
+ currentWorkerTask.SavedStateForNextReplica = (object)currentWorker;
+ break;
+ }
+ }
+ // Exit if we can't find new work, or if the loop was stoppped.
+ while (currentWorker.FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal) &&
+ ((sharedPStateFlags.LoopStateFlags == ParallelLoopStateFlags.PLS_NONE) ||
+ !sharedPStateFlags.ShouldExitLoop(nFromInclusiveLocal)));
+ }
+ catch
+ {
+ // if we catch an exception in a worker, we signal the other workers to exit the loop, and we rethrow
+ sharedPStateFlags.SetExceptional();
+ throw;
+ }
+ finally
+ {
+ // If a cleanup function was specified, call it. Otherwise, if the type is
+ // IDisposable, we will invoke Dispose on behalf of the user.
+ if (localFinally != null && bLocalValueInitialized)
+ {
+ localFinally(localValue);
+ }
+
+ // ETW event for ParallelFor Worker Join
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+ }
+ },
+ creationOptions, internalOptions);
+
+ rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler); // might throw TSE
+ rootTask.Wait();
+
+ // If we made a cancellation registration, we need to clean it up now before observing the OCE
+ // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // If we got through that with no exceptions, and we were canceled, then
+ // throw our cancellation exception
+ if (oce != null) throw oce;
+ }
+ catch (AggregateException aggExp)
+ {
+ // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // see if we can combine it into a single OCE. If not propagate the original exception
+ ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
+ throw;
+ }
+ catch (TaskSchedulerException)
+ {
+ // if we made a cancellation registration, and rootTask.RunSynchronously threw, we need to clean it up here
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+ throw;
+ }
+ finally
+ {
+ int sb_status = sharedPStateFlags.LoopStateFlags;
+ result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
+ if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
+ {
+ result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
+ }
+
+ if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
+
+ // ETW event for Parallel For End
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ long nTotalIterations = 0;
+
+ // calculate how many iterations we ran in total
+ if (sb_status == ParallelLoopStateFlags.PLS_NONE)
+ nTotalIterations = toExclusive - fromInclusive;
+ else if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
+ nTotalIterations = sharedPStateFlags.LowestBreakIteration - fromInclusive;
+ else
+ nTotalIterations = -1; //PLS_STOPPED! We can't determine this if we were stopped..
+
+ TplEtwProvider.Log.ParallelLoopEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID, nTotalIterations);
+ }
+ }
+
+ return result;
+ }
+
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the current element as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, s_defaultParallelOptions, body, null, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the current element as a parameter.
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, parallelOptions, body, null, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource, ParallelLoopState> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, s_defaultParallelOptions, null, body, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource, ParallelLoopState> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, parallelOptions, null, body, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and the current element's index (an Int64).
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, Action<TSource, ParallelLoopState, long> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, s_defaultParallelOptions, null, null, body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and the current element's index (an Int64).
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Action<TSource, ParallelLoopState, long> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForEachWorker<TSource, object>(
+ source, parallelOptions, null, null, body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ return ForEachWorker<TSource, TLocal>(
+ source, s_defaultParallelOptions, null, null, null, body, null, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source,
+ ParallelOptions parallelOptions, Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForEachWorker<TSource, TLocal>(
+ source, parallelOptions, null, null, null, body, null, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
+ /// state that may be shared amongst iterations that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> body, Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ return ForEachWorker<TSource, TLocal>(
+ source, s_defaultParallelOptions, null, null, null, null, body, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on an <see cref="T:System.Collections.IEnumerable{TSource}"/>
+ /// in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the data in the source.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// enumerable. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
+ /// state that may be shared amongst iterations that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(IEnumerable<TSource> source, ParallelOptions parallelOptions, Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> body, Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return ForEachWorker<TSource, TLocal>(
+ source, parallelOptions, null, null, null, null, body, localInit, localFinally);
+ }
+
+
+ /// <summary>
+ /// Performs the major work of the parallel foreach loop. It assumes that argument validation has
+ /// already been performed by the caller. This function's whole purpose in life is to enable as much
+ /// reuse of common implementation details for the various For overloads we offer. Without it, we'd
+ /// end up with lots of duplicate code. It handles: (1) simple foreach loops, (2) foreach loops that
+ /// depend on ParallelState, and (3) foreach loops that access indices, (4) foreach loops with thread
+ /// local data, and any necessary permutations thereof.
+ ///
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source data.</typeparam>
+ /// <typeparam name="TLocal">The type of the local data.</typeparam>
+ /// <param name="source">An enumerable data source.</param>
+ /// <param name="parallelOptions">ParallelOptions instance to use with this ForEach-loop</param>
+ /// <param name="body">The simple loop body.</param>
+ /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
+ /// <param name="bodyWithStateAndIndex">The loop body for ParallelState/indexed overloads.</param>
+ /// <param name="bodyWithStateAndLocal">The loop body for ParallelState/thread local state overloads.</param>
+ /// <param name="bodyWithEverything">The loop body for ParallelState/indexed/thread local state overloads.</param>
+ /// <param name="localInit">A selector function that returns new thread local state.</param>
+ /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
+ /// <remarks>Only one of the bodyXX arguments may be supplied (i.e. they are exclusive).</remarks>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
+ private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
+ IEnumerable<TSource> source,
+ ParallelOptions parallelOptions,
+ Action<TSource> body,
+ Action<TSource, ParallelLoopState> bodyWithState,
+ Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
+ Func<TLocal> localInit, Action<TLocal> localFinally)
+ {
+ Contract.Assert(((body == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) +
+ (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1,
+ "expected exactly one body function to be supplied");
+ Contract.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null),
+ "thread local functions should only be supplied for loops w/ thread local bodies");
+
+ // Before getting started, do a quick peek to see if we have been canceled already
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+ }
+
+ // If it's an array, we can use a fast-path that uses ldelems in the IL.
+ TSource[] sourceAsArray = source as TSource[];
+ if (sourceAsArray != null)
+ {
+ return ForEachWorker<TSource, TLocal>(
+ sourceAsArray, parallelOptions, body, bodyWithState, bodyWithStateAndIndex, bodyWithStateAndLocal,
+ bodyWithEverything, localInit, localFinally);
+ }
+
+ // If we can index into the list, we can use a faster code-path that doesn't result in
+ // contention for the single, shared enumerator object.
+ IList<TSource> sourceAsList = source as IList<TSource>;
+ if (sourceAsList != null)
+ {
+ return ForEachWorker<TSource, TLocal>(
+ sourceAsList, parallelOptions, body, bodyWithState, bodyWithStateAndIndex, bodyWithStateAndLocal,
+ bodyWithEverything, localInit, localFinally);
+ }
+
+ // This is an honest-to-goodness IEnumerable. Wrap it in a Partitioner and defer to our
+ // ForEach(Partitioner) logic.
+ return PartitionerForEachWorker<TSource, TLocal>(Partitioner.Create(source), parallelOptions, body, bodyWithState,
+ bodyWithStateAndIndex, bodyWithStateAndLocal, bodyWithEverything, localInit, localFinally);
+
+ }
+
+ /// <summary>
+ /// A fast path for the more general ForEachWorker method above. This uses ldelem instructions to
+ /// access the individual elements of the array, which will be faster.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source data.</typeparam>
+ /// <typeparam name="TLocal">The type of the local data.</typeparam>
+ /// <param name="array">An array data source.</param>
+ /// <param name="parallelOptions">The options to use for execution.</param>
+ /// <param name="body">The simple loop body.</param>
+ /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
+ /// <param name="bodyWithStateAndIndex">The loop body for indexed/ParallelLoopState overloads.</param>
+ /// <param name="bodyWithStateAndLocal">The loop body for local/ParallelLoopState overloads.</param>
+ /// <param name="bodyWithEverything">The loop body for the most generic overload.</param>
+ /// <param name="localInit">A selector function that returns new thread local state.</param>
+ /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
+ private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
+ TSource[] array,
+ ParallelOptions parallelOptions,
+ Action<TSource> body,
+ Action<TSource, ParallelLoopState> bodyWithState,
+ Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
+ Func<TLocal> localInit, Action<TLocal> localFinally)
+ {
+ Contract.Assert(array != null);
+ Contract.Assert(parallelOptions != null, "ForEachWorker(array): parallelOptions is null");
+
+ int from = array.GetLowerBound(0);
+ int to = array.GetUpperBound(0) + 1;
+
+ if (body != null)
+ {
+ return ForWorker<object>(
+ from, to, parallelOptions, (i) => body(array[i]), null, null, null, null);
+ }
+ else if (bodyWithState != null)
+ {
+ return ForWorker<object>(
+ from, to, parallelOptions, null, (i, state) => bodyWithState(array[i], state), null, null, null);
+ }
+ else if (bodyWithStateAndIndex != null)
+ {
+ return ForWorker<object>(
+ from, to, parallelOptions, null, (i, state) => bodyWithStateAndIndex(array[i], state, i), null, null, null);
+ }
+ else if (bodyWithStateAndLocal != null)
+ {
+ return ForWorker<TLocal>(
+ from, to, parallelOptions, null, null, (i, state, local) => bodyWithStateAndLocal(array[i], state, local), localInit, localFinally);
+ }
+ else
+ {
+ return ForWorker<TLocal>(
+ from, to, parallelOptions, null, null, (i, state, local) => bodyWithEverything(array[i], state, i, local), localInit, localFinally);
+ }
+ }
+
+ /// <summary>
+ /// A fast path for the more general ForEachWorker method above. This uses IList&lt;T&gt;'s indexer
+ /// capabilities to access the individual elements of the list rather than an enumerator.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the source data.</typeparam>
+ /// <typeparam name="TLocal">The type of the local data.</typeparam>
+ /// <param name="list">A list data source.</param>
+ /// <param name="parallelOptions">The options to use for execution.</param>
+ /// <param name="body">The simple loop body.</param>
+ /// <param name="bodyWithState">The loop body for ParallelState overloads.</param>
+ /// <param name="bodyWithStateAndIndex">The loop body for indexed/ParallelLoopState overloads.</param>
+ /// <param name="bodyWithStateAndLocal">The loop body for local/ParallelLoopState overloads.</param>
+ /// <param name="bodyWithEverything">The loop body for the most generic overload.</param>
+ /// <param name="localInit">A selector function that returns new thread local state.</param>
+ /// <param name="localFinally">A cleanup function to destroy thread local state.</param>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult"/> structure.</returns>
+ private static ParallelLoopResult ForEachWorker<TSource, TLocal>(
+ IList<TSource> list,
+ ParallelOptions parallelOptions,
+ Action<TSource> body,
+ Action<TSource, ParallelLoopState> bodyWithState,
+ Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
+ Func<TLocal> localInit, Action<TLocal> localFinally)
+ {
+ Contract.Assert(list != null);
+ Contract.Assert(parallelOptions != null, "ForEachWorker(list): parallelOptions is null");
+
+ if (body != null)
+ {
+ return ForWorker<object>(
+ 0, list.Count, parallelOptions, (i) => body(list[i]), null, null, null, null);
+ }
+ else if (bodyWithState != null)
+ {
+ return ForWorker<object>(
+ 0, list.Count, parallelOptions, null, (i, state) => bodyWithState(list[i], state), null, null, null);
+ }
+ else if (bodyWithStateAndIndex != null)
+ {
+ return ForWorker<object>(
+ 0, list.Count, parallelOptions, null, (i, state) => bodyWithStateAndIndex(list[i], state, i), null, null, null);
+ }
+ else if (bodyWithStateAndLocal != null)
+ {
+ return ForWorker<TLocal>(
+ 0, list.Count, parallelOptions, null, null, (i, state, local) => bodyWithStateAndLocal(list[i], state, local), localInit, localFinally);
+ }
+ else
+ {
+ return ForWorker<TLocal>(
+ 0, list.Count, parallelOptions, null, null, (i, state, local) => bodyWithEverything(list[i], state, i, local), localInit, localFinally);
+ }
+ }
+
+
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the current element as a parameter.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ Partitioner<TSource> source,
+ Action<TSource> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, body, null, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ Partitioner<TSource> source,
+ Action<TSource, ParallelLoopState> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, null, body, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
+ /// OrderablePartitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner do not return the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IList with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and the current element's index (an Int64).
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ OrderablePartitioner<TSource> source,
+ Action<TSource, ParallelLoopState, long> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+
+ if (!source.KeysNormalized)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, s_defaultParallelOptions, null, null, body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(
+ Partitioner<TSource> source,
+ Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ return PartitionerForEachWorker<TSource, TLocal>(source, s_defaultParallelOptions, null, null, null, body, null, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
+ /// OrderablePartitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner do not return the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IList with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
+ /// state that may be shared amongst iterations that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(
+ OrderablePartitioner<TSource> source,
+ Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+
+ if (!source.KeysNormalized)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
+ }
+
+ return PartitionerForEachWorker<TSource, TLocal>(source, s_defaultParallelOptions, null, null, null, null, body, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the current element as a parameter.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ Partitioner<TSource> source,
+ ParallelOptions parallelOptions,
+ Action<TSource> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, parallelOptions, body, null, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// and a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ Partitioner<TSource> source,
+ ParallelOptions parallelOptions,
+ Action<TSource, ParallelLoopState> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, parallelOptions, null, body, null, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
+ /// OrderablePartitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner do not return the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IList with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and the current element's index (an Int64).
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource>(
+ OrderablePartitioner<TSource> source,
+ ParallelOptions parallelOptions,
+ Action<TSource, ParallelLoopState, long> body)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ if (!source.KeysNormalized)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
+ }
+
+ return PartitionerForEachWorker<TSource, object>(source, parallelOptions, null, null, body, null, null, null, null);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">
+ /// Partitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">The Partitioner that contains the original data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> Partitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> Partitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner does not return
+ /// the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() method in the <paramref name="source"/> Partitioner returns an IList
+ /// with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() method in the <paramref name="source"/> Partitioner returns an
+ /// IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, and some local state that may be shared amongst iterations
+ /// that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(
+ Partitioner<TSource> source,
+ ParallelOptions parallelOptions,
+ Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ return PartitionerForEachWorker<TSource, TLocal>(source, parallelOptions, null, null, null, body, null, localInit, localFinally);
+ }
+
+ /// <summary>
+ /// Executes a for each operation on a <see cref="T:System.Collections.Concurrent.OrderablePartitioner{TSource}">
+ /// OrderablePartitioner</see> in which iterations may run in parallel.
+ /// </summary>
+ /// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam>
+ /// <typeparam name="TLocal">The type of the thread-local data.</typeparam>
+ /// <param name="source">The OrderablePartitioner that contains the original data source.</param>
+ /// <param name="parallelOptions">A <see cref="T:System.Threading.Tasks.ParallelOptions">ParallelOptions</see>
+ /// instance that configures the behavior of this operation.</param>
+ /// <param name="localInit">The function delegate that returns the initial state of the local data
+ /// for each thread.</param>
+ /// <param name="body">The delegate that is invoked once per iteration.</param>
+ /// <param name="localFinally">The delegate that performs a final action on the local state of each
+ /// thread.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="source"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="parallelOptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="body"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localInit"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="localFinally"/> argument is null.</exception>
+ /// <exception cref="T:System.OperationCanceledException">The exception that is thrown when the
+ /// <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the <paramref name="parallelOptions"/>
+ /// argument is set</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// SupportsDynamicPartitions property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// KeysNormalized property in the <paramref name="source"/> OrderablePartitioner returns
+ /// false.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when any
+ /// methods in the <paramref name="source"/> OrderablePartitioner return null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner do not return the correct number of partitions.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetPartitions() or GetOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IList with at least one null value.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The exception that is thrown when the
+ /// GetDynamicPartitions() or GetDynamicOrderablePartitions() methods in the <paramref name="source"/>
+ /// OrderablePartitioner return an IEnumerable whose GetEnumerator() method returns null.</exception>
+ /// <exception cref="T:System.AggregateException">The exception that is thrown to contain an exception
+ /// thrown from one of the specified delegates.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The exception that is thrown when the
+ /// the <see cref="T:System.Threading.CancellationTokenSource">CancellationTokenSource</see> associated with the
+ /// the <see cref="T:System.Threading.CancellationToken">CancellationToken</see> in the
+ /// <paramref name="parallelOptions"/> has been disposed.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.ParallelLoopResult">ParallelLoopResult</see> structure
+ /// that contains information on what portion of the loop completed.</returns>
+ /// <remarks>
+ /// <para>
+ /// The <see cref="T:System.Collections.Concurrent.Partitioner{TSource}">Partitioner</see> is used to retrieve
+ /// the elements to be processed, in place of the original data source. If the current element's
+ /// index is desired, the source must be an <see cref="T:System.Collections.Concurrent.OrderablePartitioner">
+ /// OrderablePartitioner</see>.
+ /// </para>
+ /// <para>
+ /// The <paramref name="body"/> delegate is invoked once for each element in the <paramref name="source"/>
+ /// Partitioner. It is provided with the following parameters: the current element,
+ /// a <see cref="System.Threading.Tasks.ParallelLoopState">ParallelLoopState</see> instance that may be
+ /// used to break out of the loop prematurely, the current element's index (an Int64), and some local
+ /// state that may be shared amongst iterations that execute on the same thread.
+ /// </para>
+ /// <para>
+ /// The <paramref name="localInit"/> delegate is invoked once for each thread that participates in the loop's
+ /// execution and returns the initial local state for each of those threads. These initial states are passed to the first
+ /// <paramref name="body"/> invocations on each thread. Then, every subsequent body invocation returns a possibly
+ /// modified state value that is passed to the next body invocation. Finally, the last body invocation on each thread returns a state value
+ /// that is passed to the <paramref name="localFinally"/> delegate. The localFinally delegate is invoked once per thread to perform a final
+ /// action on each thread's local state.
+ /// </para>
+ /// </remarks>
+ public static ParallelLoopResult ForEach<TSource, TLocal>(
+ OrderablePartitioner<TSource> source,
+ ParallelOptions parallelOptions,
+ Func<TLocal> localInit,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> body,
+ Action<TLocal> localFinally)
+ {
+ if (source == null)
+ {
+ throw new ArgumentNullException("source");
+ }
+ if (body == null)
+ {
+ throw new ArgumentNullException("body");
+ }
+ if (localInit == null)
+ {
+ throw new ArgumentNullException("localInit");
+ }
+ if (localFinally == null)
+ {
+ throw new ArgumentNullException("localFinally");
+ }
+ if (parallelOptions == null)
+ {
+ throw new ArgumentNullException("parallelOptions");
+ }
+
+ if (!source.KeysNormalized)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_OrderedPartitionerKeysNotNormalized"));
+ }
+
+ return PartitionerForEachWorker<TSource, TLocal>(source, parallelOptions, null, null, null, null, body, localInit, localFinally);
+ }
+
+ // Main worker method for Parallel.ForEach() calls w/ Partitioners.
+ private static ParallelLoopResult PartitionerForEachWorker<TSource, TLocal>(
+ Partitioner<TSource> source, // Might be OrderablePartitioner
+ ParallelOptions parallelOptions,
+ Action<TSource> simpleBody,
+ Action<TSource, ParallelLoopState> bodyWithState,
+ Action<TSource, ParallelLoopState, long> bodyWithStateAndIndex,
+ Func<TSource, ParallelLoopState, TLocal, TLocal> bodyWithStateAndLocal,
+ Func<TSource, ParallelLoopState, long, TLocal, TLocal> bodyWithEverything,
+ Func<TLocal> localInit,
+ Action<TLocal> localFinally)
+ {
+ Contract.Assert(((simpleBody == null ? 0 : 1) + (bodyWithState == null ? 0 : 1) +
+ (bodyWithStateAndIndex == null ? 0 : 1) + (bodyWithStateAndLocal == null ? 0 : 1) + (bodyWithEverything == null ? 0 : 1)) == 1,
+ "PartitionForEach: expected exactly one body function to be supplied");
+ Contract.Assert((bodyWithStateAndLocal != null) || (bodyWithEverything != null) || (localInit == null && localFinally == null),
+ "PartitionForEach: thread local functions should only be supplied for loops w/ thread local bodies");
+
+ OrderablePartitioner<TSource> orderedSource = source as OrderablePartitioner<TSource>;
+ Contract.Assert((orderedSource != null) || (bodyWithStateAndIndex == null && bodyWithEverything == null),
+ "PartitionForEach: bodies with indices are only allowable for OrderablePartitioner");
+
+ if (!source.SupportsDynamicPartitions)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerNotDynamic"));
+ }
+
+ // Before getting started, do a quick peek to see if we have been canceled already
+ if (parallelOptions.CancellationToken.IsCancellationRequested)
+ {
+ throw new OperationCanceledException(parallelOptions.CancellationToken);
+ }
+
+ // ETW event for Parallel For begin
+ int forkJoinContextID = 0;
+ Task callerTask = null;
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ forkJoinContextID = Interlocked.Increment(ref s_forkJoinContextID);
+ callerTask = Task.InternalCurrent;
+ TplEtwProvider.Log.ParallelLoopBegin((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID, TplEtwProvider.ForkJoinOperationType.ParallelForEach,
+ 0, 0);
+ }
+
+ // For all loops we need a shared flag even though we don't have a body with state,
+ // because the shared flag contains the exceptional bool, which triggers other workers
+ // to exit their loops if one worker catches an exception
+ ParallelLoopStateFlags64 sharedPStateFlags = new ParallelLoopStateFlags64();
+
+ // Instantiate our result. Specifics will be filled in later.
+ ParallelLoopResult result = new ParallelLoopResult();
+
+ // Keep track of any cancellations
+ OperationCanceledException oce = null;
+
+ CancellationTokenRegistration ctr = new CancellationTokenRegistration();
+
+ // if cancellation is enabled, we need to register a callback to stop the loop when it gets signaled
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr = parallelOptions.CancellationToken.InternalRegisterWithoutEC((o) =>
+ {
+ // Cause processing to stop
+ sharedPStateFlags.Cancel();
+ // Record our cancellation
+ oce = new OperationCanceledException(parallelOptions.CancellationToken);
+ }, null);
+ }
+
+ // Get our dynamic partitioner -- depends on whether source is castable to OrderablePartitioner
+ // Also, do some error checking.
+ IEnumerable<TSource> partitionerSource = null;
+ IEnumerable<KeyValuePair<long, TSource>> orderablePartitionerSource = null;
+ if (orderedSource != null)
+ {
+ orderablePartitionerSource = orderedSource.GetOrderableDynamicPartitions();
+ if (orderablePartitionerSource == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerReturnedNull"));
+ }
+ }
+ else
+ {
+ partitionerSource = source.GetDynamicPartitions();
+ if (partitionerSource == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_PartitionerReturnedNull"));
+ }
+ }
+
+ ParallelForReplicatingTask rootTask = null;
+
+ // This is the action that will be run by each replicable task.
+ Action partitionAction = delegate
+ {
+ Task currentWorkerTask = Task.InternalCurrent;
+
+ // ETW event for ParallelForEach Worker Fork
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelFork((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+
+ TLocal localValue = default(TLocal);
+ bool bLocalValueInitialized = false; // Tracks whether localInit ran without exceptions, so that we can skip localFinally if it wasn't
+ IDisposable myPartitionToDispose = null;
+
+ try
+ {
+ // Create a new state object that references the shared "stopped" and "exceptional" flags.
+ // If needed, it will contain a new instance of thread-local state by invoking the selector.
+ ParallelLoopState64 state = null;
+
+ if (bodyWithState != null || bodyWithStateAndIndex != null)
+ {
+ state = new ParallelLoopState64(sharedPStateFlags);
+ }
+ else if (bodyWithStateAndLocal != null || bodyWithEverything != null)
+ {
+ state = new ParallelLoopState64(sharedPStateFlags);
+ // If a thread-local selector was supplied, invoke it. Otherwise, stick with the default.
+ if (localInit != null)
+ {
+ localValue = localInit();
+ bLocalValueInitialized = true;
+ }
+ }
+
+
+ bool bIsRootTask = (rootTask == currentWorkerTask);
+
+ // initialize a loop timer which will help us decide whether we should exit early
+ LoopTimer loopTimer = new LoopTimer(rootTask.ActiveChildCount);
+
+ if (orderedSource != null)
+ {
+ // Use this path for OrderablePartitioner
+
+
+ // first check if there's saved state from a previous replica that we might be replacing.
+ // the only state to be passed down in such a transition is the enumerator
+ IEnumerator<KeyValuePair<long, TSource>> myPartition = currentWorkerTask.SavedStateFromPreviousReplica as IEnumerator<KeyValuePair<long, TSource>>;
+ if (myPartition == null)
+ {
+ // apparently we're a brand new replica, get a fresh enumerator from the partitioner
+ myPartition = orderablePartitionerSource.GetEnumerator();
+ if (myPartition == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_NullEnumerator"));
+ }
+ }
+ myPartitionToDispose = myPartition;
+
+ while (myPartition.MoveNext())
+ {
+ KeyValuePair<long, TSource> kvp = myPartition.Current;
+ long index = kvp.Key;
+ TSource value = kvp.Value;
+
+ // Update our iteration index
+ if (state != null) state.CurrentIteration = index;
+
+ if (simpleBody != null)
+ simpleBody(value);
+ else if (bodyWithState != null)
+ bodyWithState(value, state);
+ else if (bodyWithStateAndIndex != null)
+ bodyWithStateAndIndex(value, state, index);
+ else if (bodyWithStateAndLocal != null)
+ localValue = bodyWithStateAndLocal(value, state, localValue);
+ else
+ localValue = bodyWithEverything(value, state, index, localValue);
+
+ if (sharedPStateFlags.ShouldExitLoop(index)) break;
+
+ // Cooperative multitasking workaround for AppDomain fairness.
+ // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
+ // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
+ if (!bIsRootTask && loopTimer.LimitExceeded())
+ {
+ currentWorkerTask.SavedStateForNextReplica = myPartition;
+ myPartitionToDispose = null;
+ break;
+ }
+ }
+
+ }
+ else
+ {
+ // Use this path for Partitioner that is not OrderablePartitioner
+
+ // first check if there's saved state from a previous replica that we might be replacing.
+ // the only state to be passed down in such a transition is the enumerator
+ IEnumerator<TSource> myPartition = currentWorkerTask.SavedStateFromPreviousReplica as IEnumerator<TSource>;
+ if (myPartition == null)
+ {
+ // apparently we're a brand new replica, get a fresh enumerator from the partitioner
+ myPartition = partitionerSource.GetEnumerator();
+ if (myPartition == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Parallel_ForEach_NullEnumerator"));
+ }
+ }
+ myPartitionToDispose = myPartition;
+
+ // I'm not going to try to maintain this
+ if (state != null)
+ state.CurrentIteration = 0;
+
+ while (myPartition.MoveNext())
+ {
+ TSource t = myPartition.Current;
+
+ if (simpleBody != null)
+ simpleBody(t);
+ else if (bodyWithState != null)
+ bodyWithState(t, state);
+ else if (bodyWithStateAndLocal != null)
+ localValue = bodyWithStateAndLocal(t, state, localValue);
+ else
+ Contract.Assert(false, "PartitionerForEach: illegal body type in Partitioner handler");
+
+
+ // Any break, stop or exception causes us to halt
+ // We don't have the global indexing information to discriminate whether or not
+ // we are before or after a break point.
+ if (sharedPStateFlags.LoopStateFlags != ParallelLoopStateFlags.PLS_NONE)
+ break;
+
+ // Cooperative multitasking workaround for AppDomain fairness.
+ // Check if allowed loop time is exceeded, if so save current state and return. The self replicating task logic
+ // will detect this, and queue up a replacement task. Note that we don't do this on the root task.
+ if (!bIsRootTask && loopTimer.LimitExceeded())
+ {
+ currentWorkerTask.SavedStateForNextReplica = myPartition;
+ myPartitionToDispose = null;
+ break;
+ }
+ }
+ }
+ }
+ catch
+ {
+ // Inform other tasks of the exception, then rethrow
+ sharedPStateFlags.SetExceptional();
+ throw;
+ }
+ finally
+ {
+ if (localFinally != null && bLocalValueInitialized)
+ {
+ localFinally(localValue);
+ }
+
+ if (myPartitionToDispose != null)
+ {
+ myPartitionToDispose.Dispose();
+ }
+
+ // ETW event for ParallelFor Worker Join
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelJoin((currentWorkerTask != null ? currentWorkerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (currentWorkerTask != null ? currentWorkerTask.Id : 0),
+ forkJoinContextID);
+ }
+ }
+ };
+
+ try
+ {
+ // Create and start the self-replicating task.
+ // This needs to be in try-block because it can throw in BuggyScheduler.MaxConcurrencyLevel
+ rootTask = new ParallelForReplicatingTask(parallelOptions, partitionAction, TaskCreationOptions.None,
+ InternalTaskOptions.SelfReplicating);
+
+ // And process it's completion...
+ // Moved inside try{} block because faulty scheduler may throw here.
+ rootTask.RunSynchronously(parallelOptions.EffectiveTaskScheduler);
+
+ rootTask.Wait();
+
+ // If we made a cancellation registration, we need to clean it up now before observing the OCE
+ // Otherwise we could be caught in the middle of a callback, and observe PLS_STOPPED, but oce = null
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // If we got through that with no exceptions, and we were canceled, then
+ // throw our cancellation exception
+ if (oce != null) throw oce;
+ }
+ catch (AggregateException aggExp)
+ {
+ // if we made a cancellation registration, and rootTask.Wait threw, we need to clean it up here
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+
+ // see if we can combine it into a single OCE. If not propagate the original exception
+ ThrowIfReducableToSingleOCE(aggExp.InnerExceptions, parallelOptions.CancellationToken);
+ throw;
+ }
+ catch (TaskSchedulerException)
+ {
+ // if we made a cancellation registration, and either we threw an exception constructing rootTask or
+ // rootTask.RunSynchronously threw, we need to clean it up here.
+ if (parallelOptions.CancellationToken.CanBeCanceled)
+ {
+ ctr.Dispose();
+ }
+ throw;
+ }
+ finally
+ {
+ int sb_status = sharedPStateFlags.LoopStateFlags;
+ result.m_completed = (sb_status == ParallelLoopStateFlags.PLS_NONE);
+ if ((sb_status & ParallelLoopStateFlags.PLS_BROKEN) != 0)
+ {
+ result.m_lowestBreakIteration = sharedPStateFlags.LowestBreakIteration;
+ }
+
+ if ((rootTask != null) && rootTask.IsCompleted) rootTask.Dispose();
+
+ //dispose the partitioner source if it implements IDisposable
+ IDisposable d = null;
+ if (orderablePartitionerSource != null)
+ {
+ d = orderablePartitionerSource as IDisposable;
+ }
+ else
+ {
+ d = partitionerSource as IDisposable;
+ }
+
+ if (d != null)
+ {
+ d.Dispose();
+ }
+
+ // ETW event for Parallel For End
+ if (TplEtwProvider.Log.IsEnabled())
+ {
+ TplEtwProvider.Log.ParallelLoopEnd((callerTask != null ? callerTask.m_taskScheduler.Id : TaskScheduler.Current.Id), (callerTask != null ? callerTask.Id : 0),
+ forkJoinContextID, 0);
+ }
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Internal utility function that implements the OCE filtering behavior for all Parallel.* APIs.
+ /// Throws a single OperationCancelledException object with the token if the Exception collection only contains
+ /// OperationCancelledExceptions with the given CancellationToken.
+ ///
+ /// </summary>
+ /// <param name="excCollection"> The exception collection to filter</param>
+ /// <param name="ct"> The CancellationToken expected on all inner exceptions</param>
+ /// <returns></returns>
+ internal static void ThrowIfReducableToSingleOCE(IEnumerable<Exception> excCollection, CancellationToken ct)
+ {
+ bool bCollectionNotZeroLength = false;
+ if (ct.IsCancellationRequested)
+ {
+ foreach (Exception e in excCollection)
+ {
+ bCollectionNotZeroLength = true;
+ OperationCanceledException oce = e as OperationCanceledException;
+ if (oce == null || oce.CancellationToken != ct)
+ {
+ // mismatch found
+ return;
+ }
+ }
+
+ // all exceptions are OCEs with this token, let's throw it
+ if (bCollectionNotZeroLength) throw new OperationCanceledException(ct);
+ }
+ }
+
+ internal struct LoopTimer
+ {
+ public LoopTimer(int nWorkerTaskIndex)
+ {
+ // This logic ensures that we have a diversity of timeouts across worker tasks (100, 150, 200, 250, 100, etc)
+ // Otherwise all worker will try to timeout at precisely the same point, which is bad if the work is just about to finish
+ int timeOut = s_BaseNotifyPeriodMS + (nWorkerTaskIndex % PlatformHelper.ProcessorCount) * s_NotifyPeriodIncrementMS;
+
+ m_timeLimit = Environment.TickCount + timeOut;
+ }
+
+ public bool LimitExceeded()
+ {
+ Contract.Assert(m_timeLimit != 0, "Probably the default initializer for LoopTimer was used somewhere");
+
+ // comparing against the next expected time saves an addition operation here
+ // Also we omit the comparison for wrap around here. The only side effect is one extra early yield every 38 days.
+ return (Environment.TickCount > m_timeLimit);
+ }
+
+ const int s_BaseNotifyPeriodMS = 100;
+ const int s_NotifyPeriodIncrementMS = 50;
+
+ private int m_timeLimit;
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs
new file mode 100644
index 0000000000..4db3a9d105
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/ParallelLoopState.cs
@@ -0,0 +1,642 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// ParallelState.cs
+//
+//
+// A non-generic and generic parallel state class, used by the Parallel helper class
+// for parallel loop management.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Diagnostics;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+
+// Prevents compiler warnings/errors regarding the use of ref params in Interlocked methods
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+
+ /// <summary>
+ /// Enables iterations of <see cref="T:System.Threading.Tasks.Parallel"/> loops to interact with
+ /// other iterations.
+ /// </summary>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerDisplay("ShouldExitCurrentIteration = {ShouldExitCurrentIteration}")]
+ public class ParallelLoopState
+ {
+ // Derived classes will track a ParallelStateFlags32 or ParallelStateFlags64.
+ // So this is slightly redundant, but it enables us to implement some
+ // methods in this base class.
+ private ParallelLoopStateFlags m_flagsBase;
+
+ internal ParallelLoopState(ParallelLoopStateFlags fbase)
+ {
+ m_flagsBase = fbase;
+ }
+
+ /// <summary>
+ /// Internal/virtual support for ShouldExitCurrentIteration.
+ /// </summary>
+ internal virtual bool InternalShouldExitCurrentIteration
+ {
+ get
+ {
+ Contract.Assert(false);
+ throw new NotSupportedException(
+ Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the current iteration of the loop should exit based
+ /// on requests made by this or other iterations.
+ /// </summary>
+ /// <remarks>
+ /// When an iteration of a loop calls <see cref="Break()"/> or <see cref="Stop()"/>, or
+ /// when one throws an exception, or when the loop is canceled, the <see cref="Parallel"/> class will proactively
+ /// attempt to prohibit additional iterations of the loop from starting execution.
+ /// However, there may be cases where it is unable to prevent additional iterations from starting.
+ /// It may also be the case that a long-running iteration has already begun execution. In such
+ /// cases, iterations may explicitly check the <see cref="ShouldExitCurrentIteration"/> property and
+ /// cease execution if the property returns true.
+ /// </remarks>
+ public bool ShouldExitCurrentIteration
+ {
+ get
+ {
+ return InternalShouldExitCurrentIteration;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether any iteration of the loop has called <see cref="Stop()"/>.
+ /// </summary>
+ public bool IsStopped
+ {
+ get
+ {
+ return ((m_flagsBase.LoopStateFlags & ParallelLoopStateFlags.PLS_STOPPED) != 0);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether any iteration of the loop has thrown an exception that went unhandled by that
+ /// iteration.
+ /// </summary>
+ public bool IsExceptional
+ {
+ get
+ {
+ return ((m_flagsBase.LoopStateFlags & ParallelLoopStateFlags.PLS_EXCEPTIONAL) != 0);
+ }
+ }
+
+ /// <summary>
+ /// Internal/virtual support for LowestBreakIteration.
+ /// </summary>
+ internal virtual long? InternalLowestBreakIteration
+ {
+ get
+ {
+ Contract.Assert(false);
+ throw new NotSupportedException(
+ Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
+ }
+ }
+
+ /// <summary>
+ /// Gets the lowest iteration of the loop from which <see cref="Break()"/> was called.
+ /// </summary>
+ /// <remarks>
+ /// If no iteration of the loop called <see cref="Break()"/>, this property will return null.
+ /// </remarks>
+ public long? LowestBreakIteration
+ {
+ get
+ {
+ return InternalLowestBreakIteration;
+ }
+ }
+
+ /// <summary>
+ /// Communicates that the <see cref="Parallel"/> loop should cease execution at the system's earliest
+ /// convenience.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The <see cref="Break()"/> method was previously called. <see cref="Break()"/> and <see
+ /// cref="Stop()"/> may not be used in combination by iterations of the same loop.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// <see cref="Stop()"/> may be used to communicate to the loop that no other iterations need be run.
+ /// For long-running iterations that may already be executing, <see cref="Stop()"/> causes <see cref="IsStopped"/>
+ /// to return true for all other iterations of the loop, such that another iteration may check <see
+ /// cref="IsStopped"/> and exit early if it's observed to be true.
+ /// </para>
+ /// <para>
+ /// <see cref="Stop()"/> is typically employed in search-based algorithms, where once a result is found,
+ /// no other iterations need be executed.
+ /// </para>
+ /// </remarks>
+ public void Stop()
+ {
+ m_flagsBase.Stop();
+ }
+
+ // Internal/virtual support for Break().
+ internal virtual void InternalBreak()
+ {
+ Contract.Assert(false);
+ throw new NotSupportedException(
+ Environment.GetResourceString("ParallelState_NotSupportedException_UnsupportedMethod"));
+ }
+
+ /// <summary>
+ /// Communicates that the <see cref="Parallel"/> loop should cease execution at the system's earliest
+ /// convenience of iterations beyond the current iteration.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The <see cref="Stop()"/> method was previously called. <see cref="Break()"/> and <see cref="Stop()"/>
+ /// may not be used in combination by iterations of the same loop.
+ /// </exception>
+ /// <remarks>
+ /// <para>
+ /// <see cref="Break()"/> may be used to communicate to the loop that no other iterations after the
+ /// current iteration need be run. For example, if <see cref="Break()"/> is called from the 100th
+ /// iteration of a for loop iterating in parallel from 0 to 1000, all iterations less than 100 should
+ /// still be run, but the iterations from 101 through to 1000 are not necessary.
+ /// </para>
+ /// <para>
+ /// For long-running iterations that may already be executing, <see cref="Break()"/> causes <see
+ /// cref="LowestBreakIteration"/>
+ /// to be set to the current iteration's index if the current index is less than the current value of
+ /// <see cref="LowestBreakIteration"/>.
+ /// </para>
+ /// <para>
+ /// <see cref="Break()"/> is typically employed in search-based algorithms where an ordering is
+ /// present in the data source.
+ /// </para>
+ /// </remarks>
+ public void Break()
+ {
+ InternalBreak();
+ }
+
+ // Helper method to avoid repeating Break() logic between ParallelState32 and ParallelState32<TLocal>
+ internal static void Break(int iteration, ParallelLoopStateFlags32 pflags)
+ {
+ int oldValue = ParallelLoopStateFlags.PLS_NONE;
+
+ // Attempt to change state from "not stopped or broken or canceled or exceptional" to "broken".
+ if (!pflags.AtomicLoopStateUpdate(ParallelLoopStateFlags.PLS_BROKEN,
+ ParallelLoopStateFlags.PLS_STOPPED | ParallelLoopStateFlags.PLS_EXCEPTIONAL | ParallelLoopStateFlags.PLS_CANCELED,
+ ref oldValue))
+ {
+
+ // If we were already stopped, we have a problem
+ if ((oldValue & ParallelLoopStateFlags.PLS_STOPPED) != 0)
+ {
+ throw new InvalidOperationException(
+ Environment.GetResourceString("ParallelState_Break_InvalidOperationException_BreakAfterStop"));
+ }
+ else
+ {
+ // Apparently we previously got cancelled or became exceptional. No action necessary
+ return;
+ }
+ }
+
+ // replace shared LowestBreakIteration with CurrentIteration, but only if CurrentIteration
+ // is less than LowestBreakIteration.
+ int oldLBI = pflags.m_lowestBreakIteration;
+ if (iteration < oldLBI)
+ {
+ SpinWait wait = new SpinWait();
+ while (Interlocked.CompareExchange(
+ ref pflags.m_lowestBreakIteration,
+ iteration,
+ oldLBI) != oldLBI)
+ {
+ wait.SpinOnce();
+ oldLBI = pflags.m_lowestBreakIteration;
+ if (iteration > oldLBI) break;
+ }
+ }
+
+ }
+
+ // Helper method to avoid repeating Break() logic between ParallelState64 and ParallelState64<TLocal>
+ internal static void Break(long iteration, ParallelLoopStateFlags64 pflags)
+ {
+ int oldValue = ParallelLoopStateFlags.PLS_NONE;
+
+ // Attempt to change state from "not stopped or broken or canceled or exceptional" to "broken".
+ if (!pflags.AtomicLoopStateUpdate(ParallelLoopStateFlags.PLS_BROKEN,
+ ParallelLoopStateFlags.PLS_STOPPED | ParallelLoopStateFlags.PLS_EXCEPTIONAL | ParallelLoopStateFlags.PLS_CANCELED,
+ ref oldValue))
+ {
+
+ // If we were already stopped, we have a problem
+ if ((oldValue & ParallelLoopStateFlags.PLS_STOPPED) != 0)
+ {
+ throw new InvalidOperationException(
+ Environment.GetResourceString("ParallelState_Break_InvalidOperationException_BreakAfterStop"));
+ }
+ else
+ {
+ // Apparently we previously got cancelled or became exceptional. No action necessary
+ return;
+ }
+ }
+
+ // replace shared LowestBreakIteration with CurrentIteration, but only if CurrentIteration
+ // is less than LowestBreakIteration.
+ long oldLBI = pflags.LowestBreakIteration;
+ if (iteration < oldLBI)
+ {
+ SpinWait wait = new SpinWait();
+ while (Interlocked.CompareExchange(
+ ref pflags.m_lowestBreakIteration,
+ iteration,
+ oldLBI) != oldLBI)
+ {
+ wait.SpinOnce();
+ oldLBI = pflags.LowestBreakIteration;
+ if (iteration > oldLBI) break;
+ }
+ }
+
+ }
+ }
+
+ internal class ParallelLoopState32 : ParallelLoopState
+ {
+ private ParallelLoopStateFlags32 m_sharedParallelStateFlags;
+ private int m_currentIteration = 0;
+
+ /// <summary>
+ /// Internal constructor to ensure an instance isn't created by users.
+ /// </summary>
+ /// <param name="sharedParallelStateFlags">A flag shared among all threads participating
+ /// in the execution of a certain loop.</param>
+ internal ParallelLoopState32(ParallelLoopStateFlags32 sharedParallelStateFlags)
+ : base(sharedParallelStateFlags)
+ {
+ m_sharedParallelStateFlags = sharedParallelStateFlags;
+ }
+
+ /// <summary>
+ /// Tracks the current loop iteration for the owning task.
+ /// This is used to compute whether or not the task should
+ /// terminate early due to a Break() call.
+ /// </summary>
+ internal int CurrentIteration {
+ get { return m_currentIteration; }
+ set { m_currentIteration = value; }
+ }
+
+ /// <summary>
+ /// Returns true if we should be exiting from the current iteration
+ /// due to Stop(), Break() or exception.
+ /// </summary>
+ internal override bool InternalShouldExitCurrentIteration
+ {
+ get { return m_sharedParallelStateFlags.ShouldExitLoop(CurrentIteration); }
+ }
+
+ /// <summary>
+ /// Returns the lowest iteration at which Break() has been called, or
+ /// null if Break() has not yet been called.
+ /// </summary>
+ internal override long? InternalLowestBreakIteration
+ {
+ get {return m_sharedParallelStateFlags.NullableLowestBreakIteration; }
+ }
+
+ /// <summary>
+ /// Communicates that parallel tasks should stop when they reach a specified iteration element.
+ /// (which is CurrentIteration of the caller).
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">Break() called after Stop().</exception>
+ /// <remarks>
+ /// This is shared with all other concurrent threads in the system which are participating in the
+ /// loop's execution. After calling Break(), no additional iterations will be executed on
+ /// the current thread, and other worker threads will execute once they get beyond the calling iteration.
+ /// </remarks>
+ internal override void InternalBreak()
+ {
+ ParallelLoopState.Break(CurrentIteration, m_sharedParallelStateFlags);
+ }
+ }
+
+ /// <summary>
+ /// Allows independent iterations of a parallel loop to interact with other iterations.
+ /// </summary>
+ internal class ParallelLoopState64 : ParallelLoopState
+ {
+ private ParallelLoopStateFlags64 m_sharedParallelStateFlags;
+ private long m_currentIteration = 0;
+
+ /// <summary>
+ /// Internal constructor to ensure an instance isn't created by users.
+ /// </summary>
+ /// <param name="sharedParallelStateFlags">A flag shared among all threads participating
+ /// in the execution of a certain loop.</param>
+ internal ParallelLoopState64(ParallelLoopStateFlags64 sharedParallelStateFlags)
+ : base(sharedParallelStateFlags)
+ {
+ m_sharedParallelStateFlags = sharedParallelStateFlags;
+ }
+
+ /// <summary>
+ /// Tracks the current loop iteration for the owning task.
+ /// This is used to compute whether or not the task should
+ /// terminate early due to a Break() call.
+ /// </summary>
+ internal long CurrentIteration
+ {
+ // No interlocks needed, because this value is only accessed in a single thread.
+ get {return m_currentIteration;}
+ set {m_currentIteration = value; }
+ }
+
+ /// <summary>
+ /// Returns true if we should be exiting from the current iteration
+ /// due to Stop(), Break() or exception.
+ /// </summary>
+ internal override bool InternalShouldExitCurrentIteration
+ {
+ get { return m_sharedParallelStateFlags.ShouldExitLoop(CurrentIteration); }
+ }
+
+ /// <summary>
+ /// Returns the lowest iteration at which Break() has been called, or
+ /// null if Break() has not yet been called.
+ /// </summary>
+ internal override long? InternalLowestBreakIteration
+ {
+ // We don't need to worry about torn read/write here because
+ // ParallelStateFlags64.LowestBreakIteration property is protected
+ // by an Interlocked.Read().
+ get { return m_sharedParallelStateFlags.NullableLowestBreakIteration; }
+ }
+
+ /// <summary>
+ /// Communicates that parallel tasks should stop when they reach a specified iteration element.
+ /// (which is CurrentIteration of the caller).
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">Break() called after Stop().</exception>
+ /// <remarks>
+ /// Atomically sets shared StoppedBroken flag to BROKEN, then atomically sets shared
+ /// LowestBreakIteration to CurrentIteration, but only if CurrentIteration is less than
+ /// LowestBreakIteration.
+ /// </remarks>
+ internal override void InternalBreak()
+ {
+ ParallelLoopState.Break(CurrentIteration, m_sharedParallelStateFlags);
+ }
+
+ }
+
+ /// <summary>
+ /// State information that is common between ParallelStateFlags class
+ /// and ParallelStateFlags64 class.
+ /// </summary>
+ internal class ParallelLoopStateFlags
+ {
+ internal static int PLS_NONE;
+ internal static int PLS_EXCEPTIONAL = 1;
+ internal static int PLS_BROKEN = 2;
+ internal static int PLS_STOPPED = 4;
+ internal static int PLS_CANCELED = 8;
+
+ private volatile int m_LoopStateFlags = PLS_NONE;
+
+ internal int LoopStateFlags
+ {
+ get { return m_LoopStateFlags; }
+ }
+
+ internal bool AtomicLoopStateUpdate(int newState, int illegalStates)
+ {
+ int oldState = 0;
+ return AtomicLoopStateUpdate(newState, illegalStates, ref oldState);
+ }
+
+ internal bool AtomicLoopStateUpdate(int newState, int illegalStates, ref int oldState)
+ {
+ SpinWait sw = new SpinWait();
+
+ do
+ {
+ oldState = m_LoopStateFlags;
+ if ((oldState & illegalStates) != 0) return false;
+ if (Interlocked.CompareExchange(ref m_LoopStateFlags, oldState | newState, oldState) == oldState)
+ {
+ return true;
+ }
+ sw.SpinOnce();
+ } while (true);
+
+ }
+
+ internal void SetExceptional()
+ {
+ // we can set the exceptional flag regardless of the state of other bits.
+ AtomicLoopStateUpdate(PLS_EXCEPTIONAL, PLS_NONE);
+ }
+
+ internal void Stop()
+ {
+ // disallow setting of PLS_STOPPED bit only if PLS_BROKEN was already set
+ if (!AtomicLoopStateUpdate(PLS_STOPPED, PLS_BROKEN))
+ {
+ throw new InvalidOperationException(
+ Environment.GetResourceString("ParallelState_Stop_InvalidOperationException_StopAfterBreak"));
+ }
+ }
+
+ // Returns true if StoppedBroken is updated to PLS_CANCELED.
+ internal bool Cancel()
+ {
+ // we can set the canceled flag regardless of the state of other bits.
+ return (AtomicLoopStateUpdate(PLS_CANCELED, PLS_NONE));
+ }
+ }
+
+ /// <summary>
+ /// An internal class used to share accounting information in 32-bit versions
+ /// of For()/ForEach() loops.
+ /// </summary>
+ internal class ParallelLoopStateFlags32 : ParallelLoopStateFlags
+ {
+ // Records the lowest iteration at which a Break() has been called,
+ // or Int32.MaxValue if no break has been called. Used directly
+ // by Break().
+ internal volatile int m_lowestBreakIteration = Int32.MaxValue;
+
+ // Not strictly necessary, but maintains consistency with ParallelStateFlags64
+ internal int LowestBreakIteration
+ {
+ get { return m_lowestBreakIteration; }
+ }
+
+ // Does some processing to convert m_lowestBreakIteration to a long?.
+ internal long? NullableLowestBreakIteration
+ {
+ get
+ {
+ if (m_lowestBreakIteration == Int32.MaxValue) return null;
+ else
+ {
+ // protect against torn read of 64-bit value
+ long rval = m_lowestBreakIteration;
+ if (IntPtr.Size >= 8) return rval;
+ else return Interlocked.Read(ref rval);
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// Lets the caller know whether or not to prematurely exit the For/ForEach loop.
+ /// If this returns true, then exit the loop. Otherwise, keep going.
+ /// </summary>
+ /// <param name="CallerIteration">The caller's current iteration point
+ /// in the loop.</param>
+ /// <remarks>
+ /// The loop should exit on any one of the following conditions:
+ /// (1) Stop() has been called by one or more tasks.
+ /// (2) An exception has been raised by one or more tasks.
+ /// (3) Break() has been called by one or more tasks, and
+ /// CallerIteration exceeds the (lowest) iteration at which
+ /// Break() was called.
+ /// (4) The loop was canceled.
+ /// </remarks>
+ internal bool ShouldExitLoop(int CallerIteration)
+ {
+ int flags = LoopStateFlags;
+ return (flags != PLS_NONE && (
+ ((flags & (PLS_EXCEPTIONAL | PLS_STOPPED | PLS_CANCELED)) != 0) ||
+ (((flags & PLS_BROKEN) != 0) && (CallerIteration > LowestBreakIteration))));
+ }
+
+ // This lighter version of ShouldExitLoop will be used when the body type doesn't contain a state.
+ // Since simpler bodies cannot stop or break, we can safely skip checks for those flags here.
+ internal bool ShouldExitLoop()
+ {
+ int flags = LoopStateFlags;
+ return ((flags != PLS_NONE) && ((flags & (PLS_EXCEPTIONAL | PLS_CANCELED)) != 0));
+ }
+ }
+
+ /// <summary>
+ /// An internal class used to share accounting information in 64-bit versions
+ /// of For()/ForEach() loops.
+ /// </summary>
+ internal class ParallelLoopStateFlags64 : ParallelLoopStateFlags
+ {
+ // Records the lowest iteration at which a Break() has been called,
+ // or Int64.MaxValue if no break has been called. Used directly
+ // by Break().
+ internal long m_lowestBreakIteration = Int64.MaxValue;
+
+ // Performs a conditionally interlocked read of m_lowestBreakIteration.
+ internal long LowestBreakIteration
+ {
+ get
+ {
+ if (IntPtr.Size >= 8) return m_lowestBreakIteration;
+ else return Interlocked.Read(ref m_lowestBreakIteration);
+ }
+ }
+
+ // Does some processing to convert m_lowestBreakIteration to a long?.
+ internal long? NullableLowestBreakIteration
+ {
+ get
+ {
+ if (m_lowestBreakIteration == Int64.MaxValue) return null;
+ else
+ {
+ if (IntPtr.Size >= 8) return m_lowestBreakIteration;
+ else return Interlocked.Read(ref m_lowestBreakIteration);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Lets the caller know whether or not to prematurely exit the For/ForEach loop.
+ /// If this returns true, then exit the loop. Otherwise, keep going.
+ /// </summary>
+ /// <param name="CallerIteration">The caller's current iteration point
+ /// in the loop.</param>
+ /// <remarks>
+ /// The loop should exit on any one of the following conditions:
+ /// (1) Stop() has been called by one or more tasks.
+ /// (2) An exception has been raised by one or more tasks.
+ /// (3) Break() has been called by one or more tasks, and
+ /// CallerIteration exceeds the (lowest) iteration at which
+ /// Break() was called.
+ /// (4) The loop has been canceled.
+ /// </remarks>
+ internal bool ShouldExitLoop(long CallerIteration)
+ {
+ int flags = LoopStateFlags;
+ return (flags != PLS_NONE && (
+ ((flags & (PLS_EXCEPTIONAL | PLS_STOPPED | PLS_CANCELED)) != 0) ||
+ (((flags & PLS_BROKEN) != 0) && (CallerIteration > LowestBreakIteration))));
+ }
+
+ // This lighter version of ShouldExitLoop will be used when the body type doesn't contain a state.
+ // Since simpler bodies cannot stop or break, we can safely skip checks for those flags here.
+ internal bool ShouldExitLoop()
+ {
+ int flags = LoopStateFlags;
+ return ((flags != PLS_NONE) && ((flags & (PLS_EXCEPTIONAL | PLS_CANCELED)) != 0));
+ }
+ }
+
+ /// <summary>
+ /// Provides completion status on the execution of a <see cref="Parallel"/> loop.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="IsCompleted"/> returns true, then the loop ran to completion, such that all iterations
+ /// of the loop were executed. If <see cref="IsCompleted"/> returns false and <see
+ /// cref="LowestBreakIteration"/> returns null, a call to <see
+ /// cref="System.Threading.Tasks.ParallelLoopState.Stop"/> was used to end the loop prematurely. If <see
+ /// cref="IsCompleted"/> returns false and <see cref="LowestBreakIteration"/> returns a non-null integral
+ /// value, <see cref="System.Threading.Tasks.ParallelLoopState.Break()"/> was used to end the loop prematurely.
+ /// </remarks>
+ public struct ParallelLoopResult
+ {
+ internal bool m_completed;
+ internal long? m_lowestBreakIteration;
+
+ /// <summary>
+ /// Gets whether the loop ran to completion, such that all iterations of the loop were executed
+ /// and the loop didn't receive a request to end prematurely.
+ /// </summary>
+ public bool IsCompleted { get { return m_completed; } }
+
+ /// <summary>
+ /// Gets the index of the lowest iteration from which <see
+ /// cref="System.Threading.Tasks.ParallelLoopState.Break()"/>
+ /// was called.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="System.Threading.Tasks.ParallelLoopState.Break()"/> was not employed, this property will
+ /// return null.
+ /// </remarks>
+ public long? LowestBreakIteration { get { return m_lowestBreakIteration; } }
+ }
+
+}
+
+#pragma warning restore 0420
diff --git a/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs b/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs
new file mode 100644
index 0000000000..c4b66c41a9
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/ParallelRangeManager.cs
@@ -0,0 +1,278 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Implements the algorithm for distributing loop indices to parallel loop workers
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Threading;
+using System.Diagnostics.Contracts;
+
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Represents an index range
+ /// </summary>
+ internal struct IndexRange
+ {
+ // the From and To values for this range. These do not change.
+ internal long m_nFromInclusive;
+ internal long m_nToExclusive;
+
+ // The shared index, stored as the offset from nFromInclusive. Using an offset rather than the actual
+ // value saves us from overflows that can happen due to multiple workers racing to increment this.
+ // All updates to this field need to be interlocked.
+ internal volatile Shared<long> m_nSharedCurrentIndexOffset;
+
+ // to be set to 1 by the worker that finishes this range. It's OK to do a non-interlocked write here.
+ internal int m_bRangeFinished;
+ }
+
+
+ /// <summary>
+ /// The RangeWorker struct wraps the state needed by a task that services the parallel loop
+ /// </summary>
+ internal struct RangeWorker
+ {
+ // reference to the IndexRange array allocated by the range manager
+ internal readonly IndexRange[] m_indexRanges;
+
+ // index of the current index range that this worker is grabbing chunks from
+ internal int m_nCurrentIndexRange;
+
+ // the step for this loop. Duplicated here for quick access (rather than jumping to rangemanager)
+ internal long m_nStep;
+
+ // increment value is the current amount that this worker will use
+ // to increment the shared index of the range it's working on
+ internal long m_nIncrementValue;
+
+ // the increment value is doubled each time this worker finds work, and is capped at this value
+ internal readonly long m_nMaxIncrementValue;
+
+ /// <summary>
+ /// Initializes a RangeWorker struct
+ /// </summary>
+ internal RangeWorker(IndexRange[] ranges, int nInitialRange, long nStep)
+ {
+ m_indexRanges = ranges;
+ m_nCurrentIndexRange = nInitialRange;
+ m_nStep = nStep;
+
+ m_nIncrementValue = nStep;
+
+ m_nMaxIncrementValue = Parallel.DEFAULT_LOOP_STRIDE * nStep;
+ }
+
+ /// <summary>
+ /// Implements the core work search algorithm that will be used for this range worker.
+ /// </summary>
+ ///
+ /// Usage pattern is:
+ /// 1) the thread associated with this rangeworker calls FindNewWork
+ /// 2) if we return true, the worker uses the nFromInclusiveLocal and nToExclusiveLocal values
+ /// to execute the sequential loop
+ /// 3) if we return false it means there is no more work left. It's time to quit.
+ ///
+ internal bool FindNewWork(out long nFromInclusiveLocal, out long nToExclusiveLocal)
+ {
+ // since we iterate over index ranges circularly, we will use the
+ // count of visited ranges as our exit condition
+ int numIndexRangesToVisit = m_indexRanges.Length;
+
+ do
+ {
+ // local snap to save array access bounds checks in places where we only read fields
+ IndexRange currentRange = m_indexRanges[m_nCurrentIndexRange];
+
+ if (currentRange.m_bRangeFinished == 0)
+ {
+ if (m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset == null)
+ {
+ Interlocked.CompareExchange(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset, new Shared<long>(0), null);
+ }
+
+ // this access needs to be on the array slot
+ long nMyOffset = Interlocked.Add(ref m_indexRanges[m_nCurrentIndexRange].m_nSharedCurrentIndexOffset.Value,
+ m_nIncrementValue) - m_nIncrementValue;
+
+ if (currentRange.m_nToExclusive - currentRange.m_nFromInclusive > nMyOffset)
+ {
+ // we found work
+
+ nFromInclusiveLocal = currentRange.m_nFromInclusive + nMyOffset;
+ nToExclusiveLocal = nFromInclusiveLocal + m_nIncrementValue;
+
+ // Check for going past end of range, or wrapping
+ if ( (nToExclusiveLocal > currentRange.m_nToExclusive) || (nToExclusiveLocal < currentRange.m_nFromInclusive) )
+ {
+ nToExclusiveLocal = currentRange.m_nToExclusive;
+ }
+
+ // We will double our unit of increment until it reaches the maximum.
+ if (m_nIncrementValue < m_nMaxIncrementValue)
+ {
+ m_nIncrementValue *= 2;
+ if (m_nIncrementValue > m_nMaxIncrementValue)
+ {
+ m_nIncrementValue = m_nMaxIncrementValue;
+ }
+ }
+
+ return true;
+ }
+ else
+ {
+ // this index range is completed, mark it so that others can skip it quickly
+ Interlocked.Exchange(ref m_indexRanges[m_nCurrentIndexRange].m_bRangeFinished, 1);
+ }
+ }
+
+ // move on to the next index range, in circular order.
+ m_nCurrentIndexRange = (m_nCurrentIndexRange + 1) % m_indexRanges.Length;
+ numIndexRangesToVisit--;
+
+ } while (numIndexRangesToVisit > 0);
+ // we've visited all index ranges possible => there's no work remaining
+
+ nFromInclusiveLocal = 0;
+ nToExclusiveLocal = 0;
+
+ return false;
+ }
+
+
+ /// <summary>
+ /// 32 bit integer version of FindNewWork. Assumes the ranges were initialized with 32 bit values.
+ /// </summary>
+ internal bool FindNewWork32(out int nFromInclusiveLocal32, out int nToExclusiveLocal32)
+ {
+ long nFromInclusiveLocal;
+ long nToExclusiveLocal;
+
+ bool bRetVal = FindNewWork(out nFromInclusiveLocal, out nToExclusiveLocal);
+
+ Contract.Assert((nFromInclusiveLocal <= Int32.MaxValue) && (nFromInclusiveLocal >= Int32.MinValue) &&
+ (nToExclusiveLocal <= Int32.MaxValue) && (nToExclusiveLocal >= Int32.MinValue));
+
+ // convert to 32 bit before returning
+ nFromInclusiveLocal32 = (int)nFromInclusiveLocal;
+ nToExclusiveLocal32 = (int)nToExclusiveLocal;
+
+ return bRetVal;
+ }
+ }
+
+
+ /// <summary>
+ /// Represents the entire loop operation, keeping track of workers and ranges.
+ /// </summary>
+ ///
+ /// The usage pattern is:
+ /// 1) The Parallel loop entry function (ForWorker) creates an instance of this class
+ /// 2) Every thread joining to service the parallel loop calls RegisterWorker to grab a
+ /// RangeWorker struct to wrap the state it will need to find and execute work,
+ /// and they keep interacting with that struct until the end of the loop
+ internal class RangeManager
+ {
+ internal readonly IndexRange[] m_indexRanges;
+
+ internal int m_nCurrentIndexRangeToAssign;
+ internal long m_nStep;
+
+ /// <summary>
+ /// Initializes a RangeManager with the given loop parameters, and the desired number of outer ranges
+ /// </summary>
+ internal RangeManager(long nFromInclusive, long nToExclusive, long nStep, int nNumExpectedWorkers)
+ {
+ m_nCurrentIndexRangeToAssign = 0;
+ m_nStep = nStep;
+
+ // Our signed math breaks down w/ nNumExpectedWorkers == 1. So change it to 2.
+ if (nNumExpectedWorkers == 1)
+ nNumExpectedWorkers = 2;
+
+ //
+ // calculate the size of each index range
+ //
+
+ ulong uSpan = (ulong)(nToExclusive - nFromInclusive);
+ ulong uRangeSize = uSpan / (ulong) nNumExpectedWorkers; // rough estimate first
+
+ uRangeSize -= uRangeSize % (ulong) nStep; // snap to multiples of nStep
+ // otherwise index range transitions will derail us from nStep
+
+ if (uRangeSize == 0)
+ {
+ uRangeSize = (ulong) nStep;
+ }
+
+ //
+ // find the actual number of index ranges we will need
+ //
+ Contract.Assert((uSpan / uRangeSize) < Int32.MaxValue);
+
+ int nNumRanges = (int)(uSpan / uRangeSize);
+
+ if (uSpan % uRangeSize != 0)
+ {
+ nNumRanges++;
+ }
+
+
+ // Convert to signed so the rest of the logic works.
+ // Should be fine so long as uRangeSize < Int64.MaxValue, which we guaranteed by setting #workers >= 2.
+ long nRangeSize = (long)uRangeSize;
+
+ // allocate the array of index ranges
+ m_indexRanges = new IndexRange[nNumRanges];
+
+ long nCurrentIndex = nFromInclusive;
+ for (int i = 0; i < nNumRanges; i++)
+ {
+ // the fromInclusive of the new index range is always on nCurrentIndex
+ m_indexRanges[i].m_nFromInclusive = nCurrentIndex;
+ m_indexRanges[i].m_nSharedCurrentIndexOffset = null;
+ m_indexRanges[i].m_bRangeFinished = 0;
+
+ // now increment it to find the toExclusive value for our range
+ nCurrentIndex += nRangeSize;
+
+ // detect integer overflow or range overage and snap to nToExclusive
+ if (nCurrentIndex < nCurrentIndex - nRangeSize ||
+ nCurrentIndex > nToExclusive)
+ {
+ // this should only happen at the last index
+ Contract.Assert(i == nNumRanges - 1);
+
+ nCurrentIndex = nToExclusive;
+ }
+
+ // now that the end point of the new range is calculated, assign it.
+ m_indexRanges[i].m_nToExclusive = nCurrentIndex;
+ }
+ }
+
+ /// <summary>
+ /// The function that needs to be called by each new worker thread servicing the parallel loop
+ /// in order to get a RangeWorker struct that wraps the state for finding and executing indices
+ /// </summary>
+ internal RangeWorker RegisterNewWorker()
+ {
+ Contract.Assert(m_indexRanges != null && m_indexRanges.Length != 0);
+
+ int nInitialRange = (Interlocked.Increment(ref m_nCurrentIndexRangeToAssign) - 1) % m_indexRanges.Length;
+
+ return new RangeWorker(m_indexRanges, nInitialRange, m_nStep);
+ }
+ }
+}
+#pragma warning restore 0420
diff --git a/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
new file mode 100644
index 0000000000..462ee0a9bd
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/ProducerConsumerQueues.cs
@@ -0,0 +1,553 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Specialized producer/consumer queues.
+//
+//
+// ************<IMPORTANT NOTE>*************
+//
+// src\ndp\clr\src\bcl\system\threading\tasks\producerConsumerQueue.cs
+// src\ndp\fx\src\dataflow\system\threading\tasks\dataflow\internal\producerConsumerQueue.cs
+// Keep both of them consistent by changing the other file when you change this one, also avoid:
+// 1- To reference interneal types in mscorlib
+// 2- To reference any dataflow specific types
+// This should be fixed post Dev11 when this class becomes public.
+//
+// ************</IMPORTANT NOTE>*************
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Collections;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using System.Runtime.InteropServices;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>Represents a producer/consumer queue used internally by dataflow blocks.</summary>
+ /// <typeparam name="T">Specifies the type of data contained in the queue.</typeparam>
+ internal interface IProducerConsumerQueue<T> : IEnumerable<T>
+ {
+ /// <summary>Enqueues an item into the queue.</summary>
+ /// <param name="item">The item to enqueue.</param>
+ /// <remarks>This method is meant to be thread-safe subject to the particular nature of the implementation.</remarks>
+ void Enqueue(T item);
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ /// <remarks>This method is meant to be thread-safe subject to the particular nature of the implementation.</remarks>
+ bool TryDequeue(out T result);
+
+ /// <summary>Gets whether the collection is currently empty.</summary>
+ /// <remarks>This method may or may not be thread-safe.</remarks>
+ bool IsEmpty { get; }
+
+ /// <summary>Gets the number of items in the collection.</summary>
+ /// <remarks>In many implementations, this method will not be thread-safe.</remarks>
+ int Count { get; }
+
+ /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
+ /// <param name="syncObj">The sync object used to lock</param>
+ /// <returns>The collection count</returns>
+ int GetCountSafe(object syncObj);
+ }
+
+ /// <summary>
+ /// Provides a producer/consumer queue safe to be used by any number of producers and consumers concurrently.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of data contained in the queue.</typeparam>
+ [DebuggerDisplay("Count = {Count}")]
+ internal sealed class MultiProducerMultiConsumerQueue<T> : ConcurrentQueue<T>, IProducerConsumerQueue<T>
+ {
+ /// <summary>Enqueues an item into the queue.</summary>
+ /// <param name="item">The item to enqueue.</param>
+ void IProducerConsumerQueue<T>.Enqueue(T item) { base.Enqueue(item); }
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ bool IProducerConsumerQueue<T>.TryDequeue(out T result) { return base.TryDequeue(out result); }
+
+ /// <summary>Gets whether the collection is currently empty.</summary>
+ bool IProducerConsumerQueue<T>.IsEmpty { get { return base.IsEmpty; } }
+
+ /// <summary>Gets the number of items in the collection.</summary>
+ int IProducerConsumerQueue<T>.Count { get { return base.Count; } }
+
+ /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
+ /// <remarks>ConcurrentQueue.Count is thread safe, no need to acquire the lock.</remarks>
+ int IProducerConsumerQueue<T>.GetCountSafe(object syncObj) { return base.Count; }
+ }
+
+ /// <summary>
+ /// Provides a producer/consumer queue safe to be used by only one producer and one consumer concurrently.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of data contained in the queue.</typeparam>
+ [DebuggerDisplay("Count = {Count}")]
+ [DebuggerTypeProxy(typeof(SingleProducerSingleConsumerQueue<>.SingleProducerSingleConsumerQueue_DebugView))]
+ internal sealed class SingleProducerSingleConsumerQueue<T> : IProducerConsumerQueue<T>
+ {
+ // Design:
+ //
+ // SingleProducerSingleConsumerQueue (SPSCQueue) is a concurrent queue designed to be used
+ // by one producer thread and one consumer thread. SPSCQueue does not work correctly when used by
+ // multiple producer threads concurrently or multiple consumer threads concurrently.
+ //
+ // SPSCQueue is based on segments that behave like circular buffers. Each circular buffer is represented
+ // as an array with two indexes: m_first and m_last. m_first is the index of the array slot for the consumer
+ // to read next, and m_last is the slot for the producer to write next. The circular buffer is empty when
+ // (m_first == m_last), and full when ((m_last+1) % m_array.Length == m_first).
+ //
+ // Since m_first is only ever modified by the consumer thread and m_last by the producer, the two indices can
+ // be updated without interlocked operations. As long as the queue size fits inside a single circular buffer,
+ // enqueues and dequeues simply advance the corresponding indices around the circular buffer. If an enqueue finds
+ // that there is no room in the existing buffer, however, a new circular buffer is allocated that is twice as big
+ // as the old buffer. From then on, the producer will insert values into the new buffer. The consumer will first
+ // empty out the old buffer and only then follow the producer into the new (larger) buffer.
+ //
+ // As described above, the enqueue operation on the fast path only modifies the m_first field of the current segment.
+ // However, it also needs to read m_last in order to verify that there is room in the current segment. Similarly, the
+ // dequeue operation on the fast path only needs to modify m_last, but also needs to read m_first to verify that the
+ // queue is non-empty. This results in true cache line sharing between the producer and the consumer.
+ //
+ // The cache line sharing issue can be mitigating by having a possibly stale copy of m_first that is owned by the producer,
+ // and a possibly stale copy of m_last that is owned by the consumer. So, the consumer state is described using
+ // (m_first, m_lastCopy) and the producer state using (m_firstCopy, m_last). The consumer state is separated from
+ // the producer state by padding, which allows fast-path enqueues and dequeues from hitting shared cache lines.
+ // m_lastCopy is the consumer's copy of m_last. Whenever the consumer can tell that there is room in the buffer
+ // simply by observing m_lastCopy, the consumer thread does not need to read m_last and thus encounter a cache miss. Only
+ // when the buffer appears to be empty will the consumer refresh m_lastCopy from m_last. m_firstCopy is used by the producer
+ // in the same way to avoid reading m_first on the hot path.
+
+ /// <summary>The initial size to use for segments (in number of elements).</summary>
+ private const int INIT_SEGMENT_SIZE = 32; // must be a power of 2
+ /// <summary>The maximum size to use for segments (in number of elements).</summary>
+ private const int MAX_SEGMENT_SIZE = 0x1000000; // this could be made as large as Int32.MaxValue / 2
+
+ /// <summary>The head of the linked list of segments.</summary>
+ private volatile Segment m_head;
+ /// <summary>The tail of the linked list of segments.</summary>
+ private volatile Segment m_tail;
+
+ /// <summary>Initializes the queue.</summary>
+ internal SingleProducerSingleConsumerQueue()
+ {
+ // Validate constants in ctor rather than in an explicit cctor that would cause perf degradation
+ Contract.Assert(INIT_SEGMENT_SIZE > 0, "Initial segment size must be > 0.");
+ Contract.Assert((INIT_SEGMENT_SIZE & (INIT_SEGMENT_SIZE - 1)) == 0, "Initial segment size must be a power of 2");
+ Contract.Assert(INIT_SEGMENT_SIZE <= MAX_SEGMENT_SIZE, "Initial segment size should be <= maximum.");
+ Contract.Assert(MAX_SEGMENT_SIZE < Int32.MaxValue / 2, "Max segment size * 2 must be < Int32.MaxValue, or else overflow could occur.");
+
+ // Initialize the queue
+ m_head = m_tail = new Segment(INIT_SEGMENT_SIZE);
+ }
+
+ /// <summary>Enqueues an item into the queue.</summary>
+ /// <param name="item">The item to enqueue.</param>
+ public void Enqueue(T item)
+ {
+ Segment segment = m_tail;
+ var array = segment.m_array;
+ int last = segment.m_state.m_last; // local copy to avoid multiple volatile reads
+
+ // Fast path: there's obviously room in the current segment
+ int tail2 = (last + 1) & (array.Length - 1);
+ if (tail2 != segment.m_state.m_firstCopy)
+ {
+ array[last] = item;
+ segment.m_state.m_last = tail2;
+ }
+ // Slow path: there may not be room in the current segment.
+ else EnqueueSlow(item, ref segment);
+ }
+
+ /// <summary>Enqueues an item into the queue.</summary>
+ /// <param name="item">The item to enqueue.</param>
+ /// <param name="segment">The segment in which to first attempt to store the item.</param>
+ private void EnqueueSlow(T item, ref Segment segment)
+ {
+ Contract.Requires(segment != null, "Expected a non-null segment.");
+
+ if (segment.m_state.m_firstCopy != segment.m_state.m_first)
+ {
+ segment.m_state.m_firstCopy = segment.m_state.m_first;
+ Enqueue(item); // will only recur once for this enqueue operation
+ return;
+ }
+
+ int newSegmentSize = m_tail.m_array.Length << 1; // double size
+ Contract.Assert(newSegmentSize > 0, "The max size should always be small enough that we don't overflow.");
+ if (newSegmentSize > MAX_SEGMENT_SIZE) newSegmentSize = MAX_SEGMENT_SIZE;
+
+ var newSegment = new Segment(newSegmentSize);
+ newSegment.m_array[0] = item;
+ newSegment.m_state.m_last = 1;
+ newSegment.m_state.m_lastCopy = 1;
+
+ try { } finally
+ {
+ // Finally block to protect against corruption due to a thread abort
+ // between setting m_next and setting m_tail.
+ Volatile.Write(ref m_tail.m_next, newSegment); // ensure segment not published until item is fully stored
+ m_tail = newSegment;
+ }
+ }
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ public bool TryDequeue(out T result)
+ {
+ Segment segment = m_head;
+ var array = segment.m_array;
+ int first = segment.m_state.m_first; // local copy to avoid multiple volatile reads
+
+ // Fast path: there's obviously data available in the current segment
+ if (first != segment.m_state.m_lastCopy)
+ {
+ result = array[first];
+ array[first] = default(T); // Clear the slot to release the element
+ segment.m_state.m_first = (first + 1) & (array.Length - 1);
+ return true;
+ }
+ // Slow path: there may not be data available in the current segment
+ else return TryDequeueSlow(ref segment, ref array, out result);
+ }
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="array">The array from which the item was dequeued.</param>
+ /// <param name="segment">The segment from which the item was dequeued.</param>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ private bool TryDequeueSlow(ref Segment segment, ref T[] array, out T result)
+ {
+ Contract.Requires(segment != null, "Expected a non-null segment.");
+ Contract.Requires(array != null, "Expected a non-null item array.");
+
+ if (segment.m_state.m_last != segment.m_state.m_lastCopy)
+ {
+ segment.m_state.m_lastCopy = segment.m_state.m_last;
+ return TryDequeue(out result); // will only recur once for this dequeue operation
+ }
+
+ if (segment.m_next != null && segment.m_state.m_first == segment.m_state.m_last)
+ {
+ segment = segment.m_next;
+ array = segment.m_array;
+ m_head = segment;
+ }
+
+ var first = segment.m_state.m_first; // local copy to avoid extraneous volatile reads
+
+ if (first == segment.m_state.m_last)
+ {
+ result = default(T);
+ return false;
+ }
+
+ result = array[first];
+ array[first] = default(T); // Clear the slot to release the element
+ segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1);
+ segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy
+
+ return true;
+ }
+
+ /// <summary>Attempts to peek at an item in the queue.</summary>
+ /// <param name="result">The peeked item.</param>
+ /// <returns>true if an item could be peeked; otherwise, false.</returns>
+ public bool TryPeek(out T result)
+ {
+ Segment segment = m_head;
+ var array = segment.m_array;
+ int first = segment.m_state.m_first; // local copy to avoid multiple volatile reads
+
+ // Fast path: there's obviously data available in the current segment
+ if (first != segment.m_state.m_lastCopy)
+ {
+ result = array[first];
+ return true;
+ }
+ // Slow path: there may not be data available in the current segment
+ else return TryPeekSlow(ref segment, ref array, out result);
+ }
+
+ /// <summary>Attempts to peek at an item in the queue.</summary>
+ /// <param name="array">The array from which the item is peeked.</param>
+ /// <param name="segment">The segment from which the item is peeked.</param>
+ /// <param name="result">The peeked item.</param>
+ /// <returns>true if an item could be peeked; otherwise, false.</returns>
+ private bool TryPeekSlow(ref Segment segment, ref T[] array, out T result)
+ {
+ Contract.Requires(segment != null, "Expected a non-null segment.");
+ Contract.Requires(array != null, "Expected a non-null item array.");
+
+ if (segment.m_state.m_last != segment.m_state.m_lastCopy)
+ {
+ segment.m_state.m_lastCopy = segment.m_state.m_last;
+ return TryPeek(out result); // will only recur once for this peek operation
+ }
+
+ if (segment.m_next != null && segment.m_state.m_first == segment.m_state.m_last)
+ {
+ segment = segment.m_next;
+ array = segment.m_array;
+ m_head = segment;
+ }
+
+ var first = segment.m_state.m_first; // local copy to avoid extraneous volatile reads
+
+ if (first == segment.m_state.m_last)
+ {
+ result = default(T);
+ return false;
+ }
+
+ result = array[first];
+ return true;
+ }
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="predicate">The predicate that must return true for the item to be dequeued. If null, all items implicitly return true.</param>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ public bool TryDequeueIf(Predicate<T> predicate, out T result)
+ {
+ Segment segment = m_head;
+ var array = segment.m_array;
+ int first = segment.m_state.m_first; // local copy to avoid multiple volatile reads
+
+ // Fast path: there's obviously data available in the current segment
+ if (first != segment.m_state.m_lastCopy)
+ {
+ result = array[first];
+ if (predicate == null || predicate(result))
+ {
+ array[first] = default(T); // Clear the slot to release the element
+ segment.m_state.m_first = (first + 1) & (array.Length - 1);
+ return true;
+ }
+ else
+ {
+ result = default(T);
+ return false;
+ }
+ }
+ // Slow path: there may not be data available in the current segment
+ else return TryDequeueIfSlow(predicate, ref segment, ref array, out result);
+ }
+
+ /// <summary>Attempts to dequeue an item from the queue.</summary>
+ /// <param name="predicate">The predicate that must return true for the item to be dequeued. If null, all items implicitly return true.</param>
+ /// <param name="array">The array from which the item was dequeued.</param>
+ /// <param name="segment">The segment from which the item was dequeued.</param>
+ /// <param name="result">The dequeued item.</param>
+ /// <returns>true if an item could be dequeued; otherwise, false.</returns>
+ private bool TryDequeueIfSlow(Predicate<T> predicate, ref Segment segment, ref T[] array, out T result)
+ {
+ Contract.Requires(segment != null, "Expected a non-null segment.");
+ Contract.Requires(array != null, "Expected a non-null item array.");
+
+ if (segment.m_state.m_last != segment.m_state.m_lastCopy)
+ {
+ segment.m_state.m_lastCopy = segment.m_state.m_last;
+ return TryDequeueIf(predicate, out result); // will only recur once for this dequeue operation
+ }
+
+ if (segment.m_next != null && segment.m_state.m_first == segment.m_state.m_last)
+ {
+ segment = segment.m_next;
+ array = segment.m_array;
+ m_head = segment;
+ }
+
+ var first = segment.m_state.m_first; // local copy to avoid extraneous volatile reads
+
+ if (first == segment.m_state.m_last)
+ {
+ result = default(T);
+ return false;
+ }
+
+ result = array[first];
+ if (predicate == null || predicate(result))
+ {
+ array[first] = default(T); // Clear the slot to release the element
+ segment.m_state.m_first = (first + 1) & (segment.m_array.Length - 1);
+ segment.m_state.m_lastCopy = segment.m_state.m_last; // Refresh m_lastCopy to ensure that m_first has not passed m_lastCopy
+ return true;
+ }
+ else
+ {
+ result = default(T);
+ return false;
+ }
+ }
+
+ public void Clear()
+ {
+ T ignored;
+ while (TryDequeue(out ignored)) ;
+ }
+
+ /// <summary>Gets whether the collection is currently empty.</summary>
+ /// <remarks>WARNING: This should not be used concurrently without further vetting.</remarks>
+ public bool IsEmpty
+ {
+ // This implementation is optimized for calls from the consumer.
+ get
+ {
+ var head = m_head;
+ if (head.m_state.m_first != head.m_state.m_lastCopy) return false; // m_first is volatile, so the read of m_lastCopy cannot get reordered
+ if (head.m_state.m_first != head.m_state.m_last) return false;
+ return head.m_next == null;
+ }
+ }
+
+ /// <summary>Gets an enumerable for the collection.</summary>
+ /// <remarks>WARNING: This should only be used for debugging purposes. It is not safe to be used concurrently.</remarks>
+ public IEnumerator<T> GetEnumerator()
+ {
+ for (Segment segment = m_head; segment != null; segment = segment.m_next)
+ {
+ for (int pt = segment.m_state.m_first;
+ pt != segment.m_state.m_last;
+ pt = (pt + 1) & (segment.m_array.Length - 1))
+ {
+ yield return segment.m_array[pt];
+ }
+ }
+ }
+ /// <summary>Gets an enumerable for the collection.</summary>
+ /// <remarks>WARNING: This should only be used for debugging purposes. It is not safe to be used concurrently.</remarks>
+ IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
+
+ /// <summary>Gets the number of items in the collection.</summary>
+ /// <remarks>WARNING: This should only be used for debugging purposes. It is not meant to be used concurrently.</remarks>
+ public int Count
+ {
+ get
+ {
+ int count = 0;
+ for (Segment segment = m_head; segment != null; segment = segment.m_next)
+ {
+ int arraySize = segment.m_array.Length;
+ int first, last;
+ while (true) // Count is not meant to be used concurrently, but this helps to avoid issues if it is
+ {
+ first = segment.m_state.m_first;
+ last = segment.m_state.m_last;
+ if (first == segment.m_state.m_first) break;
+ }
+ count += (last - first) & (arraySize - 1);
+ }
+ return count;
+ }
+ }
+
+ /// <summary>A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object.</summary>
+ /// <remarks>The Count is not thread safe, so we need to acquire the lock.</remarks>
+ int IProducerConsumerQueue<T>.GetCountSafe(object syncObj)
+ {
+ Contract.Assert(syncObj != null, "The syncObj parameter is null.");
+ lock (syncObj)
+ {
+ return Count;
+ }
+ }
+
+ /// <summary>A segment in the queue containing one or more items.</summary>
+ [StructLayout(LayoutKind.Sequential)]
+ private sealed class Segment
+ {
+ /// <summary>The next segment in the linked list of segments.</summary>
+ internal Segment m_next;
+ /// <summary>The data stored in this segment.</summary>
+ internal readonly T[] m_array;
+ /// <summary>Details about the segment.</summary>
+ internal SegmentState m_state; // separated out to enable StructLayout attribute to take effect
+
+ /// <summary>Initializes the segment.</summary>
+ /// <param name="size">The size to use for this segment.</param>
+ internal Segment(int size)
+ {
+ Contract.Requires((size & (size - 1)) == 0, "Size must be a power of 2");
+ m_array = new T[size];
+ }
+ }
+
+ /// <summary>Stores information about a segment.</summary>
+ [StructLayout(LayoutKind.Sequential)] // enforce layout so that padding reduces false sharing
+ private struct SegmentState
+ {
+ /// <summary>Padding to reduce false sharing between the segment's array and m_first.</summary>
+ internal PaddingFor32 m_pad0;
+
+ /// <summary>The index of the current head in the segment.</summary>
+ internal volatile int m_first;
+ /// <summary>A copy of the current tail index.</summary>
+ internal int m_lastCopy; // not volatile as read and written by the producer, except for IsEmpty, and there m_lastCopy is only read after reading the volatile m_first
+
+ /// <summary>Padding to reduce false sharing between the first and last.</summary>
+ internal PaddingFor32 m_pad1;
+
+ /// <summary>A copy of the current head index.</summary>
+ internal int m_firstCopy; // not voliatle as only read and written by the consumer thread
+ /// <summary>The index of the current tail in the segment.</summary>
+ internal volatile int m_last;
+
+ /// <summary>Padding to reduce false sharing with the last and what's after the segment.</summary>
+ internal PaddingFor32 m_pad2;
+ }
+
+ /// <summary>Debugger type proxy for a SingleProducerSingleConsumerQueue of T.</summary>
+ private sealed class SingleProducerSingleConsumerQueue_DebugView
+ {
+ /// <summary>The queue being visualized.</summary>
+ private readonly SingleProducerSingleConsumerQueue<T> m_queue;
+
+ /// <summary>Initializes the debug view.</summary>
+ /// <param name="enumerable">The queue being debugged.</param>
+ public SingleProducerSingleConsumerQueue_DebugView(SingleProducerSingleConsumerQueue<T> queue)
+ {
+ Contract.Requires(queue != null, "Expected a non-null queue.");
+ m_queue = queue;
+ }
+
+ /// <summary>Gets the contents of the list.</summary>
+ [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
+ public T[] Items
+ {
+ get
+ {
+ List<T> list = new List<T>();
+ foreach (T item in m_queue)
+ list.Add(item);
+ return list.ToArray();
+ }
+ }
+ }
+ }
+
+
+ /// <summary>A placeholder class for common padding constants and eventually routines.</summary>
+ static class PaddingHelpers
+ {
+ /// <summary>A size greater than or equal to the size of the most common CPU cache lines.</summary>
+ internal const int CACHE_LINE_SIZE = 128;
+ }
+
+ /// <summary>Padding structure used to minimize false sharing in SingleProducerSingleConsumerQueue{T}.</summary>
+ [StructLayout(LayoutKind.Explicit, Size = PaddingHelpers.CACHE_LINE_SIZE - sizeof(Int32))] // Based on common case of 64-byte cache lines
+ struct PaddingFor32
+ {
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs
new file mode 100644
index 0000000000..5f79f30b35
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TPLETWProvider.cs
@@ -0,0 +1,763 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// EventSource for TPL.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading.Tasks
+{
+ using System.Diagnostics.Tracing;
+
+ /// <summary>Provides an event source for tracing TPL information.</summary>
+ [EventSource(
+ Name = "System.Threading.Tasks.TplEventSource",
+ Guid = "2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5",
+ LocalizationResources = System.CoreLib.Name)]
+ internal sealed class TplEtwProvider : EventSource
+ {
+ /// Used to determine if tasks should generate Activity IDs for themselves
+ internal bool TasksSetActivityIds; // This keyword is set
+ internal bool Debug;
+ private bool DebugActivityId;
+
+ /// <summary>
+ /// Get callbacks when the ETW sends us commands`
+ /// </summary>
+ protected override void OnEventCommand(EventCommandEventArgs command)
+ {
+ // To get the AsyncCausality events, we need to inform the AsyncCausalityTracer
+ if (command.Command == EventCommand.Enable)
+ AsyncCausalityTracer.EnableToETW(true);
+ else if (command.Command == EventCommand.Disable)
+ AsyncCausalityTracer.EnableToETW(false);
+
+ if (IsEnabled(EventLevel.Informational, Keywords.TasksFlowActivityIds))
+ ActivityTracker.Instance.Enable();
+ else
+ TasksSetActivityIds = IsEnabled(EventLevel.Informational, Keywords.TasksSetActivityIds);
+
+ Debug = IsEnabled(EventLevel.Informational, Keywords.Debug);
+ DebugActivityId = IsEnabled(EventLevel.Informational, Keywords.DebugActivityId);
+ }
+
+ /// <summary>
+ /// Defines the singleton instance for the TPL ETW provider.
+ /// The TPL Event provider GUID is {2e5dba47-a3d2-4d16-8ee0-6671ffdcd7b5}.
+ /// </summary>
+ public static TplEtwProvider Log = new TplEtwProvider();
+ /// <summary>Prevent external instantiation. All logging should go through the Log instance.</summary>
+ private TplEtwProvider() { }
+
+ /// <summary>Type of a fork/join operation.</summary>
+ public enum ForkJoinOperationType
+ {
+ /// <summary>Parallel.Invoke.</summary>
+ ParallelInvoke=1,
+ /// <summary>Parallel.For.</summary>
+ ParallelFor=2,
+ /// <summary>Parallel.ForEach.</summary>
+ ParallelForEach=3
+ }
+
+ /// <summary>Configured behavior of a task wait operation.</summary>
+ public enum TaskWaitBehavior : int
+ {
+ /// <summary>A synchronous wait.</summary>
+ Synchronous = 1,
+ /// <summary>An asynchronous await.</summary>
+ Asynchronous = 2
+ }
+
+ /// <summary>ETW tasks that have start/stop events.</summary>
+ public class Tasks // this name is important for EventSource
+ {
+ /// <summary>A parallel loop.</summary>
+ public const EventTask Loop = (EventTask)1;
+ /// <summary>A parallel invoke.</summary>
+ public const EventTask Invoke = (EventTask)2;
+ /// <summary>Executing a Task.</summary>
+ public const EventTask TaskExecute = (EventTask)3;
+ /// <summary>Waiting on a Task.</summary>
+ public const EventTask TaskWait = (EventTask)4;
+ /// <summary>A fork/join task within a loop or invoke.</summary>
+ public const EventTask ForkJoin = (EventTask)5;
+ /// <summary>A task is scheduled to execute.</summary>
+ public const EventTask TaskScheduled = (EventTask)6;
+ /// <summary>An await task continuation is scheduled to execute.</summary>
+ public const EventTask AwaitTaskContinuationScheduled = (EventTask)7;
+
+ /// <summary>AsyncCausalityFunctionality.</summary>
+ public const EventTask TraceOperation = (EventTask)8;
+ public const EventTask TraceSynchronousWork = (EventTask)9;
+ }
+
+ public class Keywords // thisname is important for EventSource
+ {
+ /// <summary>
+ /// Only the most basic information about the workings of the task library
+ /// This sets activity IDS and logs when tasks are schedules (or waits begin)
+ /// But are otherwise silent
+ /// </summary>
+ public const EventKeywords TaskTransfer = (EventKeywords) 1;
+ /// <summary>
+ /// TaskTranser events plus events when tasks start and stop
+ /// </summary>
+ public const EventKeywords Tasks = (EventKeywords) 2;
+ /// <summary>
+ /// Events associted with the higher level parallel APIs
+ /// </summary>
+ public const EventKeywords Parallel = (EventKeywords) 4;
+ /// <summary>
+ /// These are relatively verbose events that effectively just redirect
+ /// the windows AsyncCausalityTracer to ETW
+ /// </summary>
+ public const EventKeywords AsyncCausalityOperation = (EventKeywords) 8;
+ public const EventKeywords AsyncCausalityRelation = (EventKeywords) 0x10;
+ public const EventKeywords AsyncCausalitySynchronousWork = (EventKeywords) 0x20;
+
+ /// <summary>
+ /// Emit the stops as well as the schedule/start events
+ /// </summary>
+ public const EventKeywords TaskStops = (EventKeywords) 0x40;
+
+ /// <summary>
+ /// TasksFlowActivityIds indicate that activity ID flow from one task
+ /// to any task created by it.
+ /// </summary>
+ public const EventKeywords TasksFlowActivityIds = (EventKeywords) 0x80;
+
+ /// <summary>
+ /// TasksSetActivityIds will cause the task operations to set Activity Ids
+ /// This option is incompatible with TasksFlowActivityIds flow is ignored
+ /// if that keyword is set. This option is likley to be removed in the future
+ /// </summary>
+ public const EventKeywords TasksSetActivityIds = (EventKeywords) 0x10000;
+
+ /// <summary>
+ /// Relatively Verbose logging meant for debugging the Task library itself. Will probably be removed in the future
+ /// </summary>
+ public const EventKeywords Debug = (EventKeywords) 0x20000;
+ /// <summary>
+ /// Relatively Verbose logging meant for debugging the Task library itself. Will probably be removed in the future
+ /// </summary>
+ public const EventKeywords DebugActivityId = (EventKeywords) 0x40000;
+ }
+
+ /// <summary>Enabled for all keywords.</summary>
+ private const EventKeywords ALL_KEYWORDS = (EventKeywords)(-1);
+
+ //-----------------------------------------------------------------------------------
+ //
+ // TPL Event IDs (must be unique)
+ //
+
+ /// <summary>The beginning of a parallel loop.</summary>
+ private const int PARALLELLOOPBEGIN_ID = 1;
+ /// <summary>The ending of a parallel loop.</summary>
+ private const int PARALLELLOOPEND_ID = 2;
+ /// <summary>The beginning of a parallel invoke.</summary>
+ private const int PARALLELINVOKEBEGIN_ID = 3;
+ /// <summary>The ending of a parallel invoke.</summary>
+ private const int PARALLELINVOKEEND_ID = 4;
+ /// <summary>A task entering a fork/join construct.</summary>
+ private const int PARALLELFORK_ID = 5;
+ /// <summary>A task leaving a fork/join construct.</summary>
+ private const int PARALLELJOIN_ID = 6;
+
+ /// <summary>A task is scheduled to a task scheduler.</summary>
+ private const int TASKSCHEDULED_ID = 7;
+ /// <summary>A task is about to execute.</summary>
+ private const int TASKSTARTED_ID = 8;
+ /// <summary>A task has finished executing.</summary>
+ private const int TASKCOMPLETED_ID = 9;
+ /// <summary>A wait on a task is beginning.</summary>
+ private const int TASKWAITBEGIN_ID = 10;
+ /// <summary>A wait on a task is ending.</summary>
+ private const int TASKWAITEND_ID = 11;
+ /// <summary>A continuation of a task is scheduled.</summary>
+ private const int AWAITTASKCONTINUATIONSCHEDULED_ID = 12;
+ /// <summary>A continuation of a taskWaitEnd is complete </summary>
+ private const int TASKWAITCONTINUATIONCOMPLETE_ID = 13;
+ /// <summary>A continuation of a taskWaitEnd is complete </summary>
+ private const int TASKWAITCONTINUATIONSTARTED_ID = 19;
+
+ private const int TRACEOPERATIONSTART_ID = 14;
+ private const int TRACEOPERATIONSTOP_ID = 15;
+ private const int TRACEOPERATIONRELATION_ID = 16;
+ private const int TRACESYNCHRONOUSWORKSTART_ID = 17;
+ private const int TRACESYNCHRONOUSWORKSTOP_ID = 18;
+
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Parallel Events
+ //
+
+ #region ParallelLoopBegin
+ /// <summary>
+ /// Denotes the entry point for a Parallel.For or Parallel.ForEach loop
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The loop ID.</param>
+ /// <param name="OperationType">The kind of fork/join operation.</param>
+ /// <param name="InclusiveFrom">The lower bound of the loop.</param>
+ /// <param name="ExclusiveTo">The upper bound of the loop.</param>
+ [SecuritySafeCritical]
+ [Event(PARALLELLOOPBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
+ Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Start)]
+ public void ParallelLoopBegin(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
+ long InclusiveFrom, long ExclusiveTo)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
+ {
+ // There is no explicit WriteEvent() overload matching this event's fields. Therefore calling
+ // WriteEvent() would hit the "params" overload, which leads to an object allocation every time
+ // this event is fired. To prevent that problem we will call WriteEventCore(), which works with
+ // a stack based EventData array populated with the event fields.
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[6];
+
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
+ eventPayload[3].Size = sizeof(int);
+ eventPayload[3].DataPointer = ((IntPtr) (&OperationType));
+ eventPayload[4].Size = sizeof(long);
+ eventPayload[4].DataPointer = ((IntPtr) (&InclusiveFrom));
+ eventPayload[5].Size = sizeof(long);
+ eventPayload[5].DataPointer = ((IntPtr) (&ExclusiveTo));
+
+ WriteEventCore(PARALLELLOOPBEGIN_ID, 6, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ #region ParallelLoopEnd
+ /// <summary>
+ /// Denotes the end of a Parallel.For or Parallel.ForEach loop.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The loop ID.</param>
+ /// <param name="TotalIterations">the total number of iterations processed.</param>
+ [SecuritySafeCritical]
+ [Event(PARALLELLOOPEND_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Loop, Opcode = EventOpcode.Stop)]
+ public void ParallelLoopEnd(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID, long TotalIterations)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
+ {
+ // There is no explicit WriteEvent() overload matching this event's fields.
+ // Therefore calling WriteEvent() would hit the "params" overload, which leads to an object allocation every time this event is fired.
+ // To prevent that problem we will call WriteEventCore(), which works with a stack based EventData array populated with the event fields
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[4];
+
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
+ eventPayload[3].Size = sizeof(long);
+ eventPayload[3].DataPointer = ((IntPtr) (&TotalIterations));
+
+ WriteEventCore(PARALLELLOOPEND_ID, 4, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ #region ParallelInvokeBegin
+ /// <summary>Denotes the entry point for a Parallel.Invoke call.</summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The invoke ID.</param>
+ /// <param name="OperationType">The kind of fork/join operation.</param>
+ /// <param name="ActionCount">The number of actions being invoked.</param>
+ [SecuritySafeCritical]
+ [Event(PARALLELINVOKEBEGIN_ID, Level = EventLevel.Informational, ActivityOptions=EventActivityOptions.Recursive,
+ Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Start)]
+ public void ParallelInvokeBegin(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID, ForkJoinOperationType OperationType, // PFX_FORKJOIN_COMMON_EVENT_HEADER
+ int ActionCount)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
+ {
+ // There is no explicit WriteEvent() overload matching this event's fields.
+ // Therefore calling WriteEvent() would hit the "params" overload, which leads to an object allocation every time this event is fired.
+ // To prevent that problem we will call WriteEventCore(), which works with a stack based EventData array populated with the event fields
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[5];
+
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&ForkJoinContextID));
+ eventPayload[3].Size = sizeof(int);
+ eventPayload[3].DataPointer = ((IntPtr) (&OperationType));
+ eventPayload[4].Size = sizeof(int);
+ eventPayload[4].DataPointer = ((IntPtr) (&ActionCount));
+
+ WriteEventCore(PARALLELINVOKEBEGIN_ID, 5, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ #region ParallelInvokeEnd
+ /// <summary>
+ /// Denotes the exit point for a Parallel.Invoke call.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The invoke ID.</param>
+ [Event(PARALLELINVOKEEND_ID, Level = EventLevel.Informational, Task = TplEtwProvider.Tasks.Invoke, Opcode = EventOpcode.Stop)]
+ public void ParallelInvokeEnd(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.Parallel))
+ {
+ WriteEvent(PARALLELINVOKEEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
+ }
+ }
+ #endregion
+
+ #region ParallelFork
+ /// <summary>
+ /// Denotes the start of an individual task that's part of a fork/join context.
+ /// Before this event is fired, the start of the new fork/join context will be marked
+ /// with another event that declares a unique context ID.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The invoke ID.</param>
+ [Event(PARALLELFORK_ID, Level = EventLevel.Verbose, ActivityOptions=EventActivityOptions.Recursive,
+ Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Start)]
+ public void ParallelFork(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Parallel))
+ {
+ WriteEvent(PARALLELFORK_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
+ }
+ }
+ #endregion
+
+ #region ParallelJoin
+ /// <summary>
+ /// Denotes the end of an individual task that's part of a fork/join context.
+ /// This should match a previous ParallelFork event with a matching "OriginatingTaskID"
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="ForkJoinContextID">The invoke ID.</param>
+ [Event(PARALLELJOIN_ID, Level = EventLevel.Verbose, Task = TplEtwProvider.Tasks.ForkJoin, Opcode = EventOpcode.Stop)]
+ public void ParallelJoin(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ForkJoinContextID)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Parallel))
+ {
+ WriteEvent(PARALLELJOIN_ID, OriginatingTaskSchedulerID, OriginatingTaskID, ForkJoinContextID);
+ }
+ }
+ #endregion
+
+ //-----------------------------------------------------------------------------------
+ //
+ // Task Events
+ //
+
+ // These are all verbose events, so we need to call IsEnabled(EventLevel.Verbose, ALL_KEYWORDS)
+ // call. However since the IsEnabled(l,k) call is more expensive than IsEnabled(), we only want
+ // to incur this cost when instrumentation is enabled. So the Task codepaths that call these
+ // event functions still do the check for IsEnabled()
+
+ #region TaskScheduled
+ /// <summary>
+ /// Fired when a task is queued to a TaskScheduler.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ /// <param name="CreatingTaskID">The task ID</param>
+ /// <param name="TaskCreationOptions">The options used to create the task.</param>
+ [SecuritySafeCritical]
+ [Event(TASKSCHEDULED_ID, Task = Tasks.TaskScheduled, Version=1, Opcode = EventOpcode.Send,
+ Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
+ public void TaskScheduled(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int TaskID, int CreatingTaskID, int TaskCreationOptions, int appDomain)
+ {
+ // IsEnabled() call is an inlined quick check that makes this very fast when provider is off
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
+ {
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[6];
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&TaskID));
+ eventPayload[3].Size = sizeof(int);
+ eventPayload[3].DataPointer = ((IntPtr) (&CreatingTaskID));
+ eventPayload[4].Size = sizeof(int);
+ eventPayload[4].DataPointer = ((IntPtr) (&TaskCreationOptions));
+ eventPayload[5].Size = sizeof(int);
+ eventPayload[5].DataPointer = ((IntPtr) (&appDomain));
+ if (TasksSetActivityIds)
+ {
+ Guid childActivityId = CreateGuidForTaskID(TaskID);
+ WriteEventWithRelatedActivityIdCore(TASKSCHEDULED_ID, &childActivityId, 6, eventPayload);
+ }
+ else
+ WriteEventCore(TASKSCHEDULED_ID, 6, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ #region TaskStarted
+ /// <summary>
+ /// Fired just before a task actually starts executing.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ [Event(TASKSTARTED_ID,
+ Level = EventLevel.Informational, Keywords = Keywords.Tasks)]
+ public void TaskStarted(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int TaskID)
+ {
+ if (IsEnabled(EventLevel.Informational, Keywords.Tasks))
+ WriteEvent(TASKSTARTED_ID, OriginatingTaskSchedulerID, OriginatingTaskID, TaskID);
+ }
+ #endregion
+
+ #region TaskCompleted
+ /// <summary>
+ /// Fired right after a task finished executing.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ /// <param name="IsExceptional">Whether the task completed due to an error.</param>
+ [SecuritySafeCritical]
+ [Event(TASKCOMPLETED_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.TaskStops)]
+ public void TaskCompleted(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int TaskID, bool IsExceptional)
+ {
+ if (IsEnabled(EventLevel.Informational, Keywords.Tasks))
+ {
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[4];
+ Int32 isExceptionalInt = IsExceptional ? 1 : 0;
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&TaskID));
+ eventPayload[3].Size = sizeof(int);
+ eventPayload[3].DataPointer = ((IntPtr) (&isExceptionalInt));
+ WriteEventCore(TASKCOMPLETED_ID, 4, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ #region TaskWaitBegin
+ /// <summary>
+ /// Fired when starting to wait for a taks's completion explicitly or implicitly.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ /// <param name="Behavior">Configured behavior for the wait.</param>
+ /// <param name="ContinueWithTaskID">If known, if 'TaskID' has a 'continueWith' task, mention give its ID here.
+ /// 0 means unknown. This allows better visualization of the common sequential chaining case.</param>
+ /// </summary>
+ [SecuritySafeCritical]
+ [Event(TASKWAITBEGIN_ID, Version=3, Task = TplEtwProvider.Tasks.TaskWait, Opcode = EventOpcode.Send,
+ Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
+ public void TaskWaitBegin(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int TaskID, TaskWaitBehavior Behavior, int ContinueWithTaskID, int appDomain)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
+ {
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[5];
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr)(&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr)(&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr)(&TaskID));
+ eventPayload[3].Size = sizeof(int);
+ eventPayload[3].DataPointer = ((IntPtr)(&Behavior));
+ eventPayload[4].Size = sizeof(int);
+ eventPayload[4].DataPointer = ((IntPtr)(&ContinueWithTaskID));
+ if (TasksSetActivityIds)
+ {
+ Guid childActivityId = CreateGuidForTaskID(TaskID);
+ WriteEventWithRelatedActivityIdCore(TASKWAITBEGIN_ID, &childActivityId, 5, eventPayload);
+ }
+ else
+ WriteEventCore(TASKWAITBEGIN_ID, 5, eventPayload);
+ }
+ }
+ }
+ #endregion
+
+ /// <summary>
+ /// Fired when the wait for a tasks completion returns.
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ [Event(TASKWAITEND_ID,
+ Level = EventLevel.Verbose, Keywords = Keywords.Tasks)]
+ public void TaskWaitEnd(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int TaskID)
+ {
+ // Log an event if indicated.
+ if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
+ WriteEvent(TASKWAITEND_ID, OriginatingTaskSchedulerID, OriginatingTaskID, TaskID);
+ }
+
+ /// <summary>
+ /// Fired when the the work (method) associated with a TaskWaitEnd completes
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ [Event(TASKWAITCONTINUATIONCOMPLETE_ID,
+ Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
+ public void TaskWaitContinuationComplete(int TaskID)
+ {
+ // Log an event if indicated.
+ if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
+ WriteEvent(TASKWAITCONTINUATIONCOMPLETE_ID, TaskID);
+ }
+
+ /// <summary>
+ /// Fired when the the work (method) associated with a TaskWaitEnd completes
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The task ID.</param>
+ [Event(TASKWAITCONTINUATIONSTARTED_ID,
+ Level = EventLevel.Verbose, Keywords = Keywords.TaskStops)]
+ public void TaskWaitContinuationStarted(int TaskID)
+ {
+ // Log an event if indicated.
+ if (IsEnabled() && IsEnabled(EventLevel.Verbose, Keywords.Tasks))
+ WriteEvent(TASKWAITCONTINUATIONSTARTED_ID, TaskID);
+ }
+
+ /// <summary>
+ /// Fired when the an asynchronous continuation for a task is scheduled
+ /// </summary>
+ /// <param name="OriginatingTaskSchedulerID">The scheduler ID.</param>
+ /// <param name="OriginatingTaskID">The task ID.</param>
+ /// <param name="TaskID">The activityId for the continuation.</param>
+ [SecuritySafeCritical]
+ [Event(AWAITTASKCONTINUATIONSCHEDULED_ID, Task = Tasks.AwaitTaskContinuationScheduled, Opcode = EventOpcode.Send,
+ Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer|Keywords.Tasks)]
+ public void AwaitTaskContinuationScheduled(
+ int OriginatingTaskSchedulerID, int OriginatingTaskID, // PFX_COMMON_EVENT_HEADER
+ int ContinuwWithTaskId)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.TaskTransfer|Keywords.Tasks))
+ {
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[3];
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&OriginatingTaskSchedulerID));
+ eventPayload[1].Size = sizeof(int);
+ eventPayload[1].DataPointer = ((IntPtr) (&OriginatingTaskID));
+ eventPayload[2].Size = sizeof(int);
+ eventPayload[2].DataPointer = ((IntPtr) (&ContinuwWithTaskId));
+ if (TasksSetActivityIds)
+ {
+ Guid continuationActivityId = CreateGuidForTaskID(ContinuwWithTaskId);
+ WriteEventWithRelatedActivityIdCore(AWAITTASKCONTINUATIONSCHEDULED_ID, &continuationActivityId, 3, eventPayload);
+ }
+ else
+ WriteEventCore(AWAITTASKCONTINUATIONSCHEDULED_ID, 3, eventPayload);
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [Event(TRACEOPERATIONSTART_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)]
+ public void TraceOperationBegin(int TaskID, string OperationName, long RelatedContext)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityOperation))
+ {
+ unsafe
+ {
+ fixed(char* operationNamePtr = OperationName)
+ {
+ EventData* eventPayload = stackalloc EventData[3];
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&TaskID));
+
+ eventPayload[1].Size = ((OperationName.Length + 1) * 2);
+ eventPayload[1].DataPointer = ((IntPtr) operationNamePtr);
+
+ eventPayload[2].Size = sizeof(long);
+ eventPayload[2].DataPointer = ((IntPtr) (&RelatedContext));
+ WriteEventCore(TRACEOPERATIONSTART_ID, 3, eventPayload);
+ }
+ }
+ }
+ }
+
+ [SecuritySafeCritical]
+ [Event(TRACEOPERATIONRELATION_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityRelation)]
+ public void TraceOperationRelation(int TaskID, CausalityRelation Relation)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityRelation))
+ WriteEvent(TRACEOPERATIONRELATION_ID, TaskID,(int) Relation); // optmized overload for this exists
+ }
+
+ [SecuritySafeCritical]
+ [Event(TRACEOPERATIONSTOP_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalityOperation)]
+ public void TraceOperationEnd(int TaskID, AsyncCausalityStatus Status)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalityOperation))
+ WriteEvent(TRACEOPERATIONSTOP_ID, TaskID,(int) Status); // optmized overload for this exists
+ }
+
+ [SecuritySafeCritical]
+ [Event(TRACESYNCHRONOUSWORKSTART_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)]
+ public void TraceSynchronousWorkBegin(int TaskID, CausalitySynchronousWork Work)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalitySynchronousWork))
+ WriteEvent(TRACESYNCHRONOUSWORKSTART_ID, TaskID,(int) Work); // optmized overload for this exists
+ }
+
+ [SecuritySafeCritical]
+ [Event(TRACESYNCHRONOUSWORKSTOP_ID, Version=1,
+ Level = EventLevel.Informational, Keywords = Keywords.AsyncCausalitySynchronousWork)]
+ public void TraceSynchronousWorkEnd(CausalitySynchronousWork Work)
+ {
+ if (IsEnabled() && IsEnabled(EventLevel.Informational, Keywords.AsyncCausalitySynchronousWork))
+ {
+ unsafe
+ {
+ EventData* eventPayload = stackalloc EventData[1];
+ eventPayload[0].Size = sizeof(int);
+ eventPayload[0].DataPointer = ((IntPtr) (&Work));
+
+ WriteEventCore(TRACESYNCHRONOUSWORKSTOP_ID, 1, eventPayload);
+ }
+ }
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ unsafe public void RunningContinuation(int TaskID, object Object) { RunningContinuation(TaskID, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
+ [Event(20, Keywords = Keywords.Debug)]
+ private void RunningContinuation(int TaskID, long Object)
+ {
+ if (Debug)
+ WriteEvent(20, TaskID, Object);
+ }
+
+ [NonEvent, System.Security.SecuritySafeCritical]
+ unsafe public void RunningContinuationList(int TaskID, int Index, object Object) { RunningContinuationList(TaskID, Index, (long) *((void**) JitHelpers.UnsafeCastToStackPointer(ref Object))); }
+
+ [Event(21, Keywords = Keywords.Debug)]
+ public void RunningContinuationList(int TaskID, int Index, long Object)
+ {
+ if (Debug)
+ WriteEvent(21, TaskID, Index, Object);
+ }
+
+ [Event(22, Keywords = Keywords.Debug)]
+ public void DebugMessage(string Message) { WriteEvent(22, Message); }
+
+ [Event(23, Keywords = Keywords.Debug)]
+ public void DebugFacilityMessage(string Facility, string Message) { WriteEvent(23, Facility, Message); }
+
+ [Event(24, Keywords = Keywords.Debug)]
+ public void DebugFacilityMessage1(string Facility, string Message, string Value1) { WriteEvent(24, Facility, Message, Value1); }
+
+ [Event(25, Keywords = Keywords.DebugActivityId)]
+ public void SetActivityId(Guid NewId)
+ {
+ if (DebugActivityId)
+ WriteEvent(25, NewId);
+ }
+
+ [Event(26, Keywords = Keywords.Debug)]
+ public void NewID(int TaskID)
+ {
+ if (Debug)
+ WriteEvent(26, TaskID);
+ }
+
+ /// <summary>
+ /// Activity IDs are GUIDS but task IDS are integers (and are not unique across appdomains
+ /// This routine creates a process wide unique GUID given a task ID
+ /// </summary>
+ internal static Guid CreateGuidForTaskID(int taskID)
+ {
+ // The thread pool generated a process wide unique GUID from a task GUID by
+ // using the taskGuid, the appdomain ID, and 8 bytes of 'randomization' chosen by
+ // using the last 8 bytes as the provider GUID for this provider.
+ // These were generated by CreateGuid, and are reasonably random (and thus unlikley to collide
+ uint pid = EventSource.s_currentPid;
+ int appDomainID = System.Threading.Thread.GetDomainID();
+ return new Guid(taskID,
+ (short) appDomainID , (short) (appDomainID >> 16),
+ (byte)pid, (byte)(pid >> 8), (byte)(pid >> 16), (byte)(pid >> 24),
+ 0xff, 0xdc, 0xd7, 0xb5);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/Task.cs b/src/mscorlib/src/System/Threading/Tasks/Task.cs
new file mode 100644
index 0000000000..36f8401a4d
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/Task.cs
@@ -0,0 +1,7344 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A schedulable unit of work.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.ExceptionServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Microsoft.Win32;
+using System.Diagnostics.Tracing;
+
+// Disable the "reference to volatile field not treated as volatile" error.
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+
+ /// <summary>
+ /// Utility class for allocating structs as heap variables
+ /// </summary>
+ internal class Shared<T>
+ {
+ internal T Value;
+
+ internal Shared(T value)
+ {
+ this.Value = value;
+ }
+
+ }
+
+ /// <summary>
+ /// Represents the current stage in the lifecycle of a <see cref="Task"/>.
+ /// </summary>
+ public enum TaskStatus
+ {
+ /// <summary>
+ /// The task has been initialized but has not yet been scheduled.
+ /// </summary>
+ Created,
+ /// <summary>
+ /// The task is waiting to be activated and scheduled internally by the .NET Framework infrastructure.
+ /// </summary>
+ WaitingForActivation,
+ /// <summary>
+ /// The task has been scheduled for execution but has not yet begun executing.
+ /// </summary>
+ WaitingToRun,
+ /// <summary>
+ /// The task is running but has not yet completed.
+ /// </summary>
+ Running,
+ // /// <summary>
+ // /// The task is currently blocked in a wait state.
+ // /// </summary>
+ // Blocked,
+ /// <summary>
+ /// The task has finished executing and is implicitly waiting for
+ /// attached child tasks to complete.
+ /// </summary>
+ WaitingForChildrenToComplete,
+ /// <summary>
+ /// The task completed execution successfully.
+ /// </summary>
+ RanToCompletion,
+ /// <summary>
+ /// The task acknowledged cancellation by throwing an OperationCanceledException with its own CancellationToken
+ /// while the token was in signaled state, or the task's CancellationToken was already signaled before the
+ /// task started executing.
+ /// </summary>
+ Canceled,
+ /// <summary>
+ /// The task completed due to an unhandled exception.
+ /// </summary>
+ Faulted
+ }
+
+ /// <summary>
+ /// Represents an asynchronous operation.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// <see cref="Task"/> instances may be created in a variety of ways. The most common approach is by
+ /// using the Task type's <see cref="Factory"/> property to retrieve a <see
+ /// cref="System.Threading.Tasks.TaskFactory"/> instance that can be used to create tasks for several
+ /// purposes. For example, to create a <see cref="Task"/> that runs an action, the factory's StartNew
+ /// method may be used:
+ /// <code>
+ /// // C#
+ /// var t = Task.Factory.StartNew(() => DoAction());
+ ///
+ /// ' Visual Basic
+ /// Dim t = Task.Factory.StartNew(Function() DoAction())
+ /// </code>
+ /// </para>
+ /// <para>
+ /// The <see cref="Task"/> class also provides constructors that initialize the Task but that do not
+ /// schedule it for execution. For performance reasons, TaskFactory's StartNew method should be the
+ /// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
+ /// and scheduling must be separated, the constructors may be used, and the task's <see cref="Start()"/>
+ /// method may then be used to schedule the task for execution at a later time.
+ /// </para>
+ /// <para>
+ /// All members of <see cref="Task"/>, except for <see cref="Dispose()"/>, are thread-safe
+ /// and may be used from multiple threads concurrently.
+ /// </para>
+ /// <para>
+ /// For operations that return values, the <see cref="System.Threading.Tasks.Task{TResult}"/> class
+ /// should be used.
+ /// </para>
+ /// <para>
+ /// For developers implementing custom debuggers, several internal and private members of Task may be
+ /// useful (these may change from release to release). The Int32 m_taskId field serves as the backing
+ /// store for the <see cref="Id"/> property, however accessing this field directly from a debugger may be
+ /// more efficient than accessing the same value through the property's getter method (the
+ /// s_taskIdCounter Int32 counter is used to retrieve the next available ID for a Task). Similarly, the
+ /// Int32 m_stateFlags field stores information about the current lifecycle stage of the Task,
+ /// information also accessible through the <see cref="Status"/> property. The m_action System.Object
+ /// field stores a reference to the Task's delegate, and the m_stateObject System.Object field stores the
+ /// async state passed to the Task by the developer. Finally, for debuggers that parse stack frames, the
+ /// InternalWait method serves a potential marker for when a Task is entering a wait operation.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskDebugView))]
+ [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}")]
+ public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
+ {
+ [ThreadStatic]
+ internal static Task t_currentTask; // The currently executing task.
+ [ThreadStatic]
+ private static StackGuard t_stackGuard; // The stack guard object for this thread
+
+ internal static int s_taskIdCounter; //static counter used to generate unique task IDs
+ private readonly static TaskFactory s_factory = new TaskFactory();
+
+ private volatile int m_taskId; // this task's unique ID. initialized only if it is ever requested
+
+ internal object m_action; // The body of the task. Might be Action<object>, Action<TState> or Action. Or possibly a Func.
+ // If m_action is set to null it will indicate that we operate in the
+ // "externally triggered completion" mode, which is exclusively meant
+ // for the signalling Task<TResult> (aka. promise). In this mode,
+ // we don't call InnerInvoke() in response to a Wait(), but simply wait on
+ // the completion event which will be set when the Future class calls Finish().
+ // But the event would now be signalled if Cancel() is called
+
+
+ internal object m_stateObject; // A state object that can be optionally supplied, passed to action.
+ internal TaskScheduler m_taskScheduler; // The task scheduler this task runs under.
+
+ internal volatile int m_stateFlags;
+
+ private Task ParentForDebugger => m_contingentProperties?.m_parent; // Private property used by a debugger to access this Task's parent
+ private int StateFlagsForDebugger => m_stateFlags; // Private property used by a debugger to access this Task's state flags
+
+ // State constants for m_stateFlags;
+ // The bits of m_stateFlags are allocated as follows:
+ // 0x40000000 - TaskBase state flag
+ // 0x3FFF0000 - Task state flags
+ // 0x0000FF00 - internal TaskCreationOptions flags
+ // 0x000000FF - publicly exposed TaskCreationOptions flags
+ //
+ // See TaskCreationOptions for bit values associated with TaskCreationOptions
+ //
+ private const int OptionsMask = 0xFFFF; // signifies the Options portion of m_stateFlags bin: 0000 0000 0000 0000 1111 1111 1111 1111
+ internal const int TASK_STATE_STARTED = 0x10000; //bin: 0000 0000 0000 0001 0000 0000 0000 0000
+ internal const int TASK_STATE_DELEGATE_INVOKED = 0x20000; //bin: 0000 0000 0000 0010 0000 0000 0000 0000
+ internal const int TASK_STATE_DISPOSED = 0x40000; //bin: 0000 0000 0000 0100 0000 0000 0000 0000
+ internal const int TASK_STATE_EXCEPTIONOBSERVEDBYPARENT = 0x80000; //bin: 0000 0000 0000 1000 0000 0000 0000 0000
+ internal const int TASK_STATE_CANCELLATIONACKNOWLEDGED = 0x100000; //bin: 0000 0000 0001 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_FAULTED = 0x200000; //bin: 0000 0000 0010 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_CANCELED = 0x400000; //bin: 0000 0000 0100 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_WAITING_ON_CHILDREN = 0x800000; //bin: 0000 0000 1000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_RAN_TO_COMPLETION = 0x1000000; //bin: 0000 0001 0000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_WAITINGFORACTIVATION = 0x2000000; //bin: 0000 0010 0000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_COMPLETION_RESERVED = 0x4000000; //bin: 0000 0100 0000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_THREAD_WAS_ABORTED = 0x8000000; //bin: 0000 1000 0000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_WAIT_COMPLETION_NOTIFICATION = 0x10000000; //bin: 0001 0000 0000 0000 0000 0000 0000 0000
+ //This could be moved to InternalTaskOptions enum
+ internal const int TASK_STATE_EXECUTIONCONTEXT_IS_NULL = 0x20000000; //bin: 0010 0000 0000 0000 0000 0000 0000 0000
+ internal const int TASK_STATE_TASKSCHEDULED_WAS_FIRED = 0x40000000; //bin: 0100 0000 0000 0000 0000 0000 0000 0000
+
+ // A mask for all of the final states a task may be in
+ private const int TASK_STATE_COMPLETED_MASK = TASK_STATE_CANCELED | TASK_STATE_FAULTED | TASK_STATE_RAN_TO_COMPLETION;
+
+ // Values for ContingentProperties.m_internalCancellationRequested.
+ private const int CANCELLATION_REQUESTED = 0x1;
+
+ // Can be null, a single continuation, a list of continuations, or s_taskCompletionSentinel,
+ // in that order. The logic arround this object assumes it will never regress to a previous state.
+ private volatile object m_continuationObject = null;
+
+ // m_continuationObject is set to this when the task completes.
+ private static readonly object s_taskCompletionSentinel = new object();
+
+ // A private flag that would be set (only) by the debugger
+ // When true the Async Causality logging trace is enabled as well as a dictionary to relate operation ids with Tasks
+ [FriendAccessAllowed]
+ internal static bool s_asyncDebuggingEnabled; //false by default
+
+ // This dictonary relates the task id, from an operation id located in the Async Causality log to the actual
+ // task. This is to be used by the debugger ONLY. Task in this dictionary represent current active tasks.
+ private static readonly Dictionary<int, Task> s_currentActiveTasks = new Dictionary<int, Task>();
+ private static readonly Object s_activeTasksLock = new Object();
+
+ // These methods are a way to access the dictionary both from this class and for other classes that also
+ // activate dummy tasks. Specifically the AsyncTaskMethodBuilder and AsyncTaskMethodBuilder<>
+ [FriendAccessAllowed]
+ internal static bool AddToActiveTasks(Task task)
+ {
+ Contract.Requires(task != null, "Null Task objects can't be added to the ActiveTasks collection");
+ lock (s_activeTasksLock)
+ {
+ s_currentActiveTasks[task.Id] = task;
+ }
+ //always return true to keep signature as bool for backwards compatibility
+ return true;
+ }
+
+ [FriendAccessAllowed]
+ internal static void RemoveFromActiveTasks(int taskId)
+ {
+ lock (s_activeTasksLock)
+ {
+ s_currentActiveTasks.Remove(taskId);
+ }
+ }
+
+ // We moved a number of Task properties into this class. The idea is that in most cases, these properties never
+ // need to be accessed during the life cycle of a Task, so we don't want to instantiate them every time. Once
+ // one of these properties needs to be written, we will instantiate a ContingentProperties object and set
+ // the appropriate property.
+ internal class ContingentProperties
+ {
+ // Additional context
+
+ internal ExecutionContext m_capturedContext; // The execution context to run the task within, if any. Only set from non-concurrent contexts.
+
+ // Completion fields (exceptions and event)
+
+ internal volatile ManualResetEventSlim m_completionEvent; // Lazily created if waiting is required.
+ internal volatile TaskExceptionHolder m_exceptionsHolder; // Tracks exceptions, if any have occurred
+
+ // Cancellation fields (token, registration, and internally requested)
+
+ internal CancellationToken m_cancellationToken; // Task's cancellation token, if it has one
+ internal Shared<CancellationTokenRegistration> m_cancellationRegistration; // Task's registration with the cancellation token
+ internal volatile int m_internalCancellationRequested; // Its own field because multiple threads legally try to set it.
+
+ // Parenting fields
+
+ // # of active children + 1 (for this task itself).
+ // Used for ensuring all children are done before this task can complete
+ // The extra count helps prevent the race condition for executing the final state transition
+ // (i.e. whether the last child or this task itself should call FinishStageTwo())
+ internal volatile int m_completionCountdown = 1;
+ // A list of child tasks that threw an exception (TCEs don't count),
+ // but haven't yet been waited on by the parent, lazily initialized.
+ internal volatile List<Task> m_exceptionalChildren;
+ // A task's parent, or null if parent-less. Only set during Task construction.
+ internal Task m_parent;
+
+ /// <summary>
+ /// Sets the internal completion event.
+ /// </summary>
+ internal void SetCompleted()
+ {
+ var mres = m_completionEvent;
+ if (mres != null) mres.Set();
+ }
+
+ /// <summary>
+ /// Checks if we registered a CT callback during construction, and deregisters it.
+ /// This should be called when we know the registration isn't useful anymore. Specifically from Finish() if the task has completed
+ /// successfully or with an exception.
+ /// </summary>
+ internal void DeregisterCancellationCallback()
+ {
+ if (m_cancellationRegistration != null)
+ {
+ // Harden against ODEs thrown from disposing of the CTR.
+ // Since the task has already been put into a final state by the time this
+ // is called, all we can do here is suppress the exception.
+ try { m_cancellationRegistration.Value.Dispose(); }
+ catch (ObjectDisposedException) { }
+ m_cancellationRegistration = null;
+ }
+ }
+ }
+
+
+ // This field will only be instantiated to some non-null value if any ContingentProperties need to be set.
+ // This will be a ContingentProperties instance or a type derived from it
+ internal ContingentProperties m_contingentProperties;
+
+ // Special internal constructor to create an already-completed task.
+ // if canceled==true, create a Canceled task, or else create a RanToCompletion task.
+ // Constructs the task as already completed
+ internal Task(bool canceled, TaskCreationOptions creationOptions, CancellationToken ct)
+ {
+ int optionFlags = (int)creationOptions;
+ if (canceled)
+ {
+ m_stateFlags = TASK_STATE_CANCELED | TASK_STATE_CANCELLATIONACKNOWLEDGED | optionFlags;
+ m_contingentProperties = new ContingentProperties() // can't have children, so just instantiate directly
+ {
+ m_cancellationToken = ct,
+ m_internalCancellationRequested = CANCELLATION_REQUESTED,
+ };
+ }
+ else
+ m_stateFlags = TASK_STATE_RAN_TO_COMPLETION | optionFlags;
+ }
+
+ /// <summary>Constructor for use with promise-style tasks that aren't configurable.</summary>
+ internal Task()
+ {
+ m_stateFlags = TASK_STATE_WAITINGFORACTIVATION | (int)InternalTaskOptions.PromiseTask;
+ }
+
+ // Special constructor for use with promise-style tasks.
+ // Added promiseStyle parameter as an aid to the compiler to distinguish between (state,TCO) and
+ // (action,TCO). It should always be true.
+ internal Task(object state, TaskCreationOptions creationOptions, bool promiseStyle)
+ {
+ Contract.Assert(promiseStyle, "Promise CTOR: promiseStyle was false");
+
+ // Check the creationOptions. We allow the AttachedToParent option to be specified for promise tasks.
+ // Also allow RunContinuationsAsynchronously because this is the constructor called by TCS
+ if ((creationOptions & ~(TaskCreationOptions.AttachedToParent | TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions);
+ }
+
+ // Only set a parent if AttachedToParent is specified.
+ if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
+ {
+ Task parent = Task.InternalCurrent;
+ if (parent != null)
+ {
+ EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
+ }
+ }
+
+ TaskConstructorCore(null, state, default(CancellationToken), creationOptions, InternalTaskOptions.PromiseTask, null);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the Task.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="action"/> argument is null.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action action)
+ : this(action, null, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action and <see cref="System.Threading.CancellationToken">CancellationToken</see>.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the Task.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new Task.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="action"/> argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action action, CancellationToken cancellationToken)
+ : this(action, null, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action and creation options.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the Task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action action, TaskCreationOptions creationOptions)
+ : this(action, null, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action and creation options.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the Task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ : this(action, null, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action and state.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="state">An object representing data to be used by the action.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action<object> action, object state)
+ : this(action, state, null, default(CancellationToken), TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="state">An object representing data to be used by the action.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action<object> action, object state, CancellationToken cancellationToken)
+ : this(action, state, null, cancellationToken, TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="state">An object representing data to be used by the action.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the Task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action<object> action, object state, TaskCreationOptions creationOptions)
+ : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task"/> with the specified action, state, snd options.
+ /// </summary>
+ /// <param name="action">The delegate that represents the code to execute in the task.</param>
+ /// <param name="state">An object representing data to be used by the action.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the Task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ internal Task(Action<object> action, object state, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ : this(action, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
+ {
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// An internal constructor used by the factory methods on task and its descendent(s).
+ /// This variant does not capture the ExecutionContext; it is up to the caller to do that.
+ /// </summary>
+ /// <param name="action">An action to execute.</param>
+ /// <param name="state">Optional state to pass to the action.</param>
+ /// <param name="parent">Parent of Task.</param>
+ /// <param name="cancellationToken">A CancellationToken for the task.</param>
+ /// <param name="scheduler">A task scheduler under which the task will run.</param>
+ /// <param name="creationOptions">Options to control its execution.</param>
+ /// <param name="internalOptions">Internal options to control its execution</param>
+ internal Task(Delegate action, object state, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+ {
+ if (action == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.action);
+ }
+ Contract.EndContractBlock();
+
+ // Keep a link to your parent if: (A) You are attached, or (B) you are self-replicating.
+ if (parent != null &&
+ ((creationOptions & TaskCreationOptions.AttachedToParent) != 0 ||
+ (internalOptions & InternalTaskOptions.SelfReplicating) != 0))
+ {
+ EnsureContingentPropertiesInitializedUnsafe().m_parent = parent;
+ }
+
+ TaskConstructorCore(action, state, cancellationToken, creationOptions, internalOptions, scheduler);
+ }
+
+ /// <summary>
+ /// Common logic used by the following internal ctors:
+ /// Task()
+ /// Task(object action, object state, Task parent, TaskCreationOptions options, TaskScheduler taskScheduler)
+ /// </summary>
+ /// <param name="action">Action for task to execute.</param>
+ /// <param name="state">Object to which to pass to action (may be null)</param>
+ /// <param name="scheduler">Task scheduler on which to run thread (only used by continuation tasks).</param>
+ /// <param name="cancellationToken">A CancellationToken for the Task.</param>
+ /// <param name="creationOptions">Options to customize behavior of Task.</param>
+ /// <param name="internalOptions">Internal options to customize behavior of Task.</param>
+ internal void TaskConstructorCore(object action, object state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+ {
+ m_action = action;
+ m_stateObject = state;
+ m_taskScheduler = scheduler;
+
+ // Check for validity of options
+ if ((creationOptions &
+ ~(TaskCreationOptions.AttachedToParent |
+ TaskCreationOptions.LongRunning |
+ TaskCreationOptions.DenyChildAttach |
+ TaskCreationOptions.HideScheduler |
+ TaskCreationOptions.PreferFairness |
+ TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions);
+ }
+
+#if DEBUG
+ // Check the validity of internalOptions
+ int illegalInternalOptions =
+ (int) (internalOptions &
+ ~(InternalTaskOptions.SelfReplicating |
+ InternalTaskOptions.ChildReplica |
+ InternalTaskOptions.PromiseTask |
+ InternalTaskOptions.ContinuationTask |
+ InternalTaskOptions.LazyCancellation |
+ InternalTaskOptions.QueuedByRuntime));
+ Contract.Assert(illegalInternalOptions == 0, "TaskConstructorCore: Illegal internal options");
+#endif
+
+ // Throw exception if the user specifies both LongRunning and SelfReplicating
+ if (((creationOptions & TaskCreationOptions.LongRunning) != 0) &&
+ ((internalOptions & InternalTaskOptions.SelfReplicating) != 0))
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_ctor_LRandSR);
+ }
+
+ // Assign options to m_stateAndOptionsFlag.
+ Contract.Assert(m_stateFlags == 0, "TaskConstructorCore: non-zero m_stateFlags");
+ Contract.Assert((((int)creationOptions) | OptionsMask) == OptionsMask, "TaskConstructorCore: options take too many bits");
+ var tmpFlags = (int)creationOptions | (int)internalOptions;
+ if ((m_action == null) || ((internalOptions & InternalTaskOptions.ContinuationTask) != 0))
+ {
+ // For continuation tasks or TaskCompletionSource.Tasks, begin life in the
+ // WaitingForActivation state rather than the Created state.
+ tmpFlags |= TASK_STATE_WAITINGFORACTIVATION;
+ }
+ m_stateFlags = tmpFlags; // one write to the volatile m_stateFlags instead of two when setting the above options
+
+ // Now is the time to add the new task to the children list
+ // of the creating task if the options call for it.
+ // We can safely call the creator task's AddNewChild() method to register it,
+ // because at this point we are already on its thread of execution.
+
+ Task parent = m_contingentProperties?.m_parent;
+ if (parent != null
+ && ((creationOptions & TaskCreationOptions.AttachedToParent) != 0)
+ && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
+ )
+ {
+ parent.AddNewChild();
+ }
+
+ // if we have a non-null cancellationToken, allocate the contingent properties to save it
+ // we need to do this as the very last thing in the construction path, because the CT registration could modify m_stateFlags
+ if (cancellationToken.CanBeCanceled)
+ {
+ Contract.Assert((internalOptions &
+ (InternalTaskOptions.ChildReplica | InternalTaskOptions.SelfReplicating | InternalTaskOptions.ContinuationTask)) == 0,
+ "TaskConstructorCore: Did not expect to see cancelable token for replica/replicating or continuation task.");
+
+ AssignCancellationToken(cancellationToken, null, null);
+ }
+ }
+
+ /// <summary>
+ /// Handles everything needed for associating a CancellationToken with a task which is being constructed.
+ /// This method is meant to be be called either from the TaskConstructorCore or from ContinueWithCore.
+ /// </summary>
+ private void AssignCancellationToken(CancellationToken cancellationToken, Task antecedent, TaskContinuation continuation)
+ {
+ // There is no need to worry about concurrency issues here because we are in the constructor path of the task --
+ // there should not be any race conditions to set m_contingentProperties at this point.
+ ContingentProperties props = EnsureContingentPropertiesInitializedUnsafe();
+ props.m_cancellationToken = cancellationToken;
+
+ try
+ {
+ if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ {
+ cancellationToken.ThrowIfSourceDisposed();
+ }
+
+ // If an unstarted task has a valid CancellationToken that gets signalled while the task is still not queued
+ // we need to proactively cancel it, because it may never execute to transition itself.
+ // The only way to accomplish this is to register a callback on the CT.
+ // We exclude Promise tasks from this, because TaskCompletionSource needs to fully control the inner tasks's lifetime (i.e. not allow external cancellations)
+ if ((((InternalTaskOptions)Options &
+ (InternalTaskOptions.QueuedByRuntime | InternalTaskOptions.PromiseTask | InternalTaskOptions.LazyCancellation)) == 0))
+ {
+ if (cancellationToken.IsCancellationRequested)
+ {
+ // Fast path for an already-canceled cancellationToken
+ this.InternalCancel(false);
+ }
+ else
+ {
+ // Regular path for an uncanceled cancellationToken
+ CancellationTokenRegistration ctr;
+ if (antecedent == null)
+ {
+ // if no antecedent was specified, use this task's reference as the cancellation state object
+ ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback, this);
+ }
+ else
+ {
+ // If an antecedent was specified, pack this task, its antecedent and the TaskContinuation together as a tuple
+ // and use it as the cancellation state object. This will be unpacked in the cancellation callback so that
+ // antecedent.RemoveCancellation(continuation) can be invoked.
+ ctr = cancellationToken.InternalRegisterWithoutEC(s_taskCancelCallback,
+ new Tuple<Task, Task, TaskContinuation>(this, antecedent, continuation));
+ }
+
+ props.m_cancellationRegistration = new Shared<CancellationTokenRegistration>(ctr);
+ }
+ }
+ }
+ catch
+ {
+ // If we have an exception related to our CancellationToken, then we need to subtract ourselves
+ // from our parent before throwing it.
+ Task parent = m_contingentProperties?.m_parent;
+ if ((parent != null) &&
+ ((Options & TaskCreationOptions.AttachedToParent) != 0)
+ && ((parent.Options & TaskCreationOptions.DenyChildAttach) == 0))
+ {
+ parent.DisregardChild();
+ }
+ throw;
+ }
+ }
+
+
+ // Static delegate to be used as a cancellation callback on unstarted tasks that have a valid cancellation token.
+ // This is necessary to transition them into canceled state if their cancellation token is signalled while they are still not queued
+ private readonly static Action<Object> s_taskCancelCallback = new Action<Object>(TaskCancelCallback);
+ private static void TaskCancelCallback(Object o)
+ {
+ var targetTask = o as Task;
+ if (targetTask == null)
+ {
+ var tuple = o as Tuple<Task, Task, TaskContinuation>;
+ if (tuple != null)
+ {
+ targetTask = tuple.Item1;
+
+ Task antecedentTask = tuple.Item2;
+ TaskContinuation continuation = tuple.Item3;
+ antecedentTask.RemoveContinuation(continuation);
+ }
+ }
+ Contract.Assert(targetTask != null,
+ "targetTask should have been non-null, with the supplied argument being a task or a tuple containing one");
+ targetTask.InternalCancel(false);
+ }
+
+ // Debugger support
+ private string DebuggerDisplayMethodDescription
+ {
+ get
+ {
+ Delegate d = (Delegate)m_action;
+ return d != null ? d.Method.ToString() : "{null}";
+ }
+ }
+
+
+ /// <summary>
+ /// Captures the ExecutionContext so long as flow isn't suppressed.
+ /// </summary>
+ /// <param name="stackMark">A stack crawl mark pointing to the frame of the caller.</param>
+
+ [SecuritySafeCritical]
+ internal void PossiblyCaptureContext(ref StackCrawlMark stackMark)
+ {
+ Contract.Assert(m_contingentProperties == null || m_contingentProperties.m_capturedContext == null,
+ "Captured an ExecutionContext when one was already captured.");
+
+ // In the legacy .NET 3.5 build, we don't have the optimized overload of Capture()
+ // available, so we call the parameterless overload.
+ CapturedContext = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
+ }
+
+ // Internal property to process TaskCreationOptions access and mutation.
+ internal TaskCreationOptions Options
+ {
+ get
+ {
+ int stateFlags = m_stateFlags; // "cast away" volatility to enable inlining of OptionsMethod
+ return OptionsMethod(stateFlags);
+ }
+ }
+
+ // Similar to Options property, but allows for the use of a cached flags value rather than
+ // a read of the volatile m_stateFlags field.
+ internal static TaskCreationOptions OptionsMethod(int flags)
+ {
+ Contract.Assert((OptionsMask & 1) == 1, "OptionsMask needs a shift in Options.get");
+ return (TaskCreationOptions)(flags & OptionsMask);
+ }
+
+ // Atomically OR-in newBits to m_stateFlags, while making sure that
+ // no illegalBits are set. Returns true on success, false on failure.
+ internal bool AtomicStateUpdate(int newBits, int illegalBits)
+ {
+ // This could be implemented in terms of:
+ // internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags);
+ // but for high-throughput perf, that delegation's cost is noticeable.
+
+ SpinWait sw = new SpinWait();
+ do
+ {
+ int oldFlags = m_stateFlags;
+ if ((oldFlags & illegalBits) != 0) return false;
+ if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
+ {
+ return true;
+ }
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ internal bool AtomicStateUpdate(int newBits, int illegalBits, ref int oldFlags)
+ {
+ SpinWait sw = new SpinWait();
+ do
+ {
+ oldFlags = m_stateFlags;
+ if ((oldFlags & illegalBits) != 0) return false;
+ if (Interlocked.CompareExchange(ref m_stateFlags, oldFlags | newBits, oldFlags) == oldFlags)
+ {
+ return true;
+ }
+ sw.SpinOnce();
+ } while (true);
+ }
+
+ /// <summary>
+ /// Sets or clears the TASK_STATE_WAIT_COMPLETION_NOTIFICATION state bit.
+ /// The debugger sets this bit to aid it in "stepping out" of an async method body.
+ /// If enabled is true, this must only be called on a task that has not yet been completed.
+ /// If enabled is false, this may be called on completed tasks.
+ /// Either way, it should only be used for promise-style tasks.
+ /// </summary>
+ /// <param name="enabled">true to set the bit; false to unset the bit.</param>
+ internal void SetNotificationForWaitCompletion(bool enabled)
+ {
+ Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0,
+ "Should only be used for promise-style tasks"); // hasn't been vetted on other kinds as there hasn't been a need
+
+ if (enabled)
+ {
+ // Atomically set the END_AWAIT_NOTIFICATION bit
+ bool success = AtomicStateUpdate(TASK_STATE_WAIT_COMPLETION_NOTIFICATION,
+ TASK_STATE_COMPLETED_MASK | TASK_STATE_COMPLETION_RESERVED);
+ Contract.Assert(success, "Tried to set enabled on completed Task");
+ }
+ else
+ {
+ // Atomically clear the END_AWAIT_NOTIFICATION bit
+ SpinWait sw = new SpinWait();
+ while (true)
+ {
+ int oldFlags = m_stateFlags;
+ int newFlags = oldFlags & (~TASK_STATE_WAIT_COMPLETION_NOTIFICATION);
+ if (Interlocked.CompareExchange(ref m_stateFlags, newFlags, oldFlags) == oldFlags) break;
+ sw.SpinOnce();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Calls the debugger notification method if the right bit is set and if
+ /// the task itself allows for the notification to proceed.
+ /// </summary>
+ /// <returns>true if the debugger was notified; otherwise, false.</returns>
+ internal bool NotifyDebuggerOfWaitCompletionIfNecessary()
+ {
+ // Notify the debugger if of any of the tasks we've waited on requires notification
+ if (IsWaitNotificationEnabled && ShouldNotifyDebuggerOfWaitCompletion)
+ {
+ NotifyDebuggerOfWaitCompletion();
+ return true;
+ }
+ return false;
+ }
+
+ /// <summary>Returns true if any of the supplied tasks require wait notification.</summary>
+ /// <param name="tasks">The tasks to check.</param>
+ /// <returns>true if any of the tasks require notification; otherwise, false.</returns>
+ internal static bool AnyTaskRequiresNotifyDebuggerOfWaitCompletion(Task[] tasks)
+ {
+ Contract.Assert(tasks != null, "Expected non-null array of tasks");
+ foreach (var task in tasks)
+ {
+ if (task != null &&
+ task.IsWaitNotificationEnabled &&
+ task.ShouldNotifyDebuggerOfWaitCompletion) // potential recursion
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>Gets whether either the end await bit is set or (not xor) the task has not completed successfully.</summary>
+ /// <returns>(DebuggerBitSet || !RanToCompletion)</returns>
+ internal bool IsWaitNotificationEnabledOrNotRanToCompletion
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ return (m_stateFlags & (Task.TASK_STATE_WAIT_COMPLETION_NOTIFICATION | Task.TASK_STATE_RAN_TO_COMPLETION))
+ != Task.TASK_STATE_RAN_TO_COMPLETION;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether we should inform the debugger that we're ending a join with a task.
+ /// This should only be called if the debugger notification bit is set, as it is has some cost,
+ /// namely it is a virtual call (however calling it if the bit is not set is not functionally
+ /// harmful). Derived implementations may choose to only conditionally call down to this base
+ /// implementation.
+ /// </summary>
+ internal virtual bool ShouldNotifyDebuggerOfWaitCompletion // ideally would be familyAndAssembly, but that can't be done in C#
+ {
+ get
+ {
+ // It's theoretically possible but extremely rare that this assert could fire because the
+ // bit was unset between the time that it was checked and this method was called.
+ // It's so remote a chance that it's worth having the assert to protect against misuse.
+ bool isWaitNotificationEnabled = IsWaitNotificationEnabled;
+ Contract.Assert(isWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
+ return isWaitNotificationEnabled;
+ }
+ }
+
+ /// <summary>Gets whether the task's debugger notification for wait completion bit is set.</summary>
+ /// <returns>true if the bit is set; false if it's not set.</returns>
+ internal bool IsWaitNotificationEnabled // internal only to enable unit tests; would otherwise be private
+ {
+ get { return (m_stateFlags & TASK_STATE_WAIT_COMPLETION_NOTIFICATION) != 0; }
+ }
+
+ /// <summary>Placeholder method used as a breakpoint target by the debugger. Must not be inlined or optimized.</summary>
+ /// <remarks>All joins with a task should end up calling this if their debugger notification bit is set.</remarks>
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ private void NotifyDebuggerOfWaitCompletion()
+ {
+ // It's theoretically possible but extremely rare that this assert could fire because the
+ // bit was unset between the time that it was checked and this method was called.
+ // It's so remote a chance that it's worth having the assert to protect against misuse.
+ Contract.Assert(IsWaitNotificationEnabled, "Should only be called if the wait completion bit is set.");
+
+ // Now that we're notifying the debugger, clear the bit. The debugger should do this anyway,
+ // but this adds a bit of protection in case it fails to, and given that the debugger is involved,
+ // the overhead here for the interlocked is negligable. We do still rely on the debugger
+ // to clear bits, as this doesn't recursively clear bits in the case of, for example, WhenAny.
+ SetNotificationForWaitCompletion(enabled: false);
+ }
+
+
+ // Atomically mark a Task as started while making sure that it is not canceled.
+ internal bool MarkStarted()
+ {
+ return AtomicStateUpdate(TASK_STATE_STARTED, TASK_STATE_CANCELED | TASK_STATE_STARTED);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal bool FireTaskScheduledIfNeeded(TaskScheduler ts)
+ {
+ var etwLog = TplEtwProvider.Log;
+ if (etwLog.IsEnabled() && (m_stateFlags & Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED) == 0)
+ {
+ m_stateFlags |= Task.TASK_STATE_TASKSCHEDULED_WAS_FIRED;
+
+ Task currentTask = Task.InternalCurrent;
+ Task parentTask = m_contingentProperties?.m_parent;
+ etwLog.TaskScheduled(ts.Id, currentTask == null ? 0 : currentTask.Id,
+ this.Id, parentTask == null ? 0 : parentTask.Id, (int)this.Options,
+ System.Threading.Thread.GetDomainID());
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// Internal function that will be called by a new child task to add itself to
+ /// the children list of the parent (this).
+ ///
+ /// Since a child task can only be created from the thread executing the action delegate
+ /// of this task, reentrancy is neither required nor supported. This should not be called from
+ /// anywhere other than the task construction/initialization codepaths.
+ /// </summary>
+ internal void AddNewChild()
+ {
+ Contract.Assert(Task.InternalCurrent == this || this.IsSelfReplicatingRoot, "Task.AddNewChild(): Called from an external context");
+
+ var props = EnsureContingentPropertiesInitialized();
+
+ if (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot)
+ {
+ // A count of 1 indicates so far there was only the parent, and this is the first child task
+ // Single kid => no fuss about who else is accessing the count. Let's save ourselves 100 cycles
+ // We exclude self replicating root tasks from this optimization, because further child creation can take place on
+ // other cores and with bad enough timing this write may not be visible to them.
+ props.m_completionCountdown++;
+ }
+ else
+ {
+ // otherwise do it safely
+ Interlocked.Increment(ref props.m_completionCountdown);
+ }
+ }
+
+ // This is called in the case where a new child is added, but then encounters a CancellationToken-related exception.
+ // We need to subtract that child from m_completionCountdown, or the parent will never complete.
+ internal void DisregardChild()
+ {
+ Contract.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context");
+
+ var props = EnsureContingentPropertiesInitialized();
+ Contract.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2");
+ Interlocked.Decrement(ref props.m_completionCountdown);
+ }
+
+ /// <summary>
+ /// Starts the <see cref="Task"/>, scheduling it for execution to the current <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
+ /// </summary>
+ /// <remarks>
+ /// A task may only be started and run only once. Any attempts to schedule a task a second time
+ /// will result in an exception.
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
+ /// executed, or canceled, or it may have been created in a manner that doesn't support direct
+ /// scheduling.
+ /// </exception>
+ public void Start()
+ {
+ Start(TaskScheduler.Current);
+ }
+
+ /// <summary>
+ /// Starts the <see cref="Task"/>, scheduling it for execution to the specified <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
+ /// </summary>
+ /// <remarks>
+ /// A task may only be started and run only once. Any attempts to schedule a task a second time will
+ /// result in an exception.
+ /// </remarks>
+ /// <param name="scheduler">
+ /// The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> with which to associate
+ /// and execute this task.
+ /// </param>
+ /// <exception cref="ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
+ /// executed, or canceled, or it may have been created in a manner that doesn't support direct
+ /// scheduling.
+ /// </exception>
+ public void Start(TaskScheduler scheduler)
+ {
+ // Read the volatile m_stateFlags field once and cache it for subsequent operations
+ int flags = m_stateFlags;
+
+ // Need to check this before (m_action == null) because completed tasks will
+ // set m_action to null. We would want to know if this is the reason that m_action == null.
+ if (IsCompletedMethod(flags))
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_Start_TaskCompleted);
+ }
+
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+
+ var options = OptionsMethod(flags);
+ if ((options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_Start_Promise);
+ }
+ if ((options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_Start_ContinuationTask);
+ }
+
+ // Make sure that Task only gets started once. Or else throw an exception.
+ if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_Start_AlreadyStarted);
+ }
+
+ ScheduleAndStart(true);
+ }
+
+ /// <summary>
+ /// Runs the <see cref="Task"/> synchronously on the current <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A task may only be started and run only once. Any attempts to schedule a task a second time will
+ /// result in an exception.
+ /// </para>
+ /// <para>
+ /// Tasks executed with <see cref="RunSynchronously()"/> will be associated with the current <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>.
+ /// </para>
+ /// <para>
+ /// If the target scheduler does not support running this Task on the current thread, the Task will
+ /// be scheduled for execution on the scheduler, and the current thread will block until the
+ /// Task has completed execution.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
+ /// executed, or canceled, or it may have been created in a manner that doesn't support direct
+ /// scheduling.
+ /// </exception>
+ public void RunSynchronously()
+ {
+ InternalRunSynchronously(TaskScheduler.Current, waitForCompletion: true);
+ }
+
+ /// <summary>
+ /// Runs the <see cref="Task"/> synchronously on the <see
+ /// cref="System.Threading.Tasks.TaskScheduler">scheduler</see> provided.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A task may only be started and run only once. Any attempts to schedule a task a second time will
+ /// result in an exception.
+ /// </para>
+ /// <para>
+ /// If the target scheduler does not support running this Task on the current thread, the Task will
+ /// be scheduled for execution on the scheduler, and the current thread will block until the
+ /// Task has completed execution.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="InvalidOperationException">
+ /// The <see cref="Task"/> is not in a valid state to be started. It may have already been started,
+ /// executed, or canceled, or it may have been created in a manner that doesn't support direct
+ /// scheduling.
+ /// </exception>
+ /// <exception cref="ArgumentNullException">The <paramref name="scheduler"/> parameter
+ /// is null.</exception>
+ /// <param name="scheduler">The scheduler on which to attempt to run this task inline.</param>
+ public void RunSynchronously(TaskScheduler scheduler)
+ {
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ InternalRunSynchronously(scheduler, waitForCompletion: true);
+ }
+
+ //
+ // Internal version of RunSynchronously that allows not waiting for completion.
+ //
+ [SecuritySafeCritical] // Needed for QueueTask
+ internal void InternalRunSynchronously(TaskScheduler scheduler, bool waitForCompletion)
+ {
+ Contract.Requires(scheduler != null, "Task.InternalRunSynchronously(): null TaskScheduler");
+
+ // Read the volatile m_stateFlags field once and cache it for subsequent operations
+ int flags = m_stateFlags;
+
+ // Can't call this method on a continuation task
+ var options = OptionsMethod(flags);
+ if ((options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) != 0)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_Continuation);
+ }
+
+ // Can't call this method on a promise-style task
+ if ((options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_Promise);
+ }
+
+ // Can't call this method on a task that has already completed
+ if (IsCompletedMethod(flags))
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_TaskCompleted);
+ }
+
+ // Make sure that Task only gets started once. Or else throw an exception.
+ if (Interlocked.CompareExchange(ref m_taskScheduler, scheduler, null) != null)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_AlreadyStarted);
+ }
+
+ // execute only if we successfully cancel when concurrent cancel attempts are made.
+ // otherwise throw an exception, because we've been canceled.
+ if (MarkStarted())
+ {
+ bool taskQueued = false;
+ try
+ {
+ // We wrap TryRunInline() in a try/catch block and move an excepted task to Faulted here,
+ // but not in Wait()/WaitAll()/FastWaitAll(). Here, we know for sure that the
+ // task will not be subsequently scheduled (assuming that the scheduler adheres
+ // to the guideline that an exception implies that no state change took place),
+ // so it is safe to catch the exception and move the task to a final state. The
+ // same cannot be said for Wait()/WaitAll()/FastWaitAll().
+ if (!scheduler.TryRunInline(this, false))
+ {
+ scheduler.InternalQueueTask(this);
+ taskQueued = true; // only mark this after successfully queuing the task.
+ }
+
+ // A successful TryRunInline doesn't guarantee completion, as there may be unfinished children.
+ // Also if we queued the task above, the task may not be done yet.
+ if (waitForCompletion && !IsCompleted)
+ {
+ SpinThenBlockingWait(Timeout.Infinite, default(CancellationToken));
+ }
+ }
+ catch (Exception e)
+ {
+ // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
+ // 2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
+ if (!taskQueued && !(e is ThreadAbortException))
+ {
+ // We had a problem with TryRunInline() or QueueTask().
+ // Record the exception, marking ourselves as Completed/Faulted.
+ TaskSchedulerException tse = new TaskSchedulerException(e);
+ AddException(tse);
+ Finish(false);
+
+ // Mark ourselves as "handled" to avoid crashing the finalizer thread if the caller neglects to
+ // call Wait() on this task.
+ // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
+ Contract.Assert(
+ (m_contingentProperties != null) &&
+ (m_contingentProperties.m_exceptionsHolder != null) &&
+ (m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
+ "Task.InternalRunSynchronously(): Expected m_contingentProperties.m_exceptionsHolder to exist " +
+ "and to have faults recorded.");
+ m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
+
+ // And re-throw.
+ throw tse;
+ }
+ // We had a problem with waiting or this is a thread abort. Just re-throw.
+ else throw;
+ }
+ }
+ else
+ {
+ Contract.Assert((m_stateFlags & TASK_STATE_CANCELED) != 0, "Task.RunSynchronously: expected TASK_STATE_CANCELED to be set");
+ // Can't call this method on canceled task.
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_RunSynchronously_TaskCompleted);
+ }
+ }
+
+
+ ////
+ //// Helper methods for Factory StartNew methods.
+ ////
+
+
+ // Implicitly converts action to object and handles the meat of the StartNew() logic.
+ internal static Task InternalStartNew(
+ Task creatingTask, Delegate action, object state, CancellationToken cancellationToken, TaskScheduler scheduler,
+ TaskCreationOptions options, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark)
+ {
+ // Validate arguments.
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ // Create and schedule the task. This throws an InvalidOperationException if already shut down.
+ // Here we add the InternalTaskOptions.QueuedByRuntime to the internalOptions, so that TaskConstructorCore can skip the cancellation token registration
+ Task t = new Task(action, state, creatingTask, cancellationToken, options, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler);
+ t.PossiblyCaptureContext(ref stackMark);
+
+ t.ScheduleAndStart(false);
+ return t;
+ }
+
+ /// <summary>
+ /// Gets a unique ID for a <see cref="Task">Task</see> or task continuation instance.
+ /// </summary>
+ internal static int NewId()
+ {
+ int newId = 0;
+ // We need to repeat if Interlocked.Increment wraps around and returns 0.
+ // Otherwise next time this task's Id is queried it will get a new value
+ do
+ {
+ newId = Interlocked.Increment(ref s_taskIdCounter);
+ }
+ while (newId == 0);
+ TplEtwProvider.Log.NewID(newId);
+ return newId;
+ }
+
+
+ /////////////
+ // properties
+
+ /// <summary>
+ /// Gets a unique ID for this <see cref="Task">Task</see> instance.
+ /// </summary>
+ /// <remarks>
+ /// Task IDs are assigned on-demand and do not necessarily represent the order in the which Task
+ /// instances were created.
+ /// </remarks>
+ public int Id
+ {
+ get
+ {
+ if (m_taskId == 0)
+ {
+ int newId = NewId();
+ Interlocked.CompareExchange(ref m_taskId, newId, 0);
+ }
+
+ return m_taskId;
+ }
+ }
+
+ /// <summary>
+ /// Returns the unique ID of the currently executing <see cref="Task">Task</see>.
+ /// </summary>
+ public static int? CurrentId
+ {
+ get
+ {
+ Task currentTask = InternalCurrent;
+ if (currentTask != null)
+ return currentTask.Id;
+ else
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="Task">Task</see> instance currently executing, or
+ /// null if none exists.
+ /// </summary>
+ internal static Task InternalCurrent
+ {
+ get { return t_currentTask; }
+ }
+
+ /// <summary>
+ /// Gets the Task instance currently executing if the specified creation options
+ /// contain AttachedToParent.
+ /// </summary>
+ /// <param name="options">The options to check.</param>
+ /// <returns>The current task if there is one and if AttachToParent is in the options; otherwise, null.</returns>
+ internal static Task InternalCurrentIfAttached(TaskCreationOptions creationOptions)
+ {
+ return (creationOptions & TaskCreationOptions.AttachedToParent) != 0 ? InternalCurrent : null;
+ }
+
+ /// <summary>
+ /// Gets the StackGuard object assigned to the current thread.
+ /// </summary>
+ internal static StackGuard CurrentStackGuard
+ {
+ get
+ {
+ StackGuard sg = t_stackGuard;
+ if (sg == null)
+ {
+ t_stackGuard = sg = new StackGuard();
+ }
+ return sg;
+ }
+ }
+
+
+ /// <summary>
+ /// Gets the <see cref="T:System.AggregateException">Exception</see> that caused the <see
+ /// cref="Task">Task</see> to end prematurely. If the <see
+ /// cref="Task">Task</see> completed successfully or has not yet thrown any
+ /// exceptions, this will return null.
+ /// </summary>
+ /// <remarks>
+ /// Tasks that throw unhandled exceptions store the resulting exception and propagate it wrapped in a
+ /// <see cref="System.AggregateException"/> in calls to <see cref="Wait()">Wait</see>
+ /// or in accesses to the <see cref="Exception"/> property. Any exceptions not observed by the time
+ /// the Task instance is garbage collected will be propagated on the finalizer thread.
+ /// </remarks>
+ public AggregateException Exception
+ {
+ get
+ {
+ AggregateException e = null;
+
+ // If you're faulted, retrieve the exception(s)
+ if (IsFaulted) e = GetExceptions(false);
+
+ // Only return an exception in faulted state (skip manufactured exceptions)
+ // A "benevolent" race condition makes it possible to return null when IsFaulted is
+ // true (i.e., if IsFaulted is set just after the check to IsFaulted above).
+ Contract.Assert((e == null) || IsFaulted, "Task.Exception_get(): returning non-null value when not Faulted");
+
+ return e;
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="T:System.Threading.Tasks.TaskStatus">TaskStatus</see> of this Task.
+ /// </summary>
+ public TaskStatus Status
+ {
+ get
+ {
+ TaskStatus rval;
+
+ // get a cached copy of the state flags. This should help us
+ // to get a consistent view of the flags if they are changing during the
+ // execution of this method.
+ int sf = m_stateFlags;
+
+ if ((sf & TASK_STATE_FAULTED) != 0) rval = TaskStatus.Faulted;
+ else if ((sf & TASK_STATE_CANCELED) != 0) rval = TaskStatus.Canceled;
+ else if ((sf & TASK_STATE_RAN_TO_COMPLETION) != 0) rval = TaskStatus.RanToCompletion;
+ else if ((sf & TASK_STATE_WAITING_ON_CHILDREN) != 0) rval = TaskStatus.WaitingForChildrenToComplete;
+ else if ((sf & TASK_STATE_DELEGATE_INVOKED) != 0) rval = TaskStatus.Running;
+ else if ((sf & TASK_STATE_STARTED) != 0) rval = TaskStatus.WaitingToRun;
+ else if ((sf & TASK_STATE_WAITINGFORACTIVATION) != 0) rval = TaskStatus.WaitingForActivation;
+ else rval = TaskStatus.Created;
+
+ return rval;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="Task">Task</see> instance has completed
+ /// execution due to being canceled.
+ /// </summary>
+ /// <remarks>
+ /// A <see cref="Task">Task</see> will complete in Canceled state either if its <see cref="CancellationToken">CancellationToken</see>
+ /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on
+ /// its already signaled CancellationToken by throwing an
+ /// <see cref="System.OperationCanceledException">OperationCanceledException</see> that bears the same
+ /// <see cref="System.Threading.CancellationToken">CancellationToken</see>.
+ /// </remarks>
+ public bool IsCanceled
+ {
+ get
+ {
+ // Return true if canceled bit is set and faulted bit is not set
+ return (m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_FAULTED)) == TASK_STATE_CANCELED;
+ }
+ }
+
+ /// <summary>
+ /// Returns true if this task has a cancellation token and it was signaled.
+ /// To be used internally in execute entry codepaths.
+ /// </summary>
+ internal bool IsCancellationRequested
+ {
+ get
+ {
+ // check both the internal cancellation request flag and the CancellationToken attached to this task
+ var props = Volatile.Read(ref m_contingentProperties);
+ return props != null &&
+ (props.m_internalCancellationRequested == CANCELLATION_REQUESTED ||
+ props.m_cancellationToken.IsCancellationRequested);
+ }
+ }
+
+ /// <summary>
+ /// Ensures that the contingent properties field has been initialized.
+ /// ASSUMES THAT m_stateFlags IS ALREADY SET!
+ /// </summary>
+ /// <returns>The initialized contingent properties object.</returns>
+ internal ContingentProperties EnsureContingentPropertiesInitialized()
+ {
+ return LazyInitializer.EnsureInitialized(ref m_contingentProperties, () => new ContingentProperties());
+ }
+
+ /// <summary>
+ /// Without synchronization, ensures that the contingent properties field has been initialized.
+ /// ASSUMES THAT m_stateFlags IS ALREADY SET!
+ /// </summary>
+ /// <returns>The initialized contingent properties object.</returns>
+ internal ContingentProperties EnsureContingentPropertiesInitializedUnsafe()
+ {
+ return m_contingentProperties ?? (m_contingentProperties = new ContingentProperties());
+ }
+
+ /// <summary>
+ /// This internal property provides access to the CancellationToken that was set on the task
+ /// when it was constructed.
+ /// </summary>
+ internal CancellationToken CancellationToken
+ {
+ get
+ {
+ var props = Volatile.Read(ref m_contingentProperties);
+ return (props == null) ? default(CancellationToken) : props.m_cancellationToken;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether this <see cref="Task"/> threw an OperationCanceledException while its CancellationToken was signaled.
+ /// </summary>
+ internal bool IsCancellationAcknowledged
+ {
+ get { return (m_stateFlags & TASK_STATE_CANCELLATIONACKNOWLEDGED) != 0; }
+ }
+
+
+ /// <summary>
+ /// Gets whether this <see cref="Task">Task</see> has completed.
+ /// </summary>
+ /// <remarks>
+ /// <see cref="IsCompleted"/> will return true when the Task is in one of the three
+ /// final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ public bool IsCompleted
+ {
+ get
+ {
+ int stateFlags = m_stateFlags; // enable inlining of IsCompletedMethod by "cast"ing away the volatility
+ return IsCompletedMethod(stateFlags);
+ }
+ }
+
+ // Similar to IsCompleted property, but allows for the use of a cached flags value
+ // rather than reading the volatile m_stateFlags field.
+ private static bool IsCompletedMethod(int flags)
+ {
+ return (flags & TASK_STATE_COMPLETED_MASK) != 0;
+ }
+
+ // For use in InternalWait -- marginally faster than (Task.Status == TaskStatus.RanToCompletion)
+ internal bool IsRanToCompletion
+ {
+ get { return (m_stateFlags & TASK_STATE_COMPLETED_MASK) == TASK_STATE_RAN_TO_COMPLETION; }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="T:System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used
+ /// to create this task.
+ /// </summary>
+ public TaskCreationOptions CreationOptions
+ {
+ get { return Options & (TaskCreationOptions)(~InternalTaskOptions.InternalOptionsMask); }
+ }
+
+ /// <summary>
+ /// Gets a <see cref="T:System.Threading.WaitHandle"/> that can be used to wait for the task to
+ /// complete.
+ /// </summary>
+ /// <remarks>
+ /// Using the wait functionality provided by <see cref="Wait()"/>
+ /// should be preferred over using <see cref="IAsyncResult.AsyncWaitHandle"/> for similar
+ /// functionality.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="Task"/> has been disposed.
+ /// </exception>
+ WaitHandle IAsyncResult.AsyncWaitHandle
+ {
+ // Although a slim event is used internally to avoid kernel resource allocation, this function
+ // forces allocation of a true WaitHandle when called.
+ get
+ {
+ bool isDisposed = (m_stateFlags & TASK_STATE_DISPOSED) != 0;
+ if (isDisposed)
+ {
+ ThrowHelper.ThrowObjectDisposedException(ExceptionResource.Task_ThrowIfDisposed);
+ }
+ return CompletedEvent.WaitHandle;
+ }
+ }
+
+ /// <summary>
+ /// Gets the state object supplied when the <see cref="Task">Task</see> was created,
+ /// or null if none was supplied.
+ /// </summary>
+ public object AsyncState
+ {
+ get { return m_stateObject; }
+ }
+
+ /// <summary>
+ /// Gets an indication of whether the asynchronous operation completed synchronously.
+ /// </summary>
+ /// <value>true if the asynchronous operation completed synchronously; otherwise, false.</value>
+ bool IAsyncResult.CompletedSynchronously
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Provides access to the TaskScheduler responsible for executing this Task.
+ /// </summary>
+ internal TaskScheduler ExecutingTaskScheduler
+ {
+ get { return m_taskScheduler; }
+ }
+
+ /// <summary>
+ /// Provides access to factory methods for creating <see cref="Task"/> and <see cref="Task{TResult}"/> instances.
+ /// </summary>
+ /// <remarks>
+ /// The factory returned from <see cref="Factory"/> is a default instance
+ /// of <see cref="System.Threading.Tasks.TaskFactory"/>, as would result from using
+ /// the default constructor on TaskFactory.
+ /// </remarks>
+ public static TaskFactory Factory { get { return s_factory; } }
+
+ /// <summary>A task that's already been completed successfully.</summary>
+ private static Task s_completedTask;
+
+ /// <summary>Gets a task that's already been completed successfully.</summary>
+ /// <remarks>May not always return the same instance.</remarks>
+ public static Task CompletedTask
+ {
+ get
+ {
+ var completedTask = s_completedTask;
+ if (completedTask == null)
+ s_completedTask = completedTask = new Task(false, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, default(CancellationToken)); // benign initialization race condition
+ return completedTask;
+ }
+ }
+
+ /// <summary>
+ /// Provides an event that can be used to wait for completion.
+ /// Only called by IAsyncResult.AsyncWaitHandle, which means that we really do need to instantiate a completion event.
+ /// </summary>
+ internal ManualResetEventSlim CompletedEvent
+ {
+ get
+ {
+ var contingentProps = EnsureContingentPropertiesInitialized();
+ if (contingentProps.m_completionEvent == null)
+ {
+ bool wasCompleted = IsCompleted;
+ ManualResetEventSlim newMre = new ManualResetEventSlim(wasCompleted);
+ if (Interlocked.CompareExchange(ref contingentProps.m_completionEvent, newMre, null) != null)
+ {
+ // Someone else already set the value, so we will just close the event right away.
+ newMre.Dispose();
+ }
+ else if (!wasCompleted && IsCompleted)
+ {
+ // We published the event as unset, but the task has subsequently completed.
+ // Set the event's state properly so that callers don't deadlock.
+ newMre.Set();
+ }
+ }
+
+ return contingentProps.m_completionEvent;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether this is the root task of a self replicating group.
+ /// </summary>
+ internal bool IsSelfReplicatingRoot
+ {
+ get
+ {
+ // Return true if self-replicating bit is set and child replica bit is not set
+ return (Options & (TaskCreationOptions)(InternalTaskOptions.SelfReplicating | InternalTaskOptions.ChildReplica))
+ == (TaskCreationOptions)InternalTaskOptions.SelfReplicating;
+ }
+ }
+
+ /// <summary>
+ /// Determines whether the task is a replica itself.
+ /// </summary>
+ internal bool IsChildReplica
+ {
+ get { return (Options & (TaskCreationOptions)InternalTaskOptions.ChildReplica) != 0; }
+ }
+
+ internal int ActiveChildCount
+ {
+ get
+ {
+ var props = Volatile.Read(ref m_contingentProperties);
+ return props != null ? props.m_completionCountdown - 1 : 0;
+ }
+ }
+
+ /// <summary>
+ /// The property formerly known as IsFaulted.
+ /// </summary>
+ internal bool ExceptionRecorded
+ {
+ get
+ {
+ var props = Volatile.Read(ref m_contingentProperties);
+ return (props != null) && (props.m_exceptionsHolder != null) && (props.m_exceptionsHolder.ContainsFaultList);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the <see cref="Task"/> completed due to an unhandled exception.
+ /// </summary>
+ /// <remarks>
+ /// If <see cref="IsFaulted"/> is true, the Task's <see cref="Status"/> will be equal to
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">TaskStatus.Faulted</see>, and its
+ /// <see cref="Exception"/> property will be non-null.
+ /// </remarks>
+ public bool IsFaulted
+ {
+ get
+ {
+ // Faulted is "king" -- if that bit is present (regardless of other bits), we are faulted.
+ return ((m_stateFlags & TASK_STATE_FAULTED) != 0);
+ }
+ }
+
+ /// <summary>
+ /// The captured execution context for the current task to run inside
+ /// If the TASK_STATE_EXECUTIONCONTEXT_IS_NULL flag is set, this means ExecutionContext.Capture returned null, otherwise
+ /// If the captured context is the default, nothing is saved, otherwise the m_contingentProperties inflates to save the context
+ /// </summary>
+ internal ExecutionContext CapturedContext
+ {
+ get
+ {
+ if ((m_stateFlags & TASK_STATE_EXECUTIONCONTEXT_IS_NULL) == TASK_STATE_EXECUTIONCONTEXT_IS_NULL)
+ {
+ return null;
+ }
+ else
+ {
+ return m_contingentProperties?.m_capturedContext ?? ExecutionContext.PreAllocatedDefault;
+ }
+ }
+ set
+ {
+ // There is no need to atomically set this bit because this set() method is only called during construction, and therefore there should be no contending accesses to m_stateFlags
+ if (value == null)
+ {
+ m_stateFlags |= TASK_STATE_EXECUTIONCONTEXT_IS_NULL;
+ }
+ else if (!value.IsPreAllocatedDefault) // not the default context, then inflate the contingent properties and set it
+ {
+ EnsureContingentPropertiesInitializedUnsafe().m_capturedContext = value;
+ }
+ //else do nothing, this is the default context
+ }
+ }
+
+ /// <summary>
+ /// Static helper function to copy specific ExecutionContext
+ /// </summary>
+ /// <param name="capturedContext">The captured context</param>
+ /// <returns>The copied context, null if the capturedContext is null</returns>
+ private static ExecutionContext CopyExecutionContext(ExecutionContext capturedContext)
+ {
+ if (capturedContext == null)
+ return null;
+ if (capturedContext.IsPreAllocatedDefault)
+ return ExecutionContext.PreAllocatedDefault;
+
+ return capturedContext.CreateCopy();
+ }
+
+
+#if DEBUG
+ /// <summary>
+ /// Retrieves an identifier for the task.
+ /// </summary>
+ internal int InternalId
+ {
+ get { return GetHashCode(); }
+ }
+#endif
+
+ /////////////
+ // methods
+
+
+ /// <summary>
+ /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="Task"/>, this method is not thread-safe.
+ /// Also, <see cref="Dispose()"/> may only be called on a <see cref="Task"/> that is in one of
+ /// the final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The exception that is thrown if the <see cref="Task"/> is not in
+ /// one of the final states: <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Disposes the <see cref="Task"/>, releasing all of its unmanaged resources.
+ /// </summary>
+ /// <param name="disposing">
+ /// A Boolean value that indicates whether this method is being called due to a call to <see
+ /// cref="Dispose()"/>.
+ /// </param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="Task"/>, this method is not thread-safe.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ // Dispose is a nop if this task was created with the DoNotDispose internal option.
+ // This is done before the completed check, because if we're not touching any
+ // state on the task, it's ok for it to happen before completion.
+ if ((Options & (TaskCreationOptions)InternalTaskOptions.DoNotDispose) != 0)
+ {
+ return;
+ }
+
+ // Task must be completed to dispose
+ if (!IsCompleted)
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.Task_Dispose_NotCompleted);
+ }
+
+ // Dispose of the underlying completion event if it exists
+ var cp = Volatile.Read(ref m_contingentProperties);
+ if (cp != null)
+ {
+ // Make a copy to protect against racing Disposes.
+ // If we wanted to make this a bit safer, we could use an interlocked here,
+ // but we state that Dispose is not thread safe.
+ var ev = cp.m_completionEvent;
+ if (ev != null)
+ {
+ // Null out the completion event in contingent props; we'll use our copy from here on out
+ cp.m_completionEvent = null;
+
+ // In the unlikely event that our completion event is inflated but not yet signaled,
+ // go ahead and signal the event. If you dispose of an unsignaled MRES, then any waiters
+ // will deadlock; an ensuing Set() will not wake them up. In the event of an AppDomainUnload,
+ // there is no guarantee that anyone else is going to signal the event, and it does no harm to
+ // call Set() twice on m_completionEvent.
+ if (!ev.IsSet) ev.Set();
+
+ // Finally, dispose of the event
+ ev.Dispose();
+ }
+ }
+ }
+
+ // We OR the flags to indicate the object has been disposed. The task
+ // has already completed at this point, and the only conceivable race condition would
+ // be with the unsetting of the TASK_STATE_WAIT_COMPLETION_NOTIFICATION flag, which
+ // is extremely unlikely and also benign. (Worst case: we hit a breakpoint
+ // twice instead of once in the debugger. Weird, but not lethal.)
+ m_stateFlags |= TASK_STATE_DISPOSED;
+ }
+
+ /////////////
+ // internal helpers
+
+
+ /// <summary>
+ /// Schedules the task for execution.
+ /// </summary>
+ /// <param name="needsProtection">If true, TASK_STATE_STARTED bit is turned on in
+ /// an atomic fashion, making sure that TASK_STATE_CANCELED does not get set
+ /// underneath us. If false, TASK_STATE_STARTED bit is OR-ed right in. This
+ /// allows us to streamline things a bit for StartNew(), where competing cancellations
+ /// are not a problem.</param>
+ [SecuritySafeCritical] // Needed for QueueTask
+ internal void ScheduleAndStart(bool needsProtection)
+ {
+ Contract.Assert(m_taskScheduler != null, "expected a task scheduler to have been selected");
+ Contract.Assert((m_stateFlags & TASK_STATE_STARTED) == 0, "task has already started");
+
+ // Set the TASK_STATE_STARTED bit
+ if (needsProtection)
+ {
+ if (!MarkStarted())
+ {
+ // A cancel has snuck in before we could get started. Quietly exit.
+ return;
+ }
+ }
+ else
+ {
+ m_stateFlags |= TASK_STATE_STARTED;
+ }
+
+ if (s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+
+ if (AsyncCausalityTracer.LoggingOn && (Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
+ {
+ //For all other task than TaskContinuations we want to log. TaskContinuations log in their constructor
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task: "+((Delegate)m_action).Method.Name, 0);
+ }
+
+
+ try
+ {
+ // Queue to the indicated scheduler.
+ m_taskScheduler.InternalQueueTask(this);
+ }
+ catch (ThreadAbortException tae)
+ {
+ AddException(tae);
+ FinishThreadAbortedTask(true, false);
+ }
+ catch (Exception e)
+ {
+ // The scheduler had a problem queueing this task. Record the exception, leaving this task in
+ // a Faulted state.
+ TaskSchedulerException tse = new TaskSchedulerException(e);
+ AddException(tse);
+ Finish(false);
+
+ // Now we need to mark ourselves as "handled" to avoid crashing the finalizer thread if we are called from StartNew()
+ // or from the self replicating logic, because in both cases the exception is either propagated outside directly, or added
+ // to an enclosing parent. However we won't do this for continuation tasks, because in that case we internally eat the exception
+ // and therefore we need to make sure the user does later observe it explicitly or see it on the finalizer.
+
+ if ((Options & (TaskCreationOptions)InternalTaskOptions.ContinuationTask) == 0)
+ {
+ // m_contingentProperties.m_exceptionsHolder *should* already exist after AddException()
+ Contract.Assert(
+ (m_contingentProperties != null) &&
+ (m_contingentProperties.m_exceptionsHolder != null) &&
+ (m_contingentProperties.m_exceptionsHolder.ContainsFaultList),
+ "Task.ScheduleAndStart(): Expected m_contingentProperties.m_exceptionsHolder to exist " +
+ "and to have faults recorded.");
+
+ m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
+ }
+ // re-throw the exception wrapped as a TaskSchedulerException.
+ throw tse;
+ }
+ }
+
+ /// <summary>
+ /// Adds an exception to the list of exceptions this task has thrown.
+ /// </summary>
+ /// <param name="exceptionObject">An object representing either an Exception or a collection of Exceptions.</param>
+ internal void AddException(object exceptionObject)
+ {
+ Contract.Requires(exceptionObject != null, "Task.AddException: Expected a non-null exception object");
+ AddException(exceptionObject, representsCancellation: false);
+ }
+
+ /// <summary>
+ /// Adds an exception to the list of exceptions this task has thrown.
+ /// </summary>
+ /// <param name="exceptionObject">An object representing either an Exception or a collection of Exceptions.</param>
+ /// <param name="representsCancellation">Whether the exceptionObject is an OperationCanceledException representing cancellation.</param>
+ internal void AddException(object exceptionObject, bool representsCancellation)
+ {
+ Contract.Requires(exceptionObject != null, "Task.AddException: Expected a non-null exception object");
+
+#if DEBUG
+ var eoAsException = exceptionObject as Exception;
+ var eoAsEnumerableException = exceptionObject as IEnumerable<Exception>;
+ var eoAsEdi = exceptionObject as ExceptionDispatchInfo;
+ var eoAsEnumerableEdi = exceptionObject as IEnumerable<ExceptionDispatchInfo>;
+
+ Contract.Assert(
+ eoAsException != null || eoAsEnumerableException != null || eoAsEdi != null || eoAsEnumerableEdi != null,
+ "Task.AddException: Expected an Exception, ExceptionDispatchInfo, or an IEnumerable<> of one of those");
+
+ var eoAsOce = exceptionObject as OperationCanceledException;
+
+ Contract.Assert(
+ !representsCancellation ||
+ eoAsOce != null ||
+ (eoAsEdi != null && eoAsEdi.SourceException is OperationCanceledException),
+ "representsCancellation should be true only if an OCE was provided.");
+#endif
+
+ //
+ // WARNING: A great deal of care went into ensuring that
+ // AddException() and GetExceptions() are never called
+ // simultaneously. See comment at start of GetExceptions().
+ //
+
+ // Lazily initialize the holder, ensuring only one thread wins.
+ var props = EnsureContingentPropertiesInitialized();
+ if (props.m_exceptionsHolder == null)
+ {
+ TaskExceptionHolder holder = new TaskExceptionHolder(this);
+ if (Interlocked.CompareExchange(ref props.m_exceptionsHolder, holder, null) != null)
+ {
+ // If someone else already set the value, suppress finalization.
+ holder.MarkAsHandled(false);
+ }
+ }
+
+ lock (props)
+ {
+ props.m_exceptionsHolder.Add(exceptionObject, representsCancellation);
+ }
+ }
+
+ /// <summary>
+ /// Returns a list of exceptions by aggregating the holder's contents. Or null if
+ /// no exceptions have been thrown.
+ /// </summary>
+ /// <param name="includeTaskCanceledExceptions">Whether to include a TCE if cancelled.</param>
+ /// <returns>An aggregate exception, or null if no exceptions have been caught.</returns>
+ private AggregateException GetExceptions(bool includeTaskCanceledExceptions)
+ {
+ //
+ // WARNING: The Task/Task<TResult>/TaskCompletionSource classes
+ // have all been carefully crafted to insure that GetExceptions()
+ // is never called while AddException() is being called. There
+ // are locks taken on m_contingentProperties in several places:
+ //
+ // -- Task<TResult>.TrySetException(): The lock allows the
+ // task to be set to Faulted state, and all exceptions to
+ // be recorded, in one atomic action.
+ //
+ // -- Task.Exception_get(): The lock ensures that Task<TResult>.TrySetException()
+ // is allowed to complete its operation before Task.Exception_get()
+ // can access GetExceptions().
+ //
+ // -- Task.ThrowIfExceptional(): The lock insures that Wait() will
+ // not attempt to call GetExceptions() while Task<TResult>.TrySetException()
+ // is in the process of calling AddException().
+ //
+ // For "regular" tasks, we effectively keep AddException() and GetException()
+ // from being called concurrently by the way that the state flows. Until
+ // a Task is marked Faulted, Task.Exception_get() returns null. And
+ // a Task is not marked Faulted until it and all of its children have
+ // completed, which means that all exceptions have been recorded.
+ //
+ // It might be a lot easier to follow all of this if we just required
+ // that all calls to GetExceptions() and AddExceptions() were made
+ // under a lock on m_contingentProperties. But that would also
+ // increase our lock occupancy time and the frequency with which we
+ // would need to take the lock.
+ //
+ // If you add a call to GetExceptions() anywhere in the code,
+ // please continue to maintain the invariant that it can't be
+ // called when AddException() is being called.
+ //
+
+ // We'll lazily create a TCE if the task has been canceled.
+ Exception canceledException = null;
+ if (includeTaskCanceledExceptions && IsCanceled)
+ {
+ // Backcompat:
+ // Ideally we'd just use the cached OCE from this.GetCancellationExceptionDispatchInfo()
+ // here. However, that would result in a potentially breaking change from .NET 4, which
+ // has the code here that throws a new exception instead of the original, and the EDI
+ // may not contain a TCE, but an OCE or any OCE-derived type, which would mean we'd be
+ // propagating an exception of a different type.
+ canceledException = new TaskCanceledException(this);
+ }
+
+ if (ExceptionRecorded)
+ {
+ // There are exceptions; get the aggregate and optionally add the canceled
+ // exception to the aggregate (if applicable).
+ Contract.Assert(m_contingentProperties != null); // ExceptionRecorded ==> m_contingentProperties != null
+
+ // No need to lock around this, as other logic prevents the consumption of exceptions
+ // before they have been completely processed.
+ return m_contingentProperties.m_exceptionsHolder.CreateExceptionObject(false, canceledException);
+ }
+ else if (canceledException != null)
+ {
+ // No exceptions, but there was a cancelation. Aggregate and return it.
+ return new AggregateException(canceledException);
+ }
+
+ return null;
+ }
+
+ /// <summary>Gets the exception dispatch infos once the task has faulted.</summary>
+ internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
+ {
+ bool exceptionsAvailable = IsFaulted && ExceptionRecorded;
+ Contract.Assert(exceptionsAvailable, "Must only be used when the task has faulted with exceptions.");
+ return exceptionsAvailable ?
+ m_contingentProperties.m_exceptionsHolder.GetExceptionDispatchInfos() :
+ new ReadOnlyCollection<ExceptionDispatchInfo>(new ExceptionDispatchInfo[0]);
+ }
+
+ /// <summary>Gets the ExceptionDispatchInfo containing the OperationCanceledException for this task.</summary>
+ /// <returns>The ExceptionDispatchInfo. May be null if no OCE was stored for the task.</returns>
+ internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+ {
+ Contract.Assert(IsCanceled, "Must only be used when the task has canceled.");
+ return Volatile.Read(ref m_contingentProperties)?.m_exceptionsHolder?.GetCancellationExceptionDispatchInfo(); // may be null
+ }
+
+ /// <summary>
+ /// Throws an aggregate exception if the task contains exceptions.
+ /// </summary>
+ internal void ThrowIfExceptional(bool includeTaskCanceledExceptions)
+ {
+ Contract.Requires(IsCompleted, "ThrowIfExceptional(): Expected IsCompleted == true");
+
+ Exception exception = GetExceptions(includeTaskCanceledExceptions);
+ if (exception != null)
+ {
+ UpdateExceptionObservedStatus();
+ throw exception;
+ }
+ }
+
+ /// <summary>
+ /// Checks whether this is an attached task, and whether we are being called by the parent task.
+ /// And sets the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag based on that.
+ ///
+ /// This is meant to be used internally when throwing an exception, and when WaitAll is gathering
+ /// exceptions for tasks it waited on. If this flag gets set, the implicit wait on children
+ /// will skip exceptions to prevent duplication.
+ ///
+ /// This should only be called when this task has completed with an exception
+ ///
+ /// </summary>
+ internal void UpdateExceptionObservedStatus()
+ {
+ Task parent = m_contingentProperties?.m_parent;
+ if ((parent != null)
+ && ((Options & TaskCreationOptions.AttachedToParent) != 0)
+ && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
+ && Task.InternalCurrent == parent)
+ {
+ m_stateFlags |= TASK_STATE_EXCEPTIONOBSERVEDBYPARENT;
+ }
+ }
+
+ /// <summary>
+ /// Checks whether the TASK_STATE_EXCEPTIONOBSERVEDBYPARENT status flag is set,
+ /// This will only be used by the implicit wait to prevent double throws
+ ///
+ /// </summary>
+ internal bool IsExceptionObservedByParent
+ {
+ get
+ {
+ return (m_stateFlags & TASK_STATE_EXCEPTIONOBSERVEDBYPARENT) != 0;
+ }
+ }
+
+ /// <summary>
+ /// Checks whether the body was ever invoked. Used by task scheduler code to verify custom schedulers actually ran the task.
+ /// </summary>
+ internal bool IsDelegateInvoked
+ {
+ get
+ {
+ return (m_stateFlags & TASK_STATE_DELEGATE_INVOKED) != 0;
+ }
+ }
+
+ /// <summary>
+ /// Signals completion of this particular task.
+ ///
+ /// The bUserDelegateExecuted parameter indicates whether this Finish() call comes following the
+ /// full execution of the user delegate.
+ ///
+ /// If bUserDelegateExecuted is false, it mean user delegate wasn't invoked at all (either due to
+ /// a cancellation request, or because this task is a promise style Task). In this case, the steps
+ /// involving child tasks (i.e. WaitForChildren) will be skipped.
+ ///
+ /// </summary>
+ internal void Finish(bool bUserDelegateExecuted)
+ {
+ if (!bUserDelegateExecuted)
+ {
+ // delegate didn't execute => no children. We can safely call the remaining finish stages
+ FinishStageTwo();
+ }
+ else
+ {
+ var props = Volatile.Read(ref m_contingentProperties);
+
+ if (props == null || // no contingent properties means no children, so it's safe to complete ourselves
+ (props.m_completionCountdown == 1 && !IsSelfReplicatingRoot) ||
+ // Count of 1 => either all children finished, or there were none. Safe to complete ourselves
+ // without paying the price of an Interlocked.Decrement.
+ // However we need to exclude self replicating root tasks from this optimization, because
+ // they can have children joining in, or finishing even after the root task delegate is done.
+ Interlocked.Decrement(ref props.m_completionCountdown) == 0) // Reaching this sub clause means there may be remaining active children,
+ // and we could be racing with one of them to call FinishStageTwo().
+ // So whoever does the final Interlocked.Dec is responsible to finish.
+ {
+ FinishStageTwo();
+ }
+ else
+ {
+ // Apparently some children still remain. It will be up to the last one to process the completion of this task on their own thread.
+ // We will now yield the thread back to ThreadPool. Mark our state appropriately before getting out.
+
+ // We have to use an atomic update for this and make sure not to overwrite a final state,
+ // because at this very moment the last child's thread may be concurrently completing us.
+ // Otherwise we risk overwriting the TASK_STATE_RAN_TO_COMPLETION, _CANCELED or _FAULTED bit which may have been set by that child task.
+ // Note that the concurrent update by the last child happening in FinishStageTwo could still wipe out the TASK_STATE_WAITING_ON_CHILDREN flag,
+ // but it is not critical to maintain, therefore we dont' need to intruduce a full atomic update into FinishStageTwo
+
+ AtomicStateUpdate(TASK_STATE_WAITING_ON_CHILDREN, TASK_STATE_FAULTED | TASK_STATE_CANCELED | TASK_STATE_RAN_TO_COMPLETION);
+ }
+
+ // Now is the time to prune exceptional children. We'll walk the list and removes the ones whose exceptions we might have observed after they threw.
+ // we use a local variable for exceptional children here because some other thread may be nulling out m_contingentProperties.m_exceptionalChildren
+ List<Task> exceptionalChildren = props != null ? props.m_exceptionalChildren : null;
+
+ if (exceptionalChildren != null)
+ {
+ lock (exceptionalChildren)
+ {
+ exceptionalChildren.RemoveAll(s_IsExceptionObservedByParentPredicate); // RemoveAll has better performance than doing it ourselves
+ }
+ }
+ }
+ }
+
+ // statically allocated delegate for the removeall expression in Finish()
+ private readonly static Predicate<Task> s_IsExceptionObservedByParentPredicate = new Predicate<Task>((t) => { return t.IsExceptionObservedByParent; });
+
+ /// <summary>
+ /// FinishStageTwo is to be executed as soon as we known there are no more children to complete.
+ /// It can happen i) either on the thread that originally executed this task (if no children were spawned, or they all completed by the time this task's delegate quit)
+ /// ii) or on the thread that executed the last child.
+ /// </summary>
+ internal void FinishStageTwo()
+ {
+ AddExceptionsFromChildren();
+
+ // At this point, the task is done executing and waiting for its children,
+ // we can transition our task to a completion state.
+ int completionState;
+ if (ExceptionRecorded)
+ {
+ completionState = TASK_STATE_FAULTED;
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Error);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ }
+ else if (IsCancellationRequested && IsCancellationAcknowledged)
+ {
+ // We transition into the TASK_STATE_CANCELED final state if the task's CT was signalled for cancellation,
+ // and the user delegate acknowledged the cancellation request by throwing an OCE,
+ // and the task hasn't otherwise transitioned into faulted state. (TASK_STATE_FAULTED trumps TASK_STATE_CANCELED)
+ //
+ // If the task threw an OCE without cancellation being requestsed (while the CT not being in signaled state),
+ // then we regard it as a regular exception
+
+ completionState = TASK_STATE_CANCELED;
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Canceled);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ }
+ else
+ {
+ completionState = TASK_STATE_RAN_TO_COMPLETION;
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ }
+
+ // Use Interlocked.Exchange() to effect a memory fence, preventing
+ // any SetCompleted() (or later) instructions from sneak back before it.
+ Interlocked.Exchange(ref m_stateFlags, m_stateFlags | completionState);
+
+ // Set the completion event if it's been lazy allocated.
+ // And if we made a cancellation registration, it's now unnecessary.
+ var cp = Volatile.Read(ref m_contingentProperties);
+ if (cp != null)
+ {
+ cp.SetCompleted();
+ cp.DeregisterCancellationCallback();
+ }
+
+ // ready to run continuations and notify parent.
+ FinishStageThree();
+ }
+
+
+ /// <summary>
+ /// Final stage of the task completion code path. Notifies the parent (if any) that another of its children are done, and runs continuations.
+ /// This function is only separated out from FinishStageTwo because these two operations are also needed to be called from CancellationCleanupLogic()
+ /// </summary>
+ internal void FinishStageThree()
+ {
+ // Release the action so that holding this task object alive doesn't also
+ // hold alive the body of the task. We do this before notifying a parent,
+ // so that if notifying the parent completes the parent and causes
+ // its synchronous continuations to run, the GC can collect the state
+ // in the interim. And we do it before finishing continuations, because
+ // continuations hold onto the task, and therefore are keeping it alive.
+ m_action = null;
+
+ // Notify parent if this was an attached task
+ Task parent = m_contingentProperties?.m_parent;
+ if (parent != null
+ && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0)
+ && (((TaskCreationOptions)(m_stateFlags & OptionsMask)) & TaskCreationOptions.AttachedToParent) != 0)
+ {
+ parent.ProcessChildCompletion(this);
+ }
+
+ // Activate continuations (if any).
+ FinishContinuations();
+ }
+
+ /// <summary>
+ /// This is called by children of this task when they are completed.
+ /// </summary>
+ internal void ProcessChildCompletion(Task childTask)
+ {
+ Contract.Requires(childTask != null);
+ Contract.Requires(childTask.IsCompleted, "ProcessChildCompletion was called for an uncompleted task");
+
+ Contract.Assert(childTask.m_contingentProperties?.m_parent == this, "ProcessChildCompletion should only be called for a child of this task");
+
+ var props = Volatile.Read(ref m_contingentProperties);
+
+ // if the child threw and we haven't observed it we need to save it for future reference
+ if (childTask.IsFaulted && !childTask.IsExceptionObservedByParent)
+ {
+ // Lazily initialize the child exception list
+ if (props.m_exceptionalChildren == null)
+ {
+ Interlocked.CompareExchange(ref props.m_exceptionalChildren, new List<Task>(), null);
+ }
+
+ // In rare situations involving AppDomainUnload, it's possible (though unlikely) for FinishStageTwo() to be called
+ // multiple times for the same task. In that case, AddExceptionsFromChildren() could be nulling m_exceptionalChildren
+ // out at the same time that we're processing it, resulting in a NullReferenceException here. We'll protect
+ // ourselves by caching m_exceptionChildren in a local variable.
+ List<Task> tmp = props.m_exceptionalChildren;
+ if (tmp != null)
+ {
+ lock (tmp)
+ {
+ tmp.Add(childTask);
+ }
+ }
+
+ }
+
+ if (Interlocked.Decrement(ref props.m_completionCountdown) == 0)
+ {
+ // This call came from the final child to complete, and apparently we have previously given up this task's right to complete itself.
+ // So we need to invoke the final finish stage.
+
+ FinishStageTwo();
+ }
+ }
+
+ /// <summary>
+ /// This is to be called just before the task does its final state transition.
+ /// It traverses the list of exceptional children, and appends their aggregate exceptions into this one's exception list
+ /// </summary>
+ internal void AddExceptionsFromChildren()
+ {
+ // In rare occurences during AppDomainUnload() processing, it is possible for this method to be called
+ // simultaneously on the same task from two different contexts. This can result in m_exceptionalChildren
+ // being nulled out while it is being processed, which could lead to a NullReferenceException. To
+ // protect ourselves, we'll cache m_exceptionalChildren in a local variable.
+ var props = Volatile.Read(ref m_contingentProperties);
+ List<Task> exceptionalChildren = props?.m_exceptionalChildren;
+
+ if (exceptionalChildren != null)
+ {
+ // This lock is necessary because even though AddExceptionsFromChildren is last to execute, it may still
+ // be racing with the code segment at the bottom of Finish() that prunes the exceptional child array.
+ lock (exceptionalChildren)
+ {
+ foreach (Task task in exceptionalChildren)
+ {
+ // Ensure any exceptions thrown by children are added to the parent.
+ // In doing this, we are implicitly marking children as being "handled".
+ Contract.Assert(task.IsCompleted, "Expected all tasks in list to be completed");
+ if (task.IsFaulted && !task.IsExceptionObservedByParent)
+ {
+ TaskExceptionHolder exceptionHolder = Volatile.Read(ref task.m_contingentProperties).m_exceptionsHolder;
+ Contract.Assert(exceptionHolder != null);
+
+ // No locking necessary since child task is finished adding exceptions
+ // and concurrent CreateExceptionObject() calls do not constitute
+ // a concurrency hazard.
+ AddException(exceptionHolder.CreateExceptionObject(false, null));
+ }
+ }
+ }
+
+ // Reduce memory pressure by getting rid of the array
+ props.m_exceptionalChildren = null;
+ }
+ }
+
+ /// <summary>
+ /// Special purpose Finish() entry point to be used when the task delegate throws a ThreadAbortedException
+ /// This makes a note in the state flags so that we avoid any costly synchronous operations in the finish codepath
+ /// such as inlined continuations
+ /// </summary>
+ /// <param name="bTAEAddedToExceptionHolder">
+ /// Indicates whether the ThreadAbortException was added to this task's exception holder.
+ /// This should always be true except for the case of non-root self replicating task copies.
+ /// </param>
+ /// <param name="delegateRan">Whether the delegate was executed.</param>
+ internal void FinishThreadAbortedTask(bool bTAEAddedToExceptionHolder, bool delegateRan)
+ {
+ Contract.Assert(!bTAEAddedToExceptionHolder || m_contingentProperties?.m_exceptionsHolder != null,
+ "FinishThreadAbortedTask() called on a task whose exception holder wasn't initialized");
+
+ // this will only be false for non-root self replicating task copies, because all of their exceptions go to the root task.
+ if (bTAEAddedToExceptionHolder)
+ m_contingentProperties.m_exceptionsHolder.MarkAsHandled(false);
+
+ // If this method has already been called for this task, or if this task has already completed, then
+ // return before actually calling Finish().
+ if (!AtomicStateUpdate(TASK_STATE_THREAD_WAS_ABORTED,
+ TASK_STATE_THREAD_WAS_ABORTED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
+ {
+ return;
+ }
+
+ Finish(delegateRan);
+
+ }
+
+
+ /// <summary>
+ /// Executes the task. This method will only be called once, and handles bookeeping associated with
+ /// self-replicating tasks, in addition to performing necessary exception marshaling.
+ /// </summary>
+ private void Execute()
+ {
+ if (IsSelfReplicatingRoot)
+ {
+ ExecuteSelfReplicating(this);
+ }
+ else
+ {
+ try
+ {
+ InnerInvoke();
+ }
+ catch (ThreadAbortException tae)
+ {
+ // Don't record the TAE or call FinishThreadAbortedTask for a child replica task --
+ // it's already been done downstream.
+ if (!IsChildReplica)
+ {
+ // Record this exception in the task's exception list
+ HandleException(tae);
+
+ // This is a ThreadAbortException and it will be rethrown from this catch clause, causing us to
+ // skip the regular Finish codepath. In order not to leave the task unfinished, we now call
+ // FinishThreadAbortedTask here.
+ FinishThreadAbortedTask(true, true);
+ }
+ }
+ catch (Exception exn)
+ {
+ // Record this exception in the task's exception list
+ HandleException(exn);
+ }
+ }
+ }
+
+ // Allows (internal) deriving classes to support limited replication.
+ // (By default, replication is basically unlimited).
+ internal virtual bool ShouldReplicate()
+ {
+ return true;
+ }
+
+ // Allows (internal) deriving classes to instantiate the task replica as a Task super class of their choice
+ // (By default, we create a regular Task instance)
+ internal virtual Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
+ TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
+ {
+ return new Task(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken),
+ creationOptionsForReplica, internalOptionsForReplica, parentTask.ExecutingTaskScheduler);
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
+ internal virtual Object SavedStateForNextReplica
+ {
+ get { return null; }
+
+ set { /*do nothing*/ }
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
+ internal virtual Object SavedStateFromPreviousReplica
+ {
+ get { return null; }
+
+ set { /*do nothing*/ }
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
+ // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
+ internal virtual Task HandedOverChildReplica
+ {
+ get { return null; }
+
+ set { /* do nothing*/ }
+ }
+
+ private static void ExecuteSelfReplicating(Task root)
+ {
+ TaskCreationOptions creationOptionsForReplicas = root.CreationOptions | TaskCreationOptions.AttachedToParent;
+ InternalTaskOptions internalOptionsForReplicas =
+ InternalTaskOptions.ChildReplica | // child replica flag disables self replication for the replicas themselves.
+ InternalTaskOptions.SelfReplicating | // we still want to identify this as part of a self replicating group
+ InternalTaskOptions.QueuedByRuntime; // we queue and cancel these tasks internally, so don't allow CT registration to take place
+
+
+ // Important Note: The child replicas we launch from here will be attached the root replica (by virtue of the root.CreateReplicaTask call)
+ // because we need the root task to receive all their exceptions, and to block until all of them return
+
+
+ // This variable is captured in a closure and shared among all replicas.
+ bool replicasAreQuitting = false;
+
+ // Set up a delegate that will form the body of the root and all recursively created replicas.
+ Action<object> taskReplicaDelegate = null;
+ taskReplicaDelegate = delegate
+ {
+ Task currentTask = Task.InternalCurrent;
+
+
+ // Check if a child task has been handed over by a prematurely quiting replica that we might be a replacement for.
+ Task childTask = currentTask.HandedOverChildReplica;
+
+ if (childTask == null)
+ {
+ // Apparently we are not a replacement task. This means we need to queue up a child task for replication to progress
+
+ // Down-counts a counter in the root task.
+ if (!root.ShouldReplicate()) return;
+
+ // If any of the replicas have quit, we will do so ourselves.
+ if (Volatile.Read(ref replicasAreQuitting))
+ {
+ return;
+ }
+
+ // Propagate a copy of the context from the root task. It may be null if flow was suppressed.
+ ExecutionContext creatorContext = root.CapturedContext;
+
+
+ childTask = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
+ creationOptionsForReplicas, internalOptionsForReplicas);
+
+ childTask.CapturedContext = CopyExecutionContext(creatorContext);
+
+ childTask.ScheduleAndStart(false);
+ }
+
+
+
+ // Finally invoke the meat of the task.
+ // Note that we are directly calling root.InnerInvoke() even though we are currently be in the action delegate of a child replica
+ // This is because the actual work was passed down in that delegate, and the action delegate of the child replica simply contains this
+ // replication control logic.
+ try
+ {
+ // passing in currentTask only so that the parallel debugger can find it
+ root.InnerInvokeWithArg(currentTask);
+ }
+ catch (Exception exn)
+ {
+ // Record this exception in the root task's exception list
+ root.HandleException(exn);
+
+ if (exn is ThreadAbortException)
+ {
+ // If this is a ThreadAbortException it will escape this catch clause, causing us to skip the regular Finish codepath
+ // In order not to leave the task unfinished, we now call FinishThreadAbortedTask here
+ currentTask.FinishThreadAbortedTask(false, true);
+ }
+ }
+
+ Object savedState = currentTask.SavedStateForNextReplica;
+
+ // check for premature exit
+ if (savedState != null)
+ {
+ // the replica decided to exit early
+ // we need to queue up a replacement, attach the saved state, and yield the thread right away
+
+ Task replacementReplica = root.CreateReplicaTask(taskReplicaDelegate, root.m_stateObject, root, root.ExecutingTaskScheduler,
+ creationOptionsForReplicas, internalOptionsForReplicas);
+
+ // Propagate a copy of the context from the root task to the replacement task
+ ExecutionContext creatorContext = root.CapturedContext;
+ replacementReplica.CapturedContext = CopyExecutionContext(creatorContext);
+
+ replacementReplica.HandedOverChildReplica = childTask;
+ replacementReplica.SavedStateFromPreviousReplica = savedState;
+
+ replacementReplica.ScheduleAndStart(false);
+ }
+ else
+ {
+ // The replica finished normally, which means it can't find more work to grab.
+ // Time to mark replicas quitting
+
+ replicasAreQuitting = true;
+
+ // InternalCancel() could conceivably throw in the underlying scheduler's TryDequeue() method.
+ // If it does, then make sure that we record it.
+ try
+ {
+ childTask.InternalCancel(true);
+ }
+ catch (Exception e)
+ {
+ // Apparently TryDequeue threw an exception. Before propagating that exception, InternalCancel should have
+ // attempted an atomic state transition and a call to CancellationCleanupLogic() on this task. So we know
+ // the task was properly cleaned up if it was possible.
+ //
+ // Now all we need to do is to Record the exception in the root task.
+
+ root.HandleException(e);
+ }
+
+ // No specific action needed if the child could not be canceled
+ // because we attached it to the root task, which should therefore be receiving any exceptions from the child,
+ // and root.wait will not return before this child finishes anyway.
+
+ }
+ };
+
+ //
+ // Now we execute as the root task
+ //
+ taskReplicaDelegate(null);
+ }
+
+ /// <summary>
+ /// IThreadPoolWorkItem override, which is the entry function for this task when the TP scheduler decides to run it.
+ ///
+ /// </summary>
+ [SecurityCritical]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+ ExecuteEntry(false);
+ }
+
+ /// <summary>
+ /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem. This may occur
+ /// before Task would otherwise be able to observe it.
+ /// </summary>
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
+ {
+ // If the task has marked itself as Completed, then it either a) already observed this exception (so we shouldn't handle it here)
+ // or b) completed before the exception ocurred (in which case it shouldn't count against this Task).
+ if (!IsCompleted)
+ {
+ HandleException(tae);
+ FinishThreadAbortedTask(true, false);
+ }
+ }
+
+ /// <summary>
+ /// Outermost entry function to execute this task. Handles all aspects of executing a task on the caller thread.
+ /// Currently this is called by IThreadPoolWorkItem.ExecuteWorkItem(), and TaskManager.TryExecuteInline.
+ ///
+ /// </summary>
+ /// <param name="bPreventDoubleExecution"> Performs atomic updates to prevent double execution. Should only be set to true
+ /// in codepaths servicing user provided TaskSchedulers. The ConcRT or ThreadPool schedulers don't need this. </param>
+ [SecuritySafeCritical]
+ internal bool ExecuteEntry(bool bPreventDoubleExecution)
+ {
+ if (bPreventDoubleExecution || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0))
+ {
+ int previousState = 0;
+
+ // Do atomic state transition from queued to invoked. If we observe a task that's already invoked,
+ // we will return false so that TaskScheduler.ExecuteTask can throw an exception back to the custom scheduler.
+ // However we don't want this exception to be throw if the task was already canceled, because it's a
+ // legitimate scenario for custom schedulers to dequeue a task and mark it as canceled (example: throttling scheduler)
+ if (!AtomicStateUpdate(TASK_STATE_DELEGATE_INVOKED,
+ TASK_STATE_DELEGATE_INVOKED | TASK_STATE_COMPLETED_MASK,
+ ref previousState) && (previousState & TASK_STATE_CANCELED) == 0)
+ {
+ // This task has already been invoked. Don't invoke it again.
+ return false;
+ }
+ }
+ else
+ {
+ // Remember that we started running the task delegate.
+ m_stateFlags |= TASK_STATE_DELEGATE_INVOKED;
+ }
+
+ if (!IsCancellationRequested && !IsCanceled)
+ {
+ ExecuteWithThreadLocal(ref t_currentTask);
+ }
+ else if (!IsCanceled)
+ {
+ int prevState = Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);
+ if ((prevState & TASK_STATE_CANCELED) == 0)
+ {
+ CancellationCleanupLogic();
+ }
+ }
+
+ return true;
+ }
+
+ // A trick so we can refer to the TLS slot with a byref.
+ [SecurityCritical]
+ private void ExecuteWithThreadLocal(ref Task currentTaskSlot)
+ {
+ // Remember the current task so we can restore it after running, and then
+ Task previousTask = currentTaskSlot;
+
+ // ETW event for Task Started
+ var etwLog = TplEtwProvider.Log;
+ Guid savedActivityID = new Guid();
+ bool etwIsEnabled = etwLog.IsEnabled();
+ if (etwIsEnabled)
+ {
+ if (etwLog.TasksSetActivityIds)
+ EventSource.SetCurrentThreadActivityId(TplEtwProvider.CreateGuidForTaskID(this.Id), out savedActivityID);
+ // previousTask holds the actual "current task" we want to report in the event
+ if (previousTask != null)
+ etwLog.TaskStarted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id);
+ else
+ etwLog.TaskStarted(TaskScheduler.Current.Id, 0, this.Id);
+ }
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, this.Id, CausalitySynchronousWork.Execution);
+
+
+ try
+ {
+ // place the current task into TLS.
+ currentTaskSlot = this;
+
+ ExecutionContext ec = CapturedContext;
+ if (ec == null)
+ {
+ // No context, just run the task directly.
+ Execute();
+ }
+ else
+ {
+ if (IsSelfReplicatingRoot || IsChildReplica)
+ {
+ CapturedContext = CopyExecutionContext(ec);
+ }
+
+ // Run the task. We need a simple shim that converts the
+ // object back into a Task object, so that we can Execute it.
+
+ // Lazily initialize the callback delegate; benign race condition
+ var callback = s_ecCallback;
+ if (callback == null) s_ecCallback = callback = new ContextCallback(ExecutionContextCallback);
+ ExecutionContext.Run(ec, callback, this, true);
+ }
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.Execution);
+
+ Finish(true);
+ }
+ finally
+ {
+ currentTaskSlot = previousTask;
+
+ // ETW event for Task Completed
+ if (etwIsEnabled)
+ {
+ // previousTask holds the actual "current task" we want to report in the event
+ if (previousTask != null)
+ etwLog.TaskCompleted(previousTask.m_taskScheduler.Id, previousTask.Id, this.Id, IsFaulted);
+ else
+ etwLog.TaskCompleted(TaskScheduler.Current.Id, 0, this.Id, IsFaulted);
+
+ if (etwLog.TasksSetActivityIds)
+ EventSource.SetCurrentThreadActivityId(savedActivityID);
+ }
+ }
+ }
+
+ // Cached callback delegate that's lazily initialized due to ContextCallback being SecurityCritical
+ [SecurityCritical]
+ private static ContextCallback s_ecCallback;
+
+ [SecurityCritical]
+ private static void ExecutionContextCallback(object obj)
+ {
+ Task task = obj as Task;
+ Contract.Assert(task != null, "expected a task object");
+ task.Execute();
+ }
+
+
+ /// <summary>
+ /// The actual code which invokes the body of the task. This can be overriden in derived types.
+ /// </summary>
+ internal virtual void InnerInvoke()
+ {
+ // Invoke the delegate
+ Contract.Assert(m_action != null, "Null action in InnerInvoke()");
+ var action = m_action as Action;
+ if (action != null)
+ {
+ action();
+ return;
+ }
+ var actionWithState = m_action as Action<object>;
+ if (actionWithState != null)
+ {
+ actionWithState(m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in Task");
+ }
+
+ /// <summary>
+ /// Alternate InnerInvoke prototype to be called from ExecuteSelfReplicating() so that
+ /// the Parallel Debugger can discover the actual task being invoked.
+ /// Details: Here, InnerInvoke is actually being called on the rootTask object while we are actually executing the
+ /// childTask. And the debugger needs to discover the childTask, so we pass that down as an argument.
+ /// The NoOptimization and NoInlining flags ensure that the childTask pointer is retained, and that this
+ /// function appears on the callstack.
+ /// </summary>
+ /// <param name="childTask"></param>
+ [MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
+ internal void InnerInvokeWithArg(Task childTask)
+ {
+ InnerInvoke();
+ }
+
+ /// <summary>
+ /// Performs whatever handling is necessary for an unhandled exception. Normally
+ /// this just entails adding the exception to the holder object.
+ /// </summary>
+ /// <param name="unhandledException">The exception that went unhandled.</param>
+ private void HandleException(Exception unhandledException)
+ {
+ Contract.Requires(unhandledException != null);
+
+ OperationCanceledException exceptionAsOce = unhandledException as OperationCanceledException;
+ if (exceptionAsOce != null && IsCancellationRequested &&
+ m_contingentProperties.m_cancellationToken == exceptionAsOce.CancellationToken)
+ {
+ // All conditions are satisfied for us to go into canceled state in Finish().
+ // Mark the acknowledgement. The exception is also stored to enable it to be
+ // the exception propagated from an await.
+
+ SetCancellationAcknowledged();
+ AddException(exceptionAsOce, representsCancellation: true);
+ }
+ else
+ {
+ // Other exceptions, including any OCE from the task that doesn't match the tasks' own CT,
+ // or that gets thrown without the CT being set will be treated as an ordinary exception
+ // and added to the aggregate.
+
+ AddException(unhandledException);
+ }
+ }
+
+ #region Await Support
+ /// <summary>Gets an awaiter used to await this <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <returns>An awaiter instance.</returns>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public TaskAwaiter GetAwaiter()
+ {
+ return new TaskAwaiter(this);
+ }
+
+ /// <summary>Configures an awaiter used to await this <see cref="System.Threading.Tasks.Task"/>.</summary>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ /// <returns>An object used to await this task.</returns>
+ public ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext)
+ {
+ return new ConfiguredTaskAwaitable(this, continueOnCapturedContext);
+ }
+
+ /// <summary>
+ /// Sets a continuation onto the <see cref="System.Threading.Tasks.Task"/>.
+ /// The continuation is scheduled to run in the current synchronization context is one exists,
+ /// otherwise in the current task scheduler.
+ /// </summary>
+ /// <param name="continuationAction">The action to invoke when the <see cref="System.Threading.Tasks.Task"/> has completed.</param>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ /// <param name="flowExecutionContext">Whether to flow ExecutionContext across the await.</param>
+ /// <param name="stackMark">A stack crawl mark tied to execution context.</param>
+ /// <exception cref="System.InvalidOperationException">The awaiter was not properly initialized.</exception>
+ [SecurityCritical]
+ internal void SetContinuationForAwait(
+ Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext, ref StackCrawlMark stackMark)
+ {
+ Contract.Requires(continuationAction != null);
+
+ // Create the best AwaitTaskContinuation object given the request.
+ // If this remains null by the end of the function, we can use the
+ // continuationAction directly without wrapping it.
+ TaskContinuation tc = null;
+
+ // If the user wants the continuation to run on the current "context" if there is one...
+ if (continueOnCapturedContext)
+ {
+ // First try getting the current synchronization context.
+ // If the current context is really just the base SynchronizationContext type,
+ // which is intended to be equivalent to not having a current SynchronizationContext at all,
+ // then ignore it. This helps with performance by avoiding unnecessary posts and queueing
+ // of work items, but more so it ensures that if code happens to publish the default context
+ // as current, it won't prevent usage of a current task scheduler if there is one.
+ var syncCtx = SynchronizationContext.CurrentNoFlow;
+ if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
+ {
+ tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext, ref stackMark);
+ }
+ else
+ {
+ // If there was no SynchronizationContext, then try for the current scheduler.
+ // We only care about it if it's not the default.
+ var scheduler = TaskScheduler.InternalCurrent;
+ if (scheduler != null && scheduler != TaskScheduler.Default)
+ {
+ tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext, ref stackMark);
+ }
+ }
+ }
+
+ if (tc == null && flowExecutionContext)
+ {
+ // We're targeting the default scheduler, so we can use the faster path
+ // that assumes the default, and thus we don't need to store it. If we're flowing
+ // ExecutionContext, we need to capture it and wrap it in an AwaitTaskContinuation.
+ // Otherwise, we're targeting the default scheduler and we don't need to flow ExecutionContext, so
+ // we don't actually need a continuation object. We can just store/queue the action itself.
+ tc = new AwaitTaskContinuation(continuationAction, flowExecutionContext: true, stackMark: ref stackMark);
+ }
+
+ // Now register the continuation, and if we couldn't register it because the task is already completing,
+ // process the continuation directly (in which case make sure we schedule the continuation
+ // rather than inlining it, the latter of which could result in a rare but possible stack overflow).
+ if (tc != null)
+ {
+ if (!AddTaskContinuation(tc, addBeforeOthers: false))
+ tc.Run(this, bCanInlineContinuationTask: false);
+ }
+ else
+ {
+ Contract.Assert(!flowExecutionContext, "We already determined we're not required to flow context.");
+ if (!AddTaskContinuation(continuationAction, addBeforeOthers: false))
+ AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this);
+ }
+ }
+
+ /// <summary>Creates an awaitable that asynchronously yields back to the current context when awaited.</summary>
+ /// <returns>
+ /// A context that, when awaited, will asynchronously transition back into the current context at the
+ /// time of the await. If the current SynchronizationContext is non-null, that is treated as the current context.
+ /// Otherwise, TaskScheduler.Current is treated as the current context.
+ /// </returns>
+ public static YieldAwaitable Yield()
+ {
+ return new YieldAwaitable();
+ }
+ #endregion
+
+ /// <summary>
+ /// Waits for the <see cref="Task"/> to complete execution.
+ /// </summary>
+ /// <exception cref="T:System.AggregateException">
+ /// The <see cref="Task"/> was canceled -or- an exception was thrown during
+ /// the execution of the <see cref="Task"/>.
+ /// </exception>
+ public void Wait()
+ {
+#if DEBUG
+ bool waitResult =
+#endif
+ Wait(Timeout.Infinite, default(CancellationToken));
+
+#if DEBUG
+ Contract.Assert(waitResult, "expected wait to succeed");
+#endif
+ }
+
+ /// <summary>
+ /// Waits for the <see cref="Task"/> to complete execution.
+ /// </summary>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
+ /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// true if the <see cref="Task"/> completed execution within the allotted time; otherwise, false.
+ /// </returns>
+ /// <exception cref="T:System.AggregateException">
+ /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
+ /// cref="Task"/>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
+ /// infinite time-out -or- timeout is greater than
+ /// <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ public bool Wait(TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.timeout);
+ }
+
+ return Wait((int)totalMilliseconds, default(CancellationToken));
+ }
+
+
+ /// <summary>
+ /// Waits for the <see cref="Task"/> to complete execution.
+ /// </summary>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for the task to complete.
+ /// </param>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
+ /// cref="Task"/>.
+ /// </exception>
+ public void Wait(CancellationToken cancellationToken)
+ {
+ Wait(Timeout.Infinite, cancellationToken);
+ }
+
+
+ /// <summary>
+ /// Waits for the <see cref="Task"/> to complete execution.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.</param>
+ /// <returns>true if the <see cref="Task"/> completed execution within the allotted time; otherwise,
+ /// false.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
+ /// cref="Task"/>.
+ /// </exception>
+ public bool Wait(int millisecondsTimeout)
+ {
+ return Wait(millisecondsTimeout, default(CancellationToken));
+ }
+
+
+ /// <summary>
+ /// Waits for the <see cref="Task"/> to complete execution.
+ /// </summary>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for the task to complete.
+ /// </param>
+ /// <returns>
+ /// true if the <see cref="Task"/> completed execution within the allotted time; otherwise, false.
+ /// </returns>
+ /// <exception cref="T:System.AggregateException">
+ /// The <see cref="Task"/> was canceled -or- an exception was thrown during the execution of the <see
+ /// cref="Task"/>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ if (millisecondsTimeout < -1)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsTimeout);
+ }
+ Contract.EndContractBlock();
+
+ // Return immediately if we know that we've completed "clean" -- no exceptions, no cancellations
+ // and if no notification to the debugger is required
+ if (!IsWaitNotificationEnabledOrNotRanToCompletion) // (!DebuggerBitSet && RanToCompletion)
+ return true;
+
+ // Wait, and then return if we're still not done.
+ if (!InternalWait(millisecondsTimeout, cancellationToken))
+ return false;
+
+ if (IsWaitNotificationEnabledOrNotRanToCompletion) // avoid a few unnecessary volatile reads if we completed successfully
+ {
+ // Notify the debugger of the wait completion if it's requested such a notification
+ NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // If cancellation was requested and the task was canceled, throw an
+ // OperationCanceledException. This is prioritized ahead of the ThrowIfExceptional
+ // call to bring more determinism to cases where the same token is used to
+ // cancel the Wait and to cancel the Task. Otherwise, there's a race condition between
+ // whether the Wait or the Task observes the cancellation request first,
+ // and different exceptions result from the different cases.
+ if (IsCanceled) cancellationToken.ThrowIfCancellationRequested();
+
+ // If an exception occurred, or the task was cancelled, throw an exception.
+ ThrowIfExceptional(true);
+ }
+
+ Contract.Assert((m_stateFlags & TASK_STATE_FAULTED) == 0, "Task.Wait() completing when in Faulted state.");
+
+ return true;
+ }
+
+ // Convenience method that wraps any scheduler exception in a TaskSchedulerException
+ // and rethrows it.
+ private bool WrappedTryRunInline()
+ {
+ if (m_taskScheduler == null)
+ return false;
+
+ try
+ {
+ return m_taskScheduler.TryRunInline(this, true);
+ }
+ catch (Exception e)
+ {
+ // we 1) either received an unexpected exception originating from a custom scheduler, which needs to be wrapped in a TSE and thrown
+ // 2) or a a ThreadAbortException, which we need to skip here, because it would already have been handled in Task.Execute
+ if (!(e is ThreadAbortException))
+ {
+ TaskSchedulerException tse = new TaskSchedulerException(e);
+ throw tse;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
+
+ /// <summary>
+ /// The core wait function, which is only accesible internally. It's meant to be used in places in TPL code where
+ /// the current context is known or cached.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ internal bool InternalWait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ // ETW event for Task Wait Begin
+ var etwLog = TplEtwProvider.Log;
+ bool etwIsEnabled = etwLog.IsEnabled();
+ if (etwIsEnabled)
+ {
+ Task currentTask = Task.InternalCurrent;
+ etwLog.TaskWaitBegin(
+ (currentTask != null ? currentTask.m_taskScheduler.Id : TaskScheduler.Default.Id), (currentTask != null ? currentTask.Id : 0),
+ this.Id, TplEtwProvider.TaskWaitBehavior.Synchronous, 0, System.Threading.Thread.GetDomainID());
+ }
+
+ bool returnValue = IsCompleted;
+
+ // If the event hasn't already been set, we will wait.
+ if (!returnValue)
+ {
+ // Alert a listening debugger that we can't make forward progress unless it slips threads.
+ // We call NOCTD for two reasons:
+ // 1. If the task runs on another thread, then we'll be blocked here indefinitely.
+ // 2. If the task runs inline but takes some time to complete, it will suffer ThreadAbort with possible state corruption,
+ // and it is best to prevent this unless the user explicitly asks to view the value with thread-slipping enabled.
+ Debugger.NotifyOfCrossThreadDependency();
+
+ // We will attempt inline execution only if an infinite wait was requested
+ // Inline execution doesn't make sense for finite timeouts and if a cancellation token was specified
+ // because we don't know how long the task delegate will take.
+ if (millisecondsTimeout == Timeout.Infinite && !cancellationToken.CanBeCanceled &&
+ WrappedTryRunInline() && IsCompleted) // TryRunInline doesn't guarantee completion, as there may be unfinished children.
+ {
+ returnValue = true;
+ }
+ else
+ {
+ returnValue = SpinThenBlockingWait(millisecondsTimeout, cancellationToken);
+ }
+ }
+
+ Contract.Assert(IsCompleted || millisecondsTimeout != Timeout.Infinite);
+
+ // ETW event for Task Wait End
+ if (etwIsEnabled)
+ {
+ Task currentTask = Task.InternalCurrent;
+ if (currentTask != null)
+ {
+ etwLog.TaskWaitEnd(currentTask.m_taskScheduler.Id, currentTask.Id, this.Id);
+ }
+ else
+ {
+ etwLog.TaskWaitEnd(TaskScheduler.Default.Id, 0, this.Id);
+ }
+ // logically the continuation is empty so we immediately fire
+ etwLog.TaskWaitContinuationComplete(this.Id);
+ }
+
+ return returnValue;
+ }
+
+ // An MRES that gets set when Invoke is called. This replaces old logic that looked like this:
+ // ManualResetEventSlim mres = new ManualResetEventSlim(false, 0);
+ // Action<Task> completionAction = delegate {mres.Set();}
+ // AddCompletionAction(completionAction);
+ // with this:
+ // SetOnInvokeMres mres = new SetOnInvokeMres();
+ // AddCompletionAction(mres, addBeforeOthers: true);
+ // which saves a couple of allocations.
+ //
+ // Used in SpinThenBlockingWait (below), but could be seen as a general purpose mechanism.
+ private sealed class SetOnInvokeMres : ManualResetEventSlim, ITaskCompletionAction
+ {
+ internal SetOnInvokeMres() : base(false, 0) { }
+ public void Invoke(Task completingTask) { Set(); }
+ public bool InvokeMayRunArbitraryCode { get { return false; } }
+ }
+
+ /// <summary>
+ /// Waits for the task to complete, for a timeout to occur, or for cancellation to be requested.
+ /// The method first spins and then falls back to blocking on a new event.
+ /// </summary>
+ /// <param name="millisecondsTimeout">The timeout.</param>
+ /// <param name="cancellationToken">The token.</param>
+ /// <returns>true if the task is completed; otherwise, false.</returns>
+ private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ bool infiniteWait = millisecondsTimeout == Timeout.Infinite;
+ uint startTimeTicks = infiniteWait ? 0 : (uint)Environment.TickCount;
+ bool returnValue = SpinWait(millisecondsTimeout);
+ if (!returnValue)
+ {
+ var mres = new SetOnInvokeMres();
+ try
+ {
+ AddCompletionAction(mres, addBeforeOthers: true);
+ if (infiniteWait)
+ {
+ returnValue = mres.Wait(Timeout.Infinite, cancellationToken);
+ }
+ else
+ {
+ uint elapsedTimeTicks = ((uint)Environment.TickCount) - startTimeTicks;
+ if (elapsedTimeTicks < millisecondsTimeout)
+ {
+ returnValue = mres.Wait((int)(millisecondsTimeout - elapsedTimeTicks), cancellationToken);
+ }
+ }
+ }
+ finally
+ {
+ if (!IsCompleted) RemoveContinuation(mres);
+ // Don't Dispose of the MRES, because the continuation off of this task may
+ // still be running. This is ok, however, as we never access the MRES' WaitHandle,
+ // and thus no finalizable resources are actually allocated.
+ }
+ }
+ return returnValue;
+ }
+
+ /// <summary>
+ /// Spins briefly while checking IsCompleted
+ /// </summary>
+ /// <param name="millisecondsTimeout">The timeout.</param>
+ /// <returns>true if the task is completed; otherwise, false.</returns>
+ /// <exception cref="System.OperationCanceledException">The wait was canceled.</exception>
+ private bool SpinWait(int millisecondsTimeout)
+ {
+ if (IsCompleted) return true;
+
+ if (millisecondsTimeout == 0)
+ {
+ // For 0-timeouts, we just return immediately.
+ return false;
+ }
+
+ //This code is pretty similar to the custom spinning in MRES except there is no yieling after we exceed the spin count
+ int spinCount = PlatformHelper.IsSingleProcessor ? 1 : System.Threading.SpinWait.YIELD_THRESHOLD; //spin only once if we are running on a single CPU
+ for (int i = 0; i < spinCount; i++)
+ {
+ if (IsCompleted)
+ {
+ return true;
+ }
+
+ if (i == spinCount / 2)
+ {
+ Thread.Yield();
+ }
+ else
+ {
+ Thread.SpinWait(PlatformHelper.ProcessorCount * (4 << i));
+ }
+
+ }
+
+ return IsCompleted;
+ }
+
+ /// <summary>
+ /// Cancels the <see cref="Task"/>.
+ /// </summary>
+ /// <param name="bCancelNonExecutingOnly">
+ /// Indicates whether we should only cancel non-invoked tasks.
+ /// For the default scheduler this option will only be serviced through TryDequeue.
+ /// For custom schedulers we also attempt an atomic state transition.
+ /// </param>
+ /// <returns>true if the task was successfully canceled; otherwise, false.</returns>
+ [SecuritySafeCritical]
+ internal bool InternalCancel(bool bCancelNonExecutingOnly)
+ {
+ Contract.Requires((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) == 0, "Task.InternalCancel() did not expect promise-style task");
+
+ bool bPopSucceeded = false;
+ bool mustCleanup = false;
+
+ TaskSchedulerException tse = null;
+
+ // If started, and running in a task context, we can try to pop the chore.
+ if ((m_stateFlags & TASK_STATE_STARTED) != 0)
+ {
+ TaskScheduler ts = m_taskScheduler;
+
+ try
+ {
+ bPopSucceeded = (ts != null) && ts.TryDequeue(this);
+ }
+ catch (Exception e)
+ {
+ // TryDequeue threw. We don't know whether the task was properly dequeued or not. So we must let the rest of
+ // the cancellation logic run its course (record the request, attempt atomic state transition and do cleanup where appropriate)
+ // Here we will only record a TaskSchedulerException, which will later be thrown at function exit.
+
+ if (!(e is ThreadAbortException))
+ {
+ tse = new TaskSchedulerException(e);
+ }
+ }
+
+ bool bRequiresAtomicStartTransition = (ts != null && ts.RequiresAtomicStartTransition) || ((Options & (TaskCreationOptions)InternalTaskOptions.SelfReplicating) != 0);
+
+ if (!bPopSucceeded && bCancelNonExecutingOnly && bRequiresAtomicStartTransition)
+ {
+ // The caller requested cancellation of non-invoked tasks only, and TryDequeue was one way of doing it...
+ // Since that seems to have failed, we should now try an atomic state transition (from non-invoked state to canceled)
+ // An atomic transition here is only safe if we know we're on a custom task scheduler, which also forces a CAS on ExecuteEntry
+
+ // Even though this task can't have any children, we should be ready for handling any continuations that
+ // may be attached to it (although currently
+ // So we need to remeber whether we actually did the flip, so we can do clean up (finish continuations etc)
+ mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_DELEGATE_INVOKED | TASK_STATE_CANCELED);
+
+
+ // PS: This is slightly different from the regular cancellation codepath
+ // since we record the cancellation request *after* doing the state transition.
+ // However that shouldn't matter too much because the task was never invoked, thus can't have children
+ }
+
+ }
+
+ if (!bCancelNonExecutingOnly || bPopSucceeded || mustCleanup)
+ {
+ // Record the cancellation request.
+ RecordInternalCancellationRequest();
+
+ // Determine whether we need to clean up
+ // This will be the case
+ // 1) if we were able to pop, and we are able to update task state to TASK_STATE_CANCELED
+ // 2) if the task seems to be yet unstarted, and we can transition to
+ // TASK_STATE_CANCELED before anyone else can transition into _STARTED or _CANCELED or
+ // _RAN_TO_COMPLETION or _FAULTED
+ // Note that we do not check for TASK_STATE_COMPLETION_RESERVED. That only applies to promise-style
+ // tasks, and a promise-style task should not enter into this codepath.
+ if (bPopSucceeded)
+ {
+ // hitting this would mean something wrong with the AtomicStateUpdate above
+ Contract.Assert(!mustCleanup, "Possibly an invalid state transition call was made in InternalCancel()");
+
+ // Include TASK_STATE_DELEGATE_INVOKED in "illegal" bits to protect against the situation where
+ // TS.TryDequeue() returns true but the task is still left on the queue.
+ mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED, TASK_STATE_CANCELED | TASK_STATE_DELEGATE_INVOKED);
+ }
+ else if (!mustCleanup && (m_stateFlags & TASK_STATE_STARTED) == 0)
+ {
+ mustCleanup = AtomicStateUpdate(TASK_STATE_CANCELED,
+ TASK_STATE_CANCELED | TASK_STATE_STARTED | TASK_STATE_RAN_TO_COMPLETION |
+ TASK_STATE_FAULTED | TASK_STATE_DELEGATE_INVOKED);
+ }
+
+ // do the cleanup (i.e. set completion event and finish continuations)
+ if (mustCleanup)
+ {
+ CancellationCleanupLogic();
+ }
+ }
+
+ if (tse != null)
+ throw tse;
+ else
+ return (mustCleanup);
+ }
+
+ // Breaks out logic for recording a cancellation request
+ internal void RecordInternalCancellationRequest()
+ {
+ // Record the cancellation request.
+ EnsureContingentPropertiesInitialized().m_internalCancellationRequested = CANCELLATION_REQUESTED;
+ }
+
+ // Breaks out logic for recording a cancellation request
+ // This overload should only be used for promise tasks where no cancellation token
+ // was supplied when the task was created.
+ internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord)
+ {
+ RecordInternalCancellationRequest();
+
+ Contract.Assert((Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0, "Task.RecordInternalCancellationRequest(CancellationToken) only valid for promise-style task");
+ Contract.Assert(m_contingentProperties.m_cancellationToken == default(CancellationToken));
+
+ // Store the supplied cancellation token as this task's token.
+ // Waiting on this task will then result in an OperationCanceledException containing this token.
+ if (tokenToRecord != default(CancellationToken))
+ {
+ m_contingentProperties.m_cancellationToken = tokenToRecord;
+ }
+ }
+
+ // Breaks out logic for recording a cancellation request
+ // This overload should only be used for promise tasks where no cancellation token
+ // was supplied when the task was created.
+ internal void RecordInternalCancellationRequest(CancellationToken tokenToRecord, object cancellationException)
+ {
+ RecordInternalCancellationRequest(tokenToRecord);
+
+ // Store the supplied cancellation exception
+ if (cancellationException != null)
+ {
+#if DEBUG
+ var oce = cancellationException as OperationCanceledException;
+ if (oce == null)
+ {
+ var edi = cancellationException as ExceptionDispatchInfo;
+ Contract.Assert(edi != null, "Expected either an OCE or an EDI");
+ oce = edi.SourceException as OperationCanceledException;
+ Contract.Assert(oce != null, "Expected EDI to contain an OCE");
+ }
+ Contract.Assert(oce.CancellationToken == tokenToRecord,
+ "Expected OCE's token to match the provided token.");
+#endif
+ AddException(cancellationException, representsCancellation: true);
+ }
+ }
+
+ // ASSUMES THAT A SUCCESSFUL CANCELLATION HAS JUST OCCURRED ON THIS TASK!!!
+ // And this method should be called at most once per task.
+ internal void CancellationCleanupLogic()
+ {
+ Contract.Assert((m_stateFlags & (TASK_STATE_CANCELED | TASK_STATE_COMPLETION_RESERVED)) != 0, "Task.CancellationCleanupLogic(): Task not canceled or reserved.");
+ // I'd like to do this, but there is a small window for a race condition. If someone calls Wait() between InternalCancel() and
+ // here, that will set m_completionEvent, leading to a meaningless/harmless assertion.
+ //Contract.Assert((m_completionEvent == null) || !m_completionEvent.IsSet, "Task.CancellationCleanupLogic(): Completion event already set.");
+
+ // This may have been set already, but we need to make sure.
+ Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_CANCELED);
+
+ // Fire completion event if it has been lazily initialized
+ var cp = Volatile.Read(ref m_contingentProperties);
+ if (cp != null)
+ {
+ cp.SetCompleted();
+ cp.DeregisterCancellationCallback();
+ }
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Canceled);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+
+ // Notify parents, fire continuations, other cleanup.
+ FinishStageThree();
+ }
+
+
+ /// <summary>
+ /// Sets the task's cancellation acknowledged flag.
+ /// </summary>
+ private void SetCancellationAcknowledged()
+ {
+ Contract.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task");
+ Contract.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled");
+
+ m_stateFlags |= TASK_STATE_CANCELLATIONACKNOWLEDGED;
+ }
+
+
+ //
+ // Continuation passing functionality (aka ContinueWith)
+ //
+
+
+
+
+ /// <summary>
+ /// Runs all of the continuations, as appropriate.
+ /// </summary>
+ [SecuritySafeCritical] // for AwaitTaskContinuation.RunOrScheduleAction
+ internal void FinishContinuations()
+ {
+ // Atomically store the fact that this task is completing. From this point on, the adding of continuations will
+ // result in the continuations being run/launched directly rather than being added to the continuation list.
+ object continuationObject = Interlocked.Exchange(ref m_continuationObject, s_taskCompletionSentinel);
+ TplEtwProvider etw = TplEtwProvider.Log;
+ bool tplEtwProviderLoggingEnabled = etw.IsEnabled();
+ if (tplEtwProviderLoggingEnabled)
+ {
+ etw.RunningContinuation(Id, continuationObject);
+ }
+
+ // If continuationObject == null, then we don't have any continuations to process
+ if (continuationObject != null)
+ {
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceSynchronousWorkStart(CausalityTraceLevel.Required, this.Id, CausalitySynchronousWork.CompletionNotification);
+
+ // Skip synchronous execution of continuations if this task's thread was aborted
+ bool bCanInlineContinuations = !(((m_stateFlags & TASK_STATE_THREAD_WAS_ABORTED) != 0) ||
+ (Thread.CurrentThread.ThreadState == ThreadState.AbortRequested) ||
+ ((m_stateFlags & (int)TaskCreationOptions.RunContinuationsAsynchronously) != 0));
+
+ // Handle the single-Action case
+ Action singleAction = continuationObject as Action;
+ if (singleAction != null)
+ {
+ AwaitTaskContinuation.RunOrScheduleAction(singleAction, bCanInlineContinuations, ref t_currentTask);
+ LogFinishCompletionNotification();
+ return;
+ }
+
+ // Handle the single-ITaskCompletionAction case
+ ITaskCompletionAction singleTaskCompletionAction = continuationObject as ITaskCompletionAction;
+ if (singleTaskCompletionAction != null)
+ {
+ if (bCanInlineContinuations || !singleTaskCompletionAction.InvokeMayRunArbitraryCode)
+ {
+ singleTaskCompletionAction.Invoke(this);
+ }
+ else
+ {
+ ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(singleTaskCompletionAction, this), forceGlobal: false);
+ }
+ LogFinishCompletionNotification();
+ return;
+ }
+
+ // Handle the single-TaskContinuation case
+ TaskContinuation singleTaskContinuation = continuationObject as TaskContinuation;
+ if (singleTaskContinuation != null)
+ {
+ singleTaskContinuation.Run(this, bCanInlineContinuations);
+ LogFinishCompletionNotification();
+ return;
+ }
+
+ // Not a single; attempt to cast as list
+ List<object> continuations = continuationObject as List<object>;
+
+ if (continuations == null)
+ {
+ LogFinishCompletionNotification();
+ return; // Not a single or a list; just return
+ }
+
+ //
+ // Begin processing of continuation list
+ //
+
+ // Wait for any concurrent adds or removes to be retired
+ lock (continuations) { }
+ int continuationCount = continuations.Count;
+
+ // Fire the asynchronous continuations first ...
+ for (int i = 0; i < continuationCount; i++)
+ {
+ // Synchronous continuation tasks will have the ExecuteSynchronously option,
+ // and we're looking for asynchronous tasks...
+ var tc = continuations[i] as StandardTaskContinuation;
+ if (tc != null && (tc.m_options & TaskContinuationOptions.ExecuteSynchronously) == 0)
+ {
+ if (tplEtwProviderLoggingEnabled)
+ {
+ etw.RunningContinuationList(Id, i, tc);
+ }
+ continuations[i] = null; // so that we can skip this later
+ tc.Run(this, bCanInlineContinuations);
+ }
+ }
+
+ // ... and then fire the synchronous continuations (if there are any).
+ // This includes ITaskCompletionAction, AwaitTaskContinuations, and
+ // Action delegates, which are all by default implicitly synchronous.
+ for (int i = 0; i < continuationCount; i++)
+ {
+ object currentContinuation = continuations[i];
+ if (currentContinuation == null) continue;
+ continuations[i] = null; // to enable free'ing up memory earlier
+ if (tplEtwProviderLoggingEnabled)
+ {
+ etw.RunningContinuationList(Id, i, currentContinuation);
+ }
+
+ // If the continuation is an Action delegate, it came from an await continuation,
+ // and we should use AwaitTaskContinuation to run it.
+ Action ad = currentContinuation as Action;
+ if (ad != null)
+ {
+ AwaitTaskContinuation.RunOrScheduleAction(ad, bCanInlineContinuations, ref t_currentTask);
+ }
+ else
+ {
+ // If it's a TaskContinuation object of some kind, invoke it.
+ TaskContinuation tc = currentContinuation as TaskContinuation;
+ if (tc != null)
+ {
+ // We know that this is a synchronous continuation because the
+ // asynchronous ones have been weeded out
+ tc.Run(this, bCanInlineContinuations);
+ }
+ // Otherwise, it must be an ITaskCompletionAction, so invoke it.
+ else
+ {
+ Contract.Assert(currentContinuation is ITaskCompletionAction, "Expected continuation element to be Action, TaskContinuation, or ITaskContinuationAction");
+ var action = (ITaskCompletionAction)currentContinuation;
+
+ if (bCanInlineContinuations || !action.InvokeMayRunArbitraryCode)
+ {
+ action.Invoke(this);
+ }
+ else
+ {
+ ThreadPool.UnsafeQueueCustomWorkItem(new CompletionActionInvoker(action, this), forceGlobal: false);
+ }
+ }
+ }
+ }
+
+ LogFinishCompletionNotification();
+ }
+ }
+
+ private void LogFinishCompletionNotification()
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceSynchronousWorkCompletion(CausalityTraceLevel.Required, CausalitySynchronousWork.CompletionNotification);
+ }
+
+ #region Continuation methods
+
+ #region Action<Task> continuation
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task> continuationAction)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task> continuationAction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark parameter.
+ private Task ContinueWith(Action<Task> continuationAction, TaskScheduler scheduler,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ // Throw on continuation with null action
+ if (continuationAction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationAction);
+ }
+
+ // Throw on continuation with null TaskScheduler
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
+
+ Task continuationTask = new ContinuationTaskFromTask(
+ this, continuationAction, null,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+ #endregion
+
+ #region Action<Task, Object> continuation
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task, Object> continuationAction, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="cancellationToken"> The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task, Object> continuationAction, Object state, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark parameter.
+ private Task ContinueWith(Action<Task, Object> continuationAction, Object state, TaskScheduler scheduler,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ // Throw on continuation with null action
+ if (continuationAction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationAction);
+ }
+
+ // Throw on continuation with null TaskScheduler
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
+
+ Task continuationTask = new ContinuationTaskFromTask(
+ this, continuationAction, state,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+
+ #endregion
+
+ #region Func<Task, TResult> continuation
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken),
+ TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark parameter.
+ private Task<TResult> ContinueWith<TResult>(Func<Task, TResult> continuationFunction, TaskScheduler scheduler,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ // Throw on continuation with null function
+ if (continuationFunction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ }
+
+ // Throw on continuation with null task scheduler
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
+
+ Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
+ this, continuationFunction, null,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+ #endregion
+
+ #region Func<Task, Object, TResult> continuation
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken),
+ TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task"/> completes.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TResult}"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark parameter.
+ private Task<TResult> ContinueWith<TResult>(Func<Task, Object, TResult> continuationFunction, Object state, TaskScheduler scheduler,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ // Throw on continuation with null function
+ if (continuationFunction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ }
+
+ // Throw on continuation with null task scheduler
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ Contract.EndContractBlock();
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(continuationOptions, out creationOptions, out internalOptions);
+
+ Task<TResult> continuationTask = new ContinuationResultTaskFromTask<TResult>(
+ this, continuationFunction, state,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+ #endregion
+
+ /// <summary>
+ /// Converts TaskContinuationOptions to TaskCreationOptions, and also does
+ /// some validity checking along the way.
+ /// </summary>
+ /// <param name="continuationOptions">Incoming TaskContinuationOptions</param>
+ /// <param name="creationOptions">Outgoing TaskCreationOptions</param>
+ /// <param name="internalOptions">Outgoing InternalTaskOptions</param>
+ internal static void CreationOptionsFromContinuationOptions(
+ TaskContinuationOptions continuationOptions,
+ out TaskCreationOptions creationOptions,
+ out InternalTaskOptions internalOptions)
+ {
+ // This is used a couple of times below
+ TaskContinuationOptions NotOnAnything =
+ TaskContinuationOptions.NotOnCanceled |
+ TaskContinuationOptions.NotOnFaulted |
+ TaskContinuationOptions.NotOnRanToCompletion;
+
+ TaskContinuationOptions creationOptionsMask =
+ TaskContinuationOptions.PreferFairness |
+ TaskContinuationOptions.LongRunning |
+ TaskContinuationOptions.DenyChildAttach |
+ TaskContinuationOptions.HideScheduler |
+ TaskContinuationOptions.AttachedToParent|
+ TaskContinuationOptions.RunContinuationsAsynchronously;
+
+ // Check that LongRunning and ExecuteSynchronously are not specified together
+ TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning;
+ if ((continuationOptions & illegalMask) == illegalMask)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.continuationOptions, ExceptionResource.Task_ContinueWith_ESandLR);
+ }
+
+ // Check that no illegal options were specified
+ if ((continuationOptions &
+ ~(creationOptionsMask | NotOnAnything |
+ TaskContinuationOptions.LazyCancellation | TaskContinuationOptions.ExecuteSynchronously)) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.continuationOptions);
+ }
+
+ // Check that we didn't specify "not on anything"
+ if ((continuationOptions & NotOnAnything) == NotOnAnything)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.continuationOptions, ExceptionResource.Task_ContinueWith_NotOnAnything);
+ }
+
+ // This passes over all but LazyCancellation, which has no representation in TaskCreationOptions
+ creationOptions = (TaskCreationOptions)(continuationOptions & creationOptionsMask);
+
+ // internalOptions has at least ContinuationTask ...
+ internalOptions = InternalTaskOptions.ContinuationTask;
+
+ // ... and possibly LazyCancellation
+ if ((continuationOptions & TaskContinuationOptions.LazyCancellation) != 0)
+ internalOptions |= InternalTaskOptions.LazyCancellation;
+ }
+
+
+ /// <summary>
+ /// Registers the continuation and possibly runs it (if the task is already finished).
+ /// </summary>
+ /// <param name="continuationTask">The continuation task itself.</param>
+ /// <param name="scheduler">TaskScheduler with which to associate continuation task.</param>
+ /// <param name="options">Restrictions on when the continuation becomes active.</param>
+ internal void ContinueWithCore(Task continuationTask,
+ TaskScheduler scheduler,
+ CancellationToken cancellationToken,
+ TaskContinuationOptions options)
+ {
+ Contract.Requires(continuationTask != null, "Task.ContinueWithCore(): null continuationTask");
+ Contract.Requires(scheduler != null, "Task.ContinueWithCore(): null scheduler");
+ Contract.Requires(!continuationTask.IsCompleted, "Did not expect continuationTask to be completed");
+
+ // Create a TaskContinuation
+ TaskContinuation continuation = new StandardTaskContinuation(continuationTask, options, scheduler);
+
+ // If cancellationToken is cancellable, then assign it.
+ if (cancellationToken.CanBeCanceled)
+ {
+ if (IsCompleted || cancellationToken.IsCancellationRequested)
+ {
+ // If the antecedent has completed, then we will not be queuing up
+ // the continuation in the antecedent's continuation list. Likewise,
+ // if the cancellationToken has been canceled, continuationTask will
+ // be completed in the AssignCancellationToken call below, and there
+ // is no need to queue the continuation to the antecedent's continuation
+ // list. In either of these two cases, we will pass "null" for the antecedent,
+ // meaning "the cancellation callback should not attempt to remove the
+ // continuation from its antecedent's continuation list".
+ continuationTask.AssignCancellationToken(cancellationToken, null, null);
+ }
+ else
+ {
+ // The antecedent is not yet complete, so there is a pretty good chance
+ // that the continuation will be queued up in the antecedent. Assign the
+ // cancellation token with information about the antecedent, so that the
+ // continuation can be dequeued upon the signalling of the token.
+ //
+ // It's possible that the antecedent completes before the call to AddTaskContinuation,
+ // and that is a benign race condition. It just means that the cancellation will result in
+ // a futile search of the antecedent's continuation list.
+ continuationTask.AssignCancellationToken(cancellationToken, this, continuation);
+ }
+ }
+
+ // In the case of a pre-canceled token, continuationTask will have been completed
+ // in a Canceled state by now. If such is the case, there is no need to go through
+ // the motions of queuing up the continuation for eventual execution.
+ if (!continuationTask.IsCompleted)
+ {
+ // We need additional correlation produced here to ensure that at least the continuation
+ // code will be correlatable to the currrent activity that initiated "this" task:
+ // . when the antecendent ("this") is a promise we have very little control over where
+ // the code for the promise will run (e.g. it can be a task from a user provided
+ // TaskCompletionSource or from a classic Begin/End async operation); this user or
+ // system code will likely not have stamped an activity id on the thread, so there's
+ // generally no easy correlation that can be provided between the current activity
+ // and the promise. Also the continuation code may run practically on any thread.
+ // Since there may be no correlation between the current activity and the TCS's task
+ // activity, we ensure we at least create a correlation from the current activity to
+ // the continuation that runs when the promise completes.
+ if ((this.Options & (TaskCreationOptions)InternalTaskOptions.PromiseTask) != 0 &&
+ !(this is ITaskCompletionAction))
+ {
+ var etwLog = TplEtwProvider.Log;
+ if (etwLog.IsEnabled())
+ {
+ etwLog.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, Task.CurrentId ?? 0, continuationTask.Id);
+ }
+ }
+
+ // Attempt to enqueue the continuation
+ bool continuationQueued = AddTaskContinuation(continuation, addBeforeOthers: false);
+
+ // If the continuation was not queued (because the task completed), then run it now.
+ if (!continuationQueued) continuation.Run(this, bCanInlineContinuationTask: true);
+ }
+ }
+ #endregion
+
+ // Adds a lightweight completion action to a task. This is similar to a continuation
+ // task except that it is stored as an action, and thus does not require the allocation/
+ // execution resources of a continuation task.
+ //
+ // Used internally by ContinueWhenAll() and ContinueWhenAny().
+ internal void AddCompletionAction(ITaskCompletionAction action)
+ {
+ AddCompletionAction(action, addBeforeOthers: false);
+ }
+
+ private void AddCompletionAction(ITaskCompletionAction action, bool addBeforeOthers)
+ {
+ if (!AddTaskContinuation(action, addBeforeOthers))
+ action.Invoke(this); // run the action directly if we failed to queue the continuation (i.e., the task completed)
+ }
+
+ // Support method for AddTaskContinuation that takes care of multi-continuation logic.
+ // Returns true if and only if the continuation was successfully queued.
+ // THIS METHOD ASSUMES THAT m_continuationObject IS NOT NULL. That case was taken
+ // care of in the calling method, AddTaskContinuation().
+ private bool AddTaskContinuationComplex(object tc, bool addBeforeOthers)
+ {
+ Contract.Requires(tc != null, "Expected non-null tc object in AddTaskContinuationComplex");
+
+ object oldValue = m_continuationObject;
+
+ // Logic for the case where we were previously storing a single continuation
+ if ((oldValue != s_taskCompletionSentinel) && (!(oldValue is List<object>)))
+ {
+ // Construct a new TaskContinuation list
+ List<object> newList = new List<object>();
+
+ // Add in the old single value
+ newList.Add(oldValue);
+
+ // Now CAS in the new list
+ Interlocked.CompareExchange(ref m_continuationObject, newList, oldValue);
+
+ // We might be racing against another thread converting the single into
+ // a list, or we might be racing against task completion, so resample "list"
+ // below.
+ }
+
+ // m_continuationObject is guaranteed at this point to be either a List or
+ // s_taskCompletionSentinel.
+ List<object> list = m_continuationObject as List<object>;
+ Contract.Assert((list != null) || (m_continuationObject == s_taskCompletionSentinel),
+ "Expected m_continuationObject to be list or sentinel");
+
+ // If list is null, it can only mean that s_taskCompletionSentinel has been exchanged
+ // into m_continuationObject. Thus, the task has completed and we should return false
+ // from this method, as we will not be queuing up the continuation.
+ if (list != null)
+ {
+ lock (list)
+ {
+ // It is possible for the task to complete right after we snap the copy of
+ // the list. If so, then fall through and return false without queuing the
+ // continuation.
+ if (m_continuationObject != s_taskCompletionSentinel)
+ {
+ // Before growing the list we remove possible null entries that are the
+ // result from RemoveContinuations()
+ if (list.Count == list.Capacity)
+ {
+ list.RemoveAll(s_IsTaskContinuationNullPredicate);
+ }
+
+ if (addBeforeOthers)
+ list.Insert(0, tc);
+ else
+ list.Add(tc);
+
+ return true; // continuation successfully queued, so return true.
+ }
+ }
+ }
+
+ // We didn't succeed in queuing the continuation, so return false.
+ return false;
+ }
+
+ // Record a continuation task or action.
+ // Return true if and only if we successfully queued a continuation.
+ private bool AddTaskContinuation(object tc, bool addBeforeOthers)
+ {
+ Contract.Requires(tc != null);
+
+ // Make sure that, if someone calls ContinueWith() right after waiting for the predecessor to complete,
+ // we don't queue up a continuation.
+ if (IsCompleted) return false;
+
+ // Try to just jam tc into m_continuationObject
+ if ((m_continuationObject != null) || (Interlocked.CompareExchange(ref m_continuationObject, tc, null) != null))
+ {
+ // If we get here, it means that we failed to CAS tc into m_continuationObject.
+ // Therefore, we must go the more complicated route.
+ return AddTaskContinuationComplex(tc, addBeforeOthers);
+ }
+ else return true;
+ }
+
+ // Removes a continuation task from m_continuations
+ internal void RemoveContinuation(object continuationObject) // could be TaskContinuation or Action<Task>
+ {
+ // We need to snap a local reference to m_continuations since reading a volatile object is more costly.
+ // Also to prevent the value to be changed as result of a race condition with another method.
+ object continuationsLocalRef = m_continuationObject;
+
+ // Task is completed. Nothing to do here.
+ if (continuationsLocalRef == s_taskCompletionSentinel) return;
+
+ List<object> continuationsLocalListRef = continuationsLocalRef as List<object>;
+
+ if (continuationsLocalListRef == null)
+ {
+ // This is not a list. If we have a single object (the one we want to remove) we try to replace it with an empty list.
+ // Note we cannot go back to a null state, since it will mess up the AddTaskContinuation logic.
+ if (Interlocked.CompareExchange(ref m_continuationObject, new List<object>(), continuationObject) != continuationObject)
+ {
+ // If we fail it means that either AddContinuationComplex won the race condition and m_continuationObject is now a List
+ // that contains the element we want to remove. Or FinishContinuations set the s_taskCompletionSentinel.
+ // So we should try to get a list one more time
+ continuationsLocalListRef = m_continuationObject as List<object>;
+ }
+ else
+ {
+ // Exchange was successful so we can skip the last comparison
+ return;
+ }
+ }
+
+ // if continuationsLocalRef == null it means s_taskCompletionSentinel has been set already and there is nothing else to do.
+ if (continuationsLocalListRef != null)
+ {
+ lock (continuationsLocalListRef)
+ {
+ // There is a small chance that this task completed since we took a local snapshot into
+ // continuationsLocalRef. In that case, just return; we don't want to be manipulating the
+ // continuation list as it is being processed.
+ if (m_continuationObject == s_taskCompletionSentinel) return;
+
+ // Find continuationObject in the continuation list
+ int index = continuationsLocalListRef.IndexOf(continuationObject);
+
+ if (index != -1)
+ {
+ // null out that TaskContinuation entry, which will be interpreted as "to be cleaned up"
+ continuationsLocalListRef[index] = null;
+
+ }
+ }
+ }
+ }
+
+ // statically allocated delegate for the RemoveAll expression in RemoveContinuations() and AddContinuationComplex()
+ private readonly static Predicate<object> s_IsTaskContinuationNullPredicate =
+ new Predicate<object>((tc) => { return (tc == null); });
+
+
+ //
+ // Wait methods
+ //
+
+ /// <summary>
+ /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
+ /// the execution of at least one of the <see cref="Task"/> instances.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static void WaitAll(params Task[] tasks)
+ {
+#if DEBUG
+ bool waitResult =
+#endif
+ WaitAll(tasks, Timeout.Infinite);
+
+#if DEBUG
+ Contract.Assert(waitResult, "expected wait to succeed");
+#endif
+ }
+
+ /// <summary>
+ /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <returns>
+ /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
+ /// otherwise, false.
+ /// </returns>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
+ /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
+ /// the execution of at least one of the <see cref="Task"/> instances.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
+ /// infinite time-out -or- timeout is greater than
+ /// <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static bool WaitAll(Task[] tasks, TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.timeout);
+ }
+
+ return WaitAll(tasks, (int)totalMilliseconds);
+
+ }
+
+ /// <summary>
+ /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <returns>
+ /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
+ /// otherwise, false.
+ /// </returns>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.</param>
+ /// <param name="tasks">An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
+ /// the execution of at least one of the <see cref="Task"/> instances.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static bool WaitAll(Task[] tasks, int millisecondsTimeout)
+ {
+ return WaitAll(tasks, millisecondsTimeout, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <returns>
+ /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
+ /// otherwise, false.
+ /// </returns>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
+ /// the execution of at least one of the <see cref="Task"/> instances.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static void WaitAll(Task[] tasks, CancellationToken cancellationToken)
+ {
+ WaitAll(tasks, Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Waits for all of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <returns>
+ /// true if all of the <see cref="Task"/> instances completed execution within the allotted time;
+ /// otherwise, false.
+ /// </returns>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for the tasks to complete.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.AggregateException">
+ /// At least one of the <see cref="Task"/> instances was canceled -or- an exception was thrown during
+ /// the execution of at least one of the <see cref="Task"/> instances.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static bool WaitAll(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ if (tasks == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ }
+ if (millisecondsTimeout < -1)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsTimeout);
+ }
+ Contract.EndContractBlock();
+
+ cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
+
+ //
+ // In this WaitAll() implementation we have 2 alternate code paths for a task to be handled:
+ // CODEPATH1: skip an already completed task, CODEPATH2: actually wait on tasks
+ // We make sure that the exception behavior of Task.Wait() is replicated the same for tasks handled in either of these codepaths
+ //
+
+ List<Exception> exceptions = null;
+ List<Task> waitedOnTaskList = null;
+ List<Task> notificationTasks = null;
+
+ // If any of the waited-upon tasks end as Faulted or Canceled, set these to true.
+ bool exceptionSeen = false, cancellationSeen = false;
+
+ bool returnValue = true;
+
+ // Collects incomplete tasks in "waitedOnTaskList"
+ for (int i = tasks.Length - 1; i >= 0; i--)
+ {
+ Task task = tasks[i];
+
+ if (task == null)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
+ }
+
+ bool taskIsCompleted = task.IsCompleted;
+ if (!taskIsCompleted)
+ {
+ // try inlining the task only if we have an infinite timeout and an empty cancellation token
+ if (millisecondsTimeout != Timeout.Infinite || cancellationToken.CanBeCanceled)
+ {
+ // We either didn't attempt inline execution because we had a non-infinite timeout or we had a cancellable token.
+ // In all cases we need to do a full wait on the task (=> add its event into the list.)
+ AddToList(task, ref waitedOnTaskList, initSize: tasks.Length);
+ }
+ else
+ {
+ // We are eligible for inlining. If it doesn't work, we'll do a full wait.
+ taskIsCompleted = task.WrappedTryRunInline() && task.IsCompleted; // A successful TryRunInline doesn't guarantee completion
+ if (!taskIsCompleted) AddToList(task, ref waitedOnTaskList, initSize: tasks.Length);
+ }
+ }
+
+ if (taskIsCompleted)
+ {
+ if (task.IsFaulted) exceptionSeen = true;
+ else if (task.IsCanceled) cancellationSeen = true;
+ if (task.IsWaitNotificationEnabled) AddToList(task, ref notificationTasks, initSize: 1);
+ }
+ }
+
+ if (waitedOnTaskList != null)
+ {
+ // Block waiting for the tasks to complete.
+ returnValue = WaitAllBlockingCore(waitedOnTaskList, millisecondsTimeout, cancellationToken);
+
+ // If the wait didn't time out, ensure exceptions are propagated, and if a debugger is
+ // attached and one of these tasks requires it, that we notify the debugger of a wait completion.
+ if (returnValue)
+ {
+ // Add any exceptions for this task to the collection, and if it's wait
+ // notification bit is set, store it to operate on at the end.
+ foreach (var task in waitedOnTaskList)
+ {
+ if (task.IsFaulted) exceptionSeen = true;
+ else if (task.IsCanceled) cancellationSeen = true;
+ if (task.IsWaitNotificationEnabled) AddToList(task, ref notificationTasks, initSize: 1);
+ }
+ }
+
+ // We need to prevent the tasks array from being GC'ed until we come out of the wait.
+ // This is necessary so that the Parallel Debugger can traverse it during the long wait and
+ // deduce waiter/waitee relationships
+ GC.KeepAlive(tasks);
+ }
+
+ // Now that we're done and about to exit, if the wait completed and if we have
+ // any tasks with a notification bit set, signal the debugger if any requires it.
+ if (returnValue && notificationTasks != null)
+ {
+ // Loop through each task tha that had its bit set, and notify the debugger
+ // about the first one that requires it. The debugger will reset the bit
+ // for any tasks we don't notify of as soon as we break, so we only need to notify
+ // for one.
+ foreach (var task in notificationTasks)
+ {
+ if (task.NotifyDebuggerOfWaitCompletionIfNecessary()) break;
+ }
+ }
+
+ // If one or more threw exceptions, aggregate and throw them.
+ if (returnValue && (exceptionSeen || cancellationSeen))
+ {
+ // If the WaitAll was canceled and tasks were canceled but not faulted,
+ // prioritize throwing an OCE for canceling the WaitAll over throwing an
+ // AggregateException for all of the canceled Tasks. This helps
+ // to bring determinism to an otherwise non-determistic case of using
+ // the same token to cancel both the WaitAll and the Tasks.
+ if (!exceptionSeen) cancellationToken.ThrowIfCancellationRequested();
+
+ // Now gather up and throw all of the exceptions.
+ foreach (var task in tasks) AddExceptionsForCompletedTask(ref exceptions, task);
+ Contract.Assert(exceptions != null, "Should have seen at least one exception");
+ ThrowHelper.ThrowAggregateException(exceptions);
+ }
+
+ return returnValue;
+ }
+
+ /// <summary>Adds an element to the list, initializing the list if it's null.</summary>
+ /// <typeparam name="T">Specifies the type of data stored in the list.</typeparam>
+ /// <param name="item">The item to add.</param>
+ /// <param name="list">The list.</param>
+ /// <param name="initSize">The size to which to initialize the list if the list is null.</param>
+ private static void AddToList<T>(T item, ref List<T> list, int initSize)
+ {
+ if (list == null) list = new List<T>(initSize);
+ list.Add(item);
+ }
+
+ /// <summary>Performs a blocking WaitAll on the vetted list of tasks.</summary>
+ /// <param name="tasks">The tasks, which have already been checked and filtered for completion.</param>
+ /// <param name="millisecondsTimeout">The timeout.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>true if all of the tasks completed; otherwise, false.</returns>
+ private static bool WaitAllBlockingCore(List<Task> tasks, int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ Contract.Assert(tasks != null, "Expected a non-null list of tasks");
+ Contract.Assert(tasks.Count > 0, "Expected at least one task");
+
+ bool waitCompleted = false;
+ var mres = new SetOnCountdownMres(tasks.Count);
+ try
+ {
+ foreach (var task in tasks)
+ {
+ task.AddCompletionAction(mres, addBeforeOthers: true);
+ }
+ waitCompleted = mres.Wait(millisecondsTimeout, cancellationToken);
+ }
+ finally
+ {
+ if (!waitCompleted)
+ {
+ foreach (var task in tasks)
+ {
+ if (!task.IsCompleted) task.RemoveContinuation(mres);
+ }
+ }
+ // It's ok that we don't dispose of the MRES here, as we never
+ // access the MRES' WaitHandle, and thus no finalizable resources
+ // are actually created. We don't always just Dispose it because
+ // a continuation that's accessing the MRES could still be executing.
+ }
+ return waitCompleted;
+ }
+
+ // A ManualResetEventSlim that will get Set after Invoke is called count times.
+ // This allows us to replace this logic:
+ // var mres = new ManualResetEventSlim(tasks.Count);
+ // Action<Task> completionAction = delegate { if(Interlocked.Decrement(ref count) == 0) mres.Set(); };
+ // foreach(var task in tasks) task.AddCompletionAction(completionAction);
+ // with this logic:
+ // var mres = new SetOnCountdownMres(tasks.Count);
+ // foreach(var task in tasks) task.AddCompletionAction(mres);
+ // which saves a couple of allocations.
+ //
+ // Used in WaitAllBlockingCore (above).
+ private sealed class SetOnCountdownMres : ManualResetEventSlim, ITaskCompletionAction
+ {
+ private int _count;
+
+ internal SetOnCountdownMres(int count)
+ {
+ Contract.Assert(count > 0, "Expected count > 0");
+ _count = count;
+ }
+
+ public void Invoke(Task completingTask)
+ {
+ if (Interlocked.Decrement(ref _count) == 0) Set();
+ Contract.Assert(_count >= 0, "Count should never go below 0");
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return false; } }
+ }
+
+ /// <summary>
+ /// Internal WaitAll implementation which is meant to be used with small number of tasks,
+ /// optimized for Parallel.Invoke and other structured primitives.
+ /// </summary>
+ internal static void FastWaitAll(Task[] tasks)
+ {
+ Contract.Requires(tasks != null);
+
+ List<Exception> exceptions = null;
+
+ // Collects incomplete tasks in "waitedOnTaskList" and their cooperative events in "cooperativeEventList"
+ for (int i = tasks.Length - 1; i >= 0; i--)
+ {
+ if (!tasks[i].IsCompleted)
+ {
+ // Just attempting to inline here... result doesn't matter.
+ // We'll do a second pass to do actual wait on each task, and to aggregate their exceptions.
+ // If the task is inlined here, it will register as IsCompleted in the second pass
+ // and will just give us the exception.
+ tasks[i].WrappedTryRunInline();
+ }
+ }
+
+ // Wait on the tasks.
+ for (int i = tasks.Length - 1; i >= 0; i--)
+ {
+ var task = tasks[i];
+ task.SpinThenBlockingWait(Timeout.Infinite, default(CancellationToken));
+ AddExceptionsForCompletedTask(ref exceptions, task);
+
+ // Note that unlike other wait code paths, we do not check
+ // task.NotifyDebuggerOfWaitCompletionIfNecessary() here, because this method is currently
+ // only used from contexts where the tasks couldn't have that bit set, namely
+ // Parallel.Invoke. If that ever changes, such checks should be added here.
+ }
+
+ // If one or more threw exceptions, aggregate them.
+ if (exceptions != null)
+ {
+ ThrowHelper.ThrowAggregateException(exceptions);
+ }
+ }
+
+ /// <summary>
+ /// This internal function is only meant to be called by WaitAll()
+ /// If the completed task is canceled or it has other exceptions, here we will add those
+ /// into the passed in exception list (which will be lazily initialized here).
+ /// </summary>
+ internal static void AddExceptionsForCompletedTask(ref List<Exception> exceptions, Task t)
+ {
+ AggregateException ex = t.GetExceptions(true);
+ if (ex != null)
+ {
+ // make sure the task's exception observed status is set appropriately
+ // it's possible that WaitAll was called by the parent of an attached child,
+ // this will make sure it won't throw again in the implicit wait
+ t.UpdateExceptionObservedStatus();
+
+ if (exceptions == null)
+ {
+ exceptions = new List<Exception>(ex.InnerExceptions.Count);
+ }
+
+ exceptions.AddRange(ex.InnerExceptions);
+ }
+ }
+
+
+ /// <summary>
+ /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <returns>The index of the completed task in the <paramref name="tasks"/> array argument.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static int WaitAny(params Task[] tasks)
+ {
+ int waitResult = WaitAny(tasks, Timeout.Infinite);
+ Contract.Assert(tasks.Length == 0 || waitResult != -1, "expected wait to succeed");
+ return waitResult;
+ }
+
+ /// <summary>
+ /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="timeout">
+ /// A <see cref="System.TimeSpan"/> that represents the number of milliseconds to wait, or a <see
+ /// cref="System.TimeSpan"/> that represents -1 milliseconds to wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
+ /// timeout occurred.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="timeout"/> is a negative number other than -1 milliseconds, which represents an
+ /// infinite time-out -or- timeout is greater than
+ /// <see cref="System.Int32.MaxValue"/>.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static int WaitAny(Task[] tasks, TimeSpan timeout)
+ {
+ long totalMilliseconds = (long)timeout.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.timeout);
+ }
+
+ return WaitAny(tasks, (int)totalMilliseconds);
+ }
+
+ /// <summary>
+ /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for a task to complete.
+ /// </param>
+ /// <returns>
+ /// The index of the completed task in the <paramref name="tasks"/> array argument.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static int WaitAny(Task[] tasks, CancellationToken cancellationToken)
+ {
+ return WaitAny(tasks, Timeout.Infinite, cancellationToken);
+ }
+
+ /// <summary>
+ /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.
+ /// </param>
+ /// <returns>
+ /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
+ /// timeout occurred.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static int WaitAny(Task[] tasks, int millisecondsTimeout)
+ {
+ return WaitAny(tasks, millisecondsTimeout, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Waits for any of the provided <see cref="Task"/> objects to complete execution.
+ /// </summary>
+ /// <param name="tasks">
+ /// An array of <see cref="Task"/> instances on which to wait.
+ /// </param>
+ /// <param name="millisecondsTimeout">
+ /// The number of milliseconds to wait, or <see cref="System.Threading.Timeout.Infinite"/> (-1) to
+ /// wait indefinitely.
+ /// </param>
+ /// <param name="cancellationToken">
+ /// A <see cref="CancellationToken"/> to observe while waiting for a task to complete.
+ /// </param>
+ /// <returns>
+ /// The index of the completed task in the <paramref name="tasks"/> array argument, or -1 if the
+ /// timeout occurred.
+ /// </returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> argument contains a null element.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// <paramref name="millisecondsTimeout"/> is a negative number other than -1, which represents an
+ /// infinite time-out.
+ /// </exception>
+ /// <exception cref="T:System.OperationCanceledException">
+ /// The <paramref name="cancellationToken"/> was canceled.
+ /// </exception>
+ [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger
+ public static int WaitAny(Task[] tasks, int millisecondsTimeout, CancellationToken cancellationToken)
+ {
+ if (tasks == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ }
+ if (millisecondsTimeout < -1)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsTimeout);
+ }
+ Contract.EndContractBlock();
+
+ cancellationToken.ThrowIfCancellationRequested(); // early check before we make any allocations
+
+ int signaledTaskIndex = -1;
+
+ // Make a pass through the loop to check for any tasks that may have
+ // already been completed, and to verify that no tasks are null.
+
+ for (int taskIndex = 0; taskIndex < tasks.Length; taskIndex++)
+ {
+ Task task = tasks[taskIndex];
+
+ if (task == null)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Task_WaitMulti_NullTask, ExceptionArgument.tasks);
+ }
+
+ if (signaledTaskIndex == -1 && task.IsCompleted)
+ {
+ // We found our first completed task. Store it, but we can't just return here,
+ // as we still need to validate the whole array for nulls.
+ signaledTaskIndex = taskIndex;
+ }
+ }
+
+ if (signaledTaskIndex == -1 && tasks.Length != 0)
+ {
+ Task<Task> firstCompleted = TaskFactory.CommonCWAnyLogic(tasks);
+ bool waitCompleted = firstCompleted.Wait(millisecondsTimeout, cancellationToken);
+ if (waitCompleted)
+ {
+ Contract.Assert(firstCompleted.Status == TaskStatus.RanToCompletion);
+ signaledTaskIndex = Array.IndexOf(tasks, firstCompleted.Result);
+ Contract.Assert(signaledTaskIndex >= 0);
+ }
+ }
+
+ // We need to prevent the tasks array from being GC'ed until we come out of the wait.
+ // This is necessary so that the Parallel Debugger can traverse it during the long wait
+ // and deduce waiter/waitee relationships
+ GC.KeepAlive(tasks);
+
+ // Return the index
+ return signaledTaskIndex;
+ }
+
+ #region FromResult / FromException / FromCanceled
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed successfully with the specified result.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="result">The result to store into the completed task.</param>
+ /// <returns>The successfully completed task.</returns>
+ public static Task<TResult> FromResult<TResult>(TResult result)
+ {
+ return new Task<TResult>(result);
+ }
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed exceptionally with the specified exception.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="exception">The exception with which to complete the task.</param>
+ /// <returns>The faulted task.</returns>
+ public static Task FromException(Exception exception)
+ {
+ return FromException<VoidTaskResult>(exception);
+ }
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed exceptionally with the specified exception.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="exception">The exception with which to complete the task.</param>
+ /// <returns>The faulted task.</returns>
+ public static Task<TResult> FromException<TResult>(Exception exception)
+ {
+ if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
+ Contract.EndContractBlock();
+
+ var task = new Task<TResult>();
+ bool succeeded = task.TrySetException(exception);
+ Contract.Assert(succeeded, "This should always succeed on a new task.");
+ return task;
+ }
+
+ /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified token.</summary>
+ /// <param name="cancellationToken">The token with which to complete the task.</param>
+ /// <returns>The canceled task.</returns>
+ public static Task FromCanceled(CancellationToken cancellationToken)
+ {
+ if (!cancellationToken.IsCancellationRequested)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken);
+ Contract.EndContractBlock();
+ return new Task(true, TaskCreationOptions.None, cancellationToken);
+ }
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified token.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="cancellationToken">The token with which to complete the task.</param>
+ /// <returns>The canceled task.</returns>
+ public static Task<TResult> FromCanceled<TResult>(CancellationToken cancellationToken)
+ {
+ if (!cancellationToken.IsCancellationRequested)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.cancellationToken);
+ Contract.EndContractBlock();
+ return new Task<TResult>(true, default(TResult), TaskCreationOptions.None, cancellationToken);
+ }
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified exception.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="exception">The exception with which to complete the task.</param>
+ /// <returns>The canceled task.</returns>
+ internal static Task<TResult> FromCancellation<TResult>(OperationCanceledException exception)
+ {
+ if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
+ Contract.EndContractBlock();
+
+ var task = new Task<TResult>();
+ bool succeeded = task.TrySetCanceled(exception.CancellationToken, exception);
+ Contract.Assert(succeeded, "This should always succeed on a new task.");
+ return task;
+ }
+
+ /// <summary>Creates a <see cref="Task"/> that's completed due to cancellation with the specified token.</summary>
+ /// <param name="cancellationToken">The token with which to complete the task.</param>
+ /// <returns>The canceled task.</returns>
+ [FriendAccessAllowed]
+ internal static Task FromCancellation(CancellationToken cancellationToken)
+ {
+ return FromCanceled(cancellationToken);
+ }
+
+ /// <summary>Creates a <see cref="Task{TResult}"/> that's completed due to cancellation with the specified token.</summary>
+ /// <typeparam name="TResult">The type of the result returned by the task.</typeparam>
+ /// <param name="cancellationToken">The token with which to complete the task.</param>
+ /// <returns>The canceled task.</returns>
+ [FriendAccessAllowed]
+ internal static Task<TResult> FromCancellation<TResult>(CancellationToken cancellationToken)
+ {
+ return FromCanceled<TResult>(cancellationToken);
+ }
+
+ #endregion
+
+ #region Run methods
+
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a Task handle for that work.
+ /// </summary>
+ /// <param name="action">The work to execute asynchronously</param>
+ /// <returns>A Task that represents the work queued to execute in the ThreadPool.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> parameter was null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public static Task Run(Action action)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task.InternalStartNew(null, action, null, default(CancellationToken), TaskScheduler.Default,
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a Task handle for that work.
+ /// </summary>
+ /// <param name="action">The work to execute asynchronously</param>
+ /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
+ /// <returns>A Task that represents the work queued to execute in the ThreadPool.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="action"/> parameter was null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public static Task Run(Action action, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task.InternalStartNew(null, action, null, cancellationToken, TaskScheduler.Default,
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a Task(TResult) handle for that work.
+ /// </summary>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <returns>A Task(TResult) that represents the work queued to execute in the ThreadPool.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public static Task<TResult> Run<TResult>(Func<TResult> function)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(null, function, default(CancellationToken),
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a Task(TResult) handle for that work.
+ /// </summary>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
+ /// <returns>A Task(TResult) that represents the work queued to execute in the ThreadPool.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public static Task<TResult> Run<TResult>(Func<TResult> function, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(null, function, cancellationToken,
+ TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None, TaskScheduler.Default, ref stackMark);
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a proxy for the
+ /// Task returned by <paramref name="function"/>.
+ /// </summary>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <returns>A Task that represents a proxy for the Task returned by <paramref name="function"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ public static Task Run(Func<Task> function)
+ {
+ return Run(function, default(CancellationToken));
+ }
+
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a proxy for the
+ /// Task returned by <paramref name="function"/>.
+ /// </summary>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
+ /// <returns>A Task that represents a proxy for the Task returned by <paramref name="function"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="T:System.CancellationTokenSource"/> associated with <paramref name="cancellationToken"/> was disposed.
+ /// </exception>
+ public static Task Run(Func<Task> function, CancellationToken cancellationToken)
+ {
+ // Check arguments
+ if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
+ Contract.EndContractBlock();
+
+ if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ {
+ cancellationToken.ThrowIfSourceDisposed();
+ }
+
+ // Short-circuit if we are given a pre-canceled token
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled(cancellationToken);
+
+ // Kick off initial Task, which will call the user-supplied function and yield a Task.
+ Task<Task> task1 = Task<Task>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+
+ // Create a promise-style Task to be used as a proxy for the operation
+ // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
+ UnwrapPromise<VoidTaskResult> promise = new UnwrapPromise<VoidTaskResult>(task1, lookForOce: true);
+
+ return promise;
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a proxy for the
+ /// Task(TResult) returned by <paramref name="function"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result returned by the proxy Task.</typeparam>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <returns>A Task(TResult) that represents a proxy for the Task(TResult) returned by <paramref name="function"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ public static Task<TResult> Run<TResult>(Func<Task<TResult>> function)
+ {
+ return Run(function, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Queues the specified work to run on the ThreadPool and returns a proxy for the
+ /// Task(TResult) returned by <paramref name="function"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result returned by the proxy Task.</typeparam>
+ /// <param name="function">The work to execute asynchronously</param>
+ /// <param name="cancellationToken">A cancellation token that should be used to cancel the work</param>
+ /// <returns>A Task(TResult) that represents a proxy for the Task(TResult) returned by <paramref name="function"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="function"/> parameter was null.
+ /// </exception>
+ public static Task<TResult> Run<TResult>(Func<Task<TResult>> function, CancellationToken cancellationToken)
+ {
+ // Check arguments
+ if (function == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
+ Contract.EndContractBlock();
+
+ if (AppContextSwitches.ThrowExceptionIfDisposedCancellationTokenSource)
+ {
+ cancellationToken.ThrowIfSourceDisposed();
+ }
+
+ // Short-circuit if we are given a pre-canceled token
+ if (cancellationToken.IsCancellationRequested)
+ return Task.FromCanceled<TResult>(cancellationToken);
+
+ // Kick off initial Task, which will call the user-supplied function and yield a Task.
+ Task<Task<TResult>> task1 = Task<Task<TResult>>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
+
+ // Create a promise-style Task to be used as a proxy for the operation
+ // Set lookForOce == true so that unwrap logic can be on the lookout for OCEs thrown as faults from task1, to support in-delegate cancellation.
+ UnwrapPromise<TResult> promise = new UnwrapPromise<TResult>(task1, lookForOce: true);
+
+ return promise;
+ }
+
+
+ #endregion
+
+ #region Delay methods
+
+ /// <summary>
+ /// Creates a Task that will complete after a time delay.
+ /// </summary>
+ /// <param name="delay">The time span to wait before completing the returned Task</param>
+ /// <returns>A Task that represents the time delay</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="delay"/> is less than -1 or greater than Int32.MaxValue.
+ /// </exception>
+ /// <remarks>
+ /// After the specified time delay, the Task is completed in RanToCompletion state.
+ /// </remarks>
+ public static Task Delay(TimeSpan delay)
+ {
+ return Delay(delay, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Creates a Task that will complete after a time delay.
+ /// </summary>
+ /// <param name="delay">The time span to wait before completing the returned Task</param>
+ /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param>
+ /// <returns>A Task that represents the time delay</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="delay"/> is less than -1 or greater than Int32.MaxValue.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The provided <paramref name="cancellationToken"/> has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// If the cancellation token is signaled before the specified time delay, then the Task is completed in
+ /// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time
+ /// delay has expired.
+ /// </remarks>
+ public static Task Delay(TimeSpan delay, CancellationToken cancellationToken)
+ {
+ long totalMilliseconds = (long)delay.TotalMilliseconds;
+ if (totalMilliseconds < -1 || totalMilliseconds > Int32.MaxValue)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.delay, ExceptionResource.Task_Delay_InvalidDelay);
+ }
+
+ return Delay((int)totalMilliseconds, cancellationToken);
+ }
+
+ /// <summary>
+ /// Creates a Task that will complete after a time delay.
+ /// </summary>
+ /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
+ /// <returns>A Task that represents the time delay</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="millisecondsDelay"/> is less than -1.
+ /// </exception>
+ /// <remarks>
+ /// After the specified time delay, the Task is completed in RanToCompletion state.
+ /// </remarks>
+ public static Task Delay(int millisecondsDelay)
+ {
+ return Delay(millisecondsDelay, default(CancellationToken));
+ }
+
+ /// <summary>
+ /// Creates a Task that will complete after a time delay.
+ /// </summary>
+ /// <param name="millisecondsDelay">The number of milliseconds to wait before completing the returned Task</param>
+ /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned Task</param>
+ /// <returns>A Task that represents the time delay</returns>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="millisecondsDelay"/> is less than -1.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The provided <paramref name="cancellationToken"/> has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// If the cancellation token is signaled before the specified time delay, then the Task is completed in
+ /// Canceled state. Otherwise, the Task is completed in RanToCompletion state once the specified time
+ /// delay has expired.
+ /// </remarks>
+ public static Task Delay(int millisecondsDelay, CancellationToken cancellationToken)
+ {
+ // Throw on non-sensical time
+ if (millisecondsDelay < -1)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.millisecondsDelay, ExceptionResource.Task_Delay_InvalidMillisecondsDelay);
+ }
+ Contract.EndContractBlock();
+
+ // some short-cuts in case quick completion is in order
+ if (cancellationToken.IsCancellationRequested)
+ {
+ // return a Task created as already-Canceled
+ return Task.FromCanceled(cancellationToken);
+ }
+ else if (millisecondsDelay == 0)
+ {
+ // return a Task created as already-RanToCompletion
+ return Task.CompletedTask;
+ }
+
+ // Construct a promise-style Task to encapsulate our return value
+ var promise = new DelayPromise(cancellationToken);
+
+ // Register our cancellation token, if necessary.
+ if (cancellationToken.CanBeCanceled)
+ {
+ promise.Registration = cancellationToken.InternalRegisterWithoutEC(state => ((DelayPromise)state).Complete(), promise);
+ }
+
+ // ... and create our timer and make sure that it stays rooted.
+ if (millisecondsDelay != Timeout.Infinite) // no need to create the timer if it's an infinite timeout
+ {
+ promise.Timer = new Timer(state => ((DelayPromise)state).Complete(), promise, millisecondsDelay, Timeout.Infinite);
+ promise.Timer.KeepRootedWhileScheduled();
+ }
+
+ // Return the timer proxy task
+ return promise;
+ }
+
+ /// <summary>Task that also stores the completion closure and logic for Task.Delay implementation.</summary>
+ private sealed class DelayPromise : Task<VoidTaskResult>
+ {
+ internal DelayPromise(CancellationToken token)
+ : base()
+ {
+ this.Token = token;
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.Delay", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+ }
+
+ internal readonly CancellationToken Token;
+ internal CancellationTokenRegistration Registration;
+ internal Timer Timer;
+
+ internal void Complete()
+ {
+ // Transition the task to completed.
+ bool setSucceeded;
+
+ if (Token.IsCancellationRequested)
+ {
+ setSucceeded = TrySetCanceled(Token);
+ }
+ else
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ setSucceeded = TrySetResult(default(VoidTaskResult));
+ }
+
+ // If we set the value, also clean up.
+ if (setSucceeded)
+ {
+ if (Timer != null) Timer.Dispose();
+ Registration.Dispose();
+ }
+ }
+ }
+ #endregion
+
+ #region WhenAll
+ /// <summary>
+ /// Creates a task that will complete when all of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
+ /// <remarks>
+ /// <para>
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// </para>
+ /// <para>
+ /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
+ /// </para>
+ /// <para>
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// </para>
+ /// <para>
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> collection contained a null task.
+ /// </exception>
+ public static Task WhenAll(IEnumerable<Task> tasks)
+ {
+ // Take a more efficient path if tasks is actually an array
+ Task[] taskArray = tasks as Task[];
+ if (taskArray != null)
+ {
+ return WhenAll(taskArray);
+ }
+
+ // Skip a List allocation/copy if tasks is a collection
+ ICollection<Task> taskCollection = tasks as ICollection<Task>;
+ if (taskCollection != null)
+ {
+ int index = 0;
+ taskArray = new Task[taskCollection.Count];
+ foreach (var task in tasks)
+ {
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ taskArray[index++] = task;
+ }
+ return InternalWhenAll(taskArray);
+ }
+
+ // Do some argument checking and convert tasks to a List (and later an array).
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ List<Task> taskList = new List<Task>();
+ foreach (Task task in tasks)
+ {
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ taskList.Add(task);
+ }
+
+ // Delegate the rest to InternalWhenAll()
+ return InternalWhenAll(taskList.ToArray());
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when all of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
+ /// <remarks>
+ /// <para>
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// </para>
+ /// <para>
+ /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
+ /// </para>
+ /// <para>
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// </para>
+ /// <para>
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> array contained a null task.
+ /// </exception>
+ public static Task WhenAll(params Task[] tasks)
+ {
+ // Do some argument checking and make a defensive copy of the tasks array
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ Contract.EndContractBlock();
+
+ int taskCount = tasks.Length;
+ if (taskCount == 0) return InternalWhenAll(tasks); // Small optimization in the case of an empty array.
+
+ Task[] tasksCopy = new Task[taskCount];
+ for (int i = 0; i < taskCount; i++)
+ {
+ Task task = tasks[i];
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ tasksCopy[i] = task;
+ }
+
+ // The rest can be delegated to InternalWhenAll()
+ return InternalWhenAll(tasksCopy);
+ }
+
+ // Some common logic to support WhenAll() methods
+ // tasks should be a defensive copy.
+ private static Task InternalWhenAll(Task[] tasks)
+ {
+ Contract.Requires(tasks != null, "Expected a non-null tasks array");
+ return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
+ Task.CompletedTask :
+ new WhenAllPromise(tasks);
+ }
+
+ // A Task<VoidTaskResult> that gets completed when all of its constituent tasks complete.
+ // Completion logic will analyze the antecedents in order to choose completion status.
+ // This type allows us to replace this logic:
+ // Task<VoidTaskResult> promise = new Task<VoidTaskResult>(...);
+ // Action<Task> completionAction = delegate { <completion logic>};
+ // TaskFactory.CommonCWAllLogic(tasksCopy).AddCompletionAction(completionAction);
+ // return promise;
+ // which involves several allocations, with this logic:
+ // return new WhenAllPromise(tasksCopy);
+ // which saves a couple of allocations and enables debugger notification specialization.
+ //
+ // Used in InternalWhenAll(Task[])
+ private sealed class WhenAllPromise : Task<VoidTaskResult>, ITaskCompletionAction
+ {
+ /// <summary>
+ /// Stores all of the constituent tasks. Tasks clear themselves out of this
+ /// array as they complete, but only if they don't have their wait notification bit set.
+ /// </summary>
+ private readonly Task[] m_tasks;
+ /// <summary>The number of tasks remaining to complete.</summary>
+ private int m_count;
+
+ internal WhenAllPromise(Task[] tasks) :
+ base()
+ {
+ Contract.Requires(tasks != null, "Expected a non-null task array");
+ Contract.Requires(tasks.Length > 0, "Expected a non-zero length task array");
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.WhenAll", 0);
+
+ if (s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+
+ m_tasks = tasks;
+ m_count = tasks.Length;
+
+ foreach (var task in tasks)
+ {
+ if (task.IsCompleted) this.Invoke(task); // short-circuit the completion action, if possible
+ else task.AddCompletionAction(this); // simple completion action
+ }
+ }
+
+ public void Invoke(Task completedTask)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
+
+ // Decrement the count, and only continue to complete the promise if we're the last one.
+ if (Interlocked.Decrement(ref m_count) == 0)
+ {
+ // Set up some accounting variables
+ List<ExceptionDispatchInfo> observedExceptions = null;
+ Task canceledTask = null;
+
+ // Loop through antecedents:
+ // If any one of them faults, the result will be faulted
+ // If none fault, but at least one is canceled, the result will be canceled
+ // If none fault or are canceled, then result will be RanToCompletion
+ for (int i = 0; i < m_tasks.Length; i++)
+ {
+ var task = m_tasks[i];
+ Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
+
+ if (task.IsFaulted)
+ {
+ if (observedExceptions == null) observedExceptions = new List<ExceptionDispatchInfo>();
+ observedExceptions.AddRange(task.GetExceptionDispatchInfos());
+ }
+ else if (task.IsCanceled)
+ {
+ if (canceledTask == null) canceledTask = task; // use the first task that's canceled
+ }
+
+ // Regardless of completion state, if the task has its debug bit set, transfer it to the
+ // WhenAll task. We must do this before we complete the task.
+ if (task.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
+ else m_tasks[i] = null; // avoid holding onto tasks unnecessarily
+ }
+
+ if (observedExceptions != null)
+ {
+ Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
+
+ //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
+
+ TrySetException(observedExceptions);
+ }
+ else if (canceledTask != null)
+ {
+ TrySetCanceled(canceledTask.CancellationToken, canceledTask.GetCancellationExceptionDispatchInfo());
+ }
+ else
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ TrySetResult(default(VoidTaskResult));
+ }
+ }
+ Contract.Assert(m_count >= 0, "Count should never go below 0");
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
+ /// <summary>
+ /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// true iff at least one constituent task has its bit set.
+ /// </summary>
+ internal override bool ShouldNotifyDebuggerOfWaitCompletion
+ {
+ get
+ {
+ return
+ base.ShouldNotifyDebuggerOfWaitCompletion &&
+ Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(m_tasks);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when all of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
+ /// <remarks>
+ /// <para>
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// </para>
+ /// <para>
+ /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
+ /// </para>
+ /// <para>
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// The Result of the returned task will be set to an array containing all of the results of the
+ /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
+ /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
+ /// </para>
+ /// <para>
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> collection contained a null task.
+ /// </exception>
+ public static Task<TResult[]> WhenAll<TResult>(IEnumerable<Task<TResult>> tasks)
+ {
+ // Take a more efficient route if tasks is actually an array
+ Task<TResult>[] taskArray = tasks as Task<TResult>[];
+ if (taskArray != null)
+ {
+ return WhenAll<TResult>(taskArray);
+ }
+
+ // Skip a List allocation/copy if tasks is a collection
+ ICollection<Task<TResult>> taskCollection = tasks as ICollection<Task<TResult>>;
+ if (taskCollection != null)
+ {
+ int index = 0;
+ taskArray = new Task<TResult>[taskCollection.Count];
+ foreach (var task in tasks)
+ {
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ taskArray[index++] = task;
+ }
+ return InternalWhenAll<TResult>(taskArray);
+ }
+
+ // Do some argument checking and convert tasks into a List (later an array)
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ List<Task<TResult>> taskList = new List<Task<TResult>>();
+ foreach (Task<TResult> task in tasks)
+ {
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ taskList.Add(task);
+ }
+
+ // Delegate the rest to InternalWhenAll<TResult>().
+ return InternalWhenAll<TResult>(taskList.ToArray());
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when all of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of all of the supplied tasks.</returns>
+ /// <remarks>
+ /// <para>
+ /// If any of the supplied tasks completes in a faulted state, the returned task will also complete in a Faulted state,
+ /// where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
+ /// </para>
+ /// <para>
+ /// If none of the supplied tasks faulted but at least one of them was canceled, the returned task will end in the Canceled state.
+ /// </para>
+ /// <para>
+ /// If none of the tasks faulted and none of the tasks were canceled, the resulting task will end in the RanToCompletion state.
+ /// The Result of the returned task will be set to an array containing all of the results of the
+ /// supplied tasks in the same order as they were provided (e.g. if the input tasks array contained t1, t2, t3, the output
+ /// task's Result will return an TResult[] where arr[0] == t1.Result, arr[1] == t2.Result, and arr[2] == t3.Result).
+ /// </para>
+ /// <para>
+ /// If the supplied array/enumerable contains no tasks, the returned task will immediately transition to a RanToCompletion
+ /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> array contained a null task.
+ /// </exception>
+ public static Task<TResult[]> WhenAll<TResult>(params Task<TResult>[] tasks)
+ {
+ // Do some argument checking and make a defensive copy of the tasks array
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ Contract.EndContractBlock();
+
+ int taskCount = tasks.Length;
+ if (taskCount == 0) return InternalWhenAll<TResult>(tasks); // small optimization in the case of an empty task array
+
+ Task<TResult>[] tasksCopy = new Task<TResult>[taskCount];
+ for (int i = 0; i < taskCount; i++)
+ {
+ Task<TResult> task = tasks[i];
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ tasksCopy[i] = task;
+ }
+
+ // Delegate the rest to InternalWhenAll<TResult>()
+ return InternalWhenAll<TResult>(tasksCopy);
+ }
+
+ // Some common logic to support WhenAll<TResult> methods
+ private static Task<TResult[]> InternalWhenAll<TResult>(Task<TResult>[] tasks)
+ {
+ Contract.Requires(tasks != null, "Expected a non-null tasks array");
+ return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
+ new Task<TResult[]>(false, new TResult[0], TaskCreationOptions.None, default(CancellationToken)) :
+ new WhenAllPromise<TResult>(tasks);
+ }
+
+ // A Task<T> that gets completed when all of its constituent tasks complete.
+ // Completion logic will analyze the antecedents in order to choose completion status.
+ // See comments for non-generic version of WhenAllPromise class.
+ //
+ // Used in InternalWhenAll<TResult>(Task<TResult>[])
+ private sealed class WhenAllPromise<T> : Task<T[]>, ITaskCompletionAction
+ {
+ /// <summary>
+ /// Stores all of the constituent tasks. Tasks clear themselves out of this
+ /// array as they complete, but only if they don't have their wait notification bit set.
+ /// </summary>
+ private readonly Task<T>[] m_tasks;
+ /// <summary>The number of tasks remaining to complete.</summary>
+ private int m_count;
+
+ internal WhenAllPromise(Task<T>[] tasks) :
+ base()
+ {
+ Contract.Requires(tasks != null, "Expected a non-null task array");
+ Contract.Requires(tasks.Length > 0, "Expected a non-zero length task array");
+
+ m_tasks = tasks;
+ m_count = tasks.Length;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.WhenAll", 0);
+
+ if (s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+
+ foreach (var task in tasks)
+ {
+ if (task.IsCompleted) this.Invoke(task); // short-circuit the completion action, if possible
+ else task.AddCompletionAction(this); // simple completion action
+ }
+ }
+
+ public void Invoke(Task ignored)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
+
+ // Decrement the count, and only continue to complete the promise if we're the last one.
+ if (Interlocked.Decrement(ref m_count) == 0)
+ {
+ // Set up some accounting variables
+ T[] results = new T[m_tasks.Length];
+ List<ExceptionDispatchInfo> observedExceptions = null;
+ Task canceledTask = null;
+
+ // Loop through antecedents:
+ // If any one of them faults, the result will be faulted
+ // If none fault, but at least one is canceled, the result will be canceled
+ // If none fault or are canceled, then result will be RanToCompletion
+ for (int i = 0; i < m_tasks.Length; i++)
+ {
+ Task<T> task = m_tasks[i];
+ Contract.Assert(task != null, "Constituent task in WhenAll should never be null");
+
+ if (task.IsFaulted)
+ {
+ if (observedExceptions == null) observedExceptions = new List<ExceptionDispatchInfo>();
+ observedExceptions.AddRange(task.GetExceptionDispatchInfos());
+ }
+ else if (task.IsCanceled)
+ {
+ if (canceledTask == null) canceledTask = task; // use the first task that's canceled
+ }
+ else
+ {
+ Contract.Assert(task.Status == TaskStatus.RanToCompletion);
+ results[i] = task.GetResultCore(waitCompletionNotification: false); // avoid Result, which would triggering debug notification
+ }
+
+ // Regardless of completion state, if the task has its debug bit set, transfer it to the
+ // WhenAll task. We must do this before we complete the task.
+ if (task.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
+ else m_tasks[i] = null; // avoid holding onto tasks unnecessarily
+ }
+
+ if (observedExceptions != null)
+ {
+ Contract.Assert(observedExceptions.Count > 0, "Expected at least one exception");
+
+ //We don't need to TraceOperationCompleted here because TrySetException will call Finish and we'll log it there
+
+ TrySetException(observedExceptions);
+ }
+ else if (canceledTask != null)
+ {
+ TrySetCanceled(canceledTask.CancellationToken, canceledTask.GetCancellationExceptionDispatchInfo());
+ }
+ else
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+ TrySetResult(results);
+ }
+ }
+ Contract.Assert(m_count >= 0, "Count should never go below 0");
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
+ /// <summary>
+ /// Returns whether we should notify the debugger of a wait completion. This returns true
+ /// iff at least one constituent task has its bit set.
+ /// </summary>
+ internal override bool ShouldNotifyDebuggerOfWaitCompletion
+ {
+ get
+ {
+ return
+ base.ShouldNotifyDebuggerOfWaitCompletion &&
+ Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(m_tasks);
+ }
+ }
+ }
+ #endregion
+
+ #region WhenAny
+ /// <summary>
+ /// Creates a task that will complete when any of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
+ /// <remarks>
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> array contained a null task, or was empty.
+ /// </exception>
+ public static Task<Task> WhenAny(params Task[] tasks)
+ {
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ if (tasks.Length == 0)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+ }
+ Contract.EndContractBlock();
+
+ // Make a defensive copy, as the user may manipulate the tasks array
+ // after we return but before the WhenAny asynchronously completes.
+ int taskCount = tasks.Length;
+ Task[] tasksCopy = new Task[taskCount];
+ for (int i = 0; i < taskCount; i++)
+ {
+ Task task = tasks[i];
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ tasksCopy[i] = task;
+ }
+
+ // Previously implemented CommonCWAnyLogic() can handle the rest
+ return TaskFactory.CommonCWAnyLogic(tasksCopy);
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when any of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
+ /// <remarks>
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> collection contained a null task, or was empty.
+ /// </exception>
+ public static Task<Task> WhenAny(IEnumerable<Task> tasks)
+ {
+ if (tasks == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.tasks);
+ Contract.EndContractBlock();
+
+ // Make a defensive copy, as the user may manipulate the tasks collection
+ // after we return but before the WhenAny asynchronously completes.
+ List<Task> taskList = new List<Task>();
+ foreach (Task task in tasks)
+ {
+ if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks);
+ taskList.Add(task);
+ }
+
+ if (taskList.Count == 0)
+ {
+ ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_EmptyTaskList, ExceptionArgument.tasks);
+ }
+
+ // Previously implemented CommonCWAnyLogic() can handle the rest
+ return TaskFactory.CommonCWAnyLogic(taskList);
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when any of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
+ /// <remarks>
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> array contained a null task, or was empty.
+ /// </exception>
+ public static Task<Task<TResult>> WhenAny<TResult>(params Task<TResult>[] tasks)
+ {
+ // We would just like to do this:
+ // return (Task<Task<TResult>>) WhenAny( (Task[]) tasks);
+ // but classes are not covariant to enable casting Task<TResult> to Task<Task<TResult>>.
+
+ // Call WhenAny(Task[]) for basic functionality
+ Task<Task> intermediate = WhenAny((Task[])tasks);
+
+ // Return a continuation task with the correct result type
+ return intermediate.ContinueWith(Task<TResult>.TaskWhenAnyCast, default(CancellationToken),
+ TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+
+ /// <summary>
+ /// Creates a task that will complete when any of the supplied tasks have completed.
+ /// </summary>
+ /// <param name="tasks">The tasks to wait on for completion.</param>
+ /// <returns>A task that represents the completion of one of the supplied tasks. The return Task's Result is the task that completed.</returns>
+ /// <remarks>
+ /// The returned task will complete when any of the supplied tasks has completed. The returned task will always end in the RanToCompletion state
+ /// with its Result set to the first task to complete. This is true even if the first task to complete ended in the Canceled or Faulted state.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="tasks"/> argument was null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="tasks"/> collection contained a null task, or was empty.
+ /// </exception>
+ public static Task<Task<TResult>> WhenAny<TResult>(IEnumerable<Task<TResult>> tasks)
+ {
+ // We would just like to do this:
+ // return (Task<Task<TResult>>) WhenAny( (IEnumerable<Task>) tasks);
+ // but classes are not covariant to enable casting Task<TResult> to Task<Task<TResult>>.
+
+ // Call WhenAny(IEnumerable<Task>) for basic functionality
+ Task<Task> intermediate = WhenAny((IEnumerable<Task>)tasks);
+
+ // Return a continuation task with the correct result type
+ return intermediate.ContinueWith(Task<TResult>.TaskWhenAnyCast, default(CancellationToken),
+ TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DenyChildAttach, TaskScheduler.Default);
+ }
+ #endregion
+
+ [FriendAccessAllowed]
+ internal static Task<TResult> CreateUnwrapPromise<TResult>(Task outerTask, bool lookForOce)
+ {
+ Contract.Requires(outerTask != null);
+
+ return new UnwrapPromise<TResult>(outerTask, lookForOce);
+ }
+
+ internal virtual Delegate[] GetDelegateContinuationsForDebugger()
+ {
+ //Avoid an infinite loop by making sure the continuation object is not a reference to istelf.
+ if (this.m_continuationObject != this)
+ return GetDelegatesFromContinuationObject(this.m_continuationObject);
+ else
+ return null;
+ }
+
+ internal static Delegate[] GetDelegatesFromContinuationObject(object continuationObject)
+ {
+ if (continuationObject != null)
+ {
+ Action singleAction = continuationObject as Action;
+ if (singleAction != null)
+ {
+ return new Delegate[] { AsyncMethodBuilderCore.TryGetStateMachineForDebugger(singleAction) };
+ }
+
+ TaskContinuation taskContinuation = continuationObject as TaskContinuation;
+ if (taskContinuation != null)
+ {
+ return taskContinuation.GetDelegateContinuationsForDebugger();
+ }
+
+ Task continuationTask = continuationObject as Task;
+ if (continuationTask != null)
+ {
+ Contract.Assert(continuationTask.m_action == null);
+ Delegate[] delegates = continuationTask.GetDelegateContinuationsForDebugger();
+ if (delegates != null)
+ return delegates;
+ }
+
+ //We need this ITaskCompletionAction after the Task because in the case of UnwrapPromise
+ //the VS debugger is more interested in the continuation than the internal invoke()
+ ITaskCompletionAction singleCompletionAction = continuationObject as ITaskCompletionAction;
+ if (singleCompletionAction != null)
+ {
+ return new Delegate[] { new Action<Task>(singleCompletionAction.Invoke) };
+ }
+
+ List<object> continuationList = continuationObject as List<object>;
+ if (continuationList != null)
+ {
+ List<Delegate> result = new List<Delegate>();
+ foreach (object obj in continuationList)
+ {
+ var innerDelegates = GetDelegatesFromContinuationObject(obj);
+ if (innerDelegates != null)
+ {
+ foreach (var del in innerDelegates)
+ {
+ if (del != null)
+ result.Add(del);
+ }
+ }
+ }
+
+ return result.ToArray();
+ }
+ }
+
+ return null;
+ }
+
+ private static Task GetActiveTaskFromId(int taskId)
+ {
+ Task task = null;
+ s_currentActiveTasks.TryGetValue(taskId, out task);
+ return task;
+ }
+
+ private static Task[] GetActiveTasks()
+ {
+
+ return new List<Task>(s_currentActiveTasks.Values).ToArray();
+ }
+
+
+ }
+
+ 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]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+ m_action.Invoke(m_completingTask);
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
+ {
+ /* NOP */
+ }
+ }
+
+ // Proxy class for better debugging experience
+ internal class SystemThreadingTasks_TaskDebugView
+ {
+ private Task m_task;
+
+ public SystemThreadingTasks_TaskDebugView(Task task)
+ {
+ m_task = task;
+ }
+
+ public object AsyncState { get { return m_task.AsyncState; } }
+ public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
+ public Exception Exception { get { return m_task.Exception; } }
+ public int Id { get { return m_task.Id; } }
+ public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
+ public TaskStatus Status { get { return m_task.Status; } }
+ }
+
+ // Special purpose derivation of Task that supports limited replication through
+ // overriding the ShouldReplicate() method. This is used by the Parallel.For/ForEach
+ // methods.
+ internal class ParallelForReplicatingTask : Task
+ {
+ // Member variables
+ private int m_replicationDownCount; // downcounter to control replication
+
+ //
+ // Constructors
+ //
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ internal ParallelForReplicatingTask(
+ ParallelOptions parallelOptions, Action action, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions)
+ : base(action, null, Task.InternalCurrent, default(CancellationToken), creationOptions, internalOptions | InternalTaskOptions.SelfReplicating, null)
+ {
+ // Compute the down count based on scheduler/DOP info in parallelOptions.
+ m_replicationDownCount = parallelOptions.EffectiveMaxConcurrencyLevel;
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+
+ // Controls degree of replication. If downcounter is initialized to -1, then
+ // replication will be allowed to "run wild". Otherwise, this method decrements
+ // the downcounter each time it is called, calling false when it is called with
+ // a zero downcounter. This method returning false effectively ends the replication
+ // of the associated ParallelForReplicatingTask.
+ internal override bool ShouldReplicate()
+ {
+ if (m_replicationDownCount == -1) return true; // "run wild"
+
+ if (m_replicationDownCount > 0) // Decrement and return true if not called with 0 downcount
+ {
+ m_replicationDownCount--;
+ return true;
+ }
+
+ return false; // We're done replicating
+ }
+
+ internal override Task CreateReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
+ TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica)
+ {
+ return new ParallelForReplicaTask(taskReplicaDelegate, stateObject, parentTask, taskScheduler,
+ creationOptionsForReplica, internalOptionsForReplica);
+ }
+
+
+ }
+
+ internal class ParallelForReplicaTask : Task
+ {
+ internal object m_stateForNextReplica; // some replicas may quit prematurely, in which case they will use this variable
+ // to save state they want to be picked up by the next replica queued to the same thread
+
+ internal object m_stateFromPreviousReplica; // some replicas may quit prematurely, in which case they will use this variable
+ // to save state they want to be picked up by the next replica queued to the same thread
+
+ internal Task m_handedOverChildReplica; // some replicas may quit prematurely, in which case they will use this variable
+ // to hand over the child replica they had queued to the next task that will replace them
+
+ internal ParallelForReplicaTask(Action<object> taskReplicaDelegate, Object stateObject, Task parentTask, TaskScheduler taskScheduler,
+ TaskCreationOptions creationOptionsForReplica, InternalTaskOptions internalOptionsForReplica) :
+ base(taskReplicaDelegate, stateObject, parentTask, default(CancellationToken), creationOptionsForReplica, internalOptionsForReplica, taskScheduler)
+ {
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
+ internal override Object SavedStateForNextReplica
+ {
+ get { return m_stateForNextReplica; }
+
+ set { m_stateForNextReplica = value; }
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to pass on state to the next replica
+ internal override Object SavedStateFromPreviousReplica
+ {
+ get { return m_stateFromPreviousReplica; }
+
+ set { m_stateFromPreviousReplica = value; }
+ }
+
+ // Allows internal deriving classes to support replicas that exit prematurely and want to hand over the child replica that they
+ // had queued, so that the replacement replica can work with that child task instead of queuing up yet another one
+ internal override Task HandedOverChildReplica
+ {
+ get { return m_handedOverChildReplica; }
+
+ set { m_handedOverChildReplica = value; }
+ }
+ }
+
+ /// <summary>
+ /// Specifies flags that control optional behavior for the creation and execution of tasks.
+ /// </summary>
+ // NOTE: These options are a subset of TaskContinuationsOptions, thus before adding a flag check it is
+ // not already in use.
+ [Flags]
+ [Serializable]
+ public enum TaskCreationOptions
+ {
+ /// <summary>
+ /// Specifies that the default behavior should be used.
+ /// </summary>
+ None = 0x0,
+
+ /// <summary>
+ /// A hint to a <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> to schedule a
+ /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
+ /// be run sooner, and tasks scheduled later will be more likely to be run later.
+ /// </summary>
+ PreferFairness = 0x01,
+
+ /// <summary>
+ /// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the
+ /// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> that oversubscription may be
+ /// warranted.
+ /// </summary>
+ LongRunning = 0x02,
+
+ /// <summary>
+ /// Specifies that a task is attached to a parent in the task hierarchy.
+ /// </summary>
+ AttachedToParent = 0x04,
+
+ /// <summary>
+ /// Specifies that an InvalidOperationException will be thrown if an attempt is made to attach a child task to the created task.
+ /// </summary>
+ DenyChildAttach = 0x08,
+
+ /// <summary>
+ /// Prevents the ambient scheduler from being seen as the current scheduler in the created task. This means that operations
+ /// like StartNew or ContinueWith that are performed in the created task will see TaskScheduler.Default as the current scheduler.
+ /// </summary>
+ HideScheduler = 0x10,
+
+ // 0x20 is already being used in TaskContinuationOptions
+
+ /// <summary>
+ /// Forces continuations added to the current task to be executed asynchronously.
+ /// This option has precedence over TaskContinuationOptions.ExecuteSynchronously
+ /// </summary>
+ RunContinuationsAsynchronously = 0x40
+ }
+
+
+ /// <summary>
+ /// Task creation flags which are only used internally.
+ /// </summary>
+ [Flags]
+ [Serializable]
+ internal enum InternalTaskOptions
+ {
+ /// <summary> Specifies "No internal task options" </summary>
+ None,
+
+ /// <summary>Used to filter out internal vs. public task creation options.</summary>
+ InternalOptionsMask = 0x0000FF00,
+
+ ChildReplica = 0x0100,
+ ContinuationTask = 0x0200,
+ PromiseTask = 0x0400,
+ SelfReplicating = 0x0800,
+
+ /// <summary>
+ /// Store the presence of TaskContinuationOptions.LazyCancellation, since it does not directly
+ /// translate into any TaskCreationOptions.
+ /// </summary>
+ LazyCancellation = 0x1000,
+
+ /// <summary>Specifies that the task will be queued by the runtime before handing it over to the user.
+ /// This flag will be used to skip the cancellationtoken registration step, which is only meant for unstarted tasks.</summary>
+ QueuedByRuntime = 0x2000,
+
+ /// <summary>
+ /// Denotes that Dispose should be a complete nop for a Task. Used when constructing tasks that are meant to be cached/reused.
+ /// </summary>
+ DoNotDispose = 0x4000
+ }
+
+ /// <summary>
+ /// Specifies flags that control optional behavior for the creation and execution of continuation tasks.
+ /// </summary>
+ [Flags]
+ [Serializable]
+ public enum TaskContinuationOptions
+ {
+ /// <summary>
+ /// Default = "Continue on any, no task options, run asynchronously"
+ /// Specifies that the default behavior should be used. Continuations, by default, will
+ /// be scheduled when the antecedent task completes, regardless of the task's final <see
+ /// cref="System.Threading.Tasks.TaskStatus">TaskStatus</see>.
+ /// </summary>
+ None = 0,
+
+ // These are identical to their meanings and values in TaskCreationOptions
+
+ /// <summary>
+ /// A hint to a <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> to schedule a
+ /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to
+ /// be run sooner, and tasks scheduled later will be more likely to be run later.
+ /// </summary>
+ PreferFairness = 0x01,
+
+ /// <summary>
+ /// Specifies that a task will be a long-running, course-grained operation. It provides
+ /// a hint to the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> that
+ /// oversubscription may be warranted.
+ /// </summary>
+ LongRunning = 0x02,
+ /// <summary>
+ /// Specifies that a task is attached to a parent in the task hierarchy.
+ /// </summary>
+ AttachedToParent = 0x04,
+
+ /// <summary>
+ /// Specifies that an InvalidOperationException will be thrown if an attempt is made to attach a child task to the created task.
+ /// </summary>
+ DenyChildAttach = 0x08,
+ /// <summary>
+ /// Prevents the ambient scheduler from being seen as the current scheduler in the created task. This means that operations
+ /// like StartNew or ContinueWith that are performed in the created task will see TaskScheduler.Default as the current scheduler.
+ /// </summary>
+ HideScheduler = 0x10,
+
+ /// <summary>
+ /// In the case of continuation cancellation, prevents completion of the continuation until the antecedent has completed.
+ /// </summary>
+ LazyCancellation = 0x20,
+
+ RunContinuationsAsynchronously = 0x40,
+
+ // These are specific to continuations
+
+ /// <summary>
+ /// Specifies that the continuation task should not be scheduled if its antecedent ran to completion.
+ /// This option is not valid for multi-task continuations.
+ /// </summary>
+ NotOnRanToCompletion = 0x10000,
+ /// <summary>
+ /// Specifies that the continuation task should not be scheduled if its antecedent threw an unhandled
+ /// exception. This option is not valid for multi-task continuations.
+ /// </summary>
+ NotOnFaulted = 0x20000,
+ /// <summary>
+ /// Specifies that the continuation task should not be scheduled if its antecedent was canceled. This
+ /// option is not valid for multi-task continuations.
+ /// </summary>
+ NotOnCanceled = 0x40000,
+ /// <summary>
+ /// Specifies that the continuation task should be scheduled only if its antecedent ran to
+ /// completion. This option is not valid for multi-task continuations.
+ /// </summary>
+ OnlyOnRanToCompletion = NotOnFaulted | NotOnCanceled,
+ /// <summary>
+ /// Specifies that the continuation task should be scheduled only if its antecedent threw an
+ /// unhandled exception. This option is not valid for multi-task continuations.
+ /// </summary>
+ OnlyOnFaulted = NotOnRanToCompletion | NotOnCanceled,
+ /// <summary>
+ /// Specifies that the continuation task should be scheduled only if its antecedent was canceled.
+ /// This option is not valid for multi-task continuations.
+ /// </summary>
+ OnlyOnCanceled = NotOnRanToCompletion | NotOnFaulted,
+ /// <summary>
+ /// Specifies that the continuation task should be executed synchronously. With this option
+ /// specified, the continuation will be run on the same thread that causes the antecedent task to
+ /// transition into its final state. If the antecedent is already complete when the continuation is
+ /// created, the continuation will run on the thread creating the continuation. Only very
+ /// short-running continuations should be executed synchronously.
+ /// </summary>
+ ExecuteSynchronously = 0x80000
+ }
+
+ /// <summary>
+ /// Internal helper class to keep track of stack depth and decide whether we should inline or not.
+ /// </summary>
+ internal class StackGuard
+ {
+ // current thread's depth of nested inline task executions
+ private int m_inliningDepth = 0;
+
+ // For relatively small inlining depths we don't want to get into the business of stack probing etc.
+ // This clearly leaves a window of opportunity for the user code to SO. However a piece of code
+ // that can SO in 20 inlines on a typical 1MB stack size probably needs to be revisited anyway.
+ private const int MAX_UNCHECKED_INLINING_DEPTH = 20;
+
+#if !FEATURE_CORECLR
+
+ private UInt64 m_lastKnownWatermark;
+ private static int s_pageSize;
+
+ // We are conservative here. We assume that the platform needs a whole 64KB to
+ // respond to stack overflow. This means that for very small stacks (e.g. 128KB)
+ // we'll fail a lot of stack checks incorrectly.
+ private const long STACK_RESERVED_SPACE = 4096 * 16;
+
+#endif // !FEATURE_CORECLR
+
+ /// <summary>
+ /// This method needs to be called before attempting inline execution on the current thread.
+ /// If false is returned, it means we are too close to the end of the stack and should give up inlining.
+ /// Each call to TryBeginInliningScope() that returns true must be matched with a
+ /// call to EndInliningScope() regardless of whether inlining actually took place.
+ /// </summary>
+ [SecuritySafeCritical]
+ internal bool TryBeginInliningScope()
+ {
+ // If we're still under the 'safe' limit we'll just skip the stack probe to save p/invoke calls
+ if (m_inliningDepth < MAX_UNCHECKED_INLINING_DEPTH || CheckForSufficientStack())
+ {
+ m_inliningDepth++;
+ return true;
+ }
+ else
+ return false;
+ }
+
+ /// <summary>
+ /// This needs to be called once for each previous successful TryBeginInliningScope() call after
+ /// inlining related logic runs.
+ /// </summary>
+ internal void EndInliningScope()
+ {
+ m_inliningDepth--;
+ Contract.Assert(m_inliningDepth >= 0, "Inlining depth count should never go negative.");
+
+ // do the right thing just in case...
+ if (m_inliningDepth < 0) m_inliningDepth = 0;
+ }
+
+ [SecurityCritical]
+ private unsafe bool CheckForSufficientStack()
+ {
+#if FEATURE_CORECLR
+ return RuntimeHelpers.TryEnsureSufficientExecutionStack();
+#else
+ // see if we already have the system page size info recorded
+ int pageSize = s_pageSize;
+ if (pageSize == 0)
+ {
+ // If not we need to query it from GetSystemInfo()
+ // Note that this happens only once for the process lifetime
+ Win32Native.SYSTEM_INFO sysInfo = new Win32Native.SYSTEM_INFO();
+ Win32Native.GetSystemInfo(ref sysInfo);
+
+ s_pageSize = pageSize = sysInfo.dwPageSize;
+ }
+
+ Win32Native.MEMORY_BASIC_INFORMATION stackInfo = new Win32Native.MEMORY_BASIC_INFORMATION();
+
+ // We subtract one page for our request. VirtualQuery rounds UP to the next page.
+ // Unfortunately, the stack grows down. If we're on the first page (last page in the
+ // VirtualAlloc), we'll be moved to the next page, which is off the stack!
+
+ UIntPtr currentAddr = new UIntPtr(&stackInfo - pageSize);
+ UInt64 current64 = currentAddr.ToUInt64();
+
+ // Check whether we previously recorded a deeper stack than where we currently are,
+ // If so we don't need to do the P/Invoke to VirtualQuery
+ if (m_lastKnownWatermark != 0 && current64 > m_lastKnownWatermark)
+ return true;
+
+ // Actual stack probe. P/Invoke to query for the current stack allocation information.
+ Win32Native.VirtualQuery(currentAddr.ToPointer(), ref stackInfo, (UIntPtr)(sizeof(Win32Native.MEMORY_BASIC_INFORMATION)));
+
+ // If the current address minus the base (remember: the stack grows downward in the
+ // address space) is greater than the number of bytes requested plus the reserved
+ // space at the end, the request has succeeded.
+
+ if ((current64 - ((UIntPtr)stackInfo.AllocationBase).ToUInt64()) > STACK_RESERVED_SPACE)
+ {
+ m_lastKnownWatermark = current64;
+ return true;
+ }
+
+ return false;
+#endif
+ }
+ }
+
+ // Special internal struct that we use to signify that we are not interested in
+ // a Task<VoidTaskResult>'s result.
+ internal struct VoidTaskResult { }
+
+ // Interface to which all completion actions must conform.
+ // This interface allows us to combine functionality and reduce allocations.
+ // For example, see Task.SetOnInvokeMres, and its use in Task.SpinThenBlockingWait().
+ // This code:
+ // ManualResetEvent mres = new ManualResetEventSlim(false, 0);
+ // Action<Task> completionAction = delegate { mres.Set() ; };
+ // AddCompletionAction(completionAction);
+ // gets replaced with this:
+ // SetOnInvokeMres mres = new SetOnInvokeMres();
+ // AddCompletionAction(mres);
+ // For additional examples of where this is used, see internal classes Task.SignalOnInvokeCDE,
+ // Task.WhenAllPromise, Task.WhenAllPromise<T>, TaskFactory.CompleteOnCountdownPromise,
+ // TaskFactory.CompleteOnCountdownPromise<T>, and TaskFactory.CompleteOnInvokePromise.
+ internal interface ITaskCompletionAction
+ {
+ /// <summary>Invoked to run the completion action.</summary>
+ void Invoke(Task completingTask);
+
+ /// <summary>
+ /// Some completion actions are considered internal implementation details of tasks,
+ /// using the continuation mechanism only for performance reasons. Such actions perform
+ /// known quantities and types of work, and can be invoked safely as a continuation even
+ /// if the system wants to prevent arbitrary continuations from running synchronously.
+ /// This should only return false for a limited set of implementations where a small amount
+ /// of work is guaranteed to be performed, e.g. setting a ManualResetEventSlim.
+ /// </summary>
+ bool InvokeMayRunArbitraryCode { get; }
+ }
+
+ // This class encapsulates all "unwrap" logic, and also implements ITaskCompletionAction,
+ // which minimizes the allocations needed for queuing it to its antecedent. This
+ // logic is used by both the Unwrap extension methods and the unwrap-style Task.Run methods.
+ internal sealed class UnwrapPromise<TResult> : Task<TResult>, ITaskCompletionAction
+ {
+ // The possible states for our UnwrapPromise, used by Invoke() to determine which logic to execute
+ private const byte STATE_WAITING_ON_OUTER_TASK = 0; // Invoke() means "process completed outer task"
+ private const byte STATE_WAITING_ON_INNER_TASK = 1; // Invoke() means "process completed inner task"
+ private const byte STATE_DONE = 2; // Invoke() means "something went wrong and we are hosed!"
+
+ // Keep track of our state; initialized to STATE_WAITING_ON_OUTER_TASK in the constructor
+ private byte _state;
+
+ // "Should we check for OperationCanceledExceptions on the outer task and interpret them as proxy cancellation?"
+ // Unwrap() sets this to false, Run() sets it to true.
+ private readonly bool _lookForOce;
+
+ public UnwrapPromise(Task outerTask, bool lookForOce)
+ : base((object)null, outerTask.CreationOptions & TaskCreationOptions.AttachedToParent)
+ {
+ Contract.Requires(outerTask != null, "Expected non-null outerTask");
+ _lookForOce = lookForOce;
+ _state = STATE_WAITING_ON_OUTER_TASK;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "Task.Unwrap", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+
+ // Link ourselves to the outer task.
+ // If the outer task has already completed, take the fast path
+ // of immediately transferring its results or processing the inner task.
+ if (outerTask.IsCompleted)
+ {
+ ProcessCompletedOuterTask(outerTask);
+ }
+ else // Otherwise, process its completion asynchronously.
+ {
+ outerTask.AddCompletionAction(this);
+ }
+ }
+
+ // For ITaskCompletionAction
+ public void Invoke(Task completingTask)
+ {
+ // Check the current stack guard. If we're ok to inline,
+ // process the task, and reset the guard when we're done.
+ var sg = Task.CurrentStackGuard;
+ if (sg.TryBeginInliningScope())
+ {
+ try { InvokeCore(completingTask); }
+ finally { sg.EndInliningScope(); }
+ }
+ // Otherwise, we're too deep on the stack, and
+ // we shouldn't run the continuation chain here, so queue a work
+ // item to call back here to Invoke asynchronously.
+ else InvokeCoreAsync(completingTask);
+ }
+
+ /// <summary>
+ /// Processes the completed task. InvokeCore could be called twice:
+ /// once for the outer task, once for the inner task.
+ /// </summary>
+ /// <param name="completingTask">The completing outer or inner task.</param>
+ private void InvokeCore(Task completingTask)
+ {
+ switch (_state)
+ {
+ case STATE_WAITING_ON_OUTER_TASK:
+ ProcessCompletedOuterTask(completingTask);
+ // We bump the state inside of ProcessCompletedOuterTask because it can also be called from the constructor.
+ break;
+ case STATE_WAITING_ON_INNER_TASK:
+ bool result = TrySetFromTask(completingTask, lookForOce: false);
+ _state = STATE_DONE; // bump the state
+ Contract.Assert(result, "Expected TrySetFromTask from inner task to succeed");
+ break;
+ default:
+ Contract.Assert(false, "UnwrapPromise in illegal state");
+ break;
+ }
+ }
+
+ // Calls InvokeCore asynchronously.
+ [SecuritySafeCritical]
+ private void InvokeCoreAsync(Task completingTask)
+ {
+ // Queue a call to Invoke. If we're so deep on the stack that we're at risk of overflowing,
+ // there's a high liklihood this thread is going to be doing lots more work before
+ // returning to the thread pool (at the very least unwinding through thousands of
+ // stack frames). So we queue to the global queue.
+ ThreadPool.UnsafeQueueUserWorkItem(state =>
+ {
+ // InvokeCore(completingTask);
+ var tuple = (Tuple<UnwrapPromise<TResult>, Task>)state;
+ tuple.Item1.InvokeCore(tuple.Item2);
+ }, Tuple.Create<UnwrapPromise<TResult>, Task>(this, completingTask));
+ }
+
+ /// <summary>Processes the outer task once it's completed.</summary>
+ /// <param name="task">The now-completed outer task.</param>
+ private void ProcessCompletedOuterTask(Task task)
+ {
+ Contract.Requires(task != null && task.IsCompleted, "Expected non-null, completed outer task");
+ Contract.Assert(_state == STATE_WAITING_ON_OUTER_TASK, "We're in the wrong state!");
+
+ // Bump our state before proceeding any further
+ _state = STATE_WAITING_ON_INNER_TASK;
+
+ switch (task.Status)
+ {
+ // If the outer task did not complete successfully, then record the
+ // cancellation/fault information to tcs.Task.
+ case TaskStatus.Canceled:
+ case TaskStatus.Faulted:
+ bool result = TrySetFromTask(task, _lookForOce);
+ Contract.Assert(result, "Expected TrySetFromTask from outer task to succeed");
+ break;
+
+ // Otherwise, process the inner task it returned.
+ case TaskStatus.RanToCompletion:
+ var taskOfTaskOfTResult = task as Task<Task<TResult>>; // it's either a Task<Task> or Task<Task<TResult>>
+ ProcessInnerTask(taskOfTaskOfTResult != null ?
+ taskOfTaskOfTResult.Result : ((Task<Task>)task).Result);
+ break;
+ }
+ }
+
+ /// <summary>Transfer the completion status from "task" to ourself.</summary>
+ /// <param name="task">The source task whose results should be transfered to <paramref name="promise"/>.</param>
+ /// <param name="lookForOce">Whether or not to look for OperationCanceledExceptions in task's exceptions if it faults.</param>
+ /// <returns>true if the transfer was successful; otherwise, false.</returns>
+ private bool TrySetFromTask(Task task, bool lookForOce)
+ {
+ Contract.Requires(task != null && task.IsCompleted, "TrySetFromTask: Expected task to have completed.");
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
+
+ bool result = false;
+ switch (task.Status)
+ {
+ case TaskStatus.Canceled:
+ result = TrySetCanceled(task.CancellationToken, task.GetCancellationExceptionDispatchInfo());
+ break;
+
+ case TaskStatus.Faulted:
+ var edis = task.GetExceptionDispatchInfos();
+ ExceptionDispatchInfo oceEdi;
+ OperationCanceledException oce;
+ if (lookForOce && edis.Count > 0 &&
+ (oceEdi = edis[0]) != null &&
+ (oce = oceEdi.SourceException as OperationCanceledException) != null)
+ {
+ result = TrySetCanceled(oce.CancellationToken, oceEdi);
+ }
+ else
+ {
+ result = TrySetException(edis);
+ }
+ break;
+
+ case TaskStatus.RanToCompletion:
+ var taskTResult = task as Task<TResult>;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+
+ result = TrySetResult(taskTResult != null ? taskTResult.Result : default(TResult));
+ break;
+ }
+ return result;
+ }
+
+ /// <summary>
+ /// Processes the inner task of a Task{Task} or Task{Task{TResult}},
+ /// transferring the appropriate results to ourself.
+ /// </summary>
+ /// <param name="task">The inner task returned by the task provided by the user.</param>
+ private void ProcessInnerTask(Task task)
+ {
+ // If the inner task is null, the proxy should be canceled.
+ if (task == null)
+ {
+ TrySetCanceled(default(CancellationToken));
+ _state = STATE_DONE; // ... and record that we are done
+ }
+
+ // Fast path for if the inner task is already completed
+ else if (task.IsCompleted)
+ {
+ TrySetFromTask(task, lookForOce: false);
+ _state = STATE_DONE; // ... and record that we are done
+ }
+
+ // The inner task exists but is not yet complete, so when it does complete,
+ // take some action to set our completion state.
+ else
+ {
+ task.AddCompletionAction(this);
+ // We'll record that we are done when Invoke() is called.
+ }
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskCanceledException.cs b/src/mscorlib/src/System/Threading/Tasks/TaskCanceledException.cs
new file mode 100644
index 0000000000..f15e3e783a
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskCanceledException.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// An exception for task cancellations.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+
+namespace System.Threading.Tasks
+{
+
+ /// <summary>
+ /// Represents an exception used to communicate task cancellation.
+ /// </summary>
+ [Serializable]
+ public class TaskCanceledException : OperationCanceledException
+ {
+
+ [NonSerialized]
+ private Task m_canceledTask; // The task which has been canceled.
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class.
+ /// </summary>
+ public TaskCanceledException() : base(Environment.GetResourceString("TaskCanceledException_ctor_DefaultMessage"))
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/>
+ /// class with a specified error message.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ public TaskCanceledException(string message) : base(message)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/>
+ /// class with a specified error message and a reference to the inner exception that is the cause of
+ /// this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ public TaskCanceledException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/> class
+ /// with a reference to the <see cref="T:System.Threading.Tasks.Task"/> that has been canceled.
+ /// </summary>
+ /// <param name="task">A task that has been canceled.</param>
+ public TaskCanceledException(Task task) :
+ base(Environment.GetResourceString("TaskCanceledException_ctor_DefaultMessage"), task!=null ? task.CancellationToken:new CancellationToken())
+ {
+ m_canceledTask = task;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskCanceledException"/>
+ /// class with serialized data.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination. </param>
+ protected TaskCanceledException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+
+ /// <summary>
+ /// Gets the task associated with this exception.
+ /// </summary>
+ /// <remarks>
+ /// It is permissible for no Task to be associated with a
+ /// <see cref="T:System.Threading.Tasks.TaskCanceledException"/>, in which case
+ /// this property will return null.
+ /// </remarks>
+ public Task Task
+ {
+ get { return m_canceledTask; }
+ }
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs
new file mode 100644
index 0000000000..8b1dd2a62f
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskCompletionSource.cs
@@ -0,0 +1,370 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// TaskCompletionSource<TResult> is the producer end of an unbound future. Its
+// Task member may be distributed as the consumer end of the future.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Security.Permissions;
+using System.Threading;
+
+// Disable the "reference to volatile field not treated as volatile" error.
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Represents the producer side of a <see cref="T:System.Threading.Tasks.Task{TResult}"/> unbound to a
+ /// delegate, providing access to the consumer side through the <see cref="Task"/> property.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// It is often the case that a <see cref="T:System.Threading.Tasks.Task{TResult}"/> is desired to
+ /// represent another asynchronous operation.
+ /// <see cref="TaskCompletionSource{TResult}">TaskCompletionSource</see> is provided for this purpose. It enables
+ /// the creation of a task that can be handed out to consumers, and those consumers can use the members
+ /// of the task as they would any other. However, unlike most tasks, the state of a task created by a
+ /// TaskCompletionSource is controlled explicitly by the methods on TaskCompletionSource. This enables the
+ /// completion of the external asynchronous operation to be propagated to the underlying Task. The
+ /// separation also ensures that consumers are not able to transition the state without access to the
+ /// corresponding TaskCompletionSource.
+ /// </para>
+ /// <para>
+ /// All members of <see cref="TaskCompletionSource{TResult}"/> are thread-safe
+ /// and may be used from multiple threads concurrently.
+ /// </para>
+ /// </remarks>
+ /// <typeparam name="TResult">The type of the result value assocatied with this <see
+ /// cref="TaskCompletionSource{TResult}"/>.</typeparam>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class TaskCompletionSource<TResult>
+ {
+ private readonly Task<TResult> m_task;
+
+ /// <summary>
+ /// Creates a <see cref="TaskCompletionSource{TResult}"/>.
+ /// </summary>
+ public TaskCompletionSource()
+ {
+ m_task = new Task<TResult>();
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TaskCompletionSource{TResult}"/>
+ /// with the specified options.
+ /// </summary>
+ /// <remarks>
+ /// The <see cref="T:System.Threading.Tasks.Task{TResult}"/> created
+ /// by this instance and accessible through its <see cref="Task"/> property
+ /// will be instantiated using the specified <paramref name="creationOptions"/>.
+ /// </remarks>
+ /// <param name="creationOptions">The options to use when creating the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> represent options invalid for use
+ /// with a <see cref="TaskCompletionSource{TResult}"/>.
+ /// </exception>
+ public TaskCompletionSource(TaskCreationOptions creationOptions)
+ : this(null, creationOptions)
+ {
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TaskCompletionSource{TResult}"/>
+ /// with the specified state.
+ /// </summary>
+ /// <param name="state">The state to use as the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
+ public TaskCompletionSource(object state)
+ : this(state, TaskCreationOptions.None)
+ {
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TaskCompletionSource{TResult}"/> with
+ /// the specified state and options.
+ /// </summary>
+ /// <param name="creationOptions">The options to use when creating the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">The state to use as the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>'s AsyncState.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> represent options invalid for use
+ /// with a <see cref="TaskCompletionSource{TResult}"/>.
+ /// </exception>
+ public TaskCompletionSource(object state, TaskCreationOptions creationOptions)
+ {
+ m_task = new Task<TResult>(state, creationOptions);
+ }
+
+
+ /// <summary>
+ /// Gets the <see cref="T:System.Threading.Tasks.Task{TResult}"/> created
+ /// by this <see cref="TaskCompletionSource{TResult}"/>.
+ /// </summary>
+ /// <remarks>
+ /// This property enables a consumer access to the <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/> that is controlled by this instance.
+ /// The <see cref="SetResult"/>, <see cref="SetException(System.Exception)"/>,
+ /// <see cref="SetException(System.Collections.Generic.IEnumerable{System.Exception})"/>, and <see cref="SetCanceled"/>
+ /// methods (and their "Try" variants) on this instance all result in the relevant state
+ /// transitions on this underlying Task.
+ /// </remarks>
+ public Task<TResult> Task
+ {
+ get { return m_task; }
+ }
+
+ /// <summary>Spins until the underlying task is completed.</summary>
+ /// <remarks>This should only be called if the task is in the process of being completed by another thread.</remarks>
+ private void SpinUntilCompleted()
+ {
+ // Spin wait until the completion is finalized by another thread.
+ var sw = new SpinWait();
+ while (!m_task.IsCompleted)
+ sw.SpinOnce();
+ }
+
+ /// <summary>
+ /// Attempts to transition the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
+ /// state.
+ /// </summary>
+ /// <param name="exception">The exception to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>True if the operation was successful; otherwise, false.</returns>
+ /// <remarks>This operation will return false if the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="exception"/> argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public bool TrySetException(Exception exception)
+ {
+ if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
+
+ bool rval = m_task.TrySetException(exception);
+ if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
+ return rval;
+ }
+
+ /// <summary>
+ /// Attempts to transition the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
+ /// state.
+ /// </summary>
+ /// <param name="exceptions">The collection of exceptions to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>True if the operation was successful; otherwise, false.</returns>
+ /// <remarks>This operation will return false if the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="exceptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">There are one or more null elements in <paramref name="exceptions"/>.</exception>
+ /// <exception cref="T:System.ArgumentException">The <paramref name="exceptions"/> collection is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public bool TrySetException(IEnumerable<Exception> exceptions)
+ {
+ if (exceptions == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exceptions);
+
+ List<Exception> defensiveCopy = new List<Exception>();
+ foreach (Exception e in exceptions)
+ {
+ if (e == null)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NullException, ExceptionArgument.exceptions);
+ defensiveCopy.Add(e);
+ }
+
+ if (defensiveCopy.Count == 0)
+ ThrowHelper.ThrowArgumentException(ExceptionResource.TaskCompletionSourceT_TrySetException_NoExceptions, ExceptionArgument.exceptions);
+
+ bool rval = m_task.TrySetException(defensiveCopy);
+ if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
+ return rval;
+ }
+
+ /// <summary>Attempts to transition the underlying task to the faulted state.</summary>
+ /// <param name="exceptions">The collection of exception dispatch infos to bind to this task.</param>
+ /// <returns>True if the operation was successful; otherwise, false.</returns>
+ /// <remarks>Unlike the public methods, this method doesn't currently validate that its arguments are correct.</remarks>
+ internal bool TrySetException(IEnumerable<ExceptionDispatchInfo> exceptions)
+ {
+ Contract.Assert(exceptions != null);
+#if DEBUG
+ foreach(var edi in exceptions) Contract.Assert(edi != null, "Contents must be non-null");
+#endif
+
+ bool rval = m_task.TrySetException(exceptions);
+ if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
+ return rval;
+ }
+
+ /// <summary>
+ /// Transitions the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
+ /// state.
+ /// </summary>
+ /// <param name="exception">The exception to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="exception"/> argument is null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public void SetException(Exception exception)
+ {
+ if (exception == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.exception);
+
+ if (!TrySetException(exception))
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
+ }
+ }
+
+ /// <summary>
+ /// Transitions the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>
+ /// state.
+ /// </summary>
+ /// <param name="exceptions">The collection of exceptions to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="exceptions"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">There are one or more null elements in <paramref name="exceptions"/>.</exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public void SetException(IEnumerable<Exception> exceptions)
+ {
+ if (!TrySetException(exceptions))
+ {
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
+ }
+ }
+
+
+ /// <summary>
+ /// Attempts to transition the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>
+ /// state.
+ /// </summary>
+ /// <param name="result">The result value to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>True if the operation was successful; otherwise, false.</returns>
+ /// <remarks>This operation will return false if the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public bool TrySetResult(TResult result)
+ {
+ bool rval = m_task.TrySetResult(result);
+ if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
+ return rval;
+ }
+
+ /// <summary>
+ /// Transitions the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>
+ /// state.
+ /// </summary>
+ /// <param name="result">The result value to bind to this <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public void SetResult(TResult result)
+ {
+ if (!TrySetResult(result))
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
+ }
+
+ /// <summary>
+ /// Attempts to transition the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>
+ /// state.
+ /// </summary>
+ /// <returns>True if the operation was successful; otherwise, false.</returns>
+ /// <remarks>This operation will return false if the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </remarks>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public bool TrySetCanceled()
+ {
+ return TrySetCanceled(default(CancellationToken));
+ }
+
+ // Enables a token to be stored into the canceled task
+ public bool TrySetCanceled(CancellationToken cancellationToken)
+ {
+ bool rval = m_task.TrySetCanceled(cancellationToken);
+ if (!rval && !m_task.IsCompleted) SpinUntilCompleted();
+ return rval;
+ }
+
+ /// <summary>
+ /// Transitions the underlying
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/> into the
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>
+ /// state.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The underlying <see cref="T:System.Threading.Tasks.Task{TResult}"/> is already in one
+ /// of the three final states:
+ /// <see cref="System.Threading.Tasks.TaskStatus.RanToCompletion">RanToCompletion</see>,
+ /// <see cref="System.Threading.Tasks.TaskStatus.Faulted">Faulted</see>, or
+ /// <see cref="System.Threading.Tasks.TaskStatus.Canceled">Canceled</see>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The <see cref="Task"/> was disposed.</exception>
+ public void SetCanceled()
+ {
+ if(!TrySetCanceled())
+ ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs
new file mode 100644
index 0000000000..4c035dfddb
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskContinuation.cs
@@ -0,0 +1,867 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Implementation of task continuations, TaskContinuation, and its descendants.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Security;
+using System.Diagnostics.Contracts;
+using System.Runtime.ExceptionServices;
+using System.Runtime.CompilerServices;
+using System.Threading;
+
+#if FEATURE_COMINTEROP
+using System.Runtime.InteropServices.WindowsRuntime;
+#endif // FEATURE_COMINTEROP
+
+namespace System.Threading.Tasks
+{
+ // Task type used to implement: Task ContinueWith(Action<Task,...>)
+ internal sealed class ContinuationTaskFromTask : Task
+ {
+ private Task m_antecedent;
+
+ public ContinuationTaskFromTask(
+ Task antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ base(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
+ {
+ Contract.Requires(action is Action<Task> || action is Action<Task, object>,
+ "Invalid delegate type in ContinuationTaskFromTask");
+ m_antecedent = antecedent;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
+ /// </summary>
+ internal override void InnerInvoke()
+ {
+ // Get and null out the antecedent. This is crucial to avoid a memory
+ // leak with long chains of continuations.
+ var antecedent = m_antecedent;
+ Contract.Assert(antecedent != null,
+ "No antecedent was set for the ContinuationTaskFromTask.");
+ m_antecedent = null;
+
+ // Notify the debugger we're completing an asynchronous wait on a task
+ antecedent.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // Invoke the delegate
+ Contract.Assert(m_action != null);
+ var action = m_action as Action<Task>;
+ if (action != null)
+ {
+ action(antecedent);
+ return;
+ }
+ var actionWithState = m_action as Action<Task, object>;
+ if (actionWithState != null)
+ {
+ actionWithState(antecedent, m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in ContinuationTaskFromTask");
+ }
+ }
+
+ // Task type used to implement: Task<TResult> ContinueWith(Func<Task,...>)
+ internal sealed class ContinuationResultTaskFromTask<TResult> : Task<TResult>
+ {
+ private Task m_antecedent;
+
+ public ContinuationResultTaskFromTask(
+ Task antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ base(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
+ {
+ Contract.Requires(function is Func<Task, TResult> || function is Func<Task, object, TResult>,
+ "Invalid delegate type in ContinuationResultTaskFromTask");
+ m_antecedent = antecedent;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
+ /// </summary>
+ internal override void InnerInvoke()
+ {
+ // Get and null out the antecedent. This is crucial to avoid a memory
+ // leak with long chains of continuations.
+ var antecedent = m_antecedent;
+ Contract.Assert(antecedent != null,
+ "No antecedent was set for the ContinuationResultTaskFromTask.");
+ m_antecedent = null;
+
+ // Notify the debugger we're completing an asynchronous wait on a task
+ antecedent.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // Invoke the delegate
+ Contract.Assert(m_action != null);
+ var func = m_action as Func<Task, TResult>;
+ if (func != null)
+ {
+ m_result = func(antecedent);
+ return;
+ }
+ var funcWithState = m_action as Func<Task, object, TResult>;
+ if (funcWithState != null)
+ {
+ m_result = funcWithState(antecedent, m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in ContinuationResultTaskFromTask");
+ }
+ }
+
+ // Task type used to implement: Task ContinueWith(Action<Task<TAntecedentResult>,...>)
+ internal sealed class ContinuationTaskFromResultTask<TAntecedentResult> : Task
+ {
+ private Task<TAntecedentResult> m_antecedent;
+
+ public ContinuationTaskFromResultTask(
+ Task<TAntecedentResult> antecedent, Delegate action, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ base(action, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
+ {
+ Contract.Requires(action is Action<Task<TAntecedentResult>> || action is Action<Task<TAntecedentResult>, object>,
+ "Invalid delegate type in ContinuationTaskFromResultTask");
+ m_antecedent = antecedent;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
+ /// </summary>
+ internal override void InnerInvoke()
+ {
+ // Get and null out the antecedent. This is crucial to avoid a memory
+ // leak with long chains of continuations.
+ var antecedent = m_antecedent;
+ Contract.Assert(antecedent != null,
+ "No antecedent was set for the ContinuationTaskFromResultTask.");
+ m_antecedent = null;
+
+ // Notify the debugger we're completing an asynchronous wait on a task
+ antecedent.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // Invoke the delegate
+ Contract.Assert(m_action != null);
+ var action = m_action as Action<Task<TAntecedentResult>>;
+ if (action != null)
+ {
+ action(antecedent);
+ return;
+ }
+ var actionWithState = m_action as Action<Task<TAntecedentResult>, object>;
+ if (actionWithState != null)
+ {
+ actionWithState(antecedent, m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in ContinuationTaskFromResultTask");
+ }
+ }
+
+ // Task type used to implement: Task<TResult> ContinueWith(Func<Task<TAntecedentResult>,...>)
+ internal sealed class ContinuationResultTaskFromResultTask<TAntecedentResult, TResult> : Task<TResult>
+ {
+ private Task<TAntecedentResult> m_antecedent;
+
+ public ContinuationResultTaskFromResultTask(
+ Task<TAntecedentResult> antecedent, Delegate function, object state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, ref StackCrawlMark stackMark) :
+ base(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, internalOptions, null)
+ {
+ Contract.Requires(function is Func<Task<TAntecedentResult>, TResult> || function is Func<Task<TAntecedentResult>, object, TResult>,
+ "Invalid delegate type in ContinuationResultTaskFromResultTask");
+ m_antecedent = antecedent;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
+ /// </summary>
+ internal override void InnerInvoke()
+ {
+ // Get and null out the antecedent. This is crucial to avoid a memory
+ // leak with long chains of continuations.
+ var antecedent = m_antecedent;
+ Contract.Assert(antecedent != null,
+ "No antecedent was set for the ContinuationResultTaskFromResultTask.");
+ m_antecedent = null;
+
+ // Notify the debugger we're completing an asynchronous wait on a task
+ antecedent.NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // Invoke the delegate
+ Contract.Assert(m_action != null);
+ var func = m_action as Func<Task<TAntecedentResult>, TResult>;
+ if (func != null)
+ {
+ m_result = func(antecedent);
+ return;
+ }
+ var funcWithState = m_action as Func<Task<TAntecedentResult>, object, TResult>;
+ if (funcWithState != null)
+ {
+ m_result = funcWithState(antecedent, m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in ContinuationResultTaskFromResultTask");
+ }
+ }
+
+ // For performance reasons, we don't just have a single way of representing
+ // a continuation object. Rather, we have a hierarchy of types:
+ // - TaskContinuation: abstract base that provides a virtual Run method
+ // - StandardTaskContinuation: wraps a task,options,and scheduler, and overrides Run to process the task with that configuration
+ // - AwaitTaskContinuation: base for continuations created through TaskAwaiter; targets default scheduler by default
+ // - TaskSchedulerAwaitTaskContinuation: awaiting with a non-default TaskScheduler
+ // - SynchronizationContextAwaitTaskContinuation: awaiting with a "current" sync ctx
+
+ /// <summary>Represents a continuation.</summary>
+ internal abstract class TaskContinuation
+ {
+ /// <summary>Inlines or schedules the continuation.</summary>
+ /// <param name="completedTask">The antecedent task that has completed.</param>
+ /// <param name="canInlineContinuationTask">true if inlining is permitted; otherwise, false.</param>
+ internal abstract void Run(Task completedTask, bool bCanInlineContinuationTask);
+
+ /// <summary>Tries to run the task on the current thread, if possible; otherwise, schedules it.</summary>
+ /// <param name="task">The task to run</param>
+ /// <param name="needsProtection">
+ /// true if we need to protect against multiple threads racing to start/cancel the task; otherwise, false.
+ /// </param>
+ [SecuritySafeCritical]
+ protected static void InlineIfPossibleOrElseQueue(Task task, bool needsProtection)
+ {
+ Contract.Requires(task != null);
+ Contract.Assert(task.m_taskScheduler != null);
+
+ // Set the TASK_STATE_STARTED flag. This only needs to be done
+ // if the task may be canceled or if someone else has a reference to it
+ // that may try to execute it.
+ if (needsProtection)
+ {
+ if (!task.MarkStarted())
+ return; // task has been previously started or canceled. Stop processing.
+ }
+ else
+ {
+ task.m_stateFlags |= Task.TASK_STATE_STARTED;
+ }
+
+ // Try to inline it but queue if we can't
+ try
+ {
+ if (!task.m_taskScheduler.TryRunInline(task, taskWasPreviouslyQueued: false))
+ {
+ task.m_taskScheduler.InternalQueueTask(task);
+ }
+ }
+ catch (Exception e)
+ {
+ // Either TryRunInline() or QueueTask() threw an exception. Record the exception, marking the task as Faulted.
+ // However if it was a ThreadAbortException coming from TryRunInline we need to skip here,
+ // because it would already have been handled in Task.Execute()
+ if (!(e is ThreadAbortException &&
+ (task.m_stateFlags & Task.TASK_STATE_THREAD_WAS_ABORTED) != 0)) // this ensures TAEs from QueueTask will be wrapped in TSE
+ {
+ TaskSchedulerException tse = new TaskSchedulerException(e);
+ task.AddException(tse);
+ task.Finish(false);
+ }
+
+ // Don't re-throw.
+ }
+ }
+
+ internal abstract Delegate[] GetDelegateContinuationsForDebugger();
+
+ }
+
+ /// <summary>Provides the standard implementation of a task continuation.</summary>
+ internal class StandardTaskContinuation : TaskContinuation
+ {
+ /// <summary>The unstarted continuation task.</summary>
+ internal readonly Task m_task;
+ /// <summary>The options to use with the continuation task.</summary>
+ internal readonly TaskContinuationOptions m_options;
+ /// <summary>The task scheduler with which to run the continuation task.</summary>
+ private readonly TaskScheduler m_taskScheduler;
+
+ /// <summary>Initializes a new continuation.</summary>
+ /// <param name="task">The task to be activated.</param>
+ /// <param name="options">The continuation options.</param>
+ /// <param name="scheduler">The scheduler to use for the continuation.</param>
+ internal StandardTaskContinuation(Task task, TaskContinuationOptions options, TaskScheduler scheduler)
+ {
+ Contract.Requires(task != null, "TaskContinuation ctor: task is null");
+ Contract.Requires(scheduler != null, "TaskContinuation ctor: scheduler is null");
+ m_task = task;
+ m_options = options;
+ m_taskScheduler = scheduler;
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, m_task.Id, "Task.ContinueWith: " + ((Delegate)task.m_action).Method.Name, 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ Task.AddToActiveTasks(m_task);
+ }
+ }
+
+ /// <summary>Invokes the continuation for the target completion task.</summary>
+ /// <param name="completedTask">The completed task.</param>
+ /// <param name="bCanInlineContinuationTask">Whether the continuation can be inlined.</param>
+ internal override void Run(Task completedTask, bool bCanInlineContinuationTask)
+ {
+ Contract.Assert(completedTask != null);
+ Contract.Assert(completedTask.IsCompleted, "ContinuationTask.Run(): completedTask not completed");
+
+ // Check if the completion status of the task works with the desired
+ // activation criteria of the TaskContinuationOptions.
+ TaskContinuationOptions options = m_options;
+ bool isRightKind =
+ completedTask.IsRanToCompletion ?
+ (options & TaskContinuationOptions.NotOnRanToCompletion) == 0 :
+ (completedTask.IsCanceled ?
+ (options & TaskContinuationOptions.NotOnCanceled) == 0 :
+ (options & TaskContinuationOptions.NotOnFaulted) == 0);
+
+ // If the completion status is allowed, run the continuation.
+ Task continuationTask = m_task;
+ if (isRightKind)
+ {
+ //If the task was cancel before running (e.g a ContinueWhenAll with a cancelled caancelation token)
+ //we will still flow it to ScheduleAndStart() were it will check the status before running
+ //We check here to avoid faulty logs that contain a join event to an operation that was already set as completed.
+ if (!continuationTask.IsCanceled && AsyncCausalityTracer.LoggingOn)
+ {
+ // Log now that we are sure that this continuation is being ran
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, continuationTask.Id, CausalityRelation.AssignDelegate);
+ }
+ continuationTask.m_taskScheduler = m_taskScheduler;
+
+ // Either run directly or just queue it up for execution, depending
+ // on whether synchronous or asynchronous execution is wanted.
+ if (bCanInlineContinuationTask && // inlining is allowed by the caller
+ (options & TaskContinuationOptions.ExecuteSynchronously) != 0) // synchronous execution was requested by the continuation's creator
+ {
+ InlineIfPossibleOrElseQueue(continuationTask, needsProtection: true);
+ }
+ else
+ {
+ try { continuationTask.ScheduleAndStart(needsProtection: true); }
+ catch (TaskSchedulerException)
+ {
+ // No further action is necessary -- ScheduleAndStart() already transitioned the
+ // task to faulted. But we want to make sure that no exception is thrown from here.
+ }
+ }
+ }
+ // Otherwise, the final state of this task does not match the desired
+ // continuation activation criteria; cancel it to denote this.
+ else continuationTask.InternalCancel(false);
+ }
+
+ internal override Delegate[] GetDelegateContinuationsForDebugger()
+ {
+ if (m_task.m_action == null)
+ {
+ return m_task.GetDelegateContinuationsForDebugger();
+ }
+
+ return new Delegate[] { m_task.m_action as Delegate };
+ }
+ }
+
+ /// <summary>Task continuation for awaiting with a current synchronization context.</summary>
+ internal sealed class SynchronizationContextAwaitTaskContinuation : AwaitTaskContinuation
+ {
+ /// <summary>SendOrPostCallback delegate to invoke the action.</summary>
+ private readonly static SendOrPostCallback s_postCallback = state => ((Action)state)(); // can't use InvokeAction as it's SecurityCritical
+ /// <summary>Cached delegate for PostAction</summary>
+ [SecurityCritical]
+ private static ContextCallback s_postActionCallback;
+ /// <summary>The context with which to run the action.</summary>
+ private readonly SynchronizationContext m_syncContext;
+
+ /// <summary>Initializes the SynchronizationContextAwaitTaskContinuation.</summary>
+ /// <param name="context">The synchronization context with which to invoke the action. Must not be null.</param>
+ /// <param name="action">The action to invoke. Must not be null.</param>
+ /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
+ /// <param name="stackMark">The captured stack mark.</param>
+ [SecurityCritical]
+ internal SynchronizationContextAwaitTaskContinuation(
+ SynchronizationContext context, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) :
+ base(action, flowExecutionContext, ref stackMark)
+ {
+ Contract.Assert(context != null);
+ m_syncContext = context;
+ }
+
+ /// <summary>Inlines or schedules the continuation.</summary>
+ /// <param name="ignored">The antecedent task, which is ignored.</param>
+ /// <param name="canInlineContinuationTask">true if inlining is permitted; otherwise, false.</param>
+ [SecuritySafeCritical]
+ internal sealed override void Run(Task task, bool canInlineContinuationTask)
+ {
+ // If we're allowed to inline, run the action on this thread.
+ if (canInlineContinuationTask &&
+ m_syncContext == SynchronizationContext.CurrentNoFlow)
+ {
+ RunCallback(GetInvokeActionCallback(), m_action, ref Task.t_currentTask);
+ }
+ // Otherwise, Post the action back to the SynchronizationContext.
+ else
+ {
+ TplEtwProvider etwLog = TplEtwProvider.Log;
+ if (etwLog.IsEnabled())
+ {
+ m_continuationId = Task.NewId();
+ etwLog.AwaitTaskContinuationScheduled((task.ExecutingTaskScheduler ?? TaskScheduler.Default).Id, task.Id, m_continuationId);
+ }
+ RunCallback(GetPostActionCallback(), this, ref Task.t_currentTask);
+ }
+ // Any exceptions will be handled by RunCallback.
+ }
+
+ /// <summary>Calls InvokeOrPostAction(false) on the supplied SynchronizationContextAwaitTaskContinuation.</summary>
+ /// <param name="state">The SynchronizationContextAwaitTaskContinuation.</param>
+ [SecurityCritical]
+ private static void PostAction(object state)
+ {
+ var c = (SynchronizationContextAwaitTaskContinuation)state;
+
+ TplEtwProvider etwLog = TplEtwProvider.Log;
+ if (etwLog.TasksSetActivityIds && c.m_continuationId != 0)
+ {
+ c.m_syncContext.Post(s_postCallback, GetActionLogDelegate(c.m_continuationId, c.m_action));
+ }
+ else
+ {
+ c.m_syncContext.Post(s_postCallback, c.m_action); // s_postCallback is manually cached, as the compiler won't in a SecurityCritical method
+ }
+ }
+
+ private static Action GetActionLogDelegate(int continuationId, Action action)
+ {
+ return () =>
+ {
+ Guid savedActivityId;
+ Guid activityId = TplEtwProvider.CreateGuidForTaskID(continuationId);
+ System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out savedActivityId);
+ try { action(); }
+ finally { System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); }
+ };
+ }
+
+ /// <summary>Gets a cached delegate for the PostAction method.</summary>
+ /// <returns>
+ /// A delegate for PostAction, which expects a SynchronizationContextAwaitTaskContinuation
+ /// to be passed as state.
+ /// </returns>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [SecurityCritical]
+ private static ContextCallback GetPostActionCallback()
+ {
+ ContextCallback callback = s_postActionCallback;
+ if (callback == null) { s_postActionCallback = callback = PostAction; } // lazily initialize SecurityCritical delegate
+ return callback;
+ }
+ }
+
+ /// <summary>Task continuation for awaiting with a task scheduler.</summary>
+ internal sealed class TaskSchedulerAwaitTaskContinuation : AwaitTaskContinuation
+ {
+ /// <summary>The scheduler on which to run the action.</summary>
+ private readonly TaskScheduler m_scheduler;
+
+ /// <summary>Initializes the TaskSchedulerAwaitTaskContinuation.</summary>
+ /// <param name="scheduler">The task scheduler with which to invoke the action. Must not be null.</param>
+ /// <param name="action">The action to invoke. Must not be null.</param>
+ /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
+ /// <param name="stackMark">The captured stack mark.</param>
+ [SecurityCritical]
+ internal TaskSchedulerAwaitTaskContinuation(
+ TaskScheduler scheduler, Action action, bool flowExecutionContext, ref StackCrawlMark stackMark) :
+ base(action, flowExecutionContext, ref stackMark)
+ {
+ Contract.Assert(scheduler != null);
+ m_scheduler = scheduler;
+ }
+
+ /// <summary>Inlines or schedules the continuation.</summary>
+ /// <param name="ignored">The antecedent task, which is ignored.</param>
+ /// <param name="canInlineContinuationTask">true if inlining is permitted; otherwise, false.</param>
+ internal sealed override void Run(Task ignored, bool canInlineContinuationTask)
+ {
+ // If we're targeting the default scheduler, we can use the faster path provided by the base class.
+ if (m_scheduler == TaskScheduler.Default)
+ {
+ base.Run(ignored, canInlineContinuationTask);
+ }
+ else
+ {
+ // We permit inlining if the caller allows us to, and
+ // either we're on a thread pool thread (in which case we're fine running arbitrary code)
+ // or we're already on the target scheduler (in which case we'll just ask the scheduler
+ // whether it's ok to run here). We include the IsThreadPoolThread check here, whereas
+ // we don't in AwaitTaskContinuation.Run, since here it expands what's allowed as opposed
+ // to in AwaitTaskContinuation.Run where it restricts what's allowed.
+ bool inlineIfPossible = canInlineContinuationTask &&
+ (TaskScheduler.InternalCurrent == m_scheduler || Thread.CurrentThread.IsThreadPoolThread);
+
+ // Create the continuation task task. If we're allowed to inline, try to do so.
+ // The target scheduler may still deny us from executing on this thread, in which case this'll be queued.
+ var task = CreateTask(state => {
+ try { ((Action)state)(); }
+ catch (Exception exc) { ThrowAsyncIfNecessary(exc); }
+ }, m_action, m_scheduler);
+
+ if (inlineIfPossible)
+ {
+ InlineIfPossibleOrElseQueue(task, needsProtection: false);
+ }
+ else
+ {
+ // We need to run asynchronously, so just schedule the task.
+ try { task.ScheduleAndStart(needsProtection: false); }
+ catch (TaskSchedulerException) { } // No further action is necessary, as ScheduleAndStart already transitioned task to faulted
+ }
+ }
+ }
+ }
+
+ /// <summary>Base task continuation class used for await continuations.</summary>
+ internal class AwaitTaskContinuation : TaskContinuation, IThreadPoolWorkItem
+ {
+ /// <summary>The ExecutionContext with which to run the continuation.</summary>
+ private readonly ExecutionContext m_capturedContext;
+ /// <summary>The action to invoke.</summary>
+ protected readonly Action m_action;
+
+ protected int m_continuationId;
+
+ /// <summary>Initializes the continuation.</summary>
+ /// <param name="action">The action to invoke. Must not be null.</param>
+ /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
+ /// <param name="stackMark">The captured stack mark with which to construct an ExecutionContext.</param>
+ [SecurityCritical]
+ internal AwaitTaskContinuation(Action action, bool flowExecutionContext, ref StackCrawlMark stackMark)
+ {
+ Contract.Requires(action != null);
+ m_action = action;
+ if (flowExecutionContext)
+ {
+ m_capturedContext = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
+ }
+ }
+
+ /// <summary>Initializes the continuation.</summary>
+ /// <param name="action">The action to invoke. Must not be null.</param>
+ /// <param name="flowExecutionContext">Whether to capture and restore ExecutionContext.</param>
+ [SecurityCritical]
+ internal AwaitTaskContinuation(Action action, bool flowExecutionContext)
+ {
+ Contract.Requires(action != null);
+ m_action = action;
+ if (flowExecutionContext)
+ {
+ m_capturedContext = ExecutionContext.FastCapture();
+ }
+ }
+
+ /// <summary>Creates a task to run the action with the specified state on the specified scheduler.</summary>
+ /// <param name="action">The action to run. Must not be null.</param>
+ /// <param name="state">The state to pass to the action. Must not be null.</param>
+ /// <param name="scheduler">The scheduler to target.</param>
+ /// <returns>The created task.</returns>
+ protected Task CreateTask(Action<object> action, object state, TaskScheduler scheduler)
+ {
+ Contract.Requires(action != null);
+ Contract.Requires(scheduler != null);
+
+ return new Task(
+ action, state, null, default(CancellationToken),
+ TaskCreationOptions.None, InternalTaskOptions.QueuedByRuntime, scheduler)
+ {
+ CapturedContext = m_capturedContext
+ };
+ }
+
+ /// <summary>Inlines or schedules the continuation onto the default scheduler.</summary>
+ /// <param name="ignored">The antecedent task, which is ignored.</param>
+ /// <param name="canInlineContinuationTask">true if inlining is permitted; otherwise, false.</param>
+ [SecuritySafeCritical]
+ internal override void Run(Task task, bool canInlineContinuationTask)
+ {
+ // For the base AwaitTaskContinuation, we allow inlining if our caller allows it
+ // and if we're in a "valid location" for it. See the comments on
+ // IsValidLocationForInlining for more about what's valid. For performance
+ // reasons we would like to always inline, but we don't in some cases to avoid
+ // running arbitrary amounts of work in suspected "bad locations", like UI threads.
+ if (canInlineContinuationTask && IsValidLocationForInlining)
+ {
+ RunCallback(GetInvokeActionCallback(), m_action, ref Task.t_currentTask); // any exceptions from m_action will be handled by s_callbackRunAction
+ }
+ else
+ {
+ TplEtwProvider etwLog = TplEtwProvider.Log;
+ if (etwLog.IsEnabled())
+ {
+ m_continuationId = Task.NewId();
+ etwLog.AwaitTaskContinuationScheduled((task.ExecutingTaskScheduler ?? TaskScheduler.Default).Id, task.Id, m_continuationId);
+ }
+
+ // We couldn't inline, so now we need to schedule it
+ ThreadPool.UnsafeQueueCustomWorkItem(this, forceGlobal: false);
+ }
+ }
+
+ /// <summary>
+ /// Gets whether the current thread is an appropriate location to inline a continuation's execution.
+ /// </summary>
+ /// <remarks>
+ /// Returns whether SynchronizationContext is null and we're in the default scheduler.
+ /// If the await had a SynchronizationContext/TaskScheduler where it began and the
+ /// default/ConfigureAwait(true) was used, then we won't be on this path. If, however,
+ /// ConfigureAwait(false) was used, or the SynchronizationContext and TaskScheduler were
+ /// naturally null/Default, then we might end up here. If we do, we need to make sure
+ /// that we don't execute continuations in a place that isn't set up to handle them, e.g.
+ /// running arbitrary amounts of code on the UI thread. It would be "correct", but very
+ /// expensive, to always run the continuations asynchronously, incurring lots of context
+ /// switches and allocations and locks and the like. As such, we employ the heuristic
+ /// that if the current thread has a non-null SynchronizationContext or a non-default
+ /// scheduler, then we better not run arbitrary continuations here.
+ /// </remarks>
+ internal static bool IsValidLocationForInlining
+ {
+ get
+ {
+ // If there's a SynchronizationContext, we'll be conservative and say
+ // this is a bad location to inline.
+ var ctx = SynchronizationContext.CurrentNoFlow;
+ if (ctx != null && ctx.GetType() != typeof(SynchronizationContext)) return false;
+
+ // Similarly, if there's a non-default TaskScheduler, we'll be conservative
+ // and say this is a bad location to inline.
+ var sched = TaskScheduler.InternalCurrent;
+ return sched == null || sched == TaskScheduler.Default;
+ }
+ }
+
+ /// <summary>IThreadPoolWorkItem override, which is the entry function for this when the ThreadPool scheduler decides to run it.</summary>
+ [SecurityCritical]
+ void ExecuteWorkItemHelper()
+ {
+ var etwLog = TplEtwProvider.Log;
+ Guid savedActivityId = Guid.Empty;
+ if (etwLog.TasksSetActivityIds && m_continuationId != 0)
+ {
+ Guid activityId = TplEtwProvider.CreateGuidForTaskID(m_continuationId);
+ System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out savedActivityId);
+ }
+ try
+ {
+ // We're not inside of a task, so t_currentTask doesn't need to be specially maintained.
+ // We're on a thread pool thread with no higher-level callers, so exceptions can just propagate.
+
+ // If there's no execution context, just invoke the delegate.
+ if (m_capturedContext == null)
+ {
+ m_action();
+ }
+ // If there is an execution context, get the cached delegate and run the action under the context.
+ else
+ {
+ try
+ {
+ ExecutionContext.Run(m_capturedContext, GetInvokeActionCallback(), m_action, true);
+ }
+ finally { m_capturedContext.Dispose(); }
+ }
+ }
+ finally
+ {
+ if (etwLog.TasksSetActivityIds && m_continuationId != 0)
+ {
+ System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId);
+ }
+ }
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+ // inline the fast path
+ if (m_capturedContext == null && !TplEtwProvider.Log.IsEnabled()
+ )
+ {
+ m_action();
+ }
+ else
+ {
+ ExecuteWorkItemHelper();
+ }
+ }
+
+ /// <summary>
+ /// The ThreadPool calls this if a ThreadAbortException is thrown while trying to execute this workitem.
+ /// </summary>
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae) { /* nop */ }
+
+ /// <summary>Cached delegate that invokes an Action passed as an object parameter.</summary>
+ [SecurityCritical]
+ private static ContextCallback s_invokeActionCallback;
+
+ /// <summary>Runs an action provided as an object parameter.</summary>
+ /// <param name="state">The Action to invoke.</param>
+ [SecurityCritical]
+ private static void InvokeAction(object state) { ((Action)state)(); }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ [SecurityCritical]
+ protected static ContextCallback GetInvokeActionCallback()
+ {
+ ContextCallback callback = s_invokeActionCallback;
+ if (callback == null) { s_invokeActionCallback = callback = InvokeAction; } // lazily initialize SecurityCritical delegate
+ return callback;
+ }
+
+ /// <summary>Runs the callback synchronously with the provided state.</summary>
+ /// <param name="callback">The callback to run.</param>
+ /// <param name="state">The state to pass to the callback.</param>
+ /// <param name="currentTask">A reference to Task.t_currentTask.</param>
+ [SecurityCritical]
+ protected void RunCallback(ContextCallback callback, object state, ref Task currentTask)
+ {
+ Contract.Requires(callback != null);
+ Contract.Assert(currentTask == Task.t_currentTask);
+
+ // Pretend there's no current task, so that no task is seen as a parent
+ // and TaskScheduler.Current does not reflect false information
+ var prevCurrentTask = currentTask;
+ try
+ {
+ if (prevCurrentTask != null) currentTask = null;
+
+ // If there's no captured context, just run the callback directly.
+ if (m_capturedContext == null) callback(state);
+ // Otherwise, use the captured context to do so.
+ else ExecutionContext.Run(m_capturedContext, callback, state, true);
+ }
+ catch (Exception exc) // we explicitly do not request handling of dangerous exceptions like AVs
+ {
+ ThrowAsyncIfNecessary(exc);
+ }
+ finally
+ {
+ // Restore the current task information
+ if (prevCurrentTask != null) currentTask = prevCurrentTask;
+
+ // Clean up after the execution context, which is only usable once.
+ if (m_capturedContext != null) m_capturedContext.Dispose();
+ }
+ }
+
+ /// <summary>Invokes or schedules the action to be executed.</summary>
+ /// <param name="action">The action to invoke or queue.</param>
+ /// <param name="allowInlining">
+ /// true to allow inlining, or false to force the action to run asynchronously.
+ /// </param>
+ /// <param name="currentTask">
+ /// A reference to the t_currentTask thread static value.
+ /// This is passed by-ref rather than accessed in the method in order to avoid
+ /// unnecessary thread-static writes.
+ /// </param>
+ /// <remarks>
+ /// No ExecutionContext work is performed used. This method is only used in the
+ /// case where a raw Action continuation delegate was stored into the Task, which
+ /// only happens in Task.SetContinuationForAwait if execution context flow was disabled
+ /// via using TaskAwaiter.UnsafeOnCompleted or a similar path.
+ /// </remarks>
+ [SecurityCritical]
+ internal static void RunOrScheduleAction(Action action, bool allowInlining, ref Task currentTask)
+ {
+ Contract.Assert(currentTask == Task.t_currentTask);
+
+ // If we're not allowed to run here, schedule the action
+ if (!allowInlining || !IsValidLocationForInlining)
+ {
+ UnsafeScheduleAction(action, currentTask);
+ return;
+ }
+
+ // Otherwise, run it, making sure that t_currentTask is null'd out appropriately during the execution
+ Task prevCurrentTask = currentTask;
+ try
+ {
+ if (prevCurrentTask != null) currentTask = null;
+ action();
+ }
+ catch (Exception exception)
+ {
+ ThrowAsyncIfNecessary(exception);
+ }
+ finally
+ {
+ if (prevCurrentTask != null) currentTask = prevCurrentTask;
+ }
+ }
+
+ /// <summary>Schedules the action to be executed. No ExecutionContext work is performed used.</summary>
+ /// <param name="action">The action to invoke or queue.</param>
+ [SecurityCritical]
+ internal static void UnsafeScheduleAction(Action action, Task task)
+ {
+ AwaitTaskContinuation atc = new AwaitTaskContinuation(action, flowExecutionContext: false);
+
+ var etwLog = TplEtwProvider.Log;
+ if (etwLog.IsEnabled() && task != null)
+ {
+ atc.m_continuationId = Task.NewId();
+ etwLog.AwaitTaskContinuationScheduled((task.ExecutingTaskScheduler ?? TaskScheduler.Default).Id, task.Id, atc.m_continuationId);
+ }
+
+ ThreadPool.UnsafeQueueCustomWorkItem(atc, forceGlobal: false);
+ }
+
+ /// <summary>Throws the exception asynchronously on the ThreadPool.</summary>
+ /// <param name="exc">The exception to throw.</param>
+ protected static void ThrowAsyncIfNecessary(Exception exc)
+ {
+ // Awaits should never experience an exception (other than an TAE or ADUE),
+ // unless a malicious user is explicitly passing a throwing action into the TaskAwaiter.
+ // We don't want to allow the exception to propagate on this stack, as it'll emerge in random places,
+ // and we can't fail fast, as that would allow for elevation of privilege.
+ //
+ // If unhandled error reporting APIs are available use those, otherwise since this
+ // would have executed on the thread pool otherwise, let it propagate there.
+
+ if (!(exc is ThreadAbortException || exc is AppDomainUnloadedException))
+ {
+#if FEATURE_COMINTEROP
+ if (!WindowsRuntimeMarshal.ReportUnhandledError(exc))
+#endif // FEATURE_COMINTEROP
+ {
+ var edi = ExceptionDispatchInfo.Capture(exc);
+ ThreadPool.QueueUserWorkItem(s => ((ExceptionDispatchInfo)s).Throw(), edi);
+ }
+ }
+ }
+
+ internal override Delegate[] GetDelegateContinuationsForDebugger()
+ {
+ Contract.Assert(m_action != null);
+ return new Delegate[] { AsyncMethodBuilderCore.TryGetStateMachineForDebugger(m_action) };
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs
new file mode 100644
index 0000000000..198db8e15c
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskExceptionHolder.cs
@@ -0,0 +1,424 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// An abstraction for holding and aggregating exceptions.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+// Disable the "reference to volatile field not treated as volatile" error.
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics.Contracts;
+ using System.Runtime.ExceptionServices;
+ using System.Security;
+
+ /// <summary>
+ /// An exception holder manages a list of exceptions for one particular task.
+ /// It offers the ability to aggregate, but more importantly, also offers intrinsic
+ /// support for propagating unhandled exceptions that are never observed. It does
+ /// this by aggregating and throwing if the holder is ever GC'd without the holder's
+ /// contents ever having been requested (e.g. by a Task.Wait, Task.get_Exception, etc).
+ /// This behavior is prominent in .NET 4 but is suppressed by default beyond that release.
+ /// </summary>
+ internal class TaskExceptionHolder
+ {
+ /// <summary>Whether we should propagate exceptions on the finalizer.</summary>
+ private readonly static bool s_failFastOnUnobservedException = ShouldFailFastOnUnobservedException();
+ /// <summary>Whether the AppDomain has started to unload.</summary>
+ private static volatile bool s_domainUnloadStarted;
+ /// <summary>An event handler used to notify of domain unload.</summary>
+ private static volatile EventHandler s_adUnloadEventHandler;
+
+ /// <summary>The task with which this holder is associated.</summary>
+ private readonly Task m_task;
+ /// <summary>
+ /// The lazily-initialized list of faulting exceptions. Volatile
+ /// so that it may be read to determine whether any exceptions were stored.
+ /// </summary>
+ private volatile List<ExceptionDispatchInfo> m_faultExceptions;
+ /// <summary>An exception that triggered the task to cancel.</summary>
+ private ExceptionDispatchInfo m_cancellationException;
+ /// <summary>Whether the holder was "observed" and thus doesn't cause finalization behavior.</summary>
+ private volatile bool m_isHandled;
+
+ /// <summary>
+ /// Creates a new holder; it will be registered for finalization.
+ /// </summary>
+ /// <param name="task">The task this holder belongs to.</param>
+ internal TaskExceptionHolder(Task task)
+ {
+ Contract.Requires(task != null, "Expected a non-null task.");
+ m_task = task;
+ EnsureADUnloadCallbackRegistered();
+ }
+
+ [SecuritySafeCritical]
+ private static bool ShouldFailFastOnUnobservedException()
+ {
+ bool shouldFailFast = false;
+ #if !FEATURE_CORECLR
+ shouldFailFast = System.CLRConfig.CheckThrowUnobservedTaskExceptions();
+ #endif
+ return shouldFailFast;
+ }
+
+ private static void EnsureADUnloadCallbackRegistered()
+ {
+ if (s_adUnloadEventHandler == null &&
+ Interlocked.CompareExchange( ref s_adUnloadEventHandler,
+ AppDomainUnloadCallback,
+ null) == null)
+ {
+ AppDomain.CurrentDomain.DomainUnload += s_adUnloadEventHandler;
+ }
+ }
+
+ private static void AppDomainUnloadCallback(object sender, EventArgs e)
+ {
+ s_domainUnloadStarted = true;
+ }
+
+ /// <summary>
+ /// A finalizer that repropagates unhandled exceptions.
+ /// </summary>
+ ~TaskExceptionHolder()
+ {
+ // Raise unhandled exceptions only when we know that neither the process or nor the appdomain is being torn down.
+ // We need to do this filtering because all TaskExceptionHolders will be finalized during shutdown or unload
+ // regardles of reachability of the task (i.e. even if the user code was about to observe the task's exception),
+ // which can otherwise lead to spurious crashes during shutdown.
+ if (m_faultExceptions != null && !m_isHandled &&
+ !Environment.HasShutdownStarted && !AppDomain.CurrentDomain.IsFinalizingForUnload() && !s_domainUnloadStarted)
+ {
+ // We don't want to crash the finalizer thread if any ThreadAbortExceptions
+ // occur in the list or in any nested AggregateExceptions.
+ // (Don't rethrow ThreadAbortExceptions.)
+ foreach (ExceptionDispatchInfo edi in m_faultExceptions)
+ {
+ var exp = edi.SourceException;
+ AggregateException aggExp = exp as AggregateException;
+ if (aggExp != null)
+ {
+ AggregateException flattenedAggExp = aggExp.Flatten();
+ foreach (Exception innerExp in flattenedAggExp.InnerExceptions)
+ {
+ if (innerExp is ThreadAbortException)
+ return;
+ }
+ }
+ else if (exp is ThreadAbortException)
+ {
+ return;
+ }
+ }
+
+ // We will only propagate if this is truly unhandled. The reason this could
+ // ever occur is somewhat subtle: if a Task's exceptions are observed in some
+ // other finalizer, and the Task was finalized before the holder, the holder
+ // will have been marked as handled before even getting here.
+
+ // Give users a chance to keep this exception from crashing the process
+
+ // First, publish the unobserved exception and allow users to observe it
+ AggregateException exceptionToThrow = new AggregateException(
+ Environment.GetResourceString("TaskExceptionHolder_UnhandledException"),
+ m_faultExceptions);
+ UnobservedTaskExceptionEventArgs ueea = new UnobservedTaskExceptionEventArgs(exceptionToThrow);
+ TaskScheduler.PublishUnobservedTaskException(m_task, ueea);
+
+ // Now, if we are still unobserved and we're configured to crash on unobserved, throw the exception.
+ // We need to publish the event above even if we're not going to crash, hence
+ // why this check doesn't come at the beginning of the method.
+ if (s_failFastOnUnobservedException && !ueea.m_observed)
+ {
+ throw exceptionToThrow;
+ }
+ }
+ }
+
+ /// <summary>Gets whether the exception holder is currently storing any exceptions for faults.</summary>
+ internal bool ContainsFaultList { get { return m_faultExceptions != null; } }
+
+ /// <summary>
+ /// Add an exception to the holder. This will ensure the holder is
+ /// in the proper state (handled/unhandled) depending on the list's contents.
+ /// </summary>
+ /// <param name="exceptionObject">
+ /// An exception object (either an Exception, an ExceptionDispatchInfo,
+ /// an IEnumerable{Exception}, or an IEnumerable{ExceptionDispatchInfo})
+ /// to add to the list.
+ /// </param>
+ /// <remarks>
+ /// Must be called under lock.
+ /// </remarks>
+ internal void Add(object exceptionObject)
+ {
+ Add(exceptionObject, representsCancellation: false);
+ }
+
+ /// <summary>
+ /// Add an exception to the holder. This will ensure the holder is
+ /// in the proper state (handled/unhandled) depending on the list's contents.
+ /// </summary>
+ /// <param name="representsCancellation">
+ /// Whether the exception represents a cancellation request (true) or a fault (false).
+ /// </param>
+ /// <param name="exceptionObject">
+ /// An exception object (either an Exception, an ExceptionDispatchInfo,
+ /// an IEnumerable{Exception}, or an IEnumerable{ExceptionDispatchInfo})
+ /// to add to the list.
+ /// </param>
+ /// <remarks>
+ /// Must be called under lock.
+ /// </remarks>
+ internal void Add(object exceptionObject, bool representsCancellation)
+ {
+ Contract.Requires(exceptionObject != null, "TaskExceptionHolder.Add(): Expected a non-null exceptionObject");
+ Contract.Requires(
+ exceptionObject is Exception || exceptionObject is IEnumerable<Exception> ||
+ exceptionObject is ExceptionDispatchInfo || exceptionObject is IEnumerable<ExceptionDispatchInfo>,
+ "TaskExceptionHolder.Add(): Expected Exception, IEnumerable<Exception>, ExceptionDispatchInfo, or IEnumerable<ExceptionDispatchInfo>");
+
+ if (representsCancellation) SetCancellationException(exceptionObject);
+ else AddFaultException(exceptionObject);
+ }
+
+ /// <summary>Sets the cancellation exception.</summary>
+ /// <param name="exceptionObject">The cancellation exception.</param>
+ /// <remarks>
+ /// Must be called under lock.
+ /// </remarks>
+ private void SetCancellationException(object exceptionObject)
+ {
+ Contract.Requires(exceptionObject != null, "Expected exceptionObject to be non-null.");
+
+ Contract.Assert(m_cancellationException == null,
+ "Expected SetCancellationException to be called only once.");
+ // Breaking this assumption will overwrite a previously OCE,
+ // and implies something may be wrong elsewhere, since there should only ever be one.
+
+ Contract.Assert(m_faultExceptions == null,
+ "Expected SetCancellationException to be called before any faults were added.");
+ // Breaking this assumption shouldn't hurt anything here, but it implies something may be wrong elsewhere.
+ // If this changes, make sure to only conditionally mark as handled below.
+
+ // Store the cancellation exception
+ var oce = exceptionObject as OperationCanceledException;
+ if (oce != null)
+ {
+ m_cancellationException = ExceptionDispatchInfo.Capture(oce);
+ }
+ else
+ {
+ var edi = exceptionObject as ExceptionDispatchInfo;
+ Contract.Assert(edi != null && edi.SourceException is OperationCanceledException,
+ "Expected an OCE or an EDI that contained an OCE");
+ m_cancellationException = edi;
+ }
+
+ // This is just cancellation, and there are no faults, so mark the holder as handled.
+ MarkAsHandled(false);
+ }
+
+ /// <summary>Adds the exception to the fault list.</summary>
+ /// <param name="exceptionObject">The exception to store.</param>
+ /// <remarks>
+ /// Must be called under lock.
+ /// </remarks>
+ private void AddFaultException(object exceptionObject)
+ {
+ Contract.Requires(exceptionObject != null, "AddFaultException(): Expected a non-null exceptionObject");
+
+ // Initialize the exceptions list if necessary. The list should be non-null iff it contains exceptions.
+ var exceptions = m_faultExceptions;
+ if (exceptions == null) m_faultExceptions = exceptions = new List<ExceptionDispatchInfo>(1);
+ else Contract.Assert(exceptions.Count > 0, "Expected existing exceptions list to have > 0 exceptions.");
+
+ // Handle Exception by capturing it into an ExceptionDispatchInfo and storing that
+ var exception = exceptionObject as Exception;
+ if (exception != null)
+ {
+ exceptions.Add(ExceptionDispatchInfo.Capture(exception));
+ }
+ else
+ {
+ // Handle ExceptionDispatchInfo by storing it into the list
+ var edi = exceptionObject as ExceptionDispatchInfo;
+ if (edi != null)
+ {
+ exceptions.Add(edi);
+ }
+ else
+ {
+ // Handle enumerables of exceptions by capturing each of the contained exceptions into an EDI and storing it
+ var exColl = exceptionObject as IEnumerable<Exception>;
+ if (exColl != null)
+ {
+#if DEBUG
+ int numExceptions = 0;
+#endif
+ foreach (var exc in exColl)
+ {
+#if DEBUG
+ Contract.Assert(exc != null, "No exceptions should be null");
+ numExceptions++;
+#endif
+ exceptions.Add(ExceptionDispatchInfo.Capture(exc));
+ }
+#if DEBUG
+ Contract.Assert(numExceptions > 0, "Collection should contain at least one exception.");
+#endif
+ }
+ else
+ {
+ // Handle enumerables of EDIs by storing them directly
+ var ediColl = exceptionObject as IEnumerable<ExceptionDispatchInfo>;
+ if (ediColl != null)
+ {
+ exceptions.AddRange(ediColl);
+#if DEBUG
+ Contract.Assert(exceptions.Count > 0, "There should be at least one dispatch info.");
+ foreach(var tmp in exceptions)
+ {
+ Contract.Assert(tmp != null, "No dispatch infos should be null");
+ }
+#endif
+ }
+ // Anything else is a programming error
+ else
+ {
+ throw new ArgumentException(Environment.GetResourceString("TaskExceptionHolder_UnknownExceptionType"), "exceptionObject");
+ }
+ }
+ }
+ }
+
+
+ // If all of the exceptions are ThreadAbortExceptions and/or
+ // AppDomainUnloadExceptions, we do not want the finalization
+ // probe to propagate them, so we consider the holder to be
+ // handled. If a subsequent exception comes in of a different
+ // kind, we will reactivate the holder.
+ for (int i = 0; i < exceptions.Count; i++)
+ {
+ var t = exceptions[i].SourceException.GetType();
+ if (t != typeof(ThreadAbortException) && t != typeof(AppDomainUnloadedException))
+ {
+ MarkAsUnhandled();
+ break;
+ }
+ else if (i == exceptions.Count - 1)
+ {
+ MarkAsHandled(false);
+ }
+ }
+ }
+
+ /// <summary>
+ /// A private helper method that ensures the holder is considered
+ /// unhandled, i.e. it is registered for finalization.
+ /// </summary>
+ private void MarkAsUnhandled()
+ {
+ // If a thread partially observed this thread's exceptions, we
+ // should revert back to "not handled" so that subsequent exceptions
+ // must also be seen. Otherwise, some could go missing. We also need
+ // to reregister for finalization.
+ if (m_isHandled)
+ {
+ GC.ReRegisterForFinalize(this);
+ m_isHandled = false;
+ }
+ }
+
+ /// <summary>
+ /// A private helper method that ensures the holder is considered
+ /// handled, i.e. it is not registered for finalization.
+ /// </summary>
+ /// <param name="calledFromFinalizer">Whether this is called from the finalizer thread.</param>
+ internal void MarkAsHandled(bool calledFromFinalizer)
+ {
+ if (!m_isHandled)
+ {
+ if (!calledFromFinalizer)
+ {
+ GC.SuppressFinalize(this);
+ }
+
+ m_isHandled = true;
+ }
+ }
+
+ /// <summary>
+ /// Allocates a new aggregate exception and adds the contents of the list to
+ /// it. By calling this method, the holder assumes exceptions to have been
+ /// "observed", such that the finalization check will be subsequently skipped.
+ /// </summary>
+ /// <param name="calledFromFinalizer">Whether this is being called from a finalizer.</param>
+ /// <param name="includeThisException">An extra exception to be included (optionally).</param>
+ /// <returns>The aggregate exception to throw.</returns>
+ internal AggregateException CreateExceptionObject(bool calledFromFinalizer, Exception includeThisException)
+ {
+ var exceptions = m_faultExceptions;
+ Contract.Assert(exceptions != null, "Expected an initialized list.");
+ Contract.Assert(exceptions.Count > 0, "Expected at least one exception.");
+
+ // Mark as handled and aggregate the exceptions.
+ MarkAsHandled(calledFromFinalizer);
+
+ // If we're only including the previously captured exceptions,
+ // return them immediately in an aggregate.
+ if (includeThisException == null)
+ return new AggregateException(exceptions);
+
+ // Otherwise, the caller wants a specific exception to be included,
+ // so return an aggregate containing that exception and the rest.
+ Exception[] combinedExceptions = new Exception[exceptions.Count + 1];
+ for (int i = 0; i < combinedExceptions.Length - 1; i++)
+ {
+ combinedExceptions[i] = exceptions[i].SourceException;
+ }
+ combinedExceptions[combinedExceptions.Length - 1] = includeThisException;
+ return new AggregateException(combinedExceptions);
+ }
+
+ /// <summary>
+ /// Wraps the exception dispatch infos into a new read-only collection. By calling this method,
+ /// the holder assumes exceptions to have been "observed", such that the finalization
+ /// check will be subsequently skipped.
+ /// </summary>
+ internal ReadOnlyCollection<ExceptionDispatchInfo> GetExceptionDispatchInfos()
+ {
+ var exceptions = m_faultExceptions;
+ Contract.Assert(exceptions != null, "Expected an initialized list.");
+ Contract.Assert(exceptions.Count > 0, "Expected at least one exception.");
+ MarkAsHandled(false);
+ return new ReadOnlyCollection<ExceptionDispatchInfo>(exceptions);
+ }
+
+ /// <summary>
+ /// Gets the ExceptionDispatchInfo representing the singular exception
+ /// that was the cause of the task's cancellation.
+ /// </summary>
+ /// <returns>
+ /// The ExceptionDispatchInfo for the cancellation exception. May be null.
+ /// </returns>
+ internal ExceptionDispatchInfo GetCancellationExceptionDispatchInfo()
+ {
+ var edi = m_cancellationException;
+ Contract.Assert(edi == null || edi.SourceException is OperationCanceledException,
+ "Expected the EDI to be for an OperationCanceledException");
+ return edi;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs
new file mode 100644
index 0000000000..52b471628a
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskFactory.cs
@@ -0,0 +1,3206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// There are a plethora of common patterns for which Tasks are created. TaskFactory encodes
+// these patterns into helper methods. These helpers also pick up default configuration settings
+// applicable to the entire factory and configurable through its constructors.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Security;
+using System.Security.Permissions;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides support for creating and scheduling
+ /// <see cref="T:System.Threading.Tasks.Task">Tasks</see>.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// There are many common patterns for which tasks are relevant. The <see cref="TaskFactory"/>
+ /// class encodes some of these patterns into methods that pick up default settings, which are
+ /// configurable through its constructors.
+ /// </para>
+ /// <para>
+ /// A default instance of <see cref="TaskFactory"/> is available through the
+ /// <see cref="System.Threading.Tasks.Task.Factory">Task.Factory</see> property.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class TaskFactory
+ {
+ // member variables
+ private CancellationToken m_defaultCancellationToken;
+ private TaskScheduler m_defaultScheduler;
+ private TaskCreationOptions m_defaultCreationOptions;
+ private TaskContinuationOptions m_defaultContinuationOptions;
+
+
+ private TaskScheduler DefaultScheduler
+ {
+ get
+ {
+ if (m_defaultScheduler == null) return TaskScheduler.Current;
+ else return m_defaultScheduler;
+ }
+ }
+
+ // sister method to above property -- avoids a TLS lookup
+ private TaskScheduler GetDefaultScheduler(Task currTask)
+ {
+ if (m_defaultScheduler != null) return m_defaultScheduler;
+ else if ((currTask != null)
+ && ((currTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
+ )
+ return currTask.ExecutingTaskScheduler;
+ else return TaskScheduler.Default;
+ }
+
+ /* Constructors */
+
+ // ctor parameters provide defaults for the factory, which can be overridden by options provided to
+ // specific calls on the factory
+
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory"/> instance with the default configuration.
+ /// </summary>
+ /// <remarks>
+ /// This constructor creates a <see cref="TaskFactory"/> instance with a default configuration. The
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory()
+ : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// while calling the factory methods.</param>
+ /// <remarks>
+ /// This constructor creates a <see cref="TaskFactory"/> instance with a default configuration. The
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(CancellationToken cancellationToken)
+ : this(cancellationToken, TaskCreationOptions.None, TaskContinuationOptions.None, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="scheduler">
+ /// The <see cref="System.Threading.Tasks.TaskScheduler">
+ /// TaskScheduler</see> to use to schedule any tasks created with this TaskFactory. A null value
+ /// indicates that the current TaskScheduler should be used.
+ /// </param>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to
+ /// <see cref="System.Threading.Tasks.TaskCreationOptions.None">TaskCreationOptions.None</see>, the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.None">TaskContinuationOptions.None</see>,
+ /// and the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is
+ /// initialized to <paramref name="scheduler"/>, unless it's null, in which case the property is
+ /// initialized to the current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(TaskScheduler scheduler) // null means to use TaskScheduler.Current
+ : this(default(CancellationToken), TaskCreationOptions.None, TaskContinuationOptions.None, scheduler)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="creationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
+ /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory.
+ /// </param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
+ /// argument specifies an invalid value.
+ /// </exception>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
+ /// the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
+ /// name="continuationOptions"/>, and the <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to the
+ /// current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions)
+ : this(default(CancellationToken), creationOptions, continuationOptions, null)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a <see cref="TaskFactory"/> instance with the specified configuration.
+ /// </summary>
+ /// <param name="cancellationToken">The default <see cref="CancellationToken"/> that will be assigned
+ /// to tasks created by this <see cref="TaskFactory"/> unless another CancellationToken is explicitly specified
+ /// while calling the factory methods.</param>
+ /// <param name="creationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskCreationOptions">
+ /// TaskCreationOptions</see> to use when creating tasks with this TaskFactory.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// The default <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> to use when creating continuation tasks with this TaskFactory.
+ /// </param>
+ /// <param name="scheduler">
+ /// The default <see cref="System.Threading.Tasks.TaskScheduler">
+ /// TaskScheduler</see> to use to schedule any Tasks created with this TaskFactory. A null value
+ /// indicates that TaskScheduler.Current should be used.
+ /// </param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument or the <paramref name="continuationOptions"/>
+ /// argumentspecifies an invalid value.
+ /// </exception>
+ /// <remarks>
+ /// With this constructor, the
+ /// <see cref="TaskCreationOptions"/> property is initialized to <paramref name="creationOptions"/>,
+ /// the
+ /// <see cref="TaskContinuationOptions"/> property is initialized to <paramref
+ /// name="continuationOptions"/>, and the <see
+ /// cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> property is initialized to
+ /// <paramref name="scheduler"/>, unless it's null, in which case the property is initialized to the
+ /// current scheduler (see <see
+ /// cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>).
+ /// </remarks>
+ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ CheckMultiTaskContinuationOptions(continuationOptions);
+ CheckCreationOptions(creationOptions);
+
+ m_defaultCancellationToken = cancellationToken;
+ m_defaultScheduler = scheduler;
+ m_defaultCreationOptions = creationOptions;
+ m_defaultContinuationOptions = continuationOptions;
+ }
+
+ [ContractArgumentValidatorAttribute]
+ internal static void CheckCreationOptions(TaskCreationOptions creationOptions)
+ {
+ // Check for validity of options
+ if ((creationOptions &
+ ~(TaskCreationOptions.AttachedToParent |
+ TaskCreationOptions.DenyChildAttach |
+ TaskCreationOptions.HideScheduler |
+ TaskCreationOptions.LongRunning |
+ TaskCreationOptions.PreferFairness |
+ TaskCreationOptions.RunContinuationsAsynchronously)) != 0)
+ {
+ throw new ArgumentOutOfRangeException("creationOptions");
+ }
+ Contract.EndContractBlock();
+ }
+
+ /* Properties */
+
+ /// <summary>
+ /// Gets the default <see cref="System.Threading.CancellationToken">CancellationToken</see> of this
+ /// TaskFactory.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default <see cref="CancellationToken"/> that will be assigned to all
+ /// tasks created by this factory unless another CancellationToken value is explicitly specified
+ /// during the call to the factory methods.
+ /// </remarks>
+ public CancellationToken CancellationToken { get { return m_defaultCancellationToken; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> of this
+ /// TaskFactory.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default scheduler for this factory. It will be used to schedule all
+ /// tasks unless another scheduler is explicitly specified during calls to this factory's methods.
+ /// If null, <see cref="System.Threading.Tasks.TaskScheduler.Current">TaskScheduler.Current</see>
+ /// will be used.
+ /// </remarks>
+ public TaskScheduler Scheduler { get { return m_defaultScheduler; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions
+ /// </see> value of this TaskFactory.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default creation options for this factory. They will be used to create all
+ /// tasks unless other options are explicitly specified during calls to this factory's methods.
+ /// </remarks>
+ public TaskCreationOptions CreationOptions { get { return m_defaultCreationOptions; } }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskCreationOptions">TaskContinuationOptions
+ /// </see> value of this TaskFactory.
+ /// </summary>
+ /// <remarks>
+ /// This property returns the default continuation options for this factory. They will be used to create
+ /// all continuation tasks unless other options are explicitly specified during calls to this factory's methods.
+ /// </remarks>
+ public TaskContinuationOptions ContinuationOptions { get { return m_defaultContinuationOptions; } }
+
+ //
+ // StartNew methods
+ //
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
+ /// and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However,
+ /// unless creation and scheduling must be separated, StartNew is the recommended
+ /// approach for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action action)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask),
+ m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors
+ /// and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution. However,
+ /// unless creation and scheduling must be separated, StartNew is the recommended
+ /// approach for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action action, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, null, cancellationToken, GetDefaultScheduler(currTask),
+ m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action action, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, null, m_defaultCancellationToken, GetDefaultScheduler(currTask), creationOptions,
+ InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task.InternalStartNew(
+ Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions,
+ InternalTaskOptions.None, ref stackMark);
+ }
+
+ // Internal version includes InternalTaskOptions for Parallel.Invoke() support.
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ internal Task StartNew(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task.InternalStartNew(
+ Task.InternalCurrentIfAttached(creationOptions), action, null, cancellationToken, scheduler, creationOptions, internalOptions, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="action"/>
+ /// delegate.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action<Object> action, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
+ m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="action"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, state, cancellationToken, GetDefaultScheduler(currTask),
+ m_defaultCreationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="action"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action<Object> action, Object state, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task.InternalStartNew(currTask, action, state, m_defaultCancellationToken, GetDefaultScheduler(currTask),
+ creationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task">Task</see>.
+ /// </summary>
+ /// <param name="action">The action delegate to execute asynchronously.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="action"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task">Task.</see></param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="action"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and
+ /// then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task StartNew(Action<Object> action, Object state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task.InternalStartNew(
+ Task.InternalCurrentIfAttached(creationOptions), action, state, cancellationToken, scheduler,
+ creationOptions, InternalTaskOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<TResult> function)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, cancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<TResult> function, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, m_defaultCancellationToken,
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
+ /// Task{TResult}</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(
+ Task.InternalCurrentIfAttached(creationOptions), function, cancellationToken,
+ creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new <see cref="Task"/></param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, cancellationToken,
+ m_defaultCreationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Task currTask = Task.InternalCurrent;
+ return Task<TResult>.StartNew(currTask, function, state, m_defaultCancellationToken,
+ creationOptions, InternalTaskOptions.None, GetDefaultScheduler(currTask), ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates and starts a <see cref="T:System.Threading.Tasks.Task{TResult}"/>.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="function">A function delegate that returns the future result to be available through
+ /// the <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="function"/>
+ /// delegate.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">A TaskCreationOptions value that controls the behavior of the
+ /// created
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <param name="scheduler">The <see
+ /// cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created <see cref="T:System.Threading.Tasks.Task{TResult}">
+ /// Task{TResult}</see>.</param>
+ /// <returns>The started <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="function"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the <paramref
+ /// name="scheduler"/>
+ /// argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling StartNew is functionally equivalent to creating a <see cref="Task{TResult}"/> using one
+ /// of its constructors and then calling
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see> to schedule it for execution.
+ /// However, unless creation and scheduling must be separated, StartNew is the recommended approach
+ /// for both simplicity and performance.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> StartNew<TResult>(Func<Object, TResult> function, Object state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return Task<TResult>.StartNew(
+ Task.InternalCurrentIfAttached(creationOptions), function, state, cancellationToken,
+ creationOptions, InternalTaskOptions.None, scheduler, ref stackMark);
+ }
+
+ //
+ // FromAsync methods
+ //
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action
+ /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The action delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
+ /// operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task FromAsync(
+ IAsyncResult asyncResult,
+ Action<IAsyncResult> endMethod)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsync(asyncResult, endMethod, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action
+ /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The action delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
+ /// operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task FromAsync(
+ IAsyncResult asyncResult,
+ Action<IAsyncResult> endMethod,
+ TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsync(asyncResult, endMethod, creationOptions, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that executes an end method action
+ /// when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The action delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the task that executes the end method.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the asynchronous
+ /// operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task FromAsync(
+ IAsyncResult asyncResult,
+ Action<IAsyncResult> endMethod,
+ TaskCreationOptions creationOptions,
+ TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return FromAsync(asyncResult, endMethod, creationOptions, scheduler, ref stackMark);
+ }
+
+ // private version that supports StackCrawlMark.
+ private Task FromAsync(
+ IAsyncResult asyncResult,
+ Action<IAsyncResult> endMethod,
+ TaskCreationOptions creationOptions,
+ TaskScheduler scheduler,
+ ref StackCrawlMark stackMark)
+ {
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl(asyncResult, null, endMethod, creationOptions, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ object state)
+ {
+ return FromAsync(beginMethod, endMethod, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1>(
+ Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1,
+ object state)
+ {
+ return FromAsync(beginMethod, endMethod, arg1, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1>(
+ Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1, TArg2>(
+ Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1, TArg2 arg2, object state)
+ {
+ return FromAsync(beginMethod, endMethod, arg1, arg2, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1, TArg2>(
+ Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1, TArg2, TArg3>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ {
+ return FromAsync(beginMethod, endMethod, arg1, arg2, arg3, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task">Task</see> that represents a pair of begin
+ /// and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task FromAsync<TArg1, TArg2, TArg3>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Action<IAsyncResult> endMethod,
+ TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<VoidTaskResult>.FromAsyncImpl<TArg1, TArg2, TArg3>(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions);
+ }
+
+ //
+ // Additional FromAsync() overloads used for inferencing convenience
+ //
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync<TResult>(
+ IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, m_defaultCreationOptions, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync<TResult>(
+ IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that executes an end
+ /// method function when a specified <see cref="T:System.IAsyncResult">IAsyncResult</see> completes.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="asyncResult">The IAsyncResult whose completion should trigger the processing of the
+ /// <paramref name="endMethod"/>.</param>
+ /// <param name="endMethod">The function delegate that processes the completed <paramref
+ /// name="asyncResult"/>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the task that executes the end method.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="asyncResult"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>A <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents the
+ /// asynchronous operation.</returns>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> FromAsync<TResult>(
+ IAsyncResult asyncResult, Func<IAsyncResult, TResult> endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.FromAsyncImpl(asyncResult, endMethod, null, creationOptions, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TResult>(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object state)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TResult>(
+ Func<AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TResult>(
+ Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TResult>(Func<TArg1, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TResult>(Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TResult>(
+ Func<TArg1, TArg2, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, m_defaultCreationOptions);
+ }
+
+ /// <summary>
+ /// Creates a <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that represents a pair of
+ /// begin and end methods that conform to the Asynchronous Programming Model pattern.
+ /// </summary>
+ /// <typeparam name="TArg1">The type of the first argument passed to the <paramref
+ /// name="beginMethod"/> delegate.</typeparam>
+ /// <typeparam name="TArg2">The type of the second argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TArg3">The type of the third argument passed to <paramref name="beginMethod"/>
+ /// delegate.</typeparam>
+ /// <typeparam name="TResult">The type of the result available through the
+ /// <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.
+ /// </typeparam>
+ /// <param name="beginMethod">The delegate that begins the asynchronous operation.</param>
+ /// <param name="endMethod">The delegate that ends the asynchronous operation.</param>
+ /// <param name="arg1">The first argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg2">The second argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="arg3">The third argument passed to the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <param name="creationOptions">The TaskCreationOptions value that controls the behavior of the
+ /// created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="state">An object containing data to be used by the <paramref name="beginMethod"/>
+ /// delegate.</param>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="beginMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="endMethod"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="creationOptions"/> argument specifies an invalid TaskCreationOptions
+ /// value.</exception>
+ /// <returns>The created <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see> that
+ /// represents the asynchronous operation.</returns>
+ /// <remarks>
+ /// This method throws any exceptions thrown by the <paramref name="beginMethod"/>.
+ /// </remarks>
+ public Task<TResult> FromAsync<TArg1, TArg2, TArg3, TResult>(
+ Func<TArg1, TArg2, TArg3, AsyncCallback, object, IAsyncResult> beginMethod,
+ Func<IAsyncResult, TResult> endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object state, TaskCreationOptions creationOptions)
+ {
+ return TaskFactory<TResult>.FromAsyncImpl(beginMethod, endMethod, null, arg1, arg2, arg3, state, creationOptions);
+ }
+
+ /// <summary>
+ /// Check validity of options passed to FromAsync method
+ /// </summary>
+ /// <param name="creationOptions">The options to be validated.</param>
+ /// <param name="hasBeginMethod">determines type of FromAsync method that called this method</param>
+ internal static void CheckFromAsyncOptions(TaskCreationOptions creationOptions, bool hasBeginMethod)
+ {
+ if (hasBeginMethod)
+ {
+ // Options detected here cause exceptions in FromAsync methods that take beginMethod as a parameter
+ if ((creationOptions & TaskCreationOptions.LongRunning) != 0)
+ throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_LongRunning"));
+ if ((creationOptions & TaskCreationOptions.PreferFairness) != 0)
+ throw new ArgumentOutOfRangeException("creationOptions", Environment.GetResourceString("Task_FromAsync_PreferFairness"));
+ }
+
+ // Check for general validity of options
+ if ((creationOptions &
+ ~(TaskCreationOptions.AttachedToParent |
+ TaskCreationOptions.DenyChildAttach |
+ TaskCreationOptions.HideScheduler |
+ TaskCreationOptions.PreferFairness |
+ TaskCreationOptions.LongRunning)) != 0)
+ {
+ throw new ArgumentOutOfRangeException("creationOptions");
+ }
+ }
+
+
+ //
+ // ContinueWhenAll methods
+ //
+
+ // A Task<Task[]> that, given an initial collection of N tasks, will complete when
+ // it has been invoked N times. This allows us to replace this logic:
+ // Task<Task[]> promise = new Task<Task[]>(...);
+ // int _count = tasksCopy.Length;
+ // Action<Task> completionAction = delegate {if(Interlocked.Decrement(ref _count) == 0) promise.TrySetResult(tasksCopy);
+ // for(int i=0; i<_count; i++)
+ // tasksCopy[i].AddCompletionAction(completionAction);
+ // with this logic:
+ // CompletionOnCountdownPromise promise = new CompletionOnCountdownPromise(tasksCopy);
+ // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(promise);
+ // which saves a few allocations.
+ //
+ // Used in TaskFactory.CommonCWAllLogic(Task[]), below.
+ private sealed class CompleteOnCountdownPromise : Task<Task[]>, ITaskCompletionAction
+ {
+ private readonly Task[] _tasks;
+ private int _count;
+
+ internal CompleteOnCountdownPromise(Task[] tasksCopy) : base()
+ {
+ Contract.Requires((tasksCopy != null) && (tasksCopy.Length > 0), "Expected non-null task array with at least one element in it");
+ _tasks = tasksCopy;
+ _count = tasksCopy.Length;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAll", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+ }
+
+ public void Invoke(Task completingTask)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
+
+ if (completingTask.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
+ if (Interlocked.Decrement(ref _count) == 0)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+
+ TrySetResult(_tasks);
+ }
+ Contract.Assert(_count >= 0, "Count should never go below 0");
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
+ /// <summary>
+ /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// true iff at least one constituent task has its bit set.
+ /// </summary>
+ internal override bool ShouldNotifyDebuggerOfWaitCompletion
+ {
+ get
+ {
+ return
+ base.ShouldNotifyDebuggerOfWaitCompletion &&
+ Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks);
+ }
+ }
+ }
+
+ // Performs some logic common to all ContinueWhenAll() overloads
+ internal static Task<Task[]> CommonCWAllLogic(Task[] tasksCopy)
+ {
+ Contract.Requires(tasksCopy != null);
+
+ // Create a promise task to be returned to the user
+ CompleteOnCountdownPromise promise = new CompleteOnCountdownPromise(tasksCopy);
+
+ for (int i = 0; i < tasksCopy.Length; i++)
+ {
+ if (tasksCopy[i].IsCompleted) promise.Invoke(tasksCopy[i]); // Short-circuit the completion action, if possible
+ else tasksCopy[i].AddCompletionAction(promise); // simple completion action
+ }
+
+ return promise;
+ }
+
+
+ // A Task<Task<T>[]> that, given an initial collection of N tasks, will complete when
+ // it has been invoked N times. See comments for non-generic CompleteOnCountdownPromise class.
+ //
+ // Used in TaskFactory.CommonCWAllLogic<TResult>(Task<TResult>[]), below.
+ private sealed class CompleteOnCountdownPromise<T> : Task<Task<T>[]>, ITaskCompletionAction
+ {
+ private readonly Task<T>[] _tasks;
+ private int _count;
+
+ internal CompleteOnCountdownPromise(Task<T>[] tasksCopy) : base()
+ {
+ Contract.Requires((tasksCopy != null) && (tasksCopy.Length > 0), "Expected non-null task array with at least one element in it");
+ _tasks = tasksCopy;
+ _count = tasksCopy.Length;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAll<>", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+ }
+
+ public void Invoke(Task completingTask)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Join);
+
+ if (completingTask.IsWaitNotificationEnabled) this.SetNotificationForWaitCompletion(enabled: true);
+ if (Interlocked.Decrement(ref _count) == 0)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+
+ TrySetResult(_tasks);
+ }
+ Contract.Assert(_count >= 0, "Count should never go below 0");
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+
+ /// <summary>
+ /// Returns whether we should notify the debugger of a wait completion. This returns
+ /// true iff at least one constituent task has its bit set.
+ /// </summary>
+ internal override bool ShouldNotifyDebuggerOfWaitCompletion
+ {
+ get
+ {
+ return
+ base.ShouldNotifyDebuggerOfWaitCompletion &&
+ Task.AnyTaskRequiresNotifyDebuggerOfWaitCompletion(_tasks);
+ }
+ }
+ }
+
+
+ internal static Task<Task<T>[]> CommonCWAllLogic<T>(Task<T>[] tasksCopy)
+ {
+ Contract.Requires(tasksCopy != null);
+
+ // Create a promise task to be returned to the user
+ CompleteOnCountdownPromise<T> promise = new CompleteOnCountdownPromise<T>(tasksCopy);
+
+ for (int i = 0; i < tasksCopy.Length; i++)
+ {
+ if (tasksCopy[i].IsCompleted) promise.Invoke(tasksCopy[i]); // Short-circuit the completion action, if possible
+ else tasksCopy[i].AddCompletionAction(promise); // simple completion action
+ }
+
+ return promise;
+ }
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll(Task[] tasks, Action<Task[]> continuationAction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in
+ /// the <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationAction">The action delegate to execute when all tasks in the <paramref
+ /// name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAll<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>[]> continuationAction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TResult>(Task[] tasks, Func<Task[], TResult> continuationFunction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of a set of provided Tasks.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue.</param>
+ /// <param name="continuationFunction">The function delegate to execute when all tasks in the
+ /// <paramref name="tasks"/> array have completed.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAll.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAll<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>[], TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAllImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ //
+ // ContinueWhenAny methods
+ //
+
+ // A Task<Task> that will be completed the first time that Invoke is called.
+ // It allows us to replace this logic:
+ // Task<Task> promise = new Task<Task>(...);
+ // Action<Task> completionAction = delegate(Task completingTask) { promise.TrySetResult(completingTask); }
+ // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(completionAction);
+ // with this logic:
+ // CompletionOnInvokePromise promise = new CompletionOnInvokePromise(tasksCopy);
+ // for(int i=0; i<tasksCopy.Length; i++) tasksCopy[i].AddCompletionAction(promise);
+ // which saves a couple of allocations.
+ //
+ // Used in TaskFactory.CommonCWAnyLogic(), below.
+ internal sealed class CompleteOnInvokePromise : Task<Task>, ITaskCompletionAction
+ {
+ private IList<Task> _tasks; // must track this for cleanup
+ private int m_firstTaskAlreadyCompleted;
+
+ public CompleteOnInvokePromise(IList<Task> tasks) : base()
+ {
+ Contract.Requires(tasks != null, "Expected non-null collection of tasks");
+ _tasks = tasks;
+
+ if (AsyncCausalityTracer.LoggingOn)
+ AsyncCausalityTracer.TraceOperationCreation(CausalityTraceLevel.Required, this.Id, "TaskFactory.ContinueWhenAny", 0);
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ AddToActiveTasks(this);
+ }
+ }
+
+ public void Invoke(Task completingTask)
+ {
+ if (Interlocked.CompareExchange(ref m_firstTaskAlreadyCompleted, 1, 0) == 0)
+ {
+ if (AsyncCausalityTracer.LoggingOn)
+ {
+ AsyncCausalityTracer.TraceOperationRelation(CausalityTraceLevel.Important, this.Id, CausalityRelation.Choice);
+ AsyncCausalityTracer.TraceOperationCompletion(CausalityTraceLevel.Required, this.Id, AsyncCausalityStatus.Completed);
+ }
+
+ if (Task.s_asyncDebuggingEnabled)
+ {
+ RemoveFromActiveTasks(this.Id);
+ }
+
+ bool success = TrySetResult(completingTask);
+ Contract.Assert(success, "Only one task should have gotten to this point, and thus this must be successful.");
+
+ // We need to remove continuations that may be left straggling on other tasks.
+ // Otherwise, repeated calls to WhenAny using the same task could leak actions.
+ // This may also help to avoided unnecessary invocations of this whenComplete delegate.
+ // Note that we may be attempting to remove a continuation from a task that hasn't had it
+ // added yet; while there's overhead there, the operation won't hurt anything.
+ var tasks = _tasks;
+ int numTasks = tasks.Count;
+ for (int i = 0; i < numTasks; i++)
+ {
+ var task = tasks[i];
+ if (task != null && // if an element was erroneously nulled out concurrently, just skip it; worst case is we don't remove a continuation
+ !task.IsCompleted) task.RemoveContinuation(this);
+ }
+ _tasks = null;
+
+ }
+ }
+
+ public bool InvokeMayRunArbitraryCode { get { return true; } }
+ }
+ // Common ContinueWhenAny logic
+ // If the tasks list is not an array, it must be an internal defensive copy so that
+ // we don't need to be concerned about concurrent modifications to the list. If the task list
+ // is an array, it should be a defensive copy if this functionality is being used
+ // asynchronously (e.g. WhenAny) rather than synchronously (e.g. WaitAny).
+ internal static Task<Task> CommonCWAnyLogic(IList<Task> tasks)
+ {
+ Contract.Requires(tasks != null);
+
+ // Create a promise task to be returned to the user
+ var promise = new CompleteOnInvokePromise(tasks);
+
+ // At the completion of any of the tasks, complete the promise.
+
+ bool checkArgsOnly = false;
+ int numTasks = tasks.Count;
+ for(int i=0; i<numTasks; i++)
+ {
+ var task = tasks[i];
+ if (task == null) throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
+
+ if (checkArgsOnly) continue;
+
+ // If the promise has already completed, don't bother with checking any more tasks.
+ if (promise.IsCompleted)
+ {
+ checkArgsOnly = true;
+ }
+ // If a task has already completed, complete the promise.
+ else if (task.IsCompleted)
+ {
+ promise.Invoke(task);
+ checkArgsOnly = true;
+ }
+ // Otherwise, add the completion action and keep going.
+ else task.AddCompletionAction(promise);
+ }
+
+ return promise;
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the <paramref
+ /// name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny(Task[] tasks, Action<Task> continuationAction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null,continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TResult>(Task[] tasks, Func<Task, TResult> continuationFunction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TResult">The type of the result that is returned by the <paramref
+ /// name="continuationFunction"/>
+ /// delegate and associated with the created <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</typeparam>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationFunction">The function delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task{TResult}">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task{TResult}"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationFunction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TResult> ContinueWhenAny<TAntecedentResult, TResult>(Task<TAntecedentResult>[] tasks, Func<Task<TAntecedentResult>, TResult> continuationFunction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationFunction == null) throw new ArgumentNullException("continuationFunction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<TResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+ CancellationToken cancellationToken)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+ TaskContinuationOptions continuationOptions)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// that will be started upon the completion of any Task in the provided set.
+ /// </summary>
+ /// <typeparam name="TAntecedentResult">The type of the result of the antecedent <paramref name="tasks"/>.</typeparam>
+ /// <param name="tasks">The array of tasks from which to continue when one task completes.</param>
+ /// <param name="continuationAction">The action delegate to execute when one task in the
+ /// <paramref name="tasks"/> array completes.</param>
+ /// <param name="cancellationToken">The <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">The <see cref="System.Threading.Tasks.TaskContinuationOptions">
+ /// TaskContinuationOptions</see> value that controls the behavior of
+ /// the created continuation <see cref="T:System.Threading.Tasks.Task">Task</see>.</param>
+ /// <param name="scheduler">The <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// that is used to schedule the created continuation <see
+ /// cref="T:System.Threading.Tasks.Task{TResult}"/>.</param>
+ /// <returns>The new continuation <see cref="T:System.Threading.Tasks.Task"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="continuationAction"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentNullException">The exception that is thrown when the
+ /// <paramref name="scheduler"/> argument is null.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array contains a null value.</exception>
+ /// <exception cref="T:System.ArgumentException">The exception that is thrown when the
+ /// <paramref name="tasks"/> array is empty.</exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The exception that is thrown when the
+ /// <paramref name="continuationOptions"/> argument specifies an invalid TaskContinuationOptions
+ /// value.</exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ /// <remarks>
+ /// The NotOn* and OnlyOn* <see cref="System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>,
+ /// which constrain for which <see cref="System.Threading.Tasks.TaskStatus">TaskStatus</see> states a continuation
+ /// will be executed, are illegal with ContinueWhenAny.
+ /// </remarks>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[] tasks, Action<Task<TAntecedentResult>> continuationAction,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ if (continuationAction == null) throw new ArgumentNullException("continuationAction");
+ Contract.EndContractBlock();
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TaskFactory<VoidTaskResult>.ContinueWhenAnyImpl<TAntecedentResult>(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler, ref stackMark);
+ }
+
+ // Check task array and return a defensive copy.
+ // Used with ContinueWhenAll()/ContinueWhenAny().
+ internal static Task[] CheckMultiContinuationTasksAndCopy(Task[] tasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException("tasks");
+ if (tasks.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
+ Contract.EndContractBlock();
+
+ Task[] tasksCopy = new Task[tasks.Length];
+ for (int i = 0; i < tasks.Length; i++)
+ {
+ tasksCopy[i] = tasks[i];
+
+ if (tasksCopy[i] == null)
+ throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
+ }
+
+ return tasksCopy;
+ }
+
+ internal static Task<TResult>[] CheckMultiContinuationTasksAndCopy<TResult>(Task<TResult>[] tasks)
+ {
+ if (tasks == null)
+ throw new ArgumentNullException("tasks");
+ if (tasks.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_EmptyTaskList"), "tasks");
+ Contract.EndContractBlock();
+
+ Task<TResult>[] tasksCopy = new Task<TResult>[tasks.Length];
+ for (int i = 0; i < tasks.Length; i++)
+ {
+ tasksCopy[i] = tasks[i];
+
+ if (tasksCopy[i] == null)
+ throw new ArgumentException(Environment.GetResourceString("Task_MultiTaskContinuation_NullTask"), "tasks");
+ }
+
+ return tasksCopy;
+ }
+
+ // Throw an exception if "options" argument specifies illegal options
+ [ContractArgumentValidatorAttribute]
+ internal static void CheckMultiTaskContinuationOptions(TaskContinuationOptions continuationOptions)
+ {
+ // Construct a mask to check for illegal options
+ const TaskContinuationOptions NotOnAny = TaskContinuationOptions.NotOnCanceled |
+ TaskContinuationOptions.NotOnFaulted |
+ TaskContinuationOptions.NotOnRanToCompletion;
+
+ // Check that LongRunning and ExecuteSynchronously are not specified together
+ const TaskContinuationOptions illegalMask = TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.LongRunning;
+ if ((continuationOptions & illegalMask) == illegalMask)
+ {
+ throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_ContinueWith_ESandLR"));
+ }
+
+ // Check that no nonsensical options are specified.
+ if ((continuationOptions & ~(
+ TaskContinuationOptions.LongRunning |
+ TaskContinuationOptions.PreferFairness |
+ TaskContinuationOptions.AttachedToParent |
+ TaskContinuationOptions.DenyChildAttach |
+ TaskContinuationOptions.HideScheduler |
+ TaskContinuationOptions.LazyCancellation |
+ NotOnAny |
+ TaskContinuationOptions.ExecuteSynchronously)) != 0)
+ {
+ throw new ArgumentOutOfRangeException("continuationOptions");
+ }
+
+ // Check that no "fire" options are specified.
+ if ((continuationOptions & NotOnAny) != 0)
+ throw new ArgumentOutOfRangeException("continuationOptions", Environment.GetResourceString("Task_MultiTaskContinuation_FireOptions"));
+ Contract.EndContractBlock();
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs
new file mode 100644
index 0000000000..f82492499c
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskScheduler.cs
@@ -0,0 +1,757 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// This file contains the primary interface and management of tasks and queues.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+// Disable the "reference to volatile field not treated as volatile" error.
+#pragma warning disable 0420
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Threading;
+using System.Security;
+using System.Security.Permissions;
+using System.Collections.Concurrent;
+using System.Diagnostics.Contracts;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+
+namespace System.Threading.Tasks
+{
+
+ /// <summary>
+ /// Represents an abstract scheduler for tasks.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> acts as the extension point for all
+ /// pluggable scheduling logic. This includes mechanisms such as how to schedule a task for execution, and
+ /// how scheduled tasks should be exposed to debuggers.
+ /// </para>
+ /// <para>
+ /// All members of the abstract <see cref="TaskScheduler"/> type are thread-safe
+ /// and may be used from multiple threads concurrently.
+ /// </para>
+ /// </remarks>
+ [DebuggerDisplay("Id={Id}")]
+ [DebuggerTypeProxy(typeof(SystemThreadingTasks_TaskSchedulerDebugView))]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+#pragma warning disable 618
+ [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
+#pragma warning restore 618
+ public abstract class TaskScheduler
+ {
+ ////////////////////////////////////////////////////////////
+ //
+ // User Provided Methods and Properties
+ //
+
+ /// <summary>
+ /// Queues a <see cref="T:System.Threading.Tasks.Task">Task</see> to the scheduler.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A class derived from <see cref="T:System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// implements this method to accept tasks being scheduled on the scheduler.
+ /// A typical implementation would store the task in an internal data structure, which would
+ /// be serviced by threads that would execute those tasks at some time in the future.
+ /// </para>
+ /// <para>
+ /// This method is only meant to be called by the .NET Framework and
+ /// should not be called directly by the derived class. This is necessary
+ /// for maintaining the consistency of the system.
+ /// </para>
+ /// </remarks>
+ /// <param name="task">The <see cref="T:System.Threading.Tasks.Task">Task</see> to be queued.</param>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="task"/> argument is null.</exception>
+ [SecurityCritical]
+ protected internal abstract void QueueTask(Task task);
+
+ /// <summary>
+ /// Determines whether the provided <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// can be executed synchronously in this call, and if it can, executes it.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A class derived from <see cref="TaskScheduler">TaskScheduler</see> implements this function to
+ /// support inline execution of a task on a thread that initiates a wait on that task object. Inline
+ /// execution is optional, and the request may be rejected by returning false. However, better
+ /// scalability typically results the more tasks that can be inlined, and in fact a scheduler that
+ /// inlines too little may be prone to deadlocks. A proper implementation should ensure that a
+ /// request executing under the policies guaranteed by the scheduler can successfully inline. For
+ /// example, if a scheduler uses a dedicated thread to execute tasks, any inlining requests from that
+ /// thread should succeed.
+ /// </para>
+ /// <para>
+ /// If a scheduler decides to perform the inline execution, it should do so by calling to the base
+ /// TaskScheduler's
+ /// <see cref="TryExecuteTask">TryExecuteTask</see> method with the provided task object, propagating
+ /// the return value. It may also be appropriate for the scheduler to remove an inlined task from its
+ /// internal data structures if it decides to honor the inlining request. Note, however, that under
+ /// some circumstances a scheduler may be asked to inline a task that was not previously provided to
+ /// it with the <see cref="QueueTask"/> method.
+ /// </para>
+ /// <para>
+ /// The derived scheduler is responsible for making sure that the calling thread is suitable for
+ /// executing the given task as far as its own scheduling and execution policies are concerned.
+ /// </para>
+ /// </remarks>
+ /// <param name="task">The <see cref="T:System.Threading.Tasks.Task">Task</see> to be
+ /// executed.</param>
+ /// <param name="taskWasPreviouslyQueued">A Boolean denoting whether or not task has previously been
+ /// queued. If this parameter is True, then the task may have been previously queued (scheduled); if
+ /// False, then the task is known not to have been queued, and this call is being made in order to
+ /// execute the task inline without queueing it.</param>
+ /// <returns>A Boolean value indicating whether the task was executed inline.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="task"/> argument is
+ /// null.</exception>
+ /// <exception cref="T:System.InvalidOperationException">The <paramref name="task"/> was already
+ /// executed.</exception>
+ [SecurityCritical]
+ protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued);
+
+ /// <summary>
+ /// Generates an enumerable of <see cref="T:System.Threading.Tasks.Task">Task</see> instances
+ /// currently queued to the scheduler waiting to be executed.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// A class derived from <see cref="TaskScheduler"/> implements this method in order to support
+ /// integration with debuggers. This method will only be invoked by the .NET Framework when the
+ /// debugger requests access to the data. The enumerable returned will be traversed by debugging
+ /// utilities to access the tasks currently queued to this scheduler, enabling the debugger to
+ /// provide a representation of this information in the user interface.
+ /// </para>
+ /// <para>
+ /// It is important to note that, when this method is called, all other threads in the process will
+ /// be frozen. Therefore, it's important to avoid synchronization with other threads that may lead to
+ /// blocking. If synchronization is necessary, the method should prefer to throw a <see
+ /// cref="System.NotSupportedException"/>
+ /// than to block, which could cause a debugger to experience delays. Additionally, this method and
+ /// the enumerable returned must not modify any globally visible state.
+ /// </para>
+ /// <para>
+ /// The returned enumerable should never be null. If there are currently no queued tasks, an empty
+ /// enumerable should be returned instead.
+ /// </para>
+ /// <para>
+ /// For developers implementing a custom debugger, this method shouldn't be called directly, but
+ /// rather this functionality should be accessed through the internal wrapper method
+ /// GetScheduledTasksForDebugger:
+ /// <c>internal Task[] GetScheduledTasksForDebugger()</c>. This method returns an array of tasks,
+ /// rather than an enumerable. In order to retrieve a list of active schedulers, a debugger may use
+ /// another internal method: <c>internal static TaskScheduler[] GetTaskSchedulersForDebugger()</c>.
+ /// This static method returns an array of all active TaskScheduler instances.
+ /// GetScheduledTasksForDebugger then may be used on each of these scheduler instances to retrieve
+ /// the list of scheduled tasks for each.
+ /// </para>
+ /// </remarks>
+ /// <returns>An enumerable that allows traversal of tasks currently queued to this scheduler.
+ /// </returns>
+ /// <exception cref="T:System.NotSupportedException">
+ /// This scheduler is unable to generate a list of queued tasks at this time.
+ /// </exception>
+ [SecurityCritical]
+ protected abstract IEnumerable<Task> GetScheduledTasks();
+
+ /// <summary>
+ /// Indicates the maximum concurrency level this
+ /// <see cref="TaskScheduler"/> is able to support.
+ /// </summary>
+ public virtual Int32 MaximumConcurrencyLevel
+ {
+ get
+ {
+ return Int32.MaxValue;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////
+ //
+ // Internal overridable methods
+ //
+
+
+ /// <summary>
+ /// Attempts to execute the target task synchronously.
+ /// </summary>
+ /// <param name="task">The task to run.</param>
+ /// <param name="taskWasPreviouslyQueued">True if the task may have been previously queued,
+ /// false if the task was absolutely not previously queued.</param>
+ /// <returns>True if it ran, false otherwise.</returns>
+ [SecuritySafeCritical]
+ internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ // Do not inline unstarted tasks (i.e., task.ExecutingTaskScheduler == null).
+ // Do not inline TaskCompletionSource-style (a.k.a. "promise") tasks.
+ // No need to attempt inlining if the task body was already run (i.e. either TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bits set)
+ TaskScheduler ets = task.ExecutingTaskScheduler;
+
+ // Delegate cross-scheduler inlining requests to target scheduler
+ if(ets != this && ets !=null) return ets.TryRunInline(task, taskWasPreviouslyQueued);
+
+ StackGuard currentStackGuard;
+ if( (ets == null) ||
+ (task.m_action == null) ||
+ task.IsDelegateInvoked ||
+ task.IsCanceled ||
+ (currentStackGuard = Task.CurrentStackGuard).TryBeginInliningScope() == false)
+ {
+ return false;
+ }
+
+ // Task class will still call into TaskScheduler.TryRunInline rather than TryExecuteTaskInline() so that
+ // 1) we can adjust the return code from TryExecuteTaskInline in case a buggy custom scheduler lies to us
+ // 2) we maintain a mechanism for the TLS lookup optimization that we used to have for the ConcRT scheduler (will potentially introduce the same for TP)
+ bool bInlined = false;
+ try
+ {
+ task.FireTaskScheduledIfNeeded(this);
+ bInlined = TryExecuteTaskInline(task, taskWasPreviouslyQueued);
+ }
+ finally
+ {
+ currentStackGuard.EndInliningScope();
+ }
+
+ // If the custom scheduler returned true, we should either have the TASK_STATE_DELEGATE_INVOKED or TASK_STATE_CANCELED bit set
+ // Otherwise the scheduler is buggy
+ if (bInlined && !(task.IsDelegateInvoked || task.IsCanceled))
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_InconsistentStateAfterTryExecuteTaskInline"));
+ }
+
+ return bInlined;
+ }
+
+ /// <summary>
+ /// Attempts to dequeue a <see cref="T:System.Threading.Tasks.Task">Task</see> that was previously queued to
+ /// this scheduler.
+ /// </summary>
+ /// <param name="task">The <see cref="T:System.Threading.Tasks.Task">Task</see> to be dequeued.</param>
+ /// <returns>A Boolean denoting whether the <paramref name="task"/> argument was successfully dequeued.</returns>
+ /// <exception cref="T:System.ArgumentNullException">The <paramref name="task"/> argument is null.</exception>
+ [SecurityCritical]
+ protected internal virtual bool TryDequeue(Task task)
+ {
+ return false;
+ }
+
+ /// <summary>
+ /// Notifies the scheduler that a work item has made progress.
+ /// </summary>
+ internal virtual void NotifyWorkItemProgress()
+ {
+ }
+
+ /// <summary>
+ /// Indicates whether this is a custom scheduler, in which case the safe code paths will be taken upon task entry
+ /// using a CAS to transition from queued state to executing.
+ /// </summary>
+ internal virtual bool RequiresAtomicStartTransition
+ {
+ get { return true; }
+ }
+
+ /// <summary>
+ /// Calls QueueTask() after performing any needed firing of events
+ /// </summary>
+ [SecurityCritical]
+ internal void InternalQueueTask(Task task)
+ {
+ Contract.Requires(task != null);
+
+ task.FireTaskScheduledIfNeeded(this);
+
+ this.QueueTask(task);
+ }
+
+
+ ////////////////////////////////////////////////////////////
+ //
+ // Member variables
+ //
+
+ // The global container that keeps track of TaskScheduler instances for debugging purposes.
+ private static ConditionalWeakTable<TaskScheduler, object> s_activeTaskSchedulers;
+
+ // An AppDomain-wide default manager.
+ private static readonly TaskScheduler s_defaultTaskScheduler = new ThreadPoolTaskScheduler();
+
+ //static counter used to generate unique TaskScheduler IDs
+ internal static int s_taskSchedulerIdCounter;
+
+ // this TaskScheduler's unique ID
+ private volatile int m_taskSchedulerId;
+
+
+
+ ////////////////////////////////////////////////////////////
+ //
+ // Constructors and public properties
+ //
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.Tasks.TaskScheduler"/>.
+ /// </summary>
+ protected TaskScheduler()
+ {
+ // Register the scheduler in the active scheduler list. This is only relevant when debugging,
+ // so we only pay the cost if the debugger is attached when the scheduler is created. This
+ // means that the internal TaskScheduler.GetTaskSchedulersForDebugger() will only include
+ // schedulers created while the debugger is attached.
+ if (Debugger.IsAttached)
+ {
+ AddToActiveTaskSchedulers();
+ }
+ }
+
+ /// <summary>Adds this scheduler ot the active schedulers tracking collection for debugging purposes.</summary>
+ private void AddToActiveTaskSchedulers()
+ {
+ ConditionalWeakTable<TaskScheduler, object> activeTaskSchedulers = s_activeTaskSchedulers;
+ if (activeTaskSchedulers == null)
+ {
+ Interlocked.CompareExchange(ref s_activeTaskSchedulers, new ConditionalWeakTable<TaskScheduler, object>(), null);
+ activeTaskSchedulers = s_activeTaskSchedulers;
+ }
+ activeTaskSchedulers.Add(this, null);
+ }
+
+ /// <summary>
+ /// Gets the default <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> instance.
+ /// </summary>
+ public static TaskScheduler Default
+ {
+ get
+ {
+ return s_defaultTaskScheduler;
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// associated with the currently executing task.
+ /// </summary>
+ /// <remarks>
+ /// When not called from within a task, <see cref="Current"/> will return the <see cref="Default"/> scheduler.
+ /// </remarks>
+ public static TaskScheduler Current
+ {
+ get
+ {
+ TaskScheduler current = InternalCurrent;
+ return current ?? TaskScheduler.Default;
+ }
+ }
+
+ /// <summary>
+ /// Gets the <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// associated with the currently executing task.
+ /// </summary>
+ /// <remarks>
+ /// When not called from within a task, <see cref="InternalCurrent"/> will return null.
+ /// </remarks>
+ internal static TaskScheduler InternalCurrent
+ {
+ get
+ {
+ Task currentTask = Task.InternalCurrent;
+ return ( (currentTask != null)
+ && ((currentTask.CreationOptions & TaskCreationOptions.HideScheduler) == 0)
+ ) ? currentTask.ExecutingTaskScheduler : null;
+ }
+ }
+
+ /// <summary>
+ /// Creates a <see cref="TaskScheduler"/>
+ /// associated with the current <see cref="T:System.Threading.SynchronizationContext"/>.
+ /// </summary>
+ /// <remarks>
+ /// All <see cref="System.Threading.Tasks.Task">Task</see> instances queued to
+ /// the returned scheduler will be executed through a call to the
+ /// <see cref="System.Threading.SynchronizationContext.Post">Post</see> method
+ /// on that context.
+ /// </remarks>
+ /// <returns>
+ /// A <see cref="TaskScheduler"/> associated with
+ /// the current <see cref="T:System.Threading.SynchronizationContext">SynchronizationContext</see>, as
+ /// determined by <see cref="System.Threading.SynchronizationContext.Current">SynchronizationContext.Current</see>.
+ /// </returns>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The current SynchronizationContext may not be used as a TaskScheduler.
+ /// </exception>
+ public static TaskScheduler FromCurrentSynchronizationContext()
+ {
+ return new SynchronizationContextTaskScheduler();
+ }
+
+ /// <summary>
+ /// Gets the unique ID for this <see cref="TaskScheduler"/>.
+ /// </summary>
+ public Int32 Id
+ {
+ get
+ {
+ if (m_taskSchedulerId == 0)
+ {
+ int newId = 0;
+
+ // We need to repeat if Interlocked.Increment wraps around and returns 0.
+ // Otherwise next time this scheduler's Id is queried it will get a new value
+ do
+ {
+ newId = Interlocked.Increment(ref s_taskSchedulerIdCounter);
+ } while (newId == 0);
+
+ Interlocked.CompareExchange(ref m_taskSchedulerId, newId, 0);
+ }
+
+ return m_taskSchedulerId;
+ }
+ }
+
+ /// <summary>
+ /// Attempts to execute the provided <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// on this scheduler.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// Scheduler implementations are provided with <see cref="T:System.Threading.Tasks.Task">Task</see>
+ /// instances to be executed through either the <see cref="QueueTask"/> method or the
+ /// <see cref="TryExecuteTaskInline"/> method. When the scheduler deems it appropriate to run the
+ /// provided task, <see cref="TryExecuteTask"/> should be used to do so. TryExecuteTask handles all
+ /// aspects of executing a task, including action invocation, exception handling, state management,
+ /// and lifecycle control.
+ /// </para>
+ /// <para>
+ /// <see cref="TryExecuteTask"/> must only be used for tasks provided to this scheduler by the .NET
+ /// Framework infrastructure. It should not be used to execute arbitrary tasks obtained through
+ /// custom mechanisms.
+ /// </para>
+ /// </remarks>
+ /// <param name="task">
+ /// A <see cref="T:System.Threading.Tasks.Task">Task</see> object to be executed.</param>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The <paramref name="task"/> is not associated with this scheduler.
+ /// </exception>
+ /// <returns>A Boolean that is true if <paramref name="task"/> was successfully executed, false if it
+ /// was not. A common reason for execution failure is that the task had previously been executed or
+ /// is in the process of being executed by another thread.</returns>
+ [SecurityCritical]
+ protected bool TryExecuteTask(Task task)
+ {
+ if (task.ExecutingTaskScheduler != this)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_ExecuteTask_WrongTaskScheduler"));
+ }
+
+ return task.ExecuteEntry(true);
+ }
+
+ ////////////////////////////////////////////////////////////
+ //
+ // Events
+ //
+
+ private static EventHandler<UnobservedTaskExceptionEventArgs> _unobservedTaskException;
+ private static readonly object _unobservedTaskExceptionLockObject = new object();
+
+ /// <summary>
+ /// Occurs when a faulted <see cref="System.Threading.Tasks.Task"/>'s unobserved exception is about to trigger exception escalation
+ /// policy, which, by default, would terminate the process.
+ /// </summary>
+ /// <remarks>
+ /// This AppDomain-wide event provides a mechanism to prevent exception
+ /// escalation policy (which, by default, terminates the process) from triggering.
+ /// Each handler is passed a <see cref="T:System.Threading.Tasks.UnobservedTaskExceptionEventArgs"/>
+ /// instance, which may be used to examine the exception and to mark it as observed.
+ /// </remarks>
+ public static event EventHandler<UnobservedTaskExceptionEventArgs> UnobservedTaskException
+ {
+ [System.Security.SecurityCritical]
+ add
+ {
+ if (value != null)
+ {
+ RuntimeHelpers.PrepareContractedDelegate(value);
+ lock (_unobservedTaskExceptionLockObject) _unobservedTaskException += value;
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ remove
+ {
+ lock (_unobservedTaskExceptionLockObject) _unobservedTaskException -= value;
+ }
+ }
+
+
+
+
+
+
+ ////////////////////////////////////////////////////////////
+ //
+ // Internal methods
+ //
+
+ // This is called by the TaskExceptionHolder finalizer.
+ internal static void PublishUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs ueea)
+ {
+ // Lock this logic to prevent just-unregistered handlers from being called.
+ lock (_unobservedTaskExceptionLockObject)
+ {
+ // Since we are under lock, it is technically no longer necessary
+ // to make a copy. It is done here for convenience.
+ EventHandler<UnobservedTaskExceptionEventArgs> handler = _unobservedTaskException;
+ if (handler != null)
+ {
+ handler(sender, ueea);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Provides an array of all queued <see cref="System.Threading.Tasks.Task">Task</see> instances
+ /// for the debugger.
+ /// </summary>
+ /// <remarks>
+ /// The returned array is populated through a call to <see cref="GetScheduledTasks"/>.
+ /// Note that this function is only meant to be invoked by a debugger remotely.
+ /// It should not be called by any other codepaths.
+ /// </remarks>
+ /// <returns>An array of <see cref="System.Threading.Tasks.Task">Task</see> instances.</returns>
+ /// <exception cref="T:System.NotSupportedException">
+ /// This scheduler is unable to generate a list of queued tasks at this time.
+ /// </exception>
+ [SecurityCritical]
+ internal Task[] GetScheduledTasksForDebugger()
+ {
+ // this can throw InvalidOperationException indicating that they are unable to provide the info
+ // at the moment. We should let the debugger receive that exception so that it can indicate it in the UI
+ IEnumerable<Task> activeTasksSource = GetScheduledTasks();
+
+ if (activeTasksSource == null)
+ return null;
+
+ // If it can be cast to an array, use it directly
+ Task[] activeTasksArray = activeTasksSource as Task[];
+ if (activeTasksArray == null)
+ {
+ activeTasksArray = (new List<Task>(activeTasksSource)).ToArray();
+ }
+
+ // touch all Task.Id fields so that the debugger doesn't need to do a lot of cross-proc calls to generate them
+ foreach (Task t in activeTasksArray)
+ {
+ int tmp = t.Id;
+ }
+
+ return activeTasksArray;
+ }
+
+ /// <summary>
+ /// Provides an array of all active <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see>
+ /// instances for the debugger.
+ /// </summary>
+ /// <remarks>
+ /// This function is only meant to be invoked by a debugger remotely.
+ /// It should not be called by any other codepaths.
+ /// </remarks>
+ /// <returns>An array of <see cref="System.Threading.Tasks.TaskScheduler">TaskScheduler</see> instances.</returns>
+ [SecurityCritical]
+ internal static TaskScheduler[] GetTaskSchedulersForDebugger()
+ {
+ if (s_activeTaskSchedulers == null)
+ {
+ // No schedulers were tracked. Just give back the default.
+ return new TaskScheduler[] { s_defaultTaskScheduler };
+ }
+
+ ICollection<TaskScheduler> schedulers = s_activeTaskSchedulers.Keys;
+ if (!schedulers.Contains(s_defaultTaskScheduler))
+ {
+ // Make sure the default is included, in case the debugger attached
+ // after it was created.
+ schedulers.Add(s_defaultTaskScheduler);
+ }
+
+ var arr = new TaskScheduler[schedulers.Count];
+ schedulers.CopyTo(arr, 0);
+ foreach (var scheduler in arr)
+ {
+ Contract.Assert(scheduler != null, "Table returned an incorrect Count or CopyTo failed");
+ int tmp = scheduler.Id; // force Ids for debugger
+ }
+ return arr;
+ }
+
+ /// <summary>
+ /// Nested class that provides debugger view for TaskScheduler
+ /// </summary>
+ internal sealed class SystemThreadingTasks_TaskSchedulerDebugView
+ {
+ private readonly TaskScheduler m_taskScheduler;
+ public SystemThreadingTasks_TaskSchedulerDebugView(TaskScheduler scheduler)
+ {
+ m_taskScheduler = scheduler;
+ }
+
+ // returns the scheduler’s Id
+ public Int32 Id
+ {
+ get { return m_taskScheduler.Id; }
+ }
+
+ // returns the scheduler’s GetScheduledTasks
+ public IEnumerable<Task> ScheduledTasks
+ {
+ [SecurityCritical]
+ get { return m_taskScheduler.GetScheduledTasks(); }
+ }
+ }
+
+ }
+
+
+
+
+ /// <summary>
+ /// A TaskScheduler implementation that executes all tasks queued to it through a call to
+ /// <see cref="System.Threading.SynchronizationContext.Post"/> on the <see cref="T:System.Threading.SynchronizationContext"/>
+ /// that its associated with. The default constructor for this class binds to the current <see cref="T:System.Threading.SynchronizationContext"/>
+ /// </summary>
+ internal sealed class SynchronizationContextTaskScheduler : TaskScheduler
+ {
+ private SynchronizationContext m_synchronizationContext;
+
+ /// <summary>
+ /// Constructs a SynchronizationContextTaskScheduler associated with <see cref="T:System.Threading.SynchronizationContext.Current"/>
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">This constructor expects <see cref="T:System.Threading.SynchronizationContext.Current"/> to be set.</exception>
+ internal SynchronizationContextTaskScheduler()
+ {
+ SynchronizationContext synContext = SynchronizationContext.Current;
+
+ // make sure we have a synccontext to work with
+ if (synContext == null)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("TaskScheduler_FromCurrentSynchronizationContext_NoCurrent"));
+ }
+
+ m_synchronizationContext = synContext;
+
+ }
+
+ /// <summary>
+ /// Implemetation of <see cref="T:System.Threading.Tasks.TaskScheduler.QueueTask"/> for this scheduler class.
+ ///
+ /// Simply posts the tasks to be executed on the associated <see cref="T:System.Threading.SynchronizationContext"/>.
+ /// </summary>
+ /// <param name="task"></param>
+ [SecurityCritical]
+ protected internal override void QueueTask(Task task)
+ {
+ m_synchronizationContext.Post(s_postCallback, (object)task);
+ }
+
+ /// <summary>
+ /// Implementation of <see cref="T:System.Threading.Tasks.TaskScheduler.TryExecuteTaskInline"/> for this scheduler class.
+ ///
+ /// The task will be executed inline only if the call happens within
+ /// the associated <see cref="T:System.Threading.SynchronizationContext"/>.
+ /// </summary>
+ /// <param name="task"></param>
+ /// <param name="taskWasPreviouslyQueued"></param>
+ [SecurityCritical]
+ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ if (SynchronizationContext.Current == m_synchronizationContext)
+ {
+ return TryExecuteTask(task);
+ }
+ else
+ return false;
+ }
+
+ // not implemented
+ [SecurityCritical]
+ protected override IEnumerable<Task> GetScheduledTasks()
+ {
+ return null;
+ }
+
+ /// <summary>
+ /// Implementes the <see cref="T:System.Threading.Tasks.TaskScheduler.MaximumConcurrencyLevel"/> property for
+ /// this scheduler class.
+ ///
+ /// By default it returns 1, because a <see cref="T:System.Threading.SynchronizationContext"/> based
+ /// scheduler only supports execution on a single thread.
+ /// </summary>
+ public override Int32 MaximumConcurrencyLevel
+ {
+ get
+ {
+ return 1;
+ }
+ }
+
+ // preallocated SendOrPostCallback delegate
+ private static SendOrPostCallback s_postCallback = new SendOrPostCallback(PostCallback);
+
+ // this is where the actual task invocation occures
+ private static void PostCallback(object obj)
+ {
+ Task task = (Task) obj;
+
+ // calling ExecuteEntry with double execute check enabled because a user implemented SynchronizationContext could be buggy
+ task.ExecuteEntry(true);
+ }
+ }
+
+ /// <summary>
+ /// Provides data for the event that is raised when a faulted <see cref="System.Threading.Tasks.Task"/>'s
+ /// exception goes unobserved.
+ /// </summary>
+ /// <remarks>
+ /// The Exception property is used to examine the exception without marking it
+ /// as observed, whereas the <see cref="SetObserved"/> method is used to mark the exception
+ /// as observed. Marking the exception as observed prevents it from triggering exception escalation policy
+ /// which, by default, terminates the process.
+ /// </remarks>
+ public class UnobservedTaskExceptionEventArgs : EventArgs
+ {
+ private AggregateException m_exception;
+ internal bool m_observed = false;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UnobservedTaskExceptionEventArgs"/> class
+ /// with the unobserved exception.
+ /// </summary>
+ /// <param name="exception">The Exception that has gone unobserved.</param>
+ public UnobservedTaskExceptionEventArgs(AggregateException exception) { m_exception = exception; }
+
+ /// <summary>
+ /// Marks the <see cref="Exception"/> as "observed," thus preventing it
+ /// from triggering exception escalation policy which, by default, terminates the process.
+ /// </summary>
+ public void SetObserved() { m_observed = true; }
+
+ /// <summary>
+ /// Gets whether this exception has been marked as "observed."
+ /// </summary>
+ public bool Observed { get { return m_observed; } }
+
+ /// <summary>
+ /// The Exception that went unobserved.
+ /// </summary>
+ public AggregateException Exception { get { return m_exception; } }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskSchedulerException.cs b/src/mscorlib/src/System/Threading/Tasks/TaskSchedulerException.cs
new file mode 100644
index 0000000000..1d85e49342
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskSchedulerException.cs
@@ -0,0 +1,81 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// An exception for task schedulers.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+
+namespace System.Threading.Tasks
+{
+
+ /// <summary>
+ /// Represents an exception used to communicate an invalid operation by a
+ /// <see cref="T:System.Threading.Tasks.TaskScheduler"/>.
+ /// </summary>
+ [Serializable]
+ public class TaskSchedulerException : Exception
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/> class.
+ /// </summary>
+ public TaskSchedulerException() : base(Environment.GetResourceString("TaskSchedulerException_ctor_DefaultMessage")) //
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/>
+ /// class with a specified error message.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ public TaskSchedulerException(string message) : base(message)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/>
+ /// class using the default error message and a reference to the inner exception that is the cause of
+ /// this exception.
+ /// </summary>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ public TaskSchedulerException(Exception innerException)
+ : base(Environment.GetResourceString("TaskSchedulerException_ctor_DefaultMessage"), innerException)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/>
+ /// class with a specified error message and a reference to the inner exception that is the cause of
+ /// this exception.
+ /// </summary>
+ /// <param name="message">The error message that explains the reason for the exception.</param>
+ /// <param name="innerException">The exception that is the cause of the current exception.</param>
+ public TaskSchedulerException(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="T:System.Threading.Tasks.TaskSchedulerException"/>
+ /// class with serialized data.
+ /// </summary>
+ /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds
+ /// the serialized object data about the exception being thrown.</param>
+ /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that
+ /// contains contextual information about the source or destination. </param>
+ protected TaskSchedulerException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs b/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs
new file mode 100644
index 0000000000..02b130c297
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/TaskToApm.cs
@@ -0,0 +1,189 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// Helper methods for using Tasks to implement the APM pattern.
+//
+// Example usage, wrapping a Task<int>-returning FooAsync method with Begin/EndFoo methods:
+// public IAsyncResult BeginFoo(..., AsyncCallback callback, object state)
+// {
+// Task<int> t = FooAsync(...);
+// return TaskToApm.Begin(t, callback, state);
+// }
+// public int EndFoo(IAsyncResult asyncResult)
+// {
+// return TaskToApm.End<int>(asyncResult);
+// }
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.IO;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Provides support for efficiently using Tasks to implement the APM (Begin/End) pattern.
+ /// </summary>
+ internal static class TaskToApm
+ {
+ /// <summary>
+ /// Marshals the Task as an IAsyncResult, using the supplied callback and state
+ /// to implement the APM pattern.
+ /// </summary>
+ /// <param name="task">The Task to be marshaled.</param>
+ /// <param name="callback">The callback to be invoked upon completion.</param>
+ /// <param name="state">The state to be stored in the IAsyncResult.</param>
+ /// <returns>An IAsyncResult to represent the task's asynchronous operation.</returns>
+ public static IAsyncResult Begin(Task task, AsyncCallback callback, object state)
+ {
+ Contract.Requires(task != null);
+
+ // If the task has already completed, then since the Task's CompletedSynchronously==false
+ // and we want it to be true, we need to create a new IAsyncResult. (We also need the AsyncState to match.)
+ IAsyncResult asyncResult;
+ if (task.IsCompleted)
+ {
+ // Synchronous completion
+ asyncResult = new TaskWrapperAsyncResult(task, state, completedSynchronously: true);
+ if (callback != null)
+ callback(asyncResult);
+ }
+ // Otherwise, we need to schedule a callback. Whether we can use the Task as the IAsyncResult
+ // depends on whether the Task's AsyncState has reference equality with the requested state.
+ else
+ {
+ // Asynchronous completion
+ asyncResult = task.AsyncState == state ? (IAsyncResult)task : new TaskWrapperAsyncResult(task, state, completedSynchronously: false);
+ if (callback != null)
+ InvokeCallbackWhenTaskCompletes(task, callback, asyncResult);
+ }
+ return asyncResult;
+ }
+
+ /// <summary>Processes an IAsyncResult returned by Begin.</summary>
+ /// <param name="asyncResult">The IAsyncResult to unwrap.</param>
+ public static void End(IAsyncResult asyncResult)
+ {
+ Task task;
+
+ // If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
+ var twar = asyncResult as TaskWrapperAsyncResult;
+ if (twar != null)
+ {
+ task = twar.Task;
+ Contract.Assert(task != null, "TaskWrapperAsyncResult should never wrap a null Task.");
+ }
+ // Otherwise, the IAsyncResult should be a Task.
+ else
+ {
+ task = asyncResult as Task;
+ }
+
+ // Make sure we actually got a task, then complete the operation by waiting on it.
+ if (task == null)
+ __Error.WrongAsyncResult();
+ task.GetAwaiter().GetResult();
+ }
+
+ /// <summary>Processes an IAsyncResult returned by Begin.</summary>
+ /// <param name="asyncResult">The IAsyncResult to unwrap.</param>
+ public static TResult End<TResult>(IAsyncResult asyncResult)
+ {
+ Task<TResult> task;
+
+ // If the IAsyncResult is our task-wrapping IAsyncResult, extract the Task.
+ var twar = asyncResult as TaskWrapperAsyncResult;
+ if (twar != null)
+ {
+ task = twar.Task as Task<TResult>;
+ Contract.Assert(twar.Task != null, "TaskWrapperAsyncResult should never wrap a null Task.");
+ }
+ // Otherwise, the IAsyncResult should be a Task<TResult>.
+ else
+ {
+ task = asyncResult as Task<TResult>;
+ }
+
+ // Make sure we actually got a task, then complete the operation by waiting on it.
+ if (task == null)
+ __Error.WrongAsyncResult();
+ return task.GetAwaiter().GetResult();
+ }
+
+ /// <summary>Invokes the callback asynchronously when the task has completed.</summary>
+ /// <param name="antecedent">The Task to await.</param>
+ /// <param name="callback">The callback to invoke when the Task completes.</param>
+ /// <param name="asyncResult">The Task used as the IAsyncResult.</param>
+ private static void InvokeCallbackWhenTaskCompletes(Task antecedent, AsyncCallback callback, IAsyncResult asyncResult)
+ {
+ Contract.Requires(antecedent != null);
+ Contract.Requires(callback != null);
+ Contract.Requires(asyncResult != null);
+
+ // We use OnCompleted rather than ContinueWith in order to avoid running synchronously
+ // if the task has already completed by the time we get here. This is separated out into
+ // its own method currently so that we only pay for the closure if necessary.
+ antecedent.ConfigureAwait(continueOnCapturedContext:false)
+ .GetAwaiter()
+ .OnCompleted(() => callback(asyncResult));
+
+ // PERFORMANCE NOTE:
+ // Assuming we're in the default ExecutionContext, the "slow path" of an incomplete
+ // task will result in four allocations: the new IAsyncResult, the delegate+closure
+ // in this method, and the continuation object inside of OnCompleted (necessary
+ // to capture both the Action delegate and the ExecutionContext in a single object).
+ // In the future, if performance requirements drove a need, those four
+ // allocations could be reduced to one. This would be achieved by having TaskWrapperAsyncResult
+ // also implement ITaskCompletionAction (and optionally IThreadPoolWorkItem). It would need
+ // additional fields to store the AsyncCallback and an ExecutionContext. Once configured,
+ // it would be set into the Task as a continuation. Its Invoke method would then be run when
+ // the antecedent completed, and, doing all of the necessary work to flow ExecutionContext,
+ // it would invoke the AsyncCallback. It could also have a field on it for the antecedent,
+ // so that the End method would have access to the completed antecedent. For related examples,
+ // see other implementations of ITaskCompletionAction, and in particular ReadWriteTask
+ // used in Stream.Begin/EndXx's implementation.
+ }
+
+ /// <summary>
+ /// Provides a simple IAsyncResult that wraps a Task. This, in effect, allows
+ /// for overriding what's seen for the CompletedSynchronously and AsyncState values.
+ /// </summary>
+ private sealed class TaskWrapperAsyncResult : IAsyncResult
+ {
+ /// <summary>The wrapped Task.</summary>
+ internal readonly Task Task;
+ /// <summary>The new AsyncState value.</summary>
+ private readonly object m_state;
+ /// <summary>The new CompletedSynchronously value.</summary>
+ private readonly bool m_completedSynchronously;
+
+ /// <summary>Initializes the IAsyncResult with the Task to wrap and the overriding AsyncState and CompletedSynchronously values.</summary>
+ /// <param name="task">The Task to wrap.</param>
+ /// <param name="state">The new AsyncState value</param>
+ /// <param name="completedSynchronously">The new CompletedSynchronously value.</param>
+ internal TaskWrapperAsyncResult(Task task, object state, bool completedSynchronously)
+ {
+ Contract.Requires(task != null);
+ Contract.Requires(!completedSynchronously || task.IsCompleted, "If completedSynchronously is true, the task must be completed.");
+
+ this.Task = task;
+ m_state = state;
+ m_completedSynchronously = completedSynchronously;
+ }
+
+ // The IAsyncResult implementation.
+ // - IsCompleted and AsyncWaitHandle just pass through to the Task.
+ // - AsyncState and CompletedSynchronously return the corresponding values stored in this object.
+
+ object IAsyncResult.AsyncState { get { return m_state; } }
+ bool IAsyncResult.CompletedSynchronously { get { return m_completedSynchronously; } }
+ bool IAsyncResult.IsCompleted { get { return this.Task.IsCompleted; } }
+ WaitHandle IAsyncResult.AsyncWaitHandle { get { return ((IAsyncResult)this.Task).AsyncWaitHandle; } }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs b/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
new file mode 100644
index 0000000000..dd4cbc9a66
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs
@@ -0,0 +1,139 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+// TaskScheduler.cs
+//
+//
+// This file contains the primary interface and management of tasks and queues.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Security;
+using System.Diagnostics.Contracts;
+using System.Collections.Generic;
+using System.Text;
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// An implementation of TaskScheduler that uses the ThreadPool scheduler
+ /// </summary>
+ internal sealed class ThreadPoolTaskScheduler: TaskScheduler
+ {
+ /// <summary>
+ /// Constructs a new ThreadPool task scheduler object
+ /// </summary>
+ internal ThreadPoolTaskScheduler()
+ {
+ int id = base.Id; // force ID creation of the default scheduler
+ }
+
+ // static delegate for threads allocated to handle LongRunning tasks.
+ private static readonly ParameterizedThreadStart s_longRunningThreadWork = new ParameterizedThreadStart(LongRunningThreadWork);
+
+ private static void LongRunningThreadWork(object obj)
+ {
+ Contract.Requires(obj != null, "TaskScheduler.LongRunningThreadWork: obj is null");
+ Task t = obj as Task;
+ Contract.Assert(t != null, "TaskScheduler.LongRunningThreadWork: t is null");
+ t.ExecuteEntry(false);
+ }
+
+ /// <summary>
+ /// Schedules a task to the ThreadPool.
+ /// </summary>
+ /// <param name="task">The task to schedule.</param>
+ [SecurityCritical]
+ protected internal override void QueueTask(Task task)
+ {
+ if ((task.Options & TaskCreationOptions.LongRunning) != 0)
+ {
+ // Run LongRunning tasks on their own dedicated thread.
+ Thread thread = new Thread(s_longRunningThreadWork);
+ thread.IsBackground = true; // Keep this thread from blocking process shutdown
+ thread.Start(task);
+ }
+ else
+ {
+ // Normal handling for non-LongRunning tasks.
+ bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0);
+ ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue);
+ }
+ }
+
+ /// <summary>
+ /// This internal function will do this:
+ /// (1) If the task had previously been queued, attempt to pop it and return false if that fails.
+ /// (2) Propagate the return value from Task.ExecuteEntry() back to the caller.
+ ///
+ /// IMPORTANT NOTE: TryExecuteTaskInline will NOT throw task exceptions itself. Any wait code path using this function needs
+ /// to account for exceptions that need to be propagated, and throw themselves accordingly.
+ /// </summary>
+ [SecurityCritical]
+ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
+ {
+ // If the task was previously scheduled, and we can't pop it, then return false.
+ if (taskWasPreviouslyQueued && !ThreadPool.TryPopCustomWorkItem(task))
+ return false;
+
+ // Propagate the return value of Task.ExecuteEntry()
+ bool rval = false;
+ try
+ {
+ rval = task.ExecuteEntry(false); // handles switching Task.Current etc.
+ }
+ finally
+ {
+ // Only call NWIP() if task was previously queued
+ if(taskWasPreviouslyQueued) NotifyWorkItemProgress();
+ }
+
+ return rval;
+ }
+
+ [SecurityCritical]
+ protected internal override bool TryDequeue(Task task)
+ {
+ // just delegate to TP
+ return ThreadPool.TryPopCustomWorkItem(task);
+ }
+
+ [SecurityCritical]
+ protected override IEnumerable<Task> GetScheduledTasks()
+ {
+ return FilterTasksFromWorkItems(ThreadPool.GetQueuedWorkItems());
+ }
+
+ private IEnumerable<Task> FilterTasksFromWorkItems(IEnumerable<IThreadPoolWorkItem> tpwItems)
+ {
+ foreach (IThreadPoolWorkItem tpwi in tpwItems)
+ {
+ if (tpwi is Task)
+ {
+ yield return (Task)tpwi;
+ }
+ }
+ }
+
+ /// <summary>
+ /// Notifies the scheduler that work is progressing (no-op).
+ /// </summary>
+ internal override void NotifyWorkItemProgress()
+ {
+ ThreadPool.NotifyWorkItemProgress();
+ }
+
+ /// <summary>
+ /// This is the only scheduler that returns false for this property, indicating that the task entry codepath is unsafe (CAS free)
+ /// since we know that the underlying scheduler already takes care of atomic transitions from queued to non-queued.
+ /// </summary>
+ internal override bool RequiresAtomicStartTransition
+ {
+ get { return false; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Tasks/future.cs b/src/mscorlib/src/System/Threading/Tasks/future.cs
new file mode 100644
index 0000000000..39e6ca1d45
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Tasks/future.cs
@@ -0,0 +1,1667 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A task that produces a value.
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System;
+using System.Collections.Generic;
+using System.Runtime;
+using System.Runtime.CompilerServices;
+using System.Runtime.ExceptionServices;
+using System.Security;
+using System.Security.Permissions;
+using System.Threading;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+
+// Disable the "reference to volatile field not treated as volatile" error.
+#pragma warning disable 0420
+
+namespace System.Threading.Tasks
+{
+ /// <summary>
+ /// Represents an asynchronous operation that produces a result at some time in the future.
+ /// </summary>
+ /// <typeparam name="TResult">
+ /// The type of the result produced by this <see cref="Task{TResult}"/>.
+ /// </typeparam>
+ /// <remarks>
+ /// <para>
+ /// <see cref="Task{TResult}"/> instances may be created in a variety of ways. The most common approach is by
+ /// using the task's <see cref="Factory"/> property to retrieve a <see
+ /// cref="System.Threading.Tasks.TaskFactory{TResult}"/> instance that can be used to create tasks for several
+ /// purposes. For example, to create a <see cref="Task{TResult}"/> that runs a function, the factory's StartNew
+ /// method may be used:
+ /// <code>
+ /// // C#
+ /// var t = Task&lt;int&gt;.Factory.StartNew(() => GenerateResult());
+ /// - or -
+ /// var t = Task.Factory.StartNew(() => GenerateResult());
+ ///
+ /// ' Visual Basic
+ /// Dim t = Task&lt;int&gt;.Factory.StartNew(Function() GenerateResult())
+ /// - or -
+ /// Dim t = Task.Factory.StartNew(Function() GenerateResult())
+ /// </code>
+ /// </para>
+ /// <para>
+ /// The <see cref="Task{TResult}"/> class also provides constructors that initialize the task but that do not
+ /// schedule it for execution. For performance reasons, the StartNew method should be the
+ /// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation
+ /// and scheduling must be separated, the constructors may be used, and the task's
+ /// <see cref="System.Threading.Tasks.Task.Start()">Start</see>
+ /// method may then be used to schedule the task for execution at a later time.
+ /// </para>
+ /// <para>
+ /// All members of <see cref="Task{TResult}"/>, except for
+ /// <see cref="System.Threading.Tasks.Task.Dispose()">Dispose</see>, are thread-safe
+ /// and may be used from multiple threads concurrently.
+ /// </para>
+ /// </remarks>
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [DebuggerTypeProxy(typeof(SystemThreadingTasks_FutureDebugView<>))]
+ [DebuggerDisplay("Id = {Id}, Status = {Status}, Method = {DebuggerDisplayMethodDescription}, Result = {DebuggerDisplayResultDescription}")]
+ public class Task<TResult> : Task
+#if SUPPORT_IOBSERVABLE
+ , IObservable<TResult>
+#endif
+ {
+ internal TResult m_result; // The value itself, if set.
+
+ private static readonly TaskFactory<TResult> s_Factory = new TaskFactory<TResult>();
+
+ // Delegate used by:
+ // public static Task<Task<TResult>> WhenAny<TResult>(IEnumerable<Task<TResult>> tasks);
+ // public static Task<Task<TResult>> WhenAny<TResult>(params Task<TResult>[] tasks);
+ // Used to "cast" from Task<Task> to Task<Task<TResult>>.
+ internal static readonly Func<Task<Task>, Task<TResult>> TaskWhenAnyCast = completed => (Task<TResult>)completed.Result;
+
+ // Construct a promise-style task without any options.
+ internal Task() :
+ base()
+ {
+ }
+
+ // Construct a promise-style task with state and options.
+ internal Task(object state, TaskCreationOptions options) :
+ base(state, options, promiseStyle:true)
+ {
+ }
+
+
+ // Construct a pre-completed Task<TResult>
+ internal Task(TResult result) :
+ base(false, TaskCreationOptions.None, default(CancellationToken))
+ {
+ m_result = result;
+ }
+
+ internal Task(bool canceled, TResult result, TaskCreationOptions creationOptions, CancellationToken ct)
+ : base(canceled, creationOptions, ct)
+ {
+ if (!canceled)
+ {
+ m_result = result;
+ }
+ }
+
+ // Uncomment if/when we want Task.FromException
+ //// Construct a pre-faulted Task<TResult>
+ //internal Task(Exception exception)
+ // : base(exception)
+ //{
+ //}
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified function.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<TResult> function)
+ : this(function, null, default(CancellationToken),
+ TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified function.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to this task.</param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<TResult> function, CancellationToken cancellationToken)
+ : this(function, null, cancellationToken,
+ TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified function and creation options.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<TResult> function, TaskCreationOptions creationOptions)
+ : this(function, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken), creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified function and creation options.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<TResult> function, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ : this(function, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified function and state.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the action.</param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<object, TResult> function, object state)
+ : this(function, state, null, default(CancellationToken),
+ TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to the new task.</param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken)
+ : this(function, state, null, cancellationToken,
+ TaskCreationOptions.None, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the function.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<object, TResult> function, object state, TaskCreationOptions creationOptions)
+ : this(function, state, Task.InternalCurrentIfAttached(creationOptions), default(CancellationToken),
+ creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Initializes a new <see cref="Task{TResult}"/> with the specified action, state, and options.
+ /// </summary>
+ /// <param name="function">
+ /// The delegate that represents the code to execute in the task. When the function has completed,
+ /// the task's <see cref="Result"/> property will be set to return the result value of the function.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> to be assigned to the new task.</param>
+ /// <param name="creationOptions">
+ /// The <see cref="System.Threading.Tasks.TaskCreationOptions">TaskCreationOptions</see> used to
+ /// customize the task's behavior.
+ /// </param>
+ /// <exception cref="T:System.ArgumentException">
+ /// The <paramref name="function"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="creationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskCreationOptions"/>.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task(Func<object, TResult> function, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions)
+ : this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken,
+ creationOptions, InternalTaskOptions.None, null)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ internal Task(
+ Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler,
+ ref StackCrawlMark stackMark) :
+ this(valueSelector, parent, cancellationToken,
+ creationOptions, internalOptions, scheduler)
+ {
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a new future object.
+ /// </summary>
+ /// <param name="parent">The parent task for this future.</param>
+ /// <param name="valueSelector">A function that yields the future value.</param>
+ /// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
+ /// <param name="cancellationToken">The CancellationToken for the task.</param>
+ /// <param name="creationOptions">Options to control the future's behavior.</param>
+ /// <param name="internalOptions">Internal options to control the future's behavior.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="creationOptions"/> argument specifies
+ /// a SelfReplicating <see cref="Task{TResult}"/>, which is illegal."/>.</exception>
+ internal Task(Func<TResult> valueSelector, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+ base(valueSelector, null, parent, cancellationToken, creationOptions, internalOptions, scheduler)
+ {
+ if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
+ }
+ }
+
+ internal Task(
+ Func<object, TResult> valueSelector, object state, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark) :
+ this(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
+ {
+ PossiblyCaptureContext(ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a new future object.
+ /// </summary>
+ /// <param name="parent">The parent task for this future.</param>
+ /// <param name="state">An object containing data to be used by the action; may be null.</param>
+ /// <param name="valueSelector">A function that yields the future value.</param>
+ /// <param name="cancellationToken">The CancellationToken for the task.</param>
+ /// <param name="scheduler">The task scheduler which will be used to execute the future.</param>
+ /// <param name="creationOptions">Options to control the future's behavior.</param>
+ /// <param name="internalOptions">Internal options to control the future's behavior.</param>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="creationOptions"/> argument specifies
+ /// a SelfReplicating <see cref="Task{TResult}"/>, which is illegal."/>.</exception>
+ internal Task(Delegate valueSelector, object state, Task parent, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler) :
+ base(valueSelector, state, parent, cancellationToken, creationOptions, internalOptions, scheduler)
+ {
+ if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
+ }
+ }
+
+
+ // Internal method used by TaskFactory<TResult>.StartNew() methods
+ internal static Task<TResult> StartNew(Task parent, Func<TResult> function, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ if (function == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
+ }
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
+ }
+
+ // Create and schedule the future.
+ Task<TResult> f = new Task<TResult>(function, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
+
+ f.ScheduleAndStart(false);
+ return f;
+ }
+
+ // Internal method used by TaskFactory<TResult>.StartNew() methods
+ internal static Task<TResult> StartNew(Task parent, Func<object, TResult> function, object state, CancellationToken cancellationToken,
+ TaskCreationOptions creationOptions, InternalTaskOptions internalOptions, TaskScheduler scheduler, ref StackCrawlMark stackMark)
+ {
+ if (function == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.function);
+ }
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+ if ((internalOptions & InternalTaskOptions.SelfReplicating) != 0)
+ {
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.creationOptions, ExceptionResource.TaskT_ctor_SelfReplicating);
+ }
+
+ // Create and schedule the future.
+ Task<TResult> f = new Task<TResult>(function, state, parent, cancellationToken, creationOptions, internalOptions | InternalTaskOptions.QueuedByRuntime, scheduler, ref stackMark);
+
+ f.ScheduleAndStart(false);
+ return f;
+ }
+
+ // Debugger support
+ private string DebuggerDisplayResultDescription
+ {
+ get
+ {
+ return IsRanToCompletion ? "" + m_result : Environment.GetResourceString("TaskT_DebuggerNoResult");
+ }
+ }
+
+ // Debugger support
+ private string DebuggerDisplayMethodDescription
+ {
+ get
+ {
+ Delegate d = (Delegate)m_action;
+ return d != null ? d.Method.ToString() : "{null}";
+ }
+ }
+
+
+ // internal helper function breaks out logic used by TaskCompletionSource
+ internal bool TrySetResult(TResult result)
+ {
+ if (IsCompleted) return false;
+ Contract.Assert(m_action == null, "Task<T>.TrySetResult(): non-null m_action");
+
+ // "Reserve" the completion for this task, while making sure that: (1) No prior reservation
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // been recorded, and (4) Cancellation has not been requested.
+ //
+ // If the reservation is successful, then set the result and finish completion processing.
+ if (AtomicStateUpdate(TASK_STATE_COMPLETION_RESERVED,
+ TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
+ {
+ m_result = result;
+
+ // Signal completion, for waiting tasks
+
+ // This logic used to be:
+ // Finish(false);
+ // However, that goes through a windy code path, involves many non-inlineable functions
+ // and which can be summarized more concisely with the following snippet from
+ // FinishStageTwo, omitting everything that doesn't pertain to TrySetResult.
+ Interlocked.Exchange(ref m_stateFlags, m_stateFlags | TASK_STATE_RAN_TO_COMPLETION);
+
+ var cp = m_contingentProperties;
+ if (cp != null) cp.SetCompleted();
+
+ FinishStageThree();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // Transitions the promise task into a successfully completed state with the specified result.
+ // This is dangerous, as no synchronization is used, and thus must only be used
+ // before this task is handed out to any consumers, before any continuations are hooked up,
+ // before its wait handle is accessed, etc. It's use is limited to places like in FromAsync
+ // where the operation completes synchronously, and thus we know we can forcefully complete
+ // the task, avoiding expensive completion paths, before the task is actually given to anyone.
+ internal void DangerousSetResult(TResult result)
+ {
+ Contract.Assert(!IsCompleted, "The promise must not yet be completed.");
+
+ // If we have a parent, we need to notify it of the completion. Take the slow path to handle that.
+ if (m_contingentProperties?.m_parent != null)
+ {
+ bool success = TrySetResult(result);
+
+ // Nobody else has had a chance to complete this Task yet, so we should succeed.
+ Contract.Assert(success);
+ }
+ else
+ {
+ m_result = result;
+ m_stateFlags |= TASK_STATE_RAN_TO_COMPLETION;
+ }
+ }
+
+ /// <summary>
+ /// Gets the result value of this <see cref="Task{TResult}"/>.
+ /// </summary>
+ /// <remarks>
+ /// The get accessor for this property ensures that the asynchronous operation is complete before
+ /// returning. Once the result of the computation is available, it is stored and will be returned
+ /// immediately on later calls to <see cref="Result"/>.
+ /// </remarks>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ public TResult Result
+ {
+ get { return IsWaitNotificationEnabledOrNotRanToCompletion ? GetResultCore(waitCompletionNotification: true) : m_result; }
+ }
+
+ /// <summary>
+ /// Gets the result value of this <see cref="Task{TResult}"/> once the task has completed successfully.
+ /// </summary>
+ /// <remarks>
+ /// This version of Result should only be used if the task completed successfully and if there's
+ /// no debugger wait notification enabled for this task.
+ /// </remarks>
+ internal TResult ResultOnSuccess
+ {
+ get
+ {
+ Contract.Assert(!IsWaitNotificationEnabledOrNotRanToCompletion,
+ "Should only be used when the task completed successfully and there's no wait notification enabled");
+ return m_result;
+ }
+ }
+
+ // Implements Result. Result delegates to this method if the result isn't already available.
+ internal TResult GetResultCore(bool waitCompletionNotification)
+ {
+ // If the result has not been calculated yet, wait for it.
+ if (!IsCompleted) InternalWait(Timeout.Infinite, default(CancellationToken)); // won't throw if task faulted or canceled; that's handled below
+
+ // Notify the debugger of the wait completion if it's requested such a notification
+ if (waitCompletionNotification) NotifyDebuggerOfWaitCompletionIfNecessary();
+
+ // Throw an exception if appropriate.
+ if (!IsRanToCompletion) ThrowIfExceptional(includeTaskCanceledExceptions: true);
+
+ // We shouldn't be here if the result has not been set.
+ Contract.Assert(IsRanToCompletion, "Task<T>.Result getter: Expected result to have been set.");
+
+ return m_result;
+ }
+
+ // Allow multiple exceptions to be assigned to a promise-style task.
+ // This is useful when a TaskCompletionSource<T> stands in as a proxy
+ // for a "real" task (as we do in Unwrap(), ContinueWhenAny() and ContinueWhenAll())
+ // and the "real" task ends up with multiple exceptions, which is possible when
+ // a task has children.
+ //
+ // Called from TaskCompletionSource<T>.SetException(IEnumerable<Exception>).
+ internal bool TrySetException(object exceptionObject)
+ {
+ Contract.Assert(m_action == null, "Task<T>.TrySetException(): non-null m_action");
+
+ // TCS.{Try}SetException() should have checked for this
+ Contract.Assert(exceptionObject != null, "Expected non-null exceptionObject argument");
+
+ // Only accept these types.
+ Contract.Assert(
+ (exceptionObject is Exception) || (exceptionObject is IEnumerable<Exception>) ||
+ (exceptionObject is ExceptionDispatchInfo) || (exceptionObject is IEnumerable<ExceptionDispatchInfo>),
+ "Expected exceptionObject to be either Exception, ExceptionDispatchInfo, or IEnumerable<> of one of those");
+
+ bool returnValue = false;
+
+ // "Reserve" the completion for this task, while making sure that: (1) No prior reservation
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // been recorded, and (4) Cancellation has not been requested.
+ //
+ // If the reservation is successful, then add the exception(s) and finish completion processing.
+ //
+ // The lazy initialization may not be strictly necessary, but I'd like to keep it here
+ // anyway. Some downstream logic may depend upon an inflated m_contingentProperties.
+ EnsureContingentPropertiesInitialized();
+ if (AtomicStateUpdate(TASK_STATE_COMPLETION_RESERVED,
+ TASK_STATE_COMPLETION_RESERVED | TASK_STATE_RAN_TO_COMPLETION | TASK_STATE_FAULTED | TASK_STATE_CANCELED))
+ {
+ AddException(exceptionObject); // handles singleton exception or exception collection
+ Finish(false);
+ returnValue = true;
+ }
+
+ return returnValue;
+
+ }
+
+ // internal helper function breaks out logic used by TaskCompletionSource and AsyncMethodBuilder
+ // If the tokenToRecord is not None, it will be stored onto the task.
+ // This method is only valid for promise tasks.
+ internal bool TrySetCanceled(CancellationToken tokenToRecord)
+ {
+ return TrySetCanceled(tokenToRecord, null);
+ }
+
+ // internal helper function breaks out logic used by TaskCompletionSource and AsyncMethodBuilder
+ // If the tokenToRecord is not None, it will be stored onto the task.
+ // If the OperationCanceledException is not null, it will be stored into the task's exception holder.
+ // This method is only valid for promise tasks.
+ internal bool TrySetCanceled(CancellationToken tokenToRecord, object cancellationException)
+ {
+ Contract.Assert(m_action == null, "Task<T>.TrySetCanceled(): non-null m_action");
+#if DEBUG
+ var ceAsEdi = cancellationException as ExceptionDispatchInfo;
+ Contract.Assert(
+ cancellationException == null ||
+ cancellationException is OperationCanceledException ||
+ (ceAsEdi != null && ceAsEdi.SourceException is OperationCanceledException),
+ "Expected null or an OperationCanceledException");
+#endif
+
+ bool returnValue = false;
+
+ // "Reserve" the completion for this task, while making sure that: (1) No prior reservation
+ // has been made, (2) The result has not already been set, (3) An exception has not previously
+ // been recorded, and (4) Cancellation has not been requested.
+ //
+ // If the reservation is successful, then record the cancellation and finish completion processing.
+ //
+ // Note: I had to access static Task variables through Task<object>
+ // instead of Task, because I have a property named Task and that
+ // was confusing the compiler.
+ if (AtomicStateUpdate(Task<object>.TASK_STATE_COMPLETION_RESERVED,
+ Task<object>.TASK_STATE_COMPLETION_RESERVED | Task<object>.TASK_STATE_CANCELED |
+ Task<object>.TASK_STATE_FAULTED | Task<object>.TASK_STATE_RAN_TO_COMPLETION))
+ {
+ RecordInternalCancellationRequest(tokenToRecord, cancellationException);
+ CancellationCleanupLogic(); // perform cancellation cleanup actions
+ returnValue = true;
+ }
+
+ return returnValue;
+ }
+
+ /// <summary>
+ /// Provides access to factory methods for creating <see cref="Task{TResult}"/> instances.
+ /// </summary>
+ /// <remarks>
+ /// The factory returned from <see cref="Factory"/> is a default instance
+ /// of <see cref="System.Threading.Tasks.TaskFactory{TResult}"/>, as would result from using
+ /// the default constructor on the factory type.
+ /// </remarks>
+ public new static TaskFactory<TResult> Factory { get { return s_Factory; } }
+
+ /// <summary>
+ /// Evaluates the value selector of the Task which is passed in as an object and stores the result.
+ /// </summary>
+ internal override void InnerInvoke()
+ {
+ // Invoke the delegate
+ Contract.Assert(m_action != null);
+ var func = m_action as Func<TResult>;
+ if (func != null)
+ {
+ m_result = func();
+ return;
+ }
+ var funcWithState = m_action as Func<object, TResult>;
+ if (funcWithState != null)
+ {
+ m_result = funcWithState(m_stateObject);
+ return;
+ }
+ Contract.Assert(false, "Invalid m_action in Task<TResult>");
+ }
+
+ #region Await Support
+
+ /// <summary>Gets an awaiter used to await this <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <returns>An awaiter instance.</returns>
+ /// <remarks>This method is intended for compiler user rather than use directly in code.</remarks>
+ public new TaskAwaiter<TResult> GetAwaiter()
+ {
+ return new TaskAwaiter<TResult>(this);
+ }
+
+ /// <summary>Configures an awaiter used to await this <see cref="System.Threading.Tasks.Task{TResult}"/>.</summary>
+ /// <param name="continueOnCapturedContext">
+ /// true to attempt to marshal the continuation back to the original context captured; otherwise, false.
+ /// </param>
+ /// <returns>An object used to await this task.</returns>
+ public new ConfiguredTaskAwaitable<TResult> ConfigureAwait(bool continueOnCapturedContext)
+ {
+ return new ConfiguredTaskAwaitable<TResult>(this, continueOnCapturedContext);
+ }
+
+ #endregion
+
+ #region Continuation methods
+
+ #region Action<Task<TResult>> continuations
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>> continuationAction)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>> continuationAction, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>> continuationAction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, only with a stack mark.
+ internal Task ContinueWith(Action<Task<TResult>> continuationAction, TaskScheduler scheduler, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ if (continuationAction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationAction);
+ }
+
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(
+ continuationOptions,
+ out creationOptions,
+ out internalOptions);
+
+ Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
+ this, continuationAction, null,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+ #endregion
+
+ #region Action<Task<TResult>, Object> continuations
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state,CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the continuation criteria specified through the <paramref
+ /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled
+ /// instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state,TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <param name="continuationAction">
+ /// An action to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation action.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new continuation task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task"/> will not be scheduled for execution until the current task has
+ /// completed. If the criteria specified through the <paramref name="continuationOptions"/> parameter
+ /// are not met, the continuation task will be canceled instead of scheduled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationAction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith(continuationAction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, only with a stack mark.
+ internal Task ContinueWith(Action<Task<TResult>, Object> continuationAction, Object state, TaskScheduler scheduler, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ if (continuationAction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationAction);
+ }
+
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(
+ continuationOptions,
+ out creationOptions,
+ out internalOptions);
+
+ Task continuationTask = new ContinuationTaskFromResultTask<TResult>(
+ this, continuationAction, state,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationTask, scheduler, cancellationToken, continuationOptions);
+
+ return continuationTask;
+ }
+
+ #endregion
+
+ #region Func<Task<TResult>,TNewResult> continuations
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task as an argument.
+ /// </param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </para>
+ /// <para>
+ /// The <paramref name="continuationFunction"/>, when executed, should return a <see
+ /// cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
+ /// from the ContinueWith call.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be passed as
+ /// an argument this completed task.
+ /// </param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </para>
+ /// <para>
+ /// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
+ /// This task's completion state will be transferred to the task returned from the
+ /// ContinueWith call.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, CancellationToken cancellationToken,
+ TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark.
+ internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, TNewResult> continuationFunction, TaskScheduler scheduler,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ if (continuationFunction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ }
+
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(
+ continuationOptions,
+ out creationOptions,
+ out internalOptions);
+
+ Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult,TNewResult>(
+ this, continuationFunction, null,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+
+ return continuationFuture;
+ }
+ #endregion
+
+ #region Func<Task<TResult>, Object,TNewResult> continuations
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ CancellationToken cancellationToken)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, state, scheduler, default(CancellationToken), TaskContinuationOptions.None, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current
+ /// task has completed, whether it completes due to running to completion successfully, faulting due
+ /// to an unhandled exception, or exiting out early due to being canceled.
+ /// </para>
+ /// <para>
+ /// The <paramref name="continuationFunction"/>, when executed, should return a <see
+ /// cref="Task{TNewResult}"/>. This task's completion state will be transferred to the task returned
+ /// from the ContinueWith call.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ TaskContinuationOptions continuationOptions)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, state, TaskScheduler.Current, default(CancellationToken), continuationOptions, ref stackMark);
+ }
+
+ /// <summary>
+ /// Creates a continuation that executes when the target <see cref="Task{TResult}"/> completes.
+ /// </summary>
+ /// <typeparam name="TNewResult">
+ /// The type of the result produced by the continuation.
+ /// </typeparam>
+ /// <param name="continuationFunction">
+ /// A function to run when the <see cref="Task{TResult}"/> completes. When run, the delegate will be
+ /// passed the completed task and the caller-supplied state object as arguments.
+ /// </param>
+ /// <param name="state">An object representing data to be used by the continuation function.</param>
+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> that will be assigned to the new task.</param>
+ /// <param name="continuationOptions">
+ /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such
+ /// as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled</see>, as
+ /// well as execution options, such as <see
+ /// cref="System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously</see>.
+ /// </param>
+ /// <param name="scheduler">
+ /// The <see cref="TaskScheduler"/> to associate with the continuation task and to use for its
+ /// execution.
+ /// </param>
+ /// <returns>A new continuation <see cref="Task{TNewResult}"/>.</returns>
+ /// <remarks>
+ /// <para>
+ /// The returned <see cref="Task{TNewResult}"/> will not be scheduled for execution until the current task has
+ /// completed, whether it completes due to running to completion successfully, faulting due to an
+ /// unhandled exception, or exiting out early due to being canceled.
+ /// </para>
+ /// <para>
+ /// The <paramref name="continuationFunction"/>, when executed, should return a <see cref="Task{TNewResult}"/>.
+ /// This task's completion state will be transferred to the task returned from the
+ /// ContinueWith call.
+ /// </para>
+ /// </remarks>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="continuationFunction"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentOutOfRangeException">
+ /// The <paramref name="continuationOptions"/> argument specifies an invalid value for <see
+ /// cref="T:System.Threading.Tasks.TaskContinuationOptions">TaskContinuationOptions</see>.
+ /// </exception>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="scheduler"/> argument is null.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">The provided <see cref="System.Threading.CancellationToken">CancellationToken</see>
+ /// has already been disposed.
+ /// </exception>
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var have to be marked non-inlineable
+ public Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return ContinueWith<TNewResult>(continuationFunction, state, scheduler, cancellationToken, continuationOptions, ref stackMark);
+ }
+
+ // Same as the above overload, just with a stack mark.
+ internal Task<TNewResult> ContinueWith<TNewResult>(Func<Task<TResult>, Object, TNewResult> continuationFunction, Object state,
+ TaskScheduler scheduler, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, ref StackCrawlMark stackMark)
+ {
+ if (continuationFunction == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction);
+ }
+
+ if (scheduler == null)
+ {
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.scheduler);
+ }
+
+ TaskCreationOptions creationOptions;
+ InternalTaskOptions internalOptions;
+ CreationOptionsFromContinuationOptions(
+ continuationOptions,
+ out creationOptions,
+ out internalOptions);
+
+ Task<TNewResult> continuationFuture = new ContinuationResultTaskFromResultTask<TResult,TNewResult>(
+ this, continuationFunction, state,
+ creationOptions, internalOptions,
+ ref stackMark
+ );
+
+ // Register the continuation. If synchronous execution is requested, this may
+ // actually invoke the continuation before returning.
+ ContinueWithCore(continuationFuture, scheduler, cancellationToken, continuationOptions);
+
+ return continuationFuture;
+ }
+
+ #endregion
+
+ #endregion
+
+ /// <summary>
+ /// Subscribes an <see cref="IObserver{TResult}"/> to receive notification of the final state of this <see cref="Task{TResult}"/>.
+ /// </summary>
+ /// <param name="observer">
+ /// The <see cref="IObserver{TResult}"/> to call on task completion. If this Task throws an exception,
+ /// observer.OnError is called with this Task's AggregateException. If this Task RanToCompletion,
+ /// observer.OnNext is called with this Task's result, followed by a call to observer.OnCompleted.
+ /// If this Task is Canceled, observer.OnError is called with a TaskCanceledException
+ /// containing this Task's CancellationToken
+ /// </param>
+ /// <returns>An IDisposable object <see cref="Task"/>.</returns>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// The <paramref name="observer"/> argument is null.
+ /// </exception>
+#if SUPPORT_IOBSERVABLE
+ IDisposable IObservable<TResult>.Subscribe(IObserver<TResult> observer)
+ {
+ if (observer == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.observer);
+
+
+ var continuationTask =
+ this.ContinueWith(delegate(Task<TResult> observedTask, object taskObserverObject)
+ {
+ IObserver<TResult> taskObserver = (IObserver<TResult>)taskObserverObject;
+ if (observedTask.IsFaulted)
+ taskObserver.OnError(observedTask.Exception);
+ else if (observedTask.IsCanceled)
+ taskObserver.OnError(new TaskCanceledException(observedTask));
+ else
+ {
+ taskObserver.OnNext(observedTask.Result);
+ taskObserver.OnCompleted();
+ }
+
+ }, observer, TaskScheduler.Default);
+
+ return new DisposableSubscription(this, continuationTask);
+ }
+#endif
+ }
+
+#if SUPPORT_IOBSERVABLE
+ // Class that calls RemoveContinuation if Dispose() is called before task completion
+ internal class DisposableSubscription : IDisposable
+ {
+ private Task _notifyObserverContinuationTask;
+ private Task _observedTask;
+
+ internal DisposableSubscription(Task observedTask, Task notifyObserverContinuationTask)
+ {
+ _observedTask = observedTask;
+ _notifyObserverContinuationTask = notifyObserverContinuationTask;
+ }
+ void IDisposable.Dispose()
+ {
+ Task localObservedTask = _observedTask;
+ Task localNotifyingContinuationTask = _notifyObserverContinuationTask;
+ if (localObservedTask != null && localNotifyingContinuationTask != null && !localObservedTask.IsCompleted)
+ {
+ localObservedTask.RemoveContinuation(localNotifyingContinuationTask);
+ }
+ _observedTask = null;
+ _notifyObserverContinuationTask = null;
+ }
+ }
+#endif
+
+ // Proxy class for better debugging experience
+ internal class SystemThreadingTasks_FutureDebugView<TResult>
+ {
+ private Task<TResult> m_task;
+
+ public SystemThreadingTasks_FutureDebugView(Task<TResult> task)
+ {
+ m_task = task;
+ }
+
+ public TResult Result { get { return m_task.Status == TaskStatus.RanToCompletion ? m_task.Result : default(TResult); } }
+ public object AsyncState { get { return m_task.AsyncState; } }
+ public TaskCreationOptions CreationOptions { get { return m_task.CreationOptions; } }
+ public Exception Exception { get { return m_task.Exception; } }
+ public int Id { get { return m_task.Id; } }
+ public bool CancellationPending { get { return (m_task.Status == TaskStatus.WaitingToRun) && m_task.CancellationToken.IsCancellationRequested; } }
+ public TaskStatus Status { get { return m_task.Status; } }
+
+
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Thread.cs b/src/mscorlib/src/System/Threading/Thread.cs
new file mode 100644
index 0000000000..e62cfae9fe
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Thread.cs
@@ -0,0 +1,1756 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Class for creating and managing a thread.
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+ using System.Threading;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+#if FEATURE_REMOTING
+ using System.Runtime.Remoting.Contexts;
+ using System.Runtime.Remoting.Messaging;
+#endif
+ using System;
+ using System.Diagnostics;
+ using System.Security.Permissions;
+ using System.Security.Principal;
+ using System.Globalization;
+ using System.Collections.Generic;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Security;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ internal delegate Object InternalCrossContextDelegate(Object[] args);
+
+ internal class ThreadHelper
+ {
+ [System.Security.SecuritySafeCritical]
+ static ThreadHelper() {}
+
+ Delegate _start;
+ Object _startArg = null;
+ ExecutionContext _executionContext = null;
+ internal ThreadHelper(Delegate start)
+ {
+ _start = start;
+ }
+
+ internal void SetExecutionContextHelper(ExecutionContext ec)
+ {
+ _executionContext = ec;
+ }
+
+ [System.Security.SecurityCritical]
+ static internal ContextCallback _ccb = new ContextCallback(ThreadStart_Context);
+
+ [System.Security.SecurityCritical]
+ static private void ThreadStart_Context(Object state)
+ {
+ ThreadHelper t = (ThreadHelper)state;
+ if (t._start is ThreadStart)
+ {
+ ((ThreadStart)t._start)();
+ }
+ else
+ {
+ ((ParameterizedThreadStart)t._start)(t._startArg);
+ }
+ }
+
+ // call back helper
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #else
+ [System.Security.SecurityCritical]
+ #endif
+ internal void ThreadStart(object obj)
+ {
+ _startArg = obj;
+ if (_executionContext != null)
+ {
+ ExecutionContext.Run(_executionContext, _ccb, (Object)this);
+ }
+ else
+ {
+ ((ParameterizedThreadStart)_start)(obj);
+ }
+ }
+
+ // call back helper
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #else
+ [System.Security.SecurityCritical]
+ #endif
+ internal void ThreadStart()
+ {
+ if (_executionContext != null)
+ {
+ ExecutionContext.Run(_executionContext, _ccb, (Object)this);
+ }
+ else
+ {
+ ((ThreadStart)_start)();
+ }
+ }
+ }
+
+ internal struct ThreadHandle
+ {
+ private IntPtr m_ptr;
+
+ internal ThreadHandle(IntPtr pThread)
+ {
+ m_ptr = pThread;
+ }
+ }
+
+ // deliberately not [serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Thread))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Thread : CriticalFinalizerObject, _Thread
+ {
+ /*=========================================================================
+ ** Data accessed from managed code that needs to be defined in
+ ** ThreadBaseObject to maintain alignment between the two classes.
+ ** DON'T CHANGE THESE UNLESS YOU MODIFY ThreadBaseObject in vm\object.h
+ =========================================================================*/
+#if FEATURE_REMOTING
+ private Context m_Context;
+#endif
+ private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
+#if FEATURE_CORECLR
+ private SynchronizationContext m_SynchronizationContext; // On CoreCLR, this is maintained separately from ExecutionContext
+#endif
+
+ private String m_Name;
+ private Delegate m_Delegate; // Delegate
+
+#if FEATURE_LEAK_CULTURE_INFO
+ private CultureInfo m_CurrentCulture;
+ private CultureInfo m_CurrentUICulture;
+#endif
+ private Object m_ThreadStartArg;
+
+ /*=========================================================================
+ ** The base implementation of Thread is all native. The following fields
+ ** should never be used in the C# code. They are here to define the proper
+ ** space so the thread object may be allocated. DON'T CHANGE THESE UNLESS
+ ** YOU MODIFY ThreadBaseObject in vm\object.h
+ =========================================================================*/
+#pragma warning disable 169
+#pragma warning disable 414 // These fields are not used from managed.
+ // IntPtrs need to be together, and before ints, because IntPtrs are 64-bit
+ // fields on 64-bit platforms, where they will be sorted together.
+
+ private IntPtr DONT_USE_InternalThread; // Pointer
+ private int m_Priority; // INT32
+ private int m_ManagedThreadId; // INT32
+
+#pragma warning restore 414
+#pragma warning restore 169
+
+ private bool m_ExecutionContextBelongsToOuterScope;
+#if DEBUG
+ private bool m_ForbidExecutionContextMutation;
+#endif
+
+ /*=========================================================================
+ ** This manager is responsible for storing the global data that is
+ ** shared amongst all the thread local stores.
+ =========================================================================*/
+ static private LocalDataStoreMgr s_LocalDataStoreMgr;
+
+ /*=========================================================================
+ ** Thread-local data store
+ =========================================================================*/
+ [ThreadStatic]
+ static private LocalDataStoreHolder s_LocalDataStore;
+
+ // Do not move! Order of above fields needs to be preserved for alignment
+ // with native code
+ // See code:#threadCultureInfo
+#if !FEATURE_LEAK_CULTURE_INFO
+ [ThreadStatic]
+ internal static CultureInfo m_CurrentCulture;
+ [ThreadStatic]
+ internal static CultureInfo m_CurrentUICulture;
+#endif
+
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentCulture;
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentUICulture;
+
+ static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+#if FEATURE_LEAK_CULTURE_INFO
+ Thread.CurrentThread.m_CurrentCulture = args.CurrentValue;
+#else
+ m_CurrentCulture = args.CurrentValue;
+#endif // FEATURE_LEAK_CULTURE_INFO
+ }
+
+ static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+#if FEATURE_LEAK_CULTURE_INFO
+ Thread.CurrentThread.m_CurrentUICulture = args.CurrentValue;
+#else
+ m_CurrentUICulture = args.CurrentValue;
+#endif // FEATURE_LEAK_CULTURE_INFO
+ }
+
+#if FEATURE_CORECLR
+ // Adding an empty default ctor for annotation purposes
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal Thread(){}
+#endif // FEATURE_CORECLR
+
+ /*=========================================================================
+ ** Creates a new Thread object which will begin execution at
+ ** start.ThreadStart on a new thread when the Start method is called.
+ **
+ ** Exceptions: ArgumentNullException if start == null.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Thread(ThreadStart start) {
+ if (start == null) {
+ throw new ArgumentNullException("start");
+ }
+ Contract.EndContractBlock();
+ SetStartHelper((Delegate)start,0); //0 will setup Thread with default stackSize
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Thread(ThreadStart start, int maxStackSize) {
+ if (start == null) {
+ throw new ArgumentNullException("start");
+ }
+ if (0 > maxStackSize)
+ throw new ArgumentOutOfRangeException("maxStackSize",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ SetStartHelper((Delegate)start, maxStackSize);
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Thread(ParameterizedThreadStart start) {
+ if (start == null) {
+ throw new ArgumentNullException("start");
+ }
+ Contract.EndContractBlock();
+ SetStartHelper((Delegate)start, 0);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Thread(ParameterizedThreadStart start, int maxStackSize) {
+ if (start == null) {
+ throw new ArgumentNullException("start");
+ }
+ if (0 > maxStackSize)
+ throw new ArgumentOutOfRangeException("maxStackSize",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ Contract.EndContractBlock();
+ SetStartHelper((Delegate)start, maxStackSize);
+ }
+
+ [ComVisible(false)]
+ public override int GetHashCode()
+ {
+ return m_ManagedThreadId;
+ }
+
+ extern public int ManagedThreadId
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get;
+ }
+
+ // Returns handle for interop with EE. The handle is guaranteed to be non-null.
+ internal unsafe ThreadHandle GetNativeHandle()
+ {
+ IntPtr thread = DONT_USE_InternalThread;
+
+ // This should never happen under normal circumstances. m_assembly is always assigned before it is handed out to the user.
+ // There are ways how to create an unitialized objects through remoting, etc. Avoid AVing in the EE by throwing a nice
+ // exception here.
+ if (thread.IsNull())
+ throw new ArgumentException(null, Environment.GetResourceString("Argument_InvalidHandle"));
+
+ return new ThreadHandle(thread);
+ }
+
+
+ /*=========================================================================
+ ** Spawns off a new thread which will begin executing at the ThreadStart
+ ** method on the IThreadable interface passed in the constructor. Once the
+ ** thread is dead, it cannot be restarted with another call to Start.
+ **
+ ** Exceptions: ThreadStateException if the thread has already been started.
+ =========================================================================*/
+ [HostProtection(Synchronization=true,ExternalThreading=true)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Start()
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Start(ref stackMark);
+ }
+
+ [HostProtection(Synchronization=true,ExternalThreading=true)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public void Start(object parameter)
+ {
+ //In the case of a null delegate (second call to start on same thread)
+ // StartInternal method will take care of the error reporting
+ if(m_Delegate is ThreadStart)
+ {
+ //We expect the thread to be setup with a ParameterizedThreadStart
+ // if this constructor is called.
+ //If we got here then that wasn't the case
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ThreadWrongThreadStart"));
+ }
+ m_ThreadStartArg = parameter;
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ Start(ref stackMark);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ private void Start(ref StackCrawlMark stackMark)
+ {
+#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
+ // Eagerly initialize the COM Apartment state of the thread if we're allowed to.
+ StartupSetApartmentStateInternal();
+#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
+
+ // Attach current thread's security principal object to the new
+ // thread. Be careful not to bind the current thread to a principal
+ // if it's not already bound.
+ if (m_Delegate != null)
+ {
+ // If we reach here with a null delegate, something is broken. But we'll let the StartInternal method take care of
+ // reporting an error. Just make sure we dont try to dereference a null delegate.
+ ThreadHelper t = (ThreadHelper)(m_Delegate.Target);
+ ExecutionContext ec = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx);
+ t.SetExecutionContextHelper(ec);
+ }
+#if FEATURE_IMPERSONATION
+ IPrincipal principal = (IPrincipal)CallContext.Principal;
+#else
+ IPrincipal principal = null;
+#endif
+ StartInternal(principal, ref stackMark);
+ }
+
+
+#if FEATURE_CORECLR
+ internal ExecutionContext ExecutionContext
+ {
+ get { return m_ExecutionContext; }
+ set { m_ExecutionContext = value; }
+ }
+
+ internal SynchronizationContext SynchronizationContext
+ {
+ get { return m_SynchronizationContext; }
+ set { m_SynchronizationContext = value; }
+ }
+#else // !FEATURE_CORECLR
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal ExecutionContext.Reader GetExecutionContextReader()
+ {
+ return new ExecutionContext.Reader(m_ExecutionContext);
+ }
+
+ internal bool ExecutionContextBelongsToCurrentScope
+ {
+ get { return !m_ExecutionContextBelongsToOuterScope; }
+ set { m_ExecutionContextBelongsToOuterScope = !value; }
+ }
+
+#if DEBUG
+ internal bool ForbidExecutionContextMutation
+ {
+ set { m_ForbidExecutionContextMutation = value; }
+ }
+#endif
+
+ // note: please don't access this directly from mscorlib. Use GetMutableExecutionContext or GetExecutionContextReader instead.
+ public ExecutionContext ExecutionContext
+ {
+ [SecuritySafeCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ get
+ {
+ ExecutionContext result;
+ if (this == Thread.CurrentThread)
+ result = GetMutableExecutionContext();
+ else
+ result = m_ExecutionContext;
+
+ return result;
+ }
+ }
+
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal ExecutionContext GetMutableExecutionContext()
+ {
+ Contract.Assert(Thread.CurrentThread == this);
+#if DEBUG
+ Contract.Assert(!m_ForbidExecutionContextMutation);
+#endif
+ if (m_ExecutionContext == null)
+ {
+ m_ExecutionContext = new ExecutionContext();
+ }
+ else if (!ExecutionContextBelongsToCurrentScope)
+ {
+ ExecutionContext copy = m_ExecutionContext.CreateMutableCopy();
+ m_ExecutionContext = copy;
+ }
+
+ ExecutionContextBelongsToCurrentScope = true;
+ return m_ExecutionContext;
+ }
+
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal void SetExecutionContext(ExecutionContext value, bool belongsToCurrentScope)
+ {
+ m_ExecutionContext = value;
+ ExecutionContextBelongsToCurrentScope = belongsToCurrentScope;
+ }
+
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal void SetExecutionContext(ExecutionContext.Reader value, bool belongsToCurrentScope)
+ {
+ m_ExecutionContext = value.DangerousGetRawExecutionContext();
+ ExecutionContextBelongsToCurrentScope = belongsToCurrentScope;
+ }
+#endif //!FEATURE_CORECLR
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void StartInternal(IPrincipal principal, ref StackCrawlMark stackMark);
+#if FEATURE_COMPRESSEDSTACK
+ /// <internalonly/>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [DynamicSecurityMethodAttribute()]
+ [Obsolete("Thread.SetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
+ public void SetCompressedStack( CompressedStack stack )
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ThreadAPIsNotSupported"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern IntPtr SetAppDomainStack( SafeCompressedStackHandle csHandle);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ internal extern void RestoreAppDomainStack( IntPtr appDomainStack);
+
+
+ /// <internalonly/>
+ [System.Security.SecurityCritical] // auto-generated_required
+ [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")]
+ public CompressedStack GetCompressedStack()
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ThreadAPIsNotSupported"));
+ }
+#endif // #if FEATURE_COMPRESSEDSTACK
+
+
+ // Helper method to get a logical thread ID for StringBuilder (for
+ // correctness) and for FileStream's async code path (for perf, to
+ // avoid creating a Thread instance).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern static IntPtr InternalGetCurrentThread();
+
+ /*=========================================================================
+ ** Raises a ThreadAbortException in the thread, which usually
+ ** results in the thread's death. The ThreadAbortException is a special
+ ** exception that is not catchable. The finally clauses of all try
+ ** statements will be executed before the thread dies. This includes the
+ ** finally that a thread might be executing at the moment the Abort is raised.
+ ** The thread is not stopped immediately--you must Join on the
+ ** thread to guarantee it has stopped.
+ ** It is possible for a thread to do an unbounded amount of computation in
+ ** the finally's and thus indefinitely delay the threads death.
+ ** If Abort() is called on a thread that has not been started, the thread
+ ** will abort when Start() is called.
+ ** If Abort is called twice on the same thread, a DuplicateThreadAbort
+ ** exception is thrown.
+ =========================================================================*/
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread=true)]
+ public void Abort(Object stateInfo)
+ {
+ // If two aborts come at the same time, it is possible that the state info
+ // gets set by one, and the actual abort gets delivered by another. But this
+ // is not distinguishable by an application.
+ // The accessor helper will only set the value if it isn't already set,
+ // and that particular bit of native code can test much faster than this
+ // code could, because testing might cause a cross-appdomain marshalling.
+ AbortReason = stateInfo;
+
+ // Note: we demand ControlThread permission, then call AbortInternal directly
+ // rather than delegating to the Abort() function below. We do this to ensure
+ // that only callers with ControlThread are allowed to change the AbortReason
+ // of the thread. We call AbortInternal directly to avoid demanding the same
+ // permission twice.
+ AbortInternal();
+ }
+#endif
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
+#pragma warning restore 618
+ public void Abort()
+ {
+ AbortInternal();
+ }
+
+ // Internal helper (since we can't place security demands on
+ // ecalls/fcalls).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void AbortInternal();
+
+#if !FEATURE_CORECLR
+ /*=========================================================================
+ ** Resets a thread abort.
+ ** Should be called by trusted code only
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread=true)]
+ public static void ResetAbort()
+ {
+ Thread thread = Thread.CurrentThread;
+ if ((thread.ThreadState & ThreadState.AbortRequested) == 0)
+ throw new ThreadStateException(Environment.GetResourceString("ThreadState_NoAbortRequested"));
+ thread.ResetAbortNative();
+ thread.ClearAbortReason();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void ResetAbortNative();
+
+ /*=========================================================================
+ ** Suspends the thread. If the thread is already suspended, this call has
+ ** no effect.
+ **
+ ** Exceptions: ThreadStateException if the thread has not been started or
+ ** it is dead.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("Thread.Suspend has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. http://go.microsoft.com/fwlink/?linkid=14202", false)][SecurityPermission(SecurityAction.Demand, ControlThread=true)]
+ [SecurityPermission(SecurityAction.Demand, ControlThread=true)]
+ public void Suspend() { SuspendInternal(); }
+
+ // Internal helper (since we can't place security demands on
+ // ecalls/fcalls).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void SuspendInternal();
+
+ /*=========================================================================
+ ** Resumes a thread that has been suspended.
+ **
+ ** Exceptions: ThreadStateException if the thread has not been started or
+ ** it is dead or it isn't in the suspended state.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("Thread.Resume has been deprecated. Please use other classes in System.Threading, such as Monitor, Mutex, Event, and Semaphore, to synchronize Threads or protect resources. http://go.microsoft.com/fwlink/?linkid=14202", false)]
+ [SecurityPermission(SecurityAction.Demand, ControlThread=true)]
+ public void Resume() { ResumeInternal(); }
+
+ // Internal helper (since we can't place security demands on
+ // ecalls/fcalls).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void ResumeInternal();
+
+ /*=========================================================================
+ ** Interrupts a thread that is inside a Wait(), Sleep() or Join(). If that
+ ** thread is not currently blocked in that manner, it will be interrupted
+ ** when it next begins to block.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermission(SecurityAction.Demand, ControlThread=true)]
+ public void Interrupt() { InterruptInternal(); }
+
+ // Internal helper (since we can't place security demands on
+ // ecalls/fcalls).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void InterruptInternal();
+#endif
+
+ /*=========================================================================
+ ** Returns the priority of the thread.
+ **
+ ** Exceptions: ThreadStateException if the thread is dead.
+ =========================================================================*/
+
+ public ThreadPriority Priority {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return (ThreadPriority)GetPriorityNative(); }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(SelfAffectingThreading=true)]
+ set { SetPriorityNative((int)value); }
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int GetPriorityNative();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void SetPriorityNative(int priority);
+
+ /*=========================================================================
+ ** Returns true if the thread has been started and is not dead.
+ =========================================================================*/
+ public extern bool IsAlive {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ /*=========================================================================
+ ** Returns true if the thread is a threadpool thread.
+ =========================================================================*/
+ public extern bool IsThreadPoolThread {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ get;
+ }
+
+ /*=========================================================================
+ ** Waits for the thread to die or for timeout milliseconds to elapse.
+ ** Returns true if the thread died, or false if the wait timed out. If
+ ** Timeout.Infinite is given as the parameter, no timeout will occur.
+ **
+ ** Exceptions: ArgumentException if timeout < 0.
+ ** ThreadInterruptedException if the thread is interrupted while waiting.
+ ** ThreadStateException if the thread has not been started yet.
+ =========================================================================*/
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool JoinInternal(int millisecondsTimeout);
+
+ [System.Security.SecuritySafeCritical]
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ public void Join()
+ {
+ JoinInternal(Timeout.Infinite);
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ public bool Join(int millisecondsTimeout)
+ {
+ return JoinInternal(millisecondsTimeout);
+ }
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ public bool Join(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+
+ return Join((int)tm);
+ }
+
+ /*=========================================================================
+ ** Suspends the current thread for timeout milliseconds. If timeout == 0,
+ ** forces the thread to give up the remainer of its timeslice. If timeout
+ ** == Timeout.Infinite, no timeout will occur.
+ **
+ ** Exceptions: ArgumentException if timeout < 0.
+ ** ThreadInterruptedException if the thread is interrupted while sleeping.
+ =========================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void SleepInternal(int millisecondsTimeout);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void Sleep(int millisecondsTimeout)
+ {
+ SleepInternal(millisecondsTimeout);
+ // Ensure we don't return to app code when the pause is underway
+ if(AppDomainPauseManager.IsPaused)
+ AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
+ }
+
+ public static void Sleep(TimeSpan timeout)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1 || tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Sleep((int)tm);
+ }
+
+
+ /* wait for a length of time proportial to 'iterations'. Each iteration is should
+ only take a few machine instructions. Calling this API is preferable to coding
+ a explict busy loop because the hardware can be informed that it is busy waiting. */
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [HostProtection(Synchronization=true,ExternalThreading=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern void SpinWaitInternal(int iterations);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true,ExternalThreading=true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void SpinWait(int iterations)
+ {
+ SpinWaitInternal(iterations);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ private static extern bool YieldInternal();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static bool Yield()
+ {
+ return YieldInternal();
+ }
+
+ public static Thread CurrentThread {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ get {
+ Contract.Ensures(Contract.Result<Thread>() != null);
+ return GetCurrentThreadNative();
+ }
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern Thread GetCurrentThreadNative();
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetStartHelper(Delegate start, int maxStackSize)
+ {
+#if FEATURE_CORECLR
+ // We only support default stacks in CoreCLR
+ Contract.Assert(maxStackSize == 0);
+#else
+ // Only fully-trusted code is allowed to create "large" stacks. Partial-trust falls back to
+ // the default stack size.
+ ulong defaultStackSize = GetProcessDefaultStackSize();
+ if ((ulong)(uint)maxStackSize > defaultStackSize)
+ {
+ try
+ {
+ SecurityPermission.Demand(PermissionType.FullTrust);
+ }
+ catch (SecurityException)
+ {
+ maxStackSize = (int)Math.Min(defaultStackSize, (ulong)(uint)int.MaxValue);
+ }
+ }
+#endif
+
+ ThreadHelper threadStartCallBack = new ThreadHelper(start);
+ if(start is ThreadStart)
+ {
+ SetStart(new ThreadStart(threadStartCallBack.ThreadStart), maxStackSize);
+ }
+ else
+ {
+ SetStart(new ParameterizedThreadStart(threadStartCallBack.ThreadStart), maxStackSize);
+ }
+ }
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern ulong GetProcessDefaultStackSize();
+
+ /*=========================================================================
+ ** PRIVATE Sets the IThreadable interface for the thread. Assumes that
+ ** start != null.
+ =========================================================================*/
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void SetStart(Delegate start, int maxStackSize);
+
+ /*=========================================================================
+ ** Clean up the thread when it goes away.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ ~Thread()
+ {
+ // Delegate to the unmanaged portion.
+ InternalFinalize();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void InternalFinalize();
+
+#if FEATURE_COMINTEROP
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern void DisableComObjectEagerCleanup();
+#endif //FEATURE_COMINTEROP
+
+ /*=========================================================================
+ ** Return whether or not this thread is a background thread. Background
+ ** threads do not affect when the Execution Engine shuts down.
+ **
+ ** Exceptions: ThreadStateException if the thread is dead.
+ =========================================================================*/
+ public bool IsBackground {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return IsBackgroundNative(); }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(SelfAffectingThreading=true)]
+ set { SetBackgroundNative(value); }
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern bool IsBackgroundNative();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void SetBackgroundNative(bool isBackground);
+
+
+ /*=========================================================================
+ ** Return the thread state as a consistent set of bits. This is more
+ ** general then IsAlive or IsBackground.
+ =========================================================================*/
+ public ThreadState ThreadState {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return (ThreadState)GetThreadStateNative(); }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int GetThreadStateNative();
+
+#if FEATURE_COMINTEROP_APARTMENT_SUPPORT
+ /*=========================================================================
+ ** An unstarted thread can be marked to indicate that it will host a
+ ** single-threaded or multi-threaded apartment.
+ **
+ ** Exceptions: ArgumentException if state is not a valid apartment state
+ ** (ApartmentSTA or ApartmentMTA).
+ =========================================================================*/
+ [Obsolete("The ApartmentState property has been deprecated. Use GetApartmentState, SetApartmentState or TrySetApartmentState instead.", false)]
+ public ApartmentState ApartmentState
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return (ApartmentState)GetApartmentStateNative();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true, SelfAffectingThreading=true)]
+ set
+ {
+ SetApartmentStateNative((int)value, true);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public ApartmentState GetApartmentState()
+ {
+ return (ApartmentState)GetApartmentStateNative();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true, SelfAffectingThreading=true)]
+ public bool TrySetApartmentState(ApartmentState state)
+ {
+ return SetApartmentStateHelper(state, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true, SelfAffectingThreading=true)]
+ public void SetApartmentState(ApartmentState state)
+ {
+ bool result = SetApartmentStateHelper(state, true);
+ if (!result)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ApartmentStateSwitchFailed"));
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch)
+ {
+ ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state, fireMDAOnMismatch);
+
+ // Special case where we pass in Unknown and get back MTA.
+ // Once we CoUninitialize the thread, the OS will still
+ // report the thread as implicitly in the MTA if any
+ // other thread in the process is CoInitialized.
+ if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA))
+ return true;
+
+ if (retState != state)
+ return false;
+
+ return true;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int GetApartmentStateNative();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern int SetApartmentStateNative(int state, bool fireMDAOnMismatch);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern void StartupSetApartmentStateInternal();
+#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
+
+ /*=========================================================================
+ ** Allocates an un-named data slot. The slot is allocated on ALL the
+ ** threads.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static LocalDataStoreSlot AllocateDataSlot()
+ {
+ return LocalDataStoreManager.AllocateDataSlot();
+ }
+
+ /*=========================================================================
+ ** Allocates a named data slot. The slot is allocated on ALL the
+ ** threads. Named data slots are "public" and can be manipulated by
+ ** anyone.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static LocalDataStoreSlot AllocateNamedDataSlot(String name)
+ {
+ return LocalDataStoreManager.AllocateNamedDataSlot(name);
+ }
+
+ /*=========================================================================
+ ** Looks up a named data slot. If the name has not been used, a new slot is
+ ** allocated. Named data slots are "public" and can be manipulated by
+ ** anyone.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static LocalDataStoreSlot GetNamedDataSlot(String name)
+ {
+ return LocalDataStoreManager.GetNamedDataSlot(name);
+ }
+
+ /*=========================================================================
+ ** Frees a named data slot. The slot is allocated on ALL the
+ ** threads. Named data slots are "public" and can be manipulated by
+ ** anyone.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static void FreeNamedDataSlot(String name)
+ {
+ LocalDataStoreManager.FreeNamedDataSlot(name);
+ }
+
+ /*=========================================================================
+ ** Retrieves the value from the specified slot on the current thread, for that thread's current domain.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static Object GetData(LocalDataStoreSlot slot)
+ {
+ LocalDataStoreHolder dls = s_LocalDataStore;
+ if (dls == null)
+ {
+ // Make sure to validate the slot even if we take the quick path
+ LocalDataStoreManager.ValidateSlot(slot);
+ return null;
+ }
+
+ return dls.Store.GetData(slot);
+ }
+
+ /*=========================================================================
+ ** Sets the data in the specified slot on the currently running thread, for that thread's current domain.
+ =========================================================================*/
+ [HostProtection(SharedState=true, ExternalThreading=true)]
+ public static void SetData(LocalDataStoreSlot slot, Object data)
+ {
+ LocalDataStoreHolder dls = s_LocalDataStore;
+
+ // Create new DLS if one hasn't been created for this domain for this thread
+ if (dls == null) {
+ dls = LocalDataStoreManager.CreateLocalDataStore();
+ s_LocalDataStore = dls;
+ }
+
+ dls.Store.SetData(slot, data);
+ }
+
+
+ // #threadCultureInfo
+ //
+ // Background:
+ // In the desktop runtime, we allow a thread's cultures to travel with the thread
+ // across AppDomain boundaries. Furthermore we update the native thread with the
+ // culture of the managed thread. Because of security concerns and potential SxS
+ // effects, in Silverlight we are making the changes listed below.
+ //
+ // Silverlight Changes:
+ // - thread instance member cultures (CurrentCulture and CurrentUICulture)
+ // confined within AppDomains
+ // - changes to these properties don't affect the underlying native thread
+ //
+ // Ifdef:
+ // FEATURE_LEAK_CULTURE_INFO : CultureInfos can leak across AppDomains, not
+ // enabled in Silverlight
+ //
+ // Implementation notes:
+ // In Silverlight, culture members thread static (per Thread, per AppDomain).
+ //
+ // Quirks:
+ // An interesting side-effect of isolating cultures within an AppDomain is that we
+ // now need to special case resource lookup for mscorlib, which transitions to the
+ // default domain to lookup resources. See Environment.cs for more details.
+ //
+#if FEATURE_LEAK_CULTURE_INFO
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern private bool nativeGetSafeCulture(Thread t, int appDomainId, bool isUI, ref CultureInfo safeCulture);
+#endif // FEATURE_LEAK_CULTURE_INFO
+
+ // As the culture can be customized object then we cannot hold any
+ // reference to it before we check if it is safe because the app domain
+ // owning this customized culture may get unloaded while executing this
+ // code. To achieve that we have to do the check using nativeGetSafeCulture
+ // as the thread cannot get interrupted during the FCALL.
+ // If the culture is safe (not customized or created in current app domain)
+ // then the FCALL will return a reference to that culture otherwise the
+ // FCALL will return failure. In case of failure we'll return the default culture.
+ // If the app domain owning a customized culture that is set to the thread and this
+ // app domain get unloaded there is a code to clean up the culture from the thread
+ // using the code in AppDomain::ReleaseDomainStores.
+
+ public CultureInfo CurrentUICulture {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+#if FEATURE_APPX && !FEATURE_COREFX_GLOBALIZATION
+ if(AppDomain.IsAppXModel()) {
+ return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentUICultureNoAppX();
+ }
+ else
+#endif
+ {
+ return GetCurrentUICultureNoAppX();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading=true)]
+ set {
+ if (value == null) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ //If they're trying to use a Culture with a name that we can't use in resource lookup,
+ //don't even let them set it on the thread.
+ CultureInfo.VerifyCultureName(value, true);
+
+ // If you add more pre-conditions to this method, check to see if you also need to
+ // add them to CultureInfo.DefaultThreadCurrentUICulture.set.
+
+#if FEATURE_LEAK_CULTURE_INFO
+ if (nativeSetThreadUILocale(value.SortName) == false)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidResourceCultureName", value.Name));
+ }
+ value.StartCrossDomainTracking();
+#else
+ if (m_CurrentUICulture == null && m_CurrentCulture == null)
+ nativeInitCultureAccessors();
+#endif
+
+ if (!AppContextSwitches.NoAsyncCurrentCulture)
+ {
+ if (s_asyncLocalCurrentUICulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentUICulture), null);
+ }
+
+ // this one will set m_CurrentUICulture too
+ s_asyncLocalCurrentUICulture.Value = value;
+ }
+ else
+ {
+ m_CurrentUICulture = value;
+ }
+ }
+ }
+
+#if FEATURE_LEAK_CULTURE_INFO
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ internal CultureInfo GetCurrentUICultureNoAppX() {
+
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return CultureInfo.CurrentUICulture;
+#else
+
+ // Fetch a local copy of m_CurrentUICulture to
+ // avoid race conditions that malicious user can introduce
+ if (m_CurrentUICulture == null) {
+ CultureInfo appDomainDefaultUICulture = CultureInfo.DefaultThreadCurrentUICulture;
+ return (appDomainDefaultUICulture != null ? appDomainDefaultUICulture : CultureInfo.UserDefaultUICulture);
+ }
+
+#if FEATURE_LEAK_CULTURE_INFO
+ CultureInfo culture = null;
+
+ if (!nativeGetSafeCulture(this, GetDomainID(), true, ref culture) || culture == null) {
+ return CultureInfo.UserDefaultUICulture;
+ }
+
+ return culture;
+#else
+ return m_CurrentUICulture;
+#endif
+#endif
+ }
+
+ // This returns the exposed context for a given context ID.
+#if FEATURE_LEAK_CULTURE_INFO
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ static extern private bool nativeSetThreadUILocale(String locale);
+#endif
+
+ // As the culture can be customized object then we cannot hold any
+ // reference to it before we check if it is safe because the app domain
+ // owning this customized culture may get unloaded while executing this
+ // code. To achieve that we have to do the check using nativeGetSafeCulture
+ // as the thread cannot get interrupted during the FCALL.
+ // If the culture is safe (not customized or created in current app domain)
+ // then the FCALL will return a reference to that culture otherwise the
+ // FCALL will return failure. In case of failure we'll return the default culture.
+ // If the app domain owning a customized culture that is set to the thread and this
+ // app domain get unloaded there is a code to clean up the culture from the thread
+ // using the code in AppDomain::ReleaseDomainStores.
+
+ public CultureInfo CurrentCulture {
+ get {
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+#if FEATURE_APPX && !FEATURE_COREFX_GLOBALIZATION
+ if(AppDomain.IsAppXModel()) {
+ return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentCultureNoAppX();
+ }
+ else
+#endif
+ {
+ return GetCurrentCultureNoAppX();
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+#if FEATURE_LEAK_CULTURE_INFO
+ [SecurityPermission(SecurityAction.Demand, ControlThread = true)]
+#endif
+ set {
+ if (null==value) {
+ throw new ArgumentNullException("value");
+ }
+ Contract.EndContractBlock();
+
+ // If you add more pre-conditions to this method, check to see if you also need to
+ // add them to CultureInfo.DefaultThreadCurrentCulture.set.
+
+#if FEATURE_LEAK_CULTURE_INFO
+ //If we can't set the nativeThreadLocale, we'll just let it stay
+ //at whatever value it had before. This allows people who use
+ //just managed code not to be limited by the underlying OS.
+ CultureInfo.nativeSetThreadLocale(value.SortName);
+ value.StartCrossDomainTracking();
+#else
+ if (m_CurrentCulture == null && m_CurrentUICulture == null)
+ nativeInitCultureAccessors();
+#endif
+
+ if (!AppContextSwitches.NoAsyncCurrentCulture)
+ {
+ if (s_asyncLocalCurrentCulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentCulture), null);
+ }
+ // this one will set m_CurrentCulture too
+ s_asyncLocalCurrentCulture.Value = value;
+ }
+ else
+ {
+ m_CurrentCulture = value;
+ }
+ }
+ }
+
+#if FEATURE_LEAK_CULTURE_INFO
+ [System.Security.SecuritySafeCritical] // auto-generated
+#endif
+ private CultureInfo GetCurrentCultureNoAppX() {
+
+#if FEATURE_COREFX_GLOBALIZATION
+ return CultureInfo.CurrentCulture;
+#else
+ Contract.Ensures(Contract.Result<CultureInfo>() != null);
+
+ // Fetch a local copy of m_CurrentCulture to
+ // avoid race conditions that malicious user can introduce
+ if (m_CurrentCulture == null) {
+ CultureInfo appDomainDefaultCulture = CultureInfo.DefaultThreadCurrentCulture;
+ return (appDomainDefaultCulture != null ? appDomainDefaultCulture : CultureInfo.UserDefaultCulture);
+ }
+
+#if FEATURE_LEAK_CULTURE_INFO
+ CultureInfo culture = null;
+
+ if (!nativeGetSafeCulture(this, GetDomainID(), false, ref culture) || culture == null) {
+ return CultureInfo.UserDefaultCulture;
+ }
+
+ return culture;
+#else
+ return m_CurrentCulture;
+#endif
+#endif
+ }
+
+#if! FEATURE_LEAK_CULTURE_INFO
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void nativeInitCultureAccessors();
+#endif
+
+ /*=============================================================*/
+
+ /*======================================================================
+ ** Current thread context is stored in a slot in the thread local store
+ ** CurrentContext gets the Context from the slot.
+ ======================================================================*/
+#if FEATURE_REMOTING
+ public static Context CurrentContext
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+ get
+ {
+ return CurrentThread.GetCurrentContextInternal();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Context GetCurrentContextInternal()
+ {
+ if (m_Context == null)
+ {
+ m_Context = Context.DefaultContext;
+ }
+ return m_Context;
+ }
+#endif
+
+
+#if FEATURE_IMPERSONATION
+ // Get and set thread's current principal (for role based security).
+ public static IPrincipal CurrentPrincipal
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ lock (CurrentThread)
+ {
+ IPrincipal principal = (IPrincipal)
+ CallContext.Principal;
+ if (principal == null)
+ {
+ principal = GetDomain().GetThreadPrincipal();
+ CallContext.Principal = principal;
+ }
+ return principal;
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
+ set
+ {
+ CallContext.Principal = value;
+ }
+ }
+
+ // Private routine called from unmanaged code to set an initial
+ // principal for a newly created thread.
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetPrincipalInternal(IPrincipal principal)
+ {
+ GetMutableExecutionContext().LogicalCallContext.SecurityData.Principal = principal;
+ }
+#endif // FEATURE_IMPERSONATION
+
+#if FEATURE_REMOTING
+
+ // This returns the exposed context for a given context ID.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern Context GetContextInternal(IntPtr id);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern Object InternalCrossContextCallback(Context ctx, IntPtr ctxID, Int32 appDomainID, InternalCrossContextDelegate ftnToCall, Object[] args);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object InternalCrossContextCallback(Context ctx, InternalCrossContextDelegate ftnToCall, Object[] args)
+ {
+ return InternalCrossContextCallback(ctx, ctx.InternalContextID, 0, ftnToCall, args);
+ }
+
+ // CompleteCrossContextCallback is called by the EE after transitioning to the requested context
+ private static Object CompleteCrossContextCallback(InternalCrossContextDelegate ftnToCall, Object[] args)
+ {
+ return ftnToCall(args);
+ }
+#endif // FEATURE_REMOTING
+
+ /*======================================================================
+ ** Returns the current domain in which current thread is running.
+ ======================================================================*/
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern AppDomain GetDomainInternal();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern AppDomain GetFastDomainInternal();
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static AppDomain GetDomain()
+ {
+ Contract.Ensures(Contract.Result<AppDomain>() != null);
+
+
+ AppDomain ad;
+ ad = GetFastDomainInternal();
+ if (ad == null)
+ ad = GetDomainInternal();
+
+#if FEATURE_REMOTING
+ Contract.Assert(CurrentThread.m_Context == null || CurrentThread.m_Context.AppDomain == ad, "AppDomains on the managed & unmanaged threads should match");
+#endif
+ return ad;
+ }
+
+
+ /*
+ * This returns a unique id to identify an appdomain.
+ */
+ public static int GetDomainID()
+ {
+ return GetDomain().GetId();
+ }
+
+
+ // Retrieves the name of the thread.
+ //
+ public String Name {
+ get {
+ return m_Name;
+
+ }
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(ExternalThreading=true)]
+ set {
+ lock(this) {
+ if (m_Name != null)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WriteOnce"));
+ m_Name = value;
+
+ InformThreadNameChange(GetNativeHandle(), value, (value != null) ? value.Length : 0);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void InformThreadNameChange(ThreadHandle t, String name, int len);
+
+ internal Object AbortReason {
+ [System.Security.SecurityCritical] // auto-generated
+ get {
+ object result = null;
+ try
+ {
+ result = GetAbortReason();
+ }
+ catch (Exception e)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_ExceptionStateCrossAppDomain"), e);
+ }
+ return result;
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ set { SetAbortReason(value); }
+ }
+
+#if !FEATURE_CORECLR
+ /*
+ * This marks the beginning of a critical code region.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static extern void BeginCriticalRegion();
+
+ /*
+ * This marks the end of a critical code region.
+ */
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static extern void EndCriticalRegion();
+
+ /*
+ * This marks the beginning of a code region that requires thread affinity.
+ */
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static extern void BeginThreadAffinity();
+
+ /*
+ * This marks the end of a code region that requires thread affinity.
+ */
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static extern void EndThreadAffinity();
+#endif // !FEATURE_CORECLR
+
+ /*=========================================================================
+ ** Volatile Read & Write and MemoryBarrier methods.
+ ** Provides the ability to read and write values ensuring that the values
+ ** are read/written each time they are accessed.
+ =========================================================================*/
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static byte VolatileRead(ref byte address)
+ {
+ byte ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static short VolatileRead(ref short address)
+ {
+ short ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static int VolatileRead(ref int address)
+ {
+ int ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static long VolatileRead(ref long address)
+ {
+ long ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static sbyte VolatileRead(ref sbyte address)
+ {
+ sbyte ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static ushort VolatileRead(ref ushort address)
+ {
+ ushort ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static uint VolatileRead(ref uint address)
+ {
+ uint ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static IntPtr VolatileRead(ref IntPtr address)
+ {
+ IntPtr ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static UIntPtr VolatileRead(ref UIntPtr address)
+ {
+ UIntPtr ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static ulong VolatileRead(ref ulong address)
+ {
+ ulong ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static float VolatileRead(ref float address)
+ {
+ float ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static double VolatileRead(ref double address)
+ {
+ double ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static Object VolatileRead(ref Object address)
+ {
+ Object ret = address;
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ return ret;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref byte address, byte value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref short address, short value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref int address, int value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref long address, long value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref sbyte address, sbyte value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref ushort address, ushort value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref uint address, uint value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref IntPtr address, IntPtr value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref UIntPtr address, UIntPtr value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref ulong address, ulong value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref float address, float value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref double address, double value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations
+ public static void VolatileWrite(ref Object address, Object value)
+ {
+ MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
+ address = value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern void MemoryBarrier();
+
+ private static LocalDataStoreMgr LocalDataStoreManager
+ {
+ get
+ {
+ if (s_LocalDataStoreMgr == null)
+ {
+ Interlocked.CompareExchange(ref s_LocalDataStoreMgr, new LocalDataStoreMgr(), null);
+ }
+
+ return s_LocalDataStoreMgr;
+ }
+ }
+
+#if !FEATURE_CORECLR
+ void _Thread.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Thread.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Thread.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Thread.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ // Helper function to set the AbortReason for a thread abort.
+ // Checks that they're not alredy set, and then atomically updates
+ // the reason info (object + ADID).
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void SetAbortReason(Object o);
+
+ // Helper function to retrieve the AbortReason from a thread
+ // abort. Will perform cross-AppDomain marshalling if the object
+ // lives in a different AppDomain from the requester.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern Object GetAbortReason();
+
+ // Helper function to clear the AbortReason. Takes care of
+ // AppDomain related cleanup if required.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void ClearAbortReason();
+
+
+ } // End of class Thread
+
+ // declaring a local var of this enum type and passing it by ref into a function that needs to do a
+ // stack crawl will both prevent inlining of the calle and pass an ESP point to stack crawl to
+ // Declaring these in EH clauses is illegal; they must declared in the main method body
+ [Serializable]
+ internal enum StackCrawlMark
+ {
+ LookForMe = 0,
+ LookForMyCaller = 1,
+ LookForMyCallersCaller = 2,
+ LookForThread = 3
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadAbortException.cs b/src/mscorlib/src/System/Threading/ThreadAbortException.cs
new file mode 100644
index 0000000000..11c8744c72
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadAbortException.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: An exception class which is thrown into a thread to cause it to
+** abort. This is a special non-catchable exception and results in
+** the thread's death. This is thrown by the VM only and can NOT be
+** thrown by any user thread, and subclassing this is useless.
+**
+**
+=============================================================================*/
+
+namespace System.Threading
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public sealed class ThreadAbortException : SystemException
+ {
+ private ThreadAbortException()
+ : base(GetMessageFromNativeResources(ExceptionMessageKind.ThreadAbort))
+ {
+ SetErrorCode(__HResults.COR_E_THREADABORTED);
+ }
+
+ //required for serialization
+ internal ThreadAbortException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+ public Object ExceptionState
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {return Thread.CurrentThread.AbortReason;}
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadInterruptedException.cs b/src/mscorlib/src/System/Threading/ThreadInterruptedException.cs
new file mode 100644
index 0000000000..0056611955
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadInterruptedException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: An exception class to indicate that the thread was interrupted
+** from a waiting state.
+**
+**
+=============================================================================*/
+namespace System.Threading {
+ using System.Threading;
+ using System;
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ThreadInterruptedException : SystemException {
+ public ThreadInterruptedException()
+ : base(GetMessageFromNativeResources(ExceptionMessageKind.ThreadInterrupted)) {
+ SetErrorCode(__HResults.COR_E_THREADINTERRUPTED);
+ }
+
+ public ThreadInterruptedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_THREADINTERRUPTED);
+ }
+
+ public ThreadInterruptedException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_THREADINTERRUPTED);
+ }
+
+ protected ThreadInterruptedException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadLocal.cs b/src/mscorlib/src/System/Threading/ThreadLocal.cs
new file mode 100644
index 0000000000..b4cf12ab7c
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadLocal.cs
@@ -0,0 +1,815 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+#pragma warning disable 0420
+
+// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
+//
+//
+//
+// A class that provides a simple, lightweight implementation of thread-local lazy-initialization, where a value is initialized once per accessing
+// thread; this provides an alternative to using a ThreadStatic static variable and having
+// to check the variable prior to every access to see if it's been initialized.
+//
+//
+//
+// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Diagnostics.Contracts;
+
+namespace System.Threading
+{
+ /// <summary>
+ /// Provides thread-local storage of data.
+ /// </summary>
+ /// <typeparam name="T">Specifies the type of data stored per-thread.</typeparam>
+ /// <remarks>
+ /// <para>
+ /// With the exception of <see cref="Dispose()"/>, all public and protected members of
+ /// <see cref="ThreadLocal{T}"/> are thread-safe and may be used
+ /// concurrently from multiple threads.
+ /// </para>
+ /// </remarks>
+ [DebuggerTypeProxy(typeof(SystemThreading_ThreadLocalDebugView<>))]
+ [DebuggerDisplay("IsValueCreated={IsValueCreated}, Value={ValueForDebugDisplay}, Count={ValuesCountForDebugDisplay}")]
+ [HostProtection(Synchronization = true, ExternalThreading = true)]
+ public class ThreadLocal<T> : IDisposable
+ {
+
+ // a delegate that returns the created value, if null the created value will be default(T)
+ private Func<T> m_valueFactory;
+
+ //
+ // ts_slotArray is a table of thread-local values for all ThreadLocal<T> instances
+ //
+ // So, when a thread reads ts_slotArray, it gets back an array of *all* ThreadLocal<T> values for this thread and this T.
+ // The slot relevant to this particular ThreadLocal<T> instance is determined by the m_idComplement instance field stored in
+ // the ThreadLocal<T> instance.
+ //
+ [ThreadStatic]
+ static LinkedSlotVolatile[] ts_slotArray;
+
+ [ThreadStatic]
+ static FinalizationHelper ts_finalizationHelper;
+
+ // Slot ID of this ThreadLocal<> instance. We store a bitwise complement of the ID (that is ~ID), which allows us to distinguish
+ // between the case when ID is 0 and an incompletely initialized object, either due to a thread abort in the constructor, or
+ // possibly due to a memory model issue in user code.
+ private int m_idComplement;
+
+ // This field is set to true when the constructor completes. That is helpful for recognizing whether a constructor
+ // threw an exception - either due to invalid argument or due to a thread abort. Finally, the field is set to false
+ // when the instance is disposed.
+ private volatile bool m_initialized;
+
+ // IdManager assigns and reuses slot IDs. Additionally, the object is also used as a global lock.
+ private static IdManager s_idManager = new IdManager();
+
+ // A linked list of all values associated with this ThreadLocal<T> instance.
+ // We create a dummy head node. That allows us to remove any (non-dummy) node without having to locate the m_linkedSlot field.
+ private LinkedSlot m_linkedSlot = new LinkedSlot(null);
+
+ // Whether the Values property is supported
+ private bool m_trackAllValues;
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance.
+ /// </summary>
+ public ThreadLocal()
+ {
+ Initialize(null, false);
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance.
+ /// </summary>
+ /// <param name="trackAllValues">Whether to track all values set on the instance and expose them through the Values property.</param>
+ public ThreadLocal(bool trackAllValues)
+ {
+ Initialize(null, trackAllValues);
+ }
+
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance with the
+ /// specified <paramref name="valueFactory"/> function.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
+ /// </param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="valueFactory"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ public ThreadLocal(Func<T> valueFactory)
+ {
+ if (valueFactory == null)
+ throw new ArgumentNullException("valueFactory");
+
+ Initialize(valueFactory, false);
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="System.Threading.ThreadLocal{T}"/> instance with the
+ /// specified <paramref name="valueFactory"/> function.
+ /// </summary>
+ /// <param name="valueFactory">
+ /// The <see cref="T:System.Func{T}"/> invoked to produce a lazily-initialized value when
+ /// an attempt is made to retrieve <see cref="Value"/> without it having been previously initialized.
+ /// </param>
+ /// <param name="trackAllValues">Whether to track all values set on the instance and expose them via the Values property.</param>
+ /// <exception cref="T:System.ArgumentNullException">
+ /// <paramref name="valueFactory"/> is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ public ThreadLocal(Func<T> valueFactory, bool trackAllValues)
+ {
+ if (valueFactory == null)
+ throw new ArgumentNullException("valueFactory");
+
+ Initialize(valueFactory, trackAllValues);
+ }
+
+ private void Initialize(Func<T> valueFactory, bool trackAllValues)
+ {
+ m_valueFactory = valueFactory;
+ m_trackAllValues = trackAllValues;
+
+ // Assign the ID and mark the instance as initialized. To avoid leaking IDs, we assign the ID and set m_initialized
+ // in a finally block, to avoid a thread abort in between the two statements.
+ try { }
+ finally
+ {
+ m_idComplement = ~s_idManager.GetId();
+
+ // As the last step, mark the instance as fully initialized. (Otherwise, if m_initialized=false, we know that an exception
+ // occurred in the constructor.)
+ m_initialized = true;
+ }
+ }
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ ~ThreadLocal()
+ {
+ // finalizer to return the type combination index to the pool
+ Dispose(false);
+ }
+
+ #region IDisposable Members
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="T:System.Threading.ThreadLocal{T}"/>, this method is not thread-safe.
+ /// </remarks>
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ /// <summary>
+ /// Releases the resources used by this <see cref="T:System.Threading.ThreadLocal{T}" /> instance.
+ /// </summary>
+ /// <param name="disposing">
+ /// A Boolean value that indicates whether this method is being called due to a call to <see cref="Dispose()"/>.
+ /// </param>
+ /// <remarks>
+ /// Unlike most of the members of <see cref="T:System.Threading.ThreadLocal{T}"/>, this method is not thread-safe.
+ /// </remarks>
+ protected virtual void Dispose(bool disposing)
+ {
+ int id;
+
+ lock (s_idManager)
+ {
+ id = ~m_idComplement;
+ m_idComplement = 0;
+
+ if (id < 0 || !m_initialized)
+ {
+ Contract.Assert(id >= 0 || !m_initialized, "expected id >= 0 if initialized");
+
+ // Handle double Dispose calls or disposal of an instance whose constructor threw an exception.
+ return;
+ }
+ m_initialized = false;
+
+ for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ {
+ LinkedSlotVolatile[] slotArray = linkedSlot.SlotArray;
+
+ if (slotArray == null)
+ {
+ // The thread that owns this slotArray has already finished.
+ continue;
+ }
+
+ // Remove the reference from the LinkedSlot to the slot table.
+ linkedSlot.SlotArray = null;
+
+ // And clear the references from the slot table to the linked slot and the value so that
+ // both can get garbage collected.
+ slotArray[id].Value.Value = default(T);
+ slotArray[id].Value = null;
+ }
+ }
+ m_linkedSlot = null;
+ s_idManager.ReturnId(id);
+ }
+
+ #endregion
+
+ /// <summary>Creates and returns a string representation of this instance for the current thread.</summary>
+ /// <returns>The result of calling <see cref="System.Object.ToString"/> on the <see cref="Value"/>.</returns>
+ /// <exception cref="T:System.NullReferenceException">
+ /// The <see cref="Value"/> for the current thread is a null reference (Nothing in Visual Basic).
+ /// </exception>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The initialization function referenced <see cref="Value"/> in an improper manner.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ /// <remarks>
+ /// Calling this method forces initialization for the current thread, as is the
+ /// case with accessing <see cref="Value"/> directly.
+ /// </remarks>
+ public override string ToString()
+ {
+ return Value.ToString();
+ }
+
+ /// <summary>
+ /// Gets or sets the value of this instance for the current thread.
+ /// </summary>
+ /// <exception cref="T:System.InvalidOperationException">
+ /// The initialization function referenced <see cref="Value"/> in an improper manner.
+ /// </exception>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ /// <remarks>
+ /// If this instance was not previously initialized for the current thread,
+ /// accessing <see cref="Value"/> will attempt to initialize it. If an initialization function was
+ /// supplied during the construction, that initialization will happen by invoking the function
+ /// to retrieve the initial value for <see cref="Value"/>. Otherwise, the default value of
+ /// <typeparamref name="T"/> will be used.
+ /// </remarks>
+ [DebuggerBrowsable(DebuggerBrowsableState.Never)]
+ public T Value
+ {
+ get
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ LinkedSlot slot;
+ int id = ~m_idComplement;
+
+ //
+ // Attempt to get the value using the fast path
+ //
+ if (slotArray != null // Has the slot array been initialized?
+ && id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
+ && id < slotArray.Length // Is the table large enough?
+ && (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
+ && m_initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
+ )
+ {
+ // We verified that the instance has not been disposed *after* we got a reference to the slot.
+ // This guarantees that we have a reference to the right slot.
+ //
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // will not be reordered before the read of slotArray[id].
+ return slot.Value;
+ }
+
+ return GetValueSlow();
+ }
+ set
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ LinkedSlot slot;
+ int id = ~m_idComplement;
+
+ //
+ // Attempt to set the value using the fast path
+ //
+ if (slotArray != null // Has the slot array been initialized?
+ && id >= 0 // Is the ID non-negative (i.e., instance is not disposed)?
+ && id < slotArray.Length // Is the table large enough?
+ && (slot = slotArray[id].Value) != null // Has a LinkedSlot object has been allocated for this ID?
+ && m_initialized // Has the instance *still* not been disposed (important for a race condition with Dispose)?
+ )
+ {
+ // We verified that the instance has not been disposed *after* we got a reference to the slot.
+ // This guarantees that we have a reference to the right slot.
+ //
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // will not be reordered before the read of slotArray[id].
+ slot.Value = value;
+ }
+ else
+ {
+ SetValueSlow(value, slotArray);
+ }
+ }
+ }
+
+ private T GetValueSlow()
+ {
+ // If the object has been disposed, the id will be -1.
+ int id = ~m_idComplement;
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ }
+
+ Debugger.NotifyOfCrossThreadDependency();
+
+ // Determine the initial value
+ T value;
+ if (m_valueFactory == null)
+ {
+ value = default(T);
+ }
+ else
+ {
+ value = m_valueFactory();
+
+ if (IsValueCreated)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ThreadLocal_Value_RecursiveCallsToValue"));
+ }
+ }
+
+ // Since the value has been previously uninitialized, we also need to set it (according to the ThreadLocal semantics).
+ Value = value;
+ return value;
+ }
+
+ private void SetValueSlow(T value, LinkedSlotVolatile[] slotArray)
+ {
+ int id = ~m_idComplement;
+
+ // If the object has been disposed, id will be -1.
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ }
+
+ // If a slot array has not been created on this thread yet, create it.
+ if (slotArray == null)
+ {
+ slotArray = new LinkedSlotVolatile[GetNewTableSize(id + 1)];
+ ts_finalizationHelper = new FinalizationHelper(slotArray, m_trackAllValues);
+ ts_slotArray = slotArray;
+ }
+
+ // If the slot array is not big enough to hold this ID, increase the table size.
+ if (id >= slotArray.Length)
+ {
+ GrowTable(ref slotArray, id + 1);
+ ts_finalizationHelper.SlotArray = slotArray;
+ ts_slotArray = slotArray;
+ }
+
+ // If we are using the slot in this table for the first time, create a new LinkedSlot and add it into
+ // the linked list for this ThreadLocal instance.
+ if (slotArray[id].Value == null)
+ {
+ CreateLinkedSlot(slotArray, id, value);
+ }
+ else
+ {
+ // Volatile read of the LinkedSlotVolatile.Value property ensures that the m_initialized read
+ // that follows will not be reordered before the read of slotArray[id].
+ LinkedSlot slot = slotArray[id].Value;
+
+ // It is important to verify that the ThreadLocal instance has not been disposed. The check must come
+ // after capturing slotArray[id], but before assigning the value into the slot. This ensures that
+ // if this ThreadLocal instance was disposed on another thread and another ThreadLocal instance was
+ // created, we definitely won't assign the value into the wrong instance.
+
+ if (!m_initialized)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ }
+
+ slot.Value = value;
+ }
+ }
+
+ /// <summary>
+ /// Creates a LinkedSlot and inserts it into the linked list for this ThreadLocal instance.
+ /// </summary>
+ private void CreateLinkedSlot(LinkedSlotVolatile[] slotArray, int id, T value)
+ {
+ // Create a LinkedSlot
+ var linkedSlot = new LinkedSlot(slotArray);
+
+ // Insert the LinkedSlot into the linked list maintained by this ThreadLocal<> instance and into the slot array
+ lock (s_idManager)
+ {
+ // Check that the instance has not been disposed. It is important to check this under a lock, since
+ // Dispose also executes under a lock.
+ if (!m_initialized)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ }
+
+ LinkedSlot firstRealNode = m_linkedSlot.Next;
+
+ //
+ // Insert linkedSlot between nodes m_linkedSlot and firstRealNode.
+ // (m_linkedSlot is the dummy head node that should always be in the front.)
+ //
+ linkedSlot.Next = firstRealNode;
+ linkedSlot.Previous = m_linkedSlot;
+ linkedSlot.Value = value;
+
+ if (firstRealNode != null)
+ {
+ firstRealNode.Previous = linkedSlot;
+ }
+ m_linkedSlot.Next = linkedSlot;
+
+ // Assigning the slot under a lock prevents a race condition with Dispose (dispose also acquires the lock).
+ // Otherwise, it would be possible that the ThreadLocal instance is disposed, another one gets created
+ // with the same ID, and the write would go to the wrong instance.
+ slotArray[id].Value = linkedSlot;
+ }
+ }
+
+ /// <summary>
+ /// Gets a list for all of the values currently stored by all of the threads that have accessed this instance.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ public IList<T> Values
+ {
+ get
+ {
+ if (!m_trackAllValues)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("ThreadLocal_ValuesNotAvailable"));
+ }
+
+ var list = GetValuesAsList(); // returns null if disposed
+ if (list == null) throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ return list;
+ }
+ }
+
+ /// <summary>Gets all of the threads' values in a list.</summary>
+ private List<T> GetValuesAsList()
+ {
+ List<T> valueList = new List<T>();
+ int id = ~m_idComplement;
+ if (id == -1)
+ {
+ return null;
+ }
+
+ // Walk over the linked list of slots and gather the values associated with this ThreadLocal instance.
+ for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ {
+ // We can safely read linkedSlot.Value. Even if this ThreadLocal has been disposed in the meantime, the LinkedSlot
+ // objects will never be assigned to another ThreadLocal instance.
+ valueList.Add(linkedSlot.Value);
+ }
+
+ return valueList;
+ }
+
+ /// <summary>Gets the number of threads that have data in this instance.</summary>
+ private int ValuesCountForDebugDisplay
+ {
+ get
+ {
+ int count = 0;
+ for (LinkedSlot linkedSlot = m_linkedSlot.Next; linkedSlot != null; linkedSlot = linkedSlot.Next)
+ {
+ count++;
+ }
+ return count;
+ }
+ }
+
+ /// <summary>
+ /// Gets whether <see cref="Value"/> is initialized on the current thread.
+ /// </summary>
+ /// <exception cref="T:System.ObjectDisposedException">
+ /// The <see cref="ThreadLocal{T}"/> instance has been disposed.
+ /// </exception>
+ public bool IsValueCreated
+ {
+ get
+ {
+ int id = ~m_idComplement;
+ if (id < 0)
+ {
+ throw new ObjectDisposedException(Environment.GetResourceString("ThreadLocal_Disposed"));
+ }
+
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ return slotArray != null && id < slotArray.Length && slotArray[id].Value != null;
+ }
+ }
+
+
+ /// <summary>Gets the value of the ThreadLocal&lt;T&gt; for debugging display purposes. It takes care of getting
+ /// the value for the current thread in the ThreadLocal mode.</summary>
+ internal T ValueForDebugDisplay
+ {
+ get
+ {
+ LinkedSlotVolatile[] slotArray = ts_slotArray;
+ int id = ~m_idComplement;
+
+ LinkedSlot slot;
+ if (slotArray == null || id >= slotArray.Length || (slot = slotArray[id].Value) == null || !m_initialized)
+ return default(T);
+ return slot.Value;
+ }
+ }
+
+ /// <summary>Gets the values of all threads that accessed the ThreadLocal&lt;T&gt;.</summary>
+ internal List<T> ValuesForDebugDisplay // same as Values property, but doesn't throw if disposed
+ {
+ get { return GetValuesAsList(); }
+ }
+
+ /// <summary>
+ /// Resizes a table to a certain length (or larger).
+ /// </summary>
+ private void GrowTable(ref LinkedSlotVolatile[] table, int minLength)
+ {
+ Contract.Assert(table.Length < minLength);
+
+ // Determine the size of the new table and allocate it.
+ int newLen = GetNewTableSize(minLength);
+ LinkedSlotVolatile[] newTable = new LinkedSlotVolatile[newLen];
+
+ //
+ // The lock is necessary to avoid a race with ThreadLocal.Dispose. GrowTable has to point all
+ // LinkedSlot instances referenced in the old table to reference the new table. Without locking,
+ // Dispose could use a stale SlotArray reference and clear out a slot in the old array only, while
+ // the value continues to be referenced from the new (larger) array.
+ //
+ lock (s_idManager)
+ {
+ for (int i = 0; i < table.Length; i++)
+ {
+ LinkedSlot linkedSlot = table[i].Value;
+ if (linkedSlot != null && linkedSlot.SlotArray != null)
+ {
+ linkedSlot.SlotArray = newTable;
+ newTable[i] = table[i];
+ }
+ }
+ }
+
+ table = newTable;
+ }
+
+ /// <summary>
+ /// Chooses the next larger table size
+ /// </summary>
+ private static int GetNewTableSize(int minSize)
+ {
+ if ((uint)minSize > Array.MaxArrayLength)
+ {
+ // Intentionally return a value that will result in an OutOfMemoryException
+ return int.MaxValue;
+ }
+ Contract.Assert(minSize > 0);
+
+ //
+ // Round up the size to the next power of 2
+ //
+ // The algorithm takes three steps:
+ // input -> subtract one -> propagate 1-bits to the right -> add one
+ //
+ // Let's take a look at the 3 steps in both interesting cases: where the input
+ // is (Example 1) and isn't (Example 2) a power of 2.
+ //
+ // Example 1: 100000 -> 011111 -> 011111 -> 100000
+ // Example 2: 011010 -> 011001 -> 011111 -> 100000
+ //
+ int newSize = minSize;
+
+ // Step 1: Decrement
+ newSize--;
+
+ // Step 2: Propagate 1-bits to the right.
+ newSize |= newSize >> 1;
+ newSize |= newSize >> 2;
+ newSize |= newSize >> 4;
+ newSize |= newSize >> 8;
+ newSize |= newSize >> 16;
+
+ // Step 3: Increment
+ newSize++;
+
+ // Don't set newSize to more than Array.MaxArrayLength
+ if ((uint)newSize > Array.MaxArrayLength)
+ {
+ newSize = Array.MaxArrayLength;
+ }
+
+ return newSize;
+ }
+
+ /// <summary>
+ /// A wrapper struct used as LinkedSlotVolatile[] - an array of LinkedSlot instances, but with volatile semantics
+ /// on array accesses.
+ /// </summary>
+ private struct LinkedSlotVolatile
+ {
+ internal volatile LinkedSlot Value;
+ }
+
+ /// <summary>
+ /// A node in the doubly-linked list stored in the ThreadLocal instance.
+ ///
+ /// The value is stored in one of two places:
+ ///
+ /// 1. If SlotArray is not null, the value is in SlotArray.Table[id]
+ /// 2. If SlotArray is null, the value is in FinalValue.
+ /// </summary>
+ private sealed class LinkedSlot
+ {
+ internal LinkedSlot(LinkedSlotVolatile[] slotArray)
+ {
+ SlotArray = slotArray;
+ }
+
+ // The next LinkedSlot for this ThreadLocal<> instance
+ internal volatile LinkedSlot Next;
+
+ // The previous LinkedSlot for this ThreadLocal<> instance
+ internal volatile LinkedSlot Previous;
+
+ // The SlotArray that stores this LinkedSlot at SlotArray.Table[id].
+ internal volatile LinkedSlotVolatile[] SlotArray;
+
+ // The value for this slot.
+ internal T Value;
+ }
+
+ /// <summary>
+ /// A manager class that assigns IDs to ThreadLocal instances
+ /// </summary>
+ private class IdManager
+ {
+ // The next ID to try
+ private int m_nextIdToTry = 0;
+
+ // Stores whether each ID is free or not. Additionally, the object is also used as a lock for the IdManager.
+ private List<bool> m_freeIds = new List<bool>();
+
+ internal int GetId()
+ {
+ lock (m_freeIds)
+ {
+ int availableId = m_nextIdToTry;
+ while (availableId < m_freeIds.Count)
+ {
+ if (m_freeIds[availableId]) { break; }
+ availableId++;
+ }
+
+ if (availableId == m_freeIds.Count)
+ {
+ m_freeIds.Add(false);
+ }
+ else
+ {
+ m_freeIds[availableId] = false;
+ }
+
+ m_nextIdToTry = availableId + 1;
+
+ return availableId;
+ }
+ }
+
+ // Return an ID to the pool
+ internal void ReturnId(int id)
+ {
+ lock (m_freeIds)
+ {
+ m_freeIds[id] = true;
+ if (id < m_nextIdToTry) m_nextIdToTry = id;
+ }
+ }
+ }
+
+ /// <summary>
+ /// A class that facilitates ThreadLocal cleanup after a thread exits.
+ ///
+ /// After a thread with an associated thread-local table has exited, the FinalizationHelper
+ /// is reponsible for removing back-references to the table. Since an instance of FinalizationHelper
+ /// is only referenced from a single thread-local slot, the FinalizationHelper will be GC'd once
+ /// the thread has exited.
+ ///
+ /// The FinalizationHelper then locates all LinkedSlot instances with back-references to the table
+ /// (all those LinkedSlot instances can be found by following references from the table slots) and
+ /// releases the table so that it can get GC'd.
+ /// </summary>
+ private class FinalizationHelper
+ {
+ internal LinkedSlotVolatile[] SlotArray;
+ private bool m_trackAllValues;
+
+ internal FinalizationHelper(LinkedSlotVolatile[] slotArray, bool trackAllValues)
+ {
+ SlotArray = slotArray;
+ m_trackAllValues = trackAllValues;
+ }
+
+ ~FinalizationHelper()
+ {
+ LinkedSlotVolatile[] slotArray = SlotArray;
+ Contract.Assert(slotArray != null);
+
+ for (int i = 0; i < slotArray.Length; i++)
+ {
+ LinkedSlot linkedSlot = slotArray[i].Value;
+ if (linkedSlot == null)
+ {
+ // This slot in the table is empty
+ continue;
+ }
+
+ if (m_trackAllValues)
+ {
+ // Set the SlotArray field to null to release the slot array.
+ linkedSlot.SlotArray = null;
+ }
+ else
+ {
+ // Remove the LinkedSlot from the linked list. Once the FinalizationHelper is done, all back-references to
+ // the table will be have been removed, and so the table can get GC'd.
+ lock (s_idManager)
+ {
+ if (linkedSlot.Next != null)
+ {
+ linkedSlot.Next.Previous = linkedSlot.Previous;
+ }
+
+ // Since the list uses a dummy head node, the Previous reference should never be null.
+ Contract.Assert(linkedSlot.Previous != null);
+ linkedSlot.Previous.Next = linkedSlot.Next;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>A debugger view of the ThreadLocal&lt;T&gt; to surface additional debugging properties and
+ /// to ensure that the ThreadLocal&lt;T&gt; does not become initialized if it was not already.</summary>
+ internal sealed class SystemThreading_ThreadLocalDebugView<T>
+ {
+ //The ThreadLocal object being viewed.
+ private readonly ThreadLocal<T> m_tlocal;
+
+ /// <summary>Constructs a new debugger view object for the provided ThreadLocal object.</summary>
+ /// <param name="tlocal">A ThreadLocal object to browse in the debugger.</param>
+ public SystemThreading_ThreadLocalDebugView(ThreadLocal<T> tlocal)
+ {
+ m_tlocal = tlocal;
+ }
+
+ /// <summary>Returns whether the ThreadLocal object is initialized or not.</summary>
+ public bool IsValueCreated
+ {
+ get { return m_tlocal.IsValueCreated; }
+ }
+
+ /// <summary>Returns the value of the ThreadLocal object.</summary>
+ public T Value
+ {
+ get
+ {
+ return m_tlocal.ValueForDebugDisplay;
+ }
+ }
+
+ /// <summary>Return all values for all threads that have accessed this instance.</summary>
+ public List<T> Values
+ {
+ get
+ {
+ return m_tlocal.ValuesForDebugDisplay;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadPool.cs b/src/mscorlib/src/System/Threading/ThreadPool.cs
new file mode 100644
index 0000000000..09fe93c682
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadPool.cs
@@ -0,0 +1,1954 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Class for creating and managing a threadpool
+**
+**
+=============================================================================*/
+
+#pragma warning disable 0420
+
+/*
+ * Below you'll notice two sets of APIs that are separated by the
+ * use of 'Unsafe' in their names. The unsafe versions are called
+ * that because they do not propagate the calling stack onto the
+ * worker thread. This allows code to lose the calling stack and
+ * thereby elevate its security privileges. Note that this operation
+ * is much akin to the combined ability to control security policy
+ * and control security evidence. With these privileges, a person
+ * can gain the right to load assemblies that are fully trusted which
+ * then assert full trust and can call any code they want regardless
+ * of the previous stack information.
+ */
+
+namespace System.Threading
+{
+ using System.Security;
+ using System.Runtime.Remoting;
+ using System.Security.Permissions;
+ using System;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Versioning;
+ using System.Collections.Generic;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Diagnostics.Tracing;
+
+ internal static class ThreadPoolGlobals
+ {
+ //Per-appDomain quantum (in ms) for which the thread keeps processing
+ //requests in the current domain.
+ public static uint tpQuantum = 30U;
+
+ public static int processorCount = Environment.ProcessorCount;
+
+ public static bool tpHosted = ThreadPool.IsThreadPoolHosted();
+
+ public static volatile bool vmTpInitialized;
+ public static bool enableWorkerTracking;
+
+ [SecurityCritical]
+ public static ThreadPoolWorkQueue workQueue = new ThreadPoolWorkQueue();
+
+ [System.Security.SecuritySafeCritical] // static constructors should be safe to call
+ static ThreadPoolGlobals()
+ {
+ }
+ }
+
+ internal sealed class ThreadPoolWorkQueue
+ {
+ // Simple sparsely populated array to allow lock-free reading.
+ internal class SparseArray<T> where T : class
+ {
+ private volatile T[] m_array;
+
+ internal SparseArray(int initialSize)
+ {
+ m_array = new T[initialSize];
+ }
+
+ internal T[] Current
+ {
+ get { return m_array; }
+ }
+
+ internal int Add(T e)
+ {
+ while (true)
+ {
+ T[] array = m_array;
+ lock (array)
+ {
+ for (int i = 0; i < array.Length; i++)
+ {
+ if (array[i] == null)
+ {
+ Volatile.Write(ref array[i], e);
+ return i;
+ }
+ else if (i == array.Length - 1)
+ {
+ // Must resize. If there was a race condition, we start over again.
+ if (array != m_array)
+ continue;
+
+ T[] newArray = new T[array.Length * 2];
+ Array.Copy(array, newArray, i + 1);
+ newArray[i + 1] = e;
+ m_array = newArray;
+ return i + 1;
+ }
+ }
+ }
+ }
+ }
+
+ internal void Remove(T e)
+ {
+ T[] array = m_array;
+ lock (array)
+ {
+ for (int i = 0; i < m_array.Length; i++)
+ {
+ if (m_array[i] == e)
+ {
+ Volatile.Write(ref m_array[i], null);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ internal class WorkStealingQueue
+ {
+ private const int INITIAL_SIZE = 32;
+ internal volatile IThreadPoolWorkItem[] m_array = new IThreadPoolWorkItem[INITIAL_SIZE];
+ private volatile int m_mask = INITIAL_SIZE - 1;
+
+#if DEBUG
+ // in debug builds, start at the end so we exercise the index reset logic.
+ private const int START_INDEX = int.MaxValue;
+#else
+ private const int START_INDEX = 0;
+#endif
+
+ private volatile int m_headIndex = START_INDEX;
+ private volatile int m_tailIndex = START_INDEX;
+
+ private SpinLock m_foreignLock = new SpinLock(false);
+
+ public void LocalPush(IThreadPoolWorkItem obj)
+ {
+ int tail = m_tailIndex;
+
+ // We're going to increment the tail; if we'll overflow, then we need to reset our counts
+ if (tail == int.MaxValue)
+ {
+ bool lockTaken = false;
+ try
+ {
+ m_foreignLock.Enter(ref lockTaken);
+
+ if (m_tailIndex == int.MaxValue)
+ {
+ //
+ // Rather than resetting to zero, we'll just mask off the bits we don't care about.
+ // This way we don't need to rearrange the items already in the queue; they'll be found
+ // correctly exactly where they are. One subtlety here is that we need to make sure that
+ // if head is currently < tail, it remains that way. This happens to just fall out from
+ // the bit-masking, because we only do this if tail == int.MaxValue, meaning that all
+ // bits are set, so all of the bits we're keeping will also be set. Thus it's impossible
+ // for the head to end up > than the tail, since you can't set any more bits than all of
+ // them.
+ //
+ m_headIndex = m_headIndex & m_mask;
+ m_tailIndex = tail = m_tailIndex & m_mask;
+ Contract.Assert(m_headIndex <= m_tailIndex);
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ m_foreignLock.Exit(true);
+ }
+ }
+
+ // When there are at least 2 elements' worth of space, we can take the fast path.
+ if (tail < m_headIndex + m_mask)
+ {
+ Volatile.Write(ref m_array[tail & m_mask], obj);
+ m_tailIndex = tail + 1;
+ }
+ else
+ {
+ // We need to contend with foreign pops, so we lock.
+ bool lockTaken = false;
+ try
+ {
+ m_foreignLock.Enter(ref lockTaken);
+
+ int head = m_headIndex;
+ int count = m_tailIndex - m_headIndex;
+
+ // If there is still space (one left), just add the element.
+ if (count >= m_mask)
+ {
+ // We're full; expand the queue by doubling its size.
+ IThreadPoolWorkItem[] newArray = new IThreadPoolWorkItem[m_array.Length << 1];
+ for (int i = 0; i < m_array.Length; i++)
+ newArray[i] = m_array[(i + head) & m_mask];
+
+ // Reset the field values, incl. the mask.
+ m_array = newArray;
+ m_headIndex = 0;
+ m_tailIndex = tail = count;
+ m_mask = (m_mask << 1) | 1;
+ }
+
+ Volatile.Write(ref m_array[tail & m_mask], obj);
+ m_tailIndex = tail + 1;
+ }
+ finally
+ {
+ if (lockTaken)
+ m_foreignLock.Exit(false);
+ }
+ }
+ }
+
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public bool LocalFindAndPop(IThreadPoolWorkItem obj)
+ {
+ // Fast path: check the tail. If equal, we can skip the lock.
+ if (m_array[(m_tailIndex - 1) & m_mask] == obj)
+ {
+ IThreadPoolWorkItem unused;
+ if (LocalPop(out unused))
+ {
+ Contract.Assert(unused == obj);
+ return true;
+ }
+ return false;
+ }
+
+ // Else, do an O(N) search for the work item. The theory of work stealing and our
+ // inlining logic is that most waits will happen on recently queued work. And
+ // since recently queued work will be close to the tail end (which is where we
+ // begin our search), we will likely find it quickly. In the worst case, we
+ // will traverse the whole local queue; this is typically not going to be a
+ // problem (although degenerate cases are clearly an issue) because local work
+ // queues tend to be somewhat shallow in length, and because if we fail to find
+ // the work item, we are about to block anyway (which is very expensive).
+ for (int i = m_tailIndex - 2; i >= m_headIndex; i--)
+ {
+ if (m_array[i & m_mask] == obj)
+ {
+ // If we found the element, block out steals to avoid interference.
+ bool lockTaken = false;
+ try
+ {
+ m_foreignLock.Enter(ref lockTaken);
+
+ // If we encountered a race condition, bail.
+ if (m_array[i & m_mask] == null)
+ return false;
+
+ // Otherwise, null out the element.
+ Volatile.Write(ref m_array[i & m_mask], null);
+
+ // And then check to see if we can fix up the indexes (if we're at
+ // the edge). If we can't, we just leave nulls in the array and they'll
+ // get filtered out eventually (but may lead to superflous resizing).
+ if (i == m_tailIndex)
+ m_tailIndex -= 1;
+ else if (i == m_headIndex)
+ m_headIndex += 1;
+
+ return true;
+ }
+ finally
+ {
+ if (lockTaken)
+ m_foreignLock.Exit(false);
+ }
+ }
+ }
+
+ return false;
+ }
+
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public bool LocalPop(out IThreadPoolWorkItem obj)
+ {
+ while (true)
+ {
+ // Decrement the tail using a fence to ensure subsequent read doesn't come before.
+ int tail = m_tailIndex;
+ if (m_headIndex >= tail)
+ {
+ obj = null;
+ return false;
+ }
+
+ tail -= 1;
+ Interlocked.Exchange(ref m_tailIndex, tail);
+
+ // If there is no interaction with a take, we can head down the fast path.
+ if (m_headIndex <= tail)
+ {
+ int idx = tail & m_mask;
+ obj = Volatile.Read(ref m_array[idx]);
+
+ // Check for nulls in the array.
+ if (obj == null) continue;
+
+ m_array[idx] = null;
+ return true;
+ }
+ else
+ {
+ // Interaction with takes: 0 or 1 elements left.
+ bool lockTaken = false;
+ try
+ {
+ m_foreignLock.Enter(ref lockTaken);
+
+ if (m_headIndex <= tail)
+ {
+ // Element still available. Take it.
+ int idx = tail & m_mask;
+ obj = Volatile.Read(ref m_array[idx]);
+
+ // Check for nulls in the array.
+ if (obj == null) continue;
+
+ m_array[idx] = null;
+ return true;
+ }
+ else
+ {
+ // If we encountered a race condition and element was stolen, restore the tail.
+ m_tailIndex = tail + 1;
+ obj = null;
+ return false;
+ }
+ }
+ finally
+ {
+ if (lockTaken)
+ m_foreignLock.Exit(false);
+ }
+ }
+ }
+ }
+
+ public bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal)
+ {
+ return TrySteal(out obj, ref missedSteal, 0); // no blocking by default.
+ }
+
+ private bool TrySteal(out IThreadPoolWorkItem obj, ref bool missedSteal, int millisecondsTimeout)
+ {
+ obj = null;
+
+ while (true)
+ {
+ if (m_headIndex >= m_tailIndex)
+ return false;
+
+ bool taken = false;
+ try
+ {
+ m_foreignLock.TryEnter(millisecondsTimeout, ref taken);
+ if (taken)
+ {
+ // Increment head, and ensure read of tail doesn't move before it (fence).
+ int head = m_headIndex;
+ Interlocked.Exchange(ref m_headIndex, head + 1);
+
+ if (head < m_tailIndex)
+ {
+ int idx = head & m_mask;
+ obj = Volatile.Read(ref m_array[idx]);
+
+ // Check for nulls in the array.
+ if (obj == null) continue;
+
+ m_array[idx] = null;
+ return true;
+ }
+ else
+ {
+ // Failed, restore head.
+ m_headIndex = head;
+ obj = null;
+ missedSteal = true;
+ }
+ }
+ else
+ {
+ missedSteal = true;
+ }
+ }
+ finally
+ {
+ if (taken)
+ m_foreignLock.Exit(false);
+ }
+
+ return false;
+ }
+ }
+ }
+
+ internal class QueueSegment
+ {
+ // Holds a segment of the queue. Enqueues/Dequeues start at element 0, and work their way up.
+ internal readonly IThreadPoolWorkItem[] nodes;
+ private const int QueueSegmentLength = 256;
+
+ // Holds the indexes of the lowest and highest valid elements of the nodes array.
+ // The low index is in the lower 16 bits, high index is in the upper 16 bits.
+ // Use GetIndexes and CompareExchangeIndexes to manipulate this.
+ private volatile int indexes;
+
+ // The next segment in the queue.
+ public volatile QueueSegment Next;
+
+
+ const int SixteenBits = 0xffff;
+
+ void GetIndexes(out int upper, out int lower)
+ {
+ int i = indexes;
+ upper = (i >> 16) & SixteenBits;
+ lower = i & SixteenBits;
+
+ Contract.Assert(upper >= lower);
+ Contract.Assert(upper <= nodes.Length);
+ Contract.Assert(lower <= nodes.Length);
+ Contract.Assert(upper >= 0);
+ Contract.Assert(lower >= 0);
+ }
+
+ bool CompareExchangeIndexes(ref int prevUpper, int newUpper, ref int prevLower, int newLower)
+ {
+ Contract.Assert(newUpper >= newLower);
+ Contract.Assert(newUpper <= nodes.Length);
+ Contract.Assert(newLower <= nodes.Length);
+ Contract.Assert(newUpper >= 0);
+ Contract.Assert(newLower >= 0);
+ Contract.Assert(newUpper >= prevUpper);
+ Contract.Assert(newLower >= prevLower);
+ Contract.Assert(newUpper == prevUpper ^ newLower == prevLower);
+
+ int oldIndexes = (prevUpper << 16) | (prevLower & SixteenBits);
+ int newIndexes = (newUpper << 16) | (newLower & SixteenBits);
+ int prevIndexes = Interlocked.CompareExchange(ref indexes, newIndexes, oldIndexes);
+ prevUpper = (prevIndexes >> 16) & SixteenBits;
+ prevLower = prevIndexes & SixteenBits;
+ return prevIndexes == oldIndexes;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public QueueSegment()
+ {
+ Contract.Assert(QueueSegmentLength <= SixteenBits);
+ nodes = new IThreadPoolWorkItem[QueueSegmentLength];
+ }
+
+
+ public bool IsUsedUp()
+ {
+ int upper, lower;
+ GetIndexes(out upper, out lower);
+ return (upper == nodes.Length) &&
+ (lower == nodes.Length);
+ }
+
+ public bool TryEnqueue(IThreadPoolWorkItem node)
+ {
+ //
+ // If there's room in this segment, atomically increment the upper count (to reserve
+ // space for this node), then store the node.
+ // Note that this leaves a window where it will look like there is data in that
+ // array slot, but it hasn't been written yet. This is taken care of in TryDequeue
+ // with a busy-wait loop, waiting for the element to become non-null. This implies
+ // that we can never store null nodes in this data structure.
+ //
+ Contract.Assert(null != node);
+
+ int upper, lower;
+ GetIndexes(out upper, out lower);
+
+ while (true)
+ {
+ if (upper == nodes.Length)
+ return false;
+
+ if (CompareExchangeIndexes(ref upper, upper + 1, ref lower, lower))
+ {
+ Contract.Assert(Volatile.Read(ref nodes[upper]) == null);
+ Volatile.Write(ref nodes[upper], node);
+ return true;
+ }
+ }
+ }
+
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread safety")]
+ public bool TryDequeue(out IThreadPoolWorkItem node)
+ {
+ //
+ // If there are nodes in this segment, increment the lower count, then take the
+ // element we find there.
+ //
+ int upper, lower;
+ GetIndexes(out upper, out lower);
+
+ while(true)
+ {
+ if (lower == upper)
+ {
+ node = null;
+ return false;
+ }
+
+ if (CompareExchangeIndexes(ref upper, upper, ref lower, lower + 1))
+ {
+ // It's possible that a concurrent call to Enqueue hasn't yet
+ // written the node reference to the array. We need to spin until
+ // it shows up.
+ SpinWait spinner = new SpinWait();
+ while ((node = Volatile.Read(ref nodes[lower])) == null)
+ spinner.SpinOnce();
+
+ // Null-out the reference so the object can be GC'd earlier.
+ nodes[lower] = null;
+
+ return true;
+ }
+ }
+ }
+ }
+
+ // The head and tail of the queue. We enqueue to the head, and dequeue from the tail.
+ internal volatile QueueSegment queueHead;
+ internal volatile QueueSegment queueTail;
+ internal bool loggingEnabled;
+
+ internal static SparseArray<WorkStealingQueue> allThreadQueues = new SparseArray<WorkStealingQueue>(16);
+
+ private volatile int numOutstandingThreadRequests = 0;
+
+ public ThreadPoolWorkQueue()
+ {
+ queueTail = queueHead = new QueueSegment();
+ loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, FrameworkEventSource.Keywords.ThreadPool|FrameworkEventSource.Keywords.ThreadTransfer);
+ }
+
+ [SecurityCritical]
+ public ThreadPoolWorkQueueThreadLocals EnsureCurrentThreadHasQueue()
+ {
+ if (null == ThreadPoolWorkQueueThreadLocals.threadLocals)
+ ThreadPoolWorkQueueThreadLocals.threadLocals = new ThreadPoolWorkQueueThreadLocals(this);
+ return ThreadPoolWorkQueueThreadLocals.threadLocals;
+ }
+
+ [SecurityCritical]
+ internal void EnsureThreadRequested()
+ {
+ //
+ // If we have not yet requested #procs threads from the VM, then request a new thread.
+ // Note that there is a separate count in the VM which will also be incremented in this case,
+ // which is handled by RequestWorkerThread.
+ //
+ int count = numOutstandingThreadRequests;
+ while (count < ThreadPoolGlobals.processorCount)
+ {
+ int prev = Interlocked.CompareExchange(ref numOutstandingThreadRequests, count+1, count);
+ if (prev == count)
+ {
+ ThreadPool.RequestWorkerThread();
+ break;
+ }
+ count = prev;
+ }
+ }
+
+ [SecurityCritical]
+ internal void MarkThreadRequestSatisfied()
+ {
+ //
+ // The VM has called us, so one of our outstanding thread requests has been satisfied.
+ // Decrement the count so that future calls to EnsureThreadRequested will succeed.
+ // Note that there is a separate count in the VM which has already been decremented by the VM
+ // by the time we reach this point.
+ //
+ int count = numOutstandingThreadRequests;
+ while (count > 0)
+ {
+ int prev = Interlocked.CompareExchange(ref numOutstandingThreadRequests, count - 1, count);
+ if (prev == count)
+ {
+ break;
+ }
+ count = prev;
+ }
+ }
+
+ [SecurityCritical]
+ public void Enqueue(IThreadPoolWorkItem callback, bool forceGlobal)
+ {
+ ThreadPoolWorkQueueThreadLocals tl = null;
+ if (!forceGlobal)
+ tl = ThreadPoolWorkQueueThreadLocals.threadLocals;
+
+ if (loggingEnabled)
+ System.Diagnostics.Tracing.FrameworkEventSource.Log.ThreadPoolEnqueueWorkObject(callback);
+
+ if (null != tl)
+ {
+ tl.workStealingQueue.LocalPush(callback);
+ }
+ else
+ {
+ QueueSegment head = queueHead;
+
+ while (!head.TryEnqueue(callback))
+ {
+ Interlocked.CompareExchange(ref head.Next, new QueueSegment(), null);
+
+ while (head.Next != null)
+ {
+ Interlocked.CompareExchange(ref queueHead, head.Next, head);
+ head = queueHead;
+ }
+ }
+ }
+
+ EnsureThreadRequested();
+ }
+
+ [SecurityCritical]
+ internal bool LocalFindAndPop(IThreadPoolWorkItem callback)
+ {
+ ThreadPoolWorkQueueThreadLocals tl = ThreadPoolWorkQueueThreadLocals.threadLocals;
+ if (null == tl)
+ return false;
+
+ return tl.workStealingQueue.LocalFindAndPop(callback);
+ }
+
+ [SecurityCritical]
+ public void Dequeue(ThreadPoolWorkQueueThreadLocals tl, out IThreadPoolWorkItem callback, out bool missedSteal)
+ {
+ callback = null;
+ missedSteal = false;
+ WorkStealingQueue wsq = tl.workStealingQueue;
+
+ if (wsq.LocalPop(out callback))
+ Contract.Assert(null != callback);
+
+ if (null == callback)
+ {
+ QueueSegment tail = queueTail;
+ while (true)
+ {
+ if (tail.TryDequeue(out callback))
+ {
+ Contract.Assert(null != callback);
+ break;
+ }
+
+ if (null == tail.Next || !tail.IsUsedUp())
+ {
+ break;
+ }
+ else
+ {
+ Interlocked.CompareExchange(ref queueTail, tail.Next, tail);
+ tail = queueTail;
+ }
+ }
+ }
+
+ if (null == callback)
+ {
+ WorkStealingQueue[] otherQueues = allThreadQueues.Current;
+ int c = otherQueues.Length;
+ int maxIndex = c - 1;
+ int i = tl.random.Next(c);
+ while (c > 0)
+ {
+ i = (i < maxIndex) ? i + 1 : 0;
+ WorkStealingQueue otherQueue = Volatile.Read(ref otherQueues[i]);
+ if (otherQueue != null &&
+ otherQueue != wsq &&
+ otherQueue.TrySteal(out callback, ref missedSteal))
+ {
+ Contract.Assert(null != callback);
+ break;
+ }
+ c--;
+ }
+ }
+ }
+
+ [SecurityCritical]
+ static internal bool Dispatch()
+ {
+ var workQueue = ThreadPoolGlobals.workQueue;
+ //
+ // The clock is ticking! We have ThreadPoolGlobals.tpQuantum milliseconds to get some work done, and then
+ // we need to return to the VM.
+ //
+ int quantumStartTime = Environment.TickCount;
+
+ //
+ // Update our records to indicate that an outstanding request for a thread has now been fulfilled.
+ // From this point on, we are responsible for requesting another thread if we stop working for any
+ // reason, and we believe there might still be work in the queue.
+ //
+ // Note that if this thread is aborted before we get a chance to request another one, the VM will
+ // record a thread request on our behalf. So we don't need to worry about getting aborted right here.
+ //
+ workQueue.MarkThreadRequestSatisfied();
+
+ // Has the desire for logging changed since the last time we entered?
+ workQueue.loggingEnabled = FrameworkEventSource.Log.IsEnabled(EventLevel.Verbose, FrameworkEventSource.Keywords.ThreadPool|FrameworkEventSource.Keywords.ThreadTransfer);
+
+ //
+ // Assume that we're going to need another thread if this one returns to the VM. We'll set this to
+ // false later, but only if we're absolutely certain that the queue is empty.
+ //
+ bool needAnotherThread = true;
+ IThreadPoolWorkItem workItem = null;
+ try
+ {
+ //
+ // Set up our thread-local data
+ //
+ ThreadPoolWorkQueueThreadLocals tl = workQueue.EnsureCurrentThreadHasQueue();
+
+ //
+ // Loop until our quantum expires.
+ //
+ while ((Environment.TickCount - quantumStartTime) < ThreadPoolGlobals.tpQuantum)
+ {
+ //
+ // Dequeue and EnsureThreadRequested must be protected from ThreadAbortException.
+ // These are fast, so this will not delay aborts/AD-unloads for very long.
+ //
+ try { }
+ finally
+ {
+ bool missedSteal = false;
+ workQueue.Dequeue(tl, out workItem, out missedSteal);
+
+ if (workItem == null)
+ {
+ //
+ // No work. We're going to return to the VM once we leave this protected region.
+ // If we missed a steal, though, there may be more work in the queue.
+ // Instead of looping around and trying again, we'll just request another thread. This way
+ // we won't starve other AppDomains while we spin trying to get locks, and hopefully the thread
+ // that owns the contended work-stealing queue will pick up its own workitems in the meantime,
+ // which will be more efficient than this thread doing it anyway.
+ //
+ needAnotherThread = missedSteal;
+ }
+ else
+ {
+ //
+ // If we found work, there may be more work. Ask for another thread so that the other work can be processed
+ // in parallel. Note that this will only ask for a max of #procs threads, so it's safe to call it for every dequeue.
+ //
+ workQueue.EnsureThreadRequested();
+ }
+ }
+
+ if (workItem == null)
+ {
+ // Tell the VM we're returning normally, not because Hill Climbing asked us to return.
+ return true;
+ }
+ else
+ {
+ if (workQueue.loggingEnabled)
+ System.Diagnostics.Tracing.FrameworkEventSource.Log.ThreadPoolDequeueWorkObject(workItem);
+
+ //
+ // Execute the workitem outside of any finally blocks, so that it can be aborted if needed.
+ //
+ if (ThreadPoolGlobals.enableWorkerTracking)
+ {
+ bool reportedStatus = false;
+ try
+ {
+ try { }
+ finally
+ {
+ ThreadPool.ReportThreadStatus(true);
+ reportedStatus = true;
+ }
+ workItem.ExecuteWorkItem();
+ workItem = null;
+ }
+ finally
+ {
+ if (reportedStatus)
+ ThreadPool.ReportThreadStatus(false);
+ }
+ }
+ else
+ {
+ workItem.ExecuteWorkItem();
+ workItem = null;
+ }
+
+ //
+ // Notify the VM that we executed this workitem. This is also our opportunity to ask whether Hill Climbing wants
+ // us to return the thread to the pool or not.
+ //
+ if (!ThreadPool.NotifyWorkItemComplete())
+ return false;
+ }
+ }
+ // If we get here, it's because our quantum expired. Tell the VM we're returning normally.
+ return true;
+ }
+ catch (ThreadAbortException tae)
+ {
+ //
+ // This is here to catch the case where this thread is aborted between the time we exit the finally block in the dispatch
+ // loop, and the time we execute the work item. QueueUserWorkItemCallback uses this to update its accounting of whether
+ // it was executed or not (in debug builds only). Task uses this to communicate the ThreadAbortException to anyone
+ // who waits for the task to complete.
+ //
+ if (workItem != null)
+ workItem.MarkAborted(tae);
+
+ //
+ // In this case, the VM is going to request another thread on our behalf. No need to do it twice.
+ //
+ needAnotherThread = false;
+ // throw; //no need to explicitly rethrow a ThreadAbortException, and doing so causes allocations on amd64.
+ }
+ finally
+ {
+ //
+ // If we are exiting for any reason other than that the queue is definitely empty, ask for another
+ // thread to pick up where we left off.
+ //
+ if (needAnotherThread)
+ workQueue.EnsureThreadRequested();
+ }
+
+ // we can never reach this point, but the C# compiler doesn't know that, because it doesn't know the ThreadAbortException will be reraised above.
+ Contract.Assert(false);
+ return true;
+ }
+ }
+
+ // Holds a WorkStealingQueue, and remmoves it from the list when this object is no longer referened.
+ internal sealed class ThreadPoolWorkQueueThreadLocals
+ {
+ [ThreadStatic]
+ [SecurityCritical]
+ public static ThreadPoolWorkQueueThreadLocals threadLocals;
+
+ public readonly ThreadPoolWorkQueue workQueue;
+ public readonly ThreadPoolWorkQueue.WorkStealingQueue workStealingQueue;
+ public readonly Random random = new Random(Thread.CurrentThread.ManagedThreadId);
+
+ public ThreadPoolWorkQueueThreadLocals(ThreadPoolWorkQueue tpq)
+ {
+ workQueue = tpq;
+ workStealingQueue = new ThreadPoolWorkQueue.WorkStealingQueue();
+ ThreadPoolWorkQueue.allThreadQueues.Add(workStealingQueue);
+ }
+
+ [SecurityCritical]
+ private void CleanUp()
+ {
+ if (null != workStealingQueue)
+ {
+ if (null != workQueue)
+ {
+ bool done = false;
+ while (!done)
+ {
+ // Ensure that we won't be aborted between LocalPop and Enqueue.
+ try { }
+ finally
+ {
+ IThreadPoolWorkItem cb = null;
+ if (workStealingQueue.LocalPop(out cb))
+ {
+ Contract.Assert(null != cb);
+ workQueue.Enqueue(cb, true);
+ }
+ else
+ {
+ done = true;
+ }
+ }
+ }
+ }
+
+ ThreadPoolWorkQueue.allThreadQueues.Remove(workStealingQueue);
+ }
+ }
+
+ [SecuritySafeCritical]
+ ~ThreadPoolWorkQueueThreadLocals()
+ {
+ // Since the purpose of calling CleanUp is to transfer any pending workitems into the global
+ // queue so that they will be executed by another thread, there's no point in doing this cleanup
+ // if we're in the process of shutting down or unloading the AD. In those cases, the work won't
+ // execute anyway. And there are subtle race conditions involved there that would lead us to do the wrong
+ // thing anyway. So we'll only clean up if this is a "normal" finalization.
+ if (!(Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload()))
+ CleanUp();
+ }
+ }
+
+ internal sealed class RegisteredWaitHandleSafe : CriticalFinalizerObject
+ {
+ private static IntPtr InvalidHandle
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ return Win32Native.INVALID_HANDLE_VALUE;
+ }
+ }
+ private IntPtr registeredWaitHandle;
+ private WaitHandle m_internalWaitObject;
+ private bool bReleaseNeeded = false;
+ private volatile int m_lock = 0;
+
+ #if FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ #endif
+ internal RegisteredWaitHandleSafe()
+ {
+ registeredWaitHandle = InvalidHandle;
+ }
+
+ internal IntPtr GetHandle()
+ {
+ return registeredWaitHandle;
+ }
+
+ internal void SetHandle(IntPtr handle)
+ {
+ registeredWaitHandle = handle;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal void SetWaitObject(WaitHandle waitObject)
+ {
+ // needed for DangerousAddRef
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ }
+ finally
+ {
+ m_internalWaitObject = waitObject;
+ if (waitObject != null)
+ {
+ m_internalWaitObject.SafeWaitHandle.DangerousAddRef(ref bReleaseNeeded);
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ internal bool Unregister(
+ WaitHandle waitObject // object to be notified when all callbacks to delegates have completed
+ )
+ {
+ bool result = false;
+ // needed for DangerousRelease
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ }
+ finally
+ {
+ // lock(this) cannot be used reliably in Cer since thin lock could be
+ // promoted to syncblock and that is not a guaranteed operation
+ bool bLockTaken = false;
+ do
+ {
+ if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0)
+ {
+ bLockTaken = true;
+ try
+ {
+ if (ValidHandle())
+ {
+ result = UnregisterWaitNative(GetHandle(), waitObject == null ? null : waitObject.SafeWaitHandle);
+ if (result == true)
+ {
+ if (bReleaseNeeded)
+ {
+ m_internalWaitObject.SafeWaitHandle.DangerousRelease();
+ bReleaseNeeded = false;
+ }
+ // if result not true don't release/suppress here so finalizer can make another attempt
+ SetHandle(InvalidHandle);
+ m_internalWaitObject = null;
+ GC.SuppressFinalize(this);
+ }
+ }
+ }
+ finally
+ {
+ m_lock = 0;
+ }
+ }
+ Thread.SpinWait(1); // yield to processor
+ }
+ while (!bLockTaken);
+ }
+ return result;
+ }
+
+ private bool ValidHandle()
+ {
+ return (registeredWaitHandle != InvalidHandle && registeredWaitHandle != IntPtr.Zero);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ ~RegisteredWaitHandleSafe()
+ {
+ // if the app has already unregistered the wait, there is nothing to cleanup
+ // we can detect this by checking the handle. Normally, there is no race condition here
+ // so no need to protect reading of handle. However, if this object gets
+ // resurrected and then someone does an unregister, it would introduce a race condition
+ //
+ // PrepareConstrainedRegions call not needed since finalizer already in Cer
+ //
+ // lock(this) cannot be used reliably even in Cer since thin lock could be
+ // promoted to syncblock and that is not a guaranteed operation
+ //
+ // Note that we will not "spin" to get this lock. We make only a single attempt;
+ // if we can't get the lock, it means some other thread is in the middle of a call
+ // to Unregister, which will do the work of the finalizer anyway.
+ //
+ // Further, it's actually critical that we *not* wait for the lock here, because
+ // the other thread that's in the middle of Unregister may be suspended for shutdown.
+ // Then, during the live-object finalization phase of shutdown, this thread would
+ // end up spinning forever, as the other thread would never release the lock.
+ // This will result in a "leak" of sorts (since the handle will not be cleaned up)
+ // but the process is exiting anyway.
+ //
+ // During AD-unload, we don’t finalize live objects until all threads have been
+ // aborted out of the AD. Since these locked regions are CERs, we won’t abort them
+ // while the lock is held. So there should be no leak on AD-unload.
+ //
+ if (Interlocked.CompareExchange(ref m_lock, 1, 0) == 0)
+ {
+ try
+ {
+ if (ValidHandle())
+ {
+ WaitHandleCleanupNative(registeredWaitHandle);
+ if (bReleaseNeeded)
+ {
+ m_internalWaitObject.SafeWaitHandle.DangerousRelease();
+ bReleaseNeeded = false;
+ }
+ SetHandle(InvalidHandle);
+ m_internalWaitObject = null;
+ }
+ }
+ finally
+ {
+ m_lock = 0;
+ }
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void WaitHandleCleanupNative(IntPtr handle);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool UnregisterWaitNative(IntPtr handle, SafeHandle waitObject);
+ }
+
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_REMOTING
+ public sealed class RegisteredWaitHandle : MarshalByRefObject {
+#else // FEATURE_REMOTING
+ public sealed class RegisteredWaitHandle {
+#endif // FEATURE_REMOTING
+ private RegisteredWaitHandleSafe internalRegisteredWait;
+
+ internal RegisteredWaitHandle()
+ {
+ internalRegisteredWait = new RegisteredWaitHandleSafe();
+ }
+
+ internal void SetHandle(IntPtr handle)
+ {
+ internalRegisteredWait.SetHandle(handle);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetWaitObject(WaitHandle waitObject)
+ {
+ internalRegisteredWait.SetWaitObject(waitObject);
+ }
+
+
+[System.Security.SecuritySafeCritical] // auto-generated
+[System.Runtime.InteropServices.ComVisible(true)]
+ // This is the only public method on this class
+ public bool Unregister(
+ WaitHandle waitObject // object to be notified when all callbacks to delegates have completed
+ )
+ {
+ return internalRegisteredWait.Unregister(waitObject);
+ }
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void WaitCallback(Object state);
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void WaitOrTimerCallback(Object state, bool timedOut); // signalled or timed out
+
+ //
+ // This type is necessary because VS 2010's debugger looks for a method named _ThreadPoolWaitCallbacck.PerformWaitCallback
+ // on the stack to determine if a thread is a ThreadPool thread or not. We have a better way to do this for .NET 4.5, but
+ // still need to maintain compatibility with VS 2010. When compat with VS 2010 is no longer an issue, this type may be
+ // removed.
+ //
+ internal static class _ThreadPoolWaitCallback
+ {
+ [System.Security.SecurityCritical]
+ static internal bool PerformWaitCallback()
+ {
+ return ThreadPoolWorkQueue.Dispatch();
+ }
+ }
+
+ //
+ // Interface to something that can be queued to the TP. This is implemented by
+ // QueueUserWorkItemCallback, Task, and potentially other internal types.
+ // For example, SemaphoreSlim represents callbacks using its own type that
+ // implements IThreadPoolWorkItem.
+ //
+ // If we decide to expose some of the workstealing
+ // stuff, this is NOT the thing we want to expose to the public.
+ //
+ internal interface IThreadPoolWorkItem
+ {
+ [SecurityCritical]
+ void ExecuteWorkItem();
+ [SecurityCritical]
+ void MarkAborted(ThreadAbortException tae);
+ }
+
+ internal sealed class QueueUserWorkItemCallback : IThreadPoolWorkItem
+ {
+ [System.Security.SecuritySafeCritical]
+ static QueueUserWorkItemCallback() {}
+
+ private WaitCallback callback;
+ private ExecutionContext context;
+ private Object state;
+
+#if DEBUG
+ volatile int executed;
+
+ ~QueueUserWorkItemCallback()
+ {
+ Contract.Assert(
+ executed != 0 || Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload(),
+ "A QueueUserWorkItemCallback was never called!");
+ }
+
+ void MarkExecuted(bool aborted)
+ {
+ GC.SuppressFinalize(this);
+ Contract.Assert(
+ 0 == Interlocked.Exchange(ref executed, 1) || aborted,
+ "A QueueUserWorkItemCallback was called twice!");
+ }
+#endif
+
+ [SecurityCritical]
+ internal QueueUserWorkItemCallback(WaitCallback waitCallback, Object stateObj, ExecutionContext ec)
+ {
+ callback = waitCallback;
+ state = stateObj;
+ context = ec;
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+#if DEBUG
+ MarkExecuted(false);
+#endif
+ // call directly if it is an unsafe call OR EC flow is suppressed
+ if (context == null)
+ {
+ WaitCallback cb = callback;
+ callback = null;
+ cb(state);
+ }
+ else
+ {
+ ExecutionContext.Run(context, ccb, this, true);
+ }
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
+ {
+#if DEBUG
+ // this workitem didn't execute because we got a ThreadAbortException prior to the call to ExecuteWorkItem.
+ // This counts as being executed for our purposes.
+ MarkExecuted(true);
+#endif
+ }
+
+ [System.Security.SecurityCritical]
+ static internal ContextCallback ccb = new ContextCallback(WaitCallback_Context);
+
+ [System.Security.SecurityCritical]
+ static private void WaitCallback_Context(Object state)
+ {
+ QueueUserWorkItemCallback obj = (QueueUserWorkItemCallback)state;
+ WaitCallback wc = obj.callback as WaitCallback;
+ Contract.Assert(null != wc);
+ wc(obj.state);
+ }
+ }
+
+ internal sealed class QueueUserWorkItemCallbackDefaultContext : IThreadPoolWorkItem
+ {
+ [System.Security.SecuritySafeCritical]
+ static QueueUserWorkItemCallbackDefaultContext() { }
+
+ private WaitCallback callback;
+ private Object state;
+
+#if DEBUG
+ private volatile int executed;
+
+ ~QueueUserWorkItemCallbackDefaultContext()
+ {
+ Contract.Assert(
+ executed != 0 || Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload(),
+ "A QueueUserWorkItemCallbackDefaultContext was never called!");
+ }
+
+ void MarkExecuted(bool aborted)
+ {
+ GC.SuppressFinalize(this);
+ Contract.Assert(
+ 0 == Interlocked.Exchange(ref executed, 1) || aborted,
+ "A QueueUserWorkItemCallbackDefaultContext was called twice!");
+ }
+#endif
+
+ [SecurityCritical]
+ internal QueueUserWorkItemCallbackDefaultContext(WaitCallback waitCallback, Object stateObj)
+ {
+ callback = waitCallback;
+ state = stateObj;
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.ExecuteWorkItem()
+ {
+#if DEBUG
+ MarkExecuted(false);
+#endif
+ ExecutionContext.Run(ExecutionContext.PreAllocatedDefault, ccb, this, true);
+ }
+
+ [SecurityCritical]
+ void IThreadPoolWorkItem.MarkAborted(ThreadAbortException tae)
+ {
+#if DEBUG
+ // this workitem didn't execute because we got a ThreadAbortException prior to the call to ExecuteWorkItem.
+ // This counts as being executed for our purposes.
+ MarkExecuted(true);
+#endif
+ }
+
+ [System.Security.SecurityCritical]
+ static internal ContextCallback ccb = new ContextCallback(WaitCallback_Context);
+
+ [System.Security.SecurityCritical]
+ static private void WaitCallback_Context(Object state)
+ {
+ QueueUserWorkItemCallbackDefaultContext obj = (QueueUserWorkItemCallbackDefaultContext)state;
+ WaitCallback wc = obj.callback as WaitCallback;
+ Contract.Assert(null != wc);
+ obj.callback = null;
+ wc(obj.state);
+ }
+ }
+
+ internal class _ThreadPoolWaitOrTimerCallback
+ {
+ [System.Security.SecuritySafeCritical]
+ static _ThreadPoolWaitOrTimerCallback() {}
+
+ WaitOrTimerCallback _waitOrTimerCallback;
+ ExecutionContext _executionContext;
+ Object _state;
+ [System.Security.SecurityCritical]
+ static private ContextCallback _ccbt = new ContextCallback(WaitOrTimerCallback_Context_t);
+ [System.Security.SecurityCritical]
+ static private ContextCallback _ccbf = new ContextCallback(WaitOrTimerCallback_Context_f);
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal _ThreadPoolWaitOrTimerCallback(WaitOrTimerCallback waitOrTimerCallback, Object state, bool compressStack, ref StackCrawlMark stackMark)
+ {
+ _waitOrTimerCallback = waitOrTimerCallback;
+ _state = state;
+
+ if (compressStack && !ExecutionContext.IsFlowSuppressed())
+ {
+ // capture the exection context
+ _executionContext = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
+ }
+ }
+
+ [System.Security.SecurityCritical]
+ static private void WaitOrTimerCallback_Context_t(Object state)
+ {
+ WaitOrTimerCallback_Context(state, true);
+ }
+
+ [System.Security.SecurityCritical]
+ static private void WaitOrTimerCallback_Context_f(Object state)
+ {
+ WaitOrTimerCallback_Context(state, false);
+ }
+
+ static private void WaitOrTimerCallback_Context(Object state, bool timedOut)
+ {
+ _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
+ helper._waitOrTimerCallback(helper._state, timedOut);
+ }
+
+ // call back helper
+ [System.Security.SecurityCritical] // auto-generated
+ static internal void PerformWaitOrTimerCallback(Object state, bool timedOut)
+ {
+ _ThreadPoolWaitOrTimerCallback helper = (_ThreadPoolWaitOrTimerCallback)state;
+ Contract.Assert(helper != null, "Null state passed to PerformWaitOrTimerCallback!");
+ // call directly if it is an unsafe call OR EC flow is suppressed
+ if (helper._executionContext == null)
+ {
+ WaitOrTimerCallback callback = helper._waitOrTimerCallback;
+ callback(helper._state, timedOut);
+ }
+ else
+ {
+ using (ExecutionContext executionContext = helper._executionContext.CreateCopy())
+ {
+ if (timedOut)
+ ExecutionContext.Run(executionContext, _ccbt, helper, true);
+ else
+ ExecutionContext.Run(executionContext, _ccbf, helper, true);
+ }
+ }
+ }
+
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ unsafe public delegate void IOCompletionCallback(uint errorCode, // Error code
+ uint numBytes, // No. of bytes transferred
+ NativeOverlapped* pOVERLAP // ptr to OVERLAP structure
+ );
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ public static class ThreadPool
+ {
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
+#pragma warning restore 618
+ public static bool SetMaxThreads(int workerThreads, int completionPortThreads)
+ {
+ return SetMaxThreadsNative(workerThreads, completionPortThreads);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void GetMaxThreads(out int workerThreads, out int completionPortThreads)
+ {
+ GetMaxThreadsNative(out workerThreads, out completionPortThreads);
+ }
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)]
+#pragma warning restore 618
+ public static bool SetMinThreads(int workerThreads, int completionPortThreads)
+ {
+ return SetMinThreadsNative(workerThreads, completionPortThreads);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void GetMinThreads(out int workerThreads, out int completionPortThreads)
+ {
+ GetMinThreadsNative(out workerThreads, out completionPortThreads);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static void GetAvailableThreads(out int workerThreads, out int completionPortThreads)
+ {
+ GetAvailableThreadsNative(out workerThreads, out completionPortThreads);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ uint millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false)]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ uint millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ private static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ uint millisecondsTimeOutInterval,
+ bool executeOnlyOnce, // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ ref StackCrawlMark stackMark,
+ bool compressStack
+ )
+ {
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(waitObject))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy"));
+ Contract.EndContractBlock();
+#endif
+
+ RegisteredWaitHandle registeredWaitHandle = new RegisteredWaitHandle();
+
+ if (callBack != null)
+ {
+ _ThreadPoolWaitOrTimerCallback callBackHelper = new _ThreadPoolWaitOrTimerCallback(callBack, state, compressStack, ref stackMark);
+ state = (Object)callBackHelper;
+ // call SetWaitObject before native call so that waitObject won't be closed before threadpoolmgr registration
+ // this could occur if callback were to fire before SetWaitObject does its addref
+ registeredWaitHandle.SetWaitObject(waitObject);
+ IntPtr nativeRegisteredWaitHandle = RegisterWaitForSingleObjectNative(waitObject,
+ state,
+ millisecondsTimeOutInterval,
+ executeOnlyOnce,
+ registeredWaitHandle,
+ ref stackMark,
+ compressStack);
+ registeredWaitHandle.SetHandle(nativeRegisteredWaitHandle);
+ }
+ else
+ {
+ throw new ArgumentNullException("WaitOrTimerCallback");
+ }
+ return registeredWaitHandle;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ int millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ if (millisecondsTimeOutInterval < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ int millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ if (millisecondsTimeOutInterval < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle RegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ long millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ if (millisecondsTimeOutInterval < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( // throws RegisterWaitException
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ long millisecondsTimeOutInterval,
+ bool executeOnlyOnce // NOTE: we do not allow other options that allow the callback to be queued as an APC
+ )
+ {
+ if (millisecondsTimeOutInterval < -1)
+ throw new ArgumentOutOfRangeException("millisecondsTimeOutInterval", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)millisecondsTimeOutInterval,executeOnlyOnce,ref stackMark,false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle RegisterWaitForSingleObject(
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ TimeSpan timeout,
+ bool executeOnlyOnce
+ )
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(
+ WaitHandle waitObject,
+ WaitOrTimerCallback callBack,
+ Object state,
+ TimeSpan timeout,
+ bool executeOnlyOnce
+ )
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (tm < -1)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (tm > (long) Int32.MaxValue)
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_LessEqualToIntegerMaxVal"));
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RegisterWaitForSingleObject(waitObject,callBack,state,(UInt32)tm,executeOnlyOnce,ref stackMark,false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static bool QueueUserWorkItem(
+ WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC
+ Object state
+ )
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return QueueUserWorkItemHelper(callBack,state,ref stackMark,true);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static bool QueueUserWorkItem(
+ WaitCallback callBack // NOTE: we do not expose options that allow the callback to be queued as an APC
+ )
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return QueueUserWorkItemHelper(callBack,null,ref stackMark,true);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static bool UnsafeQueueUserWorkItem(
+ WaitCallback callBack, // NOTE: we do not expose options that allow the callback to be queued as an APC
+ Object state
+ )
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return QueueUserWorkItemHelper(callBack,state,ref stackMark,false);
+ }
+
+ //ThreadPool has per-appdomain managed queue of work-items. The VM is
+ //responsible for just scheduling threads into appdomains. After that
+ //work-items are dispatched from the managed queue.
+ [System.Security.SecurityCritical] // auto-generated
+ private static bool QueueUserWorkItemHelper(WaitCallback callBack, Object state, ref StackCrawlMark stackMark, bool compressStack )
+ {
+ bool success = true;
+
+ if (callBack != null)
+ {
+ //The thread pool maintains a per-appdomain managed work queue.
+ //New thread pool entries are added in the managed queue.
+ //The VM is responsible for the actual growing/shrinking of
+ //threads.
+
+ EnsureVMInitialized();
+
+ //
+ // If we are able to create the workitem, we need to get it in the queue without being interrupted
+ // by a ThreadAbortException.
+ //
+ try { }
+ finally
+ {
+ ExecutionContext context = compressStack && !ExecutionContext.IsFlowSuppressed() ?
+ ExecutionContext.Capture(ref stackMark, ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase) :
+ null;
+
+ IThreadPoolWorkItem tpcallBack = context == ExecutionContext.PreAllocatedDefault ?
+ new QueueUserWorkItemCallbackDefaultContext(callBack, state) :
+ (IThreadPoolWorkItem)new QueueUserWorkItemCallback(callBack, state, context);
+
+ ThreadPoolGlobals.workQueue.Enqueue(tpcallBack, true);
+ success = true;
+ }
+ }
+ else
+ {
+ throw new ArgumentNullException("WaitCallback");
+ }
+ return success;
+ }
+
+ [SecurityCritical]
+ internal static void UnsafeQueueCustomWorkItem(IThreadPoolWorkItem workItem, bool forceGlobal)
+ {
+ Contract.Assert(null != workItem);
+ EnsureVMInitialized();
+
+ //
+ // Enqueue needs to be protected from ThreadAbort
+ //
+ try { }
+ finally
+ {
+ ThreadPoolGlobals.workQueue.Enqueue(workItem, forceGlobal);
+ }
+ }
+
+ // This method tries to take the target callback out of the current thread's queue.
+ [SecurityCritical]
+ internal static bool TryPopCustomWorkItem(IThreadPoolWorkItem workItem)
+ {
+ Contract.Assert(null != workItem);
+ if (!ThreadPoolGlobals.vmTpInitialized)
+ return false; //Not initialized, so there's no way this workitem was ever queued.
+ return ThreadPoolGlobals.workQueue.LocalFindAndPop(workItem);
+ }
+
+ // Get all workitems. Called by TaskScheduler in its debugger hooks.
+ [SecurityCritical]
+ internal static IEnumerable<IThreadPoolWorkItem> GetQueuedWorkItems()
+ {
+ return EnumerateQueuedWorkItems(ThreadPoolWorkQueue.allThreadQueues.Current, ThreadPoolGlobals.workQueue.queueTail);
+ }
+
+ internal static IEnumerable<IThreadPoolWorkItem> EnumerateQueuedWorkItems(ThreadPoolWorkQueue.WorkStealingQueue[] wsQueues, ThreadPoolWorkQueue.QueueSegment globalQueueTail)
+ {
+ if (wsQueues != null)
+ {
+ // First, enumerate all workitems in thread-local queues.
+ foreach (ThreadPoolWorkQueue.WorkStealingQueue wsq in wsQueues)
+ {
+ if (wsq != null && wsq.m_array != null)
+ {
+ IThreadPoolWorkItem[] items = wsq.m_array;
+ for (int i = 0; i < items.Length; i++)
+ {
+ IThreadPoolWorkItem item = items[i];
+ if (item != null)
+ yield return item;
+ }
+ }
+ }
+ }
+
+ if (globalQueueTail != null)
+ {
+ // Now the global queue
+ for (ThreadPoolWorkQueue.QueueSegment segment = globalQueueTail;
+ segment != null;
+ segment = segment.Next)
+ {
+ IThreadPoolWorkItem[] items = segment.nodes;
+ for (int i = 0; i < items.Length; i++)
+ {
+ IThreadPoolWorkItem item = items[i];
+ if (item != null)
+ yield return item;
+ }
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal static IEnumerable<IThreadPoolWorkItem> GetLocallyQueuedWorkItems()
+ {
+ return EnumerateQueuedWorkItems(new ThreadPoolWorkQueue.WorkStealingQueue[] { ThreadPoolWorkQueueThreadLocals.threadLocals.workStealingQueue }, null);
+ }
+
+ [SecurityCritical]
+ internal static IEnumerable<IThreadPoolWorkItem> GetGloballyQueuedWorkItems()
+ {
+ return EnumerateQueuedWorkItems(null, ThreadPoolGlobals.workQueue.queueTail);
+ }
+
+ private static object[] ToObjectArray(IEnumerable<IThreadPoolWorkItem> workitems)
+ {
+ int i = 0;
+ foreach (IThreadPoolWorkItem item in workitems)
+ {
+ i++;
+ }
+
+ object[] result = new object[i];
+ i = 0;
+ foreach (IThreadPoolWorkItem item in workitems)
+ {
+ if (i < result.Length) //just in case someone calls us while the queues are in motion
+ result[i] = item;
+ i++;
+ }
+
+ return result;
+ }
+
+ // This is the method the debugger will actually call, if it ends up calling
+ // into ThreadPool directly. Tests can use this to simulate a debugger, as well.
+ [SecurityCritical]
+ internal static object[] GetQueuedWorkItemsForDebugger()
+ {
+ return ToObjectArray(GetQueuedWorkItems());
+ }
+
+ [SecurityCritical]
+ internal static object[] GetGloballyQueuedWorkItemsForDebugger()
+ {
+ return ToObjectArray(GetGloballyQueuedWorkItems());
+ }
+
+ [SecurityCritical]
+ internal static object[] GetLocallyQueuedWorkItemsForDebugger()
+ {
+ return ToObjectArray(GetLocallyQueuedWorkItems());
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ internal static extern bool RequestWorkerThread();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ unsafe private static extern bool PostQueuedCompletionStatus(NativeOverlapped* overlapped);
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false)]
+ unsafe public static bool UnsafeQueueNativeOverlapped(NativeOverlapped* overlapped)
+ {
+ return PostQueuedCompletionStatus(overlapped);
+ }
+
+ [SecurityCritical]
+ private static void EnsureVMInitialized()
+ {
+ if (!ThreadPoolGlobals.vmTpInitialized)
+ {
+ ThreadPool.InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking);
+ ThreadPoolGlobals.vmTpInitialized = true;
+ }
+ }
+
+ // Native methods:
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool SetMinThreadsNative(int workerThreads, int completionPortThreads);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool SetMaxThreadsNative(int workerThreads, int completionPortThreads);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetMinThreadsNative(out int workerThreads, out int completionPortThreads);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetMaxThreadsNative(out int workerThreads, out int completionPortThreads);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void GetAvailableThreadsNative(out int workerThreads, out int completionPortThreads);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool NotifyWorkItemComplete();
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ReportThreadStatus(bool isWorking);
+
+ [System.Security.SecuritySafeCritical]
+ internal static void NotifyWorkItemProgress()
+ {
+ if (!ThreadPoolGlobals.vmTpInitialized)
+ ThreadPool.InitializeVMTp(ref ThreadPoolGlobals.enableWorkerTracking);
+ NotifyWorkItemProgressNative();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void NotifyWorkItemProgressNative();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsThreadPoolHosted();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void InitializeVMTp(ref bool enableWorkerTracking);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern IntPtr RegisterWaitForSingleObjectNative(
+ WaitHandle waitHandle,
+ Object state,
+ uint timeOutInterval,
+ bool executeOnlyOnce,
+ RegisteredWaitHandle registeredWaitHandle,
+ ref StackCrawlMark stackMark,
+ bool compressStack
+ );
+
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [Obsolete("ThreadPool.BindHandle(IntPtr) has been deprecated. Please use ThreadPool.BindHandle(SafeHandle) instead.", false)]
+ [SecurityPermissionAttribute( SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public static bool BindHandle(
+ IntPtr osHandle
+ )
+ {
+ return BindIOCompletionCallbackNative(osHandle);
+ }
+#endif
+
+ #if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+ #else
+ [System.Security.SecuritySafeCritical]
+ #endif
+#pragma warning disable 618
+ [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+#pragma warning restore 618
+ public static bool BindHandle(SafeHandle osHandle)
+ {
+ if (osHandle == null)
+ throw new ArgumentNullException("osHandle");
+
+ bool ret = false;
+ bool mustReleaseSafeHandle = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ osHandle.DangerousAddRef(ref mustReleaseSafeHandle);
+ ret = BindIOCompletionCallbackNative(osHandle.DangerousGetHandle());
+ }
+ finally {
+ if (mustReleaseSafeHandle)
+ osHandle.DangerousRelease();
+ }
+ return ret;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern bool BindIOCompletionCallbackNative(IntPtr fileHandle);
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadPriority.cs b/src/mscorlib/src/System/Threading/ThreadPriority.cs
new file mode 100644
index 0000000000..c56156eb89
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadPriority.cs
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Enums for the priorities of a Thread
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+ using System.Threading;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ThreadPriority
+ {
+ /*=========================================================================
+ ** Constants for thread priorities.
+ =========================================================================*/
+ Lowest = 0,
+ BelowNormal = 1,
+ Normal = 2,
+ AboveNormal = 3,
+ Highest = 4
+
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadStart.cs b/src/mscorlib/src/System/Threading/ThreadStart.cs
new file mode 100644
index 0000000000..b968117195
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadStart.cs
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: This class is a Delegate which defines the start method
+** for starting a thread. That method must match this delegate.
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+ using System.Security.Permissions;
+ using System.Threading;
+
+ // Define the delegate
+ // NOTE: If you change the signature here, there is code in COMSynchronization
+ // that invokes this delegate in native.
+[System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void ThreadStart();
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadStartException.cs b/src/mscorlib/src/System/Threading/ThreadStartException.cs
new file mode 100644
index 0000000000..33fb460b3d
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadStartException.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Threading
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.InteropServices;
+
+ [Serializable]
+ public sealed class ThreadStartException : SystemException
+ {
+ private ThreadStartException()
+ : base(Environment.GetResourceString("Arg_ThreadStartException"))
+ {
+ SetErrorCode(__HResults.COR_E_THREADSTART);
+ }
+
+ private ThreadStartException(Exception reason)
+ : base(Environment.GetResourceString("Arg_ThreadStartException"), reason)
+ {
+ SetErrorCode(__HResults.COR_E_THREADSTART);
+ }
+
+ //required for serialization
+ internal ThreadStartException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/Threading/ThreadState.cs b/src/mscorlib/src/System/Threading/ThreadState.cs
new file mode 100644
index 0000000000..007e1bf6e9
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadState.cs
@@ -0,0 +1,36 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Enum to represent the different thread states
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+
+[Serializable]
+[Flags]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public enum ThreadState
+ {
+ /*=========================================================================
+ ** Constants for thread states.
+ =========================================================================*/
+ Running = 0,
+ StopRequested = 1,
+ SuspendRequested = 2,
+ Background = 4,
+ Unstarted = 8,
+ Stopped = 16,
+ WaitSleepJoin = 32,
+ Suspended = 64,
+ AbortRequested = 128,
+ Aborted = 256
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/ThreadStateException.cs b/src/mscorlib/src/System/Threading/ThreadStateException.cs
new file mode 100644
index 0000000000..535dffcdbf
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/ThreadStateException.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: An exception class to indicate that the Thread class is in an
+** invalid state for the method.
+**
+**
+=============================================================================*/
+
+namespace System.Threading {
+ using System;
+ using System.Runtime.Serialization;
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class ThreadStateException : SystemException {
+ public ThreadStateException()
+ : base(Environment.GetResourceString("Arg_ThreadStateException")) {
+ SetErrorCode(__HResults.COR_E_THREADSTATE);
+ }
+
+ public ThreadStateException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_THREADSTATE);
+ }
+
+ public ThreadStateException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_THREADSTATE);
+ }
+
+ protected ThreadStateException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Timeout.cs b/src/mscorlib/src/System/Threading/Timeout.cs
new file mode 100644
index 0000000000..99e24159b2
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Timeout.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Threading {
+ using System.Threading;
+ using System;
+ // A constant used by methods that take a timeout (Object.Wait, Thread.Sleep
+ // etc) to indicate that no timeout should occur.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public static class Timeout
+ {
+ [System.Runtime.InteropServices.ComVisible(false)]
+ public static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, Timeout.Infinite);
+
+ public const int Infinite = -1;
+ internal const uint UnsignedInfinite = unchecked((uint)-1);
+ }
+
+}
diff --git a/src/mscorlib/src/System/Threading/Timer.cs b/src/mscorlib/src/System/Threading/Timer.cs
new file mode 100644
index 0000000000..cb08c6e033
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Timer.cs
@@ -0,0 +1,954 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+namespace System.Threading
+{
+ using System;
+ using System.Security;
+ using System.Security.Permissions;
+ using Microsoft.Win32;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.Tracing;
+ using Microsoft.Win32.SafeHandles;
+
+
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void TimerCallback(Object state);
+
+ //
+ // TimerQueue maintains a list of active timers in this AppDomain. We use a single native timer, supplied by the VM,
+ // to schedule all managed timers in the AppDomain.
+ //
+ // Perf assumptions: We assume that timers are created and destroyed frequently, but rarely actually fire.
+ // There are roughly two types of timer:
+ //
+ // - timeouts for operations. These are created and destroyed very frequently, but almost never fire, because
+ // the whole point is that the timer only fires if something has gone wrong.
+ //
+ // - scheduled background tasks. These typically do fire, but they usually have quite long durations.
+ // So the impact of spending a few extra cycles to fire these is negligible.
+ //
+ // Because of this, we want to choose a data structure with very fast insert and delete times, but we can live
+ // with linear traversal times when firing timers.
+ //
+ // The data structure we've chosen is an unordered doubly-linked list of active timers. This gives O(1) insertion
+ // and removal, and O(N) traversal when finding expired timers.
+ //
+ // Note that all instance methods of this class require that the caller hold a lock on TimerQueue.Instance.
+ //
+ class TimerQueue
+ {
+ #region singleton pattern implementation
+
+ // The one-and-only TimerQueue for the AppDomain.
+ static TimerQueue s_queue = new TimerQueue();
+
+ public static TimerQueue Instance
+ {
+ get { return s_queue; }
+ }
+
+ private TimerQueue()
+ {
+ // empty private constructor to ensure we remain a singleton.
+ }
+
+ #endregion
+
+ #region interface to native per-AppDomain timer
+
+ //
+ // We need to keep our notion of time synchronized with the calls to SleepEx that drive
+ // the underlying native timer. In Win8, SleepEx does not count the time the machine spends
+ // sleeping/hibernating. Environment.TickCount (GetTickCount) *does* count that time,
+ // so we will get out of sync with SleepEx if we use that method.
+ //
+ // So, on Win8, we use QueryUnbiasedInterruptTime instead; this does not count time spent
+ // in sleep/hibernate mode.
+ //
+ private static int TickCount
+ {
+ [SecuritySafeCritical]
+ get
+ {
+#if !FEATURE_PAL
+ if (Environment.IsWindows8OrAbove)
+ {
+ ulong time100ns;
+
+ bool result = Win32Native.QueryUnbiasedInterruptTime(out time100ns);
+ if (!result)
+ throw Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
+
+ // convert to 100ns to milliseconds, and truncate to 32 bits.
+ return (int)(uint)(time100ns / 10000);
+ }
+ else
+#endif
+ {
+ return Environment.TickCount;
+ }
+ }
+ }
+
+ //
+ // We use a SafeHandle to ensure that the native timer is destroyed when the AppDomain is unloaded.
+ //
+ [SecurityCritical]
+ class AppDomainTimerSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ public AppDomainTimerSafeHandle()
+ : base(true)
+ {
+ }
+
+ [SecurityCritical]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ protected override bool ReleaseHandle()
+ {
+ return DeleteAppDomainTimer(handle);
+ }
+ }
+
+ [SecurityCritical]
+ AppDomainTimerSafeHandle m_appDomainTimer;
+
+ bool m_isAppDomainTimerScheduled;
+ int m_currentAppDomainTimerStartTicks;
+ uint m_currentAppDomainTimerDuration;
+
+ [SecuritySafeCritical]
+ private bool EnsureAppDomainTimerFiresBy(uint requestedDuration)
+ {
+ //
+ // The VM's timer implementation does not work well for very long-duration timers.
+ // See kb 950807.
+ // So we'll limit our native timer duration to a "small" value.
+ // This may cause us to attempt to fire timers early, but that's ok -
+ // we'll just see that none of our timers has actually reached its due time,
+ // and schedule the native timer again.
+ //
+ const uint maxPossibleDuration = 0x0fffffff;
+ uint actualDuration = Math.Min(requestedDuration, maxPossibleDuration);
+
+ if (m_isAppDomainTimerScheduled)
+ {
+ uint elapsed = (uint)(TickCount - m_currentAppDomainTimerStartTicks);
+ if (elapsed >= m_currentAppDomainTimerDuration)
+ return true; //the timer's about to fire
+
+ uint remainingDuration = m_currentAppDomainTimerDuration - elapsed;
+ if (actualDuration >= remainingDuration)
+ return true; //the timer will fire earlier than this request
+ }
+
+ // If Pause is underway then do not schedule the timers
+ // A later update during resume will re-schedule
+ if(m_pauseTicks != 0)
+ {
+ Contract.Assert(!m_isAppDomainTimerScheduled);
+ Contract.Assert(m_appDomainTimer == null);
+ return true;
+ }
+
+ if (m_appDomainTimer == null || m_appDomainTimer.IsInvalid)
+ {
+ Contract.Assert(!m_isAppDomainTimerScheduled);
+
+ m_appDomainTimer = CreateAppDomainTimer(actualDuration);
+ if (!m_appDomainTimer.IsInvalid)
+ {
+ m_isAppDomainTimerScheduled = true;
+ m_currentAppDomainTimerStartTicks = TickCount;
+ m_currentAppDomainTimerDuration = actualDuration;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (ChangeAppDomainTimer(m_appDomainTimer, actualDuration))
+ {
+ m_isAppDomainTimerScheduled = true;
+ m_currentAppDomainTimerStartTicks = TickCount;
+ m_currentAppDomainTimerDuration = actualDuration;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ //
+ // The VM calls this when the native timer fires.
+ //
+ [SecuritySafeCritical]
+ internal static void AppDomainTimerCallback()
+ {
+ Instance.FireNextTimers();
+ }
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static extern AppDomainTimerSafeHandle CreateAppDomainTimer(uint dueTime);
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ static extern bool ChangeAppDomainTimer(AppDomainTimerSafeHandle handle, uint dueTime);
+
+ [System.Security.SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ static extern bool DeleteAppDomainTimer(IntPtr handle);
+
+ #endregion
+
+ #region Firing timers
+
+ //
+ // The list of timers
+ //
+ TimerQueueTimer m_timers;
+
+
+ volatile int m_pauseTicks = 0; // Time when Pause was called
+
+ [SecurityCritical]
+ internal void Pause()
+ {
+ lock(this)
+ {
+ // Delete the native timer so that no timers are fired in the Pause zone
+ if(m_appDomainTimer != null && !m_appDomainTimer.IsInvalid)
+ {
+ m_appDomainTimer.Dispose();
+ m_appDomainTimer = null;
+ m_isAppDomainTimerScheduled = false;
+ m_pauseTicks = TickCount;
+ }
+ }
+ }
+
+ [SecurityCritical]
+ internal void Resume()
+ {
+ //
+ // Update timers to adjust their due-time to accomodate Pause/Resume
+ //
+ lock (this)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ int pauseTicks = m_pauseTicks;
+ m_pauseTicks = 0; // Set this to 0 so that now timers can be scheduled
+
+ int resumedTicks = TickCount;
+ int pauseDuration = resumedTicks - pauseTicks;
+
+ bool haveTimerToSchedule = false;
+ uint nextAppDomainTimerDuration = uint.MaxValue;
+
+ TimerQueueTimer timer = m_timers;
+ while (timer != null)
+ {
+ Contract.Assert(timer.m_dueTime != Timeout.UnsignedInfinite);
+ Contract.Assert(resumedTicks >= timer.m_startTicks);
+
+ uint elapsed; // How much of the timer dueTime has already elapsed
+
+ // Timers started before the paused event has to be sufficiently delayed to accomodate
+ // for the Pause time. However, timers started after the Paused event shouldnt be adjusted.
+ // E.g. ones created by the app in its Activated event should fire when it was designated.
+ // The Resumed event which is where this routine is executing is after this Activated and hence
+ // shouldn't delay this timer
+
+ if(timer.m_startTicks <= pauseTicks)
+ elapsed = (uint)(pauseTicks - timer.m_startTicks);
+ else
+ elapsed = (uint)(resumedTicks - timer.m_startTicks);
+
+ // Handling the corner cases where a Timer was already due by the time Resume is happening,
+ // We shouldn't delay those timers.
+ // Example is a timer started in App's Activated event with a very small duration
+ timer.m_dueTime = (timer.m_dueTime > elapsed) ? timer.m_dueTime - elapsed : 0;;
+ timer.m_startTicks = resumedTicks; // re-baseline
+
+ if (timer.m_dueTime < nextAppDomainTimerDuration)
+ {
+ haveTimerToSchedule = true;
+ nextAppDomainTimerDuration = timer.m_dueTime;
+ }
+
+ timer = timer.m_next;
+ }
+
+ if (haveTimerToSchedule)
+ {
+ EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
+ }
+ }
+ }
+ }
+
+
+ //
+ // Fire any timers that have expired, and update the native timer to schedule the rest of them.
+ //
+ private void FireNextTimers()
+ {
+ //
+ // we fire the first timer on this thread; any other timers that might have fired are queued
+ // to the ThreadPool.
+ //
+ TimerQueueTimer timerToFireOnThisThread = null;
+
+ lock (this)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ //
+ // since we got here, that means our previous timer has fired.
+ //
+ m_isAppDomainTimerScheduled = false;
+ bool haveTimerToSchedule = false;
+ uint nextAppDomainTimerDuration = uint.MaxValue;
+
+ int nowTicks = TickCount;
+
+ //
+ // Sweep through all timers. The ones that have reached their due time
+ // will fire. We will calculate the next native timer due time from the
+ // other timers.
+ //
+ TimerQueueTimer timer = m_timers;
+ while (timer != null)
+ {
+ Contract.Assert(timer.m_dueTime != Timeout.UnsignedInfinite);
+
+ uint elapsed = (uint)(nowTicks - timer.m_startTicks);
+ if (elapsed >= timer.m_dueTime)
+ {
+ //
+ // Remember the next timer in case we delete this one
+ //
+ TimerQueueTimer nextTimer = timer.m_next;
+
+ if (timer.m_period != Timeout.UnsignedInfinite)
+ {
+ timer.m_startTicks = nowTicks;
+ timer.m_dueTime = timer.m_period;
+
+ //
+ // This is a repeating timer; schedule it to run again.
+ //
+ if (timer.m_dueTime < nextAppDomainTimerDuration)
+ {
+ haveTimerToSchedule = true;
+ nextAppDomainTimerDuration = timer.m_dueTime;
+ }
+ }
+ else
+ {
+ //
+ // Not repeating; remove it from the queue
+ //
+ DeleteTimer(timer);
+ }
+
+ //
+ // If this is the first timer, we'll fire it on this thread. Otherwise, queue it
+ // to the ThreadPool.
+ //
+ if (timerToFireOnThisThread == null)
+ timerToFireOnThisThread = timer;
+ else
+ QueueTimerCompletion(timer);
+
+ timer = nextTimer;
+ }
+ else
+ {
+ //
+ // This timer hasn't fired yet. Just update the next time the native timer fires.
+ //
+ uint remaining = timer.m_dueTime - elapsed;
+ if (remaining < nextAppDomainTimerDuration)
+ {
+ haveTimerToSchedule = true;
+ nextAppDomainTimerDuration = remaining;
+ }
+ timer = timer.m_next;
+ }
+ }
+
+ if (haveTimerToSchedule)
+ EnsureAppDomainTimerFiresBy(nextAppDomainTimerDuration);
+ }
+ }
+
+ //
+ // Fire the user timer outside of the lock!
+ //
+ if (timerToFireOnThisThread != null)
+ timerToFireOnThisThread.Fire();
+ }
+
+ [SecuritySafeCritical]
+ private static void QueueTimerCompletion(TimerQueueTimer timer)
+ {
+ WaitCallback callback = s_fireQueuedTimerCompletion;
+ if (callback == null)
+ s_fireQueuedTimerCompletion = callback = new WaitCallback(FireQueuedTimerCompletion);
+
+ // Can use "unsafe" variant because we take care of capturing and restoring
+ // the ExecutionContext.
+ ThreadPool.UnsafeQueueUserWorkItem(callback, timer);
+ }
+
+ private static WaitCallback s_fireQueuedTimerCompletion;
+
+ private static void FireQueuedTimerCompletion(object state)
+ {
+ ((TimerQueueTimer)state).Fire();
+ }
+
+ #endregion
+
+ #region Queue implementation
+
+ public bool UpdateTimer(TimerQueueTimer timer, uint dueTime, uint period)
+ {
+ if (timer.m_dueTime == Timeout.UnsignedInfinite)
+ {
+ // the timer is not in the list; add it (as the head of the list).
+ timer.m_next = m_timers;
+ timer.m_prev = null;
+ if (timer.m_next != null)
+ timer.m_next.m_prev = timer;
+ m_timers = timer;
+ }
+ timer.m_dueTime = dueTime;
+ timer.m_period = (period == 0) ? Timeout.UnsignedInfinite : period;
+ timer.m_startTicks = TickCount;
+ return EnsureAppDomainTimerFiresBy(dueTime);
+ }
+
+ public void DeleteTimer(TimerQueueTimer timer)
+ {
+ if (timer.m_dueTime != Timeout.UnsignedInfinite)
+ {
+ if (timer.m_next != null)
+ timer.m_next.m_prev = timer.m_prev;
+ if (timer.m_prev != null)
+ timer.m_prev.m_next = timer.m_next;
+ if (m_timers == timer)
+ m_timers = timer.m_next;
+
+ timer.m_dueTime = Timeout.UnsignedInfinite;
+ timer.m_period = Timeout.UnsignedInfinite;
+ timer.m_startTicks = 0;
+ timer.m_prev = null;
+ timer.m_next = null;
+ }
+ }
+
+ #endregion
+ }
+
+ //
+ // A timer in our TimerQueue.
+ //
+ sealed class TimerQueueTimer
+ {
+ //
+ // All fields of this class are protected by a lock on TimerQueue.Instance.
+ //
+ // The first four fields are maintained by TimerQueue itself.
+ //
+ internal TimerQueueTimer m_next;
+ internal TimerQueueTimer m_prev;
+
+ //
+ // The time, according to TimerQueue.TickCount, when this timer's current interval started.
+ //
+ internal int m_startTicks;
+
+ //
+ // Timeout.UnsignedInfinite if we are not going to fire. Otherwise, the offset from m_startTime when we will fire.
+ //
+ internal uint m_dueTime;
+
+ //
+ // Timeout.UnsignedInfinite if we are a single-shot timer. Otherwise, the repeat interval.
+ //
+ internal uint m_period;
+
+ //
+ // Info about the user's callback
+ //
+ readonly TimerCallback m_timerCallback;
+ readonly Object m_state;
+ readonly ExecutionContext m_executionContext;
+
+
+ //
+ // When Timer.Dispose(WaitHandle) is used, we need to signal the wait handle only
+ // after all pending callbacks are complete. We set m_canceled to prevent any callbacks that
+ // are already queued from running. We track the number of callbacks currently executing in
+ // m_callbacksRunning. We set m_notifyWhenNoCallbacksRunning only when m_callbacksRunning
+ // reaches zero.
+ //
+ int m_callbacksRunning;
+ volatile bool m_canceled;
+ volatile WaitHandle m_notifyWhenNoCallbacksRunning;
+
+
+ [SecurityCritical]
+ internal TimerQueueTimer(TimerCallback timerCallback, object state, uint dueTime, uint period, ref StackCrawlMark stackMark)
+ {
+ m_timerCallback = timerCallback;
+ m_state = state;
+ m_dueTime = Timeout.UnsignedInfinite;
+ m_period = Timeout.UnsignedInfinite;
+
+ if (!ExecutionContext.IsFlowSuppressed())
+ {
+ m_executionContext = ExecutionContext.Capture(
+ ref stackMark,
+ ExecutionContext.CaptureOptions.IgnoreSyncCtx | ExecutionContext.CaptureOptions.OptimizeDefaultCase);
+ }
+
+ //
+ // After the following statement, the timer may fire. No more manipulation of timer state outside of
+ // the lock is permitted beyond this point!
+ //
+ if (dueTime != Timeout.UnsignedInfinite)
+ Change(dueTime, period);
+ }
+
+
+ internal bool Change(uint dueTime, uint period)
+ {
+ bool success;
+
+ lock (TimerQueue.Instance)
+ {
+ if (m_canceled)
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic"));
+
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ m_period = period;
+
+ if (dueTime == Timeout.UnsignedInfinite)
+ {
+ TimerQueue.Instance.DeleteTimer(this);
+ success = true;
+ }
+ else
+ {
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer))
+ FrameworkEventSource.Log.ThreadTransferSendObj(this, 1, string.Empty, true);
+
+ success = TimerQueue.Instance.UpdateTimer(this, dueTime, period);
+ }
+ }
+ }
+
+ return success;
+ }
+
+
+ public void Close()
+ {
+ lock (TimerQueue.Instance)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ if (!m_canceled)
+ {
+ m_canceled = true;
+ TimerQueue.Instance.DeleteTimer(this);
+ }
+ }
+ }
+ }
+
+
+ public bool Close(WaitHandle toSignal)
+ {
+ bool success;
+ bool shouldSignal = false;
+
+ lock (TimerQueue.Instance)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ if (m_canceled)
+ {
+ success = false;
+ }
+ else
+ {
+ m_canceled = true;
+ m_notifyWhenNoCallbacksRunning = toSignal;
+ TimerQueue.Instance.DeleteTimer(this);
+
+ if (m_callbacksRunning == 0)
+ shouldSignal = true;
+
+ success = true;
+ }
+ }
+ }
+
+ if (shouldSignal)
+ SignalNoCallbacksRunning();
+
+ return success;
+ }
+
+
+ internal void Fire()
+ {
+ bool canceled = false;
+
+ lock (TimerQueue.Instance)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ canceled = m_canceled;
+ if (!canceled)
+ m_callbacksRunning++;
+ }
+ }
+
+ if (canceled)
+ return;
+
+ CallCallback();
+
+ bool shouldSignal = false;
+ lock (TimerQueue.Instance)
+ {
+ // prevent ThreadAbort while updating state
+ try { }
+ finally
+ {
+ m_callbacksRunning--;
+ if (m_canceled && m_callbacksRunning == 0 && m_notifyWhenNoCallbacksRunning != null)
+ shouldSignal = true;
+ }
+ }
+
+ if (shouldSignal)
+ SignalNoCallbacksRunning();
+ }
+
+ [SecuritySafeCritical]
+ internal void SignalNoCallbacksRunning()
+ {
+ Win32Native.SetEvent(m_notifyWhenNoCallbacksRunning.SafeWaitHandle);
+ }
+
+ [SecuritySafeCritical]
+ internal void CallCallback()
+ {
+ if (FrameworkEventSource.IsInitialized && FrameworkEventSource.Log.IsEnabled(EventLevel.Informational, FrameworkEventSource.Keywords.ThreadTransfer))
+ FrameworkEventSource.Log.ThreadTransferReceiveObj(this, 1, string.Empty);
+
+ // call directly if EC flow is suppressed
+ if (m_executionContext == null)
+ {
+ m_timerCallback(m_state);
+ }
+ else
+ {
+ using (ExecutionContext executionContext =
+ m_executionContext.IsPreAllocatedDefault ? m_executionContext : m_executionContext.CreateCopy())
+ {
+ ContextCallback callback = s_callCallbackInContext;
+ if (callback == null)
+ s_callCallbackInContext = callback = new ContextCallback(CallCallbackInContext);
+
+ ExecutionContext.Run(
+ executionContext,
+ callback,
+ this, // state
+ true); // ignoreSyncCtx
+ }
+ }
+ }
+
+ [SecurityCritical]
+ private static ContextCallback s_callCallbackInContext;
+
+ [SecurityCritical]
+ private static void CallCallbackInContext(object state)
+ {
+ TimerQueueTimer t = (TimerQueueTimer)state;
+ t.m_timerCallback(t.m_state);
+ }
+ }
+
+ //
+ // TimerHolder serves as an intermediary between Timer and TimerQueueTimer, releasing the TimerQueueTimer
+ // if the Timer is collected.
+ // This is necessary because Timer itself cannot use its finalizer for this purpose. If it did,
+ // then users could control timer lifetimes using GC.SuppressFinalize/ReRegisterForFinalize.
+ // You might ask, wouldn't that be a good thing? Maybe (though it would be even better to offer this
+ // via first-class APIs), but Timer has never offered this, and adding it now would be a breaking
+ // change, because any code that happened to be suppressing finalization of Timer objects would now
+ // unwittingly be changing the lifetime of those timers.
+ //
+ sealed class TimerHolder
+ {
+ internal TimerQueueTimer m_timer;
+
+ public TimerHolder(TimerQueueTimer timer)
+ {
+ m_timer = timer;
+ }
+
+ ~TimerHolder()
+ {
+ //
+ // If shutdown has started, another thread may be suspended while holding the timer lock.
+ // So we can't safely close the timer.
+ //
+ // Similarly, we should not close the timer during AD-unload's live-object finalization phase.
+ // A rude abort may have prevented us from releasing the lock.
+ //
+ // Note that in either case, the Timer still won't fire, because ThreadPool threads won't be
+ // allowed to run in this AppDomain.
+ //
+ if (Environment.HasShutdownStarted || AppDomain.CurrentDomain.IsFinalizingForUnload())
+ return;
+
+ m_timer.Close();
+ }
+
+ public void Close()
+ {
+ m_timer.Close();
+ GC.SuppressFinalize(this);
+ }
+
+ public bool Close(WaitHandle notifyObject)
+ {
+ bool result = m_timer.Close(notifyObject);
+ GC.SuppressFinalize(this);
+ return result;
+ }
+
+ }
+
+
+ [HostProtection(Synchronization=true, ExternalThreading=true)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_REMOTING
+ public sealed class Timer : MarshalByRefObject, IDisposable
+#else // FEATURE_REMOTING
+ public sealed class Timer : IDisposable
+#endif // FEATURE_REMOTING
+ {
+ private const UInt32 MAX_SUPPORTED_TIMEOUT = (uint)0xfffffffe;
+
+ private TimerHolder m_timer;
+
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Timer(TimerCallback callback,
+ Object state,
+ int dueTime,
+ int period)
+ {
+ if (dueTime < -1)
+ throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (period < -1 )
+ throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+
+ TimerSetup(callback,state,(UInt32)dueTime,(UInt32)period,ref stackMark);
+ }
+
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Timer(TimerCallback callback,
+ Object state,
+ TimeSpan dueTime,
+ TimeSpan period)
+ {
+ long dueTm = (long)dueTime.TotalMilliseconds;
+ if (dueTm < -1)
+ throw new ArgumentOutOfRangeException("dueTm",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (dueTm > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("dueTm",Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge"));
+
+ long periodTm = (long)period.TotalMilliseconds;
+ if (periodTm < -1)
+ throw new ArgumentOutOfRangeException("periodTm",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (periodTm > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("periodTm",Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge"));
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ TimerSetup(callback,state,(UInt32)dueTm,(UInt32)periodTm,ref stackMark);
+ }
+
+ [CLSCompliant(false)]
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Timer(TimerCallback callback,
+ Object state,
+ UInt32 dueTime,
+ UInt32 period)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ TimerSetup(callback,state,dueTime,period,ref stackMark);
+ }
+
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Timer(TimerCallback callback,
+ Object state,
+ long dueTime,
+ long period)
+ {
+ if (dueTime < -1)
+ throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (period < -1)
+ throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (dueTime > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge"));
+ if (period > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge"));
+ Contract.EndContractBlock();
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ TimerSetup(callback,state,(UInt32) dueTime, (UInt32) period,ref stackMark);
+ }
+
+ [SecuritySafeCritical]
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public Timer(TimerCallback callback)
+ {
+ int dueTime = -1; // we want timer to be registered, but not activated. Requires caller to call
+ int period = -1; // Change after a timer instance is created. This is to avoid the potential
+ // for a timer to be fired before the returned value is assigned to the variable,
+ // potentially causing the callback to reference a bogus value (if passing the timer to the callback).
+
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ TimerSetup(callback, this, (UInt32)dueTime, (UInt32)period, ref stackMark);
+ }
+
+ [SecurityCritical]
+ private void TimerSetup(TimerCallback callback,
+ Object state,
+ UInt32 dueTime,
+ UInt32 period,
+ ref StackCrawlMark stackMark)
+ {
+ if (callback == null)
+ throw new ArgumentNullException("TimerCallback");
+ Contract.EndContractBlock();
+
+ m_timer = new TimerHolder(new TimerQueueTimer(callback, state, dueTime, period, ref stackMark));
+ }
+
+ [SecurityCritical]
+ internal static void Pause()
+ {
+ TimerQueue.Instance.Pause();
+ }
+
+ [SecurityCritical]
+ internal static void Resume()
+ {
+ TimerQueue.Instance.Resume();
+ }
+
+ public bool Change(int dueTime, int period)
+ {
+ if (dueTime < -1 )
+ throw new ArgumentOutOfRangeException("dueTime",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (period < -1)
+ throw new ArgumentOutOfRangeException("period",Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ Contract.EndContractBlock();
+
+ return m_timer.m_timer.Change((UInt32)dueTime, (UInt32)period);
+ }
+
+ public bool Change(TimeSpan dueTime, TimeSpan period)
+ {
+ return Change((long) dueTime.TotalMilliseconds, (long) period.TotalMilliseconds);
+ }
+
+ [CLSCompliant(false)]
+ public bool Change(UInt32 dueTime, UInt32 period)
+ {
+ return m_timer.m_timer.Change(dueTime, period);
+ }
+
+ public bool Change(long dueTime, long period)
+ {
+ if (dueTime < -1 )
+ throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (period < -1)
+ throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ if (dueTime > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("dueTime", Environment.GetResourceString("ArgumentOutOfRange_TimeoutTooLarge"));
+ if (period > MAX_SUPPORTED_TIMEOUT)
+ throw new ArgumentOutOfRangeException("period", Environment.GetResourceString("ArgumentOutOfRange_PeriodTooLarge"));
+ Contract.EndContractBlock();
+
+ return m_timer.m_timer.Change((UInt32)dueTime, (UInt32)period);
+ }
+
+ public bool Dispose(WaitHandle notifyObject)
+ {
+ if (notifyObject==null)
+ throw new ArgumentNullException("notifyObject");
+ Contract.EndContractBlock();
+
+ return m_timer.Close(notifyObject);
+ }
+
+ public void Dispose()
+ {
+ m_timer.Close();
+ }
+
+ internal void KeepRootedWhileScheduled()
+ {
+ GC.SuppressFinalize(m_timer);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/Volatile.cs b/src/mscorlib/src/System/Threading/Volatile.cs
new file mode 100644
index 0000000000..af687fbae1
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/Volatile.cs
@@ -0,0 +1,441 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.Versioning;
+using System.Runtime.ConstrainedExecution;
+using System.Runtime.CompilerServices;
+using System.Runtime;
+using System.Security;
+
+namespace System.Threading
+{
+ //
+ // Methods for accessing memory with volatile semantics. These are preferred over Thread.VolatileRead
+ // and Thread.VolatileWrite, as these are implemented more efficiently.
+ //
+ // (We cannot change the implementations of Thread.VolatileRead/VolatileWrite without breaking code
+ // that relies on their overly-strong ordering guarantees.)
+ //
+ // The actual implementations of these methods are typically supplied by the VM at JIT-time, because C# does
+ // not allow us to express a volatile read/write from/to a byref arg.
+ // See getILIntrinsicImplementationForVolatile() in jitinterface.cpp.
+ //
+ public static class Volatile
+ {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static bool Read(ref bool location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static sbyte Read(ref sbyte location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static byte Read(ref byte location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static short Read(ref short location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static ushort Read(ref ushort location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static int Read(ref int location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static uint Read(ref uint location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+#if BIT64
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static long Read(ref long location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ [SecuritySafeCritical] // to match 32-bit version
+ public static ulong Read(ref ulong location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+#else
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static long Read(ref long location)
+ {
+ //
+ // On 32-bit machines, we use this implementation, since an ordinary volatile read
+ // would not be atomic.
+ //
+ // On 64-bit machines, the VM will replace this with a more efficient implementation.
+ //
+ return Interlocked.CompareExchange(ref location, 0, 0);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [SecuritySafeCritical] // contains unsafe code
+ public static ulong Read(ref ulong location)
+ {
+ unsafe
+ {
+ //
+ // There is no overload of Interlocked.Exchange that accepts a ulong. So we have
+ // to do some pointer tricks to pass our arguments to the overload that takes a long.
+ //
+ fixed (ulong* pLocation = &location)
+ {
+ return (ulong)Interlocked.CompareExchange(ref *(long*)pLocation, 0, 0);
+ }
+ }
+ }
+#endif
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static IntPtr Read(ref IntPtr location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static UIntPtr Read(ref UIntPtr location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static float Read(ref float location)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static double Read(ref double location)
+ {
+ //
+ // On 32-bit machines, we use this implementation, since an ordinary volatile read
+ // would not be atomic.
+ //
+ // On 64-bit machines, the VM will replace this with a more efficient implementation.
+ //
+ return Interlocked.CompareExchange(ref location, 0, 0);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical] //the intrinsic implementation of this method contains unverifiable code
+ [System.Runtime.Versioning.NonVersionable]
+ public static T Read<T>(ref T location) where T : class
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ var value = location;
+ Thread.MemoryBarrier();
+ return value;
+ }
+
+
+
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref bool location, bool value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref sbyte location, sbyte value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref byte location, byte value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref short location, short value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref ushort location, ushort value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref int location, int value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref uint location, uint value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+#if BIT64
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref long location, long value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ [SecuritySafeCritical] // to match 32-bit version
+ public static void Write(ref ulong location, ulong value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+#else
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ public static void Write(ref long location, long value)
+ {
+ //
+ // On 32-bit machines, we use this implementation, since an ordinary volatile write
+ // would not be atomic.
+ //
+ // On 64-bit machines, the VM will replace this with a more efficient implementation.
+ //
+ Interlocked.Exchange(ref location, value);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [SecuritySafeCritical] // contains unsafe code
+ public static void Write(ref ulong location, ulong value)
+ {
+ //
+ // On 32-bit machines, we use this implementation, since an ordinary volatile write
+ // would not be atomic.
+ //
+ // On 64-bit machines, the VM will replace this with a more efficient implementation.
+ //
+ unsafe
+ {
+ //
+ // There is no overload of Interlocked.Exchange that accepts a ulong. So we have
+ // to do some pointer tricks to pass our arguments to the overload that takes a long.
+ //
+ fixed (ulong* pLocation = &location)
+ {
+ Interlocked.Exchange(ref *(long*)pLocation, (long)value);
+ }
+ }
+ }
+#endif
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref IntPtr location, IntPtr value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref UIntPtr location, UIntPtr value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref float location, float value)
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write(ref double location, double value)
+ {
+ //
+ // On 32-bit machines, we use this implementation, since an ordinary volatile write
+ // would not be atomic.
+ //
+ // On 64-bit machines, the VM will replace this with a more efficient implementation.
+ //
+ Interlocked.Exchange(ref location, value);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SecuritySafeCritical] //the intrinsic implementation of this method contains unverifiable code
+ [System.Runtime.Versioning.NonVersionable]
+ public static void Write<T>(ref T location, T value) where T : class
+ {
+ //
+ // The VM will replace this with a more efficient implementation.
+ //
+ Thread.MemoryBarrier();
+ location = value;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/WaitHandle.cs b/src/mscorlib/src/System/Threading/WaitHandle.cs
new file mode 100644
index 0000000000..9980c822a6
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/WaitHandle.cs
@@ -0,0 +1,617 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+/*=============================================================================
+**
+**
+**
+** Purpose: Class to represent all synchronization objects in the runtime (that allow multiple wait)
+**
+**
+=============================================================================*/
+
+namespace System.Threading
+{
+ using System.Threading;
+ using System.Runtime.Remoting;
+ using System;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using Microsoft.Win32.SafeHandles;
+ using System.Runtime.Versioning;
+ using System.Runtime.ConstrainedExecution;
+ using System.Diagnostics.Contracts;
+ using System.Diagnostics.CodeAnalysis;
+ using Win32Native = Microsoft.Win32.Win32Native;
+
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_REMOTING
+ public abstract class WaitHandle : MarshalByRefObject, IDisposable {
+#else // FEATURE_REMOTING
+ public abstract class WaitHandle : IDisposable {
+#endif // FEATURE_REMOTING
+ public const int WaitTimeout = 0x102;
+
+ private const int MAX_WAITHANDLES = 64;
+
+#pragma warning disable 414 // Field is not used from managed.
+ private IntPtr waitHandle; // !!! DO NOT MOVE THIS FIELD. (See defn of WAITHANDLEREF in object.h - has hardcoded access to this field.)
+#pragma warning restore 414
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal volatile SafeWaitHandle safeWaitHandle;
+
+ internal bool hasThreadAffinity;
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private static IntPtr GetInvalidHandle()
+ {
+ return Win32Native.INVALID_HANDLE_VALUE;
+ }
+ protected static readonly IntPtr InvalidHandle = GetInvalidHandle();
+ private const int WAIT_OBJECT_0 = 0;
+ private const int WAIT_ABANDONED = 0x80;
+ private const int WAIT_FAILED = 0x7FFFFFFF;
+ private const int ERROR_TOO_MANY_POSTS = 0x12A;
+
+ internal enum OpenExistingResult
+ {
+ Success,
+ NameNotFound,
+ PathNotFound,
+ NameInvalid
+ }
+
+ protected WaitHandle()
+ {
+ Init();
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private void Init()
+ {
+ safeWaitHandle = null;
+ waitHandle = InvalidHandle;
+ hasThreadAffinity = false;
+ }
+
+
+ [Obsolete("Use the SafeWaitHandle property instead.")]
+ public virtual IntPtr Handle
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get { return safeWaitHandle == null ? InvalidHandle : safeWaitHandle.DangerousGetHandle();}
+
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#endif
+ set
+ {
+ if (value == InvalidHandle)
+ {
+ // This line leaks a handle. However, it's currently
+ // not perfectly clear what the right behavior is here
+ // anyways. This preserves Everett behavior. We should
+ // ideally do these things:
+ // *) Expose a settable SafeHandle property on WaitHandle.
+ // *) Expose a settable OwnsHandle property on SafeHandle.
+ if (safeWaitHandle != null)
+ {
+ safeWaitHandle.SetHandleAsInvalid();
+ safeWaitHandle = null;
+ }
+ }
+ else
+ {
+ safeWaitHandle = new SafeWaitHandle(value, true);
+ }
+ waitHandle = value;
+ }
+ }
+
+
+ public SafeWaitHandle SafeWaitHandle
+ {
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#endif
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ get
+ {
+ if (safeWaitHandle == null)
+ {
+ safeWaitHandle = new SafeWaitHandle(InvalidHandle, false);
+ }
+ return safeWaitHandle;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)]
+#endif
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ set
+ {
+ // Set safeWaitHandle and waitHandle in a CER so we won't take
+ // a thread abort between the statements and leave the wait
+ // handle in an invalid state. Note this routine is not thread
+ // safe however.
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try { }
+ finally
+ {
+ if (value == null)
+ {
+ safeWaitHandle = null;
+ waitHandle = InvalidHandle;
+ }
+ else
+ {
+ safeWaitHandle = value;
+ waitHandle = safeWaitHandle.DangerousGetHandle();
+ }
+ }
+ }
+ }
+
+ // Assembly-private version that doesn't do a security check. Reduces the
+ // number of link-time security checks when reading & writing to a file,
+ // and helps avoid a link time check while initializing security (If you
+ // call a Serialization method that requires security before security
+ // has started up, the link time check will start up security, run
+ // serialization code for some security attribute stuff, call into
+ // FileStream, which will then call Sethandle, which requires a link time
+ // security check.). While security has fixed that problem, we still
+ // don't need to do a linktime check here.
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetHandleInternal(SafeWaitHandle handle)
+ {
+ safeWaitHandle = handle;
+ waitHandle = handle.DangerousGetHandle();
+ }
+
+ public virtual bool WaitOne (int millisecondsTimeout, bool exitContext)
+ {
+ if (millisecondsTimeout < -1)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ Contract.EndContractBlock();
+ return WaitOne((long)millisecondsTimeout,exitContext);
+ }
+
+ public virtual bool WaitOne (TimeSpan timeout, bool exitContext)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (-1 > tm || (long) Int32.MaxValue < tm)
+ {
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ return WaitOne(tm,exitContext);
+ }
+
+ public virtual bool WaitOne ()
+ {
+ //Infinite Timeout
+ return WaitOne(-1,false);
+ }
+
+ public virtual bool WaitOne(int millisecondsTimeout)
+ {
+ return WaitOne(millisecondsTimeout, false);
+ }
+
+ public virtual bool WaitOne(TimeSpan timeout)
+ {
+ return WaitOne(timeout, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")]
+ private bool WaitOne(long timeout, bool exitContext)
+ {
+ return InternalWaitOne(safeWaitHandle, timeout, hasThreadAffinity, exitContext);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal static bool InternalWaitOne(SafeHandle waitableSafeHandle, long millisecondsTimeout, bool hasThreadAffinity, bool exitContext)
+ {
+ if (waitableSafeHandle == null)
+ {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic"));
+ }
+ Contract.EndContractBlock();
+ int ret = WaitOneNative(waitableSafeHandle, (uint)millisecondsTimeout, hasThreadAffinity, exitContext);
+
+ if(AppDomainPauseManager.IsPaused)
+ AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
+
+ if (ret == WAIT_ABANDONED)
+ {
+ ThrowAbandonedMutexException();
+ }
+ return (ret != WaitTimeout);
+ }
+
+ [System.Security.SecurityCritical]
+ internal bool WaitOneWithoutFAS()
+ {
+ // version of waitone without fast application switch (FAS) support
+ // This is required to support the Wait which FAS needs (otherwise recursive dependency comes in)
+ if (safeWaitHandle == null)
+ {
+ throw new ObjectDisposedException(null, Environment.GetResourceString("ObjectDisposed_Generic"));
+ }
+ Contract.EndContractBlock();
+
+ long timeout = -1;
+ int ret = WaitOneNative(safeWaitHandle, (uint)timeout, hasThreadAffinity, false);
+ if (ret == WAIT_ABANDONED)
+ {
+ ThrowAbandonedMutexException();
+ }
+ return (ret != WaitTimeout);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int WaitOneNative(SafeHandle waitableSafeHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext);
+
+ /*========================================================================
+ ** Waits for signal from all the objects.
+ ** timeout indicates how long to wait before the method returns.
+ ** This method will return either when all the object have been pulsed
+ ** or timeout milliseonds have elapsed.
+ ** If exitContext is true then the synchronization domain for the context
+ ** (if in a synchronized context) is exited before the wait and reacquired
+ ========================================================================*/
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ private static extern int WaitMultiple(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext, bool WaitAll);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
+ {
+ if (waitHandles == null)
+ {
+ throw new ArgumentNullException("waitHandles", Environment.GetResourceString("ArgumentNull_Waithandles"));
+ }
+ if(waitHandles.Length == 0)
+ {
+ //
+ // Some history: in CLR 1.0 and 1.1, we threw ArgumentException in this case, which was correct.
+ // Somehow, in 2.0, this became ArgumentNullException. This was not fixed until Silverlight 2,
+ // which went back to ArgumentException.
+ //
+ // Now we're in a bit of a bind. Backward-compatibility requires us to keep throwing ArgumentException
+ // in CoreCLR, and ArgumentNullException in the desktop CLR. This is ugly, but so is breaking
+ // user code.
+ //
+#if FEATURE_CORECLR
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyWaithandleArray"));
+#else
+ throw new ArgumentNullException("waitHandles", Environment.GetResourceString("Argument_EmptyWaithandleArray"));
+#endif
+ }
+ if (waitHandles.Length > MAX_WAITHANDLES)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_MaxWaitHandles"));
+ }
+ if (-1 > millisecondsTimeout)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ Contract.EndContractBlock();
+ WaitHandle[] internalWaitHandles = new WaitHandle[waitHandles.Length];
+ for (int i = 0; i < waitHandles.Length; i ++)
+ {
+ WaitHandle waitHandle = waitHandles[i];
+
+ if (waitHandle == null)
+ throw new ArgumentNullException("waitHandles[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayElement"));
+
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(waitHandle))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy"));
+#endif
+
+ internalWaitHandles[i] = waitHandle;
+ }
+#if _DEBUG
+ // make sure we do not use waitHandles any more.
+ waitHandles = null;
+#endif
+
+ int ret = WaitMultiple(internalWaitHandles, millisecondsTimeout, exitContext, true /* waitall*/ );
+
+ if(AppDomainPauseManager.IsPaused)
+ AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
+
+ if ((WAIT_ABANDONED <= ret) && (WAIT_ABANDONED+internalWaitHandles.Length > ret))
+ {
+ //In the case of WaitAll the OS will only provide the
+ // information that mutex was abandoned.
+ // It won't tell us which one. So we can't set the Index or provide access to the Mutex
+ ThrowAbandonedMutexException();
+ }
+
+ GC.KeepAlive(internalWaitHandles);
+ return (ret != WaitTimeout);
+ }
+
+ public static bool WaitAll(
+ WaitHandle[] waitHandles,
+ TimeSpan timeout,
+ bool exitContext)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (-1 > tm || (long) Int32.MaxValue < tm)
+ {
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ return WaitAll(waitHandles,(int)tm, exitContext);
+ }
+
+
+ /*========================================================================
+ ** Shorthand for WaitAll with timeout = Timeout.Infinite and exitContext = true
+ ========================================================================*/
+ public static bool WaitAll(WaitHandle[] waitHandles)
+ {
+ return WaitAll(waitHandles, Timeout.Infinite, true);
+ }
+
+ public static bool WaitAll(WaitHandle[] waitHandles, int millisecondsTimeout)
+ {
+ return WaitAll(waitHandles, millisecondsTimeout, true);
+ }
+
+ public static bool WaitAll(WaitHandle[] waitHandles, TimeSpan timeout)
+ {
+ return WaitAll(waitHandles, timeout, true);
+ }
+
+
+ /*========================================================================
+ ** Waits for notification from any of the objects.
+ ** timeout indicates how long to wait before the method returns.
+ ** This method will return either when either one of the object have been
+ ** signalled or timeout milliseonds have elapsed.
+ ** If exitContext is true then the synchronization domain for the context
+ ** (if in a synchronized context) is exited before the wait and reacquired
+ ========================================================================*/
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext)
+ {
+ if (waitHandles==null)
+ {
+ throw new ArgumentNullException("waitHandles", Environment.GetResourceString("ArgumentNull_Waithandles"));
+ }
+ if(waitHandles.Length == 0)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_EmptyWaithandleArray"));
+ }
+ if (MAX_WAITHANDLES < waitHandles.Length)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_MaxWaitHandles"));
+ }
+ if (-1 > millisecondsTimeout)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ Contract.EndContractBlock();
+ WaitHandle[] internalWaitHandles = new WaitHandle[waitHandles.Length];
+ for (int i = 0; i < waitHandles.Length; i ++)
+ {
+ WaitHandle waitHandle = waitHandles[i];
+
+ if (waitHandle == null)
+ throw new ArgumentNullException("waitHandles[" + i + "]", Environment.GetResourceString("ArgumentNull_ArrayElement"));
+
+#if FEATURE_REMOTING
+ if (RemotingServices.IsTransparentProxy(waitHandle))
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_WaitOnTransparentProxy"));
+#endif
+
+ internalWaitHandles[i] = waitHandle;
+ }
+#if _DEBUG
+ // make sure we do not use waitHandles any more.
+ waitHandles = null;
+#endif
+ int ret = WaitMultiple(internalWaitHandles, millisecondsTimeout, exitContext, false /* waitany*/ );
+
+ if(AppDomainPauseManager.IsPaused)
+ AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
+
+ if ((WAIT_ABANDONED <= ret) && (WAIT_ABANDONED+internalWaitHandles.Length > ret))
+ {
+ int mutexIndex = ret -WAIT_ABANDONED;
+ if(0 <= mutexIndex && mutexIndex < internalWaitHandles.Length)
+ {
+ ThrowAbandonedMutexException(mutexIndex,internalWaitHandles[mutexIndex]);
+ }
+ else
+ {
+ ThrowAbandonedMutexException();
+ }
+ }
+
+ GC.KeepAlive(internalWaitHandles);
+ return ret;
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int WaitAny(
+ WaitHandle[] waitHandles,
+ TimeSpan timeout,
+ bool exitContext)
+ {
+ long tm = (long)timeout.TotalMilliseconds;
+ if (-1 > tm || (long) Int32.MaxValue < tm)
+ {
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ return WaitAny(waitHandles,(int)tm, exitContext);
+ }
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int WaitAny(WaitHandle[] waitHandles, TimeSpan timeout)
+ {
+ return WaitAny(waitHandles, timeout, true);
+ }
+
+
+ /*========================================================================
+ ** Shorthand for WaitAny with timeout = Timeout.Infinite and exitContext = true
+ ========================================================================*/
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int WaitAny(WaitHandle[] waitHandles)
+ {
+ return WaitAny(waitHandles, Timeout.Infinite, true);
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
+ public static int WaitAny(WaitHandle[] waitHandles, int millisecondsTimeout)
+ {
+ return WaitAny(waitHandles, millisecondsTimeout, true);
+ }
+
+ /*=================================================
+ ==
+ == SignalAndWait
+ ==
+ ==================================================*/
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern int SignalAndWaitOne(SafeWaitHandle waitHandleToSignal,SafeWaitHandle waitHandleToWaitOn, int millisecondsTimeout,
+ bool hasThreadAffinity, bool exitContext);
+
+ public static bool SignalAndWait(
+ WaitHandle toSignal,
+ WaitHandle toWaitOn)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException();
+#else
+ return SignalAndWait(toSignal,toWaitOn,-1,false);
+#endif
+ }
+
+ public static bool SignalAndWait(
+ WaitHandle toSignal,
+ WaitHandle toWaitOn,
+ TimeSpan timeout,
+ bool exitContext)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException();
+#else
+ long tm = (long)timeout.TotalMilliseconds;
+ if (-1 > tm || (long) Int32.MaxValue < tm)
+ {
+ throw new ArgumentOutOfRangeException("timeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ return SignalAndWait(toSignal,toWaitOn,(int)tm,exitContext);
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "Reviewed for thread-safety.")]
+ public static bool SignalAndWait(
+ WaitHandle toSignal,
+ WaitHandle toWaitOn,
+ int millisecondsTimeout,
+ bool exitContext)
+ {
+#if PLATFORM_UNIX
+ throw new PlatformNotSupportedException();
+#else
+ if(null == toSignal)
+ {
+ throw new ArgumentNullException("toSignal");
+ }
+ if(null == toWaitOn)
+ {
+ throw new ArgumentNullException("toWaitOn");
+ }
+ if (-1 > millisecondsTimeout)
+ {
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+ }
+ Contract.EndContractBlock();
+
+ //NOTE: This API is not supporting Pause/Resume as it's not exposed in CoreCLR (not in WP or SL)
+ int ret = SignalAndWaitOne(toSignal.safeWaitHandle,toWaitOn.safeWaitHandle,millisecondsTimeout,
+ toWaitOn.hasThreadAffinity,exitContext);
+
+#if !FEATURE_CORECLR
+ if(WAIT_FAILED != ret && toSignal.hasThreadAffinity)
+ {
+ Thread.EndCriticalRegion();
+ Thread.EndThreadAffinity();
+ }
+#endif
+
+ if(WAIT_ABANDONED == ret)
+ {
+ ThrowAbandonedMutexException();
+ }
+
+ if(ERROR_TOO_MANY_POSTS == ret)
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("Threading.WaitHandleTooManyPosts"));
+ }
+
+ //Object was signaled
+ if(WAIT_OBJECT_0 == ret)
+ {
+ return true;
+ }
+
+ //Timeout
+ return false;
+#endif
+ }
+
+ private static void ThrowAbandonedMutexException()
+ {
+ throw new AbandonedMutexException();
+ }
+
+ private static void ThrowAbandonedMutexException(int location, WaitHandle handle)
+ {
+ throw new AbandonedMutexException(location, handle);
+ }
+
+ public virtual void Close()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ protected virtual void Dispose(bool explicitDisposing)
+ {
+ if (safeWaitHandle != null)
+ {
+ safeWaitHandle.Close();
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs
new file mode 100644
index 0000000000..f873057992
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/WaitHandleCannotBeOpenedException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+namespace System.Threading
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Runtime.InteropServices;
+
+ [Serializable]
+ [ComVisibleAttribute(false)]
+
+#if FEATURE_CORECLR
+ public class WaitHandleCannotBeOpenedException : Exception {
+#else
+ public class WaitHandleCannotBeOpenedException : ApplicationException {
+#endif // FEATURE_CORECLR
+ public WaitHandleCannotBeOpenedException() : base(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException"))
+ {
+ SetErrorCode(__HResults.COR_E_WAITHANDLECANNOTBEOPENED);
+ }
+
+ public WaitHandleCannotBeOpenedException(String message) : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_WAITHANDLECANNOTBEOPENED);
+ }
+
+ public WaitHandleCannotBeOpenedException(String message, Exception innerException) : base(message, innerException)
+ {
+ SetErrorCode(__HResults.COR_E_WAITHANDLECANNOTBEOPENED);
+ }
+
+ protected WaitHandleCannotBeOpenedException(SerializationInfo info, StreamingContext context) : base (info, context)
+ {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs b/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs
new file mode 100644
index 0000000000..76c3feb649
--- /dev/null
+++ b/src/mscorlib/src/System/Threading/WaitHandleExtensions.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+
+using Microsoft.Win32.SafeHandles;
+using System.Security;
+
+namespace System.Threading
+{
+ public static class WaitHandleExtensions
+ {
+ /// <summary>
+ /// Gets the native operating system handle.
+ /// </summary>
+ /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
+ /// <returns>A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</returns>
+ [SecurityCritical]
+ public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle)
+ {
+ if (waitHandle == null)
+ {
+ throw new ArgumentNullException("waitHandle");
+ }
+
+ return waitHandle.SafeWaitHandle;
+ }
+
+ /// <summary>
+ /// Sets the native operating system handle
+ /// </summary>
+ /// <param name="waitHandle">The <see cref="System.Threading.WaitHandle"/> to operate on.</param>
+ /// <param name="value">A <see cref="System.Runtime.InteropServices.SafeHandle"/> representing the native operating system handle.</param>
+ [SecurityCritical]
+ public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle value)
+ {
+ if (waitHandle == null)
+ {
+ throw new ArgumentNullException("waitHandle");
+ }
+
+ waitHandle.SafeWaitHandle = value;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/ThrowHelper.cs b/src/mscorlib/src/System/ThrowHelper.cs
new file mode 100644
index 0000000000..3105d56f7c
--- /dev/null
+++ b/src/mscorlib/src/System/ThrowHelper.cs
@@ -0,0 +1,347 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+namespace System {
+ // This file defines an internal class used to throw exceptions in BCL code.
+ // The main purpose is to reduce code size.
+ //
+ // The old way to throw an exception generates quite a lot IL code and assembly code.
+ // Following is an example:
+ // C# source
+ // throw new ArgumentNullException("key", Environment.GetResourceString("ArgumentNull_Key"));
+ // IL code:
+ // IL_0003: ldstr "key"
+ // IL_0008: ldstr "ArgumentNull_Key"
+ // IL_000d: call string System.Environment::GetResourceString(string)
+ // IL_0012: newobj instance void System.ArgumentNullException::.ctor(string,string)
+ // IL_0017: throw
+ // which is 21bytes in IL.
+ //
+ // So we want to get rid of the ldstr and call to Environment.GetResource in IL.
+ // In order to do that, I created two enums: ExceptionResource, ExceptionArgument to represent the
+ // argument name and resource name in a small integer. The source code will be changed to
+ // ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key, ExceptionResource.ArgumentNull_Key);
+ //
+ // The IL code will be 7 bytes.
+ // IL_0008: ldc.i4.4
+ // IL_0009: ldc.i4.4
+ // IL_000a: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)
+ // IL_000f: ldarg.0
+ //
+ // This will also reduce the Jitted code size a lot.
+ //
+ // It is very important we do this for generic classes because we can easily generate the same code
+ // multiple times for different instantiation.
+ //
+
+ using Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Serialization;
+ using System.Diagnostics.Contracts;
+
+ [Pure]
+ internal static class ThrowHelper {
+ internal static void ThrowArgumentOutOfRange_IndexException() {
+ throw new ArgumentOutOfRangeException(GetArgumentName(ExceptionArgument.index),
+ Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_Index)));
+ }
+
+ internal static void ThrowIndexArgumentOutOfRange_NeedNonNegNumException() {
+ throw new ArgumentOutOfRangeException(
+ GetArgumentName(ExceptionArgument.index),
+ Environment.GetResourceString(GetResourceName(ExceptionResource.ArgumentOutOfRange_NeedNonNegNum)));
+ }
+
+ internal static void ThrowWrongKeyTypeArgumentException(object key, Type targetType) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", key, targetType), "key");
+ }
+
+ internal static void ThrowWrongValueTypeArgumentException(object value, Type targetType) {
+ throw new ArgumentException(Environment.GetResourceString("Arg_WrongType", value, targetType), "value");
+ }
+
+#if FEATURE_CORECLR
+ internal static void ThrowAddingDuplicateWithKeyArgumentException(object key) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_AddingDuplicateWithKey", key));
+ }
+#endif
+
+ internal static void ThrowKeyNotFoundException() {
+ throw new System.Collections.Generic.KeyNotFoundException();
+ }
+
+ internal static void ThrowArgumentException(ExceptionResource resource) {
+ throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowArgumentException(ExceptionResource resource, ExceptionArgument argument) {
+ throw new ArgumentException(Environment.GetResourceString(GetResourceName(resource)), GetArgumentName(argument));
+ }
+
+ internal static void ThrowArgumentNullException(ExceptionArgument argument) {
+ throw new ArgumentNullException(GetArgumentName(argument));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument) {
+ throw new ArgumentOutOfRangeException(GetArgumentName(argument));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource) {
+ throw new ArgumentOutOfRangeException(GetArgumentName(argument),
+ Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowArgumentOutOfRangeException(ExceptionArgument argument, int paramNumber, ExceptionResource resource) {
+ throw new ArgumentOutOfRangeException(GetArgumentName(argument) + "[" + paramNumber.ToString() + "]",
+ Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowInvalidOperationException(ExceptionResource resource) {
+ throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowInvalidOperationException(ExceptionResource resource, Exception e) {
+ throw new InvalidOperationException(Environment.GetResourceString(GetResourceName(resource)), e);
+ }
+
+ internal static void ThrowSerializationException(ExceptionResource resource) {
+ throw new SerializationException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowSecurityException(ExceptionResource resource) {
+ throw new System.Security.SecurityException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowRankException(ExceptionResource resource) {
+ throw new RankException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowNotSupportedException(ExceptionResource resource) {
+ throw new NotSupportedException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowUnauthorizedAccessException(ExceptionResource resource) {
+ throw new UnauthorizedAccessException(Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowObjectDisposedException(string objectName, ExceptionResource resource) {
+ throw new ObjectDisposedException(objectName, Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowObjectDisposedException(ExceptionResource resource)
+ {
+ throw new ObjectDisposedException(null, Environment.GetResourceString(GetResourceName(resource)));
+ }
+
+ internal static void ThrowNotSupportedException()
+ {
+ throw new NotSupportedException();
+ }
+
+ internal static void ThrowAggregateException(List<Exception> exceptions)
+ {
+ throw new AggregateException(exceptions);
+ }
+
+ // Allow nulls for reference types and Nullable<U>, but not for value types.
+ // Aggressively inline so the jit evaluates the if in place and either drops the call altogether
+ // Or just leaves null test and call to the Non-returning ThrowHelper.ThrowArgumentNullException
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static void IfNullAndNullsAreIllegalThenThrow<T>(object value, ExceptionArgument argName) {
+ // Note that default(T) is not equal to null for value types except when T is Nullable<U>.
+ if (!(default(T) == null) && value == null)
+ ThrowHelper.ThrowArgumentNullException(argName);
+ }
+
+ //
+ // This function will convert an ExceptionArgument enum value to the argument name string.
+ //
+ internal static string GetArgumentName(ExceptionArgument argument) {
+ Contract.Assert(Enum.IsDefined(typeof(ExceptionArgument), argument),
+ "The enum value is not defined, please check the ExceptionArgument Enum.");
+
+ return argument.ToString();
+ }
+
+ //
+ // This function will convert an ExceptionResource enum value to the resource string.
+ //
+ internal static string GetResourceName(ExceptionResource resource) {
+ Contract.Assert(Enum.IsDefined(typeof(ExceptionResource), resource),
+ "The enum value is not defined, please check the ExceptionResource Enum.");
+
+ return resource.ToString();
+ }
+
+ }
+
+ //
+ // The convention for this enum is using the argument name as the enum name
+ //
+ internal enum ExceptionArgument {
+ obj,
+ dictionary,
+ dictionaryCreationThreshold,
+ array,
+ info,
+ key,
+ collection,
+ list,
+ match,
+ converter,
+ queue,
+ stack,
+ capacity,
+ index,
+ startIndex,
+ value,
+ count,
+ arrayIndex,
+ name,
+ mode,
+ item,
+ options,
+ view,
+ sourceBytesToCopy,
+ action,
+ comparison,
+ offset,
+ newSize,
+ elementType,
+ length,
+ length1,
+ length2,
+ length3,
+ lengths,
+ len,
+ lowerBounds,
+ sourceArray,
+ destinationArray,
+ sourceIndex,
+ destinationIndex,
+ indices,
+ index1,
+ index2,
+ index3,
+ other,
+ comparer,
+ endIndex,
+ keys,
+ creationOptions,
+ timeout,
+ tasks,
+ scheduler,
+ continuationFunction,
+ millisecondsTimeout,
+ millisecondsDelay,
+ function,
+ exceptions,
+ exception,
+ cancellationToken,
+ delay,
+ asyncResult,
+ endMethod,
+ endFunction,
+ beginMethod,
+ continuationOptions,
+ continuationAction,
+
+ }
+
+ //
+ // The convention for this enum is using the resource name as the enum name
+ //
+ internal enum ExceptionResource {
+ Argument_ImplementIComparable,
+ Argument_InvalidType,
+ Argument_InvalidArgumentForComparison,
+ Argument_InvalidRegistryKeyPermissionCheck,
+ ArgumentOutOfRange_NeedNonNegNum,
+
+ Arg_ArrayPlusOffTooSmall,
+ Arg_NonZeroLowerBound,
+ Arg_RankMultiDimNotSupported,
+ Arg_RegKeyDelHive,
+ Arg_RegKeyStrLenBug,
+ Arg_RegSetStrArrNull,
+ Arg_RegSetMismatchedKind,
+ Arg_RegSubKeyAbsent,
+ Arg_RegSubKeyValueAbsent,
+
+ Argument_AddingDuplicate,
+ Serialization_InvalidOnDeser,
+ Serialization_MissingKeys,
+ Serialization_NullKey,
+ Argument_InvalidArrayType,
+ NotSupported_KeyCollectionSet,
+ NotSupported_ValueCollectionSet,
+ ArgumentOutOfRange_SmallCapacity,
+ ArgumentOutOfRange_Index,
+ Argument_InvalidOffLen,
+ Argument_ItemNotExist,
+ ArgumentOutOfRange_Count,
+ ArgumentOutOfRange_InvalidThreshold,
+ ArgumentOutOfRange_ListInsert,
+ NotSupported_ReadOnlyCollection,
+ InvalidOperation_CannotRemoveFromStackOrQueue,
+ InvalidOperation_EmptyQueue,
+ InvalidOperation_EnumOpCantHappen,
+ InvalidOperation_EnumFailedVersion,
+ InvalidOperation_EmptyStack,
+ ArgumentOutOfRange_BiggerThanCollection,
+ InvalidOperation_EnumNotStarted,
+ InvalidOperation_EnumEnded,
+ NotSupported_SortedListNestedWrite,
+ InvalidOperation_NoValue,
+ InvalidOperation_RegRemoveSubKey,
+ Security_RegistryPermission,
+ UnauthorizedAccess_RegistryNoWrite,
+ ObjectDisposed_RegKeyClosed,
+ NotSupported_InComparableType,
+ Argument_InvalidRegistryOptionsCheck,
+ Argument_InvalidRegistryViewCheck,
+ InvalidOperation_NullArray,
+ Arg_MustBeType,
+ Arg_NeedAtLeast1Rank,
+ ArgumentOutOfRange_HugeArrayNotSupported,
+ Arg_RanksAndBounds,
+ Arg_RankIndices,
+ Arg_Need1DArray,
+ Arg_Need2DArray,
+ Arg_Need3DArray,
+ NotSupported_FixedSizeCollection,
+ ArgumentException_OtherNotArrayOfCorrectLength,
+ Rank_MultiDimNotSupported,
+ InvalidOperation_IComparerFailed,
+ ArgumentOutOfRange_EndIndexStartIndex,
+ Arg_LowerBoundsMustMatch,
+ Arg_BogusIComparer,
+ Task_WaitMulti_NullTask,
+ Task_ThrowIfDisposed,
+ Task_Start_TaskCompleted,
+ Task_Start_Promise,
+ Task_Start_ContinuationTask,
+ Task_Start_AlreadyStarted,
+ Task_RunSynchronously_TaskCompleted,
+ Task_RunSynchronously_Continuation,
+ Task_RunSynchronously_Promise,
+ Task_RunSynchronously_AlreadyStarted,
+ Task_MultiTaskContinuation_NullTask,
+ Task_MultiTaskContinuation_EmptyTaskList,
+ Task_Dispose_NotCompleted,
+ Task_Delay_InvalidMillisecondsDelay,
+ Task_Delay_InvalidDelay,
+ Task_ctor_LRandSR,
+ Task_ContinueWith_NotOnAnything,
+ Task_ContinueWith_ESandLR,
+ TaskT_TransitionToFinal_AlreadyCompleted,
+ TaskT_ctor_SelfReplicating,
+ TaskCompletionSourceT_TrySetException_NullException,
+ TaskCompletionSourceT_TrySetException_NoExceptions,
+ InvalidOperation_WrongAsyncResultOrEndCalledMultiple,
+
+ }
+}
+
diff --git a/src/mscorlib/src/System/TimeSpan.cs b/src/mscorlib/src/System/TimeSpan.cs
new file mode 100644
index 0000000000..c9cfc084f3
--- /dev/null
+++ b/src/mscorlib/src/System/TimeSpan.cs
@@ -0,0 +1,445 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+ using System.Text;
+ using System;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+
+ // TimeSpan represents a duration of time. A TimeSpan can be negative
+ // or positive.
+ //
+ // TimeSpan is internally represented as a number of milliseconds. While
+ // this maps well into units of time such as hours and days, any
+ // periods longer than that aren't representable in a nice fashion.
+ // For instance, a month can be between 28 and 31 days, while a year
+ // can contain 365 or 364 days. A decade can have between 1 and 3 leapyears,
+ // depending on when you map the TimeSpan into the calendar. This is why
+ // we do not provide Years() or Months().
+ //
+ // Note: System.TimeSpan needs to interop with the WinRT structure
+ // type Windows::Foundation:TimeSpan. These types are currently binary-compatible in
+ // memory so no custom marshalling is required. If at any point the implementation
+ // details of this type should change, or new fields added, we need to remember to add
+ // an appropriate custom ILMarshaler to keep WInRT interop scenarios enabled.
+ //
+[System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable] public struct TimeSpan : IComparable
+ , IComparable<TimeSpan>, IEquatable<TimeSpan>, IFormattable
+ {
+ public const long TicksPerMillisecond = 10000;
+ private const double MillisecondsPerTick = 1.0 / TicksPerMillisecond;
+
+ public const long TicksPerSecond = TicksPerMillisecond * 1000; // 10,000,000
+ private const double SecondsPerTick = 1.0 / TicksPerSecond; // 0.0001
+
+ public const long TicksPerMinute = TicksPerSecond * 60; // 600,000,000
+ private const double MinutesPerTick = 1.0 / TicksPerMinute; // 1.6666666666667e-9
+
+ public const long TicksPerHour = TicksPerMinute * 60; // 36,000,000,000
+ private const double HoursPerTick = 1.0 / TicksPerHour; // 2.77777777777777778e-11
+
+ public const long TicksPerDay = TicksPerHour * 24; // 864,000,000,000
+ private const double DaysPerTick = 1.0 / TicksPerDay; // 1.1574074074074074074e-12
+
+ private const int MillisPerSecond = 1000;
+ private const int MillisPerMinute = MillisPerSecond * 60; // 60,000
+ private const int MillisPerHour = MillisPerMinute * 60; // 3,600,000
+ private const int MillisPerDay = MillisPerHour * 24; // 86,400,000
+
+ internal const long MaxSeconds = Int64.MaxValue / TicksPerSecond;
+ internal const long MinSeconds = Int64.MinValue / TicksPerSecond;
+
+ internal const long MaxMilliSeconds = Int64.MaxValue / TicksPerMillisecond;
+ internal const long MinMilliSeconds = Int64.MinValue / TicksPerMillisecond;
+
+ internal const long TicksPerTenthSecond = TicksPerMillisecond * 100;
+
+ public static readonly TimeSpan Zero = new TimeSpan(0);
+
+ public static readonly TimeSpan MaxValue = new TimeSpan(Int64.MaxValue);
+ public static readonly TimeSpan MinValue = new TimeSpan(Int64.MinValue);
+
+ // internal so that DateTime doesn't have to call an extra get
+ // method for some arithmetic operations.
+ internal long _ticks;
+
+ //public TimeSpan() {
+ // _ticks = 0;
+ //}
+
+ public TimeSpan(long ticks) {
+ this._ticks = ticks;
+ }
+
+ public TimeSpan(int hours, int minutes, int seconds) {
+ _ticks = TimeToTicks(hours, minutes, seconds);
+ }
+
+ public TimeSpan(int days, int hours, int minutes, int seconds)
+ : this(days,hours,minutes,seconds,0)
+ {
+ }
+
+ public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds)
+ {
+ Int64 totalMilliSeconds = ((Int64)days * 3600 * 24 + (Int64)hours * 3600 + (Int64)minutes * 60 + seconds) * 1000 + milliseconds;
+ if (totalMilliSeconds > MaxMilliSeconds || totalMilliSeconds < MinMilliSeconds)
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("Overflow_TimeSpanTooLong"));
+ _ticks = (long)totalMilliSeconds * TicksPerMillisecond;
+ }
+
+ public long Ticks {
+ get { return _ticks; }
+ }
+
+ public int Days {
+ get { return (int)(_ticks / TicksPerDay); }
+ }
+
+ public int Hours {
+ get { return (int)((_ticks / TicksPerHour) % 24); }
+ }
+
+ public int Milliseconds {
+ get { return (int)((_ticks / TicksPerMillisecond) % 1000); }
+ }
+
+ public int Minutes {
+ get { return (int)((_ticks / TicksPerMinute) % 60); }
+ }
+
+ public int Seconds {
+ get { return (int)((_ticks / TicksPerSecond) % 60); }
+ }
+
+ public double TotalDays {
+ get { return ((double)_ticks) * DaysPerTick; }
+ }
+
+ public double TotalHours {
+ get { return (double)_ticks * HoursPerTick; }
+ }
+
+ public double TotalMilliseconds {
+ get {
+ double temp = (double)_ticks * MillisecondsPerTick;
+ if (temp > MaxMilliSeconds)
+ return (double)MaxMilliSeconds;
+
+ if (temp < MinMilliSeconds)
+ return (double)MinMilliSeconds;
+
+ return temp;
+ }
+ }
+
+ public double TotalMinutes {
+ get { return (double)_ticks * MinutesPerTick; }
+ }
+
+ public double TotalSeconds {
+ get { return (double)_ticks * SecondsPerTick; }
+ }
+
+ public TimeSpan Add(TimeSpan ts) {
+ long result = _ticks + ts._ticks;
+ // Overflow if signs of operands was identical and result's
+ // sign was opposite.
+ // >> 63 gives the sign bit (either 64 1's or 64 0's).
+ if ((_ticks >> 63 == ts._ticks >> 63) && (_ticks >> 63 != result >> 63))
+ throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong"));
+ return new TimeSpan(result);
+ }
+
+
+ // Compares two TimeSpan values, returning an integer that indicates their
+ // relationship.
+ //
+ public static int Compare(TimeSpan t1, TimeSpan t2) {
+ if (t1._ticks > t2._ticks) return 1;
+ if (t1._ticks < t2._ticks) return -1;
+ return 0;
+ }
+
+ // Returns a value less than zero if this object
+ public int CompareTo(Object value) {
+ if (value == null) return 1;
+ if (!(value is TimeSpan))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeTimeSpan"));
+ long t = ((TimeSpan)value)._ticks;
+ if (_ticks > t) return 1;
+ if (_ticks < t) return -1;
+ return 0;
+ }
+
+ public int CompareTo(TimeSpan value) {
+ long t = value._ticks;
+ if (_ticks > t) return 1;
+ if (_ticks < t) return -1;
+ return 0;
+ }
+
+ public static TimeSpan FromDays(double value) {
+ return Interval(value, MillisPerDay);
+ }
+
+ public TimeSpan Duration() {
+ if (Ticks==TimeSpan.MinValue.Ticks)
+ throw new OverflowException(Environment.GetResourceString("Overflow_Duration"));
+ Contract.EndContractBlock();
+ return new TimeSpan(_ticks >= 0? _ticks: -_ticks);
+ }
+
+ public override bool Equals(Object value) {
+ if (value is TimeSpan) {
+ return _ticks == ((TimeSpan)value)._ticks;
+ }
+ return false;
+ }
+
+ public bool Equals(TimeSpan obj)
+ {
+ return _ticks == obj._ticks;
+ }
+
+ public static bool Equals(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks == t2._ticks;
+ }
+
+ public override int GetHashCode() {
+ return (int)_ticks ^ (int)(_ticks >> 32);
+ }
+
+ public static TimeSpan FromHours(double value) {
+ return Interval(value, MillisPerHour);
+ }
+
+ private static TimeSpan Interval(double value, int scale) {
+ if (Double.IsNaN(value))
+ throw new ArgumentException(Environment.GetResourceString("Arg_CannotBeNaN"));
+ Contract.EndContractBlock();
+ double tmp = value * scale;
+ double millis = tmp + (value >= 0? 0.5: -0.5);
+ if ((millis > Int64.MaxValue / TicksPerMillisecond) || (millis < Int64.MinValue / TicksPerMillisecond))
+ throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong"));
+ return new TimeSpan((long)millis * TicksPerMillisecond);
+ }
+
+ public static TimeSpan FromMilliseconds(double value) {
+ return Interval(value, 1);
+ }
+
+ public static TimeSpan FromMinutes(double value) {
+ return Interval(value, MillisPerMinute);
+ }
+
+ public TimeSpan Negate() {
+ if (Ticks==TimeSpan.MinValue.Ticks)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ Contract.EndContractBlock();
+ return new TimeSpan(-_ticks);
+ }
+
+ public static TimeSpan FromSeconds(double value) {
+ return Interval(value, MillisPerSecond);
+ }
+
+ public TimeSpan Subtract(TimeSpan ts) {
+ long result = _ticks - ts._ticks;
+ // Overflow if signs of operands was different and result's
+ // sign was opposite from the first argument's sign.
+ // >> 63 gives the sign bit (either 64 1's or 64 0's).
+ if ((_ticks >> 63 != ts._ticks >> 63) && (_ticks >> 63 != result >> 63))
+ throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong"));
+ return new TimeSpan(result);
+ }
+
+ public static TimeSpan FromTicks(long value) {
+ return new TimeSpan(value);
+ }
+
+ internal static long TimeToTicks(int hour, int minute, int second) {
+ // totalSeconds is bounded by 2^31 * 2^12 + 2^31 * 2^8 + 2^31,
+ // which is less than 2^44, meaning we won't overflow totalSeconds.
+ long totalSeconds = (long)hour * 3600 + (long)minute * 60 + (long)second;
+ if (totalSeconds > MaxSeconds || totalSeconds < MinSeconds)
+ throw new ArgumentOutOfRangeException(null, Environment.GetResourceString("Overflow_TimeSpanTooLong"));
+ return totalSeconds * TicksPerSecond;
+ }
+
+ // See System.Globalization.TimeSpanParse and System.Globalization.TimeSpanFormat
+ #region ParseAndFormat
+ public static TimeSpan Parse(String s) {
+ /* Constructs a TimeSpan from a string. Leading and trailing white space characters are allowed. */
+ return TimeSpanParse.Parse(s, null);
+ }
+ public static TimeSpan Parse(String input, IFormatProvider formatProvider) {
+ return TimeSpanParse.Parse(input, formatProvider);
+ }
+ public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider) {
+ return TimeSpanParse.ParseExact(input, format, formatProvider, TimeSpanStyles.None);
+ }
+ public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider) {
+ return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None);
+ }
+ public static TimeSpan ParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles) {
+ TimeSpanParse.ValidateStyles(styles, "styles");
+ return TimeSpanParse.ParseExact(input, format, formatProvider, styles);
+ }
+ public static TimeSpan ParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles) {
+ TimeSpanParse.ValidateStyles(styles, "styles");
+ return TimeSpanParse.ParseExactMultiple(input, formats, formatProvider, styles);
+ }
+ public static Boolean TryParse(String s, out TimeSpan result) {
+ return TimeSpanParse.TryParse(s, null, out result);
+ }
+ public static Boolean TryParse(String input, IFormatProvider formatProvider, out TimeSpan result) {
+ return TimeSpanParse.TryParse(input, formatProvider, out result);
+ }
+ public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, out TimeSpan result) {
+ return TimeSpanParse.TryParseExact(input, format, formatProvider, TimeSpanStyles.None, out result);
+ }
+ public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, out TimeSpan result) {
+ return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, TimeSpanStyles.None, out result);
+ }
+ public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) {
+ TimeSpanParse.ValidateStyles(styles, "styles");
+ return TimeSpanParse.TryParseExact(input, format, formatProvider, styles, out result);
+ }
+ public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, TimeSpanStyles styles, out TimeSpan result) {
+ TimeSpanParse.ValidateStyles(styles, "styles");
+ return TimeSpanParse.TryParseExactMultiple(input, formats, formatProvider, styles, out result);
+ }
+ public override String ToString() {
+ return TimeSpanFormat.Format(this, null, null);
+ }
+ public String ToString(String format) {
+ return TimeSpanFormat.Format(this, format, null);
+ }
+ public String ToString(String format, IFormatProvider formatProvider) {
+ if (LegacyMode) {
+ return TimeSpanFormat.Format(this, null, null);
+ }
+ else {
+ return TimeSpanFormat.Format(this, format, formatProvider);
+ }
+ }
+ #endregion
+
+ public static TimeSpan operator -(TimeSpan t) {
+ if (t._ticks==TimeSpan.MinValue._ticks)
+ throw new OverflowException(Environment.GetResourceString("Overflow_NegateTwosCompNum"));
+ return new TimeSpan(-t._ticks);
+ }
+
+ public static TimeSpan operator -(TimeSpan t1, TimeSpan t2) {
+ return t1.Subtract(t2);
+ }
+
+ public static TimeSpan operator +(TimeSpan t) {
+ return t;
+ }
+
+ public static TimeSpan operator +(TimeSpan t1, TimeSpan t2) {
+ return t1.Add(t2);
+ }
+
+ public static bool operator ==(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks == t2._ticks;
+ }
+
+ public static bool operator !=(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks != t2._ticks;
+ }
+
+ public static bool operator <(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks < t2._ticks;
+ }
+
+ public static bool operator <=(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks <= t2._ticks;
+ }
+
+ public static bool operator >(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks > t2._ticks;
+ }
+
+ public static bool operator >=(TimeSpan t1, TimeSpan t2) {
+ return t1._ticks >= t2._ticks;
+ }
+
+
+ //
+ // In .NET Framework v1.0 - v3.5 System.TimeSpan did not implement IFormattable
+ // The composite formatter ignores format specifiers on types that do not implement
+ // IFormattable, so the following code would 'just work' by using TimeSpan.ToString()
+ // under the hood:
+ // String.Format("{0:_someRandomFormatString_}", myTimeSpan);
+ //
+ // In .NET Framework v4.0 System.TimeSpan implements IFormattable. This causes the
+ // composite formatter to call TimeSpan.ToString(string format, FormatProvider provider)
+ // and pass in "_someRandomFormatString_" for the format parameter. When the format
+ // parameter is invalid a FormatException is thrown.
+ //
+ // The 'NetFx40_TimeSpanLegacyFormatMode' per-AppDomain configuration option and the 'TimeSpan_LegacyFormatMode'
+ // process-wide configuration option allows applications to run with the v1.0 - v3.5 legacy behavior. When
+ // either switch is specified the format parameter is ignored and the default output is returned.
+ //
+ // There are three ways to use the process-wide configuration option:
+ //
+ // 1) Config file (MyApp.exe.config)
+ // <?xml version ="1.0"?>
+ // <configuration>
+ // <runtime>
+ // <TimeSpan_LegacyFormatMode enabled="true"/>
+ // </runtime>
+ // </configuration>
+ // 2) Environment variable
+ // set COMPlus_TimeSpan_LegacyFormatMode=1
+ // 3) RegistryKey
+ // [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework]
+ // "TimeSpan_LegacyFormatMode"=dword:00000001
+ //
+#if !FEATURE_CORECLR
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool LegacyFormatMode();
+#endif // !FEATURE_CORECLR
+ //
+ // In Silverlight v4, specifying the APP_EARLIER_THAN_SL4.0 quirks mode allows applications to
+ // run in v2 - v3 legacy behavior.
+ //
+#if !FEATURE_CORECLR
+ [System.Security.SecuritySafeCritical]
+#endif
+ private static bool GetLegacyFormatMode() {
+#if !FEATURE_CORECLR
+ if (LegacyFormatMode()) // FCALL to check COMPlus_TimeSpan_LegacyFormatMode
+ return true;
+ return CompatibilitySwitches.IsNetFx40TimeSpanLegacyFormatMode;
+#else
+ return false;
+#endif // !FEATURE_CORECLR
+ }
+
+ private static volatile bool _legacyConfigChecked;
+ private static volatile bool _legacyMode;
+
+ private static bool LegacyMode {
+ get {
+ if (!_legacyConfigChecked) {
+ // no need to lock - idempotent
+ _legacyMode = GetLegacyFormatMode();
+ _legacyConfigChecked = true;
+ }
+ return _legacyMode;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/TimeZone.cs b/src/mscorlib/src/System/TimeZone.cs
new file mode 100644
index 0000000000..602e86ab54
--- /dev/null
+++ b/src/mscorlib/src/System/TimeZone.cs
@@ -0,0 +1,249 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+** Class: TimeZone
+**
+**
+** Purpose:
+** This class is used to represent a TimeZone. It
+** has methods for converting a DateTime to UTC from local time
+** and to local time from UTC and methods for getting the
+** standard name and daylight name of the time zone.
+**
+** The only TimeZone that we support in version 1 is the
+** CurrentTimeZone as determined by the system timezone.
+**
+**
+============================================================*/
+namespace System {
+ using System;
+ using System.Text;
+ using System.Threading;
+ using System.Collections;
+ using System.Globalization;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+#if FEATURE_CORECLR
+ [Obsolete("System.TimeZone has been deprecated. Please investigate the use of System.TimeZoneInfo instead.")]
+#endif
+ public abstract class TimeZone {
+ private static volatile TimeZone currentTimeZone = null;
+
+ // Private object for locking instead of locking on a public type for SQL reliability work.
+ private static Object s_InternalSyncObject;
+ private static Object InternalSyncObject {
+ get {
+ if (s_InternalSyncObject == null) {
+ Object o = new Object();
+ Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ }
+ return s_InternalSyncObject;
+ }
+ }
+
+
+ protected TimeZone() {
+ }
+
+ public static TimeZone CurrentTimeZone {
+ get {
+ //Grabbing the cached value is required at the top of this function so that
+ //we don't incur a race condition with the ResetTimeZone method below.
+ TimeZone tz = currentTimeZone;
+ if (tz == null) {
+ lock(InternalSyncObject) {
+ if (currentTimeZone == null) {
+ currentTimeZone = new CurrentSystemTimeZone();
+ }
+ tz = currentTimeZone;
+ }
+ }
+ return (tz);
+ }
+ }
+
+ //This method is called by CultureInfo.ClearCachedData in response to control panel
+ //change events. It must be synchronized because otherwise there is a race condition
+ //with the CurrentTimeZone property above.
+ internal static void ResetTimeZone() {
+ if (currentTimeZone!=null) {
+ lock(InternalSyncObject) {
+ currentTimeZone = null;
+ }
+ }
+ }
+
+ public abstract String StandardName {
+ get;
+ }
+
+ public abstract String DaylightName {
+ get;
+ }
+
+ public abstract TimeSpan GetUtcOffset(DateTime time);
+
+ //
+ // Converts the specified datatime to the Universal time base on the current timezone
+ //
+ public virtual DateTime ToUniversalTime(DateTime time) {
+ if (time.Kind == DateTimeKind.Utc) {
+ return time;
+ }
+ long tickCount = time.Ticks - GetUtcOffset(time).Ticks;
+ if (tickCount>DateTime.MaxTicks) {
+ return new DateTime(DateTime.MaxTicks, DateTimeKind.Utc);
+ }
+ if (tickCount<DateTime.MinTicks) {
+ return new DateTime(DateTime.MinTicks, DateTimeKind.Utc);
+ }
+ return new DateTime(tickCount, DateTimeKind.Utc);
+ }
+
+ //
+ // Convert the specified datetime value from UTC to the local time based on the time zone.
+ //
+ public virtual DateTime ToLocalTime(DateTime time) {
+ if (time.Kind == DateTimeKind.Local) {
+ return time;
+ }
+ Boolean isAmbiguousLocalDst = false;
+ Int64 offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst);
+ return new DateTime(time.Ticks + offset, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+
+ // Return an array of DaylightTime which reflects the daylight saving periods in a particular year.
+ // We currently only support having one DaylightSavingTime per year.
+ // If daylight saving time is not used in this timezone, null will be returned.
+ public abstract DaylightTime GetDaylightChanges(int year);
+
+ public virtual bool IsDaylightSavingTime(DateTime time) {
+ return (IsDaylightSavingTime(time, GetDaylightChanges(time.Year)));
+ }
+
+ // Check if the specified time is in a daylight saving time. Allows the user to
+ // specify the array of Daylight Saving Times.
+ public static bool IsDaylightSavingTime(DateTime time, DaylightTime daylightTimes) {
+ return CalculateUtcOffset(time, daylightTimes)!=TimeSpan.Zero;
+ }
+
+ //
+ // NOTENOTE: Implementation detail
+ // In the transition from standard time to daylight saving time,
+ // if we convert local time to Universal time, we can have the
+ // following (take PST as an example):
+ // Local Universal UTC Offset
+ // ----- --------- ----------
+ // 01:00AM 09:00 -8:00
+ // 02:00 (=> 03:00) 10:00 -8:00 [This time doesn't actually exist, but it can be created from DateTime]
+ // 03:00 10:00 -7:00
+ // 04:00 11:00 -7:00
+ // 05:00 12:00 -7:00
+ //
+ // So from 02:00 - 02:59:59, we should return the standard offset, instead of the daylight saving offset.
+ //
+ // In the transition from daylight saving time to standard time,
+ // if we convert local time to Universal time, we can have the
+ // following (take PST as an example):
+ // Local Universal UTC Offset
+ // ----- --------- ----------
+ // 01:00AM 08:00 -7:00
+ // 02:00 (=> 01:00) 09:00 -8:00
+ // 02:00 10:00 -8:00
+ // 03:00 11:00 -8:00
+ // 04:00 12:00 -8:00
+ //
+ // So in this case, the 02:00 does exist after the first 2:00 rolls back to 01:00. We don't need to special case this.
+ // But note that there are two 01:00 in the local time.
+
+ //
+ // And imagine if the daylight saving offset is negative (although this does not exist in real life)
+ // In the transition from standard time to daylight saving time,
+ // if we convert local time to Universal time, we can have the
+ // following (take PST as an example, but the daylight saving offset is -01:00):
+ // Local Universal UTC Offset
+ // ----- --------- ----------
+ // 01:00AM 09:00 -8:00
+ // 02:00 (=> 01:00) 10:00 -9:00
+ // 02:00 11:00 -9:00
+ // 03:00 12:00 -9:00
+ // 04:00 13:00 -9:00
+ // 05:00 14:00 -9:00
+ //
+ // So in this case, the 02:00 does exist after the first 2:00 rolls back to 01:00. We don't need to special case this.
+ //
+ // In the transition from daylight saving time to standard time,
+ // if we convert local time to Universal time, we can have the
+ // following (take PST as an example, daylight saving offset is -01:00):
+ //
+ // Local Universal UTC Offset
+ // ----- --------- ----------
+ // 01:00AM 10:00 -9:00
+ // 02:00 (=> 03:00) 11:00 -9:00
+ // 03:00 11:00 -8:00
+ // 04:00 12:00 -8:00
+ // 05:00 13:00 -8:00
+ // 06:00 14:00 -8:00
+ //
+ // So from 02:00 - 02:59:59, we should return the daylight saving offset, instead of the standard offset.
+ //
+ internal static TimeSpan CalculateUtcOffset(DateTime time, DaylightTime daylightTimes) {
+ if (daylightTimes==null) {
+ return TimeSpan.Zero;
+ }
+ DateTimeKind kind = time.Kind;
+ if (kind == DateTimeKind.Utc) {
+ return TimeSpan.Zero;
+ }
+
+ DateTime startTime;
+ DateTime endTime;
+
+ // startTime and endTime represent the period from either the start of DST to the end and includes the
+ // potentially overlapped times
+ startTime = daylightTimes.Start + daylightTimes.Delta;
+ endTime = daylightTimes.End;
+
+ // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the
+ // clock back. It is theoretically possible to have a positive delta, (which would really be daylight
+ // reduction time), where you would have to wind the clock back in the begnning.
+ DateTime ambiguousStart;
+ DateTime ambiguousEnd;
+ if (daylightTimes.Delta.Ticks > 0) {
+ ambiguousStart = endTime - daylightTimes.Delta;
+ ambiguousEnd = endTime;
+ } else {
+ ambiguousStart = startTime;
+ ambiguousEnd = startTime - daylightTimes.Delta;
+ }
+
+ Boolean isDst = false;
+ if (startTime > endTime) {
+ // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
+ // Note, the summer in the southern hemisphere begins late in the year.
+ if (time >= startTime || time < endTime) {
+ isDst = true;
+ }
+ }
+ else if (time>=startTime && time < endTime) {
+ // In northern hemisphere, the daylight saving time starts in the middle of the year.
+ isDst = true;
+ }
+
+ // If this date was previously converted from a UTC date and we were able to detect that the local
+ // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity.
+ if (isDst && time >= ambiguousStart && time < ambiguousEnd) {
+ isDst = time.IsAmbiguousDaylightSavingTime();
+ }
+
+ if (isDst) {
+ return daylightTimes.Delta;
+ }
+ return TimeSpan.Zero;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/TimeZoneInfo.cs b/src/mscorlib/src/System/TimeZoneInfo.cs
new file mode 100644
index 0000000000..a9d194afab
--- /dev/null
+++ b/src/mscorlib/src/System/TimeZoneInfo.cs
@@ -0,0 +1,5761 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+** This class is used to represent a Dynamic TimeZone. It
+** has methods for converting a DateTime between TimeZones,
+** and for reading TimeZone data from the Windows Registry
+**
+**
+============================================================*/
+
+namespace System {
+ using Microsoft.Win32;
+ using Microsoft.Win32.SafeHandles;
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+ using System.Globalization;
+ using System.IO;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using System.Runtime.Serialization;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Text;
+ using System.Threading;
+
+ //
+ // DateTime uses TimeZoneInfo under the hood for IsDaylightSavingTime, IsAmbiguousTime, and GetUtcOffset.
+ // These TimeZoneInfo APIs can throw ArgumentException when an Invalid-Time is passed in. To avoid this
+ // unwanted behavior in DateTime public APIs, DateTime internally passes the
+ // TimeZoneInfoOptions.NoThrowOnInvalidTime flag to internal TimeZoneInfo APIs.
+ //
+ // In the future we can consider exposing similar options on the public TimeZoneInfo APIs if there is enough
+ // demand for this alternate behavior.
+ //
+ [Flags]
+ internal enum TimeZoneInfoOptions {
+ None = 1,
+ NoThrowOnInvalidTime = 2
+ };
+
+
+ [Serializable]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ sealed public class TimeZoneInfo : IEquatable<TimeZoneInfo>, ISerializable, IDeserializationCallback
+ {
+ // ---- SECTION: members supporting exposed properties -------------*
+ private String m_id;
+ private String m_displayName;
+ private String m_standardDisplayName;
+ private String m_daylightDisplayName;
+ private TimeSpan m_baseUtcOffset;
+ private Boolean m_supportsDaylightSavingTime;
+ private AdjustmentRule[] m_adjustmentRules;
+
+ // ---- SECTION: members for internal support ---------*
+ private enum TimeZoneInfoResult {
+ Success = 0,
+ TimeZoneNotFoundException = 1,
+ InvalidTimeZoneException = 2,
+ SecurityException = 3
+ };
+
+
+#if FEATURE_WIN32_REGISTRY
+ // registry constants for the 'Time Zones' hive
+ //
+ private const string c_timeZonesRegistryHive = @"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones";
+ private const string c_timeZonesRegistryHivePermissionList = @"HKEY_LOCAL_MACHINE\" + c_timeZonesRegistryHive;
+ private const string c_displayValue = "Display";
+ private const string c_daylightValue = "Dlt";
+ private const string c_standardValue = "Std";
+ private const string c_muiDisplayValue = "MUI_Display";
+ private const string c_muiDaylightValue = "MUI_Dlt";
+ private const string c_muiStandardValue = "MUI_Std";
+ private const string c_timeZoneInfoValue = "TZI";
+ private const string c_firstEntryValue = "FirstEntry";
+ private const string c_lastEntryValue = "LastEntry";
+
+#endif // FEATURE_WIN32_REGISTRY
+
+#if PLATFORM_UNIX
+ private const string c_defaultTimeZoneDirectory = "/usr/share/zoneinfo/";
+ private const string c_zoneTabFileName = "zone.tab";
+ private const string c_timeZoneEnvironmentVariable = "TZ";
+ private const string c_timeZoneDirectoryEnvironmentVariable = "TZDIR";
+#endif // PLATFORM_UNIX
+
+ // constants for TimeZoneInfo.Local and TimeZoneInfo.Utc
+ private const string c_utcId = "UTC";
+ private const string c_localId = "Local";
+
+ private const int c_maxKeyLength = 255;
+
+ private const int c_regByteLength = 44;
+
+ // Number of 100ns ticks per time unit
+ private const long c_ticksPerMillisecond = 10000;
+ private const long c_ticksPerSecond = c_ticksPerMillisecond * 1000;
+ private const long c_ticksPerMinute = c_ticksPerSecond * 60;
+ private const long c_ticksPerHour = c_ticksPerMinute * 60;
+ private const long c_ticksPerDay = c_ticksPerHour * 24;
+ private const long c_ticksPerDayRange = c_ticksPerDay - c_ticksPerMillisecond;
+
+ //
+ // All cached data are encapsulated in a helper class to allow consistent view even when the data are refreshed using ClearCachedData()
+ //
+ // For example, TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData. Without the consistent snapshot,
+ // there is a chance that the internal ConvertTime calls will throw since 'source' won't be reference equal to the new TimeZoneInfo.Local.
+ //
+#pragma warning disable 0420
+ class CachedData
+ {
+ private volatile TimeZoneInfo m_localTimeZone;
+ private volatile TimeZoneInfo m_utcTimeZone;
+
+ private TimeZoneInfo CreateLocal()
+ {
+ lock (this)
+ {
+ TimeZoneInfo timeZone = m_localTimeZone;
+ if (timeZone == null) {
+ timeZone = TimeZoneInfo.GetLocalTimeZone(this);
+
+ // this step is to break the reference equality
+ // between TimeZoneInfo.Local and a second time zone
+ // such as "Pacific Standard Time"
+ timeZone = new TimeZoneInfo(
+ timeZone.m_id,
+ timeZone.m_baseUtcOffset,
+ timeZone.m_displayName,
+ timeZone.m_standardDisplayName,
+ timeZone.m_daylightDisplayName,
+ timeZone.m_adjustmentRules,
+ false);
+
+ m_localTimeZone = timeZone;
+ }
+ return timeZone;
+ }
+ }
+
+ public TimeZoneInfo Local {
+ get {
+ TimeZoneInfo timeZone = m_localTimeZone;
+ if (timeZone == null) {
+ timeZone = CreateLocal();
+ }
+ return timeZone;
+ }
+ }
+
+ private TimeZoneInfo CreateUtc()
+ {
+ lock (this)
+ {
+ TimeZoneInfo timeZone = m_utcTimeZone;
+ if (timeZone == null) {
+ timeZone = CreateCustomTimeZone(c_utcId, TimeSpan.Zero, c_utcId, c_utcId);
+ m_utcTimeZone = timeZone;
+ }
+ return timeZone;
+ }
+ }
+
+ public TimeZoneInfo Utc {
+ get {
+ Contract.Ensures(Contract.Result<TimeZoneInfo>() != null);
+
+ TimeZoneInfo timeZone = m_utcTimeZone;
+ if (timeZone == null) {
+ timeZone = CreateUtc();
+ }
+ return timeZone;
+ }
+ }
+
+ //
+ // GetCorrespondingKind-
+ //
+ // Helper function that returns the corresponding DateTimeKind for this TimeZoneInfo
+ //
+ public DateTimeKind GetCorrespondingKind(TimeZoneInfo timeZone) {
+ DateTimeKind kind;
+
+ //
+ // we check reference equality to see if 'this' is the same as
+ // TimeZoneInfo.Local or TimeZoneInfo.Utc. This check is needed to
+ // support setting the DateTime Kind property to 'Local' or
+ // 'Utc' on the ConverTime(...) return value.
+ //
+ // Using reference equality instead of value equality was a
+ // performance based design compromise. The reference equality
+ // has much greater performance, but it reduces the number of
+ // returned DateTime's that can be properly set as 'Local' or 'Utc'.
+ //
+ // For example, the user could be converting to the TimeZoneInfo returned
+ // by FindSystemTimeZoneById("Pacific Standard Time") and their local
+ // machine may be in Pacific time. If we used value equality to determine
+ // the corresponding Kind then this conversion would be tagged as 'Local';
+ // where as we are currently tagging the returned DateTime as 'Unspecified'
+ // in this example. Only when the user passes in TimeZoneInfo.Local or
+ // TimeZoneInfo.Utc to the ConvertTime(...) methods will this check succeed.
+ //
+ if ((object)timeZone == (object)m_utcTimeZone) {
+ kind = DateTimeKind.Utc;
+ }
+ else if ((object)timeZone == (object)m_localTimeZone) {
+ kind = DateTimeKind.Local;
+ }
+ else {
+ kind = DateTimeKind.Unspecified;
+ }
+
+ return kind;
+ }
+
+ public Dictionary<string, TimeZoneInfo> m_systemTimeZones;
+ public ReadOnlyCollection<TimeZoneInfo> m_readOnlySystemTimeZones;
+ public bool m_allSystemTimeZonesRead;
+
+#if FEATURE_WIN32_REGISTRY
+ [System.Security.SecuritySafeCritical]
+ private static TimeZoneInfo GetCurrentOneYearLocal() {
+ // load the data from the OS
+ TimeZoneInfo match;
+
+ Win32Native.TimeZoneInformation timeZoneInformation = new Win32Native.TimeZoneInformation();
+ long result = UnsafeNativeMethods.GetTimeZoneInformation(out timeZoneInformation);
+ if (result == Win32Native.TIME_ZONE_ID_INVALID)
+ match = CreateCustomTimeZone(c_localId, TimeSpan.Zero, c_localId, c_localId);
+ else
+ match = GetLocalTimeZoneFromWin32Data(timeZoneInformation, false);
+ return match;
+ }
+
+ private volatile OffsetAndRule m_oneYearLocalFromUtc;
+
+ public OffsetAndRule GetOneYearLocalFromUtc(int year) {
+ OffsetAndRule oneYearLocFromUtc = m_oneYearLocalFromUtc;
+ if (oneYearLocFromUtc == null || oneYearLocFromUtc.year != year) {
+ TimeZoneInfo currentYear = GetCurrentOneYearLocal();
+ AdjustmentRule rule = currentYear.m_adjustmentRules == null ? null : currentYear.m_adjustmentRules[0];
+ oneYearLocFromUtc = new OffsetAndRule(year, currentYear.BaseUtcOffset, rule);
+ m_oneYearLocalFromUtc = oneYearLocFromUtc;
+ }
+ return oneYearLocFromUtc;
+ }
+
+#endif // FEATURE_WIN32_REGISTRY
+ };
+#pragma warning restore 0420
+
+ static CachedData s_cachedData = new CachedData();
+
+ private class OffsetAndRule {
+ public int year;
+ public TimeSpan offset;
+ public AdjustmentRule rule;
+ public OffsetAndRule(int year, TimeSpan offset, AdjustmentRule rule) {
+ this.year = year;
+ this.offset = offset;
+ this.rule = rule;
+ }
+ }
+
+ // used by GetUtcOffsetFromUtc (DateTime.Now, DateTime.ToLocalTime) for max/min whole-day range checks
+ private static DateTime s_maxDateOnly = new DateTime(9999, 12, 31);
+ private static DateTime s_minDateOnly = new DateTime(1, 1, 2);
+
+ // ---- SECTION: public properties --------------*
+
+ public String Id {
+ get {
+ return m_id;
+ }
+ }
+
+ public String DisplayName {
+ get {
+ return (m_displayName == null ? String.Empty : m_displayName);
+ }
+ }
+
+ public String StandardName {
+ get {
+ return (m_standardDisplayName == null ? String.Empty : m_standardDisplayName);
+ }
+ }
+
+ public String DaylightName {
+ get {
+ return (m_daylightDisplayName == null? String.Empty : m_daylightDisplayName);
+ }
+ }
+
+ public TimeSpan BaseUtcOffset {
+ get {
+ return m_baseUtcOffset;
+ }
+ }
+
+ public Boolean SupportsDaylightSavingTime {
+ get {
+ return m_supportsDaylightSavingTime;
+ }
+ }
+
+
+ // ---- SECTION: public methods --------------*
+
+ //
+ // GetAdjustmentRules -
+ //
+ // returns a cloned array of AdjustmentRule objects
+ //
+ public AdjustmentRule [] GetAdjustmentRules() {
+ if (m_adjustmentRules == null) {
+ return new AdjustmentRule[0];
+ }
+ else {
+ return (AdjustmentRule[])m_adjustmentRules.Clone();
+ }
+ }
+
+
+ //
+ // GetAmbiguousTimeOffsets -
+ //
+ // returns an array of TimeSpan objects representing all of
+ // possible UTC offset values for this ambiguous time
+ //
+ public TimeSpan[] GetAmbiguousTimeOffsets(DateTimeOffset dateTimeOffset) {
+ if (!SupportsDaylightSavingTime) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), "dateTimeOffset");
+ }
+ Contract.EndContractBlock();
+
+ DateTime adjustedTime = (TimeZoneInfo.ConvertTime(dateTimeOffset, this)).DateTime;
+
+ Boolean isAmbiguous = false;
+ AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime);
+ if (rule != null && rule.HasDaylightSaving) {
+ DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule);
+ isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime);
+ }
+
+ if (!isAmbiguous) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetIsNotAmbiguous"), "dateTimeOffset");
+ }
+
+ // the passed in dateTime is ambiguous in this TimeZoneInfo instance
+ TimeSpan[] timeSpans = new TimeSpan[2];
+
+ TimeSpan actualUtcOffset = m_baseUtcOffset + rule.BaseUtcOffsetDelta;
+
+ // the TimeSpan array must be sorted from least to greatest
+ if (rule.DaylightDelta > TimeSpan.Zero) {
+ timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta;
+ timeSpans[1] = actualUtcOffset + rule.DaylightDelta;
+ }
+ else {
+ timeSpans[0] = actualUtcOffset + rule.DaylightDelta;
+ timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta;
+ }
+ return timeSpans;
+ }
+
+
+ public TimeSpan[] GetAmbiguousTimeOffsets(DateTime dateTime) {
+ if (!SupportsDaylightSavingTime) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), "dateTime");
+ }
+ Contract.EndContractBlock();
+
+ DateTime adjustedTime;
+ if (dateTime.Kind == DateTimeKind.Local) {
+ CachedData cachedData = s_cachedData;
+ adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, this, TimeZoneInfoOptions.None, cachedData);
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc) {
+ CachedData cachedData = s_cachedData;
+ adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, TimeZoneInfoOptions.None, cachedData);
+ }
+ else {
+ adjustedTime = dateTime;
+ }
+
+ Boolean isAmbiguous = false;
+ AdjustmentRule rule = GetAdjustmentRuleForAmbiguousOffsets(adjustedTime);
+ if (rule != null && rule.HasDaylightSaving) {
+ DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule);
+ isAmbiguous = GetIsAmbiguousTime(adjustedTime, rule, daylightTime);
+ }
+
+ if (!isAmbiguous) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsNotAmbiguous"), "dateTime");
+ }
+
+ // the passed in dateTime is ambiguous in this TimeZoneInfo instance
+ TimeSpan[] timeSpans = new TimeSpan[2];
+ TimeSpan actualUtcOffset = m_baseUtcOffset + rule.BaseUtcOffsetDelta;
+
+ // the TimeSpan array must be sorted from least to greatest
+ if (rule.DaylightDelta > TimeSpan.Zero) {
+ timeSpans[0] = actualUtcOffset; // FUTURE: + rule.StandardDelta;
+ timeSpans[1] = actualUtcOffset + rule.DaylightDelta;
+ }
+ else {
+ timeSpans[0] = actualUtcOffset + rule.DaylightDelta;
+ timeSpans[1] = actualUtcOffset; // FUTURE: + rule.StandardDelta;
+ }
+ return timeSpans;
+ }
+
+ // note the time is already adjusted
+ private AdjustmentRule GetAdjustmentRuleForAmbiguousOffsets(DateTime adjustedTime)
+ {
+ AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime);
+ if (rule != null && rule.NoDaylightTransitions && !rule.HasDaylightSaving)
+ {
+ // When using NoDaylightTransitions rules, each rule is only for one offset.
+ // When looking for the Daylight savings rules, and we found the non-DST rule,
+ // then we get the rule right before this rule.
+ return GetPreviousAdjustmentRule(rule);
+ }
+
+ return rule;
+ }
+
+ /// <summary>
+ /// Gets the AdjustmentRule that is immediately preceeding the specified rule.
+ /// If the specified rule is the first AdjustmentRule, or it isn't in m_adjustmentRules,
+ /// then the specified rule is returned.
+ /// </summary>
+ private AdjustmentRule GetPreviousAdjustmentRule(AdjustmentRule rule)
+ {
+ AdjustmentRule result = rule;
+ for (int i = 1; i < m_adjustmentRules.Length; i++)
+ {
+ if (rule.Equals(m_adjustmentRules[i]))
+ {
+ result = m_adjustmentRules[i - 1];
+ break;
+ }
+ }
+ return result;
+ }
+
+ //
+ // GetUtcOffset -
+ //
+ // returns the Universal Coordinated Time (UTC) Offset
+ // for the current TimeZoneInfo instance.
+ //
+ public TimeSpan GetUtcOffset(DateTimeOffset dateTimeOffset) {
+ return GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this);
+ }
+
+
+ public TimeSpan GetUtcOffset(DateTime dateTime) {
+ return GetUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData);
+ }
+
+ // Shortcut for TimeZoneInfo.Local.GetUtcOffset
+ internal static TimeSpan GetLocalUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) {
+ CachedData cachedData = s_cachedData;
+ return cachedData.Local.GetUtcOffset(dateTime, flags, cachedData);
+ }
+
+ internal TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags) {
+ return GetUtcOffset(dateTime, flags, s_cachedData);
+ }
+
+ private TimeSpan GetUtcOffset(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) {
+ if (dateTime.Kind == DateTimeKind.Local) {
+ if (cachedData.GetCorrespondingKind(this) != DateTimeKind.Local) {
+ //
+ // normal case of converting from Local to Utc and then getting the offset from the UTC DateTime
+ //
+ DateTime adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags);
+ return GetUtcOffsetFromUtc(adjustedTime, this);
+ }
+
+ //
+ // Fall through for TimeZoneInfo.Local.GetUtcOffset(date)
+ // to handle an edge case with Invalid-Times for DateTime formatting:
+ //
+ // Consider the invalid PST time "2007-03-11T02:00:00.0000000-08:00"
+ //
+ // By directly calling GetUtcOffset instead of converting to UTC and then calling GetUtcOffsetFromUtc
+ // the correct invalid offset of "-08:00" is returned. In the normal case of converting to UTC as an
+ // interim-step, the invalid time is adjusted into a *valid* UTC time which causes a change in output:
+ //
+ // 1) invalid PST time "2007-03-11T02:00:00.0000000-08:00"
+ // 2) converted to UTC "2007-03-11T10:00:00.0000000Z"
+ // 3) offset returned "2007-03-11T03:00:00.0000000-07:00"
+ //
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc) {
+ if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) {
+ return m_baseUtcOffset;
+ }
+ else {
+ //
+ // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a
+ // special Loss-Less case.
+ //
+ return GetUtcOffsetFromUtc(dateTime, this);
+ }
+ }
+
+ return GetUtcOffset(dateTime, this, flags);
+ }
+
+ //
+ // IsAmbiguousTime -
+ //
+ // returns true if the time is during the ambiguous time period
+ // for the current TimeZoneInfo instance.
+ //
+ public Boolean IsAmbiguousTime(DateTimeOffset dateTimeOffset) {
+ if (!m_supportsDaylightSavingTime) {
+ return false;
+ }
+
+ DateTimeOffset adjustedTime = TimeZoneInfo.ConvertTime(dateTimeOffset, this);
+ return IsAmbiguousTime(adjustedTime.DateTime);
+ }
+
+
+ public Boolean IsAmbiguousTime(DateTime dateTime) {
+ return IsAmbiguousTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
+ }
+
+ internal Boolean IsAmbiguousTime(DateTime dateTime, TimeZoneInfoOptions flags) {
+ if (!m_supportsDaylightSavingTime) {
+ return false;
+ }
+
+ DateTime adjustedTime;
+ if (dateTime.Kind == DateTimeKind.Local) {
+ CachedData cachedData = s_cachedData;
+ adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, this, flags, cachedData);
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc) {
+ CachedData cachedData = s_cachedData;
+ adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Utc, this, flags, cachedData);
+ }
+ else {
+ adjustedTime = dateTime;
+ }
+
+ AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime);
+ if (rule != null && rule.HasDaylightSaving) {
+ DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule);
+ return GetIsAmbiguousTime(adjustedTime, rule, daylightTime);
+ }
+ return false;
+ }
+
+
+
+ //
+ // IsDaylightSavingTime -
+ //
+ // Returns true if the time is during Daylight Saving time
+ // for the current TimeZoneInfo instance.
+ //
+ public Boolean IsDaylightSavingTime(DateTimeOffset dateTimeOffset) {
+ Boolean isDaylightSavingTime;
+ GetUtcOffsetFromUtc(dateTimeOffset.UtcDateTime, this, out isDaylightSavingTime);
+ return isDaylightSavingTime;
+ }
+
+
+ public Boolean IsDaylightSavingTime(DateTime dateTime) {
+ return IsDaylightSavingTime(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime, s_cachedData);
+ }
+
+ internal Boolean IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags) {
+ return IsDaylightSavingTime(dateTime, flags, s_cachedData);
+ }
+
+ private Boolean IsDaylightSavingTime(DateTime dateTime, TimeZoneInfoOptions flags, CachedData cachedData) {
+ //
+ // dateTime.Kind is UTC, then time will be converted from UTC
+ // into current instance's timezone
+ // dateTime.Kind is Local, then time will be converted from Local
+ // into current instance's timezone
+ // dateTime.Kind is UnSpecified, then time is already in
+ // current instance's timezone
+ //
+ // Our DateTime handles ambiguous times, (one is in the daylight and
+ // one is in standard.) If a new DateTime is constructed during ambiguous
+ // time, it is defaulted to "Standard" (i.e. this will return false).
+ // For Invalid times, we will return false
+
+ if (!m_supportsDaylightSavingTime || m_adjustmentRules == null) {
+ return false;
+ }
+
+ DateTime adjustedTime;
+ //
+ // handle any Local/Utc special cases...
+ //
+ if (dateTime.Kind == DateTimeKind.Local) {
+ adjustedTime = TimeZoneInfo.ConvertTime(dateTime, cachedData.Local, this, flags, cachedData);
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc) {
+ if (cachedData.GetCorrespondingKind(this) == DateTimeKind.Utc) {
+ // simple always false case: TimeZoneInfo.Utc.IsDaylightSavingTime(dateTime, flags);
+ return false;
+ }
+ else {
+ //
+ // passing in a UTC dateTime to a non-UTC TimeZoneInfo instance is a
+ // special Loss-Less case.
+ //
+ Boolean isDaylightSavings;
+ GetUtcOffsetFromUtc(dateTime, this, out isDaylightSavings);
+ return isDaylightSavings;
+ }
+ }
+ else {
+ adjustedTime = dateTime;
+ }
+
+ //
+ // handle the normal cases...
+ //
+ AdjustmentRule rule = GetAdjustmentRuleForTime(adjustedTime);
+ if (rule != null && rule.HasDaylightSaving) {
+ DaylightTime daylightTime = GetDaylightTime(adjustedTime.Year, rule);
+ return GetIsDaylightSavings(adjustedTime, rule, daylightTime, flags);
+ }
+ else {
+ return false;
+ }
+ }
+
+
+ //
+ // IsInvalidTime -
+ //
+ // returns true when dateTime falls into a "hole in time".
+ //
+ public Boolean IsInvalidTime(DateTime dateTime) {
+ Boolean isInvalid = false;
+
+ if ( (dateTime.Kind == DateTimeKind.Unspecified)
+ || (dateTime.Kind == DateTimeKind.Local && s_cachedData.GetCorrespondingKind(this) == DateTimeKind.Local) ) {
+
+ // only check Unspecified and (Local when this TimeZoneInfo instance is Local)
+ AdjustmentRule rule = GetAdjustmentRuleForTime(dateTime);
+
+ if (rule != null && rule.HasDaylightSaving) {
+ DaylightTime daylightTime = GetDaylightTime(dateTime.Year, rule);
+ isInvalid = GetIsInvalidTime(dateTime, rule, daylightTime);
+ }
+ else {
+ isInvalid = false;
+ }
+ }
+
+ return isInvalid;
+ }
+
+
+ //
+ // ClearCachedData -
+ //
+ // Clears data from static members
+ //
+ static public void ClearCachedData() {
+ // Clear a fresh instance of cached data
+ s_cachedData = new CachedData();
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ //
+ // ConvertTimeBySystemTimeZoneId -
+ //
+ // Converts the value of a DateTime object from sourceTimeZone to destinationTimeZone
+ //
+ static public DateTimeOffset ConvertTimeBySystemTimeZoneId(DateTimeOffset dateTimeOffset, String destinationTimeZoneId) {
+ return ConvertTime(dateTimeOffset, FindSystemTimeZoneById(destinationTimeZoneId));
+ }
+
+ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String destinationTimeZoneId) {
+ return ConvertTime(dateTime, FindSystemTimeZoneById(destinationTimeZoneId));
+ }
+
+ static public DateTime ConvertTimeBySystemTimeZoneId(DateTime dateTime, String sourceTimeZoneId, String destinationTimeZoneId) {
+ if (dateTime.Kind == DateTimeKind.Local && String.Compare(sourceTimeZoneId, TimeZoneInfo.Local.Id, StringComparison.OrdinalIgnoreCase) == 0) {
+ // TimeZoneInfo.Local can be cleared by another thread calling TimeZoneInfo.ClearCachedData.
+ // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call.
+ // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't
+ // be reference equal to the new TimeZoneInfo.Local
+ //
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, cachedData.Local, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData);
+ }
+ else if (dateTime.Kind == DateTimeKind.Utc && String.Compare(sourceTimeZoneId, TimeZoneInfo.Utc.Id, StringComparison.OrdinalIgnoreCase) == 0) {
+ // TimeZoneInfo.Utc can be cleared by another thread calling TimeZoneInfo.ClearCachedData.
+ // Take snapshot of cached data to guarantee this method will not be impacted by the ClearCachedData call.
+ // Without the snapshot, there is a chance that ConvertTime will throw since 'source' won't
+ // be reference equal to the new TimeZoneInfo.Utc
+ //
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, cachedData.Utc, FindSystemTimeZoneById(destinationTimeZoneId), TimeZoneInfoOptions.None, cachedData);
+ }
+ else {
+ return ConvertTime(dateTime, FindSystemTimeZoneById(sourceTimeZoneId), FindSystemTimeZoneById(destinationTimeZoneId));
+ }
+ }
+#endif // FEATURE_WIN32_REGISTRY
+
+
+ //
+ // ConvertTime -
+ //
+ // Converts the value of the dateTime object from sourceTimeZone to destinationTimeZone
+ //
+
+ static public DateTimeOffset ConvertTime(DateTimeOffset dateTimeOffset, TimeZoneInfo destinationTimeZone) {
+ if (destinationTimeZone == null) {
+ throw new ArgumentNullException("destinationTimeZone");
+ }
+
+ Contract.EndContractBlock();
+ // calculate the destination time zone offset
+ DateTime utcDateTime = dateTimeOffset.UtcDateTime;
+ TimeSpan destinationOffset = GetUtcOffsetFromUtc(utcDateTime, destinationTimeZone);
+
+ // check for overflow
+ Int64 ticks = utcDateTime.Ticks + destinationOffset.Ticks;
+
+ if (ticks > DateTimeOffset.MaxValue.Ticks) {
+ return DateTimeOffset.MaxValue;
+ }
+ else if (ticks < DateTimeOffset.MinValue.Ticks) {
+ return DateTimeOffset.MinValue;
+ }
+ else {
+ return new DateTimeOffset(ticks, destinationOffset);
+ }
+ }
+
+ static public DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) {
+ if (destinationTimeZone == null) {
+ throw new ArgumentNullException("destinationTimeZone");
+ }
+ Contract.EndContractBlock();
+
+ // Special case to give a way clearing the cache without exposing ClearCachedData()
+ if (dateTime.Ticks == 0) {
+ ClearCachedData();
+ }
+ CachedData cachedData = s_cachedData;
+ if (dateTime.Kind == DateTimeKind.Utc) {
+ return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
+ }
+ else {
+ return ConvertTime(dateTime, cachedData.Local, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
+ }
+ }
+
+ static public DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone) {
+ return ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, TimeZoneInfoOptions.None, s_cachedData);
+ }
+
+
+ static internal DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags) {
+ return ConvertTime(dateTime, sourceTimeZone, destinationTimeZone, flags, s_cachedData);
+ }
+
+ static private DateTime ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData) {
+ if (sourceTimeZone == null) {
+ throw new ArgumentNullException("sourceTimeZone");
+ }
+
+ if (destinationTimeZone == null) {
+ throw new ArgumentNullException("destinationTimeZone");
+ }
+ Contract.EndContractBlock();
+
+ DateTimeKind sourceKind = cachedData.GetCorrespondingKind(sourceTimeZone);
+ if ( ((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && (dateTime.Kind != DateTimeKind.Unspecified) && (dateTime.Kind != sourceKind) ) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_ConvertMismatch"), "sourceTimeZone");
+ }
+
+ //
+ // check to see if the DateTime is in an invalid time range. This check
+ // requires the current AdjustmentRule and DaylightTime - which are also
+ // needed to calculate 'sourceOffset' in the normal conversion case.
+ // By calculating the 'sourceOffset' here we improve the
+ // performance for the normal case at the expense of the 'ArgumentException'
+ // case and Loss-less Local special cases.
+ //
+ AdjustmentRule sourceRule = sourceTimeZone.GetAdjustmentRuleForTime(dateTime);
+ TimeSpan sourceOffset = sourceTimeZone.BaseUtcOffset;
+
+ if (sourceRule != null) {
+ sourceOffset = sourceOffset + sourceRule.BaseUtcOffsetDelta;
+ if (sourceRule.HasDaylightSaving) {
+ Boolean sourceIsDaylightSavings = false;
+ DaylightTime sourceDaylightTime = sourceTimeZone.GetDaylightTime(dateTime.Year, sourceRule);
+
+ // 'dateTime' might be in an invalid time range since it is in an AdjustmentRule
+ // period that supports DST
+ if (((flags & TimeZoneInfoOptions.NoThrowOnInvalidTime) == 0) && GetIsInvalidTime(dateTime, sourceRule, sourceDaylightTime)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeIsInvalid"), "dateTime");
+ }
+ sourceIsDaylightSavings = GetIsDaylightSavings(dateTime, sourceRule, sourceDaylightTime, flags);
+
+ // adjust the sourceOffset according to the Adjustment Rule / Daylight Saving Rule
+ sourceOffset += (sourceIsDaylightSavings ? sourceRule.DaylightDelta : TimeSpan.Zero /*FUTURE: sourceRule.StandardDelta*/);
+ }
+ }
+
+ DateTimeKind targetKind = cachedData.GetCorrespondingKind(destinationTimeZone);
+
+ // handle the special case of Loss-less Local->Local and UTC->UTC)
+ if (dateTime.Kind != DateTimeKind.Unspecified && sourceKind != DateTimeKind.Unspecified
+ && sourceKind == targetKind) {
+ return dateTime;
+ }
+
+ Int64 utcTicks = dateTime.Ticks - sourceOffset.Ticks;
+
+ // handle the normal case by converting from 'source' to UTC and then to 'target'
+ Boolean isAmbiguousLocalDst = false;
+ DateTime targetConverted = ConvertUtcToTimeZone(utcTicks, destinationTimeZone, out isAmbiguousLocalDst);
+
+ if (targetKind == DateTimeKind.Local) {
+ // Because the ticks conversion between UTC and local is lossy, we need to capture whether the
+ // time is in a repeated hour so that it can be passed to the DateTime constructor.
+ return new DateTime(targetConverted.Ticks, DateTimeKind.Local, isAmbiguousLocalDst);
+ }
+ else {
+ return new DateTime(targetConverted.Ticks, targetKind);
+ }
+ }
+
+
+
+ //
+ // ConvertTimeFromUtc -
+ //
+ // Converts the value of a DateTime object from Coordinated Universal Time (UTC) to
+ // the destinationTimeZone.
+ //
+ static public DateTime ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone) {
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, cachedData.Utc, destinationTimeZone, TimeZoneInfoOptions.None, cachedData);
+ }
+
+
+ //
+ // ConvertTimeToUtc -
+ //
+ // Converts the value of a DateTime object to Coordinated Universal Time (UTC).
+ //
+ static public DateTime ConvertTimeToUtc(DateTime dateTime) {
+ if (dateTime.Kind == DateTimeKind.Utc) {
+ return dateTime;
+ }
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, TimeZoneInfoOptions.None, cachedData);
+ }
+
+
+ static internal DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfoOptions flags) {
+ if (dateTime.Kind == DateTimeKind.Utc) {
+ return dateTime;
+ }
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, cachedData.Local, cachedData.Utc, flags, cachedData);
+ }
+
+ static public DateTime ConvertTimeToUtc(DateTime dateTime, TimeZoneInfo sourceTimeZone) {
+ CachedData cachedData = s_cachedData;
+ return ConvertTime(dateTime, sourceTimeZone, cachedData.Utc, TimeZoneInfoOptions.None, cachedData);
+ }
+
+
+ //
+ // IEquatable.Equals -
+ //
+ // returns value equality. Equals does not compare any localizable
+ // String objects (DisplayName, StandardName, DaylightName).
+ //
+ public bool Equals(TimeZoneInfo other) {
+ return (other != null && String.Compare(this.m_id, other.m_id, StringComparison.OrdinalIgnoreCase) == 0 && HasSameRules(other));
+ }
+
+ public override bool Equals(object obj) {
+ TimeZoneInfo tzi = obj as TimeZoneInfo;
+ if (null == tzi) {
+ return false;
+ }
+ return Equals(tzi);
+ }
+
+ //
+ // FromSerializedString -
+ //
+ static public TimeZoneInfo FromSerializedString(string source) {
+ if (source == null) {
+ throw new ArgumentNullException("source");
+ }
+ if (source.Length == 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidSerializedString", source), "source");
+ }
+ Contract.EndContractBlock();
+
+ return StringSerializer.GetDeserializedTimeZoneInfo(source);
+ }
+
+
+ //
+ // GetHashCode -
+ //
+ public override int GetHashCode() {
+ return m_id.ToUpper(CultureInfo.InvariantCulture).GetHashCode();
+ }
+
+ //
+ // GetSystemTimeZones -
+ //
+ // returns a ReadOnlyCollection<TimeZoneInfo> containing all valid TimeZone's
+ // from the local machine. The entries in the collection are sorted by
+ // 'DisplayName'.
+ //
+ // This method does *not* throw TimeZoneNotFoundException or
+ // InvalidTimeZoneException.
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <Asserts Name="Imperative: System.Security.PermissionSet" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static public ReadOnlyCollection<TimeZoneInfo> GetSystemTimeZones() {
+
+ CachedData cachedData = s_cachedData;
+
+ lock (cachedData) {
+ if (cachedData.m_readOnlySystemTimeZones == null) {
+ PopulateAllSystemTimeZones(cachedData);
+ cachedData.m_allSystemTimeZonesRead = true;
+
+ List<TimeZoneInfo> list;
+ if (cachedData.m_systemTimeZones != null) {
+ // return a collection of the cached system time zones
+ list = new List<TimeZoneInfo>(cachedData.m_systemTimeZones.Values);
+ }
+ else {
+ // return an empty collection
+ list = new List<TimeZoneInfo>();
+ }
+
+ // sort and copy the TimeZoneInfo's into a ReadOnlyCollection for the user
+ list.Sort(new TimeZoneInfoComparer());
+
+ cachedData.m_readOnlySystemTimeZones = new ReadOnlyCollection<TimeZoneInfo>(list);
+ }
+ }
+ return cachedData.m_readOnlySystemTimeZones;
+ }
+
+ [SecuritySafeCritical]
+ private static void PopulateAllSystemTimeZones(CachedData cachedData)
+ {
+#if FEATURE_WIN32_REGISTRY
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList));
+ permSet.Assert();
+
+ using (RegistryKey reg = Registry.LocalMachine.OpenSubKey(
+ c_timeZonesRegistryHive,
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.Default,
+ System.Security.AccessControl.RegistryRights.ReadKey
+#else
+ false
+#endif
+ )) {
+
+ if (reg != null) {
+ foreach (string keyName in reg.GetSubKeyNames()) {
+ TimeZoneInfo value;
+ Exception ex;
+ TryGetTimeZone(keyName, false, out value, out ex, cachedData); // populate the cache
+ }
+ }
+ }
+#elif PLATFORM_UNIX // FEATURE_WIN32_REGISTRY
+ string timeZoneDirectory = GetTimeZoneDirectory();
+ foreach (string timeZoneId in GetTimeZoneIds(timeZoneDirectory))
+ {
+ TimeZoneInfo value;
+ Exception ex;
+ TryGetTimeZone(timeZoneId, false, out value, out ex, cachedData); // populate the cache
+ }
+#endif // FEATURE_WIN32_REGISTRY
+ }
+
+ //
+ // HasSameRules -
+ //
+ // Value equality on the "adjustmentRules" array
+ //
+ public Boolean HasSameRules(TimeZoneInfo other) {
+ if (other == null) {
+ throw new ArgumentNullException("other");
+ }
+
+ // check the utcOffset and supportsDaylightSavingTime members
+ Contract.EndContractBlock();
+
+ if (this.m_baseUtcOffset != other.m_baseUtcOffset
+ || this.m_supportsDaylightSavingTime != other.m_supportsDaylightSavingTime) {
+ return false;
+ }
+
+ bool sameRules;
+ AdjustmentRule[] currentRules = this.m_adjustmentRules;
+ AdjustmentRule[] otherRules = other.m_adjustmentRules;
+
+ sameRules = (currentRules == null && otherRules == null)
+ ||(currentRules != null && otherRules != null);
+
+ if (!sameRules) {
+ // AdjustmentRule array mismatch
+ return false;
+ }
+
+ if (currentRules != null) {
+ if (currentRules.Length != otherRules.Length) {
+ // AdjustmentRule array length mismatch
+ return false;
+ }
+
+ for(int i = 0; i < currentRules.Length; i++) {
+ if (!(currentRules[i]).Equals(otherRules[i])) {
+ // AdjustmentRule value-equality mismatch
+ return false;
+ }
+ }
+
+ }
+ return sameRules;
+ }
+
+ //
+ // Local -
+ //
+ // returns a TimeZoneInfo instance that represents the local time on the machine.
+ // Accessing this property may throw InvalidTimeZoneException or COMException
+ // if the machine is in an unstable or corrupt state.
+ //
+ static public TimeZoneInfo Local {
+ get {
+ Contract.Ensures(Contract.Result<TimeZoneInfo>() != null);
+ return s_cachedData.Local;
+ }
+ }
+
+
+ //
+ // ToSerializedString -
+ //
+ // "TimeZoneInfo" := TimeZoneInfo Data;[AdjustmentRule Data 1];...;[AdjustmentRule Data N]
+ //
+ // "TimeZoneInfo Data" := <m_id>;<m_baseUtcOffset>;<m_displayName>;
+ // <m_standardDisplayName>;<m_daylightDispayName>;
+ //
+ // "AdjustmentRule Data" := <DateStart>;<DateEnd>;<DaylightDelta>;
+ // [TransitionTime Data DST Start]
+ // [TransitionTime Data DST End]
+ //
+ // "TransitionTime Data" += <DaylightStartTimeOfDat>;<Month>;<Week>;<DayOfWeek>;<Day>
+ //
+ public String ToSerializedString() {
+ return StringSerializer.GetSerializedString(this);
+ }
+
+
+ //
+ // ToString -
+ //
+ // returns the DisplayName:
+ // "(GMT-08:00) Pacific Time (US & Canada); Tijuana"
+ //
+ public override string ToString() {
+ return this.DisplayName;
+ }
+
+
+ //
+ // Utc -
+ //
+ // returns a TimeZoneInfo instance that represents Universal Coordinated Time (UTC)
+ //
+ static public TimeZoneInfo Utc {
+ get {
+ Contract.Ensures(Contract.Result<TimeZoneInfo>() != null);
+ return s_cachedData.Utc;
+ }
+ }
+
+
+ // -------- SECTION: constructors -----------------*
+ //
+ // TimeZoneInfo -
+ //
+ // private ctor
+ //
+#if FEATURE_WIN32_REGISTRY
+ [System.Security.SecurityCritical] // auto-generated
+ private TimeZoneInfo(Win32Native.TimeZoneInformation zone, Boolean dstDisabled) {
+
+ if (String.IsNullOrEmpty(zone.StandardName)) {
+ m_id = c_localId; // the ID must contain at least 1 character - initialize m_id to "Local"
+ }
+ else {
+ m_id = zone.StandardName;
+ }
+ m_baseUtcOffset = new TimeSpan(0, -(zone.Bias), 0);
+
+ if (!dstDisabled) {
+ // only create the adjustment rule if DST is enabled
+ Win32Native.RegistryTimeZoneInformation regZone = new Win32Native.RegistryTimeZoneInformation(zone);
+ AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(regZone, DateTime.MinValue.Date, DateTime.MaxValue.Date, zone.Bias);
+ if (rule != null) {
+ m_adjustmentRules = new AdjustmentRule[1];
+ m_adjustmentRules[0] = rule;
+ }
+ }
+
+ ValidateTimeZoneInfo(m_id, m_baseUtcOffset, m_adjustmentRules, out m_supportsDaylightSavingTime);
+ m_displayName = zone.StandardName;
+ m_standardDisplayName = zone.StandardName;
+ m_daylightDisplayName = zone.DaylightName;
+ }
+#endif // FEATURE_WIN32_REGISTRY
+
+#if PLATFORM_UNIX
+ private TimeZoneInfo(byte[] data, string id, Boolean dstDisabled)
+ {
+ TZifHead t;
+ DateTime[] dts;
+ Byte[] typeOfLocalTime;
+ TZifType[] transitionType;
+ String zoneAbbreviations;
+ Boolean[] StandardTime;
+ Boolean[] GmtTime;
+ string futureTransitionsPosixFormat;
+
+ // parse the raw TZif bytes; this method can throw ArgumentException when the data is malformed.
+ TZif_ParseRaw(data, out t, out dts, out typeOfLocalTime, out transitionType, out zoneAbbreviations, out StandardTime, out GmtTime, out futureTransitionsPosixFormat);
+
+ m_id = id;
+ m_displayName = c_localId;
+ m_baseUtcOffset = TimeSpan.Zero;
+
+ // find the best matching baseUtcOffset and display strings based on the current utcNow value.
+ // NOTE: read the display strings from the the tzfile now in case they can't be loaded later
+ // from the globalization data.
+ DateTime utcNow = DateTime.UtcNow;
+ for (int i = 0; i < dts.Length && dts[i] <= utcNow; i++) {
+ int type = typeOfLocalTime[i];
+ if (!transitionType[type].IsDst) {
+ m_baseUtcOffset = transitionType[type].UtcOffset;
+ m_standardDisplayName = TZif_GetZoneAbbreviation(zoneAbbreviations, transitionType[type].AbbreviationIndex);
+ }
+ else {
+ m_daylightDisplayName = TZif_GetZoneAbbreviation(zoneAbbreviations, transitionType[type].AbbreviationIndex);
+ }
+ }
+
+ if (dts.Length == 0) {
+ // time zones like Africa/Bujumbura and Etc/GMT* have no transition times but still contain
+ // TZifType entries that may contain a baseUtcOffset and display strings
+ for (int i = 0; i < transitionType.Length; i++) {
+ if (!transitionType[i].IsDst) {
+ m_baseUtcOffset = transitionType[i].UtcOffset;
+ m_standardDisplayName = TZif_GetZoneAbbreviation(zoneAbbreviations, transitionType[i].AbbreviationIndex);
+ }
+ else {
+ m_daylightDisplayName = TZif_GetZoneAbbreviation(zoneAbbreviations, transitionType[i].AbbreviationIndex);
+ }
+ }
+ }
+ m_displayName = m_standardDisplayName;
+
+ GetDisplayName(Interop.GlobalizationInterop.TimeZoneDisplayNameType.Generic, ref m_displayName);
+ GetDisplayName(Interop.GlobalizationInterop.TimeZoneDisplayNameType.Standard, ref m_standardDisplayName);
+ GetDisplayName(Interop.GlobalizationInterop.TimeZoneDisplayNameType.DaylightSavings, ref m_daylightDisplayName);
+
+ // TZif supports seconds-level granularity with offsets but TimeZoneInfo only supports minutes since it aligns
+ // with DateTimeOffset, SQL Server, and the W3C XML Specification
+ if (m_baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0) {
+ m_baseUtcOffset = new TimeSpan(m_baseUtcOffset.Hours, m_baseUtcOffset.Minutes, 0);
+ }
+
+ if (!dstDisabled) {
+ // only create the adjustment rule if DST is enabled
+ TZif_GenerateAdjustmentRules(out m_adjustmentRules, m_baseUtcOffset, dts, typeOfLocalTime, transitionType, StandardTime, GmtTime, futureTransitionsPosixFormat);
+ }
+
+ ValidateTimeZoneInfo(m_id, m_baseUtcOffset, m_adjustmentRules, out m_supportsDaylightSavingTime);
+ }
+
+ private void GetDisplayName(Interop.GlobalizationInterop.TimeZoneDisplayNameType nameType, ref string displayName)
+ {
+ string timeZoneDisplayName;
+ bool result = Interop.CallStringMethod(
+ (locale, id, type, stringBuilder) => Interop.GlobalizationInterop.GetTimeZoneDisplayName(
+ locale,
+ id,
+ type,
+ stringBuilder,
+ stringBuilder.Capacity),
+ CultureInfo.CurrentUICulture.Name,
+ m_id,
+ nameType,
+ out timeZoneDisplayName);
+
+ // If there is an unknown error, don't set the displayName field.
+ // It will be set to the abbreviation that was read out of the tzfile.
+ if (result)
+ {
+ displayName = timeZoneDisplayName;
+ }
+ }
+
+#endif // PLATFORM_UNIX
+
+ private TimeZoneInfo(
+ String id,
+ TimeSpan baseUtcOffset,
+ String displayName,
+ String standardDisplayName,
+ String daylightDisplayName,
+ AdjustmentRule [] adjustmentRules,
+ Boolean disableDaylightSavingTime) {
+
+ Boolean adjustmentRulesSupportDst;
+ ValidateTimeZoneInfo(id, baseUtcOffset, adjustmentRules, out adjustmentRulesSupportDst);
+
+ if (!disableDaylightSavingTime && adjustmentRules != null && adjustmentRules.Length > 0) {
+ m_adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone();
+ }
+
+ m_id = id;
+ m_baseUtcOffset = baseUtcOffset;
+ m_displayName = displayName;
+ m_standardDisplayName = standardDisplayName;
+ m_daylightDisplayName = (disableDaylightSavingTime ? null : daylightDisplayName);
+ m_supportsDaylightSavingTime = adjustmentRulesSupportDst && !disableDaylightSavingTime;
+ }
+
+ // -------- SECTION: factory methods -----------------*
+
+ //
+ // CreateCustomTimeZone -
+ //
+ // returns a simple TimeZoneInfo instance that does
+ // not support Daylight Saving Time
+ //
+ static public TimeZoneInfo CreateCustomTimeZone(
+ String id,
+ TimeSpan baseUtcOffset,
+ String displayName,
+ String standardDisplayName) {
+
+ return new TimeZoneInfo(
+ id,
+ baseUtcOffset,
+ displayName,
+ standardDisplayName,
+ standardDisplayName,
+ null,
+ false);
+ }
+
+ //
+ // CreateCustomTimeZone -
+ //
+ // returns a TimeZoneInfo instance that may
+ // support Daylight Saving Time
+ //
+ static public TimeZoneInfo CreateCustomTimeZone(
+ String id,
+ TimeSpan baseUtcOffset,
+ String displayName,
+ String standardDisplayName,
+ String daylightDisplayName,
+ AdjustmentRule [] adjustmentRules) {
+
+ return new TimeZoneInfo(
+ id,
+ baseUtcOffset,
+ displayName,
+ standardDisplayName,
+ daylightDisplayName,
+ adjustmentRules,
+ false);
+ }
+
+
+ //
+ // CreateCustomTimeZone -
+ //
+ // returns a TimeZoneInfo instance that may
+ // support Daylight Saving Time
+ //
+ // This class factory method is identical to the
+ // TimeZoneInfo private constructor
+ //
+ static public TimeZoneInfo CreateCustomTimeZone(
+ String id,
+ TimeSpan baseUtcOffset,
+ String displayName,
+ String standardDisplayName,
+ String daylightDisplayName,
+ AdjustmentRule [] adjustmentRules,
+ Boolean disableDaylightSavingTime) {
+
+ return new TimeZoneInfo(
+ id,
+ baseUtcOffset,
+ displayName,
+ standardDisplayName,
+ daylightDisplayName,
+ adjustmentRules,
+ disableDaylightSavingTime);
+ }
+
+
+
+ // ----- SECTION: private serialization instance methods ----------------*
+
+ void IDeserializationCallback.OnDeserialization(Object sender) {
+ try {
+ Boolean adjustmentRulesSupportDst;
+ ValidateTimeZoneInfo(m_id, m_baseUtcOffset, m_adjustmentRules, out adjustmentRulesSupportDst);
+
+ if (adjustmentRulesSupportDst != m_supportsDaylightSavingTime) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_CorruptField", "SupportsDaylightSavingTime"));
+ }
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ catch (InvalidTimeZoneException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ info.AddValue("Id", m_id);
+ info.AddValue("DisplayName", m_displayName);
+ info.AddValue("StandardName", m_standardDisplayName);
+ info.AddValue("DaylightName", m_daylightDisplayName);
+ info.AddValue("BaseUtcOffset", m_baseUtcOffset);
+ info.AddValue("AdjustmentRules", m_adjustmentRules);
+ info.AddValue("SupportsDaylightSavingTime", m_supportsDaylightSavingTime);
+ }
+
+
+ TimeZoneInfo(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+
+ m_id = (String)info.GetValue("Id", typeof(String));
+ m_displayName = (String)info.GetValue("DisplayName", typeof(String));
+ m_standardDisplayName = (String)info.GetValue("StandardName", typeof(String));
+ m_daylightDisplayName = (String)info.GetValue("DaylightName", typeof(String));
+ m_baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan));
+ m_adjustmentRules = (AdjustmentRule[])info.GetValue("AdjustmentRules", typeof(AdjustmentRule[]));
+ m_supportsDaylightSavingTime = (Boolean)info.GetValue("SupportsDaylightSavingTime", typeof(Boolean));
+ }
+
+
+
+ // ----- SECTION: internal instance utility methods ----------------*
+
+
+ private AdjustmentRule GetAdjustmentRuleForTime(DateTime dateTime, bool dateTimeisUtc = false) {
+ if (m_adjustmentRules == null || m_adjustmentRules.Length == 0) {
+ return null;
+ }
+
+ // Only check the whole-date portion of the dateTime for DateTimeKind.Unspecified rules -
+ // This is because the AdjustmentRule DateStart & DateEnd are stored as
+ // Date-only values {4/2/2006 - 10/28/2006} but actually represent the
+ // time span {4/2/2006@00:00:00.00000 - 10/28/2006@23:59:59.99999}
+ DateTime date;
+ if (dateTimeisUtc)
+ {
+ date = (dateTime + BaseUtcOffset).Date;
+ }
+ else
+ {
+ date = dateTime.Date;
+ }
+
+ for (int i = 0; i < m_adjustmentRules.Length; i++) {
+ AdjustmentRule rule = m_adjustmentRules[i];
+ AdjustmentRule previousRule = i > 0 ? m_adjustmentRules[i - 1] : rule;
+ if (IsAdjustmentRuleValid(rule, previousRule, dateTime, date, dateTimeisUtc)) {
+ return rule;
+ }
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Determines if 'rule' is the correct AdjustmentRule for the given dateTime.
+ /// </summary>
+ private bool IsAdjustmentRuleValid(AdjustmentRule rule, AdjustmentRule previousRule,
+ DateTime dateTime, DateTime dateOnly, bool dateTimeisUtc)
+ {
+ bool isAfterStart;
+ if (rule.DateStart.Kind == DateTimeKind.Utc)
+ {
+ DateTime dateTimeToCompare;
+ if (dateTimeisUtc)
+ {
+ dateTimeToCompare = dateTime;
+ }
+ else
+ {
+ dateTimeToCompare = ConvertToUtc(dateTime,
+ // use the previous rule to compute the dateTimeToCompare, since the time daylight savings "switches"
+ // is based on the previous rule's offset
+ previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta);
+ }
+
+ isAfterStart = dateTimeToCompare >= rule.DateStart;
+ }
+ else
+ {
+ // if the rule's DateStart is Unspecified, then use the whole-date portion
+ isAfterStart = dateOnly >= rule.DateStart;
+ }
+
+ if (!isAfterStart)
+ {
+ return false;
+ }
+
+ bool isBeforeEnd;
+ if (rule.DateEnd.Kind == DateTimeKind.Utc)
+ {
+ DateTime dateTimeToCompare;
+ if (dateTimeisUtc)
+ {
+ dateTimeToCompare = dateTime;
+ }
+ else
+ {
+ dateTimeToCompare = ConvertToUtc(dateTime, rule.DaylightDelta, rule.BaseUtcOffsetDelta);
+ }
+
+ isBeforeEnd = dateTimeToCompare <= rule.DateEnd;
+ }
+ else
+ {
+ // if the rule's DateEnd is Unspecified, then use the whole-date portion
+ isBeforeEnd = dateOnly <= rule.DateEnd;
+ }
+
+ return isBeforeEnd;
+ }
+
+ /// <summary>
+ /// Converts the dateTime to UTC using the specified deltas.
+ /// </summary>
+ private DateTime ConvertToUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta)
+ {
+ return ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: true);
+ }
+
+ /// <summary>
+ /// Converts the dateTime from UTC using the specified deltas.
+ /// </summary>
+ private DateTime ConvertFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta)
+ {
+ return ConvertToFromUtc(dateTime, daylightDelta, baseUtcOffsetDelta, convertToUtc: false);
+ }
+
+ /// <summary>
+ /// Converts the dateTime to or from UTC using the specified deltas.
+ /// </summary>
+ private DateTime ConvertToFromUtc(DateTime dateTime, TimeSpan daylightDelta, TimeSpan baseUtcOffsetDelta, bool convertToUtc)
+ {
+ TimeSpan offset = BaseUtcOffset + daylightDelta + baseUtcOffsetDelta;
+ if (convertToUtc)
+ {
+ offset = offset.Negate();
+ }
+
+ long ticks = dateTime.Ticks + offset.Ticks;
+
+ DateTime result;
+ if (ticks > DateTime.MaxValue.Ticks)
+ {
+ result = DateTime.MaxValue;
+ }
+ else if (ticks < DateTime.MinValue.Ticks)
+ {
+ result = DateTime.MinValue;
+ }
+ else
+ {
+ result = new DateTime(ticks);
+ }
+
+ return result;
+ }
+
+ // ----- SECTION: internal static utility methods ----------------*
+
+ //
+ // CheckDaylightSavingTimeNotSupported -
+ //
+ // Helper function to check if the current TimeZoneInformation struct does not support DST. This
+ // check returns true when the DaylightDate == StandardDate
+ //
+ // This check is only meant to be used for "Local".
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private Boolean CheckDaylightSavingTimeNotSupported(Win32Native.TimeZoneInformation timeZone) {
+ return ( timeZone.DaylightDate.Year == timeZone.StandardDate.Year
+ && timeZone.DaylightDate.Month == timeZone.StandardDate.Month
+ && timeZone.DaylightDate.DayOfWeek == timeZone.StandardDate.DayOfWeek
+ && timeZone.DaylightDate.Day == timeZone.StandardDate.Day
+ && timeZone.DaylightDate.Hour == timeZone.StandardDate.Hour
+ && timeZone.DaylightDate.Minute == timeZone.StandardDate.Minute
+ && timeZone.DaylightDate.Second == timeZone.StandardDate.Second
+ && timeZone.DaylightDate.Milliseconds == timeZone.StandardDate.Milliseconds);
+ }
+
+
+ //
+ // ConvertUtcToTimeZone -
+ //
+ // Helper function that converts a dateTime from UTC into the destinationTimeZone
+ //
+ // * returns DateTime.MaxValue when the converted value is too large
+ // * returns DateTime.MinValue when the converted value is too small
+ //
+ static private DateTime ConvertUtcToTimeZone(Int64 ticks, TimeZoneInfo destinationTimeZone, out Boolean isAmbiguousLocalDst) {
+ DateTime utcConverted;
+ DateTime localConverted;
+
+ // utcConverted is used to calculate the UTC offset in the destinationTimeZone
+ if (ticks > DateTime.MaxValue.Ticks) {
+ utcConverted = DateTime.MaxValue;
+ }
+ else if (ticks < DateTime.MinValue.Ticks) {
+ utcConverted = DateTime.MinValue;
+ }
+ else {
+ utcConverted = new DateTime(ticks);
+ }
+
+ // verify the time is between MinValue and MaxValue in the new time zone
+ TimeSpan offset = GetUtcOffsetFromUtc(utcConverted, destinationTimeZone, out isAmbiguousLocalDst);
+ ticks += offset.Ticks;
+
+ if (ticks > DateTime.MaxValue.Ticks) {
+ localConverted = DateTime.MaxValue;
+ }
+ else if (ticks < DateTime.MinValue.Ticks) {
+ localConverted = DateTime.MinValue;
+ }
+ else {
+ localConverted = new DateTime(ticks);
+ }
+ return localConverted;
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ //
+ // CreateAdjustmentRuleFromTimeZoneInformation-
+ //
+ // Converts a Win32Native.RegistryTimeZoneInformation (REG_TZI_FORMAT struct) to an AdjustmentRule
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private AdjustmentRule CreateAdjustmentRuleFromTimeZoneInformation(Win32Native.RegistryTimeZoneInformation timeZoneInformation, DateTime startDate, DateTime endDate, int defaultBaseUtcOffset) {
+ AdjustmentRule rule;
+ bool supportsDst = (timeZoneInformation.StandardDate.Month != 0);
+
+ if (!supportsDst) {
+ if (timeZoneInformation.Bias == defaultBaseUtcOffset)
+ {
+ // this rule will not contain any information to be used to adjust dates. just ignore it
+ return null;
+ }
+
+ return rule = AdjustmentRule.CreateAdjustmentRule(
+ startDate,
+ endDate,
+ TimeSpan.Zero, // no daylight saving transition
+ TransitionTime.CreateFixedDateRule(DateTime.MinValue, 1, 1),
+ TransitionTime.CreateFixedDateRule(DateTime.MinValue.AddMilliseconds(1), 1, 1),
+ new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0), // Bias delta is all what we need from this rule
+ noDaylightTransitions: false);
+ }
+
+ //
+ // Create an AdjustmentRule with TransitionTime objects
+ //
+ TransitionTime daylightTransitionStart;
+ if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionStart, true /* start date */)) {
+ return null;
+ }
+
+ TransitionTime daylightTransitionEnd;
+ if (!TransitionTimeFromTimeZoneInformation(timeZoneInformation, out daylightTransitionEnd, false /* end date */)) {
+ return null;
+ }
+
+ if (daylightTransitionStart.Equals(daylightTransitionEnd)) {
+ // this happens when the time zone does support DST but the OS has DST disabled
+ return null;
+ }
+
+ rule = AdjustmentRule.CreateAdjustmentRule(
+ startDate,
+ endDate,
+ new TimeSpan(0, -timeZoneInformation.DaylightBias, 0),
+ (TransitionTime)daylightTransitionStart,
+ (TransitionTime)daylightTransitionEnd,
+ new TimeSpan(0, defaultBaseUtcOffset - timeZoneInformation.Bias, 0),
+ noDaylightTransitions: false);
+
+ return rule;
+ }
+
+ //
+ // FindIdFromTimeZoneInformation -
+ //
+ // Helper function that searches the registry for a time zone entry
+ // that matches the TimeZoneInformation struct
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private String FindIdFromTimeZoneInformation(Win32Native.TimeZoneInformation timeZone, out Boolean dstDisabled) {
+ dstDisabled = false;
+
+ try {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList));
+ permSet.Assert();
+
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(
+ c_timeZonesRegistryHive,
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.Default,
+ System.Security.AccessControl.RegistryRights.ReadKey
+#else
+ false
+#endif
+ )) {
+
+ if (key == null) {
+ return null;
+ }
+ foreach (string keyName in key.GetSubKeyNames()) {
+ if (TryCompareTimeZoneInformationToRegistry(timeZone, keyName, out dstDisabled)) {
+ return keyName;
+ }
+ }
+ }
+ }
+ finally {
+ PermissionSet.RevertAssert();
+ }
+ return null;
+ }
+#endif // FEATURE_WIN32_REGISTRY
+
+
+ //
+ // GetDaylightTime -
+ //
+ // Helper function that returns a DaylightTime from a year and AdjustmentRule
+ //
+ private DaylightTime GetDaylightTime(Int32 year, AdjustmentRule rule) {
+ TimeSpan delta = rule.DaylightDelta;
+ DateTime startTime;
+ DateTime endTime;
+ if (rule.NoDaylightTransitions)
+ {
+ // NoDaylightTransitions rules don't use DaylightTransition Start and End, instead
+ // the DateStart and DateEnd are UTC times that represent when daylight savings time changes.
+ // Convert the UTC times into adjusted time zone times.
+
+ // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule
+ AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule);
+ startTime = ConvertFromUtc(rule.DateStart, previousRule.DaylightDelta, previousRule.BaseUtcOffsetDelta);
+
+ endTime = ConvertFromUtc(rule.DateEnd, rule.DaylightDelta, rule.BaseUtcOffsetDelta);
+ }
+ else
+ {
+ startTime = TransitionTimeToDateTime(year, rule.DaylightTransitionStart);
+ endTime = TransitionTimeToDateTime(year, rule.DaylightTransitionEnd);
+ }
+ return new DaylightTime(startTime, endTime, delta);
+ }
+
+ //
+ // GetIsDaylightSavings -
+ //
+ // Helper function that checks if a given dateTime is in Daylight Saving Time (DST)
+ // This function assumes the dateTime and AdjustmentRule are both in the same time zone
+ //
+ static private Boolean GetIsDaylightSavings(DateTime time, AdjustmentRule rule, DaylightTime daylightTime, TimeZoneInfoOptions flags) {
+ if (rule == null) {
+ return false;
+ }
+
+ DateTime startTime;
+ DateTime endTime;
+
+ if (time.Kind == DateTimeKind.Local) {
+ // startTime and endTime represent the period from either the start of DST to the end and ***includes*** the
+ // potentially overlapped times
+ startTime = rule.IsStartDateMarkerForBeginningOfYear() ? new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : daylightTime.Start + daylightTime.Delta;
+ endTime = rule.IsEndDateMarkerForEndOfYear() ? new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : daylightTime.End;
+ }
+ else {
+ // startTime and endTime represent the period from either the start of DST to the end and
+ // ***does not include*** the potentially overlapped times
+ //
+ // -=-=-=-=-=- Pacific Standard Time -=-=-=-=-=-=-
+ // April 2, 2006 October 29, 2006
+ // 2AM 3AM 1AM 2AM
+ // | +1 hr | | -1 hr |
+ // | <invalid time> | | <ambiguous time> |
+ // [========== DST ========>)
+ //
+ // -=-=-=-=-=- Some Weird Time Zone -=-=-=-=-=-=-
+ // April 2, 2006 October 29, 2006
+ // 1AM 2AM 2AM 3AM
+ // | -1 hr | | +1 hr |
+ // | <ambiguous time> | | <invalid time> |
+ // [======== DST ========>)
+ //
+ Boolean invalidAtStart = rule.DaylightDelta > TimeSpan.Zero;
+ startTime = rule.IsStartDateMarkerForBeginningOfYear() ? new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) : daylightTime.Start + (invalidAtStart ? rule.DaylightDelta : TimeSpan.Zero); /* FUTURE: - rule.StandardDelta; */
+ endTime = rule.IsEndDateMarkerForEndOfYear() ? new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) : daylightTime.End + (invalidAtStart ? -rule.DaylightDelta : TimeSpan.Zero);
+ }
+
+ Boolean isDst = CheckIsDst(startTime, time, endTime, false, rule);
+
+ // If this date was previously converted from a UTC date and we were able to detect that the local
+ // DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity.
+ if (isDst && time.Kind == DateTimeKind.Local) {
+ // For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the
+ // clock back. It is theoretically possible to have a positive delta, (which would really be daylight
+ // reduction time), where you would have to wind the clock back in the begnning.
+ if (GetIsAmbiguousTime(time, rule, daylightTime)) {
+ isDst = time.IsAmbiguousDaylightSavingTime();
+ }
+ }
+
+ return isDst;
+ }
+
+ /// <summary>
+ /// Gets the offset that should be used to calculate DST start times from a UTC time.
+ /// </summary>
+ private TimeSpan GetDaylightSavingsStartOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule)
+ {
+ if (rule.NoDaylightTransitions)
+ {
+ // use the previous rule to calculate the startTime, since the DST change happens w.r.t. the previous rule
+ AdjustmentRule previousRule = GetPreviousAdjustmentRule(rule);
+ return baseUtcOffset + previousRule.BaseUtcOffsetDelta + previousRule.DaylightDelta;
+ }
+ else
+ {
+ return baseUtcOffset + rule.BaseUtcOffsetDelta; /* FUTURE: + rule.StandardDelta; */
+ }
+ }
+
+ /// <summary>
+ /// Gets the offset that should be used to calculate DST end times from a UTC time.
+ /// </summary>
+ private TimeSpan GetDaylightSavingsEndOffsetFromUtc(TimeSpan baseUtcOffset, AdjustmentRule rule)
+ {
+ // NOTE: even NoDaylightTransitions rules use this logic since DST ends w.r.t. the current rule
+
+ return baseUtcOffset + rule.BaseUtcOffsetDelta + rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */
+ }
+
+ //
+ // GetIsDaylightSavingsFromUtc -
+ //
+ // Helper function that checks if a given dateTime is in Daylight Saving Time (DST)
+ // This function assumes the dateTime is in UTC and AdjustmentRule is in a different time zone
+ //
+ static private Boolean GetIsDaylightSavingsFromUtc(DateTime time, Int32 Year, TimeSpan utc, AdjustmentRule rule, out Boolean isAmbiguousLocalDst, TimeZoneInfo zone) {
+ isAmbiguousLocalDst = false;
+
+ if (rule == null) {
+ return false;
+ }
+
+
+ // Get the daylight changes for the year of the specified time.
+ DaylightTime daylightTime = zone.GetDaylightTime(Year, rule);
+
+ // The start and end times represent the range of universal times that are in DST for that year.
+ // Within that there is an ambiguous hour, usually right at the end, but at the beginning in
+ // the unusual case of a negative daylight savings delta.
+ // We need to handle the case if the current rule has daylight saving end by the end of year. If so, we need to check if next year starts with daylight saving on
+ // and get the actual daylight saving end time. Here is example for such case:
+ // Converting the UTC datetime "12/31/2011 8:00:00 PM" to "(UTC+03:00) Moscow, St. Petersburg, Volgograd (RTZ 2)" zone.
+ // In 2011 the daylight saving will go through the end of the year. If we use the end of 2011 as the daylight saving end,
+ // that will fail the conversion because the UTC time +4 hours (3 hours for the zone UTC offset and 1 hour for daylight saving) will move us to the next year "1/1/2012 12:00 AM",
+ // checking against the end of 2011 will tell we are not in daylight saving which is wrong and the conversion will be off by one hour.
+ // Note we handle the similar case when rule year start with daylight saving and previous year end with daylight saving.
+
+ bool ignoreYearAdjustment = false;
+ TimeSpan dstStartOffset = zone.GetDaylightSavingsStartOffsetFromUtc(utc, rule);
+ DateTime startTime;
+ if (rule.IsStartDateMarkerForBeginningOfYear() && daylightTime.Start.Year > DateTime.MinValue.Year) {
+ AdjustmentRule previousYearRule = zone.GetAdjustmentRuleForTime(new DateTime(daylightTime.Start.Year - 1, 12, 31));
+ if (previousYearRule != null && previousYearRule.IsEndDateMarkerForEndOfYear()) {
+ DaylightTime previousDaylightTime = zone.GetDaylightTime(daylightTime.Start.Year - 1, previousYearRule);
+ startTime = previousDaylightTime.Start - utc - previousYearRule.BaseUtcOffsetDelta;
+ ignoreYearAdjustment = true;
+ } else {
+ startTime = new DateTime(daylightTime.Start.Year, 1, 1, 0, 0, 0) - dstStartOffset;
+ }
+ } else {
+ startTime = daylightTime.Start - dstStartOffset;
+ }
+
+ TimeSpan dstEndOffset = zone.GetDaylightSavingsEndOffsetFromUtc(utc, rule);
+ DateTime endTime;
+ if (rule.IsEndDateMarkerForEndOfYear() && daylightTime.End.Year < DateTime.MaxValue.Year) {
+ AdjustmentRule nextYearRule = zone.GetAdjustmentRuleForTime(new DateTime(daylightTime.End.Year + 1, 1, 1));
+ if (nextYearRule != null && nextYearRule.IsStartDateMarkerForBeginningOfYear()) {
+ if (nextYearRule.IsEndDateMarkerForEndOfYear()) {// next year end with daylight saving on too
+ endTime = new DateTime(daylightTime.End.Year + 1, 12, 31) - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta;
+ } else {
+ DaylightTime nextdaylightTime = zone.GetDaylightTime(daylightTime.End.Year + 1, nextYearRule);
+ endTime = nextdaylightTime.End - utc - nextYearRule.BaseUtcOffsetDelta - nextYearRule.DaylightDelta;
+ }
+ ignoreYearAdjustment = true;
+ } else {
+ endTime = new DateTime(daylightTime.End.Year + 1, 1, 1, 0, 0, 0).AddTicks(-1) - dstEndOffset;
+ }
+ } else {
+ endTime = daylightTime.End - dstEndOffset;
+ }
+
+ DateTime ambiguousStart;
+ DateTime ambiguousEnd;
+ if (daylightTime.Delta.Ticks > 0) {
+ ambiguousStart = endTime - daylightTime.Delta;
+ ambiguousEnd = endTime;
+ } else {
+ ambiguousStart = startTime;
+ ambiguousEnd = startTime - daylightTime.Delta;
+ }
+
+ Boolean isDst = CheckIsDst(startTime, time, endTime, ignoreYearAdjustment, rule);
+
+ // See if the resulting local time becomes ambiguous. This must be captured here or the
+ // DateTime will not be able to round-trip back to UTC accurately.
+ if (isDst) {
+ isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd);
+
+ if (!isAmbiguousLocalDst && ambiguousStart.Year != ambiguousEnd.Year) {
+ // there exists an extreme corner case where the start or end period is on a year boundary and
+ // because of this the comparison above might have been performed for a year-early or a year-later
+ // than it should have been.
+ DateTime ambiguousStartModified;
+ DateTime ambiguousEndModified;
+ try {
+ ambiguousStartModified = ambiguousStart.AddYears(1);
+ ambiguousEndModified = ambiguousEnd.AddYears(1);
+ isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd);
+ }
+ catch (ArgumentOutOfRangeException) {}
+
+ if (!isAmbiguousLocalDst) {
+ try {
+ ambiguousStartModified = ambiguousStart.AddYears(-1);
+ ambiguousEndModified = ambiguousEnd.AddYears(-1);
+ isAmbiguousLocalDst = (time >= ambiguousStart && time < ambiguousEnd);
+ }
+ catch (ArgumentOutOfRangeException) {}
+ }
+
+ }
+ }
+
+ return isDst;
+ }
+
+
+ static private Boolean CheckIsDst(DateTime startTime, DateTime time, DateTime endTime, bool ignoreYearAdjustment, AdjustmentRule rule) {
+ Boolean isDst;
+
+ // NoDaylightTransitions AdjustmentRules should never get their year adjusted since they adjust the offset for the
+ // entire time period - which may be for multiple years
+ if (!ignoreYearAdjustment && !rule.NoDaylightTransitions) {
+ int startTimeYear = startTime.Year;
+ int endTimeYear = endTime.Year;
+
+ if (startTimeYear != endTimeYear) {
+ endTime = endTime.AddYears(startTimeYear - endTimeYear);
+ }
+
+ int timeYear = time.Year;
+
+ if (startTimeYear != timeYear) {
+ time = time.AddYears(startTimeYear - timeYear);
+ }
+ }
+
+ if (startTime > endTime) {
+ // In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
+ // Note, the summer in the southern hemisphere begins late in the year.
+ isDst = (time < endTime || time >= startTime);
+ }
+ else if (rule.NoDaylightTransitions) {
+ // In NoDaylightTransitions AdjustmentRules, the startTime is always before the endTime,
+ // and both the start and end times are inclusive
+ isDst = (time >= startTime && time <= endTime);
+ }
+ else {
+ // In northern hemisphere, the daylight saving time starts in the middle of the year.
+ isDst = (time >= startTime && time < endTime);
+ }
+ return isDst;
+ }
+
+
+ //
+ // GetIsAmbiguousTime(DateTime dateTime, AdjustmentRule rule, DaylightTime daylightTime) -
+ //
+ // returns true when the dateTime falls into an ambiguous time range.
+ // For example, in Pacific Standard Time on Sunday, October 29, 2006 time jumps from
+ // 2AM to 1AM. This means the timeline on Sunday proceeds as follows:
+ // 12AM ... [1AM ... 1:59:59AM -> 1AM ... 1:59:59AM] 2AM ... 3AM ...
+ //
+ // In this example, any DateTime values that fall into the [1AM - 1:59:59AM] range
+ // are ambiguous; as it is unclear if these times are in Daylight Saving Time.
+ //
+ static private Boolean GetIsAmbiguousTime(DateTime time, AdjustmentRule rule, DaylightTime daylightTime) {
+ Boolean isAmbiguous = false;
+ if (rule == null || rule.DaylightDelta == TimeSpan.Zero) {
+ return isAmbiguous;
+ }
+
+ DateTime startAmbiguousTime;
+ DateTime endAmbiguousTime;
+
+ // if at DST start we transition forward in time then there is an ambiguous time range at the DST end
+ if (rule.DaylightDelta > TimeSpan.Zero) {
+ if (rule.IsEndDateMarkerForEndOfYear()) { // year end with daylight on so there is no ambiguous time
+ return false;
+ }
+ startAmbiguousTime = daylightTime.End;
+ endAmbiguousTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */
+ }
+ else {
+ if (rule.IsStartDateMarkerForBeginningOfYear()) { // year start with daylight on so there is no ambiguous time
+ return false;
+ }
+ startAmbiguousTime = daylightTime.Start;
+ endAmbiguousTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */
+ }
+
+ isAmbiguous = (time >= endAmbiguousTime && time < startAmbiguousTime);
+
+ if (!isAmbiguous && startAmbiguousTime.Year != endAmbiguousTime.Year) {
+ // there exists an extreme corner case where the start or end period is on a year boundary and
+ // because of this the comparison above might have been performed for a year-early or a year-later
+ // than it should have been.
+ DateTime startModifiedAmbiguousTime;
+ DateTime endModifiedAmbiguousTime;
+ try {
+ startModifiedAmbiguousTime = startAmbiguousTime.AddYears(1);
+ endModifiedAmbiguousTime = endAmbiguousTime.AddYears(1);
+ isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime);
+ }
+ catch (ArgumentOutOfRangeException) {}
+
+ if (!isAmbiguous) {
+ try {
+ startModifiedAmbiguousTime = startAmbiguousTime.AddYears(-1);
+ endModifiedAmbiguousTime = endAmbiguousTime.AddYears(-1);
+ isAmbiguous = (time >= endModifiedAmbiguousTime && time < startModifiedAmbiguousTime);
+ }
+ catch (ArgumentOutOfRangeException) {}
+ }
+ }
+ return isAmbiguous;
+ }
+
+
+
+ //
+ // GetIsInvalidTime -
+ //
+ // Helper function that checks if a given DateTime is in an invalid time ("time hole")
+ // A "time hole" occurs at a DST transition point when time jumps forward;
+ // For example, in Pacific Standard Time on Sunday, April 2, 2006 time jumps from
+ // 1:59:59.9999999 to 3AM. The time range 2AM to 2:59:59.9999999AM is the "time hole".
+ // A "time hole" is not limited to only occurring at the start of DST, and may occur at
+ // the end of DST as well.
+ //
+ static private Boolean GetIsInvalidTime(DateTime time, AdjustmentRule rule, DaylightTime daylightTime) {
+ Boolean isInvalid = false;
+ if (rule == null || rule.DaylightDelta == TimeSpan.Zero) {
+ return isInvalid;
+ }
+
+ DateTime startInvalidTime;
+ DateTime endInvalidTime;
+
+ // if at DST start we transition forward in time then there is an ambiguous time range at the DST end
+ if (rule.DaylightDelta < TimeSpan.Zero) {
+ // if the year ends with daylight saving on then there cannot be any time-hole's in that year.
+ if (rule.IsEndDateMarkerForEndOfYear())
+ return false;
+
+ startInvalidTime = daylightTime.End;
+ endInvalidTime = daylightTime.End - rule.DaylightDelta; /* FUTURE: + rule.StandardDelta; */
+ }
+ else {
+ // if the year starts with daylight saving on then there cannot be any time-hole's in that year.
+ if (rule.IsStartDateMarkerForBeginningOfYear())
+ return false;
+
+ startInvalidTime = daylightTime.Start;
+ endInvalidTime = daylightTime.Start + rule.DaylightDelta; /* FUTURE: - rule.StandardDelta; */
+ }
+
+ isInvalid = (time >= startInvalidTime && time < endInvalidTime);
+
+ if (!isInvalid && startInvalidTime.Year != endInvalidTime.Year) {
+ // there exists an extreme corner case where the start or end period is on a year boundary and
+ // because of this the comparison above might have been performed for a year-early or a year-later
+ // than it should have been.
+ DateTime startModifiedInvalidTime;
+ DateTime endModifiedInvalidTime;
+ try {
+ startModifiedInvalidTime = startInvalidTime.AddYears(1);
+ endModifiedInvalidTime = endInvalidTime.AddYears(1);
+ isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime);
+ }
+ catch (ArgumentOutOfRangeException) {}
+
+ if (!isInvalid) {
+ try {
+ startModifiedInvalidTime = startInvalidTime.AddYears(-1);
+ endModifiedInvalidTime = endInvalidTime.AddYears(-1);
+ isInvalid = (time >= startModifiedInvalidTime && time < endModifiedInvalidTime);
+ }
+ catch (ArgumentOutOfRangeException) {}
+ }
+ }
+ return isInvalid;
+ }
+
+
+
+ //
+ // GetLocalTimeZone -
+ //
+ // Helper function for retrieving the local system time zone.
+ //
+ // returns a new TimeZoneInfo instance
+ //
+ // may throw COMException, TimeZoneNotFoundException, InvalidTimeZoneException
+ //
+ // assumes cachedData lock is taken
+ //
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private TimeZoneInfo GetLocalTimeZone(CachedData cachedData) {
+
+
+#if FEATURE_WIN32_REGISTRY
+ String id = null;
+
+ //
+ // Try using the "kernel32!GetDynamicTimeZoneInformation" API to get the "id"
+ //
+ Win32Native.DynamicTimeZoneInformation dynamicTimeZoneInformation =
+ new Win32Native.DynamicTimeZoneInformation();
+
+ // call kernel32!GetDynamicTimeZoneInformation...
+ long result = UnsafeNativeMethods.GetDynamicTimeZoneInformation(out dynamicTimeZoneInformation);
+ if (result == Win32Native.TIME_ZONE_ID_INVALID) {
+ // return a dummy entry
+ return CreateCustomTimeZone(c_localId, TimeSpan.Zero, c_localId, c_localId);
+ }
+
+ Win32Native.TimeZoneInformation timeZoneInformation =
+ new Win32Native.TimeZoneInformation(dynamicTimeZoneInformation);
+
+ Boolean dstDisabled = dynamicTimeZoneInformation.DynamicDaylightTimeDisabled;
+
+ // check to see if we can use the key name returned from the API call
+ if (!String.IsNullOrEmpty(dynamicTimeZoneInformation.TimeZoneKeyName)) {
+ TimeZoneInfo zone;
+ Exception ex;
+
+ if (TryGetTimeZone(dynamicTimeZoneInformation.TimeZoneKeyName, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success) {
+ // successfully loaded the time zone from the registry
+ return zone;
+ }
+ }
+
+ // the key name was not returned or it pointed to a bogus entry - search for the entry ourselves
+ id = FindIdFromTimeZoneInformation(timeZoneInformation, out dstDisabled);
+
+ if (id != null) {
+ TimeZoneInfo zone;
+ Exception ex;
+ if (TryGetTimeZone(id, dstDisabled, out zone, out ex, cachedData) == TimeZoneInfoResult.Success) {
+ // successfully loaded the time zone from the registry
+ return zone;
+ }
+ }
+
+ // We could not find the data in the registry. Fall back to using
+ // the data from the Win32 API
+ return GetLocalTimeZoneFromWin32Data(timeZoneInformation, dstDisabled);
+
+#elif PLATFORM_UNIX // FEATURE_WIN32_REGISTRY
+ // Without Registry support, create the TimeZoneInfo from a TZ file
+ return GetLocalTimeZoneFromTzFile();
+#endif // FEATURE_WIN32_REGISTRY
+ }
+
+
+#if PLATFORM_UNIX
+ private static TimeZoneInfoResult TryGetTimeZoneByFile(string id, out TimeZoneInfo value, out Exception e)
+ {
+ value = null;
+ e = null;
+
+ string timeZoneDirectory = GetTimeZoneDirectory();
+ string timeZoneFilePath = Path.Combine(timeZoneDirectory, id);
+ byte[] rawData;
+ try
+ {
+ rawData = File.ReadAllBytes(timeZoneFilePath);
+ }
+ catch (UnauthorizedAccessException ex)
+ {
+ e = ex;
+ return TimeZoneInfoResult.SecurityException;
+ }
+ catch (FileNotFoundException ex)
+ {
+ e = ex;
+ return TimeZoneInfoResult.TimeZoneNotFoundException;
+ }
+ catch (DirectoryNotFoundException ex)
+ {
+ e = ex;
+ return TimeZoneInfoResult.TimeZoneNotFoundException;
+ }
+ catch (IOException ex)
+ {
+ e = new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_InvalidFileData", id, timeZoneFilePath), ex);
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+
+ value = GetTimeZoneFromTzData(rawData, id);
+
+ if (value == null)
+ {
+ e = new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_InvalidFileData", id, timeZoneFilePath));
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+
+ return TimeZoneInfoResult.Success;
+ }
+
+ /// <summary>
+ /// Returns a collection of TimeZone Id values from the zone.tab file in the timeZoneDirectory.
+ /// </summary>
+ /// <remarks>
+ /// Lines that start with # are comments and are skipped.
+ /// </remarks>
+ private static IEnumerable<string> GetTimeZoneIds(string timeZoneDirectory)
+ {
+ string[] zoneTabFileLines = null;
+ try
+ {
+ zoneTabFileLines = File.ReadAllLines(Path.Combine(timeZoneDirectory, c_zoneTabFileName));
+ }
+ catch (IOException) { }
+ catch (UnauthorizedAccessException) { }
+
+ List<string> timeZoneIds = new List<string>();
+ if (zoneTabFileLines != null)
+ {
+ foreach (string zoneTabFileLine in zoneTabFileLines)
+ {
+ if (!string.IsNullOrEmpty(zoneTabFileLine) && !zoneTabFileLine.StartsWith("#"))
+ {
+ // the format of the line is "country-code \t coordinates \t TimeZone Id \t comments"
+
+ int firstTabIndex = zoneTabFileLine.IndexOf('\t');
+ if (firstTabIndex != -1)
+ {
+ int secondTabIndex = zoneTabFileLine.IndexOf('\t', firstTabIndex + 1);
+ if (secondTabIndex != -1)
+ {
+ string timeZoneId;
+ int startIndex = secondTabIndex + 1;
+ int thirdTabIndex = zoneTabFileLine.IndexOf('\t', startIndex);
+ if (thirdTabIndex != -1)
+ {
+ int length = thirdTabIndex - startIndex;
+ timeZoneId = zoneTabFileLine.Substring(startIndex, length);
+ }
+ else
+ {
+ timeZoneId = zoneTabFileLine.Substring(startIndex);
+ }
+
+ if (!string.IsNullOrEmpty(timeZoneId))
+ {
+ timeZoneIds.Add(timeZoneId);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return timeZoneIds;
+ }
+
+ /// <summary>
+ /// Gets the tzfile raw data for the current 'local' time zone using the following rules.
+ /// 1. Read the TZ environment variable. If it is set, use it.
+ /// 2. Look for the data in /etc/localtime.
+ /// 3. Look for the data in GetTimeZoneDirectory()/localtime.
+ /// 4. Use UTC if all else fails.
+ /// </summary>
+ [SecurityCritical]
+ private static bool TryGetLocalTzFile(out byte[] rawData, out string id)
+ {
+ rawData = null;
+ id = null;
+ string tzVariable = GetTzEnvironmentVariable();
+
+ // If the env var is null, use the localtime file
+ if (tzVariable == null)
+ {
+ return
+ TryLoadTzFile("/etc/localtime", ref rawData, ref id) ||
+ TryLoadTzFile(Path.Combine(GetTimeZoneDirectory(), "localtime"), ref rawData, ref id);
+ }
+
+ // If it's empty, use UTC (TryGetLocalTzFile() should return false).
+ if (tzVariable.Length == 0)
+ {
+ return false;
+ }
+
+ // Otherwise, use the path from the env var. If it's not absolute, make it relative
+ // to the system timezone directory
+ string tzFilePath;
+ if (tzVariable[0] != '/')
+ {
+ id = tzVariable;
+ tzFilePath = Path.Combine(GetTimeZoneDirectory(), tzVariable);
+ }
+ else
+ {
+ tzFilePath = tzVariable;
+ }
+ return TryLoadTzFile(tzFilePath, ref rawData, ref id);
+ }
+
+ private static string GetTzEnvironmentVariable()
+ {
+ string result = Environment.GetEnvironmentVariable(c_timeZoneEnvironmentVariable);
+ if (!string.IsNullOrEmpty(result))
+ {
+ if (result[0] == ':')
+ {
+ // strip off the ':' prefix
+ result = result.Substring(1);
+ }
+ }
+
+ return result;
+ }
+
+ private static bool TryLoadTzFile(string tzFilePath, ref byte[] rawData, ref string id)
+ {
+ if (File.Exists(tzFilePath))
+ {
+ try
+ {
+ rawData = File.ReadAllBytes(tzFilePath);
+ if (string.IsNullOrEmpty(id))
+ {
+ id = FindTimeZoneIdUsingReadLink(tzFilePath);
+
+ if (string.IsNullOrEmpty(id))
+ {
+ id = FindTimeZoneId(rawData);
+ }
+ }
+ return true;
+ }
+ catch (IOException) { }
+ catch (SecurityException) { }
+ catch (UnauthorizedAccessException) { }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Finds the time zone id by using 'readlink' on the path to see if tzFilePath is
+ /// a symlink to a file
+ /// </summary>
+ [SecuritySafeCritical]
+ private static string FindTimeZoneIdUsingReadLink(string tzFilePath)
+ {
+ string id = null;
+
+ StringBuilder symlinkPathBuilder = StringBuilderCache.Acquire(Path.MaxPath);
+ bool result = Interop.GlobalizationInterop.ReadLink(tzFilePath, symlinkPathBuilder, (uint)symlinkPathBuilder.Capacity);
+ if (result)
+ {
+ string symlinkPath = StringBuilderCache.GetStringAndRelease(symlinkPathBuilder);
+ // time zone Ids have to point under the time zone directory
+ string timeZoneDirectory = GetTimeZoneDirectory();
+ if (symlinkPath.StartsWith(timeZoneDirectory))
+ {
+ id = symlinkPath.Substring(timeZoneDirectory.Length);
+ }
+ }
+ else
+ {
+ StringBuilderCache.Release(symlinkPathBuilder);
+ }
+
+ return id;
+ }
+
+ /// <summary>
+ /// Find the time zone id by searching all the tzfiles for the one that matches rawData
+ /// and return its file name.
+ /// </summary>
+ private static string FindTimeZoneId(byte[] rawData)
+ {
+ // default to "Local" if we can't find the right tzfile
+ string id = c_localId;
+ string timeZoneDirectory = GetTimeZoneDirectory();
+ string localtimeFilePath = Path.Combine(timeZoneDirectory, "localtime");
+ string posixrulesFilePath = Path.Combine(timeZoneDirectory, "posixrules");
+ byte[] buffer = new byte[rawData.Length];
+
+ try
+ {
+ foreach (string filePath in Directory.EnumerateFiles(timeZoneDirectory, "*", SearchOption.AllDirectories))
+ {
+ // skip the localtime and posixrules file, since they won't give us the correct id
+ if (!string.Equals(filePath, localtimeFilePath, StringComparison.OrdinalIgnoreCase)
+ && !string.Equals(filePath, posixrulesFilePath, StringComparison.OrdinalIgnoreCase))
+ {
+ if (CompareTimeZoneFile(filePath, buffer, rawData))
+ {
+ // if all bytes are the same, this must be the right tz file
+ id = filePath;
+
+ // strip off the root time zone directory
+ if (id.StartsWith(timeZoneDirectory))
+ {
+ id = id.Substring(timeZoneDirectory.Length);
+ }
+ break;
+ }
+ }
+ }
+ }
+ catch (IOException) { }
+ catch (SecurityException) { }
+ catch (UnauthorizedAccessException) { }
+
+ return id;
+ }
+
+ private static bool CompareTimeZoneFile(string filePath, byte[] buffer, byte[] rawData)
+ {
+ try
+ {
+ using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
+ {
+ if (stream.Length == rawData.Length)
+ {
+ int index = 0;
+ int count = rawData.Length;
+
+ while (count > 0)
+ {
+ int n = stream.Read(buffer, index, count);
+ if (n == 0)
+ __Error.EndOfFile();
+
+ int end = index + n;
+ for (; index < end; index++)
+ {
+ if (buffer[index] != rawData[index])
+ {
+ return false;
+ }
+ }
+
+ count -= n;
+ }
+
+ return true;
+ }
+ }
+ }
+ catch (IOException) { }
+ catch (SecurityException) { }
+ catch (UnauthorizedAccessException) { }
+
+ return false;
+ }
+
+ //
+ // GetLocalTimeZoneFromTzFile -
+ //
+ // Helper function used by 'GetLocalTimeZone()' - this function wraps the call
+ // for loading time zone data from computers without Registry support.
+ //
+ // The TryGetLocalTzFile() call returns a Byte[] containing the compiled tzfile.
+ //
+ [System.Security.SecurityCritical]
+ static private TimeZoneInfo GetLocalTimeZoneFromTzFile()
+ {
+ byte[] rawData;
+ string id;
+ if (TryGetLocalTzFile(out rawData, out id))
+ {
+ TimeZoneInfo result = GetTimeZoneFromTzData(rawData, id);
+ if (result != null)
+ {
+ return result;
+ }
+ }
+
+ // if we can't find a local time zone, return UTC
+ return Utc;
+ }
+
+ private static TimeZoneInfo GetTimeZoneFromTzData(byte[] rawData, string id)
+ {
+ if (rawData != null)
+ {
+ try
+ {
+ return new TimeZoneInfo(rawData, id, false); // create a TimeZoneInfo instance from the TZif data w/ DST support
+ }
+ catch (ArgumentException) { }
+ catch (InvalidTimeZoneException) { }
+ try
+ {
+ return new TimeZoneInfo(rawData, id, true); // create a TimeZoneInfo instance from the TZif data w/o DST support
+ }
+ catch (ArgumentException) { }
+ catch (InvalidTimeZoneException) { }
+ }
+
+ return null;
+ }
+
+ private static string GetTimeZoneDirectory()
+ {
+ string tzDirectory = Environment.GetEnvironmentVariable(c_timeZoneDirectoryEnvironmentVariable);
+
+ if (tzDirectory == null)
+ {
+ tzDirectory = c_defaultTimeZoneDirectory;
+ }
+ else if (!tzDirectory.EndsWith(Path.DirectorySeparatorChar))
+ {
+ tzDirectory += Path.DirectorySeparatorChar;
+ }
+
+ return tzDirectory;
+ }
+#elif FEATURE_WIN32_REGISTRY // PLATFORM_UNIX
+
+ //
+ // GetLocalTimeZoneFromWin32Data -
+ //
+ // Helper function used by 'GetLocalTimeZone()' - this function wraps a bunch of
+ // try/catch logic for handling the TimeZoneInfo private constructor that takes
+ // a Win32Native.TimeZoneInformation structure.
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private TimeZoneInfo GetLocalTimeZoneFromWin32Data(Win32Native.TimeZoneInformation timeZoneInformation, Boolean dstDisabled) {
+ // first try to create the TimeZoneInfo with the original 'dstDisabled' flag
+ try {
+ return new TimeZoneInfo(timeZoneInformation, dstDisabled);
+ }
+ catch (ArgumentException) {}
+ catch (InvalidTimeZoneException) {}
+
+ // if 'dstDisabled' was false then try passing in 'true' as a last ditch effort
+ if (!dstDisabled) {
+ try {
+ return new TimeZoneInfo(timeZoneInformation, true);
+ }
+ catch (ArgumentException) {}
+ catch (InvalidTimeZoneException) {}
+ }
+
+ // the data returned from Windows is completely bogus; return a dummy entry
+ return CreateCustomTimeZone(c_localId, TimeSpan.Zero, c_localId, c_localId);
+ }
+#endif // PLATFORM_UNIX
+
+ //
+ // FindSystemTimeZoneById -
+ //
+ // Helper function for retrieving a TimeZoneInfo object by <time_zone_name>.
+ // This function wraps the logic necessary to keep the private
+ // SystemTimeZones cache in working order
+ //
+ // This function will either return a valid TimeZoneInfo instance or
+ // it will throw 'InvalidTimeZoneException' / 'TimeZoneNotFoundException'.
+ //
+ static public TimeZoneInfo FindSystemTimeZoneById(string id) {
+
+ // Special case for Utc as it will not exist in the dictionary with the rest
+ // of the system time zones. There is no need to do this check for Local.Id
+ // since Local is a real time zone that exists in the dictionary cache
+ if (String.Compare(id, c_utcId, StringComparison.OrdinalIgnoreCase) == 0) {
+ return TimeZoneInfo.Utc;
+ }
+
+ if (id == null) {
+ throw new ArgumentNullException("id");
+ }
+ else if (!IsValidSystemTimeZoneId(id)) {
+ throw new TimeZoneNotFoundException(Environment.GetResourceString("TimeZoneNotFound_MissingData", id));
+ }
+
+ TimeZoneInfo value;
+ Exception e;
+
+ TimeZoneInfoResult result;
+
+ CachedData cachedData = s_cachedData;
+
+ lock (cachedData) {
+ result = TryGetTimeZone(id, false, out value, out e, cachedData);
+ }
+
+ if (result == TimeZoneInfoResult.Success) {
+ return value;
+ }
+ else if (result == TimeZoneInfoResult.InvalidTimeZoneException) {
+#if FEATURE_WIN32_REGISTRY
+ throw new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_InvalidRegistryData", id), e);
+#elif PLATFORM_UNIX
+ Contract.Assert(e is InvalidTimeZoneException,
+ "TryGetTimeZone must create an InvalidTimeZoneException when it returns TimeZoneInfoResult.InvalidTimeZoneException");
+ throw e;
+#endif
+ }
+ else if (result == TimeZoneInfoResult.SecurityException) {
+#if FEATURE_WIN32_REGISTRY
+ throw new SecurityException(Environment.GetResourceString("Security_CannotReadRegistryData", id), e);
+#elif PLATFORM_UNIX
+ throw new SecurityException(Environment.GetResourceString("Security_CannotReadFileData", id), e);
+#endif
+ }
+ else {
+ throw new TimeZoneNotFoundException(Environment.GetResourceString("TimeZoneNotFound_MissingData", id), e);
+ }
+ }
+
+ private static bool IsValidSystemTimeZoneId(string id)
+ {
+ bool isValid = id.Length != 0 && !id.Contains("\0");
+
+#if FEATURE_WIN32_REGISTRY
+ isValid &= id.Length <= c_maxKeyLength;
+#endif // FEATURE_WIN32_REGISTRY
+
+ return isValid;
+ }
+
+ //
+ // GetUtcOffset -
+ //
+ // Helper function that calculates the UTC offset for a dateTime in a timeZone.
+ // This function assumes that the dateTime is already converted into the timeZone.
+ //
+ static private TimeSpan GetUtcOffset(DateTime time, TimeZoneInfo zone, TimeZoneInfoOptions flags) {
+ TimeSpan baseOffset = zone.BaseUtcOffset;
+ AdjustmentRule rule = zone.GetAdjustmentRuleForTime(time);
+
+ if (rule != null) {
+ baseOffset = baseOffset + rule.BaseUtcOffsetDelta;
+ if (rule.HasDaylightSaving) {
+ DaylightTime daylightTime = zone.GetDaylightTime(time.Year, rule);
+ Boolean isDaylightSavings = GetIsDaylightSavings(time, rule, daylightTime, flags);
+ baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */);
+ }
+ }
+
+ return baseOffset;
+ }
+
+
+ //
+ // GetUtcOffsetFromUtc -
+ //
+ // Helper function that calculates the UTC offset for a UTC-dateTime in a timeZone.
+ // This function assumes that the dateTime is represented in UTC and has *not*
+ // already been converted into the timeZone.
+ //
+ static private TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone) {
+ Boolean isDaylightSavings;
+ return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings);
+ }
+
+ static private TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out Boolean isDaylightSavings) {
+ Boolean isAmbiguousLocalDst;
+ return GetUtcOffsetFromUtc(time, zone, out isDaylightSavings, out isAmbiguousLocalDst);
+ }
+
+ // DateTime.Now fast path that avoids allocating an historically accurate TimeZoneInfo.Local and just creates a 1-year (current year) accurate time zone
+ static internal TimeSpan GetDateTimeNowUtcOffsetFromUtc(DateTime time, out Boolean isAmbiguousLocalDst) {
+ Boolean isDaylightSavings = false;
+#if FEATURE_WIN32_REGISTRY
+ isAmbiguousLocalDst = false;
+ TimeSpan baseOffset;
+ int timeYear = time.Year;
+
+ OffsetAndRule match = s_cachedData.GetOneYearLocalFromUtc(timeYear);
+ baseOffset = match.offset;
+
+ if (match.rule != null) {
+ baseOffset = baseOffset + match.rule.BaseUtcOffsetDelta;
+ if (match.rule.HasDaylightSaving) {
+ isDaylightSavings = GetIsDaylightSavingsFromUtc(time, timeYear, match.offset, match.rule, out isAmbiguousLocalDst, TimeZoneInfo.Local);
+ baseOffset += (isDaylightSavings ? match.rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */);
+ }
+ }
+ return baseOffset;
+#elif PLATFORM_UNIX
+ // Use the standard code path for the Macintosh since there isn't a faster way of handling current-year-only time zones
+ return GetUtcOffsetFromUtc(time, TimeZoneInfo.Local, out isDaylightSavings, out isAmbiguousLocalDst);
+#endif // FEATURE_WIN32_REGISTRY
+ }
+
+ static internal TimeSpan GetUtcOffsetFromUtc(DateTime time, TimeZoneInfo zone, out Boolean isDaylightSavings, out Boolean isAmbiguousLocalDst) {
+ isDaylightSavings = false;
+ isAmbiguousLocalDst = false;
+ TimeSpan baseOffset = zone.BaseUtcOffset;
+ Int32 year;
+ AdjustmentRule rule;
+
+ if (time > s_maxDateOnly) {
+ rule = zone.GetAdjustmentRuleForTime(DateTime.MaxValue);
+ year = 9999;
+ }
+ else if (time < s_minDateOnly) {
+ rule = zone.GetAdjustmentRuleForTime(DateTime.MinValue);
+ year = 1;
+ }
+ else {
+ rule = zone.GetAdjustmentRuleForTime(time, dateTimeisUtc: true);
+
+ // As we get the associated rule using the adjusted targetTime, we should use the adjusted year (targetTime.Year) too as after adding the baseOffset,
+ // sometimes the year value can change if the input datetime was very close to the beginning or the end of the year. Examples of such cases:
+ // “Libya Standard Time” when used with the date 2011-12-31T23:59:59.9999999Z
+ // "W. Australia Standard Time" used with date 2005-12-31T23:59:00.0000000Z
+ DateTime targetTime = time + baseOffset;
+ year = targetTime.Year;
+ }
+
+ if (rule != null) {
+ baseOffset = baseOffset + rule.BaseUtcOffsetDelta;
+ if (rule.HasDaylightSaving) {
+ isDaylightSavings = GetIsDaylightSavingsFromUtc(time, year, zone.m_baseUtcOffset, rule, out isAmbiguousLocalDst, zone);
+ baseOffset += (isDaylightSavings ? rule.DaylightDelta : TimeSpan.Zero /* FUTURE: rule.StandardDelta */);
+ }
+ }
+
+ return baseOffset;
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ //
+ // TransitionTimeFromTimeZoneInformation -
+ //
+ // Converts a Win32Native.RegistryTimeZoneInformation (REG_TZI_FORMAT struct) to a TransitionTime
+ //
+ // * when the argument 'readStart' is true the corresponding daylightTransitionTimeStart field is read
+ // * when the argument 'readStart' is false the corresponding dayightTransitionTimeEnd field is read
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private bool TransitionTimeFromTimeZoneInformation(Win32Native.RegistryTimeZoneInformation timeZoneInformation, out TransitionTime transitionTime, bool readStartDate) {
+ //
+ // SYSTEMTIME -
+ //
+ // If the time zone does not support daylight saving time or if the caller needs
+ // to disable daylight saving time, the wMonth member in the SYSTEMTIME structure
+ // must be zero. If this date is specified, the DaylightDate value in the
+ // TIME_ZONE_INFORMATION structure must also be specified. Otherwise, the system
+ // assumes the time zone data is invalid and no changes will be applied.
+ //
+ bool supportsDst = (timeZoneInformation.StandardDate.Month != 0);
+
+ if (!supportsDst) {
+ transitionTime = default(TransitionTime);
+ return false;
+ }
+
+ //
+ // SYSTEMTIME -
+ //
+ // * FixedDateRule -
+ // If the Year member is not zero, the transition date is absolute; it will only occur one time
+ //
+ // * FloatingDateRule -
+ // To select the correct day in the month, set the Year member to zero, the Hour and Minute
+ // members to the transition time, the DayOfWeek member to the appropriate weekday, and the
+ // Day member to indicate the occurence of the day of the week within the month (first through fifth).
+ //
+ // Using this notation, specify the 2:00a.m. on the first Sunday in April as follows:
+ // Hour = 2,
+ // Month = 4,
+ // DayOfWeek = 0,
+ // Day = 1.
+ //
+ // Specify 2:00a.m. on the last Thursday in October as follows:
+ // Hour = 2,
+ // Month = 10,
+ // DayOfWeek = 4,
+ // Day = 5.
+ //
+ if (readStartDate) {
+ //
+ // read the "daylightTransitionStart"
+ //
+ if (timeZoneInformation.DaylightDate.Year == 0) {
+ transitionTime = TransitionTime.CreateFloatingDateRule(
+ new DateTime(1, /* year */
+ 1, /* month */
+ 1, /* day */
+ timeZoneInformation.DaylightDate.Hour,
+ timeZoneInformation.DaylightDate.Minute,
+ timeZoneInformation.DaylightDate.Second,
+ timeZoneInformation.DaylightDate.Milliseconds),
+ timeZoneInformation.DaylightDate.Month,
+ timeZoneInformation.DaylightDate.Day, /* Week 1-5 */
+ (DayOfWeek) timeZoneInformation.DaylightDate.DayOfWeek);
+ }
+ else {
+ transitionTime = TransitionTime.CreateFixedDateRule(
+ new DateTime(1, /* year */
+ 1, /* month */
+ 1, /* day */
+ timeZoneInformation.DaylightDate.Hour,
+ timeZoneInformation.DaylightDate.Minute,
+ timeZoneInformation.DaylightDate.Second,
+ timeZoneInformation.DaylightDate.Milliseconds),
+ timeZoneInformation.DaylightDate.Month,
+ timeZoneInformation.DaylightDate.Day);
+ }
+ }
+ else {
+ //
+ // read the "daylightTransitionEnd"
+ //
+ if (timeZoneInformation.StandardDate.Year == 0) {
+ transitionTime = TransitionTime.CreateFloatingDateRule(
+ new DateTime(1, /* year */
+ 1, /* month */
+ 1, /* day */
+ timeZoneInformation.StandardDate.Hour,
+ timeZoneInformation.StandardDate.Minute,
+ timeZoneInformation.StandardDate.Second,
+ timeZoneInformation.StandardDate.Milliseconds),
+ timeZoneInformation.StandardDate.Month,
+ timeZoneInformation.StandardDate.Day, /* Week 1-5 */
+ (DayOfWeek) timeZoneInformation.StandardDate.DayOfWeek);
+ }
+ else {
+ transitionTime = TransitionTime.CreateFixedDateRule(
+ new DateTime(1, /* year */
+ 1, /* month */
+ 1, /* day */
+ timeZoneInformation.StandardDate.Hour,
+ timeZoneInformation.StandardDate.Minute,
+ timeZoneInformation.StandardDate.Second,
+ timeZoneInformation.StandardDate.Milliseconds),
+ timeZoneInformation.StandardDate.Month,
+ timeZoneInformation.StandardDate.Day);
+ }
+ }
+
+ return true;
+ }
+#endif // FEATURE_WIN32_REGISTRY
+
+ //
+ // TransitionTimeToDateTime -
+ //
+ // Helper function that converts a year and TransitionTime into a DateTime
+ //
+ static private DateTime TransitionTimeToDateTime(Int32 year, TransitionTime transitionTime) {
+ DateTime value;
+ DateTime timeOfDay = transitionTime.TimeOfDay;
+
+ if (transitionTime.IsFixedDateRule) {
+ // create a DateTime from the passed in year and the properties on the transitionTime
+
+ // if the day is out of range for the month then use the last day of the month
+ Int32 day = DateTime.DaysInMonth(year, transitionTime.Month);
+
+ value = new DateTime(year, transitionTime.Month, (day < transitionTime.Day) ? day : transitionTime.Day,
+ timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+ }
+ else {
+ if (transitionTime.Week <= 4) {
+ //
+ // Get the (transitionTime.Week)th Sunday.
+ //
+ value = new DateTime(year, transitionTime.Month, 1,
+ timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+
+ int dayOfWeek = (int)value.DayOfWeek;
+ int delta = (int)transitionTime.DayOfWeek - dayOfWeek;
+ if (delta < 0) {
+ delta += 7;
+ }
+ delta += 7 * (transitionTime.Week - 1);
+
+ if (delta > 0) {
+ value = value.AddDays(delta);
+ }
+ }
+ else {
+ //
+ // If TransitionWeek is greater than 4, we will get the last week.
+ //
+ Int32 daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month);
+ value = new DateTime(year, transitionTime.Month, daysInMonth,
+ timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+
+ // This is the day of week for the last day of the month.
+ int dayOfWeek = (int)value.DayOfWeek;
+ int delta = dayOfWeek - (int)transitionTime.DayOfWeek;
+ if (delta < 0) {
+ delta += 7;
+ }
+
+ if (delta > 0) {
+ value = value.AddDays(-delta);
+ }
+ }
+ }
+ return value;
+ }
+
+#if FEATURE_WIN32_REGISTRY
+ //
+ // TryCreateAdjustmentRules -
+ //
+ // Helper function that takes
+ // 1. a string representing a <time_zone_name> registry key name
+ // 2. a RegistryTimeZoneInformation struct containing the default rule
+ // 3. an AdjustmentRule[] out-parameter
+ //
+ // returns
+ // TimeZoneInfoResult.InvalidTimeZoneException,
+ // TimeZoneInfoResult.TimeZoneNotFoundException,
+ // TimeZoneInfoResult.Success
+ //
+ // Optional, Dynamic Time Zone Registry Data
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ //
+ // HKLM
+ // Software
+ // Microsoft
+ // Windows NT
+ // CurrentVersion
+ // Time Zones
+ // <time_zone_name>
+ // Dynamic DST
+ // * "FirstEntry" REG_DWORD "1980"
+ // First year in the table. If the current year is less than this value,
+ // this entry will be used for DST boundaries
+ // * "LastEntry" REG_DWORD "2038"
+ // Last year in the table. If the current year is greater than this value,
+ // this entry will be used for DST boundaries"
+ // * "<year1>" REG_BINARY REG_TZI_FORMAT
+ // See Win32Native.RegistryTimeZoneInformation
+ // * "<year2>" REG_BINARY REG_TZI_FORMAT
+ // See Win32Native.RegistryTimeZoneInformation
+ // * "<year3>" REG_BINARY REG_TZI_FORMAT
+ // See Win32Native.RegistryTimeZoneInformation
+ //
+ // This method expects that its caller has already Asserted RegistryPermission.Read
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private bool TryCreateAdjustmentRules(string id, Win32Native.RegistryTimeZoneInformation defaultTimeZoneInformation, out AdjustmentRule[] rules, out Exception e, int defaultBaseUtcOffset) {
+ e = null;
+
+ try {
+ using (RegistryKey dynamicKey = Registry.LocalMachine.OpenSubKey(
+ String.Format(CultureInfo.InvariantCulture, "{0}\\{1}\\Dynamic DST",
+ c_timeZonesRegistryHive, id),
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.Default,
+ System.Security.AccessControl.RegistryRights.ReadKey
+#else
+ false
+#endif
+ )) {
+ if (dynamicKey == null) {
+ AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(
+ defaultTimeZoneInformation, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
+
+ if (rule == null) {
+ rules = null;
+ }
+ else {
+ rules = new AdjustmentRule[1];
+ rules[0] = rule;
+ }
+
+ return true;
+ }
+
+ //
+ // loop over all of the "<time_zone_name>\Dynamic DST" hive entries
+ //
+ // read FirstEntry {MinValue - (year1, 12, 31)}
+ // read MiddleEntry {(yearN, 1, 1) - (yearN, 12, 31)}
+ // read LastEntry {(yearN, 1, 1) - MaxValue }
+
+ // read the FirstEntry and LastEntry key values (ex: "1980", "2038")
+ Int32 first = (Int32)dynamicKey.GetValue(c_firstEntryValue, -1, RegistryValueOptions.None);
+ Int32 last = (Int32)dynamicKey.GetValue(c_lastEntryValue, -1, RegistryValueOptions.None);
+
+ if (first == -1 || last == -1 || first > last) {
+ rules = null;
+ return false;
+ }
+
+ // read the first year entry
+ Win32Native.RegistryTimeZoneInformation dtzi;
+ Byte[] regValue = dynamicKey.GetValue(first.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
+ if (regValue == null || regValue.Length != c_regByteLength) {
+ rules = null;
+ return false;
+ }
+ dtzi = new Win32Native.RegistryTimeZoneInformation(regValue);
+
+ if (first == last) {
+ // there is just 1 dynamic rule for this time zone.
+ AdjustmentRule rule = CreateAdjustmentRuleFromTimeZoneInformation(dtzi, DateTime.MinValue.Date, DateTime.MaxValue.Date, defaultBaseUtcOffset);
+
+ if (rule == null) {
+ rules = null;
+ }
+ else {
+ rules = new AdjustmentRule[1];
+ rules[0] = rule;
+ }
+
+ return true;
+ }
+
+ List<AdjustmentRule> rulesList = new List<AdjustmentRule>(1);
+
+ // there are more than 1 dynamic rules for this time zone.
+ AdjustmentRule firstRule = CreateAdjustmentRuleFromTimeZoneInformation(
+ dtzi,
+ DateTime.MinValue.Date, // MinValue
+ new DateTime(first, 12, 31), // December 31, <FirstYear>
+ defaultBaseUtcOffset);
+ if (firstRule != null) {
+ rulesList.Add(firstRule);
+ }
+
+ // read the middle year entries
+ for (Int32 i = first + 1; i < last; i++) {
+ regValue = dynamicKey.GetValue(i.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
+ if (regValue == null || regValue.Length != c_regByteLength) {
+ rules = null;
+ return false;
+ }
+ dtzi = new Win32Native.RegistryTimeZoneInformation(regValue);
+ AdjustmentRule middleRule = CreateAdjustmentRuleFromTimeZoneInformation(
+ dtzi,
+ new DateTime(i, 1, 1), // January 01, <Year>
+ new DateTime(i, 12, 31), // December 31, <Year>
+ defaultBaseUtcOffset);
+ if (middleRule != null) {
+ rulesList.Add(middleRule);
+ }
+ }
+ // read the last year entry
+ regValue = dynamicKey.GetValue(last.ToString(CultureInfo.InvariantCulture), null, RegistryValueOptions.None) as Byte[];
+ dtzi = new Win32Native.RegistryTimeZoneInformation(regValue);
+ if (regValue == null || regValue.Length != c_regByteLength) {
+ rules = null;
+ return false;
+ }
+ AdjustmentRule lastRule = CreateAdjustmentRuleFromTimeZoneInformation(
+ dtzi,
+ new DateTime(last, 1, 1), // January 01, <LastYear>
+ DateTime.MaxValue.Date, // MaxValue
+ defaultBaseUtcOffset);
+ if (lastRule != null) {
+ rulesList.Add(lastRule);
+ }
+
+ // convert the ArrayList to an AdjustmentRule array
+ rules = rulesList.ToArray();
+ if (rules != null && rules.Length == 0) {
+ rules = null;
+ }
+ } // end of: using (RegistryKey dynamicKey...
+ }
+ catch (InvalidCastException ex) {
+ // one of the RegistryKey.GetValue calls could not be cast to an expected value type
+ rules = null;
+ e = ex;
+ return false;
+ }
+ catch (ArgumentOutOfRangeException ex) {
+ rules = null;
+ e = ex;
+ return false;
+ }
+ catch (ArgumentException ex) {
+ rules = null;
+ e = ex;
+ return false;
+ }
+ return true;
+ }
+
+ //
+ // TryCompareStandardDate -
+ //
+ // Helper function that compares the StandardBias and StandardDate portion a
+ // TimeZoneInformation struct to a time zone registry entry
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ static private Boolean TryCompareStandardDate(Win32Native.TimeZoneInformation timeZone, Win32Native.RegistryTimeZoneInformation registryTimeZoneInfo) {
+ return timeZone.Bias == registryTimeZoneInfo.Bias
+ && timeZone.StandardBias == registryTimeZoneInfo.StandardBias
+ && timeZone.StandardDate.Year == registryTimeZoneInfo.StandardDate.Year
+ && timeZone.StandardDate.Month == registryTimeZoneInfo.StandardDate.Month
+ && timeZone.StandardDate.DayOfWeek == registryTimeZoneInfo.StandardDate.DayOfWeek
+ && timeZone.StandardDate.Day == registryTimeZoneInfo.StandardDate.Day
+ && timeZone.StandardDate.Hour == registryTimeZoneInfo.StandardDate.Hour
+ && timeZone.StandardDate.Minute == registryTimeZoneInfo.StandardDate.Minute
+ && timeZone.StandardDate.Second == registryTimeZoneInfo.StandardDate.Second
+ && timeZone.StandardDate.Milliseconds == registryTimeZoneInfo.StandardDate.Milliseconds;
+ }
+
+ //
+ // TryCompareTimeZoneInformationToRegistry -
+ //
+ // Helper function that compares a TimeZoneInformation struct to a time zone registry entry
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private Boolean TryCompareTimeZoneInformationToRegistry(Win32Native.TimeZoneInformation timeZone, string id, out Boolean dstDisabled) {
+
+ dstDisabled = false;
+ try {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList));
+ permSet.Assert();
+
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(
+ String.Format(CultureInfo.InvariantCulture, "{0}\\{1}",
+ c_timeZonesRegistryHive, id),
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.Default,
+ System.Security.AccessControl.RegistryRights.ReadKey
+#else
+ false
+#endif
+ )) {
+
+ if (key == null) {
+ return false;
+ }
+
+ Win32Native.RegistryTimeZoneInformation registryTimeZoneInfo;
+ Byte[] regValue = (Byte[])key.GetValue(c_timeZoneInfoValue, null, RegistryValueOptions.None) as Byte[];
+ if (regValue == null || regValue.Length != c_regByteLength) return false;
+ registryTimeZoneInfo = new Win32Native.RegistryTimeZoneInformation(regValue);
+
+ //
+ // first compare the bias and standard date information between the data from the Win32 API
+ // and the data from the registry...
+ //
+ Boolean result = TryCompareStandardDate(timeZone, registryTimeZoneInfo);
+
+ if (!result) {
+ return false;
+ }
+
+ result = dstDisabled || CheckDaylightSavingTimeNotSupported(timeZone)
+ //
+ // since Daylight Saving Time is not "disabled", do a straight comparision between
+ // the Win32 API data and the registry data ...
+ //
+ ||( timeZone.DaylightBias == registryTimeZoneInfo.DaylightBias
+ && timeZone.DaylightDate.Year == registryTimeZoneInfo.DaylightDate.Year
+ && timeZone.DaylightDate.Month == registryTimeZoneInfo.DaylightDate.Month
+ && timeZone.DaylightDate.DayOfWeek == registryTimeZoneInfo.DaylightDate.DayOfWeek
+ && timeZone.DaylightDate.Day == registryTimeZoneInfo.DaylightDate.Day
+ && timeZone.DaylightDate.Hour == registryTimeZoneInfo.DaylightDate.Hour
+ && timeZone.DaylightDate.Minute == registryTimeZoneInfo.DaylightDate.Minute
+ && timeZone.DaylightDate.Second == registryTimeZoneInfo.DaylightDate.Second
+ && timeZone.DaylightDate.Milliseconds == registryTimeZoneInfo.DaylightDate.Milliseconds);
+
+ // Finally compare the "StandardName" string value...
+ //
+ // we do not compare "DaylightName" as this TimeZoneInformation field may contain
+ // either "StandardName" or "DaylightName" depending on the time of year and current machine settings
+ //
+ if (result) {
+ String registryStandardName = key.GetValue(c_standardValue, String.Empty, RegistryValueOptions.None) as String;
+ result = String.Compare(registryStandardName, timeZone.StandardName, StringComparison.Ordinal) == 0;
+ }
+ return result;
+ }
+ }
+ finally {
+ PermissionSet.RevertAssert();
+ }
+ }
+
+ //
+ // TryGetLocalizedNameByMuiNativeResource -
+ //
+ // Helper function for retrieving a localized string resource via MUI.
+ // The function expects a string in the form: "@resource.dll, -123"
+ //
+ // "resource.dll" is a language-neutral portable executable (LNPE) file in
+ // the %windir%\system32 directory. The OS is queried to find the best-fit
+ // localized resource file for this LNPE (ex: %windir%\system32\en-us\resource.dll.mui).
+ // If a localized resource file exists, we LoadString resource ID "123" and
+ // return it to our caller.
+ //
+ // <SecurityKernel Critical="True" Ring="0">
+ // <CallsSuppressUnmanagedCode Name="UnsafeNativeMethods.GetFileMUIPath(System.Int32,System.String,System.Text.StringBuilder,System.Int32&,System.Text.StringBuilder,System.Int32&,System.Int64&):System.Boolean" />
+ // <ReferencesCritical Name="Method: TryGetLocalizedNameByNativeResource(String, Int32):String" Ring="1" />
+ // </SecurityKernel>
+ [System.Security.SecuritySafeCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [FileIOPermissionAttribute(SecurityAction.Assert, AllLocalFiles = FileIOPermissionAccess.PathDiscovery)]
+#endif
+ static private string TryGetLocalizedNameByMuiNativeResource(string resource) {
+ if (String.IsNullOrEmpty(resource)) {
+ return String.Empty;
+ }
+
+ // parse "@tzres.dll, -100"
+ //
+ // filePath = "C:\Windows\System32\tzres.dll"
+ // resourceId = -100
+ //
+ string[] resources = resource.Split(new char[] {','}, StringSplitOptions.None);
+ if (resources.Length != 2) {
+ return String.Empty;
+ }
+
+ string filePath;
+ int resourceId;
+
+ // get the path to Windows\System32
+ string system32 = Environment.UnsafeGetFolderPath(Environment.SpecialFolder.System);
+
+ // trim the string "@tzres.dll" => "tzres.dll"
+ string tzresDll = resources[0].TrimStart(new char[] {'@'});
+
+ try {
+ filePath = Path.Combine(system32, tzresDll);
+ }
+ catch (ArgumentException) {
+ // there were probably illegal characters in the path
+ return String.Empty;
+ }
+
+ if (!Int32.TryParse(resources[1], NumberStyles.Integer, CultureInfo.InvariantCulture, out resourceId)) {
+ return String.Empty;
+ }
+ resourceId = -resourceId;
+
+
+ try {
+ StringBuilder fileMuiPath = StringBuilderCache.Acquire(Path.MaxPath);
+ fileMuiPath.Length = Path.MaxPath;
+ int fileMuiPathLength = Path.MaxPath;
+ int languageLength = 0;
+ Int64 enumerator = 0;
+
+ Boolean succeeded = UnsafeNativeMethods.GetFileMUIPath(
+ Win32Native.MUI_PREFERRED_UI_LANGUAGES,
+ filePath, null /* language */, ref languageLength,
+ fileMuiPath, ref fileMuiPathLength, ref enumerator);
+ if (!succeeded) {
+ StringBuilderCache.Release(fileMuiPath);
+ return String.Empty;
+ }
+ return TryGetLocalizedNameByNativeResource(StringBuilderCache.GetStringAndRelease(fileMuiPath), resourceId);
+ }
+ catch (EntryPointNotFoundException) {
+ return String.Empty;
+ }
+ }
+
+ //
+ // TryGetLocalizedNameByNativeResource -
+ //
+ // Helper function for retrieving a localized string resource via a native resource DLL.
+ // The function expects a string in the form: "C:\Windows\System32\en-us\resource.dll"
+ //
+ // "resource.dll" is a language-specific resource DLL.
+ // If the localized resource DLL exists, LoadString(resource) is returned.
+ //
+ [SecurityCritical]
+ static private string TryGetLocalizedNameByNativeResource(string filePath, int resource) {
+ using (SafeLibraryHandle handle =
+ UnsafeNativeMethods.LoadLibraryEx(filePath, IntPtr.Zero, Win32Native.LOAD_LIBRARY_AS_DATAFILE)) {
+
+ if (!handle.IsInvalid) {
+ StringBuilder localizedResource = StringBuilderCache.Acquire(Win32Native.LOAD_STRING_MAX_LENGTH);
+ localizedResource.Length = Win32Native.LOAD_STRING_MAX_LENGTH;
+
+ int result = UnsafeNativeMethods.LoadString(handle, resource,
+ localizedResource, localizedResource.Length);
+
+ if (result != 0) {
+ return StringBuilderCache.GetStringAndRelease(localizedResource);
+ }
+ }
+ }
+ return String.Empty;
+ }
+
+ //
+ // TryGetLocalizedNamesByRegistryKey -
+ //
+ // Helper function for retrieving the DisplayName, StandardName, and DaylightName from the registry
+ //
+ // The function first checks the MUI_ key-values, and if they exist, it loads the strings from the MUI
+ // resource dll(s). When the keys do not exist, the function falls back to reading from the standard
+ // key-values
+ //
+ // This method expects that its caller has already Asserted RegistryPermission.Read
+ //
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ static private Boolean TryGetLocalizedNamesByRegistryKey(RegistryKey key, out String displayName, out String standardName, out String daylightName) {
+ displayName = String.Empty;
+ standardName = String.Empty;
+ daylightName = String.Empty;
+
+ // read the MUI_ registry keys
+ String displayNameMuiResource = key.GetValue(c_muiDisplayValue, String.Empty, RegistryValueOptions.None) as String;
+ String standardNameMuiResource = key.GetValue(c_muiStandardValue, String.Empty, RegistryValueOptions.None) as String;
+ String daylightNameMuiResource = key.GetValue(c_muiDaylightValue, String.Empty, RegistryValueOptions.None) as String;
+
+ // try to load the strings from the native resource DLL(s)
+ if (!String.IsNullOrEmpty(displayNameMuiResource)) {
+ displayName = TryGetLocalizedNameByMuiNativeResource(displayNameMuiResource);
+ }
+
+ if (!String.IsNullOrEmpty(standardNameMuiResource)) {
+ standardName = TryGetLocalizedNameByMuiNativeResource(standardNameMuiResource);
+ }
+
+ if (!String.IsNullOrEmpty(daylightNameMuiResource)) {
+ daylightName = TryGetLocalizedNameByMuiNativeResource(daylightNameMuiResource);
+ }
+
+ // fallback to using the standard registry keys
+ if (String.IsNullOrEmpty(displayName)) {
+ displayName = key.GetValue(c_displayValue, String.Empty, RegistryValueOptions.None) as String;
+ }
+ if (String.IsNullOrEmpty(standardName)) {
+ standardName = key.GetValue(c_standardValue, String.Empty, RegistryValueOptions.None) as String;
+ }
+ if (String.IsNullOrEmpty(daylightName)) {
+ daylightName = key.GetValue(c_daylightValue, String.Empty, RegistryValueOptions.None) as String;
+ }
+
+ return true;
+ }
+
+ //
+ // TryGetTimeZoneByRegistryKey -
+ //
+ // Helper function that takes a string representing a <time_zone_name> registry key name
+ // and returns a TimeZoneInfo instance.
+ //
+ // returns
+ // TimeZoneInfoResult.InvalidTimeZoneException,
+ // TimeZoneInfoResult.TimeZoneNotFoundException,
+ // TimeZoneInfoResult.SecurityException,
+ // TimeZoneInfoResult.Success
+ //
+ //
+ // Standard Time Zone Registry Data
+ // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+ // HKLM
+ // Software
+ // Microsoft
+ // Windows NT
+ // CurrentVersion
+ // Time Zones
+ // <time_zone_name>
+ // * STD, REG_SZ "Standard Time Name"
+ // (For OS installed zones, this will always be English)
+ // * MUI_STD, REG_SZ "@tzres.dll,-1234"
+ // Indirect string to localized resource for Standard Time,
+ // add "%windir%\system32\" after "@"
+ // * DLT, REG_SZ "Daylight Time Name"
+ // (For OS installed zones, this will always be English)
+ // * MUI_DLT, REG_SZ "@tzres.dll,-1234"
+ // Indirect string to localized resource for Daylight Time,
+ // add "%windir%\system32\" after "@"
+ // * Display, REG_SZ "Display Name like (GMT-8:00) Pacific Time..."
+ // * MUI_Display, REG_SZ "@tzres.dll,-1234"
+ // Indirect string to localized resource for the Display,
+ // add "%windir%\system32\" after "@"
+ // * TZI, REG_BINARY REG_TZI_FORMAT
+ // See Win32Native.RegistryTimeZoneInformation
+ //
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private TimeZoneInfoResult TryGetTimeZoneByRegistryKey(string id, out TimeZoneInfo value, out Exception e) {
+ e = null;
+
+ try {
+ PermissionSet permSet = new PermissionSet(PermissionState.None);
+ permSet.AddPermission(new RegistryPermission(RegistryPermissionAccess.Read, c_timeZonesRegistryHivePermissionList));
+ permSet.Assert();
+
+ using (RegistryKey key = Registry.LocalMachine.OpenSubKey(
+ String.Format(CultureInfo.InvariantCulture, "{0}\\{1}",
+ c_timeZonesRegistryHive, id),
+#if FEATURE_MACL
+ RegistryKeyPermissionCheck.Default,
+ System.Security.AccessControl.RegistryRights.ReadKey
+#else
+ false
+#endif
+ )) {
+
+ if (key == null) {
+ value = null;
+ return TimeZoneInfoResult.TimeZoneNotFoundException;
+ }
+
+ Win32Native.RegistryTimeZoneInformation defaultTimeZoneInformation;
+ Byte[] regValue = key.GetValue(c_timeZoneInfoValue, null, RegistryValueOptions.None) as Byte[];
+ if (regValue == null || regValue.Length != c_regByteLength) {
+ // the registry value could not be cast to a byte array
+ value = null;
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+ defaultTimeZoneInformation = new Win32Native.RegistryTimeZoneInformation(regValue);
+
+ AdjustmentRule[] adjustmentRules;
+ if (!TryCreateAdjustmentRules(id, defaultTimeZoneInformation, out adjustmentRules, out e, defaultTimeZoneInformation.Bias)) {
+ value = null;
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+
+ string displayName;
+ string standardName;
+ string daylightName;
+
+ if (!TryGetLocalizedNamesByRegistryKey(key, out displayName, out standardName, out daylightName)) {
+ value = null;
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+
+ try {
+ value = new TimeZoneInfo(
+ id,
+ new TimeSpan(0, -(defaultTimeZoneInformation.Bias), 0),
+ displayName,
+ standardName,
+ daylightName,
+ adjustmentRules,
+ false);
+
+ return TimeZoneInfoResult.Success;
+ }
+ catch (ArgumentException ex) {
+ // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException
+ value = null;
+ e = ex;
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+ catch (InvalidTimeZoneException ex) {
+ // TimeZoneInfo constructor can throw ArgumentException and InvalidTimeZoneException
+ value = null;
+ e = ex;
+ return TimeZoneInfoResult.InvalidTimeZoneException;
+ }
+
+ }
+ }
+ finally {
+ PermissionSet.RevertAssert();
+ }
+ }
+#endif // FEATURE_WIN32_REGISTRY
+
+
+ //
+ // TryGetTimeZone -
+ //
+ // Helper function for retrieving a TimeZoneInfo object by <time_zone_name>.
+ //
+ // This function may return null.
+ //
+ // assumes cachedData lock is taken
+ //
+ static private TimeZoneInfoResult TryGetTimeZone(string id, Boolean dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData) {
+ TimeZoneInfoResult result = TimeZoneInfoResult.Success;
+ e = null;
+ TimeZoneInfo match = null;
+
+ // check the cache
+ if (cachedData.m_systemTimeZones != null) {
+ if (cachedData.m_systemTimeZones.TryGetValue(id, out match)) {
+ if (dstDisabled && match.m_supportsDaylightSavingTime) {
+ // we found a cache hit but we want a time zone without DST and this one has DST data
+ value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
+ }
+ else {
+ value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
+ match.m_daylightDisplayName, match.m_adjustmentRules, false);
+ }
+ return result;
+ }
+ }
+
+ // fall back to reading from the local machine
+ // when the cache is not fully populated
+ if (!cachedData.m_allSystemTimeZonesRead) {
+ result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+ }
+#if PLATFORM_UNIX
+ // On UNIX, there may be some tzfiles that aren't in the zones.tab file, and thus aren't returned from GetSystemTimeZones().
+ // If a caller asks for one of these zones before calling GetSystemTimeZones(), the time zone is returned successfully. But if
+ // GetSystemTimeZones() is called first, FindSystemTimeZoneById will throw TimeZoneNotFoundException, which is inconsistent.
+ // To fix this, even if m_allSystemTimeZonesRead is true, try reading the tzfile from disk, but don't add the time zone to the
+ // list returned from GetSystemTimeZones(). These time zones will only be available if asked for directly.
+ else {
+ result = TryGetTimeZoneFromLocalMachine(id, dstDisabled, out value, out e, cachedData);
+ }
+#else
+ else {
+ result = TimeZoneInfoResult.TimeZoneNotFoundException;
+ value = null;
+ }
+#endif // PLATFORM_UNIX
+
+ return result;
+ }
+
+ private static TimeZoneInfoResult TryGetTimeZoneFromLocalMachine(string id, bool dstDisabled, out TimeZoneInfo value, out Exception e, CachedData cachedData)
+ {
+ TimeZoneInfoResult result;
+ TimeZoneInfo match;
+
+#if FEATURE_WIN32_REGISTRY
+ result = TryGetTimeZoneByRegistryKey(id, out match, out e);
+#elif PLATFORM_UNIX
+ result = TryGetTimeZoneByFile(id, out match, out e);
+#endif // FEATURE_WIN32_REGISTRY
+
+ if (result == TimeZoneInfoResult.Success)
+ {
+ if (cachedData.m_systemTimeZones == null)
+ cachedData.m_systemTimeZones = new Dictionary<string, TimeZoneInfo>();
+
+ cachedData.m_systemTimeZones.Add(id, match);
+
+ if (dstDisabled && match.m_supportsDaylightSavingTime)
+ {
+ // we found a cache hit but we want a time zone without DST and this one has DST data
+ value = CreateCustomTimeZone(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName);
+ }
+ else
+ {
+ value = new TimeZoneInfo(match.m_id, match.m_baseUtcOffset, match.m_displayName, match.m_standardDisplayName,
+ match.m_daylightDisplayName, match.m_adjustmentRules, false);
+ }
+ }
+ else
+ {
+ value = null;
+ }
+
+ return result;
+ }
+
+#if PLATFORM_UNIX
+ // TZFILE(5) BSD File Formats Manual TZFILE(5)
+ //
+ // NAME
+ // tzfile -- timezone information
+ //
+ // SYNOPSIS
+ // #include "/usr/src/lib/libc/stdtime/tzfile.h"
+ //
+ // DESCRIPTION
+ // The time zone information files used by tzset(3) begin with the magic
+ // characters ``TZif'' to identify them as time zone information files, fol-
+ // lowed by sixteen bytes reserved for future use, followed by four four-
+ // byte values written in a ``standard'' byte order (the high-order byte of
+ // the value is written first). These values are, in order:
+ //
+ // tzh_ttisgmtcnt The number of UTC/local indicators stored in the file.
+ // tzh_ttisstdcnt The number of standard/wall indicators stored in the
+ // file.
+ // tzh_leapcnt The number of leap seconds for which data is stored in
+ // the file.
+ // tzh_timecnt The number of ``transition times'' for which data is
+ // stored in the file.
+ // tzh_typecnt The number of ``local time types'' for which data is
+ // stored in the file (must not be zero).
+ // tzh_charcnt The number of characters of ``time zone abbreviation
+ // strings'' stored in the file.
+ //
+ // The above header is followed by tzh_timecnt four-byte values of type
+ // long, sorted in ascending order. These values are written in ``stan-
+ // dard'' byte order. Each is used as a transition time (as returned by
+ // time(3)) at which the rules for computing local time change. Next come
+ // tzh_timecnt one-byte values of type unsigned char; each one tells which
+ // of the different types of ``local time'' types described in the file is
+ // associated with the same-indexed transition time. These values serve as
+ // indices into an array of ttinfo structures that appears next in the file;
+ // these structures are defined as follows:
+ //
+ // struct ttinfo {
+ // long tt_gmtoff;
+ // int tt_isdst;
+ // unsigned int tt_abbrind;
+ // };
+ //
+ // Each structure is written as a four-byte value for tt_gmtoff of type
+ // long, in a standard byte order, followed by a one-byte value for tt_isdst
+ // and a one-byte value for tt_abbrind. In each structure, tt_gmtoff gives
+ // the number of seconds to be added to UTC, tt_isdst tells whether tm_isdst
+ // should be set by localtime(3) and tt_abbrind serves as an index into the
+ // array of time zone abbreviation characters that follow the ttinfo struc-
+ // ture(s) in the file.
+ //
+ // Then there are tzh_leapcnt pairs of four-byte values, written in standard
+ // byte order; the first value of each pair gives the time (as returned by
+ // time(3)) at which a leap second occurs; the second gives the total number
+ // of leap seconds to be applied after the given time. The pairs of values
+ // are sorted in ascending order by time.b
+ //
+ // Then there are tzh_ttisstdcnt standard/wall indicators, each stored as a
+ // one-byte value; they tell whether the transition times associated with
+ // local time types were specified as standard time or wall clock time, and
+ // are used when a time zone file is used in handling POSIX-style time zone
+ // environment variables.
+ //
+ // Finally there are tzh_ttisgmtcnt UTC/local indicators, each stored as a
+ // one-byte value; they tell whether the transition times associated with
+ // local time types were specified as UTC or local time, and are used when a
+ // time zone file is used in handling POSIX-style time zone environment
+ // variables.
+ //
+ // localtime uses the first standard-time ttinfo structure in the file (or
+ // simply the first ttinfo structure in the absence of a standard-time
+ // structure) if either tzh_timecnt is zero or the time argument is less
+ // than the first transition time recorded in the file.
+ //
+ // SEE ALSO
+ // ctime(3), time2posix(3), zic(8)
+ //
+ // BSD September 13, 1994 BSD
+ //
+ //
+ //
+ // TIME(3) BSD Library Functions Manual TIME(3)
+ //
+ // NAME
+ // time -- get time of day
+ //
+ // LIBRARY
+ // Standard C Library (libc, -lc)
+ //
+ // SYNOPSIS
+ // #include <time.h>
+ //
+ // time_t
+ // time(time_t *tloc);
+ //
+ // DESCRIPTION
+ // The time() function returns the value of time in seconds since 0 hours, 0
+ // minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, without
+ // including leap seconds. If an error occurs, time() returns the value
+ // (time_t)-1.
+ //
+ // The return value is also stored in *tloc, provided that tloc is non-null.
+ //
+ // ERRORS
+ // The time() function may fail for any of the reasons described in
+ // gettimeofday(2).
+ //
+ // SEE ALSO
+ // gettimeofday(2), ctime(3)
+ //
+ // STANDARDS
+ // The time function conforms to IEEE Std 1003.1-2001 (``POSIX.1'').
+ //
+ // BUGS
+ // Neither ISO/IEC 9899:1999 (``ISO C99'') nor IEEE Std 1003.1-2001
+ // (``POSIX.1'') requires time() to set errno on failure; thus, it is impos-
+ // sible for an application to distinguish the valid time value -1 (repre-
+ // senting the last UTC second of 1969) from the error return value.
+ //
+ // Systems conforming to earlier versions of the C and POSIX standards
+ // (including older versions of FreeBSD) did not set *tloc in the error
+ // case.
+ //
+ // HISTORY
+ // A time() function appeared in Version 6 AT&T UNIX.
+ //
+ // BSD July 18, 2003 BSD
+ //
+ //
+ static private void TZif_GenerateAdjustmentRules(out AdjustmentRule[] rules, TimeSpan baseUtcOffset, DateTime[] dts, Byte[] typeOfLocalTime,
+ TZifType[] transitionType, Boolean[] StandardTime, Boolean[] GmtTime, string futureTransitionsPosixFormat)
+ {
+ rules = null;
+
+ if (dts.Length > 0)
+ {
+ int index = 0;
+ List<AdjustmentRule> rulesList = new List<AdjustmentRule>();
+
+ while (index <= dts.Length)
+ {
+ TZif_GenerateAdjustmentRule(ref index, baseUtcOffset, rulesList, dts, typeOfLocalTime, transitionType, StandardTime, GmtTime, futureTransitionsPosixFormat);
+ }
+
+ rules = rulesList.ToArray();
+ if (rules != null && rules.Length == 0)
+ {
+ rules = null;
+ }
+ }
+ }
+
+ static private void TZif_GenerateAdjustmentRule(ref int index, TimeSpan timeZoneBaseUtcOffset, List<AdjustmentRule> rulesList, DateTime[] dts,
+ Byte[] typeOfLocalTime, TZifType[] transitionTypes, Boolean[] StandardTime, Boolean[] GmtTime, string futureTransitionsPosixFormat)
+ {
+ // To generate AdjustmentRules, use the following approach:
+ // The first AdjustmentRule will go from DateTime.MinValue to the first transition time greater than DateTime.MinValue.
+ // Each middle AdjustmentRule wil go from dts[index-1] to dts[index].
+ // The last AdjustmentRule will go from dts[dts.Length-1] to Datetime.MaxValue.
+
+ // 0. Skip any DateTime.MinValue transition times. In newer versions of the tzfile, there
+ // is a "big bang" transition time, which is before the year 0001. Since any times before year 0001
+ // cannot be represented by DateTime, there is no reason to make AdjustmentRules for these unrepresentable time periods.
+ // 1. If there are no DateTime.MinValue times, the first AdjustmentRule goes from DateTime.MinValue
+ // to the first transition and uses the first standard transitionType (or the first transitionType if none of them are standard)
+ // 2. Create an AdjustmentRule for each transition, i.e. from dts[index - 1] to dts[index].
+ // This rule uses the transitionType[index - 1] and the whole AdjustmentRule only describes a single offset - either
+ // all daylight savings, or all stanard time.
+ // 3. After all the transitions are filled out, the last AdjustmentRule is created from either:
+ // a. a POSIX-style timezone description ("futureTransitionsPosixFormat"), if there is one or
+ // b. continue the last transition offset until DateTime.Max
+
+ while (index < dts.Length && dts[index] == DateTime.MinValue)
+ {
+ index++;
+ }
+
+ if (index == 0)
+ {
+ TZifType transitionType = TZif_GetEarlyDateTransitionType(transitionTypes);
+ DateTime endTransitionDate = dts[index];
+
+ TimeSpan transitionOffset = TZif_CalculateTransitionOffsetFromBase(transitionType.UtcOffset, timeZoneBaseUtcOffset);
+ TimeSpan daylightDelta = transitionType.IsDst ? transitionOffset : TimeSpan.Zero;
+ TimeSpan baseUtcDelta = transitionType.IsDst ? TimeSpan.Zero : transitionOffset;
+
+ AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(
+ DateTime.MinValue,
+ endTransitionDate.AddTicks(-1),
+ daylightDelta,
+ default(TransitionTime),
+ default(TransitionTime),
+ baseUtcDelta,
+ noDaylightTransitions: true);
+ rulesList.Add(r);
+ }
+ else if (index < dts.Length)
+ {
+ DateTime startTransitionDate = dts[index - 1];
+ TZifType startTransitionType = transitionTypes[typeOfLocalTime[index - 1]];
+
+ DateTime endTransitionDate = dts[index];
+
+ TimeSpan transitionOffset = TZif_CalculateTransitionOffsetFromBase(startTransitionType.UtcOffset, timeZoneBaseUtcOffset);
+ TimeSpan daylightDelta = startTransitionType.IsDst ? transitionOffset : TimeSpan.Zero;
+ TimeSpan baseUtcDelta = startTransitionType.IsDst ? TimeSpan.Zero : transitionOffset;
+
+ TransitionTime dstStart;
+ if (startTransitionType.IsDst)
+ {
+ // the TransitionTime fields are not used when AdjustmentRule.NoDaylightTransitions == true.
+ // However, there are some cases in the past where DST = true, and the daylight savings offset
+ // now equals what the current BaseUtcOffset is. In that case, the AdjustmentRule.DaylightOffset
+ // is going to be TimeSpan.Zero. But we still need to return 'true' from AdjustmentRule.HasDaylightSaving.
+ // To ensure we always return true from HasDaylightSaving, make a "special" dstStart that will make the logic
+ // in HasDaylightSaving return true.
+ dstStart = TransitionTime.CreateFixedDateRule(DateTime.MinValue.AddMilliseconds(2), 1, 1);
+ }
+ else
+ {
+ dstStart = default(TransitionTime);
+ }
+
+ AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(
+ startTransitionDate,
+ endTransitionDate.AddTicks(-1),
+ daylightDelta,
+ dstStart,
+ default(TransitionTime),
+ baseUtcDelta,
+ noDaylightTransitions: true);
+ rulesList.Add(r);
+ }
+ else
+ {
+ // create the AdjustmentRule that will be used for all DateTimes after the last transition
+
+ // NOTE: index == dts.Length
+ DateTime startTransitionDate = dts[index - 1];
+
+ if (!string.IsNullOrEmpty(futureTransitionsPosixFormat))
+ {
+ AdjustmentRule r = TZif_CreateAdjustmentRuleForPosixFormat(futureTransitionsPosixFormat, startTransitionDate, timeZoneBaseUtcOffset);
+ if (r != null)
+ {
+ rulesList.Add(r);
+ }
+ }
+ else
+ {
+ // just use the last transition as the rule which will be used until the end of time
+
+ TZifType transitionType = transitionTypes[typeOfLocalTime[index - 1]];
+ TimeSpan transitionOffset = TZif_CalculateTransitionOffsetFromBase(transitionType.UtcOffset, timeZoneBaseUtcOffset);
+ TimeSpan daylightDelta = transitionType.IsDst ? transitionOffset : TimeSpan.Zero;
+ TimeSpan baseUtcDelta = transitionType.IsDst ? TimeSpan.Zero : transitionOffset;
+
+ AdjustmentRule r = AdjustmentRule.CreateAdjustmentRule(
+ startTransitionDate,
+ DateTime.MaxValue,
+ daylightDelta,
+ default(TransitionTime),
+ default(TransitionTime),
+ baseUtcDelta,
+ noDaylightTransitions: true);
+ rulesList.Add(r);
+ }
+ }
+
+ index++;
+ }
+
+ private static TimeSpan TZif_CalculateTransitionOffsetFromBase(TimeSpan transitionOffset, TimeSpan timeZoneBaseUtcOffset)
+ {
+ TimeSpan result = transitionOffset - timeZoneBaseUtcOffset;
+
+ // TZif supports seconds-level granularity with offsets but TimeZoneInfo only supports minutes since it aligns
+ // with DateTimeOffset, SQL Server, and the W3C XML Specification
+ if (result.Ticks % TimeSpan.TicksPerMinute != 0)
+ {
+ result = new TimeSpan(result.Hours, result.Minutes, 0);
+ }
+
+ return result;
+ }
+
+ /// <summary>
+ /// Gets the first standard-time transition type, or simply the first transition type
+ /// if there are no standard transition types.
+ /// </summary>>
+ /// <remarks>
+ /// from 'man tzfile':
+ /// localtime(3) uses the first standard-time ttinfo structure in the file
+ /// (or simply the first ttinfo structure in the absence of a standard-time
+ /// structure) if either tzh_timecnt is zero or the time argument is less
+ /// than the first transition time recorded in the file.
+ /// </remarks>
+ private static TZifType TZif_GetEarlyDateTransitionType(TZifType[] transitionTypes)
+ {
+ for (int i = 0; i < transitionTypes.Length; i++)
+ {
+ TZifType transitionType = transitionTypes[i];
+ if (!transitionType.IsDst)
+ {
+ return transitionType;
+ }
+ }
+
+ if (transitionTypes.Length > 0)
+ {
+ return transitionTypes[0];
+ }
+
+ throw new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_NoTTInfoStructures"));
+ }
+
+ /// <summary>
+ /// Creates an AdjustmentRule given the POSIX TZ environment variable string.
+ /// </summary>
+ /// <remarks>
+ /// See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html for the format and semantics of this POSX string.
+ /// </remarks>
+ private static AdjustmentRule TZif_CreateAdjustmentRuleForPosixFormat(string posixFormat, DateTime startTransitionDate, TimeSpan timeZoneBaseUtcOffset)
+ {
+ string standardName;
+ string standardOffset;
+ string daylightSavingsName;
+ string daylightSavingsOffset;
+ string start;
+ string startTime;
+ string end;
+ string endTime;
+
+ if (TZif_ParsePosixFormat(posixFormat, out standardName, out standardOffset, out daylightSavingsName,
+ out daylightSavingsOffset, out start, out startTime, out end, out endTime))
+ {
+ // a valid posixFormat has at least standardName and standardOffset
+
+ TimeSpan? parsedBaseOffset = TZif_ParseOffsetString(standardOffset);
+ if (parsedBaseOffset.HasValue)
+ {
+ TimeSpan baseOffset = parsedBaseOffset.Value.Negate(); // offsets are backwards in POSIX notation
+ baseOffset = TZif_CalculateTransitionOffsetFromBase(baseOffset, timeZoneBaseUtcOffset);
+
+ // having a daylightSavingsName means there is a DST rule
+ if (!string.IsNullOrEmpty(daylightSavingsName))
+ {
+ TimeSpan? parsedDaylightSavings = TZif_ParseOffsetString(daylightSavingsOffset);
+ TimeSpan daylightSavingsTimeSpan;
+ if (!parsedDaylightSavings.HasValue)
+ {
+ // default DST to 1 hour if it isn't specified
+ daylightSavingsTimeSpan = new TimeSpan(1, 0, 0);
+ }
+ else
+ {
+ daylightSavingsTimeSpan = parsedDaylightSavings.Value.Negate(); // offsets are backwards in POSIX notation
+ daylightSavingsTimeSpan = TZif_CalculateTransitionOffsetFromBase(daylightSavingsTimeSpan, timeZoneBaseUtcOffset);
+ daylightSavingsTimeSpan = TZif_CalculateTransitionOffsetFromBase(daylightSavingsTimeSpan, baseOffset);
+ }
+
+ TransitionTime dstStart = TZif_CreateTransitionTimeFromPosixRule(start, startTime);
+ TransitionTime dstEnd = TZif_CreateTransitionTimeFromPosixRule(end, endTime);
+
+ return AdjustmentRule.CreateAdjustmentRule(
+ startTransitionDate,
+ DateTime.MaxValue,
+ daylightSavingsTimeSpan,
+ dstStart,
+ dstEnd,
+ baseOffset,
+ noDaylightTransitions: false);
+ }
+ else
+ {
+ // if there is no daylightSavingsName, the whole AdjustmentRule should be with no transitions - just the baseOffset
+ return AdjustmentRule.CreateAdjustmentRule(
+ startTransitionDate,
+ DateTime.MaxValue,
+ TimeSpan.Zero,
+ default(TransitionTime),
+ default(TransitionTime),
+ baseOffset,
+ noDaylightTransitions: true);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private static TimeSpan? TZif_ParseOffsetString(string offset)
+ {
+ TimeSpan? result = null;
+
+ if (!string.IsNullOrEmpty(offset))
+ {
+ bool negative = offset[0] == '-';
+ if (negative || offset[0] == '+')
+ {
+ offset = offset.Substring(1);
+ }
+
+ // Try parsing just hours first.
+ // Note, TimeSpan.TryParseExact "%h" can't be used here because some time zones using values
+ // like "26" or "144" and TimeSpan parsing would turn that into 26 or 144 *days* instead of hours.
+ int hours;
+ if (int.TryParse(offset, out hours))
+ {
+ result = new TimeSpan(hours, 0, 0);
+ }
+ else
+ {
+ TimeSpan parsedTimeSpan;
+ if (TimeSpan.TryParseExact(offset, "g", CultureInfo.InvariantCulture, out parsedTimeSpan))
+ {
+ result = parsedTimeSpan;
+ }
+ }
+
+ if (result.HasValue && negative)
+ {
+ result = result.Value.Negate();
+ }
+ }
+
+ return result;
+ }
+
+ private static TransitionTime TZif_CreateTransitionTimeFromPosixRule(string date, string time)
+ {
+ if (string.IsNullOrEmpty(date))
+ {
+ return default(TransitionTime);
+ }
+
+ if (date[0] == 'M')
+ {
+ // Mm.w.d
+ // This specifies day d of week w of month m. The day d must be between 0(Sunday) and 6.The week w must be between 1 and 5;
+ // week 1 is the first week in which day d occurs, and week 5 specifies the last d day in the month. The month m should be between 1 and 12.
+
+ int month;
+ int week;
+ DayOfWeek day;
+ if (!TZif_ParseMDateRule(date, out month, out week, out day))
+ {
+ throw new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_UnparseablePosixMDateString", date));
+ }
+
+ DateTime timeOfDay;
+ TimeSpan? timeOffset = TZif_ParseOffsetString(time);
+ if (timeOffset.HasValue)
+ {
+ // This logic isn't correct and can't be corrected until https://github.com/dotnet/corefx/issues/2618 is fixed.
+ // Some time zones use time values like, "26", "144", or "-2".
+ // This allows the week to sometimes be week 4 and sometimes week 5 in the month.
+ // For now, strip off any 'days' in the offset, and just get the time of day correct
+ timeOffset = new TimeSpan(timeOffset.Value.Hours, timeOffset.Value.Minutes, timeOffset.Value.Seconds);
+ if (timeOffset.Value < TimeSpan.Zero)
+ {
+ timeOfDay = new DateTime(1, 1, 2, 0, 0, 0);
+ }
+ else
+ {
+ timeOfDay = new DateTime(1, 1, 1, 0, 0, 0);
+ }
+
+ timeOfDay += timeOffset.Value;
+ }
+ else
+ {
+ // default to 2AM.
+ timeOfDay = new DateTime(1, 1, 1, 2, 0, 0);
+ }
+
+ return TransitionTime.CreateFloatingDateRule(timeOfDay, month, week, day);
+ }
+ else
+ {
+ // Jn
+ // This specifies the Julian day, with n between 1 and 365.February 29 is never counted, even in leap years.
+
+ // n
+ // This specifies the Julian day, with n between 0 and 365.February 29 is counted in leap years.
+
+ // These two rules cannot be expressed with the current AdjustmentRules
+ // One of them *could* be supported if we relaxed the TransitionTime validation rules, and allowed
+ // "IsFixedDateRule = true, Month = 0, Day = n" to mean the nth day of the year, picking one of the rules above
+
+ throw new InvalidTimeZoneException(Environment.GetResourceString("InvalidTimeZone_JulianDayNotSupported"));
+ }
+ }
+
+ /// <summary>
+ /// Parses a string like Mm.w.d into month, week and DayOfWeek values.
+ /// </summary>
+ /// <returns>
+ /// true if the parsing succeeded; otherwise, false.
+ /// </returns>
+ private static bool TZif_ParseMDateRule(string dateRule, out int month, out int week, out DayOfWeek dayOfWeek)
+ {
+ month = 0;
+ week = 0;
+ dayOfWeek = default(DayOfWeek);
+
+ if (dateRule[0] == 'M')
+ {
+ int firstDotIndex = dateRule.IndexOf('.');
+ if (firstDotIndex > 0)
+ {
+ int secondDotIndex = dateRule.IndexOf('.', firstDotIndex + 1);
+ if (secondDotIndex > 0)
+ {
+ string monthString = dateRule.Substring(1, firstDotIndex - 1);
+ string weekString = dateRule.Substring(firstDotIndex + 1, secondDotIndex - firstDotIndex - 1);
+ string dayString = dateRule.Substring(secondDotIndex + 1);
+
+ if (int.TryParse(monthString, out month))
+ {
+ if (int.TryParse(weekString, out week))
+ {
+ int day;
+ if (int.TryParse(dayString, out day))
+ {
+ dayOfWeek = (DayOfWeek)day;
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static bool TZif_ParsePosixFormat(
+ string posixFormat,
+ out string standardName,
+ out string standardOffset,
+ out string daylightSavingsName,
+ out string daylightSavingsOffset,
+ out string start,
+ out string startTime,
+ out string end,
+ out string endTime)
+ {
+ standardName = null;
+ standardOffset = null;
+ daylightSavingsName = null;
+ daylightSavingsOffset = null;
+ start = null;
+ startTime = null;
+ end = null;
+ endTime = null;
+
+ int index = 0;
+ standardName = TZif_ParsePosixName(posixFormat, ref index);
+ standardOffset = TZif_ParsePosixOffset(posixFormat, ref index);
+
+ daylightSavingsName = TZif_ParsePosixName(posixFormat, ref index);
+ if (!string.IsNullOrEmpty(daylightSavingsName))
+ {
+ daylightSavingsOffset = TZif_ParsePosixOffset(posixFormat, ref index);
+
+ if (index < posixFormat.Length && posixFormat[index] == ',')
+ {
+ index++;
+ TZif_ParsePosixDateTime(posixFormat, ref index, out start, out startTime);
+
+ if (index < posixFormat.Length && posixFormat[index] == ',')
+ {
+ index++;
+ TZif_ParsePosixDateTime(posixFormat, ref index, out end, out endTime);
+ }
+ }
+ }
+
+ return !string.IsNullOrEmpty(standardName) && !string.IsNullOrEmpty(standardOffset);
+ }
+
+ private static string TZif_ParsePosixName(string posixFormat, ref int index)
+ {
+ return TZif_ParsePosixString(posixFormat, ref index, c => char.IsDigit(c) || c == '+' || c == '-' || c == ',');
+ }
+
+ private static string TZif_ParsePosixOffset(string posixFormat, ref int index)
+ {
+ return TZif_ParsePosixString(posixFormat, ref index, c => !char.IsDigit(c) && c != '+' && c != '-' && c != ':');
+ }
+
+ private static void TZif_ParsePosixDateTime(string posixFormat, ref int index, out string date, out string time)
+ {
+ time = null;
+
+ date = TZif_ParsePosixDate(posixFormat, ref index);
+ if (index < posixFormat.Length && posixFormat[index] == '/')
+ {
+ index++;
+ time = TZif_ParsePosixTime(posixFormat, ref index);
+ }
+ }
+
+ private static string TZif_ParsePosixDate(string posixFormat, ref int index)
+ {
+ return TZif_ParsePosixString(posixFormat, ref index, c => c == '/' || c == ',');
+ }
+
+ private static string TZif_ParsePosixTime(string posixFormat, ref int index)
+ {
+ return TZif_ParsePosixString(posixFormat, ref index, c => c == ',');
+ }
+
+ private static string TZif_ParsePosixString(string posixFormat, ref int index, Func<char, bool> breakCondition)
+ {
+ int startIndex = index;
+ for (; index < posixFormat.Length; index++)
+ {
+ char current = posixFormat[index];
+ if (breakCondition(current))
+ {
+ break;
+ }
+ }
+
+ return posixFormat.Substring(startIndex, index - startIndex);
+ }
+
+ // Returns the Substring from zoneAbbreviations starting at index and ending at '\0'
+ // zoneAbbreviations is expected to be in the form: "PST\0PDT\0PWT\0\PPT"
+ static private String TZif_GetZoneAbbreviation(String zoneAbbreviations, int index) {
+ int lastIndex = zoneAbbreviations.IndexOf('\0', index);
+ if (lastIndex > 0) {
+ return zoneAbbreviations.Substring(index, lastIndex - index);
+ }
+ else {
+ return zoneAbbreviations.Substring(index);
+ }
+ }
+
+ // Converts an array of bytes into an int - always using standard byte order (Big Endian)
+ // per TZif file standard
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private unsafe int TZif_ToInt32 (byte[]value, int startIndex) {
+ fixed( byte * pbyte = &value[startIndex]) {
+ return (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ }
+ }
+
+ // Converts an array of bytes into a long - always using standard byte order (Big Endian)
+ // per TZif file standard
+ [System.Security.SecuritySafeCritical] // auto-generated
+ static private unsafe long TZif_ToInt64(byte[] value, int startIndex)
+ {
+ fixed (byte* pbyte = &value[startIndex])
+ {
+ int i1 = (*pbyte << 24) | (*(pbyte + 1) << 16) | (*(pbyte + 2) << 8) | (*(pbyte + 3));
+ int i2 = (*(pbyte + 4) << 24) | (*(pbyte + 5) << 16) | (*(pbyte + 6) << 8) | (*(pbyte + 7));
+ return (uint)i2 | ((long)i1 << 32);
+ }
+ }
+
+ static private long TZif_ToUnixTime(byte[] value, int startIndex, TZVersion version)
+ {
+ if (version != TZVersion.V1)
+ {
+ return TZif_ToInt64(value, startIndex);
+ }
+ else
+ {
+ return TZif_ToInt32(value, startIndex);
+ }
+ }
+
+ private static DateTime TZif_UnixTimeToDateTime(long unixTime)
+ {
+ if (unixTime < DateTimeOffset.UnixMinSeconds)
+ {
+ return DateTime.MinValue;
+ }
+
+ if (unixTime > DateTimeOffset.UnixMaxSeconds)
+ {
+ return DateTime.MaxValue;
+ }
+
+ return DateTimeOffset.FromUnixTimeSeconds(unixTime).UtcDateTime;
+ }
+
+ static private void TZif_ParseRaw(Byte[] data, out TZifHead t, out DateTime[] dts, out Byte[] typeOfLocalTime, out TZifType[] transitionType,
+ out String zoneAbbreviations, out Boolean[] StandardTime, out Boolean[] GmtTime, out string futureTransitionsPosixFormat)
+ {
+ // initialize the out parameters in case the TZifHead ctor throws
+ dts = null;
+ typeOfLocalTime = null;
+ transitionType = null;
+ zoneAbbreviations = String.Empty;
+ StandardTime = null;
+ GmtTime = null;
+ futureTransitionsPosixFormat = null;
+
+ // read in the 44-byte TZ header containing the count/length fields
+ //
+ int index = 0;
+ t = new TZifHead(data, index);
+ index += TZifHead.Length;
+
+ int timeValuesLength = 4; // the first version uses 4-bytes to specify times
+ if (t.Version != TZVersion.V1)
+ {
+ // move index past the V1 information to read the V2 information
+ index += (int)((timeValuesLength * t.TimeCount) + t.TimeCount + (6 * t.TypeCount) + ((timeValuesLength + 4) * t.LeapCount) + t.IsStdCount + t.IsGmtCount + t.CharCount);
+
+ // read the V2 header
+ t = new TZifHead(data, index);
+ index += TZifHead.Length;
+ timeValuesLength = 8; // the second version uses 8-bytes
+ }
+
+ // initialize the containers for the rest of the TZ data
+ dts = new DateTime[t.TimeCount];
+ typeOfLocalTime = new Byte[t.TimeCount];
+ transitionType = new TZifType[t.TypeCount];
+ zoneAbbreviations = String.Empty;
+ StandardTime = new Boolean[t.TypeCount];
+ GmtTime = new Boolean[t.TypeCount];
+
+ // read in the UTC transition points and convert them to Windows
+ //
+ for (int i = 0; i < t.TimeCount; i++) {
+ long unixTime = TZif_ToUnixTime(data, index, t.Version);
+ dts[i] = TZif_UnixTimeToDateTime(unixTime);
+ index += timeValuesLength;
+ }
+
+ // read in the Type Indices; there is a 1:1 mapping of UTC transition points to Type Indices
+ // these indices directly map to the array index in the transitionType array below
+ //
+ for (int i = 0; i < t.TimeCount; i++) {
+ typeOfLocalTime[i] = data[index];
+ index += 1;
+ }
+
+ // read in the Type table. Each 6-byte entry represents
+ // {UtcOffset, IsDst, AbbreviationIndex}
+ //
+ // each AbbreviationIndex is a character index into the zoneAbbreviations string below
+ //
+ for (int i = 0; i < t.TypeCount; i++) {
+ transitionType[i] = new TZifType(data, index);
+ index += 6;
+ }
+
+ // read in the Abbreviation ASCII string. This string will be in the form:
+ // "PST\0PDT\0PWT\0\PPT"
+ //
+ System.Text.Encoding enc = new System.Text.UTF8Encoding();
+ zoneAbbreviations = enc.GetString(data, index, (int)t.CharCount);
+ index += (int)t.CharCount;
+
+ // skip ahead of the Leap-Seconds Adjustment data. In a future release, consider adding
+ // support for Leap-Seconds
+ //
+ index += (int)(t.LeapCount * (timeValuesLength + 4)); // skip the leap second transition times
+
+ // read in the Standard Time table. There should be a 1:1 mapping between Type-Index and Standard
+ // Time table entries.
+ //
+ // TRUE = transition time is standard time
+ // FALSE = transition time is wall clock time
+ // ABSENT = transition time is wall clock time
+ //
+ for (int i = 0; i < t.IsStdCount && i < t.TypeCount && index < data.Length; i++) {
+ StandardTime[i] = (data[index++] != 0);
+ }
+
+ // read in the GMT Time table. There should be a 1:1 mapping between Type-Index and GMT Time table
+ // entries.
+ //
+ // TRUE = transition time is UTC
+ // FALSE = transition time is local time
+ // ABSENT = transition time is local time
+ //
+ for (int i = 0; i < t.IsGmtCount && i < t.TypeCount && index < data.Length; i++) {
+ GmtTime[i] = (data[index++] != 0);
+ }
+
+ if (t.Version != TZVersion.V1)
+ {
+ // read the POSIX-style format, which should be wrapped in newlines with the last newline at the end of the file
+ if (data[index++] == '\n' && data[data.Length - 1] == '\n')
+ {
+ futureTransitionsPosixFormat = enc.GetString(data, index, data.Length - index - 1);
+ }
+ }
+ }
+#endif // PLATFORM_UNIX
+
+ //
+ // UtcOffsetOutOfRange -
+ //
+ // Helper function that validates the TimeSpan is within +/- 14.0 hours
+ //
+ [Pure]
+ static internal Boolean UtcOffsetOutOfRange(TimeSpan offset) {
+ return (offset.TotalHours < -14.0 || offset.TotalHours > 14.0);
+ }
+
+
+ //
+ // ValidateTimeZoneInfo -
+ //
+ // Helper function that performs all of the validation checks for the
+ // factory methods and deserialization callback
+ //
+ // returns a Boolean indicating whether the AdjustmentRule[] supports DST
+ //
+ static private void ValidateTimeZoneInfo(
+ String id,
+ TimeSpan baseUtcOffset,
+ AdjustmentRule [] adjustmentRules,
+ out Boolean adjustmentRulesSupportDst) {
+
+ if (id == null) {
+ throw new ArgumentNullException("id");
+ }
+
+ if (id.Length == 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidId", id), "id");
+ }
+
+ if (UtcOffsetOutOfRange(baseUtcOffset)) {
+
+ throw new ArgumentOutOfRangeException("baseUtcOffset", Environment.GetResourceString("ArgumentOutOfRange_UtcOffset"));
+ }
+
+ if (baseUtcOffset.Ticks % TimeSpan.TicksPerMinute != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_TimeSpanHasSeconds"), "baseUtcOffset");
+ }
+ Contract.EndContractBlock();
+
+ adjustmentRulesSupportDst = false;
+
+ //
+ // "adjustmentRules" can either be null or a valid array of AdjustmentRule objects.
+ // A valid array is one that does not contain any null elements and all elements
+ // are sorted in chronological order
+ //
+
+ if (adjustmentRules != null && adjustmentRules.Length != 0) {
+ adjustmentRulesSupportDst = true;
+ AdjustmentRule prev = null;
+ AdjustmentRule current = null;
+ for (int i = 0; i < adjustmentRules.Length; i++) {
+ prev = current;
+ current = adjustmentRules[i];
+
+ if (current == null) {
+ throw new InvalidTimeZoneException(Environment.GetResourceString("Argument_AdjustmentRulesNoNulls"));
+ }
+
+ // FUTURE: check to see if this rule supports Daylight Saving Time
+ // adjustmentRulesSupportDst = adjustmentRulesSupportDst || current.SupportsDaylightSavingTime;
+ // FUTURE: test baseUtcOffset + current.StandardDelta
+
+ if (UtcOffsetOutOfRange(baseUtcOffset + current.DaylightDelta)) {
+ throw new InvalidTimeZoneException(Environment.GetResourceString("ArgumentOutOfRange_UtcOffsetAndDaylightDelta"));
+ }
+
+ if (prev != null && current.DateStart <= prev.DateEnd) {
+ // verify the rules are in chronological order and the DateStart/DateEnd do not overlap
+ throw new InvalidTimeZoneException(Environment.GetResourceString("Argument_AdjustmentRulesOutOfOrder"));
+ }
+ }
+ }
+ }
+
+/*============================================================
+**
+** Class: TimeZoneInfo.AdjustmentRule
+**
+**
+** Purpose:
+** This class is used to represent a Dynamic TimeZone. It
+** has methods for converting a DateTime to UTC from local time
+** and to local time from UTC and methods for getting the
+** standard name and daylight name of the time zone.
+**
+**
+============================================================*/
+ [Serializable]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ sealed public class AdjustmentRule : IEquatable<AdjustmentRule>, ISerializable, IDeserializationCallback
+ {
+
+ // ---- SECTION: members supporting exposed properties -------------*
+ private DateTime m_dateStart;
+ private DateTime m_dateEnd;
+ private TimeSpan m_daylightDelta;
+ private TransitionTime m_daylightTransitionStart;
+ private TransitionTime m_daylightTransitionEnd;
+ private TimeSpan m_baseUtcOffsetDelta; // delta from the default Utc offset (utcOffset = defaultUtcOffset + m_baseUtcOffsetDelta)
+ private bool m_noDaylightTransitions;
+
+ // ---- SECTION: public properties --------------*
+ public DateTime DateStart {
+ get {
+ return this.m_dateStart;
+ }
+ }
+
+ public DateTime DateEnd {
+ get {
+ return this.m_dateEnd;
+ }
+ }
+
+ public TimeSpan DaylightDelta {
+ get {
+ return this.m_daylightDelta;
+ }
+ }
+
+
+ public TransitionTime DaylightTransitionStart {
+ get {
+ return this.m_daylightTransitionStart;
+ }
+ }
+
+
+ public TransitionTime DaylightTransitionEnd {
+ get {
+ return this.m_daylightTransitionEnd;
+ }
+ }
+
+ internal TimeSpan BaseUtcOffsetDelta {
+ get {
+ return this.m_baseUtcOffsetDelta;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating that this AdjustmentRule fixes the time zone offset
+ /// from DateStart to DateEnd without any daylight transitions in between.
+ /// </summary>
+ internal bool NoDaylightTransitions {
+ get {
+ return this.m_noDaylightTransitions;
+ }
+ }
+
+ internal bool HasDaylightSaving {
+ get {
+ return this.DaylightDelta != TimeSpan.Zero
+ ||
+ (this.DaylightTransitionStart != default(TransitionTime)
+ && this.DaylightTransitionStart.TimeOfDay != DateTime.MinValue)
+ ||
+ (this.DaylightTransitionEnd != default(TransitionTime)
+ && this.DaylightTransitionEnd.TimeOfDay != DateTime.MinValue.AddMilliseconds(1));
+ }
+ }
+
+ // ---- SECTION: public methods --------------*
+
+ // IEquatable<AdjustmentRule>
+ public bool Equals(AdjustmentRule other) {
+ bool equals = (other != null
+ && this.m_dateStart == other.m_dateStart
+ && this.m_dateEnd == other.m_dateEnd
+ && this.m_daylightDelta == other.m_daylightDelta
+ && this.m_baseUtcOffsetDelta == other.m_baseUtcOffsetDelta);
+
+ equals = equals && this.m_daylightTransitionEnd.Equals(other.m_daylightTransitionEnd)
+ && this.m_daylightTransitionStart.Equals(other.m_daylightTransitionStart);
+
+ return equals;
+ }
+
+
+ public override int GetHashCode() {
+ return m_dateStart.GetHashCode();
+ }
+
+
+
+ // -------- SECTION: constructors -----------------*
+
+ private AdjustmentRule() { }
+
+
+ // -------- SECTION: factory methods -----------------*
+
+ static internal AdjustmentRule CreateAdjustmentRule(
+ DateTime dateStart,
+ DateTime dateEnd,
+ TimeSpan daylightDelta,
+ TransitionTime daylightTransitionStart,
+ TransitionTime daylightTransitionEnd,
+ bool noDaylightTransitions) {
+ ValidateAdjustmentRule(dateStart, dateEnd, daylightDelta,
+ daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions);
+
+ AdjustmentRule rule = new AdjustmentRule();
+
+ rule.m_dateStart = dateStart;
+ rule.m_dateEnd = dateEnd;
+ rule.m_daylightDelta = daylightDelta;
+ rule.m_daylightTransitionStart = daylightTransitionStart;
+ rule.m_daylightTransitionEnd = daylightTransitionEnd;
+ rule.m_baseUtcOffsetDelta = TimeSpan.Zero;
+ rule.m_noDaylightTransitions = noDaylightTransitions;
+
+ return rule;
+ }
+
+ static public AdjustmentRule CreateAdjustmentRule(
+ DateTime dateStart,
+ DateTime dateEnd,
+ TimeSpan daylightDelta,
+ TransitionTime daylightTransitionStart,
+ TransitionTime daylightTransitionEnd)
+ {
+ return CreateAdjustmentRule(dateStart, dateEnd, daylightDelta,
+ daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions: false);
+ }
+
+ static internal AdjustmentRule CreateAdjustmentRule(
+ DateTime dateStart,
+ DateTime dateEnd,
+ TimeSpan daylightDelta,
+ TransitionTime daylightTransitionStart,
+ TransitionTime daylightTransitionEnd,
+ TimeSpan baseUtcOffsetDelta,
+ bool noDaylightTransitions) {
+ AdjustmentRule rule = CreateAdjustmentRule(dateStart, dateEnd, daylightDelta,
+ daylightTransitionStart, daylightTransitionEnd, noDaylightTransitions);
+
+ rule.m_baseUtcOffsetDelta = baseUtcOffsetDelta;
+ return rule;
+ }
+
+ // ----- SECTION: internal utility methods ----------------*
+
+ //
+ // When Windows sets the daylight transition start Jan 1st at 12:00 AM, it means the year starts with the daylight saving on.
+ // We have to special case this value and not adjust it when checking if any date is in the daylight saving period.
+ //
+ internal bool IsStartDateMarkerForBeginningOfYear() {
+ return !NoDaylightTransitions &&
+ DaylightTransitionStart.Month == 1 && DaylightTransitionStart.Day == 1 && DaylightTransitionStart.TimeOfDay.Hour == 0 &&
+ DaylightTransitionStart.TimeOfDay.Minute == 0 && DaylightTransitionStart.TimeOfDay.Second == 0 &&
+ m_dateStart.Year == m_dateEnd.Year;
+ }
+
+ //
+ // When Windows sets the daylight transition end Jan 1st at 12:00 AM, it means the year ends with the daylight saving on.
+ // We have to special case this value and not adjust it when checking if any date is in the daylight saving period.
+ //
+ internal bool IsEndDateMarkerForEndOfYear() {
+ return !NoDaylightTransitions &&
+ DaylightTransitionEnd.Month == 1 && DaylightTransitionEnd.Day == 1 && DaylightTransitionEnd.TimeOfDay.Hour == 0 &&
+ DaylightTransitionEnd.TimeOfDay.Minute == 0 && DaylightTransitionEnd.TimeOfDay.Second == 0 &&
+ m_dateStart.Year == m_dateEnd.Year;
+ }
+
+ //
+ // ValidateAdjustmentRule -
+ //
+ // Helper function that performs all of the validation checks for the
+ // factory methods and deserialization callback
+ //
+ static private void ValidateAdjustmentRule(
+ DateTime dateStart,
+ DateTime dateEnd,
+ TimeSpan daylightDelta,
+ TransitionTime daylightTransitionStart,
+ TransitionTime daylightTransitionEnd,
+ bool noDaylightTransitions) {
+
+
+ if (dateStart.Kind != DateTimeKind.Unspecified && dateStart.Kind != DateTimeKind.Utc) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), "dateStart");
+ }
+
+ if (dateEnd.Kind != DateTimeKind.Unspecified && dateEnd.Kind != DateTimeKind.Utc) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecifiedOrUtc"), "dateEnd");
+ }
+
+ if (daylightTransitionStart.Equals(daylightTransitionEnd) && !noDaylightTransitions) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_TransitionTimesAreIdentical"),
+ "daylightTransitionEnd");
+ }
+
+
+ if (dateStart > dateEnd) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_OutOfOrderDateTimes"), "dateStart");
+ }
+
+ // This cannot use UtcOffsetOutOfRange to account for the scenario where Samoa moved across the International Date Line,
+ // which caused their current BaseUtcOffset to be +13. But on the other side of the line it was UTC-11 (+1 for daylight).
+ // So when trying to describe DaylightDeltas for those times, the DaylightDelta needs
+ // to be -23 (what it takes to go from UTC+13 to UTC-10)
+ if (daylightDelta.TotalHours < -23.0 || daylightDelta.TotalHours > 14.0) {
+ throw new ArgumentOutOfRangeException("daylightDelta", daylightDelta,
+ Environment.GetResourceString("ArgumentOutOfRange_UtcOffset"));
+ }
+
+ if (daylightDelta.Ticks % TimeSpan.TicksPerMinute != 0) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_TimeSpanHasSeconds"),
+ "daylightDelta");
+ }
+
+ if (dateStart != DateTime.MinValue && dateStart.Kind == DateTimeKind.Unspecified && dateStart.TimeOfDay != TimeSpan.Zero) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTimeOfDay"),
+ "dateStart");
+ }
+
+ if (dateEnd != DateTime.MaxValue && dateEnd.Kind == DateTimeKind.Unspecified && dateEnd.TimeOfDay != TimeSpan.Zero) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTimeOfDay"),
+ "dateEnd");
+ }
+ Contract.EndContractBlock();
+ }
+
+
+
+ // ----- SECTION: private serialization instance methods ----------------*
+
+ void IDeserializationCallback.OnDeserialization(Object sender) {
+ // OnDeserialization is called after each instance of this class is deserialized.
+ // This callback method performs AdjustmentRule validation after being deserialized.
+
+ try {
+ ValidateAdjustmentRule(m_dateStart, m_dateEnd, m_daylightDelta,
+ m_daylightTransitionStart, m_daylightTransitionEnd, m_noDaylightTransitions);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ info.AddValue("DateStart", m_dateStart);
+ info.AddValue("DateEnd", m_dateEnd);
+ info.AddValue("DaylightDelta", m_daylightDelta);
+ info.AddValue("DaylightTransitionStart", m_daylightTransitionStart);
+ info.AddValue("DaylightTransitionEnd", m_daylightTransitionEnd);
+ info.AddValue("BaseUtcOffsetDelta", m_baseUtcOffsetDelta);
+ info.AddValue("NoDaylightTransitions", m_noDaylightTransitions);
+ }
+
+ AdjustmentRule(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+
+ m_dateStart = (DateTime)info.GetValue("DateStart", typeof(DateTime));
+ m_dateEnd = (DateTime)info.GetValue("DateEnd", typeof(DateTime));
+ m_daylightDelta = (TimeSpan)info.GetValue("DaylightDelta", typeof(TimeSpan));
+ m_daylightTransitionStart = (TransitionTime)info.GetValue("DaylightTransitionStart", typeof(TransitionTime));
+ m_daylightTransitionEnd = (TransitionTime)info.GetValue("DaylightTransitionEnd", typeof(TransitionTime));
+
+ object o = info.GetValueNoThrow("BaseUtcOffsetDelta", typeof(TimeSpan));
+ if (o != null) {
+ m_baseUtcOffsetDelta = (TimeSpan) o;
+ }
+
+ o = info.GetValueNoThrow("NoDaylightTransitions", typeof(bool));
+ if (o != null) {
+ m_noDaylightTransitions = (bool)o;
+ }
+ }
+ }
+
+
+/*============================================================
+**
+** Class: TimeZoneInfo.TransitionTime
+**
+**
+** Purpose:
+** This class is used to represent a Dynamic TimeZone. It
+** has methods for converting a DateTime to UTC from local time
+** and to local time from UTC and methods for getting the
+** standard name and daylight name of the time zone.
+**
+**
+============================================================*/
+ [Serializable]
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ public struct TransitionTime : IEquatable<TransitionTime>, ISerializable, IDeserializationCallback
+ {
+ // ---- SECTION: members supporting exposed properties -------------*
+ private DateTime m_timeOfDay;
+ private byte m_month;
+ private byte m_week;
+ private byte m_day;
+ private DayOfWeek m_dayOfWeek;
+ private Boolean m_isFixedDateRule;
+
+
+ // ---- SECTION: public properties --------------*
+ public DateTime TimeOfDay {
+ get {
+ return m_timeOfDay;
+ }
+ }
+
+ public Int32 Month {
+ get {
+ return (int)m_month;
+ }
+ }
+
+
+ public Int32 Week {
+ get {
+ return (int)m_week;
+ }
+ }
+
+ public Int32 Day {
+ get {
+ return (int)m_day;
+ }
+ }
+
+ public DayOfWeek DayOfWeek {
+ get {
+ return m_dayOfWeek;
+ }
+ }
+
+ public Boolean IsFixedDateRule {
+ get {
+ return m_isFixedDateRule;
+ }
+ }
+
+ // ---- SECTION: public methods --------------*
+ [Pure]
+ public override bool Equals(Object obj) {
+ if (obj is TransitionTime) {
+ return Equals((TransitionTime)obj);
+ }
+ return false;
+ }
+
+ public static bool operator ==(TransitionTime t1, TransitionTime t2) {
+ return t1.Equals(t2);
+ }
+
+ public static bool operator !=(TransitionTime t1, TransitionTime t2) {
+ return (!t1.Equals(t2));
+ }
+
+ [Pure]
+ public bool Equals(TransitionTime other) {
+
+ bool equal = (this.m_isFixedDateRule == other.m_isFixedDateRule
+ && this.m_timeOfDay == other.m_timeOfDay
+ && this.m_month == other.m_month);
+
+ if (equal) {
+ if (other.m_isFixedDateRule) {
+ equal = (this.m_day == other.m_day);
+ }
+ else {
+ equal = (this.m_week == other.m_week
+ && this.m_dayOfWeek == other.m_dayOfWeek);
+ }
+ }
+ return equal;
+ }
+
+
+ public override int GetHashCode() {
+ return ((int)m_month ^ (int)m_week << 8);
+ }
+
+
+ // -------- SECTION: constructors -----------------*
+/*
+ private TransitionTime() {
+ m_timeOfDay = new DateTime();
+ m_month = 0;
+ m_week = 0;
+ m_day = 0;
+ m_dayOfWeek = DayOfWeek.Sunday;
+ m_isFixedDateRule = false;
+ }
+*/
+
+
+ // -------- SECTION: factory methods -----------------*
+
+
+ static public TransitionTime CreateFixedDateRule(
+ DateTime timeOfDay,
+ Int32 month,
+ Int32 day) {
+
+ return CreateTransitionTime(timeOfDay, month, 1, day, DayOfWeek.Sunday, true);
+ }
+
+
+ static public TransitionTime CreateFloatingDateRule(
+ DateTime timeOfDay,
+ Int32 month,
+ Int32 week,
+ DayOfWeek dayOfWeek) {
+
+ return CreateTransitionTime(timeOfDay, month, week, 1, dayOfWeek, false);
+ }
+
+
+ static private TransitionTime CreateTransitionTime(
+ DateTime timeOfDay,
+ Int32 month,
+ Int32 week,
+ Int32 day,
+ DayOfWeek dayOfWeek,
+ Boolean isFixedDateRule) {
+
+ ValidateTransitionTime(timeOfDay, month, week, day, dayOfWeek);
+
+ TransitionTime t = new TransitionTime();
+ t.m_isFixedDateRule = isFixedDateRule;
+ t.m_timeOfDay = timeOfDay;
+ t.m_dayOfWeek = dayOfWeek;
+ t.m_day = (byte)day;
+ t.m_week = (byte)week;
+ t.m_month = (byte)month;
+
+ return t;
+ }
+
+
+ // ----- SECTION: internal utility methods ----------------*
+
+ //
+ // ValidateTransitionTime -
+ //
+ // Helper function that validates a TransitionTime instance
+ //
+ static private void ValidateTransitionTime(
+ DateTime timeOfDay,
+ Int32 month,
+ Int32 week,
+ Int32 day,
+ DayOfWeek dayOfWeek) {
+
+ if (timeOfDay.Kind != DateTimeKind.Unspecified) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeKindMustBeUnspecified"), "timeOfDay");
+ }
+
+ // Month range 1-12
+ if (month < 1 || month > 12) {
+ throw new ArgumentOutOfRangeException("month", Environment.GetResourceString("ArgumentOutOfRange_MonthParam"));
+ }
+
+ // Day range 1-31
+ if (day < 1 || day > 31) {
+ throw new ArgumentOutOfRangeException("day", Environment.GetResourceString("ArgumentOutOfRange_DayParam"));
+ }
+
+ // Week range 1-5
+ if (week < 1 || week > 5) {
+ throw new ArgumentOutOfRangeException("week", Environment.GetResourceString("ArgumentOutOfRange_Week"));
+ }
+
+ // DayOfWeek range 0-6
+ if ((int)dayOfWeek < 0 || (int)dayOfWeek > 6) {
+ throw new ArgumentOutOfRangeException("dayOfWeek", Environment.GetResourceString("ArgumentOutOfRange_DayOfWeek"));
+ }
+ Contract.EndContractBlock();
+
+ if (timeOfDay.Year != 1 || timeOfDay.Month != 1
+ || timeOfDay.Day != 1 || (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0)) {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeHasTicks"), "timeOfDay");
+ }
+ }
+
+ void IDeserializationCallback.OnDeserialization(Object sender) {
+ // OnDeserialization is called after each instance of this class is deserialized.
+ // This callback method performs TransitionTime validation after being deserialized.
+
+ try {
+ ValidateTransitionTime(m_timeOfDay, (Int32)m_month, (Int32)m_week, (Int32)m_day, m_dayOfWeek);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ info.AddValue("TimeOfDay", m_timeOfDay);
+ info.AddValue("Month", m_month);
+ info.AddValue("Week", m_week);
+ info.AddValue("Day", m_day);
+ info.AddValue("DayOfWeek", m_dayOfWeek);
+ info.AddValue("IsFixedDateRule", m_isFixedDateRule);
+ }
+
+ TransitionTime(SerializationInfo info, StreamingContext context) {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+
+ m_timeOfDay = (DateTime)info.GetValue("TimeOfDay", typeof(DateTime));
+ m_month = (byte)info.GetValue("Month", typeof(byte));
+ m_week = (byte)info.GetValue("Week", typeof(byte));
+ m_day = (byte)info.GetValue("Day", typeof(byte));
+ m_dayOfWeek = (DayOfWeek)info.GetValue("DayOfWeek", typeof(DayOfWeek));
+ m_isFixedDateRule = (Boolean)info.GetValue("IsFixedDateRule", typeof(Boolean));
+ }
+ }
+
+
+/*============================================================
+**
+** Class: TimeZoneInfo.StringSerializer
+**
+**
+** Purpose:
+** This class is used to serialize and deserialize TimeZoneInfo
+** objects based on the custom string serialization format
+**
+**
+============================================================*/
+ sealed private class StringSerializer {
+
+ // ---- SECTION: private members -------------*
+ private enum State {
+ Escaped = 0,
+ NotEscaped = 1,
+ StartOfToken = 2,
+ EndOfLine = 3
+ }
+
+ private String m_serializedText;
+ private int m_currentTokenStartIndex;
+ private State m_state;
+
+ // the majority of the strings contained in the OS time zones fit in 64 chars
+ private const int initialCapacityForString = 64;
+ private const char esc = '\\';
+ private const char sep = ';';
+ private const char lhs = '[';
+ private const char rhs = ']';
+ private const string escString = "\\";
+ private const string sepString = ";";
+ private const string lhsString = "[";
+ private const string rhsString = "]";
+ private const string escapedEsc = "\\\\";
+ private const string escapedSep = "\\;";
+ private const string escapedLhs = "\\[";
+ private const string escapedRhs = "\\]";
+ private const string dateTimeFormat = "MM:dd:yyyy";
+ private const string timeOfDayFormat = "HH:mm:ss.FFF";
+
+
+ // ---- SECTION: public static methods --------------*
+
+ //
+ // GetSerializedString -
+ //
+ // static method that creates the custom serialized string
+ // representation of a TimeZoneInfo instance
+ //
+ static public String GetSerializedString(TimeZoneInfo zone) {
+ StringBuilder serializedText = StringBuilderCache.Acquire();
+
+ //
+ // <m_id>;<m_baseUtcOffset>;<m_displayName>;<m_standardDisplayName>;<m_daylightDispayName>
+ //
+ serializedText.Append(SerializeSubstitute(zone.Id));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(
+ zone.BaseUtcOffset.TotalMinutes.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(zone.DisplayName));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(zone.StandardName));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(zone.DaylightName));
+ serializedText.Append(sep);
+
+ AdjustmentRule[] rules = zone.GetAdjustmentRules();
+
+ if (rules != null && rules.Length > 0) {
+ for (int i = 0; i < rules.Length; i++) {
+ AdjustmentRule rule = rules[i];
+
+ serializedText.Append(lhs);
+ serializedText.Append(SerializeSubstitute(rule.DateStart.ToString(
+ dateTimeFormat, DateTimeFormatInfo.InvariantInfo)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(rule.DateEnd.ToString(
+ dateTimeFormat, DateTimeFormatInfo.InvariantInfo)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(rule.DaylightDelta.TotalMinutes.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ // serialize the TransitionTime's
+ SerializeTransitionTime(rule.DaylightTransitionStart, serializedText);
+ serializedText.Append(sep);
+ SerializeTransitionTime(rule.DaylightTransitionEnd, serializedText);
+ serializedText.Append(sep);
+ if (rule.BaseUtcOffsetDelta != TimeSpan.Zero) { // Serialize it only when BaseUtcOffsetDelta has a value to reduce the impact of adding rule.BaseUtcOffsetDelta
+ serializedText.Append(SerializeSubstitute(rule.BaseUtcOffsetDelta.TotalMinutes.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ }
+ if (rule.NoDaylightTransitions) { // Serialize it only when NoDaylightTransitions is true to reduce the impact of adding rule.NoDaylightTransitions
+ serializedText.Append(SerializeSubstitute("1"));
+ serializedText.Append(sep);
+ }
+ serializedText.Append(rhs);
+ }
+ }
+ serializedText.Append(sep);
+ return StringBuilderCache.GetStringAndRelease(serializedText);
+ }
+
+
+ //
+ // GetDeserializedTimeZoneInfo -
+ //
+ // static method that instantiates a TimeZoneInfo from a custom serialized
+ // string
+ //
+ static public TimeZoneInfo GetDeserializedTimeZoneInfo(String source) {
+ StringSerializer s = new StringSerializer(source);
+
+ String id = s.GetNextStringValue(false);
+ TimeSpan baseUtcOffset = s.GetNextTimeSpanValue(false);
+ String displayName = s.GetNextStringValue(false);
+ String standardName = s.GetNextStringValue(false);
+ String daylightName = s.GetNextStringValue(false);
+ AdjustmentRule[] rules = s.GetNextAdjustmentRuleArrayValue(false);
+
+ try {
+ return TimeZoneInfo.CreateCustomTimeZone(id, baseUtcOffset, displayName, standardName, daylightName, rules);
+ }
+ catch (ArgumentException ex) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), ex);
+ }
+ catch (InvalidTimeZoneException ex) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), ex);
+ }
+ }
+
+ // ---- SECTION: public instance methods --------------*
+
+
+ // -------- SECTION: constructors -----------------*
+
+ //
+ // StringSerializer -
+ //
+ // private constructor - used by GetDeserializedTimeZoneInfo()
+ //
+ private StringSerializer(String str) {
+ m_serializedText = str;
+ m_state = State.StartOfToken;
+ }
+
+
+
+ // ----- SECTION: internal static utility methods ----------------*
+
+ //
+ // SerializeSubstitute -
+ //
+ // returns a new string with all of the reserved sub-strings escaped
+ //
+ // ";" -> "\;"
+ // "[" -> "\["
+ // "]" -> "\]"
+ // "\" -> "\\"
+ //
+ static private String SerializeSubstitute(String text) {
+ text = text.Replace(escString, escapedEsc);
+ text = text.Replace(lhsString, escapedLhs);
+ text = text.Replace(rhsString, escapedRhs);
+ return text.Replace(sepString, escapedSep);
+ }
+
+
+ //
+ // SerializeTransitionTime -
+ //
+ // Helper method to serialize a TimeZoneInfo.TransitionTime object
+ //
+ static private void SerializeTransitionTime(TransitionTime time, StringBuilder serializedText) {
+ serializedText.Append(lhs);
+ Int32 fixedDate = (time.IsFixedDateRule ? 1 : 0);
+ serializedText.Append(fixedDate.ToString(CultureInfo.InvariantCulture));
+ serializedText.Append(sep);
+
+ if (time.IsFixedDateRule) {
+ serializedText.Append(SerializeSubstitute(time.TimeOfDay.ToString(timeOfDayFormat, DateTimeFormatInfo.InvariantInfo)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(time.Month.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(time.Day.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ }
+ else {
+ serializedText.Append(SerializeSubstitute(time.TimeOfDay.ToString(timeOfDayFormat, DateTimeFormatInfo.InvariantInfo)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(time.Month.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(time.Week.ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ serializedText.Append(SerializeSubstitute(((int)time.DayOfWeek).ToString(CultureInfo.InvariantCulture)));
+ serializedText.Append(sep);
+ }
+ serializedText.Append(rhs);
+ }
+
+ //
+ // VerifyIsEscapableCharacter -
+ //
+ // Helper function to determine if the passed in string token is allowed to be preceeded by an escape sequence token
+ //
+ static private void VerifyIsEscapableCharacter(char c) {
+ if (c != esc && c != sep && c != lhs && c != rhs) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidEscapeSequence", c));
+ }
+ }
+
+ // ----- SECTION: internal instance utility methods ----------------*
+
+ //
+ // SkipVersionNextDataFields -
+ //
+ // Helper function that reads past "v.Next" data fields. Receives a "depth" parameter indicating the
+ // current relative nested bracket depth that m_currentTokenStartIndex is at. The function ends
+ // successfully when "depth" returns to zero (0).
+ //
+ //
+ private void SkipVersionNextDataFields(Int32 depth /* starting depth in the nested brackets ('[', ']')*/) {
+ if (m_currentTokenStartIndex < 0 || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ State tokenState = State.NotEscaped;
+
+ // walk the serialized text, building up the token as we go...
+ for (int i = m_currentTokenStartIndex; i < m_serializedText.Length; i++) {
+ if (tokenState == State.Escaped) {
+ VerifyIsEscapableCharacter(m_serializedText[i]);
+ tokenState = State.NotEscaped;
+ }
+ else if (tokenState == State.NotEscaped) {
+ switch (m_serializedText[i]) {
+ case esc:
+ tokenState = State.Escaped;
+ break;
+
+ case lhs:
+ depth++;
+ break;
+ case rhs:
+ depth--;
+ if (depth == 0) {
+ m_currentTokenStartIndex = i + 1;
+ if (m_currentTokenStartIndex >= m_serializedText.Length) {
+ m_state = State.EndOfLine;
+ }
+ else {
+ m_state = State.StartOfToken;
+ }
+ return;
+ }
+ break;
+
+ case '\0':
+ // invalid character
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+
+ default:
+ break;
+ }
+ }
+ }
+
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+
+ //
+ // GetNextStringValue -
+ //
+ // Helper function that reads a string token from the serialized text. The function
+ // updates the m_currentTokenStartIndex to point to the next token on exit. Also m_state
+ // is set to either State.StartOfToken or State.EndOfLine on exit.
+ //
+ // The function takes a parameter "canEndWithoutSeparator".
+ //
+ // * When set to 'false' the function requires the string token end with a ";".
+ // * When set to 'true' the function requires that the string token end with either
+ // ";", State.EndOfLine, or "]". In the case that "]" is the terminal case the
+ // m_currentTokenStartIndex is left pointing at index "]" to allow the caller to update
+ // its depth logic.
+ //
+ private String GetNextStringValue(Boolean canEndWithoutSeparator) {
+
+ // first verify the internal state of the object
+ if (m_state == State.EndOfLine) {
+ if (canEndWithoutSeparator) {
+ return null;
+ }
+ else {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ }
+ if (m_currentTokenStartIndex < 0 || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ State tokenState = State.NotEscaped;
+ StringBuilder token = StringBuilderCache.Acquire(initialCapacityForString);
+
+ // walk the serialized text, building up the token as we go...
+ for (int i = m_currentTokenStartIndex; i < m_serializedText.Length; i++) {
+ if (tokenState == State.Escaped) {
+ VerifyIsEscapableCharacter(m_serializedText[i]);
+ token.Append(m_serializedText[i]);
+ tokenState = State.NotEscaped;
+ }
+ else if (tokenState == State.NotEscaped) {
+ switch (m_serializedText[i]) {
+ case esc:
+ tokenState = State.Escaped;
+ break;
+
+ case lhs:
+ // '[' is an unexpected character
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+
+ case rhs:
+ if (canEndWithoutSeparator) {
+ // if ';' is not a required terminal then treat ']' as a terminal
+ // leave m_currentTokenStartIndex pointing to ']' so our callers can handle
+ // this special case
+ m_currentTokenStartIndex = i;
+ m_state = State.StartOfToken;
+ return token.ToString();
+ }
+ else {
+ // ']' is an unexpected character
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ case sep:
+ m_currentTokenStartIndex = i + 1;
+ if (m_currentTokenStartIndex >= m_serializedText.Length) {
+ m_state = State.EndOfLine;
+ }
+ else {
+ m_state = State.StartOfToken;
+ }
+ return StringBuilderCache.GetStringAndRelease(token);
+
+ case '\0':
+ // invalid character
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+
+ default:
+ token.Append(m_serializedText[i]);
+ break;
+ }
+ }
+ }
+ //
+ // we are at the end of the line
+ //
+ if (tokenState == State.Escaped) {
+ // we are at the end of the serialized text but we are in an escaped state
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidEscapeSequence", String.Empty));
+ }
+
+ if (!canEndWithoutSeparator) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ m_currentTokenStartIndex = m_serializedText.Length;
+ m_state = State.EndOfLine;
+ return StringBuilderCache.GetStringAndRelease(token);
+ }
+
+ //
+ // GetNextDateTimeValue -
+ //
+ // Helper function to read a DateTime token. Takes a boolean "canEndWithoutSeparator"
+ // and a "format" string.
+ //
+ private DateTime GetNextDateTimeValue(Boolean canEndWithoutSeparator, string format) {
+ String token = GetNextStringValue(canEndWithoutSeparator);
+ DateTime time;
+ if (!DateTime.TryParseExact(token, format, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out time)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ return time;
+ }
+
+ //
+ // GetNextTimeSpanValue -
+ //
+ // Helper function to read a DateTime token. Takes a boolean "canEndWithoutSeparator".
+ //
+ private TimeSpan GetNextTimeSpanValue(Boolean canEndWithoutSeparator) {
+ Int32 token = GetNextInt32Value(canEndWithoutSeparator);
+
+ try {
+ return new TimeSpan(0 /* hours */, token /* minutes */, 0 /* seconds */);
+ }
+ catch (ArgumentOutOfRangeException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+
+
+ //
+ // GetNextInt32Value -
+ //
+ // Helper function to read an Int32 token. Takes a boolean "canEndWithoutSeparator".
+ //
+ private Int32 GetNextInt32Value(Boolean canEndWithoutSeparator) {
+ String token = GetNextStringValue(canEndWithoutSeparator);
+ Int32 value;
+ if (!Int32.TryParse(token, NumberStyles.AllowLeadingSign /* "[sign]digits" */, CultureInfo.InvariantCulture, out value)) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ return value;
+ }
+
+
+ //
+ // GetNextAdjustmentRuleArrayValue -
+ //
+ // Helper function to read an AdjustmentRule[] token. Takes a boolean "canEndWithoutSeparator".
+ //
+ private AdjustmentRule[] GetNextAdjustmentRuleArrayValue(Boolean canEndWithoutSeparator) {
+ List<AdjustmentRule> rules = new List<AdjustmentRule>(1);
+ int count = 0;
+
+ // individual AdjustmentRule array elements do not require semicolons
+ AdjustmentRule rule = GetNextAdjustmentRuleValue(true);
+ while (rule != null) {
+ rules.Add(rule);
+ count++;
+
+ rule = GetNextAdjustmentRuleValue(true);
+ }
+
+ if (!canEndWithoutSeparator) {
+ // the AdjustmentRule array must end with a separator
+ if (m_state == State.EndOfLine) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ if (m_currentTokenStartIndex < 0 || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ }
+
+ return (count != 0 ? rules.ToArray() : null);
+ }
+
+ //
+ // GetNextAdjustmentRuleValue -
+ //
+ // Helper function to read an AdjustmentRule token. Takes a boolean "canEndWithoutSeparator".
+ //
+ private AdjustmentRule GetNextAdjustmentRuleValue(Boolean canEndWithoutSeparator) {
+ // first verify the internal state of the object
+ if (m_state == State.EndOfLine) {
+ if (canEndWithoutSeparator) {
+ return null;
+ }
+ else {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ }
+
+ if (m_currentTokenStartIndex < 0 || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ // check to see if the very first token we see is the separator
+ if (m_serializedText[m_currentTokenStartIndex] == sep) {
+ return null;
+ }
+
+ // verify the current token is a left-hand-side marker ("[")
+ if (m_serializedText[m_currentTokenStartIndex] != lhs) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ m_currentTokenStartIndex++;
+
+ DateTime dateStart = GetNextDateTimeValue(false, dateTimeFormat);
+ DateTime dateEnd = GetNextDateTimeValue(false, dateTimeFormat);
+ TimeSpan daylightDelta = GetNextTimeSpanValue(false);
+ TransitionTime daylightStart = GetNextTransitionTimeValue(false);
+ TransitionTime daylightEnd = GetNextTransitionTimeValue(false);
+ TimeSpan baseUtcOffsetDelta = TimeSpan.Zero;
+ Int32 noDaylightTransitions = 0;
+
+ // verify that the string is now at the right-hand-side marker ("]") ...
+
+ if (m_state == State.EndOfLine || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ // Check if we have baseUtcOffsetDelta in the serialized string and then deserialize it
+ if ((m_serializedText[m_currentTokenStartIndex] >= '0' && m_serializedText[m_currentTokenStartIndex] <= '9') ||
+ m_serializedText[m_currentTokenStartIndex] == '-' || m_serializedText[m_currentTokenStartIndex] == '+') {
+ baseUtcOffsetDelta = GetNextTimeSpanValue(false);
+ }
+
+ // Check if we have NoDaylightTransitions in the serialized string and then deserialize it
+ if ((m_serializedText[m_currentTokenStartIndex] >= '0' && m_serializedText[m_currentTokenStartIndex] <= '1')) {
+ noDaylightTransitions = GetNextInt32Value(false);
+ }
+
+ if (m_state == State.EndOfLine || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ if (m_serializedText[m_currentTokenStartIndex] != rhs) {
+ // skip ahead of any "v.Next" data at the end of the AdjustmentRule
+ //
+ // FUTURE: if the serialization format is extended in the future then this
+ // code section will need to be changed to read the new fields rather
+ // than just skipping the data at the end of the [AdjustmentRule].
+ SkipVersionNextDataFields(1);
+ }
+ else {
+ m_currentTokenStartIndex++;
+ }
+
+ // create the AdjustmentRule from the deserialized fields ...
+
+ AdjustmentRule rule;
+ try {
+ rule = AdjustmentRule.CreateAdjustmentRule(dateStart, dateEnd, daylightDelta, daylightStart, daylightEnd, baseUtcOffsetDelta, noDaylightTransitions > 0);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+
+ // finally set the state to either EndOfLine or StartOfToken for the next caller
+ if (m_currentTokenStartIndex >= m_serializedText.Length) {
+ m_state = State.EndOfLine;
+ }
+ else {
+ m_state = State.StartOfToken;
+ }
+ return rule;
+ }
+
+
+ //
+ // GetNextTransitionTimeValue -
+ //
+ // Helper function to read a TransitionTime token. Takes a boolean "canEndWithoutSeparator".
+ //
+ private TransitionTime GetNextTransitionTimeValue(Boolean canEndWithoutSeparator) {
+
+ // first verify the internal state of the object
+
+ if (m_state == State.EndOfLine
+ || (m_currentTokenStartIndex < m_serializedText.Length
+ && m_serializedText[m_currentTokenStartIndex] == rhs)) {
+ //
+ // we are at the end of the line or we are starting at a "]" character
+ //
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ if (m_currentTokenStartIndex < 0 || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ // verify the current token is a left-hand-side marker ("[")
+
+ if (m_serializedText[m_currentTokenStartIndex] != lhs) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+ m_currentTokenStartIndex++;
+
+ Int32 isFixedDate = GetNextInt32Value(false);
+
+ if (isFixedDate != 0 && isFixedDate != 1) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ TransitionTime transition;
+
+ DateTime timeOfDay = GetNextDateTimeValue(false, timeOfDayFormat);
+ timeOfDay = new DateTime(1, 1, 1, timeOfDay.Hour,timeOfDay.Minute,timeOfDay.Second, timeOfDay.Millisecond);
+
+ Int32 month = GetNextInt32Value(false);
+
+ if (isFixedDate == 1) {
+ Int32 day = GetNextInt32Value(false);
+
+ try {
+ transition = TransitionTime.CreateFixedDateRule(timeOfDay, month, day);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+ }
+ else {
+ Int32 week = GetNextInt32Value(false);
+ Int32 dayOfWeek = GetNextInt32Value(false);
+
+ try {
+ transition = TransitionTime.CreateFloatingDateRule(timeOfDay, month, week, (DayOfWeek)dayOfWeek);
+ }
+ catch (ArgumentException e) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
+ }
+
+ }
+
+ // verify that the string is now at the right-hand-side marker ("]") ...
+
+ if (m_state == State.EndOfLine || m_currentTokenStartIndex >= m_serializedText.Length) {
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+ if (m_serializedText[m_currentTokenStartIndex] != rhs) {
+ // skip ahead of any "v.Next" data at the end of the AdjustmentRule
+ //
+ // FUTURE: if the serialization format is extended in the future then this
+ // code section will need to be changed to read the new fields rather
+ // than just skipping the data at the end of the [TransitionTime].
+ SkipVersionNextDataFields(1);
+ }
+ else {
+ m_currentTokenStartIndex++;
+ }
+
+ // check to see if the string is now at the separator (";") ...
+ Boolean sepFound = false;
+ if (m_currentTokenStartIndex < m_serializedText.Length
+ && m_serializedText[m_currentTokenStartIndex] == sep) {
+ // handle the case where we ended on a ";"
+ m_currentTokenStartIndex++;
+ sepFound = true;
+ }
+
+ if (!sepFound && !canEndWithoutSeparator) {
+ // we MUST end on a separator
+ throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"));
+ }
+
+
+ // finally set the state to either EndOfLine or StartOfToken for the next caller
+ if (m_currentTokenStartIndex >= m_serializedText.Length) {
+ m_state = State.EndOfLine;
+ }
+ else {
+ m_state = State.StartOfToken;
+ }
+ return transition;
+ }
+ }
+
+ private class TimeZoneInfoComparer : System.Collections.Generic.IComparer<TimeZoneInfo> {
+ int System.Collections.Generic.IComparer<TimeZoneInfo>.Compare(TimeZoneInfo x, TimeZoneInfo y) {
+ // sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel
+ int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset);
+ return comparison == 0 ? String.Compare(x.DisplayName, y.DisplayName, StringComparison.Ordinal) : comparison;
+ }
+ }
+
+#if PLATFORM_UNIX
+ private struct TZifType
+ {
+ private const int c_len = 6;
+ public static int Length
+ {
+ get
+ {
+ return c_len;
+ }
+ }
+
+ public TimeSpan UtcOffset;
+ public Boolean IsDst;
+ public Byte AbbreviationIndex;
+
+ public TZifType(Byte[] data, Int32 index)
+ {
+ if (data == null || data.Length < index + c_len)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoInvalidTZif"), "data");
+ }
+ Contract.EndContractBlock();
+ UtcOffset = new TimeSpan(0, 0, TZif_ToInt32(data, index + 00));
+ IsDst = (data[index + 4] != 0);
+ AbbreviationIndex = data[index + 5];
+ }
+ }
+
+ private struct TZifHead
+ {
+ private const int c_len = 44;
+ public static int Length
+ {
+ get
+ {
+ return c_len;
+ }
+ }
+
+ public TZifHead(Byte[] data, Int32 index)
+ {
+ if (data == null || data.Length < c_len)
+ {
+ throw new ArgumentException("bad data", "data");
+ }
+ Contract.EndContractBlock();
+
+ Magic = (uint)TZif_ToInt32(data, index + 00);
+
+ if (Magic != 0x545A6966)
+ {
+ // 0x545A6966 = {0x54, 0x5A, 0x69, 0x66} = "TZif"
+ throw new ArgumentException(Environment.GetResourceString("Argument_TimeZoneInfoBadTZif"), "data");
+ }
+
+ byte version = data[index + 04];
+ Version = version == '2' ? TZVersion.V2 :
+ version == '3' ? TZVersion.V3 :
+ TZVersion.V1; // default/fallback to V1 to guard against future, unsupported version numbers
+
+ // skip the 15 byte reserved field
+
+ // don't use the BitConverter class which parses data
+ // based on the Endianess of the machine architecture.
+ // this data is expected to always be in "standard byte order",
+ // regardless of the machine it is being processed on.
+
+ IsGmtCount = (uint)TZif_ToInt32(data, index + 20);
+ IsStdCount = (uint)TZif_ToInt32(data, index + 24);
+ LeapCount = (uint)TZif_ToInt32(data, index + 28);
+ TimeCount = (uint)TZif_ToInt32(data, index + 32);
+ TypeCount = (uint)TZif_ToInt32(data, index + 36);
+ CharCount = (uint)TZif_ToInt32(data, index + 40);
+ }
+
+ public UInt32 Magic; // TZ_MAGIC "TZif"
+ public TZVersion Version; // 1 byte for a \0 or 2 or 3
+ // public Byte[15] Reserved; // reserved for future use
+ public UInt32 IsGmtCount; // number of transition time flags
+ public UInt32 IsStdCount; // number of transition time flags
+ public UInt32 LeapCount; // number of leap seconds
+ public UInt32 TimeCount; // number of transition times
+ public UInt32 TypeCount; // number of local time types
+ public UInt32 CharCount; // number of abbreviated characters
+ }
+
+ private enum TZVersion : byte
+ {
+ V1 = 0,
+ V2,
+ V3,
+ // when adding more versions, ensure all the logic using TZVersion is still correct
+ }
+#endif // PLATFORM_UNIX
+
+ } // TimezoneInfo
+} // namespace System
diff --git a/src/mscorlib/src/System/TimeZoneNotFoundException.cs b/src/mscorlib/src/System/TimeZoneNotFoundException.cs
new file mode 100644
index 0000000000..5f8b919a76
--- /dev/null
+++ b/src/mscorlib/src/System/TimeZoneNotFoundException.cs
@@ -0,0 +1,26 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+ using System.Runtime.Serialization;
+ using System.Runtime.CompilerServices;
+
+ [Serializable]
+#if !FEATURE_CORECLR
+ [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
+#endif
+ [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
+ public class TimeZoneNotFoundException : Exception {
+ public TimeZoneNotFoundException(String message)
+ : base(message) { }
+
+ public TimeZoneNotFoundException(String message, Exception innerException)
+ : base(message, innerException) { }
+
+ protected TimeZoneNotFoundException(SerializationInfo info, StreamingContext context)
+ : base(info, context) { }
+
+ public TimeZoneNotFoundException() { }
+ }
+}
diff --git a/src/mscorlib/src/System/TimeoutException.cs b/src/mscorlib/src/System/TimeoutException.cs
new file mode 100644
index 0000000000..0b45f62fbd
--- /dev/null
+++ b/src/mscorlib/src/System/TimeoutException.cs
@@ -0,0 +1,45 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for Timeout
+**
+**
+=============================================================================*/
+
+namespace System
+{
+ using System.Runtime.Serialization;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class TimeoutException : SystemException {
+
+ public TimeoutException()
+ : base(Environment.GetResourceString("Arg_TimeoutException")) {
+ SetErrorCode(__HResults.COR_E_TIMEOUT);
+ }
+
+ public TimeoutException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_TIMEOUT);
+ }
+
+ public TimeoutException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_TIMEOUT);
+ }
+
+ //
+ //This constructor is required for serialization.
+ //
+ protected TimeoutException(SerializationInfo info, StreamingContext context)
+ : base(info, context) {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/Tuple.cs b/src/mscorlib/src/System/Tuple.cs
new file mode 100644
index 0000000000..99164bc654
--- /dev/null
+++ b/src/mscorlib/src/System/Tuple.cs
@@ -0,0 +1,959 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Text;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace System {
+
+ /// <summary>
+ /// Helper so we can call some tuple methods recursively without knowing the underlying types.
+ /// </summary>
+ internal interface ITuple {
+ string ToString(StringBuilder sb);
+ int GetHashCode(IEqualityComparer comparer);
+ int Size { get; }
+
+ }
+
+ public static class Tuple {
+ public static Tuple<T1> Create<T1>(T1 item1) {
+ return new Tuple<T1>(item1);
+ }
+
+ public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2) {
+ return new Tuple<T1, T2>(item1, item2);
+ }
+
+ public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3) {
+ return new Tuple<T1, T2, T3>(item1, item2, item3);
+ }
+
+ public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4) {
+ return new Tuple<T1, T2, T3, T4>(item1, item2, item3, item4);
+ }
+
+ public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) {
+ return new Tuple<T1, T2, T3, T4, T5>(item1, item2, item3, item4, item5);
+ }
+
+ public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) {
+ return new Tuple<T1, T2, T3, T4, T5, T6>(item1, item2, item3, item4, item5, item6);
+ }
+
+ public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) {
+ return new Tuple<T1, T2, T3, T4, T5, T6, T7>(item1, item2, item3, item4, item5, item6, item7);
+ }
+
+ public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) {
+ return new Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>>(item1, item2, item3, item4, item5, item6, item7, new Tuple<T8>(item8));
+ }
+
+ // From System.Web.Util.HashCodeCombiner
+ internal static int CombineHashCodes(int h1, int h2) {
+ return (((h1 << 5) + h1) ^ h2);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3) {
+ return CombineHashCodes(CombineHashCodes(h1, h2), h3);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4) {
+ return CombineHashCodes(CombineHashCodes(h1, h2), CombineHashCodes(h3, h4));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5) {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), h5);
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6) {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7) {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7));
+ }
+
+ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int h6, int h7, int h8) {
+ return CombineHashCodes(CombineHashCodes(h1, h2, h3, h4), CombineHashCodes(h5, h6, h7, h8));
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+
+ public T1 Item1 { get { return m_Item1; } }
+
+ public Tuple(T1 item1) {
+ m_Item1 = item1;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1> objTuple = other as Tuple<T1>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1> objTuple = other as Tuple<T1>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ return comparer.Compare(m_Item1, objTuple.m_Item1);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return comparer.GetHashCode(m_Item1);
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 1;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+
+ public Tuple(T1 item1, T2 item2) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2> objTuple = other as Tuple<T1, T2>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2> objTuple = other as Tuple<T1, T2>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item2, objTuple.m_Item2);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 2;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item3, objTuple.m_Item3);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 3;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3, T4> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+ public T4 Item4 { get { return m_Item4; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ m_Item4 = item4;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3, T4> objTuple = other as Tuple<T1, T2, T3, T4>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3, T4> objTuple = other as Tuple<T1, T2, T3, T4>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item3, objTuple.m_Item3);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item4, objTuple.m_Item4);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(", ");
+ sb.Append(m_Item4);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 4;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3, T4, T5> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+ private readonly T5 m_Item5;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+ public T4 Item4 { get { return m_Item4; } }
+ public T5 Item5 { get { return m_Item5; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ m_Item4 = item4;
+ m_Item5 = item5;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3, T4, T5> objTuple = other as Tuple<T1, T2, T3, T4, T5>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3, T4, T5> objTuple = other as Tuple<T1, T2, T3, T4, T5>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item3, objTuple.m_Item3);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item4, objTuple.m_Item4);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item5, objTuple.m_Item5);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(", ");
+ sb.Append(m_Item4);
+ sb.Append(", ");
+ sb.Append(m_Item5);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 5;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3, T4, T5, T6> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+ private readonly T5 m_Item5;
+ private readonly T6 m_Item6;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+ public T4 Item4 { get { return m_Item4; } }
+ public T5 Item5 { get { return m_Item5; } }
+ public T6 Item6 { get { return m_Item6; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ m_Item4 = item4;
+ m_Item5 = item5;
+ m_Item6 = item6;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3, T4, T5, T6> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3, T4, T5, T6> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item3, objTuple.m_Item3);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item4, objTuple.m_Item4);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item5, objTuple.m_Item5);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item6, objTuple.m_Item6);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(", ");
+ sb.Append(m_Item4);
+ sb.Append(", ");
+ sb.Append(m_Item5);
+ sb.Append(", ");
+ sb.Append(m_Item6);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 6;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3, T4, T5, T6, T7> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+ private readonly T5 m_Item5;
+ private readonly T6 m_Item6;
+ private readonly T7 m_Item7;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+ public T4 Item4 { get { return m_Item4; } }
+ public T5 Item5 { get { return m_Item5; } }
+ public T6 Item6 { get { return m_Item6; } }
+ public T7 Item7 { get { return m_Item7; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) {
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ m_Item4 = item4;
+ m_Item5 = item5;
+ m_Item6 = item6;
+ m_Item7 = item7;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3, T4, T5, T6, T7> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6, T7>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3, T4, T5, T6, T7> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6, T7>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item3, objTuple.m_Item3);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item4, objTuple.m_Item4);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item5, objTuple.m_Item5);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item6, objTuple.m_Item6);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Item7, objTuple.m_Item7);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7));
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(", ");
+ sb.Append(m_Item4);
+ sb.Append(", ");
+ sb.Append(m_Item5);
+ sb.Append(", ");
+ sb.Append(m_Item6);
+ sb.Append(", ");
+ sb.Append(m_Item7);
+ sb.Append(")");
+ return sb.ToString();
+ }
+
+ int ITuple.Size {
+ get {
+ return 7;
+ }
+ }
+ }
+
+ [Serializable]
+ public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
+
+ private readonly T1 m_Item1;
+ private readonly T2 m_Item2;
+ private readonly T3 m_Item3;
+ private readonly T4 m_Item4;
+ private readonly T5 m_Item5;
+ private readonly T6 m_Item6;
+ private readonly T7 m_Item7;
+ private readonly TRest m_Rest;
+
+ public T1 Item1 { get { return m_Item1; } }
+ public T2 Item2 { get { return m_Item2; } }
+ public T3 Item3 { get { return m_Item3; } }
+ public T4 Item4 { get { return m_Item4; } }
+ public T5 Item5 { get { return m_Item5; } }
+ public T6 Item6 { get { return m_Item6; } }
+ public T7 Item7 { get { return m_Item7; } }
+ public TRest Rest { get { return m_Rest; } }
+
+ public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) {
+ if (!(rest is ITuple)) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleLastArgumentNotATuple"));
+ }
+
+ m_Item1 = item1;
+ m_Item2 = item2;
+ m_Item3 = item3;
+ m_Item4 = item4;
+ m_Item5 = item5;
+ m_Item6 = item6;
+ m_Item7 = item7;
+ m_Rest = rest;
+ }
+
+ public override Boolean Equals(Object obj) {
+ return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
+ }
+
+ Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
+ if (other == null) return false;
+
+ Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>;
+
+ if (objTuple == null) {
+ return false;
+ }
+
+ return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3) && comparer.Equals(m_Item4, objTuple.m_Item4) && comparer.Equals(m_Item5, objTuple.m_Item5) && comparer.Equals(m_Item6, objTuple.m_Item6) && comparer.Equals(m_Item7, objTuple.m_Item7) && comparer.Equals(m_Rest, objTuple.m_Rest);
+ }
+
+ Int32 IComparable.CompareTo(Object obj) {
+ return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
+ }
+
+ Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
+ if (other == null) return 1;
+
+ Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> objTuple = other as Tuple<T1, T2, T3, T4, T5, T6, T7, TRest>;
+
+ if (objTuple == null) {
+ throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
+ }
+
+ int c = 0;
+
+ c = comparer.Compare(m_Item1, objTuple.m_Item1);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item2, objTuple.m_Item2);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item3, objTuple.m_Item3);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item4, objTuple.m_Item4);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item5, objTuple.m_Item5);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item6, objTuple.m_Item6);
+
+ if (c != 0) return c;
+
+ c = comparer.Compare(m_Item7, objTuple.m_Item7);
+
+ if (c != 0) return c;
+
+ return comparer.Compare(m_Rest, objTuple.m_Rest);
+ }
+
+ public override int GetHashCode() {
+ return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
+ }
+
+ Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
+ // We want to have a limited hash in this case. We'll use the last 8 elements of the tuple
+ ITuple t = (ITuple) m_Rest;
+ if(t.Size >= 8) { return t.GetHashCode(comparer); }
+
+ // In this case, the rest memeber has less than 8 elements so we need to combine some our elements with the elements in rest
+ int k = 8 - t.Size;
+ switch(k) {
+ case 1:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 2:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 3:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 4:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 5:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 6:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ case 7:
+ return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3), comparer.GetHashCode(m_Item4), comparer.GetHashCode(m_Item5), comparer.GetHashCode(m_Item6), comparer.GetHashCode(m_Item7), t.GetHashCode(comparer));
+ }
+ Contract.Assert(false, "Missed all cases for computing Tuple hash code");
+ return -1;
+ }
+
+ Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
+ return ((IStructuralEquatable) this).GetHashCode(comparer);
+ }
+ public override string ToString() {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("(");
+ return ((ITuple)this).ToString(sb);
+ }
+
+ string ITuple.ToString(StringBuilder sb) {
+ sb.Append(m_Item1);
+ sb.Append(", ");
+ sb.Append(m_Item2);
+ sb.Append(", ");
+ sb.Append(m_Item3);
+ sb.Append(", ");
+ sb.Append(m_Item4);
+ sb.Append(", ");
+ sb.Append(m_Item5);
+ sb.Append(", ");
+ sb.Append(m_Item6);
+ sb.Append(", ");
+ sb.Append(m_Item7);
+ sb.Append(", ");
+ return ((ITuple)m_Rest).ToString(sb);
+ }
+
+ int ITuple.Size {
+ get {
+ return 7 + ((ITuple)m_Rest).Size;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Type.cs b/src/mscorlib/src/System/Type.cs
new file mode 100644
index 0000000000..730003307a
--- /dev/null
+++ b/src/mscorlib/src/System/Type.cs
@@ -0,0 +1,1845 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+//
+//
+// Implements System.Type
+//
+// ======================================================================================
+
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Threading;
+ using System.Runtime;
+ using System.Runtime.Remoting;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using StackCrawlMark = System.Threading.StackCrawlMark;
+ using DebuggerStepThroughAttribute = System.Diagnostics.DebuggerStepThroughAttribute;
+
+ [Serializable]
+ [ClassInterface(ClassInterfaceType.None)]
+ [ComDefaultInterface(typeof(_Type))]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class Type : MemberInfo, _Type, IReflect
+ {
+ //
+ // System.Type is appdomain agile type. Appdomain agile types cannot have precise static constructors. Make
+ // sure to never introduce one here!
+ //
+ public static readonly MemberFilter FilterAttribute = new MemberFilter(__Filters.Instance.FilterAttribute);
+ public static readonly MemberFilter FilterName = new MemberFilter(__Filters.Instance.FilterName);
+ public static readonly MemberFilter FilterNameIgnoreCase = new MemberFilter(__Filters.Instance.FilterIgnoreCase);
+
+ public static readonly Object Missing = System.Reflection.Missing.Value;
+
+ public static readonly char Delimiter = '.';
+
+ // EmptyTypes is used to indicate that we are looking for someting without any parameters.
+ public readonly static Type[] EmptyTypes = EmptyArray<Type>.Value;
+
+ // The Default binder. We create a single one and expose that.
+ private static Binder defaultBinder;
+
+
+ protected Type() {}
+
+
+ // MemberInfo Methods....
+ // The Member type Field.
+ public override MemberTypes MemberType {
+ get {return System.Reflection.MemberTypes.TypeInfo;}
+ }
+
+ // Return the class that declared this type.
+ public override Type DeclaringType {
+ get {return null;}
+ }
+
+ public virtual MethodBase DeclaringMethod { get { return null; } }
+
+ // Return the class that was used to obtain this type.
+ public override Type ReflectedType
+ {
+ get {return null;}
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This is a static method that returns a Class based upon the name of the class
+ // (this name needs to be fully qualified with the package name and is
+ // case-sensitive by default).
+ ////
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(String typeName, bool throwOnError, bool ignoreCase) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeType.GetType(typeName, throwOnError, ignoreCase, false, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(String typeName, bool throwOnError) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeType.GetType(typeName, throwOnError, false, false, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(String typeName) {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeType.GetType(typeName, false, false, false, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(
+ string typeName,
+ Func<AssemblyName, Assembly> assemblyResolver,
+ Func<Assembly, string, bool, Type> typeResolver)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, false, false, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(
+ string typeName,
+ Func<AssemblyName, Assembly> assemblyResolver,
+ Func<Assembly, string, bool, Type> typeResolver,
+ bool throwOnError)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, false, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type GetType(
+ string typeName,
+ Func<AssemblyName, Assembly> assemblyResolver,
+ Func<Assembly, string, bool, Type> typeResolver,
+ bool throwOnError,
+ bool ignoreCase)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
+ }
+
+ [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
+ public static Type ReflectionOnlyGetType(String typeName, bool throwIfNotFound, bool ignoreCase)
+ {
+ StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
+ return RuntimeType.GetType(typeName, throwIfNotFound, ignoreCase, true /*reflectionOnly*/, ref stackMark);
+ }
+
+ public virtual Type MakePointerType() { throw new NotSupportedException(); }
+ public virtual StructLayoutAttribute StructLayoutAttribute { get { throw new NotSupportedException(); } }
+ public virtual Type MakeByRefType() { throw new NotSupportedException(); }
+ public virtual Type MakeArrayType() { throw new NotSupportedException(); }
+ public virtual Type MakeArrayType(int rank) { throw new NotSupportedException(); }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This will return a class based upon the progID. This is provided for
+ // COM classic support. Program ID's are not used in COM+ because they
+ // have been superceded by namespace. (This routine is called this instead
+ // of getClass() because of the name conflict with the first method above.)
+ //
+ // param progID: the progID of the class to retrieve
+ // returns: the class object associated to the progID
+ ////
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeFromProgID(String progID)
+ {
+ return RuntimeType.GetTypeFromProgIDImpl(progID, null, false);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This will return a class based upon the progID. This is provided for
+ // COM classic support. Program ID's are not used in COM+ because they
+ // have been superceded by namespace. (This routine is called this instead
+ // of getClass() because of the name conflict with the first method above.)
+ //
+ // param progID: the progID of the class to retrieve
+ // returns: the class object associated to the progID
+ ////
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeFromProgID(String progID, bool throwOnError)
+ {
+ return RuntimeType.GetTypeFromProgIDImpl(progID, null, throwOnError);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeFromProgID(String progID, String server)
+ {
+ return RuntimeType.GetTypeFromProgIDImpl(progID, server, false);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public static Type GetTypeFromProgID(String progID, String server, bool throwOnError)
+ {
+ return RuntimeType.GetTypeFromProgIDImpl(progID, server, throwOnError);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // This will return a class based upon the CLSID. This is provided for
+ // COM classic support.
+ //
+ // param CLSID: the CLSID of the class to retrieve
+ // returns: the class object associated to the CLSID
+ ////
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Type GetTypeFromCLSID(Guid clsid)
+ {
+ return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Type GetTypeFromCLSID(Guid clsid, bool throwOnError)
+ {
+ return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, throwOnError);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Type GetTypeFromCLSID(Guid clsid, String server)
+ {
+ return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, false);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public static Type GetTypeFromCLSID(Guid clsid, String server, bool throwOnError)
+ {
+ return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, throwOnError);
+ }
+
+ // GetTypeCode
+ // This method will return a TypeCode for the passed
+ // type.
+ public static TypeCode GetTypeCode(Type type)
+ {
+ if (type == null)
+ return TypeCode.Empty;
+ return type.GetTypeCodeImpl();
+ }
+
+ protected virtual TypeCode GetTypeCodeImpl()
+ {
+ // System.RuntimeType overrides GetTypeCodeInternal
+ // so we can assume that this is not a runtime type
+
+ // this is true for EnumBuilder but not the other System.Type subclasses in BCL
+ if (this != UnderlyingSystemType && UnderlyingSystemType != null)
+ return Type.GetTypeCode(UnderlyingSystemType);
+
+ return TypeCode.Object;
+ }
+
+ // Property representing the GUID associated with a class.
+ public abstract Guid GUID {
+ get;
+ }
+
+ // Return the Default binder used by the system.
+ static public Binder DefaultBinder {
+ get {
+ // Allocate the default binder if it hasn't been allocated yet.
+ if (defaultBinder == null)
+ CreateBinder();
+ return defaultBinder;
+ }
+ }
+
+ static private void CreateBinder()
+ {
+ if (defaultBinder == null)
+ {
+ DefaultBinder binder = new DefaultBinder();
+ Interlocked.CompareExchange<Binder>(ref defaultBinder, binder, null);
+ }
+ }
+
+ // Description of the Binding Process.
+ // We must invoke a method that is accessable and for which the provided
+ // parameters have the most specific match. A method may be called if
+ // 1. The number of parameters in the method declaration equals the number of
+ // arguments provided to the invocation
+ // 2. The type of each argument can be converted by the binder to the
+ // type of the type of the parameter.
+ //
+ // The binder will find all of the matching methods. These method are found based
+ // upon the type of binding requested (MethodInvoke, Get/Set Properties). The set
+ // of methods is filtered by the name, number of arguments and a set of search modifiers
+ // defined in the Binder.
+ //
+ // After the method is selected, it will be invoked. Accessability is checked
+ // at that point. The search may be control which set of methods are searched based
+ // upon the accessibility attribute associated with the method.
+ //
+ // The BindToMethod method is responsible for selecting the method to be invoked.
+ // For the default binder, the most specific method will be selected.
+ //
+ // This will invoke a specific member...
+
+ abstract public Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder,Object target,
+ Object[] args, ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters);
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args, CultureInfo culture)
+ {
+ return InvokeMember(name,invokeAttr,binder,target,args,null,culture,null);
+ }
+
+ [DebuggerStepThroughAttribute]
+ [Diagnostics.DebuggerHidden]
+ public Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, Object target, Object[] args)
+ {
+ return InvokeMember(name,invokeAttr,binder,target,args,null,null,null);
+ }
+
+
+ // Module Property associated with a class.
+ // _Type.Module
+ public new abstract Module Module { get; }
+
+ // Assembly Property associated with a class.
+ public abstract Assembly Assembly {
+ [Pure]
+ get;
+ }
+
+ // Assembly Property associated with a class.
+ // A class handle is a unique integer value associated with
+ // each class. The handle is unique during the process life time.
+ public virtual RuntimeTypeHandle TypeHandle
+ {
+ [Pure]
+ get
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ internal virtual RuntimeTypeHandle GetTypeHandleInternal() {
+ return TypeHandle;
+ }
+
+ public static RuntimeTypeHandle GetTypeHandle(Object o)
+ {
+ if (o == null)
+ throw new ArgumentNullException(null, Environment.GetResourceString("Arg_InvalidHandle"));
+ return new RuntimeTypeHandle((RuntimeType)o.GetType());
+ }
+
+ // Given a class handle, this will return the class for that handle.
+ [System.Security.SecurityCritical]
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ internal static extern RuntimeType GetTypeFromHandleUnsafe(IntPtr handle);
+
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public static extern Type GetTypeFromHandle(RuntimeTypeHandle handle);
+
+
+ // Return the fully qualified name. The name does contain the namespace.
+ public abstract String FullName {
+ [Pure]
+ get;
+ }
+
+ // Return the name space of the class.
+ public abstract String Namespace {
+ [Pure]
+ get;
+ }
+
+
+ public abstract String AssemblyQualifiedName {
+ [Pure]
+ get;
+ }
+
+
+ [Pure]
+ public virtual int GetArrayRank() {
+ Contract.Ensures(Contract.Result<int>() >= 0);
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+ // Returns the base class for a class. If this is an interface or has
+ // no base class null is returned. Object is the only Type that does not
+ // have a base class.
+ public abstract Type BaseType {
+ [Pure]
+ get;
+ }
+
+
+ // GetConstructor
+ // This method will search for the specified constructor. For constructors,
+ // unlike everything else, the default is to not look for static methods. The
+ // reason is that we don't typically expose the class initializer.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorInfo GetConstructor(BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ // Must provide some types (Type[0] for nothing)
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i=0;i<types.Length;i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetConstructorImpl(bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorInfo GetConstructor(BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i=0;i<types.Length;i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetConstructorImpl(bindingAttr, binder, CallingConventions.Any, types, modifiers);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorInfo GetConstructor(Type[] types)
+ {
+ // The arguments are checked in the called version of GetConstructor.
+ return GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, types, null);
+ }
+
+ abstract protected ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers);
+
+ // GetConstructors()
+ // This routine will return an array of all constructors supported by the class.
+ // Unlike everything else, the default is to not look for static methods. The
+ // reason is that we don't typically expose the class initializer.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorInfo[] GetConstructors() {
+ return GetConstructors(BindingFlags.Public | BindingFlags.Instance);
+ }
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ abstract public ConstructorInfo[] GetConstructors(BindingFlags bindingAttr);
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public ConstructorInfo TypeInitializer {
+ get {
+ return GetConstructorImpl(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
+ null,
+ CallingConventions.Any,
+ Type.EmptyTypes,
+ null);
+ }
+ }
+
+
+ // Return a method based upon the passed criteria. The name of the method
+ // must be provided, and exception is thrown if it is not. The bindingAttr
+ // parameter indicates if non-public methods should be searched. The types
+ // array indicates the types of the parameters being looked for.
+ public MethodInfo GetMethod(String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i = 0; i < types.Length; i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
+ }
+
+ public MethodInfo GetMethod(String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ Type[] types,
+ ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i = 0; i < types.Length; i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetMethodImpl(name, bindingAttr, binder, CallingConventions.Any, types, modifiers);
+ }
+
+ public MethodInfo GetMethod(String name, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i=0;i<types.Length;i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetMethodImpl(name, Type.DefaultLookup, null, CallingConventions.Any, types, modifiers);
+ }
+
+ public MethodInfo GetMethod(String name,Type[] types)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ for (int i=0;i<types.Length;i++)
+ if (types[i] == null)
+ throw new ArgumentNullException("types");
+ return GetMethodImpl(name, Type.DefaultLookup, null, CallingConventions.Any, types, null);
+ }
+
+ public MethodInfo GetMethod(String name, BindingFlags bindingAttr)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+ return GetMethodImpl(name, bindingAttr, null, CallingConventions.Any, null, null);
+ }
+
+ public MethodInfo GetMethod(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+ return GetMethodImpl(name, Type.DefaultLookup, null, CallingConventions.Any, null, null);
+ }
+
+ abstract protected MethodInfo GetMethodImpl(String name,
+ BindingFlags bindingAttr,
+ Binder binder,
+ CallingConventions callConvention,
+ Type[] types,
+ ParameterModifier[] modifiers);
+
+
+ // GetMethods
+ // This routine will return all the methods implemented by the class
+ public MethodInfo[] GetMethods() {
+ return GetMethods(Type.DefaultLookup);
+ }
+
+ abstract public MethodInfo[] GetMethods(BindingFlags bindingAttr);
+
+ // GetField
+ // Get Field will return a specific field based upon name
+ abstract public FieldInfo GetField(String name, BindingFlags bindingAttr);
+
+
+ public FieldInfo GetField(String name) {
+ return GetField(name, Type.DefaultLookup);
+ }
+
+
+ // GetFields
+ // Get fields will return a full array of fields implemented by a class
+ public FieldInfo[] GetFields() {
+ return GetFields(Type.DefaultLookup);
+ }
+ abstract public FieldInfo[] GetFields(BindingFlags bindingAttr);
+
+ // GetInterface
+ // This method will return an interface (as a class) based upon
+ // the passed in name.
+ public Type GetInterface(String name) {
+ return GetInterface(name,false);
+ }
+ abstract public Type GetInterface(String name, bool ignoreCase);
+
+
+ // GetInterfaces
+ // This method will return all of the interfaces implemented by a class
+ abstract public Type[] GetInterfaces();
+
+ // FindInterfaces
+ // This method will filter the interfaces supported the class
+ public virtual Type[] FindInterfaces(TypeFilter filter,Object filterCriteria)
+ {
+ if (filter == null)
+ throw new ArgumentNullException("filter");
+ Contract.EndContractBlock();
+ Type[] c = GetInterfaces();
+ int cnt = 0;
+ for (int i = 0;i<c.Length;i++) {
+ if (!filter(c[i],filterCriteria))
+ c[i] = null;
+ else
+ cnt++;
+ }
+ if (cnt == c.Length)
+ return c;
+
+ Type[] ret = new Type[cnt];
+ cnt=0;
+ for (int i=0;i<c.Length;i++) {
+ if (c[i] != null)
+ ret[cnt++] = c[i];
+ }
+ return ret;
+ }
+
+ // GetEvent
+ // This method will return a event by name if it is found.
+ // null is returned if the event is not found
+
+
+ public EventInfo GetEvent(String name) {
+ return GetEvent(name,Type.DefaultLookup);
+ }
+ abstract public EventInfo GetEvent(String name,BindingFlags bindingAttr);
+
+ // GetEvents
+ // This method will return an array of EventInfo. If there are not Events
+ // an empty array will be returned.
+ virtual public EventInfo[] GetEvents() {
+ return GetEvents(Type.DefaultLookup);
+ }
+ abstract public EventInfo[] GetEvents(BindingFlags bindingAttr);
+
+
+ // Return a property based upon the passed criteria. The nameof the
+ // parameter must be provided.
+ public PropertyInfo GetProperty(String name,BindingFlags bindingAttr,Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,bindingAttr,binder,returnType,types,modifiers);
+ }
+
+ public PropertyInfo GetProperty(String name, Type returnType, Type[] types,ParameterModifier[] modifiers)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,modifiers);
+ }
+
+ public PropertyInfo GetProperty(String name, BindingFlags bindingAttr)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,bindingAttr,null,null,null,null);
+ }
+
+ public PropertyInfo GetProperty(String name, Type returnType, Type[] types)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,types,null);
+ }
+
+ public PropertyInfo GetProperty(String name, Type[] types)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (types == null)
+ throw new ArgumentNullException("types");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,Type.DefaultLookup,null,null,types,null);
+ }
+
+ public PropertyInfo GetProperty(String name, Type returnType)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (returnType == null)
+ throw new ArgumentNullException("returnType");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,Type.DefaultLookup,null,returnType,null,null);
+ }
+
+ internal PropertyInfo GetProperty(String name, BindingFlags bindingAttr, Type returnType)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ if (returnType == null)
+ throw new ArgumentNullException("returnType");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name, bindingAttr, null, returnType, null, null);
+ }
+
+ public PropertyInfo GetProperty(String name)
+ {
+ if (name == null)
+ throw new ArgumentNullException("name");
+ Contract.EndContractBlock();
+ return GetPropertyImpl(name,Type.DefaultLookup,null,null,null,null);
+ }
+
+ protected abstract PropertyInfo GetPropertyImpl(String name, BindingFlags bindingAttr,Binder binder,
+ Type returnType, Type[] types, ParameterModifier[] modifiers);
+
+
+ // GetProperties
+ // This method will return an array of all of the properties defined
+ // for a Type.
+ abstract public PropertyInfo[] GetProperties(BindingFlags bindingAttr);
+ public PropertyInfo[] GetProperties()
+ {
+ return GetProperties(Type.DefaultLookup);
+ }
+#if !FEATURE_CORECLR
+#endif
+ // GetNestedTypes()
+ // This set of method will return any nested types that are found inside
+ // of the type.
+ public Type[] GetNestedTypes()
+ {
+ return GetNestedTypes(Type.DefaultLookup);
+ }
+
+ abstract public Type[] GetNestedTypes(BindingFlags bindingAttr);
+
+#if !FEATURE_CORECLR
+ // GetNestedType()
+#endif
+ public Type GetNestedType(String name)
+ {
+ return GetNestedType(name,Type.DefaultLookup);
+ }
+
+ abstract public Type GetNestedType(String name, BindingFlags bindingAttr);
+
+ // GetMember
+ // This method will return all of the members which match the specified string
+ // passed into the method
+ public MemberInfo[] GetMember(String name) {
+ return GetMember(name,Type.DefaultLookup);
+ }
+
+ virtual public MemberInfo[] GetMember(String name, BindingFlags bindingAttr)
+ {
+ return GetMember(name,MemberTypes.All,bindingAttr);
+ }
+
+ virtual public MemberInfo[] GetMember(String name, MemberTypes type, BindingFlags bindingAttr)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+
+ // GetMembers
+ // This will return a Member array of all of the members of a class
+ public MemberInfo[] GetMembers() {
+ return GetMembers(Type.DefaultLookup);
+ }
+ abstract public MemberInfo[] GetMembers(BindingFlags bindingAttr);
+
+ // GetDefaultMembers
+ // This will return a MemberInfo that has been marked with the
+ // DefaultMemberAttribute
+ public virtual MemberInfo[] GetDefaultMembers()
+ {
+ throw new NotImplementedException();
+ }
+
+ // FindMembers
+ // This will return a filtered version of the member information
+ public virtual MemberInfo[] FindMembers(MemberTypes memberType,BindingFlags bindingAttr,MemberFilter filter,Object filterCriteria)
+ {
+ // Define the work arrays
+ MethodInfo[] m = null;
+ ConstructorInfo[] c = null;
+ FieldInfo[] f = null;
+ PropertyInfo[] p = null;
+ EventInfo[] e = null;
+ Type[] t = null;
+
+ int i = 0;
+ int cnt = 0; // Total Matchs
+
+ // Check the methods
+ if ((memberType & System.Reflection.MemberTypes.Method) != 0) {
+ m = GetMethods(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<m.Length;i++)
+ if (!filter(m[i],filterCriteria))
+ m[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=m.Length;
+ }
+ }
+
+ // Check the constructors
+ if ((memberType & System.Reflection.MemberTypes.Constructor) != 0) {
+ c = GetConstructors(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<c.Length;i++)
+ if (!filter(c[i],filterCriteria))
+ c[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=c.Length;
+ }
+ }
+
+ // Check the fields
+ if ((memberType & System.Reflection.MemberTypes.Field) != 0) {
+ f = GetFields(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<f.Length;i++)
+ if (!filter(f[i],filterCriteria))
+ f[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=f.Length;
+ }
+ }
+
+ // Check the Properties
+ if ((memberType & System.Reflection.MemberTypes.Property) != 0) {
+ p = GetProperties(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<p.Length;i++)
+ if (!filter(p[i],filterCriteria))
+ p[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=p.Length;
+ }
+ }
+
+ // Check the Events
+ if ((memberType & System.Reflection.MemberTypes.Event) != 0) {
+ e = GetEvents(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<e.Length;i++)
+ if (!filter(e[i],filterCriteria))
+ e[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=e.Length;
+ }
+ }
+
+ // Check the Types
+ if ((memberType & System.Reflection.MemberTypes.NestedType) != 0) {
+ t = GetNestedTypes(bindingAttr);
+ if (filter != null) {
+ for (i=0;i<t.Length;i++)
+ if (!filter(t[i],filterCriteria))
+ t[i] = null;
+ else
+ cnt++;
+ } else {
+ cnt+=t.Length;
+ }
+ }
+
+ // Allocate the Member Info
+ MemberInfo[] ret = new MemberInfo[cnt];
+
+ // Copy the Methods
+ cnt = 0;
+ if (m != null) {
+ for (i=0;i<m.Length;i++)
+ if (m[i] != null)
+ ret[cnt++] = m[i];
+ }
+
+ // Copy the Constructors
+ if (c != null) {
+ for (i=0;i<c.Length;i++)
+ if (c[i] != null)
+ ret[cnt++] = c[i];
+ }
+
+ // Copy the Fields
+ if (f != null) {
+ for (i=0;i<f.Length;i++)
+ if (f[i] != null)
+ ret[cnt++] = f[i];
+ }
+
+ // Copy the Properties
+ if (p != null) {
+ for (i=0;i<p.Length;i++)
+ if (p[i] != null)
+ ret[cnt++] = p[i];
+ }
+
+ // Copy the Events
+ if (e != null) {
+ for (i=0;i<e.Length;i++)
+ if (e[i] != null)
+ ret[cnt++] = e[i];
+ }
+
+ // Copy the Types
+ if (t != null) {
+ for (i=0;i<t.Length;i++)
+ if (t[i] != null)
+ ret[cnt++] = t[i];
+ }
+
+ return ret;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ // Attributes
+ //
+ // The attributes are all treated as read-only properties on a class. Most of
+ // these boolean properties have flag values defined in this class and act like
+ // a bit mask of attributes. There are also a set of boolean properties that
+ // relate to the classes relationship to other classes and to the state of the
+ // class inside the runtime.
+ //
+ ////////////////////////////////////////////////////////////////////////////////
+
+ public bool IsNested
+ {
+ [Pure]
+ get
+ {
+ return DeclaringType != null;
+ }
+ }
+
+ // The attribute property on the Type.
+ public TypeAttributes Attributes {
+ [Pure]
+ get {return GetAttributeFlagsImpl();}
+ }
+
+ public virtual GenericParameterAttributes GenericParameterAttributes
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public bool IsVisible
+ {
+ [Pure]
+ get
+ {
+ RuntimeType rt = this as RuntimeType;
+ if (rt != null)
+ return RuntimeTypeHandle.IsVisible(rt);
+
+ if (IsGenericParameter)
+ return true;
+
+ if (HasElementType)
+ return GetElementType().IsVisible;
+
+ Type type = this;
+ while (type.IsNested)
+ {
+ if (!type.IsNestedPublic)
+ return false;
+
+ // this should be null for non-nested types.
+ type = type.DeclaringType;
+ }
+
+ // Now "type" should be a top level type
+ if (!type.IsPublic)
+ return false;
+
+ if (IsGenericType && !IsGenericTypeDefinition)
+ {
+ foreach (Type t in GetGenericArguments())
+ {
+ if (!t.IsVisible)
+ return false;
+ }
+ }
+
+ return true;
+ }
+ }
+
+ public bool IsNotPublic
+ {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NotPublic);}
+ }
+
+ public bool IsPublic {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.Public);}
+ }
+
+ public bool IsNestedPublic {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPublic);}
+ }
+
+ public bool IsNestedPrivate {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate);}
+ }
+ public bool IsNestedFamily {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily);}
+ }
+ public bool IsNestedAssembly {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly);}
+ }
+ public bool IsNestedFamANDAssem {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem);}
+ }
+ public bool IsNestedFamORAssem{
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamORAssem);}
+ }
+
+ public bool IsAutoLayout {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.AutoLayout);}
+ }
+ public bool IsLayoutSequential {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.SequentialLayout);}
+ }
+ public bool IsExplicitLayout {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.LayoutMask) == TypeAttributes.ExplicitLayout);}
+ }
+
+ public bool IsClass {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class && !IsValueType);}
+ }
+
+ public bool IsInterface {
+ [Pure]
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get
+ {
+ RuntimeType rt = this as RuntimeType;
+ if (rt != null)
+ return RuntimeTypeHandle.IsInterface(rt);
+
+ return ((GetAttributeFlagsImpl() & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface);
+ }
+ }
+
+ public bool IsValueType {
+ [Pure]
+ get {return IsValueTypeImpl();}
+ }
+
+ public bool IsAbstract {
+ [Pure]
+ get { return ((GetAttributeFlagsImpl() & TypeAttributes.Abstract) != 0); }
+ }
+
+ public bool IsSealed {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.Sealed) != 0);}
+ }
+
+#if FEATURE_CORECLR
+ public bool IsEnum {
+#else
+ public virtual bool IsEnum {
+#endif
+ [Pure]
+ get
+ {
+ // This will return false for a non-runtime Type object unless it overrides IsSubclassOf.
+ return IsSubclassOf(RuntimeType.EnumType);
+ }
+ }
+
+ public bool IsSpecialName {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.SpecialName) != 0);}
+ }
+
+ public bool IsImport {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.Import) != 0);}
+ }
+
+ public virtual bool IsSerializable
+ {
+ [Pure]
+ get
+ {
+ if ((GetAttributeFlagsImpl() & TypeAttributes.Serializable) != 0)
+ return true;
+
+ RuntimeType rt = this.UnderlyingSystemType as RuntimeType;
+
+ if (rt != null)
+ return rt.IsSpecialSerializableType();
+
+ return false;
+ }
+ }
+
+ public bool IsAnsiClass {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AnsiClass);}
+ }
+
+ public bool IsUnicodeClass {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.UnicodeClass);}
+ }
+
+ public bool IsAutoClass {
+ [Pure]
+ get {return ((GetAttributeFlagsImpl() & TypeAttributes.StringFormatMask) == TypeAttributes.AutoClass);}
+ }
+
+ // These are not backed up by attributes. Instead they are implemented
+ // based internally.
+ public bool IsArray {
+ [Pure]
+ get {return IsArrayImpl();}
+ }
+
+ internal virtual bool IsSzArray {
+ [Pure]
+ get {return false;}
+ }
+
+ public virtual bool IsGenericType {
+ [Pure]
+ get { return false; }
+ }
+
+ public virtual bool IsGenericTypeDefinition {
+ [Pure]
+ get { return false; }
+ }
+
+ public virtual bool IsConstructedGenericType
+ {
+ [Pure]
+ get { throw new NotImplementedException(); }
+ }
+
+ public virtual bool IsGenericParameter
+ {
+ [Pure]
+ get { return false; }
+ }
+
+ public virtual int GenericParameterPosition {
+ [Pure]
+ get {throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter")); }
+ }
+
+ public virtual bool ContainsGenericParameters
+ {
+ [Pure]
+ get
+ {
+ if (HasElementType)
+ return GetRootElementType().ContainsGenericParameters;
+
+ if (IsGenericParameter)
+ return true;
+
+ if (!IsGenericType)
+ return false;
+
+ Type[] genericArguments = GetGenericArguments();
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ if (genericArguments[i].ContainsGenericParameters)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ [Pure]
+ public virtual Type[] GetGenericParameterConstraints()
+ {
+ if (!IsGenericParameter)
+ throw new InvalidOperationException(Environment.GetResourceString("Arg_NotGenericParameter"));
+ Contract.EndContractBlock();
+
+ throw new InvalidOperationException();
+ }
+
+ public bool IsByRef {
+ [Pure]
+ get {return IsByRefImpl();}
+ }
+ public bool IsPointer {
+ [Pure]
+ get {return IsPointerImpl();}
+ }
+ public bool IsPrimitive {
+ [Pure]
+ get {return IsPrimitiveImpl();}
+ }
+ public bool IsCOMObject {
+ [Pure]
+ get {return IsCOMObjectImpl();}
+ }
+
+#if FEATURE_COMINTEROP
+ internal bool IsWindowsRuntimeObject {
+ [Pure]
+ get { return IsWindowsRuntimeObjectImpl(); }
+ }
+
+ internal bool IsExportedToWindowsRuntime {
+ [Pure]
+ get { return IsExportedToWindowsRuntimeImpl(); }
+ }
+#endif // FEATURE_COMINTEROP
+
+ public bool HasElementType {
+ [Pure]
+ get {return HasElementTypeImpl();}
+ }
+
+ public bool IsContextful {
+ [Pure]
+ get {return IsContextfulImpl();}
+ }
+
+ public bool IsMarshalByRef {
+ [Pure]
+ get {return IsMarshalByRefImpl();}
+ }
+
+ internal bool HasProxyAttribute {
+ [Pure]
+ get {return HasProxyAttributeImpl();}
+ }
+
+ // Protected routine to determine if this class represents a value class
+ // The default implementation of IsValueTypeImpl never returns true for non-runtime types.
+ protected virtual bool IsValueTypeImpl()
+ {
+ // Note that typeof(Enum) and typeof(ValueType) are not themselves value types.
+ // But there is no point excluding them here because customer derived System.Type
+ // (non-runtime type) objects can never be equal to a runtime type, which typeof(XXX) is.
+ // Ideally we should throw a NotImplementedException here or just return false because
+ // customer implementations of IsSubclassOf should never return true between a non-runtime
+ // type and a runtime type. There is no benefits in making that breaking change though.
+
+ return IsSubclassOf(RuntimeType.ValueType);
+ }
+
+ // Protected routine to get the attributes.
+ abstract protected TypeAttributes GetAttributeFlagsImpl();
+
+ // Protected routine to determine if this class represents an Array
+ abstract protected bool IsArrayImpl();
+
+ // Protected routine to determine if this class is a ByRef
+ abstract protected bool IsByRefImpl();
+
+ // Protected routine to determine if this class is a Pointer
+ abstract protected bool IsPointerImpl();
+
+ // Protected routine to determine if this class represents a primitive type
+ abstract protected bool IsPrimitiveImpl();
+
+ // Protected routine to determine if this class represents a COM object
+ abstract protected bool IsCOMObjectImpl();
+
+#if FEATURE_COMINTEROP
+ // Protected routine to determine if this class represents a Windows Runtime object
+ virtual internal bool IsWindowsRuntimeObjectImpl() {
+ throw new NotImplementedException();
+ }
+
+ // Determines if this type is exported to WinRT (i.e. is an activatable class in a managed .winmd)
+ virtual internal bool IsExportedToWindowsRuntimeImpl() {
+ throw new NotImplementedException();
+ }
+#endif // FEATURE_COMINTEROP
+
+ public virtual Type MakeGenericType(params Type[] typeArguments) {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+
+ // Protected routine to determine if this class is contextful
+ protected virtual bool IsContextfulImpl(){
+ return typeof(ContextBoundObject).IsAssignableFrom(this);
+ }
+
+
+ // Protected routine to determine if this class is marshaled by ref
+ protected virtual bool IsMarshalByRefImpl(){
+ return typeof(MarshalByRefObject).IsAssignableFrom(this);
+ }
+
+ internal virtual bool HasProxyAttributeImpl()
+ {
+ // We will override this in RuntimeType
+ return false;
+ }
+
+ [Pure]
+ abstract public Type GetElementType();
+
+ [Pure]
+ public virtual Type[] GetGenericArguments()
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+ public virtual Type[] GenericTypeArguments{
+ get{
+ if(IsGenericType && !IsGenericTypeDefinition){
+ return GetGenericArguments();
+ }
+ else{
+ return Type.EmptyTypes;
+ }
+
+ }
+ }
+
+ [Pure]
+ public virtual Type GetGenericTypeDefinition()
+ {
+ Contract.Ensures(Contract.Result<Type>() != null);
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+ [Pure]
+ abstract protected bool HasElementTypeImpl();
+
+ internal Type GetRootElementType()
+ {
+ Type rootElementType = this;
+
+ while (rootElementType.HasElementType)
+ rootElementType = rootElementType.GetElementType();
+
+ return rootElementType;
+ }
+
+ #region Enum methods
+
+ // Default implementations of GetEnumNames, GetEnumValues, and GetEnumUnderlyingType
+ // Subclass of types can override these methods.
+
+ public virtual string[] GetEnumNames()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.Ensures(Contract.Result<String[]>() != null);
+
+ string[] names;
+ Array values;
+ GetEnumData(out names, out values);
+ return names;
+ }
+
+ // We don't support GetEnumValues in the default implementation because we cannot create an array of
+ // a non-runtime type. If there is strong need we can consider returning an object or int64 array.
+ public virtual Array GetEnumValues()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.Ensures(Contract.Result<Array>() != null);
+
+ throw new NotImplementedException();
+ }
+
+ // Returns the enum values as an object array.
+ private Array GetEnumRawConstantValues()
+ {
+ string[] names;
+ Array values;
+ GetEnumData(out names, out values);
+ return values;
+ }
+
+ // This will return enumValues and enumNames sorted by the values.
+ private void GetEnumData(out string[] enumNames, out Array enumValues)
+ {
+ Contract.Ensures(Contract.ValueAtReturn<String[]>(out enumNames) != null);
+ Contract.Ensures(Contract.ValueAtReturn<Array>(out enumValues) != null);
+
+ FieldInfo[] flds = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
+
+ object[] values = new object[flds.Length];
+ string[] names = new string[flds.Length];
+
+ for (int i = 0; i < flds.Length; i++)
+ {
+ names[i] = flds[i].Name;
+ values[i] = flds[i].GetRawConstantValue();
+ }
+
+ // Insertion Sort these values in ascending order.
+ // We use this O(n^2) algorithm, but it turns out that most of the time the elements are already in sorted order and
+ // the common case performance will be faster than quick sorting this.
+ IComparer comparer = Comparer.Default;
+ for (int i = 1; i < values.Length; i++)
+ {
+ int j = i;
+ string tempStr = names[i];
+ object val = values[i];
+ bool exchanged = false;
+
+ // Since the elements are sorted we only need to do one comparision, we keep the check for j inside the loop.
+ while (comparer.Compare(values[j - 1], val) > 0)
+ {
+ names[j] = names[j - 1];
+ values[j] = values[j - 1];
+ j--;
+ exchanged = true;
+ if (j == 0)
+ break;
+ }
+
+ if (exchanged)
+ {
+ names[j] = tempStr;
+ values[j] = val;
+ }
+ }
+
+ enumNames = names;
+ enumValues = values;
+ }
+
+ public virtual Type GetEnumUnderlyingType()
+ {
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.Ensures(Contract.Result<Type>() != null);
+
+ FieldInfo[] fields = GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+ if (fields == null || fields.Length != 1)
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnum"), "enumType");
+
+ return fields[0].FieldType;
+ }
+
+ public virtual bool IsEnumDefined(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ // Check if both of them are of the same type
+ Type valueType = value.GetType();
+
+ // If the value is an Enum then we need to extract the underlying value from it
+ if (valueType.IsEnum)
+ {
+ if (!valueType.IsEquivalentTo(this))
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumAndObjectMustBeSameType", valueType.ToString(), this.ToString()));
+
+ valueType = valueType.GetEnumUnderlyingType();
+ }
+
+ // If a string is passed in
+ if (valueType == typeof(string))
+ {
+ string[] names = GetEnumNames();
+ if (Array.IndexOf(names, value) >= 0)
+ return true;
+ else
+ return false;
+ }
+
+ // If an enum or integer value is passed in
+ if (Type.IsIntegerType(valueType))
+ {
+ Type underlyingType = GetEnumUnderlyingType();
+ // We cannot compare the types directly because valueType is always a runtime type but underlyingType might not be.
+ if (underlyingType.GetTypeCodeImpl() != valueType.GetTypeCodeImpl())
+ throw new ArgumentException(Environment.GetResourceString("Arg_EnumUnderlyingTypeAndObjectMustBeSameType", valueType.ToString(), underlyingType.ToString()));
+
+ Array values = GetEnumRawConstantValues();
+ return (BinarySearch(values, value) >= 0);
+ }
+ else
+ {
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_UnknownEnumType"));
+ }
+ }
+
+ public virtual string GetEnumName(object value)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ if (!IsEnum)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnum"), "enumType");
+ Contract.EndContractBlock();
+
+ Type valueType = value.GetType();
+
+ if (!(valueType.IsEnum || Type.IsIntegerType(valueType)))
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeEnumBaseTypeOrEnum"), "value");
+
+ Array values = GetEnumRawConstantValues();
+ int index = BinarySearch(values, value);
+
+ if (index >= 0)
+ {
+ string[] names = GetEnumNames();
+ return names[index];
+ }
+
+ return null;
+ }
+
+ // Convert everything to ulong then perform a binary search.
+ private static int BinarySearch(Array array, object value)
+ {
+ ulong[] ulArray = new ulong[array.Length];
+ for (int i = 0; i < array.Length; ++i)
+ ulArray[i] = Enum.ToUInt64(array.GetValue(i));
+
+ ulong ulValue = Enum.ToUInt64(value);
+
+ return Array.BinarySearch(ulArray, ulValue);
+ }
+
+ internal static bool IsIntegerType(Type t)
+ {
+ return (t == typeof(int) ||
+ t == typeof(short) ||
+ t == typeof(ushort) ||
+ t == typeof(byte) ||
+ t == typeof(sbyte) ||
+ t == typeof(uint) ||
+ t == typeof(long) ||
+ t == typeof(ulong) ||
+ t == typeof(char) ||
+ t == typeof(bool));
+ }
+ #endregion
+
+ public virtual bool IsSecurityCritical { [Pure] get { throw new NotImplementedException(); } }
+
+ public virtual bool IsSecuritySafeCritical { [Pure] get { throw new NotImplementedException(); } }
+
+ public virtual bool IsSecurityTransparent { [Pure] get { throw new NotImplementedException(); } }
+
+ internal bool NeedsReflectionSecurityCheck
+ {
+ get
+ {
+ if (!IsVisible)
+ {
+ // Types which are not externally visible require security checks
+ return true;
+ }
+ else if (IsSecurityCritical && !IsSecuritySafeCritical)
+ {
+ // Critical types require security checks
+ return true;
+ }
+ else if (IsGenericType)
+ {
+ // If any of the generic arguments to this type require a security check, then this type
+ // also requires one.
+ foreach (Type genericArgument in GetGenericArguments())
+ {
+ if (genericArgument.NeedsReflectionSecurityCheck)
+ {
+ return true;
+ }
+ }
+ }
+ else if (IsArray || IsPointer)
+ {
+ return GetElementType().NeedsReflectionSecurityCheck;
+ }
+
+ return false;
+ }
+ }
+
+ // The behavior of UnderlyingSystemType varies from type to type.
+ // For IReflect objects: Return the underlying Type that represents the IReflect Object.
+ // For expando object: this is the (Object) IReflectInstance.GetType(). For Type object it is this.
+ // It could also return the baked type or the underlying enum type in RefEmit. See the comment in
+ // code:TypeBuilder.SetConstantValue.
+ public abstract Type UnderlyingSystemType {
+ get;
+ }
+
+ // Returns true of this class is a true subclass of c. Everything
+ // else returns false. If this class and c are the same class false is
+ // returned.
+ //
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Pure]
+ public virtual bool IsSubclassOf(Type c)
+ {
+ Type p = this;
+ if (p == c)
+ return false;
+ while (p != null) {
+ if (p == c)
+ return true;
+ p = p.BaseType;
+ }
+ return false;
+ }
+
+ // Returns true if the object passed is assignable to an instance of this class.
+ // Everything else returns false.
+ //
+ [Pure]
+ public virtual bool IsInstanceOfType(Object o)
+ {
+ if (o == null)
+ return false;
+
+ // No need for transparent proxy casting check here
+ // because it never returns true for a non-rutnime type.
+
+ return IsAssignableFrom(o.GetType());
+ }
+
+ // Returns true if an instance of Type c may be assigned
+ // to an instance of this class. Return false otherwise.
+ //
+ [Pure]
+ public virtual bool IsAssignableFrom(Type c)
+ {
+ if (c == null)
+ return false;
+
+ if (this == c)
+ return true;
+
+ // For backward-compatibility, we need to special case for the types
+ // whose UnderlyingSystemType are RuntimeType objects.
+ RuntimeType toType = this.UnderlyingSystemType as RuntimeType;
+ if (toType != null)
+ return toType.IsAssignableFrom(c);
+
+ // If c is a subclass of this class, then c can be cast to this type.
+ if (c.IsSubclassOf(this))
+ return true;
+
+ if (this.IsInterface)
+ {
+ return c.ImplementInterface(this);
+ }
+ else if (IsGenericParameter)
+ {
+ Type[] constraints = GetGenericParameterConstraints();
+ for (int i = 0; i < constraints.Length; i++)
+ if (!constraints[i].IsAssignableFrom(c))
+ return false;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ // Base implementation that does only ==.
+ [Pure]
+ public virtual bool IsEquivalentTo(Type other)
+ {
+ return (this == other);
+ }
+
+ internal bool ImplementInterface(Type ifaceType)
+ {
+ Contract.Requires(ifaceType != null);
+ Contract.Requires(ifaceType.IsInterface, "ifaceType must be an interface type");
+
+ Type t = this;
+ while (t != null)
+ {
+ Type[] interfaces = t.GetInterfaces();
+ if (interfaces != null)
+ {
+ for (int i = 0; i < interfaces.Length; i++)
+ {
+ // Interfaces don't derive from other interfaces, they implement them.
+ // So instead of IsSubclassOf, we should use ImplementInterface instead.
+ if (interfaces[i] == ifaceType ||
+ (interfaces[i] != null && interfaces[i].ImplementInterface(ifaceType)))
+ return true;
+ }
+ }
+
+ t = t.BaseType;
+ }
+
+ return false;
+ }
+
+ // This is only ever called on RuntimeType objects.
+ internal string FormatTypeName()
+ {
+ return FormatTypeName(false);
+ }
+
+ internal virtual string FormatTypeName(bool serialization)
+ {
+ throw new NotImplementedException();
+ }
+
+ // ToString
+ // Print the String Representation of the Type
+ public override String ToString()
+ {
+ // Why do we add the "Type: " prefix? RuntimeType.ToString() doesn't include it.
+ return "Type: " + Name;
+ }
+
+ // This method will return an array of classes based upon the array of
+ // types.
+ public static Type[] GetTypeArray(Object[] args) {
+ if (args == null)
+ throw new ArgumentNullException("args");
+ Contract.EndContractBlock();
+ Type[] cls = new Type[args.Length];
+ for (int i = 0;i < cls.Length;i++)
+ {
+ if (args[i] == null)
+ throw new ArgumentNullException();
+ cls[i] = args[i].GetType();
+ }
+ return cls;
+ }
+
+ [Pure]
+ public override bool Equals(Object o)
+ {
+ if (o == null)
+ return false;
+
+ return Equals(o as Type);
+ }
+
+ // _Type.Equals(Type)
+ [Pure]
+#if !FEATURE_CORECLR
+ public virtual bool Equals(Type o)
+#else
+ public bool Equals(Type o)
+#endif
+ {
+ if ((object)o == null)
+ return false;
+
+ return (Object.ReferenceEquals(this.UnderlyingSystemType, o.UnderlyingSystemType));
+ }
+
+ [System.Security.SecuritySafeCritical]
+ [Pure]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool operator ==(Type left, Type right);
+
+ [System.Security.SecuritySafeCritical]
+ [Pure]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public static extern bool operator !=(Type left, Type right);
+
+ public override int GetHashCode()
+ {
+ Type SystemType = UnderlyingSystemType;
+ if (!Object.ReferenceEquals(SystemType, this))
+ return SystemType.GetHashCode();
+ return base.GetHashCode();
+ }
+
+
+ // GetInterfaceMap
+ // This method will return an interface mapping for the interface
+ // requested. It will throw an argument exception if the Type doesn't
+ // implemenet the interface.
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public virtual InterfaceMapping GetInterfaceMap(Type interfaceType)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_SubclassOverride"));
+ }
+
+ // this method is required so Object.GetType is not made virtual by the compiler
+ // _Type.GetType()
+ public new Type GetType()
+ {
+ return base.GetType();
+ }
+
+#if !FEATURE_CORECLR
+ void _Type.GetTypeInfoCount(out uint pcTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Type.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException();
+ }
+
+ void _Type.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException();
+ }
+
+ // If you implement this method, make sure to include _Type.Invoke in VM\DangerousAPIs.h and
+ // include _Type in SystemDomain::IsReflectionInvocationMethod in AppDomain.cpp.
+ void _Type.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException();
+ }
+#endif
+
+ // private convenience data
+ private const BindingFlags DefaultLookup = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public;
+ internal const BindingFlags DeclaredOnlyLookup = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly;
+}
+}
diff --git a/src/mscorlib/src/System/TypeAccessException.cs b/src/mscorlib/src/System/TypeAccessException.cs
new file mode 100644
index 0000000000..5ddc9a7538
--- /dev/null
+++ b/src/mscorlib/src/System/TypeAccessException.cs
@@ -0,0 +1,40 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Runtime.Serialization;
+using System.Security;
+
+namespace System
+{
+ // TypeAccessException derives from TypeLoadException rather than MemberAccessException because in
+ // pre-v4 releases of the runtime TypeLoadException was used in lieu of a TypeAccessException.
+ [Serializable]
+ public class TypeAccessException : TypeLoadException
+ {
+ public TypeAccessException()
+ : base(Environment.GetResourceString("Arg_TypeAccessException"))
+ {
+ SetErrorCode(__HResults.COR_E_TYPEACCESS);
+ }
+
+ public TypeAccessException(string message)
+ : base(message)
+ {
+ SetErrorCode(__HResults.COR_E_TYPEACCESS);
+ }
+
+ public TypeAccessException(string message, Exception inner)
+ : base(message, inner)
+ {
+ SetErrorCode(__HResults.COR_E_TYPEACCESS);
+ }
+
+ protected TypeAccessException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ SetErrorCode(__HResults.COR_E_TYPEACCESS);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/TypeCode.cs b/src/mscorlib/src/System/TypeCode.cs
new file mode 100644
index 0000000000..bf71c2fd5b
--- /dev/null
+++ b/src/mscorlib/src/System/TypeCode.cs
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// The TypeCode enum represents the type code of an object. To obtain the
+// TypeCode for a given object, use the Value.GetTypeCode() method. The
+// TypeCode.Empty value represents a null object reference. The TypeCode.Object
+// value represents an object that doesn't implement the IConvertible interface. The
+// TypeCode.DBNull value represents the database null, which is distinct and
+// different from a null reference. The other type codes represent values that
+// use the given simple type encoding.
+//
+// Note that when an object has a given TypeCode, there is no guarantee that
+// the object is an instance of the corresponding System.XXX value class. For
+// example, an object with the type code TypeCode.Int32 might actually be an
+// instance of a nullable 32-bit integer type (with a value that isn't the
+// database null).
+//
+// There are no type codes for "Missing", "Error", "IDispatch", and "IUnknown".
+// These types of values are instead represented as classes. When the type code
+// of an object is TypeCode.Object, a further instance-of check can be used to
+// determine if the object is one of these values.
+namespace System {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public enum TypeCode {
+ Empty = 0, // Null reference
+ Object = 1, // Instance that isn't a value
+ DBNull = 2, // Database null value
+ Boolean = 3, // Boolean
+ Char = 4, // Unicode character
+ SByte = 5, // Signed 8-bit integer
+ Byte = 6, // Unsigned 8-bit integer
+ Int16 = 7, // Signed 16-bit integer
+ UInt16 = 8, // Unsigned 16-bit integer
+ Int32 = 9, // Signed 32-bit integer
+ UInt32 = 10, // Unsigned 32-bit integer
+ Int64 = 11, // Signed 64-bit integer
+ UInt64 = 12, // Unsigned 64-bit integer
+ Single = 13, // IEEE 32-bit float
+ Double = 14, // IEEE 64-bit double
+ Decimal = 15, // Decimal
+ DateTime = 16, // DateTime
+ String = 18, // Unicode character string
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/TypeInitializationException.cs b/src/mscorlib/src/System/TypeInitializationException.cs
new file mode 100644
index 0000000000..62d189d53b
--- /dev/null
+++ b/src/mscorlib/src/System/TypeInitializationException.cs
@@ -0,0 +1,66 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class to wrap exceptions thrown by
+** a type's class initializer (.cctor). This is sufficiently
+** distinct from a TypeLoadException, which means we couldn't
+** find the type.
+**
+**
+=============================================================================*/
+using System;
+using System.Runtime.Serialization;
+using System.Globalization;
+using System.Security.Permissions;
+
+namespace System {
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class TypeInitializationException : SystemException {
+ private String _typeName;
+
+ // This exception is not creatable without specifying the
+ // inner exception.
+ private TypeInitializationException()
+ : base(Environment.GetResourceString("TypeInitialization_Default")) {
+ SetErrorCode(__HResults.COR_E_TYPEINITIALIZATION);
+ }
+
+ // This is called from within the runtime. I believe this is necessary
+ // for Interop only, though it's not particularly useful.
+ private TypeInitializationException(String message) : base(message) {
+ SetErrorCode(__HResults.COR_E_TYPEINITIALIZATION);
+ }
+
+ public TypeInitializationException(String fullTypeName, Exception innerException) : base(Environment.GetResourceString("TypeInitialization_Type", fullTypeName), innerException) {
+ _typeName = fullTypeName;
+ SetErrorCode(__HResults.COR_E_TYPEINITIALIZATION);
+ }
+
+ internal TypeInitializationException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ _typeName = info.GetString("TypeName");
+ }
+
+ public String TypeName
+ {
+ get {
+ if (_typeName == null) {
+ return String.Empty;
+ }
+ return _typeName;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ base.GetObjectData(info, context);
+ info.AddValue("TypeName",TypeName,typeof(String));
+ }
+
+ }
+}
diff --git a/src/mscorlib/src/System/TypeLoadException.cs b/src/mscorlib/src/System/TypeLoadException.cs
new file mode 100644
index 0000000000..9b5d28dfba
--- /dev/null
+++ b/src/mscorlib/src/System/TypeLoadException.cs
@@ -0,0 +1,143 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: The exception class for type loading failures.
+**
+**
+=============================================================================*/
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.Remoting;
+ using System.Runtime.Serialization;
+ using System.Runtime.InteropServices;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class TypeLoadException : SystemException, ISerializable {
+
+ public TypeLoadException()
+ : base(Environment.GetResourceString("Arg_TypeLoadException")) {
+ SetErrorCode(__HResults.COR_E_TYPELOAD);
+ }
+
+ public TypeLoadException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_TYPELOAD);
+ }
+
+ public TypeLoadException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_TYPELOAD);
+ }
+
+ public override String Message
+ {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ SetMessageField();
+ return _message;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private void SetMessageField()
+ {
+ if (_message == null) {
+ if ((ClassName == null) &&
+ (ResourceId == 0))
+ _message = Environment.GetResourceString("Arg_TypeLoadException");
+
+ else {
+ if (AssemblyName == null)
+ AssemblyName = Environment.GetResourceString("IO_UnknownFileName");
+ if (ClassName == null)
+ ClassName = Environment.GetResourceString("IO_UnknownFileName");
+
+ String format = null;
+ GetTypeLoadExceptionMessage(ResourceId, JitHelpers.GetStringHandleOnStack(ref format));
+ _message = String.Format(CultureInfo.CurrentCulture, format, ClassName, AssemblyName, MessageArg);
+ }
+ }
+ }
+
+ public String TypeName
+ {
+ get {
+ if (ClassName == null)
+ return String.Empty;
+
+ return ClassName;
+ }
+ }
+
+ // This is called from inside the EE.
+ [System.Security.SecurityCritical] // auto-generated
+ private TypeLoadException(String className,
+ String assemblyName,
+ String messageArg,
+ int resourceId)
+ : base(null)
+ {
+ SetErrorCode(__HResults.COR_E_TYPELOAD);
+ ClassName = className;
+ AssemblyName = assemblyName;
+ MessageArg = messageArg;
+ ResourceId = resourceId;
+
+ // Set the _message field eagerly; debuggers look at this field to
+ // display error info. They don't call the Message property.
+ SetMessageField();
+ }
+
+ protected TypeLoadException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ ClassName = info.GetString("TypeLoadClassName");
+ AssemblyName = info.GetString("TypeLoadAssemblyName");
+ MessageArg = info.GetString("TypeLoadMessageArg");
+ ResourceId = info.GetInt32("TypeLoadResourceID");
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void GetTypeLoadExceptionMessage(int resourceId, StringHandleOnStack retString);
+
+ //We can rely on the serialization mechanism on Exception to handle most of our needs, but
+ //we need to add a few fields of our own.
+ [System.Security.SecurityCritical] // auto-generated_required
+ public override void GetObjectData(SerializationInfo info, StreamingContext context) {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ base.GetObjectData(info, context);
+ info.AddValue("TypeLoadClassName", ClassName, typeof(String));
+ info.AddValue("TypeLoadAssemblyName", AssemblyName, typeof(String));
+ info.AddValue("TypeLoadMessageArg", MessageArg, typeof(String));
+ info.AddValue("TypeLoadResourceID", ResourceId);
+ }
+
+ // If ClassName != null, GetMessage will construct on the fly using it
+ // and ResourceId (mscorrc.dll). This allows customization of the
+ // class name format depending on the language environment.
+ private String ClassName;
+ private String AssemblyName;
+ private String MessageArg;
+ internal int ResourceId;
+ }
+}
diff --git a/src/mscorlib/src/System/TypeNameParser.cs b/src/mscorlib/src/System/TypeNameParser.cs
new file mode 100644
index 0000000000..fee0f3aa64
--- /dev/null
+++ b/src/mscorlib/src/System/TypeNameParser.cs
@@ -0,0 +1,365 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System;
+using System.Diagnostics.Contracts;
+using System.IO;
+using System.Reflection;
+using System.Security;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Runtime.Versioning;
+using Microsoft.Win32.SafeHandles;
+
+namespace System
+{
+ [SecurityCritical]
+ internal class SafeTypeNameParserHandle : SafeHandleZeroOrMinusOneIsInvalid
+ {
+ #region QCalls
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _ReleaseTypeNameParser(IntPtr pTypeNameParser);
+ #endregion
+
+ public SafeTypeNameParserHandle()
+ : base(true)
+ {
+ }
+
+ [SecurityCritical]
+ protected override bool ReleaseHandle()
+ {
+ _ReleaseTypeNameParser(handle);
+ handle = IntPtr.Zero;
+ return true;
+ }
+ }
+
+ internal sealed class TypeNameParser : IDisposable
+ {
+ #region QCalls
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _CreateTypeNameParser(string typeName, ObjectHandleOnStack retHandle, bool throwOnError);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _GetNames(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _GetTypeArguments(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _GetModifiers(SafeTypeNameParserHandle pTypeNameParser, ObjectHandleOnStack retArray);
+
+ [SecurityCritical]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ private static extern void _GetAssemblyName(SafeTypeNameParserHandle pTypeNameParser, StringHandleOnStack retString);
+ #endregion
+
+ #region Static Members
+ [SecuritySafeCritical]
+ internal static Type GetType(
+ string typeName,
+ Func<AssemblyName, Assembly> assemblyResolver,
+ Func<Assembly, string, bool, Type> typeResolver,
+ bool throwOnError,
+ bool ignoreCase,
+ ref StackCrawlMark stackMark)
+ {
+ if (typeName == null)
+ throw new ArgumentNullException("typeName");
+ if (typeName.Length > 0 && typeName[0] == '\0')
+ throw new ArgumentException(Environment.GetResourceString("Format_StringZeroLength"));
+ Contract.EndContractBlock();
+
+ Type ret = null;
+
+ SafeTypeNameParserHandle handle = CreateTypeNameParser(typeName, throwOnError);
+
+ if (handle != null)
+ {
+ // If we get here the typeName must have been successfully parsed.
+ // Let's construct the Type object.
+ using (TypeNameParser parser = new TypeNameParser(handle))
+ {
+ ret = parser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
+ }
+ }
+
+ return ret;
+ }
+ #endregion
+
+ #region Private Data Members
+ [SecurityCritical]
+ private SafeTypeNameParserHandle m_NativeParser;
+ private static readonly char[] SPECIAL_CHARS = {',', '[', ']', '&', '*', '+', '\\'}; /* see typeparse.h */
+ #endregion
+
+ #region Constructor and Disposer
+ [SecuritySafeCritical]
+ private TypeNameParser(SafeTypeNameParserHandle handle)
+ {
+ m_NativeParser = handle;
+ }
+
+ [SecuritySafeCritical]
+ public void Dispose()
+ {
+ m_NativeParser.Dispose();
+ }
+ #endregion
+
+ #region private Members
+ [SecuritySafeCritical]
+ private unsafe Type ConstructType(
+ Func<AssemblyName, Assembly> assemblyResolver,
+ Func<Assembly, string, bool, Type> typeResolver,
+ bool throwOnError,
+ bool ignoreCase,
+ ref StackCrawlMark stackMark)
+ {
+ // assembly name
+ Assembly assembly = null;
+ string asmName = GetAssemblyName();
+
+ // GetAssemblyName never returns null
+ Contract.Assert(asmName != null);
+
+ if (asmName.Length > 0)
+ {
+ assembly = ResolveAssembly(asmName, assemblyResolver, throwOnError, ref stackMark);
+
+ if (assembly == null)
+ {
+ // Cannot resolve the assembly. If throwOnError is true we should have already thrown.
+ return null;
+ }
+ }
+
+ string[] names = GetNames();
+ if (names == null)
+ {
+ // This can only happen if the type name is an empty string or if the first char is '\0'
+ if (throwOnError)
+ throw new TypeLoadException(Environment.GetResourceString("Arg_TypeLoadNullStr"));
+
+ return null;
+ }
+
+ Type baseType = ResolveType(assembly, names, typeResolver, throwOnError, ignoreCase, ref stackMark);
+
+ if (baseType == null)
+ {
+ // Cannot resolve the type. If throwOnError is true we should have already thrown.
+ Contract.Assert(throwOnError == false);
+ return null;
+ }
+
+ SafeTypeNameParserHandle[] typeArguments = GetTypeArguments();
+
+ Type[] types = null;
+ if (typeArguments != null)
+ {
+ types = new Type[typeArguments.Length];
+ for (int i = 0; i < typeArguments.Length; i++)
+ {
+ Contract.Assert(typeArguments[i] != null);
+
+ using (TypeNameParser argParser = new TypeNameParser(typeArguments[i]))
+ {
+ types[i] = argParser.ConstructType(assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
+ }
+
+ if (types[i] == null)
+ {
+ // If throwOnError is true argParser.ConstructType should have already thrown.
+ Contract.Assert(throwOnError == false);
+ return null;
+ }
+ }
+ }
+
+ int[] modifiers = GetModifiers();
+
+ fixed (int* ptr = modifiers)
+ {
+ IntPtr intPtr = new IntPtr(ptr);
+ return RuntimeTypeHandle.GetTypeHelper(baseType, types, intPtr, modifiers == null ? 0 : modifiers.Length);
+ }
+ }
+
+ [SecuritySafeCritical]
+ private static Assembly ResolveAssembly(string asmName, Func<AssemblyName, Assembly> assemblyResolver, bool throwOnError, ref StackCrawlMark stackMark)
+ {
+ Contract.Requires(asmName != null && asmName.Length > 0);
+
+ Assembly assembly = null;
+
+ if (assemblyResolver == null)
+ {
+ if (throwOnError)
+ {
+ assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/);
+ }
+ else
+ {
+ // When throwOnError is false we should only catch FileNotFoundException.
+ // Other exceptions like BadImangeFormatException should still fly.
+ try
+ {
+ assembly = RuntimeAssembly.InternalLoad(asmName, null, ref stackMark, false /*forIntrospection*/);
+ }
+ catch (FileNotFoundException)
+ {
+ return null;
+ }
+ }
+ }
+ else
+ {
+ assembly = assemblyResolver(new AssemblyName(asmName));
+ if (assembly == null && throwOnError)
+ {
+ throw new FileNotFoundException(Environment.GetResourceString("FileNotFound_ResolveAssembly", asmName));
+ }
+ }
+
+ return assembly;
+ }
+
+ private static Type ResolveType(Assembly assembly, string[] names, Func<Assembly, string, bool, Type> typeResolver, bool throwOnError, bool ignoreCase, ref StackCrawlMark stackMark)
+ {
+ Contract.Requires(names != null && names.Length > 0);
+
+ Type type = null;
+
+ // both the customer provided and the default type resolvers accept escaped type names
+ string OuterMostTypeName = EscapeTypeName(names[0]);
+
+ // Resolve the top level type.
+ if (typeResolver != null)
+ {
+ type = typeResolver(assembly, OuterMostTypeName, ignoreCase);
+
+ if (type == null && throwOnError)
+ {
+ string errorString = assembly == null ?
+ Environment.GetResourceString("TypeLoad_ResolveType", OuterMostTypeName) :
+ Environment.GetResourceString("TypeLoad_ResolveTypeFromAssembly", OuterMostTypeName, assembly.FullName);
+
+ throw new TypeLoadException(errorString);
+ }
+ }
+ else
+ {
+ if (assembly == null)
+ {
+ type = RuntimeType.GetType(OuterMostTypeName, throwOnError, ignoreCase, false, ref stackMark);
+ }
+ else
+ {
+ type = assembly.GetType(OuterMostTypeName, throwOnError, ignoreCase);
+ }
+ }
+
+ // Resolve nested types.
+ if (type != null)
+ {
+ BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public;
+ if (ignoreCase)
+ bindingFlags |= BindingFlags.IgnoreCase;
+
+ for (int i = 1; i < names.Length; i++)
+ {
+ type = type.GetNestedType(names[i], bindingFlags);
+
+ if (type == null)
+ {
+ if (throwOnError)
+ throw new TypeLoadException(Environment.GetResourceString("TypeLoad_ResolveNestedType", names[i], names[i-1]));
+ else
+ break;
+ }
+ }
+ }
+
+ return type;
+ }
+
+ private static string EscapeTypeName(string name)
+ {
+ if (name.IndexOfAny(SPECIAL_CHARS) < 0)
+ return name;
+
+ StringBuilder sb = StringBuilderCache.Acquire();
+ foreach (char c in name)
+ {
+ if (Array.IndexOf<char>(SPECIAL_CHARS, c) >= 0)
+ sb.Append('\\');
+
+ sb.Append(c);
+ }
+
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ [SecuritySafeCritical]
+ private static SafeTypeNameParserHandle CreateTypeNameParser(string typeName, bool throwOnError)
+ {
+ SafeTypeNameParserHandle retHandle = null;
+ _CreateTypeNameParser(typeName, JitHelpers.GetObjectHandleOnStack(ref retHandle), throwOnError);
+
+ return retHandle;
+ }
+
+ [SecuritySafeCritical]
+ private string[] GetNames()
+ {
+ string[] names = null;
+ _GetNames(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref names));
+
+ return names;
+ }
+
+ [SecuritySafeCritical]
+ private SafeTypeNameParserHandle[] GetTypeArguments()
+ {
+ SafeTypeNameParserHandle[] arguments = null;
+ _GetTypeArguments(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref arguments));
+
+ return arguments;
+ }
+
+ [SecuritySafeCritical]
+ private int[] GetModifiers()
+ {
+ int[] modifiers = null;
+ _GetModifiers(m_NativeParser, JitHelpers.GetObjectHandleOnStack(ref modifiers));
+
+ return modifiers;
+ }
+
+ [SecuritySafeCritical]
+ private string GetAssemblyName()
+ {
+ string assemblyName = null;
+ _GetAssemblyName(m_NativeParser, JitHelpers.GetStringHandleOnStack(ref assemblyName));
+
+ return assemblyName;
+ }
+ #endregion
+ }
+}
diff --git a/src/mscorlib/src/System/TypeUnloadedException.cs b/src/mscorlib/src/System/TypeUnloadedException.cs
new file mode 100644
index 0000000000..511314d329
--- /dev/null
+++ b/src/mscorlib/src/System/TypeUnloadedException.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Exception class for attempt to access an unloaded class
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System.Runtime.Serialization;
+
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [Serializable]
+ public class TypeUnloadedException : SystemException {
+ public TypeUnloadedException()
+ : base(Environment.GetResourceString("Arg_TypeUnloadedException")) {
+ SetErrorCode(__HResults.COR_E_TYPEUNLOADED);
+ }
+
+ public TypeUnloadedException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_TYPEUNLOADED);
+ }
+
+ public TypeUnloadedException(String message, Exception innerException)
+ : base(message, innerException) {
+ SetErrorCode(__HResults.COR_E_TYPEUNLOADED);
+ }
+
+ //
+ // This constructor is required for serialization;
+ //
+ protected TypeUnloadedException(SerializationInfo info, StreamingContext context) : base (info, context) {
+ }
+ }
+}
+
diff --git a/src/mscorlib/src/System/TypedReference.cs b/src/mscorlib/src/System/TypedReference.cs
new file mode 100644
index 0000000000..7c68c4164f
--- /dev/null
+++ b/src/mscorlib/src/System/TypedReference.cs
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ // TypedReference is basically only ever seen on the call stack, and in param arrays.
+ // These are blob that must be dealt with by the compiler.
+ using System;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using FieldInfo = System.Reflection.FieldInfo;
+ using System.Security.Permissions;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ [System.Runtime.Versioning.NonVersionable] // This only applies to field layout
+ public struct TypedReference
+ {
+ private IntPtr Value;
+ private IntPtr Type;
+
+ [System.Security.SecurityCritical] // auto-generated_required
+ [CLSCompliant(false)]
+ public static TypedReference MakeTypedReference(Object target, FieldInfo[] flds) {
+ if (target == null)
+ throw new ArgumentNullException("target");
+ if (flds == null)
+ throw new ArgumentNullException("flds");
+ Contract.EndContractBlock();
+ if (flds.Length == 0)
+ throw new ArgumentException(Environment.GetResourceString("Arg_ArrayZeroError"));
+
+ IntPtr[] fields = new IntPtr[flds.Length];
+ // For proper handling of Nullable<T> don't change GetType() to something like 'IsAssignableFrom'
+ // Currently we can't make a TypedReference to fields of Nullable<T>, which is fine.
+ RuntimeType targetType = (RuntimeType)target.GetType();
+ for (int i = 0; i < flds.Length; i++)
+ {
+ RuntimeFieldInfo field = flds[i] as RuntimeFieldInfo;
+ if (field == null)
+ throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeFieldInfo"));
+
+ if (field.IsInitOnly || field.IsStatic)
+ throw new ArgumentException(Environment.GetResourceString("Argument_TypedReferenceInvalidField"));
+
+ if (targetType != field.GetDeclaringTypeInternal() && !targetType.IsSubclassOf(field.GetDeclaringTypeInternal()))
+ throw new MissingMemberException(Environment.GetResourceString("MissingMemberTypeRef"));
+
+ RuntimeType fieldType = (RuntimeType)field.FieldType;
+ if (fieldType.IsPrimitive)
+ throw new ArgumentException(Environment.GetResourceString("Arg_TypeRefPrimitve"));
+
+ if (i < (flds.Length - 1) && !fieldType.IsValueType)
+ throw new MissingMemberException(Environment.GetResourceString("MissingMemberNestErr"));
+
+ fields[i] = field.FieldHandle.Value;
+ targetType = fieldType;
+ }
+
+ TypedReference result = new TypedReference ();
+
+ // reference to TypedReference is banned, so have to pass result as pointer
+ unsafe
+ {
+ InternalMakeTypedReference(&result, target, fields, targetType);
+ }
+ return result;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ // reference to TypedReference is banned, so have to pass result as pointer
+ private unsafe static extern void InternalMakeTypedReference(void* result, Object target, IntPtr[] flds, RuntimeType lastFieldType);
+
+ public override int GetHashCode()
+ {
+ if (Type == IntPtr.Zero)
+ return 0;
+ else
+ return __reftype(this).GetHashCode();
+ }
+
+ public override bool Equals(Object o)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_NYI"));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe static Object ToObject(TypedReference value)
+ {
+ return InternalToObject(&value);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe extern static Object InternalToObject(void * value);
+
+ internal bool IsNull
+ {
+ get
+ {
+ return Value.IsNull() && Type.IsNull();
+ }
+ }
+
+ public static Type GetTargetType (TypedReference value)
+ {
+ return __reftype(value);
+ }
+
+ public static RuntimeTypeHandle TargetTypeToken (TypedReference value)
+ {
+ return __reftype(value).TypeHandle;
+ }
+
+ // This may cause the type to be changed.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ public unsafe static void SetTypedReference(TypedReference target, Object value)
+ {
+ InternalSetTypedReference(&target, value);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal unsafe extern static void InternalSetTypedReference(void * target, Object value);
+ }
+
+}
diff --git a/src/mscorlib/src/System/UInt16.cs b/src/mscorlib/src/System/UInt16.cs
new file mode 100644
index 0000000000..dba7f97b77
--- /dev/null
+++ b/src/mscorlib/src/System/UInt16.cs
@@ -0,0 +1,241 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: This class will encapsulate a short and provide an
+** Object representation of it.
+**
+**
+===========================================================*/
+namespace System {
+ using System.Globalization;
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // Wrapper for unsigned 16 bit integers.
+[Serializable]
+[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct UInt16 : IComparable, IFormattable, IConvertible
+ , IComparable<UInt16>, IEquatable<UInt16>
+ {
+ private ushort m_value;
+
+ public const ushort MaxValue = (ushort)0xFFFF;
+ public const ushort MinValue = 0;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt16, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is UInt16) {
+ return ((int)m_value - (int)(((UInt16)value).m_value));
+ }
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeUInt16"));
+ }
+
+ public int CompareTo(UInt16 value) {
+ return ((int)m_value - (int)value);
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is UInt16)) {
+ return false;
+ }
+ return m_value == ((UInt16)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(UInt16 obj)
+ {
+ return m_value == obj;
+ }
+
+ // Returns a HashCode for the UInt16
+ public override int GetHashCode() {
+ return (int)m_value;
+ }
+
+ // Converts the current value to a String in base-10 with no extra padding.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, IFormatProvider provider) {
+ return Parse(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ushort Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Parse(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ private static ushort Parse(String s, NumberStyles style, NumberFormatInfo info) {
+
+ uint i = 0;
+ try {
+ i = Number.ParseUInt32(s, style, info);
+ }
+ catch(OverflowException e) {
+ throw new OverflowException(Environment.GetResourceString("Overflow_UInt16"), e);
+ }
+
+ if (i > MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_UInt16"));
+ return (ushort)i;
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out UInt16 result) {
+ return TryParse(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt16 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out UInt16 result) {
+
+ result = 0;
+ UInt32 i;
+ if (!Number.TryParseUInt32(s, style, info, out i)) {
+ return false;
+ }
+ if (i > MaxValue) {
+ return false;
+ }
+ result = (UInt16) i;
+ return true;
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.UInt16;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "UInt16", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UInt32.cs b/src/mscorlib/src/System/UInt32.cs
new file mode 100644
index 0000000000..7010daec43
--- /dev/null
+++ b/src/mscorlib/src/System/UInt32.cs
@@ -0,0 +1,223 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: This class will encapsulate an uint and
+** provide an Object representation of it.
+**
+**
+===========================================================*/
+namespace System {
+ using System.Globalization;
+ using System;
+ using System.Runtime;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // * Wrapper for unsigned 32 bit integers.
+ [Serializable]
+ [CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct UInt32 : IComparable, IFormattable, IConvertible
+ , IComparable<UInt32>, IEquatable<UInt32>
+ {
+ private uint m_value;
+
+ public const uint MaxValue = (uint)0xffffffff;
+ public const uint MinValue = 0U;
+
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt32, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is UInt32) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ uint i = (uint)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeUInt32"));
+ }
+
+ public int CompareTo(UInt32 value) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is UInt32)) {
+ return false;
+ }
+ return m_value == ((UInt32)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(UInt32 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The absolute value of the int contained.
+ public override int GetHashCode() {
+ return ((int) m_value);
+ }
+
+ // The base 10 representation of the number with no extra padding.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt32(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s) {
+ return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt32(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, IFormatProvider provider) {
+ return Number.ParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static uint Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt32(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, out UInt32 result) {
+ return Number.TryParseUInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt32 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseUInt32(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.UInt32;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return Convert.ToUInt64(m_value);
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "UInt32", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UInt64.cs b/src/mscorlib/src/System/UInt64.cs
new file mode 100644
index 0000000000..83549cf423
--- /dev/null
+++ b/src/mscorlib/src/System/UInt64.cs
@@ -0,0 +1,218 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: This class will encapsulate an unsigned long and
+** provide an Object representation of it.
+**
+**
+===========================================================*/
+namespace System {
+ using System.Globalization;
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics.Contracts;
+
+ // Wrapper for unsigned 64 bit integers.
+[Serializable]
+[CLSCompliant(false), System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public struct UInt64 : IComparable, IFormattable, IConvertible
+ , IComparable<UInt64>, IEquatable<UInt64>
+ {
+ private ulong m_value;
+
+ public const ulong MaxValue = (ulong) 0xffffffffffffffffL;
+ public const ulong MinValue = 0x0;
+
+ // Compares this object to another object, returning an integer that
+ // indicates the relationship.
+ // Returns a value less than zero if this object
+ // null is considered to be less than any instance.
+ // If object is not of type UInt64, this method throws an ArgumentException.
+ //
+ public int CompareTo(Object value) {
+ if (value == null) {
+ return 1;
+ }
+ if (value is UInt64) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ ulong i = (ulong)value;
+ if (m_value < i) return -1;
+ if (m_value > i) return 1;
+ return 0;
+ }
+ throw new ArgumentException (Environment.GetResourceString("Arg_MustBeUInt64"));
+ }
+
+ public int CompareTo(UInt64 value) {
+ // Need to use compare because subtraction will wrap
+ // to positive for very large neg numbers, etc.
+ if (m_value < value) return -1;
+ if (m_value > value) return 1;
+ return 0;
+ }
+
+ public override bool Equals(Object obj) {
+ if (!(obj is UInt64)) {
+ return false;
+ }
+ return m_value == ((UInt64)obj).m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public bool Equals(UInt64 obj)
+ {
+ return m_value == obj;
+ }
+
+ // The value of the lower 32 bits XORed with the uppper 32 bits.
+ public override int GetHashCode() {
+ return ((int)m_value) ^ (int)(m_value >> 32);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, null, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, null, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, format, NumberFormatInfo.CurrentInfo);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public String ToString(String format, IFormatProvider provider) {
+ Contract.Ensures(Contract.Result<String>() != null);
+ return Number.FormatUInt64(m_value, format, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s) {
+ return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s, NumberStyles style) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt64(s, style, NumberFormatInfo.CurrentInfo);
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(string s, IFormatProvider provider) {
+ return Number.ParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static ulong Parse(String s, NumberStyles style, IFormatProvider provider) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.ParseUInt64(s, style, NumberFormatInfo.GetInstance(provider));
+ }
+
+ [CLSCompliant(false)]
+ public static Boolean TryParse(String s, out UInt64 result) {
+ return Number.TryParseUInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
+ }
+
+ [CLSCompliant(false)]
+ public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out UInt64 result) {
+ NumberFormatInfo.ValidateParseStyleInteger(style);
+ return Number.TryParseUInt64(s, style, NumberFormatInfo.GetInstance(provider), out result);
+ }
+
+ //
+ // IConvertible implementation
+ //
+
+ public TypeCode GetTypeCode() {
+ return TypeCode.UInt64;
+ }
+
+ /// <internalonly/>
+ bool IConvertible.ToBoolean(IFormatProvider provider) {
+ return Convert.ToBoolean(m_value);
+ }
+
+ /// <internalonly/>
+ char IConvertible.ToChar(IFormatProvider provider) {
+ return Convert.ToChar(m_value);
+ }
+
+ /// <internalonly/>
+ sbyte IConvertible.ToSByte(IFormatProvider provider) {
+ return Convert.ToSByte(m_value);
+ }
+
+ /// <internalonly/>
+ byte IConvertible.ToByte(IFormatProvider provider) {
+ return Convert.ToByte(m_value);
+ }
+
+ /// <internalonly/>
+ short IConvertible.ToInt16(IFormatProvider provider) {
+ return Convert.ToInt16(m_value);
+ }
+
+ /// <internalonly/>
+ ushort IConvertible.ToUInt16(IFormatProvider provider) {
+ return Convert.ToUInt16(m_value);
+ }
+
+ /// <internalonly/>
+ int IConvertible.ToInt32(IFormatProvider provider) {
+ return Convert.ToInt32(m_value);
+ }
+
+ /// <internalonly/>
+ uint IConvertible.ToUInt32(IFormatProvider provider) {
+ return Convert.ToUInt32(m_value);
+ }
+
+ /// <internalonly/>
+ long IConvertible.ToInt64(IFormatProvider provider) {
+ return Convert.ToInt64(m_value);
+ }
+
+ /// <internalonly/>
+ ulong IConvertible.ToUInt64(IFormatProvider provider) {
+ return m_value;
+ }
+
+ /// <internalonly/>
+ float IConvertible.ToSingle(IFormatProvider provider) {
+ return Convert.ToSingle(m_value);
+ }
+
+ /// <internalonly/>
+ double IConvertible.ToDouble(IFormatProvider provider) {
+ return Convert.ToDouble(m_value);
+ }
+
+ /// <internalonly/>
+ Decimal IConvertible.ToDecimal(IFormatProvider provider) {
+ return Convert.ToDecimal(m_value);
+ }
+
+ /// <internalonly/>
+ DateTime IConvertible.ToDateTime(IFormatProvider provider) {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "UInt64", "DateTime"));
+ }
+
+ /// <internalonly/>
+ Object IConvertible.ToType(Type type, IFormatProvider provider) {
+ return Convert.DefaultToType((IConvertible)this, type, provider);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UIntPtr.cs b/src/mscorlib/src/System/UIntPtr.cs
new file mode 100644
index 0000000000..ac3b811b42
--- /dev/null
+++ b/src/mscorlib/src/System/UIntPtr.cs
@@ -0,0 +1,249 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Platform independent integer
+**
+**
+===========================================================*/
+
+namespace System {
+
+ using System;
+ using System.Globalization;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [CLSCompliant(false)]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct UIntPtr : IEquatable<UIntPtr>, ISerializable
+ {
+ [SecurityCritical]
+ unsafe private void* m_value;
+
+ public static readonly UIntPtr Zero;
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe UIntPtr(uint value)
+ {
+ m_value = (void *)value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe UIntPtr(ulong value)
+ {
+#if BIT64
+ m_value = (void *)value;
+#else // 32
+ m_value = (void*)checked((uint)value);
+#endif
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe UIntPtr(void* value)
+ {
+ m_value = value;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ private unsafe UIntPtr(SerializationInfo info, StreamingContext context) {
+ ulong l = info.GetUInt64("value");
+
+ if (Size==4 && l>UInt32.MaxValue) {
+ throw new ArgumentException(Environment.GetResourceString("Serialization_InvalidPtrValue"));
+ }
+
+ m_value = (void *)l;
+ }
+
+ [System.Security.SecurityCritical]
+ unsafe void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ info.AddValue("value", (ulong)m_value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override bool Equals(Object obj) {
+ if (obj is UIntPtr) {
+ return (m_value == ((UIntPtr)obj).m_value);
+ }
+ return false;
+ }
+
+ [SecuritySafeCritical]
+ unsafe bool IEquatable<UIntPtr>.Equals(UIntPtr other)
+ {
+ return m_value == other.m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override int GetHashCode() {
+#if FEATURE_CORECLR
+#if BIT64
+ ulong l = (ulong)m_value;
+ return (unchecked((int)l) ^ (int)(l >> 32));
+#else // 32
+ return unchecked((int)m_value);
+#endif
+#else
+ return unchecked((int)((long)m_value)) & 0x7fffffff;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe uint ToUInt32() {
+#if BIT64
+ return checked((uint)m_value);
+#else // 32
+ return (uint)m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe ulong ToUInt64() {
+ return (ulong)m_value;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public unsafe override String ToString() {
+ Contract.Ensures(Contract.Result<String>() != null);
+
+#if BIT64
+ return ((ulong)m_value).ToString(CultureInfo.InvariantCulture);
+#else // 32
+ return ((uint)m_value).ToString(CultureInfo.InvariantCulture);
+#endif
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static explicit operator UIntPtr (uint value)
+ {
+ return new UIntPtr(value);
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static explicit operator UIntPtr (ulong value)
+ {
+ return new UIntPtr(value);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static explicit operator uint(UIntPtr value)
+ {
+#if BIT64
+ return checked((uint)value.m_value);
+#else // 32
+ return (uint)value.m_value;
+#endif
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static explicit operator ulong (UIntPtr value)
+ {
+ return (ulong)value.m_value;
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static unsafe explicit operator UIntPtr (void* value)
+ {
+ return new UIntPtr(value);
+ }
+
+ [System.Security.SecurityCritical]
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public static unsafe explicit operator void* (UIntPtr value)
+ {
+ return value.m_value;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool operator == (UIntPtr value1, UIntPtr value2)
+ {
+ return value1.m_value == value2.m_value;
+ }
+
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe static bool operator != (UIntPtr value1, UIntPtr value2)
+ {
+ return value1.m_value != value2.m_value;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static UIntPtr Add(UIntPtr pointer, int offset) {
+ return pointer + offset;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static UIntPtr operator +(UIntPtr pointer, int offset) {
+#if BIT64
+ return new UIntPtr(pointer.ToUInt64() + (ulong)offset);
+#else // 32
+ return new UIntPtr(pointer.ToUInt32() + (uint)offset);
+#endif
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static UIntPtr Subtract(UIntPtr pointer, int offset) {
+ return pointer - offset;
+ }
+
+ [System.Runtime.Versioning.NonVersionable]
+ public static UIntPtr operator -(UIntPtr pointer, int offset) {
+#if BIT64
+ return new UIntPtr(pointer.ToUInt64() - (ulong)offset);
+#else // 32
+ return new UIntPtr(pointer.ToUInt32() - (uint)offset);
+#endif
+ }
+
+ public static int Size
+ {
+ [System.Runtime.Versioning.NonVersionable]
+ get
+ {
+#if BIT64
+ return 8;
+#else // 32
+ return 4;
+#endif
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [CLSCompliant(false)]
+ [System.Runtime.Versioning.NonVersionable]
+ public unsafe void* ToPointer()
+ {
+ return m_value;
+ }
+
+ }
+}
+
+
diff --git a/src/mscorlib/src/System/UnSafeCharBuffer.cs b/src/mscorlib/src/System/UnSafeCharBuffer.cs
new file mode 100644
index 0000000000..78059b623a
--- /dev/null
+++ b/src/mscorlib/src/System/UnSafeCharBuffer.cs
@@ -0,0 +1,57 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: A class to detect incorrect usage of UnSafeBuffer
+**
+**
+===========================================================*/
+
+namespace System {
+ using System.Security;
+ using System.Diagnostics;
+ using System.Diagnostics.Contracts;
+
+ unsafe internal struct UnSafeCharBuffer{
+ [SecurityCritical]
+ char * m_buffer;
+ int m_totalSize;
+ int m_length;
+
+ [System.Security.SecurityCritical] // auto-generated
+ public UnSafeCharBuffer( char *buffer, int bufferSize) {
+ Contract.Assert( buffer != null, "buffer pointer can't be null." );
+ Contract.Assert( bufferSize >= 0, "buffer size can't be negative." );
+ m_buffer = buffer;
+ m_totalSize = bufferSize;
+ m_length = 0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void AppendString(string stringToAppend) {
+ if( String.IsNullOrEmpty( stringToAppend ) ) {
+ return;
+ }
+
+ if ( (m_totalSize - m_length) < stringToAppend.Length ) {
+ throw new IndexOutOfRangeException();
+ }
+
+ fixed( char* pointerToString = stringToAppend ) {
+ Buffer.Memcpy( (byte*) (m_buffer + m_length), (byte *) pointerToString, stringToAppend.Length * sizeof(char));
+ }
+
+ m_length += stringToAppend.Length;
+ Contract.Assert(m_length <= m_totalSize, "Buffer has been overflowed!");
+ }
+
+ public int Length {
+ get {
+ return m_length;
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UnauthorizedAccessException.cs b/src/mscorlib/src/System/UnauthorizedAccessException.cs
new file mode 100644
index 0000000000..07e95d547c
--- /dev/null
+++ b/src/mscorlib/src/System/UnauthorizedAccessException.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: An exception for OS 'access denied' types of
+** errors, including IO and limited security types
+** of errors.
+**
+**
+===========================================================*/
+
+using System;
+using System.Runtime.Serialization;
+
+namespace System {
+ // The UnauthorizedAccessException is thrown when access errors
+ // occur from IO or other OS methods.
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public class UnauthorizedAccessException : SystemException {
+ public UnauthorizedAccessException()
+ : base(Environment.GetResourceString("Arg_UnauthorizedAccessException")) {
+ SetErrorCode(__HResults.COR_E_UNAUTHORIZEDACCESS);
+ }
+
+ public UnauthorizedAccessException(String message)
+ : base(message) {
+ SetErrorCode(__HResults.COR_E_UNAUTHORIZEDACCESS);
+ }
+
+ public UnauthorizedAccessException(String message, Exception inner)
+ : base(message, inner) {
+ SetErrorCode(__HResults.COR_E_UNAUTHORIZEDACCESS);
+ }
+
+ protected UnauthorizedAccessException(SerializationInfo info, StreamingContext context) : base(info, context) {
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UnhandledExceptionEventArgs.cs b/src/mscorlib/src/System/UnhandledExceptionEventArgs.cs
new file mode 100644
index 0000000000..e155ffc68e
--- /dev/null
+++ b/src/mscorlib/src/System/UnhandledExceptionEventArgs.cs
@@ -0,0 +1,29 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+ using System.Runtime.ConstrainedExecution;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public class UnhandledExceptionEventArgs : EventArgs {
+ private Object _Exception;
+ private bool _IsTerminating;
+
+ public UnhandledExceptionEventArgs(Object exception, bool isTerminating) {
+ _Exception = exception;
+ _IsTerminating = isTerminating;
+ }
+ public Object ExceptionObject {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return _Exception; }
+ }
+ public bool IsTerminating {
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ get { return _IsTerminating; }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs b/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs
new file mode 100644
index 0000000000..7d6531945e
--- /dev/null
+++ b/src/mscorlib/src/System/UnhandledExceptionEventHandler.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System {
+
+ using System;
+#if FEATURE_CORECLR
+ [System.Security.SecurityCritical] // auto-generated
+#endif
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public delegate void UnhandledExceptionEventHandler(Object sender, UnhandledExceptionEventArgs e);
+}
diff --git a/src/mscorlib/src/System/UnitySerializationHolder.cs b/src/mscorlib/src/System/UnitySerializationHolder.cs
new file mode 100644
index 0000000000..ec32fce348
--- /dev/null
+++ b/src/mscorlib/src/System/UnitySerializationHolder.cs
@@ -0,0 +1,359 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Runtime.Remoting;
+using System.Runtime.Serialization;
+using System.Reflection;
+using System.Globalization;
+using System.Runtime.Versioning;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace System {
+
+ [Serializable]
+ // Holds classes (Empty, Null, Missing) for which we guarantee that there is only ever one instance of.
+ internal class UnitySerializationHolder : ISerializable, IObjectReference
+ {
+ #region Internal Constants
+ internal const int EmptyUnity = 0x0001;
+ internal const int NullUnity = 0x0002;
+ internal const int MissingUnity = 0x0003;
+ internal const int RuntimeTypeUnity = 0x0004;
+ internal const int ModuleUnity = 0x0005;
+ internal const int AssemblyUnity = 0x0006;
+ internal const int GenericParameterTypeUnity = 0x0007;
+ internal const int PartialInstantiationTypeUnity = 0x0008;
+
+ internal const int Pointer = 0x0001;
+ internal const int Array = 0x0002;
+ internal const int SzArray = 0x0003;
+ internal const int ByRef = 0x0004;
+ #endregion
+
+ #region Internal Static Members
+ internal static void GetUnitySerializationInfo(SerializationInfo info, Missing missing)
+ {
+ info.SetType(typeof(UnitySerializationHolder));
+ info.AddValue("UnityType", MissingUnity);
+ }
+
+ internal static RuntimeType AddElementTypes(SerializationInfo info, RuntimeType type)
+ {
+ List<int> elementTypes = new List<int>();
+ while(type.HasElementType)
+ {
+ if (type.IsSzArray)
+ {
+ elementTypes.Add(SzArray);
+ }
+ else if (type.IsArray)
+ {
+ elementTypes.Add(type.GetArrayRank());
+ elementTypes.Add(Array);
+ }
+ else if (type.IsPointer)
+ {
+ elementTypes.Add(Pointer);
+ }
+ else if (type.IsByRef)
+ {
+ elementTypes.Add(ByRef);
+ }
+
+ type = (RuntimeType)type.GetElementType();
+ }
+
+ info.AddValue("ElementTypes", elementTypes.ToArray(), typeof(int[]));
+
+ return type;
+ }
+
+ internal Type MakeElementTypes(Type type)
+ {
+ for (int i = m_elementTypes.Length - 1; i >= 0; i --)
+ {
+ if (m_elementTypes[i] == SzArray)
+ {
+ type = type.MakeArrayType();
+ }
+ else if (m_elementTypes[i] == Array)
+ {
+ type = type.MakeArrayType(m_elementTypes[--i]);
+ }
+ else if ((m_elementTypes[i] == Pointer))
+ {
+ type = type.MakePointerType();
+ }
+ else if ((m_elementTypes[i] == ByRef))
+ {
+ type = type.MakeByRefType();
+ }
+ }
+
+ return type;
+ }
+
+ internal static void GetUnitySerializationInfo(SerializationInfo info, RuntimeType type)
+ {
+ if (type.GetRootElementType().IsGenericParameter)
+ {
+ type = AddElementTypes(info, type);
+ info.SetType(typeof(UnitySerializationHolder));
+ info.AddValue("UnityType", GenericParameterTypeUnity);
+ info.AddValue("GenericParameterPosition", type.GenericParameterPosition);
+ info.AddValue("DeclaringMethod", type.DeclaringMethod, typeof(MethodBase));
+ info.AddValue("DeclaringType", type.DeclaringType, typeof(Type));
+
+ return;
+ }
+
+ int unityType = RuntimeTypeUnity;
+
+ if (!type.IsGenericTypeDefinition && type.ContainsGenericParameters)
+ {
+ // Partial instantiation
+ unityType = PartialInstantiationTypeUnity;
+ type = AddElementTypes(info, type);
+ info.AddValue("GenericArguments", type.GetGenericArguments(), typeof(Type[]));
+ type = (RuntimeType)type.GetGenericTypeDefinition();
+ }
+
+ GetUnitySerializationInfo(info, unityType, type.FullName, type.GetRuntimeAssembly());
+ }
+
+ internal static void GetUnitySerializationInfo(
+ SerializationInfo info, int unityType, String data, RuntimeAssembly assembly)
+ {
+ // A helper method that returns the SerializationInfo that a class utilizing
+ // UnitySerializationHelper should return from a call to GetObjectData. It contains
+ // the unityType (defined above) and any optional data (used only for the reflection
+ // types.)
+
+ info.SetType(typeof(UnitySerializationHolder));
+ info.AddValue("Data", data, typeof(String));
+ info.AddValue("UnityType", unityType);
+
+ String assemName;
+
+ if (assembly == null)
+ {
+ assemName = String.Empty;
+ }
+ else
+ {
+ assemName = assembly.FullName;
+ }
+
+ info.AddValue("AssemblyName", assemName);
+ }
+ #endregion
+
+ #region Private Data Members
+ private Type[] m_instantiation;
+ private int[] m_elementTypes;
+ private int m_genericParameterPosition;
+ private Type m_declaringType;
+ private MethodBase m_declaringMethod;
+ private String m_data;
+ private String m_assemblyName;
+ private int m_unityType;
+ #endregion
+
+ #region Constructor
+ internal UnitySerializationHolder(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null)
+ throw new ArgumentNullException("info");
+ Contract.EndContractBlock();
+
+ m_unityType = info.GetInt32("UnityType");
+
+ if (m_unityType == MissingUnity)
+ return;
+
+ if (m_unityType == GenericParameterTypeUnity)
+ {
+ m_declaringMethod = info.GetValue("DeclaringMethod", typeof(MethodBase)) as MethodBase;
+ m_declaringType = info.GetValue("DeclaringType", typeof(Type)) as Type;
+ m_genericParameterPosition = info.GetInt32("GenericParameterPosition");
+ m_elementTypes = info.GetValue("ElementTypes", typeof(int[])) as int[];
+
+ return;
+ }
+
+ if (m_unityType == PartialInstantiationTypeUnity)
+ {
+ m_instantiation = info.GetValue("GenericArguments", typeof(Type[])) as Type[];
+ m_elementTypes = info.GetValue("ElementTypes", typeof(int[])) as int[];
+ }
+
+ m_data = info.GetString("Data");
+ m_assemblyName = info.GetString("AssemblyName");
+ }
+ #endregion
+
+ #region Private Methods
+ private void ThrowInsufficientInformation(string field)
+ {
+ throw new SerializationException(
+ Environment.GetResourceString("Serialization_InsufficientDeserializationState", field));
+ }
+ #endregion
+
+ #region ISerializable
+ [System.Security.SecurityCritical] // auto-generated
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnitySerHolder"));
+ }
+ #endregion
+
+ #region IObjectReference
+ [System.Security.SecurityCritical] // auto-generated
+ public virtual Object GetRealObject(StreamingContext context)
+ {
+ // GetRealObject uses the data we have in m_data and m_unityType to do a lookup on the correct
+ // object to return. We have specific code here to handle the different types which we support.
+ // The reflection types (Assembly, Module, and Type) have to be looked up through their static
+ // accessors by name.
+
+ Assembly assembly;
+
+ switch (m_unityType)
+ {
+ case EmptyUnity:
+ {
+ return Empty.Value;
+ }
+
+ case NullUnity:
+ {
+ return DBNull.Value;
+ }
+
+ case MissingUnity:
+ {
+ return Missing.Value;
+ }
+
+ case PartialInstantiationTypeUnity:
+ {
+ m_unityType = RuntimeTypeUnity;
+ Type definition = GetRealObject(context) as Type;
+ m_unityType = PartialInstantiationTypeUnity;
+
+ if (m_instantiation[0] == null)
+ return null;
+
+ return MakeElementTypes(definition.MakeGenericType(m_instantiation));
+ }
+
+ case GenericParameterTypeUnity:
+ {
+ if (m_declaringMethod == null && m_declaringType == null)
+ ThrowInsufficientInformation("DeclaringMember");
+
+ if (m_declaringMethod != null)
+ return m_declaringMethod.GetGenericArguments()[m_genericParameterPosition];
+
+ return MakeElementTypes(m_declaringType.GetGenericArguments()[m_genericParameterPosition]);
+ }
+
+ case RuntimeTypeUnity:
+ {
+ if (m_data == null || m_data.Length == 0)
+ ThrowInsufficientInformation("Data");
+
+ if (m_assemblyName == null)
+ ThrowInsufficientInformation("AssemblyName");
+
+ if (m_assemblyName.Length == 0)
+ return Type.GetType(m_data, true, false);
+
+ assembly = Assembly.Load(m_assemblyName);
+
+ Type t = assembly.GetType(m_data, true, false);
+
+ return t;
+ }
+
+ case ModuleUnity:
+ {
+ if (m_data == null || m_data.Length == 0)
+ ThrowInsufficientInformation("Data");
+
+ if (m_assemblyName == null)
+ ThrowInsufficientInformation("AssemblyName");
+
+ assembly = Assembly.Load(m_assemblyName);
+
+ Module namedModule = assembly.GetModule(m_data);
+
+ if (namedModule == null)
+ throw new SerializationException(
+ Environment.GetResourceString("Serialization_UnableToFindModule", m_data, m_assemblyName));
+
+ return namedModule;
+ }
+
+ case AssemblyUnity:
+ {
+ if (m_data == null || m_data.Length == 0)
+ ThrowInsufficientInformation("Data");
+
+ if (m_assemblyName == null)
+ ThrowInsufficientInformation("AssemblyName");
+
+ assembly = Assembly.Load(m_assemblyName);
+
+ return assembly;
+ }
+
+ default:
+ throw new ArgumentException(Environment.GetResourceString("Argument_InvalidUnity"));
+ }
+ }
+ #endregion
+ }
+
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mscorlib/src/System/ValueType.cs b/src/mscorlib/src/System/ValueType.cs
new file mode 100644
index 0000000000..ae08b7d0ba
--- /dev/null
+++ b/src/mscorlib/src/System/ValueType.cs
@@ -0,0 +1,93 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: Base class for all value classes.
+**
+**
+===========================================================*/
+namespace System {
+ using System;
+ using System.Reflection;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public abstract class ValueType {
+
+ [System.Security.SecuritySafeCritical]
+ public override bool Equals (Object obj) {
+ BCLDebug.Perf(false, "ValueType::Equals is not fast. "+this.GetType().FullName+" should override Equals(Object)");
+ if (null==obj) {
+ return false;
+ }
+ RuntimeType thisType = (RuntimeType)this.GetType();
+ RuntimeType thatType = (RuntimeType)obj.GetType();
+
+ if (thatType!=thisType) {
+ return false;
+ }
+
+ Object thisObj = (Object)this;
+ Object thisResult, thatResult;
+
+ // if there are no GC references in this object we can avoid reflection
+ // and do a fast memcmp
+ if (CanCompareBits(this))
+ return FastEqualsCheck(thisObj, obj);
+
+ FieldInfo[] thisFields = thisType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+
+ for (int i=0; i<thisFields.Length; i++) {
+ thisResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(thisObj);
+ thatResult = ((RtFieldInfo)thisFields[i]).UnsafeGetValue(obj);
+
+ if (thisResult == null) {
+ if (thatResult != null)
+ return false;
+ }
+ else
+ if (!thisResult.Equals(thatResult)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool CanCompareBits(Object obj);
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern bool FastEqualsCheck(Object a, Object b);
+
+ /*=================================GetHashCode==================================
+ **Action: Our algorithm for returning the hashcode is a little bit complex. We look
+ ** for the first non-static field and get it's hashcode. If the type has no
+ ** non-static fields, we return the hashcode of the type. We can't take the
+ ** hashcode of a static member because if that member is of the same type as
+ ** the original type, we'll end up in an infinite loop.
+ **Returns: The hashcode for the type.
+ **Arguments: None.
+ **Exceptions: None.
+ ==============================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ public extern override int GetHashCode();
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern int GetHashCodeOfPtr(IntPtr ptr);
+
+ public override String ToString()
+ {
+ return this.GetType().ToString();
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Variant.cs b/src/mscorlib/src/System/Variant.cs
new file mode 100644
index 0000000000..26e2e4aa1a
--- /dev/null
+++ b/src/mscorlib/src/System/Variant.cs
@@ -0,0 +1,681 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose: The CLR implementation of Variant.
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Reflection;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Globalization;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct Variant {
+
+ //Do Not change the order of these fields.
+ //They are mapped to the native VariantData * data structure.
+ private Object m_objref;
+ private int m_data1;
+ private int m_data2;
+ private int m_flags;
+
+ // The following bits have been taken up as follows
+ // bits 0-15 - Type code
+ // bit 16 - Array
+ // bits 19-23 - Enums
+ // bits 24-31 - Optional VT code (for roundtrip VT preservation)
+
+
+ //What are the consequences of making this an enum?
+ ///////////////////////////////////////////////////////////////////////
+ // If you update this, update the corresponding stuff in OAVariantLib.cs,
+ // COMOAVariant.cpp (2 tables, forwards and reverse), and perhaps OleVariant.h
+ ///////////////////////////////////////////////////////////////////////
+ internal const int CV_EMPTY=0x0;
+ internal const int CV_VOID=0x1;
+ internal const int CV_BOOLEAN=0x2;
+ internal const int CV_CHAR=0x3;
+ internal const int CV_I1=0x4;
+ internal const int CV_U1=0x5;
+ internal const int CV_I2=0x6;
+ internal const int CV_U2=0x7;
+ internal const int CV_I4=0x8;
+ internal const int CV_U4=0x9;
+ internal const int CV_I8=0xa;
+ internal const int CV_U8=0xb;
+ internal const int CV_R4=0xc;
+ internal const int CV_R8=0xd;
+ internal const int CV_STRING=0xe;
+ internal const int CV_PTR=0xf;
+ internal const int CV_DATETIME = 0x10;
+ internal const int CV_TIMESPAN = 0x11;
+ internal const int CV_OBJECT=0x12;
+ internal const int CV_DECIMAL = 0x13;
+ internal const int CV_ENUM=0x15;
+ internal const int CV_MISSING=0x16;
+ internal const int CV_NULL=0x17;
+ internal const int CV_LAST=0x18;
+
+ internal const int TypeCodeBitMask=0xffff;
+ internal const int VTBitMask=unchecked((int)0xff000000);
+ internal const int VTBitShift=24;
+ internal const int ArrayBitMask =0x10000;
+
+ // Enum enum and Mask
+ internal const int EnumI1 =0x100000;
+ internal const int EnumU1 =0x200000;
+ internal const int EnumI2 =0x300000;
+ internal const int EnumU2 =0x400000;
+ internal const int EnumI4 =0x500000;
+ internal const int EnumU4 =0x600000;
+ internal const int EnumI8 =0x700000;
+ internal const int EnumU8 =0x800000;
+ internal const int EnumMask =0xF00000;
+
+ internal static readonly Type [] ClassTypes = {
+ typeof(System.Empty),
+ typeof(void),
+ typeof(Boolean),
+ typeof(Char),
+ typeof(SByte),
+ typeof(Byte),
+ typeof(Int16),
+ typeof(UInt16),
+ typeof(Int32),
+ typeof(UInt32),
+ typeof(Int64),
+ typeof(UInt64),
+ typeof(Single),
+ typeof(Double),
+ typeof(String),
+ typeof(void), // ptr for the moment
+ typeof(DateTime),
+ typeof(TimeSpan),
+ typeof(Object),
+ typeof(Decimal),
+ typeof(Object), // Treat enum as Object
+ typeof(System.Reflection.Missing),
+ typeof(System.DBNull),
+ };
+
+ internal static readonly Variant Empty = new Variant();
+ internal static readonly Variant Missing = new Variant(Variant.CV_MISSING, Type.Missing, 0, 0);
+ internal static readonly Variant DBNull = new Variant(Variant.CV_NULL, System.DBNull.Value, 0, 0);
+
+ //
+ // Native Methods
+ //
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern double GetR8FromVar();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern float GetR4FromVar();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void SetFieldsR4(float val);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void SetFieldsR8(double val);
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal extern void SetFieldsObject(Object val);
+
+ // Use this function instead of an ECALL - saves about 150 clock cycles
+ // by avoiding the ecall transition and because the JIT inlines this.
+ // Ends up only taking about 1/8 the time of the ECALL version.
+ internal long GetI8FromVar()
+ {
+ return ((long)m_data2<<32 | ((long)m_data1 & 0xFFFFFFFFL));
+ }
+
+ //
+ // Constructors
+ //
+
+ internal Variant(int flags, Object or, int data1, int data2) {
+ m_flags = flags;
+ m_objref=or;
+ m_data1=data1;
+ m_data2=data2;
+ }
+
+ public Variant(bool val) {
+ m_objref= null;
+ m_flags = CV_BOOLEAN;
+ m_data1 = (val)?Boolean.True:Boolean.False;
+ m_data2 = 0;
+ }
+
+ public Variant(sbyte val) {
+ m_objref=null;
+ m_flags=CV_I1;
+ m_data1=(int)val;
+ m_data2=(int)(((long)val)>>32);
+ }
+
+
+ public Variant(byte val) {
+ m_objref=null;
+ m_flags=CV_U1;
+ m_data1=(int)val;
+ m_data2=0;
+ }
+
+ public Variant(short val) {
+ m_objref=null;
+ m_flags=CV_I2;
+ m_data1=(int)val;
+ m_data2=(int)(((long)val)>>32);
+ }
+
+ public Variant(ushort val) {
+ m_objref=null;
+ m_flags=CV_U2;
+ m_data1=(int)val;
+ m_data2=0;
+ }
+
+ public Variant(char val) {
+ m_objref=null;
+ m_flags=CV_CHAR;
+ m_data1=(int)val;
+ m_data2=0;
+ }
+
+ public Variant(int val) {
+ m_objref=null;
+ m_flags=CV_I4;
+ m_data1=val;
+ m_data2=val >> 31;
+ }
+
+ public Variant(uint val) {
+ m_objref=null;
+ m_flags=CV_U4;
+ m_data1=(int)val;
+ m_data2=0;
+ }
+
+ public Variant(long val) {
+ m_objref=null;
+ m_flags=CV_I8;
+ m_data1 = (int)val;
+ m_data2 = (int)(val >> 32);
+ }
+
+ public Variant(ulong val) {
+ m_objref=null;
+ m_flags=CV_U8;
+ m_data1 = (int)val;
+ m_data2 = (int)(val >> 32);
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Variant(float val) {
+ m_objref=null;
+ m_flags=CV_R4;
+ m_data1=0;
+ m_data2=0;
+ SetFieldsR4(val);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ public Variant(double val) {
+ m_objref=null;
+ m_flags=CV_R8;
+ m_data1=0;
+ m_data2=0;
+ SetFieldsR8(val);
+ }
+
+ public Variant(DateTime val) {
+ m_objref=null;
+ m_flags=CV_DATETIME;
+ ulong ticks = (ulong)val.Ticks;
+ m_data1 = (int)ticks;
+ m_data2 = (int)(ticks>>32);
+ }
+
+ public Variant(Decimal val) {
+ m_objref = (Object)val;
+ m_flags = CV_DECIMAL;
+ m_data1=0;
+ m_data2=0;
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Variant(Object obj) {
+ m_data1=0;
+ m_data2=0;
+
+ VarEnum vt = VarEnum.VT_EMPTY;
+
+ if (obj is DateTime) {
+ m_objref=null;
+ m_flags=CV_DATETIME;
+ ulong ticks = (ulong)((DateTime)obj).Ticks;
+ m_data1 = (int)ticks;
+ m_data2 = (int)(ticks>>32);
+ return;
+ }
+
+ if (obj is String) {
+ m_flags=CV_STRING;
+ m_objref=obj;
+ return;
+ }
+
+ if (obj == null) {
+ this = Empty;
+ return;
+ }
+ if (obj == System.DBNull.Value) {
+ this = DBNull;
+ return;
+ }
+ if (obj == Type.Missing) {
+ this = Missing;
+ return;
+ }
+
+ if (obj is Array) {
+ m_flags=CV_OBJECT | ArrayBitMask;
+ m_objref=obj;
+ return;
+ }
+
+ // Compiler appeasement
+ m_flags = CV_EMPTY;
+ m_objref = null;
+
+ // Check to see if the object passed in is a wrapper object.
+ if (obj is UnknownWrapper)
+ {
+ vt = VarEnum.VT_UNKNOWN;
+ obj = ((UnknownWrapper)obj).WrappedObject;
+ }
+ else if (obj is DispatchWrapper)
+ {
+ vt = VarEnum.VT_DISPATCH;
+ obj = ((DispatchWrapper)obj).WrappedObject;
+ }
+ else if (obj is ErrorWrapper)
+ {
+ vt = VarEnum.VT_ERROR;
+ obj = (Object)(((ErrorWrapper)obj).ErrorCode);
+ Contract.Assert(obj != null, "obj != null");
+ }
+ else if (obj is CurrencyWrapper)
+ {
+ vt = VarEnum.VT_CY;
+ obj = (Object)(((CurrencyWrapper)obj).WrappedObject);
+ Contract.Assert(obj != null, "obj != null");
+ }
+ else if (obj is BStrWrapper)
+ {
+ vt = VarEnum.VT_BSTR;
+ obj = (Object)(((BStrWrapper)obj).WrappedObject);
+ }
+
+ if (obj != null)
+ {
+ SetFieldsObject(obj);
+ }
+
+ // If the object passed in is one of the wrappers then set the VARIANT type.
+ if (vt != VarEnum.VT_EMPTY)
+ m_flags |= ((int)vt << VTBitShift);
+ }
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ unsafe public Variant(void* voidPointer,Type pointerType) {
+ if (pointerType == null)
+ throw new ArgumentNullException("pointerType");
+ if (!pointerType.IsPointer)
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBePointer"),"pointerType");
+ Contract.EndContractBlock();
+
+ m_objref = pointerType;
+ m_flags=CV_PTR;
+ m_data1=(int)voidPointer;
+ m_data2=0;
+
+ }
+
+ //This is a family-only accessor for the CVType.
+ //This is never to be exposed externally.
+ internal int CVType {
+ get {
+ return (m_flags&TypeCodeBitMask);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public Object ToObject() {
+ switch (CVType) {
+ case CV_EMPTY:
+ return null;
+ case CV_BOOLEAN:
+ return (Object)(m_data1!=0);
+ case CV_I1:
+ return (Object)((sbyte)m_data1);
+ case CV_U1:
+ return (Object)((byte)m_data1);
+ case CV_CHAR:
+ return (Object)((char)m_data1);
+ case CV_I2:
+ return (Object)((short)m_data1);
+ case CV_U2:
+ return (Object)((ushort)m_data1);
+ case CV_I4:
+ return (Object)(m_data1);
+ case CV_U4:
+ return (Object)((uint)m_data1);
+ case CV_I8:
+ return (Object)(GetI8FromVar());
+ case CV_U8:
+ return (Object)((ulong)GetI8FromVar());
+ case CV_R4:
+ return (Object)(GetR4FromVar());
+ case CV_R8:
+ return (Object)(GetR8FromVar());
+ case CV_DATETIME:
+ return new DateTime(GetI8FromVar());
+ case CV_TIMESPAN:
+ return new TimeSpan(GetI8FromVar());
+ case CV_ENUM:
+ return BoxEnum();
+ case CV_MISSING:
+ return Type.Missing;
+ case CV_NULL:
+ return System.DBNull.Value;
+ case CV_DECIMAL:
+ case CV_STRING:
+ case CV_OBJECT:
+ default:
+ return m_objref;
+ }
+ }
+
+ // This routine will return an boxed enum.
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private extern Object BoxEnum();
+
+
+ // Helper code for marshaling managed objects to VARIANT's (we use
+ // managed variants as an intermediate type.
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void MarshalHelperConvertObjectToVariant(Object o, ref Variant v)
+ {
+#if FEATURE_REMOTING
+ IConvertible ic = System.Runtime.Remoting.RemotingServices.IsTransparentProxy(o) ? null : o as IConvertible;
+#else
+ IConvertible ic = o as IConvertible;
+#endif
+ if (o == null)
+ {
+ v = Empty;
+ }
+ else if (ic == null)
+ {
+ // This path should eventually go away. But until
+ // the work is done to have all of our wrapper types implement
+ // IConvertible, this is a cheapo way to get the work done.
+ v = new Variant(o);
+ }
+ else
+ {
+ IFormatProvider provider = CultureInfo.InvariantCulture;
+ switch (ic.GetTypeCode())
+ {
+ case TypeCode.Empty:
+ v = Empty;
+ break;
+
+ case TypeCode.Object:
+ v = new Variant((Object)o);
+ break;
+
+ case TypeCode.DBNull:
+ v = DBNull;
+ break;
+
+ case TypeCode.Boolean:
+ v = new Variant(ic.ToBoolean(provider));
+ break;
+
+ case TypeCode.Char:
+ v = new Variant(ic.ToChar(provider));
+ break;
+
+ case TypeCode.SByte:
+ v = new Variant(ic.ToSByte(provider));
+ break;
+
+ case TypeCode.Byte:
+ v = new Variant(ic.ToByte(provider));
+ break;
+
+ case TypeCode.Int16:
+ v = new Variant(ic.ToInt16(provider));
+ break;
+
+ case TypeCode.UInt16:
+ v = new Variant(ic.ToUInt16(provider));
+ break;
+
+ case TypeCode.Int32:
+ v = new Variant(ic.ToInt32(provider));
+ break;
+
+ case TypeCode.UInt32:
+ v = new Variant(ic.ToUInt32(provider));
+ break;
+
+ case TypeCode.Int64:
+ v = new Variant(ic.ToInt64(provider));
+ break;
+
+ case TypeCode.UInt64:
+ v = new Variant(ic.ToUInt64(provider));
+ break;
+
+ case TypeCode.Single:
+ v = new Variant(ic.ToSingle(provider));
+ break;
+
+ case TypeCode.Double:
+ v = new Variant(ic.ToDouble(provider));
+ break;
+
+ case TypeCode.Decimal:
+ v = new Variant(ic.ToDecimal(provider));
+ break;
+
+ case TypeCode.DateTime:
+ v = new Variant(ic.ToDateTime(provider));
+ break;
+
+ case TypeCode.String:
+ v = new Variant(ic.ToString(provider));
+ break;
+
+ default:
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_UnknownTypeCode", ic.GetTypeCode()));
+ }
+ }
+ }
+
+ // Helper code for marshaling VARIANTS to managed objects (we use
+ // managed variants as an intermediate type.
+ internal static Object MarshalHelperConvertVariantToObject(ref Variant v)
+ {
+ return v.ToObject();
+ }
+
+ // Helper code: on the back propagation path where a VT_BYREF VARIANT*
+ // is marshaled to a "ref Object", we use this helper to force the
+ // updated object back to the original type.
+ [System.Security.SecurityCritical] // auto-generated
+ internal static void MarshalHelperCastVariant(Object pValue, int vt, ref Variant v)
+ {
+ IConvertible iv = pValue as IConvertible;
+ if (iv == null)
+ {
+ switch (vt)
+ {
+ case 9: /*VT_DISPATCH*/
+ v = new Variant(new DispatchWrapper(pValue));
+ break;
+
+ case 12: /*VT_VARIANT*/
+ v = new Variant(pValue);
+ break;
+
+ case 13: /*VT_UNKNOWN*/
+ v = new Variant(new UnknownWrapper(pValue));
+ break;
+
+ case 36: /*VT_RECORD*/
+ v = new Variant(pValue);
+ break;
+
+ case 8: /*VT_BSTR*/
+ if (pValue == null)
+ {
+ v = new Variant(null);
+ v.m_flags = CV_STRING;
+ }
+ else
+ {
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant"));
+ }
+ break;
+
+ default:
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant"));
+ }
+ }
+ else
+ {
+ IFormatProvider provider = CultureInfo.InvariantCulture;
+ switch (vt)
+ {
+ case 0: /*VT_EMPTY*/
+ v = Empty;
+ break;
+
+ case 1: /*VT_NULL*/
+ v = DBNull;
+ break;
+
+ case 2: /*VT_I2*/
+ v = new Variant(iv.ToInt16(provider));
+ break;
+
+ case 3: /*VT_I4*/
+ v = new Variant(iv.ToInt32(provider));
+ break;
+
+ case 4: /*VT_R4*/
+ v = new Variant(iv.ToSingle(provider));
+ break;
+
+ case 5: /*VT_R8*/
+ v = new Variant(iv.ToDouble(provider));
+ break;
+
+ case 6: /*VT_CY*/
+ v = new Variant(new CurrencyWrapper(iv.ToDecimal(provider)));
+ break;
+
+ case 7: /*VT_DATE*/
+ v = new Variant(iv.ToDateTime(provider));
+ break;
+
+ case 8: /*VT_BSTR*/
+ v = new Variant(iv.ToString(provider));
+ break;
+
+ case 9: /*VT_DISPATCH*/
+ v = new Variant(new DispatchWrapper((Object)iv));
+ break;
+
+ case 10: /*VT_ERROR*/
+ v = new Variant(new ErrorWrapper(iv.ToInt32(provider)));
+ break;
+
+ case 11: /*VT_BOOL*/
+ v = new Variant(iv.ToBoolean(provider));
+ break;
+
+ case 12: /*VT_VARIANT*/
+ v = new Variant((Object)iv);
+ break;
+
+ case 13: /*VT_UNKNOWN*/
+ v = new Variant(new UnknownWrapper((Object)iv));
+ break;
+
+ case 14: /*VT_DECIMAL*/
+ v = new Variant(iv.ToDecimal(provider));
+ break;
+
+ // case 15: /*unused*/
+ // NOT SUPPORTED
+
+ case 16: /*VT_I1*/
+ v = new Variant(iv.ToSByte(provider));
+ break;
+
+ case 17: /*VT_UI1*/
+ v = new Variant(iv.ToByte(provider));
+ break;
+
+ case 18: /*VT_UI2*/
+ v = new Variant(iv.ToUInt16(provider));
+ break;
+
+ case 19: /*VT_UI4*/
+ v = new Variant(iv.ToUInt32(provider));
+ break;
+
+ case 20: /*VT_I8*/
+ v = new Variant(iv.ToInt64(provider));
+ break;
+
+ case 21: /*VT_UI8*/
+ v = new Variant(iv.ToUInt64(provider));
+ break;
+
+ case 22: /*VT_INT*/
+ v = new Variant(iv.ToInt32(provider));
+ break;
+
+ case 23: /*VT_UINT*/
+ v = new Variant(iv.ToUInt32(provider));
+ break;
+
+ default:
+ throw new InvalidCastException(Environment.GetResourceString("InvalidCast_CannotCoerceByRefVariant"));
+ }
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Version.cs b/src/mscorlib/src/System/Version.cs
new file mode 100644
index 0000000000..f3520b81a2
--- /dev/null
+++ b/src/mscorlib/src/System/Version.cs
@@ -0,0 +1,504 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** Purpose:
+**
+**
+===========================================================*/
+namespace System {
+
+ using System.Diagnostics.Contracts;
+ using System.Text;
+ using CultureInfo = System.Globalization.CultureInfo;
+ using NumberStyles = System.Globalization.NumberStyles;
+
+ // A Version object contains four hierarchical numeric components: major, minor,
+ // build and revision. Build and revision may be unspecified, which is represented
+ // internally as a -1. By definition, an unspecified component matches anything
+ // (both unspecified and specified), and an unspecified component is "less than" any
+ // specified component.
+
+ [Serializable]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class Version : ICloneable, IComparable
+ , IComparable<Version>, IEquatable<Version>
+ {
+ // AssemblyName depends on the order staying the same
+ private int _Major;
+ private int _Minor;
+ private int _Build = -1;
+ private int _Revision = -1;
+ private static readonly char[] SeparatorsArray = new char[] { '.' };
+
+ public Version(int major, int minor, int build, int revision) {
+ if (major < 0)
+ throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (minor < 0)
+ throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (build < 0)
+ throw new ArgumentOutOfRangeException("build",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (revision < 0)
+ throw new ArgumentOutOfRangeException("revision",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+ Contract.EndContractBlock();
+
+ _Major = major;
+ _Minor = minor;
+ _Build = build;
+ _Revision = revision;
+ }
+
+ public Version(int major, int minor, int build) {
+ if (major < 0)
+ throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (minor < 0)
+ throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (build < 0)
+ throw new ArgumentOutOfRangeException("build",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ Contract.EndContractBlock();
+
+ _Major = major;
+ _Minor = minor;
+ _Build = build;
+ }
+
+ public Version(int major, int minor) {
+ if (major < 0)
+ throw new ArgumentOutOfRangeException("major",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+
+ if (minor < 0)
+ throw new ArgumentOutOfRangeException("minor",Environment.GetResourceString("ArgumentOutOfRange_Version"));
+ Contract.EndContractBlock();
+
+ _Major = major;
+ _Minor = minor;
+ }
+
+ public Version(String version) {
+ Version v = Version.Parse(version);
+ _Major = v.Major;
+ _Minor = v.Minor;
+ _Build = v.Build;
+ _Revision = v.Revision;
+ }
+
+ public Version()
+ {
+ _Major = 0;
+ _Minor = 0;
+ }
+
+ // Properties for setting and getting version numbers
+ public int Major {
+ get { return _Major; }
+ }
+
+ public int Minor {
+ get { return _Minor; }
+ }
+
+ public int Build {
+ get { return _Build; }
+ }
+
+ public int Revision {
+ get { return _Revision; }
+ }
+
+ public short MajorRevision {
+ get { return (short)(_Revision >> 16); }
+ }
+
+ public short MinorRevision {
+ get { return (short)(_Revision & 0xFFFF); }
+ }
+
+ public Object Clone() {
+ Version v = new Version();
+ v._Major = _Major;
+ v._Minor = _Minor;
+ v._Build = _Build;
+ v._Revision = _Revision;
+ return(v);
+ }
+
+ public int CompareTo(Object version)
+ {
+ if (version == null)
+ {
+ return 1;
+ }
+
+ Version v = version as Version;
+ if (v == null)
+ {
+ throw new ArgumentException(Environment.GetResourceString("Arg_MustBeVersion"));
+ }
+
+ if (this._Major != v._Major)
+ if (this._Major > v._Major)
+ return 1;
+ else
+ return -1;
+
+ if (this._Minor != v._Minor)
+ if (this._Minor > v._Minor)
+ return 1;
+ else
+ return -1;
+
+ if (this._Build != v._Build)
+ if (this._Build > v._Build)
+ return 1;
+ else
+ return -1;
+
+ if (this._Revision != v._Revision)
+ if (this._Revision > v._Revision)
+ return 1;
+ else
+ return -1;
+
+ return 0;
+ }
+
+ public int CompareTo(Version value)
+ {
+ if (value == null)
+ return 1;
+
+ if (this._Major != value._Major)
+ if (this._Major > value._Major)
+ return 1;
+ else
+ return -1;
+
+ if (this._Minor != value._Minor)
+ if (this._Minor > value._Minor)
+ return 1;
+ else
+ return -1;
+
+ if (this._Build != value._Build)
+ if (this._Build > value._Build)
+ return 1;
+ else
+ return -1;
+
+ if (this._Revision != value._Revision)
+ if (this._Revision > value._Revision)
+ return 1;
+ else
+ return -1;
+
+ return 0;
+ }
+
+ public override bool Equals(Object obj) {
+ Version v = obj as Version;
+ if (v == null)
+ return false;
+
+ // check that major, minor, build & revision numbers match
+ if ((this._Major != v._Major) ||
+ (this._Minor != v._Minor) ||
+ (this._Build != v._Build) ||
+ (this._Revision != v._Revision))
+ return false;
+
+ return true;
+ }
+
+ public bool Equals(Version obj)
+ {
+ if (obj == null)
+ return false;
+
+ // check that major, minor, build & revision numbers match
+ if ((this._Major != obj._Major) ||
+ (this._Minor != obj._Minor) ||
+ (this._Build != obj._Build) ||
+ (this._Revision != obj._Revision))
+ return false;
+
+ return true;
+ }
+
+ public override int GetHashCode()
+ {
+ // Let's assume that most version numbers will be pretty small and just
+ // OR some lower order bits together.
+
+ int accumulator = 0;
+
+ accumulator |= (this._Major & 0x0000000F) << 28;
+ accumulator |= (this._Minor & 0x000000FF) << 20;
+ accumulator |= (this._Build & 0x000000FF) << 12;
+ accumulator |= (this._Revision & 0x00000FFF);
+
+ return accumulator;
+ }
+
+ public override String ToString() {
+ if (_Build == -1) return(ToString(2));
+ if (_Revision == -1) return(ToString(3));
+ return(ToString(4));
+ }
+
+ public String ToString(int fieldCount) {
+ StringBuilder sb;
+ switch (fieldCount) {
+ case 0:
+ return(String.Empty);
+ case 1:
+ return(_Major.ToString());
+ case 2:
+ sb = StringBuilderCache.Acquire();
+ AppendPositiveNumber(_Major, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Minor, sb);
+ return StringBuilderCache.GetStringAndRelease(sb);
+ default:
+ if (_Build == -1)
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "2"), "fieldCount");
+
+ if (fieldCount == 3)
+ {
+ sb = StringBuilderCache.Acquire();
+ AppendPositiveNumber(_Major, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Minor, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Build, sb);
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ if (_Revision == -1)
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "3"), "fieldCount");
+
+ if (fieldCount == 4)
+ {
+ sb = StringBuilderCache.Acquire();
+ AppendPositiveNumber(_Major, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Minor, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Build, sb);
+ sb.Append('.');
+ AppendPositiveNumber(_Revision, sb);
+ return StringBuilderCache.GetStringAndRelease(sb);
+ }
+
+ throw new ArgumentException(Environment.GetResourceString("ArgumentOutOfRange_Bounds_Lower_Upper", "0", "4"), "fieldCount");
+ }
+ }
+
+ //
+ // AppendPositiveNumber is an optimization to append a number to a StringBuilder object without
+ // doing any boxing and not even creating intermediate string.
+ // Note: as we always have positive numbers then it is safe to convert the number to string
+ // regardless of the current culture as we’ll not have any punctuation marks in the number
+ //
+ private const int ZERO_CHAR_VALUE = (int) '0';
+ private static void AppendPositiveNumber(int num, StringBuilder sb)
+ {
+ Contract.Assert(num >= 0, "AppendPositiveNumber expect positive numbers");
+
+ int index = sb.Length;
+ int reminder;
+
+ do
+ {
+ reminder = num % 10;
+ num = num / 10;
+ sb.Insert(index, (char)(ZERO_CHAR_VALUE + reminder));
+ } while (num > 0);
+ }
+
+ public static Version Parse(string input) {
+ if (input == null) {
+ throw new ArgumentNullException("input");
+ }
+ Contract.EndContractBlock();
+
+ VersionResult r = new VersionResult();
+ r.Init("input", true);
+ if (!TryParseVersion(input, ref r)) {
+ throw r.GetVersionParseException();
+ }
+ return r.m_parsedVersion;
+ }
+
+ public static bool TryParse(string input, out Version result) {
+ VersionResult r = new VersionResult();
+ r.Init("input", false);
+ bool b = TryParseVersion(input, ref r);
+ result = r.m_parsedVersion;
+ return b;
+ }
+
+ private static bool TryParseVersion(string version, ref VersionResult result) {
+ int major, minor, build, revision;
+
+ if ((Object)version == null) {
+ result.SetFailure(ParseFailureKind.ArgumentNullException);
+ return false;
+ }
+
+ String[] parsedComponents = version.Split(SeparatorsArray);
+ int parsedComponentsLength = parsedComponents.Length;
+ if ((parsedComponentsLength < 2) || (parsedComponentsLength > 4)) {
+ result.SetFailure(ParseFailureKind.ArgumentException);
+ return false;
+ }
+
+ if (!TryParseComponent(parsedComponents[0], "version", ref result, out major)) {
+ return false;
+ }
+
+ if (!TryParseComponent(parsedComponents[1], "version", ref result, out minor)) {
+ return false;
+ }
+
+ parsedComponentsLength -= 2;
+
+ if (parsedComponentsLength > 0) {
+ if (!TryParseComponent(parsedComponents[2], "build", ref result, out build)) {
+ return false;
+ }
+
+ parsedComponentsLength--;
+
+ if (parsedComponentsLength > 0) {
+ if (!TryParseComponent(parsedComponents[3], "revision", ref result, out revision)) {
+ return false;
+ } else {
+ result.m_parsedVersion = new Version(major, minor, build, revision);
+ }
+ } else {
+ result.m_parsedVersion = new Version(major, minor, build);
+ }
+ } else {
+ result.m_parsedVersion = new Version(major, minor);
+ }
+
+ return true;
+ }
+
+ private static bool TryParseComponent(string component, string componentName, ref VersionResult result, out int parsedComponent) {
+ if (!Int32.TryParse(component, NumberStyles.Integer, CultureInfo.InvariantCulture, out parsedComponent)) {
+ result.SetFailure(ParseFailureKind.FormatException, component);
+ return false;
+ }
+
+ if (parsedComponent < 0) {
+ result.SetFailure(ParseFailureKind.ArgumentOutOfRangeException, componentName);
+ return false;
+ }
+
+ return true;
+ }
+
+ public static bool operator ==(Version v1, Version v2) {
+ if (Object.ReferenceEquals(v1, null)) {
+ return Object.ReferenceEquals(v2, null);
+ }
+
+ return v1.Equals(v2);
+ }
+
+ public static bool operator !=(Version v1, Version v2) {
+ return !(v1 == v2);
+ }
+
+ public static bool operator <(Version v1, Version v2) {
+ if ((Object) v1 == null)
+ throw new ArgumentNullException("v1");
+ Contract.EndContractBlock();
+ return (v1.CompareTo(v2) < 0);
+ }
+
+ public static bool operator <=(Version v1, Version v2) {
+ if ((Object) v1 == null)
+ throw new ArgumentNullException("v1");
+ Contract.EndContractBlock();
+ return (v1.CompareTo(v2) <= 0);
+ }
+
+ public static bool operator >(Version v1, Version v2) {
+ return (v2 < v1);
+ }
+
+ public static bool operator >=(Version v1, Version v2) {
+ return (v2 <= v1);
+ }
+
+ internal enum ParseFailureKind {
+ ArgumentNullException,
+ ArgumentException,
+ ArgumentOutOfRangeException,
+ FormatException
+ }
+
+ internal struct VersionResult {
+ internal Version m_parsedVersion;
+ internal ParseFailureKind m_failure;
+ internal string m_exceptionArgument;
+ internal string m_argumentName;
+ internal bool m_canThrow;
+
+ internal void Init(string argumentName, bool canThrow) {
+ m_canThrow = canThrow;
+ m_argumentName = argumentName;
+ }
+
+ internal void SetFailure(ParseFailureKind failure) {
+ SetFailure(failure, String.Empty);
+ }
+
+ internal void SetFailure(ParseFailureKind failure, string argument) {
+ m_failure = failure;
+ m_exceptionArgument = argument;
+ if (m_canThrow) {
+ throw GetVersionParseException();
+ }
+ }
+
+ internal Exception GetVersionParseException() {
+ switch (m_failure) {
+ case ParseFailureKind.ArgumentNullException:
+ return new ArgumentNullException(m_argumentName);
+ case ParseFailureKind.ArgumentException:
+ return new ArgumentException(Environment.GetResourceString("Arg_VersionString"));
+ case ParseFailureKind.ArgumentOutOfRangeException:
+ return new ArgumentOutOfRangeException(m_exceptionArgument, Environment.GetResourceString("ArgumentOutOfRange_Version"));
+ case ParseFailureKind.FormatException:
+ // Regenerate the FormatException as would be thrown by Int32.Parse()
+ try {
+ Int32.Parse(m_exceptionArgument, CultureInfo.InvariantCulture);
+ } catch (FormatException e) {
+ return e;
+ } catch (OverflowException e) {
+ return e;
+ }
+ Contract.Assert(false, "Int32.Parse() did not throw exception but TryParse failed: " + m_exceptionArgument);
+ return new FormatException(Environment.GetResourceString("Format_InvalidString"));
+ default:
+ Contract.Assert(false, "Unmatched case in Version.GetVersionParseException() for value: " + m_failure);
+ return new ArgumentException(Environment.GetResourceString("Arg_VersionString"));
+ }
+ }
+
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/Void.cs b/src/mscorlib/src/System/Void.cs
new file mode 100644
index 0000000000..51df8781aa
--- /dev/null
+++ b/src/mscorlib/src/System/Void.cs
@@ -0,0 +1,18 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+////////////////////////////////////////////////////////////////////////////////
+// Void
+// This class represents the void return type
+////////////////////////////////////////////////////////////////////////////////
+
+namespace System {
+
+ using System;
+ [Serializable]
+ [System.Runtime.InteropServices.ComVisible(true)]
+ public struct Void
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/WeakReference.cs b/src/mscorlib/src/System/WeakReference.cs
new file mode 100644
index 0000000000..d12ca3e853
--- /dev/null
+++ b/src/mscorlib/src/System/WeakReference.cs
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: A wrapper for establishing a WeakReference to an Object.
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Security.Permissions;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+ [System.Runtime.InteropServices.ComVisible(true)]
+#if !FEATURE_CORECLR
+ [SecurityPermissionAttribute(SecurityAction.InheritanceDemand, Flags=SecurityPermissionFlag.UnmanagedCode)] // Don't call Object::MemberwiseClone.
+#endif
+ [Serializable]
+ public class WeakReference : ISerializable
+ {
+ // If you fix bugs here, please fix them in WeakReference<T> at the same time.
+
+ // This field is not a regular GC handle. It can have a special values that are used to prevent a race condition between setting the target and finalization.
+ internal IntPtr m_handle;
+
+#if FEATURE_CORECLR
+ // Migrating InheritanceDemands requires this default ctor, so we can mark it SafeCritical
+ [SecuritySafeCritical]
+ protected WeakReference() {
+ Contract.Assert(false, "WeakReference's protected default ctor should never be used!");
+ throw new NotImplementedException();
+ }
+#endif
+
+ // Creates a new WeakReference that keeps track of target.
+ // Assumes a Short Weak Reference (ie TrackResurrection is false.)
+ //
+ public WeakReference(Object target)
+ : this(target, false) {
+ }
+
+ //Creates a new WeakReference that keeps track of target.
+ //
+ public WeakReference(Object target, bool trackResurrection) {
+ Create(target, trackResurrection);
+ }
+
+ protected WeakReference(SerializationInfo info, StreamingContext context) {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ Object target = info.GetValue("TrackedObject",typeof(Object));
+ bool trackResurrection = info.GetBoolean("TrackResurrection");
+
+ Create(target, trackResurrection);
+ }
+
+ //Determines whether or not this instance of WeakReference still refers to an object
+ //that has not been collected.
+ //
+ public extern virtual bool IsAlive {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ get;
+ }
+
+ //Returns a boolean indicating whether or not we're tracking objects until they're collected (true)
+ //or just until they're finalized (false).
+ //
+ public virtual bool TrackResurrection {
+ // We need to call IsTrackResurrection non-virtually in GetObjectData, and so the virtual property cannot be FCall directly
+ get { return IsTrackResurrection(); }
+ }
+
+ //Gets the Object stored in the handle if it's accessible.
+ // Or sets it.
+ //
+ public extern virtual Object Target {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ get;
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ set;
+ }
+
+ // Free all system resources associated with this reference.
+ //
+ // Note: The WeakReference finalizer is not actually run, but
+ // treated specially in gc.cpp's ScanForFinalization
+ // This is needed for subclasses deriving from WeakReference, however.
+ // Additionally, there may be some cases during shutdown when we run this finalizer.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ extern ~WeakReference();
+
+ [SecurityCritical]
+ public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info==null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+ info.AddValue("TrackedObject", Target, typeof(Object));
+ info.AddValue("TrackResurrection", IsTrackResurrection());
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ private extern void Create(Object target, bool trackResurrection);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ private extern bool IsTrackResurrection();
+ }
+
+}
diff --git a/src/mscorlib/src/System/WeakReferenceOfT.cs b/src/mscorlib/src/System/WeakReferenceOfT.cs
new file mode 100644
index 0000000000..b8195df6d9
--- /dev/null
+++ b/src/mscorlib/src/System/WeakReferenceOfT.cs
@@ -0,0 +1,121 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+** Purpose: A wrapper for establishing a WeakReference to a generic type.
+**
+===========================================================*/
+namespace System
+{
+ using System;
+ using System.Runtime.Serialization;
+ using System.Security;
+ using System.Runtime;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+
+ [Serializable]
+ // This class is sealed to mitigate security issues caused by Object::MemberwiseClone.
+ public sealed class WeakReference<T> : ISerializable
+ where T : class
+ {
+ // If you fix bugs here, please fix them in WeakReference at the same time.
+
+ // This field is not a regular GC handle. It can have a special values that are used to prevent a race condition between setting the target and finalization.
+ internal IntPtr m_handle;
+
+ // Creates a new WeakReference that keeps track of target.
+ // Assumes a Short Weak Reference (ie TrackResurrection is false.)
+ //
+ public WeakReference(T target)
+ : this(target, false)
+ {
+ }
+
+ //Creates a new WeakReference that keeps track of target.
+ //
+ public WeakReference(T target, bool trackResurrection)
+ {
+ Create(target, trackResurrection);
+ }
+
+ internal WeakReference(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ T target = (T)info.GetValue("TrackedObject", typeof(T));
+ bool trackResurrection = info.GetBoolean("TrackResurrection");
+
+ Create(target, trackResurrection);
+ }
+
+ //
+ // We are exposing TryGetTarget instead of a simple getter to avoid a common problem where people write incorrect code like:
+ //
+ // WeakReference ref = ...;
+ // if (ref.Target != null)
+ // DoSomething(ref.Target)
+ //
+ [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
+ public bool TryGetTarget(out T target)
+ {
+ // Call the worker method that has more performant but less user friendly signature.
+ T o = this.Target;
+ target = o;
+ return o != null;
+ }
+
+ public void SetTarget(T target)
+ {
+ this.Target = target;
+ }
+
+ // This is property for better debugging experience (VS debugger shows values of properties when you hover over the variables)
+ private extern T Target
+ {
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ get;
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ set;
+ }
+
+ // Free all system resources associated with this reference.
+ //
+ // Note: The WeakReference<T> finalizer is not usually run, but
+ // treated specially in gc.cpp's ScanForFinalization
+ // This is needed for subclasses deriving from WeakReference<T>, however.
+ // Additionally, there may be some cases during shutdown when we run this finalizer.
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ extern ~WeakReference();
+
+ [SecurityCritical]
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ if (info == null) {
+ throw new ArgumentNullException("info");
+ }
+ Contract.EndContractBlock();
+
+ info.AddValue("TrackedObject", this.Target, typeof(T));
+ info.AddValue("TrackResurrection", IsTrackResurrection());
+ }
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ private extern void Create(T target, bool trackResurrection);
+
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ [SecuritySafeCritical]
+ private extern bool IsTrackResurrection();
+ }
+}
diff --git a/src/mscorlib/src/System/XmlIgnoreMemberAttribute.cs b/src/mscorlib/src/System/XmlIgnoreMemberAttribute.cs
new file mode 100644
index 0000000000..04a8e688e6
--- /dev/null
+++ b/src/mscorlib/src/System/XmlIgnoreMemberAttribute.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Attribute for properties/members that the Xml Serializer should
+** ignore.
+**
+**
+=============================================================================*/
+
+namespace System
+{
+ [AttributeUsage(AttributeTargets.Property|AttributeTargets.Field)]
+ internal sealed class XmlIgnoreMemberAttribute : Attribute
+ {
+ }
+}
diff --git a/src/mscorlib/src/System/_LocalDataStore.cs b/src/mscorlib/src/System/_LocalDataStore.cs
new file mode 100644
index 0000000000..a3a312f104
--- /dev/null
+++ b/src/mscorlib/src/System/_LocalDataStore.cs
@@ -0,0 +1,244 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Class that stores local data. This class is used in cooperation
+** with the _LocalDataStoreMgr class.
+**
+**
+=============================================================================*/
+
+namespace System {
+
+ using System;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // Helper class to aid removal of LocalDataStore from the LocalDataStoreMgr
+ // LocalDataStoreMgr does not holds references to LocalDataStoreHolder. It holds
+ // references to LocalDataStore only. LocalDataStoreHolder finalizer will run once
+ // the only outstanding reference to the store is in LocalDataStoreMgr.
+ sealed internal class LocalDataStoreHolder
+ {
+ private LocalDataStore m_Store;
+
+ public LocalDataStoreHolder(LocalDataStore store)
+ {
+ m_Store = store;
+ }
+
+ ~LocalDataStoreHolder()
+ {
+ LocalDataStore store = m_Store;
+ if (store == null)
+ return;
+
+ store.Dispose();
+ }
+
+ public LocalDataStore Store
+ {
+ get
+ {
+ return m_Store;
+ }
+ }
+ }
+
+ sealed internal class LocalDataStoreElement
+ {
+ private Object m_value;
+ private long m_cookie; // This is immutable cookie of the slot used to verify that
+ // the value is indeed indeed owned by the slot. Necessary
+ // to avoid resurection holes.
+
+ public LocalDataStoreElement(long cookie)
+ {
+ m_cookie = cookie;
+ }
+
+ public Object Value
+ {
+ get
+ {
+ return m_value;
+ }
+ set
+ {
+ m_value = value;
+ }
+ }
+
+ public long Cookie
+ {
+ get
+ {
+ return m_cookie;
+ }
+ }
+ }
+
+ // This class will not be marked serializable
+ sealed internal class LocalDataStore
+ {
+ private LocalDataStoreElement[] m_DataTable;
+ private LocalDataStoreMgr m_Manager;
+
+ /*=========================================================================
+ ** Initialize the data store.
+ =========================================================================*/
+ public LocalDataStore(LocalDataStoreMgr mgr, int InitialCapacity)
+ {
+ // Store the manager of the local data store.
+ m_Manager = mgr;
+
+ // Allocate the array that will contain the data.
+ m_DataTable = new LocalDataStoreElement[InitialCapacity];
+ }
+
+ /*=========================================================================
+ ** Delete this store from its manager
+ =========================================================================*/
+ internal void Dispose()
+ {
+ m_Manager.DeleteLocalDataStore(this);
+ }
+
+ /*=========================================================================
+ ** Retrieves the value from the specified slot.
+ =========================================================================*/
+ public Object GetData(LocalDataStoreSlot slot)
+ {
+ // Validate the slot.
+ m_Manager.ValidateSlot(slot);
+
+ // Cache the slot index to avoid synchronization issues.
+ int slotIdx = slot.Slot;
+
+ if (slotIdx >= 0)
+ {
+ // Delay expansion of m_DataTable if we can
+ if (slotIdx >= m_DataTable.Length)
+ return null;
+
+ // Retrieve the data from the given slot.
+ LocalDataStoreElement element = m_DataTable[slotIdx];
+
+ //Initially we prepopulate the elements to be null.
+ if (element == null)
+ return null;
+
+ // Check that the element is owned by this slot by comparing cookies.
+ // This is necesary to avoid resurection race conditions.
+ if (element.Cookie == slot.Cookie)
+ return element.Value;
+
+ // Fall thru and throw exception
+ }
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
+ }
+
+ /*=========================================================================
+ ** Sets the data in the specified slot.
+ =========================================================================*/
+ public void SetData(LocalDataStoreSlot slot, Object data)
+ {
+ // Validate the slot.
+ m_Manager.ValidateSlot(slot);
+
+ // Cache the slot index to avoid synchronization issues.
+ int slotIdx = slot.Slot;
+
+ if (slotIdx >= 0)
+ {
+ LocalDataStoreElement element = (slotIdx < m_DataTable.Length) ? m_DataTable[slotIdx] : null;
+ if (element == null)
+ {
+ element = PopulateElement(slot);
+ }
+
+ // Check that the element is owned by this slot by comparing cookies.
+ // This is necesary to avoid resurection race conditions.
+ if (element.Cookie == slot.Cookie)
+ {
+ // Set the data on the given slot.
+ element.Value = data;
+ return;
+ }
+
+ // Fall thru and throw exception
+ }
+
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
+ }
+
+ /*=========================================================================
+ ** This method does clears the unused slot.
+ * Assumes lock on m_Manager is taken
+ =========================================================================*/
+ internal void FreeData(int slot, long cookie)
+ {
+ // We try to delay allocate the dataTable (in cases like the manager clearing a
+ // just-freed slot in all stores
+ if (slot >= m_DataTable.Length)
+ return;
+
+ LocalDataStoreElement element = m_DataTable[slot];
+ if (element != null && element.Cookie == cookie)
+ m_DataTable[slot] = null;
+ }
+
+ /*=========================================================================
+ ** Method used to expand the capacity of the local data store.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ private LocalDataStoreElement PopulateElement(LocalDataStoreSlot slot)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try {
+ Monitor.Enter(m_Manager, ref tookLock);
+
+ // Make sure that the slot was not freed in the meantime
+ int slotIdx = slot.Slot;
+ if (slotIdx < 0)
+ throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_SlotHasBeenFreed"));
+
+ if (slotIdx >= m_DataTable.Length)
+ {
+ int capacity = m_Manager.GetSlotTableLength();
+
+ // Validate that the specified capacity is larger than the current one.
+ Contract.Assert(capacity >= m_DataTable.Length, "LocalDataStore corrupted: capacity >= m_DataTable.Length");
+
+ // Allocate the new data table.
+ LocalDataStoreElement[] NewDataTable = new LocalDataStoreElement[capacity];
+
+ // Copy all the objects into the new table.
+ Array.Copy(m_DataTable, NewDataTable, m_DataTable.Length);
+
+ // Save the new table.
+ m_DataTable = NewDataTable;
+ }
+
+ // Validate that there is enough space in the local data store now
+ Contract.Assert(slotIdx < m_DataTable.Length, "LocalDataStore corrupted: slotIdx < m_DataTable.Length");
+
+ if (m_DataTable[slotIdx] == null)
+ m_DataTable[slotIdx] = new LocalDataStoreElement(slot.Cookie);
+
+ return m_DataTable[slotIdx];
+ }
+ finally {
+ if (tookLock)
+ Monitor.Exit(m_Manager);
+ }
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/_LocalDataStoreMgr.cs b/src/mscorlib/src/System/_LocalDataStoreMgr.cs
new file mode 100644
index 0000000000..615413848d
--- /dev/null
+++ b/src/mscorlib/src/System/_LocalDataStoreMgr.cs
@@ -0,0 +1,339 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================================
+**
+**
+**
+** Purpose: Class that manages stores of local data. This class is used in
+** cooperation with the LocalDataStore class.
+**
+**
+=============================================================================*/
+namespace System {
+
+ using System;
+ using System.Collections.Generic;
+ using System.Threading;
+ using System.Runtime.CompilerServices;
+ using System.Diagnostics.Contracts;
+
+ // This class is an encapsulation of a slot so that it is managed in a secure fashion.
+ // It is constructed by the LocalDataStoreManager, holds the slot and the manager
+ // and cleans up when it is finalized.
+ // This class will not be marked serializable
+[System.Runtime.InteropServices.ComVisible(true)]
+ public sealed class LocalDataStoreSlot
+ {
+ private LocalDataStoreMgr m_mgr;
+ private int m_slot;
+ private long m_cookie;
+
+ // Construct the object to encapsulate the slot.
+ internal LocalDataStoreSlot(LocalDataStoreMgr mgr, int slot, long cookie)
+ {
+ m_mgr = mgr;
+ m_slot = slot;
+ m_cookie = cookie;
+ }
+
+ // Accessors for the two fields of this class.
+ internal LocalDataStoreMgr Manager
+ {
+ get
+ {
+ return m_mgr;
+ }
+ }
+ internal int Slot
+ {
+ get
+ {
+ return m_slot;
+ }
+ }
+ internal long Cookie
+ {
+ get
+ {
+ return m_cookie;
+ }
+ }
+
+ // Release the slot reserved by this object when this object goes away.
+ ~LocalDataStoreSlot()
+ {
+ LocalDataStoreMgr mgr = m_mgr;
+ if (mgr == null)
+ return;
+
+ int slot = m_slot;
+
+ // Mark the slot as free.
+ m_slot = -1;
+
+ mgr.FreeDataSlot(slot, m_cookie);
+ }
+ }
+
+ // This class will not be marked serializable
+ sealed internal class LocalDataStoreMgr
+ {
+ private const int InitialSlotTableSize = 64;
+ private const int SlotTableDoubleThreshold = 512;
+ private const int LargeSlotTableSizeIncrease = 128;
+
+ /*=========================================================================
+ ** Create a data store to be managed by this manager and add it to the
+ ** list. The initial size of the new store matches the number of slots
+ ** allocated in this manager.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LocalDataStoreHolder CreateLocalDataStore()
+ {
+ // Create a new local data store.
+ LocalDataStore store = new LocalDataStore(this, m_SlotInfoTable.Length);
+ LocalDataStoreHolder holder = new LocalDataStoreHolder(store);
+
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Add the store to the array list and return it.
+ m_ManagedLocalDataStores.Add(store);
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ return holder;
+ }
+
+ /*=========================================================================
+ * Remove the specified store from the list of managed stores..
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void DeleteLocalDataStore(LocalDataStore store)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Remove the store to the array list and return it.
+ m_ManagedLocalDataStores.Remove(store);
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Allocates a data slot by finding an available index and wrapping it
+ ** an object to prevent clients from manipulating it directly, allowing us
+ ** to make assumptions its integrity.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LocalDataStoreSlot AllocateDataSlot()
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ LocalDataStoreSlot slot;
+
+ int slotTableSize = m_SlotInfoTable.Length;
+
+ // In case FreeDataSlot has moved the pointer back, the next slot may not be available.
+ // Find the first actually available slot.
+ int availableSlot = m_FirstAvailableSlot;
+ while (availableSlot < slotTableSize)
+ {
+ if (!m_SlotInfoTable[availableSlot])
+ break;
+ availableSlot++;
+ }
+
+ // Check if there are any slots left.
+ if (availableSlot >= slotTableSize)
+ {
+ // The table is full so we need to increase its size.
+ int newSlotTableSize;
+ if (slotTableSize < SlotTableDoubleThreshold)
+ {
+ // The table is still relatively small so double it.
+ newSlotTableSize = slotTableSize * 2;
+ }
+ else
+ {
+ // The table is relatively large so simply increase its size by a given amount.
+ newSlotTableSize = slotTableSize + LargeSlotTableSizeIncrease;
+ }
+
+ // Allocate the new slot info table.
+ bool[] newSlotInfoTable = new bool[newSlotTableSize];
+
+ // Copy the old array into the new one.
+ Array.Copy(m_SlotInfoTable, newSlotInfoTable, slotTableSize);
+ m_SlotInfoTable = newSlotInfoTable;
+ }
+
+ // availableSlot is the index of the empty slot.
+ m_SlotInfoTable[availableSlot] = true;
+
+ // We do not need to worry about overflowing m_CookieGenerator. It would take centuries
+ // of intensive slot allocations on current machines to get the 2^64 counter to overflow.
+ // We will perform the increment with overflow check just to play it on the safe side.
+ slot = new LocalDataStoreSlot(this, availableSlot, checked(m_CookieGenerator++));
+
+ // Save the new "first available slot".hint
+ m_FirstAvailableSlot = availableSlot + 1;
+
+ // Return the selected slot
+ return slot;
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Allocate a slot and associate a name with it.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LocalDataStoreSlot AllocateNamedDataSlot(String name)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Allocate a normal data slot.
+ LocalDataStoreSlot slot = AllocateDataSlot();
+
+ // Insert the association between the name and the data slot number
+ // in the hash table.
+ m_KeyToSlotMap.Add(name, slot);
+ return slot;
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Retrieve the slot associated with a name, allocating it if no such
+ ** association has been defined.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public LocalDataStoreSlot GetNamedDataSlot(String name)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Lookup in the hashtable to try find a slot for the name.
+ LocalDataStoreSlot slot = m_KeyToSlotMap.GetValueOrDefault(name);
+
+ // If the name is not yet in the hashtable then add it.
+ if (null == slot)
+ return AllocateNamedDataSlot(name);
+
+ // The name was in the hashtable so return the associated slot.
+ return slot;
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Eliminate the association of a name with a slot. The actual slot will
+ ** be reclaimed when the finalizer for the slot object runs.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ public void FreeNamedDataSlot(String name)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Remove the name slot association from the hashtable.
+ m_KeyToSlotMap.Remove(name);
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Free's a previously allocated data slot on ALL the managed data stores.
+ =========================================================================*/
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal void FreeDataSlot(int slot, long cookie)
+ {
+ bool tookLock = false;
+ RuntimeHelpers.PrepareConstrainedRegions();
+ try
+ {
+ Monitor.Enter(this, ref tookLock);
+ // Go thru all the managed stores and set the data on the specified slot to 0.
+ for (int i = 0; i < m_ManagedLocalDataStores.Count; i++)
+ {
+ ((LocalDataStore)m_ManagedLocalDataStores[i]).FreeData(slot, cookie);
+ }
+
+ // Mark the slot as being no longer occupied.
+ m_SlotInfoTable[slot] = false;
+ if (slot < m_FirstAvailableSlot)
+ m_FirstAvailableSlot = slot;
+ }
+ finally
+ {
+ if (tookLock)
+ Monitor.Exit(this);
+ }
+ }
+
+ /*=========================================================================
+ ** Check that this is a valid slot for this store
+ =========================================================================*/
+ public void ValidateSlot(LocalDataStoreSlot slot)
+ {
+ // Make sure the slot was allocated for this store.
+ if (slot == null || slot.Manager != this)
+ throw new ArgumentException(Environment.GetResourceString("Argument_ALSInvalidSlot"));
+ Contract.EndContractBlock();
+ }
+
+ /*=========================================================================
+ ** Return the number of allocated slots in this manager.
+ =========================================================================*/
+ internal int GetSlotTableLength()
+ {
+ return m_SlotInfoTable.Length;
+ }
+
+ private bool[] m_SlotInfoTable = new bool[InitialSlotTableSize];
+ private int m_FirstAvailableSlot;
+ private List<LocalDataStore> m_ManagedLocalDataStores = new List<LocalDataStore>();
+ private Dictionary<String, LocalDataStoreSlot> m_KeyToSlotMap = new Dictionary<String, LocalDataStoreSlot>();
+ private long m_CookieGenerator;
+ }
+}
diff --git a/src/mscorlib/src/System/__ComObject.cs b/src/mscorlib/src/System/__ComObject.cs
new file mode 100644
index 0000000000..a5923707b6
--- /dev/null
+++ b/src/mscorlib/src/System/__ComObject.cs
@@ -0,0 +1,206 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*============================================================
+**
+**
+**
+** __ComObject is the root class for all COM wrappers. This class
+** defines only the basics. This class is used for wrapping COM objects
+** accessed from COM+
+**
+**
+===========================================================*/
+namespace System {
+
+ using System;
+ using System.Collections;
+ using System.Threading;
+ using System.Runtime.InteropServices;
+ using System.Runtime.InteropServices.WindowsRuntime;
+ using System.Runtime.CompilerServices;
+ using System.Reflection;
+ using System.Security.Permissions;
+
+ internal class __ComObject : MarshalByRefObject
+ {
+ private Hashtable m_ObjectToDataMap;
+
+ /*============================================================
+ ** default constructor
+ ** can't instantiate this directly
+ =============================================================*/
+ protected __ComObject ()
+ {
+ }
+
+ //====================================================================
+ // Overrides ToString() to make sure we call to IStringable if the
+ // COM object implements it in the case of weakly typed RCWs
+ //====================================================================
+ public override string ToString()
+ {
+ //
+ // Only do the IStringable cast when running under AppX for better compat
+ // Otherwise we could do a IStringable cast in classic apps which could introduce
+ // a thread transition which would lead to deadlock
+ //
+ if (AppDomain.IsAppXModel())
+ {
+ // Check whether the type implements IStringable.
+ IStringable stringableType = this as IStringable;
+ if (stringableType != null)
+ {
+ return stringableType.ToString();
+ }
+ }
+
+ return base.ToString();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal IntPtr GetIUnknown(out bool fIsURTAggregated)
+ {
+ fIsURTAggregated = !GetType().IsDefined(typeof(ComImportAttribute), false);
+ return System.Runtime.InteropServices.Marshal.GetIUnknownForObject(this);
+ }
+
+ //====================================================================
+ // This method retrieves the data associated with the specified
+ // key if any such data exists for the current __ComObject.
+ //====================================================================
+ internal Object GetData(Object key)
+ {
+ Object data = null;
+
+ // Synchronize access to the map.
+ lock(this)
+ {
+ // If the map hasn't been allocated, then there can be no data for the specified key.
+ if (m_ObjectToDataMap != null)
+ {
+ // Look up the data in the map.
+ data = m_ObjectToDataMap[key];
+ }
+ }
+
+ return data;
+ }
+
+ //====================================================================
+ // This method sets the data for the specified key on the current
+ // __ComObject.
+ //====================================================================
+ internal bool SetData(Object key, Object data)
+ {
+ bool bAdded = false;
+
+ // Synchronize access to the map.
+ lock(this)
+ {
+ // If the map hasn't been allocated yet, allocate it.
+ if (m_ObjectToDataMap == null)
+ m_ObjectToDataMap = new Hashtable();
+
+ // If there isn't already data in the map then add it.
+ if (m_ObjectToDataMap[key] == null)
+ {
+ m_ObjectToDataMap[key] = data;
+ bAdded = true;
+ }
+ }
+
+ return bAdded;
+ }
+
+ //====================================================================
+ // This method is called from within the EE and releases all the
+ // cached data for the __ComObject.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated
+ internal void ReleaseAllData()
+ {
+ // Synchronize access to the map.
+ lock(this)
+ {
+
+ // If the map hasn't been allocated, then there is nothing to do.
+ if (m_ObjectToDataMap != null)
+ {
+ foreach (Object o in m_ObjectToDataMap.Values)
+ {
+ // Note: the value could be an object[]
+ // We are fine for now as object[] doesn't implement IDisposable nor derive from __ComObject
+
+ // If the object implements IDisposable, then call Dispose on it.
+ IDisposable DisposableObj = o as IDisposable;
+ if (DisposableObj != null)
+ DisposableObj.Dispose();
+
+ // If the object is a derived from __ComObject, then call Marshal.ReleaseComObject on it.
+ __ComObject ComObj = o as __ComObject;
+ if (ComObj != null)
+ Marshal.ReleaseComObject(ComObj);
+ }
+
+ // Set the map to null to indicate it has been cleaned up.
+ m_ObjectToDataMap = null;
+ }
+ }
+ }
+
+ //====================================================================
+ // This method is called from within the EE and is used to handle
+ // calls on methods of event interfaces.
+ //====================================================================
+ [System.Security.SecurityCritical] // auto-generated
+ internal Object GetEventProvider(RuntimeType t)
+ {
+ // Check to see if we already have a cached event provider for this type.
+ Object EvProvider = GetData(t);
+
+ // If we don't then we need to create one.
+ if (EvProvider == null)
+ EvProvider = CreateEventProvider(t);
+
+ return EvProvider;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal int ReleaseSelf()
+ {
+ return Marshal.InternalReleaseComObject(this);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void FinalReleaseSelf()
+ {
+ Marshal.InternalFinalReleaseComObject(this);
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+#if !FEATURE_CORECLR
+ [ReflectionPermissionAttribute(SecurityAction.Assert, MemberAccess=true)]
+#endif
+ private Object CreateEventProvider(RuntimeType t)
+ {
+ // Create the event provider for the specified type.
+ Object EvProvider = Activator.CreateInstance(t, Activator.ConstructorDefault | BindingFlags.NonPublic, null, new Object[]{this}, null);
+
+ // Attempt to cache the wrapper on the object.
+ if (!SetData(t, EvProvider))
+ {
+ // Dispose the event provider if it implements IDisposable.
+ IDisposable DisposableEvProv = EvProvider as IDisposable;
+ if (DisposableEvProv != null)
+ DisposableEvProv.Dispose();
+
+ // Another thead already cached the wrapper so use that one instead.
+ EvProvider = GetData(t);
+ }
+
+ return EvProvider;
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/__Filters.cs b/src/mscorlib/src/System/__Filters.cs
new file mode 100644
index 0000000000..aabb52d803
--- /dev/null
+++ b/src/mscorlib/src/System/__Filters.cs
@@ -0,0 +1,155 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//
+// This class defines the delegate methods for the COM+ implemented filters.
+//
+//
+//
+
+namespace System {
+ using System;
+ using System.Reflection;
+ using System.Globalization;
+ [Serializable]
+ internal class __Filters {
+
+ // Filters...
+ // The following are the built in filters defined for this class. These
+ // should really be defined as static methods. They are used in as delegates
+ // which currently doesn't support static methods. We will change this
+ // once the compiler supports delegates.
+ //
+ // Note that it is not possible to make this class static as suggested by
+ // the above comment anymore because of it got marked serializable.
+
+ internal static readonly __Filters Instance = new __Filters();
+
+ // FilterAttribute
+ // This method will search for a member based upon the attribute passed in.
+ // filterCriteria -- an Int32 representing the attribute
+ internal virtual bool FilterAttribute(MemberInfo m,Object filterCriteria)
+ {
+ // Check that the criteria object is an Integer object
+ if (filterCriteria == null)
+ throw new InvalidFilterCriteriaException(Environment.GetResourceString("RFLCT.FltCritInt"));
+
+ switch (m.MemberType)
+ {
+ case MemberTypes.Constructor:
+ case MemberTypes.Method: {
+
+ MethodAttributes criteria = 0;
+ try {
+ int i = (int) filterCriteria;
+ criteria = (MethodAttributes) i;
+ }
+ catch {
+ throw new InvalidFilterCriteriaException(Environment.GetResourceString("RFLCT.FltCritInt"));
+ }
+
+
+ MethodAttributes attr;
+ if (m.MemberType == MemberTypes.Method)
+ attr = ((MethodInfo) m).Attributes;
+ else
+ attr = ((ConstructorInfo) m).Attributes;
+
+ if (((criteria & MethodAttributes.MemberAccessMask) != 0) && (attr & MethodAttributes.MemberAccessMask) != (criteria & MethodAttributes.MemberAccessMask))
+ return false;
+ if (((criteria & MethodAttributes.Static) != 0) && (attr & MethodAttributes.Static) == 0)
+ return false;
+ if (((criteria & MethodAttributes.Final) != 0) && (attr & MethodAttributes.Final) == 0)
+ return false;
+ if (((criteria & MethodAttributes.Virtual) != 0) && (attr & MethodAttributes.Virtual) == 0)
+ return false;
+ if (((criteria & MethodAttributes.Abstract) != 0) && (attr & MethodAttributes.Abstract) == 0)
+ return false;
+ if (((criteria & MethodAttributes.SpecialName) != 0) && (attr & MethodAttributes.SpecialName) == 0)
+ return false;
+ return true;
+ }
+ case MemberTypes.Field:
+ {
+ FieldAttributes criteria = 0;
+ try {
+ int i = (int) filterCriteria;
+ criteria = (FieldAttributes) i;
+ }
+ catch {
+ throw new InvalidFilterCriteriaException(Environment.GetResourceString("RFLCT.FltCritInt"));
+ }
+
+ FieldAttributes attr = ((FieldInfo) m).Attributes;
+ if (((criteria & FieldAttributes.FieldAccessMask) != 0) && (attr & FieldAttributes.FieldAccessMask) != (criteria & FieldAttributes.FieldAccessMask))
+ return false;
+ if (((criteria & FieldAttributes.Static) != 0) && (attr & FieldAttributes.Static) == 0)
+ return false;
+ if (((criteria & FieldAttributes.InitOnly) != 0) && (attr & FieldAttributes.InitOnly) == 0)
+ return false;
+ if (((criteria & FieldAttributes.Literal) != 0) && (attr & FieldAttributes.Literal) == 0)
+ return false;
+ if (((criteria & FieldAttributes.NotSerialized) != 0) && (attr & FieldAttributes.NotSerialized) == 0)
+ return false;
+ if (((criteria & FieldAttributes.PinvokeImpl) != 0) && (attr & FieldAttributes.PinvokeImpl) == 0)
+ return false;
+ return true;
+ }
+ }
+
+ return false;
+ }
+ // FilterName
+ // This method will filter based upon the name. A partial wildcard
+ // at the end of the string is supported.
+ // filterCriteria -- This is the string name
+ internal virtual bool FilterName(MemberInfo m,Object filterCriteria)
+ {
+ // Check that the criteria object is a String object
+ if(filterCriteria == null || !(filterCriteria is String))
+ throw new InvalidFilterCriteriaException(Environment.GetResourceString("RFLCT.FltCritString"));
+
+ // At the moment this fails if its done on a single line....
+ String str = ((String) filterCriteria);
+ str = str.Trim();
+
+ String name = m.Name;
+ // Get the nested class name only, as opposed to the mangled one
+ if (m.MemberType == MemberTypes.NestedType)
+ name = name.Substring(name.LastIndexOf('+') + 1);
+ // Check to see if this is a prefix or exact match requirement
+ if (str.Length > 0 && str[str.Length - 1] == '*') {
+ str = str.Substring(0, str.Length - 1);
+ return (name.StartsWith(str, StringComparison.Ordinal));
+ }
+
+ return (name.Equals(str));
+ }
+
+ // FilterIgnoreCase
+ // This delegate will do a name search but does it with the
+ // ignore case specified.
+ internal virtual bool FilterIgnoreCase(MemberInfo m,Object filterCriteria)
+ {
+ // Check that the criteria object is a String object
+ if(filterCriteria == null || !(filterCriteria is String))
+ throw new InvalidFilterCriteriaException(Environment.GetResourceString("RFLCT.FltCritString"));
+
+ String str = (String) filterCriteria;
+ str = str.Trim();
+
+ String name = m.Name;
+ // Get the nested class name only, as opposed to the mangled one
+ if (m.MemberType == MemberTypes.NestedType)
+ name = name.Substring(name.LastIndexOf('+') + 1);
+ // Check to see if this is a prefix or exact match requirement
+ if (str.Length > 0 && str[str.Length - 1] == '*') {
+ str = str.Substring(0, str.Length - 1);
+ return (String.Compare(name,0,str,0,str.Length,StringComparison.OrdinalIgnoreCase)==0);
+ }
+
+ return (String.Compare(str,name, StringComparison.OrdinalIgnoreCase) == 0);
+ }
+ }
+}
diff --git a/src/mscorlib/src/System/__HResults.cs b/src/mscorlib/src/System/__HResults.cs
new file mode 100644
index 0000000000..d1f21e22ae
--- /dev/null
+++ b/src/mscorlib/src/System/__HResults.cs
@@ -0,0 +1,129 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//=============================================================================
+//
+//
+// Purpose: Define HResult constants. Every exception has one of these.
+//
+//
+//===========================================================================*/
+namespace System {
+ // Note: FACILITY_URT is defined as 0x13 (0x8013xxxx). Within that
+ // range, 0x1yyy is for Runtime errors (used for Security, Metadata, etc).
+ // In that subrange, 0x15zz and 0x16zz have been allocated for classlib-type
+ // HResults. Also note that some of our HResults have to map to certain
+ // COM HR's, etc.
+
+ // Another arbitrary decision... Feel free to change this, as long as you
+ // renumber the HResults yourself (and update rexcep.h).
+ // Reflection will use 0x1600 -> 0x161f. IO will use 0x1620 -> 0x163f.
+ // Security will use 0x1640 -> 0x165f
+
+ // There are __HResults files in the IO, Remoting, Reflection &
+ // Security/Util directories as well, so choose your HResults carefully.
+
+ using System;
+ internal static class __HResults
+ {
+
+ internal const int RO_E_CLOSED = unchecked((int)0x80000013);
+ internal const int E_BOUNDS = unchecked((int)0x8000000B);
+ internal const int E_CHANGED_STATE = unchecked((int)0x8000000C);
+ internal const int E_FAIL = unchecked((int)0x80004005);
+ internal const int E_POINTER = unchecked((int)0x80004003);
+ internal const int E_NOTIMPL = unchecked((int)0x80004001);
+ internal const int REGDB_E_CLASSNOTREG = unchecked((int)0x80040154);
+ internal const int COR_E_AMBIGUOUSMATCH = unchecked((int)0x8000211D);
+ internal const int COR_E_APPDOMAINUNLOADED = unchecked((int)0x80131014);
+ internal const int COR_E_APPLICATION = unchecked((int)0x80131600);
+ internal const int COR_E_ARGUMENT = unchecked((int)0x80070057);
+ internal const int COR_E_ARGUMENTOUTOFRANGE = unchecked((int)0x80131502);
+ internal const int COR_E_ARITHMETIC = unchecked((int)0x80070216);
+ internal const int COR_E_ARRAYTYPEMISMATCH = unchecked((int)0x80131503);
+ internal const int COR_E_BADIMAGEFORMAT = unchecked((int)0x8007000B);
+ internal const int COR_E_TYPEUNLOADED = unchecked((int)0x80131013);
+ internal const int COR_E_CANNOTUNLOADAPPDOMAIN = unchecked((int)0x80131015);
+ internal const int COR_E_COMEMULATE = unchecked((int)0x80131535);
+ internal const int COR_E_CONTEXTMARSHAL = unchecked((int)0x80131504);
+ internal const int COR_E_DATAMISALIGNED = unchecked((int)0x80131541);
+ internal const int COR_E_TIMEOUT = unchecked((int)0x80131505);
+ internal const int COR_E_CUSTOMATTRIBUTEFORMAT = unchecked((int)0x80131605);
+ internal const int COR_E_DIVIDEBYZERO = unchecked((int)0x80020012); // DISP_E_DIVBYZERO
+ internal const int COR_E_DUPLICATEWAITOBJECT = unchecked((int)0x80131529);
+ internal const int COR_E_EXCEPTION = unchecked((int)0x80131500);
+ internal const int COR_E_EXECUTIONENGINE = unchecked((int)0x80131506);
+ internal const int COR_E_FIELDACCESS = unchecked((int)0x80131507);
+ internal const int COR_E_FORMAT = unchecked((int)0x80131537);
+ internal const int COR_E_INDEXOUTOFRANGE = unchecked((int)0x80131508);
+ internal const int COR_E_INSUFFICIENTMEMORY = unchecked((int)0x8013153D);
+ internal const int COR_E_INSUFFICIENTEXECUTIONSTACK = unchecked((int)0x80131578);
+ internal const int COR_E_INVALIDCAST = unchecked((int)0x80004002);
+ internal const int COR_E_INVALIDCOMOBJECT = unchecked((int)0x80131527);
+ internal const int COR_E_INVALIDFILTERCRITERIA = unchecked((int)0x80131601);
+ internal const int COR_E_INVALIDOLEVARIANTTYPE = unchecked((int)0x80131531);
+ internal const int COR_E_INVALIDOPERATION = unchecked((int)0x80131509);
+ internal const int COR_E_INVALIDPROGRAM = unchecked((int)0x8013153A);
+ internal const int COR_E_KEYNOTFOUND = unchecked((int)0x80131577);
+ internal const int COR_E_MARSHALDIRECTIVE = unchecked((int)0x80131535);
+ internal const int COR_E_MEMBERACCESS = unchecked((int)0x8013151A);
+ internal const int COR_E_METHODACCESS = unchecked((int)0x80131510);
+ internal const int COR_E_MISSINGFIELD = unchecked((int)0x80131511);
+ internal const int COR_E_MISSINGMANIFESTRESOURCE = unchecked((int)0x80131532);
+ internal const int COR_E_MISSINGMEMBER = unchecked((int)0x80131512);
+ internal const int COR_E_MISSINGMETHOD = unchecked((int)0x80131513);
+ internal const int COR_E_MISSINGSATELLITEASSEMBLY = unchecked((int)0x80131536);
+ internal const int COR_E_MULTICASTNOTSUPPORTED = unchecked((int)0x80131514);
+ internal const int COR_E_NOTFINITENUMBER = unchecked((int)0x80131528);
+ internal const int COR_E_PLATFORMNOTSUPPORTED = unchecked((int)0x80131539);
+ internal const int COR_E_NOTSUPPORTED = unchecked((int)0x80131515);
+ internal const int COR_E_NULLREFERENCE = unchecked((int)0x80004003);
+ internal const int COR_E_OBJECTDISPOSED = unchecked((int)0x80131622);
+ internal const int COR_E_OPERATIONCANCELED = unchecked((int)0x8013153B);
+ internal const int COR_E_OUTOFMEMORY = unchecked((int)0x8007000E);
+ internal const int COR_E_OVERFLOW = unchecked((int)0x80131516);
+ internal const int COR_E_RANK = unchecked((int)0x80131517);
+ internal const int COR_E_REFLECTIONTYPELOAD = unchecked((int)0x80131602);
+ internal const int COR_E_RUNTIMEWRAPPED = unchecked((int)0x8013153E);
+ internal const int COR_E_SAFEARRAYRANKMISMATCH = unchecked((int)0x80131538);
+ internal const int COR_E_SAFEARRAYTYPEMISMATCH = unchecked((int)0x80131533);
+ internal const int COR_E_SAFEHANDLEMISSINGATTRIBUTE = unchecked((int)0x80131623);
+ internal const int COR_E_SECURITY = unchecked((int)0x8013150A);
+ internal const int COR_E_SERIALIZATION = unchecked((int)0x8013150C);
+ internal const int COR_E_SEMAPHOREFULL = unchecked((int)0x8013152B);
+ internal const int COR_E_WAITHANDLECANNOTBEOPENED = unchecked((int)0x8013152C);
+ internal const int COR_E_ABANDONEDMUTEX = unchecked((int)0x8013152D);
+ internal const int COR_E_STACKOVERFLOW = unchecked((int)0x800703E9);
+ internal const int COR_E_SYNCHRONIZATIONLOCK = unchecked((int)0x80131518);
+ internal const int COR_E_SYSTEM = unchecked((int)0x80131501);
+ internal const int COR_E_TARGET = unchecked((int)0x80131603);
+ internal const int COR_E_TARGETINVOCATION = unchecked((int)0x80131604);
+ internal const int COR_E_TARGETPARAMCOUNT = unchecked((int)0x8002000e);
+ internal const int COR_E_THREADABORTED = unchecked((int)0x80131530);
+ internal const int COR_E_THREADINTERRUPTED = unchecked((int)0x80131519);
+ internal const int COR_E_THREADSTATE = unchecked((int)0x80131520);
+ internal const int COR_E_THREADSTOP = unchecked((int)0x80131521);
+ internal const int COR_E_THREADSTART = unchecked((int)0x80131525);
+ internal const int COR_E_TYPEACCESS = unchecked((int)0x80131543);
+ internal const int COR_E_TYPEINITIALIZATION = unchecked((int)0x80131534);
+ internal const int COR_E_TYPELOAD = unchecked((int)0x80131522);
+ internal const int COR_E_ENTRYPOINTNOTFOUND = unchecked((int)0x80131523);
+ internal const int COR_E_DLLNOTFOUND = unchecked((int)0x80131524);
+ internal const int COR_E_UNAUTHORIZEDACCESS = unchecked((int)0x80070005);
+ internal const int COR_E_UNSUPPORTEDFORMAT = unchecked((int)0x80131523);
+ internal const int COR_E_VERIFICATION = unchecked((int)0x8013150D);
+ internal const int COR_E_HOSTPROTECTION = unchecked((int)0x80131640);
+ internal const int CORSEC_E_MIN_GRANT_FAIL = unchecked((int)0x80131417);
+ internal const int CORSEC_E_NO_EXEC_PERM = unchecked((int)0x80131418);
+ internal const int CORSEC_E_POLICY_EXCEPTION = unchecked((int)0x80131416);
+ internal const int CORSEC_E_XMLSYNTAX = unchecked((int)0x80131418);
+ internal const int NTE_FAIL = unchecked((int)0x80090020);
+ internal const int CORSEC_E_CRYPTO = unchecked((int)0x80131430);
+ internal const int CORSEC_E_CRYPTO_UNEX_OPER = unchecked((int)0x80131431);
+ internal const int DISP_E_OVERFLOW = unchecked((int)0x8002000a);
+ internal const int FUSION_E_REF_DEF_MISMATCH = unchecked((int)0x80131040);
+ internal const int FUSION_E_INVALID_NAME = unchecked((int)0x80131047);
+ internal const int TYPE_E_TYPEMISMATCH = unchecked((int)0x80028ca0);
+ }
+}
diff --git a/src/mscorlib/src/System/cominterfaces.cs b/src/mscorlib/src/System/cominterfaces.cs
new file mode 100644
index 0000000000..7d3620a22d
--- /dev/null
+++ b/src/mscorlib/src/System/cominterfaces.cs
@@ -0,0 +1,68 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.Serialization;
+using System.Security.Permissions;
+using System.Security.Policy;
+
+namespace System.Runtime.InteropServices
+{
+ [GuidAttribute("03973551-57A1-3900-A2B5-9083E3FF2943")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Activator))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Activator
+ {
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+ }
+
+ [GuidAttribute("917B14D0-2D9E-38B8-92A9-381ACF52F7C0")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Attribute))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Attribute
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+
+ [GuidAttribute("C281C7F1-4AA9-3517-961A-463CFED57E75")]
+ [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ [CLSCompliant(false)]
+ [TypeLibImportClassAttribute(typeof(System.Threading.Thread))]
+[System.Runtime.InteropServices.ComVisible(true)]
+ public interface _Thread
+ {
+#if !FEATURE_CORECLR
+ void GetTypeInfoCount(out uint pcTInfo);
+
+ void GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo);
+
+ void GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId);
+
+ void Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr);
+#endif
+ }
+}
diff --git a/src/mscorlib/src/System/mda.cs b/src/mscorlib/src/System/mda.cs
new file mode 100644
index 0000000000..089039c73c
--- /dev/null
+++ b/src/mscorlib/src/System/mda.cs
@@ -0,0 +1,88 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+
+namespace System
+{
+#if MDA_SUPPORTED
+ internal static class Mda
+ {
+ internal static class StreamWriterBufferedDataLost
+ {
+ // State: 0 (not queried); 1 (enabled); 2 (disabled)
+ private static volatile int _enabledState;
+ private static volatile int _captureAllocatedCallStackState;
+
+ internal static bool Enabled {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_enabledState == 0) {
+ if (Mda.IsStreamWriterBufferedDataLostEnabled())
+ _enabledState = 1;
+ else
+ _enabledState = 2;
+ }
+
+ return (_enabledState == 1);
+ }
+ }
+
+ internal static bool CaptureAllocatedCallStack {
+ [System.Security.SecuritySafeCritical] // auto-generated
+ get {
+ if (_captureAllocatedCallStackState == 0) {
+ if (Mda.IsStreamWriterBufferedDataLostCaptureAllocatedCallStack())
+ _captureAllocatedCallStackState = 1;
+ else
+ _captureAllocatedCallStackState = 2;
+ }
+
+ return (_captureAllocatedCallStackState == 1);
+ }
+ }
+
+ [System.Security.SecuritySafeCritical] // auto-generated
+ internal static void ReportError(String text) {
+ Mda.ReportStreamWriterBufferedDataLost(text);
+ }
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ReportStreamWriterBufferedDataLost(String text);
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsStreamWriterBufferedDataLostEnabled();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsStreamWriterBufferedDataLostCaptureAllocatedCallStack();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void MemberInfoCacheCreation();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void DateTimeInvalidLocalFormat();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern bool IsInvalidGCHandleCookieProbeEnabled();
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void FireInvalidGCHandleCookieProbe(IntPtr cookie);
+
+ [System.Security.SecurityCritical]
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ internal static extern void ReportErrorSafeHandleRelease(Exception ex);
+ }
+#endif
+}
diff --git a/src/mscorlib/src/mscorlib.Friends.cs b/src/mscorlib/src/mscorlib.Friends.cs
new file mode 100644
index 0000000000..fc8ed53fff
--- /dev/null
+++ b/src/mscorlib/src/mscorlib.Friends.cs
@@ -0,0 +1,27 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+using System.Runtime.CompilerServices;
+
+#if FEATURE_CORECLR
+// We need this to be able to typeforward to internal types
+[assembly: InternalsVisibleTo("mscorlib, PublicKey=00240000048000009400000006020000002400005253413100040000010001008d56c76f9e8649383049f383c44be0ec204181822a6c31cf5eb7ef486944d032188ea1d3920763712ccb12d75fb77e9811149e6148e5d32fbaab37611c1878ddc19e20ef135d0cb2cff2bfec3d115810c3d9069638fe4be215dbf795861920e5ab6f7db2e2ceef136ac23d5dd2bf031700aec232f6c6b1c785b4305c123b37ab", AllInternalsVisible=false)]
+#endif
+
+// For now we are only moving to using this file over AssemblyAttributes.cspp in CoreSys, ideally we would move away from the centralized
+// AssemblyAttributes.cspp model for the other build types at a future point in time.
+#if FEATURE_CORESYSTEM
+
+// Depends on things like SuppressUnmanagedCodeAttribute and WindowsRuntimeImportAttribute
+[assembly: InternalsVisibleTo("System.Runtime.WindowsRuntime, PublicKey=" + _InternalsVisibleToKeys.EcmaPublicKeyFull, AllInternalsVisible=false)]
+
+// Depends on WindowsRuntimeImportAttribute
+[assembly: InternalsVisibleTo("System.Runtime.WindowsRuntime.UI.Xaml, PublicKey=" + _InternalsVisibleToKeys.EcmaPublicKeyFull, AllInternalsVisible=false)]
+
+internal class _InternalsVisibleToKeys
+{
+ // Token = b77a5c561934e089
+ internal const string EcmaPublicKeyFull = "00000000000000000400000000000000";
+}
+
+#endif // FEATURE_CORESYS
diff --git a/src/mscorlib/src/mscorlib.txt b/src/mscorlib/src/mscorlib.txt
new file mode 100644
index 0000000000..01d593b778
--- /dev/null
+++ b/src/mscorlib/src/mscorlib.txt
@@ -0,0 +1,3494 @@
+; Licensed to the .NET Foundation under one or more agreements.
+; The .NET Foundation licenses this file to you under the MIT license.
+; See the LICENSE file in the project root for more information.
+
+; These are the managed resources for mscorlib.dll.
+; See those first three bytes in the file? This is in UTF-8. Leave the
+; Unicode byte order mark (U+FEFF) written in UTF-8 at the start of this file.
+
+; For resource info, see the ResourceManager documentation and the ResGen tool,
+; which is a managed app using ResourceWriter.
+; ResGen now supports limited preprocessing of txt files, you can use
+; #if SYMBOL and #if !SYMBOL to control what sets of resources are included in
+; the resulting resources.
+
+; The naming scheme is: [Namespace.] ExceptionName _ Reason
+; We'll suppress "System." where possible.
+; Examples:
+; Argument_Null
+; Reflection.TargetInvokation_someReason
+
+; Usage Notes:
+; * Keep exceptions in alphabetical order by package
+; * A single space may exist on either side of the equal sign.
+; * Follow the naming conventions.
+; * Any lines starting with a '#' or ';' are ignored
+; * Equal signs aren't legal characters for keys, but may occur in values.
+; * Correctly punctuate all sentences. Most resources should end in a period.
+; Remember, your mother will probably read some of these messages.
+; * You may use " (quote), \n and \t. Use \\ for a single '\' character.
+; * String inserts work. i.e., BadNumber_File = Wrong number in file "{0}".
+
+; Real words, used by code like Environment.StackTrace
+#if INCLUDE_RUNTIME
+Word_At = at
+StackTrace_InFileLineNumber = in {0}:line {1}
+UnknownError_Num = Unknown error "{0}".
+AllocatedFrom = Allocated from:
+
+; Note this one is special, used as a divider between stack traces!
+Exception_EndOfInnerExceptionStack = --- End of inner exception stack trace ---
+Exception_WasThrown = Exception of type '{0}' was thrown.
+
+; The following are used in the implementation of ExceptionDispatchInfo
+Exception_EndStackTraceFromPreviousThrow = --- End of stack trace from previous location where exception was thrown ---
+
+Arg_ParamName_Name = Parameter name: {0}
+ArgumentOutOfRange_ActualValue = Actual value was {0}.
+
+NoDebugResources = [{0}]\r\nArguments: {1}\r\nDebugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version={2}&File={3}&Key={4}
+#endif // INCLUDE_RUNTIME
+
+#if !FEATURE_CORECLR
+UnknownError = Unknown error.
+#endif // !FEATURE_CORECLR
+
+#if INCLUDE_DEBUG
+
+; For code contracts
+AssumptionFailed = Assumption failed.
+AssumptionFailed_Cnd = Assumption failed: {0}
+AssertionFailed = Assertion failed.
+AssertionFailed_Cnd = Assertion failed: {0}
+PreconditionFailed = Precondition failed.
+PreconditionFailed_Cnd = Precondition failed: {0}
+PostconditionFailed = Postcondition failed.
+PostconditionFailed_Cnd = Postcondition failed: {0}
+PostconditionOnExceptionFailed = Postcondition failed after throwing an exception.
+PostconditionOnExceptionFailed_Cnd = Postcondition failed after throwing an exception: {0}
+InvariantFailed = Invariant failed.
+InvariantFailed_Cnd = Invariant failed: {0}
+MustUseCCRewrite = An assembly (probably "{1}") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.{0} and the CONTRACTS_FULL symbol is defined. Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild. CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. \r\nAfter the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane. Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL.
+
+; Access Control
+#if FEATURE_MACL
+AccessControl_MustSpecifyContainerAcl = The named parameter must be a container ACL.
+AccessControl_MustSpecifyLeafObjectAcl = The named parameter must be a non-container ACL.
+AccessControl_AclTooLong = Length of the access control list exceed the allowed maximum.
+AccessControl_MustSpecifyDirectoryObjectAcl = The named parameter must be a directory-object ACL.
+AccessControl_MustSpecifyNonDirectoryObjectAcl = The named parameter must be a non-directory-object ACL.
+AccessControl_InvalidSecurityDescriptorRevision = Security descriptor with revision other than '1' are not legal.
+AccessControl_InvalidSecurityDescriptorSelfRelativeForm = Security descriptor must be in the self-relative form.
+AccessControl_NoAssociatedSecurity = Unable to perform a security operation on an object that has no associated security. This can happen when trying to get an ACL of an anonymous kernel object.
+AccessControl_InvalidHandle = The supplied handle is invalid. This can happen when trying to set an ACL on an anonymous kernel object.
+AccessControl_UnexpectedError = Method failed with unexpected error code {0}.
+AccessControl_InvalidSidInSDDLString = The SDDL string contains an invalid sid or a sid that cannot be translated.
+AccessControl_InvalidOwner = The security identifier is not allowed to be the owner of this object.
+AccessControl_InvalidGroup = The security identifier is not allowed to be the primary group of this object.
+AccessControl_InvalidAccessRuleType = The access rule is not the correct type.
+AccessControl_InvalidAuditRuleType = The audit rule is not the correct type.
+#endif // FEATURE_MACL
+
+; Identity Reference Library
+#if FEATURE_IDENTITY_REFERENCE
+IdentityReference_IdentityNotMapped = Some or all identity references could not be translated.
+IdentityReference_MustBeIdentityReference = The targetType parameter must be of IdentityReference type.
+IdentityReference_AccountNameTooLong = Account name is too long.
+IdentityReference_DomainNameTooLong = Domain name is too long.
+IdentityReference_InvalidNumberOfSubauthorities = The number of sub-authorities must not exceed {0}.
+IdentityReference_IdentifierAuthorityTooLarge = The size of the identifier authority must not exceed 6 bytes.
+IdentityReference_InvalidSidRevision = SIDs with revision other than '1' are not supported.
+IdentityReference_CannotCreateLogonIdsSid = Well-known SIDs of type LogonIdsSid cannot be created.
+IdentityReference_DomainSidRequired = The domainSid parameter must be specified for creating well-known SID of type {0}.
+IdentityReference_NotAWindowsDomain = The domainSid parameter is not a valid Windows domain SID.
+#endif // FEATURE_IDENTITY_REFERENCE
+
+; AccessException
+Acc_CreateGeneric = Cannot create a type for which Type.ContainsGenericParameters is true.
+Acc_CreateAbst = Cannot create an abstract class.
+Acc_CreateInterface = Cannot create an instance of an interface.
+Acc_NotClassInit = Type initializer was not callable.
+Acc_CreateGenericEx = Cannot create an instance of {0} because Type.ContainsGenericParameters is true.
+Acc_CreateArgIterator = Cannot dynamically create an instance of ArgIterator.
+Acc_CreateAbstEx = Cannot create an instance of {0} because it is an abstract class.
+Acc_CreateInterfaceEx = Cannot create an instance of {0} because it is an interface.
+Acc_CreateVoid = Cannot dynamically create an instance of System.Void.
+Acc_ReadOnly = Cannot set a constant field.
+Acc_RvaStatic = SkipVerification permission is needed to modify an image-based (RVA) static field.
+Access_Void = Cannot create an instance of void.
+
+; ArgumentException
+Arg_TypedReference_Null = The TypedReference must be initialized.
+Argument_AddingDuplicate__ = Item has already been added. Key in dictionary: '{0}' Key being added: '{1}'
+Argument_AddingDuplicate = An item with the same key has already been added.
+#if FEATURE_CORECLR
+Argument_AddingDuplicateWithKey = An item with the same key has already been added. Key: {0}
+#endif // FEATURE_CORECLR
+Argument_MethodDeclaringTypeGenericLcg = Method '{0}' has a generic declaring type '{1}'. Explicitly provide the declaring type to GetTokenFor.
+Argument_MethodDeclaringTypeGeneric = Cannot resolve method {0} because the declaring type of the method handle {1} is generic. Explicitly provide the declaring type to GetMethodFromHandle.
+Argument_FieldDeclaringTypeGeneric = Cannot resolve field {0} because the declaring type of the field handle {1} is generic. Explicitly provide the declaring type to GetFieldFromHandle.
+Argument_ApplicationTrustShouldHaveIdentity = An ApplicationTrust must have an application identity before it can be persisted.
+Argument_ConversionOverflow = Conversion buffer overflow.
+Argument_CodepageNotSupported = {0} is not a supported code page.
+Argument_CultureNotSupported = Culture is not supported.
+Argument_CultureInvalidIdentifier = {0} is an invalid culture identifier.
+Argument_OneOfCulturesNotSupported = Culture name {0} or {1} is not supported.
+Argument_CultureIetfNotSupported = Culture IETF Name {0} is not a recognized IETF name.
+Argument_CultureIsNeutral = Culture ID {0} (0x{0:X4}) is a neutral culture; a region cannot be created from it.
+Argument_InvalidNeutralRegionName = The region name {0} should not correspond to neutral culture; a specific culture name is required.
+Argument_InvalidGenericInstArray = Generic arguments must be provided for each generic parameter and each generic argument must be a RuntimeType.
+Argument_GenericArgsCount = The number of generic arguments provided doesn't equal the arity of the generic type definition.
+Argument_CultureInvalidFormat = Culture '{0}' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture.
+Argument_CompareOptionOrdinal = CompareOption.Ordinal cannot be used with other options.
+Argument_CustomCultureCannotBePassedByNumber = Customized cultures cannot be passed by LCID, only by name.
+Argument_EncodingConversionOverflowChars = The output char buffer is too small to contain the decoded characters, encoding '{0}' fallback '{1}'.
+Argument_EncodingConversionOverflowBytes = The output byte buffer is too small to contain the encoded data, encoding '{0}' fallback '{1}'.
+Argument_EncoderFallbackNotEmpty = Must complete Convert() operation or call Encoder.Reset() before calling GetBytes() or GetByteCount(). Encoder '{0}' fallback '{1}'.
+Argument_EmptyFileName = Empty file name is not legal.
+Argument_EmptyPath = Empty path name is not legal.
+Argument_EmptyName = Empty name is not legal.
+Argument_ImplementIComparable = At least one object must implement IComparable.
+Argument_InvalidType = The type of arguments passed into generic comparer methods is invalid.
+Argument_InvalidTypeForCA=Cannot build type parameter for custom attribute with a type that does not support the AssemblyQualifiedName property. The type instance supplied was of type '{0}'.
+Argument_IllegalEnvVarName = Environment variable name cannot contain equal character.
+Argument_IllegalAppId = Application identity does not have same number of components as manifest paths.
+Argument_IllegalAppBase = The application base specified is not valid.
+Argument_UnableToParseManifest = Unexpected error while parsing the specified manifest.
+Argument_IllegalAppIdMismatch = Application identity does not match identities in manifests.
+Argument_InvalidAppId = Invalid identity: no deployment or application identity specified.
+Argument_InvalidGenericArg = The generic type parameter was not valid
+Argument_InvalidArrayLength = Length of the array must be {0}.
+Argument_InvalidArrayType = Target array type is not compatible with the type of items in the collection.
+Argument_InvalidAppendMode = Append access can be requested only in write-only mode.
+Argument_InvalidEnumValue = The value '{0}' is not valid for this usage of the type {1}.
+Argument_EnumIsNotIntOrShort = The underlying type of enum argument must be Int32 or Int16.
+Argument_InvalidEnum = The Enum type should contain one and only one instance field.
+Argument_InvalidKeyStore = '{0}' is not a valid KeyStore name.
+Argument_InvalidFileMode&AccessCombo = Combining FileMode: {0} with FileAccess: {1} is invalid.
+Argument_InvalidFileMode&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid.
+Argument_InvalidFileModeTruncate&RightsCombo = Combining FileMode: {0} with FileSystemRights: {1} is invalid. FileMode.Truncate is valid only when used with FileSystemRights.Write.
+Argument_InvalidFlag = Value of flags is invalid.
+Argument_InvalidAnyFlag = No flags can be set.
+Argument_InvalidHandle = The handle is invalid.
+Argument_InvalidRegistryKeyPermissionCheck = The specified RegistryKeyPermissionCheck value is invalid.
+Argument_InvalidRegistryOptionsCheck = The specified RegistryOptions value is invalid.
+Argument_InvalidRegistryViewCheck = The specified RegistryView value is invalid.
+Argument_InvalidSubPath = The directory specified, '{0}', is not a subdirectory of '{1}'.
+Argument_NoRegionInvariantCulture = There is no region associated with the Invariant Culture (Culture ID: 0x7F).
+Argument_ResultCalendarRange = The result is out of the supported range for this calendar. The result should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive.
+Argument_ResultIslamicCalendarRange = The date is out of the supported range for the Islamic calendar. The date should be greater than July 18th, 622 AD (Gregorian date).
+Argument_NeverValidGenericArgument = The type '{0}' may not be used as a type argument.
+Argument_NotEnoughGenArguments = The type or method has {1} generic parameter(s), but {0} generic argument(s) were provided. A generic argument must be provided for each generic parameter.
+Argument_NullFullTrustAssembly = A null StrongName was found in the full trust assembly list.
+Argument_GenConstraintViolation = GenericArguments[{0}], '{1}', on '{2}' violates the constraint of type '{3}'.
+Argument_InvalidToken = Token {0:x} is not valid in the scope of module {1}.
+Argument_InvalidTypeToken = Token {0:x} is not a valid Type token.
+Argument_ResolveType = Token {0:x} is not a valid Type token in the scope of module {1}.
+Argument_ResolveMethod = Token {0:x} is not a valid MethodBase token in the scope of module {1}.
+Argument_ResolveField = Token {0:x} is not a valid FieldInfo token in the scope of module {1}.
+Argument_ResolveMember = Token {0:x} is not a valid MemberInfo token in the scope of module {1}.
+Argument_ResolveString = Token {0:x} is not a valid string token in the scope of module {1}.
+Argument_ResolveModuleType = Token {0} resolves to the special module type representing this module.
+Argument_ResolveMethodHandle = Type handle '{0}' and method handle with declaring type '{1}' are incompatible. Get RuntimeMethodHandle and declaring RuntimeTypeHandle off the same MethodBase.
+Argument_ResolveFieldHandle = Type handle '{0}' and field handle with declaring type '{1}' are incompatible. Get RuntimeFieldHandle and declaring RuntimeTypeHandle off the same FieldInfo.
+Argument_ResourceScopeWrongDirection = Resource type in the ResourceScope enum is going from a more restrictive resource type to a more general one. From: "{0}" To: "{1}"
+Argument_BadResourceScopeTypeBits = Unknown value for the ResourceScope: {0} Too many resource type bits may be set.
+Argument_BadResourceScopeVisibilityBits = Unknown value for the ResourceScope: {0} Too many resource visibility bits may be set.
+Argument_WaitHandleNameTooLong = The name can be no more than 260 characters in length.
+Argument_EnumTypeDoesNotMatch = The argument type, '{0}', is not the same as the enum type '{1}'.
+InvalidOperation_MethodBuilderBaked = The signature of the MethodBuilder can no longer be modified because an operation on the MethodBuilder caused the methodDef token to be created. For example, a call to SetCustomAttribute requires the methodDef token to emit the CustomAttribute token.
+InvalidOperation_GenericParametersAlreadySet = The generic parameters are already defined on this MethodBuilder.
+Arg_AccessException = Cannot access member.
+Arg_AppDomainUnloadedException = Attempted to access an unloaded AppDomain.
+Arg_ApplicationException = Error in the application.
+Arg_ArgumentOutOfRangeException = Specified argument was out of the range of valid values.
+Arg_ArithmeticException = Overflow or underflow in the arithmetic operation.
+Arg_ArrayLengthsDiffer = Array lengths must be the same.
+Arg_ArrayPlusOffTooSmall = Destination array is not long enough to copy all the items in the collection. Check array index and length.
+Arg_ArrayTypeMismatchException = Attempted to access an element as a type incompatible with the array.
+Arg_BadImageFormatException = Format of the executable (.exe) or library (.dll) is invalid.
+Argument_BadImageFormatExceptionResolve = A BadImageFormatException has been thrown while parsing the signature. This is likely due to lack of a generic context. Ensure genericTypeArguments and genericMethodArguments are provided and contain enough context.
+Arg_BufferTooSmall = Not enough space available in the buffer.
+Arg_CATypeResolutionFailed = Failed to resolve type from string "{0}" which was embedded in custom attribute blob.
+Arg_CannotHaveNegativeValue = String cannot contain a minus sign if the base is not 10.
+Arg_CannotUnloadAppDomainException = Attempt to unload the AppDomain failed.
+Arg_CannotMixComparisonInfrastructure = The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other.
+Arg_ContextMarshalException = Attempted to marshal an object across a context boundary.
+Arg_DataMisalignedException = A datatype misalignment was detected in a load or store instruction.
+Arg_DevicesNotSupported = FileStream will not open Win32 devices such as disk partitions and tape drives. Avoid use of "\\\\.\\" in the path.
+Arg_DuplicateWaitObjectException = Duplicate objects in argument.
+Arg_EntryPointNotFoundException = Entry point was not found.
+Arg_DllNotFoundException = Dll was not found.
+Arg_ExecutionEngineException = Internal error in the runtime.
+Arg_FieldAccessException = Attempted to access a field that is not accessible by the caller.
+Arg_FileIsDirectory_Name = The target file "{0}" is a directory, not a file.
+Arg_FormatException = One of the identified items was in an invalid format.
+Arg_IndexOutOfRangeException = Index was outside the bounds of the array.
+Arg_InsufficientExecutionStackException = Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space.
+Arg_InvalidCastException = Specified cast is not valid.
+Arg_InvalidOperationException = Operation is not valid due to the current state of the object.
+Arg_CorruptedCustomCultureFile = The file of the custom culture {0} is corrupt. Try to unregister this culture.
+Arg_InvokeMember = InvokeMember can be used only for COM objects.
+Arg_InvalidNeutralResourcesLanguage_Asm_Culture = The NeutralResourcesLanguageAttribute on the assembly "{0}" specifies an invalid culture name: "{1}".
+Arg_InvalidNeutralResourcesLanguage_FallbackLoc = The NeutralResourcesLanguageAttribute specifies an invalid or unrecognized ultimate resource fallback location: "{0}".
+Arg_InvalidSatelliteContract_Asm_Ver = Satellite contract version attribute on the assembly '{0}' specifies an invalid version: {1}.
+Arg_MethodAccessException = Attempt to access the method failed.
+Arg_MethodAccessException_WithMethodName = Attempt to access the method "{0}" on type "{1}" failed.
+Arg_MethodAccessException_WithCaller = Attempt by security transparent method '{0}' to access security critical method '{1}' failed.
+Arg_MissingFieldException = Attempted to access a non-existing field.
+Arg_MissingMemberException = Attempted to access a missing member.
+Arg_MissingMethodException = Attempted to access a missing method.
+Arg_MulticastNotSupportedException = Attempted to add multiple callbacks to a delegate that does not support multicast.
+Arg_NotFiniteNumberException = Number encountered was not a finite quantity.
+Arg_NotSupportedException = Specified method is not supported.
+Arg_UnboundGenParam = Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
+Arg_UnboundGenField = Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.
+Arg_NotGenericParameter = Method may only be called on a Type for which Type.IsGenericParameter is true.
+Arg_GenericParameter = Method must be called on a Type for which Type.IsGenericParameter is false.
+Arg_NotGenericTypeDefinition = {0} is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true.
+Arg_NotGenericMethodDefinition = {0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true.
+Arg_BadLiteralFormat = Encountered an invalid type for a default value.
+Arg_MissingActivationArguments = The AppDomainSetup must specify the activation arguments for this call.
+Argument_BadParameterTypeForCAB = Cannot emit a CustomAttribute with argument of type {0}.
+Argument_InvalidMemberForNamedArgument = The member must be either a field or a property.
+Argument_InvalidTypeName = The name of the type is invalid.
+
+; Note - don't change the NullReferenceException default message. This was
+; negotiated carefully with the VB team to avoid saying "null" or "nothing".
+Arg_NullReferenceException = Object reference not set to an instance of an object.
+
+Arg_AccessViolationException = Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
+Arg_OverflowException = Arithmetic operation resulted in an overflow.
+Arg_PathGlobalRoot = Paths that begin with \\\\?\\GlobalRoot are internal to the kernel and should not be opened by managed applications.
+Arg_PathIllegal = The path is not of a legal form.
+Arg_PathIllegalUNC = The UNC path should be of the form \\\\server\\share.
+Arg_RankException = Attempted to operate on an array with the incorrect number of dimensions.
+Arg_RankMultiDimNotSupported = Only single dimensional arrays are supported for the requested action.
+Arg_NonZeroLowerBound = The lower bound of target array must be zero.
+Arg_RegSubKeyValueAbsent = No value exists with that name.
+Arg_ResourceFileUnsupportedVersion = The ResourceReader class does not know how to read this version of .resources files. Expected version: {0} This file: {1}
+Arg_ResourceNameNotExist = The specified resource name "{0}" does not exist in the resource file.
+Arg_SecurityException = Security error.
+Arg_SerializationException = Serialization error.
+Arg_StackOverflowException = Operation caused a stack overflow.
+Arg_SurrogatesNotAllowedAsSingleChar = Unicode surrogate characters must be written out as pairs together in the same call, not individually. Consider passing in a character array instead.
+Arg_SynchronizationLockException = Object synchronization method was called from an unsynchronized block of code.
+Arg_RWLockRestoreException = ReaderWriterLock.RestoreLock was called without releasing all locks acquired since the call to ReleaseLock.
+Arg_SystemException = System error.
+Arg_TimeoutException = The operation has timed out.
+Arg_UnauthorizedAccessException = Attempted to perform an unauthorized operation.
+Arg_ArgumentException = Value does not fall within the expected range.
+Arg_DirectoryNotFoundException = Attempted to access a path that is not on the disk.
+Arg_DriveNotFoundException = Attempted to access a drive that is not available.
+Arg_EndOfStreamException = Attempted to read past the end of the stream.
+Arg_HexStyleNotSupported = The number style AllowHexSpecifier is not supported on floating point data types.
+Arg_IOException = I/O error occurred.
+Arg_InvalidHexStyle = With the AllowHexSpecifier bit set in the enum bit field, the only other valid bits that can be combined into the enum value must be a subset of those in HexNumber.
+Arg_KeyNotFound = The given key was not present in the dictionary.
+Argument_InvalidNumberStyles = An undefined NumberStyles value is being used.
+Argument_InvalidDateTimeStyles = An undefined DateTimeStyles value is being used.
+Argument_InvalidTimeSpanStyles = An undefined TimeSpanStyles value is being used.
+Argument_DateTimeOffsetInvalidDateTimeStyles = The DateTimeStyles value 'NoCurrentDateDefault' is not allowed when parsing DateTimeOffset.
+Argument_NativeResourceAlreadyDefined = Native resource has already been defined.
+Argument_BadObjRef = Invalid ObjRef provided to '{0}'.
+Argument_InvalidCultureName = Culture name '{0}' is not supported.
+Argument_NameTooLong = The name '{0}' is too long to be a Culture or Region name, which is limited to {1} characters.
+Argument_NameContainsInvalidCharacters = The name '{0}' contains characters that are not valid for a Culture or Region.
+Argument_InvalidRegionName = Region name '{0}' is not supported.
+Argument_CannotCreateTypedReference = Cannot use function evaluation to create a TypedReference object.
+Arg_ArrayZeroError = Array must not be of length zero.
+Arg_BogusIComparer = Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: '{0}'.
+Arg_CreatInstAccess = Cannot specify both CreateInstance and another access type.
+Arg_CryptographyException = Error occurred during a cryptographic operation.
+Arg_DateTimeRange = Combination of arguments to the DateTime constructor is out of the legal range.
+Arg_DecBitCtor = Decimal byte array constructor requires an array of length four containing valid decimal bytes.
+Arg_DlgtTargMeth = Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
+Arg_DlgtTypeMis = Delegates must be of the same type.
+Arg_DlgtNullInst = Delegate to an instance method cannot have null 'this'.
+Arg_DllInitFailure = One machine may not have remote administration enabled, or both machines may not be running the remote registry service.
+Arg_EmptyArray = Array may not be empty.
+Arg_EmptyOrNullArray = Array may not be empty or null.
+Arg_EmptyCollection = Collection must not be empty.
+Arg_EmptyOrNullString = String may not be empty or null.
+Argument_ItemNotExist = The specified item does not exist in this KeyedCollection.
+Argument_EncodingNotSupported = '{0}' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
+Argument_FallbackBufferNotEmpty = Cannot change fallback when buffer is not empty. Previous Convert() call left data in the fallback buffer.
+Argument_InvalidCodePageConversionIndex = Unable to translate Unicode character \\u{0:X4} at index {1} to specified code page.
+Argument_InvalidCodePageBytesIndex = Unable to translate bytes {0} at index {1} from specified code page to Unicode.
+Argument_RecursiveFallback = Recursive fallback not allowed for character \\u{0:X4}.
+Argument_RecursiveFallbackBytes = Recursive fallback not allowed for bytes {0}.
+Arg_EnumAndObjectMustBeSameType = Object must be the same type as the enum. The type passed in was '{0}'; the enum type was '{1}'.
+Arg_EnumIllegalVal = Illegal enum value: {0}.
+Arg_EnumNotSingleFlag = Must set exactly one flag.
+Arg_EnumAtLeastOneFlag = Must set at least one flag.
+Arg_EnumUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object must be a String. Type passed in was '{0}'; the enum underlying type was '{1}'.
+Arg_EnumFormatUnderlyingTypeAndObjectMustBeSameType = Enum underlying type and the object must be same type or object. Type passed in was '{0}'; the enum underlying type was '{1}'.
+Arg_EnumMustHaveUnderlyingValueField = All enums must have an underlying value__ field.
+Arg_COMAccess = Must specify property Set or Get or method call for a COM Object.
+Arg_COMPropSetPut = Only one of the following binding flags can be set: BindingFlags.SetProperty, BindingFlags.PutDispProperty, BindingFlags.PutRefDispProperty.
+Arg_FldSetGet = Cannot specify both Get and Set on a field.
+Arg_PropSetGet = Cannot specify both Get and Set on a property.
+Arg_CannotBeNaN = TimeSpan does not accept floating point Not-a-Number values.
+Arg_FldGetPropSet = Cannot specify both GetField and SetProperty.
+Arg_FldSetPropGet = Cannot specify both SetField and GetProperty.
+Arg_FldSetInvoke = Cannot specify Set on a Field and Invoke on a method.
+Arg_FldGetArgErr = No arguments can be provided to Get a field value.
+Arg_FldSetArgErr = Only the field value can be specified to set a field value.
+Arg_GetMethNotFnd = Property Get method was not found.
+Arg_GuidArrayCtor = Byte array for GUID must be exactly {0} bytes long.
+Arg_HandleNotAsync = Handle does not support asynchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened synchronously (that is, it was not opened for overlapped I/O).
+Arg_HandleNotSync = Handle does not support synchronous operations. The parameters to the FileStream constructor may need to be changed to indicate that the handle was opened asynchronously (that is, it was opened explicitly for overlapped I/O).
+Arg_HTCapacityOverflow = Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.
+Arg_IndexMustBeInt = All indexes must be of type Int32.
+Arg_InvalidConsoleColor = The ConsoleColor enum value was not defined on that enum. Please use a defined color from the enum.
+Arg_InvalidFileAttrs = Invalid File or Directory attributes value.
+Arg_InvalidHandle = Invalid handle.
+Arg_InvalidTypeInSignature = The signature Type array contains some invalid type (i.e. null, void)
+Arg_InvalidTypeInRetType = The return Type contains some invalid type (i.e. null, ByRef)
+Arg_EHClauseNotFilter = This ExceptionHandlingClause is not a filter.
+Arg_EHClauseNotClause = This ExceptionHandlingClause is not a clause.
+Arg_ReflectionOnlyCA = It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType (see Assembly.ReflectionOnly) -- use CustomAttributeData instead.
+Arg_ReflectionOnlyInvoke = It is illegal to invoke a method on a Type loaded via ReflectionOnlyGetType.
+Arg_ReflectionOnlyField = It is illegal to get or set the value on a field on a Type loaded via ReflectionOnlyGetType.
+Arg_MemberInfoNullModule = The Module object containing the member cannot be null.
+Arg_ParameterInfoNullMember = The MemberInfo object defining the parameter cannot be null.
+Arg_ParameterInfoNullModule = The Module object containing the parameter cannot be null.
+Arg_AssemblyNullModule = The manifest module of the assembly cannot be null.
+Arg_LongerThanSrcArray = Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
+Arg_LongerThanDestArray = Destination array was not long enough. Check destIndex and length, and the array's lower bounds.
+Arg_LowerBoundsMustMatch = The arrays' lower bounds must be identical.
+Arg_MustBeBoolean = Object must be of type Boolean.
+Arg_MustBeByte = Object must be of type Byte.
+Arg_MustBeChar = Object must be of type Char.
+Arg_MustBeDateTime = Object must be of type DateTime.
+Arg_MustBeDateTimeOffset = Object must be of type DateTimeOffset.
+Arg_MustBeDecimal = Object must be of type Decimal.
+Arg_MustBeDelegate = Type must derive from Delegate.
+Arg_MustBeDouble = Object must be of type Double.
+Arg_MustBeDriveLetterOrRootDir = Object must be a root directory ("C:\\") or a drive letter ("C").
+Arg_MustBeEnum = Type provided must be an Enum.
+Arg_MustBeEnumBaseTypeOrEnum = The value passed in must be an enum base or an underlying type for an enum, such as an Int32.
+Arg_MustBeGuid = Object must be of type GUID.
+Arg_MustBeIdentityReferenceType = Type must be an IdentityReference, such as NTAccount or SecurityIdentifier.
+Arg_MustBeInterface = Type passed must be an interface.
+Arg_MustBeInt16 = Object must be of type Int16.
+Arg_MustBeInt32 = Object must be of type Int32.
+Arg_MustBeInt64 = Object must be of type Int64.
+Arg_MustBePrimArray = Object must be an array of primitives.
+Arg_MustBePointer = Type must be a Pointer.
+Arg_MustBeStatic = Method must be a static method.
+Arg_MustBeString = Object must be of type String.
+Arg_MustBeStringPtrNotAtom = The pointer passed in as a String must not be in the bottom 64K of the process's address space.
+Arg_MustBeSByte = Object must be of type SByte.
+Arg_MustBeSingle = Object must be of type Single.
+Arg_MustBeTimeSpan = Object must be of type TimeSpan.
+Arg_MustBeType = Type must be a type provided by the runtime.
+Arg_MustBeUInt16 = Object must be of type UInt16.
+Arg_MustBeUInt32 = Object must be of type UInt32.
+Arg_MustBeUInt64 = Object must be of type UInt64.
+Arg_MustBeVersion = Object must be of type Version.
+Arg_MustBeTrue = Argument must be true.
+Arg_MustAllBeRuntimeType = At least one type argument is not a runtime type.
+Arg_NamedParamNull = Named parameter value must not be null.
+Arg_NamedParamTooBig = Named parameter array cannot be bigger than argument array.
+Arg_Need1DArray = Array was not a one-dimensional array.
+Arg_Need2DArray = Array was not a two-dimensional array.
+Arg_Need3DArray = Array was not a three-dimensional array.
+Arg_NeedAtLeast1Rank = Must provide at least one rank.
+Arg_NoDefCTor = No parameterless constructor defined for this object.
+Arg_BitArrayTypeUnsupported = Only supported array types for CopyTo on BitArrays are Boolean[], Int32[] and Byte[].
+Arg_DivideByZero = Attempted to divide by zero.
+Arg_NoAccessSpec = Must specify binding flags describing the invoke operation required (BindingFlags.InvokeMethod CreateInstance GetField SetField GetProperty SetProperty).
+Arg_NoStaticVirtual = Method cannot be both static and virtual.
+Arg_NotFoundIFace = Interface not found.
+Arg_ObjObjEx = Object of type '{0}' cannot be converted to type '{1}'.
+Arg_ObjObj = Object type cannot be converted to target type.
+Arg_FieldDeclTarget = Field '{0}' defined on type '{1}' is not a field on the target object which is of type '{2}'.
+Arg_OleAutDateInvalid = Not a legal OleAut date.
+Arg_OleAutDateScale = OleAut date did not convert to a DateTime correctly.
+Arg_PlatformNotSupported = Operation is not supported on this platform.
+Arg_PlatformSecureString = SecureString is only supported on Windows 2000 SP3 and higher platforms.
+Arg_ParmCnt = Parameter count mismatch.
+Arg_ParmArraySize = Must specify one or more parameters.
+Arg_Path2IsRooted = Second path fragment must not be a drive or UNC name.
+Arg_PathIsVolume = Path must not be a drive.
+Arg_PrimWiden = Cannot widen from source type to target type either because the source type is a not a primitive type or the conversion cannot be accomplished.
+Arg_NullIndex = Arrays indexes must be set to an object instance.
+Arg_VarMissNull = Missing parameter does not have a default value.
+Arg_PropSetInvoke = Cannot specify Set on a property and Invoke on a method.
+Arg_PropNotFound = Could not find the specified property.
+Arg_RankIndices = Indices length does not match the array rank.
+Arg_RanksAndBounds = Number of lengths and lowerBounds must match.
+Arg_RegSubKeyAbsent = Cannot delete a subkey tree because the subkey does not exist.
+Arg_RemoveArgNotFound = Cannot remove the specified item because it was not found in the specified Collection.
+Arg_RegKeyDelHive = Cannot delete a registry hive's subtree.
+Arg_RegKeyNoRemoteConnect = No remote connection to '{0}' while trying to read the registry.
+Arg_RegKeyOutOfRange = Registry HKEY was out of the legal range.
+Arg_RegKeyNotFound = The specified registry key does not exist.
+Arg_RegKeyStrLenBug = Registry key names should not be greater than 255 characters.
+Arg_RegValStrLenBug = Registry value names should not be greater than 16,383 characters.
+Arg_RegBadKeyKind = The specified RegistryValueKind is an invalid value.
+Arg_RegGetOverflowBug = RegistryKey.GetValue does not allow a String that has a length greater than Int32.MaxValue.
+Arg_RegSetMismatchedKind = The type of the value object did not match the specified RegistryValueKind or the object could not be properly converted.
+Arg_RegSetBadArrType = RegistryKey.SetValue does not support arrays of type '{0}'. Only Byte[] and String[] are supported.
+Arg_RegSetStrArrNull = RegistryKey.SetValue does not allow a String[] that contains a null String reference.
+Arg_RegInvalidKeyName = Registry key name must start with a valid base key name.
+Arg_ResMgrNotResSet = Type parameter must refer to a subclass of ResourceSet.
+Arg_SetMethNotFnd = Property set method not found.
+Arg_TypeRefPrimitve = TypedReferences cannot be redefined as primitives.
+Arg_UnknownTypeCode = Unknown TypeCode value.
+Arg_VersionString = Version string portion was too short or too long.
+Arg_NoITypeInfo = Specified TypeInfo was invalid because it did not support the ITypeInfo interface.
+Arg_NoITypeLib = Specified TypeLib was invalid because it did not support the ITypeLib interface.
+Arg_NoImporterCallback = Specified type library importer callback was invalid because it did not support the ITypeLibImporterNotifySink interface.
+Arg_ImporterLoadFailure = The type library importer encountered an error during type verification. Try importing without class members.
+Arg_InvalidBase = Invalid Base.
+Arg_EnumValueNotFound = Requested value '{0}' was not found.
+Arg_EnumLitValueNotFound = Literal value was not found.
+Arg_MustContainEnumInfo = Must specify valid information for parsing in the string.
+Arg_InvalidSearchPattern = Search pattern cannot contain ".." to move up directories and can be contained only internally in file/directory names, as in "a..b".
+Arg_NegativeArgCount = Argument count must not be negative.
+Arg_InvalidAccessEntry = Specified access entry is invalid because it is unrestricted. The global flags should be specified instead.
+Arg_InvalidFileName = Specified file name was invalid.
+Arg_InvalidFileExtension = Specified file extension was not a valid extension.
+Arg_COMException = Error HRESULT E_FAIL has been returned from a call to a COM component.
+Arg_ExternalException = External component has thrown an exception.
+Arg_InvalidComObjectException = Attempt has been made to use a COM object that does not have a backing class factory.
+Arg_InvalidOleVariantTypeException = Specified OLE variant was invalid.
+Arg_MarshalDirectiveException = Marshaling directives are invalid.
+Arg_MarshalAsAnyRestriction = AsAny cannot be used on return types, ByRef parameters, ArrayWithOffset, or parameters passed from unmanaged to managed.
+Arg_NDirectBadObject = No PInvoke conversion exists for value passed to Object-typed parameter.
+Arg_SafeArrayTypeMismatchException = Specified array was not of the expected type.
+Arg_VTableCallsNotSupportedException = Attempted to make an early bound call on a COM dispatch-only interface.
+Arg_SafeArrayRankMismatchException = Specified array was not of the expected rank.
+Arg_AmbiguousMatchException = Ambiguous match found.
+Arg_CustomAttributeFormatException = Binary format of the specified custom attribute was invalid.
+Arg_InvalidFilterCriteriaException = Specified filter criteria was invalid.
+Arg_TypeLoadNullStr = A null or zero length string does not represent a valid Type.
+Arg_TargetInvocationException = Exception has been thrown by the target of an invocation.
+Arg_TargetParameterCountException = Number of parameters specified does not match the expected number.
+Arg_TypeAccessException = Attempt to access the type failed.
+Arg_TypeLoadException = Failure has occurred while loading a type.
+Arg_TypeUnloadedException = Type had been unloaded.
+Arg_ThreadStateException = Thread was in an invalid state for the operation being executed.
+Arg_ThreadStartException = Thread failed to start.
+Arg_WrongAsyncResult = IAsyncResult object did not come from the corresponding async method on this type.
+Arg_WrongType = The value "{0}" is not of type "{1}" and cannot be used in this generic collection.
+Argument_InvalidArgumentForComparison = Type of argument is not compatible with the generic comparer.
+Argument_ALSInvalidCapacity = Specified capacity must not be less than the current capacity.
+Argument_ALSInvalidSlot = Specified slot number was invalid.
+Argument_IdnIllegalName = Decoded string is not a valid IDN name.
+Argument_IdnBadBidi = Left to right characters may not be mixed with right to left characters in IDN labels.
+Argument_IdnBadLabelSize = IDN labels must be between 1 and 63 characters long.
+Argument_IdnBadNameSize = IDN names must be between 1 and {0} characters long.
+Argument_IdnBadPunycode = Invalid IDN encoded string.
+Argument_IdnBadStd3 = Label contains character '{0}' not allowed with UseStd3AsciiRules
+Arg_InvalidANSIString = The ANSI string passed in could not be converted from the default ANSI code page to Unicode.
+Arg_InvalidUTF8String = The UTF8 string passed in could not be converted to Unicode.
+Argument_InvalidCharSequence = Invalid Unicode code point found at index {0}.
+Argument_InvalidCharSequenceNoIndex = String contains invalid Unicode code points.
+Argument_InvalidCalendar = Not a valid calendar for the given culture.
+Argument_InvalidNormalizationForm = Invalid or unsupported normalization form.
+Argument_InvalidPathChars = Illegal characters in path.
+Argument_InvalidOffLen = Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
+Argument_InvalidSeekOrigin = Invalid seek origin.
+Argument_SeekOverflow = The specified seek offset '{0}' would result in a negative Stream position.
+Argument_InvalidUnity = Invalid Unity type.
+Argument_LongEnvVarName = Environment variable name cannot contain 1024 or more characters.
+Argument_LongEnvVarValue = Environment variable name or value is too long.
+Argument_StringFirstCharIsZero = The first char in the string is the null character.
+Argument_OnlyMscorlib = Only mscorlib's assembly is valid.
+Argument_PathEmpty = Path cannot be the empty string or all whitespace.
+Argument_PathFormatNotSupported = The given path's format is not supported.
+Argument_PathUriFormatNotSupported = URI formats are not supported.
+Argument_TypeNameTooLong = Type name was too long. The fully qualified type name must be less than 1,024 characters.
+Argument_StreamNotReadable = Stream was not readable.
+Argument_StreamNotWritable = Stream was not writable.
+Argument_InvalidNumberOfMembers = MemberData contains an invalid number of members.
+Argument_InvalidValue = Value was invalid.
+Argument_InvalidKey = Key was invalid.
+Argument_MinMaxValue = '{0}' cannot be greater than {1}.
+Argument_InvalidGroupSize = Every element in the value array should be between one and nine, except for the last element, which can be zero.
+Argument_MustHaveAttributeBaseClass = Type passed in must be derived from System.Attribute or System.Attribute itself.
+Argument_NoUninitializedStrings = Uninitialized Strings cannot be created.
+Argument_UnequalMembers = Supplied MemberInfo does not match the expected type.
+Argument_BadFormatSpecifier = Format specifier was invalid.
+Argument_InvalidHighSurrogate = Found a high surrogate char without a following low surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters.
+Argument_InvalidLowSurrogate = Found a low surrogate char without a preceding high surrogate at index: {0}. The input may not be in this encoding, or may not contain valid Unicode (UTF-16) characters.
+Argument_UnmatchingSymScope = Non-matching symbol scope.
+Argument_NotInExceptionBlock = Not currently in an exception block.
+Argument_BadExceptionCodeGen = Incorrect code generation for exception block.
+Argument_NotExceptionType = Does not extend Exception.
+Argument_DuplicateResourceName = Duplicate resource name within an assembly.
+Argument_BadPersistableModuleInTransientAssembly = Cannot have a persistable module in a transient assembly.
+Argument_InvalidPermissionState = Invalid permission state.
+Argument_UnrestrictedIdentityPermission = Identity permissions cannot be unrestricted.
+Argument_WrongType = Operation on type '{0}' attempted with target of incorrect type.
+Argument_IllegalZone = Illegal security permission zone specified.
+Argument_HasToBeArrayClass = Must be an array type.
+Argument_InvalidDirectory = Invalid directory, '{0}'.
+Argument_DataLengthDifferent = Parameters 'members' and 'data' must have the same length.
+Argument_SigIsFinalized = Completed signature cannot be modified.
+Argument_ArraysInvalid = Array or pointer types are not valid.
+Argument_GenericsInvalid = Generic types are not valid.
+Argument_LargeInteger = Integer or token was too large to be encoded.
+Argument_BadSigFormat = Incorrect signature format.
+Argument_UnmatchedMethodForLocal = Local passed in does not belong to this ILGenerator.
+Argument_DuplicateName = Tried to add NamedPermissionSet with non-unique name.
+Argument_InvalidXMLElement = Invalid XML. Missing required tag <{0}> for type '{1}'.
+Argument_InvalidXMLMissingAttr = Invalid XML. Missing required attribute '{0}'.
+Argument_CannotGetTypeTokenForByRef = Cannot get TypeToken for a ByRef type.
+Argument_NotASimpleNativeType = The UnmanagedType passed to DefineUnmanagedMarshal is not a simple type. None of the following values may be used: UnmanagedType.ByValTStr, UnmanagedType.SafeArray, UnmanagedType.ByValArray, UnmanagedType.LPArray, UnmanagedType.CustomMarshaler.
+Argument_NotACustomMarshaler = Not a custom marshal.
+Argument_NoUnmanagedElementCount = Unmanaged marshal does not have ElementCount.
+Argument_NoNestedMarshal = Only LPArray or SafeArray has nested unmanaged marshal.
+Argument_InvalidXML = Invalid Xml.
+Argument_NoUnderlyingCCW = The object has no underlying COM data associated with it.
+Argument_BadFieldType = Bad field type in defining field.
+Argument_InvalidXMLBadVersion = Invalid Xml - can only parse elements of version one.
+Argument_NotAPermissionElement = 'elem' was not a permission element.
+Argument_NPMSInvalidName = Name can be neither null nor empty.
+Argument_InvalidElementTag = Invalid element tag '{0}'.
+Argument_InvalidElementText = Invalid element text '{0}'.
+Argument_InvalidElementName = Invalid element name '{0}'.
+Argument_InvalidElementValue = Invalid element value '{0}'.
+Argument_AttributeNamesMustBeUnique = Attribute names must be unique.
+#if FEATURE_CAS_POLICY
+Argument_UninitializedCertificate = Uninitialized certificate object.
+Argument_MembershipConditionElement = Element must be a <IMembershipCondition> element.
+Argument_ReservedNPMS = Cannot remove or modify reserved permissions set '{0}'.
+Argument_NPMSInUse = Permission set '{0}' was in use and could not be deleted.
+Argument_StrongNameGetPublicKey = Unable to obtain public key for StrongNameKeyPair.
+Argument_SiteCannotBeNull = Site name must be specified.
+Argument_BlobCannotBeNull = Public key must be specified.
+Argument_ZoneCannotBeNull = Zone must be specified.
+Argument_UrlCannotBeNull = URL must be specified.
+Argument_NoNPMS = Unable to find a permission set with the provided name.
+Argument_FailedCodeGroup = Failed to create a code group of type '{0}'.
+Argument_CodeGroupChildrenMustBeCodeGroups = All objects in the input list must have a parent type of 'CodeGroup'.
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_IMPERSONATION
+Argument_InvalidPrivilegeName = Privilege '{0}' is not valid on this system.
+Argument_TokenZero = Token cannot be zero.
+Argument_InvalidImpersonationToken = Invalid token for impersonation - it cannot be duplicated.
+Argument_ImpersonateUser = Unable to impersonate user.
+#endif // FEATURE_IMPERSONATION
+Argument_InvalidHexFormat = Improperly formatted hex string.
+Argument_InvalidSite = Invalid site.
+Argument_InterfaceMap = 'this' type cannot be an interface itself.
+Argument_ArrayGetInterfaceMap = Interface maps for generic interfaces on arrays cannot be retrieved.
+Argument_InvalidName = Invalid name.
+Argument_InvalidDirectoryOnUrl = Invalid directory on URL.
+Argument_InvalidUrl = Invalid URL.
+Argument_InvalidKindOfTypeForCA = This type cannot be represented as a custom attribute.
+Argument_MustSupplyContainer = When supplying a FieldInfo for fixing up a nested type, a valid ID for that containing object must also be supplied.
+Argument_MustSupplyParent = When supplying the ID of a containing object, the FieldInfo that identifies the current field within that object must also be supplied.
+Argument_NoClass = Element does not specify a class.
+Argument_WrongElementType = '{0}' element required.
+Argument_UnableToGeneratePermissionSet = Unable to generate permission set; input XML may be malformed.
+Argument_NoEra = No Era was supplied.
+Argument_AssemblyAlreadyFullTrust = Assembly was already fully trusted.
+Argument_AssemblyNotFullTrust = Assembly was not fully trusted.
+Argument_AssemblyWinMD = Assembly must not be a Windows Runtime assembly.
+Argument_MemberAndArray = Cannot supply both a MemberInfo and an Array to indicate the parent of a value type.
+Argument_ObjNotComObject = The object's type must be __ComObject or derived from __ComObject.
+Argument_ObjIsWinRTObject = The object's type must not be a Windows Runtime type.
+Argument_TypeNotComObject = The type must be __ComObject or be derived from __ComObject.
+Argument_TypeIsWinRTType = The type must not be a Windows Runtime type.
+Argument_CantCallSecObjFunc = Cannot evaluate a security function.
+Argument_StructMustNotBeValueClass = The structure must not be a value class.
+Argument_NoSpecificCulture = Please select a specific culture, such as zh-CN, zh-HK, zh-TW, zh-MO, zh-SG.
+Argument_InvalidResourceCultureName = The given culture name '{0}' cannot be used to locate a resource file. Resource filenames must consist of only letters, numbers, hyphens or underscores.
+Argument_InvalidParamInfo = Invalid type for ParameterInfo member in Attribute class.
+Argument_EmptyDecString = Decimal separator cannot be the empty string.
+Argument_OffsetOfFieldNotFound = Field passed in is not a marshaled member of the type '{0}'.
+Argument_EmptyStrongName = StrongName cannot have an empty string for the assembly name.
+Argument_NotSerializable = Argument passed in is not serializable.
+Argument_EmptyApplicationName = ApplicationId cannot have an empty string for the name.
+Argument_NoDomainManager = The domain manager specified by the host could not be instantiated.
+Argument_NoMain = Main entry point not defined.
+Argument_InvalidDateTimeKind = Invalid DateTimeKind value.
+Argument_ConflictingDateTimeStyles = The DateTimeStyles values AssumeLocal and AssumeUniversal cannot be used together.
+Argument_ConflictingDateTimeRoundtripStyles = The DateTimeStyles value RoundtripKind cannot be used with the values AssumeLocal, AssumeUniversal or AdjustToUniversal.
+Argument_InvalidDigitSubstitution = The DigitSubstitution property must be of a valid member of the DigitShapes enumeration. Valid entries include Context, NativeNational or None.
+Argument_InvalidNativeDigitCount = The NativeDigits array must contain exactly ten members.
+Argument_InvalidNativeDigitValue = Each member of the NativeDigits array must be a single text element (one or more UTF16 code points) with a Unicode Nd (Number, Decimal Digit) property indicating it is a digit.
+ArgumentException_InvalidAceBinaryForm = The binary form of an ACE object is invalid.
+ArgumentException_InvalidAclBinaryForm = The binary form of an ACL object is invalid.
+ArgumentException_InvalidSDSddlForm = The SDDL form of a security descriptor object is invalid.
+Argument_InvalidSafeHandle = The SafeHandle is invalid.
+Argument_CannotPrepareAbstract = Abstract methods cannot be prepared.
+Argument_ArrayTooLarge = The input array length must not exceed Int32.MaxValue / {0}. Otherwise BitArray.Length would exceed Int32.MaxValue.
+Argument_RelativeUrlMembershipCondition = UrlMembershipCondition requires an absolute URL.
+Argument_EmptyWaithandleArray = Waithandle array may not be empty.
+Argument_InvalidSafeBufferOffLen = Offset and length were greater than the size of the SafeBuffer.
+Argument_NotEnoughBytesToRead = There are not enough bytes remaining in the accessor to read at this position.
+Argument_NotEnoughBytesToWrite = There are not enough bytes remaining in the accessor to write at this position.
+Argument_OffsetAndLengthOutOfBounds = Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection.
+Argument_OffsetAndCapacityOutOfBounds = Offset and capacity were greater than the size of the view.
+Argument_UnmanagedMemAccessorWrapAround = The UnmanagedMemoryAccessor capacity and offset would wrap around the high end of the address space.
+Argument_UnrecognizedLoaderOptimization = Unrecognized LOADER_OPTIMIZATION property value. Supported values may include "SingleDomain", "MultiDomain", "MultiDomainHost", and "NotSpecified".
+ArgumentException_NotAllCustomSortingFuncsDefined = Implementations of all the NLS functions must be provided.
+ArgumentException_MinSortingVersion = The runtime does not support a version of "{0}" less than {1}.
+
+;
+; =====================================================
+; Reflection Emit resource strings
+Arugment_EmitMixedContext1 = Type '{0}' was loaded in the ReflectionOnly context but the AssemblyBuilder was not created as AssemblyBuilderAccess.ReflectionOnly.
+Arugment_EmitMixedContext2 = Type '{0}' was not loaded in the ReflectionOnly context but the AssemblyBuilder was created as AssemblyBuilderAccess.ReflectionOnly.
+Argument_BadSizeForData = Data size must be > 0 and < 0x3f0000
+Argument_InvalidLabel = Invalid Label.
+Argument_RedefinedLabel = Label multiply defined.
+Argument_UnclosedExceptionBlock = The IL Generator cannot be used while there are unclosed exceptions.
+Argument_MissingDefaultConstructor = was missing default constructor.
+Argument_TooManyFinallyClause = Exception blocks may have at most one finally clause.
+Argument_NotInTheSameModuleBuilder = The argument passed in was not from the same ModuleBuilder.
+Argument_BadCurrentLocalVariable = Bad current local variable for setting symbol information.
+Argument_DuplicateModuleName = Duplicate dynamic module name within an assembly.
+Argument_DuplicateTypeName = Duplicate type name within an assembly.
+Argument_InvalidAssemblyName = Assembly names may not begin with whitespace or contain the characters '/', or '\\' or ':'.
+Argument_InvalidGenericInstantiation = The given generic instantiation was invalid.
+Argument_DuplicatedFileName = Duplicate file names.
+Argument_GlobalFunctionHasToBeStatic = Global members must be static.
+Argument_BadPInvokeOnInterface = PInvoke methods cannot exist on interfaces.
+Argument_BadPInvokeMethod = PInvoke methods must be static and native and cannot be abstract.
+Argument_MethodRedefined = Method has been already defined.
+Argument_BadTypeAttrAbstractNFinal = Bad type attributes. A type cannot be both abstract and final.
+Argument_BadTypeAttrNestedVisibilityOnNonNestedType = Bad type attributes. Nested visibility flag set on a non-nested type.
+Argument_BadTypeAttrNonNestedVisibilityNestedType = Bad type attributes. Non-nested visibility flag set on a nested type.
+Argument_BadTypeAttrInvalidLayout = Bad type attributes. Invalid layout attribute specified.
+Argument_BadTypeAttrReservedBitsSet = Bad type attributes. Reserved bits set on the type.
+Argument_BadFieldSig = Field signatures do not have return types.
+Argument_ShouldOnlySetVisibilityFlags = Should only set visibility flags when creating EnumBuilder.
+Argument_BadNestedTypeFlags = Visibility of interfaces must be one of the following: NestedAssembly, NestedFamANDAssem, NestedFamily, NestedFamORAssem, NestedPrivate or NestedPublic.
+Argument_ShouldNotSpecifyExceptionType = Should not specify exception type for catch clause for filter block.
+Argument_BadLabel = Bad label in ILGenerator.
+Argument_BadLabelContent = Bad label content in ILGenerator.
+Argument_EmitWriteLineType = EmitWriteLine does not support this field or local type.
+Argument_ConstantNull = Null is not a valid constant value for this type.
+Argument_ConstantDoesntMatch = Constant does not match the defined type.
+Argument_ConstantNotSupported = {0} is not a supported constant type.
+Argument_BadConstructor = Cannot have private or static constructor.
+Argument_BadConstructorCallConv = Constructor must have standard calling convention.
+Argument_BadPropertyForConstructorBuilder = Property must be on the same type of the given ConstructorInfo.
+Argument_NotAWritableProperty = Not a writable property.
+Argument_BadFieldForConstructorBuilder = Field must be on the same type of the given ConstructorInfo.
+Argument_BadAttributeOnInterfaceMethod = Interface method must be abstract and virtual.
+ArgumentException_BadMethodImplBody = MethodOverride's body must be from this type.
+Argument_BadParameterCountsForConstructor = Parameter count does not match passed in argument value count.
+Argument_BadParameterTypeForConstructor = Passed in argument value at index {0} does not match the parameter type.
+Argument_BadTypeInCustomAttribute = An invalid type was used as a custom attribute constructor argument, field or property.
+Argument_DateTimeBadBinaryData = The binary data must result in a DateTime with ticks between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+Argument_VerStringTooLong = The unmanaged Version information is too large to persist.
+Argument_UnknownUnmanagedCallConv = Unknown unmanaged calling convention for function signature.
+Argument_BadConstantValue = Bad default value.
+Argument_IllegalName = Illegal name.
+Argument_cvtres_NotFound = Cannot find cvtres.exe
+Argument_BadCAForUnmngRSC = Bad '{0}' while generating unmanaged resource information.
+Argument_MustBeInterfaceMethod = The MemberInfo must be an interface method.
+Argument_CORDBBadVarArgCallConv = Cannot evaluate a VarArgs function.
+Argument_CORDBBadMethod = Cannot find the method on the object instance.
+Argument_InvalidOpCodeOnDynamicMethod = Ldtoken, Ldftn and Ldvirtftn OpCodes cannot target DynamicMethods.
+Argument_InvalidTypeForDynamicMethod = Invalid type owner for DynamicMethod.
+Argument_NeedGenericMethodDefinition = Method must represent a generic method definition on a generic type definition.
+Argument_MethodNeedGenericDeclaringType = The specified method cannot be dynamic or global and must be declared on a generic type definition.
+Argument_ConstructorNeedGenericDeclaringType = The specified constructor must be declared on a generic type definition.
+Argument_FieldNeedGenericDeclaringType = The specified field must be declared on a generic type definition.
+Argument_InvalidMethodDeclaringType = The specified method must be declared on the generic type definition of the specified type.
+Argument_InvalidConstructorDeclaringType = The specified constructor must be declared on the generic type definition of the specified type.
+Argument_InvalidFieldDeclaringType = The specified field must be declared on the generic type definition of the specified type.
+Argument_NeedNonGenericType = The specified Type must not be a generic type definition.
+Argument_MustBeTypeBuilder = 'type' must contain a TypeBuilder as a generic argument.
+Argument_CannotSetParentToInterface = Cannot set parent to an interface.
+Argument_MismatchedArrays = Two arrays, {0} and {1}, must be of the same size.
+Argument_NeedNonGenericObject = The specified object must not be an instance of a generic type.
+Argument_NeedStructWithNoRefs = The specified Type must be a struct containing no references.
+Argument_NotMethodCallOpcode = The specified opcode cannot be passed to EmitCall.
+
+; =====================================================
+;
+Argument_ModuleAlreadyLoaded = The specified module has already been loaded.
+Argument_MustHaveLayoutOrBeBlittable = The specified structure must be blittable or have layout information.
+Argument_NotSimpleFileName = The filename must not include a path specification.
+Argument_TypeMustBeVisibleFromCom = The specified type must be visible from COM.
+Argument_TypeMustBeComCreatable = The type must be creatable from COM.
+Argument_TypeMustNotBeComImport = The type must not be imported from COM.
+Argument_PolicyFileDoesNotExist = The requested policy file does not exist.
+Argument_NonNullObjAndCtx = Either obj or ctx must be null.
+Argument_NoModuleFileExtension = Module file name '{0}' must have file extension.
+Argument_TypeDoesNotContainMethod = Type does not contain the given method.
+Argument_StringZeroLength = String cannot be of zero length.
+Argument_MustBeString = String is too long or has invalid contents.
+Argument_AbsolutePathRequired = Absolute path information is required.
+Argument_ManifestFileDoesNotExist = The specified manifest file does not exist.
+Argument_MustBeRuntimeType = Type must be a runtime Type object.
+Argument_TypeNotValid = The Type object is not valid.
+Argument_MustBeRuntimeMethodInfo = MethodInfo must be a runtime MethodInfo object.
+Argument_MustBeRuntimeFieldInfo = FieldInfo must be a runtime FieldInfo object.
+Argument_InvalidFieldInfo = The FieldInfo object is not valid.
+Argument_InvalidConstructorInfo = The ConstructorInfo object is not valid.
+Argument_MustBeRuntimeAssembly = Assembly must be a runtime Assembly object.
+Argument_MustBeRuntimeModule = Module must be a runtime Module object.
+Argument_MustBeRuntimeParameterInfo = ParameterInfo must be a runtime ParameterInfo object.
+Argument_InvalidParameterInfo = The ParameterInfo object is not valid.
+Argument_MustBeRuntimeReflectionObject = The object must be a runtime Reflection object.
+Argument_InvalidMarshalByRefObject = The MarshalByRefObject is not valid.
+Argument_TypedReferenceInvalidField = Field in TypedReferences cannot be static or init only.
+Argument_HandleLeak = Cannot pass a GCHandle across AppDomains.
+Argument_ArgumentZero = Argument cannot be zero.
+Argument_ImproperType = Improper types in collection.
+Argument_NotAMembershipCondition = The type does not implement IMembershipCondition
+Argument_NotAPermissionType = The type does not implement IPermission
+Argument_NotACodeGroupType = The type does not inherit from CodeGroup
+Argument_NotATP = Type must be a TransparentProxy
+Argument_AlreadyACCW = The object already has a CCW associated with it.
+Argument_OffsetLocalMismatch = The UTC Offset of the local dateTime parameter does not match the offset argument.
+Argument_OffsetUtcMismatch = The UTC Offset for Utc DateTime instances must be 0.
+Argument_UTCOutOfRange = The UTC time represented when the offset is applied must be between year 0 and 10,000.
+Argument_OffsetOutOfRange = Offset must be within plus or minus 14 hours.
+Argument_OffsetPrecision = Offset must be specified in whole minutes.
+Argument_FlagNotSupported = One or more flags are not supported.
+Argument_MustBeFalse = Argument must be initialized to false
+Argument_ToExclusiveLessThanFromExclusive = fromInclusive must be less than or equal to toExclusive.
+Argument_FrameworkNameTooShort=FrameworkName cannot have less than two components or more than three components.
+Argument_FrameworkNameInvalid=FrameworkName is invalid.
+Argument_FrameworkNameMissingVersion=FrameworkName version component is missing.
+#if FEATURE_COMINTEROP
+Argument_TypeNotActivatableViaWindowsRuntime = Type '{0}' does not have an activation factory because it is not activatable by Windows Runtime.
+Argument_WinRTSystemRuntimeType = Cannot marshal type '{0}' to Windows Runtime. Only 'System.RuntimeType' is supported.
+Argument_Unexpected_TypeSource = Unexpected TypeKind when marshaling Windows.Foundation.TypeName.
+#endif // FEATURE_COMINTEROP
+
+; ArgumentNullException
+ArgumentNull_Array = Array cannot be null.
+ArgumentNull_ArrayValue = Found a null value within an array.
+ArgumentNull_ArrayElement = At least one element in the specified array was null.
+ArgumentNull_Assembly = Assembly cannot be null.
+ArgumentNull_AssemblyName = AssemblyName cannot be null.
+ArgumentNull_AssemblyNameName = AssemblyName.Name cannot be null or an empty string.
+ArgumentNull_Buffer = Buffer cannot be null.
+ArgumentNull_Collection = Collection cannot be null.
+ArgumentNull_CultureInfo = CultureInfo cannot be null.
+ArgumentNull_Dictionary = Dictionary cannot be null.
+ArgumentNull_FileName = File name cannot be null.
+ArgumentNull_Key = Key cannot be null.
+ArgumentNull_Graph = Object Graph cannot be null.
+ArgumentNull_Path = Path cannot be null.
+ArgumentNull_Stream = Stream cannot be null.
+ArgumentNull_String = String reference not set to an instance of a String.
+ArgumentNull_Type = Type cannot be null.
+ArgumentNull_Obj = Object cannot be null.
+ArgumentNull_GUID = GUID cannot be null.
+ArgumentNull_NullMember = Member at position {0} was null.
+ArgumentNull_Generic = Value cannot be null.
+ArgumentNull_WithParamName = Parameter '{0}' cannot be null.
+ArgumentNull_Child = Cannot have a null child.
+ArgumentNull_SafeHandle = SafeHandle cannot be null.
+ArgumentNull_CriticalHandle = CriticalHandle cannot be null.
+ArgumentNull_TypedRefType = Type in TypedReference cannot be null.
+ArgumentNull_ApplicationTrust = The application trust cannot be null.
+ArgumentNull_TypeRequiredByResourceScope = The type parameter cannot be null when scoping the resource's visibility to Private or Assembly.
+ArgumentNull_Waithandles = The waitHandles parameter cannot be null.
+
+; ArgumentOutOfRangeException
+ArgumentOutOfRange_AddressSpace = The number of bytes cannot exceed the virtual address space on a 32 bit machine.
+ArgumentOutOfRange_ArrayLB = Number was less than the array's lower bound in the first dimension.
+ArgumentOutOfRange_ArrayLBAndLength = Higher indices will exceed Int32.MaxValue because of large lower bound and/or length.
+ArgumentOutOfRange_ArrayLength = The length of the array must be between {0} and {1}, inclusive.
+ArgumentOutOfRange_ArrayLengthMultiple = The length of the array must be a multiple of {0}.
+ArgumentOutOfRange_ArrayListInsert = Insertion index was out of range. Must be non-negative and less than or equal to size.
+ArgumentOutOfRange_ArrayTooSmall = Destination array is not long enough to copy all the required data. Check array length and offset.
+ArgumentOutOfRange_BeepFrequency = Console.Beep's frequency must be between {0} and {1}.
+ArgumentOutOfRange_BiggerThanCollection = Larger than collection size.
+ArgumentOutOfRange_Bounds_Lower_Upper = Argument must be between {0} and {1}.
+ArgumentOutOfRange_Count = Count must be positive and count must refer to a location within the string/array/collection.
+ArgumentOutOfRange_CalendarRange = Specified time is not supported in this calendar. It should be between {0} (Gregorian date) and {1} (Gregorian date), inclusive.
+ArgumentOutOfRange_ConsoleBufferBoundaries = The value must be greater than or equal to zero and less than the console's buffer size in that dimension.
+ArgumentOutOfRange_ConsoleBufferLessThanWindowSize = The console buffer size must not be less than the current size and position of the console window, nor greater than or equal to Int16.MaxValue.
+ArgumentOutOfRange_ConsoleWindowBufferSize = The new console window size would force the console buffer size to be too large.
+ArgumentOutOfRange_ConsoleTitleTooLong = The console title is too long.
+ArgumentOutOfRange_ConsoleWindowPos = The window position must be set such that the current window size fits within the console's buffer, and the numbers must not be negative.
+ArgumentOutOfRange_ConsoleWindowSize_Size = The value must be less than the console's current maximum window size of {0} in that dimension. Note that this value depends on screen resolution and the console font.
+ArgumentOutOfRange_ConsoleKey = Console key values must be between 0 and 255.
+ArgumentOutOfRange_CursorSize = The cursor size is invalid. It must be a percentage between 1 and 100.
+ArgumentOutOfRange_BadYearMonthDay = Year, Month, and Day parameters describe an un-representable DateTime.
+ArgumentOutOfRange_BadHourMinuteSecond = Hour, Minute, and Second parameters describe an un-representable DateTime.
+ArgumentOutOfRange_DateArithmetic = The added or subtracted value results in an un-representable DateTime.
+ArgumentOutOfRange_DateTimeBadMonths = Months value must be between +/-120000.
+ArgumentOutOfRange_DateTimeBadYears = Years value must be between +/-10000.
+ArgumentOutOfRange_DateTimeBadTicks = Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+ArgumentOutOfRange_Day = Day must be between 1 and {0} for month {1}.
+ArgumentOutOfRange_DecimalRound = Decimal can only round to between 0 and 28 digits of precision.
+ArgumentOutOfRange_DecimalScale = Decimal's scale value must be between 0 and 28, inclusive.
+ArgumentOutOfRange_Era = Time value was out of era range.
+ArgumentOutOfRange_Enum = Enum value was out of legal range.
+ArgumentOutOfRange_FileLengthTooBig = Specified file length was too large for the file system.
+ArgumentOutOfRange_FileTimeInvalid = Not a valid Win32 FileTime.
+ArgumentOutOfRange_GetByteCountOverflow = Too many characters. The resulting number of bytes is larger than what can be returned as an int.
+ArgumentOutOfRange_GetCharCountOverflow = Too many bytes. The resulting number of chars is larger than what can be returned as an int.
+ArgumentOutOfRange_HashtableLoadFactor = Load factor needs to be between 0.1 and 1.0.
+ArgumentOutOfRange_HugeArrayNotSupported = Arrays larger than 2GB are not supported.
+ArgumentOutOfRange_InvalidHighSurrogate = A valid high surrogate character is between 0xd800 and 0xdbff, inclusive.
+ArgumentOutOfRange_InvalidLowSurrogate = A valid low surrogate character is between 0xdc00 and 0xdfff, inclusive.
+ArgumentOutOfRange_InvalidEraValue = Era value was not valid.
+ArgumentOutOfRange_InvalidUserDefinedAceType = User-defined ACEs must not have a well-known ACE type.
+ArgumentOutOfRange_InvalidUTF32 = A valid UTF32 value is between 0x000000 and 0x10ffff, inclusive, and should not include surrogate codepoint values (0x00d800 ~ 0x00dfff).
+ArgumentOutOfRange_Index = Index was out of range. Must be non-negative and less than the size of the collection.
+ArgumentOutOfRange_IndexString = Index was out of range. Must be non-negative and less than the length of the string.
+ArgumentOutOfRange_StreamLength = Stream length must be non-negative and less than 2^31 - 1 - origin.
+ArgumentOutOfRange_LessEqualToIntegerMaxVal = Argument must be less than or equal to 2^31 - 1 milliseconds.
+ArgumentOutOfRange_Month = Month must be between one and twelve.
+ArgumentOutOfRange_MustBeNonNegInt32 = Value must be non-negative and less than or equal to Int32.MaxValue.
+ArgumentOutOfRange_NeedNonNegNum = Non-negative number required.
+ArgumentOutOfRange_NeedNonNegOrNegative1 = Number must be either non-negative and less than or equal to Int32.MaxValue or -1.
+ArgumentOutOfRange_NeedPosNum = Positive number required.
+ArgumentOutOfRange_NegativeCapacity = Capacity must be positive.
+ArgumentOutOfRange_NegativeCount = Count cannot be less than zero.
+ArgumentOutOfRange_NegativeLength = Length cannot be less than zero.
+ArgumentOutOfRange_NegFileSize = Length must be non-negative.
+ArgumentOutOfRange_ObjectID = objectID cannot be less than or equal to zero.
+ArgumentOutOfRange_SmallCapacity = capacity was less than the current size.
+ArgumentOutOfRange_QueueGrowFactor = Queue grow factor must be between {0} and {1}.
+ArgumentOutOfRange_RoundingDigits = Rounding digits must be between 0 and 15, inclusive.
+ArgumentOutOfRange_StartIndex = StartIndex cannot be less than zero.
+ArgumentOutOfRange_MustBePositive = '{0}' must be greater than zero.
+ArgumentOutOfRange_MustBeNonNegNum = '{0}' must be non-negative.
+ArgumentOutOfRange_LengthGreaterThanCapacity = The length cannot be greater than the capacity.
+ArgumentOutOfRange_ListInsert = Index must be within the bounds of the List.
+ArgumentOutOfRange_StartIndexLessThanLength = startIndex must be less than length of string.
+ArgumentOutOfRange_StartIndexLargerThanLength = startIndex cannot be larger than length of string.
+ArgumentOutOfRange_EndIndexStartIndex = endIndex cannot be greater than startIndex.
+ArgumentOutOfRange_IndexCount = Index and count must refer to a location within the string.
+ArgumentOutOfRange_IndexCountBuffer = Index and count must refer to a location within the buffer.
+ArgumentOutOfRange_IndexLength = Index and length must refer to a location within the string.
+ArgumentOutOfRange_InvalidThreshold = The specified threshold for creating dictionary is out of range.
+ArgumentOutOfRange_Capacity = Capacity exceeds maximum capacity.
+ArgumentOutOfRange_Length = The specified length exceeds maximum capacity of SecureString.
+ArgumentOutOfRange_LengthTooLarge = The specified length exceeds the maximum value of {0}.
+ArgumentOutOfRange_SmallMaxCapacity = MaxCapacity must be one or greater.
+ArgumentOutOfRange_GenericPositive = Value must be positive.
+ArgumentOutOfRange_Range = Valid values are between {0} and {1}, inclusive.
+ArgumentOutOfRange_AddValue = Value to add was out of range.
+ArgumentOutOfRange_OffsetLength = Offset and length must refer to a position in the string.
+ArgumentOutOfRange_OffsetOut = Either offset did not refer to a position in the string, or there is an insufficient length of destination character array.
+ArgumentOutOfRange_PartialWCHAR = Pointer startIndex and length do not refer to a valid string.
+ArgumentOutOfRange_ParamSequence = The specified parameter index is not in range.
+ArgumentOutOfRange_Version = Version's parameters must be greater than or equal to zero.
+ArgumentOutOfRange_TimeoutTooLarge = Time-out interval must be less than 2^32-2.
+ArgumentOutOfRange_UIntPtrMax-1 = The length of the buffer must be less than the maximum UIntPtr value for your platform.
+ArgumentOutOfRange_UnmanagedMemStreamLength = UnmanagedMemoryStream length must be non-negative and less than 2^63 - 1 - baseAddress.
+ArgumentOutOfRange_UnmanagedMemStreamWrapAround = The UnmanagedMemoryStream capacity would wrap around the high end of the address space.
+ArgumentOutOfRange_PeriodTooLarge = Period must be less than 2^32-2.
+ArgumentOutOfRange_Year = Year must be between 1 and 9999.
+ArgumentOutOfRange_BinaryReaderFillBuffer = The number of bytes requested does not fit into BinaryReader's internal buffer.
+ArgumentOutOfRange_PositionLessThanCapacityRequired = The position may not be greater or equal to the capacity of the accessor.
+
+; ArithmeticException
+Arithmetic_NaN = Function does not accept floating point Not-a-Number values.
+
+; ArrayTypeMismatchException
+ArrayTypeMismatch_CantAssignType = Source array type cannot be assigned to destination array type.
+ArrayTypeMismatch_ConstrainedCopy = Array.ConstrainedCopy will only work on array types that are provably compatible, without any form of boxing, unboxing, widening, or casting of each array element. Change the array types (i.e., copy a Derived[] to a Base[]), or use a mitigation strategy in the CER for Array.Copy's less powerful reliability contract, such as cloning the array or throwing away the potentially corrupt destination array.
+
+; BadImageFormatException
+BadImageFormat_ResType&SerBlobMismatch = The type serialized in the .resources file was not the same type that the .resources file said it contained. Expected '{0}' but read '{1}'.
+BadImageFormat_ResourcesIndexTooLong = Corrupt .resources file. String for name index '{0}' extends past the end of the file.
+BadImageFormat_ResourcesNameTooLong = Corrupt .resources file. Resource name extends past the end of the file.
+BadImageFormat_ResourcesNameInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into name section.
+BadImageFormat_ResourcesHeaderCorrupted = Corrupt .resources file. Unable to read resources from this file because of invalid header information. Try regenerating the .resources file.
+BadImageFormat_ResourceNameCorrupted = Corrupt .resources file. A resource name extends past the end of the stream.
+BadImageFormat_ResourceNameCorrupted_NameIndex = Corrupt .resources file. The resource name for name index {0} extends past the end of the stream.
+BadImageFormat_ResourceDataLengthInvalid = Corrupt .resources file. The specified data length '{0}' is not a valid position in the stream.
+BadImageFormat_TypeMismatch = Corrupt .resources file. The specified type doesn't match the available data in the stream.
+BadImageFormat_InvalidType = Corrupt .resources file. The specified type doesn't exist.
+BadImageFormat_ResourcesIndexInvalid = Corrupt .resources file. The resource index '{0}' is outside the valid range.
+BadImageFormat_StreamPositionInvalid = Corrupt .resources file. The specified position '{0}' is not a valid position in the stream.
+BadImageFormat_ResourcesDataInvalidOffset = Corrupt .resources file. Invalid offset '{0}' into data section.
+BadImageFormat_NegativeStringLength = Corrupt .resources file. String length must be non-negative.
+BadImageFormat_ParameterSignatureMismatch = The parameters and the signature of the method don't match.
+
+; Cryptography
+; These strings still appear in bcl.small but should go away eventually
+Cryptography_CSSM_Error = Error 0x{0} from the operating system security framework: '{1}'.
+Cryptography_CSSM_Error_Unknown = Error 0x{0} from the operating system security framework.
+Cryptography_InvalidDSASignatureSize = Length of the DSA signature was not 40 bytes.
+Cryptography_InvalidHandle = {0} is an invalid handle.
+Cryptography_InvalidOID = Object identifier (OID) is unknown.
+Cryptography_OAEPDecoding = Error occurred while decoding OAEP padding.
+Cryptography_PasswordDerivedBytes_InvalidIV = The Initialization vector should have the same length as the algorithm block size in bytes.
+Cryptography_SSE_InvalidDataSize = Length of the data to encrypt is invalid.
+Cryptography_X509_ExportFailed = The certificate export operation failed.
+Cryptography_X509_InvalidContentType = Invalid content type.
+Cryptography_CryptoStream_FlushFinalBlockTwice = FlushFinalBlock() method was called twice on a CryptoStream. It can only be called once.
+Cryptography_HashKeySet = Hash key cannot be changed after the first write to the stream.
+Cryptography_HashNotYetFinalized = Hash must be finalized before the hash value is retrieved.
+Cryptography_InsufficientBuffer = Input buffer contains insufficient data.
+Cryptography_InvalidBlockSize = Specified block size is not valid for this algorithm.
+Cryptography_InvalidCipherMode = Specified cipher mode is not valid for this algorithm.
+Cryptography_InvalidIVSize = Specified initialization vector (IV) does not match the block size for this algorithm.
+Cryptography_InvalidKeySize = Specified key is not a valid size for this algorithm.
+Cryptography_PasswordDerivedBytes_FewBytesSalt = Salt is not at least eight bytes.
+Cryptography_PKCS7_InvalidPadding = Padding is invalid and cannot be removed.
+Cryptography_UnknownHashAlgorithm='{0}' is not a known hash algorithm.
+
+#if FEATURE_CRYPTO
+Cryptography_Config_EncodedOIDError = Encoded OID length is too large (greater than 0x7f bytes).
+Cryptography_CSP_AlgKeySizeNotAvailable = Algorithm implementation does not support a key size of {0}.
+Cryptography_CSP_AlgorithmNotAvailable = Cryptographic service provider (CSP) could not be found for this algorithm.
+Cryptography_CSP_CFBSizeNotSupported = Feedback size for the cipher feedback mode (CFB) must be 8 bits.
+Cryptography_CSP_NotFound = The requested key container was not found.
+Cryptography_CSP_NoPrivateKey = Object contains only the public half of a key pair. A private key must also be provided.
+Cryptography_CSP_OFBNotSupported = Output feedback mode (OFB) is not supported by this implementation.
+Cryptography_CSP_WrongKeySpec = The specified cryptographic service provider (CSP) does not support this key algorithm.
+Cryptography_HashNameSet = Hash name cannot be changed after the first write to the stream.
+Cryptography_HashAlgorithmNameNullOrEmpty = The hash algorithm name cannot be null or empty.
+Cryptography_InvalidHashSize = {0} algorithm hash size is {1} bytes.
+Cryptography_InvalidKey_Weak = Specified key is a known weak key for '{0}' and cannot be used.
+Cryptography_InvalidKey_SemiWeak = Specified key is a known semi-weak key for '{0}' and cannot be used.
+Cryptography_InvalidKeyParameter = Parameter '{0}' is not a valid key parameter.
+Cryptography_InvalidFeedbackSize = Specified feedback size is invalid.
+Cryptography_InvalidOperation = This operation is not supported for this class.
+Cryptography_InvalidPaddingMode = Specified padding mode is not valid for this algorithm.
+Cryptography_InvalidFromXmlString = Input string does not contain a valid encoding of the '{0}' '{1}' parameter.
+Cryptography_MissingKey = No asymmetric key object has been associated with this formatter object.
+Cryptography_MissingOID = Required object identifier (OID) cannot be found.
+Cryptography_NotInteractive = The current session is not interactive.
+Cryptography_NonCompliantFIPSAlgorithm = This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
+Cryptography_Padding_Win2KEnhOnly = Direct Encryption and decryption using RSA are not available on this platform.
+Cryptography_Padding_EncDataTooBig = The data to be encrypted exceeds the maximum for this modulus of {0} bytes.
+Cryptography_Padding_DecDataTooBig = The data to be decrypted exceeds the maximum for this modulus of {0} bytes.
+Cryptography_PasswordDerivedBytes_ValuesFixed = Value of '{0}' cannot be changed after the bytes have been retrieved.
+Cryptography_PasswordDerivedBytes_TooManyBytes = Requested number of bytes exceeds the maximum.
+Cryptography_PasswordDerivedBytes_InvalidAlgorithm = Algorithm is unavailable or is not supported for this operation.
+Cryptography_PKCS1Decoding = Error occurred while decoding PKCS1 padding.
+Cryptography_RC2_EKSKS = EffectiveKeySize value must be at least as large as the KeySize value.
+Cryptography_RC2_EKSKS2 = EffectiveKeySize must be the same as KeySize in this implementation.
+Cryptography_RC2_EKS40 = EffectiveKeySize value must be at least 40 bits.
+Cryptography_SSD_InvalidDataSize = Length of the data to decrypt is invalid.
+Cryptography_AddNullOrEmptyName = CryptoConfig cannot add a mapping for a null or empty name.
+Cryptography_AlgorithmTypesMustBeVisible = Algorithms added to CryptoConfig must be accessable from outside their assembly.
+#endif // FEATURE_CRYPTO
+
+; EventSource
+EventSource_ToString = EventSource({0}, {1})
+EventSource_EventSourceGuidInUse = An instance of EventSource with Guid {0} already exists.
+EventSource_KeywordNeedPowerOfTwo = Value {0} for keyword {1} needs to be a power of 2.
+EventSource_UndefinedKeyword = Use of undefined keyword value {0} for event {1}.
+EventSource_UnsupportedEventTypeInManifest = Unsupported type {0} in event source.
+EventSource_ListenerNotFound = Listener not found.
+EventSource_ListenerCreatedInsideCallback = Creating an EventListener inside a EventListener callback.
+EventSource_AttributeOnNonVoid = Event attribute placed on method {0} which does not return 'void'.
+EventSource_NeedPositiveId = Event IDs must be positive integers.
+EventSource_ReservedOpcode = Opcode values less than 11 are reserved for system use.
+EventSource_ReservedKeywords = Keywords values larger than 0x0000100000000000 are reserved for system use
+EventSource_PayloadTooBig=The payload for a single event is too large.
+EventSource_NoFreeBuffers=No Free Buffers available from the operating system (e.g. event rate too fast).
+EventSource_NullInput=Null passed as a event argument.
+EventSource_TooManyArgs=Too many arguments.
+EventSource_SessionIdError=Bit position in AllKeywords ({0}) must equal the command argument named "EtwSessionKeyword" ({1}).
+EventSource_EnumKindMismatch = The type of {0} is not expected in {1}.
+EventSource_MismatchIdToWriteEvent = Event {0} is givien event ID {1} but {2} was passed to WriteEvent.
+EventSource_EventIdReused = Event {0} has ID {1} which is already in use.
+EventSource_EventNameReused = Event name {0} used more than once. If you wish to overload a method, the overloaded method should have a NonEvent attribute.
+EventSource_UndefinedChannel = Use of undefined channel value {0} for event {1}.
+EventSource_UndefinedOpcode = Use of undefined opcode value {0} for event {1}.
+ArgumentOutOfRange_MaxArgExceeded = The total number of parameters must not exceed {0}.
+ArgumentOutOfRange_MaxStringsExceeded = The number of String parameters must not exceed {0}.
+ArgumentOutOfRange_NeedValidId = The ID parameter must be in the range {0} through {1}.
+EventSource_NeedGuid = The Guid of an EventSource must be non zero.
+EventSource_NeedName = The name of an EventSource must not be null.
+EventSource_EtwAlreadyRegistered = The provider has already been registered with the operating system.
+EventSource_ListenerWriteFailure = An error occurred when writing to a listener.
+EventSource_TypeMustDeriveFromEventSource = Event source types must derive from EventSource.
+EventSource_TypeMustBeSealedOrAbstract = Event source types must be sealed or abstract.
+EventSource_TaskOpcodePairReused = Event {0} (with ID {1}) has the same task/opcode pair as event {2} (with ID {3}).
+EventSource_EventMustHaveTaskIfNonDefaultOpcode = Event {0} (with ID {1}) has a non-default opcode but not a task.
+EventSource_EventNameDoesNotEqualTaskPlusOpcode = Event {0} (with ID {1}) has a name that is not the concatenation of its task name and opcode.
+EventSource_PeriodIllegalInProviderName = Period character ('.') is illegal in an ETW provider name ({0}).
+EventSource_IllegalOpcodeValue = Opcode {0} has a value of {1} which is outside the legal range (11-238).
+EventSource_OpcodeCollision = Opcodes {0} and {1} are defined with the same value ({2}).
+EventSource_IllegalTaskValue = Task {0} has a value of {1} which is outside the legal range (1-65535).
+EventSource_TaskCollision = Tasks {0} and {1} are defined with the same value ({2}).
+EventSource_IllegalKeywordsValue = Keyword {0} has a value of {1} which is outside the legal range (0-0x0000080000000000).
+EventSource_KeywordCollision = Keywords {0} and {1} are defined with the same value ({2}).
+EventSource_EventChannelOutOfRange = Channel {0} has a value of {1} which is outside the legal range (16-254).
+EventSource_ChannelTypeDoesNotMatchEventChannelValue = Channel {0} does not match event channel value {1}.
+EventSource_MaxChannelExceeded = Attempt to define more than the maximum limit of 8 channels for a provider.
+EventSource_DuplicateStringKey = Multiple definitions for string "{0}".
+EventSource_EventWithAdminChannelMustHaveMessage = Event {0} specifies an Admin channel {1}. It must specify a Message property.
+EventSource_UnsupportedMessageProperty = Event {0} specifies an illegal or unsupported formatting message ("{1}").
+EventSource_AbstractMustNotDeclareKTOC = Abstract event source must not declare {0} nested type.
+EventSource_AbstractMustNotDeclareEventMethods = Abstract event source must not declare event methods ({0} with ID {1}).
+EventSource_EventMustNotBeExplicitImplementation = Event method {0} (with ID {1}) is an explicit interface method implementation. Re-write method as implicit implementation.
+EventSource_EventParametersMismatch = Event {0} was called with {1} argument(s), but it is defined with {2} parameter(s).
+EventSource_InvalidCommand = Invalid command value.
+EventSource_InvalidEventFormat = Can't specify both etw event format flags.
+EventSource_AddScalarOutOfRange = Getting out of bounds during scalar addition.
+EventSource_PinArrayOutOfRange = Pins are out of range.
+EventSource_DataDescriptorsOutOfRange = Data descriptors are out of range.
+EventSource_NotSupportedArrayOfNil = Arrays of Nil are not supported.
+EventSource_NotSupportedArrayOfBinary = Arrays of Binary are not supported.
+EventSource_NotSupportedArrayOfNullTerminatedString = Arrays of null-terminated string are not supported.
+EventSource_TooManyFields = Too many fields in structure.
+EventSource_RecursiveTypeDefinition = Recursive type definition is not supported.
+EventSource_NotSupportedEnumType = Enum type {0} underlying type {1} is not supported for serialization.
+EventSource_NonCompliantTypeError = The API supports only anonymous types or types decorated with the EventDataAttribute. Non-compliant type: {0} dataType.
+EventSource_NotSupportedNestedArraysEnums = Nested arrays/enumerables are not supported.
+EventSource_IncorrentlyAuthoredTypeInfo = Incorrectly-authored TypeInfo - a type should be serialized as one field or as one group
+EventSource_NotSupportedCustomSerializedData = Enumerables of custom-serialized data are not supported
+EventSource_StopsFollowStarts = An event with stop suffix must follow a corresponding event with a start suffix.
+EventSource_NoRelatedActivityId = EventSource expects the first parameter of the Event method to be of type Guid and to be named "relatedActivityId" when calling WriteEventWithRelatedActivityId.
+EventSource_VarArgsParameterMismatch = The parameters to the Event method do not match the parameters to the WriteEvent method. This may cause the event to be displayed incorrectly.
+
+; ExecutionEngineException
+ExecutionEngine_InvalidAttribute = Attribute cannot have multiple definitions.
+ExecutionEngine_MissingSecurityDescriptor = Unable to retrieve security descriptor for this frame.
+
+;;ExecutionContext
+ExecutionContext_UndoFailed = Undo operation on a component context threw an exception
+ExecutionContext_ExceptionInAsyncLocalNotification = An exception was not handled in an AsyncLocal<T> notification callback.
+
+
+; FieldAccessException
+FieldAccess_InitOnly = InitOnly (aka ReadOnly) fields can only be initialized in the type/instance constructor.
+
+; FormatException
+Format_AttributeUsage = Duplicate AttributeUsageAttribute found on attribute type {0}.
+Format_Bad7BitInt32 = Too many bytes in what should have been a 7 bit encoded Int32.
+Format_BadBase = Invalid digits for the specified base.
+Format_BadBase64Char = The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.
+Format_BadBase64CharArrayLength = Invalid length for a Base-64 char array or string.
+Format_BadBoolean = String was not recognized as a valid Boolean.
+Format_BadDateTime = String was not recognized as a valid DateTime.
+Format_BadDateTimeCalendar = The DateTime represented by the string is not supported in calendar {0}.
+Format_BadDayOfWeek = String was not recognized as a valid DateTime because the day of week was incorrect.
+Format_DateOutOfRange = The DateTime represented by the string is out of range.
+Format_BadDatePattern = Could not determine the order of year, month, and date from '{0}'.
+Format_BadFormatSpecifier = Format specifier was invalid.
+Format_BadTimeSpan = String was not recognized as a valid TimeSpan.
+Format_BadQuote = Cannot find a matching quote character for the character '{0}'.
+Format_EmptyInputString = Input string was either empty or contained only whitespace.
+Format_ExtraJunkAtEnd = Additional non-parsable characters are at the end of the string.
+Format_GuidBrace = Expected {0xdddddddd, etc}.
+Format_GuidComma = Could not find a comma, or the length between the previous token and the comma was zero (i.e., '0x,'etc.).
+Format_GuidBraceAfterLastNumber = Could not find a brace, or the length between the previous token and the brace was zero (i.e., '0x,'etc.).
+Format_GuidDashes = Dashes are in the wrong position for GUID parsing.
+Format_GuidEndBrace = Could not find the ending brace.
+Format_GuidHexPrefix = Expected hex 0x in '{0}'.
+Format_GuidInvLen = Guid should contain 32 digits with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
+Format_GuidInvalidChar = Guid string should only contain hexadecimal characters.
+Format_GuidUnrecognized = Unrecognized Guid format.
+Format_InvalidEnumFormatSpecification = Format String can be only "G", "g", "X", "x", "F", "f", "D" or "d".
+Format_InvalidGuidFormatSpecification = Format String can be only "D", "d", "N", "n", "P", "p", "B", "b", "X" or "x".
+Format_InvalidString = Input string was not in a correct format.
+Format_IndexOutOfRange = Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
+Format_UnknowDateTimeWord = The string was not recognized as a valid DateTime. There is an unknown word starting at index {0}.
+Format_NeedSingleChar = String must be exactly one character long.
+Format_NoParsibleDigits = Could not find any recognizable digits.
+Format_RepeatDateTimePattern = DateTime pattern '{0}' appears more than once with different values.
+Format_StringZeroLength = String cannot have zero length.
+Format_TwoTimeZoneSpecifiers = The String being parsed cannot contain two TimeZone specifiers.
+Format_UTCOutOfRange= The UTC representation of the date falls outside the year range 1-9999.
+Format_OffsetOutOfRange=The time zone offset must be within plus or minus 14 hours.
+Format_MissingIncompleteDate=There must be at least a partial date with a year present in the input.
+
+; IndexOutOfRangeException
+IndexOutOfRange_ArrayRankIndex = Array does not have that many dimensions.
+IndexOutOfRange_IORaceCondition = Probable I/O race condition detected while copying memory. The I/O package is not thread safe by default. In multithreaded applications, a stream must be accessed in a thread-safe way, such as a thread-safe wrapper returned by TextReader's or TextWriter's Synchronized methods. This also applies to classes like StreamWriter and StreamReader.
+IndexOutOfRange_UMSPosition = Unmanaged memory stream position was beyond the capacity of the stream.
+
+; InsufficientMemoryException
+InsufficientMemory_MemFailPoint = Insufficient available memory to meet the expected demands of an operation at this time. Please try again later.
+InsufficientMemory_MemFailPoint_TooBig = Insufficient memory to meet the expected demands of an operation, and this system is likely to never satisfy this request. If this is a 32 bit system, consider booting in 3 GB mode.
+InsufficientMemory_MemFailPoint_VAFrag = Insufficient available memory to meet the expected demands of an operation at this time, possibly due to virtual address space fragmentation. Please try again later.
+
+
+; InvalidCastException
+InvalidCast_DBNull = Object cannot be cast to DBNull.
+InvalidCast_DownCastArrayElement = At least one element in the source array could not be cast down to the destination array type.
+InvalidCast_Empty = Object cannot be cast to Empty.
+InvalidCast_FromDBNull = Object cannot be cast from DBNull to other types.
+InvalidCast_FromTo = Invalid cast from '{0}' to '{1}'.
+InvalidCast_IConvertible = Object must implement IConvertible.
+InvalidCast_OATypeMismatch = OleAut reported a type mismatch.
+InvalidCast_StoreArrayElement = Object cannot be stored in an array of this type.
+InvalidCast_CannotCoerceByRefVariant = Object cannot be coerced to the original type of the ByRef VARIANT it was obtained from.
+InvalidCast_CannotCastNullToValueType = Null object cannot be converted to a value type.
+#if FEATURE_COMINTEROP
+InvalidCast_WinRTIPropertyValueElement = Object in an IPropertyValue is of type '{0}', which cannot be converted to a '{1}'.
+InvalidCast_WinRTIPropertyValueCoersion = Object in an IPropertyValue is of type '{0}' with value '{1}', which cannot be converted to a '{2}'.
+InvalidCast_WinRTIPropertyValueArrayCoersion = Object in an IPropertyValue is of type '{0}' which cannot be convereted to a '{1}' due to array element '{2}': {3}.
+#endif // FEATURE_COMINTEROP
+
+; InvalidOperationException
+InvalidOperation_ActivationArgsAppTrustMismatch = The activation arguments and application trust for the AppDomain must correspond to the same application identity.
+InvalidOperation_AddContextFrozen = Attempted to add properties to a frozen context.
+InvalidOperation_AppDomainSandboxAPINeedsExplicitAppBase = This API requires the ApplicationBase to be specified explicitly in the AppDomainSetup parameter.
+InvalidOperation_CantCancelCtrlBreak = Applications may not prevent control-break from terminating their process.
+InvalidOperation_CalledTwice = The method cannot be called twice on the same instance.
+InvalidOperation_CollectionCorrupted = A prior operation on this collection was interrupted by an exception. Collection's state is no longer trusted.
+InvalidOperation_CriticalTransparentAreMutuallyExclusive = SecurityTransparent and SecurityCritical attributes cannot be applied to the assembly scope at the same time.
+InvalidOperation_SubclassedObject = Cannot set sub-classed {0} object to {1} object.
+InvalidOperation_ExceptionStateCrossAppDomain = Thread.ExceptionState cannot access an ExceptionState from a different AppDomain.
+InvalidOperation_DebuggerLaunchFailed = Debugger unable to launch.
+InvalidOperation_ApartmentStateSwitchFailed = Failed to set the specified COM apartment state.
+InvalidOperation_EmptyQueue = Queue empty.
+InvalidOperation_EmptyStack = Stack empty.
+InvalidOperation_CannotRemoveFromStackOrQueue = Removal is an invalid operation for Stack or Queue.
+InvalidOperation_EnumEnded = Enumeration already finished.
+InvalidOperation_EnumFailedVersion = Collection was modified; enumeration operation may not execute.
+InvalidOperation_EnumNotStarted = Enumeration has not started. Call MoveNext.
+InvalidOperation_EnumOpCantHappen = Enumeration has either not started or has already finished.
+InvalidOperation_ModifyRONumFmtInfo = Unable to modify a read-only NumberFormatInfo object.
+#if FEATURE_CAS_POLICY
+InvalidOperation_ModifyROPermSet = ReadOnlyPermissionSet objects may not be modified.
+#endif // FEATURE_CAS_POLICY
+InvalidOperation_MustBeSameThread = This operation must take place on the same thread on which the object was created.
+InvalidOperation_MustRevertPrivilege = Must revert the privilege prior to attempting this operation.
+InvalidOperation_ReadOnly = Instance is read-only.
+InvalidOperation_RegRemoveSubKey = Registry key has subkeys and recursive removes are not supported by this method.
+InvalidOperation_IComparerFailed = Failed to compare two elements in the array.
+InvalidOperation_InternalState = Invalid internal state.
+InvalidOperation_DuplicatePropertyName = Another property by this name already exists.
+InvalidOperation_NotCurrentDomain = You can only define a dynamic assembly on the current AppDomain.
+InvalidOperation_ContextAlreadyFrozen = Context is already frozen.
+InvalidOperation_WriteOnce = This property has already been set and cannot be modified.
+InvalidOperation_MethodBaked = Type definition of the method is complete.
+InvalidOperation_MethodHasBody = Method already has a body.
+InvalidOperation_ModificationOfNonCanonicalAcl = This access control list is not in canonical form and therefore cannot be modified.
+InvalidOperation_Method = This method is not supported by the current object.
+InvalidOperation_NotADebugModule = Not a debug ModuleBuilder.
+InvalidOperation_NoMultiModuleAssembly = You cannot have more than one dynamic module in each dynamic assembly in this version of the runtime.
+InvalidOperation_OpenLocalVariableScope = Local variable scope was not properly closed.
+InvalidOperation_SetVolumeLabelFailed = Volume labels can only be set for writable local volumes.
+InvalidOperation_SetData = An additional permission should not be supplied for setting loader information.
+InvalidOperation_SetData_OnlyOnce = SetData can only be used to set the value of a given name once.
+InvalidOperation_SetData_OnlyLocationURI = SetData cannot be used to set the value for '{0}'.
+InvalidOperation_TypeHasBeenCreated = Unable to change after type has been created.
+InvalidOperation_TypeNotCreated = Type has not been created.
+InvalidOperation_NoUnderlyingTypeOnEnum = Underlying type information on enumeration is not specified.
+InvalidOperation_ResMgrBadResSet_Type = '{0}': ResourceSet derived classes must provide a constructor that takes a String file name and a constructor that takes a Stream.
+InvalidOperation_AssemblyHasBeenSaved = Assembly '{0}' has been saved.
+InvalidOperation_ModuleHasBeenSaved = Module '{0}' has been saved.
+InvalidOperation_CannotAlterAssembly = Unable to alter assembly information.
+InvalidOperation_BadTransientModuleReference = Unable to make a reference to a transient module from a non-transient module.
+InvalidOperation_BadILGeneratorUsage = ILGenerator usage is invalid.
+InvalidOperation_BadInstructionOrIndexOutOfBound = MSIL instruction is invalid or index is out of bounds.
+InvalidOperation_ShouldNotHaveMethodBody = Method body should not exist.
+InvalidOperation_EntryMethodNotDefinedInAssembly = Entry method is not defined in the same assembly.
+InvalidOperation_CantSaveTransientAssembly = Cannot save a transient assembly.
+InvalidOperation_BadResourceContainer = Unable to add resource to transient module or transient assembly.
+InvalidOperation_CantInstantiateAbstractClass = Instances of abstract classes cannot be created.
+InvalidOperation_CantInstantiateFunctionPointer = Instances of function pointers cannot be created.
+InvalidOperation_BadTypeAttributesNotAbstract = Type must be declared abstract if any of its methods are abstract.
+InvalidOperation_BadInterfaceNotAbstract = Interface must be declared abstract.
+InvalidOperation_ConstructorNotAllowedOnInterface = Interface cannot have constructors.
+InvalidOperation_BadMethodBody = Method '{0}' cannot have a method body.
+InvalidOperation_MetaDataError = Metadata operation failed.
+InvalidOperation_BadEmptyMethodBody = Method '{0}' does not have a method body.
+InvalidOperation_EndInvokeCalledMultiple = EndInvoke can only be called once for each asynchronous operation.
+InvalidOperation_EndReadCalledMultiple = EndRead can only be called once for each asynchronous operation.
+InvalidOperation_EndWriteCalledMultiple = EndWrite can only be called once for each asynchronous operation.
+InvalidOperation_AsmLoadedForReflectionOnly = Assembly has been loaded as ReflectionOnly. This API requires an assembly capable of execution.
+InvalidOperation_NoAsmName = Assembly does not have an assembly name. In order to be registered for use by COM, an assembly must have a valid assembly name.
+InvalidOperation_NoAsmCodeBase = Assembly does not have a code base.
+InvalidOperation_HandleIsNotInitialized = Handle is not initialized.
+InvalidOperation_HandleIsNotPinned = Handle is not pinned.
+InvalidOperation_SlotHasBeenFreed = LocalDataStoreSlot storage has been freed.
+InvalidOperation_GlobalsHaveBeenCreated = Type definition of the global function has been completed.
+InvalidOperation_NotAVarArgCallingConvention = Calling convention must be VarArgs.
+InvalidOperation_CannotImportGlobalFromDifferentModule = Unable to import a global method or field from a different module.
+InvalidOperation_NonStaticComRegFunction = COM register function must be static.
+InvalidOperation_NonStaticComUnRegFunction = COM unregister function must be static.
+InvalidOperation_InvalidComRegFunctionSig = COM register function must have a System.Type parameter and a void return type.
+InvalidOperation_InvalidComUnRegFunctionSig = COM unregister function must have a System.Type parameter and a void return type.
+InvalidOperation_MultipleComRegFunctions = Type '{0}' has more than one COM registration function.
+InvalidOperation_MultipleComUnRegFunctions = Type '{0}' has more than one COM unregistration function.
+InvalidOperation_MustCallInitialize = You must call Initialize on this object instance before using it.
+InvalidOperation_MustLockForReadOrWrite = Object must be locked for read or write.
+InvalidOperation_MustLockForWrite = Object must be locked for read.
+InvalidOperation_NoValue = Nullable object must have a value.
+InvalidOperation_ResourceNotStream_Name = Resource '{0}' was not a Stream - call GetObject instead.
+InvalidOperation_ResourceNotString_Name = Resource '{0}' was not a String - call GetObject instead.
+InvalidOperation_ResourceNotString_Type = Resource was of type '{0}' instead of String - call GetObject instead.
+InvalidOperation_ResourceWriterSaved = The resource writer has already been closed and cannot be edited.
+InvalidOperation_UnderlyingArrayListChanged = This range in the underlying list is invalid. A possible cause is that elements were removed.
+InvalidOperation_AnonymousCannotImpersonate = An anonymous identity cannot perform an impersonation.
+InvalidOperation_DefaultConstructorILGen = Unable to access ILGenerator on a constructor created with DefineDefaultConstructor.
+InvalidOperation_DefaultConstructorDefineBody = The method body of the default constructor cannot be changed.
+InvalidOperation_ComputerName = Computer name could not be obtained.
+InvalidOperation_MismatchedAsyncResult = The IAsyncResult object provided does not match this delegate.
+InvalidOperation_PIAMustBeStrongNamed = Primary interop assemblies must be strongly named.
+InvalidOperation_HashInsertFailed = Hashtable insert failed. Load factor too high. The most common cause is multiple threads writing to the Hashtable simultaneously.
+InvalidOperation_UnknownEnumType = Unknown enum type.
+InvalidOperation_GetVersion = OSVersion's call to GetVersionEx failed.
+InvalidOperation_DateTimeParsing = Internal Error in DateTime and Calendar operations.
+InvalidOperation_UserDomainName = UserDomainName native call failed.
+InvalidOperation_WaitOnTransparentProxy = Cannot wait on a transparent proxy.
+InvalidOperation_NoPublicAddMethod = Cannot add the event handler since no public add method exists for the event.
+InvalidOperation_NoPublicRemoveMethod = Cannot remove the event handler since no public remove method exists for the event.
+InvalidOperation_NotSupportedOnWinRTEvent = Adding or removing event handlers dynamically is not supported on WinRT events.
+InvalidOperation_ConsoleKeyAvailableOnFile = Cannot see if a key has been pressed when either application does not have a console or when console input has been redirected from a file. Try Console.In.Peek.
+InvalidOperation_ConsoleReadKeyOnFile = Cannot read keys when either application does not have a console or when console input has been redirected from a file. Try Console.Read.
+InvalidOperation_ThreadWrongThreadStart = The thread was created with a ThreadStart delegate that does not accept a parameter.
+InvalidOperation_ThreadAPIsNotSupported = Use CompressedStack.(Capture/Run) or ExecutionContext.(Capture/Run) APIs instead.
+InvalidOperation_NotNewCaptureContext = Cannot apply a context that has been marshaled across AppDomains, that was not acquired through a Capture operation or that has already been the argument to a Set call.
+InvalidOperation_NullContext = Cannot call Set on a null context
+InvalidOperation_CannotCopyUsedContext = Only newly captured contexts can be copied
+InvalidOperation_CannotUseSwitcherOtherThread = Undo operation must be performed on the thread where the corresponding context was Set.
+InvalidOperation_SwitcherCtxMismatch = The Undo operation encountered a context that is different from what was applied in the corresponding Set operation. The possible cause is that a context was Set on the thread and not reverted(undone).
+InvalidOperation_CannotOverrideSetWithoutRevert = Must override both HostExecutionContextManager.SetHostExecutionContext and HostExecutionContextManager.Revert.
+InvalidOperation_CannotUseAFCOtherThread = AsyncFlowControl object must be used on the thread where it was created.
+InvalidOperation_CannotRestoreUnsupressedFlow = Cannot restore context flow when it is not suppressed.
+InvalidOperation_CannotSupressFlowMultipleTimes = Context flow is already suppressed.
+InvalidOperation_CannotUseAFCMultiple = AsyncFlowControl object can be used only once to call Undo().
+InvalidOperation_AsyncFlowCtrlCtxMismatch = AsyncFlowControl objects can be used to restore flow only on the Context that had its flow suppressed.
+InvalidOperation_TimeoutsNotSupported = Timeouts are not supported on this stream.
+InvalidOperation_Overlapped_Pack = Cannot pack a packed Overlapped again.
+InvalidOperation_OnlyValidForDS = Adding ACEs with Object Flags and Object GUIDs is only valid for directory-object ACLs.
+InvalidOperation_WrongAsyncResultOrEndReadCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndRead was called multiple times with the same IAsyncResult.
+InvalidOperation_WrongAsyncResultOrEndWriteCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or EndWrite was called multiple times with the same IAsyncResult.
+InvalidOperation_WrongAsyncResultOrEndCalledMultiple = Either the IAsyncResult object did not come from the corresponding async method on this type, or the End method was called multiple times with the same IAsyncResult.
+InvalidOperation_NoSecurityDescriptor = The object does not contain a security descriptor.
+InvalidOperation_NotAllowedInReflectionOnly = The requested operation is invalid in the ReflectionOnly context.
+InvalidOperation_NotAllowedInDynamicMethod = The requested operation is invalid for DynamicMethod.
+InvalidOperation_PropertyInfoNotAvailable = This API does not support PropertyInfo tokens.
+InvalidOperation_EventInfoNotAvailable = This API does not support EventInfo tokens.
+InvalidOperation_UnexpectedWin32Error = Unexpected error when calling an operating system function. The returned error code is 0x{0:x}.
+InvalidOperation_AssertTransparentCode = Cannot perform CAS Asserts in Security Transparent methods
+InvalidOperation_NullModuleHandle = The requested operation is invalid when called on a null ModuleHandle.
+InvalidOperation_NotWithConcurrentGC = This API is not available when the concurrent GC is enabled.
+InvalidOperation_WithoutARM = This API is not available when AppDomain Resource Monitoring is not turned on.
+InvalidOperation_NotGenericType = This operation is only valid on generic types.
+InvalidOperation_TypeCannotBeBoxed = The given type cannot be boxed.
+InvalidOperation_HostModifiedSecurityState = The security state of an AppDomain was modified by an AppDomainManager configured with the NoSecurityChanges flag.
+InvalidOperation_StrongNameKeyPairRequired = A strong name key pair is required to emit a strong-named dynamic assembly.
+#if FEATURE_COMINTEROP
+InvalidOperation_EventTokenTableRequiresDelegate = Type '{0}' is not a delegate type. EventTokenTable may only be used with delegate types.
+#endif // FEATURE_COMINTEROP
+InvalidOperation_NullArray = The underlying array is null.
+;system.security.claims
+InvalidOperation_ClaimCannotBeRemoved = The Claim '{0}' was not able to be removed. It is either not part of this Identity or it is a claim that is owned by the Principal that contains this Identity. For example, the Principal will own the claim when creating a GenericPrincipal with roles. The roles will be exposed through the Identity that is passed in the constructor, but not actually owned by the Identity. Similar logic exists for a RolePrincipal.
+InvalidOperationException_ActorGraphCircular = Actor cannot be set so that circular directed graph will exist chaining the subjects together.
+InvalidOperation_AsyncIOInProgress = The stream is currently in use by a previous operation on the stream.
+InvalidOperation_APIInvalidForCurrentContext = The API '{0}' cannot be used on the current platform. See http://go.microsoft.com/fwlink/?LinkId=248273 for more information.
+
+; InvalidProgramException
+InvalidProgram_Default = Common Language Runtime detected an invalid program.
+
+; Isolated Storage
+#if FEATURE_ISOSTORE
+IsolatedStorage_AssemblyMissingIdentity = Unable to determine assembly of the caller.
+IsolatedStorage_ApplicationMissingIdentity = Unable to determine application identity of the caller.
+IsolatedStorage_DomainMissingIdentity = Unable to determine domain of the caller.
+IsolatedStorage_AssemblyGrantSet = Unable to determine granted permission for assembly.
+IsolatedStorage_DomainGrantSet = Unable to determine granted permission for domain.
+IsolatedStorage_ApplicationGrantSet = Unable to determine granted permission for application.
+IsolatedStorage_Init = Initialization failed.
+IsolatedStorage_ApplicationNoEvidence = Unable to determine identity of application.
+IsolatedStorage_AssemblyNoEvidence = Unable to determine identity of assembly.
+IsolatedStorage_DomainNoEvidence = Unable to determine the identity of domain.
+IsolatedStorage_DeleteDirectories = Unable to delete; directory or files in the directory could be in use.
+IsolatedStorage_DeleteFile = Unable to delete file.
+IsolatedStorage_CreateDirectory = Unable to create directory.
+IsolatedStorage_DeleteDirectory = Unable to delete, directory not empty or does not exist.
+IsolatedStorage_Operation_ISFS = Operation not permitted on IsolatedStorageFileStream.
+IsolatedStorage_Operation = Operation not permitted.
+IsolatedStorage_Path = Path must be a valid file name.
+IsolatedStorage_FileOpenMode = Invalid mode, see System.IO.FileMode.
+IsolatedStorage_SeekOrigin = Invalid origin, see System.IO.SeekOrigin.
+IsolatedStorage_Scope_U_R_M = Invalid scope, expected User, User|Roaming or Machine.
+IsolatedStorage_Scope_Invalid = Invalid scope.
+IsolatedStorage_Exception = An error occurred while accessing IsolatedStorage.
+IsolatedStorage_QuotaIsUndefined = {0} is not defined for this store. An operation was performed that requires access to {0}. Stores obtained using enumeration APIs do not have a well-defined {0}, since partial evidence is used to open the store.
+IsolatedStorage_CurrentSizeUndefined = Current size cannot be determined for this store.
+IsolatedStorage_DomainUndefined = Domain cannot be determined on an Assembly or Application store.
+IsolatedStorage_ApplicationUndefined = Application cannot be determined on an Assembly or Domain store.
+IsolatedStorage_AssemblyUndefined = Assembly cannot be determined for an Application store.
+IsolatedStorage_StoreNotOpen = Store must be open for this operation.
+IsolatedStorage_OldQuotaLarger = The new quota must be larger than the old quota.
+IsolatedStorage_UsageWillExceedQuota = There is not enough free space to perform the operation.
+IsolatedStorage_NotValidOnDesktop = The Site scope is currently not supported.
+IsolatedStorage_OnlyIncreaseUserApplicationStore = Increasing the quota of this scope is not supported. Only the user application scope’s quota can be increased.
+#endif // FEATURE_ISOSTORE
+
+; Verification Exception
+Verification_Exception = Operation could destabilize the runtime.
+
+; IL stub marshaler exceptions
+Marshaler_StringTooLong = Marshaler restriction: Excessively long string.
+
+; Missing (General)
+MissingConstructor_Name = Constructor on type '{0}' not found.
+MissingField = Field not found.
+MissingField_Name = Field '{0}' not found.
+MissingMember = Member not found.
+MissingMember_Name = Member '{0}' not found.
+MissingMethod_Name = Method '{0}' not found.
+MissingModule = Module '{0}' not found.
+MissingType = Type '{0}' not found.
+
+; MissingManifestResourceException
+Arg_MissingManifestResourceException = Unable to find manifest resource.
+MissingManifestResource_LooselyLinked = Could not find a manifest resource entry called "{0}" in assembly "{1}". Please check spelling, capitalization, and build rules to ensure "{0}" is being linked into the assembly.
+MissingManifestResource_NoNeutralAsm = Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "{0}" was correctly embedded or linked into assembly "{1}" at compile time, or that all the satellite assemblies required are loadable and fully signed.
+MissingManifestResource_NoNeutralDisk = Could not find any resources appropriate for the specified culture (or the neutral culture) on disk.
+MissingManifestResource_MultipleBlobs = A case-insensitive lookup for resource file "{0}" in assembly "{1}" found multiple entries. Remove the duplicates or specify the exact case.
+MissingManifestResource_ResWFileNotLoaded = Unable to load resources for resource file "{0}" in package "{1}".
+MissingManifestResource_NoPRIresources = Unable to open Package Resource Index.
+
+; MissingMember
+MissingMemberTypeRef = FieldInfo does not match the target Type.
+MissingMemberNestErr = TypedReference can only be made on nested value Types.
+
+; MissingSatelliteAssemblyException
+MissingSatelliteAssembly_Default = Resource lookup fell back to the ultimate fallback resources in a satellite assembly, but that satellite either was not found or could not be loaded. Please consider reinstalling or repairing the application.
+MissingSatelliteAssembly_Culture_Name = The satellite assembly named "{1}" for fallback culture "{0}" either could not be found or could not be loaded. This is generally a setup problem. Please consider reinstalling or repairing the application.
+
+; MulticastNotSupportedException
+Multicast_Combine = Delegates that are not of type MulticastDelegate may not be combined.
+
+; NotImplementedException
+Arg_NotImplementedException = The method or operation is not implemented.
+NotImplemented_ResourcesLongerThan2^63 = Resource files longer than 2^63 bytes are not currently implemented.
+
+; NotSupportedException
+NotSupported_NYI = This feature is not currently implemented.
+NotSupported_AbstractNonCLS = This non-CLS method is not implemented.
+NotSupported_ChangeType = ChangeType operation is not supported.
+NotSupported_ByRefLike = Cannot create boxed ByRef-like values.
+NotSupported_ByRefLike[] = Cannot create arrays of ByRef-like values.
+NotSupported_OpenType = Cannot create arrays of open type.
+NotSupported_DBNullSerial = Only one DBNull instance may exist, and calls to DBNull deserialization methods are not allowed.
+NotSupported_DelegateSerHolderSerial = DelegateSerializationHolder objects are designed to represent a delegate during serialization and are not serializable themselves.
+NotSupported_DelegateCreationFromPT = Application code cannot use Activator.CreateInstance to create types that derive from System.Delegate. Delegate.CreateDelegate can be used instead.
+NotSupported_EncryptionNeedsNTFS = File encryption support only works on NTFS partitions.
+NotSupported_FileStreamOnNonFiles = FileStream was asked to open a device that was not a file. For support for devices like 'com1:' or 'lpt1:', call CreateFile, then use the FileStream constructors that take an OS handle as an IntPtr.
+NotSupported_FixedSizeCollection = Collection was of a fixed size.
+NotSupported_KeyCollectionSet = Mutating a key collection derived from a dictionary is not allowed.
+NotSupported_ValueCollectionSet = Mutating a value collection derived from a dictionary is not allowed.
+NotSupported_MemStreamNotExpandable = Memory stream is not expandable.
+NotSupported_ObsoleteResourcesFile = Found an obsolete .resources file in assembly '{0}'. Rebuild that .resources file then rebuild that assembly.
+NotSupported_OleAutBadVarType = The given Variant type is not supported by this OleAut function.
+NotSupported_PopulateData = This Surrogate does not support PopulateData().
+NotSupported_ReadOnlyCollection = Collection is read-only.
+NotSupported_RangeCollection = The specified operation is not supported on Ranges.
+NotSupported_SortedListNestedWrite = This operation is not supported on SortedList nested types because they require modifying the original SortedList.
+NotSupported_SubclassOverride = Derived classes must provide an implementation.
+NotSupported_TypeCannotDeserialized = Direct deserialization of type '{0}' is not supported.
+NotSupported_UnreadableStream = Stream does not support reading.
+NotSupported_UnseekableStream = Stream does not support seeking.
+NotSupported_UnwritableStream = Stream does not support writing.
+NotSupported_CannotWriteToBufferedStreamIfReadBufferCannotBeFlushed = Cannot write to a BufferedStream while the read buffer is not empty if the underlying stream is not seekable. Ensure that the stream underlying this BufferedStream can seek or avoid interleaving read and write operations on this BufferedStream.
+NotSupported_Method = Method is not supported.
+NotSupported_Constructor = Object cannot be created through this constructor.
+NotSupported_DynamicModule = The invoked member is not supported in a dynamic module.
+NotSupported_TypeNotYetCreated = The invoked member is not supported before the type is created.
+NotSupported_SymbolMethod = Not supported in an array method of a type definition that is not complete.
+NotSupported_NotDynamicModule = The MethodRental.SwapMethodBody method can only be called to swap the method body of a method in a dynamic module.
+NotSupported_DynamicAssembly = The invoked member is not supported in a dynamic assembly.
+NotSupported_NotAllTypesAreBaked = Type '{0}' was not completed.
+NotSupported_CannotSaveModuleIndividually = Unable to save a ModuleBuilder if it was created underneath an AssemblyBuilder. Call Save on the AssemblyBuilder instead.
+NotSupported_MaxWaitHandles = The number of WaitHandles must be less than or equal to 64.
+NotSupported_IllegalOneByteBranch = Illegal one-byte branch at position: {0}. Requested branch was: {1}.
+NotSupported_OutputStreamUsingTypeBuilder = Output streams do not support TypeBuilders.
+NotSupported_ValueClassCM = Custom marshalers for value types are not currently supported.
+NotSupported_Void[] = Arrays of System.Void are not supported.
+NotSupported_NoParentDefaultConstructor = Parent does not have a default constructor. The default constructor must be explicitly defined.
+NotSupported_NonReflectedType = Not supported in a non-reflected type.
+NotSupported_GlobalFunctionNotBaked = The type definition of the global function is not completed.
+NotSupported_SecurityPermissionUnion = Union is not implemented.
+NotSupported_UnitySerHolder = The UnitySerializationHolder object is designed to transmit information about other types and is not serializable itself.
+NotSupported_UnknownTypeCode = TypeCode '{0}' was not valid.
+NotSupported_WaitAllSTAThread = WaitAll for multiple handles on a STA thread is not supported.
+NotSupported_SignalAndWaitSTAThread = SignalAndWait on a STA thread is not supported.
+NotSupported_CreateInstanceWithTypeBuilder = CreateInstance cannot be used with an object of type TypeBuilder.
+NotSupported_NonUrlAttrOnMBR = UrlAttribute is the only attribute supported for MarshalByRefObject.
+NotSupported_ActivAttrOnNonMBR = Activation Attributes are not supported for types not deriving from MarshalByRefObject.
+NotSupported_ActivForCom = Activation Attributes not supported for COM Objects.
+NotSupported_NoCodepageData = No data is available for encoding {0}. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.
+NotSupported_CodePage50229 = The ISO-2022-CN Encoding (Code page 50229) is not supported.
+NotSupported_DynamicAssemblyNoRunAccess = Cannot execute code on a dynamic assembly without run access.
+NotSupported_IDispInvokeDefaultMemberWithNamedArgs = Invoking default method with named arguments is not supported.
+NotSupported_Type = Type is not supported.
+NotSupported_GetMethod = The 'get' method is not supported on this property.
+NotSupported_SetMethod = The 'set' method is not supported on this property.
+NotSupported_DeclarativeUnion = Declarative unionizing of these permissions is not supported.
+NotSupported_StringComparison = The string comparison type passed in is currently not supported.
+NotSupported_WrongResourceReader_Type = This .resources file should not be read with this reader. The resource reader type is "{0}".
+NotSupported_MustBeModuleBuilder = Module argument must be a ModuleBuilder.
+NotSupported_CallToVarArg = Vararg calling convention not supported.
+NotSupported_TooManyArgs = Stack size too deep. Possibly too many arguments.
+NotSupported_DeclSecVarArg = Assert, Deny, and PermitOnly are not supported on methods with a Vararg calling convention.
+NotSupported_AmbiguousIdentity = The operation is ambiguous because the permission represents multiple identities.
+NotSupported_DynamicMethodFlags = Wrong MethodAttributes or CallingConventions for DynamicMethod. Only public, static, standard supported
+NotSupported_GlobalMethodSerialization = Serialization of global methods (including implicit serialization via the use of asynchronous delegates) is not supported.
+NotSupported_InComparableType = A type must implement IComparable<T> or IComparable to support comparison.
+NotSupported_ManagedActivation = Cannot create uninitialized instances of types requiring managed activation.
+NotSupported_ByRefReturn = ByRef return value not supported in reflection invocation.
+NotSupported_DelegateMarshalToWrongDomain = Delegates cannot be marshaled from native code into a domain other than their home domain.
+NotSupported_ResourceObjectSerialization = Cannot read resources that depend on serialization.
+NotSupported_One = The arithmetic type '{0}' cannot represent the number one.
+NotSupported_Zero = The arithmetic type '{0}' cannot represent the number zero.
+NotSupported_MaxValue = The arithmetic type '{0}' does not have a maximum value.
+NotSupported_MinValue = The arithmetic type '{0}' does not have a minimum value.
+NotSupported_PositiveInfinity = The arithmetic type '{0}' cannot represent positive infinity.
+NotSupported_NegativeInfinity = The arithmetic type '{0}' cannot represent negative infinity.
+NotSupported_UmsSafeBuffer = This operation is not supported for an UnmanagedMemoryStream created from a SafeBuffer.
+NotSupported_Reading = Accessor does not support reading.
+NotSupported_Writing = Accessor does not support writing.
+NotSupported_UnsafePointer = This accessor was created with a SafeBuffer; use the SafeBuffer to gain access to the pointer.
+NotSupported_CollectibleCOM = COM Interop is not supported for collectible types.
+NotSupported_CollectibleAssemblyResolve = Resolving to a collectible assembly is not supported.
+NotSupported_CollectibleBoundNonCollectible = A non-collectible assembly may not reference a collectible assembly.
+NotSupported_CollectibleDelegateMarshal = Delegate marshaling for types within collectible assemblies is not supported.
+NotSupported_NonStaticMethod = Non-static methods with NativeCallableAttribute are not supported.
+NotSupported_NativeCallableTarget = Methods with NativeCallableAttribute cannot be used as delegate target.
+NotSupported_GenericMethod = Generic methods with NativeCallableAttribute are not supported.
+NotSupported_NonBlittableTypes = Non-blittable parameter types are not supported for NativeCallable methods.
+
+#if FEATURE_WINDOWSPHONE
+NotSupported_UserDllImport = DllImport cannot be used on user-defined methods.
+NotSupported_UserCOM = COM Interop is not supported for user-defined types.
+#endif //FEATURE_WINDOWSPHONE
+#if FEATURE_CAS_POLICY
+NotSupported_RequiresCasPolicyExplicit = This method explicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information.
+NotSupported_RequiresCasPolicyImplicit = This method implicitly uses CAS policy, which has been obsoleted by the .NET Framework. In order to enable CAS policy for compatibility reasons, please use the NetFx40_LegacySecurityPolicy configuration switch. Please see http://go.microsoft.com/fwlink/?LinkID=155570 for more information.
+NotSupported_CasDeny = The Deny stack modifier has been obsoleted by the .NET Framework. Please see http://go.microsoft.com/fwlink/?LinkId=155571 for more information.
+NotSupported_SecurityContextSourceAppDomainInHeterogenous = SecurityContextSource.CurrentAppDomain is not supported in heterogenous AppDomains.
+#endif // FEATURE_CAS_POLICY
+#if FEATURE_APPX
+NotSupported_AppX = {0} is not supported in AppX.
+LoadOfFxAssemblyNotSupported_AppX = {0} of .NET Framework assemblies is not supported in AppX.
+#endif
+#if FEATURE_COMINTEROP
+NotSupported_WinRT_PartialTrust = Windows Runtime is not supported in partial trust.
+#endif // FEATURE_COMINTEROP
+; ReflectionTypeLoadException
+ReflectionTypeLoad_LoadFailed = Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
+#if !FEATURE_CORECLR
+NotSupported_NoTypeInfo = Cannot resolve {0} to a TypeInfo object.
+#endif
+#if FEATURE_COMINTEROP
+NotSupported_PIAInAppxProcess = A Primary Interop Assembly is not supported in AppX.
+#endif
+#if FEATURE_WINDOWSPHONE
+; Not referring to "Windows Phone" in the messages, as FEATURE_WINDOWSPHONE is defined for .NET Core as well.
+NotSupported_WindowsPhone = {0} is not supported.
+NotSupported_AssemblyLoadCodeBase = Assembly.Load with a Codebase is not supported.
+#endif
+
+; TypeLoadException
+TypeLoad_ResolveType = Could not resolve type '{0}'.
+TypeLoad_ResolveTypeFromAssembly = Could not resolve type '{0}' in assembly '{1}'.
+TypeLoad_ResolveNestedType = Could not resolve nested type '{0}' in type "{1}'.
+FileNotFound_ResolveAssembly = Could not resolve assembly '{0}'.
+
+; NullReferenceException
+NullReference_This = The pointer for this method was null.
+
+; ObjectDisposedException
+ObjectDisposed_Generic = Cannot access a disposed object.
+ObjectDisposed_FileClosed = Cannot access a closed file.
+ObjectDisposed_ObjectName_Name = Object name: '{0}'.
+ObjectDisposed_ReaderClosed = Cannot read from a closed TextReader.
+ObjectDisposed_ResourceSet = Cannot access a closed resource set.
+ObjectDisposed_RegKeyClosed = Cannot access a closed registry key.
+ObjectDisposed_StreamClosed = Cannot access a closed Stream.
+ObjectDisposed_WriterClosed = Cannot write to a closed TextWriter.
+ObjectDisposed_ViewAccessorClosed = Cannot access a closed accessor.
+
+; OperationCanceledException
+OperationCanceled = The operation was canceled.
+
+; OutOfMemoryException
+OutOfMemory_GCHandleMDA = The GCHandle MDA has run out of available cookies.
+
+; OverflowException
+Overflow_Byte = Value was either too large or too small for an unsigned byte.
+Overflow_Char = Value was either too large or too small for a character.
+Overflow_Currency = Value was either too large or too small for a Currency.
+Overflow_Decimal = Value was either too large or too small for a Decimal.
+Overflow_Int16 = Value was either too large or too small for an Int16.
+Overflow_Int32 = Value was either too large or too small for an Int32.
+Overflow_Int64 = Value was either too large or too small for an Int64.
+Overflow_NegateTwosCompNum = Negating the minimum value of a twos complement number is invalid.
+Overflow_NegativeUnsigned = The string was being parsed as an unsigned number and could not have a negative sign.
+Overflow_SByte = Value was either too large or too small for a signed byte.
+Overflow_Single = Value was either too large or too small for a Single.
+Overflow_Double = Value was either too large or too small for a Double.
+Overflow_TimeSpanTooLong = TimeSpan overflowed because the duration is too long.
+Overflow_TimeSpanElementTooLarge = The TimeSpan could not be parsed because at least one of the numeric components is out of range or contains too many digits.
+Overflow_Duration = The duration cannot be returned for TimeSpan.MinValue because the absolute value of TimeSpan.MinValue exceeds the value of TimeSpan.MaxValue.
+Overflow_UInt16 = Value was either too large or too small for a UInt16.
+Overflow_UInt32 = Value was either too large or too small for a UInt32.
+Overflow_UInt64 = Value was either too large or too small for a UInt64.
+
+; PlatformNotsupportedException
+PlatformNotSupported_RequiresLonghorn = This operation is only supported on Windows Vista and above.
+PlatformNotSupported_RequiresNT = This operation is only supported on Windows 2000, Windows XP, and higher.
+PlatformNotSupported_RequiresW2kSP3 = This operation is only supported on Windows 2000 SP3 or later operating systems.
+#if FEATURE_COMINTEROP
+PlatformNotSupported_WinRT = Windows Runtime is not supported on this operating system.
+#endif // FEATURE_COMINTEROP
+
+; PolicyException
+; This still appears in bcl.small but should go away eventually
+Policy_Default = Error occurred while performing a policy operation.
+Policy_CannotLoadSemiTrustAssembliesDuringInit = All assemblies loaded as part of AppDomain initialization must be fully trusted.
+#if FEATURE_IMPERSONATION
+Policy_PrincipalTwice = Default principal object cannot be set twice.
+#endif // FEATURE_IMPERSONATION
+#if FEATURE_CAS_POLICY
+Policy_PolicyAlreadySet = Policy for this domain cannot be set twice.
+Policy_NoExecutionPermission = Execution permission cannot be acquired.
+Policy_NoRequiredPermission = Required permissions cannot be acquired.
+Policy_MultipleExclusive = More than one exclusive group is not allowed.
+Policy_RecoverNotFileBased = PolicyLevel object not based on a file cannot be recovered.
+Policy_RecoverNoConfigFile = No old configuration file exists to recover.
+Policy_UnableToSave = Policy level '{0}' could not be saved: {1}.
+Policy_BadXml = Policy configuration XML is invalid. The required tag '{0}' is missing.
+Policy_NonFullTrustAssembly = Policy references an assembly not in the full trust assemblies list.
+Policy_MissingActivationContextInAppEvidence = The application evidence does not contain a Fusion activation context.
+Policy_NoTrustManager = A trust manager could not be loaded for this application.
+Policy_GrantSetDoesNotMatchDomain = An assembly was provided an invalid grant set by runtime host '{0}'. In a homogenous AppDomain, the only valid grant sets are FullTrust and the AppDomain's sandbox grant set.
+#endif // FEATURE_CAS_POLICY
+Policy_SaveNotFileBased = PolicyLevel object not based on a file cannot be saved.
+Policy_AppTrustMustGrantAppRequest = ApplicationTrust grant set does not contain ActivationContext's minimum request set.
+
+Error_SecurityPolicyFileParse = Error occurred while parsing the '{0}' policy level. The default policy level was used instead.
+Error_SecurityPolicyFileParseEx = Error '{1}' occurred while parsing the '{0}' policy level. The default policy level was used instead.
+
+#if FEATURE_CAS_POLICY
+Policy_EvidenceMustBeSerializable = Objects used as evidence must be serializable.
+Policy_DuplicateEvidence = The evidence collection already contains evidence of type '{0}'. Multiple pieces of the same type of evidence are not allowed.
+Policy_IncorrectHostEvidence = Runtime host '{0}' returned evidence of type '{1}' from a request for evidence of type '{2}'.
+Policy_NullHostEvidence = Runtime host '{0}' returned null when asked for assembly evidence for assembly '{1}'.
+Policy_NullHostGrantSet = Runtime host '{0}' returned a null grant set from ResolvePolicy.
+#endif // FEATURE_CAS_POLICY
+
+; Policy codegroup and permission set names and descriptions
+#if FEATURE_CAS_POLICY
+Policy_AllCode_Name = All_Code
+Policy_AllCode_DescriptionFullTrust = Code group grants all code full trust and forms the root of the code group tree.
+Policy_AllCode_DescriptionNothing = Code group grants no permissions and forms the root of the code group tree.
+Policy_MyComputer_Name = My_Computer_Zone
+Policy_MyComputer_Description = Code group grants full trust to all code originating on the local computer
+Policy_Intranet_Name = LocalIntranet_Zone
+Policy_Intranet_Description = Code group grants the intranet permission set to code from the intranet zone. This permission set grants intranet code the right to use isolated storage, full UI access, some capability to do reflection, and limited access to environment variables.
+Policy_IntranetNet_Name = Intranet_Same_Site_Access
+Policy_IntranetNet_Description = All intranet code gets the right to connect back to the site of its origin.
+Policy_IntranetFile_Name = Intranet_Same_Directory_Access
+Policy_IntranetFile_Description = All intranet code gets the right to read from its install directory.
+Policy_Internet_Name = Internet_Zone
+Policy_Internet_Description = Code group grants code from the Internet zone the Internet permission set. This permission set grants Internet code the right to use isolated storage and limited UI access.
+Policy_InternetNet_Name = Internet_Same_Site_Access
+Policy_InternetNet_Description = All Internet code gets the right to connect back to the site of its origin.
+Policy_Trusted_Name = Trusted_Zone
+Policy_Trusted_Description = Code from a trusted zone is granted the Internet permission set. This permission set grants the right to use isolated storage and limited UI access.
+Policy_TrustedNet_Name = Trusted_Same_Site_Access
+Policy_TrustedNet_Description = All Trusted Code gets the right to connect back to the site of its origin.
+Policy_Untrusted_Name = Restricted_Zone
+Policy_Untrusted_Description = Code coming from a restricted zone does not receive any permissions.
+Policy_Microsoft_Name = Microsoft_Strong_Name
+Policy_Microsoft_Description = Code group grants full trust to code signed with the Microsoft strong name.
+Policy_Ecma_Name = ECMA_Strong_Name
+Policy_Ecma_Description = Code group grants full trust to code signed with the ECMA strong name.
+
+; Policy permission set descriptions
+Policy_PS_FullTrust = Allows full access to all resources
+Policy_PS_Everything = Allows unrestricted access to all resources covered by built-in permissions
+Policy_PS_Nothing = Denies all resources, including the right to execute
+Policy_PS_Execution = Permits execution
+Policy_PS_SkipVerification = Grants right to bypass the verification
+Policy_PS_Internet = Default rights given to Internet applications
+Policy_PS_LocalIntranet = Default rights given to applications on the local intranet
+
+; default Policy level names
+Policy_PL_Enterprise = Enterprise
+Policy_PL_Machine = Machine
+Policy_PL_User = User
+Policy_PL_AppDomain = AppDomain
+#endif // FEATURE_CAS_POLICY
+
+; RankException
+Rank_MultiDimNotSupported = Only single dimension arrays are supported here.
+Rank_MustMatch = The specified arrays must have the same number of dimensions.
+
+; TypeInitializationException
+TypeInitialization_Default = Type constructor threw an exception.
+TypeInitialization_Type = The type initializer for '{0}' threw an exception.
+
+; TypeLoadException
+
+
+;
+; Reflection exceptions
+;
+RtType.InvalidCaller = Caller is not a friend.
+
+;CustomAttributeFormatException
+RFLCT.InvalidPropFail = '{0}' property specified was not found.
+RFLCT.InvalidFieldFail = '{0}' field specified was not found.
+
+;InvalidFilterCriteriaException
+RFLCT.FltCritString = A String must be provided for the filter criteria.
+RFLCT.FltCritInt = An Int32 must be provided for the filter criteria.
+
+; TargetException
+RFLCT.Targ_ITargMismatch = Object does not match target type.
+RFLCT.Targ_StatMethReqTarg = Non-static method requires a target.
+RFLCT.Targ_StatFldReqTarg = Non-static field requires a target.
+
+;AmbiguousMatchException
+RFLCT.Ambiguous = Ambiguous match found.
+RFLCT.AmbigCust = Multiple custom attributes of the same type found.
+
+;
+; Remoting exceptions
+;
+Remoting_AppDomainUnloaded_ThreadUnwound = The application domain in which the thread was running has been unloaded.
+Remoting_AppDomainUnloaded = The target application domain has been unloaded.
+Remoting_CantRemotePointerType = Pointer types cannot be passed in a remote call.
+Remoting_TypeCantBeRemoted = The given type cannot be passed in a remote call.
+Remoting_Delegate_TooManyTargets = The delegate must have only one target.
+Remoting_InvalidContext = The context is not valid.
+Remoting_InvalidValueTypeFieldAccess = An attempt was made to calculate the address of a value type field on a remote object. This was likely caused by an attempt to directly get or set the value of a field within this embedded value type. Avoid this and instead provide and use access methods for each field in the object that will be accessed remotely.
+Remoting_Message_BadRetValOrOutArg = Bad return value or out-argument inside the return message.
+Remoting_NonPublicOrStaticCantBeCalledRemotely = Permission denied: cannot call non-public or static methods remotely.
+Remoting_Proxy_ProxyTypeIsNotMBR = classToProxy argument must derive from MarshalByRef type.
+Remoting_TP_NonNull = The transparent proxy field of a real proxy must be null.
+#if FEATURE_REMOTING
+Remoting_Activation_BadAttribute = Activation attribute does not implement the IContextAttribute interface.
+Remoting_Activation_BadObject = Proxy Attribute returned an incompatible object when constructing an instance of type {0}.
+Remoting_Activation_MBR_ProxyAttribute = Proxy Attributes are supported on ContextBound types only.
+Remoting_Activation_ConnectFailed = An attempt to connect to the remote activator failed with exception '{0}'.
+Remoting_Activation_Failed = Activation failed due to an unknown reason.
+Remoting_Activation_InconsistentState = Inconsistent state during activation; there may be two proxies for the same object.
+Remoting_Activation_MissingRemoteAppEntry = Cannot find an entry for remote application '{0}'.
+Remoting_Activation_NullReturnValue = Return value of construction call was null.
+Remoting_Activation_NullFromInternalUnmarshal = InternalUnmarshal of returned ObjRef from activation call returned null.
+Remoting_Activation_WellKnownCTOR = Cannot run a non-default constructor when connecting to well-known objects.
+Remoting_Activation_PermissionDenied = Type '{0}' is not registered for activation.
+Remoting_Activation_PropertyUnhappy = A context property did not approve the candidate context for activating the object.
+Remoting_Activation_AsyncUnsupported = Async Activation not supported.
+Remoting_AmbiguousCTOR = Cannot resolve the invocation to the correct constructor.
+Remoting_AmbiguousMethod = Cannot resolve the invocation to the correct method.
+Remoting_AppDomains_NYI = This feature is not yet supported for cross-application domain.
+Remoting_AppDomainsCantBeCalledRemotely = Permission denied: cannot call methods on the AppDomain class remotely.
+Remoting_AssemblyLoadFailed = Cannot load assembly '{0}'.
+Remoting_Attribute_UseAttributeNotsettable = UseAttribute not allowed in SoapTypeAttribute.
+Remoting_BadType = Cannot load type '{0}'.
+Remoting_BadField = Remoting cannot find field '{0}' on type '{1}'.
+Remoting_BadInternalState_ActivationFailure = Invalid internal state: Activation service failed to initialize.
+Remoting_BadInternalState_ProxySameAppDomain = Invalid internal state: A marshal by ref object should not have a proxy in its own AppDomain.
+Remoting_BadInternalState_FailEnvoySink = Invalid internal state: Failed to create an envoy sink for the object.
+Remoting_CantDisconnectClientProxy = Cannot call disconnect on a proxy.
+Remoting_CantInvokeIRemoteDispatch = Cannot invoke methods on IRemoteDispatch.
+Remoting_ChannelNameAlreadyRegistered = The channel '{0}' is already registered.
+Remoting_ChannelNotRegistered = The channel '{0}' is not registered with remoting services.
+Remoting_Channel_PopOnEmptySinkStack = Tried to pop data from an empty channel sink stack.
+Remoting_Channel_PopFromSinkStackWithoutPush = A channel sink tried to pop data from the stack without first pushing data onto the stack.
+Remoting_Channel_StoreOnEmptySinkStack = A channel sink called the Store method when the sink stack was empty.
+Remoting_Channel_StoreOnSinkStackWithoutPush = A channel sink called the Store method on the sink stack without first pushing data onto the stack.
+Remoting_Channel_CantCallAPRWhenStackEmpty = Cannot call the AsyncProcessResponse method on the previous channel sink because the stack is empty.
+Remoting_Channel_CantCallFRSWhenStackEmtpy = Called FlipRememberedStack() when stack was not null.
+Remoting_Channel_CantCallGetResponseStreamWhenStackEmpty = Cannot call the GetResponseStream method on the previous channel sink because the stack is empty.
+Remoting_Channel_DispatchSinkMessageMissing = No message was deserialized prior to calling the DispatchChannelSink.
+Remoting_Channel_DispatchSinkWantsNullRequestStream = The request stream should be null when the DispatchChannelSink is called.
+Remoting_Channel_CannotBeSecured = Channel {0} cannot be secured. Please consider using a channel that implements ISecurableChannel
+Remoting_Config_ChannelMissingCtor = To be used from a .config file, the channel type '{0}' must have a constructor of the form '{1}'
+Remoting_Config_SinkProviderMissingCtor = To be used from a .config file, the sink provider type '{0}' must have a constructor of the form '{1}'
+Remoting_Config_SinkProviderNotFormatter = A sink provider of type '{0}' is incorrectly labeled as a 'formatter'.
+Remoting_Config_ConfigurationFailure = Remoting configuration failed with the exception '{0}'.
+Remoting_Config_InvalidTimeFormat = Invalid time format '{0}'. Examples of valid time formats include 7D, 10H, 5M, 30S, or 20MS.
+Remoting_Config_AppNameSet = The remoting application name, '{0}', had already been set.
+Remoting_Config_ErrorsModeSet = The remoting custom errors mode had already been set.
+Remoting_Config_CantRedirectActivationOfWellKnownService = Attempt to redirect activation for type '{0}, {1}'. This is not allowed since either a well-known service type has already been registered with that type or that type has been registered has a activated service type.
+Remoting_Config_CantUseRedirectedTypeForWellKnownService = Attempt to register a well-known or activated service type of type '{0}, {1}'. This is not allowed since the type has already been redirected to activate elsewhere.
+Remoting_Config_InvalidChannelType = '{0}' does not implement IChannelReceiver or IChannelSender. All channels must implement one of these interfaces.
+Remoting_Config_InvalidSinkProviderType = Unable to use '{0}' as a channel sink provider. It does not implement '{1}'.
+Remoting_Config_MissingWellKnownModeAttribute = Well-known service entries must contain a 'mode' attribute with a value of 'Singleton' or 'SingleCall'.
+Remoting_Config_MissingTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'typeName, assemblyName'.
+Remoting_Config_MissingXmlTypeAttribute = '{0}' entries must contain a '{1}' attribute of the form 'xmlTypeName, xmlTypeNamespace'.
+Remoting_Config_NoAppName = Improper remoting configuration: missing ApplicationName property.
+Remoting_Config_NonTemplateIdAttribute = Only '{0}' templates can have an 'id' attribute.
+Remoting_Config_PreloadRequiresTypeOrAssembly = Preload entries require a type or assembly attribute.
+Remoting_Config_ProviderNeedsElementName = Sink providers must have an element name of 'formatter' or 'provider'.
+Remoting_Config_RequiredXmlAttribute = '{0}' entries require a '{1}' attribute.
+Remoting_Config_ReadFailure = .Config file '{0}' cannot be read successfully due to exception '{1}'.
+Remoting_Config_NodeMustBeUnique = There can be only one '{0}' node in the '{1}' section of a config file.
+Remoting_Config_TemplateCannotReferenceTemplate = A '{0}' template cannot reference another '{0}' template.
+Remoting_Config_TypeAlreadyRedirected = Attempt to redirect activation of type '{0}, {1}' which is already redirected.
+Remoting_Config_UnknownValue = Unknown value {1} was found on the {0} node.
+Remoting_Config_UnableToResolveTemplate = Cannot resolve '{0}' template reference: '{1}'.
+Remoting_Config_VersionPresent = Version information is present in the assembly name '{0}' which is not allowed for '{1}' entries.
+Remoting_Contexts_BadProperty = A property that contributed a bad sink to the chain was found.
+Remoting_Contexts_NoProperty = A property with the name '{0}' was not found.
+Remoting_Contexts_ContextNotFrozenForCallBack = Context should be frozen before calling the DoCallBack method.
+Remoting_Default = Unknown remoting error.
+Remoting_HandlerNotRegistered = The tracking handler of type '{0}' is not registered with Remoting Services.
+Remoting_InvalidMsg = Invalid Message Object.
+Remoting_InvalidCallingType = Attempted to call a method declared on type '{0}' on an object which exposes '{1}'.
+Remoting_InvalidRequestedType = The server object type cannot be cast to the requested type '{0}'.
+Remoting_InternalError = Server encountered an internal error. For more information, turn off customErrors in the server's .config file.
+Remoting_Lifetime_ILeaseReturn = Expected a return object of type ILease, but received '{0}'.
+Remoting_Lifetime_InitialStateInitialLeaseTime = InitialLeaseTime property can only be set when the lease is in initial state. The state is '{0}'.
+Remoting_Lifetime_InitialStateRenewOnCall = RenewOnCallTime property can only be set when the lease is in initial state. The state is '{0}'.
+Remoting_Lifetime_InitialStateSponsorshipTimeout = SponsorshipTimeout property can only be set when the lease is in initial state. State is '{0}'.
+Remoting_Lifetime_SetOnce = '{0}' can only be set once within an AppDomain.
+Remoting_Message_ArgMismatch = {2} arguments were passed to '{0}::{1}'. {3} arguments were expected by this method.
+Remoting_Message_BadAsyncResult = The async result object is null or of an unexpected type.
+Remoting_Message_BadType = The method was called with a Message of an unexpected type.
+Remoting_Message_CoercionFailed = The argument type '{0}' cannot be converted into parameter type '{1}'.
+Remoting_Message_MissingArgValue = Expecting an instance of type '{0}' at pos {1} in the args array.
+Remoting_Message_BadSerialization = Invalid or malformed serialization information for the message object.
+Remoting_NoIdentityEntry = No remoting information was found for this object.
+Remoting_NotRemotableByReference = Trying to create a proxy to an unbound type.
+Remoting_NullMessage = The method was called with a null message.
+Remoting_Proxy_BadType = The proxy is of an unsupported type.
+Remoting_ResetURI = Attempt to reset the URI for an object from '{0}' to '{1}'.
+Remoting_ServerObjectNotFound = The server object for URI '{0}' is not registered with the remoting infrastructure (it may have been disconnected).
+Remoting_SetObjectUriForMarshal__ObjectNeedsToBeLocal = SetObjectUriForMarshal method should only be called for MarshalByRefObjects that exist in the current AppDomain.
+Remoting_SetObjectUriForMarshal__UriExists = SetObjectUriForMarshal method has already been called on this object or the object has already been marshaled.
+Remoting_Proxy_BadReturnType = Return argument has an invalid type.
+Remoting_Proxy_ReturnValueTypeCannotBeNull = ByRef value type parameter cannot be null.
+Remoting_Proxy_BadReturnTypeForActivation = Bad return type for activation call via Invoke: must be of type IConstructionReturnMessage.
+Remoting_Proxy_BadTypeForActivation = Type mismatch between proxy type '{0}' and activation type '{1}'.
+Remoting_Proxy_ExpectedOriginalMessage = The message passed to Invoke should be passed to PropagateOutParameters.
+Remoting_Proxy_InvalidCall = Trying to call proxy while constructor call is in progress.
+Remoting_Proxy_InvalidState = Channel sink does not exist. Failed to dispatch async call.
+Remoting_Proxy_NoChannelSink = This remoting proxy has no channel sink which means either the server has no registered server channels that are listening, or this application has no suitable client channel to talk to the server.
+Remoting_Proxy_InvalidCallType = Only the synchronous call type is supported for messages that are not of type Message.
+Remoting_Proxy_WrongContext = ExecuteMessage can be called only from the native context of the object.
+Remoting_SOAPInteropxsdInvalid = Soap Parse error, xsd:type '{0}' invalid {1}
+Remoting_SOAPQNameNamespace = SoapQName missing a Namespace value '{0}'.
+Remoting_ThreadAffinity_InvalidFlag = The specified flag '{0}' does not have one of the valid values.
+Remoting_TrackingHandlerAlreadyRegistered = The handler has already been registered with TrackingServices.
+Remoting_URIClash = Found two different objects associated with the same URI, '{0}'.
+Remoting_URIExists = The remoted object already has an associated URI.
+Remoting_URIToProxy = Trying to associate the URI with a proxy.
+Remoting_WellKnown_MustBeMBR = Attempted to create well-known object of type '{0}'. Well-known objects must derive from the MarshalByRefObject class.
+Remoting_WellKnown_CtorCantMarshal = '{0}': A well-known object cannot marshal itself in its constructor, or perform any action that would cause it to be marshaled (such as passing the 'this' pointer as a parameter to a remote method).
+Remoting_WellKnown_CantDirectlyConnect = Attempt to connect to a server using its object URI: '{0}'. A valid, complete URL must be used.
+Remoting_Connect_CantCreateChannelSink = Cannot create channel sink to connect to URL '{0}'. An appropriate channel has probably not been registered.
+Remoting_UnexpectedNullTP = Failed to create a transparent proxy. If a custom RealProxy is being used ensure it sets the proxy type.
+; The following remoting exception messages appear in native resources too (mscorrc.rc)
+Remoting_Disconnected = Object '{0}' has been disconnected or does not exist at the server.
+Remoting_Message_MethodMissing = The method '{0}' was not found on the interface/type '{1}'.
+#endif // FEATURE_REMOTING
+
+; Resources exceptions
+;
+Resources_StreamNotValid = Stream is not a valid resource file.
+ResourceReaderIsClosed = ResourceReader is closed.
+
+; RuntimeWrappedException
+RuntimeWrappedException = An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException.
+
+; UnauthorizedAccessException
+UnauthorizedAccess_MemStreamBuffer = MemoryStream's internal buffer cannot be accessed.
+UnauthorizedAccess_IODenied_Path = Access to the path '{0}' is denied.
+UnauthorizedAccess_IODenied_NoPathName = Access to the path is denied.
+UnauthorizedAccess_RegistryKeyGeneric_Key = Access to the registry key '{0}' is denied.
+UnauthorizedAccess_RegistryNoWrite = Cannot write to the registry key.
+UnauthorizedAccess_SystemDomain = Cannot execute an assembly in the system domain.
+
+;
+; Security exceptions
+;
+
+;SecurityException
+; These still appear in bcl.small but should go away eventually
+Security_Generic = Request for the permission of type '{0}' failed.
+Security_GenericNoType = Request failed.
+Security_NoAPTCA = That assembly does not allow partially trusted callers.
+Security_RegistryPermission = Requested registry access is not allowed.
+Security_MustRevertOverride = Stack walk modifier must be reverted before another modification of the same type can be performed.
+#if FEATURE_CAS_POLICY
+Security_CannotGenerateHash = Hash for the assembly cannot be generated.
+Security_CannotGetRawData = Assembly bytes could not be retrieved.
+Security_PrincipalPermission = Request for principal permission failed.
+Security_Action = The action that failed was:
+Security_TypeFirstPermThatFailed = The type of the first permission that failed was:
+Security_FirstPermThatFailed = The first permission that failed was:
+Security_Demanded = The demand was for:
+Security_GrantedSet = The granted set of the failing assembly was:
+Security_RefusedSet = The refused set of the failing assembly was:
+Security_Denied = The denied permissions were:
+Security_PermitOnly = The only permitted permissions were:
+Security_Assembly = The assembly or AppDomain that failed was:
+Security_Method = The method that caused the failure was:
+Security_Zone = The Zone of the assembly that failed was:
+Security_Url = The Url of the assembly that failed was:
+Security_AnonymouslyHostedDynamicMethodCheckFailed = The demand failed due to the code access security information captured during the creation of an anonymously hosted dynamic method. In order for this operation to succeed, ensure that the demand would have succeeded at the time the method was created. See http://go.microsoft.com/fwlink/?LinkId=288746 for more information.
+#endif // FEATURE_CAS_POLICY
+
+;
+; HostProtection exceptions
+;
+
+HostProtection_HostProtection = Attempted to perform an operation that was forbidden by the CLR host.
+HostProtection_ProtectedResources = The protected resources (only available with full trust) were:
+HostProtection_DemandedResources = The demanded resources were:
+
+;
+; IO exceptions
+;
+
+; EOFException
+IO.EOF_ReadBeyondEOF = Unable to read beyond the end of the stream.
+
+; FileNotFoundException
+IO.FileNotFound = Unable to find the specified file.
+IO.FileNotFound_FileName = Could not find file '{0}'.
+IO.FileName_Name = File name: '{0}'
+IO.FileLoad = Could not load the specified file.
+
+; IOException
+IO.IO_AlreadyExists_Name = Cannot create "{0}" because a file or directory with the same name already exists.
+IO.IO_BindHandleFailed = BindHandle for ThreadPool failed on this handle.
+IO.IO_FileExists_Name = The file '{0}' already exists.
+IO.IO_FileStreamHandlePosition = The OS handle's position is not what FileStream expected. Do not use a handle simultaneously in one FileStream and in Win32 code or another FileStream. This may cause data loss.
+IO.IO_FileTooLong2GB = The file is too long. This operation is currently limited to supporting files less than 2 gigabytes in size.
+IO.IO_FileTooLongOrHandleNotSync = IO operation will not work. Most likely the file will become too long or the handle was not opened to support synchronous IO operations.
+IO.IO_FixedCapacity = Unable to expand length of this stream beyond its capacity.
+IO.IO_InvalidStringLen_Len = BinaryReader encountered an invalid string length of {0} characters.
+IO.IO_NoConsole = There is no console.
+IO.IO_NoPermissionToDirectoryName = <Path discovery permission to the specified directory was denied.>
+IO.IO_SeekBeforeBegin = An attempt was made to move the position before the beginning of the stream.
+IO.IO_SeekAppendOverwrite = Unable seek backward to overwrite data that previously existed in a file opened in Append mode.
+IO.IO_SetLengthAppendTruncate = Unable to truncate data that previously existed in a file opened in Append mode.
+IO.IO_SharingViolation_File = The process cannot access the file '{0}' because it is being used by another process.
+IO.IO_SharingViolation_NoFileName = The process cannot access the file because it is being used by another process.
+IO.IO_StreamTooLong = Stream was too long.
+IO.IO_CannotCreateDirectory = The specified directory '{0}' cannot be created.
+IO.IO_SourceDestMustBeDifferent = Source and destination path must be different.
+IO.IO_SourceDestMustHaveSameRoot = Source and destination path must have identical roots. Move will not work across volumes.
+
+; DirectoryNotFoundException
+IO.DriveNotFound_Drive = Could not find the drive '{0}'. The drive might not be ready or might not be mapped.
+IO.PathNotFound_Path = Could not find a part of the path '{0}'.
+IO.PathNotFound_NoPathName = Could not find a part of the path.
+
+; PathTooLongException
+IO.PathTooLong = The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
+
+#if FEATURE_CORECLR
+; SecurityException
+FileSecurityState_OperationNotPermitted = File operation not permitted. Access to path '{0}' is denied.
+#endif
+
+; PrivilegeNotHeldException
+PrivilegeNotHeld_Default = The process does not possess some privilege required for this operation.
+PrivilegeNotHeld_Named = The process does not possess the '{0}' privilege which is required for this operation.
+
+; General strings used in the IO package
+IO_UnknownFileName = [Unknown]
+IO_StreamWriterBufferedDataLost = A StreamWriter was not closed and all buffered data within that StreamWriter was not flushed to the underlying stream. (This was detected when the StreamWriter was finalized with data in its buffer.) A portion of the data was lost. Consider one of calling Close(), Flush(), setting the StreamWriter's AutoFlush property to true, or allocating the StreamWriter with a "using" statement. Stream type: {0}\r\nFile name: {1}\r\nAllocated from:\r\n {2}
+IO_StreamWriterBufferedDataLostCaptureAllocatedFromCallstackNotEnabled = callstack information is not captured by default for performance reasons. Please enable captureAllocatedCallStack config switch for streamWriterBufferedDataLost MDA (refer to MSDN MDA documentation for how to do this).
+
+;
+; Serialization Exceptions
+;
+; SerializationException
+Serialization_InvalidData=An error occurred while deserializing the object. The serialized data is corrupt.
+Serialization_InvalidPtrValue = An IntPtr or UIntPtr with an eight byte value cannot be deserialized on a machine with a four byte word size.
+Serialization_MemberTypeNotRecognized = Unknown member type.
+Serialization_InsufficientState = Insufficient state to return the real object.
+Serialization_InvalidFieldState = Object fields may not be properly initialized.
+Serialization_MissField = Field {0} is missing.
+Serialization_NullSignature = The method signature cannot be null.
+Serialization_UnknownMember = Cannot get the member '{0}'.
+Serialization_InsufficientDeserializationState = Insufficient state to deserialize the object. Missing field '{0}'. More information is needed.
+Serialization_UnableToFindModule = The given module {0} cannot be found within the assembly {1}.
+Serialization_InvalidOnDeser = OnDeserialization method was called while the object was not being deserialized.
+Serialization_MissingKeys = The Keys for this Hashtable are missing.
+Serialization_MissingValues = The values for this dictionary are missing.
+Serialization_NullKey = One of the serialized keys is null.
+Serialization_KeyValueDifferentSizes = The keys and values arrays have different sizes.
+Serialization_SameNameTwice = Cannot add the same member twice to a SerializationInfo object.
+Serialization_BadParameterInfo = Non existent ParameterInfo. Position bigger than member's parameters length.
+Serialization_NoParameterInfo = Serialized member does not have a ParameterInfo.
+Serialization_NotFound = Member '{0}' was not found.
+Serialization_StringBuilderMaxCapacity = The serialized MaxCapacity property of StringBuilder must be positive and greater than or equal to the String length.
+Serialization_StringBuilderCapacity = The serialized Capacity property of StringBuilder must be positive, less than or equal to MaxCapacity and greater than or equal to the String length.
+Serialization_InvalidDelegateType = Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator's assembly.
+Serialization_OptionalFieldVersionValue = Version value must be positive.
+Serialization_MissingDateTimeData = Invalid serialized DateTime data. Unable to find 'ticks' or 'dateData'.
+Serialization_DateTimeTicksOutOfRange = Invalid serialized DateTime data. Ticks must be between DateTime.MinValue.Ticks and DateTime.MaxValue.Ticks.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_MemberOutOfRange = The deserialized value of the member "{0}" in the class "{1}" is out of range.
+
+#if FEATURE_SERIALIZATION
+Serialization_NoID = Object has never been assigned an objectID.
+Serialization_UnknownMemberInfo = Only FieldInfo, PropertyInfo, and SerializationMemberInfo are recognized.
+Serialization_UnableToFixup = Cannot perform fixup.
+Serialization_NoType = Object does not specify a type.
+Serialization_ValueTypeFixup = ValueType fixup on Arrays is not implemented.
+Serialization_PartialValueTypeFixup = Fixing up a partially available ValueType chain is not implemented.
+Serialization_InvalidID = Object specifies an invalid ID.
+Serialization_DuplicateSelector = Selector is already on the list of checked selectors.
+Serialization_NoBaseType = Object does not specify a base type.
+Serialization_ArrayNoLength = Array does not specify a length.
+Serialization_CannotGetType = Cannot get the type '{0}'.
+Serialization_AssemblyNotFound = Unable to find assembly '{0}'.
+Serialization_ArrayInvalidLength = Array specifies an invalid length.
+Serialization_MalformedArray = The array information in the stream is invalid.
+Serialization_MultipleMembers = Cannot resolve multiple members with the same name.
+Serialization_ObjectUsedBeforeDeserCallback = An object was used before its deserialization callback ran, which may break higher-level consistency guarantees in the application.
+Serialization_RegisterTwice = An object cannot be registered twice.
+Serialization_IdTooSmall = Object IDs must be greater than zero.
+Serialization_TooManyReferences = The implementation of the IObjectReference interface returns too many nested references to other objects that implement IObjectReference.
+Serialization_NotISer = The given object does not implement the ISerializable interface.
+Serialization_MissingKeyValuePairs = The KeyValuePairs for this Dictionary are missing.
+Serialization_SurrogateCycleInArgument = Selector contained a cycle.
+Serialization_SurrogateCycle = Adding selector will introduce a cycle.
+Serialization_NeverSeen = A fixup is registered to the object with ID {0}, but the object does not appear in the graph.
+Serialization_IORIncomplete = The object with ID {0} implements the IObjectReference interface for which all dependencies cannot be resolved. The likely cause is two instances of IObjectReference that have a mutual dependency on each other.
+Serialization_NotCyclicallyReferenceableSurrogate = {0}.SetObjectData returns a value that is neither null nor equal to the first parameter. Such Surrogates cannot be part of cyclical reference.
+Serialization_ObjectNotSupplied = The object with ID {0} was referenced in a fixup but does not exist.
+Serialization_TooManyElements = The internal array cannot expand to greater than Int32.MaxValue elements.
+Serialization_InvalidType = Only system-provided types can be passed to the GetUninitializedObject method. '{0}' is not a valid instance of a type.
+Serialization_MissingObject = The object with ID {0} was referenced in a fixup but has not been registered.
+Serialization_InvalidFixupType = A member fixup was registered for an object which implements ISerializable or has a surrogate. In this situation, a delayed fixup must be used.
+Serialization_InvalidFixupDiscovered = A fixup on an object implementing ISerializable or having a surrogate was discovered for an object which does not have a SerializationInfo available.
+Serialization_InvalidFormat = The input stream is not a valid binary format. The starting contents (in bytes) are: {0} ...
+Serialization_ParentChildIdentical = The ID of the containing object cannot be the same as the object ID.
+Serialization_IncorrectNumberOfFixups = The ObjectManager found an invalid number of fixups. This usually indicates a problem in the Formatter.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_NonSerType = Type '{0}' in Assembly '{1}' is not marked as serializable.
+Serialization_ConstructorNotFound = The constructor to deserialize an object of type '{0}' was not found.
+
+; SerializationException used by Formatters
+Serialization_ArrayType = Invalid array type '{0}'.
+Serialization_ArrayTypeObject = Array element type is Object, 'dt' attribute is null.
+Serialization_Assembly = No assembly information is available for object on the wire, '{0}'.
+Serialization_AssemblyId = No assembly ID for object type '{0}'.
+Serialization_BinaryHeader = Binary stream '{0}' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
+Serialization_CrossAppDomainError = Cross-AppDomain BinaryFormatter error; expected '{0}' but received '{1}'.
+Serialization_CorruptedStream = Invalid BinaryFormatter stream.
+Serialization_HeaderReflection = Header reflection error: number of value members: {0}.
+Serialization_ISerializableTypes = Types not available for ISerializable object '{0}'.
+Serialization_ISerializableMemberInfo = MemberInfo requested for ISerializable type.
+Serialization_MBRAsMBV = Type {0} must be marshaled by reference in this context.
+Serialization_Map = No map for object '{0}'.
+Serialization_MemberInfo = MemberInfo cannot be obtained for ISerialized Object '{0}'.
+Serialization_Method = Invalid MethodCall or MethodReturn stream format.
+Serialization_MissingMember = Member '{0}' in class '{1}' is not present in the serialized stream and is not marked with {2}.
+Serialization_NoMemberInfo = No MemberInfo for Object {0}.
+Serialization_ObjNoID = Object {0} has never been assigned an objectID.
+Serialization_ObjectTypeEnum = Invalid ObjectTypeEnum {0}.
+Serialization_ParseError = Parse error. Current element is not compatible with the next element, {0}.
+Serialization_SerMemberInfo = MemberInfo type {0} cannot be serialized.
+Serialization_Stream = Attempting to deserialize an empty stream.
+Serialization_StreamEnd = End of Stream encountered before parsing was completed.
+Serialization_TopObject = No top object.
+Serialization_TopObjectInstantiate = Top object cannot be instantiated for element '{0}'.
+Serialization_TypeCode = Invalid type code in stream '{0}'.
+Serialization_TypeExpected = Invalid expected type.
+Serialization_TypeMissing = Type is missing for member of type Object '{0}'.
+Serialization_TypeRead = Invalid read type request '{0}'.
+Serialization_TypeSecurity = Type {0} and the types derived from it (such as {1}) are not permitted to be deserialized at this security level.
+Serialization_TypeWrite = Invalid write type request '{0}'.
+Serialization_XMLElement = Invalid element '{0}'.
+Serialization_Security = Because of security restrictions, the type {0} cannot be accessed.
+Serialization_TypeLoadFailure = Unable to load type {0} required for deserialization.
+Serialization_RequireFullTrust = A type '{0}' that is defined in a partially trusted assembly cannot be type forwarded from an assembly with a different Public Key Token or without a public key token. To fix this, please either turn on unsafeTypeForwarding flag in the configuration file or remove the TypeForwardedFrom attribute.
+; The following serialization exception messages appear in native resources too (mscorrc.rc)
+Serialization_TypeResolved = Type is not resolved for member '{0}'.
+#endif // FEATURE_SERIALIZATION
+
+;
+; StringBuilder Exceptions
+;
+Arg_LongerThanSrcString = Source string was not long enough. Check sourceIndex and count.
+
+
+;
+; System.Threading
+;
+
+;
+; Thread Exceptions
+;
+ThreadState_NoAbortRequested = Unable to reset abort because no abort was requested.
+Threading.WaitHandleTooManyPosts = The WaitHandle cannot be signaled because it would exceed its maximum count.
+;
+; WaitHandleCannotBeOpenedException
+;
+Threading.WaitHandleCannotBeOpenedException = No handle of the given name exists.
+Threading.WaitHandleCannotBeOpenedException_InvalidHandle = A WaitHandle with system-wide name '{0}' cannot be created. A WaitHandle of a different type might have the same name.
+
+;
+; AbandonedMutexException
+;
+Threading.AbandonedMutexException = The wait completed due to an abandoned mutex.
+
+; AggregateException
+AggregateException_ctor_DefaultMessage=One or more errors occurred.
+AggregateException_ctor_InnerExceptionNull=An element of innerExceptions was null.
+AggregateException_DeserializationFailure=The serialization stream contains no inner exceptions.
+AggregateException_ToString={0}{1}---> (Inner Exception #{2}) {3}{4}{5}
+
+; Cancellation
+CancellationToken_CreateLinkedToken_TokensIsEmpty=No tokens were supplied.
+CancellationTokenSource_Disposed=The CancellationTokenSource has been disposed.
+CancellationToken_SourceDisposed=The CancellationTokenSource associated with this CancellationToken has been disposed.
+
+; Exceptions shared by all concurrent collection
+ConcurrentCollection_SyncRoot_NotSupported=The SyncRoot property may not be used for the synchronization of concurrent collections.
+
+; Exceptions shared by ConcurrentStack and ConcurrentQueue
+ConcurrentStackQueue_OnDeserialization_NoData=The serialization stream contains no elements.
+
+; ConcurrentStack<T>
+ConcurrentStack_PushPopRange_StartOutOfRange=The startIndex argument must be greater than or equal to zero.
+ConcurrentStack_PushPopRange_CountOutOfRange=The count argument must be greater than or equal to zero.
+ConcurrentStack_PushPopRange_InvalidCount=The sum of the startIndex and count arguments must be less than or equal to the collection's Count.
+
+; ConcurrentDictionary<TKey, TValue>
+ConcurrentDictionary_ItemKeyIsNull=TKey is a reference type and item.Key is null.
+ConcurrentDictionary_SourceContainsDuplicateKeys=The source argument contains duplicate keys.
+ConcurrentDictionary_IndexIsNegative=The index argument is less than zero.
+ConcurrentDictionary_ConcurrencyLevelMustBePositive=The concurrencyLevel argument must be positive.
+ConcurrentDictionary_CapacityMustNotBeNegative=The capacity argument must be greater than or equal to zero.
+ConcurrentDictionary_ArrayNotLargeEnough=The index is equal to or greater than the length of the array, or the number of elements in the dictionary is greater than the available space from index to the end of the destination array.
+ConcurrentDictionary_ArrayIncorrectType=The array is multidimensional, or the type parameter for the set cannot be cast automatically to the type of the destination array.
+ConcurrentDictionary_KeyAlreadyExisted=The key already existed in the dictionary.
+ConcurrentDictionary_TypeOfKeyIncorrect=The key was of an incorrect type for this dictionary.
+ConcurrentDictionary_TypeOfValueIncorrect=The value was of an incorrect type for this dictionary.
+
+; Partitioner
+Partitioner_DynamicPartitionsNotSupported=Dynamic partitions are not supported by this partitioner.
+
+; OrderablePartitioner
+OrderablePartitioner_GetPartitions_WrongNumberOfPartitions=GetPartitions returned an incorrect number of partitions.
+
+; PartitionerStatic
+PartitionerStatic_CurrentCalledBeforeMoveNext=MoveNext must be called at least once before calling Current.
+PartitionerStatic_CanNotCallGetEnumeratorAfterSourceHasBeenDisposed=Can not call GetEnumerator on partitions after the source enumerable is disposed
+
+; CDSCollectionETWBCLProvider events
+event_ConcurrentStack_FastPushFailed=Push to ConcurrentStack spun {0} time(s).
+event_ConcurrentStack_FastPopFailed=Pop from ConcurrentStack spun {0} time(s).
+event_ConcurrentDictionary_AcquiringAllLocks=ConcurrentDictionary acquiring all locks on {0} bucket(s).
+event_ConcurrentBag_TryTakeSteals=ConcurrentBag stealing in TryTake.
+event_ConcurrentBag_TryPeekSteals=ConcurrentBag stealing in TryPeek.
+
+; CountdownEvent
+CountdownEvent_Decrement_BelowZero=Invalid attempt made to decrement the event's count below zero.
+CountdownEvent_Increment_AlreadyZero=The event is already signaled and cannot be incremented.
+CountdownEvent_Increment_AlreadyMax=The increment operation would cause the CurrentCount to overflow.
+
+; Parallel
+Parallel_Invoke_ActionNull=One of the actions was null.
+Parallel_ForEach_OrderedPartitionerKeysNotNormalized=This method requires the use of an OrderedPartitioner with the KeysNormalized property set to true.
+Parallel_ForEach_PartitionerNotDynamic=The Partitioner used here must support dynamic partitioning.
+Parallel_ForEach_PartitionerReturnedNull=The Partitioner used here returned a null partitioner source.
+Parallel_ForEach_NullEnumerator=The Partitioner source returned a null enumerator.
+
+; Semaphore
+Argument_SemaphoreInitialMaximum=The initial count for the semaphore must be greater than or equal to zero and less than the maximum count.
+
+; SemaphoreFullException
+Threading_SemaphoreFullException=Adding the specified count to the semaphore would cause it to exceed its maximum count.
+
+; Lazy
+Lazy_ctor_ValueSelectorNull=The valueSelector argument is null.
+Lazy_ctor_InfoNull=The info argument is null.
+Lazy_ctor_deserialization_ValueInvalid=The Value cannot be null.
+Lazy_ctor_ModeInvalid=The mode argument specifies an invalid value.
+Lazy_CreateValue_NoParameterlessCtorForT=The lazily-initialized type does not have a public, parameterless constructor.
+Lazy_StaticInit_InvalidOperation=ValueFactory returned null.
+Lazy_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance.
+Lazy_ToString_ValueNotCreated=Value is not created.
+
+
+;ThreadLocal
+ThreadLocal_Value_RecursiveCallsToValue=ValueFactory attempted to access the Value property of this instance.
+ThreadLocal_Disposed=The ThreadLocal object has been disposed.
+ThreadLocal_ValuesNotAvailable=The ThreadLocal object is not tracking values. To use the Values property, use a ThreadLocal constructor that accepts the trackAllValues parameter and set the parameter to true.
+
+; SemaphoreSlim
+SemaphoreSlim_ctor_InitialCountWrong=The initialCount argument must be non-negative and less than or equal to the maximumCount.
+SemaphoreSlim_ctor_MaxCountWrong=The maximumCount argument must be a positive number. If a maximum is not required, use the constructor without a maxCount parameter.
+SemaphoreSlim_Wait_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive.
+SemaphoreSlim_Release_CountWrong=The releaseCount argument must be greater than zero.
+SemaphoreSlim_Disposed=The semaphore has been disposed.
+
+; ManualResetEventSlim
+ManualResetEventSlim_ctor_SpinCountOutOfRange=The spinCount argument must be in the range 0 to {0}, inclusive.
+ManualResetEventSlim_ctor_TooManyWaiters=There are too many threads currently waiting on the event. A maximum of {0} waiting threads are supported.
+ManualResetEventSlim_Disposed=The event has been disposed.
+
+; SpinLock
+SpinLock_TryEnter_ArgumentOutOfRange=The timeout must be a value between -1 and Int32.MaxValue, inclusive.
+SpinLock_TryEnter_LockRecursionException=The calling thread already holds the lock.
+SpinLock_TryReliableEnter_ArgumentException=The tookLock argument must be set to false before calling this method.
+SpinLock_Exit_SynchronizationLockException=The calling thread does not hold the lock.
+SpinLock_IsHeldByCurrentThread=Thread tracking is disabled.
+
+; SpinWait
+SpinWait_SpinUntil_TimeoutWrong=The timeout must represent a value between -1 and Int32.MaxValue, inclusive.
+SpinWait_SpinUntil_ArgumentNull=The condition argument is null.
+
+; CdsSyncEtwBCLProvider events
+event_SpinLock_FastPathFailed=SpinLock beginning to spin.
+event_SpinWait_NextSpinWillYield=Next spin will yield.
+event_Barrier_PhaseFinished=Barrier finishing phase {1}.
+
+#if PLATFORM_UNIX
+; Unix threading
+PlatformNotSupported_NamedSynchronizationPrimitives=The named version of this synchronization primitive is not supported on this platform.
+PlatformNotSupported_NamedSyncObjectWaitAnyWaitAll=Wait operations on multiple wait handles including a named synchronization primitive are not supported on this platform.
+#endif
+
+;
+; System.Threading.Tasks
+;
+
+; AsyncMethodBuilder
+AsyncMethodBuilder_InstanceNotInitialized=The builder was not properly initialized.
+
+; TaskAwaiter and YieldAwaitable
+AwaitableAwaiter_InstanceNotInitialized=The awaitable or awaiter was not properly initialized.
+TaskAwaiter_TaskNotCompleted=The awaited task has not yet completed.
+
+; Task<T>
+TaskT_SetException_HasAnInitializer=A task's Exception may only be set directly if the task was created without a function.
+TaskT_TransitionToFinal_AlreadyCompleted=An attempt was made to transition a task to a final state when it had already completed.
+TaskT_ctor_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating for a Task<TResult>.
+TaskT_DebuggerNoResult={Not yet computed}
+
+; Task
+Task_ctor_LRandSR=(Internal)An attempt was made to create a LongRunning SelfReplicating task.
+Task_ThrowIfDisposed=The task has been disposed.
+Task_Dispose_NotCompleted=A task may only be disposed if it is in a completion state (RanToCompletion, Faulted or Canceled).
+Task_Start_Promise=Start may not be called on a promise-style task.
+Task_Start_AlreadyStarted=Start may not be called on a task that was already started.
+Task_Start_TaskCompleted=Start may not be called on a task that has completed.
+Task_Start_ContinuationTask=Start may not be called on a continuation task.
+Task_RunSynchronously_AlreadyStarted=RunSynchronously may not be called on a task that was already started.
+Task_RunSynchronously_TaskCompleted=RunSynchronously may not be called on a task that has already completed.
+Task_RunSynchronously_Promise=RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.
+Task_RunSynchronously_Continuation=RunSynchronously may not be called on a continuation task.
+Task_ContinueWith_NotOnAnything=The specified TaskContinuationOptions excluded all continuation kinds.
+Task_ContinueWith_ESandLR=The specified TaskContinuationOptions combined LongRunning and ExecuteSynchronously. Synchronous continuations should not be long running.
+Task_MultiTaskContinuation_NullTask=The tasks argument included a null value.
+Task_MultiTaskContinuation_FireOptions=It is invalid to exclude specific continuation kinds for continuations off of multiple tasks.
+Task_MultiTaskContinuation_EmptyTaskList=The tasks argument contains no tasks.
+Task_FromAsync_TaskManagerShutDown=FromAsync was called with a TaskManager that had already shut down.
+Task_FromAsync_SelfReplicating=It is invalid to specify TaskCreationOptions.SelfReplicating in calls to FromAsync.
+Task_FromAsync_LongRunning=It is invalid to specify TaskCreationOptions.LongRunning in calls to FromAsync.
+Task_FromAsync_PreferFairness=It is invalid to specify TaskCreationOptions.PreferFairness in calls to FromAsync.
+Task_WaitMulti_NullTask=The tasks array included at least one null element.
+Task_Delay_InvalidMillisecondsDelay=The value needs to be either -1 (signifying an infinite timeout), 0 or a positive integer.
+Task_Delay_InvalidDelay=The value needs to translate in milliseconds to -1 (signifying an infinite timeout), 0 or a positive integer less than or equal to Int32.MaxValue.
+
+; TaskCanceledException
+TaskCanceledException_ctor_DefaultMessage=A task was canceled.
+
+;TaskCompletionSource<T>
+TaskCompletionSourceT_TrySetException_NullException=The exceptions collection included at least one null element.
+TaskCompletionSourceT_TrySetException_NoExceptions=The exceptions collection was empty.
+
+;TaskExceptionHolder
+TaskExceptionHolder_UnknownExceptionType=(Internal)Expected an Exception or an IEnumerable<Exception>
+TaskExceptionHolder_UnhandledException=A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
+
+; TaskScheduler
+TaskScheduler_ExecuteTask_TaskAlreadyExecuted=ExecuteTask may not be called for a task which was already executed.
+TaskScheduler_ExecuteTask_WrongTaskScheduler=ExecuteTask may not be called for a task which was previously queued to a different TaskScheduler.
+TaskScheduler_InconsistentStateAfterTryExecuteTaskInline=The TryExecuteTaskInline call to the underlying scheduler succeeded, but the task body was not invoked.
+TaskScheduler_FromCurrentSynchronizationContext_NoCurrent=The current SynchronizationContext may not be used as a TaskScheduler.
+
+; TaskSchedulerException
+TaskSchedulerException_ctor_DefaultMessage=An exception was thrown by a TaskScheduler.
+
+;
+; ParallelState ( used in Parallel.For(), Parallel.ForEach() )
+ParallelState_Break_InvalidOperationException_BreakAfterStop=Break was called after Stop was called.
+ParallelState_Stop_InvalidOperationException_StopAfterBreak=Stop was called after Break was called.
+ParallelState_NotSupportedException_UnsupportedMethod=This method is not supported.
+
+;
+; TPLETWProvider events
+event_ParallelLoopBegin=Beginning {3} loop {2} from Task {1}.
+event_ParallelLoopEnd=Ending loop {2} after {3} iterations.
+event_ParallelInvokeBegin=Beginning ParallelInvoke {2} from Task {1} for {4} actions.
+event_ParallelInvokeEnd=Ending ParallelInvoke {2}.
+event_ParallelFork=Task {1} entering fork/join {2}.
+event_ParallelJoin=Task {1} leaving fork/join {2}.
+event_TaskScheduled=Task {2} scheduled to TaskScheduler {0}.
+event_TaskStarted=Task {2} executing.
+event_TaskCompleted=Task {2} completed.
+event_TaskWaitBegin=Beginning wait ({3}) on Task {2}.
+event_TaskWaitEnd=Ending wait on Task {2}.
+
+
+;
+; Weak Reference Exception
+;
+WeakReference_NoLongerValid = The weak reference is no longer valid.
+
+
+;
+; Interop Exceptions
+;
+Interop.COM_TypeMismatch = Type mismatch between source and destination types.
+Interop_Marshal_Unmappable_Char = Cannot marshal: Encountered unmappable character.
+
+#if FEATURE_COMINTEROP_WINRT_DESKTOP_HOST
+WinRTHostDomainName = Windows Runtime Object Host Domain for '{0}'
+#endif
+
+;
+; Loader Exceptions
+;
+Loader_InvalidPath = Relative path must be a string that contains the substring, "..", or does not contain a root directory.
+Loader_Name = Name:
+Loader_NoContextPolicies = There are no context policies.
+Loader_ContextPolicies = Context Policies:
+
+;
+; AppDomain Exceptions
+AppDomain_RequireApplicationName = ApplicationName must be set before the DynamicBase can be set.
+AppDomain_AppBaseNotSet = The ApplicationBase must be set before retrieving this property.
+
+#if FEATURE_HOST_ASSEMBLY_RESOLVER
+AppDomain_BindingModelIsLocked = Binding model is already locked for the AppDomain and cannot be reset.
+Argument_CustomAssemblyLoadContextRequestedNameMismatch = Resolved assembly's simple name should be the same as of the requested assembly.
+#endif // FEATURE_HOST_ASSEMBLY_RESOLVER
+;
+; XMLSyntaxExceptions
+XMLSyntax_UnexpectedEndOfFile = Unexpected end of file.
+XMLSyntax_ExpectedCloseBracket = Expected > character.
+XMLSyntax_ExpectedSlashOrString = Expected / character or string.
+XMLSyntax_UnexpectedCloseBracket = Unexpected > character.
+XMLSyntax_SyntaxError = Invalid syntax on line {0}.
+XMLSyntax_SyntaxErrorEx = Invalid syntax on line {0} - '{1}'.
+XMLSyntax_InvalidSyntax = Invalid syntax.
+XML_Syntax_InvalidSyntaxInFile = Invalid XML in file '{0}' near element '{1}'.
+XMLSyntax_InvalidSyntaxSatAssemTag = Invalid XML in file "{0}" near element "{1}". The <satelliteassemblies> section only supports <assembly> tags.
+XMLSyntax_InvalidSyntaxSatAssemTagBadAttr = Invalid XML in file "{0}" near "{1}" and "{2}". In the <satelliteassemblies> section, the <assembly> tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name.
+XMLSyntax_InvalidSyntaxSatAssemTagNoAttr = Invalid XML in file "{0}". In the <satelliteassemblies> section, the <assembly> tag must have exactly 1 attribute called 'name', whose value is a fully-qualified assembly name.
+
+; CodeGroup
+#if FEATURE_CAS_POLICY
+NetCodeGroup_PermissionSet = Same site Web
+MergeLogic_Union = Union
+MergeLogic_FirstMatch = First Match
+FileCodeGroup_PermissionSet = Same directory FileIO - '{0}'
+#endif // FEATURE_CAS_POLICY
+
+; MembershipConditions
+StrongName_ToString = StrongName - {0}{1}{2}
+StrongName_Name = name = {0}
+StrongName_Version = version = {0}
+Site_ToString = Site
+Publisher_ToString = Publisher
+Hash_ToString = Hash - {0} = {1}
+ApplicationDirectory_ToString = ApplicationDirectory
+Zone_ToString = Zone - {0}
+All_ToString = All code
+Url_ToString = Url
+GAC_ToString = GAC
+#if FEATURE_CAS_POLICY
+Site_ToStringArg = Site - {0}
+Publisher_ToStringArg = Publisher - {0}
+Url_ToStringArg = Url - {0}
+#endif // FEATURE_CAS_POLICY
+
+
+; Interop non exception strings.
+TypeLibConverter_ImportedTypeLibProductName = Assembly imported from type library '{0}'.
+
+;
+; begin System.TimeZoneInfo ArgumentException's
+;
+Argument_AdjustmentRulesNoNulls = The AdjustmentRule array cannot contain null elements.
+Argument_AdjustmentRulesOutOfOrder = The elements of the AdjustmentRule array must be in chronological order and must not overlap.
+Argument_AdjustmentRulesAmbiguousOverlap = The elements of the AdjustmentRule array must not contain ambiguous time periods that extend beyond the DateStart or DateEnd properties of the element.
+Argument_AdjustmentRulesrDaylightSavingTimeOverlap = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap adjacent elements in such a way as to cause invalid or ambiguous time periods.
+Argument_AdjustmentRulesrDaylightSavingTimeOverlapNonRuleRange = The elements of the AdjustmentRule array must not contain Daylight Saving Time periods that overlap the DateStart or DateEnd properties in such a way as to cause invalid or ambiguous time periods.
+Argument_AdjustmentRulesInvalidOverlap = The elements of the AdjustmentRule array must not contain invalid time periods that extend beyond the DateStart or DateEnd properties of the element.
+Argument_ConvertMismatch = The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local.
+Argument_DateTimeHasTimeOfDay = The supplied DateTime includes a TimeOfDay setting. This is not supported.
+Argument_DateTimeIsInvalid = The supplied DateTime represents an invalid time. For example, when the clock is adjusted forward, any time in the period that is skipped is invalid.
+Argument_DateTimeIsNotAmbiguous = The supplied DateTime is not in an ambiguous time range.
+Argument_DateTimeOffsetIsNotAmbiguous = The supplied DateTimeOffset is not in an ambiguous time range.
+Argument_DateTimeKindMustBeUnspecifiedOrUtc = The supplied DateTime must have the Kind property set to DateTimeKind.Unspecified or DateTimeKind.Utc.
+Argument_DateTimeHasTicks = The supplied DateTime must have the Year, Month, and Day properties set to 1. The time cannot be specified more precisely than whole milliseconds.
+Argument_InvalidId = The specified ID parameter '{0}' is not supported.
+Argument_InvalidSerializedString = The specified serialized string '{0}' is not supported.
+Argument_InvalidREG_TZI_FORMAT = The REG_TZI_FORMAT structure is corrupt.
+Argument_OutOfOrderDateTimes = The DateStart property must come before the DateEnd property.
+Argument_TimeSpanHasSeconds = The TimeSpan parameter cannot be specified more precisely than whole minutes.
+Argument_TimeZoneInfoBadTZif = The tzfile does not begin with the magic characters 'TZif'. Please verify that the file is not corrupt.
+Argument_TimeZoneInfoInvalidTZif = The TZif data structure is corrupt.
+Argument_TransitionTimesAreIdentical = The DaylightTransitionStart property must not equal the DaylightTransitionEnd property.
+;
+; begin System.TimeZoneInfo ArgumentOutOfRangeException's
+;
+ArgumentOutOfRange_DayParam = The Day parameter must be in the range 1 through 31.
+ArgumentOutOfRange_DayOfWeek = The DayOfWeek enumeration must be in the range 0 through 6.
+ArgumentOutOfRange_MonthParam = The Month parameter must be in the range 1 through 12.
+ArgumentOutOfRange_UtcOffset = The TimeSpan parameter must be within plus or minus 14.0 hours.
+ArgumentOutOfRange_UtcOffsetAndDaylightDelta = The sum of the BaseUtcOffset and DaylightDelta properties must within plus or minus 14.0 hours.
+ArgumentOutOfRange_Week = The Week parameter must be in the range 1 through 5.
+;
+; begin System.TimeZoneInfo InvalidTimeZoneException's
+;
+InvalidTimeZone_InvalidRegistryData = The time zone ID '{0}' was found on the local computer, but the registry information was corrupt.
+InvalidTimeZone_InvalidFileData = The time zone ID '{0}' was found on the local computer, but the file at '{1}' was corrupt.
+InvalidTimeZone_InvalidWin32APIData = The Local time zone was found on the local computer, but the data was corrupt.
+InvalidTimeZone_NoTTInfoStructures = There are no ttinfo structures in the tzfile. At least one ttinfo structure is required in order to construct a TimeZoneInfo object.
+InvalidTimeZone_UnparseablePosixMDateString = '{0}' is not a valid POSIX-TZ-environment-variable MDate rule. A valid rule has the format 'Mm.w.d'.
+InvalidTimeZone_JulianDayNotSupported = Julian dates in POSIX strings are unsupported.
+;
+; begin System.TimeZoneInfo SecurityException's
+;
+Security_CannotReadRegistryData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the registry information.
+Security_CannotReadFileData = The time zone ID '{0}' was found on the local computer, but the application does not have permission to read the file.
+;
+; begin System.TimeZoneInfo SerializationException's
+;
+Serialization_CorruptField = The value of the field '{0}' is invalid. The serialized data is corrupt.
+Serialization_InvalidEscapeSequence = The serialized data contained an invalid escape sequence '\\{0}'.
+;
+; begin System.TimeZoneInfo TimeZoneNotFoundException's
+;
+TimeZoneNotFound_MissingData = The time zone ID '{0}' was not found on the local computer.
+;
+; end System.TimeZoneInfo
+;
+
+
+; Tuple
+ArgumentException_TupleIncorrectType=Argument must be of type {0}.
+ArgumentException_TupleNonIComparableElement=The tuple contains an element of type {0} which does not implement the IComparable interface.
+ArgumentException_TupleLastArgumentNotATuple=The last element of an eight element tuple must be a Tuple.
+ArgumentException_OtherNotArrayOfCorrectLength=Object is not a array with the same number of elements as the array to compare it to.
+
+; WinRT collection adapters
+Argument_IndexOutOfArrayBounds=The specified index is out of bounds of the specified array.
+Argument_InsufficientSpaceToCopyCollection=The specified space is not sufficient to copy the elements from this Collection.
+ArgumentOutOfRange_IndexLargerThanMaxValue=This collection cannot work with indices larger than Int32.MaxValue - 1 (0x7FFFFFFF - 1).
+ArgumentOutOfRange_IndexOutOfRange=The specified index is outside the current index range of this collection.
+InvalidOperation_CollectionBackingListTooLarge=The collection backing this List contains too many elements.
+InvalidOperation_CollectionBackingDictionaryTooLarge=The collection backing this Dictionary contains too many elements.
+InvalidOperation_CannotRemoveLastFromEmptyCollection=Cannot remove the last element from an empty collection.
+
+; Globalization resources
+;------------------
+
+#if !FEATURE_CORECLR
+Globalization.LegacyModifier = Legacy
+
+;
+;Total items: 809
+;
+Globalization.ci_ = Invariant Language (Invariant Country)
+Globalization.ci_aa = Afar
+Globalization.ci_aa-DJ = Afar (Djibouti)
+Globalization.ci_aa-ER = Afar (Eritrea)
+Globalization.ci_aa-ET = Afar (Ethiopia)
+Globalization.ci_af = Afrikaans
+Globalization.ci_af-NA = Afrikaans (Namibia)
+Globalization.ci_af-ZA = Afrikaans (South Africa)
+Globalization.ci_agq = Aghem
+Globalization.ci_agq-CM = Aghem (Cameroon)
+Globalization.ci_ak = Akan
+Globalization.ci_ak-GH = Akan (Ghana)
+Globalization.ci_am = Amharic
+Globalization.ci_am-ET = Amharic (Ethiopia)
+Globalization.ci_ar = Arabic
+Globalization.ci_ar-001 = Arabic (World)
+Globalization.ci_ar-AE = Arabic (U.A.E.)
+Globalization.ci_ar-BH = Arabic (Bahrain)
+Globalization.ci_ar-DJ = Arabic (Djibouti)
+Globalization.ci_ar-DZ = Arabic (Algeria)
+Globalization.ci_ar-EG = Arabic (Egypt)
+Globalization.ci_ar-ER = Arabic (Eritrea)
+Globalization.ci_ar-IL = Arabic (Israel)
+Globalization.ci_ar-IQ = Arabic (Iraq)
+Globalization.ci_ar-JO = Arabic (Jordan)
+Globalization.ci_ar-KM = Arabic (Comoros)
+Globalization.ci_ar-KW = Arabic (Kuwait)
+Globalization.ci_ar-LB = Arabic (Lebanon)
+Globalization.ci_ar-LY = Arabic (Libya)
+Globalization.ci_ar-MA = Arabic (Morocco)
+Globalization.ci_ar-MR = Arabic (Mauritania)
+Globalization.ci_ar-OM = Arabic (Oman)
+Globalization.ci_ar-PS = Arabic (Palestinian Authority)
+Globalization.ci_ar-QA = Arabic (Qatar)
+Globalization.ci_ar-SA = Arabic (Saudi Arabia)
+Globalization.ci_ar-SD = Arabic (Sudan)
+Globalization.ci_ar-SO = Arabic (Somalia)
+Globalization.ci_ar-SS = Arabic (South Sudan)
+Globalization.ci_ar-SY = Arabic (Syria)
+Globalization.ci_ar-TD = Arabic (Chad)
+Globalization.ci_ar-TN = Arabic (Tunisia)
+Globalization.ci_ar-YE = Arabic (Yemen)
+Globalization.ci_arn = Mapudungun
+Globalization.ci_arn-CL = Mapudungun (Chile)
+Globalization.ci_as = Assamese
+Globalization.ci_as-IN = Assamese (India)
+Globalization.ci_asa = Asu
+Globalization.ci_asa-TZ = Asu (Tanzania)
+Globalization.ci_ast = Asturian
+Globalization.ci_ast-ES = Asturian (Spain)
+Globalization.ci_az = Azerbaijani
+Globalization.ci_az-Cyrl = Azerbaijani (Cyrillic)
+Globalization.ci_az-Cyrl-AZ = Azerbaijani (Cyrillic, Azerbaijan)
+Globalization.ci_az-Latn = Azerbaijani (Latin)
+Globalization.ci_az-Latn-AZ = Azerbaijani (Latin, Azerbaijan)
+Globalization.ci_ba = Bashkir
+Globalization.ci_ba-RU = Bashkir (Russia)
+Globalization.ci_bas = Basaa
+Globalization.ci_bas-CM = Basaa (Cameroon)
+Globalization.ci_be = Belarusian
+Globalization.ci_be-BY = Belarusian (Belarus)
+Globalization.ci_bem = Bemba
+Globalization.ci_bem-ZM = Bemba (Zambia)
+Globalization.ci_bez = Bena
+Globalization.ci_bez-TZ = Bena (Tanzania)
+Globalization.ci_bg = Bulgarian
+Globalization.ci_bg-BG = Bulgarian (Bulgaria)
+Globalization.ci_bm = Bambara
+Globalization.ci_bm-Latn = Bambara (Latin)
+Globalization.ci_bm-Latn-ML = Bambara (Latin, Mali)
+Globalization.ci_bm-ML = Bamanankan (Latin, Mali)
+Globalization.ci_bn = Bangla
+Globalization.ci_bn-BD = Bangla (Bangladesh)
+Globalization.ci_bn-IN = Bangla (India)
+Globalization.ci_bo = Tibetan
+Globalization.ci_bo-CN = Tibetan (PRC)
+Globalization.ci_bo-IN = Tibetan (India)
+Globalization.ci_br = Breton
+Globalization.ci_br-FR = Breton (France)
+Globalization.ci_brx = Bodo
+Globalization.ci_brx-IN = Bodo (India)
+Globalization.ci_bs = Bosnian
+Globalization.ci_bs-Cyrl = Bosnian (Cyrillic)
+Globalization.ci_bs-Cyrl-BA = Bosnian (Cyrillic, Bosnia and Herzegovina)
+Globalization.ci_bs-Latn = Bosnian (Latin)
+Globalization.ci_bs-Latn-BA = Bosnian (Latin, Bosnia and Herzegovina)
+Globalization.ci_byn = Blin
+Globalization.ci_byn-ER = Blin (Eritrea)
+Globalization.ci_ca = Catalan
+Globalization.ci_ca-AD = Catalan (Andorra)
+Globalization.ci_ca-ES = Catalan (Catalan)
+Globalization.ci_ca-ES-valencia = Valencian (Spain)
+Globalization.ci_ca-FR = Catalan (France)
+Globalization.ci_ca-IT = Catalan (Italy)
+Globalization.ci_cgg = Chiga
+Globalization.ci_cgg-UG = Chiga (Uganda)
+Globalization.ci_chr = Cherokee
+Globalization.ci_chr-Cher = Cherokee (Cherokee)
+Globalization.ci_chr-Cher-US = Cherokee (Cherokee)
+Globalization.ci_co = Corsican
+Globalization.ci_co-FR = Corsican (France)
+Globalization.ci_cs = Czech
+Globalization.ci_cs-CZ = Czech (Czech Republic)
+Globalization.ci_cy = Welsh
+Globalization.ci_cy-GB = Welsh (United Kingdom)
+Globalization.ci_da = Danish
+Globalization.ci_da-DK = Danish (Denmark)
+Globalization.ci_da-GL = Danish (Greenland)
+Globalization.ci_dav = Taita
+Globalization.ci_dav-KE = Taita (Kenya)
+Globalization.ci_de = German
+Globalization.ci_de-AT = German (Austria)
+Globalization.ci_de-BE = German (Belgium)
+Globalization.ci_de-CH = German (Switzerland)
+Globalization.ci_de-DE = German (Germany)
+Globalization.ci_de-DE_phoneb = German (Germany)
+Globalization.ci_de-LI = German (Liechtenstein)
+Globalization.ci_de-LU = German (Luxembourg)
+Globalization.ci_dje = Zarma
+Globalization.ci_dje-NE = Zarma (Niger)
+Globalization.ci_dsb = Lower Sorbian
+Globalization.ci_dsb-DE = Lower Sorbian (Germany)
+Globalization.ci_dua = Duala
+Globalization.ci_dua-CM = Duala (Cameroon)
+Globalization.ci_dv = Divehi
+Globalization.ci_dv-MV = Divehi (Maldives)
+Globalization.ci_dyo = Jola-Fonyi
+Globalization.ci_dyo-SN = Jola-Fonyi (Senegal)
+Globalization.ci_dz = Dzongkha
+Globalization.ci_dz-BT = Dzongkha (Bhutan)
+Globalization.ci_ebu = Embu
+Globalization.ci_ebu-KE = Embu (Kenya)
+Globalization.ci_ee = Ewe
+Globalization.ci_ee-GH = Ewe (Ghana)
+Globalization.ci_ee-TG = Ewe (Togo)
+Globalization.ci_el = Greek
+Globalization.ci_el-CY = Greek (Cyprus)
+Globalization.ci_el-GR = Greek (Greece)
+Globalization.ci_en = English
+Globalization.ci_en-001 = English (World)
+Globalization.ci_en-029 = English (Caribbean)
+Globalization.ci_en-150 = English (Europe)
+Globalization.ci_en-AG = English (Antigua and Barbuda)
+Globalization.ci_en-AI = English (Anguilla)
+Globalization.ci_en-AS = English (American Samoa)
+Globalization.ci_en-AU = English (Australia)
+Globalization.ci_en-BB = English (Barbados)
+Globalization.ci_en-BE = English (Belgium)
+Globalization.ci_en-BM = English (Bermuda)
+Globalization.ci_en-BS = English (Bahamas)
+Globalization.ci_en-BW = English (Botswana)
+Globalization.ci_en-BZ = English (Belize)
+Globalization.ci_en-CA = English (Canada)
+Globalization.ci_en-CC = English (Cocos [Keeling] Islands)
+Globalization.ci_en-CK = English (Cook Islands)
+Globalization.ci_en-CM = English (Cameroon)
+Globalization.ci_en-CX = English (Christmas Island)
+Globalization.ci_en-DM = English (Dominica)
+Globalization.ci_en-ER = English (Eritrea)
+Globalization.ci_en-FJ = English (Fiji)
+Globalization.ci_en-FK = English (Falkland Islands)
+Globalization.ci_en-FM = English (Micronesia)
+Globalization.ci_en-GB = English (United Kingdom)
+Globalization.ci_en-GD = English (Grenada)
+Globalization.ci_en-GG = English (Guernsey)
+Globalization.ci_en-GH = English (Ghana)
+Globalization.ci_en-GI = English (Gibraltar)
+Globalization.ci_en-GM = English (Gambia)
+Globalization.ci_en-GU = English (Guam)
+Globalization.ci_en-GY = English (Guyana)
+Globalization.ci_en-HK = English (Hong Kong SAR)
+Globalization.ci_en-IE = English (Ireland)
+Globalization.ci_en-IM = English (Isle of Man)
+Globalization.ci_en-IN = English (India)
+Globalization.ci_en-IO = English (British Indian Ocean Territory)
+Globalization.ci_en-JE = English (Jersey)
+Globalization.ci_en-JM = English (Jamaica)
+Globalization.ci_en-KE = English (Kenya)
+Globalization.ci_en-KI = English (Kiribati)
+Globalization.ci_en-KN = English (Saint Kitts and Nevis)
+Globalization.ci_en-KY = English (Cayman Islands)
+Globalization.ci_en-LC = English (Saint Lucia)
+Globalization.ci_en-LR = English (Liberia)
+Globalization.ci_en-LS = English (Lesotho)
+Globalization.ci_en-MG = English (Madagascar)
+Globalization.ci_en-MH = English (Marshall Islands)
+Globalization.ci_en-MO = English (Macao SAR)
+Globalization.ci_en-MP = English (Northern Mariana Islands)
+Globalization.ci_en-MS = English (Montserrat)
+Globalization.ci_en-MT = English (Malta)
+Globalization.ci_en-MU = English (Mauritius)
+Globalization.ci_en-MW = English (Malawi)
+Globalization.ci_en-MY = English (Malaysia)
+Globalization.ci_en-NA = English (Namibia)
+Globalization.ci_en-NF = English (Norfolk Island)
+Globalization.ci_en-NG = English (Nigeria)
+Globalization.ci_en-NR = English (Nauru)
+Globalization.ci_en-NU = English (Niue)
+Globalization.ci_en-NZ = English (New Zealand)
+Globalization.ci_en-PG = English (Papua New Guinea)
+Globalization.ci_en-PH = English (Republic of the Philippines)
+Globalization.ci_en-PK = English (Pakistan)
+Globalization.ci_en-PN = English (Pitcairn Islands)
+Globalization.ci_en-PR = English (Puerto Rico)
+Globalization.ci_en-PW = English (Palau)
+Globalization.ci_en-RW = English (Rwanda)
+Globalization.ci_en-SB = English (Solomon Islands)
+Globalization.ci_en-SC = English (Seychelles)
+Globalization.ci_en-SD = English (Sudan)
+Globalization.ci_en-SG = English (Singapore)
+Globalization.ci_en-SH = English (St Helena, Ascension, Tristan da Cunha)
+Globalization.ci_en-SL = English (Sierra Leone)
+Globalization.ci_en-SS = English (South Sudan)
+Globalization.ci_en-SX = English (Sint Maarten)
+Globalization.ci_en-SZ = English (Swaziland)
+Globalization.ci_en-TC = English (Turks and Caicos Islands)
+Globalization.ci_en-TK = English (Tokelau)
+Globalization.ci_en-TO = English (Tonga)
+Globalization.ci_en-TT = English (Trinidad and Tobago)
+Globalization.ci_en-TV = English (Tuvalu)
+Globalization.ci_en-TZ = English (Tanzania)
+Globalization.ci_en-UG = English (Uganda)
+Globalization.ci_en-UM = English (US Minor Outlying Islands)
+Globalization.ci_en-US = English (United States)
+Globalization.ci_en-VC = English (Saint Vincent and the Grenadines)
+Globalization.ci_en-VG = English (British Virgin Islands)
+Globalization.ci_en-VI = English (US Virgin Islands)
+Globalization.ci_en-VU = English (Vanuatu)
+Globalization.ci_en-WS = English (Samoa)
+Globalization.ci_en-ZA = English (South Africa)
+Globalization.ci_en-ZM = English (Zambia)
+Globalization.ci_en-ZW = English (Zimbabwe)
+Globalization.ci_eo = Esperanto
+Globalization.ci_eo-001 = Esperanto (World)
+Globalization.ci_es = Spanish
+Globalization.ci_es-419 = Spanish (Latin America)
+Globalization.ci_es-AR = Spanish (Argentina)
+Globalization.ci_es-BO = Spanish (Bolivia)
+Globalization.ci_es-CL = Spanish (Chile)
+Globalization.ci_es-CO = Spanish (Colombia)
+Globalization.ci_es-CR = Spanish (Costa Rica)
+Globalization.ci_es-CU = Spanish (Cuba)
+Globalization.ci_es-DO = Spanish (Dominican Republic)
+Globalization.ci_es-EC = Spanish (Ecuador)
+Globalization.ci_es-ES = Spanish (Spain)
+Globalization.ci_es-ES_tradnl = Spanish (Spain)
+Globalization.ci_es-GQ = Spanish (Equatorial Guinea)
+Globalization.ci_es-GT = Spanish (Guatemala)
+Globalization.ci_es-HN = Spanish (Honduras)
+Globalization.ci_es-MX = Spanish (Mexico)
+Globalization.ci_es-NI = Spanish (Nicaragua)
+Globalization.ci_es-PA = Spanish (Panama)
+Globalization.ci_es-PE = Spanish (Peru)
+Globalization.ci_es-PH = Spanish (Philippines)
+Globalization.ci_es-PR = Spanish (Puerto Rico)
+Globalization.ci_es-PY = Spanish (Paraguay)
+Globalization.ci_es-SV = Spanish (El Salvador)
+Globalization.ci_es-US = Spanish (United States)
+Globalization.ci_es-UY = Spanish (Uruguay)
+Globalization.ci_es-VE = Spanish (Bolivarian Republic of Venezuela)
+Globalization.ci_et = Estonian
+Globalization.ci_et-EE = Estonian (Estonia)
+Globalization.ci_eu = Basque
+Globalization.ci_eu-ES = Basque (Basque)
+Globalization.ci_ewo = Ewondo
+Globalization.ci_ewo-CM = Ewondo (Cameroon)
+Globalization.ci_fa = Persian
+Globalization.ci_fa-AF = Persian (Afghanistan)
+Globalization.ci_fa-IR = Persian (Iran)
+Globalization.ci_ff = Fulah
+Globalization.ci_ff-CM = Fulah (Cameroon)
+Globalization.ci_ff-GN = Fulah (Guinea)
+Globalization.ci_ff-Latn = Fulah (Latin)
+Globalization.ci_ff-Latn-SN = Fulah (Latin, Senegal)
+Globalization.ci_ff-MR = Fulah (Mauritania)
+Globalization.ci_fi = Finnish
+Globalization.ci_fi-FI = Finnish (Finland)
+Globalization.ci_fil = Filipino
+Globalization.ci_fil-PH = Filipino (Philippines)
+Globalization.ci_fo = Faroese
+Globalization.ci_fo-FO = Faroese (Faroe Islands)
+Globalization.ci_fr = French
+Globalization.ci_fr-BE = French (Belgium)
+Globalization.ci_fr-BF = French (Burkina Faso)
+Globalization.ci_fr-BI = French (Burundi)
+Globalization.ci_fr-BJ = French (Benin)
+Globalization.ci_fr-BL = French (Saint Barthélemy)
+Globalization.ci_fr-CA = French (Canada)
+Globalization.ci_fr-CD = French (Congo DRC)
+Globalization.ci_fr-CF = French (Central African Republic)
+Globalization.ci_fr-CG = French (Congo)
+Globalization.ci_fr-CH = French (Switzerland)
+Globalization.ci_fr-CI = French (Côte d’Ivoire)
+Globalization.ci_fr-CM = French (Cameroon)
+Globalization.ci_fr-DJ = French (Djibouti)
+Globalization.ci_fr-DZ = French (Algeria)
+Globalization.ci_fr-FR = French (France)
+Globalization.ci_fr-GA = French (Gabon)
+Globalization.ci_fr-GF = French (French Guiana)
+Globalization.ci_fr-GN = French (Guinea)
+Globalization.ci_fr-GP = French (Guadeloupe)
+Globalization.ci_fr-GQ = French (Equatorial Guinea)
+Globalization.ci_fr-HT = French (Haiti)
+Globalization.ci_fr-KM = French (Comoros)
+Globalization.ci_fr-LU = French (Luxembourg)
+Globalization.ci_fr-MA = French (Morocco)
+Globalization.ci_fr-MC = French (Monaco)
+Globalization.ci_fr-MF = French (Saint Martin)
+Globalization.ci_fr-MG = French (Madagascar)
+Globalization.ci_fr-ML = French (Mali)
+Globalization.ci_fr-MQ = French (Martinique)
+Globalization.ci_fr-MR = French (Mauritania)
+Globalization.ci_fr-MU = French (Mauritius)
+Globalization.ci_fr-NC = French (New Caledonia)
+Globalization.ci_fr-NE = French (Niger)
+Globalization.ci_fr-PF = French (French Polynesia)
+Globalization.ci_fr-PM = French (Saint Pierre and Miquelon)
+Globalization.ci_fr-RE = French (Reunion)
+Globalization.ci_fr-RW = French (Rwanda)
+Globalization.ci_fr-SC = French (Seychelles)
+Globalization.ci_fr-SN = French (Senegal)
+Globalization.ci_fr-SY = French (Syria)
+Globalization.ci_fr-TD = French (Chad)
+Globalization.ci_fr-TG = French (Togo)
+Globalization.ci_fr-TN = French (Tunisia)
+Globalization.ci_fr-VU = French (Vanuatu)
+Globalization.ci_fr-WF = French (Wallis and Futuna)
+Globalization.ci_fr-YT = French (Mayotte)
+Globalization.ci_fur = Friulian
+Globalization.ci_fur-IT = Friulian (Italy)
+Globalization.ci_fy = Frisian
+Globalization.ci_fy-NL = Frisian (Netherlands)
+Globalization.ci_ga = Irish
+Globalization.ci_ga-IE = Irish (Ireland)
+Globalization.ci_gd = Scottish Gaelic
+Globalization.ci_gd-GB = Scottish Gaelic (United Kingdom)
+Globalization.ci_gl = Galician
+Globalization.ci_gl-ES = Galician (Galician)
+Globalization.ci_gn = Guarani
+Globalization.ci_gn-PY = Guarani (Paraguay)
+Globalization.ci_gsw = Alsatian
+Globalization.ci_gsw-CH = Alsatian (Switzerland)
+Globalization.ci_gsw-FR = Alsatian (France)
+Globalization.ci_gsw-LI = Alsatian (Liechtenstein)
+Globalization.ci_gu = Gujarati
+Globalization.ci_gu-IN = Gujarati (India)
+Globalization.ci_guz = Gusii
+Globalization.ci_guz-KE = Gusii (Kenya)
+Globalization.ci_gv = Manx
+Globalization.ci_gv-IM = Manx (Isle of Man)
+Globalization.ci_ha = Hausa
+Globalization.ci_ha-Latn = Hausa (Latin)
+Globalization.ci_ha-Latn-GH = Hausa (Latin, Ghana)
+Globalization.ci_ha-Latn-NE = Hausa (Latin, Niger)
+Globalization.ci_ha-Latn-NG = Hausa (Latin, Nigeria)
+Globalization.ci_haw = Hawaiian
+Globalization.ci_haw-US = Hawaiian (United States)
+Globalization.ci_he = Hebrew
+Globalization.ci_he-IL = Hebrew (Israel)
+Globalization.ci_hi = Hindi
+Globalization.ci_hi-IN = Hindi (India)
+Globalization.ci_hr = Croatian
+Globalization.ci_hr-BA = Croatian (Latin, Bosnia and Herzegovina)
+Globalization.ci_hr-HR = Croatian (Croatia)
+Globalization.ci_hsb = Upper Sorbian
+Globalization.ci_hsb-DE = Upper Sorbian (Germany)
+Globalization.ci_hu = Hungarian
+Globalization.ci_hu-HU = Hungarian (Hungary)
+Globalization.ci_hu-HU_technl = Hungarian (Hungary)
+Globalization.ci_hy = Armenian
+Globalization.ci_hy-AM = Armenian (Armenia)
+Globalization.ci_ia = Interlingua
+Globalization.ci_ia-001 = Interlingua (World)
+Globalization.ci_ia-FR = Interlingua (France)
+Globalization.ci_id = Indonesian
+Globalization.ci_id-ID = Indonesian (Indonesia)
+Globalization.ci_ig = Igbo
+Globalization.ci_ig-NG = Igbo (Nigeria)
+Globalization.ci_ii = Yi
+Globalization.ci_ii-CN = Yi (PRC)
+Globalization.ci_is = Icelandic
+Globalization.ci_is-IS = Icelandic (Iceland)
+Globalization.ci_it = Italian
+Globalization.ci_it-CH = Italian (Switzerland)
+Globalization.ci_it-IT = Italian (Italy)
+Globalization.ci_it-SM = Italian (San Marino)
+Globalization.ci_iu = Inuktitut
+Globalization.ci_iu-Cans = Inuktitut (Syllabics)
+Globalization.ci_iu-Cans-CA = Inuktitut (Syllabics, Canada)
+Globalization.ci_iu-Latn = Inuktitut (Latin)
+Globalization.ci_iu-Latn-CA = Inuktitut (Latin, Canada)
+Globalization.ci_ja = Japanese
+Globalization.ci_ja-JP = Japanese (Japan)
+Globalization.ci_ja-JP_radstr = Japanese (Japan)
+Globalization.ci_jgo = Ngomba
+Globalization.ci_jgo-CM = Ngomba (Cameroon)
+Globalization.ci_jmc = Machame
+Globalization.ci_jmc-TZ = Machame (Tanzania)
+Globalization.ci_jv = Javanese
+Globalization.ci_jv-Latn = Javanese
+Globalization.ci_jv-Latn-ID = Javanese (Indonesia)
+Globalization.ci_ka = Georgian
+Globalization.ci_ka-GE = Georgian (Georgia)
+Globalization.ci_ka-GE_modern = Georgian (Georgia)
+Globalization.ci_kab = Kabyle
+Globalization.ci_kab-DZ = Kabyle (Algeria)
+Globalization.ci_kam = Kamba
+Globalization.ci_kam-KE = Kamba (Kenya)
+Globalization.ci_kde = Makonde
+Globalization.ci_kde-TZ = Makonde (Tanzania)
+Globalization.ci_kea = Kabuverdianu
+Globalization.ci_kea-CV = Kabuverdianu (Cabo Verde)
+Globalization.ci_khq = Koyra Chiini
+Globalization.ci_khq-ML = Koyra Chiini (Mali)
+Globalization.ci_ki = Kikuyu
+Globalization.ci_ki-KE = Kikuyu (Kenya)
+Globalization.ci_kk = Kazakh
+Globalization.ci_kk-KZ = Kazakh (Kazakhstan)
+Globalization.ci_kkj = Kako
+Globalization.ci_kkj-CM = Kako (Cameroon)
+Globalization.ci_kl = Greenlandic
+Globalization.ci_kl-GL = Greenlandic (Greenland)
+Globalization.ci_kln = Kalenjin
+Globalization.ci_kln-KE = Kalenjin (Kenya)
+Globalization.ci_km = Khmer
+Globalization.ci_km-KH = Khmer (Cambodia)
+Globalization.ci_kn = Kannada
+Globalization.ci_kn-IN = Kannada (India)
+Globalization.ci_ko = Korean
+Globalization.ci_ko-KR = Korean (Korea)
+Globalization.ci_kok = Konkani
+Globalization.ci_kok-IN = Konkani (India)
+Globalization.ci_ks = Kashmiri
+Globalization.ci_ks-Arab = Kashmiri (Perso-Arabic)
+Globalization.ci_ks-Arab-IN = Kashmiri (Perso-Arabic)
+Globalization.ci_ksb = Shambala
+Globalization.ci_ksb-TZ = Shambala (Tanzania)
+Globalization.ci_ksf = Bafia
+Globalization.ci_ksf-CM = Bafia (Cameroon)
+Globalization.ci_ksh = Colognian
+Globalization.ci_ksh-DE = Ripuarian (Germany)
+Globalization.ci_ku = Central Kurdish
+Globalization.ci_ku-Arab = Central Kurdish (Arabic)
+Globalization.ci_ku-Arab-IQ = Central Kurdish (Iraq)
+Globalization.ci_kw = Cornish
+Globalization.ci_kw-GB = Cornish (United Kingdom)
+Globalization.ci_ky = Kyrgyz
+Globalization.ci_ky-KG = Kyrgyz (Kyrgyzstan)
+Globalization.ci_lag = Langi
+Globalization.ci_lag-TZ = Langi (Tanzania)
+Globalization.ci_lb = Luxembourgish
+Globalization.ci_lb-LU = Luxembourgish (Luxembourg)
+Globalization.ci_lg = Ganda
+Globalization.ci_lg-UG = Ganda (Uganda)
+Globalization.ci_lkt = Lakota
+Globalization.ci_lkt-US = Lakota (United States)
+Globalization.ci_ln = Lingala
+Globalization.ci_ln-AO = Lingala (Angola)
+Globalization.ci_ln-CD = Lingala (Congo DRC)
+Globalization.ci_ln-CF = Lingala (Central African Republic)
+Globalization.ci_ln-CG = Lingala (Congo)
+Globalization.ci_lo = Lao
+Globalization.ci_lo-LA = Lao (Lao P.D.R.)
+Globalization.ci_lt = Lithuanian
+Globalization.ci_lt-LT = Lithuanian (Lithuania)
+Globalization.ci_lu = Luba-Katanga
+Globalization.ci_lu-CD = Luba-Katanga (Congo DRC)
+Globalization.ci_luo = Luo
+Globalization.ci_luo-KE = Luo (Kenya)
+Globalization.ci_luy = Luyia
+Globalization.ci_luy-KE = Luyia (Kenya)
+Globalization.ci_lv = Latvian
+Globalization.ci_lv-LV = Latvian (Latvia)
+Globalization.ci_mas = Masai
+Globalization.ci_mas-KE = Masai (Kenya)
+Globalization.ci_mas-TZ = Masai (Tanzania)
+Globalization.ci_mer = Meru
+Globalization.ci_mer-KE = Meru (Kenya)
+Globalization.ci_mfe = Morisyen
+Globalization.ci_mfe-MU = Morisyen (Mauritius)
+Globalization.ci_mg = Malagasy
+Globalization.ci_mg-MG = Malagasy (Madagascar)
+Globalization.ci_mgh = Makhuwa-Meetto
+Globalization.ci_mgh-MZ = Makhuwa-Meetto (Mozambique)
+Globalization.ci_mgo = Meta'
+Globalization.ci_mgo-CM = Meta' (Cameroon)
+Globalization.ci_mi = Maori
+Globalization.ci_mi-NZ = Maori (New Zealand)
+Globalization.ci_mk = Macedonian (FYROM)
+Globalization.ci_mk-MK = Macedonian (Former Yugoslav Republic of Macedonia)
+Globalization.ci_ml = Malayalam
+Globalization.ci_ml-IN = Malayalam (India)
+Globalization.ci_mn = Mongolian
+Globalization.ci_mn-Cyrl = Mongolian (Cyrillic)
+Globalization.ci_mn-MN = Mongolian (Cyrillic, Mongolia)
+Globalization.ci_mn-Mong = Mongolian (Traditional Mongolian)
+Globalization.ci_mn-Mong-CN = Mongolian (Traditional Mongolian, PRC)
+Globalization.ci_mn-Mong-MN = Mongolian (Traditional Mongolian, Mongolia)
+Globalization.ci_moh = Mohawk
+Globalization.ci_moh-CA = Mohawk (Mohawk)
+Globalization.ci_mr = Marathi
+Globalization.ci_mr-IN = Marathi (India)
+Globalization.ci_ms = Malay
+Globalization.ci_ms-BN = Malay (Brunei Darussalam)
+Globalization.ci_ms-MY = Malay (Malaysia)
+Globalization.ci_ms-SG = Malay (Latin, Singapore)
+Globalization.ci_mt = Maltese
+Globalization.ci_mt-MT = Maltese (Malta)
+Globalization.ci_mua = Mundang
+Globalization.ci_mua-CM = Mundang (Cameroon)
+Globalization.ci_my = Burmese
+Globalization.ci_my-MM = Burmese (Myanmar)
+Globalization.ci_naq = Nama
+Globalization.ci_naq-NA = Nama (Namibia)
+Globalization.ci_nb = Norwegian (Bokmål)
+Globalization.ci_nb-NO = Norwegian, Bokmål (Norway)
+Globalization.ci_nb-SJ = Norwegian, Bokmål (Svalbard and Jan Mayen)
+Globalization.ci_nd = North Ndebele
+Globalization.ci_nd-ZW = North Ndebele (Zimbabwe)
+Globalization.ci_ne = Nepali
+Globalization.ci_ne-IN = Nepali (India)
+Globalization.ci_ne-NP = Nepali (Nepal)
+Globalization.ci_nl = Dutch
+Globalization.ci_nl-AW = Dutch (Aruba)
+Globalization.ci_nl-BE = Dutch (Belgium)
+Globalization.ci_nl-BQ = Dutch (Bonaire, Sint Eustatius and Saba)
+Globalization.ci_nl-CW = Dutch (Curaçao)
+Globalization.ci_nl-NL = Dutch (Netherlands)
+Globalization.ci_nl-SR = Dutch (Suriname)
+Globalization.ci_nl-SX = Dutch (Sint Maarten)
+Globalization.ci_nmg = Kwasio
+Globalization.ci_nmg-CM = Kwasio (Cameroon)
+Globalization.ci_nn = Norwegian (Nynorsk)
+Globalization.ci_nn-NO = Norwegian, Nynorsk (Norway)
+Globalization.ci_nnh = Ngiemboon
+Globalization.ci_nnh-CM = Ngiemboon (Cameroon)
+Globalization.ci_no = Norwegian
+Globalization.ci_nqo = N'ko
+Globalization.ci_nqo-GN = N'ko (Guinea)
+Globalization.ci_nr = South Ndebele
+Globalization.ci_nr-ZA = South Ndebele (South Africa)
+Globalization.ci_nso = Sesotho sa Leboa
+Globalization.ci_nso-ZA = Sesotho sa Leboa (South Africa)
+Globalization.ci_nus = Nuer
+Globalization.ci_nus-SD = Nuer (Sudan)
+Globalization.ci_nyn = Nyankole
+Globalization.ci_nyn-UG = Nyankole (Uganda)
+Globalization.ci_oc = Occitan
+Globalization.ci_oc-FR = Occitan (France)
+Globalization.ci_om = Oromo
+Globalization.ci_om-ET = Oromo (Ethiopia)
+Globalization.ci_om-KE = Oromo (Kenya)
+Globalization.ci_or = Odia
+Globalization.ci_or-IN = Odia (India)
+Globalization.ci_os = Ossetic
+Globalization.ci_os-GE = Ossetian (Cyrillic, Georgia)
+Globalization.ci_os-RU = Ossetian (Cyrillic, Russia)
+Globalization.ci_pa = Punjabi
+Globalization.ci_pa-Arab = Punjabi (Arabic)
+Globalization.ci_pa-Arab-PK = Punjabi (Islamic Republic of Pakistan)
+Globalization.ci_pa-IN = Punjabi (India)
+Globalization.ci_pl = Polish
+Globalization.ci_pl-PL = Polish (Poland)
+Globalization.ci_prs = Dari
+Globalization.ci_prs-AF = Dari (Afghanistan)
+Globalization.ci_ps = Pashto
+Globalization.ci_ps-AF = Pashto (Afghanistan)
+Globalization.ci_pt = Portuguese
+Globalization.ci_pt-AO = Portuguese (Angola)
+Globalization.ci_pt-BR = Portuguese (Brazil)
+Globalization.ci_pt-CV = Portuguese (Cabo Verde)
+Globalization.ci_pt-GW = Portuguese (Guinea-Bissau)
+Globalization.ci_pt-MO = Portuguese (Macao SAR)
+Globalization.ci_pt-MZ = Portuguese (Mozambique)
+Globalization.ci_pt-PT = Portuguese (Portugal)
+Globalization.ci_pt-ST = Portuguese (São Tomé and Príncipe)
+Globalization.ci_pt-TL = Portuguese (Timor-Leste)
+Globalization.ci_qps-ploc = Pseudo Language (Pseudo)
+Globalization.ci_qps-ploca = Pseudo Language (Pseudo Asia)
+Globalization.ci_qps-plocm = Pseudo Language (Pseudo Mirrored)
+Globalization.ci_qu = Quechua
+Globalization.ci_qu-BO = Quechua (Bolivia)
+Globalization.ci_qu-EC = Quechua (Ecuador)
+Globalization.ci_qu-PE = Quechua (Peru)
+Globalization.ci_quc = K'iche'
+Globalization.ci_quc-Latn = K'iche'
+Globalization.ci_quc-Latn-GT = K'iche' (Guatemala)
+Globalization.ci_qut = K'iche
+Globalization.ci_qut-GT = K'iche (Guatemala)
+Globalization.ci_quz = Quechua
+Globalization.ci_quz-BO = Quechua (Bolivia)
+Globalization.ci_quz-EC = Quechua (Ecuador)
+Globalization.ci_quz-PE = Quechua (Peru)
+Globalization.ci_rm = Romansh
+Globalization.ci_rm-CH = Romansh (Switzerland)
+Globalization.ci_rn = Rundi
+Globalization.ci_rn-BI = Rundi (Burundi)
+Globalization.ci_ro = Romanian
+Globalization.ci_ro-MD = Romanian (Moldova)
+Globalization.ci_ro-RO = Romanian (Romania)
+Globalization.ci_rof = Rombo
+Globalization.ci_rof-TZ = Rombo (Tanzania)
+Globalization.ci_ru = Russian
+Globalization.ci_ru-BY = Russian (Belarus)
+Globalization.ci_ru-KG = Russian (Kyrgyzstan)
+Globalization.ci_ru-KZ = Russian (Kazakhstan)
+Globalization.ci_ru-MD = Russian (Moldova)
+Globalization.ci_ru-RU = Russian (Russia)
+Globalization.ci_ru-UA = Russian (Ukraine)
+Globalization.ci_rw = Kinyarwanda
+Globalization.ci_rw-RW = Kinyarwanda (Rwanda)
+Globalization.ci_rwk = Rwa
+Globalization.ci_rwk-TZ = Rwa (Tanzania)
+Globalization.ci_sa = Sanskrit
+Globalization.ci_sa-IN = Sanskrit (India)
+Globalization.ci_sah = Sakha
+Globalization.ci_sah-RU = Sakha (Russia)
+Globalization.ci_saq = Samburu
+Globalization.ci_saq-KE = Samburu (Kenya)
+Globalization.ci_sbp = Sangu
+Globalization.ci_sbp-TZ = Sangu (Tanzania)
+Globalization.ci_sd = Sindhi
+Globalization.ci_sd-Arab = Sindhi (Arabic)
+Globalization.ci_sd-Arab-PK = Sindhi (Islamic Republic of Pakistan)
+Globalization.ci_se = Sami (Northern)
+Globalization.ci_se-FI = Sami, Northern (Finland)
+Globalization.ci_se-NO = Sami, Northern (Norway)
+Globalization.ci_se-SE = Sami, Northern (Sweden)
+Globalization.ci_seh = Sena
+Globalization.ci_seh-MZ = Sena (Mozambique)
+Globalization.ci_ses = Koyraboro Senni
+Globalization.ci_ses-ML = Koyraboro Senni (Mali)
+Globalization.ci_sg = Sango
+Globalization.ci_sg-CF = Sango (Central African Republic)
+Globalization.ci_shi = Tachelhit
+Globalization.ci_shi-Latn = Tachelhit (Latin)
+Globalization.ci_shi-Latn-MA = Tachelhit (Latin, Morocco)
+Globalization.ci_shi-Tfng = Tachelhit (Tifinagh)
+Globalization.ci_shi-Tfng-MA = Tachelhit (Tifinagh, Morocco)
+Globalization.ci_si = Sinhala
+Globalization.ci_si-LK = Sinhala (Sri Lanka)
+Globalization.ci_sk = Slovak
+Globalization.ci_sk-SK = Slovak (Slovakia)
+Globalization.ci_sl = Slovenian
+Globalization.ci_sl-SI = Slovenian (Slovenia)
+Globalization.ci_sma = Sami (Southern)
+Globalization.ci_sma-NO = Sami, Southern (Norway)
+Globalization.ci_sma-SE = Sami, Southern (Sweden)
+Globalization.ci_smj = Sami (Lule)
+Globalization.ci_smj-NO = Sami, Lule (Norway)
+Globalization.ci_smj-SE = Sami, Lule (Sweden)
+Globalization.ci_smn = Sami (Inari)
+Globalization.ci_smn-FI = Sami, Inari (Finland)
+Globalization.ci_sms = Sami (Skolt)
+Globalization.ci_sms-FI = Sami, Skolt (Finland)
+Globalization.ci_sn = Shona
+Globalization.ci_sn-Latn = Shona (Latin)
+Globalization.ci_sn-Latn-ZW = Shona (Latin, Zimbabwe)
+Globalization.ci_so = Somali
+Globalization.ci_so-DJ = Somali (Djibouti)
+Globalization.ci_so-ET = Somali (Ethiopia)
+Globalization.ci_so-KE = Somali (Kenya)
+Globalization.ci_so-SO = Somali (Somalia)
+Globalization.ci_sq = Albanian
+Globalization.ci_sq-AL = Albanian (Albania)
+Globalization.ci_sq-MK = Albanian (Macedonia, FYRO)
+Globalization.ci_sr = Serbian
+Globalization.ci_sr-Cyrl = Serbian (Cyrillic)
+Globalization.ci_sr-Cyrl-BA = Serbian (Cyrillic, Bosnia and Herzegovina)
+Globalization.ci_sr-Cyrl-CS = Serbian (Cyrillic, Serbia and Montenegro (Former))
+Globalization.ci_sr-Cyrl-ME = Serbian (Cyrillic, Montenegro)
+Globalization.ci_sr-Cyrl-RS = Serbian (Cyrillic, Serbia)
+Globalization.ci_sr-Latn = Serbian (Latin)
+Globalization.ci_sr-Latn-BA = Serbian (Latin, Bosnia and Herzegovina)
+Globalization.ci_sr-Latn-CS = Serbian (Latin, Serbia and Montenegro (Former))
+Globalization.ci_sr-Latn-ME = Serbian (Latin, Montenegro)
+Globalization.ci_sr-Latn-RS = Serbian (Latin, Serbia)
+Globalization.ci_ss = Swati
+Globalization.ci_ss-SZ = Swati (Swaziland)
+Globalization.ci_ss-ZA = Swati (South Africa)
+Globalization.ci_ssy = Saho
+Globalization.ci_ssy-ER = Saho (Eritrea)
+Globalization.ci_st = Southern Sotho
+Globalization.ci_st-LS = Sesotho (Lesotho)
+Globalization.ci_st-ZA = Southern Sotho (South Africa)
+Globalization.ci_sv = Swedish
+Globalization.ci_sv-AX = Swedish (Ã…land Islands)
+Globalization.ci_sv-FI = Swedish (Finland)
+Globalization.ci_sv-SE = Swedish (Sweden)
+Globalization.ci_sw = Kiswahili
+Globalization.ci_sw-KE = Kiswahili (Kenya)
+Globalization.ci_sw-TZ = Kiswahili (Tanzania)
+Globalization.ci_sw-UG = Kiswahili (Uganda)
+Globalization.ci_swc = Congo Swahili
+Globalization.ci_swc-CD = Congo Swahili (Congo DRC)
+Globalization.ci_syr = Syriac
+Globalization.ci_syr-SY = Syriac (Syria)
+Globalization.ci_ta = Tamil
+Globalization.ci_ta-IN = Tamil (India)
+Globalization.ci_ta-LK = Tamil (Sri Lanka)
+Globalization.ci_ta-MY = Tamil (Malaysia)
+Globalization.ci_ta-SG = Tamil (Singapore)
+Globalization.ci_te = Telugu
+Globalization.ci_te-IN = Telugu (India)
+Globalization.ci_teo = Teso
+Globalization.ci_teo-KE = Teso (Kenya)
+Globalization.ci_teo-UG = Teso (Uganda)
+Globalization.ci_tg = Tajik
+Globalization.ci_tg-Cyrl = Tajik (Cyrillic)
+Globalization.ci_tg-Cyrl-TJ = Tajik (Cyrillic, Tajikistan)
+Globalization.ci_th = Thai
+Globalization.ci_th-TH = Thai (Thailand)
+Globalization.ci_ti = Tigrinya
+Globalization.ci_ti-ER = Tigrinya (Eritrea)
+Globalization.ci_ti-ET = Tigrinya (Ethiopia)
+Globalization.ci_tig = Tigre
+Globalization.ci_tig-ER = Tigre (Eritrea)
+Globalization.ci_tk = Turkmen
+Globalization.ci_tk-TM = Turkmen (Turkmenistan)
+Globalization.ci_tn = Setswana
+Globalization.ci_tn-BW = Setswana (Botswana)
+Globalization.ci_tn-ZA = Setswana (South Africa)
+Globalization.ci_to = Tongan
+Globalization.ci_to-TO = Tongan (Tonga)
+Globalization.ci_tr = Turkish
+Globalization.ci_tr-CY = Turkish (Cyprus)
+Globalization.ci_tr-TR = Turkish (Turkey)
+Globalization.ci_ts = Tsonga
+Globalization.ci_ts-ZA = Tsonga (South Africa)
+Globalization.ci_tt = Tatar
+Globalization.ci_tt-RU = Tatar (Russia)
+Globalization.ci_twq = Tasawaq
+Globalization.ci_twq-NE = Tasawaq (Niger)
+Globalization.ci_tzm = Tamazight
+Globalization.ci_tzm-Latn = Tamazight (Latin)
+Globalization.ci_tzm-Latn-DZ = Tamazight (Latin, Algeria)
+Globalization.ci_tzm-Latn-MA = Central Atlas Tamazight (Latin, Morocco)
+Globalization.ci_tzm-Tfng = Tamazight (Tifinagh)
+Globalization.ci_tzm-Tfng-MA = Central Atlas Tamazight (Tifinagh, Morocco)
+Globalization.ci_ug = Uyghur
+Globalization.ci_ug-CN = Uyghur (PRC)
+Globalization.ci_uk = Ukrainian
+Globalization.ci_uk-UA = Ukrainian (Ukraine)
+Globalization.ci_ur = Urdu
+Globalization.ci_ur-IN = Urdu (India)
+Globalization.ci_ur-PK = Urdu (Islamic Republic of Pakistan)
+Globalization.ci_uz = Uzbek
+Globalization.ci_uz-Arab = Uzbek (Perso-Arabic)
+Globalization.ci_uz-Arab-AF = Uzbek (Perso-Arabic, Afghanistan)
+Globalization.ci_uz-Cyrl = Uzbek (Cyrillic)
+Globalization.ci_uz-Cyrl-UZ = Uzbek (Cyrillic, Uzbekistan)
+Globalization.ci_uz-Latn = Uzbek (Latin)
+Globalization.ci_uz-Latn-UZ = Uzbek (Latin, Uzbekistan)
+Globalization.ci_vai = Vai
+Globalization.ci_vai-Latn = Vai (Latin)
+Globalization.ci_vai-Latn-LR = Vai (Latin, Liberia)
+Globalization.ci_vai-Vaii = Vai (Vai)
+Globalization.ci_vai-Vaii-LR = Vai (Vai, Liberia)
+Globalization.ci_ve = Venda
+Globalization.ci_ve-ZA = Venda (South Africa)
+Globalization.ci_vi = Vietnamese
+Globalization.ci_vi-VN = Vietnamese (Vietnam)
+Globalization.ci_vo = Volapük
+Globalization.ci_vo-001 = Volapük (World)
+Globalization.ci_vun = Vunjo
+Globalization.ci_vun-TZ = Vunjo (Tanzania)
+Globalization.ci_wae = Walser
+Globalization.ci_wae-CH = Walser (Switzerland)
+Globalization.ci_wal = Wolaytta
+Globalization.ci_wal-ET = Wolaytta (Ethiopia)
+Globalization.ci_wo = Wolof
+Globalization.ci_wo-SN = Wolof (Senegal)
+Globalization.ci_x-IV = Invariant Language (Invariant Country)
+Globalization.ci_x-IV_mathan = Invariant Language (Invariant Country)
+Globalization.ci_xh = isiXhosa
+Globalization.ci_xh-ZA = isiXhosa (South Africa)
+Globalization.ci_xog = Soga
+Globalization.ci_xog-UG = Soga (Uganda)
+Globalization.ci_yav = Yangben
+Globalization.ci_yav-CM = Yangben (Cameroon)
+Globalization.ci_yi = Yiddish
+Globalization.ci_yi-001 = Yiddish (World)
+Globalization.ci_yo = Yoruba
+Globalization.ci_yo-BJ = Yoruba (Benin)
+Globalization.ci_yo-NG = Yoruba (Nigeria)
+Globalization.ci_zgh = Standard Moroccan Tamazight
+Globalization.ci_zgh-Tfng = Standard Moroccan Tamazight (Tifinagh)
+Globalization.ci_zgh-Tfng-MA = Standard Moroccan Tamazight (Tifinagh, Morocco)
+Globalization.ci_zh = Chinese
+Globalization.ci_zh-CHS = Chinese (Simplified) Legacy
+Globalization.ci_zh-CHT = Chinese (Traditional) Legacy
+Globalization.ci_zh-CN = Chinese (Simplified, PRC)
+Globalization.ci_zh-CN_stroke = Chinese (Simplified, PRC)
+Globalization.ci_zh-Hans = Chinese (Simplified)
+Globalization.ci_zh-Hant = Chinese (Traditional)
+Globalization.ci_zh-HK = Chinese (Traditional, Hong Kong S.A.R.)
+Globalization.ci_zh-HK_radstr = Chinese (Traditional, Hong Kong S.A.R.)
+Globalization.ci_zh-MO = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-MO_radstr = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-MO_stroke = Chinese (Traditional, Macao S.A.R.)
+Globalization.ci_zh-SG = Chinese (Simplified, Singapore)
+Globalization.ci_zh-SG_stroke = Chinese (Simplified, Singapore)
+Globalization.ci_zh-TW = Chinese (Traditional, Taiwan)
+Globalization.ci_zh-TW_pronun = Chinese (Traditional, Taiwan)
+Globalization.ci_zh-TW_radstr = Chinese (Traditional, Taiwan)
+Globalization.ci_zu = isiZulu
+Globalization.ci_zu-ZA = isiZulu (South Africa)
+;------------------
+;
+;Total items: 129
+;
+Globalization.ri_029 = Caribbean
+Globalization.ri_AE = U.A.E.
+Globalization.ri_AF = Afghanistan
+Globalization.ri_AL = Albania
+Globalization.ri_AM = Armenia
+Globalization.ri_AR = Argentina
+Globalization.ri_AT = Austria
+Globalization.ri_AU = Australia
+Globalization.ri_AZ = Azerbaijan
+Globalization.ri_BA = Bosnia and Herzegovina
+Globalization.ri_BD = Bangladesh
+Globalization.ri_BE = Belgium
+Globalization.ri_BG = Bulgaria
+Globalization.ri_BH = Bahrain
+Globalization.ri_BN = Brunei Darussalam
+Globalization.ri_BO = Bolivia
+Globalization.ri_BR = Brazil
+Globalization.ri_BY = Belarus
+Globalization.ri_BZ = Belize
+Globalization.ri_CA = Canada
+Globalization.ri_CH = Switzerland
+Globalization.ri_CL = Chile
+Globalization.ri_CN = People's Republic of China
+Globalization.ri_CO = Colombia
+Globalization.ri_CR = Costa Rica
+Globalization.ri_CS = Serbia and Montenegro (Former)
+Globalization.ri_CZ = Czech Republic
+Globalization.ri_DE = Germany
+Globalization.ri_DK = Denmark
+Globalization.ri_DO = Dominican Republic
+Globalization.ri_DZ = Algeria
+Globalization.ri_EC = Ecuador
+Globalization.ri_EE = Estonia
+Globalization.ri_EG = Egypt
+Globalization.ri_ER = Eritrea
+Globalization.ri_ES = Spain
+Globalization.ri_ET = Ethiopia
+Globalization.ri_FI = Finland
+Globalization.ri_FO = Faroe Islands
+Globalization.ri_FR = France
+Globalization.ri_GB = United Kingdom
+Globalization.ri_GE = Georgia
+Globalization.ri_GL = Greenland
+Globalization.ri_GR = Greece
+Globalization.ri_GT = Guatemala
+Globalization.ri_HK = Hong Kong S.A.R.
+Globalization.ri_HN = Honduras
+Globalization.ri_HR = Croatia
+Globalization.ri_HU = Hungary
+Globalization.ri_ID = Indonesia
+Globalization.ri_IE = Ireland
+Globalization.ri_IL = Israel
+Globalization.ri_IN = India
+Globalization.ri_IQ = Iraq
+Globalization.ri_IR = Iran
+Globalization.ri_IS = Iceland
+Globalization.ri_IT = Italy
+Globalization.ri_IV = Invariant Country
+Globalization.ri_JM = Jamaica
+Globalization.ri_JO = Jordan
+Globalization.ri_JP = Japan
+Globalization.ri_KE = Kenya
+Globalization.ri_KG = Kyrgyzstan
+Globalization.ri_KH = Cambodia
+Globalization.ri_KR = Korea
+Globalization.ri_KW = Kuwait
+Globalization.ri_KZ = Kazakhstan
+Globalization.ri_LA = Lao P.D.R.
+Globalization.ri_LB = Lebanon
+Globalization.ri_LI = Liechtenstein
+Globalization.ri_LK = Sri Lanka
+Globalization.ri_LT = Lithuania
+Globalization.ri_LU = Luxembourg
+Globalization.ri_LV = Latvia
+Globalization.ri_LY = Libya
+Globalization.ri_MA = Morocco
+Globalization.ri_MC = Principality of Monaco
+Globalization.ri_ME = Montenegro
+Globalization.ri_MK = Macedonia (FYROM)
+Globalization.ri_MN = Mongolia
+Globalization.ri_MO = Macao S.A.R.
+Globalization.ri_MT = Malta
+Globalization.ri_MV = Maldives
+Globalization.ri_MX = Mexico
+Globalization.ri_MY = Malaysia
+Globalization.ri_NG = Nigeria
+Globalization.ri_NI = Nicaragua
+Globalization.ri_NL = Netherlands
+Globalization.ri_NO = Norway
+Globalization.ri_NP = Nepal
+Globalization.ri_NZ = New Zealand
+Globalization.ri_OM = Oman
+Globalization.ri_PA = Panama
+Globalization.ri_PE = Peru
+Globalization.ri_PH = Philippines
+Globalization.ri_PK = Islamic Republic of Pakistan
+Globalization.ri_PL = Poland
+Globalization.ri_PR = Puerto Rico
+Globalization.ri_PT = Portugal
+Globalization.ri_PY = Paraguay
+Globalization.ri_QA = Qatar
+Globalization.ri_RO = Romania
+Globalization.ri_RS = Serbia
+Globalization.ri_RU = Russia
+Globalization.ri_RW = Rwanda
+Globalization.ri_SA = Saudi Arabia
+Globalization.ri_SE = Sweden
+Globalization.ri_SG = Singapore
+Globalization.ri_SI = Slovenia
+Globalization.ri_SK = Slovakia
+Globalization.ri_SN = Senegal
+Globalization.ri_SV = El Salvador
+Globalization.ri_SY = Syria
+Globalization.ri_TH = Thailand
+Globalization.ri_TJ = Tajikistan
+Globalization.ri_TM = Turkmenistan
+Globalization.ri_TN = Tunisia
+Globalization.ri_TR = Turkey
+Globalization.ri_TT = Trinidad and Tobago
+Globalization.ri_TW = Taiwan
+Globalization.ri_UA = Ukraine
+Globalization.ri_US = United States
+Globalization.ri_UY = Uruguay
+Globalization.ri_UZ = Uzbekistan
+Globalization.ri_VE = Bolivarian Republic of Venezuela
+Globalization.ri_VN = Vietnam
+Globalization.ri_YE = Yemen
+Globalization.ri_ZA = South Africa
+Globalization.ri_ZW = Zimbabwe
+#endif //!FEATURE_CORECLR
+
+;------------------
+; Encoding names:
+;
+;Total items: 147
+;
+Globalization.cp_1200 = Unicode
+Globalization.cp_1201 = Unicode (Big-Endian)
+Globalization.cp_65001 = Unicode (UTF-8)
+Globalization.cp_65000 = Unicode (UTF-7)
+Globalization.cp_12000 = Unicode (UTF-32)
+Globalization.cp_12001 = Unicode (UTF-32 Big-Endian)
+Globalization.cp_20127 = US-ASCII
+Globalization.cp_28591 = Western European (ISO)
+
+#if FEATURE_NON_UNICODE_CODE_PAGES
+Globalization.cp_37 = IBM EBCDIC (US-Canada)
+Globalization.cp_437 = OEM United States
+Globalization.cp_500 = IBM EBCDIC (International)
+Globalization.cp_708 = Arabic (ASMO 708)
+Globalization.cp_720 = Arabic (DOS)
+Globalization.cp_737 = Greek (DOS)
+Globalization.cp_775 = Baltic (DOS)
+Globalization.cp_850 = Western European (DOS)
+Globalization.cp_852 = Central European (DOS)
+Globalization.cp_855 = OEM Cyrillic
+Globalization.cp_857 = Turkish (DOS)
+Globalization.cp_858 = OEM Multilingual Latin I
+Globalization.cp_860 = Portuguese (DOS)
+Globalization.cp_861 = Icelandic (DOS)
+Globalization.cp_862 = Hebrew (DOS)
+Globalization.cp_863 = French Canadian (DOS)
+Globalization.cp_864 = Arabic (864)
+Globalization.cp_865 = Nordic (DOS)
+Globalization.cp_866 = Cyrillic (DOS)
+Globalization.cp_869 = Greek, Modern (DOS)
+Globalization.cp_870 = IBM EBCDIC (Multilingual Latin-2)
+Globalization.cp_874 = Thai (Windows)
+Globalization.cp_875 = IBM EBCDIC (Greek Modern)
+Globalization.cp_932 = Japanese (Shift-JIS)
+Globalization.cp_936 = Chinese Simplified (GB2312)
+Globalization.cp_949 = Korean
+Globalization.cp_950 = Chinese Traditional (Big5)
+Globalization.cp_1026 = IBM EBCDIC (Turkish Latin-5)
+Globalization.cp_1047 = IBM Latin-1
+Globalization.cp_1140 = IBM EBCDIC (US-Canada-Euro)
+Globalization.cp_1141 = IBM EBCDIC (Germany-Euro)
+Globalization.cp_1142 = IBM EBCDIC (Denmark-Norway-Euro)
+Globalization.cp_1143 = IBM EBCDIC (Finland-Sweden-Euro)
+Globalization.cp_1144 = IBM EBCDIC (Italy-Euro)
+Globalization.cp_1145 = IBM EBCDIC (Spain-Euro)
+Globalization.cp_1146 = IBM EBCDIC (UK-Euro)
+Globalization.cp_1147 = IBM EBCDIC (France-Euro)
+Globalization.cp_1148 = IBM EBCDIC (International-Euro)
+Globalization.cp_1149 = IBM EBCDIC (Icelandic-Euro)
+Globalization.cp_1250 = Central European (Windows)
+Globalization.cp_1251 = Cyrillic (Windows)
+Globalization.cp_1252 = Western European (Windows)
+Globalization.cp_1253 = Greek (Windows)
+Globalization.cp_1254 = Turkish (Windows)
+Globalization.cp_1255 = Hebrew (Windows)
+Globalization.cp_1256 = Arabic (Windows)
+Globalization.cp_1257 = Baltic (Windows)
+Globalization.cp_1258 = Vietnamese (Windows)
+Globalization.cp_1361 = Korean (Johab)
+Globalization.cp_10000 = Western European (Mac)
+Globalization.cp_10001 = Japanese (Mac)
+Globalization.cp_10002 = Chinese Traditional (Mac)
+Globalization.cp_10003 = Korean (Mac)
+Globalization.cp_10004 = Arabic (Mac)
+Globalization.cp_10005 = Hebrew (Mac)
+Globalization.cp_10006 = Greek (Mac)
+Globalization.cp_10007 = Cyrillic (Mac)
+Globalization.cp_10008 = Chinese Simplified (Mac)
+Globalization.cp_10010 = Romanian (Mac)
+Globalization.cp_10017 = Ukrainian (Mac)
+Globalization.cp_10021 = Thai (Mac)
+Globalization.cp_10029 = Central European (Mac)
+Globalization.cp_10079 = Icelandic (Mac)
+Globalization.cp_10081 = Turkish (Mac)
+Globalization.cp_10082 = Croatian (Mac)
+Globalization.cp_20000 = Chinese Traditional (CNS)
+Globalization.cp_20001 = TCA Taiwan
+Globalization.cp_20002 = Chinese Traditional (Eten)
+Globalization.cp_20003 = IBM5550 Taiwan
+Globalization.cp_20004 = TeleText Taiwan
+Globalization.cp_20005 = Wang Taiwan
+Globalization.cp_20105 = Western European (IA5)
+Globalization.cp_20106 = German (IA5)
+Globalization.cp_20107 = Swedish (IA5)
+Globalization.cp_20108 = Norwegian (IA5)
+Globalization.cp_20261 = T.61
+Globalization.cp_20269 = ISO-6937
+Globalization.cp_20273 = IBM EBCDIC (Germany)
+Globalization.cp_20277 = IBM EBCDIC (Denmark-Norway)
+Globalization.cp_20278 = IBM EBCDIC (Finland-Sweden)
+Globalization.cp_20280 = IBM EBCDIC (Italy)
+Globalization.cp_20284 = IBM EBCDIC (Spain)
+Globalization.cp_20285 = IBM EBCDIC (UK)
+Globalization.cp_20290 = IBM EBCDIC (Japanese katakana)
+Globalization.cp_20297 = IBM EBCDIC (France)
+Globalization.cp_20420 = IBM EBCDIC (Arabic)
+Globalization.cp_20423 = IBM EBCDIC (Greek)
+Globalization.cp_20424 = IBM EBCDIC (Hebrew)
+Globalization.cp_20833 = IBM EBCDIC (Korean Extended)
+Globalization.cp_20838 = IBM EBCDIC (Thai)
+Globalization.cp_20866 = Cyrillic (KOI8-R)
+Globalization.cp_20871 = IBM EBCDIC (Icelandic)
+Globalization.cp_20880 = IBM EBCDIC (Cyrillic Russian)
+Globalization.cp_20905 = IBM EBCDIC (Turkish)
+Globalization.cp_20924 = IBM Latin-1
+Globalization.cp_20932 = Japanese (JIS 0208-1990 and 0212-1990)
+Globalization.cp_20936 = Chinese Simplified (GB2312-80)
+Globalization.cp_20949 = Korean Wansung
+Globalization.cp_21025 = IBM EBCDIC (Cyrillic Serbian-Bulgarian)
+Globalization.cp_21027 = Ext Alpha Lowercase
+Globalization.cp_21866 = Cyrillic (KOI8-U)
+Globalization.cp_28592 = Central European (ISO)
+Globalization.cp_28593 = Latin 3 (ISO)
+Globalization.cp_28594 = Baltic (ISO)
+Globalization.cp_28595 = Cyrillic (ISO)
+Globalization.cp_28596 = Arabic (ISO)
+Globalization.cp_28597 = Greek (ISO)
+Globalization.cp_28598 = Hebrew (ISO-Visual)
+Globalization.cp_28599 = Turkish (ISO)
+Globalization.cp_28603 = Estonian (ISO)
+Globalization.cp_28605 = Latin 9 (ISO)
+Globalization.cp_29001 = Europa
+Globalization.cp_38598 = Hebrew (ISO-Logical)
+Globalization.cp_50000 = User Defined
+Globalization.cp_50220 = Japanese (JIS)
+Globalization.cp_50221 = Japanese (JIS-Allow 1 byte Kana)
+Globalization.cp_50222 = Japanese (JIS-Allow 1 byte Kana - SO/SI)
+Globalization.cp_50225 = Korean (ISO)
+Globalization.cp_50227 = Chinese Simplified (ISO-2022)
+Globalization.cp_50229 = Chinese Traditional (ISO-2022)
+Globalization.cp_50930 = IBM EBCDIC (Japanese and Japanese Katakana)
+Globalization.cp_50931 = IBM EBCDIC (Japanese and US-Canada)
+Globalization.cp_50933 = IBM EBCDIC (Korean and Korean Extended)
+Globalization.cp_50935 = IBM EBCDIC (Simplified Chinese)
+Globalization.cp_50937 = IBM EBCDIC (Traditional Chinese)
+Globalization.cp_50939 = IBM EBCDIC (Japanese and Japanese-Latin)
+Globalization.cp_51932 = Japanese (EUC)
+Globalization.cp_51936 = Chinese Simplified (EUC)
+Globalization.cp_51949 = Korean (EUC)
+Globalization.cp_52936 = Chinese Simplified (HZ)
+Globalization.cp_54936 = Chinese Simplified (GB18030)
+Globalization.cp_57002 = ISCII Devanagari
+Globalization.cp_57003 = ISCII Bengali
+Globalization.cp_57004 = ISCII Tamil
+Globalization.cp_57005 = ISCII Telugu
+Globalization.cp_57006 = ISCII Assamese
+Globalization.cp_57007 = ISCII Oriya
+Globalization.cp_57008 = ISCII Kannada
+Globalization.cp_57009 = ISCII Malayalam
+Globalization.cp_57010 = ISCII Gujarati
+Globalization.cp_57011 = ISCII Punjabi
+#endif // FEATURE_NON_UNICODE_CODE_PAGES
+#endif // INCLUDE_DEBUG
+
+;------------------
+